mirror of
https://github.com/niklasvh/html2canvas.git
synced 2023-08-10 21:13:10 +03:00
Add support for pseudoelements
This commit is contained in:
parent
b5891c49b4
commit
5d20493f46
@ -14,5 +14,5 @@
|
|||||||
"jQuery": true
|
"jQuery": true
|
||||||
},
|
},
|
||||||
"predef": ["NodeParser", "NodeContainer", "StackingContext", "TextContainer", "ImageLoader", "CanvasRenderer", "Renderer", "Support", "bind", "Promise",
|
"predef": ["NodeParser", "NodeContainer", "StackingContext", "TextContainer", "ImageLoader", "CanvasRenderer", "Renderer", "Support", "bind", "Promise",
|
||||||
"ImageContainer", "ProxyImageContainer", "DummyImageContainer", "Font", "FontMetrics", "GradientContainer", "LinearGradientContainer", "WebkitGradientContainer", "log", "smallImage"]
|
"ImageContainer", "ProxyImageContainer", "DummyImageContainer", "Font", "FontMetrics", "GradientContainer", "LinearGradientContainer", "WebkitGradientContainer", "log", "smallImage", "parseBackgrounds"]
|
||||||
}
|
}
|
||||||
|
@ -363,12 +363,16 @@ NodeContainer.prototype.isElementVisible = function() {
|
|||||||
|
|
||||||
NodeContainer.prototype.css = function(attribute) {
|
NodeContainer.prototype.css = function(attribute) {
|
||||||
if (!this.computedStyles) {
|
if (!this.computedStyles) {
|
||||||
this.computedStyles = this.node.ownerDocument.defaultView.getComputedStyle(this.node, null);
|
this.computedStyles = this.computedStyle(null);
|
||||||
}
|
}
|
||||||
|
|
||||||
return this.styles[attribute] || (this.styles[attribute] = this.computedStyles[attribute]);
|
return this.styles[attribute] || (this.styles[attribute] = this.computedStyles[attribute]);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
NodeContainer.prototype.computedStyle = function(type) {
|
||||||
|
return this.node.ownerDocument.defaultView.getComputedStyle(this.node, type);
|
||||||
|
};
|
||||||
|
|
||||||
NodeContainer.prototype.cssInt = function(attribute) {
|
NodeContainer.prototype.cssInt = function(attribute) {
|
||||||
var value = parseInt(this.css(attribute), 10);
|
var value = parseInt(this.css(attribute), 10);
|
||||||
return (isNaN(value)) ? 0 : value; // borders in old IE are throwing 'medium' for demo.html
|
return (isNaN(value)) ? 0 : value; // borders in old IE are throwing 'medium' for demo.html
|
||||||
@ -393,103 +397,6 @@ NodeContainer.prototype.fontWeight = function() {
|
|||||||
};
|
};
|
||||||
|
|
||||||
NodeContainer.prototype.parseBackgroundImages = function() {
|
NodeContainer.prototype.parseBackgroundImages = function() {
|
||||||
function parseBackgrounds(backgroundImage) {
|
|
||||||
var whitespace = ' \r\n\t',
|
|
||||||
method, definition, prefix, prefix_i, block, results = [],
|
|
||||||
mode = 0, numParen = 0, quote, args;
|
|
||||||
var appendResult = function() {
|
|
||||||
if(method) {
|
|
||||||
if (definition.substr(0, 1) === '"') {
|
|
||||||
definition = definition.substr(1, definition.length - 2);
|
|
||||||
}
|
|
||||||
if (definition) {
|
|
||||||
args.push(definition);
|
|
||||||
}
|
|
||||||
if (method.substr(0, 1) === '-' && (prefix_i = method.indexOf('-', 1 ) + 1) > 0) {
|
|
||||||
prefix = method.substr(0, prefix_i);
|
|
||||||
method = method.substr(prefix_i);
|
|
||||||
}
|
|
||||||
results.push({
|
|
||||||
prefix: prefix,
|
|
||||||
method: method.toLowerCase(),
|
|
||||||
value: block,
|
|
||||||
args: args,
|
|
||||||
image: null
|
|
||||||
});
|
|
||||||
}
|
|
||||||
args = [];
|
|
||||||
method = prefix = definition = block = '';
|
|
||||||
};
|
|
||||||
args = [];
|
|
||||||
method = prefix = definition = block = '';
|
|
||||||
backgroundImage.split("").forEach(function(c) {
|
|
||||||
if (mode === 0 && whitespace.indexOf(c) > -1) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
switch(c) {
|
|
||||||
case '"':
|
|
||||||
if(!quote) {
|
|
||||||
quote = c;
|
|
||||||
}
|
|
||||||
else if(quote === c) {
|
|
||||||
quote = null;
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
case '(':
|
|
||||||
if(quote) {
|
|
||||||
break;
|
|
||||||
} else if(mode === 0) {
|
|
||||||
mode = 1;
|
|
||||||
block += c;
|
|
||||||
return;
|
|
||||||
} else {
|
|
||||||
numParen++;
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
case ')':
|
|
||||||
if (quote) {
|
|
||||||
break;
|
|
||||||
} else if(mode === 1) {
|
|
||||||
if(numParen === 0) {
|
|
||||||
mode = 0;
|
|
||||||
block += c;
|
|
||||||
appendResult();
|
|
||||||
return;
|
|
||||||
} else {
|
|
||||||
numParen--;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
|
|
||||||
case ',':
|
|
||||||
if (quote) {
|
|
||||||
break;
|
|
||||||
} else if(mode === 0) {
|
|
||||||
appendResult();
|
|
||||||
return;
|
|
||||||
} else if (mode === 1) {
|
|
||||||
if (numParen === 0 && !method.match(/^url$/i)) {
|
|
||||||
args.push(definition);
|
|
||||||
definition = '';
|
|
||||||
block += c;
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
block += c;
|
|
||||||
if (mode === 0) {
|
|
||||||
method += c;
|
|
||||||
} else {
|
|
||||||
definition += c;
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
appendResult();
|
|
||||||
return results;
|
|
||||||
}
|
|
||||||
|
|
||||||
return this.backgroundImages || (this.backgroundImages = parseBackgrounds(this.css("backgroundImage")));
|
return this.backgroundImages || (this.backgroundImages = parseBackgrounds(this.css("backgroundImage")));
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -588,6 +495,103 @@ function isPercentage(value) {
|
|||||||
return value.toString().indexOf("%") !== -1;
|
return value.toString().indexOf("%") !== -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function parseBackgrounds(backgroundImage) {
|
||||||
|
var whitespace = ' \r\n\t',
|
||||||
|
method, definition, prefix, prefix_i, block, results = [],
|
||||||
|
mode = 0, numParen = 0, quote, args;
|
||||||
|
var appendResult = function() {
|
||||||
|
if(method) {
|
||||||
|
if (definition.substr(0, 1) === '"') {
|
||||||
|
definition = definition.substr(1, definition.length - 2);
|
||||||
|
}
|
||||||
|
if (definition) {
|
||||||
|
args.push(definition);
|
||||||
|
}
|
||||||
|
if (method.substr(0, 1) === '-' && (prefix_i = method.indexOf('-', 1 ) + 1) > 0) {
|
||||||
|
prefix = method.substr(0, prefix_i);
|
||||||
|
method = method.substr(prefix_i);
|
||||||
|
}
|
||||||
|
results.push({
|
||||||
|
prefix: prefix,
|
||||||
|
method: method.toLowerCase(),
|
||||||
|
value: block,
|
||||||
|
args: args,
|
||||||
|
image: null
|
||||||
|
});
|
||||||
|
}
|
||||||
|
args = [];
|
||||||
|
method = prefix = definition = block = '';
|
||||||
|
};
|
||||||
|
args = [];
|
||||||
|
method = prefix = definition = block = '';
|
||||||
|
backgroundImage.split("").forEach(function(c) {
|
||||||
|
if (mode === 0 && whitespace.indexOf(c) > -1) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
switch(c) {
|
||||||
|
case '"':
|
||||||
|
if(!quote) {
|
||||||
|
quote = c;
|
||||||
|
}
|
||||||
|
else if(quote === c) {
|
||||||
|
quote = null;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case '(':
|
||||||
|
if(quote) {
|
||||||
|
break;
|
||||||
|
} else if(mode === 0) {
|
||||||
|
mode = 1;
|
||||||
|
block += c;
|
||||||
|
return;
|
||||||
|
} else {
|
||||||
|
numParen++;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case ')':
|
||||||
|
if (quote) {
|
||||||
|
break;
|
||||||
|
} else if(mode === 1) {
|
||||||
|
if(numParen === 0) {
|
||||||
|
mode = 0;
|
||||||
|
block += c;
|
||||||
|
appendResult();
|
||||||
|
return;
|
||||||
|
} else {
|
||||||
|
numParen--;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
|
case ',':
|
||||||
|
if (quote) {
|
||||||
|
break;
|
||||||
|
} else if(mode === 0) {
|
||||||
|
appendResult();
|
||||||
|
return;
|
||||||
|
} else if (mode === 1) {
|
||||||
|
if (numParen === 0 && !method.match(/^url$/i)) {
|
||||||
|
args.push(definition);
|
||||||
|
definition = '';
|
||||||
|
block += c;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
block += c;
|
||||||
|
if (mode === 0) {
|
||||||
|
method += c;
|
||||||
|
} else {
|
||||||
|
definition += c;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
appendResult();
|
||||||
|
return results;
|
||||||
|
}
|
||||||
|
|
||||||
function NodeParser(element, renderer, support, imageLoader, options) {
|
function NodeParser(element, renderer, support, imageLoader, options) {
|
||||||
log("Starting NodeParser");
|
log("Starting NodeParser");
|
||||||
this.renderer = renderer;
|
this.renderer = renderer;
|
||||||
@ -597,9 +601,10 @@ function NodeParser(element, renderer, support, imageLoader, options) {
|
|||||||
this.stack = new StackingContext(true, 1, element.ownerDocument, null);
|
this.stack = new StackingContext(true, 1, element.ownerDocument, null);
|
||||||
var parent = new NodeContainer(element, null);
|
var parent = new NodeContainer(element, null);
|
||||||
parent.visibile = parent.isElementVisible();
|
parent.visibile = parent.isElementVisible();
|
||||||
this.nodes = [parent].concat(this.getChildren(parent)).filter(function(container) {
|
this.createPseudoHideStyles(element.ownerDocument);
|
||||||
|
this.nodes = flatten([parent].concat(this.getChildren(parent)).filter(function(container) {
|
||||||
return container.visible = container.isElementVisible();
|
return container.visible = container.isElementVisible();
|
||||||
});
|
}).map(this.getPseudoElements, this));
|
||||||
this.fontMetrics = new FontMetrics();
|
this.fontMetrics = new FontMetrics();
|
||||||
log("Fetched nodes");
|
log("Fetched nodes");
|
||||||
this.images = imageLoader.fetch(this.nodes.filter(isElement));
|
this.images = imageLoader.fetch(this.nodes.filter(isElement));
|
||||||
@ -614,6 +619,68 @@ function NodeParser(element, renderer, support, imageLoader, options) {
|
|||||||
}, this));
|
}, this));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
NodeParser.prototype.createPseudoHideStyles = function(document) {
|
||||||
|
var hidePseudoElements = document.createElement('style');
|
||||||
|
hidePseudoElements.innerHTML = '.' + this.pseudoHideClass + ':before { content: "" !important; display: none !important; }' +
|
||||||
|
'.' + this.pseudoHideClass + ':after { content: "" !important; display: none !important; }';
|
||||||
|
document.body.appendChild(hidePseudoElements);
|
||||||
|
};
|
||||||
|
|
||||||
|
NodeParser.prototype.getPseudoElements = function(container) {
|
||||||
|
var nodes = [[container]];
|
||||||
|
if (container instanceof NodeContainer) {
|
||||||
|
var before = this.getPseudoElement(container, ":before");
|
||||||
|
var after = this.getPseudoElement(container, ":after");
|
||||||
|
|
||||||
|
if (before) {
|
||||||
|
container.node.insertBefore(before[0].node, container.node.firstChild);
|
||||||
|
nodes.push(before);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (after) {
|
||||||
|
container.node.appendChild(after[0].node);
|
||||||
|
nodes.push(after);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (before || after) {
|
||||||
|
container.node.className += " " + this.pseudoHideClass;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return flatten(nodes);
|
||||||
|
};
|
||||||
|
|
||||||
|
NodeParser.prototype.getPseudoElement = function(container, type) {
|
||||||
|
var style = container.computedStyle(type);
|
||||||
|
if(!style || !style.content || style.content === "none" || style.content === "-moz-alt-content" || style.display === "none") {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
var content = stripQuotes(style.content);
|
||||||
|
var isImage = content.substr(0, 3) === 'url';
|
||||||
|
var pseudoNode = document.createElement(isImage ? 'img' : 'html2canvaspseudoelement');
|
||||||
|
var pseudoContainer = new NodeContainer(pseudoNode, container);
|
||||||
|
Object.keys(style).filter(indexedProperty).forEach(function(property) {
|
||||||
|
// Prevent assigning of read only CSS Rules, ex. length, parentRule
|
||||||
|
try {
|
||||||
|
pseudoNode.style[property] = style[property];
|
||||||
|
} catch (e) {
|
||||||
|
log('Tried to assign readonly property ', property, 'Error:', e);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
pseudoNode.className = this.pseudoHideClass;
|
||||||
|
|
||||||
|
if (isImage) {
|
||||||
|
pseudoNode.src = parseBackgrounds(content)[0].args[0];
|
||||||
|
return [pseudoContainer];
|
||||||
|
} else {
|
||||||
|
var text = document.createTextNode(content);
|
||||||
|
pseudoNode.appendChild(text);
|
||||||
|
return [pseudoContainer, new TextContainer(text, pseudoContainer)];
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
NodeParser.prototype.getChildren = function(parentContainer) {
|
NodeParser.prototype.getChildren = function(parentContainer) {
|
||||||
return flatten([].filter.call(parentContainer.node.childNodes, renderableNode).map(function(node) {
|
return flatten([].filter.call(parentContainer.node.childNodes, renderableNode).map(function(node) {
|
||||||
var container = [node.nodeType === Node.TEXT_NODE ? new TextContainer(node, parentContainer) : new NodeContainer(node, parentContainer)].filter(nonIgnoredElement);
|
var container = [node.nodeType === Node.TEXT_NODE ? new TextContainer(node, parentContainer) : new NodeContainer(node, parentContainer)].filter(nonIgnoredElement);
|
||||||
@ -918,6 +985,8 @@ NodeParser.prototype.parseBackgroundClip = function(container, borderPoints, bor
|
|||||||
return borderArgs;
|
return borderArgs;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
NodeParser.prototype.pseudoHideClass = "___html2canvas___pseudoelement";
|
||||||
|
|
||||||
function getCurvePoints(x, y, r1, r2) {
|
function getCurvePoints(x, y, r1, r2) {
|
||||||
var kappa = 4 * ((Math.sqrt(2) - 1) / 3);
|
var kappa = 4 * ((Math.sqrt(2) - 1) / 3);
|
||||||
var ox = (r1) * kappa, // control point offset horizontal
|
var ox = (r1) * kappa, // control point offset horizontal
|
||||||
@ -1137,6 +1206,15 @@ function flatten(arrays) {
|
|||||||
return [].concat.apply([], arrays);
|
return [].concat.apply([], arrays);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function stripQuotes(content) {
|
||||||
|
var first = content.substr(0, 1);
|
||||||
|
return (first === content.substr(content.length - 1) && first.match(/'|"/)) ? content.substr(1, content.length - 2) : content;
|
||||||
|
}
|
||||||
|
|
||||||
|
function indexedProperty(property) {
|
||||||
|
return (isNaN(parseInt(property, 10)));
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
Copyright (c) 2013 Yehuda Katz, Tom Dale, and contributors
|
Copyright (c) 2013 Yehuda Katz, Tom Dale, and contributors
|
||||||
|
|
||||||
|
3
build/html2canvas.min.js
vendored
3
build/html2canvas.min.js
vendored
File diff suppressed because one or more lines are too long
@ -20,12 +20,16 @@ NodeContainer.prototype.isElementVisible = function() {
|
|||||||
|
|
||||||
NodeContainer.prototype.css = function(attribute) {
|
NodeContainer.prototype.css = function(attribute) {
|
||||||
if (!this.computedStyles) {
|
if (!this.computedStyles) {
|
||||||
this.computedStyles = this.node.ownerDocument.defaultView.getComputedStyle(this.node, null);
|
this.computedStyles = this.computedStyle(null);
|
||||||
}
|
}
|
||||||
|
|
||||||
return this.styles[attribute] || (this.styles[attribute] = this.computedStyles[attribute]);
|
return this.styles[attribute] || (this.styles[attribute] = this.computedStyles[attribute]);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
NodeContainer.prototype.computedStyle = function(type) {
|
||||||
|
return this.node.ownerDocument.defaultView.getComputedStyle(this.node, type);
|
||||||
|
};
|
||||||
|
|
||||||
NodeContainer.prototype.cssInt = function(attribute) {
|
NodeContainer.prototype.cssInt = function(attribute) {
|
||||||
var value = parseInt(this.css(attribute), 10);
|
var value = parseInt(this.css(attribute), 10);
|
||||||
return (isNaN(value)) ? 0 : value; // borders in old IE are throwing 'medium' for demo.html
|
return (isNaN(value)) ? 0 : value; // borders in old IE are throwing 'medium' for demo.html
|
||||||
@ -50,103 +54,6 @@ NodeContainer.prototype.fontWeight = function() {
|
|||||||
};
|
};
|
||||||
|
|
||||||
NodeContainer.prototype.parseBackgroundImages = function() {
|
NodeContainer.prototype.parseBackgroundImages = function() {
|
||||||
function parseBackgrounds(backgroundImage) {
|
|
||||||
var whitespace = ' \r\n\t',
|
|
||||||
method, definition, prefix, prefix_i, block, results = [],
|
|
||||||
mode = 0, numParen = 0, quote, args;
|
|
||||||
var appendResult = function() {
|
|
||||||
if(method) {
|
|
||||||
if (definition.substr(0, 1) === '"') {
|
|
||||||
definition = definition.substr(1, definition.length - 2);
|
|
||||||
}
|
|
||||||
if (definition) {
|
|
||||||
args.push(definition);
|
|
||||||
}
|
|
||||||
if (method.substr(0, 1) === '-' && (prefix_i = method.indexOf('-', 1 ) + 1) > 0) {
|
|
||||||
prefix = method.substr(0, prefix_i);
|
|
||||||
method = method.substr(prefix_i);
|
|
||||||
}
|
|
||||||
results.push({
|
|
||||||
prefix: prefix,
|
|
||||||
method: method.toLowerCase(),
|
|
||||||
value: block,
|
|
||||||
args: args,
|
|
||||||
image: null
|
|
||||||
});
|
|
||||||
}
|
|
||||||
args = [];
|
|
||||||
method = prefix = definition = block = '';
|
|
||||||
};
|
|
||||||
args = [];
|
|
||||||
method = prefix = definition = block = '';
|
|
||||||
backgroundImage.split("").forEach(function(c) {
|
|
||||||
if (mode === 0 && whitespace.indexOf(c) > -1) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
switch(c) {
|
|
||||||
case '"':
|
|
||||||
if(!quote) {
|
|
||||||
quote = c;
|
|
||||||
}
|
|
||||||
else if(quote === c) {
|
|
||||||
quote = null;
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
case '(':
|
|
||||||
if(quote) {
|
|
||||||
break;
|
|
||||||
} else if(mode === 0) {
|
|
||||||
mode = 1;
|
|
||||||
block += c;
|
|
||||||
return;
|
|
||||||
} else {
|
|
||||||
numParen++;
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
case ')':
|
|
||||||
if (quote) {
|
|
||||||
break;
|
|
||||||
} else if(mode === 1) {
|
|
||||||
if(numParen === 0) {
|
|
||||||
mode = 0;
|
|
||||||
block += c;
|
|
||||||
appendResult();
|
|
||||||
return;
|
|
||||||
} else {
|
|
||||||
numParen--;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
|
|
||||||
case ',':
|
|
||||||
if (quote) {
|
|
||||||
break;
|
|
||||||
} else if(mode === 0) {
|
|
||||||
appendResult();
|
|
||||||
return;
|
|
||||||
} else if (mode === 1) {
|
|
||||||
if (numParen === 0 && !method.match(/^url$/i)) {
|
|
||||||
args.push(definition);
|
|
||||||
definition = '';
|
|
||||||
block += c;
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
block += c;
|
|
||||||
if (mode === 0) {
|
|
||||||
method += c;
|
|
||||||
} else {
|
|
||||||
definition += c;
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
appendResult();
|
|
||||||
return results;
|
|
||||||
}
|
|
||||||
|
|
||||||
return this.backgroundImages || (this.backgroundImages = parseBackgrounds(this.css("backgroundImage")));
|
return this.backgroundImages || (this.backgroundImages = parseBackgrounds(this.css("backgroundImage")));
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -244,3 +151,100 @@ NodeContainer.prototype.TEXT_SHADOW_VALUES = /(-?\d+px)|(#.+)|(rgb\(.+\))|(rgba\
|
|||||||
function isPercentage(value) {
|
function isPercentage(value) {
|
||||||
return value.toString().indexOf("%") !== -1;
|
return value.toString().indexOf("%") !== -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function parseBackgrounds(backgroundImage) {
|
||||||
|
var whitespace = ' \r\n\t',
|
||||||
|
method, definition, prefix, prefix_i, block, results = [],
|
||||||
|
mode = 0, numParen = 0, quote, args;
|
||||||
|
var appendResult = function() {
|
||||||
|
if(method) {
|
||||||
|
if (definition.substr(0, 1) === '"') {
|
||||||
|
definition = definition.substr(1, definition.length - 2);
|
||||||
|
}
|
||||||
|
if (definition) {
|
||||||
|
args.push(definition);
|
||||||
|
}
|
||||||
|
if (method.substr(0, 1) === '-' && (prefix_i = method.indexOf('-', 1 ) + 1) > 0) {
|
||||||
|
prefix = method.substr(0, prefix_i);
|
||||||
|
method = method.substr(prefix_i);
|
||||||
|
}
|
||||||
|
results.push({
|
||||||
|
prefix: prefix,
|
||||||
|
method: method.toLowerCase(),
|
||||||
|
value: block,
|
||||||
|
args: args,
|
||||||
|
image: null
|
||||||
|
});
|
||||||
|
}
|
||||||
|
args = [];
|
||||||
|
method = prefix = definition = block = '';
|
||||||
|
};
|
||||||
|
args = [];
|
||||||
|
method = prefix = definition = block = '';
|
||||||
|
backgroundImage.split("").forEach(function(c) {
|
||||||
|
if (mode === 0 && whitespace.indexOf(c) > -1) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
switch(c) {
|
||||||
|
case '"':
|
||||||
|
if(!quote) {
|
||||||
|
quote = c;
|
||||||
|
}
|
||||||
|
else if(quote === c) {
|
||||||
|
quote = null;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case '(':
|
||||||
|
if(quote) {
|
||||||
|
break;
|
||||||
|
} else if(mode === 0) {
|
||||||
|
mode = 1;
|
||||||
|
block += c;
|
||||||
|
return;
|
||||||
|
} else {
|
||||||
|
numParen++;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case ')':
|
||||||
|
if (quote) {
|
||||||
|
break;
|
||||||
|
} else if(mode === 1) {
|
||||||
|
if(numParen === 0) {
|
||||||
|
mode = 0;
|
||||||
|
block += c;
|
||||||
|
appendResult();
|
||||||
|
return;
|
||||||
|
} else {
|
||||||
|
numParen--;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
|
case ',':
|
||||||
|
if (quote) {
|
||||||
|
break;
|
||||||
|
} else if(mode === 0) {
|
||||||
|
appendResult();
|
||||||
|
return;
|
||||||
|
} else if (mode === 1) {
|
||||||
|
if (numParen === 0 && !method.match(/^url$/i)) {
|
||||||
|
args.push(definition);
|
||||||
|
definition = '';
|
||||||
|
block += c;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
block += c;
|
||||||
|
if (mode === 0) {
|
||||||
|
method += c;
|
||||||
|
} else {
|
||||||
|
definition += c;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
appendResult();
|
||||||
|
return results;
|
||||||
|
}
|
||||||
|
@ -7,9 +7,10 @@ function NodeParser(element, renderer, support, imageLoader, options) {
|
|||||||
this.stack = new StackingContext(true, 1, element.ownerDocument, null);
|
this.stack = new StackingContext(true, 1, element.ownerDocument, null);
|
||||||
var parent = new NodeContainer(element, null);
|
var parent = new NodeContainer(element, null);
|
||||||
parent.visibile = parent.isElementVisible();
|
parent.visibile = parent.isElementVisible();
|
||||||
this.nodes = [parent].concat(this.getChildren(parent)).filter(function(container) {
|
this.createPseudoHideStyles(element.ownerDocument);
|
||||||
|
this.nodes = flatten([parent].concat(this.getChildren(parent)).filter(function(container) {
|
||||||
return container.visible = container.isElementVisible();
|
return container.visible = container.isElementVisible();
|
||||||
});
|
}).map(this.getPseudoElements, this));
|
||||||
this.fontMetrics = new FontMetrics();
|
this.fontMetrics = new FontMetrics();
|
||||||
log("Fetched nodes");
|
log("Fetched nodes");
|
||||||
this.images = imageLoader.fetch(this.nodes.filter(isElement));
|
this.images = imageLoader.fetch(this.nodes.filter(isElement));
|
||||||
@ -24,6 +25,68 @@ function NodeParser(element, renderer, support, imageLoader, options) {
|
|||||||
}, this));
|
}, this));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
NodeParser.prototype.createPseudoHideStyles = function(document) {
|
||||||
|
var hidePseudoElements = document.createElement('style');
|
||||||
|
hidePseudoElements.innerHTML = '.' + this.pseudoHideClass + ':before { content: "" !important; display: none !important; }' +
|
||||||
|
'.' + this.pseudoHideClass + ':after { content: "" !important; display: none !important; }';
|
||||||
|
document.body.appendChild(hidePseudoElements);
|
||||||
|
};
|
||||||
|
|
||||||
|
NodeParser.prototype.getPseudoElements = function(container) {
|
||||||
|
var nodes = [[container]];
|
||||||
|
if (container instanceof NodeContainer) {
|
||||||
|
var before = this.getPseudoElement(container, ":before");
|
||||||
|
var after = this.getPseudoElement(container, ":after");
|
||||||
|
|
||||||
|
if (before) {
|
||||||
|
container.node.insertBefore(before[0].node, container.node.firstChild);
|
||||||
|
nodes.push(before);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (after) {
|
||||||
|
container.node.appendChild(after[0].node);
|
||||||
|
nodes.push(after);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (before || after) {
|
||||||
|
container.node.className += " " + this.pseudoHideClass;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return flatten(nodes);
|
||||||
|
};
|
||||||
|
|
||||||
|
NodeParser.prototype.getPseudoElement = function(container, type) {
|
||||||
|
var style = container.computedStyle(type);
|
||||||
|
if(!style || !style.content || style.content === "none" || style.content === "-moz-alt-content" || style.display === "none") {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
var content = stripQuotes(style.content);
|
||||||
|
var isImage = content.substr(0, 3) === 'url';
|
||||||
|
var pseudoNode = document.createElement(isImage ? 'img' : 'html2canvaspseudoelement');
|
||||||
|
var pseudoContainer = new NodeContainer(pseudoNode, container);
|
||||||
|
Object.keys(style).filter(indexedProperty).forEach(function(property) {
|
||||||
|
// Prevent assigning of read only CSS Rules, ex. length, parentRule
|
||||||
|
try {
|
||||||
|
pseudoNode.style[property] = style[property];
|
||||||
|
} catch (e) {
|
||||||
|
log('Tried to assign readonly property ', property, 'Error:', e);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
pseudoNode.className = this.pseudoHideClass;
|
||||||
|
|
||||||
|
if (isImage) {
|
||||||
|
pseudoNode.src = parseBackgrounds(content)[0].args[0];
|
||||||
|
return [pseudoContainer];
|
||||||
|
} else {
|
||||||
|
var text = document.createTextNode(content);
|
||||||
|
pseudoNode.appendChild(text);
|
||||||
|
return [pseudoContainer, new TextContainer(text, pseudoContainer)];
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
NodeParser.prototype.getChildren = function(parentContainer) {
|
NodeParser.prototype.getChildren = function(parentContainer) {
|
||||||
return flatten([].filter.call(parentContainer.node.childNodes, renderableNode).map(function(node) {
|
return flatten([].filter.call(parentContainer.node.childNodes, renderableNode).map(function(node) {
|
||||||
var container = [node.nodeType === Node.TEXT_NODE ? new TextContainer(node, parentContainer) : new NodeContainer(node, parentContainer)].filter(nonIgnoredElement);
|
var container = [node.nodeType === Node.TEXT_NODE ? new TextContainer(node, parentContainer) : new NodeContainer(node, parentContainer)].filter(nonIgnoredElement);
|
||||||
@ -328,6 +391,8 @@ NodeParser.prototype.parseBackgroundClip = function(container, borderPoints, bor
|
|||||||
return borderArgs;
|
return borderArgs;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
NodeParser.prototype.pseudoHideClass = "___html2canvas___pseudoelement";
|
||||||
|
|
||||||
function getCurvePoints(x, y, r1, r2) {
|
function getCurvePoints(x, y, r1, r2) {
|
||||||
var kappa = 4 * ((Math.sqrt(2) - 1) / 3);
|
var kappa = 4 * ((Math.sqrt(2) - 1) / 3);
|
||||||
var ox = (r1) * kappa, // control point offset horizontal
|
var ox = (r1) * kappa, // control point offset horizontal
|
||||||
@ -546,3 +611,12 @@ function nonIgnoredElement(nodeContainer) {
|
|||||||
function flatten(arrays) {
|
function flatten(arrays) {
|
||||||
return [].concat.apply([], arrays);
|
return [].concat.apply([], arrays);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function stripQuotes(content) {
|
||||||
|
var first = content.substr(0, 1);
|
||||||
|
return (first === content.substr(content.length - 1) && first.match(/'|"/)) ? content.substr(1, content.length - 2) : content;
|
||||||
|
}
|
||||||
|
|
||||||
|
function indexedProperty(property) {
|
||||||
|
return (isNaN(parseInt(property, 10)));
|
||||||
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user