Interactive SVG using <object>?

I’ve continued to slowly figure this out. This requires a lot of setup to ask my question:

SVG

I have a web server that generates SVG. For this question, it generates a very simple 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>

It’s just a fancy-looking “merge” sign. Note that it has four PATH elements.

Inlining

To get the SVG into a post, I’m using some javascript added via my theme.

The end-goal would be to make a proper plugin. But I’m just trying to build a proof-of-concept. So it’s simply pasted into the </head> section of my theme customization:

<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('loaded!');
        $(target).children('path').each(function(){alert('here is a 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>

Where…

var UMB = { is simply a global variable that avoids me having giant anonymous functions all over the place.

$.fn.umdv = is [what I think is called] a “plugin” extending JQuery.

api.decorateCooked( let’s me manipulate the post before it’s sent to the browser.

Incantation

In a topic, I then write…

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

UMB.svgload('__URL_REDACTED__', this) is called for that DIV.

UMB.svgload() correctly groks that /vtest string, composes a url and makes the AJAX request. It successfully does the append(data) and *boop* my SVG is inline…

My alert() inside UMB.svgload() then fires, just as expected. (It’s obviously a debug hack, right? :)

The question (finally)

I have a STAFF ONLY topic in my Discourse hosted forum where you can see this in action. (I’m talking to Discourse staff/support who can barge into my installation as Admin users.)

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

Why doesn’t…

$(target).children('path').each(function(){alert('here is a path element');});

…select any of the PATH elements?

It does nothing—no errors. Nothing.

Next

Where I’ll be going if I get this trivial alert() proof-of-concept working…

I’m aware that the chunk of the DOM I’m “working with” is not yet connected to the actual document DOM (at the point where UMB.svgload() is called.) That’s why I expect $(target)… to be what I need.

Ultimately, I’m inlining vastly more complex SVG and I’ll need to use more complex JQuery selectors. I want to find many elements inside $(target) and attach event handlers (onclick for example) that will be calling other UMB.… global functions.

1 Like