100 lines
		
	
	
		
			2.4 KiB
		
	
	
	
		
			JavaScript
		
	
	
	
	
	
			
		
		
	
	
			100 lines
		
	
	
		
			2.4 KiB
		
	
	
	
		
			JavaScript
		
	
	
	
	
	
| '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'));
 | |
|   };
 | |
| };
 | 
