source: Dev/trunk/src/client/dojo/io/script.js @ 485

Last change on this file since 485 was 483, checked in by hendrikvanantwerpen, 11 years ago

Added Dojo 1.9.3 release.

File size: 8.6 KB
Line 
1define([
2        "../_base/connect", /*===== "../_base/declare", =====*/ "../_base/kernel", "../_base/lang",
3        "../sniff", "../_base/window","../_base/xhr",
4        "../dom", "../dom-construct", "../request/script", "../aspect"
5], function(connect, /*===== declare, =====*/ kernel, lang, has, win, xhr, dom, domConstruct, _script, aspect){
6
7        // module:
8        //              dojo/io/script
9
10        kernel.deprecated("dojo/io/script", "Use dojo/request/script.", "2.0");
11
12        /*=====
13        var __ioArgs = declare(kernel.__IoArgs, {
14                // summary:
15                //              All the properties described in the dojo.__ioArgs type, apply to this
16                //              type as well, EXCEPT "handleAs". It is not applicable to
17                //              dojo/io/script.get() calls, since it is implied by the usage of
18                //              "jsonp" (response will be a JSONP call returning JSON)
19                //              or the response is pure JavaScript defined in
20                //              the body of the script that was attached.
21                // callbackParamName: String
22                //              Deprecated as of Dojo 1.4 in favor of "jsonp", but still supported for
23                //              legacy code. See notes for jsonp property.
24                // jsonp: String
25                //              The URL parameter name that indicates the JSONP callback string.
26                //              For instance, when using Yahoo JSONP calls it is normally,
27                //              jsonp: "callback". For AOL JSONP calls it is normally
28                //              jsonp: "c".
29                // checkString: String
30                //              A string of JavaScript that when evaluated like so:
31                //              "typeof(" + checkString + ") != 'undefined'"
32                //              being true means that the script fetched has been loaded.
33                //              Do not use this if doing a JSONP type of call (use callbackParamName instead).
34                // frameDoc: Document
35                //              The Document object for a child iframe. If this is passed in, the script
36                //              will be attached to that document. This can be helpful in some comet long-polling
37                //              scenarios with Firefox and Opera.
38        });
39        =====*/
40
41        var script = {
42                // summary:
43                //              TODOC
44
45                get: function(/*__ioArgs*/ args){
46                        // summary:
47                        //              sends a get request using a dynamically created script tag.
48                        var rDfd;
49                        var dfd = this._makeScriptDeferred(args, function(dfd){
50                                rDfd && rDfd.cancel();
51                        });
52                        var ioArgs = dfd.ioArgs;
53                        xhr._ioAddQueryToUrl(ioArgs);
54
55                        xhr._ioNotifyStart(dfd);
56
57                        rDfd = _script.get(ioArgs.url, {
58                                timeout: args.timeout,
59                                jsonp: ioArgs.jsonp,
60                                checkString: args.checkString,
61                                ioArgs: ioArgs,
62                                frameDoc: args.frameDoc,
63                                canAttach: function(rDfd){
64                                        // sync values
65                                        ioArgs.requestId = rDfd.id;
66                                        ioArgs.scriptId = rDfd.scriptId;
67                                        ioArgs.canDelete = rDfd.canDelete;
68
69                                        return script._canAttach(ioArgs);
70                                }
71                        }, true);
72
73                        // Run _validCheck at the same time dojo/request/watch runs the
74                        // rDfd.isValid function
75                        aspect.around(rDfd, "isValid", function(isValid){
76                                return function(response){
77                                        script._validCheck(dfd);
78                                        return isValid.call(this, response);
79                                };
80                        });
81
82                        rDfd.then(function(){
83                                dfd.resolve(dfd);
84                        }).otherwise(function(error){
85                                dfd.ioArgs.error = error;
86                                dfd.reject(error);
87                        });
88
89                        return dfd;
90                },
91
92                attach: _script._attach,
93                remove: _script._remove,
94
95                _makeScriptDeferred: function(/*Object*/ args, /*Function?*/ cancel){
96                        // summary:
97                        //              sets up a Deferred object for an IO request.
98                        var dfd = xhr._ioSetArgs(args, cancel || this._deferredCancel, this._deferredOk, this._deferredError);
99
100                        var ioArgs = dfd.ioArgs;
101                        ioArgs.id = kernel._scopeName + "IoScript" + (this._counter++);
102                        ioArgs.canDelete = false;
103
104                        //Special setup for jsonp case
105                        ioArgs.jsonp = args.callbackParamName || args.jsonp;
106                        if(ioArgs.jsonp){
107                                //Add the jsonp parameter.
108                                ioArgs.query = ioArgs.query || "";
109                                if(ioArgs.query.length > 0){
110                                        ioArgs.query += "&";
111                                }
112                                ioArgs.query += ioArgs.jsonp +
113                                        "=" + (args.frameDoc ? "parent." : "") +
114                                        kernel._scopeName + ".io.script.jsonp_" + ioArgs.id + "._jsonpCallback";
115
116                                ioArgs.frameDoc = args.frameDoc;
117
118                                //Setup the Deferred to have the jsonp callback.
119                                ioArgs.canDelete = true;
120                                dfd._jsonpCallback = this._jsonpCallback;
121                                this["jsonp_" + ioArgs.id] = dfd;
122                        }
123                        // Make sure this runs no matter what happens to clean things up if need be
124                        dfd.addBoth(function(value){
125                                if(ioArgs.canDelete){
126                                        if(value instanceof Error){
127                                                // Set up a callback that will clean things up for timeouts and cancels
128                                                script["jsonp_" + ioArgs.id]._jsonpCallback = function(){
129                                                        // Delete the cached deferred
130                                                        delete script["jsonp_" + ioArgs.id];
131                                                        if(ioArgs.requestId){
132                                                                // Call the dojo/request/script callback to clean itself up as well
133                                                                kernel.global[_script._callbacksProperty][ioArgs.requestId]();
134                                                        }
135                                                };
136                                        }else{
137                                                script._addDeadScript(ioArgs);
138                                        }
139                                }
140                        });
141                        return dfd; // dojo/_base/Deferred
142                },
143
144                _deferredCancel: function(/*Deferred*/ dfd){
145                        // summary:
146                        //              canceller function for xhr._ioSetArgs call.
147
148                        //DO NOT use "this" and expect it to be script.
149                        dfd.canceled = true;
150                },
151
152                _deferredOk: function(/*Deferred*/ dfd){
153                        // summary:
154                        //              okHandler function for xhr._ioSetArgs call.
155
156                        //DO NOT use "this" and expect it to be script.
157                        var ioArgs = dfd.ioArgs;
158
159                        //Favor JSONP responses, script load events then lastly ioArgs.
160                        //The ioArgs are goofy, but cannot return the dfd since that stops
161                        //the callback chain in Deferred. The return value is not that important
162                        //in that case, probably a checkString case.
163                        return ioArgs.json || ioArgs.scriptLoaded || ioArgs;
164                },
165
166                _deferredError: function(/*Error*/ error, /*Deferred*/ dfd){
167                        // summary:
168                        //              errHandler function for xhr._ioSetArgs call.
169
170                        console.log("dojo.io.script error", error);
171                        return error;
172                },
173
174                _deadScripts: [],
175                _counter: 1,
176
177                _addDeadScript: function(/*Object*/ ioArgs){
178                        // summary:
179                        //              sets up an entry in the deadScripts array.
180                        script._deadScripts.push({id: ioArgs.id, frameDoc: ioArgs.frameDoc});
181                        //Being extra paranoid about leaks:
182                        ioArgs.frameDoc = null;
183                },
184
185                _validCheck: function(/*Deferred*/ dfd){
186                        // summary:
187                        //              inflight check function to see if dfd is still valid.
188
189                        // TODO: why isn't dfd accessed?
190
191                        //Do script cleanup here. We wait for one inflight pass
192                        //to make sure we don't get any weird things by trying to remove a script
193                        //tag that is part of the call chain (IE 6 has been known to
194                        //crash in that case).
195                        var deadScripts = script._deadScripts;
196                        if(deadScripts && deadScripts.length > 0){
197                                for(var i = 0; i < deadScripts.length; i++){
198                                        //Remove the script tag
199                                        script.remove(deadScripts[i].id, deadScripts[i].frameDoc);
200                                        //Clean up the deferreds
201                                        delete script["jsonp_" + deadScripts[i].id];
202                                        deadScripts[i].frameDoc = null;
203                                }
204                                script._deadScripts = [];
205                        }
206
207                        return true;
208                },
209
210                _ioCheck: function(dfd){
211                        // summary:
212                        //              inflight check function to see if IO finished.
213                        // dfd: Deferred
214                        var ioArgs = dfd.ioArgs;
215                        //Check for finished jsonp
216                        if(ioArgs.json || (ioArgs.scriptLoaded && !ioArgs.args.checkString)){
217                                return true;
218                        }
219
220                        //Check for finished "checkString" case.
221                        var checkString = ioArgs.args.checkString;
222                        return checkString && eval("typeof(" + checkString + ") != 'undefined'");
223
224
225                },
226
227                _resHandle: function(/*Deferred*/ dfd){
228                        // summary:
229                        //              inflight function to handle a completed response.
230                        if(script._ioCheck(dfd)){
231                                dfd.callback(dfd);
232                        }else{
233                                //This path should never happen since the only way we can get
234                                //to _resHandle is if _ioCheck is true.
235                                dfd.errback(new Error("inconceivable dojo.io.script._resHandle error"));
236                        }
237                },
238
239                _canAttach: function(/*===== ioArgs =====*/ ){
240                        // summary:
241                        //              A method that can be overridden by other modules
242                        //              to control when the script attachment occurs.
243                        // ioArgs: Object
244                        return true;
245                },
246
247                _jsonpCallback: function(/*JSON Object*/ json){
248                        // summary:
249                        //              generic handler for jsonp callback. A pointer to this function
250                        //              is used for all jsonp callbacks.  NOTE: the "this" in this
251                        //              function will be the Deferred object that represents the script
252                        //              request.
253                        this.ioArgs.json = json;
254                        if(this.ioArgs.requestId){
255                                kernel.global[_script._callbacksProperty][this.ioArgs.requestId](json);
256                        }
257                }
258        };
259
260        lang.setObject("dojo.io.script", script);
261
262        /*=====
263        script.attach = function(id, url, frameDocument){
264                // summary:
265                //              creates a new `<script>` tag pointing to the specified URL and
266                //              adds it to the document.
267                // description:
268                //              Attaches the script element to the DOM. Use this method if you
269                //              just want to attach a script to the DOM and do not care when or
270                //              if it loads.
271        };
272        script.remove = function(id, frameDocument){
273                // summary:
274                //              removes the script element with the given id, from the given frameDocument.
275                //              If no frameDocument is passed, the current document is used.
276        };
277        =====*/
278
279        return script;
280});
Note: See TracBrowser for help on using the repository browser.