2016/03/27

ライブラリを使わずJavaScriptでインクリメンタルサーチを実装する

インクリメンタルサーチとはキー入力ごとに自動的に検索処理を行う手法のひとつ。
ただ環境によってはライブラリが使えず、自分たちで実装する必要があったりする。
ということで、今回は素のJavaScriptのみでインクリメンタルサーチを実装する。


HTML


<input type='text' id="keyword">

<ul id="list">
</ul>




JavaScript


var data = ['apple','apricot','avocado','banana','bilberry','blackberry','blackcurrant','blueberry','boysenberry','cantaloupe','currant','cherry','cherimoya','cloudberry','coconut','cranberry','damson','date','dragonfruit','durian','elderberry','feijoa','fig','goji berry','gooseberry','grape','raisin','grapefruit','guava','huckleberry','jabuticaba','jackfruit','jambul','jujube','juniper berry','kiwi fruit','kumquat','lemon','lime','loquat','lychee','mango','marion berry','melon','cantaloupe','honeydew','watermelon','miracle fruit','mulberry','nectarine','olive','orange','blood orange','clementine','mandarine','tangerine','papaya','passionfruit','peach','pear','persimmon','physalis','plum/prune','pineapple','pomegranate','pomelo','purple mangosteen','quince','raspberry','salmonberry','rambutan','redcurrant','salal berry','salak','satsuma','star fruit','strawberry','tamarillo','tamarind','ugli fruit'];

とりあえず data がサーバから取得したデータと見立てて説明する。
var keyupStack = [];
var keyword = document.getElementById('keyword');
keyword.addEventListener('keyup', function () {
  keyupStack.push(1);

  setTimeout(function () {
    keyupStack.pop();
    // 最後にkeyupされてから一定時間次の入力がなかったら実行
    if (keyupStack.length === 0) {
      // 部分一致を可能にする(例: .*a.*b.*c.*)
      var buf = '.*' + this.value.replace(/(.)/g, "$1.*");
      var reg = new RegExp(buf);
      
      var filteredLists = data.filter(function (d) {
       return reg.test(d);
      });
      createRow(filteredLists);
    }
  }.bind(this), 300);
});

var createRow = function (lists) {
  var list = document.getElementById('list');
  list.textContent = null;
  lists.forEach(function (l) {
    var li = document.createElement('li');
    li.appendChild(document.createTextNode(l));
    list.appendChild(li);
  });
};

// 初期表示
createRow(data);



今回はDOMを一旦消して再構成しているが、 display: none をつかって非表示にする方法もある。この場合は見えないだけでDOMは存在するので、ページネーションライブラリを使うときは注意が必要そう。


スペース区切りでAND検索をしたい場合は、以下のように実装できる。
// 略
var words = this.value.split(/\s/g);
var lists = data.filter(function (d) {
  return words.every(function (w) {
      return d.indexOf(s) >= 0;
  });
});



おまけ(jQueryを使った場合)


var keyupStack = [];
$('#keyword').on('keyup', function () {
  keyupStack.push(1);
  
  setTimeout(function () {
    keyupStack.pop();
    if (keyupStack.length === 0) {
      // 部分一致を可能にする(例: .*a.*b.*c.*)
      var buf = '.*' + $(this).val().replace(/(.)/g, "$1.*");
      var reg = new RegExp(buf);

      // 最後にkeyupされてから次の入力がなかった場合
      var filteredLists = $.grep(data, function (d) {
       return reg.test(d);
      }.bind(this));
      createRow(filteredLists);
    }
  }.bind(this), 300);
});

var createRow = function (lists) {
  var list = $('#list');
  $('#list').empty();
  $.each(lists, function (i, v) {
    var item = $('<li>').append(v);
    list.append(item);
  });
};

// 初期表示
createRow(data);


今、仕事でインクリメンタルサーチまわりの開発をしているので、より良い実装方法がわかりしだい別途記事にしようと思う。



以上

written by @bc_rikko

0 件のコメント :

コメントを投稿