Overblog Suivre ce blog
Editer l'article Administration Créer mon blog
16 novembre 2008 7 16 /11 /novembre /2008 17:09

Nous voilà partis pour le démontage/remontage du programme modulesPliants.js, celui qui permet de donner une classe ou une autre à un module lorsqu'on clique sur sa barre de titre. Il est présenté dans cet article et voici son code source :

 function moduleCliquable(id,etat) { function clicTitre(e) { e = e || window.event; var s=e.target||e.srcElement; if (!s)return true; if (s.nodeType == 3||s.nodeType == 4) s = s.parentNode; while(!(/\bbox\s/.test(s.className)) ) s=s.parentNode; if (/\bon\b/.test(s.className)) s.className=s.className.replace(/\bon\b/,' off '); else if (/\boff\b/.test(s.className)) s.className=s.className.replace(/\boff\b/,' on '); else s.className+=' on'; return false; } var r,rr,rBox,rTitre,i; if (!id) return; rBox=document.getElementById(id); if (!rBox||!rBox.className||! /\bbox\b/.test(rBox.className)) return; rr=rBox.getElementsByTagName('div'); for (i=0;r=rr[i];i++) { if (!r.className||! /\bbox-titre\b/.test(r.className)) continue; rTitre=r; break; } if (!rTitre) {alert("Pas de titre pour "+id+" ?");return} if(etat!='on' && etat!='off') etat='on'; rBox.className+=' '+etat; if (rTitre.addEventListener) rTitre.addEventListener('click',clicTitre,false); else if (rTitre.attachEvent) rTitre.attachEvent('onclick',clicTitre); } 

C'est pas simple

En tout cas c'est plus compliqué que d'habitude, autant vous avertir. Il faudra réfléchir un bon coup avant de se lancer, et s'instruire en cours de route.

Ce qu'on veut obtenir : qu'un clic sur le titre du module fasse "quelque chose" dans le module où se trouve ce titre. "Quelque chose" consiste à ajouter telle ou telle classe (on ou off) au module.

SI nous pouvions (MAIS nous ne le pouvons pas) modifier le source HTML du titre du module, nous y ajouterions un onclick pour aboutir à :

 <div class="box ...."> <div class="box-titre" onclick="/* faire quelque chose */"> <h2><span>titre du module</span></h2> </div> 

Le problème serait alors  simplement  de concevoir le /* faire quelque chose */. MAIS, puisque nous ne pouvons pas intervenir sur ce code HTML, nous devons accomplir deux tâches au lieu d'une, et écrire deux fonctions :

  1. une fonction pour /* faire quelque chose */, ce qu'on appelle un event handler en VO et un gestionnaire d'événements en bon français. L'événement à gérer est le clic sur le titre, bien sûr.
  2. une fonction pour greffer ce gestionnaire d'événements au bon endroit, qui est le div de classe box-titre contenu dans le module, lui-même de classe box.

Ces deux fonctions vont s'exécuter à des moments différents. Le  greffeur , dans notre cas rien d'autre que la fonction moduleCliquable, agira une seule fois. Le gestionnaire, lui, attendra tranquillement que le visiteur clique sur le titre : tôt, tard, peut-être plusieurs fois, peut-être jamais, et en tout cas longtemps après la fin de l'exécution du  greffeur . C'est bien pour ça qu'on a besoin de créer deux fonctions distinctes.

Bien sûr, si vous avez déjà lu quelques-uns de mes  démontages , vous voyez venir un certain nombre de questions subalternes et vous en connaissez les réponses :

  • le  greffeur  de gestionnaire devra trouver le module, lui donner son état initial, puis trouver le titre du module : on a déjà fait ce genre de choses. Ensuite il devra greffer le gestionnaire au titre, ça c'est nouveau.
  • le gestionnaire, lui, devra remonter de l'élément sur lequel on a cliqué jusqu'au module lui-même, puis lire et modifier la classe de ce module : ça aussi, c'est du déjà vu. Mais comment le gestionnaire saura-t-il sur quel élément on a cliqué : le div, le h2 ou le span? Nouveauté encore.

