The problem space:
I have an SVG map that I embed inline to html using JQUERY Ajax. Then I use java script to address many elements in the svg object to change attributes and add event listeners based on data series. The data and the maps are interactive. Users can change state over many permutations.
I am also using JQUERY UI 1.10.3 Tabs
There are numerous categories. Therefore depending on the presentation there could be multiple copies of the svg map on the same Tab and many different Tabs having the same svg map.
Each copy of the svg document has the same element IDs. The problem I am experiencing is that the element IDs are conflicting with each other in the HTML DOM. So that the only elements that are addressable are the elements from the svg object that occurs first in the HTML document.
My question is:
Do I need to make the elements IDs unique for each instance of the svg object? Or is there a way to set scope and context to the svg object in the HTML DOM?
Example:
Each containing div has a unique ID that I use to insert the svg document and retrieve the SVG document.
<div id="svgMap_div_1" class="cIG" style="height: 500px; width: 750px"></div>
Code used to load the svg document that is received from ajax (mimeType = "image/svg+xml"):
document.getElementById('svgMap_div_1').appendChild(svgXMLObject.documentElement)
Code used to retrieve the svg document. The declaration for svgDoc is local to the function it is implemented in and is unique.
var svgDoc = document.getElementById('svgMap_div_1').ownerDocument;
Code used to update the individual elements. When the identical svg objects (child elements have the same IDs) are in the same HTML DOM, then this javascript will always address the svg object that occurs first in the HTML DOM even if it is retrieved from a discrete div for example id='svgMap_div_2'.
var svgElem = svgDoc.getElementById('elemID');
svgElem.setAttribute("fill", '#0000FF');
I believe that the root of the problem is that svgDoc is retrieved using ownerDocument. Rather than create a discrete object with scope and context, it reaches through to the entire DOM so that the DOM is the context. See the code reference from the IDE:
HTMLDocument Node.ownerDocument
Property ownerDocument .html
See Also:
Document
Since:
Standard ECMA-262 3rd. Edition
Level 2 Document Object Model Core Definition.
@type
Document
I can develop a working algorithm to make all of the ids unique if I have to but I sure would like to find a better way. I have experimented with other methods and properties to get a working svg document object but none of these are working for me.
Below is a working example to demonstrate what happens when both svg objects are in different div on the same page. All four binations change the color of the first rectangle. If you change the ID for the rect in the second object to 'box-b' and address it accordingly ('bbox_div', 'box-b'), then both rectangles are operated on independent from one another.
<script type='text/javascript'>
function colorBox(divID, svgElem, colorHex) {
/* DOM This is the original solution that did not work !!!*/
// var svgDoc = document.getElementById(divID).ownerDocument.
// var svgBox = svgDoc.getElementById(svgElem);
// svgBox.setAttribute("fill", colorHex);
/* querySelector */
// document.querySelector("#"+divID + " ."+svgElem).setAttribute("fill", colorHex);
/* jquery div */
// var svgBox = $('#'+divID+' svg').find('#'+svgElem);
// svgBox.css("fill", colorHex);
/* jquery class */
$('#'+divID+' svg').find('.'+svgElem).css("fill", colorHex);
}
</script>
<div style="height: 100px; width: 100px">
<a href="#" onclick="colorBox('abox_div', 'box-a', '#FF0000');return false;">Box A Red</a><br>
<a href="#" onclick="colorBox('abox_div', 'box-a', '#0000FF');return false;">Box A Blue</a><br>
<a href="#" onclick="colorBox('bbox_div', 'box-a', '#FF0000');return false;">Box B Red</a><br>
<a href="#" onclick="colorBox('bbox_div', 'box-a', '#0000FF');return false;">Box B Blue</a><br -->
</div>
<div id="abox_div" style="height: 100px; width: 100px">
<svg xmlns=""
width="0.990919in"
height="0.597218in"
viewBox="0 0 71.3461 42.9997">
<style type="text/css">
<![CDATA[
.allboxes {fill:#00FF00}
]]>
</style>
<g class="box-a allboxes" transform="translate(0.24,-0.24)" fill="#e8eef7">
<rect x="0" y="0.48" width="70.8661" height="42.5197" ><title>Box A</title></rect>
</g>
</svg>
</div>
<div id="bbox_div" style="height: 100px; width: 100px">
<svg xmlns=""
width="0.990919in"
height="0.597218in"
viewBox="0 0 71.3461 42.9997">
<g class="box-a allboxes" transform="translate(0.24,-0.24)" fill="#e8eef7">
<rect x="0" y="0.48" width="70.8661" height="42.5197" ><title>Box B</title></rect>
</g>
</svg>
</div>
The problem space:
I have an SVG map that I embed inline to html using JQUERY Ajax. Then I use java script to address many elements in the svg object to change attributes and add event listeners based on data series. The data and the maps are interactive. Users can change state over many permutations.
I am also using JQUERY UI 1.10.3 Tabs
There are numerous categories. Therefore depending on the presentation there could be multiple copies of the svg map on the same Tab and many different Tabs having the same svg map.
Each copy of the svg document has the same element IDs. The problem I am experiencing is that the element IDs are conflicting with each other in the HTML DOM. So that the only elements that are addressable are the elements from the svg object that occurs first in the HTML document.
My question is:
Do I need to make the elements IDs unique for each instance of the svg object? Or is there a way to set scope and context to the svg object in the HTML DOM?
Example:
Each containing div has a unique ID that I use to insert the svg document and retrieve the SVG document.
<div id="svgMap_div_1" class="cIG" style="height: 500px; width: 750px"></div>
Code used to load the svg document that is received from ajax (mimeType = "image/svg+xml"):
document.getElementById('svgMap_div_1').appendChild(svgXMLObject.documentElement)
Code used to retrieve the svg document. The declaration for svgDoc is local to the function it is implemented in and is unique.
var svgDoc = document.getElementById('svgMap_div_1').ownerDocument;
Code used to update the individual elements. When the identical svg objects (child elements have the same IDs) are in the same HTML DOM, then this javascript will always address the svg object that occurs first in the HTML DOM even if it is retrieved from a discrete div for example id='svgMap_div_2'.
var svgElem = svgDoc.getElementById('elemID');
svgElem.setAttribute("fill", '#0000FF');
I believe that the root of the problem is that svgDoc is retrieved using ownerDocument. Rather than create a discrete object with scope and context, it reaches through to the entire DOM so that the DOM is the context. See the code reference from the IDE:
HTMLDocument Node.ownerDocument
Property ownerDocument http://www.w3/TR/2000/REC-DOM-Level-2-Core-20001113/ecma-script-binding.html
See Also:
Document
Since:
Standard ECMA-262 3rd. Edition
Level 2 Document Object Model Core Definition.
@type
Document
I can develop a working algorithm to make all of the ids unique if I have to but I sure would like to find a better way. I have experimented with other methods and properties to get a working svg document object but none of these are working for me.
Below is a working example to demonstrate what happens when both svg objects are in different div on the same page. All four binations change the color of the first rectangle. If you change the ID for the rect in the second object to 'box-b' and address it accordingly ('bbox_div', 'box-b'), then both rectangles are operated on independent from one another.
<script type='text/javascript'>
function colorBox(divID, svgElem, colorHex) {
/* DOM This is the original solution that did not work !!!*/
// var svgDoc = document.getElementById(divID).ownerDocument.
// var svgBox = svgDoc.getElementById(svgElem);
// svgBox.setAttribute("fill", colorHex);
/* querySelector */
// document.querySelector("#"+divID + " ."+svgElem).setAttribute("fill", colorHex);
/* jquery div */
// var svgBox = $('#'+divID+' svg').find('#'+svgElem);
// svgBox.css("fill", colorHex);
/* jquery class */
$('#'+divID+' svg').find('.'+svgElem).css("fill", colorHex);
}
</script>
<div style="height: 100px; width: 100px">
<a href="#" onclick="colorBox('abox_div', 'box-a', '#FF0000');return false;">Box A Red</a><br>
<a href="#" onclick="colorBox('abox_div', 'box-a', '#0000FF');return false;">Box A Blue</a><br>
<a href="#" onclick="colorBox('bbox_div', 'box-a', '#FF0000');return false;">Box B Red</a><br>
<a href="#" onclick="colorBox('bbox_div', 'box-a', '#0000FF');return false;">Box B Blue</a><br -->
</div>
<div id="abox_div" style="height: 100px; width: 100px">
<svg xmlns="http://www.w3/2000/svg"
width="0.990919in"
height="0.597218in"
viewBox="0 0 71.3461 42.9997">
<style type="text/css">
<![CDATA[
.allboxes {fill:#00FF00}
]]>
</style>
<g class="box-a allboxes" transform="translate(0.24,-0.24)" fill="#e8eef7">
<rect x="0" y="0.48" width="70.8661" height="42.5197" ><title>Box A</title></rect>
</g>
</svg>
</div>
<div id="bbox_div" style="height: 100px; width: 100px">
<svg xmlns="http://www.w3/2000/svg"
width="0.990919in"
height="0.597218in"
viewBox="0 0 71.3461 42.9997">
<g class="box-a allboxes" transform="translate(0.24,-0.24)" fill="#e8eef7">
<rect x="0" y="0.48" width="70.8661" height="42.5197" ><title>Box B</title></rect>
</g>
</svg>
</div>
Share
Improve this question
edited Sep 6, 2013 at 19:51
Threadid
asked Sep 6, 2013 at 3:11
ThreadidThreadid
7601 gold badge7 silver badges27 bronze badges
1
- Final solution that eliminates conflicting ids employs JQUERY .class selector and has multiple classes for unique and mon style attribute assignments. See updated working example in original question. – Threadid Commented Sep 6, 2013 at 19:40
2 Answers
Reset to default 3I believe it's strictly speaking invalid HTML if you have duplicate IDs. I'd suggest using some other mechanism of identifying the elements, either using classes instead of IDs or data-
attributes. Then you could move from .getElemntById()
to either .querySelector()
(try on JS Bin):
<html>
<head>
<title></title>
</head>
<body>
<div id="div1">
<svg xmlns="http://www.w3/2000/svg" width="50px" height="50px">
<rect class="rect1" width="50px" height="50px"/>
</svg>
</div>
<div id="div2">
<svg xmlns="http://www.w3/2000/svg" width="50px" height="50px">
<rect class="rect1" width="50px" height="50px"/>
</svg>
</div>
<script type="text/javascript">
document.querySelector("#div1 .rect1").setAttribute("fill","red");
document.querySelector("#div2 .rect1").setAttribute("fill","green");
</script>
</body>
</html>
or .getElementsByClassName()
(try on JS Bin):
<html>
<head>
<title></title>
</head>
<body>
<div id="div1">
<svg xmlns="http://www.w3/2000/svg" width="50px" height="50px">
<rect class="rect1" width="50px" height="50px"/>
</svg>
</div>
<div id="div2">
<svg xmlns="http://www.w3/2000/svg" width="50px" height="50px">
<rect class="rect1" width="50px" height="50px"/>
</svg>
</div>
<script type="text/javascript">
document.getElementById("div1").getElementsByClassName("rect1")[0].setAttribute("fill","red");
document.getElementById("div2").getElementsByClassName("rect1")[0].setAttribute("fill","green");
</script>
</body>
</html>
Probably .querySelector()
would also work if you leave the ID attributes as they are, like:
document.querySelector("#div1 [id=rect1]")
but I'd still suggest using data-
attributes as this avoids any potential ID pitfalls.
Since you are already using jQuery, you can use jQuery's selectors, which don't care about duplicate ids.
function colorBox(divID, svgElem, colorHex) {
var svgBox = $('#'+divID+' svg').find('#'+svgElem);
svgBox.css("fill", colorHex);
}
Demo here: http://jsfiddle/w9KA3/1/
发布者:admin,转转请注明出处:http://www.yc00.com/questions/1744891898a4599464.html
评论列表(0条)