Nor*_*les 1 html javascript dom textnode
我想在TreeWalker的文本节点中插入html标签,但TreeWalker强制我的html括号进入< > 无论我尝试过什么.这是代码:
var text;
var tree = document.createTreeWalker(document.body,NodeFilter.SHOW_TEXT);
while (tree.nextNode()) {
text = tree.currentNode.nodeValue;
text = text.replace(/(\W)(\w+)/g, '$1<element onmouseover="sendWord(\'$2\')">$2</element>');
text = text.replace(/^(\w+)/, '<element onmouseover="sendWord(\'$1\')">$1</element>');
tree.currentNode.nodeValue = text;
}
Run Code Online (Sandbox Code Playgroud)
使用\ <或"而不是'将无济于事.我的解决方法是将所有DOM树复制到一个字符串并用它替换html主体.它适用于非常简单的网页并解决我的第一个问题,但是糟糕的黑客攻击并不会在一个简单的页面上工作.我想知道我是否可以直接使用文本节点而不是使用解决方法.以下是(当前错误)解决方法的代码:
var text;
var newHTML = "";
var tree = document.createTreeWalker(document.body);
while (tree.nextNode()) {
text = tree.currentNode.nodeValue;
if (tree.currentNode.nodeType == 3){
text = text.replace(/(\W)(\w+)/g, '$1<element onmouseover="sendWord(\'$2\')">$2</element>');
text = text.replace(/^(\w+)/, '<element onmouseover="sendWord(\'$1\')">$1</element>');
}
newHTML += text
}
document.body.innerHTML = newHTML;
Run Code Online (Sandbox Code Playgroud)
编辑:我意识到更好的解决方法是自定义标记文本节点((Customtag_Start_Here)等),将整个DOM复制到字符串,并使用我的海关标签来识别文本节点并以这种方式修改它们.但如果我不必,我宁愿不要.
要将文本节点"更改"为元素,必须将其替换为元素.例如:
var text = tree.currentNode;
var el = document.createElement('foo');
el.setAttribute('bar','yes');
text.parentNode.replaceChild( el, text );
Run Code Online (Sandbox Code Playgroud)
如果要保留文本节点的一部分,并在"中间"注入元素,则需要创建另一个文本节点,并将其和元素插入树中树的适当位置.
编辑:这是一个对你来说非常有用的功能.:)
给定一个文本节点,它在文本值上运行正则表达式.对于它找到的每个匹配,它会调用您提供的自定义函数.如果该函数返回一个字符串,则替换匹配.但是,如果该函数返回如下对象:
{ name:"element", attrs{onmouseover:"sendWord('foo')"}, content:"foo" }
Run Code Online (Sandbox Code Playgroud)
然后它将在匹配周围拆分文本节点并在该位置注入一个元素.您还可以返回字符串数组或这些对象(并且可以递归地使用数组,字符串或对象作为content属性).
function textNodeReplace(node,regex,handler) {
var mom=node.parentNode, nxt=node.nextSibling,
doc=node.ownerDocument, hits;
if (regex.global) {
while(node && (hits=regex.exec(node.nodeValue))){
regex.lastIndex = 0;
node=handleResult( node, hits, handler.apply(this,hits) );
}
} else if (hits=regex.exec(node.nodeValue))
handleResult( node, hits, handler.apply(this,hits) );
function handleResult(node,hits,results){
var orig = node.nodeValue;
node.nodeValue = orig.slice(0,hits.index);
[].concat(create(mom,results)).forEach(function(n){
mom.insertBefore(n,nxt);
});
var rest = orig.slice(hits.index+hits[0].length);
return rest && mom.insertBefore(doc.createTextNode(rest),nxt);
}
function create(el,o){
if (o.map) return o.map(function(v){ return create(el,v) });
else if (typeof o==='object') {
var e = doc.createElementNS(o.namespaceURI || el.namespaceURI,o.name);
if (o.attrs) for (var a in o.attrs) e.setAttribute(a,o.attrs[a]);
if (o.content) [].concat(create(e,o.content)).forEach(e.appendChild,e);
return e;
} else return doc.createTextNode(o+"");
}
}
Run Code Online (Sandbox Code Playgroud)
它不是完全通用的,因为它不支持属性上的命名空间.但希望这足以让你前进.:)
你会像这样使用它:
findAllTextNodes(document.body).forEach(function(textNode){
replaceTextNode( textNode, /\b\w+/g, function(match){
return {
name:'element',
attrs:{onmouseover:"sendWord('"+match[0]+"')"},
content:match[0]
};
});
});
function findAllTextNodes(node){
var walker = node.ownerDocument.createTreeWalker(node,NodeFilter.SHOW_TEXT);
var textNodes = [];
while (walker.nextNode())
if (walker.currentNode.parentNode.tagName!='SCRIPT')
textNodes.push(walker.currentNode);
return textNodes;
}
Run Code Online (Sandbox Code Playgroud)
或者如果你想要更接近原始正则表达式的东西:
replaceTextNode( textNode, /(^|\W)(\w+)/g, function(match){
return [
match[1], // might be an empty string
{
name:'element',
attrs:{onmouseover:"sendWord('"+match[2]+"')"},
content:match[2]
}
];
});
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
1559 次 |
| 最近记录: |