arvgta / ajaxify

Ajaxify - The Ajax Plugin
https://4nf.org/
274 stars 124 forks source link

DOMContentLoaded in an Ajax environment #211

Closed arvgta closed 3 years ago

arvgta commented 3 years ago

EDIT: Fixed from version 8.1.3


We noticed, that when porting from the jQuery ready() event to DOMContentLoaded, that jQuery does a bit more than just calling the latter.

The new entry point of Ajaxify looks like this:

if (document.readyState === "complete" || (document.readyState !== "loading" && !document.documentElement.doScroll)) 
    run();
else document.addEventListener('DOMContentLoaded', run);

...where run() does the actual initialisation...

(Source: https://www.sitepoint.com/jquery-document-ready-plain-javascript/)

There is no problem assumed with that.


The actual problem:

A different story however is, that there may be issues when third party scripts employ DOMContentLoaded, albeit these would be noticeable in most Ajax environments.

Here is a description of the problem, which in our own terms:

DOMContentLoaded relies on detecting page load after browser refresh and not after ajax/fetch request. This is why jQuery's ready function has additions that covers ajax/fetch requests.

Whenever the former happens, our users could actually regard this as a bug. We are thinking of generically patching this effect somehow.


Proposed solution(s):

One suggested approach is for Ajaxify to provide a built-in but public function onReady() that makes it easier to substitute calls to

window.addEventListener('DOMContentLoaded', ...)

onReady() source code:

// plain javascript document ready detection /////////////
let onReady = (cb) => {
    let compl = () => { document.removeEventListener("DOMContentLoaded", compl); window.removeEventListener("load", compl); cb(); }
    if (document.readyState !== "loading") window.setTimeout(cb);
    else {document.addEventListener("DOMContentLoaded", compl); window.addEventListener("load", compl);}
}

(This is hand-made code and obviously changes a bit of the browsers default behaviour)

onReady()could be then used as follows :

window.addEventListener('DOMContentLoaded', function () {
    let slides = document.querySelectorAll('#carousel .carousel-item');
    let first_slide = slides[0];
    pgia.play(first_slide, 'Show');
});

...becomes...

onReady(() => {
    let slides = document.querySelectorAll('#carousel .carousel-item');
    let first_slide = slides[0];
    pgia.play(first_slide, 'Show');
});

Is there a more "official" way of dealing with the problem already on the net?