Add d3.set
Taking inspiration from d3.map, d3.set is a simple shim for ES6 sets.
This commit is contained in:
Родитель
35ac9dd9ae
Коммит
1e8a579810
1
Makefile
1
Makefile
|
@ -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 \
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
Различия файлов скрыты, потому что одна или несколько строк слишком длинны
|
@ -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);
|
|
@ -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);
|
Загрузка…
Ссылка в новой задаче