Skate in Mars

Aller au contenu | Aller au menu | Aller à la recherche

jeudi 1 mai 2008

The missing link

Bon, comme cela fait vraiment trop longtemps que je n'ai pas bloggué (même mr_pouit et illovae blogguent plus que moi Oo), il est temps de profiter de cette belle journée pour rester enfermé et sortir un bon petit tas de liens \o/

Mais avant, un petit pardon pour le downtime ce week-end et ce début de semaine, mon alimentation et ma carte mère sont mortes en même temps, et le seul magasin ouvert le lundi qui faisait des prix corrects a trouvé malin de me vendre une alim défectueuse... La bonne chose c'est que j'ai eu l'occasion de tester ubuntu 8.04 sur le eee :-) (quoi, vous l'avez déjà installé sur votre pc principal ? vous êtes fous ?)
  • LA nouvelle c'est bien sur Dotclear 2 en Release Candidate ! On a beau râler, le travail accompli semble bien énorme. http://www.dotclear.net/blog/post/2008/05/01/Dotclear-20-RC1
  • Tant qu'a faire dans les releases : OpenBSD 4.3, le plugin del.icio.us pour FF3, Rails 2.1RC qui bouillonne, sans oublier Netbeans 6.1 que je teste actuellement et qui pourrait presque me faire oublier eclipse (je sais ce que vous allez dire, mais faut bien utiliser son core2duo et ses 4Go de ram de temps en temps :o )
  • Les utilisateurs de la dernière ubuntu ont sûrement remarqué que la zone de texte de message dans pidgin 2.4 n'est plus redimensionnable. Un choix plus que discutable qui a entraîné une bonne flamewar sur un ticket trac ouvert à cette occasion : http://developer.pidgin.im/ticket/4986#comment:272 Un plugin est apparemment tout de même disponible pour restaurer le comportement originel
  • Des trucs sympas et utiles en js : Une interface basée sur prototype pour recadrer une image (exemple d'implémentation rails); un gros tas de libs/scripts plus ou moins biens; et des exemples d'utilisation de mootools (qui roxe, rappelons-le)
Ca suffira pour quelques temps, j'espère ?

mercredi 5 septembre 2007

Chaînage de méthodes en JavaScript

Lorsque l'on code en JavaScript (et dans bien d'autres langages), on se retrouve parfois avec des tartines de code qui utilisent plusieurs méthodes d'un même objet. Par exemple :

document.getElementById("infozone").className = "affiche";
document.getElementById("infozone").innerHTML = "Hello";
document.getElementById("infozone").style.display = "block";
(Exemple fictif, on ne devrait surtout pas utiliser .style.display et .innerHTML)
L'exemple est explicite, on va ajouter la classe affiche, insérer le texte "Hello" (et remplacer le HTML existant) et modifier la propriété CSS display de l'élément "infozone".
Ce genre de code est assez répétitif, mais heureusement les grandes librairies javascript nous permettent de gagner du temps grâce au chaînage de méthodes.
Comme son nom l'indique cela consiste à enchaîner les méhodes sur un même objet.

Pratique


Pour plus de clarté on va voir des exemples avec les bibliothèques Jquery, Mootools et Prototype pour réduire le code utilisé en exemple et le rendre plus propre.

1. Prototype


Inutile de présenter prototype, la bibliothèque utilisée par rails et une des plus mises en avant.
$() est un raccourci vers document.getElementById(), en plus d'étendre l'élément sélectionné en lui ajoutant des méthodes assez utiles (on peut également lui passer un élément html quelconque en argument pour profiter des méthodes étendues de prototype).

$("infozone").addClassName('affiche').update("Hello").show();

Quelques améliorations : addClassName nous permet de conserver les classes deja existantes de l'élément et update permet de nettoyer le html inséré.

2. Mootools


Mootools est une librairie pas tellement connue mais rapide et légère et est assez puissante au niveau des effets que l'on peut utiliser. On peut également choisir de télécharger seulement quelques éléments de la lib pour encore alléger le tout.

$("infozone").addClass("affiche").setText("Hello").setStyle('display', 'block');

La méthode d'ajout d'une classe est plus claire que pour prototype, par contre il n'y a pas de méthodes du genre show() ou hide() (c'est un choix des développeurs qui estiment que setStyle fait son boulot).

3. Jquery


Jquery est une bibliothèque assez à la mode en ce moment et qui a justement popularisé le concept de chaînage de méthodes car il repose essentiellement sur ce concept comme le montre le site et les démos.

$("#infozone").addClass("affiche").text("Hello").show();

