Seit kurzer Zeit gibt es ein JavaScript-API, mit welchem man Vibrationen von mobilen Geräten im Browser steuern kann. Um den Umgang mit dem API intuitiver zu gestalten, habe ich einen Navigator.Vibrate-Wrapper namens Burp.js geschrieben. Dieser funktioniert folgendermaßen:

Burp('*·*·*·**-**', 200);

Die Burp-Funktion nimmt zwei Parameter entgegen: Einen String, welcher den Rhythmus der Vibration steuert. Sternchen bilden dabei Vibrationen, Punkte (Middle Dot) sind kurze Unterbrechungen und Bindestriche Pausen, welche die gleiche Länge wie die Vibrationen haben. Mehrere Vibrationen bzw. Pausen hintereinander werden addiert.

Der zweite, optionale Parameter gibt in Millisekunden an, wie lang die Vibrationen und Pausen sein sollen. Der Default-Wert ist 300ms.

Hier gibt es eine Demo dazu …

Das ganze wird theoretisch vom mobilen Firefox, dem Android-Browser und dem mobilen Chrome unterstützt. Praktisch zum Laufen bekommen habe ich es jedoch nur im Mobile Firefox. Man wird sehen, wie es sich entwickelt. Für mehr Informationen empfehle ich den Beitrag auf MDN dazu.

Responsive Webdesign (kurz: RWD) kann man getrost als old News bezeichnen und mittlerweile weiß jeder, worum es beim Responsive Webdesign geht. Sollte man meinen.

Meine Recherche nach einem Drupal-Template am gestrigen Abend hat mich jedoch ziemlich ernüchtert und mich an eine BarCamp-Session erinnert, wo der Vortragende über Responsive Webdesign erzählen wollte, jedoch nur eine kleine Einführung in Media Queries gab und sich anschließend im Glauben wähnte, das Thema angemessen erschlagen zu haben. Doch beschränkt sich der RWD-Ansatz mitnichten nur auf den Einsatz von Media Queries.

Aber zurück zu meiner Recherche: Wie es heutzutage beim intensiven Betrachten einer Website Gang und Gäbe ist, habe ich mir jeweils mit dem Cursor den linken Browser-Rand geschnappt und das Fenster horizontal auf und zu gezogen. Das hat sich in den letzten Jahren zu einer regelrechten Neurose in Webdesigner-Kreisen entwickelt. Doch liegt der Nutzen auf der Hand: Man kriegt eine Demonstration darüber, wie sich die Seite ungefähr auf kleineren Bildschirmen verhält.

Dabei war das Resultat in den meisten Fällen das gleiche: Der Inhalt schreckte angsterfüllt zurück sobald der Fensterrand näher kam und kauerte sich nahezu klaustrophobisch in die Seitenmitte. Nur, um nach kurzer Zeit abermals zusammen zu zucken und in neuerliche, geschrumpfte Hab-Acht-Stellung zu verfallen. Da ich einen "Auftrag" hatte und keine Lust, mich mit diesen "Schmuddelkindern" des RWDs intensiver auseinander zu setzen, habe ich die Breakpoints in den Media Queries nicht näher untersucht.

Ich würde jedoch Geld darauf wetten, dass da einfach anhand der Auflösung aktueller iPhones und iPads die Breakpoints gesetzt und das Layout neu-definiert wurde. Das ist auch akzeptabel für Besucher mit "Referenz"-Geräten. Wer jedoch das Pech hat, bspw. mit einem Tablet auf die Seite zu kommen, das eine geringfügig kleinere Auflösung als das iPad hat, bekommt das iPhone-Layout angezeigt: ein Klopapier-breiter Inhaltsstreifen in Gesellschaft zweiter dicker Whitespace-Bereiche links und rechts.

Hier lässt sich der Effekt gut beobachten (der Name des Templates grenzt an Hohn).

Schön und gut, denkt sich da vielleicht der/die geneigte Leser/in. Toll ist das nicht, aber wie soll man es denn dann machen?

"Nichts leichter wie dies!", um es mit den Worten Helge Schneiders zu sagen. Man schmeißt die lästigen Pixel-Angaben aus seinem Stylesheet und macht Breiten-Angaben sowie horizontale Abstände in Prozent-Angaben. Zusätzlich gibt man eine Maximal-Breite der Seite an, damit diese bspw. nicht auf 24-Zoll-Bildschirmen den kompletten horizontalen Raum einnimmt. In den Media Queries ergänzt man anschließend noch Angaben zur Anpassung des Layouts der Elemente. Das Resultat ist ein Design, dass sich geschmeidig wie eine junge Katze dem Browser-Fenster anpasst, egal, wie breit es ist.

