JS:jQuery.windowName.plugin

A common problem for every widget developer is getting data from the page to the server. The main obstacle is the cross-domain support or the lack there of. This is not as much as a problem when you’re sending small amounts of the data – you can load scripts from other domains sending the data through the GET request. A completely different story is the sending of lots of data, where you would normally need a POST request. Until now there were just a few possible solutions – use a Flash cross-domain bridge and build your own browser extension being the most prominent.

Now on you can easily use a new technique, first presented by Kris Zyp who wrote a dojo implementation for it. I was hoping that somebody would port this to other libraries but since nobody did I decided to do it myself. And a week later you can download the jQuery plugin.

Usage:

Just include the plugin in your code and use the builtin $.ajax function as you would normally. It will automatically figure out if it needs to be run (POST to a foreign domain), otherwise it will let the original function handle the request.

History

0.8.0-rc1

  • The first public release. It has been tested but not yet used in a production environment.
Known issues:
  1. The interval checking sometimes breaks the POST so no data is sent and the request returns an error.
  2. If you have a property called method, target or action this won’t work.

0.8.0-rc2

  • Fixed issues with empty posts (timer removed)
  • Fixed issues with method, submit, target, action data variables.
  • windowname added to data now
  • Window.name transport can now be requested via settings.windowname
  • Tested with more data – works on IE7, IE8 (both Vista), Firefox2 (Vista), Firefox3 (OSX, Vista), Safari3 (OSX, Vista), Opera 9.5 (OSX, Vista), Chrome

0.9.0

  • Added GET requests
  • You can specify a local empty file that it will request after post to get data with a settings.localfile setting
  • Fixed IE – if there’s a 404 on the requested local file and it’s too short IE will replace it with its own 404 which does not allow getting data from window.name
  • Added the full BSD license of the dojo code

0.9.1

  • Fixed a bug where + were left instead of spaces
  • Fixed an IE bug when fields named method, action, target would throw an error

How it works

The plugin hijacks the $.ajax function and will do its magic when you’re POSTing to a foreign (domain not same as domain of document) domain or you specify settings.windowname to force it. If these conditions are not met it will use the default ajax function to create the request.

The script first creates an iframe that will be the target of its request. If the request is of type GET it will open the location with the specified data as querystring in the iframe, if it’s a POST request it will first create a form with hidden fields that represent all data being sent. To allow sending of method, target, action and submit some magic is done (those override some important form object stuff) after which the form is posted to the iframe. This is readyState 2.

After the posted file is loaded (meaning it should have now set the window.name) an onload event is fired that loads an empty local file into the iframe. The empty local (same domain as the page) file can be set in the settings (settings.localfile) – if it isn’t the script will first try loading /robots.txt and /crossdomain.xml (two files commonly found in the root that are small) and if both fail it will load the page it’s on. All this is done only on IE where 404 doesn’t count as local. This is readyState 3.

When the local file is loaded and it is surely local we can read the text from the window.name. If it’s a string and it isn’t our default we set status to 200 and set the string as responseText, otherwise we set a 502 status. We can now cleanup which means removing the form, the iframe and all references we created in the global space.

The whole thing is written in such a manner that it will return a fully qualified XMLHttpRequest object with all methods and properties. You can abort the request and it will cancel loading and clean up, you can access readyState, responseText and everything else you’d do to an XHR object. It does however not implement features that cannot be used due to the fact that it’s an ordinary form submit – setting headers and such.

Interesting use

I’ve found that window.name transport is ideal for saving files – you can force the window.name transport to a url that will return a file with an Content-disposition: attachment; header. When the file loads you’ll get a popup to save it and the frame will disappear automatically. It’s even more convenient if you’re creating the file with a POST request.

Future

As I intend to use this in a production environment I reckon most of the tweaks will come during testing and while in production. No new features are currently planned.

Download

Download the JavaScript

Must read

Kris Zyp wrote a great article about this and also contributed window.name transport to dojo.

