Как я могу переключить-выбрать несколько флажков, таких как GMail?


в GMail пользователь может щелкнуть по одному флажку в списке электронной почты, удерживать клавишу Shift и выбрать второй флажок. Затем JavaScript будет выбирать / снимать флажки, которые находятся между двумя флажками.

Мне любопытно, как это делается? Это JQuery или какой-то базовый (или сложный) JavaScript?

10 73

10 ответов:

Я написал автономную демо-версию, которая использует jquery:

$(document).ready(function() {
    var $chkboxes = $('.chkbox');
    var lastChecked = null;

    $chkboxes.click(function(e) {
        if(!lastChecked) {
            lastChecked = this;
            return;
        }

        if(e.shiftKey) {
            var start = $chkboxes.index(this);
            var end = $chkboxes.index(lastChecked);

            $chkboxes.slice(Math.min(start,end), Math.max(start,end)+ 1).prop('checked', lastChecked.checked);

        }

        lastChecked = this;
    });
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<html>
    <head>
    </head>
    <body>
        <input type="checkbox" id="id_chk1" class="chkbox" value="1" />Check 1<br/>
        <input type="checkbox" id="id_chk2" class="chkbox" value="2" />Check 2<br/>
        <input type="checkbox" id="id_chk3" class="chkbox" value="3" />Check 3<br/>
        <input type="checkbox" id="id_chk4" class="chkbox" value="4" />Check 4<br/>
        <input type="checkbox" id="id_chk5" class="chkbox" value="5" />Check 5<br/>
        <input type="checkbox" id="id_chk6" class="chkbox" value="6" />Check 6<br/>
        <input type="checkbox" id="id_chk7" class="chkbox" value="7" />Check 7<br/>
    </body>
</html>

Это делается с помощью довольно простого javascript.

они отслеживают идентификатор последнего флажка, и когда установлен другой флажок, они используют атрибут события shiftKey чтобы увидеть, если сдвиг был проведен при нажатии на флажок. Если это так, то они устанавливают проверено собственность каждого флажка между двумя в true.

чтобы определить, когда флажок установлен, они, вероятно, использовать onclick событие на флажки

недавно я написал плагин jQuery, который предоставляет эту функцию и многое другое.

после включения плагина вам просто нужно инициализировать контекст флажков со следующим фрагментом кода:

$('#table4').checkboxes({ range: true });

вот ссылка на документацию, демо и скачать: http://rmariuzzo.github.io/checkboxes.js/

Кажется, что все ответы я могу найти в интернете полностью зависит от jQuery для этого. JQuery добавляет очень мало функциональности. Вот быстрая версия, которая не требует каких-либо рамок:

function allow_group_select_checkboxes(checkbox_wrapper_id){
    var lastChecked = null;
    var checkboxes = document.querySelectorAll('#'+checkbox_wrapper_id+' input[type="checkbox"]');

    //I'm attaching an index attribute because it's easy, but you could do this other ways...
    for (var i=0;i<checkboxes.length;i++){
        checkboxes[i].setAttribute('data-index',i);
    }

    for (var i=0;i<checkboxes.length;i++){
        checkboxes[i].addEventListener("click",function(e){

            if(lastChecked && e.shiftKey) {
                var i = parseInt(lastChecked.getAttribute('data-index'));
                var j = parseInt(this.getAttribute('data-index'));
                var check_or_uncheck = this.checked;

                var low = i; var high=j;
                if (i>j){
                    var low = j; var high=i; 
                }

                for(var c=0;c<checkboxes.length;c++){
                    if (low <= c && c <=high){
                        checkboxes[c].checked = check_or_uncheck;
                    }   
                }
            } 
            lastChecked = this;
        });
    }
}

а затем инициализировать его всякий раз, когда вам это нужно:

allow_group_select_checkboxes('[id of a wrapper that contains the checkboxes]')

ну, пост довольно старый, но вот решение, с которым я только что столкнулся: jQuery поле плагин

получил это решение от http://abcoder.com/javascript/jquery/simple-check-uncheck-all-jquery-function/ (ныне мертвый):

JavaScript и HTML код

var NUM_BOXES = 10;
    // last checkbox the user clicked
    var last = -1;
    function check(event) {
    // in IE, the event object is a property of the window object
    // in Mozilla, event object is passed to event handlers as a parameter
    if (!event) { event = window.event }
    var num = parseInt(/box\[(\d+)\]/.exec(this.name)[1]);
    if (event.shiftKey && last != -1) {
    var di = num > last ? 1 : -1;
    for (var i = last; i != num; i += di) {
      document.forms.boxes['box[' + i + ']'].checked = true;
     }
    }
      last = num;
    }
    function init() {
      for (var i = 0; i < NUM_BOXES; i++) {
        document.forms.boxes['box[' + i + ']'].onclick = check;
      }
    }
<body onload="init()">
    <form name="boxes">
    <input name="box[0]" type="checkbox">
    <input name="box[1]" type="checkbox">
    <input name="box[2]" type="checkbox">
    <input name="box[3]" type="checkbox">
    <input name="box[4]" type="checkbox">
    <input name="box[5]" type="checkbox">
    <input name="box[6]" type="checkbox">
    <input name="box[7]" type="checkbox">
    <input name="box[8]" type="checkbox">
    <input name="box[9]" type="checkbox">
    </form></body>

вдохновленный прекрасными ответами, вот простая версия JavaScript с использованием Array.prototype чтобы заставить nodelists использовать функции массива, а не for петли.

(function () { // encapsulating variables with IIFE
  var lastcheck = null // no checkboxes clicked yet

  // get desired checkboxes
  var checkboxes = document.querySelectorAll('div.itemslist input[type=checkbox]')

  // loop over checkboxes to add event listener
  Array.prototype.forEach.call(checkboxes, function (cbx, idx) {
    cbx.addEventListener('click', function (evt) {

      // test for shift key, not first checkbox, and not same checkbox
      if ( evt.shiftKey && null !== lastcheck && idx !== lastcheck ) {

        // get range of checks between last-checkbox and shift-checkbox
        // Math.min/max does our sorting for us
        Array.prototype.slice.call(checkboxes, Math.min(lastcheck, idx), Math.max(lastcheck, idx))
          // and loop over each
          .forEach(function (ccbx) {
            ccbx.checked = true
        })
      }
      lastcheck = idx // set this checkbox as last-checked for later
    })
  })
}())
<div class="itemslist">
  <input type="checkbox" name="one"   value="1">
  <input type="checkbox" name="two"   value="2">
  <input type="checkbox" name="three" value="3">
  <input type="checkbox" name="four"  value="4">
  <input type="checkbox" name="five"  value="5">
</div>

вот также еще одна реализация, похожая на перспективы множественного выбора..

    <script type="text/javascript">

function inRange(x, range)
{
    return (x >= range[0] && x <= range[1]);
}

$(document).ready(function() {
    var $chkboxes = $('.chkbox');
    var firstClick = 1;
    var lastClick = null;
    var range = [];

    $chkboxes.click(function(e) {
        if(!e.shiftKey && !e.ctrlKey) {

            $('#index-' + firstClick).prop('checked', false);

            firstClick = $chkboxes.index(this) + 1;

            if (firstClick !== null && firstClick !== ($chkboxes.index(this)+1)) {
                $('#index-' + firstClick).prop('checked', true);
            }
        } else if (e.shiftKey) {
            lastClick = $chkboxes.index(this) + 1;
            if ((firstClick < lastClick) && !inRange(lastClick, range)) {
                for (i = firstClick; i < lastClick; i++) {
                    $('#index-' + i).prop('checked', true);
                }
                range = [firstClick, lastClick];
            } else if ((firstClick > lastClick) && !inRange(lastClick, range)) {
                for (i = lastClick; i < firstClick; i++) {
                    $('#index-' + i).prop('checked', true);
                }
                range = [lastClick, firstClick];
            } else if ((firstClick < lastClick) && inRange(lastClick, range)) {
                for (i = 1; i < 100; i++) {
                    $('#index-' + i).prop('checked', false);
                }

                for (i = firstClick; i < lastClick; i++) {
                    $('#index-' + i).prop('checked', true);
                }
                range = [firstClick, lastClick];
            }else if ((firstClick > lastClick) && inRange(lastClick, range)) {
                for (i = 1; i < 100; i++) {
                    $('#index-' + i).prop('checked', false);
                }

                for (i = lastClick; i < firstClick; i++) {
                    $('#index-' + i).prop('checked', true);
                }
                range = [lastClick, firstClick];
            }
        }
    });
});

Я взял версию jQuery из @BC. и преобразовал его в версию ES6, так как код на самом деле довольно элегантно решает проблему, если кто-то все еще натыкается на это...

function enableGroupSelection( selector ) {
  let lastChecked = null;
  const checkboxes = Array.from( document.querySelectorAll( selector ) );

  checkboxes.forEach( checkbox => checkbox.addEventListener( 'click', event => {
    if ( !lastChecked ) {
      lastChecked = checkbox;

      return;
    }

    if ( event.shiftKey ) {
      const start = checkboxes.indexOf( checkbox );
      const end   = checkboxes.indexOf( lastChecked );

      checkboxes
        .slice( Math.min( start, end ), Math.max( start, end ) + 1 )
        .forEach( checkbox => checkbox.checked = lastChecked.checked );
    }

    lastChecked = checkbox;
  } ) );
}

это решение jquery, которое я написал и использую:

  • все флажки имеют одинаковый класс с именем chksel
  • для более быстрого индивидуального выбора класс снесет заказ по имени chksel_index
  • тоже друг checkbox имеет атрибут с именем rg которые содержат то же самое индекс

    var chksel_last=-1;
    $('.chksel').click(function(ev){
       if(ev.shiftKey){var i=0;
          if(chksel_last >=0){
            if($(this).attr('rg') >= chksel_last){
             for(i=chksel_last;i<=$(this).attr('rg');i++){$('.chksel_'+i).attr('checked','true')}}
            if($(this).attr('rg') <= chksel_last){for(i=$(this).attr('rg');i<=chksel_last;i++){$('.chksel_'+i).attr('checked','true')}}
          }  
          chksel_last=$(this).attr('rg');
       }else{chksel_last=$(this).attr('rg');}
    

    })