lib/visage/public/javascripts/raphael.js in visage-app-0.1.8 vs lib/visage/public/javascripts/raphael.js in visage-app-0.2.0

- old
+ new

@@ -1,86 +1,100 @@ /*! - * Raphael 1.3.0 - JavaScript Vector Library + * Raphael 1.4.3 - JavaScript Vector Library * - * Copyright (c) 2008 - 2009 Dmitry Baranovskiy (http://raphaeljs.com) + * Copyright (c) 2010 Dmitry Baranovskiy (http://raphaeljs.com) * Licensed under the MIT (http://www.opensource.org/licenses/mit-license.php) license. */ - -window.Raphael = (function () { +Raphael = (function () { + function R() { + if (R.is(arguments[0], array)) { + var a = arguments[0], + cnv = create[apply](R, a.splice(0, 3 + R.is(a[0], nu))), + res = cnv.set(); + for (var i = 0, ii = a[length]; i < ii; i++) { + var j = a[i] || {}; + elements.test(j.type) && res[push](cnv[j.type]().attr(j)); + } + return res; + } + return create[apply](R, arguments); + } + R.version = "1.4.3"; var separator = /[, ]+/, elements = /^(circle|rect|path|ellipse|text|image)$/, + proto = "prototype", + has = "hasOwnProperty", doc = document, win = window, oldRaphael = { - was: "Raphael" in win, + was: Object[proto][has].call(win, "Raphael"), is: win.Raphael }, - R = function () { - if (R.is(arguments[0], "array")) { - var a = arguments[0], - cnv = create[apply](R, a.splice(0, 3 + R.is(a[0], nu))), - res = cnv.set(); - for (var i = 0, ii = a[length]; i < ii; i++) { - var j = a[i] || {}; - elements.test(j.type) && res[push](cnv[j.type]().attr(j)); - } - return res; - } - return create[apply](R, arguments); - }, Paper = function () {}, appendChild = "appendChild", apply = "apply", concat = "concat", + supportsTouch = "createTouch" in doc, E = "", S = " ", split = "split", - events = "click dblclick mousedown mousemove mouseout mouseover mouseup"[split](S), - has = "hasOwnProperty", + events = "click dblclick mousedown mousemove mouseout mouseover mouseup touchstart touchmove touchend orientationchange touchcancel gesturestart gesturechange gestureend"[split](S), + touchMap = { + mousedown: "touchstart", + mousemove: "touchmove", + mouseup: "touchend" + }, join = "join", length = "length", - proto = "prototype", lowerCase = String[proto].toLowerCase, math = Math, mmax = math.max, mmin = math.min, nu = "number", + string = "string", + array = "array", toString = "toString", + fillString = "fill", objectToString = Object[proto][toString], paper = {}, pow = math.pow, push = "push", rg = /^(?=[\da-f]$)/, - ISURL = /^url\(['"]?([^\)]+)['"]?\)$/i, - colourRegExp = /^\s*((#[a-f\d]{6})|(#[a-f\d]{3})|rgb\(\s*([\d\.]+\s*,\s*[\d\.]+\s*,\s*[\d\.]+)\s*\)|rgb\(\s*([\d\.]+%\s*,\s*[\d\.]+%\s*,\s*[\d\.]+%)\s*\)|hs[bl]\(\s*([\d\.]+\s*,\s*[\d\.]+\s*,\s*[\d\.]+)\s*\)|hs[bl]\(\s*([\d\.]+%\s*,\s*[\d\.]+%\s*,\s*[\d\.]+%)\s*\))\s*$/i, + ISURL = /^url\(['"]?([^\)]+?)['"]?\)$/i, + colourRegExp = /^\s*((#[a-f\d]{6})|(#[a-f\d]{3})|rgba?\(\s*([\d\.]+\s*,\s*[\d\.]+\s*,\s*[\d\.]+(?:\s*,\s*[\d\.]+)?)\s*\)|rgba?\(\s*([\d\.]+%\s*,\s*[\d\.]+%\s*,\s*[\d\.]+%(?:\s*,\s*[\d\.]+%))\s*\)|hs[bl]\(\s*([\d\.]+\s*,\s*[\d\.]+\s*,\s*[\d\.]+)\s*\)|hs[bl]\(\s*([\d\.]+%\s*,\s*[\d\.]+%\s*,\s*[\d\.]+%)\s*\))\s*$/i, round = math.round, setAttribute = "setAttribute", toFloat = parseFloat, toInt = parseInt, + ms = " progid:DXImageTransform.Microsoft", upperCase = String[proto].toUpperCase, - availableAttrs = {"clip-rect": "0 0 1e9 1e9", cursor: "default", cx: 0, cy: 0, fill: "#fff", "fill-opacity": 1, font: '10px "Arial"', "font-family": '"Arial"', "font-size": "10", "font-style": "normal", "font-weight": 400, gradient: 0, height: 0, href: "http://raphaeljs.com/", opacity: 1, path: "M0,0", r: 0, rotation: 0, rx: 0, ry: 0, scale: "1 1", src: "", stroke: "#000", "stroke-dasharray": "", "stroke-linecap": "butt", "stroke-linejoin": "butt", "stroke-miterlimit": 0, "stroke-opacity": 1, "stroke-width": 1, target: "_blank", "text-anchor": "middle", title: "Raphael", translation: "0 0", width: 0, x: 0, y: 0}, - availableAnimAttrs = {along: "along", "clip-rect": "csv", cx: nu, cy: nu, fill: "colour", "fill-opacity": nu, "font-size": nu, height: nu, opacity: nu, path: "path", r: nu, rotation: "csv", rx: nu, ry: nu, scale: "csv", stroke: "colour", "stroke-opacity": nu, "stroke-width": nu, translation: "csv", width: nu, x: nu, y: nu}, + availableAttrs = {blur: 0, "clip-rect": "0 0 1e9 1e9", cursor: "default", cx: 0, cy: 0, fill: "#fff", "fill-opacity": 1, font: '10px "Arial"', "font-family": '"Arial"', "font-size": "10", "font-style": "normal", "font-weight": 400, gradient: 0, height: 0, href: "http://raphaeljs.com/", opacity: 1, path: "M0,0", r: 0, rotation: 0, rx: 0, ry: 0, scale: "1 1", src: "", stroke: "#000", "stroke-dasharray": "", "stroke-linecap": "butt", "stroke-linejoin": "butt", "stroke-miterlimit": 0, "stroke-opacity": 1, "stroke-width": 1, target: "_blank", "text-anchor": "middle", title: "Raphael", translation: "0 0", width: 0, x: 0, y: 0}, + availableAnimAttrs = {along: "along", blur: nu, "clip-rect": "csv", cx: nu, cy: nu, fill: "colour", "fill-opacity": nu, "font-size": nu, height: nu, opacity: nu, path: "path", r: nu, rotation: "csv", rx: nu, ry: nu, scale: "csv", stroke: "colour", "stroke-opacity": nu, "stroke-width": nu, translation: "csv", width: nu, x: nu, y: nu}, rp = "replace"; - R.version = "1.3.0"; R.type = (win.SVGAngle || doc.implementation.hasFeature("http://www.w3.org/TR/SVG11/feature#BasicStructure", "1.1") ? "SVG" : "VML"); if (R.type == "VML") { - var d = document.createElement("div"); + var d = doc.createElement("div"); d.innerHTML = '<!--[if vml]><br><br><![endif]-->'; if (d.childNodes[length] != 2) { - return null; + return R.type = null; } + d = null; } R.svg = !(R.vml = R.type == "VML"); Paper[proto] = R[proto]; R._id = 0; R._oid = 0; R.fn = {}; R.is = function (o, type) { type = lowerCase.call(type); - return ((type == "object" || type == "undefined") && typeof o == type) || (o == null && type == "null") || lowerCase.call(objectToString.call(o).slice(8, -1)) == type; + return (type == "object" && o === Object(o)) || + (type == "undefined" && typeof o == type) || + (type == "null" && o == null) || + lowerCase.call(objectToString.call(o).slice(8, -1)) == type; }; + R.setWindow = function (newwin) { win = newwin; doc = win.document; }; // colour utilities @@ -90,16 +104,16 @@ var trim = /^\s+|\s+$/g; toHex = cacher(function (color) { var bod; color = (color + E)[rp](trim, E); try { - var docum = new ActiveXObject("htmlfile"); + var docum = new win.ActiveXObject("htmlfile"); docum.write("<body>"); docum.close(); bod = docum.body; } catch(e) { - bod = createPopup().document.body; + bod = win.createPopup().document.body; } var range = bod.createTextRange(); try { bod.style.color = color; var value = range.queryCommandValue("ForeColor"); @@ -119,10 +133,16 @@ return doc.defaultView.getComputedStyle(i, E).getPropertyValue("color"); }); } return toHex(color); }; + var hsbtoString = function () { + return "hsb(" + [this.h, this.s, this.b] + ")"; + }, + rgbtoString = function () { + return this.hex; + }; R.hsb2rgb = cacher(function (hue, saturation, brightness) { if (R.is(hue, "object") && "h" in hue && "s" in hue && "b" in hue) { brightness = hue.b; saturation = hue.s; hue = hue.h; @@ -147,11 +167,11 @@ green = [t, brightness, brightness, q, p, p, t][i]; blue = [p, p, t, brightness, brightness, q, p][i]; red *= 255; green *= 255; blue *= 255; - var rgb = {r: red, g: green, b: blue}, + var rgb = {r: red, g: green, b: blue, toString: rgbtoString}, r = (~~red)[toString](16), g = (~~green)[toString](16), b = (~~blue)[toString](16); r = r[rp](rg, "0"); g = g[rp](rg, "0"); @@ -163,11 +183,11 @@ if (R.is(red, "object") && "r" in red && "g" in red && "b" in red) { blue = red.b; green = red.g; red = red.r; } - if (R.is(red, "string")) { + if (R.is(red, string)) { var clr = R.getRGB(red); red = clr.r; green = clr.g; blue = clr.b; } @@ -195,13 +215,15 @@ } hue /= 6; hue < 0 && hue++; hue > 1 && hue--; } - return {h: hue, s: saturation, b: brightness}; + return {h: hue, s: saturation, b: brightness, toString: hsbtoString}; }, R); - var p2s = /,?([achlmqrstvxz]),?/gi; + var p2s = /,?([achlmqrstvxz]),?/gi, + commaSpaces = /\s*,\s*/, + hsrg = {hs: 1, rg: 1}; R._path2string = function () { return this.join(",")[rp](p2s, "$1"); }; function cacher(f, scope, postprocessor) { function newf() { @@ -225,15 +247,16 @@ return {r: -1, g: -1, b: -1, hex: "none", error: 1}; } if (colour == "none") { return {r: -1, g: -1, b: -1, hex: "none"}; } - !(({hs: 1, rg: 1})[has](colour.substring(0, 2)) || colour.charAt() == "#") && (colour = toHex(colour)); + !(hsrg[has](colour.substring(0, 2)) || colour.charAt() == "#") && (colour = toHex(colour)); var res, red, green, blue, + opacity, t, rgb = colour.match(colourRegExp); if (rgb) { if (rgb[2]) { blue = toInt(rgb[2].substring(5), 16); @@ -244,30 +267,32 @@ blue = toInt((t = rgb[3].charAt(3)) + t, 16); green = toInt((t = rgb[3].charAt(2)) + t, 16); red = toInt((t = rgb[3].charAt(1)) + t, 16); } if (rgb[4]) { - rgb = rgb[4][split](/\s*,\s*/); + rgb = rgb[4][split](commaSpaces); red = toFloat(rgb[0]); green = toFloat(rgb[1]); blue = toFloat(rgb[2]); + opacity = toFloat(rgb[3]); } if (rgb[5]) { - rgb = rgb[5][split](/\s*,\s*/); + rgb = rgb[5][split](commaSpaces); red = toFloat(rgb[0]) * 2.55; green = toFloat(rgb[1]) * 2.55; blue = toFloat(rgb[2]) * 2.55; + opacity = toFloat(rgb[3]); } if (rgb[6]) { - rgb = rgb[6][split](/\s*,\s*/); + rgb = rgb[6][split](commaSpaces); red = toFloat(rgb[0]); green = toFloat(rgb[1]); blue = toFloat(rgb[2]); return R.hsb2rgb(red, green, blue); } if (rgb[7]) { - rgb = rgb[7][split](/\s*,\s*/); + rgb = rgb[7][split](commaSpaces); red = toFloat(rgb[0]) * 2.55; green = toFloat(rgb[1]) * 2.55; blue = toFloat(rgb[2]) * 2.55; return R.hsb2rgb(red, green, blue); } @@ -277,10 +302,11 @@ b = (~~blue)[toString](16); r = r[rp](rg, "0"); g = g[rp](rg, "0"); b = b[rp](rg, "0"); rgb.hex = "#" + r + g + b; + isFinite(toFloat(opacity)) && (rgb.o = opacity); return rgb; } return {r: -1, g: -1, b: -1, hex: "none", error: 1}; }, R); R.getColor = function (value) { @@ -296,31 +322,38 @@ }; R.getColor.reset = function () { delete this.start; }; // path utilities + var pathCommand = /([achlmqstvz])[\s,]*((-?\d*\.?\d*(?:e[-+]?\d+)?\s*,?\s*)+)/ig, + pathValues = /(-?\d*\.?\d*(?:e[-+]?\d+)?)\s*,?\s*/ig; R.parsePathString = cacher(function (pathString) { if (!pathString) { return null; } var paramCounts = {a: 7, c: 6, h: 1, l: 2, m: 2, q: 4, s: 4, t: 2, v: 1, z: 0}, data = []; - if (R.is(pathString, "array") && R.is(pathString[0], "array")) { // rough assumption + if (R.is(pathString, array) && R.is(pathString[0], array)) { // rough assumption data = pathClone(pathString); } if (!data[length]) { - (pathString + E)[rp](/([achlmqstvz])[\s,]*((-?\d*\.?\d*(?:e[-+]?\d+)?\s*,?\s*)+)/ig, function (a, b, c) { + (pathString + E)[rp](pathCommand, function (a, b, c) { var params = [], name = lowerCase.call(b); - c[rp](/(-?\d*\.?\d*(?:e[-+]?\d+)?)\s*,?\s*/ig, function (a, b) { + c[rp](pathValues, function (a, b) { b && params[push](+b); }); + if (name == "m" && params[length] > 2) { + data[push]([b][concat](params.splice(0, 2))); + name = "l"; + b = b == "m" ? "l" : "L"; + } while (params[length] >= paramCounts[name]) { data[push]([b][concat](params.splice(0, paramCounts[name]))); if (!paramCounts[name]) { break; - }; + } } }); } data[toString] = R._path2string; return data; @@ -375,11 +408,11 @@ height: mmax[apply](0, Y) - ymin }; }), pathClone = function (pathArray) { var res = []; - if (!R.is(pathArray, "array") || !R.is(pathArray && pathArray[0], "array")) { // rough assumption + if (!R.is(pathArray, array) || !R.is(pathArray && pathArray[0], array)) { // rough assumption pathArray = R.parsePathString(pathArray); } for (var i = 0, ii = pathArray[length]; i < ii; i++) { res[i] = []; for (var j = 0, jj = pathArray[i][length]; j < jj; j++) { @@ -388,11 +421,11 @@ } res[toString] = R._path2string; return res; }, pathToRelative = cacher(function (pathArray) { - if (!R.is(pathArray, "array") || !R.is(pathArray && pathArray[0], "array")) { // rough assumption + if (!R.is(pathArray, array) || !R.is(pathArray && pathArray[0], array)) { // rough assumption pathArray = R.parsePathString(pathArray); } var res = [], x = 0, y = 0, @@ -462,11 +495,11 @@ } res[toString] = R._path2string; return res; }, 0, pathClone), pathToAbsolute = cacher(function (pathArray) { - if (!R.is(pathArray, "array") || !R.is(pathArray && pathArray[0], "array")) { // rough assumption + if (!R.is(pathArray, array) || !R.is(pathArray && pathArray[0], array)) { // rough assumption pathArray = R.parsePathString(pathArray); } var res = [], x = 0, y = 0, @@ -571,21 +604,25 @@ y2 = xy.y; var cos = math.cos(PI / 180 * angle), sin = math.sin(PI / 180 * angle), x = (x1 - x2) / 2, y = (y1 - y2) / 2; - rx = mmax(rx, math.abs(x)); - ry = mmax(ry, math.abs(y)); + var h = (x * x) / (rx * rx) + (y * y) / (ry * ry); + if (h > 1) { + h = math.sqrt(h); + rx = h * rx; + ry = h * ry; + } var rx2 = rx * rx, ry2 = ry * ry, k = (large_arc_flag == sweep_flag ? -1 : 1) * math.sqrt(math.abs((rx2 * ry2 - rx2 * y * y - ry2 * x * x) / (rx2 * y * y + ry2 * x * x))), cx = k * rx * y / ry + (x1 + x2) / 2, cy = k * -ry * x / rx + (y1 + y2) / 2, f1 = math.asin(((y1 - cy) / ry).toFixed(7)), f2 = math.asin(((y2 - cy) / ry).toFixed(7)); - + f1 = x1 < cx ? PI - f1 : f1; f2 = x2 < cx ? PI - f2 : f2; f1 < 0 && (f1 = PI * 2 + f1); f2 < 0 && (f2 = PI * 2 + f2); if (sweep_flag && f1 > f2) { @@ -788,11 +825,11 @@ } dot.color = dot.color.hex; par[2] && (dot.offset = par[2] + "%"); dots[push](dot); } - for (var i = 1, ii = dots[length] - 1; i < ii; i++) { + for (i = 1, ii = dots[length] - 1; i < ii; i++) { if (!dots[i].offset) { var start = toFloat(dots[i - 1].offset || 0), end = 0; for (var j = i + 1; j < ii; j++) { if (dots[j].offset) { @@ -812,53 +849,47 @@ } } } return dots; }), - getContainer = function () { - var container, - x, - y, - width, - height; - if (R.is(arguments[0], "string") || R.is(arguments[0], "object")) { - if (R.is(arguments[0], "string")) { - container = doc.getElementById(arguments[0]); - } else { - container = arguments[0]; - } + getContainer = function (x, y, w, h) { + var container; + if (R.is(x, string) || R.is(x, "object")) { + container = R.is(x, string) ? doc.getElementById(x) : x; if (container.tagName) { - if (arguments[1] == null) { + if (y == null) { return { container: container, width: container.style.pixelWidth || container.offsetWidth, height: container.style.pixelHeight || container.offsetHeight }; } else { - return {container: container, width: arguments[1], height: arguments[2]}; + return {container: container, width: y, height: w}; } } - } else if (R.is(arguments[0], nu) && arguments[length] > 3) { - return {container: 1, x: arguments[0], y: arguments[1], width: arguments[2], height: arguments[3]}; + } else { + return {container: 1, x: x, y: y, width: w, height: h}; } }, plugins = function (con, add) { var that = this; - for (var prop in add) if (add[has](prop) && !(prop in con)) { - switch (typeof add[prop]) { - case "function": - (function (f) { - con[prop] = con === that ? f : function () { return f[apply](that, arguments); }; - })(add[prop]); - break; - case "object": - con[prop] = con[prop] || {}; - plugins.call(this, con[prop], add[prop]); - break; - default: - con[prop] = add[prop]; - break; + for (var prop in add) { + if (add[has](prop) && !(prop in con)) { + switch (typeof add[prop]) { + case "function": + (function (f) { + con[prop] = con === that ? f : function () { return f[apply](that, arguments); }; + })(add[prop]); + break; + case "object": + con[prop] = con[prop] || {}; + plugins.call(this, con[prop], add[prop]); + break; + default: + con[prop] = add[prop]; + break; + } } } }, tear = function (el, paper) { el == paper.top && (paper.top = el.prev); @@ -911,35 +942,26 @@ // SVG if (R.svg) { Paper[proto].svgns = "http://www.w3.org/2000/svg"; Paper[proto].xlink = "http://www.w3.org/1999/xlink"; - var round = function (num) { + round = function (num) { return +num + (~~num === num) * .5; - }, - roundPath = function (path) { - for (var i = 0, ii = path[length]; i < ii; i++) { - if (lowerCase.call(path[i][0]) != "a") { - for (var j = 1, jj = path[i][length]; j < jj; j++) { - path[i][j] = round(path[i][j]); - } - } else { - path[i][6] = round(path[i][6]); - path[i][7] = round(path[i][7]); + }; + var $ = function (el, attr) { + if (attr) { + for (var key in attr) { + if (attr[has](key)) { + el[setAttribute](key, attr[key] + E); } } - return path; - }, - $ = function (el, attr) { - if (attr) { - for (var key in attr) if (attr[has](key)) { - el[setAttribute](key, attr[key]); - } - } else { - return doc.createElementNS(Paper[proto].svgns, el); - } - }; + } else { + el = doc.createElementNS(Paper[proto].svgns, el); + el.style.webkitTapHighlightColor = "rgba(0,0,0,0)"; + return el; + } + }; R[toString] = function () { return "Your browser supports SVG.\nYou are running Rapha\xebl " + this.version; }; var thePath = function (pathString, SVG) { var el = $("path"); @@ -988,10 +1010,14 @@ } var dots = parseDots(gradient); if (!dots) { return null; } + var id = o.getAttribute(fillString); + id = id.match(/^url\(#(.*)\)$/); + id && SVG.defs.removeChild(doc.getElementById(id[1])); + var el = $(type + "Gradient"); el.id = "r" + (R._id++)[toString](36); $(el, type == "radial" ? {fx: fx, fy: fy} : {x1: vector[0], y1: vector[1], x2: vector[2], y2: vector[3]}); SVG.defs[appendChild](el); for (var i = 0, ii = dots[length]; i < ii; i++) { @@ -999,11 +1025,11 @@ $(stop, { offset: dots[i].offset ? dots[i].offset : !i ? "0%" : "100%", "stop-color": dots[i].color || "#fff" }); el[appendChild](stop); - }; + } $(o, { fill: "url(#" + el.id + ")", opacity: 1, "fill-opacity": 1 }); @@ -1054,225 +1080,232 @@ } else { rotxy[1] = +rotxy[1]; rotxy[2] = +rotxy[2]; } toFloat(rot) && o.rotate(0, true); - for (var att in params) if (params[has](att)) { - if (!availableAttrs[has](att)) { - continue; - } - var value = params[att]; - attrs[att] = value; - switch (att) { - case "rotation": - o.rotate(value, true); - break; - // Hyperlink - case "href": - case "title": - case "target": - var pn = node.parentNode; - if (lowerCase.call(pn.tagName) != "a") { - var hl = $("a"); - pn.insertBefore(hl, node); - hl[appendChild](node); - pn = hl; - } - pn.setAttributeNS(o.Paper[proto].xlink, att, value); - break; - case "cursor": - node.style.cursor = value; - break; - case "clip-rect": - var rect = (value + E)[split](separator); - if (rect[length] == 4) { - o.clip && o.clip.parentNode.parentNode.removeChild(o.clip.parentNode); - var el = $("clipPath"), - rc = $("rect"); - el.id = "r" + (R._id++)[toString](36); - $(rc, { - x: rect[0], - y: rect[1], - width: rect[2], - height: rect[3] - }); - el[appendChild](rc); - o.paper.defs[appendChild](el); - $(node, {"clip-path": "url(#" + el.id + ")"}); - o.clip = rc; - } - if (!value) { - var clip = doc.getElementById(node.getAttribute("clip-path")[rp](/(^url\(#|\)$)/g, E)); - clip && clip.parentNode.removeChild(clip); - $(node, {"clip-path": E}); - delete o.clip; - } - break; - case "path": - if (value && o.type == "path") { - attrs.path = roundPath(pathToAbsolute(value)); - $(node, {d: attrs.path}); - } - break; - case "width": - node[setAttribute](att, value); - if (attrs.fx) { - att = "x"; - value = attrs.x; - } else { + for (var att in params) { + if (params[has](att)) { + if (!availableAttrs[has](att)) { + continue; + } + var value = params[att]; + attrs[att] = value; + switch (att) { + case "blur": + o.blur(value); break; - } - case "x": - if (attrs.fx) { - value = -attrs.x - (attrs.width || 0); - } - case "rx": - if (att == "rx" && o.type == "rect") { + case "rotation": + o.rotate(value, true); break; - } - case "cx": - rotxy && (att == "x" || att == "cx") && (rotxy[1] += value - attrs[att]); - node[setAttribute](att, round(value)); - o.pattern && updatePosition(o); - break; - case "height": - node[setAttribute](att, value); - if (attrs.fy) { - att = "y"; - value = attrs.y; - } else { + case "href": + case "title": + case "target": + var pn = node.parentNode; + if (lowerCase.call(pn.tagName) != "a") { + var hl = $("a"); + pn.insertBefore(hl, node); + hl[appendChild](node); + pn = hl; + } + pn.setAttributeNS(o.paper.xlink, att, value); break; - } - case "y": - if (attrs.fy) { - value = -attrs.y - (attrs.height || 0); - } - case "ry": - if (att == "ry" && o.type == "rect") { + case "cursor": + node.style.cursor = value; break; - } - case "cy": - rotxy && (att == "y" || att == "cy") && (rotxy[2] += value - attrs[att]); - node[setAttribute](att, round(value)); - o.pattern && updatePosition(o); + case "clip-rect": + var rect = (value + E)[split](separator); + if (rect[length] == 4) { + o.clip && o.clip.parentNode.parentNode.removeChild(o.clip.parentNode); + var el = $("clipPath"), + rc = $("rect"); + el.id = "r" + (R._id++)[toString](36); + $(rc, { + x: rect[0], + y: rect[1], + width: rect[2], + height: rect[3] + }); + el[appendChild](rc); + o.paper.defs[appendChild](el); + $(node, {"clip-path": "url(#" + el.id + ")"}); + o.clip = rc; + } + if (!value) { + var clip = doc.getElementById(node.getAttribute("clip-path")[rp](/(^url\(#|\)$)/g, E)); + clip && clip.parentNode.removeChild(clip); + $(node, {"clip-path": E}); + delete o.clip; + } break; - case "r": - if (o.type == "rect") { - $(node, {rx: value, ry: value}); - } else { + case "path": + if (o.type == "path") { + $(node, {d: value ? attrs.path = pathToAbsolute(value) : "M0,0"}); + } + break; + case "width": node[setAttribute](att, value); - } - break; - case "src": - if (o.type == "image") { - node.setAttributeNS(o.paper.xlink, "href", value); - } - break; - case "stroke-width": - node.style.strokeWidth = value; - // Need following line for Firefox - node[setAttribute](att, value); - if (attrs["stroke-dasharray"]) { - addDashes(o, attrs["stroke-dasharray"]); - } - break; - case "stroke-dasharray": - addDashes(o, value); - break; - case "translation": - var xy = (value + E)[split](separator); - xy[0] = +xy[0] || 0; - xy[1] = +xy[1] || 0; - if (rotxy) { - rotxy[1] += xy[0]; - rotxy[2] += xy[1]; - } - translate.call(o, xy[0], xy[1]); - break; - case "scale": - var xy = (value + E)[split](separator); - o.scale(+xy[0] || 1, +xy[1] || +xy[0] || 1, +xy[2] || null, +xy[3] || null); - break; - case "fill": - var isURL = (value + E).match(ISURL); - if (isURL) { - var el = $("pattern"), - ig = $("image"); - el.id = "r" + (R._id++)[toString](36); - $(el, {x: 0, y: 0, patternUnits: "userSpaceOnUse", height: 1, width: 1}); - $(ig, {x: 0, y: 0}); - ig.setAttributeNS(o.paper.xlink, "href", isURL[1]); - el[appendChild](ig); - - var img = doc.createElement("img"); - img.style.cssText = "position:absolute;left:-9999em;top-9999em"; - img.onload = function () { - $(el, {width: this.offsetWidth, height: this.offsetHeight}); - $(ig, {width: this.offsetWidth, height: this.offsetHeight}); - doc.body.removeChild(this); - o.paper.safari(); - }; - doc.body[appendChild](img); - img.src = isURL[1]; - o.paper.defs[appendChild](el); - node.style.fill = "url(#" + el.id + ")"; - $(node, {fill: "url(#" + el.id + ")"}); - o.pattern = el; + if (attrs.fx) { + att = "x"; + value = attrs.x; + } else { + break; + } + case "x": + if (attrs.fx) { + value = -attrs.x - (attrs.width || 0); + } + case "rx": + if (att == "rx" && o.type == "rect") { + break; + } + case "cx": + rotxy && (att == "x" || att == "cx") && (rotxy[1] += value - attrs[att]); + node[setAttribute](att, round(value)); o.pattern && updatePosition(o); break; - } - if (!R.getRGB(value).error) { - delete params.gradient; - delete attrs.gradient; - !R.is(attrs.opacity, "undefined") && - R.is(params.opacity, "undefined") && - $(node, {opacity: attrs.opacity}); - !R.is(attrs["fill-opacity"], "undefined") && - R.is(params["fill-opacity"], "undefined") && - $(node, {"fill-opacity": attrs["fill-opacity"]}); - } else if ((({circle: 1, ellipse: 1})[has](o.type) || (value + E).charAt() != "r") && addGradientFill(node, value, o.paper)) { - attrs.gradient = value; - attrs.fill = "none"; + case "height": + node[setAttribute](att, value); + if (attrs.fy) { + att = "y"; + value = attrs.y; + } else { + break; + } + case "y": + if (attrs.fy) { + value = -attrs.y - (attrs.height || 0); + } + case "ry": + if (att == "ry" && o.type == "rect") { + break; + } + case "cy": + rotxy && (att == "y" || att == "cy") && (rotxy[2] += value - attrs[att]); + node[setAttribute](att, round(value)); + o.pattern && updatePosition(o); break; - } - case "stroke": - node[setAttribute](att, R.getRGB(value).hex); - break; - case "gradient": - (({circle: 1, ellipse: 1})[has](o.type) || (value + E).charAt() != "r") && addGradientFill(node, value, o.paper); - break; - case "opacity": - case "fill-opacity": - if (attrs.gradient) { - var gradient = doc.getElementById(node.getAttribute("fill")[rp](/^url\(#|\)$/g, E)); - if (gradient) { - var stops = gradient.getElementsByTagName("stop"); - stops[stops[length] - 1][setAttribute]("stop-opacity", value); + case "r": + if (o.type == "rect") { + $(node, {rx: value, ry: value}); + } else { + node[setAttribute](att, value); } break; - } - default: - att == "font-size" && (value = toInt(value, 10) + "px"); - var cssrule = att[rp](/(\-.)/g, function (w) { - return upperCase.call(w.substring(1)); - }); - node.style[cssrule] = value; - // Need following line for Firefox - node[setAttribute](att, value); - break; + case "src": + if (o.type == "image") { + node.setAttributeNS(o.paper.xlink, "href", value); + } + break; + case "stroke-width": + node.style.strokeWidth = value; + // Need following line for Firefox + node[setAttribute](att, value); + if (attrs["stroke-dasharray"]) { + addDashes(o, attrs["stroke-dasharray"]); + } + break; + case "stroke-dasharray": + addDashes(o, value); + break; + case "translation": + var xy = (value + E)[split](separator); + xy[0] = +xy[0] || 0; + xy[1] = +xy[1] || 0; + if (rotxy) { + rotxy[1] += xy[0]; + rotxy[2] += xy[1]; + } + translate.call(o, xy[0], xy[1]); + break; + case "scale": + xy = (value + E)[split](separator); + o.scale(+xy[0] || 1, +xy[1] || +xy[0] || 1, isNaN(toFloat(xy[2])) ? null : +xy[2], isNaN(toFloat(xy[3])) ? null : +xy[3]); + break; + case fillString: + var isURL = (value + E).match(ISURL); + if (isURL) { + el = $("pattern"); + var ig = $("image"); + el.id = "r" + (R._id++)[toString](36); + $(el, {x: 0, y: 0, patternUnits: "userSpaceOnUse", height: 1, width: 1}); + $(ig, {x: 0, y: 0}); + ig.setAttributeNS(o.paper.xlink, "href", isURL[1]); + el[appendChild](ig); + + var img = doc.createElement("img"); + img.style.cssText = "position:absolute;left:-9999em;top-9999em"; + img.onload = function () { + $(el, {width: this.offsetWidth, height: this.offsetHeight}); + $(ig, {width: this.offsetWidth, height: this.offsetHeight}); + doc.body.removeChild(this); + o.paper.safari(); + }; + doc.body[appendChild](img); + img.src = isURL[1]; + o.paper.defs[appendChild](el); + node.style.fill = "url(#" + el.id + ")"; + $(node, {fill: "url(#" + el.id + ")"}); + o.pattern = el; + o.pattern && updatePosition(o); + break; + } + var clr = R.getRGB(value); + if (!clr.error) { + delete params.gradient; + delete attrs.gradient; + !R.is(attrs.opacity, "undefined") && + R.is(params.opacity, "undefined") && + $(node, {opacity: attrs.opacity}); + !R.is(attrs["fill-opacity"], "undefined") && + R.is(params["fill-opacity"], "undefined") && + $(node, {"fill-opacity": attrs["fill-opacity"]}); + } else if ((({circle: 1, ellipse: 1})[has](o.type) || (value + E).charAt() != "r") && addGradientFill(node, value, o.paper)) { + attrs.gradient = value; + attrs.fill = "none"; + break; + } + clr[has]("o") && $(node, {"fill-opacity": clr.o / 100}); + case "stroke": + clr = R.getRGB(value); + node[setAttribute](att, clr.hex); + att == "stroke" && clr[has]("o") && $(node, {"stroke-opacity": clr.o / 100}); + break; + case "gradient": + (({circle: 1, ellipse: 1})[has](o.type) || (value + E).charAt() != "r") && addGradientFill(node, value, o.paper); + break; + case "opacity": + case "fill-opacity": + if (attrs.gradient) { + var gradient = doc.getElementById(node.getAttribute(fillString)[rp](/^url\(#|\)$/g, E)); + if (gradient) { + var stops = gradient.getElementsByTagName("stop"); + stops[stops[length] - 1][setAttribute]("stop-opacity", value); + } + break; + } + default: + att == "font-size" && (value = toInt(value, 10) + "px"); + var cssrule = att[rp](/(\-.)/g, function (w) { + return upperCase.call(w.substring(1)); + }); + node.style[cssrule] = value; + // Need following line for Firefox + node[setAttribute](att, value); + break; + } } } tuneText(o, params); if (rotxy) { o.rotate(rotxy.join(S)); } else { toFloat(rot) && o.rotate(rot, true); } }; - var leading = 1.2; - var tuneText = function (el, params) { + var leading = 1.2, + tuneText = function (el, params) { if (el.type != "text" || !(params[has]("text") || params[has]("font") || params[has]("font-size") || params[has]("x") || params[has]("y"))) { return; } var a = el.attrs, node = el.node, @@ -1289,21 +1322,21 @@ i && $(tspan, {dy: fontSize * leading, x: a.x}); tspan[appendChild](doc.createTextNode(texts[i])); node[appendChild](tspan); } } else { - var texts = node.getElementsByTagName("tspan"); - for (var i = 0, ii = texts[length]; i < ii; i++) { + texts = node.getElementsByTagName("tspan"); + for (i = 0, ii = texts[length]; i < ii; i++) { i && $(texts[i], {dy: fontSize * leading, x: a.x}); } } $(node, {y: a.y}); var bb = el.getBBox(), dif = a.y - (bb.y + bb.height / 2); dif && isFinite(dif) && $(node, {y: a.y + dif}); - }; - var Element = function (node, svg) { + }, + Element = function (node, svg) { var X = 0, Y = 0; this[0] = node; this.id = R._oid++; this.node = node; @@ -1409,52 +1442,52 @@ } } hide && this.hide(); return bbox; }; - Element[proto].attr = function () { + Element[proto].attr = function (name, value) { if (this.removed) { return this; } - if (arguments[length] == 0) { + if (name == null) { var res = {}; for (var i in this.attrs) if (this.attrs[has](i)) { res[i] = this.attrs[i]; } this._.rt.deg && (res.rotation = this.rotate()); (this._.sx != 1 || this._.sy != 1) && (res.scale = this.scale()); res.gradient && res.fill == "none" && (res.fill = res.gradient) && delete res.gradient; return res; } - if (arguments[length] == 1 && R.is(arguments[0], "string")) { - if (arguments[0] == "translation") { + if (value == null && R.is(name, string)) { + if (name == "translation") { return translate.call(this); } - if (arguments[0] == "rotation") { + if (name == "rotation") { return this.rotate(); } - if (arguments[0] == "scale") { + if (name == "scale") { return this.scale(); } - if (arguments[0] == "fill" && this.attrs.fill == "none" && this.attrs.gradient) { + if (name == fillString && this.attrs.fill == "none" && this.attrs.gradient) { return this.attrs.gradient; } - return this.attrs[arguments[0]]; + return this.attrs[name]; } - if (arguments[length] == 1 && R.is(arguments[0], "array")) { + if (value == null && R.is(name, array)) { var values = {}; - for (var j in arguments[0]) if (arguments[0][has](j)) { - values[arguments[0][j]] = this.attrs[arguments[0][j]]; + for (var j = 0, jj = name.length; j < jj; j++) { + values[name[j]] = this.attr(name[j]); } return values; } - if (arguments[length] == 2) { + if (value != null) { var params = {}; - params[arguments[0]] = arguments[1]; + params[name] = value; setFillAndStroke(this, params); - } else if (arguments[length] == 1 && R.is(arguments[0], "object")) { - setFillAndStroke(this, arguments[0]); + } else if (name != null && R.is(name, "object")) { + setFillAndStroke(this, name); } return this; }; Element[proto].toFront = function () { if (this.removed) { @@ -1496,10 +1529,32 @@ var node = element.node; node.parentNode.insertBefore(this.node, node); insertbefore(this, element, this.paper); return this; }; + Element[proto].blur = function (size) { + // Experimental. No Safari support. Use it on your own risk. + var t = this; + if (+size !== 0) { + var fltr = $("filter"), + blur = $("feGaussianBlur"); + t.attrs.blur = size; + fltr.id = "r" + (R._id++)[toString](36); + $(blur, {stdDeviation: +size || 1.5}); + fltr.appendChild(blur); + t.paper.defs.appendChild(fltr); + t._blur = fltr; + $(t.node, {filter: "url(#" + fltr.id + ")"}); + } else { + if (t._blur) { + t._blur.parentNode.removeChild(t._blur); + delete t._blur; + delete t.attrs.blur; + } + t.node.removeAttribute("filter"); + } + }; var theCircle = function (svg, x, y, r) { x = round(x); y = round(y); var el = $("circle"); svg.canvas && svg.canvas[appendChild](el); @@ -1557,20 +1612,22 @@ this.canvas[setAttribute]("width", this.width); this.canvas[setAttribute]("height", this.height); return this; }; var create = function () { - var con = getContainer[apply](null, arguments), + var con = getContainer[apply](0, arguments), container = con && con.container, x = con.x, y = con.y, width = con.width, height = con.height; if (!container) { throw new Error("SVG container not found."); } var cnvs = $("svg"); + x = x || 0; + y = y || 0; width = width || 512; height = height || 342; $(cnvs, { xmlns: "http://www.w3.org/2000/svg", version: 1.1, @@ -1610,84 +1667,105 @@ for (var i in this) { this[i] = removed(i); } }; } - + // VML if (R.vml) { - var path2vml = function (path) { - var total = /[ahqstv]/ig, - command = pathToAbsolute; - (path + E).match(total) && (command = path2curve); - total = /[clmz]/g; - if (command == pathToAbsolute && !(path + E).match(total)) { - var map = {M: "m", L: "l", C: "c", Z: "x", m: "t", l: "r", c: "v", z: "x"}, - bites = /([clmz]),?([^clmz]*)/gi, - val = /-?[^,\s-]+/g; - var res = (path + E)[rp](bites, function (all, command, args) { - var vals = []; - args[rp](val, function (value) { - vals[push](round(value)); + var map = {M: "m", L: "l", C: "c", Z: "x", m: "t", l: "r", c: "v", z: "x"}, + bites = /([clmz]),?([^clmz]*)/gi, + val = /-?[^,\s-]+/g, + coordsize = 1e3 + S + 1e3, + zoom = 10, + pathlike = {path: 1, rect: 1}, + path2vml = function (path) { + var total = /[ahqstv]/ig, + command = pathToAbsolute; + (path + E).match(total) && (command = path2curve); + total = /[clmz]/g; + if (command == pathToAbsolute && !(path + E).match(total)) { + var res = (path + E)[rp](bites, function (all, command, args) { + var vals = [], + isMove = lowerCase.call(command) == "m", + res = map[command]; + args[rp](val, function (value) { + if (isMove && vals[length] == 2) { + res += vals + map[command == "m" ? "l" : "L"]; + vals = []; + } + vals[push](round(value * zoom)); + }); + return res + vals; }); - return map[command] + vals; - }); - return res; - } - var pa = command(path), p, res = [], r; - for (var i = 0, ii = pa[length]; i < ii; i++) { - p = pa[i]; - r = lowerCase.call(pa[i][0]); - r == "z" && (r = "x"); - for (var j = 1, jj = p[length]; j < jj; j++) { - r += round(p[j]) + (j != jj - 1 ? "," : E); + return res; } - res[push](r); - } - return res[join](S); - }; + var pa = command(path), p, r; + res = []; + for (var i = 0, ii = pa[length]; i < ii; i++) { + p = pa[i]; + r = lowerCase.call(pa[i][0]); + r == "z" && (r = "x"); + for (var j = 1, jj = p[length]; j < jj; j++) { + r += round(p[j] * zoom) + (j != jj - 1 ? "," : E); + } + res[push](r); + } + return res[join](S); + }; R[toString] = function () { return "Your browser doesn\u2019t support SVG. Falling down to VML.\nYou are running Rapha\xebl " + this.version; }; - var thePath = function (pathString, VML) { + thePath = function (pathString, vml) { var g = createNode("group"); - g.style.cssText = "position:absolute;left:0;top:0;width:" + VML.width + "px;height:" + VML.height + "px"; - g.coordsize = VML.coordsize; - g.coordorigin = VML.coordorigin; + g.style.cssText = "position:absolute;left:0;top:0;width:" + vml.width + "px;height:" + vml.height + "px"; + g.coordsize = vml.coordsize; + g.coordorigin = vml.coordorigin; var el = createNode("shape"), ol = el.style; - ol.width = VML.width + "px"; - ol.height = VML.height + "px"; - el.coordsize = this.coordsize; - el.coordorigin = this.coordorigin; + ol.width = vml.width + "px"; + ol.height = vml.height + "px"; + el.coordsize = coordsize; + el.coordorigin = vml.coordorigin; g[appendChild](el); - var p = new Element(el, g, VML); + var p = new Element(el, g, vml), + attr = {fill: "none", stroke: "#000"}; + pathString && (attr.path = pathString); p.isAbsolute = true; p.type = "path"; p.path = []; p.Path = E; - pathString && setFillAndStroke(p, {fill: "none", stroke: "#000", path: pathString}); - VML.canvas[appendChild](g); + setFillAndStroke(p, attr); + vml.canvas[appendChild](g); return p; }; - var setFillAndStroke = function (o, params) { + setFillAndStroke = function (o, params) { o.attrs = o.attrs || {}; var node = o.node, a = o.attrs, s = node.style, xy, + newpath = (params.x != a.x || params.y != a.y || params.width != a.width || params.height != a.height || params.r != a.r) && o.type == "rect", res = o; + for (var par in params) if (params[has](par)) { a[par] = params[par]; } + if (newpath) { + a.path = rectPath(a.x, a.y, a.width, a.height, a.r); + o.X = a.x; + o.Y = a.y; + o.W = a.width; + o.H = a.height; + } params.href && (node.href = params.href); params.title && (node.title = params.title); params.target && (node.target = params.target); params.cursor && (s.cursor = params.cursor); - if (params.path && o.type == "path") { - a.path = params.path; - node.path = path2vml(a.path); + "blur" in params && o.blur(params.blur); + if (params.path && o.type == "path" || newpath) { + node.path = path2vml(a.path); } if (params.rotation != null) { o.rotate(params.rotation, true); } if (params.translation) { @@ -1729,11 +1807,11 @@ } if (o.type == "image" && params.src) { node.src = params.src; } if (o.type == "image" && params.opacity) { - node.filterOpacity = " progid:DXImageTransform.Microsoft.Alpha(opacity=" + (params.opacity * 100) + ")"; + node.filterOpacity = ms + ".Alpha(opacity=" + (params.opacity * 100) + ")"; s.filter = (node.filterMatrix || E) + (node.filterOpacity || E); } params.font && (s.font = params.font); params["font-family"] && (s.fontFamily = '"' + params["font-family"][split](",")[0][rp](/^['"]+|['"]+$/g, E) + '"'); params["font-size"] && (s.fontSize = params["font-size"]); @@ -1749,15 +1827,15 @@ params["stroke-dasharray"] != null || params["stroke-miterlimit"] != null || params["stroke-linejoin"] != null || params["stroke-linecap"] != null) { node = o.shape || node; - var fill = (node.getElementsByTagName("fill") && node.getElementsByTagName("fill")[0]), + var fill = (node.getElementsByTagName(fillString) && node.getElementsByTagName(fillString)[0]), newfill = false; - !fill && (newfill = fill = createNode("fill")); + !fill && (newfill = fill = createNode(fillString)); if ("fill-opacity" in params || "opacity" in params) { - var opacity = ((+a["fill-opacity"] + 1 || 2) - 1) * ((+a.opacity + 1 || 2) - 1); + var opacity = ((+a["fill-opacity"] + 1 || 2) - 1) * ((+a.opacity + 1 || 2) - 1) * ((+R.getRGB(params.fill).o + 1 || 2) - 1); opacity < 0 && (opacity = 0); opacity > 1 && (opacity = 1); fill.opacity = opacity; } params.fill && (fill.on = true); @@ -1791,13 +1869,14 @@ params["stroke-linejoin"] || params["stroke-linecap"]) { stroke.on = true; } (params.stroke == "none" || stroke.on == null || params.stroke == 0 || params["stroke-width"] == 0) && (stroke.on = false); - stroke.on && params.stroke && (stroke.color = R.getRGB(params.stroke).hex); - var opacity = ((+a["stroke-opacity"] + 1 || 2) - 1) * ((+a.opacity + 1 || 2) - 1), - width = (toFloat(params["stroke-width"]) || 1) * .75; + var strokeColor = R.getRGB(params.stroke); + stroke.on && params.stroke && (stroke.color = strokeColor.hex); + opacity = ((+a["stroke-opacity"] + 1 || 2) - 1) * ((+a.opacity + 1 || 2) - 1) * ((+strokeColor.o + 1 || 2) - 1); + var width = (toFloat(params["stroke-width"]) || 1) * .75; opacity < 0 && (opacity = 0); opacity > 1 && (opacity = 1); params["stroke-width"] == null && (width = a["stroke-width"]); params["stroke-width"] && (stroke.weight = width); width && width < 1 && (opacity *= width) && (stroke.weight = 1); @@ -1822,11 +1901,11 @@ stroke.dashstyle = dasharray[has](params["stroke-dasharray"]) ? dasharray[params["stroke-dasharray"]] : E; } newstroke && node[appendChild](stroke); } if (res.type == "text") { - var s = res.paper.span.style; + s = res.paper.span.style; a.font && (s.font = a.font); a["font-family"] && (s.fontFamily = a["font-family"]); a["font-size"] && (s.fontSize = a["font-size"]); a["font-weight"] && (s.fontWeight = a["font-weight"]); a["font-style"] && (s.fontStyle = a["font-style"]); @@ -1850,14 +1929,14 @@ res.node.style["v-text-align"] = "center"; break; } } }; - var addGradientFill = function (o, gradient) { + addGradientFill = function (o, gradient) { o.attrs = o.attrs || {}; var attrs = o.attrs, - fill = o.node.getElementsByTagName("fill"), + fill, type = "linear", fxfy = ".5 .5"; o.attrs.gradient = gradient; gradient = (gradient + E)[rp](radial_gradient, function (all, fx, fy) { type = "radial"; @@ -1880,33 +1959,35 @@ var dots = parseDots(gradient); if (!dots) { return null; } o = o.shape || o.node; - fill = fill[0] || createNode("fill"); + fill = o.getElementsByTagName(fillString)[0] || createNode(fillString); + !fill.parentNode && o.appendChild(fill); if (dots[length]) { fill.on = true; fill.method = "none"; - fill.type = (type == "radial") ? "gradientradial" : "gradient"; fill.color = dots[0].color; fill.color2 = dots[dots[length] - 1].color; var clrs = []; for (var i = 0, ii = dots[length]; i < ii; i++) { dots[i].offset && clrs[push](dots[i].offset + S + dots[i].color); } - fill.colors && (fill.colors.value = clrs[length] ? clrs[join](",") : "0% " + fill.color); + fill.colors && (fill.colors.value = clrs[length] ? clrs[join]() : "0% " + fill.color); if (type == "radial") { + fill.type = "gradientradial"; fill.focus = "100%"; fill.focussize = fxfy; fill.focusposition = fxfy; } else { + fill.type = "gradient"; fill.angle = (270 - angle) % 360; } } return 1; }; - var Element = function (node, group, vml) { + Element = function (node, group, vml) { var Rotation = 0, RotX = 0, RotY = 0, Scale = 1; this[0] = node; @@ -1956,11 +2037,11 @@ this._.rt.cx = cx; this._.rt.cy = cy; this.setBox(this.attrs, cx, cy); this.Group.style.rotation = this._.rt.deg; // gradient fix for rotation. TODO - // var fill = (this.shape || this.node).getElementsByTagName("fill"); + // var fill = (this.shape || this.node).getElementsByTagName(fillString); // fill = fill[0] || {}; // var b = ((360 - this._.rt.deg) - 270) % 360; // !R.is(fill.angle, "undefined") && (fill.angle = b); return this; }; @@ -1991,11 +2072,10 @@ x = attr.cx - attr.rx; y = attr.cy - attr.ry; w = attr.rx * 2; h = attr.ry * 2; break; - case "rect": case "image": x = +attr.x; y = +attr.y; w = attr.width || 0; h = attr.height || 0; @@ -2005,10 +2085,11 @@ x = attr.x - round(this.W / 2); y = attr.y - this.H / 2; w = this.W; h = this.H; break; + case "rect": case "path": if (!this.attrs.path) { x = 0; y = 0; w = this.paper.width; @@ -2029,55 +2110,30 @@ break; } cx = (cx == null) ? x + w / 2 : cx; cy = (cy == null) ? y + h / 2 : cy; var left = cx - this.paper.width / 2, - top = cy - this.paper.height / 2; - if (this.type == "path" || this.type == "text") { - (gs.left != left + "px") && (gs.left = left + "px"); - (gs.top != top + "px") && (gs.top = top + "px"); - this.X = this.type == "text" ? x : -left; - this.Y = this.type == "text" ? y : -top; - this.W = w; - this.H = h; - (os.left != -left + "px") && (os.left = -left + "px"); - (os.top != -top + "px") && (os.top = -top + "px"); + top = cy - this.paper.height / 2, t; + gs.left != (t = left + "px") && (gs.left = t); + gs.top != (t = top + "px") && (gs.top = t); + this.X = pathlike[has](this.type) ? -left : x; + this.Y = pathlike[has](this.type) ? -top : y; + this.W = w; + this.H = h; + if (pathlike[has](this.type)) { + os.left != (t = -left * zoom + "px") && (os.left = t); + os.top != (t = -top * zoom + "px") && (os.top = t); + } else if (this.type == "text") { + os.left != (t = -left + "px") && (os.left = t); + os.top != (t = -top + "px") && (os.top = t); } else { - (gs.left != left + "px") && (gs.left = left + "px"); - (gs.top != top + "px") && (gs.top = top + "px"); - this.X = x; - this.Y = y; - this.W = w; - this.H = h; - (gs.width != this.paper.width + "px") && (gs.width = this.paper.width + "px"); - (gs.height != this.paper.height + "px") && (gs.height = this.paper.height + "px"); - (os.left != x - left + "px") && (os.left = x - left + "px"); - (os.top != y - top + "px") && (os.top = y - top + "px"); - (os.width != w + "px") && (os.width = w + "px"); - (os.height != h + "px") && (os.height = h + "px"); - var arcsize = (+params.r || 0) / mmin(w, h); - if (this.type == "rect" && this.arcsize.toFixed(4) != arcsize.toFixed(4) && (arcsize || this.arcsize)) { - // We should replace element with the new one - var o = createNode("roundrect"), - a = {}, - i = 0, - ii = this.events && this.events[length]; - o.arcsize = arcsize; - o.raphael = this; - this.Group[appendChild](o); - this.Group.removeChild(this.node); - this[0] = this.node = o; - this.arcsize = arcsize; - for (var i in attr) { - a[i] = attr[i]; - } - delete a.scale; - this.attr(a); - if (this.events) for (; i < ii; i++) { - this.events[i].unbind = addEvent(this.node, this.events[i].name, this.events[i].f, this); - } - } + gs.width != (t = this.paper.width + "px") && (gs.width = t); + gs.height != (t = this.paper.height + "px") && (gs.height = t); + os.left != (t = x - left + "px") && (os.left = t); + os.top != (t = y - top + "px") && (os.top = t); + os.width != (t = w + "px") && (os.width = t); + os.height != (t = h + "px") && (os.height = t); } }; Element[proto].hide = function () { !this.removed && (this.Group.style.display = "none"); return this; @@ -2088,11 +2144,11 @@ }; Element[proto].getBBox = function () { if (this.removed) { return this; } - if (this.type == "path") { + if (pathlike[has](this.type)) { return pathDimensions(this.attrs.path); } return { x: this.X + (this.bbx || 0), y: this.Y, @@ -2111,61 +2167,61 @@ for (var i in this) { delete this[i]; } this.removed = true; }; - Element[proto].attr = function () { + Element[proto].attr = function (name, value) { if (this.removed) { return this; } - if (arguments[length] == 0) { + if (name == null) { var res = {}; for (var i in this.attrs) if (this.attrs[has](i)) { res[i] = this.attrs[i]; } this._.rt.deg && (res.rotation = this.rotate()); (this._.sx != 1 || this._.sy != 1) && (res.scale = this.scale()); res.gradient && res.fill == "none" && (res.fill = res.gradient) && delete res.gradient; return res; } - if (arguments[length] == 1 && R.is(arguments[0], "string")) { - if (arguments[0] == "translation") { + if (value == null && R.is(name, string)) { + if (name == "translation") { return translate.call(this); } - if (arguments[0] == "rotation") { + if (name == "rotation") { return this.rotate(); } - if (arguments[0] == "scale") { + if (name == "scale") { return this.scale(); } - if (arguments[0] == "fill" && this.attrs.fill == "none" && this.attrs.gradient) { + if (name == fillString && this.attrs.fill == "none" && this.attrs.gradient) { return this.attrs.gradient; } - return this.attrs[arguments[0]]; + return this.attrs[name]; } - if (this.attrs && arguments[length] == 1 && R.is(arguments[0], "array")) { - var values = {}; - for (var i = 0, ii = arguments[0][length]; i < ii; i++) { - values[arguments[0][i]] = this.attrs[arguments[0][i]]; - }; + if (this.attrs && value == null && R.is(name, array)) { + var ii, values = {}; + for (i = 0, ii = name[length]; i < ii; i++) { + values[name[i]] = this.attr(name[i]); + } return values; } var params; - if (arguments[length] == 2) { + if (value != null) { params = {}; - params[arguments[0]] = arguments[1]; + params[name] = value; } - arguments[length] == 1 && R.is(arguments[0], "object") && (params = arguments[0]); + value == null && R.is(name, "object") && (params = name); if (params) { if (params.text && this.type == "text") { this.node.string = params.text; } setFillAndStroke(this, params); if (params.gradient && (({circle: 1, ellipse: 1})[has](this.type) || (params.gradient + E).charAt() != "r")) { addGradientFill(this, params.gradient); } - (this.type != "path" || this._.rt.deg) && this.setBox(this.attrs); + (!pathlike[has](this.type) || this._.rt.deg) && this.setBox(this.attrs); } return this; }; Element[proto].toFront = function () { !this.removed && this.Group.parentNode[appendChild](this.Group); @@ -2200,17 +2256,32 @@ } element.Group.parentNode.insertBefore(this.Group, element.Group); insertbefore(this, element, this.paper); return this; }; + var blurregexp = / progid:\S+Blur\([^\)]+\)/g; + Element[proto].blur = function (size) { + var s = this.node.style, + f = s.filter; + f = f.replace(blurregexp, ""); + if (+size !== 0) { + this.attrs.blur = size; + s.filter = f + ms + ".Blur(pixelradius=" + (+size || 1.5) + ")"; + s.margin = Raphael.format("-{0}px 0 0 -{0}px", Math.round(+size || 1.5)); + } else { + s.filter = f; + s.margin = 0; + delete this.attrs.blur; + } + }; - var theCircle = function (vml, x, y, r) { + theCircle = function (vml, x, y, r) { var g = createNode("group"), o = createNode("oval"), ol = o.style; g.style.cssText = "position:absolute;left:0;top:0;width:" + vml.width + "px;height:" + vml.height + "px"; - g.coordsize = vml.coordsize; + g.coordsize = coordsize; g.coordorigin = vml.coordorigin; g[appendChild](o); var res = new Element(o, g, vml); res.type = "circle"; setFillAndStroke(res, {stroke: "#000", fill: "none"}); @@ -2218,34 +2289,37 @@ res.attrs.cy = y; res.attrs.r = r; res.setBox({x: x - r, y: y - r, width: r * 2, height: r * 2}); vml.canvas[appendChild](g); return res; - }, + }; + function rectPath(x, y, w, h, r) { + if (r) { + return R.format("M{0},{1}l{2},0a{3},{3},0,0,1,{3},{3}l0,{5}a{3},{3},0,0,1,{4},{3}l{6},0a{3},{3},0,0,1,{4},{4}l0,{7}a{3},{3},0,0,1,{3},{4}z", x + r, y, w - r * 2, r, -r, h - r * 2, r * 2 - w, r * 2 - h); + } else { + return R.format("M{0},{1}l{2},0,0,{3},{4},0z", x, y, w, h, -w); + } + } theRect = function (vml, x, y, w, h, r) { - var g = createNode("group"), - o = createNode("roundrect"), - arcsize = (+r || 0) / (mmin(w, h)); - g.style.cssText = "position:absolute;left:0;top:0;width:" + vml.width + "px;height:" + vml.height + "px"; - g.coordsize = vml.coordsize; - g.coordorigin = vml.coordorigin; - g[appendChild](o); - o.arcsize = arcsize; - var res = new Element(o, g, vml); + var path = rectPath(x, y, w, h, r), + res = vml.path(path), + a = res.attrs; + res.X = a.x = x; + res.Y = a.y = y; + res.W = a.width = w; + res.H = a.height = h; + a.r = r; + a.path = path; res.type = "rect"; - setFillAndStroke(res, {stroke: "#000"}); - res.arcsize = arcsize; - res.setBox({x: x, y: y, width: w, height: h, r: r}); - vml.canvas[appendChild](g); return res; - }, + }; theEllipse = function (vml, x, y, rx, ry) { var g = createNode("group"), o = createNode("oval"), ol = o.style; g.style.cssText = "position:absolute;left:0;top:0;width:" + vml.width + "px;height:" + vml.height + "px"; - g.coordsize = vml.coordsize; + g.coordsize = coordsize; g.coordorigin = vml.coordorigin; g[appendChild](o); var res = new Element(o, g, vml); res.type = "ellipse"; setFillAndStroke(res, {stroke: "#000"}); @@ -2254,17 +2328,17 @@ res.attrs.rx = rx; res.attrs.ry = ry; res.setBox({x: x - rx, y: y - ry, width: rx * 2, height: ry * 2}); vml.canvas[appendChild](g); return res; - }, + }; theImage = function (vml, src, x, y, w, h) { var g = createNode("group"), o = createNode("image"), ol = o.style; g.style.cssText = "position:absolute;left:0;top:0;width:" + vml.width + "px;height:" + vml.height + "px"; - g.coordsize = vml.coordsize; + g.coordsize = coordsize; g.coordorigin = vml.coordorigin; o.src = src; g[appendChild](o); var res = new Element(o, g, vml); res.type = "image"; @@ -2274,22 +2348,22 @@ res.attrs.w = w; res.attrs.h = h; res.setBox({x: x, y: y, width: w, height: h}); vml.canvas[appendChild](g); return res; - }, + }; theText = function (vml, x, y, text) { var g = createNode("group"), el = createNode("shape"), ol = el.style, path = createNode("path"), ps = path.style, o = createNode("textpath"); g.style.cssText = "position:absolute;left:0;top:0;width:" + vml.width + "px;height:" + vml.height + "px"; - g.coordsize = vml.coordsize; + g.coordsize = coordsize; g.coordorigin = vml.coordorigin; - path.v = R.format("m{0},{1}l{2},{1}", round(x), round(y), round(x) + 1); + path.v = R.format("m{0},{1}l{2},{1}", round(x * 10), round(y * 10), round(x * 10) + 1); path.textpathok = true; ol.width = vml.width; ol.height = vml.height; o.string = text + E; o.on = true; @@ -2307,21 +2381,21 @@ res.attrs.h = 1; setFillAndStroke(res, {font: availableAttrs.font, stroke: "none", fill: "#000"}); res.setBox(); vml.canvas[appendChild](g); return res; - }, + }; setSize = function (width, height) { var cs = this.canvas.style; width == +width && (width += "px"); height == +height && (height += "px"); cs.width = width; cs.height = height; cs.clip = "rect(0 " + width + " " + height + " 0)"; return this; - }, - createNode; + }; + var createNode; doc.createStyleSheet().addRule(".rvml", "behavior:url(#default#VML)"); try { !doc.namespaces.rvml && doc.namespaces.add("rvml", "urn:schemas-microsoft-com:vml"); createNode = function (tagName) { return doc.createElement('<rvml:' + tagName + ' class="rvml">'); @@ -2329,12 +2403,12 @@ } catch (e) { createNode = function (tagName) { return doc.createElement('<' + tagName + ' xmlns="urn:schemas-microsoft.com:vml" class="rvml">'); }; } - var create = function () { - var con = getContainer[apply](null, arguments), + create = function () { + var con = getContainer[apply](0, arguments), container = con.container, height = con.height, s, width = con.width, x = con.x, @@ -2343,29 +2417,30 @@ throw new Error("VML container not found."); } var res = new Paper, c = res.canvas = doc.createElement("div"), cs = c.style; + x = x || 0; + y = y || 0; width = width || 512; height = height || 342; width == +width && (width += "px"); height == +height && (height += "px"); res.width = 1e3; res.height = 1e3; - res.coordsize = "1000 1000"; + res.coordsize = zoom * 1e3 + S + zoom * 1e3; res.coordorigin = "0 0"; res.span = doc.createElement("span"); res.span.style.cssText = "position:absolute;left:-9999em;top:-9999em;padding:0;margin:0;line-height:1;display:inline;"; c[appendChild](res.span); - cs.cssText = R.format("width:{0};height:{1};position:absolute;clip:rect(0 {0} {1} 0);overflow:hidden", width, height); + cs.cssText = R.format("width:{0};height:{1};display:inline-block;position:relative;clip:rect(0 {0} {1} 0);overflow:hidden", width, height); if (container == 1) { doc.body[appendChild](c); cs.left = x + "px"; cs.top = y + "px"; + cs.position = "absolute"; } else { - container.style.width = width; - container.style.height = height; if (container.firstChild) { container.insertBefore(c, container.firstChild); } else { container[appendChild](c); } @@ -2383,41 +2458,70 @@ Paper[proto].remove = function () { this.canvas.parentNode.removeChild(this.canvas); for (var i in this) { this[i] = removed(i); } + return true; }; } // rest // Safari or Chrome (WebKit) rendering bug workaround method - if ((/^Apple|^Google/).test(navigator.vendor) && !(navigator.userAgent.indexOf("Version/4.0") + 1)) { + if ((/^Apple|^Google/).test(win.navigator.vendor) && (!(win.navigator.userAgent.indexOf("Version/4.0") + 1) || win.navigator.platform.slice(0, 2) == "iP")) { Paper[proto].safari = function () { var rect = this.rect(-99, -99, this.width + 99, this.height + 99); - setTimeout(function () {rect.remove();}); + win.setTimeout(function () {rect.remove();}); }; } else { Paper[proto].safari = function () {}; } // Events - var addEvent = (function () { + var preventDefault = function () { + this.returnValue = false; + }, + preventTouch = function () { + return this.originalEvent.preventDefault(); + }, + stopPropagation = function () { + this.cancelBubble = true; + }, + stopTouch = function () { + return this.originalEvent.stopPropagation(); + }, + addEvent = (function () { if (doc.addEventListener) { return function (obj, type, fn, element) { + var realName = supportsTouch && touchMap[type] ? touchMap[type] : type; var f = function (e) { + if (supportsTouch && touchMap[has](type)) { + for (var i = 0, ii = e.targetTouches && e.targetTouches.length; i < ii; i++) { + if (e.targetTouches[i].target == obj) { + var olde = e; + e = e.targetTouches[i]; + e.originalEvent = olde; + e.preventDefault = preventTouch; + e.stopPropagation = stopTouch; + break; + } + } + } return fn.call(element, e); }; - obj.addEventListener(type, f, false); + obj.addEventListener(realName, f, false); return function () { - obj.removeEventListener(type, f, false); + obj.removeEventListener(realName, f, false); return true; }; }; } else if (doc.attachEvent) { return function (obj, type, fn, element) { var f = function (e) { - return fn.call(element, e || win.event); + e = e || win.event; + e.preventDefault = e.preventDefault || preventDefault; + e.stopPropagation = e.stopPropagation || stopPropagation; + return fn.call(element, e); }; obj.attachEvent("on" + type, f); var detacher = function () { obj.detachEvent("on" + type, f); return true; @@ -2426,18 +2530,18 @@ }; } })(); for (var i = events[length]; i--;) { (function (eventName) { - Element[proto][eventName] = function (fn) { + R[eventName] = Element[proto][eventName] = function (fn) { if (R.is(fn, "function")) { this.events = this.events || []; - this.events.push({name: eventName, f: fn, unbind: addEvent(this.shape || this.node, eventName, fn, this)}); + this.events.push({name: eventName, f: fn, unbind: addEvent(this.shape || this.node || doc, eventName, fn, this)}); } return this; }; - Element[proto]["un" + eventName] = function (fn) { + R["un" + eventName] = Element[proto]["un" + eventName] = function (fn) { var events = this.events, l = events[length]; while (l--) if (events[l].name == eventName && events[l].f == fn) { events[l].unbind(); events.splice(l, 1); @@ -2452,21 +2556,58 @@ return this.mouseover(f_in).mouseout(f_out); }; Element[proto].unhover = function (f_in, f_out) { return this.unmouseover(f_in).unmouseout(f_out); }; + Element[proto].drag = function (onmove, onstart, onend) { + this._drag = {}; + var el = this.mousedown(function (e) { + (e.originalEvent ? e.originalEvent : e).preventDefault(); + this._drag.x = e.clientX; + this._drag.y = e.clientY; + this._drag.id = e.identifier; + onstart && onstart.call(this, e.clientX, e.clientY); + Raphael.mousemove(move).mouseup(up); + }), + move = function (e) { + var x = e.clientX, + y = e.clientY; + if (supportsTouch) { + var i = e.touches.length, + touch; + while (i--) { + touch = e.touches[i]; + if (touch.identifier == el._drag.id) { + x = touch.clientX; + y = touch.clientY; + (e.originalEvent ? e.originalEvent : e).preventDefault(); + break; + } + } + } else { + e.preventDefault(); + } + onmove && onmove.call(el, x - el._drag.x, y - el._drag.y, x, y); + }, + up = function () { + el._drag = {}; + Raphael.unmousemove(move).unmouseup(up); + onend && onend.call(el); + }; + return this; + }; Paper[proto].circle = function (x, y, r) { return theCircle(this, x || 0, y || 0, r || 0); }; Paper[proto].rect = function (x, y, w, h, r) { return theRect(this, x || 0, y || 0, w || 0, h || 0, r || 0); }; Paper[proto].ellipse = function (x, y, rx, ry) { return theEllipse(this, x || 0, y || 0, rx || 0, ry || 0); }; Paper[proto].path = function (pathString) { - pathString && !R.is(pathString, "string") && !R.is(pathString[0], "array") && (pathString += E); + pathString && !R.is(pathString, string) && !R.is(pathString[0], array) && (pathString += E); return thePath(R.format[apply](R, arguments), this); }; Paper[proto].image = function (src, x, y, w, h) { return theImage(this, src || "about:blank", x || 0, y || 0, w || 0, h || 0); }; @@ -2480,12 +2621,23 @@ Paper[proto].setSize = setSize; Paper[proto].top = Paper[proto].bottom = null; Paper[proto].raphael = R; function x_y() { return this.x + S + this.y; + } + Element[proto].resetScale = function () { + if (this.removed) { + return this; + } + this._.sx = 1; + this._.sy = 1; + this.attrs.scale = "1 1"; }; Element[proto].scale = function (x, y, cx, cy) { + if (this.removed) { + return this; + } if (x == null && y == null) { return { x: this._.sx, y: this._.sy, toString: x_y @@ -2532,16 +2684,21 @@ r: a.r * mmin(dirx * kx, diry * ky), cx: ncx, cy: ncy }); break; + case "text": + this.attr({ + x: ncx, + y: ncy + }); + break; case "path": var path = pathToRelative(a.path), skip = true; for (var i = 0, ii = path[length]; i < ii; i++) { var p = path[i], - j, P0 = upperCase.call(p[0]); if (P0 == "M" && skip) { continue; } else { skip = false; @@ -2549,13 +2706,13 @@ if (P0 == "A") { p[path[i][length] - 2] *= kx; p[path[i][length] - 1] *= ky; p[1] *= dirx * kx; p[2] *= diry * ky; - p[5] = +(dirx + diry ? !!+p[5] : !+p[5]); + p[5] = +!(dirx + diry ? !+p[5] : +p[5]); } else if (P0 == "H") { - for (j = 1, jj = p[length]; j < jj; j++) { + for (var j = 1, jj = p[length]; j < jj; j++) { p[j] *= kx; } } else if (P0 == "V") { for (j = 1, jj = p[length]; j < jj; j++) { p[j] *= ky; @@ -2564,13 +2721,13 @@ for (j = 1, jj = p[length]; j < jj; j++) { p[j] *= (j % 2) ? kx : ky; } } } - var dim2 = pathDimensions(path), - dx = ncx - dim2.x - dim2.width / 2, - dy = ncy - dim2.y - dim2.height / 2; + var dim2 = pathDimensions(path); + dx = ncx - dim2.x - dim2.width / 2; + dy = ncy - dim2.y - dim2.height / 2; path[0][1] += dx; path[0][2] += dy; this.attr({path: path}); break; } @@ -2582,11 +2739,11 @@ dy = (diry == -1) ? -a.y - (newh || 0) : a.y; this.attr({x: dx, y: dy}); a.fx = dirx - 1; a.fy = diry - 1; } else { - this.node.filterMatrix = " progid:DXImageTransform.Microsoft.Matrix(M11="[concat](dirx, + this.node.filterMatrix = ms + ".Matrix(M11="[concat](dirx, ", M12=0, M21=0, M22=", diry, ", Dx=0, Dy=0, sizingmethod='auto expand', filtertype='bilinear')"); s.filter = (this.node.filterMatrix || E) + (this.node.filterOpacity || E); } } else { @@ -2605,16 +2762,31 @@ this._.sy = y; } return this; }; Element[proto].clone = function () { + if (this.removed) { + return null; + } var attr = this.attr(); delete attr.scale; delete attr.translation; return this.paper[this.type]().attr(attr); }; - var getLengthFactory = function (istotal, subpath) { + var getPointAtSegmentLength = cacher(function (p1x, p1y, c1x, c1y, c2x, c2y, p2x, p2y, length) { + var len = 0, + old; + for (var i = 0; i < 1.001; i+=.001) { + var dot = R.findDotsAtSegment(p1x, p1y, c1x, c1y, c2x, c2y, p2x, p2y, i); + i && (len += pow(pow(old.x - dot.x, 2) + pow(old.y - dot.y, 2), .5)); + if (len >= length) { + return dot; + } + old = dot; + } + }), + getLengthFactory = function (istotal, subpath) { return function (path, length, onlystart) { path = path2curve(path); var x, y, p, l, sp = "", subpaths = {}, point, len = 0; for (var i = 0, ii = path.length; i < ii; i++) { @@ -2624,24 +2796,22 @@ y = +p[2]; } else { l = segmentLength(x, y, p[1], p[2], p[3], p[4], p[5], p[6]); if (len + l > length) { if (subpath && !subpaths.start) { - point = R.findDotsAtSegment(x, y, p[1], p[2], p[3], p[4], p[5], p[6], (length - len) / l); + point = getPointAtSegmentLength(x, y, p[1], p[2], p[3], p[4], p[5], p[6], length - len); sp += ["C", point.start.x, point.start.y, point.m.x, point.m.y, point.x, point.y]; - if (onlystart) { - return sp; - } + if (onlystart) {return sp;} subpaths.start = sp; - sp = ["M", point.x, point.y, "C", point.n.x, point.n.y, point.end.x, point.end.y, p[5], p[6]][join](); + sp = ["M", point.x, point.y + "C", point.n.x, point.n.y, point.end.x, point.end.y, p[5], p[6]][join](); len += l; x = +p[5]; y = +p[6]; continue; } if (!istotal && !subpath) { - point = R.findDotsAtSegment(x, y, p[1], p[2], p[3], p[4], p[5], p[6], (length - len) / l); + point = getPointAtSegmentLength(x, y, p[1], p[2], p[3], p[4], p[5], p[6], length - len); return {x: point.x, y: point.y, alpha: point.alpha}; } } len += l; x = +p[5]; @@ -2658,28 +2828,34 @@ segmentLength = cacher(function (p1x, p1y, c1x, c1y, c2x, c2y, p2x, p2y) { var old = {x: 0, y: 0}, len = 0; for (var i = 0; i < 1.01; i+=.01) { var dot = findDotAtSegment(p1x, p1y, c1x, c1y, c2x, c2y, p2x, p2y, i); - i && (len += math.sqrt(pow(old.x - dot.x, 2) + pow(old.y - dot.y, 2))); + i && (len += pow(pow(old.x - dot.x, 2) + pow(old.y - dot.y, 2), .5)); old = dot; } return len; }); var getTotalLength = getLengthFactory(1), getPointAtLength = getLengthFactory(), getSubpathsAtLength = getLengthFactory(0, 1); Element[proto].getTotalLength = function () { - if (this.type != "path") return; + if (this.type != "path") {return;} + if (this.node.getTotalLength) { + return this.node.getTotalLength(); + } return getTotalLength(this.attrs.path); }; Element[proto].getPointAtLength = function (length) { - if (this.type != "path") return; + if (this.type != "path") {return;} return getPointAtLength(this.attrs.path, length); }; Element[proto].getSubpath = function (from, to) { - if (this.type != "path") return; + if (this.type != "path") {return;} + if (math.abs(this.getTotalLength() - to) < 1e-6) { + return getSubpathsAtLength(this.attrs.path, from).end; + } var a = getSubpathsAtLength(this.attrs.path, to, 1); return from ? getSubpathsAtLength(a, from).end : a; }; // animation easing formulas @@ -2739,17 +2915,17 @@ } } return l; } }; - + var animationElements = {length : 0}, animation = function () { var Now = +new Date; for (var l in animationElements) if (l != "length" && animationElements[has](l)) { var e = animationElements[l]; - if (e.stop) { + if (e.stop || e.el.removed) { delete animationElements[l]; animationElements[length]--; continue; } var time = Now - e.start, @@ -2776,11 +2952,11 @@ diff.x = point.x; diff.y = point.y; that.translate(point.x - diff.sx, point.y - diff.sy); to.rot && that.rotate(diff.r + point.alpha, point.x, point.y); break; - case "number": + case nu: now = +from[attr] + pos * ms * diff[attr]; break; case "colour": now = "rgb(" + [ upto255(round(from[attr].r + pos * ms * diff[attr].r)), @@ -2815,11 +2991,11 @@ case "scale": now = [+from[attr][0] + pos * ms * diff[attr][0], +from[attr][1] + pos * ms * diff[attr][1], (2 in to[attr] ? to[attr][2] : E), (3 in to[attr] ? to[attr][3] : E)][join](S); break; case "clip-rect": now = []; - var i = 4; + i = 4; while (i--) { now[i] = +from[attr][i] + pos * ms * diff[attr][i]; } break; } @@ -2829,29 +3005,29 @@ } that.attr(set); that._run && that._run.call(that); } else { if (to.along) { - var point = getPointAtLength(to.along, to.len * !to.back); + point = getPointAtLength(to.along, to.len * !to.back); that.translate(diff.sx - (diff.x || 0) + point.x - diff.sx, diff.sy - (diff.y || 0) + point.y - diff.sy); to.rot && that.rotate(diff.r + point.alpha, point.x, point.y); } (t.x || t.y) && that.translate(-t.x, -t.y); - to.scale && (to.scale = to.scale + E); + to.scale && (to.scale += E); that.attr(to); delete animationElements[l]; animationElements[length]--; that.in_animation = null; R.is(callback, "function") && callback.call(that); } e.prev = time; } - R.svg && that && that.paper.safari(); - animationElements[length] && setTimeout(animation); + R.svg && that && that.paper && that.paper.safari(); + animationElements[length] && win.setTimeout(animation); }, upto255 = function (color) { - return color > 255 ? 255 : (color < 0 ? 0 : color); + return mmax(mmin(color, 255), 0); }, translate = function (x, y) { if (x == null) { return {x: this._.tx, y: this._.ty, toString: x_y}; } @@ -2920,11 +3096,11 @@ to.rot = params.rot; to.back = params.back; to.len = len; params.rot && (diff.r = toFloat(this.rotate()) || 0); break; - case "number": + case nu: diff[attr] = (to[attr] - from[attr]) / ms; break; case "colour": from[attr] = R.getRGB(from[attr]); var toColour = R.getRGB(to[attr]); @@ -2964,11 +3140,11 @@ diff[attr] = [(values[0] - from[attr][0]) / ms, (values[1] - from[attr][1]) / ms, 0, 0]; break; case "clip-rect": from[attr] = (from[attr] + E)[split](separator); diff[attr] = []; - var i = 4; + i = 4; while (i--) { diff[attr][i] = (values[i] - from[attr][i]) / ms; } break; } @@ -3007,10 +3183,11 @@ // Set var Set = function (items) { this.items = []; this[length] = 0; + this.type = "set"; if (items) { for (var i = 0, ii = items[length]; i < ii; i++) { if (items[i] && (items[i].constructor == Element || items[i].constructor == Set)) { this[this.items[length]] = this.items[this.items[length]] = items[i]; this[length]++; @@ -3044,33 +3221,35 @@ return this; }; })(method); } Set[proto].attr = function (name, value) { - if (name && R.is(name, "array") && R.is(name[0], "object")) { + if (name && R.is(name, array) && R.is(name[0], "object")) { for (var j = 0, jj = name[length]; j < jj; j++) { this.items[j].attr(name[j]); } } else { for (var i = 0, ii = this.items[length]; i < ii; i++) { - this.items[i].attr[apply](this.items[i], arguments); + this.items[i].attr(name, value); } } return this; }; Set[proto].animate = function (params, ms, easing, callback) { (R.is(easing, "function") || !easing) && (callback = easing || null); var len = this.items[length], i = len, + item, set = this, collector; callback && (collector = function () { !--len && callback.call(set); }); - this.items[--i].animate(params, ms, easing || collector, collector); + easing = R.is(easing, string) ? easing : collector; + item = this.items[--i].animate(params, ms, easing, collector); while (i--) { - this.items[i].animateWith(this.items[len - 1], params, ms, easing || collector, collector); + this.items[i].animateWith(item, params, ms, easing, collector); } return this; }; Set[proto].insertAfter = function (el) { var i = this.items[length]; @@ -3098,11 +3277,18 @@ y: y, width: mmax[apply](0, w) - x, height: mmax[apply](0, h) - y }; }; - + Set[proto].clone = function (s) { + s = new Set; + for (var i = 0, ii = this.items[length]; i < ii; i++) { + s[push](this.items[i].clone()); + } + return s; + }; + R.registerFont = function (font) { if (!font.face) { return font; } this.fonts = this.fonts || {}; @@ -3142,10 +3328,13 @@ }; Paper[proto].getFont = function (family, weight, style, stretch) { stretch = stretch || "normal"; style = style || "normal"; weight = +weight || {normal: 400, bold: 700, lighter: 300, bolder: 800}[weight] || 400; + if (!R.fonts) { + return; + } var font = R.fonts[family]; if (!font) { var name = new RegExp("(^|\\s)" + family[rp](/[^\w\d\s+!~.:_-]/g, E) + "(\\s|$)", "i"); for (var fontName in R.fonts) if (R.fonts[has](fontName)) { if (name.test(fontName)) { @@ -3170,11 +3359,11 @@ var out = this.set(), letters = (string + E)[split](E), shift = 0, path = E, scale; - R.is(font, "string") && (font = this.getFont(font)); + R.is(font, string) && (font = this.getFont(font)); if (font) { scale = (size || 16) / font.face["units-per-em"]; var bb = font.face.bbox.split(separator), top = +bb[0], height = +bb[1] + (origin == "baseline" ? bb[3] - bb[1] + (+font.face.descent) : (bb[3] - bb[1]) / 2); @@ -3186,30 +3375,21 @@ } out.scale(scale, scale, top, height).translate(x - top, y - height); } return out; }; - - R.format = function (token) { - var args = R.is(arguments[1], "array") ? [0][concat](arguments[1]) : arguments, - rg = /\{(\d+)\}/g; - token && R.is(token, "string") && args[length] - 1 && (token = token[rp](rg, function (str, i) { + + var formatrg = /\{(\d+)\}/g; + R.format = function (token, params) { + var args = R.is(params, array) ? [0][concat](params) : arguments; + token && R.is(token, string) && args[length] - 1 && (token = token[rp](formatrg, function (str, i) { return args[++i] == null ? E : args[i]; })); return token || E; }; R.ninja = function () { - var r = win.Raphael, u; - if (oldRaphael.was) { - win.Raphael = oldRaphael.is; - } else { - try { - delete win.Raphael; - } catch (e) { - win.Raphael = u; - } - } - return r; + oldRaphael.was ? (Raphael = oldRaphael.is) : delete Raphael; + return R; }; R.el = Element[proto]; return R; -})(); \ No newline at end of file +})();