mirror of
https://github.com/niklasvh/html2canvas.git
synced 2023-08-10 21:13:10 +03:00
Fallback to jsonp proxy if browser doesn't support cors xhr/image
This commit is contained in:
parent
df0a696b6a
commit
bc08edc340
@ -15,5 +15,5 @@
|
|||||||
"jQuery": true
|
"jQuery": true
|
||||||
},
|
},
|
||||||
"predef": ["NodeParser", "NodeContainer", "StackingContext", "TextContainer", "ImageLoader", "CanvasRenderer", "Renderer", "Support", "bind", "Promise", "getBounds", "offsetBounds", "XHR",
|
"predef": ["NodeParser", "NodeContainer", "StackingContext", "TextContainer", "ImageLoader", "CanvasRenderer", "Renderer", "Support", "bind", "Promise", "getBounds", "offsetBounds", "XHR",
|
||||||
"ImageContainer", "ProxyImageContainer", "DummyImageContainer", "Font", "FontMetrics", "GradientContainer", "LinearGradientContainer", "WebkitGradientContainer", "SVGContainer", "SVGNodeContainer", "FrameContainer", "html2canvas", "log", "smallImage", "parseBackgrounds", "createWindowClone"]
|
"ImageContainer", "ProxyImageContainer", "DummyImageContainer", "Font", "FontMetrics", "GradientContainer", "LinearGradientContainer", "WebkitGradientContainer", "SVGContainer", "SVGNodeContainer", "FrameContainer", "html2canvas", "log", "smallImage", "parseBackgrounds", "createWindowClone", "decode64", "Proxy", "ProxyURL"]
|
||||||
}
|
}
|
||||||
|
80
dist/html2canvas.js
vendored
80
dist/html2canvas.js
vendored
@ -591,6 +591,7 @@ window.html2canvas = function(nodeList, options) {
|
|||||||
};
|
};
|
||||||
|
|
||||||
window.html2canvas.punycode = this.punycode;
|
window.html2canvas.punycode = this.punycode;
|
||||||
|
window.html2canvas.proxy = {};
|
||||||
|
|
||||||
function renderDocument(document, options, windowWidth, windowHeight) {
|
function renderDocument(document, options, windowWidth, windowHeight) {
|
||||||
return createWindowClone(document, document, windowWidth, windowHeight, options).then(function(container) {
|
return createWindowClone(document, document, windowWidth, windowHeight, options).then(function(container) {
|
||||||
@ -799,7 +800,7 @@ function FrameContainer(container, sameOrigin, proxy) {
|
|||||||
|
|
||||||
FrameContainer.prototype.proxyLoad = function(proxy, bounds) {
|
FrameContainer.prototype.proxyLoad = function(proxy, bounds) {
|
||||||
var container = this.src;
|
var container = this.src;
|
||||||
return XHR(proxy + "?url=" + container.src).then(documentFromHTML(container)).then(function(doc) {
|
return new Proxy(container.src, proxy, window.document).then(documentFromHTML(container)).then(function(doc) {
|
||||||
return createWindowClone(doc, container.ownerDocument, bounds.width, bounds.height, {});
|
return createWindowClone(doc, container.ownerDocument, bounds.width, bounds.height, {});
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
@ -2172,45 +2173,74 @@ function hasUnicode(string) {
|
|||||||
return /[^\u0000-\u00ff]/.test(string);
|
return /[^\u0000-\u00ff]/.test(string);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function Proxy(src, proxyUrl, document) {
|
||||||
|
var callback = createCallback(supportsCORS);
|
||||||
|
var url = createProxyUrl(proxyUrl, src, callback);
|
||||||
|
|
||||||
|
return supportsCORS ? XHR(url) : (jsonp(document, url, callback).then(function(response) {
|
||||||
|
return decode64(response.content);
|
||||||
|
}));
|
||||||
|
}
|
||||||
|
var proxyCount = 0;
|
||||||
|
|
||||||
|
var supportsCORS = ('withCredentials' in new XMLHttpRequest());
|
||||||
|
var supportsCORSImage = ('crossOrigin' in new Image());
|
||||||
|
|
||||||
|
function ProxyURL(src, proxyUrl, document) {
|
||||||
|
var callback = createCallback(supportsCORSImage);
|
||||||
|
var url = createProxyUrl(proxyUrl, src, callback);
|
||||||
|
return (supportsCORSImage ? Promise.resolve(url) : jsonp(document, url, callback).then(function(response) {
|
||||||
|
return "data:" + response.type + ";base64," + response.content;
|
||||||
|
}));
|
||||||
|
}
|
||||||
|
|
||||||
|
function jsonp(document, url, callback) {
|
||||||
|
return new Promise(function(resolve, reject) {
|
||||||
|
var s = document.createElement("script");
|
||||||
|
var cleanup = function() {
|
||||||
|
delete window.html2canvas.proxy[callback];
|
||||||
|
document.body.removeChild(s);
|
||||||
|
};
|
||||||
|
window.html2canvas.proxy[callback] = function(response) {
|
||||||
|
cleanup();
|
||||||
|
resolve(response);
|
||||||
|
};
|
||||||
|
s.src = url;
|
||||||
|
s.onerror = function(e) {
|
||||||
|
cleanup();
|
||||||
|
reject(e);
|
||||||
|
};
|
||||||
|
document.body.appendChild(s);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
function createCallback(useCORS) {
|
||||||
|
return !useCORS ? "html2canvas_" + Date.now() + "_" + (++proxyCount) + "_" + Math.round(Math.random() * 100000) : "";
|
||||||
|
}
|
||||||
|
|
||||||
|
function createProxyUrl(proxyUrl, src, callback) {
|
||||||
|
return proxyUrl + "?url=" + encodeURIComponent(src) + (callback.length ? "&callback=html2canvas.proxy." + callback : "");
|
||||||
|
}
|
||||||
|
|
||||||
function ProxyImageContainer(src, proxy) {
|
function ProxyImageContainer(src, proxy) {
|
||||||
var callbackName = "html2canvas_" + proxyImageCount++;
|
|
||||||
var script = document.createElement("script");
|
var script = document.createElement("script");
|
||||||
var link = document.createElement("a");
|
var link = document.createElement("a");
|
||||||
link.href = src;
|
link.href = src;
|
||||||
src = link.href;
|
src = link.href;
|
||||||
var requestUrl = proxy + ((proxy.indexOf("?") > -1) ? "&" : "?" ) + 'url=' + encodeURIComponent(src) + '&callback=' + callbackName;
|
|
||||||
this.src = src;
|
this.src = src;
|
||||||
this.image = new Image();
|
this.image = new Image();
|
||||||
var self = this;
|
var self = this;
|
||||||
this.promise = new Promise(function(resolve, reject) {
|
this.promise = new Promise(function(resolve, reject) {
|
||||||
|
self.image.crossOrigin = "Anonymous";
|
||||||
self.image.onload = resolve;
|
self.image.onload = resolve;
|
||||||
self.image.onerror = reject;
|
self.image.onerror = reject;
|
||||||
|
|
||||||
window[callbackName] = function(a){
|
new ProxyURL(src, proxy, document).then(function(url) {
|
||||||
if (a.substring(0,6) === "error:"){
|
self.image.src = url;
|
||||||
reject();
|
})['catch'](reject);
|
||||||
} else {
|
|
||||||
self.image.src = a;
|
|
||||||
}
|
|
||||||
window[callbackName] = undefined; // to work with IE<9 // NOTE: that the undefined callback property-name still exists on the window object (for IE<9)
|
|
||||||
try {
|
|
||||||
delete window[callbackName]; // for all browser that support this
|
|
||||||
} catch(ex) {}
|
|
||||||
script.parentNode.removeChild(script);
|
|
||||||
};
|
|
||||||
script.setAttribute("type", "text/javascript");
|
|
||||||
script.setAttribute("src", requestUrl);
|
|
||||||
document.body.appendChild(script);
|
|
||||||
})['catch'](function() {
|
|
||||||
var dummy = new DummyImageContainer(src);
|
|
||||||
return dummy.promise.then(function(image) {
|
|
||||||
self.image = image;
|
|
||||||
});
|
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
var proxyImageCount = 0;
|
|
||||||
|
|
||||||
function Renderer(width, height, images, options, document) {
|
function Renderer(width, height, images, options, document) {
|
||||||
this.width = width;
|
this.width = width;
|
||||||
this.height = height;
|
this.height = height;
|
||||||
|
4
dist/html2canvas.min.js
vendored
4
dist/html2canvas.min.js
vendored
File diff suppressed because one or more lines are too long
@ -9,7 +9,7 @@
|
|||||||
"url": "http://hertzen.com"
|
"url": "http://hertzen.com"
|
||||||
},
|
},
|
||||||
"engines": {
|
"engines": {
|
||||||
"node": ">=0.8.0"
|
"node": ">=0.10.0"
|
||||||
},
|
},
|
||||||
"dependencies": {},
|
"dependencies": {},
|
||||||
"repository": {
|
"repository": {
|
||||||
@ -30,7 +30,7 @@
|
|||||||
"grunt-contrib-uglify": "^0.6.0",
|
"grunt-contrib-uglify": "^0.6.0",
|
||||||
"grunt-contrib-watch": "^0.6.1",
|
"grunt-contrib-watch": "^0.6.1",
|
||||||
"grunt-execute": "^0.2.2",
|
"grunt-execute": "^0.2.2",
|
||||||
"html2canvas-proxy": "0.0.2",
|
"html2canvas-proxy": "0.0.5",
|
||||||
"humanize-duration": "^2.0.1",
|
"humanize-duration": "^2.0.1",
|
||||||
"lodash": "^2.4.1",
|
"lodash": "^2.4.1",
|
||||||
"png-js": ">= 0.1.1",
|
"png-js": ">= 0.1.1",
|
||||||
|
@ -23,6 +23,7 @@ window.html2canvas = function(nodeList, options) {
|
|||||||
};
|
};
|
||||||
|
|
||||||
window.html2canvas.punycode = this.punycode;
|
window.html2canvas.punycode = this.punycode;
|
||||||
|
window.html2canvas.proxy = {};
|
||||||
|
|
||||||
function renderDocument(document, options, windowWidth, windowHeight) {
|
function renderDocument(document, options, windowWidth, windowHeight) {
|
||||||
return createWindowClone(document, document, windowWidth, windowHeight, options).then(function(container) {
|
return createWindowClone(document, document, windowWidth, windowHeight, options).then(function(container) {
|
||||||
|
@ -20,7 +20,7 @@ function FrameContainer(container, sameOrigin, proxy) {
|
|||||||
|
|
||||||
FrameContainer.prototype.proxyLoad = function(proxy, bounds) {
|
FrameContainer.prototype.proxyLoad = function(proxy, bounds) {
|
||||||
var container = this.src;
|
var container = this.src;
|
||||||
return XHR(proxy + "?url=" + container.src).then(documentFromHTML(container)).then(function(doc) {
|
return new Proxy(container.src, proxy, window.document).then(documentFromHTML(container)).then(function(doc) {
|
||||||
return createWindowClone(doc, container.ownerDocument, bounds.width, bounds.height, {});
|
return createWindowClone(doc, container.ownerDocument, bounds.width, bounds.height, {});
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
48
src/proxy.js
Normal file
48
src/proxy.js
Normal file
@ -0,0 +1,48 @@
|
|||||||
|
function Proxy(src, proxyUrl, document) {
|
||||||
|
var callback = createCallback(supportsCORS);
|
||||||
|
var url = createProxyUrl(proxyUrl, src, callback);
|
||||||
|
|
||||||
|
return supportsCORS ? XHR(url) : (jsonp(document, url, callback).then(function(response) {
|
||||||
|
return decode64(response.content);
|
||||||
|
}));
|
||||||
|
}
|
||||||
|
var proxyCount = 0;
|
||||||
|
|
||||||
|
var supportsCORS = ('withCredentials' in new XMLHttpRequest());
|
||||||
|
var supportsCORSImage = ('crossOrigin' in new Image());
|
||||||
|
|
||||||
|
function ProxyURL(src, proxyUrl, document) {
|
||||||
|
var callback = createCallback(supportsCORSImage);
|
||||||
|
var url = createProxyUrl(proxyUrl, src, callback);
|
||||||
|
return (supportsCORSImage ? Promise.resolve(url) : jsonp(document, url, callback).then(function(response) {
|
||||||
|
return "data:" + response.type + ";base64," + response.content;
|
||||||
|
}));
|
||||||
|
}
|
||||||
|
|
||||||
|
function jsonp(document, url, callback) {
|
||||||
|
return new Promise(function(resolve, reject) {
|
||||||
|
var s = document.createElement("script");
|
||||||
|
var cleanup = function() {
|
||||||
|
delete window.html2canvas.proxy[callback];
|
||||||
|
document.body.removeChild(s);
|
||||||
|
};
|
||||||
|
window.html2canvas.proxy[callback] = function(response) {
|
||||||
|
cleanup();
|
||||||
|
resolve(response);
|
||||||
|
};
|
||||||
|
s.src = url;
|
||||||
|
s.onerror = function(e) {
|
||||||
|
cleanup();
|
||||||
|
reject(e);
|
||||||
|
};
|
||||||
|
document.body.appendChild(s);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
function createCallback(useCORS) {
|
||||||
|
return !useCORS ? "html2canvas_" + Date.now() + "_" + (++proxyCount) + "_" + Math.round(Math.random() * 100000) : "";
|
||||||
|
}
|
||||||
|
|
||||||
|
function createProxyUrl(proxyUrl, src, callback) {
|
||||||
|
return proxyUrl + "?url=" + encodeURIComponent(src) + (callback.length ? "&callback=html2canvas.proxy." + callback : "");
|
||||||
|
}
|
@ -1,38 +1,18 @@
|
|||||||
function ProxyImageContainer(src, proxy) {
|
function ProxyImageContainer(src, proxy) {
|
||||||
var callbackName = "html2canvas_" + proxyImageCount++;
|
|
||||||
var script = document.createElement("script");
|
var script = document.createElement("script");
|
||||||
var link = document.createElement("a");
|
var link = document.createElement("a");
|
||||||
link.href = src;
|
link.href = src;
|
||||||
src = link.href;
|
src = link.href;
|
||||||
var requestUrl = proxy + ((proxy.indexOf("?") > -1) ? "&" : "?" ) + 'url=' + encodeURIComponent(src) + '&callback=' + callbackName;
|
|
||||||
this.src = src;
|
this.src = src;
|
||||||
this.image = new Image();
|
this.image = new Image();
|
||||||
var self = this;
|
var self = this;
|
||||||
this.promise = new Promise(function(resolve, reject) {
|
this.promise = new Promise(function(resolve, reject) {
|
||||||
|
self.image.crossOrigin = "Anonymous";
|
||||||
self.image.onload = resolve;
|
self.image.onload = resolve;
|
||||||
self.image.onerror = reject;
|
self.image.onerror = reject;
|
||||||
|
|
||||||
window[callbackName] = function(a){
|
new ProxyURL(src, proxy, document).then(function(url) {
|
||||||
if (a.substring(0,6) === "error:"){
|
self.image.src = url;
|
||||||
reject();
|
})['catch'](reject);
|
||||||
} else {
|
|
||||||
self.image.src = a;
|
|
||||||
}
|
|
||||||
window[callbackName] = undefined; // to work with IE<9 // NOTE: that the undefined callback property-name still exists on the window object (for IE<9)
|
|
||||||
try {
|
|
||||||
delete window[callbackName]; // for all browser that support this
|
|
||||||
} catch(ex) {}
|
|
||||||
script.parentNode.removeChild(script);
|
|
||||||
};
|
|
||||||
script.setAttribute("type", "text/javascript");
|
|
||||||
script.setAttribute("src", requestUrl);
|
|
||||||
document.body.appendChild(script);
|
|
||||||
})['catch'](function() {
|
|
||||||
var dummy = new DummyImageContainer(src);
|
|
||||||
return dummy.promise.then(function(image) {
|
|
||||||
self.image = image;
|
|
||||||
});
|
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
var proxyImageCount = 0;
|
|
||||||
|
@ -8,6 +8,6 @@
|
|||||||
<script type="text/javascript" src="../test.js"></script>
|
<script type="text/javascript" src="../test.js"></script>
|
||||||
</head>
|
</head>
|
||||||
<body>
|
<body>
|
||||||
<iframe src="http://hertzen.com/" width="500" height="500"></iframe>
|
<iframe src="http://hertzen.com/" width="800" height="800"></iframe>
|
||||||
</body>
|
</body>
|
||||||
</html>
|
</html>
|
||||||
|
@ -12,7 +12,7 @@ var h2cSelector, h2cOptions;
|
|||||||
}
|
}
|
||||||
|
|
||||||
var sources = ['log', 'punycode/punycode', 'core', 'nodecontainer', 'stackingcontext', 'textcontainer', 'support', 'imagecontainer', 'dummyimagecontainer', 'proxyimagecontainer', 'gradientcontainer',
|
var sources = ['log', 'punycode/punycode', 'core', 'nodecontainer', 'stackingcontext', 'textcontainer', 'support', 'imagecontainer', 'dummyimagecontainer', 'proxyimagecontainer', 'gradientcontainer',
|
||||||
'lineargradientcontainer', 'webkitgradientcontainer', 'svgcontainer', 'svgnodecontainer', 'imageloader', 'nodeparser', 'font', 'fontmetrics', 'renderer', 'promise', 'xhr', 'framecontainer', 'renderers/canvas'];
|
'lineargradientcontainer', 'webkitgradientcontainer', 'svgcontainer', 'svgnodecontainer', 'imageloader', 'nodeparser', 'font', 'fontmetrics', 'renderer', 'promise', 'xhr', 'framecontainer', 'proxy', 'renderers/canvas'];
|
||||||
|
|
||||||
['/tests/assets/jquery-1.6.2'].concat(window.location.search === "?selenium" ? ['/dist/html2canvas'] : sources.map(function(src) { return '/src/' + src; })).forEach(appendScript);
|
['/tests/assets/jquery-1.6.2'].concat(window.location.search === "?selenium" ? ['/dist/html2canvas'] : sources.map(function(src) { return '/src/' + src; })).forEach(appendScript);
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user