UNPKG

js-lib

Version:

常用js插件供项目调用

1,421 lines (1,394 loc) 298 kB
// ┌────────────────────────────────────────────────────────────────────┐ \\ // │ Raphaël 2.1.0 - JavaScript Vector Library │ \\ // ├────────────────────────────────────────────────────────────────────┤ \\ // │ Copyright © 2008-2012 Dmitry Baranovskiy (http://raphaeljs.com) │ \\ // │ Copyright © 2008-2012 Sencha Labs (http://sencha.com) │ \\ // ├────────────────────────────────────────────────────────────────────┤ \\ // │ Licensed under the MIT (http://raphaeljs.com/license.html) license.│ \\ // └────────────────────────────────────────────────────────────────────┘ \\ // Copyright (c) 2013 Adobe Systems Incorporated. All rights reserved. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // ┌────────────────────────────────────────────────────────────┐ \\ // │ Eve 0.4.2 - JavaScript Events Library │ \\ // ├────────────────────────────────────────────────────────────┤ \\ // │ Author Dmitry Baranovskiy (http://dmitry.baranovskiy.com/) │ \\ // └────────────────────────────────────────────────────────────┘ \\ (function (glob) { var version = "0.4.2", has = "hasOwnProperty", separator = /[\.\/]/, wildcard = "*", fun = function () {}, numsort = function (a, b) { return a - b; }, current_event, stop, events = {n: {}}, /*\ * eve [ method ] * Fires event with given `name`, given scope and other parameters. > Arguments - name (string) name of the *event*, dot (`.`) or slash (`/`) separated - scope (object) context for the event handlers - varargs (...) the rest of arguments will be sent to event handlers = (object) array of returned values from the listeners \*/ eve = function (name, scope) { name = String(name); var e = events, oldstop = stop, args = Array.prototype.slice.call(arguments, 2), listeners = eve.listeners(name), z = 0, f = false, l, indexed = [], queue = {}, out = [], ce = current_event, errors = []; current_event = name; stop = 0; for (var i = 0, ii = listeners.length; i < ii; i++) if ("zIndex" in listeners[i]) { indexed.push(listeners[i].zIndex); if (listeners[i].zIndex < 0) { queue[listeners[i].zIndex] = listeners[i]; } } indexed.sort(numsort); while (indexed[z] < 0) { l = queue[indexed[z++]]; out.push(l.apply(scope, args)); if (stop) { stop = oldstop; return out; } } for (i = 0; i < ii; i++) { l = listeners[i]; if ("zIndex" in l) { if (l.zIndex == indexed[z]) { out.push(l.apply(scope, args)); if (stop) { break; } do { z++; l = queue[indexed[z]]; l && out.push(l.apply(scope, args)); if (stop) { break; } } while (l) } else { queue[l.zIndex] = l; } } else { out.push(l.apply(scope, args)); if (stop) { break; } } } stop = oldstop; current_event = ce; return out.length ? out : null; }; // Undocumented. Debug only. eve._events = events; /*\ * eve.listeners [ method ] * Internal method which gives you array of all event handlers that will be triggered by the given `name`. > Arguments - name (string) name of the event, dot (`.`) or slash (`/`) separated = (array) array of event handlers \*/ eve.listeners = function (name) { var names = name.split(separator), e = events, item, items, k, i, ii, j, jj, nes, es = [e], out = []; for (i = 0, ii = names.length; i < ii; i++) { nes = []; for (j = 0, jj = es.length; j < jj; j++) { e = es[j].n; items = [e[names[i]], e[wildcard]]; k = 2; while (k--) { item = items[k]; if (item) { nes.push(item); out = out.concat(item.f || []); } } } es = nes; } return out; }; /*\ * eve.on [ method ] ** * Binds given event handler with a given name. You can use wildcards “`*`” for the names: | eve.on("*.under.*", f); | eve("mouse.under.floor"); // triggers f * Use @eve to trigger the listener. ** > Arguments ** - name (string) name of the event, dot (`.`) or slash (`/`) separated, with optional wildcards - f (function) event handler function ** = (function) returned function accepts a single numeric parameter that represents z-index of the handler. It is an optional feature and only used when you need to ensure that some subset of handlers will be invoked in a given order, despite of the order of assignment. > Example: | eve.on("mouse", eatIt)(2); | eve.on("mouse", scream); | eve.on("mouse", catchIt)(1); * This will ensure that `catchIt()` function will be called before `eatIt()`. * * If you want to put your handler before non-indexed handlers, specify a negative value. * Note: I assume most of the time you don’t need to worry about z-index, but it’s nice to have this feature “just in case”. \*/ eve.on = function (name, f) { name = String(name); if (typeof f != "function") { return function () {}; } var names = name.split(separator), e = events; for (var i = 0, ii = names.length; i < ii; i++) { e = e.n; e = e.hasOwnProperty(names[i]) && e[names[i]] || (e[names[i]] = {n: {}}); } e.f = e.f || []; for (i = 0, ii = e.f.length; i < ii; i++) if (e.f[i] == f) { return fun; } e.f.push(f); return function (zIndex) { if (+zIndex == +zIndex) { f.zIndex = +zIndex; } }; }; /*\ * eve.f [ method ] ** * Returns function that will fire given event with optional arguments. * Arguments that will be passed to the result function will be also * concated to the list of final arguments. | el.onclick = eve.f("click", 1, 2); | eve.on("click", function (a, b, c) { | console.log(a, b, c); // 1, 2, [event object] | }); > Arguments - event (string) event name - varargs (…) and any other arguments = (function) possible event handler function \*/ eve.f = function (event) { var attrs = [].slice.call(arguments, 1); return function () { eve.apply(null, [event, null].concat(attrs).concat([].slice.call(arguments, 0))); }; }; /*\ * eve.stop [ method ] ** * Is used inside an event handler to stop the event, preventing any subsequent listeners from firing. \*/ eve.stop = function () { stop = 1; }; /*\ * eve.nt [ method ] ** * Could be used inside event handler to figure out actual name of the event. ** > Arguments ** - subname (string) #optional subname of the event ** = (string) name of the event, if `subname` is not specified * or = (boolean) `true`, if current event’s name contains `subname` \*/ eve.nt = function (subname) { if (subname) { return new RegExp("(?:\\.|\\/|^)" + subname + "(?:\\.|\\/|$)").test(current_event); } return current_event; }; /*\ * eve.nts [ method ] ** * Could be used inside event handler to figure out actual name of the event. ** ** = (array) names of the event \*/ eve.nts = function () { return current_event.split(separator); }; /*\ * eve.off [ method ] ** * Removes given function from the list of event listeners assigned to given name. * If no arguments specified all the events will be cleared. ** > Arguments ** - name (string) name of the event, dot (`.`) or slash (`/`) separated, with optional wildcards - f (function) event handler function \*/ /*\ * eve.unbind [ method ] ** * See @eve.off \*/ eve.off = eve.unbind = function (name, f) { if (!name) { eve._events = events = {n: {}}; return; } var names = name.split(separator), e, key, splice, i, ii, j, jj, cur = [events]; for (i = 0, ii = names.length; i < ii; i++) { for (j = 0; j < cur.length; j += splice.length - 2) { splice = [j, 1]; e = cur[j].n; if (names[i] != wildcard) { if (e[names[i]]) { splice.push(e[names[i]]); } } else { for (key in e) if (e[has](key)) { splice.push(e[key]); } } cur.splice.apply(cur, splice); } } for (i = 0, ii = cur.length; i < ii; i++) { e = cur[i]; while (e.n) { if (f) { if (e.f) { for (j = 0, jj = e.f.length; j < jj; j++) if (e.f[j] == f) { e.f.splice(j, 1); break; } !e.f.length && delete e.f; } for (key in e.n) if (e.n[has](key) && e.n[key].f) { var funcs = e.n[key].f; for (j = 0, jj = funcs.length; j < jj; j++) if (funcs[j] == f) { funcs.splice(j, 1); break; } !funcs.length && delete e.n[key].f; } } else { delete e.f; for (key in e.n) if (e.n[has](key) && e.n[key].f) { delete e.n[key].f; } } e = e.n; } } }; /*\ * eve.once [ method ] ** * Binds given event handler with a given name to only run once then unbind itself. | eve.once("login", f); | eve("login"); // triggers f | eve("login"); // no listeners * Use @eve to trigger the listener. ** > Arguments ** - name (string) name of the event, dot (`.`) or slash (`/`) separated, with optional wildcards - f (function) event handler function ** = (function) same return function as @eve.on \*/ eve.once = function (name, f) { var f2 = function () { eve.unbind(name, f2); return f.apply(this, arguments); }; return eve.on(name, f2); }; /*\ * eve.version [ property (string) ] ** * Current version of the library. \*/ eve.version = version; eve.toString = function () { return "You are running Eve " + version; }; (typeof module != "undefined" && module.exports) ? (module.exports = eve) : (typeof define != "undefined" ? (define("eve", [], function() { return eve; })) : (glob.eve = eve)); })(this); // ┌─────────────────────────────────────────────────────────────────────┐ \\ // │ "Raphaël 2.1.0" - JavaScript Vector Library │ \\ // ├─────────────────────────────────────────────────────────────────────┤ \\ // │ Copyright (c) 2008-2011 Dmitry Baranovskiy (http://raphaeljs.com) │ \\ // │ Copyright (c) 2008-2011 Sencha Labs (http://sencha.com) │ \\ // │ Licensed under the MIT (http://raphaeljs.com/license.html) license. │ \\ // └─────────────────────────────────────────────────────────────────────┘ \\ (function (glob, factory) { // AMD support if (typeof define === "function" && define.amd) { // Define as an anonymous module define(["eve"], function( eve ) { return factory(glob, eve); }); } else { // Browser globals (glob is window) // Raphael adds itself to window factory(glob, glob.eve); } }(this, function (window, eve) { /*\ * Raphael [ method ] ** * Creates a canvas object on which to draw. * You must do this first, as all future calls to drawing methods * from this instance will be bound to this canvas. > Parameters ** - container (HTMLElement|string) DOM element or its ID which is going to be a parent for drawing surface - width (number) - height (number) - callback (function) #optional callback function which is going to be executed in the context of newly created paper * or - x (number) - y (number) - width (number) - height (number) - callback (function) #optional callback function which is going to be executed in the context of newly created paper * or - all (array) (first 3 or 4 elements in the array are equal to [containerID, width, height] or [x, y, width, height]. The rest are element descriptions in format {type: type, <attributes>}). See @Paper.add. - callback (function) #optional callback function which is going to be executed in the context of newly created paper * or - onReadyCallback (function) function that is going to be called on DOM ready event. You can also subscribe to this event via Eve’s “DOMLoad” event. In this case method returns `undefined`. = (object) @Paper > Usage | // Each of the following examples create a canvas | // that is 320px wide by 200px high. | // Canvas is created at the viewport’s 10,50 coordinate. | var paper = Raphael(10, 50, 320, 200); | // Canvas is created at the top left corner of the #notepad element | // (or its top right corner in dir="rtl" elements) | var paper = Raphael(document.getElementById("notepad"), 320, 200); | // Same as above | var paper = Raphael("notepad", 320, 200); | // Image dump | var set = Raphael(["notepad", 320, 200, { | type: "rect", | x: 10, | y: 10, | width: 25, | height: 25, | stroke: "#f00" | }, { | type: "text", | x: 30, | y: 40, | text: "Dump" | }]); \*/ function R(first) { if (R.is(first, "function")) { return loaded ? first() : eve.on("raphael.DOMload", first); } else if (R.is(first, array)) { return R._engine.create[apply](R, first.splice(0, 3 + R.is(first[0], nu))).add(first); } else { var args = Array.prototype.slice.call(arguments, 0); if (R.is(args[args.length - 1], "function")) { var f = args.pop(); return loaded ? f.call(R._engine.create[apply](R, args)) : eve.on("raphael.DOMload", function () { f.call(R._engine.create[apply](R, args)); }); } else { return R._engine.create[apply](R, arguments); } } } R.version = "2.1.0"; R.eve = eve; var loaded, separator = /[, ]+/, elements = {circle: 1, rect: 1, path: 1, ellipse: 1, text: 1, image: 1}, formatrg = /\{(\d+)\}/g, proto = "prototype", has = "hasOwnProperty", g = { doc: document, win: window }, oldRaphael = { was: Object.prototype[has].call(g.win, "Raphael"), is: g.win.Raphael }, Paper = function () { /*\ * Paper.ca [ property (object) ] ** * Shortcut for @Paper.customAttributes \*/ /*\ * Paper.customAttributes [ property (object) ] ** * If you have a set of attributes that you would like to represent * as a function of some number you can do it easily with custom attributes: > Usage | paper.customAttributes.hue = function (num) { | num = num % 1; | return {fill: "hsb(" + num + ", 0.75, 1)"}; | }; | // Custom attribute “hue” will change fill | // to be given hue with fixed saturation and brightness. | // Now you can use it like this: | var c = paper.circle(10, 10, 10).attr({hue: .45}); | // or even like this: | c.animate({hue: 1}, 1e3); | | // You could also create custom attribute | // with multiple parameters: | paper.customAttributes.hsb = function (h, s, b) { | return {fill: "hsb(" + [h, s, b].join(",") + ")"}; | }; | c.attr({hsb: "0.5 .8 1"}); | c.animate({hsb: [1, 0, 0.5]}, 1e3); \*/ this.ca = this.customAttributes = {}; }, paperproto, appendChild = "appendChild", apply = "apply", concat = "concat", supportsTouch = ('ontouchstart' in g.win) || g.win.DocumentTouch && g.doc instanceof DocumentTouch, //taken from Modernizr touch test E = "", S = " ", Str = String, split = "split", events = "click dblclick mousedown mousemove mouseout mouseover mouseup touchstart touchmove touchend touchcancel"[split](S), touchMap = { mousedown: "touchstart", mousemove: "touchmove", mouseup: "touchend" }, lowerCase = Str.prototype.toLowerCase, math = Math, mmax = math.max, mmin = math.min, abs = math.abs, pow = math.pow, PI = math.PI, nu = "number", string = "string", array = "array", toString = "toString", fillString = "fill", objectToString = Object.prototype.toString, paper = {}, push = "push", ISURL = R._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*\)|hsba?\(\s*([\d\.]+(?:deg|\xb0|%)?\s*,\s*[\d\.]+%?\s*,\s*[\d\.]+(?:%?\s*,\s*[\d\.]+)?)%?\s*\)|hsla?\(\s*([\d\.]+(?:deg|\xb0|%)?\s*,\s*[\d\.]+%?\s*,\s*[\d\.]+(?:%?\s*,\s*[\d\.]+)?)%?\s*\))\s*$/i, isnan = {"NaN": 1, "Infinity": 1, "-Infinity": 1}, bezierrg = /^(?:cubic-)?bezier\(([^,]+),([^,]+),([^,]+),([^\)]+)\)/, round = math.round, setAttribute = "setAttribute", toFloat = parseFloat, toInt = parseInt, upperCase = Str.prototype.toUpperCase, availableAttrs = R._availableAttrs = { "arrow-end": "none", "arrow-start": "none", 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/", "letter-spacing": 0, opacity: 1, path: "M0,0", r: 0, rx: 0, ry: 0, 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", transform: "", width: 0, x: 0, y: 0 }, availableAnimAttrs = R._availableAnimAttrs = { 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, rx: nu, ry: nu, stroke: "colour", "stroke-opacity": nu, "stroke-width": nu, transform: "transform", width: nu, x: nu, y: nu }, whitespace = /[\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]/g, commaSpaces = /[\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]*,[\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]*/, hsrg = {hs: 1, rg: 1}, p2s = /,?([achlmqrstvxz]),?/gi, pathCommand = /([achlmrqstvz])[\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,]*((-?\d*\.?\d*(?:e[\-+]?\d+)?[\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]*,?[\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]*)+)/ig, tCommand = /([rstm])[\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,]*((-?\d*\.?\d*(?:e[\-+]?\d+)?[\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]*,?[\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]*)+)/ig, pathValues = /(-?\d*\.?\d*(?:e[\-+]?\d+)?)[\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]*,?[\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]*/ig, radial_gradient = R._radial_gradient = /^r(?:\(([^,]+?)[\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]*,[\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]*([^\)]+?)\))?/, eldata = {}, sortByKey = function (a, b) { return a.key - b.key; }, sortByNumber = function (a, b) { return toFloat(a) - toFloat(b); }, fun = function () {}, pipe = function (x) { return x; }, rectPath = R._rectPath = function (x, y, w, h, r) { if (r) { return [["M", x + r, y], ["l", w - r * 2, 0], ["a", r, r, 0, 0, 1, r, r], ["l", 0, h - r * 2], ["a", r, r, 0, 0, 1, -r, r], ["l", r * 2 - w, 0], ["a", r, r, 0, 0, 1, -r, -r], ["l", 0, r * 2 - h], ["a", r, r, 0, 0, 1, r, -r], ["z"]]; } return [["M", x, y], ["l", w, 0], ["l", 0, h], ["l", -w, 0], ["z"]]; }, ellipsePath = function (x, y, rx, ry) { if (ry == null) { ry = rx; } return [["M", x, y], ["m", 0, -ry], ["a", rx, ry, 0, 1, 1, 0, 2 * ry], ["a", rx, ry, 0, 1, 1, 0, -2 * ry], ["z"]]; }, getPath = R._getPath = { path: function (el) { return el.attr("path"); }, circle: function (el) { var a = el.attrs; return ellipsePath(a.cx, a.cy, a.r); }, ellipse: function (el) { var a = el.attrs; return ellipsePath(a.cx, a.cy, a.rx, a.ry); }, rect: function (el) { var a = el.attrs; return rectPath(a.x, a.y, a.width, a.height, a.r); }, image: function (el) { var a = el.attrs; return rectPath(a.x, a.y, a.width, a.height); }, text: function (el) { var bbox = el._getBBox(); return rectPath(bbox.x, bbox.y, bbox.width, bbox.height); }, set : function(el) { var bbox = el._getBBox(); return rectPath(bbox.x, bbox.y, bbox.width, bbox.height); } }, /*\ * Raphael.mapPath [ method ] ** * Transform the path string with given matrix. > Parameters - path (string) path string - matrix (object) see @Matrix = (string) transformed path string \*/ mapPath = R.mapPath = function (path, matrix) { if (!matrix) { return path; } var x, y, i, j, ii, jj, pathi; path = path2curve(path); for (i = 0, ii = path.length; i < ii; i++) { pathi = path[i]; for (j = 1, jj = pathi.length; j < jj; j += 2) { x = matrix.x(pathi[j], pathi[j + 1]); y = matrix.y(pathi[j], pathi[j + 1]); pathi[j] = x; pathi[j + 1] = y; } } return path; }; R._g = g; /*\ * Raphael.type [ property (string) ] ** * Can be “SVG”, “VML” or empty, depending on browser support. \*/ R.type = (g.win.SVGAngle || g.doc.implementation.hasFeature("http://www.w3.org/TR/SVG11/feature#BasicStructure", "1.1") ? "SVG" : "VML"); if (R.type == "VML") { var d = g.doc.createElement("div"), b; d.innerHTML = '<v:shape adj="1"/>'; b = d.firstChild; b.style.behavior = "url(#default#VML)"; if (!(b && typeof b.adj == "object")) { return (R.type = E); } d = null; } /*\ * Raphael.svg [ property (boolean) ] ** * `true` if browser supports SVG. \*/ /*\ * Raphael.vml [ property (boolean) ] ** * `true` if browser supports VML. \*/ R.svg = !(R.vml = R.type == "VML"); R._Paper = Paper; /*\ * Raphael.fn [ property (object) ] ** * You can add your own method to the canvas. For example if you want to draw a pie chart, * you can create your own pie chart function and ship it as a Raphaël plugin. To do this * you need to extend the `Raphael.fn` object. You should modify the `fn` object before a * Raphaël instance is created, otherwise it will take no effect. Please note that the * ability for namespaced plugins was removed in Raphael 2.0. It is up to the plugin to * ensure any namespacing ensures proper context. > Usage | Raphael.fn.arrow = function (x1, y1, x2, y2, size) { | return this.path( ... ); | }; | // or create namespace | Raphael.fn.mystuff = { | arrow: function () {…}, | star: function () {…}, | // etc… | }; | var paper = Raphael(10, 10, 630, 480); | // then use it | paper.arrow(10, 10, 30, 30, 5).attr({fill: "#f00"}); | paper.mystuff.arrow(); | paper.mystuff.star(); \*/ R.fn = paperproto = Paper.prototype = R.prototype; R._id = 0; R._oid = 0; /*\ * Raphael.is [ method ] ** * Handfull replacement for `typeof` operator. > Parameters - o (…) any object or primitive - type (string) name of the type, i.e. “string”, “function”, “number”, etc. = (boolean) is given value is of given type \*/ R.is = function (o, type) { type = lowerCase.call(type); if (type == "finite") { return !isnan[has](+o); } if (type == "array") { return o instanceof Array; } return (type == "null" && o === null) || (type == typeof o && o !== null) || (type == "object" && o === Object(o)) || (type == "array" && Array.isArray && Array.isArray(o)) || objectToString.call(o).slice(8, -1).toLowerCase() == type; }; function clone(obj) { if (Object(obj) !== obj) { return obj; } var res = new obj.constructor; for (var key in obj) if (obj[has](key)) { res[key] = clone(obj[key]); } return res; } /*\ * Raphael.angle [ method ] ** * Returns angle between two or three points > Parameters - x1 (number) x coord of first point - y1 (number) y coord of first point - x2 (number) x coord of second point - y2 (number) y coord of second point - x3 (number) #optional x coord of third point - y3 (number) #optional y coord of third point = (number) angle in degrees. \*/ R.angle = function (x1, y1, x2, y2, x3, y3) { if (x3 == null) { var x = x1 - x2, y = y1 - y2; if (!x && !y) { return 0; } return (180 + math.atan2(-y, -x) * 180 / PI + 360) % 360; } else { return R.angle(x1, y1, x3, y3) - R.angle(x2, y2, x3, y3); } }; /*\ * Raphael.rad [ method ] ** * Transform angle to radians > Parameters - deg (number) angle in degrees = (number) angle in radians. \*/ R.rad = function (deg) { return deg % 360 * PI / 180; }; /*\ * Raphael.deg [ method ] ** * Transform angle to degrees > Parameters - deg (number) angle in radians = (number) angle in degrees. \*/ R.deg = function (rad) { return rad * 180 / PI % 360; }; /*\ * Raphael.snapTo [ method ] ** * Snaps given value to given grid. > Parameters - values (array|number) given array of values or step of the grid - value (number) value to adjust - tolerance (number) #optional tolerance for snapping. Default is `10`. = (number) adjusted value. \*/ R.snapTo = function (values, value, tolerance) { tolerance = R.is(tolerance, "finite") ? tolerance : 10; if (R.is(values, array)) { var i = values.length; while (i--) if (abs(values[i] - value) <= tolerance) { return values[i]; } } else { values = +values; var rem = value % values; if (rem < tolerance) { return value - rem; } if (rem > values - tolerance) { return value - rem + values; } } return value; }; /*\ * Raphael.createUUID [ method ] ** * Returns RFC4122, version 4 ID \*/ var createUUID = R.createUUID = (function (uuidRegEx, uuidReplacer) { return function () { return "xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx".replace(uuidRegEx, uuidReplacer).toUpperCase(); }; })(/[xy]/g, function (c) { var r = math.random() * 16 | 0, v = c == "x" ? r : (r & 3 | 8); return v.toString(16); }); /*\ * Raphael.setWindow [ method ] ** * Used when you need to draw in `&lt;iframe>`. Switched window to the iframe one. > Parameters - newwin (window) new window object \*/ R.setWindow = function (newwin) { eve("raphael.setWindow", R, g.win, newwin); g.win = newwin; g.doc = g.win.document; if (R._engine.initWin) { R._engine.initWin(g.win); } }; var toHex = function (color) { if (R.vml) { // http://dean.edwards.name/weblog/2009/10/convert-any-colour-value-to-hex-in-msie/ var trim = /^\s+|\s+$/g; var bod; try { var docum = new ActiveXObject("htmlfile"); docum.write("<body>"); docum.close(); bod = docum.body; } catch(e) { bod = createPopup().document.body; } var range = bod.createTextRange(); toHex = cacher(function (color) { try { bod.style.color = Str(color).replace(trim, E); var value = range.queryCommandValue("ForeColor"); value = ((value & 255) << 16) | (value & 65280) | ((value & 16711680) >>> 16); return "#" + ("000000" + value.toString(16)).slice(-6); } catch(e) { return "none"; } }); } else { var i = g.doc.createElement("i"); i.title = "Rapha\xebl Colour Picker"; i.style.display = "none"; g.doc.body.appendChild(i); toHex = cacher(function (color) { i.style.color = color; return g.doc.defaultView.getComputedStyle(i, E).getPropertyValue("color"); }); } return toHex(color); }, hsbtoString = function () { return "hsb(" + [this.h, this.s, this.b] + ")"; }, hsltoString = function () { return "hsl(" + [this.h, this.s, this.l] + ")"; }, rgbtoString = function () { return this.hex; }, prepareRGB = function (r, g, b) { if (g == null && R.is(r, "object") && "r" in r && "g" in r && "b" in r) { b = r.b; g = r.g; r = r.r; } if (g == null && R.is(r, string)) { var clr = R.getRGB(r); r = clr.r; g = clr.g; b = clr.b; } if (r > 1 || g > 1 || b > 1) { r /= 255; g /= 255; b /= 255; } return [r, g, b]; }, packageRGB = function (r, g, b, o) { r *= 255; g *= 255; b *= 255; var rgb = { r: r, g: g, b: b, hex: R.rgb(r, g, b), toString: rgbtoString }; R.is(o, "finite") && (rgb.opacity = o); return rgb; }; /*\ * Raphael.color [ method ] ** * Parses the color string and returns object with all values for the given color. > Parameters - clr (string) color string in one of the supported formats (see @Raphael.getRGB) = (object) Combined RGB & HSB object in format: o { o r (number) red, o g (number) green, o b (number) blue, o hex (string) color in HTML/CSS format: #••••••, o error (boolean) `true` if string can’t be parsed, o h (number) hue, o s (number) saturation, o v (number) value (brightness), o l (number) lightness o } \*/ R.color = function (clr) { var rgb; if (R.is(clr, "object") && "h" in clr && "s" in clr && "b" in clr) { rgb = R.hsb2rgb(clr); clr.r = rgb.r; clr.g = rgb.g; clr.b = rgb.b; clr.hex = rgb.hex; } else if (R.is(clr, "object") && "h" in clr && "s" in clr && "l" in clr) { rgb = R.hsl2rgb(clr); clr.r = rgb.r; clr.g = rgb.g; clr.b = rgb.b; clr.hex = rgb.hex; } else { if (R.is(clr, "string")) { clr = R.getRGB(clr); } if (R.is(clr, "object") && "r" in clr && "g" in clr && "b" in clr) { rgb = R.rgb2hsl(clr); clr.h = rgb.h; clr.s = rgb.s; clr.l = rgb.l; rgb = R.rgb2hsb(clr); clr.v = rgb.b; } else { clr = {hex: "none"}; clr.r = clr.g = clr.b = clr.h = clr.s = clr.v = clr.l = -1; } } clr.toString = rgbtoString; return clr; }; /*\ * Raphael.hsb2rgb [ method ] ** * Converts HSB values to RGB object. > Parameters - h (number) hue - s (number) saturation - v (number) value or brightness = (object) RGB object in format: o { o r (number) red, o g (number) green, o b (number) blue, o hex (string) color in HTML/CSS format: #•••••• o } \*/ R.hsb2rgb = function (h, s, v, o) { if (this.is(h, "object") && "h" in h && "s" in h && "b" in h) { v = h.b; s = h.s; h = h.h; o = h.o; } h *= 360; var R, G, B, X, C; h = (h % 360) / 60; C = v * s; X = C * (1 - abs(h % 2 - 1)); R = G = B = v - C; h = ~~h; R += [C, X, 0, 0, X, C][h]; G += [X, C, C, X, 0, 0][h]; B += [0, 0, X, C, C, X][h]; return packageRGB(R, G, B, o); }; /*\ * Raphael.hsl2rgb [ method ] ** * Converts HSL values to RGB object. > Parameters - h (number) hue - s (number) saturation - l (number) luminosity = (object) RGB object in format: o { o r (number) red, o g (number) green, o b (number) blue, o hex (string) color in HTML/CSS format: #•••••• o } \*/ R.hsl2rgb = function (h, s, l, o) { if (this.is(h, "object") && "h" in h && "s" in h && "l" in h) { l = h.l; s = h.s; h = h.h; } if (h > 1 || s > 1 || l > 1) { h /= 360; s /= 100; l /= 100; } h *= 360; var R, G, B, X, C; h = (h % 360) / 60; C = 2 * s * (l < .5 ? l : 1 - l); X = C * (1 - abs(h % 2 - 1)); R = G = B = l - C / 2; h = ~~h; R += [C, X, 0, 0, X, C][h]; G += [X, C, C, X, 0, 0][h]; B += [0, 0, X, C, C, X][h]; return packageRGB(R, G, B, o); }; /*\ * Raphael.rgb2hsb [ method ] ** * Converts RGB values to HSB object. > Parameters - r (number) red - g (number) green - b (number) blue = (object) HSB object in format: o { o h (number) hue o s (number) saturation o b (number) brightness o } \*/ R.rgb2hsb = function (r, g, b) { b = prepareRGB(r, g, b); r = b[0]; g = b[1]; b = b[2]; var H, S, V, C; V = mmax(r, g, b); C = V - mmin(r, g, b); H = (C == 0 ? null : V == r ? (g - b) / C : V == g ? (b - r) / C + 2 : (r - g) / C + 4 ); H = ((H + 360) % 6) * 60 / 360; S = C == 0 ? 0 : C / V; return {h: H, s: S, b: V, toString: hsbtoString}; }; /*\ * Raphael.rgb2hsl [ method ] ** * Converts RGB values to HSL object. > Parameters - r (number) red - g (number) green - b (number) blue = (object) HSL object in format: o { o h (number) hue o s (number) saturation o l (number) luminosity o } \*/ R.rgb2hsl = function (r, g, b) { b = prepareRGB(r, g, b); r = b[0]; g = b[1]; b = b[2]; var H, S, L, M, m, C; M = mmax(r, g, b); m = mmin(r, g, b); C = M - m; H = (C == 0 ? null : M == r ? (g - b) / C : M == g ? (b - r) / C + 2 : (r - g) / C + 4); H = ((H + 360) % 6) * 60 / 360; L = (M + m) / 2; S = (C == 0 ? 0 : L < .5 ? C / (2 * L) : C / (2 - 2 * L)); return {h: H, s: S, l: L, toString: hsltoString}; }; R._path2string = function () { return this.join(",").replace(p2s, "$1"); }; function repush(array, item) { for (var i = 0, ii = array.length; i < ii; i++) if (array[i] === item) { return array.push(array.splice(i, 1)[0]); } } function cacher(f, scope, postprocessor) { function newf() { var arg = Array.prototype.slice.call(arguments, 0), args = arg.join("\u2400"), cache = newf.cache = newf.cache || {}, count = newf.count = newf.count || []; if (cache[has](args)) { repush(count, args); return postprocessor ? postprocessor(cache[args]) : cache[args]; } count.length >= 1e3 && delete cache[count.shift()]; count.push(args); cache[args] = f[apply](scope, arg); return postprocessor ? postprocessor(cache[args]) : cache[args]; } return newf; } var preload = R._preload = function (src, f) { var img = g.doc.createElement("img"); img.style.cssText = "position:absolute;left:-9999em;top:-9999em"; img.onload = function () { f.call(this); this.onload = null; g.doc.body.removeChild(this); }; img.onerror = function () { g.doc.body.removeChild(this); }; g.doc.body.appendChild(img); img.src = src; }; function clrToString() { return this.hex; } /*\ * Raphael.getRGB [ method ] ** * Parses colour string as RGB object > Parameters - colour (string) colour string in one of formats: # <ul> # <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>#•••••• — 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(•••%, •••%, •••%) — 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(•••%, •••%, •••%) — same as above, but in %</li> # <li>hsl(•••, •••, •••) — same as hsb</li> # <li>hsl(•••%, •••%, •••%) — same as hsb</li> # </ul> = (object) RGB object in format: o { o r (number) red, o g (number) green, o b (number) blue o hex (string) color in HTML/CSS format: #••••••, o error (boolean) true if string can’t be parsed o } \*/ R.getRGB = cacher(function (colour) { if (!colour || !!((colour = Str(colour)).indexOf("-") + 1)) { return {r: -1, g: -1, b: -1, hex: "none", error: 1, toString: clrToString}; } if (colour == "none") { return {r: -1, g: -1, b: -1, hex: "none", toString: clrToString}; } !(hsrg[has](colour.toLowerCase().substring(0, 2)) || colour.charAt() == "#") && (colour = toHex(colour)); var res, red, green, blue, opacity, t, values, rgb = colour.match(colourRegExp); if (rgb) { if (rgb[2]) { blue = toInt(rgb[2].substring(5), 16); green = toInt(rgb[2].substring(3, 5), 16); red = toInt(rgb[2].substring(1, 3), 16); } if (rgb[3]) { 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]) { values = rgb[4][split](commaSpaces); red = toFloat(values[0]); values[0].slice(-1) == "%" && (red *= 2.55); green = toFloat(values[1]); values[1].slice(-1) == "%" && (green *= 2.55); blue = toFloat(values[2]); values[2].slice(-1) == "%" && (blue *= 2.55); rgb[1].toLowerCase().slice(0, 4) == "rgba" && (opacity = toFloat(values[3])); values[3] && values[3].slice(-1) == "%" && (opacity /= 100); } if (rgb[5]) { values = rgb[5][split](commaSpaces); red = toFloat(values[0]); values[0].slice(-1) == "%" && (red *= 2.55); green = toFloat(values[1]); values[1].slice(-1) == "%" && (green *= 2.55); blue = toFloat(values[2]); values[2].slice(-1) == "%" && (blue *= 2.55); (values[0].slice(-3) == "deg" || values[0].slice(-1) == "\xb0") && (red /= 360); rgb[1].toLowerCase().slice(0, 4) == "hsba" && (opacity = toFloat(values[3])); values[3] && values[3].slice(-1) == "%" && (opacity /= 100); return R.hsb2rgb(red, green, blue, opacity); } if (rgb[6]) { values = rgb[6][split](commaSpaces); red = toFloat(values[0]); values[0].slice(-1) == "%" && (red *= 2.55); green = toFloat(values[1]); values[1].slice(-1) == "%" && (green *= 2.55); blue = toFloat(values[2]); values[2].slice(-1) == "%" && (blue *= 2.55); (values[0].slice(-3) == "deg" || values[0].slice(-1) == "\xb0") && (red /= 360); rgb[1].toLowerCase().slice(0, 4) == "hsla" && (opacity = toFloat(values[3])); values[3] && values[3].slice(-1) == "%" && (opacity /= 100); return R.hsl2rgb(red, green, blue, opacity); } rgb = {r: red, g: green, b: blue, toString: clrToString}; rgb.hex = "#" + (16777216 | blue | (green << 8) | (red << 16)).toString(16).slice(1); R.is(opacity, "finite") && (rgb.opacity = opacity); return rgb; } return {r: -1, g: -1, b: -1, hex: "none", error: 1, toString: clrToString}; }, R); /*\ * Raphael.hsb [ method ] ** * Converts HSB values to hex representation of the colour. > Parameters - h (number) hue - s (number) saturation - b (number) value or brightness = (string) hex representation of the colour. \*/ R.hsb = cacher(function (h, s, b) { return R.hsb2rgb(h, s, b).hex; }); /*\ * Raphael.hsl [ method ] ** * Converts HSL values to hex representation of the colour. > Parameters - h (number) hue - s (number) saturation - l (number) luminosity = (string) hex representation of the colour. \*/ R.hsl = cacher(function (h, s, l) { return R.hsl2rgb(h, s, l).hex; }); /*\ * Raphael.rgb [ method ] ** * Converts RGB values to hex representation of the colour. > Parameters - r (number) red - g (number) green - b (number) blue = (string) hex representation of the colour. \*/ R.rgb = cacher(function (r, g, b) { return "#" + (16777216 | b | (g << 8) | (r << 16)).toString(16).slice(1); }); /*\ * Raphael.getColor [ method ] ** * On each call returns next colour in the spectrum. To reset it back to red call @Raphael.getColor.reset > Parameters - value (number) #optional brightness, default is `0.75` = (string) hex representation of the colour. \*/ R.getColor = function (value) { var start = this.getColor.start = this.getColor.start || {h: 0, s: 1, b: value || .75}, rgb = this.hsb2rgb(start.h, start.s, start.b); start.h += .075; if (start.h > 1) { start.h = 0; start.s -= .2; start.s <= 0 && (this.getColor.start = {h: 0, s: 1, b: start.b}); } return rgb.hex; }; /*\ * Raphael.getColor.reset [ method ] ** * Resets spectrum position for @Raphael.getColor back to red. \*/ R.getColor.reset = function () { delete this.start; }; // http://schepers.cc/getting-to-the-point function catmullRom2bezier(crp, z) { var d = []; for (var i = 0, iLen = crp.length; iLen - 2 * !z > i; i += 2) { var p = [