If you’re using Keith Wood’s great jQuery SVG plugin, you may find that the .css() function doesn’t work on SVG elements, as in:
var elem = $('#test');
if (elem.css('display') == 'none') {
elem.css('display', '');
}
will generate an error when CSS properties are written, but not when they are read. To address this, add this code to jquery.svgdom.js:
/* Support CSS on SVG nodes. */
var origCSS = $.fn.css;
$.fn.css = function(name, value, type) {
if (typeof name === 'string' && value === undefined) {
var val = origCSS.apply(this, [name, value, type]);
return (val && val.baseVal ? val.baseVal.valueAsString : val);
}
var options = name;
if (typeof name === 'string') {
options = {};
options[name] = value;
}
return this.each(function() {
if (isSVGElem(this)) {
for (var n in options) {
this.style[n] = (typeof options[n] == 'function' ? options[n]() : options[n]);
}
}
else {
origCSS.apply($(this), [name, value, type]);
}
});
}
I make no guarantees that it works on all platforms or browsers, but I mimicked the way Keith implemented .attr() for SVG elements, using the style attribute instead, so it hopefully has similar levels of portability. So far it works for me in Firefox 3.5 and Chrome 3.0. I'm going to guess that it works in Safari, because old code that used the style attribute worked there as well. No idea about IE, because my SVG doesn't load in that to begin with...
In addition to this, I needed to use the plugin to modify existing inline SVG, which seemed daunting given that the plugin normally created its own SVG canvas to render on. However, by hacking together a few calls to some of the internal functions I was able to get a jQuery SVG Wrapper with which I could call methods such as circle(), etc.:
var theDiv = $("#svg-container-div")[0];
$.svg._afterLoad(theDiv, $("#svg-root-element"), {});
var svgRoot = $.svg._getSVG($("#svg-container-div"));
var svgDoc = $("#svg-root-element");
svgRoot._svg = svgDoc[0];
svgRoot.circle(svgDoc[0], 270, 150, 25, {'id' : 'testcircle', 'fill' : "#ffffff", 'stroke' : '#ff0000'});
I'm not sure that this method of doing things is entirely acceptable as far as using the plugin correctly, but for me it successfully modified the DOM and I was able to reference the created elements without incident afterwards. At this point there was one last thing that I wanted to change about the plugin: when creating an SVG element I needed to specify a DOM element, not a jQuery wrapper. Usually this just means that the jQuery wrapper must be de-referenced to get the node, i.e. svgDoc[0] above, but I would get annoyed having to remember to add the array de-reference, so I modified jquery.svg.js again, this time changing the definition of _args, which handles argument decoding for all of the svg functions:
_args: function(values, names, optSettings) {
names.splice(0, 0, 'parent');
names.splice(names.length, 0, 'settings');
var args = {};
var offset = 0;
var vOffset = 0;
if (values[0] != null && (typeof values[0] != 'object' || !values[0].nodeName)) {
if (!(values[0].jquery && values[0][0].nodeName)) {
args['parent'] = null;
offset = 1;
vOffset = 0;
}
else {
args['parent'] = values[0][0];
offset = 1;
vOffset = 1;
}
}
for (var i = 0; i < values.length; i++) {
args[names[i + offset]] = values[i+vOffset];
}
if (optSettings) {
$.each(optSettings, function(i, value) {
if (typeof args[value] == 'object') {
args.settings = args[value];
args[value] = null;
}
});
}
return args;
},
This should provide the same behavior but allow the results of $(selector) to be supplied directly as the first argument to any SVG drawing methods (circle, rect, etc.), but only the first of these will be painted to, which is most useful when selecting an id, not a class. In addition the previous method of directly supplying an SVG DOM element will still work, as will falling back to using the default internal reference that is established when the SVG canvas is created.
Like
0 Responses
Stay in touch with the conversation, subscribe to the RSS feed for comments on this post.