2150 |
mathias |
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 |
}
|
|
|
26 |
=====*/
|
|
|
27 |
|
|
|
28 |
dojo.io.script = {
|
|
|
29 |
get: function(/*dojo.io.script.__ioArgs*/args){
|
|
|
30 |
// summary:
|
|
|
31 |
// sends a get request using a dynamically created script tag.
|
|
|
32 |
var dfd = this._makeScriptDeferred(args);
|
|
|
33 |
var ioArgs = dfd.ioArgs;
|
|
|
34 |
dojo._ioAddQueryToUrl(ioArgs);
|
|
|
35 |
|
|
|
36 |
this.attach(ioArgs.id, ioArgs.url);
|
|
|
37 |
dojo._ioWatch(dfd, this._validCheck, this._ioCheck, this._resHandle);
|
|
|
38 |
return dfd;
|
|
|
39 |
},
|
|
|
40 |
|
|
|
41 |
attach: function(/*String*/id, /*String*/url){
|
|
|
42 |
// summary:
|
|
|
43 |
// creates a new <script> tag pointing to the specified URL and
|
|
|
44 |
// adds it to the document.
|
|
|
45 |
// description:
|
|
|
46 |
// Attaches the script element to the DOM. Use this method if you
|
|
|
47 |
// just want to attach a script to the DOM and do not care when or
|
|
|
48 |
// if it loads.
|
|
|
49 |
var element = dojo.doc.createElement("script");
|
|
|
50 |
element.type = "text/javascript";
|
|
|
51 |
element.src = url;
|
|
|
52 |
element.id = id;
|
|
|
53 |
dojo.doc.getElementsByTagName("head")[0].appendChild(element);
|
|
|
54 |
},
|
|
|
55 |
|
|
|
56 |
remove: function(/*String*/id){
|
|
|
57 |
//summary: removes the script element with the given id.
|
|
|
58 |
dojo._destroyElement(dojo.byId(id));
|
|
|
59 |
|
|
|
60 |
//Remove the jsonp callback on dojo.io.script, if it exists.
|
|
|
61 |
if(this["jsonp_" + id]){
|
|
|
62 |
delete this["jsonp_" + id];
|
|
|
63 |
}
|
|
|
64 |
},
|
|
|
65 |
|
|
|
66 |
_makeScriptDeferred: function(/*Object*/args){
|
|
|
67 |
//summary:
|
|
|
68 |
// sets up a Deferred object for an IO request.
|
|
|
69 |
var dfd = dojo._ioSetArgs(args, this._deferredCancel, this._deferredOk, this._deferredError);
|
|
|
70 |
|
|
|
71 |
var ioArgs = dfd.ioArgs;
|
|
|
72 |
ioArgs.id = "dojoIoScript" + (this._counter++);
|
|
|
73 |
ioArgs.canDelete = false;
|
|
|
74 |
|
|
|
75 |
//Special setup for jsonp case
|
|
|
76 |
if(args.callbackParamName){
|
|
|
77 |
//Add the jsonp parameter.
|
|
|
78 |
ioArgs.query = ioArgs.query || "";
|
|
|
79 |
if(ioArgs.query.length > 0){
|
|
|
80 |
ioArgs.query += "&";
|
|
|
81 |
}
|
|
|
82 |
ioArgs.query += args.callbackParamName + "=dojo.io.script.jsonp_" + ioArgs.id + "._jsonpCallback";
|
|
|
83 |
|
|
|
84 |
//Setup the Deferred to have the jsonp callback.
|
|
|
85 |
ioArgs.canDelete = true;
|
|
|
86 |
dfd._jsonpCallback = this._jsonpCallback;
|
|
|
87 |
this["jsonp_" + ioArgs.id] = dfd;
|
|
|
88 |
}
|
|
|
89 |
return dfd; // dojo.Deferred
|
|
|
90 |
},
|
|
|
91 |
|
|
|
92 |
_deferredCancel: function(/*Deferred*/dfd){
|
|
|
93 |
//summary: canceller function for dojo._ioSetArgs call.
|
|
|
94 |
|
|
|
95 |
//DO NOT use "this" and expect it to be dojo.io.script.
|
|
|
96 |
dfd.canceled = true;
|
|
|
97 |
if(dfd.ioArgs.canDelete){
|
|
|
98 |
dojo.io.script._deadScripts.push(dfd.ioArgs.id);
|
|
|
99 |
}
|
|
|
100 |
},
|
|
|
101 |
|
|
|
102 |
_deferredOk: function(/*Deferred*/dfd){
|
|
|
103 |
//summary: okHandler function for dojo._ioSetArgs call.
|
|
|
104 |
|
|
|
105 |
//DO NOT use "this" and expect it to be dojo.io.script.
|
|
|
106 |
|
|
|
107 |
//Add script to list of things that can be removed.
|
|
|
108 |
if(dfd.ioArgs.canDelete){
|
|
|
109 |
dojo.io.script._deadScripts.push(dfd.ioArgs.id);
|
|
|
110 |
}
|
|
|
111 |
|
|
|
112 |
if(dfd.ioArgs.json){
|
|
|
113 |
//Make sure to *not* remove the json property from the
|
|
|
114 |
//Deferred, so that the Deferred can still function correctly
|
|
|
115 |
//after the response is received.
|
|
|
116 |
return dfd.ioArgs.json;
|
|
|
117 |
}else{
|
|
|
118 |
//FIXME: cannot return the dfd here, otherwise that stops
|
|
|
119 |
//the callback chain in Deferred. So return the ioArgs instead.
|
|
|
120 |
//This doesn't feel right.
|
|
|
121 |
return dfd.ioArgs;
|
|
|
122 |
}
|
|
|
123 |
},
|
|
|
124 |
|
|
|
125 |
_deferredError: function(/*Error*/error, /*Deferred*/dfd){
|
|
|
126 |
//summary: errHandler function for dojo._ioSetArgs call.
|
|
|
127 |
|
|
|
128 |
if(dfd.ioArgs.canDelete){
|
|
|
129 |
//DO NOT use "this" and expect it to be dojo.io.script.
|
|
|
130 |
if(error.dojoType == "timeout"){
|
|
|
131 |
//For timeouts, remove the script element immediately to
|
|
|
132 |
//avoid a response from it coming back later and causing trouble.
|
|
|
133 |
dojo.io.script.remove(dfd.ioArgs.id);
|
|
|
134 |
}else{
|
|
|
135 |
dojo.io.script._deadScripts.push(dfd.ioArgs.id);
|
|
|
136 |
}
|
|
|
137 |
}
|
|
|
138 |
console.debug("dojo.io.script error", error);
|
|
|
139 |
return error;
|
|
|
140 |
},
|
|
|
141 |
|
|
|
142 |
_deadScripts: [],
|
|
|
143 |
_counter: 1,
|
|
|
144 |
|
|
|
145 |
_validCheck: function(/*Deferred*/dfd){
|
|
|
146 |
//summary: inflight check function to see if dfd is still valid.
|
|
|
147 |
|
|
|
148 |
//Do script cleanup here. We wait for one inflight pass
|
|
|
149 |
//to make sure we don't get any weird things by trying to remove a script
|
|
|
150 |
//tag that is part of the call chain (IE 6 has been known to
|
|
|
151 |
//crash in that case).
|
|
|
152 |
var _self = dojo.io.script;
|
|
|
153 |
var deadScripts = _self._deadScripts;
|
|
|
154 |
if(deadScripts && deadScripts.length > 0){
|
|
|
155 |
for(var i = 0; i < deadScripts.length; i++){
|
|
|
156 |
//Remove the script tag
|
|
|
157 |
_self.remove(deadScripts[i]);
|
|
|
158 |
}
|
|
|
159 |
dojo.io.script._deadScripts = [];
|
|
|
160 |
}
|
|
|
161 |
|
|
|
162 |
return true;
|
|
|
163 |
},
|
|
|
164 |
|
|
|
165 |
_ioCheck: function(/*Deferred*/dfd){
|
|
|
166 |
//summary: inflight check function to see if IO finished.
|
|
|
167 |
|
|
|
168 |
//Check for finished jsonp
|
|
|
169 |
if(dfd.ioArgs.json){
|
|
|
170 |
return true;
|
|
|
171 |
}
|
|
|
172 |
|
|
|
173 |
//Check for finished "checkString" case.
|
|
|
174 |
var checkString = dfd.ioArgs.args.checkString;
|
|
|
175 |
if(checkString && eval("typeof(" + checkString + ") != 'undefined'")){
|
|
|
176 |
return true;
|
|
|
177 |
}
|
|
|
178 |
|
|
|
179 |
return false;
|
|
|
180 |
},
|
|
|
181 |
|
|
|
182 |
_resHandle: function(/*Deferred*/dfd){
|
|
|
183 |
//summary: inflight function to handle a completed response.
|
|
|
184 |
if(dojo.io.script._ioCheck(dfd)){
|
|
|
185 |
dfd.callback(dfd);
|
|
|
186 |
}else{
|
|
|
187 |
//This path should never happen since the only way we can get
|
|
|
188 |
//to _resHandle is if _ioCheck is true.
|
|
|
189 |
dfd.errback(new Error("inconceivable dojo.io.script._resHandle error"));
|
|
|
190 |
}
|
|
|
191 |
},
|
|
|
192 |
|
|
|
193 |
_jsonpCallback: function(/*JSON Object*/json){
|
|
|
194 |
//summary:
|
|
|
195 |
// generic handler for jsonp callback. A pointer to this function
|
|
|
196 |
// is used for all jsonp callbacks. NOTE: the "this" in this
|
|
|
197 |
// function will be the Deferred object that represents the script
|
|
|
198 |
// request.
|
|
|
199 |
this.ioArgs.json = json;
|
|
|
200 |
}
|
|
|
201 |
}
|
|
|
202 |
|
|
|
203 |
}
|