diff --git a/src/set.js b/src/set.js index 923dec0..0398c1d 100644 --- a/src/set.js +++ b/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; }; -}); \ No newline at end of file +}); diff --git a/test/set.js b/test/set.js index e91ddc8..43d82fb 100644 --- a/test/set.js +++ b/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); }); -}); \ No newline at end of file +});