[OpenLayers-Commits] r7335 - in trunk/openlayers: build lib lib/OpenLayers lib/OpenLayers/Format lib/OpenLayers/Layer lib/OpenLayers/Request lib/OpenLayers/Tile tests tests/Request tests/Tile tests/manual
commits at openlayers.org
commits at openlayers.org
Mon Jun 9 15:51:38 EDT 2008
Author: tschaub
Date: 2008-06-09 15:51:38 -0400 (Mon, 09 Jun 2008)
New Revision: 7335
Added:
trunk/openlayers/lib/OpenLayers/Request.js
trunk/openlayers/lib/OpenLayers/Request/
trunk/openlayers/lib/OpenLayers/Request/XMLHttpRequest.js
trunk/openlayers/tests/Request.html
trunk/openlayers/tests/Request/
trunk/openlayers/tests/Request/XMLHttpRequest.html
Modified:
trunk/openlayers/build/license.txt
trunk/openlayers/lib/OpenLayers.js
trunk/openlayers/lib/OpenLayers/Ajax.js
trunk/openlayers/lib/OpenLayers/Format/KML.js
trunk/openlayers/lib/OpenLayers/Layer/GML.js
trunk/openlayers/lib/OpenLayers/Layer/GeoRSS.js
trunk/openlayers/lib/OpenLayers/Layer/MapGuide.js
trunk/openlayers/lib/OpenLayers/Layer/Text.js
trunk/openlayers/lib/OpenLayers/Layer/WFS.js
trunk/openlayers/lib/OpenLayers/Tile/WFS.js
trunk/openlayers/tests/Ajax.html
trunk/openlayers/tests/Tile/WFS.html
trunk/openlayers/tests/list-tests.html
trunk/openlayers/tests/manual/ajax.html
Log:
Adding cross-browser XMLHttpRequest functionality and convenience methods around it in the OpenLayers.Request namespace. Deprecating OpenLayers.Ajax.Request. Full support sync/async requests using all HTTP verbs now. r=elemoine (closes #1565)
Modified: trunk/openlayers/build/license.txt
===================================================================
--- trunk/openlayers/build/license.txt 2008-06-09 19:11:03 UTC (rev 7334)
+++ trunk/openlayers/build/license.txt 2008-06-09 19:51:38 UTC (rev 7335)
@@ -43,3 +43,12 @@
*
**/
+/**
+ * Contains XMLHttpRequest.js <http://code.google.com/p/xmlhttprequest/>
+ * Copyright 2007 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
+ */
Modified: trunk/openlayers/lib/OpenLayers/Ajax.js
===================================================================
--- trunk/openlayers/lib/OpenLayers/Ajax.js 2008-06-09 19:11:03 UTC (rev 7334)
+++ trunk/openlayers/lib/OpenLayers/Ajax.js 2008-06-09 19:51:38 UTC (rev 7335)
@@ -30,16 +30,18 @@
*/
-/**
-* @param {} request
-*/
+/**
+ * Function: OpenLayers.nullHandler
+ * @param {} request
+ */
OpenLayers.nullHandler = function(request) {
alert(OpenLayers.i18n("unhandledRequest", {'statusText':request.statusText}));
};
/**
* Function: loadURL
- * Background load a document.
+ * Background load a document. For more flexibility in using XMLHttpRequest,
+ * see the <OpenLayers.Request> methods.
*
* Parameters:
* uri - {String} URI of source doc
@@ -49,35 +51,32 @@
* caller - {Object} object which gets callbacks
* onComplete - {Function} Optional callback for success. The callback
* will be called with this set to caller and will receive the request
- * object as an argument.
+ * object as an argument. Note that if you do not specify an onComplete
+ * function, <OpenLayers.nullHandler> will be called (which pops up an
+ * alert dialog).
* onFailure - {Function} Optional callback for failure. In the event of
* a failure, the callback will be called with this set to caller and will
- * receive the request object as an argument.
+ * receive the request object as an argument. Note that if you do not
+ * specify an onComplete function, <OpenLayers.nullHandler> will be called
+ * (which pops up an alert dialog).
*
* Returns:
- * {XMLHttpRequest} The request object. To abort loading, call
- * request.abort().
+ * {<OpenLayers.Request.XMLHttpRequest>} The request object. To abort loading,
+ * call request.abort().
*/
OpenLayers.loadURL = function(uri, params, caller,
onComplete, onFailure) {
-
- var success = (onComplete) ? OpenLayers.Function.bind(onComplete, caller)
- : OpenLayers.nullHandler;
-
- var failure = (onFailure) ? OpenLayers.Function.bind(onFailure, caller)
- : OpenLayers.nullHandler;
-
- // from prototype.js
- var request = new OpenLayers.Ajax.Request(
- uri,
- {
- method: 'get',
- parameters: params,
- onComplete: success,
- onFailure: failure
- }
- );
- return request.transport;
+
+ if(typeof params == 'string') {
+ params = OpenLayers.Util.getParameters(params);
+ }
+ var success = (onComplete) ? onComplete : OpenLayers.nullHandler;
+ var failure = (onFailure) ? onFailure : OpenLayers.nullHandler;
+
+ return OpenLayers.Request.GET({
+ url: uri, params: params,
+ success: success, failure: failure, scope: caller
+ });
};
/**
@@ -263,6 +262,7 @@
/**
* Class: OpenLayers.Ajax.Request
+ * *Deprecated*. Use <OpenLayers.Request> method instead.
*
* Inherit:
* - <OpenLayers.Ajax.Base>
Modified: trunk/openlayers/lib/OpenLayers/Format/KML.js
===================================================================
--- trunk/openlayers/lib/OpenLayers/Format/KML.js 2008-06-09 19:11:03 UTC (rev 7334)
+++ trunk/openlayers/lib/OpenLayers/Format/KML.js 2008-06-09 19:51:38 UTC (rev 7335)
@@ -249,11 +249,9 @@
*
*/
fetchLink: function(href) {
- var request = new OpenLayers.Ajax.Request(href,
- {method: 'get', asynchronous: false });
-
- if (request && request.transport) {
- return request.transport.responseText;
+ var request = OpenLayers.Request.GET({url: href, async: false});
+ if (request) {
+ return request.responseText;
}
},
Modified: trunk/openlayers/lib/OpenLayers/Layer/GML.js
===================================================================
--- trunk/openlayers/lib/OpenLayers/Layer/GML.js 2008-06-09 19:11:03 UTC (rev 7334)
+++ trunk/openlayers/lib/OpenLayers/Layer/GML.js 2008-06-09 19:51:38 UTC (rev 7335)
@@ -100,7 +100,12 @@
*/
loadGML: function() {
if (!this.loaded) {
- var results = OpenLayers.loadURL(this.url, null, this, this.requestSuccess, this.requestFailure);
+ OpenLayers.Request.GET({
+ url: this.url,
+ success: this.requestSuccess,
+ failure: this.requestFailure,
+ scope: this
+ });
this.loaded = true;
}
},
Modified: trunk/openlayers/lib/OpenLayers/Layer/GeoRSS.js
===================================================================
--- trunk/openlayers/lib/OpenLayers/Layer/GeoRSS.js 2008-06-09 19:11:03 UTC (rev 7334)
+++ trunk/openlayers/lib/OpenLayers/Layer/GeoRSS.js 2008-06-09 19:51:38 UTC (rev 7335)
@@ -100,7 +100,11 @@
loadRSS: function() {
if (!this.loaded) {
this.events.triggerEvent("loadstart");
- OpenLayers.loadURL(this.location, null, this, this.parseData);
+ OpenLayers.Request.GET({
+ url: this.location,
+ success: this.parseData,
+ scope: this
+ });
this.loaded = true;
}
},
@@ -127,7 +131,7 @@
* Parse the data returned from the Events call.
*
* Parameters:
- * ajaxRequest - {XMLHttpRequest}
+ * ajaxRequest - {<OpenLayers.Request.XMLHttpRequest>}
*/
parseData: function(ajaxRequest) {
var doc = ajaxRequest.responseXML;
Modified: trunk/openlayers/lib/OpenLayers/Layer/MapGuide.js
===================================================================
--- trunk/openlayers/lib/OpenLayers/Layer/MapGuide.js 2008-06-09 19:11:03 UTC (rev 7334)
+++ trunk/openlayers/lib/OpenLayers/Layer/MapGuide.js 2008-06-09 19:51:38 UTC (rev 7335)
@@ -202,12 +202,10 @@
getVisParams.mapName = this.params.mapName;
getVisParams.format = 'text/xml';
getVisParams = OpenLayers.Util.extend(getVisParams, params);
-
- new OpenLayers.Ajax.Request(this.url,
- { parameters: getVisParams,
- method: 'get',
- asynchronous: false //must be synchronous call to return control here
- });
+
+ OpenLayers.Request.GET({
+ url: this.url, params: getVisParams, async: false
+ });
}
//construct the full URL
Modified: trunk/openlayers/lib/OpenLayers/Layer/Text.js
===================================================================
--- trunk/openlayers/lib/OpenLayers/Layer/Text.js 2008-06-09 19:11:03 UTC (rev 7334)
+++ trunk/openlayers/lib/OpenLayers/Layer/Text.js 2008-06-09 19:51:38 UTC (rev 7335)
@@ -109,8 +109,12 @@
};
this.events.triggerEvent("loadstart");
- OpenLayers.loadURL(this.location, null,
- this, this.parseData, onFail);
+ OpenLayers.Request.GET({
+ url: this.location,
+ success: this.parseData,
+ failure: onFail,
+ scope: this
+ });
this.loaded = true;
}
}
@@ -137,7 +141,7 @@
* Method: parseData
*
* Parameters:
- * ajaxRequest - {XMLHttpRequest}
+ * ajaxRequest - {<OpenLayers.Request.XMLHttpRequest>}
*/
parseData: function(ajaxRequest) {
var text = ajaxRequest.responseText;
Modified: trunk/openlayers/lib/OpenLayers/Layer/WFS.js
===================================================================
--- trunk/openlayers/lib/OpenLayers/Layer/WFS.js 2008-06-09 19:11:03 UTC (rev 7334)
+++ trunk/openlayers/lib/OpenLayers/Layer/WFS.js 2008-06-09 19:51:38 UTC (rev 7335)
@@ -455,21 +455,14 @@
}
var data = this.writer.write(this.features);
-
- var url = this.url;
- var success = OpenLayers.Function.bind(this.commitSuccess, this);
-
- var failure = OpenLayers.Function.bind(this.commitFailure, this);
-
- // from prototype.js
- new OpenLayers.Ajax.Request(url,
- { method: 'post',
- postBody: data,
- onComplete: success,
- onFailure: failure
- }
- );
+ OpenLayers.Request.POST({
+ url: this.url,
+ data: data,
+ success: this.commitSuccess,
+ failure: this.commitFailure,
+ scope: this
+ });
},
/**
Added: trunk/openlayers/lib/OpenLayers/Request/XMLHttpRequest.js
===================================================================
--- trunk/openlayers/lib/OpenLayers/Request/XMLHttpRequest.js (rev 0)
+++ trunk/openlayers/lib/OpenLayers/Request/XMLHttpRequest.js 2008-06-09 19:51:38 UTC (rev 7335)
@@ -0,0 +1,313 @@
+// Copyright 2007 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;
+
+ // Constructor
+ function cXMLHttpRequest() {
+ this._object = oXMLHttpRequest ? new oXMLHttpRequest : new window.ActiveXObject('Microsoft.XMLHTTP');
+ };
+
+ // 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 = "";
+
+ // 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) {
+
+ // 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;
+
+ // BUGFIX: IE - memory leak on page unload (inter-page leak)
+ if (bIE) {
+ var fOnUnload = function() {
+ if (oRequest._object.readyState != cXMLHttpRequest.DONE)
+ fCleanTransport(oRequest);
+ };
+ if (bAsync)
+ window.attachEvent("onunload", fOnUnload);
+ }
+
+ this._object.onreadystatechange = function() {
+ if (bGecko && !bAsync)
+ return;
+
+ // Synchronize state
+ oRequest.readyState = oRequest._object.readyState;
+
+ //
+ fSynchronizeValues(oRequest);
+
+ // BUGFIX: Firefox fires unneccesary DONE when aborting
+ if (oRequest._aborted) {
+ // Reset readyState to UNSENT
+ oRequest.readyState = cXMLHttpRequest.UNSENT;
+
+ // Return now
+ return;
+ }
+
+ if (oRequest.readyState == cXMLHttpRequest.DONE) {
+ //
+ 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
+ oRequest._object.open(sMethod, sUrl, bAsync, sUser, sPassword);
+ 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 untill 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;
+ };
+
+ // Add method sniffer
+ if (cXMLHttpRequest.onopen)
+ cXMLHttpRequest.onopen.apply(this, arguments);
+
+ this._object.open(sMethod, sUrl, bAsync, sUser, sPassword);
+
+ // BUGFIX: Gecko - missing readystatechange calls in synchronous requests
+ if (!bAsync && bGecko) {
+ this.readyState = cXMLHttpRequest.OPENED;
+
+ fReadyStateChange(this);
+ }
+ };
+ cXMLHttpRequest.prototype.send = function(vData) {
+ // Add method sniffer
+ if (cXMLHttpRequest.onsend)
+ cXMLHttpRequest.onsend.apply(this, arguments);
+
+ // 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 (!this._headers["Content-Type"])
+ this._object.setRequestHeader("Content-Type", "application/xml");
+ }
+
+ this._object.send(vData);
+
+ // BUGFIX: Gecko - missing readystatechange calls in synchronous requests
+ if (bGecko && !this._async) {
+ this.readyState = cXMLHttpRequest.OPENED;
+
+ // Synchronize state
+ fSynchronizeValues(this);
+
+ // Simulate missing states
+ while (this.readyState < cXMLHttpRequest.DONE) {
+ this.readyState++;
+ fReadyStateChange(this);
+ // Check if we are aborted
+ if (this._aborted)
+ return;
+ }
+ }
+ };
+ cXMLHttpRequest.prototype.abort = function() {
+ // Add method sniffer
+ if (cXMLHttpRequest.onabort)
+ cXMLHttpRequest.onabort.apply(this, arguments);
+
+ // BUGFIX: Gecko - unneccesary DONE when aborting
+ if (this.readyState > cXMLHttpRequest.UNSENT)
+ this._aborted = true;
+
+ this._object.abort();
+
+ // BUGFIX: IE - memory leak
+ fCleanTransport(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);
+ };
+ cXMLHttpRequest.prototype.toString = function() {
+ return '[' + "object" + ' ' + "XMLHttpRequest" + ']';
+ };
+ cXMLHttpRequest.toString = function() {
+ return '[' + "XMLHttpRequest" + ']';
+ };
+
+ // Helper function
+ function fReadyStateChange(oRequest) {
+ // Execute onreadystatechange
+ if (oRequest.onreadystatechange)
+ oRequest.onreadystatechange.apply(oRequest);
+
+ // Sniffing code
+ if (cXMLHttpRequest.onreadystatechange)
+ cXMLHttpRequest.onreadystatechange.apply(oRequest);
+ };
+
+ function fGetDocument(oRequest) {
+ var oDocument = oRequest.responseXML;
+ // Try parsing responseText
+ if (bIE && oDocument && !oDocument.documentElement && oRequest.getResponseHeader("Content-Type").match(/[^\/]+\/[^\+]+\+xml/)) {
+ oDocument = new ActiveXObject('Microsoft.XMLDOM');
+ oDocument.loadXML(oRequest.responseText);
+ }
+ // Check if there is no error in document
+ if (oDocument)
+ if ((bIE && oDocument.parseError != 0) || (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;
+
+ // Delete private properties
+ delete oRequest._headers;
+ };
+
+ // 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;
+})();
\ No newline at end of file
Added: trunk/openlayers/lib/OpenLayers/Request.js
===================================================================
--- trunk/openlayers/lib/OpenLayers/Request.js (rev 0)
+++ trunk/openlayers/lib/OpenLayers/Request.js 2008-06-09 19:51:38 UTC (rev 7335)
@@ -0,0 +1,266 @@
+/* Copyright (c) 2006-2008 MetaCarta, Inc., published under the Clear BSD
+ * license. See http://svn.openlayers.org/trunk/openlayers/license.txt for the
+ * full text of the license. */
+
+/**
+ * Namespace: OpenLayers.Request
+ * The OpenLayers.Request namespace contains convenience methods for working
+ * with XMLHttpRequests. These methods work with a cross-browser
+ * W3C compliant <OpenLayers.Request.XMLHttpRequest> class.
+ */
+OpenLayers.Request = {
+
+ /**
+ * Constant: DEFAULT_CONFIG
+ * {Object} Default configuration for all requests.
+ */
+ DEFAULT_CONFIG: {
+ method: "GET",
+ url: window.location.href,
+ async: true,
+ user: undefined,
+ password: undefined,
+ params: null,
+ proxy: OpenLayers.ProxyHost,
+ headers: {},
+ data: null,
+ callback: function() {},
+ success: null,
+ failure: null,
+ scope: null
+ },
+
+ /**
+ * APIMethod: issue
+ * Create a new XMLHttpRequest object, open it, set any headers, bind
+ * a callback to done state, and send any data.
+ *
+ * Parameters:
+ * config - {Object} Object containing properties for configuring the
+ * request. Allowed configuration properties are described below.
+ * This object is modified and should not be reused.
+ *
+ * Allowed config properties:
+ * method - {String} One of GET, POST, PUT, DELETE, HEAD, or
+ * OPTIONS. Default is GET.
+ * url - {String} URL for the request.
+ * async - {Boolean} Open an asynchronous request. Default is true.
+ * user - {String} User for relevant authentication scheme. Set
+ * to null to clear current user.
+ * password - {String} Password for relevant authentication scheme.
+ * Set to null to clear current password.
+ * proxy - {String} Optional proxy. Defaults to
+ * <OpenLayers.ProxyHost>.
+ * params - {Object} Any key:value pairs to be appended to the
+ * url as a query string. Assumes url doesn't already include a query
+ * string or hash. Parameter values that are arrays will be
+ * concatenated with a comma (note that this goes against form-encoding)
+ * as is done with <OpenLayers.Util.getParameterString>.
+ * headers - {Object} Object with header:value pairs to be set on
+ * the request.
+ * data - {Object} Any data to send with the request.
+ * callback - {Function} Function to call when request is done.
+ * To determine if the request failed, check request.status (200
+ * indicates success).
+ * success - {Function} Optional function to call if request status is in
+ * the 200s. This will be called in addition to callback above and
+ * would typically only be used as an alternative.
+ * failure - {Function} Optional function to call if request status is not
+ * in the 200s. This will be called in addition to callback above and
+ * would typically only be used as an alternative.
+ * scope - {Object} If callback is a public method on some object,
+ * set the scope to that object.
+ *
+ * Returns:
+ * {XMLHttpRequest} Request object. To abort the request before a response
+ * is received, call abort() on the request object.
+ */
+ issue: function(config) {
+ // apply default config - proxy host may have changed
+ var defaultConfig = OpenLayers.Util.extend(
+ this.DEFAULT_CONFIG,
+ {proxy: OpenLayers.ProxyHost}
+ );
+ config = OpenLayers.Util.applyDefaults(config, defaultConfig);
+
+ // create request, open, and set headers
+ var request = new OpenLayers.Request.XMLHttpRequest();
+ var url = config.url;
+ if(config.params) {
+ url += "?" + OpenLayers.Util.getParameterString(config.params);
+ }
+ if(config.proxy && (url.indexOf("http") == 0)) {
+ url = config.proxy + encodeURIComponent(url);
+ }
+ request.open(
+ config.method, url, config.async, config.user, config.password
+ );
+ for(var header in config.headers) {
+ request.setRequestHeader(header, config.headers[header]);
+ }
+
+ // bind callbacks to readyState 4 (done)
+ var complete = (config.scope) ?
+ OpenLayers.Function.bind(config.callback, config.scope) :
+ config.callback;
+
+ // optional success callback
+ var success;
+ if(config.success) {
+ success = (config.scope) ?
+ OpenLayers.Function.bind(config.success, config.scope) :
+ config.success;
+ }
+
+ // optional failure callback
+ var failure;
+ if(config.failure) {
+ failure = (config.scope) ?
+ OpenLayers.Function.bind(config.failure, config.scope) :
+ config.failure;
+ }
+
+ request.onreadystatechange = function() {
+ if(request.readyState == OpenLayers.Request.XMLHttpRequest.DONE) {
+ complete(request);
+ if(success && request.status >= 200 && request.status < 300) {
+ success(request);
+ }
+ if(failure && (request.status < 200 || request.status >= 300)) {
+ failure(request);
+ }
+ }
+ }
+
+ // send request (optionally with data) and return
+ request.send(config.data);
+ return request;
+ },
+
+ /**
+ * APIMethod: GET
+ * Send an HTTP GET request. Additional configuration properties are
+ * documented in the <issue> method, with the method property set
+ * to GET.
+ *
+ * Parameters:
+ * config - {Object} Object with properties for configuring the request.
+ * See the <issue> method for documentation of allowed properties.
+ * This object is modified and should not be reused.
+ *
+ * Returns:
+ * {XMLHttpRequest} Request object.
+ */
+ GET: function(config) {
+ config = OpenLayers.Util.extend(config, {method: "GET"});
+ return OpenLayers.Request.issue(config);
+ },
+
+ /**
+ * APIMethod: POST
+ * Send a POST request. Additional configuration properties are
+ * documented in the <issue> method, with the method property set
+ * to POST and "Content-Type" header set to "application/xml".
+ *
+ * Parameters:
+ * config - {Object} Object with properties for configuring the request.
+ * See the <issue> method for documentation of allowed properties. The
+ * default "Content-Type" header will be set to "application-xml" if
+ * none is provided. This object is modified and should not be reused.
+ *
+ * Returns:
+ * {XMLHttpRequest} Request object.
+ */
+ POST: function(config) {
+ config = OpenLayers.Util.extend(config, {method: "POST"});
+ // set content type to application/xml if it isn't already set
+ config.headers = config.headers ? config.headers : {};
+ if(!("CONTENT-TYPE" in OpenLayers.Util.upperCaseObject(config.headers))) {
+ config.headers["Content-Type"] = "application/xml";
+ }
+ return OpenLayers.Request.issue(config);
+ },
+
+ /**
+ * APIMethod: PUT
+ * Send an HTTP PUT request. Additional configuration properties are
+ * documented in the <issue> method, with the method property set
+ * to PUT and "Content-Type" header set to "application/xml".
+ *
+ * Parameters:
+ * config - {Object} Object with properties for configuring the request.
+ * See the <issue> method for documentation of allowed properties. The
+ * default "Content-Type" header will be set to "application-xml" if
+ * none is provided. This object is modified and should not be reused.
+ *
+ * Returns:
+ * {XMLHttpRequest} Request object.
+ */
+ PUT: function(config) {
+ config = OpenLayers.Util.extend(config, {method: "PUT"});
+ // set content type to application/xml if it isn't already set
+ config.headers = config.headers ? config.headers : {};
+ if(!("CONTENT-TYPE" in OpenLayers.Util.upperCaseObject(config.headers))) {
+ config.headers["Content-Type"] = "application/xml";
+ }
+ return OpenLayers.Request.issue(config);
+ },
+
+ /**
+ * APIMethod: DELETE
+ * Send an HTTP DELETE request. Additional configuration properties are
+ * documented in the <issue> method, with the method property set
+ * to DELETE.
+ *
+ * Parameters:
+ * config - {Object} Object with properties for configuring the request.
+ * See the <issue> method for documentation of allowed properties.
+ * This object is modified and should not be reused.
+ *
+ * Returns:
+ * {XMLHttpRequest} Request object.
+ */
+ DELETE: function(config) {
+ config = OpenLayers.Util.extend(config, {method: "DELETE"});
+ return OpenLayers.Request.issue(config);
+ },
+
+ /**
+ * APIMethod: HEAD
+ * Send an HTTP HEAD request. Additional configuration properties are
+ * documented in the <issue> method, with the method property set
+ * to HEAD.
+ *
+ * Parameters:
+ * config - {Object} Object with properties for configuring the request.
+ * See the <issue> method for documentation of allowed properties.
+ * This object is modified and should not be reused.
+ *
+ * Returns:
+ * {XMLHttpRequest} Request object.
+ */
+ HEAD: function(config) {
+ config = OpenLayers.Util.extend(config, {method: "HEAD"});
+ return OpenLayers.Request.issue(config);
+ },
+
+ /**
+ * APIMethod: OPTIONS
+ * Send an HTTP OPTIONS request. Additional configuration properties are
+ * documented in the <issue> method, with the method property set
+ * to OPTIONS.
+ *
+ * Parameters:
+ * config - {Object} Object with properties for configuring the request.
+ * See the <issue> method for documentation of allowed properties.
+ * This object is modified and should not be reused.
+ *
+ * Returns:
+ * {XMLHttpRequest} Request object.
+ */
+ OPTIONS: function(config) {
+ config = OpenLayers.Util.extend(config, {method: "OPTIONS"});
+ return OpenLayers.Request.issue(config);
+ }
+
+};
\ No newline at end of file
Modified: trunk/openlayers/lib/OpenLayers/Tile/WFS.js
===================================================================
--- trunk/openlayers/lib/OpenLayers/Tile/WFS.js 2008-06-09 19:11:03 UTC (rev 7334)
+++ trunk/openlayers/lib/OpenLayers/Tile/WFS.js 2008-06-09 19:51:38 UTC (rev 7335)
@@ -32,7 +32,7 @@
/**
* Property: request
- * {OpenLayers.Ajax.Request}
+ * {<OpenLayers.Request.XMLHttpRequest>}
*/
request: null,
@@ -100,8 +100,7 @@
/**
* Method: loadFeaturesForRegion
- * get the full request string from the ds and the tile params
- * and call the AJAX loadURL().
+ * Abort any pending requests and issue another request for data.
*
* Input are function pointers for what to do on success and failure.
*
@@ -113,7 +112,12 @@
if(this.request) {
this.request.abort();
}
- this.request = OpenLayers.loadURL(this.url, null, this, success);
+ this.request = OpenLayers.Request.GET({
+ url: this.url,
+ success: success,
+ failure: failure,
+ scope: this
+ });
},
/**
@@ -122,7 +126,7 @@
* layer.addFeatures in vector mode, addResults otherwise.
*
* Parameters:
- * request - {XMLHttpRequest}
+ * request - {<OpenLayers.Request.XMLHttpRequest>}
*/
requestSuccess:function(request) {
if (this.features) {
Modified: trunk/openlayers/lib/OpenLayers.js
===================================================================
--- trunk/openlayers/lib/OpenLayers.js 2008-06-09 19:11:03 UTC (rev 7334)
+++ trunk/openlayers/lib/OpenLayers.js 2008-06-09 19:51:38 UTC (rev 7335)
@@ -84,6 +84,8 @@
"Rico/Corner.js",
"Rico/Color.js",
"OpenLayers/Ajax.js",
+ "OpenLayers/Request.js",
+ "OpenLayers/Request/XMLHttpRequest.js",
"OpenLayers/Events.js",
"OpenLayers/Projection.js",
"OpenLayers/Map.js",
Modified: trunk/openlayers/tests/Ajax.html
===================================================================
--- trunk/openlayers/tests/Ajax.html 2008-06-09 19:11:03 UTC (rev 7334)
+++ trunk/openlayers/tests/Ajax.html 2008-06-09 19:51:38 UTC (rev 7335)
@@ -4,13 +4,21 @@
<script type="text/javascript">
function test_Ajax_loadUrl(t) {
- t.plan(1);
- var req = OpenLayers.Ajax.Request;
- OpenLayers.ProxyHost = "/?url=";
- OpenLayers.Ajax.Request.prototype.request = function(uri) {
- t.eq(uri, "/?url=http%3A%2F%2Fexample.com%2F%3Fformat%3Dimage%2Bkml", "URI matches what we expect from loadurl");
- }
- OpenLayers.loadURL("http://example.com/?format=image+kml");
+ t.plan(5);
+ var _get = OpenLayers.Request.GET;
+ var caller = {};
+ var onComplete = function() {};
+ var onFailure = function() {};
+ var params = {};
+ OpenLayers.Request.GET = function(config) {
+ t.eq(config.url, "http://example.com/?format=image+kml", "correct url")
+ t.eq(config.params, params, "correct params");
+ t.eq(config.scope, caller, "correct scope");
+ t.ok(config.success === onComplete, "correct success callback");
+ t.ok(config.failure === onFailure, "correct failure callback");
+ };
+ OpenLayers.loadURL("http://example.com/?format=image+kml", params, caller, onComplete, onFailure);
+ OpenLayers.Request.GET = _get;
}
</script>
</head>
Added: trunk/openlayers/tests/Request/XMLHttpRequest.html
===================================================================
--- trunk/openlayers/tests/Request/XMLHttpRequest.html (rev 0)
+++ trunk/openlayers/tests/Request/XMLHttpRequest.html 2008-06-09 19:51:38 UTC (rev 7335)
@@ -0,0 +1,14 @@
+<html>
+<head>
+ <script src="../../lib/OpenLayers.js"></script>
+ <script type="text/javascript">
+ function test_constructor(t) {
+ t.plan(1);
+ t.ok(new OpenLayers.Request.XMLHttpRequest(),
+ "constructor didn't fail and we trust the code is well tested in OpenLayers.Request methods");
+ }
+ </script>
+</head>
+<body>
+</body>
+</html>
Added: trunk/openlayers/tests/Request.html
===================================================================
--- trunk/openlayers/tests/Request.html (rev 0)
+++ trunk/openlayers/tests/Request.html 2008-06-09 19:51:38 UTC (rev 7335)
@@ -0,0 +1,205 @@
+<html>
+<head>
+ <script src="../lib/OpenLayers.js"></script>
+ <script type="text/javascript">
+ function setup() {
+ window._xhr = OpenLayers.Request.XMLHttpRequest;
+ var anon = new Function();
+ OpenLayers.Request.XMLHttpRequest = function() {};
+ OpenLayers.Request.XMLHttpRequest.prototype = {
+ open: anon,
+ setRequestHeader: anon,
+ send: anon
+ };
+ OpenLayers.Request.XMLHttpRequest.DONE = 4;
+ }
+ function teardown() {
+ OpenLayers.Request.XMLHttpRequest = window._xhr;
+ delete window._xhr;
+ }
+
+ function test_issue(t) {
+ setup();
+
+ t.plan(18);
+ var request, config;
+ var proto = OpenLayers.Request.XMLHttpRequest.prototype;
+ var issue = OpenLayers.Function.bind(OpenLayers.Request.issue,
+ OpenLayers.Request);
+
+ // test that issue returns a new XMLHttpRequest - 1 test
+ request = issue();
+ t.ok(request instanceof OpenLayers.Request.XMLHttpRequest,
+ "returns an XMLHttpRequest instance");
+
+ // test that issue calls xhr.open with correct args from config - 5 tests
+ var _open = proto.open;
+ config = {
+ method: "foo",
+ url: "http://nowhere",
+ async: "bar",
+ user: "uncle",
+ password: "sam"
+ };
+ proto.open = function(method, url, async, user, password) {
+ t.eq(method, config.method, "open called with correct method");
+ t.eq(url, config.url, "open called with correct url");
+ t.eq(async, config.async, "open called with correct async");
+ t.eq(user, config.user, "open called with correct user");
+ t.eq(password, config.password, "open called with correct password");
+ }
+ request = issue(config);
+ proto.open = _open;
+
+ // test that headers are correctly set - 4 tests
+ var _setRequestHeader = proto.setRequestHeader;
+ config = {
+ headers: {
+ foo: "bar",
+ chicken: "soup"
+ }
+ };
+ proto.setRequestHeader = function(key, value) {
+ t.ok(key in config.headers, "setRequestHeader called with key: " + key);
+ t.eq(value, config.headers[key], "setRequestHeader called with correct value: " + value);
+ }
+ request = issue(config);
+ proto.setRequestHeader = _setRequestHeader;
+
+ // test that callback is called (no scope) - 1 test
+ var unbound = function(request) {
+ t.ok(request instanceof OpenLayers.Request.XMLHttpRequest,
+ "unbound callback called with xhr instance");
+ }
+ config = {
+ callback: unbound
+ };
+ request = issue(config);
+ request.readyState = OpenLayers.Request.XMLHttpRequest.DONE;
+ request.onreadystatechange();
+
+ // test that callback is called (with scope) - 2 tests
+ var obj = {};
+ var bound = function(request) {
+ t.ok(this === obj, "bound callback has correct scope");
+ t.ok(request instanceof OpenLayers.Request.XMLHttpRequest,
+ "bound callback called with xhr instance");
+ }
+ config = {
+ callback: bound,
+ scope: obj
+ };
+ request = issue(config);
+ request.readyState = 4;
+ request.onreadystatechange();
+
+ // test that send is called with data - 1 test
+ var _send = proto.send;
+ config = {
+ method: "PUT",
+ data: "bling"
+ };
+ proto.send = function(data) {
+ t.eq(data, config.data, "send called with correct data");
+ }
+ request = issue(config);
+ proto.send = _send;
+
+ // test that optional success callback is only called with 200s and
+ // failure is only called with non-200s
+ var _send = proto.send;
+ proto.send = function() {};
+
+ config = {
+ success: function(req) {
+ t.ok(req.status >= 200 && req.status < 300,
+ "success callback called with " + req.status + " status");
+ },
+ failure: function(req) {
+ t.ok(req.status < 200 || req.status >= 300,
+ "failure callback called with " + req.status + " status");
+ }
+ };
+ request = issue(config);
+ request.readyState = 4;
+
+ // mock up status 200 (1 test)
+ request.status = 200;
+ request.onreadystatechange();
+
+ // mock up status 299 (1 test)
+ request.status = 299;
+ request.onreadystatechange();
+
+ // mock up status 100 (1 test)
+ request.status = 100;
+ request.onreadystatechange();
+
+ // mock up status 300 (1 test)
+ request.status = 300;
+ request.onreadystatechange();
+
+ proto.send = _send;
+
+ teardown();
+ }
+
+ function test_GET(t) {
+ t.plan(1);
+ var _issue = OpenLayers.Request.issue;
+ OpenLayers.Request.issue = function(config) {
+ t.eq(config.method, "GET", "calls issue with correct method");
+ }
+ OpenLayers.Request.GET();
+ OpenLayers.Request.issue = _issue;
+ }
+ function test_POST(t) {
+ t.plan(1);
+ var _issue = OpenLayers.Request.issue;
+ OpenLayers.Request.issue = function(config) {
+ t.eq(config.method, "POST", "calls issue with correct method");
+ }
+ OpenLayers.Request.POST();
+ OpenLayers.Request.issue = _issue;
+ }
+ function test_PUT(t) {
+ t.plan(1);
+ var _issue = OpenLayers.Request.issue;
+ OpenLayers.Request.issue = function(config) {
+ t.eq(config.method, "PUT", "calls issue with correct method");
+ }
+ OpenLayers.Request.PUT();
+ OpenLayers.Request.issue = _issue;
+ }
+ function test_DELETE(t) {
+ t.plan(1);
+ var _issue = OpenLayers.Request.issue;
+ OpenLayers.Request.issue = function(config) {
+ t.eq(config.method, "DELETE", "calls issue with correct method");
+ }
+ OpenLayers.Request.DELETE();
+ OpenLayers.Request.issue = _issue;
+ }
+ function test_HEAD(t) {
+ t.plan(1);
+ var _issue = OpenLayers.Request.issue;
+ OpenLayers.Request.issue = function(config) {
+ t.eq(config.method, "HEAD", "calls issue with correct method");
+ }
+ OpenLayers.Request.HEAD();
+ OpenLayers.Request.issue = _issue;
+ }
+ function test_OPTIONS(t) {
+ t.plan(1);
+ var _issue = OpenLayers.Request.issue;
+ OpenLayers.Request.issue = function(config) {
+ t.eq(config.method, "OPTIONS", "calls issue with correct method");
+ }
+ OpenLayers.Request.OPTIONS();
+ OpenLayers.Request.issue = _issue;
+ }
+ </script>
+</head>
+<body>
+</body>
+</html>
Modified: trunk/openlayers/tests/Tile/WFS.html
===================================================================
--- trunk/openlayers/tests/Tile/WFS.html 2008-06-09 19:11:03 UTC (rev 7334)
+++ trunk/openlayers/tests/Tile/WFS.html 2008-06-09 19:51:38 UTC (rev 7335)
@@ -64,12 +64,12 @@
var g_Success = {};
- var tLoadURL = OpenLayers.loadURL;
- OpenLayers.loadURL = function(url, params, caller, onComplete) {
- t.ok(url == tile.url, "tile's url correctly passed as 1st param to loadURL");
- t.ok(params == null, "null passed as 2nd param to loadURL");
- t.ok(caller == tile, "tile passed as 3rd param to loadURL");
- t.ok(onComplete == g_Success, "success param from loadFeaturesForRegion() passed as 4th param to loadURL");
+ var _get = OpenLayers.Request.GET;
+ OpenLayers.Request.GET = function(config) {
+ t.ok(config.url == tile.url, "tile's url correctly passed");
+ t.ok(config.params == null, "null params");
+ t.ok(config.scope == tile, "tile passed as scope");
+ t.ok(config.success == g_Success, "success passed");
};
//no running request -- 4 tests
@@ -82,8 +82,8 @@
}
};
OpenLayers.Tile.WFS.prototype.loadFeaturesForRegion.apply(tile, [g_Success]);
-
- OpenLayers.loadURL = tLoadURL;
+
+ OpenLayers.Request.GET = _get;
}
function test_Tile_WFS_destroy(t) {
Modified: trunk/openlayers/tests/list-tests.html
===================================================================
--- trunk/openlayers/tests/list-tests.html 2008-06-09 19:11:03 UTC (rev 7334)
+++ trunk/openlayers/tests/list-tests.html 2008-06-09 19:51:38 UTC (rev 7335)
@@ -57,6 +57,8 @@
<li>Lang.html</li>
<li>Layer.html</li>
<li>Renderer.html</li>
+ <li>Request.html</li>
+ <li>Request/XMLHttpRequest.html</li>
<li>Layer/EventPane.html</li>
<li>Layer/FixedZoomLevels.html</li>
<li>Layer/GeoRSS.html</li>
Modified: trunk/openlayers/tests/manual/ajax.html
===================================================================
--- trunk/openlayers/tests/manual/ajax.html 2008-06-09 19:11:03 UTC (rev 7334)
+++ trunk/openlayers/tests/manual/ajax.html 2008-06-09 19:51:38 UTC (rev 7335)
@@ -1,70 +1,49 @@
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
- <title>Ajax Acceptance Test</title>
- <style type="text/css">
-
- body {
- font-size: 0.8em;
- }
- p {
- padding-top: 1em;
- }
-
- .buttons {
- margin: 1em;
- float: left;
- }
-
- </style>
-
+ <title>XHR Acceptance Test</title>
<script src="../../lib/OpenLayers.js"></script>
<script type="text/javascript">
var url = "ajax.txt";
function sendSynchronous(){
- var request = new OpenLayers.Ajax.Request(url, {
- 'asynchronous': false,
- onComplete: function() {
+ var request = OpenLayers.Request.GET({
+ url: url,
+ async: false,
+ callback: function() {
document.getElementById('send_sync').value += 'request completed\n';
}
});
document.getElementById('send_sync').value += 'other processing\n';
}
function sendAsynchronous(){
- var request = new OpenLayers.Ajax.Request(url, {
- onComplete: function() {
+ var request = OpenLayers.Request.GET({
+ url: url,
+ callback: function() {
document.getElementById('send_sync').value += 'request completed\n';
}
});
document.getElementById('send_sync').value += 'other processing\n';
}
function sendAndAbort(){
- var request = new OpenLayers.Ajax.Request(url, {
- onComplete: function(request) {
- if (request.responseText == '') {
- document.getElementById('send_sync').value += 'request aborted\n';
- }
+ var request = OpenLayers.Request.GET({
+ url: url,
+ callback: function() {
+ document.getElementById('send_sync').value += 'never called\n';
}
});
- request.transport.abort();
+ request.abort();
document.getElementById('send_sync').value += 'other processing\n';
}
- </script>
- </head>
- <body >
- <div class="buttons">
- <button onclick="sendSynchronous()">Send an synchronous Ajax request</button><br />
- <button onclick="sendAsynchronous()">Send an asynchronous Ajax request</button><br />
- <button onclick="sendAndAbort()">Send a request and abort it</button><br />
+ </script>
+ </head>
+ <body >
+ <button onclick="sendSynchronous()">synchronous</button>
+ expected output: "request completed" then "other processing"<br />
+ <button onclick="sendAsynchronous()">asynchronous</button>
+ expected output: "other processing" then "request completed"<br />
+ <button onclick="sendAndAbort()">send and abort</button>
+ expected output: "other processing" (and not "never called")<br />
<textarea id="send_sync" rows="6"></textarea><br />
<button onclick="document.getElementById('send_sync').value = ''">Clear</button>
- </div>
- <p><b></b></p>
- <p>Clicking on the different buttons should give the following results in the textarea below :</p>
- <ul>
- <li>synchronous: "request completed" then "other processing"</li>
- <li>asynchronous: "other processing" then "request completed"</li>
- <li>abort: "request aborted" then "other processing" (note that real XHR behavior would not call onComplete with abort - meaning "request aborted" would not be displayed here)</li>
- </ul>
</body>
</html>
More information about the Commits
mailing list