JavaScript/jQuery сортировка элементов DOM
Доброй ночи, коллеги,
столкнулся с задачей сортировки группы элементов DOM для отображения в две или три колонки в зависимости от ширины окна браузера пользователя. В проекте используется Bootstrap. Вот такой простенький HTML отобразит данные в две или три колонки в зависимости от ширины окна браузера (у всех вложенных div-ов есть CSS свойство {float: left}). <div id="list"> <div data-count="7" class="col-xs-6 col-lg-4">07</div> <div data-count="8" class="col-xs-6 col-lg-4">08</div> <div data-count="9" class="col-xs-6 col-lg-4">09</div> <div data-count="10" class="col-xs-6 col-lg-4">10</div> <div data-count="11" class="col-xs-6 col-lg-4">11</div> <div data-count="12" class="col-xs-6 col-lg-4">12</div> <div data-count="1" class="col-xs-6 col-lg-4">01</div> <div data-count="2" class="col-xs-6 col-lg-4">02</div> <div data-count="3" class="col-xs-6 col-lg-4">03</div> <div data-count="4" class="col-xs-6 col-lg-4">04</div> <div data-count="5" class="col-xs-6 col-lg-4">05</div> <div data-count="6" class="col-xs-6 col-lg-4">06</div> <div data-count="13" class="col-xs-6 col-lg-4">13</div> </div> Задача отсортировать элементы так, чтобы "на выходе" вывод в три колонки выглядел так 1 6 11 2 7 12 3 8 13 4 9 5 10 Ну, и в две соответственно так 1 8 2 9 3 10 4 11 5 12 6 13 7 Задача для меня оказалась непосильной, прошу помощи у гуру. Пока что у меня получилось следующее: function sortList() { var data = $("#list > div"); // Сначала сортируем элементы по порядку // по аттрибуту 'data-count' data.sort(function (a, b) { a = parseInt($(a).attr('data-count'), 10); b = parseInt($(b).attr('data-count'), 10); if(a > b) { return 1; } else if(a < b) { return -1; } else { return 0; } }); var result = {}; var cols = 3; // К-во колонок var rows = Math.ceil($(data).size()/cols); var prev; var i = 0; for(var row = 1; row <= rows; row++) { for(var col = 1; col <= cols; col++) { var index = (col == 1) ? row : row + (rows * (col - 1)); index--; if(index in data) { result[i] = data[index]; i++; } else { // Здесь нужно как-то добавить пустой // элемент <div class="col-xs-6 col-lg-4"></div> // но как ????????? // $(result[i-1]).after('<div class="col-xs-6 col-lg-4">-</div>'); НЕ РАБОТАЕТ } } } $('#list').html(result); } Не знаю, насколько данный код оптимален, но он работает, за исключением того, что я не придумал как добавить новый элемент пустышку |
РНР знаете? Есть в нем функция разбивающая массив на части array_chunk(), правда вывод будет не так как у вас, а
1 2 3 4 5 6 7 8 Если пойдет, то js-аналог ее здесь найдете. |
|
onotole,
<!DOCTYPE HTML> <html> <head> <title>Untitled</title> <meta charset="utf-8"> <style type="text/css"> #list{ width:300px; display:flex; flex-flow:column wrap; height:300px; } #list>div{ -webkit-animation:spin 5s ease-in-out infinite 2s; animation:spin 5s ease-in-out infinite 2s; width:33%; height:19%; border:1px #FF0033 solid; text-align:center; line-height:2em; } @keyframes spin{ 50%{ width:50%; height:12%; } 100%{ width:33%; height:19%; } } @-webkit-keyframes spin{ 50%{ width:50%; height:12%; } 100%{ width:33%; height:19%; } } </style> <script src="http://ajax.googleapis.com/ajax/libs/jquery/1.11.0/jquery.min.js"></script> <script> $(function() { var elems = document.querySelectorAll("#list > div"); var arr = $.makeArray(elems); arr.sort(function(a, b) { return $(a).data("count") - $(b).data("count") }); $(arr).appendTo("#list"); }); </script> </head> <body> <div id="list"> <div data-count="7" class="col-xs-6 col-lg-4">07</div> <div data-count="8" class="col-xs-6 col-lg-4">08</div> <div data-count="9" class="col-xs-6 col-lg-4">09</div> <div data-count="10" class="col-xs-6 col-lg-4">10</div> <div data-count="11" class="col-xs-6 col-lg-4">11</div> <div data-count="12" class="col-xs-6 col-lg-4">12</div> <div data-count="1" class="col-xs-6 col-lg-4">01</div> <div data-count="2" class="col-xs-6 col-lg-4">02</div> <div data-count="3" class="col-xs-6 col-lg-4">03</div> <div data-count="4" class="col-xs-6 col-lg-4">04</div> <div data-count="5" class="col-xs-6 col-lg-4">05</div> <div data-count="6" class="col-xs-6 col-lg-4">06</div> <div data-count="13" class="col-xs-6 col-lg-4">13</div> </div> </body> </html> |
Цитата:
рони, прорисовка в моем скрипте итак уже реализована, проблема в том, что если количество элементов не кратно количеству столбцов, а, точнее, если один элемент "лишний", то нужно вставлять элемент-пустышку, а я не разобрался как... Что касается предложенного примера, то, к сожалению, длина списка заранее неизвестна, и может значительно отличаться, поэтому, я не могу указать высоту для #list, а без таковой Ваш пример не работает. |
onotole,
ваше css? |
onotole,
<!DOCTYPE HTML> <html> <head> <title>Untitled</title> <meta charset="utf-8"> <style type="text/css"> #list{ width:300px; } #list>div{ float: left; width:32%; height:50px; border:1px #FF0033 solid; text-align:center; line-height:2em; } </style> <script src="http://ajax.googleapis.com/ajax/libs/jquery/1.11.0/jquery.min.js"></script> <script> $(function() { var elems = document.querySelectorAll("#list > div"); var arr = $.makeArray(elems); arr.sort(function(a, b) { return $(a).data("count") - $(b).data("count") }); function printNumbers(arr, cols) { var fragment = document.createDocumentFragment(); var cNum = arr.length; var step = Math.ceil(cNum / cols); for (var i = 0; i < step; i++) { fragment.appendChild(arr[i]); for (var k = 1; k < cols; k++) { var n = i + step * k; if (n < cNum) fragment.appendChild(arr[n]); else fragment.appendChild(document.createElement('div')) } } return fragment } $(printNumbers(arr, 3)).appendTo("#list"); }); </script> </head> <body> <div id="list"> <div data-count="7" class="col-xs-6 col-lg-4">07</div> <div data-count="8" class="col-xs-6 col-lg-4">08</div> <div data-count="9" class="col-xs-6 col-lg-4">09</div> <div data-count="10" class="col-xs-6 col-lg-4">10</div> <div data-count="11" class="col-xs-6 col-lg-4">11</div> <div data-count="12" class="col-xs-6 col-lg-4">12</div> <div data-count="1" class="col-xs-6 col-lg-4">01</div> <div data-count="2" class="col-xs-6 col-lg-4">02</div> <div data-count="3" class="col-xs-6 col-lg-4">03</div> <div data-count="4" class="col-xs-6 col-lg-4">04</div> <div data-count="5" class="col-xs-6 col-lg-4">05</div> <div data-count="6" class="col-xs-6 col-lg-4">06</div> <div data-count="13" class="col-xs-6 col-lg-4">13</div> </div> </body> </html> |
рони,
Благодарю, отличный пример, если других вариантов не останется, постараюсь задействовать его, вообще, же, полностью эмулируя среду bootstrap, сортировка поломалась <!DOCTYPE HTML> <html> <head> <title>Untitled</title> <meta charset="utf-8"> <link href="http://maxcdn.bootstrapcdn.com/bootstrap/3.3.2/css/bootstrap.min.css" rel="stylesheet"> <style type="text/css"> #list{ width:100%; } #list>div{ height:50px; border:1px #FF0033 solid; text-align:center; line-height:2em; } </style> <script src="http://ajax.googleapis.com/ajax/libs/jquery/1.11.0/jquery.min.js"></script> <script> $(function() { var elems = document.querySelectorAll("#list > div"); var arr = $.makeArray(elems); arr.sort(function(a, b) { return $(a).data("count") - $(b).data("count") }); function printNumbers(arr, cols) { var fragment = document.createDocumentFragment(); var cNum = arr.length; var step = Math.ceil(cNum / cols); for (var i = 0; i < step; i++) { fragment.appendChild(arr[i]); for (var k = 1; k < cols; k++) { var n = i + step * k; if (n < cNum) fragment.appendChild(arr[n]); else fragment.appendChild(document.createElement('div')) } } return fragment } $(printNumbers(arr, 3)).appendTo("#list"); }); </script> </head> <body> <div class="container"> <div id="list"> <div data-count="7" class="col-xs-6 col-lg-4">07</div> <div data-count="8" class="col-xs-6 col-lg-4">08</div> <div data-count="9" class="col-xs-6 col-lg-4">09</div> <div data-count="10" class="col-xs-6 col-lg-4">10</div> <div data-count="11" class="col-xs-6 col-lg-4">11</div> <div data-count="12" class="col-xs-6 col-lg-4">12</div> <div data-count="1" class="col-xs-6 col-lg-4">01</div> <div data-count="2" class="col-xs-6 col-lg-4">02</div> <div data-count="3" class="col-xs-6 col-lg-4">03</div> <div data-count="4" class="col-xs-6 col-lg-4">04</div> <div data-count="5" class="col-xs-6 col-lg-4">05</div> <div data-count="6" class="col-xs-6 col-lg-4">06</div> <div data-count="13" class="col-xs-6 col-lg-4">13</div> </div> </div> </body> </html> |
рони, немного переделал функцию, чтобы создаваемым пустышкам присваивались классы, и все заработало, ОГРОМНОЕ СПАСИБО!
function printNumbers(arr, cols) { var fragment = document.createDocumentFragment(); var cNum = arr.length; var step = Math.ceil(cNum / cols); for (var i = 0; i < step; i++) { fragment.appendChild(arr[i]); for (var k = 1; k < cols; k++) { var n = i + step * k; if (n < cNum) fragment.appendChild(arr[n]); else { var div = document.createElement('div'); div.className = "col-xs-6 col-lg-4"; fragment.appendChild(div); // fragment.appendChild(document.createElement('div')) } } } return fragment } |
Цитата:
смотреть пост 1 строку 50 |
onotole,
превосходно именно так :victory: |
Еще немного допилил, при каждом новом пересорте надо убирать пустышки, созданные при прошлой сортировке, иначе, сортировка ломается
|
onotole,
:) ещё можно количество колонок вычислять |
Цитата:
|
Часовой пояс GMT +3, время: 18:07. |