source: Dev/branches/rest-dojo-ui/client/dojo/io/script.js @ 256

Last change on this file since 256 was 256, checked in by hendrikvanantwerpen, 13 years ago

Reworked project structure based on REST interaction and Dojo library. As
soon as this is stable, the old jQueryUI branch can be removed (it's
kept for reference).

File size: 8.3 KB
Line 
1define(["../main"], function(dojo) {
2        // module:
3        //              dojo/io/script
4        // summary:
5        //              TODOC
6
7        dojo.getObject("io", true, dojo);
8
9/*=====
10dojo.declare("dojo.io.script.__ioArgs", dojo.__IoArgs, {
11        constructor: function(){
12                //      summary:
13                //              All the properties described in the dojo.__ioArgs type, apply to this
14                //              type as well, EXCEPT "handleAs". It is not applicable to
15                //              dojo.io.script.get() calls, since it is implied by the usage of
16                //              "jsonp" (response will be a JSONP call returning JSON)
17                //              or the response is pure JavaScript defined in
18                //              the body of the script that was attached.
19                //      callbackParamName: String
20                //              Deprecated as of Dojo 1.4 in favor of "jsonp", but still supported for
21                //              legacy code. See notes for jsonp property.
22                //      jsonp: String
23                //              The URL parameter name that indicates the JSONP callback string.
24                //              For instance, when using Yahoo JSONP calls it is normally,
25                //              jsonp: "callback". For AOL JSONP calls it is normally
26                //              jsonp: "c".
27                //      checkString: String
28                //              A string of JavaScript that when evaluated like so:
29                //              "typeof(" + checkString + ") != 'undefined'"
30                //              being true means that the script fetched has been loaded.
31                //              Do not use this if doing a JSONP type of call (use callbackParamName instead).
32                //      frameDoc: Document
33                //              The Document object for a child iframe. If this is passed in, the script
34                //              will be attached to that document. This can be helpful in some comet long-polling
35                //              scenarios with Firefox and Opera.
36                this.callbackParamName = callbackParamName;
37                this.jsonp = jsonp;
38                this.checkString = checkString;
39                this.frameDoc = frameDoc;
40        }
41});
42=====*/
43
44        var loadEvent = dojo.isIE ? "onreadystatechange" : "load",
45                readyRegExp = /complete|loaded/;
46
47        dojo.io.script = {
48                get: function(/*dojo.io.script.__ioArgs*/args){
49                        //      summary:
50                        //              sends a get request using a dynamically created script tag.
51                        var dfd = this._makeScriptDeferred(args);
52                        var ioArgs = dfd.ioArgs;
53                        dojo._ioAddQueryToUrl(ioArgs);
54
55                        dojo._ioNotifyStart(dfd);
56
57                        if(this._canAttach(ioArgs)){
58                                var node = this.attach(ioArgs.id, ioArgs.url, args.frameDoc);
59
60                                //If not a jsonp callback or a polling checkString case, bind
61                                //to load event on the script tag.
62                                if(!ioArgs.jsonp && !ioArgs.args.checkString){
63                                        var handle = dojo.connect(node, loadEvent, function(evt){
64                                                if(evt.type == "load" || readyRegExp.test(node.readyState)){
65                                                        dojo.disconnect(handle);
66                                                        ioArgs.scriptLoaded = evt;
67                                                }
68                                        });
69                                }
70                        }
71
72                        dojo._ioWatch(dfd, this._validCheck, this._ioCheck, this._resHandle);
73                        return dfd;
74                },
75
76                attach: function(/*String*/id, /*String*/url, /*Document?*/frameDocument){
77                        //      summary:
78                        //              creates a new <script> tag pointing to the specified URL and
79                        //              adds it to the document.
80                        //      description:
81                        //              Attaches the script element to the DOM.  Use this method if you
82                        //              just want to attach a script to the DOM and do not care when or
83                        //              if it loads.
84                        var doc = (frameDocument || dojo.doc);
85                        var element = doc.createElement("script");
86                        element.type = "text/javascript";
87                        element.src = url;
88                        element.id = id;
89                        element.async = true;
90                        element.charset = "utf-8";
91                        return doc.getElementsByTagName("head")[0].appendChild(element);
92                },
93
94                remove: function(/*String*/id, /*Document?*/frameDocument){
95                        //summary: removes the script element with the given id, from the given frameDocument.
96                        //If no frameDocument is passed, the current document is used.
97                        dojo.destroy(dojo.byId(id, frameDocument));
98
99                        //Remove the jsonp callback on dojo.io.script, if it exists.
100                        if(this["jsonp_" + id]){
101                                delete this["jsonp_" + id];
102                        }
103                },
104
105                _makeScriptDeferred: function(/*Object*/args){
106                        //summary:
107                        //              sets up a Deferred object for an IO request.
108                        var dfd = dojo._ioSetArgs(args, this._deferredCancel, this._deferredOk, this._deferredError);
109
110                        var ioArgs = dfd.ioArgs;
111                        ioArgs.id = dojo._scopeName + "IoScript" + (this._counter++);
112                        ioArgs.canDelete = false;
113
114                        //Special setup for jsonp case
115                        ioArgs.jsonp = args.callbackParamName || args.jsonp;
116                        if(ioArgs.jsonp){
117                                //Add the jsonp parameter.
118                                ioArgs.query = ioArgs.query || "";
119                                if(ioArgs.query.length > 0){
120                                        ioArgs.query += "&";
121                                }
122                                ioArgs.query += ioArgs.jsonp
123                                        + "="
124                                        + (args.frameDoc ? "parent." : "")
125                                        + dojo._scopeName + ".io.script.jsonp_" + ioArgs.id + "._jsonpCallback";
126
127                                ioArgs.frameDoc = args.frameDoc;
128
129                                //Setup the Deferred to have the jsonp callback.
130                                ioArgs.canDelete = true;
131                                dfd._jsonpCallback = this._jsonpCallback;
132                                this["jsonp_" + ioArgs.id] = dfd;
133                        }
134                        return dfd; // dojo.Deferred
135                },
136
137                _deferredCancel: function(/*Deferred*/dfd){
138                        //summary: canceller function for dojo._ioSetArgs call.
139
140                        //DO NOT use "this" and expect it to be dojo.io.script.
141                        dfd.canceled = true;
142                        if(dfd.ioArgs.canDelete){
143                                dojo.io.script._addDeadScript(dfd.ioArgs);
144                        }
145                },
146
147                _deferredOk: function(/*Deferred*/dfd){
148                        //summary: okHandler function for dojo._ioSetArgs call.
149
150                        //DO NOT use "this" and expect it to be dojo.io.script.
151                        var ioArgs = dfd.ioArgs;
152
153                        //Add script to list of things that can be removed.
154                        if(ioArgs.canDelete){
155                                dojo.io.script._addDeadScript(ioArgs);
156                        }
157
158                        //Favor JSONP responses, script load events then lastly ioArgs.
159                        //The ioArgs are goofy, but cannot return the dfd since that stops
160                        //the callback chain in Deferred. The return value is not that important
161                        //in that case, probably a checkString case.
162                        return ioArgs.json || ioArgs.scriptLoaded || ioArgs;
163                },
164
165                _deferredError: function(/*Error*/error, /*Deferred*/dfd){
166                        //summary: errHandler function for dojo._ioSetArgs call.
167
168                        if(dfd.ioArgs.canDelete){
169                                //DO NOT use "this" and expect it to be dojo.io.script.
170                                if(error.dojoType == "timeout"){
171                                        //For timeouts, remove the script element immediately to
172                                        //avoid a response from it coming back later and causing trouble.
173                                        dojo.io.script.remove(dfd.ioArgs.id, dfd.ioArgs.frameDoc);
174                                }else{
175                                        dojo.io.script._addDeadScript(dfd.ioArgs);
176                                }
177                        }
178                        console.log("dojo.io.script error", error);
179                        return error;
180                },
181
182                _deadScripts: [],
183                _counter: 1,
184
185                _addDeadScript: function(/*Object*/ioArgs){
186                        //summary: sets up an entry in the deadScripts array.
187                        dojo.io.script._deadScripts.push({id: ioArgs.id, frameDoc: ioArgs.frameDoc});
188                        //Being extra paranoid about leaks:
189                        ioArgs.frameDoc = null;
190                },
191
192                _validCheck: function(/*Deferred*/dfd){
193                        //summary: inflight check function to see if dfd is still valid.
194
195                        //Do script cleanup here. We wait for one inflight pass
196                        //to make sure we don't get any weird things by trying to remove a script
197                        //tag that is part of the call chain (IE 6 has been known to
198                        //crash in that case).
199                        var _self = dojo.io.script;
200                        var deadScripts = _self._deadScripts;
201                        if(deadScripts && deadScripts.length > 0){
202                                for(var i = 0; i < deadScripts.length; i++){
203                                        //Remove the script tag
204                                        _self.remove(deadScripts[i].id, deadScripts[i].frameDoc);
205                                        deadScripts[i].frameDoc = null;
206                                }
207                                dojo.io.script._deadScripts = [];
208                        }
209
210                        return true;
211                },
212
213                _ioCheck: function(/*Deferred*/dfd){
214                        //summary: inflight check function to see if IO finished.
215                        var ioArgs = dfd.ioArgs;
216                        //Check for finished jsonp
217                        if(ioArgs.json || (ioArgs.scriptLoaded && !ioArgs.args.checkString)){
218                                return true;
219                        }
220
221                        //Check for finished "checkString" case.
222                        var checkString = ioArgs.args.checkString;
223                        return checkString && eval("typeof(" + checkString + ") != 'undefined'");
224
225
226                },
227
228                _resHandle: function(/*Deferred*/dfd){
229                        //summary: inflight function to handle a completed response.
230                        if(dojo.io.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(/*Object*/ioArgs){
240                        //summary: A method that can be overridden by other modules
241                        //to control when the script attachment occurs.
242                        return true;
243                },
244
245                _jsonpCallback: function(/*JSON Object*/json){
246                        //summary:
247                        //              generic handler for jsonp callback. A pointer to this function
248                        //              is used for all jsonp callbacks.  NOTE: the "this" in this
249                        //              function will be the Deferred object that represents the script
250                        //              request.
251                        this.ioArgs.json = json;
252                }
253        };
254
255        return dojo.io.script;
256});
Note: See TracBrowser for help on using the repository browser.