Skip to content

Commit

Permalink
0.1.1
Browse files Browse the repository at this point in the history
  • Loading branch information
aFarkas committed Oct 12, 2014
1 parent 554a56a commit 75e2931
Show file tree
Hide file tree
Showing 7 changed files with 80 additions and 55 deletions.
51 changes: 36 additions & 15 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,19 +1,33 @@
#lazysizes
**lazysizes** is a fast (jankfree) lazyloader for images (including responsive images), iframes and scripts/widgets without any dependency.

##Features

* supports standard conform **responsive images** (``srcset`` and ``picture``)
* loads ``iframes`` and ``script``
* Optional **automatic ``sizes`` attribute calculation** for your repsonsive images (simply add ``data-sizes="auto"``). respimg was never so easy.
* **easy to use** / no configuration required:
* no configuration required for scrollable areas (overflow: auto/scroll)
* no configuration or callback invocation required for any kind of JS widgets (tabs, carousels, accordions, dialogs) or any JS behaviors (i.e.: infinite scroll/AJAX)
* performance and memory optimized
* **absolutley jankfree** (decoding an image or parsing an iframe might create a jank, but the script itself will never ever, even if you had thounds of images to lazy load on one page)
* uses the low quality image placeholder pattern, if an image already has a valid source
* JS off syntax possible
* lightweight only 2kb

##Download and Embed

Simply download the [lazysizes.min.js](lazysizes.min.js) and include it in your webpage:

```html
<script src="lazysizes.min.js"></script>
<script src="lazysizes.min.js" async=""></script>
```