La grande différence est visible dans la fonction $ qui contrairement aux autres libs est utilisé avec des sélecteurs (ici on utilise le sélecteur CSS "#" qui identifie l'id d'un élément). On peut également utiliser des sélecteurs CSS3 ou XPath. Prototype et Mootools utilisent tous deux la fonction $$() pour cet usage.
La fonction text est aussi assez différente car elle est utilisée de deux manières : appelée avec un argument elle se comporte comme update() ou setText(), mais si on l'appelle sans argument elle renverra le texte de l'élément (auquel sera retiré les balises HTML).

Comment ca marche ?


Le principe est en fait très simple.
Chacune des méthodes que l'on a vu renvoie l'élément sur lequel elle a été appliquée.
Voici par exemple le code de la méthode Element.hide de prototype :

hide: function(element) {
 $(element).style.display = 'none';
 return element; // <-- la magic touch
},


C'est donc sur cet élément que l'on va appliquer la prochaine méthode de notre chaîne de fonction.

Pour aller plus loin, vous pouvez également lire mon précédent article "
Des sous-menus déroulants non obstrusifs avec Jquery" ou l'on peut voir l'utilisation du chaînage de méthode pour gagner en clarté et en taille dans un script non-obstrusif, en plus de se déplacer dans le DOM :
$(this).parent().parent().children("li").find("ul.montre").slideToggle("").removeClass("montre").addClass("matched");

PS : J'espère que cet article vous aura donné envie d'utiliser une des nombreuses bibliothèques Javascript mises à disposition, sinon, voici 6 raisons pour le faire.

mercredi 6 juin 2007

Des sous-menus déroulants non obstrusifs avec Jquery


Lors de mon stage, j'ai dû réaliser le prototype d'une page d'accueil qui comprenait plusieurs rubriques et sous-menus.
Le nombre d'éléments à présenter étant trop important il fallait cacher les sous-menus et les afficher à la demande.
Le tout devant être non obstrusif j'ai finalement décidé d'utiliser Jquery pour réaliser des menus déroulants.

La solution est ainsi très élégante et ne requiert que peu de Javascript. Le balisage HTML reste également très propre et valide même si on peut encore améliorer ce côté-ci.
Analysons ce dernier :

<div id="menus">
    <div id="enfants">
        <h2>Accueil d'enfants</h2>
        <ul>
            <li id="enfants_da">
                <a href="#">Déficients auditifs</a>
                <ul>
                    <li><a href="#">Centre 1</a></li>
                    <li><a href="#">Centre 2</a></li>
                    <li><a href="#">Centre 3</a></li>
                </ul>
            </li>
            <li>
                <a href="#">Déficients visuels</a>
                <ul id="enfants_dv">
                    <li><a href="#">Centre 1b</a></li>
                    <li><a href="#">Centre 2b</a></li>
                    <li><a href="#">Centre 3b</a></li>
                </ul>
            </li>
        </ul>
    </div>

    <div id="adultes">
    <!-- Même balisage que pour les enfants -->
    </div>
</div>


Par défaut on doit voir uniquement le titre de la rubrique (le <h2>) ainsi que les liens.
Le tout doit également être visible avec un navigateur ayant le javascript désactivé mais utilisant les CSS, on ne va donc pas utiliser directement ceux-ci pour cacher le <ul> des sous-rubriques.

Voici le code javascript qui utilise donc Jquery.

<script type="text/javascript">
    $(document).ready(function(){

    $("#menus div ul ul").hide();
    $("#menus div ul ul ul").show(); //sous-sous-menus

    $("#menus div ul li a").click(function(){
        $(this).parent().parent().children("li").find("ul.montre").slideToggle("").removeClass("montre").addClass("matched");
        $(this).parent().children("ul").not(".matched").addClass("montre").slideToggle("slow");
        $(this).parent().parent().children("li").find("ul.matched").removeClass("matched");
        if ($(this).attr("href") == "#") {
            return false;
        }
    });

    }); //fin onready
</script>

    
Notez que ce code suffit pour _tous_ les menus (les <div id="enfants">, <div id="adultes"> etc).
Le tout est donc assez compact et élégant en plus d'être adaptable facilement.

Commencons par la fonction de base à utiliser : $(document).ready();
Le paramètre à passer à cette fonction est une fonction qui sera appelée lorsque le DOM sera prêt (entre le chargement du HTML et celui des éléments externes tels que les images).
Remarquez si vous ne le saviez pas que Javascript nous permet d'utiliser ici une fonction anonyme : function(){} en paramètre, ce qui évite de créer la fonction ailleurs.

