html2canvas/src/imageloader.js

127 lines
4.2 KiB
JavaScript

function ImageLoader(options, support) {
this.link = null;
this.options = options;
this.support = support;
this.origin = window.location.protocol + window.location.hostname + window.location.port;
}
ImageLoader.prototype.findImages = function(nodes) {
var images = [];
nodes.filter(isImage).map(urlImage).forEach(this.addImage(images, this.loadImage), this);
nodes.filter(isSVGNode).map(svgImage).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]);
} else {
return new DummyImageContainer(imageData);
}
};
ImageLoader.prototype.isSVG = function(src) {
return (/(.+).svg$/i.test(src)) || SVGContainer.prototype.isInline(src);
};
ImageLoader.prototype.imageExists = function(images, src) {
return images.some(function(image) {
return image.src === src;
});
};
ImageLoader.prototype.isSameOrigin = 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/
var origin = link.protocol + link.hostname + link.port;
return (origin === this.origin);
};
ImageLoader.prototype.getPromise = function(container) {
return container.promise;
};
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));
}, function() {
log("Failed loading image #"+ (index+1));
});
});
this.ready = Promise.all(this.images.map(this.getPromise));
log("Finished searching images");
return this;
};
function isImage(container) {
return container.node.nodeName === "IMG";
}
function isSVGNode(container) {
return container.node.nodeName === "svg";
}
function urlImage(container) {
return {
args: [container.node.src],
method: "url"
};
}
function svgImage(container) {
return {
args: [container.node],
method: "svg"
};
}