Files
openlayers/lib/OpenLayers/Ajax.js
crschmidt 64fc4fcb1b Patch from funky_c to move all alert()s in the library to a single
OpenLayers.Console.userError function. This allows for easy overriding of this
function for people who need to report errors at an application level (or
hiding these errors entirely), with the same default behavior as previous
releases. Patch from funky_c, r=me, (Closes #1651)


git-svn-id: http://svn.openlayers.org/trunk/openlayers@7675 dc9f47b5-9b13-0410-9fdd-eb0c1a62fdaf
2008-08-01 22:21:50 +00:00

677 lines
19 KiB
JavaScript

/* 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. */
/**
* @requires OpenLayers/Request/XMLHttpRequest.js
*/
OpenLayers.ProxyHost = "";
//OpenLayers.ProxyHost = "examples/proxy.cgi?url=";
/**
* Ajax reader for OpenLayers
*
* @uri url to do remote XML http get
* @param {String} 'get' format params (x=y&a=b...)
* @who object to handle callbacks for this request
* @complete the function to be called on success
* @failure the function to be called on failure
*
* example usage from a caller:
*
* caps: function(request) {
* -blah-
* },
*
* OpenLayers.loadURL(url,params,this,caps);
*
* Notice the above example does not provide an error handler; a default empty
* handler is provided which merely logs the error if a failure handler is not
* supplied
*
*/
/**
* Function: OpenLayers.nullHandler
* @param {} request
*/
OpenLayers.nullHandler = function(request) {
OpenLayers.Console.userError(OpenLayers.i18n("unhandledRequest", {'statusText':request.statusText}));
};
/**
* Function: loadURL
* Background load a document. For more flexibility in using XMLHttpRequest,
* see the <OpenLayers.Request> methods.
*
* Parameters:
* uri - {String} URI of source doc
* params - {String} or {Object} GET params. Either a string in the form
* "?hello=world&foo=bar" (do not forget the leading question mark)
* or an object in the form {'hello': 'world', 'foo': 'bar}
* 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. Note that if you do not specify an onComplete
* function, <OpenLayers.nullHandler> will be called (which pops up a
* user friendly error message 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. Note that if you do not
* specify an onComplete function, <OpenLayers.nullHandler> will be called
* (which pops up a user friendly error message dialog).
*
* Returns:
* {<OpenLayers.Request.XMLHttpRequest>} The request object. To abort loading,
* call request.abort().
*/
OpenLayers.loadURL = function(uri, params, caller,
onComplete, onFailure) {
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
});
};
/**
* Function: parseXMLString
* Parse XML into a doc structure
*
* Parameters:
* text - {String}
*
* Returns:
* {?} Parsed AJAX Responsev
*/
OpenLayers.parseXMLString = function(text) {
//MS sucks, if the server is bad it dies
var index = text.indexOf('<');
if (index > 0) {
text = text.substring(index);
}
var ajaxResponse = OpenLayers.Util.Try(
function() {
var xmldom = new ActiveXObject('Microsoft.XMLDOM');
xmldom.loadXML(text);
return xmldom;
},
function() {
return new DOMParser().parseFromString(text, 'text/xml');
},
function() {
var req = new XMLHttpRequest();
req.open("GET", "data:" + "text/xml" +
";charset=utf-8," + encodeURIComponent(text), false);
if (req.overrideMimeType) {
req.overrideMimeType("text/xml");
}
req.send(null);
return req.responseXML;
}
);
return ajaxResponse;
};
/**
* Namespace: OpenLayers.Ajax
*/
OpenLayers.Ajax = {
/**
* Method: emptyFunction
*/
emptyFunction: function () {},
/**
* Method: getTransport
*
* Returns:
* {Object} Transport mechanism for whichever browser we're in, or false if
* none available.
*/
getTransport: function() {
return OpenLayers.Util.Try(
function() {return new XMLHttpRequest();},
function() {return new ActiveXObject('Msxml2.XMLHTTP');},
function() {return new ActiveXObject('Microsoft.XMLHTTP');}
) || false;
},
/**
* Property: activeRequestCount
* {Integer}
*/
activeRequestCount: 0
};
/**
* Namespace: OpenLayers.Ajax.Responders
* {Object}
*/
OpenLayers.Ajax.Responders = {
/**
* Property: responders
* {Array}
*/
responders: [],
/**
* Method: register
*
* Parameters:
* responderToAdd - {?}
*/
register: function(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);
},
/**
* Method: dispatch
*
* Parameters:
* callback - {?}
* request - {?}
* transport - {?}
*/
dispatch: function(callback, request, transport) {
var responder;
for (var i = 0; i < this.responders.length; i++) {
responder = this.responders[i];
if (responder[callback] &&
typeof responder[callback] == 'function') {
try {
responder[callback].apply(responder,
[request, transport]);
} catch (e) {}
}
}
}
};
OpenLayers.Ajax.Responders.register({
/**
* Function: onCreate
*/
onCreate: function() {
OpenLayers.Ajax.activeRequestCount++;
},
/**
* Function: onComplete
*/
onComplete: function() {
OpenLayers.Ajax.activeRequestCount--;
}
});
/**
* Class: OpenLayers.Ajax.Base
*/
OpenLayers.Ajax.Base = OpenLayers.Class({
/**
* Constructor: OpenLayers.Ajax.Base
*
* Parameters:
* options - {Object}
*/
initialize: function(options) {
this.options = {
method: 'post',
asynchronous: true,
contentType: 'application/xml',
parameters: ''
};
OpenLayers.Util.extend(this.options, options || {});
this.options.method = this.options.method.toLowerCase();
if (typeof this.options.parameters == 'string') {
this.options.parameters =
OpenLayers.Util.getParameters(this.options.parameters);
}
}
});
/**
* Class: OpenLayers.Ajax.Request
* *Deprecated*. Use <OpenLayers.Request> method instead.
*
* Inherit:
* - <OpenLayers.Ajax.Base>
*/
OpenLayers.Ajax.Request = OpenLayers.Class(OpenLayers.Ajax.Base, {
/**
* 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]);
if (OpenLayers.ProxyHost && OpenLayers.String.startsWith(url, "http")) {
url = OpenLayers.ProxyHost + encodeURIComponent(url);
}
this.transport = OpenLayers.Ajax.getTransport();
this.request(url);
},
/**
* Method: request
*
* Parameters:
* url - {String}
*/
request: function(url) {
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 {
var response = new OpenLayers.Ajax.Response(this);
if (this.options.onCreate) {
this.options.onCreate(response);
}
OpenLayers.Ajax.Responders.dispatch('onCreate',
this,
response);
this.transport.open(this.method.toUpperCase(),
this.url,
this.options.asynchronous);
if (this.options.asynchronous) {
window.setTimeout(
OpenLayers.Function.bind(this.respondToReadyState, this, 1),
10);
}
this.transport.onreadystatechange =
OpenLayers.Function.bind(this.onStateChange, this);
this.setRequestHeaders();
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: onStateChange
*/
onStateChange: function() {
var readyState = this.transport.readyState;
if (readyState > 1 && !((readyState == 4) && this._complete)) {
this.respondToReadyState(this.transport.readyState);
}
},
/**
* Method: setRequestHeaders
*/
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 extras.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: success
*
* Returns:
* {Boolean} -
*/
success: function() {
var status = this.getStatus();
return !status || (status >=200 && status < 300);
},
/**
* Method: getStatus
*
* Returns:
* {Integer} - Status
*/
getStatus: function() {
try {
return this.transport.status || 0;
} catch (e) {
return 0;
}
},
/**
* Method: respondToReadyState
*
* Parameters:
* readyState - {?}
*/
respondToReadyState: function(readyState) {
var state = OpenLayers.Ajax.Request.Events[readyState];
var response = new OpenLayers.Ajax.Response(this);
if (state == 'Complete') {
try {
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 = response.getHeader('Content-type');
}
try {
(this.options['on' + state] ||
OpenLayers.Ajax.emptyFunction)(response);
OpenLayers.Ajax.Responders.dispatch('on' + state,
this,
response);
} catch (e) {
this.dispatchException(e);
}
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
* If the optional onException function is set, execute it
* and then dispatch the call to any other listener registered
* for onException.
*
* If no optional onException function is set, we suspect that
* the user may have also not used
* OpenLayers.Ajax.Responders.register to register a listener
* for the onException call. To make sure that something
* gets done with this exception, only dispatch the call if there
* are listeners.
*
* If you explicitly want to swallow exceptions, set
* request.options.onException to an empty function (function(){})
* or register an empty function with <OpenLayers.Ajax.Responders>
* for onException.
*
* Parameters:
* exception - {?}
*/
dispatchException: function(exception) {
var handler = this.options.onException;
if(handler) {
// call options.onException and alert any other listeners
handler(this, exception);
OpenLayers.Ajax.Responders.dispatch('onException', this, exception);
} else {
// check if there are any other listeners
var listener = false;
var responders = OpenLayers.Ajax.Responders.responders;
for (var i = 0; i < responders.length; i++) {
if(responders[i].onException) {
listener = true;
break;
}
}
if(listener) {
// call all listeners
OpenLayers.Ajax.Responders.dispatch('onException', this, exception);
} else {
// let the exception through
throw exception;
}
}
}
});
/**
* Property: Events
* {Array(String)}
*/
OpenLayers.Ajax.Request.Events =
['Uninitialized', 'Loading', 'Loaded', 'Interactive', 'Complete'];
/**
* Class: OpenLayers.Ajax.Response
*/
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
*
* Parameters:
* parentnode - {?}
* nsuri - {?}
* nsprefix - {?}
* tagname - {?}
*
* Returns:
* {?}
*/
OpenLayers.Ajax.getElementsByTagNameNS = function(parentnode, nsuri,
nsprefix, tagname) {
var elem = null;
if (parentnode.getElementsByTagNameNS) {
elem = parentnode.getElementsByTagNameNS(nsuri, tagname);
} else {
elem = parentnode.getElementsByTagName(nsprefix + ':' + tagname);
}
return elem;
};
/**
* Function: serializeXMLToString
* Wrapper function around XMLSerializer, which doesn't exist/work in
* IE/Safari. We need to come up with a way to serialize in those browser:
* for now, these browsers will just fail. #535, #536
*
* Parameters:
* xmldom {XMLNode} xml dom to serialize
*
* Returns:
* {?}
*/
OpenLayers.Ajax.serializeXMLToString = function(xmldom) {
var serializer = new XMLSerializer();
var data = serializer.serializeToString(xmldom);
return data;
};