function ImageLoader(options, support) { this.link = null; this.options = options; this.support = support; this.origin = this.getOrigin(window.location.href); } ImageLoader.prototype.findImages = function(nodes) { var images = []; nodes.reduce(function(imageNodes, container) { switch(container.node.nodeName) { case "IMG": return imageNodes.concat([{ args: [container.node.src], method: "url" }]); case "svg": case "IFRAME": return imageNodes.concat([{ args: [container.node], method: container.node.nodeName }]); } return imageNodes; }, []).forEach(this.addImage(images, this.loadImage), this); return images; }; ImageLoader.prototype.findBackgroundImage = function(images, container) { container.parseBackgroundImages().filter(this.hasImageBackground).forEach(this.addImage(images, this.loadImage), this); return images; }; ImageLoader.prototype.addImage = function(images, callback) { return function(newImage) { newImage.args.forEach(function(image) { if (!this.imageExists(images, image)) { images.splice(0, 0, callback.call(this, newImage)); log('Added image #' + (images.length), typeof(image) === "string" ? image.substring(0, 100) : image); } }, this); }; }; ImageLoader.prototype.hasImageBackground = function(imageData) { return imageData.method !== "none"; }; ImageLoader.prototype.loadImage = function(imageData) { if (imageData.method === "url") { var src = imageData.args[0]; if (this.isSVG(src) && !this.support.svg && !this.options.allowTaint) { return new SVGContainer(src); } else if (src.match(/data:image\/.*;base64,/i)) { return new ImageContainer(src.replace(/url\(['"]{0,}|['"]{0,}\)$/ig, ''), false); } else if (this.isSameOrigin(src) || this.options.allowTaint === true || this.isSVG(src)) { return new ImageContainer(src, false); } else if (this.support.cors && !this.options.allowTaint && this.options.useCORS) { return new ImageContainer(src, true); } else if (this.options.proxy) { return new ProxyImageContainer(src, this.options.proxy); } else { return new DummyImageContainer(src); } } else if (imageData.method === "linear-gradient") { return new LinearGradientContainer(imageData); } else if (imageData.method === "gradient") { return new WebkitGradientContainer(imageData); } else if (imageData.method === "svg") { return new SVGNodeContainer(imageData.args[0], this.support.svg); } else if (imageData.method === "IFRAME") { return new FrameContainer(imageData.args[0], this.isSameOrigin(imageData.args[0].src), this.options); } else { return new DummyImageContainer(imageData); } }; ImageLoader.prototype.isSVG = function(src) { return src.substring(src.length - 3).toLowerCase() === "svg" || SVGContainer.prototype.isInline(src); }; ImageLoader.prototype.imageExists = function(images, src) { return images.some(function(image) { return image.src === src; }); }; ImageLoader.prototype.isSameOrigin = function(url) { return (this.getOrigin(url) === this.origin); }; ImageLoader.prototype.getOrigin = function(url) { var link = this.link || (this.link = document.createElement("a")); link.href = url; link.href = link.href; // IE9, LOL! - http://jsfiddle.net/niklasvh/2e48b/ return link.protocol + link.hostname + link.port; }; ImageLoader.prototype.getPromise = function(container) { return this.timeout(container, this.options.imageTimeout)['catch'](function() { var dummy = new DummyImageContainer(container.src); return dummy.promise.then(function(image) { container.image = image; }); }); }; ImageLoader.prototype.get = function(src) { var found = null; return this.images.some(function(img) { return (found = img).src === src; }) ? found : null; }; ImageLoader.prototype.fetch = function(nodes) { this.images = nodes.reduce(bind(this.findBackgroundImage, this), this.findImages(nodes)); this.images.forEach(function(image, index) { image.promise.then(function() { log("Succesfully loaded image #"+ (index+1), image); }, function(e) { log("Failed loading image #"+ (index+1), image, e); }); }); this.ready = Promise.all(this.images.map(this.getPromise, this)); log("Finished searching images"); return this; }; ImageLoader.prototype.timeout = function(container, timeout) { var timer; return Promise.race([container.promise, new Promise(function(res, reject) { timer = setTimeout(function() { log("Timed out loading image", container); reject(container); }, timeout); })]).then(function(container) { clearTimeout(timer); return container; }); };