1/*! 2 * jQuery Lazy - v0.1.19 3 * http://jquery.eisbehr.de/lazy/ 4 * http://eisbehr.de 5 * 6 * Copyright 2014, Daniel 'Eisbehr' Kern 7 * 8 * Dual licensed under the MIT and GPL v2 licenses: 9 * http://www.opensource.org/licenses/mit-license.php 10 * http://www.gnu.org/licenses/gpl-2.0.html 11 * 12 * jQuery("img.lazy").lazy(); 13 */ 14 15(function($, window, document, undefined) 16{ 17 $.fn.lazy = function(settings) 18 { 19 /** 20 * settings and configuration data 21 * @type {} 22 */ 23 var configuration = 24 { 25 // general 26 bind : "load", 27 //threshold : 500, 28 threshold : 0, //change by steve 29 fallbackHeight : 2000, 30 visibleOnly : true, 31 appendScroll : window, 32 33 // delay 34 delay : -1, 35 combined : false, 36 37 // attribute 38 attribute : "data-src", 39 removeAttribute : true, 40 41 // effect 42 effect : "show", 43 effectTime : 0, 44 45 // throttle 46 enableThrottle : false, 47 throttle : 250, 48 49 // callback 50 beforeLoad : null, 51 onLoad : null, 52 afterLoad : null, 53 onError : null, 54 onFinishedAll : null 55 }; 56 57 // overwrite configuration with custom user settings 58 if( settings ) $.extend(configuration, settings); 59 60 // all given items by jQuery selector 61 var items = this; 62 63 // a helper to trigger the onFinishedAll after all other events 64 var awaitingAfterLoad = 0; 65 66 // on first page load get initial images 67 if( configuration.bind == "load" ) $(window).load(_init); 68 69 // if event driven don't wait for page loading 70 else if( configuration.bind == "event" ) _init(); 71 72 // bind error callback to images if wanted 73 if( configuration.onError ) items.bind("error", function() { _triggerCallback(configuration.onError, $(this)); }); 74 75 /** 76 * lazyLoadImages(allImages) 77 * 78 * the 'lazy magic' 79 * check and load all needed images 80 * 81 * @param allImages boolean 82 * @return void 83 */ 84 function lazyLoadImages(allImages) 85 { 86 if( typeof allImages != "boolean" ) allImages = false; 87 88 items.each(function() 89 { 90 var element = $(this); 91 var tag = this.tagName.toLowerCase(); 92 93 if( _isInLoadableArea(element) || allImages ) 94 { 95 // the lazy magic 96 if( // image source attribute is available 97 element.attr(configuration.attribute) && 98 // and is image tag where attribute is not equal source 99 ((tag == "img" && element.attr(configuration.attribute) != element.attr("src")) || 100 // or is non image tag where attribute is not equal background 101 ((tag != "img" && element.attr(configuration.attribute) != element.css("background-image"))) ) && 102 // and is not actually loaded just before 103 !element.data('status') && 104 // and is visible or visibility doesn't matter 105 (element.is(":visible") || !configuration.visibleOnly) ) 106 { 107 // create image object 108 var imageObj = $(new Image()); 109 110 // increment count of items waiting for after load 111 ++awaitingAfterLoad; 112 113 // bind error event if wanted, otherwise only reduce waiting count 114 if(configuration.onError) imageObj.error(function() { element.data("status", ''); _triggerCallback(configuration.onError, element); _reduceAwaiting(); }); 115 else imageObj.error(function() { element.data("status", ''); _reduceAwaiting(); }); 116 117 // bind after load callback to image 118 var onLoad = true; 119 imageObj.one("load", function() 120 { 121 var callable = function() 122 { 123 if( onLoad ) 124 { 125 window.setTimeout(callable, 100); 126 return; 127 } 128 129 // remove element from view 130 element.hide(); 131 132 // set image back to element 133 if( tag == "img" ) element.attr("src", imageObj.attr("src")); 134 else element.css("background-image", "url(" + imageObj.attr("src") + ")"); 135 136 // bring it back with some effect! 137 element[configuration.effect](configuration.effectTime); 138 139 // remove attribute from element 140 if( configuration.removeAttribute ) element.removeAttr(configuration.attribute); 141 142 // call after load event 143 _triggerCallback(configuration.afterLoad, element); 144 element.data("status", "loaded"); 145 146 // unbind event and remove image object 147 imageObj.unbind("load"); 148 imageObj.remove(); 149 150 // remove item from waiting cue and possible trigger finished event 151 _reduceAwaiting(); 152 }; 153 154 callable(); 155 }); 156 157 // trigger function before loading image 158 _triggerCallback(configuration.beforeLoad, element); 159 160 // set source 161 imageObj.attr("src", element.attr(configuration.attribute)); 162 163 // trigger function before loading image 164 _triggerCallback(configuration.onLoad, element); 165 onLoad = false; 166 167 // call after load even on cached image 168 if( imageObj.complete ) imageObj.load(); 169
170 // mark element always as loaded 171 element.data("status", "loading"); 172 } 173 } 174 }); 175 176 // cleanup all items which are already loaded 177 items = $(items).filter(function() 178 { 179 return $(this).data("status") !="loaded"; 180 }); 181 } 182 183 /** 184 * _init() 185 * 186 * initialize lazy plugin 187 * bind loading to events or set delay time to load all images at once 188 * 189 * @return void 190 */ 191 function _init() 192 { 193 // if delay time is set load all images at once after delay time 194 if( configuration.delay >= 0 ) setTimeout(function() { lazyLoadImages(true); }, configuration.delay); 195 196 // if no delay is set or combine usage is active bind events 197 if( configuration.delay < 0 || configuration.combined ) 198 { 199 // load initial images 200 lazyLoadImages(false); 201 202 // bind lazy load functions to scroll and resize event 203 $(configuration.appendScroll).bind("scroll", _throttle(configuration.throttle, lazyLoadImages)); 204 $(configuration.appendScroll).bind("resize", _throttle(configuration.throttle, lazyLoadImages)); 205 } 206 } 207 208 /** 209 * _isInLoadableArea(element) 210 * 211 * check if the given element is inside the current viewport or threshold 212 * 213 * @param element jQuery 214 * @return boolean 215 */ 216 function _isInLoadableArea(element) 217 { 218 var top = document.documentElement.scrollTop ? document.documentElement.scrollTop : document.body.scrollTop; 219 //return (top + _getActualHeight() + configuration.threshold) > (element.offset().top + element.height()); 220 return (top + _getActualHeight()) > (element.offset().top + configuration.threshold);//change by steve 221 } 222 223 /** 224 * _getActualHeight() 225 * 226 * try to allocate current viewport height of the browser 227 * uses fallback option when no height is found 228 * 229 * @return number 230 */ 231 function _getActualHeight() 232 { 233 if( window.innerHeight ) return window.innerHeight; 234 if( document.documentElement && document.documentElement.clientHeight ) return document.documentElement.clientHeight; 235 if( document.body && document.body.clientHeight ) return document.body.clientHeight; 236 if( document.body && document.body.offsetHeight ) return document.body.offsetHeight; 237 238 return configuration.fallbackHeight; 239 } 240 241 /** 242 * _throttle(delay, call) 243 * 244 * helper function to throttle down event triggering 245 * 246 * @param delay integer 247 * @param call function object 248 * @return function object 249 */ 250 function _throttle(delay, call) 251 { 252 var _timeout; 253 var _exec = 0; 254 255 function callable() 256 { 257 var elapsed = +new Date() - _exec; 258 259 function run() 260 { 261 _exec = +new Date(); 262 call.apply(); 263 } 264 265 _timeout && clearTimeout(_timeout); 266 267 if( elapsed > delay || !configuration.enableThrottle ) run(); 268 else _timeout = setTimeout(run, delay - elapsed); 269 } 270 271 return callable; 272 } 273 274 /** 275 * _reduceAwaiting() 276 * 277 * reduce count of awaiting elements to the afterLoad event and fire onFinishedAll if reached zero 278 * 279 * @return void 280 */ 281 function _reduceAwaiting() 282 { 283 --awaitingAfterLoad; 284 285 // if no items were left trigger finished event 286 if( !items.size() && !awaitingAfterLoad ) _triggerCallback(configuration.onFinishedAll, null); 287 } 288 289 /** 290 * _triggerCallback(callback, element) 291 * 292 * single implementation to handle callbacks and pass parameter 293 * 294 * @param callback function object 295 * @param element jQuery 296 * @return void 297 */ 298 function _triggerCallback(callback, element) 299 { 300 if( callback ) 301 { 302 if( element !== null ) 303 callback(element); 304 else 305 callback(); 306 } 307 } 308 309 return this; 310 }; 311 312 // make lazy a bit more case-insensitive :) 313 $.fn.Lazy = $.fn.lazy; 314 315})(jQuery, window, document);
Line numbers count LF bytes from the start of the resource, as the search results do. Vendor segments are library code the classifier recognised; they are stored but not indexed. Bytes are shown as Latin1 characters, one per byte.