【问题标题】:Search body for string and then style在正文中搜索字符串,然后搜索样式
【发布时间】:2016-02-21 14:50:51
【问题描述】:

我需要使用 jQuery 搜索文档以找到特定的单词。它实际上是一个品牌名称,无论在何处使用,都必须是粗体和斜体。

我可以使用:contain 做到这一点,但只能基于单个元素。我需要能够浏览锚点、列表 div 等。

$( "a:contains('brand name')" ).html().replace('brand name'.... 

任何想法都将不胜感激。

更新: 我已经做到了这一点,它可以工作并替换页面上的所有内容,但我现在需要用一个类包装一个跨度。如此接近,但难住了这一点。再次提出想法将不胜感激。

    $("body *").contents().each(function() {
  if(this.nodeType==3){
    this.nodeValue = this.nodeValue.replace(/brandname/g, 'colour');

  }
});

【问题讨论】:

  • $( ":contains('brand name')" ) 将返回所有元素。
  • It's actually a brand name that has to be bold and italic wherever used & I can do this using :contain but only on an individual element basis. I need to be able to go through anchors, lists divs etc. 但是在 b 元素中包装 div 不是有效的 HTML 标记。不太清楚你在期待什么?
  • @A.Wolff - 在任何情况下都期望单词并且只有单词“BrandName”被包裹在跨度中。不是
    BrandName
    ,而是
    BrandName

标签: jquery replace contains nodevalue


【解决方案1】:

您可以将 textNodes 替换为文档片段。这允许您对文本和样式节点进行分组,并将其与现有的 textNode 交换。

var x = 0;
$("body *").contents().each(function() {

   if (this.nodeType == 3 && this.parentElement.tagName != "SCRIPT") {

     var text = this.nodeValue;
     var i = 0, lastIndex = 0;
     var search = /brandname/ig;
     var result;
     var parent = this.parentNode;
     var textNode = null;
     var highlight = null;
     var textRange = "";
     var fragment = document.createDocumentFragment();

     // Do search
     while ((result = search.exec(text)) !== null) {
    
       // add plain text before match
       textRange = text.substring(lastIndex, result.index);
       if (textRange != '') {
         textNode = document.createTextNode(textRange);
         fragment.appendChild(textNode);
       }
       
       // add highlight elements
       highlight = document.createElement('span');
       highlight.innerHTML = result[0];
       highlight.className = "hi";
       fragment.appendChild(highlight);
       lastIndex = search.lastIndex;
     }

     // Add trailing text
     textRange = text.substring(lastIndex);
     if (textRange != '') {
       textNode = document.createTextNode(textRange);
       fragment.appendChild(textNode);
     }
     
     // Replace textNode with our text+highlight
     if(fragment.children.length > 0) {
       this.parentNode.replaceChild(fragment, this);
     }
   }

 });
span.hi {
  background-color: #FFCC00;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<p>
  Hello world this is my brandname. The BrAnDNAMe is regex matched and we can change subelements like "<a href=''>Brandname</a>." It should not replace <b>elements</b> that don't match.
</p>

【讨论】:

    【解决方案2】:

    $.fn.ignore = function(sel){
      return this.clone().find(sel||">*").remove().end();
    };
    
    function rebrand(el, word){
      if (!word.length && !el) return;
      var $el = $(el), html = $el.ignore("script").html(),
          rgx = new RegExp("(?![^<]+>)("+ word +")", "g");
      $el.html( html.replace(rgx, "<span class='brand'>$1</span>") );
    }
    
    $(function() { // DOM ready
    
      // !!!  IMPORTANT: REBRAND FIRST !!!
      rebrand("body", "Brand Name");
      // so the following code will not break on lost events, data bindings etc...
    
      // Other DOM ready code here like:
      $("button").click(function(){ $(this).css({color:"red"}); });
      
    });
    
    // Other JS, jQ code here...
    .brand{
        color: rgba(255,0, 100,0.4);
        font: italic normal bold 1em/1 sans-serif;
    }
    <script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
    <div>
      <h1>Title with Brand Name!</h1>
      <p>
        Change styles only to Brand Name!<br>
        but don't mess with <a href="#">links to Brand Name are cool</a><br>
        <button>Button with Brand Name works!</button>
      </p>
      <ul>
        <li>Other Brand</li><li>Brand Name</li><li>Brandy</li>
      </ul>
    </div>
    <div>
      <h2>Subtitle <i>and italic Brand Name</i></h2>
      <p>The HTML will not get messed cause of Brand Nameing<br>
      Paragraph with a &lt;b&gt; tag <b>bold Brand Name actually</b></p>
      <code>This is a code tag with a Brand Name :)</code>
    </div>

    感谢这两个答案:
    jQuery.ignore Plugin
    Highlight Words (Ignoring names of HTML tags)

    【讨论】:

      【解决方案3】:

      如果您的代码有效,只需添加这样类似的代码行:

      this.nodeValue.wrap( "<span class='new'></span>" );
      

      【讨论】:

        【解决方案4】:
        var rgx_BRAND = /(foo)/ig;
        $("*")
            .contents()
            .filter(function() {
                return this.nodeType === Node.TEXT_NODE && this.textContent.search(rgx_BRAND) > -1;
            })
            .each(function(){
                var html = this.textContent.replace(rgx_BRAND, '<b class="-my-brand">$1</b>');
                $(this).before(html).remove();
            });
        

        希望这有帮助,干杯

        【讨论】:

          【解决方案5】:

          我的解决方案与之前的解决方案略有不同,但我认为无论如何总是有效的。

          在下面我的 jQuery 函数中:

          function replaceBrand(brandName) {
              $('body').find(":not(iframe)").contents().filter(function(index, element) {
              if (element.nodeType == 3 && element.nodeValue.indexOf(brandName) != -1) {
                  var newInnerValue = element.nodeValue.replace(brandName, '<div><span class="brand">' + brandName + '</span></div>');
                  $(element).replaceWith(newInnerValue);
              }
          });
          

          }

          replaceBrand('品牌名称', '新品牌');

          【讨论】:

            【解决方案6】:

            从你的 sn-p 出发:

            $(function() {
                var parent, needle = 'brandname',
                    regex = new RegExp(needle, 'g');
                $("body *").contents().each(function() {
                    if(this.nodeType==3 && ((parent = $(this.parentNode)).length > 0) {
                        parent.html(parent.html().replace(
                            regex, '<span class="brand-name">' + needle + '</span>'));
                    }
                }
            });
            

            这可能不是最有效的方法,但相当容易并且可以在我的测试中完成工作。查找 parentNode 属性应该可以在 all browsers 中使用。

            【讨论】:

            • 小心,这也将替换父级中与品牌名称匹配的任何类名或其他属性值。这可能是 OP 使用 nodeValue 的原因。
            猜你喜欢
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 2021-03-26
            • 1970-01-01
            • 2015-09-11
            • 1970-01-01
            • 1970-01-01
            • 2012-11-01
            相关资源
            最近更新 更多