Outils pour utilisateurs

Outils du site


issue195:inkscape

Différences

Ci-dessous, les différences entre deux révisions de la page.

Lien vers cette vue comparative

Les deux révisions précédentesRévision précédente
Prochaine révision
Révision précédente
issue195:inkscape [2023/08/03 08:45] d52frissue195:inkscape [2023/08/03 12:42] (Version actuelle) auntiee
Ligne 6: Ligne 6:
 Correction : Cet article inclut une correction pour résoudre un problème dans le code publié le mois dernier qui ne fonctionnait pas si Inkscape insérait la balise <script> près du haut du fichier SVG. Correction : Cet article inclut une correction pour résoudre un problème dans le code publié le mois dernier qui ne fonctionnait pas si Inkscape insérait la balise <script> près du haut du fichier SVG.
  
-La dernière fois, j'ai montré comment écrire un petit morceau de JavaScript qui peut être ajouté à un fichier Inkscape de plusieurs pages afin que toutes les pages soient visibles dans un navigateur Web en ajoutant « #page-2 » à l'URL (sans les guillemets, et en remplaçant « 2 » par le numéro de la page concernée). C'est une avancée utile, mais Inkscape vous permet de nommer explicitement les pagesil serait donc intéressant de pouvoir utiliser ces noms dans l'URL, plutôt qu'une chaîne générique. Ce mois-ci, je vais étendre le script existant pour ajouter exactement cette capacité. Mais avant cela, je dois résoudre un problème qui a été découvert par « dwhall » sur le forum officiel d'Inkscape.+La dernière fois, j'ai montré comment écrire un petit morceau de JavaScript qui peut être ajouté à un fichier Inkscape de plusieurs pages afin que toutes les pages soient visibles dans un navigateur Web en ajoutant « #page-2 » à l'URL (sans les guillemets, et en remplaçant « 2 » par le numéro de la page concernée). C'est une avancée utile, mais Inkscape vous permet de nommer explicitement les pages il serait donc intéressant de pouvoir utiliser ces noms dans l'URL, plutôt qu'une chaîne générique. Ce mois-ci, je vais étendre le script existant pour ajouter cette capacité. Mais avant cela, je dois résoudre un problème qui a été découvert par « dwhall » sur le forum officiel d'Inkscape.
  
  
Ligne 13: Ligne 13:
 One solution to this is to manually move the <script> tag to the end of the file – but that involves editing XML in a text editor, which is not a very user-friendly approach. Instead I’ve modified the code by wrapping it all in a function, named ‘createViewElements()’. That stops the code running immediately as the JavaScript is parsed, but we still need some way to make sure it still runs once the page has loaded. The answer to this is to add a line at the end, outside the function, which listens for the browser’s ‘onload’ event, and responds by calling the function.** One solution to this is to manually move the <script> tag to the end of the file – but that involves editing XML in a text editor, which is not a very user-friendly approach. Instead I’ve modified the code by wrapping it all in a function, named ‘createViewElements()’. That stops the code running immediately as the JavaScript is parsed, but we still need some way to make sure it still runs once the page has loaded. The answer to this is to add a line at the end, outside the function, which listens for the browser’s ‘onload’ event, and responds by calling the function.**
  
