Pour mon premier article sur ce blog, j'ai choisi de présenter MooTools, un framework Javascript open source
orienté objet distribué sous licence MIT.
Après une rapide présentation des bases, je montrerai, grâce à quatre courts
exemples, quelques unes des possibilités de MooTools, en espérant vous donner
l'envie d'aller plus loin par vous-mêmes.
Récupération de la librairie MooTools
La version actuelle est la 1.2.4, le core est disponible sur le site officiel en
version compressée (par YUI ou JSMin) et non compressée.
Il est également possible de définir sa propre version de MooTools en
choisissant les modules à intégrer au moment du téléchargement, ce qui permet
d'en optimiser la taille au maximum.
Les plugins officiels sont disponibles ici.
La classe Element
Element est la classe de base de MooTools, c'est par elle que l'on doit
passer pour créer ou récupérer un noeud DOM.
Des getters et setters permettent de manipuler les attributs des noeuds, les
styles et les événements :
var myButton = new Element('button');
myButton.set('text', 'Je suis un bouton');
Ci-dessous, un exemple de création d'un bouton plus complet utilisant la
syntaxe JSON :
var myOtherButton = new Element('button', {
'class': 'BigButton',
'html': 'Je suis un très gros bouton',
'styles': { 'font-size': '14px', 'font-weight': 'bold' },
'events': {
'click': function(){ alert('Click'); },
'mouseover': function(){ alert('Mouseover'); }
}
});
Le parcours de l'arborescence
La fonction $ permet de récupérer un Element unique :
var buttonOK = $('btnOK'); // retourne l'Element ayant l'ID 'btnOK';
La fonction $$ permet de récupérer une collection d'Element :
var forms = $$('form'); // retourne tous les formulaires
var inputsWithValue = $$('input[value]'); // retourne tous les inputs ayant l'attribut 'value'
var gifImages = $$('img[src$=.gif]'); // retourne toutes les images ayant l'extension '.gif'
var buttons = $$('button', 'input[type=button]'); // retourne tous les boutons et les inputs de type bouton
var bigInputs = $$('#form input.BigButton'); // retourne tous les inputs de classe 'BigButton' appartenant à l'élément ayant l'ID 'form'
A noter qu'il est possible de travailler directement à partir des noeuds
DOM :
var buttonOK = $(document.getElementById('btnOK'));
var inputs = $$(document.getElementsByTagName('input'))
Pour les recherches qui doivent s'effectuer à partir d'un élément précis, il
existe les fonctions getElement() et getElements() :
var loginForm = $('loginForm');
var loginInputs = loginForm.getElements('input');
Exemple 1 : création d'un bouton qui change le style de la
page
Nous allons commencer par créer un bouton en HTML, avec un identifiant afin
de le retrouver plus facilement.
Le code Javascript se résumera à l'ajout de l'évènement 'click' sur ce bouton
et à la création de la fonction à appeler.
Cette dernière se contente ici de modifier la couleur du body et de la police,
et d'ajouter un padding-left à tous les paragraphes.
Code HTML :
<button id="btnStyle">Changer le style</button>
Code Javascript :
window.addEvent('domready', function() {
$('btnStyle').addEvent('click', changeStyle);
}
var changeStyle = function() {
$(document.body).setStyles({ 'background-color': '#000000', 'color': '#ffffff' });
$$('p').each(function(p) {
p.setStyle('padding-left', '20px');
});
}
Les évènements
L'évènement 'domready' permet de lancer l'exécution d'une fonction lorsque
le DOM est prêt, c'est-à-dire lorsque l'arborescence est prête à être lue et
écrite.
La différence avec 'onload' est que la vérification ne se fait que sur le DOM
et non sur les ressources annexes telles que CSS, images... etc...
window.addEvent('domready', function() {
alert('Traitement...');
});
Les autres évènements sont les évènements Javascript traditionnels :
- boutons de la souris (click, dblclick, mouseup, mousedown, contextmenu,
mousewheel, ...)
- mouvements de la souris (mousemove, mouseover, mouseout, ...)
- clavier (keypress, keydown, keyup, ...)
- fenêtre (load, unload, beforeunload, resize, move, ...)
- éléments (focus, blur, change, reset, ...)
Il est possible de créer un évènement personnalisé grâce à table
Element.Events, puis de l'appeler comme un autre évènement.
Exemple 2 : création d'un évènement pour gérer le déplacement
d'un conteneur
La première étape consiste à créer un container en position absolute et de
lui donner un identifiant pour nous permettre de le récupérer rapidement.
A l'intérieur nous mettons une image, un avion qui va se déplacer lorsqu'on
appuie sur la flèche de droite ou sur la touche D.
Puis, nous créons l'évènement, en lui fournissant un évènement de base,
keydown, et une fonction précisant les conditions pour que l'évènement soit
lancé.
Code HTML :
<div id="plane" style="position: absolute"><img src="avion.png"/></div>
Code Javascript :
Element.Events.planemove = {
'base': 'keydown',
'condition': function(event) {
return event.key == "d" || event.key == "right";
}
};
$(document).addEvent('planemove', function(event) {
var image = $('plane');
var pos = image.getPosition();
pos.x++;
image.setPosition({ 'x': pos.x, 'y': pos.y });
});
Les classes
MooTools permet de créer ses propres classes.
L'héritage se définit par Extends et Implements, le premier permettant de
redéfinir les variables et fonctions de la classe mère mais pas le
second.
Le constructeur correspond à la fonction initialize.
Exemple 3 : création d'une classe Square pour dessiner des
carrés sur la page
Afin de présenter l'héritage, commençons par créer une classe Shape.
Celle-ci ne définit qu'un constructeur, contenant les coordonnées du point
d'origine de la forme à dessiner.
Puis nous créons la classe Square, qui hérite de Shape, et qui possède une
largeur.
La fonction draw() nous permet de dessiner le carré dans le body, en utilisant
un div correspondant aux positions et dimensions.
var Shape = new Class({
'initialize': function(options) {
this.x = options.x;
this.y = options.y;
}
});
var Square = new Class({
'Extends': Shape,
'initialize': function(options) {
this.parent(options)
this.width = options.width;
},
'draw': function() {
if (this.width) {
var element = new Element('div', {
'text': 'Carré',
'styles': {
'position': 'absolute',
'top': this.x,
'left': this.y,
'height': this.width,
'width': this.width,
'background-color': '#AA0000'
}
}).inject(document.body);
}
return this;
}
});
var square = new Square({ 'x': 300, 'y': 30, 'width': 100 });
square.draw();
Les effets
La librairie utilisée est MooFX, disponible également pour Prototype.
Les effets utilisent des transitions, une transition pouvant être linéaire,
cubique, élastique... etc...
Les effets présents dans le Core sont Tween et Morph, le premier permet
d'appliquer une transition sur une valeur CSS, et le second de le faire sur
plusieurs.
Exemple 4 : création d'un menu simple qui apparait lorsqu'on
clique sur un bouton
Attention, cet exemple requiert un plugin disponible sur le site
officiel, Fx.Slide.
Le menu ci-dessous se compose d'une liste de liens affichés en colonne, et
masqués (barre de menu).
Ils apparaissent et disparaissent lorsqu'on clique sur un bouton (flèche), avec
un effet de glissement.
Remarque : le style (couleurs, images, marges...) doit être codé en CSS et
donc ne se trouve pas ci-dessous.
// Menus à afficher
var menuLabels = [['Menu 1', 'http://mootools.net'],
['Menu 2', 'http://www.sfeir.com'],
['Menu 3', 'http://www.google.fr']];
// Barre de menu
var menuBar;
// Classe créée pour la barre de menu
var MenuBar = new Class({
'initialize': function(items) {
// Menus à afficher
this.items = items;
// Element de l'arborescence
this.rootElement = new Element('div');
if (this.items) {
var l = this.items.length;
for (var i = 0; i < l; i++) {
var a = new Element('a', {
'text': this.items[i][0],
'class': 'Menu',
'href': this.items[i][1],
'events': {
// Petit effet de rollover
'mouseover': function() { this.set('class', 'MenuOver'); },
'mouseleave': function() { this.set('class', 'Menu'); }
}
}).inject(this.rootElement);
}
}
},
// Fonction permettant d'ajouter la barre de menu à un élément parent
// Le slide hide permet de la masquer instantanément au démarrage
'appendTo': function(parentElement) {
this.rootElement.inject(parentElement).slide('hide');
},
// Ouverture de la barre : on fait apparaître les liens avec la transition Bounce
'open': function() {
this.rootElement.set('slide', {duration: 'long', transition: 'bounce:out'}).slide('in');
},
// Fermeture de la barre : on fait disparaître les liens avec la transition Pow
'close': function() {
this.rootElement.set('slide', {duration: 'long', transition: 'pow:out'}).slide('out');
}
});
// Bouton pour ouvrir le menu
var opacity = 0.4;
var openArrow = new Element('div', {
'html': '▼',
'class': 'Arrow',
'styles': { 'opacity': opacity },
'events': {
'mouseover': function() {
this.setStyle('text-decoration', 'underline');
this.fade(1);
},
'mouseleave': function() {
this.setStyle('text-decoration', 'none');
this.fade(opacity);
},
'click': function() {
openMenu();
}
}
});
// Bouton pour fermer le menu
var closeArrow = new Element('div', {
'html': '▲',
'class': 'Arrow',
'events': {
'click': function() { closeMenu(); }
}
});
// Fonction d'ouverture du menu : on change de flèche et on ouvre la barre de menus
function openMenu() {
closeArrow.replaces(openArrow);
menuBar.open();
}
// Fonction de fermeture du menu : on change de flèche et on ferme la barre de menus
function closeMenu() {
openArrow.replaces(closeArrow);
menuBar.close();
}
window.addEvent('domready', function() {
// Création d'un wrapper en position absolute
var menuWrapper = new Element('div', {
'styles': { 'position': 'absolute', 'width': '100%', 'top': '0px', 'left': '0px', 'text-align': 'center' }
});
menuWrapper.inject($(document.body));
// Création de la barre de menu
menuBar = new MenuBar(menuLabels);
menuBar.appendTo(menuWrapper);
// Ajout du bouton d'ouverture
openArrow.inject(menuWrapper);
}
Conclusion
Cet article a présenté les bases de MooTools, c'est-à-dire comment manipuler
les éléments, créer des classes et des événements.
Le framework contient d'autres outils, par exemple pour gérer les cookies, les
requêtes au format XML, HTML et JSON.
La spécificité de MooTools est qu'il dispose d'un ensemble de classes qui en
fait quasiment un langage de programmation complet.
Là où avec jQuery par exemple, la création d'un élément se résume à une copie
de code HTML, MooTools utilise une syntaxe plus naturelle au programmeur objet,
plus structurée et plus simple à maintenir.
La contrepartie est la nécessité de connaître un minimum Javascript et la
programmation objet, ce qui peut rebuter ceux qui ne se sentent pas
particulièrement à l'aise et qui souhaitent simplement avoir rapidement du code
qui tourne.
De plus, MooTools possède une communauté moins importante que ses
concurrents les plus célèbres, les principaux inconvénients étant les plugins
moins nombreux, et le fait qu'on peut avoir un peu plus de difficulté à trouver
des réponses à ses questions lorsqu'on se trouve face à un problème.