Werte mit JavaScript sortieren

Listen und Tabellen sind oft die beste Methode, um Daten im Web anzuzeigen. Sie müssen sich jedoch keine Gedanken darüber machen, diese Informationen manuell zu sortieren. Im heutigen Tutorial werden Sie ein jQuery-Plugin erstellen, das alle Ihre Enten mit JavaScript in einer Reihe anordnet!


Vorwort

Wie genau funktioniert das Sortieren in JavaScript? Es ist nicht zu kompliziert: Jedes Array-Objekt verfügt über eine Sortiermethode. Wenn Sie keine Parameter übergeben, werden die Objekte im Array in Strings konvertiert, pseudoalphabetisch sortiert und zurückgegeben. Normalerweise ist das schrecklich. Erwägen Sie, die Zahlen 0 - 10 alphabetisch zu sortieren. Sie würden dies erhalten: [0, 1, 10, 2, 3, 4, 5, 6, 7, 8, 9]. Glücklicherweise können wir der Sortiermethode eine Funktion übergeben. Diese Funktion sollte zwei Parameter (die zwei zu vergleichenden Elemente) annehmen: dann wird 0 zurückgegeben, wenn sie gleich sind, eine negative Zahl, wenn der erste Parameter Vorrang hat, oder eine positive Zahl des zweiten Parameters sollte zuerst kommen. Zahlen sind also eigentlich das Einfachste, um "manuell" zu sortieren:

 numberArray.sort (Funktion (a, b) return a - b);

Offensichtlich gibt dies 0 zurück, wenn die Zahlen gleich sind, eine negative Zahl, wenn ein sollte zuerst sein und eine positive Zahl wenn b sollte zuerst sein.

Wir werden verschiedene Datentypen sortieren, einige in mehreren Formaten. Dies alles wird jedoch viel nützlicher sein, wenn wir es in ein jQuery-Plugin packen!

Die Plugin-Shell

Wenn Sie nicht mit dem Schreiben von jQuery-Plugins vertraut sind, lesen Sie den Screencast von Jeffrey Way "Sie können immer noch kein jQuery-Plugin erstellen?" Wenn Sie mit jQuery vertraut sind, sind Sie in kürzester Zeit auf dem neuesten Stand! (wahres Geständnis: Ich hätte eigentlich nie ein Plugin geschrieben, bis ich dieses gemacht habe).

Wir richten unser Plugin, das als Datensort bezeichnet wird, auf folgende Weise ein: Wir übergeben ein Array von Elementen zum Sortieren; Wir können vier Parameter angeben.

  • Datentyp (der Datentyp, den Sie sortieren)
  • sortElement (das untergeordnete Element, nach dem Sie sortieren möchten, falls gewünscht)
  • sortAttr (das Attribut, nach dem Sie sortieren möchten, falls gewünscht)
  • umgekehrt (die Richtung, in der sie sortieren sollen)

Ein vollständig modifizierter Aufruf unseres Plugins könnte also so aussehen:

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

