No GMail, o usuário pode clicar em uma caixa de seleção na lista de e-mail, manter pressionada a tecla Shift e selecionar uma segunda caixa de seleção. O JavaScript irá então marcar / desmarcar as caixas de seleção que estão entre as duas caixas de seleção.
Estou curioso para saber como isso é feito? Isso é JQuery ou algum JavaScript básico (ou complexo)?
javascript
gmail
Ascaloniano
fonte
fonte
Respostas:
Escrevi uma demonstração independente que usa 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>
fonte
.prop('checked'
, não.attr('checked'
. jsFiddle: jsfiddle.net/dn4jv9a5Isso é feito por meio de um javascript bastante simples.
Eles controlam a id da última caixa marcada e quando outra caixa de seleção é marcada, eles usam o atributo de evento shiftKey para ver se shift foi pressionado enquanto clicava na caixa de seleção. Nesse caso, eles definem a propriedade marcada de cada caixa de seleção entre as duas como verdadeira.
Para determinar quando uma caixa está marcada, eles provavelmente usam um evento onclick nas caixas de seleção
fonte
Recentemente, escrevi um plugin jQuery que fornece esse recurso e muito mais.
Depois de incluir o plug-in, você só precisa inicializar o contexto das caixas de seleção com o seguinte snippet de código:
$('#table4').checkboxes({ range: true });
Aqui está o link para a documentação, demonstração e download: http://rmariuzzo.github.io/checkboxes.js/
fonte
Parece que todas as respostas que encontro online dependem completamente do jQuery para isso. JQuery adiciona muito pouca funcionalidade. Esta é uma versão rápida que não requer nenhuma estrutura:
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; }); } }
E então inicialize-o sempre que precisar:
allow_group_select_checkboxes('[id of a wrapper that contains the checkboxes]')
fonte
Bem, a postagem é bem antiga, mas aqui está uma solução que acabei de encontrar: Plug-In jQuery Field
fonte
Consegui essa solução em http://abcoder.com/javascript/jquery/simple-check-uncheck-all-jquery-function/ (agora morto) :
Código JavaScript e 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>
fonte
Inspirado pelas boas respostas fornecidas, aqui está uma versão simples do JavaScript que usa
Array.prototype
para forçar as listas de nós a usar funções de array, em vez defor
loops.(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>
fonte
Gostei muito do exemplo do gyo e adicionei algum código para que funcione em todas as caixas de seleção com o mesmo nome.
Eu também adicionei um MutationObserver para que os eventos também sejam tratados nas caixas de seleção recém-adicionadas.
$(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>
fonte
Peguei a versão jQuery de @BC. e o transformei em uma versão ES6, já que o código está resolvendo o problema de maneira bastante elegante, caso alguém ainda se depare com isso ...
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; } ) ); }
fonte
Encontrou a melhor solução que funciona para marcar e desmarcar caixas de seleção.
Usa um javascript & Jquery principal.
$(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>
fonte
Aqui está outra implementação semelhante à seleção múltipla do 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]; } } }); });
fonte
Esta é a solução jquery que escrevi e uso:
chksel
chksel_index
Além disso, cada
checkbox
um tem um atributo denominadorg
que contém o mesmo índicevar 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');}
})
fonte
esta solução funciona para mim, também baseada em Ajax para 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>
fonte