如何使用 jQuery 为特定单词的所有实例设置样式 /parts/?

IT技术 javascript jquery string
2021-02-04 10:19:05

不寻常的情况。我有一个客户,我们称他们为“立即购买”。他们想为他们的名字的每个实例在其整个网站的副本,以程式化的类似“购买现在”,其中他们的名字下半年为黑体。

我真的不想花一天时间为所有副本添加 <strong> 标签。有没有使用 jQuery 做到这一点的好方法?

我已经看到了 jQuery 的高亮插件,它非常接近,但我只需要加粗该词的后半部分。

5个回答

为了可靠地做到这一点,您必须遍历文档中的每个元素,寻找文本节点,并在其中搜索文本。(这就是问题中提到的插件所做的。)

这是一个允许 RegExp 模式匹配的普通 JavaScript/DOM。jQuery 在这里并没有真正给你太多帮助,因为选择器只能选择元素,而 ':contains' 选择器是递归的,所以对我们来说不太有用。

// Find text in descendents of an element, in reverse document order
// pattern must be a regexp with global flag
//
function findText(element, pattern, callback) {
    for (var childi= element.childNodes.length; childi-->0;) {
        var child= element.childNodes[childi];
        if (child.nodeType==1) {
            findText(child, pattern, callback);
        } else if (child.nodeType==3) {
            var matches= [];
            var match;
            while (match= pattern.exec(child.data))
                matches.push(match);
            for (var i= matches.length; i-->0;)
                callback.call(window, child, matches[i]);
        }
    }
}

findText(document.body, /\bBuyNow\b/g, function(node, match) {
    var span= document.createElement('span');
    span.className= 'highlight';
    node.splitText(match.index+6);
    span.appendChild(node.splitText(match.index+3));
    node.parentNode.insertBefore(span, node.nextSibling);
});

正则表达式和replace()浮现在脑海中。就像是

var text = $([selector]).html();
text = text.replace(/Now/g,'<strong>Now<\strong>');
$([selector]).html(text);

使用html()此操作时要小心首先,有可能替换元素href属性中匹配的字符串<a>和其他可能导致页面不正确运行的属性。也许可以编写一个更好的正则表达式来克服一些潜在的问题,但性能可能会受到影响(我不是正则表达式专家)。其次,使用html()替换内容会导致不可序列化的数据(例如绑定到被替换元素标记的事件处理程序、表单数据等)丢失。编写一个仅针对文本节点的函数可能是更好/更安全的选择,这仅取决于页面的复杂程度。

如果您有权访问 HMTL 文件,如果内容是静态的,最好对他们想要更改文件中外观的单词进行查找和替换。NotePad++Find in Files选项在大多数情况下都适用于这项工作。

遵循 SingleShot 的建议并使用<span>CSS 类将提供比使用<strong>元素更大的灵活性

内容最终将在 CMS 中,因此进行全局查找/替换(在 Coda 中,就我而言:)不是我最喜欢的解决方案,尽管我想到了。我选择了另一种解决方案,因为粗体字也在整个网站中<strong>经常</strong>使用,包括页面名称,所以也不行。不过谢谢。:)
2021-03-15 10:19:05
您应该比文本更好地缓存元素: var elem = $([selector]); elem.html(elem.html().replace(/Now/g,'<strong>Now<\strong>'));
2021-03-16 10:19:05
只是测试一个!另请注意,设置html()将丢失所有不可序列化的信息,例如事件处理程序、JavaScript 引用和表单数据。
2021-03-29 10:19:05
@bobince - 我会在答案中提出一些警告。最安全的方法可能是仅对文本节点进行操作,但我看到您的答案中涵盖了该角度:)
2021-03-31 10:19:05
不要用正则表达式解析 HTML。<a href="BuyNow.html">-> oop。
2021-04-04 10:19:05

我写了一个小插件来做到这一点。看一下对类似问题的回答。

我强烈建议您使用我编写的插件,而不是下载已接受的答案中建议的插件——它要快得多。

var Run=Run || {};

Run.makestrong= function(hoo, Rx){
 if(hoo.data){
  var X= document.createElement('strong');
  X.style.color= 'red'; // testing only, easier to spot changes
  var pa= hoo.parentNode;
  var res, el, tem;
  var str= hoo.data;
  while(str && (res= Rx.exec(str))!= null){
   var tem= res[1];
   el= X.cloneNode(true);
   el.appendChild(document.createTextNode(tem));
   hoo.replaceData(res.index, tem.length,'');
   hoo= hoo.splitText(res.index);
   str= hoo.data;
   if(str) pa.insertBefore(el, hoo);
   else{
    pa.appendChild(el);
    return;
   }
  }
 }
}

Run.godeep= function(hoo, fun, arg){
 var A= [];
 if(hoo){
  hoo= hoo.firstChild;
  while(hoo!= null){
   if(hoo.nodeType== 3){
    if(hoo.data) A[A.length]= fun(hoo, arg);
   }
   else A= A.concat(arguments.callee(hoo, fun, arg));
   hoo= hoo.nextSibling;
  }
 }
 return A;
}

//test

**Run.godeep(document.body, Run.makestrong,/([Ee]+)/g);**

这不是一个 jQuery 脚本而是纯 javaScript,我相信它可以稍微改变一下。 链接