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?
In v6 the calendar/listing content was loaded dynamically into the page whenever you shifted months or used filters, I expect v7 is the same. Have you tested to see if that is what you're seeing?
That's probably exactly it. Is there a way to use scripts on that content? Specifically, we're using jquery to add divs.
That's a great question. I don't know of there's an event handler or something that you could tie into.
I had this issue with v6 when overriding urls in performance content so that they would point to our development content server when being displayed by our QA TNEW site. Since it was content in the DB, I just ran a URL updater on the content table in the database during Live->Test copies. Obviously, I can't do that with v7. I think I have an enhancement request in to be able to do arbitrary URL mangling for TNEW config in QA...
Are you on the TN Web slack channel?
Would something like $(window).ajaxComplete(function() work for you?
I think I was asking about this exact same thing in the TN_WebShare slack a couple of days ago: https://tn-webshare.slack.com/archives/C02GE71RP/p1554299345073600
I was looking into .ajaxComplete() since it looked like TNEW is using jQuery's ajax library to do its async loading, but it seemed like there were a number of different ajax calls happening so I was curious how I could be more specific with my hook. Can/does TNEW fire a specific event once the events are loaded and the DOM is ready to be manipulated? (Someone in chat suggested using a MutationObserver, but I haven't yet looked into how this would be implemented.)
We don't pay for slack around here, but I'm on the planning committee channel so there must be some way I can get there. Do you have to invite me?
Chaz Stuart if youd like to request access to our developer slack channel, you can complete the form here on tessituranetwork.com:
https://www.tessituranetwork.com/devs
Slack is free to download and use if you have access to a channel. Once you submit the form, you'll receive an email at the address you indicate that will walk you through it.
Thanks
Chris
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
Hey Billy- most people (Nick Reilingh) 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