使用jQuery键入时过滤列表

时间:2009-11-20 17:25:38

标签: jquery ajax

我计划使用简单的数据库查询创建我的Web应用程序的无序用户列表,但之后计划让人们通过在文本输入中键入他们正在寻找的人名来过滤此列表。 / p>

我希望使用jQuery将输入框中的字符串与列表项中的任何一个匹配,然后隐藏其他项,可能是通过动态地将新类应用于包含匹配字符串的类,并隐藏所有其他不包含该类的人。

有没有人知道这样做的好方法?

6 个答案:

答案 0 :(得分:49)

假设您的ulid theList,以下是这样做的一种方式。

<input type="text" onkeyup="filter(this)" />

<script language="javascript" type="text/javascript">
    function filter(element) {
        var value = $(element).val();

        $("#theList > li").each(function() {
            if ($(this).text().search(value) > -1) {
                $(this).show();
            }
            else {
                $(this).hide();
            }
        });
    }
</script>

或者,对于基于Marek Tihkan发布的更简洁的版本,您可以使用以下内容替换each()循环。不确定这是否会表现更好或更差。

$('#theList > li:not(:contains(' + value + '))').hide(); 
$('#theList > li:contains(' + value + ')').show();

答案 1 :(得分:10)

如果输入文本为空,则Nikolas给出的解决方案与Marek之间的解决方案会出现错误。
下面的解决方案纠正了该问题并适用于由'a'标签包围的列表。

该函数还用于过滤元素,其中第一个字母为大写字母(例如带有名称)。因此排序过滤。如果您输入'An'或'an',那么您将从这些字母开始获取列表中的所有元素(例如,Anthony将匹配但Fanny no)。

function filter (element,what) {
    var value = $(element).val();
    value = value.toLowerCase().replace(/\b[a-z]/g, function(letter) {
        return letter.toUpperCase();
    });

    if (value == '') {
        $(what+' > a > li').show();
    }
    else {
        $(what + ' > a > li:not(:contains(' + value + '))').hide();
        $(what + ' > a > li:contains(' + value + ')').show();
    }
};

以下是与脚本配合使用的示例HTML代码:

<input type="text" onkeyup="filter(this,'theList')" />
<ul id="theList">
    <li><a href="">Tyrone Schlecht</a></li>
    <li><a href="">Javier Ress</a></li>
    <li><a href="">Carlene Tomes</a></li>
    <li><a href="">Neil Aigner</a></li>
    <li><a href="">Nita Schreffler</a></li>
    <li><a href="">Clinton Knuckles</a></li>
    <li><a href="">Eve Kellett</a></li>
    <li><a href="">Jamie Kaspar</a></li>
    <li><a href="">Emilia Hooton</a></li>
    <li><a href="">Kenya Sidney</a></li>
</ul>

答案 2 :(得分:7)

我通过迭代所有这些并隐藏那些不匹配的女巫并展示了匹配的那些来做到了。

$('li').hide(); 
$('li:contains(' + needle + ')').show();

答案 3 :(得分:2)

你可以使用LiveQuery从John移植到php的jQuery。

注意:它依赖于Quicksilver's score method in PHP方法,该方法已由LiquidMetal.scorejoshaven's string.score

移植到JavaScript

使用示例

$("#text_box_selector").liveUpdate("#list_selector");

注意#list_selector必须找到包含li元素的元素

插件+排序+现场演示

