karlitos
karlitos

Reputation: 1656

Is it possible to set custom attributes of SVG objects as number and not as string?

I am assigning artificial attributes to a SVG-G element (SVG group object). I move the group with its content with SVG transformations and I store the x/y coordinates of the group and its width/height in those attributes.

I am using the D3 Javascript library and the call :

embeddedElemContainer = nodeBoxContainer.append('svg:g')
    .attr('x', x)
    .attr('y', y)
    .attr('width', width)
    .attr('height', height)

results in following object :

<g transform="translate(13.585786437626904,31.585786437626904)" x="13.585786437626904" y="31.585786437626904" width="43.00000000000001" height="0"></g>

This is Ok, the only ting bothering me is the fact, that the attribute values are stored as string. If I want to use them for some computation, I am forced to cast.

parseInt(@embeddedElemContainer.attr('x'))

Is there a way to store those values directly as integer/double ?

Upvotes: 8

Views: 10258

Answers (2)

Steve P
Steve P

Reputation: 19397

The normal approach in D3 is to have lists of data that are bound to nodes. See the data portion of the Selection API. D3 puts this in the __data__ property of the DOM nodes that it creates/modifies. Internally D3 pulls out that property and passes it as a parameter to various functions, but you can certainly access it yourself directly.

It's also possible to associate an arbitrary data structure to a single node via the Datum method.

Without the rest of the context it's hard to say, but below is a modified version of what I think you are trying to do:

var vis = d3.select("body").append("svg").attr("width", 400).attr("height", 300);

var groupData = {x: 100, y:100, height: 50, width: 50, theanswer : 42, thecolor: "blue", somedouble: 45.1651654 };

var embeddedElemContainer = vis.append('svg:g')
    .datum( groupData )
    .attr( 'id', 'mygroup' )
    .attr( 'x', function(d) { return d.x; } )
    .attr( 'y', function(d) { return d.y; } )
    .attr( 'height', function(d) { return d.height; } )
    .attr( 'width', function(d) { return d.width; } )

// the regular DOM way:
console.log(document.getElementById('mygroup').__data__)

// the D3 way:
console.log( d3.select('#mygroup').datum() );

Both console.log statements output:

height: 50
somedouble: 45.1651654
theanswer: 42
thecolor: "blue"
width: 50
x: 100
y: 100

Upvotes: 7

Ezekiel Victor
Ezekiel Victor

Reputation: 3876

You could override d3's attr function to sniff out numbers and do the parseInt for you. That might present compatibility problems later, so maybe it would be better to create a new attrInt function, for example:

d3.selection.prototype.attrInt = function(name, value) {
  if(arguments.length == 1) {
    return parseInt(this.attr(name));
  } else {
    return this.attr(name, value);
  }
};

Disclaimer: I don't have experience with d3 so I'm not sure if that is the correct prototype to attach to; I just picked that up from glancing at the source. :)

Upvotes: 0

Related Questions