Added gradients. Changed plugin architecture.

master
Dmitry Baranovskiy 2013-07-11 13:23:37 +10:00
parent c22245fc56
commit 2270a96f12
5 changed files with 387 additions and 68 deletions

BIN
bg.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.7 KiB

View File

@ -3,6 +3,11 @@
<head> <head>
<meta charset="utf-8"> <meta charset="utf-8">
<title>Savage</title> <title>Savage</title>
<style media="screen">
body {
background: #030 url("bg.png");
}
</style>
<script src="eve/eve.js"></script> <script src="eve/eve.js"></script>
<script src="mina.js"></script> <script src="mina.js"></script>
<script src="elemental.js"></script> <script src="elemental.js"></script>
@ -25,31 +30,31 @@
</script> </script>
<script> <script>
window.onload = function () { window.onload = function () {
// // 1 // 1
var s = Savage("100%", 600); var s = Savage("100%", 600);
// // 2 // 2
var c = s.circle(100, 100, 50); var c = s.circle(100, 100, 50);
// // 3 // 3
c.attr({ c.attr({
fill: "#bada55", fill: "#bada55",
stroke: "#000", stroke: "#000",
"stroke-width": 5 "stroke-width": 5
}); });
// // 4 // 4
var c2 = s.circle(70, 100, 40); var c2 = s.circle(70, 100, 40);
var g = s.g(c2, s.circle(130, 100, 40)); var g = s.group(c2, s.circle(130, 100, 40));
g.attr({ g.attr({
fill: "#fff" fill: "#fff"
}); });
// // 5 // 5
c.attr({ c.attr({
mask: g mask: g
}); });
// // 6 // 6
c2.animate({r: 25}, 1000); c2.animate({r: 25}, 1000);
// // 7 // 7
g.select("circle:nth-child(2)").animate({r: 25}, 1000); g.select("circle:nth-child(2)").animate({r: 25}, 1000);
// // 8 // 8
var p = s.path("M10-5-10,15M15,0,0,15M0-5-20,15").attr({ var p = s.path("M10-5-10,15M15,0,0,15M0-5-20,15").attr({
fill: "none", fill: "none",
stroke: "#bada55", stroke: "#bada55",
@ -58,26 +63,33 @@
c.attr({ c.attr({
fill: p fill: p
}); });
// // 9 // 9
g.attr({ g.attr({
fill: Savage(document.getElementById("pattern")) fill: Savage(document.getElementById("pattern"))
}); });
// // 10 // 10
g.attr({fill: "r()#fff-#000"});
// 11
g.attr({fill: "R(100, 100, 50)#fff-#000"});
// 12
var svg = document.getElementById("svg").text; var svg = document.getElementById("svg").text;
var f = Savage.fragment(svg); var f = Savage.fragment(svg);
f.select("path[fill='#D40000']").attr({fill: "#bada55"}); f.select("path[fill='#D40000']").attr({fill: "#bada55"});
g = s.g(f.selectAll("path")); g = s.group(f.selectAll("path"));
s.append(g); s.append(g);
// // 11 // 13
g.attr({ g.attr({
transform: "r45t100,0s.5" transform: "r45t100,0s.5"
}); });
console.log(g.attr("transform")); // console.log(g.attr("transform"));
// // 12 // 14
s.text(200, 100, "SAVAGE"); s.text(200, 100, "SAVAGE");
// // 13 // 15
var t = s.text(200, 120, ["S","A","V","A","G","E"]); var t = s.text(200, 120, "SAVAGE".split(""));
t.selectAll("tspan tspan:nth-child(odd)").attr({fill: "red"}); t.selectAll("tspan tspan:nth-child(odd)").attr({
fill: "#900",
"font-size": "20px"
});
}; };
</script> </script>
</head> </head>

View File

@ -1,7 +1,6 @@
(function () { Savage.plugin(function (Savage, Element, Paper, glob) {
var mmax = Math.max, var mmax = Math.max,
mmin = Math.min, mmin = Math.min;
g = eve("savage.globals")[0];
// Set // Set
var Set = function (items) { var Set = function (items) {
@ -71,9 +70,9 @@
} }
return this; return this;
}; };
setproto.attr = function (name, value) { setproto.attr = function (value) {
for (var i = 0, ii = this.items.length; i < ii; i++) { for (var i = 0, ii = this.items.length; i < ii; i++) {
this.items[i].attr(name, value); this.items[i].attr(value);
} }
return this; return this;
}; };
@ -190,11 +189,11 @@
}; };
setproto.type = "set"; setproto.type = "set";
// export // export
g.savage.set = function () { Savage.set = function () {
var set = new Set; var set = new Set;
if (arguments.length) { if (arguments.length) {
set.push.apply(set, Array.prototype.slice.call(arguments, 0)); set.push.apply(set, Array.prototype.slice.call(arguments, 0));
} }
return set; return set;
}; };
})(); });

