Yannick Croissant - Blog

Mootools Forge

Les développeurs de Mootools ont enfin ouvert la forge, un annuaire regroupant les plugins pour le framework.

Chaque développeur peut y créer son compte et y ajouter ses plugins, mais pour cela il faut que ces derniers soient obligatoirement hébergés sur GitHub, ce qui est assez contraignant pour ceux qui, comme moi, ne sont pas habitués à Git1. Mais une fois cela fait l'ajout de son plugin à la forge se fait en 1 clic2.

J'ai commencé à ajouter les miens3, vous pouvez pour l'instant y retrouver ShapeHover et String.toDOM (que j'avais présenté dans ce billet ). J'en ai encore 2 ou 3 à ajouter, il me faut encore faire du ménage dans le code, faire la doc et les exemples, c'est que ça prend du temps ces trucs…

Voila, donc la prochaine fois que vous aurez besoin de plugins pour votre projet utilisant Mootools, vous saurez où chercher (déjà plus de 70 plugins référencés !).


  1. Mais c'est l'occasion ou jamais de s'y mettre ;)  

  2. N'oubliez pas de lire le guide avant d'ajouter votre plugin.  

  3. Voir mon profil sur la forge  

Tuez les tous

Hop, cette semaine est sortit Tuezlestous.com sur lequel j'ai bossé comme intégrateur.

Tuezlestous.com

Pour faire simple : c'est un site qui parle de zombies

Vous pouvez y retrouver des news sur tous les sujets touchants aux zombies (films, bds, livres, jeux vidéos, etc.), des articles et un forum.

Voila, je vous encourage à aller découvrir tout ça :)

Quelques nouvelles

Allo allo, ça marche toujours ce truc ? Ha, on dirait que oui.

Donc contrairement aux apparences ce blog n'est pas mort, j'ai juste eu une période avec beaucoup de boulot et vous savez ce que c'est : plus le temps passe et plus c'est dur de s'y remettre.

Donc en attendant un vrai article avec des morceaux intéressants dedans voici un petit récapitulatif :

  • Lancement de la nouvelle version du site de l'Olympique Lyonnais fin avril.
  • Refonte graphique du site de l'Olympique de Marseille début août.
  • Victoire ! On a laissé tomber la compatibilité IE6 sur la refonte du side de l'OM. Die IE6 Die !
  • J'aurais quelques plugins Mootools potentiellement intéressants à publier, il me reste un peu de nettoyage et de la doc à faire.
  • Je vais (enfin) abandonner Wordpress pour ce blog, et passer sur un blog sous Django. J'espère pouvoir le lancer dans "pas trop longtemps" (faut surtout que je me motive pour le terminer).
  • Je participe à un nouveau projet sur mon temps libre, je vous en reparlerai à son lancement ;)
  • Comme chaque année, je serai à Paris Web du 8 au 10 octobre. L'Événement à ne rater sous aucun prétexte !

Voila voila, et vous ça va ?

Live Events pour Moootools

Mootools implémente maintenant cette fonctionnalité dans More depuis la version 1.2.3.1 : Element.Delegation. Utilisez donc plutôt le code ci-dessous si votre projet utilise une version plus ancienne de Mootools.

Il n'y a pas que Mootools dans la vie, il y a aussi JQuery. Et lui aussi a des trucs sympa qui sont malheureusement absents (pour l'instant) de Mootools. Par exemple sa version 1.3 a introduit les Live Events qui peuvent grandement faciliter la gestion des événements dans vos pages. Je l'ai donc adapté pour Mootools 1.2

Explication

Pour commencer, qu'est qu'ils appellent un "live event" exactement ? Hé bien il s'agit d'un événement que vous assignez une seule fois dans votre page et qui est propagé à tous les éléments qui correspondent au sélecteur que vous avez indiqué, même si vous ajoutez d'autres éléments de ce type.

Concrètement : Vous avez dans votre page un lien :

