Javascript 修改HTML,同时保留现有元素和事件侦听器
我是新来的。我试着向你解释我的问题。 我正在为管理DOM的Chrome开发一个扩展。 我必须将Javascript 修改HTML,同时保留现有元素和事件侦听器,javascript,jquery,html,google-chrome-extension,split,Javascript,Jquery,Html,Google Chrome Extension,Split,我是新来的。我试着向你解释我的问题。 我正在为管理DOM的Chrome开发一个扩展。 我必须将标记元素中的每个单词拆分,以便在每个单词上的一些css功能之后应用,但保留可能位于标记中的其他标记元素(,等) 网页中可能的文本示例: <p> Sed ut <a> perspiciatis unde omnis </a> iste natus <em> error sit </em> voluptatem <st
标记元素中的每个单词拆分,以便在每个单词上的一些css功能之后应用,但保留可能位于标记中的其他标记元素(,
等)
网页中可能的文本示例:
<p>
Sed ut <a> perspiciatis unde omnis </a>
iste natus <em> error sit </em>
voluptatem <strong> accusantium </strong>
doloremque laudantium
</p>
全方位透视
iste自然错误
voluptatemaccusantium
劳丹蒂姆酒店
使用jQuery,我想在每个单词周围放置一个
标记,以定义一个类属性,用于css。
我发现这个代码可以正确地分割单词(属于<代码> <代码>,但不考虑代码中的其他可能元素> <>>代码>
使用的代码(不满足我的需要):
$(“p”)。每个(函数(){
var originalText=$(this.text().split(“”);
var SpandText=[];
对于(变量i=0;i
在上面显示的示例中,此代码生成以下输出,删除其他标记元素:
<p>
<span>Sed</span>
<span>ut</span>
<span>perspiciatis</span>
<span>unde</span>
<span>omnis</span>
<span>iste</span>
<span>natus</span>
<span>error</span>
<span>sit</span>
<span>voluptatem</span>
<span>accusantium</span>
<span>doloremque</span>
<span>laudantium</span>
</p>
塞德
美国犹他州
透视术
unde
奥姆尼斯
伊斯特
纳图斯
错误
坐着
沃鲁帕特姆
accusantium
多洛雷姆格
劳丹提姆
这接近于我需要的解决方案,但在本例中,示例中的所有标记(,
)都被删除并替换为
标记
相反,我希望保留
的html结构,并且只为每个单词插入..
这就是我想要实现的输出:
<p>
<span>Sed</span>
<span>ut</span>
<a> <span>perspiciatis</span> <span>unde</span> <span>omnis</span> </a>
<span>iste</span>
<span>natus</span>
<em> <span>error</span> <span>sit</span> </em>
<span>voluptatem</span>
<strong> <span>accusantium</span> </strong>
<span>doloremque</span>
<span>laudantium</span>
</p>
塞德
美国犹他州
全向透视
伊斯特
纳图斯
错误定位
沃鲁帕特姆
accusantium
多洛雷姆格
劳丹提姆
你能帮我吗?永远不要通过innerHTML或jQuery的HTML()替换HTML
替换HTML会破坏JavaScript中添加到子元素的所有事件侦听器,并使浏览器重新解析整个事件,这是一个CPU密集型操作,因此在速度较慢的设备上可能会变慢。不要这样做
仅递归处理文本节点:
const span=document.createElement('span');
span.className='foo';
appendChild(document.createTextNode(“”));
//根据HTML规范,它们将显示为文本
常量skipTags=['textarea','rp'];
for(document.getElementsByTagName('p')的常数p){
const walker=document.createTreeWalker(p,NodeFilter.SHOW_TEXT);
//首先收集节点,因为我们无法在漫游时插入新的跨度节点
常量textNodes=[];
for(设n;(n=walker.nextNode());){
if(n.nodeValue.trim()&&!skipTags.includes(n.parentNode.localName)){
textNodes.push(n);
}
}
for(文本节点的常数n){
const fragment=document.createDocumentFragment();
用于(n.nodeValue.split(/(\s+/)的常数){
如果(s.trim()){
span.firstChild.nodeValue=s;
片段.appendChild(span.cloneNode(true));
}否则{
fragment.appendChild(document.createTextNode);
}
}
n、 replaceChild(片段,n);
}
}
因为我们可能要替换数千个节点,所以这段代码试图加快速度:它使用API、DOM克隆、通过简单的正则表达式跳过可能的超长空格序列和换行符序列,以及DocumentFragment将新节点放置在一个变异操作中。当然也不使用jQuery
另外,还有一些高级库用于更复杂的匹配和处理,如。欢迎使用堆栈溢出。我不会使用.text()
,因为它只读取元素的文本,而.html()
将读取标记和文本。基本上,您需要迭代
的内容,找到每个单词(查找空格“”
),并用
标记将它们包装起来。您还希望了解HTML元素,并且应该保留它们,但是这些元素的内容也应该以类似的方式包装
$(函数(){
函数包装(w){
返回“+w+”;
}
函数标记文字(str){
var html=$.parseHTML(str);
var节点=[];
$.each(html、函数(i、el){
nodes.push({
姓名:el.nodeName,
类型:el.nodeType,
内容:el.nodeValue,
元素:el
});
});
log(html,节点);
var部分=[];
变量t;
$.each(节点、函数(k、项){
如果(item.type==3){
t=item.content.trim().split(“”);
$。每个(t,函数(j,s){
零件推送(包装件);
});
}否则{
t=$(item.element).text().trim().split(“”);
$(item.element).html(“”);
$。每个(t,函数(j,s){
$(item.element).append(wrapWord+“”);
});
零件.push($(item.element).prop(“outerHTML”);
}
});
控制台日志(部件);
返回零件。连接(“”);
}
$($p.highlight”).html(markupText($($p.highlight”).prop(“innerHTML”));
});代码>
p.突出显示跨度{
背景色:#FF0;
}
Lorem ipsum dolor sit amet,是一位杰出的献身者。但这是一种致命的疾病。埃涅阿斯·埃吉特·马克西姆斯·普鲁斯。请不要忘记过去,不要忘记过去。这是我的梦想,也是我的梦想。比本杜姆·维利特·波苏尔·森佩尔万岁
在所有情况下都能清楚地看到错误所在的位置,请使用accusantiumdoloremque laudantium
谢谢!我以前从未使用过TreeWalker API,但我尝试过您的解决方案,但它并不完全有效。
<p>
<span>Sed</span>
<span>ut</span>
<a> <span>perspiciatis</span> <span>unde</span> <span>omnis</span> </a>
<span>iste</span>
<span>natus</span>
<em> <span>error</span> <span>sit</span> </em>
<span>voluptatem</span>
<strong> <span>accusantium</span> </strong>
<span>doloremque</span>
<span>laudantium</span>
</p>
const span = document.createElement('span');
span.className = 'foo';
span.appendChild(document.createTextNode(''));
// these will display <span> as a literal text per HTML specification
const skipTags = ['textarea', 'rp'];
for (const p of document.getElementsByTagName('p')) {
const walker = document.createTreeWalker(p, NodeFilter.SHOW_TEXT);
// collect the nodes first because we can't insert new span nodes while walking
const textNodes = [];
for (let n; (n = walker.nextNode());) {
if (n.nodeValue.trim() && !skipTags.includes(n.parentNode.localName)) {
textNodes.push(n);
}
}
for (const n of textNodes) {
const fragment = document.createDocumentFragment();
for (const s of n.nodeValue.split(/(\s+)/)) {
if (s.trim()) {
span.firstChild.nodeValue = s;
fragment.appendChild(span.cloneNode(true));
} else {
fragment.appendChild(document.createTextNode(s));
}
}
n.parentNode.replaceChild(fragment, n);
}
}