2009-10-21 56 views
14

Tôi đang cố gắng sắp xếp lại các phần tử con của thẻ input bằng cách so sánh thuộc tính danh mục của chúng theo thứ tự danh mục trong Javascript biến category_sort_order. Sau đó, tôi cần xóa các div có thuộc tính danh mục không xuất hiện trong category_sort_order.Sắp xếp số Div trong jQuery theo Thứ tự sắp xếp tùy chỉnh

Kết quả dự kiến ​​nên là:

bất kỳ
Product1
PRODUCT2
tải

Mã:

<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ôi thật sự không còn biết nơi bắt đầu với t nhiệm vụ của mình nhưng nếu bạn có thể vui lòng cung cấp bất kỳ sự trợ giúp nào tôi sẽ vô cùng biết ơn.

Trả lời

17

Tôi đã viết một plugin jQuery để làm điều này có thể dễ dàng điều chỉnh cho trường hợp sử dụng của bạn.

The original plugin is here

Dưới đây là một revamp cho bạn câu hỏi

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

và sử dụng như vậy

var category_sort_order = ['any', 'product', 'download']; 
$('#input').reOrder(category_sort_order); 

Điều này xảy ra để có được thứ tự đúng cho các sản phẩm lần này như Product1 xuất hiện trước PRODUCT2 trong danh sách ban đầu, nhưng nó có thể được thay đổi dễ dàng để sắp xếp các danh mục đầu tiên trước khi đưa vào mảng và thêm vào DOM. Ngoài ra, nếu sử dụng điều này cho một số yếu tố, nó có thể được cải thiện bằng cách nối thêm tất cả các phần tử trong mảng trong một lần thay vì lặp qua mảng và chắp thêm một phần tử tại một thời điểm. Đây có thể là một trường hợp tốt cho DocumentFragments.

+1

Điều này thực sự là thanh lịch Russ. Công việc tốt đẹp. –

9

Đây là cách thực hiện. Tôi đã sử dụng số này SO question làm tham chiếu.

Tôi đã thử nghiệm mã này và nó hoạt động đúng cách ví dụ của bạn:

$(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>'); 
      } 
     }; 
    } 
}); 

Làm thế nào nó hoạt động

Trước hết, mã này đòi hỏi các thư viện JQuery. Nếu bạn hiện không sử dụng nó, tôi khuyên bạn nên sử dụng nó.

Mã bắt đầu bằng cách nhận tất cả các div con của div đầu vào chứa thuộc tính danh mục. Sau đó, nó giúp tiết kiệm nội dung html của họ và loại họ để hai mảng riêng biệt (nhưng trong cùng một vị trí.

Tiếp theo nó gạt bỏ tất cả các divs dưới div input.

Cuối cùng, nó đi qua danh mục của bạn theo thứ tự bạn chỉ định trong mảng và gắn thêm các divs hợp đứa trẻ theo đúng thứ tự.

các đối với phần vòng lặp

@eyelidlessness làm một công việc tốt trong việc giải thích cho các vòng, nhưng tôi cũng sẽ tham gia một Whack tại trong ngữ cảnh của mã này.

Dòng đầu tiên:

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

Nghĩa là mã mà sau (tất cả mọi thứ trong cặp ngoặc nhọn {code}) sẽ được lặp đi lặp lại một số lần.Mặc dù định dạng trông cổ xưa (và sorta là) nó nói:

  1. Tạo một biến số gọi tôi và đặt nó bằng không
  2. Nếu biến đó là ít hơn số lượng các mục trong mảng category_sort_order, sau đó làm những gì trong ngoặc đơn
  3. Khi dấu ngoặc kết thúc, thêm một vào biến i (i ++ có nghĩa là thêm một)
  4. Sau đó nó lặp lại bước hai và ba cho đến khi cuối cùng tôi lớn hơn số hạng mục trong mảng đó.

A.K Mọi thứ trong ngoặc đơn sẽ được chạy một lần cho mọi danh mục.

Di chuyển ... cho mỗi danh mục, một vòng lặp khác được gọi. Điều này:

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

lặp qua tất cả các loại div mà chúng tôi vừa xóa khỏi màn hình.

Trong vòng lặp này, câu lệnh if sẽ kiểm tra xem có bất kỳ div nào từ màn hình khớp với danh mục hiện tại hay không. Nếu vậy, chúng được thêm vào, nếu không phải vòng lặp tiếp tục tìm kiếm cho đến khi nó đi qua mọi div.

+0

Cảm ơn sự giúp đỡ của bạn. Tôi là người mới sử dụng javascript và trong khi tôi hiểu phần đầu tiên của mã, tôi bị bối rối bởi phần thứ hai. Các dòng i = 0 và j = 0 là gì? Tôi thấy những điều này rất nhiều và không thể hiểu được. Cảm ơn bạn lần nữa. – lightyrs

+0

hnovic, đó là các biến lặp. Chúng tương ứng với các phím số của 'mảng 'mà chúng lặp lại. Một vòng lặp 'for' (thường) là câu lệnh đầu tiên của nó là khóa đầu tiên, câu lệnh thứ hai của nó là khóa cuối cùng và câu lệnh cuối cùng của nó là một lệnh chuyển từ khóa ban đầu sang khóa cuối cùng (thường là' i ++ 'hoặc' i-- '). – eyelidlessness

+0

Điều này có lợi ích của việc không thao túng dom nhiều hơn nó có, nhưng nó sử dụng html nội tuyến mà là một chút yucky, đặc biệt là khi mọi thứ bắt đầu thay đổi. –

1

Tôi nghĩ rằng đây là một vấn đề thực sự thú vị, đây là một giải pháp phân loại dễ dàng, nhưng không thực sự đáng kinh ngạc mà tôi đã đưa ra.

Bạn có thể xem các trang thử nghiệm trên jsbin đây: 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); 