-Bien que j'aie largement testé le code avant d'écrire l'article précédent, dwhall n'a pas réussi à le faire fonctionner dans ses propres fichiers. En creusant un peu, j'ai pu trouver le problème : dans mes fichiers de test, la balise <script> était insérée à la fin du fichier, alors que la leur l'était au début. Je ne sais pas exactement pourquoi cette différence s'est produite - nous avions tous deux utilisé différentes versions d'Inkscape, et j'avais également fait quelques modifications manuelles en testant le code, de sorte que la différence aurait pu être introduite de plusieurs façons différentes. Le fait que la balise <script> soit placée au début du fichier signifiait que le code JS était exécuté avant que le contenu SVG n'ait fini d'être lu et rendu, de sorte que l'appel à getElementsByTagName(), par exemple, ne renvoyait pas les éléments corrects. Ce même code fonctionnait correctement lorsqu'il se trouvait au bas du fichier.+Bien que j'aie largement testé le code avant d'écrire l'article précédent, dwhall n'a pas réussi à le faire fonctionner dans ses propres fichiers. En creusant un peu, j'ai pu trouver le problème : dans mes fichiers de test, la balise <script> était insérée à la fin du fichier, alors que la leur l'était au début. Je ne sais pas exactement pourquoi cette différence s'est produite - nous avions tous deux utilisé différentes versions d'Inkscape, et j'avais également fait quelques modifications manuelles en testant le code, de sorte que la différence aurait pu être introduite de plusieurs façons. Le fait que la balise <script> soit placée au début du fichier signifiait que le code JS était exécuté avant que le contenu SVG n'ait fini d'être lu et rendu, de sorte que l'appel à getElementsByTagName(), par exemple, ne renvoyait pas les éléments corrects. Ce même code fonctionnait correctement lorsque la balise se trouvait au bas du fichier.
  
-Une solution consiste à déplacer manuellement la balise <script> à la fin du fichier, mais cela implique de modifier le XML dans un éditeur de texte, ce qui n'est pas une approche très conviviale. Au lieu de cela, j'ai modifié le code en l'enveloppant dans une fonction, nommée « createViewElements() ». Cela empêche le code de s'exécuter immédiatement lorsque le JavaScript est analysé, mais nous avons toujours besoin d'un moyen de nous assurer qu'il s'exécute toujours une fois que la page a été chargée. La solution consiste à ajouter une ligne à la fin, en dehors de la fonction, qui écoute l'événement « onload » du navigateur et y répond en appelant la fonction.+Une solution consiste à déplacer manuellement la balise <script> à la fin du fichier, mais cela implique de modifier le XML dans un éditeur de texte, ce qui n'est pas une approche très conviviale. Au lieu de cela, j'ai modifié le code en l'enveloppant dans une fonction, nommée « createViewElements() ». Cela empêche le code de s'exécuter immédiatement lorsque le JavaScript est analysé, mais nous devons encore nous assurer qu'il s'exécute toujours une fois que la page a été chargée. La solution consiste à ajouter une ligne à la fin, en dehors de la fonction, qui écoute l'événement « onload » du navigateur et y répond en appelant la fonction.
  
  
Ligne 26: Ligne 26:
 Avec ces changements, le code ressemble maintenant à ce qui est montré ci-dessus. Avec ces changements, le code ressemble maintenant à ce qui est montré ci-dessus.
  
-J'ai ajouté des numéros de ligne pour indiquer plus clairement à quelles parties du code je fais référence dans le reste de l'article de ce mois, mais j'utilise la convention qui date de mes années BASIC dans les années 80 et qui consiste à incrémenter les nombres par dizaines afin de pouvoir insérer de nouvelles lignes de code entre les lignes si nécessaire. N'incluez aucun numéro de ligne lorsque vous entrez ce code dans Inkscape ! J'ai également supprimé les appels à console.log() que j'avais précédemment laissés, par souci de concision. Si votre propre code les contient encore, cela ne posera aucun problème.+J'ai ajouté des numéros de ligne pour indiquer plus clairement à quelles parties du code je fais référence dans le reste de cet article, mais j'utilise la convention qui date de mes années BASIC dans les années 80 et qui consiste à incrémenter les nombres par dizaines afin de pouvoir insérer de nouvelles lignes de code entre les lignes si nécessaire. N'incluez aucun numéro de ligne lorsque vous entrez ce code dans Inkscape ! J'ai également supprimé les appels à console.log() que j'avais précédemment laissés, par souci de concision. Si votre propre code les contient encore, cela ne posera aucun problème.
  
 Si nous voulons que ce code prenne en charge les pages nommées, nous devons commencer par nommer quelques pages dans Inkscape, puis ouvrir l'éditeur XML pour voir comment ces valeurs sont stockées dans le fichier. En utilisant la même page de démonstration que la dernière fois, j'ai donné à chaque page un nom basé sur son contenu - « Étoile rouge », « Diamant orange » et ainsi de suite. Si nous voulons que ce code prenne en charge les pages nommées, nous devons commencer par nommer quelques pages dans Inkscape, puis ouvrir l'éditeur XML pour voir comment ces valeurs sont stockées dans le fichier. En utilisant la même page de démonstration que la dernière fois, j'ai donné à chaque page un nom basé sur son contenu - « Étoile rouge », « Diamant orange » et ainsi de suite.
