SVG interactif avec

Je tente d’intégrer une visualisation de données interactive basée sur SVG. Je génère le SVG à partir d’un système distinct (mais toujours dans le même domaine de second niveau que mon installation Discourse). J’ai essayé d’intégrer le SVG à l’aide d’une balise OBJECT…

<object type="image/svg+xml" data="full_URL_to_foo.svg">
(affiché si le chargement de l'objet échoue)
</object>

Si j’intègre simplement ce SVG (il est généré dynamiquement à chaque fois) avec une balise IMG, l’image s’affiche, mais (comme je m’y attendais) il n’y a aucune interactivité…

<img src="full_URL_to_foo.svg">

Des idées ou des pistes où je pourrais trouver des indices concernant les SVG et Discourse ? :slight_smile:

1 « J'aime »

Le moyen le plus simple de faire fonctionner cela consiste à utiliser une iframe. Ajoutez le domaine SVG au paramètre de site allowed_iframes et intégrez-le dans un message en utilisant HTML.

5 « J'aime »

Hmmmm, donc c’est la méthode facile.

Existe-t-il une méthode difficile que je pourrais essayer ?

…parce que je veux avoir des liens dans le SVG qui modifient l’emplacement du navigateur. Les liens dans le SVG, dans un IFRAME, changent ce qui est affiché dans l’IFRAME . . .

Je soupçonne que l’incorporation de JS dans le sujet, juste avant l’IFRAME, et l’appel d’une fonction JS dans la page onclick dans le SVG… cela ne fonctionnera probablement pas non plus.

Est-ce que je suis clair ? Devrais-je ajouter un peu de code JS léger, à l’instar de Mitigate XSS Attacks with Content Security Policy, puis essayer d’y accéder depuis le SVG dans l’IFRAME ? …ou est-ce que « dans l’IFRAME » est une forteresse hermétique ?

Peut-être que je devrais demander comment je peux intégrer directement le SVG dans la page ? Ensuite, utiliser le code JS injecté par le composant du thème pour interagir avec mon autre serveur et mettre à jour dynamiquement le SVG ?

Un coup de main s’il vous plaît :slight_smile:

2 « J'aime »

Placer le SVG dans le message en l’entourant d’une div spéciale et utiliser un composant de thème pour le convertir en balise object via le rappel decorateCooked pourrait fonctionner. Consultez le Guide du développeur pour les thèmes Discourse.

3 « J'aime »

…au cas où quelqu’un suivrait, decorateCooked() est obsolète. Je teste decorateCookedElement() à la place.

1 « J'aime »

Je suis confronté à une erreur CORS (Access-Control-Allow-Origin). Je ne suis pas familier avec son fonctionnement…

J’ai deux sites : le site Discourse hébergé (forum.moversmindset.com) et un site WordPress basé sur Apache (moversmindset.com). Notez qu’il n’y a pas de contenu évident sur le site WordPress : il génère des flux RSS, sert des médias, etc. Si vous accédez au domaine, il vous redirigera simplement vers le forum.

J’ai un répertoire qui renvoie des réponses de type SVG aux requêtes GET. Par exemple (ce n’est pas l’URL réelle) : https://moversmindset.com/foo/bar.php

Dans mon thème Discourse, j’expérimente avec du code JavaScript (qui deviendra éventuellement un plugin officiel). Il appelle api.decorateCooked() sur des DIV spécifiques qui contiennent un attribut data-custom ajouté. Ainsi, à l’intérieur de la fonction appelée par decorateCooked(), je fais essentiellement :

$.get(‘https://moversmindset.com/foo/bar.php’ … bla bla blah

Je souhaite donc récupérer le SVG puis l’ajouter au DOM. Mais la console d’erreurs de mon navigateur indique :

Question :

Cela signifie-t-il que je dois configurer CORS sur l’installation Discourse ou sur le serveur Apache/WordPress ?

Je dois déjà avoir configuré https://moversmindset.com comme autorisé dans les paramètres CORS de Discourse.

2 « J'aime »

Je pense que c’est de ce côté-ci. Peux-tu jeter un coup d’œil à Access-Control-Allow-Origin header - HTTP | MDN si ce n’est pas déjà fait et voir si cela te donne des indices ?

4 « J'aime »

de tout petits pas, mais OUI !

J’ai dû ajouter un en-tête Access-Control-Allow-Origin sur le serveur Apache/WP. Cela a rendu le j/s (provenant de la plateforme Discourse) heureux. Merci.

3 « J'aime »

J’ai continué à comprendre cela progressivement. Cela nécessite beaucoup de configuration pour poser ma question :

SVG

J’ai un serveur web qui génère des SVG. Pour cette question, il génère un SVG de test très simple…

<svg xmlns="http://www.w3.org/2000/svg" stroke-linejoin="round" viewBox="0 0 100 100">
<path d="M50,4L4,50L50,96L96,50Z" stroke="#40638C" stroke-width="3"></path>
<path d="M50,5L5,50L50,95L95,50Z" stroke="#333" fill="#40638C" stroke-width="3"></path>
<path d="M37,42c-1,0,11-20,13-20c1,0,15,20,13,20h-9c0,8,9,22,12,25l-4,4l-8,-7v13h-10v-35z" stroke="#40495E" fill="#40495E"></path>
<path d="M35,40c-1,0,11-20,13-20c1,0,15,20,13,20h-9c0,8,9,22,12,25l-4,4l-8,-7v13h-10v-35z" stroke="#333" fill="#555"></path>
</svg>

C’est simplement un signe de « fusion » assez élaboré. Notez qu’il contient quatre éléments PATH.

Intégration

Pour intégrer le SVG dans un message, j’utilise un script JavaScript ajouté via mon thème.

L’objectif final serait de créer un véritable plugin. Mais je cherche simplement à construire une preuve de concept. Donc, j’ai simplement collé le code dans la section <head> de la personnalisation de mon thème :

<script type="text/discourse-plugin" version="0.8">
var UMB = {
    svgload: function(base, target) {
        var url = base + $(target).text();
        $(target).html('');
        $.ajax({
            method: "GET",
            url: url,
            async: false,
            dataType: "text",
            success: function(data) { $(target).append(data); }
        });
        alert('chargé !');
        $(target).children('path').each(function(){alert('voici un élément path');});
    },
}
$.fn.umbdv = function() {
    this.each(
        function() {
            UMB.svgload('__URL_REDACTED__', this);
        }
    );
    return this;
};
api.decorateCooked(
  $elem => $elem.children('.cooked div[data-custom="umbdv"]').umbdv(),
  { id: 'umbdv' }
);
</script>

Où…

var UMB = { est simplement une variable globale qui m’évite d’avoir des fonctions anonymes géantes partout.

$.fn.umbdv = est [ce que je pense être appelé] un « plugin » étendant JQuery.

api.decorateCooked( me permet de manipuler le message avant qu’il ne soit envoyé au navigateur.

Incantation

Dans un sujet, j’écris ensuite…

<div data-custom="umbdv">/vtest</div>

UMB.svgload('__URL_REDACTED__', this) est appelé pour ce DIV.

UMB.svgload() comprend correctement la chaîne /vtest, compose une URL et effectue la requête AJAX. Il exécute avec succès append(data) et boop, mon SVG est intégré…

Mon alert() à l’intérieur de UMB.svgload() se déclenche ensuite, exactement comme prévu. (C’est évidemment une astuce de débogage, non ? :))

La question (enfin)

J’ai un sujet réservé AU PERSONNEL dans mon forum hébergé sur Discourse où vous pouvez voir cela en action. (Je m’adresse au personnel/support de Discourse qui peut pénétrer dans mon installation en tant qu’utilisateurs Admin.)

https://forum.moversmindset.com/t/svg-experimentation-in-progress/1109

Pourquoi…

$(target).children('path').each(function(){alert('voici un élément path');});

…ne sélectionne aucun des éléments PATH ?

Cela ne fait rien — aucune erreur. Rien du tout.

Suivant

Voici où j’irai si je parviens à faire fonctionner cette preuve de concept triviale avec alert()

Je suis conscient que le fragment du DOM avec lequel je « travaille » n’est pas encore connecté au DOM réel du document (au moment où UMB.svgload() est appelé). C’est pourquoi j’attends que $(target)… soit ce dont j’ai besoin.

À terme, j’intégrerai des SVG beaucoup plus complexes et j’aurai besoin d’utiliser des sélecteurs JQuery plus avancés. Je veux trouver de nombreux éléments à l’intérieur de $(target) et attacher des gestionnaires d’événements (comme onclick, par exemple) qui appelleront d’autres fonctions globales UMB.….

1 « J'aime »

Les iframes peuvent modifier la navigation de niveau supérieur si vous le souhaitez

http://w3c-test.org/html/semantics/embedded-content/the-iframe-element/iframe_sandbox_allow_top_navigation_by_user_activation-manual.html

3 « J'aime »

Merci pour l’astuce !

Mais je préfère nettement le SVG en ligne maintenant.

Quoi qu’il en soit. Quelques semaines plus tard. Ça ne fonctionne pas.

Il ne semble pas possible de manipuler les éléments du DOM SVG une fois qu’ils sont intégrés dans le document principal. Je n’arrive donc pas à comprendre comment ajouter des déclencheurs ou des actions d’événements (ce qu’on pourrait facilement faire avec onclick, etc., si le SVG était chargé dans une iframe).

((Je n’utilise pas d’iframe, c’était tout l’objectif.))

¯\_(ツ)_/¯

1 « J'aime »

This topic was automatically closed 30 days after the last reply. New replies are no longer allowed.