Пропустить выбор tr с помощью jquery при нажатии клавиши

#javascript #jquery #html #dom

#javascript #jquery #HTML #dom

Вопрос:

Итак, у меня сейчас такая ситуация:

https://jsfiddle.net/rucjr5cm/

 $(function() {
  var row = $('.DataList tbody tr.highlight');
  var index = row.index();
  console.log('current row: '   index);

  function highlight(tableIndex) {
    $('.DataList tbody tr').removeClass('highlight');
    $('.DataList tbody tr:eq('   tableIndex   ')').addClass('highlight');
  }

  $(document).keydown(function(e) {
    var currentRow = $('.DataList tbody tr.highlight');

    switch (e.which) {
      case 38:
        var prevRow = currentRow.closest('.DataList tbody tr:not(.Header, .SubHeader, .Total)').prev('tr');
        highlight(prevRow.index());
        break;
      case 40:
        var nextRow = currentRow.closest('.DataList tbody tr:not(.Header, .SubHeader, .Total)').next('tr');
        highlight(nextRow.index());
        break;
    }
  });
});  
 .highlight {
  background-color: yellow !important;
}
.Header,
.SubHeader,
.Total {
  background-color: grey;
}  
 <script src="https://code.jquery.com/jquery-3.1.1.js" integrity="sha256-16cdPddA6VdVInumRGo6IbivbERE8p7CQR3HzTBuELA=" crossorigin="anonymous"></script>
<table id="data" class="DataList" border="1" cellspacing="1" cellpadding="1">
  <tbody>
    <tr>
      <th>#</th>
      <th>header2</th>
      <th>header3</th>
      <th>header4</th>
      <th>header5</th>
    </tr>
    <tr>
      <td>1</td>
      <td>data</td>
      <td>data</td>
      <td>data</td>
      <td>data</td>
    </tr>
    <tr class="Header">
      <td>2</td>
      <td>data</td>
      <td>data</td>
      <td>data</td>
      <td>data</td>
    </tr>
    <tr class="SubHeader">
      <td>3</td>
      <td>data</td>
      <td>data</td>
      <td>data</td>
      <td>data</td>
    </tr>
    <tr class="highlight">
      <td>4</td>
      <td>data</td>
      <td>data</td>
      <td>data</td>
      <td>data</td>
    </tr>
    <tr>
      <td>5</td>
      <td>data</td>
      <td>data</td>
      <td>data</td>
      <td>data</td>
    </tr>
    <tr class="Total">
      <td>6</td>
      <td>data</td>
      <td>data</td>
      <td>data</td>
      <td>data</td>
    </tr>
  </tbody>
</table>  

Я бы хотел, чтобы выделенная строка пропускала серые (которые определяются классами и не могут быть изменены). Было бы неплохо также, если бы был достигнут последний, не выделенный серым цветом, перейти к первому (опять же, не выделенный серым цветом).

Я тоже пытался использовать ближайший следующий и предыдущий подход из jQuery, но из этого тоже ничего не вышло.

Я никогда не использовал ближайший и следующий / предыдущий подход, и я, конечно, делаю что-то не так, может кто-нибудь оказать какую-либо помощь в этом?

Большое спасибо!

Комментарии:

1. ваша функция highlight(tableIndex) всегда будет вызываться путем передачи значения -1, т.е. highlight(-1)

Ответ №1:

Я бы использовал функции nextAll and prevAll :

 var rows = $('.DataList tbody tr');   // cache this for better performance

function highlight(row) {
  // changed to use the cached object
  rows.removeClass('highlight');
  
  // instead of using the index, you can just pass the object in
  row.addClass('highlight');
}

$(document).keydown(function(e) {
  
  var currentRow = rows.filter('.highlight');   // use filter to get the current highlight

  switch (e.which) {
    case 38:
      e.preventDefault(); // this will stop the page moving when the arrow is pressed

      var prevRows = currentRow.prevAll('tr').not('.Header,.SubHeader,.Total'),  // use prevAll to get all preceding rows and then filter out ones with the classes,
          prevRow;
      
      if (prevRows.length) {
        // test if there is a matching row and then highlight it
        prevRow = prevRows.eq(0);
      } else {
        // no matching so start from the end 
        prevRow = currentRow.nextAll('tr').not('.Header,.SubHeader,.Total').last(); 
      }
      
      highlight(prevRow); // no need to figure out the index.  but if you want you would do rows.index(prevRow); - gets the index with regards to all rows
      break;

    case 40:
      e.preventDefault(); // this will stop the page moving when the arrow is pressed
      var nextRows = currentRow.nextAll('tr').not('.Header,.SubHeader,.Total'),  // same as above but next
          nextRow; 
      
      if (nextRows.length) {
        nextRow = nextRows.eq(0);
      } else {
        nextRow = currentRow.prevAll('tr').not('.Header,.SubHeader,.Total').last();  
        // no matching so start from the beginning 
      }
      
      highlight(nextRow);
      break;
  }
});  
 .highlight {
  background-color: yellow !important;
}

