jQuery Europe 2013, Tag 1

jqconfeu13

Am 20 bis 22. Februar fand der europäische Ableger der jQuery Conference statt. Als Austragungsort wurde das verschneite Wien gewählt; und mit dem Palais Liechtenstein ein würdiger Veranstaltungsort gefunden (siehe Bilder unten). Rund 400 Besucher trafen sich in Österreich um sich an einem … Weiterlesen

Liferay Europe Symposium 2011 – Ein Überblick

Am 18. und 19. Oktober wurde im Sheraton Hotel in Offenbach bei Frankfurt das vierte Liferay Europe Symposium ausgetragen. In zahlreichen Vorträgen und Workshops wurden die Highlights des kommenden Liferay Releases 6.1 vorgestellt und anhand von Showcases die Einsatzmöglichkeiten des Systems in Unternehmen vorgestellt.

Im Jahr 2000 von Brian Chan zunächst als Enterprise Portal-Lösung für Non-Profit -Organisationen erdacht hat sich Liferay über die Jahre zu einer festen Größe im Bereich der Enterprise Web-Portale entwickelt. Liferay spielt heute in einer Liga mit Portal-Lösungen von SAP oder IBM und wird weltweit von vielen namenhaften Unternehmen, wie Volkswagen, Lufthansa, Liebherr, Duden, T-Mobile oder Vodafone für Inter- und Intranetlösungen eingesetzt. Als einzige Open-Source-Alternative wird Liferay im Gartner Report „Magic Quadrant for Horizontal Portal Products“ im September 2010 als eine der führenden Portal-Lösungen gesehen.

Auch Namics erhält von Kunden vermehrt Anfragen nach Portal- und Kollaborations-Lösungen, sodass das diesjährige Liferay Symposium zum Anlass genommen wurde, um sich ein genaueres Bild vom Produkt zu verschaffen und mögliche Einsatzszenarien für Namics zu ergründen. Mit unserem Head of Technology Sven Niedner und mir waren an den beiden Tagen des Symposiums zwei Namics Mitarbeiter vor Ort. Mit insgesamt über 300 Teilnehmern aus ganz Europa war das Symposium sehr gut besucht und ermöglichte uns bei ungezwungener Atmosphäre mit zahlreichen Teilnehmern, aber auch Mitarbeitern von Liferay in Kontakt zu treten.

Im Folgenden möchte ich die Highlights des in den kommenden Monaten erscheinenden Liferay Releases 6.1 kurz vorstellen.

Liferay Allgemein

Liferay baut auf dem Java Portlet Standard JSR-286 auf und kann daher sehr leicht mit Hilfe von Java Portlets um neue Funktionen erweitert werden. Mit dem Liferay Marketplace wird ein Appstore geschaffen, der es Entwicklern ermöglicht eigene Portlets unkompliziert und auf einer zentralen Plattform zu vertreiben.

Für Redakteure wird das UI optimiert. Mit Drag & Drop Unterstützung an verschiedenen Stellen, Formulareditoren sowie einem komfortablen graphischen Workflow Editor (gestattet auch die Anbindung externer Workflow Engines) können viele Aufgaben wesentlich einfacher erledigt werden.

Dank dem Versionierungssystem von Liferay können sehr leicht unterschiedliche Versionen einzelner Seiten oder gar Branches von ganzen Auftritten erstellt werden und nach wunsch zeitgesteuert ausgespielt werden (z.B. Weihnachts- oder Oster-Versionen des Webauftritts).
In der neusten Version verfügt Liferay standardmäßig über eine WURFL gesteuerte Endgeräteerkennung, so dass sehr leicht für die unterschiedlichsten Endgeräte optimierte Seiten ausgespielt werden können.
Auch die in Liferay integrierte Lucene basierte Suche wird überarbeitet. Sie unterstützt ab sofort facettierte Suchen
In der neuen Version verfügt Liferay Die Lucene basierte Suche innerhalb von Liferay wird um die Möglichkeit einer facettierten Suche und einer Integration das Liferay eigenen Tagging-System erweitert.

Liferay Web CMS

