35

我想知道是否有一种轻量级的方法可以使用JavaScript或jQuery嗅出文档中的特定文本字符;并查找此角色的所有实例。然后!编写一个能力,用例如a替换此的所有实例$.

我为初学者找到了这个片段:

var str='测试:'';str=str.replace(/'/g,“”);

基本上;我想要一个单页文档的解决方案。抓取X的所有实例并使其成为XY。仅限文本字符。

5
  • 2
    是的,可能有一种方法可以做到这一点,但最简单的方法是从页面中删除所有事件处理程序和元素数据。$(“body”).html($(body).html().replace(/\€/g,'$'))这是一种糟糕的做法。
    – 凯文·B
    评论 2013年9月5日18:49
  • 2
    如果您想避免丢失事件和元素数据,那么它会变得更加复杂。
    – 凯文·B
    评论 2013年9月5日18:50
  • 1
    谢谢@KevinB——我想进一步充实一下。我只是好奇。我可以补充什么来更具体一些?
    – 丹中尉
    评论 2013年9月5日19:01
  • 2
    最好是在服务器端进行,但如果这不是一个选项,那么客户端需要选择文档中的所有文本节点,对其进行迭代,然后分别在每个文本节点上执行替换。
    – 凯文·B
    评论 2013年9月5日19:05
  • 1
    这是一个使用我不久前写的插件突出显示文本的示例。jsfiddle.net/2t8TV/1我用它来包装所有出现的使用span,然后我替换了这些span中的文本。
    – 凯文B
    评论 2013年9月5日19:09

14答案14

重置为默认值
38

这个怎么样,替换@具有$:

$(“body”).children().each(函数(){$(this).html($(this).html().replace(/@@/g,“$”));});

http://jsfiddle.net/maximua/jp96C/1/

  • 4
    正在添加如果要替换alpha字符,正则表达式将提供不区分大小写的搜索.replace(/soMeWord/gi,“另一个单词”); 评论 2014年2月23日20:20
  • 1
    @DavidBailey的精彩接球,包括前后空位,让我减少了机会 评论 2016年10月21日15:17
  • 对我来说,这会使浏览器窗口跳回页面顶部,因此这不是一个适用于我的动态加载元素的解决方案。知道为什么吗? 评论 4月19日10:48
27

ECMAScript 2015+方法

解决此任务时的陷阱

这似乎是一项简单的任务,但您必须注意以下几点:

  • 只需替换整个HTML(例如,使用内部HTML)导致的受影响子树DOM公司完全删除和替换,但事件侦听器附加到现有,现已删除元素,因此它们将与它们一起删除。同样,WeakMap(弱点地图)现有元素的条目都将被删除。这是因为所有这些内容都需要参考文献元素或节点;a已更换内部HTML将创建全新的引用并丢弃旧的引用。
  • 替换HTML也可能会替换<脚本><样式>内容或HTML标记或属性名称,这并不总是需要的。
  • 更改HTML可能会导致攻击。
  • 您可能需要替换属性值,例如标题中高音,以可控的方式还有,但这些全有或全无的方法以及正则表达式没有能力这样做。

防范使用以下方法通常无法解决攻击。例如,如果取来call从页面上的某个位置读取URL,然后向该URL发送请求,下面的函数不会阻止这一点,因为这种情况本质上是不安全的。

替换所有元素的文本内容

这基本上会选择包含普通文本的所有元素,遍历其子节点(其中也包括文本节点),查找这些文本节点并替换其内容。

您可以选择指定不同的根目标,例如。replaceOnDocument(/€/g,“$”,{target:someElement});; 默认情况下<body>被选中。

