用jQuery保持以前的突出显示

时间:2019-01-12 17:27:52

标签: javascript jquery

我创建了一个简单的表格来显示我遇到的问题。当使用复选框突出显示值时,如果第二个复选框中存在该值,则仍突出显示该值。没关系。但是当我取消单击第一个或第二个复选框时,尽管突出显示仍在第一个复选框中并仍被单击,但突出显示消失了。 当未选中第二个复选框时,是否可以保持突出显示? 我希望我说清楚了。如果您愿意,这是我的jsfiddle:https://jsfiddle.net/6k5caw8h/19/

谢谢。

HTML:

$(document).ready(function() {
  $('.selector').each(function() {
    $(this).on('click', function(e) {
      check($(this).prop("checked") ? $("#nextColor").val() : '#fff', $(this).attr("name"));
    });
  });
  $('.all').each(function() {
    $(this).on('click', all);
  });

  function all(event) {
    if ($(this).is(':checked')) {
      let checked = $("input:checkbox:not(:checked)", $(this).parents('form')).not(this);
      checked.prop("checked", true);
      check($("#nextColor").val(), ...checked.map((i, e) => e.name).get());
    } else {
      let checked = $("input:checkbox(:checked)", $(this).parents('form')).not(this);
      checked.prop("checked", false);
      check('#fff', ...checked.map((i, e) => e.name).get());
    }
  }

  function check(color, ...elements) {
    $('td').each((i, td) => {
      if (elements.includes($(td).text())) $(td).css('background', color);
    });
  }
});
table.tb {
  border: 1px solid #CCC;
  font-family: Arial, Helvetica, sans-serif;
  font-size: 12px;
  border-collapse: collapse;
  table-layout: fixed;
  margin-left: 200px;
}

