Correctly clone <select> and <textarea> value property

This commit is contained in:
Niklas von Hertzen 2015-01-05 22:58:36 +02:00
parent 498527918c
commit 9b372a4399
6 changed files with 201 additions and 80 deletions

19
dist/html2canvas.js vendored
View File

@ -581,6 +581,7 @@ window.html2canvas = function(nodeList, options) {
options.javascriptEnabled = typeof(options.javascriptEnabled) === "undefined" ? false : options.javascriptEnabled;
options.imageTimeout = typeof(options.imageTimeout) === "undefined" ? 10000 : options.imageTimeout;
options.renderer = typeof(options.renderer) === "function" ? options.renderer : CanvasRenderer;
options.strict = !!options.strict;
if (typeof(nodeList) === "string") {
if (typeof(options.proxy) !== "string") {
@ -705,6 +706,10 @@ function createWindowClone(ownerDocument, containerDocument, width, height, opti
return new Promise(function(resolve) {
var documentClone = container.contentWindow.document;
cloneNodeValues(ownerDocument.documentElement, documentElement, "textarea");
cloneNodeValues(ownerDocument.documentElement, documentElement, "select");
/* Chrome doesn't detect relative background-images assigned in inline <style> sheets when fetched through getComputedStyle
if window url is about:blank, we can assign the url to current by writing onto the document
*/
@ -733,6 +738,15 @@ function createWindowClone(ownerDocument, containerDocument, width, height, opti
});
}
function cloneNodeValues(document, clone, nodeName) {
var originalNodes = document.getElementsByTagName(nodeName);
var clonedNodes = clone.getElementsByTagName(nodeName);
var count = originalNodes.length;
for (var i = 0; i < count; i++) {
clonedNodes[i].value = originalNodes[i].value;
}
}
function restoreOwnerScroll(ownerDocument, x, y) {
if (x !== ownerDocument.defaultView.pageXOffset || y !== ownerDocument.defaultView.pageYOffset) {
ownerDocument.defaultView.scrollTo(x, y);
@ -2245,7 +2259,8 @@ NodeParser.prototype.paintRadio = function(container) {
};
NodeParser.prototype.paintFormValue = function(container) {
if (container.getValue().length > 0) {
var value = container.getValue();
if (value.length > 0) {
var document = container.node.ownerDocument;
var wrapper = document.createElement('html2canvaswrapper');
var properties = ['lineHeight', 'textAlign', 'fontFamily', 'fontWeight', 'fontSize', 'color',
@ -2265,7 +2280,7 @@ NodeParser.prototype.paintFormValue = function(container) {
wrapper.style.position = "fixed";
wrapper.style.left = bounds.left + "px";
wrapper.style.top = bounds.top + "px";
wrapper.textContent = container.getValue();
wrapper.textContent = value;
document.body.appendChild(wrapper);
this.paintText(new TextContainer(wrapper.firstChild, container));
document.body.removeChild(wrapper);

File diff suppressed because one or more lines are too long

View File

@ -17,6 +17,7 @@ window.html2canvas = function(nodeList, options) {
options.javascriptEnabled = typeof(options.javascriptEnabled) === "undefined" ? false : options.javascriptEnabled;
options.imageTimeout = typeof(options.imageTimeout) === "undefined" ? 10000 : options.imageTimeout;
options.renderer = typeof(options.renderer) === "function" ? options.renderer : CanvasRenderer;
options.strict = !!options.strict;
if (typeof(nodeList) === "string") {
if (typeof(options.proxy) !== "string") {
@ -141,6 +142,10 @@ function createWindowClone(ownerDocument, containerDocument, width, height, opti
return new Promise(function(resolve) {
var documentClone = container.contentWindow.document;
cloneNodeValues(ownerDocument.documentElement, documentElement, "textarea");
cloneNodeValues(ownerDocument.documentElement, documentElement, "select");
/* Chrome doesn't detect relative background-images assigned in inline <style> sheets when fetched through getComputedStyle
if window url is about:blank, we can assign the url to current by writing onto the document
*/
@ -169,6 +174,15 @@ function createWindowClone(ownerDocument, containerDocument, width, height, opti
});
}
function cloneNodeValues(document, clone, nodeName) {
var originalNodes = document.getElementsByTagName(nodeName);
var clonedNodes = clone.getElementsByTagName(nodeName);
var count = originalNodes.length;
for (var i = 0; i < count; i++) {
clonedNodes[i].value = originalNodes[i].value;
}
}
function restoreOwnerScroll(ownerDocument, x, y) {
if (x !== ownerDocument.defaultView.pageXOffset || y !== ownerDocument.defaultView.pageYOffset) {
ownerDocument.defaultView.scrollTo(x, y);

View File

@ -388,7 +388,8 @@ NodeParser.prototype.paintRadio = function(container) {
};
NodeParser.prototype.paintFormValue = function(container) {
if (container.getValue().length > 0) {
var value = container.getValue();
if (value.length > 0) {
var document = container.node.ownerDocument;
var wrapper = document.createElement('html2canvaswrapper');
var properties = ['lineHeight', 'textAlign', 'fontFamily', 'fontWeight', 'fontSize', 'color',
@ -408,7 +409,7 @@ NodeParser.prototype.paintFormValue = function(container) {
wrapper.style.position = "fixed";
wrapper.style.left = bounds.left + "px";
wrapper.style.top = bounds.top + "px";
wrapper.textContent = container.getValue();
wrapper.textContent = value;
document.body.appendChild(wrapper);
this.paintText(new TextContainer(wrapper.firstChild, container));
document.body.removeChild(wrapper);

View File

@ -0,0 +1,163 @@
<html>
<head>
<meta charset="utf-8">
<title>Mocha Tests</title>
<link rel="stylesheet" href="lib/mocha.css" />
<script src="../../dist/html2canvas.js"></script>
<script src="../../src/log.js"></script>
<script src="../../src/renderer.js"></script>
<script src="../../src/renderers/canvas.js"></script>
<script src="../assets/jquery-1.6.2.js"></script>
<script src="lib/expect.js"></script>
<script src="lib/mocha.js"></script>
<style>
.block {
width: 200px;
height: 200px;
}
</style>
</head>
<body>
<div id="mocha"></div>
<script>mocha.setup('bdd')</script>
<div id="block1" class="block">
<input type="text" value="text" />
</div>
<div id="block2" class="block">
<input type="password" value="password" />
</div>
<div id="block3" class="block">
<input type="text" value="text" />
</div>
<div id="block4" class="block">
<textarea>text</textarea>
</div>
<div id="block5" class="block">
<select>
<option value="1">1</option>
<option value="2" selected>2</option>
<option value="3">3</option>
</select>
</div>
<div id="green-block"></div>
<script>
describe("Rendering input values", function() {
it("uses default value for input[type='text']", function(done) {
CanvasRenderer.prototype.text = function(text) {
expect(text).to.equal('text');
};
html2canvas(document.querySelector("#block1"), {renderer: CanvasRenderer, strict: true}).then(function(canvas) {
expect(canvas.width).to.equal(200);
expect(canvas.height).to.equal(200);
done();
}).catch(function(error) {
done(error);
});
});
it("uses transformed value for input[type='password']", function(done) {
var count = 0;
CanvasRenderer.prototype.text = function(text) {
expect(text).to.equal('•');
count++;
};
html2canvas(document.querySelector("#block2"), {renderer: CanvasRenderer, strict: true}).then(function(canvas) {
expect(canvas.width).to.equal(200);
expect(canvas.height).to.equal(200);
expect(count).to.equal("password".length);
done();
}).catch(function(error) {
done(error);
});
});
it("used property and not attribute for rendering", function(done) {
document.querySelector("#block3 input").value = 'updated';
CanvasRenderer.prototype.text = function(text) {
expect(text).to.equal('updated');
};
html2canvas(document.querySelector("#block3"), {renderer: CanvasRenderer, strict: true}).then(function(canvas) {
expect(canvas.width).to.equal(200);
expect(canvas.height).to.equal(200);
done();
}).catch(function(error) {
done(error);
});
});
describe("Rendering textarea values", function() {
it("uses default value correctly", function(done) {
CanvasRenderer.prototype.text = function(text) {
expect(text).to.equal('text');
};
html2canvas(document.querySelector("#block4"), {renderer: CanvasRenderer, strict: true}).then(function(canvas) {
expect(canvas.width).to.equal(200);
expect(canvas.height).to.equal(200);
done();
}).catch(function(error) {
done(error);
});
});
it("used property and not attribute for rendering", function(done) {
document.querySelector("#block4 textarea").value = 'updated';
CanvasRenderer.prototype.text = function(text) {
expect(text).to.equal('updated');
};
html2canvas(document.querySelector("#block4"), {renderer: CanvasRenderer, strict: true, logging: true, removeContainer: false}).then(function(canvas) {
expect(canvas.width).to.equal(200);
expect(canvas.height).to.equal(200);
done();
}).catch(function(error) {
done(error);
});
});
});
describe("Select values", function() {
it("uses default value correctly", function(done) {
CanvasRenderer.prototype.text = function(text) {
expect(text).to.equal('2');
};
html2canvas(document.querySelector("#block5"), {renderer: CanvasRenderer, strict: true}).then(function(canvas) {
expect(canvas.width).to.equal(200);
expect(canvas.height).to.equal(200);
done();
}).catch(function(error) {
done(error);
});
});
it("used property and not attribute for rendering", function(done) {
document.querySelector("#block5 select").value = '3';
CanvasRenderer.prototype.text = function(text) {
expect(text).to.equal('3');
};
html2canvas(document.querySelector("#block5"), {renderer: CanvasRenderer, strict: true, logging: true, removeContainer: false}).then(function(canvas) {
expect(canvas.width).to.equal(200);
expect(canvas.height).to.equal(200);
done();
}).catch(function(error) {
done(error);
});
});
});
});
mocha.checkLeaks();
mocha.globals(['jQuery']);
if (window.mochaPhantomJS) {
mochaPhantomJS.run();
}
else {
mocha.run();
}
</script>
</body>
</html>

View File

@ -1,72 +0,0 @@
<html>
<head>
<meta charset="utf-8">
<title>Mocha Tests</title>
<link rel="stylesheet" href="lib/mocha.css" />
<script src="../../dist/html2canvas.js"></script>
<script src="../../src/log.js"></script>
<script src="../../src/renderer.js"></script>
<script src="../../src/renderers/canvas.js"></script>
<script src="../assets/jquery-1.6.2.js"></script>
<script src="lib/expect.js"></script>
<script src="lib/mocha.js"></script>
<style>
.block {
width: 200px;
height: 200px;
}
</style>
</head>
<body>
<div id="mocha"></div>
<script>mocha.setup('bdd')</script>
<div id="block1" class="block">
<input type="text" value="text" />
</div>
<div id="block2" class="block">
<input type="password" value="password" />
</div>
<div id="green-block"></div>
<script>
describe("Rendering input values", function() {
it("uses default value for input[type='text']", function(done) {
CanvasRenderer.prototype.text = function(text) {
expect(text).to.equal('text');
};
html2canvas(document.querySelector("#block1"), {renderer: CanvasRenderer, strict: true}).then(function(canvas) {
expect(canvas.width).to.equal(200);
expect(canvas.height).to.equal(200);
done();
}).catch(function(error) {
done(error);
});
});
it("uses transformed value for input[type='password']", function(done) {
var count = 0;
CanvasRenderer.prototype.text = function(text) {
expect(text).to.equal('•');
count++;
};
html2canvas(document.querySelector("#block2"), {renderer: CanvasRenderer, strict: true}).then(function(canvas) {
expect(canvas.width).to.equal(200);
expect(canvas.height).to.equal(200);
expect(count).to.equal("password".length);
done();
}).catch(function(error) {
done(error);
});
});
});
mocha.checkLeaks();
mocha.globals(['jQuery']);
if (window.mochaPhantomJS) {
mochaPhantomJS.run();
}
else {
mocha.run();
}
</script>
</body>
</html>