javascripthtmlsvgsafariforeignobject

Safari fails to replace SVG element with: NoModificationAllowedError: The object can not be modified


I would like to replace all my SVG’s <rect> elements with foreignObject which does work fine FireFox and Chromium-based Browser but fails in Safari.

MWE:

HTML/SVG

<!DOCTYPE html>
<html lang="en">
  <body>
    <svg>
      <rect id="rect1" width="100" height="100" />
    </svg>
  </body>
</html>

JavaScript

let myRect = document.getElementById("rect1")
myRect.outerHTML = myRect.outerHTML.replace("<rect", "<foreignObject").replace("</rect>", "</foreignObject>")

Safari fails with: NoModificationAllowedError: The object can not be modified.

I know the issue is due to outerHTML is on the HTML namespace while SVG is on XML, yet is there a way to make this work in SVG?

Thanks for any insight into this issue.


Solution

  • Replacing strings is very error prone

    Replace the element .. after copying attributes

    <svg id=SVG>
      <rect id="rect1" width="100" height="100" />
      <g>    
        <rect id="rect2" width="100" height="100" />
      </g>
    </svg>
    
    <script>
      let svg = SVG;
      svg.querySelectorAll("rect").forEach(rect => {
        let obj = document.createElementNS("http://www.w3.org/2000/svg", "foreignObject");
        [...rect.attributes].map(  ({name,value}) => obj.setAttribute(name, value)  );
        rect.replaceWith(obj);
      });
      console.log(SVG.outerHTML);
    </script>

    PS unreadable rect.parentNode.replaceChild(obj, rect); for IE11