Valorile de sortare cu JavaScript

Listele și tabelele sunt adesea cea mai bună modalitate de a afișa date pe web; dar nu ar trebui să vă faceți griji cu privire la sortarea acestor informații manual. În tutorialul de astăzi, veți face un plugin jQuery care va pune toate rațele într-un rând cu ușurință JavaScript!


Prefaţă

Deci, cum funcționează sortarea în JavaScript? Nu este prea complicat: orice obiect de matrice are o metodă de sortare. Dacă nu îi transmiteți niciun parametru, acesta va converti obiectele din matrice în șiruri, le sortează pseudo-alfabetic și le va returna. De obicei, acest lucru este teribil; ia în considerare sortarea numerelor 0 - 10 în ordine alfabetică. Veți obține acest lucru: [0, 1, 10, 2, 3, 4, 5, 6, 7, 8, 9]. Din fericire, putem trece o funcție la metoda de sortare. Această funcție ar trebui să ia doi parametri (cele două elemente care urmează să fie comparate): atunci, va reveni 0 dacă sunt egale, un număr negativ dacă primul parametru are prioritate sau un număr pozitiv al celui de-al doilea parametru ar trebui să fie primul. Deci, numerele sunt de fapt cel mai simplu lucru pentru a sorta "manual":

 numberArray.sort (funcția (a, b) return a - b);

Evident, acest lucru va returna 0 dacă numerele sunt egale, un număr negativ dacă A ar trebui să fie primul, și un număr pozitiv dacă b ar trebui să fie primul.

Vom analiza mai multe tipuri diferite de date, câteva în mai multe formate; dar acest lucru va fi mult mai util dacă îl înfășurăm într-un plugin jQuery, așa că, haideți să începem prin instalarea acelei coajă!

Pluginul Shell

Dacă nu sunteți familiarizați cu scrierea pluginurilor jQuery, verificați ecranul lui Jeffrey Way "" Încă nu puteți crea un plugin jQuery? " Te va duce rapid la viteză, dacă te simți confortabil cu jQuery! (adevarata confesiune: nu scriam niciodata un plugin pana nu am facut asta).

Vom configura plugin-ul nostru, numit datasort, în felul următor: îi vom transmite o serie de elemente pentru sortare; putem specifica patru parametri.

  • tipul de date (tipul de date pe care îl sortați)
  • sortElement (elementul copil pe care doriți să îl sortați, dacă doriți)
  • sortAttr (atributul pe care doriți să-l sortați, dacă doriți)
  • invers (direcția pe care ar trebui să o sorteze)

Deci, un apel complet modificat la pluginul nostru ar putea arăta astfel:

 $ ('ul.names li) .datasort (datatype:' alpha ', sortElement:' span.first ', sortAttr:' rel ', invers: true);

Iată shell-ul plugin-ului:

 (funcția ($) $ .fn.datasort = funcție (opțiuni) var defaults = // setați valorile implicite de tip dat: "alfa", sortElement: false, sortAttr: false, reverse: false parametrii impliciți și cei ai utilizatorului, setările prestabilite pentru valori implicite = $ .extend (, implicit, opțiuni), datatypes = , base = , if = this; if (typeof settings.datatype === string) that.sort (datatypes [settings.datatype]); dacă (typeof settings.datatype === 'function') that.sort (set.datatype); if (set.reverse) that = $ ($. (), (), (), (), (), (), ().

Deci, iată cum va funcționa: vom stabili toate variabilele la început. Apoi, dacă parametrul de tip dat este un șir, vom găsi funcția de sortare corespunzătoare în obiectul dat de date și sortați cu acesta; dacă parametrul datat este o funcție, vom sorta cu ea. În cele din urmă, dacă setarea inversă este setată la true, vom inversa ordinea elementelor sortate (deoarece obiectele jQuery nu sunt adevărate matrice JavaScript, funcția inversă nu va funcționa pe ele, deci putem folosi $ .makeArray ( ) să o transformăm într-una, apoi, odată ce este inversată, noi o re-jquery-fy it!).

A face un pic mai mult de bază

La cel mai mic nivel, puteți sorta aproape orice tip de date într-unul din două moduri: le vom numi în ordine alfabetică și numerică. Să creăm aceste două funcții ca proprietăți ale obiectului de bază.

 baza = alfa: funcție (a, b) a = a.toUpperCase (); b = b.toUpperCase (); retur (a < b) ? -1 : (a > b): 1: 0; // operatorul ternar: condiție? returnIfTrue: returnIfFalse, numărul: funcția (a, b) a = parseFloat (a); b = parseFloat (b); returnați a - b; ,

Destul de simplu, nu? Pur și simplu normalizați cele două valori, comparați și reveniți. Partea dificilă este analizarea datelor pe care dorim să le trimitem acestor funcții; asta vom face acum. Cu toate acestea, există încă un lucru.

La sortarea elementelor în matrice, este posibil să nu dorim să sortăm pur și simplu textul elementului propriu-zis. Parametrii sortElement și sortAttr ai pluginului nostru sunt în acest scop. De exemplu, probabil vom dori să sortați rândurile de tabel pe baza unei anumite coloane de celule de tabelă. În acest caz, vom folosi $ ('table tr'). Datasort (sortElement: 'td.price')). Sau poate dorim să sortăm o listă a imaginilor după atributele lor alt: $ ('ul li') datasort (sortElement: 'img', sortAttr: 'alt'). Din această cauză, trebuie să adăugăm încă o funcție la obiectul de bază:

 (a, b) a, b) var get = funcția (i) var o = $ (i ); dacă (set.sortElement) o = o.children (settings.sortElement);  dacă (setări.sortAttr) o = o.attr (set.sortAttr);  altceva o = o.text ();  retur o; ; returnați a: get (a), b: get (b); ,

