GMail gibi birden çok onay kutusunu nasıl seçebilirim?


86

GMail'de, kullanıcı e-posta listesindeki bir onay kutusunu tıklayabilir, Shift tuşunu basılı tutabilir ve ikinci bir onay kutusunu seçebilir. JavaScript daha sonra iki seçim kutusu arasındaki onay kutularını seçecek / seçimlerini kaldıracaktır.

Bunun nasıl yapıldığını merak ediyorum? Bu JQuery mi yoksa temel (veya karmaşık) bir JavaScript mi?


Yanıtlar:


184

Jquery kullanan bağımsız bir demo yazdım:

$(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
For döngüsünü kullanmak yerine dilim çağırabilirsiniz. Şöyle görünecektir: "$ ['. Chkbox']. Dilim (min ..., maks ... + 1) .attr ('işaretlendi', lastChecked.checked)"
Matthew Crumley

10
Cevap, soyutlanmış jquery eklentisi olmadan yetersizdir. İşte gist.github.com/3784055
Andy Ray

3
Shift-tıklama olmadan bazı kutuların işaretini kaldırdıktan sonra birden çok kez shift-tıklama yapmak için işe yaramıyor gibi görünüyor. jsfiddle.net/5fG5b
Greg Pettit

3
Öyle olması gerektiği için .prop('checked'değil .attr('checked'. jsFiddle: jsfiddle.net/dn4jv9a5
caitlin

3
@schnauss teşekkür ederim, haklısın ve cevabı güncelledim. Savunmamda, orijinal cevap prop () kullanılmadan önce yazılmıştır
BC.

36

Bu oldukça basit bir javascript ile yapılır.

Son kontrol edilen kutunun kimliğini takip ederler ve başka bir onay kutusu işaretlendiğinde, onay kutusunu tıklarken vardiyanın tutulup tutulmadığını görmek için shiftKey olay özniteliğini kullanırlar. Eğer öyleyse , ikisi arasındaki her onay kutusunun işaretli özelliğini true olarak ayarlarlar.

Bir kutunun ne zaman işaretlendiğini belirlemek için muhtemelen onay kutularında bir onclick olayı kullanırlar.


2
İsterseniz, Mozilla Geliştirici Ağı'ndaki şu referansları kullanabilirsiniz: shiftKey olay özniteliği , Giriş öğesi özellikleri , onclick .
PhoneixS

14

Son zamanlarda, bu özelliği ve daha fazlasını sağlayan bir jQuery eklentisi yazdım.

Eklentiyi ekledikten sonra, aşağıdaki kod parçacığı ile onay kutularının bağlamını başlatmanız yeterlidir:

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

Dokümantasyon, demo ve indirme bağlantısı: http://rmariuzzo.github.io/checkboxes.js/


10

Görünüşe göre çevrimiçi bulabildiğim her cevap bunun için tamamen jQuery'ye bağlı. JQuery çok az işlevsellik ekler. Herhangi bir çerçeve gerektirmeyen hızlı bir sürüm:

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

Ve daha sonra ihtiyacınız olduğunda onu başlatın:

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


3

Bu çözümü http://abcoder.com/javascript/jquery/simple-check-uncheck-all-jquery-function/ adresinden aldım (artık öldü) :

JavaScript ve HTML kodu

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>


Bağlantılar alanı artık kullanımda değil.
Zaren Wienclaw

2

Sağlanan iyi yanıtlardan esinlenerek, burada düğüm Array.prototypelistelerini fordöngüler yerine dizi işlevlerini kullanmaya zorlamak için kullanılan sade bir JavaScript sürümü .

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


Seçimi kaldırma işlevi ile nasıl iyileştirilir?
RSH

2

Gyo'nun örneğini gerçekten beğendim ve bazı kodlar ekledim, böylece aynı ada sahip tüm onay kutularında çalışıyor.

Ayrıca bir MutationObserver ekledim, böylece olaylar yeni eklenen onay kutularında da işlenir.

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

@BC'den jQuery sürümünü aldım. ve bunu bir ES6 sürümüne dönüştürdü, çünkü kod aslında sorunu oldukça zarif bir şekilde çözüyor, birileri hala buna rastlarsa diye ...

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
  • Hem seçme hem de seçimlerini kaldırma onay kutuları için işe yarayan daha iyi çözümü buldu.

  • Çekirdek bir javascript ve Jquery kullanır.

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

Birden çok seçimi Outlooks'a benzer başka bir uygulama da burada.

    <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

Bu yazdığım ve kullandığım jquery çözümü:

  • Tüm onay kutularının adı aynı sınıfa sahiptir chksel
  • Daha hızlı bireysel seçim için bir sınıf, adlı sırayı taşıyacaktır. chksel_index
  • Ayrıca her checkboxbirinin rgaynı dizini içeren bir özniteliği vardır

    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

bu çözüm benim için çalışıyor, ayrıca DataTables https://jsfiddle.net/6ouhv7bw/4/ için ajax çalışıyor

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

0

İşte Elegant uygulaması. Buradaki fikir, ilk seçilen girdiyi lastChecked değişkenine depolamaktır ve kullanıcı shiftKey ile girdi alanını seçtiğinde bir döngü çalıştırıp inBetween (boolean) değiştirip tüm onay kutularını gerçek değerle işaretleyeceğiz. Wesbos'tan ilham aldı.

let checkboxes= document.querySelectorAll('.wrapper input[type="checkbox"]');
let lastChecked;

function logic(e)
{
let inBetween= false;   
if(e.shiftKey)
{
  checkboxes.forEach(checkbox=>{
    if(checkbox===this  || checkbox===lastChecked)
    {
      inBetween =!inBetween;
    }
    if(inBetween) checkbox.checked=true;
    
  })             
}
 lastChecked= this;   
}

checkboxes.forEach((checkbox,i) => checkbox.addEventListener('click',logic));
.wrapper{
 display: flex;
 flex-direction: column;
}
<div class="wrapper">
  <input type="checkbox" name="one">
  <input type="checkbox" name="two">
  <input type="checkbox" name="three">
  <input type="checkbox" name="four">
  <input type="checkbox" name="five">
</div>
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.