【问题标题】:How to force Jquery to check for CHECKED boxes last, after checking for NOT CHECKED?在检查 NOT CHECKED 之后,如何强制 Jquery 最后检查 CHECKED 框?
【发布时间】:2018-10-19 18:11:41
【问题描述】:

我有复选框来过滤页面上显示的 DIV。我在fiddle 和下面都有代码。

此代码有效,但问题在于“国家/地区”复选框。如果取消选中“Argentina”,蓝色 div 就会消失。但它应该留下来,因为它的数据国家领域也有“巴西”和“墨西哥”。

换句话说,只有在“国家”下的三个复选框都未选中时,蓝色 div 才会消失。

我相信这是因为我的代码首先循环通过 CHECKED 复选框并显示它们,然后循环通过 UNCHECKED 复选框并隐藏它们。所以它看到巴西和墨西哥被选中,从技术上显示它们的瞬间,但随后立即看到阿根廷未被选中,所以它最终隐藏了它。

我的想法是颠倒我循环的顺序,即先循环通过 UNCHECKED 然后再 CHECKED。所以我在 Jquery 中切换了它,但它根本停止工作。不知道为什么会破坏它。

如果有人对如何正确执行此操作和/或如果我颠倒循环的顺序如何使其工作有任何想法,请告诉我。

HTML:

<div class="Row sel" style="background: #eeeeee;" data-region="Americas" data-country="Brazil" data-tier="Elite Reseller">
<div class="Heading">Allegiant Technology</div>
<div class="Copy">Brazil</div>
<div class="Copy">Elite Reseller</div>
</div>

<div class="Row sel" style="background: red;" data-region="APAC" data-country="Mexico" data-tier="Preferred Reseller">
<div class="Heading">Folco Communications</div>
<div class="Copy">Mexico</div>
<div class="Copy">Preferred Reseller</div>
</div>
<div class="Row sel" style="background: blue;" data-region="EMEA" data-country="Argentina, Mexico, Brazil" data-tier="Authorized Reseller">
<div class="Heading">Latin Telecom</div>
<div class="Copy">Argentina; Mexico; Brazil</div>
<div class="Copy">Authorized Reseller</div>
</div>


<div style="text-align:left; max-width: 1000px;  margin-left: auto;  margin-right: auto;  padding-left: 50px;">
<span class="title">Region:</span><br>
<input class="css-checkbox" type="checkbox" id="APAC" data-type="region" data-value="APAC" checked > 
<label for="APAC" class="css-label">APAC</label>
<input class="css-checkbox" type="checkbox" id="EMEA" data-type="region" data-value="EMEA" checked>
<label for="EMEA" class="css-label">EMEA</label>
<input class="css-checkbox" type="checkbox" id="Americas" data-type="region" data-value="Americas" checked>
<label for="Americas" class="css-label">Americas</label>
<br>
<br>
<span class="title">Partner Type:</span><br>
<input class="css-checkbox" type="checkbox" id="Preferred" data-type='tier'  data-value='Preferred Reseller' checked>
<label for="Preferred" class="css-label">Preferred</label>
<input class="css-checkbox" type="checkbox" id="Elite" data-type='tier'  data-value='Elite Reseller' checked>
<label for="Elite" class="css-label">Elite</label>
<input class="css-checkbox" type="checkbox" id="Authorized" data-type='tier'  data-value='Authorized Reseller' checked>
<label for="Authorized" class="css-label">Authorized</label>
<br>
<br>
<span class="title">Country:</span><br>
<input class="css-checkbox" type="checkbox" id="Argentina" data-type='country'  data-value='Argentina' checked>
<label for="Argentina" class="css-label">Argentina</label>
<input class="css-checkbox" type="checkbox" id="Brazil" data-type='country'  data-value='Brazil' checked>
<label for="Brazil" class="css-label">Brazil</label>
<input class="css-checkbox" type="checkbox" id="Mexico" data-type='country'  data-value='Mexico' checked>
<label for="Mexico" class="css-label">Mexico</label>
</div>

JS:

$('[type="checkbox"]').on('change', function () {
  $('[type="checkbox"]:checked').each( function (ind, inp) { //loop over checked checkboxes
    var type = inp.dataset.type, value = inp.dataset.value; 
    $('div[data-' + type +'*="' + value +'"]').show();  
  })
  $('[type="checkbox"]:not(:checked)').each( function (ind, inp) { //loop over unchecked checkboxes
    var type = inp.dataset.type, value = inp.dataset.value; 
    $('div[data-' + type +'*="' + value +'"]').hide();  
  })    

});

【问题讨论】:

  • 您不仅要遍历国家/地区复选框,还要遍历层级和区域。
  • 每次检查或取消检查某些内容时,我不能循环遍历所有这些吗?还是我应该只在被操纵的输入上循环遍历特定的数据类型?
  • 我的意思是,您取消选中所有国家/地区,但仍选中 EMEAAuthorized。这就是为什么仍然显示蓝色 div。
  • 您希望内容区域显示匹配任何个复选框吗?
  • 别抱歉,这是我的错,因为我显然没有正确解释它。但是,是的,你说的是对的。要显示经销商的 div,必须选中它的 Region,并且必须选中它的 Partner Type,并且必须至少选中一个 Country。显然,“至少一个”的最后一个小警告给我带来了问题,因为我目前正在最后检查 UNCHECKED 框,如果找到一个,它会隐藏 div。因此,即使巴西和阿根廷被选中,如果它看到墨西哥未被选中,它也会隐藏那个蓝色 div(当它不应该时)。这样就清楚了吗?

标签: javascript jquery html checkbox dataset