Le code commence donc réellement à l'intérieur de cette fonction.
La première ligne permet de cacher les sous-menus. La fonction $() retourne les éléments Jquery qui correspondent aux sélecteurs demandés en paramètre. On peut utiliser comme ici du CSS mais aussi Xpath par exemple.
Cette fonction est comparable à la fonction $$() de Prototype.
On applique donc ici la méthode hide() à tous ces éléments. Tous les sous-menus seront ainsi cachés (facile non ? :) ).
La deuxième ligne est necesaire pour éviter aux sous-sous-menus (des <ul> dans les <ul> des centres, ici cela peut-être des services internes d'un centre) de rester constamment cachés à cause de la première règle.

Passons donc au coeur de la technique avec la fonction suivante. Ici on applique à tous les liens une méthode qui permet de leur associer une action lors d'un clic (au lieu d'utiliser onclick directement dans le HTML).
Comme pour le $(document).ready(); on passe une fonction anonyme en paramètre qui représentera l'action à effectuer.

La première ligne de cette fonction montre la particularité de Jquery qui est le chaînage des méthodes. Chaque méthode renvoie en effet l'élément sur lequel il agit.
Le $(this) représente ici l'élement sur lequel on greffe l'evènement, c'est donc la balise <a> dans notre cas.
Les deux parent() permettent de remonter dans le DOM : on se retrouve donc à agir sur la balise (on devrait parler de noeud plus exactement) <ul>.
Avec children("li") on peut voir que Jquery va gérer sans problème le fait que l'on se retrouve avec plusieurs éléments.
find() permet ensuite de 'trier' les éléments trouvés, ici un <ul> qui possède la classe montre.
On applique ensuite la méthode slideToggle() qui est celle qui permet d'obtenir l'effet de menu déroulant (voir la démo sur le site de Jquery).
On enlève ensuite la classe "montre" avec une simple méthode.

La deuxième ligne est celle qui va montrer le sous-menu demandé (le <ul> présent dans le même <li> que le lien) et y ajouter la classe montre.
La troisième enlève la classe "matched" à tous les éléments qui la possédaient auparavant.

Un peu d'explications : les éléments montrés se voient ici appliqués la classe "montre" ce qui permet de savoir quels éléments sont affichés ou non.
En effet on souhaite n'afficher qu'un seul sous-menu à la fois, il faut donc cacher les sous-menus déjà montrés (ceux qui possèdent la classe montre).
La classe matched permet d'éviter de cacher puis remontrer directement un sous-menu sur lequel on a cliqué deux fois :
en effet, on peut imaginer que si l'utilisateur clique sur un sous-menu une deuxième fois ce sera pour le cacher.
On trie donc dans la règle d'affichage les éléments matched car on sait que ceux-ci ont déjà été cachés. On enlève ensuite cette classe pour éviter des problèmes à la prochaine utilisation.

Le dernier test permet de renvoyer false si le lien a pour cible '#'. Cela permet de ne pas remonter en haut de la page, mais laisse la possibilité d'utiliser de vrais liens dans le menus (si l'on ne souhaite pas de sous-menus dans une partie précise).

C'est tout ! Je ne propose pas de capture d'écran ou de démo, la page étant pour le moment utilisée uniquement dans l'association ou je réliase le stage, mais voici le css que j'utilise :

#menus {
margin-left: 20px;
overflow-y: auto;
overflow-x: hidden;
font-size: 14px;
font-family: Verdana, sans-serif;
font-weight: bold;
color: #456b90;
height: 700px;
}
#menus a {
text-decoration: none;
}
#menus div {
position: absolute;
margin-top: 10px;
}
#menus div ul {
width: 150px;
margin-top: 0px;
margin-left: 0;
padding-left: 20px;
background-color: #FFFFFF;
}
#menus div h2 {
font-size: 19px;
font-family: "Trebuchet MS", sans-serif;
margin-bottom: 7px;
}
#menus div ul li p {
margin: 1px;
padding: 4px;
}
#menus div ul li ul {
background-color: #75b9e4;
padding: 4px;
font-size: 12px;
font-weight: normal;
list-style-type: none;
margin: 0;
}

#enfants {
left: 700px;
top: 30px;
}
#enfants h2 {
color: #6be32f;
}


Chaque sous-partie (enfants, adultes) est positionnée de manière absolue dans la page avec left et top.

On peut donc conclure en affirmant sans problèmes que Jquery permet de réaliser plusieurs effets graphiques dans la page, de manière assez simple et surtout en restant accessible et non obstrusif :)

J'ai peu parlé de Jquery, on aurait pourtant pu dire que la lib est légère (une version compréssée étant de plus disponible), rapide, bref un bon candidat au remplacement de Prototype. Voici quelques liens comme d'habitude :)