Выберите несколько строк таблицы HTML с помощью Ctrl + click и Shift + click

Демо

Я хочу выбрать несколько строк с помощью клавиш Windows Shift и Ctrl, таких как выбор нескольких папок в Windows.

Из таблицы выбранных строк я должен получить первый столбец (id студента) и перейти на сторону сервера C# и удалить эти записи из базы данных.

Я написал код в javascript, но имя класса не применяется к <tr> on Shift или Ctrl + щелчок левой кнопкой мыши.

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

Ответ 1

Вероятно, это не вся необходимая функциональность, поскольку вопрос немного расплывчатый, но он пытается добавить кнопку Ctrl или Shift + левую кнопку мыши, чтобы выбрать или отменить выбор нескольких строк таблицы - см. демонстрацию и код ниже. Отказ от ответственности: только проверенные в Chrome и код почти наверняка могут быть оптимизированы.

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
}

Я также посмотрел бы addEventListener vs onclick и переместил привязку обработчика события из HTML и в JavaScript. Это называется ненавязчивый Javascript.

Ресурсы, которые вы, возможно, захотите прочитать:

Ответ 2

Здесь плагин jQuery, который я написал недавно для проекта. Мысль об обмене...

Работает точно так же, как вы привыкли, + он чрезвычайно быстрый заставляет его работать с массивом без необходимости проверки атрибутов, классов и т.д., а триггеры 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>

Ответ 3

Я сделал это для работы со всеми поведениями проводника Windows 7 и событиями jQuery мыши.

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

Обратите внимание, что:

  • Когда вы просто щелкаете, вы устанавливаете опорную точку для следующего щелчка мышью
  • Используйте Ctrl-Shift, чтобы расширить свой текущий выбор, а не свернуть, как это делает Shift.
  • Используйте Ctrl кнопкой мыши, чтобы добавить стержень, вы можете использовать Ctrl-Shift, чтобы затем расширить это выделение вокруг новой оси.

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

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

Ответ 5

Я знаю, что этот вопрос уже ответил, и он довольно старый, но я нашел ответ byyyb, чтобы он был очень полезным. Возможно, это связано с тем, что ответ anyb может быть устаревшим сейчас, но мне пришлось немного изменить его решение для работы с моим проектом, поэтому я решил, что поделился бы моей обновленной версией. Вот что я закончил, используя опрыскивание 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");
    }
}

Ответ 6

Следующий код - это модификация от Robo C Buljan, так как я хотел многократно использовать флажки и клавишу переключения

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