Skip to content

Commit f8ae20d

Browse files
committed
Simplify data join. Add insert & empty.
The data join is now specified as a single function of data, as with all other properties. This allows the key to be computed on the previously-bound data, rather than requiring the key to be serialized into the DOM (say, as an attribute). In the case that there is no previously-bound data, it is still possible to access the associated node as the `this` context. The `enter` operator no longer performs an append. For symmetry with the `exit` operator, you must call `append` after obtaining the entering selection. This requires a tiny bit more code, but should make the code more clear. Also, it provides an opportunity to use a different instantiation operator, such as the new `insert` operator. This takes a second argument, which is a selector for the insert-before reference element. For example, the selector ":first-child" will prepend nodes. The `empty` operator allows you to query whether a selection is empty (i.e., contains zero matching nodes).
1 parent 44e67e2 commit f8ae20d

42 files changed

Lines changed: 291 additions & 252 deletions

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

d3.js

Lines changed: 50 additions & 36 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
(function(){d3 = {version: "0.29.6"}; // semver
1+
(function(){d3 = {version: "0.30.0"}; // semver
22
if (!Date.now) Date.now = function() {
33
return +new Date();
44
};
@@ -935,9 +935,6 @@ d3.selectAll = function(query) {
935935
};
936936

937937
function d3_selection(groups) {
938-
var i = -1,
939-
n = groups.length,
940-
group;
941938

942939
function select(select) {
943940
var subgroups = [],
@@ -1016,24 +1013,10 @@ function d3_selection(groups) {
10161013

10171014
// TODO data(null) for clearing data?
10181015
groups.data = function(data, join) {
1019-
var i = -1,
1020-
n = groups.length,
1021-
group,
1022-
enter = [],
1016+
var enter = [],
10231017
update = [],
10241018
exit = [];
10251019

1026-
if (typeof join == "string") join = d3_selection_join(join);
1027-
1028-
// TODO support join as a function, based on previously-bound data?
1029-
// else if (typeof join == "function") {
1030-
// var dataKey = join;
1031-
// join = {
1032-
// nodeKey: function(n) { return n.__data__ && dataKey(n.__data__); },
1033-
// dataKey: dataKey
1034-
// };
1035-
// }
1036-
10371020
function bind(group, groupData) {
10381021
var i = 0,
10391022
n = group.length,
@@ -1046,8 +1029,19 @@ function d3_selection(groups) {
10461029
node,
10471030
nodeData;
10481031

1049-
function enterAppend(e) {
1050-
return group.parentNode.appendChild(e);
1032+
function enterNode(data) {
1033+
return {
1034+
__data__: data,
1035+
appendChild: function(a) {
1036+
return group.parentNode.appendChild(a);
1037+
},
1038+
insertBefore: function(a, b) {
1039+
return group.parentNode.insertBefore(a, b);
1040+
},
1041+
querySelector: function(a) {
1042+
return group.parentNode.querySelector(a);
1043+
}
1044+
};
10511045
}
10521046

10531047
if (join) {
@@ -1058,7 +1052,7 @@ function d3_selection(groups) {
10581052
j = groupData.length;
10591053

10601054
for (i = 0; i < n; i++) {
1061-
key = join.nodeKey(node = group[i]);
1055+
key = join.call(node = group[i], node.__data__, i);
10621056
if (key in nodeByKey) {
10631057
exitNodes[j++] = group[i];
10641058
} else {
@@ -1068,13 +1062,13 @@ function d3_selection(groups) {
10681062
}
10691063

10701064
for (i = 0; i < m; i++) {
1071-
node = nodeByKey[key = join.dataKey(nodeData = groupData[i])];
1065+
node = nodeByKey[key = join.call(null, nodeData = groupData[i], i)];
10721066
if (node) {
10731067
node.__data__ = nodeData;
10741068
updateNodes[i] = node;
10751069
enterNodes[i] = exitNodes[i] = null;
10761070
} else {
1077-
enterNodes[i] = {appendChild: enterAppend, __data__: nodeData},
1071+
enterNodes[i] = enterNode(nodeData),
10781072
updateNodes[i] = exitNodes[i] = null;
10791073
}
10801074
delete nodeByKey[key];
@@ -1094,12 +1088,12 @@ function d3_selection(groups) {
10941088
updateNodes[i] = node;
10951089
enterNodes[i] = exitNodes[i] = null;
10961090
} else {
1097-
enterNodes[i] = {appendChild: enterAppend, __data__: nodeData};
1091+
enterNodes[i] = enterNode(nodeData);
10981092
updateNodes[i] = exitNodes[i] = null;
10991093
}
11001094
}
11011095
for (; i < m; i++) {
1102-
enterNodes[i] = {appendChild: enterAppend, __data__: groupData[i]};
1096+
enterNodes[i] = enterNode(groupData[i]);
11031097
updateNodes[i] = exitNodes[i] = null;
11041098
}
11051099
for (; i < n1; i++) {
@@ -1123,6 +1117,9 @@ function d3_selection(groups) {
11231117
exit.push(exitNodes);
11241118
}
11251119

1120+
var i = -1,
1121+
n = groups.length,
1122+
group;
11261123
if (typeof data == "function") {
11271124
while (++i < n) {
11281125
bind(group = groups[i], data.call(group, group.parentData, i));
@@ -1134,8 +1131,8 @@ function d3_selection(groups) {
11341131
}
11351132

11361133
var selection = d3_selection(update);
1137-
selection.enter = function(name) {
1138-
return d3_selection(enter).append(name);
1134+
selection.enter = function() {
1135+
return d3_selection(enter);
11391136
};
11401137
selection.exit = function() {
11411138
return d3_selection(exit);
@@ -1167,6 +1164,10 @@ function d3_selection(groups) {
11671164
return null;
11681165
}
11691166

1167+
groups.empty = function() {
1168+
return !first(function() { return true; });
1169+
};
1170+
11701171
groups.node = function() {
11711172
return first(function() { return this; });
11721173
};
@@ -1394,6 +1395,27 @@ function d3_selection(groups) {
13941395
return select(name.local ? appendNS : append);
13951396
};
13961397

1398+
// TODO insert(node, function)?
1399+
// TODO insert(function, string)?
1400+
// TODO insert(function, function)?
1401+
groups.insert = function(name, before) {
1402+
name = d3.ns.qualify(name);
1403+
1404+
function insert(node) {
1405+
return node.insertBefore(
1406+
document.createElement(name),
1407+
node.querySelector(before));
1408+
}
1409+
1410+
function insertNS(node) {
1411+
return node.insertBefore(
1412+
document.createElementNS(name.space, name.local),
1413+
node.querySelector(before));
1414+
}
1415+
1416+
return select(name.local ? insertNS : insert);
1417+
};
1418+
13971419
// TODO remove(query)?
13981420
// TODO remove(node)?
13991421
// TODO remove(function)?
@@ -1448,14 +1470,6 @@ function d3_selection(groups) {
14481470
return groups;
14491471
}
14501472

1451-
// TODO support namespaces for key?
1452-
function d3_selection_join(key) {
1453-
return {
1454-
nodeKey: function(node) { return node.getAttribute(key); },
1455-
dataKey: function(data) { return data[key]; }
1456-
};
1457-
}
1458-
14591473
function d3_selection_comparator(comparator) {
14601474
if (!arguments.length) comparator = d3.ascending;
14611475
return function(a, b) {

0 commit comments

Comments
 (0)