Safari not showing dynamic SVG content in accordion
Hi,
I am using an accordion and one of the sections contains SVG content
which is a mix of static and dynamic DOM elements. On Firefox this
works fine but in Safari I see the dynamic components of the SVG only
when first displayed. If I hide that accordion section and then
reopen it, only the static SVG components are displayed. I looked at
the Safari Activity window and it appears that the SVG source file is
reloaded every time I open that accordion section (at least when
loading a test file locally).
Is this a known issue with Safari or is jquery initiating that reload
with Safari? (I scanned the discussion list here but I can't find a
mention of this)
The only thing I can think to do about this is to catch accordion
events and reinitialize the dynamic parts of the SVG every time the
accordion section reopens. That sounds ugly and I'm not sure how to
distinguish that accordion section from the others when it reopens.
Test Environment:
Safari 4.0.3 on Mac OS 10.6.1 (shows problem)
Firefox 3.0.14 on Mac OS 10.6.1 (works fine)
Thanks for any suggestions.
Glenn
Details follow (test html with embedded javascript and svg file that
show the problem - sorry I spent no time on css to clean these up...)
Notes:
1) the svgContext code just ensures that the svg document is loaded
before the dynamic content is drawn (in this case, a single black
circle).
2) The black circle is created in the DOM by drawDynamicSvgContent()
once when the document is loaded.
---html start---
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://
www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
<html>
<head>
<title>Canada-USA Commodity Trade</title>
<meta http-equiv="Content-Type" content="text/html;
charset=iso-8859-1">
<link type="text/css" rel="stylesheet" href="css/jquery-ui-1.7.2/
smoothness/ui.all.css"/>
<script type="text/javascript" src="jquery-1.3.2.min.js"></script>
<script type="text/javascript" src="jquery-ui-1.7.2.min.js"></
script>
<script language="javascript" type="text/javascript">
<!-- Hide script from old browsers
function drawDynamicSvgContent(context) {
var d = context.getDoc();
var circle = d.createElementNS('http://www.w3.org/2000/svg',
'circle');
d.getElementById('testGroup').appendChild(circle);
circle.setAttribute('fill', 'black');
circle.setAttribute('stroke', 'black');
circle.setAttribute('cx', 49);
circle.setAttribute('cy', 100);
circle.setAttribute('r', 10);
}
function svgContext(opts) {
var loaded = false;
var doc = null;
var win = null;
var obj = document.getElementById(opts.svgObjId);
if (null == obj) {
alert('svgContext - failed to access document object node
('+opts.svgObjId+')');
return;
}
var entryPoints = {}; // define entryPoints BEFORE init() because
the callback returns entryPoints.
function getDoc() {
return(loaded ? doc : null);
}
entryPoints.getDoc = getDoc;
function getWin() {
return(loaded ? win : null);
}
entryPoints.getWin = getWin;
function getSvgObjId() {
return(loaded ? opts.svgObjId : null);
}
entryPoints.getSvgObjId = getSvgObjId;
function retry(pourquoi) {
setTimeout(function() { init(); }, 100);
}
function init() {
doc = null;
win = null;
if (obj.contentDocument != null) {
doc = obj.contentDocument;
} else if (null != obj.getSVGDocument) {
try {
doc = obj.getSVGDocument();
} catch (e) {
alert('svgContext - Failed to access SVG DOCUMENT - not
initialized ['+e.name+'/'+e.message+']');
return;
}
} else {
retry(1);
return;
}
if (doc && doc.defaultView) {
win = doc.defaultView;
} else if (obj.window) {
win = obj.window;
} else if (null != obj.getWindow) {
try {
win = obj.getWindow();
} catch (e) {
alert('svgContext - Failed to access SVG WINDOW - not
initialized ['+e.name+'/'+e.message+']');
return;
}
} else {
retry(2);
return;
}
if (null != doc && null != win) {
var found = true; // assume true
if (null != opts.elementIds) {
for (var i=0; i<opts.elementIds.length; i++) {
if (null == doc.getElementById(opts.elementIds[i])) {
found = false;
break;
}
}
}
if (found) {
loaded = true; // before callback so callback can access SVG
context elements
if (null != opts.callbackFn) {
opts.callbackFn(entryPoints);
}
} else {
retry(3);
}
} else {
retry(4);
}
}
init();
return(entryPoints);
}
$().ready(function() {
var context = svgContext({
svgObjId : 'svgObj',
elementIds : [
'background',
'testGroup'
],
callbackFn : function(c) { // c is the initialized svg context
drawDynamicSvgContent(c);
}
});
$('#accordion').accordion({ autoHeight: false });
});
// End hiding script from old browsers -->
</script>
</head>
<body>
<div id="accordion">
<a href="#">SVG Content (static and dynamic)</a>
<div id="svgContentDiv">
<object id="svgObj" type="image/svg+xml" data="test.svg"
width="100" height="150"></object>
</div>
<a href="#">Some Text</a>
<div id="textDiv">
Some test text...
</div>
</div>
</body>
</html>
----html end---
---svg start---
<?xml version="1.0" standalone="no"?>
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/
Graphics/SVG/1.1/DTD/svg11.dtd">
<svg width="100%" height="100%" version="1.1" viewBox="0 0 100 150"
xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/
xlink">
<g id="background">
<rect rx="5" x="1" y="1" width="98" height="148" fill="#c3d0dc"
stroke="none"/>
</g>
<text x="49" y="39" text-anchor="middle" font-size="10" font-
family="Arial">A circle should</text>
<text x="49" y="49" text-anchor="middle" font-size="10" font-
family="Arial">appear below.</text>
<g id="testGroup">
</g>
</svg>
---svg end---