]>
git.immae.eu Git - github/shaarli/Shaarli.git/blob - inc/blazy-1.3.1.js
2 hey, [be]Lazy.js - v1.3.1 - 2015.02.01
3 A lazy loading and multi-serving image script
4 (c) Bjoern Klinggaard - @bklinggaard - http://dinbror.dk/blazy
6 ;(function(root
, blazy
) {
7 if (typeof define
=== 'function' && define
.amd
) {
8 // AMD. Register bLazy as an anonymous module
10 } else if (typeof exports
=== 'object') {
11 // Node. Does not work with strict CommonJS, but
12 // only CommonJS-like environments that support module.exports,
14 module
.exports
= blazy();
16 // Browser globals. Register bLazy on window
19 })(this, function () {
23 var source
, options
, viewport
, images
, count
, isRetina
, destroyed
;
25 var validateT
, saveViewportOffsetT
;
28 function Blazy(settings
) {
29 //IE7- fallback for missing querySelectorAll support
30 if (!document
.querySelectorAll
) {
31 var s
=document
.createStyleSheet();
32 document
.querySelectorAll = function(r
, c
, i
, j
, a
) {
33 a
=document
.all
, c
=[], r
= r
.replace(/\[for\b/gi, '[htmlFor').split(',');
34 for (i
=r
.length
; i
--;) {
35 s
.addRule(r
[i
], 'k:v');
36 for (j
=a
.length
; j
--;) a
[j
].currentStyle
.k
&& c
.push(a
[j
]);
47 options
= settings
|| {};
48 options
.error
= options
.error
|| false;
49 options
.offset
= options
.offset
|| 100;
50 options
.success
= options
.success
|| false;
51 options
.selector
= options
.selector
|| '.b-lazy';
52 options
.separator
= options
.separator
|| '|';
53 options
.container
= options
.container
? document
.querySelectorAll(options
.container
) : false;
54 options
.errorClass
= options
.errorClass
|| 'b-error';
55 options
.breakpoints
= options
.breakpoints
|| false;
56 options
.successClass
= options
.successClass
|| 'b-loaded';
57 options
.src
= source
= options
.src
|| 'data-src';
58 isRetina
= window
.devicePixelRatio
> 1;
59 viewport
.top
= 0 - options
.offset
;
60 viewport
.left
= 0 - options
.offset
;
61 //throttle, ensures that we don't call the functions too often
62 validateT
= throttle(validate
, 25);
63 saveViewportOffsetT
= throttle(saveViewportOffset
, 50);
67 //handle multi-served image src
68 each(options
.breakpoints
, function(object
){
69 if(object
.width
>= window
.screen
.width
) {
80 ************************************/
81 Blazy
.prototype.revalidate = function() {
84 Blazy
.prototype.load = function(element
, force
){
85 if(!isElementLoaded(element
)) loadImage(element
, force
);
87 Blazy
.prototype.destroy = function(){
88 if(options
.container
){
89 each(options
.container
, function(object
){
90 unbindEvent(object
, 'scroll', validateT
);
93 unbindEvent(window
, 'scroll', validateT
);
94 unbindEvent(window
, 'resize', validateT
);
95 unbindEvent(window
, 'resize', saveViewportOffsetT
);
101 /* private helper functions
102 ************************************/
103 function initialize(){
104 // First we create an array of images to lazy load
105 createImageArray(options
.selector
);
106 // Then we bind resize and scroll events if not already binded
109 if(options
.container
) {
110 each(options
.container
, function(object
){
111 bindEvent(object
, 'scroll', validateT
);
114 bindEvent(window
, 'resize', saveViewportOffsetT
);
115 bindEvent(window
, 'resize', validateT
);
116 bindEvent(window
, 'scroll', validateT
);
118 // And finally, we start to lazy load. Should bLazy ensure domready?
122 function validate() {
123 for(var i
= 0; i
<count
; i
++){
124 var image
= images
[i
];
125 if(elementInView(image
) || isElementLoaded(image
)) {
126 Blazy
.prototype.load(image
);
133 Blazy
.prototype.destroy();
137 function loadImage(ele
, force
){
138 // if element is visible
139 if(force
|| (ele
.offsetWidth
> 0 && ele
.offsetHeight
> 0)) {
140 var dataSrc
= ele
.getAttribute(source
) || ele
.getAttribute(options
.src
); // fallback to default data-src
142 var dataSrcSplitted
= dataSrc
.split(options
.separator
);
143 var src
= dataSrcSplitted
[isRetina
&& dataSrcSplitted
.length
> 1 ? 1 : 0];
144 var img
= new Image();
145 // cleanup markup, remove data source attributes
146 each(options
.breakpoints
, function(object
){
147 ele
.removeAttribute(object
.src
);
149 ele
.removeAttribute(options
.src
);
150 img
.onerror = function() {
151 if(options
.error
) options
.error(ele
, "invalid");
152 ele
.className
= ele
.className
+ ' ' + options
.errorClass
;
154 img
.onload = function() {
155 // Is element an image or should we add the src as a background image?
156 ele
.nodeName
.toLowerCase() === 'img' ? ele
.src
= src : ele
.style
.backgroundImage
= 'url("' + src
+ '")';
157 ele
.className
= ele
.className
+ ' ' + options
.successClass
;
158 if(options
.success
) options
.success(ele
);
160 img
.src
= src
; //preload image
162 if(options
.error
) options
.error(ele
, "missing");
163 ele
.className
= ele
.className
+ ' ' + options
.errorClass
;
168 function elementInView(ele
) {
169 var rect
= ele
.getBoundingClientRect();
173 rect
.right
>= viewport
.left
174 && rect
.bottom
>= viewport
.top
175 && rect
.left
<= viewport
.right
176 && rect
.top
<= viewport
.bottom
180 function isElementLoaded(ele
) {
181 return (' ' + ele
.className
+ ' ').indexOf(' ' + options
.successClass
+ ' ') !== -1;
184 function createImageArray(selector
) {
185 var nodelist
= document
.querySelectorAll(selector
);
186 count
= nodelist
.length
;
187 //converting nodelist to array
188 for(var i
= count
; i
--; images
.unshift(nodelist
[i
])){}
191 function saveViewportOffset(){
192 viewport
.bottom
= (window
.innerHeight
|| document
.documentElement
.clientHeight
) + options
.offset
;
193 viewport
.right
= (window
.innerWidth
|| document
.documentElement
.clientWidth
) + options
.offset
;
196 function bindEvent(ele
, type
, fn
) {
197 if (ele
.attachEvent
) {
198 ele
.attachEvent
&& ele
.attachEvent('on' + type
, fn
);
200 ele
.addEventListener(type
, fn
, false);
204 function unbindEvent(ele
, type
, fn
) {
205 if (ele
.detachEvent
) {
206 ele
.detachEvent
&& ele
.detachEvent('on' + type
, fn
);
208 ele
.removeEventListener(type
, fn
, false);
212 function each(object
, fn
){
214 var l
= object
.length
;
215 for(var i
= 0; i
<l
&& fn(object
[i
], i
) !== false; i
++){}
219 function throttle(fn
, minDelay
) {
222 var now
= +new Date();
223 if (now
- lastCall
< minDelay
) {
227 fn
.apply(images
, arguments
);