**Over the past two articles, I’ve introduced the Web > Interactive Mockup extension, and gone on to show how it’s possible to create the same effect – and with fewer problems – with just a minimal amount of JavaScript. This time, I’ll be finishing this project by adding a little more code that will demonstrate some additional mock-up capabilities that simply aren’t possible using the extension. As a reminder, so far I’ve created a mock-up design consisting of three layers, each representing a different page in a website (which could equally well have been a design for an app, tutorial or presentation). By stacking the layers on top of each other, the JS code simply has to hide all the layers, then re-show the right one when the mock UI is clicked. This code is stored in the Inkscape document, and accessed via File > Document Properties, then the Scripting tab, the Embedded Scripts tab, and finally clicking on the randomly-generated Script ID in the list. Your code will appear in the Content pane at the bottom of the dialog – which is unfortunately not resizeable (you may wish to copy/paste between Inkscape and a text editor to make it easier to modify the code). After last month’s additions, the code looks like that shown above.** Au cours des deux derniers articles, j'ai présenté l'extension Web > Maquette Web interactive, puis j'ai montré comment il est possible de créer le même effet - et avec moins de problèmes - avec une quantité minimale de JavaScript. Cette fois-ci, je vais terminer ce projet en ajoutant un peu plus de code qui démontrera quelques capacités supplémentaires de maquettage qui ne sont tout simplement pas possibles en utilisant l'extension. Pour rappel, jusqu'à présent, j'ai créé une maquette composée de trois calques, chacune représentant une page différente d'un site Web (qui aurait tout aussi bien pu être la conception d'une application, d'un tutoriel ou d'une présentation). En empilant les calques les uns sur les autres, le code JS doit simplement masquer tous les calques, puis réafficher le bon lorsque l'on clique sur la maquette de l'interface utilisateur. Ce code est stocké dans le document Inkscape, et on y accède via Fichier > Propriétés du document, puis l'onglet Programmation, l'onglet Programmes incorporés, et enfin en cliquant sur l'ID du script généré aléatoirement dans la liste. Le code apparaîtra dans le volet Contenu au bas de la boîte de dialogue - qui n'est malheureusement pas redimensionnable (vous pouvez copier/coller entre Inkscape et un éditeur de texte pour faciliter la modification du code). Après les ajouts du mois dernier, le code ressemble à celui illustré ci-dessus. **Within each interactive element, a single line of JS triggers the change to a different ‘page’ of the demo. These can be found by right-clicking on one of the elements, selecting Object Properties, then expanding the Interactivity section at the bottom of the dialog. For my examples, I’m just triggering changes on mouse clicks, so the ‘onclick’ field contains something like this: showLayer("about") That’s all we needed to do in order to create an interactive mock-up that scales with the size of the web browser, and doesn’t allow any non-active pages to be visible. Now let’s push things a little further with the addition of some new features. When looking at the pages of our mock website, it’s clear that they have some common elements – in this case the whole header section. Wouldn’t it be nice if we could keep those on a separate layer, so that any changes to those elements can be made in a single place, rather than having to apply them to each separate layer in our file? This is the sort of thing for which many applications use a ‘Master’ layer. Although not as politically charged as the use of ‘master-slave’ relationships in the computing world, it’s nonetheless a term that can offend people, and which is tending to be phased out. So rather than propagate a troublesome word for no real gain, I’ll be using the term ‘Main layer’.** Dans chaque élément interactif, une seule ligne de JS déclenche le passage à une autre « page » de la démo. Vous pouvez les trouver en cliquant avec le bouton droit de la souris sur l'un des éléments, en sélectionnant Propriétés de l'objet, puis en développant la section Interactivité en bas de la boîte de dialogue. Pour mes exemples, je ne déclenche des changements qu'en cas de clics de souris, le champ « onclick » contient donc quelque chose comme ceci : showLayer("about") C'est tout ce dont nous avions besoin pour créer une maquette interactive qui s'adapte à la taille du navigateur Web et empêche les pages non actives d'être visibles. Poussons maintenant les choses un peu plus loin en ajoutant quelques nouvelles fonctionnalités. Lorsque l'on regarde les pages de notre site Web fictif, il est clair qu'elles ont des éléments communs - dans ce cas, toute la section de l'en-tête. Ne serait-il pas agréable de pouvoir les conserver sur un calque séparé, de sorte que toute modification de ces éléments puisse être effectuée en un seul endroit, plutôt que de devoir l'appliquer à chaque calque distinct de notre fichier ? C'est le genre de choses pour lesquelles de nombreuses applications utilisent un calque « maître ». Bien qu'il ne soit pas aussi politiquement chargé que l'utilisation des relations « maître-esclave » dans le monde de l'informatique, c'est néanmoins un terme qui peut offenser les gens et qui tend à disparaître progressivement. Aussi, plutôt que de propager un mot gênant sans réel intérêt, j'utiliserai le terme « calque principal ». **Our first step, therefore, is to split the file into a single Main layer, plus one additional layer for each page. The Main layer will contain all the common elements, and the others will contain just the page-specific parts. We therefore want our Main layer to be at the bottom of the z-stack, and to remain visible at all times. Here’s how our existing three layers are split into the four we now need: On the left we have the previous three pages. On the right we now have our Main layer at the bottom, with the three content layers above. I’ve added a green border around each of the content layers to indicate their extents: they each now have a transparent background, so without that it wouldn’t be so clear exactly how they relate to the positions in the old pages. These green borders are a temporary addition while developing the mock-up, and are removed before the layers are actually used. Additionally, although I’ve spread the pages out for this image, in practice they’re all stacked on top of each other within the document’s viewBox, as before. By showing the Main layer, plus one of the others at a time, we can therefore reproduce the same appearance as the three layers in the old version. All we need to do now is to modify our code to do the same thing on our behalf. To make the new code a little more readable, we’ll first use the XML editor to change the ID of the new layer to ‘main’, in the same way that we changed the layer IDs previously. When viewed in the XML editor, the top level of our document now looks something like that shown above.** Notre première étape consiste donc à diviser le fichier en un seul calque principal, plus un calque supplémentaire pour chaque page. Le calque principal contiendra tous les éléments communs, et les autres ne contiendront que les parties spécifiques à la page. Nous voulons donc que notre calque principal se trouve en bas de la pile z et qu'il reste visible à tout moment. Voici comment nos trois calques existants sont divisés en quatre calques dont nous avons maintenant besoin (en haut à gauche). À gauche, nous avons les trois pages précédentes. À droite, nous avons maintenant notre calque principal en bas, avec les trois calques de contenu au-dessus. J'ai ajouté une bordure verte autour de chacune des couches de contenu pour indiquer leur étendue : elles ont toutes un arrière-plan transparent ; sans cela, leur lien avec leurs positions dans les anciennes pages ne serait pas très clair. Ces bordures vertes sont un ajout temporaire pendant le développement de la maquette, et seront retirées avant que les calques ne soient réellement utilisés. En outre, bien que j'aie étalé les pages sur cette image, dans la pratique, elles sont toutes empilées les unes sur les autres dans la fenêtre (viewBox) du document, comme auparavant. En affichant le calque principal, plus un des autres à la fois, nous pouvons donc reproduire la même apparence que les trois calques de l'ancienne version. Il ne nous reste plus qu'à modifier notre code pour qu'il fasse la même chose à notre place. Pour rendre le nouveau code un peu plus lisible, nous allons d'abord utiliser l'éditeur XML pour changer l'ID du nouveau calque en « main » (principal), de la même manière que nous avons changé les ID des calques précédemment. Dans l'éditeur XML, le niveau supérieur de notre document ressemble maintenant à l'illustration ci-dessus. **Looking back at our JavaScript file from earlier, we still want our function to perform the same basic task: hide all the layers, then show a specific one. Except now we also want it to show a second layer at the same time. It’s these two lines that are responsible for re-showing the specified layer in the existing code: const layerToShow = document.querySelector("#" + id); layerToShow.style.display = "inline"; We could simply add a similar pair of lines, hard-coding the ID in the querySelector() call as "#main". That would definitely do the job, but it’s not very flexible. What if we want to show two ‘main’ layers later, perhaps to separate the text from the graphic elements? To give us this extra flexibility let’s create an array of layers that we want to show, then loop over them to turn them all on. If you’re not a programmer you may not be familiar with arrays: for our purposes you can think of them as a special type of variable that can hold a list of things. For this simple mock-up, our list will always contain ‘main’ and the id that was passed into the function, but you should be able to guess how you might extend it to include ‘main-text’ and ‘main-graphics’: const layersToDisplay = ["main", id];** En regardant notre fichier JavaScript de tout à l'heure, nous voulons toujours que notre fonction effectue la même tâche de base : masquer tous les calques, puis afficher un calque spécifique. Sauf que maintenant, nous voulons aussi qu'elle affiche un deuxième calque en même temps. Ce sont ces deux lignes qui sont responsables du réaffichage du calque spécifié dans le code existant : const layerToShow = document.querySelector("#" + id); layerToShow.style.display = "inline"; Nous pourrions simplement ajouter une paire de lignes similaires, en codant en dur l'ID dans l'appel querySelector() comme « #main ». Cela ferait l'affaire, mais ce n'est pas très souple. Que faire si nous voulons afficher deux calques « principaux » plus tard, peut-être pour séparer le texte des éléments graphiques ? Pour nous donner cette flexibilité supplémentaire, créons un éventail (« array ») des calques que nous voulons afficher, puis bouclons sur ceux-ci pour les activer tous. Si vous n'êtes pas un programmeur, vous n'êtes peut-être pas familier avec les « arrays » : pour nos besoins, vous pouvez les considérer comme un type spécial de variable qui peut contenir une liste de choses. Pour cette simple maquette, notre liste contiendra toujours « main » et l'id qui a été passé dans la fonction, mais vous devriez être capable de deviner comment vous pourriez l'étendre pour inclure « main-text » et « main-graphics » : const layersToDisplay = ["main", id] ; **Now we need to step through the array, pulling out one item at a time to work with. As we pull each of them out (using a forEach() loop), we get to assign the value to a variable. By naming this variable ‘id’, we are able to reuse our existing code for finding and showing the layer. The end result is something very similar to the code that was previously at the end of the showLayer() function, just with a little more wrapped around it (shown above). The last thing we need to do is to make sure that all the clickable elements still call the showLayer() function, passing the correct ID, after the re-working of layers that we did earlier. It’s particularly important to double-check any items that you’ve moved to the Main layer. Once you’re happy, load the page into a web browser and ensure each of the elements functions as you expect it to when you click on it – if any don’t, then double-check the code associated with them. So far, so good. But on trying out your interactive mock-up, you may have noticed that the mouse pointer doesn’t change to indicate that elements are clickable. It’s a minor visual thing, but we can definitely improve it. There are various ways to tackle this, but they all end up with us needing a line of CSS that tells the browser what cursor type to use. We want this to apply to all the elements with an ‘onclick’ handler. In our SVG, these are all implemented using ‘onclick’ attributes directly in the XML content – which means we should be able to add a style rule using an ‘[onclick]’ selector (matches any element with an ‘onclick’ attribute). That sounds like a perfect use for Inkscape’s ‘Selectors and CSS dialog’, right?** Maintenant, nous devons parcourir l'éventail, en extrayant un élément à la fois pour travailler avec. Au fur et à mesure que nous extrayons chacun d'entre eux (en utilisant une boucle forEach()), nous pouvons affecter la valeur à une variable. En nommant cette variable « id », nous pouvons réutiliser notre code existant pour trouver et afficher le calque. Le résultat final est très similaire au code qui se trouvait précédemment à la fin de la fonction showLayer(), mais avec un peu plus d'habillage (voir ci-dessus). La dernière chose que nous devons faire est de nous assurer que tous les éléments cliquables appellent toujours la fonction showLayer(), en passant l'ID correct, après le remaniement des calques que nous avons fait plus tôt. Il est particulièrement important de revérifier tous les éléments que vous avez déplacés vers le calque principal. Une fois que vous êtes satisfait, chargez la page dans un navigateur Web et vérifiez que chaque élément fonctionne comme prévu lorsque vous cliquez dessus - si ce n'est pas le cas, vérifiez le code qui lui est associé. Jusqu'ici, tout va bien. Mais en essayant votre maquette interactive, vous avez peut-être remarqué que le pointeur de la souris ne change pas pour indiquer que les éléments sont cliquables. Il s'agit d'un problème visuel mineur, mais nous pouvons certainement l'améliorer. Il existe plusieurs façons d'aborder ce problème, mais elles aboutissent toutes à la nécessité d'une ligne de CSS qui indique au navigateur le type de curseur à utiliser. Nous voulons que cette ligne s'applique à tous les éléments dotés d'un attribut « onclick ». Dans notre SVG, ces éléments sont tous implémentés à l'aide d'attributs « onclick » directement dans le contenu XML, ce qui signifie que nous devrions être en mesure d'ajouter une règle de style à l'aide d'un sélecteur « [onclick] » (correspondant à tout élément avec un attribut « onclick »). Cela semble être une utilisation parfaite de la boîte de dialogue « Sélecteurs et CSS » d'Inkscape, n'est-ce pas ? **Wrong. As I mentioned in part 112 of this series, the dialog doesn’t recognise the attribute selector syntax. An alternative is to create a suitable