1

現在フィルタリングしようとしているオプションが2つありますが、3番目、場合によっては4番目に追加する予定です(たとえば、現在、価格とレビューをフィルタリングしていますが、リストにさらに価格を追加したいと考えています。また、3つ、4つ、または5つの星で構成される「評価」のような別のフィルターカテゴリ)。

以下にリストしたロジックを使用すると問題なく動作しますが、進むにつれて非常に長く複雑になる(そして不要になる)と感じています。コードをリファクタリングする方法があることを知っています。それを実行するための最良の方法は何でしょうか。HTML:

  <select class="deals">
    <option value="deals-all">All deals</option>
    <option value="50">$50</option>
    <option value="25">$25</option>
  </select>

  <select class="reviews">
    <option value="reviews-all">All reviews</option>
    <option value="reviews-positive">Positive reviews</option>
    <option value="reviews-negative">Negative reviews</option>
  </select>

jQuery

 $('.reviews, .deals').change(function() {

var reviewsVal = $('.reviews :selected').val();
var dealsVal = $('.deals :selected').val();



 if((reviewsVal == 'reviews-all') && (dealsVal == 'deals-all')) {

      $('.review-positive').show();
 $('.review-negative').show();
 $('.deals-25').show();
 $('.deals-50').show();
 } 


else if((dealsVal == '50') && (reviewsVal == 'reviews-positive')) {
 $('.review-negative.deals-50').hide();
 $('.review-positive.deals-50').show();
 $('.review-negative.deals-25').hide();
 $('.review-positive.deals-25').hide();

 }

 else if((dealsVal == '50') && (reviewsVal == 'reviews-negative')) {
 $('.review-negative.deals-50').show();
 $('.review-positive.deals-50').hide();
 $('.review-negative.deals-25').hide();
 $('.review-positive.deals-25').hide();
 }

else if((dealsVal == '25') && (reviewsVal == 'reviews-positive')) {
 $('.review-negative.deals-50').hide();
 $('.review-positive.deals-50').hide();
 $('.review-negative.deals-25').hide();
 $('.review-positive.deals-25').show();
}

else if((dealsVal == '25') && (reviewsVal == 'reviews-negative')) {
 $('.review-negative.deals-50').hide();
 $('.review-positive.deals-50').hide();
 $('.review-negative.deals-25').show();
 $('.review-positive.deals-25').hide();
}

 else if((dealsVal == 'deals-all') && (reviewsVal == 'reviews-positive')) {
 $('.review-negative.deals-50').hide();
 $('.review-positive.deals-50').show();
 $('.review-negative.deals-25').hide();
 $('.review-positive.deals-25').show();
}

else if((dealsVal == 'deals-all') && (reviewsVal == 'reviews-negative')) {
 $('.review-negative.deals-50').show();
 $('.review-positive.deals-50').hide();
 $('.review-negative.deals-25').show();
 $('.review-positive.deals-25').hide();
}

else if((dealsVal == '50') && (reviewsVal == 'reviews-all')) {
 $('.review-negative.deals-50').show();
 $('.review-positive.deals-50').show();
 $('.review-negative.deals-25').hide();
 $('.review-positive.deals-25').hide();
}

else if((dealsVal == '25') && (reviewsVal == 'reviews-all')) {
 $('.review-negative.deals-50').hide();
 $('.review-positive.deals-50').hide();
 $('.review-negative.deals-25').show();
 $('.review-positive.deals-25').show();
}

else {
 $('.review-positive').show();
 $('.review-negative').show();
 $('.deals-25').show();
 $('.deals-50').show();
} 
});

$('.reviews-positive').click(function() {
$('.review-negative').hide();
$('.review-positive').show();
});

$('.reviews-negative').click(function() {
$('.review-positive').hide();
$('.review-negative').show();
});


});​

うまくいけば、あなたは私が何をしようとしているのかを見ることができます、どんな入力にも感謝します。

*編集:jsfiddle:http ://jsfiddle.net/TXywp/1/

4

2 に答える 2

2

コードを単純化し、保守と拡張を容易にする2つの異なるアプローチを考えることができます。

  1. 条件に基づいて、どのアイテムを非表示または表示するかをアルゴリズムで導き出すことができます。

  2. 条件とアクションのテーブルを作成して、新しい条件とアクションを追加するだけで、テーブルに新しいアイテムを追加することができます。

  3. HTMLを変更して、表示する内容を自己記述できるようにします。

テーブル駆動型アプローチは次のようになります。

$('.reviews, .deals').change(function() {

    var allDeals = '.review-negative.deals-50, .review-positive.deals-50, .review-positive.deals-25, .review-negative.deals-25';

    var table = [
        {rv: 'reviews-all', dv: 'deals-all', show: '.review-positive, .review-negative, .deals-25, .deals-50'},
        {rv: 'reviews-positive', dv: '50', show: '.review-positive.deals-50'},
        {rv: 'reviews-negative', dv: '50', show: '.review-negative.deals-50'},
        {rv: 'reviews-positive', dv: '25', show: '.review-positive.deals-25'}
        {rv: 'reviews-negative', dv: '25', show: '.review-negative.deals-25'},
        {rv: 'reviews-positive', dv: 'deals-all', show: '.review-positive.deals-50, .review-positive.deals-25'},
        {rv: 'reviews-negative', dv: 'deals-all', show: '.review-negative.deals-50, .review-negative.deals-25'},
        {rv: 'reviews-all', dv: '50', show: '.review-negative.deals-50, .review-positive.deals-50'},
        {rv: 'reviews-all', dv: '25', show: '.review-negative.deals-25, .review-positive.deals-25'}
    ];

    var reviewsVal = $('.reviews :selected').val();
    var dealsVal = $('.deals :selected').val();

    $(allDeals).hide();

    var item, found = false;
    for (var i = 0, len = table.length; i < len; i++) {
        item = table[i];
        if (dealsVal == item.dv && reviewsVal == item.rv) {
            $(item.show).show();
            found = true;
            break;
        }
    }

    if (!found) {
        $('.review-positive, .review-negative, .deals-25, .deals-50').show();
    } 
});

