Adding new rectangles if needed

At this point, we've only updated the style and dimensions of the rectangles which are updated. We repeat pretty much the same process for the rectangles that need to be created. This happens when our data array is larger than the number of rectangles we can find:

rectangles.enter() 
.append("rect")
.attr("class", "enter")
.attr("x", function(d, i) { return i * (rectangleWidth + 5) })
.attr("y", 50)
.attr("width", function(d) {return d})
.attr("height", function(d) {return d});

Not that different from the update call, but this time we first call the enter() function and then create the SVG element we want to add like this: .append("rect"). After the append call, we configure the rectangle and set its class, width, and height properties, just like we did in the previous section (this time the CSS will render the newly added rectangle in green). If you look at the code, you can see that we also set the position of this element by setting the x and y attributes of the added rectangle. This is needed since this is the first time this rectangle is added, and we need to determine where to position it. We fix the y position to 50, but need to make the x position dependent on the position of the element from the data array to which it is bound. We once again bind the attribute to a function. This time we specify a function with two arguments: function(d, i) {...}. The first one is the element from the data array, and the second argument (i), is the position in the data array. So the first element has i = 0, the second i = 1, and so on. Now, when we add a new rectangle we calculate its x position by just multiplying its array position with the maximum rectangleWidth and add a couple of pixels margin. This way none of our rectangles will overlap.

If you look at the code for adding new elements, and updating existing ones, you might notice some duplicate code. In both instances, we use .attr to set the width and the height properties. If we'd wanted to, we could remove this duplication by using the .merge function. The code to set the new width and height for the new elements and the updated ones would then look like this:

rectangles.attr("class", "update"); 

rectangles.enter()
.append("rect")
.attr("class", "enter")
.attr("x", function(d, i) { return i * (rectangleWidth + 5) })
.attr("y", 50)
.merge(rectangles)
.attr("width", function(d) {return d})
.attr("height", function(d) {return d});

This means that after merging the new and updated elements together, on that combined set, we use the .attr function to set the width and the height property. Personally, I'd like to keep these steps separate, since it is more clear what happens in each of the steps.