Side navigation
#9827 closed enhancement (invalid)
Opened July 14, 2011 09:11PM UTC
Closed July 23, 2011 06:22PM UTC
Last modified January 21, 2013 06:48PM UTC
jQuery getScript .text and .async support
Reported by: | daveartz | Owned by: | jaubourg |
---|---|---|---|
Priority: | low | Milestone: | 1.next |
Component: | ajax | Version: | 1.6.2 |
Keywords: | Cc: | dmethvin | |
Blocked by: | Blocking: |
Description
Hey guys, more control is needed for loading scripts asynchronously, especially with Google+'s new explicit initialization feature.
Specifically it would be nice to do something like this:
jQuery.getScript("https://apis.google.com/js/plusone.js", { async: true, text: '{"parsetags":"explicit"}', function(){ callback });
I got this working in my Boot library by using the innerHTML property to set the .text, it was the only thing that worked reliably.
https:github.com/artzstudio/Boot/blob/master/src/boot.js
(see my getScript for reference).
There are other folks looking to do this cleanly:
http://stackoverflow.com/questions/6207815/issue-loading-google-1-widget-asynchronously
Cheers!
Dave Artz
Attachments (0)
Change History (12)
Changed July 14, 2011 09:28PM UTC by comment:1
Changed July 14, 2011 10:13PM UTC by comment:2
Hey Dave, can you restate this in the form of a bug report or feature request? Would this best be done by an external script loader, or are you asking for a modest change to $.getScript()
?
Changed July 14, 2011 11:13PM UTC by comment:3
component: | unfiled → ajax |
---|---|
owner: | → daveartz |
priority: | undecided → low |
status: | new → pending |
Changed July 15, 2011 01:32AM UTC by comment:4
Yes, modest change to $.getScript (which I guess is just an alias for certain $.ajax options), which is why I classified as an enhancement.
However I may need to dig a little further as innerHTML threw an error in IE6, maybe I can research this a bit further for you and provide a patch, wouldn't want you to spend effort if this is a relatively low priority.
Changed July 15, 2011 01:17PM UTC by comment:5
Just to make this a bit clearer, I think what you're asking for is the ability to set the script tag's inner content before making the request. Correct? It's already async if we use a script tag.
Changed July 15, 2011 01:28PM UTC by comment:6
I believe he's asking for the ability to actually have jQuery set the "async" attribute of the script tag that is being created for the request that (which is indeed already async)
http://davidwalsh.name/html5-async
If so, I'd tend to think this should be tacked on as some sort of $.ajax option - I don't really like the idea of suddenly allowing $.getScript to take an config options object where it never has accepted one before
Changed July 22, 2011 12:15AM UTC by comment:7
cc: | → jaubourg |
---|
So, first of all, an async option to make script tag non async (in the script tag sense of the term) won't work in IE and webkit anyway, so you can forget about that.
If anything, making the script tag async is what makes script loading consistent across browsers: it will be async no matter what. Beside, what most people would expect is the $.ajax call to be synchronous which will never ever happen with script tag injection.
Now one has to give credit to Google for inventing the most unconventional and awkward ways to load scripts in history... so I guess they chose that way because a param string would make cache hits less likely (not by much, mind you). What a poor design decision indeed.
That being said, I really don't see yet another option making it into ajax at this point. However, from what I see in the stackoverflow page, you don't need to actual control script loading (no success callback)... why not do something like:
$( "<script/>", { src: "https://apis.google.com/js/plusone.js", text: JSON.stringify({ parsetags: "explicit" }) }).appendTo( "head" );
Seems nearly as short as $.getScript and doesn't involve some weird patch for this very specific case.
However, I cannot guarantee that plusone.js doesn't look at the latest script in the head, so if you use getScript after that... well, you could always ask google for a proper, standard, way to load their scripts.
Changed July 23, 2011 10:43AM UTC by comment:8
@jaubourg - Fair point on the async / default behavior and I concur, I have no idea what Google was thinking. LinkedIn also does something similar, any ideas why they went this route? Avoiding an inline script following it for cleanliness perhaps... http://developer.linkedinlabs.com/tutorials/jsapi_authentication/
The problem with the $("<script>") technique would be that I wouldn't know when the script loaded, the primary reason I'm looking for a solution in getScript here. I need to set Google+ to explicit mode, and initialize everything after I know the script has loaded and executed.
Changed July 23, 2011 01:12PM UTC by comment:9
cc: | jaubourg → dmethvin |
---|---|
milestone: | None → 1.next |
owner: | daveartz → jaubourg |
status: | pending → assigned |
Hmmm... the madness is spreading it seems ;)
I'm still convinced it's about making sure you hit the cache no matter your config parameters, seems like the only advantage this technique has over a query string in the url (putting it in the script tag that made the request itself makes it much simpler to find and, as opposed to a secondary inline script, avoids a global var declaration or a syntax error when the inline tag is reached by the browser).
The thing is this technique tries to have one's cake and eat it too imo, in the sense an initialization method/function would have worked wonder here, but the guys behind the libs want to do things automagically no matter what: "drop the script and it works", if you see what I mean.
For the time being, you could redefine the script transport found in https://github.com/jquery/jquery/blob/master/src/ajax/script.js: just extract the jQuery.ajaxTransport statement, replace the dataType expression (first parameter) as "+script" to make sure you'll override the existing one and add something like follows just before line 75-77:
if ( s.scriptText ) { $( script ).text( s.scriptText ); }
If you drop this redefined transport, you should have a solution to your problem (though you'd need to use ajax rather than getScript):
$.ajax( "https://apis.google.com/js/plusone.js", { dataType: "script", scriptText: JSON.stringify({ parsetags: "explicit" }) });
Not ideal but it should do the trick for the time being ;)
I'm still pondering if this warrants an inclusion in jQuery (the option would only be local to the script tag injection transport but, still, it's yet another option we'd have to document -- now try and explain this one in plain english btw ;)).
An alternative would be to support some kind of different *type* (is in the ajax option), so that we know data is supposed to be put in the script tag body:
$.ajax( "https://apis.google.com/js/plusone.js", { dataType: "script", type: "inline", data: JSON.stringify({ parsetags: "explicit" })});
I would favour something like this, especially given the script tag injection transport does not support the type option anyway (always normalized it to "get"), though "inline" is not a very good name but heh.
I'd like to have other team members weight in here so that we can try and find a proper solution (knowing the second one has my vote).
Changed July 23, 2011 05:21PM UTC by comment:10
Thanks for the advice. I think you can close this issue, I failed at getting IE to create the node with the explicit config and having Google take to it. Tried .innerHTML, .text, and createTextNode.
I'm doing something entirely different now, creating dummy <divs> and doing gapi.plusone.render( $elem[0], options );
Thanks for taking the time to look at this edge case with me :)
Changed July 23, 2011 06:22PM UTC by comment:11
resolution: | → invalid |
---|---|
status: | assigned → closed |
OK, that's good news somehow, probably means the whole system only works with the latest script tag in the document (which always happen for non-dynamic non-async script tags).
As long as there is a way to load things asynchronously, all is good I guess.
Changed January 21, 2013 06:48PM UTC by comment:12
window['___gcfg'] = { parsetags: 'explicit' };
Crap, setting innerHTML on a script node seems to bust IE6.