Articles web

Nos articles concernant les techniques web sont centrés sur des solutions pratiques qui mettent en œuvre, le plus souvent, notre framework web : Vae Soli!

Des articles généraux sont également fournis dans le respect des standards du web.

Tous nos articles web sont disponibles sous le couvert de la licence Icône Creative Commons Creative Commons — Paternité - pas de modification.

2011-05-02 à 13:30:04

Création d'une zone dynamique

Ce que nous cherchons à faire c'est de créer, à la volée, une zone d'édition qui n'existait pas au moment où la page a été créée. Imaginons par exemple un tableau dans lequel on indique une date dans l'une des colonnes. Imaginons encore que nous souhaitions permettre à l'utilisateur de modifier la date en question : cliquez sur une date de la colonne "Date".

Liste de choses à faire
Todo Cat Date DescriptionStatut
Téléphoner à Remy PRI
14/05/2011
Lui demander s'il vient au BBQ de Chantal Ongoing
0%
Envoyer l'adresse de Pierre à Chantal PRI
18/05/2011
Chantal souhaite inviter Pierre à son BBQ mais elle n'a pas son adresse email Ongoing
0%

Après avoir visualisé l'endroit où nous souhaiterions insérer la zone d'édition (dans la colonne date, sur la bonne ligne), voyons un peu le code HTML de la table :

<table class="sample">
    <caption>Liste de choses à faire</caption>
    <thead>
        <tr>
            <th>Todo</th>
            <th>Cat</th>
            <th>Date</th>
            <th>Description</th>
            <th class="status">Statut</th>
        </tr>
    </thead>
    <tbody>
        <tr id="LS-10bb977b-2075-43c4-96cb-ae2d65758c60">
            <td>Téléphoner à Remy</td>
            <td>PRI</td>
            <td class="date"><div onclick="alert('Je voudrais éditer la date');">14/05/2011</div></td>
            <td>Lui demander s'il vient au BBQ de Chantal</td>
            <td class="status">Ongoing<br />0%</td>
        </tr>
        <tr id="LS-6d00e2a6-c735-4bd4-a84f-a22b59933b45">
            <td>Envoyer l'adresse de Pierre à Chantal</td>
            <td>PRI</td>
            <td class="date"><div onclick="alert('Je voudrais éditer la date');">18/05/2011</div></td>
            <td>Chantal souhaite inviter Pierre à son BBQ mais elle n'a pas son adresse email</td>
            <td class="status">Ongoing<br />0%</td>
        </tr>
    </tbody>
</table>
    

Ainsi que vous pouvez le constater, il n'y a pas de quoi s'émerveiller : une simple boîte d'alerte en Javascript fait le travail.

Ce qui faudrait maintenant, c'est de réaliser une fonction Javascript qui propose la création de la zone d'édition. Nous allons y aller pas à pas :

<script type="text/javascript">
function EditDate01( o )
{
    alert( 'Je voudrais éditer la date' );
}
</script>

<table class="sample">
    <caption>Liste de choses à faire</caption>
    <thead>
        <tr>
            <th>Todo</th>
            <th>Cat</th>
            <th>Date</th>
            <th>Description</th>
            <th class="status">Statut</th>
        </tr>
    </thead>
    <tbody>
        <tr id="LS-10bb977b-2075-43c4-96cb-ae2d65758c60">
            <td>Téléphoner à Remy</td>
            <td>PRI</td>
            <td class="date"><div onclick="EditDate01(this);">14/05/2011</div></td>
            <td>Lui demander s'il vient au BBQ de Chantal</td>
            <td class="status">Ongoing<br />0%</td>
        </tr>
        <tr id="LS-6d00e2a6-c735-4bd4-a84f-a22b59933b45">
            <td>Envoyer l'adresse de Pierre à Chantal</td>
            <td>PRI</td>
            <td class="date"><div onclick="EditDate01(this);">18/05/2011</div></td>
            <td>Chantal souhaite inviter Pierre à son BBQ mais elle n'a pas son adresse email</td>
            <td class="status">Ongoing<br />0%</td>
        </tr>
    </tbody>
