简体   繁体   中英

Multi-select checkboxes with tablesorter

I have a Python script which generates an HTML table. The final column of the table contains checkboxes. I want to use the Shift key to select multiple checkboxes. So, I've incorporated this Javascript .

However, I'm sorting the table columns after loading using tablesorter (and after calling the above Javascript). Furthermore, the user can also sort columns by clicking on column headers. This results in the wrong checkboxes being selected after the user uses Shift-click.

So far I have tried:

  • moving the select multiple checkboxes javascript to after the sorting (which seems logical to me), but then the sorting functionality does not work
  • the other javascript answers to that question ( How can I shift-select multiple checkboxes like GMail? ) but then multi-select does not work
  • other Googled code ( like this ) - but again multi-select does not work

The code:

<script src='shift-click-select.js'></script>
<script src='jquery-latest.js'></script>
<script src='jquery.tablesorter.min.js'></script>
<script>
//Javascript function to sort table "my_table" by default on first column (0,0) and then on second column (1) in ascending order (0).
$(function() {
    $("#my_table").tablesorter({sortList:[[0,0],[1,0]]});
});
</script>
<table id="my_table" class="tablesorter" border="0" cellpadding="0" cellspacing="1">
    <td><input type="checkbox" name="%s" class="chkbox" /></td>
    ...
</table>

note: shift-click-select.js is from answer mention above .

My guess is that I might need to re-number the checkboxes every time the table is resorted, but I'm hoping there is an easier way?

I suspect that you copied the code from this post almost exactly:

<script type="text/javascript">
    var lastChecked = null;

    $(document).ready(function() {
        var $chkboxes = $('.chkbox');
        $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).attr('checked', lastChecked.checked);

            }

            lastChecked = this;
        });
    });
</script>

The problem you're probably experiencing is caused by the var $chkboxes = $('.chkbox'); invoked on the document being ready. That's declaring a list of .chkbox objects in their initial order when the page loads. tablesorter then changes the order.

If what I'm assuming is correct, then getting it to work properly would be as simple as changing:

var $chkboxes = $('.chkbox');
$chkboxes.click(function(e) ...

to:

$('.chkbox').click(function(e) {
    var $chkboxes = $('.chkbox');

This way the checkbox order is determined on each click rather than once on page load.

It would help if we got to see the contents of your shift-click-select.js .

using this i was able to achieve desired function

$(function() {
    var $table = $('#myTable');
    var $chkboxes,lastChecked = null;
    $table
    .tablesorter({sortList:[[0,0],[1,0]]})
    .on('sortEnd',function() {
        $chkboxes = $table.find(':checkbox');
    })
    .on('click',":checkbox",function(e){
        if(!lastChecked) {
            lastChecked = this;
            return;
        }
        if(e.shiftKey) {
            var start = $chkboxes.index(this);
            var end = $chkboxes.index(lastChecked);
            var last = lastChecked.checked; //cache as we might change its value
            $chkboxes.slice(Math.min(start,end), Math.max(start,end)+ 1).prop('checked', last);
        }
        lastChecked = this;
    });
});

notice i changed attr('checked' to prop('checked' as checked="false" is an invalid state

I used senordev's solution on my app, but found a large pitfall in my testing, which I've resolved below.

senordev's implied solution:

$('.chkbox').click(function(e) {
   var $chkboxes = $('.chkbox')

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

The issue I ran into was regarding filtration, if I filtered out some rows, and shift-selected, the script would select all the hidden rows in between as well (sometimes thousands). Therefore, I added a small fix:

var $chkboxes = $('.chkbox')

to

var $chkboxes = $('.chkbox').filter(':visible');

Additional corner cases I accounted for include resetting the lastChecked value whenever the sort changes (because lastChecked might now be on a completely different page) and when the filters change (because lastChecked might not be visible anymore).

$("table").tablesorter({
   ...
})
// Clear the lastChecked to avoid unexpected selections.
// e.g. lastChecked might not be on the visible page anymore.
.bind("sortStart",function() { 
   lastChecked = null
}).bind("sortEnd",function() { 
   lastChecked = null
}).bind('filterEnd', function() {
   lastChecked = null
});

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM