2013-12-09 5 views
2

У меня есть несколько флажков, которые фильтруют продукты в зависимости от того, какие флажки были выбраны. Фильтр работает при нажатии флажков, а идентификаторы продуктов добавляются в массив. Как вы можете видеть, у обоих фильтров есть одни и те же идентификаторы, поэтому, если они нажимают более одного окна ввода, я хочу убедиться, что идентификаторы только вставляются в массив один раз. Например. если у них есть input.white выбрано и input.greymelange выбрано, тогда они нажали на filter-btn. Я хочу, чтобы повторные идентификаторы повторялись один раз. Есть ли способ, которым я могу это сделать?Нажмите на массив, только если его нет

Jquery

var productIds = [""]; 

$(document).on('click', 'a.filter-btn', function(e){ 

    $(".listingTemplate").html(""); 
    if ($('input.white').is(':checked')) { 
      productIds.push("4021401143741", "4021402266227"); 
    } 

    if ($('input.greymelange').is(':checked')) { 
      productIds.push("4021401143741", "4021402266227","4021402266418", "4021401143796"); 
    } 
}); 

HTML

<input type="checkbox" id="white" class="white" value="white" />     
<input type="checkbox" id="greymelange" class="greymelange" value="greymelange" /> 
<a href="#" class="filter-btn">filter</a> 
+0

... Что именно вы пытаетесь сделать с этим кодом? Я думаю, что перепроектирование кода для обработки продуктов, а не фильтров упростит ваш код, а также будет более дружественным к базе данных. – user1618143

ответ

4

Вы можете использовать $.inArray() и $.each()

1) Храните все свои новые значения в массиве deArray.
2) Итерация этого массива с помощью $.each, а затем найти ли это в productIds с помощью inArray()

if ($('input.greymelange').is(':checked')) { 
     var deArray = ["4021401143741", "4021402266227", "4021402266418", "4021401143796"]; 
     $.each(deArray, function (i, j) { 
      if ($.inArray(j, productIds) == -1) { 
       productIds.push(j); 
      } 
     }); 
    } 

предложения: не объявлять пустую строку в массиве.

var productIds = [""]; //considered as an string. This will affect 
         //when you check length, now it is 1 
var productIds = []; //length is 0 

Наконец,

var productIds = []; 

$(document).on('click', 'a.filter-btn', function (e) { 
    $(".listingTemplate").html(""); 
    if ($('input.white').is(':checked')) { 
     var dArray = ["4021401143741", "4021402266227"]; 
     $.each(dArray, function (i, j) { 
      if ($.inArray(j, productIds) == -1) { 
       console.log(j) 
       productIds.push(j); 
      } 
     }) 
    } 

     if ($('input.greymelange').is(':checked')) { 
      var deArray = ["4021401143741", "4021402266227", "4021402266418", "4021401143796"]; 
      $.each(deArray, function (i, j) { 
       if ($.inArray(j, productIds) == -1) { 
        productIds.push(j); 
       } 
      }) 
     } 
      console.log(productIds) 
     }); 

JSFiddle

+0

привет, не должен использовать deArray в каждой функции где-нибудь? – user1937021

+0

@ user1937021 хороший улов :) Я обновил. Он должен использоваться в 'each' – Praveen

+0

@ user1937021 У меня была некоторая опечатка, я исправил ее в этой скрипке http://jsfiddle.net/74MAr/ – Praveen

0

Вы должны проверить, если элемент содержится, прежде чем добавить в список. К сожалению, это не так просто, как это должно быть, но следующий стек объясняет, что: How do I check if an array includes an object in JavaScript?

Поскольку вы помечено это как JQuery, следующий (пример) код может работать для вас:

if ($.inArray("4021401143741", productIds) === -1) 
    productIds.push("4021401143741"); 

Для более информацию об этом звонке see here. Удачи!

0

Чтобы проверить, если элемент уже существует в массиве, вы можете использовать Array.indexOf. Обратите внимание, что нет изначально в IE < 9, но я опубликовал ниже код, который добавит его в прототип Array, если он недоступен.

