Blame view

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