14 回答
这个怎么样,替换@
为$
:
$("body").children().each(function () {
$(this).html( $(this).html().replace(/@/g,"$") );
});
ECMAScript 2015+ 方法
解决此任务时的陷阱
这似乎是一项简单的任务,但您必须注意几件事:
- 简单地替换整个 HTML 会杀死所有 DOM 功能,比如事件监听器
- 替换 HTML 也可能替换
<script>
或替换<style>
内容,或 HTML 标记或属性,这并不总是需要的 - 更改 HTML 可能会导致xss攻击
- 您可能还想替换
title
和alt
(以受控方式)之类的属性
防范xss攻击一般不能通过以下方法解决。例如,如果fetch
调用从页面上的某处读取 URL,然后向该 URL 发送请求,则下面的函数不会阻止它,因为这种情况本质上是不安全的。
替换所有元素的文本内容
这基本上选择了所有包含普通文本的元素,遍历它们的子节点——其中也是文本节点——寻找那些文本节点并替换它们的内容。
您可以选择指定不同的根target
,例如replaceOnDocument(/€/g, "$", { target: someElement });
;默认情况下,<body>
选择 。
const replaceOnDocument = (pattern, string, {target = document.body} = {}) => {
// Handle `string` — see the last section
[
target,
...target.querySelectorAll("*:not(script):not(noscript):not(style)")
].forEach(({childNodes: [...nodes]}) => nodes
.filter(({nodeType}) => nodeType === document.TEXT_NODE)
.forEach((textNode) => textNode.textContent = textNode.textContent.replace(pattern, string)));
};
replaceOnDocument(/€/g, "$");
替换文本节点、元素属性和属性
现在,这有点复杂:您需要检查三种情况:一个节点是否是文本节点,它是否是一个元素并且它的属性应该被替换,或者它是否是一个元素并且它的属性应该被替换。replacer
对象为文本节点和元素提供方法。
在替换属性和属性之前,替换器需要检查元素是否有匹配的属性;否则会创建新的属性,这是不可取的。它还需要检查目标属性是否为字符串,因为只能替换字符串,或者与目标属性匹配的属性是否不是函数,因为这可能导致xss攻击。
在下面的示例中,您可以看到如何使用扩展功能:在可选的第三个参数中,您可以添加一个attrs
属性和一个props
属性,每个属性都是一个可迭代的(例如一个数组),用于要替换的属性和属性分别更换。
您还会注意到此代码段使用flatMap
. 如果不支持,请使用 polyfill 或将其替换为reduce
–<code>concat 或map
–<code>reduce–<code>concat 构造,如链接文档中所示。
const replaceOnDocument = (() => {
const replacer = {
[document.TEXT_NODE](node, pattern, string){
node.textContent = node.textContent.replace(pattern, string);
},
[document.ELEMENT_NODE](node, pattern, string, {attrs, props} = {}){
attrs.forEach((attr) => {
if(typeof node[attr] !== "function" && node.hasAttribute(attr)){
node.setAttribute(attr, node.getAttribute(attr).replace(pattern, string));
}
});
props.forEach((prop) => {
if(typeof node[prop] === "string" && node.hasAttribute(prop)){
node[prop] = node[prop].replace(pattern, string);
}
});
}
};
return (pattern, string, {target = document.body, attrs: [...attrs] = [], props: [...props] = []} = {}) => {
// Handle `string` — see the last section
[
target,
...[
target,
...target.querySelectorAll("*:not(script):not(noscript):not(style)")
].flatMap(({childNodes: [...nodes]}) => nodes)
].filter(({nodeType}) => replacer.hasOwnProperty(nodeType))
.forEach((node) => replacer[node.nodeType](node, pattern, string, {
attrs,
props
}));
};
})();
replaceOnDocument(/€/g, "$", {
attrs: [
"title",
"alt",
"onerror" // This will be ignored
],
props: [
"value" // Changing an `<input>`’s `value` attribute won’t change its current value, so the property needs to be accessed here
]
});
替换为 HTML 实体
如果您需要使其与 HTML 实体(如)一起使用­
,则上述方法只会从字面上生成 string ­
,因为这是一个HTML实体,并且仅在分配.innerHTML
或使用相关方法时才有效。
所以让我们通过将输入字符串传递给接受 HTML 字符串的东西来解决它:一个新的、临时的HTMLDocument
. 这是由DOMParser
'parseFromString
方法创建的;最后我们阅读了它documentElement
的textContent
:
string = new DOMParser().parseFromString(string, "text/html").documentElement.textContent;
如果您想使用它,请选择上述方法之一,具体取决于您是否要替换除文本之外的 HTML 属性和 DOM 属性;然后只需将注释替换为// Handle `string` — see the last section
上述行。
现在您可以使用replaceOnDocument(/Güterzug/g, "Güter­zug");
.
注意:如果你不使用字符串处理代码,你也可以去掉{
}
周围的箭头函数体。
请注意,这会解析 HTML 实体,但仍然不允许插入实际的 HTML 标签,因为我们只读取textContent
. 这对于大多数xss情况也是安全的:由于我们正在使用parseFromString
并且页面document
不受影响,因此不会<script>
下载任何onerror
处理程序并且不会执行任何处理程序。
如果结果更简单,您还应该考虑直接在 JavaScript 字符串中使用\xAD
而不是。­
我自己的建议如下:
function nativeSelector() {
var elements = document.querySelectorAll("body, body *");
var results = [];
var child;
for(var i = 0; i < elements.length; i++) {
child = elements[i].childNodes[0];
if(elements[i].hasChildNodes() && child.nodeType == 3) {
results.push(child);
}
}
return results;
}
var textnodes = nativeSelector(),
_nv;
for (var i = 0, len = textnodes.length; i<len; i++){
_nv = textnodes[i].nodeValue;
textnodes[i].nodeValue = _nv.replace(/£/g,'€');
}
该nativeSelector()
函数来自这个问题的答案(由Anurag发布):getElementsByTagName() 等效于 textNodes。
我想你可能想多了。
我的方法很简单。
用 div 标签括住您的页面:
<div id="mydiv">
<!-- you page here -->
</div>
在您的 javascript 中:
var html=document.getElementById('mydiv').innerHTML;
html = html.replace(/this/g,"that");
document.getElementById('mydiv').innerHTML=html;
类似于@max-malik 的答案,但不使用 jQuery,您也可以使用document.createTreeWalker执行此操作:
button.addEventListener('click', e => {
const treeWalker = document.createTreeWalker(document.body);
while (treeWalker.nextNode()) {
const node = treeWalker.currentNode;
node.textContent = node.textContent.replace(/@/g, '$');
}
})
<div>This is an @ that we are @ replacing.</div>
<div>This is another @ that we are replacing.</div>
<div>
<span>This is an @ in a span in @ div.</span>
</div>
<br>
<input id="button" type="button" value="Replace @ with $" />
香草 JavaScript 解决方案:
document.body.innerHTML = document.body.innerHTML.replace(/Original/g, "New")
在不使用 jquery 的 javascript 中:
document.body.innerText = document.body.innerText.replace('actualword', 'replacementword');
最好是在服务器端执行此操作或将货币符号包装在您可以选择的元素中,然后再将其返回给浏览器,但是如果两者都不是选项,您可以选择正文中的所有文本节点并对其进行替换. 下面我正在使用我 2 年前编写的插件来执行此操作,该插件旨在突出显示文本。我正在做的是找到所有出现的 € 并将其包装在一个带有类货币符号的跨度中,然后我将替换这些跨度的文本。
(function($){
$.fn.highlightText = function () {
// handler first parameter
// is the first parameter a regexp?
var re,
hClass,
reStr,
argType = $.type(arguments[0]),
defaultTagName = $.fn.highlightText.defaultTagName;
if ( argType === "regexp" ) {
// first argument is a regular expression
re = arguments[0];
}
// is the first parameter an array?
else if ( argType === "array" ) {
// first argument is an array, generate
// regular expression string for later use
reStr = arguments[0].join("|");
}
// is the first parameter a string?
else if ( argType === "string" ) {
// store string in regular expression string
// for later use
reStr = arguments[0];
}
// else, return out and do nothing because this
// argument is required.
else {
return;
}
// the second parameter is optional, however,
// it must be a string or boolean value. If it is
// a string, it will be used as the highlight class.
// If it is a boolean value and equal to true, it
// will be used as the third parameter and the highlight
// class will default to "highlight". If it is undefined,
// the highlight class will default to "highlight" and
// the third parameter will default to false, allowing
// the plugin to match partial matches.
// ** The exception is if the first parameter is a regular
// expression, the third parameter will be ignored.
argType = $.type(arguments[1]);
if ( argType === "string" ) {
hClass = arguments[1];
}
else if ( argType === "boolean" ) {
hClass = "highlight";
if ( reStr ) {
reStr = "\\b" + reStr + "\\b";
}
}
else {
hClass = "highlight";
}
if ( arguments[2] && reStr ) {
reStr = reStr = "\\b" + reStr + "\\b";
}
// if re is not defined ( which means either an array or
// string was passed as the first parameter ) create the
// regular expression.
if (!re) {
re = new RegExp( "(" + reStr + ")", "ig" );
}
// iterate through each matched element
return this.each( function() {
// select all contents of this element
$( this ).find( "*" ).andSelf().contents()
// filter to only text nodes that aren't already highlighted
.filter( function () {
return this.nodeType === 3 && $( this ).closest( "." + hClass ).length === 0;
})
// loop through each text node
.each( function () {
var output;
output = this.nodeValue
.replace( re, "<" + defaultTagName + " class='" + hClass + "'>$1</" + defaultTagName +">" );
if ( output !== this.nodeValue ) {
$( this ).wrap( "<p></p>" ).parent()
.html( output ).contents().unwrap();
}
});
});
};
$.fn.highlightText.defaultTagName = "span";
})( jQuery );
$("body").highlightText("€","currency-symbol");
$("span.currency-symbol").text("$");
使用拆分和连接方法
$("#idBut").click(function() {
$("body").children().each(function() {
$(this).html($(this).html().split('@').join("$"));
});
});
这是解决方案
对于文档中的每个元素,使用.text(fn)函数body
修改其文本。
$("body *").text(function() {
return $(this).text().replace("x", "xy");
});
因为无论如何您都将使用 jQuery,请尝试:
https://github.com/cowboy/jquery-replacetext
然后就做
$("p").replaceText("£", "$")
只替换文本而不弄乱其他元素似乎做得很好
您可以使用:
str.replace(/text/g, "replaced text");
str.replace(/replacetext/g,'actualtext')
replacetext
这将替换with的所有实例actualtext
这可能有助于寻找此答案的人:以下使用 jquery 它搜索整个文档并仅替换文本。例如,如果我们有
<a href="/i-am/123/a/overpopulation">overpopulation</a>
我们想在 overpopulation 这个词周围添加一个带有类 overpop 的跨度
<a href="/i-am/123/a/overpopulation"><span class="overpop">overpopulation</span></a>
我们将运行以下
$("*:containsIN('overpopulation')").filter(
function() {
return $(this).find("*:contains('" + str + "')").length == 0
}
).html(function(_, html) {
if (html != 'undefined') {
return html.replace(/(overpopulation)/gi, '<span class="overpop">$1</span>');
}
});
搜索不区分大小写搜索整个文档并仅替换文本部分在这种情况下我们正在搜索字符串“overpopulation”
$.extend($.expr[":"], {
"containsIN": function(elem, i, match, array) {
return (elem.textContent || elem.innerText || "").toLowerCase().indexOf((match[3] || "").toLowerCase()) >= 0;
}
});