diff --git a/src/Parse.js b/src/Parse.js
index 85f2105..de6ec6a 100644
--- a/src/Parse.js
+++ b/src/Parse.js
@@ -7,7 +7,14 @@ _html2canvas.Parse = function (images, options) {
support = _html2canvas.Util.Support(options, doc),
ignoreElementsRegExp = new RegExp("(" + options.ignoreElements + ")"),
body = doc.body,
- getCSS = _html2canvas.Util.getCSS;
+ getCSS = _html2canvas.Util.getCSS,
+ pseudoHide = "___html2canvas___pseudoelement",
+ hidePseudoElements = doc.createElement('style');
+
+ hidePseudoElements.innerHTML = '.' + pseudoHide + '-before:before { content: "" !important; display: none !important; }' +
+ '.' + pseudoHide + '-after:after { content: "" !important; display: none !important; }';
+
+ body.appendChild(hidePseudoElements);
images = images || {};
@@ -750,6 +757,64 @@ _html2canvas.Parse = function (images, options) {
numDraws+=1;
}
+ function getPseudoElement(el, which) {
+ var elStyle = window.getComputedStyle(el, which);
+ if(!elStyle || !elStyle.content || elStyle.content === "none" || elStyle.content === "-moz-alt-content") {
+ return;
+ }
+ var content = elStyle.content + '',
+ first = content.substr( 0, 1 );
+ //strips quotes
+ if(first === content.substr( content.length - 1 ) && first.match(/'|"/)) {
+ content = content.substr( 1, content.length - 2 );
+ }
+
+ var isImage = content.substr( 0, 3 ) === 'url',
+ elps = document.createElement( isImage ? 'img' : 'span' );
+
+ elps.className = pseudoHide + "-before " + pseudoHide + "-after";
+
+ Object.keys(elStyle).filter(indexedProperty).forEach(function(prop) {
+ elps.style[prop] = elStyle[prop];
+ });
+
+ if(isImage) {
+ elps.src = _html2canvas.Util.parseBackgroundImage(content)[0].args[0];
+ } else {
+ elps.innerHTML = content;
+ }
+ return elps;
+ }
+
+ function indexedProperty(property) {
+ return (isNaN(window.parseInt(property, 10)));
+ }
+
+ function injectPseudoElements(el, stack) {
+ var before = getPseudoElement(el, ':before'),
+ after = getPseudoElement(el, ':after');
+ if(!before && !after) {
+ return;
+ }
+
+ if(before) {
+ el.className += " " + pseudoHide + "-before";
+ el.parentNode.insertBefore(before, el);
+ parseElement(before, stack, true);
+ el.parentNode.removeChild(before);
+ el.className = el.className.replace(pseudoHide + "-before", "").trim();
+ }
+
+ if (after) {
+ el.className += " " + pseudoHide + "-after";
+ el.appendChild(after);
+ parseElement(after, stack, true);
+ el.removeChild(after);
+ el.className = el.className.replace(pseudoHide + "-after", "").trim();
+ }
+
+ }
+
function renderBackgroundRepeat(ctx, image, backgroundPosition, bounds) {
var offsetX = Math.round(bounds.left + backgroundPosition.left),
offsetY = Math.round(bounds.top + backgroundPosition.top);
@@ -787,7 +852,9 @@ _html2canvas.Parse = function (images, options) {
function renderBackgroundRepeating(el, bounds, ctx, image, imageIndex) {
var backgroundSize = _html2canvas.Util.BackgroundSize(el, bounds, image, imageIndex),
backgroundPosition = _html2canvas.Util.BackgroundPosition(el, bounds, image, imageIndex, backgroundSize),
- backgroundRepeat = getCSS(el, "backgroundRepeat").split(",").map(function(value) { return value.trim(); });
+ backgroundRepeat = getCSS(el, "backgroundRepeat").split(",").map(function(value) {
+ return value.trim();
+ });
image = resizeImage(image, backgroundSize);
@@ -810,7 +877,12 @@ _html2canvas.Parse = function (images, options) {
break;
default:
- renderBackgroundRepeat(ctx, image, backgroundPosition, { top: bounds.top, left: bounds.left, width: image.width, height: image.height });
+ renderBackgroundRepeat(ctx, image, backgroundPosition, {
+ top: bounds.top,
+ left: bounds.left,
+ width: image.width,
+ height: image.height
+ });
break;
}
}
@@ -829,8 +901,8 @@ _html2canvas.Parse = function (images, options) {
}
var key = backgroundImage.method === 'url' ?
- backgroundImage.args[0] :
- backgroundImage.value;
+ backgroundImage.args[0] :
+ backgroundImage.value;
image = loadImage(key);
@@ -899,7 +971,7 @@ _html2canvas.Parse = function (images, options) {
return backgroundBounds;
}
- function renderElement(element, parentStack){
+ function renderElement(element, parentStack, pseudoElement){
var bounds = _html2canvas.Util.Bounds(element),
image,
bgcolor = (ignoreElementsRegExp.test(element.nodeName)) ? "#efefef" : getCSS(element, "backgroundColor"),
@@ -925,6 +997,10 @@ _html2canvas.Parse = function (images, options) {
renderBorders(ctx, border.args, border.color);
});
+ if (!pseudoElement) {
+ injectPseudoElements(element, stack);
+ }
+
switch(element.nodeName){
case "IMG":
if ((image = loadImage(element.getAttribute('src')))) {
@@ -965,14 +1041,14 @@ _html2canvas.Parse = function (images, options) {
return (getCSS(element, 'display') !== "none" && getCSS(element, 'visibility') !== "hidden" && !element.hasAttribute("data-html2canvas-ignore"));
}
- function parseElement (el, stack) {
+ function parseElement (el, stack, pseudoElement) {
if (isElementVisible(el)) {
- stack = renderElement(el, stack) || stack;
+ stack = renderElement(el, stack, pseudoElement) || stack;
if (!ignoreElementsRegExp.test(el.nodeName)) {
_html2canvas.Util.Children(el).forEach(function(node) {
if (node.nodeType === 1) {
- parseElement(node, stack);
+ parseElement(node, stack, pseudoElement);
} else if (node.nodeType === 3) {
renderText(el, node, stack);
}
@@ -1059,7 +1135,7 @@ _html2canvas.Parse = function (images, options) {
});
stack.backgroundColor = getCSS(document.documentElement, "backgroundColor");
-
+ body.removeChild(hidePseudoElements);
return stack;
}
diff --git a/src/Preload.js b/src/Preload.js
index e49d84f..609e5f1 100644
--- a/src/Preload.js
+++ b/src/Preload.js
@@ -89,16 +89,64 @@ _html2canvas.Preload = function( options ) {
}
- function getImages (el) {
- el.__html2canvas__id = uid++;
+ function loadPseudoElement(element, type) {
+ var style = window.getComputedStyle(element, type),
+ content = style.content;
+ if (content.substr(0, 3) === 'url') {
+ methods.loadImage(_html2canvas.Util.parseBackgroundImage(content)[0].args[0]);
+ }
+ loadBackgroundImages(style.backgroundImage, element);
+ }
- var contents = _html2canvas.Util.Children(el),
- i,
- background_image,
- background_images,
+ function loadPseudoElementImages(element) {
+ loadPseudoElement(element, ":before");
+ loadPseudoElement(element, ":after");
+ }
+
+ function loadBackgroundImages(background_image, el) {
+ var background_images,
src,
img,
- bounds,
+ bounds;
+ // opera throws exception on external-content.html
+
+ background_images = _html2canvas.Util.parseBackgroundImage(background_image);
+ for(var imageIndex = background_images.length; imageIndex-- > 0;) {
+ background_image = background_images[imageIndex];
+
+ if(!background_image ||
+ !background_image.method ||
+ !background_image.args ||
+ background_image.args.length === 0 ) {
+ continue;
+ }
+ if (background_image.method === 'url') {
+ src = background_image.args[0];
+ methods.loadImage(src);
+
+ } else if( background_image.method.match( /\-?gradient$/ ) ) {
+ if(bounds === undefined) {
+ bounds = _html2canvas.Util.Bounds(el);
+ }
+
+ img = _html2canvas.Generate.Gradient( background_image.value, bounds);
+
+ if ( img !== undefined ){
+ images[background_image.value] = {
+ img: img,
+ succeeded: true
+ };
+ images.numTotal++;
+ images.numLoaded++;
+ start();
+ }
+ }
+ }
+ }
+
+ function getImages (el) {
+ var contents = _html2canvas.Util.Children(el),
+ i,
elNodeType = false;
// Firefox fails with permission denied on pages with iframes
@@ -117,46 +165,14 @@ _html2canvas.Preload = function( options ) {
h2clog("html2canvas: failed to access some element's nodeType - Exception: " + ex.message);
}
- if (elNodeType === 1 || elNodeType === undefined){
-
- // opera throws exception on external-content.html
+ if (elNodeType === 1 || elNodeType === undefined) {
+ loadPseudoElementImages(el);
try {
- background_image = _html2canvas.Util.getCSS(el, 'backgroundImage');
+ loadBackgroundImages(_html2canvas.Util.getCSS(el, 'backgroundImage'), el);
} catch(e) {
h2clog("html2canvas: failed to get background-image - Exception: " + e.message);
}
- background_images = _html2canvas.Util.parseBackgroundImage(background_image);
- for(var imageIndex = background_images.length; imageIndex-- > 0;) {
- background_image = background_images[imageIndex];
-
- if(!background_image ||
- !background_image.method ||
- !background_image.args ||
- background_image.args.length === 0 ) {
- continue;
- }
- if (background_image.method === 'url') {
- src = background_image.args[0];
- methods.loadImage(src);
-
- } else if( background_image.method.match( /\-?gradient$/ ) ) {
- if(bounds === undefined) {
- bounds = _html2canvas.Util.Bounds( el );
- }
-
- img = _html2canvas.Generate.Gradient( background_image.value, bounds);
-
- if ( img !== undefined ){
- images[background_image.value] = {
- img: img,
- succeeded: true
- };
- images.numTotal++;
- images.numLoaded++;
- start();
- }
- }
- }
+ loadBackgroundImages(el);
}
}
@@ -211,94 +227,6 @@ _html2canvas.Preload = function( options ) {
*/
}
- var uid = 0, injectStyle;
- function injectPseudoElements(el) {
- if(!_html2canvas.Util.isElementVisible(el)) {
- return;
- }
-
- var before = getPseudoElement(el, ':before'),
- after = getPseudoElement(el, ':after');
- if(!before && !after) {
- return;
- }
- if(!el.id) {
- el.id = '__html2canvas__' + (uid++);
- }
- if(!injectStyle) {
- injectStyle = document.createElement('style');
- }
-
- if(before) {
- el.__html2canvas_before = before;
- injectStyle.innerHTML += '#' + el.id + ':before { content: "" !important; display: none !important; }\n';
- if(el.childNodes.length > 0) {
- el.insertBefore(before, el.childNodes[0]);
- } else {
- el.appendChild(before);
- }
- }
-
- if (after) {
- el.__html2canvas_after = after;
- injectStyle.innerHTML += '#' + el.id + ':after { content: "" !important; display: none !important; }\n';
- el.appendChild(after);
- }
- }
-
- function removePseudoElements(el) {
- var before = el.__html2canvas_before,
- after = el.__html2canvas_after;
- if(before) {
- el.__html2canvas_before = undefined;
- el.removeChild(before);
- }
- if(after) {
- el.__html2canvas_after = undefined;
- el.removeChild(after);
- }
- }
-
- function cleanupPseudoElements(){
- if(!injectStyle) {
- return;
- }
- injectStyle.parentNode.removeChild(injectStyle);
- injectStyle = undefined;
-
- [].slice.apply(element.all || element.getElementsByTagName('*'))
- .forEach(removePseudoElements);
- }
-
- function indexedProperty(property) {
- return (!isNaN(window.parseInt(property, 10)));
- }
-
- function getPseudoElement(el, which) {
- var elStyle = window.getComputedStyle(el, which);
- if(!elStyle || !elStyle.content || elStyle.content === "none" || elStyle.content === "-moz-alt-content") { return; }
- var content = elStyle.content + '',
- first = content.substr( 0, 1 );
- //strips quotes
- if(first === content.substr( content.length - 1 ) && first.match(/'|"/)) {
- content = content.substr( 1, content.length - 2 );
- }
-
- var isImage = content.substr( 0, 3 ) === 'url',
- elps = document.createElement( isImage ? 'img' : 'span' );
-
- elps.className = '__html2canvas__' + which.substr(1);
- Object.keys(elStyle).filter(indexedProperty).forEach(function(prop) {
- elps.style[prop] = elStyle[prop];
- });
- if(isImage) {
- elps.src = _html2canvas.Util.parseBackgroundImage(content)[0].args[0];
- } else {
- elps.innerHTML = content;
- }
- return elps;
- }
-
methods = {
loadImage: function( src ) {
var img, imageObj;
@@ -392,15 +320,12 @@ _html2canvas.Preload = function( options ) {
start();
}
}
-
- cleanupPseudoElements();
},
renderingDone: function() {
if (timeoutTimer) {
window.clearTimeout(timeoutTimer);
}
- cleanupPseudoElements();
}
};
@@ -408,17 +333,10 @@ _html2canvas.Preload = function( options ) {
timeoutTimer = window.setTimeout(methods.cleanupDOM, options.timeout);
}
- [].slice.apply(element.all || element.getElementsByTagName('*'))
- .forEach(injectPseudoElements);
- if(injectStyle) {
- element.appendChild(injectStyle);
- }
-
-
h2clog('html2canvas: Preload starts: finding background-images');
images.firstRun = true;
- getImages( element );
+ getImages(element);
h2clog('html2canvas: Preload: Finding images');
// load images
diff --git a/src/Util.js b/src/Util.js
index 74b5f27..a77c35b 100644
--- a/src/Util.js
+++ b/src/Util.js
@@ -8,7 +8,7 @@ window.html2canvas = function(elements, opts) {
background: "#fff",
// preload options
- proxy: "",
+ proxy: null,
timeout: 0, // no timeout
useCORS: false, // try to load images as CORS (where available), before falling back to proxy
allowTaint: false, // whether to allow images to taint the canvas, won't need proxy if set to true
@@ -18,7 +18,7 @@ window.html2canvas = function(elements, opts) {
ignoreElements: "IFRAME|OBJECT|PARAM",
useOverflow: true,
letterRendering: false,
- chinese: false,
+ chinese: false,
// render options
diff --git a/tests/readme.md b/tests/readme.md
index 51db39c..2ffdd03 100644
--- a/tests/readme.md
+++ b/tests/readme.md
@@ -2,7 +2,7 @@