Hier lässt sich das ganze praktisch erfahren (kurioserweise ist das Professional Theme unter RWD-Gesichtspunkten besser als das Best Responsive Theme …)

Dem Design ist es nun egal, mit welchem Gerät man die Seite besucht. Die Breakpoints wurden auch nicht nach Lieblingshersteller gesetzt, sondern anhand des Inhalts. Unterstützt werden nicht eine handvoll Auflösungen, sondern ein stufenloser Bereich zwischen einer Minimal- und einer Maximalauflösung.

Und warum habe ich diesen Artikel geschrieben? Ganz einfach, um Missverständnisse aus der Welt zu räumen. Für diejenigen, die nicht selbst HTML/CSS schreiben, jedoch auf fertige Themes/Templates zurückgreifen und da etwas responsives suchen, der Hinweis, genau zu prüfen, was einem da als "responsive" angeboten wird. Euren Besuchern auf Mobile Devices zuliebe solltet ihr auf pseudo-responsive, fixe Layouts verzichten und richtige, responsive Fluid-Layouts wählen. So wird euer Inhalt immer anständig dargestellt, nicht nur auf drei Geräten. Den Unterschied sieht man im sogenannten Browser-Fenster-Auf-und-Zuzieh-Test.

Und für diejenigen, die selbst entwickeln und beim Thema Responsive Webdesign bisher als erste Assoziation Media Queries hatten, die Bitte, sich des Themas umfassender anzunehmen. RWD ist ein neuer Ansatz abseits fixer Layouts. Media Queries sind dabei nur ein Teilaspekt. Folgende zwei Bücher sind ein großartiger Einstieg in das Thema:

  1. Responsive Webdesign: Reaktionsfähige Websites gestalten und umsetzen | neu, umfassend und auf deutsch
  2. Responsive Web Design | der Klassiker von Ethan Marcotte

So, das musste ich einfach mal loswerden. Fragen, Anregungen, Ergänzungen sind hoch willkommen. Scheib einfach einen Kommentar.

Das Wochenende um den 19./20. Januar 2013 hatten die Kollegen von Doctape zum Hackathon geladen. Anlass der Veranstaltung — falls es zum Hacken einen Anlass braucht — war der Launch des Doctape-API, welche von den anwesenden Codern auf Herz und Nieren getestet werden sollte. Als Veranstaltungsort wurde das Co-Working-Space EDELSTALL gewählt, da es zum einen die nötige Infrastruktur für den Anlass bot und zum anderen die Doctape-Büros beherbergt.


Photo by Nicolas Hafele

Los ging es Freitag abend mit einer Präsentation des Unternehmens und der Veranstaltung, sowie einer Vorstellungsrunde der Teilnehmenden. Einige hatten auch direkt schon eine Idee, was sie bauen wollten, andere waren noch in der Findungsphase. Ungeachtet dessen machte sich eigentlich jeder sofort daran, einen ersten Zugang zum API per oAuth2 zu bekommen. Fürs leibliche Wohl wurde eine ansehnliche Pizza-Bestellung abgeschickt.

Ich selbst ließ es am Freitag bei der erfolgreichen Authentifizierung bewenden und trat um 00:30 Uhr den Heimweg an. Einige waren jedoch schon im Flow und blieben teilweise bis 04:00 Uhr morgens.


Photo by Nicolas Hafele

Am Samstag ging es um 10:00 Uhr ganz entspannt weiter. Ein gemeinsames Frühstück verschaffte die nötige Stärkung für einen langen Tag des Codens. Nach und nach trudelten auch die Nachtaktiven ein, so dass man ab dem frühen Nachmittag wieder vollzählig an den Rechnern saß und das API strapazierte. Ich hatte nun auch die Muße, mich meiner geplanten App zu widmen. Fürs leibliche Wohl traf mittags ein dicker Topf feinsten Chili con Carnes ein. Standesgemäß und vom Chili beflügelt wurde auch Samstags wieder bis tief in die Nacht hinein gehackt.

