[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
