[6a3a178] | 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 | };
|
---|