Dieser Artikel ist Teil einer Serie:
Nachdem wir in den letzten Teilen der Serie die Basics hinter uns gebracht haben, geht es heute um die eigentlichen Bausteine des Mootools-Frameworks: Objekte. Mootools ist objektorientiert und wir schauen uns in diesem Teil der Serie an, wie man diese verwendet. Außerdem exerzieren wir damit ein Tutorial durch, an dessen Ende wir ein Script mit Ajax- und Drag&Drop-Funktionen geschrieben haben werden – in nur 11 Zeilen Mootools-Code.
Mootools und Objekte
So gut wie alles in Mootools ist ein Objekt – Plugins, HTML-Elemente, Ajax-Requests, der JSON-Parser und alles andere. Elemente werden in Mootools mit new
erstellt und haben wie ganz normale Javascript-Objekte Eigenschaften und Methoden. Ein Beispiel:
// Wir erstellen ein neues Div mit der Klasse
// "foobar" und ein paar Inline-Styles
var meinDiv = new Element('div', {
'class': 'foobar',
'text': 'Das ist ein ganz tolles, neues Div!',
'styles': {
'font-weight': 'bold',
'margin': '1em'
}
});
// Die "inject()"-Methode des Div-Objekts fügt das
// Element in ein anderes Element ein
var meinAnderesDiv = $('meinAnderesDiv');
meinDiv.inject(meinAnderesDiv);
So läuft es bei Mootools mit allem – auch mit Effekten. Der eine oder andere mag sich an dieses Code-Beispiel aus dem letzten Teil der Artikelserie erinnern:
// Das Element mit der Mootools-Fade-Methode ausblenden
$('foo').fade('out');
Der Fade-Effekt an dieser Stelle hier sieht nicht nach einem Objekt aus, oder? Das ist aber auch nur so, weil die fade()
-Methode von HTML-Elementen als eine handliche Abkürzung für das eigentliche Effekte-Objekt ist. Für Effekte wie eine einfache Überblendung ist das Fx.Tween-Objekt zuständig, das in voller Pracht so aussieht:
// Element auswählen
var meinElement = $('meinDiv');
// Effekt-Objekt erstellen
var meinEffekt = new Fx.Tween(meinElement, {
'duration': 500
});
// Effekt starten!
meinEffekt.start('opacity', 1, 0);
Das ist etwas mehr zu tippen als meinElement.fade()
, macht aber auch mehr möglich, denn dem Fx.Tween-Objekt kann man eine Reihe nützlicher Optionen mitgeben. So lässt sich der Effekt fein steuern – im Beispiel wird die Dauer des Ausfadens auf 500ms festgelegt, aber man kann auf diese auch Effekte koppeln, die Framerate festlegen und Events nutzen.
Kurz gesagt: Objekte sind bei Mootools die Bausteine des Frameworks. Für einige Funktionen gibt es Abkürzungen, aber ohne Objekte geht es nicht. Und das ist auch gut so.
Ein etwas komplexeres Beispiel
Gregor hat sich in den Kommentaren zum letzten Teil der Serie ein Code-Beispiel gewünscht, das Drag&Drop verwendet und die Position der durch die Gegend gedragten Elements per Ajax abspeichert. Nichts leichter als das!
Zuerst brauchen wir das Mootools-Plugin für Drag&Drop. Das nennt sich schlicht und ergreifend Drag und ist im More Builder, der Download-Seite für Plugins aus der More-Komponente von Mootools, zu beziehen. Für Ajax brauchen wir nichts weiter, denn das Request-Objekt ist Bestandteil der Core-Komponente. Folgendes HTML soll den Rahmen für unser kleines Tutorial darstellen:
<!DOCTYPE html>
<html>
<head>
<meta http-equiv="content-type" content="text/html; charset=UTF-8">
<title>Test</title>
<style type="text/css">
body, html { height:100%; width:100%; margin:0; padding:0; }
#drag { background:#000; color:#FFF; cursor:pointer; width:100px; position:absolute; top:0; left:0; padding:8px; }
</style>
<script type="text/javascript" src="mootools-1.2.3-core-yc.js"></script>
<script type="text/javascript" src="mootools-1.2.3.1-more.js"></script>
<script type="text/javascript">
window.addEvent('domready', function(){
// Hier kommt unser Code hin
});
</script>
</head>
<body>
<div id="drag">Zieh mich!</div>
</body>
</html>
Als nächstes erstellen wir das Objekt für die Drag-Funktion. Zusätzliche Optionen sind erst mal nicht nötig, also erstellen wir einfach ein Drag
für das Div mit der ID drag
.
var tutorialDrag = new Drag('drag');
Was man hier schön sieht, ist dass Drag
(wie die meisten Plugins) eine eingebaute Dollar-Funktion hat, d.h. man muss ein HTML-Element, das man an ein Plugin übergeben will, nicht vorher mit $()
oder $$()
ausgewählt haben. Man kann das machen, kann aber genau so gut einfach die ID als String übergeben.
Nächster Schritt: das Request-Objekt für die Ajax-Funktion.
var tutorialRequest = new Request({
url: 'save.php'
});
Hier müssen wir die Zieladresse für den Request als Option url
mitgeben. Die Datei save.php
wird das Speichern der Position des Objekts übernehmen.
Nun müssen wir das Drag- und das Request-Objekt so verzahnen, dass der Request ausgelöst wird, wenn unser Zieh-mich-Div verschoben wurde. Praktischerweise hat Drag ein complete
-Event, mit dem wir eine Funktion auslösen können, sobald der Benutzer sein Verschieben abgeschlossen hat. Also bauen wir unser Drag-Objekt entsprechend um:
var tutorialDrag = new Drag('drag', {
onComplete: function(){
tutorialRequest.send();
}
});
Damit rufen wir die send()
-Methode des Request-Objekts aus, die die Ajax-Anfrage abschickt. Einziges Problem dabei: Wir haben noch gar keine Daten, die wir speichern könnten. Was wir hierfür brauchen sind die X- und Y-Koordinaten des Drag-Divs, die wir mit der getPosition-Methode abfragen können. Und weil das complete
-Event des Drag-Objekts das verschobene Element selbst mitübergibt, können wir es uns recht einfach machen:
var tutorialDrag = new Drag('drag', {
onComplete:function(el){
var pos = el.getPosition();
tutorialRequest.send();
}
});
Die pos
-Variable enthält jetzt ein Objekt mit den X- und Y-Koordinaten unseres Divs:
{ x: 47, y: 175 }
Das naheliegendste wäre, dieses Objekt für die Speicherung in einen JSON-String zu verwandeln, was mit dem JSON-Encoder von Mootools denkbar einfach ist. Das Ergebnis senden wir dann in Form eines Querys mit der send()
-Methode des Request-Objekts.
var tutorialDrag = new Drag('drag', {
onComplete: function(el){
var pos = el.getPosition();
tutorialRequest.send('pos=' + JSON.encode(pos));
}
});
Und damit sind wir eigentlich fertig. Wir haben ein komplettes, JSON verwendendes Drag&Drop-Ajax-Script in 11 Zeilen gebaut:
window.addEvent('domready', function(){
var tutorialDrag = new Drag('drag', {
onComplete:function(el){
var pos = el.getPosition();
tutorialRequest.send('pos=' + JSON.encode(pos));
}
});
var tutorialRequest = new Request({
url: 'save.php'
});
});
Was jetzt noch fehlt ist das PHP zum bearbeiten des Ajax-Requests …
// save.php
if($_POST['pos']){
if($fp = fopen('position.txt', 'w')){
fwrite($fp, $_POST['pos']);
fclose($fp);
}
}
… und zum Auslesen der Koordinaten beim Laden der Seite:
// Auslesen der Daten in der HTML-Datei
$style = '';
if($fp = fopen('position.txt', 'r')){
$line = fgets($fp, 100);
$dimensions = json_decode(stripslashes($line));
if($dimensions->x && $dimensions->y){
$style = 'style="top:'.$dimensions->y.'px; left:'.$dimensions->x.'px;"';
}
fclose($fp);
}
<div <?php echo $style; ?> id="drag">Zieh mich!</div>
Es funktioniert! Nach jedem Neuladen der Seite ist das Drag-Element wieder an genau der Stelle, wo man es gelassen hat (jedenfalls so lange nicht mehrere Leute gleichzeitig daran herumspielen). Das gesamte Script gibt es auch gezippt zum Download.
Fazit und Ausblick
Dieses kleine Tutorial hat ganz gut zwei Eigenschaften von Mootools demonstriert:
- Alles ist ein Objekt
- Der Code ist ausgesprochen kompakt
Aber auch das ist nicht die wahre Stärke von Mootools – richtig gut wird es erst, wenn man selbst anfängt Plugins zu schreiben oder bestehende Plugins zu erweitern. Darum soll es dann im nächsten Teil gehen. Wer für diesen Teil 4 Sonderwünsche hat, der möge sie in den Kommentaren hinterlassen.
Kommentare (25)
Markus Thömmes ¶
31. Juli 2009, 13:17 Uhr
Suuuuper Postreihe! Ich beginne doch tatsächlich das Ganze zu verstehen. Vielen Dank schonmal soweit.
wetternest ¶
31. Juli 2009, 17:56 Uhr
echt coole sache!
da hab ich doch etwas komplizierter geschrieben...
für den nächsten teil noch eine frage: was ist ein plugin, was kann das woher kommt das und so weiter
max ¶
31. Juli 2009, 18:57 Uhr
hinter und gebracht haben
wohl eher
hinter uns gebracht haben
max ¶
31. Juli 2009, 19:12 Uhr
... aber 'mal im Ernst, sehr schön geschriebener Beitrag, genau das Richtige für uns Normalsterblichen ;)
Peter ¶
31. Juli 2009, 20:50 Uhr
Zitat max:
Danke für den Hinweis, ist korrigiert.
Lars ¶
31. Juli 2009, 23:16 Uhr
Da fehlt ein Verb (evtl. sieht?) gleich nach dem zweiten Codebeispiel:
Ansonsten sehr schick, works like a charm :)
Nachdem ich eh schon ein Fan von Objektorientierung bin, weiß ich jetzt auch was ich hernehmen muß, wenn's denn mal Javascript sein soll.
Peter ¶
1. August 2009, 09:20 Uhr
Zitat Lars:
Danke, ist ergänzt!
Benny ¶
1. August 2009, 14:32 Uhr
Hab ich jetzt gerade die Demo kaputt gemacht, weil ich die drag-box oben links aus dem fenster geschoben habe, wo man nicht mehr drankommnt?
Gregor ¶
1. August 2009, 16:07 Uhr
Danke!
CRI ¶
2. August 2009, 12:36 Uhr
Zitat Benny:
hm - vielleicht?
komm an kein div mehr ran (opera 9.64 win)
ansonsten vielen dank für die vorstellungsreihe!
Peter ¶
2. August 2009, 12:42 Uhr
Aber meine Herren, wir haben doch alle Entwicklungstools im Browser oder? Einfach das Element per Firebug o.Ä. wieder in den sichtbaren Bereich schieben, einmal draggen und schon ist es repariert.
Rene Descher-Hackel ¶
8. August 2009, 08:16 Uhr
Zitat Peter:
Von abgesehen, dass Javascriptframeworks eine echt coole Sache sind, so sollte das Script mit Defaultwerten arbeiten, sprich wenn ein Benutzer den Container außerhalb des sichtbaren Bereiches zieht. Benutzer sind so - sie machen meistens das, was sie nicht machen sollten ;-)
Ansonsten knackiger Beitrag - gleich ich Ahänger vom jQuery bin ;-)
Thomas ¶
2. August 2010, 15:44 Uhr
Hallo Peter,
auf der Suche nach einer Möglichkeit, ein Div einzublenden, bin ich bei dieser sehr guten Tutorialserie gelandet. Danke dafür.
Die Tween-Funktion habe ich angewendet; klappt nahezu auf allen Browsern.
Nur der Safari-Browser unter OS X zeigt erst den Inhalt des Divs kurz beim Seitenaufruf an, wird dann auf unsichtbar (0) gesetzt und dann eingeblendet (1).
Mit CSS kann ich zwar das Div unsichtbar setzen, dann ist dieser Effekt verschwunden, leider bei deaktiviertem Javascript auch die Inhalte des Divs.
Gibt es noch einen Kniff, damit es auch im Safari "rund" läuft?
Beste Grüße
Thomas
Peter ¶
2. August 2010, 15:50 Uhr
Kannst du mal den JS-Code hier einfügen? Schau in die Formatierungsmöglichkeiten, da gibt es Tags für Javascript-Highlighting.
Thomas ¶
2. August 2010, 15:54 Uhr
Hallo Peter,
ups das geht ja fix ;-)
window.addEvent('domready', function () {
$$('#main div').each(function(el){
// Effekt-Objekt erstellen
var meinEffekt = new Fx.Tween(el, {
'duration': 1500
});
// Effekt starten!
meinEffekt.start('opacity', 0, 1);
});
});
Im Div #main sind Text und Bildinhalte, die eingeblendet sollen bei jedem Seitenaufruf.
Danke. Thomas
Marc ¶
2. August 2010, 15:54 Uhr
Setze in Deinen Head
Und sprich das DIV in der CSS mit
an. Blitzt es dann immer noch?
Daniel Rauber ¶
2. August 2010, 15:55 Uhr
Zitat Thomas:
Du könntest das DIV im CSS auf unsichtbar setzten und das Problem mit dem deaktivierten JS umgehen indem du mit den Tags im HTML etwas erzeugst was dein DIV im CSS sichtbar macht, zum Beispiel eine Klasse einfügst oder so.
Thomas ¶
2. August 2010, 16:10 Uhr
Danke euch beiden.
@Marc: Das sieht jetzt sehr gut aus :-)
Danke.
Thomas
florian ¶
2. August 2010, 16:59 Uhr
das problem müsste auch in chrome bestehen?!
falls ja: du hast s mit in deinem content-bereich?
die webkit-engine - mit der sowohl safari als auch chrome arbeiten - ist so schnell, dass dom-objekte, die externe inhalte (flash, imgs, ...) erst in ihrer endlichen größe gerendert werden, wenn der dom schon komplett geladen ist ....
mit anderen worten: mach mal aus dem 'domready' ein 'load' -- nur zur probe!
besser?
Thomas ¶
2. August 2010, 18:27 Uhr
Hallo Florian,
danke für dein Feedback.
Nein mit load wird es wie vorher: Inhalt wird kurz angezeigt.
Ich habe den Code nun im Head:
Oliver ¶
25. September 2010, 18:55 Uhr
Tolles Tutorial...
seit 10 Jahre drücke ich mich vor JA, aber für meine ARbeit ist der umgang mit einem js framework unverzichtbar... endlich bringt mir jemand das ganze näher und da ich auch schon ne weile mit php arbeite. und dort auch ab und zu oop, fällt mir das ganze nicht sooo schwer, wie befürchtet
Danke!!
nun brauch ich nur noch kleine Tutorials oder eine deutsche referenz, die mir die ganzen standard/grundfunktionenen listet und bebeispielt... hab zb ne ecke suche müssen, bevor ich wußte, wie ich mit get set den 'text' eines elementes ändere...war aber shcon in der lage viel kompliziertere Dinge zu managen!
Gruss aus Berlin
Oliver
Oliver ¶
25. September 2010, 18:57 Uhr
Nachtrag, das drop beispiel hätte ich gern erweitert erklärt, wie man das drop nur für bestimmte regionen erlaubt.. ähnlich piwik, falls das bekannt ist!
Peter ¶
25. September 2010, 21:34 Uhr
Die offizielle Doku hat reichlich eingebaute Beispiele. Für regional beschränktes Drop einfach Drag.Move verwenden.
Olaf ¶
26. September 2010, 03:23 Uhr
Hallo Peter,
herzlichen Dank für dieses Tutorial!
Aller Anfang ist schwer. Na klar. Aber du bietest hier eine super geile Möglichkeit, den Einstieg zu finden. Danke, danke!
Und für alle, die du auch angemoot hast :
Es gibt hier noch eine schöne ausführliche Anleitung zum Einstieg.
Noch mal tausend Dank und viele Grüße,
Olaf
hb ¶
18. September 2012, 16:04 Uhr
Meinetwegen 'alt', aber immer noch sehr nützlich!
Vielen Dank für die konkreten Beispiele, die haben mir gerade sehr geholfen!