URL: https://linuxfr.org/news/developper-une-interface-web-avec-le-toolkit-atlas-1-2 Title: Développer une interface web avec le toolkit Atlas (1/2) Authors: Claude SIMON Ysabeau Date: 2020-12-21T17:19:56+01:00 License: CC By-SA Tags: web, spa, python et atlas_toolkit Score: 4 Le *toolkit* *Atlas* permet de programmer des interfaces d’applications web monopages ([SPA](https://en.wikipedia.org/wiki/Single-page_application)). Il est léger (quelques dizaines de Ko), sans dépendances, ne nécessite pas de savoir programmer en *JavaScript*, et n’impose pas d’architecture logicielle de type [*MVC*](https://fr.wikipedia.org/wiki/Mod%C3%A8le-vue-contr%C3%B4leur). En outre, toute application développée avec le *toolkit* *Atlas* 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 [code QR](https://fr.wikipedia.org/wiki/Code_QR) qui s’affiche dans l’application. Le *toolkit* *Atlas* a déjà fait l’objet de [quelques publications](https://linuxfr.org/tags/atlas_toolkit/public) ici même. Pour varier un peu les plaisirs durant ces longues soirées ~~d’hiver~~ de couvre-feu, voici la première partie d’un document qui devrait faciliter l’utilisation du *toolkit* *Atlas*. Il détaille le développement d’une application (très) basique de gestion de contacts, dont l’apparence est la suivante : ![Apparence de l'application faisant l'objet du tutoriel 'Contacts'](https://q37.info/s/39dr4tcr.png) Le *toolkit* *Atlas* est disponible pour *Java*, *Node.js*, *Perl*, *Python* et *Ruby*. C’est la version la plus populaire, à savoir *Python*, 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. ---- [Homepage](https://atlastk.org) [Sur GitHub](https://github.com/epeios-q37/atlas-python) [Sur Repl.it](https://repl.it/@AtlasTK/atlas-python) [API](https://atlastk.org/api/fr) [Seconde partie](https://q37.info/s/jz9ttdjb) ---- # À propos de ce document L’accent étant mis sur la mise en œuvre de l'*API* du *toolkit* *Atlas*, le lecteur est supposé posséder les connaissances (basiques) nécessaires à la compréhension du code *HTML*/*CSS* et *Python* présent dans ce document. Les fichiers sources associés à ce document sont disponibles dans un [dépôt *GitHub*](https://github.com/epeios-q37/atlas-python/tree/master/tutorials/Contacts), lui-même cloné [sur *Repl.it*](https://repl.it/@AtlasTK/atlas-python), un *IDE* en ligne. Si *Python* 3 est installé sur votre ordinateur, vous pouvez récupérer le dépôt *GitHub* et visualiser/exécuter directement sur votre machine le code associé aux différentes sections de ce document. Vous pouvez également, notamment si vous n’avez pas installé *Python* 3, visualiser/exécuter, éventuellement après modification, ce code directement dans votre navigateur en utilisant le lien *Repl.it* ci-dessus. 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 *Repl.it* et en local. Les lignes, dans les fichiers source, précédant la ligne `import atlastk` 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 *toolkit* *Atlas*. # Le ficher *HTML* principal (`Main.html`) > Code source : [lien sur GitHub](https://github.com/epeios-q37/atlas-python/blob/master/tutorials/Contacts/Main.html). Le fichier `Main.html` est un fichier au format *HTML* décrivant l’interface. Ce fichier va prendre place dans la section *body* de la page *HTML* constituant l’interface de l’application. ## Structure générale Voici un aperçu partiel du contenu de ce fichier, mettant en évidence sa structure générale : ```html
``` Il est aisément compréhensible de celles et ceux qui sont familiers avec *HTML*. Ses différentes sous-parties, qui prennent la place de commentaires ci-dessus, vont être détaillées ci-dessous. ## Détail d’un contact Voici le code dédié à l’affichage du détail d’un contact : ```html
``` On y trouve un tableau, avec, pour chacun des champs constituant un contact, une ligne (chacune délimitée par `` et ``) accompagnée d’un libellé et d’un identifiant explicite. ## Boutons généraux Ces boutons vont servir à créer/éditer/supprimer un contact. En voici le code : ```html ``` À part l’attribut `data-xdh-onevent`, on n’a là que du *HTML* des plus classiques. Les différentes classes (valeurs `Display` et `DisplayAndSelect` des attributs `class`) ont cependant un rôle bien particulier, qui sera révélé dans les sections qui suivent. L’attribut `data-xdh-onevent` prend ici la place de l’habituel attribut `onclick`. L’attribut `onclick` prend habituellement pour valeur le code *JavaScript* à lancer lorsque l’on clique sur le bouton auquel il est affecté. Ici, à la place, on utilise l’attribut `data-xdh-onevent`, qui va prendre pour valeur un libellé d’action, libellé que l’on retrouvera dans le code *Python*. On va pouvoir ainsi coder les actions à réaliser lors d’un clic sur le bouton non plus en *JavaScript*, mais en *Python*. ## Boutons de saisie Ces boutons sont affichés lors de la saisie d’un contact, et permettent de valider ou d’annuler cette saisie. Voici le code correspondant : ```html ``` Là encore, rien de particulier, mis à part l’attribut `data-xdh-onevent`, que l’on a déjà rencontré ci-dessus. Le contenu des attributs `data-xdh-onevent`, à savoir `Cancel` et `Submit`, va être utilisé dans le code *Python* de l’application. Notez qu’ici le nom du bouton (la valeur de l’élément `button`) est identique à la valeur de son attribut `data-xdh-onevent`. C’est uniquement par commodité ; ce n’est en rien obligatoire. ## Liste de contacts Cette partie affiche le tableau qui va accueillir la liste des contacts au sein de son élément `tbody`, dont le contenu va être généré par l’application. En voici le contenu : ```html
Name Address Phone Note
``` Notez l’identifiant `Content`, que l’on va retrouver dans le code *Python*. L’identifiant `Contacts` n’est, lui, utilisé que dans le fichier `Head.html` décrit ci-dessous. # Le fichier *HTML* des métadonnées (`Head.html`) > Code source : [lien sur GitHub](https://github.com/epeios-q37/atlas-python/blob/master/tutorials/Contacts/Head.html). Ce fichier, également au format *HTML*, prendra place dans la section *head* de la page *HTML* constituant l’interface de l’application. ## Apparence de l’application La première partie de ce fichier définit le titre, l’icône, et, à l’aide de quelques règles *CSS*, diverses retouches au niveau de l’apparence de l’interface. En voici le contenu : ```html Address book ``` ## Visibilité des boutons La seconde partie du fichier permet de gérer la visibilité des boutons. En voici le contenu : ```html ``` On y voit des éléments `style` accompagnés d’un identifiant. Ces éléments vont permettre de cacher/afficher certains boutons. En effet, chaque élément `style` 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 *CSS* 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. On retrouvera les différents identifiants de ces éléments `style` dans le code *Python* détaillé dans les sections qui suivent. # Rendu de l’interface (`part1.py`) > * Code source : [lien sur GitHub](https://github.com/epeios-q37/atlas-python/blob/master/tutorials/Contacts/part1.py) ; > * exécution : > * sur [*Repl.it*](https://repl.it/@AtlasTK/atlas-python#tutorials/Contacts/part1.py) : bouton *Run*, `n1` + *entrée*, clic sur URL, > * en local : `python3 atlas-python/tutorials/Contacts/part1.py` 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. ## Affichage de la page *HTML* En premier lieu, on va définir la fonction qui sera appelée à chaque ouverture de session : ```python def ac_connect(dom): dom.inner("",open("Main.html").read()) ``` `dom` est un objet fournit par le *toolkit* *Atlas* ; chaque session a sa propre instance de cet objet. Dans cette fonction, la méthode `inner(…)`va remplacer la totalité de la page web par le contenu du fichier `Main.html` précédemment décrit. 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. À titre indicatif, il existe également les méthodes `before(…)`, `begin(…)`, `end(…)` et `after(…)` 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. On va ensuite affecter cette fonction à une action, à l’aide d’un dictionnaire nommé, par convention, `CALLBACKS` : ```python CALLBACKS = { "": ac_connect } ``` Ici, `ac_connect` est affecté à une action dont le libellé est une chaîne vide. Cette valeur correspond à l’action qui est lancée à chaque nouvelle session. ## La boucle évènementielle On va ensuite lancer la boucle évènementielle de l’application, en lui passant le dictionnaire des actions, ainsi que le contenu du fichier `Head.html` décrit précédemment : ```python atlastk.launch(CALLBACKS,None,open("Head.html").read()) ``` Le paramètre dont la valeur est `None` sera abordé plus tard. # Liste des contacts (`part2.py`) > * Code source : [lien sur GitHub](https://github.com/epeios-q37/atlas-python/blob/master/tutorials/Contacts/part2.py) ; > * exécution : > * sur [*Repl.it*](https://repl.it/@AtlasTK/atlas-python#tutorials/Contacts/part2.py) : bouton *Run*, `n2` + *entrée*, clic sur URL, > * en local : `python3 atlas-python/tutorials/Contacts/part2.py` Dans cette section, nous allons programmer l’affichage de la liste des contacts. ## Liste fictive On va d’abord créer une liste de contacts fictive, histoire d’avoir quelque chose à afficher : ```python EXAMPLE = [ { "Name": "Holmes, Sherlock", "Address": "221B Baker Street, Londres", "Phone": "(use telegraph)", "Note": "Great detective!" }, { "Name": "Holmes, Mycroft", "Address": "Diogenes Club, Pall Mall, Londres", "Phone": "(use telegraph)", "Note": "Works for the British government.\nBrother of Holmes, Sherlock." }, { "Name": "Tintin", "Address": "Château de Moulinsart", "Phone": "421", "Note": "Has a dog named Snowy." }, { "Name": "Tournesol, Tryphon (prof.)", "Address": "Château de Moulinsart", "Phone": "421", "Note": "Creator of the Bianca rose." } ] ``` On va affecter cette liste à une variable qui fera office de base de données : ```python contacts = EXAMPLE ``` ## Affichage Créons une fonction dédiée à l’affichage de cette liste : ```python def display_contacts(dom): html = "" for contactId in range(len(contacts)): contact = contacts[contactId] html += f'' for key in contact: html += f'{contact[key]}' html += '' dom.inner("Content", html) ``` 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 `html`. Le contenu de cette variable est ensuite injecté dans le corps de la table, plus précisément dans l’élément `tbody` d’identifiant `Content` (voir le fichier `Main.html`), grâce à la méthode `inner(…)`, 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 `Content`. Chaque ligne du tableau a son propre identifiant, et un attribut `data-xdh-onevent="Select"` qui fera l’objet de la prochaine section. Enfin, on ajoute l’appel à cette fonction dans la fonction `ac_connect(…)`, : ```python def ac_connect(dom): dom.inner("",open("Main.html").read()) display_contacts(dom) ``` # Détail d’un contact (`part3.py`) > * Code source : [lien sur GitHub](https://github.com/epeios-q37/atlas-python/blob/master/tutorials/Contacts/part3.py) ; > * exécution : > * sur [*Repl.it*](https://repl.it/@AtlasTK/atlas-python#tutorials/Contacts/part3.py) : bouton *Run*, `n3` + *entrée*, clic sur URL, > * en local : `python3 atlas-python/tutorials/Contacts/part3.py` Procédons maintenant à l’affichage des détails d’un contact sélectionné par l’utilisateur. ## Affichage On va commencer par le remplissage des champs au sommet de l’interface avec les valeurs du contact sélectionné dans la liste. Voici la fonction correspondante : ```python def display_contact(contactId,dom): dom.set_values(contacts[contactId]) ``` La méthode `set_values(…)` prend un dictionnaire avec, pour clefs, des identifiants d’éléments, et, pour valeurs, le contenu que doivent prendre ces éléments. Comme, dans la page *HTML*, 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 `set_values(…)`. `contactId` est l’index, dans la liste `contacts`, du contact à afficher. ## Sélection On va maintenant définir la fonction que l’on va affecter à l’action `Select` définit dans l’attribut `data-xdh-onevent` du code *HTML* qui est crée dans la précédente section : ```python def ac_select(dom,id): display_contact(int(id),dom) ``` Le paramètre `id` 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 `Select` via l’attribut `data-xdh-onevent`. Conformément à ce qui va être défini ci-dessous dans la variable `CALLBACKS`, cette action va lancer la fonction `ac_select`. Dans la section précédente, on a vu que, pour le tableau *HTML* contenant la liste des contacts, chaque ligne a pour identifiant l’index, dans la table `contacts`, du contact correspondant. On peut donc utiliser directement `id`, après l’avoir converti en entier (`id` est fourni sous forme d’une chaîne de caractères), pour le passer à la fonction `display_contact(…)` On met à jour la table `CALLBACKS`, en affectant cette fonction à l’action `Select` (définie comme valeur de l’attribut `data-xdh-onevent` dans le code *HTML* généré dans la précédente section) : ```python CALLBACKS = { … "Select": ac_select } ``` # *À suivre…* Sur les recommandations de l’équipe de modération, ce document a été découpé en deux dépêches. Celle-ci présentait le fichier *HTML* principal, celui des métadonnées, ainsi que les principales fonctions relatives à l’affichage. La [seconde dépêche](https://q37.info/s/jz9ttdjb) portera sur la gestion des évènements.