<a class="event" href="#">My link</a>

Si j'assigne un événement à ce lien par la manière classique :

document.getElement('a.event').addEvent('click', function(e){
    alert('Alert');
});

Et si dans le futur j'en ajoute un second identique ou que je le supprime puis que je le recrée alors les nouveaux liens n'auront pas d'événement associés.

Hors avec les Live Events je peux assigner un événement à tous les liens qui ont la class "event" :

$(document.body).addLiveEvent('click', 'a.event', function(e){
    alert('Alert');
});

Peu importe les manipulations que je fais dessus plus tard dans ma page, les événements y resteront associés (à condition bien sûr qu'ils correspondent toujours au sélecteur (ici "a.event").

En fait, pour réussir cette performance, l'événement n'est associé qu'une fois au parent des éléments ciblés, ici body, et lors d'un click sur l'un de ses enfants, si celui-ci correspond au sélecteur, l'événement est exécuté (on appel ça la délégation d'événement).

Un des avantages, outre le fait de pouvoir ajouter/supprimer des éléments, est de n'avoir qu'un seul événement pour tous vos éléments similaires, ce qui peut potentiellement être un gain conséquent de performance et de mémoire dans votre application.

Code source de addLiveEvent

/*
 * Attach an event to an element and use bubbling to fire the event on the childs who match a CSS selector
 * 
 * Usage : parentElement.addLiveEvent(event, selector, function)
 * 
 * parentElement - The parent to bind
 * event - The event name to monitor ('click', 'mouseover', etc) without the prefix 'on'
 * selector - The CSS Selector the childs need to match
 * function - The function to execute
 * 
 * Example :
 * $(document.body).addLiveEvent('click', 'a', function(e){ alert('Alert'); });
 * 
 */
Element.implement({
    addLiveEvent: function(event, selector, fn){
        this.addEvent(event, function(e){
            var t = $(e.target);
            if (!t.match(selector)) return false;
            fn.apply(t, [e]);
        }.bindWithEvent(this, selector, fn));
    }
});

(oui, le commentaire est plus long que le code...)

Démo en ligne

Live Events for Mootools (demo)

Convertir une chaine de caractère en noeuds DOM

Plus je fais de javascript "lourd" plus j'ai besoin de générer du code HTML via mes scripts. Au début j'utilisais les méthodes du DOM (createElement, appendChild, etc.) mais dès qu'on a une structure HTML un peu compliquée ça devient vraiment le bordel (et ce même avec un framework). Et je ne vous raconte même pas l'horreur pour la maintenance après...

Il restait la solution du bon vieux innerHTML, non standard mais qui marche très bien et est très rapide. Mais ça ne convenait pas vraiment si je voulait insérer mon bout de code après un élément précis, ajouter des événements sur une portion précise de ce code etc.

Donc je me suis fait une petite méthode String.toDOM() qui permet de convertir une chaine de caractère en noeuds DOM.

Voici la version en pure javascript :

String.prototype.toDOM = function(){
    // Define the wrapper and his level
    var wrapper = ['', ''], level = 0;
    if (new RegExp('^&lt;thead|^<tfoot|^<tbody').test(this)) wrapper = ['<table>', '</table>'], level = 1;
    else if (new RegExp('^<tr').test(this)) wrapper = ['<table><tbody>', '</tbody></table>'], level = 2;
    else if (new RegExp('^<th|^<td').test(this)) wrapper = ['<table><tbody><tr>', '</tr></tbody></table>'], level = 3;
    else if (new RegExp('^<li').test(this)) wrapper = ['<ul>', '</ul>'], level = 1;
    else if (new RegExp('^<dt|^<dd').test(this)) wrapper = ['<dl>', '</dl>'], level = 1;

    // Convert the string into DOM nodes (keeping text nodes)
    var html = document.createElement('div');
    html.innerHTML = wrapper[0] + this + wrapper[1];
    html = html.childNodes;

    // Strip the wrapper
    for (;level > 0; level--) html = html[0].childNodes;

    return html;
}

    // Example :
    var code = '<p>Lien vers mon <a href="http://dev.k1der.net">Blog</a></p>'.toDOM(); // Return a NodeList with the DOM nodes , code[0] is the <p>
    alert(code[0].getElementsByTagName('a')[0].getAttribute('href')); // alert "http://dev.k1der.net"

Et celle si vous utilisez Mootools :

String.implement({
    toDOM: function(){
        // Define the wrapper and his level
        var wrapper = ['', ''], level = 0;
        if (this.test('^<thead|^<tfoot|^<tbody')) wrapper = ['<table>', '</table>'], level = 1;
        else if (this.test('^<tr')) wrapper = ['<table><tbody>', '</tbody></table>'], level = 2;
        else if (this.test('^<th|^<td')) wrapper = ['<table><tbody><tr>', '</tr></tbody></table>'], level = 3;
        else if (this.test('^<li')) wrapper = ['<ul>', '</ul>'], level = 1;
        else if (this.test('^<dt|^<dd')) wrapper = ['<dl>', '</dl>'], level = 1;

        // Convert the string into DOM nodes (keeping text nodes)
        var html = new Element('div', {html: wrapper[0] + this + wrapper[1]}).childNodes;

        // Strip the wrapper
        for (;level > 0; level--) html = html[0].childNodes;

        // Extend the elements for IE
        if (Browser.Engine.trident) for (var i = 0, l = html.length; i < l; i++) $(html[i]);

        return $A(html);
    }
});

// Example :
var code = '<p>Lien vers mon <a href="http://dev.k1der.net">Blog</a></p>'.toDOM(); // Return a NodeList with the DOM nodes , code[0] is the <p>
alert(code[0].getElement('a').get('href')); // alert "http://dev.k1der.net"

Le principe est simple, on injecte la chaine dans un <div> puis on récupère tous les enfants de cet élément. C'est tout bête, c'est innerHTML qui fait tout le boulot.

Il faut bien sûr avoir un code valide dans votre chaine de départ, sinon vous risquez d'avoir des surprises suivant les navigateurs (d'où les wrappers pour ne pas ajouter directement un <td> dans un <div>).

Combinez cette méthode avec String.substitute de Mootools et vous obtenez un système basique et léger de template pour vos scripts javascript :

'<h1><a href="{link}">{text}</a></h1>'.substitute({
    link: "http://dev.k1der.net",
    text: "Blog"
}).toDOM()[0].inject(document.body, 'top'); // Inject <h1><a href="http://dev.k1der.net">Blog</a></h1> at the top of the body

Pratique non ?

Conventions de codage (x)HTML et CSS

Il y a quelque temps j'avais fais un post Organiser ses CSS. Depuis, j'ai mis au propre la documentation des conventions que j'utilise pour mon boulot.

Ce n'est encore que des documents de travail alors il manque sûrement plein de choses et il y en a sans doutes d'autres qui ne sont pas très claires, n'hésitez pas à me le signaler.

Tags :

Performances : Le cas des publicités

Tout intégrateur aura tôt ou tard à faire à un script de pub, ces bouts de javascript qui viennent faire un gros document.write() au milieu de votre belle page codée avec amour. Oui, c'est dur, mais vous êtes bien souvent obligé de le mettre...

Alors bien sûr vous pouvez tout de suite renoncer à avoir une bonne note avec YSlow, mais n'abandonnez pas pour autant, on va essayer de limiter les dégâts.

Comme conseillé dans les bonnes pratiques, il faut essayer de mettre les scripts de pub en bas de page. Pas toujours simple, parfois il faut tricher un peu pour y arriver.

Généralement ce genre de script se présente de cette façon :

<script type="text/javascript"><!--
    document.write('<scr'+'ipt type="text/javascript" src="http://ads.server.com/ads.js"></scri'+'pt>');
//--></script>

Ce script va généralement lui même faire un document.write() d'un autre script qui lui même fera un autre document.write() de la publicité (et avec un peu de chance, aucun de ces 3 éléments ne seront hébergés sur le même domaine). Oui, bonjour le bordel juste pour afficher une pub.

Voila, ça c'est notre ennemi, maintenant comment obtenir ce que l'on veut sans sacrifier les performances ?

===Le positionnement en CSS===

Suivant les pubs, il est parfois possible de les positionner en absolue dans la page via CSS.

L'idée est de placer nos scripts de pub dans des conteneurs en fin de page puis de positionner nos conteneurs en CSS.

[...]
        <div id="ads-megabanner"><!-- Script de pub --></div>
        <div id="ads-skyscrapper"><!-- Script de pub --></div>
    </body>
</html>

Et le CSS :

#ads-megabanner { left: 10px; position:absolute; top:10px; }
#ads-skyscrapper { position:absolute; right:10px; top:10px; }

De cette façon nos 2 pubs seront placées en haut de la page. Simple et efficace.

===Le déplacement dans le DOM===

Il y a des cas où le positionnement en absolue n'est pas possible, dans ce cas il existe une technique un peu plus tordue mais tout aussi efficace. Il s'agit d'exécuter le script de pub en bas de page puis de déplacer le code généré à l'endroit approprié dans la page.

Pour cela il me faut un conteneur à l'endroit où je souhaite faire apparaitre ma pub.

[...]
<div id="ads-container"></div>
[...]

Ma pub, quand à elle, est placée en bas de page, comme dans l'exemple précédent. A ceci pret qu'elle est suivie d'un bout de script qui va la déplacer dans mon conteneur :

[...]
        <div id="ads-carre"><!-- Script de pub --></div>
        <script type="text/javascript">document.getElementById('ads-container').appendChild(document.getElementById('ads-carre'));</script>
    </body>
</html>

J'obtiens alors comme résultat :

[...]
<div id="ads-container">
    <div id="ads-carre"><!-- Script de pub --></div>
</div>
[...]

Pour éviter un mauvais affichage si le script est vraiment lent à charger, on peut appliquer un CSS afin de la masquer avant le déplacement :

#ads-carre { display:none; }
#ads-container #ads-carre { display:block; }

Voila, au final nos publicités ne bloquent plus le chargement et sont bien placées dans la page.

Page d'exemple pour l'intégration des pubs

Quelques petits conseils pour finir :

  • Placez vos javascripts juste avant les scripts de pubs, sinon ils seront bloqués jusqu'à ce ces derniers ne chargent complètement.
  • N'utilisez pas de fonctions avec des noms génériques dans vos pages, préfixez-les si possible. Parfois les pubs insèrent leurs propres fonctions, qui peuvent écraser les vôtres. J'ai vu des setCookies(), readCookies() ou encore popup() (manque de pot, j'avais déjà une fonction popup() sur le site, du coup plus aucune ne marchait).
  • Testez ces techniques avant des les appliquer sur votre site. Je n'ai rencontré aucun problème avec mes régies pub et il n'y a pas de raison qu'il y en ai, mais les scripts de pub sont tellement tordus...
Tags :

Paris Web 2008

Me voila de retour de Paris Web 2008 et je dois dire que c'est encore une édition réussie pour ce rendez-vous incontournable pour tous les professionnels du web français.

C'est déjà la 3ème édition et c'est toujours du bonheur : des conférences toutes plus intéressantes les unes que les autres, des rencontres avec des gens super intéressants et bien sûr une superbe ambiance.

[caption id="" align="aligncenter" width="240" caption="Paris Web 2008 par Oncle Tom"]Paris Web 2008 par Oncle Tom[/caption]

Si le jeudi était déjà très bien (bien que je n'ai pas du tout accroché à la dernière conférence), le vendredi était quand à lui vraiment exceptionnel ! Avoir une table ronde avec des personnes de chaque principal navigateur du marché est quand même un tour de force. Et, si on en crois la loooongue liste de questions qui leur était posées, tout le monde est vraiment préoccupé des futures évolutions des navigateurs (en particulier d'IE, qui essaye tant bien que mal de réparer les dégâts).

[caption id="" align="aligncenter" width="240" caption="La table ronde navigateur par lejoe"]La table ronde navigateur par lejoe[/caption]

Par contre j'ai été un peu déçu d'une partie des ateliers auxquels j'ai assisté. J'ai trouvé l'atelier "Cascade et héritage" trop simple, la première partie sur l'héritage m'a endormi tandis que la seconde sur l'organisation était plus intéressante mais aurait mérité d'être beaucoup plus approfondie. Ensuite je n'ai pas du tout aimé l'atelier "Validation avancée des formulaires " où on nous a juste décrit ligne par ligne un script de validation (révision du DOM en somme). Sinon j'ai beaucoup aimé les ateliers "Enrichissement progressif" et "Firebug, Web Inspector" (bien que ce dernier outil ne soit pas encore tout à fait au point, c'est très prometteur).

Bref, j'ai encore une fois appris (et révisé) beaucoup de choses. Et maintenant que je suis retourné au boulot, voici la phase là plus difficile : la mise en pratique. J'ai quelques projets qui doivent arriver sous peu et j'espère pouvoir faire quelques trucs sympa dessus.

Vous pouvez retrouver les photos dans le groupe flickr Paris Web 2008 et les présentations sur Slideshare (elle arrivent petit à petit).

Encore bravo à toute l'équipe de Paris Web, ils ont fait un travail vraiment formidable. J'ai déjà hâte à l'année prochaine :)

Left 4 Dead

Left 4 Dead

Comme prévu la démo de Left 4 Dead est disponible depuis hier pour tous ceux qui ont pré-commandé le jeu. Et comme prévu, ça déchire tout.

Dans la démo on a accès à la moitié de la campagne "No mercy" (sur 4 campagnes en tout), c'est à dire à 2 niveaux complets. Le principe des niveaux est simple : aller du point A au point B, sans mourir entre temps.

On est plutôt bien équipé en début de niveau : trousse de soin, arme (fusil à pompe ou mitraillette) et toutes les munitions que l'on peut transporter (un sacré paquet, n'ayez pas peur de gaspiller). On a en plus un pistolet (munitions infinies) et on peut en ramasser un deuxième plus tard dans le niveau.

Bill - Left 4 Dead

Sinon à première vue le jeu à une très bonne rejouabilité, grâce au principe du Director chaque partie est différente : les vagues de zombies, les bosses, les items changent à chaque partie et s'adaptent en fonction de votre style de jeu, de votre vie, de vos munitions, etc. Impossible de savoir quand est-ce qu'une vague de zombies va vous arriver sur le coin de la gueule, donc vous êtes constamment vigilant et sous pression.

Le coop. apporte vraiment au gameplay et c'est le pur bonheur d'y jouer avec des potes. Prévoyez le casque+micro, ça aide et ça y rajoute vraiment de l'ambiance quand tout le monde crie parce qu'une énorme vague de zombies vous arrive dessus :). On nous pousse vraiment à coopérer (soins, alerte lorsqu'un d'entre vous est à terre, avertissement au groupe si on trouve une arme ou une trousse de soins, etc.). Et croyez moi, vous n'avez vraiment pas envi qu'un de vos potes ne meurt, parce qu'après, généralement, votre tour vient rapidement...

Louis - Left 4 Dead

Bon, si vous ne jouez pas avec des bras cassés choisissez directement la difficulté Advanced et pour du vrai chalenge passez en Expert (notre groupe a bloqué au boss de fin en Expert :'( ).

Bon tout n'est pas encore rose, actuellement le système de serveur est très bizarre, pas moyen de choisir celui que l'on veut (console style), le jeu nous en choisi un automatiquement (et souvent ça lag à mort) ou alors on rejoint une partie avec des amis (c'est encore le plus simple). Hier soir c'était vraiment la galère pour jouer, alors une fois que l'on trouvait un bon serveur on ne le lâchait plus ! (apparemment ils ont patché des trucs ce matin mais je n'ai pas encore eu le temps de tester). Mais mis à part ce "petit" problème, rien à signaler.

Le jeu est très fluide, d'après certains il bouffe même moins en ressources que TF2 ;) Et on peut avoir vraiment beaucoup de zombies à l'écran, Left4Dead411.com a testé jusqu'à 1200 zombies simultanément !

Tout ça plus l'ambiance survival horror, ça va être à coup sûr un énorme succès en LAN !

Vivement ce soir que je j'y retourne :)

Quelques liens bonus :

PS: C'est moi où ils ont utilisé un indicateur d'Ajaxload (Big Circle Ball) pour l'indicateur de chargement ? Dommage : c'est moche...

Quel type de développeur suis-je ?

Petit aperçu (ironique) des différents types de développeurs.

Évidement je ne rentre dans aucun groupe (ça serait trop facile), je pense que je me situe à peu prêt entre le pragmatique et le ninja(1), avec un petit côté libriste aussi.

  • Os : Windows XP(2) / Ubuntu
  • Éditeur : Aptana
  • Langages favoris : PHP, xHTML, CSS, Javascript(3)
  • VCS : Subversion(4)
  • Navigateur : Firefox

Et vous ?

  1. Vive les claviers ergonomiques ! Et faudrai que je trouve le temps de me mettre à Dvorak ;)
  2. Et oui, je reste un joueur malgré tout.
  3. Je suis dev font-end, ça se voit tant que ça ?
  4. Intéressé par Git, mais ça manque encore de client desktop potable.

Projets

Les petits logiciels ci-dessous sont des choses que j'ai réalisé pour des besoins personnels et que je balance ici car ça peut (éventuellement) être utile à d'autres personnes et que c'est toujours mieux que de les laisser prendre la poussière sur mon disque dur. N'espérez pas y trouver des trucs super aboutis avec un support à toute épreuve. Ils sont livrés tel quel avec la seule garantie du "Chez moi ça marche". Les sources sont fournies et je vous encourage donc de faire joujou avec ;) Dernière chose, ils sont tous sous licence MIT.

Small

Un petit moteur de blog minimaliste réalisé en 2005 : stockage des billets dans des fichiers texte, flux rss, options de mise en forme minimale et possibilité de joindre un fichier à un billet. C'est tout, mais ça suffit à certains :)

Télécharger Small (1.0)

Démo : Blog | Admin (admin/admin)

(ça manque un peu de documentation, si ça intéresse des gens il se pourrait que je m'y remette)

Compressor

Un petit utilitaire qui permet de fusionner plusieurs fichiers Javascript puis de les compresser avec YUI Compressor. Celui-ci a été réalisé avec AutoIt.

Télécharger Compressor (1.0.1)

GetText

Un petit utilitaire qui permet de parcourir vos templates à la recherche des chaines à traduire. Celui-ci a été réalisé avec AutoIt.

Télécharger GetText (1.0.1)

Summarize

Un petit utilitaire qui permet de réaliser un sommaire de l'arborescence de vos fichiers CSS à partir de vos commentaires. Celui-ci a été réalisé avec AutoIt.

Télécharger Summarize (1.0.1)

Summarize

Un petit utilitaire qui permet de réaliser un sommaire de l'arborescence de vos fichiers CSS à partir de vos commentaires

GetText

Un petit utilitaire qui permet de parcourir vos templates à la recherche des chaines à traduire.

Compressor

Un petit utilitaire qui permet de fusionner plusieurs fichiers javascript puis de les compresser avec YUI Compressor

Small

Moteur de blog minimaliste