// https://github.com/joshaven/string_score
String.prototype.score = function (word, fuzziness) {
  'use strict';

  // If the string is equal to the word, perfect match.
  if (this === word) { return 1; }

  //if it's not a perfect match and is empty return 0
  if (word === "") { return 0; }

  var runningScore = 0,
      charScore,
      finalScore,
      string = this,
      lString = string.toLowerCase(),
      strLength = string.length,
      lWord = word.toLowerCase(),
      wordLength = word.length,
      idxOf,
      startAt = 0,
      fuzzies = 1,
      fuzzyFactor,
      i;

  // Cache fuzzyFactor for speed increase
  if (fuzziness) { fuzzyFactor = 1 - fuzziness; }

  // Walk through word and add up scores.
  // Code duplication occurs to prevent checking fuzziness inside for loop
  if (fuzziness) {
    for (i = 0; i < wordLength; i+=1) {

      // Find next first case-insensitive match of a character.
      idxOf = lString.indexOf(lWord[i], startAt);

      if (idxOf === -1) {
        fuzzies += fuzzyFactor;
      } else {
        if (startAt === idxOf) {
          // Consecutive letter & start-of-string Bonus
          charScore = 0.7;
        } else {
          charScore = 0.1;

          // Acronym Bonus
          // Weighing Logic: Typing the first character of an acronym is as if you
          // preceded it with two perfect character matches.
          if (string[idxOf - 1] === ' ') { charScore += 0.8; }
        }

        // Same case bonus.
        if (string[idxOf] === word[i]) { charScore += 0.1; }

        // Update scores and startAt position for next round of indexOf
        runningScore += charScore;
        startAt = idxOf + 1;
      }
    }
  } else {
    for (i = 0; i < wordLength; i+=1) {
      idxOf = lString.indexOf(lWord[i], startAt);
      if (-1 === idxOf) { return 0; }

      if (startAt === idxOf) {
        charScore = 0.7;
      } else {
        charScore = 0.1;
        if (string[idxOf - 1] === ' ') { charScore += 0.8; }
      }
      if (string[idxOf] === word[i]) { charScore += 0.1; }
      runningScore += charScore;
      startAt = idxOf + 1;
    }
  }

  // Reduce penalty for longer strings.
  finalScore = 0.5 * (runningScore / strLength    + runningScore / wordLength) / fuzzies;

  if ((lWord[0] === lString[0]) && (finalScore < 0.85)) {
    finalScore += 0.15;
  }

  return finalScore;
};

// http://ejohn.org/apps/livesearch/jquery.livesearch.js
jQuery.fn.liveUpdate = function(list) {
  list = jQuery(list);

  if (list.length) {
    var rows = list.children('li'),
      cache = rows.map(function() {
        return this.innerHTML.toLowerCase();
      });

    this
      .keyup(filter).keyup()
      .parents('form').submit(function() {
        return false;
      });
  }

  return this;

  function filter() {
    var term = jQuery.trim(jQuery(this).val().toLowerCase()),
      scores = [];

    if (!term) {
      rows.show();
    } else {
      rows.hide();

      cache.each(function(i) {
        var score = this.score(term);
        if (score > 0) {
          scores.push([score, i]);
        }
      });

      jQuery.each(scores.sort(function(a, b) {
        return b[0] - a[0];
      }), function() {
        jQuery(rows[this[1]]).show();
      });
    }
  }
};

$("#search").liveUpdate("#colors");
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.1/jquery.min.js"></script>

<input type="text" id="search"><br/>

<ul id="colors">
  <li>Cat Book</li>
  <li>Dog Basket</li>
  <li>Bear Cub</li>
  <li>Car Door</li>
  <li>Another option</li>
  <li>Another Animal</li>
</ul>

答案 4 :(得分:1)

// Just a shorter version
$('ul>li').hide().has(':contains(' + needle + ')').show();

// case insensitive searching with animation
$("ul>li").slideUp().filter( function() {
     return $(this).text().toLowerCase().indexOf(needle) > -1
}).stop(true).fadeIn();

答案 5 :(得分:0)

this W3 example的主要灵感中,我开发了一个可能的替代方案compact solution

在示例中,链接可能会看到3个不同的选项:

  • 仅过滤UL项目
  • 过滤任何项目
  • 使用CSS动画效果过滤任何项目

以下是最简单的JS代码,该代码只需借助$("#anyItemList *")选择器就可以过滤任何类型的元素:

  $("#anyItemListInputFilter").on("keyup", function() {
    var value = $(this).val().toLowerCase();
    $("#anyItemList *").filter(function() {
        let item = $(this).text().toLowerCase().indexOf(value) > -1;
      $(this).toggle(item);
    });
  });

如果所需过滤仅用于UL列表,则可以使用$("#ulList li")来更改选择器(例如)

如果您还想添加CSS动画效果,则存在一些限制:

  • max-height中需要预定义的px(如果设置足够高的话,可能影响不大)
  • overflow-y:hidden;

所以我被迫宣布:

#anyItemAnimatedList * {
  transition:all 0.5s ease;
  opacity:1;
  max-height:500px;
 overflow-y:hidden;
}

#anyItemAnimatedList ul {
  list-style-position:inside;
}

#anyItemAnimatedList .hidden {
  max-height:0;
  opacity:0;
  border:0;
}

隐藏效果是结合opacitymax-height CSS过渡而来的,border:0对于覆盖button标签默认浏览器样式是必需的。

此外,由于OLUL列表对于设置list-style-position:inside;是必要的,因为Firefox和Chrome共享一个奇怪的默认行为,在默认{{ 1}}。

对于Firefox,自2003年以来,这是known bug !!!而且还有Chrome has the same behaviour