source: Dev/trunk/src/client/dojo/request/iframe.js @ 485

Last change on this file since 485 was 483, checked in by hendrikvanantwerpen, 11 years ago

Added Dojo 1.9.3 release.

File size: 11.4 KB
Line 
1define([
2        'module',
3        'require',
4        './watch',
5        './util',
6        './handlers',
7        '../_base/lang',
8        '../io-query',
9        '../query',
10        '../has',
11        '../dom',
12        '../dom-construct',
13        '../_base/window',
14        '../NodeList-dom'/*=====,
15        '../request',
16        '../_base/declare' =====*/
17], function(module, require, watch, util, handlers, lang, ioQuery, query, has, dom, domConstruct, win/*=====, NodeList, request, declare =====*/){
18        var mid = module.id.replace(/[\/\.\-]/g, '_'),
19                onload = mid + '_onload';
20
21        if(!win.global[onload]){
22                win.global[onload] = function(){
23                        var dfd = iframe._currentDfd;
24                        if(!dfd){
25                                iframe._fireNextRequest();
26                                return;
27                        }
28
29                        var response = dfd.response,
30                                options = response.options,
31                                formNode = dom.byId(options.form) || dfd._tmpForm;
32
33                        if(formNode){
34                                // remove all the hidden content inputs
35                                var toClean = dfd._contentToClean;
36                                for(var i=0; i<toClean.length; i++){
37                                        var key = toClean[i];
38                                        //Need to cycle over all nodes since we may have added
39                                        //an array value which means that more than one node could
40                                        //have the same .name value.
41                                        for(var j=0; j<formNode.childNodes.length; j++){
42                                                var childNode = formNode.childNodes[j];
43                                                if(childNode.name === key){
44                                                        domConstruct.destroy(childNode);
45                                                        break;
46                                                }
47                                        }
48                                }
49
50                                // restore original action + target
51                                dfd._originalAction && formNode.setAttribute('action', dfd._originalAction);
52                                if(dfd._originalMethod){
53                                        formNode.setAttribute('method', dfd._originalMethod);
54                                        formNode.method = dfd._originalMethod;
55                                }
56                                if(dfd._originalTarget){
57                                        formNode.setAttribute('target', dfd._originalTarget);
58                                        formNode.target = dfd._originalTarget;
59                                }
60                        }
61
62                        if(dfd._tmpForm){
63                                domConstruct.destroy(dfd._tmpForm);
64                                delete dfd._tmpForm;
65                        }
66
67                        dfd._finished = true;
68                };
69        }
70
71        function create(name, onloadstr, uri){
72                if(win.global[name]){
73                        return win.global[name];
74                }
75
76                if(win.global.frames[name]){
77                        return win.global.frames[name];
78                }
79
80                if(!uri){
81                        if(has('config-useXDomain') && !has('config-dojoBlankHtmlUrl')){
82                                console.warn('dojo/request/iframe: When using cross-domain Dojo builds,' +
83                                        ' please save dojo/resources/blank.html to your domain and set dojoConfig.dojoBlankHtmlUrl' +
84                                        ' to the path on your domain to blank.html');
85                        }
86                        uri = (has('config-dojoBlankHtmlUrl')||require.toUrl('dojo/resources/blank.html'));
87                }
88
89                var frame = domConstruct.place(
90                        '<iframe id="'+name+'" name="'+name+'" src="'+uri+'" onload="'+onloadstr+
91                        '" style="position: absolute; left: 1px; top: 1px; height: 1px; width: 1px; visibility: hidden">',
92                        win.body());
93
94                win.global[name] = frame;
95
96                return frame;
97        }
98
99        function setSrc(_iframe, src, replace){
100                var frame = win.global.frames[_iframe.name];
101
102                if(frame.contentWindow){
103                        // We have an iframe node instead of the window
104                        frame = frame.contentWindow;
105                }
106
107                try{
108                        if(!replace){
109                                frame.location = src;
110                        }else{
111                                frame.location.replace(src);
112                        }
113                }catch(e){
114                        console.log('dojo/request/iframe.setSrc: ', e);
115                }
116        }
117
118        function doc(iframeNode){
119                if(iframeNode.contentDocument){
120                        return iframeNode.contentDocument;
121                }
122                var name = iframeNode.name;
123                if(name){
124                        var iframes = win.doc.getElementsByTagName('iframe');
125                        if(iframeNode.document && iframes[name].contentWindow && iframes[name].contentWindow.document){
126                                return iframes[name].contentWindow.document;
127                        }else if(win.doc.frames[name] && win.doc.frames[name].document){
128                                return win.doc.frames[name].document;
129                        }
130                }
131                return null;
132        }
133
134        function createForm(){
135                return domConstruct.create('form', {
136                        name: mid + '_form',
137                        style: {
138                                position: 'absolute',
139                                top: '-1000px',
140                                left: '-1000px'
141                        }
142                }, win.body());
143        }
144
145        function fireNextRequest(){
146                // summary:
147                //              Internal method used to fire the next request in the queue.
148                var dfd;
149                try{
150                        if(iframe._currentDfd || !iframe._dfdQueue.length){
151                                return;
152                        }
153                        do{
154                                dfd = iframe._currentDfd = iframe._dfdQueue.shift();
155                        }while(dfd && (dfd.canceled || (dfd.isCanceled && dfd.isCanceled())) && iframe._dfdQueue.length);
156
157                        if(!dfd || dfd.canceled || (dfd.isCanceled && dfd.isCanceled())){
158                                iframe._currentDfd = null;
159                                return;
160                        }
161
162                        var response = dfd.response,
163                                options = response.options,
164                                c2c = dfd._contentToClean = [],
165                                formNode = dom.byId(options.form),
166                                notify = util.notify,
167                                data = options.data || null,
168                                queryStr;
169
170                        if(!dfd._legacy && options.method === 'POST' && !formNode){
171                                formNode = dfd._tmpForm = createForm();
172                        }else if(options.method === 'GET' && formNode && response.url.indexOf('?') > -1){
173                                queryStr = response.url.slice(response.url.indexOf('?') + 1);
174                                data = lang.mixin(ioQuery.queryToObject(queryStr), data);
175                        }
176
177                        if(formNode){
178                                if(!dfd._legacy){
179                                        var parentNode = formNode;
180                                        do{
181                                                parentNode = parentNode.parentNode;
182                                        }while(parentNode !== win.doc.documentElement);
183
184                                        // Append the form node or some browsers won't work
185                                        if(!parentNode){
186                                                formNode.style.position = 'absolute';
187                                                formNode.style.left = '-1000px';
188                                                formNode.style.top = '-1000px';
189                                                win.body().appendChild(formNode);
190                                        }
191
192                                        if(!formNode.name){
193                                                formNode.name = mid + '_form';
194                                        }
195                                }
196
197                                // if we have things in data, we need to add them to the form
198                                // before submission
199                                if(data){
200                                        var createInput = function(name, value){
201                                                domConstruct.create('input', {
202                                                        type: 'hidden',
203                                                        name: name,
204                                                        value: value
205                                                }, formNode);
206                                                c2c.push(name);
207                                        };
208                                        for(var x in data){
209                                                var val = data[x];
210                                                if(lang.isArray(val) && val.length > 1){
211                                                        for(var i=0; i<val.length; i++){
212                                                                createInput(x, val[i]);
213                                                        }
214                                                }else{
215                                                        if(!formNode[x]){
216                                                                createInput(x, val);
217                                                        }else{
218                                                                formNode[x].value = val;
219                                                        }
220                                                }
221                                        }
222                                }
223
224                                //IE requires going through getAttributeNode instead of just getAttribute in some form cases,
225                                //so use it for all.  See #2844
226                                var actionNode = formNode.getAttributeNode('action'),
227                                        methodNode = formNode.getAttributeNode('method'),
228                                        targetNode = formNode.getAttributeNode('target');
229
230                                if(response.url){
231                                        dfd._originalAction = actionNode ? actionNode.value : null;
232                                        if(actionNode){
233                                                actionNode.value = response.url;
234                                        }else{
235                                                formNode.setAttribute('action', response.url);
236                                        }
237                                }
238
239                                if(!dfd._legacy){
240                                        dfd._originalMethod = methodNode ? methodNode.value : null;
241                                        if(methodNode){
242                                                methodNode.value = options.method;
243                                        }else{
244                                                formNode.setAttribute('method', options.method);
245                                        }
246                                }else{
247                                        if(!methodNode || !methodNode.value){
248                                                if(methodNode){
249                                                        methodNode.value = options.method;
250                                                }else{
251                                                        formNode.setAttribute('method', options.method);
252                                                }
253                                        }
254                                }
255
256                                dfd._originalTarget = targetNode ? targetNode.value : null;
257                                if(targetNode){
258                                        targetNode.value = iframe._iframeName;
259                                }else{
260                                        formNode.setAttribute('target', iframe._iframeName);
261                                }
262                                formNode.target = iframe._iframeName;
263
264                                notify && notify.emit('send', response, dfd.promise.cancel);
265                                iframe._notifyStart(response);
266                                formNode.submit();
267                        }else{
268                                // otherwise we post a GET string by changing URL location for the
269                                // iframe
270
271                                var extra = '';
272                                if(response.options.data){
273                                        extra = response.options.data;
274                                        if(typeof extra !== 'string'){
275                                                extra = ioQuery.objectToQuery(extra);
276                                        }
277                                }
278                                var tmpUrl = response.url + (response.url.indexOf('?') > -1 ? '&' : '?') + extra;
279                                notify && notify.emit('send', response, dfd.promise.cancel);
280                                iframe._notifyStart(response);
281                                iframe.setSrc(iframe._frame, tmpUrl, true);
282                        }
283                }catch(e){
284                        dfd.reject(e);
285                }
286        }
287
288        // dojo/request/watch handlers
289        function isValid(response){
290                return !this.isFulfilled();
291        }
292        function isReady(response){
293                return !!this._finished;
294        }
295        function handleResponse(response, error){
296                if(!error){
297                        try{
298                                var options = response.options,
299                                        doc = iframe.doc(iframe._frame),
300                                        handleAs = options.handleAs;
301
302                                if(handleAs !== 'html'){
303                                        if(handleAs === 'xml'){
304                                                // IE6-8 have to parse the XML manually. See http://bugs.dojotoolkit.org/ticket/6334
305                                                if(doc.documentElement.tagName.toLowerCase() === 'html'){
306                                                        query('a', doc.documentElement).orphan();
307                                                        var xmlText = doc.documentElement.innerText;
308                                                        xmlText = xmlText.replace(/>\s+</g, '><');
309                                                        response.text = lang.trim(xmlText);
310                                                }else{
311                                                        response.data = doc;
312                                                }
313                                        }else{
314                                                // 'json' and 'javascript' and 'text'
315                                                response.text = doc.getElementsByTagName('textarea')[0].value; // text
316                                        }
317                                        handlers(response);
318                                }else{
319                                        response.data = doc;
320                                }
321                        }catch(e){
322                                error = e;
323                        }
324                }
325
326                if(error){
327                        this.reject(error);
328                }else if(this._finished){
329                        this.resolve(response);
330                }else{
331                        this.reject(new Error('Invalid dojo/request/iframe request state'));
332                }
333        }
334        function last(response){
335                this._callNext();
336        }
337
338        var defaultOptions = {
339                method: 'POST'
340        };
341        function iframe(url, options, returnDeferred){
342                var response = util.parseArgs(url, util.deepCreate(defaultOptions, options), true);
343                url = response.url;
344                options = response.options;
345
346                if(options.method !== 'GET' && options.method !== 'POST'){
347                        throw new Error(options.method + ' not supported by dojo/request/iframe');
348                }
349
350                if(!iframe._frame){
351                        iframe._frame = iframe.create(iframe._iframeName, onload + '();');
352                }
353
354                var dfd = util.deferred(response, null, isValid, isReady, handleResponse, last);
355                dfd._callNext = function(){
356                        if(!this._calledNext){
357                                this._calledNext = true;
358                                iframe._currentDfd = null;
359                                iframe._fireNextRequest();
360                        }
361                };
362                dfd._legacy = returnDeferred;
363
364                iframe._dfdQueue.push(dfd);
365                iframe._fireNextRequest();
366
367                watch(dfd);
368
369                return returnDeferred ? dfd : dfd.promise;
370        }
371
372        /*=====
373        iframe = function(url, options){
374                // summary:
375                //              Sends a request using an iframe element with the given URL and options.
376                // url: String
377                //              URL to request
378                // options: dojo/request/iframe.__Options?
379                //              Options for the request.
380                // returns: dojo/request.__Promise
381        };
382        iframe.__BaseOptions = declare(request.__BaseOptions, {
383                // form: DOMNode?
384                //              A form node to use to submit data to the server.
385                // data: String|Object?
386                //              Data to transfer. When making a GET request, this will
387                //              be converted to key=value parameters and appended to the
388                //              URL.
389        });
390        iframe.__MethodOptions = declare(null, {
391                // method: String?
392                //              The HTTP method to use to make the request. Must be
393                //              uppercase. Only `"GET"` and `"POST"` are accepted.
394                //              Default is `"POST"`.
395        });
396        iframe.__Options = declare([iframe.__BaseOptions, iframe.__MethodOptions]);
397
398        iframe.get = function(url, options){
399                // summary:
400                //              Send an HTTP GET request using an iframe element with the given URL and options.
401                // url: String
402                //              URL to request
403                // options: dojo/request/iframe.__BaseOptions?
404                //              Options for the request.
405                // returns: dojo/request.__Promise
406        };
407        iframe.post = function(url, options){
408                // summary:
409                //              Send an HTTP POST request using an iframe element with the given URL and options.
410                // url: String
411                //              URL to request
412                // options: dojo/request/iframe.__BaseOptions?
413                //              Options for the request.
414                // returns: dojo/request.__Promise
415        };
416        =====*/
417        iframe.create = create;
418        iframe.doc = doc;
419        iframe.setSrc = setSrc;
420
421        // TODO: Make these truly private in 2.0
422        iframe._iframeName = mid + '_IoIframe';
423        iframe._notifyStart = function(){};
424        iframe._dfdQueue = [];
425        iframe._currentDfd = null;
426        iframe._fireNextRequest = fireNextRequest;
427
428        util.addCommonMethods(iframe, ['GET', 'POST']);
429
430        return iframe;
431});
Note: See TracBrowser for help on using the repository browser.