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

View File

@@ -135,9 +135,9 @@ OpenLayers.Ajax = {
*/
getTransport: function() {
return OpenLayers.Util.Try(
function() {return new XMLHttpRequest();},
function() {return new ActiveXObject('Msxml2.XMLHTTP');},
function() {return new ActiveXObject('Microsoft.XMLHTTP');},
function() {return new XMLHttpRequest();}
function() {return new ActiveXObject('Microsoft.XMLHTTP');}
) || false;
},
@@ -167,12 +167,22 @@ OpenLayers.Ajax.Responders = {
* responderToAdd - {?}
*/
register: function(responderToAdd) {
for (var i = 0; i < this.responders.length; i++){
if (responderToAdd == this.responders[i]){
return;
}
}
this.responders.push(responderToAdd);
for (var i = 0; i < this.responders.length; i++){
if (responderToAdd == this.responders[i]){
return;
}
}
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 - {?}
* request - {?}
* transport - {?}
* json - {?}
*/
dispatch: function(callback, request, transport, json) {
dispatch: function(callback, request, transport) {
var responder;
for (var i = 0; i < this.responders.length; i++) {
responder = this.responders[i];
@@ -193,7 +202,7 @@ OpenLayers.Ajax.Responders = {
typeof responder[callback] == 'function') {
try {
responder[callback].apply(responder,
[request, transport, json]);
[request, transport]);
} catch (e) {}
}
}
@@ -217,50 +226,34 @@ OpenLayers.Ajax.Responders.register({
});
/**
* Namespace: OpenLayers.Ajax.Base
* {Object}
* Class: OpenLayers.Ajax.Base
*/
OpenLayers.Ajax.Base = function() {};
OpenLayers.Ajax.Base.prototype = {
OpenLayers.Ajax.Base = OpenLayers.Class({
/**
* Function: setOptions
* Constructor: OpenLayers.Ajax.Base
*
* Parameters:
* options - {Object}
*/
setOptions: function(options) {
initialize: function(options) {
this.options = {
'method': 'post',
'asynchronous': true,
'parameters': ''
method: 'post',
asynchronous: true,
contentType: 'application/x-www-form-urlencoded',
encoding: 'UTF-8',
parameters: ''
};
OpenLayers.Util.extend(this.options, options || {});
},
/**
* Function: responseIsSuccess
*
* Returns:
* {Boolean}
*/
responseIsSuccess: function() {
return this.transport.status == undefined ||
this.transport.status == 0 ||
(this.transport.status >= 200 && this.transport.status < 300);
},
this.options.method = this.options.method.toLowerCase();
/**
* Function: responseIsFailure
*
* Returns:
* {Boolean}
*/
responseIsFailure: function() {
return !this.responseIsSuccess();
if (typeof this.options.parameters == 'string') {
this.options.parameters =
OpenLayers.Util.getParameters(this.options.parameters);
}
}
};
});
/**
* Class: OpenLayers.Ajax.Request
@@ -270,16 +263,24 @@ OpenLayers.Ajax.Base.prototype = {
*/
OpenLayers.Ajax.Request = OpenLayers.Class(OpenLayers.Ajax.Base, {
/**
* Constructor: OpenLayers.Ajax.Request
*
* Parameters:
* url - {String}
* options - {Object}
*/
/**
* Property: _complete
*
* {Boolean}
*/
_complete: false,
/**
* Constructor: OpenLayers.Ajax.Request
*
* Parameters:
* url - {String}
* options - {Object}
*/
initialize: function(url, options) {
OpenLayers.Ajax.Base.prototype.initialize.apply(this, [options]);
this.transport = OpenLayers.Ajax.getTransport();
this.setOptions(options);
this.request(url);
},
@@ -290,129 +291,139 @@ OpenLayers.Ajax.Request = OpenLayers.Class(OpenLayers.Ajax.Base, {
* url - {String}
*/
request: function(url) {
var parameters = this.options.parameters || '';
if (parameters.length > 0) {
parameters += '&_=';
this.url = url;
this.method = this.options.method;
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 {
this.url = url;
if (this.options.method == 'get' && parameters.length > 0) {
this.url += (this.url.match(/\?/) ? '&' : '?') + parameters;
var response = new OpenLayers.Ajax.Response(this);
if (this.options.onCreate) {
this.options.onCreate(response);
}
OpenLayers.Ajax.Responders.dispatch('onCreate',
this,
this.transport);
response);
this.transport.open(this.options.method,
this.transport.open(this.method.toUpperCase(),
this.url,
this.options.asynchronous);
if (this.options.asynchronous) {
setTimeout(OpenLayers.Function.bind(
(function() {this.respondToReadyState(1);}),this), 10
);
window.setTimeout(
OpenLayers.Function.bind(this.respondToReadyState, this, 1),
10);
}
this.transport.onreadystatechange =
OpenLayers.Function.bind(this.onStateChange, this);
this.setRequestHeaders();
var body = this.options.postBody ? this.options.postBody
: parameters;
this.transport.send(this.options.method == 'post' ? body : null);
this.body = this.method == 'post' ?
(this.options.postBody || params) : null;
this.transport.send(this.body);
// Force Firefox to handle ready state 4 for synchronous requests
if (!this.options.asynchronous &&
this.transport.overrideMimeType) {
this.onStateChange();
}
} catch (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
*/
onStateChange: function() {
var readyState = this.transport.readyState;
if (readyState != 1) {
this.respondToReadyState(this.transport.readyState);
if (readyState > 1 && !((readyState == 4) && this._complete)) {
this.respondToReadyState(this.transport.readyState);
}
},
/**
* Method: header
*
* Returns:
* {?}
* Method: setRequestHeaders
*/
header: function(name) {
try {
return this.transport.getResponseHeader(name);
} catch (e) {}
setRequestHeaders: function() {
var headers = {
'X-Requested-With': 'XMLHttpRequest',
'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:
* {?}
* {Boolean} -
*/
evalJSON: function() {
try {
return eval(this.header('X-JSON'));
} catch (e) {}
success: function() {
var status = this.getStatus();
return !status || (status >=200 && status < 300);
},
/**
* Method: evalResponse
* Method: getStatus
*
* Returns:
* {?}
* {Integer} - Status
*/
evalResponse: function() {
getStatus: function() {
try {
return eval(this.transport.responseText);
return this.transport.status || 0;
} catch (e) {
this.dispatchException(e);
return 0
}
},
@@ -423,44 +434,55 @@ OpenLayers.Ajax.Request = OpenLayers.Class(OpenLayers.Ajax.Base, {
* readyState - {?}
*/
respondToReadyState: function(readyState) {
var event = OpenLayers.Ajax.Request.Events[readyState];
var transport = this.transport, json = this.evalJSON();
var state = OpenLayers.Ajax.Request.Events[readyState];
var response = new OpenLayers.Ajax.Response(this);
if (event == 'Complete') {
if (state == 'Complete') {
try {
var responseSuccess = this.responseIsSuccess() ? 'Success'
: 'Failure';
(this.options['on' + this.transport.status] ||
this.options['on' + responseSuccess] ||
OpenLayers.Ajax.emptyFunction)(transport, json);
this._complete = true;
(this.options['on' + response.status] ||
this.options['on' + (this.success() ? 'Success' : 'Failure')] ||
OpenLayers.Ajax.emptyFunction)(response);
} catch (e) {
this.dispatchException(e);
}
var contentType = this.header('Content-type') || '';
if (contentType.match(/^text\/javascript/i)) {
this.evalResponse();
}
var contentType = response.getHeader('Content-type');
}
try {
(this.options['on' + event] ||
OpenLayers.Ajax.emptyFunction)(transport, json);
OpenLayers.Ajax.Responders.dispatch('on' + event,
(this.options['on' + state] ||
OpenLayers.Ajax.emptyFunction)(response);
OpenLayers.Ajax.Responders.dispatch('on' + state,
this,
transport,
json);
response);
} catch (e) {
this.dispatchException(e);
}
// Avoid memory leak in MSIE: clean up the oncomplete event handler
if (event == 'Complete') {
if (state == 'Complete') {
// avoid memory leak in MSIE: clean up
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
*
@@ -468,17 +490,10 @@ OpenLayers.Ajax.Request = OpenLayers.Class(OpenLayers.Ajax.Base, {
* exception - {?}
*/
dispatchException: function(exception) {
if (this.options.onException) {
this.options.onException(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;
}
(this.options.onException ||
OpenLayers.Ajax.emptyFunction)(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 =
['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
*

70
tests/manual/ajax.html Normal file
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
tests/manual/ajax.txt Normal file
View File

@@ -0,0 +1 @@
one fake text file