can3p (can3p) wrote in changelog,
can3p
can3p
changelog

[ljcom] r10653: LJSUP-9016: LJ-like - add donate button

Committer: dpetrov
LJSUP-9016: LJ-like - add donate button
A   trunk/htdocs/js/jquery/
A   trunk/htdocs/js/jquery/jquery.postmessage.js
A   trunk/htdocs/js/jquery/jquery.storage.js
A   trunk/htdocs/misc/xdr.html
Added: trunk/htdocs/js/jquery/jquery.postmessage.js
===================================================================
--- trunk/htdocs/js/jquery/jquery.postmessage.js	                        (rev 0)
+++ trunk/htdocs/js/jquery/jquery.postmessage.js	2011-06-16 04:26:48 UTC (rev 10653)
@@ -0,0 +1,352 @@
+/*!
+ * jQuery rpc plugin.
+ * @author Dmitry Petrov <Dmitry.Petrov@sup.com>, 2011
+ *
+ * Plugin is used to allow crossdomain communication between container window and child
+ * popups. To make communication work in older browsers, user has to put html (xfr.html) file in the
+ * root of container page domain.
+ *
+ * To allow communication either container should initiate communication or child popup
+ * should know the origin of the container ( protocol://host:port ).
+ *
+ * Contents of xdr.html:
+ * <!DOCTYPE HTML>
+ * <html lang="en">
+ * <head>
+ *     <meta charset="UTF-8">
+ *     <script type="text/javascript">
+ *         function sendData() {
+ *             if ( location.hash && location.hash.length > 1 ) {
+ *                 window.parent.opener.rpcMessage = location.hash;
+ *                 location.hash = '#';
+ *             }
+ *         }
+ * 
+ *         setInterval( sendData, 50 );
+ *     </script>
+ * </head>
+ * <body>
+ * </body>
+ * </html>
+ *
+ * Plugin was tested to work in IE7+, Firefox 3.5+, Opera 10.10+, Google Chrome 12
+ *
+ * @TODO: Plugin doesn't check origin of the messages for now, though it's not possible for old
+ * browser because of technology used to pass data ( hash polling ).
+ *
+ */
+(function( window, $ ){
+		var cache_bust = 1,
+			interval_id,
+
+		/**
+		 * has_postMessage shows if browser supports postMessage communication. IE8 is disabled because it
+		 * doesn't allow to use postMessage from popup.
+		 */
+		has_postMessage = !!window.postMessage && ( !$.browser.msie || parseInt( $.browser.version, 10 ) > 8 ),
+		/**
+		 * senderUrl stores the address of container window
+		 */
+		senderUrl,
+		/**
+		 * iframeUrl stores the address of iframe in the domain of container window
+		 */
+		iframeUrl,
+		receiveCallbacks = [],
+		senderDomainFrame,
+		/*
+		 * pollDelay is a delay for checking it hash changed
+		 */
+		pollDelay = 100;
+
+	/**
+	 * targets is a collection of targets to exhange messages with. Container can pass messages to the multiple domains
+	 */
+	var targets = function() {
+		var container = [];
+
+		var collection = {
+			add: function( w, ref ) {
+				var pos;
+				if( ( pos = collection.indexOf( w ) === -1 ) ){
+					container.push( { win: w, href: ref } );
+				} else {
+					collection[ pos ].href = ref;
+				}
+			},
+
+			remove: function( w ) {
+				var pos;
+				if( ( pos = collection( w ) === -1 ) ){
+					return;
+				} else {
+					collection.splice( pos, 1 );
+					collection[ pos ].href = ref;
+				}
+			},
+
+			indexOf: function( w ) {
+				for( var i = 0; i < collection.length; ++i ) {
+					if( w === collection[ i ].top ) {
+						return i;
+					}
+				}
+
+				return -1;
+			},
+
+			getTarget: function( win ) {
+				var pos = collection.indexOf( win );
+				if( pos === -1 ) {
+					return;
+				} else {
+					container[ pos ].href;
+				}
+			}
+		};
+
+		return collection;
+	}();
+
+	/**
+	 * Converts message object to the hash string ready to pass to other window
+	 *
+	 * @param {Object} message
+	 * @return {String}
+	 */
+	function toHash( message ) {
+		message = typeof message === 'string' ? message : $.param( message );
+		return '#' + (+new Date) + (cache_bust++) + ':rpc&' + message;
+	}
+
+	/**
+	 * Converts param string like a=b&c=d to the object { a: 'b', c: 'd' }
+	 *
+	 * @param {String} hasStr
+	 *
+	 * @return {Object}
+	 */
+	function toObject( hashStr ) {
+		var obj = {}, pair;
+		var pairs = hashStr.split( "&" );
+		for( var arg = 0; arg < pairs.length; arg++ ) {
+			pair = pairs[ arg ].split( "=" );
+
+			//if user passes simple string, we return it as an response
+			if( pair.length === 1 && pairs.length === 1 )  {
+				return pair[0];
+			}
+
+			obj[ pair[ 0 ] ] = decodeURIComponent( pair[ 1 ] );
+		}
+
+		return obj;
+	}
+
+	/**
+	 * Checks if hash contains correct rpc call
+	 */
+	function isHash( str ) {
+		return /#\d{14}:rpc(.*)&/.test( str );
+	}
+
+	function extractBaseUrl( url ) {
+		return url.replace( /([^:]+:\/\/[^\/]+).*/, '$1' )
+	}
+
+	/**
+	 * Function tries to find rpc call through different communication channels ( hash or window rpcMessage property )
+	 *
+	 * @return {Boolean}
+	 */
+	function catchEvent() {
+		var channel = '';
+		if( !has_postMessage && location.hash.length > 0 && /^#\d+:rpc&.*$/.test( location.hash ) ) {
+			channel = location.hash;
+			location.hash = '';
+		} else if( window.rpcMessage && window.rpcMessage.length > 0 && /^#\d+:rpc&.*$/.test( window.rpcMessage ) ) {
+			channel = window.rpcMessage;
+			window.rpcMessage = '';
+		} else {
+			return;
+		}
+
+		return toObject( channel.replace( /#\d+:rpc&/, '' ) );
+	}
+
+	/**
+	 * Polling loop
+	 */
+	function startPolling() {
+		interval_id && clearInterval( interval_id );
+		interval_id = null;
+
+		interval_id = setInterval( function() {
+			var data = catchEvent();
+
+			if( data ) {
+				for( var i = 0; i < receiveCallbacks.length; ++i ) {
+					var cb = receiveCallbacks[ i ].pmcb || receiveCallbacks[ i ].cb;
+					cb( { data: data } );
+				}
+			}
+		}, pollDelay );
+	}
+
+	/**
+	 * @namespace $.rpc
+	 */
+	$.rpc = $.rpc || {};
+
+	/**
+	 * Send message to the other window. If senderUrl us set the code acts like child window.
+	 *
+	 * @param {Object|String} message
+	 * @param {Object} target Window object of the window to send message to
+	 */
+	$.rpc.postMessage = function( message, target ) {
+		target = target || parent;
+
+		var target_url, useFrame = false;
+		if( !(target_url = targets.getTarget( target ) ) ) {
+			if( has_postMessage ) {
+				target_url = "*";
+			} else {
+				if( !senderUrl ) {
+					throw "Transport channel has not been init for communication";
+				} else {
+					target_url = senderUrl;
+					useFrame = true;
+				}
+			}
+		}
+
+		if ( has_postMessage ) {
+			window.setTimeout( function() {
+				target.postMessage( typeof message === 'string' ? message : $.param( message ), extractBaseUrl( target_url ) );
+			}, 0 );
+
+		} else if ( target_url ) {
+			if( useFrame ) {
+				// window.open( iframeUrl + toHash( message ), 'xdr' );
+				$( senderDomainFrame ).attr( 'src', iframeUrl + toHash( message ) );
+			} else {
+				target.location = target_url.replace( /#.*$/, '' ) + toHash( message );
+			}
+		}
+	};
+
+	/**
+	 * Bind callback to listen messages
+	 *
+	 * @param {Function} callback
+	 */
+	$.rpc.bind = function( callback ) {
+		if ( has_postMessage ) {
+			var rm_callback = function(e) {
+				e = e || window.event;
+				callback( e );
+			};
+
+			if ( window.addEventListener ) {
+				window.addEventListener( 'message', rm_callback, false );
+			} else {
+				window.attachEvent( 'onmessage', rm_callback );
+			}
+			receiveCallbacks.push( { cb: callback, pmcb: rm_callback } );
+		} else {
+			receiveCallbacks.push( { cb: callback } );
+		}
+	};
+
+	/**
+	 * Stop listening messages with callback
+	 */
+	$.rpc.unbind = function( callback ) {
+		for( var i = 0; i < receiveCallbacks.length; ++i ) {
+			if( receiveCallbacks[ i ].cb === callback ) {
+				if ( has_postMessage ) {
+					if ( window.addEventListener ) {
+						window.removeEventListener( 'message', receiveCallbacks[ i ] );
+					} else {
+						windowdetachEvent( 'onmessage', receiveCallbacks[ i ] );
+					}
+				}
+				receiveCallbacks.splice( i, 1 );
+				return;
+			}
+		}
+	}
+
+	/**
+	 * Init communication with child window from container. Function makes sense only for browsers
+	 *     that do not support postMessage.
+	 *
+	 *  @param {Object} w window object of child window.
+	 *  @param {String} recipientUrl url if the child window
+	 *  @param {String} senderUrl url of the container window
+	 */
+	$.rpc.initRecipient = function( w, recipientUrl, senderUrl ) {
+		//if only fallback method is used, we have to pass parent window url with query string to enable communication
+		if( !has_postMessage ) {
+			w.location = recipientUrl.replace( /#.*$/, '' ) + toHash( { transport_url: senderUrl } );
+		} else {
+			w.location = recipientUrl;
+		}
+
+		targets.add( w, recipientUrl );
+	};
+
+	//plugin listens messages in case if parent window will send it's url.
+	if( !has_postMessage ) {
+		var bootstrap = function( e ) {
+			if( e.data && e.data.transport_url ) {
+				$.rpc.setSender( e.data.transport_url );
+				$.rpc.unbind( bootstrap );
+			}
+		};
+		$.rpc.bind( bootstrap );
+	}
+
+	/**
+	 * Set Url of the parent window in the child. Function also initiates communication channel,
+	 *    if it has not been done yet.
+	 *
+	 * @param {String} url
+	 */
+	$.rpc.setSender = function( url ) {
+		senderUrl = url;
+
+		//setting senderUrl means that we're in child window, so we need
+		//to create the page in the domain of parent window
+		if( !has_postMessage ) {
+			iframeUrl = extractBaseUrl( url ) + '/xdr.html';
+
+			if( !senderDomainFrame ) {
+				senderDomainFrame = document.createElement( 'iframe' );
+				senderDomainFrame.id = 'xdr';
+				senderDomainFrame.src = iframeUrl;
+				senderDomainFrame.style.display = 'none';
+
+				document.body.insertBefore( senderDomainFrame, document.body.firstChild );
+			} else {
+				$( senderDomainFrame ).attr( 'src', iframeUrl );
+			}
+
+		}
+	};
+
+	/**
+	 * Return current url of the parent window.
+	 *
+	 * @return {String}
+	 */
+	$.rpc.getSender = function() {
+		return senderUrl;
+	};
+
+	$.rpc.hasPostMessage = has_postMessage;
+
+	startPolling();
+
+})( window, jQuery );

Added: trunk/htdocs/js/jquery/jquery.storage.js
===================================================================
--- trunk/htdocs/js/jquery/jquery.storage.js	                        (rev 0)
+++ trunk/htdocs/js/jquery/jquery.storage.js	2011-06-16 04:26:48 UTC (rev 10653)
@@ -0,0 +1,123 @@
+/*!
+ * jQuery storage plugin.
+ * @author Dmitry Petrov <Dmitry.Petrov@sup.com>, 2011
+ *
+ * Plugin uses local storage if availible and falls back to IE userData mechanism.
+ *
+ * @TODO: add cookie and simple ( non-persistent ) storage providers.
+ *
+ * Plugin supports IE5.5+, Firefox 3.5+, Opera 10.5+, Google Chrome, Apple Safari 4+
+ */
+( function( $ ) {
+    /**
+     * @namespace $.storage
+     */
+    $.storage = function() {
+        
+        /**
+         * Every provider should have the same interface and provide isSupported function to
+         * test if it's applicable in current browser
+         */
+        var userDataProvider = function() {
+            var storageId = 'jQueryStorageProvider',
+                storageName = '__jQueryStorage__',
+                node;
+            function _create()  {
+                node = $( '<link>' ).attr( 'id', storageId ).css( 'display', 'none' ).appendTo( $( 'head' ) ).get(0);
+                node.addBehavior( '#default#userdata' );
+                node.load( storageName );
+            }
+
+            _create();
+
+            return {
+                /**
+                 * Set item in the storage
+                 *
+                 * @param {String} name
+                 * @param {String} val
+                 */
+                setItem: function( name, val ) {
+                    node.setAttribute( name, val );
+                    node.save( storageName );
+                },
+                /**
+                 * Get item from the storage.
+                 *
+                 * @param {String} Item name.
+                 * @return {Object|String} Item value or null it it does not exist.
+                 */
+                getItem: function( name ) {
+                    return node.getAttribute( name );
+                },
+                /**
+                 * Remove item from the storage
+                 *
+                 * @param @{String} Item name.
+                 */
+                removeItem: function( name ) {
+                    node.removeAttribute( name );
+                    node.save( storageName );
+                }
+            }
+        };
+
+        userDataProvider.isSupported = function() { return $.browser.msie && ( +$.browser.version ) > 5; };
+
+        var localStorageProvider = function() {
+            function _create()  {
+            }
+
+            _create();
+
+            return {
+                setItem: function( name, val ) {
+                    localStorage.setItem( name, val );
+                },
+                getItem: function( name ) {
+                    return localStorage.getItem( name );
+                },
+                removeItem: function( name ) {
+                    localStorage.removeItem( name );
+                }
+            }
+        };
+
+        localStorageProvider.isSupported = function() { return !!window.localStorage; };
+
+        var simpleProvider = function() {
+            var store;
+            function _create()  {
+                store = {};
+            }
+
+            _create();
+
+            return {
+                setItem: function( name, val ) {
+                    store.name = val;
+                },
+                getItem: function( name ) {
+                    return store.name || null;
+                },
+                removeItem: function( name ) {
+                    delete store.name;
+                }
+            }
+        };
+
+        simpleProvider.isSupported = function() { return true; };
+
+        //currently all transports should be implemented inside plugin.
+        var providers = [ localStorageProvider, userDataProvider, simpleProvider ];
+
+        for( var i = 0; i < providers.length; ++i ) {
+            if( providers[ i ].isSupported() ) {
+                return providers[ i ]();
+            }
+        }
+
+        //We shoud never reach this point.
+    }();
+
+} ) ( jQuery );

Added: trunk/htdocs/misc/xdr.html
===================================================================
--- trunk/htdocs/misc/xdr.html	                        (rev 0)
+++ trunk/htdocs/misc/xdr.html	2011-06-16 04:26:48 UTC (rev 10653)
@@ -0,0 +1,18 @@
+<!DOCTYPE HTML>
+<html lang="en">
+<head>
+	<meta charset="UTF-8">
+	<script type="text/javascript">
+		function sendData() {
+			if ( location.hash && location.hash.length > 1 ) {
+				window.parent.opener.rpcMessage = location.hash;
+				location.hash = '#';
+			}
+		}
+
+		setInterval( sendData, 50 );
+	</script>
+</head>
+<body>
+</body>
+</html>

Tags: can3p, html, js, ljcom
Subscribe
  • Post a new comment

    Error

    Anonymous comments are disabled in this journal

    default userpic

    Your reply will be screened

    Your IP address will be recorded 

  • 0 comments