Adding a way to specify how attributes are bound on Set objects
This commit is backward compatible with previous versions but adds a new option for handling attribute applications on Set objects. The normal behavior (of applying the attribute to all elements in the set) is preserved unless the developer explicitly defines how the attribute should be treated. This relatively simply change allows three useful cases. First, the user can specify that an attribute to applied to a specific element. Second, it allows pseudo-attributes to be defined and applied to a specific element. Finally, and most powerfully, it allows the user to specify a function to be called when a given attribute is set. That function can, of course, apply the attribute to a number of different elements. This commit includes test cases for all these cases.master
parent
f94872941f
commit
b54624a11b
42
src/set.js
42
src/set.js
|
@ -18,6 +18,7 @@ Snap.plugin(function (Snap, Element, Paper, glob) {
|
|||
// Set
|
||||
var Set = function (items) {
|
||||
this.items = [];
|
||||
this.bindings = {};
|
||||
this.length = 0;
|
||||
this.type = "set";
|
||||
if (items) {
|
||||
|
@ -87,9 +88,46 @@ Snap.plugin(function (Snap, Element, Paper, glob) {
|
|||
}
|
||||
return this;
|
||||
};
|
||||
/*\
|
||||
* Set.bind
|
||||
[ method ]
|
||||
**
|
||||
* Specifies how to handle a specific attribute when applied
|
||||
* to a set.
|
||||
*
|
||||
**
|
||||
- attr (string) attribute name
|
||||
- callback (function) function to run
|
||||
* or
|
||||
- attr (string) attribute name
|
||||
- element (Element) specific element in the set to apply the attribute to
|
||||
* or
|
||||
- attr (string) attribute name
|
||||
- element (Element) specific element in the set to apply the attribute to
|
||||
- eattr (string) attribute on the element to bind the attribute to
|
||||
= (object) Set object
|
||||
\*/
|
||||
setproto.bind = function(attr, a, b) {
|
||||
var data = {};
|
||||
if (typeof(a)=="function") {
|
||||
this.bindings[attr] = a;
|
||||
} else {
|
||||
var aname = b || attr;
|
||||
this.bindings[attr] = function(v) {
|
||||
data[aname] = v;
|
||||
a.attr(data);
|
||||
}
|
||||
}
|
||||
return this;
|
||||
}
|
||||
setproto.attr = function (value) {
|
||||
var unbound = {};
|
||||
for (var k in value) {
|
||||
if (this.bindings[k]) this.bindings[k](value[k]);
|
||||
else unbound[k] = value[k];
|
||||
}
|
||||
for (var i = 0, ii = this.items.length; i < ii; i++) {
|
||||
this.items[i].attr(value);
|
||||
this.items[i].attr(unbound);
|
||||
}
|
||||
return this;
|
||||
};
|
||||
|
@ -210,4 +248,4 @@ Snap.plugin(function (Snap, Element, Paper, glob) {
|
|||
}
|
||||
return set;
|
||||
};
|
||||
});
|
||||
});
|
||||
|
|
47
test/set.js
47
test/set.js
|
@ -82,6 +82,51 @@ describe("Set methods", function () {
|
|||
expect(set[1]).to.be(rect2);
|
||||
expect(set[2]).to.be(rect3);
|
||||
});
|
||||
it("Set.attr", function() {
|
||||
var rect1 = s.rect(10, 20, 30, 40);
|
||||
var rect2 = s.rect(10, 20, 30, 40);
|
||||
var set = Snap.set(rect1, rect2);
|
||||
set.attr({"fill": "#ff0000"});
|
||||
expect(rect1.node.getAttribute("fill")).to.be("#ff0000");
|
||||
expect(rect2.node.getAttribute("fill")).to.be("#ff0000");
|
||||
set.attr({"stroke": "#0000ff"});
|
||||
expect(rect1.node.getAttribute("stroke")).to.be("#0000ff");
|
||||
expect(rect2.node.getAttribute("stroke")).to.be("#0000ff");
|
||||
});
|
||||
it("Set.bind", function() {
|
||||
var rect1 = s.rect(10, 20, 30, 40);
|
||||
var rect2 = s.rect(10, 20, 30, 40);
|
||||
var set = Snap.set(rect1, rect2);
|
||||
|
||||
// Setting "stroke" on set only applies it to rect1
|
||||
set.bind("stroke", rect1);
|
||||
// Setting "fill1" on set maps to fill attribute on rect1
|
||||
set.bind("fill1", rect1, "fill");
|
||||
// Setting "fill2" on set maps to fill attribute on rect2
|
||||
set.bind("fill2", function(v) { rect2.attr({"fill": v}); });
|
||||
|
||||
// Set everything to black
|
||||
rect1.attr({"fill": "#000000", "stroke": "#000000"})
|
||||
rect2.attr({"fill": "#000000", "stroke": "#000000"})
|
||||
|
||||
set.attr({"fill1": "#00ff00"});
|
||||
expect(rect1.node.getAttribute("fill")).to.be("#00ff00");
|
||||
expect(rect2.node.getAttribute("fill")).to.be("#000000");
|
||||
|
||||
// Will trigger the fallback implementation of attr which is
|
||||
// to set that attribute on all elements in the set.
|
||||
set.attr({"fill": "#ff0000"});
|
||||
expect(rect1.node.getAttribute("fill")).to.be("#ff0000");
|
||||
expect(rect2.node.getAttribute("fill")).to.be("#ff0000");
|
||||
|
||||
set.attr({"fill2": "#00ff00"});
|
||||
expect(rect1.node.getAttribute("fill")).to.be("#ff0000");
|
||||
expect(rect2.node.getAttribute("fill")).to.be("#00ff00");
|
||||
|
||||
set.attr({"stroke": "#0000ff"});
|
||||
expect(rect1.node.getAttribute("stroke")).to.be("#0000ff");
|
||||
expect(rect2.node.getAttribute("stroke")).to.be("#000000");
|
||||
});
|
||||
it("Set.splice - remove only", function() {
|
||||
var rect1 = s.rect(10, 20, 30, 40);
|
||||
var rect2 = s.rect(10, 20, 30, 40);
|
||||
|
@ -119,4 +164,4 @@ describe("Set methods", function () {
|
|||
expect(removedSet[1]).to.be(rect2);
|
||||
expect(removedSet[2]).to.be(rect4);
|
||||
});
|
||||
});
|
||||
});
|
||||
|
|
Loading…
Reference in New Issue