Сортировка разделов в jQuery по пользовательскому порядку сортировки
Я пытаюсь повторно сортировать дочерние элементы тега input
путем сравнения
их атрибут категории к порядку категорий в Javascript
переменная category_sort_order
. Затем мне нужно удалить divs, чей атрибут категории
не отображается в category_sort_order
.
Ожидаемый результат:
любой
product1
product2
скачать
Код:
<div id="input">
<div category="download">download</div>
<div category="video">video1</div>
<div category="video">video2</div>
<div category="product">product1</div>
<div category="any">any</div>
<div category="product">product2</div>
</div>
<script type="text/javascript">
var category_sort_order = ['any', 'product', 'download'];
</script>
Я действительно даже не знаю, с чего начать, но если бы вы могли оказать любую помощь, я бы очень признателен.
Ответы
Ответ 1
Я написал плагин jQuery, чтобы делать такие вещи, которые можно легко адаптировать для вашего использования.
Оригинальный плагин здесь
Здесь вы можете задать вопрос
(function($) {
$.fn.reOrder = function(array) {
return this.each(function() {
if (array) {
for(var i=0; i < array.length; i++)
array[i] = $('div[category="' + array[i] + '"]');
$(this).empty();
for(var i=0; i < array.length; i++)
$(this).append(array[i]);
}
});
}
})(jQuery);
и используйте так:
var category_sort_order = ['any', 'product', 'download'];
$('#input').reOrder(category_sort_order);
Это происходит, чтобы получить правильный заказ для продуктов на этот раз, поскольку product1 появляется перед product2 в исходном списке, но его можно легко изменить, чтобы отсортировать категории сначала, прежде чем вставлять их в массив и добавлять к DOM. Кроме того, если использовать это для нескольких элементов, его можно было бы улучшить, добавив все элементы в массив за один раз, вместо того, чтобы итерации по массиву и добавления по одному. Это, вероятно, было бы хорошим примером для DocumentFragments.
Ответ 2
Просто отметьте,
Так как сортировка jQuery 1.3.2 проста, без какого-либо плагина:
$('#input div').sort(CustomSort).appendTo('#input');
function CustomSort( a ,b ){
//your custom sort function returning -1 or 1
//where a , b are $('#input div') elements
}
Это сортирует все div, которые являются дочерними элементами элемента с id = "input".
Ответ 3
Вот как это сделать. Я использовал этот вопрос SO как ссылку.
Я протестировал этот код, и он работает правильно для вашего примера:
$(document).ready(function() {
var categories = new Array();
var content = new Array();
//Get Divs
$('#input > [category]').each(function(i) {
//Add to local array
categories[i] = $(this).attr('category');
content[i] = $(this).html();
});
$('#input').empty();
//Sort Divs
var category_sort_order = ['any', 'product', 'download'];
for(i = 0; i < category_sort_order.length; i++) {
//Grab all divs in this category and add them back to the form
for(j = 0; j < categories.length; j++) {
if(categories[j] == category_sort_order[i]) {
$('#input').append('<div category="' +
category_sort_order[i] + '">'
+ content[j] + '</div>');
}
};
}
});
Как это работает
Прежде всего, для этого кода требуется библиотека JQuery. Если вы в настоящее время не используете его, я настоятельно рекомендую его.
Код начинается с получения всех дочерних divs входного div, которые содержат атрибут категории. Затем он сохраняет свой html-контент и свою категорию в два отдельных массива (но в том же месте.
Затем он очищает все div под входным div.
Наконец, он проходит через ваши категории в порядке, указанном в массиве, и добавляет соответствующие дочерние div в правильном порядке.
Секция цикла For
@eyelidlessness отлично справляется с пояснениями для циклов, но я также буду бить его. в контексте этого кода.
Первая строка:
for(i = 0; i < category_sort_order.length; i++) {
Означает, что следующий код (все в фигурных скобках {code}) будет повторяться несколько раз. Хотя формат выглядит архаичным (и sorta is), он говорит:
- Создайте цифровую переменную я и установите ее равной нулю
- Если эта переменная меньше количества элементов в массиве category_sort_order, тогда выполните действия в скобках
- Когда скобки закончатся, добавьте один к переменной я (i ++ означает добавить один)
- Затем он повторяет шаги два и три, пока я не станет больше числа категорий в этом массиве.
A.K.A все, что находится в скобках, будет запускаться один раз для каждой категории.
Перемещение... для каждой категории вызывается другой цикл. Это:
for(j = 0; j < categories.length; j++) {
пересекает все категории разделов, которые мы просто удалили с экрана.
В этом цикле оператор if проверяет, соответствует ли какой-либо из div с экрана текущей категории. Если это так, они добавляются, если цикл не продолжается, пока он не пройдет через каждый div.
Ответ 4
Добавление (или добавление) узлов DOM снова будет сортировать их в том порядке, в котором вы хотите.
Используя jQuery, вам просто нужно выбрать их в том порядке, в котором вы хотите, и снова добавить (или добавить их) в свой контейнер.
$(['any', 'product', 'video'])
.map(function(index, category)
{
return $('[category='+category+']');
})
.prependTo('#input');
Простите, что вы хотели удалить узлы, не входящие в список вашей категории. Вот исправленная версия:
// Create a jQuery from our array of category names,
// it won't be usable in the DOM but still some
// jQuery methods can be used
var divs = $(['any', 'product', 'video'])
// Replace each category name in our array by the
// actual DOM nodes selected using the attribute selector
// syntax of jQuery.
.map(function(index, category)
{
// Here we need to do .get() to return an array of DOM nodes
return $('[category='+category+']').get();
});
// Remove everything in #input and replace them by our DOM nodes.
$('#input').empty().append(divs);
// The trick here is that DOM nodes are selected
// in the order we want them in the end.
// So when we append them again to the document,
// they will be appended in the order we want.
Ответ 5
Я думал, что это действительно интересная проблема, вот простое, но не невероятно эффективное решение для сортировки, которое я придумал.
Вы можете просмотреть тестовую страницу на jsbin здесь: http://jsbin.com/ocuta
function compare(x, y, context){
if($.inArray(x, context) > $.inArray(y, context)) return 1;
}
function dom_sort(selector, order_list) {
$items = $(selector);
var dirty = false;
for(var i = 0; i < ($items.length - 1); i++) {
if (compare($items.eq(i).attr('category'), $items.eq(i+1).attr('category'), order_list)) {
dirty = true;
$items.eq(i).before($items.eq(i+1).remove());
}
}
if (dirty) setTimeout(function(){ dom_sort(selector, order_list); }, 0);
};
dom_sort('#input div[category]', category_sort_order);
Обратите внимание, что setTimeout
может не понадобиться, но он чувствует себя безопаснее. Ваш звонок.
Возможно, вы могли бы очистить некоторую производительность, сохранив ссылку на родителя и просто получая потомки каждый раз, вместо повторного запуска селектора. Однако я собирался для простоты. Вы должны каждый раз вызывать селектор, потому что порядок изменяется в сортировке, и я не сохраняю ссылку на родителя где-нибудь.
Ответ 6
Кажется довольно прямым использовать метод sort
для этого:
var category_sort_order = ['any', 'product', 'download'];
// select your categories
$('#input > div')
// filter the selection down to wanted items
.filter(function(){
// get the categories index in the sort order list ("weight")
var w = $.inArray( $(this).attr('category'), category_sort_order );
// in the sort order list?
if ( w > -1 ) {
// this item should be sorted, we'll store it sorting index, and keep it
$( this ).data( 'sortindex', w );
return true;
}
else {
// remove the item from the DOM and the selection
$( this ).remove();
return false;
}
})
// sort the remainder of the items
.sort(function(a, b){
// use the previously defined values to compare who goes first
return $( a ).data( 'sortindex' ) -
$( b ).data( 'sortindex' );
})
// reappend the selection into it parent node to "apply" it
.appendTo( '#input' );
Если вы используете старую версию jQuery (1.2), которая не имеет метода sort
, вы можете добавить ее следующим образом:
jQuery.fn.sort = Array.prototype.sort;