Interaktives SVG mit A

Ich versuche, eine interaktive, auf SVG basierende Datenvisualisierung einzubetten. Ich generiere das SVG in einem separaten System (befindet sich aber noch in derselben Second-Level-Domain wie meine Discourse-Installation). Ich habe versucht, das SVG über ein OBJECT-Tag einzubinden…

<object type="image/svg+xml" data="vollständige_URL_zu_foo.svg">
(wird angezeigt, falls das Laden des Objekts fehlschlägt)
</object>

Wenn ich das SVG (das jedes Mal dynamisch generiert wird) einfach über ein IMG-Tag einbinde, erscheint die Grafik, aber (wie erwartet) gibt es keine Interaktivität…

<img src="vollständige_URL_zu_foo.svg">

Habt ihr Gedanken oder Hinweise, wo ich weitere Informationen zu SVGs und Discourse finden kann? :slight_smile:

1 „Gefällt mir“

Der einfachere Weg, dies zum Laufen zu bringen, ist die Verwendung eines iframes. Fügen Sie die SVG-Domain zur Site-Einstellung allowed_iframes hinzu und fügen Sie sie mit HTML zu einem Beitrag hinzu.

5 „Gefällt mir“

Hmmmm, das ist also der einfache Weg.

Gibt es einen schwierigeren Weg, den ich ausprobieren kann?

…weil ich Links im SVG haben möchte, die den Browserstandort ändern. Links im SVG innerhalb eines IFRAMEs ändern, was im IFRAME angezeigt wird …

Ich vermute, dass das Einbetten von JavaScript im Thema, direkt vor dem IFRAME, und das Aufrufen einer JavaScript-Funktion auf der Seite per onclick im SVG … ebenfalls nicht funktionieren wird.

Mache ich mich verständlich? Sollte ich etwas schlankes JavaScript-Code-Beispiel ala Mitigate XSS Attacks with Content Security Policy hinzufügen und dann versuchen, das aus dem SVG im IFRAME aufzurufen? …oder ist „im IFRAME

2 „Gefällt mir“

Das Einfügen des SVGs in den Beitrag, der durch ein spezielles umgebendes div gekennzeichnet ist, und die Verwendung einer Theme-Komponente, um es mithilfe des decorateCooked-Callbacks in ein object-Tag umzuwandeln, könnte funktionieren. Überprüfen Sie den Entwicklerleitfaden für Discourse-Themes.

3 „Gefällt mir“

…falls jemand mitliest: decorateCooked() ist veraltet. Ich experimentiere stattdessen mit decorateCookedElement().

1 „Gefällt mir“

Ich habe ein Problem mit CORS/Access-Control-Allow-Origin. Mir ist nicht klar, wie das funktioniert…

Ich habe zwei Seiten: die gehostete Discourse-Seite (forum.moversmindset.com) und eine auf Apache basierende WordPress-Seite (moversmindset.com). Beachten Sie, dass auf der WordPress-Seite keine offensichtlichen Inhalte zu finden sind – sie generiert ausschließlich RSS-Feeds, bedient Medien usw. Wenn Sie die Domain aufrufen, werden Sie einfach zum Forum weitergeleitet.

Ich habe ein Verzeichnis, das SVG-artige Antworten auf GET-Anfragen bereitstellt. Zum Beispiel (nicht die echte URL): https://moversmindset.com/foo/bar.php

In meinem Discourse-Theme experimentiere ich mit Skriptcode (der später ein richtiges Plugin werden soll). Er ruft api.decorateCooked() für bestimmte DIVs auf, die ein data-custom-Attribut haben. Also mache ich innerhalb der von decorateCooked() aufgerufenen Funktion im Wesentlichen folgendes:

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

Ich möchte also das SVG abrufen und dann an das DOM anhängen. Aber meine Browserfehlerkonsole meldet:

Frage:

Bedeutet das, dass ich CORS entweder auf der Discourse-Installation oder auf der Apache/WordPress-Seite konfigurieren muss?

Ich habe https://moversmindset.com bereits in den CORS-Einstellungen von Discourse als erlaubt konfiguriert.

2 „Gefällt mir“

Ich glaube, es ist auf dieser Seite. Könntest du dir bitte, falls du es noch nicht getan hast, Access-Control-Allow-Origin header - HTTP | MDN ansehen und schauen, ob das dir irgendwelche Hinweise gibt?

