Taking inspiration from d3.map, d3.set is a simple shim for ES6 sets.
This commit is contained in:
John Firebaugh 2013-02-09 14:42:04 -08:00
Родитель 35ac9dd9ae
Коммит 1e8a579810
5 изменённых файлов: 210 добавлений и 4 удалений

Просмотреть файл

@ -34,6 +34,7 @@ d3.core.js: \
src/core/class.js \
src/core/array.js \
src/core/map.js \
src/core/set.js \
src/core/identity.js \
src/core/true.js \
src/core/functor.js \

34
d3.js поставляемый
Просмотреть файл

@ -104,6 +104,40 @@ d3 = function() {
}
});
var d3_map_prefix = "\0", d3_map_prefixCode = d3_map_prefix.charCodeAt(0);
d3.set = function(array) {
var set = new d3_Set();
if (array) for (var i = 0; i < array.length; i++) set.add(array[i]);
return set;
};
function d3_Set() {}
d3_class(d3_Set, {
has: function(value) {
return d3_set_prefix + value in this;
},
add: function(value) {
this[d3_set_prefix + value] = true;
return value;
},
remove: function(value) {
value = d3_set_prefix + value;
return value in this && delete this[value];
},
values: function() {
var values = [];
this.forEach(function(value) {
values.push(value);
});
return values;
},
forEach: function(f) {
for (var value in this) {
if (value.charCodeAt(0) === d3_set_prefixCode) {
f.call(this, value.substring(1));
}
}
}
});
var d3_set_prefix = "\0", d3_set_prefixCode = d3_set_prefix.charCodeAt(0);
function d3_identity(d) {
return d;
}

8
d3.min.js поставляемый

Различия файлов скрыты, потому что одна или несколько строк слишком длинны

38
src/core/set.js Normal file
Просмотреть файл

@ -0,0 +1,38 @@
d3.set = function(array) {
var set = new d3_Set();
if (array) for (var i = 0; i < array.length; i++) set.add(array[i]);
return set;
};
function d3_Set() {}
d3_class(d3_Set, {
has: function(value) {
return d3_set_prefix + value in this;
},
add: function(value) {
this[d3_set_prefix + value] = true;
return value;
},
remove: function(value) {
value = d3_set_prefix + value;
return value in this && delete this[value];
},
values: function() {
var values = [];
this.forEach(function(value) {
values.push(value);
});
return values;
},
forEach: function(f) {
for (var value in this) {
if (value.charCodeAt(0) === d3_set_prefixCode) {
f.call(this, value.substring(1));
}
}
}
});
var d3_set_prefix = "\0", // prevent collision with built-ins
d3_set_prefixCode = d3_set_prefix.charCodeAt(0);

133
test/core/set-test.js Normal file
Просмотреть файл

@ -0,0 +1,133 @@
require("../env");
var vows = require("vows"),
assert = require("assert");
var suite = vows.describe("d3.set");
suite.addBatch({
"constructor": {
"set() returns an empty set": function() {
var set = d3.set();
assert.deepEqual(set.values(), []);
},
"set(null) returns an empty set": function() {
var set = d3.set(null);
assert.deepEqual(set.values(), []);
},
"set(array) adds array entries": function() {
var set = d3.set(["foo"]);
assert.isTrue(set.has("foo"));
var set = d3.set(["foo", "bar"]);
assert.isTrue(set.has("foo"));
assert.isTrue(set.has("bar"));
}
},
"forEach": {
"empty sets have an empty values array": function() {
var set = d3.set();
assert.deepEqual(set.values(), []);
set.add("foo");
assert.deepEqual(set.values(), ["foo"]);
set.remove("foo");
assert.deepEqual(set.values(), []);
},
"values are returned in arbitrary order": function() {
var set = d3.set(["foo", "bar"]);
assert.deepEqual(set.values().sort(d3.ascending()), ["bar", "foo"]);
var set = d3.set(["bar", "foo"]);
assert.deepEqual(set.values().sort(d3.ascending()), ["bar", "foo"]);
},
"observes changes via add and remove": function() {
var set = d3.set(["foo", "bar"]);
assert.deepEqual(set.values().sort(d3.ascending()), ["bar", "foo"]);
set.remove("foo");
assert.deepEqual(set.values(), ["bar"]);
set.add("bar");
assert.deepEqual(set.values(), ["bar"]);
set.add("foo");
assert.deepEqual(set.values().sort(d3.ascending()), ["bar", "foo"]);
set.remove("bar");
assert.deepEqual(set.values(), ["foo"]);
set.remove("foo");
assert.deepEqual(set.values(), []);
set.remove("foo");
assert.deepEqual(set.values(), []);
}
},
"values": {
"returns an array of string values": function() {
var set = d3.set(["foo", "bar"]);
assert.deepEqual(set.values().sort(), ["bar", "foo"]);
}
},
"has": {
"empty sets do not have object built-ins": function() {
var set = d3.set();
assert.isFalse(set.has("__proto__"));
assert.isFalse(set.has("hasOwnProperty"));
},
"coerces values to strings": function() {
var set = d3.set(["42", "null", "undefined"]);
assert.isTrue(set.has(42));
assert.isTrue(set.has(null));
assert.isTrue(set.has(undefined));
},
"observes changes via add and remove": function() {
var set = d3.set(["foo"]);
assert.isTrue(set.has("foo"));
set.add("foo");
assert.isTrue(set.has("foo"));
set.remove("foo");
assert.isFalse(set.has("foo"));
set.add("foo");
assert.isTrue(set.has("foo"));
},
"returns undefined for missing values": function() {
var set = d3.set(["foo"]);
assert.isFalse(set.has("bar"));
}
},
"add": {
"returns the set value": function() {
var set = d3.set();
assert.equal(set.add("foo"), "foo");
},
"can add values using built-in names": function() {
var set = d3.set();
set.add("__proto__");
assert.isTrue(set.has("__proto__"));
},
"coerces values to strings": function() {
var set = d3.set();
set.add(42);
assert.isTrue(set.has(42));
set.add(null);
assert.isTrue(set.has(null));
set.add(undefined);
assert.isTrue(set.has(undefined));
assert.deepEqual(set.values().sort(), ["42", "null", "undefined"]);
},
"can add null, undefined or empty string values": function() {
var set = d3.set();
set.add("");
set.add("null");
set.add("undefined");
assert.isTrue(set.has(""));
assert.isTrue(set.has("null"));
assert.isTrue(set.has("undefined"));
}
},
"remove": {
"returns true if the value was removed": function() {
var set = d3.set(["foo"]);
assert.isTrue(set.remove("foo"));
},
"returns false if the value is not an element": function() {
var set = d3.set();
assert.isFalse(set.remove("foo"));
}
}
});
suite.export(module);