Das Liferay Web CMS wird als die populärste Java Web Content Management Lösungen gezählt. In der neusten Version bietet es frei konfigurierbare Redakteursformulare, mit dem Asset Publisher eine Möglichkeit zur Erstellung unterschiedlicher Sichten auf Daten sowie ein komplett neues UI zur Definition von Kategorien und Vokabularen. Alle Inhalte im CMS können auf einfachste Art und Weise lokalisiert werden, wobei für jedes Contentelement eine Defaultsprache festgelegt werden kann.
Alle Webinhalte können um Kommentar- und Bewertungsfunktionen erweitert und sehr leicht mit anderen Inhalten verknüpft (z.B. Autoren mit ihren Büchern und umgekehrt) werden

Liferay als Social Collaboration System

Die ohnehin bereits sehr umfangreichen Kollaborationsmöglichkeiten werden konsequent erweitert. Foren, Blogs und Wikis werden um umfangreiche WYSIWYG Editoren ergänzt sowie allgemein die Social Sharing Funktionen optimiert.
Liferay befolgt den Open Social Standard 1.1 und kann daher problemlos mit den Unterschiedlichen großen Sozialen Netzwerken interagieren und Informationen austauschen.

Liferays Dokument- und Medienverwaltung

Mit dem kommenden Liferay Release werden die zuvor als separate Einheit betriebene Dokument- und Medienverwaltung unter der „Documents and Media Library“ vereint. Hierfür wurde ein komplett neues UI geschaffen und dieses damit sehr stark an native Dateiexplorer angeglichen. Die Benutzeroberfläche ist komplett Ajax basiert, bietet aber dennoch eine vollständige Unterstützung der Browser History (Zurück- und Vorwärts-Button), was insbesondere für das Bookmarking einzelner Verzeichnisse sehr hilfreich ist.

Die neue Dokument- und Medienverwaltung bietet vollständigen Drag & Drop Support und erlaubt dabei sowohl die Auswahl einzelner als auch mehrerer Dateien. Die Metadaten sämtlicher Dateien werden beim Hochladen automatisiert extrahiert und können zudem sehr leicht um eigene Metadaten erweitert werden. Jede Datei kann weiterhin mit Tags versehen und in Kategorien eingeordnet sowie mit unterschiedlichen Zugriffsberechtigungen versehen werden.

Ein meiner Meinung nach sehr cooles Feature ist die automatisierte Umwandlung von textuellen Inhalten der verschiedensten Formate in PDFs. Auf diese Weise können von nahezu allen hochgeladenen Dateien Vorschauversionen angeboten werden. Ein ähnliches Feature wird für Video Dateien angeboten. Diese werden automatisiert in Flashvideos umgewandelt.

Die Medien in Liferay müssen nicht zwingend direkt in Liferay abgelegt werden, sondern können auch in einem bereits im Unternehmen vorhandenen Content Repository verbleiben. Als CMIS 1.0 Consumer können zahlreiche externe DMS (Alfresco, FileNet, Nuxeo, etc.) sehr leicht angebunden werden. Aber auch proprietäre Systeme, wie SharePoint oder Documentum, können vergleichsweise einfach integriert werden.
Ein Highlight stellt zudem Liferay Sync dar. Vergleichbar mit Dropbox ist hierüber eine komfortable Synchronisation der Daten der Dokument- und Medienverwaltung mit dem Clientrechner oder dem Smartphone (iPhone, Adroid) möglich.

Fazit

Das Liferay Symposium war sehr interessant und konnte uns zahlreiche interessante Einblicke in das System und dessen mögliche Einsatzszenarien geben. Alles in allem herrschte an beiden Tagen eine sehr entspannte Atmosphäre und wir konnten mit zahlreichen Entwicklern, Produktverantwortlichen sowie Firmenvertretern in Kontakt treten. Bei weiteren Fragen könnt ihr euch gerne an mich oder Sven Niedner wenden. Sobald uns die Slides zur Verfügung stehen, werde ich diese hier noch veröffentlichen.

Flexible & erweiterbare jQuery Plugins

jQuery ist ein mächtiges Framework welches das Arbeiten mit JavaScript stark erleichtert. Mittlerweile ist jQuery mit Abstand das verbreitetste JavaScript Framework der Welt. Ganze UI-Elemente wie Tabs, oder Funktionsblöcke wie etwa eine Bildergalerie sucht man jedoch – bei jQuery selber – vergeblich. jQuery stellt lediglich zahlreiche mehr oder minder kleine Helfer zur Verfügung, welche es ermöglichen, solche Dinge mit geringem Aufwand zu erstellen.