.Header,
.SubHeader,
.Total {
  background-color: grey;
}  
 <script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<table id="data" class="DataList" border="1" cellspacing="1" cellpadding="1">
  <thead>               <!-- put header into a thead so it's not included in highlighting -->
    <tr>
      <th>#</th>
      <th>header2</th>
      <th>header3</th>
      <th>header4</th>
      <th>header5</th>
    </tr>
  </thead>
  <tbody>
    <tr>
      <td>1</td>
      <td>data</td>
      <td>data</td>
      <td>data</td>
      <td>data</td>
    </tr>
    <tr class="Header">
      <td>2</td>
      <td>data</td>
      <td>data</td>
      <td>data</td>
      <td>data</td>
    </tr>
    <tr class="SubHeader">
      <td>3</td>
      <td>data</td>
      <td>data</td>
      <td>data</td>
      <td>data</td>
    </tr>
    <tr class="highlight">
      <td>4</td>
      <td>data</td>
      <td>data</td>
      <td>data</td>
      <td>data</td>
    </tr>
    <tr>
      <td>5</td>
      <td>data</td>
      <td>data</td>
      <td>data</td>
      <td>data</td>
    </tr>
    <tr class="Total">
      <td>6</td>
      <td>data</td>
      <td>data</td>
      <td>data</td>
      <td>data</td>
    </tr>
  </tbody>
</table>  

С closest вашим первоначальным ответом — он проходит через предков (родителей), а не через братьев и сестер

Комментарии:

1. возможно ли, чтобы он переходил к первой (возможной) строке при достижении последней возможной строки? это выглядит действительно многообещающе

2. @Dunnow см. Редактирование. Я также остановил прокрутку страницы при нажатии стрелки

3. <3 похоже, это именно то, что ожидалось, большое спасибо

4. Я просто подумал, что вы можете захотеть переместить e.preventDefault() в каждый из операторов case (в противном случае это предотвратит действие по умолчанию для всех нажатий клавиш!)

Ответ №2:

  1. измените опечатку в highlight
  2. простой предварительный и следующий селектор
  3. если pre amp; next tr не найден, используйте первый / последний обычный tr в качестве следующей цели выделения

 var row = $('.DataList tbody tr.highlight');
				
			function highlight(tableIndex) {
				$('.DataList tbody tr').removeClass('highlight');
				$('.DataList tbody tr:eq(' tableIndex ')').addClass('highlight'); 
			}

			$(document).keydown(function (e) {
				var currentRow = $('.DataList tbody tr.highlight');
        var normalRowSelector = 'tr:not(.Header,.SubHeader,.Total,.highlight)';
        var nextHltIndex = -1;
				switch(e.which) {
					case 38:
						nextHltIndex = currentRow.prev(normalRowSelector).index();
            if(nextHltIndex == -1){
            	nextHltIndex = $(normalRowSelector).filter(":last").index();
            }
					break;
					case 40:
						nextHltIndex = currentRow.next(normalRowSelector).index();
            if(nextHltIndex == -1){
            	nextHltIndex = $(normalRowSelector).filter(":first").index();
            }
					break;
				}
        highlight(nextHltIndex);
			 });  
 .highlight {
  background-color: yellow !important;
}
		
.Header, .SubHeader, .Total  {
  background-color: grey;
}  
 <script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<table id="data" class="DataList" border="1" cellspacing="1" cellpadding="1">
	<tbody>
        <tr class="Header">
            <th>#</th>
            <th>header2</th>
            <th>header3</th>
            <th>header4</th>
            <th>header5</th>
        </tr>
        <tr>
            <td>1</td>
            <td>data</td>
            <td>data</td>
            <td>data</td>
            <td>data</td>
        </tr>
        <tr class="Header">
            <td>2</td>
            <td>data</td>
            <td>data</td>
            <td>data</td>
            <td>data</td>
        </tr>
        <tr class="SubHeader">
            <td>3</td>
            <td>data</td>
            <td>data</td>
            <td>data</td>
            <td>data</td>
        </tr>
        <tr class="highlight">
            <td>4</td>
            <td>data</td>
            <td>data</td>
            <td>data</td>
            <td>data</td>
        </tr>
        <tr>
            <td>5</td>
            <td>data</td>
            <td>data</td>
            <td>data</td>
            <td>data</td>
        </tr>
        <tr class="Total">
            <td>6</td>
            <td>data</td>
            <td>data</td>
            <td>data</td>
            <td>data</td>
        </tr>
    </tbody>
</table>  

jsFiddle

Комментарии:

1. он не возвращается к строке # 1, он отлично работает, когда падает

Ответ №3:

Я обновил jsfiddle. Не могли бы вы ознакомиться с обновленным

jsfiddle

Надеюсь, вам нужна эта функциональность?

Ответ №4:

Идентификатор является строго селектором, а не классом.

Попробуйте это

 $('#data tr.highlight');
  

Ответ №5:

jsfiddle

Я обновил jsfiddle, который вы предоставляете, и новый подход, похоже, работает просто отлично.

Используется not() для предотвращения добавления класса highlight к любому tr attribute , который имеет class

Еще одна вещь — ваша первая tr , которая содержит все th , что должно быть включено в thead раздел раньше tbody , но я не изменил его для вас, пожалуйста, сделайте это самостоятельно

Комментарии:

1. Это тот, который работает лучше всего, проблема в том, что я предоставил упрощенную структуру таблицы, которую я хочу специально избегать. Заголовок, .SubHeader, .Total это классы, но строки все еще могут иметь другие классы. При таком подходе это не сработало бы, можно ли использовать другую логику для пропуска этих дорогих стилей? Я также должен указать, что таблица не имеет фиксированного количества строк, и может быть, что индекс 0 является одним из тех классов, которых я хочу избежать

2. Я не знал, что вы хотите избежать этих классов, хотя все, что вы хотите, это избегать серых. В любом случае @Pete уже сделал это для вас, так что, думаю, мне не нужно редактировать свой. : D

3. да, в любом случае, спасибо, вы, ребята, были очень быстрыми, не ожидали так много отзывов так скоро