Chapter 01Applying Functions to Selected Elements

Selection.each

The selection.each method allows us to apply a function to each element in the selection in order.  The argument to each is a function.  As before, we can pass in a named function, unnamed function, a lambda expression, or specify the function inline. The function is passed d (data from a data join), i (index), and nodes (an array of elements in the current group. For information on groups read How Selections Work. The nodes array can be used to get a particular element using nodes[i].

d3.selectAll("#eachSVG circle").each((d,i,nodes) => {
    if (i % 2 == 0) {
        nodes[i].setAttribute("fill", "pink");
    }});
<script>
    function applyEach(){
        d3.selectAll("#eachSVG circle").each((d,i,nodes) => {
            if (i % 2 == 0) {
                nodes[i].setAttribute("fill", "pink");
            }});
    }
</script>

<svg id="eachSVG" width="300" height="60">
    <circle r="20" cx="30" cy="30" fill="lightblue" />
    <circle r="20" cx="80" cy="30" fill="lightblue" />
    <circle r="20" cx="130" cy="30" fill="lightblue" />
    <circle r="20" cx="180" cy="30" fill="lightblue" />
</svg>

<button id="eachButton" onclick="applyEach()">Apply Each</button>

Selection.call

The selection.call method executes the function that is passed into it once while passing in a reference to the given selection on which it is called along with any optional arguments that are passed into the call method.

For example, suppose we have the following function that takes a selection, attribute name, and attribute value as arguments, and sets the attribute for each circle element in the selection.

function setAttr(selection, attr, value) {
    selection.selectAll("circle").attr(attr, value);
}

Suppose also that we have an SVG element with an id attribute set to “callSVG”.  Then we can select the SVG element using select and call the call function on it.  If we pass the name of the above function, setAttr, along with the strings “fill” and “pink” as arguments to call, then all of the circles in the selection will have their fill attributes set to pink.

d3.select("#callSVG").call(setAttr, "fill", "pink");
<script>
    function setAttr(selection, attr, value) {
        selection.selectAll("circle").attr(attr, value);
    }

    function applyCall(){
        d3.select("#callSVG").call(setAttr, "fill", "pink");
    }
</script>

<svg id="callSVG" width="300" height="60">
    <circle r="20" cx="30" cy="30" fill="lightblue" />
    <circle r="20" cx="80" cy="30" fill="lightblue" />
    <circle r="20" cx="130" cy="30" fill="lightblue" />
    <circle r="20" cx="180" cy="30" fill="lightblue" />
</svg>

<button id="callButton" onclick="applyCall()">Apply Call</button>