Kategorien
HTML/CSS JavaScript & jQuery

Trüffelschwein: Knwl.JS filtert Daten automatisch

In Texten stecken gern wichtige Informationen wie Zeit- und Ortsangaben, E-Mail-Adressen, Telefonnummern, Links und andere Datenschnipsel. Die JavaScript-Bibliothek Knwl.JS findet solche Informationen automatisch und kann sie aus dem Text filtern und zur weiteren Verarbeitung verfügbar machen. So sind mit etwas Kreativität sehr flexible Lösungen möglich. Dabei ist die Anwendung kein Hexenwerk.

Trüffelschwein: Knwl.JS filtert Daten automatisch

Knwl.JS: Plugins zum Erkennen verschiedener Inhalte

Knwl.js muss zunächst im HTML-Head eingebunden werden. Anschließend lässt sich ein beliebiger Textabschnitt auf bestimmte Inhalte durchsuchen. Dazu wird der Text direkt oder auch als Variable der Methode KnwlInstance.init() zugewiesen. Anschließend muss man sich für ein Plugin entscheiden, welches den Text nach bestimmten inhaltlichen Mustern durchsucht. Eines dieser Plugins ist date, welches nach Datumsangaben sucht.

KnwlInstant.init("Today is December 19th 2015.");
var output = KnwlInstance.get("date");

Im Beispiel wird per KnwlInstance.get() das Plug-in date aufgerufen. Es durchforstet die zuvor übergebene Zeichenkette auf Datumsangaben und gibt alle gefundenen Angaben im JSON-Format zurück.

var output = [
  {
    "year": 2015,
    "month": 8,
    "day": 11,
    "preview": "Today is August 11th 2015.","found": 2
  }
]

Die JSON-Zeichenfolge enthält nun je nach Plugin unterschiedliche Werte. Bei einem Datum wird dieses in Jahr, Monat und Tag aufgeschlüsselt zurückgegeben. Zusätzlich wird bei allen Plugins per preview der Satz übergeben, in dem der jeweilige Wert gefunden wurde. Über found wird dann rückgemeldet, an welcher Stelle im Text (in Wörtern) die entsprechende Angabe gefunden wurde.

knwljs1

Werden mehrere Daten gefunden, gibt Knwl.js diese als einzelne JSON-Objekte wider.

Datums-, Zeit- und Ortsangaben nur in Englisch

Leider erkennt Knwl.js Datums- und Zeitangaben nur dann, wenn sie in englischer Sprache hinterlegt sind. Andere Sprachen werden zumindest derzeit nicht unterstützt. Gleiches gilt für das Plugin place, welches Ländernamen in Texten erkennt.

var output = [
  {
    "place": "Germany",
    "preview": "This is Germany.","found": 2
  }
]

Ähnlich schwierig, wie Datums-, Zeit- und Ortsangaben, sind auch Telefonnummern in anderen Sprachen zu erkennen. Denn auch hierbei wird nur die übliche englische Schreibweise unterstützt.

Links und E-Mail-Adressen in jeder Sprache möglich

Trotz der ausschließlichen Unterstützung der englischen Sprache kann man Kwnl.js durchaus in deutschen Texten verwenden – zumindest dann, wenn man es nutzen möchte, um Links und E-Mail-Adressen herauszulesen.

var output = [
  {
    "link": "http://www.drweb.de/",
    "preview": "Unter http://www.drweb.de/ gibt es täglich Neues.","found": 1
  }
]

Wichtig bei der Erkennung von Links ist, dass bei diesen das jeweilige Protokoll – „http://“, „https://“ oder „ftp://“ – vorangestellt ist. Auch E-Mail-Adressen werden zuverlässig erkannt.

Eigene Plugins entwickeln

Will man das Erkennen deutschsprachiger Zeit- und Ortsangaben unterstützen, muss man selbst Hand anlegen und ein eigenes Plugin für Knwl.js entwickeln. In der Dokumentation der Bibliothek findet man dazu einen eigenen Abschnitt. Jedes Plugin wird in einer eigenen JavaScript-Datei hinterlegt.

Auf diese Weise kann man sich recht einfach eigene Plugins bauen. Natürlich sind nicht nur „Übersetzungen“ ins Deutsche möglich. Man kann auch gänzlich eigene Plugins entwickeln, welche beispielsweise metrische Maße, Währungen oder Farben aus einem Text herausfiltern.

Einige experimentelle Plugins findet man in der Dokumentation zu Knwl.js.

Fazit

Knwl.js bietet vielfältige Möglichkeiten, strukturierte Werte aus Texten herauszufiltern. Aufgrund der Fixierung auf die englische Sprache muss man zwar vieles anpassen, kann aber mit etwas Fantasie auch sehr individuelle Werte herausfinden lassen.

knwljs2
Demo zum Probieren

Neben einer Dokumentation gibt es eine Demo, bei der beliebiger Text eingegeben und per Knwl.js geparst werden kann.

(dpe)

Kategorien
JavaScript & jQuery Programmierung Sonstige Programmiersprachen

ECMAScript 6 besser verstehen: Template Strings

Willkommen zum zweiten Teil unserer Artikelserie zu ECMAScript 6. Eines der Features, das ich am neuen Microsoft Edge, der neuen Browser Rendering Engine von Microsoft, am meisten mag, ist ihre umfangreiche Unterstützung von ECMAScript 6. In dieser Serie stelle ich einige der coolen Dinge vor, die man mit ECMAScript 6 tun kann, vor allem, wenn man große Web-Anwendungen schreibt.

ECMAScript 6 besser verstehen: Template Strings

Im ersten Teil habe ich euch in das Thema Klassen und Vererbung eingeführt. In diesem Artikel konzentriere ich mich auf Template Strings, ausgehend von meinen eigenen Erfahrungen beim Erstellen von Embedded Expressions.

Eine Lösung für das „Line Return“-Problem

Wenn ich an babylon.js arbeite, habe ich mit Code für Shader zu tun. Für ein besseres Verständnis würde ich sagen, man könnte diesen Code am ehesten als einen Haufen Text beschreiben, der wie C aussieht.

Ein Beispiel dafür findet sich hier.

Das Problem bei sehr langen Texten in JavaScript ist der Zeilenwechsel. Wie oft haben wir Dinge wie diese hier geschrieben?

var myTooLongString = "A long time ago, in a galaxy far," +
                      "far away...." +
                      "It is a period of civil war." +
                      "Rebel spaceships, striking" +
                      "from a hidden base, have won" +
                      "their first victory against" + 
                      "the evil Galactic Empire.";

Bei mehr als 200 Zeilen langem Code für Shaders wird das richtig anstrengend.

Glücklicherweise besitzt ECMAScript 6 das neue Template Strings-Feature. Neben anderen schönen Erleichterungen, die dieses Feature bietet, unterstützt ein Template String vor allem direkt mehrzeilige Strings:

var myTooLongString = `A long time ago, in a galaxy far
far away....
It is a period of civil war.
Rebel spaceships, striking
from a hidden base, have won
their first victory against
the evil Galactic Empire`;

Weil innerhalb eines Template String alle Zeichen von Bedeutung sind, kann man keine Leerzeichen an den Anfang der Zeilen einfügen.

Als JavaScript-Entwickler haben wir drei Arten, um Strings zu definieren:

Und was ist daran nun ein Template?

Die Unterstützung mehrzeiligen Codes ist nicht das einzige Feature von Template Strings. So kann man Template Strings auch dafür nutzen, um Platzhalter mit Variablenwerten zu ersetzen, wie ihr es z.B. mit printf in C/C++ oder string.Format in C# sicher schon getan habt:

var items = [];
items.push("banana");
items.push("tomato");
items.push("light saber");

var total = 100.5;

result.innerHTML = `You have ${items.length} item(s) in your basket for a total of $${total}`;

Dieser Code führt zu folgender Ausgabe:

You have 3 item(s) in your basket for a total of $100.5

Ganz praktisch oder?
Hier zur Erinnerung, wie das mit ECMAScript 5 ging:

result.innerHTML = "You have " + items.length + " item(s) in your basket for a total of $" + total;

Mit Tags noch einen Schritt weiter gehen

Im letzten Schritt der Spezifikation von Template Strings geht es darum, vor dem String selbst eine eigene Funktion einzufügen (custom function), um einen Template String mit einem „Tag“ zu erstellen:

var myUselessFunction = function (strings,...values) {
    var output = "";
    for (var index = 0; index < values.length; index++) {
        output += strings[index] + values[index];
    }

    output += strings[index]
    return output;
}

result.innerHTML = myUselessFunction `You have ${items.length} item(s) in your basket for a total of $${total}`;

Die Funktion dient hier dazu, sowohl Zugang zu den konstanten Teilen des Strings als auch zu den Variablen-Werten zu bekommen.
Im vorhergehenden Beispiel sehen Strings und Werte (values) wie folgt aus:

  • strings[0] = “You have “
  • values[0] = 3
  • strings[1] = “items in your basket for a total of $”
  • values[1] = 100.5
  • strings[2] = “”

Wie wir sehen, ist jeder Value[n] umgeben von konstanten Strings (strings[n] und strings[n + 1]).

Das gibt uns Kontrolle darüber, wie der endgültige Output-String aufgebaut ist. Im vorigen Beispiel haben wir nur das grundsätzliche Verhalten von Template Strings reproduziert. Wir können aber auch noch weiter gehen und dem String eine coole Verarbeitung (processing) mitgeben.

Hier zum Beispiel ist ein Stückchen Code, welches Strings blockiert, die versuchen, benutzerdefinierte DOM-Elemente einzuschleusen:

var items = [];
items.push("banana");
items.push("tomato");
items.push("light saber");

var total = "Trying to hijack your site 
"; var myTagFunction = function (strings,...values) { var output = ""; for (var index = 0; index < values.length; index++) { var valueString = values[index].toString(); if (valueString.indexOf("<") !== -1) { // Far more complex tests can be implemented here :) return "String analyzed and refused!"; } output += strings[index] + values[index]; } output += strings[index] return output; } result.innerHTML = myTagFunction `You have ${items.length} item(s) in your basket for a total of $${total}`;

"Getaggte" Template Strings sind für viele Anwendungen geeignet, wie z.B. Sicherheit, Ortsbestimmung, das Erstellen einer eigenen, domain-spezifischen Sprache und mehr.

Raw Strings

Tagging-Funktionen haben eine besondere Option, wenn sie auf konstante Strings zugreifen: Sie nutzen strings.raw um "unescaped" String-Values zu erhalten. Das heißt z.B. im Fall von “\n” wird das nicht als einzelnes Zeichen betrachtet, sondern tatsächlich als zwei Zeichen “\” und “n”.

Hauptziel ist es, uns zu ermöglichen, auf den String zugreifen zu können, so wie er eingegeben wurde:

var myRawFunction = function (strings,...values) {
    var output = "";
    for (var index = 0; index < values.length; index++) {
        output += strings.raw[index] + values[index];
    }

    output += strings.raw[index]

    console.log(strings.length, values.length);
    return output;
}

result.innerHTML = myRawFunction `You have ${items.length} item(s) in your basket\n.For a total of $${total}`;

Dieser Code führt zu folgender Ausgabe:

You have 3 item(s) in your basket\n. For a total of $100.5

Man kann auch eine neue String-Funktion nutzen: String.raw(). Diese bereits eingebaute Funktion führt genau das aus, was unser voriges Beispiel bereits getan hat:

result.innerHTML = String.raw `You have ${items.length} item(s) in your basket\n.For a total of $${total}`;

Fazit

Microsoft Edge und die aktuellen Versionen von Chrome (41+), Opera(28+) and Firefox (35+) unterstützen Template Strings. In welcher Breite ECMAScript 6 allgemein unterstützt wird, kannst du hier nachschlagen. Wer Anwendungen für das moderne Web erstellen will, für den sind Template Strings eine sinnvolle Sache.

Einen vollständigen Überblick zu den neuen Web-Standards und Features, die Microsoft Edge mitbringt – wie z.B. WebAudio – bietet die Liste von http://dev.modern.ie/platform/status.

Mehr Tipps, Tricks und Hilfen rund um JavaScript

Microsoft hält eine ganze Reihe kostenloser Lehrangebote zu zahlreichen Open Source JavaScript-Themen bereit – und seit der Veröffentlichung von Microsoft Edge tun wir in diesem Bereich noch sehr viel mehr. Auch von mir gibt es Tutorials:

Außerdem haben wir da noch die Schulungsreihe unseres Teams:

Praktisch sind zudem die folgenden kostenlosen Tools: Visual Studio Community, Azure Trial und Cross Browser Testing Tools für Mac, Linux oder Windows.

Dieser Artikel ist Teil der Web-Dev Tech-Series von Microsoft. Wir freuen uns Microsoft Edge (früher Project Spartan genannt) und seine neue Rendering Engine mit euch zu teilen. Kostenlose Virtual Machines oder Remote Testings für Mac, iOS, Android oder Windows gibt es hier: @ dev.modern.IE.

(dpe)

Kategorien
JavaScript & jQuery Programmierung

JavaScript: Mit Closure Space private Attribute erstellen

Vor einiger Zeit habe ich einen Angular Cloud Data Connector entwickelt, der es Angular-Entwicklern erlaubt, mithilfe von Webstandards, wie indexierten DB, Cloud-Daten zu nutzen, und zwar konkret Azure Mobile Service. Ich wollte Java-Entwicklern die Möglichkeit geben, private Attribute (private members) in ein Objekt einzubetten. Die Technik, die ich für diesen speziellen Fall benutze, nenne ich “closure space”. In diesem Tutorial zeige ich, wie man das für verschiedene Projekte nutzen kann und inwiefern Performance und Speicher der gängigen Browser davon beeinflusst werden.

Aber bevor wir richtig anfangen, werde ich noch kurz erklären, wozu man private Attribute braucht und auf welche Weise man sie auch “simulieren” kann.

Wozu brauchen wir private Attribute?

Wenn wir ein Objekt mit JavaScript erstellen, können wir Wertattribute (value members) festlegen. Um den Lese-/Schreibzugriff darauf zu steuern, müssen wir Zugriffsberechtigte wie folgt definieren:

var entity = {};

entity._property = "hello world";
Object.defineProperty(entity, "property", {
    get: function () { return this._property; },
    set: function (value) {
        this._property = value;
    },
    enumerable: true,
    configurable: true
});

Auf diese Weise haben wir die volle Kontrolle über den Lese-/Schreibzugriff. Problematisch ist jedoch, dass das _property Attribut noch zugänglich ist und direkt verändert werden kann.

Genau deshalb brauchen wir einen solideren Weg, um private Attribute festzulegen, die nur mithilfe der Funktionen des Objekts zugänglich sind.

Die Nutzung von Closure Space

Die Lösung heißt: Closure Space. Dieser Speicherraum wird vom Browser bereitgestellt, und zwar jedes Mal, wenn eine innere Funktion Zugang zu Variablen aus dem Bereich einer äußeren Funktion besitzt. Das ist manchmal eine ziemlich knifflige Angelegenheit, aber für unsere Zwecke ist die Lösung perfekt.

Um diese Funktion zu nutzen, ändern wir also den vorherigen Code in diesen hier:

var createProperty = function (obj, prop, currentValue) {
    Object.defineProperty(obj, prop, {
        get: function () { return currentValue; },
        set: function (value) {
            currentValue = value;
        },
        enumerable: true,
        configurable: true
    });
}

var entity = {};

var myVar = "hello world";
createProperty(entity, "property", myVar);

In diesem Beispiel hat die Funktion createProperty die Variable currentValue, welche von Get/Set-Funktionen erkannt wird. Diese Variable wird im Closure Space der Get- und Set-Funktionen gespeichert. Ausschließlich diese beiden Funktionen können nun die Variable currentValue sehen und aktualisieren! Mission erfüllt!

Fast zumindest. Der einzige Vorbehalt: Der Quellenwert (myVar) ist nach wie vor zugänglich. Deshalb zeige ich hier eine Version mit noch besserem Schutz:

var createProperty = function (obj, prop) {
    var currentValue = obj[prop];
    Object.defineProperty(obj, prop, {
        get: function () { return currentValue; },
        set: function (value) {
            currentValue = value;
        },
        enumerable: true,
        configurable: true
    });
}

var entity = {
    property: "hello world"
};

createProperty(entity, "property");

Mit dieser Methode wird sogar der Quellenwert unsichtbar. Nun haben wir die Aufgabe aber wirklich erfüllt!

Ein Blick auf die Performance

Jetzt schauen wir mal wie sich das Ganze auf die Performance auswirkt.

Ganz klar, Closure Space oder sogar Eigenschaften sind langsamer und aufwändiger als reine Variablen. Deshalb will ich mich in diesem Artikel auf den Unterschied zwischen dem üblichen Weg und der Closure Space-Technik konzentrieren.

Um nachzuweisen, dass die Nutzung von Closure Space verhältnismäßig effizienter ist als der herkömmliche Weg, habe ich diesen kleinen Benchmark-Code geschrieben:

<!DOCTYPE html>
  <html xmlns="http://www.w3.org/1999/xhtml">
  <head>
  <title></title>
  </head>
  <style>
  html {
  font-family: "Helvetica Neue", Helvetica;
  }
  </style>
  <body>
  <div id="results">Computing...</div>
  <script>
  var results = document.getElementById("results");
  var sampleSize = 1000000;
  var opCounts = 1000000;
  
 var entities = [];

 setTimeout(function () {
  // Creating entities
  for (var index = 0; index < sampleSize; index++) {
  entities.push({
  property: "hello world (" + index + ")"
  });
  }

 // Random reads
  var start = new Date().getTime();
  for (index = 0; index < opCounts; index++) {
  var position = Math.floor(Math.random() * entities.length);
  var temp = entities[position].property;
  }
  var end = new Date().getTime();

 results.innerHTML = "<strong>Results:</strong><br>Using member access: <strong>" + (end - start) + "</strong> ms";
  }, 0);

 setTimeout(function () {
  // Closure space =======================================
  var createProperty = function (obj, prop, currentValue) {
  Object.defineProperty(obj, prop, {
  get: function () { return currentValue; },
  set: function (value) {
  currentValue = value;
  },
  enumerable: true,
  configurable: true
  });
  }
  // Adding property and using closure space to save private value
  for (var index = 0; index < sampleSize; index++) {
  var entity = entities[index];

 var currentValue = entity.property;
  createProperty(entity, "property", currentValue);
  }

 // Random reads
  var start = new Date().getTime();
  for (index = 0; index < opCounts; index++) {
  var position = Math.floor(Math.random() * entities.length);
  var temp = entities[position].property;
  }
  var end = new Date().getTime();

 results.innerHTML += "<br>Using closure space: <strong>" + (end - start) + "</strong> ms";
  }, 0);

 setTimeout(function () {
  // Using local member =======================================
  // Adding property and using local member to save private value
  for (var index = 0; index < sampleSize; index++) {
  var entity = entities[index];

 entity._property = entity.property;
  Object.defineProperty(entity, "property", {
  get: function () { return this._property; },
  set: function (value) {
  this._property = value;
  },
  enumerable: true,
  configurable: true
  });
  }

 // Random reads
  var start = new Date().getTime();
  for (index = 0; index < opCounts; index++) {
  var position = Math.floor(Math.random() * entities.length);
  var temp = entities[position].property;
  }
  var end = new Date().getTime();

 results.innerHTML += "<br>Using local member: <strong>" + (end - start) + "</strong> ms";
  }, 0);

 </script>
  </body>
  </html>

