//This file will not work for Opera or on https URLs. It can be made to work by having the site host //a blank html page that can be loaded in the iframe instead of using about:blank and document.write. ;(function(){ var oldRequestData = AIM.core.requestData; var requestData = function(transactionObject) { //See if we should revert to old definition if //sockets are in play. if (AIM.params.useSWFListener) { AIM.core.requestData = oldRequestData; return AIM.core.requestData.apply(AIM.core, arguments); } var len = AIM.core.AIMData.length; transactionObject.timestamp = Date.parse(new Date()); var aimData = AIM.core.AIMData[len] = {}; aimData.objData = transactionObject; if(transactionObject.dataURI.indexOf("?") == -1) { transactionObject.dataURI+="?r=" + len + "&nocache=" + Date.parse(new Date()); } else { transactionObject.dataURI+="&r=" + len + "&nocache=" + Date.parse(new Date()); } AIM.core.debug("requestData: " + transactionObject.dataURI); aimScriptFrame.add(transactionObject); }; //Override AIM.core.acceptData so we can get script IDs that can be cleaned up. var oldAcceptData = AIM.core.acceptData; var acceptData = function(json) { //See if we should revert to old definition if //sockets are in play. if (AIM.params.useSWFListener) { AIM.core.acceptData = oldAcceptData; return AIM.core.acceptData.apply(AIM.core, arguments); } var requestId = parseInt(json.response.requestId); //Track which node can be removed. aimScriptFrame.completed(AIM.core.AIMData[requestId].objData); //Do the original action. return oldAcceptData.apply(AIM.core, arguments); }; //Override AIM.core.listen so we can get script IDs that can be cleaned up. var oldListen = AIM.core.listen; var listeners = {}; var listenerFrameId = null; var listen = function(json) { //See if we should revert to old definition if //sockets are in play. if (AIM.params.useSWFListener) { AIM.core.listen = oldListen; return AIM.core.listen.apply(AIM.core, arguments); } aimScriptFrame._done[listenerFrameId].push(json.response.requestId); AIM.core.watchReadyState(); return oldListen.apply(AIM.core, arguments); } var oldListenerObject = AIM.core.createListenerObject; createListenerObject = function() { AIM.core.debug("scriptiframe createListenerObject called"); //See if we should revert to old definition if //sockets are in play. if (AIM.params.useSWFListener) { AIM.core.createListenerObject = oldListenerObject; return AIM.core.createListenerObject.apply(AIM.core, arguments); } //Work from original AIM.core.createListenerObject clearTimeout(AIM.core.requestInterval); AIM.core.destroyListenerObject(false); //Create a dummy transaction object. //Create a script ID here so we can find it in the response as the requestId property. var scriptId = "aimScriptFrame" + (scriptCounter++); var transactionObject = { dataURI: AIM.params.listenerURI + "&r=" + scriptId + "&" + Date.parse(new Date()), aimScriptFrameScriptId: scriptId, aimScriptFrameId:"AimCoreFetchPipe" }; //Add to the right iframe pipe. aimScriptFrame.add(transactionObject); //Grab the iframe's name for use in the AIM.core.listen override. listenerFrameId = transactionObject.aimScriptFrameId; //Work from original AIM.core.createListenerObject AIM.core.connectionTimer = window.setTimeout(AIM.core.resetConnection,AIM.params.REQUEST_TIMEOUT + 3000); document.cookie = "AIM-fetchURI=" + AIM.params.listenerURI + "; path=/; domain=" + document.domain; }; //Browser detection. You know you love it. var ua = navigator.userAgent; var isGecko = (ua.indexOf("Gecko") >= 0 && !parseFloat(ua.split("WebKit/")[1])); //Counter used for script IDs inside an iframe. var scriptCounter = 0; window.aimScriptFrame = { add: function(transactionObject) { //Assumes callback is called c=, to make this easy to plug into AIM. var url = transactionObject.dataURI; if (isGecko) { url = url.replace(/([&?])c=/, "$1c=parent."); } AIM.core.debug("aimScriptFrame.add url: " + url); //Set up the IDs. var frameId = transactionObject.aimScriptFrameId || "aimScriptFramePipe"; var scriptId = transactionObject.aimScriptFrameScriptId || "aimScriptFrame" + (scriptCounter++); //Hold onto to IDs for cleanup later. transactionObject.aimScriptFrameId = frameId; transactionObject.aimScriptFrameScriptId = scriptId; //Create container for done scripts. if (!this._done[frameId]) { this._done[frameId] = []; } if (isGecko) { var ioArgs = { id: scriptId, url: url }; var frame = document.getElementById(frameId); if(!frame){ //Loading of the frame document is asynchronous, //so we need to do callback stuff. //This may fail for https urls, given the about: seed URL. this._getWaiters(frameId).push(ioArgs); this.createIframe(frameId, "aimScriptFrame._loaded('" + frameId + "');", "about:blank"); }else{ //Frame loading could still be happening. Only call attach if the frame has loaded. if(aimScriptFrame._loadedIds[frameId]){ //Clean up done scripts. this.clean(frameId); //Attach the new script. this.attach(ioArgs.id, ioArgs.url, frame.contentDocument); }else{ this._getWaiters(frameId).push(ioArgs); } } } else { //For non-Gecko browsers just use current document. this.clean(frameId); this.attach(scriptId, url); } }, completed: function(transactionObject) { //Tracks done scripts for removal later. this._done[transactionObject.aimScriptFrameId].push(transactionObject.aimScriptFrameScriptId); }, attach: function(/*String*/id, /*String*/url, /*Document?*/frameDocument){ var doc = (frameDocument || document); var element = doc.createElement("script"); element.type = "text/javascript"; element.src = url; element.id = id; element.charset = "utf-8"; doc.getElementsByTagName("head")[0].appendChild(element); }, clean: function(frameId) { //Clean up done scripts for a given iframe ID. var done = this._done[frameId]; if (done && done.length) { var doc = isGecko ? document.getElementById(frameId).contentDocument : document; var scriptId; while((scriptId = done.pop())) { var node = doc.getElementById(scriptId); if (node) { node.parentNode.removeChild(node); } } } }, _waiters: {}, _loadedIds: {}, _done: {}, _getWaiters: function(/*String*/frameId){ return this._waiters[frameId] || (this._waiters[frameId] = []); }, _loaded: function(/*String*/frameId){ //summary: callback used when waiting for a frame to load //Write in a skeleton document. var doc = document.getElementById(frameId).contentDocument; doc.write(''); //Only do doc.close for isGecko doc.close(); //Attach all the waiting requests. var waiters = this._getWaiters(frameId); for(var i = 0; i < waiters.length; i++){ var ioArgs = waiters[i]; this.attach(ioArgs.id, ioArgs.url, doc); } //Clean up state. this._loadedIds[frameId] = true; this._waiters[frameId] = null; }, //May not work for https pages, unless you create the iframe with //a uri that is an https value. Optimized only for isGecko. createIframe: function(/*String*/fname, /*String*/onloadstr, /*String?*/uri){ uri = uri || "about:blank"; var cframe = null; cframe = document.createElement("iframe"); cframe.name = fname; cframe.setAttribute("name", fname); cframe.id = fname; document.getElementsByTagName("body")[0].appendChild(cframe); window[fname] = cframe; var s = cframe.style; s.position = "absolute"; s.left = top = "1px"; s.height = width = "1px"; s.visibility = "hidden"; cframe.contentWindow.location.replace(uri); cframe.onload = new Function(onloadstr); return cframe; }, engage: function() { AIM.core.requestData = requestData; AIM.core.acceptData = acceptData; AIM.core.listen = listen; AIM.core.createListenerObject = createListenerObject; } }; })();