Можно ли сделать этот вид более элегантным / рекурсивным - PullRequest
1 голос
/ 05 октября 2010

У меня есть таблица, которую нужно отсортировать по нескольким столбцам - скажем, музыка, которая отсортирована по жанру, затем по исполнителю, альбому и т. Или вы можете отсортировать по исполнителю / альбому / треку. Вот что я придумал в jquery:

function tableSort (by) {                                                                             
    var mylist = $('#mainList');                                                                      
    var listitems = $('.row').get();                                                                                                                                               
    listitems.sort(function(a, b) {                                                                   
        var cidA=$(a).attr('id');                                                       
        var cidB=$(b).attr('id');                                                       
        var i=[1,2,4,3];                                                                              
        var compA=[];                                                                                 
        var compB=[];                                                                                 
        compA[0]=$(a).find('.album').html();                                     
        compB[0]=$(b).find('.album').html();;                                    
        compA[1]=$(a).find('.artist').html();             
        compB[1]=$(b).find('.artist').html();             
        compA[2]=$(a).find('.genre').html();                                                             
        compB[2]=$(b).find('.genre').html();                                                             
        compA[3]=$(a).find('.track').val();                                                          
        compB[3]=$(b).find('.track').val();                                                          
        switch (by) {                                                                                 
            case 'genre->artist->album':
                i=[2,0,1,3];                                                                          
                break;                                                                                
            case 'genre->album->artist':                                                                             
                i=[2,1,0,3];                                                                          
                break;                                                                                
            default:                                                                                  
                compA='';                                                                             
                compB='';                                                                             
        }                                                                                             
        var comp=(compA[i[0]] < compB[i[0]]) ? -1 : (compA[i[0]] > compB[i[0]]) ? 1 : 0;              
        if (comp==0) comp=(compA[i[1]] < compB[i[1]]) ? -1 : (compA[i[1]] > compB[i[1]]) ? 1 : 0;     
        if (comp==0) comp=(compA[i[2]] < compB[i[2]]) ? -1 : (compA[i[2]] > compB[i[2]]) ? 1 : 0;     
        if (comp==0) comp=(compA[i[3]] < compB[i[3]]) ? -1 : (compA[i[3]] > compB[i[3]]) ? 1 : 0;     
        return comp;                                                                                  
    });                                                                                               

$.each(listitems, function(i, v) {                                                                    
    var id=$(v).attr('id').split('_')[1];                                                             
    mylist.append(v);                                                                                 
    });                                                                                               
}

Это работает для меня с 3-4 заказами, но должен быть более элегантный и масштабируемый способ!

Ответы [ 6 ]

2 голосов
/ 05 октября 2010

Не проверено, но должно работать:

listitems.sort(function(a, b) { 
    var $a=$(a),$b=$(b),
        i=[1,2,4,3],  
        compA=[],   
        compB=[],
        cols=['album', 'artist', 'genre', 'track'];
    for(var c=0; c<cols.length; c++)
    {
        var fn=cols[c]==="track" ? "val" : "html";
        compA.push($a.find("."+cols[c])[fn]());
        compB.push($b.find("."+cols[c])[fn]());
    }
    switch (by) { 
        case 'genre->artist->album':
            i=[2,0,1,3];
            break;
        case 'genre->album->artist':
            i=[2,1,0,3];
            break;
        /*default: 
            compA='';   //WHY???
            compB='';*/
    }
    for(c=0; c<i.length; c++)
    {
        if(compA[i[c]]<compB[i[c]]) return -1;
        else if(compA[i[c]]>compB[i[c]]) return 1;
    }
    return 0;
});
1 голос
/ 05 октября 2010

У mck89 отличный ответ, но я исправил числовую сортировку и попытался очистить все это немного больше ( демо ):

HTML

