• Li chevron_right

      Développer une interface web avec le toolkit Atlas (1/2)

      Claude SIMON · pubsub.eckmul.net / linuxfr_news · Friday, 1 January, 2021 - 12:02 · 57 minutes

    <div><p>Le <em>toolkit</em> <em>Atlas</em> permet de programmer des interfaces d’applications web monopages (<a href="https://en.wikipedia.org/wiki/Single-page_application">SPA</a>). Il est léger (quelques dizaines de Ko), sans dépendances, ne nécessite pas de savoir programmer en <em>JavaScript</em>, et n’impose pas d’architecture logicielle de type <a href="https://fr.wikipedia.org/wiki/Mod%C3%A8le-vue-contr%C3%B4leur"><em>MVC</em></a>.</p> <p>En outre, toute application développée avec le <em>toolkit</em> <em>Atlas</em> est, dès son lancement, instantanément et automatiquement accessible de n’importe quel dispositif (smartphone, tablette…) équipé d’un navigateur web moderne connecté à Internet. Cet accès est facilité par un <a href="https://fr.wikipedia.org/wiki/Code_QR">code QR</a> qui s’affiche dans l’application.</p> <p>Le <em>toolkit</em> <em>Atlas</em> a déjà fait l’objet de <a href="//linuxfr.org/tags/atlas_toolkit/public">quelques publications</a> ici même. Pour varier un peu les plaisirs durant ces longues soirées <s>d’hiver</s> de couvre-feu, voici la première partie d’un document qui devrait faciliter l’utilisation du <em>toolkit</em> <em>Atlas</em>. Il détaille le développement d’une application (très) basique de gestion de contacts, dont l’apparence est la suivante :</p> <p><img src="//img.linuxfr.org/img/68747470733a2f2f7133372e696e666f2f732f33396472347463722e706e67/39dr4tcr.png" alt="Apparence de l'application faisant l'objet du tutoriel 'Contacts'" title="Source : https://q37.info/s/39dr4tcr.png"></p> <p>Le <em>toolkit</em> <em>Atlas</em> est disponible pour <em>Java</em>, <em>Node.js</em>, <em>Perl</em>, <em>Python</em> et <em>Ruby</em>. C’est la version la plus populaire, à savoir <em>Python</em>, qui est utilisée pour ce document. Cependant, l’API étant la même pour toutes les versions, on peut facilement le transposer aux autres langages disponibles.</p> </div><ul><li>lien nᵒ 1 : <a title="https://atlastk.org" hreflang="en" href="https://linuxfr.org/redirect/107573">Homepage</a></li><li>lien nᵒ 2 : <a title="https://github.com/epeios-q37/atlas-python" hreflang="en" href="https://linuxfr.org/redirect/107574">Sur GitHub</a></li><li>lien nᵒ 3 : <a title="https://repl.it/@AtlasTK/atlas-python" hreflang="en" href="https://linuxfr.org/redirect/107575">Sur Repl.it</a></li><li>lien nᵒ 4 : <a title="https://atlastk.org/api/fr" hreflang="fr" href="https://linuxfr.org/redirect/107613">API</a></li><li>lien nᵒ 5 : <a title="https://q37.info/s/jz9ttdjb" hreflang="fr" href="https://linuxfr.org/redirect/107614">Seconde partie</a></li></ul><div><h2 class="sommaire">Sommaire</h2> <ul class="toc"> <li><a href="#toc-%C3%80-propos-de-ce-document">À propos de ce document</a></li> <li> <a href="#toc-le-ficher-html-principal-mainhtml">Le ficher <em>HTML</em> principal (<code>Main.html</code>)</a><ul> <li><a href="#toc-structure-g%C3%A9n%C3%A9rale">Structure générale</a></li> <li><a href="#toc-d%C3%A9tail-dun-contact">Détail d’un contact</a></li> <li><a href="#toc-boutons-g%C3%A9n%C3%A9raux">Boutons généraux</a></li> <li><a href="#toc-boutons-de-saisie">Boutons de saisie</a></li> <li><a href="#toc-liste-de-contacts">Liste de contacts</a></li> </ul> </li> <li> <a href="#toc-le-fichier-html-des-m%C3%A9tadonn%C3%A9es-headhtml">Le fichier <em>HTML</em> des métadonnées (<code>Head.html</code>)</a><ul> <li><a href="#toc-apparence-de-lapplication">Apparence de l’application</a></li> <li><a href="#toc-visibilit%C3%A9-des-boutons">Visibilité des boutons</a></li> </ul> </li> <li> <a href="#toc-rendu-de-linterface-part1py">Rendu de l’interface (<code>part1.py</code>)</a><ul> <li><a href="#toc-affichage-de-la-page-html">Affichage de la page <em>HTML</em></a></li> <li><a href="#toc-la-boucle-%C3%A9v%C3%A8nementielle">La boucle évènementielle</a></li> </ul> </li> <li> <a href="#toc-liste-des-contacts-part2py">Liste des contacts (<code>part2.py</code>)</a><ul> <li><a href="#toc-liste-fictive">Liste fictive</a></li> <li><a href="#toc-affichage">Affichage</a></li> </ul> </li> <li> <a href="#toc-d%C3%A9tail-dun-contact-part3py">Détail d’un contact (<code>part3.py</code>)</a><ul> <li><a href="#toc-affichage-1">Affichage</a></li> <li><a href="#toc-s%C3%A9lection">Sélection</a></li> </ul> </li> <li><a href="#toc-%C3%80-suivre"><em>À suivre…</em></a></li> </ul> <h2 id="toc-À-propos-de-ce-document">À propos de ce document</h2> <p>L’accent étant mis sur la mise en œuvre de l'<em>API</em> du <em>toolkit</em> <em>Atlas</em>, le lecteur est supposé posséder les connaissances (basiques) nécessaires à la compréhension du code <em>HTML</em>/<em>CSS</em> et <em>Python</em> présent dans ce document. </p> <p>Les fichiers sources associés à ce document sont disponibles dans un <a href="https://github.com/epeios-q37/atlas-python/tree/master/tutorials/Contacts">dépôt <em>GitHub</em></a>, lui-même cloné <a href="https://repl.it/@AtlasTK/atlas-python">sur <em>Repl.it</em></a>, un <em>IDE</em> en ligne.<br> Si <em>Python</em> 3 est installé sur votre ordinateur, vous pouvez récupérer le dépôt <em>GitHub</em> et visualiser/exécuter directement sur votre machine le code associé aux différentes sections de ce document.<br> Vous pouvez également, notamment si vous n’avez pas installé <em>Python</em> 3, visualiser/exécuter, éventuellement après modification, ce code directement dans votre navigateur en utilisant le lien <em>Repl.it</em> ci-dessus.</p> <p>Pour ne pas allonger outre mesure ce document, chaque section ne contiendra que les détails du code sur lequel elle porte. Néanmoins, au début de chaque section, il y aura un lien vers le code source complet tel que décrit dans cette section, ainsi que les instructions à lancer pour l’exécuter sur <em>Repl.it</em> et en local.</p> <p>Les lignes, dans les fichiers source, précédant la ligne <code>import atlastk</code> ne sont là que pour faciliter l’utilisation de ces fichiers dans le cadre de ce document et ne sont pas nécessaires à une utilisation courante du <em>toolkit</em> <em>Atlas</em>.</p> <h2 id="toc-le-ficher-html-principal-mainhtml">Le ficher <em>HTML</em> principal (<code>Main.html</code>)</h2> <blockquote> <p>Code source : <a href="https://github.com/epeios-q37/atlas-python/blob/master/tutorials/Contacts/Main.html">lien sur GitHub</a>.</p> </blockquote> <p>Le fichier <code>Main.html</code> est un fichier au format <em>HTML</em> décrivant l’interface.<br> Ce fichier va prendre place dans la section <em>body</em> de la page <em>HTML</em> constituant l’interface de l’application.</p> <h3 id="toc-structure-générale">Structure générale</h3> <p>Voici un aperçu partiel du contenu de ce fichier, mettant en évidence sa structure générale :</p> <pre><code class="html"><span class="p">&lt;</span><span class="nt">fieldset</span><span class="p">&gt;</span> <span class="p">&lt;</span><span class="nt">fieldset</span> <span class="na">id</span><span class="o">=</span><span class="s">"Contact"</span><span class="p">&gt;</span> <span class="c">&lt;!-- Détail d’un contact --&gt;</span> <span class="p">&lt;/</span><span class="nt">fieldset</span><span class="p">&gt;</span> <span class="p">&lt;</span><span class="nt">div</span> <span class="na">style</span><span class="o">=</span><span class="s">"display: table; margin: 10px auto auto auto;"</span><span class="p">&gt;</span> <span class="p">&lt;</span><span class="nt">div</span><span class="p">&gt;</span> <span class="c">&lt;!-- Boutons généraux --&gt;</span> <span class="p">&lt;/</span><span class="nt">div</span><span class="p">&gt;</span> <span class="p">&lt;</span><span class="nt">div</span> <span class="na">class</span><span class="o">=</span><span class="s">"Edition"</span><span class="p">&gt;</span> <span class="c">&lt;!-- Boutons de saisie--&gt;</span> <span class="p">&lt;/</span><span class="nt">div</span><span class="p">&gt;</span> <span class="p">&lt;/</span><span class="nt">div</span><span class="p">&gt;</span> <span class="p">&lt;/</span><span class="nt">fieldset</span><span class="p">&gt;</span> <span class="p">&lt;</span><span class="nt">div</span> <span class="na">style</span><span class="o">=</span><span class="s">"display: table; margin: 10px auto auto auto; border-collapse: collapse;"</span><span class="p">&gt;</span> <span class="c">&lt;!-- Liste des contacts --&gt;</span> <span class="p">&lt;/</span><span class="nt">div</span><span class="p">&gt;</span></code></pre> <p>Il est aisément compréhensible de celles et ceux qui sont familiers avec <em>HTML</em>.</p> <p>Ses différentes sous-parties, qui prennent la place de commentaires ci-dessus, vont être détaillées ci-dessous.</p> <h3 id="toc-détail-dun-contact">Détail d’un contact</h3> <p>Voici le code dédié à l’affichage du détail d’un contact :</p> <pre><code class="html"><span class="p">&lt;</span><span class="nt">table</span> <span class="na">style</span><span class="o">=</span><span class="s">"margin: auto;"</span><span class="p">&gt;</span> <span class="p">&lt;</span><span class="nt">tr</span><span class="p">&gt;</span> <span class="p">&lt;</span><span class="nt">td</span><span class="p">&gt;</span> <span class="p">&lt;</span><span class="nt">label</span> <span class="na">for</span><span class="o">=</span><span class="s">"Name"</span><span class="p">&gt;</span>Full name:<span class="p">&lt;/</span><span class="nt">label</span><span class="p">&gt;</span> <span class="p">&lt;/</span><span class="nt">td</span><span class="p">&gt;</span> <span class="p">&lt;</span><span class="nt">td</span><span class="p">&gt;</span> <span class="p">&lt;</span><span class="nt">input</span> <span class="na">id</span><span class="o">=</span><span class="s">"Name"</span> <span class="na">size</span><span class="o">=</span><span class="s">"50"</span> <span class="p">/&gt;</span> <span class="p">&lt;/</span><span class="nt">td</span><span class="p">&gt;</span> <span class="p">&lt;/</span><span class="nt">tr</span><span class="p">&gt;</span> <span class="p">&lt;</span><span class="nt">tr</span><span class="p">&gt;</span> <span class="p">&lt;</span><span class="nt">td</span><span class="p">&gt;</span> <span class="p">&lt;</span><span class="nt">label</span> <span class="na">for</span><span class="o">=</span><span class="s">"Address"</span><span class="p">&gt;</span>Address:<span class="p">&lt;/</span><span class="nt">label</span><span class="p">&gt;</span> <span class="p">&lt;/</span><span class="nt">td</span><span class="p">&gt;</span> <span class="p">&lt;</span><span class="nt">td</span><span class="p">&gt;</span> <span class="p">&lt;</span><span class="nt">input</span> <span class="na">id</span><span class="o">=</span><span class="s">"Address"</span> <span class="na">size</span><span class="o">=</span><span class="s">"50"</span> <span class="p">/&gt;</span> <span class="p">&lt;/</span><span class="nt">td</span><span class="p">&gt;</span> <span class="p">&lt;/</span><span class="nt">tr</span><span class="p">&gt;</span> <span class="p">&lt;</span><span class="nt">tr</span><span class="p">&gt;</span> <span class="p">&lt;</span><span class="nt">td</span><span class="p">&gt;</span> <span class="p">&lt;</span><span class="nt">label</span> <span class="na">for</span><span class="o">=</span><span class="s">"Phone"</span><span class="p">&gt;</span>Phone:<span class="p">&lt;/</span><span class="nt">label</span><span class="p">&gt;</span> <span class="p">&lt;/</span><span class="nt">td</span><span class="p">&gt;</span> <span class="p">&lt;</span><span class="nt">td</span><span class="p">&gt;</span> <span class="p">&lt;</span><span class="nt">input</span> <span class="na">id</span><span class="o">=</span><span class="s">"Phone"</span> <span class="na">type</span><span class="o">=</span><span class="s">"tel"</span> <span class="na">size</span><span class="o">=</span><span class="s">"50"</span> <span class="p">/&gt;</span> <span class="p">&lt;/</span><span class="nt">td</span><span class="p">&gt;</span> <span class="p">&lt;/</span><span class="nt">tr</span><span class="p">&gt;</span> <span class="p">&lt;</span><span class="nt">tr</span><span class="p">&gt;</span> <span class="p">&lt;</span><span class="nt">td</span><span class="p">&gt;</span> <span class="p">&lt;</span><span class="nt">label</span> <span class="na">for</span><span class="o">=</span><span class="s">"Note"</span><span class="p">&gt;</span>Note:<span class="p">&lt;/</span><span class="nt">label</span><span class="p">&gt;</span> <span class="p">&lt;/</span><span class="nt">td</span><span class="p">&gt;</span> <span class="p">&lt;</span><span class="nt">td</span><span class="p">&gt;</span> <span class="p">&lt;</span><span class="nt">textarea</span> <span class="na">id</span><span class="o">=</span><span class="s">"Note"</span> <span class="na">style</span><span class="o">=</span><span class="s">"width: 100%;"</span><span class="p">&gt;&lt;/</span><span class="nt">textarea</span><span class="p">&gt;</span> <span class="p">&lt;/</span><span class="nt">td</span><span class="p">&gt;</span> <span class="p">&lt;/</span><span class="nt">tr</span><span class="p">&gt;</span> <span class="p">&lt;/</span><span class="nt">table</span><span class="p">&gt;</span></code></pre> <p>On y trouve un tableau, avec, pour chacun des champs constituant un contact, une ligne (chacune délimitée par <code>&lt;tr&gt;</code> et <code>&lt;/tr&gt;</code>) accompagnée d’un libellé et d’un identifiant explicite.</p> <h3 id="toc-boutons-généraux">Boutons généraux</h3> <p>Ces boutons vont servir à créer/éditer/supprimer un contact.<br> En voici le code :</p> <pre><code class="html"><span class="p">&lt;</span><span class="nt">button</span> <span class="na">class</span><span class="o">=</span><span class="s">"Display"</span> <span class="na">data-xdh-onevent</span><span class="o">=</span><span class="s">"New"</span><span class="p">&gt;</span>New<span class="p">&lt;/</span><span class="nt">button</span><span class="p">&gt;</span><span class="c">&lt;!-- Bouton pour la création --&gt;</span> <span class="p">&lt;</span><span class="nt">span</span> <span class="na">class</span><span class="o">=</span><span class="s">"DisplayAndSelect"</span><span class="p">&gt;</span> <span class="p">&lt;</span><span class="nt">button</span> <span class="na">data-xdh-onevent</span><span class="o">=</span><span class="s">"Edit"</span><span class="p">&gt;</span>Edit<span class="p">&lt;/</span><span class="nt">button</span><span class="p">&gt;</span><span class="c">&lt;!-- Bouton pour l'édition --&gt;</span> <span class="p">&lt;</span><span class="nt">button</span> <span class="na">data-xdh-onevent</span><span class="o">=</span><span class="s">"Delete"</span><span class="p">&gt;</span>Delete<span class="p">&lt;/</span><span class="nt">button</span><span class="p">&gt;</span><span class="c">&lt;!-- Bouton pour la suppression --&gt;</span> <span class="p">&lt;/</span><span class="nt">span</span><span class="p">&gt;</span></code></pre> <p>À part l’attribut <code>data-xdh-onevent</code>, on n’a là que du <em>HTML</em> des plus classiques.<br> Les différentes classes (valeurs <code>Display</code> et <code>DisplayAndSelect</code> des attributs <code>class</code>) ont cependant un rôle bien particulier, qui sera révélé dans les sections qui suivent.</p> <p>L’attribut <code>data-xdh-onevent</code> prend ici la place de l’habituel attribut <code>onclick</code>. L’attribut <code>onclick</code> prend habituellement pour valeur le code <em>JavaScript</em> à lancer lorsque l’on clique sur le bouton auquel il est affecté.<br> Ici, à la place, on utilise l’attribut <code>data-xdh-onevent</code>, qui va prendre pour valeur un libellé d’action, libellé que l’on retrouvera dans le code <em>Python</em>. On va pouvoir ainsi coder les actions à réaliser lors d’un clic sur le bouton non plus en <em>JavaScript</em>, mais en <em>Python</em>.</p> <h3 id="toc-boutons-de-saisie">Boutons de saisie</h3> <p>Ces boutons sont affichés lors de la saisie d’un contact, et permettent de valider ou d’annuler cette saisie.<br> Voici le code correspondant :</p> <pre><code class="html"><span class="p">&lt;</span><span class="nt">button</span> <span class="na">data-xdh-onevent</span><span class="o">=</span><span class="s">"Cancel"</span><span class="p">&gt;</span>Cancel<span class="p">&lt;/</span><span class="nt">button</span><span class="p">&gt;</span><span class="c">&lt;!-- Bouton pour l’annulation de la saisie --&gt;</span> <span class="p">&lt;</span><span class="nt">button</span> <span class="na">data-xdh-onevent</span><span class="o">=</span><span class="s">"Submit"</span><span class="p">&gt;</span>Submit<span class="p">&lt;/</span><span class="nt">button</span><span class="p">&gt;</span><span class="c">&lt;!-- Bouton pour la validation de la saisie --&gt;</span></code></pre> <p>Là encore, rien de particulier, mis à part l’attribut <code>data-xdh-onevent</code>, que l’on a déjà rencontré ci-dessus.<br> Le contenu des attributs <code>data-xdh-onevent</code>, à savoir <code>Cancel</code> et <code>Submit</code>, va être utilisé dans le code <em>Python</em> de l’application. <br> Notez qu’ici le nom du bouton (la valeur de l’élément <code>button</code>) est identique à la valeur de son attribut <code>data-xdh-onevent</code>. C’est uniquement par commodité ; ce n’est en rien obligatoire.</p> <h3 id="toc-liste-de-contacts">Liste de contacts</h3> <p>Cette partie affiche le tableau qui va accueillir la liste des contacts au sein de son élément <code>tbody</code>, dont le contenu va être généré par l’application.</p> <p>En voici le contenu :</p> <pre><code class="html"><span class="p">&lt;</span><span class="nt">table</span> <span class="na">id</span><span class="o">=</span><span class="s">"Contacts"</span> <span class="na">style</span><span class="o">=</span><span class="s">"cursor: default; border-collapse: collapse;"</span><span class="p">&gt;</span> <span class="p">&lt;</span><span class="nt">thead</span><span class="p">&gt;</span> <span class="p">&lt;</span><span class="nt">th</span><span class="p">&gt;</span>Name<span class="p">&lt;/</span><span class="nt">th</span><span class="p">&gt;</span> <span class="p">&lt;</span><span class="nt">th</span><span class="p">&gt;</span>Address<span class="p">&lt;/</span><span class="nt">th</span><span class="p">&gt;</span> <span class="p">&lt;</span><span class="nt">th</span><span class="p">&gt;</span>Phone<span class="p">&lt;/</span><span class="nt">th</span><span class="p">&gt;</span> <span class="p">&lt;</span><span class="nt">th</span><span class="p">&gt;</span>Note<span class="p">&lt;/</span><span class="nt">th</span><span class="p">&gt;</span> <span class="p">&lt;/</span><span class="nt">thead</span><span class="p">&gt;</span> <span class="p">&lt;</span><span class="nt">tbody</span> <span class="na">id</span><span class="o">=</span><span class="s">"Content"</span> <span class="p">/&gt;</span> <span class="p">&lt;/</span><span class="nt">table</span><span class="p">&gt;</span></code></pre> <p>Notez l’identifiant <code>Content</code>, que l’on va retrouver dans le code <em>Python</em>. L’identifiant <code>Contacts</code> n’est, lui, utilisé que dans le fichier <code>Head.html</code> décrit ci-dessous.</p> <h2 id="toc-le-fichier-html-des-métadonnées-headhtml">Le fichier <em>HTML</em> des métadonnées (<code>Head.html</code>)</h2> <blockquote> <p>Code source : <a href="https://github.com/epeios-q37/atlas-python/blob/master/tutorials/Contacts/Head.html">lien sur GitHub</a>.</p> </blockquote> <p>Ce fichier, également au format <em>HTML</em>, prendra place dans la section <em>head</em> de la page <em>HTML</em> constituant l’interface de l’application.</p> <h3 id="toc-apparence-de-lapplication">Apparence de l’application</h3> <p>La première partie de ce fichier définit le titre, l’icône, et, à l’aide de quelques règles <em>CSS</em>, diverses retouches au niveau de l’apparence de l’interface.</p> <p>En voici le contenu :</p> <pre><code class="html"><span class="p">&lt;</span><span class="nt">title</span><span class="p">&gt;</span>Address book<span class="p">&lt;/</span><span class="nt">title</span><span class="p">&gt;</span> <span class="p">&lt;</span><span class="nt">link</span> <span class="na">rel</span><span class="o">=</span><span class="s">"icon"</span> <span class="na">type</span><span class="o">=</span><span class="s">"image/png"</span> <span class="na">href</span><span class="o">=</span><span class="s">"data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAACAAAAAgBAMAAACBVGfHAAAAMFBMVEUEAvyEhsxERuS8urQsKuycnsRkYtzc2qwUFvRUVtysrrx0ctTs6qTMyrSUksQ0NuyciPBdAAABHklEQVR42mNgwAa8zlxjDd2A4POfOXPmzZkFCAH2M8fNzyALzDlzg2ENssCbMwkMOsgCa858YOjBKxBzRoHhD7LAHiBH5swCT9HQ6A9ggZ4zp7YCrV0DdM6pBpAAG5Blc2aBDZA68wCsZPuZU0BDH07xvHOmAGKKvgMP2NA/Zw7ADIYJXGDgLQeBBSCBFu0aoAPYQUadMQAJAE29zwAVWMCWpgB08ZnDQGsbGhpsgCqBQHNfzRkDEIPlzFmo0T5nzoMovjPHoAK8Zw5BnA5yDosDSAVYQOYMKIDZzkoDzagAsjhqzjRAfXTmzAQgi/vMQZA6pjtAvhEk0E+ATWRRm6YBZuScCUCNN5szH1D4TGdOoSrggtiNAH3vBBjwAQCglIrSZkf1MQAAAABJRU5ErkJggg=="</span> <span class="p">/&gt;</span> <span class="p">&lt;</span><span class="nt">style</span><span class="p">&gt;</span> <span class="p">#</span><span class="nn">Contact</span> <span class="nt">label</span> <span class="p">{</span> <span class="k">font-weight</span><span class="p">:</span> <span class="kc">bold</span><span class="p">;</span> <span class="p">}</span> <span class="p">#</span><span class="nn">Contact</span> <span class="nt">span</span> <span class="p">{</span> <span class="k">text-align</span><span class="p">:</span> <span class="kc">left</span><span class="p">;</span> <span class="p">}</span> <span class="p">#</span><span class="nn">Contacts</span> <span class="nt">th</span><span class="o">,</span> <span class="p">#</span><span class="nn">Contacts</span> <span class="nt">td</span> <span class="p">{</span> <span class="k">border</span><span class="p">:</span> <span class="mi">1</span><span class="kt">px</span> <span class="kc">solid</span> <span class="kc">black</span><span class="p">;</span> <span class="k">padding</span><span class="p">:</span> <span class="mi">0</span><span class="kt">%</span> <span class="mi">5</span><span class="kt">px</span><span class="p">;</span> <span class="p">}</span> <span class="p">#</span><span class="nn">Contacts</span> <span class="nt">td</span><span class="p">:</span><span class="nd">nth-child</span><span class="o">(</span><span class="nt">3</span><span class="o">)</span> <span class="p">{</span> <span class="k">text-align</span><span class="p">:</span> <span class="kc">right</span><span class="p">;</span> <span class="p">}</span> <span class="p">#</span><span class="nn">Contacts</span> <span class="nt">tr</span><span class="p">:</span><span class="nd">nth-child</span><span class="o">(</span><span class="nt">even</span><span class="o">)</span> <span class="p">{</span> <span class="k">background</span><span class="p">:</span> <span class="mh">#CCC</span> <span class="p">}</span> <span class="p">#</span><span class="nn">Contacts</span> <span class="nt">tr</span><span class="p">:</span><span class="nd">nth-child</span><span class="o">(</span><span class="nt">odd</span><span class="o">)</span> <span class="p">{</span> <span class="k">background</span><span class="p">:</span> <span class="mh">#FFF</span> <span class="p">}</span> <span class="p">#</span><span class="nn">Contact</span> <span class="o">*</span><span class="p">:</span><span class="nd">disabled</span> <span class="p">{</span> <span class="k">background-color</span><span class="p">:</span> <span class="kc">snow</span><span class="p">;</span> <span class="k">color</span><span class="p">:</span> <span class="kc">initial</span><span class="p">;</span> <span class="p">}</span> <span class="p">&lt;/</span><span class="nt">style</span><span class="p">&gt;</span></code></pre> <h3 id="toc-visibilité-des-boutons">Visibilité des boutons</h3> <p>La seconde partie du fichier permet de gérer la visibilité des boutons.</p> <p>En voici le contenu :</p> <pre><code class="html"><span class="p">&lt;</span><span class="nt">style</span> <span class="na">id</span><span class="o">=</span><span class="s">"HideDisplay"</span><span class="p">&gt;</span> <span class="p">.</span><span class="nc">Display</span> <span class="p">{</span> <span class="k">display</span><span class="p">:</span> <span class="kc">none</span><span class="p">;</span> <span class="p">}</span> <span class="p">&lt;/</span><span class="nt">style</span><span class="p">&gt;</span> <span class="p">&lt;</span><span class="nt">style</span> <span class="na">id</span><span class="o">=</span><span class="s">"HideDisplayAndSelect"</span><span class="p">&gt;</span> <span class="p">.</span><span class="nc">DisplayAndSelect</span> <span class="p">{</span> <span class="k">display</span><span class="p">:</span> <span class="kc">none</span><span class="p">;</span> <span class="p">}</span> <span class="p">&lt;/</span><span class="nt">style</span><span class="p">&gt;</span> <span class="p">&lt;</span><span class="nt">style</span> <span class="na">id</span><span class="o">=</span><span class="s">"HideEdition"</span><span class="p">&gt;</span> <span class="p">.</span><span class="nc">Edition</span> <span class="p">{</span> <span class="k">display</span><span class="p">:</span> <span class="kc">none</span><span class="p">;</span> <span class="p">}</span> <span class="p">&lt;/</span><span class="nt">style</span><span class="p">&gt;</span></code></pre> <p>On y voit des éléments <code>style</code> accompagnés d’un identifiant. Ces éléments vont permettre de cacher/afficher certains boutons.<br> En effet, chaque élément <code>style</code> définit une règle pour une certaine classe. En activant/désactivant un de ces éléments, on ajoute/retire à cette classe la règle <em>CSS</em> contenu dans l’élément. Par conséquent, on agit ainsi sur les éléments, en l’occurrence des boutons, auxquels cette classe est affectée.</p> <p>On retrouvera les différents identifiants de ces éléments <code>style</code> dans le code <em>Python</em> détaillé dans les sections qui suivent.</p> <h2 id="toc-rendu-de-linterface-part1py">Rendu de l’interface (<code>part1.py</code>)</h2> <blockquote> <ul> <li>Code source : <a href="https://github.com/epeios-q37/atlas-python/blob/master/tutorials/Contacts/part1.py">lien sur GitHub</a> ;</li> <li>exécution : <ul> <li>sur <a href="https://repl.it/@AtlasTK/atlas-python#tutorials/Contacts/part1.py"><em>Repl.it</em></a> : bouton <em>Run</em>, <code>n1</code> + <em>entrée</em>, clic sur URL,</li> <li>en local : <code>python3 atlas-python/tutorials/Contacts/part1.py</code> </li> </ul> </li> </ul> </blockquote> <p>On va ici afficher l’interface de l’application, dont, suite à une action de l’utilisateur, seules les parties qui le nécessitent seront modifiées.</p> <h3 id="toc-affichage-de-la-page-html">Affichage de la page <em>HTML</em> </h3> <p>En premier lieu, on va définir la fonction qui sera appelée à chaque ouverture de session :</p> <pre><code class="python"><span class="k">def</span> <span class="nf">ac_connect</span><span class="p">(</span><span class="n">dom</span><span class="p">):</span> <span class="n">dom</span><span class="o">.</span><span class="n">inner</span><span class="p">(</span><span class="s2">""</span><span class="p">,</span><span class="nb">open</span><span class="p">(</span><span class="s2">"Main.html"</span><span class="p">)</span><span class="o">.</span><span class="n">read</span><span class="p">())</span></code></pre> <p><code>dom</code> est un objet fournit par le <em>toolkit</em> <em>Atlas</em> ; chaque session a sa propre instance de cet objet.</p> <p>Dans cette fonction, la méthode <code>inner(…)</code>va remplacer la totalité de la page web par le contenu du fichier <code>Main.html</code> précédemment décrit.<br> Le premier paramètre de cette méthode est l’identifiant de l’élément dont on va remplacer le contenu. La chaîne vide est une valeur spéciale qui fait référence à l’élément racine de la page.<br> À titre indicatif, il existe également les méthodes <code>before(…)</code>, <code>begin(…)</code>, <code>end(…)</code> et <code>after(…)</code> pour insérer le contenu respectivement juste avant, au début, à la fin ou juste après l’élément dont l’identifiant est passé en paramètre.</p> <p>On va ensuite affecter cette fonction à une action, à l’aide d’un dictionnaire nommé, par convention, <code>CALLBACKS</code> :</p> <pre><code class="python"><span class="n">CALLBACKS</span> <span class="o">=</span> <span class="p">{</span> <span class="s2">""</span><span class="p">:</span> <span class="n">ac_connect</span> <span class="p">}</span></code></pre> <p>Ici, <code>ac_connect</code> est affecté à une action dont le libellé est une chaîne vide. Cette valeur correspond à l’action qui est lancée à chaque nouvelle session.</p> <h3 id="toc-la-boucle-évènementielle">La boucle évènementielle</h3> <p>On va ensuite lancer la boucle évènementielle de l’application, en lui passant le dictionnaire des actions, ainsi que le contenu du fichier <code>Head.html</code> décrit précédemment :</p> <pre><code class="python"><span class="n">atlastk</span><span class="o">.</span><span class="n">launch</span><span class="p">(</span><span class="n">CALLBACKS</span><span class="p">,</span><span class="bp">None</span><span class="p">,</span><span class="nb">open</span><span class="p">(</span><span class="s2">"Head.html"</span><span class="p">)</span><span class="o">.</span><span class="n">read</span><span class="p">())</span></code></pre> <p>Le paramètre dont la valeur est <code>None</code> sera abordé plus tard.</p> <h2 id="toc-liste-des-contacts-part2py">Liste des contacts (<code>part2.py</code>)</h2> <blockquote> <ul> <li>Code source : <a href="https://github.com/epeios-q37/atlas-python/blob/master/tutorials/Contacts/part2.py">lien sur GitHub</a> ;</li> <li>exécution : <ul> <li>sur <a href="https://repl.it/@AtlasTK/atlas-python#tutorials/Contacts/part2.py"><em>Repl.it</em></a> : bouton <em>Run</em>, <code>n2</code> + <em>entrée</em>, clic sur URL,</li> <li>en local : <code>python3 atlas-python/tutorials/Contacts/part2.py</code> </li> </ul> </li> </ul> </blockquote> <p>Dans cette section, nous allons programmer l’affichage de la liste des contacts.</p> <h3 id="toc-liste-fictive">Liste fictive</h3> <p>On va d’abord créer une liste de contacts fictive, histoire d’avoir quelque chose à afficher :</p> <pre><code class="python"><span class="n">EXAMPLE</span> <span class="o">=</span> <span class="p">[</span> <span class="p">{</span> <span class="s2">"Name"</span><span class="p">:</span> <span class="s2">"Holmes, Sherlock"</span><span class="p">,</span> <span class="s2">"Address"</span><span class="p">:</span> <span class="s2">"221B Baker Street, Londres"</span><span class="p">,</span> <span class="s2">"Phone"</span><span class="p">:</span> <span class="s2">"(use telegraph)"</span><span class="p">,</span> <span class="s2">"Note"</span><span class="p">:</span> <span class="s2">"Great detective!"</span> <span class="p">},</span> <span class="p">{</span> <span class="s2">"Name"</span><span class="p">:</span> <span class="s2">"Holmes, Mycroft"</span><span class="p">,</span> <span class="s2">"Address"</span><span class="p">:</span> <span class="s2">"Diogenes Club, Pall Mall, Londres"</span><span class="p">,</span> <span class="s2">"Phone"</span><span class="p">:</span> <span class="s2">"(use telegraph)"</span><span class="p">,</span> <span class="s2">"Note"</span><span class="p">:</span> <span class="s2">"Works for the British government.</span><span class="se">\n</span><span class="s2">Brother of Holmes, Sherlock."</span> <span class="p">},</span> <span class="p">{</span> <span class="s2">"Name"</span><span class="p">:</span> <span class="s2">"Tintin"</span><span class="p">,</span> <span class="s2">"Address"</span><span class="p">:</span> <span class="s2">"Château de Moulinsart"</span><span class="p">,</span> <span class="s2">"Phone"</span><span class="p">:</span> <span class="s2">"421"</span><span class="p">,</span> <span class="s2">"Note"</span><span class="p">:</span> <span class="s2">"Has a dog named Snowy."</span> <span class="p">},</span> <span class="p">{</span> <span class="s2">"Name"</span><span class="p">:</span> <span class="s2">"Tournesol, Tryphon (prof.)"</span><span class="p">,</span> <span class="s2">"Address"</span><span class="p">:</span> <span class="s2">"Château de Moulinsart"</span><span class="p">,</span> <span class="s2">"Phone"</span><span class="p">:</span> <span class="s2">"421"</span><span class="p">,</span> <span class="s2">"Note"</span><span class="p">:</span> <span class="s2">"Creator of the Bianca rose."</span> <span class="p">}</span> <span class="p">]</span></code></pre> <p>On va affecter cette liste à une variable qui fera office de base de données :</p> <pre><code class="python"><span class="n">contacts</span> <span class="o">=</span> <span class="n">EXAMPLE</span></code></pre> <h3 id="toc-affichage">Affichage</h3> <p>Créons une fonction dédiée à l’affichage de cette liste :</p> <pre><code class="python"><span class="k">def</span> <span class="nf">display_contacts</span><span class="p">(</span><span class="n">dom</span><span class="p">):</span> <span class="n">html</span> <span class="o">=</span> <span class="s2">""</span> <span class="k">for</span> <span class="n">contactId</span> <span class="ow">in</span> <span class="nb">range</span><span class="p">(</span><span class="nb">len</span><span class="p">(</span><span class="n">contacts</span><span class="p">)):</span> <span class="n">contact</span> <span class="o">=</span> <span class="n">contacts</span><span class="p">[</span><span class="n">contactId</span><span class="p">]</span> <span class="n">html</span> <span class="o">+=</span> <span class="n">f</span><span class="s1">'&lt;tr id="{contactId}" data-xdh-onevent="Select" style="cursor: pointer;"&gt;'</span> <span class="k">for</span> <span class="n">key</span> <span class="ow">in</span> <span class="n">contact</span><span class="p">:</span> <span class="n">html</span> <span class="o">+=</span> <span class="n">f</span><span class="s1">'&lt;td&gt;{contact[key]}&lt;/td&gt;'</span> <span class="n">html</span> <span class="o">+=</span> <span class="s1">'&lt;/td&gt;'</span> <span class="n">dom</span><span class="o">.</span><span class="n">inner</span><span class="p">(</span><span class="s2">"Content"</span><span class="p">,</span> <span class="n">html</span><span class="p">)</span></code></pre> <p>Dans cette fonction, on récupère chaque contact de la liste, et, pour chacun de ces contacts, le contenu de chacun de ses champs. On va s’en servir pour créer le contenu du corps du tableau dédié à l’affichage de la liste, contenu qui sera stocké dans la variable <code>html</code>.<br> Le contenu de cette variable est ensuite injecté dans le corps de la table, plus précisément dans l’élément <code>tbody</code> d’identifiant <code>Content</code> (voir le fichier <code>Main.html</code>), grâce à la méthode <code>inner(…)</code>, que l’on a déjà rencontrée. Notez que le premier paramètre n’est plus, comme auparavant, une chaîne de caractères vide, mais bien l’identifiant de l’élément concerné, à savoir <code>Content</code>.<br> Chaque ligne du tableau a son propre identifiant, et un attribut <code>data-xdh-onevent="Select"</code> qui fera l’objet de la prochaine section.</p> <p>Enfin, on ajoute l’appel à cette fonction dans la fonction <code>ac_connect(…)</code>, :</p> <pre><code class="python"><span class="k">def</span> <span class="nf">ac_connect</span><span class="p">(</span><span class="n">dom</span><span class="p">):</span> <span class="n">dom</span><span class="o">.</span><span class="n">inner</span><span class="p">(</span><span class="s2">""</span><span class="p">,</span><span class="nb">open</span><span class="p">(</span><span class="s2">"Main.html"</span><span class="p">)</span><span class="o">.</span><span class="n">read</span><span class="p">())</span> <span class="n">display_contacts</span><span class="p">(</span><span class="n">dom</span><span class="p">)</span></code></pre> <h2 id="toc-détail-dun-contact-part3py">Détail d’un contact (<code>part3.py</code>)</h2> <blockquote> <ul> <li>Code source : <a href="https://github.com/epeios-q37/atlas-python/blob/master/tutorials/Contacts/part3.py">lien sur GitHub</a> ;</li> <li>exécution : <ul> <li>sur <a href="https://repl.it/@AtlasTK/atlas-python#tutorials/Contacts/part3.py"><em>Repl.it</em></a> : bouton <em>Run</em>, <code>n3</code> + <em>entrée</em>, clic sur URL,</li> <li>en local : <code>python3 atlas-python/tutorials/Contacts/part3.py</code> </li> </ul> </li> </ul> </blockquote> <p>Procédons maintenant à l’affichage des détails d’un contact sélectionné par l’utilisateur.</p> <h3 id="toc-affichage-1">Affichage</h3> <p>On va commencer par le remplissage des champs au sommet de l’interface avec les valeurs du contact sélectionné dans la liste.</p> <p>Voici la fonction correspondante :</p> <pre><code class="python"><span class="k">def</span> <span class="nf">display_contact</span><span class="p">(</span><span class="n">contactId</span><span class="p">,</span><span class="n">dom</span><span class="p">):</span> <span class="n">dom</span><span class="o">.</span><span class="n">set_values</span><span class="p">(</span><span class="n">contacts</span><span class="p">[</span><span class="n">contactId</span><span class="p">])</span></code></pre> <p>La méthode <code>set_values(…)</code> prend un dictionnaire avec, pour clefs, des identifiants d’éléments, et, pour valeurs, le contenu que doivent prendre ces éléments.<br> Comme, dans la page <em>HTML</em>, les identifiants des éléments sont identiques aux clefs correspondant aux champs d’un contact, le dictionnaire est déjà constitué et n’est plus à construire. On l’utilise donc tel quel dans l’appel de la méthode <code>set_values(…)</code>.<br> <code>contactId</code> est l’index, dans la liste <code>contacts</code>, du contact à afficher. </p> <h3 id="toc-sélection">Sélection</h3> <p>On va maintenant définir la fonction que l’on va affecter à l’action <code>Select</code> définit dans l’attribut <code>data-xdh-onevent</code> du code <em>HTML</em> qui est crée dans la précédente section :</p> <pre><code class="python"><span class="k">def</span> <span class="nf">ac_select</span><span class="p">(</span><span class="n">dom</span><span class="p">,</span><span class="nb">id</span><span class="p">):</span> <span class="n">display_contact</span><span class="p">(</span><span class="nb">int</span><span class="p">(</span><span class="nb">id</span><span class="p">),</span><span class="n">dom</span><span class="p">)</span></code></pre> <p>Le paramètre <code>id</code> contient l’identifiant de l’élément recevant l’évènement à l’origine de l’action à laquelle cette fonction a été affectée. Ici, l’évènement est un clic sur une ligne du tableau contenant la liste des contacts, évènement auquel a été associée l’action <code>Select</code> via l’attribut <code>data-xdh-onevent</code>. Conformément à ce qui va être défini ci-dessous dans la variable <code>CALLBACKS</code>, cette action va lancer la fonction <code>ac_select</code>.</p> <p>Dans la section précédente, on a vu que, pour le tableau <em>HTML</em> contenant la liste des contacts, chaque ligne a pour identifiant l’index, dans la table <code>contacts</code>, du contact correspondant. On peut donc utiliser directement <code>id</code>, après l’avoir converti en entier (<code>id</code> est fourni sous forme d’une chaîne de caractères), pour le passer à la fonction <code>display_contact(…)</code></p> <p>On met à jour la table <code>CALLBACKS</code>, en affectant cette fonction à l’action <code>Select</code> (définie comme valeur de l’attribut <code>data-xdh-onevent</code> dans le code <em>HTML</em> généré dans la précédente section) :</p> <pre><code class="python"><span class="n">CALLBACKS</span> <span class="o">=</span> <span class="p">{</span> <span class="err">…</span> <span class="s2">"Select"</span><span class="p">:</span> <span class="n">ac_select</span> <span class="p">}</span></code></pre> <h2 id="toc-À-suivre"><em>À suivre…</em></h2> <p>Sur les recommandations de l’équipe de modération, ce document a été découpé en deux dépêches.</p> <p>Celle-ci présentait le fichier <em>HTML</em> principal, celui des métadonnées, ainsi que les principales fonctions relatives à l’affichage. La <a href="https://q37.info/s/jz9ttdjb">seconde dépêche</a> portera sur la gestion des évènements.</p> </div><div><a href="https://linuxfr.org/news/developper-une-interface-web-avec-le-toolkit-atlas-1-2.epub">Télécharger ce contenu au format EPUB</a></div> <p> <strong>Commentaires :</strong> <a href="//linuxfr.org/nodes/122684/comments.atom">voir le flux Atom</a> <a href="https://linuxfr.org/news/developper-une-interface-web-avec-le-toolkit-atlas-1-2#comments">ouvrir dans le navigateur</a> </p>