lazyload.js 5.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180
  1. /*!
  2. * Lazy Load - JavaScript plugin for lazy loading images
  3. *
  4. * Copyright (c) 2007-2019 Mika Tuupola
  5. *
  6. * Licensed under the MIT license:
  7. * http://www.opensource.org/licenses/mit-license.php
  8. *
  9. * Project home:
  10. * https://appelsiini.net/projects/lazyload
  11. *
  12. * Version: 2.0.0-rc.2
  13. *
  14. */
  15. (function (root, factory) {
  16. if (typeof exports === "object") {
  17. module.exports = factory(root);
  18. } else if (typeof define === "function" && define.amd) {
  19. define([], factory);
  20. } else {
  21. root.LazyLoad = factory(root);
  22. }
  23. }) (typeof global !== "undefined" ? global : this.window || this.global, function (root) {
  24. "use strict";
  25. if (typeof define === "function" && define.amd){
  26. root = window;
  27. }
  28. const defaults = {
  29. src: "data-src",
  30. srcset: "data-srcset",
  31. selector: ".lazyload",
  32. root: null,
  33. rootMargin: "0px",
  34. threshold: 0
  35. };
  36. /**
  37. * Merge two or more objects. Returns a new object.
  38. * @private
  39. * @param {Boolean} deep If true, do a deep (or recursive) merge [optional]
  40. * @param {Object} objects The objects to merge together
  41. * @returns {Object} Merged values of defaults and options
  42. */
  43. const extend = function () {
  44. let extended = {};
  45. let deep = false;
  46. let i = 0;
  47. let length = arguments.length;
  48. /* Check if a deep merge */
  49. if (Object.prototype.toString.call(arguments[0]) === "[object Boolean]") {
  50. deep = arguments[0];
  51. i++;
  52. }
  53. /* Merge the object into the extended object */
  54. let merge = function (obj) {
  55. for (let prop in obj) {
  56. if (Object.prototype.hasOwnProperty.call(obj, prop)) {
  57. /* If deep merge and property is an object, merge properties */
  58. if (deep && Object.prototype.toString.call(obj[prop]) === "[object Object]") {
  59. extended[prop] = extend(true, extended[prop], obj[prop]);
  60. } else {
  61. extended[prop] = obj[prop];
  62. }
  63. }
  64. }
  65. };
  66. /* Loop through each object and conduct a merge */
  67. for (; i < length; i++) {
  68. let obj = arguments[i];
  69. merge(obj);
  70. }
  71. return extended;
  72. };
  73. function LazyLoad(images, options) {
  74. this.settings = extend(defaults, options || {});
  75. this.images = images || document.querySelectorAll(this.settings.selector);
  76. this.observer = null;
  77. this.init();
  78. }
  79. LazyLoad.prototype = {
  80. init: function() {
  81. /* Without observers load everything and bail out early. */
  82. if (!root.IntersectionObserver) {
  83. this.loadImages();
  84. return;
  85. }
  86. let self = this;
  87. let observerConfig = {
  88. root: this.settings.root,
  89. rootMargin: this.settings.rootMargin,
  90. threshold: [this.settings.threshold]
  91. };
  92. this.observer = new IntersectionObserver(function(entries) {
  93. Array.prototype.forEach.call(entries, function (entry) {
  94. if (entry.isIntersecting) {
  95. self.observer.unobserve(entry.target);
  96. let src = entry.target.getAttribute(self.settings.src);
  97. let srcset = entry.target.getAttribute(self.settings.srcset);
  98. if ("img" === entry.target.tagName.toLowerCase()) {
  99. if (src) {
  100. entry.target.src = src;
  101. }
  102. if (srcset) {
  103. entry.target.srcset = srcset;
  104. }
  105. } else {
  106. entry.target.style.backgroundImage = "url(" + src + ")";
  107. }
  108. }
  109. });
  110. }, observerConfig);
  111. Array.prototype.forEach.call(this.images, function (image) {
  112. self.observer.observe(image);
  113. });
  114. },
  115. loadAndDestroy: function () {
  116. if (!this.settings) { return; }
  117. this.loadImages();
  118. this.destroy();
  119. },
  120. loadImages: function () {
  121. if (!this.settings) { return; }
  122. let self = this;
  123. Array.prototype.forEach.call(this.images, function (image) {
  124. let src = image.getAttribute(self.settings.src);
  125. let srcset = image.getAttribute(self.settings.srcset);
  126. if ("img" === image.tagName.toLowerCase()) {
  127. if (src) {
  128. image.src = src;
  129. }
  130. if (srcset) {
  131. image.srcset = srcset;
  132. }
  133. } else {
  134. image.style.backgroundImage = "url('" + src + "')";
  135. }
  136. });
  137. },
  138. destroy: function () {
  139. if (!this.settings) { return; }
  140. this.observer.disconnect();
  141. this.settings = null;
  142. }
  143. };
  144. root.lazyload = function(images, options) {
  145. return new LazyLoad(images, options);
  146. };
  147. if (root.jQuery) {
  148. const $ = root.jQuery;
  149. $.fn.lazyload = function (options) {
  150. options = options || {};
  151. options.attribute = options.attribute || "data-src";
  152. new LazyLoad($.makeArray(this), options);
  153. return this;
  154. };
  155. }
  156. return LazyLoad;
  157. });