Nun ist es natürlich nicht praktisch komplexe Funktionen wieder und wieder – und für jedes Projekt neu – zu schreiben. Hier kommen die „jQuery Plugins“ ins Spiel. Ein jQuery Plugin ist in der Regel eine Erweiterung von jQuery und kann beliebig komplexe Funktionen – von History Handling über UI-Elemente bis zu Lightboxen – bereitstellen.

Aufbau eines Plugins

Die jQuery Plugin API dient dazu, jQuery um neue Funktionen zu erweitern:

// jQuery um Tab Funktion erweitern:
$.fn.tabsPlugin = function(userOptions) {
   // Plugin Code...
}

Plugins sind meist sehr ähnlich aufgebaut. Sie werden in der Regel auf ein Set von HTML Elementen angewendet und man kann das Verhalten des Plugins mit Optionen etwas beeinflussen. In etwa so:

var options = {
     activeTab: 2
};
$('div.tabs').tabsPlugin(options);

Damit würde man etwas HTML Code…
2307-html Code.png

…in ein Modul verwandeln das etwa wie folgt aussieht:
2306-Tabs-thumb-500x83-2305.png

Das Plugin hat dabei meist eigene Optionen, sogenannte Defaults. Diese werden durch die Optionen, welche der Benutzer dem Plugin beim Aufruf mitgegeben hat ergänzt:

var options = $.extend({}, $.fn.tabsPlugin.defaults, userOptions);

Innerhalb des Plugins, wird danach die entsprechende Plugin-Funktion auf jedem einzelnen der übergebenen Elemente ausgeführt. Dabei muss darauf geachtet werden, dass die Funktion nur auf das jeweilige Element Einfluss hat, damit mehrere Elemente auf der Seite die gleiche Funktionalität haben können.

var $tabSets = $(this);
$tabSets.each(function(){
     // Auf jedem Element die gewünschte Funktion ausführen
     var $tabSet = $(this); // Aktuelles Tab-Set
     ...
});

Nun soll’s ein bisschen anders sein…

Ein Problem vieler Plugins ist, dass sie zwar meist ihre Aufgabe gut erledigen, nicht selten auch viele Optionen mitbringen, aber nicht flexibel oder erweiterbar sind. Nehmen wir ein Plugin, das aus einem Set an HTML Elementen ein Tab-UI generieren soll. Dieses Plugin übernimmt das Sammeln der Tabs und zugehörigen Panels, sowie das Ein- und Ausblenden der Panels beim Klick auf ein Tab. Ausserdem bringt es noch einige Optionen mit, womit der Benutzer festlegen kann, welche Klassen die ausgewählten Tabs haben sollen und welches Tab zu Beginn aktiviert werden soll. Ist doch Perfekt, nicht?

Was nun, wenn der Inhalt des Panels beim Aufruf der Seite noch nicht vorhanden ist sondern erst nachgeladen werden soll, wenn man das entsprechende Tab aktiviert? Herkömmliche Plugins versagen hier oft und gewünschte Funktionalität muss direkt im Plugin eingefügt werden. Dabei geht die Update-Fähigkeit verloren und es leidet die Wiederverwendbarkeit und Sicherheit des Projekts. Im Wissen, dass der Benutzer vielleicht mit dem Plugin noch weiter Anwendungsfälle hat neigt der Autor des Plugins dazu, möglichst viele Funktionen in sein Plugin zu stecken, da er es ja flexibel halten möchte. Damit wird es gross, schwerfällig und unübersichtlich und verfügt über eine Menge Funktionen, welche viele unter Umständen gar nicht brauchen. Der Autor des besagten Tab-Plugins muss dabei an Tastatur-Bedienbarkeit, Ajax- und History-Fähigkeit sowie vieles mehr denken.

Evented jQuery Plugins = flexibel & erweiterbar

Eine Lösung für dieses Problem lautet Custom Events oder kürzer – Evented. Dabei muss sich der Plugin Autor überlegen, welche grundlegende Funktionen das Plugin benötigt und stellt diese in einer möglichst schlichten Form zur Verfügung.

