Oczywiście podane tutaj pliki są uproszczone, by łatwiej znaleźć problem.
Próbuję to zrobić na różne sposoby, ale nic nie wychodzi. Oba pliki mają znajdować się lokalnie na dysku użytkownika.
plik kolo.svg
<?xml version="1.0"?> <svg width="160" height="160" xmlns="http://www.w3.org/2000/svg" xlinkns="http://www.w3.org/1999/xlink"> <g> <ellipse ry="50" rx="50" id="koloSVG" cy="70" cx="70" stroke-width="5" stroke="#003300" fill="#66ff66"/> </g> <script> function klik1(){alert('klik1');} var e=document.getElementById('koloSVG'); //e.addEventListener("click",klik1,false); //(a) //e.addEventListener("click",top.klik2,false); //(b) //e.addEventListener("click",parent.klik2,false); //(c) </script> </svg>
plik proba.html
plik proba.js
function klik2(){ //funkcja, która ma być wywołana przy kliknięciu na koło s pliku .svg alert('klik2'); } function loadSVG() //próba załadowania pliku kolo.svg poprzez XMLHttpRequest { var SVGFile="kolo.svg"; var loadXML = new XMLHttpRequest; function handler() { if(loadXML.readyState == 4) { if (loadXML.status == 200) { var xmlString=loadXML.responseText; document.getElementById('mydiv').innerHTML=xmlString; } } } if (loadXML != null) { loadXML.open("GET", SVGFile, true); loadXML.onreadystatechange = handler; loadXML.send(); //(*) } } window.addEventListener("load",loadDocument,false); function loadDocument(){ //loadSVG(); (d) //addEventToSVG('embed'); // (e) //addEventToSVG('frame'); // (f) //addEventToSVG('object'); // (g) //addEventToSVG2('frame'); // (h) //addEventToSVG2('object'); // (i) //addEventToSVG2('embed'); // (j) } function addEventToSVG(elementID){ //próba dotarcia do elementu id="koloSVG" var svgdoc=document.getElementById(elementID).getSVGDocument(); //(**) var e=svgdoc.getElementById('koloSVG'); e.addEventListener("click",klik2,false); } function addEventToSVG2(elementID){ //kolejna próba dotarcia do elementu id="koloSVG" var svgdoc=document.getElementById(elementID).contentDocument(); //(***) var e=svgdoc.getElementById('koloSVG'); e.addEventListener("click",klik2,false); }
Jeśli w pliku kolo.svg odkomentuję odpowiednie linijki, to będzie następujące działanie:
( a ) : Wszystko ok, ale ja chcę wywołać funkcję spoza pliku svg, czyli klik2.
( b ) - ( c ) : Uncaught SecurityError: Blocked a frame with origin "null" from accessing a frame with origin "null". Protocols, domains, and ports must match. (3 razy, bo 3 obrazki) Linijka powodująca błąd to kolejno ( b ) i ( c ).
Jeśli w pliku proba.js odkomentuję odpowiednie linijki, to będzie następujące działanie:
( d - czyli chcę załadować obrazek poprzez XMLHttpRequest) : XMLHttpRequest cannot load file:///G:/.../kolo.svg. Cross origin requests are only supported for HTTP.
oraz: Uncaught NetworkError: A network error occurred.
( e ) - ( g ) : Uncaught SecurityError: Failed to execute 'getSVGDocument' on 'HTMLEmbedElement': Blocked a frame with origin "null" from accessing a frame with origin "null". Protocols, domains, and ports must match. Linijka powodująca błąd to (*)
( h ) - ( i ) : Uncaught SecurityError: Failed to read the 'contentDocument' property from 'HTMLIFrameElement': Blocked a frame with origin "null" from accessing a frame with origin "null". Protocols, domains, and ports must match. Linijka powodująca błąd to (**)
( j ) : Uncaught TypeError: Object #<HTMLEmbedElement> has no method 'contentDocument'. Linijka powodująca błąd to (**)
Odpalałem to na Google Chrome 33.0.1750.154 m
Nie mam pojęcia, jak to w takim razie zrobić. Szukałem tych błędów w google i zdaje się, że problem jest z tym, że plik svg jest umiejscowiony lokalnie (gdybym mógł dać link w postaci http://..., to by niby poszło), ale nie wiem, czy dobrze zrozumiałem i dlaczego to miałby być problem. Gdzieś znalazłem różne dywagacje na temat ,,same origin policy", ale przecież te dwa pliki są w jednym źródle.
Nie chodzi mi też o to, by w pliku svg zasysać plik proba.js, bo kliknięcie musi operować na danych, które są zewnętrzne wobec pliku svg.