Performance Optimization

Forsta HX Platform - API Scripting Guide

Performance Optimization

Debouncing Input Events:

/**
 * debounce - Creates a debounced version of a function
 * @param {Function} func - The function to debounce
 * @param {number} wait - Milliseconds to wait before executing
 * @returns {Function} - Debounced version of the input function
 * @description Delays function execution until after 'wait' milliseconds
 *              have passed since the last call. If called again before
 *              the timeout, the timer resets. Useful for expensive operations
 *              triggered by frequent events like typing or scrolling.
 */
function debounce(func, wait) {
    var timeout; // Stores the setTimeout reference
    // Return a wrapper function that manages the delay
    return function() {
        var context = this, args = arguments; // Preserve context and arguments
        clearTimeout(timeout); // Cancel any pending execution
        // Schedule new execution after 'wait' milliseconds
        timeout = setTimeout(function() {
            func.apply(context, args); // Execute with original context/args
        }, wait);
    };
}

// Usage for expensive operations
var expensiveSearch = debounce(function() {
    var query = f(AQ1).val();
    // Expensive API call or calculation
    searchDatabase(query);
}, 500);

f(AQ1).on('input', expensiveSearch);

Lazy Loading:

/**
 * lazyLoadQuestion - Loads question content only when needed
 * @param {string} qid - The question ID to load
 * @description Checks if question is already loaded using jQuery data().
 *              If not loaded, fetches content via AJAX and initializes
 *              the question. Reduces initial page load time for long surveys.
 */
function lazyLoadQuestion(qid) {
    // Check if question has already been loaded using jQuery .data()
    if(!f(qid).data('loaded')) {
        // Load question content
        $.get('/api/question/' + qid, function(html) {
            f(qid).html(html);
            f(qid).data('loaded', true);
            initializeQuestion(qid);
        });
    }
}

// Initialize on scroll into view
var observer = new IntersectionObserver(function(entries) {
    entries.forEach(function(entry) {
        if(entry.isIntersecting) {
            var qid = $(entry.target).data('question');
            lazyLoadQuestion(qid);
        }
    });
});

$('.question').each(function() {
    observer.observe(this);
});