Verwendung der Widget Factory von jQuery UI

Lange Zeit war die einzige Möglichkeit, benutzerdefinierte Steuerelemente in jQuery zu schreiben, die Erweiterung von $ .fn Namespace. Dies funktioniert gut für einfache Widgets. Wenn Sie jedoch mehr Stateful-Widgets erstellen, wird dies schnell mühsam. Um die Erstellung von Widgets zu erleichtern, hat das jQuery-UI-Team die Widget Factory eingeführt, die den Großteil der Speicherplatine entfernt, die normalerweise mit der Verwaltung eines Widgets verbunden ist.

Die Widgetfabrik, Teil der jQuery UI Core, bietet eine objektorientierte Methode zum Verwalten des Lebenszyklus eines Widgets. Diese Lebenszyklusaktivitäten umfassen:

  • Widget erstellen und zerstören
  • Widget-Optionen ändern
  • Machen "Super"Aufrufe in untergeordneten Widgets
  • Ereignisbenachrichtigungen

Lassen Sie uns diese API näher untersuchen, während wir ein einfaches Bullet-Chart-Widget erstellen.


Das Bullet Chart Widget

Bevor wir dieses Widget erstellen, sollten wir einige Bausteine ​​des Widgets verstehen. Das Bullet Chart ist ein Konzept, das von Stephen Few als Variation des Balkendiagramms eingeführt wurde.

Das Diagramm besteht aus einer Reihe von Balken und Markierungen, die einander überlagert sind, um die relative Leistung anzuzeigen. Es gibt eine quantitative Skala, um den tatsächlichen Wertebereich anzuzeigen. Durch das Stapeln der Balken und Marker auf diese Weise können mehr Informationen übermittelt werden, ohne die Lesbarkeit zu beeinträchtigen. Die Legende erzählt von den Informationen, die wir planen.

Der HTML-Code für dieses Diagramm sieht folgendermaßen aus:

 
Grüne Linie
0
25
50
75
100

