Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Select multiple HTML table rows with Ctrl+click and Shift+click

Demo

I want to select multiple rows using Windows Shift and Ctrl keys, like multiple folder selection in Windows.

From table of selected rows I have to get the first column (student id) and pass to server side C# and delete those records from database.

I have written a code in javascript but the classname is not being applied to <tr> on Shift or Ctrl+ left click.

HTML

<table id="tableStudent" border="1">
    <thead>
        <tr>
            <th>ID</th>
            <th>Name</th>
            <th>Class</th>
        </tr>
    </thead>
    <tbody>
        <tr onmousedown="RowClick(this,false);">
            <td>1</td>
            <td>John</td>
            <td>4th</td>
        </tr>
         <tr onmousedown="RowClick(this,false);">
            <td>2</td>
            <td>Jack</td>
            <td>5th</td>
        </tr>
         <tr onmousedown="RowClick(this,false);">
            <td>3</td>
            <td>Michel</td>
            <td>6th</td>
        </tr>
        <tr onmousedown="RowClick(this,false);">
            <td>4</td>
            <td>Mike</td>
            <td>7th</td>
        </tr>
        <tr onmousedown="RowClick(this,false);">
            <td>5</td>
            <td>Yke</td>
            <td>8th</td>
        </tr>
         <tr onmousedown="RowClick(this,false);">
            <td>6</td>
            <td>4ke</td>
            <td>9th</td>
        </tr>
        <tr onmousedown="RowClick(this,false);">
            <td>7</td>
            <td>7ke</td>
            <td>10th</td>
        </tr>
    </tbody>
</table>

JavaScript

var selectedrow;
function RowClick(currenttr, lock) {
var trs =tableStudent.tBodies[0].getElementsByTagName("tr");
var cnt;
    if(window.event.button==2)
    {
        if(currenttr.className=='selected')
        return false;
    }
alert(trs.length);
if (((window.event.shiftKey) && (window.event.ctrlKey) ) ||(window.event.shiftKey))
    {
        for(var j=0; j<trs.length; j++)
        {
            if (trs[j].className!='normallock')
            {
                trs[j].className='normal';
            }
        }
        var mark=false;

        if (typeof(selectedrow)=="undefined")
        {
            selectedrow=currenttr;
            selectedrow.className='selected'
            return false;
        }
        for(var j=0; j<trs.length; j++)
        {

            if ((trs[j].id ==selectedrow.id) || (trs[j].id ==currenttr.id) )
            {
                if (trs[j].className!='normallock')
                {
                trs[j].className='selected'
                mark = !(mark);
                }
            }
            else
            {
                if(mark==true)
                {
                    if (trs[j].className!='normallock')
                    trs[j].className='selected'
                }
            }
        }
    }
    else if(window.event.ctrlKey)
    {
        //if ctrl key is seelcted while selecting the patients
        // select the patient with currently clicked row plus
        // maintain the previous seelcted status
        cnt=0;
        for(var j=0; j<trs.length; j++)
        {
            if(trs[j].id == currenttr.id)
            {
                if(trs[j].className=='selected')
                {
                    trs[j].className='normal';
                }else
                {
                    trs[j].className='selected';
                }
            }
            if(trs[j].className=='selected')
            {
                cnt++;
            }
        }

        if(cnt==0)
        {
            selectedrow=undefined;
            return false;
        }
    }
    else
    {
        for(var j=0; j<trs.length; j++)
        {
            if(trs[j].id == currenttr.id)
            {
                trs[j].className='selected'
            }
            else
            {
                if (trs[j].className!='normallock')
                trs[j].className='normal';
            }

        }
    }
    selectedrow=currenttr;
}
like image 481
John Avatar asked Jul 31 '13 07:07

John


People also ask

How to select multiple rows in HTML table?

Select multiple HTML table rows with Ctrl+click and Shift+click.

How do I select multiple rows in react table?

Rows Selection Modes in React DataTable. Select multiple rows by holding Shift or Ctrl and clicking on a row.


2 Answers

It's probably not all of the functionality you want, since the question is a bit vague, but he's an attempt at adding Ctrl or Shift+ left mouse button to select or deselect multiple table rows - see demo and code below. Disclaimer: Only tested in Chrome and code can almost certainly be optimised.

JavaScript

var lastSelectedRow;
var trs = document.getElementById('tableStudent').tBodies[0].getElementsByTagName('tr');

// disable text selection
document.onselectstart = function() {
    return false;
}

function RowClick(currenttr, lock) {
    if (window.event.ctrlKey) {
        toggleRow(currenttr);
    }

    if (window.event.button === 0) {
        if (!window.event.ctrlKey && !window.event.shiftKey) {
            clearAll();
            toggleRow(currenttr);
        }

        if (window.event.shiftKey) {
            selectRowsBetweenIndexes([lastSelectedRow.rowIndex, currenttr.rowIndex])
        }
    }
}

