views:

388

answers:

2

Hi,

I'm trying to access some custom data emitted into an SVG document by Visio 2007. I've used jquery.svg.js by Keith Wood. Unfortunately, even with the svgdom extension, I am not able to get to the shape I'm after to animate it.

Here's what the SVG looks like:

...
<g id="group4-6" transform="translate(30.7955,-30.7955)" v:mID="4" v:groupContext="group" v:layerMember="0;1">
<v:custProps>
 <v:cp id="helloWorld" v:nameU="AgentName" v:lbl="AgentName" v:type="0" v:langID="3081" v:val="VT4(Bob)"/>
</v:custProps>
<v:userDefs>
 <v:ud v:nameU="Show" v:val="VT0(1):5"/>
</v:userDefs>
<title>Sheet.4</title>
<g id="shape5-7" ...

I'm trying to access the group 'shape5-7', by navigating to it relative to the custom property containing 'Bob'. i.e. I want to animate the shape with Bob attached to it. I tried the following, but I got nothing back.

$("v:cp[v:val*=Bob]:parent:parent > g:first", desk)
    .each(function(i, item) { Log('found something'); })
        .animate({ svgFill: 'red' }, 2000)
        .animate({ svgFill: 'white' }, 2000);

I've tried it with and without the XML namespace prefixes. And I know that the shape can be found in the SVG DOM, since $("#shape5-7") finds the right shape and animates nicely. It looks like as soon as I try to access non-SVG elements in the SVG DOM I get failures. Am I asking too much of the jquery.svg.js library here, or am I just missing something?

I am using the modified version of jquery with the 1.4.2 version of jquery.svg.js running in Google Chrome 2.0.172.43. I'm in the proof-of-concept phase at the moment, so if you can show me how to do the same task using the Raphael or ProcessingJS libraries (or any other), I'd be willing to switch. JQuery-centric solutions are my preference though.

Thanks

Andrew Matthews

+1  A: 

It looks like you have at least two logical errors in your selector. According to your sample, the element g is not a child of v:cp and thus the > g:first portion at the end of your selector will not be matched. Also given the structure of your SVG I'm not sure why you need :parent:parent in the selector (plus specifying :parent more than once is redundant). The tag v:cp is self-closing and contains no child elements so the psuedo :parent will cause this portion not to match as well. Try this code:

$('v:cp[v:val*=Bob]', desk)
    .parent()
    .nextAll('g:first')
    .each(function(i, item) { Log('found something'); })
    .animate({ svgFill: 'red' }, 2000)
    .animate({ svgFill: 'white' }, 2000);
Marve
A: 

Hi Marve,

Thanks for the response. Unfortunately that doesn't work. Here's what I was hoping my jquery selectors would do:

v:cp:parent:parent refers to the parent of the parent of v:cp (or the enclosing g)

> g:first refers to the first g child of the parent g.

As far as I could tell, my original selectors meant the same as your example (if I included an extra .parent() call.

I did find an answer eventually. It animates the desired group's parent (which in my case is enough):

$('cp', desk)
    .filter(function(index) {
        return $(this).attr("v:val") == "VT4(Bob)";
    })
    .parent()
    .parent()
    .each(function(i, item) { Log('found something'); })
    .animate({ svgFill: 'red' }, 2000)
    .animate({ svgFill: 'white' }, 2000);

I was unable to navigate back down to the child group shape5-7, that I was after, but I'm confident that that manual traverse will work, where the selectors didn't.

Thanks for the help.

Andrew

Andrew Matthews
Glad to hear that you found a solution. Just so you know, the `:parent` pseudo selector matches elements that are parents. It doesn't navigate to the parent of the selected element ala `.parent()`. See the docs for [:parent](http://docs.jquery.com/Selectors/parent) vs [parent()](http://docs.jquery.com/Traversing/parent).
Marve
O.I.C. I did play about with things like :parent:first to give the first parent. Clearly a pointless exercise! I guess that would also explain why use of g:parent:parent > g:first animated everything!
Andrew Matthews