Ligne 39: Ligne 39:
 Ce n'est peut-être pas très évident lorsque cette capture d'écran a été redimensionnée et compressée pour correspondre au fichier PDF du magazine, mais si vous le faites vous-même, vous constaterez rapidement que les noms de page sont stockés dans l'élément <inkscape:page> (rien d'étonnant à cela !), dans un attribut appelé « label » qui se trouve également dans l'espace de noms « inkscape ». L'utilisation de l'espace de noms sur l'attribut me semble un peu inutile, étant donné que l'élément entier n'est pas standard et se trouve déjà dans un espace de noms personnalisé, mais nous devons travailler avec le format que nous avons, et non avec ce que nous pensons qu'il devrait être. Ce n'est peut-être pas très évident lorsque cette capture d'écran a été redimensionnée et compressée pour correspondre au fichier PDF du magazine, mais si vous le faites vous-même, vous constaterez rapidement que les noms de page sont stockés dans l'élément <inkscape:page> (rien d'étonnant à cela !), dans un attribut appelé « label » qui se trouve également dans l'espace de noms « inkscape ». L'utilisation de l'espace de noms sur l'attribut me semble un peu inutile, étant donné que l'élément entier n'est pas standard et se trouve déjà dans un espace de noms personnalisé, mais nous devons travailler avec le format que nous avons, et non avec ce que nous pensons qu'il devrait être.
  
-Nous devrons extraire les noms de page dans des variables JavaScript pour les traiter ultérieurement. En réalité, notre code fonctionne déjà sur une page à la fois, grâce à la boucle forEach(), et nous n'avons donc besoin que d'extraire le nom venant de l'attribut de la page en cours de traitement. Nous avons déjà utilisé la fonction getAttribute() pour extraire les valeurs d'attribut, mais cette fois-ci, nous devons également nous occuper de l'espace de noms. Pour cela, il faut utiliser la fonction getAttributeNS(), qui est exactement la même, mais qui prend un espace de noms comme premier paramètre. Malgré cette petite différence, nous garderons regroupé tout le code d'obtention des attributs, ce qui se traduit par l'insertion de la ligne 105 :+Nous devrons extraire les noms de page dans des variables JavaScript pour les traiter ultérieurement. En réalité, notre code fonctionne déjà sur une page à la fois, grâce à la boucle forEach(), et nous n'avons donc besoin que d'extraire le nom venant de l'attribut de la page en cours de traitement. Nous avons déjà utilisé la fonction getAttribute() pour extraire les valeurs d'attribut, maiscette fois-ci, nous devons également nous occuper de l'espace de noms. Pour cela, il faut utiliser la fonction getAttributeNS(), qui est exactement la même, mais qui prend un espace de noms comme premier paramètre. Malgré cette petite différence, nous garderons regroupé tout le code d'obtention des attributs, ce qui se traduit par l'insertion de la ligne 105 :
  
 105 const label = page.getAttributeNS(inkNS, 'label'); 105 const label = page.getAttributeNS(inkNS, 'label');
Ligne 51: Ligne 51:
 Il est tout à fait possible que l'attribut label n'existe pas sur une page particulière. Vous devriez être libre d'ajouter des étiquettes à certaines pages et pas à d'autres, sans que le code ne soit cassé. Heureusement, getAttributeNS() ne tombera pas à l'eau dans ce cas, mais retournera une valeur JS nulle. Ainsi, si « label » contient une chaîne de caractères, nous savons que la page a été étiquetée, alors que si elle est nulle, il n'y a pas eu d'étiquetage de la page. Nous pouvons utiliser cela pour écrire une instruction « if » contenant du code qui ne doit être exécuté que si une étiquette est présente. Cette instruction est insérée à la fin de la boucle existante, de sorte que le fichier se présente comme suit (en haut à droite). Il est tout à fait possible que l'attribut label n'existe pas sur une page particulière. Vous devriez être libre d'ajouter des étiquettes à certaines pages et pas à d'autres, sans que le code ne soit cassé. Heureusement, getAttributeNS() ne tombera pas à l'eau dans ce cas, mais retournera une valeur JS nulle. Ainsi, si « label » contient une chaîne de caractères, nous savons que la page a été étiquetée, alors que si elle est nulle, il n'y a pas eu d'étiquetage de la page. Nous pouvons utiliser cela pour écrire une instruction « if » contenant du code qui ne doit être exécuté que si une étiquette est présente. Cette instruction est insérée à la fin de la boucle existante, de sorte que le fichier se présente comme suit (en haut à droite).
  
-Notez le saut dans les numéros de ligne après 162, car nous aurons besoin de plus qu'une simple ligne de code dans cette section. La première chose à faire ici est de s'assurer que l'étiquette est valide pour être utilisée comme identifiant d'un élément <view>. Les ID ont des règles assez strictes sur les caractères qu'ils sont autorisés à contenir, alors que les étiquettes de page Inkscape sont beaucoup plus laxistes. Nous allons adopter une approche plutôt basique de ce problème : nous allons simplement remplacer chaque caractère qui n'est pas alphanumérique par un trait de soulignement.+Notez le saut dans les numéros de ligne après 162, car nous aurons besoin de plus qu'une seule ligne de code dans cette section. La première chose à faire ici est de s'assurer que l'étiquette est valide pour être utilisée comme identifiant d'un élément <view>. Les ID ont des règles assez strictes sur les caractères qu'ils sont autorisés à contenir, alors que les étiquettes de page Inkscape sont beaucoup plus laxistes. Nous allons adopter une approche plutôt basique de ce problème : nous allons simplement remplacer chaque caractère qui n'est pas alphanumérique par un trait de soulignement.
  
 163 const idLabel = label.replace(/\W/g, '_') ; 163 const idLabel = label.replace(/\W/g, '_') ;
Ligne 64: Ligne 64:
 Dans le monde de la ligne de commande, vous êtes peut-être à l'aise avec les classes de caractères dans les expressions régulières - des valeurs spéciales telles que [:alnum :] qui correspondent à la plage de caractères alphanumériques (équivalente à [a-zA-Z0-9]). JS possède son propre ensemble de classes de caractères, la correspondance la plus proche de [:alnum :] étant \w (w minuscule). Ce caractère correspond non seulement aux caractères alphanumériques, mais aussi au caractère de soulignement. Non, je ne sais pas pourquoi ils ont décidé d'ajouter un trait de soulignement arbitraire dans le mélange, mais c'est ainsi que cela fonctionne. Chacune de ces classes de caractères a son inverse, qui utilise la version majuscule de la lettre. Ainsi, le « \W » utilisé dans notre code correspond à tout caractère qui n'est PAS un caractère alphanumérique ou un trait de soulignement. Dans le monde de la ligne de commande, vous êtes peut-être à l'aise avec les classes de caractères dans les expressions régulières - des valeurs spéciales telles que [:alnum :] qui correspondent à la plage de caractères alphanumériques (équivalente à [a-zA-Z0-9]). JS possède son propre ensemble de classes de caractères, la correspondance la plus proche de [:alnum :] étant \w (w minuscule). Ce caractère correspond non seulement aux caractères alphanumériques, mais aussi au caractère de soulignement. Non, je ne sais pas pourquoi ils ont décidé d'ajouter un trait de soulignement arbitraire dans le mélange, mais c'est ainsi que cela fonctionne. Chacune de ces classes de caractères a son inverse, qui utilise la version majuscule de la lettre. Ainsi, le « \W » utilisé dans notre code correspond à tout caractère qui n'est PAS un caractère alphanumérique ou un trait de soulignement.
  
-<nowiki>+
 **The ‘g’ at the end of the regex is a flag that turns this into a ‘global’ regular expression. All that means is that it will apply to all the substrings that match, not just the first one. Without this a label such as “Red star #1” would be transformed into “Red_star #1”. With this one extra character the transformation becomes “Red_star__1” instead. Note that both the second space and the hash character are transformed, resulting in a double-underscore in the final string. If you prefer to collapse sequences of multiple matching characters down to a single underscore, replace the regex with /\W+/g instead. The additional ‘+’ will cause the ‘\W’ to not just match a single character, but any consecutive sequence of one or more characters, replacing entire spans of non-alphanumerics with a single underscore. I think this is usually a little more user-friendly, so I’ll include the ‘+’ in the final code. **The ‘g’ at the end of the regex is a flag that turns this into a ‘global’ regular expression. All that means is that it will apply to all the substrings that match, not just the first one. Without this a label such as “Red star #1” would be transformed into “Red_star #1”. With this one extra character the transformation becomes “Red_star__1” instead. Note that both the second space and the hash character are transformed, resulting in a double-underscore in the final string. If you prefer to collapse sequences of multiple matching characters down to a single underscore, replace the regex with /\W+/g instead. The additional ‘+’ will cause the ‘\W’ to not just match a single character, but any consecutive sequence of one or more characters, replacing entire spans of non-alphanumerics with a single underscore. I think this is usually a little more user-friendly, so I’ll include the ‘+’ in the final code.
  
 Now that we’ve got an ID-friendly name, we can create the new <view> element, just like we did last time. In fact, the code will be virtually identical, which makes it a prime target for moving out into a separate function. For our purposes we want a function that takes the strings for the ID and viewBox as parameters, as well as a reference to the current <page> element. It will create the new <view> and append it to the <page>, as before. The current code looks like this (above).** Now that we’ve got an ID-friendly name, we can create the new <view> element, just like we did last time. In fact, the code will be virtually identical, which makes it a prime target for moving out into a separate function. For our purposes we want a function that takes the strings for the ID and viewBox as parameters, as well as a reference to the current <page> element. It will create the new <view> and append it to the <page>, as before. The current code looks like this (above).**
  
-Le « g » à la fin de l'expression rationnelle est un indicateur qui la transforme en expression rationnelle « globale ». Cela signifie qu'elle s'appliquera à toutes les sous-chaînes qui correspondentet pas seulement à la première. Sans cela, une étiquette telle que « Étoile rouge n° 1 » serait transformée en « Étoile_rouge n° 1 ». Avec ce caractère supplémentaire, la transformation devient « Red_star__1 ». Notez que le deuxième espace et le caractère dièse sont tous deux transformés, ce qui donne un double trait dans la chaîne finale. Si vous préférez réduire les séquences de plusieurs caractères correspondants à un seul trait de soulignement, remplacez la regex par /\W+/g. Le « + » supplémentaire fera en sorte que « \W » ne corresponde pas seulement à un seul caractère, mais à toute séquence consécutive d'un ou plusieurs caractères, remplaçant ainsi des étendues entières de caractères non alphanumériques par un seul trait de soulignement. Je pense que c'est généralement un peu plus convivialc'est pourquoi j'inclurai le « + » dans le code final.+Le « g » à la fin de l'expression rationnelle est un indicateur qui la transforme en expression rationnelle « globale ». Cela signifie qu'elle s'appliquera à toutes les sous-chaînes qui correspondent et pas seulement à la première. Sans cela, une étiquette telle que « Étoile rouge n° 1 » serait transformée en « Étoile_rouge n° 1 ». Avec ce caractère supplémentaire, la transformation devient « Red_star__1 ». Notez que le deuxième espace et le caractère dièse sont tous deux transformés, ce qui donne un double trait dans la chaîne finale. Si vous préférez réduire les séquences de plusieurs caractères correspondants à un seul trait de soulignement, remplacez la regex par /\W+/g. Le « + » supplémentaire fera en sorte que « \W » ne corresponde pas seulement à un seul caractère, mais à toute séquence consécutive d'un ou plusieurs caractères, remplaçant ainsi des étendues entières de caractères non alphanumériques par un seul trait de soulignement. Je pense que c'est généralement un peu plus convivial et c'est pourquoi j'inclurai le « + » dans le code final
 + 
 +Maintenant que nous avons un nom convivial, nous pouvons créer le nouvel élément <view>, comme nous l'avons fait la dernière fois. En fait, le code sera pratiquement identique, ce qui en fait une cible de choix pour le transférer dans une fonction distincte. Pour nos besoins, nous voulons une fonction qui prenne en paramètre les chaînes de l'ID et de la viewBox, ainsi qu'une référence à l'élément <page> actuel. Elle créera la nouvelle <view> et l'ajoutera à la <page>, comme auparavant. Le code actuel ressemble à ceci (ci-dessus).
  
-Maintenant que nous avons un nom convivial, nous pouvons créer le nouvel élément <view>, comme nous l'avons fait la dernière fois. En fait, le code sera pratiquement identique, ce qui en fait une cible de choix pour le transférer dans une fonction distincte. Pour nos besoins, nous voulons une fonction qui prenne en paramètre les chaînes de l'ID et de la viewBox, ainsi qu'une référence à l'élément <page> actuel. Elle créera la nouvelle <vue> et l'ajoutera à la <page>, comme auparavant. Le code actuel ressemble à ceci (ci-dessus). 
-<\nowiki> 
  
 **Let’s extract lines 130 to 160 into a function, which we’ll put between the end of the existing function (line 180) and the event listener (line 200). The main change in this code is that the ID that we previously generated on line 140 is now going to be passed in to the function call, so on line 184 below we use the parameter name. We’ll also move the svgNS variable (previously on line 30, now on line 183) as it’s only used by the createElementNS() function and no longer needs to exist in the main function (next page, top right). **Let’s extract lines 130 to 160 into a function, which we’ll put between the end of the existing function (line 180) and the event listener (line 200). The main change in this code is that the ID that we previously generated on line 140 is now going to be passed in to the function call, so on line 184 below we use the parameter name. We’ll also move the svgNS variable (previously on line 30, now on line 183) as it’s only used by the createElementNS() function and no longer needs to exist in the main function (next page, top right).
Ligne 80: Ligne 80:
 I’ve opened the developer tools and switched to the Inspector in order to see what’s actually happened in the document. Sure enough, each of my <inkscape:page> elements now contains two children, both <view> elements, with an ID corresponding to the page number, and another corresponding to the label. Either can be used as a fragment identifier in the URL to give exactly the same result.** I’ve opened the developer tools and switched to the Inspector in order to see what’s actually happened in the document. Sure enough, each of my <inkscape:page> elements now contains two children, both <view> elements, with an ID corresponding to the page number, and another corresponding to the label. Either can be used as a fragment identifier in the URL to give exactly the same result.**
  
-Extrayons les lignes 130 à 160 dans une fonction, que nous placerons entre la fin de la fonction existante (ligne 180) et l'écouteur d'événements (ligne 200). Le principal changement dans ce code est que l'ID que nous avons précédemment généré à la ligne 140 va maintenant être transmis à l'appel de la fonction ; et donc, à la ligne 184 en dessous, nous utilisons le nom du paramètre. Nous allons également déplacer la variable svgNS (précédemment à la ligne 30, maintenant à la ligne 183) car elle n'est utilisée que par la fonction createElementNS() et n'a plus besoin d'exister dans la fonction principale (page suivante, en haut à droite).+Extrayons les lignes 130 à 160 dans une fonction, que nous placerons entre la fin de la fonction existante (ligne 180) et l'écouteur d'événements (ligne 200). Le principal changement dans ce code est que l'ID que nous avons précédemment généré à la ligne 140 va maintenant être transmis à l'appel de la fonction ; ainsi, à la ligne 184 en dessous, nous utilisons le nom du paramètre. Nous allons également déplacer la variable svgNS (précédemment à la ligne 30, maintenant à la ligne 183)car elle n'est utilisée que par la fonction createElementNS() et n'a plus besoin d'exister dans la fonction principale (page suivante, en haut à droite).
  
 Si vous avez suivi jusqu'ici, bravo ! Il est temps de faire une pause et de tester les nouvelles fonctionnalités. Vous devriez pouvoir accéder à chaque page soit en ajoutant « #page-n » à l'URL (par exemple, file.svg#page-3), soit en ajoutant un dièse suivi du titre de la page, les caractères non alphanumériques étant remplacés par des traits de soulignement. Avec mon fichier test, l'ajout de « #Orange_diamond » à l'URL produit ceci (image de la page suivante, en bas à gauche). Si vous avez suivi jusqu'ici, bravo ! Il est temps de faire une pause et de tester les nouvelles fonctionnalités. Vous devriez pouvoir accéder à chaque page soit en ajoutant « #page-n » à l'URL (par exemple, file.svg#page-3), soit en ajoutant un dièse suivi du titre de la page, les caractères non alphanumériques étant remplacés par des traits de soulignement. Avec mon fichier test, l'ajout de « #Orange_diamond » à l'URL produit ceci (image de la page suivante, en bas à gauche).
  
-J'ai ouvert les outils de développement et je suis allé dans l'inspecteur afin de voir ce qui s'est réellement passé dans le document. Bien sûr, chacun de mes éléments <inkscape:page> contient maintenant deux enfants, tous deux des éléments <view>, avec un ID correspondant au numéro de page et un autre correspondant à l'étiquette. L'un ou l'autre peut être utilisé comme identifiant de fragment dans l'URL pour donner exactement le même résultat.+J'ai ouvert les outils de développement et je suis allé dans l'inspecteur afin de voir ce qui s'est réellement passé dans le document. Effectivement, chacun de mes éléments <inkscape:page> contient maintenant deux enfants, tous deux des éléments <view>, avec un ID correspondant au numéro de page et un autre correspondant à l'étiquette. L'un ou l'autre peut être utilisé comme identifiant de fragment dans l'URL pour donner exactement le même résultat.
  
  
Ligne 95: Ligne 95:
 Vous pouvez vous arrêter là si vous voulez. Nous avons atteint l'objectif que nous nous étions fixé d'être capables d'accéder à des pages par leur étiquette. Mais, avec un petit effort, nous pouvons rendre ce script encore plus utile. Il existe une façon pour que ces ajouts soient appliqués en permanence au fichier. Vous pouvez vous arrêter là si vous voulez. Nous avons atteint l'objectif que nous nous étions fixé d'être capables d'accéder à des pages par leur étiquette. Mais, avec un petit effort, nous pouvons rendre ce script encore plus utile. Il existe une façon pour que ces ajouts soient appliqués en permanence au fichier.
  
-Actuellement, notre fichier SVG a une sérieuse limitation. Les éléments <view> sont créés dynamiquement quand le Javascript tourne - mais JS ne tourne que quand le fichier SVG est chargé directement ou via une balise <tag>, deux cas peu communs dans le Web actuel. Le plus osuvent, nos fichiers sont tiré sur une page par une balise HTML <img> ou une fonction CSS url(), et dans ces cas nous ne pouvons pas utiliser les identifieurs de fragment, sauf si nous éditions manuellement le fichier pour ajouter des éléments <view> comme décrit dans un article précédent.+Actuellement, notre fichier SVG a une sérieuse limitation. Les éléments <view> sont créés dynamiquement quand le Javascript tourne - mais JS ne tourne que quand le fichier SVG est chargé directement ou via une balise <objet>, deux cas peu communs dans le Web actuel. Le plus souvent, nos fichiers sont tirés sur une page par une balise HTML <img> ou une fonction CSS url(), et dans ces cas nous ne pouvons pas utiliser les identifieurs de fragment, sauf si nous éditons manuellement le fichier pour ajouter des éléments <view> comme décrit dans un article précédent.
  
-Pour contourner ce point, le code de cet article doit être ajouté, puis le fichier SVG chargé directement dans le navigateur Web et ensuite le fichier sauvé (avec un nouveau nom) dans le navigateur Web. Le nouveau fichier contient la version actuelle du document - c'est-à-dire celle qui contient les éléments <view> que le code a créé. Nous avons simplement automatisé la tache d'ajout des nouveaux éléments au fichier, en évitant le besoin d'une modification manuelle, source d'erreur.+Pour contourner cela, le code de cet article doit être ajouté, puis le fichier SVG chargé directement dans le navigateur Web et ensuite le fichier sauvé (avec un nouveau nom) dans le navigateur Web. Le nouveau fichier contient la version actuelle du document - c'est-à-dire celle qui contient les éléments <view> que le code a créé. Nous avons simplement automatisé la tache d'ajout des nouveaux éléments au fichier, en évitant le besoin d'une modification manuelle, source d'erreur.
  
  
Ligne 108: Ligne 108:
 Cela fonctionne, mais nous laisse avec un petit problème. Le nouveau fichier contient déjà les éléments <view> supplémentaires... mais il contient également le code qui crée les nouveaux éléments <view>. Si ce fichier est chargé directement dans un navigateur, tous les nouveaux éléments <view> sont créés à nouveau, ce qui fait qu'il y en a deux fois plus que ce que nous voulions. Voici ce que cela donne dans les outils de développement de Firefox (en bas à gauche). Cela fonctionne, mais nous laisse avec un petit problème. Le nouveau fichier contient déjà les éléments <view> supplémentaires... mais il contient également le code qui crée les nouveaux éléments <view>. Si ce fichier est chargé directement dans un navigateur, tous les nouveaux éléments <view> sont créés à nouveau, ce qui fait qu'il y en a deux fois plus que ce que nous voulions. Voici ce que cela donne dans les outils de développement de Firefox (en bas à gauche).
  
-Pour résoudre ce problème, nous devons modifier la fonction qui crée les éléments <view> afin de tester l'existence de l'ID dans la page. S'il en existe déjà, la fonction quitte la page avant de créer de nouveaux éléments. Dans le cas contraire, elle continue comme avant. Nous pouvons y parvenir en plaçant quelques lignes au début de la fonction. Elles vont après la ligne 182, mais comme j'ai déjà utilisé les numéros de ligne après celle-ci, je les montrerai sans numéro dans le code ci-dessous (c'était la même chose dans les années 80 - l'idée de numéroter par dizaines tombe à l'eau dès qu'il faut insérer 11 nouvelles lignes !) En haut à droite.+Pour résoudre ce problème, nous devons modifier la fonction qui crée les éléments <view> afin de tester l'existence de l'ID dans la page. S'il en existe déjà, la fonction quitte la page avant de créer de nouveaux éléments. Dans le cas contraire, elle continue comme avant. Nous pouvons y parvenir en plaçant quelques lignes au début de la fonction. Leur place est après la ligne 182, mais comme j'ai déjà utilisé les numéros de ligne après celle-ci, je les montrerai sans numéro dans le code ci-dessous (c'était la même chose dans les années 80 - l'idée de numéroter par dizaines tombe à l'eau dès qu'il faut insérer 11 nouvelles lignes !) En haut à droite.
  
 La première ligne assigne null à la variable « foundID » si l'ID n'existe PAS déjà dans la page. Dans le cas contraire, elle attribue une référence à l'élément. La deuxième ligne teste ensuite « foundID » et renvoie la fonction si elle n'est pas nulle (c'est-à-dire si l'élément existe déjà). La première ligne assigne null à la variable « foundID » si l'ID n'existe PAS déjà dans la page. Dans le cas contraire, elle attribue une référence à l'élément. La deuxième ligne teste ensuite « foundID » et renvoie la fonction si elle n'est pas nulle (c'est-à-dire si l'élément existe déjà).
issue195/inkscape.1691045125.txt.gz · Dernière modification : 2023/08/03 08:45 de d52fr