/*
* HTMLParser - This implementation of parser assumes we are parsing HTML in browser
* and user DOM methods available in browser for parsing HTML.
*
* @author Himanshu Gilani
*
*/
var HTMLParser = function(node, handler, opts) {
opts = opts || {};
var nodesToIgnore = opts['nodesToIgnore'] || [];
var parseHiddenNodes = opts['parseHiddenNodes'] || 'false';
var c = node.childNodes;
for ( var i = 0; i < c.length; i++) {
try {
var ignore = false;
for(var k=0; k< nodesToIgnore.length; k++) {
if(c[i].nodeName.toLowerCase() == nodesToIgnore[k]) {
ignore= true;
break;
}
}
//NOTE hidden node testing is expensive in FF.
if (ignore || (!parseHiddenNodes && isHiddenNode(c[i])) ){
continue;
}
if (c[i].nodeName.toLowerCase() != "#text" && c[i].nodeName.toLowerCase() != "#comment") {
var attrs = [];
if (c[i].hasAttributes()) {
var attributes = c[i].attributes;
for ( var a = 0; a < attributes.length; a++) {
var attribute = attributes.item(a);
attrs.push({
name : attribute.nodeName,
value : attribute.nodeValue,
});
}
}
if (handler.start) {
if (c[i].hasChildNodes()) {
handler.start(c[i].nodeName, attrs, false);
if (c[i].nodeName.toLowerCase() == "pre" || c[i].nodeName.toLowerCase() == "code") {
handler.chars(c[i].innerHTML);
} else if (c[i].nodeName.toLowerCase() == "iframe" || c[i].nodeName.toLowerCase() == "frame") {
if (c[i].contentDocument && c[i].contentDocument.documentElement) {
return HTMLParser(c[i].contentDocument.documentElement, handler, opts);
}
} else if (c[i].hasChildNodes()) {
HTMLParser(c[i], handler, opts);
}
if (handler.end) {
handler.end(c[i].nodeName);
}
} else {
handler.start(c[i].nodeName, attrs, true);
}
}
} else if (c[i].nodeName.toLowerCase() == "#text") {
if (handler.chars) {
handler.chars(c[i].nodeValue);
}
} else if (c[i].nodeName.toLowerCase() == "#comment") {
if (handler.comment) {
handler.comment(c[i].nodeValue);
}
}
} catch (e) {
//properly log error
console.log("error while parsing node: " + c[i].nodeName.toLowerCase());
}
}
};
function isHiddenNode(node) {
if(node.nodeName.toLowerCase() == "title"){
return false;
}
if (window.getComputedStyle) {
try {
var style = window.getComputedStyle(node, null);
if (style.getPropertyValue && style.getPropertyValue('display') == 'none') {
return true;
}
} catch (e) {
// consume and ignore. node styles are not accessible
}
return false;
}
}