Der Sonntag begann wie der Samstag gemütlich mit einem gemeinsamen Frühstück. Anschließend gab es noch ein paar Stunden Zeit, das eigene Projekt fertig zu machen. Um 15:30 Uhr war dann Präsentation der Ergebnisse angesagt. Folgende, beachtliche Resultate sind zu vermelden:

Couchtape

Couchtape ist eine pfiffige, auf Node.js und WebSockets basierende Anwendung, die eine zentral zugängliche Playlist anzeigt und sukzessive abarbeitet. Die Songs kommen von einem Doctape-Account. Die Playlist wiederum kann von Anwesenden befüllt werden, indem diese mit ihrem Smartphone (per Browser) auf das Couchtape-System gehen und dort die verfügbaren Songs auswählen und auf die Liste setzen. Durch die Verwendung von WebSockets ist gewährleistet, dass die zentrale Playlist und alle anwesenden Clients immer in Sync sind.

Das Projekt wird weiter entwickelt und freut sich über Contributors!

TapeBooth

TapeBooth ist eine iOS-App, die es ermöglicht, Bilder zu machen, diese mit Filtern zu versehen und anschließend zu teilen. Nebenbei findet automatisch eine Synchronisierung mit dem eigenen Doctape-Account statt, so dass die Fotos automatisch in Doctape verwaltet werden können. Instagram for Doctapers könnte man — etwas einfallslos — sagen.

Der Name ist Programm. Doctape-Gallery ist mit Node.js realisiert, zieht alle Fotos über das API und stellt sie in einer schicken Galerie dar. Per Tagging können Bilder in unterschiedliche Galerien eingeordnet werden.

MIDI-Delight

Mein Beitrag zur Veranstaltung: MIDI-Delight zieht alle MIDI-Dateien, die man in seinem Doctape abgelegt hat, und bietet die Möglichkeit, sie im Browser anzuhören. Das ganze baut auf der bei Midi.js gleisteten Arbeit auf und funktioniert leider nur in modernen Desktop-Browsern, auch wenn das Layout der App etwas anderes suggeriert.

Das war es, was ich in Erinnerung behalten habe. Die Liste ist unvollständig. Wer seinen Beitrag zum Doctape-Hackathon hier nicht wiederfindet und das gerne ändern möchte, teilt es mir am besten über einen Kommentar mit. Ich passe die Liste dann an.

Ansonsten bleibt festzuhalten, dass die Veranstaltung gelungen und ein großer Spaß war. Vielen Dank an Doctape und auf ein nächstes mal!

Auf dem ConventionCamp in der Session "We survived the Shitstorm" habe ich gelernt, dass man einen Shitstorm auch als Socialstorm bezeichnen kann. Das ist dann neutraler. Die Kollegen von Brigitte.de waren scheinbar nicht in besagter Session, in der zwei Vertreter von Continental und Jack Wolfskin ihre Erfahrungen mit Socialstorms teilten und darlegten, was damals falsch gemacht wurde.

Mit dem Artikel Männer, die Skateboard fahren hatte Brigitte.de es nämlich geschafft, einen (sozialen) Sturm der Entrüstung zu entfachen und damit wiederum einen ganzen Schwung voll Kommentare zu generieren, die teilweise unterhalb der Gürtellinie angesiedelt waren.

In der Reaktion darauf wurden die gleichen Fehler gemacht, wie schon bei Continental und Jack Wolfskin zuvor. Glücklicherweise sind die Stellungnahmen seitens Brigitte.de direkt als Ergänzung in den Text eingeflossen, so dass sich im Nachhinein noch sehr schön nachvollziehen lässt, wie die Nummer abgelaufen ist. Zuerst die Trotzreaktion: Darauf beharren, dass man sich nichts hat zu Schulden kommen lassen, die Kommentarfunktion sperren und bestehende, nicht gefällige Kommentare löschen.

Anschließend leichtes Zurückrudern, nachdem man merkt, dass sich die Wogen auf diese Weise nicht glätten lassen. Schlussendlich realisiert man, dass man in einem bi-direktionalen Dialogmedium nicht einfach durch Abgeben eines Statements Fakten schaffen kann, sondern in einen Dialog mit der Gegenseite treten muss. Damit sind dann die Voraussetzungen geschaffen, dem Socialstorm ein Ende zu bereiten.

