]>
Commit | Line | Data |
---|---|---|
f0cfe83e AD |
1 | define("dojo/io/script", [ |
2 | "../_base/connect", /*===== "../_base/declare", =====*/ "../_base/kernel", "../_base/lang", | |
3 | "../sniff", "../_base/window","../_base/xhr", | |
4 | "../dom", "../dom-construct", "../request/script" | |
5 | ], function(connect, /*===== declare, =====*/ kernel, lang, has, win, xhr, dom, domConstruct, _script){ | |
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 | rDfd.then(function(){ | |
74 | dfd.resolve(dfd); | |
75 | }).otherwise(function(error){ | |
76 | dfd.ioArgs.error = error; | |
77 | dfd.reject(error); | |
78 | }); | |
79 | ||
80 | return dfd; | |
81 | }, | |
82 | ||
83 | attach: _script._attach, | |
84 | remove: _script._remove, | |
85 | ||
86 | _makeScriptDeferred: function(/*Object*/ args, /*Function?*/ cancel){ | |
87 | // summary: | |
88 | // sets up a Deferred object for an IO request. | |
89 | var dfd = xhr._ioSetArgs(args, cancel || this._deferredCancel, this._deferredOk, this._deferredError); | |
90 | ||
91 | var ioArgs = dfd.ioArgs; | |
92 | ioArgs.id = kernel._scopeName + "IoScript" + (this._counter++); | |
93 | ioArgs.canDelete = false; | |
94 | ||
95 | //Special setup for jsonp case | |
96 | ioArgs.jsonp = args.callbackParamName || args.jsonp; | |
97 | if(ioArgs.jsonp){ | |
98 | //Add the jsonp parameter. | |
99 | ioArgs.query = ioArgs.query || ""; | |
100 | if(ioArgs.query.length > 0){ | |
101 | ioArgs.query += "&"; | |
102 | } | |
103 | ioArgs.query += ioArgs.jsonp + | |
104 | "=" + (args.frameDoc ? "parent." : "") + | |
105 | kernel._scopeName + ".io.script.jsonp_" + ioArgs.id + "._jsonpCallback"; | |
106 | ||
107 | ioArgs.frameDoc = args.frameDoc; | |
108 | ||
109 | //Setup the Deferred to have the jsonp callback. | |
110 | ioArgs.canDelete = true; | |
111 | dfd._jsonpCallback = this._jsonpCallback; | |
112 | this["jsonp_" + ioArgs.id] = dfd; | |
113 | } | |
114 | return dfd; // dojo/_base/Deferred | |
115 | }, | |
116 | ||
117 | _deferredCancel: function(/*Deferred*/ dfd){ | |
118 | // summary: | |
119 | // canceller function for xhr._ioSetArgs call. | |
120 | ||
121 | //DO NOT use "this" and expect it to be script. | |
122 | dfd.canceled = true; | |
123 | }, | |
124 | ||
125 | _deferredOk: function(/*Deferred*/ dfd){ | |
126 | // summary: | |
127 | // okHandler function for xhr._ioSetArgs call. | |
128 | ||
129 | //DO NOT use "this" and expect it to be script. | |
130 | var ioArgs = dfd.ioArgs; | |
131 | ||
132 | //Favor JSONP responses, script load events then lastly ioArgs. | |
133 | //The ioArgs are goofy, but cannot return the dfd since that stops | |
134 | //the callback chain in Deferred. The return value is not that important | |
135 | //in that case, probably a checkString case. | |
136 | return ioArgs.json || ioArgs.scriptLoaded || ioArgs; | |
137 | }, | |
138 | ||
139 | _deferredError: function(/*Error*/ error, /*Deferred*/ dfd){ | |
140 | // summary: | |
141 | // errHandler function for xhr._ioSetArgs call. | |
142 | ||
143 | console.log("dojo.io.script error", error); | |
144 | return error; | |
145 | }, | |
146 | ||
147 | _deadScripts: [], | |
148 | _counter: 1, | |
149 | ||
150 | _addDeadScript: function(/*Object*/ ioArgs){ | |
151 | // summary: | |
152 | // sets up an entry in the deadScripts array. | |
153 | script._deadScripts.push({id: ioArgs.id, frameDoc: ioArgs.frameDoc}); | |
154 | //Being extra paranoid about leaks: | |
155 | ioArgs.frameDoc = null; | |
156 | }, | |
157 | ||
158 | _validCheck: function(/*Deferred*/ dfd){ | |
159 | // summary: | |
160 | // inflight check function to see if dfd is still valid. | |
161 | ||
162 | // TODO: why isn't dfd accessed? | |
163 | ||
164 | //Do script cleanup here. We wait for one inflight pass | |
165 | //to make sure we don't get any weird things by trying to remove a script | |
166 | //tag that is part of the call chain (IE 6 has been known to | |
167 | //crash in that case). | |
168 | var deadScripts = script._deadScripts; | |
169 | if(deadScripts && deadScripts.length > 0){ | |
170 | for(var i = 0; i < deadScripts.length; i++){ | |
171 | //Remove the script tag | |
172 | script.remove(deadScripts[i].id, deadScripts[i].frameDoc); | |
173 | deadScripts[i].frameDoc = null; | |
174 | } | |
175 | script._deadScripts = []; | |
176 | } | |
177 | ||
178 | return true; | |
179 | }, | |
180 | ||
181 | _ioCheck: function(dfd){ | |
182 | // summary: | |
183 | // inflight check function to see if IO finished. | |
184 | // dfd: Deferred | |
185 | var ioArgs = dfd.ioArgs; | |
186 | //Check for finished jsonp | |
187 | if(ioArgs.json || (ioArgs.scriptLoaded && !ioArgs.args.checkString)){ | |
188 | return true; | |
189 | } | |
190 | ||
191 | //Check for finished "checkString" case. | |
192 | var checkString = ioArgs.args.checkString; | |
193 | return checkString && eval("typeof(" + checkString + ") != 'undefined'"); | |
194 | ||
195 | ||
196 | }, | |
197 | ||
198 | _resHandle: function(/*Deferred*/ dfd){ | |
199 | // summary: | |
200 | // inflight function to handle a completed response. | |
201 | if(script._ioCheck(dfd)){ | |
202 | dfd.callback(dfd); | |
203 | }else{ | |
204 | //This path should never happen since the only way we can get | |
205 | //to _resHandle is if _ioCheck is true. | |
206 | dfd.errback(new Error("inconceivable dojo.io.script._resHandle error")); | |
207 | } | |
208 | }, | |
209 | ||
210 | _canAttach: function(/*===== ioArgs =====*/ ){ | |
211 | // summary: | |
212 | // A method that can be overridden by other modules | |
213 | // to control when the script attachment occurs. | |
214 | // ioArgs: Object | |
215 | return true; | |
216 | }, | |
217 | ||
218 | _jsonpCallback: function(/*JSON Object*/ json){ | |
219 | // summary: | |
220 | // generic handler for jsonp callback. A pointer to this function | |
221 | // is used for all jsonp callbacks. NOTE: the "this" in this | |
222 | // function will be the Deferred object that represents the script | |
223 | // request. | |
224 | this.ioArgs.json = json; | |
225 | kernel.global[_script._callbacksProperty][this.ioArgs.requestId](json); | |
226 | } | |
227 | }; | |
228 | ||
229 | lang.setObject("dojo.io.script", script); | |
230 | ||
231 | /*===== | |
232 | script.attach = function(id, url, frameDocument){ | |
233 | // summary: | |
234 | // creates a new `<script>` tag pointing to the specified URL and | |
235 | // adds it to the document. | |
236 | // description: | |
237 | // Attaches the script element to the DOM. Use this method if you | |
238 | // just want to attach a script to the DOM and do not care when or | |
239 | // if it loads. | |
240 | }; | |
241 | script.remove = function(id, frameDocument){ | |
242 | // summary: | |
243 | // removes the script element with the given id, from the given frameDocument. | |
244 | // If no frameDocument is passed, the current document is used. | |
245 | }; | |
246 | =====*/ | |
247 | ||
248 | return script; | |
249 | }); |