D3 console.log in the function chain

Is there a basic function / object in D3 that would allow you to keep a log "in line"?

I am reading a Scott Merry book from D3 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 am currently doing 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 great when creating this interactive console output: enter image description here But .. What is the D3 way to do this?

+4
source share
3 answers

You can use your solution by changing the prototype of choosing d3 (unlike the prototype of an object, I don’t think it could be considered “terrible”, although I am a bit incomplete to mess with d3 internally), but I feel that you are looking for selection.call().

, , selection.call, , :

, . . (docs)

, . :

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

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

selection.call , . (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);
}

:

enter image description here

.

+3

, , - , , selection.call(). , , , D3. d3.selection() , .

:

const logger = {
  log() {
    console.log(...arguments);
    return this;
  }
}

d3.selection.prototype:

Object.assign(d3.selection.prototype, logger);

logger.log() , , , this, .

, , , . :

const logger = {
  log() {          // Generic method logging all arguments.
    console.log(...arguments);
    return this;
  },
  
  logMsg(msg) {    // Logging just a simple msg.
    console.log(msg);
    return this;
  },
  
  logSel() {       // Log the selection.
    console.log(this);
    return this;
  },
  
  logAttr(name) {  // Log the attributes with "name" for all selected elements.
    this.each(function(d, i) {
      let attr = d3.select(this).attr(name);
      console.log(`Node ${i}: ${name}=${attr}`);
    });
    return this;
  },
  
  logData() {      // Log the data bound to this selection.
    console.log(this.data());
    return this;
  },

  logNodeData() {  // Log datum per node.
    this.each(function(d, i) {
      console.log(`Node ${i}: ${d}`);
    });
    return this;
  }
};

Object.assign(d3.selection.prototype, logger);

d3.select("body")
    .logMsg("Start")
  .append("svg").selectAll(null)
    .log(1, {}, "Test")
    // .logSel()   // this doesn't work well in Stack snippets
  .data([1,2])
  .enter().append("circle")
    .attr("r", "10")
    .logAttr("r")
    .logData()
    .logNodeData()
    .logMsg("End");
<script src="https://d3js.org/d3.v5.js"></script>
Hide result
+3

:

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

In other words, I don’t think there is a “d3” method that allows you to register and sadly, I think you should do it in the usual way:

console.log(d3.select("body").selectAll("div").data(dataset).enter());
+1
source

Source: https://habr.com/ru/post/1696117/


All Articles