II. Prémisses▲
II-A. ▲
À la lecture de l'entrée en matière, vous l'aurez peut-être deviné - vous, programmeur ayant déjà une certaine expérience du JavaScript et de ses possibilités - que le contrôle que nous allons créer ici va être développé sous la forme d'une (pseudo) classe JavaScript.
Exprimons l'interface initiale dont nous aurons besoin. Pour cela, utilisons une définition de classe « à la C++ » comme base de départ de nos développements. Il s'agit là de l'interface publique de notre contrôle.
/*
public class HtmlEditTable {
public:
HtmlEditTable(object o);
void AppendTo(control parent);
Array AllData();
};
*/
Ce n'est pas du bonheur ça ? Interface initiale minimaliste, mais suffisante… Tellement simple qu'il n'est pas nécessaire a priori d'expliciter les fonctionnalités. Mais soyons fou, le but de ce tutoriel est tout de même de fournir des explications pas à pas et je ne dérogerais point à la règle, que nenni mon bon monsieur !
- HtmlEditTable : constructeur de la classe auquel on passe en paramètre un objet renseignant les propriétés de notre table éditable.
- AppendTo : méthode qui ajoute notre contrôle en tant que dernier nœud enfant d'un nœud par conséquent parent.
- AllData : méthode qui renvoie les données contenues dans la table sous forme d'un Array.
Cette interface nous permettra de réaliser deux des objectifs que nous nous sommes fixés, à savoir :
- Génération automatique du contrôle ;
- Accès simple aux données.
Eh oui, figurez-vous qu'en première approche cela suffit amplement. Il est judicieux de commencer petit, mais fonctionnel et bien pensé.
Remarquez au passage que nous venons de baptiser notre contrôle HtmlEditTable.
II-B. A <table> !▲
Jusqu'ici nous sommes tout de même restés dans l'abstrait. Effectivement nous allons créer une classe JavaScript, mais que va-t-elle nous générer ? Finalement qu'essayons-nous de faire, quel sera le rendu ?
Et bien je vous parlais en introduction de la toute basique table HTML. Cette table est le pilier de notre futur contrôle. En effet, une table éditable n'est autre qu'une table HTML dont les cellules permettront l'édition d'une façon que nous verrons bientôt. Donc, en première approximation, nous essayons au travers du JavaScript de générer une table HTML qui aura dans le DOM la tête suivante :
<
table>
<
caption>
</
caption>
<
thead>
<
tr>
<
td>
</
td>
</
tr>
</
thead>
<
tbody>
<
tr>
<
td>
</
td>
</
tr>
</
tbody>
<
tfoot>
<
tr>
<
td>
</
td>
</
tr>
</
tfoot>
</
table>
Mais alors, comment rendre une table ordinaire éditable ?
II-C. Édith la Môme▲
Eh oui, l'homonyme de la Môme est la solution. Pour obtenir une cellule éditable nous allons utiliser un Edit, ou plus justement un <input type=« text »/>. L'idée étant de créer à la volée un Edit sur le double-clic d'une cellule, nous allons avoir besoin d'un Edit coopérant avec la table pour échanger des données. À dessein, nous implémenterons une classe JavaScript assurant la création d'un Edit répondant à nos besoins. Là encore, l'interface publique que l'on peut envisager est très simple.
/*
public class HtmlEdit {
public:
HtmlEdit();
void AppendTo(control parent);
};
*/
Explicitons-la :
- HtmlEdit : constructeur sans paramètre de la classe ;
- AppendTo : méthode qui ajoute le contrôle d'édition en tant que nœud enfant du contrôle parent. Dans notre cas, le parent sera une cellule de la table.
II-D. Bulma et la Capsule Corp.▲
Ce contrôle d'édition, que nous venons de baptiser HtmlEdit, est spécifique à notre table. Il serait donc pertinent d'en limiter l'accès à l'implémentation de cette dernière. Si nous reprenons la définition précédente de notre classe HtmlEditTable cela nous donne :
/*
public class HtmlEditTable {
public:
HtmlEditTable(object o);
void AppendTo(control parent);
Array AllData();
private:
class HtmlEdit {
public:
HtmlEdit();
void AppendTo(control parent);
};
};
*/
L'encapsulation est un des principes fondamentaux de la programmation orientée objet. Même si le JavaScript ne permet pas à proprement parler de faire de la programmation objet, il en permet une certaine émulation et nous permet d'encapsuler des fonctionnalités dans la limite où l'utilisateur ne se découvre pas une âme de super guerrier de l'espace et n'envoie pas une vague déferlante sur les barrières que vous lui imposez. Je vous conseille la lecture du tutoriel « Espaces de noms en JavaScript » si vous voulez en savoir plus sur l'encapsulation de données et de fonctionnalités en JavaScript.
II-E. Page de test▲
Eh oui, nous pouvons d'ores et déjà mettre en place une page de test puisque nous avons notre interface minimale. Cela nous permettra d'expliciter les informations que nous voulons passer à notre objet et que l'on devra traiter lors de l'implémentation de la classe HtmlEditTable.
Voici une page de test très simple dans laquelle on inclut les scripts et les styles nécessaires : HtmlEditTable.js et HtmlEditTable.css.
HtmlEditTable.js contiendra tous les scripts de l'implémentation de la HtmlEditTable.
HtmlEditTable.css contiendra tous les styles de la HtmlEditTable. Je n'explique pas ici l'import de CSS et ses avantages face au link classique. Je vous renvoie à votre moteur de recherche préféré pour obtenir de plus amples informations sur la question.
Dans le corps du document, un script nous permet d'instancier et d'ajouter au document une instance de la classe HtmlEditTable. On passe au constructeur toutes les informations utiles à la création de la table, à savoir :
- le nombre de colonnes (X) ou la liste des noms de colonnes (Xn) ;
- le nombre de lignes (Y) ou la liste des noms de lignes (Yn) ;
- les données (data) ;
- le titre de la table (caption) ;
- la liste des en-têtes de colonnes (head).
Ces données sont passées au constructeur sous la forme d'un objet (en notation JSON). L'ajout à la page de notre contrôle est assuré par l'appel de la fonction AppendTo(). Le contrôle sera alors ajouté en queue de la liste des enfants du corps du document (des objets, ajoutés par la suite au document, iront se positionner après notre contrôle).
<!
DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN"
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd"
>
<
html>
<
head>
<
script type=
"text/javascript"
src=
"HtmlEditTable.js"
>
</
script>
<
style type=
"text/css"
>
@import url
(
HtmlEditTable.
css);
</
style>
</
head>
<
body>
<
script>
var table =
new HtmlEditTable
({
"X"
:
8
,
"Y"
:
5
,
"data"
:
[
"15/09/2008"
,
"12/20"
,
"15/20"
,
"9.5/20"
,
"17/20"
,
"2/20"
,
"23/30"
,
"95/100"
,
"02/10/2008"
,
"15.5/20"
,
"13.5/20"
,
"7/20"
,
"16/20"
,
"2/20"
,
"19/30"
,
"96/100"
,
"25/10/2008"
,
"11.5/20"
,
"13/20"
,
"10/20"
,
"16/20"
,
"2/20"
,
"22/30"
,
"97/100"
,
"09/11/2008"
,
"18/20"
,
"16/20"
,
"10.5/20"
,
"18.5/20"
,
"2/20"
,
"25/30"
,
"98/100"
,
"29/11/2008"
,
"17/20"
,
"17/20"
,
"9/20"
,
"19/20"
,
"2/20"
,
"26/30"
,
"99.5/100"
],
"caption"
:
"Relevé de note de Mr. X - 1er trimestre 2009"
,
"head"
:
[
"Date"
,
"Français"
,
"Anglais"
,
"Maths"
,
"Physique"
,
"Histoire"
,
"Géographie"
,
"E.P.S."
]
}
);
table.AppendTo
(
document
.
body);
</
script>
<
br/>
<
input type=
"button"
value=
"Export"
onclick
=
"document.getElementById('zone').value = table.AllData().join(',')"
/>
<
br/>
<
textarea
id=
"zone"
style=
"width:45em;height:10em;"
></
textarea
>
</
body>
</
html>
Un bouton et une zone de texte finalisent notre page de texte. Le clic sur le bouton aura pour conséquence l'écriture dans la zone de texte de toutes les données contenues dans la table. La récupération des données sous forme d'un Array est assurée par la fonction AllData().
Vous voyez, avec cette page de test, que nous avons dès à présent utilisé la totalité de l'interface publique précédemment définie de notre classe.
II-F. Le masque de Zorro▲
Lorsque l'on conçoit une classe, une bibliothèque, etc., il est important de distinguer l'interface publique de l'implémentation. Vous devez bien différencier les fonctionnalités qui seront exhibées de celles qui devront rester internes à votre code. En JavaScript, la notion de privé et public n'existe pas, si ce n'est au travers d'astuces diverses et variées.
Dans le cadre de notre étude, afin de garder notre implémentation privée, nous allons introduire deux classes qui renfermeront les fonctions utilitaires nécessaires à nos développements. La classe Tools exhibera des fonctionnalités générales et compatibles avec tous les navigateurs modernes et la classe HtmlEditTableHelper exhibera des fonctionnalités spécifiques à l'implémentation de notre table éditable. À ce stade de notre implémentation, ces classes sont accessibles par les utilisateurs de notre code. Nous verrons plus tard comment masquer ces classes. Dans un premier temps, elles serviront à ne pas encombrer l'interface de notre contrôle avec des fonctionnalités propres à son implémentation.
var HtmlEditTableHelper =
{
// fonctions spécifiques au développement d'une table éditable
};
var Tools =
{
// fonctions générales et compatibles avec les navigateurs modernes
};
J'ai abusivement défini Tools et HtmlEditTableHelper comme étant des classes. Il s'agit en réalité d'objets définissant des propriétés. Ces propriétés sont des fonctions. Ce qui fait de ces objets l'équivalent de classes possédant des fonctions statiques.