Làm cách nào để chuyển-chọn nhiều hộp kiểm như GMail?


86

Trong GMail, người dùng có thể nhấp vào một hộp kiểm trong danh sách email, giữ phím Shift và chọn hộp kiểm thứ hai. Sau đó, JavaScript sẽ chọn / bỏ chọn các hộp kiểm nằm giữa hai ô checbox.

Tôi tò mò là làm thế nào điều này được thực hiện? Đây là JQuery hay một số JavaScript cơ bản (hoặc phức tạp)?


4
Dễ dàng tìm ý chính cho @ BC của câu trả lời. Gist.github.com/3784055
Andy Ray

Câu trả lời:


184

Tôi đã viết một bản trình diễn độc lập sử dụng 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>


8
Bạn có thể gọi slice thay vì sử dụng vòng lặp for. Nó sẽ giống như sau: "$ ('. Chkbox'). Slice (min ..., max ... + 1) .attr ('check', lastChecked.checked)"
Matthew Crumley

10
Câu trả lời là khập khiễng nếu không có plugin jquery trừu tượng. Vì vậy, đây bạn hãy truy cập gist.github.com/3784055
Andy Ray

3
Có vẻ như không hoạt động khi thực hiện nhấp shift nhiều lần sau khi bỏ chọn một số hộp mà không cần nhấn shift. jsfiddle.net/5fG5b
Greg Pettit

3
Đó là bởi vì nó nên được .prop('checked', không phải .attr('checked'. jsFiddle: jsfiddle.net/dn4jv9a5
Caitlin

3
@schnauss cảm ơn bạn, bạn nói đúng và tôi đã cập nhật câu trả lời. Để bào chữa cho tôi, câu trả lời ban đầu đã được viết trước khi có prop ()
BC.

36

Điều này được thực hiện thông qua javascript khá đơn giản.

Họ theo dõi id của hộp kiểm cuối cùng và khi hộp kiểm khác được chọn, họ sử dụng thuộc tính sự kiện shiftKey để xem liệu shift có được giữ trong khi nhấp vào hộp kiểm hay không. Nếu vậy, họ đặt thuộc tính đã chọn của mỗi hộp kiểm ở giữa hai thành true.

Để xác định khi một hộp được chọn, họ có thể sử dụng một sự kiện onclick trên các hộp kiểm


2
Nếu bạn muốn, bạn có thể sử dụng tài liệu tham khảo này từ Mozilla Developer Network: shiftKey sự kiện thuộc tính , thuộc tính yếu tố đầu vào , onclick .
PhoneixS

14

Gần đây, tôi đã viết một plugin jQuery cung cấp tính năng đó và hơn thế nữa.

Sau khi bao gồm plugin, bạn chỉ cần khởi tạo ngữ cảnh của hộp kiểm bằng đoạn mã sau:

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

Đây là liên kết đến tài liệu, bản demo và tải xuống: http://rmariuzzo.github.io/checkboxes.js/


10

Có vẻ như mọi câu trả lời tôi có thể tìm thấy trên mạng đều hoàn toàn phụ thuộc vào jQuery cho việc này. JQuery thêm rất ít chức năng. Đây là một phiên bản nhanh không yêu cầu bất kỳ khuôn khổ nào:

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;
        });
    }
}

Và sau đó khởi tạo nó bất cứ khi nào bạn cần:

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


3

Nhận giải pháp này từ http://abcoder.com/javascript/jquery/simple-check-uncheck-all-jquery- Chức năng/ (hiện đã chết) :

JavaScript và mã 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>


Miền liên kết không còn được sử dụng.
Zaren Wienclaw

2

Lấy cảm hứng từ những câu trả lời hay được cung cấp, đây là một phiên bản JavaScript đơn giản sử dụng Array.prototypeđể ép buộc những người theo dõi nút sử dụng các hàm mảng, thay vì forcác vòng lặp.