</table>
    

A priori, on ne fait rien de plus qu'avant, sauf qu'on a créé une fonction Javascript. On peut s'en convaincre en testant la table ci- dessous :

Liste de choses à faire
Todo Cat Date Description Statut
Téléphoner à Remy PRI
14/05/2011
Lui demander s'il vient au BBQ de Chantal Ongoing
0%
Envoyer l'adresse de Pierre à Chantal PRI
18/05/2011
Chantal souhaite inviter Pierre à son BBQ mais elle n'a pas son adresse email Ongoing
0%

A présent faisons évoluer la fonction Javascript pour lui demander d'afficher ce qui est contenu dans la colonne :

<script type="text/javascript">
function EditDate01( o )
{
    alert( 'On devrait éditer ' + o.innerHTML );
}
</script>

Et nous pouvons tester ce que cela donne avec la table qui suit :

Liste de choses à faire
Todo Cat Date Description Statut
Téléphoner à Remy PRI
14/05/2011
Lui demander s'il vient au BBQ de Chantal Ongoing
0%
Envoyer l'adresse de Pierre à Chantal PRI
18/05/2011
Chantal souhaite inviter Pierre à son BBQ mais elle n'a pas son adresse email Ongoing
0%

Nous savons donc comment nous pouvons retrouver le contenu de la colonne. A priori, ce qu'il nous reste à faire à présent c'est de proposer une zone de saisie. Pour ce faire, nous allons utiliser la méthode createElement() du document (DOM) et allons lui donner les propriétés voulues :

Line 001: <script type="text/javascript">
Line 002: function EditDate01( o )
Line 003: {
Line 004:     var oTextbox   = document.createElement( 'input' );
Line 005:
Line 006:     oTextbox.type  = 'text';
Line 007:     oTextbox.name  = 'dateBox';
Line 008:     oTextbox.value = o.innerHTML;
Line 009:     o.innerHTML    = '';
Line 010:     o.onclick      = '';  // devrait être null pour FF et Chrome
Line 011:     o.appendChild( oTextbox );
Line 012: }
Line 013: </script>
  1. Ligne 004: création de la zone d'édition
  2. Ligne 006: on souhaite une zone texte
  3. Ligne 007: on donne un nom à la zone
  4. Ligne 008: on édite ce qu'il y avait dans la colonne
  5. Ligne 009: on vide la colonne
  6. Ligne 010: on élimine le gestionnaire du onclick (sinon on entre de nouveau dans la même fonction Javascript)
  7. Ligne 011: on ajoute la zone d'édition fraîchement créée dans la colonne/ligne (paramètre 'o')

Et on peut tester avec la table ci-dessous ce qui se passe :

Liste de choses à faire
Todo Cat Date Description Statut
Téléphoner à Remy PRI
14/05/2011
Lui demander s'il vient au BBQ de Chantal Ongoing
0%
Envoyer l'adresse de Pierre à Chantal PRI
18/05/2011
Chantal souhaite inviter Pierre à son BBQ mais elle n'a pas son adresse email Ongoing
0%

Cela marche! Génial! Mais … ce n'est pas encore parfait parce que je ne peux plus revenir à l'état d'origine (avoir la table comme elle m'était présentée avant que je n'édite quoi que ce soit). En fait, lorsque je quitte la zone d'édition, je devrais remettre ce que je viens d'éditer dans la colonne d'où je viens (ligne respectée également). Ce n'est pas si compliqué que cela : une légère modification et une petite addition y contribueront (ATTENTION : ceci ne marchera que sous Opera; pour le code valable en Firefox et Chrome, veuillez consulter la fin de l'article.).