Ich erstelle eine Million Objekte, jeweils mit einem Eigenschaftsattribut (property member). Dann lasse ich drei Tests laufen:

  • Führe 1 Million Direktzugriffe auf die Eigenschaft aus
  • Führe 1 Million Direktzugriffe auf die “Closure Space” Version aus
  • Führe 1 Million Direktzugriffe auf die reguläre Get/Set Version aus

Hier eine Tabelle und eine Grafik von den Ergebnissen:


Deutlich zu sehen ist, dass die Closure Space-Version in allen Fällen schneller arbeitet als die reguläre Version. Abhängig vom Browser kann die Optimierung sehr eindrucksvoll ausfallen.

Die Performance von Chrome war weniger gut, als ich sie erwartet hatte. Um einen Bug auszuschließen, fragte ich daher bei Google nach, was die Ursache dafür sein könnte. Nebenbei bemerkt: Wer ausprobieren will, wie dieser Test für Microsoft Edge ausgeht – der neue Browser von Microsoft, der in Windows 10 enthalten ist – der kann ihn hier herunterladen.

Wie auch immer, wenn wir genau hinschauen, sehen wir, dass die Nutzung von Closure Space oder sogar einer Eigenschaft zehnmal langsamer funktioniert, als der direkte Zugriff auf ein Attribut. Das nur als Warnung, das Ganze mit Bedacht anzuwenden.

Speicherbedarf

Wir sollten auch prüfen, ob diese Technik nicht zu viel Speicherkapazität bindet. Um also auch dafür einen Benchmark-Test durchzuführen, habe ich diese drei Stückchen Code geschrieben:

Referenz Code

var sampleSize = 1000000;

var entities = [];

// Creating entities
for (var index = 0; index < sampleSize; index++) {
    entities.push({
        property: "hello world (" + index + ")"
    });
}

Der übliche Weg

var sampleSize = 1000000;

var entities = [];

// Adding property and using local member to save private value
for (var index = 0; index < sampleSize; index++) {
    var entity = {};

    entity._property = "hello world (" + index + ")";
    Object.defineProperty(entity, "property", {
        get: function () { return this._property; },
        set: function (value) {
            this._property = value;
        },
        enumerable: true,
        configurable: true
    });

    entities.push(entity);
}

Closure Space-Version

var sampleSize = 1000000;

var entities = [];

var createProperty = function (obj, prop, currentValue) {
    Object.defineProperty(obj, prop, {
        get: function () { return currentValue; },
        set: function (value) {
            currentValue = value;
        },
        enumerable: true,
        configurable: true
    });
}

