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