eisbehr jquery lazy

lazy load page elements

此腳本不應該直接安裝,它是一個供其他腳本使用的函式庫。欲使用本函式庫,請在腳本 metadata 寫上: // @require https://update.gf.qytechs.cn/scripts/34959/229001/eisbehr%20jquery%20lazy.js

  1. /*!
  2. * jQuery & Zepto Lazy - v1.7.6
  3. * http://jquery.eisbehr.de/lazy/
  4. *
  5. * Copyright 2012 - 2017, Daniel 'Eisbehr' Kern
  6. *
  7. * Dual licensed under the MIT and GPL-2.0 licenses:
  8. * http://www.opensource.org/licenses/mit-license.php
  9. * http://www.gnu.org/licenses/gpl-2.0.html
  10. *
  11. * $("img.lazy").lazy();
  12. */
  13.  
  14. ;(function(window, undefined) {
  15. "use strict";
  16.  
  17. // noinspection JSUnresolvedVariable
  18. /**
  19. * library instance - here and not in construct to be shorter in minimization
  20. * @return void
  21. */
  22. var $ = window.jQuery || window.Zepto,
  23.  
  24. /**
  25. * unique plugin instance id counter
  26. * @type {number}
  27. */
  28. lazyInstanceId = 0,
  29.  
  30. /**
  31. * helper to register window load for jQuery 3
  32. * @type {boolean}
  33. */
  34. windowLoaded = false;
  35.  
  36. /**
  37. * make lazy available to jquery - and make it a bit more case-insensitive :)
  38. * @access public
  39. * @type {function}
  40. * @param {object} settings
  41. * @return void
  42. */
  43. $.fn.Lazy = $.fn.lazy = function(settings) {
  44. return new LazyPlugin(this, settings);
  45. };
  46.  
  47. /**
  48. * helper to add plugins to lazy prototype configuration
  49. * @access public
  50. * @type {function}
  51. * @param {string|Array} names
  52. * @param {string|Array} [elements]
  53. * @param {function} loader
  54. * @return void
  55. */
  56. $.Lazy = $.lazy = function(names, elements, loader) {
  57. // make second parameter optional
  58. if( $.isFunction(elements) ) {
  59. loader = elements;
  60. elements = [];
  61. }
  62.  
  63. // exit here if parameter is not a callable function
  64. if( !$.isFunction(loader) ) {
  65. return;
  66. }
  67.  
  68. // make parameters an array of names to be sure
  69. names = $.isArray(names) ? names : [names];
  70. elements = $.isArray(elements) ? elements : [elements];
  71.  
  72. var config = LazyPlugin.prototype.config,
  73. forced = config._f || (config._f = {});
  74.  
  75. // add the loader plugin for every name
  76. for( var i = 0, l = names.length; i < l; i++ ) {
  77. if( config[names[i]] === undefined || $.isFunction(config[names[i]]) ) {
  78. config[names[i]] = loader;
  79. }
  80. }
  81.  
  82. // add forced elements loader
  83. for( var c = 0, a = elements.length; c < a; c++ ) {
  84. forced[elements[c]] = names[0];
  85. }
  86. };
  87.  
  88. /**
  89. * contains all logic and the whole element handling
  90. * is packed in a private function outside class to reduce memory usage, because it will not be created on every plugin instance
  91. * @access private
  92. * @type {function}
  93. * @param {LazyPlugin} instance
  94. * @param {object} config
  95. * @param {object|Array} items
  96. * @param {object} events
  97. * @param {string} namespace
  98. * @return void
  99. */
  100. function _executeLazy(instance, config, items, events, namespace) {
  101. /**
  102. * a helper to trigger the 'onFinishedAll' callback after all other events
  103. * @access private
  104. * @type {number}
  105. */
  106. var _awaitingAfterLoad = 0,
  107.  
  108. /**
  109. * visible content width
  110. * @access private
  111. * @type {number}
  112. */
  113. _actualWidth = -1,
  114.  
  115. /**
  116. * visible content height
  117. * @access private
  118. * @type {number}
  119. */
  120. _actualHeight = -1,
  121.  
  122. /**
  123. * determine possibly detected high pixel density
  124. * @access private
  125. * @type {boolean}
  126. */
  127. _isRetinaDisplay = false,
  128.  
  129. /**
  130. * dictionary entry for better minimization
  131. * @access private
  132. * @type {string}
  133. */
  134. _afterLoad = "afterLoad",
  135.  
  136. /**
  137. * dictionary entry for better minimization
  138. * @access private
  139. * @type {string}
  140. */
  141. _load = "load",
  142.  
  143. /**
  144. * dictionary entry for better minimization
  145. * @access private
  146. * @type {string}
  147. */
  148. _error = "error",
  149.  
  150. /**
  151. * dictionary entry for better minimization
  152. * @access private
  153. * @type {string}
  154. */
  155. _img = "img",
  156.  
  157. /**
  158. * dictionary entry for better minimization
  159. * @access private
  160. * @type {string}
  161. */
  162. _src = "src",
  163.  
  164. /**
  165. * dictionary entry for better minimization
  166. * @access private
  167. * @type {string}
  168. */
  169. _srcset = "srcset",
  170.  
  171. /**
  172. * dictionary entry for better minimization
  173. * @access private
  174. * @type {string}
  175. */
  176. _sizes = "sizes",
  177.  
  178. /**
  179. * dictionary entry for better minimization
  180. * @access private
  181. * @type {string}
  182. */
  183. _backgroundImage = "background-image";
  184.  
  185. /**
  186. * initialize plugin
  187. * bind loading to events or set delay time to load all items at once
  188. * @access private
  189. * @return void
  190. */
  191. function _initialize() {
  192. // detect actual device pixel ratio
  193. // noinspection JSUnresolvedVariable
  194. _isRetinaDisplay = window.devicePixelRatio > 1;
  195.  
  196. // prepare all initial items
  197. items = _prepareItems(items);
  198.  
  199. // if delay time is set load all items at once after delay time
  200. if( config.delay >= 0 ) {
  201. setTimeout(function() {
  202. _lazyLoadItems(true);
  203. }, config.delay);
  204. }
  205.  
  206. // if no delay is set or combine usage is active bind events
  207. if( config.delay < 0 || config.combined ) {
  208. // create unique event function
  209. events.e = _throttle(config.throttle, function(event) {
  210. // reset detected window size on resize event
  211. if( event.type === "resize" ) {
  212. _actualWidth = _actualHeight = -1;
  213. }
  214.  
  215. // execute 'lazy magic'
  216. _lazyLoadItems(event.all);
  217. });
  218.  
  219. // create function to add new items to instance
  220. events.a = function(additionalItems) {
  221. additionalItems = _prepareItems(additionalItems);
  222. items.push.apply(items, additionalItems);
  223. };
  224.  
  225. // create function to get all instance items left
  226. events.g = function() {
  227. // filter loaded items before return in case internal filter was not running until now
  228. return (items = $(items).filter(function() {
  229. return !$(this).data(config.loadedName);
  230. }));
  231. };
  232.  
  233. // create function to force loading elements
  234. events.f = function(forcedItems) {
  235. for( var i = 0; i < forcedItems.length; i++ ) {
  236. // only handle item if available in current instance
  237. // use a compare function, because Zepto can't handle object parameter for filter
  238. // var item = items.filter(forcedItems[i]);
  239. /* jshint loopfunc: true */
  240. var item = items.filter(function() {
  241. return this === forcedItems[i];
  242. });
  243.  
  244. if( item.length ) {
  245. _lazyLoadItems(false, item);
  246. }
  247. }
  248. };
  249.  
  250. // load initial items
  251. _lazyLoadItems();
  252.  
  253. // bind lazy load functions to scroll and resize event
  254. // noinspection JSUnresolvedVariable
  255. $(config.appendScroll).on("scroll." + namespace + " resize." + namespace, events.e);
  256. }
  257. }
  258.  
  259. /**
  260. * prepare items before handle them
  261. * @access private
  262. * @param {Array|object|jQuery} items
  263. * @return {Array|object|jQuery}
  264. */
  265. function _prepareItems(items) {
  266. // fetch used configurations before loops
  267. var defaultImage = config.defaultImage,
  268. placeholder = config.placeholder,
  269. imageBase = config.imageBase,
  270. srcsetAttribute = config.srcsetAttribute,
  271. loaderAttribute = config.loaderAttribute,
  272. forcedTags = config._f || {};
  273.  
  274. // filter items and only add those who not handled yet and got needed attributes available
  275. items = $(items).filter(function() {
  276. var element = $(this),
  277. tag = _getElementTagName(this);
  278.  
  279. return !element.data(config.handledName) &&
  280. (element.attr(config.attribute) || element.attr(srcsetAttribute) || element.attr(loaderAttribute) || forcedTags[tag] !== undefined);
  281. })
  282.  
  283. // append plugin instance to all elements
  284. .data("plugin_" + config.name, instance);
  285.  
  286. for( var i = 0, l = items.length; i < l; i++ ) {
  287. var element = $(items[i]),
  288. tag = _getElementTagName(items[i]),
  289. elementImageBase = element.attr(config.imageBaseAttribute) || imageBase;
  290.  
  291. // generate and update source set if an image base is set
  292. if( tag === _img && elementImageBase && element.attr(srcsetAttribute) ) {
  293. element.attr(srcsetAttribute, _getCorrectedSrcSet(element.attr(srcsetAttribute), elementImageBase));
  294. }
  295.  
  296. // add loader to forced element types
  297. if( forcedTags[tag] !== undefined && !element.attr(loaderAttribute) ) {
  298. element.attr(loaderAttribute, forcedTags[tag]);
  299. }
  300.  
  301. // set default image on every element without source
  302. if( tag === _img && defaultImage && !element.attr(_src) ) {
  303. element.attr(_src, defaultImage);
  304. }
  305.  
  306. // set placeholder on every element without background image
  307. else if( tag !== _img && placeholder && (!element.css(_backgroundImage) || element.css(_backgroundImage) === "none") ) {
  308. element.css(_backgroundImage, "url('" + placeholder + "')");
  309. }
  310. }
  311.  
  312. return items;
  313. }
  314.  
  315. /**
  316. * the 'lazy magic' - check all items
  317. * @access private
  318. * @param {boolean} [allItems]
  319. * @param {object} [forced]
  320. * @return void
  321. */
  322. function _lazyLoadItems(allItems, forced) {
  323. // skip if no items where left
  324. if( !items.length ) {
  325. // destroy instance if option is enabled
  326. if( config.autoDestroy ) {
  327. // noinspection JSUnresolvedFunction
  328. instance.destroy();
  329. }
  330.  
  331. return;
  332. }
  333.  
  334. var elements = forced || items,
  335. loadTriggered = false,
  336. imageBase = config.imageBase || "",
  337. srcsetAttribute = config.srcsetAttribute,
  338. handledName = config.handledName;
  339.  
  340. // loop all available items
  341. for( var i = 0; i < elements.length; i++ ) {
  342. // item is at least in loadable area
  343. if( allItems || forced || _isInLoadableArea(elements[i]) ) {
  344. var element = $(elements[i]),
  345. tag = _getElementTagName(elements[i]),
  346. attribute = element.attr(config.attribute),
  347. elementImageBase = element.attr(config.imageBaseAttribute) || imageBase,
  348. customLoader = element.attr(config.loaderAttribute);
  349.  
  350. // is not already handled
  351. if( !element.data(handledName) &&
  352. // and is visible or visibility doesn't matter
  353. (!config.visibleOnly || element.is(":visible")) && (
  354. // and image source or source set attribute is available
  355. (attribute || element.attr(srcsetAttribute)) && (
  356. // and is image tag where attribute is not equal source or source set
  357. (tag === _img && (elementImageBase + attribute !== element.attr(_src) || element.attr(srcsetAttribute) !== element.attr(_srcset))) ||
  358. // or is non image tag where attribute is not equal background
  359. (tag !== _img && elementImageBase + attribute !== element.css(_backgroundImage))
  360. ) ||
  361. // or custom loader is available
  362. customLoader ))
  363. {
  364. // mark element always as handled as this point to prevent double handling
  365. loadTriggered = true;
  366. element.data(handledName, true);
  367.  
  368. // load item
  369. _handleItem(element, tag, elementImageBase, customLoader);
  370. }
  371. }
  372. }
  373.  
  374. // when something was loaded remove them from remaining items
  375. if( loadTriggered ) {
  376. items = $(items).filter(function() {
  377. return !$(this).data(handledName);
  378. });
  379. }
  380. }
  381.  
  382. /**
  383. * load the given element the lazy way
  384. * @access private
  385. * @param {object} element
  386. * @param {string} tag
  387. * @param {string} imageBase
  388. * @param {function} [customLoader]
  389. * @return void
  390. */
  391. function _handleItem(element, tag, imageBase, customLoader) {
  392. // increment count of items waiting for after load
  393. ++_awaitingAfterLoad;
  394.  
  395. // extended error callback for correct 'onFinishedAll' handling
  396. var errorCallback = function() {
  397. _triggerCallback("onError", element);
  398. _reduceAwaiting();
  399.  
  400. // prevent further callback calls
  401. errorCallback = $.noop;
  402. };
  403.  
  404. // trigger function before loading image
  405. _triggerCallback("beforeLoad", element);
  406.  
  407. // fetch all double used data here for better code minimization
  408. var srcAttribute = config.attribute,
  409. srcsetAttribute = config.srcsetAttribute,
  410. sizesAttribute = config.sizesAttribute,
  411. retinaAttribute = config.retinaAttribute,
  412. removeAttribute = config.removeAttribute,
  413. loadedName = config.loadedName,
  414. elementRetina = element.attr(retinaAttribute);
  415.  
  416. // handle custom loader
  417. if( customLoader ) {
  418. // on load callback
  419. var loadCallback = function() {
  420. // remove attribute from element
  421. if( removeAttribute ) {
  422. element.removeAttr(config.loaderAttribute);
  423. }
  424.  
  425. // mark element as loaded
  426. element.data(loadedName, true);
  427.  
  428. // call after load event
  429. _triggerCallback(_afterLoad, element);
  430.  
  431. // remove item from waiting queue and possibly trigger finished event
  432. // it's needed to be asynchronous to run after filter was in _lazyLoadItems
  433. setTimeout(_reduceAwaiting, 1);
  434.  
  435. // prevent further callback calls
  436. loadCallback = $.noop;
  437. };
  438.  
  439. // bind error event to trigger callback and reduce waiting amount
  440. element.off(_error).one(_error, errorCallback)
  441.  
  442. // bind after load callback to element
  443. .one(_load, loadCallback);
  444.  
  445. // trigger custom loader and handle response
  446. if( !_triggerCallback(customLoader, element, function(response) {
  447. if( response ) {
  448. element.off(_load);
  449. loadCallback();
  450. }
  451. else {
  452. element.off(_error);
  453. errorCallback();
  454. }
  455. })) element.trigger(_error);
  456. }
  457.  
  458. // handle images
  459. else {
  460. // create image object
  461. var imageObj = $(new Image());
  462.  
  463. // bind error event to trigger callback and reduce waiting amount
  464. imageObj.one(_error, errorCallback)
  465.  
  466. // bind after load callback to image
  467. .one(_load, function() {
  468. // remove element from view
  469. element.hide();
  470.  
  471. // set image back to element
  472. // do it as single 'attr' calls, to be sure 'src' is set after 'srcset'
  473. if( tag === _img ) {
  474. element.attr(_sizes, imageObj.attr(_sizes))
  475. .attr(_srcset, imageObj.attr(_srcset))
  476. .attr(_src, imageObj.attr(_src));
  477. }
  478. else {
  479. element.css(_backgroundImage, "url('" + imageObj.attr(_src) + "')");
  480. }
  481.  
  482. // bring it back with some effect!
  483. element[config.effect](config.effectTime);
  484.  
  485. // remove attribute from element
  486. if( removeAttribute ) {
  487. element.removeAttr(srcAttribute + " " + srcsetAttribute + " " + retinaAttribute + " " + config.imageBaseAttribute);
  488.  
  489. // only remove 'sizes' attribute, if it was a custom one
  490. if( sizesAttribute !== _sizes ) {
  491. element.removeAttr(sizesAttribute);
  492. }
  493. }
  494.  
  495. // mark element as loaded
  496. element.data(loadedName, true);
  497.  
  498. // call after load event
  499. _triggerCallback(_afterLoad, element);
  500.  
  501. // cleanup image object
  502. imageObj.remove();
  503.  
  504. // remove item from waiting queue and possibly trigger finished event
  505. _reduceAwaiting();
  506. });
  507.  
  508. // set sources
  509. // do it as single 'attr' calls, to be sure 'src' is set after 'srcset'
  510. var imageSrc = (_isRetinaDisplay && elementRetina ? elementRetina : element.attr(srcAttribute)) || "";
  511. imageObj.attr(_sizes, element.attr(sizesAttribute))
  512. .attr(_srcset, element.attr(srcsetAttribute))
  513. .attr(_src, imageSrc ? imageBase + imageSrc : null);
  514.  
  515. // call after load even on cached image
  516. imageObj.complete && imageObj.trigger(_load); // jshint ignore : line
  517. }
  518. }
  519.  
  520. /**
  521. * check if the given element is inside the current viewport or threshold
  522. * @access private
  523. * @param {object} element
  524. * @return {boolean}
  525. */
  526. function _isInLoadableArea(element) {
  527. var elementBound = element.getBoundingClientRect(),
  528. direction = config.scrollDirection,
  529. threshold = config.threshold,
  530. vertical = // check if element is in loadable area from top
  531. ((_getActualHeight() + threshold) > elementBound.top) &&
  532. // check if element is even in loadable are from bottom
  533. (-threshold < elementBound.bottom),
  534. horizontal = // check if element is in loadable area from left
  535. ((_getActualWidth() + threshold) > elementBound.left) &&
  536. // check if element is even in loadable area from right
  537. (-threshold < elementBound.right);
  538.  
  539. if( direction === "vertical" ) {
  540. return vertical;
  541. }
  542. else if( direction === "horizontal" ) {
  543. return horizontal;
  544. }
  545.  
  546. return vertical && horizontal;
  547. }
  548.  
  549. /**
  550. * receive the current viewed width of the browser
  551. * @access private
  552. * @return {number}
  553. */
  554. function _getActualWidth() {
  555. return _actualWidth >= 0 ? _actualWidth : (_actualWidth = $(window).width());
  556. }
  557.  
  558. /**
  559. * receive the current viewed height of the browser
  560. * @access private
  561. * @return {number}
  562. */
  563. function _getActualHeight() {
  564. return _actualHeight >= 0 ? _actualHeight : (_actualHeight = $(window).height());
  565. }
  566.  
  567. /**
  568. * get lowercase tag name of an element
  569. * @access private
  570. * @param {object} element
  571. * @returns {string}
  572. */
  573. function _getElementTagName(element) {
  574. return element.tagName.toLowerCase();
  575. }
  576.  
  577. /**
  578. * prepend image base to all srcset entries
  579. * @access private
  580. * @param {string} srcset
  581. * @param {string} imageBase
  582. * @returns {string}
  583. */
  584. function _getCorrectedSrcSet(srcset, imageBase) {
  585. if( imageBase ) {
  586. // trim, remove unnecessary spaces and split entries
  587. var entries = srcset.split(",");
  588. srcset = "";
  589.  
  590. for( var i = 0, l = entries.length; i < l; i++ ) {
  591. srcset += imageBase + entries[i].trim() + (i !== l - 1 ? "," : "");
  592. }
  593. }
  594.  
  595. return srcset;
  596. }
  597.  
  598. /**
  599. * helper function to throttle down event triggering
  600. * @access private
  601. * @param {number} delay
  602. * @param {function} callback
  603. * @return {function}
  604. */
  605. function _throttle(delay, callback) {
  606. var timeout,
  607. lastExecute = 0;
  608.  
  609. return function(event, ignoreThrottle) {
  610. var elapsed = +new Date() - lastExecute;
  611.  
  612. function run() {
  613. lastExecute = +new Date();
  614. // noinspection JSUnresolvedFunction
  615. callback.call(instance, event);
  616. }
  617.  
  618. timeout && clearTimeout(timeout); // jshint ignore : line
  619.  
  620. if( elapsed > delay || !config.enableThrottle || ignoreThrottle ) {
  621. run();
  622. }
  623. else {
  624. timeout = setTimeout(run, delay - elapsed);
  625. }
  626. };
  627. }
  628.  
  629. /**
  630. * reduce count of awaiting elements to 'afterLoad' event and fire 'onFinishedAll' if reached zero
  631. * @access private
  632. * @return void
  633. */
  634. function _reduceAwaiting() {
  635. --_awaitingAfterLoad;
  636.  
  637. // if no items were left trigger finished event
  638. if( !items.length && !_awaitingAfterLoad ) {
  639. _triggerCallback("onFinishedAll");
  640. }
  641. }
  642.  
  643. /**
  644. * single implementation to handle callbacks, pass element and set 'this' to current instance
  645. * @access private
  646. * @param {string|function} callback
  647. * @param {object} [element]
  648. * @param {*} [args]
  649. * @return {boolean}
  650. */
  651. function _triggerCallback(callback, element, args) {
  652. if( (callback = config[callback]) ) {
  653. // jQuery's internal '$(arguments).slice(1)' are causing problems at least on old iPads
  654. // below is shorthand of 'Array.prototype.slice.call(arguments, 1)'
  655. callback.apply(instance, [].slice.call(arguments, 1));
  656. return true;
  657. }
  658.  
  659. return false;
  660. }
  661.  
  662. // if event driven or window is already loaded don't wait for page loading
  663. if( config.bind === "event" || windowLoaded ) {
  664. _initialize();
  665. }
  666.  
  667. // otherwise load initial items and start lazy after page load
  668. else {
  669. // noinspection JSUnresolvedVariable
  670. $(window).on(_load + "." + namespace, _initialize);
  671. }
  672. }
  673.  
  674. /**
  675. * lazy plugin class constructor
  676. * @constructor
  677. * @access private
  678. * @param {object} elements
  679. * @param {object} settings
  680. * @return {object|LazyPlugin}
  681. */
  682. function LazyPlugin(elements, settings) {
  683. /**
  684. * this lazy plugin instance
  685. * @access private
  686. * @type {object|LazyPlugin|LazyPlugin.prototype}
  687. */
  688. var _instance = this,
  689.  
  690. /**
  691. * this lazy plugin instance configuration
  692. * @access private
  693. * @type {object}
  694. */
  695. _config = $.extend({}, _instance.config, settings),
  696.  
  697. /**
  698. * instance generated event executed on container scroll or resize
  699. * packed in an object to be referenceable and short named because properties will not be minified
  700. * @access private
  701. * @type {object}
  702. */
  703. _events = {},
  704.  
  705. /**
  706. * unique namespace for instance related events
  707. * @access private
  708. * @type {string}
  709. */
  710. _namespace = _config.name + "-" + (++lazyInstanceId);
  711.  
  712. // noinspection JSUndefinedPropertyAssignment
  713. /**
  714. * wrapper to get or set an entry from plugin instance configuration
  715. * much smaller on minify as direct access
  716. * @access public
  717. * @type {function}
  718. * @param {string} entryName
  719. * @param {*} [value]
  720. * @return {LazyPlugin|*}
  721. */
  722. _instance.config = function(entryName, value) {
  723. if( value === undefined ) {
  724. return _config[entryName];
  725. }
  726.  
  727. _config[entryName] = value;
  728. return _instance;
  729. };
  730.  
  731. // noinspection JSUndefinedPropertyAssignment
  732. /**
  733. * add additional items to current instance
  734. * @access public
  735. * @param {Array|object|string} items
  736. * @return {LazyPlugin}
  737. */
  738. _instance.addItems = function(items) {
  739. _events.a && _events.a($.type(items) === "string" ? $(items) : items); // jshint ignore : line
  740. return _instance;
  741. };
  742.  
  743. // noinspection JSUndefinedPropertyAssignment
  744. /**
  745. * get all left items of this instance
  746. * @access public
  747. * @returns {object}
  748. */
  749. _instance.getItems = function() {
  750. return _events.g ? _events.g() : {};
  751. };
  752.  
  753. // noinspection JSUndefinedPropertyAssignment
  754. /**
  755. * force lazy to load all items in loadable area right now
  756. * by default without throttle
  757. * @access public
  758. * @type {function}
  759. * @param {boolean} [useThrottle]
  760. * @return {LazyPlugin}
  761. */
  762. _instance.update = function(useThrottle) {
  763. _events.e && _events.e({}, !useThrottle); // jshint ignore : line
  764. return _instance;
  765. };
  766.  
  767. // noinspection JSUndefinedPropertyAssignment
  768. /**
  769. * force element(s) to load directly, ignoring the viewport
  770. * @access public
  771. * @param {Array|object|string} items
  772. * @return {LazyPlugin}
  773. */
  774. _instance.force = function(items) {
  775. _events.f && _events.f($.type(items) === "string" ? $(items) : items); // jshint ignore : line
  776. return _instance;
  777. };
  778.  
  779. // noinspection JSUndefinedPropertyAssignment
  780. /**
  781. * force lazy to load all available items right now
  782. * this call ignores throttling
  783. * @access public
  784. * @type {function}
  785. * @return {LazyPlugin}
  786. */
  787. _instance.loadAll = function() {
  788. _events.e && _events.e({all: true}, true); // jshint ignore : line
  789. return _instance;
  790. };
  791.  
  792. // noinspection JSUndefinedPropertyAssignment
  793. /**
  794. * destroy this plugin instance
  795. * @access public
  796. * @type {function}
  797. * @return undefined
  798. */
  799. _instance.destroy = function() {
  800. // unbind instance generated events
  801. // noinspection JSUnresolvedFunction, JSUnresolvedVariable
  802. $(_config.appendScroll).off("." + _namespace, _events.e);
  803. // noinspection JSUnresolvedVariable
  804. $(window).off("." + _namespace);
  805.  
  806. // clear events
  807. _events = {};
  808.  
  809. return undefined;
  810. };
  811.  
  812. // start using lazy and return all elements to be chainable or instance for further use
  813. // noinspection JSUnresolvedVariable
  814. _executeLazy(_instance, _config, elements, _events, _namespace);
  815. return _config.chainable ? elements : _instance;
  816. }
  817.  
  818. /**
  819. * settings and configuration data
  820. * @access public
  821. * @type {object}
  822. */
  823. LazyPlugin.prototype.config = {
  824. // general
  825. name : "lazy",
  826. chainable : true,
  827. autoDestroy : true,
  828. bind : "load",
  829. threshold : 500,
  830. visibleOnly : false,
  831. appendScroll : window,
  832. scrollDirection : "both",
  833. imageBase : null,
  834. defaultImage : "data:image/gif;base64,R0lGODlhAQABAIAAAP///wAAACH5BAEAAAAALAAAAAABAAEAAAICRAEAOw==",
  835. placeholder : null,
  836. delay : -1,
  837. combined : false,
  838.  
  839. // attributes
  840. attribute : "data-src",
  841. srcsetAttribute : "data-srcset",
  842. sizesAttribute : "data-sizes",
  843. retinaAttribute : "data-retina",
  844. loaderAttribute : "data-loader",
  845. imageBaseAttribute : "data-imagebase",
  846. removeAttribute : true,
  847. handledName : "handled",
  848. loadedName : "loaded",
  849.  
  850. // effect
  851. effect : "show",
  852. effectTime : 0,
  853.  
  854. // throttle
  855. enableThrottle : true,
  856. throttle : 250,
  857.  
  858. // callbacks
  859. beforeLoad : undefined,
  860. afterLoad : undefined,
  861. onError : undefined,
  862. onFinishedAll : undefined
  863. };
  864.  
  865. // register window load event globally to prevent not loading elements
  866. // since jQuery 3.X ready state is fully async and may be executed after 'load'
  867. $(window).on("load", function() {
  868. windowLoaded = true;
  869. });
  870. })(window);

QingJ © 2025

镜像随时可能失效,请加Q群300939539或关注我们的公众号极客氢云获取最新地址