SVG interativo usando

Estou tentando incorporar uma visualização de dados interativa baseada em SVG. Estou gerando o SVG a partir de um sistema separado (mas ainda no mesmo domínio de segundo nível que minha instalação do Discourse). Tentei importar o SVG usando uma tag OBJECT…

<object type="image/svg+xml" data="full_URL_to_foo.svg">
(aparece se o carregamento do objeto falhar)
</object>

Se eu simplesmente importar esse SVG (que é gerado dinamicamente a cada vez) com uma tag IMG, a visualização aparece, mas (como eu esperava) não há interatividade…

<img src="full_URL_to_foo.svg">

Alguma ideia ou dica sobre onde posso buscar mais informações sobre SVGs e o Discourse? :slight_smile:

1 curtida

A maneira mais fácil de fazer isso funcionar é usando um iframe. Adicione o domínio SVG à configuração do site allowed_iframes e inclua-o em uma postagem usando HTML.

5 curtidas

Hmmmm, então esse é o jeito fácil.

Existe um jeito difícil que eu possa tentar?

…porque eu quero ter links no SVG que alterem a localização do navegador. Links no SVG, dentro de um IFRAME, mudam o que é exibido no IFRAME…

Suspeito que incorporar j/s no tópico, logo antes do IFRAME, e chamar uma função j/s na página no onclick do SVG… isso também não vai funcionar.

Estou fazendo sentido? Deveria estar adicionando algum código j/s simples, à la Mitigate XSS Attacks with Content Security Policy, e depois tentar chamar isso de dentro do SVG no IFRAME? …ou “dentro do IFRAME” é uma fortaleza à prova de tudo?

Talvez eu devesse perguntar como posso incluir o SVG diretamente na página? Depois usar o j/s injetado pelo theme-component para interagir com meu outro servidor e atualizar dinamicamente o SVG?

Por favor, um soco na cara (dica) :slight_smile:

2 curtidas

Colocar o SVG na postagem marcada por um div especial envolvente e usar um tema-componente para transformá-lo em uma tag object usando o callback decorateCooked pode funcionar. Consulte o Guia do Desenvolvedor para Temas do Discourse

3 curtidas

…caso alguém esteja acompanhando, decorateCooked() está obsoleto. Estou testando o decorateCookedElement() no lugar.

1 curtida

Estou com um problema relacionado ao CORS/Access-Control-Allow-Origin. Não estou familiarizado com como isso funciona…

Tenho dois sites: o site hospedado do Discourse (forum.moversmindset.com) e um site WordPress baseado no Apache (moversmindset.com). Note que não há conteúdo óbvio no site WordPress — ele apenas gera feeds RSS, serve mídia, etc. Se você acessar o domínio, ele apenas redirecionará para o fórum.

Tenho um diretório que responde a solicitações GET com arquivos do tipo SVG. Por exemplo (não é a URL real): https://moversmindset.com/foo/bar.php

No meu tema do Discourse, estou experimentando com código de script (que eventualmente será um plugin adequado). Ele chama api.decorateCooked() em DIVs específicas que possuem algum atributo data-custom adicionado. Então, dentro da função chamada por decorateCooked(), estou fazendo algo como:

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

Quero recuperar o SVG e, em seguida, anexá-lo ao DOM. Mas o console de erros do meu navegador diz:

Pergunta:

Isso significa que preciso configurar o CORS na instalação do Discourse ou no Apache/WordPress?

Eu tenho https://moversmindset.com configurado como permitido no CORS no Discourse.

2 curtidas

Eu acho que está deste lado. Você já conferiu Access-Control-Allow-Origin header - HTTP | MDN e viu se isso te dá alguma pista?

4 curtidas

passinhos minúsculos, mas SIM!

Tive que adicionar um cabeçalho Access-Control-Allow-Origin no servidor apache/WP. Isso deixou o j/s (proveniente da plataforma Discourse) feliz. Obrigado.

3 curtidas

Continuei a descobrir isso aos poucos. Isso requer bastante configuração para fazer minha pergunta:

SVG

Tenho um servidor web que gera SVG. Para esta pergunta, ele gera um SVG de teste muito simples…

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

É apenas um sinal de “mesclar” com aparência elaborada. Note que ele possui quatro elementos PATH.

Inline

Para colocar o SVG em uma postagem, estou usando algum JavaScript adicionado via meu tema.

O objetivo final seria criar um plugin adequado. Mas estou apenas tentando construir um conceito de prova. Então, ele é simplesmente colado na seção <head> da personalização do meu tema:

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

Onde…

var UMB = { é simplesmente uma variável global que me evita ter funções anônimas gigantes por toda parte.

$.fn.umbdv = é [o que eu acho que se chama] um “plugin” que estende o JQuery.

api.decorateCooked( me permite manipular a postagem antes que ela seja enviada ao navegador.

Encantação

Em um tópico, eu então escrevo…

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

UMB.svgload('__URL_REDACTED__', this) é chamado para aquele DIV.

UMB.svgload() entende corretamente a string /vtest, compõe uma URL e faz a solicitação AJAX. Ele executa com sucesso o append(data) e boop, meu SVG fica inline…

Meu alert() dentro de UMB.svgload() então dispara, exatamente como esperado. (Obviamente é uma gambiarra de debug, certo? :))

A pergunta (finalmente)

Tenho um tópico APENAS PARA FUNCIONÁRIOS no meu fórum hospedado no Discourse onde você pode ver isso em ação. (Estou falando com a equipe de suporte do Discourse que pode entrar na minha instalação como usuários Admin.)

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

Por que…

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

…não seleciona nenhum dos elementos PATH?

Não faz nada — nenhum erro. Nada.

Próximo

Para onde irei se conseguir fazer esse trivial alert() de conceito de prova funcionar…

Estou ciente de que o fragmento do DOM com o qual estou “trabalhando” ainda não está conectado ao DOM real do documento (no momento em que UMB.svgload() é chamado). É por isso que espero que $(target)… seja o que eu preciso.

No final das contas, estou inlineando SVGs muito mais complexos e precisarei usar seletores JQuery mais complexos. Quero encontrar muitos elementos dentro de $(target) e anexar manipuladores de eventos (onclick, por exemplo) que chamarão outras funções globais UMB.….

1 curtida

IFrames podem alterar a navegação de nível superior, se você quiser.

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

3 curtidas

Obrigado pela dica!

Mas definitivamente prefiro o SVG inline agora.

De qualquer forma. Semanas depois. Isso não funciona.

Parece impossível manipular os elementos do DOM do SVG depois que ele é incorporado ao documento principal. Então, não consigo descobrir como adicionar gatilhos de eventos ou ações (o que seria fácil fazer com onclick e afins se o SVG fosse carregado em um iframe).

{(não usar um iframe era todo o meu objetivo.)}

¯\_(ツ)_/¯

1 curtida

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