【解决方案1】:

这是一种可能的解决方案:

这个方法的关键是比较两个数组。
我正在使用用户It's me ... Alexthis answer 中找到的一些原型函数。

这个想法是将每个经销商的属性与检查的值进行比较。
仅在选中每种类型的至少一个属性,仅示出经销商。

我构建了一个检查值数组,按类型组织在一个多维数组中。
然后我将每个经销商的属性与这些值进行比较。
如果每种类型至少有一个值被选中,则会显示该经销商。

Array.prototype.indexOfAny = function(array) {
  return this.findIndex(function(v) {
    return array.indexOf(v) != -1;
  });
}

Array.prototype.containsAny = function(array) {
  return this.indexOfAny(array) != -1;
}



function getAllChecked() {

  // build a multidimensional array of checked values, organized by type

  var values = [];
  var $checked = $checkboxes.filter(':checked');

  $checked.each(function() {

    var $check = $(this);
    var type = $check.data('type');
    var value = $check.data('value');

    if (typeof values[type] !== "object") {
      values[type] = [];
    }

    values[type].push(value);

  });

  return values;

}

function evaluateReseller($reseller, checkedValues) {

  // Evaluate a selected reseller against checked values.
  // Determine whether at least one of the reseller's attributes for
  // each type is found in the checked values.

  var data = $reseller.data();
  var found = false;

  $.each(data, function(prop, values) {

    values = values.split(',').map(function(value) {
      return value.trim();
    });

    found = prop in checkedValues && values.containsAny(checkedValues[prop]);

    if (!found) {
      return false;
    }

  });

  return found;

}


var $checkboxes = $('[type="checkbox"]');
var $resellers = $('.Row.sel');

$checkboxes.on('change', function() {

  // get all checked values.
  var checkedValues = getAllChecked();

  // compare each resellers attributes to the checked values.
  $resellers.each(function(k, reseller) {

    var $reseller = $(reseller);
    var found = evaluateReseller($reseller, checkedValues);

    // if at least one value of each type is checked, show this reseller.
    // otherwise, hide it.

    if (found) {
      $reseller.show();
    } else {
      $reseller.hide();
    }

  });

});
#reseller_allegiant {
  background: lightgreen;
}

#reseller_folco {
  background: pink;
}

#reseller_latin_telecom {
  background: lightblue;
}

#controls {
  text-align: left;
  max-width: 1000px;
  margin: 2em auto 0;
  padding-left: 50px;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>

<div class="Row sel" id="reseller_allegiant" data-region="Americas" data-country="Brazil" data-tier="Elite Reseller">
  <div class="Heading">Allegiant Technology</div>
  <div class="Copy">Brazil</div>
  <div class="Copy">Elite Reseller</div>
</div>

<div class="Row sel" id="reseller_folco" data-region="APAC" data-country="Mexico" data-tier="Preferred Reseller">
  <div class="Heading">Folco Communications</div>
  <div class="Copy">Mexico</div>
  <div class="Copy">Preferred Reseller</div>
</div>

<div class="Row sel" id="reseller_latin_telecom" data-region="EMEA" data-country="Argentina, Mexico, Brazil" data-tier="Authorized Reseller">
  <div class="Heading">Latin Telecom</div>
  <div class="Copy">Argentina; Mexico; Brazil</div>
  <div class="Copy">Authorized Reseller</div>
</div>

<div id="controls">
  <span class="title">Region:</span><br>
  <input class="css-checkbox" type="checkbox" id="APAC" data-type="region" data-value="APAC" checked>
  <label for="APAC" class="css-label">APAC</label>
  <input class="css-checkbox" type="checkbox" id="EMEA" data-type="region" data-value="EMEA" checked>
  <label for="EMEA" class="css-label">EMEA</label>
  <input class="css-checkbox" type="checkbox" id="Americas" data-type="region" data-value="Americas" checked>
  <label for="Americas" class="css-label">Americas</label>
  <br>
  <br>
  <span class="title">Partner Type:</span><br>
  <input class="css-checkbox" type="checkbox" id="Preferred" data-type='tier' data-value='Preferred Reseller' checked>
  <label for="Preferred" class="css-label">Preferred</label>
  <input class="css-checkbox" type="checkbox" id="Elite" data-type='tier' data-value='Elite Reseller' checked>
  <label for="Elite" class="css-label">Elite</label>
  <input class="css-checkbox" type="checkbox" id="Authorized" data-type='tier' data-value='Authorized Reseller' checked>
  <label for="Authorized" class="css-label">Authorized</label>
  <br>
  <br>
  <span class="title">Country:</span><br>
  <input class="css-checkbox" type="checkbox" id="Argentina" data-type='country' data-value='Argentina' checked>
  <label for="Argentina" class="css-label">Argentina</label>
  <input class="css-checkbox" type="checkbox" id="Brazil" data-type='country' data-value='Brazil' checked>
  <label for="Brazil" class="css-label">Brazil</label>
  <input class="css-checkbox" type="checkbox" id="Mexico" data-type='country' data-value='Mexico' checked>
  <label for="Mexico" class="css-label">Mexico</label>
</div>

【讨论】:

  • 这似乎完全符合我的要求,非常感谢。乍一看,代码让我有点困惑,但这完全取决于我和我的经验不足。您的 cmets 帮助很大,我稍后会深入研究它,直到它完全有意义:) 再次感谢您的帮助!
猜你喜欢
  • 2012-04-01
  • 1970-01-01
  • 2020-02-08
  • 1970-01-01
  • 1970-01-01
  • 2016-12-24
  • 2013-06-23
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多