##[Demo with code examples](http://afarkas.github.io/lazysizes/#examples)
can be seen [here](http://afarkas.github.io/lazysizes/#examples).

##API
lazysizes comes with a simple markup and JS API:
**lazysizes** comes with a simple markup and JS API:

###Markup API
Simply add the ``class`` ``lazyload`` to all ``img`` and ``iframe`` elements, which should be loaded lazy. Instead of a ``src`` or ``srcset`` attribute, use a ``data-src`` or ``data-srcset`` attribute:
Expand All @@ -24,24 +38,24 @@ Simply add the ``class`` ``lazyload`` to all ``img`` and ``iframe`` elements, wh
<img data-srcset="responsive-image1.jpg 1x, responsive-image2.jpg 2x" class="lazyload" />
```

As a nice bonus lazysizes supports setting the ``sizes`` attribute automatically corresponding to the current size of your image. To add support for this add the value ``auto`` to the ``data-sizes`` attribute:
**lazysizes** supports setting the ``sizes`` attribute automatically corresponding to the current size of your image. To add support for this add the value ``auto`` to the ``data-sizes`` attribute:

```html
<img
data-sizes="auto"
data-srcset="responsive-image1.jpg 300w,
data-srcset="responsive-image1.jpg 300w,
responsive-image2.jpg 600w,
responsive-image3.jpg 900w" class="lazyload" />
```

**How sizes is calculated**: The automatic sizes calculation takes the with of the image and the width of its parent element and uses the largeest number of those two calculated numbers. It's therefore important, that all images are contained in a wrapper that isn't much bigger than the image should shown. Otherwise a wrong (too big) sizes attribute will be calculated.
**Important: How ``sizes`` is calculated**: The automatic sizes calculation takes the width of the image and the width of its parent element and uses the largest number of those two calculated numbers. It's therefore important, that all images are contained in a wrapper that isn't much bigger than the image should shown. Otherwise a wrong (too big) sizes attribute will be calculated.

For JS off support simply use a ``span`` or ``div`` element as a wrapper for a ``noscript`` element:

```html
<span
data-sizes="auto"
data-srcset="responsive-image1.jpg 300w,
data-srcset="responsive-image1.jpg 300w,
responsive-image2.jpg 600w,
responsive-image3.jpg 900w" class="lazyload">
<noscript>
Expand All @@ -50,16 +64,23 @@ For JS off support simply use a ``span`` or ``div`` element as a wrapper for a `
</span>
```

###JS API
**lazysizes** automatically detects new elements with the class ``lazyload`` so you wont need to call anything.

####``lazySizes.updateAllLazy``
In case a lazyload image was hidden and then shown via JS the method ``lazySizes.updateAllLazy`` can be called:
##recommended markup: LQIP
We recommend to use the LQIP pattern: Simply add a low quality image as the ``src``:

```js
lazySizes.updateAllLazy();
```html
<img
data-sizes="auto"
src="lqip-src.jpg"
data-srcset="lqip-src.jpg 150w,
image2.jpg 300w,
image3.jpg 600w,
image4.jpg 900w" class="lazyload" />
```

###JS API
**lazysizes** automatically detects new elements with the class ``lazyload`` so you won't need to call anything in most situations.


####``lazySizes.unveilLazy(DOMNode)``

In case a developer wants to show an image even if it is not inside the viewport the ``lazySizes.unveilLazy(DOMNode)`` can be called:
Expand All @@ -77,7 +98,7 @@ lazySizes.updateAllSizes();
```

##Browser Support
**lazysizes** is supported by [all browsers which support ``getElementsByClassName``](http://caniuse.com/#feat=getelementsbyclassname). (No IE8 support.)
**lazysizes** is supports the following browsers: IE9+, Firefox 21+, Chrome 27+, Safari 6.1+, iOS Safari 7.0+, Android 4.1+

##About responsive image support
For full cross browser responsive image support a polyfill like [respimage](https://github.com/aFarkas/respimage) or [picturefill](https://github.com/scottjehl/picturefill) has to be used.
For full cross browser responsive image support a polyfill like [respimage](https://github.com/aFarkas/respimage) or [picturefill](https://github.com/scottjehl/picturefill) has to be used.
2 changes: 1 addition & 1 deletion bower.json
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
{
"name": "lazysizes",
"repo": "afarkas/lazysizes",
"version": "0.1.0",
"version": "0.1.1",
"main": "lazysizes.min.js",
"scripts": [
"lazysizes.min.js"
Expand Down
2 changes: 1 addition & 1 deletion component.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "lazysizes",
"version": "0.1.0",
"version": "0.1.1",
"repo": "afarkas/lazysizes",
"main": "lazysizes.min.js",
"scripts": ["lazysizes.min.js"],
Expand Down
7 changes: 1 addition & 6 deletions index.html
Original file line number Diff line number Diff line change
Expand Up @@ -227,7 +227,7 @@ <h3>responsive image with the <code>picture</code> element</h3>
<div class="row" id="autosizes-example">
<div class="alert alert-info">
<p><strong>automatic sizes feature</strong>: In case of lazy loading images the <code>sizes</code> attribute of the <code>img</code>/<code>source</code> elements can be calculated with JS.</p>
<p>This automatic sizes feature is directly included in <strong>lazySizes<</strong>. Simply use the keyword <code>auto</code> inside of the <code>data-sizes</code> attributes (<code>data-sizes="auto"</code>).</p>
<p>This automatic sizes feature is directly included in <strong>lazySizes</strong>. Simply use the keyword <code>auto</code> inside of the <code>data-sizes</code> attributes (<code>data-sizes="auto"</code>).</p>
</div>

<div class="col-sm-12">
Expand Down Expand Up @@ -619,10 +619,5 @@ <h3>Widgets/Javascript/Script</h3>


</div>
<script>
$(document).on('slide.bs.carousel', function(){
lazySizes.updateAllLazy();
});
</script>
</body>
</html>
67 changes: 38 additions & 29 deletions lazysizes.js
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@
var regScript = /^script$/i;
var regImg = /^img$/i;
var noDataTouch = {sizes: 1, src: 1, srcset: 1};
var inViewTreshhold = 99;
var inViewTreshhold = 66;
var lazyloadElems = document.getElementsByClassName('lazyload');
var autosizesElems = document.getElementsByClassName('lazyautosizes');
var setImmediate = window.setImmediate || window.setTimeout;
Expand Down Expand Up @@ -57,21 +57,6 @@
};
}



function inView(el) {
var rect = el.getBoundingClientRect();
var bottom, right, left, top;

return !!(
(bottom = rect.bottom) >= (inViewTreshhold * -1) &&
(top = rect.top) <= window.innerHeight + inViewTreshhold &&
(right = rect.right) >= (inViewTreshhold * -1) &&
(left = rect.left) <= window.innerWidth + inViewTreshhold &&
(bottom || right || left || top)
);
}

function updatePolyfill(el, full){
var imageData;
if(window.picturefill){
Expand Down Expand Up @@ -108,30 +93,40 @@
if(!running){
running = true;
clearTimeout(timer);
timer = setTimeout(run, 66);
timer = setTimeout(run, 99);
}
}
};
})();

var evalLazyElements = function (){
var now, i, checkTime;
var now, i, checkTime, vW, vH, rect, top, left, right, bottom, negativeTreshhold;
var len = lazyloadElems.length;
if(len){
now = Date.now();
checkTime = 0;
vW = window.innerWidth + inViewTreshhold;
vH = window.innerHeight + inViewTreshhold;
negativeTreshhold = inViewTreshhold * -1;

i = globalLazyIndex || 0;

clearLazyTimer();

for(; i < len; i++){
if (inView(lazyloadElems[i])){
rect = lazyloadElems[i].getBoundingClientRect();

if ((bottom = rect.bottom) >= negativeTreshhold &&
(top = rect.top) <= vH &&
(right = rect.right) >= negativeTreshhold &&
(left = rect.left) <= vW &&
(bottom || right || left || top)){
unveilLazy(lazyloadElems[i]);
} else {
checkTime++;
if(2 < checkTime && i < len - 1 && Date.now() - now > 9){
globalLazyIndex = i + 1;

globalLazyTimer = setTimeout(evalLazyElements, 20);
break;
}
Expand Down Expand Up @@ -285,6 +280,7 @@

if(i > checkTime && i < len - 1 && Date.now() - now > 9){
globalSizesIndex = i + 1;

globalSizesTimer = setTimeout(evalSizesElements, 20);
break;
}
Expand All @@ -308,7 +304,8 @@
elemWidth :
parentWidth;

if(width){
if(width && (!elem._lazysizesWidth || width > elem._lazysizesWidth)){
elem._lazysizesWidth = width;
width += 'px';
elem.setAttribute('sizes', width);

Expand All @@ -326,33 +323,45 @@
}
}

// bind to all possible events ;-) This might look like a performance disaster, but it isn't.
// The main check functions are written to run extreme fast without consuming memory.
var onload = function(){
inViewTreshhold *= 3;
clearTimeout(globalInitialTimer);

document.addEventListener('load', lazyEvalLazy.throttled, true);
};
var onready = function(){
if(window.MutationObserver){
new MutationObserver( lazyEvalLazy.debounce ).observe( document.body || document.documentElement, {childList: true, subtree: true} );
new MutationObserver( lazyEvalLazy.throttled ).observe( document.body || document.documentElement, {childList: true, subtree: true, attributes: true} );
} else {
(document.body || document.documentElement).addEventListener( "DOMNodeInserted", lazyEvalLazy.debounce, true);
(document.body || document.documentElement).addEventListener( "DOMNodeInserted", lazyEvalLazy.throttled, true);
(document.body || document.documentElement).addEventListener( "DOMAttrModified", lazyEvalLazy.throttled, true);
}
document.body.addEventListener('scroll', lazyEvalLazy.throttled, true);
};

window.addEventListener('scroll', lazyEvalLazy.throttled, false);

window.addEventListener('resize', lazyEvalLazy.debounce, false);
document.addEventListener('load', lazyEvalLazy.debounce, true);
window.addEventListener('scroll', lazyEvalLazy.throttled, false);
(document.body || document.documentElement).addEventListener('scroll', lazyEvalLazy.throttled, true);

document.addEventListener('touchmove', lazyEvalLazy.debounce, true);
document.addEventListener('readystatechange', lazyEvalLazy.debounce, false);
document.addEventListener('touchmove', lazyEvalLazy.throttled, false);

window.addEventListener('resize', lazyEvalLazy.debounce, false);
window.addEventListener('resize', lazyEvalSizes, false);

if( /^i|^loade|c/.test(document.readyState) ){
onready();
} else {
document.addEventListener('DOMContentLoaded', onready, false);
}

if(document.readyState == 'complete'){
onload();
} else {
window.addEventListener('load', onload, false);
document.addEventListener('readystatechange', lazyEvalLazy.throttled, false);
}
lazyEvalLazy.debounce();
lazyEvalLazy.throttled();

return {
updateAllSizes: lazyEvalSizes,
Expand Down
Loading

0 comments on commit 75e2931

Please sign in to comment.