Serious rewrite in the Ajax namespace by pgiraud to keep up with prototype.js 1.6. Thanks for the effort and for suffering numerous revisions. Now, let's cross our fingers... r=crschmidt,me (closes #1170)

git-svn-id: http://svn.openlayers.org/trunk/openlayers@5535 dc9f47b5-9b13-0410-9fdd-eb0c1a62fdaf
This commit is contained in:
Tim Schaub
2007-12-20 09:26:53 +00:00
parent 44543b3e36
commit 3268e53ed1
3 changed files with 338 additions and 167 deletions
+250 -150
View File
@@ -135,9 +135,9 @@ OpenLayers.Ajax = {
*/ */
getTransport: function() { getTransport: function() {
return OpenLayers.Util.Try( return OpenLayers.Util.Try(
function() {return new XMLHttpRequest();},
function() {return new ActiveXObject('Msxml2.XMLHTTP');}, function() {return new ActiveXObject('Msxml2.XMLHTTP');},
function() {return new ActiveXObject('Microsoft.XMLHTTP');}, function() {return new ActiveXObject('Microsoft.XMLHTTP');}
function() {return new XMLHttpRequest();}
) || false; ) || false;
}, },
@@ -167,12 +167,22 @@ OpenLayers.Ajax.Responders = {
* responderToAdd - {?} * responderToAdd - {?}
*/ */
register: function(responderToAdd) { register: function(responderToAdd) {
for (var i = 0; i < this.responders.length; i++){ for (var i = 0; i < this.responders.length; i++){
if (responderToAdd == this.responders[i]){ if (responderToAdd == this.responders[i]){
return; return;
} }
} }
this.responders.push(responderToAdd); this.responders.push(responderToAdd);
},
/**
* Method: unregister
*
* Parameters:
* responderToRemove - {?}
*/
unregister: function(responderToRemove) {
OpenLayers.Util.removeItem(this.reponders, responderToRemove);
}, },
/** /**
@@ -182,9 +192,8 @@ OpenLayers.Ajax.Responders = {
* callback - {?} * callback - {?}
* request - {?} * request - {?}
* transport - {?} * transport - {?}
* json - {?}
*/ */
dispatch: function(callback, request, transport, json) { dispatch: function(callback, request, transport) {
var responder; var responder;
for (var i = 0; i < this.responders.length; i++) { for (var i = 0; i < this.responders.length; i++) {
responder = this.responders[i]; responder = this.responders[i];
@@ -193,7 +202,7 @@ OpenLayers.Ajax.Responders = {
typeof responder[callback] == 'function') { typeof responder[callback] == 'function') {
try { try {
responder[callback].apply(responder, responder[callback].apply(responder,
[request, transport, json]); [request, transport]);
} catch (e) {} } catch (e) {}
} }
} }
@@ -217,50 +226,34 @@ OpenLayers.Ajax.Responders.register({
}); });
/** /**
* Namespace: OpenLayers.Ajax.Base * Class: OpenLayers.Ajax.Base
* {Object}
*/ */
OpenLayers.Ajax.Base = function() {}; OpenLayers.Ajax.Base = OpenLayers.Class({
OpenLayers.Ajax.Base.prototype = {
/** /**
* Function: setOptions * Constructor: OpenLayers.Ajax.Base
* *
* Parameters: * Parameters:
* options - {Object} * options - {Object}
*/ */
setOptions: function(options) { initialize: function(options) {
this.options = { this.options = {
'method': 'post', method: 'post',
'asynchronous': true, asynchronous: true,
'parameters': '' contentType: 'application/x-www-form-urlencoded',
encoding: 'UTF-8',
parameters: ''
}; };
OpenLayers.Util.extend(this.options, options || {}); OpenLayers.Util.extend(this.options, options || {});
},
/** this.options.method = this.options.method.toLowerCase();
* Function: responseIsSuccess
*
* Returns:
* {Boolean}
*/
responseIsSuccess: function() {
return this.transport.status == undefined ||
this.transport.status == 0 ||
(this.transport.status >= 200 && this.transport.status < 300);
},
/** if (typeof this.options.parameters == 'string') {
* Function: responseIsFailure this.options.parameters =
* OpenLayers.Util.getParameters(this.options.parameters);
* Returns: }
* {Boolean}
*/
responseIsFailure: function() {
return !this.responseIsSuccess();
} }
}; });
/** /**
* Class: OpenLayers.Ajax.Request * Class: OpenLayers.Ajax.Request
@@ -270,16 +263,24 @@ OpenLayers.Ajax.Base.prototype = {
*/ */
OpenLayers.Ajax.Request = OpenLayers.Class(OpenLayers.Ajax.Base, { OpenLayers.Ajax.Request = OpenLayers.Class(OpenLayers.Ajax.Base, {
/** /**
* Constructor: OpenLayers.Ajax.Request * Property: _complete
* *
* Parameters: * {Boolean}
* url - {String} */
* options - {Object} _complete: false,
*/
/**
* Constructor: OpenLayers.Ajax.Request
*
* Parameters:
* url - {String}
* options - {Object}
*/
initialize: function(url, options) { initialize: function(url, options) {
OpenLayers.Ajax.Base.prototype.initialize.apply(this, [options]);
this.transport = OpenLayers.Ajax.getTransport(); this.transport = OpenLayers.Ajax.getTransport();
this.setOptions(options);
this.request(url); this.request(url);
}, },
@@ -290,129 +291,139 @@ OpenLayers.Ajax.Request = OpenLayers.Class(OpenLayers.Ajax.Base, {
* url - {String} * url - {String}
*/ */
request: function(url) { request: function(url) {
var parameters = this.options.parameters || ''; this.url = url;
if (parameters.length > 0) { this.method = this.options.method;
parameters += '&_='; var params = OpenLayers.Util.extend({}, this.options.parameters);
if (this.method != 'get' && this.method != 'post') {
// simulate other verbs over post
params['_method'] = this.method;
this.method = 'post';
}
this.parameters = params;
if (params = OpenLayers.Util.getParameterString(params)) {
// when GET, append parameters to URL
if (this.method == 'get') {
this.url += ((this.url.indexOf('?') > -1) ? '&' : '?') + params;
} else if (/Konqueror|Safari|KHTML/.test(navigator.userAgent)) {
params += '&_=';
}
} }
try { try {
this.url = url; var response = new OpenLayers.Ajax.Response(this);
if (this.options.method == 'get' && parameters.length > 0) { if (this.options.onCreate) {
this.url += (this.url.match(/\?/) ? '&' : '?') + parameters; this.options.onCreate(response);
} }
OpenLayers.Ajax.Responders.dispatch('onCreate', OpenLayers.Ajax.Responders.dispatch('onCreate',
this, this,
this.transport); response);
this.transport.open(this.options.method, this.transport.open(this.method.toUpperCase(),
this.url, this.url,
this.options.asynchronous); this.options.asynchronous);
if (this.options.asynchronous) { if (this.options.asynchronous) {
setTimeout(OpenLayers.Function.bind( window.setTimeout(
(function() {this.respondToReadyState(1);}),this), 10 OpenLayers.Function.bind(this.respondToReadyState, this, 1),
); 10);
} }
this.transport.onreadystatechange = this.transport.onreadystatechange =
OpenLayers.Function.bind(this.onStateChange, this); OpenLayers.Function.bind(this.onStateChange, this);
this.setRequestHeaders(); this.setRequestHeaders();
var body = this.options.postBody ? this.options.postBody this.body = this.method == 'post' ?
: parameters; (this.options.postBody || params) : null;
this.transport.send(this.options.method == 'post' ? body : null); this.transport.send(this.body);
// Force Firefox to handle ready state 4 for synchronous requests // Force Firefox to handle ready state 4 for synchronous requests
if (!this.options.asynchronous && if (!this.options.asynchronous &&
this.transport.overrideMimeType) { this.transport.overrideMimeType) {
this.onStateChange(); this.onStateChange();
} }
} catch (e) { } catch (e) {
this.dispatchException(e); this.dispatchException(e);
} }
}, },
/**
* Method: setRequestHeaders
*/
setRequestHeaders: function() {
var requestHeaders = [
'X-Requested-With',
'XMLHttpRequest',
'X-Prototype-Version',
'OpenLayers'
];
if (this.options.method == 'post' && !this.options.postBody) {
requestHeaders.push('Content-type',
'application/x-www-form-urlencoded');
// Force "Connection: close" for Mozilla browsers to work around
// a bug where XMLHttpReqeuest sends an incorrect Content-length
// header. See Mozilla Bugzilla #246651.
if (this.transport.overrideMimeType) {
requestHeaders.push('Connection', 'close');
}
}
if (this.options.requestHeaders) {
requestHeaders.push.apply(requestHeaders,
this.options.requestHeaders);
}
for (var i = 0; i < requestHeaders.length; i += 2) {
this.transport.setRequestHeader(requestHeaders[i],
requestHeaders[i+1]);
}
},
/** /**
* Method: onStateChange * Method: onStateChange
*/ */
onStateChange: function() { onStateChange: function() {
var readyState = this.transport.readyState; var readyState = this.transport.readyState;
if (readyState != 1) { if (readyState > 1 && !((readyState == 4) && this._complete)) {
this.respondToReadyState(this.transport.readyState); this.respondToReadyState(this.transport.readyState);
} }
}, },
/** /**
* Method: header * Method: setRequestHeaders
*
* Returns:
* {?}
*/ */
header: function(name) { setRequestHeaders: function() {
try { var headers = {
return this.transport.getResponseHeader(name); 'X-Requested-With': 'XMLHttpRequest',
} catch (e) {} 'Accept': 'text/javascript, text/html, application/xml, text/xml, */*',
'OpenLayers': true
};
if (this.method == 'post') {
headers['Content-type'] = this.options.contentType +
(this.options.encoding ? '; charset=' + this.options.encoding : '');
/* Force "Connection: close" for older Mozilla browsers to work
* around a bug where XMLHttpRequest sends an incorrect
* Content-length header. See Mozilla Bugzilla #246651.
*/
if (this.transport.overrideMimeType &&
(navigator.userAgent.match(/Gecko\/(\d{4})/) || [0,2005])[1] < 2005) {
headers['Connection'] = 'close';
}
}
// user-defined headers
if (typeof this.options.requestHeaders == 'object') {
var extras = this.options.requestHeaders;
if (typeof extra.push == 'function') {
for (var i = 0, length = extras.length; i < length; i += 2) {
headers[extras[i]] = extras[i+1];
}
} else {
for (var i in extras) {
headers[i] = pair[i];
}
}
}
for (var name in headers) {
this.transport.setRequestHeader(name, headers[name]);
}
}, },
/** /**
* Method: evalJSON * Method: success
* *
* Returns: * Returns:
* {?} * {Boolean} -
*/ */
evalJSON: function() { success: function() {
try { var status = this.getStatus();
return eval(this.header('X-JSON')); return !status || (status >=200 && status < 300);
} catch (e) {}
}, },
/** /**
* Method: evalResponse * Method: getStatus
* *
* Returns: * Returns:
* {?} * {Integer} - Status
*/ */
evalResponse: function() { getStatus: function() {
try { try {
return eval(this.transport.responseText); return this.transport.status || 0;
} catch (e) { } catch (e) {
this.dispatchException(e); return 0
} }
}, },
@@ -423,44 +434,55 @@ OpenLayers.Ajax.Request = OpenLayers.Class(OpenLayers.Ajax.Base, {
* readyState - {?} * readyState - {?}
*/ */
respondToReadyState: function(readyState) { respondToReadyState: function(readyState) {
var event = OpenLayers.Ajax.Request.Events[readyState]; var state = OpenLayers.Ajax.Request.Events[readyState];
var transport = this.transport, json = this.evalJSON(); var response = new OpenLayers.Ajax.Response(this);
if (event == 'Complete') { if (state == 'Complete') {
try { try {
var responseSuccess = this.responseIsSuccess() ? 'Success' this._complete = true;
: 'Failure'; (this.options['on' + response.status] ||
this.options['on' + (this.success() ? 'Success' : 'Failure')] ||
(this.options['on' + this.transport.status] || OpenLayers.Ajax.emptyFunction)(response);
this.options['on' + responseSuccess] ||
OpenLayers.Ajax.emptyFunction)(transport, json);
} catch (e) { } catch (e) {
this.dispatchException(e); this.dispatchException(e);
} }
var contentType = this.header('Content-type') || ''; var contentType = response.getHeader('Content-type');
if (contentType.match(/^text\/javascript/i)) {
this.evalResponse();
}
} }
try { try {
(this.options['on' + event] || (this.options['on' + state] ||
OpenLayers.Ajax.emptyFunction)(transport, json); OpenLayers.Ajax.emptyFunction)(response);
OpenLayers.Ajax.Responders.dispatch('on' + event, OpenLayers.Ajax.Responders.dispatch('on' + state,
this, this,
transport, response);
json);
} catch (e) { } catch (e) {
this.dispatchException(e); this.dispatchException(e);
} }
// Avoid memory leak in MSIE: clean up the oncomplete event handler if (state == 'Complete') {
if (event == 'Complete') { // avoid memory leak in MSIE: clean up
this.transport.onreadystatechange = OpenLayers.Ajax.emptyFunction; this.transport.onreadystatechange = OpenLayers.Ajax.emptyFunction;
} }
}, },
/**
* Method: getHeader
*
* Parameters:
* name - {String} Header name
*
* Returns:
* {?} - response header for the given name
*/
getHeader: function(name) {
try {
return this.transport.getResponseHeader(name);
} catch (e) {
return null
}
},
/** /**
* Method: dispatchException * Method: dispatchException
* *
@@ -468,17 +490,10 @@ OpenLayers.Ajax.Request = OpenLayers.Class(OpenLayers.Ajax.Base, {
* exception - {?} * exception - {?}
*/ */
dispatchException: function(exception) { dispatchException: function(exception) {
if (this.options.onException) { (this.options.onException ||
this.options.onException(this, exception); OpenLayers.Ajax.emptyFunction)(this, exception);
} else {
// if we get here, Responders.dispatch('onException') will never
// be called. too bad. we should probably take out the Responders
// stuff anyway.
throw exception;
}
OpenLayers.Ajax.Responders.dispatch('onException', this, exception); OpenLayers.Ajax.Responders.dispatch('onException', this, exception);
} }
}); });
/** /**
@@ -488,6 +503,91 @@ OpenLayers.Ajax.Request = OpenLayers.Class(OpenLayers.Ajax.Base, {
OpenLayers.Ajax.Request.Events = OpenLayers.Ajax.Request.Events =
['Uninitialized', 'Loading', 'Loaded', 'Interactive', 'Complete']; ['Uninitialized', 'Loading', 'Loaded', 'Interactive', 'Complete'];
/**
* Class: OpenLayers.Ajax.Request
*
* Inherit:
* - <OpenLayers.Ajax.Base>
*/
OpenLayers.Ajax.Response = OpenLayers.Class({
/**
* Property: status
*
* {Integer}
*/
status: 0,
/**
* Property: statusText
*
* {String}
*/
statusText: '',
/**
* Constructor: OpenLayers.Ajax.Response
*
* Parameters:
* request - {Object}
*/
initialize: function(request) {
this.request = request;
var transport = this.transport = request.transport,
readyState = this.readyState = transport.readyState;
if ((readyState > 2 &&
!(!!(window.attachEvent && !window.opera))) ||
readyState == 4) {
this.status = this.getStatus();
this.statusText = this.getStatusText();
this.responseText = transport.responseText == null ?
'' : String(transport.responseText);
}
if(readyState == 4) {
var xml = transport.responseXML;
this.responseXML = xml === undefined ? null : xml;
}
},
/**
* Method: getStatus
*/
getStatus: OpenLayers.Ajax.Request.prototype.getStatus,
/**
* Method: getStatustext
*
* Returns:
* {String} - statusText
*/
getStatusText: function() {
try {
return this.transport.statusText || '';
} catch (e) {
return '';
}
},
/**
* Method: getHeader
*/
getHeader: OpenLayers.Ajax.Request.prototype.getHeader,
/**
* Method: getResponseHeader
*
* Returns:
* {?} - response header for given name
*/
getResponseHeader: function(name) {
return this.transport.getResponseHeader(name);
}
});
/** /**
* Function: getElementsByTagNameNS * Function: getElementsByTagNameNS
* *
+70
View File
@@ -0,0 +1,70 @@
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<title>Draw Feature Acceptance Test</title>
<style type="text/css">
body {
font-size: 0.8em;
}
p {
padding-top: 1em;
}
.buttons {
margin: 1em;
float: left;
}
</style>
<script src="../../lib/OpenLayers.js"></script>
<script type="text/javascript">
var url = "ajax.txt";
function sendSynchronous(){
var request = new OpenLayers.Ajax.Request(url, {
onComplete: 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, {
'asynchronous': false,
onComplete: 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';
}
}
});
request.transport.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 />
<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>"other processing" then "request completed"</li>
<li>"request completed" then "other processing"</li>
<li>"request aborted" then "other processing"</li>
</ul>
</body>
</html>
+1
View File
@@ -0,0 +1 @@
one fake text file