使用 Ctrl+单击和 Shift+单击选择多个 HTML 表格行

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/17964108/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-29 11:41:35  来源:igfitidea点击:

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

javascripthtmlweb-applicationsweb

提问by John

Demo

演示

I want to select multiple rows using Windows Shiftand Ctrlkeys, like multiple folder selection in Windows.

我想使用 WindowsShiftCtrl键选择多行,就像 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.

从选定行的表中,我必须获取第一列(学生 ID)并传递到服务器端C#并从数据库中删除这些记录。

I have written a code in javascript but the classnameis not being applied to <tr>on Shiftor Ctrl+ left click.

我用 javascript 编写了一个代码,但类名没有应用于<tr>onShiftCtrl+ left click

HTML

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

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

回答by andyb

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

这可能不是您想要的所有功能,因为问题有点模糊,但他试图添加CtrlShift+鼠标左键来选择或取消选择多个表行 -请参阅下面的演示和代码。免责声明:仅在 Chrome 中测试,代码几乎可以肯定会被优化

JavaScript

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

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

CSS

.selected {
    background: lightBlue
}

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

我还会查看addEventListener 与 onclick并将事件处理程序绑定从HTML移到JavaScript 中。这被称为Unobtrusive Javascript

Resources you might want to read:

您可能想阅读的资源:

回答by Roko C. Buljan

Here's a jQuery pluginI wrote recently for a project. Thought sharing...

这是我最近为一个项目编写的jQuery 插件。思想分享...

Works exactly like you're used to, + it's extremely fastcause it operates over an Array without the need to check for attributes, classes etc, and the add/removeClass triggers only on the selected elements:

工作方式与您习惯的完全一样,+ 它非常快,因为它可以在 Array 上运行而无需检查属性、类等,并且 add/removeClass 仅在所选元素上触发:

