toolkit/javascript/d3/src/core/selection-data.js
changeset 47 c0b4a8b5a012
equal deleted inserted replaced
46:efd9c589177a 47:c0b4a8b5a012
       
     1 // TODO data(null) for clearing data?
       
     2 d3_selectionPrototype.data = function(data, join) {
       
     3   var enter = [],
       
     4       update = [],
       
     5       exit = [];
       
     6 
       
     7   function bind(group, groupData) {
       
     8     var i,
       
     9         n = group.length,
       
    10         m = groupData.length,
       
    11         n0 = Math.min(n, m),
       
    12         n1 = Math.max(n, m),
       
    13         updateNodes = [],
       
    14         enterNodes = [],
       
    15         exitNodes = [],
       
    16         node,
       
    17         nodeData;
       
    18 
       
    19     if (join) {
       
    20       var nodeByKey = {},
       
    21           keys = [],
       
    22           key,
       
    23           j = groupData.length;
       
    24 
       
    25       for (i = -1; ++i < n;) {
       
    26         key = join.call(node = group[i], node.__data__, i);
       
    27         if (key in nodeByKey) {
       
    28           exitNodes[j++] = node; // duplicate key
       
    29         } else {
       
    30           nodeByKey[key] = node;
       
    31         }
       
    32         keys.push(key);
       
    33       }
       
    34 
       
    35       for (i = -1; ++i < m;) {
       
    36         node = nodeByKey[key = join.call(groupData, nodeData = groupData[i], i)];
       
    37         if (node) {
       
    38           node.__data__ = nodeData;
       
    39           updateNodes[i] = node;
       
    40           enterNodes[i] = exitNodes[i] = null;
       
    41         } else {
       
    42           enterNodes[i] = d3_selection_dataNode(nodeData);
       
    43           updateNodes[i] = exitNodes[i] = null;
       
    44         }
       
    45         delete nodeByKey[key];
       
    46       }
       
    47 
       
    48       for (i = -1; ++i < n;) {
       
    49         if (keys[i] in nodeByKey) {
       
    50           exitNodes[i] = group[i];
       
    51         }
       
    52       }
       
    53     } else {
       
    54       for (i = -1; ++i < n0;) {
       
    55         node = group[i];
       
    56         nodeData = groupData[i];
       
    57         if (node) {
       
    58           node.__data__ = nodeData;
       
    59           updateNodes[i] = node;
       
    60           enterNodes[i] = exitNodes[i] = null;
       
    61         } else {
       
    62           enterNodes[i] = d3_selection_dataNode(nodeData);
       
    63           updateNodes[i] = exitNodes[i] = null;
       
    64         }
       
    65       }
       
    66       for (; i < m; ++i) {
       
    67         enterNodes[i] = d3_selection_dataNode(groupData[i]);
       
    68         updateNodes[i] = exitNodes[i] = null;
       
    69       }
       
    70       for (; i < n1; ++i) {
       
    71         exitNodes[i] = group[i];
       
    72         enterNodes[i] = updateNodes[i] = null;
       
    73       }
       
    74     }
       
    75 
       
    76     enterNodes.update
       
    77         = updateNodes;
       
    78 
       
    79     enterNodes.parentNode
       
    80         = updateNodes.parentNode
       
    81         = exitNodes.parentNode
       
    82         = group.parentNode;
       
    83 
       
    84     enter.push(enterNodes);
       
    85     update.push(updateNodes);
       
    86     exit.push(exitNodes);
       
    87   }
       
    88 
       
    89   var i = -1,
       
    90       n = this.length,
       
    91       group;
       
    92   if (typeof data === "function") {
       
    93     while (++i < n) {
       
    94       bind(group = this[i], data.call(group, group.parentNode.__data__, i));
       
    95     }
       
    96   } else {
       
    97     while (++i < n) {
       
    98       bind(group = this[i], data);
       
    99     }
       
   100   }
       
   101 
       
   102   var selection = d3_selection(update);
       
   103   selection.enter = function() { return d3_selection_enter(enter); };
       
   104   selection.exit = function() { return d3_selection(exit); };
       
   105   return selection;
       
   106 };
       
   107 
       
   108 function d3_selection_dataNode(data) {
       
   109   return {__data__: data};
       
   110 }