function toggleRow(row) {
    row.className = row.className == 'selected' ? '' : 'selected';
    lastSelectedRow = row;
}

function selectRowsBetweenIndexes(indexes) {
    indexes.sort(function(a, b) {
        return a - b;
    });

    for (var i = indexes[0]; i <= indexes[1]; i++) {
        trs[i-1].className = 'selected';
    }
}

function clearAll() {
    for (var i = 0; i < trs.length; i++) {
        trs[i].className = '';
    }
}

HTML

<table id="tableStudent" border="1">
    <thead>
        <tr>
            <th>ID</th>
            <th>Name</th>
            <th>Class</th>
        </tr>
    </thead>
    <tbody>
        <tr onmousedown="RowClick(this,false);">
            <td>1</td>
            <td>John</td>
            <td>4th</td>
        </tr>
         <tr onmousedown="RowClick(this,false);">
            <td>2</td>
            <td>Jack</td>
            <td>5th</td>
        </tr>
         <tr onmousedown="RowClick(this,false);">
            <td>3</td>
            <td>Michel</td>
            <td>6th</td>
        </tr>
        <tr onmousedown="RowClick(this,false);">
            <td>4</td>
            <td>Mike</td>
            <td>7th</td>
        </tr>
        <tr onmousedown="RowClick(this,false);">
            <td>5</td>
            <td>Yke</td>
            <td>8th</td>
        </tr>
         <tr onmousedown="RowClick(this,false);">
            <td>6</td>
            <td>4ke</td>
            <td>9th</td>
        </tr>
        <tr onmousedown="RowClick(this,false);">
            <td>7</td>
            <td>7ke</td>
            <td>10th</td>
        </tr>
    </tbody>
</table>

CSS

.selected {
    background: lightBlue
}

I would also look at addEventListener vs onclick and move the event handler binding out of the HTML and into JavaScript. This is known as Unobtrusive Javascript.

Resources you might want to read:

  • Retrieve Table Row Index of Current Row
  • disable text selection while pressing 'shift'
  • https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/sort
like image 64
andyb Avatar answered Sep 18 '22 16:09

andyb


I made it work with all the Windows 7 explorer behaviors and jquery mouse events.

http://jsfiddle.net/ubershmekel/nUV23/6/

Note that:

  • When you just click, you set a pivot for the next shift-click
  • Use Ctrl-Shift to expand your current selection and not pivot like Shift-alone does.
  • Use Ctrl-click to add a pivot, you can use Ctrl-Shift to then expand that selection around the new pivot.

The js:

var selectionPivot;
// 1 for left button, 2 for middle, and 3 for right.
var LEFT_MOUSE_BUTTON = 1;
var trs = document.getElementById('tableStudent').tBodies[0].getElementsByTagName('tr');
var idTds = $('td:first-child');
idTds.each(function(idx, val) {
    // onselectstart because IE doesn't respect the css `user-select: none;`
    val.onselectstart = function() { return false; };
    $(val).mousedown(function(event) {
        if(event.which != LEFT_MOUSE_BUTTON) {
            return;
        }
        var row = trs[idx];
        if (!event.ctrlKey && !event.shiftKey) {
            clearAll();
            toggleRow(row);
            selectionPivot = row;
            return;
        }
        if (event.ctrlKey && event.shiftKey) {
            selectRowsBetweenIndexes(selectionPivot.rowIndex, row.rowIndex);
            return;
        }
        if (event.ctrlKey) {
            toggleRow(row);
            selectionPivot = row;
        }
        if (event.shiftKey) {
            clearAll();
            selectRowsBetweenIndexes(selectionPivot.rowIndex, row.rowIndex);
        }
    });
});

function toggleRow(row) {
    row.className = row.className == 'selected' ? '' : 'selected';
}

function selectRowsBetweenIndexes(ia, ib) {
    var bot = Math.min(ia, ib);
    var top = Math.max(ia, ib);

    for (var i = bot; i <= top; i++) {
        trs[i-1].className = 'selected';
    }
}

function clearAll() {
    for (var i = 0; i < trs.length; i++) {
        trs[i].className = '';
    }
}

And the CSS:

.selected {
    background: #bdf;
}

td:first-child {
    -webkit-user-select: none;
    -khtml-user-select: none;
    -moz-user-select: none;
    -o-user-select: none;
    user-select: none;
}

td,th {
    padding: 3px;
    border: 2px solid #aaa;
}

table {
    border-collapse: collapse;
}
like image 21
ubershmekel Avatar answered Sep 18 '22 16:09

ubershmekel