32 Responses to “JS:jQuery.windowName.plugin”

  1. […] After a week of mostly testing and fine-tuning the code I finally released the windowName transport plugin for jQuery. You can get the plugin here but I suggest you first check the plugin page. […]

  2. thanks for doing this port. I had a couple of issues trying to get it going.
    The data that gets posted is double urlencoded, so if my original data was “Dramatic Chipmunk Time”, i get “Dramatic+Chipmunk+Time” as the value on the other side. I got this doing both form.serialize() and form.serializeArray() to produce the data.
    I can’t seem to get the callback to fire, and have tracked it down to the iframes’ window.name is not changing properly. When i load my target page in another window, it changes the name as expected. Does this plugin require additional behavior on the target end?
    Finally, I would love to work with you on building this out to support $.get requests as well. Then we would have a full drop-in $.ajax replacement. Really great work getting this going!

  3. i got a version going that addresses the issues i named. Had to disable the ival = setInterval thing you had going to get frame onload detection working properly in FF3. What browser was that targetted for? Haven’t had a chance to check this stuff in IE, but have a look at my version here: http://gist.github.com/14811

  4. @Austin – it seemed like a good choice for browsers that have lame support for onload. i had problems with onload in IE specifically. The trouble with the timer is that it can break off the post if you’re sending lots of data unfortunatelly. I have to change this but I need a solution for IE first…

  5. @Austin – I see that you’re using the not yet released feature that will allow sending an xhr function in the settings. I wrote the code to support it, but wanted the plugin to work without patching 1.2.6…

  6. Hi Marko,

    It’s great that you’ve done this port, and I really appreciate your attribution to Kris and SitePen… we put a lot of work into figuring this stuff out.

    I would like to kindly request one change. Since you are using the code under the GPL, that means you’re making a derivative work of our code under the BSD license (since our other license, the AFL, is incompatible with the GPL per the FSF). One condition of the BSD is that you include full copyright attribution in your derivative work. Our copyright notice looks like this:

    /*
    Copyright (c) 2004-2008, The Dojo Foundation
    All Rights Reserved.

    Licensed under the Academic Free License version 2.1 or above OR the
    modified BSD license. For more information on Dojo licensing, see:

    http://dojotoolkit.org/license

    */

    Thanks so much, and good luck with the continued development of your plugin!

  7. […] can download the plugin here or you can go to the jQuery plugins page to get […]

  8. […] our example we return to the page: http://beebole.com/myapp/local.html. Marko Mrdjenovič, in its jQuery implementation tries to get /robot.txt or /crossdomain.xml which are common files found in the root of web […]

  9. mike says:

    Does this work with ie6?

  10. I have absolutely no idea as I don’t have it. Can test and check it out (IE6 on WinXP) if you need to be sure…

  11. Jonathan says:

    Is it possible to adapt this to not utilize a service based approach, but rather a cross-domain scripting call to get the window.name of a page contained in a local iframe?

  12. Not quite sure what you mean. If what you’re trying to say is that you don’t need to send data you can do that easily. Or are you saying that you would like to keep an iframe visible or it already exists and you would like to read its window.name?

  13. Jonathan says:

    Thanks for the reply and sorry it took me so long to get back. The latter of the two situations you reference is the one I am most interested in. I have an iFrame on the page that the user uses to manipulate an analytic object. I would like to have a button in the outer frame that reads the window.name property from the page hosted in the iFrame. Thanks again – terrific stuff.

  14. Logan says:

    Great work..
    Look like it has an issue with Safari browser. the browser identify itself is loading the web page in an indefinite loop. can anybody has a look and suggest a quick fix for it.
    Thanks

  15. Buddy says:

    DOCUMENT.DOMAIN PERMISSIONS ISSUE

    If you change the parent’s document.domain then you will create a permissions issue between you “the parent” and “the child” which is the iframe.

    Solutions:
    1) Edit the localfile html to also set the document.domain so that the browser will think they match.
    2) Do not set the document.domain

    (jquery window.name transport document.domain fix)

  16. […] our example we return to the page: http://beebole.com/myapp/local.html. Marko Mrdjenovič, in its jQuery implementation tries to get /robot.txt or /crossdomain.xml which are common files found in the root of web […]

  17. Jonathan says:

    Any testing done with ssl enabled on the target file in the ajax call?

  18. Konstantin says:

    Plugin does it’s job really good.
    I read the code, but could not understand why it needs to call for crossdomain.xml and robots.txt before performing the actual query. Can you please clarify this for me?

  19. The reason is pretty simple – you need to have a file on a local domain load inside the iframe to be able to access its window.name property. The defaults in the plugin are robots.txt and crossdomain.xml as they are commonly present on websites – you could override this with any local file though.

  20. Thanks for the plugin. I know the plugin is a derivative of the Dojo plugin, so I was wondering if you could also release your plugin under the Dojo license.

  21. I never got around to signing the release form so Dojo could use the changes. I intend to release the update under LGPL, but haven’t gotten around yet…

  22. Nice, but..
    “Unsafe JavaScript attempt to access frame with URL”
    (Chromium)

    Probably it is that modern browsers consider this window.name thing (or something else that you do on the iframe) to be unsafe, so they deny it.

    Luckily, on modern browsers we can do regular xhr-POST, and don’t need such hacks.

    Btw, here
    http://www.sitepen.com/blog/2008/07/22/windowname-transport/comment-page-1/#comment-88973
    kzyp says
    “@john: I assume you are talking about the jQuery version, which may not work Safari 3. The Dojo version that I wrote has been tested and does work on Safari 3.”

  23. Btw, I think your article would benefit from a “how should the response html look like” section.

    I assume this is enough,
    $data = array(…);
    $json_str = json_encode(json_encode($data));
    print <<<EOT

    window.name = $json_str;

    EOT;
    exit();
    Or maybe some html head and stuff around.

  24. AndyDM says:

    This stuff works great! I only have an issue where the windowname is never being set and as such we never come into either success nor error events of the original ajax call. I see in your code that you add &windowname=true to the data that’s being posted, but this is totally ignored on the server. Do I need to implement something for that?

  25. The server needs to know when the request is a windowname request, so it knows what to return. It’s also a good idea to implement a timeout on the client, because sometimes windowname never gets set and you need to handle that as an error…

  26. AndyDM says:

    Ok, supposing that I do send windowname=true to the server and I read this out there, I am currently posting to a WCF service. What do I need to return or do to make the windowname work?

  27. AndyDM says:

    Also, I always receive an error in the plugin because $.httpSuccess and $.httpData don’t exist…

  28. AndyDM says:

    I got it running now, thanks anyway. I did have to remove $.httpSuccess and $.httpData as they simply don’t exist. I’m running jQuery version 1.6.4.

  29. Nishant says:

    any ideas on how to make this work with jQuery version 1.7.2 ? i get errors as these functions do not exist – $.httpSuccess and $.httpData. simply removing them like the above reader suggested does not work

  30. No idea – I might look into it, but I wouldn’t get my hopes up if I were you. You should look into EasyXDM if you’re looking for a solution that works and is actively developed…

  31. ekrami says:

    Hello.
    Thank you very much for your plugin.
    Please help me.How we can use async false when using this plugin.When setting async: flase in jquery ajax it does not work.
    Thanks again.

  32. It’s a really old plugin, haven’t checked it or used it in a while…

Leave a Reply