Lưu ý rằng setTimeout có thể không cần thiết, nhưng nó chỉ cảm thấy an toàn hơn. Cuộc gọi của bạn.

Bạn có thể làm sạch một số hiệu suất bằng cách lưu trữ tham chiếu đến phụ huynh và chỉ nhận con mỗi lần thay vì chạy lại bộ chọn. Tôi đã đi cho đơn giản mặc dù. Bạn phải gọi bộ chọn mỗi lần, bởi vì thứ tự thay đổi trong một sắp xếp, và tôi không lưu trữ một tham chiếu đến phụ huynh ở bất cứ đâu.

+0

Điều này cũng sẽ đặt các danh mục không được tìm thấy trong mảng sắp xếp thứ tự ở phía trước danh sách. Thay vào đó, nếu bạn muốn chúng ở cuối, hãy kiểm tra -1 trên hàm $ .inArray. –

5

Việc thêm (hoặc thêm) các nút DOM một lần nữa sẽ thực sự sắp xếp chúng theo thứ tự bạn muốn.

Sử dụng jQuery, bạn chỉ cần chọn chúng theo thứ tự bạn muốn và nối thêm (hoặc thêm lại) chúng vào vùng chứa của chúng một lần nữa.

$(['any', 'product', 'video']) 
    .map(function(index, category) 
    { 
     return $('[category='+category+']'); 
    }) 
    .prependTo('#input'); 

Xin lỗi, nhỡ mà bạn muốn loại bỏ các nút không có trong danh sách mục của bạn. Đây là phiên bản đã sửa:

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

Cảm ơn sự giúp đỡ của bạn. Cái này hoạt động ra sao!? Bạn có thể giải thích dùm không. Cảm ơn bạn lần nữa – lightyrs

+0

sử dụng tốt nhất bản đồ() '. Mục cuối cùng trong mảng phải là 'download' mặc dù :) –

+0

Tôi thích nó. Đó là một giải pháp rất thanh lịch. – Borgar

0

Đó là dường như khá trực tiếp để sử dụng phương pháp sort cho một này:

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

Nếu bạn tình cờ được sử dụng một phiên bản cũ của jQuery (1.2) mà không có phương pháp sort, bạn có thể thêm nó với điều này:

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

Chỉ cần lưu ý,

Vì không jQuery 1.3.2 sắp xếp rất đơn giản mà không cần bất kỳ plugin như:

$('#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 
} 

Điều này sẽ sắp xếp tất cả div là phần tử con của phần tử có id = "input".

+0

giải pháp này hoạt động hoàn toàn tốt – lamarant

Các vấn đề liên quan