grepの高速化

APIリファレンスのインクリメンタル検索は、keyup毎に全divを検索しているので、前回の検索結果をキャッシュするように修正してみた。


追記
さらに修正。

  var headers = null;
  var stack = [];

  function Grep(keyword, elements, then_fn, else_fn) {
    this.keyword = keyword;
    this.elements = elements;

    this.run = function() {
      this.result = filter(function(element) {
                      var text = scrapeText(element).toLowerCase();
                      var test = (!text || text.indexOf(keyword.toLowerCase()) >= 0);
                      test ? then_fn(element) : else_fn(element);
                      return test;
                    }, elements);
    }
  }

  function show(element) { showElement(element.parentNode) }
  function hide(element) { hideElement(element.parentNode) }

  connect('phrase', 'onkeyup', function() {
    headers || (headers = getElementsByTagAndClassName('div', 'function-header'));

    var grep = null;
    var keyword = this.value;
    var prev = stack[stack.length - 1];

    function is_inc() {
      return prev && keyword &&
             (prev.keyword.length == keyword.length - 1) &&
             (keyword.indexOf(prev.keyword) >= 0);
    }

    function is_dec() {
      return prev && keyword &&
             (prev.keyword.length == keyword.length + 1) &&
             (prev.keyword.indexOf(keyword) >= 0);
    }

    if(is_inc()) {
      grep = new Grep(keyword, prev.result, show, hide);
      stack.push(grep);
    } else if(is_dec()) {
      stack.pop();
      grep = stack[stack.length - 1];
    } else if(!prev || prev.keyword != keyword){
      grep = new Grep(keyword, headers, show, hide);
      stack = [grep];
    }

    grep && grep.run();
  });

stackとかあるところがかっこ悪い。もっと関数プログラミング的にスマートにできそうだけど、地頭が悪いので思いつかず。