123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317 |
- /*!
- * author:jieyou
- * see https://github.com/jieyou/lazyload
- * part of the code fork from tuupola's https://github.com/tuupola/jquery_lazyload
- */
- ;(function(factory){
- if(typeof define === 'function' && define.amd){ // AMD
- // you may need to change `define([------>'jquery'<------], factory)`
- // if you use zepto, change it rely name, such as `define(['zepto'], factory)`
- // if your jquery|zepto lib is in other path, change it such as `define(['lib\jquery.min'], factory)`
- define(['jquery'], factory)
- }else{ // Global
- factory(window.jQuery || window.Zepto)
- }
- })(function($,undefined){
- var w = window,
- $window = $(w),
- defaultOptions = {
- threshold : 0,
- failure_limit : 0,
- event : 'scroll',
- effect : 'show',
- effect_params : null,
- container : w,
- data_attribute : 'original',
- data_srcset_attribute : 'original-srcset',
- skip_invisible : true,
- appear : emptyFn,
- load : emptyFn,
- vertical_only : false,
- minimum_interval : 300,
- use_minimum_interval_in_ios : false,
- url_rewriter_fn : emptyFn,
- no_fake_img_loader : false,
- placeholder_data_img : 'data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAYAAAAfFcSJAAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8YQUAAAAJcEhZcwAADsQAAA7EAZUrDhsAAAANSURBVBhXYzh8+PB/AAffA0nNPuCLAAAAAElFTkSuQmCC',
- // for IE6\7 that does not support data image
- placeholder_real_img : 'http://ditu.baidu.cn/yyfm/lazyload/0.0.1/img/placeholder.png'
- // todo : 将某些属性用global来配置,而不是每次在$(selector).lazyload({})内配置
- },
- isIOS = (/(?:iphone|ipod|ipad).*os/gi).test(navigator.appVersion),
- isIOS5 = isIOS && (/(?:iphone|ipod|ipad).*os 5/gi).test(navigator.appVersion),
- type // function
- function emptyFn(){}
- type = (function(){
- var object_prototype_toString = Object.prototype.toString
- return function(obj){
- // todo: compare the speeds of replace string twice or replace a regExp
- return object_prototype_toString.call(obj).replace('[object ','').replace(']','')
- }
- })()
- function belowthefold($element, options){
- var fold
- if(options._$container == $window){
- fold = ('innerHeight' in w ? w.innerHeight : $window.height()) + $window.scrollTop()
- }else{
- fold = options._$container.offset().top + options._$container.height()
- }
- return fold <= $element.offset().top - options.threshold
- }
- function rightoffold($element, options){
- var fold
- if(options._$container == $window){
- // Zepto do not support `$window.scrollLeft()` yet.
- fold = $window.width() + ($.fn.scrollLeft?$window.scrollLeft():w.pageXOffset)
- }else{
- fold = options._$container.offset().left + options._$container.width()
- }
- return fold <= $element.offset().left - options.threshold
- }
- function abovethetop($element, options){
- var fold
- if(options._$container == $window){
- fold = $window.scrollTop()
- }else{
- fold = options._$container.offset().top
- }
- // console.log('abovethetop fold '+ fold)
- // console.log('abovethetop $element.height() '+ $element.height())
- return fold >= $element.offset().top + options.threshold + $element.height()
- }
- function leftofbegin($element, options){
- var fold
- if(options._$container == $window){
- // Zepto do not support `$window.scrollLeft()` yet.
- fold = $.fn.scrollLeft?$window.scrollLeft():w.pageXOffset
- }else{
- fold = options._$container.offset().left
- }
- return fold >= $element.offset().left + options.threshold + $element.width()
- }
- function checkAppear($elements, options){
- var counter = 0
- $elements.each(function(i,e){
- var $element = $elements.eq(i)
- if(options.skip_invisible &&
- // Support zepto
- !($element.width() || $element.height()) && $element.css("display") !== "none"){
- return
- }
- function appear(){
- $element.trigger('_lazyload_appear')
- // if we found an image we'll load, reset the counter
- counter = 0
- }
- // If vertical_only is set to true, only check the vertical to decide appear or not
- // In most situations, page can only scroll vertically, set vertical_only to true will improve performance
- if(options.vertical_only){
- if(abovethetop($element, options)){
- // Nothing.
- }else if(!belowthefold($element, options)){
- appear()
- }else{
- if(++counter > options.failure_limit){
- return false
- }
- }
- }else{
- if(abovethetop($element, options) || leftofbegin($element, options)){
- // Nothing.
- }else if(!belowthefold($element, options) && !rightoffold($element, options)){
- appear()
- }else{
- if(++counter > options.failure_limit){
- return false
- }
- }
- }
- })
- }
- // Remove image from array so it is not looped next time.
- function getUnloadElements($elements){
- return $elements.filter(function(i,e){
- return !$elements.eq(i)._lazyload_loadStarted
- })
- }
- if(!$.fn.hasOwnProperty('lazyload')){
- $.fn.lazyload = function(options){
- var $elements = this,
- isScrollEvent,
- isScrollTypeEvent,
- scrollTimer = null,
- hasMinimumInterval
- if(!$.isPlainObject(options)){
- options = {}
- }
- $.each(defaultOptions,function(k,v){
- if($.inArray(k,['threshold','failure_limit','minimum_interval']) != -1){ // these params can be a string
- if(type(options[k]) == 'String'){
- options[k] = parseInt(options[k],10)
- }else{
- options[k] = v
- }
- }else if(k == 'container'){ // options.container can be a seletor string \ dom \ jQuery object
- if(options.hasOwnProperty(k)){
- if(options[k] == w || options[k] == document){
- options._$container = $window
- }else{
- options._$container = $(options[k])
- }
- }else{
- options._$container = $window
- }
- delete options.container
- }else if(defaultOptions.hasOwnProperty(k) && (!options.hasOwnProperty(k) || (type(options[k]) != type(defaultOptions[k])))){
- options[k] = v
- }
- })
- isScrollEvent = options.event == 'scroll'
- // isScrollTypeEvent. cantains custom scrollEvent . Such as 'scrollstart' & 'scrollstop'
- isScrollTypeEvent = isScrollEvent || options.event == 'scrollstart' || options.event == 'scrollstop'
- $elements.each(function(i,e){
- var element = this,
- $element = $elements.eq(i),
- placeholderSrc = $element.attr('src'),
- originalSrcInAttr = $element.attr('data-'+options.data_attribute), // `data-original` attribute value
- originalSrc = options.url_rewriter_fn == emptyFn?
- originalSrcInAttr:
- options.url_rewriter_fn.call(element,$element,originalSrcInAttr),
- originalSrcset = $element.attr('data-'+options.data_srcset_attribute),
- isImg = $element.is('img')
- if($element._lazyload_loadStarted == true || placeholderSrc == originalSrc){
- $element._lazyload_loadStarted = true
- $elements = getUnloadElements($elements)
- return
- }
- $element._lazyload_loadStarted = false
- // If element is an img and no src attribute given, use placeholder.
- if(isImg && !placeholderSrc){
- // For browsers that do not support data image.
- $element.one('error',function(){ // `on` -> `one` : IE6 triggered twice error event sometimes
- $element.attr('src',options.placeholder_real_img)
- }).attr('src',options.placeholder_data_img)
- }
-
- // When appear is triggered load original image.
- $element.one('_lazyload_appear',function(){
- var effectParamsIsArray = $.isArray(options.effect_params),
- effectIsNotImmediacyShow
- function loadFunc(){
- // In most situations, the effect is immediacy show, at this time there is no need to hide element first
- // Hide this element may cause css reflow, call it as less as possible
- if(effectIsNotImmediacyShow){
- // todo: opacity:0 for fadeIn effect
- $element.hide()
- }
- if(isImg){
- // attr srcset first
- if(originalSrcset){
- $element.attr('srcset', originalSrcset)
- }
- if(originalSrc){
- $element.attr('src', originalSrc)
- }
- }else{
- $element.css('background-image','url("' + originalSrc + '")')
- }
- if(effectIsNotImmediacyShow){
- $element[options.effect].apply($element,effectParamsIsArray?options.effect_params:[])
- }
- $elements = getUnloadElements($elements)
- }
- if(!$element._lazyload_loadStarted){
- effectIsNotImmediacyShow = (options.effect != 'show' && $.fn[options.effect] && (!options.effect_params || (effectParamsIsArray && options.effect_params.length == 0)))
- if(options.appear != emptyFn){
- options.appear.call(element, $elements.length, options)
- }
- $element._lazyload_loadStarted = true
- if(options.no_fake_img_loader || originalSrcset){
- if(options.load != emptyFn){
- $element.one('load',function(){
- options.load.call(element, $elements.length, options)
- })
- }
- loadFunc()
- }else{
- $('<img />').one('load', function(){ // `on` -> `one` : IE6 triggered twice load event sometimes
- loadFunc()
- if(options.load != emptyFn){
- options.load.call(element, $elements.length, options)
- }
- }).attr('src',originalSrc)
- }
- }
- })
- // When wanted event is triggered load original image
- // by triggering appear.
- if (!isScrollTypeEvent){
- $element.on(options.event, function(){
- if (!$element._lazyload_loadStarted){
- $element.trigger('_lazyload_appear')
- }
- })
- }
- })
- // Fire one scroll event per scroll. Not one scroll event per image.
- if(isScrollTypeEvent){
- hasMinimumInterval = options.minimum_interval != 0
- options._$container.on(options.event, function(){
- // desktop and Android device triggered many times `scroll` event in once user scrolling
- if(isScrollEvent && hasMinimumInterval && (!isIOS || options.use_minimum_interval_in_ios)){
- if(!scrollTimer){
- scrollTimer = setTimeout(function(){
- checkAppear($elements, options)
- scrollTimer = null
- },options.minimum_interval) // only check once in 300ms
- }
- }else{
- return checkAppear($elements, options)
- }
- })
- }
- // Check if something appears when window is resized.
- // Force initial check if images should appear when window onload.
- $window.on('resize load', function(){
- checkAppear($elements, options)
- })
-
- // With IOS5 force loading images when navigating with back button.
- // Non optimal workaround.
- if(isIOS5){
- $window.on('pageshow', function(e){
- if(e.originalEvent && e.originalEvent.persisted){
- $elements.trigger('_lazyload_appear')
- }
- })
- }
- // Force initial check if images should appear.
- $(function(){
- checkAppear($elements, options)
- })
-
- return this
- }
- }
- })
|