Сортировка списка по алфавиту с модулем
У меня нет никаких проблем с захватом списка элементов и сортировкой их по алфавиту, но я с трудом понимаю, как это сделать с модулем.
### обновление ###
Вот код, работающий "по-моему", однако мне больше нравится повторное использование ответа, представленного ниже, поэтому я принял этот ответ.
<script type="text/javascript">
$(document).ready( function() {
$('.sectionList2').each( function() {
var oldList = $('li a', this),
columns = 4,
newList = [];
for( var start = 0; start < columns; start++){
for( var i = start; i < oldList.length; i += columns){
newList.push('<li><a href="' + oldList[i].href + '">' + $(oldList[i]).text() + '</a></li>');
}
}
$(this).html(newList.join(''));
});
});
</script>
Например. Допустим, у меня есть следующий неупорядоченный список:
<ul>
<li><a href="~">Boots</a></li>
<li><a href="~">Eyewear</a></li>
<li><a href="~">Gloves</a></li>
<li><a href="~">Heated Gear</a></li>
<li><a href="~">Helmet Accessories</a></li>
<li><a href="~">Helmets</a></li>
<li><a href="~">Jackets</a></li>
<li><a href="~">Mechanic's Wear</a></li>
<li><a href="~">Pants</a></li>
<li><a href="~">Protection</a></li>
<li><a href="~">Rainwear</a></li>
<li><a href="~">Random Apparel</a></li>
<li><a href="~">Riding Suits</a></li>
<li><a href="~">Riding Underwear</a></li>
<li><a href="~">Socks</a></li>
<li><a href="~">Vests</a></li>
</ul>
У меня есть этот список, установленный для отображения в 4 столбцах с каждым Li плавающим право. Визуально это затрудняет поиск элементов в больших списках. Вывод, который мне нужен, таков:
<ul>
<li><a href="~">Boots</a></li>
<li><a href="~">Helmet Accessories</a></li>
<li><a href="~">Pants</a></li>
<li><a href="~">Riding Suits</a></li>
<li><a href="~">Eyewear</a></li>
<li><a href="~">Helmets</a></li>
<li><a href="~">Protection</a></li>
<li><a href="~">Riding Underwear</a></li>
<li><a href="~">Gloves</a></li>
<li><a href="~">Jackets</a></li>
<li><a href="~">Rainwear</a></li>
<li><a href="~">Socks</a></li>
<li><a href="~">Heated Gear</a></li>
<li><a href="~">Mechanic's Wear</a></li>
<li><a href="~">Random Apparel</a></li>
<li><a href="~">Vests</a></li>
</ul>
То, что я ищу, - это функция, которая может передать мой массив элементов списка и получить мой массив, отсортированный в алфавитном порядке, с модулем выбора; в данном случае 4.
Любая помощь была бы признательна, поскольку я не могу найти никакой документации по этому вопросу.4 ответа:
Распределите список по алфавиту. В вашем случае это уже сделано, но если нет:
function alphabetizeElements(a, b) { var aText = $(a).text(); var bText = $(b).text(); return aText > bText ? 1 : aText < bText ? -1 : 0; } var alphabetizedList = $("#myList li").sort(alphabetizeElements);
Хранить алфавитный индекс каждого элемента:
$.each(alphabetizedList, function(i) { $(this).data("alphaIndex", i); });
Отсортируйте алфавитный список сначала по модулю, а затем по индексу:
function listColumnSortFn(columns) { return function(a, b) { var aIndex = $(a).data("alphaIndex"); var bIndex = $(b).data("alphaIndex"); return ((aIndex % columns) - (bIndex % columns)) || (aIndex - bIndex); } } var columnSortedList = alphabetizedList.sort(listColumnSortFn(4));
Замените элементы списка отсортированными элементами:
$("#myList li").remove(); $("#myList").append(columnSortedList);
Вот все это вместе взятое:
function sortList(columns) { var alphabetizedList = $("#myList li").sort(alphabetizeElements); $.each(alphabetizedList, function(i) { $(this).data("alphaIndex", i); }); var columnSortedList = alphabetizedList.sort(listColumnSortFn(columns)); $("#myList li").remove(); $("#myList").append(columnSortedList); } function alphabetizeElements(a, b) { var aText = $(a).text(); var bText = $(b).text(); return aText > bText ? 1 : aText < bText ? -1 : 0; } function listColumnSortFn(columns) { return function(a, b) { var aIndex = $(a).data("alphaIndex"); var bIndex = $(b).data("alphaIndex"); return ((aIndex % columns) - (bIndex % columns)) || (aIndex - bIndex); } } $(function() { sortList(4); });
var columnify = function (a,n) { var result = []; for (var i = 0, lastIndex = a.length - 1; i < lastIndex; i++) result.push(a[i * n % (lastIndex)]); result[lastIndex] = a[lastIndex]; return result; } var products = ["Boots", "Eyewear", "Gloves", "Heated Gear", "Helmet Accessories", "Helmets", "Jackets", "Mechanic's Wear", "Pants", "Protection", "Rainwear", "Random Apparel", "Riding Suits", "Riding Underwear", "Socks", "Vests",] columnify(products, 4) ["Boots", "Helmet Accessories", "Pants", "Riding Suits", "Eyewear", "Helmets", "Protection", "Riding Underwear", "Gloves", "Jackets", "Rainwear", "Socks", "Heated Gear", "Mechanic's Wear", "Random Apparel", "Vests"]
Примените эту функцию к уже отсортированному списку, и тогда она вернет список строк в том порядке (почти), который вы хотите. Затем добавьте список, который был возвращен в порядке, к неупорядоченному списку в DOM.
Кроме того, я не проверял его ни с чем, кроме этого списка. Так что на твоем месте я бы так и сделал. Из того, что я вижу, это работает только в том случае, если длина списка кратнаn
. Не то чтобы отличное решение, но для меня уже поздно, и я не могу утруждать себя, чтобы придумать что-нибудь получше.EDIT: Исправлена ошибка с последним элементом
Посмотрим, сработает ли это: http://jsfiddle.net/6xm9m/2
var newList = new Array(); var listItem = $('#list > li'); var mod = 4; var colCount = Math.ceil(listItem.length / mod); listItem.each(function(index) { var newIndex = ((index % colCount) * mod) + Math.floor(index / colCount); // $(this).text(newIndex); newList[newIndex] = this; }); $('#list').empty(); for(var i = 0; i < newList.length; i++){ $('#list').append(newList[i]); }
Нуждается в улучшении, вероятно, но я не совсем уверен, насколько хорошо это работает вообще.
Вот, пожалуйста. Код удивительно прост, как только вы его поймете. Я понимаю, что вы используете jQuery, но я недостаточно знаком с ним, чтобы использовать его функции. Это достаточно просто, что, возможно, это и не нужно.
function pivotArray(arr, columns) { var l = arr.length, out = [], ind = 0, i = 0; for (; i < l; i += 1) { out[ind] = arr[i]; ind += columns; if (ind >= l) { ind = ind % columns + 1; } } return out; }
И вот тест, чтобы доказать, что он работает (протестирован в Firefox 3.6.9, IE 6, Chrome 1.0.154.36):
<html> <head> <style type="text/css"> a.panelnum { display:block; float:left; width:40px; height:40px; border:1px solid black; text-align:center; vertical-align:middle; text-decoration:none; font-size:2em; } </style> </head> <body onload="doit(17, 4);"> <div id="output" style="border:1px solid blue;"> </div> <script type="text/javascript"> function pivotArray(arr, columns) { var l = arr.length, out = [], ind = 0, i = 0; for (; i < l; i += 1) { out[ind] = arr[i]; ind += columns; if (ind >= l) { ind = ind % columns + 1; } } return out; } function doit(size, columns) { document.getElementById('output').innerHTML = 'starting'; var l = size; var inp = []; for (var i = 0; i < l; i += 1) { inp[i] = i; } var result = pivotArray(inp, columns); var str = ''; for (i = 0; i < l; i += 1) { str += '<a class="panelnum">' + result[i] + '</a>'; } var d = document.getElementById('output') d.innerHTML = '<p>Some pre text</p>' + str + '<p style="clear:both;">and some post text</p>'; d.style.width = (columns * d.childNodes[1].offsetWidth + 2) + 'px'; } </script> </body> </html>
Еще одна вещь: может быть полезно просто перемещать элементы на месте. У меня почти был сценарий для этого, но мой сценарий бежал назад (как будто плавает сначала шел сверху вниз). Если у меня будет время, я поработаю над этим и отправлю код.
P.S. Кто-нибудь хочет дать мне указания на то, почему я должен был добавить 2 к вычислению ширины для IE6? Подождите... это ведь границы див, не так ли?