1 if(!dojo._hasResource["dojo.io.script"]){ //_hasResource checks added by build. Do not use _hasResource directly in your code.
2 dojo._hasResource["dojo.io.script"] = true;
3 dojo.provide("dojo.io.script");
6 dojo.io.script.__ioArgs = function(kwArgs){
8 // All the properties described in the dojo.__ioArgs type, apply to this
9 // type as well, EXCEPT "handleAs". It is not applicable to
10 // dojo.io.script.get() calls, since it is implied by the usage of
11 // "callbackParamName" (response will be a JSONP call returning JSON)
12 // or "checkString" (response is pure JavaScript defined in
13 // the body of the script that was attached). The following additional
14 // properties are allowed for dojo.io.script.get():
15 // callbackParamName: String
16 // The URL parameter name that indicates the JSONP callback string.
17 // For instance, when using Yahoo JSONP calls it is normally,
18 // callbackParamName: "callback". For AOL JSONP calls it is normally
19 // callbackParamName: "c".
20 // checkString: String
21 // A string of JavaScript that when evaluated like so:
22 // "typeof(" + checkString + ") != 'undefined'"
23 // being true means that the script fetched has been loaded.
24 // Do not use this if doing a JSONP type of call (use callbackParamName instead).
25 // frameDoc: Document.
26 // The Document object for a child iframe. If this is passed in, the script
27 // will be attached to that document. This can be helpful in some comet long-polling
28 // scenarios with Firefox and Opera.
33 get: function(/*dojo.io.script.__ioArgs*/args){
35 // sends a get request using a dynamically created script tag.
36 var dfd = this._makeScriptDeferred(args);
37 var ioArgs = dfd.ioArgs;
38 dojo._ioAddQueryToUrl(ioArgs);
40 this.attach(ioArgs.id, ioArgs.url, args.frameDoc);
41 dojo._ioWatch(dfd, this._validCheck, this._ioCheck, this._resHandle);
45 attach: function(/*String*/id, /*String*/url, /*Document?*/frameDocument){
47 // creates a new <script> tag pointing to the specified URL and
48 // adds it to the document.
50 // Attaches the script element to the DOM. Use this method if you
51 // just want to attach a script to the DOM and do not care when or
53 var doc = (frameDocument || dojo.doc);
54 var element = doc.createElement("script");
55 element.type = "text/javascript";
58 doc.getElementsByTagName("head")[0].appendChild(element);
61 remove: function(/*String*/id){
62 //summary: removes the script element with the given id.
63 dojo._destroyElement(dojo.byId(id));
65 //Remove the jsonp callback on dojo.io.script, if it exists.
66 if(this["jsonp_" + id]){
67 delete this["jsonp_" + id];
71 _makeScriptDeferred: function(/*Object*/args){
73 // sets up a Deferred object for an IO request.
74 var dfd = dojo._ioSetArgs(args, this._deferredCancel, this._deferredOk, this._deferredError);
76 var ioArgs = dfd.ioArgs;
77 ioArgs.id = dojo._scopeName + "IoScript" + (this._counter++);
78 ioArgs.canDelete = false;
80 //Special setup for jsonp case
81 if(args.callbackParamName){
82 //Add the jsonp parameter.
83 ioArgs.query = ioArgs.query || "";
84 if(ioArgs.query.length > 0){
87 ioArgs.query += args.callbackParamName
89 + (args.frameDoc ? "parent." : "")
90 + "dojo.io.script.jsonp_" + ioArgs.id + "._jsonpCallback";
92 //Setup the Deferred to have the jsonp callback.
93 ioArgs.canDelete = true;
94 dfd._jsonpCallback = this._jsonpCallback;
95 this["jsonp_" + ioArgs.id] = dfd;
97 return dfd; // dojo.Deferred
100 _deferredCancel: function(/*Deferred*/dfd){
101 //summary: canceller function for dojo._ioSetArgs call.
103 //DO NOT use "this" and expect it to be dojo.io.script.
105 if(dfd.ioArgs.canDelete){
106 dojo.io.script._deadScripts.push(dfd.ioArgs.id);
110 _deferredOk: function(/*Deferred*/dfd){
111 //summary: okHandler function for dojo._ioSetArgs call.
113 //DO NOT use "this" and expect it to be dojo.io.script.
115 //Add script to list of things that can be removed.
116 if(dfd.ioArgs.canDelete){
117 dojo.io.script._deadScripts.push(dfd.ioArgs.id);
121 //Make sure to *not* remove the json property from the
122 //Deferred, so that the Deferred can still function correctly
123 //after the response is received.
124 return dfd.ioArgs.json;
126 //FIXME: cannot return the dfd here, otherwise that stops
127 //the callback chain in Deferred. So return the ioArgs instead.
128 //This doesn't feel right.
133 _deferredError: function(/*Error*/error, /*Deferred*/dfd){
134 //summary: errHandler function for dojo._ioSetArgs call.
136 if(dfd.ioArgs.canDelete){
137 //DO NOT use "this" and expect it to be dojo.io.script.
138 if(error.dojoType == "timeout"){
139 //For timeouts, remove the script element immediately to
140 //avoid a response from it coming back later and causing trouble.
141 dojo.io.script.remove(dfd.ioArgs.id);
143 dojo.io.script._deadScripts.push(dfd.ioArgs.id);
146 console.debug("dojo.io.script error", error);
153 _validCheck: function(/*Deferred*/dfd){
154 //summary: inflight check function to see if dfd is still valid.
156 //Do script cleanup here. We wait for one inflight pass
157 //to make sure we don't get any weird things by trying to remove a script
158 //tag that is part of the call chain (IE 6 has been known to
159 //crash in that case).
160 var _self = dojo.io.script;
161 var deadScripts = _self._deadScripts;
162 if(deadScripts && deadScripts.length > 0){
163 for(var i = 0; i < deadScripts.length; i++){
164 //Remove the script tag
165 _self.remove(deadScripts[i]);
167 dojo.io.script._deadScripts = [];
173 _ioCheck: function(/*Deferred*/dfd){
174 //summary: inflight check function to see if IO finished.
176 //Check for finished jsonp
181 //Check for finished "checkString" case.
182 var checkString = dfd.ioArgs.args.checkString;
183 if(checkString && eval("typeof(" + checkString + ") != 'undefined'")){
190 _resHandle: function(/*Deferred*/dfd){
191 //summary: inflight function to handle a completed response.
192 if(dojo.io.script._ioCheck(dfd)){
195 //This path should never happen since the only way we can get
196 //to _resHandle is if _ioCheck is true.
197 dfd.errback(new Error("inconceivable dojo.io.script._resHandle error"));
201 _jsonpCallback: function(/*JSON Object*/json){
203 // generic handler for jsonp callback. A pointer to this function
204 // is used for all jsonp callbacks. NOTE: the "this" in this
205 // function will be the Deferred object that represents the script
207 this.ioArgs.json = json;