Почему эта функция перемешивания работает только с 4+ элементами?JsFiddle включен - PullRequest
0 голосов
/ 08 июня 2018

У меня есть следующий код, который перетасовывает набор элементов в строке таблицы.Однако функция перемешивания работает только при наличии 4+ элементов:

var parent = $("#parent");


function shuffleRows(parent) {
  var rows = parent.children().children(".shuffledtd1");
  for (var i = rows.length - 1; i > 0; i--) {
    var j = Math.floor(Math.random() * (i + 1));
    var temp = rows[i];
    rows.eq(i - 1).after(rows[j]);
    rows.eq(j - 1).after(temp);
  }
}

shuffleRows(parent);
<script src="https://code.jquery.com/jquery-3.3.1.min.js"></script>
<table>
  <tbody id="parent">

    <tr id="node2" class="shufflerow">
      <td class="shuffledtd shuffledtd1">AA</td>
      <td class="shuffledtd shuffledtd1">BB</td>

      <!-- IF I DELETE THIS AND THE FOLLOWING ROW, THE PRIOR 2 ROWS NO LONGER SHUFFLE -->
      <td class="shuffledtd shuffledtd1">CC</td>
      <td class="shuffledtd shuffledtd1">DD</td>
    </tr>

  </tbody>
</table>

Полный код: http://jsfiddle.net/d8rkgx0z/

Я думаю, что это как-то связано с этой частью кода:

    rows.eq(i - 1).after(rows[j]);
    rows.eq(j - 1).after(temp);

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

Заранее спасибо за помощь!

Ответы [ 3 ]

0 голосов
/ 08 июня 2018

Ваш сценарий может быть упрощен на большую длину, особенно с использованием правильных селекторов и случайного сортировщика (Охвачены оба случая сортировки td в пределах tr - или tr в пределах tbody:

const randomSorter = () => 0.5 - Math.random();

$('.shufflecells tr').each(function() {
  $(this).html($('td', this).sort(randomSorter));
});

$('.shufflerows').each(function() {
  $(this).html($('tr', this).sort(randomSorter));
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.0.3/jquery.min.js"></script>
<table>
  <tbody class="shufflecells">
    <tr>
      <td>AA</td>
      <td>BB</td>
      <td>CC</td>
      <td>DD</td>
    </tr>
  </tbody>
</table>

<table>
  <tbody class="shufflecells">
    <tr>
      <td>AA</td>
      <td>BB</td>
    </tr>
  </tbody>
</table>

<table>
  <tbody class="shufflerows">
    <tr>
      <td>AA</td>
    </tr>
    <tr>
      <td>BB</td>
    </tr>
    <tr>
      <td>CC</td>
    </tr>
    <tr>
      <td>DD</td>
    </tr>
  </tbody>
</table>
0 голосов
/ 08 июня 2018

Ответ Ибрагима Махрира - более элегантный способ сделать то, что вы пытаетесь сделать, но в интересах помочь вам понять, почему ваше решение не работает, я также публикую это сообщение.

Проблема:

Проблема, с которой вы столкнулись, заключается в том, что когда i = 0, когда вы делаете (i - 1), вы получаете отрицательный показатель, который не является допустимым индексом в вашей таблице.

rows.eq (i - 1) .after (row [j]);

Способ работы вашего решения:

Ниже описано, как вы могли решить эту проблему с помощью существующего кода:

function shuffleRows(parent) {
    var rows = parent.children().children(".shuffledtd1");
    // Changed to i >= 0.
    for (var i = rows.length - 1; i >= 0; i--) {
        var j = Math.floor(Math.random() * (i + 1));
        var temp = rows[i];
        // Changed to just i, instead if i-1.
        rows.eq(i).after(rows[j]);
        rows.eq(j - 1).after(temp);
    }
}

$('button').on('click', function() {
	shuffleRows($("#parent"));
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>

<table>
    <tbody id="parent">

        <tr id="node2" class="shufflerow">
            <td class="shuffledtd shuffledtd1">AA</td>
            <td class="shuffledtd shuffledtd1">BB</td>
            <td class="shuffledtd shuffledtd1">CC</td>

        </tr>
  
    </tbody>
</table>
<button>Shuffle</button>

Этот фрагмент только что внес два небольших изменения, которые я отметил в коде, чтобы избежать возникшей проблемы с отрицательным индексом.

Опять же,Есть гораздо более элегантные способы решения этой задачи, но я всегда много понимаю, почему что-то не работает, поэтому я хотел, чтобы у вас было объяснение.

0 голосов
/ 08 июня 2018

Вместо того, чтобы дважды вызывать children, просто передайте прямой родительский элемент ячеек.Кроме того, перетасовать детей намного проще, используя jQuery#sort:

var parent = $("#node2");                                        // parent should be the tr element not the tbody which is in fact a grandparent not a parent

function shuffleChildren(parent) {
  parent.children()                                              // get the children of the parent element
        .sort(function() { return Math.random() - 0.5; })        // sort them randomly (shuffling)
        .appendTo(parent);                                       // add them back to parent so that the shuffling takes effect
}

shuffleChildren(parent);

Пример:

var parent = $("#node2");                                        // parent should be the tr element not the tbody which is in fact a grandparent not a parent

function shuffleChildren(parent) {
  parent.children()                                              // get the children of the parent element
        .sort(function() { return Math.random() - 0.5; })        // sort them randomly (shuffling)
        .appendTo(parent);                                       // add them back to parent so that the shuffling takes effect
}

shuffleChildren(parent);
<script src="https://code.jquery.com/jquery-3.3.1.min.js"></script>
<table>
  <tbody id="parent">
    <tr id="node2" class="shufflerow">
      <td class="shuffledtd shuffledtd1">AA</td>
      <td class="shuffledtd shuffledtd1">BB</td>
      <td class="shuffledtd shuffledtd1">CC</td>
      <td class="shuffledtd shuffledtd1">DD</td>
    </tr>
  </tbody>
</table>

Примечание: Если вы хотите сделать это для всех строк, просто используйте jQuery#each:

$("#parent tr").each(function() {                                // get all tr inside #parent
    shuffleChildren($(this));                                    // shuffle their children
});

Кстати, вы тасуете ячейки, а не строки.

...