Reputation: 1867
I am trying to make a reusable chart with d3.js. The codes are working, but they are very redundant.
I am trying to simplify the code below:
function myChart(){
// default properties
var svgWidth = 1000,
svgHeight = 250;
function chart(selection){
// do something with the previous properties ....
}
// define setter-getter functions
chart.svgWidth = function(_){
if(!arguments.length) return svgWidth;
svgWidth = _;
return chart;
};
chart.svgHeight = function(_){
if(!arguments.length) return svgHeight;
svgHeight = _;
return chart;
};
return chart;
}
As you can see, all the setter-getter functions are very similar. If there are many properties to be set, say 10, then the setter-getter functions will be stacked very long.
So is anybody able to simplify it?
Upvotes: 1
Views: 380
Reputation: 102198
I believe that this getSet.js function is exactly what you want: https://gist.github.com/gneatgeek/5892586.
According to its creator, it can:
Dynamically create getter/setter functions for D3 components
As link-only answers are not recommended at S.O. (since the link can change or become unreachable) here is a brief explanation.
This is the said function:
function getSet(option, component) {
return function(_) {
if (!arguments.length) {
return this[option];
}
this[option] = _;
return component;
};
}
Let's see how to use it. First, you'll have store your variables in an object (which is one of the drawbacks of the function, see link above), like this:
var opts = {
width: 200,
height: 50,
color: '#000'
};
After that, you use this for...in
loop:
for (var key in opts) {
chart[key] = getSet(key, chart).bind(opts);
}
That way, you can dynamically generate your setter/getters.
Here is a demo, using the getters:
function getSet(option, component) {
return function(_) {
if (!arguments.length) {
return this[option];
}
this[option] = _;
return component;
};
}
function chart() {
// do something
};
var opts = {
width: 200,
height: 50,
color: '#000'
};
for (var key in opts) {
chart[key] = getSet(key, chart).bind(opts);
}
//using the getters
console.log(chart.height())
console.log(chart.width())
console.log(chart.color())
<script src="https://d3js.org/d3.v4.min.js"></script>
Now let's set some values using the setters and after that get them using the getters:
function getSet(option, component) {
return function(_) {
if (!arguments.length) {
return this[option];
}
this[option] = _;
return component;
};
}
function chart() {
// do something
};
var opts = {
width: 200,
height: 50,
color: '#000'
};
for (var key in opts) {
chart[key] = getSet(key, chart).bind(opts);
}
//using the setters...
chart.width(42)
chart.height(3.14)
chart.color("foo")
//...and then the getters
console.log(chart.width())
console.log(chart.height())
console.log(chart.color())
<script src="https://d3js.org/d3.v4.min.js"></script>
Upvotes: 1
Reputation: 10263
KISS: define a defaults
object and iterate over it's keys in order to create new properties:
function myChart(){
// default properties
var defaults = {
svgWidth: 1000,
svgHeight: 250
}
function chart(selection){
// do something with the previous properties ....
}
Object.keys(defaults).forEach((key) => {
chart[key] = function(_) {
if(!arguments.length) return defaults[key];
defaults[key] = _;
return chart;
};
});
return chart;
}
Upvotes: 1