summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
Diffstat (limited to 'plugins/jetpack/_inc/jquery.jetpack-resize.js')
-rw-r--r--plugins/jetpack/_inc/jquery.jetpack-resize.js292
1 files changed, 292 insertions, 0 deletions
diff --git a/plugins/jetpack/_inc/jquery.jetpack-resize.js b/plugins/jetpack/_inc/jquery.jetpack-resize.js
new file mode 100644
index 00000000..8c044339
--- /dev/null
+++ b/plugins/jetpack/_inc/jquery.jetpack-resize.js
@@ -0,0 +1,292 @@
+/* global Jetpack, JSON */
+/**
+ * Resizeable Iframes.
+ *
+ * Start listening to resize postMessage events for selected iframes:
+ * $( selector ).Jetpack( 'resizeable' );
+ * - OR -
+ * Jetpack.resizeable( 'on', context );
+ *
+ * Resize selected iframes:
+ * $( selector ).Jetpack( 'resizeable', 'resize', { width: 100, height: 200 } );
+ * - OR -
+ * Jetpack.resizeable( 'resize', { width: 100, height: 200 }, context );
+ *
+ * Stop listening to resize postMessage events for selected iframes:
+ * $( selector ).Jetpack( 'resizeable', 'off' );
+ * - OR -
+ * Jetpack.resizeable( 'off', context );
+ *
+ * Stop listening to all resize postMessage events:
+ * Jetpack.resizeable( 'off' );
+ */
+( function( $ ) {
+ var listening = false, // Are we listening for resize postMessage events
+ sourceOrigins = [], // What origins are allowed to send resize postMessage events
+ $sources = false, // What iframe elements are we tracking resize postMessage events from
+ URLtoOrigin, // Utility to convert URLs into origins
+ setupListener, // Binds global resize postMessage event handler
+ destroyListener, // Unbinds global resize postMessage event handler
+ methods; // Jetpack.resizeable methods
+
+ // Setup the Jetpack global
+ if ( 'undefined' === typeof window.Jetpack ) {
+ window.Jetpack = {
+ /**
+ * Handles the two different calling methods:
+ * $( selector ).Jetpack( 'namespace', 'method', context ) // here, context is optional and is used to filter the collection
+ * - vs. -
+ * Jetpack.namespace( 'method', context ) // here context defines the collection
+ *
+ * @internal
+ *
+ * Call as: Jetpack.getTarget.call( this, context )
+ *
+ * @param string context: jQuery selector
+ * @return jQuery|undefined object on which to perform operations or undefined when context cannot be determined
+ */
+ getTarget: function( context ) {
+ if ( this instanceof jQuery ) {
+ return context ? this.filter( context ) : this;
+ }
+
+ return context ? $( context ) : context;
+ },
+ };
+ }
+
+ // Setup the Jetpack jQuery method
+ if ( 'undefined' === typeof $.fn.Jetpack ) {
+ /**
+ * Dispatches calls to the correct namespace
+ *
+ * @param string namespace
+ * @param ...
+ * @return mixed|jQuery (chainable)
+ */
+ $.fn.Jetpack = function( namespace ) {
+ if ( 'function' === typeof Jetpack[ namespace ] ) {
+ // Send the call to the correct Jetpack.namespace
+ return Jetpack[ namespace ].apply( this, Array.prototype.slice.call( arguments, 1 ) );
+ } else {
+ $.error( 'Namespace "' + namespace + '" does not exist on jQuery.Jetpack' );
+ }
+ };
+ }
+
+ // Define Jetpack.resizeable() namespace to just always bail if no postMessage
+ if ( 'function' !== typeof window.postMessage ) {
+ $.extend( window.Jetpack, {
+ /**
+ * Defines the Jetpack.resizeable() namespace.
+ * See below for non-trivial definition for browsers with postMessage.
+ */
+ resizeable: function() {
+ $.error( 'Browser does not support window.postMessage' );
+ },
+ } );
+
+ return;
+ }
+
+ /**
+ * Utility to convert URLs into origins
+ *
+ * http://example.com:port/path?query#fragment -> http://example.com:port
+ *
+ * @param string URL
+ * @return string origin
+ */
+ URLtoOrigin = function( URL ) {
+ if ( ! URL.match( /^https?:\/\// ) ) {
+ URL = document.location.href;
+ }
+ return URL.split( '/' )
+ .slice( 0, 3 )
+ .join( '/' );
+ };
+
+ /**
+ * Binds global resize postMessage event handler
+ */
+ setupListener = function() {
+ listening = true;
+
+ $( window ).on( 'message.JetpackResizeableIframe', function( e ) {
+ var event = e.originalEvent,
+ data;
+
+ // Ensure origin is allowed
+ if ( -1 === $.inArray( event.origin, sourceOrigins ) ) {
+ return;
+ }
+
+ // Some browsers send structured data, some send JSON strings
+ if ( 'object' === typeof event.data ) {
+ data = event.data.data;
+ } else {
+ try {
+ data = JSON.parse( event.data );
+ } catch ( err ) {
+ data = false;
+ }
+ }
+
+ if ( ! data.data ) {
+ return;
+ }
+
+ // Un-nest
+ data = data.data;
+
+ // Is it a resize event?
+ if ( 'undefined' === typeof data.action || 'resize' !== data.action ) {
+ return;
+ }
+
+ // Find the correct iframe and resize it
+ $sources
+ .filter( function() {
+ if ( 'undefined' !== typeof data.name ) {
+ return this.name === data.name;
+ } else {
+ return event.source === this.contentWindow;
+ }
+ } )
+ .first()
+ .Jetpack( 'resizeable', 'resize', data );
+ } );
+ };
+
+ /**
+ * Unbinds global resize postMessage event handler
+ */
+ destroyListener = function() {
+ listening = false;
+ $( window ).off( 'message.JetpackResizeableIframe' );
+
+ sourceOrigins = [];
+ $( '.jetpack-resizeable' ).removeClass( 'jetpack-resizeable' );
+ $sources = false;
+ };
+
+ // Methods for Jetpack.resizeable() namespace
+ methods = {
+ /**
+ * Start listening for resize postMessage events on the given iframes
+ *
+ * Call statically as: Jetpack.resizeable( 'on', context )
+ * Call as: $( selector ).Jetpack( 'resizeable', 'on', context ) // context optional: used to filter the collectino
+ *
+ * @param string context jQuery selector.
+ * @return jQuery (chainable)
+ */
+ on: function( context ) {
+ var target = Jetpack.getTarget.call( this, context );
+
+ if ( ! listening ) {
+ setupListener();
+ }
+
+ target
+ .each( function() {
+ sourceOrigins.push( URLtoOrigin( $( this ).attr( 'src' ) ) );
+ } )
+ .addClass( 'jetpack-resizeable' );
+
+ $sources = $( '.jetpack-resizeable' );
+
+ return target;
+ },
+
+ /**
+ * Stop listening for resize postMessage events on the given iframes
+ *
+ * Call statically as: Jetpack.resizeable( 'off', context )
+ * Call as: $( selector ).Jetpack( 'resizeable', 'off', context ) // context optional: used to filter the collectino
+ *
+ * @param string context jQuery selector
+ * @return jQuery (chainable)
+ */
+ off: function( context ) {
+ var target = Jetpack.getTarget.call( this, context );
+
+ if ( 'undefined' === typeof target ) {
+ destroyListener();
+
+ return target;
+ }
+
+ target
+ .each( function() {
+ var origin = URLtoOrigin( $( this ).attr( 'src' ) ),
+ pos = $.inArray( origin, sourceOrigins );
+
+ if ( -1 !== pos ) {
+ sourceOrigins.splice( pos, 1 );
+ }
+ } )
+ .removeClass( 'jetpack-resizeable' );
+
+ $sources = $( '.jetpack-resizeable' );
+
+ return target;
+ },
+
+ /**
+ * Resize the given iframes
+ *
+ * Call statically as: Jetpack.resizeable( 'resize', dimensions, context )
+ * Call as: $( selector ).Jetpack( 'resizeable', 'resize', dimensions, context ) // context optional: used to filter the collectino
+ *
+ * @param object dimensions in pixels: { width: (int), height: (int) }
+ * @param string context jQuery selector
+ * @return jQuery (chainable)
+ */
+ resize: function( dimensions, context ) {
+ var target = Jetpack.getTarget.call( this, context );
+
+ $.each( [ 'width', 'height' ], function( i, variable ) {
+ var value = 0,
+ container;
+ if ( 'undefined' !== typeof dimensions[ variable ] ) {
+ value = parseInt( dimensions[ variable ], 10 );
+ }
+
+ if ( 0 !== value ) {
+ target[ variable ]( value );
+ container = target.parent();
+ if ( container.hasClass( 'slim-likes-widget' ) ) {
+ container[ variable ]( value );
+ }
+ }
+ } );
+
+ return target;
+ },
+ };
+
+ // Define Jetpack.resizeable() namespace
+ $.extend( window.Jetpack, {
+ /**
+ * Defines the Jetpack.resizeable() namespace.
+ * See above for trivial definition for browsers with no postMessage.
+ *
+ * @param string method
+ * @param ...
+ * @return mixed|jQuery (chainable)
+ */
+ resizeable: function( method ) {
+ if ( methods[ method ] ) {
+ // Send the call to the correct Jetpack.resizeable() method
+ return methods[ method ].apply( this, Array.prototype.slice.call( arguments, 1 ) );
+ } else if ( ! method ) {
+ // By default, send to Jetpack.resizeable( 'on' ), which isn't useful in that form but is when called as
+ // jQuery( selector ).Jetpack( 'resizeable' )
+ return methods.on.apply( this );
+ } else {
+ $.error( 'Method ' + method + ' does not exist on Jetpack.resizeable' );
+ }
+ },
+ } );
+} )( jQuery );