Valerii Vasin (valerii) wrote in changelog,
Valerii Vasin
valerii
changelog

[livejournal] r23221: LJSUP-14127: Optimize $.fn.ljLikes() plu...

Committer: vvasin
LJSUP-14127: Optimize $.fn.ljLikes() plugin to perform parsing only likes that are currently on the page at once. Rewrite plugin.
U   trunk/htdocs/js/jquery_fn.js
Modified: trunk/htdocs/js/jquery_fn.js
===================================================================
--- trunk/htdocs/js/jquery_fn.js	2012-10-30 13:14:15 UTC (rev 23220)
+++ trunk/htdocs/js/jquery_fn.js	2012-10-30 15:28:41 UTC (rev 23221)
@@ -17,7 +17,7 @@
  * - if two arguments have been provided: setting selection from startPos to endPos
  * - if one argument: set cursor to startPos
  * - if no arguments: get selection of field
- * 
+ *
  * @param  {number} startPos Start caret position
  * @param  {number} endPos   End caret position.
  */
@@ -114,7 +114,7 @@
 			return this.each(function() {
 				if (this.getAttribute("placeholder")) {
 					var $this = jQuery(this);
-					
+
 					if (!$this.data('jQuery-has-placeholder')) {
 						$this.focus(check_focus).blur(check_blur);
 
@@ -449,22 +449,107 @@
 
 /**
  * Parse lj-likes plugin
- * It parse all elements with class 'lj-like', uncomment their content
+ * It parses all elements with class 'lj-like', uncomment their content
  * and parse with LiveJournal.parseLikeButtons()
+ *
+ * @todo Move plugin to separate file
  */
 ;(function ($) {
 	'use strict';
 
-	$.fn.ljLikes = function () {
+	// empty collection that will contain not parsed lj-like elements
+	// that are currently on the page
+	var _likes = $();
 
-		return $(this).each(function () {
-			$(this).find('.lj-like').each(function () {
-				$(this).html(function (html) {
-					// remove comments node
-					return $.trim( $(this).html().replace(/<!--([\s\S]*?)-->/mig, '$1') );
-				});
-				LiveJournal.parseLikeButtons($(this));
+	/**
+	 * Remove comments inside node and parse likes
+	 * @param  {Object} node jQuery node
+	 * @return {Object}      jQuery node
+	 */
+	function parse(node) {
+		var html = node.html();
+
+		html = $.trim( html.replace(/<!--([\s\S]*?)-->/mig, '$1') );
+		node.html(html);
+		LiveJournal.parseLikeButtons( node );
+
+		return node;
+	}
+
+	/**
+	 * handler for scroll event for lazy loading of likes
+	 */
+	function lazyLoad() {
+		var screenableLikes = null;
+
+		if ( _likes.length === 0 ) {
+			return;
+		}
+
+		// find likes that are on the screen
+		screenableLikes = _likes.filter(':screenable');
+
+		if ( !screenableLikes.length ) {
+			return;
+		}
+
+		screenableLikes.each(function () {
+			var node = $(this);
+
+			// move parsing to the end of the event loop
+			setTimeout(function () {
+				parse( node );
+			}, 0);
+		});
+
+		// remove handled likes from the queue
+		_likes = _likes.not(screenableLikes);
+	}
+
+	// handle scroll event
+	$(window).on('scroll', lazyLoad);
+
+	$.fn.ljLikes = function (opts) {
+		var likes = null;
+
+		if ( this.length === 0 ) {
+			return this;
+		}
+
+		opts = $.extend({}, $.fn.ljLikes.defaults, opts || {});
+
+		// find elements with lj-likes class
+		likes = this.find('.lj-like')
+			.add( this.filter('.lj-like') );
+
+		if (likes.length === 0) {
+			return this;
+		}
+
+		if ( !opts.lazy ) {
+			// not lazy: immediately parsing
+			likes.each(function () {
+				var node = $(this);
+
+				// parse should be deferred
+				setTimeout(function () {
+					parse( node );
+				}, 0);
 			});
-		});
+		} else {
+			// add likes for further lazy loading
+			_likes = _likes.add( likes );
+			// parse all added screenable elements
+			lazyLoad();
+		}
+
+		return this;
 	};
+
+	// default plugin options
+	$.fn.ljLikes.defaults = {
+		// lazy loading of likes - will be parsed when becomes screenable
+		// if false - we will parse likes at the moment
+		lazy: true
+	};
 }(jQuery));
\ No newline at end of file

Tags: invis89, js, livejournal, vvasin
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