<?xml version="1.0" encoding="utf-8"?><?xml-stylesheet title="XSL formatting" type="text/xsl" href="http://www.the-asw.com/feed/rss2/xslt" ?><rss version="2.0"
  xmlns:dc="http://purl.org/dc/elements/1.1/"
  xmlns:wfw="http://wellformedweb.org/CommentAPI/"
  xmlns:content="http://purl.org/rss/1.0/modules/content/">
<channel>
  <title>The ASW - javascript</title>
  <link>http://www.the-asw.com/</link>
  <description></description>
  <language>fr</language>
  <pubDate>Fri, 14 Nov 2008 16:51:08 +0100</pubDate>
  <copyright></copyright>
  <docs>http://blogs.law.harvard.edu/tech/rss</docs>
  <generator>Dotclear</generator>
  
    
  <item>
    <title>Nouveau blog de développeur</title>
    <link>http://www.the-asw.com/post/2007/07/16/Nouveau-blog-de-developpeur</link>
    <guid isPermaLink="false">urn:md5:0ffc0b0a35624628e3dc56f4b0b2343e</guid>
    <pubDate>Mon, 16 Jul 2007 19:07:00 +0200</pubDate>
    <dc:creator>cgo2</dc:creator>
        <category>Développement web</category>
        <category>javascript</category><category>php</category>    
    <description>    &lt;p&gt;Ma nouvelle boite, &lt;a href=&quot;http://www.bsocom.com&quot;&gt;BSO Communication&lt;/a&gt;, vient d'ouvrir son blog répondant au doux nom de &lt;a href=&quot;http://www.bsohq.fr/&quot;&gt;BSO HQ&lt;/a&gt;. Je vais m'occuper de la partie développement, en racontant de temps en temps mes péripéties quotidiennes avec PHP, Javascript, Ruby et tout un tas d'autres langages qui font le web 2.0 (et peut être même plus). Il y a(ura) également 3 rubriques Hébergement, Système et Réseaux, pour ceux qui s'interressent au métier d'opérateur Internet et d'hébergeur. Si avec ça je ne vous ait pas donné envie de l'ajouter immédiatement à votre aggrégateur RSS favori, je sais pas ce qu'il faut. Non, pas des femmes dénudées, c'est pas l'E3 ici.&lt;/p&gt;</description>
    
    
    
          <comments>http://www.the-asw.com/post/2007/07/16/Nouveau-blog-de-developpeur#comment-form</comments>
      <wfw:comment>http://www.the-asw.com/post/2007/07/16/Nouveau-blog-de-developpeur#comment-form</wfw:comment>
      <wfw:commentRss>http://www.the-asw.com/feed/rss2/comments/79</wfw:commentRss>
      </item>
    
  <item>
    <title>Une version optimisée pour PHP de JSMin</title>
    <link>http://www.the-asw.com/post/2007/03/28/Une-version-optimisee-pour-PHP-de-JSMin</link>
    <guid isPermaLink="false">urn:md5:dcbeaf0f55f519173e6a2884ae3cb8c7</guid>
    <pubDate>Wed, 28 Mar 2007 18:23:00 +0200</pubDate>
    <dc:creator>cgo2</dc:creator>
        <category>Développement web</category>
        <category>c</category><category>javascript</category><category>php</category>    
    <description>&lt;p&gt;Les Javascripts permettent de faire tout pleins de choses sur un site web, c'est cool.
Mais à force d'empiler les librairies, les &lt;em&gt;frameworks&lt;/em&gt; et autres fonctions, 
on peut vite se retrouver avec deux kilo-tonnes de script, ce qui n'est ni très
agréable à charger et ni très léger pour la bande passante.&lt;/p&gt;

&lt;p&gt;Heureusement, plusieurs librairies (plus ou mois efficaces) existent et permettent
de compresser les scripts. JSMin est l'une d'entre elle.&lt;/p&gt;    &lt;p&gt;A l'origine, JSMin est un petit
programme écrit en C par &lt;a href=&quot;http://www.crockford.com/javascript/jsmin.html&quot; hreflang=&quot;en&quot;&gt;Douglas Crokford&lt;/a&gt;.
Il prend un fichier Javascript et supprime tout
ce qui n'est strictement nécessaire, c'est-à-dire :&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;les commentaires (&lt;code&gt;/* */&lt;/code&gt; et &lt;code&gt;//&lt;/code&gt;),&lt;/li&gt;
&lt;li&gt;les lignes vides et retour à la ligne,&lt;/li&gt;
&lt;li&gt;les espaces (sauf dans les chaines de caractères et les expressions régulières).&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Contrairement à d'autres &lt;em&gt;packer&lt;/em&gt;, JSMin &lt;strong&gt;ne brouille pas le code&lt;/strong&gt;,
c'est-à-dire que le fichier compressé reste lisible, débuggable et modifiable (même si une petite
ré-indentation est nécessaire), ce qui est quand même un avantage très appréciable.&lt;/p&gt;

&lt;p&gt;Il existe une &lt;a href=&quot;http://gggeek.altervista.org/2006/12/22/shrink-the-size-of-your-javascript-with-js-min-the-php-way/&quot; hreflang=&quot;en&quot;&gt;version PHP de JSMin&lt;/a&gt;,
mais, comme son auteur l'indique, il s'agit d'une « conversion simple et brutale
du C vers le PHP », entendez par là qu'elle n'est pas du tout optimisée et donc
super lente. Evidemment, la version C est théoriquement utilisable en PHP via la fonction
&lt;code&gt;shell_exec&lt;/code&gt;, mais c'est totalement impensable sur un hébergement mutualisé.&lt;/p&gt;

&lt;p&gt;Récemment, j'ai dû mettre en place un système de compression et de concaténation
des javascripts « à la volée » ; c'est-à-dire que les javascripts sont compressés
la première fois qu'un utilisateur les demande, puis mis en cache (vaguement
inspiré &lt;a href=&quot;http://www.ejeliot.com/blog/72&quot; hreflang=&quot;en&quot;&gt;de ce post&lt;/a&gt;).
Dès qu'un fichier est mis à jour, le cache est regénéré. Ainsi, je conserve les versions
commentées et indentées pour développer, et je n'ai pas à me soucier de les
compresser avant de les mettre en ligne. C'est magique.&lt;/p&gt;

