forked from cowboy/jquery-postmessage
-
Notifications
You must be signed in to change notification settings - Fork 0
/
jquery.ba-postmessage.js
222 lines (198 loc) · 8.42 KB
/
jquery.ba-postmessage.js
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
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
/*!
* jQuery postMessage - v0.5 - 9/11/2009
* http://benalman.com/projects/jquery-postmessage-plugin/
*
* Copyright (c) 2009 "Cowboy" Ben Alman
* Dual licensed under the MIT and GPL licenses.
* http://benalman.com/about/license/
*/
// Script: jQuery postMessage: Cross-domain scripting goodness
//
// *Version: 0.5, Last updated: 9/11/2009*
//
// 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.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 interval_id,
last_hash,
cache_bust = 1,
// 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_url, target ) {
if ( !target_url ) { 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_url.replace( /([^:]+:\/\/[^\/]+).*/, '$1' ) );
} else if ( target_url ) {
// 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.
target.location = target_url.replace( /#.*$/, '' ) + '#' + (+new Date) + (cache_bust++) + '&' + message;
}
};
// 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 ) {
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 the location.hash changes.
interval_id && clearInterval( interval_id );
interval_id = null;
if ( callback ) {
delay = typeof source_origin === 'number'
? source_origin
: typeof delay === 'number'
? delay
: 100;
interval_id = setInterval(function(){
var hash = document.location.hash,
re = /^#?\d+&/;
if ( hash !== last_hash && re.test( hash ) ) {
last_hash = hash;
callback({ data: hash.replace( re, '' ) });
}
}, delay );
}
}
};
})(jQuery);