All Downloads are FREE. Search and download functionalities are using the official Maven repository.

META-INF.resources.bower_components.imagesloaded.imagesloaded.js Maven / Gradle / Ivy

There is a newer version: 1.2.0.3-jre17-rc1
Show newest version
/*!
 * imagesLoaded v3.1.8
 * JavaScript is all like "You images are done yet or what?"
 * MIT License
 */

(function (window, factory) {
    'use strict';
    // universal module definition

    /*global define: false, module: false, require: false */

    if (typeof define === 'function' && define.amd) {
        // AMD
        define([
            'eventEmitter/EventEmitter',
            'eventie/eventie'
        ], function (EventEmitter, eventie) {
            return factory(window, EventEmitter, eventie);
        });
    } else if (typeof exports === 'object') {
        // CommonJS
        module.exports = factory(
            window,
            require('wolfy87-eventemitter'),
            require('eventie')
        );
    } else {
        // browser global
        window.imagesLoaded = factory(
            window,
            window.EventEmitter,
            window.eventie
        );
    }

})(window,

// --------------------------  factory -------------------------- //

    function factory(window, EventEmitter, eventie) {

        'use strict';

        var $ = window.jQuery;
        var console = window.console;
        var hasConsole = typeof console !== 'undefined';

// -------------------------- helpers -------------------------- //

// extend objects
        function extend(a, b) {
            for (var prop in b) {
                a[prop] = b[prop];
            }
            return a;
        }

        var objToString = Object.prototype.toString;

        function isArray(obj) {
            return objToString.call(obj) === '[object Array]';
        }

// turn element or nodeList into an array
        function makeArray(obj) {
            var ary = [];
            if (isArray(obj)) {
                // use object if already an array
                ary = obj;
            } else if (typeof obj.length === 'number') {
                // convert nodeList to array
                for (var i = 0, len = obj.length; i < len; i++) {
                    ary.push(obj[i]);
                }
            } else {
                // array of single index
                ary.push(obj);
            }
            return ary;
        }

        // -------------------------- imagesLoaded -------------------------- //

        /**
         * @param {Array, Element, NodeList, String} elem
         * @param {Object or Function} options - if function, use as callback
         * @param {Function} onAlways - callback function
         */
        function ImagesLoaded(elem, options, onAlways) {
            // coerce ImagesLoaded() without new, to be new ImagesLoaded()
            if (!( this instanceof ImagesLoaded )) {
                return new ImagesLoaded(elem, options);
            }
            // use elem as selector string
            if (typeof elem === 'string') {
                elem = document.querySelectorAll(elem);
            }

            this.elements = makeArray(elem);
            this.options = extend({}, this.options);

            if (typeof options === 'function') {
                onAlways = options;
            } else {
                extend(this.options, options);
            }

            if (onAlways) {
                this.on('always', onAlways);
            }

            this.getImages();

            if ($) {
                // add jQuery Deferred object
                this.jqDeferred = new $.Deferred();
            }

            // HACK check async to allow time to bind listeners
            var _this = this;
            setTimeout(function () {
                _this.check();
            });
        }

        ImagesLoaded.prototype = new EventEmitter();

        ImagesLoaded.prototype.options = {};

        ImagesLoaded.prototype.getImages = function () {
            this.images = [];

            // filter & find items if we have an item selector
            for (var i = 0, len = this.elements.length; i < len; i++) {
                var elem = this.elements[i];
                // filter siblings
                if (elem.nodeName === 'IMG') {
                    this.addImage(elem);
                }
                // find children
                // no non-element nodes, #143
                var nodeType = elem.nodeType;
                if (!nodeType || !( nodeType === 1 || nodeType === 9 || nodeType === 11 )) {
                    continue;
                }
                var childElems = elem.querySelectorAll('img');
                // concat childElems to filterFound array
                for (var j = 0, jLen = childElems.length; j < jLen; j++) {
                    var img = childElems[j];
                    this.addImage(img);
                }
            }
        };

        /**
         * @param {Image} img
         */
        ImagesLoaded.prototype.addImage = function (img) {
            var loadingImage = new LoadingImage(img);
            this.images.push(loadingImage);
        };

        ImagesLoaded.prototype.check = function () {
            var _this = this;
            var checkedCount = 0;
            var length = this.images.length;
            this.hasAnyBroken = false;
            // complete if no images
            if (!length) {
                this.complete();
                return;
            }

            function onConfirm(image, message) {
                if (_this.options.debug && hasConsole) {
                    console.log('confirm', image, message);
                }

                _this.progress(image);
                checkedCount++;
                if (checkedCount === length) {
                    _this.complete();
                }
                return true; // bind once
            }

            for (var i = 0; i < length; i++) {
                var loadingImage = this.images[i];
                loadingImage.on('confirm', onConfirm);
                loadingImage.check();
            }
        };

        ImagesLoaded.prototype.progress = function (image) {
            this.hasAnyBroken = this.hasAnyBroken || !image.isLoaded;
            // HACK - Chrome triggers event before object properties have changed. #83
            var _this = this;
            setTimeout(function () {
                _this.emit('progress', _this, image);
                if (_this.jqDeferred && _this.jqDeferred.notify) {
                    _this.jqDeferred.notify(_this, image);
                }
            });
        };

        ImagesLoaded.prototype.complete = function () {
            var eventName = this.hasAnyBroken ? 'fail' : 'done';
            this.isComplete = true;
            var _this = this;
            // HACK - another setTimeout so that confirm happens after progress
            setTimeout(function () {
                _this.emit(eventName, _this);
                _this.emit('always', _this);
                if (_this.jqDeferred) {
                    var jqMethod = _this.hasAnyBroken ? 'reject' : 'resolve';
                    _this.jqDeferred[jqMethod](_this);
                }
            });
        };

        // -------------------------- jquery -------------------------- //

        if ($) {
            $.fn.imagesLoaded = function (options, callback) {
                var instance = new ImagesLoaded(this, options, callback);
                return instance.jqDeferred.promise($(this));
            };
        }


        // --------------------------  -------------------------- //

        function LoadingImage(img) {
            this.img = img;
        }

        LoadingImage.prototype = new EventEmitter();

        LoadingImage.prototype.check = function () {
            // first check cached any previous images that have same src
            var resource = cache[this.img.src] || new Resource(this.img.src);
            if (resource.isConfirmed) {
                this.confirm(resource.isLoaded, 'cached was confirmed');
                return;
            }

            // If complete is true and browser supports natural sizes,
            // try to check for image status manually.
            if (this.img.complete && this.img.naturalWidth !== undefined) {
                // report based on naturalWidth
                this.confirm(this.img.naturalWidth !== 0, 'naturalWidth');
                return;
            }

            // If none of the checks above matched, simulate loading on detached element.
            var _this = this;
            resource.on('confirm', function (resrc, message) {
                _this.confirm(resrc.isLoaded, message);
                return true;
            });

            resource.check();
        };

        LoadingImage.prototype.confirm = function (isLoaded, message) {
            this.isLoaded = isLoaded;
            this.emit('confirm', this, message);
        };

        // -------------------------- Resource -------------------------- //

        // Resource checks each src, only once
        // separate class from LoadingImage to prevent memory leaks. See #115

        var cache = {};

        function Resource(src) {
            this.src = src;
            // add to cache
            cache[src] = this;
        }

        Resource.prototype = new EventEmitter();

        Resource.prototype.check = function () {
            // only trigger checking once
            if (this.isChecked) {
                return;
            }
            // simulate loading on detached element
            var proxyImage = new Image();
            eventie.bind(proxyImage, 'load', this);
            eventie.bind(proxyImage, 'error', this);
            proxyImage.src = this.src;
            // set flag
            this.isChecked = true;
        };

        // ----- events ----- //

        // trigger specified handler for event type
        Resource.prototype.handleEvent = function (event) {
            var method = 'on' + event.type;
            if (this[method]) {
                this[method](event);
            }
        };

        Resource.prototype.onload = function (event) {
            this.confirm(true, 'onload');
            this.unbindProxyEvents(event);
        };

        Resource.prototype.onerror = function (event) {
            this.confirm(false, 'onerror');
            this.unbindProxyEvents(event);
        };

        // ----- confirm ----- //

        Resource.prototype.confirm = function (isLoaded, message) {
            this.isConfirmed = true;
            this.isLoaded = isLoaded;
            this.emit('confirm', this, message);
        };

        Resource.prototype.unbindProxyEvents = function (event) {
            eventie.unbind(event.target, 'load', this);
            eventie.unbind(event.target, 'error', this);
        };

        // -----  ----- //

        return ImagesLoaded;

    });




© 2015 - 2025 Weber Informatics LLC | Privacy Policy