From 1b57c83b82736c386e804a1c1119793a5a8c549f Mon Sep 17 00:00:00 2001 From: aFarkas Date: Sat, 31 Jan 2015 21:32:44 +0100 Subject: [PATCH] 0.9.0-RC2 --- README.md | 14 +++++++------- plugins/optimumx/ls.optimumx.js | 2 +- plugins/optimumx/ls.optimumx.min.js | 2 +- tests/functional-tests-plugins.js | 25 +++++++++++++++++-------- 4 files changed, 26 insertions(+), 17 deletions(-) diff --git a/README.md b/README.md index f1f42025..fc4879a5 100644 --- a/README.md +++ b/README.md @@ -40,10 +40,10 @@ 1. **Works without any configuration or JS callbacks in any web enviroment**: The script works as an universal, self-initializing, self-configuring and self-destroying component and detects any changes to the visibility of any current and future image/iframe elements automatically no matter whether it becomes visible through a user scroll, a CSS animation triggered through ``:hover`` or through any kind of JS behavior (carousel, slider, infinite scroll, isotope/filtering/sorting, AJAX, SPAs...). Also works automatically in conjunction with any kind of JS-/CSS-/Frontend-Framework (jQuery mobile, Bootstrap, Backbone, Angular, React, ember). 2. **Future-proof**: It directly includes standard responsive image support (``picture`` and ``srcset``) 3. **Separation of concerns**: For responsive image support it adds an automatic ``sizes`` calculation as also alias names for media queries feature. There is also no JS change needed if you add a scrollable container with CSS (overflow: auto) or create a mega menu containing images. -4. **Performance**: It's based on high efficient and best practice code (runtime **and** memory) to work jank-free at 60fps. -5. **Extendable**: It provides JS and CSS hooks to extend lazySizes with any kind of lazy loading or effects (see also the [available plugins/snippets](#plugins)). +4. **Performance**: It's based on high efficient and best practice code (runtime **and** memory) to work jank-free at 60fps. Can be used with thousands of images/iframes on CSS and JS heavy pages/webapps. +5. **Extendable**: It provides JS and CSS hooks to extend lazySizes with any kind of lazy loading, lazy instantiation, inview callbacks or effects (see also the [available plugins/snippets](#plugins)). 6. **Intelligent prefetch**: lazySizes prefetches near the view assets, only while the browser network is idling. (see also ``expand`` option) -7. **Lightweight, but mature solution**: lazySizes has the right balance between lightweight and a reliable and fast solution +7. **Lightweight, but mature solution**: lazySizes has the right balance between a lightweight and a reliable and fast solution ##[Demo with code examples](http://afarkas.github.io/lazysizes/#examples) Can be seen [here](http://afarkas.github.io/lazysizes/#examples). @@ -73,7 +73,7 @@ Add the ``class`` ``lazyload`` to all ``img`` and ``iframe`` elements, which sho responsive-image3.jpg 900w" class="lazyload" /> ``` -**Important: How ``sizes`` is calculated**: The automatic sizes calculation takes the width of the image. If it is below ``50`` (can be configured through the ``minSize`` option), lazySizes traverses up the DOM tree until it finds a parent which is over ``50`` and uses this number. Often the following general CSS rule might help: ``img[data-sizes="auto"] { display: block; }``. +**Important: How ``sizes`` is calculated**: The automatic sizes calculation takes the width of the image. If it is below ``50`` (can be configured through the ``minSize`` option), lazySizes traverses up the DOM tree until it finds a parent which is over ``50`` and uses this number. Often the following general CSS rule might help: ``img[data-sizes="auto"] { display: block; }``. (see also [specifying image/iframe dimensions](#specify-dimensions) ##Recommended markup patterns For some image bots (search engines and social networks), legacy browsers (IE8) or JS disabled browsers, it is important to serve a usable ``src`` attribute: @@ -182,7 +182,6 @@ Here the list of options: * ``lazySizesConfig.srcset`` (default: ``"data-srcset"``): The attribute, which should be transformed to ``srcset``. * ``lazySizesConfig.sizesAttr`` (default: ``"data-sizes"``): The attribute, which should be transformed to ``sizes``. Makes almost only sense with the value ``"auto"``. Otherwise the ``sizes`` attribute should be used directly. * ``lazySizesConfig.customMedia`` (default: ``{}``): The ``customMedia`` option object is an alias map for different media queries. It can be used to separate your specific media queries implementation for the ``source[media]`` attribute by creating labeled media queries. (See also the [custommedia extension](plugins/custommedia)). -* ``lazySizesConfig.init`` (default: ``true``): By default lazySizes initializes itself as soon as possible, to load inview assets as soon as possible. In the unlikely case you need to setup/configure something with a later script you can set this option to ``false`` and call ``lazySizes.init();`` later explicitly. ```html @@ -425,7 +425,7 @@ Due to the fact, that it is designed to be invoked with a high frequency and the class="lazyload" /> ``` -##Tip: Specifying image dimensions (minimizing reflows and avoiding page jumps) +##Tip: Specifying image dimensions (minimizing reflows and avoiding page jumps) To minimize reflows, content jumping or unpredictable behavior with some other JS widgets (isotope, masonry, some sliders/carousels...) the width **and** the height of an image should be calculable by the browser before the image source itself is loaded. For "static" images this can done using either CSS or using the content attributes: ```html diff --git a/plugins/optimumx/ls.optimumx.js b/plugins/optimumx/ls.optimumx.js index c5dea4ed..c95b27b4 100644 --- a/plugins/optimumx/ls.optimumx.js +++ b/plugins/optimumx/ls.optimumx.js @@ -54,7 +54,7 @@ if(typeof config.getOptimumX != 'function'){ config.getOptimumX = function(/*element*/){ - var dpr = window.devicePixelRatio; + var dpr = window.devicePixelRatio || 1; if(dpr > 2.4){ dpr *= 0.63; // returns 1.9 for 3 } else if(dpr > 1.9){ diff --git a/plugins/optimumx/ls.optimumx.min.js b/plugins/optimumx/ls.optimumx.min.js index 6aa4401e..fcfdff65 100644 --- a/plugins/optimumx/ls.optimumx.min.js +++ b/plugins/optimumx/ls.optimumx.min.js @@ -1,3 +1,3 @@ /*! lazysizes - v0.9.0-RC2 - 2015-01-31 Licensed MIT */ -!function(a,b){"use strict";function c(a,b){return a.w-b.w}function d(a){var b={srcset:a.getAttribute(lazySizes.cfg.srcsetAttr)||""},d=l(b.srcset);return Object.defineProperty(a,"_lazyOptimumx",{value:b,writable:!0}),b.cands=d,b.index=0,b.dirty=!1,d[0]&&d[0].w?(d.sort(c),b.cSrcset=[d[0].c]):(b.cSrcset=b.srcset?[b.srcset]:[],b.cands=[]),b}function e(a){var b,c,e,f=a.parentNode||{},g=d(a);if(g.isImg=!0,m.test(f.nodeName||""))for(g.picture=!0,b=f.getElementsByTagName("source"),c=0,e=b.length;e>c;c++)d(b[c]).isImg=!1;return g}function f(a,b,c){var d,e;return a&&a.w?a.w>c?!1:(d=1-a.w/c,e=b/c-1,0>e-d):!0}function g(a,b){var c,d;for(c=a.index+1;c=f.cands.length&&(a.removeAttribute("data-optimumx"),a.removeAttribute("data-maxdpr"))),e):void 0}function i(a){var b=a.getAttribute("data-optimumx")||a.getAttribute("data-maxdpr");return b&&(b="auto"==b?j.getOptimumX(a):parseFloat(b,10)),b}var j,k,l,m=/^picture$/i,n=b.documentElement;l=function(){var a,b=/(([^,\s].[^\s]+)\s+(\d+)w)/g,c=/\s+\d+h/g,d=function(b,c,d,e){a.push({c:c,u:d,w:1*e})};return function(e){return a=[],e.replace(c,"").replace(b,d),a}}(),j=a.lazySizes&&lazySizes.cfg||a.lazySizesConfig,j||(j={},a.lazySizesConfig=j),"function"!=typeof j.getOptimumX&&(j.getOptimumX=function(){var b=a.devicePixelRatio;return b>2.4?b*=.63:b>1.9?b*=.8:b>1.4&&(b*=.9),Math.min(Math.round(100*b)/100,2)}),k=function(){a.lazySizes&&!a.lazySizes.getOptimumX&&(lazySizes.getX=i,lazySizes.pWS=l,n.removeEventListener("lazybeforeunveil",k))},n.addEventListener("lazybeforeunveil",k),setTimeout(k),a.devicePixelRatio&&(addEventListener("lazybeforesizes",function(b){var c,d,f,g,j,k,l,m;if(!(b.defaultPrevented||!(c=i(b.target))||c>=a.devicePixelRatio)&&(d=b.target._lazyOptimumx||e(b.target),f=b.details.width*c,f&&(d.width||0)l;l++)h(k[l],f,g);b.details.srcset=h(b.target,f,g)}}),addEventListener("lazybeforeunveil",function(a){a.target._lazyOptimumx&&(a.target._lazyOptimumx=null)}))}(window,document); \ No newline at end of file +!function(a,b){"use strict";function c(a,b){return a.w-b.w}function d(a){var b={srcset:a.getAttribute(lazySizes.cfg.srcsetAttr)||""},d=l(b.srcset);return Object.defineProperty(a,"_lazyOptimumx",{value:b,writable:!0}),b.cands=d,b.index=0,b.dirty=!1,d[0]&&d[0].w?(d.sort(c),b.cSrcset=[d[0].c]):(b.cSrcset=b.srcset?[b.srcset]:[],b.cands=[]),b}function e(a){var b,c,e,f=a.parentNode||{},g=d(a);if(g.isImg=!0,m.test(f.nodeName||""))for(g.picture=!0,b=f.getElementsByTagName("source"),c=0,e=b.length;e>c;c++)d(b[c]).isImg=!1;return g}function f(a,b,c){var d,e;return a&&a.w?a.w>c?!1:(d=1-a.w/c,e=b/c-1,0>e-d):!0}function g(a,b){var c,d;for(c=a.index+1;c=f.cands.length&&(a.removeAttribute("data-optimumx"),a.removeAttribute("data-maxdpr"))),e):void 0}function i(a){var b=a.getAttribute("data-optimumx")||a.getAttribute("data-maxdpr");return b&&(b="auto"==b?j.getOptimumX(a):parseFloat(b,10)),b}var j,k,l,m=/^picture$/i,n=b.documentElement;l=function(){var a,b=/(([^,\s].[^\s]+)\s+(\d+)w)/g,c=/\s+\d+h/g,d=function(b,c,d,e){a.push({c:c,u:d,w:1*e})};return function(e){return a=[],e.replace(c,"").replace(b,d),a}}(),j=a.lazySizes&&lazySizes.cfg||a.lazySizesConfig,j||(j={},a.lazySizesConfig=j),"function"!=typeof j.getOptimumX&&(j.getOptimumX=function(){var b=a.devicePixelRatio||1;return b>2.4?b*=.63:b>1.9?b*=.8:b>1.4&&(b*=.9),Math.min(Math.round(100*b)/100,2)}),k=function(){a.lazySizes&&!a.lazySizes.getOptimumX&&(lazySizes.getX=i,lazySizes.pWS=l,n.removeEventListener("lazybeforeunveil",k))},n.addEventListener("lazybeforeunveil",k),setTimeout(k),a.devicePixelRatio&&(addEventListener("lazybeforesizes",function(b){var c,d,f,g,j,k,l,m;if(!(b.defaultPrevented||!(c=i(b.target))||c>=a.devicePixelRatio)&&(d=b.target._lazyOptimumx||e(b.target),f=b.details.width*c,f&&(d.width||0)l;l++)h(k[l],f,g);b.details.srcset=h(b.target,f,g)}}),addEventListener("lazybeforeunveil",function(a){a.target._lazyOptimumx&&(a.target._lazyOptimumx=null)}))}(window,document); \ No newline at end of file diff --git a/tests/functional-tests-plugins.js b/tests/functional-tests-plugins.js index 33dc7b02..3c3eae1e 100644 --- a/tests/functional-tests-plugins.js +++ b/tests/functional-tests-plugins.js @@ -269,7 +269,7 @@ $.extend(window.lazyTests, { riasReinit: ['lazysizes rias can be re-initialized', function(assert){ var done = assert.async(); - this.promise.always(function($){ + this.promise.always(function($, frameWindow){ var placeholderSrc, $image; var initTest = function(){ var success = [ @@ -320,6 +320,11 @@ $.extend(window.lazyTests, { var run = function(){ if(test.length){ placeholderSrc = test.shift(); + + if(!window.devicePixelRatio){ + $image.removeAttr('src'); + } + $image .attr('data-src', placeholderSrc[0]) .addClass('lazyload') @@ -328,23 +333,27 @@ $.extend(window.lazyTests, { done(); } }; - - - $image = $('') - .appendTo('body') - ; - - run(); + $image = $(''); $image.on('lazybeforeunveil', function(e){ setTimeout(function(){ + console.log('jo') placeholderSrc[1](); run(); }, 9); }); + + $image.appendTo('body'); + + run(); }); }], optimumxReinit: ['lazysizes optimumx can be re-initialized', function(assert){ + + if(!window.devicePixelRatio){ + assert.ok(true); + return; + } var done = assert.async(); this.promise.always(function($){