Your idea of using a <canvas>
is possible.
See DEMO (tested on Chrome, Safari and Opera).
You can convert the following into 3 different canvases using html2canvas, and compare their base64 string to determine if they are visually the same. You should wrap them in separate containers so that all the texts are rendered in the canvases.
<div id="target1-container">
<div id="target1"> Some<sup>en</sup> <i><b>text</b></i> </div>
</div>
<div id="target2-container">
<div id="target2"> Some<sup>en</sup> <span class='boldIt'>text</span></div>
</div>
<div id="target3-container">
<div id="target3"> Someen text</div>
</div>
Converting to canvas and base64 strings, using async.js to handle multiple asynchronous calls:
async.parallel({
target1: function (callback) {
html2canvas(document.getElementById("target1-container"), {
onrendered: function (canvas) {
callback(null, canvas.toDataURL());
}
});
},
target2: function (callback) {
html2canvas(document.getElementById("target2-container"), {
onrendered: function (canvas) {
callback(null, canvas.toDataURL());
}
});
},
target3: function (callback) {
html2canvas(document.getElementById("target3-container"), {
onrendered: function (canvas) {
callback(null, canvas.toDataURL());
}
});
}
},
function (err, results) {
console.log(results);
});
Regarding your updated question, here's a function to compare the visual appearance of elements defined by the strings:
function compare(arr, fn) {
// create test div
var testdiv = document.createElement("div");
testdiv.style.marginTop = '1000px';
document.body.appendChild(testdiv);
async.map(
arr,
function (data, callback) {
var htStr = data.one,
htStr2 = data.two;
// create elements from strings
var el = document.createElement("div"),
el2 = document.createElement("div");
el.innerHTML = htStr;
testdiv.appendChild(el);
el2.innerHTML = htStr2;
testdiv.appendChild(el2);
// convert to canvas and base64 strings
async.parallel([
function (callback) {
html2canvas(el, {
onrendered: function (canvas) {
callback(null, canvas.toDataURL());
}
});
},
function (callback) {
html2canvas(el2, {
onrendered: function (canvas) {
callback(null, canvas.toDataURL());
}
});
}
],
// start comparison
function (err, results) {
if (results[0] === results[1]) {
callback(null, true);
} else {
callback(null, false);
}
});
},
// callback function
function (err, results) {
document.body.removeChild(testdiv);
if (typeof fn === 'function') {
fn(results);
}
}
);
}
// elements to be tested
var arr = [];
arr.push({
one: '<div id="target1"> Some<sup>en</sup> <i><b>text</b></i> </div>',
two: '<div id="target2"> Some<sup>en</sup> <span class="boldIt">text</span></div>'
});
arr.push({
one: '<div id="target1"> Some<sup>en</sup> <i><b>text</b></i> </div>',
two: '<div id="target3"> Someen text</div>'
});
// let the test begin
compare(arr, function (result) {
console.log(result);
});
It returns an array in a callback function, with
true
meaning the elements being visually the same, and
false
meaning they being different.
See the console in this DEMO.