1 /* Copyright (c) 2006-2008 MetaCarta, Inc., published under the Clear BSD
2 * license. See http://svn.openlayers.org/trunk/openlayers/license.txt for the
3 * full text of the license. */
6 * @requires OpenLayers/Request/XMLHttpRequest.js
7 * @requires OpenLayers/Console.js
10 OpenLayers.ProxyHost = "";
11 //OpenLayers.ProxyHost = "examples/proxy.cgi?url=";
14 * Ajax reader for OpenLayers
16 * @uri url to do remote XML http get
17 * @param {String} 'get' format params (x=y&a=b...)
18 * @who object to handle callbacks for this request
19 * @complete the function to be called on success
20 * @failure the function to be called on failure
22 * example usage from a caller:
24 * caps: function(request) {
28 * OpenLayers.loadURL(url,params,this,caps);
30 * Notice the above example does not provide an error handler; a default empty
31 * handler is provided which merely logs the error if a failure handler is not
38 * Function: OpenLayers.nullHandler
41 OpenLayers.nullHandler = function(request) {
42 OpenLayers.Console.userError(OpenLayers.i18n("unhandledRequest", {'statusText':request.statusText}));
46 * APIFunction: loadURL
47 * Background load a document. For more flexibility in using XMLHttpRequest,
48 * see the <OpenLayers.Request> methods.
51 * uri - {String} URI of source doc
52 * params - {String} or {Object} GET params. Either a string in the form
53 * "?hello=world&foo=bar" (do not forget the leading question mark)
54 * or an object in the form {'hello': 'world', 'foo': 'bar}
55 * caller - {Object} object which gets callbacks
56 * onComplete - {Function} Optional callback for success. The callback
57 * will be called with this set to caller and will receive the request
58 * object as an argument. Note that if you do not specify an onComplete
59 * function, <OpenLayers.nullHandler> will be called (which pops up a
60 * user friendly error message dialog).
61 * onFailure - {Function} Optional callback for failure. In the event of
62 * a failure, the callback will be called with this set to caller and will
63 * receive the request object as an argument. Note that if you do not
64 * specify an onComplete function, <OpenLayers.nullHandler> will be called
65 * (which pops up a user friendly error message dialog).
68 * {<OpenLayers.Request.XMLHttpRequest>} The request object. To abort loading,
69 * call request.abort().
71 OpenLayers.loadURL = function(uri, params, caller,
72 onComplete, onFailure) {
74 if(typeof params == 'string') {
75 params = OpenLayers.Util.getParameters(params);
77 var success = (onComplete) ? onComplete : OpenLayers.nullHandler;
78 var failure = (onFailure) ? onFailure : OpenLayers.nullHandler;
80 return OpenLayers.Request.GET({
81 url: uri, params: params,
82 success: success, failure: failure, scope: caller
87 * Function: parseXMLString
88 * Parse XML into a doc structure
94 * {?} Parsed AJAX Responsev
96 OpenLayers.parseXMLString = function(text) {
98 //MS sucks, if the server is bad it dies
99 var index = text.indexOf('<');
101 text = text.substring(index);
104 var ajaxResponse = OpenLayers.Util.Try(
106 var xmldom = new ActiveXObject('Microsoft.XMLDOM');
107 xmldom.loadXML(text);
111 return new DOMParser().parseFromString(text, 'text/xml');
114 var req = new XMLHttpRequest();
115 req.open("GET", "data:" + "text/xml" +
116 ";charset=utf-8," + encodeURIComponent(text), false);
117 if (req.overrideMimeType) {
118 req.overrideMimeType("text/xml");
121 return req.responseXML;
130 * Namespace: OpenLayers.Ajax
135 * Method: emptyFunction
137 emptyFunction: function () {},
140 * Method: getTransport
143 * {Object} Transport mechanism for whichever browser we're in, or false if
146 getTransport: function() {
147 return OpenLayers.Util.Try(
148 function() {return new XMLHttpRequest();},
149 function() {return new ActiveXObject('Msxml2.XMLHTTP');},
150 function() {return new ActiveXObject('Microsoft.XMLHTTP');}
155 * Property: activeRequestCount
158 activeRequestCount: 0
162 * Namespace: OpenLayers.Ajax.Responders
165 OpenLayers.Ajax.Responders = {
168 * Property: responders
177 * responderToAdd - {?}
179 register: function(responderToAdd) {
180 for (var i = 0; i < this.responders.length; i++){
181 if (responderToAdd == this.responders[i]){
185 this.responders.push(responderToAdd);
192 * responderToRemove - {?}
194 unregister: function(responderToRemove) {
195 OpenLayers.Util.removeItem(this.reponders, responderToRemove);
206 dispatch: function(callback, request, transport) {
208 for (var i = 0; i < this.responders.length; i++) {
209 responder = this.responders[i];
211 if (responder[callback] &&
212 typeof responder[callback] == 'function') {
214 responder[callback].apply(responder,
215 [request, transport]);
222 OpenLayers.Ajax.Responders.register({
226 onCreate: function() {
227 OpenLayers.Ajax.activeRequestCount++;
231 * Function: onComplete
233 onComplete: function() {
234 OpenLayers.Ajax.activeRequestCount--;
239 * Class: OpenLayers.Ajax.Base
241 OpenLayers.Ajax.Base = OpenLayers.Class({
244 * Constructor: OpenLayers.Ajax.Base
249 initialize: function(options) {
253 contentType: 'application/xml',
256 OpenLayers.Util.extend(this.options, options || {});
258 this.options.method = this.options.method.toLowerCase();
260 if (typeof this.options.parameters == 'string') {
261 this.options.parameters =
262 OpenLayers.Util.getParameters(this.options.parameters);
268 * Class: OpenLayers.Ajax.Request
269 * *Deprecated*. Use <OpenLayers.Request> method instead.
272 * - <OpenLayers.Ajax.Base>
274 OpenLayers.Ajax.Request = OpenLayers.Class(OpenLayers.Ajax.Base, {
277 * Property: _complete
284 * Constructor: OpenLayers.Ajax.Request
290 initialize: function(url, options) {
291 OpenLayers.Ajax.Base.prototype.initialize.apply(this, [options]);
293 if (OpenLayers.ProxyHost && OpenLayers.String.startsWith(url, "http")) {
294 url = OpenLayers.ProxyHost + encodeURIComponent(url);
297 this.transport = OpenLayers.Ajax.getTransport();
307 request: function(url) {
309 this.method = this.options.method;
310 var params = OpenLayers.Util.extend({}, this.options.parameters);
312 if (this.method != 'get' && this.method != 'post') {
313 // simulate other verbs over post
314 params['_method'] = this.method;
315 this.method = 'post';
318 this.parameters = params;
320 if (params = OpenLayers.Util.getParameterString(params)) {
321 // when GET, append parameters to URL
322 if (this.method == 'get') {
323 this.url += ((this.url.indexOf('?') > -1) ? '&' : '?') + params;
324 } else if (/Konqueror|Safari|KHTML/.test(navigator.userAgent)) {
329 var response = new OpenLayers.Ajax.Response(this);
330 if (this.options.onCreate) {
331 this.options.onCreate(response);
334 OpenLayers.Ajax.Responders.dispatch('onCreate',
338 this.transport.open(this.method.toUpperCase(),
340 this.options.asynchronous);
342 if (this.options.asynchronous) {
344 OpenLayers.Function.bind(this.respondToReadyState, this, 1),
348 this.transport.onreadystatechange =
349 OpenLayers.Function.bind(this.onStateChange, this);
350 this.setRequestHeaders();
352 this.body = this.method == 'post' ?
353 (this.options.postBody || params) : null;
354 this.transport.send(this.body);
356 // Force Firefox to handle ready state 4 for synchronous requests
357 if (!this.options.asynchronous &&
358 this.transport.overrideMimeType) {
359 this.onStateChange();
362 this.dispatchException(e);
367 * Method: onStateChange
369 onStateChange: function() {
370 var readyState = this.transport.readyState;
371 if (readyState > 1 && !((readyState == 4) && this._complete)) {
372 this.respondToReadyState(this.transport.readyState);
377 * Method: setRequestHeaders
379 setRequestHeaders: function() {
381 'X-Requested-With': 'XMLHttpRequest',
382 'Accept': 'text/javascript, text/html, application/xml, text/xml, */*',
386 if (this.method == 'post') {
387 headers['Content-type'] = this.options.contentType +
388 (this.options.encoding ? '; charset=' + this.options.encoding : '');
390 /* Force "Connection: close" for older Mozilla browsers to work
391 * around a bug where XMLHttpRequest sends an incorrect
392 * Content-length header. See Mozilla Bugzilla #246651.
394 if (this.transport.overrideMimeType &&
395 (navigator.userAgent.match(/Gecko\/(\d{4})/) || [0,2005])[1] < 2005) {
396 headers['Connection'] = 'close';
399 // user-defined headers
400 if (typeof this.options.requestHeaders == 'object') {
401 var extras = this.options.requestHeaders;
403 if (typeof extras.push == 'function') {
404 for (var i = 0, length = extras.length; i < length; i += 2) {
405 headers[extras[i]] = extras[i+1];
408 for (var i in extras) {
409 headers[i] = extras[i];
414 for (var name in headers) {
415 this.transport.setRequestHeader(name, headers[name]);
425 success: function() {
426 var status = this.getStatus();
427 return !status || (status >=200 && status < 300);
436 getStatus: function() {
438 return this.transport.status || 0;
445 * Method: respondToReadyState
450 respondToReadyState: function(readyState) {
451 var state = OpenLayers.Ajax.Request.Events[readyState];
452 var response = new OpenLayers.Ajax.Response(this);
454 if (state == 'Complete') {
456 this._complete = true;
457 (this.options['on' + response.status] ||
458 this.options['on' + (this.success() ? 'Success' : 'Failure')] ||
459 OpenLayers.Ajax.emptyFunction)(response);
461 this.dispatchException(e);
464 var contentType = response.getHeader('Content-type');
468 (this.options['on' + state] ||
469 OpenLayers.Ajax.emptyFunction)(response);
470 OpenLayers.Ajax.Responders.dispatch('on' + state,
474 this.dispatchException(e);
477 if (state == 'Complete') {
478 // avoid memory leak in MSIE: clean up
479 this.transport.onreadystatechange = OpenLayers.Ajax.emptyFunction;
487 * name - {String} Header name
490 * {?} - response header for the given name
492 getHeader: function(name) {
494 return this.transport.getResponseHeader(name);
501 * Method: dispatchException
502 * If the optional onException function is set, execute it
503 * and then dispatch the call to any other listener registered
506 * If no optional onException function is set, we suspect that
507 * the user may have also not used
508 * OpenLayers.Ajax.Responders.register to register a listener
509 * for the onException call. To make sure that something
510 * gets done with this exception, only dispatch the call if there
513 * If you explicitly want to swallow exceptions, set
514 * request.options.onException to an empty function (function(){})
515 * or register an empty function with <OpenLayers.Ajax.Responders>
521 dispatchException: function(exception) {
522 var handler = this.options.onException;
524 // call options.onException and alert any other listeners
525 handler(this, exception);
526 OpenLayers.Ajax.Responders.dispatch('onException', this, exception);
528 // check if there are any other listeners
529 var listener = false;
530 var responders = OpenLayers.Ajax.Responders.responders;
531 for (var i = 0; i < responders.length; i++) {
532 if(responders[i].onException) {
538 // call all listeners
539 OpenLayers.Ajax.Responders.dispatch('onException', this, exception);
541 // let the exception through
552 OpenLayers.Ajax.Request.Events =
553 ['Uninitialized', 'Loading', 'Loaded', 'Interactive', 'Complete'];
556 * Class: OpenLayers.Ajax.Response
558 OpenLayers.Ajax.Response = OpenLayers.Class({
569 * Property: statusText
576 * Constructor: OpenLayers.Ajax.Response
581 initialize: function(request) {
582 this.request = request;
583 var transport = this.transport = request.transport,
584 readyState = this.readyState = transport.readyState;
586 if ((readyState > 2 &&
587 !(!!(window.attachEvent && !window.opera))) ||
589 this.status = this.getStatus();
590 this.statusText = this.getStatusText();
591 this.responseText = transport.responseText == null ?
592 '' : String(transport.responseText);
595 if(readyState == 4) {
596 var xml = transport.responseXML;
597 this.responseXML = xml === undefined ? null : xml;
604 getStatus: OpenLayers.Ajax.Request.prototype.getStatus,
607 * Method: getStatustext
610 * {String} - statusText
612 getStatusText: function() {
614 return this.transport.statusText || '';
623 getHeader: OpenLayers.Ajax.Request.prototype.getHeader,
626 * Method: getResponseHeader
629 * {?} - response header for given name
631 getResponseHeader: function(name) {
632 return this.transport.getResponseHeader(name);
638 * Function: getElementsByTagNameNS
649 OpenLayers.Ajax.getElementsByTagNameNS = function(parentnode, nsuri,
652 if (parentnode.getElementsByTagNameNS) {
653 elem = parentnode.getElementsByTagNameNS(nsuri, tagname);
655 elem = parentnode.getElementsByTagName(nsprefix + ':' + tagname);
662 * Function: serializeXMLToString
663 * Wrapper function around XMLSerializer, which doesn't exist/work in
664 * IE/Safari. We need to come up with a way to serialize in those browser:
665 * for now, these browsers will just fail. #535, #536
668 * xmldom {XMLNode} xml dom to serialize
673 OpenLayers.Ajax.serializeXMLToString = function(xmldom) {
674 var serializer = new XMLSerializer();
675 var data = serializer.serializeToString(xmldom);