2009-10-21 104 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