Line 001: <script type="text/javascript">
Line 002: function EditDate01( o )
Line 003: {
Line 004:     var oTextbox    = document.createElement( 'input' );
Line 005:
Line 006:     oTextbox.type   = 'text';
Line 007:     oTextbox.name   = 'dateBox';
Line 008:     oTextbox.value  = o.innerHTML;
Line 009:     oTextbox.onblur = "ResetDate(this)";
Line 010:     o.innerHTML     = '';
Line 011:     o.onclick       = '';
Line 012:
Line 013:     o.appendChild( oTextbox );
Line 014:     oTextbox.focus();
Line 015: }
Line 016:
Line 017: function ResetDate( o )
Line 018: {
Line 019:     oDiv = o.parentNode;
Line 020:     oDiv.innerHTML = o.value;
Line 021:
Line 022:     if ( oDiv.nodeName == 'DIV' )
Line 023:     {
Line 024:         if ( oDiv.onclick )
Line 025:         {
Line 026:             oDiv.onclick = "EditDate01(this)";
Line 027:         }
Line 028:     }
Line 029: }
Line 030: </script>

Qu'est-ce que ce code change à notre affaire ?

  1. Ligne 009: Lorsqu'on quitte la zone d'édition, nous voulons que la table reprenne sa forme antérieure. Pour ce faire, nous demandons d'exécuter la fonction Javascript ResetDate() à laquelle nous envoyons en paramètre la zone d'édition dont nous venons.
  2. Ligne 014: il s'agit d'une petite amélioration qui nous permet de positionner le curseur directement sur la zone d'édition.
  3. Ligne 017: nous définissons la fonction ResetDate(). Celle-ci reçoit un paramètre qui est la zone d'édition que nous venons de quitter.
  4. Ligne 019: Le noeud parent de la zone d'édition est la division dans laquelle la zone d'édition est contenue.
  5. Ligne 020: On modifie le contenu de la division avec la valeur de la zone d'édition (en d'autres termes on remet dans la colonne ce qui était contenu dans la zone d'édition).
  6. Ligne 022: Si le noeud parent est bien une division…
  7. Ligne 024: … et si nous avons un attribut onclick
  8. Ligne 026: … alors remettons le gestionnaire onclick à la valeur qui était la sienne avant de changer quoi que ce soit.

Et le test avec la table ci-dessous devrait vous convaincre de ce que nous sommes arrivés à notre fin.

Liste de choses à faire
Todo Cat Date Description Statut
Téléphoner à Remy PRI
14/05/2011
Lui demander s'il vient au BBQ de Chantal Ongoing
0%
Envoyer l'adresse de Pierre à Chantal PRI
18/05/2011
Chantal souhaite inviter Pierre à son BBQ mais elle n'a pas son adresse email Ongoing
0%

Et voilà … nous savons maintenant comment avoir des zones d'édition totalement dynamiques (avec Opera). En mêlant ce code avec un peu d'Ajax, on pourrait même mettre la base de données à jour directement.

Firefox, Chrome, Internet Explorer …

Opera permet effectivement des notations simplifiées pour le positionnement des gestionnaires d'événements onblur et onclick. Comme il est souhaitable de faire du code qui soit compatible avec tous les navigateurs (ou du moins le plus grand nombre), il faut envisager d'effectuer quelques modifications au code qui a été présenté. Pour faire court, voici le même code avec les modifications nécessaires en gras, rouge :

<script type="text/javascript">
function EditDate( o )
{
    var oTextbox    = document.createElement( 'input' );

    oTextbox.type   = 'text';
    oTextbox.name   = 'dateBox';
    oTextbox.value  = o.innerHTML;
    oTextbox.onblur = function(event) { ResetDate( oTextbox ); };
    o.innerHTML     = '';
    o.onclick       = '';

    o.appendChild( oTextbox );
    oTextbox.focus();
}

function ResetDate( o )
{
    if ( oDiv = o.parentNode )
    {
        oDiv.innerHTML = o.value;
    
        if ( oDiv.nodeName.toLowerCase() == 'div' )
        {
            oDiv.onclick = function(event) { EditDate( oDiv ); };
        }
    }
}
</script>

Et voilà, cette fois le tour est joué pour tous les navigateurs. On va pouvoir créer des pages extrêmement dynamiques pour le plus grand plaisir des visiteurs de nos pages.