2009-10-21 66 views
14

我试图通过Javascript代码 变量category_sort_order比较 其类别属性的类别顺序标签input的子元素进行重新排序。然后,我需要删除 未在category_sort_order中出现的div类别。排序的div jQuery中通过自定义排序次序

预期的结果应该是:

任何
产品1
产品2
下载

代码:

<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> 

我真的不知道哪里以t开头他的任务,但如果你可以请提供任何援助,我会非常感激。

回答

17

我写了一个jQuery插件来做这种事情,可以很容易地适应您的使用情况。

The original plugin is here

这里有一个改造为你质疑

(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); 

出现这种情况,以获得正确的顺序为产品这次作为产品1产品之前出现在原始列表中,但可以在将数组放入数组并添加到DOM之前轻松更改以对类别进行排序。另外,如果将它用于多个元素,可以通过一次追加数组中的所有元素来改进它,而不是遍历数组并一次追加一个元素。这可能是DocumentFragments的一个好例子。

+1

这真是优雅的拉斯。工作很好。 – 2009-10-21 22:39:53

9

这是怎么做到的。我用这个SO question作为参考。

我测试此代码,它工作正常您例如:

$(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库。如果你目前没有使用它,我强烈推荐它。

代码首先获取包含category属性的输入div的所有子div。然后,它节省了他们的HTML内容和他们的类别到两个独立的阵列(但在相同的位置。

接下来,它会清除掉所有的div输入DIV下。

最后,经过您的类别顺序您在阵列中指定并追加匹配孩子的div以正确的顺序。

For循环部分

@eyelidlessness做了解释for循环的一个很好的工作,但我也将采取重击在它在这个代码的背景下,

第一行:

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

意味着,如下(大括号内的一切{代码})的代码将被重复许多次。虽然格式看起来过时的(和八九不离十是)它说:

  1. 创建一个名为许多变量i并将其设置等于零
  2. 如果变量小于项目的category_sort_order数组中的号码,然后在括号中做什么
  3. 当方括号结束时,向变量i添加一个(i ++意味着添加一个)
  4. 然后重复第二步和第三步,直到我终于大于该数组中的类别数。

A.K.A无论在括号内,每个类别都会运行一次。

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

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

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

在此循环中,if语句检查屏幕上是否有任何div与当前类别匹配。如果是这样,他们正在追加,如果没有循环继续搜索,直到它通过每一个div。

+0

谢谢你的帮助。 我是一个JavaScript新手,虽然我理解你的代码的第一部分,但我对第二部分感到困惑。什么是i = 0和j = 0行?我看到这些很多并且无法理解。 再次感谢。 – lightyrs 2009-10-21 22:07:22

+0

hnovic,那些是迭代器变量。它们对应于它们迭代的“数组”的数字键。一个'for'循环(通常)将第一个语句作为初始键,第二个语句作为最后一个键,最后一个语句是从初始键移动到最终键的指令(通常是'i ++'或'i-- ')。 – eyelidlessness 2009-10-21 22:13:56

+0

这样做的好处在于不会更多地操纵dom,但它确实使用内联html,这有点不可取,特别是当事情开始发生变化时。 – 2009-10-21 22:20:04

1

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

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

您可能可以通过存储对父级的引用并每次只让孩子进行清理,而不是重新运行选择器。尽管我尽量简单。您必须每次调用选择器,因为顺序会发生变化,而且我不会在任何地方存储对父代的引用。

+0

这也会将未在排序顺序数组中找到的类别放在列表的前面。如果你想在最后使用它们,请在$ .inArray函数中检查-1。 – 2009-10-21 22:07:34

5

再次附加(或预先)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. 
+0

谢谢你的帮助。这个怎么用!?你能解释一下吗? 再次感谢 – lightyrs 2009-10-21 22:35:51

+0

不错的使用'map()'。数组中的最后一项应该是'download' :) – 2009-10-21 22:52:57

+0

我喜欢它。这是一个非常优雅的解决方案。 – Borgar 2009-10-21 22:56:04

0

它似乎相当直接用于这一个sort方法:如果你碰巧使用的是旧版本的jQuery(1.2)的

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.fn.sort = Array.prototype.sort; 
15

只要注意,

由于存在的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 =“输入”的孩子。

+0

这个解决方案工作得很好 – lamarant 2013-02-12 16:24:54