2

以下の関数を使用すると、ユーザーは製品をdata-attributesでフィルタリングでき、複数の値で同時にフィルタリングできます。これは、選択された値の配列を作成することによって行われます。いずれかの値がクリックされると(この場合はチェック/オフ)、すべてのアイテムが非表示になり、更新された配列の値に一致するアイテムが再表示されます。

1つをフィルタリングする場合は正しく機能しますdata-attributeが、複数の属性でフィルタリングするように組み合わせると、いずれかの値に一致するすべての結果が表示されなくなり、代わりに、指定されたすべての値に一致する結果のみが表示されます。

ここに問題を示すフィドルを投稿しました:http://jsfiddle.net/chayacooper/WZpMh/94/ 1つを除くすべてのアイテムは両方の値を持っているdata-style="V-Neck"ためdata-color="Black"、いずれかのフィルターが選択されていますが、別の値の場合、data-attribute一部のアイテムは非表示になっています。

$(document).ready(function () {
    var selected = [];
    $('#attributes-Colors *').click(function () {
        var attrColor = $(this).data('color');
        var $this = $(this);
        if ($this.parent().hasClass("active")) {
            $this.parent().removeClass("active");
            selected.splice(selected.indexOf(attrColor),1);
        }
        else {
            $this.parent().addClass("active");
            selected.push(attrColor);
        }
        $("#content").find("*").hide();
        $.each(selected, function(index,item) {
            $('#content').find('[data-color *="' + item + '"]').show();
        });
        return false;
    });

$('#attributes-Silhouettes *').click(function () {
        var attrStyle = $(this).data('style');
        var $this = $(this);
        if ($this.parent().hasClass("active")) {
            $this.parent().removeClass("active");
            selected.splice(selected.indexOf(attrStyle),1);
        }
        else {
            $this.parent().addClass("active");
            selected.push(attrStyle);
        }           
        $("#content").find("*").hide();
        $.each(selected, function(index,item) {
            $('#content').find('[data-style *="' + item + '"]').show();
        });
       return false;
    });
});   
4

1 に答える 1

1

両方のハンドラーがselected配列を更新していますが、で実行されるハンドラーは1つだけclickです。1つ目は色が(選択解除された)場合、2つ目はスタイルの場合です。「ブラック」と「クルーネック」をクリックしたとしましょう。そのとき、選択したアレイは次のようになります[ "Black", "Crew_Neck" ]。次に選択を行うときに、「半袖」をクリックすると、2番目の(スタイル)ハンドラーが実行されます。起こっていることは次のとおりです。

  1. Short_Sleeves 選択したアレイに追加されます。
  2. すべてのアイテムはを使用して非表示になります$("#content").find("*").hide();
  3. 選択した配列が繰り返され、動的セレクターに基づいてアイテムが再度表示されます。

3番目が問題です。上記の例では、スタイルがクリックされたため、スタイルハンドラーが実行されています。選択した配列内の色であるアイテムは失敗します。これは、たとえば、などのセレクターで要素が見つからないため$('#content').find('[data-style *="Black"]').show();です。

私は2つのことを提案します。

  1. 1つはカラー用、もう1つはスタイル用の2つの選択配列を保持します。
  2. コードを組み合わせて、両方のグループに1つのハンドラーのみを使用します。

これが(ほとんど)実用的な例です。

単一のハンドラーを使用するために結合し、どのグループが変更されたかを認識できるように、コンテナーにを追加したことに注意しdata-type="color|style"てください。.filterOptions

完全なスクリプトは次のとおりです。

$(document).ready(function () {
    // use 2 arrays so the combined handler uses correct group 
    var selected = { color: [], style: [] };

    // code was similar enough to combine to 1 handler for both groups
    $('.filterOptions').on("click", "a", function (e) {
        // figure out which group...
        var type = $(e.delegateTarget).data("type");
        var $this = $(this);
        // ...and the value of the checkbox checked
        var attrValue = $this.data(type);

        // same as before but using 'type' to access the correct array
        if ($this.parent().hasClass("active")) {
            $this.parent().removeClass("active");
            selected[type].splice(selected[type].indexOf(attrValue),1);
        }
        else {
            $this.parent().addClass("active");
            selected[type].push(attrValue);
        }

        // also showing all again if no more boxes are checked
        if (attrValue == 'All' || $(".active", ".filterOptions").length == 0) {
            $('#content').find('*').show();
        } 
        else {
            // hide 'em all
            $("#content").find("*").hide();
            // go through both style and color arrays
            for (var key in selected) {
                // and show any that have been checked
                $.each(selected[key], function(index,item) {
                    $('#content').find('[data-' + key + ' *="' + item + '"]').show();
                });
            }
        }
    }); 
});

更新:コメントからの提案を組み込む

リンクの代わりにチェックボックスを使用してハンドラーを機能させることは、イベントバインディングコードへの小さな変更でした。changeの代わりにメソッドを使用し、:の代わりに要素clickをリッスンするようになりました。:checkboxa

$('.filterOptions').on("change", ":checkbox", function (e) {
    // handler code
});

「すべて」のオプション「しゃっくり」は、思ったよりも修正が少し難しかったです。これが私が最終的に得たものです:

// get a jQuery object with all the options the user selected
var checked = $(":checked", ".filterOptions");

// show all of the available options if...
if (checked.length == 0 // ...no boxes are checked
    || // ...or...
    checked.filter(".all").length > 0) // ...at least one "All" box is checked...
{
    // remainder of code, including else block, unchanged
}

また、上記の条件を単純化するためallに、適切な要素にクラスを追加しました。checkbox

更新されたフィドル

于 2013-03-27T07:10:25.110 に答える