Search code examples
ember.jssvgember-clihtml5-historysvg-filters

Broken SVG Filter id link when using History API with Ember CLI


I'm generating SVG visualizations with D3.js in an Ember-cli Application. The SVGs utilize filters and markers that are accessed through the id attribute:

<svg>
    <defs>
        <filter id="filterId">
            ...
        </filter>
    </defs>
    <g>
        <g class="nodes">
            <circle filter="url(#filterId)" ...></circle>
        </g>
    </g>
</svg>

This works fine on the index page (url: ), but is broken when traversing to other routes (ex: \otherRoute). It will work on the other route if I change circle to

<circle filter="url(./otherRoute#filterId)" ...></circle>

But it then breaks on the index and all other pages.

I can fix it by manually prepending the url to #filterId when building the svg elements on each route or by using the hash locationType in ember-cli (which uses /#routeUrl instead of /routeUrl), but was wondering if there was a generic way to automatically link to the current url so I can still use the history API?


Solution

  • Ran into the same issue with a clip-path attribute after moving from hash URLs to the history API. The original implementation was an SVG element like:

    <svg>
      <clipPath id="clip-path-ember1919">
        <path d="..."></path>
      </clipPath>
      <g clip-path="url(#clip-path-ember1919)">
        <rect ...></rect>
      </g>
    </svg>
    

    This had been achieved with a simple D3 append:

    var emberId = this.$().attr('id');
    svg.append('g')
        .attr('clip-path', "url(#clip-path-#{emberId})");
    

    To solve the issues raised by the history API, I used the same solution you described (prepending the URL), but by using window.location.pathname:

    var emberId = this.$().attr('id');
    var relPath = 
    svg.append('g')
          .attr('clip-path', "url(." + window.location.pathname + "#clip-path-" + emberId + ")");
    

    This creates an SVG element much like the circle element referenced in the question.

    <svg>
      <clipPath id="clip-path-ember1919">
        <path d="..."></path>
      </clipPath>
      <g clip-path="url(./path/to/page#clip-path-ember1919)">
        <rect ...></rect>
      </g>
    </svg>
    

    Long way of saying: similar solution to the original poster, just using window.location.pathname to generate the prepended URL.