Authored by 姜枫

jquery-lazyload/1.1.5

  1 +{
  2 + "curly": true,
  3 + "eqeqeq": true,
  4 + "eqnull": true,
  5 + "immed": true,
  6 + "noarg": true,
  7 + "quotmark": "double",
  8 + "trailing": true,
  9 + "undef": true,
  10 + "unused": true,
  11 +
  12 + "node": true,
  13 + "jquery": true,
  14 + "browser": true
  15 +}
  1 +# Contributing to Lazy Load
  2 +
  3 +## Only one feature or change per pull request
  4 +
  5 +Make pull requests only one feature or change at the time. For example you have fixed a bug. You also have optimized some code. Optimization is not related to a bug. These should be submitted as separate pull requests. This way I can easily choose what to include. It is also easier to understand the code changes. Commit messages should be descriptive and full sentences.
  6 +
  7 +Do not commit minified versions. Do not touch the version number. Make the pull requests against [1.9.x branch](https://github.com/tuupola/jquery_lazyload/commits/1.9.x).
  8 +
  9 +## Write meaningful commit messages
  10 +
  11 +Proper commit message is full sentence. It starts with capital letter but does not end with period. Headlines do not end with period. The GitHub default `Update filename.js` is not enough. When needed include also longer explanation what the commit does.
  12 +
  13 +```
  14 +Capitalized, short (50 chars or less) summary
  15 +
  16 +More detailed explanatory text, if necessary. Wrap it to about 72
  17 +characters or so. In some contexts, the first line is treated as the
  18 +subject of an email and the rest of the text as the body. The blank
  19 +line separating the summary from the body is critical (unless you omit
  20 +the body entirely); tools like rebase can get confused if you run the
  21 +two together.
  22 +```
  23 +
  24 +When in doubt see Tim Pope's blogpost [A Note About Git Commit Messages](http://tbaggery.com/2008/04/19/a-note-about-git-commit-messages.html)
  25 +
  26 +## Follow the existing coding standards
  27 +
  28 +When contributing to open source project it is polite to follow the original authors coding standars. They might be different than yours. It is not a holy war. Just follow then original.
  29 +
  30 +```javascript
  31 +var snake_case = "something";
  32 +
  33 +function camelCase(options) {
  34 +}
  35 +
  36 +if (true !== false) {
  37 + console.log("here be dragons");
  38 +}
  39 +```
  1 +module.exports = function(grunt) {
  2 + "use strict";
  3 +
  4 + grunt.initConfig({
  5 + pkg: grunt.file.readJSON("package.json"),
  6 + uglify : {
  7 + options: {
  8 + banner: "/*! Lazy Load <%= pkg.version %> - MIT license - Copyright 2010-2013 Mika Tuupola */\n"
  9 + },
  10 + target: {
  11 + files: {
  12 + "jquery.lazyload.min.js" : "jquery.lazyload.js",
  13 + "jquery.scrollstop.min.js" : "jquery.scrollstop.js"
  14 + }
  15 + }
  16 + },
  17 + watch: {
  18 + files: ["*.js", "!*.min.js" ,"test/spec/*Spec.js"],
  19 + tasks: ["test"],
  20 + },
  21 + jshint: {
  22 + files: ["*.js", "!*.min.js" ,"test/spec/*Spec.js"],
  23 + options: {
  24 + jshintrc: ".jshintrc"
  25 + }
  26 + },
  27 + jasmine: {
  28 + src: ["jquery.lazyload.js"],
  29 + options: {
  30 + helpers: "test/spec/*Helper.js",
  31 + specs: "test/spec/*Spec.js",
  32 + vendor: ["test/vendor/jquery-1.9.0.js", "test/vendor/jasmine-jquery.js"]
  33 + }
  34 + }
  35 + });
  36 +
  37 + grunt.loadNpmTasks("grunt-contrib-uglify");
  38 + grunt.loadNpmTasks("grunt-contrib-jshint");
  39 + grunt.loadNpmTasks("grunt-contrib-jasmine");
  40 + grunt.loadNpmTasks("grunt-contrib-watch");
  41 +
  42 + //grunt.registerTask("test", ["jshint", "jasmine"]);
  43 + grunt.registerTask("test", ["jshint"]);
  44 + grunt.registerTask("default", ["test", "uglify"]);
  45 +
  46 +};
  1 +# History
  2 +
  3 +---
  4 +
  5 +## 1.1.3
  6 +
  7 +增加图片加载失败时的图片显示
  8 +
  9 +USAGE:
  10 +
  11 + lazyLoad({
  12 + try_again_css: 'xx'
  13 + });
  14 +
  15 +如果提供了try_again_css,则使用自定义样式,否则使用默认样式
  1 +# yoho.lazyload [![spm version](http://spm.yoho.cn/badge/yoho.lazyload)](http://spm.yoho.cn/package/yoho.lazyload)
  2 +
  3 +---
  4 +
  5 +yoho lazyload
  6 +
  7 +## Install
  8 +
  9 +```
  10 +$ spm install yoho.lazyload --save
  11 +```
  12 +
  13 +## Usage
  14 +lazyload对原代码做了一层封装,默认配置参数:
  15 +
  16 + {
  17 + effect : 'fadeIn',
  18 + effect_speed: 10,
  19 + placeholder: 'data:image/gif;base64,R0lGODlhAQABAJEAAAAAAP///93d3f///yH5BAEAAAMALAAAAAABAAEAAAICVAEAOw==',
  20 + skip_invisible: false
  21 + }
  22 +
  23 +```js
  24 +var Lazyload = require('yoho.lazyload');
  25 +// use Lazyload
  26 +//接受2个参数,为指定的$imgs添加lazyload并可配置需要的参数(需要的时候覆盖默认参数项);若图片参数不传则为$('img.lazy')添加lazyload效果
  27 +lazyLoad([$imgs, configs]);
  28 +
  29 +//如果你想用原来的方法加载lazyload
  30 +require('yoho.lazylaod/lib/jquery.lazyload');
  31 +```
  32 +//点击重新下载图片时,阻止默认行为,防止页面发生跳转。add by liangzhifeng at 2015.11.4
  33 +
  34 +// 超时时间改为5秒。modify by liangzhifeng at 2015.11.6
  35 +
  36 +// 超时图片要加上原来的样式。modify by liangzhifeng at 2015.12.15
  1 +{
  2 + "name": "jquery_lazyload",
  3 + "version": "1.9.3",
  4 + "homepage": "http://www.appelsiini.net/projects/lazyload",
  5 + "authors": [
  6 + "Mika Tuupola <tuupola@appelsiini.net>"
  7 + ],
  8 + "description": "jQuery plugin for lazy loading images",
  9 + "main": [
  10 + "jquery.lazyload.js",
  11 + "jquery.scrollstop.js"
  12 + ],
  13 + "license": "MIT",
  14 + "ignore": [
  15 + "**/.*",
  16 + "**/*.min.js",
  17 + "**/*.html",
  18 + "**/*.textile",
  19 + "Gruntfile.js",
  20 + "lazyload.jquery.json",
  21 + "package.json",
  22 + "node_modules",
  23 + "bower_components",
  24 + "test",
  25 + "img"
  26 + ]
  27 +}
  1 +/**
  2 + * lazyload
  3 + * @author: xuqi(qi.xu@yoho.cn)
  4 + * @date: 2015/6/25
  5 + */
  6 +var $ = require('jquery');
  7 +require('./lib/jquery.lazyload.js');
  8 +
  9 +/**
  10 + * 为指定imgs添加lazyload效果,未指定imgs则为所有img.lazy添加lazyload效果
  11 + * @params imgs lazyload的图片
  12 + * @params options lazyload效果选项
  13 + */
  14 +module.exports = function(imgs, options) {
  15 + var setting = {
  16 + effect : 'fadeIn',
  17 + effect_speed: 10,
  18 + placeholder: 'data:image/gif;base64,R0lGODlhAQABAJEAAAAAAP///93d3f///yH5BAEAAAMALAAAAAABAAEAAAICVAEAOw==',
  19 + skip_invisible: false
  20 + }, $imgs, argsLength = arguments.length;
  21 +
  22 + //分解参数
  23 + (function seperateOptions() {
  24 + switch (argsLength) {
  25 + case 0:
  26 + $imgs = $('img.lazy');
  27 + break;
  28 + case 1:
  29 + if (imgs instanceof $) {
  30 + //img
  31 + $imgs = imgs;
  32 + } else {
  33 + $imgs = $('img.lazy');
  34 + $.extend(setting, imgs);
  35 + }
  36 + break;
  37 + case 2:
  38 + $imgs = imgs;
  39 + setting = $.extend(setting, options);
  40 + break;
  41 + }
  42 + }());
  43 +
  44 + $imgs.lazyload(setting);
  45 +};
  1 +(function($, window, document, undefined) {
  2 + var $window = $(window);
  3 + var webp = false;
  4 +
  5 + function check_webp_feature(feature, callback) {
  6 + var kTestImages = {
  7 + lossy: "UklGRiIAAABXRUJQVlA4IBYAAAAwAQCdASoBAAEADsD+JaQAA3AAAAAA",
  8 + lossless: "UklGRhoAAABXRUJQVlA4TA0AAAAvAAAAEAcQERGIiP4HAA==",
  9 + alpha: "UklGRkoAAABXRUJQVlA4WAoAAAAQAAAAAAAAAAAAQUxQSAwAAAARBxAR/Q9ERP8DAABWUDggGAAAABQBAJ0BKgEAAQAAAP4AAA3AAP7mtQAAAA==",
  10 + animation: "UklGRlIAAABXRUJQVlA4WAoAAAASAAAAAAAAAAAAQU5JTQYAAAD/////AABBTk1GJgAAAAAAAAAAAAAAAAAAAGQAAABWUDhMDQAAAC8AAAAQBxAREYiI/gcA"
  11 + };
  12 + var img = new Image();
  13 + img.onload = function () {
  14 + var result = (img.width > 0) && (img.height > 0);
  15 + callback(feature, result);
  16 + };
  17 + img.onerror = function () {
  18 + callback(feature, false);
  19 + };
  20 + img.src = "data:image/webp;base64," + kTestImages[feature];
  21 + }
  22 +
  23 + setTimeout(function(){
  24 + check_webp_feature('lossy', function(feature, result) {
  25 + webp = result;
  26 + });
  27 + }, 50);
  28 +
  29 + function img_url_format(imgUrl, opts) {
  30 + if (!imgUrl) {
  31 + return imgUrl;
  32 + }
  33 + var splits = imgUrl.split('?');
  34 + var url = splits[0];
  35 + var query = splits[1] || '';
  36 +
  37 + if (query.indexOf('imageView2') === 0) {
  38 + if (query.indexOf('/q/') < 0 && !!opts.q) {
  39 + query += '/q/' + opts.q;
  40 + }
  41 + if (query.indexOf('/format/') < 0 && !!opts.format) {
  42 + query += '/format/' + opts.format;
  43 + }
  44 + return imgUrl + '?' + query;
  45 + } else if (query.indexOf('imageMogr2') === 0) {
  46 + if (query.indexOf('/quality/') < 0 && !!opts.q) {
  47 + query += '/quality/' + opts.q;
  48 + }
  49 + if (query.indexOf('/format/') < 0 && !!opts.format) {
  50 + query += '/format/' + opts.format;
  51 + }
  52 + return imgUrl + '?' + query;
  53 + } else if (query === '') {
  54 + var imageUrl = 'imageView2/2/interlace/1/q/' + opts.q;
  55 +
  56 + if (opts.format) {
  57 + imageUrl += '/format/' + opts.format;
  58 + }
  59 + return url + '?' +imageUrl;
  60 + } else {
  61 + return imgUrl;
  62 + }
  63 + }
  64 +
  65 + $.fn.lazyload = function(options) {
  66 + var elements = this;
  67 + var $container;
  68 + var settings = {
  69 + threshold : 0,
  70 + failure_limit : 0,
  71 + event : "scroll",
  72 + effect : "show",
  73 + container : window,
  74 + data_attribute : "original",
  75 + skip_invisible : true,
  76 + appear : null,
  77 + load : null,
  78 + yasPath: '/web/',
  79 + yasImgDomain: 'http://analytics.yhurl.com/yas.gif',
  80 + placeholder : "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAYAAAAfFcSJAAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8YQUAAAAJcEhZcwAADsQAAA7EAZUrDhsAAAANSURBVBhXYzh8+PB/AAffA0nNPuCLAAAAAElFTkSuQmCC",
  81 + try_again_css: null
  82 +
  83 + };
  84 +
  85 + function update() {
  86 + var counter = 0;
  87 +
  88 + elements.each(function() {
  89 + var $this = $(this);
  90 + if (settings.skip_invisible && !$this.is(":visible")) {
  91 + return;
  92 + }
  93 + if ($.abovethetop(this, settings) ||
  94 + $.leftofbegin(this, settings)) {
  95 + /* Nothing. */
  96 + } else if (!$.belowthefold(this, settings) &&
  97 + !$.rightoffold(this, settings)) {
  98 + $this.trigger("appear");
  99 + /* if we found an image we'll load, reset the counter */
  100 + counter = 0;
  101 + } else {
  102 + if (++counter > settings.failure_limit) {
  103 + return false;
  104 + }
  105 + }
  106 + });
  107 +
  108 + };
  109 +
  110 + //add by jp, 发送图片方式跨域发送消息
  111 + function crossSend(param, callback) {
  112 + var image = new Image(1, 1);
  113 + image.src = settings.yasImgDomain + settings.yasPath + '?' + param;
  114 + image.onload = function() {
  115 + image.onload = null;
  116 + if (callback) {
  117 + callback();
  118 + }
  119 + };
  120 + };
  121 +
  122 + if(options) {
  123 + /* Maintain BC for a couple of versions. */
  124 + if (undefined !== options.failurelimit) {
  125 + options.failure_limit = options.failurelimit;
  126 + delete options.failurelimit;
  127 + }
  128 + if (undefined !== options.effectspeed) {
  129 + options.effect_speed = options.effectspeed;
  130 + delete options.effectspeed;
  131 + }
  132 +
  133 + $.extend(settings, options);
  134 + }
  135 +
  136 + /* Cache container as jQuery as object. */
  137 + $container = (settings.container === undefined ||
  138 + settings.container === window) ? $window : $(settings.container);
  139 +
  140 + /* Fire one scroll event per scroll. Not one scroll event per image. */
  141 + if (0 === settings.event.indexOf("scroll")) {
  142 + $container.bind(settings.event, function() {
  143 + return update();
  144 + });
  145 + }
  146 +
  147 + this.each(function() {
  148 + var self = this;
  149 + var $self = $(self);
  150 + var original = $self.attr("data-" + settings.data_attribute);
  151 +
  152 + original = img_url_format(original, {q: 75, format: (webp ? 'webp': '')});
  153 + setTimeout(function(){
  154 + var preImg = new Image();
  155 + preImg.src = original;
  156 + }, 100);
  157 +
  158 + self.loaded = false;
  159 +
  160 + /* If no src attribute given use data:uri. */
  161 + if ($self.attr("src") === undefined || $self.attr("src") === false || $self.attr("src") === '') {
  162 + if ($self.is("img")) {
  163 + $self.attr("src", settings.placeholder);
  164 + }
  165 + }
  166 +
  167 + /* When appear is triggered load original image. */
  168 + $self.one("appear", function() {
  169 +
  170 + //add by jp
  171 + if($self.timerid) clearTimeout($self.timerid);
  172 + //console.log("img appear, this.loaded:" + this.loaded + ", id:" + $self.attr("id"));
  173 +
  174 + if (!this.loaded) {
  175 + if (settings.appear) {
  176 + var elements_left = elements.length;
  177 + settings.appear.call(self, elements_left, settings);
  178 + }
  179 + $("<img />")
  180 + //add by jp
  181 + .bind("error abort", function(){
  182 + $self.attr("src",settings.placeholder);
  183 + loadfail({info:'error'});
  184 + })
  185 + .bind("load", function() {
  186 +
  187 + //add by jp, 加载超时后,不再进行加载,通过传统方式设置src,边下载边渲染
  188 + if($self.loadtimeout){
  189 + return;
  190 + }
  191 +
  192 + //add by jp, 清理检测图片下载超时定时器
  193 + clearTimeout($self.timerid);
  194 +
  195 + //add by jp, 上报图片加载成功事件
  196 + if( $self.attr("pfmrpt") ){
  197 + //crossImgSend('success');
  198 + }
  199 +
  200 + $self.hide();
  201 + if ($self.is("img")) {
  202 + $self.attr("src", original);
  203 + } else {
  204 + $self.css("background-image", "url('" + original + "')");
  205 + }
  206 + $self[settings.effect](settings.effect_speed);
  207 +
  208 + self.loaded = true;
  209 +
  210 + /* Remove image from array so it is not looped next time. */
  211 + var temp = $.grep(elements, function(element) {
  212 + return !element.loaded;
  213 + });
  214 + elements = $(temp);
  215 +
  216 + if (settings.load) {
  217 + var elements_left = elements.length;
  218 + settings.load.call(self, elements_left, settings);
  219 + }
  220 + })
  221 + .attr("src", $self.attr("data-" + settings.data_attribute));
  222 +
  223 + //add by jp , 临时保存图片url
  224 + $self.src = $self.attr("data-" + settings.data_attribute);
  225 +
  226 + //add by jp , 上报图片开始加载事件
  227 + if( $self.attr("pfmrpt") && _yas && _yas.add){
  228 + //crossImgSend(,'start');
  229 + }
  230 +
  231 + //add by jp, 图片加载失败或超时的处理
  232 + var loadtimeout = function(options){
  233 +
  234 + //记录标识图片加载超时
  235 + $self.loadtimeout = true;
  236 +
  237 + //上报图片加载超时事件
  238 + if( $self.attr("pfmrpt") && _yas && _yas.add){
  239 + options.info ; //error or timeout
  240 + //crossImgSend(settings.yasImgDomain,settings.yasPath,'fail');
  241 + }
  242 +
  243 + //清除图片src取值,便于图片边下载边渲染
  244 + $self.attr("src","");
  245 +
  246 + setTimeout(function(){
  247 + $self.attr("src",$self.src);
  248 + },50);
  249 +
  250 + };
  251 +
  252 + //add by jp, 图片加载失败或超时的处理
  253 + var loadfail = function(options){
  254 +
  255 + //记录标识图片加载超时
  256 + $self.loadtimeout = true;
  257 +
  258 + //上报图片加载失败事件
  259 + if( $self.attr("pfmrpt") && _yas && _yas.add){
  260 + options.info ; //error or timeout
  261 + //crossImgSend(settings.yasImgDomain,settings.yasPath,'fail');
  262 + }
  263 +
  264 + var width = $self.width();
  265 + var height = $self.height();
  266 +
  267 + var $tryagain = $("<div class="+settings.try_again_css+" style='background-image:url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAYAAAAfFcSJAAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8YQUAAAAJcEhZcwAADsQAAA7EAZUrDhsAAAANSURBVBhXYzh8+PB/AAffA0nNPuCLAAAAAElFTkSuQmCC) ;text-align: center;position:relative;width:"+width+"px;height:"+height+"px; line-height:"+height+"px'>图片打开失败,点击重新加载</div>");
  268 + // $tryagain.css("background-image",settings.placeholder);
  269 + $self.replaceWith($tryagain);
  270 + $tryagain.bind("click", function(e){
  271 + e.preventDefault();
  272 + $tryagain.replaceWith($self);
  273 + //清除图片src取值,便于图片边下载边渲染
  274 + $self.attr("src","");
  275 + setTimeout(function(){
  276 + $self.attr("src",$self.src);
  277 + },50);
  278 + });
  279 + };
  280 +
  281 +
  282 + //图片下载超时检测
  283 + $self.timerid = setTimeout(loadtimeout,5000);
  284 +
  285 +
  286 + }
  287 + });
  288 +
  289 + /* When wanted event is triggered load original image */
  290 + /* by triggering appear. */
  291 + if (0 !== settings.event.indexOf("scroll")) {
  292 + $self.bind(settings.event, function() {
  293 + if (!self.loaded) {
  294 + $self.trigger("appear");
  295 + }
  296 + });
  297 + }
  298 + });
  299 +
  300 + /* Check if something appears when window is resized. */
  301 + $window.bind("resize", function() {
  302 + update();
  303 + });
  304 +
  305 + /* With IOS5 force loading images when navigating with back button. */
  306 + /* Non optimal workaround. */
  307 + if ((/(?:iphone|ipod|ipad).*os 5/gi).test(navigator.appVersion)) {
  308 + $window.bind("pageshow", function(event) {
  309 + if (event.originalEvent && event.originalEvent.persisted) {
  310 + elements.each(function() {
  311 + $(this).trigger("appear");
  312 + });
  313 + }
  314 + });
  315 + }
  316 +
  317 + /* Force initial check if images should appear. */
  318 + $(document).ready(function() {
  319 + update();
  320 + });
  321 +
  322 + return this;
  323 + };
  324 +
  325 +
  326 +
  327 + /* Convenience methods in jQuery namespace. */
  328 + /* Use as $.belowthefold(element, {threshold : 100, container : window}) */
  329 +
  330 + $.belowthefold = function(element, settings) {
  331 + var fold;
  332 +
  333 + if (settings.container === undefined || settings.container === window) {
  334 + fold = (window.innerHeight ? window.innerHeight : $window.height()) + $window.scrollTop();
  335 + } else {
  336 + fold = $(settings.container).offset().top + $(settings.container).height();
  337 + }
  338 +
  339 + return fold <= $(element).offset().top - settings.threshold;
  340 + };
  341 +
  342 + $.rightoffold = function(element, settings) {
  343 + var fold;
  344 +
  345 + if (settings.container === undefined || settings.container === window) {
  346 + fold = $window.width() + $window.scrollLeft();
  347 + } else {
  348 + fold = $(settings.container).offset().left + $(settings.container).width();
  349 + }
  350 +
  351 + return fold <= $(element).offset().left - settings.threshold;
  352 + };
  353 +
  354 + $.abovethetop = function(element, settings) {
  355 + var fold;
  356 +
  357 + if (settings.container === undefined || settings.container === window) {
  358 + fold = $window.scrollTop();
  359 + } else {
  360 + fold = $(settings.container).offset().top;
  361 + }
  362 +
  363 + return fold >= $(element).offset().top + settings.threshold + $(element).height();
  364 + };
  365 +
  366 + $.leftofbegin = function(element, settings) {
  367 + var fold;
  368 +
  369 + if (settings.container === undefined || settings.container === window) {
  370 + fold = $window.scrollLeft();
  371 + } else {
  372 + fold = $(settings.container).offset().left;
  373 + }
  374 +
  375 + return fold >= $(element).offset().left + settings.threshold + $(element).width();
  376 + };
  377 +
  378 + $.inviewport = function(element, settings) {
  379 + return !$.rightoffold(element, settings) && !$.leftofbegin(element, settings) &&
  380 + !$.belowthefold(element, settings) && !$.abovethetop(element, settings);
  381 + };
  382 +
  383 +})($, window, document);
  1 +{
  2 + "name": "yoho.lazyload",
  3 + "version": "1.1.5",
  4 + "engines": {
  5 + "node": ">= 0.8.0"
  6 + },
  7 + "description": "yoho lazyload, encased with version 1.9.3 of jquery.lazyload with jquery 2.1.4",
  8 + "author": "Mika Tuupola <tuupola@appelsiini.net>",
  9 + "repository": {
  10 + "type": "git",
  11 + "url": "git@github.com:YOHO-LAB/jquery_lazyload.git"
  12 + },
  13 + "licenses": "MIT",
  14 + "spm": {
  15 + "main": "lazyload.js",
  16 + "dependencies": {
  17 + "jquery": "2.1.4"
  18 + },
  19 + "devDependencies": {
  20 + "expect.js": "0.3.1"
  21 + }
  22 + },
  23 + "scripts": {
  24 + "test": "grunt test",
  25 + "test": "spm test",
  26 + "build": "spm build"
  27 + },
  28 + "devDependencies": {
  29 + "spm": "3",
  30 + "grunt": "~0.4.1",
  31 + "grunt-contrib-jshint": "~0.6.4",
  32 + "grunt-contrib-uglify": "~0.2.4",
  33 + "grunt-contrib-jasmine": "~0.5.2",
  34 + "grunt-contrib-watch": "~0.5.3"
  35 + }
  36 +}