1/** 2 * Lazy Load XT v1.1.0 2016-01-12 3 * http://ressio.github.io/lazy-load-xt 4 * (C) 2016 RESS.io 5 * Licensed under MIT 6 * reformatted code by ThemeComplete 7 */ 8 9( function( $, window, document ) { 10 'use strict'; 11 12 // options 13 var lazyLoadXT = 'lazyLoadXT', 14 dataLazied = 'lazied', 15 loadError = 'load error', 16 classLazyHidden = 'lazy-hidden', 17 docElement = document.documentElement || document.body, 18 // force load all images in Opera Mini and some mobile browsers without scroll event or getBoundingClientRect() 19 forceLoad = 20 window.onscroll === undefined || 21 !! window.operamini || 22 ! docElement.getBoundingClientRect, 23 options = { 24 autoInit: true, // auto initialize in document ready 25 selector: 'img[data-src]', // selector for lazyloading elements 26 blankImage: 'data:image/gif;base64,R0lGODlhAQABAIAAAAAAAP///yH5BAEAAAAALAAAAAABAAEAAAIBRAA7', 27 throttle: 99, // interval (ms) for changes check 28 forceLoad: forceLoad, // force auto load all images 29 30 loadEvent: 'pageshow', // check AJAX-loaded content in jQueryMobile 31 updateEvent: 'load orientationchange resize scroll touchmove focus', // page-modified events 32 forceEvent: 'lazyloadall', // force loading of all elements 33 34 //onstart: null, 35 oninit: { removeClass: 'lazy' }, // init handler 36 onshow: { addClass: classLazyHidden }, // start loading handler 37 onload: { removeClass: classLazyHidden, addClass: 'lazy-loaded' }, // load success handler 38 onerror: { removeClass: classLazyHidden }, // error handler 39 //oncomplete: null, // complete handler 40 41 //scrollContainer: undefined, 42 checkDuplicates: true 43 }, 44 elementOptions = { 45 srcAttr: 'data-src', 46 edgeX: 0, 47 edgeY: 0, 48 visibleOnly: true 49 }, 50 $window = $( window ), 51 $isFunction = function( f ) { 52 return typeof f === 'function'; 53 }, 54 $extend = $.extend, 55 $data = 56 $.data || 57 function( el, name ) { 58 return $( el ).data( name ); 59 }, 60 elements = [], 61 topLazy = 0, 62 /* 63 waitingMode=0 : no setTimeout 64 waitingMode=1 : setTimeout, no deferred events 65 waitingMode=2 : setTimeout, deferred events 66 */ 67 waitingMode = 0; 68 69 $[ lazyLoadXT ] = $extend( options, elementOptions, $[ lazyLoadXT ] ); 70 71 /** 72 * Return options.prop if obj.prop is undefined, otherwise return obj.prop 73 * 74 * @param {*} obj 75 * @param {*} prop 76 */ 77 function getOrDef( obj, prop ) { 78 return obj[ prop ] === undefined ? options[ prop ] : obj[ prop ]; 79 } 80 81 function scrollTop() { 82 var scroll = window.pageYOffset; 83 return scroll === undefined ? docElement.scrollTop : scroll; 84 } 85 86 /** 87 * Run check of lazy elements after timeout 88 */ 89 function timeoutLazyElements() { 90 if ( waitingMode > 1 ) { 91 waitingMode = 1; 92 checkLazyElements(); 93 setTimeout( timeoutLazyElements, options.throttle ); 94 } else { 95 waitingMode = 0; 96 } 97 } 98 99 /** 100 * Queue check of lazy elements because of event e 101 * 102 * @param {Event} [e] 103 */ 104 function queueCheckLazyElements( e ) { 105 if ( ! elements.length ) { 106 return; 107 } 108 109 // fast check for scroll event without new visible elements 110 if ( e && e.type === 'scroll' && e.currentTarget === window ) { 111 if ( topLazy >= scrollTop() ) { 112 return; 113 } 114 } 115 116 if ( ! waitingMode ) { 117 setTimeout( timeoutLazyElements, 0 ); 118 } 119 waitingMode = 2; 120 } 121 122 /** 123 * Process function/object event handler 124 * 125 * @param {string} event suffix 126 * @param {jQuery} $el 127 */ 128 function triggerEvent( event, $el ) { 129 var handler = options[ 'on' + event ]; 130 if ( handler ) { 131 if ( $isFunction( handler ) ) { 132 handler.call( $el[ 0 ] ); 133 } else { 134 if ( handler.addClass ) { 135 $el.addClass( handler.addClass ); 136 } 137 if ( handler.removeClass ) { 138 $el.removeClass( handler.removeClass ); 139 } 140 } 141 } 142 143 $el.trigger( 'lazy' + event, [ $el ] ); 144 145 // queue next check as images may be resized after loading of actual file 146 queueCheckLazyElements(); 147 } 148 149 /** 150 * Trigger onload/onerror handler 151 * 152 * @param {Event} e 153 */ 154 function triggerLoadOrError( e ) { 155 triggerEvent( e.type, $( e.currentTarget ).off( loadError, triggerLoadOrError ) ); 156 } 157 158 /** 159 * Load visible elements 160 * 161 * @param {bool} [force] loading of all elements 162 */ 163 function checkLazyElements( force ) {
164 var viewportTop, viewportHeight, viewportWidth, i, length; 165 166 var $el, el, objData, removeNode, visible, topEdge; 167 168 var elPos, edgeX, edgeY; 169 170 var srcAttr, src; 171 172 if ( ! elements.length ) { 173 return; 174 } 175 176 force = force || options.forceLoad; 177 178 topLazy = Infinity; 179 180 viewportTop = scrollTop(); 181 viewportHeight = window.innerHeight || docElement.clientHeight; 182 viewportWidth = window.innerWidth || docElement.clientWidth; 183 184 for ( i = 0, length = elements.length; i < length; i += 1 ) { 185 $el = elements[ i ]; 186 el = $el[ 0 ]; 187 objData = $el[ lazyLoadXT ]; 188 removeNode = false; 189 visible = force || $data( el, dataLazied ) < 0; 190 191 // remove items that are not in DOM 192 if ( ! $.contains( docElement, el ) ) { 193 removeNode = true; 194 } else if ( force || ! objData.visibleOnly || el.offsetWidth || el.offsetHeight ) { 195 if ( ! visible ) { 196 elPos = el.getBoundingClientRect(); 197 edgeX = objData.edgeX; 198 edgeY = objData.edgeY; 199 200 topEdge = elPos.top + viewportTop - edgeY - viewportHeight; 201 202 visible = topEdge <= viewportTop && elPos.bottom > -edgeY && elPos.left <= viewportWidth + edgeX && elPos.right > -edgeX; 203 } 204 205 if ( visible ) { 206 $el.on( loadError, triggerLoadOrError ); 207 208 triggerEvent( 'show', $el ); 209 210 srcAttr = objData.srcAttr; 211 src = $isFunction( srcAttr ) ? srcAttr( $el ) : el.getAttribute( srcAttr ); 212 213 if ( src ) { 214 el.src = src; 215 } 216 217 removeNode = true; 218 } else if ( topEdge < topLazy ) { 219 topLazy = topEdge; 220 } 221 } 222 223 if ( removeNode ) { 224 $data( el, dataLazied, 0 ); 225 elements.splice( i, 1 ); 226 i = i - 1; 227 length = length - 1; 228 } 229 } 230 231 if ( ! length ) { 232 triggerEvent( 'complete', $( docElement ) ); 233 } 234 } 235 236 /** 237 * Add new elements to lazy-load list: 238 * $(elements).lazyLoadXT() or $(window).lazyLoadXT() 239 * 240 * @param {Object} [overrides] override global options 241 */ 242 $.fn[ lazyLoadXT ] = function( overrides ) { 243 var blankImage; 244 var checkDuplicates; 245 var scrollContainer; 246 var forceShow; 247 var elementOptionsOverrides = {}; 248 249 overrides = overrides || {}; 250 251 blankImage = getOrDef( overrides, 'blankImage' ); 252 checkDuplicates = getOrDef( overrides, 'checkDuplicates' ); 253 scrollContainer = getOrDef( overrides, 'scrollContainer' ); 254 forceShow = getOrDef( overrides, 'show' ); 255 256 // empty overrides.scrollContainer is supported by both jQuery and Zepto 257 $( scrollContainer ).on( 'scroll', queueCheckLazyElements ); 258 259 Object.keys( elementOptions ).forEach( function( prop ) { 260 elementOptionsOverrides[ prop ] = getOrDef( overrides, prop ); 261 } ); 262 263 return this.each( function( index, el ) { 264 var duplicate; 265 var $el; 266 if ( el === window ) { 267 $( options.selector ).lazyLoadXT( overrides ); 268 } else { 269 duplicate = checkDuplicates && $data( el, dataLazied ); 270 $el = $( el ).data( dataLazied, forceShow ? -1 : 1 ); 271 272 // prevent duplicates 273 if ( duplicate ) { 274 queueCheckLazyElements(); 275 return; 276 } 277 278 if ( blankImage && el.tagName === 'IMG' && ! el.src ) { 279 el.src = blankImage; 280 } 281 282 // clone elementOptionsOverrides object 283 $el[ lazyLoadXT ] = $extend( {}, elementOptionsOverrides ); 284 285 triggerEvent( 'init', $el ); 286 287 elements.push( $el ); 288 queueCheckLazyElements(); 289 } 290 } ); 291 }; 292 293 /** 294 * Initialize list of hidden elements 295 */ 296 function initLazyElements() { 297 $window.lazyLoadXT(); 298 } 299 300 /** 301 * Loading of all elements 302 */ 303 function forceLoadAll() { 304 checkLazyElements( true ); 305 } 306 307 /** 308 * Initialization 309 */ 310 // document ready 311 $( function() { 312 triggerEvent( 'start', $window ); 313 314 $window.on( options.updateEvent, queueCheckLazyElements ).on( options.forceEvent, forceLoadAll ); 315 316 $( document ).on( options.updateEvent, queueCheckLazyElements ); 317 318 if ( options.autoInit ) { 319 $window.on( options.loadEvent, initLazyElements ); 320 initLazyElements(); // standard initialization 321 } 322 } ); 323}( window.jQuery || window.Zepto || window.$, window, document ) ); 324 325( function( $ ) { 326 'use strict'; 327 328 var options = $.lazyLoadXT; 329 330 options.selector += ',video,iframe[data-src]';
331 options.videoPoster = 'data-poster'; 332 333 $( document ).on( 'lazyshow', 'video', function( e, $el ) { 334 var srcAttr = $el.lazyLoadXT.srcAttr, 335 isFuncSrcAttr = typeof srcAttr === 'function', 336 changed = false; 337 338 $el.attr( 'poster', $el.attr( options.videoPoster ) ); 339 $el.children( 'source,track' ).each( function( index, el ) { 340 var $child = $( el ), 341 src = isFuncSrcAttr ? srcAttr( $child ) : $child.attr( srcAttr ); 342 if ( src ) { 343 $child.attr( 'src', src ); 344 changed = true; 345 } 346 } ); 347 348 // reload video 349 if ( changed ) { 350 this.load(); 351 } 352 } ); 353}( window.jQuery || window.Zepto || window.$ ) );
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.