【问题标题】:jQuery search (:contains) without punctuation excluding specific classjQuery 搜索 (:contains) 没有标点符号,不包括特定的类
【发布时间】:2012-08-22 12:55:08
【问题描述】:

目前我在 html 文件中的 div 中搜索,如果在其中找到结果,则删除 hideMe 类,以显示找到的赞美诗。我想知道我是否可以在没有标点符号的情况下搜索赞美诗(从输入和输出中删除标点符号),同时从搜索中排除 info 类。

<div id="himnario">
   <div id="1" class="song hideMe">
      <div class="info">I don't want this info to be searched</div>
      <div class="tuneName">This tune should be searched</div>
      <ol>
         <li>Verse 1</li>
         <li>Verse 2</li>
      </ol>
   </div>
   <div id="2" class="song hideMe">...</div>
</div>

我目前的搜索代码是:

$("#himnario div.song:Contains("+item+")").removeClass('hideMe').highlight(item);
isHighlighted = true; //check if highlighted later and unhighlight, for better performance

(用“包含”扩展jquery如下)

return jQuery(a).text().toUpperCase().indexOf(m[3].toUpperCase()) >= 0; 

另外,我使用jquery plugin 来突出显示结果,所以我想这会使事情复杂化。如果需要,对于标点符号妨碍的那些地方,高亮可能会失效。

当然,效率越高越好,因为这将成为移动应用程序的一部分...如果从搜索中删除 info 类需要很长时间,我将不得不从文件中删除它,因为它不是不是绝对必要的。

我从here 中发现了以下代码可能会有所帮助,它应该去除无效字符,但由于我有限的编码能力,我不确定如何将其正确地合并到自定义包含函数中。

Return Regex.Replace(strIn, "[^\w\.@-]", "")

非常感谢您的帮助。

编辑:感谢@Nick,这是首选的解决方案:

$('#himnario').children().addClass('hideMe'); // hide all hymns
//http://stackoverflow.com/questions/12152098/jquery-search-contains-without-punctuation-excluding-specific-class
// Get rid of punctuation in your search item - this only allows alphanumeric
item2 = item.toUpperCase().replace(/<(.|\n)*?>|[^a-z0-9\s]/gi, ''); 
// Loop though each song
$('#himnario').children().each(function() {
    var $this_song = $(this);
    // Examine the song title & the ordered list, but not the hidden info (first child)
    $this_song.children('.tuneName, ol').each(function() {
        // Get the html, strip the punctuation and check if it contains the item
        if ($(this).html().toUpperCase().replace(/<(.|\n)*?>|[^a-z0-9\s]/gi, '').indexOf(item2) !== -1) {
            // If item is contained, change song class
            $this_song.removeClass('hideMe').highlight(item); //original search phrase
            isHighlighted = true; //check later, for better performance
            return false;   // Prevents examination of song lines if the title contains the item
        } 
    });            
});

高亮功能:

/*
highlight v3
Highlights arbitrary terms.
<http://johannburkard.de/blog/programming/javascript/highlight-javascript-text-higlighting-jquery-plugin.html>
MIT license.
Johann Burkard
<http://johannburkard.de>
<mailto:jb@eaio.com>
*/
jQuery.fn.highlight = function(pat) {
 function innerHighlight(node, pat) {
  var skip = 0;
  if (node.nodeType == 3) {
   var pos = node.data.toUpperCase().indexOf(pat);
   if (pos >= 0) {
    var spannode = document.createElement('span');
    spannode.className = 'highlight';
    var middlebit = node.splitText(pos);
    var endbit = middlebit.splitText(pat.length);
    var middleclone = middlebit.cloneNode(true);
    spannode.appendChild(middleclone);
    middlebit.parentNode.replaceChild(spannode, middlebit);
    skip = 1;
   }
  }
  else if (node.nodeType == 1 && node.childNodes && !/(script|style)/i.test(node.tagName)) {
   for (var i = 0; i < node.childNodes.length; ++i) {
    i += innerHighlight(node.childNodes[i], pat);
   }
  }
  return skip;
 }
 return this.each(function() {
  innerHighlight(this, pat.toUpperCase());
 });
};

jQuery.fn.removeHighlight = function() {
 return this.find("span.highlight").each(function() {
  this.parentNode.firstChild.nodeName;
  with (this.parentNode) {
   replaceChild(this.firstChild, this);
   normalize();
  }
 }).end();
};

【问题讨论】:

  • 排除 .info 类是什么意思,您根本不想搜索该元素,而只是不想在页面上显示它?
  • @adeneo,我目前有 .info 隐藏在 display:none;这是我不想在搜索中找到的额外曲调信息,但当然它目前被拾取,因为它只是被隐藏了。

标签: jquery search contains


【解决方案1】:

为什么不直接使用 Javascript 来完成这项工作?一个简单的正则表达式应该可以解决问题:

str.replace(/[^a-z0-9\s]/gi, '')

