Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

D3 console.log in a function chain

Is there a base function/object in D3 which would allow "in-line" logging?

I'm reading Scott Murry's nifty D3 book and want to do this:

  d3.select("body").selectAll("div")
    .log("body")
    .data(dataset)
    .log("data")
    .enter()
    .log("enter")
    .append("div")
    .log("div")
    .attr("class", "bar")
    .log("class");

I currently do this Horrible Thing:

const log = function (msg, val) {
  const data = val ? val : this
  const label = msg ? msg : "data:"
  console.log(label, data)
  return data
}

Object.prototype.log = log

This works fine, producing this clickable console output: enter image description here But .. What is the D3 way to do this?

like image 582
backspaces Avatar asked Apr 12 '18 16:04

backspaces


People also ask

What does .data do in D3?

data() returns the values from the array it's been passed, we can use these values to change attributes and styles for SVG elements with a method chain. NOTE: It's possible to use . data() for changing other elements, but we'll focus on SVG. D3 can change the radius by using values from from an array radiusData.

How to load a csv file into D3?

We can load a csv file or csv data using d3. csv() method.

What can console log do?

console. log specifically is a method for developers to write code to inconspicuously inform the developers what the code is doing. It can be used to alert you that there's an issue, but shouldn't take the place of an interactive debugger when it comes time to debug the code.

How do you use D3 select this?

select() function in D3. js is used to select the first element that matches the specified selector string. If any element is not matched then it returns the empty selection. If multiple elements are matched with the selector then only the first matching element will be selected.


2 Answers

For logging datas in your chain, you can just use a fake attribute :

d3.select("body").selectAll("div")
  .data(dataset)
  .enter()
  .append("div")
  .attr("fake", d=> console.log(d));

For the other things, I don't think there is a "d3" way which allows to log and sadly, I think you have to do it with a normal way :

console.log(d3.select("body").selectAll("div").data(dataset).enter());
like image 52
Pierre Capo Avatar answered Sep 22 '22 11:09

Pierre Capo


You could use your solution by modifying the d3 selection prototype (as opposed to the object prototype, I don't think that could be considered "horrible" - though I'm a little partial to messing with d3 internally), but I feel you are looking for selection.call().

If you want to access the current selection, but not interrupt method chaining, selection.call is probably your best bet:

Invokes the specified function exactly once, passing in this selection along with any optional arguments. Returns this selection. (docs)

The called function's first parameter will be the selection, further optional parameters can be passed in the call method itself. The general form is:

selection.call(func, arg, arg, ...)

function func(selection, arg, arg, ...) {}

Using selection.call for logging shouldn't be too hard to rig up with this method. Here's a quick mock up (v4/5):

var dataset = d3.range(10);

  d3.select("body").selectAll("div")
    .call(log,"body")
    .data(dataset)
    .call(log,"dataset")
    .enter()
    .call(log,"enter")
    .append("div")
    .call(log,"div")
    .attr("class", "bar")
    .call(log,"bar");

function log(sel,msg) {
  console.log(msg,sel);
}

And the results:

enter image description here

Here's the mock up in action.

like image 26
Andrew Reid Avatar answered Sep 19 '22 11:09

Andrew Reid