constreplaceOnDocument=(模式,字符串,{target=document.body}={})=>{//句柄`string`-见最后一节[目标,…target.querySelectorAll(“*:not(script):not(noscript):not(style)”)].forEach(({childNodes:[…nodes]})=>个节点.filter(({nodeType})=>nodeType===节点。文本_代码).forEach((textNode)=>textNode.textContent=textNode.textContent.replace(pattern,string));};替换文档(/€/g,“$”);

替换文本节点、元素属性和属性

现在,这有点复杂:您需要检查三种情况:节点是否是文本节点,无论它是元素还是属性应该被替换,或者它是否是一个元素及其财产应该更换。A类替代品对象为文本节点和元素提供方法。

在替换属性和属性之前,替换者需要检查元素是否有匹配的属性;否则会创建不受欢迎的新属性。它还需要检查目标属性是否是字符串,因为只能替换字符串,或者与目标属性匹配的属性是否不是函数,因为这可能会导致攻击。

在下面的示例中,您可以看到如何使用扩展功能:在可选的第三个参数中,可以添加属性属性和道具属性,每个属性都是可迭代的(例如数组),分别用于要替换的属性和要替换的特性。

您还将注意到,此代码段使用平面地图。如果不支持,请使用polyfill或将其替换为减少凹面(concat),或地图减少凹面(concat)构造,如链接文档中所示。

const replaceOnDocument=(()=>{常量替换={[节点.TEXT_Node](节点、模式、字符串){node.textContent=节点.textContent.replace(pattern,string);},[Node.ELEMENT_Node](节点,模式,字符串,{attrs,属性}={}){attrs.forEach((attr)=>{if(节点类型[attr]!==“函数”&&node.hasAttribute(attr)){node.setAttribute(attr,node.getAttribute(attr).replace(pattern,string));}});props.forEach((prop)=>{if(节点类型[prop]===“字符串”&&node.hasAttribute(prop)){node[prop]=节点[prop].replace(pattern,string);}});}};return(pattern,string,{target=document.body,attrs:[…attrs]=[],props:[…props]=[]}={})=>{//句柄`string`-见最后一节[目标,...[目标,…target.querySelectorAll(“*:not(script):not(noscript):not(style)”)].flatMap(({childNodes:[…nodes]})=>个节点)].filter(({nodeType})=>replacer.hasOwnProperty(nodeType)).forEach((node)=>replacer[node.nodeType](节点、模式、字符串、{属性,道具}));};})();替换文档(/€/g,“$”{属性:[“标题”,“alt”,“onerror”//这将被忽略],道具:[“value”//更改`<input>`的`value`属性不会更改其当前值,因此需要在此处访问该属性]});

替换为HTML实体

如果需要使用HTML实体,如&害羞;,上述方法只会产生字符串&害羞;,因为那是一个HTML格式实体,并且仅在分配时有效.innerHTML或使用相关方法。

因此,让我们通过将输入字符串传递给接受HTML字符串的对象来解决这个问题:一个新的临时字符串HTML文档。这是由DOMParser公司parseFromString解析方法;最后我们读了它文档元素text内容:

string=new DOMParser().parseFromString(string,“text/html”).documentElement.textContent;

如果您想使用这种方法,请选择上述方法之一,具体取决于您是否要替换文本之外的HTML属性和DOM属性;然后简单地替换注释//句柄`string`-见最后一节按上面的行。

现在您可以使用replaceOnDocument(/Güterzug/G,“G&uuml;ter&shy;zug”);.

注意:如果不使用字符串处理代码,也可以删除{ }围绕箭头函数体。

注意,这会解析HTML实体,但仍然不允许插入实际的HTML标记,因为我们只读取text内容。这对大多数情况下的:因为我们正在使用解析自字符串和页面的文件没有受到影响,没有<脚本>下载了,但没有一个错误处理程序被执行。

您还应该考虑使用\x公元而不是&害羞;直接在JavaScript字符串中,如果结果更简单的话。

7
  • 1
    本身看起来很棒,但我需要用插入软连字符的相同单词替换单词。这是因为CSS连字符功能在某些荷兰语单词上出现了错误。然后,您的函数使浏览器呈现:低调(&S);雷姆ip&shy;总和(拉丁语示例)。你不会碰巧知道如何解决这个问题,是吗? 评论 2018年6月26日11:39
  • 2
    谢谢!你已经让我走上了正确的轨道内部HTML。我正在研究另一种方法,将两者兼而有之。因此,我们可以看到哪一个是下一个web开发人员最快、最容易维护的。正如阿诺德过去常说的那样:我会回来的。;-) 评论 2018年6月26日12:52
  • 2
    Hier bin ich wieder先生。实际上,我真的不知道如何测试脚本的速度。我可以想象一些事情,但仅此而已。然而,我确实想出了一个简单的分叉脚本,可以用其他普通单词替换,并可以插入HTML实体。请参见jsfiddle.net/FrankConijn/t1e0k2fx/4。将中央滚动条移至右侧,缩小输出字段,然后看到单词“me­de­wer kers­te­vre­den­heids­on­der­zoek”被连字符连接。 评论 2018年6月26日20:12
  • 1
    @FrankConijn尽管该解决方案使用内部HTML具有重写事件侦听器问题的替换… 评论 2018年6月26日20:49
  • 2
    @FrankConijn看是否可以附加到内部HTML而不破坏后代的事件侦听器?基本上,body.childrens[someChild].addEventListener(someEvent,someListener);然后body.innerHTML+=一些附加内容;body.innerHTML=someNewContent;序列化并重新传递整个HTML,清除任何以前绑定的事件侦听器。这就是为什么在我的方法中,我会小心地替换单个文本节点的内容。 评论 2018年6月26日21:00
22

我自己的建议如下:

函数nativeSelector(){var elements=document.querySelectorAll(“body,body*”);var结果=[];var子项;for(var i=0;i<元素长度;i++){child=元素[i].childNodes[0];if(elements[i].hasChildNodes()&&child.nodeType==3){结果:push(child);}}回报结果;}var textnodes=nativeSelector(),_nv;for(var i=0,len=textnodes.length;i<len;i++){_nv=textnodes[i].nodeValue;textnodes[i].nodeValue=_nv.replace(/英镑/g,‘€’);}

JS提琴演示.

这个本地选择器()函数来自答案(发布人阿努拉(Anurag))对于这个问题:textNodes的getElementsByTagName()等效项.

0
7

与@max-malik的答案类似,但不使用jQuery,也可以使用文档.createTreeWalker:

button.addEventListener('单击',e=>{const treeWalker=document.createTreeWalker(document.body,NodeFilter.SHOW_TEXT);while(treeWalker.nextNode()){const节点=treeWalker.currentNode;node.textContent=节点.textContent.replace(/@/g,'$');}})
<div>这是一个我们正在替换的@</div(分频)><div>这是我们正在替换的另一个@</div(分频)><div><span>这是@div中span中的@</span></div><br><input id=“button”type=“button“value=”将@替换为$“/>

1
  • 优雅而有表现力,这应该是公认的答案。 评论 2021年10月23日15:30
6

我想你可能想得太多了。

我的方法很简单。

用div标记将页面括起来:

<div id=“mydiv”><!-- 您在此处翻页--></div>

在javascript中:

var html=document.getElementById('mydiv').innerHTML;html=html.replace(/this/g,“that”);document.getElementById('mydiv').innerHTML=html;

在不使用jquery的javascript中:

document.body.innerText=文档.body.innerText.replace('actualword','replacementword');
  • 4
    不使用正则表达式,使用switch/modifier,它将只替换“actualword”的第一个实例。 评论 2013年9月5日18:54
  • 1
    请制作一个演示来证明这是有效的。在我的测试装置中,它没有任何作用, 评论 2018年6月26日11:00
  • 2
    @FrankConijn实际上您必须设置innerText,这在答案中没有显示。document.body.innerText=文档.body.innerText.replace('actualword','replacementword')...
    – 授予
    评论 2018年11月27日23:12

Vanilla JavaScript解决方案:

document.body.innerHTML=document.body.innerHTML.replacement(/Ooriginal/g,“新建”)
2

最好是在服务器端执行此操作,或者在将货币符号返回到浏览器之前将其包装在可以选择的元素中,但是,如果两者都不是选项,则可以选择正文中的所有文本节点并对其进行替换。下面我用了一个两年前写的插件来做这个,这个插件是用来突出显示文本的。我要做的是找到所有出现的€,并用类currency-symbol将其包装在span中,然后替换这些span的文本。

演示

(函数($){$.fn.highlightText=函数(){//处理程序第一个参数//第一个参数是regexp吗?var re,无功功率,h类,要求,argType=$.type(参数[0]),默认标记名=$.fn.highlightText.defaultTagName;if(argType===“regexp”){//第一个参数是正则表达式re=参数[0];}       //第一个参数是数组吗?else if(argType===“数组”){//第一个参数是数组,生成//供以后使用的正则表达式字符串reStr=参数[0].join(“|”);}       //第一个参数是字符串吗?else if(argType===“string”){//将字符串存储在正则表达式字符串中//供以后使用reStr=参数[0];}//否则,返回后什么也不做,因为//参数是必需的。其他{回报;}//然而,第二个参数是可选的,//它必须是字符串或布尔值。如果是的话//字符串,它将用作突出显示类。//如果它是一个布尔值并且等于true,则//将用作第三个参数和突出显示//类将默认为“高亮显示”。如果未定义,//highlight类将默认为“highlights”,并且//第三个参数将默认为false,允许//用于匹配部分匹配的插件。//**如果第一个参数是正则参数,则例外//表达式,第三个参数将被忽略。argType=$.type(参数[1]);if(argType===“字符串”){hClass=参数[1];}else if(argType===“boolean”){hClass=“highlight”;if(要求){reStr=“\\b”+reStr+“\\b“;}}其他{hClass=“highlight”;}if(参数[2]和reStr){reStr=reStr=“\\b”+reStr+“\\b“;} //如果未定义re(这意味着数组或//字符串作为第一个参数传递)创建//正则表达式。如果(!re){re=新RegExp(“(”+reStr+“)”,“ig”);}//迭代每个匹配的元素return this.each(function(){//选择此元素的所有内容$(this).find(“*”).andSelf().contents()//只筛选到尚未突出显示的文本节点.filter(函数(){return this.nodeType===3&&$(this).最近(“.”+hClass).长度===0;})//循环通过每个文本节点.each(函数(){无功输出;输出=this.nodeValue.replace(re,“<”+defaultTagName+“class='”+hClass+“'>$1”);if(输出!==this.nodeValue){$(this).wrap(“<p></p>”).parent().html(输出).contents().unwrap();}});});};$.fn.highlightText.defaultTagName=“span”;})(jQuery);$(“正文”).highlightText(“€”,“货币符号”);$(“span.currency-symbol”).text(“$”);
1
  • 2
    显然,在大型网站的body元素上执行此操作效率极低,因此您应该用一个选择器来替换“body”,该选择器可以选择出现此符号的所有区域。
    – 凯文·B
    评论 2013年9月5日19:27
2

使用拆分和连接方法

$(“#idBut”)点击(function(){$(“body”).children().each(function(){$(this).html($(this).html().split('@').jjoin(“$”));});});

这里是解决方案

2
  • 1
    实际上,这是最好的解决方案。因为在另一个解决方案中,您无法动态执行 评论 2016年8月16日6:11
  • 2
    @伊利亚斯·朱马杜德耶夫这不是最好的解决方案。这将覆盖DOM并销毁所有事件侦听器。 评论 2017年1月27日4:04
1

您可以使用:

str.replace(/text/g,“替换文本”);
2
1

对于文档中的每个元素身体使用修改其文本.text(fn)功能。

$(“body*”).text(函数(){return$(this).text().replace(“x”,“xy”);});
1
  • 但这会破坏HTML。 评论 2018年3月1日18:48
1

由于您仍将使用jQuery,请尝试:

https://github.com/cowdow/jquery-replacetext

那就做吧

$(“p”).replaceText(“£”,“$”)

它似乎能很好地替换文本而不干扰其他元素

0
str.replace(/replacetext/g,'actualtext')

这将替换的所有实例替换文本具有实际文本

  • 1
    作者希望“在文档中嗅出特定的文本字符”,而不仅仅是在字符串中 评论 2013年9月5日19:07
  • 1
    @问题中的MaxMalyk。。我认为很明显,嗅探部分已经完成&“str”值已经提取出来。 评论 2013年9月5日19:08
  • 1
    不,它不是:>>本质上;我想要一个单页文档的解决方案。抓取X的所有实例并使其成为XY。只有文本字符<< 评论 2013年9月5日19:10
0

以下内容可能有助于寻找此答案:下面使用jquery搜索整个文档,只替换文本。例如,如果我们

人口过剩</a>

我们想添加一个span,使类overpop围绕单词overplopulation

<a href=“/i-am/123/a/人口过剩”><span class=“overpop”>人口过剩</span></a>

我们将运行以下命令

$(“*:containsIN(‘过多’)”).filter(函数(){return$(this).find(“*:包含('”+str+“')”).length==0}).html(函数(_,html){if(html!=“未定义”){return html.replace(/(overplopulation)/gi,'<span class=“overpop”>$1</span>');}});

搜索不区分大小写,搜索整个文档,只替换文本部分,在这种情况下,我们搜索的是字符串“overplopulation”

$.extend($.expr[“:”]{“containsIN”:函数(elem,i,match,array){return(elem.textContent||elem.innerText||“”).toLowerCase().indexOf((match[3]||““”).toLowerCase())>=0;}});

你的答案

单击“发布您的答案”,表示您同意我们的服务条款并确认您已阅读我们的隐私政策.

不是你想要的答案吗?浏览标记的其他问题问你自己的问题.