<table>
 <tr><td colspan=2>Sort:</td></tr>
 <tr><td>Direction:</td><td><select class="dir"><option value="asc">Ascending</option><option value="desc">Descending</option></select></td></tr>
 <tr><td>Order:</td><td><ul class="order"><li>Album <span>-&gt;</span></li><li>Artist <span>-&gt;</span></li><li>Genre <span>-&gt;</span></li><li>Track <span style="display:none">-&gt;</span></li></ul></td></tr>
 <tr><td colspan=2><button>Sort</button></td></tr>
</table>
<br>
<table id="mainList">
 <thead>
  <tr><th>Album</th><th>Artist</th><th>Genre</th><th>Track</th></tr>
 </thead>
 <tbody>
  <tr><td>...</td><td>...</td><td>...</td><td>#</td></tr>
  ...
 </tbody>
</table>

Скрипт

$(document).ready(function(){
 $('.order').sortable({
  update: function(e,ui){
   $('.order span').show().filter(':last').hide(); // hide last arrow
  }
 });

 $(':button').click(function(){
  var table = ['Album', 'Artist', 'Genre', 'Track'],
   order = [];
  $('.order li').each(function(){
   order.push( $.inArray( $(this).text().replace(' ->',''), table ) );
  });
  tableSort(order, $('.dir').val());
 })
})

 function tableSort(by,dir){
  var mylist = $('#mainList'),
   listitems = mylist.find('tbody tr').get();

  listitems.sort(function(a, b) {
   var $a = $(a),
    $b = $(b),
    i = by,
    compA = [],
    compB = [],
    c;

   for(c=0; c<3; c++){
    compA.push($a.find('td').eq(c).html()); // Alphabetical
    compB.push($b.find('td').eq(c).html());
   }
    compA.push(('0' + $a.find('td:last').html()).slice(-2)); // Numerical (2 digit numbers)
    compB.push(('0' + $b.find('td:last').html()).slice(-2)); // use '00' + ....slice(-3) for 3 digit numbers, etc...

   for(c=0; c<i.length; c++){
    return (dir == 'asc') ?
     ((compA[i[c]] < compB[i[c]]) ? -1 : (compA[i[c]] > compB[i[c]]) ? 1 : 0) : // ascending sort
     ((compA[i[c]] > compB[i[c]]) ? -1 : (compA[i[c]] < compB[i[c]]) ? 1 : 0)   // descending sort
   }
  });

  $.each(listitems, function(i, v) {
   mylist.append(v);
  });
 }
1 голос
/ 05 октября 2010

Я бы порекомендовал использовать плагин для чего-то подобного.

Быстрый поиск в Google показывает TableSorter , который, я считаю, делает все, что вы искали.Минимизированная версия тоже всего 12 КБ, поэтому ее не так сложно загрузить на сайт.

1 голос
/ 05 октября 2010

Если вы не против использования плагина, попробуйте tableorter или легкий tinytable

0 голосов
/ 06 октября 2010

Мой javascript / jQuery не очень хорош, но общая техника, которая может быть полезна здесь, - это создание составного ключа сортировки из выбранных столбцов с последующей сортировкой по нему.

Для этого вы определяете максимально возможную длину каждого столбца, дополняете значение в каждом столбце сортировки до максимального значения, а затем объединяете значения в столбцах сортировки, чтобы получить один составной ключ сортировки.

Например, если порядок сортировки - жанр / альбом / исполнитель, а максимальная длина этих полей равна 20/100/100, то для каждой строки составной ключ сортировки равен

pad(genre, 20) + pad(album, 100) + pad(artist, 100)

где pad - это функция, которая дополняет заданный текст до заданной длины пробелами.

Для заданного набора столбцов сортировки вы можете определить функцию, которая принимает строку в качестве входных данных и возвращает составной ключ сортировки. Затем просто отсортируйте эти (одиночные) значения. Заполнение и объединение гарантируют, что ключ сортировки каждой строки имеет одинаковую длину, и что естественная сортировка строк даст желаемый порядок.

0 голосов
/ 05 октября 2010

Я рекомендую плагин для обработки сортировки и разгрузки потенциальных ошибок сообществу. jqGrid приходит на ум, но я не думаю, что у вас будут проблемы с слишком малым выбором:)

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...