// Adding property and using closure space to save private value
for (var index = 0; index < sampleSize; index++) {
    var entity = {};

    var currentValue = "hello world (" + index + ")";
    createProperty(entity, "property", currentValue);

    entities.push(entity);

Dann ließ ich alle drei Codes durchlaufen und startete den integrierten Memory Profiler (als Beispiel nutzte ich hier die F12 Tools):

Auf meinem Computer erhielt ich daraufhin folgende Ergebnisse:

Im Vergleich von Closure Space und dem üblichen Weg hatte nur Chrome leicht bessere Werte für die Closure Space-Version. IE11 und Firefox brauchten ein bisschen mehr Speicher, aber generell waren alle Browser relativ vergleichbar. Als User wird man da kaum einen Unterschied bemerken.

Mehr Tipps, Tricks und Hilfen rund um JavaScript

Microsoft hält eine ganze Reihe kostenloser Lehrangebote zu zahlreichen Open Source JavaScript-Themen bereit – und seit der Veröffentlichung von Microsoft Edge tun wir in diesem Bereich noch sehr viel mehr. Auch von mir gibt es Tutorials:

Außerdem haben wir noch die Schulungsreihe unseres Teams:

Praktisch sind zudem die folgenden kostenlosen Tools: Visual Studio Community, Azure Testversion und Cross Browser Testing Tools für Mac, Linux oder Windows.

Fazit

Wie wir gesehen haben, können wir mit Closure Space sehr gut wirklich private Daten erstellen. Das kostet uns ein bisschen Speicherplatz, aber meiner Meinung nach ist das vertretbar (und bringt uns schließlich gleichzeitig eine bessere Performance, als wenn wir den üblichen Weg nutzen würden).

Wer Fragen zu diesem Artikel hat, kann mich gern auf Twitter kontaktieren: @deltakosh

Und wer es gleich selbst versuchen will, kann den gesamten verwendeten Code hier finden. Es gibt außerdem eine gute Kurzeinweisung in die Azure Mobile Services, und zwar hier.

Dieser Artikel ist Teil der Web-Dev Tech-Series von Microsoft. Wir freuen uns Microsoft Edge (früher Project Spartan genannt) und seine neue Rendering Engine mit euch zu teilen. Kostenlose Virtual Machines oder Remote Testings für Mac, iOS, Android oder Windows gibt es hier: @ dev.modern.IE.

(dpe)

Kategorien
JavaScript & jQuery Programmierung

JavaScript: Bessere Auswertung der Performance durch User Marks

Wer an fortgeschrittenem JavaScript-Code arbeitet, wie zum Beispiel einer 3D-Engine, wird sich früher oder später fragen, wie sich dieser Code optimieren lässt und wie viel Zeit man mit bestimmten Abschnitten des Codes verbringen sollte. In diesem Tutorial stelle ich einige Tools vor, die uns sagen, wie gut die Performance unseres Codes tatsächlich ist und wie wir Anwendermarkierungen (User Marks) im Memory Graph am besten nutzen, um die Leistungsfähigkeit des Codes auszuwerten.

JavaScript: Bessere Auswertung der Performance durch User Marks

Sie wollen einen schnellen Überlick zum Thema? Dann gleich mal dieses Video ansehen.

Wer Fragen zu diesem Artikel hat, kann mich gern auf Twitter kontaktieren (@deltakosh)

Profiler gesucht?

Dazu fällt mir gleich der integrierte Profiler ein, der in den Updates zu den Internet Explorer F12 Dev Tools enthalten ist — dessen Weiterentwicklung, die auch für Microsoft Edge verfügbar sind. Aber natürlich sind andere, ähnlich funktionale Tools ebenso geeignet.

Wer das mal mit Android, iOS oder Mac OS ausprobieren will, kann auch remote.IE nutzen, um eine Windows 10 Technical Preview-Instanz in wenigen Minuten zum Laufen zu bringen. Dann einfach den Internet Explorer “e” öffnen (eine temporäre Client Shell mit konfigurierter neuer Rendering Engine von Microsoft Edge), “F12” klicken und daraufhin sollte das Folgende zu sehen sein:

Hierbei ist zu beachten, dass bei den neuen F12 Tools, die Teil des Windows 10 Technical Previews sind, der Profiler im Fenster „UI responsiveness“ zu finden ist:

Schauen wir uns nun andere Optionen an, die uns Erkenntnisse über die Performance unseres Codes vermitteln können.

console.time

Hier muss man einfach nur console.time() und console.timeEnd() vor bzw. nach dem Teil des Codes aufrufen, der getestet werden soll. Als Ergebnis erhält man einen String in der Konsole, der die Zeit zwischen time und timeEnd anzeigt.

Natürlich ist das recht einfach und kann auch leicht emuliert werden, aber mir persönlich gefällt besonders die Unkompliziertheit dieser Funktion.

Und es kommt noch besser: Man kann einen String angeben, um eine Bezeichnung für die Messwerte zu bekommen.

Dies habe ich zum Beispiel für Babylon.js getan:

console.time("Active meshes evaluation");
this._evaluateActiveMeshes();
console.timeEnd("Active meshes evaluation");

Diese Art von Code ist in allen wichtigen Funktionen zu finden und wenn man Performance Logging aktiviert hat, erhält man jede Menge interessanter Informationen:

Hinweis: Das Rendering von Text in die Konsole kann eine Menge CPU-Power beanspruchen.

Da diese Funktion an sich keine Standardfunktion ist, hat mich die Kompatibilität mit unterschiedlichen Browsern umso mehr überzeugt. Sie wird von Chrome, Firefox, IE, Opera und Safari unterstützt.

Performance Object

Wer es gern etwas visueller mag, dem sei performance object empfohlen. Neben anderen interessanten Features, um die Performance einer Webseite zu messen, gibt es die Funktion mark, die eine Anwendermarkierung (user mark) aussendet.

Eine Anwendermarkierung verbindet einen Namen mit einem Zeitwert. Teile des Codes können mit dieser API gemessen werden, um genaue Werte zu erhalten. Es gibt einen tollen Artikel über diese API von Aurelio de Rosa bei SitePoint.

An dieser Stelle hier geht es mir nur darum, diese API zu benutzen, um konkrete Anwendermarkierungen im UI Responsiveness Screen bildlich darzustellen:

Dieses Tool ermöglicht es, eine Session zu erfassen und festzustellen, wie stark dabei die CPU beansprucht wird:

Wir können dann einen konkreten Frame vergrößert darstellen, indem wir den Eintrag “Animation frame callback” auswählen und dort nach einem Rechtsklick “filter to event” wählen.

Der gewählte Frame wird daraufhin gefiltert:

Dank des neuen F12 Tools können wir nun zu den JavaScript Call Stacks wechseln, um mehr Details zu diesem Event zu bekommen:

Es ist an dieser Stelle jedoch etwas schwierig, zu erkennen, wie der Code während des Events tatsächlich umgesetzt wurde.

Hier jedoch helfen uns die User Marks aus der Klemme. Wir können unsere eigenen Marker hinzufügen und sind dann in der Lage einen Frame aufzuteilen. Dort können wir dann analysieren, welches Feature am aufwändigsten ist.

performance.mark("Begin of something…just now!");

Wer ein eigenes Framework erstellt, erhält daduch außerdem die sehr praktische Möglichkeit, den eigenen Code mit Messwerten zu belegen:

performance.mark("Active meshes evaluation-Begin");
this._evaluateActiveMeshes();
performance.mark("Active meshes evaluation-End");
performance.measure("Active meshes evaluation", "Active meshes evaluation-Begin", "Active meshes evaluation-End");

Schauen wir uns doch mal an, was uns das bei babylon.js bringt, hier für die Instanz mit der “V8”-Szene:

Wir können nun babylon.js auffordern, für uns User Marks und Messwerte auszusenden. Dazu benutzen wir den debug layer:

Mithilfe des UI Responsiveness Analyzer erhalten wir diese Ansicht:

Deutlich zu sehen: Die User Marks werden oberhalb des Events angezeigt (die orangefarbenen Dreiecke), ebenso die Bereiche für alle Messungen:

Auf diese Weise lässt sich in diesem Beispiel sehr leicht bestimmen, dass die Abschnitte [Render targets] und [Main render] am aufwändigsten operieren.

Der vollständige Code, den babylon.js nutzt, um den Usern zu ermöglichen, die Performance verschiedener Funktionen zu testen, sieht so aus:

  Tools._StartUserMark = function (counterName, condition) {
    if (typeof condition === "undefined") { condition = true; }
    if (!condition || !Tools._performance.mark) {
        return;
    }
    Tools._performance.mark(counterName + "-Begin");
};

Tools._EndUserMark = function (counterName, condition) {
    if (typeof condition === "undefined") { condition = true; }
    if (!condition || !Tools._performance.mark) {
        return;
    }
    Tools._performance.mark(counterName + "-End");
    Tools._performance.measure(counterName, counterName + "-Begin", counterName + "-End");
};

Tools._StartPerformanceConsole = function (counterName, condition) {
    if (typeof condition === "undefined") { condition = true; }
    if (!condition) {
        return;
    }

    Tools._StartUserMark(counterName, condition);

    if (console.time) {
        console.time(counterName);
    }
};

Tools._EndPerformanceConsole = function (counterName, condition) {
    if (typeof condition === "undefined") { condition = true; }
    if (!condition) {
        return;
    }

    Tools._EndUserMark(counterName, condition);

    if (console.time) {
        console.timeEnd(counterName);
    }
};

Dank der F12 Tools und den User Marks erhalten wir also ein sehr nützliches Dashboard, das uns zeigt, wie effizient verschiedene Teile des Codes zusammenarbeiten.

Mehr Tipps, Tricks und Hilfen rund um JavaScript

Microsoft hält eine ganze Reihe kostenloser Lehrangebote zu zahlreichen Open Source JavaScript-Themen bereit – und seit der Veröffentlichung von Microsoft Edge tun wir in diesem Bereich noch sehr viel mehr. Auch von mir gibt es Tutorials:

Außerdem haben wir noch die Schulungsreihe unseres Teams:

Praktisch sind zudem die folgenden kostenlosen Tools: Visual Studio Community, Azure Testversion sowie Cross Browser Testing Tools für Mac, Linux oder Windows.

Dieser Artikel ist Teil der Web-Dev Tech-Series von Microsoft. Wir freuen uns Microsoft Edge (früher Project Spartan genannt) und seine neue Rendering Engine mit euch zu teilen. Kostenlose Virtual Machines oder Remote Testings für Mac, iOS, Android oder Windows gibt es hier: @ dev.modern.IE.

(dpe)

Kategorien
JavaScript & jQuery Programmierung

Aus der Praxis: Wir bauen eine Chatroom Web-App mit Node.js (Teil 6)

In dieser Node.js Tutorial-Serie zeigen wir, wie man eine Node.js-getriebene Echtzeit-Chatroom Web App erstellt, die vollständig cloud-fähig ist. Es wird darum gehen, Node.js auf einem Windows-Rechner aufzusetzen, ein Web-Frontend mit Express zu entwickeln, eine Node-Express-App auf Azure zu bringen, Socket.IO zu nutzen, um einen Echtzeit-Layer hinzuzufügen und zu zeigen, wie man das Ganze zum Schluss einsetzt.

Aus der Praxis: Wir bauen eine Chatroom Web-App mit Node.js

Schwierigkeitsstufe: Einsteiger bis mittlere Kenntnisse, vorausgesetzt werden HTML5 und JavaScript

Teil 6 – Das Finale: Debugging Remote-Node-Apps

Herzlich willkommen zum sechsten und gleichzeitig letzten Teil unserer Praxis-Serie zu Node.js: Wir programmieren eine Node.js-getriebene Chatroom Web-App.

In dieser letzten Folge geht es um die finale Bereitstellung des Chatrooms. Ich erkläre euch, wie man dabei ein Remote Debugging durchführt.

In Azure bereitstellen!

Unsere Node.js-getriebene anonyme Chatroom-App läuft. Dann wollen wir sie jetzt mit ein paar Klicks auch in der Cloud bereitstellen. Das funktioniert mit jeder Cloud, die Node.js unterstützt. Ich werde hier Microsoft Azure benutzen, weil ich dort auch eine Node.js Website kostenlos laufen lassen kann.

Einen kostenlosen Testzugang für Microsoft Azure gibt es hier. Dieser ermöglicht, Microsoft Azure einen Monat lang im Wert von €170 zu testen. Auf dem Service, den wir hier nutzen, Azure Websites, kann man damit bis zu zehn Webseiten kostenlos laufen lassen.

1. Sobald das Azure-Konto eingerichtet ist, gehen wir zurück zur IDE. Dort führen wir auf unserem Express-Projekt einen Rechtsklick aus und wählen im Menü dann „Publish„.

Wir bauen eine Chatroom Web-App mit Node.js

2. Das Menü „Publish“ öffnet einen Assistenten mit einigen Optionen. Wir wählen als Ziel Microsoft Azure-Websites.

3. An dieser Stelle erfolgt der Login, und zwar mit dem gleichen Microsoft-Konto wie bei der Azure-Anmeldung.

4. Nun wählen wir „New“ aus, um eine neue Azure-Webseite zu erstellen. Existiert schon eine, könnten wir auch einfach diese im Dropdown-Menü auswählen.

clip_image003

5. Nun füllen wir die Felder im Assistenten aus (siehe unten). Darauf achten, einen unverwechselbaren Namen für die Seite zu wählen und dann „Create“ klicken.

BLOG POST - Part 6 - Screenshot 3

6. Als Nächstes erscheint ein vorausgefüllter Assistent mit einem Button „Publish“, den wir klicken.

clip_image007

Geschafft! Das Projekt ist in der Azure-Cloud veröffentlicht! Aber die Arbeit ist damit noch nicht vollständig erledigt.

WebSockets bei Azure-Websites aktivieren

Um sicherzustellen, dass WebSockets auf unserer Website aktiviert ist, müssen wir ein paar weitere Dinge erledigen. Wer sich das Ganze gern etwas detaillierter ansehen oder die FAQ dazu durchstöbern will, sollte sich diese Seite nicht entgehen lassen.

Als erstes aktivieren wir WebSockets von der Azure-Befehlszeile oder dem Konfigurations-Tab aus:

clip_image008

Dann ändern wir unsere web.config Datei und die folgende Zeile zum system.webServer XML-Element.

<webSocket enabled="false" />

Das klingt erstmal unlogisch, ist aber genau richtig so. Denn dieser Schritt deaktiviert das IIS-WebSockets-Modul, das seine eigene WebSockets-Implementierung enthält und mit Node.js-spezifischen WebSockets Modulen wie Socket.IO kollidiert.

Das Debugging von Remote Node Apps

Node Tools für Visual Studio (NTVS) hat etliche fortgeschrittene Debug-Funktionen dabei, wie zum Beispiel bedingte Programmstopps, “Hit Count“- Programmstopps, Tracepoints und Remote Debugging Support für Windows, Linux und OS X. Mehr dazu gibt es hier.

Mit Remote Node-Instanzen verbinden

NTVS unterstützt Remote Debugging Code, der auf Azure-Websites läuft. Im Gegensatz zu gewöhnlichem Remote Debugging ist hier der Zielrechner nicht direkt über TCP zu erreichen. NTVS besitzt dafür einen WebSocket-Proxy für das Debugging-Protokoll, der das Protokoll via HTTP zeigt.

Wenn man ein Windows-Azure-Projekt aufsetzt, ist der Proxy bereits vollständig konfiguriert in Web.Debug.config. Um ihn auf der Azure-Website zu aktivieren, muss man das Projekt in der Debug-Konfiguration veröffentlichen. Das tun wir mit den nun folgenden Schritten.

1. Rechtsklick auf dem Projekt und Publish auswählen.

clip_image001[1]

2. Links den Tab Settings auswählen und im Dropdown-Menü die Konfiguration “Debug” wählen.

clip_image010

3. Auf Publish klicken.

Wenn unser Projekt ordnungsgemäß bereitgestellt und WebSockets aktiviert wurde, können wir die Website vom Server-Explorer aus einfügen. Wer das Server-Explorer-Fenster noch nicht geöffnet hat, kann das über View > Server Explorer tun. Unter Windows Azure > Web Sites können wir dann unsere Website finden. Dort führen wir dann einen Rechtsklick aus. Wenn die Website läuft und das Projekt mithilfe der Debug-Konfiguration bereitgestellt wurde, sollte im Kontextmenü der Attach Debugger (Node.js)-Befehl sichtbar sein.

clip_image011

Protokolle lesen und streamen

Das Streaming der aktuellen Protokolle ist nicht schwierig. Wir müssen einfach im Server-Explorer auf unsere Webseite rechtsklicken und View Streaming Logs auswählen.

clip_image012

Fazit

Glückwunsch! Wir haben es vollbracht! Der anonyme Echtzeit-Chatroom läuft in der Cloud. In dieser Tutorial-Serie haben wir nicht nur gelernt, wie man Node aufsetzt, ein Web-Frontend mit Express entwickelt und die App in die Cloud bringt, sondern auch wie man socket.io nutzt, um einen Echtzeit-Layer einzufügen. Zu guter Letzt wissen wir nun auch, wie man das Ganze am Ende bereitstellt.

clip_image013

Wer will, kann die einzelnen Teile noch mal auf meinem Blog nachlesen (in englischer Sprache). Hin und wieder stelle ich dort auch Updates zu diesem Tutorial bereit. Wer mehr Neuigkeiten dazu erfahren will, kann mir einfach auf Twitter folgen @ramisayar.

P.S. Ja, auch für noch mehr „Hurra-GIFs“ habe ich einen Link-Tipp.

Alle Teile der Node.js-Serie hier bei Dr. Web

#1: Einführung in Node.js

#2: Express mit Node.js und Azure

#3: Ein Chatroom-Backend mit Node.js, Socket.IO und Mongo aufsetzen

#4: Eine Chatroom-UI mit Bootstrap erstellen

#5: Den Chatroom mit WebSockets verbinden

#6: Das Finale: Debugging Remote-Node-Apps (dieser Beitrag)

Noch mehr Lernmaterial zu Node.js auf Azure

Ausführlichere Lehrinhalte zu Node gibt es in meinem Kurs an der Microsoft Virtual Academy.

Sehr hilfreich sind auch diese Kurzvideos zu ähnlichen Node-Themen:

Dieser Artikel ist Teil der Web-Dev Tech-Series von Microsoft. Wir freuen uns Microsoft Edge (früher Project Spartan genannt) und seine neue Rendering Engine mit euch zu teilen. Kostenlose Virtual Machines oder Remote Testings für Mac, iOS, Android oder Windows gibt es hier: @ dev.modern.IE.

(dpe)

Kategorien
JavaScript & jQuery Programmierung

Aus der Praxis: Wir bauen eine Chatroom Web-App mit Node.js (Teil 5)

In dieser Node.js Tutorial-Serie zeigen wir, wie man eine Node.js-getriebene Echtzeit-Chatroom Web App erstellt, die vollständig cloud-fähig ist. Es wird darum gehen, Node.js auf einem Windows-Rechner aufzusetzen, ein Web-Frontend mit Express zu entwickeln, eine Node-Express-App auf Azure zu bringen, Socket.IO zu nutzen, um einen Echtzeit-Layer hinzuzufügen und zu zeigen, wie man das Ganze zum Schluss einsetzt.

Wir bauen eine Chatroom Web-App mit Node.js (Teil 5)

Schwierigkeitsstufe: Einsteiger bis mittlere Kenntnisse, vorausgesetzt werden HTML5 und JavaScript

Teil 5 – Den Chatroom mit WebSockets verbinden

Willkommen zurück zu Teil 5 unserer Praxis-Serie zu Node.js: Wir programmieren eine Node.js-getriebene Chatroom Web-App.

In diesem Teil erkläre ich, wie man den Frontend-Chatroom mit dem Node-Chatroom-Backend verbindet, das wir in Teil 2, Teil 3 und Teil 4 erstellt haben.

Hinzufügen von jQuery, SocketIO und index.js

Bevor wir beginnen, unseren Frontend-JavaScript-Code zu schreiben, sollten wir sicherstellen, dass alle benötigten Dateien und Abhängigkeiten vom Node-Server ausgeliefert werden. Zu Beginn fügen wir jQuery und Socket.IO der Datei layout.jade hinzu, die durch alle anderen jade Dateien unseres Projekts erweitert wird.

WIr ersetzen den Link zu bootstrap.min.js mit einem Link zu allen Dateien, die wir benötigen.

script(type='text/javascript' src='http://ajax.aspnetcdn.com/ajax/jQuery/jquery-2.1.1.min.js')
script(type='text/javascript' src='/js/bootstrap.min.js')
script(type='text/javascript' src='/socket.io/socket.io.js')

Beachte: die erste Zeile verweist auf jQuery, das im Microsoft Ajax Content Delivery Network gehostet wird. Dieses CDN beinhaltet beliebte JavaScript-Bibliotheken von Drittanbietern, wie jQuery. Dadurch kann man diese sehr einfach den eigenen Webanwendungen hinzufügen. Die Performance von Ajax-Anwendungen wird durch die Nutzung eines CDN deutlich verbessert. Die Inhalte eines CDN werden auf weltweit verteilten Servern zwischengespeichert. Das CDN unterstützt SSL (HTTPS) für den Fall, dass man eine Webseite mit der Hilfe von Secure Sockets Layer ausliefern will.

Nun füge ich am Ende eine weitere Zeile hinzu, um einen neuen Block zu erstellen.

block body_end

Dadurch kann jede Jade-Datei, die eine layout.jade Erweiterung hat, auch Script-Tags unmittelbar vor dem Ende des Body-Tags einfügen.

Jetzt nutzen wir unseren neuen Block, um dort einen Link zu unserer index.js-Datei einzufügen, die wir im Ordner public/js erstellen werden (bitte nicht vergessen).

block body_end
  script(type='text/javascript' src='/js/index.js')

Wichtig: Der Block beginnt ohne Einzug, um den Code-Konventionen von Jade zu genügen. Wer jetzt den Node-Server ausführt und zur Hauptseite seines Browsers geht, wird in den F12-Tools entdecken, dass die Dateien korrekt ausgeliefert werden.

Schnelle Anpassungen in app.js

Jetzt würde ich gern paar Dinge in app.js ändern. Als erstes will ich die Reihenfolge der Sortierung umkehren – damit die ältesten Mitteilungen zuerst gesendet werden. Außerdem sollen die neuesten Chat-Nachrichten auf dem gleichen Kanal gesendet werden, auf dem die neuen Nachrichten empfangen werden. Diese Änderungen vollziehe ich in den Zeilen 49 und 50 von app.js. Und so sieht es dann aus:

var stream = collection.find().sort().limit(10).stream();
stream.on('data', function (chat) { socket.emit('chat', chat.content); });

Nicht vergessen: Die Umgebungsvariable CUSTOMCONNSTR_MONGOLAB_URI muss festgelegt werden, bevor die app.js-Datei erneut aufgerufen wird, da ansonsten das Node-Backend abstürzt, weil es keine Verbindung zur MongoDB herstellen kann.

Den Send-Button aktivieren

Nun ist es an der Zeit, den Send-Button zu aktivieren, um mithilfe von WebSockets Nachrichten im Mitteilungsfeld an den Backend-Server des Chat-Channels zu senden.

var socket = io();
$('#send-message-btn').click(function () {
    var msg = $('#message-box').val();
    socket.emit('chat', msg);
    $('#messages').append($('
').text(msg)); $('#message-box').val(''); return false; }); socket.on('chat', function (msg) { $('#messages').append($('

').text(msg)); });

Zeile 1

Wir erstellen ein Socket, indem wir die Funktion io() aufrufen, die sich in der Datei socket.io-client.js befindet.

Zeile 2

Danach sorgen wir dafür, dass durch einen Klick auf den Send-Message-Button eine Funktion ausgeführt wird. Dafür nutzen wir die Funktion $ von jQuery und den Click-Event-Handler.

Zeile 3

Wir erhalten den String-Value des Mitteilungsfensters mithilfe der Funktion $ von jQuery.

Zeile 4

Wir nutzen die emit-Funktion auf der Socket-Variable, die wir in Zeile 1 erstellt haben, um eine Mitteilung an den ‘chat’-Channel zu senden, die den Wert des Mitteilungsfensters enthält.

Zeilen 5-7

Hier fügen wir die Nachricht im Mitteilungsfenster der Div #messages hinzu, damit der User erkennt, dass die Nachricht gesendet wurde. Wir weisen den Wert des Mitteilungsfensters einem leeren String zu, um es wieder frei zu machen.

Zeilen 9-10

Wir wollen die im Chat-Channel erhaltenen Nachrichten anderer User der Div #messages hinzufügen. Das Node-Backend wird die vom Client geschriebene Mitteilung nicht an sich selbst zurücksenden. Aber das geht in Ordnung, weil wir diese schon im Click-Handler eingefügt haben.

Wir bauen eine Chatroom Web-App mit Node.js (Teil 5)

Fazit

Geschafft! Wir haben Backend und Frontend mithilfe von WebSockets verbunden. Wer jetzt noch eine Identifikation oder Avatare für alle User hinzufügen will – kein Problem. Aber auch ohne das ist der Chatroom jetzt einsatzbereit. In der nächsten Folge erkläre ich wie der Chatroom auf Azure angewendet und von Fehlern befreit wird.

Dranbleiben für Teil 6!

Teil 6 — das Finale mit dem Debugging von Remote Node Apps — wird schon bald hier bei Dr. Web veröffentlicht. In englischer Sprache gibt es ihn schon auf meinem Blog.

Wer mehr Neuigkeiten dazu und zu anderen Artikeln erfahren will, kann mir einfach auf Twitter folgen: @ramisayar.

Weitere Teile der Serie bei MSDN (in englischer Sprache)

Part 1 – Introduction to Node.js
Part 2 – Welcome to Express with Node.js and Azure
Part 3 – Building a Backend with Node, Mongo and Socket.IO
Part 4 – Building a Chatroom UI with Bootstrap
Part 5 – Connecting the Chatroom with WebSockets
Part 6 – The Finale and Debugging Remote Node Apps

Noch mehr Lernen über Node auf Azure

Ausführlichere Lehrinhalte zu Node gibt es in meinem Kurs an der Microsoft Virtual Academy.

Sehr hilfreich sind auch diese Kurzvideos zu ähnlichen Node-Themen:

Dieser Artikel ist Teil der Web-Dev Tech-Series von Microsoft. Wir freuen uns Microsoft Edge (früher Project Spartan genannt) und seine neue Rendering Engine mit euch zu teilen. Kostenlose Virtual Machines oder Remote Testings für Mac, iOS, Android oder Windows gibt es hier: @ dev.modern.IE.

(dpe)

Kategorien
JavaScript & jQuery Programmierung

Aus der Praxis: Wir bauen eine Chatroom Web-App mit Node.js (Teil 4)

In dieser Node.js Tutorial-Serie zeigen wir, wie man eine Node.js-getriebene Echtzeit-Chatroom Web App erstellt, die vollständig cloud-fähig ist. Es wird darum gehen, Node.js auf einem Windows-Rechner aufzusetzen, ein Web-Frontend mit Express zu entwickeln, eine Node-Express-App auf Azure zu bringen, Socket.IO zu nutzen, um einen Echtzeit-Layer hinzuzufügen und zu zeigen, wie man das Ganze zum Schluss einsetzt.

Aus der Praxis: Wir bauen eine Chatroom Web App mit Node.js (Teil 4)

Schwierigkeitsstufe: Einsteiger bis mittlere Kenntnisse, vorausgesetzt werden HTML5 und JavaScript

Teil 4 – Eine Chatroom-UI mit Bootstrap erstellen

Willkommen zurück zu Teil 4 unserer Praxis-Serie zu Node.js: Wir programmieren eine Node.js-getriebene Chatroom Web-App. In diesem Teil erkläre ich, wie man ein mit Bootstrap entworfenes Frontend dem Chatroom-Backend hinzufügt, welches wir in Teil 2 und Teil 3 gebaut haben.

Was ist Bootstrap?

Bootstrap ist ein sehr weit verbreitetes und beliebtes HTML- und CSS-Framework, um Websites und Web-Anwendungen zu erstellen. Es ist mit Abstand das Top-Projekt bei GitHub. Bootstrap unterstützt responsives Webdesign, wodurch eine Webseite unabhängig vom Gerät korrekt dargestellt wird, egal ob auf dem Desktop-Computer, einem Tablet oder anderen Mobilgeräten, wie Smartphones etc.

Bootstrap dem Projekt hinzufügen

Um Bootstrap unserem Projekt hinzuzufügen, müssen wir die verkleinerten CSS- und JS-Dateien für Bootstrap herunterladen. Das ist hier möglich. Nach dem Download von Bootstrap gilt es, die Datei zu entpacken und die Ordner “css”, “js” und “fonts” in den “public”-Ordner unseres Projekts zu kopieren.

In unserer bestehenden Ordnerstruktur fallen jetzt ein paar Unstimmigkeiten ins Auge. Wir werden daher die Stylesheets- und JavaScript-Ordner vereinheitlichen. Ich persönlich bevorzuge die Bootstrap-Benennungen, das heißt “css” statt “stylesheets” und “js” statt “javascripts”, da diese mit den Libraries von Drittanbietern geteilt werden. Nun kopieren wir die Dateien von “stylesheets” in “css” und löschen den “javascripts” Ordner, der jetzt leer sein sollte. In layout.jade ändern wir dann die folgende Zeile:

link(rel='stylesheet' href='/stylesheets/style.css')

zu:

link(rel='stylesheet' href='/css/style.css')

Als nächstes fügen wir die Bootstrap-CSS-Links im Header und die entsprechenden Meta-Tags für HTML5-Apps in der layout.jade-Datei hinzu. Die folgenden Zeilen müssen vor der Zeile mit dem style.css-Link eingefügt werden.

meta(charset="utf-8")
meta(http-equiv="X-UA-Compatible" content="IE=edge")
link(rel='stylesheet' href='/css/bootstrap.min.css')
link(rel='stylesheet' href='/css/bootstrap-theme.min.css')

Nun fügen wir die JavaScript-Datei hinzu, die Bootstrap für seine Komponenten und Plugins benötigt. Dazu fügen wir die folgende Zeile am Ende von layout.jade ein:

script(type='text/javascript' src='/js/bootstrap.min.js')

Vollständiges layout.jade

doctype html
html
  head
    title= title
    meta(charset="utf-8")
    meta(http-equiv="X-UA-Compatible" content="IE=edge")
    link(rel='stylesheet' href='/css/bootstrap.min.css')
    link(rel='stylesheet' href='/css/bootstrap-theme.min.css')
    link(rel='stylesheet' href='/css/style.css')

  body
    block content

    script(type='text/javascript' src='/js/bootstrap.min.js')

Erstellen des Chat-UI-Layouts

Jetzt ist das Chat-Userinterface-Layout an der Reihe. Hier ist es sicher hilfreich, sich tiefer in Bootstrap einzulesen und dieses etwas längere Tutorial anzuschauen. Alle Chat-Engines haben einen Bereich für die aktuellen Mitteilungen und einen Bereich, in dem die Nutzer Mitteilungen schreiben und senden können. Traditionell war das Layout so gestaltet, dass die Mitteilungen oben erschienen und das Schreibfeld unten positioniert war.

Es erfordert einen gewissen Aufwand, um in HTML ein Element am unteren Rand des Viewports zu fixieren. Ich werde mich dafür an diesem Beispiel orientieren, um unten eine Fußzeile zu fixieren. Dazu modifizieren wir die index.jade-Datei und entfernen alle Code-Zeilen unterhalb des Content-Blocks.
Zunächst fügen wir den Seitenbereich ein, der die ankommenden Mitteilungen enthalten soll.

Dazu fügen wir erstmal eine div mit der Klasse wrap hinzu. In Jade müssen wir einfach nur wrap schreiben, um eine <div class=”wrap”></div> zu erstellen. Indem wir den Einzug nutzen, teilen wir der Jade-Templating-Engine mit, dass mehr eingerückte Elemente innerhalb der weniger eingerückten Elemente stehen.

Wer es in den anderen Teilen des Tutorials verpasst hat: Dieses Jade-Tutorial lohnt sich wirklich.

Als nächstes fügen wir eine weitere div mit der Klasse container-fluid hinzu, um der Seite eine flexible Breite zu geben. Dazu kommt ein H1-Element: “Welcome to the Node Chatroom” sowie eine div mit einer ID messages und schließlich eine div mit der Klasse push, mit dem wir das Bearbeitungsfeld für Mitteilungen im Chatroom an das untere Ende des Viewports schieben.

  .wrap
    .container-fluid
        h1 Welcome to the Node Chatroom
        #messages

        .push

Nun gehen wir daran, das Schreibfeld zu programmieren. Dabei wollen wir das Textfeld und den Sende-Button in einer div namens Footer und einer div namens „container-fluid“ erfassen. Das Footer div hat den gleichen Einzug wie das wrap div.

Jetzt nutzen wir das Bootstrap-Grid-System (mehr dazu hier) um das Textfeld in zwei Teile zu trennen. In der größeren Spalte wird man die Mitteilungen schreiben können, die andere enthält den Block-Level-Button, mit dem man die Nachricht absenden kann.

Deutlich wird, dass Jade uns ermöglicht, die Attribute eines Elements mit Hilfe der Absatzvermerke genau festzulegen. Der Code sieht dann wie folgt aus:

  .footer
    .container-fluid
      .row
        .col-xs-8.col-sm-9
          input(type="text" id="message-box" class="form-control input-lg" placeholder="Write a message here..." rows="3")
        .col-xs-4.col-sm-3
          button#send-message-btn.btn.btn-primary.btn-lg.btn-block Send Message

Vollständiges index.jade

extends layout

block content
  .wrap
    .container-fluid
        h1 Welcome to the Node Chatroom
        #messages

        .push
  .footer
    .container-fluid
      .row
        .col-xs-8.col-sm-9
          input(type="text" id="message-box" class="form-control input-lg" placeholder="Write a message here..." rows="3")
        .col-xs-4.col-sm-3
          button#send-message-btn.btn.btn-primary.btn-lg.btn-block Send Message

Mit CSS das Textfeld unten fixieren

Um das Textfeld unten in der Ansicht zu fixieren, werden wir einige benutzerdefinierte CSS zur Seite public/css/style.styl hinzufügen. Diese Datei nutzt den Stylus CSS-Präprozessor, aber man kann auch textbasiertes CSS kopieren, welches erneut in die erstellte CSS-Datei kopiert wird.

Zunächst stellen wir sicher, dass die ganze Seite wirklich 100% der Höhe einnimmt.

html, body
  height: 100%

Dann achten wir darauf, dass der Wrap-Bereich die maximal mögliche Höhe einnimmt, aber unten einen Rand von 60px für unsere Fußzeile und das Textfeld lässt.

.wrap 
  min-height: 100%
  height: auto !important
  height: 100%
  margin: 0 auto -60px

Nun stellen wir sicher, dass die Fläche für den Textbereich berücksichtigt wird und ordnen diese der Fußzeile zu.

.push, .footer 
  height: 60px

Um zum Schluss noch etwas stylisch zu werden, geben wir der Fußzeile eine dezente Hintergrundfarbe.

.footer
  background-color: #f5f5f5

Vollständige Style.styl

html, body
  height: 100%
 
.wrap 
  min-height: 100%
  height: auto !important
  height: 100%
  margin: 0 auto -60px
 
.push, .footer 
  height: 60px
 
.footer
  background-color: #f5f5f5

Screenshot

Fazit

Perfekt! Wir haben Bootstrap und die Jade/Stylus-Präprozessoren genutzt, um unseren Node-basierten Chatroom mit einem netten UI-Layout auszustatten. Im nächsten Teil werde ich erklären, wie man die UI und das Node-Backend via WebSockets verbindet.

Dranbleiben für Teil 5!

Teil 5 — Den Chatroom mit WebSockets verbinden — wird schon bald hier bei Dr. Web veröffentlicht. Wer mehr Neuigkeiten dazu und zu anderen Artikeln erfahren will, kann mir einfach auf Twitter folgen: @ramisayar.

Weitere Teile der Serie bei MSDN (in Englisch)

Part 1 – Introduction to Node.js
Part 2 – Welcome to Express with Node.js and Azure
Part 3 – Building a Backend with Node, Mongo and Socket.IO
Part 4 – Building a Chatroom UI with Bootstrap
Part 5 – Connecting the Chatroom with WebSockets
Part 6 – The Finale and Debugging Remote Node Apps

Noch mehr Lernen über Node auf Azure

Ausführlichere Lehrinhalte zu Node gibt es in meinem Kurs an der Microsoft Virtual Academy.

Sehr hilfreich sind auch diese Kurzvideos zu ähnlichen Node-Themen:

Dieser Artikel ist Teil der Web-Dev Tech-Series von Microsoft. Wir freuen uns Microsoft Edge (früher Project Spartan genannt) und seine neue Rendering Engine mit euch zu teilen. Kostenlose Virtual Machines oder Remote Testings für Mac, iOS, Android oder Windows gibt es hier: @ dev.modern.IE.

(dpe)

Kategorien
JavaScript & jQuery Programmierung

Aus der Praxis: Wir bauen eine Chatroom Web-App mit Node.js (Teil 3)

In dieser Node.js Tutorial-Serie zeigen wir, wie man eine Node.js-getriebene Echtzeit-Chatroom Web App erstellt, die vollständig cloud-fähig ist. Es wird darum gehen, Node.js auf einem Windows-Rechner aufzusetzen, ein Web-Frontend mit Express zu entwickeln, eine Node-Express-App auf Azure zu bringen, Socket.IO zu nutzen, um einen Echtzeit-Layer hinzuzufügen und zu zeigen, wie man das Ganze zum Schluss einsetzt.

Aus der Praxis: Wir bauen eine Chatroom Web-App mit Node.js (Teil 3)

Schwierigkeitsstufe: Einsteiger bis mittlere Kenntnisse, vorausgesetzt werden HTML5 und JavaScript.

Teil 3 – Ein Chatroom Backend mit Node.js, Socket.IO und Mongo aufsetzen

Willkommen zurück zu Teil 3 der Praxis-Tutorialserie zu Node.js: Wir programmieren eine Node.js-getriebene Chatroom-Web-App. In diesem Teil erkläre ich, wie man die bestehende Express-basierte Node.js-App nutzt, um ein Chatroom-Backend mit WebSocket-Unterstützung zu erstellen.

Was sind WebSockets? Was ist Socket.IO?

WebSocket ist ein Netzwerkprotokoll, mit dem Web-Anwendungen eine bidirektionale Verbindung zwischen Webbrowser und Webserver über TCP aufbauen können. Es ist vollständig kompatibel mit HTTP und nutzt den TCP-Port 80. WebSocket ermöglicht Web-Anwendungen in Echtzeit und fortgeschrittene Interaktionen zwischen Client und Server. Das Protokoll wird von zahlreichen Servern unterstützt, darunter Edge und Internet Explorer, Google Chrome, Firefox, Safari und Opera.

Socket.IO ist eine JavaScript-Library und ein Node.js-Modul. Damit gelingt es sehr einfach und schnell, bidirektionale, event-basierte Kommunikations-Apps zu erstellen. Die Nutzung von WebSockets wird dadurch stark vereinfacht. Wir werden für unsere Chatroom-App Socket.IO v1.0 benutzen.

Socket.IO zu package.json hinzufügen

Package.json ist eine Datei, die verschiedene Metadaten enthält, die für das Projekt relevant sind, einschließlich ihrer Abhängigkeiten. NPM nutzt diese Datei, um Module zu laden, die für das Projekt benötigt werden. Hier lohnt es sich, einen Blick auf diese interaktive Erklärung von package.json und was alles drin steckt, zu werfen.
Nun fügen wir Socket.IO dem Projekt als Abhängigkeit hinzu. Das kann man auf zweierlei Weise tun.

1. Wer schon die anderen Teile der Tutorial-Serie verfolgt und bereits ein Projekt im Visual Studio Setup erstellt hat, braucht nur einen Rechtsklick auf den NPM-Teil des Projekts auszuführen, um dann “Install New npm Packages…” auszuwählen.

clip_image002

Nachdem sich das Fenster geöffnet hat, suchen wir nach “socket.io”, wählen das oberste Ergebnis aus und machen ein Häkchen bei “Add to package.json”. Dann klicken wir den Button “Install Package”. Nun wird Socket.IO in unserem Projekt installiert und zur package.json-Datei hinzugefügt.

clip_image004

package.json

{
  "name": "NodeChatroom",
  "version": "0.0.0",
  "description": "NodeChatroom",
  "main": "app.js",
  "author": {
    "name": "Rami Sayar",
    "email": ""
  },
  "dependencies": {
    "express": "3.4.4",
    "jade": "*",
    "socket.io": "^1.0.6",
    "stylus": "*"
  }
}

2. Wer mit OS X oder Linux arbeitet, muss den folgenden Befehl im Root-Verzeichnis des Projektordners ausführen, um das gleiche Ergebnis zu erhalten.

npm install --save socket.io

Socket.IO der app.js hinzufügen

Im nächsten Schritt fügen wir Socket.IO der app.js hinzu. Dazu suchen wir den folgenden Code:

http.createServer(app).listen(app.get('port'), function(){
  console.log('Express server listening on port ' + app.get('port'));
});

Und ersetzen ihn durch:

var serve = http.createServer(app);
var io = require('socket.io')(serve);

serve.listen(app.get('port'), function () {
    console.log('Express server listening on port ' + app.get('port'));
});

Auf diese Weise wird der HTTP-Server in einer Variable namens serve erfasst und übermittelt, so dass das Socket.IO Modul sich diesem zuordnet. Der letzte Block des Codes nimmt die Variable serve und führt die Funktion listen aus, welche den HTTP-Server startet.

Protokollieren, wenn User kommen und gehen

Gut wäre es natürlich, protokollieren zu können, wenn ein User den Chatroom betritt. Das gelingt mit dem folgenden Code. Er löst bei jedem connection Event eine Callback-Funktion via WebSocket an unseren HTTP-Server aus. In der Callback-Funktion rufen wir console.log auf, um zu protokollieren, dass ein User anwesend ist. Wir können diesen Code hinzufügen, nachdem wir serve.listen aufgerufen haben.

io.on('connection', function (socket) {
    console.log('a user connected');
});

Um auch festzuhalten, wann ein User den Chatroom verlässt, müssen wir das disconnect Event für jedes Socket verbinden. Wir fügen dazu den folgenden Code nach dem console.log des vorhergehenden Code-Blocks hinzu.

    socket.on('disconnect', function () {
        console.log('user disconnected');
    });

Und so sieht der Code dann aus:

io.on('connection', function (socket) {
    console.log('a user connected');
    socket.on('disconnect', function () {
        console.log('user disconnected');
    });
});

Senden einer Mitteilung aus dem Chat-Channel

Socket.IO besitzt eine Funktion namens emit, um Events zu übertragen.
Nach dem Empfang einer Mitteilung im Chat-Channel, wird sie durch den Aufruf von emit mit dem Sende-Marker in der Callback-Funktion an alle anderen Verbindungen auf diesem Socket gesendet.

socket.on('chat', function (msg) {
    socket.broadcast.emit('chat', msg);
});

So sieht der Code dann aus:

io.on('connection', function (socket) {
    console.log('a user connected');
    socket.on('disconnect', function () {
        console.log('user disconnected');
    });
 
    socket.on('chat', function (msg) {
        socket.broadcast.emit('chat', msg);
    });
});

Mitteilungen in einer NoSQL-Datenbank sichern

Der Chatroom sollte Chat-Mitteilungen in einem einfachen Datenspeicher sichern. Für gewöhnlich gibt es zwei Wege, um Datenbestände in Node zu speichern. Entweder man nutzt einen Datenbank-spezifischen Driver oder eine ORM. In diesem Tutorial werde ich MongoDB nutzen, um die Mitteilungen zu sichern. Natürlich gibt es viele weitere Möglichkeiten, einschließlich SQL-Datenbanken wie PostgreSQL oder MySQL.

Als erstes stellen wir sicher, dass wir eine MongoDB haben, mit der wir uns verbinden können. Diese kann man auch von Drittanbietern, wie MongoHQ oder MongoLab, hosten lassen. In diesem Tutorial wird sehr gut gezeigt, wie man eine MongoDB mit Hilfe des MongoLab-Add-On in Azure erstellt. Für unsere Zwecke reicht es hier, bis zu “Create the App” zu lesen. Hauptsache, wir haben die MONGOLAB_URI irgendwo gespeichert und können auf diese später leicht zugreifen.

Nachdem wir die MongoDB erstellt haben und MONGOLAB_URI für die Datenbank haben (zu finden unter Connection-Information in der Zwischenablage), werden wir dafür sorgen, dass der URI für die Anwendung verfügbar ist. Es ist nicht zu empfehlen, vertrauliche Informationen wie diesen URI in den Code oder in eine Konfigurationsdatei unseres Quellcode-Management-Tools einzubauen.

Wir können den Wert der Connection-Strings-Liste im Konfigurationsmenü unserer Azure-Web-Anwendung hinzufügen (wie im vorhergehenden Tutorial beschrieben) oder wir fügen ihn der App-Setting-Liste hinzu (mit dem Namen CUSTOMCONNSTR_MONGOLAB_URI). Auf unserem lokalen Rechner können wir den Wert den Umgebungsvariablen hinzufügen; mit dem Namen CUSTOMCONNSTR_MONGOLAB_URI und dem Wert des URI.

Im nächsten Schritt sorgen wir dafür, dass unser Projekt MongoDB unterstützt. Das gelingt, indem wir die folgende Zeile dem Abhängigkeiten-Objekt in package.json hinzufügen. Vergesst dabei nicht das Sichern der Änderungen in der Datei.

"mongodb": "^1.4.10",

Es folgt ein Rechtsklick im NPM-Teil der Projekts im Solution-Explorer, um das Kontextmenü anzeigen zu lassen. Jetzt “Install missing npm packages” klicken, um das MongoDB Paket zu installieren und es damit als Modul nutzbar zu machen.

clip_image005

Nun importieren wir dieses Modul, um das MongoDB-Client-Object in app.js nutzen zu können. Dafür fügen wir die folgenden Code-Zeilen nach den ersten require(‘’) Funktionsaufrufen ein, wie in Zeile 11.

var mongo = require('mongodb').MongoClient;

Nun wollen wir uns mit der Datenbank mit Hilfe des URI verbinden, das uns in der CUSTOMCONNSTR_MONGOLAB_URI-Umgebungsvariable vorliegt. Nachdem wir verbunden sind, fügen wir die Chat-Mitteilung ein, die über die Socket-Verbindungen empfangen wurde.

mongo.connect(process.env.CUSTOMCONNSTR_MONGOLAB_URI, function (err, db) {
    var collection = db.collection('chat messages');
    collection.insert({ content: msg }, function (err, o) {
        if (err) { console.warn(err.message); }
        else { console.log("chat message inserted into db: " + msg); }
    });
});

Deutlich im obigen Code zu sehen: Wir nutzen das process.env-Objekt, um den Wert der Umgebungsvariable zu erhalten. Nun begeben wir uns in eine Collection in der Datenbank und rufen die Insert-Funktion mit dem Inhalt in einem Objekt auf.

Nun wird jede Mitteilung in der MongoDB-Datenbank gespeichert.

Aussenden der zehn aktuellsten Mitteilungen

Natürlich sollen sich die User nicht total verloren fühlen, nachdem sie den Chatroom betreten haben. Daher ist es sicher sinnvoll, die letzten zehn erhaltenen Mitteilungen vom Server zu senden, um den Usern etwas Kontext zu geben. Dafür müssen wir Mongo verbinden. In diesem Fall nehme ich davon Abstand, den gesamten Socket-Code mit nur einer Verbindung in die Datenbank zu schicken. So ist sicher gestellt, dass der Server weiter arbeiten kann, auch wenn die Verbindung zur Datenbank mal verloren geht.

Um die Liste zu sortieren, und die Anfrage tatsächlich auf die zehn aktuellsten Mitteilungen zu beschränken, nutzen wir die von MongoDB generierte _id, da sie einen Zeitmarker enthält (in komplexeren Anwendungen ist es stets angebracht, einen Zeitmarker für jede Mitteilung zu haben). Jetzt rufen wir die limit-Funktion auf, um unsere Liste auf zehn Mitteilungen zu beschränken.

Wir streamen die Ergebnisse von MongoDB, damit sie an den Chatroom ausgesendet werden können, sobald sie eingetroffen sind.

mongo.connect(process.env.CUSTOMCONNSTR_MONGOLAB_URI, function (err, db) {
    var collection = db.collection('chat messages')
    var stream = collection.find().sort({ _id : -1 }).limit(10).stream();
    stream.on('data', function (chat) { socket.emit('chat', chat.content); });
});

Der obige Code erledigt den Job genau so, wie in den vorhergehenden Absätzen beschrieben.

Auf Azure anwenden

Um das Ganze wieder auf Azure laufen zu lassen, kann man einfach den Schritten folgen, die in den vergangenen Teilen des Tutorials beschrieben wurden (zum Beispiel in Teil 2).

Fazit

Nun haben wir ein Chat-System erstellt, das über WebSockets empfangene Mitteilungen an alle verbundenen Clients aussendet. Außerdem sichert es die Nachrichten in einer Datenbank und stellt die zehn aktuellsten Mitteilungen bereit, um allen Usern, die den Chatroom betreten, ausreichend Kontext zu geben.

Und jetzt heißt es: dran bleiben. Denn Teil 4 — Eine Chatroom-UI mit Bootstrap erstellen — wird schon bald hier bei Dr. Web veröffentlicht. Wer mehr Neuigkeiten dazu und zu anderen Artikeln erfahren will, kann mir einfach auf Twitter folgen @ramisayar.

Weitere Teile der Serie bei MSDN (in englischer Sprache)

Part 1 –  Introduction to Node.js
Part 2  – Welcome to Express with Node.js and Azure
Part 3 – Building a Backend with Node, Mongo and Socket.IO
Part 4 – Building a Chatroom UI with Bootstrap
Part 5 – Connecting the Chatroom with WebSockets
Part 6 – The Finale and Debugging Remote Node Apps

Noch mehr Lernen über Node auf Azure

Ausführlichere Lehrinhalte zu Node gibt es in meinem Kurs an der Microsoft Virtual Academy.

Sehr hilfreich sind auch diese Kurzvideos zu ähnlichen Node-Themen:

Dieser Artikel ist Teil der Web-Dev Tech-Series von Microsoft. Wir freuen uns Microsoft Edge (früher Project Spartan genannt) und seine neue Rendering Engine mit euch zu teilen. Kostenlose Virtual Machines oder Remote Testings für Mac, iOS, Android oder Windows gibt es hier: @ dev.modern.IE.

Zur besseren Übersicht und als Extra-Service folgt hier der gesamte Quellcode der app.js

//
/**
 * Module dependencies.
 */

var express = require('express');
var routes = require('./routes');
var user = require('./routes/user');
var http = require('http');
var path = require('path');

var mongo = require('mongodb').MongoClient;

var app = express();

// all environments
app.set('port', process.env.PORT || 3000);
app.set('views', path.join(__dirname, 'views'));
app.set('view engine', 'jade');
app.use(express.favicon());
app.use(express.logger('dev'));
app.use(express.json());
app.use(express.urlencoded());
app.use(express.methodOverride());
app.use(app.router);
app.use(require('stylus').middleware(path.join(__dirname, 'public')));
app.use(express.static(path.join(__dirname, 'public')));

// development only
if ('development' == app.get('env')) {
  app.use(express.errorHandler());
}

app.get('/', routes.index);
app.get('/users', user.list);

var serve = http.createServer(app);
var io = require('socket.io')(serve);

serve.listen(app.get('port'), function () {
    console.log('Express server listening on port ' + app.get('port'));
});

io.on('connection', function (socket) {
    console.log('a user connected');

    mongo.connect(process.env.CUSTOMCONNSTR_MONGOLAB_URI, function (err, db) {
        var collection = db.collection('chat messages')
        var stream = collection.find().sort({ _id : -1 }).limit(10).stream();
        stream.on('data', function (chat) { socket.emit('chat', chat); });
    });

    socket.on('disconnect', function () {
        console.log('user disconnected');
    });

    socket.on('chat', function (msg) {
        mongo.connect(process.env.CUSTOMCONNSTR_MONGOLAB_URI, function (err, db) {
            var collection = db.collection('chat messages');
            collection.insert({ content: msg }, function (err, o) {
                if (err) { console.warn(err.message); }
                else { console.log("chat message inserted into db: " + msg); }
            });
        });

        socket.broadcast.emit('chat', msg);
    });
});

(dpe)

Kategorien
(Kostenlose) Services Apps Boilerplates & andere Tools CMS Essentials Freebies, Tools und Templates JavaScript & jQuery Programmierung Sonstige Programmiersprachen Tipps, Tricks & Tutorials Webdesign WordPress

Codester: Neuer Marktplatz für Entwickler und Designer bietet faire Bedingungen und mehr

Heute möchte ich dir Codester vorstellen. Codester ist ein brandneuer Marktplatz für Entwickler und Designer. Hier kannst du Code Schnipsel, Skripte, Themes, Plugins und vieles mehr kaufen, um dein nächstes großes oder kleines Projekt aufzupolieren. Fertige Komponenten zu benutzen, spart Zeit und Zeit ist – wie wir alle wissen – Geld. Also nimm dir fünf Minuten und lies den folgenden Artikel.

Codester: Marktplatz für Designer und Entwickler

Codester: Ein kurzer Rundgang

Skript-Verzeichnisse waren eine große Sache Ende der Neunziger und noch zu Beginn des neuen Jahrtausends. Ich kann mich noch gut an das bekannteste von ihnen, HotScripts.com, erinnern. HotScripts war die Lösung für jede Aufgabe, dieirgendwas mit Programmierung zu tun hatte. Später wurde HotScripts dann von einem bekannten Websiteaufkäufer aufgekauft. Danach passierte leider nicht mehr viel. Und auch, wenn sie heute noch existieren, befinden sie sich seitdem in einem Stillstand. Besuch die Seite besser nicht, wenn du sie noch von früher kennst. Das würde nur deine nostalgischen Erinnerungen an vergangene Tage zerstören.

Ich bin im letzten Jahrzehnt keinem ähnlichen Service begegnet. Obwohl es keinen Mangel an Marktplätzen für Designer gibt, müssen Entwickler sich mit einer anderen Wahrheit auseinandersetzen. Aber: im Sommer diesen Jahres hat eine kleine Gruppe motivierter Entwickler eine Lösung für dieses Problem ersonnen. Willkommen, Codester.com, ein schnell wachsender, würdiger Nachfolger des vorher erwähnten Dinosauriers.

Codester spricht sowohl Designer als auch Entwickler an. Dabei haben jedoch alle angebotenen Elemente, zumindest zur Zeit, einen entwicklungsorientierten Touch. Nehmen wir die Grafikabteilung als Beispiel. Hier stellt Codester Benutzeroberflächen, Spiele-Code und Mockups neben Icons und Logos zur Verfügung. Das ist keine Spielzeugkiste für selbstverliebte Designer. Hier will keiner eine freundliche Bestätigung seines guten Geschmacks erheischen. Hier geht es darum, Arbeit zu erledigen. Dass Codester im Moment nicht allzu viele Dinge im Angebot hat, solltest du nicht als allzu großen Nachteil empfinden. Sie haben immerhin gerade erst angefangen.

Codester: Marktplatz für Designer und Entwickler

Wenn du dir die Hände wirklich schmutzig machen möchtest, wühl dich durch die Skript & Code-Abteilung, in der du Lösungen in PHP, JavaScript, Ruby, Python, Java, C, C++, C# und VB.Net finden wirst. Aktuell hat zwar nur die PHP-Kategorie eine nennenswerte Sammlung an Skripten anzubieten, aber die Leute hinter Codester arbeiten aktiv daran, das Portfolio schnell zu erweitern.

Wenn du ein App-Entwickler bist, solltest du den Bereich Mobile Apps besuchen, wo du vielleicht genau den einen Code-Schnipsel für iOS, Android, Unity, Corona oder Titanium findest, nach dem du die letzten fünf Nächte gesucht hast.

Heutzutage sind zwar einzelne Skripte immer noch nützlich und gefragt, aber die größere Nachfrage kommt von Entwicklern aus der CMS-Branche. Es ist sicherlich möglich, jedes gegebene Skript so zu verändern, dass es mit jedem CMS funktioniert. Das kann ich für WordPress fast uneingeschränkt bestätigen. Allerdings ist es effizienter, sich direkt für ein Skript-Modul, Plugin, Erweiterung, oder wie auch immer die Namenskonventionen deines CMS sein mögen, zu entscheiden und es in dem Umfeld, für das es gemacht wurde, zu benutzen.

Codester ist derselben Meinung und bietet eine Vielfalt an Plugins für WordPress, Joomla, Drupal, Magento, Prestashop, osCommerce, X-Cart und Opencart an. Themes, auch wenn sie sich mehr auf das Design beziehen, kombinieren Form und Funktion, um letztendlich die gewünschte Nutzererfahrung zu erreichen. Daher ist es konsequent, dass Codester einen separaten Abschnitt mit Themes, verfügbar für WordPress, Magento, Joomla, Drupal, Prestashop, Opencart, Muse, Tumblr und Ghost unterhält. Arbeitest du ganz ohne CMS, ist vielleicht die Sammlung von HTML-Templates am gleichen Ort interessant.

Codester: Vom Suchen und Finden

Codester ist auf Wachstum ausgerichtet und direkt so gebaut worden, dass es auch mit großen Beständen virtuos umgehen kann. Zurzeit kannst du einfach durch die Hauptabschnitte und Kategorien browsen. Darunter ist keine einzige, die man nicht innerhalb von ein paar Minuten durchscrollen kann. Sollte das Wachstum aber mit konstantem Tempo voranschreiten, wird sich das in wenigen Monaten deutlich verändert haben. Das Team hat vorgesorgt und den Service so strukturiert, dass es auch dann noch leicht sein wird, das benötigte Werkzeug zu finden, wenn es tausende Skripte, Themes oder was auch immer zu filtern gibt.

Codester: Marktplatz für Designer und Entwickler

Der offensichtlichste Weg, eine Lösung auf Codester zu suchen, ist es, die obere Suchleiste auf der Startseite zu verwenden. Gib deinen Suchbegriff ein und schau, was Codester dazu findet. Das ist nicht sehr effizient, sobald du bereits in der Lage bist, deine Parameter etwas einzuschränken, was bei einem typischen Entwicklungsprojekt höchstwahrscheinlich der Fall sein wird. Codester arbeitet nicht mit zusätzlichen Tags, um bestimmte zusammengehörende Inhalte zu gruppieren – zumindest nicht von der Suchleiste aus.

Daher ist der empfehlenswertere Weg an die Inhalte zu komme,n das Browsen durch die Kategorien. Sobald du eine beliebige Kategorie auswählst, wird dir ihr Inhalt in einer Rasterübersicht präsentiert. Von diesem Raster aus, kannst du die Detailseite eines jeden Elementes öffnen, um zu weiteren INformationen zu gelangen. Die wichtigsten Informationen findest du aber bereits direkt im Übersichtsgrid. Dort kannst du den Preis, ein Vorschaubild, eine kurze Beschreibung und die Zielplattform sehen. Videos und Live-Previews sind auch über das Raster zugänglich. Also kannst du deine Wahl schnell auf ein oder zwei Angebote einschränken, die dich wirklich interessieren.

Codester: Marktplatz für Designer und Entwickler

Mit einem Klick auf die Vorschau des Elements öffnet sich die Detail-Seite. Diese erfüllt das, was ihr Name verspricht. Hier findest du sämtliche wichtigen Information zum Produkt. Die Beschreibungen sind ausführlich, Screenshots gibt es wie Sand am Meer. Hier befindet sich auch eine Box mit zusätzlichen Tags, die das jeweilige Tool zusätzich kategorisieren. Ein Klick auf einen der Tags, öffnet ein weiteres Grid, das alle Produkte aus Codesters Portfolio zeigt, denen dasselbe Tag zugeordnet wurde.

Die Detail-Seite ist in vier Segmente eingeteilt, bei denen die Übersicht die Standardansicht nach dem Öffnen der Seite ist. Es gibt Tabs für Bewertungen, Support und FAQ. Der Support-Tab bietet eine direkte Support-Möglichkeit, ähnlich eines Kommentarbereiches in einem CMS. Jeder mit einem Account kann Fragen stellen, während nur tatsächliche Käufer eines Produktes Bewertungen zu diesem Produkt veröffentlichen können. Ein FAQ-Bereich beantwortet schon mal die häufigsten Fragen, um den Support-Bereich zu entlasten.

Codester: Marktplatz für Designer und Entwickler

Share-Buttons erlauben es dir, Codester-Inhalte auf Facebook, Twitter, Google+, Pinterest, LinkedIn oder per E-Mail zu teilen. Ein Partnerprogramm ist jedem zugänglich und bietet 10 Prozent Kommission für jeden Käufer, der auf deine Empfehlung hin gekauft hat.

Codesters Lizensen

Die Kosten der einzelnen Elemente variieren stark, die Lizensen aber nicht. Zur Wahl steht jeweils die reguläre und die erweiterte Lizenz. Die (günstigere) reguläre Lizenz erlaubt, das gekaufte Produkt in einem deiner Projekte, ob privat, kommerziell oder für einen Kunden, zu verwenden. Die erweiterte Lizenz bietet dasselbe, mit der Ausnahme, dass das Produkt bei dieser Lizenz für eine unbegrenzte Anzahl von Projekten benutzt werden kann. Du darfst lediglich die Produkte nicht als solche verkaufen, aber das sollte ohnehin selbstverständlich sein.

Codester: Verkaufe Deine Arbeit

Wie man es von einem Marktplatz erwartet, bietet Codester keine eigenen Produkte an, sondern arbeitet als eine Art Mittelsmann für talentierte Entwickler und Designer, die daran interessiert sind, ihre Skripte, Plugins, Themes, Quellcodes an die Welt zu verkaufen. Hier mitzumachen ist ganz einfach.

Codester hat sehr wenige, dabei sehr gerechte Bedingungen für Verkäufer. Verkäufer verdienen 70 Prozent von jedem Kauf. Es gibt keine Mindestanzahl an Verkäufen, ebenso keine Mindestmenge an aufgelaufenen Beträgen, bevor man eine Auszahlung anfordern kann, nichts. Die Bezahlung erfolgt über PayPal oder Wire am Ende jeden Monats. Es gibt keine zusätzlichen Gebühren oder andere Haken und Ösen.

Codester: Bild dir deine Eigene Meinung

Mir gefällt das Projekt. Codester ist eine gut gestaltete, sorgfältig geschriebene Marktplatzumgebung mit Fokus auf Entwickler und das ist eine gute Sache an sich. Codester braucht viel mehr Beteiligung durch die Community, sei es durch mehr Angebote in den verschiedenen Kategorien oder mehr Interaktion mit den bereits existierenden Angeboten. Hier kommst du ins Spiel. Schau dir Codester an und mach dir ein eigenes Bild. Unterstütz es, wenn es dir gefällt.

Kategorien
JavaScript & jQuery Programmierung

Aus der Praxis: wir bauen eine Chatroom Web-App mit Node.js (Teil 2)

In dieser Node.js Tutorial-Serie zeigen wir, wie man eine Node.js-getriebene Echtzeit-Chatroom Web App erstellt, die vollständig cloud-fähig ist. Es wird darum gehen, Node.js auf einem Windows-Rechner aufzusetzen, ein Web Frontend mit Express zu entwickeln, eine Node Express App auf Azure zu bringen, wie man Socket.IO nutzt um einen Echtzeit-Layer hinzuzufügen und wie man das Ganze zum Schluss einsetzt.

nodejs-parttwo-teaser_DE
Schwierigkeitsstufe: Einsteiger bis mittlere Kenntnisse, vorausgesetzt werden HTML5 und JavaScript.

Teil 2: Express mit Node.js und Azure

Hier nun also Teil 2 der Praxis-Tutorialserie über Node.js: Wir programmieren eine Node.js-getriebene Chatroom Web App. In diesem Teil erkläre ich wie man ein neues Express-basiertes Node-Projekt aufsetzt und es auf Azure laufen lässt.

Was ist Express?

Express ist ein minimalistisches, flexibles Open Source Web-Framework, welches die Entwicklung von Webseiten, Web Apps und APIs erheblich vereinfacht.

Wofür ist Express gut?

Express erleichtert es dank Route Support HTTP Requests zu beantworten, Responses können dadurch an bestimmte URLs geschrieben werden. Express unterstützt zudem mehrere Template Engines, um die Erstellung von HTTP Responses zu vereinfachen.

Alles bereit und Node.js installiert? Wer Hilfe braucht, schaut einfach noch mal in Teil 1: Einführung in Node.js.

Und los geht´s

Ein neues Node.js Projekt zu starten ist keine große Sache.

1. Visual Studio starten. Im Datei-Menü erst Neu klicken und dann Projekt.

clip_image001

2. Danach auf der linken Seite: Installiert > Vorlagen > JavaScript Menüpunkt aufrufen und rechts Basic Windows Azure Express Application auswählen. Speicherort und Namen für das Projekt bestimmen und OK klicken.

clip_image003

3. In der Folge informiert eine Nachricht darüber, dass in package.json definierte Abhängigkeiten installiert werden müssen, und zwar mithilfe des NPM Paketmanagers. Dieser wird hier genauer erklärt.

clip_image004

4. Nun wird ein Projekt erzeugt, das die Datei app.js enthält. Und hier fangen wir an.

Erklärung von app.js

//
/**
 * Module dependencies.
 */

var express = require('express');
var routes = require('./routes');
var user = require('./routes/user');
var http = require('http');
var path = require('path');

var app = express();

// all environments
app.set('port', process.env.PORT || 3000);
app.set('views', path.join(__dirname, 'views'));
app.set('view engine', 'jade');
app.use(express.favicon());
app.use(express.logger('dev'));
app.use(express.json());
app.use(express.urlencoded());
app.use(express.methodOverride());
app.use(app.router);
app.use(require('stylus').middleware(path.join(__dirname, 'public')));
app.use(express.static(path.join(__dirname, 'public')));

// development only
if ('development' == app.get('env')) {
  app.use(express.errorHandler());
}

app.get('/', routes.index);
app.get('/users', user.list);

http.createServer(app).listen(app.get('port'), function(){
  console.log('Express server listening on port ' + app.get('port'));
});

Zeilen 6 bis 10

Die Zeilen 6 bis 10 laden verschiedene Module, einschließlich express, http und path. Besonders interessant sind aber das Modul routes (dazu später mehr) und das user Modul im routes-Ordner.

Zeile 12

In dieser Ziele riefen wir die Funktion express() auf, die unsere App erzeugen wird. Diese App werden wir benutzen, wenn wir einen HTTP Server erstellen wollen. Gleichzeitig wird dieses Objekt alle Eigenschaften unserer Web Applikation enthalten sowie das Mapping zwischen der URL, die bei einem Request übertragen wird, und der Funktion, welche die entsprechende Response abwickelt.

Zeilen 15 bis 17

In diesen Zeilen legen wir verschiedene Einstellungsparameter fest, darunter auf welchem Port der Server läuft (Zeile 15) und in welchem Verzeichnis die HTML Datei-Templates zu finden sind (Zeile 16). In Zeile 17 bestimmen wir die Template-Engine die wir benutzen wollen, in unserem Fall ist es Jade. Jade ist eine weit verbreitete Template-Engine, die das Schreiben von HTML-Code sehr erleichtert, unter anderem weil sie auf spezielle Syntax-Erfordernisse wie spitze Klammern (<>) verzichtet. Wer die Template-Engine so verändern will, dass sie einfach nur HTML ausgibt und nichts weiter, ersetzt die Zeile 17 mit folgendem Code:
app.set(‚view engine‘, ‚html‘);

Zeilen 18 bis 23

In diesen Zeilen legen wir verschiedene Einstellungsparameter fest. Die Bedeutung der einzelnen Parameter ist aus der API Dokumentation ersichtlich. Für dieses Tutorial muss man das aber nicht im Einzelnen wissen.

Zeilen 24 und 25

Diese Zeilen sind insofern interessant, als dass wir hier eine Middleware bestimmen, die Stylus CSS Sheets und HTML bearbeitet. Middleware ist dabei eine Ebene, die automatisch in die Funktionsaufrufe zwischen dem Empfang eines Requests und der Ausgabe einer Response eingefügt wird. In unserem Fall soll Express die Stylus Middleware und die Static Middleware nutzen für alle Requests bei denen die URL einen bestimmten Pfad innerhalb des öffentlichen Ordners unseres Projekts vorgibt. Dafür führen wir keine Request-Funktion für diese URL aus, sondern nehmen server CSS und JavaScript wörtlich.

Zeile 27 bis 30

In diesen Zeilen geben wir an , wie Express mit Fehlern umgeht, falls die Umgebung nicht als „Produktion“, sondern als „Entwicklung“ eingestellt ist. Über diese Zeilen muss man sich keine Gedanken machen.

Zeilen 32 und 33

Hier planen wir schließlich einen URL-Pfad innerhalb eines HTTP Requests zu einer bestimmten Funktion, welche die Response verarbeitet. Darauf kommen wir gleich noch einmal zurück.

Zeilen 35 bis 38

MIt diesen Zeilen erstellen wir einen HTTP Server und bestimmen den Port, zusammen mit einem Callback für den Fall, dass der Server erfolgreich gestartet wurde.

Routing

Routing und wie man es am besten macht – das ist ein oft diskutiertes Thema und eine endgültige Antwort gibt es wohl nicht. Es gibt zahlreiche Module, die das Routing für Express und Node.js realisieren. Jedes hat seine Besonderheiten und speziellen Strukturen, da ist wohl für jeden etwas dabei. Wir arbeiten hier mit der Routing-Engine, die bereits in Express enthalten ist. In app.js hatten wir die Routing-Engine bereits festgelegt, die Route-Module können einfach aus dem Routing-Verzeichnis importiert werden. Die Routes haben wir in den Zeilen 32 und 33 hinzugefügt. Anders gesagt, wir haben die URL im Browser zur Funktion auf dem Server, die den Request bearbeiten soll, gemappt. Diese die Requests bearbeitenden Funktionen befinden sich im Routing-Verzeichnis. Schauen wir uns daher doch gleich mal index.js an.

/*
 * GET home page.
 */

exports.index = function(req, res){
  res.render('index', { title: 'Express' });
};

Ziemlich unscheinbar, aber diese drei Zeilen erledigen tatsächlich eine Menge Arbeit. Zeile 1 fügt der Exportvariable die Funktion index hinzu. Die Exportvariable wird durch Node.js erstellt, und zwar immer dann wenn ein Modul geladen wird, das es ermöglicht, Funktionen und Variablen zu anderen Modulen zu übertragen, in diesem Fall das app.js Modul.
Die Funktion index nimmt zwei Parameter an, req und res. Wie in Teil 1 beschrieben, verwalten der req Parameter die erhaltenen Requests und der res Parameter eine Variable zu der man die Response schreibt. In unserem Fall führen wir in der Response-Variable die Render-Funktion aus, die zwei Parameter annimmt. Da ist zum einen der Parameter, der bestimmt, welche Ansicht (view) genutzt wird (view ist eine Datei im Views-Verzeichnis), eine Dateiendung ist nicht nötig, index wird index.jade. Der zweite Parameter ist ein Daten enthaltenes Objekt, das in das Jade-Template eingefügt werden kann.

Das Index Template

Das index.jade Template ist eine komplett andere Sprache, die jedoch nicht Teil dieses Tutorials ist. Für diese Tutorial-Serie ist HTML-Wissen notwendig und in diesem Fall wird schnell deutlich, dass Jade Templating das Mapping fast immer direkt zu HTML vollzieht.

extends layout

block content
  h1= title
  p Welcome to #{title}

Mit Ausnahme der Keywords “block” und “extends” bedeuten alle anderen Keywords das Gleiche wie in HTML. Dieses Template wird durch Jade Middleware umgewandelt, welches wir in das folgende HTML geladen haben.

<!DOCTYPE html>
<html>
<head>
    <title>Express</title>
    <link rel="stylesheet" href="/stylesheets/style.css">
</head>
  <body>
    <h1>Express</h1>
        <p>Welcome to Express</p>
  </body>
</html>

Deutlich wird, dass der entstandene H1 tag den Wert des Titels enthält, den wir zuvor in der Render-Funktion übergeben haben. Außerdem wurde er, im Einklang mit dem Text, direkt in den p tag eingefügt. Auffällig ist aber auch, dass das entstandene HTML Elemente enthält, die nicht in Jade gemappt wurden. Und genau hier brauchen wir dann auch das Keyword “extends”. Im vorliegenden Fall haben wir die Datei layout.jade erweitert.

doctype html
html
  head
    title= title
    link(rel='stylesheet', href='/stylesheets/style.css')
  body
    block content

Schon bemerkt? Der Ausdruck “block content” erscheint in beiden Dateien. Jade nutzt das, um zu bestimmen, dass dieser HTML-Block genau hierher gehört (in der Datei layout.jade) und genau so aussehen soll (in der Datei index.jade).

In der Datei layout.jade fällt der Link zu einer style.css Datei auf, welche in unserem Ausgangsprojekt offenbar gar nicht existiert. Diese Datei wird durch den style.styl Code erstellt, mithilfe der Stylus Middleware, die wir in app.js eingestellt hatten.

Und schon haben wir’s! So kommen wir von app.js zu einem Routing, das die Response bestimmt und schließlich zu einer Ansicht (view), die angibt wie die Response letztlich aussieht. Man kann die Web App lokal laufen lassen, wenn man die Debug-Taste klickt (ein anderer Browser ist durch das Klicken des Dropdown-Menüs auf der rechten Seite möglich).

clip_image012

Als Erstes wird dann ein Node.js Server gestartet und der Internet Explorer geöffnet, der die root URL anzeigt.

Veröffentlichen über Azure (für alle, die Visual Studio nutzen)

Jetzt haben wir also eine funktionierende Express-basierte Node.js App am Start. Dann ist der nächste Schritt doch, sie auch in der Cloud laufen zu lassen. Dazu braucht es nur ein paar Klicks. Die App kann in jeder Cloud betrieben werden, die Node.js unterstützt. Beispiele sind Nodejitsu, Heroku und Engine Yard. Wir werden hier Microsoft Azure nutzen, weil man dort eine Node.js Website kostenlos laufen lassen kann.

Zur kostenlosen Testversion von Microsoft Azure geht es hier. Damit bekommt man alle Services von Azure bis zu einer Höhe von 150€ gratis. Mit Azure Websites, das wir hier nutzen, kann man bis zu zehn Webseiten kostenlos betreiben.

1. Sobald das Azure-Konto eingerichtet ist, gehen wir zurück zur IDE. Dort führen wir auf unserem Express Projekt einen Rechtsklick aus und wählen im Menü dann „Veröffentlichen“.

clip_image018

2. Das Menü „Veröffentlichen“ öffnet einen Assistenten mit einigen Optionen, wir wählen als Ziel Microsoft Azure Websites.

3. An dieser Stelle erfolgt der Login, und zwar mit dem gleichen Microsoft-Konto wie bei der Azure-Anmeldung.

4. Nun „Neu“ auswählen, um eine neue Azure Webseite zu erstellen. Existiert schon eine, dann einfach diese im Dropdown-Menü auswählen.

http://blogs.msdn.com/resized-image.ashx/__size/550x0/__key/communityserver-blogs-components-weblogfiles/00-00-00-60-29/4532.BLOG-POST-_2D00_-Part-2-_2D00_-Screenshot-12.png

5. Die Felder im Assistenten ausfüllen (siehe unten). Darauf achten, einen unverwechselbaren Namen für die Seite zu wählen und dann „Erstellen“ klicken.

http://blogs.msdn.com/resized-image.ashx/__size/550x0/__key/communityserver-blogs-components-weblogfiles/00-00-00-60-29/7823.BLOG-POST-_2D00_-Part-2-_2D00_-Screenshot-13.png

6. Als Nächstes erscheint ein vorausgefüllter Assistent mit einem Button Veröffentlichen am Ende, diesen dann klicken.

clip_image024

GESCHAFFT! Das Projekt ist in der Azure Cloud veröffentlicht!

Jetzt lohnt es sich, mal ein paar Azure Webseiten im Azure Portal anzusehen. Sehr empfehlenswert ist auch dieses Video.

Wichtiger Tipp: Falls beim Veröffentlichen Probleme auftreten sollten, unbedingt das Projekt näher am Stammverzeichnis platzieren, um kurzzeitige Fehler beim Kopieren zu vermeiden.

clip_image026

clip_image028

Dranbleiben für Teil 3!

Teil 3 (Wie man ein Backend mit Node, Mongo and Socket.IO aufbaut) erscheint bald hier bei Dr.Web. Wer mehr Neuigkeiten dazu und zu anderen Artikeln erfahren will, kann mir einfach auf Twitter folgen: @ramisayar.

Weiteres Wissenswerte zu Node auf Azure

Ausführlichere Lehrinhalte zu Node gibt es in meinem Kurs an der Microsoft Virtual Academy.
Sehr hilfreich auch diese Kurzvideos über ähnliche Node-Themen:

Dieser Artikel ist Teil der Web Dev Tech Series von Microsoft. Wir freuen uns, das Projekt Spartan und seine neue Rendering Engine mit euch zu teilen. Kostenlose Virtual Machines oder Remote Testings für Mac, iOS, Android oder Windows gibt es hier: modern.IE.

Weitere Teile dieser Serie bei MSDN

Part 1 –  Introduction to Node.js
Part 2 – Welcome to Express with Node.js and Azure
Part 3 – Building a Backend with Node, Mongo and Socket.IO
Part 4 – Building a Chatroom UI with Bootstrap
Part 5 – Connecting the Chatroom with WebSockets
Part 6 – The Finale and Debugging Remote Node Apps

(dpe)

Kategorien
Design JavaScript & jQuery Webdesign

SVG: So erstellst du interaktive Grafiken für deine Website

Dass das SVG-Format weit mehr ist als ein vektorbasiertes Grafikformat, dürfte inzwischen bekannt sein. Animationen und Interaktionen gehören ebenfalls zum Repertoire des Vektorformats. Da auch JavaScript innerhalb einer SVG-Datei eingesetzt werden kann, ergeben sich zahlreiche Anwendungsmöglichkeiten. Die JavaScript-Lösung svidget.js stellt hierfür ein umfangreiches Framework zur Verfügung, welches das Erstellen und Einbinden von SVG-Grafiken in Form von Widgets ermöglicht.

SVG: So erstellst du interaktive Grafiken für deine Website

SVG-Widgets erstellen und einbinden

SVG-Widgets sind zunächst einmal klassische SVG-Dateien, die dank des Frameworks von svidget.js um zusätzliche Elemente erweitert werden, mit denen sich das Aussehen einer Grafik beeinflussen lässt. Zusätzlich erlaubt das Framework, Aktionen und Ereignisse zu definieren. Die SVG-Widgets werden über das „<object>“-Element in ein HTML-Dokument eingebunden und können dann per „<parameter>“-Element konfiguriert werden. Wie sich die per „<parameter>“ gemachten Angaben auf die SVG-Datei auswirken, wird innerhalb der SVG-Datei festgelegt.

Damit das Framework funktioniert, musst du die JavaScript-Datei „svidget.js“ sowohl in dein HTML-Dokument als auch in die jeweilige SVG-Datei einbinden.

Parameter in SVG-Datei festlegen

Mit svidget.js ist es beispielsweise möglich, ein und dieselbe SVG-Datei mit unterschiedlichem Aussehen in ein und dasselbe HTML-Dokument einzubinden. Dabei wird innerhalb der SVG-Datei festgelegt, welche Parameter berücksichtigt werden sollen.

<svidget:params>
  <svidget:param name="backgroundColor" type="string" subtype="color" binding="#elementA@fill" />
  <svidget:param name="borderColor" type="string" subtype="color" binding="#elementB@stroke" />
  <svidget:param name="borderWidth" type="number" binding="#elementA@stroke-width, #elementB@stroke-width" />
</svidget:params>

Innerhalb des Elementes „<svidget:params>“ legst du einzelne Parameter per „<svidget:param>“ fest. Diese interpretieren später die Angaben, die du in den „<parameter>“-Elementen des einbindenden HTML-Dokumentes gemacht hast. Neben der Angabe eines Namens wird mit „type“ und „subtype“ vorgegeben, was für ein Wert erwartet wird. Die ersten beiden Angaben im Beispiel erwarten eine Zeichenkette, die eine Farbe beschreiben muss, die dritte Angabe eine Zahl.

svidgetjs

Über „binding“ legst du fest, was mit dem Wert geschehen soll. Die Zeichenkette vor dem @-Zeichen beschreibt die ID der SVG-Form und die Zeichenkette danach das Attribut der Form, die den Wert erhalten soll. Der Wert „#elementA@fill“ weist somit der „fill“-Eigenschaft der Form mit der ID „elementA“ die Farbe zu, die per „backgroundColor“ definiert wurde.

Zu guter Letzt musst du noch die JavaScript-Datei einbinden.

<script type="application/javascript" xlink:href="svidget.js"></script>

SVG-Widget in HTML-Dokument einbinden

Im nächsten Schritt baust du die SVG-Datei in ein HTML-Dokument ein. Hierzu verwendest du das „<object>“-Element.

<object data="star.svg" role="svidget" id="star" type="image/svg+xml" width="200" height="200">
  <param name="borderColor" value="red" />
  <param name="backgroundColor" value="green" />
  <param name="borderWidth" value="3" />
</object>

Über die Eigenschaft „data“ wird die SVG-Datei referenziert. Wichtig ist, dass per „role“ der Wert „svidget“ angegeben wird. Nur so weiß das Framework, dass die SVG-Datei auch als SVG-Widget behandelt werden soll. Über die „<param>“-Elemente kannst du nun die Hintergrundfarbe sowie Rahmenfarbe und -stärke angeben. Die Namen für die einzelnen „<param>“-Elemente müssen den Namen der jeweiligen „<svidget:param>“-Namen in der SVG-Datei entsprechen.

svidgetjs_stern1
Aussehen des Sterns per „<param>“-Elemente geändert

Aktionen festlegen

Für Interaktivität sorgen die Aktionen, die du mit den Elementen „<svidget:actions>“ und „<svidget:action>“ definieren kannst.

<svidget:actions>
  <svidget:action name="backgroundColorChange" binding="changeBackgroundColor">
    <svidget:actionparam name="newBackgroundColor" type="string" subtype="color" />
  </svidget:action>
</svidget:actions>

Im Beispiel wird die Aktion „backgroundColorChange“ definiert. Über „binding“ habe ich den Namen einer Funktion angegeben, die ausgeführt werden soll, sobald über das HTML-Dokument diese Aktion aufgerufen wird. Über „<svidget:actionparam>“ definiert man Parameter, die per JavaScript im HTML-Dokument an das SVG-Widget übergeben werden.

function changeBackgroundColor(newBackgroundColor) {
  svidget.current().param("backgroundColor").value(newBackgroundColor);
}

Die Funktion „changeBackgroundColor()“ innerhalb der SVG-Datei ändert die Hintergrundfarbe des SVG-Widgets mit dem über „newBackgroundColor“ übergebenen Wert.

Innerhalb des HTML-Dokumentes legst du einen Event-Listener an, der per Klick auf ein Element die Aktion im SVG-Widget aufruft.

document.getElementById("button").addEventListener("click", function() {
 svidget.widget("star").action("backgroundColorChange").invoke("red");
}, false);

Im Beispiel wird per Klick auf das Element mit der ID „button“ innerhalb des SVG-Widgets mit der ID „star“ die Aktion „backgroundColorChange“ aufgerufen. Per „invoke()“ wird ein Wert – in diesem Fall die Farbangabe „red“ – übergeben. Die Funktion „changeBackgroundColor()“ innerhalb der SVG-Datei sorgt nun dafür, dass der Parameter „backgroundColor“ über den Buttonklick auf den Wert „red“ geändert wird.

svidgetjs_stern2
Aussehen des Sterns nach der Aktion „backgroundColorChange“

Ereignisse festlegen

Eine weitere Funktionalität von svidget.js ist es, Ereignisse zu definieren. Damit ist es möglich, über das HTML-Dokument auf ein Ereignis in der SVG-Datei zu reagieren. Dazu muss, ähnlich wie bei den Aktionen innerhalb der SVG-Datei, ein Ereignis per „<svidget:events>“ und „<svidget:event>“ angelegt werden.

<svidget:events>
  <svidget:event name="changeComplete" />
</svidget:events>

Anschließend muss innerhalb der SVG-Datei noch irgendwo festgelegt werden, wann dem HTML-Dokument mitgeteilt werden soll, dass das Ereignis eingetroffen ist. Das kann beispielsweise innerhalb der Funktion „changeBackgroundColor()“ erfolgen.

function changeBackgroundColor(newBackgroundColor) {
  svidget.current().param("backgroundColor").value(newBackgroundColor);
  svidget.current().event("changeComplete").trigger();
}

Die zusätzliche Zeile sorgt dafür, dass per „trigger()“ das Ereignis „changeComplete“ ausgelöst wird. Innerhalb der HTML-Datei musst du nun noch festlegen, was dort passieren soll, wenn das Ereignis vom SVG-Widget ausgelöst wurde.

svidget.loaded(function (e) {
  svidget.widget("star").event("changeComplete").on(function() {
    console.log("Fertig!");
  });
});

Im Beispiel wird beim Ereignis einfach eine Funktion aufgerufen, die etwas in die Konsole des Browsers schreibt. Sobald also in der SVG-Datei die Funktion „changeBackgroundColor()“ ausgeführt wird, schreibt das HTML-Dokument per „console.log()“ etwas in die Konsole.

Anwendungsmöglichkeiten und Link zum Beitrag

Die hier vorgestellten Möglichkeiten stellen nur einen kleinen Ausschnitt des weit größeren Funktionsumfangs von svidget.js dar. Das Framework eignet sich prima, um zum Beispiel Diagramme per SVG darzustellen. Innerhalb der SVG-Datei können die Formen für ein Torten- oder Balkendiagramm festgelegt werden. Über die Parameter lassen sich dann die Werte und Bezeichnungen übergeben. Dieselbe SVG-Datei kann somit verschieden dargestellt werden.

svidgetjs_beispiele

Es gibt eine umfangreiche Dokumentation, sowie zahlreiche Beispiele, die auch die unterschiedlichen Anwendungsmöglichkeiten von svidget.js widerspiegeln. Das Framework steht unter der gängigen MIT-Lizenz zur kostenlosen Verwendung, auch zu kommerziellen Zwecken, zur Verfügung und kommt ohne zusätzliche JavaScript-Bibliotheken aus.

(dpe)

Kategorien
JavaScript & jQuery Programmierung

Aus der Praxis: wir bauen eine Chatroom Web-App mit Node.js (Teil 1)

In dieser Node.js Tutorial-Serie zeigen wir, wie man eine Node.js-getriebene Echtzeit-Chatroom Web-App erstellt, die vollständig cloud-fähig ist. Es wird darum gehen, Node.js auf einem Windows-Rechner aufzusetzen (oder, für alle Mac-User, zumindest die Konzepte dahinter zu verstehen), ein Web-Frontend mit Express zu entwickeln, eine Node-Express-App auf Azure zu bringen, wie man Socket.IO nutzt um einen Echtzeit-Layer hinzuzufügen und wie man das Ganze zum Schluss einsetzt. Als Entwicklungsumgebung verwendet das Tutorial das optionale Visual Studio und das Node.js Tools für Visual Studio Plugin — die Links für den kostenlosen Download beider Tools folgen weiter unten.

nodejs-partone-teaser_DE

Schwierigkeitsstufe: Einsteiger bis mittlere Kenntnisse, vorausgesetzt werden HTML5 und JavaScript.

Teil 1 – Einführung in Node.js

Hier nun also der Teil 1 der Praxis-Tutorialserie über Node.js: Wir programmieren eine Node.js-getriebene Chatroom Web App. In diesem Teil erkläre ich was Node.js überhaupt ist, warum man sich unbedingt mit Node.js beschäftigen sollte und wie man es auf dem Rechner einrichtet.

Was ist Node.js… und wofür brauche ich das?

Node.js ist eine Laufzeitumgebung und Bibliothek um JavaScript Applikationen außerhalb des Browsers laufen zu lassen. Node.js wird vor allem dafür benutzt um Server-Applikationen in Echtzeit laufen zu lassen und glänzt in seiner Leistungsfähigkeit durch die Nutzung nicht-blockierender I/O und asynchroner Events. Rund um Node.js ist ein komplettes Web-Ökosystem entstanden, mit mehreren nutzbaren Web App Frameworks und Protokollimplementierungen. Kurz: Es gehört zweifellos zu den einfachsten und schnellsten Tools, um heutzutage Echtzeit-Anwendungen für das Web zu schreiben.

Warum man mit Node.js arbeiten sollte? Ganz einfach: JavaScript. JavaScript ist unglaublich populär und weitverbreitet. Dass das Web zum heutigen dynamischen Wunderland wurde, dazu hat diese Sprache als eine der Hauptantriebskräfte sicher ganz wesentlich beigetragen. Was inzwischen alles innerhalb eines Browsers möglich ist schlägt alles Andere!

JavaScript entstand eigentlich am Frontend — aber dank der V8 JavaScript Engine und der Arbeit von Ryan Dahl kann man heute vernetzte JavaScript Anwendungen außerhalb des Browsers laufen lassen, eben mit dem Ziel Web Apps zu bauen. Node.js hilft die Programmiersprachen die von deiner App genutzt werden, zusammen zu bringen. Es ist keine weitere Sprache für das Backend nötig, JavaScript kann überall genutzt werden. Wer Erfahrungen mit der Programmierung und dem Design von Webseiten hat sowie mit Web App Frontends in HTML, CSS und JavaScript, der braucht keine andere Sprache zu lernen um komplexe, daten-getriebene Backends für Apps zu schreiben.

Node.js spielt zudem eine wesentliche Rolle bei der Weiterentwicklung von WebSockets als eine Methode für die Echtzeit-Kommunikation zwischen Frontend und Backend. Die Nutzung von WebSockets und von Bibliotheken wie Socket I/O, die auf diesem Protokoll aufbauen, haben die Erwartungen daran, was Web-Anwendungen heute leisten sollen nach oben geschraubt. Und uns Entwicklern die Chance gegeben, das Web neu zu denken und zu gestalten.

Node.js in Windows 8 aufsetzen

Wir brauchen zuallererst einen halbwegs aktuellen und frisch konfigurierten Rechner. Und dann kann es losgehen mit der Installation von Node.js auf Windows 8.1.

1. Node.js installieren

Als erstes die Node.js Runtime herunterladen und installieren. Mit dem Windows Installer geht das kinderleicht.

Wer dagegen ein Fan von Chocolatey ist, dem Paketmanager für Windows, kann Node.js folgendermaßen installieren:

choco install nodejs.install

2. Set-up bestätigen

Dann genau hinschauen, ob das Node.js Installationsprogramm zur PATH Systemumgebungsvariable hinzugefügt wurde. Wer wissen will, wie man die Umgebungsvariable in Windows 8 und WIndows 8.1 verändern kann, schaut am besten dieses Video. Der folgende Ordner muss unbedingt zur PATH Variable hinzugefügt worden sein:

C:\Program Files (x86)\nodejs\

Wer bei der Befehlseingabe node –h eingibt, dem sollte die Hilfe-Dokumentation für das Node.js Installationsprogramm angezeigt werden.

Neben Node.js sollte auch NPM, das System welches die Node.js Pakete verwaltet, installiert und über die Befehlseingabe erreichbar sein. Einfach npm –h eingeben, und dann sollte die Hilfe-Dokumenation von NPM angezeigt werden.

Wenn was schiefläuft…

Wenn ein Fehler wie dieser auftreten sollte…:

Error: ENOENT, stat 'C:\Users\someuser\AppData\Roaming\npm'

…sollte man einen Ordner erstellen auf dem oben angegebenen Pfad, siehe auch diese StackOverflow Frage. Dieses Problem tritt nur im aktuellen Node.js Installer auf und sollte mit der nächsten Version beseitigt sein. Der Ordner wird so erstellt:

mkdir -r C:\Users\someuser\AppData\Roaming\npm

Ein Entwicklungswerkzeug auswählen

Nachdem Node.js installiert ist, ist es jetzt an der Zeit ein Entwicklungswerkzeug auszuwählen. Es gibt da kaum Einschränkungen. In den Tutorials werde ich jedoch sowohl Visual Studio nutzen, um die Chat Engine zu entwickeln, zu debuggen und aufzusetzen als auch Node.js Tools for Visual Studio (NTVS) – ein kostenloses Open Source Plugin für Visual Studio, das die Entwicklung von Node.js Anwendungen unterstützt.

Ein neues Node.js Projekt in Visual Studio starten

Hinweis: Die Screenshots zeigen Visual Studio 2013 Ultimate.

Ein neues Node.js Projekt zu starten ist keine große Sache.

1. Visual Studio starten. Im Datei-Menü erst Neu klicken und dann Projekt.

http://blogs.msdn.com/resized-image.ashx/__size/550x0/__key/communityserver-blogs-components-weblogfiles/00-00-00-60-29/0741.BLOG-POST-_2D00_-Part-1-_2D00_-Screenshot-1.png

2. Im Fenster „Neues Projekt“ erst die Menüauswahl Installiert vergrößern, dann Vorlagen, und schließlich JavaScript auswählen. Im Hauptfenster Blank Node.js Web Application wählen. Dann einen Speicherort und einen Namen für das Projekt wählen und OK klicken.

http://blogs.msdn.com/resized-image.ashx/__size/550x0/__key/communityserver-blogs-components-weblogfiles/00-00-00-60-29/3414.BLOG-POST-_2D00_-Part-1-_2D00_-Screenshot-2.png

3. Angezeigt wird der folgende Bildschirminhalt. An dieser Stelle kann man Visual Studio auch erstmal ganz zwanglos ausprobieren und entdecken. Jetzt kann man die erstellte server.js Datei im Solution Explorer öffnen (normalerweise rechts auf dem Bildschirm sichtbar, aber sie kann auch an anderer Stelle auftauchen.)

http://blogs.msdn.com/resized-image.ashx/__size/550x0/__key/communityserver-blogs-components-weblogfiles/00-00-00-60-29/0211.BLOG-POST-_2D00_-Part-1-_2D00_-Screenshot-3.png

4. Jetzt die Node.js Web-Anwendung im favorisierten Browser debuggen.

http://blogs.msdn.com/resized-image.ashx/__size/550x0/__key/communityserver-blogs-components-weblogfiles/00-00-00-60-29/2235.BLOG-POST-_2D00_-Part-1-_2D00_-Screenshot-4.png

“Hello World” in Node.js

Wie in anderen Sprachen auch, zeigt der generierte Beispiel-Code, wie man “Hello World” im Browser anzeigen lassen kann. Nun werde ich erklären wie der erstellte Code in server.js Zeile für Zeile funktioniert.

*Hinweis: Wie oben schon erwähnt, geht diese Serie davon aus, dass Kenntnisse über JavaScript und HTML5 vorhanden sind und man weiß wie HTTP/das Internet funktionieren.

Zeile 1

  var http = require('http');

Node.js besitzt ein einfaches System um Modul und Abhängigkeiten zu laden. Dazu einfach die Funktion “require” mit dem Dateipfad oder dem Verzeichnis, welches das Modul enthält, aufrufen. Daraufhin wird eine Variable zurückgegeben, die alle exportierten Funktionen dieses Moduls enthält.

Zeile 2

var port = process.env.port || 1337;

In dieser Zeile bestimmen wir an welchem Port der HTTP Server, der das HTML ausgibt, laufen soll. Falls eine Portnummer in den Umgebungsvariablen angegeben ist, nehmen wir diese. Ansonsten benutzen wir einfach die 1337.

Zeile 3

http.createServer(function (req, res) {

Wir brauchen einen Server der die HTTP-Anfragen (Requests) bearbeitet. Wir übergeben auch die createServer Funktion, eine Callback-Funktion mit zwei Parametern um jede einzelne Anfrage zu bearbeiten und eine Antwort (Response) zu senden. Wer noch nicht mit Callback-Funktionen in JavaScript gearbeitet hat, dem empfehle ich Michael Vollmers Artikel. Die erhaltene Anfrage wird im req parameter übermittelt und die Antwort solllte an den res parameter gehen.

Zeile 4

res.writeHead(200, { 'Content-Type': 'text/plain' });

Jede HTTP-Response benötigt eine Statuszeile und Headers. Mehr über HTTP Header und wie sie funktionieren gibt es in diesem Artikel. Im vorliegenden Beispiel wollen wir zu 200 OK als Status-Reponse zurück und den Content-Type als einfachen Text festlegen. Dazu rufen wir die writeHead function auf dem Response-Objekt auf.

Zeile 5

res.end('Hello World\n');

Nach dem Schreiben der Response wollen wir die Ende Funktion aufrufen. Wir können auch den endgültigen Inhalt mit der Ende Funktion durchlaufen lassen. In diesem Fall senden wir den String “Hello World” in normalem Text.

Zeile 6

}).listen(port);

Wir sperren den Callback und rufen die listen Funktion am anfangs definierten Port auf. Dadurch wird der Server gestartet, der nun beginnt Requests am festgelegten Port anzunehmen.

Um das Resultat zu sehen, beginnt man nun mit dem Debuggen: Dazu einfach den Button klicken, der im vorigen Screenshot zu sehen war. Nun ist “Hello World” im Browser zu sehen.

http://blogs.msdn.com/resized-image.ashx/__size/550x0/__key/communityserver-blogs-components-weblogfiles/00-00-00-60-29/7652.BLOG-POST-_2D00_-Part-1-_2D00_-Screenshot-5.png

Voilà! Und schon ist eine Node.js App auf Windows 8.1 mithilfe von Visual Studio 2013 zum Laufen gebracht.

Dranbleiben für Teil 2!

Teil 2 — Wie man das “Hello World”-Projekt in die Cloud bringt — ist hier in meinem Blog zu finden. Wer mehr Neuigkeiten dazu und zu anderen Artikeln will, kann mir einfach auf Twitter folgen: @ramisayar.

Weiteres Wissenswerte zu Node auf Azure

Ausführlichere Lehrinhalte zu Node gibt es in meinem Kurs an der Microsoft Virtual Academy.
Sehr hilfreich auch diese Kurzvideos über ähnliche Node-Themen:

Dieser Artikel ist Teil der Web Dev Tech Series von Microsoft. Wir freuen uns, das Projekt Spartan und seine neue Rendering Engine mit euch zu teilen. Kostenlose Virtual Machines oder Remote Testings für Mac, iOS, Android oder Windows gibt es hier: http:// modern.IE.

Weitere Teile dieser Serie bei MSDN

Part 1 – Introduction to Node.js
Part 2 – Welcome to Express with Node.js and Azure
Part 3 – Building a Backend with Node, Mongo and Socket.IO
Part 4 – Building a Chatroom UI with Bootstrap
Part 5 – Connecting the Chatroom with WebSockets
Part 6 – The Finale and Debugging Remote Node Apps

Kategorien
Design JavaScript & jQuery Programmierung Webdesign

TremulaJS: Diese animierte und zeitgemäße Bildergalerie hat mich begeistert

Wenn es darum geht, Bilder oder andere visuelle Daten für eine Website aufzubereiten, kannst du auf zahlreiche JavaScript-Bibliotheken, die aus einer losen Bildersammlung gestalterisch und funktionell ansprechende Galerien zaubern, zurückgreifen. Allseits beliebt ist zum Beispiel das Image-Carousel, bei dem die Bilder per Mausbewegung oder Wischgeste gewechselt werden. TremulaJS stellt ebenfalls ein sehr umfangreiches Framework zur Verfügung, mit dem du animierte Galerien erstellen und deren Optik sehr individuell konfigurieren kannst.

TremulaJS als Bildergalerie

TremulaJS: Bilder als „Mountain“, „Turntable“ oder im Pinterest-Stil darstellen

Das Framework stellt verschiedene Darstellungsformen zur Verfügung, mit denen du deine Bilder präsentieren kannst. Sie gibt es zum Beispiel die „Mountain“-Ansicht, bei der Bilder kreisförmig angeordnet sind, dabei aber stets nur ein Ausschnitt des Kreises zu sehen ist. Somit sind die Bilder also nur in einem Bogen angeordnet, der als „Mountain“ bezeichnet wird. Eine andere Form der Darstellung ist das „Turntable“-Format. Hierbei werden Bilder von rechts beziehungsweise links ins Bild hinein geklappt. Auch eine klassische mehrspaltige Anordnung, wie man sie bei Pinterest kennt, ist möglich.

TremulaJS als Bildergalerie
„Mountain“-Darstellung

Insgesamt stehen sechs verschiedene Möglichkeiten zur Verfügung, mit denen du deine Bilder in Form bringen kannst. Auf einer Demo-Seite werden die einzelnen Darstellungsformen sehr schön veranschaulicht.

TremulaJS als Bildergalerie
„Turntable“-Darstellung

Zudem gibt es eine Vielzahl zusätzlicher Einstellungsparameter, mit denen du das Aussehen deiner Galerie noch anpassen kannst. So kannst du die Darstellungsgröße der Bilder anpassen, sowie die Anzahl der Zeilen und Spalten. Auf diese Weise kann das „Mountain“-Format nicht nur aus nebeneinander auf einem Kreis angeordneter Bilder bestehen, sondern zusätzlich aus untereinander angeordneten Bildern. Hierdurch lassen sich formatfüllende Galerien erzeugen, die zudem noch responsiv sind.

TremulaJS als Bildergalerie
Pinterest-Darstellung

Animationen mit Impuls

Neben den verschiedenen Darstellungsformen glänzt TremulaJS durch beeindruckende Animationseffekte. Per Mausbewegung oder Wischgeste wird die Galerie in Bewegung gebracht. Je nach Darstellungsform werden Bilder auf einem Kreis („Mountain“) gedreht oder ins Bild geklappt („Turntable“) oder einfach horizontal beziehungsweise vertikal bewegt.

Während bei solchen Animationseffekten häufig nur die Mausbewegung oder Gester eins zu eins umgesetzt wird, simuliert TremulaJS physikalische Impulskräfte, um eine natürlich anmutende Bewegung zu erzeugen. Wird also mit viel „Schwung“ per Geste oder Maus-Drag die Galerie in Bewegung gebracht, wird entsprechend schnell und weit animiert. Erst langsam kommt die Animation wieder zum Stehen.

Mit der „Mountain“-Ansicht erreichst du einen ähnlichen Effekt, wie er beim Drehen eines Rades eintritt. Durch die Simulation physikalischer Kräfte ist die Navigation durch eine Galerie sehr intuitiv und die Animationen zeigen sich sehr angenehm in der Wahrnehmung.

Unendlich viele Bilder laden dank JSON

Die einzelnen Bilder einer Galerie werden bei TremulaJS nicht im HTML-Quelltext ausgezeichnet, sondern über das Framework per JSON-Objekt geladen. Im HTML-Body wird lediglich ein „<div>“-Element ausgezeichnet, welches als Platzhalter für die Galerie dient.

So kannst du beispielsweise die Flickr-API nutzen, um Bilder per JSON zu laden und in einer eigenen Galerie darzustellen. Da die Bilder nicht fest im Quelltest verankert sind, müssen auch nicht alle Bilder der Galerie auf einmal geladen werden. So gibt es die Möglichkeit, Bilder sukzessive nachzuladen. Galerien mit hunderten Bildern stellen daher kein Problem dar.

In der Demo zu TremulaJS sieht man sehr schön, wie flüssig auch bei vielen zu ladenden Bildern selbst schnelle Bewegungen sauber ausgeführt werden.

TremulaJS: Komplexe JavaScript-Struktur und einige Abhängigkeiten

Anders als es bei vielen anderen Galerie-Bibliotheken der Fall ist, ist die Anwendung von TremulaJS nicht mit einigen wenigen eigenen Zeilen JavaScript getan. Der Aufwand ist doch etwas höher.

Zunächst wird das HTML-Element, in welches die Galerie platziert werden soll, übergeben. Die vielen Konfigurationsparameter werden über eine Objektliteral definiert.

TremulaJS als Bildergalerie
Bearbeitbarer Quelltext in CodePen

Das Laden der Bilder erfolgt über eigene Funktionen, die individuell programmiert werden. Daher stelle ich dir an dieser Stelle auch keine Code-Snippets vor. Allerdings gibt es auf CodePen eine recht einfache Demo, die das Laden von Flickr-Bildern zeigt. Hier kannst du dich ganz gut in das Framework einarbeiten und selbst herumprobieren.

Außerdem existiert ein gut dokumentiertes Beispiel zum Herunterladen, welches HTML-, CSS- und JavaScript-Datei beinhaltet.

Die Komplexität von TremulaJS spiegelt sich auch in den Abhängigkeiten von anderen Bibliotheken wider. So setzt das Framework jQuery, Hammer.JS und jsBezier voraus. Während Hammer.js für die Umsetzung der Wischgesten auf Mobilgeräten verantwortlich ist, wird jsBezier benötigt, um die Animation auf Kurven wie beispielsweise dem Kreis bei der „Mountain“-Ansicht zu realisieren.

Fazit

TremulaJS ermöglicht formatfüllende Galerien, die dank schicker und natürlich wirkender Animationen Spaß machen. Der Einsatz ist mit etwas Aufwand verbunden, der sich aber ganz klar lohnt, wenn man mehr möchte, als nur ein klassisches Image-Carousel oder ähnliches.

TremulaJS wird von Garris Shipon & Art.com Labs gepflegt. Es steht auf Github unter der liberalen MIT-Lizenz zum Download bereit und darf sowohl für private, wie kommerzielle Projekte, ebenso für Auftragsarbeiten verwendet werden.

(dpe)

Kategorien
Design JavaScript & jQuery Webdesign

Popmotion hat interaktive Animationen im Griff

Statische Seiten, ganz ohne Animationen, werden zunehmend weniger oder abnehmend mehr, je nach Sichtweise. Mit CSS3 und JavaScript sind schließlich allerlei Effekte für animierte Übergänge und aufwändige Animationen möglich. Selbst interaktive Animationen stellen keine grundsätzliche Problematik in der Webentwicklung mehr dar. Dennoch erfordern gerade komplexe Bewegungen vor allem in Kombination mit interaktiven Elementen einen gewissen Programmieraufwand. Mit der JavaScript-Engine Popmotion steht dir ein umfangreiches Tool zur Verfügung, das dir beim Erstellen von diversen interaktiven Animationen und animierten Benutzeroberflächen unter die Arme greift.

Popmotion hat interaktive Animationen im Griff

Klare Aufteilung: Popmotion verwendet Actors und Tweens

Die Grundlage für eine Animation mit Popmotion sind die sogenannten Actors. Das sind HTML-Elemente, die mit einer Aktion – das kann ein Tween oder ein Simulate sein – in Bewegung gebracht werden.

var ball = new ui.Actor("#ball");

Im Beispiel machen wir per „ui.Actor()“ das HTML-Element mit der ID „ball“ zu einem Actor. Das Aussehen des Elementes wird wie gewohnt per CSS festgelegt. Anschließend definieren wir eine Aktion, welche die Art und Weise der Animation beschreibt.

popmotion

Für eine klassische Animation bietet sich ein Tween an. In diesem legen wir fest, wie die Animation eines Actors auszusehen hat.

var bewegung = new ui.Tween({
  values: {
    y: 100
  }
});

Im Beispiel wird per „ui.Tween()“ eine einfache Bewegung angelegt. Über ein Objektliteral fügst du dem Tween verschiedene Eigenschaften hinzu. Hier wird der Wert „y“ auf 100 festgelegt. Das bedeutet, dass sich der Actor um 100 Pixel auf der Y-Achse nach unten bewegen wird.

popmotion_features
Die Features von Popmotion

Im letzten Schritt müssen Actor und Tween noch zusammengebracht werden.

ball.start(bewegung);

Aufmerksame Leser haben es vermutlich schon festgestellt. Bis hierhin unterscheidet sich ein Tween nicht von nativen CSS3-Animationen. Allerdings stehen dir mit Popmotion noch einige zusätzliche Parameter zur Verfügung. So gibt es eine Vielzahl an Easings, die über das hinausgehen, was CSS3 anbietet.

ball.start(bewegung.extend({
  duration: 5000,
  ease: "backOut"
}));

Über „extend()“ fügst du der Animation zusätzliche Parameter hinzu. Neben „duration“ für die Animationsdauer kannst du mit „ease“ eine Easingfunktion angeben. Das Schlüsselwort „backOut“ sorgt zum Beispiel dafür, dass die Animation zunächst über das angegebene Ziel hinausschießt und dann wieder zurückgefedert wird – ähnlich wie man es bei elastischen Materialien sieht.

Popmotion für Fortgeschrittene: Physikalische Simulation mit Simulates

Neben klassischen Tweens gibt es als Alternative sogenannte Simulates. Diese unterscheiden sich in der Funktionalität von klassischen Tweens. Ersetzt man im Beispiel einfach „ui.Tween()“ durch „ui.Simulate()“ ändert die Animation ihr Verhalten.

var bewegung = new ui.Simulate({
  values: {
    y: 100
  }
});

Denn jetzt wird der Actor nicht mehr nur um 100 Pixel nach unten bewegt, sondern unendlich. Der Wert für „y“ gibt nämlich die Bewegung pro Sekunde an. Der Actor wird also pro Sekunde 100 Pixel bewegt.

Außerdem stellen die Simulates spezielle Parameter zur Verfügung, mit denen sich physikalische Animationen simulieren lassen. So gibt es den Parameter „acceleration“, über den die Beschleunigung einer Animation definiert wird. Erwartet wird ein Wert, der die Beschleunigung in Einheiten pro Sekunde angibt.

ball.start(bewegung.extend({
  acceleration: 500
}));

Im Beispiel beschleunigt der Actor also um 500 Pixel pro Sekunde. Alternativ zur Beschleunigung kann mit „friction“ ein Wert für die Reibung angegeben werden. Erwartet wird hier ein Wert zwischen 0 und 1, wobei 1 für maximale Reibung steht. Eine Animation wird hierdurch je nach Wert langsam oder schnell abgebremst.

ball.start(bewegung.extend({
  friction: 0.1
}));

Event-Handler für Interaktionen

Damit die Animationen auch tatsächlich interaktiv eingesetzt werden können, stellt Popmotion einige Event-Handler zur Verfügung, die zu Beginn oder Ende einer Animation, aber auch bei jedem Frame beziehungsweise jeder Veränderung eine Funktion aufrufen können.

var ball = new ui.Actor({
  element: "#ball",
  onComplete: function() {
    alert("Fertig.");
  }
});

Im Beispiel fügen wir dem Actor neben der ID des Elementes noch den Event-Handler „onComplete“ hinzu. Alles wird als Objektliteral angegeben, sodass die ID als Wert von „element“ hinterlegt werden muss.

Nach abgespielter Animation erfolgt im Beispiel die Ausgabe eines einfachen Alerts.

Tracking mit Popmotion:  Benutzereingaben für Bewegungen nutzen

Ebenfalls interessant und sinnvoll ist das sogenannte Tracking. Hiermit kannst du zum Beispiel dafür sorgen, dass ein Nutzer mit der Maus ein Element in einem vorgegebenen Bereich bewegen kann.

var tracking = new ui.Track({
  values: {
    x: {
      min: 0,
      max: 100
    }
  }
});

Im Beispiel wird für die X-Achse ein Bereich zwischen 0 und 100 Pixel definiert. Über ein Event kannst du nun das Tracking auf einen Actor anwenden.

document.getElementById("ball").addEventListener("mousedown",function(e) {
  e.preventDefault();
  e.stopPropagation();
  ballActor.start(tracking, e);
}, false);

Im Beispiel kann ein Nutzer bei gedrückter Maustaste auf dem Element mit der ID „ball“ dieses zwischen 0 und 100 Pixel auf der X-Achse verschieben. Mit dem Tracking kannst du also relativ einfach eigene Fortschrittsbalken definieren.

Fazit, Kosten und Lizenz

Die hier vorgestellten Möglichkeiten stellen nur einen kleinen Ausschnitt dessen dar, was die JavaScript-Engine alles kann. Ein Blick in die Guides mit einigen Beispielen lohnt sich, um sich einen umfassenden Eindruck von Popmotion zu verschaffen. Es gibt zudem eine umfangreiche Dokumentation.

popmotion_guides
Guides zeigen, was Popmotion kann

Die Bibliothek ist keine 50 Kilobyte groß und kommt ohne Abhängigkeiten aus. jQuery oder andere Frameworks sind also nicht notwendig, um Popmotion nutzen zu können. Die Engine nutzt zeitgemäßes JavaScript wie „requestAnimationFrame“, um Animationen performant auszuführen.

Für nicht-kommerzielle Projekte ist die Verwendung von Popmotion kostenlos. Die kommerzielle Nutzung kostet runde 10 US-Dollar pro Monat und Projekt.

(dpe)

Kategorien
Bilder & Vektorgrafiken bearbeiten JavaScript & jQuery Webdesign

DrawSVG für jQuery – animierte Pfade beleben deine Website

Das SVG-Format kann ja glücklicherweise sehr viel mehr, als nur vektorbasierte Grafiken bereitzustellen. Auch Animationen sind möglich. Und mit JavaScript kannst du diese Animationen auf unterschiedliche Art und Weise steuern und beeinflussen. Das jQuery-Plugin DrawSVG lässt dich die Pfade einer SVG-Grafik per Animation zeichnen. Dabei gibt es mehrere Möglichkeiten, wie die Pfade gezeichnet werden können.

DrawSVG für jQuery - animierte Pfade beleben deine Website

Voraussetzung für DrawSVG

Als jQuery-Plugin muss der JavaScript-Allrounder natürlich zusammen mit dem Plugin im HTML-Head eingebunden sein. Anschließend ist es möglich, die Pfade einer SVG-Grafik zu animieren. Gemeint sind hierbei die per „<path>“-Element angelegten SVG-Formen. Strichstärke und -Farbe der Pfade können wie gewohnt per Attribut oder CSS definiert werden. Eine Füllfarbe sollte diesen Pfaden nicht zugeordnet werden, da diese nicht animiert würde und daher immer sichtbar wäre.

Zum Zeichnen der Pfade nutzt DrawSVG die Eigenschaften „stroke-dasharray“ und „stroke-dashoffset“. Diese beiden Eigenschaften solltest du daher ebenfalls nicht anderweitig einsetzen.

drawsvg_beispiel1
Zwei Ansichten während der Animation

Da das Plugin Zugriff auf den DOM-Baum der SVG-Grafik benötigt, sollte der SVG-Quelltext im HTML-Element eingebunden sein. Eine einfache Animation erfolgt über den Aufruf einer einfachen Zeile JavaScript.

$("svg").drawsvg("animate");

Das Beispiel greift auf alle SVG-Elemente zu, die im HTML-Dokument ausgezeichnet sind und versetzt diese per „drawsvg()“ in Animation. Dazu wird die komplette Grafik zunächst ausgeblendet. Anschließend zeichnet das Plugin ohne weiteres Zutun die einzelnen Pfade der Grafik. Damit ein realistischer Zeicheneffekt entsteht, werden die einzelnen Pfade einer Grafik mit einem kurzen zeitlichen Versatz animiert.

Je mehr Pfade eine SVG-Grafik also enthält, desto mehr einzeln startende Animationen sind vorhanden.

Animation per Optionen einstellen

Den zeitlichen Versatz für die Anfangszeit der einzelnen Pfade kannst du über die Option „stagger“ individuell festlegen.

var $svg = $("svg").drawsvg({
  stagger: 5000
 }).drawsvg("animate");

Die Optionen werden über einen eigenen Aufruf von „drawsvg()“ als Objektliteral übergeben. Im Beispiel wird der Versatz auf 5 Sekunden gesetzt. Die Länge der Animation, die standardmäßig eine Sekunde beträgt, kannst du ebenfalls per Option ändern.

var $svg = $("svg").drawsvg({
  stagger: 5000,
  duration: 10000
 }).drawsvg("animate");

Außerdem hast du die Möglichkeit, eine Callback-Funktion zu übergeben, die aufgerufen wird, sobald die Animation beendet wurde und die Grafik komplett sichtbar wird.

var $svg = $("svg").drawsvg({
  callback: function() {
    alert("Animation ist fertig.");
  }
 }).drawsvg("animate");

Im Beispiel geben wir einen einfachen Alert aus, sobald die Animation vervollständigt wurde.

drawsvg

Grafik per Scolling zeichnen

Mit ein paar Zeilen mehr JavaScript kannst du die SVG-Grafik auch per Scrolling zeichnen. Dazu muss das SVG-Element mittels CSS fixiert („position: fixed“) werden, damit es immer sichtbar ist. Außerdem muss die Seite natürlich scrollbar sein. Dazu kannst du einfach eine ausreichende Höhe per CSS definieren. Folgende Zeilen sorgen dann dafür, dass die Grafik durch das Herunterscrollen gezeichnet wird.

var $svg = $("svg").drawsvg();

$(window).on("scroll", function() {
  $svg.drawsvg("progress", $(window).scrollTop() / ($(document).height() - $(window).height()));
});

Eine Gesamtdauer für die Animation ist bei dieser Form logischerweise überflüssig. Denn die Animation ist in diesem Fall abhängig von der Scrollgeschwindigkeit. Je schneller gescrollt wird, desto schneller wird gezeichnet. Scrollst du wieder noch oben, verschwindet die Zeichnung auch wieder.

DrawSVG mit Pfaden und Maskierungen verwenden

Eine weitere Möglichkeit, das Plugin zu nutzen, besteht in der Kombination von Pfaden und Maskierungen. So kann beispielsweise ein „<mask>“-Element ja auch einen Pfad beinhalten. Ist dieser Pfad so gezeichnet, dass er dank ausreichend starker Linienstärke die komplette Maskierungsfläche füllt, kannst du damit sehr schön Bilder oder andere Elemente einblenden lassen.

drawsvg_beispiel2
Zwei Ansichten während einer Maskierungsanimation

Fazit und Link zum Beitrag

Die Einsatzmöglichkeiten von DrawSVG sind vielfältig. Dabei ist das Plugin schnell angewendet. Trotz weniger Optionen kann man sehr schöne Effekte erzielen. Die Dokumentation ist entsprechend übersichtlich. Einige Demos zeigen exemplarisch, was alles möglich ist.

DrawSVG wird von Leonardo Santos aus Porto Alegre entwickelt und steht auf Github auch zur Mitwirkung bereit. Das Plugin ist kommerziell frei verwendbar, da Santos es unter der liberalen MIT-Lizenz vertreibt.

(dpe)

Kategorien
JavaScript & jQuery Programmierung Webdesign

jQuery: Inhalte animiert einblenden mit animatedModal.js

Dank CSS3 sind Animationen immer häufiger ein fester Bestandteil zeitgemäßer Websites. So werden sie für Off-Canvas-Navigationen oder auch zur Einblendung zusätzlicher Inhalte wie Galerien eingesetzt. Das Framework animatedModal.js ermöglicht es, solche zusätzlichen Inhalte – Modals genannt – per CSS3-Animationen browserfüllend einzublenden. So lassen sich Bilder, Filme, zusätzliche Texte und alles, was sonst noch per Buttonklick eingeblendet werden soll, effektvoll in Szene setzen.

animatedmodaljs-teaser_DE

Modal auszeichnen und per animatedModal.js einblenden

Da die Animationen zum Ein- und Ausblenden der Modal-Bereiche über die CSS-Bibliothek „animate.css“ erfolgt, muss diese zunächst im HTML-Head eingebunden werden. Anschließend wird ein Modal-Bereich im HTML-Body ausgezeichnet. Das kann beispielsweise ein „<div>“-Element sein. Möglich sind aber auch HTML5-Elemente wie „<section>“ oder „<aside>“. Über eine ID wird der Modal-Bereich später angesprochen.

<div id="beispiel">
  <div class="close-beispiel">Schließen</div>
  <div class="modal-content">
    …
  </div>
</div>

Jeder Modal-Bereich besitzt zwei Kindelemente: ein Element, über welches der Modal-Bereich wieder geschlossen wird, und ein Element mit dem eigentlichen Inhalt des Modal-Bereichs. Das Schließen-Element muss einen Klassennamen besitzen, der aus „close-“ und der ID des Elternelements besteht – im Beispiel also „close-beispiel“. Der Inhaltebereich erhält den Klassennamen „modal-content“.

Um einen Modal-Bereich öffnen zu können, muss noch ein Button beziehungsweise ein Link per „<a>“-Element ausgezeichnet werden. Dieser erhält eine ID sowie als „href“-Attribut die Ziel-ID – also die ID des Modal-Bereichs.

<a id="beispiellink" href="#beispiel">Öffnen</a>

Im Beispiel soll per Klick auf den Link der Modal-Bereich mit der ID „beispiel“ geöffnet werden. Anschließend werden jQuery und die Datei „animatedModal.js“ im HTML-Body eingebunden. Über jQuery wird dem Öffnen-Link die Methode „animatedModal()“ zugewiesen.

$("#beispiellink").animatedModal();

Mehr ist zunächst nicht zu machen. animatedModal.js öffnet den Modal-Bereich anhand der im „href“-Attribut angegebenen ID per Zo0m-in-Animation und mit einem vordefiniertem Hintergrund. Die Schließen-Schaltfläche wird als Text mittig am oberen Rand dargestellt. Diesen kann man mit eigenem CSS den Bedürfnissen anpassen.

Aussehen und Animation einstellen

Um den Modal-Bereich zu indivisualisieren, stehen einem eine Reihe von Optionen zur Verfügung. So gibt es zum Beispiel die Möglichkeit, die Hintergrundfarbe für den Bereich festzulegen.

$("#beispiellink").animatedModal({
  color: "#000000"
});

Im Beispiel wird der Hintergrund schwarz dargestellt. Auch die Art der Ein- und Ausblend-Animation kann man einstellen. Hier stehen einem die Animationsvorgaben von „animate.css“ zur Verfügung. Auch die Dauer der Animation lässt sich angeben.

$("#beispiellink").animatedModal({
  animatedIn: "bounceIn",
  animatedOut: "bounceOut",
  animationDuration: "2s"
});

Während über „animatedIn“ und „animatedOut“ eine Animationsvorgabe angegeben wird, definiert „animationDuration“ die Dauer. Diese wird in Sekunden in der CSS-Einheit für Sekunden zugewiesen.

Für den Fall, dass der Inhalt des Modal-Bereiches so lang ist, dass sich ein Scrollen eventuell nicht vermeiden lässt, gibt es die Möglichkeit, das Scrollen innerhalb dieses Bereiches zu erlauben.

$("#beispiellink").animatedModal({
  overflow: "scroll"
});

Der Wert für die Option „overflow“ muss einem der möglichen Werte für die gleichlautende CSS-Eigenschaft entsprechen.

Per Events auf Öffnen und Schließen reagieren

animatedModal.js stellt zudem vier Events zur Verfügung, mit denen auf das Öffnen und Schließen eines Modal-Bereichs reagiert werden kann. So gibt es die Events „beforeOpen“ und „afterOpen“ sowie „beforeClose“ und „afterClose“.

Die Ereignisse „beforeOpen“ und „beforeClose“ rufen eine Funktion auf, sobald ein Button beziehungsweise Link zum Öffnen oder Schließen eines Modal-Bereichs betätigt wurden. „afterOpen“ und „afterClose“ hingegen werden ausgeführt, sobald die Animation zum Ein- beziehungsweise Ausblenden beendet wurde.

$("#beispiellink").animatedModal({
  beforeOpen: function() {
    console.log("Öffnen-Link wurde geklickt, Animation wird jetzt gestartet.");
  }
});

Im Beispiel wird etwas in die Konsole des Browsers geschrieben, sobald ein Link zum Öffnen eines Modal-Bereichs angeklickt wird.

Die Events können beispielsweise genutzt werden, um den Elementen innerhalb eines Modal-Bereichs Klassen zuzuweisen, die eine Animation starten. So werden während des animierten Öffnens des Modal-Bereichs auch die anderen Elemente per Animation in Stellung gebracht. Auf der Projektseite finden sich dazu einige schöne Beispiele.

animatedmodaljs_beispiel
Beispiel für eine Einblendung, bei der auch die Inhalte per Animation zum Einsatz kommen. 

Browsersupport und Lizenz

animatedModal.js läuft unter allen modernen Browsern. Der Internet Explorer wird ab Version 10 unterstützt. Das Script steht unter der MIT-Lizenz und kann daher kostenfrei auch in kommerziellen Projekten eingesetzt werden.

Im Download-Paket sind alle notwendigen Dateien vorhanden, einschließlich einer kleinen Demo-HTML-Datei. So kann man direkt selbst animatedModal.js ein wenig ausprobieren.

Links zum Beitrag

(dpe)