jQuery Cross-Site AJAX Plugin

April 12th, 2007 by Ralf S. Engelschall

It is well known that with the help of a dynamically generated XHTML <script> DOM element one can achieve a portable cross-site variation of an AJAX-style client-server communication as the <script> is not staying under the “same-origin security policy” which restricts the regular AJAX methods. This allows one to load code from a third-party URL in the background.

For this in JavaScript one generates a <script> DOM element with a type attribute set to text/javascript and a src attribute set to the URL of the third-partly URL. That’s it. Well, more or less. But as a jQuery user I wanted this functionality abstracted with a variation of the already existing (plain AJAX) jQuery.getScript() function, which in turn especially allows me to execute a callback function once the script is loaded. And for cleanup and memory leak prevention reasons I wanted that the dynamically generated <script> DOM node is garbage collected automatically, too.

My result is a small jQuery plugin jquery.xsajax.js which provides just this. Find this jQuery plugin in the File Repository area.

14 Responses to “jQuery Cross-Site AJAX Plugin”

  1. Remy Sharp says:

    That plugin doesn’t work in Safari. It looks like you lifted the logic from the jQuery library because I hit a similar problem.

    The reason it doesn’t work in Safari is because the script element doesn’t fire any events when the external library is loaded, and hence listening for the onreadystatechange doesn’t work.

    I wrote an entry on how to get around this problem, but I’m not sure it will be helpful to your plugin without replicating the core test:

    http://remysharp.com/2007/04/12/how-to-detect-when-an-external-library-has-loaded/

  2. Ralf S. Engelschall says:

    Remy Sharp: yes, I had to apply the MSIE special case first and then determined that jQuery core contains a similar thing. And hence I’ve taken over the Safari special case blindly, because I’ve no Safari at hand myself. I’ll look at your workaround. Thanks for the hint.

  3. Ralf S. Engelschall says:

    BTW, does anybody know whether Konqueror/KHTML and Safari/WebKit emit any(!) event at all after loading a <script>?

  4. Ralf S. Engelschall says:

    Ok, I’ve looked deeper into the WebKit sources and the source WebKit/WebCore/html/HTMLTokenizer.cpp shows in the function HTMLTokenizer::notifyFinished() an explicit code which seems to emit the “load” event for the <script> tag. And this line exists already since a longer time in WebKit. So, as long as one uses a not too ancient Safari, I would expect that the “load” event on a <script> fires just fine.

    Unfortunately I’ve no Safari available myself, so can someone with a recent Safari please go to…

    http://trainofthoughts.org/repo/export/jquery/jquery.xsajax.test.html

    …and see whether you see the expected output…

    1. start sequence
    2. end sequence
    3. loaded script 1
    4. loaded script 2
    

    …occurs. If you only see the first two lines, we still have a problem with Safari. If the last two lines also are visible it means the “load” event fired just fine in Safari.

  5. Ralf S. Engelschall says:

    Ok, in the latest version of jquery.xsajax.js I’ve now tried to apply a Safari specific workaround based on two <script> tags. Perhaps someone with Safari can run http://trainofthoughts.org/repo/export/jquery/jquery.xsajax.test.html and tell me what output sequence (“N. xxxxx, N. xxxx”) is visible.

  6. Ralf S. Engelschall says:

    According to responses on jquery-discuss the plugin now also should work in Safari.

  7. traunic says:

    This is a really interesting plugin. I have been a long time JSAN user http://openjsan.org/doc/c/cw/cwest/JSAN/0.10/lib/JSAN.html and yesterday saw the videos of John Resig on yahoo. So this morning I tried jquery for the first time and within an hour had trimmed many of my core functions down to 1/3 their original size. But I was still lacking the On-Demand Javascript http://ajaxpatterns.org/On-Demand_Javascript and lazy loading I am so used to. Instead of using jquery and jsan seperately i was curious how well the two could be integrated. I found a couple require plugins, but they load async which is not so great for lazy loading, they also lack the namespace aspect that jsan provides.

    I took a quick crack at replicating jsan.use and came up w/:

    (function(jq){
    	jq.extend({
    		jsanUse: function(pkg, o){
    			o = jq.extend({
    				includePath: ['/jslib','jslib'],
    				altURL: null,
    				min: false
    			}, o || {});
    			if(o.altURL == null){
    				path = pkg.replace(/\./g, '/');
    				path = (o.min)?path.concat('-min.js'):path.concat('.js');
    			}else{
    				path = o.altURL;
    			}
    			try {
    				classdef = eval(pkg);
    				if (typeof classdef != 'undefined') return classdef;
    			} catch (e) { /* nice try, eh? */ }
    			for (var i = 0; i ...
    
  8. djot says:

    -
    Hi,

    The picture of yourself hides the links in the menu (Firefox v2.0.0.3) … is there no way to set you to :invisible? ;)

    The Cursor is somehow :invisible in this comment textarea, after typing some letters …

    djot
    -

  9. Gary Gurevich says:

    Clever workaround, but in my tests under Safari, there is no guarantee that scripts will be loaded in the order they are created within the DOM. See my test case here:

    http://xorox.net/trax/jsloadtest.html

    Expected output for sequential execution would be 1,2,3,4 but Safari 413.2 shows 3,1,2,4.

  10. apl says:

    Is there any solution for getting *HTML content* from other cross-site url?

  11. Sadaf says:

    Hi!!

    is it freely available?? how can i download the js file?? the svn client asks me for username and password.

    Regards,

  12. Ralf S. Engelschall says:

    It can be downloaded directly from the SVN web frontend: http://trainofthoughts.org/repo/getfile?f=jquery/jquery.xsajax.js&v=35

  13. Sadaf says:

    Thanks :)

  14. Peter Rosti says:

    The easiest way to transcend the “same-origin security policy” issue has been available for many years, yet it is shunned almost universally as a dogma for historical reasons. It deserves a new look. This is the use of frames. YES, ordinary framesets and frames (not iframes). While frames got a bad reputation many years ago for some shortcomings, the use of framesets and frames continues today, because of several reasons:
    1) NO same-origin security policy!
    2) Nested frames can be used in such a way that a (parent) frameset can contain a script which is accessible to every (child) frame contained in the frameset. This is a powerful construct. Many javascript programs have been developed which make use of this.
    3) Framesets and frames have a remarkably powerful and VERY concise format for defining the structure – This syntax includes the use of a wildcard spacing symbol (the star “*” symbol), which represents a “remainder by subtraction”. For example, one can define an attribute rows=”80,*,40″, which means take 80 pixels in height for the top frame, and 40 pixels in height for the bottom frmae, and * pixels (the “remainder”) for the middle frame. Try doing this in AJAX!! You can, but it is messy.
    4) Essentially ALL modern browsers FULLY support framesets and frames correctly.

    But the absence of a same-origin security policy is CRITICALLY IMPORTANT!!! It allows you to do things which a few years ago were considered improper, including “framing in” a page from one website into another website. Using framesets, this is easy, and does not require circumventing anything.

Leave a Reply