Ar putea părea complicat, dar nu este. Noi creăm doar un obiect jQuery cu fiecare element; dacă setElement este setat, vom folosi metoda children () pentru a obține elementele potrivite. Apoi, dacă un sortAttr este setat, obținem valoarea lui; dacă nu, obținem textul elementului. Am pus toate acestea la o funcție interioară și returnează un obiect cu două proprietăți; aceste proprietăți sunt valorile pe care trebuie să le analizăm și să le trimitem la funcția de sortare de bază corespunzătoare.

Acest lucru părea probabil ca o mulțime de pregătire de lucru, dar ceea ce am făcut cu adevărat este abstractizarea cât mai mult cod posibil. În acest fel, vor fi mult mai puțin cod repetat, deoarece acțiunile importante au fost combinate ca funcții.

Sortarea cuvintelor și a numerelor

Suntem în sfârșit aici: partea distractivă! Vom începe prin construirea a două funcții simple pentru obiectul dat. Acestea vor trece simplu valorile la base.extract () și apoi vor trece acele valori returnate la clasa corespunzătoare de sortare.

 datatypes = alfa: funcție (a, b) var o = base.extract (a, b); baza de întoarcere.alpha (o.a, o.b); , numărul: funcția (a, b) var o = base.extract (a, b); pentru (var e în o) o [e] = o [e] .locați (/ [$]? (-? \ d +.? d +) /, '\ $ 1');  return numărul de bază (o.a, o.b); ,,

Sorterul nostru alfabetic ar trebui să fie evident. Numãrul de sortare face un pic mai mult: înainte de a trece valorile extrase pe, ea stripe un semn de dolar în față. Am păstrat această expresie regulată simplă, dar ați putea analiza o mulțime de formate de numere diferite aici dacă doriți să obțineți complexitate. Să încercăm pluginul nostru evolutiv; creați o pagină html de bază:

     Sortarea datelor    
Nume Numele de familie
Jeffrey Cale
Sean talmeș
Adam morar
Ian Yates
Adrian Încerca
Caleb Aylsworth
  • 4,09
  • 4.10
  • 67.8
  • 100
  • -98
  • 67.7
  • 23
  • $ 299,66
  • $ 299,57
  • $ 0,14
  • $ 80.00

Am inclus o masă și două liste (și le-am desenat pe scurt). Luați notă de apelurile pluginului nostru: folosim tipul de date implicit pentru tabel, dar sortăm cu celulele tabelului cu o clasă de ultim; încercați să o schimbați în "td.first". Apoi, sortăm listele numeric și inversăm una dintre ele. Iată dovada muncii noastre:

Destul de frumos, dar acestea erau valori relativ simple; dacă dorim să putem sorta mai multe formate pentru un singur tip?

Datele de sortare

