js-lib
Version:
常用js插件供项目调用
1,421 lines (1,394 loc) • 298 kB
JavaScript
// ┌────────────────────────────────────────────────────────────────────┐ \\
// │ 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 `<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, 100, 0)</code>”)</li>
# <li>rgb(•••%, •••%, •••%) — same as above, but in %: (“<code>rgb(100%, 175%, 0%)</code>”)</li>
# <li>hsb(•••, •••, •••) — hue, saturation and brightness values: (“<code>hsb(0.5, 0.25, 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 = [