PageSourceSearch

https://www.isoftstone.com/resources/zh-cn/templates/isoftstone/js/jquery.lazyloadxt.js

js isoftstone.com collected 2026-10-02 14:46:02 UTC 9,162 bytes, 294 lines download raw bytes

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

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.