&lt;p&gt;Mais, la version originale de JSMin en PHP met parfois plus de 3 secondes à compresser
certains fichiers, ce qui est bien trop long. Donc je n'ai pas pû m'empêcher
de faire un tour dans le code pour l'optimiser. J'ai remplacé toutes les boucles
de lecture caractère par caractère (typique du C) par des fonctions natives PHP 
comme &lt;code&gt;strpos&lt;/code&gt; et &lt;code&gt;strlen&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;J'ai également viré toute
la partie qui concernait les fichiers (dans la version originale, il est possible
de passer un nom de fichier à JSMin pour qu'il le lise directement), parceque
en PHP c'est &lt;strong&gt;beaucoup&lt;/strong&gt; plus rapide de lire d'abord le fichier (par
une fonction comme &lt;code&gt;file_get_contents&lt;/code&gt;) et de travailler sur la chaine
de caractère représentant le contenu.&lt;/p&gt;

&lt;p&gt;Le gain en vitesse dépend fortement de la taille et du contenu du fichier ; dans
mon cas c'est entre 10% et 50% plus rapide.&lt;/p&gt;

&lt;h3&gt;Utilisation&lt;/h3&gt;

&lt;p&gt;Le constructeur prend 2 paramètres : le code à compresser (&lt;code&gt;string&lt;/code&gt;)
et, si besoin, un tableau de commentaires à ajouter en début de fichier (&lt;code&gt;array&lt;/code&gt; ou rien).
Ensuite il suffit d'appeller la fonction &lt;code&gt;minify()&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Exemple :&lt;/p&gt;
&lt;pre&gt;$code = file_get_contents('foo.js');
$compressor = new MyJsMin($code, array('Hello', 'World'));
echo $compressor-&amp;gt;minify();&lt;/pre&gt;

&lt;p&gt;Le fichier &lt;code&gt;foo.js&lt;/code&gt; contient :&lt;/p&gt;
&lt;pre&gt;function foo(bar)
{
bar += 1;
alert('hello world !');
}
&lt;/pre&gt;
&lt;p&gt;Le résultat sera :&lt;/p&gt;

&lt;pre&gt;// hello
// world

function foo(bar)
{bar+=1;alert('hello world !');}
&lt;/pre&gt;

&lt;h3&gt;Sources&lt;/h3&gt;

&lt;ul&gt;
	&lt;li&gt;Sources &lt;a href=&quot;http://www.the-asw.com/public/web/myjsmin/MyJsMin.class.phps&quot;&gt;de MyJsMin&lt;/a&gt;.&lt;/li&gt;
	&lt;li&gt;Pour JSMin en PHP, voir &lt;a href=&quot;http://gggeek.altervista.org/2006/12/22/shrink-the-size-of-your-javascript-with-js-min-the-php-way/&quot;&gt;le blog de l'auteur&lt;/a&gt;.&lt;/li&gt;
	&lt;li&gt;La &lt;a href=&quot;http://www.crockford.com/javascript/jsmin.html&quot;&gt;page de la version originale&lt;/a&gt; de JSMin en C (avec des liens vers d'autres langages)&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;Test en ligne&lt;/h3&gt;

&lt;p&gt;Vous pouvez tester les performances du script &lt;a href=&quot;http://www.the-asw.com/public/web/myjsmin/&quot;&gt;grace à cette page&lt;/a&gt; (en anglais, parceque c'est la classe internationnale).&lt;/p&gt;</description>
    
    
    
          <comments>http://www.the-asw.com/post/2007/03/28/Une-version-optimisee-pour-PHP-de-JSMin#comment-form</comments>
      <wfw:comment>http://www.the-asw.com/post/2007/03/28/Une-version-optimisee-pour-PHP-de-JSMin#comment-form</wfw:comment>
      <wfw:commentRss>http://www.the-asw.com/feed/rss2/comments/74</wfw:commentRss>
      </item>
    
  <item>
    <title>Position du curseur dans un textarea</title>
    <link>http://www.the-asw.com/post/2007/02/20/70-position-du-curseur-dans-un-textarea</link>
    <guid isPermaLink="false">urn:md5:11941d3135485972c57a4a92ec921500</guid>
    <pubDate>Tue, 20 Feb 2007 14:36:00 +0000</pubDate>
    <dc:creator>cgo2</dc:creator>
        <category>Développement web</category>
        <category>javascript</category>    
    <description>Comment détecter, en javascript, la position du curseur dans un textarea ? Comment déplacer le curseur ? Comment récuperer le texte sélectionné, ainsi que les coordonnées de la selection ? Evidemment sous Firefox tout roule, mais pour le navigateur de Microsoft c'est autre chose... Après avoir passé 5 bonnes heures sur Google à lire des solutions aussi farfelue qu'inefficaces (à base de Math.round, de boucles imbriqués, ou de soustraction d'un coeffient alétoire), j'ai fini par chercher ma propre solution. Voici quelques pistes pour soumettre Internet Explorer à votre volonté !    &lt;p&gt;J'ai essayé de faire 5 actions, que je vais décrire dans cet article :&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;obtenir le texte sélectionné dans un textarea donné ;&lt;/li&gt;
&lt;li&gt;obtenir la position du début de la selection du contenu du textarea (en commençant à 0) ;&lt;/li&gt;
&lt;li&gt;obtenir la position de la fin de la selection du contenu ;&lt;/li&gt;
&lt;li&gt;déplacer le curseur à une position, en précisant éventuellement une position de fin pour créer une selection ;&lt;/li&gt;
&lt;li&gt;remplacer le texte sélectionné par un autre.&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;D'abord, examinons le comportement standard (testé sous Mozilla Firefox &gt;= 1.5).&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Chaque textarea sauvegarde sa propre selection.&lt;/li&gt;
&lt;li&gt;Chaque textarea contient 2 variables &lt;code&gt;selectionStart&lt;/code&gt; et &lt;code&gt;selectionEnd&lt;/code&gt; qui contiennent à tout moment les coordonnées de la selection (si rien n'est selectionné, &lt;code&gt;selectionStart&lt;/code&gt; est égal à &lt;code&gt;selectionEnd&lt;/code&gt;)&lt;/li&gt;
&lt;li&gt;Chaque textarea possède une méthode &lt;code&gt;setSelectionRange(start, end)&lt;/code&gt; qui permet de créer une selection ou de positionner le curseur (en passant 2 fois la même valeur).&lt;/li&gt;
&lt;li&gt;Pour remplacer le texte selectionné, il faut couper le texte en 3 : avant, selection, après, et le remplacer par avant + nouvelle selection + après. Il faut penser à remettre d'indice de &lt;em&gt;scroll&lt;/em&gt; afin de conserver la barre de défilement à la même position.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Voyons maintenant le comportement d'Internet Explorer, qui, comme a son habitude, est totalement illogique, incohérent et, disons-le, complètement con.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Internet Explorer ne gère qu'une seule sélection pour toute le document, accessible via &lt;code&gt;document.selection&lt;/code&gt;. En conséquence de quoi, il faut toujours penser à faire un &lt;code&gt;focus()&lt;/code&gt; sur le textarea à traiter, sans quoi on risque d'avoir des résultats totalement incohérents.&lt;/li&gt;
&lt;li&gt;Cependant, il est possible de créer une selection pour chaque textarea. Mais ces selections ne contiendront pas le texte selectionné, elles servent uniquement à déplacer le curseur (!) (j'avais prévenu que c'était complètement con...).&lt;/li&gt;
&lt;li&gt;Pour manipuler une selection, il faut créer un objet &lt;code&gt;TextRange&lt;/code&gt;, qui permet de faire des tas de choses (y compris des choses &lt;a href=&quot;http://msdn.microsoft.com/workshop/author/dhtml/reference/methods/getbookmark.asp&quot; hreflang=&quot;en&quot;&gt;documentées comme « opaque » par Microsoft&lt;/a&gt;), mais &lt;strong&gt;pas de récupèrer la position du curseur&lt;/strong&gt;.&lt;/li&gt;
&lt;li&gt;Il est impossible se spécifier directement la position du curseur.&lt;/li&gt;
&lt;li&gt;Il y a une méthode propriétaire pour remplacer la sélection, en mettant à jour l'attribut &lt;code&gt;text&lt;/code&gt; de l'objet &lt;code&gt;range&lt;/code&gt; (&lt;code&gt;range.text = 'toto'&lt;/code&gt;).&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Voyons maintenant comment dominer IE.&lt;/p&gt;

&lt;p&gt;Note : Les fonctions proposées ici sont destinées à être utilisée dans une
classe où &lt;code&gt;this&lt;/code&gt; représente l'objet textarea. N'hésitez à pas adapter pour votre propre besoin :)&lt;/p&gt;

&lt;h4&gt;Obtenir la sélection&lt;/h4&gt;

&lt;p&gt;La fonction suivante permet d'obtenir le texte sélectionné dans un textarea.&lt;/p&gt;

&lt;pre&gt;
getSelection: function ()
{
	if (this.setSelectionRange)
		return this.value.substring(this.selectionStart, this.selectionEnd);
	else if (document.selection) {
		this.focus();
		return document.selection.createRange().text;
	}
}
&lt;/pre&gt;

&lt;h4&gt;Obtenir les coordonnées du curseur&lt;/h4&gt;

&lt;p&gt;Alors là, ça devient rigolo. La solution : récupérer la selection globale,
puis la recopier dans une selection locale au textarea. Ensuite, déplacer
la fin de la selection le plus possible (la selection locale, contraiement à la selection globale du document, s'arrettera à la fin de texte). Enfin, effectuer une petite soustraction.&lt;/p&gt;

&lt;pre&gt;
getSelectionStart: function()
{
	if ( typeof this.selectionStart != 'undefined' )
		return this.selectionStart;
	
	// IE Support
	this.focus();
	var range = this.createTextRange();
	range.moveToBookmark(document.selection.createRange().getBookmark());
	range.moveEnd('character', this.value.length);
	return this.value.length - range.text.length;
}
&lt;/pre&gt;

&lt;p&gt;Même principe pour la fin.&lt;/p&gt;

&lt;pre&gt;
getSelectionEnd: function()
{
	if ( typeof this.selectionEnd != 'undefined' )
		return this.selectionEnd;

	// IE Support
	this.focus();
	var range = this.createTextRange();
	range.moveToBookmark(document.selection.createRange().getBookmark());
	range.moveStart('character', - this.value.length);
	return range.text.length;
}
&lt;/pre&gt;

&lt;h4&gt;Positionner le curseur&lt;/h4&gt;

&lt;p&gt;Cette fois ci, la technique est de créer une selection vide, de la positionner
au bon endroit, de d'utiliser la méthode &lt;code&gt;select()&lt;/code&gt; pour la faire apparaitre.&lt;/p&gt;

&lt;pre&gt;
setCaretPos: function(start, end)
{
	end = end || start;
	this.focus();
	if (this.setSelectionRange)
		this.setSelectionRange(start, end);
	else if (document.selection) {
		var range = this.createTextRange();
		range.moveStart('character', start);
		range.moveEnd('character', - this.value.length + end);
		range.select();
	}
}
&lt;/pre&gt;

&lt;h4&gt;Remplacer la sélection&lt;/h4&gt;

&lt;p&gt;Avec toutes ces méthodes cross-browser, la fonction de remplacement est un jeu d'enfant !&lt;/p&gt;
&lt;p&gt;J'ai ajouté un paramètre &lt;code&gt;keep&lt;/code&gt; indiquant s'il faut garder ou non le texte selectionné après remplacement.&lt;/p&gt;

&lt;pre&gt;
replaceSelection: function (str, keep)
{
	this.focus();
	
	var start = this.getSelectionStart();
	var stop = this.getSelectionEnd();
	var end = start + str.length;
	var scrollPos = this.scrollTop;
		
	this.value = this.value.substring(0, start) + str + this.value.substring(stop);
	if ( keep ) this.setCaretPos(start, end);
	else this.setCaretPos(end);
	this.scrollTop = scrollPos;
}
&lt;/pre&gt;

&lt;p&gt;En esperant que tout ceci vous servira :)&lt;/p&gt;</description>
    
    
    
          <comments>http://www.the-asw.com/post/2007/02/20/70-position-du-curseur-dans-un-textarea#comment-form</comments>
      <wfw:comment>http://www.the-asw.com/post/2007/02/20/70-position-du-curseur-dans-un-textarea#comment-form</wfw:comment>
      <wfw:commentRss>http://www.the-asw.com/feed/rss2/comments/70</wfw:commentRss>
      </item>
    
  <item>
    <title>Une interface de formulaire à base de tableaux dynamiques</title>
    <link>http://www.the-asw.com/post/2005/09/18/50-une-interface-de-formulaire-a-base-de-tableaux-dynamiques</link>
    <guid isPermaLink="false">urn:md5:561ab3e9ee1cc453fa22d9b4e2b24636</guid>
    <pubDate>Sun, 18 Sep 2005 17:25:00 +0000</pubDate>
    <dc:creator>cgo2</dc:creator>
        <category>Développement web</category>
        <category>javascript</category>    
    <description>Oui, je sais, les tableaux de mise en page c'est mal. Mais quand il s'agit de présenter des données en tableau, par exemple : le prix des carottes en fonction de la vitesse du vent et de l'age du capitaine, alors ils sont indispensables. Je dirais même plus, ça serait une erreur de ne pas les utiliser. Maintenant, imaginons que nous ayons à programmer une interface pour saisir le prix des carottes : comment faire simple, léger, accessible, rapide à développer et agréable à utiliser ? L'idéal serait de se rapprocher du fonctionnement d'un tableur : pouvoir ajouter, supprimer ou éditer des lignes, et sauvegarder le document à la fin. Et bien en interface web, c'est possible grace à Javascript et DOM (et un peu de PHP pour le traitement).    &lt;h3&gt;Première étape : construire la page&lt;/h3&gt;

&lt;p&gt;Tout d'abord, il faut faire la page web. Pour cela, on utilise du XHTML tout à fait classique, et on construit un tableau. Je vous invite à lire l'article &lt;a href=&quot;http://openweb.eu.org/articles/tableaux_css/&quot; hreflang=&quot;fr&quot;&gt;Habillage de tableaux avec des CSS&lt;/a&gt; sur Openweb pour en savoir plus sur la manière de faire un tableau conforme aux standards.&lt;/p&gt;

&lt;p&gt;Le tableau que j'ai choisi de dessiner est on-ne-peut-plus simple : il contient 4 colonnes contenants chacunes un champ de type &quot;text&quot;, et une dernière colonnes contenant les actions possibles. Pour l'instant, la seule action possible est la suppression d'une ligne.&lt;/p&gt;

&lt;p&gt;Le code donne (vous pouvez consulter &lt;a href=&quot;http://www.the-asw.com/files/web/dtable/ex1.html&quot;&gt;l'exemple 1&lt;/a&gt;) :&lt;/p&gt;

&lt;pre&gt;
&amp;lt;table class=&quot;dTable&quot;&amp;gt;
	&amp;lt;thead&amp;gt;
		&amp;lt;tr&amp;gt;
			&amp;lt;th&amp;gt;Colonne 1&amp;lt;/th&amp;gt;
			&amp;lt;th&amp;gt;Colonne 2&amp;lt;/th&amp;gt;
			&amp;lt;th&amp;gt;Colonne 3&amp;lt;/th&amp;gt;
			&amp;lt;th&amp;gt;Colonne 4&amp;lt;/th&amp;gt;
			&amp;lt;th&amp;gt;Actions&amp;lt;/th&amp;gt;
		&amp;lt;/tr&amp;gt;
	&amp;lt;/thead&amp;gt;
	
	&amp;lt;tfoot&amp;gt;
		&amp;lt;tr&amp;gt;
			&amp;lt;th colspan=&quot;5&quot;&amp;gt;&amp;lt;a href=&quot;http://www.the-asw.com/post/2005/09/18/#&quot;&amp;gt;Ajouter une ligne&amp;lt;/a&amp;gt;&amp;lt;/th&amp;gt;
		&amp;lt;/tr&amp;gt;
	&amp;lt;/tfoot&amp;gt;
	
	&amp;lt;tbody&amp;gt;
		
		&amp;lt;tr&amp;gt;
			&amp;lt;td&amp;gt;&amp;lt;input type=&quot;text&quot; name=&quot;champ1[]&quot; /&amp;gt;&amp;lt;/td&amp;gt;
			&amp;lt;td&amp;gt;&amp;lt;input type=&quot;text&quot; name=&quot;champ2[]&quot; /&amp;gt;&amp;lt;/td&amp;gt;
			&amp;lt;td&amp;gt;&amp;lt;input type=&quot;text&quot; name=&quot;champ3[]&quot; /&amp;gt;&amp;lt;/td&amp;gt;
			&amp;lt;td&amp;gt;&amp;lt;input type=&quot;text&quot; name=&quot;champ4[]&quot; /&amp;gt;&amp;lt;/td&amp;gt;
			&amp;lt;td&amp;gt;&amp;lt;a href=&quot;http://www.the-asw.com/post/2005/09/18/#&quot;&amp;gt;Supp&amp;lt;/a&amp;gt;&amp;lt;/td&amp;gt;
		&amp;lt;/tr&amp;gt;
		
	&amp;lt;/tbody&amp;gt;
&amp;lt;/table&amp;gt;
&lt;/pre&gt;

&lt;p&gt;Les liens ont tous pour trajet (&lt;code&gt;href&lt;/code&gt;) la valeur &lt;code&gt;#&lt;/code&gt;. Cela revient à dire qu'ils n'ont pas d'effet... pour l'instant. J'ai appliqué la classe &lt;code&gt;dTable&lt;/code&gt; au tableau (comme &amp;laquo;&amp;nbsp;Dynamic Table&amp;nbsp;&amp;raquo;) afin de pouvoir l'identifier parmis d'autres eventuels tableaux, qui, eux, ne seront pas dynamiques. Enfin, dernier détails, les champs &lt;code&gt;input&lt;/code&gt; ont tous un nom finissant par &lt;code&gt;[]&lt;/code&gt;. Nous verrons dans la troisième partie à quoi ça va servir.&lt;/p&gt;


&lt;h3&gt;Deuxième étape : rendre le tableau dynamique&lt;/h3&gt;

&lt;p&gt;Maintenant on rentre dans le vif du sujet. Pour rendre ce tableau dynamique, on va utiliser du Javascript et du DOM, en s'arrageant pour qu'il soit compatible Internet Explorer et Firefox.&lt;/p&gt;

&lt;p&gt;Première chose : inclure un script. Pour cela, on rajoute dans le header de la page html la ligne suivante (avec &lt;code&gt;dtable.js&lt;/code&gt; le nom du fichier script) :&lt;/p&gt;
&lt;pre&gt;&amp;lt;script type=&quot;text/javascript&quot; src=&quot;http://www.the-asw.com/post/2005/09/18/dtable.js&quot;&amp;gt;&amp;lt;/script&amp;gt;&lt;/pre&gt;

&lt;p&gt;Bien ensuite, un peu de conception... Comment allons nous procéder ?&lt;/p&gt;

&lt;h4&gt;Ajout&lt;/h4&gt;

&lt;p&gt;Pour ajouter une ligne, le plus simple est d'utiliser la méthode DOM &lt;code&gt;cloneNode()&lt;/code&gt; qui permet de dupliquer un noeud (par exemple un &lt;code&gt;tr&lt;/code&gt;, donc une ligne du tableau) et &lt;code&gt;appendChild()&lt;/code&gt; qui permet d'ajouter un noeud à un autre (par exemple le &lt;code&gt;tr&lt;/code&gt; cloné au &lt;code&gt;tbody&lt;/code&gt;, donc au corps du tableau). Cette méthode est très simple à condition d'avoir une ligne &amp;laquo;&amp;nbsp;de référence&amp;nbsp;&amp;raquo;, c'est à dire une ligne vide que l'on pourra cloner pour simuler l'ajout de ligne. La première ligne du tableau (la seule que j'ai saisis dans le code html ci-dessus) fera office de référence.&lt;/p&gt;

&lt;p&gt;Nous allons faire une fonction &lt;code&gt;addLigne&lt;/code&gt; qui prend en paramètre l'élément appellant (en l'occurence il s'agira d'un lien, donc d'un element &lt;code&gt;A&lt;/code&gt;). A partir du lien, il faudra retrouver le tableau en &amp;laquo;&amp;nbsp;remontant&amp;nbsp;&amp;raquo; dans l'arbre html à la recherche du parent s'appelant &lt;code&gt;TABLE&lt;/code&gt;. A partir du tableau, on pourra retrouver le &lt;code&gt;TBODY&lt;/code&gt; et la première ligne, et effectuer l'ajout.&lt;/p&gt;
&lt;p&gt;Pour retrouver le parent d'un élément, j'utilise une fonction récursive, &lt;code&gt;getParent(element, parentTagName)&lt;/code&gt;, dont voici l'implémentation :&lt;/p&gt;

&lt;pre&gt;
/* trouve le tag &quot;parentTagName&quot; parent de &quot;element&quot; */
function getParent(element, parentTagName) {
	if ( ! element )
		return null;
	else if ( element.nodeType == 1 &amp;&amp; element.tagName.toLowerCase() == parentTagName.toLowerCase() )
		return element;
	else
		return getParent(element.parentNode, parentTagName);
}
&lt;/pre&gt;

&lt;p&gt;Le code pour ajouter une ligne devient :&lt;/p&gt;
&lt;pre&gt;
/* ajoute une ligne */
function addLigne(link) {
	// 1. récuperer le node &quot;TABLE&quot; à manipuler
	var td = link.parentNode;
	var table = getParent(td,'TABLE');
	
	// 2. on va manipuler le TBODY
	var tbody = table.tBodies[0];
	
	// 3. on clone la ligne de reference
	var newTr = tbody.rows[0].cloneNode(true);
	tbody.appendChild(newTr);
}
&lt;/pre&gt;

&lt;p&gt;Pour appeller cette fonction, on peut transformer le lien &amp;laquo;&amp;nbsp;Ajouter une ligne&amp;nbsp;&amp;raquo; comme ceci&amp;nbsp;:&lt;/p&gt;
&lt;pre&gt;
&amp;lt;a href=&quot;http://www.the-asw.com/post/2005/09/18/#&quot; onclick=&quot;addLigne(this); return false;&quot;&amp;gt;
&lt;/pre&gt;
&lt;p&gt;Le &lt;code&gt;return false;&lt;/code&gt; permet de stopper le traitement normal du lien et donc de ne pas executer le href.&lt;/p&gt;

&lt;h4&gt;Suppression&lt;/h4&gt;

&lt;p&gt;Là encore, une fonction DOM nous mache tout le travail : &lt;code&gt;removeChild()&lt;/code&gt;. Il suffit de trouver le &lt;code&gt;TR&lt;/code&gt; à supprimer en remontant l'arbre html depuis le lien appellant, et de le retirer du &lt;code&gt;TBODY&lt;/code&gt;&lt;/p&gt;

&lt;pre&gt;
/* supprimer une ligne */
function delLigne(link) {
	// 1. récuperer le node &quot;TABLE&quot; à manipuler
	var td = link.parentNode;
	var table = getParent(td, 'TABLE');
	
	// 2. récuperer le TBODY
	var tbody = table.tBodies[0];
	
	// 3. Supprimer le TR
	tbody.removeChild(getParent(td, 'TR'));
}
&lt;/pre&gt;

&lt;p&gt;Pareil que pour l'ajout, on peut transformer les liens &amp;laquo;&amp;nbsp;Supp&amp;nbsp;&amp;raquo; comme ceci&amp;nbsp;:&lt;/p&gt;
&lt;pre&gt;
&amp;lt;a href=&quot;http://www.the-asw.com/post/2005/09/18/#&quot; onclick=&quot;delLigne(this); return false;&quot;&amp;gt;
&lt;/pre&gt;

&lt;p&gt;L'ajout et la suppression donnent &lt;a href=&quot;http://www.the-asw.com/files/web/dtable/ex2.html&quot;&gt;l'exemple 2&lt;/a&gt;.&lt;/p&gt;

&lt;h4&gt;Protéger la première ligne&lt;/h4&gt;

&lt;p&gt;Le problème de l'exemple 2, que vous avez peut-être remarqué en testant, est que la première ligne, la ligne de référence donc, est supprimable comme les autres. Et lorsqu'on supprime tous les lignes, il n'y en a plus aucune à cloner ! On va donc masquer la première ligne avec la propriété CSS &lt;code&gt;display=&quot;none&quot;&lt;/code&gt; et en ajoute une vide supplémentaire.&lt;/p&gt;

&lt;p&gt;On ajoute au code :&lt;/p&gt;

&lt;pre&gt;
window.onload = dtableInit;

/* initialise le script */
function dtableInit() {
	var table = document.getElementsByTagName('TABLE');
	for ( var i = 0; i &lt; table.length; i++ ) {
		// on récupère tous les tableaux dynamiques
		if ( table[i].className == 'dTable' ) {
			
			var tbody = table[i].tBodies[0];
			var newTr = tbody.rows[0].cloneNode(true);
			
			// on masque la première ligne du tbody (la ligne de reference)
			tbody.rows[0].style.display = 'none';
			
			// on en ajoute une
			tbody.appendChild(newTr);
			
		}
	}
}
&lt;/pre&gt;

&lt;p&gt;Un dernier problème subsiste : lorsqu'on clone cette ligne, son style est cloné également. Toutes les lignes sont donc invisibles ! Il faut ajouter à la fin de &lt;code&gt;addLigne&lt;/code&gt; de quoi les remettres visibles :&lt;/p&gt;
&lt;pre&gt;
	if ( document.all )
		newTr.style.display = &quot;block&quot;; // pour IE
	else
		newTr.style.display = &quot;table-row&quot;; // pour Gecko
&lt;/pre&gt;

&lt;p&gt;L'utilisation de &lt;code&gt;document.all&lt;/code&gt; permet de détecter s'il s'agit d'IE ou pas. En effet, seul ce navigateur implémente cette propriété (non-standard).&lt;/p&gt;
&lt;p&gt;Vous pouvez tester ce code dans &lt;a href=&quot;http://www.the-asw.com/files/web/dtable/ex3.html&quot;&gt;l'exemple 3&lt;/a&gt;.&lt;/p&gt;

&lt;h3&gt;Troisième étape : traiter les données&lt;/h3&gt;

&lt;p&gt;Grace à leur nom finissant par &lt;code&gt;[]&lt;/code&gt;, les valeurs des champs &lt;code&gt;input&lt;/code&gt; seront assemblées dans un tableau lors du post du formulaire. Résultat : on se retrouve avec 4 tableaux : &lt;code&gt;champ1&lt;/code&gt;, &lt;code&gt;champ2&lt;/code&gt;, &lt;code&gt;champ3&lt;/code&gt; et &lt;code&gt;champ4&lt;/code&gt; correspondants aux 4 colonnes du tableaux html. Les lignes de ces tableaux correspondent aux lignes du tableau html (en commençant par 0).&lt;/p&gt;
&lt;p&gt;Imaginons qu'il faille mettre à jour une base, le plus rapide est de tout supprimer puis de réinsérer les données directement ! Pas besoin de s'embêter à trouver ce qui a changé puisque tout est renvoyé.&lt;/p&gt;
&lt;p&gt;Dernière chose : au moment de traiter ces données, il ne faut pas oublier d'oublier l'index 0, qui correspond à la ligne de référence.&lt;/p&gt;

&lt;p&gt;Vous pouvez tester le résultat renvoyé par le serveur grace à &lt;a href=&quot;http://www.the-asw.com/files/web/dtable/dtable.php&quot;&gt;l'exemple 4&lt;/a&gt;.&lt;/p&gt;

&lt;h3&gt;Conclusion&lt;/h3&gt;
&lt;p&gt;Rajouter des fonctions à ce script est extrement simple : il suffit de veiller à ne pas toucher à la première ligne. On peut par exemple imaginer des fonctions permettant de monter une ligne, de la descendre, de la dupliquer, etc. Bref, les possibilités de créer des interfaces web se rapprochant de celles des clients lourds sont de plus en plus nombreuses et de plus en plus simples à mettre en oeuvre grace notamment aux standards du W3C !&lt;/p&gt;</description>
    
    
    
          <comments>http://www.the-asw.com/post/2005/09/18/50-une-interface-de-formulaire-a-base-de-tableaux-dynamiques#comment-form</comments>
      <wfw:comment>http://www.the-asw.com/post/2005/09/18/50-une-interface-de-formulaire-a-base-de-tableaux-dynamiques#comment-form</wfw:comment>
      <wfw:commentRss>http://www.the-asw.com/feed/rss2/comments/50</wfw:commentRss>
      </item>
    
  <item>
    <title>Centrer un float en CSS</title>
    <link>http://www.the-asw.com/post/2005/08/23/46-centrer-un-float-en-css</link>
    <guid isPermaLink="false">urn:md5:3e81973e788f8353c4a67dc22d334486</guid>
    <pubDate>Tue, 23 Aug 2005 21:32:00 +0000</pubDate>
    <dc:creator>cgo2</dc:creator>
        <category>Développement web</category>
        <category>css</category><category>javascript</category>    
    <description>Une zone - la galerie - doit être constituée de un ou plusieurs éléments - les boites - centrés à l'interieur et sur une seule ligne. En HTML &amp;laquo;&amp;nbsp;à la papy&amp;nbsp;&amp;raquo; c'est très facile à faire : la galerie est une cellule d'un tableau avec la propriété &lt;code&gt;align=&quot;center&quot;&lt;/code&gt;, et le contenu est un tableau d'une seule ligne dont le nombre de cellules varie de 1 à 5 (le nombre maximum de boites pour tenir sur une seule ligne). Mais comment faire ça en CSS ?    &lt;h3&gt;Problématique&lt;/h3&gt;

&lt;p&gt;L'effet recherché ressemble à ça :&lt;/p&gt;

&lt;p class=&quot;center&quot;&gt;&lt;img src=&quot;http://www.the-asw.com/images/web/centragecss_shema_1.png&quot; alt=&quot;L'effet recherché&quot; /&gt;&lt;/p&gt;

&lt;p&gt;Ma première idée, pour placer les boîtes est d'utiliser le positionnement float avec un &lt;code&gt;hr&lt;/code&gt; et la propriété &lt;code&gt;clear : both;&lt;/code&gt; comme expliqué dans &lt;a href=&quot;http://openweb.eu.org/articles/initiation_float/&quot; hreflang=&quot;fr&quot;&gt;ce très bon article sur OpenWeb&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Au niveau code ça donne : &lt;/p&gt;

&lt;pre&gt;
&amp;lt;div class=&quot;galerie&quot;&amp;gt;
	&amp;lt;div class=&quot;boîte&quot;&amp;gt;boîte 1&amp;lt;/div&amp;gt;
	&amp;lt;div class=&quot;boîte&quot;&amp;gt;boîte 2&amp;lt;/div&amp;gt;
	&amp;lt;div class=&quot;boîte&quot;&amp;gt;boîte 3&amp;lt;/div&amp;gt;
	&amp;lt;div class=&quot;boîte&quot;&amp;gt;boîte 4&amp;lt;/div&amp;gt;
	&amp;lt;div class=&quot;boîte&quot;&amp;gt;boîte 5&amp;lt;/div&amp;gt;
	
	&amp;lt;hr class=&quot;clear&quot; /&amp;gt;
&amp;lt;/div&amp;gt;
&lt;/pre&gt;

&lt;p&gt;Appliquons le style suivant :&lt;/p&gt;

&lt;pre&gt;
.galerie {
	background : #ccc;
	width : 360px; /* (50 + (5 * 2) + 10) * 5 + 10 */
}
.boîte {
	background : #69c;
	
	float : left;
	margin : 10px 0 10px 10px;
	padding : 5px;
	width : 50px;
	
	text-align : center;
}
.clear {
	clear : both;
	visibility : hidden;
}
&lt;/pre&gt;

&lt;p&gt;&amp;Ccedil;a donne :&lt;/p&gt;

&lt;p class=&quot;center&quot;&gt;&lt;img src=&quot;http://www.the-asw.com/images/web/centragecss_exemple_1.png&quot; alt=&quot;Exemple 1.1&quot; /&gt;&lt;/p&gt;
&lt;p&gt;Avec 3 boîtes uniquement :&lt;/p&gt;
&lt;p class=&quot;center&quot;&gt;&lt;img src=&quot;http://www.the-asw.com/images/web/centragecss_exemple_2.png&quot; alt=&quot;Exemple 1.2&quot; /&gt;&lt;/p&gt;

&lt;p&gt;Vous pouvez tester &lt;a href=&quot;http://www.the-asw.com/files/web/centragecss/index.html#ex1&quot;&gt;ce premier exemple&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Le positionnement est celui recherché lorsque toutes les boîtes sont présentes, mais, malheureusement, dès qu'il manque des boîtes, celles restantes sont calées à gauche. C'est tout à fait logique puisqu'elles sont flottantes à gauche, mais ce n'est pas ce que nous voulons !&lt;/p&gt;


&lt;h3&gt;Un deuxième conteneur pour le centrage&lt;/h3&gt;

&lt;p&gt;Au départ, j'ai simplement essayé &lt;a href=&quot;http://css.alsacreations.com/Faire-une-mise-en-page-sans-tableaux/Centrer-les-elements-ou-un-site-web-en-CSS&quot; hreflang=&quot;fr&quot;&gt;quelques techniques de centrage css&lt;/a&gt; appliquées sur les fiches ou sur le conteneur. Mais rien de tout ça ne fonctionne.&lt;/p&gt;

&lt;p&gt;Le problème est qu'on ne peut pas centrer un flottant, à cause de sa conception même. Comme écrit très justement dans &lt;a href=&quot;http://openweb.eu.org/articles/initiation_float/&quot; hreflang=&quot;fr&quot;&gt;l'article d'Openweb&lt;/a&gt; : &lt;q&gt;Une boîte flottante est retirée du flux normal, et placée le plus à droite (float: right) ou le plus à gauche (float: left) possible dans son conteneur.&lt;/q&gt; Il est donc logique que les techniques de centrage ne puisse pas s'appliquer (centrer par rapport à quoi, puisque la boîte est retirée du flux ?).&lt;/p&gt;

&lt;p&gt;Par contre, un élément non-flottant peut, lui, être centré (par exemple avec la technique des marges &lt;code&gt;auto&lt;/code&gt;). Imaginons que l'on crée un autre conteneur, qui soit centré par rapport au premier (la galerie), et qui contienne les fiches...&lt;/p&gt;

&lt;p class=&quot;center&quot;&gt;&lt;img src=&quot;http://www.the-asw.com/images/web/centragecss_shema_2.png&quot; alt=&quot;L'effet recherché&quot; /&gt;&lt;/p&gt;

&lt;p&gt;Au niveau code ça donne :&lt;/p&gt;

&lt;pre&gt;
&amp;lt;div class=&quot;galerie&quot;&amp;gt;
	&amp;lt;div class=&quot;conteneur&quot;&amp;gt;
		&amp;lt;div class=&quot;boîte&quot;&amp;gt;boîte 1&amp;lt;/div&amp;gt;
		&amp;lt;div class=&quot;boîte&quot;&amp;gt;boîte 2&amp;lt;/div&amp;gt;
		&amp;lt;div class=&quot;boîte&quot;&amp;gt;boîte 3&amp;lt;/div&amp;gt;
		&amp;lt;div class=&quot;boîte&quot;&amp;gt;boîte 4&amp;lt;/div&amp;gt;
		&amp;lt;div class=&quot;boîte&quot;&amp;gt;boîte 5&amp;lt;/div&amp;gt;
		
		&amp;lt;hr class=&quot;clear&quot; /&amp;gt;
	&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&lt;/pre&gt;

&lt;p&gt;On applique le même style que précédemment. Mais il faut rajouter de quoi centrer le conteneur :&lt;/p&gt;

&lt;pre&gt;
.galerie {
	text-align : center; /* uniquement pour IE */
}
.conteneur {
	margin : 0 auto;
}
&lt;/pre&gt;

&lt;p&gt;Là se pose un problème - &lt;em&gt;LE&lt;/em&gt; problème devrais-je dire - : pour que ça fonctionne il faut que le conteneur enveloppe parfaitement les boîtes, et donc soit exactement à la bonne taille. La formule donnant la taille est facile à trouver :&lt;/p&gt;
&lt;pre&gt;
taille = nombre de boîtes * ( width + padding + margin-left ) + margin-right
&lt;/pre&gt;
&lt;p&gt;Mais je n'ai strictement aucune idée de comment faire ça en CSS. C'est théoriquement possible de le fixer dans un style inline (dans la page) appliqué au moment où le script qui génére la page affiche les boîtes. Une autre solution est d'utiliser &lt;acronym title=&quot;Document Objet Model&quot;&gt;DOM&lt;/acronym&gt; pour manipuler en Javascript les styles de la page.&lt;/p&gt;

&lt;h3&gt;Implémentation en Javascript/DOM&lt;/h3&gt;

&lt;p&gt;Le script doit se charger de calculer la taille en fonction du nombre d'éléments contenus. Pour ça il faut :
&lt;ol&gt;
&lt;li&gt;Trouver le conteneur à agrandir ; on utilisera la méthode &lt;code&gt;getElementsById&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;Compter le nombre de boîtes contenues :
	&lt;ul&gt;
		&lt;li&gt;Trouver les éléments &lt;code&gt;div&lt;/code&gt; avec la méthode &lt;code&gt;getElementsByTagName&lt;/code&gt;&lt;/li&gt;
		&lt;li&gt;Eliminer ceux qui ne sont pas directement fils du conteneur (si les boîtes contiennent d'autres divs par exemple&lt;/li&gt;
	&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;Calculer la taille et agrandir le conteneur&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Mon implémentation (qui n'est sûrement pas optimale) :&lt;/p&gt;
&lt;pre&gt;
&amp;lt;script type=&quot;text/javascript&quot;&amp;gt;
 // &amp;lt;![CDATA[
function setContainerSize(truc) {
	var navroot = document.getElementById(truc);
	if ( navroot ) {
		var lis = navroot.getElementsByTagName(&quot;div&quot;);
		/* XXX : y a-t-il un moyen plus simple de ne détecter que les divs de rang 1 ?
		 *       ou, détecter selon une classe ? */
		var ok = 0; var nok = 0;
		for ( i = 0; i &amp;lt; lis.length; i++ ) {
			if ( lis[i].parentNode != navroot )
				nok++;
			else 
				ok++;
		}
		navroot.style.width = ok * 70 + 10 + 'px';
	}
}
 // ]]&amp;gt;
&amp;lt;/script&amp;gt;
&lt;/pre&gt;

&lt;p&gt;Maintenant, pour utiliser cette fonction, on effectue les modifications suivantes :&lt;/p&gt;
&lt;pre&gt;
&amp;lt;body &lt;strong&gt;onload=&quot;setContainerSize('c1');&quot;&lt;/strong&gt;&amp;gt;
...
&amp;lt;div class=&quot;conteneur&quot; &lt;strong&gt;id=&quot;c1&quot;&lt;/strong&gt;&amp;gt;
&lt;/pre&gt;

&lt;p&gt;&amp;Ccedil;a donne :&lt;/p&gt;

&lt;p class=&quot;center&quot;&gt;&lt;img src=&quot;http://www.the-asw.com/images/web/centragecss_exemple_3.png&quot; alt=&quot;Exemple 2&quot; /&gt;&lt;/p&gt;

&lt;p&gt;Vous pouvez consulter &lt;a href=&quot;http://www.the-asw.com/files/web/centragecss/index.html#ex2&quot;&gt;cet exemple&lt;/a&gt;.&lt;/li&gt;

&lt;h3&gt;Limites et pistes de reflexions&lt;/h3&gt;

&lt;p&gt;Cette méthode a été testée avec succès sur IE 6, Firefox 1.x, Safari 1.3 et Camino 0.9.&lt;/p&gt;

&lt;p&gt;Une limitation principale de cette méthode est l'impossibilité de centrer sur plusieurs lignes. Par exemple, si la première ligne contient 5 boîtes et la deuxième 2, les 2 seront calées à gauche. Je n'ai pas vraiment cherché comment résoudre ce problème, car ça n'était pas mon besoin.&lt;/p&gt;
&lt;p&gt;L'autre amélioration possible concerne l'implémentation du script, et notamment la façon de compter les éléments &lt;code&gt;div&lt;/code&gt; qui n'est sûrement pas optimale. Il serait également intéressant de pouvoir ne pas coder en dur les tailles des div dans le script, de manière à avoir du code réutilisable. Mais là ça dépasse mes connaissance en DOM :)&lt;/p&gt;
&lt;p&gt;Enfin, étant donné que le centrage se fait par un script, les boîtes ne sont pas centrées tant que la page n'est pas complètement chargée. Dans certains cas ça provoque un petit décalage à l'écran le temps que le chargement se termine...&lt;/p&gt;

&lt;h3&gt;Quelques liens supplémentaires&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;http://css.alsacreations.com/Faire-une-mise-en-page-sans-tableaux/Centrer-les-elements-ou-un-site-web-en-CSS&quot; hreflang=&quot;fr&quot;&gt;Centrer les éléments ou un site web en CSS&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;http://www.mozilla.org/docs/dom/domref/&quot; hreflang=&quot;en&quot;&gt;Gecko DOM Reference&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Merci à Scara, MrGecko et tout le &lt;a href=&quot;http://www.the-asw.com/articles/irc/&quot;&gt;chan #asw&lt;/a&gt; pour la relecture ;)&lt;/p&gt;</description>
    
    
    
          <comments>http://www.the-asw.com/post/2005/08/23/46-centrer-un-float-en-css#comment-form</comments>
      <wfw:comment>http://www.the-asw.com/post/2005/08/23/46-centrer-un-float-en-css#comment-form</wfw:comment>
      <wfw:commentRss>http://www.the-asw.com/feed/rss2/comments/46</wfw:commentRss>
      </item>
    
</channel>
</rss>