Je vous propose, comme d'habitude, de construire ces deux fonctions progressivement : de la vue générale vers les détails. Cependant il faudra bien faire une pause pour bavarder d'événéments – pas un cours complet, juste le nécessaire. Ensuite seulement nous compléterons l'ébauche. Prenez un bon fauteuil.

Le  greffeur 

Premier jet

C'est au  greffeur  qu'on indique le module à traiter (identifié par… son identifiant !) et, en option, l'état initial qu'on souhaite donner à ce module. Gagnons une étape : la liste de courses se trouve directement dans l'ébauche, sous forme de commentaires :

 function moduleCliquable(id_du_module, etat_initial) { /* chercher le module */ /* si absent, abandon */ /* chercher la barre de titre */ /* si absente, message d'erreur et abandon */ /* si un état initial est fourni, vérifier sa validité */ /* si l'état initial est absent ou invalide, le prendre égal à on */ /* ajouter l'état initial dans la liste des classes du module */ /* greffer le gestionnaire d'événements au titre */ } moduleCliquable(id_du_1er_module); moduleCliquable(id_du_2eme_module); moduleCliquable(id_du_3eme_module); /* etc*/ 

Stop ! Ce premier jet est tout à fait classique et correct, mais pas pratique : les modules à rendre cliquables sont au choix de l'auteur du blog, on ne va pas lui imposer de modifier le fichier JS à chaque fois. C'est peu commode et source inépuisable d'erreurs. Donc les appels à moduleCliquable s'écriront directement dans le pied de page du blog, après l'appel au fichier JS. Ça vous semble rationnel ? Poursuivons.

Début de réalisation

