From 0a178de6b09dbdd932b178ae5a2f88da19ae8170 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Sigur=C3=B0ur=20Gu=C3=B0brandsson?= Date: Fri, 7 Nov 2014 16:03:30 +0000 Subject: [PATCH 1/4] Changed "text widget" to "sidebar widgets" + Twitter option This modification adds the ability to lazy load all items in the sidebar (not only the text_widget). Optionally, you can select "text widget" if you don't want to use an observer. Also added twitter timeline lazy loading. --- admin.php | 12 +++++++++--- 1 file changed, 9 insertions(+), 3 deletions(-) diff --git a/admin.php b/admin.php index 2d9151d..03b074a 100755 --- a/admin.php +++ b/admin.php @@ -20,10 +20,10 @@ function page_content() { 'value' => array( 'yes' => __( 'Yes', 'bj-lazy-load' ), 'no' => __( 'No', 'bj-lazy-load' ) ), ), array( - 'title' => __( 'Apply to text widgets', 'bj-lazy-load' ), + 'title' => __( 'Apply to sidebar widgets', 'bj-lazy-load' ), 'type' => 'radio', - 'name' => 'filter_widget_text', - 'value' => array( 'yes' => __( 'Yes', 'bj-lazy-load' ), 'no' => __( 'No', 'bj-lazy-load' ) ), + 'name' => 'filter_sidebar_widgets', + 'value' => array( 'yes' => __( 'Yes', 'bj-lazy-load' ), 'no' => __( 'No', 'bj-lazy-load' ), 'only_text_widgets' => __( 'Only Text Widgets', 'bj-lazy-load' ) ), ), array( 'title' => __( 'Apply to post thumbnails', 'bj-lazy-load' ), @@ -49,6 +49,12 @@ function page_content() { 'name' => 'lazy_load_iframes', 'value' => array( 'yes' => __( 'Yes', 'bj-lazy-load' ), 'no' => __( 'No', 'bj-lazy-load' ) ), ), + array( + 'title' => __( 'Lazy load twitter timeline', 'bj-lazy-load' ), + 'type' => 'radio', + 'name' => 'lazy_load_twitter_timeline', + 'value' => array( 'yes' => __( 'Yes', 'bj-lazy-load' ), 'no' => __( 'No', 'bj-lazy-load' ) ), + ), array( 'title' => __( 'Theme loader function', 'bj-lazy-load' ), 'type' => 'select', From 22d468293daeec3e56a0f44f5c082251dac720bd Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Sigur=C3=B0ur=20Gu=C3=B0brandsson?= Date: Fri, 7 Nov 2014 16:11:25 +0000 Subject: [PATCH 2/4] Update bj-lazy-load.php Added the ability to lazy load the whole sidebar, as opposed to only the text widgets. You can also select the option to lazy load only text widgets. Modified the function 'filter' to check for lazy loading the twitter timeline. Added the function '_filter_twitter_timeline' to filter the twitter timeline. Yes, the regex is SUPPOSED to be safe .. but you never know about regex (esp since HTML is irregular) Hmm .. maybe it would have been smart to allow both single quote and double quote .. as well as allow for more classes ... oh well.. next revision. Changed the function '_get_options' to include the new 'filter_sidebar_widgets' (had to remove filter_text_widget) and 'lazy_load_twitter_timeline' Added functions 'observe_sidebar' and 'stop_observing_sidebar_and_output_sidebar' to observe the sidebar html output. The functions do not run on the admin side, only the template side. The action hooks are not documented, but you can find them in widgets.php in the wordpress repository. --- bj-lazy-load.php | 86 +++++++++++++++++++++++++++++++++++++++--------- 1 file changed, 70 insertions(+), 16 deletions(-) diff --git a/bj-lazy-load.php b/bj-lazy-load.php index f603ae9..8d9ee37 100755 --- a/bj-lazy-load.php +++ b/bj-lazy-load.php @@ -78,7 +78,11 @@ function __construct() { if ( $options->get( 'filter_content' ) == 'yes' ) { add_filter( 'the_content', array( $this, 'filter' ), 200 ); } - if ( $options->get( 'filter_widget_text' ) == 'yes' ) { + if ( $options->get( 'filter_sidebar_widgets' ) == 'yes' ) { + add_action( 'dynamic_sidebar_before', array( $this, 'observe_sidebar' ), 200 ); + add_action( 'dynamic_sidebar_after', array( $this, 'stop_observing_sidebar_and_output_sidebar' ), 200 ); + } + if ( $options->get( 'filter_sidebar_widgets' ) == 'only_text_widgets' ) { add_filter( 'widget_text', array( $this, 'filter' ), 200 ); } if ( $options->get( 'filter_post_thumbnails' ) == 'yes' ) { @@ -165,6 +169,10 @@ static function filter( $content ) { if ( $options->get('lazy_load_iframes') == 'yes' ) { $content = $BJLL->_filter_iframes( $content ); } + + if ( $options->get('lazy_load_twitter_timeline') == 'yes' ) { + $content = $BJLL->_filter_twitter_timeline( $content ); + } return $content; } @@ -237,23 +245,47 @@ protected function _filter_iframes( $content ) { return $content; } + protected function _filter_twitter_timeline( $content ) { + + $matches = array(); + preg_match_all( '/]*?class="twitter-timeline".*?<\/a>/s', $content, $matches ); + + $search = array(); + $replace = array(); + + foreach ( $matches[0] as $twitterTimelineHTML ) { + + $replaceHTML = ''; + + $replaceHTML .= ''; + + array_push( $search, $twitterTimelineHTML ); + array_push( $replace, $replaceHTML ); + } + + $content = str_replace( $search, $replace, $content ); + + return $content; + } + protected static function _get_options() { return new scbOptions( 'bj_lazy_load_options', __FILE__, array( - 'filter_content' => 'yes', - 'filter_widget_text' => 'yes', - 'filter_post_thumbnails' => 'yes', - 'filter_gravatars' => 'yes', - 'lazy_load_images' => 'yes', - 'lazy_load_iframes' => 'yes', - 'theme_loader_function' => 'wp_footer', - 'placeholder_url' => '', - 'skip_classes' => '', - 'load_hidpi' => 'no', - 'load_responsive' => 'no', - 'disable_on_wptouch' => 'yes', - 'disable_on_mobilepress' => 'yes', - 'infinite_scroll' => 'no', - 'threshold' => '200' + 'filter_content' => 'yes', + 'filter_sidebar_widgets' => 'yes', + 'filter_post_thumbnails' => 'yes', + 'filter_gravatars' => 'yes', + 'lazy_load_images' => 'yes', + 'lazy_load_iframes' => 'yes', + 'lazy_load_twitter_timeline' => 'yes', + 'theme_loader_function' => 'wp_footer', + 'placeholder_url' => '', + 'skip_classes' => '', + 'load_hidpi' => 'no', + 'load_responsive' => 'no', + 'disable_on_wptouch' => 'yes', + 'disable_on_mobilepress' => 'yes', + 'infinite_scroll' => 'no', + 'threshold' => '200' ) ); } @@ -310,6 +342,28 @@ static function has_mobilepress() { return false; } + function observe_sidebar() { + if ( !is_admin() ) { + // Only start observing output if we're not in the admin area + ob_start(); + } + } + + function stop_observing_sidebar_and_output_sidebar() { + if ( !is_admin() ) { + // Only work with observer if we're not in the admin area + + // Get the sidebar content and shut down the observer + $sidebar_contents = ob_get_clean(); + + // Process the sidebar content for iframes and images + $sidebar_contents = $this->filter($sidebar_contents); + + // Output the sidebar content + echo $sidebar_contents; + } + } + } } From c4c8bf8a1e3fc80eb55769e6904715d9d4d3802c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Sigur=C3=B0ur=20Gu=C3=B0brandsson?= Date: Fri, 7 Nov 2014 16:13:05 +0000 Subject: [PATCH 3/4] Added twitter lazy loading js code Added twitter timeline lazy loading javascript code. This allows twitter timelines to be lazy loaded. --- js/bj-lazy-load.js | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) diff --git a/js/bj-lazy-load.js b/js/bj-lazy-load.js index 1897f2d..267e883 100755 --- a/js/bj-lazy-load.js +++ b/js/bj-lazy-load.js @@ -48,6 +48,15 @@ var BJLL = BJLL || {}; $el.attr( 'data-lazy-src' ) ) ); + } else if ( data_lazy_type == 'twitter' ) { + $el.replaceWith( + bj_lazy_load_base64_decode( + $el.attr( 'data-lazy-src' ) + ) + ); + if (typeof twttr !== "undefined") { + twttr.widgets.load(); + } } }).addClass( 'data-lazy-ready' ); @@ -115,4 +124,4 @@ var BJLL = BJLL || {}; } $( window ).on( 'resize', function() { $( document ).trigger( 'scroll' ); } ); -})(jQuery); \ No newline at end of file +})(jQuery); From fb444a839d95907eea515ab9e8c5f020b10e674f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Sigur=C3=B0ur=20Gu=C3=B0brandsson?= Date: Fri, 7 Nov 2014 16:16:19 +0000 Subject: [PATCH 4/4] Closure-compiled the latest combined JS Used Google's Closure Compiler to compile the bj-lazy-load.js and jquery.sonar.js. Used "simple" settings from the closure compiler. http://closure-compiler.appspot.com/home --- js/combined.min.js | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/js/combined.min.js b/js/combined.min.js index 3806da9..23c4f61 100755 --- a/js/combined.min.js +++ b/js/combined.min.js @@ -1 +1,7 @@ -(function($,win,doc,undefined){$.fn.sonar=function(distance,full){if(typeof distance==="boolean"){full=distance;distance=undefined}return $.sonar(this[0],distance,full)};var body=doc.body,$win=$(win),onScreenEvent="scrollin",offScreenEvent="scrollout",detect=function(elem,distance,full){if(elem){body||(body=doc.body);var parentElem=elem,elemTop=0,bodyHeight=body.offsetHeight,screenHeight=win.innerHeight||doc.documentElement.clientHeight||body.clientHeight||0,scrollTop=doc.documentElement.scrollTop||win.pageYOffset||body.scrollTop||0,elemHeight=elem.offsetHeight||0;if(!elem.sonarElemTop||elem.sonarBodyHeight!==bodyHeight){if(parentElem.offsetParent){do{elemTop+=parentElem.offsetTop}while(parentElem=parentElem.offsetParent)}elem.sonarElemTop=elemTop;elem.sonarBodyHeight=bodyHeight}distance=distance===undefined?0:distance;return!(elem.sonarElemTop+(full?0:elemHeight)scrollTop+screenHeight+distance)}},pollQueue={},pollActive=0,pollId,poll=function(){pollId&&clearTimeout(pollId);pollId=setTimeout(function(){var elem,elems,screenEvent,options,detected,i,l;for(screenEvent in pollQueue){elems=pollQueue[screenEvent];for(i=0,l=elems.length;i1&&"yes"==BJLL.load_hidpi&&(loadimgwidth=Math.ceil(window.devicePixelRatio*loadimgwidth));var srcimgurl=$el.attr("data-lazy-src");"undefined"!=typeof BJLL.site_url&&"undefined"!=typeof BJLL.network_site_url&&(srcimgurl=srcimgurl.replace(BJLL.site_url,BJLL.network_site_url)),imgurl=BJLL.thumb_base+encodeURIComponent(srcimgurl)+"&w="+loadimgwidth}}$el.hide().attr("src",imgurl).removeClass("lazy-hidden").fadeIn()}else"iframe"==data_lazy_type&&$el.replaceWith(bj_lazy_load_base64_decode($el.attr("data-lazy-src")))}).addClass("data-lazy-ready")}function bj_lazy_load_base64_decode(data){var o1,o2,o3,h1,h2,h3,h4,bits,b64="ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=",i=0,ac=0,dec="",tmp_arr=[];if(!data)return data;data+="";do h1=b64.indexOf(data.charAt(i++)),h2=b64.indexOf(data.charAt(i++)),h3=b64.indexOf(data.charAt(i++)),h4=b64.indexOf(data.charAt(i++)),bits=h1<<18|h2<<12|h3<<6|h4,o1=bits>>16&255,o2=bits>>8&255,o3=255&bits,tmp_arr[ac++]=64==h3?String.fromCharCode(o1):64==h4?String.fromCharCode(o1,o2):String.fromCharCode(o1,o2,o3);while(if+k+d)}},k={},q=0,f,r=function(){f&&clearTimeout(f);f=setTimeout(function(){var a,b,d,c,f,l,g;for(d in k)for(b=k[d],l=0,g=b.length;l>16&255,d=e>>8&255,e&=255,64== +k?g[m++]=String.fromCharCode(b):64==h?g[m++]=String.fromCharCode(b,d):g[m++]=String.fromCharCode(b,d,e);while(f