ngr900
ngr900

Reputation: 492

Accessing .SVG file's contentDocument from file input - cross frame issue on Chrome

I'm trying to access an SVG's contentDocument (and change fill colors for specific paths, but that I don't have a problem with) via JavaScript. The SVG comes from user input. Whenever I try to access the contentDocument I get the error:

(index):41 Uncaught DOMException: Failed to read the 'contentDocument' property from 'HTMLObjectElement': Blocked a frame with origin "http://localhost" from accessing a cross-origin frame.

As you can see I'm using a local server the but results are the same when accessing the file locally. Here's my code:

document.getElementById("input-image").addEventListener("load", function () {
    console.log("image loaded");
    let svgDoc = this.contentDocument;
}, false);

var src = document.getElementById("file-input");
var target = document.getElementById("input-image");
var fr = new FileReader();
fr.onload = function (e) {
    target.data = this.result;
};
src.addEventListener("change", function () {
    fr.readAsDataURL(src.files[0]);
});

And the HTML:

<object data="" type="image/svg+xml" id="input-image" width="100%" height="100%"></object>
<input id="file-input" type="file" accept=".svg" />

And here's a jsFiddle.

I know this can be fixed by actually uploading the file to the server and then accessing it locally (as in, on the server) but is there a way to get this to work without introducting server side scripting and uploads?

Upvotes: 0

Views: 1158

Answers (1)

traktor
traktor

Reputation: 19301

A suggestion for an alternative method of loading a local svg file into the DOM is to

  1. read the file as text (let's assume it's ASCII or utf-8 encoding) after selection.
  2. write the content to an iframe object's document
  3. pick up the svgElement from within the iframe.

Concept code

This code uses an example string instead of performing step 1.

    let svgTest = function() {

    let iframe = document.createElement("iframe");
    document.body.appendChild(iframe); // insert it in the document, somewhere

    // normally read the svg as text, but here just use an example from
    // https://developer.mozilla.org/en-US/docs/Web/SVG/Tutorial/Getting_Started

    let result = `
        <svg version="1.1"
             baseProfile="full"
             width="300" height="200"
             xmlns="http://www.w3.org/2000/svg">
          <rect width="100%" height="100%" fill="red" />
          <circle cx="150" cy="100" r="80" fill="green" />
          <text x="150" y="125" font-size="60" text-anchor="middle" fill="white">SVG</text>
        </svg>
    `;

    // write it to the iframe and close the document
    let doc = iframe.contentWindow.document;
    doc.write(result)
    doc.close();

    // get the svgElement
    let svgElement = doc.getElementsByTagName("svg")[0];
    let svgRect = svgElement.getBoundingClientRect();

    // set iframe size (may need adjustment)
    doc.body.style.margin = "0";
    iframe.width = svgRect.width;
    iframe.height = svgRect.height;

    }; //end of svgTest
    svgTest();

Upvotes: 2

Related Questions