-
Notifications
You must be signed in to change notification settings - Fork 2k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
External scripts are evaluated async #331
Comments
Sorry, but there is no way to run "blocking" scripts as you can on an initial page load after the fact. Its just not possible with the way DOM fragment parsers work. |
sorry @josh, can't understand your explanation. what do you mean ' as you can on an initial page load after the fact'? |
@brauliobo are you sure that commenting out that line made the scripts execute sequentially? I would expect this to not actually execute the scripts at all. |
@shogun70 yes, I am, because this will make jquery's html() call to see those scripts |
@brauliobo: Thanks - I didn't know html() executed scripts. I think your suggestion makes more sense than the current behavior. |
This “problem“ bothers me as well. So I get a pjaxed request that contains HTML of the new page and some Scripts are not executed. If I remove this from the source code:
...scripts are executed (well, So what's the point of removing scripts from response? I'm looking for a way to inject scripts when a page loads, don't want to load every script (script per page) in container. Thanks! |
To summarize, what's the point of removing scripts from HTML response? |
Wating the reason... :) |
There are two types of
If you think you've found a bug with this system please be more specific about what you're doing—which version of jquery-pjax are you using, what does your pjax response looks like, which script tag you expected to get executed but never did? |
@mislav Please read the description of this issue. The problem is with the execution order, which is not preserved when using |
Ah OK I understand. This is another example of how pjax doesn't (and can't) behave identically to static pages. You should construct your external script tags to not depend on each other at eval time, or handle script loading manually in your app using pjax events.
TL;DR; due to browser limitations, it's nontrivial for us to fix this without implementing a whole script loader withing pjax plugin. |
I had proposed a way that is already handled by jquery automatically. jquery knows how to deal with |
@brauliobo What does jquery do? |
http://api.jquery.com/html/ and http://api.jquery.com/append/ handles That's why just commenting the line where pjax extract |
The situation that @brauliobo (obrigado por apontar a linha culpada) describe is really common. |
OK, let's clear something up first. Or, you people are welcome to prove me wrong. Consider this HTML: <p>Hello world!</p>
<script src="external1.js"></script>
<script src="external2.js"></script>
<script>External.something("foo")</script> Here we have multiple external script loads, and an inline script that relies on the example
Now, nobody other than me would be happier if we managed to fix this and ensure that pjaxed sites work always exactly the same as native page loads. Because of that, I'm accepting constructive suggestions on how we can technically make this work. However, the solution can't depend on |
@mislav 2 is wrong. jQuery does guarantee execution order. I'm not sure, but I think it runs scripts syncronously when found by |
@brauliobo OK, that might be true. Can you point us to somewhere where we can verify this? Perhaps a location in its source code |
In |
|
Ah so it doesn't use OK so what we can do in pjax is try to detect whether @josh How does that sound? |
Its not really possible in CSP 1.0 to feature detect if |
No? What happens if you call |
It will crash and send back a CSP violation ping back to our servers each
|
I haven't able to fully test this but it seems promising: function cspEnabled() {
try {
eval("return false;");
} catch (e) {
return true;
}
} from http://stackoverflow.com/questions/19140169/how-to-detect-content-security-policy-csp |
it is pretty similiar to what angular.js is doing: IgorMinar/angular.js@e05b78a |
Again, that causes a violation report which is unacceptable.
|
@josh So a CSP disable/enable option is the only alternative. (just like angular.js did) |
I don't really like the general idea of having two different modes that
|
@josh Tracking scripts should be as easy as storing the list of |
On Wed, Dec 10, 2014 at 10:06 AM, Bráulio Bhavamitra <
It seems so, which sucks a lot because I don't want that to be an option. I'd rather just draw a line and say we as a library won't support sites |
This commit uses onload to load the scripts serially, in the original order (excluding already loaded scripts). It also loads inline scripts in the original order, by appending them to the container (so it only relies on |
I looked at the implementation and it seems solid. We might look into including something like that if we can simplify the implementation, and if the |
@mislav +1 |
@mislav +1 on at least having a configuration option for this. Has there been any progress with this since? |
No progress since. I wasn't super motivated to prioritize this since pjax works very well for our use case and we generally don't need loading in sync. |
Are there still plans to follow through with this feature? |
Couldnt code like quoted in the inital report use the onload event to intialise properly? <script src='external_script_with_function.js' onload='function_from_external_script();'/> |
That's not a solution if you have an existing site you'd like to pjaxify and especially if the code is out of your control, because it's part of a framework, like Yii 2. |
The filament group has a repository called loadJS : https://github.com/filamentgroup/loadJS/blob/master/loadJS.js <script>
/*! loadJS: load a JS file asynchronously. [c]2014 @scottjehl, Filament Group, Inc. (Based on http://goo.gl/REQGQ by Paul Irish). Licensed MIT */
(function( w ){
var loadJS = function( src, cb ){
"use strict";
var ref = w.document.getElementsByTagName( "script" )[ 0 ];
var script = w.document.createElement( "script" );
script.src = src;
script.async = true;
ref.parentNode.insertBefore( script, ref );
if (cb && typeof(cb) === "function") {
script.onload = cb;
}
return script;
};
// commonjs
if( typeof module !== "undefined" ){
module.exports = loadJS;
}
else {
w.loadJS = loadJS;
}
}( typeof global !== "undefined" ? global : this ));
$(document).on('pjax:end', function () {
$(document).on('submit', 'form[data-pjax]', function (event) {
$.pjax.submit(event, '#ajax-content')
});
loadJS("components/jquery/jquery.min.js' ) ?>", function () {
loadJS("bower_components/bootstrap-datepicker/js/bootstrap-datepicker.js", function (){
$('#datepicker').datepicker({autoclose: true});
});
});
});
</script> Is this a possible solution? |
As external scripts are removed from the content and then evaluated by inserting them into head, they end up being evaluated async which causes somes dependent symbols not to work. See this example
function_from_external_script_above()
won't work!Commenting the line
obj.scripts = findAll(obj.contents, 'script[src]').remove()
workarounded the issue.I understand that a sync evaluation may hang the application, but as this example demonstrate it is necessary on some cases. I suggest a configuration to support both behaviours or support only the sync behaviour.
The text was updated successfully, but these errors were encountered: