/* File: comet.js Title: Comet plugin for xajax */ /* @package comet plugin @version $Id: @copyright Copyright (c) 2007 by Steffen Konerow (IE) @license http://www.xajaxproject.org/bsd_license.txt BSD License */ /* Class: xajax.ext.comet This class contains all functions for using comet streaming with xajax. */ try { if (undefined == xajax.ext) xajax.ext = { }; } catch (e) { } try { if (undefined == xajax.ext.comet) xajax.ext.comet = { }; } catch (e) { alert("Could not create xajax.ext.comet namespace"); } // create Shorthand for xajax.ext.comet xjxEc = xajax.ext.comet; // ------------------------------------------------------------------------------------------------------------------------------------- /* Function: detectSupport Detects browser for using fallback methods instead of multipart XHR responses. */ xjxEc.detectSupport = function() { var agt = navigator.userAgent.toLowerCase(); if (agt.indexOf("opera") != -1) return 'Opera'; if (agt.indexOf("staroffice") != -1) return 'Star Office'; if (agt.indexOf("webtv") != -1) return 'WebTV'; if (agt.indexOf("beonex") != -1) return 'Beonex'; if (agt.indexOf("chimera") != -1) return 'Chimera'; if (agt.indexOf("netpositive") != -1) return 'NetPositive'; if (agt.indexOf("phoenix") != -1) return 'Phoenix'; if (agt.indexOf("firefox") != -1) return 'Firefox'; if (agt.indexOf("safari") != -1) return 'Safari'; if (agt.indexOf("skipstone") != -1) return 'SkipStone'; if (agt.indexOf("msie") != -1) return 'Internet Explorer'; if (agt.indexOf("netscape") != -1) return 'Netscape'; if (agt.indexOf("mozilla/5.0") != -1) return 'Mozilla'; if (agt.indexOf('\/') != -1) { if (agt.substr(0, agt.indexOf('\/')) != 'mozilla') { return navigator.userAgent.substr(0, agt.indexOf('\/')); } else return 'Netscape'; } else if (agt.indexOf(' ') != -1) return navigator.userAgent.substr(0, agt.indexOf(' ')); else return navigator.userAgent; // if (navigator.appVersion.indexOf("MSIE")!=-1) // { // var version,temp; // temp=navigator.appVersion.split("MSIE") // version=parseFloat(temp[1]) // if (version>=5.5) return "MSIE"; // } // if ( "undefined" != typeof window.opera ) // { // return "OPERA"; // } // if ( "undefined" != typeof window.Iterator ) // { // return "FF2"; // } return false; } // ------------------------------------------------------------------------------------------------------------------------------------- /* Function: prepareRequestXHR Prepares the XMLHttpRequest object for this xajax request in FF/Safari browsers. */ xjxEc.prepareRequestXHR = function (oRequest) { if (true == oRequest.comet) { var xx = xajax; var xt = xx.tools; oRequest.request = xt.getRequestObject(); oRequest.setRequestHeaders = function(headers) { if ('object' == typeof headers) { for (var optionName in headers) this.request.setRequestHeader(optionName, headers[optionName]); } } oRequest.setCommonRequestHeaders = function() { this.setRequestHeaders(this.commonHeaders); } oRequest.setPostRequestHeaders = function() { this.setRequestHeaders(this.postHeaders); } oRequest.setGetRequestHeaders = function() { this.setRequestHeaders(this.getHeaders); } oRequest.applyRequestHeaders = function() { } oRequest.setCommonRequestHeaders = function() { this.request.setRequestHeader('If-Modified-Since', 'Sat, 1 Jan 2000 00:00:00 GMT'); this.request.setRequestHeader('streaming', 'xhr'); if (typeof (oRequest.header) == "object") { for (a in oRequest.header) this.request.setRequestHeader(a, oRequest.header[a]); } } oRequest.comet = { }; oRequest.comet.LastPosition = 0; oRequest.comet.inProgress = false; var pollLatestResponse = function() { xjxEc.responseProcessor.XHR(oRequest); } oRequest.pollTimer = setInterval(pollLatestResponse, 300); oRequest.request.onreadystatechange = function() { if (oRequest.request.readyState < 3) { console.log('readyState < 3'); return; } if (oRequest.request.readyState == 4) { console.log('readyState == 4'); clearInterval(oRequest.pollTimer); xjxEc.responseProcessor.XHR(oRequest); //xajax.responseReceived(oRequest); xajax.completeResponse(oRequest); return; } } oRequest.finishRequest = function() { return this.returnValue; } if ('undefined' != typeof oRequest.userName && 'undefined' != typeof oRequest.password) { oRequest.open = function() { this.request.open(this.method, this.requestURI, true, oRequest.userName, oRequest.password); } } else { oRequest.open = function() { this.request.open(this.method, this.requestURI, true); } } if ('POST' == oRequest.method) { // W3C: Method is case sensitive oRequest.applyRequestHeaders = function() { this.setCommonRequestHeaders(); try { this.setPostRequestHeaders(); } catch (e) { this.method = 'GET'; this.requestURI += this.requestURI.indexOf('?') == -1 ? '?' : '&'; this.requestURI += this.requestData; this.requestData = ''; if (0 == this.requestRetry) this.requestRetry = 1; throw e; } } } else { oRequest.applyRequestHeaders = function() { this.setCommonRequestHeaders(); this.setGetRequestHeaders(); } } return; } return xjxEc.prepareRequest(oRequest); } // ------------------------------------------------------------------------------------------------------------------------------------- /* Function: connect_htmlfile Create a hidden iframe for IE */ xjxEc.connect_htmlfile = function (url, callback, oRequest) { try { xjxEc.transferDoc = new ActiveXObject("htmlfile"); xjxEc.transferDoc.open(); xjxEc.transferDoc.write(""); xjxEc.transferDoc.write(""); xjxEc.transferDoc.write(""); xjxEc.transferDoc.close(); xjxEc.ifrDiv = xjxEc.transferDoc.createElement("div"); xjxEc.transferDoc.body.appendChild(xjxEc.ifrDiv); xjxEc.ifrDiv.innerHTML = ""; xjxEc.transferDoc.callback = function (response) { callback(response, oRequest); }; } catch (ex) { } } // ------------------------------------------------------------------------------------------------------------------------------------- /* Function: prepareRequestActiveX Prepares the Iframe for streaming with active X */ xjxEc.prepareRequestActiveX = function(oRequest) { if (true == oRequest.comet) { var xx = xajax; var xt = xx.tools; oRequest.requestURI += oRequest.requestURI.indexOf('?') == -1 ? '?' : '&'; oRequest.requestURI += oRequest.requestData; oRequest.requestData = ''; try { xjxEc.connect_htmlfile(oRequest.requestURI, xjxEc.responseProcessor.ActiveX, oRequest); if (0 < oRequest.requestRetry) oRequest.requestRetry = 0; } catch (ex) { } return; } return xjxEc.prepareRequest(oRequest); } // ------------------------------------------------------------------------------------------------------------------------------------- /* Function: prepareRequestHTMLDRAFT Prepares streaming with HTML 5 Draft */ xjxEc.prepareRequestHTMLDRAFT = function(oRequest) { if (true == oRequest.comet) { var xx = xajax; var xt = xx.tools; oRequest.requestURI += oRequest.requestURI.indexOf('?') == -1 ? '?' : '&'; oRequest.requestURI += oRequest.requestData; oRequest.requestURI += "&xjxstreaming=HTML5DRAFT"; oRequest.inProgress = false; try { var uri = oRequest.requestURI; var es = document.createElement("event-source"); es.setAttribute("src", uri); es.setAttribute("width", 200); es.setAttribute("height", 200); es.style.display = "block"; callback = function(event) { xjxEc.responseProcessor.HTMLDRAFT(event.data, oRequest); }; remove = function() { es.removeEventListener("xjxstream", callback, false); es.removeEventListener("xjxendstream", remove, false); //document.body.removeChild(es); } es.addEventListener("xjxstream", callback, false); es.addEventListener("xjxendstream", remove, false); document.body.appendChild(es); if (0 < oRequest.requestRetry) oRequest.requestRetry = 0; } catch (ex) { } return; } return xjxEc.prepareRequest(oRequest); } // ------------------------------------------------------------------------------------------------------------------------------------- /* Function: responseProcessor.XHR Processes the streaming response for FF/Safari */ xajax.debug = { }; xajax.debug.prepareDebugText = function(text) { try { text = text.replace(/&/g, '&').replace(//g, '>').replace(/\n/g, '
'); return text; } catch (e) { xajax.debug.stringReplace = function(haystack, needle, newNeedle) { var segments = haystack.split(needle); haystack = ''; for (var i = 0; i < segments.length; ++i) { if (0 != i) haystack += newNeedle; haystack += segments[i]; } return haystack; } xajax.debug.prepareDebugText = function(text) { text = xajax.debug.stringReplace(text, '&', '&'); text = xajax.debug.stringReplace(text, '<', '<'); text = xajax.debug.stringReplace(text, '>', '>'); text = xajax.debug.stringReplace(text, '\n', '
'); return text; } xajax.debug.prepareDebugText(text); } } xjxEc.responseProcessor = { } xjxEc.responseProcessor.XHR = function(oRequest) { var xx = xajax; var xt = xx.tools; var xcb = xx.callback; var gcb = xcb.global; var lcb = oRequest.callback; var oRet = oRequest.returnValue; if ("" == oRequest.request.responseText) return; var allMessages = oRequest.request.responseText; if (true === oRequest.comet.inProgress) return; oRequest.comet.inProgress = true; do { var unprocessed = allMessages.substring(oRequest.comet.LastPosition); var messageXMLEndIndex = unprocessed.indexOf(""); if (messageXMLEndIndex != -1) { var endOfFirstMessageIndex = messageXMLEndIndex + ("").length; var anUpdate = unprocessed.substring(0, endOfFirstMessageIndex); var cmd = (new DOMParser()).parseFromString(anUpdate, "text/xml"); try { var seq = 0; var child = cmd.documentElement.firstChild; xt.xml.processFragment(child, seq, oRet, oRequest); } catch (ex) { } xt.queue.process(xx.response); oRequest.comet.LastPosition += endOfFirstMessageIndex; } } while (messageXMLEndIndex != -1); oRequest.comet.inProgress = false; return oRet; } // ------------------------------------------------------------------------------------------------------------------------------------- /* Function: responseProcessor.ActiveX Processes the streaming response for IE */ xjxEc.responseProcessor.ActiveX = function(response, oRequest) { response.replace('\"', '"'); var xx = xajax; var xt = xx.tools; var xcb = xx.callback; var gcb = xcb.global; var lcb = oRequest.callback; var oRet = oRequest.returnValue; if (response) { var cmd = (new DOMParser()).parseFromString(response, "text/xml"); var seq = 0; var child = cmd.documentElement.firstChild; xt.xml.processFragment(child, seq, oRequest); if (null == xx.response.timeout) xt.queue.process(xx.response); } return oRet; } // ------------------------------------------------------------------------------------------------------------------------------------- /* Function: responseProcessor.HTMLDRAFT Processes the streaming response for HTML 5 Draft Browsers (Opera 9+) */ xjxEc.responseProcessor.HTMLDRAFT = function(response, oRequest) { var xx = xajax; var xt = xx.tools; var xcb = xx.callback; var gcb = xcb.global; var lcb = oRequest.callback; var oRet = oRequest.returnValue; if (oRequest.inProgress) return; if (response && oRequest.lastResponse !== response) { oRequest.inProgress = true; var cmd = (new DOMParser()).parseFromString(response, "text/xml"); var seq = 0; var child = cmd.documentElement.firstChild; xt.xml.processFragment(child, seq, oRequest); if (null == xx.response.timeout) xt.queue.process(xx.response); oRequest.inProgress=false; oRequest.lastResponse = response } return oRet; } // ------------------------------------------------------------------------------------------------------------------------------------- /* Function: submitRequestActiveX Supresses the xajax.submitRequest() function call for IE in streaming calls. */ xjxEc.submitRequestActiveX = function(oRequest) { if (true == oRequest.comet) return; xjxEc.submitRequest(oRequest); } // ------------------------------------------------------------------------------------------------------------------------------------- /* variable setup. Detects IE and replaces the according functions */ xjxEc.prepareRequest = xajax.prepareRequest; xjxEc.stream_support = xjxEc.detectSupport(); switch (xjxEc.stream_support) { case "Internet Explorer": xajax.prepareRequest = xjxEc.prepareRequestActiveX; xjxEc.submitRequest = xajax.submitRequest; xajax.submitRequest = xjxEc.submitRequestActiveX; break; case "Firefox": case "Safari": xajax.prepareRequest = xjxEc.prepareRequestXHR; break; case "Opera": xajax.prepareRequest = xjxEc.prepareRequestHTMLDRAFT; xjxEc.submitRequest = xajax.submitRequest; xajax.submitRequest = xjxEc.submitRequestActiveX; break; default: alert("Xajax.Ext.Comet: Your browser does not support comet streaming or is not yet supported by this plugin!"); } // ------------------------------------------------------------------------------------------------------------------------------------- /* Function: DOMParser Prototype DomParser for IE/Opera */ if (typeof DOMParser == "undefined") { DOMParser = function () { } DOMParser.prototype.parseFromString = function (str, contentType) { if (typeof ActiveXObject != "undefined") { var d = new ActiveXObject("Microsoft.XMLDOM"); d.loadXML(str); return d; } else if (typeof XMLHttpRequest != "undefined") { var req = new XMLHttpRequest; req.open("GET", "data:" + (contentType || "application/xml") + ";charset=utf-8," + encodeURIComponent(str), false); if (req.overrideMimeType) { req.overrideMimeType(contentType); } req.send(null); return req.responseXML; } } } // -------------------------------------------------------------------------------------------------------------------------------------