How can I shift-select multiple checkboxes like GMail?

后端 未结 13 979
野趣味
野趣味 2020-11-30 17:33

In GMail, the user can click on one checkbox in the email list, hold down the Shift key, and select a second checkbox. The JavaScript will then select/unselect the checkboxe

相关标签:
13条回答
  • 2020-11-30 17:43

    I wrote a self-contained demo that uses 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>

    0 讨论(0)
  • 2020-11-30 17:46

    It seems like every answer I can find online is completely dependent on jQuery for this. JQuery adds very little functionality. Here's a quick version that doesn't require any frameworks:

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

    And then initialize it whenever you need it:

    allow_group_select_checkboxes('[id of a wrapper that contains the checkboxes]')
    
    0 讨论(0)
  • 2020-11-30 17:49

    This is done through fairly simple javascript.

    They keep track of the id of the last checked box and when when another checkbox is checked they use the shiftKey event attribute to see if shift was held while clicking the checkbox. If so they set the checked property of each checkbox in between the two to true.

    To determine when a box is checked they probably use an onclick event on the checkboxes

    0 讨论(0)
  • 2020-11-30 17:50
    • Found the better solution it works for both select and deselects checkboxes.

    • Uses a core javascript & 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', 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 讨论(0)
  • 2020-11-30 17:54

    Got this solution from http://abcoder.com/javascript/jquery/simple-check-uncheck-all-jquery-function/ (now dead):

    JavaScript and HTML code

    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>

    0 讨论(0)
  • 2020-11-30 17:57

    Here is also another implementation similar to Outlooks multiple selection..

        <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 讨论(0)
提交回复
热议问题