192
svg.js
View File

@ -11,6 +11,8 @@ var Savage = function (w, h) {
return new Element(glob.doc.querySelector(w)); return new Element(glob.doc.querySelector(w));
} }
} }
w = w == null ? "100%" : w;
h = h == null ? "100%" : h;
return new Paper(w, h); return new Paper(w, h);
}; };
var glob = { var glob = {
@ -38,13 +40,12 @@ var has = "hasOwnProperty",
spaces = "\x09\x0a\x0b\x0c\x0d\x20\xa0\u1680\u180e\u2000\u2001\u2002\u2003\u2004\u2005\u2006\u2007\u2008\u2009\u200a\u202f\u205f\u3000\u2028\u2029", spaces = "\x09\x0a\x0b\x0c\x0d\x20\xa0\u1680\u180e\u2000\u2001\u2002\u2003\u2004\u2005\u2006\u2007\u2008\u2009\u200a\u202f\u205f\u3000\u2028\u2029",
separator = new RegExp("[," + spaces + "]+"), separator = new RegExp("[," + spaces + "]+"),
whitespace = new RegExp("[" + spaces + "]", "g"), whitespace = new RegExp("[" + spaces + "]", "g"),
commaSpaces = new RegExp("[" + spaces + "]*,[" + spaces + "*]"), commaSpaces = new RegExp("[" + spaces + "]*,[" + spaces + "]*"),
hsrg = {hs: 1, rg: 1}, hsrg = {hs: 1, rg: 1},
p2s = /,?([a-z]),?/gi, p2s = /,?([a-z]),?/gi,
pathCommand = new RegExp("([a-z])[" + spaces + ",]*((-?\\d*\\.?\\d*(?:e[\\-+]?\\d+)?[" + spaces + "]*,?[" + spaces + "]*)+)", "ig"), pathCommand = new RegExp("([a-z])[" + spaces + ",]*((-?\\d*\\.?\\d*(?:e[\\-+]?\\d+)?[" + spaces + "]*,?[" + spaces + "]*)+)", "ig"),
tCommand = new RegExp("([rstm])[" + spaces + ",]*((-?\\d*\\.?\\d*(?:e[\\-+]?\\d+)?[" + spaces + "]*,?[" + spaces + "]*)+)", "ig"), tCommand = new RegExp("([rstm])[" + spaces + ",]*((-?\\d*\\.?\\d*(?:e[\\-+]?\\d+)?[" + spaces + "]*,?[" + spaces + "]*)+)", "ig"),
pathValues = new RegExp("(-?\\d*\\.?\\d*(?:e[\\-+]?\\d+)?)[" + spaces + "]*,?[" + spaces + "]*", "ig"), pathValues = new RegExp("(-?\\d*\\.?\\d*(?:e[\\-+]?\\d+)?)[" + spaces + "]*,?[" + spaces + "]*", "ig"),
radial_gradient = new RegExp("^r(?:\\(([^,]+?)[" + spaces + "]*,[" + spaces + "]*([^\\)]+?)\\))?"),
idgen = 0, idgen = 0,
idprefix = "S" + (+new Date).toString(36), idprefix = "S" + (+new Date).toString(36),
ID = function () { ID = function () {
@ -109,6 +110,24 @@ function is(o, type) {
(type == "array" && Array.isArray && Array.isArray(o)) || (type == "array" && Array.isArray && Array.isArray(o)) ||
objectToString.call(o).slice(8, -1).toLowerCase() == type; objectToString.call(o).slice(8, -1).toLowerCase() == type;
} }
var preload = (function () {
function onerror() {
this.parentNode.removeChild(this);
}
return function (src, f) {
var img = glob.doc.createElement("img"),
body = glob.doc.body;
img.style.cssText = "position:absolute;left:-9999em;top:-9999em";
img.onload = function () {
f.call(img);
img.onload = img.onerror = null;
body.removeChild(img);
};
img.onerror = onerror;
body.appendChild(img);
img.src = src;
};
}());
function clone(obj) { function clone(obj) {
if (typeof obj == "function" || Object(obj) !== obj) { if (typeof obj == "function" || Object(obj) !== obj) {
return obj; return obj;
@ -425,7 +444,7 @@ Savage.Matrix = Matrix;
# <li>Colour name (<code>red</code>, <code>green</code>, <code>cornflowerblue</code>, etc)</li> # <li>Colour name (<code>red</code>, <code>green</code>, <code>cornflowerblue</code>, etc)</li>
# <li># shortened HTML colour: (<code>#000</code>, <code>#fc0</code>, etc)</li> # <li># shortened HTML colour: (<code>#000</code>, <code>#fc0</code>, etc)</li>
# <li># full length HTML colour: (<code>#000000</code>, <code>#bd2300</code>)</li> # <li># full length HTML colour: (<code>#000000</code>, <code>#bd2300</code>)</li>
# <li>rgb(, , ) red, green and blue channels values: (<code>rgb(200,&nbsp;100,&nbsp;0)</code>)</li> # <li>rgb(, , ) red, green and blue channels values: (<code>rgb(200,&nbsp;100,&nbsp;0)</code>)</li>
# <li>rgb(%, %, %) same as above, but in %: (<code>rgb(100%,&nbsp;175%,&nbsp;0%)</code>)</li> # <li>rgb(%, %, %) same as above, but in %: (<code>rgb(100%,&nbsp;175%,&nbsp;0%)</code>)</li>
# <li>hsb(, , ) hue, saturation and brightness values: (<code>hsb(0.5,&nbsp;0.25,&nbsp;1)</code>)</li> # <li>hsb(, , ) hue, saturation and brightness values: (<code>hsb(0.5,&nbsp;0.25,&nbsp;1)</code>)</li>
# <li>hsb(%, %, %) same as above, but in %</li> # <li>hsb(%, %, %) same as above, but in %</li>
@ -438,7 +457,7 @@ Savage.Matrix = Matrix;
o g (number) green, o g (number) green,
o b (number) blue o b (number) blue
o hex (string) color in HTML/CSS format: #, o hex (string) color in HTML/CSS format: #,
o error (boolean) true if string cant be parsed o error (boolean) true if string cant be parsed
o } o }
\*/ \*/
Savage.getRGB = cacher(function (colour) { Savage.getRGB = cacher(function (colour) {
@ -571,7 +590,9 @@ hsltoString = function () {
return "hsl(" + [this.h, this.s, this.l] + ")"; return "hsl(" + [this.h, this.s, this.l] + ")";
}, },
rgbtoString = function () { rgbtoString = function () {
return this.hex; return this.opacity == 1 || this.opacity == null ?
this.hex :
"rgba(" + [this.r, this.g, this.b, this.opacity] + ")";
}, },
prepareRGB = function (r, g, b) { prepareRGB = function (r, g, b) {
if (g == null && is(r, "object") && "r" in r && "g" in r && "b" in r) { if (g == null && is(r, "object") && "r" in r && "g" in r && "b" in r) {
@ -594,9 +615,9 @@ prepareRGB = function (r, g, b) {
return [r, g, b]; return [r, g, b];
}, },
packageRGB = function (r, g, b, o) { packageRGB = function (r, g, b, o) {
r *= 255; r = math.round(r * 255);
g *= 255; g = math.round(g * 255);
b *= 255; b = math.round(b * 255);
var rgb = { var rgb = {
r: r, r: r,
g: g, g: g,
@ -621,7 +642,7 @@ packageRGB = function (r, g, b, o) {
o g (number) green, o g (number) green,
o b (number) blue, o b (number) blue,
o hex (string) color in HTML/CSS format: #, o hex (string) color in HTML/CSS format: #,
o error (boolean) `true` if string cant be parsed, o error (boolean) `true` if string cant be parsed,
o h (number) hue, o h (number) hue,
o s (number) saturation, o s (number) saturation,
o v (number) value (brightness), o v (number) value (brightness),
@ -1696,11 +1717,20 @@ function Element(el) {
el.savage = id; el.savage = id;
hub[id] = this; hub[id] = this;
} }
function arrayFirstValue(arr) {
var res;
for (var i = 0, ii = arr.length; i < ii; i++) {
res = res || arr[i];
if (res) {
return res;
}
}
}
(function (elproto) { (function (elproto) {
elproto.attr = function (params) { elproto.attr = function (params) {
var node = this.node; var node = this.node;
if (is(params, "string")) { if (is(params, "string")) {
return eve("savage.util.getattr." + params, this)[0]; return arrayFirstValue(eve("savage.util.getattr." + params, this));
} }
for (var att in params) { for (var att in params) {
if (params[has](att)) { if (params[has](att)) {
@ -1883,6 +1913,31 @@ function Element(el) {
p.node.appendChild(this.node); p.node.appendChild(this.node);
return p; return p;
}; };
elproto.marker = function (x, y, width, height, refX, refY) {
var p = make("marker", this.paper.defs);
if (x == null) {
x = this.getBBox();
}
if (x && "x" in x) {
y = x.y;
width = x.width;
height = x.height;
refX = x.refX;
refY = x.refY;
x = x.x;
}
$(p.node, {
viewBox: [x, y, width, height].join(S),
markerWidth: width,
markerHeight: height,
orient: "auto",
refX: refX || 0,
refY: refY || 0,
id: p.id
});
p.node.appendChild(this.node);
return p;
};
// animation // animation
function applyAttr(el, key) { function applyAttr(el, key) {
var at = {}; var at = {};
@ -2026,6 +2081,38 @@ function wrap(dom) {
} }
return el; return el;
}; };
proto.image = function (src, x, y, width, height) {
var el = make("image", this.node);
if (is(src, "object") && "src" in src) {
el.attr(src);
} else if (src != null) {
var set = {
"xlink:href": src,
preserveAspectRatio: "none"
};
if (x != null && y != null) {
set.x = x;
set.y = y;
}
if (width != null && height != null) {
set.width = width;
set.height = height;
} else {
preload(src, function () {
$(el.node, {
width: this.offsetWidth,
height: this.offsetHeight
});
});
}
$(el.node, set);
}
return el;
};
proto.custom = function (name) {
var el = make(name, this.node);
return el;
};
proto.ellipse = function (cx, cy, rx, ry) { proto.ellipse = function (cx, cy, rx, ry) {
var el = make("ellipse", this.node); var el = make("ellipse", this.node);
if (is(cx, "object") && "cx" in cx) { if (is(cx, "object") && "cx" in cx) {
@ -2139,7 +2226,7 @@ function wrap(dom) {
// gradients // gradients
(function () { (function () {
proto.gradient = function (str) { proto.gradient = function (str) {
var grad = eve("savage.util.grad.parse", null, str)[0], var grad = arrayFirstValue(eve("savage.util.grad.parse", null, str)),
el; el;
if (grad.type.toLowerCase() == "l") { if (grad.type.toLowerCase() == "l") {
el = this.gradientLinear.apply(this, grad.params); el = this.gradientLinear.apply(this, grad.params);
@ -2147,7 +2234,7 @@ function wrap(dom) {
el = this.gradientRadial.apply(this, grad.params); el = this.gradientRadial.apply(this, grad.params);
} }
if (grad.type != grad.type.toLowerCase()) { if (grad.type != grad.type.toLowerCase()) {
el.attr({ $(el.node, {
gradientUnits: "userSpaceOnUse" gradientUnits: "userSpaceOnUse"
}); });
} }
@ -2195,9 +2282,9 @@ function wrap(dom) {
y2 = $(this.node, "y2") || 0; y2 = $(this.node, "y2") || 0;
return box(x1, y1, math.abs(x2 - x1), math.abs(y2 - y1)); return box(x1, y1, math.abs(x2 - x1), math.abs(y2 - y1));
} else { } else {
var cx = this.node.cx, var cx = this.node.cx || .5,
cy = this.node.cy, cy = this.node.cy || .5,
r = this.node.r; r = this.node.r || 0;
return box(cx - r, cy - r, r * 2, r * 2); return box(cx - r, cy - r, r * 2, r * 2);
} }
} }
@ -2216,6 +2303,26 @@ function wrap(dom) {
} }
return el; return el;
}; };
proto.gradientRadial = function (cx, cy, r, fx, fy) {
var el = make("radialGradient", this.node);
el.stops = stops;
el.addStop = addStop;
el.getBBox = getBBox;
if (cx != null) {
$(el.node, {
cx: cx,
cy: cy,
r: r
});
}
if (fx != null && fy != null) {
$(el.node, {
fx: fx,
fy: fy
});
}
return el;
};
}()); }());
}(Paper.prototype)); }(Paper.prototype));
// Attributes event handlers // Attributes event handlers
@ -2351,6 +2458,15 @@ eve.on("savage.util.attr.transform", function (value) {
this.transform(value); this.transform(value);
eve.stop(); eve.stop();
}); });
eve.on("savage.util.attr.r", function (value) {
if (this.type == "rect") {
eve.stop();
$(this.node, {
rx: value,
ry: value
});
}
});
eve.on("savage.util.attr.text", function (value) { eve.on("savage.util.attr.text", function (value) {
if (this.type == "text") { if (this.type == "text") {
var i = 0, var i = 0,
@ -2376,15 +2492,24 @@ eve.on("savage.util.attr.text", function (value) {
}); });
// default // default
var availableAttributes = { var availableAttributes = {
rect: {x: 0, y: 0, width: 0, height: 0, rx: 0, ry: 0}, rect: {x: 0, y: 0, width: 0, height: 0, rx: 0, ry: 0, "class": 0},
circle: {cx: 0, cy: 0, r: 0}, circle: {cx: 0, cy: 0, r: 0, "class": 0},
ellipse: {cx: 0, cy: 0, rx: 0, ry: 0}, ellipse: {cx: 0, cy: 0, rx: 0, ry: 0, "class": 0},
line: {x1: 0, y1: 0, x2: 0, y2: 0}, line: {x1: 0, y1: 0, x2: 0, y2: 0, "class": 0},
polyline: {points: ""}, polyline: {points: "", "class": 0},
polygon: {points: ""}, polygon: {points: "", "class": 0},
text: {x: 0, y: 0, dx: 0, dy: 0, rotate: 0, textLength: 0}, text: {x: 0, y: 0, dx: 0, dy: 0, rotate: 0, textLength: 0, lengthAdjust: 0, "class": 0},
tspan: {x: 0, y: 0, dx: 0, dy: 0, rotate: 0, textLength: 0}, tspan: {x: 0, y: 0, dx: 0, dy: 0, rotate: 0, textLength: 0, lengthAdjust: 0, "class": 0},
path: {d: ""} textPath: {"xlink:href": 0, startOffset: 0, method: 0, spacing: 0, "class": 0},
marker: {viewBox: 0, preserveAspectRatio: 0, refX: 0, refY: 0, markerUnits: 0, markerWidth: 0, markerHeight: 0, orient: 0, "class": 0},
linearGradient: {x1: 0, y1: 0, x2: 0, y2: 0, gradientUnits: 0, gradientTransform: 0, spreadMethod: 0, "xlink:href": 0, "class": 0},
radialGradient: {cx: 0, cy: 0, r: 0, fx: 0, fy: 0, gradientUnits: 0, gradientTransform: 0, spreadMethod: 0, "xlink:href": 0, "class": 0},
stop: {offset: 0, "class": 0},
pattern: {viewBox: 0, preserveAspectRatio: 0, x: 0, y: 0, width: 0, height: 0, patternUnits: 0, patternContentUnits: 0, patternTransform: 0, "xlink:href": 0, "class": 0},
clipPath: {transform: 0, clipPathUnits: 0, "class": 0},
mask: {x: 0, y: 0, width: 0, height: 0, maskUnits: 0, maskContentUnits: 0, "class": 0},
image: {preserveAspectRatio: 0, transform: 0, x: 0, y: 0, width: 0, height: 0, "xlink:href": 0, "class": 0},
path: {d: "", "class": 0}
}; };
eve.on("savage.util.attr", function (value) { eve.on("savage.util.attr", function (value) {
var att = eve.nt(); var att = eve.nt();
@ -2403,6 +2528,12 @@ eve.on("savage.util.getattr.transform", function () {
eve.stop(); eve.stop();
return this.transform(); return this.transform();
})(-1); })(-1);
eve.on("savage.util.getattr.r", function () {
if (this.type == "rect" && $(this.node, "rx") == $(this.node, "ry")) {
eve.stop();
return $(this.node, "rx");
}
})(-1);
eve.on("savage.util.getattr.viewBox", function () { eve.on("savage.util.getattr.viewBox", function () {
eve.stop(); eve.stop();
var vb = $(this.node, "viewBox").split(separator); var vb = $(this.node, "viewBox").split(separator);
@ -2424,16 +2555,11 @@ eve.on("savage.util.getattr", function () {
if (availableAttributes[has](this.type) && availableAttributes[this.type][has](att)) { if (availableAttributes[has](this.type) && availableAttributes[this.type][has](att)) {
return this.node.getAttribute(att); return this.node.getAttribute(att);
} else { } else {
return document.defaultView.getComputedStyle(this.node, null).getPropertyValue(style); return glob.doc.defaultView.getComputedStyle(this.node, null).getPropertyValue(style);
} }
}); });
eve.on("savage.globals", function () { Savage.plugin = function (f) {
return { f(Savage, Element, Paper, glob);
savage: Savage, };
element: Element,
paper: Paper,
glob: glob
};
});
return Savage; return Savage;
}()); }());

View File

@ -3,19 +3,25 @@
<head> <head>
<meta charset="utf-8"> <meta charset="utf-8">
<title>Savage Tests</title> <title>Savage Tests</title>
<link rel="stylesheet" href="mocha.css" /> <style media="screen">
<script src="../mywork/eve/eve.js"></script> svg {
<script src="mina.js"></script> position: absolute;
<script src="elemental.js"></script> top: -999em;
<script src="svg.js"></script> left: -999em;
<script src="savage.set.js"></script> }
</style>
<link rel="stylesheet" href="mocha/mocha.css">
<script src="../eve/eve.js"></script>
<script src="../mina.js"></script>
<script src="../elemental.js"></script>
<script src="../svg.js"></script>
<script src="../savage.set.js"></script>
</head> </head>
<body> <body>
<div id="mocha"></div> <div id="mocha"></div>
<script src="expect/expect.js"></script>
<script src="expect.js"></script> <script src="mocha/mocha.js"></script>
<script src="mocha.js"></script> <script>mocha.setup("bdd");</script>
<script>mocha.setup('bdd');</script>
<script> <script>
describe("System check", function () { describe("System check", function () {
it("Savage exists", function () { it("Savage exists", function () {
@ -161,6 +167,182 @@
expect(C.textContent).to.be("test"); expect(C.textContent).to.be("test");
}); });
}); });
describe("Colours", function () {
it("parses hex colour", function () {
expect(Savage.color("#fC0").hex).to.be("#ffcc00");
});
it("parses RGB", function () {
var c = Savage.color("rgb(255, 204, 0)");
expect(c.hex).to.be("#ffcc00");
expect(c.r).to.be(255);
expect(c.g).to.be(204);
expect(c.b).to.be(0);
});
it("parses HSL", function () {
var c = Savage.color("hsl(0.1333, 1, .5)");
expect(c.hex).to.be("#ffcc00");
expect(c.h.toFixed(3)).to.be("0.133");
expect(c.s).to.be(1);
expect(c.l).to.be(.5);
});
it("parses HSB", function () {
var c = Savage.color("hsb(0.1333, 1, 1)");
expect(c.hex).to.be("#ffcc00");
expect(c.h.toFixed(3)).to.be("0.133");
expect(c.s).to.be(1);
expect(c.v).to.be(1);
});
it("parses RGBA", function () {
var c = Savage.color("rgba(255, 204, 0, .75)");
expect(c.hex).to.be("#ffcc00");
expect(c.r).to.be(255);
expect(c.g).to.be(204);
expect(c.b).to.be(0);
expect(c.opacity).to.be(.75);
});
it("parses HSLA", function () {
var c = Savage.color("hsla(0.1333, 1, .5, .5)");
expect(c.hex).to.be("#ffcc00");
expect(c.r).to.be(255);
expect(c.g).to.be(204);
expect(c.b).to.be(0);
expect(c.opacity).to.be(.5);
});
it("parses HSBA", function () {
var c = Savage.color("hsba(0.1333, 1, 1, .5)");
expect(c.hex).to.be("#ffcc00");
expect(c.r).to.be(255);
expect(c.g).to.be(204);
expect(c.b).to.be(0);
expect(c.opacity).to.be(.5);
});
it("parses names", function () {
var c = Savage.color("DodgerBlue");
expect(c.hex).to.be("#1e90ff");
c = Savage.color("FireBrick");
expect(c.hex).to.be("#b22222");
c = Savage.color("MintCream");
expect(c.hex).to.be("#f5fffa");
});
});
describe("Attributes", function () {
var s, r;
beforeEach(function () {
s = Savage(100, 100);
r = s.rect(10, 10, 50, 50);
});
afterEach(function () {
s.remove();
});
function colorTestProp(key) {
var o = {};
return function () {
o[key] = "#fc0";
r.attr(o);
expect(r.node.getAttribute(key)).to.be("#ffcc00");
o[key] = "rgb(255, 204, 0)";
r.attr(o);
expect(r.node.getAttribute(key)).to.be("#ffcc00");
o[key] = "hsl(0.1333, 1, .5)";
r.attr(o);
expect(r.node.getAttribute(key)).to.be("#ffcc00");
o[key] = "hsb(0.1333, 1, 1)";
r.attr(o);
expect(r.node.getAttribute(key)).to.be("#ffcc00");
o[key] = "rgba(255, 204, 0, .5)";
r.attr(o);
expect(r.node.getAttribute(key)).to.be("rgba(255,204,0,0.5)");
o[key] = "hsla(0.1333, 1, .5, .5)";
r.attr(o);
expect(r.node.getAttribute(key)).to.be("rgba(255,204,0,0.5)");
o[key] = "hsba(0.1333, 1, 1, .5)";
r.attr(o);
expect(r.node.getAttribute(key)).to.be("rgba(255,204,0,0.5)");
};
}
function colorTestStyle(key) {
var o = {};
return function () {
function val() {
return Savage.color(r.node.style[key]).hex;
}
o[key] = "#fc0";
r.attr(o);
expect(val()).to.be("#ffcc00");
o[key] = "rgb(255, 204, 0)";
r.attr(o);
expect(val()).to.be("#ffcc00");
o[key] = "hsl(0.1333, 1, .5)";
r.attr(o);
expect(val()).to.be("#ffcc00");
o[key] = "hsb(0.1333, 1, 1)";
r.attr(o);
expect(val()).to.be("#ffcc00");
o[key] = "rgba(255, 204, 0, .5)";
r.attr(o);
expect(val()).to.be("#ffcc00");
o[key] = "hsla(0.1333, 1, .5, .5)";
r.attr(o);
expect(val()).to.be("#ffcc00");
o[key] = "hsba(0.1333, 1, 1, .5)";
r.attr(o);
expect(val()).to.be("#ffcc00");
};
}
it("sets fill", colorTestProp("fill"));
it("sets stroke", colorTestStyle("stroke"));
it("circle core attributes", function () {
var c = s.circle(10, 20, 30);
expect(c.node.getAttribute("cx")).to.be("10");
expect(c.node.getAttribute("cy")).to.be("20");
expect(c.node.getAttribute("r")).to.be("30");
c.attr({
cx: 40,
cy: 50,
r: "5%"
});
expect(c.node.getAttribute("cx")).to.be("40");
expect(c.node.getAttribute("cy")).to.be("50");
expect(c.node.getAttribute("r")).to.be("5%");
});
it("rect core attributes", function () {
var c = s.rect(10, 20, 30, 40);
expect(c.node.getAttribute("x")).to.be("10");
expect(c.node.getAttribute("y")).to.be("20");
expect(c.node.getAttribute("width")).to.be("30");
expect(c.node.getAttribute("height")).to.be("40");
c.attr({
x: 40,
y: 50,
width: "5%",
height: "6%",
r: 10
});
expect(c.node.getAttribute("x")).to.be("40");
expect(c.node.getAttribute("y")).to.be("50");
expect(c.node.getAttribute("width")).to.be("5%");
expect(c.node.getAttribute("height")).to.be("6%");
expect(c.node.getAttribute("rx")).to.be("10");
expect(c.node.getAttribute("ry")).to.be("10");
});
it("ellipse core attributes", function () {
var c = s.ellipse(10, 20, 30, 40);
expect(c.node.getAttribute("cx")).to.be("10");
expect(c.node.getAttribute("cy")).to.be("20");
expect(c.node.getAttribute("rx")).to.be("30");
expect(c.node.getAttribute("ry")).to.be("40");
c.attr({
cx: 40,
cy: 50,
rx: "5%",
ry: "6%"
});
expect(c.node.getAttribute("cx")).to.be("40");
expect(c.node.getAttribute("cy")).to.be("50");
expect(c.node.getAttribute("rx")).to.be("5%");
expect(c.node.getAttribute("ry")).to.be("6%");
});
});
</script> </script>
<script> <script>
mocha.checkLeaks(); mocha.checkLeaks();