(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>


Làm thế nào để cải thiện với chức năng bỏ chọn?
RSH

2

Tôi thực sự thích ví dụ của gyo và thêm một số mã để nó hoạt động trên tất cả các hộp kiểm có cùng tên.

Tôi cũng đã thêm một MutationObserver để các sự kiện cũng được xử lý trên các hộp kiểm mới được thêm vào.

$(document).ready(function() {
    var previouslyClicked = {};

    var rangeEventHandler = function(event) {
        if (event.shiftKey && previouslyClicked[this.name] && this != previouslyClicked[this.name]) {
            var $checkboxes = $('input[type=checkbox][name='+this.name+']').filter(':visible');
            var start = $checkboxes.index( this );
            var end = $checkboxes.index( previouslyClicked[this.name] );
//              console.log('range', start, end, this, previouslyClicked[this.name]);
            $checkboxes.slice(Math.min(start,end), Math.max(start,end)+ 1).prop('checked', previouslyClicked[this.name].checked);
        } else {
            previouslyClicked[this.name] = this;
        }
    };

    if ("MutationObserver" in window) { // https://developer.mozilla.org/en-US/docs/Web/API/MutationObserver/MutationObserver to refresh on new checkboxes
        var mutationCallback = function(mutationList, observer) {
            mutationList.forEach((mutation) => {
                mutation.addedNodes.forEach((node) => {
                    if (node.nodeName == 'INPUT' && node.type == 'checkbox') {
                        $(node).on('click.selectRange', rangeEventHandler);
                    }
                });
            });
        };

        var observer = new MutationObserver(mutationCallback);
        observer.observe(document, {
            childList: true,
            attributes: false,  // since name is dynamically read
            subtree: true
        });
    }

    $('input[type=checkbox][name]').on('click.selectRange', rangeEventHandler);
});
<html>
<head>
</head>
<body>
  <script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
  <div>
    First:
    <input type="checkbox" name="first">
    <input type="checkbox" name="first">
    <input type="checkbox" name="first">
    <input type="checkbox" name="first">
    <input type="checkbox" name="first">
  </div>
  <div>
    Second:
    <input type="checkbox" name="second">
    <input type="checkbox" name="second">
    <input type="checkbox" name="second">
    <input type="checkbox" name="second">
    <input type="checkbox" name="second">
  </div>
</body>
</html>


1

Tôi đã lấy phiên bản jQuery từ @BC. và chuyển đổi nó thành một phiên bản ES6, vì mã thực sự giải quyết vấn đề khá dễ dàng, trong trường hợp bất kỳ ai vẫn tình cờ gặp phải điều này ...

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;
  } ) );
}

1
  • Đã tìm thấy giải pháp tốt hơn nó hoạt động cho cả hộp kiểm chọn và bỏ chọn.

  • Sử dụng javascript & Jquery cốt lõi.

$(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', e.target.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>


0

Đây cũng là một cách triển khai khác tương tự như nhiều lựa chọn trong Outlook ..

    <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];
            }
        }
    });
});


0

Đây là giải pháp jquery mà tôi đã viết và sử dụng:

  • Tất cả các hộp kiểm có cùng một lớp được đặt tên chksel
  • Để lựa chọn cá nhân nhanh hơn, một lớp sẽ thực hiện theo thứ tự có tên chksel_index
  • Ngoài ra, mỗi checkboxthuộc tính có tên rgchứa cùng một chỉ mục

    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');}
    

    })


0

giải pháp này phù hợp với tôi, cũng là ajax dựa trên DataTables https://jsfiddle.net/6ouhv7bw/4/

<table id="dataTable">

<tbody>
<tr>
<td><input type="checkbox"></td>
</tr>

<tr>
<td><input type="checkbox"></td>
</tr>

<tr>
<td><input type="checkbox"></td>
</tr>

<tr>
<td><input type="checkbox"></td>
</tr>
</tbody>
</table>

<script>
$(document).ready(function() {
   var $chkboxes = $('#dataTable');
var $range = '#dataTable tbody';
var $first = false;
var $indexWrapp = 'tr';
var lastChecked = null;
var $checkboxes = 'input[type="checkbox"]';

$chkboxes.on('click',$checkboxes,function(e) {

    if ($first===false) {

        lastChecked = $(this).closest($indexWrapp).index();
        lastCheckedInput = $(this).prop('checked');
        $first=true;
        return;
    }

    if (e.shiftKey) {

        var start = lastChecked;
        var end =  $(this).closest($indexWrapp).index();

       $( $range+' '+$indexWrapp).each(function() {
          $currIndex=$(this).index();
          if( $currIndex>=start && $currIndex<=end ){
              $(this).find($checkboxes).prop('checked', lastCheckedInput);
          }

       })
    }

     lastCheckedInput = $(this).prop('checked');
     lastChecked = $(this).closest($indexWrapp).index();
});
</script>
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.