define("dojo/request/script", [ 'module', './watch', './util', '../_base/array', '../_base/lang', '../on', '../dom', '../dom-construct', '../has', '../_base/window'/*=====, '../request', '../_base/declare' =====*/ ], function(module, watch, util, array, lang, on, dom, domConstruct, has, win/*=====, request, declare =====*/){ has.add('script-readystatechange', function(global, document){ var script = document.createElement('script'); return typeof script['onreadystatechange'] !== 'undefined' && (typeof global['opera'] === 'undefined' || global['opera'].toString() !== '[object Opera]'); }); var mid = module.id.replace(/[\/\.\-]/g, '_'), counter = 0, loadEvent = has('script-readystatechange') ? 'readystatechange' : 'load', readyRegExp = /complete|loaded/, callbacks = this[mid + '_callbacks'] = {}, deadScripts = []; function attach(id, url, frameDoc){ var doc = (frameDoc || win.doc), element = doc.createElement('script'); element.type = 'text/javascript'; element.src = url; element.id = id; element.async = true; element.charset = 'utf-8'; return doc.getElementsByTagName('head')[0].appendChild(element); } function remove(id, frameDoc, cleanup){ domConstruct.destroy(dom.byId(id, frameDoc)); if(callbacks[id]){ if(cleanup){ // set callback to a function that deletes itself so requests that // are in-flight don't error out when returning and also // clean up after themselves callbacks[id] = function(){ delete callbacks[id]; }; }else{ delete callbacks[id]; } } } function _addDeadScript(dfd){ // Be sure to check ioArgs because it can dynamically change in the dojox/io plugins. // See http://bugs.dojotoolkit.org/ticket/15890. var options = dfd.response.options, frameDoc = options.ioArgs ? options.ioArgs.frameDoc : options.frameDoc; deadScripts.push({ id: dfd.id, frameDoc: frameDoc }); if(options.ioArgs){ options.ioArgs.frameDoc = null; } options.frameDoc = null; } function canceler(dfd, response){ if(dfd.canDelete){ //For timeouts and cancels, remove the script element immediately to //avoid a response from it coming back later and causing trouble. script._remove(dfd.id, response.options.frameDoc, true); } } function isValid(response){ //Do script cleanup here. We wait for one inflight pass //to make sure we don't get any weird things by trying to remove a script //tag that is part of the call chain (IE 6 has been known to //crash in that case). if(deadScripts && deadScripts.length){ array.forEach(deadScripts, function(_script){ script._remove(_script.id, _script.frameDoc); _script.frameDoc = null; }); deadScripts = []; } return response.options.jsonp ? !response.data : true; } function isReadyScript(response){ return !!this.scriptLoaded; } function isReadyCheckString(response){ var checkString = response.options.checkString; return checkString && eval('typeof(' + checkString + ') !== "undefined"'); } function handleResponse(response, error){ if(this.canDelete){ _addDeadScript(this); } if(error){ this.reject(error); }else{ this.resolve(response); } } function script(url, options, returnDeferred){ var response = util.parseArgs(url, util.deepCopy({}, options)); url = response.url; options = response.options; var dfd = util.deferred( response, canceler, isValid, options.jsonp ? null : (options.checkString ? isReadyCheckString : isReadyScript), handleResponse ); lang.mixin(dfd, { id: mid + (counter++), canDelete: false }); if(options.jsonp){ var queryParameter = new RegExp('[?&]' + options.jsonp + '='); if(!queryParameter.test(url)){ url += queryParameter + (options.frameDoc ? 'parent.' : '') + mid + '_callbacks.' + dfd.id; } dfd.canDelete = true; callbacks[dfd.id] = function(json){ response.data = json; dfd.handleResponse(response); }; } if(util.notify){ util.notify.emit('send', response, dfd.promise.cancel); } if(!options.canAttach || options.canAttach(dfd)){ var node = script._attach(dfd.id, url, options.frameDoc); if(!options.jsonp && !options.checkString){ var handle = on(node, loadEvent, function(evt){ if(evt.type === 'load' || readyRegExp.test(node.readyState)){ handle.remove(); dfd.scriptLoaded = evt; } }); } } watch(dfd); return returnDeferred ? dfd : dfd.promise; } script.get = script; /*===== script = function(url, options){ // summary: // Sends a request using a script element with the given URL and options. // url: String // URL to request // options: dojo/request/script.__Options? // Options for the request. // returns: dojo/request.__Promise }; script.__BaseOptions = declare(request.__BaseOptions, { // jsonp: String? // The URL parameter name that indicates the JSONP callback string. // For instance, when using Yahoo JSONP calls it is normally, // jsonp: "callback". For AOL JSONP calls it is normally // jsonp: "c". // checkString: String? // A string of JavaScript that when evaluated like so: // "typeof(" + checkString + ") != 'undefined'" // being true means that the script fetched has been loaded. // Do not use this if doing a JSONP type of call (use `jsonp` instead). // frameDoc: Document? // The Document object of a child iframe. If this is passed in, the script // will be attached to that document. This can be helpful in some comet long-polling // scenarios with Firefox and Opera. }); script.__MethodOptions = declare(null, { // method: String? // This option is ignored. All requests using this transport are // GET requests. }); script.__Options = declare([script.__BaseOptions, script.__MethodOptions]); script.get = function(url, options){ // summary: // Send an HTTP GET request using a script element with the given URL and options. // url: String // URL to request // options: dojo/request/script.__BaseOptions? // Options for the request. // returns: dojo/request.__Promise }; =====*/ // TODO: Remove in 2.0 script._attach = attach; script._remove = remove; script._callbacksProperty = mid + '_callbacks'; return script; });