3

テキストボックスに入力するとフィルタリングされるテーブルBackbone.js/Underscore.jsをレンダリングするために使用しています。HTMLこの場合、それは基本的な電話帳です。
テーブルのコンテンツは、JSONファイルが入力されたコレクションから取得されます。JSONファイルの基本的な例を以下に示します。

[{
    "Name":"Sales and Services",
    "Department":"Small Business",
    "Extension":"45446",
},
{
    "Name":"Technical Support",
    "Department":"Small Business",
    "Extension":"18800",
},
{
    "Name":"Research and Development",
    "Department":"Mid Market",
    "Extension":"75752",
}]

テキストボックスの値を小文字に変換し、その値をコレクションと一緒にこの関数に渡します。次に、戻り値を新しいコレクションに割り当て、それを使用してページを再レンダリングします。

filterTable = function(collection, filterValue) {
    var filteredCollection;
    if (filterValue === "") {
        return collection.toJSON();
    }
    return filteredCollection = collection.filter(function(data) {
        return _.some(_.values(data.toJSON()), function(value) {
            value = (!isNaN(value) ? value.toString() : value.toLowerCase());
            return value.indexOf(filterValue) >= 0;
        });
    });
};

問題は、関数がリテラルであるということです。私の例から「SalesandServices」部門を見つけるには、それを正確に入力するか、「Sales」または「Services」と入力する必要があります。「salserv」と入力できませんでしたが、それでも自分がやりたいことを見つけることができませんでした。

テキストをWordの配列に分割するのにかなり信頼できると思われるJavaScriptをすでに作成しました(現在、使用中のコードに更新されています)。

toWords = function(text) {
    text = text.toLowerCase();
    text = text.replace(/[^A-Za-z_0-9@.]/g, ' ');
    text = text.replace(/[\s]+/g, ' ').replace(/\s\s*$/, '');
    text = text.split(new RegExp("\\s+"));
    var newsplit = [];
    for (var index in text) {
        if (text[index]) {
            newsplit.push(text[index]);
        };
    };
    text = newsplit;
    return text;
};

「split」配列の各単語をループして、各単語がキー/値の1つに存在するかどうかを確認したいと思います。すべての単語が存在する限り、それは真理イテレータを通過し、コレクションに追加されてテーブルにレンダリングされます。

したがって、私の例では、「sal serv」と入力すると、これらの文字列の両方が最初のアイテムの名前内に存在し、返されます。
ただし、「sales business」と入力した場合、両方の値がそのアイテムに表示されていても、同じ2つの単語が[名前]セクションに存在しないため、これは返されません。

これをバックボーン/アンダースコアで書く方法がわからない、またはこれが最善の方法であるとしても。ドキュメントを見ましたが、どの機能が最も簡単かわかりませんでした。

これが理にかなっていることを願っています。私は少し慣れていないのでJavascript、ディープエンドに飛び込んだことに気づきましたが、学習は楽しい部分です;-)
必要に応じて、より多くのコードまたはおそらくJSFiddleを提供できます。

4

1 に答える 1

1

アンダースコアを使用するanyall、これが比較的簡単になります。その要点は次のとおりです。

  var toWords = function(text) {
    //Do any fancy cleanup and split to words
    //I'm just doing a simple split by spaces.
    return text.toLowerCase().split(/\s+/);
  };

  var partialMatch = function(original, fragment) {   
    //get the words of each input string
    var origWords = toWords(original + ""), //force to string
        fragWords = toWords(fragment);

    //if all words in the fragment match any of the original words, 
    //returns true, otherwise false
    return _.all(fragWords, function(frag) {
      return _.any(origWords, function(orig) {
        return orig && orig.indexOf(frag) >= 0;
      });
    });
  };

  //here's your original filterTable function slightly simplified
  var filterTable = function(collection, filterValue) {
      if (filterValue === "") {
          return collection.toJSON();
      }
      return collection.filter(function(data) {
          return _.some(_.values(data.toJSON()), function(value) {
              return partialMatch(value, filterValue);
          });
      });
  };

注:この方法は、最初にコレクション内のすべてのアイテムをループし、次に各アイテムのすべてのフィールドをループし、次にそのアイテム値のすべての単語をループするため、計算上かなり非効率的です。さらに、ループ内で宣言されたネストされた関数がいくつかあるため、メモリ フットプリントは最適ではありません。データのセットが小さい場合は問題ありませんが、必要に応じて、さまざまな最適化を行うことができます。時間があれば、後で戻ってこれを少し編集するかもしれません。

/テストされていないコード サンプル

于 2013-01-14T16:51:35.450 に答える