TNEW V7 JS loading inconsistent

Working on the templating of our TNEW V7 site and we've encountered a pretty specific problem with script loading orders. On our event listing page, we load a script file that triggers the scripts on $(window).load(function(). The script file loads every time and the console log always indicates that the script fires. However, the script impacts the loaded performance content, and sometimes the script fires after that content is loaded which is correct, but sometimes the script fires before that content loads. It's about 50/50 when it works.

The $(window).load(function() trigger is the only one we could get to work at all, but I guess this inconsistency tells me that the performance information can load after the window. Has anybody experienced and fixed this? Is there a JS trigger that could work?

Parents
  • Hi Chaz,

    Good question.

    Ideally, TNEW would provide a hook or a callback to give a customization the ability to modify any event elements at the best times. I'll make sure there's an enhancement request for this. In lieu of that feature -

    `ajaxComplete` might work if you're trying to specifically modify the _data_ and not the rendered elements. But as Nick mentioned you'd also need to write some code to filter out unrelated ajax requests. You'd also need to incorporate some kind of delay after the ajax response is received to allow TNEW's standard processing/rendering of the data if you did want to modify the rendered elements. I don't think I'd start with this option.

    `MutationObserver` seems promising - it might be your best bet. I didn't realize it had as good of browser support as it does. I'd start here and see how that goes.

    Let us know how it goes!

    Billy

Reply
  • Hi Chaz,

    Good question.

    Ideally, TNEW would provide a hook or a callback to give a customization the ability to modify any event elements at the best times. I'll make sure there's an enhancement request for this. In lieu of that feature -

    `ajaxComplete` might work if you're trying to specifically modify the _data_ and not the rendered elements. But as Nick mentioned you'd also need to write some code to filter out unrelated ajax requests. You'd also need to incorporate some kind of delay after the ajax response is received to allow TNEW's standard processing/rendering of the data if you did want to modify the rendered elements. I don't think I'd start with this option.

    `MutationObserver` seems promising - it might be your best bet. I didn't realize it had as good of browser support as it does. I'd start here and see how that goes.

    Let us know how it goes!

    Billy

Children
  • Hey Billy- most people () have been pointing us in the direction of MutationObserver. We haven't quite got it working, but there is promise here. We will follow up when we have good news.

  • Hi Folks.  and I have worked out a usable solution, which can be seen here:
    https://www.vafest.org/scripts/TNEW%20files/index.js

    The most relevant portion portion of the code was taken from the blog post below:
    http://ryanmorr.com/using-mutation-observers-to-watch-for-element-availability/ 

    We did in fact use MutationObserver to solve this problem, but there were two very specific challenges.

    1. Our goal was to add divs to the production season list items. Because of inconsistent load times and hooks, we found it best to observe changes to all descendant nodes of #tn-events-list-view, but because we are adding nodes here, it created an infinite loop.
    2. The load time of #tn-events-list-view was predictable, but the load time of the <ul class=”list-unstyled”> (the list of production season content) was not, so we needed to be able to know that it was loaded before running any scripts on it.

    The article listed above provided a solution to both problems. The script described has a function that checks if a given element has loaded while running the observe function so that everything happens when it needs to. Unfortunately, this meant that our final script would run once for every observed mutation, or once for every production season that was impacted, so we added something to check for the first added node so that it would only run once:


    $(window).load(function () {   
        (function (win) {
            'use strict';
     
            var listeners = [],
                doc = win.document,
     
                MutationObserver = win.MutationObserver || win.WebKitMutationObserver,
                observer;
     
            function ready(selector, fn) {
                // Store the selector and callback to be monitored
                listeners.push({
                    selector: selector,
                    fn: fn
                });
                if (!observer) {
                    // Watch for changes in the document
                    var targetNode = document.querySelector('#tn-events-list-view');
                    observer = new MutationObserver(check);
                    observer.observe(targetNode, {
                        childList: true,
                        subtree: true
                    });
                }
                // Check if the element is currently in the DOM
                check();
            }
     
            function check() {
                // Check the DOM for elements matching a stored selector
                for (var i = 0, len = listeners.length, listener, elements; i < len; i++) {
                    listener = listeners[i];
                    // Query for elements matching the specified selector
                    elements = doc.querySelectorAll(listener.selector);
                    for (var j = 0, jLen = elements.length, element; j < jLen; j++) {
                        element = elements[j];
                        // Make sure the callback isn't invoked with the
                        // same element more than once
                        //The first added element is "color1" which is detected by the next few lines
                        if (!element.ready && element.childNodes[3].firstChild.className != 'color1') {
                            element.ready = true;
                            // Invoke the callback with the element
                            listener.fn.call(element, element);
                        }
                    }
                }
            }
     
            // Expose `ready`
            win.ready = ready;
     
        })(this);
     
        ready('.tn-prod-list-item', function (element) {
        //Do the thing you want to do        
        });
    })
     

     

    We’re no experts, so certainly things can be improved upon, but it seems to be working nicely, and hopefully could prove useful to anyone trying to add nodes to the event listing.

    Chaz




  • Nice! Glad to hear you got things working. Thanks for sharing your solution Thumbsup