使用jQuery使用非拉丁字符搜索过滤器功能

时间:2018-08-25 09:51:15

标签: jquery html css

基于我之前的question,我试图在社区的帮助下构建一个搜索过滤器功能,即使用户在搜索输入字段中输入非拉丁字符(在这种情况下,该字符也是如此)瑞典字母)。

这是我到目前为止所拥有的:

var langMap = {
'a' : 'å',
'a' : 'ä',
'o' : 'ö'
}

$('#search-items-box').keyup(function(){
   var valThis = $(this).val().toLowerCase();
   var filteredWord = valThis.split('').map(function(letter){
   	if (langMap[letter]) {
    	return langMap[letter];
    }
    return letter;
   }).join('');
   
    if(filteredWord == ""){
        $('.itemsList .m3-item').show();           
    } else {
        $('.itemsList .m3-item').each(function(){
            var text = $(this).text().toLowerCase();
            (text.indexOf(filteredWord) == 0) ? $(this).show() : $(this).hide();
        });
   }
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.9.1/jquery.min.js"></script>
<input placeholder="Search Me" id="search-items-box" type="text" /> 

<div class="itemsList">
<div class="m3-item">Orånge</div>
<div class="m3-item">Banäna</div>
<div class="m3-item">Potatö</div>
</div>

问题是搜索无法正常进行。如果尝试键入三个单词,您会注意到结果没有显示。

JSFIDDLE Here

2 个答案:

答案 0 :(得分:1)

第一个条件是,如果满足此条件,则在每次击键时都要更改字符输入:

if (langMap[letter]) {
    return langMap[letter];

现在,当您键入'b'时,香蕉将出现在搜索中,因为'b'不是langMap数组的一部分,因此不会被修改。它搜索以'b'开头的任何单词,搜索结果为'Banäna'

但是,一旦您输入“ a”,香蕉便不再存在,因为它已转换为“å”。结果,它正在搜索“bå”,该结果将返回零结果(按预期)。

另一方面,您稍后还会在langMap数组中遇到另一个问题:

var langMap = {
    'a' : 'å',
    'a' : 'ä',
    'o' : 'ö'
};

您有一个键'a',它定义了两个不同的值。其中一个值将永远无法访问。

根据我们的讨论,这是我建议的解决方案:

  • 反转langMap的键和值
  • 将比较后的文本转换为拉丁字符

     var langMap = {
      "å":"a",
      "ä":"a",
      "ö":"o"
     }
    
     $('#search-items-box').keyup(function(){
      var valThis = $(this).val().toLowerCase();
      var filteredWord = getLatinWord(valThis);
    
      if(filteredWord == ""){
          $('.itemsList .m3-item').show();           
      } else {
          $('.itemsList .m3-item').each(function(){
              var text = $(this).text().toLowerCase();
              text = getLatinWord(text);
              (text.indexOf(filteredWord) === 0) ? $(this).show() : $(this).hide();
          });
      }
     });
    
     function getLatinWord(word){
       return word.split('').map(function(character){
                              if (langMap[character]) {
                                return langMap[character];
                              }
                              return character;
                           }).join('');
     }
    

答案 1 :(得分:0)

在这里,我提出了一种以数据为中心的方法。这是使您的可能匹配满足需求的问题。根据您的规范,标准化的单词应具有以下特征:

  1. 将所有非ASCII字符替换为其ASCII近似值
  2. 所有内容都应小写

这是在函数normalizeWord中完成的。

其余的代码创建一个dictionary来绑定原始 这个词是标准化的表示形式。 filter函数返回 数据集中与输入匹配的原始单词的列表。

实际上,将代码绑定到DOM时会出现一些不匹配的情况,因为这种方法实际上适用于给定的数据集。在现实生活中,我只是从过滤后的列表中重建匹配项的HTML表示,而不是显示和隐藏已经存在的DOM元素。

$(function() {
  var langMap = {
    'å' : 'a',
    'ä' : 'a',
    'ö' : 'o'
  };

  var words = [
    'Orånge',
    'Banäna',
    'Potatö'
  ];

  // Create normalized words

  // The map with the original and normalized word
  var dictionary = {};

  // Normalization
  words.forEach(function(w) {
    var word = normalizeWord(w);
    dictionary[word] = w;
  });

  function normalizeWord(word) {
    for (key in langMap) {
      word = word.toLowerCase()
        .replace(new RegExp(key, 'g'), langMap[key]);
    }
    return word;
  }

  function filter(word) {
    var possibleMatch = normalizeWord(word);
    var result = [];
    for (normalizedWord in dictionary) {
      if (normalizedWord.indexOf(possibleMatch) === 0) {
        result.push(dictionary[normalizedWord]);
      }
    }
    return result;
  }

  // Test
  var results = [
    'b -> ' + filter('b'),
    'bs -> ' +  filter('bs'),
    'baNana -> ' + filter('baNana'),
    'Potatö ->  ' + filter('Potatö')
  ]

  console.log(results);

  // Binding to the DOM
  $('#search-items-box').keyup(function() {
    var value = $(this).val();
    var matches = filter(value);

    if (matches.length === 0) {
      $('.itemsList .m3-item').show();
      return;
    }

    $('.itemsList .m3-item').each(function() {
      var $this = $(this),
        value = $this.html();

      if (matches.indexOf(value) > -1) {
        $this.show();
      } else {
        $this.hide();
      }
    });
  });
});