]> git.wh0rd.org - tt-rss.git/blame - lib/dojo/io/iframe.js.uncompressed.js
make precache_headlines_idle() start slower
[tt-rss.git] / lib / dojo / io / iframe.js.uncompressed.js
CommitLineData
1354d172
AD
1define("dojo/io/iframe", ["../main", "require"], function(dojo, require) {
2 // module:
3 // dojo/io/iframe
4 // summary:
5 // TODOC
6
7dojo.getObject("io", true, dojo);
8
9/*=====
10dojo.declare("dojo.io.iframe.__ioArgs", dojo.__IoArgs, {
11 constructor: function(){
12 // summary:
13 // All the properties described in the dojo.__ioArgs type, apply
14 // to this type. The following additional properties are allowed
15 // for dojo.io.iframe.send():
16 // method: String?
17 // The HTTP method to use. "GET" or "POST" are the only supported
18 // values. It will try to read the value from the form node's
19 // method, then try this argument. If neither one exists, then it
20 // defaults to POST.
21 // handleAs: String?
22 // Specifies what format the result data should be given to the
23 // load/handle callback. Valid values are: text, html, xml, json,
24 // javascript. IMPORTANT: For all values EXCEPT html and xml, The
25 // server response should be an HTML file with a textarea element.
26 // The response data should be inside the textarea element. Using an
27 // HTML document the only reliable, cross-browser way this
28 // transport can know when the response has loaded. For the html
29 // handleAs value, just return a normal HTML document. NOTE: xml
30 // is now supported with this transport (as of 1.1+); a known issue
31 // is if the XML document in question is malformed, Internet Explorer
32 // will throw an uncatchable error.
33 // content: Object?
34 // If "form" is one of the other args properties, then the content
35 // object properties become hidden form form elements. For
36 // instance, a content object of {name1 : "value1"} is converted
37 // to a hidden form element with a name of "name1" and a value of
38 // "value1". If there is not a "form" property, then the content
39 // object is converted into a name=value&name=value string, by
40 // using dojo.objectToQuery().
41 this.method = method;
42 this.handleAs = handleAs;
43 this.content = content;
44 }
45});
46=====*/
47
48dojo.io.iframe = {
49 // summary:
50 // Sends an Ajax I/O call using and Iframe (for instance, to upload files)
51
52 create: function(/*String*/fname, /*String*/onloadstr, /*String?*/uri){
53 // summary:
54 // Creates a hidden iframe in the page. Used mostly for IO
55 // transports. You do not need to call this to start a
56 // dojo.io.iframe request. Just call send().
57 // fname: String
58 // The name of the iframe. Used for the name attribute on the
59 // iframe.
60 // onloadstr: String
61 // A string of JavaScript that will be executed when the content
62 // in the iframe loads.
63 // uri: String
64 // The value of the src attribute on the iframe element. If a
65 // value is not given, then dojo/resources/blank.html will be
66 // used.
67 if(window[fname]){ return window[fname]; }
68 if(window.frames[fname]){ return window.frames[fname]; }
69 var turi = uri;
70 if(!turi){
71 if(dojo.config["useXDomain"] && !dojo.config["dojoBlankHtmlUrl"]){
72 console.warn("dojo.io.iframe.create: When using cross-domain Dojo builds,"
73 + " please save dojo/resources/blank.html to your domain and set djConfig.dojoBlankHtmlUrl"
74 + " to the path on your domain to blank.html");
75 }
76 turi = (dojo.config["dojoBlankHtmlUrl"]||require.toUrl("../resources/blank.html"));
77 }
78 var cframe = dojo.place(
79 '<iframe id="'+fname+'" name="'+fname+'" src="'+turi+'" onload="'+onloadstr+
80 '" style="position: absolute; left: 1px; top: 1px; height: 1px; width: 1px; visibility: hidden">',
81 dojo.body());
82
83 window[fname] = cframe;
84
85 return cframe;
86 },
87
88 setSrc: function(/*DOMNode*/iframe, /*String*/src, /*Boolean*/replace){
89 //summary:
90 // Sets the URL that is loaded in an IFrame. The replace parameter
91 // indicates whether location.replace() should be used when
92 // changing the location of the iframe.
93 try{
94 if(!replace){
95 if(dojo.isWebKit){
96 iframe.location = src;
97 }else{
98 frames[iframe.name].location = src;
99 }
100 }else{
101 // Fun with DOM 0 incompatibilities!
102 var idoc;
103 if(dojo.isIE || dojo.isWebKit){
104 idoc = iframe.contentWindow.document;
105 }else{ // if(d.isMozilla){
106 idoc = iframe.contentWindow;
107 }
108
109 //For Safari (at least 2.0.3) and Opera, if the iframe
110 //has just been created but it doesn't have content
111 //yet, then iframe.document may be null. In that case,
112 //use iframe.location and return.
113 if(!idoc){
114 iframe.location = src;
115 }else{
116 idoc.location.replace(src);
117 }
118 }
119 }catch(e){
120 console.log("dojo.io.iframe.setSrc: ", e);
121 }
122 },
123
124 doc: function(/*DOMNode*/iframeNode){
125 //summary: Returns the document object associated with the iframe DOM Node argument.
126 return iframeNode.contentDocument || // W3
127 (
128 (
129 (iframeNode.name) && (iframeNode.document) &&
130 (dojo.doc.getElementsByTagName("iframe")[iframeNode.name].contentWindow) &&
131 (dojo.doc.getElementsByTagName("iframe")[iframeNode.name].contentWindow.document)
132 )
133 ) || // IE
134 (
135 (iframeNode.name)&&(dojo.doc.frames[iframeNode.name])&&
136 (dojo.doc.frames[iframeNode.name].document)
137 ) || null;
138 },
139
140 send: function(/*dojo.io.iframe.__ioArgs*/args){
141 //summary:
142 // Function that sends the request to the server.
143 // This transport can only process one send() request at a time, so if send() is called
144 //multiple times, it will queue up the calls and only process one at a time.
145 if(!this["_frame"]){
146 this._frame = this.create(this._iframeName, dojo._scopeName + ".io.iframe._iframeOnload();");
147 }
148
149 //Set up the deferred.
150 var dfd = dojo._ioSetArgs(
151 args,
152 function(/*Deferred*/dfd){
153 //summary: canceller function for dojo._ioSetArgs call.
154 dfd.canceled = true;
155 dfd.ioArgs._callNext();
156 },
157 function(/*Deferred*/dfd){
158 //summary: okHandler function for dojo._ioSetArgs call.
159 var value = null;
160 try{
161 var ioArgs = dfd.ioArgs;
162 var dii = dojo.io.iframe;
163 var ifd = dii.doc(dii._frame);
164 var handleAs = ioArgs.handleAs;
165
166 //Assign correct value based on handleAs value.
167 value = ifd; //html
168 if(handleAs != "html"){
169 if(handleAs == "xml"){
170 // FF, Saf 3+ and Opera all seem to be fine with ifd being xml. We have to
171 // do it manually for IE6-8. Refs #6334.
172 if(dojo.isIE < 9 || (dojo.isIE && dojo.isQuirks)){
173 dojo.query("a", dii._frame.contentWindow.document.documentElement).orphan();
174 var xmlText=(dii._frame.contentWindow.document).documentElement.innerText;
175 xmlText=xmlText.replace(/>\s+</g, "><");
176 xmlText=dojo.trim(xmlText);
177 //Reusing some code in base dojo for handling XML content. Simpler and keeps
178 //Core from duplicating the effort needed to locate the XML Parser on IE.
179 var fauxXhr = { responseText: xmlText };
180 value = dojo._contentHandlers["xml"](fauxXhr); // DOMDocument
181 }
182 }else{
183 value = ifd.getElementsByTagName("textarea")[0].value; //text
184 if(handleAs == "json"){
185 value = dojo.fromJson(value); //json
186 }else if(handleAs == "javascript"){
187 value = dojo.eval(value); //javascript
188 }
189 }
190 }
191 }catch(e){
192 value = e;
193 }finally{
194 ioArgs._callNext();
195 }
196 return value;
197 },
198 function(/*Error*/error, /*Deferred*/dfd){
199 //summary: errHandler function for dojo._ioSetArgs call.
200 dfd.ioArgs._hasError = true;
201 dfd.ioArgs._callNext();
202 return error;
203 }
204 );
205
206 //Set up a function that will fire the next iframe request. Make sure it only
207 //happens once per deferred.
208 dfd.ioArgs._callNext = function(){
209 if(!this["_calledNext"]){
210 this._calledNext = true;
211 dojo.io.iframe._currentDfd = null;
212 dojo.io.iframe._fireNextRequest();
213 }
214 };
215
216 this._dfdQueue.push(dfd);
217 this._fireNextRequest();
218
219 //Add it the IO watch queue, to get things like timeout support.
220 dojo._ioWatch(
221 dfd,
222 function(/*Deferred*/dfd){
223 //validCheck
224 return !dfd.ioArgs["_hasError"];
225 },
226 function(dfd){
227 //ioCheck
228 return (!!dfd.ioArgs["_finished"]);
229 },
230 function(dfd){
231 //resHandle
232 if(dfd.ioArgs._finished){
233 dfd.callback(dfd);
234 }else{
235 dfd.errback(new Error("Invalid dojo.io.iframe request state"));
236 }
237 }
238 );
239
240 return dfd;
241 },
242
243 _currentDfd: null,
244 _dfdQueue: [],
245 _iframeName: dojo._scopeName + "IoIframe",
246
247 _fireNextRequest: function(){
248 //summary: Internal method used to fire the next request in the bind queue.
249 try{
250 if((this._currentDfd)||(this._dfdQueue.length == 0)){ return; }
251 //Find next deferred, skip the canceled ones.
252 do{
253 var dfd = this._currentDfd = this._dfdQueue.shift();
254 } while(dfd && dfd.canceled && this._dfdQueue.length);
255
256 //If no more dfds, cancel.
257 if(!dfd || dfd.canceled){
258 this._currentDfd = null;
259 return;
260 }
261
262 var ioArgs = dfd.ioArgs;
263 var args = ioArgs.args;
264
265 ioArgs._contentToClean = [];
266 var fn = dojo.byId(args["form"]);
267 var content = args["content"] || {};
268 if(fn){
269 if(content){
270 // if we have things in content, we need to add them to the form
271 // before submission
272 var pHandler = function(name, value) {
273 dojo.create("input", {type: "hidden", name: name, value: value}, fn);
274 ioArgs._contentToClean.push(name);
275 };
276 for(var x in content){
277 var val = content[x];
278 if(dojo.isArray(val) && val.length > 1){
279 var i;
280 for (i = 0; i < val.length; i++) {
281 pHandler(x,val[i]);
282 }
283 }else{
284 if(!fn[x]){
285 pHandler(x,val);
286 }else{
287 fn[x].value = val;
288 }
289 }
290 }
291 }
292 //IE requires going through getAttributeNode instead of just getAttribute in some form cases,
293 //so use it for all. See #2844
294 var actnNode = fn.getAttributeNode("action");
295 var mthdNode = fn.getAttributeNode("method");
296 var trgtNode = fn.getAttributeNode("target");
297 if(args["url"]){
298 ioArgs._originalAction = actnNode ? actnNode.value : null;
299 if(actnNode){
300 actnNode.value = args.url;
301 }else{
302 fn.setAttribute("action",args.url);
303 }
304 }
305 if(!mthdNode || !mthdNode.value){
306 if(mthdNode){
307 mthdNode.value= (args["method"]) ? args["method"] : "post";
308 }else{
309 fn.setAttribute("method", (args["method"]) ? args["method"] : "post");
310 }
311 }
312 ioArgs._originalTarget = trgtNode ? trgtNode.value: null;
313 if(trgtNode){
314 trgtNode.value = this._iframeName;
315 }else{
316 fn.setAttribute("target", this._iframeName);
317 }
318 fn.target = this._iframeName;
319 dojo._ioNotifyStart(dfd);
320 fn.submit();
321 }else{
322 // otherwise we post a GET string by changing URL location for the
323 // iframe
324 var tmpUrl = args.url + (args.url.indexOf("?") > -1 ? "&" : "?") + ioArgs.query;
325 dojo._ioNotifyStart(dfd);
326 this.setSrc(this._frame, tmpUrl, true);
327 }
328 }catch(e){
329 dfd.errback(e);
330 }
331 },
332
333 _iframeOnload: function(){
334 var dfd = this._currentDfd;
335 if(!dfd){
336 this._fireNextRequest();
337 return;
338 }
339
340 var ioArgs = dfd.ioArgs;
341 var args = ioArgs.args;
342 var fNode = dojo.byId(args.form);
343
344 if(fNode){
345 // remove all the hidden content inputs
346 var toClean = ioArgs._contentToClean;
347 for(var i = 0; i < toClean.length; i++) {
348 var key = toClean[i];
349 //Need to cycle over all nodes since we may have added
350 //an array value which means that more than one node could
351 //have the same .name value.
352 for(var j = 0; j < fNode.childNodes.length; j++){
353 var chNode = fNode.childNodes[j];
354 if(chNode.name == key){
355 dojo.destroy(chNode);
356 break;
357 }
358 }
359 }
360
361 // restore original action + target
362 if(ioArgs["_originalAction"]){
363 fNode.setAttribute("action", ioArgs._originalAction);
364 }
365 if(ioArgs["_originalTarget"]){
366 fNode.setAttribute("target", ioArgs._originalTarget);
367 fNode.target = ioArgs._originalTarget;
368 }
369 }
370
371 ioArgs._finished = true;
372 }
373};
374
375return dojo.io.iframe;
376});