var products = []; 
function addProducts() { 
    for(var i = 0, l = arguments.length; i < l; i++) { 
     if(products.indexOf(arguments[i]) === -1) { 
      products.push(arguments[i]); 
     } 
    } 
} 
//Add indexOf if it doesn't exist natively 
if (!Array.prototype.indexOf) { 
    Array.prototype.indexOf = function(elt) { 
     var len = this.length >>> 0; 
     var from = Number(arguments[1]) || 0; 
     from = (from < 0) 
      ? Math.ceil(from) 
      : Math.floor(from); 
     if (from < 0) 
      from += len; 

     for(; from < len; from++) { 
      if(from in this && this[from] === elt) 
      return from; 
     } 
     return -1; 
    }; 
} 

Затем использовать эти новые функции, вы можете изменить ваш код будет:

$(document).on('click', 'a.filter-btn', function(e) { 
    if($('input.white').is(':checked')) { 
     addProducts("4021401143741", "4021402266227"); 
    } 
    if($('input.greymelange').is(':checked')) { 
     addProducts("4021401143741", "4021402266227","4021402266418", "4021401143796"); 
    } 
}); 

Так же, как примечание стороны. Если вы можете избежать этого, вы не должны привязывать события к документу. Привязывание событий к документу может вызвать проблемы с производительностью, если вы используете множество событий. Каждый раз, когда запускается событие click, эта функция запускается, чтобы проверить, соответствует ли цель вашей заданной цели. Чтобы ограничить этот удар производительности, вы должны привязать их к ближайшему не меняющемуся элементу. В примере ввода внутри формы вы можете добавить его в форму.

0

Добавьте код, указанный ниже, в ischecked conditional. // Continue execution для подталкивания значений.

isSet = false; 
currentVal = '999999999999'; 
$.each(productIds, function(index, value) { 
    if(value == currentVal){ 
    isSet = true; 
    } 
}); 

if(isSet){ 
// Continue execution 
} else { 
// failure 
} 
0

Нужно ли быть массивом? Похоже, вы бы лучше использовать простой объект:

productIds[ 420… ] = true; 

Это зависит от остальной части коды, но это звучит, как вы хотите реализовать хэш/таблицу значений/словарь, а не массив - было бы также проще проверить существование таким образом.

2

Если у вас есть только фиксированный набор идентификаторов продукта, зачем вам нужен массив переменной длины для хранения идентификаторов продуктов?

Я бы предложил создать объект, содержащий эту логику, которую вы можете использовать.

function productMapper() { 
    var colorToIdMap = { 
     'white' = [ 
      '4021401143741', 
      '4021402266227' 
     ], 
     'greymelange' = [ 
      '4021401143741', 
      '4021402266227', 
      '4021402266418', 
      '4021401143796' 
     ] 
    }; 
    var selectedIds = []; 
    function selectIds(color) { 
     this.selectedIds = []; 
     var colorIds = this.colorToIdMap[color]; 
     for(i = 0; i < colorIds.length; i++) { 
      var currentId = colorIds[i]; 
      if(this.selectedIds.indexOf(currentId) === -1) { 
       this.selectedIds.push(currentId); 
      } 
     } 
    } 
    function getSelectedIds() { 
     return this.selectedIds; 
    } 
} 

Использование может быть:

var selectedProductMap = new productMapper(); 

$(document).on('click', 'a.filter-btn', function(e){ 

    $(".listingTemplate").html(""); 
    if ($('input.white').is(':checked')) { 
      selectedProductMap.selectIds('white'); 
    } 

    if ($('input.greymelange').is(':checked')) { 
      selectedProductMap.selectIds('greymelange'); 
    } 
}); 

Преимущество здесь в том, что при добавлении новых цветов и продукт идентификаторам легко просто добавить их к этому классу (или иметь ту часть класса построен динамически из базы данных.

Я бы также предложил посмотреть рефакторинг HTML, так что вам не нужно добавлять условие if для каждого параметра цвета. Возможно, все вкладки флажка имеют общий класс и выводят значение цвета из ввода собственность. Как это можно сделать в вашей функции onclick:

$('input.filterCheckbox').each(function(index.value)) { 
    var $currentCheckbox = $(this); 
    if($currentCheckbox.is(':checked')) { 
     selectedProductMap.selectIds($currentCheckbox.val()); 
    } 
} 

var currentlySelectedIds = selectedProductMap.getSelectedIds(); 
Смежные вопросы