Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Specifying charts without using a name #41

Open
hughsk opened this issue Aug 13, 2013 · 4 comments
Open

Specifying charts without using a name #41

hughsk opened this issue Aug 13, 2013 · 4 comments

Comments

@hughsk
Copy link

hughsk commented Aug 13, 2013

In some cases it'd be nice to pass the chart definition directly to d3.selection.prototype.chart instead of defining a chart using d3.chart and a unique name - mostly to avoid naming collisions. For example:

d3.select('.graph')
  .append('svg')
  .chart({
    initialize: function() {
      console.log('initializing the chart')
    }
  })

Is there a way of doing this right now? If not, would you guys be open to it? I'm happy to submit a pull request if so.

@jugglinmike
Copy link
Member

Hey there Hugh!

I feel your concerns when it comes to namespacing. d3.chart's "factory-style" API was designed to be familiar to d3.js users, but it won't scale well for large projects.

My concern with the solution you've suggested is that it will allow people to make "anonymous charts", which would be difficult to re-use.

The good news is that d3.chart and d3.chart#extend both return a reference to the chart constructor, so if you like, you can work with that directly. Using this reference would allow you to, for instance, define your charts for module loaders:

var LineChart = d3.chart("LineChart", { /* your extra special chart code here */});

// CommonJS-style
module.exports = LineChart;

// AMD-style
define(function() {
  return LineChart;
});

Using the constructor directly is currently undocumented, but the first argument should be the chart's "base", and all additional arguments will be sliced off and applied to the chart's initialize method. So these two are equivalent:

d3.select("body").append("svg").chart("LineChart", 1, 2, 3);

new LineChart(d3.select("body").append("svg"), 1, 2, 3);

Does this help?

@idoa01
Copy link

idoa01 commented Aug 28, 2013

Thanks for the tip! I hope that you'll make this way documented so it won't break in future versions :)

it would be nice to be able to use the LineChart class instead of the string "LineChart" when using the d3.chart() method.

something in the lines of:

var LineChart = d3.chart("LineChart", { /* your extra special chart code here */});
var AwesomeLineChart = d3.chart(LineChart).extend("AwesomeLineChart", { /* more awesome code here */});

d3.select("body").append("svg").chart(AwesomeLineChart, 1, 2, 3);
new AwesomeLineChart(d3.select("body").append("svg"), 1, 2, 3);

removing the need to name the charts would be even better, but I suspect that this would need a bigger refractor than the above code.
ultimately, I would like to write code like this (AMD-style):

/* file: line-chart.js */
define(["d3", "d3.chart"], function(d3, Chart) {
    return Chart.extend({  /* your extra special chart code here */ });
});

/* file: awesome-line-chart.js */
define(["line-chart"], function(LineChart) {
    return LineChart.extend({  /* more awesome code here */ });
});

/* file: app.js */
define(["awesome-line-chart"], function(AwesomeLineChart) {
    var svg = d3.select("body").append("svg");
    var line_chart = new AwesomeLineChart(svg, 1, 2, 3);

   /* OR: just with a selector */
   var line_chart = new AwesomeLineChart("body svg", 1, 2, 3);
});

@hughsk
Copy link
Author

hughsk commented Aug 28, 2013

Hey Mike! Thanks for your explanation.

I get the need to have something in place for larger projects, but my main concern is when sharing base charts across multiple projects, possibly even npm/bower/jam/component - we've been contemplating this for a while now. By namespacing a chart there's always a slight risk of external charts interfering with others, either app-specific or in another module/script.

It'd be great to explicitly pass null to the chart name for these cases, e.g:

var LineChart = module.exports = d3.chart(null, { /* very special chart code */ })

From looking at the code, I think this would be a small change, but up to you! :)

@jeanlauliac
Copy link
Contributor

+1 for this kind of capability, notably for extending! I think it could make sense not to follow too closely the so-named "factory-style" of d3.js since d3.chart is more "high-level".

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

4 participants