Skip to content

Commit

Permalink
Enter and exit return empty by default.
Browse files Browse the repository at this point in the history
  • Loading branch information
mbostock committed May 19, 2015
1 parent 938bb1d commit 3630ec0
Show file tree
Hide file tree
Showing 3 changed files with 46 additions and 8 deletions.
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ API changes from D3 3.x:

* The selection.data method, when called with arguments, now modifies the current selection to be the update selection, rather than returning a new selection. See [#2402](https://github.com/mbostock/d3/issues/2402).

* The selection.enter and selection.exit selections are now simply fields (defined by selection.data), not methods. See [#2402](https://github.com/mbostock/d3/issues/2402).
* The selection.enter and selection.exit methods now return empty selections if the selection has not yet been bound to data. (Previously, these methods were only defined after calling selection.data, and attempting to access them before binding to data would throw an error.) See [#2402](https://github.com/mbostock/d3/issues/2402).

* The selection.data method, when called *without* arguments, now returns an array of data for all elements in the selection, not just the first group.

Expand Down
32 changes: 25 additions & 7 deletions lib/d3/selection.js
Original file line number Diff line number Diff line change
Expand Up @@ -302,7 +302,9 @@ Selection.prototype = {
}

var enterGroups = new Array(m),
exitGroups = new Array(m);
exitGroups = new Array(m),
enter,
exit;

function bind(group, groupData, j) {
var i,
Expand Down Expand Up @@ -331,7 +333,7 @@ Selection.prototype = {

for (i = -1; ++i < m;) {
if (!(node = nodeByKeyValue.get(keyValue = key.call(groupData, nodeData = groupData[i], i)))) {
enterGroup[i] = new Placeholder(nodeData);
enterGroup[i] = new EnterNode(nodeData);
} else if (node !== true) { // no duplicate data key
updateGroup[i] = node;
node.__data__ = nodeData;
Expand All @@ -352,11 +354,11 @@ Selection.prototype = {
node.__data__ = nodeData;
updateGroup[i] = node;
} else {
enterGroup[i] = new Placeholder(nodeData);
enterGroup[i] = new EnterNode(nodeData);
}
}
for (; i < m; ++i) {
enterGroup[i] = new Placeholder(groupData[i]);
enterGroup[i] = new EnterNode(groupData[i]);
}
for (; i < n; ++i) {
exitGroup[i] = group[i];
Expand All @@ -380,11 +382,21 @@ Selection.prototype = {
}
}

this.enter = new EnterSelection(enterGroups);
this.exit = new Selection(exitGroups);
enter = new EnterSelection(enterGroups);
exit = new Selection(exitGroups);
this.enter = function() { return enter; };
this.exit = function() { return exit; };
return this;
},

enter: function() {
return this.data(dataOf).enter();
},

exit: function() {
return this.data(dataOf).exit();
},

datum: function(value) {
return arguments.length
? this.property("__data__", value)
Expand Down Expand Up @@ -563,7 +575,7 @@ EnterSelection.prototype.insert = function(name, before) {
return Selection.prototype.insert.call(this, name, before);
};

function Placeholder(data) {
function EnterNode(data) {
this.__data__ = data;
}

Expand Down Expand Up @@ -690,6 +702,12 @@ function filteredListenerOf(listener, args) {
};
}

function dataOf() {
var i = -1, n = this.length, data = new Array(n), node;
while (++i < n) if (node = this[i]) data[i] = node.__data__;
return data;
}

function ascending(a, b) {
return a < b ? -1 : a > b ? 1 : a >= b ? 0 : NaN;
}
Expand Down
20 changes: 20 additions & 0 deletions test/d3/selection-test.js
Original file line number Diff line number Diff line change
Expand Up @@ -19,3 +19,23 @@ tape("can subselect a child element", function(test) {
test.equal(s.node(), document.querySelector("h1"), "that element is the expected element");
test.end();
});

tape("the enter selection is initially empty", function(test) {
var document = jsdom.jsdom("<h1>hello</h1>"),
s = selection.select(document.documentElement).selectAll("h1"),
e = s.enter();
test.ok(e instanceof selection, "returns an instanceof selection");
test.equal(e.size(), 0, "the enter selection is empty");
test.equal(e, s.enter(), "the enter selection is sticky");
test.end();
});

tape("the exit selection is initially empty", function(test) {
var document = jsdom.jsdom("<h1>hello</h1>"),
s = selection.select(document.documentElement).selectAll("h1"),
e = s.exit();
test.ok(e instanceof selection, "returns an instanceof selection");
test.equal(e.size(), 0, "the exit selection is empty");
test.equal(e, s.exit(), "the exit selection is sticky");
test.end();
});

0 comments on commit 3630ec0

Please sign in to comment.