Skip to content

Instantly share code, notes, and snippets.

@thanpolas
Last active August 8, 2018 03:06
Show Gist options
  • Save thanpolas/723d0ec4ac418841eec0 to your computer and use it in GitHub Desktop.
Save thanpolas/723d0ec4ac418841eec0 to your computer and use it in GitHub Desktop.
In the absence of CORS support the Hidden Iframe technique is the only way to submit a big amount of data (over 2kb that jsonp can handle).
/**
* @fileOverview Hidden iFrame implementation for browsers without CORS.
*
* Usage:
* var iframe = new Iframe();
* iframe.submit(url, {data: yourData}, function(err) {});
*
* The server will get a POST request on the defined URL with the data
* JSON encoded in the body attribute named "data".
*/
var noop = function() {};
/**
* Hidden iFrame implementation for browsers without CORS.
*
* @constructor
*/
var Iframe = module.exports = function() {
/** @type {String} The target action of the form submission */
this.url = '';
/** @type {Object} Contains the invoke options */
this.opts = {};
/** @type {Function} User defined callback */
this.cb = noop;
/** @type {?Document.iframe} iframe document instance */
this.iframe = null;
/** @type {?Document.form} form document instance */
this.form = null;
/** @type {String} The name / id of the iframe */
this.iframeName = 'hidden_iframe_submit';
/** @type {?Document.iframe} The iframe element on the DOM */
this.iframeEl = null;
this._iframeLoadBinded = this._onIframeLoad.bind(this);
};
/**
* Submit data using a hidden iframe.
*
* @param {string} url The url to submit to.
* @param {Object} opts Options for the submission.
* @param {*} data Data to send.
* @param {Function} cb Nodejs Callback.
*/
Iframe.prototype.submit = function(url, opts, cb) {
this.url = url;
this.cb = cb;
this.opts = opts;
this._createIframe();
this._createForm();
document.body.appendChild(this.form);
document.body.appendChild(this.iframe);
this.iframeEl = document.getElementById(this.iframeName);
if (this.iframeEl.addEventListener) {
this.iframeEl.addEventListener('load', this._iframeLoadBinded, true);
}
if (this.iframeEl.attachEvent) {
this.iframeEl.attachEvent('onload', this._iframeLoadBinded);
}
this.form.submit();
};
/**
* Triggers when iframe emits the onload event.
*
* @private
*/
Iframe.prototype._onIframeLoad = function() {
// Add event...
if (this.iframeEl.detachEvent) {
this.iframeEl.detachEvent('onload', this._iframeLoadBinded);
} else {
this.iframeEl.removeEventListener('load', this._iframeLoadBinded, false);
}
this.cb(null);
};
/**
* Create the iframe object.
*
* @private
*/
Iframe.prototype._createIframe = function() {
var iframe = this.iframe = document.createElement('iframe');
iframe.style.display = 'none';
iframe.setAttribute('name', this.iframeName);
iframe.setAttribute('id', this.iframeName);
iframe.setAttribute('width', '0');
iframe.setAttribute('height', '0');
iframe.setAttribute('border', '0');
iframe.setAttribute('src', 'javascript:false;');
};
/**
* Create the form to submit.
*
* @private
*/
Iframe.prototype._createForm = function() {
var form = this.form = document.createElement('form');
form.style.display = 'none';
form.setAttribute('target', this.iframeName);
form.setAttribute('action', this.url);
form.setAttribute('method', 'post');
form.setAttribute('enctype', 'application/x-www-form-urlencoded');
form.setAttribute('encoding', 'application/x-www-form-urlencoded');
var input = document.createElement('input');
input.style.display = 'none';
input.setAttribute('type', 'text');
input.setAttribute('name', 'data');
var data = this._jsonData();
input.setAttribute('value', data);
form.appendChild(input);
};
/**
* JSON Stringify the incoming data.
*
* @return {string} JSON Encoded string.
* @private
*/
Iframe.prototype._jsonData = function() {
var data = {};
try {
data = JSON.stringify(this.opts.data);
} catch(ex) {
// no action
}
return data;
};
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment