]> git.pond.sub.org Git - eow/blob - static/dojo-release-1.1.1/dojo/io/script.js
add Dojo 1.1.1
[eow] / static / dojo-release-1.1.1 / dojo / io / script.js
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");
4
5 /*=====
6 dojo.io.script.__ioArgs = function(kwArgs){
7         //      summary:
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.
29 }
30 =====*/
31
32 dojo.io.script = {
33         get: function(/*dojo.io.script.__ioArgs*/args){
34                 //      summary:
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);
39
40                 this.attach(ioArgs.id, ioArgs.url, args.frameDoc);
41                 dojo._ioWatch(dfd, this._validCheck, this._ioCheck, this._resHandle);
42                 return dfd;
43         },
44
45         attach: function(/*String*/id, /*String*/url, /*Document?*/frameDocument){
46                 //      summary:
47                 //              creates a new <script> tag pointing to the specified URL and
48                 //              adds it to the document.
49                 //      description:
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
52                 //              if it loads.
53                 var doc = (frameDocument || dojo.doc);
54                 var element = doc.createElement("script");
55                 element.type = "text/javascript";
56                 element.src = url;
57                 element.id = id;
58                 doc.getElementsByTagName("head")[0].appendChild(element);
59         },
60
61         remove: function(/*String*/id){
62                 //summary: removes the script element with the given id.
63                 dojo._destroyElement(dojo.byId(id));
64                 
65                 //Remove the jsonp callback on dojo.io.script, if it exists.
66                 if(this["jsonp_" + id]){
67                         delete this["jsonp_" + id];
68                 }
69         },
70
71         _makeScriptDeferred: function(/*Object*/args){
72                 //summary: 
73                 //              sets up a Deferred object for an IO request.
74                 var dfd = dojo._ioSetArgs(args, this._deferredCancel, this._deferredOk, this._deferredError);
75
76                 var ioArgs = dfd.ioArgs;
77                 ioArgs.id = dojo._scopeName + "IoScript" + (this._counter++);
78                 ioArgs.canDelete = false;
79
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){
85                                 ioArgs.query += "&";
86                         }
87                         ioArgs.query += args.callbackParamName
88                                 + "="
89                                 + (args.frameDoc ? "parent." : "")
90                                 + "dojo.io.script.jsonp_" + ioArgs.id + "._jsonpCallback";
91
92                         //Setup the Deferred to have the jsonp callback.
93                         ioArgs.canDelete = true;
94                         dfd._jsonpCallback = this._jsonpCallback;
95                         this["jsonp_" + ioArgs.id] = dfd;
96                 }
97                 return dfd; // dojo.Deferred
98         },
99         
100         _deferredCancel: function(/*Deferred*/dfd){
101                 //summary: canceller function for dojo._ioSetArgs call.
102
103                 //DO NOT use "this" and expect it to be dojo.io.script.
104                 dfd.canceled = true;
105                 if(dfd.ioArgs.canDelete){
106                         dojo.io.script._deadScripts.push(dfd.ioArgs.id);
107                 }
108         },
109
110         _deferredOk: function(/*Deferred*/dfd){
111                 //summary: okHandler function for dojo._ioSetArgs call.
112
113                 //DO NOT use "this" and expect it to be dojo.io.script.
114
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);
118                 }
119
120                 if(dfd.ioArgs.json){
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;
125                 }else{
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.
129                         return dfd.ioArgs;
130                 }
131         },
132         
133         _deferredError: function(/*Error*/error, /*Deferred*/dfd){
134                 //summary: errHandler function for dojo._ioSetArgs call.
135
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);
142                         }else{
143                                 dojo.io.script._deadScripts.push(dfd.ioArgs.id);
144                         }
145                 }
146                 console.debug("dojo.io.script error", error);
147                 return error;
148         },
149
150         _deadScripts: [],
151         _counter: 1,
152
153         _validCheck: function(/*Deferred*/dfd){
154                 //summary: inflight check function to see if dfd is still valid.
155
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]);
166                         }
167                         dojo.io.script._deadScripts = [];
168                 }
169
170                 return true;
171         },
172
173         _ioCheck: function(/*Deferred*/dfd){
174                 //summary: inflight check function to see if IO finished.
175
176                 //Check for finished jsonp
177                 if(dfd.ioArgs.json){
178                         return true;
179                 }
180
181                 //Check for finished "checkString" case.
182                 var checkString = dfd.ioArgs.args.checkString;
183                 if(checkString && eval("typeof(" + checkString + ") != 'undefined'")){
184                         return true;
185                 }
186
187                 return false;
188         },
189
190         _resHandle: function(/*Deferred*/dfd){
191                 //summary: inflight function to handle a completed response.
192                 if(dojo.io.script._ioCheck(dfd)){
193                         dfd.callback(dfd);
194                 }else{
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"));
198                 }
199         },
200
201         _jsonpCallback: function(/*JSON Object*/json){
202                 //summary: 
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
206                 //              request.
207                 this.ioArgs.json = json;
208         }
209 }
210
211 }