Unser Widget, das wir anrufen jquery.bulletchart, generiert diesen HTML-Code dynamisch aus den bereitgestellten Daten. Das endgültige Widget kann in den Quelldateien angezeigt werden, die Sie von GitHub herunterladen können. Der Aufruf zum Erstellen des Widgets sollte folgendermaßen aussehen:

 $ ('. chart'). bulletchart (Größe: 86, Balken: [title: 'Projected Target'), Wert: 75, css: ", title: 'Actual Target', Wert: 50, css: ' blau '], Marker: [title:' Green Line ', Wert: 80, css:' green ', title:' Minimum Threshold ', Wert: 50, css:' red '], Ticks: [ 0, 25, 50, 75, 100]);

Alle Werte sind in Prozent angegeben. Das Größe Diese Option kann verwendet werden, wenn mehrere Aufzählungsdiagramme mit relativer Größe nebeneinander platziert werden sollen. Das Zecken Mit dieser Option können Sie die Etiketten auf die Waage setzen. Die Markierungen und Balken werden als Array von Objektliteralen mit angegeben Titel, Wert und css Eigenschaften.


Widget erstellen

Nun, da wir die Struktur des Widgets kennen, beginnen wir mit der Erstellung. Ein Widget wird durch Aufrufen erstellt $ .widget () mit dem Namen des Widgets und einem Objekt, das seine Instanzmethoden enthält. Die genaue API sieht folgendermaßen aus:

jQuery.widget (Name [, Basis], Prototyp)

Im Moment arbeiten wir nur mit Namen und Prototypargumenten. Für das Bulletchart sieht unser grundlegender Widget-Stub wie folgt aus:

 $ .widget ('nt.bulletchart', Optionen: , _create: function () , _destroy: function () , _setOption: function (Schlüssel, Wert) );

Es wird empfohlen, dass Sie immer einen Namen für Ihre Widget-Namen angeben. In diesem Fall verwenden wir 'nt.bulletchart'. Alle jQuery-Benutzeroberflächen-Widgets befinden sich unterui'Namespace. Obwohl wir einen Namensraum für das Widget haben, enthält der Aufruf zum Erstellen eines Widgets für ein Element den Namespace nicht. Um ein Bullet-Diagramm zu erstellen, würden wir einfach anrufen $ ('# elem'). bulletchart ().

Die Instanzeigenschaften werden nach dem Namen des Widgets angegeben. Alle privaten Methoden des Widgets sollten standardmäßig '_' vorangestellt werden. Es gibt einige spezielle Eigenschaften, die von der Widget-Factory erwartet werden. Dazu gehören die Optionen, _erstellen, _zerstören und _setOption.

  • Optionen: Dies sind die Standardoptionen für das Widget
  • _erstellen: Die Widget-Factory ruft diese Methode auf, wenn das Widget zum ersten Mal instanziiert wird. Dies wird verwendet, um das ursprüngliche DOM zu erstellen und Event-Handler anzuhängen.
  • _drin: Nach dem Anruf an _erstellen, die Fabrik ruft an _drin. Dies wird im Allgemeinen verwendet, um das Widget in den Ausgangszustand zurückzusetzen. Wenn ein Widget erstellt wurde, rufen Sie den einfachen Widget-Konstruktor auf, z. $ .bulletchart (), setzt auch das Widget zurück. Das ruft intern an _drin.
  • _setOption: Wird aufgerufen, wenn Sie im Widget eine Option festlegen, mit einem Aufruf wie: $ ('# elem'). bulletchart ('Option', 'Größe', 100). Später werden andere Optionen zum Einstellen von Optionen im Widget angezeigt.

Erstellen des Anfangs-DOM mit _erstellen

Unser Bulletchart-Widget wird in der Umgebung zum Leben erweckt _erstellen Methode. Hier bauen wir die Grundstruktur für das Diagramm auf. Das _erstellen Funktion kann unten gesehen werden. Sie werden feststellen, dass hier nicht viel passiert, außer dass Sie den Container der obersten Ebene erstellen. Die eigentliche Erstellung des DOM für Balken, Markierungen und Ticks geschieht im _setOption Methode. Das mag zunächst etwas kontrapunktisch erscheinen, aber es gibt einen triftigen Grund dafür.

 _create: function () this.element.addClass ('bullet-chart'); // Chartcontainer this._container = $ ('
') .appendTo (this.element); this._setOptions ('size': this.options.size, 'ticks': this.options.ticks, 'bars': this.options.bars, 'markers': this.options.markers);

Beachten Sie, dass die Balken, Markierungen und Markierungen auch durch Einstellen von Optionen im Widget geändert werden können. Wenn wir den Code für seine Konstruktion drin behalten _erstellen, wir würden uns innen wiederholen _setOption. Verschieben Sie den Code nach _setOption und ruft es aus auf _erstellen entfernt die Vervielfältigung und zentralisiert die Konstruktion.

Darüber hinaus zeigt der obige Code eine andere Möglichkeit, Optionen im Widget festzulegen. Mit dem _setOptions Methode (beachten Sie den Plural), können Sie mehrere Optionen auf einmal einstellen. Intern führt die Fabrik einzelne Anrufe durch _setOption für jede der Optionen.

Das _setOption Methode

Für das Aufzählungsdiagramm das _setOption Methode ist das Arbeitstier. Es übernimmt die Erstellung von Markierungen, Balken und Häkchen sowie alle an diesen Eigenschaften vorgenommenen Änderungen. Es löscht alle vorhandenen Elemente und erstellt sie basierend auf dem neuen Wert neu.

Das _setOption Die Methode empfängt sowohl den Optionsschlüssel als auch einen Wert als Argumente. Der Schlüssel ist der Name der Option, der einem der Schlüssel in den Standardoptionen entsprechen sollte. Um beispielsweise die Balken im Widget zu ändern, führen Sie den folgenden Aufruf aus:

$ ('# elem'). bulletchart ('option', 'bars', [title: 'New Marker', Wert: 50])

Das _setOption Methode für das Bulletchart sieht so aus:

 _setOption: function (key, value) var self = this, prev = this.options [key], fnMap = 'bars': function () createBars (value, self); , 'Marker': function () createMarkers (value, self); , 'ticks': function () createTickBar (value, self); , 'size': function () self.element.find ('. chart-container') .css ('width', value + '%'); ; // Basis this._super (Schlüssel, Wert); if (key in fnMap) fnMap [key] (); // Feuerereignis this._triggerOptionChanged (key, prev, value); 

Hier erstellen wir einen einfachen Hash des Optionsnamens an die entsprechende Funktion. Mit diesem Hash arbeiten wir nur mit gültigen Optionen und ignorieren unbemerkt ungültige. Hier passiert noch zwei weitere Dinge: ein Anruf an _Super() und feuerte das geänderte Ereignis ab. Wir werden sie später in diesem Artikel betrachten.

Für jede der Optionen, die das DOM ändern, rufen wir eine bestimmte Hilfsmethode auf. Die Hilfsmethoden, createBars, createMarkers und createTickBar werden außerhalb der Eigenschaften der Widget-Instanz angegeben. Dies liegt daran, dass sie für alle Widgets gleich sind und nicht für jede Widgetinstanz einzeln erstellt werden müssen.

// Erstellungsfunktionen function createTickBar (Ticks, Widget) // Bestehendes Widget löschen.container.find ('. Tick-bar'). Remove (); var tickBar = $ ('
'); $ .each (Ticks, Funktion (idx, tick) var t = $ ('
') .css (' links ', Häkchen +'% '); var tl = $ ('
') .css (' links ', Häkchen +'% ') .text (Häkchen); tickBar.append (t); tickBar.append (tl); ); widget._container.append (tickBar); function createMarkers (Markierungen, Widget) // Bestehendes Widget löschen._container.find ('. marker'). remove (); $ .each (Marker, Funktion (idx, m) var marker = $ ('
') .css (left: m.value +'% ') .addClass (m.css) .attr (' marker-index ', idx); widget._container.append (Markierung); ); function createBars (bars, widget) // Bestehendes Widget löschen._container.find ('. bar'). remove (); $ .each (Bars, Funktion (idx, bar) var bar = $ ('
') .css (left: 0, width:' 0% ') .addClass (bar.css) .attr (' bar-index ', idx) .animate (width: bar.value +'% ') ); widget._container.append (bar); );

Alle Erstellungsfunktionen beziehen sich auf Prozentsätze. Dadurch wird sichergestellt, dass das Diagramm gut fließt, wenn Sie die Größe des enthaltenden Elements ändern.

Die Standardoptionen

Wenn beim Erstellen des Widgets keine Optionen angegeben werden, werden die Standardeinstellungen übernommen. Dies ist die Rolle der Optionen Eigentum. Für das Bulletchart sehen unsere Standardoptionen folgendermaßen aus:

 $ .widget ('nt.bulletchart', Optionen: // Prozentsatz: 0 - 100 Größe: 100, // [title: 'Sample Bar', Wert: 75, css: "], bars: [] , // [title: 'Sample Marker', Wert: 50, css: "], Marker: [], // Ticks - Prozentwerte Ticks: [0, 10, 20, 30, 40, 50, 60 , 70, 80, 90, 100],…

Wir beginnen mit einer Größe von 100%, keine Barren und Marker und mit jedem Häkchen 10%. Mit diesen Standardeinstellungen sollte unser Bullet-Diagramm folgendermaßen aussehen:

Bisher haben wir gesehen, wie man das Widget mit erstellt _erstellen und aktualisieren Sie es mit _setOption. Es gibt eine andere Lebenszyklusmethode, die beim Zerstören eines Widgets aufgerufen wird. Dies ist das _zerstören Methode. Wenn du anrufst $ ('# elem'). bulletchart ('destroy'), Die Widget-Factory ruft intern auf _zerstören in Ihrer Widget-Instanz. Das Widget ist dafür verantwortlich, alles, was es in das DOM eingeführt hat, zu entfernen. Dies kann Klassen und andere DOM-Elemente einschließen, die im hinzugefügt wurden _erstellen Methode. Dies ist auch ein guter Ort, um Event-Handler zu lösen. Das _zerstören sollte das genaue Gegenteil von dem sein _erstellen Methode.

Für das Bullet-Chart-Widget das _zerstören ist ganz einfach:

 _destroy: function () this.element.removeClass ('bullet-chart'); this.element.empty (); ,

Unterklassen, Ereignisse und mehr

Unser Bulletchart-Widget ist fast vollständig, bis auf eine letzte Funktion: Legende. Die Legende ist sehr wichtig, da sie den Markierungen und Balken mehr Bedeutung verleiht. In diesem Abschnitt werden wir eine Legende neben dem Diagramm hinzufügen.

Anstatt diese Funktion direkt zum Bulletchart-Widget hinzuzufügen, erstellen wir eine Unterklasse, bulletchart2, das wird die Legende unterstützen. Dabei werden wir auch einige interessante Features der Widget Factory-Vererbung betrachten.

Legende hinzufügen

Die Widget Factory unterstützt die Unterklassen eines Widgets, um speziellere Versionen zu erstellen. Früher in diesem Artikel haben wir die API für gesehen $ .widget (), was drei Argumente hatte:

jQuery.widget (Name [, Basis], Prototyp)

Mit dem zweiten Parameter können wir eine Basisklasse für unser Widget auswählen. Unsere bulletchart2 Widget, welche Unterklassen Bulletchart, wird folgende Unterschrift haben:

 $ .widget ('nt.bulletchart2', $ .nt.bulletchart, Optionen: // Legende anzeigen / ausblenden: true) // sorgt dafür, dass wir denselben Namespace wie das Basis-WidgetEventPrefix: $ .nt.bulletchart beibehalten .prototype.widgetEventPrefix, _create: function () …, _destroy: function () …, _setOption: function (Schlüssel, Wert) …)

Hier gibt es einige interessante Dinge zu beachten:

  • Wir benennen weiterhin unseren Widget-Namen: nt.bulletchart2.
  • Die Widget-Factory setzt das Widget automatisch unter $ .nt Namespace. Um auf unser vorheriges Widget zu verweisen, haben wir verwendet $ .nt.bulletchart. Wenn wir eines der standardmäßigen jQuery-Benutzeroberflächen-Widgets in eine Unterklasse unterteilen würden, würden wir sie ebenfalls mit referenzieren $ .ui.widget-name
  • Das widgetEventPrefix ist eine neue Eigenschaft, die wir noch nicht gesehen haben. Wir werden darauf eingehen, wenn wir über Ereignisse sprechen. Der Rest der Instanzeigenschaften sollte bekannt sein.

Da wir mit der Legende mehr DOM-Elemente hinzufügen, müssen wir die _erstellen Methode. Dies bedeutet auch, dass wir überschreiben müssen _zerstören, um symmetrisch zu sein.

 _create: function () var self = this; this._legend = $ ('
') .appendTo (this.element);… // Basis anrufen this._super (); this._setOption ('legend', this.options.legend); , _destroy: function () this.element.find ('. legend'). empty ();… this._super (); ,

Hier sehen wir wieder das gleiche Muster wie zuvor _erstellen Methode. Wir erstellen den Container für die Legende und rufen dann an _setOption den Rest der Legende bauen. Da überschreiben wir die _erstellen, Wir müssen sicherstellen, dass wir die Basis anrufen _erstellen. Wir machen das mit dem Anruf an _Super. In ähnlicher Weise in _zerstören, Wir sehen auch den Anruf an _Super.

Nun fragen Sie sich vielleicht: Woher weiß das Widget, welche Supermethode mit einer einfachen, unqualifizierten Methode aufgerufen werden soll? _Super Aufruf? Die Intelligenz dafür liegt im Inneren der Widget-Fabrik. Wenn ein Widget untergeordnet ist, richtet die Factory die _Super verweisen für jede Instanzfunktion unterschiedlich. Also, wenn du anrufst _Super Von Ihrer Instanzmethode zeigt es immer auf die richtige _Super Methode.

Ereignisbenachrichtigungen

Da das Bulletchart das Ändern von Markierungen und Balken unterstützt, muss die Legende mit diesen Änderungen synchron sein. Darüber hinaus unterstützen wir auch das Umschalten der Sichtbarkeit von Markierungen und Balken durch Klicken auf die Legendenelemente. Dies ist nützlich, wenn Sie mehrere Marker und Balken haben. Indem Sie einige Elemente ausblenden, können Sie die anderen klarer sehen.

Um die Synchronisierung der Legende mit den Änderungen an Markierungen und Balken zu unterstützen, klicken Sie auf bulletchart2 Das Widget muss alle Änderungen an diesen Eigenschaften überwachen. Die Basis-Bulletchart löst bereits bei jeder Änderung ihrer Optionen ein Änderungsereignis aus. Hier ist der entsprechende Ausschnitt aus dem Basis-Widget:

 _setOption: Funktion (Schlüssel, Wert) var self = this, prev = this.options [key];… // base this._super (key, value); if (key in fnMap) fnMap [key] (); // Feuerereignis this._triggerOptionChanged (key, prev, value); , _triggerOptionChanged: function (optionKey, previousValue, currentValue) this._trigger ('setOption', Typ: 'setOption', Option: optionKey, previous: previousValue); 

Immer wenn eine Option eingestellt ist, wird die setOption Ereignis wird ausgelöst. Die Ereignisdaten enthalten den vorherigen und neuen Wert für die Option, die geändert wurde.

Durch Abhören dieses Ereignisses im untergeordneten Widget können Sie feststellen, wann sich die Markierungen oder Balken ändern. Das bulletchart2 Widget abonniert dieses Ereignis in seiner _erstellen Methode. Das Abonnieren von Widgets-Ereignissen wird mit dem Aufruf an erreicht this.element.on (). this.element verweist auf das jQuery-Element, auf dem das Widget instanziiert wurde. Da das Ereignis auf dem Element ausgelöst wird, muss unser Ereignisabonnement darauf erfolgen.

 _create: function () var self = this; this._legend = $ ('
') .appendTo (this.element);… // Legende auf Änderungen an Markierungen und Balken anwenden this.element.on (' bulletchart: setoption ', Funktion (Ereignis, Daten) if (data.option ===' - Markierungen ') createLegend (data.current, self.options.bars, self); else if (data.option ===' bars ') createLegend (self.options.markers, data.current, self); ); // Die Basis aufrufen this._super (); this._setOption ('legend', this.options.legend);

Notieren Sie sich den Ereignisnamen, der zum Abonnieren verwendet wird: 'bulletchart: setoption'. Als Richtlinie fügt die Widget-Factory ein Ereignispräfix für Ereignisse hinzu, die vom Widget ausgelöst werden. Standardmäßig ist dieses Präfix der Name des Widgets, dies kann jedoch leicht mit dem Symbol geändert werden widgetEventPrefix Eigentum. Das Basis-Bulletchart-Widget ändert dies in 'bulletchart:'.

$ .widget ('nt.bulletchart', Optionen: …, widgetEventPrefix: 'bulletchart:'…);

Wir müssen auch abonnieren 'klicken' Ereignisse auf den Legendenelementen, um die entsprechende Markierung / Leiste auszublenden / anzuzeigen. Wir machen das mit dem _auf Methode. Diese Methode nimmt einen Hash der Ereignissignatur an die Handlerfunktion. Der Handler-Kontext (diese) ist korrekt auf die Widget-Instanz gesetzt. Ein weiterer Komfort mit _auf ist, dass die Widget-Factory die Ereignisse bei der Zerstörung automatisch aufhebt.

 _create: function () … // Klickt auf die Legendenelemente this._on ('click.legend-item'): function (event) var elt = $ (event.currentTarget), item = elt.data ('chart-item'), Selector = '[' + item.type + '-index =' + item.index + ']'; this.element.find (Selector) .fadeToggle (); elt.toggleClass (' verblassen');  );… 

Mehr Tipps

Die Widget-Factory enthält ein paar weitere Kleinigkeiten, die Sie kennen sollten.

Verweis auf die Widget-Instanz

Bisher haben wir nur eine Möglichkeit gesehen, Methoden im Widget aufzurufen. Wir haben das mit gemacht $ ('# elem) .bulletchart (' Methodenname '). Dies erlaubt jedoch nur das Aufrufen von öffentlichen Methoden wie 'Option', 'Zerstören', 'Ein', 'Aus'. Wenn Sie diese Methoden direkt in der Widget-Instanz aufrufen möchten, gibt es eine Möglichkeit, dies zu tun. Die Widget-Factory fügt die Widget-Instanz an die an Daten() Objekt des Elements. Sie können diese Instanz wie folgt erhalten:

var widget = $ ('# elem'). data ('bulletchart'); widget.destroy ();

Wenn Sie alle Bulletchart-Widgets auf der Seite abrufen möchten, gibt es außerdem eine Auswahlmöglichkeit dafür:

var allCharts = $ (': nt-bulletchart');

Einige spezielle Methoden

Es gibt einige spezielle Methoden, die Sie kennen sollten und die weniger häufig verwendet werden: _getCreateEventData () und _getCreateOptions (). Ersteres wird zum Anhängen von Ereignisdaten für das 'create' -Ereignis verwendet, das nach Beendigung des Aufrufs an ausgelöst wird _erstellen.

_getCreateOptions dient zum Anhängen zusätzlicher Standardoptionen für das Widget oder zum Überschreiben vorhandener Optionen. Die vom Benutzer bereitgestellten Optionen überschreiben die von dieser Methode zurückgegebenen Optionen, wodurch wiederum die Standardoptionen des Widgets überschrieben werden.


Zusammenfassung

Das ist ein Wrap! Wenn Sie weiter erforschen möchten, sollten Sie mit den folgenden Referenzen gut zurechtkommen. Natürlich ist die beste Informationsquelle immer der Quellcode selbst. Ich würde gerne die Quelle jquery.ui.widget auf GitHub lesen.

  • JQueryUI Widget Factory-API
  • Folien auf Widget Factory