Hier ist die Plugin-Shell:

 (function ($) $ .fn.datasort = function (Optionen) var defaults = // Setzt die Standardparameterwerte datatype: 'alpha', sortElement: false, sortAttr: false, reverse: false, // kombinieren Standard- und Benutzerparameter, Standardeinstellungen überschreiben = $ .extend (, Standardwerte, Optionen), Datentypen = , Basis = , = = this; if (typeof settings.datatype === 'string')  that.sort (datatypes [settings.datatype]); if (typeof settings.datatype === 'function') that.sort (settings.datatype); if (settings.reverse) das = $ ($. makeArray (this) .reverse ()); $ .each (that, function (index, element) that.parent (). append (element););;) (jQuery);

Und so funktioniert es: Wir werden am Anfang alle Variablen einrichten. Wenn der Datentyp-Parameter eine Zeichenfolge ist, finden wir die entsprechende Sortierfunktion im Datentypobjekt und sortieren danach. Wenn der Datentyp-Parameter eine Funktion ist, werden wir damit sortieren. Wenn die Einstellung "reverse" auf "true" gesetzt ist, kehren wir die Reihenfolge der sortierten Elemente um (da jQuery-Objekte keine echten JavaScript-Arrays sind, funktioniert die Funktion "reverse" nicht für sie. Daher können wir $ .makeArray verwenden ( ) um es in eins zu verwandeln; dann, wenn es umgekehrt ist, machen wir es neu!.

Ein bisschen mehr Grundsteinlegung

Auf der untersten Ebene können Sie fast alle Arten von Daten auf zwei Arten sortieren: Wir rufen sie alphabetisch und numerisch auf. Erstellen Sie diese beiden Funktionen als Eigenschaften Ihres Basisobjekts.

 base = alpha: function (a, b) a = a.toUpperCase (); b = b. toUpperCase (); Rückkehr (a < b) ? -1 : (a > b): 1: 0; // ternärer Operator: Bedingung? returnIfTrue: returnIfFalse, number: function (a, b) a = parseFloat (a); b = parseFloat (b); Rückgabe a - b; ,

Ganz einfach, wie? Normalisieren Sie einfach die beiden Werte, vergleichen Sie und kehren Sie zurück. Der schwierige Teil besteht darin, die Daten zu analysieren, die wir an diese Funktionen senden möchten. das machen wir jetzt. Es gibt jedoch noch eine weitere Sache.

Beim Sortieren von Elementen im Array möchten wir möglicherweise nicht einfach nach dem Text des Elements selbst sortieren. Zu diesem Zweck dienen die Parameter sortElement und sortAttr unseres Plugins. Zum Beispiel möchten wir wahrscheinlich Tabellenzeilen nach einer bestimmten Spalte von Tabellenzellen sortieren. In diesem Fall würden wir $ ('table tr'). Datasort (sortElement: 'td.price') verwenden. Oder wir möchten vielleicht eine Liste von Bildern nach ihren alt-Attributen sortieren: $ ('ul li'). Datasort (sortElement: 'img', sortAttr: 'alt'). Aus diesem Grund müssen wir unserem Basisobjekt eine weitere Funktion hinzufügen:

 base = alpha: Funktion (a, b) …, Zahl: Funktion (a, b) …, extrahieren: Funktion (a, b) var get = Funktion (i) var o = $ (i ); if (settings.sortElement) o = o.children (settings.sortElement);  if (settings.sortAttr) o = o.attr (settings.sortAttr);  else o = o.text ();  return o; ; return a: get (a), b: get (b); ,

Es mag kompliziert aussehen, ist es aber nicht. Wir erstellen einfach ein jQuery-Objekt mit jedem Element. Wenn sortElement gesetzt ist, verwenden wir die children () -Methode, um die richtigen Elemente zu erhalten. Wenn dann ein sortAttr gesetzt ist, erhalten wir seinen Wert. Wenn nicht, erhalten wir den Text des Elements. Wir haben all dies auf eine innere Funktion festgelegt und ein Objekt mit zwei Eigenschaften zurückgegeben. Diese Eigenschaften sind die Werte, die wir analysieren und an die entsprechende Basissortierfunktion senden müssen.

Dies schien wahrscheinlich eine Menge Vorarbeit zu sein, aber wir haben wirklich so viel Code wie möglich abstrahiert. Auf diese Weise werden sie viel weniger Code wiederholen, da die wichtigen Aktionen als Funktionen gebündelt wurden.

Wörter und Zahlen sortieren

Endlich sind wir hier: der lustige Teil! Wir beginnen damit, zwei einfache Funktionen für unser Datentypobjekt zu erstellen. Diese übergeben Werte einfach an base.extract () und übergeben diese Rückgabewerte dann an die entsprechende Sortierklasse.

 Datentypen = Alpha: Funktion (a, b) var o = base.extract (a, b); Rücklaufbasis α (o.a, o.b); , number: Funktion (a, b) var o = base.extract (a, b); für (var e in o) o [e] = o [e] .replace (/ [$]? (-? \ d +.? \ d +) /, '\ $ 1');  return base.number (o.a, o.b); ,,

Unser alphabetischer Sortierer sollte offensichtlich sein. Der Nummernsortierer macht noch ein bisschen mehr: Bevor er die extrahierten Werte weitergibt, entfernt er ein Dollarzeichen an der Vorderseite. Ich habe diesen regulären Ausdruck einfach gehalten, aber Sie könnten hier viele verschiedene Zahlenformate analysieren, wenn Sie komplex werden möchten. Probieren Sie unser weiterentwickeltes Plugin aus. Erstellen Sie eine einfache HTML-Seite:

     Datensortierung    
Vorname Nachname
Jeffrey Weg
Sean Hodge
Adam Müller
Ian Yates
Adrian Versuchen
Caleb Aylsworth
  • 4,09
  • 4,10
  • 67,8
  • 100
  • -98
  • 67,7
  • 23
  • 299,66 $
  • 299,57 $
  • $ 0,14
  • 80,00 $

Ich habe eine Tabelle und zwei Listen hinzugefügt (und ich habe sie kurz gestylt). Beachten Sie unsere Plugin-Aufrufe: Wir verwenden den Standarddatentyp für die Tabelle, sortieren jedoch nach den Tabellenzellen mit der letzten Klasse. Ändern Sie dies in 'td.first'. Dann sortieren wir die Listen numerisch und kehren eine davon um. Hier ist der Beweis unserer Arbeit:

Ziemlich schön, aber das waren relativ einfache Werte; Was ist, wenn wir mehrere Formate für einen Typ sortieren möchten?

Sortierdaten

Es gibt verschiedene Möglichkeiten, Datumsangaben zu schreiben, was es ziemlich schwierig macht, sie zum Sortieren zu analysieren. Die meisten davon können wir jedoch damit abdecken:

 Datum: Funktion (a, b) var o = base.extract (a, b); für (var e in o) o [e] = o [e] .replace (/ - / g, ") .replace (/ januar | jan / i, '01') .replace (/ februar | feb / i , '02') .replace (/ march | mar / i, '03') .replace (/ april | apr / i, '04') .replace (/ mai / i, '05') .replace (/ juni jun / i, '06') .replace (/ juli | jul / i, '07') .replace (/ august | aug / i, '08') .replace (/ september | sept | sep / i, ' 09 ') .replace (/ oktober | oct / i,' 10 ') .replace (/ november | nov / i,' 11 ') .replace (/ december | dec / i,' 12 ') .replace (/ ( \ d 2) (\ d 2), (\ d 4) /, '\ $ 3 \ $ 1 \ $ 2') .replace (/ (\ d 2) \ / (\ d 2 ) \ / (\ d 4) /, '\ $ 3 \ $ 2 \ $ 1'); return base.number (oa, ob);, 

Also, was machen wir hier? Zunächst einmal die Logik: Wenn alle Datumsangaben JJJJMMTT formatiert sind, werden sie mit numerischer Sortierung korrekt sortiert. Unser Parser kann folgende Datumsformate sortieren:

  • JJJJ-MM-TT
  • JJJJMMTT
  • DD / MM / JJJJ
  • Monat TT, JJJJ

Zuerst entfernen wir unsere Bindestriche, wodurch JYYY-MM-DD für die Analyse bereit ist. Dann ersetzen wir jeden Monatsnamen oder seine Abkürzung durch seinen Zahlenwert. Schließlich müssen wir die Zahlen für TT / MM / JJJ und Monat TT, JJJJ neu anordnen. Das tun die letzten beiden Ausdrücke. Um es auszuprobieren, fügen Sie diese Liste in unseren HTML-Code ein:

 
  • 2009-10-06
  • 25. September 1995
  • 1990-06-18
  • 20100131
  • 18. Juni 2009
  • 02/11/1993
  • 15941219
  • 1965-08-05
  • 1425-12-25

Und nenne es so:

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

Ist dies ein perfekter Datums-Parser? Auf keinen Fall; Wir können DD / MM / YY nicht sortieren, da es keine Möglichkeit gibt, zu wissen, in welchem ​​Jahrhundert sich das befindet. Außerdem können wir den Unterschied zwischen DD / MM / YY und MM / DD / YY nicht unterscheiden, also müssen wir nur wähle ein.

Sortierzeit

Die Sortierzeitwerte müssen einer der am schwierigsten zu sortierenden Werte sein: Wir müssen 12-Stunden-Zeit, 24-Stunden-Zeit und Werte mit oder ohne AM / PM-Tags und Sekunden akzeptieren können. Ich denke, es ist am einfachsten, die Zeit alphabetisch zu sortieren, obwohl es alle Zahlen sind. Warum? Betrachten Sie diese zwei Zeitstempel: 00:15:37 und 12:15. Der erste sollte zuerst kommen, aber wenn wir sie nach der Nummer sortieren, werden sie als Floats analysiert und enden als 1537 und 1215. Nun kommt der zweite Wert an erster Stelle. Wenn Sie alphabetisch sortieren, müssen Sie die Doppelpunkte nicht entfernen (parseFloat () würde sie verschlucken). So wird es gemacht.

 Zeit: Funktion (a, b) var o = base.extract (a, b), nachmittags = / ^ (+) PM $ / i; für (var e in o) o [e] = o [e] .split (':'); var last = o [e] .length - 1; if (nachmittags. test (o [e] [last])) o [e] [0] = (parseInt (o [e] [0]) + 12) .toString (); o [e] [last] = o [e] [last] .replace (nachmittags '\ $ 1');  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); 

Gehen wir diese Zeile für Zeile durch.

 var o = base.extract (a, b), nachmittags = / ^ (+) PM $ / i;

Wir beginnen mit unseren Variablen: unseren extrahierten Werten und einem regulären Ausdruck, um das PM-Label zu überprüfen.

 für (var e in o) o [e] = o [e] .split (':'); var last = o [e] .length - 1; if (nachmittags. test (o [e] [last])) o [e] [0] = (parseInt (o [e] [0]) + 12) .toString (); o [e] [last] = o [e] [last] .replace (nachmittags '\ $ 1'); 

Als Nächstes beginnen wir mit einer for-Schleife und gehen alle Werte durch, die wir sortieren. Zuerst teilen wir es an den Doppelpunkten in ein Array auf. Wir schaffen einen einfachen Weg, um zu den letzten Elementen des Arrays zu gelangen: unsere 'letzte' Variable. Dann testen wir unseren PM-Regex am letzten Element in unserem Array. Wenn es true zurückgibt, hat dieser Wert das PM-Tag. Deshalb fügen wir dem ersten Element in unserem Array 12 hinzu. Dies ist der Stundenwert. Wir tun dies, weil wir alle Werte in 24 Stunden formatieren müssen. (Um dies zu tun, müssen wir es in eine Zahl umwandeln, 12 hinzufügen und es dann wieder in eine Zeichenfolge umwandeln.) Schließlich verwenden wir erneut den PM-Regex, um dieses Label vom letzten Element im Array zu entfernen.

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

In diesem letzten Abschnitt überprüfen wir den Stundenwert für zwei Bedingungen: Ist es weniger als 10? und hat die Zeichenfolge nur ein Zeichen? Dies ist wichtig, da ein Wert wie 08 als 8 geparst wird und weniger als 10 beträgt. Aber wir versuchen zu sehen, ob wir eine Null vor der Front hinzufügen müssen. Wenn die Zeichenfolge nur ein Zeichen enthält, fügen wir die Null hinzu, sodass 3 zu 03 wird. Dadurch werden die Dinge in Ordnung gehalten!

Bevor wir das Array verbinden, entfernen wir alle AM-Labels. Also jetzt das…

 
  • 1:15:47
  • 15:45 Uhr
  • 12:00:17
  • 06:56
  • 19:39
  • 4:32 morgens
  • 00:15:36

… Kann damit sortiert werden…

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

Und wir sind fertig! Seht die Früchte unserer Arbeit:

Weitere Zufallswerte

Wir haben unser jQuery-Plugin so eingerichtet, dass Benutzer Sortierungsfunktionen als Datentypparameter übergeben können. Dadurch können wir das Plugin problemlos erweitern, obwohl wir über den Pluginaufruf keinen Zugriff auf die Basisklasse haben. Wir können leicht eine Funktion zum Sortieren von Psudeo-Bewertungen schreiben:

 $ ('ul.rating li'). datasort (Datentyp: Funktion (a, b) var o = a: $ (a) .text (), b: $ (b) .text () für ( var e in o) o [e] = o [e] .replace (/ schlecht / i, 0) .replace (/ zufriedenstellend / i, 1) .replace (/ good / i, 2) .replace (/ ausgezeichnet / i, 3); return oa - ob;);

Hierbei werden die einfachsten regulären Ausdrücke verwendet, um eine Liste wie folgt zu sortieren:

 
  • Gut
  • Ausgezeichnet
  • Arm
  • Zufriedenstellend

Das ist eine Verpackung!

Jetzt wissen Sie Bescheid: Das Sortieren von Werten in JavaScript ist wirklich nicht so schwer, wie Sie vielleicht gedacht haben. Sie können sich vorstellen, dass dies nützlich ist, um eine Tabelle zu sortieren.

 $ ('table # myTable thead th'). toggle (function () var $ this = $ (this); $ ('table # meinTable tbody tr'). datasort (datentyp: $ this.attr ('rel' ), sortElement: 'td.' + $ this.attr ('class'));, function () var $ this = $ (this); $ ('table # myTable tbody tr'). datasort ( Datentyp: $ this.attr ('rel'), sortElement: 'td.' + $ this.attr ('class'), reverse: true);); 

(Versuchen Sie, den jQuery-Code für die Tabelle im ersten Beispiel durch dieses zu ersetzen!)

Natürlich könnten wir dieses Plugin erheblich verbessern. Zum Beispiel könnten wir es überprüfen lassen rel atttribute für einen Datentyp, wenn dieser nicht als Parameter angegeben ist, und standardmäßig alpha, wenn nein rel. Aber das ist abgesehen von der Sortierung.

Zusammenfassend führen wir folgende Schritte durch, um mit JavaScipt zu sortieren:

  1. Bestimmen Sie die verschiedenen Formate, die Sie sortieren möchten.
  2. Entscheiden Sie, in welchem ​​Format Sie sortieren möchten.
  3. Sortieren Sie das Array von Elementen mit der sort () -Methode und übergeben Sie eine Funktion, die die beiden Elemente in das gewünschte Format konvertiert, bevor Sie sie vergleichen

Haben Sie einen Datentyp für unser Plugin? Haben Sie eine bessere Möglichkeit, eine davon zu sortieren? Lass es uns in den Kommentaren hören!

  • Folgen Sie uns auf Twitter oder abonnieren Sie den Nettuts + RSS-Feed für die besten Webentwicklungs-Tutorials im Web.