[ Index ] |
PHP Cross Reference of MediaWiki-1.24.0 |
[Summary view] [Print] [Text view]
1 /*! 2 * MockJax - jQuery Plugin to Mock Ajax requests 3 * 4 * Version: 1.4.0 5 * Released: 2011-02-04 6 * Source: http://github.com/appendto/jquery-mockjax 7 * Docs: http://enterprisejquery.com/2010/07/mock-your-ajax-requests-with-mockjax-for-rapid-development 8 * Plugin: mockjax 9 * Author: Jonathan Sharp (http://jdsharp.com) 10 * License: MIT,GPL 11 * 12 * Copyright (c) 2010 appendTo LLC. 13 * Dual licensed under the MIT or GPL licenses. 14 * http://appendto.com/open-source-licenses 15 */ 16 (function($) { 17 var _ajax = $.ajax, 18 mockHandlers = []; 19 20 function parseXML(xml) { 21 if ( window['DOMParser'] == undefined && window.ActiveXObject ) { 22 DOMParser = function() { }; 23 DOMParser.prototype.parseFromString = function( xmlString ) { 24 var doc = new ActiveXObject('Microsoft.XMLDOM'); 25 doc.async = 'false'; 26 doc.loadXML( xmlString ); 27 return doc; 28 }; 29 } 30 31 try { 32 var xmlDoc = ( new DOMParser() ).parseFromString( xml, 'text/xml' ); 33 if ( $.isXMLDoc( xmlDoc ) ) { 34 var err = $('parsererror', xmlDoc); 35 if ( err.length == 1 ) { 36 throw('Error: ' + $(xmlDoc).text() ); 37 } 38 } else { 39 throw('Unable to parse XML'); 40 } 41 } catch( e ) { 42 var msg = ( e.name == undefined ? e : e.name + ': ' + e.message ); 43 $(document).trigger('xmlParseError', [ msg ]); 44 return undefined; 45 } 46 return xmlDoc; 47 } 48 49 $.extend({ 50 ajax: function(origSettings) { 51 var s = jQuery.extend(true, {}, jQuery.ajaxSettings, origSettings), 52 mock = false; 53 // Iterate over our mock handlers (in registration order) until we find 54 // one that is willing to intercept the request 55 $.each(mockHandlers, function(k, v) { 56 if ( !mockHandlers[k] ) { 57 return; 58 } 59 var m = null; 60 // If the mock was registered with a function, let the function decide if we 61 // want to mock this request 62 if ( $.isFunction(mockHandlers[k]) ) { 63 m = mockHandlers[k](s); 64 } else { 65 m = mockHandlers[k]; 66 // Inspect the URL of the request and check if the mock handler's url 67 // matches the url for this ajax request 68 if ( $.isFunction(m.url.test) ) { 69 // The user provided a regex for the url, test it 70 if ( !m.url.test( s.url ) ) { 71 m = null; 72 } 73 } else { 74 // Look for a simple wildcard '*' or a direct URL match 75 var star = m.url.indexOf('*'); 76 if ( ( m.url != '*' && m.url != s.url && star == -1 ) || 77 ( star > -1 && m.url.substr(0, star) != s.url.substr(0, star) ) ) { 78 // The url we tested did not match the wildcard * 79 m = null; 80 } 81 } 82 if ( m ) { 83 // Inspect the data submitted in the request (either POST body or GET query string) 84 if ( m.data && s.data ) { 85 var identical = false; 86 // Deep inspect the identity of the objects 87 (function ident(mock, live) { 88 // Test for situations where the data is a querystring (not an object) 89 if (typeof live === 'string') { 90 // Querystring may be a regex 91 identical = $.isFunction( mock.test ) ? mock.test(live) : mock == live; 92 return identical; 93 } 94 $.each(mock, function(k, v) { 95 if ( live[k] === undefined ) { 96 identical = false; 97 return false; 98 } else { 99 identical = true; 100 if ( typeof live[k] == 'object' ) { 101 return ident(mock[k], live[k]); 102 } else { 103 if ( $.isFunction( mock[k].test ) ) { 104 identical = mock[k].test(live[k]); 105 } else { 106 identical = ( mock[k] == live[k] ); 107 } 108 return identical; 109 } 110 } 111 }); 112 })(m.data, s.data); 113 // They're not identical, do not mock this request 114 if ( identical == false ) { 115 m = null; 116 } 117 } 118 // Inspect the request type 119 if ( m && m.type && m.type != s.type ) { 120 // The request type doesn't match (GET vs. POST) 121 m = null; 122 } 123 } 124 } 125 if ( m ) { 126 mock = true; 127 128 // Handle console logging 129 var c = $.extend({}, $.mockjaxSettings, m); 130 if ( c.log && $.isFunction(c.log) ) { 131 c.log('MOCK ' + s.type.toUpperCase() + ': ' + s.url, $.extend({}, s)); 132 } 133 134 var jsre = /=\?(&|$)/, jsc = (new Date()).getTime(); 135 136 // Handle JSONP Parameter Callbacks, we need to replicate some of the jQuery core here 137 // because there isn't an easy hook for the cross domain script tag of jsonp 138 if ( s.dataType === "jsonp" ) { 139 if ( s.type.toUpperCase() === "GET" ) { 140 if ( !jsre.test( s.url ) ) { 141 s.url += (rquery.test( s.url ) ? "&" : "?") + (s.jsonp || "callback") + "=?"; 142 } 143 } else if ( !s.data || !jsre.test(s.data) ) { 144 s.data = (s.data ? s.data + "&" : "") + (s.jsonp || "callback") + "=?"; 145 } 146 s.dataType = "json"; 147 } 148 149 // Build temporary JSONP function 150 if ( s.dataType === "json" && (s.data && jsre.test(s.data) || jsre.test(s.url)) ) { 151 jsonp = s.jsonpCallback || ("jsonp" + jsc++); 152 153 // Replace the =? sequence both in the query string and the data 154 if ( s.data ) { 155 s.data = (s.data + "").replace(jsre, "=" + jsonp + "$1"); 156 } 157 158 s.url = s.url.replace(jsre, "=" + jsonp + "$1"); 159 160 // We need to make sure 161 // that a JSONP style response is executed properly 162 s.dataType = "script"; 163 164 // Handle JSONP-style loading 165 window[ jsonp ] = window[ jsonp ] || function( tmp ) { 166 data = tmp; 167 success(); 168 complete(); 169 // Garbage collect 170 window[ jsonp ] = undefined; 171 172 try { 173 delete window[ jsonp ]; 174 } catch(e) {} 175 176 if ( head ) { 177 head.removeChild( script ); 178 } 179 }; 180 } 181 182 var rurl = /^(\w+:)?\/\/([^\/?#]+)/, 183 parts = rurl.exec( s.url ), 184 remote = parts && (parts[1] && parts[1] !== location.protocol || parts[2] !== location.host); 185 186 // Test if we are going to create a script tag (if so, intercept & mock) 187 if ( s.dataType === "script" && s.type.toUpperCase() === "GET" && remote ) { 188 // Synthesize the mock request for adding a script tag 189 var callbackContext = origSettings && origSettings.context || s; 190 191 function success() { 192 // If a local callback was specified, fire it and pass it the data 193 if ( s.success ) { 194 s.success.call( callbackContext, ( m.response ? m.response.toString() : m.responseText || ''), status, {} ); 195 } 196 197 // Fire the global callback 198 if ( s.global ) { 199 trigger( "ajaxSuccess", [{}, s] ); 200 } 201 } 202 203 function complete() { 204 // Process result 205 if ( s.complete ) { 206 s.complete.call( callbackContext, {} , status ); 207 } 208 209 // The request was completed 210 if ( s.global ) { 211 trigger( "ajaxComplete", [{}, s] ); 212 } 213 214 // Handle the global AJAX counter 215 if ( s.global && ! --jQuery.active ) { 216 jQuery.event.trigger( "ajaxStop" ); 217 } 218 } 219 220 function trigger(type, args) { 221 (s.context ? jQuery(s.context) : jQuery.event).trigger(type, args); 222 } 223 224 if ( m.response && $.isFunction(m.response) ) { 225 m.response(origSettings); 226 } else { 227 $.globalEval(m.responseText); 228 } 229 success(); 230 complete(); 231 return false; 232 } 233 mock = _ajax.call($, $.extend(true, {}, origSettings, { 234 // Mock the XHR object 235 xhr: function() { 236 // Extend with our default mockjax settings 237 m = $.extend({}, $.mockjaxSettings, m); 238 239 if ( m.contentType ) { 240 m.headers['content-type'] = m.contentType; 241 } 242 243 // Return our mock xhr object 244 return { 245 status: m.status, 246 readyState: 1, 247 open: function() { }, 248 send: function() { 249 // This is a substitute for < 1.4 which lacks $.proxy 250 var process = (function(that) { 251 return function() { 252 return (function() { 253 // The request has returned 254 this.status = m.status; 255 this.readyState = 4; 256 257 // We have an executable function, call it to give 258 // the mock handler a chance to update it's data 259 if ( $.isFunction(m.response) ) { 260 m.response(origSettings); 261 } 262 // Copy over our mock to our xhr object before passing control back to 263 // jQuery's onreadystatechange callback 264 if ( s.dataType == 'json' && ( typeof m.responseText == 'object' ) ) { 265 this.responseText = JSON.stringify(m.responseText); 266 } else if ( s.dataType == 'xml' ) { 267 if ( typeof m.responseXML == 'string' ) { 268 this.responseXML = parseXML(m.responseXML); 269 } else { 270 this.responseXML = m.responseXML; 271 } 272 } else { 273 this.responseText = m.responseText; 274 } 275 // jQuery < 1.4 doesn't have onreadystate change for xhr 276 if ( $.isFunction(this.onreadystatechange) ) { 277 this.onreadystatechange( m.isTimeout ? 'timeout' : undefined ); 278 } 279 }).apply(that); 280 }; 281 })(this); 282 283 if ( m.proxy ) { 284 // We're proxying this request and loading in an external file instead 285 _ajax({ 286 global: false, 287 url: m.proxy, 288 type: m.proxyType, 289 data: m.data, 290 dataType: s.dataType, 291 complete: function(xhr, txt) { 292 m.responseXML = xhr.responseXML; 293 m.responseText = xhr.responseText; 294 this.responseTimer = setTimeout(process, m.responseTime || 0); 295 } 296 }); 297 } else { 298 // type == 'POST' || 'GET' || 'DELETE' 299 if ( s.async === false ) { 300 // TODO: Blocking delay 301 process(); 302 } else { 303 this.responseTimer = setTimeout(process, m.responseTime || 50); 304 } 305 } 306 }, 307 abort: function() { 308 clearTimeout(this.responseTimer); 309 }, 310 setRequestHeader: function() { }, 311 getResponseHeader: function(header) { 312 // 'Last-modified', 'Etag', 'content-type' are all checked by jQuery 313 if ( m.headers && m.headers[header] ) { 314 // Return arbitrary headers 315 return m.headers[header]; 316 } else if ( header.toLowerCase() == 'last-modified' ) { 317 return m.lastModified || (new Date()).toString(); 318 } else if ( header.toLowerCase() == 'etag' ) { 319 return m.etag || ''; 320 } else if ( header.toLowerCase() == 'content-type' ) { 321 return m.contentType || 'text/plain'; 322 } 323 }, 324 getAllResponseHeaders: function() { 325 var headers = ''; 326 $.each(m.headers, function(k, v) { 327 headers += k + ': ' + v + "\n"; 328 }); 329 return headers; 330 } 331 }; 332 } 333 })); 334 return false; 335 } 336 }); 337 // We don't have a mock request, trigger a normal request 338 if ( !mock ) { 339 return _ajax.apply($, arguments); 340 } else { 341 return mock; 342 } 343 } 344 }); 345 346 $.mockjaxSettings = { 347 //url: null, 348 //type: 'GET', 349 log: function(msg) { 350 window['console'] && window.console.log && window.console.log(msg); 351 }, 352 status: 200, 353 responseTime: 500, 354 isTimeout: false, 355 contentType: 'text/plain', 356 response: '', 357 responseText: '', 358 responseXML: '', 359 proxy: '', 360 proxyType: 'GET', 361 362 lastModified: null, 363 etag: '', 364 headers: { 365 etag: 'IJF@H#@923uf8023hFO@I#H#', 366 'content-type' : 'text/plain' 367 } 368 }; 369 370 $.mockjax = function(settings) { 371 var i = mockHandlers.length; 372 mockHandlers[i] = settings; 373 return i; 374 }; 375 $.mockjaxClear = function(i) { 376 if ( arguments.length == 1 ) { 377 mockHandlers[i] = null; 378 } else { 379 mockHandlers = []; 380 } 381 }; 382 })(jQuery);
title
Description
Body
title
Description
Body
title
Description
Body
title
Body
Generated: Fri Nov 28 14:03:12 2014 | Cross-referenced by PHPXref 0.7.1 |