简体   繁体   English

如何进行基因剔除搜索多个关键字以及实时搜索

[英]how to have knockout search multiple keywords as well as live search

i am desperately trying to have knockout apply a live search to my project. 我拼命想让淘汰赛对我的项目进行实时搜索。 This search needs the ability to differentiate between spaces in the query and use them as separated search queries. 此搜索需要能够区分查询中的空格,并将其用作单独的搜索查询。 For example; 例如; if user types "Matrix" it pulls up both DVD and Bluray Matrix movies... But if user types in Matrix DVD nothing appears. 如果用户键入“ Matrix”,则将同时显示DVD和Bluray Matrix电影。但是,如果用户键入Matrix DVD,则不会显示任何内容。

I am trying to make it search everything in the data separated by space in the query. 我试图使其搜索查询中用空格分隔的数据中的所有内容。

Here is my fiddle: https://jsfiddle.net/neosketo/eLgscy1t/10/ 这是我的小提琴: https : //jsfiddle.net/neosketo/eLgscy1t/10/

HTML: HTML:

<div id="container">
<h1>Movie Search</h1>
<form>
  <input id="search" type="search" name="search" placeholder="Search for a user" data-bind="value: query, valueUpdate: 'keyup'" autocomplete="off" />
</form>

<table data-bind="visible: movies().length > 0">
  <thead><tr><th>Type</th><th>Name</th><th>Media</th></tr></thead>
  <tbody data-bind="foreach: movies">
    <tr>
      <td data-bind="text: type"></td>
      <td data-bind="text: name"></td>
      <td data-bind="text: media"></td>
    </tr>    
  </tbody>
</table>
</div>

JAVASCRIPT: JAVASCRIPT:

var movies = [
  { type: 'action',     name: 'The Matrix',                 media: 'DVD'},
  { type: 'action',     name: 'The Matrix',                 media: 'Bluray'},
  { type: 'fantasy',    name: 'Lord of the Rings',  media: 'DVD'},
  { type: 'fantasy',    name: 'Lord of the Rings',  media: 'Bluray'},
  { type: 'comedy',     name: 'Dumb and Dumber',        media: 'DVD'},
  { type: 'comedy',     name: 'Dumb and Dumber',        media: 'Bluray'}
];

var viewModel = {
  movies: ko.observableArray([]),
  query: ko.observable(''),

  search: function(value) {
    viewModel.movies.removeAll();

    if (value == '') return;

    for (var movie in movies) {
      if (movies[movie].name.toLowerCase().indexOf(value.toLowerCase()) >= 0) {
        viewModel.movies.push(movies[movie]);
      }
    }
  }
};

viewModel.query.subscribe(viewModel.search);
ko.applyBindings(viewModel);

I'd start out by extending your movie objects to include their own collection of search terms. 首先,将您的电影对象扩展为包括他们自己的搜索字词集合。 You don't want to recalculate this every time you type a character: 您不想每次输入字符时都重新计算:

var moviesWithSearchString = movies.map(function(movie) {
  var ogKeys = Object.keys(movie);
  return Object.assign({}, movie, {
    _searchProps: ogKeys
      .map(function(key) {
        return movie[key].toLowerCase();
      })
  });
});

The _searchProps property holds an array of search words. _searchProps属性包含一个搜索词数组。 For your first movie: ["action", "the matrix", "dvd"] 对于您的第一部电影: ["action", "the matrix", "dvd"]

Now, in your search method, we need to transform the search query into an array of lowercase words as well: 现在,在您的search方法中,我们还需要将搜索查询转换为小写单词数组:

var searchVals = value
  .toLowerCase()
  .split(" ");

Then, the fun part begins. 然后,有趣的部分开始。 We want every ( Array.prototype.every ) search word to appear ( String.prototype.includes ) in at least once ( Array.prototype.some ) of our movie's properties: 我们希望每个Array.prototype.every )搜索词在影片属性的至少一次Array.prototype.some )中出现String.prototype.includes ):

viewModel.movies(moviesWithSearchString.filter(function(movie) {
  return searchVals.every(function(searchVal) {
    return movie._searchProps.some(function(searchProp) {
      return searchProp.includes(searchVal);
    });
  });
}));

The working examples: 工作示例:

fiddle: https://jsfiddle.net/dkrct5ko/ 小提琴: https : //jsfiddle.net/dkrct5ko/

stack snippet: 堆栈片段:

 var movies = [{ type: 'action', name: 'The Matrix', media: 'DVD' }, { type: 'action', name: 'The Matrix', media: 'Bluray' }, { type: 'fantasy', name: 'Lord of the Rings', media: 'DVD' }, { type: 'fantasy', name: 'Lord of the Rings', media: 'Bluray' }, { type: 'comedy', name: 'Dumb and Dumber', media: 'DVD' }, { type: 'comedy', name: 'Dumb and Dumber', media: 'Bluray' }]; var moviesWithSearchString = movies.map(function(movie) { var ogKeys = Object.keys(movie); return Object.assign({}, movie, { _searchProps: ogKeys .map(function(key) { return movie[key].toLowerCase(); }) }); }); var viewModel = { movies: ko.observableArray([]), query: ko.observable(''), search: function(value) { var searchVals = value .toLowerCase() .split(" "); viewModel.movies(moviesWithSearchString.filter(function(movie) { return searchVals.every(function(searchVal) { return movie._searchProps.some(function(searchProp) { return searchProp.includes(searchVal); }); }); })); } }; viewModel.query.subscribe(viewModel.search); ko.applyBindings(viewModel); 
 body { margin: 2em; text-align: center; } form { margin-bottom: 2em; } table { text-align: left; margin: 0 auto; } th, td { padding: .2em; } 
 <script src="https://cdnjs.cloudflare.com/ajax/libs/knockout/3.2.0/knockout-min.js"></script> <div id="container"> <h1>Movie Search</h1> <form> <input id="search" type="search" name="search" placeholder="Search for a user" data-bind="value: query, valueUpdate: 'keyup'" autocomplete="off" /> </form> <table data-bind="visible: movies().length > 0"> <thead> <tr> <th>Type</th> <th>Name</th> <th>Media</th> </tr> </thead> <tbody data-bind="foreach: movies"> <tr> <td data-bind="text: type"></td> <td data-bind="text: name"></td> <td data-bind="text: media"></td> </tr> </tbody> </table> </div> 

Note that some of the Array and String methods are not supported in old browsers. 请注意,旧的浏览器不支持某些ArrayString方法。 Check out the linked articles for polyfills. 查看链接文章中的polyfills。

You could split the query term by space and then use the .some array method to search through the movies. 您可以按空间划分查询词,然后使用.some数组方法搜索电影。

search: function(value) {
  viewModel.movies.removeAll();

  if (!value) return;

  var values = value.split(' ');

  for (var movie in movies) {
    var found = values.some(function(word) {
        return !!word && movies[movie].name.toLowerCase().indexOf(word.toLowerCase()) >= 0;
    });
    if (found) {
      viewModel.movies.push(movies[movie]);
    }
  }
}

!!word simply short circuits the search in case the user entered multiple spaces resulting in an empty string from the split. 如果用户输入多个空格,导致拆分中出现空字符串, !!word只会使搜索短路。

Fiddle: https://jsfiddle.net/eLgscy1t/12/ 小提琴: https : //jsfiddle.net/eLgscy1t/12/

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM