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:
Lassen Sie uns diese API näher untersuchen, während wir ein einfaches Bullet-Chart-Widget erstellen.
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 Linie0255075100
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.
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
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.
_setOption
MethodeFü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.
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 (); ,
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.
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:
nt.bulletchart2
.$ .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
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.
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'); );…
Die Widget-Factory enthält ein paar weitere Kleinigkeiten, die Sie kennen sollten.
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');
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.
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.