From bcac8bdd6ff54dc438034b0c9f1a662dd03abdd4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?R=C3=A9my=20Perona?= Date: Mon, 18 Dec 2017 19:43:18 -0500 Subject: [PATCH 1/7] add intersectionObserver version of lazyload script --- assets/js/lazyload-10.3.5.js | 249 +++++++++++++++++++++++++++++++ assets/js/lazyload-10.3.5.min.js | 1 + 2 files changed, 250 insertions(+) create mode 100755 assets/js/lazyload-10.3.5.js create mode 100755 assets/js/lazyload-10.3.5.min.js diff --git a/assets/js/lazyload-10.3.5.js b/assets/js/lazyload-10.3.5.js new file mode 100755 index 0000000..6df7a24 --- /dev/null +++ b/assets/js/lazyload-10.3.5.js @@ -0,0 +1,249 @@ +var _extends = Object.assign || function (target) { for (var i = 1; i < arguments.length; i++) { var source = arguments[i]; for (var key in source) { if (Object.prototype.hasOwnProperty.call(source, key)) { target[key] = source[key]; } } } return target; }; + +var _typeof = typeof Symbol === "function" && typeof Symbol.iterator === "symbol" ? function (obj) { return typeof obj; } : function (obj) { return obj && typeof Symbol === "function" && obj.constructor === Symbol && obj !== Symbol.prototype ? "symbol" : typeof obj; }; + +(function (global, factory) { + (typeof exports === 'undefined' ? 'undefined' : _typeof(exports)) === 'object' && typeof module !== 'undefined' ? module.exports = factory() : typeof define === 'function' && define.amd ? define(factory) : global.LazyLoad = factory(); +})(this, function () { + 'use strict'; + + var defaultSettings = { + elements_selector: "img", + container: document, + threshold: 300, + data_src: "src", + data_srcset: "srcset", + class_loading: "loading", + class_loaded: "loaded", + class_error: "error", + callback_load: null, + callback_error: null, + callback_set: null + }; + + var dataPrefix = "data-"; + + var getData = function getData(element, attribute) { + return element.getAttribute(dataPrefix + attribute); + }; + + var setData = function setData(element, attribute, value) { + return element.setAttribute(dataPrefix + attribute, value); + }; + + var purgeElements = function purgeElements(elements) { + return elements.filter(function (element) { + return !getData(element, "was-processed"); + }); + }; + + /* Creates instance and notifies it through the window element */ + var createInstance = function createInstance(classObj, options) { + var event; + var eventString = "LazyLoad::Initialized"; + var instance = new classObj(options); + try { + // Works in modern browsers + event = new CustomEvent(eventString, { detail: { instance: instance } }); + } catch (err) { + // Works in Internet Explorer (all versions) + event = document.createEvent("CustomEvent"); + event.initCustomEvent(eventString, false, false, { instance: instance }); + } + window.dispatchEvent(event); + }; + + /* Auto initialization of one or more instances of lazyload, depending on the + options passed in (plain object or an array) */ + var autoInitialize = function autoInitialize(classObj, options) { + if (!options.length) { + // Plain object + createInstance(classObj, options); + } else { + // Array of objects + for (var i = 0, optionsItem; optionsItem = options[i]; i += 1) { + createInstance(classObj, optionsItem); + } + } + }; + + var setSourcesForPicture = function setSourcesForPicture(element, settings) { + var dataSrcSet = settings.data_srcset; + + var parent = element.parentNode; + if (parent.tagName !== "PICTURE") { + return; + } + for (var i = 0, pictureChild; pictureChild = parent.children[i]; i += 1) { + if (pictureChild.tagName === "SOURCE") { + var sourceSrcset = getData(pictureChild, dataSrcSet); + if (sourceSrcset) { + pictureChild.setAttribute("srcset", sourceSrcset); + } + } + } + }; + + var setSources = function setSources(element, settings) { + var dataSrc = settings.data_src, + dataSrcSet = settings.data_srcset; + + var tagName = element.tagName; + var elementSrc = getData(element, dataSrc); + if (tagName === "IMG") { + setSourcesForPicture(element, settings); + var imgSrcset = getData(element, dataSrcSet); + if (imgSrcset) { + element.setAttribute("srcset", imgSrcset); + } + if (elementSrc) { + element.setAttribute("src", elementSrc); + } + return; + } + if (tagName === "IFRAME") { + if (elementSrc) { + element.setAttribute("src", elementSrc); + } + return; + } + if (elementSrc) { + element.style.backgroundImage = 'url("' + elementSrc + '")'; + } + }; + + var supportsClassList = "classList" in document.createElement("p"); + + var addClass = function addClass(element, className) { + if (supportsClassList) { + element.classList.add(className); + return; + } + element.className += (element.className ? " " : "") + className; + }; + + var removeClass = function removeClass(element, className) { + if (supportsClassList) { + element.classList.remove(className); + return; + } + element.className = element.className.replace(new RegExp("(^|\\s+)" + className + "(\\s+|$)"), " ").replace(/^\s+/, "").replace(/\s+$/, ""); + }; + + var callCallback = function callCallback(callback, argument) { + if (callback) { + callback(argument); + } + }; + + var loadString = "load"; + var errorString = "error"; + + var removeListeners = function removeListeners(element, loadHandler, errorHandler) { + element.removeEventListener(loadString, loadHandler); + element.removeEventListener(errorString, errorHandler); + }; + + var addOneShotListeners = function addOneShotListeners(element, settings) { + var onLoad = function onLoad(event) { + onEvent(event, true, settings); + removeListeners(element, onLoad, onError); + }; + var onError = function onError(event) { + onEvent(event, false, settings); + removeListeners(element, onLoad, onError); + }; + element.addEventListener(loadString, onLoad); + element.addEventListener(errorString, onError); + }; + + var onEvent = function onEvent(event, success, settings) { + var element = event.target; + removeClass(element, settings.class_loading); + addClass(element, success ? settings.class_loaded : settings.class_error); // Setting loaded or error class + callCallback(success ? settings.callback_load : settings.callback_error, element); // Calling loaded or error callback + }; + + var revealElement = function revealElement(element, settings) { + if (["IMG", "IFRAME"].indexOf(element.tagName) > -1) { + addOneShotListeners(element, settings); + addClass(element, settings.class_loading); + } + setSources(element, settings); + setData(element, "was-processed", true); + callCallback(settings.callback_set, element); + }; + + var LazyLoad = function LazyLoad(instanceSettings, elements) { + this._settings = _extends({}, defaultSettings, instanceSettings); + this._setObserver(); + this.update(elements); + }; + + LazyLoad.prototype = { + _setObserver: function _setObserver() { + var _this = this; + + if (!("IntersectionObserver" in window)) { + return; + } + + var settings = this._settings; + var onIntersection = function onIntersection(entries) { + entries.forEach(function (entry) { + if (entry.intersectionRatio > 0) { + var element = entry.target; + revealElement(element, settings); + _this._observer.unobserve(element); + } + }); + _this._elements = purgeElements(_this._elements); + }; + this._observer = new IntersectionObserver(onIntersection, { + root: settings.container === document ? null : settings.container, + rootMargin: settings.threshold + "px" + }); + }, + + update: function update(elements) { + var _this2 = this; + + var settings = this._settings; + var nodeSet = elements || settings.container.querySelectorAll(settings.elements_selector); + + this._elements = purgeElements(Array.prototype.slice.call(nodeSet)); // nodeset to array for IE compatibility + if (this._observer) { + this._elements.forEach(function (element) { + _this2._observer.observe(element); + }); + return; + } + // Fallback: load all elements at once + this._elements.forEach(function (element) { + revealElement(element, settings); + }); + this._elements = purgeElements(this._elements); + }, + + destroy: function destroy() { + var _this3 = this; + + if (this._observer) { + purgeElements(this._elements).forEach(function (element) { + _this3._observer.unobserve(element); + }); + this._observer = null; + } + this._elements = null; + this._settings = null; + } + }; + + /* Automatic instances creation if required (useful for async script loading!) */ + var autoInitOptions = window.lazyLoadOptions; + if (autoInitOptions) { + autoInitialize(LazyLoad, autoInitOptions); + } + + return LazyLoad; +}); \ No newline at end of file diff --git a/assets/js/lazyload-10.3.5.min.js b/assets/js/lazyload-10.3.5.min.js new file mode 100755 index 0000000..80cac38 --- /dev/null +++ b/assets/js/lazyload-10.3.5.min.js @@ -0,0 +1 @@ +var _extends=Object.assign||function(e){for(var t=1;t-1&&(f(e,t),c(e,t.class_loading)),a(e,t),n(e,"was-processed",!0),u(t.callback_set,e)},m=function(t,n){this._settings=_extends({},e,t),this._setObserver(),this.update(n)};m.prototype={_setObserver:function(){var e=this;if("IntersectionObserver"in window){var t=this._settings;this._observer=new IntersectionObserver(function(n){n.forEach(function(n){if(n.intersectionRatio>0){var r=n.target;_(r,t),e._observer.unobserve(r)}}),e._elements=r(e._elements)},{root:t.container===document?null:t.container,rootMargin:t.threshold+"px"})}},update:function(e){var t=this,n=this._settings,s=e||n.container.querySelectorAll(n.elements_selector);this._elements=r(Array.prototype.slice.call(s)),this._observer?this._elements.forEach(function(e){t._observer.observe(e)}):(this._elements.forEach(function(e){_(e,n)}),this._elements=r(this._elements))},destroy:function(){var e=this;this._observer&&(r(this._elements).forEach(function(t){e._observer.unobserve(t)}),this._observer=null),this._elements=null,this._settings=null}};var b=window.lazyLoadOptions;return b&&function(e,t){if(t.length)for(var n,r=0;n=t[r];r+=1)s(e,n);else s(e,t)}(m,b),m}); \ No newline at end of file From 1cead1c8bccd4f6412ac1d9916eea0884b1a893a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?R=C3=A9my=20Perona?= Date: Mon, 18 Dec 2017 19:44:23 -0500 Subject: [PATCH 2/7] remove version constant --- rocket-lazy-load.php | 1 - 1 file changed, 1 deletion(-) diff --git a/rocket-lazy-load.php b/rocket-lazy-load.php index 5bb030c..38e3314 100644 --- a/rocket-lazy-load.php +++ b/rocket-lazy-load.php @@ -31,7 +31,6 @@ define( 'ROCKET_LL_3RD_PARTY_PATH', ROCKET_LL_PATH . '3rd-party/' ); define( 'ROCKET_LL_ASSETS_URL', plugin_dir_url( __FILE__ ) . 'assets/' ); define( 'ROCKET_LL_FRONT_JS_URL', ROCKET_LL_ASSETS_URL . 'js/' ); -define( 'ROCKET_LL_JS_VERSION' , '8.2' ); /** From a53e3982209e6c42a44bdd4080cea28a66970735 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?R=C3=A9my=20Perona?= Date: Mon, 18 Dec 2017 19:44:52 -0500 Subject: [PATCH 3/7] set skip_invisible lazyload option to false --- rocket-lazy-load.php | 1 + 1 file changed, 1 insertion(+) diff --git a/rocket-lazy-load.php b/rocket-lazy-load.php index 38e3314..33f23a2 100644 --- a/rocket-lazy-load.php +++ b/rocket-lazy-load.php @@ -112,6 +112,7 @@ function rocket_lazyload_script() { elements_selector: "img, iframe", data_src: "lazy-src", data_srcset: "lazy-srcset", + skip_invisible: false, class_loading: "lazyloading", class_loaded: "lazyloaded", threshold: $threshold, From 6ed2adfdb0021ce59fa492fa116b2b8f49653f84 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?R=C3=A9my=20Perona?= Date: Mon, 18 Dec 2017 19:52:12 -0500 Subject: [PATCH 4/7] conditionally load the lazyload script version depending on browser support of intersectionObserver --- rocket-lazy-load.php | 63 +++++++++++++++++++------------------------- 1 file changed, 27 insertions(+), 36 deletions(-) diff --git a/rocket-lazy-load.php b/rocket-lazy-load.php index 33f23a2..53df5e2 100644 --- a/rocket-lazy-load.php +++ b/rocket-lazy-load.php @@ -3,7 +3,7 @@ * Plugin Name: Lazy Load by WP Rocket * Plugin URI: http://wordpress.org/plugins/rocket-lazy-load/ * Description: The tiny Lazy Load script for WordPress without jQuery or others libraries. - * Version: 1.4.4 + * Version: 1.4.5 * Author: WP Media * Author URI: https://wp-rocket.me * Text Domain: rocket-lazy-load @@ -105,30 +105,46 @@ function rocket_lazyload_script() { return; } + $suffix = defined( 'SCRIPT_DEBUG' ) && SCRIPT_DEBUG ? '' : '.min'; + + /** + * Filters the threshold at which lazyload is triggered + * + * @since 1.2 + * @author Remy Perona + * + * @param int $threshold Threshold value. + */ $threshold = apply_filters( 'rocket_lazyload_threshold', 300 ); - echo <<window.lazyLoadOptions = { + echo ' -HTML; + } + }; // Your options here. See "recipes" for more information about async. + b.appendChild(s); +}(window, document));'; if ( rocket_lazyload_get_option( 'youtube' ) ) { echo << Date: Mon, 18 Dec 2017 19:54:47 -0500 Subject: [PATCH 5/7] update changelog and PHP required version --- readme.txt | 3 +++ 1 file changed, 3 insertions(+) diff --git a/readme.txt b/readme.txt index dfa772d..584a01b 100644 --- a/readme.txt +++ b/readme.txt @@ -3,6 +3,7 @@ Contributors: creativejuiz, tabrisrp, wp_media Tags: lazyload, lazy load, images, iframes, thumbnail, thumbnails, smiley, smilies, avatar, gravatar Requires at least: 3.0 Tested up to: 4.8 +Requires PHP: 5.3 Stable tag: 1.4.5 The tiny Lazy Load script for WordPress without jQuery, works for images and iframes. @@ -67,6 +68,8 @@ Some plugins are not compatible without lazy loading. Please open a support thre = 1.4.5 = * Rename Setting Page Name in WP Menu * New Product Banner in Settings Page +* Conditionally load a different version of the script depending on browser support of IntersectionObserver +* Fix a bug where images initially hidden are not correctly displayed when coming into view (slider, tabs, accordion) = 1.4.4 = * Admin Redesign From 5daef0b760a8c72ce5db4ad1cf62de8d28524e15 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?R=C3=A9my=20Perona?= Date: Mon, 18 Dec 2017 19:56:34 -0500 Subject: [PATCH 6/7] fix bad copy/paste --- rocket-lazy-load.php | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/rocket-lazy-load.php b/rocket-lazy-load.php index 53df5e2..f56ceba 100644 --- a/rocket-lazy-load.php +++ b/rocket-lazy-load.php @@ -165,8 +165,8 @@ function rocket_lazyload_enqueue() { return; } - if ( get_rocket_option( 'lazyload_youtube' ) ) { - $css = '.rll-youtube-player{position:relative;padding-bottom:56.23%;height:0;overflow:hidden;max-width:100%;background:#000;margin:5px}.rll-youtube-player iframe{position:absolute;top:0;left:0;width:100%;height:100%;z-index:100;background:0 0}.rll-youtube-player img{bottom:0;display:block;left:0;margin:auto;max-width:100%;width:100%;position:absolute;right:0;top:0;border:none;height:auto;cursor:pointer;-webkit-transition:.4s all;-moz-transition:.4s all;transition:.4s all}.rll-youtube-player img:hover{-webkit-filter:brightness(75%)}.rll-youtube-player .play{height:72px;width:72px;left:50%;top:50%;margin-left:-36px;margin-top:-36px;position:absolute;background:url(' . WP_ROCKET_FRONT_URL . 'img/play.png) no-repeat;cursor:pointer}'; + if ( rocket_lazyload_get_option( 'youtube' ) ) { + $css = '.rll-youtube-player{position:relative;padding-bottom:56.23%;height:0;overflow:hidden;max-width:100%;background:#000;margin:5px}.rll-youtube-player iframe{position:absolute;top:0;left:0;width:100%;height:100%;z-index:100;background:0 0}.rll-youtube-player img{bottom:0;display:block;left:0;margin:auto;max-width:100%;width:100%;position:absolute;right:0;top:0;border:none;height:auto;cursor:pointer;-webkit-transition:.4s all;-moz-transition:.4s all;transition:.4s all}.rll-youtube-player img:hover{-webkit-filter:brightness(75%)}.rll-youtube-player .play{height:72px;width:72px;left:50%;top:50%;margin-left:-36px;margin-top:-36px;position:absolute;background:url(' . ROCKET_LL_ASSETS_URL . 'img/play.png) no-repeat;cursor:pointer}'; wp_register_style( 'rocket-lazyload', false ); wp_enqueue_style( 'rocket-lazyload' ); From e8a63675fdef8359018f2ac2739ac9a265b5e124 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?R=C3=A9my=20Perona?= Date: Mon, 18 Dec 2017 19:57:57 -0500 Subject: [PATCH 7/7] remove unnecessary inline comment --- rocket-lazy-load.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/rocket-lazy-load.php b/rocket-lazy-load.php index f56ceba..24da6e7 100644 --- a/rocket-lazy-load.php +++ b/rocket-lazy-load.php @@ -142,7 +142,7 @@ class_loaded: "lazyloaded", } } } - }; // Your options here. See "recipes" for more information about async. + }; b.appendChild(s); }(window, document));';