.tb td {
  padding: 5px;
  margin: 5px;
  border: 1px solid #ccc;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/1.12.4/jquery.min.js"></script>
<input id="nextColor" type="color" value="#9ac99d">
<form id="form1" name="form1" method="post" action="">
  <label><input type="checkbox" name="SelectAll" class="all" />SelectAll</label>
  <label><input type="checkbox" name="x" class="selector" />x</label>
  <label><input type="checkbox" name="y" class="selector" />y</label>
</form>

<form id="form1" name="form1" method="post" action="">
  <label><input type="checkbox" name="SelectAll" class="all" />SelectAll</label>
  <label><input type="checkbox" name="x" class="selector" />x</label>
  <label><input type="checkbox" name="z" class="selector" />z</label>
</form>
<table class="tb">
  <tbody>
    <tr>
      <td>x</td>
      <td>y</td>
    </tr>
    <tr>
      <td>z</td>
      <td>x</td>
    </tr>
    <tr>
      <td>q</td>
      <td>a</td>
    </tr>
  </tbody>
</table>

3 个答案:

答案 0 :(得分:2)

您的问题来自以下有问题的代码行:取消选中针对同一字母的复选框似乎忽略了其他字母的状态:

check($(this).prop("checked") ? $("#nextColor").val() : '#fff', $(this).attr("name"));

在这一行中,您只是在检查是否选中了要单击的特定复选框,而实际上应该检查所有具有相同name属性的复选框,并查看是否任何已选中。

因此,您可以做的是简单地遍历所有.selectors并按(1)与当前复选框匹配的name属性的值和(2)如果选中它们来对其进行过滤。如果选中其中任何一个,则传递给check()的第一个参数应为true

const $sameNameSelector = $('.selector[name="'+$(this).attr('name')+'"]');
const isAnySameNameSelectorChecked = $sameNameSelector.filter(function() { return this.checked }).length;
check(isAnySameNameSelectorChecked ? $("#nextColor").val() : '#fff', $(this).attr("name"));

更新:这似乎无法解决您的问题,因为all()还调用了一些复杂的逻辑。您只需要:

  1. click.selector上检查.change事件监听器
  2. 只需使用.all复选框即可触发对.selector复选框的更改,并手动触发change事件。然后,这将触发所有单个复选框上的单个逻辑,而无需重复任何逻辑:
function all(event) {
    $(this).closest('form').find('.selector').prop('checked', this.checked).trigger('change');
}

提示:您无需执行$('.selector').each({ $(this).on('...'); }),然后绑定事件处理程序。 jQuery可以智能地处理它,因此您只需执行$('。selector')。on(...);'。

$(document).ready(function() {

  $('.selector').on('change', function(e) {
    const $sameNameSelector = $('.selector[name="' + $(this).attr('name') + '"]');
    const isAnySameNameSelectorChecked = $sameNameSelector.filter(function() {
      return this.checked
    }).length;
    check(isAnySameNameSelectorChecked ? $("#nextColor").val() : '#fff', $(this).attr("name"));
  });
  $('.all').each(function() {
    $(this).on('click', all);
  });

  function all(event) {
    $(this).closest('form').find('.selector').prop('checked', this.checked).trigger('change');
  }

  function check(color, ...elements) {
    $('td').each((i, td) => {
      if (elements.includes($(td).text())) $(td).css('background', color);
    });
  }


});
table.tb {
  border: 1px solid #CCC;
  font-family: Arial, Helvetica, sans-serif;
  font-size: 12px;
  border-collapse: collapse;
  table-layout: fixed;
  margin-left: 200px;
}

.tb td {
  padding: 5px;
  margin: 5px;
  border: 1px solid #ccc;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<input id="nextColor" type="color" value="#9ac99d">

<form id="form1" name="form1" method="post" action="">

  <label><input type="checkbox" name="SelectAll" class="all" />SelectAll</label>
  <label><input type="checkbox" name="x" class="selector" />x</label>
  <label><input type="checkbox" name="y" class="selector" />y</label>

</form>

<form id="form1" name="form1" method="post" action="">

  <label><input type="checkbox" name="SelectAll" class="all" />SelectAll</label>
  <label><input type="checkbox" name="x" class="selector" />x</label>
  <label><input type="checkbox" name="z" class="selector" />z</label>

</form>


<table class="tb">
  <tbody>
    <tr>
      <td>x</td>
      <td>y</td>
    </tr>
    <tr>
      <td>z</td>
      <td>x</td>
    </tr>
    <tr>
      <td>q</td>
      <td>a</td>
    </tr>
  </tbody>
</table>

答案 1 :(得分:1)

要保持先前的突出显示,您需要保留检查的历史记录以及检查时选择的颜色。一种简单的方法是将颜色数据和时间戳直接分配给复选框。以下javascript解决了维护历史记录的实际问题,因此当删除支票时,将恢复以前支票的颜色。

我重构了代码以执行渲染循环 renderChecks(),这是一种更易于维护的设计模式。

请参阅:https://jsfiddle.net/c6pt0eb5/1/

$(document).ready(function() {

  $('.selector').each(function() {
    $(this).on('click', function(e) {
      if ($(this).is(':checked')) {
      	$(this).data("color",[$("#nextColor").val(),Date.now()]);
      }
      renderChecks();
    });
  });
  $('.all').each(function() {
    $(this).on('click', all);
  });

  function all(event) {
    if ($(this).is(':checked')) {
      let checked = $("input:checkbox", $(this).parents('form')).not(this);
      checked.prop("checked", true);
      checked.data("color",[$("#nextColor").val(),Date.now()]);
    } else {
      let checked = $("input:checkbox(:checked)", $(this).parents('form')).not(this);
      checked.prop("checked", false);      
    }
    renderChecks();
  }

  function renderChecks() {
    const checks = {};
    const names = [];
  	$(".selector:checked").each((i,val) => {
       
       if (checks[$(val).attr('name')]) {
          checks[$(val).attr('name')].push($(val).data('color'));           
          checks[$(val).attr('name')].sort((a,b) => a - b);
       } else {
          checks[$(val).attr('name')] = [$(val).data('color')];
          names.push($(val).attr('name'));
       }});
       
       $('td').each((i, td) => {
           $(td).css('background','#fff');
           const text = $(td).text();
           let t = null;
           names.forEach((name) => {               
               if (text.includes(name)) {
                   if (t == null || t < checks[name][0][1]) {
                      t = checks[name][0][1];
                      $(td).css('background', checks[name][0][0]);
                   }
               }
           });                      
       });       
       
  }

});


  
table.tb {
  border: 1px solid #CCC;
  font-family: Arial, Helvetica, sans-serif;
  font-size: 12px;
  border-collapse: collapse;
  table-layout: fixed;
  margin-left: 200px;
}

.tb td {
  padding: 5px;
  margin: 5px;
  border: 1px solid #ccc;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/1.12.4/jquery.min.js"></script>
<input id="nextColor" type="color" value="#9ac99d">
<form id="form1" name="form1" method="post" action="">
  <label><input type="checkbox" name="SelectAll" class="all" />SelectAll</label>
  <label><input type="checkbox" name="x" class="selector" />x</label>
  <label><input type="checkbox" name="y" class="selector" />y</label>
</form>

<form id="form1" name="form1" method="post" action="">
  <label><input type="checkbox" name="SelectAll" class="all" />SelectAll</label>
  <label><input type="checkbox" name="x" class="selector" />x</label>
  <label><input type="checkbox" name="z" class="selector" />z</label>
</form>
<table class="tb">
  <tbody>
    <tr>
      <td>x</td>
      <td>y</td>
    </tr>
    <tr>
      <td>z</td>
      <td>x</td>
    </tr>
    <tr>
      <td>q</td>
      <td>a</td>
    </tr>
  </tbody>
</table>

注意:接受的答案不会保留先前的突出显示,而只是保留当前的突出显示。

答案 2 :(得分:1)

我注意到在选中所有子项时“ SelectAll”不会被选中-我假设您希望在选中所有子项时希望将其“选中”(一个共同的要求),以便取消选中您不必检查并取消选中SelectAll的所有子项。

另一件事是您是否希望对相关检查进行检查,即当您检查“ x”时是否希望其他“ x”被检查?如果您这样做,请在我在此处提供的代码中取消注释此行,并且命名的类似内容将同步检查和取消选中:

  //  allChecksNotMe.prop("checked", isChecked);

好的,现在我们已经过了复选框管理,让我们看看保持突出显示。现在,该要求还不太清楚-取消选中时,将其变成白色#fff。您希望还是仅在未选中“所有”时才希望?或永远不要变白;即一次带有颜色,即使未经检查,他们也会保留它吗?我的第二个示例提供了在未选中时保持突出显示颜色以及将其重置为当前颜色选择的方法。

$(function() {
  let cbx = "[type='checkbox']";
  let cbxSel = ".selector" + cbx;
  $(cbxSel) //.add('.all[type="checkbox"]')
    .on('change', function(e) {
      let me = $(this);
      let myname = $(this).attr("name");
      let namesel = "[name='" + myname + "']";
      let allpeer = $(".all" + cbx);
      let allChecksNotMe = $(cbxSel + namesel).not(me);
      let isChecked = this.checked;
      // uncomment to keep like checks in sync
      //  allChecksNotMe.prop("checked", isChecked);
      allpeer.trigger('checkcolor');
      let color = $("#nextColor").val();
      let newColor = isChecked ? color : '#fff';
      check(newColor, myname);
    });
  $('form').on('checkcolor', '.all', function(event) {
    let myForm = $(event.delegateTarget);
    // checks on form
    let formChecks = myForm.find(cbxSel);
    let formChecksChecked = formChecks.filter(':checked');
    let areAllChecked = (formChecks.length == formChecksChecked.length);
    $(this).prop("checked", areAllChecked);
  })
  $('.all' + cbx).on('change', function() {
    let isChecked = this.checked;
    let myForm = $(this).closest('form');
    // checks on form
    myForm.find(cbxSel)
      .prop('checked', isChecked).trigger("change");
  });

  function check(color, ...elements) {
    let newColor = {
      'background-color': color
    };
    $('.tb tbody').find('td').filter(function(index) {
      return elements.includes($(this).text());
    }).css(newColor);
  }
});
table.tb {
  border: 1px solid #CCC;
  font-family: Arial, Helvetica, sans-serif;
  font-size: 12px;
  border-collapse: collapse;
  table-layout: fixed;
  margin-left: 200px;
}

.tb td {
  padding: 5px;
  margin: 5px;
  border: 1px solid #ccc;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/1.12.4/jquery.min.js"></script>
<input id="nextColor" type="color" value="#9ac99d">
<form id="form1" name="form1" method="post" action="">
  <label><input type="checkbox" name="SelectAll" class="all" />SelectAll</label>
  <label><input type="checkbox" name="x" class="selector" />x</label>
  <label><input type="checkbox" name="y" class="selector" />y</label>
</form>

<form id="form2" name="form2" method="post" action="">
  <label><input type="checkbox" name="SelectAll" class="all" />SelectAll</label>
  <label><input type="checkbox" name="x" class="selector" />x</label>
  <label><input type="checkbox" name="z" class="selector" />z</label>
</form>
<table class="tb">
  <tbody>
    <tr>
      <td>x</td>
      <td>y</td>
    </tr>
    <tr>
      <td>z</td>
      <td>x</td>
    </tr>
    <tr>
      <td>q</td>
      <td>a</td>
    </tr>
  </tbody>
</table>

具有突出显示差异的替代项:

$(function() {
  let cbx = "[type='checkbox']";
  let cbxSel = ".selector" + cbx;
  $(cbxSel) //.add('.all[type="checkbox"]')
    .on('change', function(e) {
      let me = $(this);
      let myname = $(this).attr("name");
      let namesel = "[name='" + myname + "']";
      let allpeer = $(".all" + cbx);
      let namedPeers = $(cbxSel + namesel);
      let allChecksNotMe = namedPeers.not(me);
      let isChecked = this.checked;
      // uncomment to keep like checks in sync
      //  allChecksNotMe.prop("checked", isChecked);
      allpeer.trigger('allchecked');
      let anyNamedChecked = !!namedPeers.filter(":checked").length;
      let keep = $('#keepcolor')[0].checked;
      let reset = $('#resetcolor')[0].checked;
      check(anyNamedChecked, myname, keep, reset);
    });
  $('form').on('allchecked', '.all', function(event) {
    let myForm = $(event.delegateTarget);
    // checks on form
    let formChecks = myForm.find(cbxSel);
    let formChecksChecked = formChecks.filter(':checked');
    let areAllChecked = (formChecks.length == formChecksChecked.length);
    $(this).prop("checked", areAllChecked);
  })
  $('.all' + cbx).on('change', function() {
    let isChecked = this.checked;
    let myForm = $(this).closest('form');
    // checks on form
    myForm.find(cbxSel)
      .prop('checked', isChecked).trigger("change");
  });

  function check(anyNamedChecked, myname, keepColor = false, reset = true) {
    let color = $("#nextColor").val();
    let newColor = anyNamedChecked ? color : '#fff';
    let colorCSS = {
      'background-color': newColor
    };
    $('.tb tbody').find('td').filter(function(index) {
      return myname.includes($(this).text());
    }).each(function(index, element) {
      let me = $(element);
      if (keepColor) {
        let scolor = reset ? color : me.data("savecolor");
        if (!!scolor) {
          colorCSS = {
            'background-color': scolor
          };
        }
        me.data("savecolor", !!scolor ? scolor : color);
      }
      $(element).css(colorCSS);
    });
  }
});
table.tb {
  border: 1px solid #CCC;
  font-family: Arial, Helvetica, sans-serif;
  font-size: 12px;
  border-collapse: collapse;
  table-layout: fixed;
  margin-left: 200px;
}

.tb td {
  padding: 5px;
  margin: 5px;
  border: 1px solid #ccc;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/1.12.4/jquery.min.js"></script>

<input id="nextColor" type="color" value="#9ac99d">
<label><input id="keepcolor" type="checkbox" name="keepcolor" />Keep Color</label>
<label><input id="resetcolor" type="checkbox" name="resetcolor" />Reset Color</label>
<form id="form1" name="form1" method="post" action="">
  <label><input type="checkbox" name="SelectAll" class="all" />SelectAll</label>
  <label><input type="checkbox" name="x" class="selector" />x</label>
  <label><input type="checkbox" name="y" class="selector" />y</label>
</form>

<form id="form2" name="form2" method="post" action="">
  <label><input type="checkbox" name="SelectAll" class="all" />SelectAll</label>
  <label><input type="checkbox" name="x" class="selector" />x</label>
  <label><input type="checkbox" name="z" class="selector" />z</label>
</form>
<table class="tb">
  <tbody>
    <tr>
      <td>x</td>
      <td>y</td>
    </tr>
    <tr>
      <td>z</td>
      <td>x</td>
    </tr>
    <tr>
      <td>q</td>
      <td>a</td>
    </tr>
  </tbody>
</table>