The Terrific Way Of JavaScript

Wie im „letzten Post“:https://blog.namics.com/2010/07/terrific-oocss-part2.html veranschaulicht, setzt Terrific im HTML/CSS Part voll auf „OOCSS“:http://wiki.github.com/stubbornella/oocss. In Sachen JavaScript beschreitet Terrific jedoch völlig eigene Wege.

Was bringt’s?

Die Hauptvorteile des JavaScript Systems von Terrific sind:

Leichtgewichtige Architektur
Terrific strukturiert die JavaScript-Entwicklung ohne dabei die Entwickler einzuschränken. So können Entwickler weiterhin ihr gesamtes „jQuery“:http://www.jquery.com – Knowhow voll einsetzen und profitieren gleichzeitig von den zahlreichen Features und Möglichkeiten von Terrific.

Modulare Entwicklung
Die gesamte JavaScript-Entwicklung wird durch Terrific modularisiert. So können sämtliche „Module“:http://blog.namics.com/2010/06/terrific-part1.html einzeln entwickelt und getestet werden und – was noch viel wichtiger ist – ohne Seiteneffekte miteinander kombiniert werden.

Skalierbarkeit
Die Seite wird mit wachsender JavaScript-Grösse nicht durch unzählige DOM-Operationen und Events verlangsamt. Es wird wirklich nur der Code ausgeführt, welcher wirklich von den Terrific-Komponenten benötigt wird.

Einfache Integration
Mit Terrific entwickelte Frontends lassen sich mühelos in die verschiedensten Backendsysteme und CMS integrieren. So kann die Frontendentwicklung komplett vom entsprechenden Zielsystem entkoppelt werden.

Wie haben wir es gemacht?

Wie schon im „ersten Post dieser Serie“:http://blog.namics.com/2010/06/terrific-part1.html erwähnt, nutzt Terrific die „OOCSS-Namenskonventionen“:http://blog.namics.com/2010/07/terrific-oocss-part2.html technologieübergreifend sowohl für den HTML/CSS Part als auch für den JavaScript Part.
Dies erlaubt es Terrific, einen einheitlichen Bootstrapping-Mechanismus zu verwenden – egal ob es sich dabei um einfache Seiten mit wenig JavaScript-Funktionalität oder komplexe Applikationen handelt.

(function($) {
    var application = new Nx.Application($('.page'));
    application.registerModules();
    application.startAll();
})(Nx.$);

That’s it! Abgesehen von dem „Drumherum“ – ein klassischer 3-Zeiler ;-)

Die einzelnen Zeilen haben es jedoch ganz schön in sich.

var application = new Nx.Application($('.page'));

Diese Zeile instanziert eine neue Terrific-Application. Was auffällt ist, dass Terrific den „Namespace“:http://docs.jquery.com/Using_jQuery_with_Other_Libraries Nx (für Namics) verwendet. So kann Terrific auch parallel zu bestehenden oder durch das Backendsystem vorgegebenen JavaScript-Funktionalitäten verwendet werden.
Der Parameter $(‚.page‘) gibt den Context der Applikation an – .page ist nach OOCSS-Konvention der Seitencontainer.

application.registerModules();

registerModules übernimmt den Hauptteil des Bootstraps. Die Methode durchsucht den DOM-Tree nach Modulen – nach OOCSS-Konvention besitzen sämtliche Module die Klasse .mod – und instanziert per Namenskonvention die entsprechenden Module. Zum Beispiel wird für die Klasse .modNews das JavaScript Modul Nx.Module.News instanziert.

Als Pendant zu den OOCSS-Skins bietet Terrific JavaScript-Skins an – welche im Grunde nichts anderes als Module „Decorators“:http://en.wikipedia.org/wiki/Decorator_pattern#JavaScript sind.
Auch die Dekoration der Module geschieht – wie könnte es auch anders sein – per OOCSS-Namenskonvention. Besitzt ein DOM-Node die Skin-Klasse .skinNewsHighlighted so wird das Nx.Module.News Modul mit dem Nx.Module.News.Highlighted Skin dekoriert.

Um eine Kommunikation zwischen den Modulen zu ermöglichen – ohne mit dem „Loose Coupling“:http://en.wikipedia.org/wiki/Loose_coupling Gedanken zu brechen – werden in der registerModules-Methode auch noch per Namenskonvention definierte Kommunikationskanäle zwischen den Modulen aufgebaut.

Nachdem also alle Module inkl. Skins und Connectors in der Application registriert sind, kommt der Bootstrap in die letzte Phase.

application.startAll();

Mit startAll wird die Initialisierung der Module gestartet. Jedes Modul durchläuft dabei potentiell vier Phasen, welche nach Bedarf durch die entsprechende „Hook-Methode“:http://de.wikipedia.org/wiki/Schablonenmethode implementiert werden können.

  • dependencies – Nachladen von Libraries, Plugins etc. via Ajax
  • beforeBinding – Daten per Ajax holen, DOM Manipulationen etc.
  • onBinding – Events binden
  • afterBinding – Default State herstellen, Events triggern etc.

In den häufigsten Fällen werden jedoch nicht alle Phasen, sondern nur die onBinding-Phase benötigt. Terrific kümmert sich dabei um das Timing und die sequentielle Abarbeitung der vier Module-Phasen.

Beispiel gefällig?

Greifen wir das Modul-Beispiel aus dem „letzten Post“:“http://blog.namics.com/2010/07/terrific-oocss-part2.html wieder auf.

2131-Terrific-Module.png

