source: Dev/branches/rest-dojo-ui/client/dojo/io/iframe.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: 11.6 KB
Line 
1define(["../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});
Note: See TracBrowser for help on using the repository browser.