Programming collection

January 2, 2008

Cross domain connection manager with same calling mechanism as YUI

Filed under: Javascript — terenceyim @ 4:24 pm
Tags: , , , ,

Update: The same functionality is now provided by the Yahoo! YUI Get Utility.

Update 2: Since the domain I used to host the file is not longer exist, I just paste the JS at the end of the post.

The YUI connection manager use XMLHttpRequest to make remote call, hence calling cross domain URL is prohibited by the browser security model. This class is to solve this situation without the need to setup any server side proxy, while maintaining the same calling mechanism as the YUI connection manager.

Script source: http://rockstonesand.com/js/crossdomainmanager.js

Minified version: http://rockstonesand.com/js/crossdomainmanager_min.js

Usage: Same as YUI connection manager

Functions supported:

asyncRequest, isCallInProgress, abort

Example:
Client side:

<script src="http://rockstonesand.com/js/crossdomainmanager_min.js"></script>
<script>
// Same callback object definition as YUI connection manager
var callback = {
    success: function(obj) {
        var response = obj.responseText;
        // Do UI updates
    },
    failure: function(obj) {
    }
};
var txId = CrossDomainConnect.asyncRequest(
   "http://api.flickr.com/services/feeds/photos_public.gne?lang=en-us&format=json",
   callback,
   "jsoncallback");
</script>

Limitations:

  • Only GET method is supported, as it uses script tag hack
  • The target server side script must support an additional “callback” parameter for the connection manager to specify a callback function.

The crossdomainmanager.js:


var CrossDomainConnect = {

    seqNo : 0,
    scriptNodeMap : {},

    asyncRequest : function(url, callback, callbackName) {

        // The URL must support a "callback" parameter
        if (!callbackName) {
            callbackName = "callback";
        }

        var responseName = "response" + this.seqNo;
        this.seqNo++;

        if (url.indexOf('?') === -1) {
            url += "?" + callbackName + "=CrossDomainConnect." + responseName;
        } else {
            url += "&" + callbackName + "=CrossDomainConnect." + responseName;
        }

        // Create the script node
        var node = document.createElement("script");
        node.setAttribute('src', url);

        this.scriptNodeMap[responseName] = node;

        var responseObj = { tId : responseName };
        if (callback.argument) {
            responseObj.argument = callback.argument;
        }

        var timeoutId = null;

        // Bind the response function
        this[responseName] = function(str) {
            delete this[responseName];
            delete this.scriptNodeMap[responseName];

            if (timeoutId) {
                clearTimeout(timeoutId);
            }

            // Must use setTimeout, otherwise may cause crashes in IE6
            setTimeout(function() {
                node.parentNode.removeChild(node);
            }, 0);

            responseObj.status = 200;
            responseObj.responseText = str;

            if (callback.scope) {
                callback.success.call(callback.scope, responseObj);
            } else {
                callback.success(responseObj);
            }
        };

        // Setup timeout function
        if (callback.timeout) {
            var that = this;
            var timeoutFunc = function() {
                that.abort(responseName, callback);
            };

            // Set the timeout
            timeoutId = setTimeout(timeoutFunc, callback.timeout);
        }

        var p = document.getElementsByTagName("head")[0] || document.body;

        p.appendChild(node);

        return responseName;
    },

    isCallInProgress : function(txId) {
        return this.hasOwnProperty(txId);
    },

    abort : function(txId, callback) {
        if (this[txId]) {
            var node = this.scriptNodeMap[txId];

            setTimeout(function() {
                node.parentNode.removeChild(node);
                node = null;
            }, 0);

            delete this[txId];
            delete this.scriptNodeMap[txId];

            if (callback) {
                var responseObj = { tId : txId };
                if (callback.argument) {
                    responseObj.argument = callback.argument;
                }

                responseObj.status = -1;
                responseObj.statusText = "transaction aborted";

                if (callback.scope) {
                    callback.failure.call(calback.scope, responseObj);
                } else {
                    callback.failure(responseObj);
                }
            }

            return true;
        }

        return false;
    }
};

3 Comments »

  1. JS is not available anymore. :-(
    It’s possbile to achive “the same” by the new YUI3 Cross-Domain-IO Flash version?
    Thanks!

    Comment by Bernhard — August 18, 2008 @ 1:52 pm | Reply

  2. god damn it…

    i need that JS…. but it’s just crashed…

    anyone has the backup file??

    Comment by jarkid — September 2, 2009 @ 6:03 am | Reply

    • I have included the JS in the post.

      Comment by terenceyim — September 2, 2009 @ 9:27 am | Reply


RSS feed for comments on this post. TrackBack URI

Leave a comment

Blog at WordPress.com.