Occupons-nous de tous les tests préliminaires :

 function moduleCliquable(id,etat) { var r,rr,rBox,rTitre,i; if (!id) return; // argument id oublié : on ne peut rien faire ! rBox=document.getElementById(id); // rBox : référence du module, peut-être if (!rBox||!rBox.className||! /\bbox\b/.test(rBox.className)) return; // 3 tests combinés : rBox existe ? a une classe ? la bonne classe ? rr=rBox.getElementsByTagName('div'); // rr : tous les div du module, on va y chercher le titre for (i=0;r=rr[i];i++) // boucle d'exament des div { if (!r.className||! /\bbox-titre\b/.test(r.className)) continue; // 2 test combinés : r a une classe ? la bonne classe ? rTitre=r; break; // le titre est trouvé : on interrompt la boucle } if (!rTitre) {alert("Pas de titre pour "+id+" ?");return} // sait-on jamais : pas de titre ??? if(etat!='on' && etat!='off') etat='on'; // vérifie l'état initial proposé. En cas de doute, on prend 'on' rBox.className+=' '+etat; // le module a désormais la classe 'etat' en plus de celles qu'il avait déjà /* greffer le gestionnaire d'événements au titre */ } 

Je me contente de commenter rapidement chaque instruction, toutes les techniques utilisées ici sont présentées plus en détail dans d'autres  démontages . Comme d'habitude je fais du  ceinture et bretelles  en matière de tests : systématiquement vérifier que quelque chose existe avant d'en tester la valeur, systématiquement vérifier que tout ce dont on aura besoin ensuite existe, que les arguments ont une valeur acceptable, etc. et toujours penser au cas où le test rate. Maintenant, calez-vous bien dans le fauteuil.

Petit amphi : les événements

Un événement c'est quoi ? Tout ce qui peut se produire dans une page tant qu'elle est à l'écran.

La fin de son chargement est un événement, le début de son déchargement en est un autre (exercice : pourquoi le début du chargement et la fin du déchargement sont-ils des événéments indétectables ?). Bouger la souris,  scroller  la fenêtre, la redimensionner, cliquer quelque part, frapper une touche… sont des événements. Plus subtil : créer ou supprimer un petit (ou gros) div à l'aide de JavaScript est encore un événement, et je crois bien que changer un style ou une classe en sont aussi. J'avais bien dit : tout !

Un événement a une source : l'endroit où il se produit. Pour la fin de chargement de la page la source est le document, pour un clic c'est l'élément où vous cliquez, etc.

Un événement, enfin, se propage et c'est bien pratique. Question : si vous cliquez "dans le titre du module", vous cliquez dans quoi, exactement ? Selon la mise en page et selon la précision de votre visée ce peut être dans le span, le h2 ou le div. Hé ouais. Faut-il prévoir explicitement un traitement pour chacun de ces cas, attacher un onclick à chacun de ces éléments ? Looooourd. En fait quand vous cliquez sur, mettons, le span, tout à fait à l'intérieur du titre, il se produit non pas un ni trois, mais une kyrielle d'événements : l'événement d'origine, "cliquer dans le span", est propagé de parent en parent. Il y aura donc un événement clic dans le h2, puis dans le div, puis dans le module, puis dans la colonne des modules, puis… jusqu'à la page elle-même. L'événément  monte  comme une bulle dans une flûte de champagne, c'est pourquoi ce processus s'appelle event bubbling.

Bien : il se produit donc un tas d'événements partout. Un événement, on en fait quoi ? Le plus souvent : rien. Si vous cliquez au hasard dans le fond du blog il ne se passe rien. Si vous cliquez sur un titre de module, la bulle monte jusqu'au document où elle éclate sans laisser de trace. Il ne se produit rien SAUF. Sauf si un ou plusieurs des éléments qui voient passer la bulle sont dotés d'un gestionnaire de cet événement.

Un gestionnaire d'événements, c'est quoi ? Une série d'instructions (autrement dit : une fonction) attachée à un élément du document, et qui se déclenche quand elle voit passer l'événement. Ah ben celle-là, on ne l'avait pas vu venir.

Dans le cas de ce que nous cherchons à faire : si on clique sur le span, le h2 ou le div, l'événement monte jusqu'au div. Là, le gestionnaire que nous aurons greffé (je vous expliquerai comment) l'attrape, y lit tout ce qui l'intéresse (je vous expliquerai) et agit, puis laisse filer l'événement au niveau supérieur et au-delà. Ça semble clair ? En tout cas, ça a déjà deux conséquences :

  1. la source de l'événement n'est pas forcément l'élément qui le traite : l'événement peut avoir eu lieu dans un descendant de qui le traite ;
  2. il aurait été, dans notre cas, vraiment lourd de mettre un gestionnaire d'événements à chacun des trois niveaux : on risquait de déclencher de une à trois actions pour un seul clic !

Lestés de cette science nouvelle, écrivons le gestionnaire d'événements.

Fabriquer le gestionnaire d'événements

Récupérer les informations sur l'événément

Nous y voilà. Ce gestionnaire sera une fonction, on l'a dit, baptisons-la clicTitre et écrivons :

 function clicTitre() { /* mais qu'est-ce qu'on va bien pouvoir faire ?*/ } 

Une fonction c'est bien joli mais, d'habitude, ça a des arguments, des informations qu'on lui passe pour qu'elle travaille, non ? Très juste. Celle-ci en a, un seul, et ce n'est pas vous qui le choisissez mais le navigateur qui le transmet. C'est un objet, par convention on l'appelle e comme event :

 function clicTitre(e) { /* mais qu'est-ce qu'on va faire de e ?*/ } 

Cet objet e contient tout ce que qu'on peut savoir sur l'événement. Sa source bien sûr, et tous les renseignements pertinents selon le type d'événement : position de la souris et bouton actionné pour un événément de souris, touche frappée pour un événement de clavier, amplitude du déplacement pour un "scroll"… bref, tout. C'est toujours comme ça, sauf… sauf avec IE. Lui ne transmet pas d'objet e mais tient à jour un objet unique window.event, contenant à peu près les mêmes informations. Pour tout simplifier, il est des cas où IE transmet tout de même un argument à la fonction.

Comment s'en sortir ? Surtout pas en cherchant à savoir quel navigateur on utilise (browser detection, aussi appelée browser sniffing) mais seulement en cherchant si ce navigateur offre ce qu'on désire (capability detection). Pourquoi "surtout pas" ? D'abord parce qu'on n'est jamais sûr d'avoir la bonne réponse : nombreuses versions d'un même navigateur, divers modes de fonctionnement, navigateurs peu répandus déclarant qu'ils sont "presque comme" tel grand, etc. . Ensuite parce que ce n'est pas vraiment la question : on veut simplement savoir si e contient quelque chose, sans quoi on se rabat sur window.event. La manière la plus courte de le dire est :

 e = e || window.event; // si e est défini : e = lui-même // sinon e = window.event 

Ce point réglé, quelle est la source de l'événement ? Là aussi, différence : les navigateurs DOM l'indiquent dans e.target et IE dans e.srcElement. Même genre de difficulté que pour l'objet événement, même genre de réponse :

 var s=e.target||e.srcElement; 

Prudence : si jamais on n'avait rien obtenu ?

 if (!s) return true ; 

Pourquoi true ? On est dans un gestionnaire d'événements attaché à un élément, quelque chose qui agit en supplément du comportement par défaut de l'élément. Le navigateur attend du gestionnaire qu'il réponde à la question "Dois-je appliquer aussi le traitement par défaut ?". Donc, généralement, false si le gestionnaire a pu faire son travail et true s'il n'a pas pu.

Une dernière précaution : il arrive que certaines versions anciennes de Safari considèrent que l'événement s'est produit non pas dans l'élément (span, h2 ou div) mais dans le texte de l'élément. Ce peut être gênant : un pur texte n'a ni classe ni style ni rien… juste du texte. Heureusement la parade existe :

 if (s.nodeType == 3||s.nodeType == 4) s = s.parentNode; 

Au bout de tout ça, notre ébauche de gestionnaire ressemble à ça :

 function clicTitre(e) { e = e || window.event; var s=e.target||e.srcElement; if (!s)return true; if (s.nodeType == 3||s.nodeType == 4) s = s.parentNode; // à ce point on connaît la source s de l'événément. /* il est temps de faire le vrai boulot !*/ return false; // false parce que le boulot a été fait. } 

Tant d'explications pour si peu de chose ? Vous êtes dur : vous avez là un modèle tout à fait général de gestionnaire d'événements, ça sert à tout bout de champ ! Ne nous reste plus qu'à écrire le traitement dont nous avons besoin dans notre cas particulier.

Faire le travail

Il consiste en deux choses :

  1. remonter de la source de l'événement au module qui contient cette source,
  2. et tripoter la classe de ce module.

Le premier point est simple à traiter : on remonte de parent en parent jusqu'à en trouver un de classe box, ce qui se fait en une instruction :

 while(!(/\bbox\b/.test(s.className)) ) s=s.parentNode; 

Oups ! Ça marche pas ! Cela vient de l'expression rationnelle (regexp) utilisée. \bbox\b signifie : "limite de mot-b-o-x-limite de mot". Et qu'est-ce qu'une limite de mot ? Le début de la chaîne ou sa fin, un espace, certains signes de ponctuation. Le tiret "-" fait partie de ces "certains signes de ponctuation". Et dans la remontée vers le module on tombe sur le div du titre, dont la classe est box-titre. Donc la remontée s'arrête là. Arf, il faut improviser. Heureusement, la classe d'un module est toujours box autre_chose, ce qui nous offre une échappatoire : chercher un espace après "b-o-x", et l'instruction devient :

 while(!(/\bbox\s/.test(s.className)) ) s=s.parentNode; 
… et ça, ça marche !

Deuxième point : modifier la classe du box. En français :

  • si le className contient le mot on, on le remplace par off,
  • si le className contient le mot off, on le remplace par on,
  • s'il ne contient aucun des deux (situation anormale puisque le module est réputé avoir été initialisé) on lui ajoute la classe on (solution de repêchage, sans doute critiquable).

Cela se traite encore à coups d'expressions rationnelles

 if (/\bon\b/.test(s.className)) s.className=s.className.replace(/\bon\b/,' off '); else if (/\boff\b/.test(s.className)) s.className=s.className.replace(/\boff\b/,' on '); else s.className+=' on'; 

Fin de l'écriture du gestionnaire d'événements, et récapitulation :

 function clicTitre(e) { e = e || window.event; var s=e.target||e.srcElement; if (!s)return true; if (s.nodeType == 3||s.nodeType == 4) s = s.parentNode; while(!(/\bbox\s/.test(s.className)) ) s=s.parentNode; if (/\bon\b/.test(s.className)) s.className=s.className.replace(/\bon\b/,' off '); else if (/\boff\b/.test(s.className)) s.className=s.className.replace(/\boff\b/,' on '); else s.className+=' on'; return false; } 

Soufflons cinq minutes

Faisons le point, je sens que vous avez la tête comme un compteur à gaz :

  • nous avons écrit, presque complètement, la fonction principale moduleCliquable qui prépare le module et son titre,
  • nous avons écrit clicTitre, la fonction qui se déclenchera lors du clic sur le titre,
  • il nous reste à écrire, dans moduleCliquable, de quoi greffer le gestionnaire clicTitre au div de titre du module : rTitre.

Et là, je suis obligé de vous infliger un autre amphi…

Autre amphi : les gestionnaires d'événements.

Il existe deux manières d'ajouter un gestionnaire d'événements :

  1. la manière  classique  et ancienne que vous connaissez peut-être déjà : onclick="/* faire quelque chose*/ "
  2. la manière  moderne , DOM, W3C, ECMA… que je m'en vas vous exposer bientôt.

Sans vous donner tous les détails des nuances entre les deux, voici quelques points à retenir :

  • la manière classique est bien rodée, et tous les navigateurs l'implémentent de la même manière. Très bon point pour elle.
  • elle ne permet d'attribuer qu'une seule fonction à l'élément. Si vous avez besoin d'ajouter une autre fonction il vous faut gérer à la main l'enchaînement des deux. Très mauvais point, bloquant, lorsqu'on se met à empiler les gadgets sur un blog.
  • la manière DOM permet de gérer proprement plusieurs gestionnaires pour un même élément, de les ajouter et les enlever sans difficulté. Bon point.
  • Internet Explorer, comme toujours, l'accommode à sa propre sauce. Pénible mauvais point mais surmontable (évidemment que je vais vous expliquer !)

Dans notre cas, et bien que nous ne puissions pas tripoter le code HTML, nous avons le choix. Le gestionnaire onclick est en effet un attribut de l'élément au même titre que sa classe, son title ou son style. Nous pourrions donc écrire :

 refTitre.onclick=clicTitre ; // PAS de parenthèses après clicTitre ! 

C'est ça, la méthode classique. Pourquoi : PAS de parenthèses ! Hein, pourquoi ? Si l'on avait écrit clicTitre(), on aurait déclenché l'exécution de clicTitre puis utilisé son résultat (true ou false) en guise de gestionnaire onclick. Pas terrible.

Inversement clicTitre sans parenthèses désigne la fonction elle-même (=son adresse en mémoire) plutôt que le résultat de son exécution. C'est bien ce que nous désirons : que le gestionnaire d'événements soit cette fonction et non une constante true ou false.

Puisque c'est simple et que ça marche, pourquoi s'en priver ?

Je vous l'ai dit, ce procédé fait de clicTitre le seul gestionnaire de clic attaché à refTitre. Or il peut y en avoir déjà un ou plusieurs autres. Dans notre cas précis, non : OB n'en met aucun – mais ça peut changer. Par ailleurs, un autre programme JavaScript, récupéré ici ou là, le fera peut-être.

Alors, autant apprendre la méthode qui ménage l'avenir, d'autant qu'elle n'est pas très compliquée.

Greffer le gestionnaire d'événements

Comme toujours, il existe une manière normalisée, W3C, DOM… de faire les choses et une manière IE.

Manière normalisée :

 rTitre.addEventListener('click',clicTitre,false); 

Manière IE :

 rTitre.attachEvent('onclick',clicTitre); 

C'est très proche, si ce n'est qu'on écrit click dans un cas et onclick dans l'autre, et qu'il y a un argument false sur lequel je ne m'étendrai pas : il correspond à quelque chose qui est possible dans les navigateurs convenables et pas dans IE. Notez aussi que, pas plus que dans la méthode classique, on n'écrit de parenthèses après clicTitre, et cela pour les mêmes raisons.

Comment distinguer le cas IE du cas non-IE ? Comme précédemment : toujours pas question de détecter le navigateur employé, on lui demande plutôt ce qu'il sait faire – en clair, quelles méthodes il propose. Ce qui donne :

 if (rTitre.addEventListener) rTitre.addEventListener('click',clicTitre,false); else if (rTitre.attachEvent) rTitre.attachEvent('onclick',clicTitre); 

Paraphrase de ces instructions : rTitre possède-t-il la méthode addEventListener ? Si oui, je l'utilise. Si non, possède-t-il la méthode attachEvent ? Si oui, je l'utilise… et si non, ce navigateur est vraiment une vieille bouse et je laisse tomber (=pas d'autre else)

On aurait pu, dans le cas de la  vieille bouse , décider au contraire de passer en force et ajouter une dernière ligne :

 else rTitre.onclick=clicTitre; 

Affaire d'évaluation personnelle : j'ai pensé qu'un navigateur incapable de traiter l'une ou l'autre des deux branches ne devait pas non plus se sentir très à l'aise avec le CSS. Comme le recours au CSS est le complément indispensable de ce programme, mieux valait renoncer.

Notez une nouvelle fois l'absence de parenthèses après les noms des méthodes, dans les tests :

 if (rTitre.addEventListener) 
… teste l'existence de la méthode addEventListener dans l'objet rTitre, sans exécuter cette méthode, alors que
 if (rTitre.addEventListener() ) 
exécute la méthode puis teste son résultat (et plante le programme si la méthode n'existe pas).

Assemblage final

Cette fois on a tout écrit. Le programme JS va ressembler à :

 function clicTitre(e) { /* le gestionnaire d'événements */ } function moduleCliquable(id,etat) { /* greffe clicTitre au titre d'un module */ } 
… et on ajoutera quelques appels à moduleCliquable dans le pied de page du blog. Mais ça me chiffonne encore un peu. Encoooooore ? Attendez voir !

Les deux fonctions clicTitre et moduleCliquable sont  visibles de l'extérieur , peuvent être invoquées n'importe où dans le blog. C'est normal pour moduleCliquable, pas pour clicTitre : à quoi bon pouvoir déclencher un gestionnaire de clic en l'absence de clic ?

Au mieux c'est inutile, au pire cela créera des perturbations. Et on peut tout craindre si un autre script définit une fonction ou variable nommée clicTitre.

Pour toutes ces raisons, il faudrait donc que clicTitre n'ait de sens qu'à l'intérieur de moduleCliquable. Hé bien, tadaaa, on peut ! On peut déclarer une fonction à l'intérieur d'une autre fonction et elle ne sera visible que depuis cette fonction  enveloppante , tout comme une variable déclarée dans une fonction n'est visible que depuis cette fonction. Beau, non ?

Revoici donc le code définitif du programme :

 function moduleCliquable(id,etat) { function clicTitre(e) { e = e || window.event; var s=e.target||e.srcElement; if (!s)return true; if (s.nodeType == 3||s.nodeType == 4) s = s.parentNode; while(!(/\bbox\s/.test(s.className)) ) s=s.parentNode; if (/\bon\b/.test(s.className)) s.className=s.className.replace(/\bon\b/,' off '); else if (/\boff\b/.test(s.className)) s.className=s.className.replace(/\boff\b/,' on '); else s.className+=' on'; return false; } var r,rr,rBox,rTitre,i; if (!id) return; rBox=document.getElementById(id); if (!rBox||!rBox.className||! /\bbox\b/.test(rBox.className)) return; rr=rBox.getElementsByTagName('div'); for (i=0;r=rr[i];i++) { if (!r.className||! /\bbox-titre\b/.test(r.className)) continue; rTitre=r; break; } if (!rTitre) {alert("Pas de titre pour "+id+" ?");return} if(etat!='on' && etat!='off') etat='on'; rBox.className+=' '+etat; if (rTitre.addEventListener) rTitre.addEventListener('click',clicTitre,false); else if (rTitre.attachEvent) rTitre.attachEvent('onclick',clicTitre); } 

Pour conclure

Il y a dans ce programme, outre son intérêt pratique, plusieurs éléments utiles pour qui veut fabriquer ses propres JS :

  • la gestion d'événements, ça c'est la grande nouveauté ;
  • la manière de s'adapter à divers navigateurs, en testant non pas le navigateur mais ce qu'il propose ;
  • quelques finesses d'expressions rationnelles, toujours bonnes à connaître ;
  • enfin, un petit peu de navigation dans la page.

Voilà une boîte à outils qui commence à ressembler à quelque chose :-)


J'ai enfin compris quelque chose aux événements en lisant cet exposé sur le site de Peter-Paul Koch, et j'ai recopié sans honte plusieurs de ses solutions (mais, vous le voyez, je cite toujours mes sources !).

Son site et d'autres que je trouve utiles sont rassemblés dans l'article Apprendre JavaScript.

par Aïe mes doigts ! - dans JavaScript Mania
commenter cet article

commentaires

Sagan33 11/05/2012 14:05

Ce qu'il y a de sûr c'est que quand j'aurai 2 mn, je vais lire attentivement ton programme, pour pouvoir en créer un à moi "modules occultables" - pourquoi pas !
Bonne journée Bren, courage, les degrés baissent...

AïmD ! 11/05/2012 18:36



Oh mais pas besoin de créer un deuxième programme pour ça, je pense. Une définition bien choisie des classes on et off devrait suffire.



Sagan33 10/05/2012 19:11

Oh ! on t'appelle Monsieur quatre cerveaux sûrement.
Quand je serai devenue plus intelligente, je viendrai relire.
Ce soir, je me dis que le principal est bien d'avoir réussi à placer tes modules cliquables. Le reste...
On peut te remercier pour ces sources, elles ne se trouvent pas souvent.
Très bonne soirée Bren,
Journée étouffante dans le Sud-ouest.

AïmD ! 10/05/2012 22:16



On m'appelle le plus souvent par mon prénom, ça me plaît bien et me suffit :-)


Ce démontage-là n'est pas le plus facile de la série (litote). La vérité est que j'ai conçu mes programmes au fil de l'expérience acquise en JavaScript, les plus anciens sont donc les plus
simples - pas toujours les plus clairement rédigés, hélas ! De toute manière, tout ceci n'a d'intérêt que pour qui s'intéresse à la programmation et n'aide en rien à utiliser le programme.
Maintenant que je dédouble les articles, ça finira peut-être par se savoir :-D


Fait pas des plus frais ici non plus...



Archives