javascriptjquerysvgexist-db

SVG built via javascript does not display in exist-db, but does as plain HTML


I have some Javascript that produces an inline svg object. It works fine standalone if cut-and-pasted from the eXist page and saved as straight HTML, but implemented within eXist the svg is built but does not display on the page. I'm not quite sure how to fix this, and would appreciate any suggestions. If I'm doing something wrong, I'd also appreciate it if you could let me know why it works in straight HTML but not in the eXist-db page.

Code on the page, rendered via xslt and calling to the javascript to build the dimensions of the svg viewbox and the path:

<div xmlns="http://www.w3.org/1999/xhtml" id="gathering_layout">
    <svg id="gathering_structure" width="100%" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 160 110">
        <path d="M 80 100 C 60 95, 40 100, 10 100, -20 100" stroke="#CCCCCC" stroke-width="1.5%" stroke-linecap="round" fill="transparent"></path>
    </svg>
</div>

The function in my javascript, simplified for display here:

function test_model()
{
    var svgNode = document.getElementById('gathering_structure');
            
            svgNode.setAttribute("width","100%");
            svgNode.setAttribute("xmlns","http://www.w3.org/2000/svg");
            svgNode.setAttribute("viewBox","0 0 160 110");
            
            var strokePath = document.createElement("path");
                        
            strokePath.setAttribute("d",'M 80 100 C 60 95, 40 100, 10 100, -20 100');
            strokePath.setAttribute("stroke","#CCCCCC");
            strokePath.setAttribute("stroke-width","1.5%");
            strokePath.setAttribute("stroke-linecap","round");
            strokePath.setAttribute("fill","transparent");
                        
            svgNode.appendChild(strokePath);
            
            
}

I suspect the page is being built before the Javascript has a chance to append its children, but my attempt to get around that by calling to the Javascript at the very end of the view through a jQuery $('document').ready() call doesn't seem to be resolving things. Javascript does work if it's fairly simple -- I have an .onclick() elsewhere on the page that works fine -- so it seems to be something specific to svg on eXist rather than a bad javascript implementation.


Solution

  • Like enxaneta says in the comments; It is all about the correct NameSpace

    Wrapped in a native JavaScript Web Component you can rule out any load order issues.
    As Web Components can be defined at any time and will "upgrade" existing/already parsed
    <svg-in-js> DOM elements.

    <svg-with-js color="green"></svg-with-js>
    <svg-with-js color="blue" ></svg-with-js>
    <svg-with-js color="red"  ></svg-with-js>
    
    <script>
      customElements.define("svg-with-js", class extends HTMLElement {
        connectedCallback() {
          let NameSpace = "http://www.w3.org/2000/svg";
          let svg = document.createElementNS( NameSpace , "svg");
          //svg.setAttribute("width", "100%"); // is default
          //svg.setAttribute("xmlns", NS ); // is default (in an HTML document)
          svg.setAttribute("viewBox", "0 0 160 10");
          let path = document.createElementNS( NameSpace , "path");
          path.setAttribute("d", 'M10 5H140V10');
          path.setAttribute("stroke", this.getAttribute("color"));
          path.setAttribute("stroke-width", "1.5%");
          path.setAttribute("stroke-linecap", "round");
          path.setAttribute("fill", "transparent");
          svg.append(path);
          this.append(svg);
        }
      });
    </script>