| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451 |
- // XMLHttpRequest.js Copyright (C) 2010 Sergey Ilinsky (http://www.ilinsky.com)
- //
- // Licensed under the Apache License, Version 2.0 (the "License");
- // you may not use this file except in compliance with the License.
- // You may obtain a copy of the License at
- //
- // http://www.apache.org/licenses/LICENSE-2.0
- //
- // Unless required by applicable law or agreed to in writing, software
- // distributed under the License is distributed on an "AS IS" BASIS,
- // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- // See the License for the specific language governing permissions and
- // limitations under the License.
- /**
- * @requires OpenLayers/Request.js
- */
- (function () {
- // Save reference to earlier defined object implementation (if any)
- var oXMLHttpRequest = window.XMLHttpRequest;
- // Define on browser type
- var bGecko = !!window.controllers,
- bIE = window.document.all && !window.opera,
- bIE7 = bIE && window.navigator.userAgent.match(/MSIE 7.0/);
- // Enables "XMLHttpRequest()" call next to "new XMLHttpReques()"
- function fXMLHttpRequest() {
- this._object = oXMLHttpRequest && !bIE7 ? new oXMLHttpRequest : new window.ActiveXObject("Microsoft.XMLHTTP");
- this._listeners = [];
- };
- // Constructor
- function cXMLHttpRequest() {
- return new fXMLHttpRequest;
- };
- cXMLHttpRequest.prototype = fXMLHttpRequest.prototype;
- // BUGFIX: Firefox with Firebug installed would break pages if not executed
- if (bGecko && oXMLHttpRequest.wrapped)
- cXMLHttpRequest.wrapped = oXMLHttpRequest.wrapped;
- // Constants
- cXMLHttpRequest.UNSENT = 0;
- cXMLHttpRequest.OPENED = 1;
- cXMLHttpRequest.HEADERS_RECEIVED = 2;
- cXMLHttpRequest.LOADING = 3;
- cXMLHttpRequest.DONE = 4;
- // Public Properties
- cXMLHttpRequest.prototype.readyState = cXMLHttpRequest.UNSENT;
- cXMLHttpRequest.prototype.responseText = '';
- cXMLHttpRequest.prototype.responseXML = null;
- cXMLHttpRequest.prototype.status = 0;
- cXMLHttpRequest.prototype.statusText = '';
- // Priority proposal
- cXMLHttpRequest.prototype.priority = "NORMAL";
- // Instance-level Events Handlers
- cXMLHttpRequest.prototype.onreadystatechange = null;
- // Class-level Events Handlers
- cXMLHttpRequest.onreadystatechange = null;
- cXMLHttpRequest.onopen = null;
- cXMLHttpRequest.onsend = null;
- cXMLHttpRequest.onabort = null;
- // Public Methods
- cXMLHttpRequest.prototype.open = function(sMethod, sUrl, bAsync, sUser, sPassword) {
- // Delete headers, required when object is reused
- delete this._headers;
- // When bAsync parameter value is omitted, use true as default
- if (arguments.length < 3)
- bAsync = true;
- // Save async parameter for fixing Gecko bug with missing readystatechange in synchronous requests
- this._async = bAsync;
- // Set the onreadystatechange handler
- var oRequest = this,
- nState = this.readyState,
- fOnUnload;
- // BUGFIX: IE - memory leak on page unload (inter-page leak)
- if (bIE && bAsync) {
- fOnUnload = function() {
- if (nState != cXMLHttpRequest.DONE) {
- fCleanTransport(oRequest);
- // Safe to abort here since onreadystatechange handler removed
- oRequest.abort();
- }
- };
- window.attachEvent("onunload", fOnUnload);
- }
- // Add method sniffer
- if (cXMLHttpRequest.onopen)
- cXMLHttpRequest.onopen.apply(this, arguments);
- if (arguments.length > 4)
- this._object.open(sMethod, sUrl, bAsync, sUser, sPassword);
- else
- if (arguments.length > 3)
- this._object.open(sMethod, sUrl, bAsync, sUser);
- else
- this._object.open(sMethod, sUrl, bAsync);
- this.readyState = cXMLHttpRequest.OPENED;
- fReadyStateChange(this);
- this._object.onreadystatechange = function() {
- if (bGecko && !bAsync)
- return;
- // Synchronize state
- oRequest.readyState = oRequest._object.readyState;
- //
- fSynchronizeValues(oRequest);
- // BUGFIX: Firefox fires unnecessary DONE when aborting
- if (oRequest._aborted) {
- // Reset readyState to UNSENT
- oRequest.readyState = cXMLHttpRequest.UNSENT;
- // Return now
- return;
- }
- if (oRequest.readyState == cXMLHttpRequest.DONE) {
- // Free up queue
- delete oRequest._data;
- /* if (bAsync)
- fQueue_remove(oRequest);*/
- //
- fCleanTransport(oRequest);
- // Uncomment this block if you need a fix for IE cache
- /*
- // BUGFIX: IE - cache issue
- if (!oRequest._object.getResponseHeader("Date")) {
- // Save object to cache
- oRequest._cached = oRequest._object;
- // Instantiate a new transport object
- cXMLHttpRequest.call(oRequest);
- // Re-send request
- if (sUser) {
- if (sPassword)
- oRequest._object.open(sMethod, sUrl, bAsync, sUser, sPassword);
- else
- oRequest._object.open(sMethod, sUrl, bAsync, sUser);
- }
- else
- oRequest._object.open(sMethod, sUrl, bAsync);
- oRequest._object.setRequestHeader("If-Modified-Since", oRequest._cached.getResponseHeader("Last-Modified") || new window.Date(0));
- // Copy headers set
- if (oRequest._headers)
- for (var sHeader in oRequest._headers)
- if (typeof oRequest._headers[sHeader] == "string") // Some frameworks prototype objects with functions
- oRequest._object.setRequestHeader(sHeader, oRequest._headers[sHeader]);
- oRequest._object.onreadystatechange = function() {
- // Synchronize state
- oRequest.readyState = oRequest._object.readyState;
- if (oRequest._aborted) {
- //
- oRequest.readyState = cXMLHttpRequest.UNSENT;
- // Return
- return;
- }
- if (oRequest.readyState == cXMLHttpRequest.DONE) {
- // Clean Object
- fCleanTransport(oRequest);
- // get cached request
- if (oRequest.status == 304)
- oRequest._object = oRequest._cached;
- //
- delete oRequest._cached;
- //
- fSynchronizeValues(oRequest);
- //
- fReadyStateChange(oRequest);
- // BUGFIX: IE - memory leak in interrupted
- if (bIE && bAsync)
- window.detachEvent("onunload", fOnUnload);
- }
- };
- oRequest._object.send(null);
- // Return now - wait until re-sent request is finished
- return;
- };
- */
- // BUGFIX: IE - memory leak in interrupted
- if (bIE && bAsync)
- window.detachEvent("onunload", fOnUnload);
- }
- // BUGFIX: Some browsers (Internet Explorer, Gecko) fire OPEN readystate twice
- if (nState != oRequest.readyState)
- fReadyStateChange(oRequest);
- nState = oRequest.readyState;
- }
- };
- function fXMLHttpRequest_send(oRequest) {
- oRequest._object.send(oRequest._data);
- // BUGFIX: Gecko - missing readystatechange calls in synchronous requests
- if (bGecko && !oRequest._async) {
- oRequest.readyState = cXMLHttpRequest.OPENED;
- // Synchronize state
- fSynchronizeValues(oRequest);
- // Simulate missing states
- while (oRequest.readyState < cXMLHttpRequest.DONE) {
- oRequest.readyState++;
- fReadyStateChange(oRequest);
- // Check if we are aborted
- if (oRequest._aborted)
- return;
- }
- }
- };
- cXMLHttpRequest.prototype.send = function(vData) {
- // Add method sniffer
- if (cXMLHttpRequest.onsend)
- cXMLHttpRequest.onsend.apply(this, arguments);
- if (!arguments.length)
- vData = null;
- // BUGFIX: Safari - fails sending documents created/modified dynamically, so an explicit serialization required
- // BUGFIX: IE - rewrites any custom mime-type to "text/xml" in case an XMLNode is sent
- // BUGFIX: Gecko - fails sending Element (this is up to the implementation either to standard)
- if (vData && vData.nodeType) {
- vData = window.XMLSerializer ? new window.XMLSerializer().serializeToString(vData) : vData.xml;
- if (!oRequest._headers["Content-Type"])
- oRequest._object.setRequestHeader("Content-Type", "application/xml");
- }
- this._data = vData;
- /*
- // Add to queue
- if (this._async)
- fQueue_add(this);
- else*/
- fXMLHttpRequest_send(this);
- };
- cXMLHttpRequest.prototype.abort = function() {
- // Add method sniffer
- if (cXMLHttpRequest.onabort)
- cXMLHttpRequest.onabort.apply(this, arguments);
- // BUGFIX: Gecko - unnecessary DONE when aborting
- if (this.readyState > cXMLHttpRequest.UNSENT)
- this._aborted = true;
- this._object.abort();
- // BUGFIX: IE - memory leak
- fCleanTransport(this);
- this.readyState = cXMLHttpRequest.UNSENT;
- delete this._data;
- /* if (this._async)
- fQueue_remove(this);*/
- };
- cXMLHttpRequest.prototype.getAllResponseHeaders = function() {
- return this._object.getAllResponseHeaders();
- };
- cXMLHttpRequest.prototype.getResponseHeader = function(sName) {
- return this._object.getResponseHeader(sName);
- };
- cXMLHttpRequest.prototype.setRequestHeader = function(sName, sValue) {
- // BUGFIX: IE - cache issue
- if (!this._headers)
- this._headers = {};
- this._headers[sName] = sValue;
- return this._object.setRequestHeader(sName, sValue);
- };
- // EventTarget interface implementation
- cXMLHttpRequest.prototype.addEventListener = function(sName, fHandler, bUseCapture) {
- for (var nIndex = 0, oListener; oListener = this._listeners[nIndex]; nIndex++)
- if (oListener[0] == sName && oListener[1] == fHandler && oListener[2] == bUseCapture)
- return;
- // Add listener
- this._listeners.push([sName, fHandler, bUseCapture]);
- };
- cXMLHttpRequest.prototype.removeEventListener = function(sName, fHandler, bUseCapture) {
- for (var nIndex = 0, oListener; oListener = this._listeners[nIndex]; nIndex++)
- if (oListener[0] == sName && oListener[1] == fHandler && oListener[2] == bUseCapture)
- break;
- // Remove listener
- if (oListener)
- this._listeners.splice(nIndex, 1);
- };
- cXMLHttpRequest.prototype.dispatchEvent = function(oEvent) {
- var oEventPseudo = {
- 'type': oEvent.type,
- 'target': this,
- 'currentTarget':this,
- 'eventPhase': 2,
- 'bubbles': oEvent.bubbles,
- 'cancelable': oEvent.cancelable,
- 'timeStamp': oEvent.timeStamp,
- 'stopPropagation': function() {}, // There is no flow
- 'preventDefault': function() {}, // There is no default action
- 'initEvent': function() {} // Original event object should be initialized
- };
- // Execute onreadystatechange
- if (oEventPseudo.type == "readystatechange" && this.onreadystatechange)
- (this.onreadystatechange.handleEvent || this.onreadystatechange).apply(this, [oEventPseudo]);
- // Execute listeners
- for (var nIndex = 0, oListener; oListener = this._listeners[nIndex]; nIndex++)
- if (oListener[0] == oEventPseudo.type && !oListener[2])
- (oListener[1].handleEvent || oListener[1]).apply(this, [oEventPseudo]);
- };
- //
- cXMLHttpRequest.prototype.toString = function() {
- return '[' + "object" + ' ' + "XMLHttpRequest" + ']';
- };
- cXMLHttpRequest.toString = function() {
- return '[' + "XMLHttpRequest" + ']';
- };
- // Helper function
- function fReadyStateChange(oRequest) {
- // Sniffing code
- if (cXMLHttpRequest.onreadystatechange)
- cXMLHttpRequest.onreadystatechange.apply(oRequest);
- // Fake event
- oRequest.dispatchEvent({
- 'type': "readystatechange",
- 'bubbles': false,
- 'cancelable': false,
- 'timeStamp': new Date + 0
- });
- };
- function fGetDocument(oRequest) {
- var oDocument = oRequest.responseXML,
- sResponse = oRequest.responseText;
- // Try parsing responseText
- if (bIE && sResponse && oDocument && !oDocument.documentElement && oRequest.getResponseHeader("Content-Type").match(/[^\/]+\/[^\+]+\+xml/)) {
- oDocument = new window.ActiveXObject("Microsoft.XMLDOM");
- oDocument.async = false;
- oDocument.validateOnParse = false;
- oDocument.loadXML(sResponse);
- }
- // Check if there is no error in document
- if (oDocument)
- if ((bIE && oDocument.parseError != 0) || !oDocument.documentElement || (oDocument.documentElement && oDocument.documentElement.tagName == "parsererror"))
- return null;
- return oDocument;
- };
- function fSynchronizeValues(oRequest) {
- try { oRequest.responseText = oRequest._object.responseText; } catch (e) {}
- try { oRequest.responseXML = fGetDocument(oRequest._object); } catch (e) {}
- try { oRequest.status = oRequest._object.status; } catch (e) {}
- try { oRequest.statusText = oRequest._object.statusText; } catch (e) {}
- };
- function fCleanTransport(oRequest) {
- // BUGFIX: IE - memory leak (on-page leak)
- oRequest._object.onreadystatechange = new window.Function;
- };
- /*
- // Queue manager
- var oQueuePending = {"CRITICAL":[],"HIGH":[],"NORMAL":[],"LOW":[],"LOWEST":[]},
- aQueueRunning = [];
- function fQueue_add(oRequest) {
- oQueuePending[oRequest.priority in oQueuePending ? oRequest.priority : "NORMAL"].push(oRequest);
- //
- setTimeout(fQueue_process);
- };
- function fQueue_remove(oRequest) {
- for (var nIndex = 0, bFound = false; nIndex < aQueueRunning.length; nIndex++)
- if (bFound)
- aQueueRunning[nIndex - 1] = aQueueRunning[nIndex];
- else
- if (aQueueRunning[nIndex] == oRequest)
- bFound = true;
- if (bFound)
- aQueueRunning.length--;
- //
- setTimeout(fQueue_process);
- };
- function fQueue_process() {
- if (aQueueRunning.length < 6) {
- for (var sPriority in oQueuePending) {
- if (oQueuePending[sPriority].length) {
- var oRequest = oQueuePending[sPriority][0];
- oQueuePending[sPriority] = oQueuePending[sPriority].slice(1);
- //
- aQueueRunning.push(oRequest);
- // Send request
- fXMLHttpRequest_send(oRequest);
- break;
- }
- }
- }
- };
- */
- // Internet Explorer 5.0 (missing apply)
- if (!window.Function.prototype.apply) {
- window.Function.prototype.apply = function(oRequest, oArguments) {
- if (!oArguments)
- oArguments = [];
- oRequest.__func = this;
- oRequest.__func(oArguments[0], oArguments[1], oArguments[2], oArguments[3], oArguments[4]);
- delete oRequest.__func;
- };
- };
- // Register new object with window
- /**
- * Class: OpenLayers.Request.XMLHttpRequest
- * Standard-compliant (W3C) cross-browser implementation of the
- * XMLHttpRequest object. From
- * http://code.google.com/p/xmlhttprequest/.
- */
- OpenLayers.Request.XMLHttpRequest = cXMLHttpRequest;
- })();
|