Skip to content

Instantly share code, notes, and snippets.

@kyungw00k
Forked from zachleat/jquery.postmessage.js
Created October 31, 2016 16:03
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save kyungw00k/f31a815e2453da6ea49d9c219d81f279 to your computer and use it in GitHub Desktop.
Save kyungw00k/f31a815e2453da6ea49d9c219d81f279 to your computer and use it in GitHub Desktop.
postMessage polyfill for IE < 8 that uses window.name and queues messages so they aren't lost while polling. Requires a JSON.parse polyfill (like JSON.js).
/*!
* jQuery postMessage - v1.0 - 8/26/2011
*
* Copyright (c) 2011 "zachleat" Zach Leatherman
* Copyright (c) 2009 "Cowboy" Ben Alman
* Dual licensed under the MIT and GPL licenses.
* http://jquery.org/license
*/
/* Forked from http://benalman.com/projects/jquery-postmessage-plugin/
* http://benalman.com/about/license/
*/
// Script: jQuery postMessage: Cross-domain scripting goodness
//
// *Version: 1.0, Last updated: 8/24/2011*
//
// Project Home - http://benalman.com/projects/jquery-postmessage-plugin/
// GitHub - http://github.com/cowboy/jquery-postmessage/
// Source - http://github.com/cowboy/jquery-postmessage/raw/master/jquery.ba-postmessage.js
// (Minified) - http://github.com/cowboy/jquery-postmessage/raw/master/jquery.ba-postmessage.min.js (0.9kb)
//
// About: License
//
// Copyright (c) 2009 "Cowboy" Ben Alman,
// Dual licensed under the MIT and GPL licenses.
// http://benalman.com/about/license/
//
// About: Examples
//
// This working example, complete with fully commented code, illustrates one
// way in which this plugin can be used.
//
// Iframe resizing - http://benalman.com/code/projects/jquery-postmessage/examples/iframe/
//
// About: Support and Testing
//
// Information about what version or versions of jQuery this plugin has been
// tested with and what browsers it has been tested in.
//
// jQuery Versions - 1.3.2
// Browsers Tested - Internet Explorer 6-8, Firefox 3, Safari 3-4, Chrome, Opera 9.
//
// About: Release History
//
// 0.6 - (8/24/2011) Using window.name instead of hash, added queueing (otherwise limited to one per 100ms delay)
// 0.5 - (9/11/2009) Improved cache-busting
// 0.4 - (8/25/2009) Initial release
(function($){
'$:nomunge'; // Used by YUI compressor.
// A few vars used in non-awesome browsers.
var receive_interval_id,
send_interval_id,
targets = [],
message_queue = {},
// A var used in awesome browsers.
rm_callback,
// A few convenient shortcuts.
window = this,
FALSE = !1,
// Reused internal strings.
postMessage = 'postMessage',
addEventListener = 'addEventListener',
p_receiveMessage,
// I couldn't get window.postMessage to actually work in Opera 9.64!
has_postMessage = window[postMessage] && !$.browser.opera;
// Method: jQuery.postMessage
//
// This method will call window.postMessage if available, setting the
// targetOrigin parameter to the base of the target_url parameter for maximum
// security in browsers that support it. If window.postMessage is not available,
// the target window's location.hash will be used to pass the message. If an
// object is passed as the message param, it will be serialized into a string
// using the jQuery.param method.
//
// Usage:
//
// > jQuery.postMessage( message, target_url [, target ] );
//
// Arguments:
//
// message - (String) A message to be passed to the other frame.
// message - (Object) An object to be serialized into a params string, using
// the jQuery.param method.
// target_url - (String) The URL of the other frame this window is
// attempting to communicate with. This must be the exact URL (including
// any query string) of the other window for this script to work in
// browsers that don't support window.postMessage.
// target - (Object) A reference to the other frame this window is
// attempting to communicate with. If omitted, defaults to `parent`.
//
// Returns:
//
// Nothing.
$[postMessage] = function( message, target_origin, target, delay ) {
if ( !target_origin ) { return; }
// Serialize the message if not a string. Note that this is the only real
// jQuery dependency for this script. If removed, this script could be
// written as very basic JavaScript.
message = typeof message === 'string' ? message : $.param( message );
// Default to parent if unspecified.
target = target || parent;
if ( has_postMessage ) {
// The browser supports window.postMessage, so call it with a targetOrigin
// set appropriately, based on the target_url parameter.
target[postMessage]( message, target_origin );
} else {
// The browser does not support window.postMessage, so set the location
// of the target to target_url#message. A bit ugly, but it works! A cache
// bust parameter is added to ensure that repeat messages trigger the
// callback.
var index = -1;
for(var j=0, k=targets.length; j<k; j++) {
if(targets[j] == target) {
index = j;
break;
}
}
if(index === -1) {
index = targets.length;
targets.push(target);
}
if(!message_queue[index]) {
message_queue[index] = [];
}
message_queue[index].push({source: location.href, message: message});
send_interval_id && clearInterval( send_interval_id );
send_interval_id = null;
send_interval_id = setInterval(function(){
for(var index in message_queue) {
targets[index].name = JSON.stringify(message_queue[index]);
}
// reset
targets = [];
message_queue = {};
}, delay );
}
};
// Method: jQuery.receiveMessage
//
// Register a single callback for either a window.postMessage call, if
// supported, or if unsupported, for any change in the current window
// location.hash. If window.postMessage is supported and source_origin is
// specified, the source window will be checked against this for maximum
// security. If window.postMessage is unsupported, a polling loop will be
// started to watch for changes to the location.hash.
//
// Note that for simplicity's sake, only a single callback can be registered
// at one time. Passing no params will unbind this event (or stop the polling
// loop), and calling this method a second time with another callback will
// unbind the event (or stop the polling loop) first, before binding the new
// callback.
//
// Also note that if window.postMessage is available, the optional
// source_origin param will be used to test the event.origin property. From
// the MDC window.postMessage docs: This string is the concatenation of the
// protocol and "://", the host name if one exists, and ":" followed by a port
// number if a port is present and differs from the default port for the given
// protocol. Examples of typical origins are https://example.org (implying
// port 443), http://example.net (implying port 80), and http://example.com:8080.
//
// Usage:
//
// > jQuery.receiveMessage( callback [, source_origin ] [, delay ] );
//
// Arguments:
//
// callback - (Function) This callback will execute whenever a <jQuery.postMessage>
// message is received, provided the source_origin matches. If callback is
// omitted, any existing receiveMessage event bind or polling loop will be
// canceled.
// source_origin - (String) If window.postMessage is available and this value
// is not equal to the event.origin property, the callback will not be
// called.
// source_origin - (Function) If window.postMessage is available and this
// function returns false when passed the event.origin property, the
// callback will not be called.
// delay - (Number) An optional zero-or-greater delay in milliseconds at
// which the polling loop will execute (for browser that don't support
// window.postMessage). If omitted, defaults to 100.
//
// Returns:
//
// Nothing!
$.receiveMessage = p_receiveMessage = function( callback, source_origin, delay, retrieve_window) {
if ( has_postMessage ) {
// Since the browser supports window.postMessage, the callback will be
// bound to the actual event associated with window.postMessage.
if ( callback ) {
// Unbind an existing callback if it exists.
rm_callback && p_receiveMessage();
// Bind the callback. A reference to the callback is stored for ease of
// unbinding.
rm_callback = function(e) {
if ( ( typeof source_origin === 'string' && e.origin !== source_origin )
|| ( $.isFunction( source_origin ) && source_origin( e.origin ) === FALSE ) ) {
return FALSE;
}
callback( e );
};
}
if ( window[addEventListener] ) {
window[ callback ? addEventListener : 'removeEventListener' ]( 'message', rm_callback, FALSE );
} else {
window[ callback ? 'attachEvent' : 'detachEvent' ]( 'onmessage', rm_callback );
}
} else {
// Since the browser sucks, a polling loop will be started, and the
// callback will be called whenever window.name changes.
receive_interval_id && clearInterval( receive_interval_id );
receive_interval_id = null;
if ( callback ) {
delay = delay || 100;
receive_interval_id = setInterval(function(){
var raw_messages = window.name;
if ( raw_messages ) {
window.name = '';
var messages = JSON.parse(raw_messages),
source;
for(var j=0, k=messages.length; j<k; j++) {
source = retrieve_window(messages[j].source);
if(source !== false) {
callback({ source: source, data: messages[j].message });
}
}
}
}, delay );
}
}
};
})(jQuery);
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment