<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:wfw="http://wellformedweb.org/CommentAPI/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
	xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
	>
<channel>
	<title>La Case de l&#039;Oncle Tom &#187; code</title>
	<atom:link href="http://case.oncle-tom.net/tag/code/feed/" rel="self" type="application/rss+xml" />
	<link>http://case.oncle-tom.net</link>
	<description>Développement Web, bonnes pratiques et performances</description>
	<lastBuildDate>Sun, 25 Dec 2011 19:33:29 +0000</lastBuildDate>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
	<generator>http://wordpress.org/?v=3.3.1</generator>
<atom:link rel="search"
           href="http://case.oncle-tom.net/opensearch"
           type="application/opensearchdescription+xml"
           title="Content Search" />		<item>
		<title>2011 : l&#8217;année du #fail personnel</title>
		<link>http://case.oncle-tom.net/2011/annee-du-fail-personnel/</link>
		<comments>http://case.oncle-tom.net/2011/annee-du-fail-personnel/#comments</comments>
		<pubDate>Wed, 21 Dec 2011 17:49:29 +0000</pubDate>
		<dc:creator>Oncle Tom</dc:creator>
				<category><![CDATA[Entrepreneuriat]]></category>
		<category><![CDATA[Personnel]]></category>
		<category><![CDATA[choix]]></category>
		<category><![CDATA[code]]></category>
		<category><![CDATA[freelance]]></category>
		<category><![CDATA[indépendant]]></category>
		<category><![CDATA[partage]]></category>
		<category><![CDATA[photos]]></category>
		<category><![CDATA[professionnel]]></category>
		<category><![CDATA[projet]]></category>
		<category><![CDATA[réflexion]]></category>
		<category><![CDATA[web]]></category>
		<guid isPermaLink="false">http://case.oncle-tom.net/?p=18470</guid>
		<description><![CDATA[Progresser par l'échec ? C'est un peu la conclusion d'une année teintée de conflits et d'un climat environnant tourné vers la perte et la destruction.]]></description>
			<content:encoded><![CDATA[<p>Après un éclat de rire, détendu, je lâche à un ami &laquo;&nbsp;on s&#8217;est bien vautré cette année quand même&nbsp;&raquo;. Cette réflexion m&#8217;est venue lors d&#8217;une soirée, alors que j&#8217;observais l&#8217;apparente tranquilité des convives. Cet ami me répond : &laquo;&nbsp;tu sais, c&#8217;est le cas de tout le monde dans cette pièce&nbsp;&raquo;.</p>
<p>Et de continuer à savourer de plus belle les discussions et autres flacons présents sur la table de banquet.</p>
<p style="text-align: center;"><a title="Dongxinlianzi Hutong by Oncle Tom, on Flickr" href="http://www.flickr.com/photos/the-jedi/6186924596/"><img class="aligncenter" src="http://farm7.staticflickr.com/6154/6186924596_1b82668227.jpg" alt="Dongxinlianzi Hutong" width="500" height="500" /></a></p>
<p><span id="more-18470"></span></p>
<h3>Paradoxe</h3>
<p>Ce discours a de quoi étonner, surtout pour les personnes m&#8217;ayant physiquement fréquenté ces derniers temps. Pourtant cette année, rien ne s&#8217;est passé comme je l&#8217;imaginais ou ne l&#8217;espérais, que ça soit sur le plan professionnel ou personnel. Pourtant tout a été indispensable, des échecs à la réussite. Je dirais même que la réussite a en majeure partie puisé dans l&#8217;échec ; tout particulièrement en 2011.</p>
<p>Cette année j&#8217;ai appris que l&#8217;aspiration à un idéal ne devait pas <strong>compromettre sa propre intégrité</strong>.</p>
<p>Cette année j&#8217;ai appris qu&#8217;un idéal peut voler en éclat du jour au lendemain, obligeant à <strong>reconstruire un modèle de vie en un cycle solaire</strong>.</p>
<p>Cette année j&#8217;ai appris qu&#8217;être freelance et travailler chez soi, même en sortant souvent, c&#8217;est un <strong>état d&#8217;exception insupportable pour le moral</strong>.</p>
<p>Cette année j&#8217;ai appris à <strong>revenir en phase avec mon ombre</strong>.</p>
<p>Cette année j&#8217;ai appris à <strong>suivre les étoiles dans la nuit</strong>.</p>
<p>Cette année j&#8217;ai appris.</p>
<h3>Contribution en baisse/berne</h3>
<p>Que ça soit au niveau du rythme de publication sur ce blog, ça n&#8217;a pas dû dépasser <strong>la <em>frénésie</em> d&#8217;un article tous les 2 mois</strong>. J&#8217;en connais qui attendent encore des billets envisagés et annoncés il y a 1 an. Engloutir 3 ou 4 heures par billet est quelque chose qui m&#8217;est devenu plus difficile à envisager.</p>
<p>Idem dans le choix des sujets où plus ça va, et moins l&#8217;aspect technique me paraît prédominant. Le meilleur <em>framework</em> du monde n&#8217;empêchera pas un projet de foirer. Pour une durée de vie somme toute réduite (6 mois de projet pour 2 ou 3 ans de vie avant de tout réécrire).</p>
<p>Fatalement, coder sur des projets personnels en dehors des heures de travail a subi la même cure d&#8217;amaigrissement : cela s&#8217;est traduit par des petites livraisons sur des projets déjà existants. De tête, rien de neuf … mis à part une implémentation <a href="http://oncletom.github.com/html-game-of-life/"><acronym title="HyperText Markup Language">HTML</acronym> du Game of Life de Conway</a>.</p>
<p><strong>S&#8217;il fallait créer, ce fût avec des images</strong> puisqu&#8217;en <a href="http://www.flickr.com/photos/the-jedi/archives/date-taken/2011/calendar/">2011, je capturais une photo tous les 3 jours, en moyenne</a> ; en numérique et en argentique.</p>
<h3>La solitude quotidienne du freelance</h3>
<p>À bientôt 12 mois d&#8217;exercice, ce que j&#8217;avais initialement estimé être le paradis s&#8217;est transformé en poids pesant : <strong>travailler de chez soi est humainement insupportable à moyen et long terme</strong>.</p>
<p>J&#8217;aurais dû m&#8217;en douter : passer de l&#8217;extrême à un autre, de l&#8217;<em>open space</em> bruyant au bureau individuel chez soi, ça n&#8217;a forcément rien de bon. C&#8217;était très bien au début, parce que j&#8217;en avais besoin. C&#8217;était très bien à certains moments, parce que j&#8217;en avais besoin.<br />
Par contre, ne pas croiser une seule personne pendant ses horaires de travail, c&#8217;est particulièrement étrange.<br />
<strong>C&#8217;est pesant</strong>.</p>
<p>Ça m&#8217;a fait comprendre pourquoi la thématique des lieux de <em>coworking</em> intéresse tant que ça les indépendants. La discussion est source de distraction … mais le lien social est indispensable en journée ET en soirée.</p>
<p>Juste en soirée, ce n&#8217;est pas viable. <em>Period</em>.</p>
<h3>La pression (soci|idé|anim)ale</h3>
<p>Cette année j&#8217;ai perdu un idéal me propulsant sans crier gare dans la situation du drogué en manque, sans autre choix que de renoncer à sa poudre blanche. Gérer la situation en ayant à gérer les projets professionnels, les clients et le calendrier n&#8217;a pas été une partie de plaisir.<br />
Fort heureusement l&#8217;été est prompt à une indulgence de délais.</p>
<p>Cette crise a envahi plusieurs pans de ma vie, telle une contagion invisible, et m&#8217;a fait comprendre et réaliser un certain nombre de concepts :</p>
<ul>
<li>avant d&#8217;en être conscient, on est décidément incapable de faire nos pas dans la vie sans <strong>reproduire ce qu&#8217;on a vu étant jeune</strong>, nos parents en premier lieu, que ce soit par mimétisme ou par opposition ;</li>
<li>quand on est propulsé dans le vide, on n&#8217;a pas le choix : <strong>il faut être inventif</strong> et rapidement arriver à déterminer ce qu&#8217;on est, ce qu&#8217;on veut, pour remonter la falaise et reprendre son chemin ;</li>
<li><strong>avancer vers l&#8217;inconnu fait partie de notre quotidien</strong> : on peut tout perdre du jour au lendemain, et on n&#8217;a pas le choix que de jongler avec les faits ;</li>
<li>si l&#8217;inconnu est omniprésent, <strong>suivre un chemin que l&#8217;on a choisi est indispensable</strong> ;</li>
<li><strong>renoncer à un idéal n&#8217;est pas renoncer à soi</strong>, à une partie de soi : il y a tout le reste, tout ce qu&#8217;on connaît, ce qu&#8217;on ne connaît pas encore et ce qu&#8217;on ne connaîtra jamais.</li>
</ul>
<p>D&#8217;un autre côté, tout ceci a eu pour effet de renforcer le <strong>désir de singularité</strong> : si l&#8217;homme est un animal social (Aristote ne connaissait pas Facebook), il reste la pierre fondatrice de sa socialité. Autrement dit, il doit <strong>disposer de ses propres raisons d&#8217;exister</strong>, individuellement.</p>
<p><strong>Pour rendre un développeur heureux, il faudrait finalement passer plus de temps avec lui</strong>, à parler, qu&#8217;à choisir l&#8217;architecture de code la plus abstraite car la plus évolutive possible.</p>
<p style="text-align: center;"><a title="Peer to Peer by Oncle Tom, on Flickr" href="http://www.flickr.com/photos/the-jedi/6393687987/"><img class="aligncenter" src="http://farm8.staticflickr.com/7025/6393687987_7762280d60.jpg" alt="Peer to Peer" width="495" height="500" /></a></p>
<h3>L&#8217;aventure humaine</h3>
<p>Avec ou sans surprise, <strong>on en revient aux hommes, et aux femmes</strong>. Ces gens qu&#8217;on connaissait peu, de loin ou qui sont géographiquement loin. Ces gens qui s&#8217;ouvrent, partagent et écoutent.</p>
<p>Ceux qui courent en haut des colines, ressentent et t&#8217;aident de leur silence empli de compassion. Ceux qui partagent une bouteille et un morceau de fromage parce qu&#8217;il n&#8217;y a que ça de vrai. Ceux qui te prêtent une épaule sur un fond de carte postale aux odeurs de lavande. Ceux dont le père n&#8217;est pas mort à Venise. Ceux qui te font découvrir une musique transportant au plus haut de la stratosphère. Ceux qui courent avec toi dans le métro un jour de grève. Ceux que tu ne connais que depuis 1h et t&#8217;accompagnent dans un des meilleurs concerts de ta vie. Ceux pour qui un verre de rouge accompagné de cigare restera la meilleure conclusion nocturne. Ceux dont la couleur flamboyante de leur manteau te recouvrira d&#8217;une nouvelle envie.</p>
<p>Ces gens qui te rencontrent et 1 an plus tard, tels des <strong>mousquetaires</strong>, signent avec toi un pacte d&#8217;associés, pour construire un projet faisant saliver les investisseurs, et ravissant chaque client y ayant recours (d&#8217;ailleurs, <a href="https://github.com/Dijiwan/Jobs">on recrute des développeurs Web experimentés</a> et <a href="http://iframe.bfmbusiness.com/BFM_Academie/candidats.php">j&#8217;en parle à la BFM Académie</a>).</p>
<p>Et c&#8217;est là où je me dis que travailler chez soi, c&#8217;est du gâchis social.</p>
<p style="text-align: center;"><a title="The Conflict by Oncle Tom, on Flickr" href="http://www.flickr.com/photos/the-jedi/6314643648/"><img class="aligncenter" src="http://farm7.staticflickr.com/6238/6314643648_e2f57e248b.jpg" alt="The Conflict" width="500" height="333" /></a></p>
<h3>Conclusion</h3>
<p>Le fil rouge de cet article est un <strong>triptyque problème/conflit/solution</strong>. À ce titre, je ne saurais que trop vous conseiller la lecture de l&#8217;ouvrage <a href="http://www.amazon.fr/Conflit-Georges-Simmel/dp/2908024837">Le conflit</a> de Georg Simmel (ainsi qu&#8217;une bonne palanquée de ses écrits). On y retrouve beaucoup d&#8217;exemples sociologiques, historiques et amoureux des conflits, ce qu&#8217;ils ont engendré … très souvent en bien d&#8217;ailleurs. Comme il écrit, le conflit est déjà une étape avancée dans la résolution d&#8217;un problème. C&#8217;est donc sain.</p>
<p>Il aurait été évidemment bien plus agréable et <em>hype</em> de dire que c&#8217;était une année <em>awesome</em> et libertaire.<br />
Sauf que ça n&#8217;a pas été le cas et pour rien au monde, je n&#8217;aurais voulu qu&#8217;il en soit autrement.</p>
<p><strong>2011 aura été exceptionnelle jusqu&#8217;au bout</strong>.</p>]]></content:encoded>
			<wfw:commentRss>http://case.oncle-tom.net/2011/annee-du-fail-personnel/feed/</wfw:commentRss>
		<slash:comments>8</slash:comments>
		</item>
		<item>
		<title>WordPress, mises à jour automatiques et FTP : la solution</title>
		<link>http://case.oncle-tom.net/2010/wordpress-updates-automatiques/</link>
		<comments>http://case.oncle-tom.net/2010/wordpress-updates-automatiques/#comments</comments>
		<pubDate>Mon, 22 Nov 2010 16:33:14 +0000</pubDate>
		<dc:creator>Oncle Tom</dc:creator>
				<category><![CDATA[WordPress]]></category>
		<category><![CDATA[astuce]]></category>
		<category><![CDATA[code]]></category>
		<category><![CDATA[configuration]]></category>
		<category><![CDATA[logiciels libres]]></category>
		<category><![CDATA[upgrade]]></category>
		<guid isPermaLink="false">http://case.oncle-tom.net/?p=17698</guid>
		<description><![CDATA[Marre de mettre à jour vos extensions WordPress à la main ? Vous ne comprenez pas quoi faire avec l'écran de mise à jour FTP de WordPress ? Cet article contient la solution pour rétablir les mises à jour automatiques sans toucher à votre configuration serveur.]]></description>
			<content:encoded><![CDATA[<p>Lorsque j&#8217;étais hébergé chez <a href="http://www.ovh.com/">OVH</a>, avant de basculer vers <a href="http://alwaysdata.com/">AlwaysData</a> pour gagner en vitesse d&#8217;affichage, la mise à jour de mes extensions se faisait le plus simplement du monde depuis l&#8217;interface d&#8217;administration.</p>
<p>Seulement voilà, lors de toute tentative de mise à jour, que ce soit du blog, d&#8217;une extension ou d&#8217;un thème, un écran de configuration de paramètres <acronym title="File Transfer Protocol">FTP</acronym> apparaît. Comme nous sommes des feignants, on ne voudra en aucun cas ouvrir un serveur <acronym title="File Transfer Protocol">FTP</acronym>, qui n&#8217;aurait d&#8217;ailleurs pour d&#8217;autre intérêt que de faciliter les intrusions dans votre système.</p>
<p><span id="more-17698"></span></p>
<h3>Où trouver l&#8217;information ?</h3>
<p>En cherchant un peu, je suis tombé sur l&#8217;ensemble des <a href="http://codex.wordpress.org/Editing_wp-config.php">directives de configuration de WordPress</a>, dont les <a href="http://codex.wordpress.org/Editing_wp-config.php#WordPress_Upgrade_Constants">constantes liées au système de fichier</a>.<br />
Cette section précise ce qu&#8217;il faut savoir, même si c&#8217;est suffisamment technique pour perdre toute personne ne comprenant rien au code (et on ne leur en voudra pas).</p>
<p>Le problème vient du fait que si l&#8217;<strong>utilisateur propriétaire</strong> du système de fichier n&#8217;est pas le même utilisateur du serveur <acronym title="HyperText Transfer Protocol">HTTP</acronym>, WordPress bascule automatiquement en mise à jour via <acronym title="File Transfer Protocol">FTP</acronym>.</p>
<p>L&#8217;astuce consiste à forcer WordPress en mode <em>direct</em> (système de fichier) et à donner les droits d&#8217;écriture au <strong>groupe propriétaire</strong> correspondant à celui du serveur <acronym title="HyperText Transfer Protocol">HTTP</acronym> (<em>www-data</em> pour Apache et Nginx sous Debian et Ubuntu).</p>
<h3>Configuration de wp-config.php</h3>
<p>Forcer le mode direct est très simple. Il suffit d&#8217;éditer le fichier <em>wp-config.php</em>, celui-là même qui contient les identifiants de connexion à la base de données et autres joyeusetés. Et d&#8217;y rajouter cette ligne, avant la première directive par exemple :</p>
<pre><code class="php">define('FS_METHOD', 'direct');</code></pre>
<p>Enregistrez, et c&#8217;est plié.</p>
<h3>Réglage des permissions</h3>
<p>Côté permissions, ça peut également se régler en 2 coups de terminal. Partons du principe que le <strong>groupe propriétaire</strong> de votre serveur <acronym title="HyperText Transfer Protocol">HTTP</acronym> est <em>www-data</em>, à la base de votre installation WordPress, il suffit de faire ceci :</p>
<pre><code class="shell">chgrp -R www-data wp-content/upgrade wp-content/themes wp-content/plugins wp-content/uploads
chmod g+wx wp-content/upgrade wp-content/themes wp-content/plugins wp-content/uploads</code></pre>
<p>Cette manipulation attribue <em>www-data</em> comme propriétaire des répertoires que vous souhaitez rendre accessibles en écriture et ce, de manière récursive. Dans un second temps, elle attribute les droits d&#8217;écriture et d&#8217;exécution au groupe propriétaire (peu importe le nom du groupe).<br />
Si vous êtes perdu(e) avec la commande <a href="http://www.siteduzero.com/tutoriel-3-36115-les-chmod.html"><code>chmod</code>, un peu de lecture pour apprendre à le manipuler</a> (ça sauve la vie).</p>
<h3>Conclusion</h3>
<p>A ce stade des choses, tout est fonctionnel : tentez d&#8217;installer une nouvelle extension, ça passera comme une lettre à la poste.<br />
Si vous rencontrez des difficultés, c&#8217;est très certainement parce que les permissions des fichiers qui tentent d&#8217;être modifiées ne sont pas suffisantes pour le groupe propriétaire du serveur <acronym title="HyperText Transfer Protocol">HTTP</acronym>. Ajustez la procédure des permissions par rapport à votre besoin.</p>
<p>C&#8217;est pas sorcier, il suffisait de le savoir  :-)</p>]]></content:encoded>
			<wfw:commentRss>http://case.oncle-tom.net/2010/wordpress-updates-automatiques/feed/</wfw:commentRss>
		<slash:comments>14</slash:comments>
		</item>
		<item>
		<title>Ajouter TinyMCE dans un plugin WordPress</title>
		<link>http://case.oncle-tom.net/2009/ajouter-tinymce-plugin-wordpress/</link>
		<comments>http://case.oncle-tom.net/2009/ajouter-tinymce-plugin-wordpress/#comments</comments>
		<pubDate>Tue, 03 Feb 2009 06:00:39 +0000</pubDate>
		<dc:creator>Oncle Tom</dc:creator>
				<category><![CDATA[Développement Web]]></category>
		<category><![CDATA[WordPress]]></category>
		<category><![CDATA[api]]></category>
		<category><![CDATA[code]]></category>
		<category><![CDATA[firebug]]></category>
		<category><![CDATA[Javascript]]></category>
		<category><![CDATA[logiciels libres]]></category>
		<category><![CDATA[plugin]]></category>
		<category><![CDATA[tinymce]]></category>
		<guid isPermaLink="false">http://case.oncle-tom.net/?p=1297</guid>
		<description><![CDATA[J&#8217;ai eu besoin récemment d&#8217;inclure un éditeur visuel dans un plugin WordPress. Je pensais que c&#8217;était une tâche aisée sans chercher sur Google : il n&#8217;y avait qu&#8217;à faire comme les développeurs de WordPress ! J&#8217;ai pensé à tort et ça m&#8217;a confirmé une fois de plus que le code source de WordPress était un [...]]]></description>
			<content:encoded><![CDATA[<p><a href="http://case.oncle-tom.net/images/2009/04/wordpress-badge.png"><img class="aligncenter size-thumbnail wp-image-1347" title="WordPress Logo" src="http://case.oncle-tom.net/images/2009/04/wordpress-badge-138x138.png" alt="WordPress Logo" width="138" height="138" /></a></p>
<p>J&#8217;ai eu besoin récemment d&#8217;inclure un éditeur visuel dans un plugin WordPress. Je pensais que c&#8217;était une tâche aisée sans chercher sur Google : il n&#8217;y avait qu&#8217;à faire comme les développeurs de WordPress !</p>
<p>J&#8217;ai pensé à tort et ça m&#8217;a confirmé une fois de plus que le code source de WordPress était un joyeux bazar.<br />
<span id="more-1297"></span></p>
<h3>Le besoin</h3>
<p>Mon besoin était tout bête : sur une seule page de mon plugin, j&#8217;avais besoin de transformer un bête champ texte en éditeur avancé avec possibilité d&#8217;uploader des images et tout ça.</p>
<p>Avec ce simple besoin, j&#8217;ai cependant constaté :</p>
<ol>
<li>qu&#8217;il était <strong>pénible</strong> de remonter le cheminement logique de l&#8217;éditeur jusqu&#8217;à l&#8217;inclusion des scripts</li>
<li>qu&#8217;il n&#8217;y a <strong>pas de façon standard</strong> d&#8217;ajouter l&#8217;éditeur : il y a bien une fonction <code>wp_tiny_mce</code> mais elle ne fait pas tout &#8230; c&#8217;est à dire que sans inclure ses dépendances (non documentées), cette fonction n&#8217;est d&#8217;aucune utilité</li>
<li>qu&#8217;on trouve <strong>à boire et à manger</strong> dans le code de WordPress. Pour le <cite>code is poetry</cite>, on est plutôt proche du SMS kikoololesque</li>
</ol>
<p>Après avoir trouvé ma solution, je suis cependant tombé sur un <a href="http://blog.zen-dreams.com/fr/2008/11/06/how-to-include-tinymce-in-your-wp-plugin/">article expliquant comment inclure TinyMCE dans WordPress</a>. Elle est juste mais nous verrons que seule la moitié du chemin a été faite avec.</p>
<h3>La solution</h3>
<pre><code class="php">&lt;?php
add_action('admin_menu', 'include_tinymce');
function include_tinycme()
{
  add_action('admin_head', 'wp_tiny_mce');
  wp_enqueue_script('jquery-ui-core');
  wp_enqueue_script('jquery-ui-tabs');
  wp_enqueue_script('editor');
  wp_enqueue_script('media-upload');
  add_thickbox();
}</code></pre>
<p>Plusieurs remarques par rapport à ce code :</p>
<ul>
<li><strong>Le choix de l&#8217;action</strong><br />
Le mien s&#8217;est porté sur <em>admin_menu</em>. Vous pourriez en choisir une autre, du moment qu&#8217;elle s&#8217;exécute <em>avant</em> admin_head. J&#8217;ai choisi celle-là parce que c&#8217;est là que j&#8217;y construis les menus de l&#8217;administration : WordPress est initialisé et n&#8217;a pas encore été affiché.</li>
<li><strong>Le choix wp_enqueue_script</strong><br />
J&#8217;aurais pu caller cette fonction en tant que filtre de <code>admin_head</code> et utiliser la fonction <code>print_script</code> MAIS je soupçonne cette dernière fonction de ne pas vérifier si un autre script du même nom a été inclus.<br />
J&#8217;ai choisi de ne pas créer de conflit : <code>wp_enqueue_script</code> ne chargera qu&#8217;1 fois et 1 seule le script nommé. Pas de chichi.</li>
<li><strong>L&#8217;inclusion de l&#8217;éditeur</strong><br />
Pour afficher l&#8217;éditeur, il suffira d&#8217;appeler la fonction <code>the_editor()</code> en lieu et place de son <code>textarea</code>. Vous noterez toutefois que vous serez obligé(e)s de nommer l&#8217;éditeur <em>content</em> sous peine de devoir ajouter quelques filtres supplémentaires.</li>
</ul>
<p>Après à vous de vous débrouiller avec l&#8217;architecture de votre plugin. Personnellement j&#8217;ai tout basculé dans des classes depuis un bon moment pour éviter tout conflit de nom.</p>
<h3>La solution optimisée</h3>
<p>Cependant ne crions pas victoire si vite : avec ce qu&#8217;on a fait, nous avons juste réussi à inclure TinyMCE sur <em>toutes</em> les pages de l&#8217;admin WordPress. Ce n&#8217;est pas ce que je recommanderai pour deux raisons :</p>
<ol>
<li>le respect des performances utilisateurs : charger 150Ko de JavaScript pour rien sur une page sans TinyMCE, c&#8217;est du gâchis</li>
<li>on ne fait pas une généralité pour une exception</li>
</ol>
<p>Heureusement pour nous WordPress est <em>bien fichu</em> car il nous fournit 2 variables globales (*hm*) d&#8217;exception :</p>
<ul>
<li><strong>$plugin_page</strong><br />
Cette variable contient le nom de la page renseignée par les méthodes <code>add_management_page()</code> et <code>add_options_page()</code>. On aurait pu passer directement par <a href="http://codex.wordpress.org/Plugin_API/Action_Reference">admin_print_script*</a> mais il faisait flemme d&#8217;ajouter une fonction de plus.<br />
Exemple :</p>
<pre><code class="php">&lt;?php
add_management_page('Titre', 'Label', 8, 'test_management_page', 'mon_callback');
//$plugin_page vaudra 'test_management_page'</code></pre>
</li>
<li><strong>$pagenow</strong><br />
Cette variable contient le nom du fichier actuellement exécuté.<br />
Si vous vous trouvez sur <kbd>wp-admin/tools.php?page=test_management_page</kbd>, <code>$pagenow</code> vaudra <code>tools.php</code></li>
</ul>
<p>Avec ces deux variables, on est capable de charger ce qu&#8217;on veut, où on veut et quand on veut.</p>
<p>Au final, ça nous donnerait ceci :</p>
<pre><code class="php">&lt;?php
add_action('admin_menu', 'include_tinymce');
function include_tinycme()
{
  global $plugin_page;
  if ($plugin_page === 'test_management_page')
  {</code><code class="php">
    add_action('admin_head', 'wp_tiny_mce');
    wp_enqueue_script('jquery-ui-core');
    wp_enqueue_script('jquery-ui-tabs');
    wp_enqueue_script('editor');
    wp_enqueue_script('media-upload');
    add_thickbox();</code>
<code class="php">  }
}</code></pre>
<p>Là on a bien terminé le travail.</p>
<h3>Conclusion</h3>
<p>Il n&#8217;y a au final pas grand chose à chose à ajouter pour disposer de TinyMCE. Encore faut-il le savoir.</p>
<p>On peut cependant regretter le manque de flexibilité de cette manipulation :</p>
<ul>
<li>j&#8217;ai definé la liste des fichiers en cherchant les noms de fonctions JavaScript manquantes (merci Firebug et l&#8217;affichage des exceptions en console)</li>
<li>la liste des dépendances de <code>wp_enqueue_script</code> n&#8217;est absolument pas complète : <em>editor</em> devrait appeler <em>wp_tiny_mce</em> et <em>media-upload</em> (voire <em>jquery-ui-*</em>)</li>
</ul>
<p>Un jour WordPress nettoiera son code pour faciliter la maintenance &#8230;</p>]]></content:encoded>
			<wfw:commentRss>http://case.oncle-tom.net/2009/ajouter-tinymce-plugin-wordpress/feed/</wfw:commentRss>
		<slash:comments>13</slash:comments>
		</item>
		<item>
		<title>WordPress en tant que dépendance SVN</title>
		<link>http://case.oncle-tom.net/2008/wordpress-svn-external/</link>
		<comments>http://case.oncle-tom.net/2008/wordpress-svn-external/#comments</comments>
		<pubDate>Tue, 23 Dec 2008 06:00:59 +0000</pubDate>
		<dc:creator>Oncle Tom</dc:creator>
				<category><![CDATA[WordPress]]></category>
		<category><![CDATA[bonne pratique]]></category>
		<category><![CDATA[code]]></category>
		<category><![CDATA[codex]]></category>
		<category><![CDATA[htaccess]]></category>
		<category><![CDATA[i18n]]></category>
		<category><![CDATA[logiciels libres]]></category>
		<category><![CDATA[optimisation]]></category>
		<category><![CDATA[php]]></category>
		<category><![CDATA[plugins]]></category>
		<category><![CDATA[svn]]></category>
		<category><![CDATA[wordpress mu]]></category>
		<guid isPermaLink="false">http://case.oncle-tom.net/?p=1237</guid>
		<description><![CDATA[Mettre à jour WordPress était pénible jusqu&#8217;à l&#8217;arrivée de la version 2.7. On bénéficie désormais de la mise à jour automatique : un clic, ça télécharge et ça déploie. Il existe cependant une méthode alternative reposant sur Subversion (SVN). C&#8217;est la méthode idéale pour tout développeur WordPress ou gestionnaire de blogs. C&#8217;est celle que j&#8217;emploie [...]]]></description>
			<content:encoded><![CDATA[<p>Mettre à jour WordPress était pénible jusqu&#8217;à l&#8217;arrivée de la version 2.7. On bénéficie désormais de la mise à jour automatique : un clic, ça télécharge et ça déploie.</p>
<p><img class="aligncenter size-full wp-image-912" title="Logo WordPress" src="http://case.oncle-tom.net/images/2008/05/wordpress-logo.png" alt="" width="273" height="66" /></p>
<p>Il existe cependant une <strong>méthode alternative reposant sur Subversion</strong> (<acronym title="Subversion">SVN</acronym>). C&#8217;est la méthode idéale pour tout développeur WordPress ou gestionnaire de blogs. C&#8217;est celle que j&#8217;emploie depuis la version 2.6 grâce notamment à la constante WP_CONTENT.</p>
<p>Explications et application concrète.</p>
<p><span id="more-1237"></span></p>
<p>Avant toute chose, sachez que <strong>ce tutorial est optimisé pour les personnes qui versionnent entièrement leur projet</strong>. Il n&#8217;est pas question ici d&#8217;avoir une arborescence libre et de procéder à des <em>checkout</em> un peu partout. C&#8217;est possible mais pas du plus grand intérêt.</p>
<p>L&#8217;avantage évident ici est de pouvoir déployer son blog n&#8217;importe où en un rien de temps.</p>
<h3>Structure des fichiers</h3>
<p>Installer WordPress en tant que dépendance <acronym title="Subversion">SVN</acronym> revient à mélanger 2 techniques :</p>
<ul>
<li><a href="http://codex.wordpress.org/Giving_WordPress_Its_Own_Directory">Installer WordPress dans son propre répertoire<br />
</a></li>
<li><a href="http://codex.wordpress.org/Installing_WordPress_With_Clean_Subversion_Repositories">Installer WordPress proprement depuis <acronym title="Subversion">SVN</acronym></a></li>
</ul>
<p>Je suis pénible donc je n&#8217;ai pas spécialement envie de modifier un fichier <em>core</em> ou autre chose que <em>wp-config.php</em>. Tout le contraire de ce qu&#8217;indique la première méthode.</p>
<p>La seconde explication m&#8217;a toutefois posé légèrement problème puisqu&#8217;un peu brutale et posant soucis chez OVH.</p>
<img class="size-full wp-image-1254" title="Arborescence fichier avec WordPress SVN" src="http://case.oncle-tom.net/images/2008/12/wordpress-svn-basic-filetree.png" alt="Arborescence fichier avec WordPress SVN" width="329" height="298" />
<p>Celles et ceux qui voient la capture d&#8217;écran ci-dessus peuvent constater que <em>tout WordPress</em> a été déplacé dans un sous-répertoire <em>wordpress</em> au même niveau que wp-content.<br />
On ne garde à la racine que le fichier <em>.htaccess</em> et <em>wp-config.php</em>.</p>
<p>Sur le répertoire racine, j&#8217;ai appliqué ces propriétés pour WordPress 2.7 :</p>
<ul>
<li><kbd>svn:ignore</kbd> :<kbd><br />
</kbd></p>
<pre><code class="svn">wp-config.php</code></pre>
</li>
<li><kbd>svn:externals</kbd> :<kbd><br />
</kbd></p>
<pre><code class="svn">wordpress http://svn.automattic.com/wordpress/branches/2.7</code></pre>
</li>
</ul>
<p>Je ne versionne volontairement pas le fichier wp-config.php car c&#8217;est le seul fichier susceptible de changer d&#8217;une instance à une autre. Je le récupère depuis wordpress/wp-config-sample.php et je le personnalise selon mes besoins.<br />
Et puis versionner des mots de passe &#8230; qui y tient ?</p>
<h3>Configuration</h3>
<p>Après cette restructuration, on aura toutefois besoin de configurer 2-3 bricoles. Vraiment rien de méchant promis.</p>
<h4>Le .htaccess</h4>
<p>Voici ma configuration. Elle peut être aisément déportée dans votre déclaration de <em>Virtual Host</em> pour des raisons de performance. Sur un serveur mutualisé vous n&#8217;avez en général pas accès à ce dernier type de configuration.</p>
<pre><code>&lt;IfModule mod_rewrite.c&gt;
Options -Multiviews -Indexes +FollowSymlinks
RewriteEngine On
RewriteBase /
# Moving to dependency
RewriteRule ^(index.php|wp-[a-z0-9-]+\.php|xmlrpc.php)?$ wordpress/$1 [L]
RewriteRule ^(wp-admin|wp-includes)/(.*)$ wordpress/$1/$2 [QSA,L]
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule . wordpress/index.php [L]
&lt;/IfModule&gt;
# BEGIN WordPress
# END WordPress</code></pre>
<p>Ce fichier est très inspiré de la <a href="http://codex.wordpress.org/Installing_WordPress_With_Clean_Subversion_Repositories">configuration <acronym title="Subversion">SVN</acronym> proposée sur le Codex WordPress</a>. Seulement voilà, cette renvoie tout sur <em>index.php</em> &#8230; et omet ainsi tous les accès aux fichiers situés à la racine, avec entre autre :</p>
<ul>
<li>wp-cron.php</li>
<li>wp-link-opml.php</li>
<li>wp-trackback.php</li>
<li>xmlrpc.php</li>
</ul>
<p>Je vous fais grâce des contrôleurs de flux (Atom, <acronym title="Really Simple Syndication">RSS</acronym> &amp; cie) et des appels en directs à <em>index.php</em> effectués par certains plugins.</p>
<p>Donc non on ne peut pas vraiment se passer de ces fichiers. D&#8217;où ces 2 règles :</p>
<ul>
<li>
<pre><code>RewriteRule ^(index.php|wp-[a-z0-9-]+\.php|xmlrpc.php)?$ wordpress/$1 [L]
</code></pre>
<p>On capte tous les fichiers <acronym title="Pre-Hypertext Processing">PHP</acronym> (les contrôleurs) originellement situés à la racine de WordPress.</li>
<li>
<pre><code>RewriteRule ^(wp-admin|wp-includes)/(.*)$ wordpress/$1/$2 [QSA,L]</code></pre>
<p>Et là c&#8217;est pour le confort de conserver les adresses initiales &#8230; mais aussi pour éviter de modifier un bout de paramétrage dans l&#8217;admin. Le jour où vous décidez de rebasculer à l&#8217;ancien système, ça se fera sans douleur <img src='http://case.oncle-tom.net/wp-includes/images/smilies/icon_smile.gif' alt=':-)' class='wp-smiley' /> </li>
</ul>
<p>Enfin, pourquoi avoir poussé les commentaires WordPress vers le bas ? Tout simplement pour <strong>éviter que nos règles personnalisées soient écrasées par WordPress</strong> lors d&#8217;une mise à jour des permaliens. Nos règles primeront toujours ainsi.</p>
<h4>Le fichier wp-config.php</h4>
<p>Dans le fichier <em>wp-config.php</em>, nous n&#8217;allons rien modifier. Nous allons juste ajouter forcer 2 paramètres. Ils indiqueront à WordPress où se trouve le véritable répertoire <em>wp-content</em> (renommable mais je ne jouerai pas avec).</p>
<img class="size-full wp-image-1262" title="wp-config.php modifié pour WordPress SVN" src="http://case.oncle-tom.net/images/2008/12/wordpress-svn-wpconfig.png" alt="wp-config.php modifié pour WordPress SVN" width="600" height="266" />
<h4>Le blog</h4>
<p>Bon j&#8217;ai menti un peu toute à l&#8217;heure en indiquant qu&#8217;on ne toucherait qu&#8217;à <em>wp-config.php</em>. Cependant la modification est on ne peut plus mineure et ne concerne que l&#8217;upload de medias.</p>
<p>En effet si on ne touche pas à l&#8217;emplacement des fichiers envoyés, WordPress considère qu&#8217;ils sont uploadés dans wordpress/wp-content/uploads. C&#8217;est fort gênant mais heureusement, en préfixant le chemin par ../ ou en tapant un chemin absolu tout rentrera dans l&#8217;ordre.</p>
<img class="size-full wp-image-1261" title="Correction de chemin pour WordPress SVN" src="http://case.oncle-tom.net/images/2008/12/wordpress-svn-file-uploads-fix.png" alt="Correction de chemin pour WordPress SVN" width="600" height="74" />
<p>À noter qu&#8217;il s&#8217;agit du <strong>seul paramétrage hors d&#8217;un fichier</strong>. Si j&#8217;avais pu m&#8217;en passer je l&#8217;aurais fait.</p>
<h3>Dépendance <acronym title="Subversion">SVN</acronym> pour la traduction</h3>
<p>C&#8217;est en tombant sur un autre <a href="http://sunfox.org/blog/2007/05/28/installation-svn-de-wordpress-et-de-ses-plugins/">article traitant de svn:externals pour WordPress</a> que j&#8217;ai été interpelé sur la prise en charge des langues via <acronym title="Subversion">SVN</acronym> également.<br />
Le système n&#8217;est pas parfait puisqu&#8217;on ne peut gérer qu&#8217;une seule langue par ce biais là. Ça ne conviendra donc pas aux blogs multilingues.</p>
<img class="size-full wp-image-1260" title="Dépendance SVN pour les traductions WordPress" src="http://case.oncle-tom.net/images/2008/12/wordpress-i18n-svn-external.png" alt="Dépendance SVN pour les traductions WordPress" width="550" height="104" />
<p>La technique consiste à transformer <code>wp-content/languages</code> en <kbd>svn:externals</kbd>.<br />
Ça donnerait ceci pour la version française de WordPress 2.7, au niveau du <kbd>svn:externals</kbd> du répertoire <code>wp-content</code> :</p>
<pre><code class="svn">languages http://svn.automattic.com/wordpress-<acronym title="internationalisation">i18n</acronym>/fr_FR/branches/2.7/messages/</code></pre>
<p><strong>Simple et efficace</strong> mais ça reste encore de la bricole.</p>
<h3>Cas particulier : plugins et <acronym title="internationalisation">i18n</acronym></h3>
<p>Je vous expose le problème mais malheureusement vous ne pourrez pas y faire grand chose. Par contre ami développeurs, pour rendre votre code de plugin 100% portable, merci de prendre note <img src='http://case.oncle-tom.net/wp-includes/images/smilies/icon_wink.gif' alt=';-)' class='wp-smiley' /> </p>
<p>Le chargement des traductions s&#8217;effectue à l&#8217;aide de la fonction load_plugin_textdomain(). Elle prenait seulement 2 paramètres jusqu&#8217;à l&#8217;arrivée de WordPress 2.6. Ça n&#8217;a pas été crié sur les toits mais elle prend désormais 3 &#8230; et c&#8217;est du 3ème argument qu&#8217;il faut utiliser désormais :</p>
<ol>
<li><code class="php">$domain</code> : l&#8217;espace de nom des traduction (inchangé)</li>
<li><code class="php">$abs_rel_path</code> : chemin relatif par rapport à l&#8217;emplacement de WordPress (déprécié, on y mettait <code>PLUGINDIR.'/'.dirname(plugin_basename(__FILE__))</code> en général)</li>
<li><code class="php">$plugin_rel_path</code> :  chemin relatif par rapport à l&#8217;emplacement des plugins (c&#8217;est qui nous intéresse ; <code>dirname(plugin_basename(__FILE__))</code> nous suffira désormais)</li>
</ol>
<p>Vous trouverez un <a href="http://codex.wordpress.org/Writing_a_Plugin#Internationalizing_Your_Plugin">exemple sur le Codex, du côté de l&#8217;internationalisation des plugins</a>.<br />
Un exemple de code pérenne :</p>
<pre><code class="php">load_plugin_textdomain('votreplugin', dirname(plugin_basename(__FILE__)), dirname(plugin_basename(__FILE__)));</code></pre>
<p>Et si jamais vous utilisez votre plugin en lien symbolique ça ne fonctionnera pas &#8230; mais on s&#8217;éloigne du sujet <img src='http://case.oncle-tom.net/wp-includes/images/smilies/icon_wink.gif' alt=';-)' class='wp-smiley' /> </p>
<h3>Et pour WordPress Mu ?</h3>
<p>Je ne m&#8217;attarderai pas dessus mais les manipulations sont sensiblement les mêmes. Je n&#8217;ai pas encore eu l&#8217;occasion d&#8217;essayer mais j&#8217;ose imaginer qu&#8217;il n&#8217;y a pas tant de différences que ça <img src='http://case.oncle-tom.net/wp-includes/images/smilies/icon_smile.gif' alt=':-)' class='wp-smiley' /> </p>
<h3>Conclusion</h3>
<p>Le jour où vous souhaitez migrer vers une autre version majeure de WordPress, c&#8217;est simple :<strong> il suffit de changer les externals vers le tag adéquat</strong>.</p>
<p>Pourquoi ne pas utiliser le <em>trunk</em> directement me demanderez-vous ? Le trunk de WordPress est plutôt instable puisque c&#8217;est là que se construit la prochaine version de manière systématique. L&#8217;utilisation des <strong>branches permet de bénéficier des correctifs</strong> sans avoir à modifier le moindre external.<br />
Si vous avez un grand besoin de stabilité, alors utilisez les <em>tags</em> qui sont en principe figés.</p>
<p>On remarquera aussi que malgré son âge, <strong>WordPress commence à peine à proposer des solutions d&#8217;industrialisation</strong>.<br />
Les liens symboliques sont en effet très mal gérés. Tentez d&#8217;utiliser un seul répertoire source pour plusieurs blogs avec des liens symboliques et tout s&#8217;effondre.</p>
<p>La preuve en est aussi avec le <strong>manque de ressources disponibles sur le Web</strong> et traitant ce sujet. Ça m&#8217;étonnerait d&#8217;être le premier à vouloir déployer du WordPress via <acronym title="Subversion">SVN</acronym>.<br />
Les choses s&#8217;améliorent mais pour le côté <cite>code is poetry</cite>, on en est encore loin.</p>]]></content:encoded>
			<wfw:commentRss>http://case.oncle-tom.net/2008/wordpress-svn-external/feed/</wfw:commentRss>
		<slash:comments>8</slash:comments>
		</item>
		<item>
		<title>Développement efficace avec les frameworks CSS</title>
		<link>http://case.oncle-tom.net/2008/developpement-efficace-frameworks-css/</link>
		<comments>http://case.oncle-tom.net/2008/developpement-efficace-frameworks-css/#comments</comments>
		<pubDate>Tue, 25 Nov 2008 06:00:08 +0000</pubDate>
		<dc:creator>Oncle Tom</dc:creator>
				<category><![CDATA[Développement Web]]></category>
		<category><![CDATA[blueprint]]></category>
		<category><![CDATA[bonnes pratiques]]></category>
		<category><![CDATA[code]]></category>
		<category><![CDATA[css]]></category>
		<category><![CDATA[frameworks]]></category>
		<category><![CDATA[logiciels libres]]></category>
		<category><![CDATA[parisweb]]></category>
		<category><![CDATA[rythme vertical]]></category>
		<category><![CDATA[xhtml]]></category>
		<guid isPermaLink="false">http://case.oncle-tom.net/?p=1211</guid>
		<description><![CDATA[J&#8217;ai eu peur il y a 2 semaines en arrivant à Paris-Web 2008 : en discutant avec plusieurs personnes, il se trouve que peu d&#8217;entre elles connaissaient les frameworks CSS. Je craignais de n&#8217;attirer personne avec ce sujet lors des ateliers du samedi. Les frameworks CSS ont été mentionnés la première fois dans la conférence [...]]]></description>
			<content:encoded><![CDATA[<p><img class="aligncenter size-full wp-image-1214" title="Logo Blueprint" src="http://case.oncle-tom.net/images/2008/11/blueprint-logo.png" alt="" width="340" height="82" /></p>
<p>J&#8217;ai eu peur il y a 2 semaines en arrivant à <a href="http://case.oncle-tom.net/2008/11/20/paris-web-2008-webdesign-qualite-standards/">Paris-Web 2008</a> : en discutant avec plusieurs personnes, il se trouve que peu d&#8217;entre elles connaissaient les <em>frameworks</em> <acronym title="Cascading Style Sheets">CSS</acronym>. Je craignais de n&#8217;attirer personne avec ce sujet lors des <a href="http://www.paris-web.fr/2008/-samedi-15-novembre-technique-">ateliers du samedi</a>.</p>
<p>Les <em>frameworks</em> <acronym title="Cascading Style Sheets">CSS</acronym> ont été mentionnés la première fois dans la conférence <a href="http://www.wait-till-i.com/2008/10/31/working-in-the-now/">Working in the Now</a> (<a title="Visualiser la présentation Working in the Now de Christian Heilmann" href="http://www.slideshare.net/cheilmann/working-in-the-now-presentation">visualiser la présentation</a>). Au final, on n&#8217;était pas loin de faire salle comble avec plus d&#8217;une vingtaine de participants à vue de nez.</p>
<p>Une petite scéance de rattrapage s&#8217;impose <img src='http://case.oncle-tom.net/wp-includes/images/smilies/icon_wink.gif' alt=';-)' class='wp-smiley' /> </p>
<p><span id="more-1211"></span></p>
<h3>Pourquoi avoir choisi ce sujet ?</h3>
<p>J&#8217;ai lu un article sur <a href="http://www.biologeek.com/ergonomie,informatique/l-importance-du-rythme-vertical-en-design-css/">l&#8217;importance du rythme vertical</a> l&#8217;an dernier sur <a href="http://www.biologeek.com">Biologeek</a> et ça m&#8217;a sensibilisé au fait qu&#8217;on pouvait rendre la lecture d&#8217;un site tout simplement en rendant prédictible la position du texte.</p>
<p>Entre temps j&#8217;ai également lu l&#8217;excellent <a href="http://case.oncle-tom.net/2007/12/11/critique-transcender-css-sublimez-design-web/">Transcender <acronym title="Cascading Style Sheets">CSS</acronym></a> d&#8217;<a href="http://www.stuffandnonsense.co.uk">Andy Clarke</a>. J&#8217;y ai été sublimé par des présentations de sites totalement en grille.</p>
<p>Depuis je suis devenu fan de <a href="http://www.blueprintcss.org/">Blueprint <acronym title="Cascading Style Sheets">CSS</acronym></a> (je crois que ça s&#8217;est remarqué lors de mon intervention <img src='http://case.oncle-tom.net/wp-includes/images/smilies/icon_wink.gif' alt=';-)' class='wp-smiley' /> ). J&#8217;ai commencé à l&#8217;utiliser sur des projets personnels puis dans un cadre professionnel. J&#8217;utilisais déjà <a href="http://www.symfony-project.org">symfony</a> comme framework <acronym title="Pre-Hypertext Processing">PHP</acronym> et <a href="http://jquery.com">jQuery</a> comme framework JavaScript alors pourquoi pas Blueprint ?</p>
<p>Comme le suggérait très justement <a href="http://www.wait-till-i.com">Christian Heilmann</a> dans sa présentation, l&#8217;utilisation d&#8217;outils déjà existants est nécessaire pour réduire les coûts de production. C&#8217;était déjà un bon alibi mais je les apprécie aussi parce qu&#8217;on gagne un temps fou ! On se concentre sur le code métier, pas le reste.</p>
<h3>La présentation</h3>
<p>Je n&#8217;en dis pas plus, je vous laisse lire la présentation. Ayez toutefois en tête qu&#8217;en vrai elle dure facilement 1h.</p>
<div style="text-align:center"><object classid="clsid:d27cdb6e-ae6d-11cf-96b8-444553540000" width="425" height="355" codebase="http://download.macromedia.com/pub/shockwave/cabs/flash/swflash.cab#version=6,0,40,0"><param name="allowFullScreen" value="true" /><param name="allowScriptAccess" value="always" /><param name="src" value="http://static.slideshare.net/swf/ssplayer2.swf?doc=pariswebdeveloppementefficaceframeworkscss-1226764594180788-9&amp;stripped_title=dveloppement-efficace-avec-les-frameworks-css-presentation" /><embed type="application/x-shockwave-flash" width="425" height="355" src="http://static.slideshare.net/swf/ssplayer2.swf?doc=pariswebdeveloppementefficaceframeworkscss-1226764594180788-9&amp;stripped_title=dveloppement-efficace-avec-les-frameworks-css-presentation" allowscriptaccess="always" allowfullscreen="true"></embed></object></div>
<h3>Ce qu&#8217;il faut en retenir</h3>
<p>J&#8217;ai rencontré 2 types de réactions lorsque j&#8217;ai parlé des frameworks : les enthousiastes et les réfractaires.</p>
<p>Je ne reviens pas sur les enthousiastes : il suffit de lire ma présentation. Les atouts les ont clairement séduit.<br />
Je m&#8217;intéresserai plutôt aux réfractaires. Assez paradoxalement, ce n&#8217;est pas dans la salle que je les ai eu mais en dehors. Les principaux arguments étaient :</p>
<ul>
<li>ça rajoute des kilo-octets superflus</li>
<li>on perd le contrôle de notre code</li>
<li>j&#8217;utilise déjà le mini-framework d&#8217;un collègue ou qui existait dans mon entreprise avant que j&#8217;arrive</li>
</ul>
<p>Ces arguments sont tout à fait acceptables &#8230; mais ça dépend dans quel contexte.</p>
<div id="attachment_1215" class="wp-caption aligncenter" style="width: 510px"><img class="size-full wp-image-1215" title="Exemple de mise en forme en grille" src="http://case.oncle-tom.net/images/2008/11/blueprint-sample.png" alt="Exemple de mise en forme en grille" width="500" height="226" /><p class="wp-caption-text">Exemple de mise en forme en grille</p></div>
<p>Les sites à la recherche de performances exceptionnelles, ceux pour qui un Ko supprimé économise plusieurs Go de bande-passante par jour &#8230; oui ceux-là ont un grand intérêt à réfléchir à l&#8217;adoption d&#8217;un <em>framework</em>, aussi compressé qu&#8217;il soit.<br />
Je ne me fais pas de soucis pour eux : en général ils ont leur propre <em>framework</em>, totalement adapté à leur besoin. Cependant ça n&#8217;empêche pas d&#8217;aller prendre des idées ailleurs et de découvrir de nouveaux concepts. Puis de les intégrer.</p>
<p>Lorsqu&#8217;on adopte un outil de développement rapide (RAD), la conception ne se fait plus par rapport à nos habitudes mais par rapport à des <strong>principes établis</strong>. On ne fait plus forcément comme on veut mais les meilleurs <em>frameworks</em> disposent de fonctionnalités répondant à cette problématique. Le <a href="http://www.jdclayton.com/blueprints_compress_a_walkthrough.html"><em>compressor</em></a> de Blueprint en est un parfait exemple.<br />
Il permet de construire une version de Blueprint adaptée à son besoin, inclut des feuilles de notre choix et compresse le tout en un seul fichier prêt à la mise en production.</p>
<p>Maintenant l&#8217;avantage d&#8217;un <em>framework</em> c&#8217;est qu&#8217;une <strong>communauté</strong> ou un groupe de personnes compétentes en ont la gestion. Ces mainteneurs produisent une documentation, des spécifications et un code suffisamment compréhensible à lire. Ce n&#8217;est pas forcément le cas de Joe le développeur à qui on aura demandé 36 choses en même temps.<br />
Je fais davantage confiance à un outil éprouvé avec succès sur des milliers de projets qu&#8217;un outil développé sur un coin de bureau, malgré toute la bonne volonté de son concepteur.<br />
C&#8217;est également un risque certes mais un bon outil délaissé aura tout de même le mérite de fonctionner &#8230; et d&#8217;avoir davantage de chances de trouver un repreneur.</p>
<p>Une remarque intéressante a également émergé de l&#8217;atelier : faut-il utiliser un <em>framework</em> <acronym title="Cascading Style Sheets">CSS</acronym> avant ou après que la créa graphique ait été établie ?<br />
Je réitère ma réponse : <strong>l&#8217;idéal est que tout soit pris en charge le plus tôt possible</strong>. Autrement dit, intégrer les contraintes du <em>framework</em> dès la conception graphique est un gros atout. Le découpage de la maquette n&#8217;en sera que facilité et ça évitera tout bricolage.<br />
Certains outils l&#8217;ont d&#8217;ailleurs bien compris en proposant des supports pour graphistes au format PSD, Visio, Fireworks etc.</p>
<div id="attachment_1213" class="wp-caption aligncenter" style="width: 310px"><a href="http://case.oncle-tom.net/images/2008/11/960-sketch-sheets.png"><img class="size-medium wp-image-1213" title="Feuilles de dessin pour 960 Grid System" src="http://case.oncle-tom.net/images/2008/11/960-sketch-sheets-300x232.png" alt="Feuilles de dessin pour 960 Grid System" width="300" height="232" /></a><p class="wp-caption-text">Feuilles de dessin pour 960 Grid System</p></div>
<h3>Conclusion</h3>
<p>Quoiqu&#8217;il en soit, les <em>frameworks</em> <acronym title="Cascading Style Sheets">CSS</acronym> sont à mon avis promis à un bel avenir dès lors que les critères d&#8217;industrialisation auront débarqué au sein des agences Web.</p>
<p>Aujourd&#8217;hui une petite agence a tout à gagner à maîtriser de tels outils et à annoncer qu&#8217;elle développera mieux, plus vite et moins cher. Le prix ne fait pas tout : ce sont les <strong>outils et la qualité du développement</strong>. Tous les <em>frameworks</em> cités sont également des logiciels libres.</p>
<p>J&#8217;espère que cet aperçu rapide aura ouvert les yeux à certains d&#8217;entre vous. Je suis preneur de vos retours, surtout en entreprise. Ça vaut également pour celles et ceux qui ne sont toujours pas convaincu de l&#8217;intérêt des <em>frameworks</em> <acronym title="Cascading Style Sheets">CSS</acronym> <img src='http://case.oncle-tom.net/wp-includes/images/smilies/icon_wink.gif' alt=';-)' class='wp-smiley' /> </p>
<p><strong>Remarque</strong> : il y avait 2 ateliers complémentaires à Paris-Web :</p>
<ul>
<li><a href="http://css.mammouthland.net/parisweb/optimisation-css.php">Optimiser ses <acronym title="Cascading Style Sheets">CSS</acronym></a></li>
<li><a href="http://romy.tetue.net/spip.php?article555">Cascade et héritage : concevoir, organiser, optimiser et maintenir ses feuilles de style</a></li>
</ul>]]></content:encoded>
			<wfw:commentRss>http://case.oncle-tom.net/2008/developpement-efficace-frameworks-css/feed/</wfw:commentRss>
		<slash:comments>25</slash:comments>
		</item>
		<item>
		<title>Conventions de programmation : la nécessaire maturité</title>
		<link>http://case.oncle-tom.net/2008/conventions-de-programmation-necessaire-maturite/</link>
		<comments>http://case.oncle-tom.net/2008/conventions-de-programmation-necessaire-maturite/#comments</comments>
		<pubDate>Wed, 23 Jul 2008 05:00:04 +0000</pubDate>
		<dc:creator>Oncle Tom</dc:creator>
				<category><![CDATA[Développement Web]]></category>
		<category><![CDATA[bonnes pratiques]]></category>
		<category><![CDATA[code]]></category>
		<category><![CDATA[coding standards]]></category>
		<category><![CDATA[conventions]]></category>
		<category><![CDATA[css]]></category>
		<category><![CDATA[eclipse]]></category>
		<category><![CDATA[html]]></category>
		<category><![CDATA[Javascript]]></category>
		<category><![CDATA[pear]]></category>
		<category><![CDATA[php]]></category>
		<category><![CDATA[phpdoc]]></category>
		<category><![CDATA[symfony]]></category>
		<guid isPermaLink="false">http://case.oncle-tom.net/?p=1014</guid>
		<description><![CDATA[Tout développeur, que ce soit à l&#8217;école ou en apprenant sur le tas, écrit du code. J&#8217;espère n&#8217;avoir perdu personne à ce stade de l&#8217;explication Inconsciemment on cherchera à utiliser un style d&#8217;écriture avec lequel on se sent à l&#8217;aise, qu&#8217;on pourra et saura relire facilement et dans le meilleur des cas, qui pourra être [...]]]></description>
			<content:encoded><![CDATA[<p style="text-align:center"><img class="size-full wp-image-1028" title="Exemple de code PHP" src="http://case.oncle-tom.net/images/2008/07/sample-php-code.png" alt="Exemple" width="500" height="184" /></p>
<p>Tout développeur, que ce soit à l&#8217;école ou en apprenant sur le tas, écrit du code. J&#8217;espère n&#8217;avoir perdu personne à ce stade de l&#8217;explication <img src='http://case.oncle-tom.net/wp-includes/images/smilies/icon_wink.gif' alt=';-)' class='wp-smiley' /> </p>
<p><strong>Inconsciemment on cherchera à utiliser un style d&#8217;écriture avec lequel on se sent à l&#8217;aise</strong>, qu&#8217;on pourra et saura relire facilement et dans le meilleur des cas, qui pourra être relu par une autre personne sans avoir à engager d&#8217;interprète.</p>
<p>Tout développeur tend donc à utiliser des <a href="http://fr.wikipedia.org/wiki/Convention_de_nommage_(programmation)">conventions de programmation</a> (<em>coding standards</em>), que ce soit en <acronym title="HyperText Markup Language">HTML</acronym>, <acronym title="Pre-Hypertext Processing">PHP</acronym>, <acronym title="Cascading Style Sheets">CSS</acronym>, JavaScript ou même en Cobol. Et <strong>utiliser des conventions, c&#8217;est bien</strong> !</p>
<p><span id="more-1014"></span></p>
<h3>Quelle convention de nommage adopter ?</h3>
<p>Avant de choisir une convention, encore faudrait-il savoir quelles conventions existent :</p>
<ul>
<li>pas de convention</li>
<li><a href="http://fr.wikipedia.org/wiki/Notation_hongroise">convention hongroise</a></li>
<li><a href="http://pear.php.net/manual/fr/standards.php">convention PEAR</a></li>
<li><a href="http://www.symfony-project.org/book/1_0/02-Exploring-Symfony-s-Code">convention symfony</a></li>
<li><a href="http://framework.zend.com/manual/fr/coding-standard.html">convention Zend Framework</a></li>
<li><a href="http://codex.wordpress.org/WordPress_Coding_Standards">convention WordPress</a> (que j&#8217;abhorre)</li>
<li>etc.</li>
</ul>
<p>Autant dire qu&#8217;il y a de tout et pour tous les goûts.<br />
Ce qu&#8217;il faut retenir d&#8217;<strong>une convention c&#8217;est qu&#8217;elle explicite des règles de développement</strong> :</p>
<ul>
<li>sur le nommage des éléments</li>
<li>sur l&#8217;indentation des éléments</li>
<li>sur les structures de contrôle (if, else, tout ça quoi)</li>
<li>sur la syntaxe des commentaires</li>
<li>sur la syntaxe de la documentation (le code auto-documenté c&#8217;est bon !)</li>
<li>sur l&#8217;organisation des fichiers, éventuellement</li>
</ul>
<p>C&#8217;est pour ça que partir sur une <strong>convention parfaite sur le papier mais inapplicable est une vaste fumisterie</strong>. L&#8217;idéal étant de pouvoir reprendre du code dans un projet sans avoir eu besoin de lire la documentation pour en comprendre l&#8217;organisation.</p>
<p>Mon conseil : <strong>essayez, choisissez</strong> mais ne prenez pas non plus trop laxiste en terme de notation.<br />
Une chose est sure : quand on a essayé une belle</p>
<h3>Mes conventions de nommage en <acronym title="Pre-Hypertext Processing">PHP</acronym></h3>
<p style="text-align:center"><a href="http://case.oncle-tom.net/images/2008/07/eclipse-php-code-sample.png"><img class="size-medium wp-image-1022" title="Exemple de code PHP dans Eclipse" src="http://case.oncle-tom.net/images/2008/07/eclipse-php-code-sample-300x207.png" alt="Exemple de code PHP dans Eclipse" width="300" height="207" /></a></p>
<p>J&#8217;avoue, la notation utilisée dans <a href="http://www.symfony-project.org/">symfony</a> m&#8217;a tellement plu que je la réutilise quasiment partout. Ci-dessus, une illustration montrant du code pour un <a href="http://case.oncle-tom.net/code/wordpress/">plugin WordPress</a> (en <acronym title="Pre-Hypertext Processing">PHP</acronym> 4 malheureusement &#8230;). Elle en présente un bon aperçu.</p>
<h4>Notation</h4>
<p>J&#8217;utilise UpperCamelCase pour le nommage des classes <em>sauf</em> s&#8217;il y a un préfixe qui, lui, reste en minuscule.<br />
<em>Exemples</em> : <code>class AmazonWidgetsShortcodes</code>, <code>class sfUploader</code>.</p>
<p>Pour ce qui est méthodes de classes, j&#8217;utilise lowerCamelCase. Comme ça on sait qu&#8217;on reste dans un objet et c&#8217;est pas plus mal.</p>
<p>Enfin, pour les fonctions orphelines, <em>helpers</em> &amp; cie, c&#8217;est tout en minuscule séparé par des underscore (un nom particulier à ça ? <em>lowered_and_underscored</em> ? <img src='http://case.oncle-tom.net/wp-includes/images/smilies/icon_wink.gif' alt=';-)' class='wp-smiley' /> )<br />
<em>Exemple</em> : <code>add_filter()</code></p>
<h4>Indentation</h4>
<p>Dans l&#8217;indentation il y a 2 camps : celui des espaces et celui des tabulations.</p>
<p>J&#8217;ai suivi celui des <strong>espaces</strong> pour une simple et bonne raison : 1 tabulation a une taille différente selon les éditeurs, que ça soit votre IDE, votre shell ou n&#8217;importe quel logiciel de texte. L&#8217;idéal est d&#8217;avoir un rendu identique dans tous les éditeurs sans paramétrage.</p>
<p>En revanche, là encore je suis mais j&#8217;aime, je suis sur une <strong>tabulation à 2 espaces</strong> : c&#8217;est bête mais je trouve ça plus esthétique et on arrive moins rapidement à la limite de 80 caractères.</p>
<p>Cette &laquo;&nbsp;limite&nbsp;&raquo; n&#8217;est que virtuelle mais ouvrez un terminal, 80 lignes par défaut. C&#8217;est plus confortable de rester en-dessous de ce nombre. Ceci dit je fais quelques exceptions, des fois <img src='http://case.oncle-tom.net/wp-includes/images/smilies/icon_wink.gif' alt=';-)' class='wp-smiley' /> </p>
<h4>Structures de contrôle</h4>
<p>On pourrait résumer à <cite>1 ligne = 1 action</cite> et 2 types d&#8217;utilisation.</p>
<p>Tout d&#8217;abord les structures dans le code à proprement parler :</p>
<ul>
<li>un espace entre l&#8217;opérateur et la parenthèse ouvrante</li>
<li>un retour à la ligne à chaque accolade</li>
<li>pas d&#8217;espaces dans les lignes vides (résidus d&#8217;indentation)</li>
<li>systématiquement les accolades, même en cas de ligne unique après l&#8217;opérateur</li>
<li>opérateur ternaire quand ça reste simple, pas trop long et plus lisible</li>
</ul>
<p>Côté templating en revanche j&#8217;utilise la <a href="http://fr.php.net/manual/fr/control-structures.alternative-syntax.php">syntaxe alternative de <acronym title="Pre-Hypertext Processing">PHP</acronym></a> à raison d&#8217;un opérateur par ligne :</p>
<pre><code class="php">&lt;ol class="posts"&gt;
&lt;?php foreach($posts as $post): ?&gt;
  &lt;li id="post-&lt;?php echo $post-&gt;getId() ?&gt;"&gt;
    &lt;a href="&lt;?php $post-&gt;getPermalink() ?&gt;"&gt;
      &lt;?php echo $post-&gt;getTitle() ?&gt;
    &lt;/a&gt;
  &lt;/li&gt;
&lt;?php endforeach ?&gt;
&lt;/ol&gt;</code></pre>
<h4>Syntaxe de la documentation</h4>
<p>Enfin, pour terminer sur la partie <acronym title="Pre-Hypertext Processing">PHP</acronym>, <a href="http://www.phpdoc.org/">PHPDoc</a> est surpuissante en plus d&#8217;être simple à utiliser. Comble du bonheur, sa syntaxe est réutilisable dans d&#8217;autres langages.</p>
<p>PHPDoc est le principe du <strong>code autodocumenté</strong> :</p>
<ol>
<li>vous commentez votre code avec la syntaxe PHPDoc</li>
<li>vous générez sa documentation avec le programme PHPDoc (en <acronym title="HyperText Markup Language">HTML</acronym>, <acronym title="Portable Document Format">PDF</acronym> etc.)</li>
</ol>
<p>L&#8217;idéal est de <strong>documenter en même temps qu&#8217;on produit le code</strong>. Par principe on revient rarement sur son propre code juste pour le loisir de le décrire, par manque de temps ou par flemme.</p>
<h3>Mes conventions de nommage en JavaScript</h3>
<p style="text-align:center"><a href="http://case.oncle-tom.net/images/2008/07/eclipse-javascript-code-sample.png"><img class="size-medium wp-image-1021" title="Exemple de code JavaScript dans Eclipse" src="http://case.oncle-tom.net/images/2008/07/eclipse-javascript-code-sample-300x288.png" alt="Exemple de code JavaScript dans Eclipse" width="300" height="288" /></a></p>
<p>Ne vous inquiétez pas, je ne vais pas tout recommencer pour JavaScript <img src='http://case.oncle-tom.net/wp-includes/images/smilies/icon_wink.gif' alt=';-)' class='wp-smiley' />  Je suis à peu près la même logique qu&#8217;en <acronym title="Pre-Hypertext Processing">PHP</acronym> à part pour les accolades.</p>
<p>En effet si je conserve un comportement similaire pour les structures de contrôles (1 accolade par ligne) :</p>
<ul>
<li>je ne fais pas de retour à la ligne sur les accolades/parenthèse ouvrante d&#8217;une fonction/objet anonyme</li>
<li>je ne fais pas de retour à la ligne après une accolade/parenthèse fermante s&#8217;il y a une virgule ou parenthèse après</li>
</ul>
<pre><code class="javascript">var OncleTom = {
  age:      25,
  pensee:   function(){
    return this.age * Math.random()
  }
};</code></pre>
<h3>Mes conventions de nommage en <acronym title="Cascading Style Sheets">CSS</acronym></h3>
<p style="text-align:center"><img class="aligncenter size-full wp-image-879" title="Folding en CSS" src="http://case.oncle-tom.net/images/2008/02/css-folding.png" alt="" width="500" height="138" /></p>
<p>Inutile de paraphraser ce que j&#8217;ai déjà écris dans mon article sur les <a href="http://case.oncle-tom.net/2008/02/26/bonnes-pratiques-codage-css/">bonnes pratiques de codage <acronym title="Cascading Style Sheets">CSS</acronym></a>.</p>
<p>Deux lectures en une oui <img src='http://case.oncle-tom.net/wp-includes/images/smilies/icon_wink.gif' alt=';-)' class='wp-smiley' /> </p>
<h3>Conclusion</h3>
<p>Bon au final on voit que ce n&#8217;est pas si compliqué que ça d&#8217;apporter un brin de rigueur.<br />
On pourra même s&#8217;amuser à compléter le tout par la disposition des méthodes et fonctions d ans un fichier par ordre alphabétique (j&#8217;en connais un que ça fera sourire <img src='http://case.oncle-tom.net/wp-includes/images/smilies/icon_wink.gif' alt=';-)' class='wp-smiley' /> ).</p>
<p>Les vues <em>Outline</em> fournissent un plan du code et certains logiciels ne semblent pas disposer d&#8217;une fonction de tri. Et au cas où un jour vous n&#8217;auriez pas votre IDE favori sous le nez, ça ne mange pas de pain de fonctionner ainsi.</p>
<p style="text-align:center"><img class="size-full wp-image-1020" title="Plan de code dans Eclipse (Outline)" src="http://case.oncle-tom.net/images/2008/07/eclipse-outline.png" alt="Plan de code dans Eclipse (Outline)" width="334" height="288" /></p>
<p>Que l&#8217;on travaille seul à plusieurs, et à plus fortes raison dans ce dernier cas, l&#8217;utilisation de notations et conventions est un gage de qualité. Ça rend le travail plus facilement interopérable avec d&#8217;autres développeurs, plus facile à relire, plus facile à maintenir.</p>
<p><strong>Ça n&#8217;empêchera jamais des bugs</strong> ou de sortir du mauvais code mais c&#8217;est ça, c&#8217;est une autre histoire.</p>
<p>Enfin, j&#8217;aimerais terminer cet article en écrivant qu&#8217;il a fait l&#8217;objet d&#8217;une <a href="http://blog.damienalexandre.fr/index.php?post/2008/07/19/Mes-conventions-de-programmation">chaîne par le Padawan PHPiste Damien Alexandre</a>. C&#8217;était l&#8217;occasion de faire une réponse qui passe inaperçue <img src='http://case.oncle-tom.net/wp-includes/images/smilies/icon_wink.gif' alt=';-)' class='wp-smiley' /> </p>
<p>Ça ne m&#8217;empêchera en revanche pas de refiler la patate chaude à <a href="http://prendreuncafe.com/blog/">NicoDePrendreUnCafé</a>, de tenter d&#8217;insuffler de l&#8217;activité au blog de <a href="http://lacot.org/blog">Xavier Lacot</a>, de Spipifier <a href="http://www.gasteroprod.com">Gastero Prod</a>, d&#8217;extirper une technique ninja pyjama à <a href="http://shiii.org/">remouk</a> et pourquoi pas lire avec attention l&#8217;avis pythonien de <a href="http://www.biologeek.com/journal/">David Larlet</a> ?</p>
<p>Et <em>just for fun</em>, un petit coup d&#8217;électrode à un de mes futurs étudiants, <a href="http://blog.thierry.poinot.fr/">Thierry Poinot</a>.</p>]]></content:encoded>
			<wfw:commentRss>http://case.oncle-tom.net/2008/conventions-de-programmation-necessaire-maturite/feed/</wfw:commentRss>
		<slash:comments>19</slash:comments>
		</item>
		<item>
		<title>Microformats : comment microformater du contenu déjà existant ?</title>
		<link>http://case.oncle-tom.net/2008/microformats-comment-microformater-du-contenu-deja-existant/</link>
		<comments>http://case.oncle-tom.net/2008/microformats-comment-microformater-du-contenu-deja-existant/#comments</comments>
		<pubDate>Thu, 03 Apr 2008 21:07:42 +0000</pubDate>
		<dc:creator>Oncle Tom</dc:creator>
				<category><![CDATA[Développement Web]]></category>
		<category><![CDATA[Standards du Web]]></category>
		<category><![CDATA[adr]]></category>
		<category><![CDATA[atom]]></category>
		<category><![CDATA[clever age]]></category>
		<category><![CDATA[code]]></category>
		<category><![CDATA[css]]></category>
		<category><![CDATA[firefox]]></category>
		<category><![CDATA[google maps]]></category>
		<category><![CDATA[hatom]]></category>
		<category><![CDATA[hcalendar]]></category>
		<category><![CDATA[hcard]]></category>
		<category><![CDATA[logiciels libres]]></category>
		<category><![CDATA[microformats]]></category>
		<category><![CDATA[rss]]></category>
		<category><![CDATA[tag]]></category>
		<category><![CDATA[wikia]]></category>
		<category><![CDATA[xhtml]]></category>
		<category><![CDATA[xoxo]]></category>
		<category><![CDATA[yahoo]]></category>
		<guid isPermaLink="false">http://case.oncle-tom.net/2008/04/03/microformats-comment-microformater-du-contenu-deja-existant/</guid>
		<description><![CDATA[Nous avions dressé un panorama des microformats dans un précédent article intitulé « microformats : republier et donner du sens aux contenus ». Nous avions notamment conclu que leur intégration était rapide, peu coûteuse et surtout bénéfique tant pour le visiteur que pour la visibilité du contenu. Nous nous intéresserons cette fois-ci à une partie [...]]]></description>
			<content:encoded><![CDATA[
<p style="text-align:center"><img src="http://case.oncle-tom.net/images/2007/07/logo-microformats.gif" alt="Microformats logo" /></p>
<p>Nous avions dressé un panorama des microformats dans un précédent article intitulé « <a href="http://case.oncle-tom.net/2008/01/29/microformats-republier-donner-sens-aux-contenus/">microformats : republier et donner du sens aux contenus</a> ». Nous avions notamment conclu que leur<strong> intégration était rapide, peu coûteuse et surtout bénéfique</strong> tant pour le visiteur que pour la visibilité du contenu.</p>
<p>Nous nous intéresserons cette fois-ci à une partie plus pratique des microformats : leur <strong>intégration</strong>. Toutefois ce rapide apprentissage sera didactique puisque nous apprendrons à identifier visuellement quels contenus d’une page peuvent être microformatés mais aussi comment microformater du code <acronym title="HyperText Markup Language">HTML</acronym> déjà existant.<br />
<span id="more-896"></span></p>
<h3>Des sites déjà microformatés</h3>
<p>Intéressons-nous toutefois à des sites ayant déjà microformaté leurs contenus. Nous pourrons ainsi éveiller notre curiosité et préparer le travail de réflexion de la prochaine étape.</p>
<p><strong><a href="http://maps.google.fr/?q=clever-age&amp;near=paris">Exemple avec Google Maps</a></strong> :</p>
<p style="text-align:center"><img src="http://case.oncle-tom.net/images/2008/04/microformats-sites-google-maps.jpg" alt="Microformats sur Google Maps" /></p>
<p>Google Maps est un service de recherche cartographique accessible via un simple navigateur Web. Le moteur donne un accès à des recherches de lieux, de calculs d&#8217;itinéraires mais aussi d&#8217;emplacement d&#8217;entreprises.</p>
<p>Le support des microformats sur Google Maps est relativement léger mais suffisant pour être utile.<br />
Contrairement à ce que l&#8217;on aurait pu penser, Google n&#8217;a pas intégré le <a href="http://microformats.org/wiki/geo">microformat geo</a> pour exporter les coordonnées GPS d&#8217;un point. La société s&#8217;est concentrée sur les données personnelles au moyen de deux microformats combinés :</p>
<ul>
<li> <a href="http://microformats.org/wiki/hcard">microformat hCard</a> (correspond à la réunion des encadrés bleu et vert)</li>
<li> <a href="http://microformats.org/wiki/adr">microformat adr</a> (correspond à l&#8217;encadré vert uniquement)</li>
</ul>
<p>Cette combinaison facilite l&#8217;extraction des adresse postales et des entités (individus ou entreprises).</p>
<p><strong><a href="http://upcoming.yahoo.com/search/?loc=paris">Exemple avec Yahoo ! Upcoming</a></strong> :</p>
<p style="text-align:center"><img src="http://case.oncle-tom.net/images/2008/04/microformats-sites-yahoo-upcoming.jpg" alt="Microformats sur Yahoo! Upcoming" /></p>
<p>Yahoo ! Upcoming est un service gratuit cataloguant tous les évènements à venir par pays, ville, date et même par catégories (cinéma, concerts, expositions etc.).</p>
<p>Le microformat par excellence à adopter était bien évidemment le <a href="http://microformats.org/wiki/hcalendar">microformat hCalendar</a>. Chaque occurence microformatée est représentée par un rectangle vert et peut contenir ces différents attributs, entre autre :</p>
<ul>
<li> date de début de l&#8217;évènement</li>
<li> date de fin de l&#8217;évènement</li>
<li> titre de l&#8217;évènement</li>
<li> description de l&#8217;évènement</li>
<li> le lieu de l&#8217;évènement (sous forme d&#8217;adresse complète ou pas)</li>
<li> une <acronym title="Uniform Resource Locator">URL</acronym> menant à un descriptif plus approfondi de l&#8217;évènement</li>
</ul>
<p>Ce microformatage permet d&#8217;aller au-delà d&#8217;une lecture classique puisque de manière simple, elle permet au visiteur de récupérer les évènements qui l&#8217;intéresse pour les ajouter à son gestionnaire de temps favoris, qu&#8217;il soit logiciel ou en ligne.</p>
<h3>Identifier visuellement les microformats à intégrer</h3>
<p>Identifier des microformats déjà implémenté est assez simple avec les outils adéquats. En revanche pour décider de microformater du contenu, deux outils sont indispensables :</p>
<ul>
<li> la documentation des microformats pour savoir <strong>quoi implémenter</strong></li>
<li> un peu de jugeotte pour savoir <strong>comment implémenter</strong> <img src='http://case.oncle-tom.net/wp-includes/images/smilies/icon_wink.gif' alt=';-)' class='wp-smiley' /> </li>
</ul>
<p>Avec un peu de pratique et de connaissance des différents microformats, il ne faut pas plus de 5 à 10 minutes pour identifier les contenus microformatables. La difficulté d&#8217;intégration dépendra uniquement de la structure technique affichant les données : plus elle sera complexe, plus le microformatage pourra être long &#8230; au même titre que toute autre modification basique.</p>
<p><strong><a href="http://re.search.wikia.com/search#clever%20age">Exemple avec Wikia Search</a></strong> :</p>
<p style="text-align:center"><img src="http://case.oncle-tom.net/images/2008/04/microformats-tomicroformat-wikia-search.jpg" alt="Microformats sur Wikia Search" /></p>
<p>Wikia Search est un moteur de recherche lancé au tout début de l&#8217;année 2008 par un des fondateurs de l&#8217;encyclopédie en ligne Wikipédia. Ce moteur en reprend d&#8217;ailleurs le principe du wiki pour contribuer à l&#8217;élaboration et la notation de meilleurs résultats.</p>
<p>Il est d&#8217;ailleurs étonnant de voir qu&#8217;aucun microformat ne soit présent malgré de tels objectifs. La capture d&#8217;écran ci-dessus découpe la page en 3 zones microformatables distinctes :</p>
<ol>
<li> le lien sur logo aurait pu se voir agrémenter d&#8217;un <a href="http://microformats.org/wiki/rel-home">rel-home</a> pour signifier un retour vers la page d&#8217;accueil ;</li>
<li> les résultats auraient pu quant à eux embarquer :
<ul>
<li> le <a href="http://microformats.org/wiki/hatom">microformat hAtom</a> pour faciliter la syndication de contenu et l&#8217;extraction des résultats.</li>
<li> le <a href="http://microformats.org/wiki/hreview">microformat hReview</a> ou <a href="http://microformats.org/wiki/vote-links">VoteLinks</a> sur les encadrés orangés identifiant les zones de votes.</li>
</ul>
</li>
<li> enfin le <a href="http://microformats.org/wiki/hcard">microformat hCard</a> aurait été le bienvenu sur la liste des résultats correspond à des personnes.</li>
</ol>
<p>On peut constater que plus il y a d&#8217;emplacement représentant des contenus différents sur une page, plus on a de chances qu&#8217;un microformat corresponde.</p>
<p><strong><a href="http://www.clever-age.com/">Exemple avec Clever Age</a></strong> :</p>
<p style="text-align:center"><img src="http://case.oncle-tom.net/images/2008/04/microformats-tomicroformat-cleverage.jpg" alt="Microformats sur Clever Age" /></p>
<p>J&#8217;ai dénombré pas moins de 5 zones pouvant accueillir des microformats :</p>
<ol>
<li> les dernières actualités pourraient utiliser le <a href="http://microformats.org/wiki/hatom">microformat hAtom</a>. Un flux <acronym title="Really Simple Syndication">RSS</acronym> est déjà disponible sur la page mais ce serait offrir un chemin de traverse pour les visiteurs et les moteurs d&#8217;indexation ;</li>
<li> le <a href="http://microformats.org/wiki/hcalendar">microformat hCalendar</a> aiderait à la réutilisation des données dans les gestionnaires de temps. Imaginez un chef d&#8217;entreprise affairé désireux de transmettre à ses collaborateurs une ressource contenant toutes les informations de leur future formation : peu d&#8217;effort et un gain de communication ;</li>
<li> ajouter facilement Clever Age dans votre carnet de contacts et de prestataires serait également facilité si le <a href="http://microformats.org/wiki/hcard">microformat hCard</a> redistribuait le nom et les moyens de contact de la société ;</li>
<li> en complément au moyen de contact, l&#8217;emplacement géographique des agences serait à portée de clic avec le <a href="http://microformats.org/wiki/geo">microformat geo</a>. Après tout, Google Maps proposera peut-être un jour d&#8217;importer des <acronym title="Uniform Resource Locator">URL</acronym> microformatée en plus des fichiers KMZ (Google Earth) <img src='http://case.oncle-tom.net/wp-includes/images/smilies/icon_wink.gif' alt=';-)' class='wp-smiley' />  ;</li>
<li> enfin, le microformatage de la dernière partie dépend de ce qu&#8217;on aimerait redistribuer :
<ul>
<li> le <a href="http://microformats.org/wiki/hatom">microformat hAtom</a> pour offrir 3 flux de syndication mais le peu d&#8217;éléments (2 à chaque fois) tende à infirmer la pertinence de ce microformat dans le cas présent ;</li>
<li> le <a href="http://microformats.org/wiki/xoxo">microformat XOXO</a> est adapté à décrire des types de contenus embarqués dans une page ; ici des flux <acronym title="Really Simple Syndication">RSS</acronym>. Il serait à placer sur chaque lien pointant vers les flux <acronym title="Really Simple Syndication">RSS</acronym> ;</li>
<li> le <a href="http://microformats.org/wiki/xfolk">microformat Xfolk</a> est adapté aux collections d&#8217;<acronym title="Uniform Resource Locator">URL</acronym> plus communément appelés « favoris » ou « marque-pages »</li>
</ul>
</li>
</ol>
<p>Avec ce dernier exemple, nous venons de voir que le microformatage était facilement adaptable à un site Web de société. Dans ce cas précis, il y a énormément de contenu republiable mais pas systématiquement de manière pertinente.</p>
<h3>Intégrer les microformats dans du (X)<acronym title="HyperText Markup Language">HTML</acronym></h3>
<p>Les précédents exemples, sur de l&#8217;existant et ce qui pourrait exister, avaient pour but de former notre esprit à reconnaitre des zones susceptibles d&#8217;être microformatées.</p>
<p>La difficulté de l&#8217;exercice est d&#8217;ajouter du balisage sans altérer la présentation actuelle. Je traiterai du site de Clever Age dont nous avons parlé précédemment.</p>
<p><strong>Microformater des données d&#8217;entités</strong></p>
<p>Voici le code de départ, repris tel quel :</p>
<pre><code>Clever Age - Siège social : 01.53.34.66.10</code></pre>
<p>Comme nous avons pu le voir, la gestion d&#8217;identités passe par le <a href="http://microformats.org/wiki/hcard">microformat hCard</a> :</p>
<pre><code>&lt;span class="vcard"&gt;
&lt;span class="fn org"&gt;Clever Age&lt;/span&gt; - Siège social : &lt;span class="tel"&gt;&lt;span class="value"&gt;01.53.34.66.10&lt;/span&gt;&lt;/span&gt;
&lt;/span&gt;</code></pre>
<p>La balise <em>span</em> est une balise en-ligne neutre au sens où &#8230; n&#8217;en a pas justement. <em>div</em> est son pendant de type bloc.</p>
<p><strong>Microformater des ressources syndiquées</strong><br />
Voici le code de départ (simplifié par rapport à l&#8217;exemple afin de réduire le code à lire) :</p>
<pre><code>&lt;dl&gt;
&lt;dt&gt;&lt;a href="/rss/blog.xml"&gt;derniers billets du blog&lt;/a&gt;&lt;/dt&gt;
&lt;dd&gt;...&lt;/dd&gt;
&lt;dt&gt;&lt;a href="/rss/publications.xml"&gt;dernières publications&lt;/a&gt;&lt;/dt&gt;
&lt;dd&gt;...&lt;/dd&gt;
&lt;dt&gt;&lt;a href="/rss/cleverlink.xml"&gt;derniers Clever Links&lt;/a&gt;&lt;/dt&gt;
&lt;dd&gt;...&lt;/dd&gt;
&lt;/dl&gt;</code></pre>
<p>Le <a href="http://microformats.org/wiki/xoxo">microformat XOXO</a> nous permet de définir une liste d&#8217;éléments en fonction des <a href="http://microformats.org/wiki/xoxo#The_XOXO_Document_Type">modules <acronym title="eXtensible HyperText Markup Language">XHTML</acronym></a> :</p>
<pre><code>&lt;dl class="xoxo"&gt;
&lt;dt&gt;&lt;a href="/rss/blog.xml" rel="feed" type="text/xml"&gt;derniers billets du blog&lt;/a&gt;&lt;/dt&gt;
&lt;dd&gt;...&lt;/dd&gt;
&lt;dt&gt;&lt;a href="/rss/publications.xml" rel="feed" type="text/xml"&gt;dernières publications&lt;/a&gt;&lt;/dt&gt;
&lt;dd&gt;...&lt;/dd&gt;
&lt;dt&gt;&lt;a href="/rss/cleverlink.xml" rel="feed" type="text/xml"&gt;derniers Clever Links&lt;/a&gt;&lt;/dt&gt;
&lt;dd&gt;...&lt;/dd&gt;
&lt;/dl&gt;</code></pre>
<p>Le microformatage a été rendu possible uniquement en utilisant de manière standardisée des attributs définis par <acronym title="eXtensible HyperText Markup Language">XHTML</acronym>.<br />
Malgré cet aspect de simplicité, il faut s&#8217;investir dans la compréhension des spécifications <acronym title="eXtensible HyperText Markup Language">XHTML</acronym>. Ce n&#8217;est un problème que pour les personnes produisant du code <acronym title="eXtensible HyperText Markup Language">XHTML</acronym> non-conforme.</p>
<h3>Valider l&#8217;intégration des microformats</h3>
<p>La question qui se pose toujours après avoir produit un code quelconque c&#8217;est comment le tester ? Il existe à l&#8217;heure actuelle trois outils gratuits :</p>
<ul>
<li> la relecture manuelle avec la documentation à côté <img src='http://case.oncle-tom.net/wp-includes/images/smilies/icon_wink.gif' alt=';-)' class='wp-smiley' /> </li>
<li> l&#8217;<a href="https://addons.mozilla.org/firefox/addon/4106">extension Operator pour Firefox</a>. Elle n&#8217;est toutefois pas complète et ne permettra pas de tester tous les microformats existants. Cette extension propose dans ses options un <em>mode débogage</em> très utile ;</li>
<li> le service en ligne <a href="http://microformatique.com/optimus/">Optimus</a>. Ce service polyvalent est capable de retourner sous forme de flux <acronym title="eXtensible Markup Language">XML</acronym> ou JSON les microformats présents dans une page Web. Il propose également un validateur, toujours pour une page Web, décrivant les erreurs de microformatage.</li>
</ul>
<h3>Conclusion</h3>
<p>Il est difficile d&#8217;infuser en un article la manière de microformater du contenu. Fort heureusement la documentation des microformats abonde d&#8217;exemples en traitant des cas de figure concrets. Les spécifications restent là pour savoir quels sont les attributs, obligatoires ou pas.</p>
<p>De manière générale <strong>l&#8217;intégration des microformats est relativement aisée</strong> mais il existe 3 difficultés principales à l&#8217;intégration des microformats :</p>
<ul>
<li> difficultés liées à la <strong>plate-forme technique</strong> d&#8217;intégration ;</li>
<li> difficultés liées à un <strong>manque de données</strong>. Certaines spécifications exigent la présence de données particulières que l&#8217;on n&#8217;a pas ou que l&#8217;on ne peut afficher, rendant invalide le contenu ;</li>
<li> difficultés liées à un <strong>code <acronym title="HyperText Markup Language">HTML</acronym> désorganisé</strong>. L&#8217;abus de <em>div</em> et le non-respect de hiérarchie est une source de problèmes et si elle rend pénible l&#8217;intégration des microformats, elle pose problème à la maintenance du code et des <acronym title="Cascading Style Sheets">CSS</acronym>.</li>
</ul>
<p>Intégrer les microformats c&#8217;est finalement mener une <strong>réflexion sur la qualité du code produit</strong>. Un bon code, respectueux des standards et sémantique sera pérenne dans le temps, facilitera le microformatage et aura davantage de chances d&#8217;être accessible.</p>]]></content:encoded>
			<wfw:commentRss>http://case.oncle-tom.net/2008/microformats-comment-microformater-du-contenu-deja-existant/feed/</wfw:commentRss>
		<slash:comments>2</slash:comments>
		</item>
		<item>
		<title>Bonnes pratiques de codage CSS</title>
		<link>http://case.oncle-tom.net/2008/bonnes-pratiques-codage-css/</link>
		<comments>http://case.oncle-tom.net/2008/bonnes-pratiques-codage-css/#comments</comments>
		<pubDate>Tue, 26 Feb 2008 06:00:18 +0000</pubDate>
		<dc:creator>Oncle Tom</dc:creator>
				<category><![CDATA[Développement Web]]></category>
		<category><![CDATA[Standards du Web]]></category>
		<category><![CDATA[aptana]]></category>
		<category><![CDATA[bonnes pratiques]]></category>
		<category><![CDATA[code]]></category>
		<category><![CDATA[coding standards]]></category>
		<category><![CDATA[compresseur]]></category>
		<category><![CDATA[conventions]]></category>
		<category><![CDATA[css]]></category>
		<category><![CDATA[CSSDoc]]></category>
		<category><![CDATA[eclipse]]></category>
		<category><![CDATA[feuille de style]]></category>
		<category><![CDATA[indentation]]></category>
		<category><![CDATA[logiciels libres]]></category>
		<category><![CDATA[optimisation]]></category>
		<guid isPermaLink="false">http://case.oncle-tom.net/2008/02/26/bonnes-pratiques-codage-css/</guid>
		<description><![CDATA[J&#8217;y songeais mais l&#8217;article «De l&#8217;ordre, que diable !» m&#8217;a incité à m&#8217;y atteler plus tôt que prévu. Il n&#8217;y a en effet pas de méthode universelle pour programmer les CSS mais après plusieurs années d&#8217;expérience, j&#8217;ai affiné ma réflexion que je vous livre aujourd&#8217;hui. Où l&#8217;on parlera de présentation en 1 ligne, de CSSDoc [...]]]></description>
			<content:encoded><![CDATA[<p style="text-align:center"><img src="http://case.oncle-tom.net/images/2008/02/css-url-import.png" alt="CSS URL @import" /></p>
<p>J&#8217;y songeais mais l&#8217;article «<a href="http://blog.alsacreations.com/2008/02/21/411-de-lordre-que-diable-">De l&#8217;ordre, que diable !</a>» m&#8217;a incité à m&#8217;y atteler plus tôt que prévu.<br />
Il n&#8217;y a en effet <strong>pas de méthode universelle pour programmer</strong> les <acronym title="Cascading Style Sheets"><acronym title="Cascading Style Sheets">CSS</acronym></acronym> mais après plusieurs années d&#8217;expérience, j&#8217;ai affiné ma réflexion que je vous livre aujourd&#8217;hui.</p>
<p>Où l&#8217;on parlera de présentation en 1 ligne, de CSSDoc mais aussi de <em>folding</em> et d&#8217;indentation. <strong>En clair, tout plein de bonnes pratiques</strong> de développement en <acronym title="Cascading Style Sheets">CSS</acronym> qui vous feront gagner du temps, vous éviterons de la sueur et sentent bon le travail de qualité.<br />
<span id="more-878"></span></p>
<h3>Halte là et retour à la ligne !</h3>
<p>J&#8217;ai utilisé pendant un moment la technique dite du <a href="http://orderedlist.com/articles/single-line-css">single line <acronym title="Cascading Style Sheets">CSS</acronym></a> ; à savoir 1 ligne par déclaration.<br />
Je n&#8217;hésiterai pas une seconde à dire que je déconseille fortement cette écriture pour les raisons suivantes :</p>
<ul>
<li>si on souhaite gagner de la place, il y a des compresseurs (je recommande <a href="http://developer.yahoo.com/yui/compressor/">YUI Compressor</a>): pas la peine de réaliser ce travail nous-même ;</li>
<li>l&#8217;ajout de commentaires n&#8217;en est que plus compliqué : on a tous besoin de commenter certains passages cruciaux, notamment les <em>hacks</em> et autres <em>fix</em> ;</li>
<li>c&#8217;est tout bonnement illisible dès qu&#8217;on s&#8217;y replonge quelques semaines plus tard : imaginez pour quelqu&#8217;un qui n&#8217;a pas écrit le code !</li>
</ul>
<p>Les arguments avancés pour cette technique ne tiennent pas la route : <strong>on recherche avant tout la qualité et la facilité de relecture</strong>. Les quelques kilo-octets à perdre se feront par le biais de programmes. Ça ne doit certainement pas entraver le développement.</p>
<h3>L&#8217;auto-documentation avec la syntaxe CSSDoc</h3>
<p>Les habitués de Java connaissent <a href="http://java.sun.com/j2se/javadoc/">JavaDoc</a>.<br />
Les habitués de <acronym title="Pre-Hypertext Processing">PHP</acronym> connaissent <a href="http://www.phpdoc.org/">PHPDoc</a>.<br />
Les habitués de JavaScript connaissent <a href="http://code.google.com/p/jsdoc-toolkit/">JsDoc Toolkit</a> (dérivé de <a href="http://jsdoc.sourceforge.net/">JsDoc</a>).</p>
<p>Il était donc tout naturel que cette syntaxe de commentaires et d&#8217;auto-documentation soit utilisable en <acronym title="Cascading Style Sheets">CSS</acronym> avec <a href="http://cssdoc.net">CSSDoc</a>. Il n&#8217;y a pas d&#8217;inconvénient à l&#8217;utiliser, au contraire, que des avantages :</p>
<ul>
<li>la syntaxe permet d&#8217;<strong>harmoniser les commentaires</strong> sur les projets impliquant plusieurs développeurs ;</li>
<li>sa syntaxe <strong>facilite la relecture</strong> puisqu&#8217;elle est connue et employée dans de nombreux langages, autres que les <acronym title="Cascading Style Sheets">CSS</acronym> ;</li>
<li>l&#8217;<strong>auto-documentation du code</strong> c&#8217;est faciliter la génération d&#8217;une documentation externe en automatisant le processus ;</li>
<li>documenter en même temps que l&#8217;on écrit c&#8217;est <strong>comprendre ce que l&#8217;on fait</strong> et gagner du temps en évitant une écriture <em>a posteriori</em> ;</li>
</ul>
<p><a href="http://cssdoc.net/wiki/CssdocDraft">La syntaxe CSSDoc est documentée</a>,  aisément reconnaissable et est supportée par les meilleurs éditeurs <acronym title="Cascading Style Sheets">CSS</acronym>, dont <a href="http://www.aptana.com/">Aptana IDE</a> :</p>
<pre><code class="css">/**
 * @author Oncle Tom
 * @lastmodified Fev, 26 2008
 * @media print, screen
 * @site http://www.oncle-tom.net/
 */
/**
 * Redéfinition des balises <acronym title="HyperText Markup Language">HTML</acronym>
 *
 * @section html
 * @todo utiliser un reset.css conforme
 */
html,
*{
  margin: 0;
  padding: 0;
}</code></pre>
<h3>L&#8217;organisation hiérarchique</h3>
<p>J&#8217;ai pour habitude de travailler avec une seule feuille de style par media. Comme je travaille sur des <strong>hiérarchies thématiques</strong>, leur découpage en plusieurs fichiers ne consiste qu&#8217;à du copier/coller. On peut ainsi facilement passer d&#8217;une mono-feuille à du multi-feuilles. Je ne suis pas un fervent utilisateur de ces dernières car un code bien lisible sur une seule page n&#8217;est pas problématique.<br />
Je ne l&#8217;emploie que pour faciliter la réutilisation des <acronym title="Cascading Style Sheets">CSS</acronym> sur plusieurs projets partageant la même base graphique.</p>
<p>Concrètement, je vais d&#8217;abord organiser ma feuille pour redéfinir les éléments <acronym title="HyperText Markup Language">HTML</acronym> génériques puis créer autant de sections qu&#8217;il n&#8217;y en a sur ma page (navigation, contenu, navigation de contenu, contenus annexes etc.).<br />
Plus je m&#8217;avancerai dans la profondeur du balisage <acronym title="HyperText Markup Language">HTML</acronym> et plus j&#8217;indenterai mon code. Cette indentation fait penser à celle utilisée par le <a href="http://www.python.org/">langage Python</a>.</p>
<p>On pourrait résumer cette convention à ceci :</p>
<ul>
<li><strong>pas de tabulation</strong>, que des espaces pour avoir le même affichage peu importe les éditeurs</li>
<li>2 espaces par tabulation</li>
<li><strong>attributs classés par ordre alphabétique</strong> (même logique pour tout le monde)</li>
<li>une ligne d&#8217;espace entre les définitions ; pas de ligne entre les définitions proches/liées</li>
</ul>
<p>C&#8217;est simple et voici un exemple de résultat :</p>
<pre><code class="css">/**
 * Redéfinition du <acronym title="HyperText Markup Language">HTML</acronym>
 */
a{
  text-decoration: underline;
}
  a img{
    border: none;
  }
p{
  line-height: 1.5em;
}
  p img{
    margin: 1.5em
  }
  p img.top{
    margin-top: 0;
  }
/**
 * Contenu
 */
#main-content{
  clear: both;
  width: 100%;
}
  /**
   * Articles
   */
  #articles{
    margin-bottom: 2em;
  }
    #articles h2{
      font-size: 1.5em;
      font-weight: bold;
    }</code></pre>
<p>Les mieux organisés d&#8217;entre vous ajouteront un <strong>tri par fréquence d&#8217;utilisation</strong> afin d&#8217;optimiser les va-et-vient : on met en haut ce qu&#8217;on est susceptible de modifier le plus souvent, en bas ce à quoi on touchera rarement. Je ne vais pas jusque là mais ça reste envisageable, pertinent et surtout adapté aux plus chevronnés de l&#8217;optimisation.</p>
<h3>Autres conseils et astuces</h3>
<h4>Utilisation de raccourcis</h4>
<p>Les <em>aficionados</em> de l&#8217;optimisation et du gain de temps apprécieront cette méthode, s&#8217;ils ne l&#8217;utilisent pas déjà. J&#8217;ai pour habitude de placer des raccourcis dans mes sections pour <strong>faciliter l&#8217;utilisation d&#8217;une recherche via le raccourci clavier</strong> <kbd>Control+F</kbd>.<br />
Je préfixe chaque raccourci d&#8217;un symbole <kbd>=</kbd> :</p>
<pre><code class="css">/**
 * Liens d'évitement
 * =evitement
 */</code></pre>
<p>Je trouve cette méthode très pratique pour atteindre des portions de code. On évite ainsi un appel à la touche <kbd>Alt Gr</kbd> pour appuyer sur le # d&#8217;un ID (pour peu que l&#8217;on n&#8217;ait que des ID en tant que sections). On évite aussi les collisions de nom ou les recherches infructueuses pour cause de changement de nom de classes ou d&#8217;ID.</p>
<h4>De la sémantique, que diable !</h4>
<p>Je suis particulièrement attaché à cette bonne pratique d&#8217;autant plus qu&#8217;elle ne tombe pas forcément sous le sens de tout le monde : <strong>nommez vos ID et classes en fonction de leur <em>signification</em>, pas de leur <em>représentation</em></strong>. C&#8217;est la suite logique de la séparation fond et forme du <acronym title="HyperText Markup Language">HTML</acronym> et des <acronym title="Cascading Style Sheets">CSS</acronym>.</p>
<p><strong>Mauvaise sémantique</strong> :</p>
<pre><code class="css">.rouge{
  color: red;
}
#sidebar{
  /* ... */
}
#top-links{
  /* ... */
}</code></pre>
<p><strong>Bonne/meilleure sémantique</strong> :</p>
<pre><code class="css">.important{
  color: red;
}
#alternate-navigation{
  /* ... */
}
#main-links{
  /* ... */
}</code></pre>
<p><code>#sidebar</code> pourra être renommé différemment selon son contenu, selon que l&#8217;encart contienne des éléments de navigation supplémentaires, des informations utilisateur (<code>#user-content</code>) ou encore des widgets (<code>#widgets</code>).<br />
En conservant votre <acronym title="HyperText Markup Language">HTML</acronym> intact et en jouant sur les <acronym title="Cascading Style Sheets">CSS</acronym>, la <code>#sidebar</code> peut en effet se retrouver tout en bas, à l&#8217;horizontale. Aurez-vous toujours envie de l&#8217;appeler pareil ? Pas forcément. <strong>Un bon nommage est un nommage qui se conserve peu importe l&#8217;aspect de la présentation</strong>.</p>
<h4>Du choix de la langue</h4>
<p>Cette bonne pratique s&#8217;applique aussi bien aux <acronym title="Cascading Style Sheets">CSS</acronym> qu&#8217;à d&#8217;autres langages. Il faut partir du principe qu&#8217;<strong>il ne faut pas mélanger les langues dans le code</strong>, tant dans les commentaires que dans le nommage des classes et ID. <strong>Choisissez-une langue et restez avec</strong>.<br />
Certaines contraintes peuvent faciliter le choix de la langue : le travail avec une équipe internationale ou la redistribution du code. Dans ce cas l&#8217;anglais sera à 99% votre langue de prédilection.</p>
<p>Il n&#8217;y a pas de choix idéal : certains préféreront le tout français, d&#8217;autres le tout anglais. L&#8217;essentiel est que ce <strong>choix soit motivé par des arguments objectifs, pas une préférence personnelle</strong>.</p>
<h4>Recours au <em>folding</em></h4>
<p>J&#8217;en parle succintement mais le <em>folding</em> consiste à utiliser votre éditeur <acronym title="Cascading Style Sheets">CSS</acronym> pour <strong>masquer une partie de code</strong>. Eclipse propose par exemple de masquer toutes les définitions et tous les commentaires : leur contenu n&#8217;est révélé qu&#8217;en le dépliant.</p>
<p>Je ne suis pas un fervent utilisateur de cette pratique bien que je respecte son utilisation. Je trouve qu&#8217;en utilisation les précédentes astuces (hiérarchie + recherche) on s&#8217;y retrouve très bien.</p>
<p style="text-align:center"><img src="http://case.oncle-tom.net/images/2008/02/css-folding.png" alt="Folding en CSS" /></p>
<h3>Conclusion</h3>
<p>Ma méthodologie n&#8217;est pas parfaite, peut être perfectible et ne conviendra pas à tout le monde, par goûts ou par habitudes. Ces dernières sont cependant à combattre pour améliorer son travail. <strong>Quoi de mieux qu&#8217;un code propre, bien documenté et où l&#8217;on trouvera facilement ce que l&#8217;on cherche</strong> ?</p>
<p>C&#8217;est ce qui importe. <strong>Il y a autant de façons de coder qu&#8217;il n&#8217;y a de développeurs</strong>. Le tout est d&#8217;être ouvert aux améliorations possibles, aux méthodes existantes et à l&#8217;intérêt de leurs utilisations. Je trouverai peut-être cet article obsolète dans 1 an mais il aura été un point de passage.</p>
<p>J&#8217;espère qu&#8217;il le sera au moins en partie pour vous, développeur en herbe ou féru des pseudo-classes <img src='http://case.oncle-tom.net/wp-includes/images/smilies/icon_wink.gif' alt=';-)' class='wp-smiley' /> </p>
]]></content:encoded>
			<wfw:commentRss>http://case.oncle-tom.net/2008/bonnes-pratiques-codage-css/feed/</wfw:commentRss>
		<slash:comments>7</slash:comments>
		</item>
		<item>
		<title>Utilisation de variables dans MySQL</title>
		<link>http://case.oncle-tom.net/2007/utilisation-variables-mysql/</link>
		<comments>http://case.oncle-tom.net/2007/utilisation-variables-mysql/#comments</comments>
		<pubDate>Fri, 13 Jul 2007 11:00:30 +0000</pubDate>
		<dc:creator>Oncle Tom</dc:creator>
				<category><![CDATA[Développement Web]]></category>
		<category><![CDATA[astuce]]></category>
		<category><![CDATA[code]]></category>
		<category><![CDATA[MySQL]]></category>
		<category><![CDATA[optimisation]]></category>
		<guid isPermaLink="false">http://case.oncle-tom.net/2007/07/13/utilisation-variables-mysql/</guid>
		<description><![CDATA[MySQL, depuis la version 3.23.6, permet de déclarer des variables dans ses requêtes. Il est d&#8217;ailleurs possible de scripter ses requêtes mais c&#8217;est une autre histoire. Ca peut sembler inutile à première vue lorsqu&#8217;on utilise MySQL au travers d&#8217;API d&#8217;autres langages (PHP, Perl, C# etc.). Et pourtant ça peut vous être très utile pour économiser [...]]]></description>
			<content:encoded><![CDATA[<p><strong>MySQL</strong>, depuis la version <em>3.23.6</em>, permet de déclarer des variables dans ses requêtes. Il est d&#8217;ailleurs possible de scripter ses requêtes mais c&#8217;est une autre histoire.</p>
<p>Ca peut sembler inutile à première vue lorsqu&#8217;on utilise MySQL au travers d&#8217;<acronym title="Application Programming Interface"><acronym title="Application Programming Interface">API</acronym></acronym> d&#8217;autres langages (<acronym title="PHP : Hypertext Processor"><acronym title="Pre-Hypertext Processing">PHP</acronym></acronym>, <acronym title="Practical Extraction and Report Language">Perl</acronym>, C# etc.). Et pourtant ça peut vous être très utile pour économiser des requêtes, du temps à programmer ces boucles et puis surtout, <strong>par flemme</strong>.</p>
<p>Oui, la flemme est pour moi la <strong>qualité numéro un</strong> du développeur car <em>le flemmard a pour but d&#8217;arriver à ses fins en un minimum d&#8217;efforts</em>.<br />
<span id="more-618"></span></p>
<h3>Déclaration de variables</h3>
<p>On peut déclarer une variable de deux façons dans MySQL.<br />
La première méthode consiste à utiliser l&#8217;opérateur <code>SET</code>.</p>
<pre><code class="sql">SET @pierre = 3, @feuille = 3 + 2, @ciseau = @pierre % @feuille ;</code></pre>
<p>On peut également consister une variable à partir d&#8217;une requête.</p>
<pre><code class="sql">SELECT @nb_total := COUNT(*) FROM `ma_table` ;</code></pre>
<p><strong>Note</strong> : dans ce cas là, on préfixe l&#8217;opérateur <code>=</code> de <code>:</code> (deux points).</p>
<h3>Utilisation simple des variables</h3>
<p>L&#8217;utilisation première qui peut en être faite c&#8217;est d&#8217;assainir vos requêtes <acronym title="Structured Query Language">SQL</acronym> en évitant au maximum l&#8217;apparition de variables issues d&#8217;autres langages.<br />
<strong>Avant</strong> :</p>
<pre><code class="sql">SELECT * FROM `ma_table` WHERE colonne1 = {$variable1}, colonne2 = '{$variable2}' LIMIT 1;</code></pre>
<p><strong>Après</strong> :</p>
<pre><code class="sql">SET @variable1 = {$variable1}, @variable2 = '{$variable2}';
SELECT * FROM `ma_table` WHERE colonne1 = @variable1, colonne2 = @variable2 LIMIT 1;</code></pre>
<p>Comme les variables sont effectives pour la connexion courante, une variable MySQL peut être réutilisée à tout moment. De quoi décomplexifier certains scripts pas forcément bien structurés.</p>
<h3>Utilisation complexe des variables</h3>
<p><strong>Les variables peuvent également être modifiées à même la requête</strong>. C&#8217;est à dire qu&#8217;à chaque itération effectuée par MySQL, le moteur va réévaluer le contenu de la variable. J&#8217;ai notamment eu besoin de ça pour ajouter de nouveaux éléments à la suite d&#8217;autres tout en renumérotant leur ordre. Je souhaitais <strong>éviter une boucle récursive en <acronym title="Pre-Hypertext Processing">PHP</acronym></strong> qui aurait occasionné de multiples requêtes.</p>
<p>Je dispose d&#8217;une table (<code>item_liste</code>) avec plusieurs éléments, une clé primaire sur deux champs (<code>item_id</code> et <code>item_cat</code>) ainsi qu&#8217;un autre champ indexé permettant de les trier dans un ordre donné (<code>item_ordre</code>). Le but : prendre des éléments de la catégorie 1 pour les mettre à la suite de la catégorie 2.</p>
<p>Voici en gros ce que ça donne au final :</p>
<pre><code class="sql">SELECT @ordre := IFNULL(MAX(item_ordre), 0) FROM `item_liste` WHERE item_cat = 2 ;
UPDATE `item_liste` SET item_ordre = @ordre := @ordre+1, item_cat = 2 WHERE item_cat = 1 ;</code></pre>
<ol>
<li>On compte la borne supérieure de la catégorie 2. Pourquoi un <code>IFNULL</code> ? Parce <code>MAX()</code> retournera <code>NULL</code> si un des <code>item_ordre</code> en contient un. C&#8217;est une sécurité ;</li>
<li>On met à jour les éléments de la catégorie 1 avec leur nouvel ordonnancement et leur nouvelle catégorie.</li>
</ol>
<p><strong>Alors pourquoi ça fonctionne</strong> ? La commande <code>UPDATE</code> balaie les lignes <strong>une par une</strong> et du coup, <strong>met à jour la variable <code>@ordre</code> à chaque ligne</strong>. Nous retrouvons ainsi l&#8217;effet désiré : incrémenter chaque ligne déplacée dans la nouvelle catégorie.</p>
<p>Il existe des utilisations plus compliquées que celles-là mais je pense que c&#8217;est un bon départ pour se faire une idée de ce qui est faisable par ce biais là. L&#8217;imagination et les besoins feront le reste <img src='http://case.oncle-tom.net/wp-includes/images/smilies/icon_wink.gif' alt=';-)' class='wp-smiley' /> </p>
]]></content:encoded>
			<wfw:commentRss>http://case.oncle-tom.net/2007/utilisation-variables-mysql/feed/</wfw:commentRss>
		<slash:comments>9</slash:comments>
		</item>
		<item>
		<title>Tableau auto-extensible en JavaScript</title>
		<link>http://case.oncle-tom.net/2007/tableau-auto-extensible-en-javascript/</link>
		<comments>http://case.oncle-tom.net/2007/tableau-auto-extensible-en-javascript/#comments</comments>
		<pubDate>Tue, 26 Jun 2007 11:59:32 +0000</pubDate>
		<dc:creator>Oncle Tom</dc:creator>
				<category><![CDATA[Accessibilité]]></category>
		<category><![CDATA[Développement Web]]></category>
		<category><![CDATA[Standards du Web]]></category>
		<category><![CDATA[ajax]]></category>
		<category><![CDATA[bonne pratique]]></category>
		<category><![CDATA[code]]></category>
		<category><![CDATA[dom]]></category>
		<category><![CDATA[html]]></category>
		<category><![CDATA[Javascript]]></category>
		<category><![CDATA[mootools]]></category>
		<guid isPermaLink="false">http://case.oncle-tom.net/2007/06/26/tableau-auto-extensible-en-javascript/</guid>
		<description><![CDATA[Bon nombre de clients utilisant les sites Internet de mon employeur passent des commandes en saisissant directement les codes articles de leur choix. Ce n&#8217;est pas anodin : pour du réassort de magasin, ils savent exactement ce qu&#8217;ils veulent. Et un beau jour on vient me voir en me disant qu&#8217;ils ne peuvent saisir qu&#8217;un [...]]]></description>
			<content:encoded><![CDATA[<p>Bon nombre de clients utilisant les sites Internet de mon employeur passent des commandes en saisissant directement les codes articles de leur choix. Ce n&#8217;est pas anodin : pour du réassort de magasin, ils savent exactement ce qu&#8217;ils veulent. Et un beau jour on vient me voir en me disant qu&#8217;<cite>ils ne peuvent saisir qu&#8217;un code et une seule quantité à la fois</cite>, qu&#8217;il faudrait changer ça.</p>
<p style="text-align:center"><img src="http://case.oncle-tom.net/images/2007/06/articles-autoexpand-mini.png" alt="Ligne article" /></p>
<p>Voici donc mon constat de départ :</p>
<ul>
<li>un client doit pouvoir saisir <em>un seul article</em> s&#8217;il le veut</li>
<li>un client doit pouvoir saisir <em>10 articles</em> s&#8217;il le veut</li>
<li>un client doit pouvoir saisir <em>100 articles</em> s&#8217;il le veut</li>
<li>mais <strong>celui qui n&#8217;en saisit que 10 ne doit pas être gêné par 100 lignes de formulaire à remplir</strong></li>
<li>un <em>débutant</em> doit pouvoir saisir 100 lignes sans avoir de mode d&#8217;emploi sous la main</li>
</ul>
<p>Donc ma solution a été très simple : <strong>je ne mettrai qu&#8217;une ligne</strong>.<br />
<span id="more-680"></span></p>
<h3>L&#8217;idée</h3>
<p>Comment faire pour satisfaire tout le monde, les gros donneurs d&#8217;ordre comme les petits ?<br />
<strong>En faisant en sorte que le formulaire s&#8217;adapte à leur besoin.</strong> Je voulais donc qu&#8217;à chaque ligne complétée s&#8217;en ajoute une autre avant de passer à la validation finale. Place au combo <strong>JavaScript + <acronym title="Document Object Model">DOM</acronym> = Ajax</strong>.</p>
<h3>La version dégradée</h3>
<p>Une <em>bonne pratique de l&#8217;Ajax</em> est de partir du cas particulier : celui où les conditions ne sont pas requises. En clair, une personne qui n&#8217;a pas JavaScript d&#8217;activé ou pas de JavaScript tout court.<br />
Conclusion, j&#8217;ai décidé de générer un tableau en <acronym title="HyperText Markup Language">HTML</acronym> de 10 lignes. 10 est un choix arbitraire, modifiable à tout moment et qui ne doit donc pas gêner la version dynamique en cas de changement (ajout de colonne, ajout de lignes).</p>
<p style="text-align:center"><img src="http://case.oncle-tom.net/images/2007/06/articles-autoexpand.png" alt="Tableau auto-extansible dégradé" /></p>
<h3>La version Ajax</h3>
<p>On peut manipuler le document à loisir grâce à JavaScript. <strong>Avec un code propre et ordonné c&#8217;est d&#8217;autant plus simple</strong>. Alors voici la logique à mettre en oeuvre :</p>
<ol>
<li>éliminer toutes les lignes dont on ne veut pas et n&#8217;en garder qu&#8217;une</li>
<li>assigner à chaque champ de formulaire de la ligne (<code>input</code>, <code>select</code>, <code>textarea</code>) une fonction de vérification : si tous les éléments de la ligne sont remplis / cochés et qu&#8217;il n&#8217;y a pas de ligne après, on clonera la ligne</li>
<li>cloner la ligne en la vidant de ses valeurs, en modifiant les noms de champ pour les rendre exploitable après coup</li>
</ol>
<p><strong><br />
Ce qu&#8217;on l&#8217;on veut étant relativement simple, <em>le code doit l&#8217;être également</em></strong> ! Le résultat aussi, la preuve en mouvement.</p>
<div style="text-align:center"><object classid="clsid:d27cdb6e-ae6d-11cf-96b8-444553540000" width="372" height="188" codebase="http://download.macromedia.com/pub/shockwave/cabs/flash/swflash.cab#version=6,0,40,0"><param name="src" value="http://case.oncle-tom.net/images/2007/06/articles-autoexpand.swf" /><embed type="application/x-shockwave-flash" width="372" height="188" src="http://case.oncle-tom.net/images/2007/06/articles-autoexpand.swf"></embed></object></div>
<p>Au final, <strong>50 lignes de JavaScript ont suffit</strong> à transformer un tableau complètement statique en tableau dynamique, s&#8217;adaptant à la demande de n&#8217;importe quel client. Client qui pourra également utiliser le clavier pour davantage d&#8217;efficacité de saisie.</p>
<p>C&#8217;est à dire <strong>exactement ce que l&#8217;on souhaitait au départ</strong>.</p>
<h3>Le code</h3>
<h4>Le tableau <acronym title="HyperText Markup Language">HTML</acronym></h4>
<pre><code class="html">&lt;table cellspacing="0" id="ajout_multi_articles"&gt;
  &lt;thead&gt;
    &lt;tr&gt;
      &lt;th&gt;Code article&lt;/th&gt;
      &lt;th&gt;Quantité&lt;/th&gt;
    &lt;/tr&gt;
  &lt;/thead&gt;
  &lt;tbody&gt;
    &lt;tr class="article"&gt;
      &lt;th&gt;&lt;input type="text" name="article[1][ref]" maxlength="10" /&gt;&lt;/th&gt;
      &lt;td&gt;&lt;input type="text" name="article[1][qte]" maxlength="5" size="5" /&gt;&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr class="article"&gt;
      &lt;th&gt;&lt;input type="text" name="article[2][ref]" maxlength="10" /&gt;&lt;/th&gt;
      &lt;td&gt;&lt;input type="text" name="article[2][qte]" maxlength="5" size="5" /&gt;&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr class="article"&gt;
      &lt;th&gt;&lt;input type="text" name="article[3][ref]" maxlength="10" /&gt;&lt;/th&gt;
      &lt;td&gt;&lt;input type="text" name="article[3][qte]" maxlength="5" size="5" /&gt;&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr class="article"&gt;
      &lt;th&gt;&lt;input type="text" name="article[4][ref]" maxlength="10" /&gt;&lt;/th&gt;
      &lt;td&gt;&lt;input type="text" name="article[4][qte]" maxlength="5" size="5" /&gt;&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr class="article"&gt;
      &lt;th&gt;&lt;input type="text" name="article[5][ref]" maxlength="10" /&gt;&lt;/th&gt;
      &lt;td&gt;&lt;input type="text" name="article[5][qte]" maxlength="5" size="5" /&gt;&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr class="article"&gt;
      &lt;th&gt;&lt;input type="text" name="article[6][ref]" maxlength="10" /&gt;&lt;/th&gt;
      &lt;td&gt;&lt;input type="text" name="article[6][qte]" maxlength="5" size="5" /&gt;&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr class="article"&gt;
      &lt;th&gt;&lt;input type="text" name="article[7][ref]" maxlength="10" /&gt;&lt;/th&gt;
      &lt;td&gt;&lt;input type="text" name="article[7][qte]" maxlength="5" size="5" /&gt;&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr class="article"&gt;
      &lt;th&gt;&lt;input type="text" name="article[8][ref]" maxlength="10" /&gt;&lt;/th&gt;
      &lt;td&gt;&lt;input type="text" name="article[8][qte]" maxlength="5" size="5" /&gt;&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr class="article"&gt;
      &lt;th&gt;&lt;input type="text" name="article[9][ref]" maxlength="10" /&gt;&lt;/th&gt;
      &lt;td&gt;&lt;input type="text" name="article[9][qte]" maxlength="5" size="5" /&gt;&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr class="article"&gt;
      &lt;th&gt;&lt;input type="text" name="article[10][ref]" maxlength="10" /&gt;&lt;/th&gt;
      &lt;td&gt;&lt;input type="text" name="article[10][qte]" maxlength="5" size="5" /&gt;&lt;/td&gt;
    &lt;/tr&gt;
  &lt;/tbody&gt;
&lt;/table&gt;</code></pre>
<h4>La fonction JavaScript</h4>
<pre><code class="javascript">/**
 * Transforme un tableau multi-lignes en un tableau mono-ligne mais auto-extensible
 * Renomme également les noms de champ en suivant un masque paramétrable ; par défaut article[]
 *
 * @usage articlesMultiRows([{'css_id': ?, 'css_row_class': ?, 'check_inputs': ?}])
 * @param {Object} params Objet contenant (ou pas) les paramètres de contrôle de la classe
 */
function articlesMultiRows(params)
{
  this.row_number = 0;
  /*
   * Extension des paramètres par défaut
   */
  var params = params || {};
  params.css_id = params.css_id || 'ajout_multi_articles';
  params.css_row_class = params.css_row_class || 'article';
  params.check_inputs = params.check_inputs || 'input,select,textarea';
  /**
   * Initialise le tableau de données et accroche les méthodes dynamiques
   */
  this.init = function(){
    //aucun ID détecté, pas la peine de continuer plus loin
    if (!$(params.css_id))
    {
      return false;
    }
    //on récupère les lignes, on enlève la première du tableau et on supprime les autres
    var rows = $(params.css_id).getElements('tr.'+params.css_row_class);
    var row_first = rows.shift();
    rows.removeElements();
    rows = null;
    /*
     * On assigne l'évènement aux champs paramétrés de la ligne
     * On place le focus sur le premier champ
     */
    $ES(params.check_inputs, row_first).addEvent('blur', rowCheck);
    $(row_first).getElement('input').focus();
    row_number = 1;
    /*
     * On écrit un petit message sympathique indiquant le fonctionnement du bazar
     * On le fait via JavaScript car un utilisateur sans <acronym title="JavaScript">JS</acronym> ne pourrait justement pas suivre les infos
     * Il est placé juste avant le tableau
     */
    new Element('p',{
          'class' : 'message'
          }).setHTML("Dès qu'un code article et une quantité sont saisis ci-dessous, &lt;strong&gt;une nouvelle ligne s'ajoute automatiquement&lt;/strong&gt;.&lt;br /&gt;Afin d'accélérer votre saisie, &lt;em&gt;utilisez la touche de tabulation de votre clavier&lt;/em&gt; pour passer d'un champ à l'autre. Vous verrez, c'est facile et surtout efficace !").injectBefore(params.css_id);
  };
  /**
   * Vérifie si la ligne a entièrement été complétée et le cas échéant, déclenche l'ajout de ligne
   */
  this.rowCheck = function(){
    var row = { 'inputs' : 0, 'completed' : 0, 'dom' : $(this).getParent().getParent() };
    $ES(params.check_inputs, row.dom).each(function(input){
      //Un élément de plus ...
      ++row.inputs;
      //... dont on vérifie s'il est bien complété
      switch (input.getTag())
      {
        case 'input':
        case 'textarea':
          if (input.value.clean())
          {
            ++row.completed;
          }
        break;
        case 'select':
          if (input.selectedIndex &gt;= 0 &amp;&amp; input.selectedIndex &lt; input.length)
          {
            ++row.completed;
          }
        break;
      }
    });
    /*
     * Pour insérer une nouvelle ligne, on doit avoir :
     * - autant de champs complétés que de champs existants
     * - aucun élément suivant
     */
    if (row.inputs === row.completed &amp;&amp; !row.dom.getNext())
    {
      rowInsert(row.dom);
    }
  };
  /**
   * Insère une nouvelle ligne en clonant la dernière du tableau et la purgeant de ses valeurs
   *
   * @param {Object} row Noeud <acronym title="Document Object Model">DOM</acronym> correspondant à la ligne à cloner
   */
  this.rowInsert = function( row ){
    //On incrémente le nombre de lignes dispo
    //Ce numéro sert à changer les masques de nom de champ
    ++row_number;
    var row_clone = row.clone();
    //Clonage de la ligne
    $ES('input[type=text],input[type=password],input[type=hidden],textarea', row_clone).setProperty('value', '');
    $ES(params.check_inputs, row_clone).removeEvents('blur'); /* obligé car <acronym title="Internet Explorer 5">IE5</acronym>+ clone aussi les évènements ... alors qu'il ne le devrait pas */
    $ES(params.check_inputs, row_clone).addEvent('blur', rowCheck); /* oui oui, <acronym title="Internet Explorer 5">IE5</acronym>+ ne rassignait pas cet évènement comme il fallait malgré ça */
    //On remplace les noms des champs pour que permettre une utilisation des résultats $_POST
    $ES(params.check_inputs, row_clone).each(function(input){
      input.name = input.name.replace(new RegExp('^'+params.css_row_class+'\[[0-9]+\]'), params.css_row_class+'['+row_number+']');
    });
    //Injection de la ligne, une fois tout le travail terminé
    row_clone.injectAfter(row);
    //Nettoyage, le clonage, ça salit
    row_clone = null;
    row = null;
  };
  /*
   * Initialisation de la classe
   */
  this.init();
}
/*
 * Initialisation du tableau multi-lignes avec les options par défaut
 */
window.addEvent('domready', articlesMultiRows);</code></pre>
]]></content:encoded>
			<wfw:commentRss>http://case.oncle-tom.net/2007/tableau-auto-extensible-en-javascript/feed/</wfw:commentRss>
		<slash:comments>18</slash:comments>
		</item>
		<item>
		<title>Mise à jour automatique d&#8217;une feuille de style CSS dans le navigateur Web</title>
		<link>http://case.oncle-tom.net/2007/mise-a-jour-automatique-css-navigateur-web/</link>
		<comments>http://case.oncle-tom.net/2007/mise-a-jour-automatique-css-navigateur-web/#comments</comments>
		<pubDate>Fri, 25 May 2007 11:00:09 +0000</pubDate>
		<dc:creator>Oncle Tom</dc:creator>
				<category><![CDATA[Développement Web]]></category>
		<category><![CDATA[Standards du Web]]></category>
		<category><![CDATA[astuce]]></category>
		<category><![CDATA[bonnes pratiques]]></category>
		<category><![CDATA[cache]]></category>
		<category><![CDATA[code]]></category>
		<category><![CDATA[css]]></category>
		<guid isPermaLink="false">http://case.oncle-tom.net/2007/05/25/mise-a-jour-automatique-css-navigateur-web/</guid>
		<description><![CDATA[Bien souvent on est amené à modifier une feuille de style existante pour adapter la présentation ou corriger un bug (qui a pensé à Internet Explorer ?). Bien souvent on modifie directement cette feuille de style pour ensuite écraser les anciennes versions sur les sites en production. Et généralement on se confronte au problème du [...]]]></description>
			<content:encoded><![CDATA[<p>Bien souvent on est amené à <strong>modifier une feuille de style existante pour adapter la présentation</strong> ou corriger un bug (qui a pensé à <em>Internet Explorer</em> ?).<br />
Bien souvent on modifie directement cette feuille de style pour ensuite écraser les anciennes versions sur les sites en production.</p>
<p>Et généralement on se confronte au <strong>problème du cache des navigateurs Web</strong>. Ces derniers conservent en mémoire les feuilles de style pendant un certain temps causant ainsi un décalage entre le fichier <acronym title="Cascading Style Sheet"><acronym title="Cascading Style Sheets">CSS</acronym></acronym> du serveur (et la présentation souhaitée) et celui du navigateur (reposant sur une présentation obsolète).<br />
<span id="more-632"></span></p>
<h3>Inclure une feuille de style</h3>
<p>L&#8217;inclusion d&#8217;une feuille de style au sein même de la page n&#8217;est pas une opération qui devrait vous poser trop de problèmes. Elle peut se faire de deux façons, la première étant compatible avec tous les navigateurs, la seconde seulement avec les navigateurs modernes.</p>
<pre><code class="txt">/* inclusion "old school" */
&lt;link rel="stylesheet" type="text/css" href="url/style.css" media="screen" /&gt;
/* inclusion "moderne" */
&lt;style type="text/css"&gt;@import url('url/style.css') screen;&lt;/style&gt;</code></pre>
<h3>Inclure une feuille de style avec mise à jour automatique</h3>
<p>Vous allez voir, c&#8217;est tout bête. <em>On reprend l&#8217;exemple précédent</em> ; on veut conserver le même nom de fichier mais il a été mis à jour et on souhaite que le <em>navigateur le recharge sans que l&#8217;utilisateur ait à faire un petit F5</em> sur son clavier.</p>
<pre><code class="txt">/* inclusion "old school" */
&lt;link rel="stylesheet" type="text/css" href="url/style.css<ins>?v=1234</ins>" media="screen" /&gt;
/* inclusion "moderne" */
&lt;style type="text/css"&gt;@import url('url/style.css<ins>?v=1234</ins>') screen;&lt;/style&gt;</code></pre>
<p>Vous voyez le <strong>v=1234</strong> ? Le fait d&#8217;ajouter un paramètre au fichier appelé dupe le navigateur et lui fait croire qu&#8217;il s&#8217;agit d&#8217;un fichier différent de <em>style.css</em>. En réalité on peut mettre n&#8217;importe quoi en paramètre (le timestamp de mise à jour du fichier par exemple. Par exemple <code>style.css?1180077252</code>).</p>
<h3>Pourquoi ça fonctionne ?</h3>
<p>Dans une <acronym title="Uniform Ressource Identifier"><acronym title="Uniform Resource Identifier">URI</acronym></acronym>, le chemin physique du fichier s&#8217;arrête juste avant le <kbd>?</kbd>. <em>Tout ce qui est inscrit après est considéré comme étant des paramètres</em>, compléments virtuels du-dit fichier. Ce qui importe au navigateur, c&#8217;est que le fichier en question renvoie bien des données dans le type <acronym title="Multipurpose Internet Mail Extensions"><acronym title="Multipurpose Internet Mail Extension">MIME</acronym></acronym> attendu, ici <code>text/css</code>.</p>
<p><strong>Le navigateur gère le cache d&#8217;un fichier par rapport à son adresse complète</strong>, ceci incluant les paramètres fournis. Pour lui, <code>style.css?v=1</code> et <code>style.css?v=2</code> sont deux fichiers différents, peu importe s&#8217;il s&#8217;agit en réalité du fichier <code>style.css</code>.<br />
En cas de changement de paramètre, <strong>le navigateur estime qu&#8217;il s&#8217;agit d&#8217;un nouveau fichier</strong>, récupère celui-ci et, magie, utilise la dernière version en date de celui-ci plutôt qu&#8217;une version en cache, obsolète.</p>
<p>Cette petite astuce permet de <em>gagner en crédibilité face à des clients</em>, <em>évite aux internautes d&#8217;être perdus</em> dans un affichage incohérent misant fortement sur les feuilles de style.<br />
Exactement ce que l&#8217;on recherchait <img src='http://case.oncle-tom.net/wp-includes/images/smilies/icon_wink.gif' alt=';-)' class='wp-smiley' /> </p>
]]></content:encoded>
			<wfw:commentRss>http://case.oncle-tom.net/2007/mise-a-jour-automatique-css-navigateur-web/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
	</channel>
</rss>

