1 | 'use strict';
|
---|
2 |
|
---|
3 | var random = require('../../utils/random')
|
---|
4 | , urlUtils = require('../../utils/url')
|
---|
5 | ;
|
---|
6 |
|
---|
7 | var debug = function() {};
|
---|
8 | if (process.env.NODE_ENV !== 'production') {
|
---|
9 | debug = require('debug')('sockjs-client:sender:jsonp');
|
---|
10 | }
|
---|
11 |
|
---|
12 | var form, area;
|
---|
13 |
|
---|
14 | function createIframe(id) {
|
---|
15 | debug('createIframe', id);
|
---|
16 | try {
|
---|
17 | // ie6 dynamic iframes with target="" support (thanks Chris Lambacher)
|
---|
18 | return global.document.createElement('<iframe name="' + id + '">');
|
---|
19 | } catch (x) {
|
---|
20 | var iframe = global.document.createElement('iframe');
|
---|
21 | iframe.name = id;
|
---|
22 | return iframe;
|
---|
23 | }
|
---|
24 | }
|
---|
25 |
|
---|
26 | function createForm() {
|
---|
27 | debug('createForm');
|
---|
28 | form = global.document.createElement('form');
|
---|
29 | form.style.display = 'none';
|
---|
30 | form.style.position = 'absolute';
|
---|
31 | form.method = 'POST';
|
---|
32 | form.enctype = 'application/x-www-form-urlencoded';
|
---|
33 | form.acceptCharset = 'UTF-8';
|
---|
34 |
|
---|
35 | area = global.document.createElement('textarea');
|
---|
36 | area.name = 'd';
|
---|
37 | form.appendChild(area);
|
---|
38 |
|
---|
39 | global.document.body.appendChild(form);
|
---|
40 | }
|
---|
41 |
|
---|
42 | module.exports = function(url, payload, callback) {
|
---|
43 | debug(url, payload);
|
---|
44 | if (!form) {
|
---|
45 | createForm();
|
---|
46 | }
|
---|
47 | var id = 'a' + random.string(8);
|
---|
48 | form.target = id;
|
---|
49 | form.action = urlUtils.addQuery(urlUtils.addPath(url, '/jsonp_send'), 'i=' + id);
|
---|
50 |
|
---|
51 | var iframe = createIframe(id);
|
---|
52 | iframe.id = id;
|
---|
53 | iframe.style.display = 'none';
|
---|
54 | form.appendChild(iframe);
|
---|
55 |
|
---|
56 | try {
|
---|
57 | area.value = payload;
|
---|
58 | } catch (e) {
|
---|
59 | // seriously broken browsers get here
|
---|
60 | }
|
---|
61 | form.submit();
|
---|
62 |
|
---|
63 | var completed = function(err) {
|
---|
64 | debug('completed', id, err);
|
---|
65 | if (!iframe.onerror) {
|
---|
66 | return;
|
---|
67 | }
|
---|
68 | iframe.onreadystatechange = iframe.onerror = iframe.onload = null;
|
---|
69 | // Opera mini doesn't like if we GC iframe
|
---|
70 | // immediately, thus this timeout.
|
---|
71 | setTimeout(function() {
|
---|
72 | debug('cleaning up', id);
|
---|
73 | iframe.parentNode.removeChild(iframe);
|
---|
74 | iframe = null;
|
---|
75 | }, 500);
|
---|
76 | area.value = '';
|
---|
77 | // It is not possible to detect if the iframe succeeded or
|
---|
78 | // failed to submit our form.
|
---|
79 | callback(err);
|
---|
80 | };
|
---|
81 | iframe.onerror = function() {
|
---|
82 | debug('onerror', id);
|
---|
83 | completed();
|
---|
84 | };
|
---|
85 | iframe.onload = function() {
|
---|
86 | debug('onload', id);
|
---|
87 | completed();
|
---|
88 | };
|
---|
89 | iframe.onreadystatechange = function(e) {
|
---|
90 | debug('onreadystatechange', id, iframe.readyState, e);
|
---|
91 | if (iframe.readyState === 'complete') {
|
---|
92 | completed();
|
---|
93 | }
|
---|
94 | };
|
---|
95 | return function() {
|
---|
96 | debug('aborted', id);
|
---|
97 | completed(new Error('Aborted'));
|
---|
98 | };
|
---|
99 | };
|
---|