In der Praxis ist es natürlich immer empfehlenswert, die Schritte eins und zwei zu überspringen. Aber vielleicht sind das auch Erfahrungen, die Unternehmen einmal machen müssen.

Angenommen man lädt mit seine JavaScript-Dateien mit Require.js, wobei man über das data-main-Attribut die Require.js-Konfiguration anspricht und innerhalb dieser mithilfe der deps-Eigenschaft die weiteren benötigten Dateien anmeldet. Hat man nun keine klassiche "Single-page App", sondern mehrere Unterseiten, auf welchen man unterschiedliche Funktionalitäten anbieten möchte, hat man drei Möglichkeiten:

  1. Man verpackt alles in eine JavaScript-Datei und lädt diese auf allen Unterseiten
    Das ist ziemlich unelegant und läuft der Idee von Require.js, JavaScript zu modularisieren, zuwider.
  2. Man legt für jeden Unterseite eine Config-Datei an, die das gewünschte, zur Unterseite gehörige Script lädt
    Auch dies ist unelegant, da es Redundanz und unnötigen Overhead erzeugt.
  3. Man definiert am Script-Tag, welches die Require.js-Library einbindet, seitenspezifische Umgebungsvariablen
    Dazu im folgenden mehr …

Der Trick bei letzterer Herangehensweise ist, mithilfe des HTML5-data-Attributs weitere Informationen zu übergeben und dem Script-Tag eine ID zu verpassen, so dass es einfach angesprochen werden kann. Dadurch hat man die Möglichkeit, mit einer Konfigurationsdatei flexibel auf die jeweilige Unterseite zu reagieren.

Folgendermaßen sieht das Einbinden von Require.js aus:

<script src="path/to/require.js" id="requirejs" data-main="path/to/config" data-env="about" data-devmode="1"></script>

require.js und die config.js werden geladen. Soweit, so normal. Außerdem wird mithilfe von data-env definiert, dass es sich bei der aktuellen Seite um die "About"-Seite handelt, und mithilfe von data-devmode weiterhin festgelegt, dass der Entwicklungsmodus aktiv ist. Bei letzterem muss man auf "0" und "1" zurückgreifen, da die Attributwerte immer als String ausgelesen werden. "true" und "false" wären als nicht-leere Strings also beide in der Abfrage true.

"0" und "1" jedoch kann man über den Umweg Integer in Boolean umwandeln. Dies geht mithilfe von Bitwise-Operatoren folgendermaßen:

typeof ('1337' | 0) // => "number"

Die zu ladene config.js sieht dann folgendermaßen aus:

var requirejsElem = document.getElementById('requirejs');

require.config({

    deps : (function () {
        return [requirejsElem.getAttribute('data-env') + '.main']
    })(),

    urlArgs : (function () {
        return !!(requirejsElem.getAttribute('data-devmode')|0)
            ? 'bust=' + Date.now()
            : '';
    })(),

    paths : {
        jquery : 'libs/jquery-1.8.2.min'
    }

});

Als erstes wird das Script-Tag, welches Require.js lädt, in der Variable requirejsElem gespeichert, um bequem darauf zugreifen zu können. Dies ist zwar eine globale Variable, was es eigentlich zu vermeiden gilt, aber hier heiligt der Zweck die Mittel.

Als nächste folgt die eigentliche Require.js-Konfiguration. Die deps-Eigenschaft, welche die benötigte Applikationslogik lädt, ist nun dynamisch und spricht alle <prefix>.main.js-Dateien an. In diesen können dann die jeweils benötigten Module per require([&hellip;]) geladen werden.

Das devmode-Flag wird fürs Cache-Busting genutzt. Ist die Seite im Dev-Mode, wird an alle Script-Pfade der GET-Parameter bust angehängt und diesem der aktuelle Timecode übergeben.

Befindet sich die Seite nicht im Dev-Mode, wird der urlArgs-Eigenschaft ein leerer String übergeben und das Caching der Scripte findet statt.

Dies sind nur zwei Möglichkeiten, Require.js mithilfe des data-Attributs flexibler zu nutzen. Im täglichen Entwicklerleben ergeben sich bestimmt noch weitere praktische Anwendungsfälle. Kann man zudem sicher sein, nur für moderne Browser zu entwickeln, muss man nicht umständlich mit getAttribute hantieren, sondern kann auf die HTML5-data-Attribute-API zurückgreifen. Anstatt requirejsElem.getAttribute('data-env') reicht in dem Fall requirejsElem.dataset.env.