Există o serie de modalități diferite de a scrie date, ceea ce face destul de dificil să le analizăm pentru sortare. Cu toate acestea, putem acoperi majoritatea acestora cu acest lucru:

 data: funcția (a, b) var o = baza.extract (a, b); pentru (var e in o) o [e] = o [e] .replace (/ - / g, ") .replace (/ ianuarie | jan / i, 01 ' , '02') .replace (/ march | mar / i, '03') .replace (/ aprilie | apr / i, '04' | jun / i, 06) .replace (/ july | jul / i, '07') .replace (/ august | aug / i, '08' 09 ') .replace (/ october | oct / i,' 10 ') .replace (/ november | nov / i,' 11 ' \ d 2) (\ d 2), (\ d 4) /, '\ $ 3 \ $ 1 \ $ 2' ) \ / (\ d 4) /, '\ $ 3 \ $ 2 \ $ 1');, 

Deci, ce facem aici? Mai întâi, iată logica: dacă toate datele sunt formatate YYYYMMDD, acestea vor sorta corect cu sortarea numerică. Parserul nostru poate sorta următoarele formate de date:

  • AAAA-LL-ZZ
  • AAAALLZZ
  • ZZ / LL / AAAA
  • luna DD, AAAA

Mai intai renuntam la liniutele noastre, ceea ce va lasa AAAA-MM-DD gata pentru parsare. Apoi, înlocuim numele sau abrevierea fiecărei luni cu valoarea numărului. În cele din urmă, trebuie să rearanjăm numerele pentru DD / MM / AAA și luna DD, AAAA. Asta fac ultimele două expresii. Pentru o încercare, lipiți această listă în codul HTML:

 
  • 2009-10-06
  • sept 25, 1995
  • 1990-06-18
  • 20100131
  • 18 iunie 2009
  • 02/11/1993
  • 15941219
  • 1965-08-05
  • 1425-12-25

Și spuneți-le cu aceasta:

 $ ('ul.date li'). datasort (datatype: 'date');

Este un parser perfect pentru date? Nu prin nici un mijloc; nu putem sorta DD / MM / YY, deoarece nu există nici o modalitate de a ști care este secolul acesta. De asemenea, nu putem spune diferența dintre DD / MM / YY și MM / DD / YY, deci trebuie doar să Alege una.

Timp de sortare

Valorile timpului de sortare trebuie să fie una dintre cele mai dificile valori de sortare: trebuie să putem accepta timp de 12 ore, timp de 24 de ore și valori cu sau fără etichete AM / PM și secunde. Cred că este mai ușor să sortați timpul alfabetic, chiar dacă toate numerele. De ce? Luați în considerare aceste două timbre: 00:15:37 și 12:15. Primul ar trebui să vină mai întâi, dar dacă le sortăm după număr, ele vor fi analizate ca flotoare și vor sfârși ca 1537 și 1215. Acum, a doua valoare va fi prima dată. De asemenea, atunci când sortăm în ordine alfabetică, nu trebuie să scoatem colonii (parseFloat () s-ar sufoca pe ele). Deci, iată cum sa făcut.

 timpul: funcția (a, b) var o = baza.extract (a, b), după-amiaza = / (((+)) PM $ / i; pentru (var e în o) o [e] = o [e] .split (':'); var ultima = o [e] .length - 1; dacă (după-amiază.test (o [e] [ultima])) o [e] [0] = parseInt (o [e] [0]); o [e] [ultima] = o [e] [ultima] .replace (după-amiază, '\ $ 1');  dacă (parseInt (o [e] [0]) < 10 && o[e][0].length === 1)  o[e][0] = '0' + o[e][0];  o[e][last] = o[e][last].replace(/^(.+) AM$/i, '\$1'); o[e] = o[e].join(");  return base.alpha(o.a, o.b); 

Să trecem prin linia asta.

 var o = baza.extract (a, b), după-amiază = / ((+)) PM $ / i;

Începem cu variabilele noastre: valorile extrase și o expresie regulată pentru a verifica eticheta PM.

 pentru (var e în o) o [e] = o [e] .split (':'); var ultima = o [e] .length - 1; dacă (după-amiază.test (o [e] [ultima])) o [e] [0] = parseInt (o [e] [0]); o [e] [ultima] = o [e] [ultima] .replace (după-amiază, '\ $ 1'); 

Apoi, vom începe o buclă, pentru a trece prin fiecare dintre valorile pe care le sortim; în primul rând, l-am împărțit într-o matrice la colonii. Creăm o modalitate ușoară de a ajunge la ultimele elemente ale matricei: ultima noastră variabilă. Apoi, testăm regexul nostru PM pe ultimul element din matricea noastră; dacă se întoarce adevărat, această valoare are eticheta PM. Prin urmare, vom adăuga 12 la primul element din matricea noastră, care va fi valoarea orei; facem acest lucru pentru că avem nevoie de toate valorile care trebuie formatate în timp de 24 de ore. (Rețineți că, pentru a face acest lucru, trebuie să îl convertim într-un număr, să adăugăm 12 și apoi să îl transformăm într-un șir). În cele din urmă, folosim din nou regexul PM pentru a elimina acea etichetă din ultimul element din matrice.

 if (parseInt (o [e] [0]) < 10 && o[e][0].length === 1)  o[e][0] = '0' + o[e][0];  o[e][last] = o[e][last].replace(/^(.+) AM$/i, '\$1'); o[e] = o[e].join(");  return base.alpha(o.a, o.b);

În această ultimă bucată, verificăm valoarea oră pentru două condiții: este mai mică de 10? și șirul are un singur caracter? Acest lucru este important deoarece o valoare ca 08 va fi analizată ca 8 și va fi mai mică de 10; dar încercăm să vedem dacă trebuie să adăugăm un zero în față. Dacă șirul are doar un caracter, atunci adăugăm zero, deci 3 devine 03. Acest lucru va face lucrurile în ordine!

Înainte de a intra în matrice, eliminăm orice etichete AM. Deci acum ...

 
  • 01:15:47
  • 3:45 PM
  • 12:00:17
  • 06:56
  • 19:39
  • 4:32 AM
  • 00:15:36

... pot fi sortate cu ...

 $ ('ul.time li'). datasort (datatype: 'time'); 

Și am terminat! Iată roadele muncii noastre:

Mai multe valori aleatoare

Am creat pluginul nostru jQuery astfel încât utilizatorii să poată trece funcțiile de sortare ca parametru datatype. Acest lucru ne permite să extindem cu ușurință pluginul, deși nu avem acces la clasa de bază din apelul pluginului. Putem scrie cu ușurință o funcție pentru a sorta psudeo-rating-uri:

 $ (a, b) var o = a: $ (a) .text (), b: $ (b) .text var / in / o) o [e] = o [e] .replace (/ / i, 3); retur oa-ob;);

Aceasta folosește cele mai simple expresii regulate posibile pentru a sorta o listă ca aceasta:

 
  • Bun
  • Excelent
  • slab
  • Satisfăcător

E un Wrap!

Acum esti in stiinta: valorile de sortare din JavaScript nu sunt la fel de greu ca s-ar fi putut crede. Vă puteți imagina că este util să sortați o masă, cu ceva de genul:

 $ ('table # myTable td'). comanda (function () var $ this = $ (this); $ (' ), sortElement: 'td' + $ this.attr ('class'));, function () var $ this = $ (this); $ ('table # myTable tbody tr' datatype: $ this.attr ('rel'), sortElement: 'td.' + $ this.attr ('class'), invers: true);); 

(Încercați să înlocuiți codul jQuery pentru tabel în primul exemplu cu acest!)

Desigur, am putea îmbunătăți foarte mult acest plugin; de exemplu, am putea să o verificăm rel atttribute pentru un tip de date dacă unul nu este dat ca parametru și implicit pentru alfa dacă nu există rel. Dar asta este în afară de sortare.

În concluzie, pentru a sorta cu JavaScipt, urmăm acești pași:

  1. Determinați diferitele formate pe care doriți să le sortați.
  2. Decideți în ce format doriți să sortați.
  3. Sortați matricea de elemente cu metoda sort (), trecând într-o funcție care va converti cele două elemente la formatul dorit înainte de a le compara

Aveți un tip de date pentru a adăuga pluginul nostru? Aveți o modalitate mai bună de a sorta una dintre acestea? Să o auzim în comentarii!

  • Urmați-ne pe Twitter sau abonați la Nettuts + RSS Feed pentru cele mai bune tutoriale de dezvoltare web de pe web.


Cod