Ein Tab-UI-Element hat im Grossen und Ganzen eine Funktion: Beim Klick auf ein Tab, soll das zugehörige Panel aktiviert und alle anderen deaktiviert werden. Wir brauchen also eine „activate“ Funktion. Ausserdem müssen zu Beginn alle Tabs gesucht, und die zugehörigen Panels gespeichert werden. Dazu benötigen wir eine „setupTabs“ Funktion. Des weiteren sollten die Panels wissen, zu welchem Tab sie gehören: „setupPanels„. Beim Aufruf der Seite sollen diese beiden Funktionen ausgeführt werden und das erste Tab aktiviert werden, dazu brauchen wir noch eine letzte Funktion, die „initialize“ Funktion.

Diese Funktionen sind „Events“. Jedes übergebene Set an HTML Elementen wird mit diesen Events versehen. Da der Event damit immer zu einem Tab-Element gehört, kann damit auch das Problem von allfälligen Konflikten mit anderen Tab-Elementen einfach gelöst werden. Wenn auf einer Seite zwei Tab-Elemente vorhanden sind, beeinfluss Tab-Verbund eins den zweiten Tab-Verbund nicht, wenn darauf der activate Event ausgeführt wird:

...
$tabSets.bind("activate",
        function(e, selected) {
            // selektiertes Tab aktivieren
        }
);
...

Events nach Aussen verfügbar machen

Der Trick besteht nun darin, dass diese Funktionen nicht einfach fest in das Plugin integriert sind, sondern das jede einzelne Funktion in ein Array gepackt wird, welches über ein Objekt customEvents von aussen Zugänglich ist. Die Funktions-Array können dadurch ergänzt, oder gar ganz überschrieben werden, bevor das Plugin auf ein Set von HTML Elementen angewendet wird.

var customEvents = {
    initialize: [function(options) {
        this.bind("initialize." + options.namespace,
        function(e) {
            // Tabs und Panels vorbereiten
            //und erstes Tab Aktivieren
        });
    }],

    setupPanels: [function(options) {
        this.bind("setupPanels." + options.namespace,
        function(e) {
            // Panels mit zugehörigem Tab verbinden
        });
    }],

    setupTabs: [function(options) {
        this.bind("setupTabs." + options.namespace,
        function(e) {
            // Tabs suchen und activate Funktion bei klick ausführen
        });
    }],

    activate: [function(options) {
        this.bind("activate." + options.namespace,
        function(e, selected) {
            // Alle Tabs deaktivieren und selektiertes
            // Tab und Panel aktivieren
        });
    }]
};

Events ergänzen

Im unserem Beispiel wollten wir, dass der Inhalt des Panels erst vom Server geladen wird, wenn das Tab aktiviert wird. Die Vorgehensweise ist nun denkbar einfach, man fügt einfach vor der Plugin-Standard-Funktion eine neue Funktion hinzu, welche den Inhalt des Panels via Ajax vom Server lädt. Dabei muss man zu keiner Zeit das Plugin selber verändern. Wenn der Plugin Autor ein Bug-Fix veröffentlich, kann das Plugin einfach aktualisiert werden – die Grundfunktionen werden die gleichen bleiben und die Erweiterung wird nicht tangiert da sie sich ausserhalb des Plugins befindet.

// Neue Funktion vor die bestehende
// activate Funktion schieben:
customEvents.activate.unshift( function(options) {
    // Die Erweiterung auf das Grund-Element
    // (nicht die einzelnen Tabs) binden:
    this.bind("activate." + options.namespace,
        function(e, selectedTab) {
            // Den Inhalt des Tabs hier
            // per Ajax in das Panel laden:
            var url= selectedTab.href;
            $(selected).data('$panel').load(url);
   });
});

Der Kern des Plugins ist dabei lediglich dafür verantwortlich, dass die Default Einstellungen mit den Benutzer-Optionen ergänzt werden und dass danach alle Tab-Elemente die Custom Events erhalten.

Hello World!

Nachdem man dieses erweiterbare und flexible Tabs-Plugin geschrieben hat, ist es natürlich schön, wenn sich der Rest der Welt auch daran erfreuen kann. In meinem nächsten Post werde ich zeigen, wo und wie man ein eigenes Plugin veröffentlichen kann und was dabei zu beachten ist.