En mans rester; en annan flugas hem von krissen und CC-Lizenz

Angenommen, man begibt sich in den App Store. Man begibt sich direkt dort hin, geht nicht über Los. Man wählt ein Programm bzw. eine App, um hier mal dem Jargon treu zu bleiben, und beginnt den Download-Prozess. Nach einer Weile ist man dieses Prozesses überdrüssig — aus Gründen oder wegen Dingen — und bricht ihn daher ab.

Nach einigen Wochen oder Monaten schaut man mal wieder beim App Store vorbei. Man ist auf der Suche nach diesem einen Programm bzw. dieser einen App, hat allerdings vollkommen verdrängt, dass man unlängst schon einmal begonnen hatte, dieses bzw. diese herunter zu laden. Zugegeben: Geschichten über Superlative menschlicher Geistesleistung fangen anders an, aber Hand aufs Herz — das Gehirn ist nun einmal so angelegt, nicht alles zu speichern. Dafür gibt es schließlich Maschinen, sogenannte l'Ordinateurs, wie unser französischer Nachbar sie liebevoll zu nennen pflegt.

Wie dem auch sei, man sucht sich also die gewünschte App raus und klickt auf "Installieren". Anschließend wartet man darauf, dass es etwas passiert. Dies kann man sehr lange tun. Zum Beispiel bis man schwarz wird oder gar bis Ultimo. Es ist schier ein grenzenloses Wartevergnügen. Der Installationsvorgang startet schlicht und ergreifend nicht, da die App schon auf der "Einkäufe"-Liste steht, mit dem Status "Installation abgebrochen".

"Ein Klick auf den Installieren-Button könnte doch den Vorgang fortsetzen", denkt da der DAU und jeder andere, der nur ein Stück weit höher qualifiziert ist. Aber das wäre zu einfach. Stattdessen passiert einfach nichts. Rein gar nichts!

Da kann man sich wirklich nur zurücklehnen und sich von Herzen freuen, ob dieser verzückenden Schmalspur-Programmier-Arbeit. Ganz besonders auch in Anbetracht der Tatsache, dass man vor nicht allzu langer Zeit einen Safari in der Version 6 untergejubelt bekommen hat, der so grottenschlecht ist, dass man sich ernsthaft fragt, ob sich die Kollegen in Cupertino zur Entspannung in der Mittagspause die Hinterköpfe mit Baseball-Schlägern blau schlagen.

Übrigens: Bei dem Programm, das gerade vom App Store herüber gesurrt kommt, handelt es sich um XCode. Diversen Twitter-Einträgen zufolge kommt damit ein Stück Software, welches wohl das Potenzial hat, meinen dünnen Geduldsfaden massiv zu traktieren. Ich bin gespannt!

"Drop-a-Site" auf GitHub | Download

Hin und wieder kommt man in die Verlegenheit, eine kleine statische Seite aufsetzen zu müssen. Diese ist vom Umfang her so dünn, dass es sich nicht lohnt, eine Datenbank anzulegen und das Standard-CMS/-Framework der Wahl zu strapazieren. Andererseits hat man aber auch keine Lust, mit einem Haufen statischer HTML-Dateien rum zu hantieren.

Das ist der Punkt, wo so genannte "Static Site Generators" ins Spiel kommen. Ein Vertreter dieser Gattung möchte "Drop-a-Site" sein — einfachste Bereitstellung statischer Inhalte mithilfe von URL-Rewriting. Dabei habe ich Wert auf Simplizität gelegt. Man definiert die Pfade zu seinen Seiten sowie die zugehörigen Seitentitel, und "Drop-a-Site" liefert aus. Auf weiterführende Features habe ich bewusst verzichtet.

Die Einrichtung von "Drop-a-Site" ist denkbar einfach:

1. Seiten-URL definieren

Die nötigen Anpassungen müssen in der config.php vorgenommen werden. In der SITE_URL-Konstante wird der vollständige URL der Seite gespeichert. Liegt die Seite nicht im Wurzelverzeichnis sondern in einem Unterordner, muss das mit eingetragen werden.

2. Unterseitepfade und -titel definieren

