OpenLayers OpenLayers

Ticket #1170: ajax.patch

File ajax.patch, 20.2 kB (added by tschaub, 1 year ago)

ajax prototype.js style

  • tests/manual/ajax.txt

    old new  
  • tests/manual/ajax.html

    old new  
     1<html xmlns="http://www.w3.org/1999/xhtml"> 
     2  <head> 
     3    <title>Draw Feature Acceptance Test</title> 
     4    <style type="text/css"> 
     5     
     6        body { 
     7            font-size: 0.8em; 
     8        } 
     9        p { 
     10            padding-top: 1em; 
     11        } 
     12         
     13        .buttons { 
     14            margin: 1em; 
     15            float: left; 
     16        } 
     17 
     18    </style> 
     19 
     20    <script src="../../lib/OpenLayers.js"></script> 
     21    <script type="text/javascript"> 
     22        var url = "ajax.txt"; 
     23        function sendSynchronous(){ 
     24            var request = new OpenLayers.Ajax.Request(url, { 
     25                onComplete: function() { 
     26                    document.getElementById('send_sync').value += 'request completed\n'; 
     27                } 
     28            }); 
     29            document.getElementById('send_sync').value += 'other processing\n'; 
     30        } 
     31        function sendAsynchronous(){ 
     32            var request = new OpenLayers.Ajax.Request(url, { 
     33               'asynchronous': false, 
     34                onComplete: function() { 
     35                    document.getElementById('send_sync').value += 'request completed\n'; 
     36                } 
     37            }); 
     38            document.getElementById('send_sync').value += 'other processing\n'; 
     39        } 
     40        function sendAndAbort(){ 
     41            var request = new OpenLayers.Ajax.Request(url, { 
     42                onComplete: function(request) { 
     43                    if (request.responseText == '') { 
     44                        document.getElementById('send_sync').value += 'request aborted\n'; 
     45                    } 
     46                } 
     47            }); 
     48            request.transport.abort(); 
     49            document.getElementById('send_sync').value += 'other processing\n'; 
     50        } 
     51 
     52    </script> 
     53  </head> 
     54  <body > 
     55    <div class="buttons"> 
     56        <button onclick="sendSynchronous()">Send an synchronous Ajax request</button><br /> 
     57        <button onclick="sendAsynchronous()">Send an asynchronous Ajax request</button><br /> 
     58        <button onclick="sendAndAbort()">Send a request and abort it</button><br /> 
     59        <textarea id="send_sync" rows="6"></textarea><br /> 
     60        <button onclick="document.getElementById('send_sync').value = ''">Clear</button> 
     61    </div> 
     62    <p><b></b></p> 
     63    <p>Clicking on the different buttons should give the following results in the textarea below :</p> 
     64    <ul> 
     65      <li>"other processing" then "request completed"</li> 
     66      <li>"request completed" then "other processing"</li> 
     67      <li>"request aborted" then "other processing"</li> 
     68    </ul> 
     69  </body> 
     70</html> 
  • lib/OpenLayers/Ajax.js

    old new  
    135135     */ 
    136136    getTransport: function() { 
    137137        return OpenLayers.Util.Try( 
     138            function() {return new XMLHttpRequest();}, 
    138139            function() {return new ActiveXObject('Msxml2.XMLHTTP');}, 
    139             function() {return new ActiveXObject('Microsoft.XMLHTTP');}, 
    140             function() {return new XMLHttpRequest();} 
     140            function() {return new ActiveXObject('Microsoft.XMLHTTP');} 
    141141        ) || false; 
    142142    }, 
    143143 
     
    167167     * responderToAdd - {?} 
    168168     */ 
    169169    register: function(responderToAdd) { 
    170       for (var i = 0; i < this.responders.length; i++){ 
    171           if (responderToAdd == this.responders[i]){ 
    172               return; 
    173          
    174      
    175       this.responders.push(responderToAdd); 
     170        for (var i = 0; i < this.responders.length; i++){ 
     171            if (responderToAdd == this.responders[i]){ 
     172                return; 
     173           
     174       
     175        this.responders.push(responderToAdd); 
    176176    }, 
    177177 
    178178    /** 
     179     * Method: unregister 
     180     *   
     181     * Parameters: 
     182     * responderToRemove - {?} 
     183     */ 
     184    unregister: function(responderToRemove) { 
     185        OpenLayers.Util.removeItem(this.reponders, responderToRemove); 
     186    }, 
     187 
     188    /** 
    179189     * Method: dispatch 
    180190     *  
    181191     * Parameters: 
    182192     * callback - {?} 
    183193     * request - {?} 
    184194     * transport - {?} 
    185      * json - {?} 
    186195     */ 
    187     dispatch: function(callback, request, transport, json) { 
     196    dispatch: function(callback, request, transport) { 
    188197        var responder; 
    189198        for (var i = 0; i < this.responders.length; i++) { 
    190199            responder = this.responders[i]; 
     
    193202                typeof responder[callback] == 'function') { 
    194203                try { 
    195204                    responder[callback].apply(responder,  
    196                                               [request, transport, json]); 
     205                                              [request, transport]); 
    197206                } catch (e) {} 
    198207            } 
    199208        } 
     
    217226}); 
    218227 
    219228/** 
    220  * Namespace: OpenLayers.Ajax.Base 
    221  * {Object} 
     229 * Class: OpenLayers.Ajax.Base 
    222230 */ 
    223 OpenLayers.Ajax.Base = function() {}; 
    224 OpenLayers.Ajax.Base.prototype = { 
    225  
     231OpenLayers.Ajax.Base = OpenLayers.Class({ 
     232       
    226233    /** 
    227      * Function: setOptions 
     234     * Constructor: OpenLayers.Ajax.Base 
    228235     *  
    229      * Parameters: 
     236     * Parameters:  
    230237     * options - {Object} 
    231238     */ 
    232     setOptions: function(options) { 
     239    initialize: function(options) { 
    233240        this.options = { 
    234             'method': 'post', 
    235             'asynchronous': true, 
    236             'parameters': '' 
     241            method:       'post', 
     242            asynchronous: true, 
     243            contentType:  'application/x-www-form-urlencoded', 
     244            encoding:     'UTF-8', 
     245            parameters:   '' 
    237246        }; 
    238247        OpenLayers.Util.extend(this.options, options || {}); 
    239     }, 
    240  
    241     /** 
    242      * Function: responseIsSuccess 
    243      *  
    244      * Returns: 
    245      * {Boolean} 
    246      */ 
    247     responseIsSuccess: function() { 
    248         return this.transport.status == undefined ||  
    249                this.transport.status == 0 ||  
    250                (this.transport.status >= 200 && this.transport.status < 300); 
    251     }, 
    252  
    253     /** 
    254      * Function: responseIsFailure 
    255      *  
    256      * Returns: 
    257      * {Boolean} 
    258      */ 
    259     responseIsFailure: function() { 
    260         return !this.responseIsSuccess(); 
     248         
     249        this.options.method = this.options.method.toLowerCase(); 
     250         
     251        if (typeof this.options.parameters == 'string') { 
     252            this.options.parameters =  
     253                OpenLayers.Util.getParameters(this.options.parameters); 
     254        } 
    261255    } 
    262 }
     256})
    263257 
    264  
    265258/** 
    266259 * Class: OpenLayers.Ajax.Request 
    267260 * 
     
    269262 *  - <OpenLayers.Ajax.Base> 
    270263 */ 
    271264OpenLayers.Ajax.Request = OpenLayers.Class(OpenLayers.Ajax.Base, { 
     265 
     266    /** 
     267     * Property: _complete 
     268     * 
     269     * {Boolean} 
     270     */ 
     271    _complete: false, 
    272272       
    273       /** 
    274        * Constructor: OpenLayers.Ajax.Request 
    275        *  
    276        * Parameters:  
    277        * url - {String} 
    278        * options - {Object} 
    279        */ 
     273    /** 
     274     * Constructor: OpenLayers.Ajax.Request 
     275     *  
     276     * Parameters:  
     277     * url - {String} 
     278     * options - {Object} 
     279     */ 
    280280    initialize: function(url, options) { 
     281        OpenLayers.Ajax.Base.prototype.initialize.apply(this, [options]); 
     282         
    281283        this.transport = OpenLayers.Ajax.getTransport(); 
    282         this.setOptions(options); 
    283284        this.request(url); 
    284285    }, 
    285286 
     
    290291     * url - {String} 
    291292     */ 
    292293    request: function(url) { 
    293         var parameters = this.options.parameters || ''; 
    294         if (parameters.length > 0) { 
    295             parameters += '&_='; 
     294        this.url = url; 
     295        this.method = this.options.method; 
     296        var params = OpenLayers.Util.extend({}, this.options.parameters); 
     297         
     298        if (this.method != 'get' && this.method != 'post') { 
     299            // simulate other verbs over post 
     300            params['_method'] = this.method; 
     301            this.method = 'post'; 
    296302        } 
     303 
     304        this.parameters = params;         
     305         
     306        if (params = OpenLayers.Util.getParameterString(params)) { 
     307            // when GET, append parameters to URL 
     308            if (this.method == 'get') { 
     309                this.url += ((this.url.indexOf('?') > -1) ? '&' : '?') + params; 
     310            } else if (/Konqueror|Safari|KHTML/.test(navigator.userAgent)) { 
     311                params += '&_='; 
     312            } 
     313        } 
    297314        try { 
    298             this.url = url
    299             if (this.options.method == 'get' && parameters.length > 0) { 
    300                this.url += (this.url.match(/\?/) ? '&' : '?') + parameters
     315            var response = new OpenLayers.Ajax.Response(this)
     316            if (this.options.onCreate) { 
     317                this.options.onCreate(response)
    301318            } 
    302319             
    303320            OpenLayers.Ajax.Responders.dispatch('onCreate',  
    304321                                                this,  
    305                                                 this.transport); 
     322                                                response); 
    306323     
    307             this.transport.open(this.options.method,  
     324            this.transport.open(this.method.toUpperCase(),  
    308325                                this.url, 
    309326                                this.options.asynchronous); 
    310327     
    311328            if (this.options.asynchronous) { 
    312                 setTimeout(OpenLayers.Function.bind
    313                     (function() {this.respondToReadyState(1);}),this), 10 
    314                 ); 
     329                window.setTimeout
     330                    OpenLayers.Function.bind(this.respondToReadyState, this, 1), 
     331                    10); 
    315332            } 
    316333             
    317334            this.transport.onreadystatechange =  
    318335                OpenLayers.Function.bind(this.onStateChange, this);     
    319336            this.setRequestHeaders(); 
    320337     
    321             var body = this.options.postBody ? this.options.postBody  
    322                                              : parameters
    323             this.transport.send(this.options.method == 'post' ? body : null); 
     338            this.body =  this.method == 'post' ? 
     339                (this.options.postBody || params) : null
     340            this.transport.send(this.body); 
    324341     
    325342            // Force Firefox to handle ready state 4 for synchronous requests 
    326343            if (!this.options.asynchronous &&  
    327344                this.transport.overrideMimeType) { 
    328                  
    329345                this.onStateChange(); 
    330346            } 
    331      
    332347        } catch (e) { 
    333348            this.dispatchException(e); 
    334349        } 
    335350    }, 
     351 
     352    /** 
     353     * Method: onStateChange 
     354     */ 
     355    onStateChange: function() { 
     356        var readyState = this.transport.readyState; 
     357        if (readyState > 1 && !((readyState == 4) && this._complete)) { 
     358            this.respondToReadyState(this.transport.readyState); 
     359        } 
     360    }, 
    336361      
    337362    /** 
    338363     * Method: setRequestHeaders 
    339364     */ 
    340365    setRequestHeaders: function() { 
    341         var requestHeaders = [ 
    342             'X-Requested-With', 
    343             'XMLHttpRequest', 
    344             'X-Prototype-Version', 
    345             'OpenLayers' 
    346         ]; 
     366        var headers = { 
     367            'X-Requested-With': 'XMLHttpRequest', 
     368            'Accept': 'text/javascript, text/html, application/xml, text/xml, */*', 
     369            'OpenLayers': true 
     370        }; 
     371 
     372        if (this.method == 'post') { 
     373            headers['Content-type'] = this.options.contentType + 
     374                (this.options.encoding ? '; charset=' + this.options.encoding : ''); 
    347375     
    348         if (this.options.method == 'post' && !this.options.postBody) { 
    349             requestHeaders.push('Content-type', 
    350                                 'application/x-www-form-urlencoded'); 
    351      
    352             // Force "Connection: close" for Mozilla browsers to work around 
    353             // a bug where XMLHttpReqeuest sends an incorrect Content-length 
    354             // header. See Mozilla Bugzilla #246651. 
    355             if (this.transport.overrideMimeType) { 
    356                 requestHeaders.push('Connection', 'close'); 
     376            /* Force "Connection: close" for older Mozilla browsers to work 
     377             * around a bug where XMLHttpRequest sends an incorrect 
     378             * Content-length header. See Mozilla Bugzilla #246651. 
     379             */ 
     380            if (this.transport.overrideMimeType && 
     381                (navigator.userAgent.match(/Gecko\/(\d{4})/) || [0,2005])[1] < 2005) { 
     382                headers['Connection'] = 'close'; 
    357383            } 
    358384        } 
    359      
    360         if (this.options.requestHeaders) { 
    361             requestHeaders.push.apply(requestHeaders,  
    362                                       this.options.requestHeaders); 
     385        // user-defined headers 
     386        if (typeof this.options.requestHeaders == 'object') {     
     387            var extras = this.options.requestHeaders; 
     388             
     389            if (typeof extra.push == 'function') { 
     390                for (var i = 0, length = extras.length; i < length; i += 2) { 
     391                    headers[extras[i]] = extras[i+1]; 
     392                } 
     393            } else { 
     394                for (var i in extras) { 
     395                    headers[i] = pair[i]; 
     396                } 
     397            } 
    363398        } 
    364            
    365         for (var i = 0; i < requestHeaders.length; i += 2) { 
    366             this.transport.setRequestHeader(requestHeaders[i],  
    367                                             requestHeaders[i+1]); 
     399         
     400        for (var name in headers) { 
     401            this.transport.setRequestHeader(name, headers[name]); 
    368402        } 
    369403    }, 
    370  
     404     
    371405    /** 
    372      * Method: onStateChange 
    373      */ 
    374     onStateChange: function() { 
    375         var readyState = this.transport.readyState; 
    376         if (readyState != 1) { 
    377           this.respondToReadyState(this.transport.readyState); 
    378         } 
    379     }, 
    380  
    381     /**  
    382      * Method: header 
    383      *  
     406     * Method: success 
     407     * 
    384408     * Returns: 
    385      * {?} 
     409     * {Boolean} -  
    386410     */ 
    387     header: function(name) { 
    388         try { 
    389             return this.transport.getResponseHeader(name); 
    390         } catch (e) {} 
     411    success: function() { 
     412        var status = this.getStatus(); 
     413        return !status || (status >=200 && status < 300); 
    391414    }, 
    392  
    393     /**  
    394      * Method: evalJSON 
    395      *  
     415     
     416    /** 
     417     * Method: getStatus 
     418     * 
    396419     * Returns: 
    397      * {?} 
     420     * {Integer} - Status 
    398421     */ 
    399     evalJSON: function() { 
     422    getStatus: function() { 
    400423        try { 
    401             return eval(this.header('X-JSON')); 
    402         } catch (e) {} 
    403     }, 
    404  
    405     /** 
    406      * Method: evalResponse 
    407      *  
    408      * Returns:  
    409      * {?} 
    410      */ 
    411     evalResponse: function() { 
    412         try { 
    413             return eval(this.transport.responseText); 
     424            return this.transport.status || 0; 
    414425        } catch (e) { 
    415             this.dispatchException(e); 
     426            return 0 
    416427        } 
    417428    }, 
    418429 
     
    423434     * readyState - {?} 
    424435     */ 
    425436    respondToReadyState: function(readyState) { 
    426         var event = OpenLayers.Ajax.Request.Events[readyState]; 
    427         var transport = this.transport, json = this.evalJSON(); 
     437        var state = OpenLayers.Ajax.Request.Events[readyState]; 
     438        var response = new OpenLayers.Ajax.Response(this); 
    428439     
    429         if (event == 'Complete') { 
     440        if (state == 'Complete') { 
    430441            try { 
    431                 var responseSuccess = this.responseIsSuccess() ? 'Success' 
    432                                                                 : 'Failure'; 
    433                                                                   
    434                 (this.options['on' + this.transport.status] || 
    435                  this.options['on' + responseSuccess] || 
    436                  OpenLayers.Ajax.emptyFunction)(transport, json); 
     442                this._complete = true; 
     443                (this.options['on' + response.status] || 
     444                    this.options['on' + (this.success() ? 'Success' : 'Failure')] || 
     445                    OpenLayers.Ajax.emptyFunction)(response); 
    437446            } catch (e) { 
    438447                this.dispatchException(e); 
    439448            } 
    440449     
    441             var contentType = this.header('Content-type') || ''; 
    442             if (contentType.match(/^text\/javascript/i)) { 
    443                 this.evalResponse(); 
    444             } 
     450            var contentType = response.getHeader('Content-type'); 
    445451        } 
    446452     
    447453        try { 
    448             (this.options['on' + event] ||  
    449              OpenLayers.Ajax.emptyFunction)(transport, json); 
    450              OpenLayers.Ajax.Responders.dispatch('on' + event,  
     454            (this.options['on' + state] ||  
     455             OpenLayers.Ajax.emptyFunction)(response); 
     456             OpenLayers.Ajax.Responders.dispatch('on' + state,  
    451457                                                 this,  
    452                                                  transport,  
    453                                                  json); 
     458                                                 response); 
    454459        } catch (e) { 
    455460            this.dispatchException(e); 
    456461        } 
    457462     
    458         // Avoid memory leak in MSIE: clean up the oncomplete event handler 
    459         if (event == 'Complete') { 
     463        if (state == 'Complete') { 
     464            // avoid memory leak in MSIE: clean up 
    460465            this.transport.onreadystatechange = OpenLayers.Ajax.emptyFunction; 
    461466        } 
    462467    }, 
     468     
     469    /** 
     470     * Method: getHeader 
     471     *  
     472     * Parameters: 
     473     * name - {String} Header name 
     474     * 
     475     * Returns: 
     476     * {?} - response header for the given name 
     477     */ 
     478    getHeader: function(name) { 
     479        try { 
     480            return this.transport.getResponseHeader(name); 
     481        } catch (e) { 
     482            return null 
     483        } 
     484    }, 
    463485 
    464486    /** 
    465487     * Method: dispatchException 
     
    468490     * exception - {?} 
    469491     */ 
    470492    dispatchException: function(exception) { 
    471         if (this.options.onException) { 
    472             this.options.onException(this, exception); 
    473         } else { 
    474             // if we get here, Responders.dispatch('onException') will never 
    475             // be called. too bad. we should probably take out the Responders 
    476             // stuff anyway. 
    477             throw exception; 
    478         } 
     493        (this.options.onException || 
     494            OpenLayers.Ajax.emptyFunction)(this, exception); 
    479495        OpenLayers.Ajax.Responders.dispatch('onException', this, exception); 
    480496    } 
    481      
    482497}); 
    483498 
    484499/**  
     
    489504  ['Uninitialized', 'Loading', 'Loaded', 'Interactive', 'Complete']; 
    490505 
    491506/** 
     507 * Class: OpenLayers.Ajax.Request 
     508 * 
     509 * Inherit: 
     510 *  - <OpenLayers.Ajax.Base> 
     511 */ 
     512OpenLayers.Ajax.Response = OpenLayers.Class({ 
     513 
     514    /** 
     515     * Property: status 
     516     * 
     517     * {Integer} 
     518     */ 
     519    status: 0, 
     520     
     521 
     522    /** 
     523     * Property: statusText 
     524     * 
     525     * {String} 
     526     */ 
     527    statusText: '', 
     528       
     529    /** 
     530     * Constructor: OpenLayers.Ajax.Response 
     531     *  
     532     * Parameters:  
     533     * request - {Object} 
     534     */ 
     535    initialize: function(request) { 
     536        this.request = request; 
     537        var transport = this.transport = request.transport, 
     538            readyState = this.readyState = transport.readyState; 
     539         
     540        if ((readyState > 2 && 
     541            !(!!(window.attachEvent && !window.opera))) || 
     542            readyState == 4) { 
     543            this.status       = this.getStatus(); 
     544            this.statusText   = this.getStatusText(); 
     545            this.responseText = transport.responseText == null ? 
     546                '' : String(transport.responseText); 
     547        } 
     548         
     549        if(readyState == 4) { 
     550            var xml = transport.responseXML; 
     551            this.responseXML  = xml === undefined ? null : xml; 
     552        } 
     553    }, 
     554     
     555    /** 
     556     * Method: getStatus 
     557     */ 
     558    getStatus: OpenLayers.Ajax.Request.prototype.getStatus, 
     559     
     560    /** 
     561     * Method: getStatustext 
     562     * 
     563     * Returns: 
     564     * {String} - statusText 
     565     */ 
     566    getStatusText: function() { 
     567        try { 
     568            return this.transport.statusText || ''; 
     569        } catch (e) { 
     570            return ''; 
     571        } 
     572    }, 
     573     
     574    /** 
     575     * Method: getHeader 
     576     */ 
     577    getHeader: OpenLayers.Ajax.Request.prototype.getHeader, 
     578     
     579    /**  
     580     * Method: getResponseHeader 
     581     * 
     582     * Returns: 
     583     * {?} - response header for given name 
     584     */ 
     585    getResponseHeader: function(name) { 
     586        return this.transport.getResponseHeader(name); 
     587    } 
     588}); 
     589 
     590 
     591/** 
    492592 * Function: getElementsByTagNameNS 
    493593 *  
    494594 * Parameters: