arvgta / ajaxify

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

Script handling made transparent #156

Closed arvgta closed 5 years ago

arvgta commented 5 years ago

Documented on 4nf.org


Prior to release 7.2.5, any scripts on the target page were rebuilt on the main page, by dynamically creating a new script tag along with its contents and attributes. Instead, I would like to pass through inline scripts and external script references without tampering with them from now on.

1. Inline scripts

The new logic is very simple:

$s.clone().appendTo($.cd("g")) //append inline script to content div

(where $s holds the jQuery script object of the target page)

...and it works!

2. External scripts

The ideal approach:

Analogue to the above, I tried the following logic:

$S.clone().appendTo("head"); //appending to content div results in the same behaviour

...which works functionally, but unfortunately triggers the following warning, coming from jQuery itself:

Synchronous XMLHttpRequest on the main thread is deprecated

(that is a known issue in the jQuery community and does not come from Ajaxify)

Question: Is it possible to workaround the above warning or suppress it?


The old approach:

//Insert single external JS script - we have to go low level to avoid a warning coming from jQuery append()
//But we'll do our best to support all salient attributes
var script = document.createElement("script"), Type = $S.attr("type"), aSync = $S.attr("async"), deFer = $S.attr("defer");
if(Type) script.type = Type;
script.src = url;
script.async = aSync ? true : asyncdef;
if(deFer) script.defer = true;
document.head.appendChild(script)

...(where $S holds the jQuery script object of the target page and asyncdef is usually false)

The old approach does not trigger the above warning

However, the core script attributes are not all supported, not to mention the global HTML attributes...


The new approach:

Employs this technique I found at stackoverflow.com

...more specifically, this looks really promising:

//Insert single external JS script - we have to go low level to avoid a warning coming from jQuery append()
//But we'll do our best to support all salient attributes
var script = document.createElement("script");
_cloneAttributes(script, $S); //clone all attributes of script element generically
document.head.appendChild(script); //it doesn't matter much, if we append to head or content div

cloneAttributes: function (el, $S) { //clone all attributes of script element generically
     var attr, attributes = Array.prototype.slice.call($S[0].attributes); //slice performs a copy, too
     el.async = asyncdef; //initialise with asyncdef - may be overwritten in the while loop
     while(attr = attributes.pop()) { //fetch one of all the attributes at a time
         el.setAttribute(attr.nodeName, attr.nodeValue); //low-level insertion
     }
 }

...and it works!

arvgta commented 5 years ago

No news is good news, I suppose.... Closing...