Im $pages-Array werden die Pfade zu den Unterseiten sowie deren Titel gespeichert. Das URL-Rewriting sorgt dafür, dass die Seiten über den eingetragenen Pfaden erreichbar sind. Unter- und Unter-Unterseiten stellen kein Problem dar.

3. Anpassung für den Fall, dass die Seite nicht in der Wurzelebene liegt

Liegt deine Seite in der Wurzelebene, kannst du diesen Punkt getrost überspingen.

Liegt die zu erstellende Seite jedoch in einem Unterordner, muss die Deklaration der $req-Variable angepasst werden. Genauer gesagt, muss der Pfad zur Unterseite aus dem Request-String entfernt werden. Ist die Seite bspw. über die Adresse http://example.com/foo/bar/ erreichbar, muss die Deklaration der $req-Variablen folgendermaßen aussehen:

$req = trim(str_replace('/foo/bar/', '', $_SERVER['REQUEST_URI']), '/');

4. Anpassen der .htaccess-Datei

Auch diesen Punkt kannst du überspringen, wenn deine Seite in der Wurzeleben liegt.

Andernfalls musst du dem mod_rewrite mitteilen, in welchem Unterordner die Seite liegt, damit es fehlerfrei funktionieren kann. Dafür gibt es in der .htaccess den Wert RewriteBase. Ausgehend von der Annahme, die Adresse deiner Seite ist http://example.com/foo/bar/, muss der Eintrag in der .htaccess so aussehen:

RewriteBase /foo/bar/

5. Einstellen der Inhalte

Schlussendlich müssen nur noch die Inhalte eingetütet werden. Diese werden im Ordner "inc" gelagert und nach den entsprechenden Seiten benannt. Zur Seite "about" gehört also die Datei "about.inc.php". Für Unterseiten müssen entsprechende Ordner innerhalb von "inc" angelegt werden.

Zusätzlich gibt es innerhalb von "inc" den "components"-Ordner - in diesem können Template-Parts wie Header, Footer, Navigation, etc. ablegt werden.


Das ist auch schon alles, was es zu tun gibt, um "Drop-a-Site" in Betrieb zu nehmen. Natürlich kann das System nach Belieben erweitert und ausgebaut werden. Allerdings muss man dabei abwägen, ob es den Aufwand wert ist.

Bei Fragen oder Anregungen sei an die Kommentarfunktion verwiesen.

"Drop-a-Site" auf GitHub | Download


Foto von Viktor Schanz

Letztes Wochenende fand zum zweiten mal das Summercamp in Alfeld statt. Dabei handelt es sich um ein Barcamp in kleinem, man möchte sagen familiären Rahmen. So wurden zum einen interessante Sessions geboten zu den Themen Arduino (von @Handgemenge), dem CMS ProcessWire (von @MichaelvanLaar), Frontend-Performance-Optimierung (von @nikolassv), u.v.m.

Andererseits bot die persönliche Atmosphäre die Möglichkeit, auch außerhalb der Sessions ins Gespräch zu kommen und sich bspw. über Politikverdrossenheit oder das Für und Wider von CSS-Frameworks zu unterhalten. Darüber hinaus gab es eine von @elcario organisierte PowerPoint-Karaoke am Samstag Abend und anschließend noch eine spontane Transport-Tycoon-“Session” bis in die Nacht hinein.

Organisiert wurde das Summercamp wieder von Kai Thrun. Deshalb an dieser Stelle einen ganz herzlichen Dank an ihn, sowie die Sponsoren und alle anderen, die mitgeholfen haben, dieses Ereignis möglich zu machen. Wir sehen uns hoffentlich in einem Jahr wieder in Alfeld.

Demo | Download

Wenn aus dem "One-Pager" ein "Multi-One-Pager" wird, kann sich ein gewisser Overhead bezüglich der geladenen Skripte einstellen. Angenommen man baut eine Web-App, die aus vielen Einzelseiten besteht, und jede Einzelseite stellt für sich einen "One-Pager" dar, welcher nicht zwingend beim Besuch eines Nutzers aufgerufen wird. Dann werden — benutzt man Require.js zum Laden der Skripte — beim initialen Aufruf der Web-App alle Skripte geladen, auch wenn sie letztlich gar nicht benötigt werden.