そして、これがアルゴリズム的な方法で、配列に1つの新しいエントリを追加するだけで新しい取引値を追加できます。取引が2つしかない場合、これはテーブル駆動型のアプローチよりもおそらく手間がかかりますが、取引レベルが4つ以上ある場合は、保守がはるかに簡単になります。

$('.reviews, .deals').change(function() {
    var deals = ['25', '50'];

    function addAllDeals(base, prefix) {
        for (var i = 0; i < deals.length; i++) {
            if (base) base += ", ";
            base += prefix + deals[i];
        }
        return(base);
    }

    function addSingleDeal(prefixes, deal) {
        var sel = [];
        for (var i = 0; i < prefixes.length; i++) {
            sel.push(prefixes[i] + deal);
        }
        return(sel.join(", ");
    }

    var reviewsVal = $('.reviews :selected').val();
    var dealsVal = $('.deals :selected').val();
    var itemsToShow = "";

    // hide everything to start
    var initialHide = addAllDeals("", ".review-positive.deals-");
    initialHide = addAllDeals(initialHide, ".review-negative.deals-");
    $(initialHide).hide();

    if (reviewsVal == 'reviews-all') {
        if (dealsVal == 'deals-all') {
            itemsToShow = addAllDeals(".review-positive, .review-negative", ".deals-");
        } else {
            itemsToShow = addSingleDeal([".review-negative.deals-", ".review-negative.deals-"], dealsVal);
        }
    } else if (reviewsVal == 'reviews-positive') {
        itemsToShow = '.review-positive.deals-' + dealsVal;
    } else if (reviewVal == 'reviews-negative') {
        itemsToShow = '.review-negative.deals-' + dealsVal;
    } else {
        itemsToShow = addAllDeals(".review-positive, .review-negative", ".deals-");
    }
});

HTMLを(上記の3番目のオプションのように)次のように変更できる場合:

  <select class="deals">
    <option value="deals-all" data-base=".review-positive, .review-negative">All deals</option>
    <option value="50" data-base=".deals-50">$50</option>
    <option value="25" data-base=".deals-25">$25</option>
  </select>

  <select class="reviews">
    <option value="reviews-all" data-filter="">All reviews</option>
    <option value="reviews-positive" data-filter=".review-positive">Positive reviews</option>
    <option value="reviews-negative" data-filter=".review-negative">Negative reviews</option>
  </select>

次に、この単純なjavascriptを使用できます。

 $('.reviews, .deals').change(function() {

    var dealsBase = $('.deals :selected').data("base");
    var reviewsFilter = $('.reviews :selected').data("filter");

     // hide all
     $(".review-negative, .review-positive").hide();

     // show the desired ones
     var base = $(dealsBase);
     if (reviewsFilter) {
         base = base.filter(reviewsFilter);
     }
     base.show();
});

警告:これを試すためのコード/ HTMLの実用的なjsFiddleの例を提供しなかったため、このコードは実行されておらず、入力エラーがないかチェックされていません。しかし、うまくいけば、2つのアプローチのアイデアを得ることができます。

于 2012-09-19T17:18:21.970 に答える
1

動的な結果を得るには、標準化された命名が最善の方法です。まず、基準セレクターを標準化し、それらに一般的なクラスを与え、idプロパティで区別することから始めます。値の命名規則に従うこともお勧めします。これは、次の行に何かを生成します

    <select id="deal" class="criteriaSelector">
      <option value="all">All deals</option>
      <option value="50">$50</option>
      <option value="25">$25</option>
    </select>

    <select id="review" class="criteriaSelector">
      <option value="all">All reviews</option>
      <option value="positive">Positive reviews</option>
      <option value="negative">Negative reviews</option>
    </select>

次に、フィルタリングクラスに加えて、ジェネリッククラスをフィルタリングするすべてのアイテムを指定します。例として.itemを使用します。また、 。{id}-{value}システムを使用すると完全に機能するように、選択した値と基準名からクラスを構築できるようにする必要があります。これは私たちに何かを残すでしょう

    <div class="item review-positive deal-25"></div>
    <div class="item review-negative deal-50"></div>

この設定により、動的で拡張可能なコードを構築できます。

    $('.criteriaSelector').change(function() {
      // Initialize criteria string
      var criteria = '';
      // Set value for all selector
      var showAll = true;

      // Iterate over all criteriaSelectors
      $('.criteriaSelector').each(function(){
        // Get value
        var val = $(this).children(':selected').val();
        // Check if this limits our results
        if(val !== 'all'){
          // Append selector to criteria
          criteria += '.' + $(this).attr('id') + '-' + val;
          // We don't want to show all results anymore
          showAll = false;
        }
      });
      // Check if results are limited somehow
      if(showAll){
        // No criterias were set so show all
        $('.item').show();
      } else {
        // Hide all items
        $('.item').hide();
        // Show the ones that were selected
        $(criteria).show();
      }

    });

これで、新しい基準セレクターを追加しても、命名規則に従っている限り、このコードを変更する必要はありません。

于 2012-09-19T17:59:00.257 に答える