Javascript Framework MooTools

10. Februar 2009 Keine Kommentare »

Java-Script Frameworks gibt es mittlerweile unglaublich viele für die verschiedensten Einsatzgebiete. Einige disqualifizieren sich schon aufgrund ihrer unzureichenden Erweiterungsmöglichkeiten, andere hingegen sind in Sachen Dateigröße viel zu “großzügig” wodurch die Ladezeit der Seite unnötig verlängert wird.

Ein Framework, dass allerdings (fast) uneingeschränkt empfohlen werden kann ist MooTools. MooTools ist ein freies JavaScript-Framework, zur effizienten Entwicklung von erweiterbarem Code. Es ist vollständig objektorientiert, modular aufgebaut, kompakt und liefert browserübergreifend kompatiblem Code. Die Erweiterbarkeit und seine Modularität ermöglichen es dem Entwickler, selbst zu entscheiden, welche Komponenten er wirklich einzusetzen möchte und welche lieber nicht.

Außerdem existiert eine umfangreiche Dokumentation des Frameworks. Auf der folgenden Seite werden einige Beispiele vorgestellt. Es gibt auch zahlreiche Plugins und Erweiterungen basierend auf dem MooTools Framework.

Tags:

Bookmarken bei... del.icio.us:Javascript Framework MooTools furl:Javascript Framework MooTools Y!:Javascript Framework MooTools

Galerie-Komponente für Joomla 1.5

29. September 2008 Keine Kommentare »

MorfeoShow ist eine Galerie-Komponente für Joomla 1.5. Mit ihr ist es möglich, Bildergalerien mit verschiedenen Effekten zu erstellen.
Die Komponente kann wahlweise mit Javascript/AJAX oder Flash arbeiten. Im Funktionsumfang ist ebenfalls die Möglichkeit enthalten, die Bilder vom Bilderdienst Flickr oder von Picasa zu beziehen und anzeigen zu lassen.
Eine Auswahl an Galerietypen sind u.a. ImageRotator, Simpleviwer, PostCard, Polaroid, Flickr und auch Google Maps.

Eine Live-Demo mit allen verfügbaren Anzeigemöglichkeiten ist auf der Seite des Herstellers (http://morfeoshow.joomlaitalia.com) zu finden .

Tags:, , , ,

Bookmarken bei... del.icio.us:Galerie-Komponente für Joomla 1.5 furl:Galerie-Komponente für Joomla 1.5 Y!:Galerie-Komponente für Joomla 1.5

Flash Mediaplayer

18. August 2008 Keine Kommentare »

Der JW FLV Player ermöglicht es Video- sowie Audio-Files in eine Homepage einzubinden und abzuspielen. Unterstützt
werden alle Formate, die der Adobe Flash Player abspielen kann. Darunter zählen bspw. FLV, MP4, MP3, AAC, JPG, PNG
und GIF.  Zusätzlich zu diesem Funktionsumfang können auch Live Streamings abgespielt werden. Diverse Konfigurationsmöglichkeiten erlauben das Abspielen von Playlists und beschriftetenVideoformaten.

Die JW FLV Player API ermöglicht die Konfiguration des Players mit Hilfe der Sprachen JavaScript und ActionScript. Auf der Website des Herstellers findet man unter anderem eine Installationsanleitung und auch ein Wiki, das für die meisten Fragen rund um die Einstellungsmöglichkeiten bereits passende Antworten enthält.

Die Installation des Players ist dank der hervorangenden und ausführlichen Beschreibung des Entwicklers für Jedermann verständlich. Als erstes muss das vollständige Paket von hier heruntergeladen werden.
Anschließend muss der Inhalt des Pakets extrahiert werden und ins root-Verzeichnis des Webserver kopiert werden. In dem jeweiligen Website Dokument, in dem ein Video-/Audio-Film abgespielt werden soll, muss der folgende Code eingefügt werden.

[code]
<div id='preview'>The player will show in this paragraph</div>

<script type='text/javascript' src='swfobject.js'></script>
<script type='text/javascript'>
var s1 = new SWFObject('player.swf','player','400','300','9');
s1.addParam('allowfullscreen','true');
s1.addParam('allowscriptaccess','always');
s1.addParam('flashvars','file=video.flv');
s1.write('preview');
</script>
[/code]

In das Div-Tag mit der id=’preview’ wird die Ausgabe des Videos positioniert. Dies ermöglicht es, den JavaScript-Code unabhängig von der späteren Position der Videoausgabe in das html-Dokument einzubauen. Beim Initialisieren des Players können Einstellungen wie z.B. Breite und Höhe mit übergeben werden. Die restlichen Einstellungen betreffen Parameter und Variablen, die weitere Anpassungen erlauben.
Eine komplette Liste über Möglichkeiten der Anpassung ist hier zu finden.

Tags:, ,

Bookmarken bei... del.icio.us:Flash Mediaplayer furl:Flash Mediaplayer Y!:Flash Mediaplayer

Debug-Funktionen für JavaScript

20. November 2007 1 Kommentar »

Häufig sieht man sich bei der Arbeit mit JavaScript mit der Situation konfrontiert, dass man statt mit einer ausgereiften Entwicklungsumgebung mit integriertem Debugger mit einem blanken Texteditor Vorlieb nehmen muss. Insbesondere bei der Arbeit mit DOM-Objekten wird die Fehlersuche dann weniger komfortabel als man es sich vielleicht wünscht :-)

