按自定义排序顺序对jQuery中的Div进行排序

我正在尝试通过将其类别属性与Javascript变量category_sort_order的类别顺序进行比较来重新排序标记input的子元素。 然后我需要删除其category属性没有出现在category_sort_order中的div。

预期结果应该是:

任何
产品1
产品2
下载

代码:

 
download
video1
video2
product1
any
product2
var category_sort_order = ['any', 'product', 'download'];

我真的甚至不知道从哪里开始这项任务,但如果你能提供任何帮助,我将非常感激。

我写了一个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的一个很好的例子。

请注意,

由于有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 } 

这将对具有id =“input”的元素的子元素的所有div进行排序。

这是怎么做的。 我用这个问题作为参考。

我测试了这段代码,它适用于您的示例:

 $(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('
' + content[j] + '
'); } }; } });

这个怎么运作

首先,这段代码需要JQuery库。 如果您目前没有使用它,我强烈推荐它。

代码首先获取包含category属性的输入div的所有子div。 然后它将他们的html内容及其类别保存到两个单独的数组(但在同一位置。

接下来它清除输入div下的所有div。

最后,它按照您在数组中指定的顺序遍历您的类别,并以正确的顺序追加匹配的子div。

For循环部分

@eyelidlessness在解释循环方面做得很好,但我也会对它进行重击。 在此代码的上下文中。

第一行:

 for(i = 0; i < category_sort_order.length; i++) { 

意味着后面的代码(大括号{code}中的所有内容)将重复多次。 虽然格式看起来很古老(而sorta是),但它说:

  1. 创建一个名为i的数字变量,并将其设置为零
  2. 如果该变量小于category_sort_order数组中的项数,则在括号中执行哪些操作
  3. 括号完成后,将一个加到变量i(i ++表示添加一个)
  4. 然后它重复第二步和第三步,直到我最终大于该数组中的类别数。

对于每个类别,括号中的任何内容都将运行一次。

继续...对于每个类别,调用另一个循环。 这个:

 for(j = 0; j < categories.length; j++) { 

循环遍历我们刚刚从屏幕上删除的div的所有类别。

在此循环中,if语句检查屏幕中的任何div是否与当前类别匹配。 如果是这样,它们会附加,如果不是,循环继续搜索,直到它通过每个div。

再次追加(或预先添加)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. 

我认为这是一个非常有趣的问题,这是一个简单但不是令人难以置信的高性能排序解决方案,我想出了。

您可以在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可能不是必需的,但它只是感觉更安全。 你的来电。

您可以通过存储对父级的引用并且每次只获取子级而不是重新运行选择器来清理某些性能。 我的目的是为了简单。 你必须每次都调用选择器,因为顺序会改变排序,而我不会在任何地方存储对父级的引用。

对这个使用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's 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's parent node to "apply" it .appendTo( '#input' ); 

如果您碰巧使用的是没有sort方法的旧版jQuery(1.2),可以使用以下方法添加它:

 jQuery.fn.sort = Array.prototype.sort;