// Use like:
// $("table").selekt();
//
// Available options:
$("table").selekt({
  children: "tr",           // Elements to target (default: "tbody tr")
  className: "selected",    // Desired CSS class  (default: "selected")
  onSelect: function(sel) { // Useful callback
    $("span").text(sel.length + ' in ' + this.id);
  }
});
.selected { background: #0bf; }
table {border: 1px solid #555;display: inline-block; vertical-align: top;}
<p>Seleceted: <span id="info">0</span></p>

<table id="table_1">
  <tr><td>1 SELECT ME</td></tr>
  <tr><td>2 SELECT ME</td></tr>
  <tr><td>3 SELECT ME</td></tr>
  <tr><td>4 SELECT ME</td></tr>
  <tr><td>5 SELECT ME</td></tr>
  <tr><td>6 SELECT ME</td></tr>
</table>

<table id="table_2">
  <tr><td>1 SELECT ME</td></tr>
  <tr><td>2 SELECT ME</td></tr>
  <tr><td>3 SELECT ME</td></tr>
  <tr><td>4 SELECT ME</td></tr>
</table>

<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<script>
;(function($) {
  // selekt jQuery plugin // http://stackoverflow.com/a/35813513/383904
  $.fn.selekt = function() {

    var settings = $.extend({
      children: "tbody tr",
      className: "selected",
      onSelect: function() {}
    }, arguments[0] || {});

    return this.each(function(_, that) {
      var $ch = $(this).find(settings.children),
        sel = [],
        last;

      $ch.on("mousedown", function(ev) {
        var isCtrl = (ev.ctrlKey || ev.metaKey),
          isShift = ev.shiftKey,
          ti = $ch.index(this),
          li = $ch.index(last),
          ai = $.inArray(this, sel);

        if (isShift || isCtrl) ev.preventDefault();

        $(sel).removeClass(settings.className);

        if (isCtrl) {
          if (ai > -1) sel.splice(ai, 1);
          else sel.push(this);
        } else if (isShift && sel.length > 0) {
          if (ti > li) ti = [li, li = ti][0];
          sel = $ch.slice(ti, li + 1);
        } else {
          sel = ai < 0 || sel.length > 1 ? [this] : [];
        }

        last = this;
        $(sel).addClass(settings.className);
        settings.onSelect.call(that, sel);
      });
    });
  };
}(jQuery));
</script>

回答by ubershmekel

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

我使它适用于所有 Windows 7 资源管理器行为和 jquery 鼠标事件。

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

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.
  • 只需单击即可为下一次 shift 单击设置轴心
  • 使用 Ctrl-Shift 扩展您当前的选择,而不是像单独使用 Shift 那样旋转。
  • 使用 Ctrl-单击添加一个枢轴,您可以使用 Ctrl-Shift 然后围绕新的枢轴扩展该选择。

The js:

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:

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

回答by Sergey NN

Check this example:

检查这个例子:

JSFiddle: Highlight list with shift and ctrl

JSFiddle:使用 shift 和 ctrl 突出显示列表

Part of the code:

部分代码:

switch(e.type) {
    case "keydown" :
        console.log('k_down');
        keysPressed.push(e.keyCode);
        break;
    case "keyup" :
        console.log('k_up');
        var idx = keysPressed.indexOf(e.keyCode);
        if (idx >= 0)
            keysPressed.splice(idx, 1);
        break;
}

Sources could be found here: Source files github

来源可以在这里找到: 源文件github

回答by CosmicBuffalo

I know this question is already answered and it's pretty old, but I found the answer by andyb to be super helpful. Perhaps it was because andyb's answer might be outdated now, but I ended up having to change his solution a bit to work with my project, so I figured I'd share my updated version. Here is what I ended up with, using a sprinkling of jQuery.

我知道这个问题已经有人回答了,而且已经很老了,但我发现 andyb 的回答非常有帮助。也许是因为 andyb 的答案现在可能已经过时了,但我最终不得不稍微改变他的解决方案以适应我的项目,所以我想我会分享我的更新版本。这是我最终得到的结果,使用了一点 jQuery。

$(document).ready(function(){
    //put all the table rows in a variable after page load to pass in to RowClick
    var trs = $('#tableStudent tr')
    //bind the click handler to all the table rows
    $('tr').on('click', function(){
        //call the RowClick function on click event
        RowClick($(this),false,trs)
    })
})

//declare variable to store the most recently clicked row
var lastSelectedRow;

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

function RowClick(currentrow, lock, rows) {
    //if control is held down, toggle the row
    if (window.event.ctrlKey) {
        toggleRow(currentrow);
    }

    //if there are no buttons held down...
    if (window.event.button === 0) {

        //if neither control or shift are held down...
        if (!window.event.ctrlKey && !window.event.shiftKey) {
            //clear selection
            clearAll(rows);
            //toggle clicked row
            toggleRow(currentrow);
        }

        //if shift is held down...
        if (window.event.shiftKey) {
            //pass the indexes of the last selected row and currently selected row along with all rows
            selectRowsBetweenIndexes([lastSelectedRow.index(), currentrow.index()], rows)
        }
    }
}

function toggleRow(row) {
    //if the row is not the header row...
    if (!row.hasClass('header-row')){
        //if the row is selected...
        if (row.hasClass('selected')){
            //deselect it
            row.removeClass('selected')
        }
        else{
            //otherwise, select it
            row.addClass('selected')
        }
        //reassign the most recently selected row
        lastSelectedRow = row;
    }
}

function selectRowsBetweenIndexes(indexes,rows) {
    //sort the indexes in ascending order
    indexes.sort(function(a, b) {
        return a - b;
    });

    //for every row starting at the first index, until the second index...
    for (var i = indexes[0]; i <= indexes[1]; i++) {
        //select the row
        $(rows[i+1]).addClass('selected');
    }
}

function clearAll(rows) {
    //for all rows...
    for (var i = 0; i < rows.length; i++) {
        //deselect each row
        $(rows[i]).removeClass("selected");
    }
}

回答by Akshay Vijay Jain

Following code is modification from Robo C Buljan, since i wanted to multiselect using checkboxes and shift key

以下代码是 Robo C Buljan 的修改,因为我想使用复选框和 shift 键进行多选

<includeScript value="/jquery-3.2.0.min.js" />
<script>
 ;(function($) {
 // selekt jQuery plugin // http://stackoverflow.com/a/35813513/383904
 $.fn.selekt = function() {
   var settings = $.extend({
       children: "td input[type='checkbox'][name='ids']",
       onSelect: function(){
       }
   }, arguments[0] || {});
   return this.each(function(_, that){
     var $ch = $(this).find(settings.children),
     sel = [],
     last;
     $ch.on("mouseup", function(ev) {
      /* Note 1: Remember this code is run when a checkbox is clicked and is run before checbox's state changes because of click 
      i.e. to say if the checkbox was checked and we clicked it to uncheck, then this event handler (mouse up)code is called before the unchecing happens */
       if(ev.shiftKey || ev.ctrlKey){
         ev.preventDefault();
         ev.stopPropagation();
       }
       var self = this;
       var ti = $ch.index(this), // index of current element in the matching elements
           li = $ch.index(last), // index of last element in the matching elements
           ai = $.inArray(this, sel); // index of this in the sel array
       if(ev.ctrlKey) {
         if(ai > -1) sel.splice(ai, 1);
         else sel.push(this);
       }
       else if(ev.shiftKey && sel.length > 0) {
         if(ti > li) ti = [li, li=ti][0];
         sel = $ch.slice(ti, li+1);
       }
       else {
         sel = ai < 0 || sel.length > 1 ? [this] : [];
       }
       last = this;
       /* purpose 2 
       code to check checkboxes inside the array*/
       $(sel).each(function(index, checkbox){
        /* see/search Note 1 in comments, if the checkbox is already checked/unchecked then uncheck/check all the elements straight from the last element correspondingly */
        if(self.checked) { 
         if( checkbox != self){
           checkbox.checked = false;
         }
        } else { 
         if( checkbox != self){
           checkbox.checked = true;
         }
        }
       })
       /*end of purpose 2*/

       // settings.onSelect.call(that, sel); // this is defined just in case we want to call some function  after the select/deselect operation
     });
   });
 };
 }(jQuery));
 setTimeout(function(){
  $("table.list").selekt();  
 },500)
 
</script>