JavaScript bietet nun allerdings die Möglichkeit, bequem Eigenschaften und Methoden von Objekten zur Laufzeit zu erfragen. Damit kann man sich zwei hilfreiche Funktionen basteln, mit denen man Eigenschaftswerte von Objekten sichtbar machen kann.

[code lang="javascript"]
function obj2str (p_Obj) {
var strText = "";
var i = 0;
for (prop in p_Obj) {
strText += i++ + " " + prop + ": " + p_Obj[prop] + "\n";
}
return strText;
}

function printObject (p_Obj) {
var wnd = window.open ();
var str = obj2str (p_Obj);
str = str.replace (/\ str = str.replace (/\>/g, ">");
wnd.document.write ("

<pre><br/>\n " + str + " \n<br/></pre>

");
wnd.focus ();
}

[/code]

Durch den Aufruf von printObject (obj) öffnet sich ein Browserfenster, das alle Eigenschaften von obj inklusive ihrer Inhalte ausgibt.

Zum Debugging von Funktionsaufrufen ist die folgende Funktion hilfreich:

[code lang="javascript"]
Function.prototype.callString=function(){
var args = this.arguments;
var str = this.caller + " \n --calls--> \n \t (";
for (var i = 0; i < args.length - 1; i++) {
str += args[i] + ", ";
}

str += args[args.length-1] + ") \n";
str += this.toString ();
return str;
};
[/code]

Der Aufruf erfolgt über

[code lang="javascript"]
function callString (p_strFuncName) {
var fn = eval (p_strFuncName);
alert (p_strFuncName + ": " + fn.callString ());
}
[/code]

CallString gibt den Code einer Funktion samt Aufrufparameter aus.

Tags:, ,

Bookmarken bei... del.icio.us:Debug-Funktionen für JavaScript furl:Debug-Funktionen für JavaScript Y!:Debug-Funktionen für JavaScript

Funktionale Erweiterung von JavaScript

19. November 2007 2 Kommentare »

JavaScript ist eine objektbasierte Skriptprache mit dynamischer Typisierung, mit deren Hilfe man Webseiten mit clientseitigem “Verhalten” versehen kann. Im Zeiten von Web 2.0 und insbesondere Ajax kann man beobachten, dass Seiten zunehmend dynamischer werden. Ihre Programmlogik und die damit verbundene Entwicklungsarbeit werden immer umfangreicher. Es stellt sich daher die Frage, inwieweit die Sprache für solche Anforderungen geeignet ist.

An dieser Stelle möchte ich nun einige bekannte Eigenschaften von JavaScript betrachten. Im Zusammenhang mit der Eignung für umfangreiche Entwicklungen sind zwei Eigenschaften von JavaScript interessant. Diese verleihen Programmen einen – mitunter überraschend – hohen Grad an Dynamik.

Zunächst ist die Sprache objektbasiert im folgenden Sinne. Vererbungsbeziehungen werden über eine sogenannte prototypische Vererbung ad-hoc aufgebaut. Das bedeutet nichts anderes, als dass jedes Objekt zu jeder Zeit um beliebige Eigenschaften und Methoden erweitert werden kann. Weiterhin gibt es keine mit den “klassischen” objektorientierten Sprachen vergleichbaren sprachlichen Mittel, um Daten zu kapseln. Es gibt zwar Wege, eine Kapselung über lokale Variablen in Konstruktorfunktionen zu erreichen, allerdings gibt es hierfür keine explizite Ausdrucksweise wie etwa in C++ oder Java.

Zum anderen nimmt der Interpreter zu keiner Zeit eine Prüfung von Funktionsaufrufen vor. Weder Typ noch die Anzahl (!) der übergebenen Parameter werden mit der Definition einer Funktion verglichen.

Beispiel:

Eine Funktion

[code lang="JavaScript"]
function test (p_1, p_2, p_3) {
alert (p_1); alert (p_2); alert (p_3);
}
[/code]

kann als test (1), test (1,2) oder test (1,2,3) aufgerufen werden. Nicht übergebene Parameter haben innerhalb der Funktion den Wert “undefined”. Diese und andere Eigenschaften führen dazu, dass es bei umfangreichen Programmteilen mitunter schwierig ist, abzuschätzen, wie sich ein Stück Code bei seinem Aufruf verhält.

JavaScript ist natürlich nicht ohne Grund so geraten. Vielmehr eignen sich dynamische Skriptsprachen gut zur Entwicklung von Prototypen oder einfacher Programmlogiken. Bei umfangreichen Entwicklungen ist – zumindest meiner Erfahrung nach – ein “ordendliches”, sprich: statisches Typsystem durchaus eine große Hilfe. Die Dinge sind nun aber wie sie sind und kann man versuchen, das Beste daraus zu machen. In diesem Artikel möchte ich daher zeigen, wie man JavaScript etwas von dem Feeling einer funktional Sprache verleihen kann. Funktionale Sprachen zeichnen sich in gewissem Sinne dadurch aus, dass Programme auf einer abstrakteren Ebene formuliert und dadurch kompakter werden. Davon verspreche ich mir zweierlei: Zum einen wird die Lesbarkeit des Codes verbessert, zum anderen werden Wiederverwendbarkeit und Robustheit erhöht, da für häufig verwendete Konzepte benannte Strukturen definiert werden.

Funktionale Programmiersprachen zeichnen sich im wesentlich durch zwei Konzepte aus:

  1. Referentielle Transparenz
  2. Funktionen sind First-Class-Objects

Referentielle Transparenz bedeutet, dass der Wert einer Variablen nur von ihrer Umgebung abhängt und nicht vom Zeitpunkt ihrer Verwendung. Variablen werden daher eher “im mathematischen Sinn” aufgefasst und weniger als benannte Speicherplätze. Insbesondere ist eine Variable, für die referentielle Transparenz gilt, unabhängig von Seiteneffekten. JavaScript bietet dieses Konzept nicht. Bei Funktionsaufrufen kann man ihm aber durch Wertkopien und die ausschließliche Verwendung lokaler Variablen nahekommen.

Werden Funktionen als First-Class-Objects aufgefasst, können sie genauso wie Werte behandelt werden und damit auch Rückgabewerte oder Parameter von Funktionen sein oder zur Laufzeit erzeugt werden. Das geht über das Konzept eines einfachen Funktionszeigers in C hinaus – hier sind bspw. keine anonymen oder partiell evaluierten Funktionen möglich. In JavaScript sind Funktionen Objekte. Sie können zur Laufzeit – auch anonym – erzeugt und verarbeitet werden. Darüber hinaus sind Funktionen in JavaScript Closures. Das bedeutet, eine lokal definierte Funktion “erbt” das sie umgebende lexikalische Scope.

[code lang="JavaScript"]
function testClosure () {
var myInt = 1;
var closure = function (e) {
return e + myInt;
}
alert (closure ( 2));
}

[/code]

Innerhalb von closure () ist myInt sichtbar, obwohl es nicht global deklariert ist. Mit Hilfe dieser Eigenschaft ist es bspw. auch möglich, Eventhandler zu parametrieren, ohne globale Variablen zu verwenden.

JavaScript bietet mit diesen Eigenschaften nun die Möglichkeit, sogenannte Funktionale zu definieren. Das sind im syntaktischen Sinne gewöhnliche Funktionen mit der Besonderheit, dass sie eine oder mehrere Funktionen als Parameter entgegen nehmen und deren Ausführung steuern. Ich möchte hier exemplarisch drei Beispiele für Funktionale zeigen, die auch in anderen Sprachen verfügbar sind. Diese sind map, filter und foldr.

Map nimmt eine Liste l und eine unäre Funktion f als Parameter und wendet f auf jedes Element von l an. Die Parameter von Filter sind eine Liste l und ein unäres Prädikat p. Die Rückgabe von filter sind dann alle Element von l, für die p gilt. Foldr ist etwas komplizierter. Die Parameter sind eine Liste l, eine binäre Funktion f und ein für die Funktion neutrales Element n. Die Rückgabe von foldr ist ein einziges Element, das folgendermaßen bestimmt wird: f wird auf das letzte Element von l und n angewendet. Das Ergebnis nennen wir e1 := f (l[-1], n). Dann wird f auf e1 und das vorletzte Element von l angewendet: e2 := f (l[-2], e1), u.s.w. bis nur noch ein Element übrigbleibt. Mit Hilfe von foldr kann man Elemente kumulieren, Maxima ermitteln und Listen sortieren – vorausgesetzt man definiert eine entsprechende Funktion.

Im folgenden zeige ich, wie diese Funktionale in JavaScript realisiert werden können. Durch sein Konzept der prototypischen Vererbung bietet JavaScript die Möglichkeit, vorhandene “Klassen” auch nachträglich um eigene Methoden zu erweitern. Unsere Funktionale arbeiten auf Listen – es bietet sich daher an, sie dem eingebauten “Listen”-typ – dem Array als Methoden in die Schuhe zu schieben. Die vorgestellten Implementierungen werden daher als Erweiterungen des Array-Prototyps realisiert. Um eine Art referentielle Transparenz zu erhalten, legen alle Methoden Kopien der übergebenen Felder an.

Eine Implementierung von map () lässt sich in JavaScript folgendermaßen realisieren:

  1. p_Func ist die Funktion, die auf jedes Element der Array-Instanz angewendet wird

[code lang="JavaScript"]
Array.prototype.map = function (p_Func) {
var ret = new Array (this.length);
for (var i = 0; i < this.length; i++) {
ret[i] = p_Func (this[i], i);
}
return ret;
};

[/code]

Im Fall von Filter kann das Ergebnis dann so aussehen:

  1. p_Func ist das Prädikat, das auf das Array angewendet werden soll
  2. p_bReturnIndex gibt an, ob das Ergebnis-Array die Indices oder die Elemente beinhalten soll
  3. p_bPreserveIndex gibt an, ob nicht enthaltene Elemente ausgespart werden sollen
  4. p_Neutral ist ein neutraler Wert, der für nicht enthaltene Werte gesetzt wird, sofern p_bPreserveIndex gesetzt ist

[code lang="javascript"]
Array.prototype.filter = function (p_Func, p_bReturnIndex, p_bPreserveIndex, p_Neutral) {
var ret = new Array ();
for (var i = 0; i < this.length; i++) {
if (p_Func (this[i], i)) {
if (p_bPreserveIndex) {
(p_bReturnIndex) ? ret[i] = i : ret[i] = this[i];
} else {
(p_bReturnIndex) ? ret.push (i) : ret.push (this[i]);
}
} else if (p_bPreserveIndex) {
(p_bReturnIndex) ? ret[i] = -1 : ret[i] = p_Neutral;
}
}
return ret;
};
[/code]

Map kann auf die folgende Weise umgesetzt werden:

  1. p_Func ist die Funktion, die auf jedes Element angewendet werden soll. An dieser Stelle wird eine binäre Funktion übergeben, die als zweites Argument den aktuellen Index des Elements erhält.

[code lang="javascript"]
Array.prototype.map = function (p_Func) {
var ret = new Array (this.length);
for (var i = 0; i < this.length; i++) {
ret[i] = p_Func (this[i], i);
}
return ret;
};
[/code]

Die Umsetzung von Foldr ist wie folgt:

  1. p_Func ist eine binäre Funktion
  2. p_Neutral ist ein neutrales Element dieser Funktion

[code lang="javascript"]
Array.prototype.foldr = function(p_Func, p_Neutral) {
return (this.length == 0) ? p_Neutral :
p_Func(this[0], this.slice(1).foldr(p_Func, p_Neutral));
};
[/code]

Die Funktionalität gegenüber einer “einfachen” Schleife ist hier nicht eingeschränkt. Lokal definierte Funktionen in JavaScript sind sogenannte Closures. Das bedeutet, dass Variablen aus dem umgebenden Scope im inneren einer solchen Funktion sichtbar sind.

Beispiel:

[code lang="javascript"]
var myArray = new Array (1,2,3,4);
var myInt = 3;
var smaller = myArray.filter (function (p_El) { return p_El < myInt; } );
[/code]

Die Variable myInt ist innerhalb der anonymen Funktion sichtbar, obwohl sie außerhalb definiert wurde.

Was erreichen wir damit? Zum einen erhält man eine bessere Wiedererkennbarkeit von Codeabschnitten. In einer Schleife kann im Prinzip alles mögliche getan werden – bei einem Funktional ist auf einen Blick klar, was seine Aufgabe ist. Zum anderen bieten zwingt man sich letztendlich auch dazu, seinen Code besser durch Funktionen zu strukturieren. Neben anonymen Funktionen können die Funktionale auch benannte Funktionen mit einer passenden Signatur entgegen nehmen. Das trägt widerum zu einer besseren Lesbarkeit und darüber hinaus zu einer höheren Wiederverwendbarkeit verglichen mit einem einfachen Schleifenrumpf bei.

Beispiel:

In dem Array myArray sollen alle geraden Zahlen mal 2 genommen werden.

[code lang="javascript"]
var myArray = new Array (1,2,3,4);
[/code]

In einer einfachen Schleife sieht das etwa so aus:

[code lang="javascript"]
var newArray = new Array ();
for (var i = 0; i < myArray.length; i++) {
if (myArray[i] % 2 == 0) {
newArray.push (2 * myArray[i]);
}
}
[/code]

Der funktionale Ausdruck ist hingegen deutlich kompakter als die Schleife:

[code lang="javascript"]
var twotime = function (p_Par) { return p_Par * 2; }
var even = function (p_Par) { return p_Par % 2 == 0; }
var newArray = myArray.map (twotime).filter (even);
[/code]

Der auf diese Art veränderte Array-Prototyp wirkt sich auf alle Instanzen aus, die im Anschluss an die Deklarationen gebildet werden. Insbesondere bei der Arbeit mit DOM-Objekten muss man allerdings beachten, dass diese bereits im Browser instatiiert sind, bevor externe JavaScript-Quellen geladen werden. Um also Arrays, wie sie von DOM-Objekten geliefert werden, auf diese Art verwenden zu können, muss man eine neue Array-Instanz bilden. Das kann man am einfachsten mit einer Art Konstruktor-Funktion erreichen:

[code lang="JavaScript"]
Array.prototype.construct = function (a) {
for (var i = 0; i < a.length; i++) {
this.push (a[i]);
}
return this;
};
[/code]

Gehen wir nun davon aus, dass wir es mit einer Html-Tabelle zu tun haben, die in jeder ihrer Zellen eine Textbox beinhaltet. Der Einfachheit halber sollen zunächst lediglich die Werte dieser Textboxen beschafft werden. Mit Hilfe von Funktionalen kann diese Aufgabe lösen.

Wir brauchen zunächst eine Funktion, welche die Textboxen ermittelt.

[code lang="JavaScript"]
var fnGetTextbox = function (nd, pos) {
return nd.getElementsByTagName("input")[0];
};
[/code]

[code lang="JavaScript"]
function getTextboxes (p_Table) {
var vndCells = new Array ().construct (p_Table.getElementsByTagName ("td"));
var vtxtInput = vndCells.map (fnGetTextbox);
return vtxtInput;
}
[/code]

Weiterhin definieren wir eine Funktion, die den Wert einer Textbox liest.

[code lang="JavaScript"]
var fnGetValue = function (nd, pos) {
return (nd ? nd.value : '');
};

[code lang="JavaScript"]
var vtxtInput = getTextboxes (row);
var vValues = vtxtInput.map (fnGetValue);
[/code]

Um aufwändigere Aufgaben zu erledigen, kann man map () mit einer lokalen Funktion parametrieren.

[code lang="JavaScript"]
var vtxtInput = getTextboxes (row);
var newValue = "Inhalt: ";
var vValues = vtxtInput.map (function (p_Nd, p_iPos) {
p_Nd.value = newValue + p_iPos;
return p_Nd;
});
[/code]

Selbstverständlich sind Funktionale nicht wirklich mächtiger als Schleifen. Der entscheidende Unterschied, der nicht zuletzt beim Einsatz mit DOM zum Tragen kommt, ist allerdings der folgende: Das Wissen um die Strukturen innerhalb der Listenelemente (sprich: wie liegen Eigenschaften von Elementen innerhalb von Zellen einer Tabelle) ist innerhalb einer Funktion gekapselt. Auf diese Weise wird Code, der für die Traversierung einer Struktur verantwortlich ist, getrennt von der Logik, die einzelne Elemente betrifft.

Tags:,

Bookmarken bei... del.icio.us:Funktionale Erweiterung von JavaScript furl:Funktionale Erweiterung von JavaScript Y!:Funktionale Erweiterung von JavaScript