2012-10-15 12 views
5

następstwie tego postu (link github: https://github.com/padolsey/jQuery-Plugins/blob/master/sortElements/jquery.sortElements.js) jQuery table sort, ja z powodzeniem sortować kolumny, jednak to nie działa w przypadku rowspan: Na przykład przypadek jak tenjQuery sortColumns: Jak sortować poprawnie rowspan

Grape  3,096,671M 
      1,642,721M 
Apple  2,602,750M 
      3,122,020M 

Kiedy klikam na drugiej kolumnie, to starają się uporządkować

Apple  2,602,750M 
      1,642,721M 
Grape  3,096,671M 
      3,122,020M 

(oczekiwany wynik powinien być, że powinien tylko porządek w obrębie każdej rowspan

Grape  1,642,721M 
      3,096,671M 
Apple  2,602,750M 
      3,122,020M 

lub

Grape  3,096,671M 
      1,642,721M 
Apple  3,122,020M 
      2,602,750M 

)

więc albo które jak widać nie jest poprawny, proszę każdy guru jQuery pomóc mi rozwiązać ten problem. Oto mój kod

var inverse = false; 
function sortColumn(index){ 
    index = index + 1; 
    var table = jQuery('#resultsTable'); 
    table.find('td').filter(function(){ 
     return jQuery(this).index() == index; 
    }).sortElements(function(a, b){ 
     a = convertToNum($(a).text()); 
     b = convertToNum($(b).text()); 

     return (
      isNaN(a) || isNaN(b) ? 
      a > b : +a > +b 
      ) ? 
     inverse ? -1 : 1 : 
     inverse ? 1 : -1; 
    },function(){ 
     return this.parentNode; 
    }); 
    inverse = !inverse; 
} 
function convertToNum(str){ 
    if(isNaN(str)){ 
     var holder = ""; 
     for(i=0; i<str.length; i++){         
      if(!isNaN(str.charAt(i))){ 
       holder += str.charAt(i); 
      } 
     } 
     return holder; 
    }else{ 
     return str; 
    } 
} 

Pytanie:

1.How mogę rozwiązać ten z rowspan. LICZBA ROWSPAN NIE ZAWSZE JEST TA SAMEGO. Powyższy przykład zarówno Grape, jak i Apple mają rozpiętość rzędu 2, ale nie zawsze tak jest.

2.Can każdy wyjaśnić tę składnię:

return (
      isNaN(a) || isNaN(b) ? 
      a > b : +a > +b 
      ) ? 
     inverse ? -1 : 1 : 
     inverse ? 1 : -1; 

Więc widzę, że jeśli A lub B nie jest liczbą, a następnie zrobić porównanie ciąg inaczej zrobić porównanie liczb, ale nie rozumieją

inverse ? -1 : 1 : 
inverse ? 1 : -1; 

przypadki testowe

<table id="resultsTable"> 
     <thead> 
      <tr> 
       <th>Fruit</th> 
       <th onclick="sortColumn(1)">Quantity</th> 
       <th onclick="sortColumn(2)">Rate</th> 
      </tr> 
     </thead> 
     <tbody> 
      <tr> 
       <td rowspan="4">Grape</td> 
       <td>15</td> 
       <td>5</td> 
      </tr> 
      <tr> 
       <td>4</td> 
       <td>2</td> 
      </tr> 
      <tr> 
       <td>88</td> 
       <td>1</td> 
      </tr> 
      <tr>      
       <td>11</td> 
       <td>3</td> 
      </tr> 
      <tr> 
       <td rowspan="3">Melon</td> 
       <td>21</td> 
       <td>2</td> 
      </tr> 
      <tr> 
       <td>2</td> 
       <td>0</td> 
      </tr> 
      <tr> 
       <td>35</td> 
       <td>1</td> 
      </tr> 
      <tr> 
       <td rowspan="6">Melon</td> 
       <td>24</td> 
       <td>5</td> 
      </tr> 
      <tr> 
       <td>66</td> 
       <td>2</td> 
      </tr> 
      <tr> 
       <td>100</td> 
       <td>4</td> 
      </tr> 
      <tr> 
       <td>21</td> 
       <td>1</td> 
      </tr> 
      <tr> 
       <td>65</td> 
       <td>3</td> 
      </tr> 
      <tr> 
       <td>2</td> 
       <td>0</td> 
      </tr> 
     </tbody> 
<table> 
+0

Jaki jest oczekiwany wynik? –

+0

@ Newbo.O: Powinien sortować tylko w obrębie poszczególnych zakresów. Zaktualizowałem moje pytanie z oczekiwanym wynikiem. –

+0

Sortować tylko w obrębie podziału na wiersze lub: ** sortować każdą grupę podziału wierszy, a następnie sortować grupy według pierwszej wartości **? –

Odpowiedz

3

Warunki kodu do pracy:

  • Kolumny zawierające td S z rowspan wszystko musi być po lewej stronie stołu
  • Wszystkie td s w tych kolumnach must mają rowspan , nawet jeśli jest to 1
  • Grupy rzędów do posortowania są wykonane z prawej strony tych kolumn (ale można je łatwo zmienić)

jsFiddle:http://jsfiddle.net/5GrAC/77/

var inverse = false; 

function sortColumn(index) { 
    var trs = $('#resultsTable > tbody > tr'), 
     nbRowspans = trs.first().children('[rowspan]').length, 
     offset = trs.first().children('[rowspan]').last().offset().left; 

    var tds = trs.children('[rowspan]').each(function() { 
     $(this).data('row', $(this).parent().index()); 
     $(this).data('column', $(this).index()); 
     $(this).data('offset', $(this).offset().left) 
    }).each(function() { 
     if($(this).data('offset') != offset) 
      return; 

     var rowMin = $(this).data('row'), 
      rowMax = rowMin + parseInt($(this).attr('rowspan')); 

     trs.slice(rowMin, rowMax).children().filter(function() { 
      return $(this).index() == index + $(this).parent().children('[rowspan]').length - nbRowspans; 
     }).sortElements(function(a, b) { 
      a = convertToNum($(a).text()); 
      b = convertToNum($(b).text()); 

      return (
       isNaN(a) || isNaN(b) ? 
       a > b : +a > +b 
       ) ? 
      inverse ? -1 : 1 : 
      inverse ? 1 : -1; 
     }, function() { 
      return this.parentNode; 
     }); 
    }); 

    var trs = $('#resultsTable > tbody > tr'); 
    tds.each(function() { 
     if($(this).parent().index() != $(this).data('row')) 
      $(this).insertBefore(trs.eq($(this).data('row')).children().eq($(this).data('column'))); 
    }); 

    inverse = !inverse; 
} 

Szybkie wyjaśnienia:

  • znalezienie wszystkich td S z rowspan
  • Pozycje tych td s są zapisane, włączając lewy przesunięcie
  • Te td s filtrowane są przez ich pierwotnego offset pracować tylko ze skrajnie prawych te
  • tr s podobne do siebie prowadzonego td są klasyfikowane za pomocą kolumny poszukiwanych
  • Wszystkie td sz rowspan wreszcie wrócił do ich pierwotnego stanowisko razie potrzeby

o pytaniu 2, ja odpowiem tylko kompletne bartlaarhoven poprzez mówiąc, kod może również być napisane jak t on następujący:

return (
     (isNaN(a) || isNaN(b) ? a > b : +a > +b) ? 1 : -1 
    ) * (inverse ? -1 : 1); 

można łatwo odczytać, że inverse służy do odwrotny rezultat.

+0

Więc srry, ponieważ sposób w jaki przechodzę w indeksie, potrzebuję "index = index + 1", jednak w twoim przypadku proszę go wyjąć. Ponadto użyłem twojego kodu, ale stół jest zepsuty, postawiłem stół, którego używam do testowania w moim pytaniu, czy możesz go obejrzeć. Dziękuję bardzo. Ja też to badam.Dziękuję –

+0

Mój błąd, czasami przenosiłem 'td' do' thead' ... Zaktualizowałem swoją odpowiedź, aby to naprawić. Stworzyłem też jsfiddle z próbką danych (nie wstawiłem żadnego CSS, więc jest trochę brzydki, ale działa) –

+0

Dziękuję, jesteś niesamowity, jeszcze jedna rzecz. Blok mmiddle (środkowy blok 'Melon'), jego sortowanie jest odwrotne dla wszystkich pozostałych. Czy mógłbyś na to spojrzeć, proszę. Bardzo dziękuję: D –

2

Zważywszy na pytanie nr 1, spróbuj ten kod:

var inverse = false; 
var curRowSpan = 0; 
var curIndex = 0; 
var doRowSpan = false; 
function sortColumn(index){ 
    index = index + 1; 
    var table = jQuery('#resultsTable'); 
    table.find('td').filter(function() { 
     var result = false; 
     // if it is a column before the sorting column, watch the rowSpan 
     if (curRowSpan == 0 && jQuery(this).index() < index && jQuery(this).attr("rowspan") > 1) { 
      curRowSpan = jQuery(this).attr("rowspan"); 
      doRowSpan = true; 
      // we are not in the sorting column so we can safely continue 
      continue; 
     } 

     if(!doRowSpan) curIndex = index - (curRowSpan?1:0); 
     else curIndex = index; 

     if(jQuery(this).index() == curIndex) { 
      // we are at the sorting column 
      if(curRowSpan > 0) { 
       curRowSpan--; 
      } 
      // set this to false for the following row 
      doRowSpan = false; 
      result = true; 
     } 

     return result; 
    }).sortElements(function(a, b){ 
     a = convertToNum($(a).text()); 
     b = convertToNum($(b).text()); 

     return (
      isNaN(a) || isNaN(b) ? 
      a > b : +a > +b 
     ) ? 
      inverse ? -1 : 1 : 
      inverse ? 1 : -1; 
     },function(){ 
      return this.parentNode; 
     }); 
     inverse = !inverse; 
    } 
    function convertToNum(str){ 
     if(isNaN(str)){ 
      var holder = ""; 
      for(i=0; i<str.length; i++){         
       if(!isNaN(str.charAt(i))){ 
        holder += str.charAt(i); 
       } 
      } 
      return holder; 
     }else{ 
      return str; 
     } 
    } 

Rozważając pytanie 2; odejmijmy, skąd pochodzi. Przede wszystkim chcielibyśmy sprawdzić, czy a> b, i, jak już poprawnie widzieliście, robimy różnicę pomiędzy porównywaniem ciągów i porównywaniem liczb.

Chcemy po prostu dać:

return (
     isNaN(a) || isNaN(b) ? 
     a > b : +a > +b 
     ) ? 1 : -1; 

ta sprawdza czy a> b (albo łańcuch lub numer mądry mądry), a następnie zwraca 1 na prawdziwe i -1 na false.

Teraz wstawiamy parametr inverse, który powinien odwrócić wynik. Oznacza to, że , jeśli odwrotność == prawda, to 1 staje się -1, a -1 staje się 1. W kodzie ten pogrubiony fragment tekstu zastąpiłby każde wystąpienie 1 za pomocą inverse ? -1 : 1 i każdego wystąpienia -1 z -1 z -1. Dokładnie to, co robi się w wynikowym kodzie.

UPDATE: Dodano doRowSpan w kodzie, ponieważ nie powinna dostosować indeks jeśli jesteśmy w <tr> że zawiera rowspan- td.

+0

Dziękuję bardzo. Kiedy podłączam twój kod, otrzymałem ten błąd javascript 'Uncaught SyntaxError: Illegal continue statement'. Można to sprawdzić, używam 'http: // ajax.googleapis.com/ajax/libs/jquery/1.8.2/jquery.min.js' –

+0

, ponieważ sposób w jaki przechodzę w indeksie, potrzebuję index = index + 1, jednak w twoim przypadku proszę go wyjąć. Ponadto użyłem twojego kodu (bez kontynuacji), ale stół jest zepsuty, stawiam tabelę, której używam do testowania w moim pytaniu, możesz ją obejrzeć. Dziękuję bardzo. Ja też to badam. Dziękuję –