4 „Gefällt mir“

winzige Schritte, aber JA!

Ich musste einen Access-Control-Allow-Origin-Header auf dem Apache/WP-Server hinzufügen. Das hat das JavaScript (von der Discourse-Plattform) zufrieden gestellt. Danke.

3 „Gefällt mir“

Ich habe langsam weiter herausgefunden, wie das geht. Um meine Frage zu stellen, ist viel Vorbereitung nötig:

SVG

Ich habe einen Webserver, der SVG generiert. Für diese Frage erzeugt er eine sehr einfache Test-SVG…

<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>

Es ist nur ein stilvoll aussehendes „Merge“-Symbol. Beachten Sie, dass es vier PATH-Elemente enthält.

Inline-Einbindung

Um die SVG in einen Beitrag einzubinden, verwende ich etwas JavaScript, das über mein Theme hinzugefügt wird.

Das Endziel wäre, ein richtiges Plugin zu erstellen. Aber ich versuche gerade nur, einen Proof-of-Concept zu bauen. Daher wird es einfach in den <head>-Bereich meiner Theme-Anpassung eingefügt:

<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('geladen!');
        $(target).children('path').each(function(){alert('hier ist ein path-Element');});
    },
}
$.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>

Woher…

var UMB = { ist einfach eine globale Variable, die mir erlaubt, riesige anonyme Funktionen überall zu vermeiden.

$.fn.umbdv = ist [was ich für] eine „Plugin“-Erweiterung von JQuery halte.

api.decorateCooked( ermöglicht es mir, den Beitrag zu manipulieren, bevor er an den Browser gesendet wird.

Aufruf

In einem Topic schreibe ich dann…

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

UMB.svgload('__URL_REDACTED__', this) wird für dieses DIV aufgerufen.

UMB.svgload() versteht korrekt den String /vtest, stellt eine URL zusammen und führt die AJAX-Anfrage aus. Es führt erfolgreich append(data) aus und boop – meine SVG ist inline…

Mein alert() innerhalb von UMB.svgload() wird dann wie erwartet ausgelöst. (Es ist offensichtlich ein Debug-Hack, oder? :))

Die Frage (endlich)

Ich habe ein NUR FÜR MITARBEITER bestimmtes Topic in meinem Discourse-Forum, in dem man dies live sehen kann. (Ich spreche mit Discourse-Mitarbeitern/Support, die als Admin-Benutzer in meine Installation eindringen können.)

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

Warum selektiert…

$(target).children('path').each(function(){alert('hier ist ein path-Element');});

…keines der PATH-Elemente?

Es passiert nichts – keine Fehler. Nichts.

Nächste Schritte

Wo ich hingehe, wenn dieser triviale alert()-Proof-of-Concept funktioniert…

Mir ist bewusst, dass der DOM-Abschnitt, mit dem ich „arbeite“, zum Zeitpunkt des Aufrufs von UMB.svgload() noch nicht mit dem tatsächlichen Dokument-DOM verbunden ist. Deshalb erwarte ich, dass $(target)… das ist, was ich brauche.

Letztendlich bin ich dabei, weitaus komplexere SVGs inline einzubinden, und ich werde komplexere JQuery-Selektoren benötigen. Ich möchte viele Elemente innerhalb von $(target) finden und Ereignisbehandlungsfunktionen (z. B. onclick) hinzufügen, die andere globale UMB.…-Funktionen aufrufen.

1 „Gefällt mir“

Iframes können die Navigation auf der obersten Ebene ändern, wenn du das möchtest.

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

3 „Gefällt mir“

Danke für den Tipp!

Aber ich bevorzuge SVG inline.

Aaaaaaanyway. Wochen später. Das funktioniert nicht.

Es scheint nicht möglich zu sein, die SVG-DOM-Elemente zu manipulieren, sobald sie im Hauptdokument inline eingebunden sind. Also kann ich nicht herausfinden, wie man Event-Trigger/Aktionen hinzufügt (was man als onclick etc. leicht tun könnte, wenn das SVG in einem iframe geladen wird)
((Das nicht Verwenden eines iFrames war mein ganzes Ziel.))

¯\_(ツ)_/¯

1 „Gefällt mir“

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