Das Currency Converter Module hat folgende Funktionalitäten:

  • Ajax Live-Convertion
  • Non-JavaScript Variante mit Convert Button
  • Automatische Erstberechnung des aktuellen Werts

dependencies

Da nicht nach jedem Tastendruck eine Ajax-Berechnung ausgelöst werden soll, sondern nur sobald der Benutzer aufhört zu tippen, benötigen wir das „jQuery throttle / debounce Plugin“:http://benalman.com/code/projects/jquery-throttle-debounce/docs/files/jquery-ba-throttle-debounce-js.html von „Ben Alman“:http://benalman.com/.

/**
 * Hook function to load the module specific dependencies.
 *
 * @method dependencies
 * @return void
*/
dependencies: function() {
    this.require('jquery.throttle-debounce.min.js', 'plugin', 'onBinding');
}

Der dritte Parameter – in unserem Beispiel „onBinding“ – gibt an, in welcher Phase die dependency benötigt wird. Terrific kümmert sich um das Timing und die entsprechenden Callbacks. Zudem stellt Terrific sicher, dass von mehreren Modulen benötigte dependencies nicht doppelt nachgeladen werden.

beforeBinding

Alternativ zur Live-Convertion bietet die Non-JavaScript Variante einen zusätzlichen Convert Button. Dieser kann in der JavaScript Variante versteckt werden. DOM Manipulationen werden – um unnötiges Flackern zu vermeiden – in der beforeBinding-Phase durchgeführt.

/**
 * Hook function to do module specific stuff before binding the events (i.e. fetching some data).
 *
 * @method beforeBinding
 * @param {Function} callback the callback function which must be called at the end
 * @return void
 */
beforeBinding: function(callback) {
    $(':submit', this.$ctx).hide();
    callback();
}

Durch die Verwendung von this.$ctx (this.$ctx enthält den Module-DOM-Node) als zweiten Parameter im jQuery-Selector, werden die Events nur auf die aktuelle Modulinstanz gebunden. So können Module also auch problemlos mehrmals auf einer Seite verwendet werden.

onBinding

In der onBinding-Phase werden die Events gebunden.

/**
 * Hook function to bind the module specific events.
 *
 * @method onBinding
 * @return void
*/
onBinding: function() {
    var that = this;

    // disable the standard action on submit
    $('.converter', this.$ctx).bind('submit', function() {
       return false;
    });

    // bind the keyup event to start the convertion. To reduce the number
    // of ajax calls, the debounce plugin is used.
    $('.amount', this.$ctx).keyup($.debounce(250, function() {
        var $this = $(this).closest('form');
        var url = $this.attr('action') + '?' + $this.serialize();
        // ajax stuff etc.
        ...
        return false;
    }));
}

In unserem Beispiel wird durch return false – da die Live-Convertion nicht per Enter, sondern automatisch nach Beendigung der Eingabe ausgelöst werden soll – die Standard-Submitaktion unterbunden.

Im keyup-Eventhandler kommt das in der dependencies-Phase nachgeladene debounce-Plugin zum Einsatz. Dadurch kann die Anzahl Ajax-Requests stark reduziert werden, da die Berechnung erst nach 250ms Idle-Time ausgelöst wird.

afterBinding

Damit dem Benutzer gleich zu Beginn eine aktuelle Berechnung präsentiert werden kann – zum Beispiel der aktuelle Eurokurs – wird in der afterBinding-Phase die Initialberechnung ausgelöst.

/**
 * Hook function to do module specific stuff after binding the events (i.e. triggering some events).
 *
 * @method afterBinding
 * @return void
 */
afterBinding: function() {
    $('.amount', this.$ctx).trigger('keyup');
}

Was kann Terrific sonst noch?

Obwohl die Modul-Funktionalität den Hauptpart des Terrific JavaScript Systems darstellt, hat Terrific noch zahlreiche weitere JavaScript Features zu bieten, die das Programmiererleben erheblich erleichtern. Einige der Funktionen, die Terrific mit sich bringt:

  • Skins – Module Decorators
  • Layouts – seitenweite Funktionalitäten, z.B. Drag’n Drop von Modulen etc.
  • Connectors – ermöglichen die Kommunikation zwischen Modulen über konfigurierbare Kanäle
  • Sandbox – Bezug von Ressourcen, Zugriff auf andere Modulinstanzen etc.
  • Logging-Architektur
  • Zentrales Errorhandling

Die Terrific-Funktionalitäten sind also ziemlich umfassend ;-). Bis jetzt konnten wir alle Kundenwünsche mit den Bordmitteln von Terrific umsetzen. Neue, anspruchsvolle und herausfordernde Frontends sind also herzlich willkommen!

Real World Beispiele?

Das „Intranet von Repower“:http://www.namics.com/taten/neues-intranet-repower/ wurde komplett mit Terrific umgesetzt. Integriert wurde das Ganze in das Enterprise Wiki „Atlassian Confluence“:http://www.atlassian.com/software/confluence/. Wiki? Anspruchvolles Frontend? Wie man dies unter einen Hut bringen kann, zeigen wir im nächsten Terrific-Post!

h4. Weitere Terrific Informationen

Open Source Projekt: Terrific und TerrificJS

Terrific – Modulare Frontendentwicklung
Terrific und OOCSS
The Terrific Way Of JavaScript
Terrific im Projekprozess

Hinterlasse eine Antwort

Deine E-Mail-Adresse wird nicht veröffentlicht. Erforderliche Felder sind markiert *

*

*

Du kannst folgende HTML-Tags benutzen: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <s> <strike> <strong>