In diesem Fall wäre es praktischer, mehrere Require.js-Instanzen anzulegen und durch einen zentralen Router gesteuert bei Bedarf aufzurufen. Dieses Szenario habe ich einmal mithilfe von Backbone.js nachgestellt. Die "Web-App" besteht aus diversen Einzelseiten, welche bestimmte jQuery-UI-Widgets beinhalten. Außerdem gibt es eine Startseite mit einem kurzen Erklärungstext. Ziel ist es, den Startseiteninhalt und die jQuery-UI-Widgets nur bei Bedarf zu laden.

Dafür wird beim Aufruf der Seite lediglich eine fundamentale Require.js-Instanz aufgerufen, die die global benötigten Skripte — jQuery, Underscore, Backbone, den jQuery-UI-Core und einen Observer — laden und einen Backbone-Router initialisieren, der die Autoloader-Funktionalität zur Verfügung stellt.

require(['jQuery', 'Underscore', 'Backbone', 'Observer'], function ($, _, Backbone, Observer) {

  var Router = Backbone.Router.extend({

    routes : {
      ':site/*sub' : 'autoLoad'
    },

    initialize : function () {
      location.hash = location.hash || 'index/';

      Backbone.history.start();
    },

    autoLoad : function (site, sub) {
      var path = 'sites/' + site + '/app';

      require([path], function (App) {
        App.init({
          subPages : sub
        });
      });
    }
  }),

  router = new Router();

});

Der Router prüft als erstes, ob ein Location-Hash gesetzt ist. Ist dies nicht der Fall, wird der Hash /index/ gesetzt, was die Initialisierung der Startseite einleitet. Weiterhin wartet der Router auf Änderungen des Location-Hash und führt im Bedarfsfall die autoLoad-Funktion aus, welche das gewünschte Modul/die gewünschte Seite lädt. Das *sub im routes-String des Routers stellt sicher, dass auch beim initialen Aufruf von Unter-Unterseiten die Autoload-Funktion tut, was sie soll.

Das vom Autoloader geladene Skript übergibt eine init-Funktion — dabei kann es sich, je nachdem ob die Seite lediglich statischen Inhalt hat oder tiefergreifende Funktionalität besitzt, entweder um eine Backbone-View- oder eine Backbone-Router-Instanz handeln.

var init = function () {
    return new View();
  };

return {
  init : init
};
var init = function (args) {
    return new Router(args);
  };

return {
  init : init
};

Das Datepicker-Modul habe ich als Beispiel für eine zusätzliche Router-Instanz gewählt. Inhaltlich zugegebenermaßen etwas mau, wird doch deutlich, dass auf diese Weise die Funktionalität der Web-App auch auf Unterebenen gewährleistet werden kann, ohne dass dies beim initialen Aufruf der Seite angemeldet bzw. geladen werden muss.

Beobachtet man den Inhalt des HTML-Head beim Durchklicken der Seite im Firebug bzw. Web Inspector, kann man sehr schön verfolgen, wie die jeweils benötigten Module und Widgets sukzessive nachgeladen werden.

Ich hoffe, mein Versuch, den Sachverhalt hier darzustellen, ist einigermaßen verständlich. Über Anregungen, Anmerkungen und Fragen freue ich mich immer. Sollte diesbezüglich Bedarf bestehen, kann ich nur dazu ermutigen, regen Gebrauch von der Kommentar-Funktion zu machen.

Außerdem sei darauf hingewiesen, dass der Code zur schnellen Inspektion auch auf GitHub zur Verfügung steht.

Um etwas Zerstreuung vom Uni-Lernstress zu bekommen, habe ich einen Ausflug in die bunte Node.js-Welt unternommen. Als Mittel zum Zweck diente mir dabei das digitale Notizbrett "Clipboard". Serverseitig kommt das Application-Framework Express zum Einsatz. Gespeichert werden die Daten in einer MongoDB-Datenbank mithilfe von Mongoose.

Client-seitig kommt die bewährte Kombo aus Underscore, Backbone und jQuery zum Einsatz. Für Ordnung sorgt überdies Require.js, wobei ich auf folgenden Ansatz zurückgegriffen habe: Modular JavaScript & Backbone.js. Außerdem hat jQueryUI einen "Gast-Auftritt" und sorgt für die Draggability der Notizen.

Das Hosting übernimmt dankenswerterweise AppFog, die Daten werden bei MongoHQ abgelegt. Defenitiv zwei sehr praktische Services.

(Clipboard-Code bei GitHub)