Skip to Content
Menu

lazyLoadAssets()

Only load certain third-party JavaScript libraries on pages which they are needed.

JavaScript February 7, 2021

Usage

This function runs automatically, so it is not called manually. Is this incorrect?

Was this page helpful? Yes No


    A feedback message is required to submit this form.


    Please check that you have entered a valid email address.

    Enter your email address if you would like a response.

    Thank you for your feedback!

    Source File

    Located in /assets/js/modules/optimization.js on line 474.

    No Hooks

    This function does not have any filters or actions available. Request one?
    JavaScript
    nebula.lazyLoadAssets = async function(){
        nebula.site.resources.lazy.promises = {};
    
        //Detect if Bootstrap JS is needed and load it
        //A wildcard attribute name selector would be super useful here, but does not exist. Something like [data-bs-*] would be perfect...
        //That being said, the Offcanvas component will be used on 95% of Nebula sites, so this will likely load on every page regardless.
        if ( typeof bootstrap === 'undefined' ){ //If Bootstrap JS has not already been initialized
            if ( jQuery('.offcanvas, .accordion, .alert, .carousel, .collapse, .dropdown-menu, .modal, .nav-tabs, .nav-pills, [data-bs-toggle]').length ){
                nebula.loadJS(nebula.site.resources.scripts['nebula_bootstrap']).then(function(){ //Load Bootstrap JS
                    nebula.initBootstrapFunctions(); //Initialize Nebula Bootstrap helper functionality now that Bootstrap JS has finished loading here
                });
            }
        } else {
            nebula.initBootstrapFunctions(); //Initialize Nebula Bootstrap helper functionality immediately since Bootstrap JS has already been loaded somewhere else
        }
    
        //Lazy load elements as they scroll into viewport
        try {
            //Observe the entries that are identified and added later (below)
            let lazyObserver = new IntersectionObserver(function(entries){
                entries.forEach(async function(entry){
                    //await nebula.yield();
    
                    if ( entry.intersectionRatio > 0 ){
                        nebula.loadElement(jQuery(entry.target));
                        lazyObserver.unobserve(entry.target); //Stop observing the element
                    }
                });
            }, {
                rootMargin: '50%', //Extend the area of the observer (100% = Double the Viewport). Try to prevent visible loading of elements by triggering the load much earlier than actually needed.
                threshold: 0.1
            });
    
            //Create the entries and add them to the observer
            jQuery('.nebula-lazy-position, .lazy-load, .nebula-lazy').each(function(){
                lazyObserver.observe(jQuery(this)[0]); //Observe the element
            });
    
            //When scroll reaches the bottom, ensure everything has loaded at this point
            //Only when IntersectionObserver exists because otherwise everything is immediately loaded anyway
            let lazyLoadScrollBottom = function(){
                if( nebula.dom.window.scrollTop()+nebula.dom.window.height() > nebula.dom.document.height()-500 ){ //When the scroll position reaches 500px above the bottom
                    nebula.loadEverything();
                    window.removeEventListener('scroll', lazyLoadScrollBottom); //Stop listening for this scroll event
                }
            };
            window.addEventListener('scroll', lazyLoadScrollBottom); //Scroll is passive by default
        } catch(error){
            nebula.loadEverything(); //If any error, load everything immediately
            nebula.help('Lazy Load Observer: ' + error + '. All assets have been loaded immediately.', '/functions/lazyloadassets/', true);
        }
    
        //Load all lazy elements at once if requested
        nebula.dom.window.on('nebula_load', function(){
            if ( typeof window.requestIdleCallback === 'function' ){ //If requestIdleCallback exists, use it. Remove this check when Safari supports it
                window.requestIdleCallback(function(){
                    nebula.loadEverything();
                });
            } else { //Otherwise, just run immediately
                nebula.loadEverything();
            }
        });
    
        //Lazy load CSS assets
        //Listen for requestIdleCallback here when Safari supports it
        jQuery.each(nebula.site.resources.lazy.styles, function(handle, condition){
            if ( condition === 'all' || jQuery(condition).length ){
                if ( nebula.site.resources.styles[handle.replaceAll('-', '_')] ){ //If that handle exists in the registered styles
                    nebula.loadCSS(nebula.site.resources.styles[handle.replaceAll('-', '_')]);
                }
            }
        });
    
        //Lazy load JS assets
        //Listen for requestIdleCallback here when Safari supports it
        jQuery.each(nebula.site.resources.lazy.scripts, function(handle, condition){
            if ( condition === 'all' || jQuery(condition).length ){
                if ( nebula.site.resources.scripts[handle.replaceAll('-', '_')] ){ //If that handle exists in the registered scripts
                    nebula.loadJS(nebula.site.resources.scripts[handle.replaceAll('-', '_')], handle); //Load it (with a Promise)
                }
            }
        });
    
        //Load the Google Maps API if 'googlemap' class exists
        if ( jQuery('.googlemap').length ){
            if ( typeof google == 'undefined' || typeof google.maps == 'undefined' ){ //If the API has not already been called
                nebula.loadJS('https://www.google.com/jsapi?key=' + nebula.site.options.nebula_google_browser_api_key, 'google-maps').then(function(){ //May not need key here, but just to be safe.
                    google.load('maps', '3', {
                        other_params: 'libraries=places&key=' + nebula.site.options.nebula_google_browser_api_key,
                        callback: function(){
                            nebula.dom.document.trigger('nebula_google_maps_api_loaded');
                        }
                    });
                });
            } else {
                nebula.dom.document.trigger('nebula_google_maps_api_loaded'); //Already loaded
            }
        }
    
        if ( jQuery('pre.nebula-code, pre.nebula-code').length ){
            nebula.loadCSS(nebula.site.resources.styles.nebula_pre);
            nebula.pre();
        }
    };
    

    Override

    To override or disable this JavaScript function, simply redeclare it with the exact same function name. Remember: Some functionality is conditionally loaded via dynamic imports, so if your function is not overriding properly, try listening for a DOM event (described below).

    JavaScript

    For non-module import functions:

    nebula.lazyLoadAssets = function(){
        //Write your own code here, leave it blank, or return false.
    }


    For dynamically imported module function overrides:

    jQuery(window).on('load', function(){
        nebula.lazyLoadAssets = function(){
            //Write your own code here, leave it blank, or return false.
        }
    });


    Custom Nebula DOM events do also exist, so you could also try the following if the Window Load listener does not work:

    jQuery(document).on('nebula_module_loaded', function(module){
        //Note that the module variable is also available to know which module specifically was imported
        if ( typeof nebula.lazyLoadAssets === 'function' ){
            nebula.lazyLoadAssets = function(){
                //Write your own code here, leave it blank, or return false.
            }
    	}
    });