这将采用字符串str 并删除任何不是数字或字母(字母数字)的字符。如果我是你,我不会覆盖原始 HTML(当然,除非那是重点),而是我会将 HTML 的值存储在一个字符串 str 中,然后对其执行讨厌的正则表达式那里。这样,原始 HTML 将保持完整,如果您愿意,您仍然可以使用和输出新字符串。真的不需要 jQuery,:contains 只需要slow you down

【讨论】:

  • 谢谢,我试过这个正则表达式,它也像尼克的/[\W]/gi, ''一样工作,不确定速度是否有差异。
  • 更新:由于 \s 用于保留空格,这实际上效果更好。
  • 那你应该点赞或标记为正确,这样其他人就可以看到效率的提高。
  • 我想给它投票,但我不能用我的点数限制。我可以将多个答案标记为正确吗?尼克提供了完整的解决方案。
  • 你不能,但这没什么大不了的。只要尼克的回答足够,那就太好了!
【解决方案2】:

如果你通过 id 直接找到一个元素,然后从那里过滤,jQuery 的工作速度最快。所以,我假设你的 HTML 是这样的:

<div id="himnario">
    <div id="1" class="song hideMe">
        <div class="info">Hidden text</div>
        <div class="tuneName">Search me!</div>
        <ol>
            <li>Verse 1</li> 
            <li>Verse 2</li>
        </ol>
    </div>
    <div id="2" class="song hideMe">
        ...
    </div>
</div>

要最有效地查找歌曲,请执行以下操作:

$('#himnario').children()...

注意:children()find() 好得多,因为它只搜索到一个级别的深度。如果只有儿童歌曲,则不指定 .song 会加快速度。如果是这样,你已经走得更快了。

一旦你有了孩子,你就可以使用each(),这不是绝对最快的方式,但没关系。所以这会检查每首歌曲/孩子:

$('#himnario').children().each(function(index) {...});

对于您的情况:

// Get rid of punctuation in you search item - this only allows alphanumeric
item = item.replace(/[\W]/gi, '');

// Loop though each song
$('#himnario').children().each(function() {
    var $this_song = $(this);

    // Loop through each line in this song [EDIT: this doesn't account for the title]
    $this_song.find('li').each(function() {

        // Get the html from the line, strip the punctuation and check if it contains the item
        if $(this).html().replace(/[\W]/gi, '').indexOf(item) !== -1 {
            // If item is contained, change song class
            $this_song.removeClass('hideMe');
            return false;   // Stops each_line loop once found one instance of item
        } 
    }            
});

我没有对突出显示做任何事情。我也没有对此进行测试,但是一旦发现任何小错误,它应该可以正常工作:)

编辑:根据您的“歌曲标题”字段,您可以执行以下操作:

// Get rid of punctuation in you search item - this only allows alphanumeric
item = item.replace(/[\W]/gi, '');

// Loop though each song
$('#himnario').children().each(function() {
    var $this_song = $(this);

    // Examine the song title & the ordered list, but not the hidden info (first child)
    $this_song.children().not(':first').each(function() {

        // Get the html, strip the punctuation and check if it contains the item
        if $(this).html().replace(/[\W]/gi, '').indexOf(item) !== -1 {
            // If item is contained, change song class
            $this_song.removeClass('hideMe');
            return false;   // Prevents examination of song lines if the title contains the item
        } 
    }            
});

这个版本应该比循环遍历每一行更快。另请注意,我已从 .each 调用中删除了 indexindex2 变量,因为您不使用它们。

【讨论】:

  • 感谢所有的帮助和努力!我想通过将 tuneName 类添加到赞美诗结构中的编辑,我将不得不使用您的第一个示例并在 li 或 .tuneName 中搜索?
  • @Nathan 我已经编辑了代码以允许tuneName。我也意识到,我原来的第二个版本(我现在已经删除了)不允许你不想搜索隐藏字段的事实。上面的代码应该可以很好地改变歌曲的类别。你不应该真的需要这个插件,除非我误解了你想要做什么。如果我有,请随时询问:)
  • 太棒了!这很好用。我做了一些小的调整,比如添加 .toUpperCase、突出显示代码和语法,但效果非常好。您可以在link 看到工作结果。我认为唯一可以改进的是突出显示不适用于标点符号有所不同的搜索,但这没什么大不了的。我将尝试将解决方案代码粘贴到上面的编辑中...
  • 我应该对第一行 $('#himnario').children().addClass('hideMe'); 做一些不同的事情以使其更快吗?我想知道添加 :visible 是否会更快,所以它只检查可见元素,但我不确定这是否有帮助。像('#himnario').children().addClass('hideMe').each(function() { 这样的东西?再次感谢,您帮了大忙。
  • 再想一想,我什至不想担心亮点交易,所以也不要为此烦恼。我敢肯定这需要更多的正则表达式和处理时间,他们会意识到这不是完全匹配,因为它没有突出显示。
猜你喜欢
  • 1970-01-01
  • 2021-11-21
  • 1970-01-01
  • 1970-01-01
  • 2014-02-13
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2017-08-22
相关资源
最近更新 更多