GPQAPP

Форк
0
8438 строк · 303.3 Кб
1
// ┌───────────────────────────────────────────────────────────────────────────────────────────────────────┐ \\
2
// │ Raphaël 2.3.0 - JavaScript Vector Library                                                             │ \\
3
// ├───────────────────────────────────────────────────────────────────────────────────────────────────────┤ \\
4
// │ Copyright © 2008-2016 Dmitry Baranovskiy (http://raphaeljs.com)                                       │ \\
5
// │ Copyright © 2008-2016 Sencha Labs (http://sencha.com)                                                 │ \\
6
// ├───────────────────────────────────────────────────────────────────────────────────────────────────────┤ \\
7
// │ Licensed under the MIT (https://github.com/DmitryBaranovskiy/raphael/blob/master/license.txt) license.│ \\
8
// └───────────────────────────────────────────────────────────────────────────────────────────────────────┘ \\
9

10
(function webpackUniversalModuleDefinition(root, factory) {
11
	if(typeof exports === 'object' && typeof module === 'object')
12
		module.exports = factory();
13
	else if(typeof define === 'function' && define.amd)
14
		define([], factory);
15
	else if(typeof exports === 'object')
16
		exports["Raphael"] = factory();
17
	else
18
		root["Raphael"] = factory();
19
})(window, function() {
20
return /******/ (function(modules) { // webpackBootstrap
21
/******/ 	// The module cache
22
/******/ 	var installedModules = {};
23
/******/
24
/******/ 	// The require function
25
/******/ 	function __webpack_require__(moduleId) {
26
/******/
27
/******/ 		// Check if module is in cache
28
/******/ 		if(installedModules[moduleId]) {
29
/******/ 			return installedModules[moduleId].exports;
30
/******/ 		}
31
/******/ 		// Create a new module (and put it into the cache)
32
/******/ 		var module = installedModules[moduleId] = {
33
/******/ 			i: moduleId,
34
/******/ 			l: false,
35
/******/ 			exports: {}
36
/******/ 		};
37
/******/
38
/******/ 		// Execute the module function
39
/******/ 		modules[moduleId].call(module.exports, module, module.exports, __webpack_require__);
40
/******/
41
/******/ 		// Flag the module as loaded
42
/******/ 		module.l = true;
43
/******/
44
/******/ 		// Return the exports of the module
45
/******/ 		return module.exports;
46
/******/ 	}
47
/******/
48
/******/
49
/******/ 	// expose the modules object (__webpack_modules__)
50
/******/ 	__webpack_require__.m = modules;
51
/******/
52
/******/ 	// expose the module cache
53
/******/ 	__webpack_require__.c = installedModules;
54
/******/
55
/******/ 	// define getter function for harmony exports
56
/******/ 	__webpack_require__.d = function(exports, name, getter) {
57
/******/ 		if(!__webpack_require__.o(exports, name)) {
58
/******/ 			Object.defineProperty(exports, name, { enumerable: true, get: getter });
59
/******/ 		}
60
/******/ 	};
61
/******/
62
/******/ 	// define __esModule on exports
63
/******/ 	__webpack_require__.r = function(exports) {
64
/******/ 		if(typeof Symbol !== 'undefined' && Symbol.toStringTag) {
65
/******/ 			Object.defineProperty(exports, Symbol.toStringTag, { value: 'Module' });
66
/******/ 		}
67
/******/ 		Object.defineProperty(exports, '__esModule', { value: true });
68
/******/ 	};
69
/******/
70
/******/ 	// create a fake namespace object
71
/******/ 	// mode & 1: value is a module id, require it
72
/******/ 	// mode & 2: merge all properties of value into the ns
73
/******/ 	// mode & 4: return value when already ns object
74
/******/ 	// mode & 8|1: behave like require
75
/******/ 	__webpack_require__.t = function(value, mode) {
76
/******/ 		if(mode & 1) value = __webpack_require__(value);
77
/******/ 		if(mode & 8) return value;
78
/******/ 		if((mode & 4) && typeof value === 'object' && value && value.__esModule) return value;
79
/******/ 		var ns = Object.create(null);
80
/******/ 		__webpack_require__.r(ns);
81
/******/ 		Object.defineProperty(ns, 'default', { enumerable: true, value: value });
82
/******/ 		if(mode & 2 && typeof value != 'string') for(var key in value) __webpack_require__.d(ns, key, function(key) { return value[key]; }.bind(null, key));
83
/******/ 		return ns;
84
/******/ 	};
85
/******/
86
/******/ 	// getDefaultExport function for compatibility with non-harmony modules
87
/******/ 	__webpack_require__.n = function(module) {
88
/******/ 		var getter = module && module.__esModule ?
89
/******/ 			function getDefault() { return module['default']; } :
90
/******/ 			function getModuleExports() { return module; };
91
/******/ 		__webpack_require__.d(getter, 'a', getter);
92
/******/ 		return getter;
93
/******/ 	};
94
/******/
95
/******/ 	// Object.prototype.hasOwnProperty.call
96
/******/ 	__webpack_require__.o = function(object, property) { return Object.prototype.hasOwnProperty.call(object, property); };
97
/******/
98
/******/ 	// __webpack_public_path__
99
/******/ 	__webpack_require__.p = "";
100
/******/
101
/******/
102
/******/ 	// Load entry module and return exports
103
/******/ 	return __webpack_require__(__webpack_require__.s = "./dev/raphael.amd.js");
104
/******/ })
105
/************************************************************************/
106
/******/ ({
107

108
/***/ "./dev/raphael.amd.js":
109
/*!****************************!*\
110
  !*** ./dev/raphael.amd.js ***!
111
  \****************************/
112
/*! no static exports found */
113
/***/ (function(module, exports, __webpack_require__) {
114

115
var __WEBPACK_AMD_DEFINE_ARRAY__, __WEBPACK_AMD_DEFINE_RESULT__;!(__WEBPACK_AMD_DEFINE_ARRAY__ = [__webpack_require__(/*! ./raphael.core */ "./dev/raphael.core.js"), __webpack_require__(/*! ./raphael.svg */ "./dev/raphael.svg.js"), __webpack_require__(/*! ./raphael.vml */ "./dev/raphael.vml.js")], __WEBPACK_AMD_DEFINE_RESULT__ = (function(R) {
116

117
    return R;
118

119
}).apply(exports, __WEBPACK_AMD_DEFINE_ARRAY__),
120
				__WEBPACK_AMD_DEFINE_RESULT__ !== undefined && (module.exports = __WEBPACK_AMD_DEFINE_RESULT__));
121

122
/***/ }),
123

124
/***/ "./dev/raphael.core.js":
125
/*!*****************************!*\
126
  !*** ./dev/raphael.core.js ***!
127
  \*****************************/
128
/*! no static exports found */
129
/***/ (function(module, exports, __webpack_require__) {
130

131
var __WEBPACK_AMD_DEFINE_ARRAY__, __WEBPACK_AMD_DEFINE_RESULT__;!(__WEBPACK_AMD_DEFINE_ARRAY__ = [__webpack_require__(/*! eve */ "./node_modules/eve-raphael/eve.js")], __WEBPACK_AMD_DEFINE_RESULT__ = (function(eve) {
132

133
    /*\
134
     * Raphael
135
     [ method ]
136
     **
137
     * Creates a canvas object on which to draw.
138
     * You must do this first, as all future calls to drawing methods
139
     * from this instance will be bound to this canvas.
140
     > Parameters
141
     **
142
     - container (HTMLElement|string) DOM element or its ID which is going to be a parent for drawing surface
143
     - width (number)
144
     - height (number)
145
     - callback (function) #optional callback function which is going to be executed in the context of newly created paper
146
     * or
147
     - x (number)
148
     - y (number)
149
     - width (number)
150
     - height (number)
151
     - callback (function) #optional callback function which is going to be executed in the context of newly created paper
152
     * or
153
     - 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.
154
     - callback (function) #optional callback function which is going to be executed in the context of newly created paper
155
     * or
156
     - 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`.
157
     = (object) @Paper
158
     > Usage
159
     | // Each of the following examples create a canvas
160
     | // that is 320px wide by 200px high.
161
     | // Canvas is created at the viewport’s 10,50 coordinate.
162
     | var paper = Raphael(10, 50, 320, 200);
163
     | // Canvas is created at the top left corner of the #notepad element
164
     | // (or its top right corner in dir="rtl" elements)
165
     | var paper = Raphael(document.getElementById("notepad"), 320, 200);
166
     | // Same as above
167
     | var paper = Raphael("notepad", 320, 200);
168
     | // Image dump
169
     | var set = Raphael(["notepad", 320, 200, {
170
     |     type: "rect",
171
     |     x: 10,
172
     |     y: 10,
173
     |     width: 25,
174
     |     height: 25,
175
     |     stroke: "#f00"
176
     | }, {
177
     |     type: "text",
178
     |     x: 30,
179
     |     y: 40,
180
     |     text: "Dump"
181
     | }]);
182
    \*/
183
    function R(first) {
184
        if (R.is(first, "function")) {
185
            return loaded ? first() : eve.on("raphael.DOMload", first);
186
        } else if (R.is(first, array)) {
187
            return R._engine.create[apply](R, first.splice(0, 3 + R.is(first[0], nu))).add(first);
188
        } else {
189
            var args = Array.prototype.slice.call(arguments, 0);
190
            if (R.is(args[args.length - 1], "function")) {
191
                var f = args.pop();
192
                return loaded ? f.call(R._engine.create[apply](R, args)) : eve.on("raphael.DOMload", function () {
193
                    f.call(R._engine.create[apply](R, args));
194
                });
195
            } else {
196
                return R._engine.create[apply](R, arguments);
197
            }
198
        }
199
    }
200
    R.version = "2.3.0";
201
    R.eve = eve;
202
    var loaded,
203
        separator = /[, ]+/,
204
        elements = {circle: 1, rect: 1, path: 1, ellipse: 1, text: 1, image: 1},
205
        formatrg = /\{(\d+)\}/g,
206
        proto = "prototype",
207
        has = "hasOwnProperty",
208
        g = {
209
            doc: document,
210
            win: window
211
        },
212
        oldRaphael = {
213
            was: Object.prototype[has].call(g.win, "Raphael"),
214
            is: g.win.Raphael
215
        },
216
        Paper = function () {
217
            /*\
218
             * Paper.ca
219
             [ property (object) ]
220
             **
221
             * Shortcut for @Paper.customAttributes
222
            \*/
223
            /*\
224
             * Paper.customAttributes
225
             [ property (object) ]
226
             **
227
             * If you have a set of attributes that you would like to represent
228
             * as a function of some number you can do it easily with custom attributes:
229
             > Usage
230
             | paper.customAttributes.hue = function (num) {
231
             |     num = num % 1;
232
             |     return {fill: "hsb(" + num + ", 0.75, 1)"};
233
             | };
234
             | // Custom attribute “hue” will change fill
235
             | // to be given hue with fixed saturation and brightness.
236
             | // Now you can use it like this:
237
             | var c = paper.circle(10, 10, 10).attr({hue: .45});
238
             | // or even like this:
239
             | c.animate({hue: 1}, 1e3);
240
             |
241
             | // You could also create custom attribute
242
             | // with multiple parameters:
243
             | paper.customAttributes.hsb = function (h, s, b) {
244
             |     return {fill: "hsb(" + [h, s, b].join(",") + ")"};
245
             | };
246
             | c.attr({hsb: "0.5 .8 1"});
247
             | c.animate({hsb: [1, 0, 0.5]}, 1e3);
248
            \*/
249
            this.ca = this.customAttributes = {};
250
        },
251
        paperproto,
252
        appendChild = "appendChild",
253
        apply = "apply",
254
        concat = "concat",
255
        //taken from Modernizr touch test: https://github.com/Modernizr/Modernizr/blob/master/feature-detects/touchevents.js#L40
256
        supportsTouch = ('ontouchstart' in window) || window.TouchEvent || window.DocumentTouch && document instanceof DocumentTouch,
257
        E = "",
258
        S = " ",
259
        Str = String,
260
        split = "split",
261
        events = "click dblclick mousedown mousemove mouseout mouseover mouseup touchstart touchmove touchend touchcancel"[split](S),
262
        touchMap = {
263
            mousedown: "touchstart",
264
            mousemove: "touchmove",
265
            mouseup: "touchend"
266
        },
267
        lowerCase = Str.prototype.toLowerCase,
268
        math = Math,
269
        mmax = math.max,
270
        mmin = math.min,
271
        abs = math.abs,
272
        pow = math.pow,
273
        PI = math.PI,
274
        nu = "number",
275
        string = "string",
276
        array = "array",
277
        toString = "toString",
278
        fillString = "fill",
279
        objectToString = Object.prototype.toString,
280
        paper = {},
281
        push = "push",
282
        ISURL = R._ISURL = /^url\(['"]?(.+?)['"]?\)$/i,
283
        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,
284
        isnan = {"NaN": 1, "Infinity": 1, "-Infinity": 1},
285
        bezierrg = /^(?:cubic-)?bezier\(([^,]+),([^,]+),([^,]+),([^\)]+)\)/,
286
        round = math.round,
287
        setAttribute = "setAttribute",
288
        toFloat = parseFloat,
289
        toInt = parseInt,
290
        upperCase = Str.prototype.toUpperCase,
291
        availableAttrs = R._availableAttrs = {
292
            "arrow-end": "none",
293
            "arrow-start": "none",
294
            blur: 0,
295
            "clip-rect": "0 0 1e9 1e9",
296
            cursor: "default",
297
            cx: 0,
298
            cy: 0,
299
            fill: "#fff",
300
            "fill-opacity": 1,
301
            font: '10px "Arial"',
302
            "font-family": '"Arial"',
303
            "font-size": "10",
304
            "font-style": "normal",
305
            "font-weight": 400,
306
            gradient: 0,
307
            height: 0,
308
            href: "http://raphaeljs.com/",
309
            "letter-spacing": 0,
310
            opacity: 1,
311
            path: "M0,0",
312
            r: 0,
313
            rx: 0,
314
            ry: 0,
315
            src: "",
316
            stroke: "#000",
317
            "stroke-dasharray": "",
318
            "stroke-linecap": "butt",
319
            "stroke-linejoin": "butt",
320
            "stroke-miterlimit": 0,
321
            "stroke-opacity": 1,
322
            "stroke-width": 1,
323
            target: "_blank",
324
            "text-anchor": "middle",
325
            title: "Raphael",
326
            transform: "",
327
            width: 0,
328
            x: 0,
329
            y: 0,
330
            "class": ""
331
        },
332
        availableAnimAttrs = R._availableAnimAttrs = {
333
            blur: nu,
334
            "clip-rect": "csv",
335
            cx: nu,
336
            cy: nu,
337
            fill: "colour",
338
            "fill-opacity": nu,
339
            "font-size": nu,
340
            height: nu,
341
            opacity: nu,
342
            path: "path",
343
            r: nu,
344
            rx: nu,
345
            ry: nu,
346
            stroke: "colour",
347
            "stroke-opacity": nu,
348
            "stroke-width": nu,
349
            transform: "transform",
350
            width: nu,
351
            x: nu,
352
            y: nu
353
        },
354
        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,
355
        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]*/,
356
        hsrg = {hs: 1, rg: 1},
357
        p2s = /,?([achlmqrstvxz]),?/gi,
358
        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,
359
        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,
360
        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,
361
        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]*([^\)]+?)\))?/,
362
        eldata = {},
363
        sortByKey = function (a, b) {
364
            return a.key - b.key;
365
        },
366
        sortByNumber = function (a, b) {
367
            return toFloat(a) - toFloat(b);
368
        },
369
        fun = function () {},
370
        pipe = function (x) {
371
            return x;
372
        },
373
        rectPath = R._rectPath = function (x, y, w, h, r) {
374
            if (r) {
375
                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"]];
376
            }
377
            return [["M", x, y], ["l", w, 0], ["l", 0, h], ["l", -w, 0], ["z"]];
378
        },
379
        ellipsePath = function (x, y, rx, ry) {
380
            if (ry == null) {
381
                ry = rx;
382
            }
383
            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"]];
384
        },
385
        getPath = R._getPath = {
386
            path: function (el) {
387
                return el.attr("path");
388
            },
389
            circle: function (el) {
390
                var a = el.attrs;
391
                return ellipsePath(a.cx, a.cy, a.r);
392
            },
393
            ellipse: function (el) {
394
                var a = el.attrs;
395
                return ellipsePath(a.cx, a.cy, a.rx, a.ry);
396
            },
397
            rect: function (el) {
398
                var a = el.attrs;
399
                return rectPath(a.x, a.y, a.width, a.height, a.r);
400
            },
401
            image: function (el) {
402
                var a = el.attrs;
403
                return rectPath(a.x, a.y, a.width, a.height);
404
            },
405
            text: function (el) {
406
                var bbox = el._getBBox();
407
                return rectPath(bbox.x, bbox.y, bbox.width, bbox.height);
408
            },
409
            set : function(el) {
410
                var bbox = el._getBBox();
411
                return rectPath(bbox.x, bbox.y, bbox.width, bbox.height);
412
            }
413
        },
414
        /*\
415
         * Raphael.mapPath
416
         [ method ]
417
         **
418
         * Transform the path string with given matrix.
419
         > Parameters
420
         - path (string) path string
421
         - matrix (object) see @Matrix
422
         = (string) transformed path string
423
        \*/
424
        mapPath = R.mapPath = function (path, matrix) {
425
            if (!matrix) {
426
                return path;
427
            }
428
            var x, y, i, j, ii, jj, pathi;
429
            path = path2curve(path);
430
            for (i = 0, ii = path.length; i < ii; i++) {
431
                pathi = path[i];
432
                for (j = 1, jj = pathi.length; j < jj; j += 2) {
433
                    x = matrix.x(pathi[j], pathi[j + 1]);
434
                    y = matrix.y(pathi[j], pathi[j + 1]);
435
                    pathi[j] = x;
436
                    pathi[j + 1] = y;
437
                }
438
            }
439
            return path;
440
        };
441

442
    R._g = g;
443
    /*\
444
     * Raphael.type
445
     [ property (string) ]
446
     **
447
     * Can be “SVG”, “VML” or empty, depending on browser support.
448
    \*/
449
    R.type = (g.win.SVGAngle || g.doc.implementation.hasFeature("http://www.w3.org/TR/SVG11/feature#BasicStructure", "1.1") ? "SVG" : "VML");
450
    if (R.type == "VML") {
451
        var d = g.doc.createElement("div"),
452
            b;
453
        d.innerHTML = '<v:shape adj="1"/>';
454
        b = d.firstChild;
455
        b.style.behavior = "url(#default#VML)";
456
        if (!(b && typeof b.adj == "object")) {
457
            return (R.type = E);
458
        }
459
        d = null;
460
    }
461
    /*\
462
     * Raphael.svg
463
     [ property (boolean) ]
464
     **
465
     * `true` if browser supports SVG.
466
    \*/
467
    /*\
468
     * Raphael.vml
469
     [ property (boolean) ]
470
     **
471
     * `true` if browser supports VML.
472
    \*/
473
    R.svg = !(R.vml = R.type == "VML");
474
    R._Paper = Paper;
475
    /*\
476
     * Raphael.fn
477
     [ property (object) ]
478
     **
479
     * You can add your own method to the canvas. For example if you want to draw a pie chart,
480
     * you can create your own pie chart function and ship it as a Raphaël plugin. To do this
481
     * you need to extend the `Raphael.fn` object. You should modify the `fn` object before a
482
     * Raphaël instance is created, otherwise it will take no effect. Please note that the
483
     * ability for namespaced plugins was removed in Raphael 2.0. It is up to the plugin to
484
     * ensure any namespacing ensures proper context.
485
     > Usage
486
     | Raphael.fn.arrow = function (x1, y1, x2, y2, size) {
487
     |     return this.path( ... );
488
     | };
489
     | // or create namespace
490
     | Raphael.fn.mystuff = {
491
     |     arrow: function () {…},
492
     |     star: function () {…},
493
     |     // etc…
494
     | };
495
     | var paper = Raphael(10, 10, 630, 480);
496
     | // then use it
497
     | paper.arrow(10, 10, 30, 30, 5).attr({fill: "#f00"});
498
     | paper.mystuff.arrow();
499
     | paper.mystuff.star();
500
    \*/
501
    R.fn = paperproto = Paper.prototype = R.prototype;
502
    R._id = 0;
503
    /*\
504
     * Raphael.is
505
     [ method ]
506
     **
507
     * Handful of replacements for `typeof` operator.
508
     > Parameters
509
     - o (…) any object or primitive
510
     - type (string) name of the type, i.e. “string”, “function”, “number”, etc.
511
     = (boolean) is given value is of given type
512
    \*/
513
    R.is = function (o, type) {
514
        type = lowerCase.call(type);
515
        if (type == "finite") {
516
            return !isnan[has](+o);
517
        }
518
        if (type == "array") {
519
            return o instanceof Array;
520
        }
521
        return  (type == "null" && o === null) ||
522
                (type == typeof o && o !== null) ||
523
                (type == "object" && o === Object(o)) ||
524
                (type == "array" && Array.isArray && Array.isArray(o)) ||
525
                objectToString.call(o).slice(8, -1).toLowerCase() == type;
526
    };
527

528
    function clone(obj) {
529
        if (typeof obj == "function" || Object(obj) !== obj) {
530
            return obj;
531
        }
532
        var res = new obj.constructor;
533
        for (var key in obj) if (obj[has](key)) {
534
            res[key] = clone(obj[key]);
535
        }
536
        return res;
537
    }
538

539
    /*\
540
     * Raphael.angle
541
     [ method ]
542
     **
543
     * Returns angle between two or three points
544
     > Parameters
545
     - x1 (number) x coord of first point
546
     - y1 (number) y coord of first point
547
     - x2 (number) x coord of second point
548
     - y2 (number) y coord of second point
549
     - x3 (number) #optional x coord of third point
550
     - y3 (number) #optional y coord of third point
551
     = (number) angle in degrees.
552
    \*/
553
    R.angle = function (x1, y1, x2, y2, x3, y3) {
554
        if (x3 == null) {
555
            var x = x1 - x2,
556
                y = y1 - y2;
557
            if (!x && !y) {
558
                return 0;
559
            }
560
            return (180 + math.atan2(-y, -x) * 180 / PI + 360) % 360;
561
        } else {
562
            return R.angle(x1, y1, x3, y3) - R.angle(x2, y2, x3, y3);
563
        }
564
    };
565
    /*\
566
     * Raphael.rad
567
     [ method ]
568
     **
569
     * Transform angle to radians
570
     > Parameters
571
     - deg (number) angle in degrees
572
     = (number) angle in radians.
573
    \*/
574
    R.rad = function (deg) {
575
        return deg % 360 * PI / 180;
576
    };
577
    /*\
578
     * Raphael.deg
579
     [ method ]
580
     **
581
     * Transform angle to degrees
582
     > Parameters
583
     - rad (number) angle in radians
584
     = (number) angle in degrees.
585
    \*/
586
    R.deg = function (rad) {
587
        return Math.round ((rad * 180 / PI% 360)* 1000) / 1000;
588
    };
589
    /*\
590
     * Raphael.snapTo
591
     [ method ]
592
     **
593
     * Snaps given value to given grid.
594
     > Parameters
595
     - values (array|number) given array of values or step of the grid
596
     - value (number) value to adjust
597
     - tolerance (number) #optional tolerance for snapping. Default is `10`.
598
     = (number) adjusted value.
599
    \*/
600
    R.snapTo = function (values, value, tolerance) {
601
        tolerance = R.is(tolerance, "finite") ? tolerance : 10;
602
        if (R.is(values, array)) {
603
            var i = values.length;
604
            while (i--) if (abs(values[i] - value) <= tolerance) {
605
                return values[i];
606
            }
607
        } else {
608
            values = +values;
609
            var rem = value % values;
610
            if (rem < tolerance) {
611
                return value - rem;
612
            }
613
            if (rem > values - tolerance) {
614
                return value - rem + values;
615
            }
616
        }
617
        return value;
618
    };
619

620
    /*\
621
     * Raphael.createUUID
622
     [ method ]
623
     **
624
     * Returns RFC4122, version 4 ID
625
    \*/
626
    var createUUID = R.createUUID = (function (uuidRegEx, uuidReplacer) {
627
        return function () {
628
            return "xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx".replace(uuidRegEx, uuidReplacer).toUpperCase();
629
        };
630
    })(/[xy]/g, function (c) {
631
        var r = math.random() * 16 | 0,
632
            v = c == "x" ? r : (r & 3 | 8);
633
        return v.toString(16);
634
    });
635

636
    /*\
637
     * Raphael.setWindow
638
     [ method ]
639
     **
640
     * Used when you need to draw in `&lt;iframe>`. Switched window to the iframe one.
641
     > Parameters
642
     - newwin (window) new window object
643
    \*/
644
    R.setWindow = function (newwin) {
645
        eve("raphael.setWindow", R, g.win, newwin);
646
        g.win = newwin;
647
        g.doc = g.win.document;
648
        if (R._engine.initWin) {
649
            R._engine.initWin(g.win);
650
        }
651
    };
652
    var toHex = function (color) {
653
        if (R.vml) {
654
            // http://dean.edwards.name/weblog/2009/10/convert-any-colour-value-to-hex-in-msie/
655
            var trim = /^\s+|\s+$/g;
656
            var bod;
657
            try {
658
                var docum = new ActiveXObject("htmlfile");
659
                docum.write("<body>");
660
                docum.close();
661
                bod = docum.body;
662
            } catch(e) {
663
                bod = createPopup().document.body;
664
            }
665
            var range = bod.createTextRange();
666
            toHex = cacher(function (color) {
667
                try {
668
                    bod.style.color = Str(color).replace(trim, E);
669
                    var value = range.queryCommandValue("ForeColor");
670
                    value = ((value & 255) << 16) | (value & 65280) | ((value & 16711680) >>> 16);
671
                    return "#" + ("000000" + value.toString(16)).slice(-6);
672
                } catch(e) {
673
                    return "none";
674
                }
675
            });
676
        } else {
677
            var i = g.doc.createElement("i");
678
            i.title = "Rapha\xebl Colour Picker";
679
            i.style.display = "none";
680
            g.doc.body.appendChild(i);
681
            toHex = cacher(function (color) {
682
                i.style.color = color;
683
                return g.doc.defaultView.getComputedStyle(i, E).getPropertyValue("color");
684
            });
685
        }
686
        return toHex(color);
687
    },
688
    hsbtoString = function () {
689
        return "hsb(" + [this.h, this.s, this.b] + ")";
690
    },
691
    hsltoString = function () {
692
        return "hsl(" + [this.h, this.s, this.l] + ")";
693
    },
694
    rgbtoString = function () {
695
        return this.hex;
696
    },
697
    prepareRGB = function (r, g, b) {
698
        if (g == null && R.is(r, "object") && "r" in r && "g" in r && "b" in r) {
699
            b = r.b;
700
            g = r.g;
701
            r = r.r;
702
        }
703
        if (g == null && R.is(r, string)) {
704
            var clr = R.getRGB(r);
705
            r = clr.r;
706
            g = clr.g;
707
            b = clr.b;
708
        }
709
        if (r > 1 || g > 1 || b > 1) {
710
            r /= 255;
711
            g /= 255;
712
            b /= 255;
713
        }
714

715
        return [r, g, b];
716
    },
717
    packageRGB = function (r, g, b, o) {
718
        r *= 255;
719
        g *= 255;
720
        b *= 255;
721
        var rgb = {
722
            r: r,
723
            g: g,
724
            b: b,
725
            hex: R.rgb(r, g, b),
726
            toString: rgbtoString
727
        };
728
        R.is(o, "finite") && (rgb.opacity = o);
729
        return rgb;
730
    };
731

732
    /*\
733
     * Raphael.color
734
     [ method ]
735
     **
736
     * Parses the color string and returns object with all values for the given color.
737
     > Parameters
738
     - clr (string) color string in one of the supported formats (see @Raphael.getRGB)
739
     = (object) Combined RGB & HSB object in format:
740
     o {
741
     o     r (number) red,
742
     o     g (number) green,
743
     o     b (number) blue,
744
     o     hex (string) color in HTML/CSS format: #••••••,
745
     o     error (boolean) `true` if string can’t be parsed,
746
     o     h (number) hue,
747
     o     s (number) saturation,
748
     o     v (number) value (brightness),
749
     o     l (number) lightness
750
     o }
751
    \*/
752
    R.color = function (clr) {
753
        var rgb;
754
        if (R.is(clr, "object") && "h" in clr && "s" in clr && "b" in clr) {
755
            rgb = R.hsb2rgb(clr);
756
            clr.r = rgb.r;
757
            clr.g = rgb.g;
758
            clr.b = rgb.b;
759
            clr.hex = rgb.hex;
760
        } else if (R.is(clr, "object") && "h" in clr && "s" in clr && "l" in clr) {
761
            rgb = R.hsl2rgb(clr);
762
            clr.r = rgb.r;
763
            clr.g = rgb.g;
764
            clr.b = rgb.b;
765
            clr.hex = rgb.hex;
766
        } else {
767
            if (R.is(clr, "string")) {
768
                clr = R.getRGB(clr);
769
            }
770
            if (R.is(clr, "object") && "r" in clr && "g" in clr && "b" in clr) {
771
                rgb = R.rgb2hsl(clr);
772
                clr.h = rgb.h;
773
                clr.s = rgb.s;
774
                clr.l = rgb.l;
775
                rgb = R.rgb2hsb(clr);
776
                clr.v = rgb.b;
777
            } else {
778
                clr = {hex: "none"};
779
                clr.r = clr.g = clr.b = clr.h = clr.s = clr.v = clr.l = -1;
780
            }
781
        }
782
        clr.toString = rgbtoString;
783
        return clr;
784
    };
785
    /*\
786
     * Raphael.hsb2rgb
787
     [ method ]
788
     **
789
     * Converts HSB values to RGB object.
790
     > Parameters
791
     - h (number) hue
792
     - s (number) saturation
793
     - v (number) value or brightness
794
     = (object) RGB object in format:
795
     o {
796
     o     r (number) red,
797
     o     g (number) green,
798
     o     b (number) blue,
799
     o     hex (string) color in HTML/CSS format: #••••••
800
     o }
801
    \*/
802
    R.hsb2rgb = function (h, s, v, o) {
803
        if (this.is(h, "object") && "h" in h && "s" in h && "b" in h) {
804
            v = h.b;
805
            s = h.s;
806
            o = h.o;
807
            h = h.h;
808
        }
809
        h *= 360;
810
        var R, G, B, X, C;
811
        h = (h % 360) / 60;
812
        C = v * s;
813
        X = C * (1 - abs(h % 2 - 1));
814
        R = G = B = v - C;
815

816
        h = ~~h;
817
        R += [C, X, 0, 0, X, C][h];
818
        G += [X, C, C, X, 0, 0][h];
819
        B += [0, 0, X, C, C, X][h];
820
        return packageRGB(R, G, B, o);
821
    };
822
    /*\
823
     * Raphael.hsl2rgb
824
     [ method ]
825
     **
826
     * Converts HSL values to RGB object.
827
     > Parameters
828
     - h (number) hue
829
     - s (number) saturation
830
     - l (number) luminosity
831
     = (object) RGB object in format:
832
     o {
833
     o     r (number) red,
834
     o     g (number) green,
835
     o     b (number) blue,
836
     o     hex (string) color in HTML/CSS format: #••••••
837
     o }
838
    \*/
839
    R.hsl2rgb = function (h, s, l, o) {
840
        if (this.is(h, "object") && "h" in h && "s" in h && "l" in h) {
841
            l = h.l;
842
            s = h.s;
843
            h = h.h;
844
        }
845
        if (h > 1 || s > 1 || l > 1) {
846
            h /= 360;
847
            s /= 100;
848
            l /= 100;
849
        }
850
        h *= 360;
851
        var R, G, B, X, C;
852
        h = (h % 360) / 60;
853
        C = 2 * s * (l < .5 ? l : 1 - l);
854
        X = C * (1 - abs(h % 2 - 1));
855
        R = G = B = l - C / 2;
856

857
        h = ~~h;
858
        R += [C, X, 0, 0, X, C][h];
859
        G += [X, C, C, X, 0, 0][h];
860
        B += [0, 0, X, C, C, X][h];
861
        return packageRGB(R, G, B, o);
862
    };
863
    /*\
864
     * Raphael.rgb2hsb
865
     [ method ]
866
     **
867
     * Converts RGB values to HSB object.
868
     > Parameters
869
     - r (number) red
870
     - g (number) green
871
     - b (number) blue
872
     = (object) HSB object in format:
873
     o {
874
     o     h (number) hue
875
     o     s (number) saturation
876
     o     b (number) brightness
877
     o }
878
    \*/
879
    R.rgb2hsb = function (r, g, b) {
880
        b = prepareRGB(r, g, b);
881
        r = b[0];
882
        g = b[1];
883
        b = b[2];
884

885
        var H, S, V, C;
886
        V = mmax(r, g, b);
887
        C = V - mmin(r, g, b);
888
        H = (C == 0 ? null :
889
             V == r ? (g - b) / C :
890
             V == g ? (b - r) / C + 2 :
891
                      (r - g) / C + 4
892
            );
893
        H = ((H + 360) % 6) * 60 / 360;
894
        S = C == 0 ? 0 : C / V;
895
        return {h: H, s: S, b: V, toString: hsbtoString};
896
    };
897
    /*\
898
     * Raphael.rgb2hsl
899
     [ method ]
900
     **
901
     * Converts RGB values to HSL object.
902
     > Parameters
903
     - r (number) red
904
     - g (number) green
905
     - b (number) blue
906
     = (object) HSL object in format:
907
     o {
908
     o     h (number) hue
909
     o     s (number) saturation
910
     o     l (number) luminosity
911
     o }
912
    \*/
913
    R.rgb2hsl = function (r, g, b) {
914
        b = prepareRGB(r, g, b);
915
        r = b[0];
916
        g = b[1];
917
        b = b[2];
918

919
        var H, S, L, M, m, C;
920
        M = mmax(r, g, b);
921
        m = mmin(r, g, b);
922
        C = M - m;
923
        H = (C == 0 ? null :
924
             M == r ? (g - b) / C :
925
             M == g ? (b - r) / C + 2 :
926
                      (r - g) / C + 4);
927
        H = ((H + 360) % 6) * 60 / 360;
928
        L = (M + m) / 2;
929
        S = (C == 0 ? 0 :
930
             L < .5 ? C / (2 * L) :
931
                      C / (2 - 2 * L));
932
        return {h: H, s: S, l: L, toString: hsltoString};
933
    };
934
    R._path2string = function () {
935
        return this.join(",").replace(p2s, "$1");
936
    };
937
    function repush(array, item) {
938
        for (var i = 0, ii = array.length; i < ii; i++) if (array[i] === item) {
939
            return array.push(array.splice(i, 1)[0]);
940
        }
941
    }
942
    function cacher(f, scope, postprocessor) {
943
        function newf() {
944
            var arg = Array.prototype.slice.call(arguments, 0),
945
                args = arg.join("\u2400"),
946
                cache = newf.cache = newf.cache || {},
947
                count = newf.count = newf.count || [];
948
            if (cache[has](args)) {
949
                repush(count, args);
950
                return postprocessor ? postprocessor(cache[args]) : cache[args];
951
            }
952
            count.length >= 1e3 && delete cache[count.shift()];
953
            count.push(args);
954
            cache[args] = f[apply](scope, arg);
955
            return postprocessor ? postprocessor(cache[args]) : cache[args];
956
        }
957
        return newf;
958
    }
959

960
    var preload = R._preload = function (src, f) {
961
        var img = g.doc.createElement("img");
962
        img.style.cssText = "position:absolute;left:-9999em;top:-9999em";
963
        img.onload = function () {
964
            f.call(this);
965
            this.onload = null;
966
            g.doc.body.removeChild(this);
967
        };
968
        img.onerror = function () {
969
            g.doc.body.removeChild(this);
970
        };
971
        g.doc.body.appendChild(img);
972
        img.src = src;
973
    };
974

975
    function clrToString() {
976
        return this.hex;
977
    }
978

979
    /*\
980
     * Raphael.getRGB
981
     [ method ]
982
     **
983
     * Parses colour string as RGB object
984
     > Parameters
985
     - colour (string) colour string in one of formats:
986
     # <ul>
987
     #     <li>Colour name (“<code>red</code>”, “<code>green</code>”, “<code>cornflowerblue</code>”, etc)</li>
988
     #     <li>#••• — shortened HTML colour: (“<code>#000</code>”, “<code>#fc0</code>”, etc)</li>
989
     #     <li>#•••••• — full length HTML colour: (“<code>#000000</code>”, “<code>#bd2300</code>”)</li>
990
     #     <li>rgb(•••, •••, •••) — red, green and blue channels’ values: (“<code>rgb(200,&nbsp;100,&nbsp;0)</code>”)</li>
991
     #     <li>rgb(•••%, •••%, •••%) — same as above, but in %: (“<code>rgb(100%,&nbsp;175%,&nbsp;0%)</code>”)</li>
992
     #     <li>hsb(•••, •••, •••) — hue, saturation and brightness values: (“<code>hsb(0.5,&nbsp;0.25,&nbsp;1)</code>”)</li>
993
     #     <li>hsb(•••%, •••%, •••%) — same as above, but in %</li>
994
     #     <li>hsl(•••, •••, •••) — same as hsb</li>
995
     #     <li>hsl(•••%, •••%, •••%) — same as hsb</li>
996
     # </ul>
997
     = (object) RGB object in format:
998
     o {
999
     o     r (number) red,
1000
     o     g (number) green,
1001
     o     b (number) blue
1002
     o     hex (string) color in HTML/CSS format: #••••••,
1003
     o     error (boolean) true if string can’t be parsed
1004
     o }
1005
    \*/
1006
    R.getRGB = cacher(function (colour) {
1007
        if (!colour || !!((colour = Str(colour)).indexOf("-") + 1)) {
1008
            return {r: -1, g: -1, b: -1, hex: "none", error: 1, toString: clrToString};
1009
        }
1010
        if (colour == "none") {
1011
            return {r: -1, g: -1, b: -1, hex: "none", toString: clrToString};
1012
        }
1013
        !(hsrg[has](colour.toLowerCase().substring(0, 2)) || colour.charAt() == "#") && (colour = toHex(colour));
1014
        var res,
1015
            red,
1016
            green,
1017
            blue,
1018
            opacity,
1019
            t,
1020
            values,
1021
            rgb = colour.match(colourRegExp);
1022
        if (rgb) {
1023
            if (rgb[2]) {
1024
                blue = toInt(rgb[2].substring(5), 16);
1025
                green = toInt(rgb[2].substring(3, 5), 16);
1026
                red = toInt(rgb[2].substring(1, 3), 16);
1027
            }
1028
            if (rgb[3]) {
1029
                blue = toInt((t = rgb[3].charAt(3)) + t, 16);
1030
                green = toInt((t = rgb[3].charAt(2)) + t, 16);
1031
                red = toInt((t = rgb[3].charAt(1)) + t, 16);
1032
            }
1033
            if (rgb[4]) {
1034
                values = rgb[4][split](commaSpaces);
1035
                red = toFloat(values[0]);
1036
                values[0].slice(-1) == "%" && (red *= 2.55);
1037
                green = toFloat(values[1]);
1038
                values[1].slice(-1) == "%" && (green *= 2.55);
1039
                blue = toFloat(values[2]);
1040
                values[2].slice(-1) == "%" && (blue *= 2.55);
1041
                rgb[1].toLowerCase().slice(0, 4) == "rgba" && (opacity = toFloat(values[3]));
1042
                values[3] && values[3].slice(-1) == "%" && (opacity /= 100);
1043
            }
1044
            if (rgb[5]) {
1045
                values = rgb[5][split](commaSpaces);
1046
                red = toFloat(values[0]);
1047
                values[0].slice(-1) == "%" && (red *= 2.55);
1048
                green = toFloat(values[1]);
1049
                values[1].slice(-1) == "%" && (green *= 2.55);
1050
                blue = toFloat(values[2]);
1051
                values[2].slice(-1) == "%" && (blue *= 2.55);
1052
                (values[0].slice(-3) == "deg" || values[0].slice(-1) == "\xb0") && (red /= 360);
1053
                rgb[1].toLowerCase().slice(0, 4) == "hsba" && (opacity = toFloat(values[3]));
1054
                values[3] && values[3].slice(-1) == "%" && (opacity /= 100);
1055
                return R.hsb2rgb(red, green, blue, opacity);
1056
            }
1057
            if (rgb[6]) {
1058
                values = rgb[6][split](commaSpaces);
1059
                red = toFloat(values[0]);
1060
                values[0].slice(-1) == "%" && (red *= 2.55);
1061
                green = toFloat(values[1]);
1062
                values[1].slice(-1) == "%" && (green *= 2.55);
1063
                blue = toFloat(values[2]);
1064
                values[2].slice(-1) == "%" && (blue *= 2.55);
1065
                (values[0].slice(-3) == "deg" || values[0].slice(-1) == "\xb0") && (red /= 360);
1066
                rgb[1].toLowerCase().slice(0, 4) == "hsla" && (opacity = toFloat(values[3]));
1067
                values[3] && values[3].slice(-1) == "%" && (opacity /= 100);
1068
                return R.hsl2rgb(red, green, blue, opacity);
1069
            }
1070
            rgb = {r: red, g: green, b: blue, toString: clrToString};
1071
            rgb.hex = "#" + (16777216 | blue | (green << 8) | (red << 16)).toString(16).slice(1);
1072
            R.is(opacity, "finite") && (rgb.opacity = opacity);
1073
            return rgb;
1074
        }
1075
        return {r: -1, g: -1, b: -1, hex: "none", error: 1, toString: clrToString};
1076
    }, R);
1077
    /*\
1078
     * Raphael.hsb
1079
     [ method ]
1080
     **
1081
     * Converts HSB values to hex representation of the colour.
1082
     > Parameters
1083
     - h (number) hue
1084
     - s (number) saturation
1085
     - b (number) value or brightness
1086
     = (string) hex representation of the colour.
1087
    \*/
1088
    R.hsb = cacher(function (h, s, b) {
1089
        return R.hsb2rgb(h, s, b).hex;
1090
    });
1091
    /*\
1092
     * Raphael.hsl
1093
     [ method ]
1094
     **
1095
     * Converts HSL values to hex representation of the colour.
1096
     > Parameters
1097
     - h (number) hue
1098
     - s (number) saturation
1099
     - l (number) luminosity
1100
     = (string) hex representation of the colour.
1101
    \*/
1102
    R.hsl = cacher(function (h, s, l) {
1103
        return R.hsl2rgb(h, s, l).hex;
1104
    });
1105
    /*\
1106
     * Raphael.rgb
1107
     [ method ]
1108
     **
1109
     * Converts RGB values to hex representation of the colour.
1110
     > Parameters
1111
     - r (number) red
1112
     - g (number) green
1113
     - b (number) blue
1114
     = (string) hex representation of the colour.
1115
    \*/
1116
    R.rgb = cacher(function (r, g, b) {
1117
        function round(x) { return (x + 0.5) | 0; }
1118
        return "#" + (16777216 | round(b) | (round(g) << 8) | (round(r) << 16)).toString(16).slice(1);
1119
    });
1120
    /*\
1121
     * Raphael.getColor
1122
     [ method ]
1123
     **
1124
     * On each call returns next colour in the spectrum. To reset it back to red call @Raphael.getColor.reset
1125
     > Parameters
1126
     - value (number) #optional brightness, default is `0.75`
1127
     = (string) hex representation of the colour.
1128
    \*/
1129
    R.getColor = function (value) {
1130
        var start = this.getColor.start = this.getColor.start || {h: 0, s: 1, b: value || .75},
1131
            rgb = this.hsb2rgb(start.h, start.s, start.b);
1132
        start.h += .075;
1133
        if (start.h > 1) {
1134
            start.h = 0;
1135
            start.s -= .2;
1136
            start.s <= 0 && (this.getColor.start = {h: 0, s: 1, b: start.b});
1137
        }
1138
        return rgb.hex;
1139
    };
1140
    /*\
1141
     * Raphael.getColor.reset
1142
     [ method ]
1143
     **
1144
     * Resets spectrum position for @Raphael.getColor back to red.
1145
    \*/
1146
    R.getColor.reset = function () {
1147
        delete this.start;
1148
    };
1149

1150
    // http://schepers.cc/getting-to-the-point
1151
    function catmullRom2bezier(crp, z) {
1152
        var d = [];
1153
        for (var i = 0, iLen = crp.length; iLen - 2 * !z > i; i += 2) {
1154
            var p = [
1155
                        {x: +crp[i - 2], y: +crp[i - 1]},
1156
                        {x: +crp[i],     y: +crp[i + 1]},
1157
                        {x: +crp[i + 2], y: +crp[i + 3]},
1158
                        {x: +crp[i + 4], y: +crp[i + 5]}
1159
                    ];
1160
            if (z) {
1161
                if (!i) {
1162
                    p[0] = {x: +crp[iLen - 2], y: +crp[iLen - 1]};
1163
                } else if (iLen - 4 == i) {
1164
                    p[3] = {x: +crp[0], y: +crp[1]};
1165
                } else if (iLen - 2 == i) {
1166
                    p[2] = {x: +crp[0], y: +crp[1]};
1167
                    p[3] = {x: +crp[2], y: +crp[3]};
1168
                }
1169
            } else {
1170
                if (iLen - 4 == i) {
1171
                    p[3] = p[2];
1172
                } else if (!i) {
1173
                    p[0] = {x: +crp[i], y: +crp[i + 1]};
1174
                }
1175
            }
1176
            d.push(["C",
1177
                  (-p[0].x + 6 * p[1].x + p[2].x) / 6,
1178
                  (-p[0].y + 6 * p[1].y + p[2].y) / 6,
1179
                  (p[1].x + 6 * p[2].x - p[3].x) / 6,
1180
                  (p[1].y + 6*p[2].y - p[3].y) / 6,
1181
                  p[2].x,
1182
                  p[2].y
1183
            ]);
1184
        }
1185

1186
        return d;
1187
    }
1188
    /*\
1189
     * Raphael.parsePathString
1190
     [ method ]
1191
     **
1192
     * Utility method
1193
     **
1194
     * Parses given path string into an array of arrays of path segments.
1195
     > Parameters
1196
     - pathString (string|array) path string or array of segments (in the last case it will be returned straight away)
1197
     = (array) array of segments.
1198
    \*/
1199
    R.parsePathString = function (pathString) {
1200
        if (!pathString) {
1201
            return null;
1202
        }
1203
        var pth = paths(pathString);
1204
        if (pth.arr) {
1205
            return pathClone(pth.arr);
1206
        }
1207

1208
        var paramCounts = {a: 7, c: 6, h: 1, l: 2, m: 2, r: 4, q: 4, s: 4, t: 2, v: 1, z: 0},
1209
            data = [];
1210
        if (R.is(pathString, array) && R.is(pathString[0], array)) { // rough assumption
1211
            data = pathClone(pathString);
1212
        }
1213
        if (!data.length) {
1214
            Str(pathString).replace(pathCommand, function (a, b, c) {
1215
                var params = [],
1216
                    name = b.toLowerCase();
1217
                c.replace(pathValues, function (a, b) {
1218
                    b && params.push(+b);
1219
                });
1220
                if (name == "m" && params.length > 2) {
1221
                    data.push([b][concat](params.splice(0, 2)));
1222
                    name = "l";
1223
                    b = b == "m" ? "l" : "L";
1224
                }
1225
                if (name == "r") {
1226
                    data.push([b][concat](params));
1227
                } else while (params.length >= paramCounts[name]) {
1228
                    data.push([b][concat](params.splice(0, paramCounts[name])));
1229
                    if (!paramCounts[name]) {
1230
                        break;
1231
                    }
1232
                }
1233
            });
1234
        }
1235
        data.toString = R._path2string;
1236
        pth.arr = pathClone(data);
1237
        return data;
1238
    };
1239
    /*\
1240
     * Raphael.parseTransformString
1241
     [ method ]
1242
     **
1243
     * Utility method
1244
     **
1245
     * Parses given path string into an array of transformations.
1246
     > Parameters
1247
     - TString (string|array) transform string or array of transformations (in the last case it will be returned straight away)
1248
     = (array) array of transformations.
1249
    \*/
1250
    R.parseTransformString = cacher(function (TString) {
1251
        if (!TString) {
1252
            return null;
1253
        }
1254
        var paramCounts = {r: 3, s: 4, t: 2, m: 6},
1255
            data = [];
1256
        if (R.is(TString, array) && R.is(TString[0], array)) { // rough assumption
1257
            data = pathClone(TString);
1258
        }
1259
        if (!data.length) {
1260
            Str(TString).replace(tCommand, function (a, b, c) {
1261
                var params = [],
1262
                    name = lowerCase.call(b);
1263
                c.replace(pathValues, function (a, b) {
1264
                    b && params.push(+b);
1265
                });
1266
                data.push([b][concat](params));
1267
            });
1268
        }
1269
        data.toString = R._path2string;
1270
        return data;
1271
    }, this, function(elem) {
1272
        if (!elem) return elem;
1273
        var newData = [];
1274
        for (var i = 0; i < elem.length; i++) {
1275
            var newLevel = [];
1276
            for (var j = 0; j < elem[i].length; j++) {
1277
                newLevel.push(elem[i][j]);
1278
            }
1279
            newData.push(newLevel);
1280
        }
1281
      return newData; } );
1282
    // PATHS
1283
    var paths = function (ps) {
1284
        var p = paths.ps = paths.ps || {};
1285
        if (p[ps]) {
1286
            p[ps].sleep = 100;
1287
        } else {
1288
            p[ps] = {
1289
                sleep: 100
1290
            };
1291
        }
1292
        setTimeout(function () {
1293
            for (var key in p) if (p[has](key) && key != ps) {
1294
                p[key].sleep--;
1295
                !p[key].sleep && delete p[key];
1296
            }
1297
        });
1298
        return p[ps];
1299
    };
1300
    /*\
1301
     * Raphael.findDotsAtSegment
1302
     [ method ]
1303
     **
1304
     * Utility method
1305
     **
1306
     * Find dot coordinates on the given cubic bezier curve at the given t.
1307
     > Parameters
1308
     - p1x (number) x of the first point of the curve
1309
     - p1y (number) y of the first point of the curve
1310
     - c1x (number) x of the first anchor of the curve
1311
     - c1y (number) y of the first anchor of the curve
1312
     - c2x (number) x of the second anchor of the curve
1313
     - c2y (number) y of the second anchor of the curve
1314
     - p2x (number) x of the second point of the curve
1315
     - p2y (number) y of the second point of the curve
1316
     - t (number) position on the curve (0..1)
1317
     = (object) point information in format:
1318
     o {
1319
     o     x: (number) x coordinate of the point
1320
     o     y: (number) y coordinate of the point
1321
     o     m: {
1322
     o         x: (number) x coordinate of the left anchor
1323
     o         y: (number) y coordinate of the left anchor
1324
     o     }
1325
     o     n: {
1326
     o         x: (number) x coordinate of the right anchor
1327
     o         y: (number) y coordinate of the right anchor
1328
     o     }
1329
     o     start: {
1330
     o         x: (number) x coordinate of the start of the curve
1331
     o         y: (number) y coordinate of the start of the curve
1332
     o     }
1333
     o     end: {
1334
     o         x: (number) x coordinate of the end of the curve
1335
     o         y: (number) y coordinate of the end of the curve
1336
     o     }
1337
     o     alpha: (number) angle of the curve derivative at the point
1338
     o }
1339
    \*/
1340
    R.findDotsAtSegment = function (p1x, p1y, c1x, c1y, c2x, c2y, p2x, p2y, t) {
1341
        var t1 = 1 - t,
1342
            t13 = pow(t1, 3),
1343
            t12 = pow(t1, 2),
1344
            t2 = t * t,
1345
            t3 = t2 * t,
1346
            x = t13 * p1x + t12 * 3 * t * c1x + t1 * 3 * t * t * c2x + t3 * p2x,
1347
            y = t13 * p1y + t12 * 3 * t * c1y + t1 * 3 * t * t * c2y + t3 * p2y,
1348
            mx = p1x + 2 * t * (c1x - p1x) + t2 * (c2x - 2 * c1x + p1x),
1349
            my = p1y + 2 * t * (c1y - p1y) + t2 * (c2y - 2 * c1y + p1y),
1350
            nx = c1x + 2 * t * (c2x - c1x) + t2 * (p2x - 2 * c2x + c1x),
1351
            ny = c1y + 2 * t * (c2y - c1y) + t2 * (p2y - 2 * c2y + c1y),
1352
            ax = t1 * p1x + t * c1x,
1353
            ay = t1 * p1y + t * c1y,
1354
            cx = t1 * c2x + t * p2x,
1355
            cy = t1 * c2y + t * p2y,
1356
            alpha = (90 - math.atan2(mx - nx, my - ny) * 180 / PI);
1357
        (mx > nx || my < ny) && (alpha += 180);
1358
        return {
1359
            x: x,
1360
            y: y,
1361
            m: {x: mx, y: my},
1362
            n: {x: nx, y: ny},
1363
            start: {x: ax, y: ay},
1364
            end: {x: cx, y: cy},
1365
            alpha: alpha
1366
        };
1367
    };
1368
    /*\
1369
     * Raphael.bezierBBox
1370
     [ method ]
1371
     **
1372
     * Utility method
1373
     **
1374
     * Return bounding box of a given cubic bezier curve
1375
     > Parameters
1376
     - p1x (number) x of the first point of the curve
1377
     - p1y (number) y of the first point of the curve
1378
     - c1x (number) x of the first anchor of the curve
1379
     - c1y (number) y of the first anchor of the curve
1380
     - c2x (number) x of the second anchor of the curve
1381
     - c2y (number) y of the second anchor of the curve
1382
     - p2x (number) x of the second point of the curve
1383
     - p2y (number) y of the second point of the curve
1384
     * or
1385
     - bez (array) array of six points for bezier curve
1386
     = (object) point information in format:
1387
     o {
1388
     o     min: {
1389
     o         x: (number) x coordinate of the left point
1390
     o         y: (number) y coordinate of the top point
1391
     o     }
1392
     o     max: {
1393
     o         x: (number) x coordinate of the right point
1394
     o         y: (number) y coordinate of the bottom point
1395
     o     }
1396
     o }
1397
    \*/
1398
    R.bezierBBox = function (p1x, p1y, c1x, c1y, c2x, c2y, p2x, p2y) {
1399
        if (!R.is(p1x, "array")) {
1400
            p1x = [p1x, p1y, c1x, c1y, c2x, c2y, p2x, p2y];
1401
        }
1402
        var bbox = curveDim.apply(null, p1x);
1403
        return {
1404
            x: bbox.min.x,
1405
            y: bbox.min.y,
1406
            x2: bbox.max.x,
1407
            y2: bbox.max.y,
1408
            width: bbox.max.x - bbox.min.x,
1409
            height: bbox.max.y - bbox.min.y
1410
        };
1411
    };
1412
    /*\
1413
     * Raphael.isPointInsideBBox
1414
     [ method ]
1415
     **
1416
     * Utility method
1417
     **
1418
     * Returns `true` if given point is inside bounding boxes.
1419
     > Parameters
1420
     - bbox (string) bounding box
1421
     - x (string) x coordinate of the point
1422
     - y (string) y coordinate of the point
1423
     = (boolean) `true` if point inside
1424
    \*/
1425
    R.isPointInsideBBox = function (bbox, x, y) {
1426
        return x >= bbox.x && x <= bbox.x2 && y >= bbox.y && y <= bbox.y2;
1427
    };
1428
    /*\
1429
     * Raphael.isBBoxIntersect
1430
     [ method ]
1431
     **
1432
     * Utility method
1433
     **
1434
     * Returns `true` if two bounding boxes intersect
1435
     > Parameters
1436
     - bbox1 (string) first bounding box
1437
     - bbox2 (string) second bounding box
1438
     = (boolean) `true` if they intersect
1439
    \*/
1440
    R.isBBoxIntersect = function (bbox1, bbox2) {
1441
        var i = R.isPointInsideBBox;
1442
        return i(bbox2, bbox1.x, bbox1.y)
1443
            || i(bbox2, bbox1.x2, bbox1.y)
1444
            || i(bbox2, bbox1.x, bbox1.y2)
1445
            || i(bbox2, bbox1.x2, bbox1.y2)
1446
            || i(bbox1, bbox2.x, bbox2.y)
1447
            || i(bbox1, bbox2.x2, bbox2.y)
1448
            || i(bbox1, bbox2.x, bbox2.y2)
1449
            || i(bbox1, bbox2.x2, bbox2.y2)
1450
            || (bbox1.x < bbox2.x2 && bbox1.x > bbox2.x || bbox2.x < bbox1.x2 && bbox2.x > bbox1.x)
1451
            && (bbox1.y < bbox2.y2 && bbox1.y > bbox2.y || bbox2.y < bbox1.y2 && bbox2.y > bbox1.y);
1452
    };
1453
    function base3(t, p1, p2, p3, p4) {
1454
        var t1 = -3 * p1 + 9 * p2 - 9 * p3 + 3 * p4,
1455
            t2 = t * t1 + 6 * p1 - 12 * p2 + 6 * p3;
1456
        return t * t2 - 3 * p1 + 3 * p2;
1457
    }
1458
    function bezlen(x1, y1, x2, y2, x3, y3, x4, y4, z) {
1459
        if (z == null) {
1460
            z = 1;
1461
        }
1462
        z = z > 1 ? 1 : z < 0 ? 0 : z;
1463
        var z2 = z / 2,
1464
            n = 12,
1465
            Tvalues = [-0.1252,0.1252,-0.3678,0.3678,-0.5873,0.5873,-0.7699,0.7699,-0.9041,0.9041,-0.9816,0.9816],
1466
            Cvalues = [0.2491,0.2491,0.2335,0.2335,0.2032,0.2032,0.1601,0.1601,0.1069,0.1069,0.0472,0.0472],
1467
            sum = 0;
1468
        for (var i = 0; i < n; i++) {
1469
            var ct = z2 * Tvalues[i] + z2,
1470
                xbase = base3(ct, x1, x2, x3, x4),
1471
                ybase = base3(ct, y1, y2, y3, y4),
1472
                comb = xbase * xbase + ybase * ybase;
1473
            sum += Cvalues[i] * math.sqrt(comb);
1474
        }
1475
        return z2 * sum;
1476
    }
1477
    function getTatLen(x1, y1, x2, y2, x3, y3, x4, y4, ll) {
1478
        if (ll < 0 || bezlen(x1, y1, x2, y2, x3, y3, x4, y4) < ll) {
1479
            return;
1480
        }
1481
        var t = 1,
1482
            step = t / 2,
1483
            t2 = t - step,
1484
            l,
1485
            e = .01;
1486
        l = bezlen(x1, y1, x2, y2, x3, y3, x4, y4, t2);
1487
        while (abs(l - ll) > e) {
1488
            step /= 2;
1489
            t2 += (l < ll ? 1 : -1) * step;
1490
            l = bezlen(x1, y1, x2, y2, x3, y3, x4, y4, t2);
1491
        }
1492
        return t2;
1493
    }
1494
    function intersect(x1, y1, x2, y2, x3, y3, x4, y4) {
1495
        if (
1496
            mmax(x1, x2) < mmin(x3, x4) ||
1497
            mmin(x1, x2) > mmax(x3, x4) ||
1498
            mmax(y1, y2) < mmin(y3, y4) ||
1499
            mmin(y1, y2) > mmax(y3, y4)
1500
        ) {
1501
            return;
1502
        }
1503
        var nx = (x1 * y2 - y1 * x2) * (x3 - x4) - (x1 - x2) * (x3 * y4 - y3 * x4),
1504
            ny = (x1 * y2 - y1 * x2) * (y3 - y4) - (y1 - y2) * (x3 * y4 - y3 * x4),
1505
            denominator = (x1 - x2) * (y3 - y4) - (y1 - y2) * (x3 - x4);
1506

1507
        if (!denominator) {
1508
            return;
1509
        }
1510
        var px = nx / denominator,
1511
            py = ny / denominator,
1512
            px2 = +px.toFixed(2),
1513
            py2 = +py.toFixed(2);
1514
        if (
1515
            px2 < +mmin(x1, x2).toFixed(2) ||
1516
            px2 > +mmax(x1, x2).toFixed(2) ||
1517
            px2 < +mmin(x3, x4).toFixed(2) ||
1518
            px2 > +mmax(x3, x4).toFixed(2) ||
1519
            py2 < +mmin(y1, y2).toFixed(2) ||
1520
            py2 > +mmax(y1, y2).toFixed(2) ||
1521
            py2 < +mmin(y3, y4).toFixed(2) ||
1522
            py2 > +mmax(y3, y4).toFixed(2)
1523
        ) {
1524
            return;
1525
        }
1526
        return {x: px, y: py};
1527
    }
1528
    function inter(bez1, bez2) {
1529
        return interHelper(bez1, bez2);
1530
    }
1531
    function interCount(bez1, bez2) {
1532
        return interHelper(bez1, bez2, 1);
1533
    }
1534
    function interHelper(bez1, bez2, justCount) {
1535
        var bbox1 = R.bezierBBox(bez1),
1536
            bbox2 = R.bezierBBox(bez2);
1537
        if (!R.isBBoxIntersect(bbox1, bbox2)) {
1538
            return justCount ? 0 : [];
1539
        }
1540
        var l1 = bezlen.apply(0, bez1),
1541
            l2 = bezlen.apply(0, bez2),
1542
            n1 = mmax(~~(l1 / 5), 1),
1543
            n2 = mmax(~~(l2 / 5), 1),
1544
            dots1 = [],
1545
            dots2 = [],
1546
            xy = {},
1547
            res = justCount ? 0 : [];
1548
        for (var i = 0; i < n1 + 1; i++) {
1549
            var p = R.findDotsAtSegment.apply(R, bez1.concat(i / n1));
1550
            dots1.push({x: p.x, y: p.y, t: i / n1});
1551
        }
1552
        for (i = 0; i < n2 + 1; i++) {
1553
            p = R.findDotsAtSegment.apply(R, bez2.concat(i / n2));
1554
            dots2.push({x: p.x, y: p.y, t: i / n2});
1555
        }
1556
        for (i = 0; i < n1; i++) {
1557
            for (var j = 0; j < n2; j++) {
1558
                var di = dots1[i],
1559
                    di1 = dots1[i + 1],
1560
                    dj = dots2[j],
1561
                    dj1 = dots2[j + 1],
1562
                    ci = abs(di1.x - di.x) < .001 ? "y" : "x",
1563
                    cj = abs(dj1.x - dj.x) < .001 ? "y" : "x",
1564
                    is = intersect(di.x, di.y, di1.x, di1.y, dj.x, dj.y, dj1.x, dj1.y);
1565
                if (is) {
1566
                    if (xy[is.x.toFixed(4)] == is.y.toFixed(4)) {
1567
                        continue;
1568
                    }
1569
                    xy[is.x.toFixed(4)] = is.y.toFixed(4);
1570
                    var t1 = di.t + abs((is[ci] - di[ci]) / (di1[ci] - di[ci])) * (di1.t - di.t),
1571
                        t2 = dj.t + abs((is[cj] - dj[cj]) / (dj1[cj] - dj[cj])) * (dj1.t - dj.t);
1572
                    if (t1 >= 0 && t1 <= 1.001 && t2 >= 0 && t2 <= 1.001) {
1573
                        if (justCount) {
1574
                            res++;
1575
                        } else {
1576
                            res.push({
1577
                                x: is.x,
1578
                                y: is.y,
1579
                                t1: mmin(t1, 1),
1580
                                t2: mmin(t2, 1)
1581
                            });
1582
                        }
1583
                    }
1584
                }
1585
            }
1586
        }
1587
        return res;
1588
    }
1589
    /*\
1590
     * Raphael.pathIntersection
1591
     [ method ]
1592
     **
1593
     * Utility method
1594
     **
1595
     * Finds intersections of two paths
1596
     > Parameters
1597
     - path1 (string) path string
1598
     - path2 (string) path string
1599
     = (array) dots of intersection
1600
     o [
1601
     o     {
1602
     o         x: (number) x coordinate of the point
1603
     o         y: (number) y coordinate of the point
1604
     o         t1: (number) t value for segment of path1
1605
     o         t2: (number) t value for segment of path2
1606
     o         segment1: (number) order number for segment of path1
1607
     o         segment2: (number) order number for segment of path2
1608
     o         bez1: (array) eight coordinates representing beziér curve for the segment of path1
1609
     o         bez2: (array) eight coordinates representing beziér curve for the segment of path2
1610
     o     }
1611
     o ]
1612
    \*/
1613
    R.pathIntersection = function (path1, path2) {
1614
        return interPathHelper(path1, path2);
1615
    };
1616
    R.pathIntersectionNumber = function (path1, path2) {
1617
        return interPathHelper(path1, path2, 1);
1618
    };
1619
    function interPathHelper(path1, path2, justCount) {
1620
        path1 = R._path2curve(path1);
1621
        path2 = R._path2curve(path2);
1622
        var x1, y1, x2, y2, x1m, y1m, x2m, y2m, bez1, bez2,
1623
            res = justCount ? 0 : [];
1624
        for (var i = 0, ii = path1.length; i < ii; i++) {
1625
            var pi = path1[i];
1626
            if (pi[0] == "M") {
1627
                x1 = x1m = pi[1];
1628
                y1 = y1m = pi[2];
1629
            } else {
1630
                if (pi[0] == "C") {
1631
                    bez1 = [x1, y1].concat(pi.slice(1));
1632
                    x1 = bez1[6];
1633
                    y1 = bez1[7];
1634
                } else {
1635
                    bez1 = [x1, y1, x1, y1, x1m, y1m, x1m, y1m];
1636
                    x1 = x1m;
1637
                    y1 = y1m;
1638
                }
1639
                for (var j = 0, jj = path2.length; j < jj; j++) {
1640
                    var pj = path2[j];
1641
                    if (pj[0] == "M") {
1642
                        x2 = x2m = pj[1];
1643
                        y2 = y2m = pj[2];
1644
                    } else {
1645
                        if (pj[0] == "C") {
1646
                            bez2 = [x2, y2].concat(pj.slice(1));
1647
                            x2 = bez2[6];
1648
                            y2 = bez2[7];
1649
                        } else {
1650
                            bez2 = [x2, y2, x2, y2, x2m, y2m, x2m, y2m];
1651
                            x2 = x2m;
1652
                            y2 = y2m;
1653
                        }
1654
                        var intr = interHelper(bez1, bez2, justCount);
1655
                        if (justCount) {
1656
                            res += intr;
1657
                        } else {
1658
                            for (var k = 0, kk = intr.length; k < kk; k++) {
1659
                                intr[k].segment1 = i;
1660
                                intr[k].segment2 = j;
1661
                                intr[k].bez1 = bez1;
1662
                                intr[k].bez2 = bez2;
1663
                            }
1664
                            res = res.concat(intr);
1665
                        }
1666
                    }
1667
                }
1668
            }
1669
        }
1670
        return res;
1671
    }
1672
    /*\
1673
     * Raphael.isPointInsidePath
1674
     [ method ]
1675
     **
1676
     * Utility method
1677
     **
1678
     * Returns `true` if given point is inside a given closed path.
1679
     > Parameters
1680
     - path (string) path string
1681
     - x (number) x of the point
1682
     - y (number) y of the point
1683
     = (boolean) true, if point is inside the path
1684
    \*/
1685
    R.isPointInsidePath = function (path, x, y) {
1686
        var bbox = R.pathBBox(path);
1687
        return R.isPointInsideBBox(bbox, x, y) &&
1688
               interPathHelper(path, [["M", x, y], ["H", bbox.x2 + 10]], 1) % 2 == 1;
1689
    };
1690
    R._removedFactory = function (methodname) {
1691
        return function () {
1692
            eve("raphael.log", null, "Rapha\xebl: you are calling to method \u201c" + methodname + "\u201d of removed object", methodname);
1693
        };
1694
    };
1695
    /*\
1696
     * Raphael.pathBBox
1697
     [ method ]
1698
     **
1699
     * Utility method
1700
     **
1701
     * Return bounding box of a given path
1702
     > Parameters
1703
     - path (string) path string
1704
     = (object) bounding box
1705
     o {
1706
     o     x: (number) x coordinate of the left top point of the box
1707
     o     y: (number) y coordinate of the left top point of the box
1708
     o     x2: (number) x coordinate of the right bottom point of the box
1709
     o     y2: (number) y coordinate of the right bottom point of the box
1710
     o     width: (number) width of the box
1711
     o     height: (number) height of the box
1712
     o     cx: (number) x coordinate of the center of the box
1713
     o     cy: (number) y coordinate of the center of the box
1714
     o }
1715
    \*/
1716
    var pathDimensions = R.pathBBox = function (path) {
1717
        var pth = paths(path);
1718
        if (pth.bbox) {
1719
            return clone(pth.bbox);
1720
        }
1721
        if (!path) {
1722
            return {x: 0, y: 0, width: 0, height: 0, x2: 0, y2: 0};
1723
        }
1724
        path = path2curve(path);
1725
        var x = 0,
1726
            y = 0,
1727
            X = [],
1728
            Y = [],
1729
            p;
1730
        for (var i = 0, ii = path.length; i < ii; i++) {
1731
            p = path[i];
1732
            if (p[0] == "M") {
1733
                x = p[1];
1734
                y = p[2];
1735
                X.push(x);
1736
                Y.push(y);
1737
            } else {
1738
                var dim = curveDim(x, y, p[1], p[2], p[3], p[4], p[5], p[6]);
1739
                X = X[concat](dim.min.x, dim.max.x);
1740
                Y = Y[concat](dim.min.y, dim.max.y);
1741
                x = p[5];
1742
                y = p[6];
1743
            }
1744
        }
1745
        var xmin = mmin[apply](0, X),
1746
            ymin = mmin[apply](0, Y),
1747
            xmax = mmax[apply](0, X),
1748
            ymax = mmax[apply](0, Y),
1749
            width = xmax - xmin,
1750
            height = ymax - ymin,
1751
                bb = {
1752
                x: xmin,
1753
                y: ymin,
1754
                x2: xmax,
1755
                y2: ymax,
1756
                width: width,
1757
                height: height,
1758
                cx: xmin + width / 2,
1759
                cy: ymin + height / 2
1760
            };
1761
        pth.bbox = clone(bb);
1762
        return bb;
1763
    },
1764
        pathClone = function (pathArray) {
1765
            var res = clone(pathArray);
1766
            res.toString = R._path2string;
1767
            return res;
1768
        },
1769
        pathToRelative = R._pathToRelative = function (pathArray) {
1770
            var pth = paths(pathArray);
1771
            if (pth.rel) {
1772
                return pathClone(pth.rel);
1773
            }
1774
            if (!R.is(pathArray, array) || !R.is(pathArray && pathArray[0], array)) { // rough assumption
1775
                pathArray = R.parsePathString(pathArray);
1776
            }
1777
            var res = [],
1778
                x = 0,
1779
                y = 0,
1780
                mx = 0,
1781
                my = 0,
1782
                start = 0;
1783
            if (pathArray[0][0] == "M") {
1784
                x = pathArray[0][1];
1785
                y = pathArray[0][2];
1786
                mx = x;
1787
                my = y;
1788
                start++;
1789
                res.push(["M", x, y]);
1790
            }
1791
            for (var i = start, ii = pathArray.length; i < ii; i++) {
1792
                var r = res[i] = [],
1793
                    pa = pathArray[i];
1794
                if (pa[0] != lowerCase.call(pa[0])) {
1795
                    r[0] = lowerCase.call(pa[0]);
1796
                    switch (r[0]) {
1797
                        case "a":
1798
                            r[1] = pa[1];
1799
                            r[2] = pa[2];
1800
                            r[3] = pa[3];
1801
                            r[4] = pa[4];
1802
                            r[5] = pa[5];
1803
                            r[6] = +(pa[6] - x).toFixed(3);
1804
                            r[7] = +(pa[7] - y).toFixed(3);
1805
                            break;
1806
                        case "v":
1807
                            r[1] = +(pa[1] - y).toFixed(3);
1808
                            break;
1809
                        case "m":
1810
                            mx = pa[1];
1811
                            my = pa[2];
1812
                        default:
1813
                            for (var j = 1, jj = pa.length; j < jj; j++) {
1814
                                r[j] = +(pa[j] - ((j % 2) ? x : y)).toFixed(3);
1815
                            }
1816
                    }
1817
                } else {
1818
                    r = res[i] = [];
1819
                    if (pa[0] == "m") {
1820
                        mx = pa[1] + x;
1821
                        my = pa[2] + y;
1822
                    }
1823
                    for (var k = 0, kk = pa.length; k < kk; k++) {
1824
                        res[i][k] = pa[k];
1825
                    }
1826
                }
1827
                var len = res[i].length;
1828
                switch (res[i][0]) {
1829
                    case "z":
1830
                        x = mx;
1831
                        y = my;
1832
                        break;
1833
                    case "h":
1834
                        x += +res[i][len - 1];
1835
                        break;
1836
                    case "v":
1837
                        y += +res[i][len - 1];
1838
                        break;
1839
                    default:
1840
                        x += +res[i][len - 2];
1841
                        y += +res[i][len - 1];
1842
                }
1843
            }
1844
            res.toString = R._path2string;
1845
            pth.rel = pathClone(res);
1846
            return res;
1847
        },
1848
        pathToAbsolute = R._pathToAbsolute = function (pathArray) {
1849
            var pth = paths(pathArray);
1850
            if (pth.abs) {
1851
                return pathClone(pth.abs);
1852
            }
1853
            if (!R.is(pathArray, array) || !R.is(pathArray && pathArray[0], array)) { // rough assumption
1854
                pathArray = R.parsePathString(pathArray);
1855
            }
1856
            if (!pathArray || !pathArray.length) {
1857
                return [["M", 0, 0]];
1858
            }
1859
            var res = [],
1860
                x = 0,
1861
                y = 0,
1862
                mx = 0,
1863
                my = 0,
1864
                start = 0;
1865
            if (pathArray[0][0] == "M") {
1866
                x = +pathArray[0][1];
1867
                y = +pathArray[0][2];
1868
                mx = x;
1869
                my = y;
1870
                start++;
1871
                res[0] = ["M", x, y];
1872
            }
1873
            var crz = pathArray.length == 3 && pathArray[0][0] == "M" && pathArray[1][0].toUpperCase() == "R" && pathArray[2][0].toUpperCase() == "Z";
1874
            for (var r, pa, i = start, ii = pathArray.length; i < ii; i++) {
1875
                res.push(r = []);
1876
                pa = pathArray[i];
1877
                if (pa[0] != upperCase.call(pa[0])) {
1878
                    r[0] = upperCase.call(pa[0]);
1879
                    switch (r[0]) {
1880
                        case "A":
1881
                            r[1] = pa[1];
1882
                            r[2] = pa[2];
1883
                            r[3] = pa[3];
1884
                            r[4] = pa[4];
1885
                            r[5] = pa[5];
1886
                            r[6] = +(pa[6] + x);
1887
                            r[7] = +(pa[7] + y);
1888
                            break;
1889
                        case "V":
1890
                            r[1] = +pa[1] + y;
1891
                            break;
1892
                        case "H":
1893
                            r[1] = +pa[1] + x;
1894
                            break;
1895
                        case "R":
1896
                            var dots = [x, y][concat](pa.slice(1));
1897
                            for (var j = 2, jj = dots.length; j < jj; j++) {
1898
                                dots[j] = +dots[j] + x;
1899
                                dots[++j] = +dots[j] + y;
1900
                            }
1901
                            res.pop();
1902
                            res = res[concat](catmullRom2bezier(dots, crz));
1903
                            break;
1904
                        case "M":
1905
                            mx = +pa[1] + x;
1906
                            my = +pa[2] + y;
1907
                        default:
1908
                            for (j = 1, jj = pa.length; j < jj; j++) {
1909
                                r[j] = +pa[j] + ((j % 2) ? x : y);
1910
                            }
1911
                    }
1912
                } else if (pa[0] == "R") {
1913
                    dots = [x, y][concat](pa.slice(1));
1914
                    res.pop();
1915
                    res = res[concat](catmullRom2bezier(dots, crz));
1916
                    r = ["R"][concat](pa.slice(-2));
1917
                } else {
1918
                    for (var k = 0, kk = pa.length; k < kk; k++) {
1919
                        r[k] = pa[k];
1920
                    }
1921
                }
1922
                switch (r[0]) {
1923
                    case "Z":
1924
                        x = mx;
1925
                        y = my;
1926
                        break;
1927
                    case "H":
1928
                        x = r[1];
1929
                        break;
1930
                    case "V":
1931
                        y = r[1];
1932
                        break;
1933
                    case "M":
1934
                        mx = r[r.length - 2];
1935
                        my = r[r.length - 1];
1936
                    default:
1937
                        x = r[r.length - 2];
1938
                        y = r[r.length - 1];
1939
                }
1940
            }
1941
            res.toString = R._path2string;
1942
            pth.abs = pathClone(res);
1943
            return res;
1944
        },
1945
        l2c = function (x1, y1, x2, y2) {
1946
            return [x1, y1, x2, y2, x2, y2];
1947
        },
1948
        q2c = function (x1, y1, ax, ay, x2, y2) {
1949
            var _13 = 1 / 3,
1950
                _23 = 2 / 3;
1951
            return [
1952
                    _13 * x1 + _23 * ax,
1953
                    _13 * y1 + _23 * ay,
1954
                    _13 * x2 + _23 * ax,
1955
                    _13 * y2 + _23 * ay,
1956
                    x2,
1957
                    y2
1958
                ];
1959
        },
1960
        a2c = function (x1, y1, rx, ry, angle, large_arc_flag, sweep_flag, x2, y2, recursive) {
1961
            // for more information of where this math came from visit:
1962
            // http://www.w3.org/TR/SVG11/implnote.html#ArcImplementationNotes
1963
            var _120 = PI * 120 / 180,
1964
                rad = PI / 180 * (+angle || 0),
1965
                res = [],
1966
                xy,
1967
                rotate = cacher(function (x, y, rad) {
1968
                    var X = x * math.cos(rad) - y * math.sin(rad),
1969
                        Y = x * math.sin(rad) + y * math.cos(rad);
1970
                    return {x: X, y: Y};
1971
                });
1972
            if (!recursive) {
1973
                xy = rotate(x1, y1, -rad);
1974
                x1 = xy.x;
1975
                y1 = xy.y;
1976
                xy = rotate(x2, y2, -rad);
1977
                x2 = xy.x;
1978
                y2 = xy.y;
1979
                var cos = math.cos(PI / 180 * angle),
1980
                    sin = math.sin(PI / 180 * angle),
1981
                    x = (x1 - x2) / 2,
1982
                    y = (y1 - y2) / 2;
1983
                var h = (x * x) / (rx * rx) + (y * y) / (ry * ry);
1984
                if (h > 1) {
1985
                    h = math.sqrt(h);
1986
                    rx = h * rx;
1987
                    ry = h * ry;
1988
                }
1989
                var rx2 = rx * rx,
1990
                    ry2 = ry * ry,
1991
                    k = (large_arc_flag == sweep_flag ? -1 : 1) *
1992
                        math.sqrt(abs((rx2 * ry2 - rx2 * y * y - ry2 * x * x) / (rx2 * y * y + ry2 * x * x))),
1993
                    cx = k * rx * y / ry + (x1 + x2) / 2,
1994
                    cy = k * -ry * x / rx + (y1 + y2) / 2,
1995
                    f1 = math.asin(((y1 - cy) / ry).toFixed(9)),
1996
                    f2 = math.asin(((y2 - cy) / ry).toFixed(9));
1997

1998
                f1 = x1 < cx ? PI - f1 : f1;
1999
                f2 = x2 < cx ? PI - f2 : f2;
2000
                f1 < 0 && (f1 = PI * 2 + f1);
2001
                f2 < 0 && (f2 = PI * 2 + f2);
2002
                if (sweep_flag && f1 > f2) {
2003
                    f1 = f1 - PI * 2;
2004
                }
2005
                if (!sweep_flag && f2 > f1) {
2006
                    f2 = f2 - PI * 2;
2007
                }
2008
            } else {
2009
                f1 = recursive[0];
2010
                f2 = recursive[1];
2011
                cx = recursive[2];
2012
                cy = recursive[3];
2013
            }
2014
            var df = f2 - f1;
2015
            if (abs(df) > _120) {
2016
                var f2old = f2,
2017
                    x2old = x2,
2018
                    y2old = y2;
2019
                f2 = f1 + _120 * (sweep_flag && f2 > f1 ? 1 : -1);
2020
                x2 = cx + rx * math.cos(f2);
2021
                y2 = cy + ry * math.sin(f2);
2022
                res = a2c(x2, y2, rx, ry, angle, 0, sweep_flag, x2old, y2old, [f2, f2old, cx, cy]);
2023
            }
2024
            df = f2 - f1;
2025
            var c1 = math.cos(f1),
2026
                s1 = math.sin(f1),
2027
                c2 = math.cos(f2),
2028
                s2 = math.sin(f2),
2029
                t = math.tan(df / 4),
2030
                hx = 4 / 3 * rx * t,
2031
                hy = 4 / 3 * ry * t,
2032
                m1 = [x1, y1],
2033
                m2 = [x1 + hx * s1, y1 - hy * c1],
2034
                m3 = [x2 + hx * s2, y2 - hy * c2],
2035
                m4 = [x2, y2];
2036
            m2[0] = 2 * m1[0] - m2[0];
2037
            m2[1] = 2 * m1[1] - m2[1];
2038
            if (recursive) {
2039
                return [m2, m3, m4][concat](res);
2040
            } else {
2041
                res = [m2, m3, m4][concat](res).join()[split](",");
2042
                var newres = [];
2043
                for (var i = 0, ii = res.length; i < ii; i++) {
2044
                    newres[i] = i % 2 ? rotate(res[i - 1], res[i], rad).y : rotate(res[i], res[i + 1], rad).x;
2045
                }
2046
                return newres;
2047
            }
2048
        },
2049
        findDotAtSegment = function (p1x, p1y, c1x, c1y, c2x, c2y, p2x, p2y, t) {
2050
            var t1 = 1 - t;
2051
            return {
2052
                x: pow(t1, 3) * p1x + pow(t1, 2) * 3 * t * c1x + t1 * 3 * t * t * c2x + pow(t, 3) * p2x,
2053
                y: pow(t1, 3) * p1y + pow(t1, 2) * 3 * t * c1y + t1 * 3 * t * t * c2y + pow(t, 3) * p2y
2054
            };
2055
        },
2056
        curveDim = cacher(function (p1x, p1y, c1x, c1y, c2x, c2y, p2x, p2y) {
2057
            var a = (c2x - 2 * c1x + p1x) - (p2x - 2 * c2x + c1x),
2058
                b = 2 * (c1x - p1x) - 2 * (c2x - c1x),
2059
                c = p1x - c1x,
2060
                t1 = (-b + math.sqrt(b * b - 4 * a * c)) / 2 / a,
2061
                t2 = (-b - math.sqrt(b * b - 4 * a * c)) / 2 / a,
2062
                y = [p1y, p2y],
2063
                x = [p1x, p2x],
2064
                dot;
2065
            abs(t1) > "1e12" && (t1 = .5);
2066
            abs(t2) > "1e12" && (t2 = .5);
2067
            if (t1 > 0 && t1 < 1) {
2068
                dot = findDotAtSegment(p1x, p1y, c1x, c1y, c2x, c2y, p2x, p2y, t1);
2069
                x.push(dot.x);
2070
                y.push(dot.y);
2071
            }
2072
            if (t2 > 0 && t2 < 1) {
2073
                dot = findDotAtSegment(p1x, p1y, c1x, c1y, c2x, c2y, p2x, p2y, t2);
2074
                x.push(dot.x);
2075
                y.push(dot.y);
2076
            }
2077
            a = (c2y - 2 * c1y + p1y) - (p2y - 2 * c2y + c1y);
2078
            b = 2 * (c1y - p1y) - 2 * (c2y - c1y);
2079
            c = p1y - c1y;
2080
            t1 = (-b + math.sqrt(b * b - 4 * a * c)) / 2 / a;
2081
            t2 = (-b - math.sqrt(b * b - 4 * a * c)) / 2 / a;
2082
            abs(t1) > "1e12" && (t1 = .5);
2083
            abs(t2) > "1e12" && (t2 = .5);
2084
            if (t1 > 0 && t1 < 1) {
2085
                dot = findDotAtSegment(p1x, p1y, c1x, c1y, c2x, c2y, p2x, p2y, t1);
2086
                x.push(dot.x);
2087
                y.push(dot.y);
2088
            }
2089
            if (t2 > 0 && t2 < 1) {
2090
                dot = findDotAtSegment(p1x, p1y, c1x, c1y, c2x, c2y, p2x, p2y, t2);
2091
                x.push(dot.x);
2092
                y.push(dot.y);
2093
            }
2094
            return {
2095
                min: {x: mmin[apply](0, x), y: mmin[apply](0, y)},
2096
                max: {x: mmax[apply](0, x), y: mmax[apply](0, y)}
2097
            };
2098
        }),
2099
        path2curve = R._path2curve = cacher(function (path, path2) {
2100
            var pth = !path2 && paths(path);
2101
            if (!path2 && pth.curve) {
2102
                return pathClone(pth.curve);
2103
            }
2104
            var p = pathToAbsolute(path),
2105
                p2 = path2 && pathToAbsolute(path2),
2106
                attrs = {x: 0, y: 0, bx: 0, by: 0, X: 0, Y: 0, qx: null, qy: null},
2107
                attrs2 = {x: 0, y: 0, bx: 0, by: 0, X: 0, Y: 0, qx: null, qy: null},
2108
                processPath = function (path, d, pcom) {
2109
                    var nx, ny, tq = {T:1, Q:1};
2110
                    if (!path) {
2111
                        return ["C", d.x, d.y, d.x, d.y, d.x, d.y];
2112
                    }
2113
                    !(path[0] in tq) && (d.qx = d.qy = null);
2114
                    switch (path[0]) {
2115
                        case "M":
2116
                            d.X = path[1];
2117
                            d.Y = path[2];
2118
                            break;
2119
                        case "A":
2120
                            path = ["C"][concat](a2c[apply](0, [d.x, d.y][concat](path.slice(1))));
2121
                            break;
2122
                        case "S":
2123
                            if (pcom == "C" || pcom == "S") { // In "S" case we have to take into account, if the previous command is C/S.
2124
                                nx = d.x * 2 - d.bx;          // And reflect the previous
2125
                                ny = d.y * 2 - d.by;          // command's control point relative to the current point.
2126
                            }
2127
                            else {                            // or some else or nothing
2128
                                nx = d.x;
2129
                                ny = d.y;
2130
                            }
2131
                            path = ["C", nx, ny][concat](path.slice(1));
2132
                            break;
2133
                        case "T":
2134
                            if (pcom == "Q" || pcom == "T") { // In "T" case we have to take into account, if the previous command is Q/T.
2135
                                d.qx = d.x * 2 - d.qx;        // And make a reflection similar
2136
                                d.qy = d.y * 2 - d.qy;        // to case "S".
2137
                            }
2138
                            else {                            // or something else or nothing
2139
                                d.qx = d.x;
2140
                                d.qy = d.y;
2141
                            }
2142
                            path = ["C"][concat](q2c(d.x, d.y, d.qx, d.qy, path[1], path[2]));
2143
                            break;
2144
                        case "Q":
2145
                            d.qx = path[1];
2146
                            d.qy = path[2];
2147
                            path = ["C"][concat](q2c(d.x, d.y, path[1], path[2], path[3], path[4]));
2148
                            break;
2149
                        case "L":
2150
                            path = ["C"][concat](l2c(d.x, d.y, path[1], path[2]));
2151
                            break;
2152
                        case "H":
2153
                            path = ["C"][concat](l2c(d.x, d.y, path[1], d.y));
2154
                            break;
2155
                        case "V":
2156
                            path = ["C"][concat](l2c(d.x, d.y, d.x, path[1]));
2157
                            break;
2158
                        case "Z":
2159
                            path = ["C"][concat](l2c(d.x, d.y, d.X, d.Y));
2160
                            break;
2161
                    }
2162
                    return path;
2163
                },
2164
                fixArc = function (pp, i) {
2165
                    if (pp[i].length > 7) {
2166
                        pp[i].shift();
2167
                        var pi = pp[i];
2168
                        while (pi.length) {
2169
                            pcoms1[i]="A"; // if created multiple C:s, their original seg is saved
2170
                            p2 && (pcoms2[i]="A"); // the same as above
2171
                            pp.splice(i++, 0, ["C"][concat](pi.splice(0, 6)));
2172
                        }
2173
                        pp.splice(i, 1);
2174
                        ii = mmax(p.length, p2 && p2.length || 0);
2175
                    }
2176
                },
2177
                fixM = function (path1, path2, a1, a2, i) {
2178
                    if (path1 && path2 && path1[i][0] == "M" && path2[i][0] != "M") {
2179
                        path2.splice(i, 0, ["M", a2.x, a2.y]);
2180
                        a1.bx = 0;
2181
                        a1.by = 0;
2182
                        a1.x = path1[i][1];
2183
                        a1.y = path1[i][2];
2184
                        ii = mmax(p.length, p2 && p2.length || 0);
2185
                    }
2186
                },
2187
                pcoms1 = [], // path commands of original path p
2188
                pcoms2 = [], // path commands of original path p2
2189
                pfirst = "", // temporary holder for original path command
2190
                pcom = ""; // holder for previous path command of original path
2191
            for (var i = 0, ii = mmax(p.length, p2 && p2.length || 0); i < ii; i++) {
2192
                p[i] && (pfirst = p[i][0]); // save current path command
2193

2194
                if (pfirst != "C") // C is not saved yet, because it may be result of conversion
2195
                {
2196
                    pcoms1[i] = pfirst; // Save current path command
2197
                    i && ( pcom = pcoms1[i-1]); // Get previous path command pcom
2198
                }
2199
                p[i] = processPath(p[i], attrs, pcom); // Previous path command is inputted to processPath
2200

2201
                if (pcoms1[i] != "A" && pfirst == "C") pcoms1[i] = "C"; // A is the only command
2202
                // which may produce multiple C:s
2203
                // so we have to make sure that C is also C in original path
2204

2205
                fixArc(p, i); // fixArc adds also the right amount of A:s to pcoms1
2206

2207
                if (p2) { // the same procedures is done to p2
2208
                    p2[i] && (pfirst = p2[i][0]);
2209
                    if (pfirst != "C")
2210
                    {
2211
                        pcoms2[i] = pfirst;
2212
                        i && (pcom = pcoms2[i-1]);
2213
                    }
2214
                    p2[i] = processPath(p2[i], attrs2, pcom);
2215

2216
                    if (pcoms2[i]!="A" && pfirst=="C") pcoms2[i]="C";
2217

2218
                    fixArc(p2, i);
2219
                }
2220
                fixM(p, p2, attrs, attrs2, i);
2221
                fixM(p2, p, attrs2, attrs, i);
2222
                var seg = p[i],
2223
                    seg2 = p2 && p2[i],
2224
                    seglen = seg.length,
2225
                    seg2len = p2 && seg2.length;
2226
                attrs.x = seg[seglen - 2];
2227
                attrs.y = seg[seglen - 1];
2228
                attrs.bx = toFloat(seg[seglen - 4]) || attrs.x;
2229
                attrs.by = toFloat(seg[seglen - 3]) || attrs.y;
2230
                attrs2.bx = p2 && (toFloat(seg2[seg2len - 4]) || attrs2.x);
2231
                attrs2.by = p2 && (toFloat(seg2[seg2len - 3]) || attrs2.y);
2232
                attrs2.x = p2 && seg2[seg2len - 2];
2233
                attrs2.y = p2 && seg2[seg2len - 1];
2234
            }
2235
            if (!p2) {
2236
                pth.curve = pathClone(p);
2237
            }
2238
            return p2 ? [p, p2] : p;
2239
        }, null, pathClone),
2240
        parseDots = R._parseDots = cacher(function (gradient) {
2241
            var dots = [];
2242
            for (var i = 0, ii = gradient.length; i < ii; i++) {
2243
                var dot = {},
2244
                    par = gradient[i].match(/^([^:]*):?([\d\.]*)/);
2245
                dot.color = R.getRGB(par[1]);
2246
                if (dot.color.error) {
2247
                    return null;
2248
                }
2249
                dot.opacity = dot.color.opacity;
2250
                dot.color = dot.color.hex;
2251
                par[2] && (dot.offset = par[2] + "%");
2252
                dots.push(dot);
2253
            }
2254
            for (i = 1, ii = dots.length - 1; i < ii; i++) {
2255
                if (!dots[i].offset) {
2256
                    var start = toFloat(dots[i - 1].offset || 0),
2257
                        end = 0;
2258
                    for (var j = i + 1; j < ii; j++) {
2259
                        if (dots[j].offset) {
2260
                            end = dots[j].offset;
2261
                            break;
2262
                        }
2263
                    }
2264
                    if (!end) {
2265
                        end = 100;
2266
                        j = ii;
2267
                    }
2268
                    end = toFloat(end);
2269
                    var d = (end - start) / (j - i + 1);
2270
                    for (; i < j; i++) {
2271
                        start += d;
2272
                        dots[i].offset = start + "%";
2273
                    }
2274
                }
2275
            }
2276
            return dots;
2277
        }),
2278
        tear = R._tear = function (el, paper) {
2279
            el == paper.top && (paper.top = el.prev);
2280
            el == paper.bottom && (paper.bottom = el.next);
2281
            el.next && (el.next.prev = el.prev);
2282
            el.prev && (el.prev.next = el.next);
2283
        },
2284
        tofront = R._tofront = function (el, paper) {
2285
            if (paper.top === el) {
2286
                return;
2287
            }
2288
            tear(el, paper);
2289
            el.next = null;
2290
            el.prev = paper.top;
2291
            paper.top.next = el;
2292
            paper.top = el;
2293
        },
2294
        toback = R._toback = function (el, paper) {
2295
            if (paper.bottom === el) {
2296
                return;
2297
            }
2298
            tear(el, paper);
2299
            el.next = paper.bottom;
2300
            el.prev = null;
2301
            paper.bottom.prev = el;
2302
            paper.bottom = el;
2303
        },
2304
        insertafter = R._insertafter = function (el, el2, paper) {
2305
            tear(el, paper);
2306
            el2 == paper.top && (paper.top = el);
2307
            el2.next && (el2.next.prev = el);
2308
            el.next = el2.next;
2309
            el.prev = el2;
2310
            el2.next = el;
2311
        },
2312
        insertbefore = R._insertbefore = function (el, el2, paper) {
2313
            tear(el, paper);
2314
            el2 == paper.bottom && (paper.bottom = el);
2315
            el2.prev && (el2.prev.next = el);
2316
            el.prev = el2.prev;
2317
            el2.prev = el;
2318
            el.next = el2;
2319
        },
2320
        /*\
2321
         * Raphael.toMatrix
2322
         [ method ]
2323
         **
2324
         * Utility method
2325
         **
2326
         * Returns matrix of transformations applied to a given path
2327
         > Parameters
2328
         - path (string) path string
2329
         - transform (string|array) transformation string
2330
         = (object) @Matrix
2331
        \*/
2332
        toMatrix = R.toMatrix = function (path, transform) {
2333
            var bb = pathDimensions(path),
2334
                el = {
2335
                    _: {
2336
                        transform: E
2337
                    },
2338
                    getBBox: function () {
2339
                        return bb;
2340
                    }
2341
                };
2342
            extractTransform(el, transform);
2343
            return el.matrix;
2344
        },
2345
        /*\
2346
         * Raphael.transformPath
2347
         [ method ]
2348
         **
2349
         * Utility method
2350
         **
2351
         * Returns path transformed by a given transformation
2352
         > Parameters
2353
         - path (string) path string
2354
         - transform (string|array) transformation string
2355
         = (string) path
2356
        \*/
2357
        transformPath = R.transformPath = function (path, transform) {
2358
            return mapPath(path, toMatrix(path, transform));
2359
        },
2360
        extractTransform = R._extractTransform = function (el, tstr) {
2361
            if (tstr == null) {
2362
                return el._.transform;
2363
            }
2364
            tstr = Str(tstr).replace(/\.{3}|\u2026/g, el._.transform || E);
2365
            var tdata = R.parseTransformString(tstr),
2366
                deg = 0,
2367
                dx = 0,
2368
                dy = 0,
2369
                sx = 1,
2370
                sy = 1,
2371
                _ = el._,
2372
                m = new Matrix;
2373
            _.transform = tdata || [];
2374
            if (tdata) {
2375
                for (var i = 0, ii = tdata.length; i < ii; i++) {
2376
                    var t = tdata[i],
2377
                        tlen = t.length,
2378
                        command = Str(t[0]).toLowerCase(),
2379
                        absolute = t[0] != command,
2380
                        inver = absolute ? m.invert() : 0,
2381
                        x1,
2382
                        y1,
2383
                        x2,
2384
                        y2,
2385
                        bb;
2386
                    if (command == "t" && tlen == 3) {
2387
                        if (absolute) {
2388
                            x1 = inver.x(0, 0);
2389
                            y1 = inver.y(0, 0);
2390
                            x2 = inver.x(t[1], t[2]);
2391
                            y2 = inver.y(t[1], t[2]);
2392
                            m.translate(x2 - x1, y2 - y1);
2393
                        } else {
2394
                            m.translate(t[1], t[2]);
2395
                        }
2396
                    } else if (command == "r") {
2397
                        if (tlen == 2) {
2398
                            bb = bb || el.getBBox(1);
2399
                            m.rotate(t[1], bb.x + bb.width / 2, bb.y + bb.height / 2);
2400
                            deg += t[1];
2401
                        } else if (tlen == 4) {
2402
                            if (absolute) {
2403
                                x2 = inver.x(t[2], t[3]);
2404
                                y2 = inver.y(t[2], t[3]);
2405
                                m.rotate(t[1], x2, y2);
2406
                            } else {
2407
                                m.rotate(t[1], t[2], t[3]);
2408
                            }
2409
                            deg += t[1];
2410
                        }
2411
                    } else if (command == "s") {
2412
                        if (tlen == 2 || tlen == 3) {
2413
                            bb = bb || el.getBBox(1);
2414
                            m.scale(t[1], t[tlen - 1], bb.x + bb.width / 2, bb.y + bb.height / 2);
2415
                            sx *= t[1];
2416
                            sy *= t[tlen - 1];
2417
                        } else if (tlen == 5) {
2418
                            if (absolute) {
2419
                                x2 = inver.x(t[3], t[4]);
2420
                                y2 = inver.y(t[3], t[4]);
2421
                                m.scale(t[1], t[2], x2, y2);
2422
                            } else {
2423
                                m.scale(t[1], t[2], t[3], t[4]);
2424
                            }
2425
                            sx *= t[1];
2426
                            sy *= t[2];
2427
                        }
2428
                    } else if (command == "m" && tlen == 7) {
2429
                        m.add(t[1], t[2], t[3], t[4], t[5], t[6]);
2430
                    }
2431
                    _.dirtyT = 1;
2432
                    el.matrix = m;
2433
                }
2434
            }
2435

2436
            /*\
2437
             * Element.matrix
2438
             [ property (object) ]
2439
             **
2440
             * Keeps @Matrix object, which represents element transformation
2441
            \*/
2442
            el.matrix = m;
2443

2444
            _.sx = sx;
2445
            _.sy = sy;
2446
            _.deg = deg;
2447
            _.dx = dx = m.e;
2448
            _.dy = dy = m.f;
2449

2450
            if (sx == 1 && sy == 1 && !deg && _.bbox) {
2451
                _.bbox.x += +dx;
2452
                _.bbox.y += +dy;
2453
            } else {
2454
                _.dirtyT = 1;
2455
            }
2456
        },
2457
        getEmpty = function (item) {
2458
            var l = item[0];
2459
            switch (l.toLowerCase()) {
2460
                case "t": return [l, 0, 0];
2461
                case "m": return [l, 1, 0, 0, 1, 0, 0];
2462
                case "r": if (item.length == 4) {
2463
                    return [l, 0, item[2], item[3]];
2464
                } else {
2465
                    return [l, 0];
2466
                }
2467
                case "s": if (item.length == 5) {
2468
                    return [l, 1, 1, item[3], item[4]];
2469
                } else if (item.length == 3) {
2470
                    return [l, 1, 1];
2471
                } else {
2472
                    return [l, 1];
2473
                }
2474
            }
2475
        },
2476
        equaliseTransform = R._equaliseTransform = function (t1, t2) {
2477
            t2 = Str(t2).replace(/\.{3}|\u2026/g, t1);
2478
            t1 = R.parseTransformString(t1) || [];
2479
            t2 = R.parseTransformString(t2) || [];
2480
            var maxlength = mmax(t1.length, t2.length),
2481
                from = [],
2482
                to = [],
2483
                i = 0, j, jj,
2484
                tt1, tt2;
2485
            for (; i < maxlength; i++) {
2486
                tt1 = t1[i] || getEmpty(t2[i]);
2487
                tt2 = t2[i] || getEmpty(tt1);
2488
                if ((tt1[0] != tt2[0]) ||
2489
                    (tt1[0].toLowerCase() == "r" && (tt1[2] != tt2[2] || tt1[3] != tt2[3])) ||
2490
                    (tt1[0].toLowerCase() == "s" && (tt1[3] != tt2[3] || tt1[4] != tt2[4]))
2491
                    ) {
2492
                    return;
2493
                }
2494
                from[i] = [];
2495
                to[i] = [];
2496
                for (j = 0, jj = mmax(tt1.length, tt2.length); j < jj; j++) {
2497
                    j in tt1 && (from[i][j] = tt1[j]);
2498
                    j in tt2 && (to[i][j] = tt2[j]);
2499
                }
2500
            }
2501
            return {
2502
                from: from,
2503
                to: to
2504
            };
2505
        };
2506
    R._getContainer = function (x, y, w, h) {
2507
        var container;
2508
        container = h == null && !R.is(x, "object") ? g.doc.getElementById(x) : x;
2509
        if (container == null) {
2510
            return;
2511
        }
2512
        if (container.tagName) {
2513
            if (y == null) {
2514
                return {
2515
                    container: container,
2516
                    width: container.style.pixelWidth || container.offsetWidth,
2517
                    height: container.style.pixelHeight || container.offsetHeight
2518
                };
2519
            } else {
2520
                return {
2521
                    container: container,
2522
                    width: y,
2523
                    height: w
2524
                };
2525
            }
2526
        }
2527
        return {
2528
            container: 1,
2529
            x: x,
2530
            y: y,
2531
            width: w,
2532
            height: h
2533
        };
2534
    };
2535
    /*\
2536
     * Raphael.pathToRelative
2537
     [ method ]
2538
     **
2539
     * Utility method
2540
     **
2541
     * Converts path to relative form
2542
     > Parameters
2543
     - pathString (string|array) path string or array of segments
2544
     = (array) array of segments.
2545
    \*/
2546
    R.pathToRelative = pathToRelative;
2547
    R._engine = {};
2548
    /*\
2549
     * Raphael.path2curve
2550
     [ method ]
2551
     **
2552
     * Utility method
2553
     **
2554
     * Converts path to a new path where all segments are cubic bezier curves.
2555
     > Parameters
2556
     - pathString (string|array) path string or array of segments
2557
     = (array) array of segments.
2558
    \*/
2559
    R.path2curve = path2curve;
2560
    /*\
2561
     * Raphael.matrix
2562
     [ method ]
2563
     **
2564
     * Utility method
2565
     **
2566
     * Returns matrix based on given parameters.
2567
     > Parameters
2568
     - a (number)
2569
     - b (number)
2570
     - c (number)
2571
     - d (number)
2572
     - e (number)
2573
     - f (number)
2574
     = (object) @Matrix
2575
    \*/
2576
    R.matrix = function (a, b, c, d, e, f) {
2577
        return new Matrix(a, b, c, d, e, f);
2578
    };
2579
    function Matrix(a, b, c, d, e, f) {
2580
        if (a != null) {
2581
            this.a = +a;
2582
            this.b = +b;
2583
            this.c = +c;
2584
            this.d = +d;
2585
            this.e = +e;
2586
            this.f = +f;
2587
        } else {
2588
            this.a = 1;
2589
            this.b = 0;
2590
            this.c = 0;
2591
            this.d = 1;
2592
            this.e = 0;
2593
            this.f = 0;
2594
        }
2595
    }
2596
    (function (matrixproto) {
2597
        /*\
2598
         * Matrix.add
2599
         [ method ]
2600
         **
2601
         * Adds given matrix to existing one.
2602
         > Parameters
2603
         - a (number)
2604
         - b (number)
2605
         - c (number)
2606
         - d (number)
2607
         - e (number)
2608
         - f (number)
2609
         or
2610
         - matrix (object) @Matrix
2611
        \*/
2612
        matrixproto.add = function (a, b, c, d, e, f) {
2613
            var out = [[], [], []],
2614
                m = [[this.a, this.c, this.e], [this.b, this.d, this.f], [0, 0, 1]],
2615
                matrix = [[a, c, e], [b, d, f], [0, 0, 1]],
2616
                x, y, z, res;
2617

2618
            if (a && a instanceof Matrix) {
2619
                matrix = [[a.a, a.c, a.e], [a.b, a.d, a.f], [0, 0, 1]];
2620
            }
2621

2622
            for (x = 0; x < 3; x++) {
2623
                for (y = 0; y < 3; y++) {
2624
                    res = 0;
2625
                    for (z = 0; z < 3; z++) {
2626
                        res += m[x][z] * matrix[z][y];
2627
                    }
2628
                    out[x][y] = res;
2629
                }
2630
            }
2631
            this.a = out[0][0];
2632
            this.b = out[1][0];
2633
            this.c = out[0][1];
2634
            this.d = out[1][1];
2635
            this.e = out[0][2];
2636
            this.f = out[1][2];
2637
        };
2638
        /*\
2639
         * Matrix.invert
2640
         [ method ]
2641
         **
2642
         * Returns inverted version of the matrix
2643
         = (object) @Matrix
2644
        \*/
2645
        matrixproto.invert = function () {
2646
            var me = this,
2647
                x = me.a * me.d - me.b * me.c;
2648
            return new Matrix(me.d / x, -me.b / x, -me.c / x, me.a / x, (me.c * me.f - me.d * me.e) / x, (me.b * me.e - me.a * me.f) / x);
2649
        };
2650
        /*\
2651
         * Matrix.clone
2652
         [ method ]
2653
         **
2654
         * Returns copy of the matrix
2655
         = (object) @Matrix
2656
        \*/
2657
        matrixproto.clone = function () {
2658
            return new Matrix(this.a, this.b, this.c, this.d, this.e, this.f);
2659
        };
2660
        /*\
2661
         * Matrix.translate
2662
         [ method ]
2663
         **
2664
         * Translate the matrix
2665
         > Parameters
2666
         - x (number)
2667
         - y (number)
2668
        \*/
2669
        matrixproto.translate = function (x, y) {
2670
            this.add(1, 0, 0, 1, x, y);
2671
        };
2672
        /*\
2673
         * Matrix.scale
2674
         [ method ]
2675
         **
2676
         * Scales the matrix
2677
         > Parameters
2678
         - x (number)
2679
         - y (number) #optional
2680
         - cx (number) #optional
2681
         - cy (number) #optional
2682
        \*/
2683
        matrixproto.scale = function (x, y, cx, cy) {
2684
            y == null && (y = x);
2685
            (cx || cy) && this.add(1, 0, 0, 1, cx, cy);
2686
            this.add(x, 0, 0, y, 0, 0);
2687
            (cx || cy) && this.add(1, 0, 0, 1, -cx, -cy);
2688
        };
2689
        /*\
2690
         * Matrix.rotate
2691
         [ method ]
2692
         **
2693
         * Rotates the matrix
2694
         > Parameters
2695
         - a (number)
2696
         - x (number)
2697
         - y (number)
2698
        \*/
2699
        matrixproto.rotate = function (a, x, y) {
2700
            a = R.rad(a);
2701
            x = x || 0;
2702
            y = y || 0;
2703
            var cos = +math.cos(a).toFixed(9),
2704
                sin = +math.sin(a).toFixed(9);
2705
            this.add(cos, sin, -sin, cos, x, y);
2706
            this.add(1, 0, 0, 1, -x, -y);
2707
        };
2708
        /*\
2709
         * Matrix.x
2710
         [ method ]
2711
         **
2712
         * Return x coordinate for given point after transformation described by the matrix. See also @Matrix.y
2713
         > Parameters
2714
         - x (number)
2715
         - y (number)
2716
         = (number) x
2717
        \*/
2718
        matrixproto.x = function (x, y) {
2719
            return x * this.a + y * this.c + this.e;
2720
        };
2721
        /*\
2722
         * Matrix.y
2723
         [ method ]
2724
         **
2725
         * Return y coordinate for given point after transformation described by the matrix. See also @Matrix.x
2726
         > Parameters
2727
         - x (number)
2728
         - y (number)
2729
         = (number) y
2730
        \*/
2731
        matrixproto.y = function (x, y) {
2732
            return x * this.b + y * this.d + this.f;
2733
        };
2734
        matrixproto.get = function (i) {
2735
            return +this[Str.fromCharCode(97 + i)].toFixed(4);
2736
        };
2737
        matrixproto.toString = function () {
2738
            return R.svg ?
2739
                "matrix(" + [this.get(0), this.get(1), this.get(2), this.get(3), this.get(4), this.get(5)].join() + ")" :
2740
                [this.get(0), this.get(2), this.get(1), this.get(3), 0, 0].join();
2741
        };
2742
        matrixproto.toFilter = function () {
2743
            return "progid:DXImageTransform.Microsoft.Matrix(M11=" + this.get(0) +
2744
                ", M12=" + this.get(2) + ", M21=" + this.get(1) + ", M22=" + this.get(3) +
2745
                ", Dx=" + this.get(4) + ", Dy=" + this.get(5) + ", sizingmethod='auto expand')";
2746
        };
2747
        matrixproto.offset = function () {
2748
            return [this.e.toFixed(4), this.f.toFixed(4)];
2749
        };
2750
        function norm(a) {
2751
            return a[0] * a[0] + a[1] * a[1];
2752
        }
2753
        function normalize(a) {
2754
            var mag = math.sqrt(norm(a));
2755
            a[0] && (a[0] /= mag);
2756
            a[1] && (a[1] /= mag);
2757
        }
2758
        /*\
2759
         * Matrix.split
2760
         [ method ]
2761
         **
2762
         * Splits matrix into primitive transformations
2763
         = (object) in format:
2764
         o dx (number) translation by x
2765
         o dy (number) translation by y
2766
         o scalex (number) scale by x
2767
         o scaley (number) scale by y
2768
         o shear (number) shear
2769
         o rotate (number) rotation in deg
2770
         o isSimple (boolean) could it be represented via simple transformations
2771
        \*/
2772
        matrixproto.split = function () {
2773
            var out = {};
2774
            // translation
2775
            out.dx = this.e;
2776
            out.dy = this.f;
2777

2778
            // scale and shear
2779
            var row = [[this.a, this.c], [this.b, this.d]];
2780
            out.scalex = math.sqrt(norm(row[0]));
2781
            normalize(row[0]);
2782

2783
            out.shear = row[0][0] * row[1][0] + row[0][1] * row[1][1];
2784
            row[1] = [row[1][0] - row[0][0] * out.shear, row[1][1] - row[0][1] * out.shear];
2785

2786
            out.scaley = math.sqrt(norm(row[1]));
2787
            normalize(row[1]);
2788
            out.shear /= out.scaley;
2789

2790
            // rotation
2791
            var sin = -row[0][1],
2792
                cos = row[1][1];
2793
            if (cos < 0) {
2794
                out.rotate = R.deg(math.acos(cos));
2795
                if (sin < 0) {
2796
                    out.rotate = 360 - out.rotate;
2797
                }
2798
            } else {
2799
                out.rotate = R.deg(math.asin(sin));
2800
            }
2801

2802
            out.isSimple = !+out.shear.toFixed(9) && (out.scalex.toFixed(9) == out.scaley.toFixed(9) || !out.rotate);
2803
            out.isSuperSimple = !+out.shear.toFixed(9) && out.scalex.toFixed(9) == out.scaley.toFixed(9) && !out.rotate;
2804
            out.noRotation = !+out.shear.toFixed(9) && !out.rotate;
2805
            return out;
2806
        };
2807
        /*\
2808
         * Matrix.toTransformString
2809
         [ method ]
2810
         **
2811
         * Return transform string that represents given matrix
2812
         = (string) transform string
2813
        \*/
2814
        matrixproto.toTransformString = function (shorter) {
2815
            var s = shorter || this[split]();
2816
            if (s.isSimple) {
2817
                s.scalex = +s.scalex.toFixed(4);
2818
                s.scaley = +s.scaley.toFixed(4);
2819
                s.rotate = +s.rotate.toFixed(4);
2820
                return  (s.dx || s.dy ? "t" + [s.dx, s.dy] : E) +
2821
                        (s.scalex != 1 || s.scaley != 1 ? "s" + [s.scalex, s.scaley, 0, 0] : E) +
2822
                        (s.rotate ? "r" + [s.rotate, 0, 0] : E);
2823
            } else {
2824
                return "m" + [this.get(0), this.get(1), this.get(2), this.get(3), this.get(4), this.get(5)];
2825
            }
2826
        };
2827
    })(Matrix.prototype);
2828

2829
    var preventDefault = function () {
2830
        this.returnValue = false;
2831
    },
2832
    preventTouch = function () {
2833
        return this.originalEvent.preventDefault();
2834
    },
2835
    stopPropagation = function () {
2836
        this.cancelBubble = true;
2837
    },
2838
    stopTouch = function () {
2839
        return this.originalEvent.stopPropagation();
2840
    },
2841
    getEventPosition = function (e) {
2842
        var scrollY = g.doc.documentElement.scrollTop || g.doc.body.scrollTop,
2843
            scrollX = g.doc.documentElement.scrollLeft || g.doc.body.scrollLeft;
2844

2845
        return {
2846
            x: e.clientX + scrollX,
2847
            y: e.clientY + scrollY
2848
        };
2849
    },
2850
    addEvent = (function () {
2851
        if (g.doc.addEventListener) {
2852
            return function (obj, type, fn, element) {
2853
                var f = function (e) {
2854
                    var pos = getEventPosition(e);
2855
                    return fn.call(element, e, pos.x, pos.y);
2856
                };
2857
                obj.addEventListener(type, f, false);
2858

2859
                if (supportsTouch && touchMap[type]) {
2860
                    var _f = function (e) {
2861
                        var pos = getEventPosition(e),
2862
                            olde = e;
2863

2864
                        for (var i = 0, ii = e.targetTouches && e.targetTouches.length; i < ii; i++) {
2865
                            if (e.targetTouches[i].target == obj) {
2866
                                e = e.targetTouches[i];
2867
                                e.originalEvent = olde;
2868
                                e.preventDefault = preventTouch;
2869
                                e.stopPropagation = stopTouch;
2870
                                break;
2871
                            }
2872
                        }
2873

2874
                        return fn.call(element, e, pos.x, pos.y);
2875
                    };
2876
                    obj.addEventListener(touchMap[type], _f, false);
2877
                }
2878

2879
                return function () {
2880
                    obj.removeEventListener(type, f, false);
2881

2882
                    if (supportsTouch && touchMap[type])
2883
                        obj.removeEventListener(touchMap[type], _f, false);
2884

2885
                    return true;
2886
                };
2887
            };
2888
        } else if (g.doc.attachEvent) {
2889
            return function (obj, type, fn, element) {
2890
                var f = function (e) {
2891
                    e = e || g.win.event;
2892
                    var scrollY = g.doc.documentElement.scrollTop || g.doc.body.scrollTop,
2893
                        scrollX = g.doc.documentElement.scrollLeft || g.doc.body.scrollLeft,
2894
                        x = e.clientX + scrollX,
2895
                        y = e.clientY + scrollY;
2896
                    e.preventDefault = e.preventDefault || preventDefault;
2897
                    e.stopPropagation = e.stopPropagation || stopPropagation;
2898
                    return fn.call(element, e, x, y);
2899
                };
2900
                obj.attachEvent("on" + type, f);
2901
                var detacher = function () {
2902
                    obj.detachEvent("on" + type, f);
2903
                    return true;
2904
                };
2905
                return detacher;
2906
            };
2907
        }
2908
    })(),
2909
    drag = [],
2910
    dragMove = function (e) {
2911
        var x = e.clientX,
2912
            y = e.clientY,
2913
            scrollY = g.doc.documentElement.scrollTop || g.doc.body.scrollTop,
2914
            scrollX = g.doc.documentElement.scrollLeft || g.doc.body.scrollLeft,
2915
            dragi,
2916
            j = drag.length;
2917
        while (j--) {
2918
            dragi = drag[j];
2919
            if (supportsTouch && e.touches) {
2920
                var i = e.touches.length,
2921
                    touch;
2922
                while (i--) {
2923
                    touch = e.touches[i];
2924
                    if (touch.identifier == dragi.el._drag.id) {
2925
                        x = touch.clientX;
2926
                        y = touch.clientY;
2927
                        (e.originalEvent ? e.originalEvent : e).preventDefault();
2928
                        break;
2929
                    }
2930
                }
2931
            } else {
2932
                e.preventDefault();
2933
            }
2934
            var node = dragi.el.node,
2935
                o,
2936
                next = node.nextSibling,
2937
                parent = node.parentNode,
2938
                display = node.style.display;
2939
            g.win.opera && parent.removeChild(node);
2940
            node.style.display = "none";
2941
            o = dragi.el.paper.getElementByPoint(x, y);
2942
            node.style.display = display;
2943
            g.win.opera && (next ? parent.insertBefore(node, next) : parent.appendChild(node));
2944
            o && eve("raphael.drag.over." + dragi.el.id, dragi.el, o);
2945
            x += scrollX;
2946
            y += scrollY;
2947
            eve("raphael.drag.move." + dragi.el.id, dragi.move_scope || dragi.el, x - dragi.el._drag.x, y - dragi.el._drag.y, x, y, e);
2948
        }
2949
    },
2950
    dragUp = function (e) {
2951
        R.unmousemove(dragMove).unmouseup(dragUp);
2952
        var i = drag.length,
2953
            dragi;
2954
        while (i--) {
2955
            dragi = drag[i];
2956
            dragi.el._drag = {};
2957
            eve("raphael.drag.end." + dragi.el.id, dragi.end_scope || dragi.start_scope || dragi.move_scope || dragi.el, e);
2958
        }
2959
        drag = [];
2960
    },
2961
    /*\
2962
     * Raphael.el
2963
     [ property (object) ]
2964
     **
2965
     * You can add your own method to elements. This is useful when you want to hack default functionality or
2966
     * want to wrap some common transformation or attributes in one method. In difference to canvas methods,
2967
     * you can redefine element method at any time. Expending element methods wouldn’t affect set.
2968
     > Usage
2969
     | Raphael.el.red = function () {
2970
     |     this.attr({fill: "#f00"});
2971
     | };
2972
     | // then use it
2973
     | paper.circle(100, 100, 20).red();
2974
    \*/
2975
    elproto = R.el = {};
2976
    /*\
2977
     * Element.click
2978
     [ method ]
2979
     **
2980
     * Adds event handler for click for the element.
2981
     > Parameters
2982
     - handler (function) handler for the event
2983
     = (object) @Element
2984
    \*/
2985
    /*\
2986
     * Element.unclick
2987
     [ method ]
2988
     **
2989
     * Removes event handler for click for the element.
2990
     > Parameters
2991
     - handler (function) #optional handler for the event
2992
     = (object) @Element
2993
    \*/
2994

2995
    /*\
2996
     * Element.dblclick
2997
     [ method ]
2998
     **
2999
     * Adds event handler for double click for the element.
3000
     > Parameters
3001
     - handler (function) handler for the event
3002
     = (object) @Element
3003
    \*/
3004
    /*\
3005
     * Element.undblclick
3006
     [ method ]
3007
     **
3008
     * Removes event handler for double click for the element.
3009
     > Parameters
3010
     - handler (function) #optional handler for the event
3011
     = (object) @Element
3012
    \*/
3013

3014
    /*\
3015
     * Element.mousedown
3016
     [ method ]
3017
     **
3018
     * Adds event handler for mousedown for the element.
3019
     > Parameters
3020
     - handler (function) handler for the event
3021
     = (object) @Element
3022
    \*/
3023
    /*\
3024
     * Element.unmousedown
3025
     [ method ]
3026
     **
3027
     * Removes event handler for mousedown for the element.
3028
     > Parameters
3029
     - handler (function) #optional handler for the event
3030
     = (object) @Element
3031
    \*/
3032

3033
    /*\
3034
     * Element.mousemove
3035
     [ method ]
3036
     **
3037
     * Adds event handler for mousemove for the element.
3038
     > Parameters
3039
     - handler (function) handler for the event
3040
     = (object) @Element
3041
    \*/
3042
    /*\
3043
     * Element.unmousemove
3044
     [ method ]
3045
     **
3046
     * Removes event handler for mousemove for the element.
3047
     > Parameters
3048
     - handler (function) #optional handler for the event
3049
     = (object) @Element
3050
    \*/
3051

3052
    /*\
3053
     * Element.mouseout
3054
     [ method ]
3055
     **
3056
     * Adds event handler for mouseout for the element.
3057
     > Parameters
3058
     - handler (function) handler for the event
3059
     = (object) @Element
3060
    \*/
3061
    /*\
3062
     * Element.unmouseout
3063
     [ method ]
3064
     **
3065
     * Removes event handler for mouseout for the element.
3066
     > Parameters
3067
     - handler (function) #optional handler for the event
3068
     = (object) @Element
3069
    \*/
3070

3071
    /*\
3072
     * Element.mouseover
3073
     [ method ]
3074
     **
3075
     * Adds event handler for mouseover for the element.
3076
     > Parameters
3077
     - handler (function) handler for the event
3078
     = (object) @Element
3079
    \*/
3080
    /*\
3081
     * Element.unmouseover
3082
     [ method ]
3083
     **
3084
     * Removes event handler for mouseover for the element.
3085
     > Parameters
3086
     - handler (function) #optional handler for the event
3087
     = (object) @Element
3088
    \*/
3089

3090
    /*\
3091
     * Element.mouseup
3092
     [ method ]
3093
     **
3094
     * Adds event handler for mouseup for the element.
3095
     > Parameters
3096
     - handler (function) handler for the event
3097
     = (object) @Element
3098
    \*/
3099
    /*\
3100
     * Element.unmouseup
3101
     [ method ]
3102
     **
3103
     * Removes event handler for mouseup for the element.
3104
     > Parameters
3105
     - handler (function) #optional handler for the event
3106
     = (object) @Element
3107
    \*/
3108

3109
    /*\
3110
     * Element.touchstart
3111
     [ method ]
3112
     **
3113
     * Adds event handler for touchstart for the element.
3114
     > Parameters
3115
     - handler (function) handler for the event
3116
     = (object) @Element
3117
    \*/
3118
    /*\
3119
     * Element.untouchstart
3120
     [ method ]
3121
     **
3122
     * Removes event handler for touchstart for the element.
3123
     > Parameters
3124
     - handler (function) #optional handler for the event
3125
     = (object) @Element
3126
    \*/
3127

3128
    /*\
3129
     * Element.touchmove
3130
     [ method ]
3131
     **
3132
     * Adds event handler for touchmove for the element.
3133
     > Parameters
3134
     - handler (function) handler for the event
3135
     = (object) @Element
3136
    \*/
3137
    /*\
3138
     * Element.untouchmove
3139
     [ method ]
3140
     **
3141
     * Removes event handler for touchmove for the element.
3142
     > Parameters
3143
     - handler (function) #optional handler for the event
3144
     = (object) @Element
3145
    \*/
3146

3147
    /*\
3148
     * Element.touchend
3149
     [ method ]
3150
     **
3151
     * Adds event handler for touchend for the element.
3152
     > Parameters
3153
     - handler (function) handler for the event
3154
     = (object) @Element
3155
    \*/
3156
    /*\
3157
     * Element.untouchend
3158
     [ method ]
3159
     **
3160
     * Removes event handler for touchend for the element.
3161
     > Parameters
3162
     - handler (function) #optional handler for the event
3163
     = (object) @Element
3164
    \*/
3165

3166
    /*\
3167
     * Element.touchcancel
3168
     [ method ]
3169
     **
3170
     * Adds event handler for touchcancel for the element.
3171
     > Parameters
3172
     - handler (function) handler for the event
3173
     = (object) @Element
3174
    \*/
3175
    /*\
3176
     * Element.untouchcancel
3177
     [ method ]
3178
     **
3179
     * Removes event handler for touchcancel for the element.
3180
     > Parameters
3181
     - handler (function) #optional handler for the event
3182
     = (object) @Element
3183
    \*/
3184
    for (var i = events.length; i--;) {
3185
        (function (eventName) {
3186
            R[eventName] = elproto[eventName] = function (fn, scope) {
3187
                if (R.is(fn, "function")) {
3188
                    this.events = this.events || [];
3189
                    this.events.push({name: eventName, f: fn, unbind: addEvent(this.shape || this.node || g.doc, eventName, fn, scope || this)});
3190
                }
3191
                return this;
3192
            };
3193
            R["un" + eventName] = elproto["un" + eventName] = function (fn) {
3194
                var events = this.events || [],
3195
                    l = events.length;
3196
                while (l--){
3197
                    if (events[l].name == eventName && (R.is(fn, "undefined") || events[l].f == fn)) {
3198
                        events[l].unbind();
3199
                        events.splice(l, 1);
3200
                        !events.length && delete this.events;
3201
                    }
3202
                }
3203
                return this;
3204
            };
3205
        })(events[i]);
3206
    }
3207

3208
    /*\
3209
     * Element.data
3210
     [ method ]
3211
     **
3212
     * Adds or retrieves given value associated with given key.
3213
     **
3214
     * See also @Element.removeData
3215
     > Parameters
3216
     - key (string) key to store data
3217
     - value (any) #optional value to store
3218
     = (object) @Element
3219
     * or, if value is not specified:
3220
     = (any) value
3221
     * or, if key and value are not specified:
3222
     = (object) Key/value pairs for all the data associated with the element.
3223
     > Usage
3224
     | for (var i = 0, i < 5, i++) {
3225
     |     paper.circle(10 + 15 * i, 10, 10)
3226
     |          .attr({fill: "#000"})
3227
     |          .data("i", i)
3228
     |          .click(function () {
3229
     |             alert(this.data("i"));
3230
     |          });
3231
     | }
3232
    \*/
3233
    elproto.data = function (key, value) {
3234
        var data = eldata[this.id] = eldata[this.id] || {};
3235
        if (arguments.length == 0) {
3236
            return data;
3237
        }
3238
        if (arguments.length == 1) {
3239
            if (R.is(key, "object")) {
3240
                for (var i in key) if (key[has](i)) {
3241
                    this.data(i, key[i]);
3242
                }
3243
                return this;
3244
            }
3245
            eve("raphael.data.get." + this.id, this, data[key], key);
3246
            return data[key];
3247
        }
3248
        data[key] = value;
3249
        eve("raphael.data.set." + this.id, this, value, key);
3250
        return this;
3251
    };
3252
    /*\
3253
     * Element.removeData
3254
     [ method ]
3255
     **
3256
     * Removes value associated with an element by given key.
3257
     * If key is not provided, removes all the data of the element.
3258
     > Parameters
3259
     - key (string) #optional key
3260
     = (object) @Element
3261
    \*/
3262
    elproto.removeData = function (key) {
3263
        if (key == null) {
3264
            delete eldata[this.id];
3265
        } else {
3266
            eldata[this.id] && delete eldata[this.id][key];
3267
        }
3268
        return this;
3269
    };
3270
     /*\
3271
     * Element.getData
3272
     [ method ]
3273
     **
3274
     * Retrieves the element data
3275
     = (object) data
3276
    \*/
3277
    elproto.getData = function () {
3278
        return clone(eldata[this.id] || {});
3279
    };
3280
    /*\
3281
     * Element.hover
3282
     [ method ]
3283
     **
3284
     * Adds event handlers for hover for the element.
3285
     > Parameters
3286
     - f_in (function) handler for hover in
3287
     - f_out (function) handler for hover out
3288
     - icontext (object) #optional context for hover in handler
3289
     - ocontext (object) #optional context for hover out handler
3290
     = (object) @Element
3291
    \*/
3292
    elproto.hover = function (f_in, f_out, scope_in, scope_out) {
3293
        return this.mouseover(f_in, scope_in).mouseout(f_out, scope_out || scope_in);
3294
    };
3295
    /*\
3296
     * Element.unhover
3297
     [ method ]
3298
     **
3299
     * Removes event handlers for hover for the element.
3300
     > Parameters
3301
     - f_in (function) handler for hover in
3302
     - f_out (function) handler for hover out
3303
     = (object) @Element
3304
    \*/
3305
    elproto.unhover = function (f_in, f_out) {
3306
        return this.unmouseover(f_in).unmouseout(f_out);
3307
    };
3308
    var draggable = [];
3309
    /*\
3310
     * Element.drag
3311
     [ method ]
3312
     **
3313
     * Adds event handlers for drag of the element.
3314
     > Parameters
3315
     - onmove (function) handler for moving
3316
     - onstart (function) handler for drag start
3317
     - onend (function) handler for drag end
3318
     - mcontext (object) #optional context for moving handler
3319
     - scontext (object) #optional context for drag start handler
3320
     - econtext (object) #optional context for drag end handler
3321
     * Additionally following `drag` events will be triggered: `drag.start.<id>` on start,
3322
     * `drag.end.<id>` on end and `drag.move.<id>` on every move. When element will be dragged over another element
3323
     * `drag.over.<id>` will be fired as well.
3324
     *
3325
     * Start event and start handler will be called in specified context or in context of the element with following parameters:
3326
     o x (number) x position of the mouse
3327
     o y (number) y position of the mouse
3328
     o event (object) DOM event object
3329
     * Move event and move handler will be called in specified context or in context of the element with following parameters:
3330
     o dx (number) shift by x from the start point
3331
     o dy (number) shift by y from the start point
3332
     o x (number) x position of the mouse
3333
     o y (number) y position of the mouse
3334
     o event (object) DOM event object
3335
     * End event and end handler will be called in specified context or in context of the element with following parameters:
3336
     o event (object) DOM event object
3337
     = (object) @Element
3338
    \*/
3339
    elproto.drag = function (onmove, onstart, onend, move_scope, start_scope, end_scope) {
3340
        function start(e) {
3341
            (e.originalEvent || e).preventDefault();
3342
            var x = e.clientX,
3343
                y = e.clientY,
3344
                scrollY = g.doc.documentElement.scrollTop || g.doc.body.scrollTop,
3345
                scrollX = g.doc.documentElement.scrollLeft || g.doc.body.scrollLeft;
3346
            this._drag.id = e.identifier;
3347
            if (supportsTouch && e.touches) {
3348
                var i = e.touches.length, touch;
3349
                while (i--) {
3350
                    touch = e.touches[i];
3351
                    this._drag.id = touch.identifier;
3352
                    if (touch.identifier == this._drag.id) {
3353
                        x = touch.clientX;
3354
                        y = touch.clientY;
3355
                        break;
3356
                    }
3357
                }
3358
            }
3359
            this._drag.x = x + scrollX;
3360
            this._drag.y = y + scrollY;
3361
            !drag.length && R.mousemove(dragMove).mouseup(dragUp);
3362
            drag.push({el: this, move_scope: move_scope, start_scope: start_scope, end_scope: end_scope});
3363
            onstart && eve.on("raphael.drag.start." + this.id, onstart);
3364
            onmove && eve.on("raphael.drag.move." + this.id, onmove);
3365
            onend && eve.on("raphael.drag.end." + this.id, onend);
3366
            eve("raphael.drag.start." + this.id, start_scope || move_scope || this, this._drag.x, this._drag.y, e);
3367
        }
3368
        this._drag = {};
3369
        draggable.push({el: this, start: start});
3370
        this.mousedown(start);
3371
        return this;
3372
    };
3373
    /*\
3374
     * Element.onDragOver
3375
     [ method ]
3376
     **
3377
     * Shortcut for assigning event handler for `drag.over.<id>` event, where id is id of the element (see @Element.id).
3378
     > Parameters
3379
     - f (function) handler for event, first argument would be the element you are dragging over
3380
    \*/
3381
    elproto.onDragOver = function (f) {
3382
        f ? eve.on("raphael.drag.over." + this.id, f) : eve.unbind("raphael.drag.over." + this.id);
3383
    };
3384
    /*\
3385
     * Element.undrag
3386
     [ method ]
3387
     **
3388
     * Removes all drag event handlers from given element.
3389
    \*/
3390
    elproto.undrag = function () {
3391
        var i = draggable.length;
3392
        while (i--) if (draggable[i].el == this) {
3393
            this.unmousedown(draggable[i].start);
3394
            draggable.splice(i, 1);
3395
            eve.unbind("raphael.drag.*." + this.id);
3396
        }
3397
        !draggable.length && R.unmousemove(dragMove).unmouseup(dragUp);
3398
        drag = [];
3399
    };
3400
    /*\
3401
     * Paper.circle
3402
     [ method ]
3403
     **
3404
     * Draws a circle.
3405
     **
3406
     > Parameters
3407
     **
3408
     - x (number) x coordinate of the centre
3409
     - y (number) y coordinate of the centre
3410
     - r (number) radius
3411
     = (object) Raphaël element object with type “circle”
3412
     **
3413
     > Usage
3414
     | var c = paper.circle(50, 50, 40);
3415
    \*/
3416
    paperproto.circle = function (x, y, r) {
3417
        var out = R._engine.circle(this, x || 0, y || 0, r || 0);
3418
        this.__set__ && this.__set__.push(out);
3419
        return out;
3420
    };
3421
    /*\
3422
     * Paper.rect
3423
     [ method ]
3424
     *
3425
     * Draws a rectangle.
3426
     **
3427
     > Parameters
3428
     **
3429
     - x (number) x coordinate of the top left corner
3430
     - y (number) y coordinate of the top left corner
3431
     - width (number) width
3432
     - height (number) height
3433
     - r (number) #optional radius for rounded corners, default is 0
3434
     = (object) Raphaël element object with type “rect”
3435
     **
3436
     > Usage
3437
     | // regular rectangle
3438
     | var c = paper.rect(10, 10, 50, 50);
3439
     | // rectangle with rounded corners
3440
     | var c = paper.rect(40, 40, 50, 50, 10);
3441
    \*/
3442
    paperproto.rect = function (x, y, w, h, r) {
3443
        var out = R._engine.rect(this, x || 0, y || 0, w || 0, h || 0, r || 0);
3444
        this.__set__ && this.__set__.push(out);
3445
        return out;
3446
    };
3447
    /*\
3448
     * Paper.ellipse
3449
     [ method ]
3450
     **
3451
     * Draws an ellipse.
3452
     **
3453
     > Parameters
3454
     **
3455
     - x (number) x coordinate of the centre
3456
     - y (number) y coordinate of the centre
3457
     - rx (number) horizontal radius
3458
     - ry (number) vertical radius
3459
     = (object) Raphaël element object with type “ellipse”
3460
     **
3461
     > Usage
3462
     | var c = paper.ellipse(50, 50, 40, 20);
3463
    \*/
3464
    paperproto.ellipse = function (x, y, rx, ry) {
3465
        var out = R._engine.ellipse(this, x || 0, y || 0, rx || 0, ry || 0);
3466
        this.__set__ && this.__set__.push(out);
3467
        return out;
3468
    };
3469
    /*\
3470
     * Paper.path
3471
     [ method ]
3472
     **
3473
     * Creates a path element by given path data string.
3474
     > Parameters
3475
     - pathString (string) #optional path string in SVG format.
3476
     * Path string consists of one-letter commands, followed by comma seprarated arguments in numercal form. Example:
3477
     | "M10,20L30,40"
3478
     * Here we can see two commands: “M”, with arguments `(10, 20)` and “L” with arguments `(30, 40)`. Upper case letter mean command is absolute, lower case—relative.
3479
     *
3480
     # <p>Here is short list of commands available, for more details see <a href="http://www.w3.org/TR/SVG/paths.html#PathData" title="Details of a path's data attribute's format are described in the SVG specification.">SVG path string format</a>.</p>
3481
     # <table><thead><tr><th>Command</th><th>Name</th><th>Parameters</th></tr></thead><tbody>
3482
     # <tr><td>M</td><td>moveto</td><td>(x y)+</td></tr>
3483
     # <tr><td>Z</td><td>closepath</td><td>(none)</td></tr>
3484
     # <tr><td>L</td><td>lineto</td><td>(x y)+</td></tr>
3485
     # <tr><td>H</td><td>horizontal lineto</td><td>x+</td></tr>
3486
     # <tr><td>V</td><td>vertical lineto</td><td>y+</td></tr>
3487
     # <tr><td>C</td><td>curveto</td><td>(x1 y1 x2 y2 x y)+</td></tr>
3488
     # <tr><td>S</td><td>smooth curveto</td><td>(x2 y2 x y)+</td></tr>
3489
     # <tr><td>Q</td><td>quadratic Bézier curveto</td><td>(x1 y1 x y)+</td></tr>
3490
     # <tr><td>T</td><td>smooth quadratic Bézier curveto</td><td>(x y)+</td></tr>
3491
     # <tr><td>A</td><td>elliptical arc</td><td>(rx ry x-axis-rotation large-arc-flag sweep-flag x y)+</td></tr>
3492
     # <tr><td>R</td><td><a href="http://en.wikipedia.org/wiki/Catmull–Rom_spline#Catmull.E2.80.93Rom_spline">Catmull-Rom curveto</a>*</td><td>x1 y1 (x y)+</td></tr></tbody></table>
3493
     * * “Catmull-Rom curveto” is a not standard SVG command and added in 2.0 to make life easier.
3494
     * Note: there is a special case when path consist of just three commands: “M10,10R…z”. In this case path will smoothly connects to its beginning.
3495
     > Usage
3496
     | var c = paper.path("M10 10L90 90");
3497
     | // draw a diagonal line:
3498
     | // move to 10,10, line to 90,90
3499
     * For example of path strings, check out these icons: http://raphaeljs.com/icons/
3500
    \*/
3501
    paperproto.path = function (pathString) {
3502
        pathString && !R.is(pathString, string) && !R.is(pathString[0], array) && (pathString += E);
3503
        var out = R._engine.path(R.format[apply](R, arguments), this);
3504
        this.__set__ && this.__set__.push(out);
3505
        return out;
3506
    };
3507
    /*\
3508
     * Paper.image
3509
     [ method ]
3510
     **
3511
     * Embeds an image into the surface.
3512
     **
3513
     > Parameters
3514
     **
3515
     - src (string) URI of the source image
3516
     - x (number) x coordinate position
3517
     - y (number) y coordinate position
3518
     - width (number) width of the image
3519
     - height (number) height of the image
3520
     = (object) Raphaël element object with type “image”
3521
     **
3522
     > Usage
3523
     | var c = paper.image("apple.png", 10, 10, 80, 80);
3524
    \*/
3525
    paperproto.image = function (src, x, y, w, h) {
3526
        var out = R._engine.image(this, src || "about:blank", x || 0, y || 0, w || 0, h || 0);
3527
        this.__set__ && this.__set__.push(out);
3528
        return out;
3529
    };
3530
    /*\
3531
     * Paper.text
3532
     [ method ]
3533
     **
3534
     * Draws a text string. If you need line breaks, put “\n” in the string.
3535
     **
3536
     > Parameters
3537
     **
3538
     - x (number) x coordinate position
3539
     - y (number) y coordinate position
3540
     - text (string) The text string to draw
3541
     = (object) Raphaël element object with type “text”
3542
     **
3543
     > Usage
3544
     | var t = paper.text(50, 50, "Raphaël\nkicks\nbutt!");
3545
    \*/
3546
    paperproto.text = function (x, y, text) {
3547
        var out = R._engine.text(this, x || 0, y || 0, Str(text));
3548
        this.__set__ && this.__set__.push(out);
3549
        return out;
3550
    };
3551
    /*\
3552
     * Paper.set
3553
     [ method ]
3554
     **
3555
     * Creates array-like object to keep and operate several elements at once.
3556
     * Warning: it doesn’t create any elements for itself in the page, it just groups existing elements.
3557
     * Sets act as pseudo elements — all methods available to an element can be used on a set.
3558
     = (object) array-like object that represents set of elements
3559
     **
3560
     > Usage
3561
     | var st = paper.set();
3562
     | st.push(
3563
     |     paper.circle(10, 10, 5),
3564
     |     paper.circle(30, 10, 5)
3565
     | );
3566
     | st.attr({fill: "red"}); // changes the fill of both circles
3567
    \*/
3568
    paperproto.set = function (itemsArray) {
3569
        !R.is(itemsArray, "array") && (itemsArray = Array.prototype.splice.call(arguments, 0, arguments.length));
3570
        var out = new Set(itemsArray);
3571
        this.__set__ && this.__set__.push(out);
3572
        out["paper"] = this;
3573
        out["type"] = "set";
3574
        return out;
3575
    };
3576
    /*\
3577
     * Paper.setStart
3578
     [ method ]
3579
     **
3580
     * Creates @Paper.set. All elements that will be created after calling this method and before calling
3581
     * @Paper.setFinish will be added to the set.
3582
     **
3583
     > Usage
3584
     | paper.setStart();
3585
     | paper.circle(10, 10, 5),
3586
     | paper.circle(30, 10, 5)
3587
     | var st = paper.setFinish();
3588
     | st.attr({fill: "red"}); // changes the fill of both circles
3589
    \*/
3590
    paperproto.setStart = function (set) {
3591
        this.__set__ = set || this.set();
3592
    };
3593
    /*\
3594
     * Paper.setFinish
3595
     [ method ]
3596
     **
3597
     * See @Paper.setStart. This method finishes catching and returns resulting set.
3598
     **
3599
     = (object) set
3600
    \*/
3601
    paperproto.setFinish = function (set) {
3602
        var out = this.__set__;
3603
        delete this.__set__;
3604
        return out;
3605
    };
3606
    /*\
3607
     * Paper.getSize
3608
     [ method ]
3609
     **
3610
     * Obtains current paper actual size.
3611
     **
3612
     = (object)
3613
     \*/
3614
    paperproto.getSize = function () {
3615
        var container = this.canvas.parentNode;
3616
        return {
3617
            width: container.offsetWidth,
3618
            height: container.offsetHeight
3619
                };
3620
        };
3621
    /*\
3622
     * Paper.setSize
3623
     [ method ]
3624
     **
3625
     * If you need to change dimensions of the canvas call this method
3626
     **
3627
     > Parameters
3628
     **
3629
     - width (number) new width of the canvas
3630
     - height (number) new height of the canvas
3631
    \*/
3632
    paperproto.setSize = function (width, height) {
3633
        return R._engine.setSize.call(this, width, height);
3634
    };
3635
    /*\
3636
     * Paper.setViewBox
3637
     [ method ]
3638
     **
3639
     * Sets the view box of the paper. Practically it gives you ability to zoom and pan whole paper surface by
3640
     * specifying new boundaries.
3641
     **
3642
     > Parameters
3643
     **
3644
     - x (number) new x position, default is `0`
3645
     - y (number) new y position, default is `0`
3646
     - w (number) new width of the canvas
3647
     - h (number) new height of the canvas
3648
     - fit (boolean) `true` if you want graphics to fit into new boundary box
3649
    \*/
3650
    paperproto.setViewBox = function (x, y, w, h, fit) {
3651
        return R._engine.setViewBox.call(this, x, y, w, h, fit);
3652
    };
3653
    /*\
3654
     * Paper.top
3655
     [ property ]
3656
     **
3657
     * Points to the topmost element on the paper
3658
    \*/
3659
    /*\
3660
     * Paper.bottom
3661
     [ property ]
3662
     **
3663
     * Points to the bottom element on the paper
3664
    \*/
3665
    paperproto.top = paperproto.bottom = null;
3666
    /*\
3667
     * Paper.raphael
3668
     [ property ]
3669
     **
3670
     * Points to the @Raphael object/function
3671
    \*/
3672
    paperproto.raphael = R;
3673
    var getOffset = function (elem) {
3674
        var box = elem.getBoundingClientRect(),
3675
            doc = elem.ownerDocument,
3676
            body = doc.body,
3677
            docElem = doc.documentElement,
3678
            clientTop = docElem.clientTop || body.clientTop || 0, clientLeft = docElem.clientLeft || body.clientLeft || 0,
3679
            top  = box.top  + (g.win.pageYOffset || docElem.scrollTop || body.scrollTop ) - clientTop,
3680
            left = box.left + (g.win.pageXOffset || docElem.scrollLeft || body.scrollLeft) - clientLeft;
3681
        return {
3682
            y: top,
3683
            x: left
3684
        };
3685
    };
3686
    /*\
3687
     * Paper.getElementByPoint
3688
     [ method ]
3689
     **
3690
     * Returns you topmost element under given point.
3691
     **
3692
     = (object) Raphaël element object
3693
     > Parameters
3694
     **
3695
     - x (number) x coordinate from the top left corner of the window
3696
     - y (number) y coordinate from the top left corner of the window
3697
     > Usage
3698
     | paper.getElementByPoint(mouseX, mouseY).attr({stroke: "#f00"});
3699
    \*/
3700
    paperproto.getElementByPoint = function (x, y) {
3701
        var paper = this,
3702
            svg = paper.canvas,
3703
            target = g.doc.elementFromPoint(x, y);
3704
        if (g.win.opera && target.tagName == "svg") {
3705
            var so = getOffset(svg),
3706
                sr = svg.createSVGRect();
3707
            sr.x = x - so.x;
3708
            sr.y = y - so.y;
3709
            sr.width = sr.height = 1;
3710
            var hits = svg.getIntersectionList(sr, null);
3711
            if (hits.length) {
3712
                target = hits[hits.length - 1];
3713
            }
3714
        }
3715
        if (!target) {
3716
            return null;
3717
        }
3718
        while (target.parentNode && target != svg.parentNode && !target.raphael) {
3719
            target = target.parentNode;
3720
        }
3721
        target == paper.canvas.parentNode && (target = svg);
3722
        target = target && target.raphael ? paper.getById(target.raphaelid) : null;
3723
        return target;
3724
    };
3725

3726
    /*\
3727
     * Paper.getElementsByBBox
3728
     [ method ]
3729
     **
3730
     * Returns set of elements that have an intersecting bounding box
3731
     **
3732
     > Parameters
3733
     **
3734
     - bbox (object) bbox to check with
3735
     = (object) @Set
3736
     \*/
3737
    paperproto.getElementsByBBox = function (bbox) {
3738
        var set = this.set();
3739
        this.forEach(function (el) {
3740
            if (R.isBBoxIntersect(el.getBBox(), bbox)) {
3741
                set.push(el);
3742
            }
3743
        });
3744
        return set;
3745
    };
3746

3747
    /*\
3748
     * Paper.getById
3749
     [ method ]
3750
     **
3751
     * Returns you element by its internal ID.
3752
     **
3753
     > Parameters
3754
     **
3755
     - id (number) id
3756
     = (object) Raphaël element object
3757
    \*/
3758
    paperproto.getById = function (id) {
3759
        var bot = this.bottom;
3760
        while (bot) {
3761
            if (bot.id == id) {
3762
                return bot;
3763
            }
3764
            bot = bot.next;
3765
        }
3766
        return null;
3767
    };
3768
    /*\
3769
     * Paper.forEach
3770
     [ method ]
3771
     **
3772
     * Executes given function for each element on the paper
3773
     *
3774
     * If callback function returns `false` it will stop loop running.
3775
     **
3776
     > Parameters
3777
     **
3778
     - callback (function) function to run
3779
     - thisArg (object) context object for the callback
3780
     = (object) Paper object
3781
     > Usage
3782
     | paper.forEach(function (el) {
3783
     |     el.attr({ stroke: "blue" });
3784
     | });
3785
    \*/
3786
    paperproto.forEach = function (callback, thisArg) {
3787
        var bot = this.bottom;
3788
        while (bot) {
3789
            if (callback.call(thisArg, bot) === false) {
3790
                return this;
3791
            }
3792
            bot = bot.next;
3793
        }
3794
        return this;
3795
    };
3796
    /*\
3797
     * Paper.getElementsByPoint
3798
     [ method ]
3799
     **
3800
     * Returns set of elements that have common point inside
3801
     **
3802
     > Parameters
3803
     **
3804
     - x (number) x coordinate of the point
3805
     - y (number) y coordinate of the point
3806
     = (object) @Set
3807
    \*/
3808
    paperproto.getElementsByPoint = function (x, y) {
3809
        var set = this.set();
3810
        this.forEach(function (el) {
3811
            if (el.isPointInside(x, y)) {
3812
                set.push(el);
3813
            }
3814
        });
3815
        return set;
3816
    };
3817
    function x_y() {
3818
        return this.x + S + this.y;
3819
    }
3820
    function x_y_w_h() {
3821
        return this.x + S + this.y + S + this.width + " \xd7 " + this.height;
3822
    }
3823
    /*\
3824
     * Element.isPointInside
3825
     [ method ]
3826
     **
3827
     * Determine if given point is inside this element’s shape
3828
     **
3829
     > Parameters
3830
     **
3831
     - x (number) x coordinate of the point
3832
     - y (number) y coordinate of the point
3833
     = (boolean) `true` if point inside the shape
3834
    \*/
3835
    elproto.isPointInside = function (x, y) {
3836
        var rp = this.realPath = getPath[this.type](this);
3837
        if (this.attr('transform') && this.attr('transform').length) {
3838
            rp = R.transformPath(rp, this.attr('transform'));
3839
        }
3840
        return R.isPointInsidePath(rp, x, y);
3841
    };
3842
    /*\
3843
     * Element.getBBox
3844
     [ method ]
3845
     **
3846
     * Return bounding box for a given element
3847
     **
3848
     > Parameters
3849
     **
3850
     - isWithoutTransform (boolean) flag, `true` if you want to have bounding box before transformations. Default is `false`.
3851
     = (object) Bounding box object:
3852
     o {
3853
     o     x: (number) top left corner x
3854
     o     y: (number) top left corner y
3855
     o     x2: (number) bottom right corner x
3856
     o     y2: (number) bottom right corner y
3857
     o     width: (number) width
3858
     o     height: (number) height
3859
     o }
3860
    \*/
3861
    elproto.getBBox = function (isWithoutTransform) {
3862
        if (this.removed) {
3863
            return {};
3864
        }
3865
        var _ = this._;
3866
        if (isWithoutTransform) {
3867
            if (_.dirty || !_.bboxwt) {
3868
                this.realPath = getPath[this.type](this);
3869
                _.bboxwt = pathDimensions(this.realPath);
3870
                _.bboxwt.toString = x_y_w_h;
3871
                _.dirty = 0;
3872
            }
3873
            return _.bboxwt;
3874
        }
3875
        if (_.dirty || _.dirtyT || !_.bbox) {
3876
            if (_.dirty || !this.realPath) {
3877
                _.bboxwt = 0;
3878
                this.realPath = getPath[this.type](this);
3879
            }
3880
            _.bbox = pathDimensions(mapPath(this.realPath, this.matrix));
3881
            _.bbox.toString = x_y_w_h;
3882
            _.dirty = _.dirtyT = 0;
3883
        }
3884
        return _.bbox;
3885
    };
3886
    /*\
3887
     * Element.clone
3888
     [ method ]
3889
     **
3890
     = (object) clone of a given element
3891
     **
3892
    \*/
3893
    elproto.clone = function () {
3894
        if (this.removed) {
3895
            return null;
3896
        }
3897
        var out = this.paper[this.type]().attr(this.attr());
3898
        this.__set__ && this.__set__.push(out);
3899
        return out;
3900
    };
3901
    /*\
3902
     * Element.glow
3903
     [ method ]
3904
     **
3905
     * Return set of elements that create glow-like effect around given element. See @Paper.set.
3906
     *
3907
     * Note: Glow is not connected to the element. If you change element attributes it won’t adjust itself.
3908
     **
3909
     > Parameters
3910
     **
3911
     - glow (object) #optional parameters object with all properties optional:
3912
     o {
3913
     o     width (number) size of the glow, default is `10`
3914
     o     fill (boolean) will it be filled, default is `false`
3915
     o     opacity (number) opacity, default is `0.5`
3916
     o     offsetx (number) horizontal offset, default is `0`
3917
     o     offsety (number) vertical offset, default is `0`
3918
     o     color (string) glow colour, default is `black`
3919
     o }
3920
     = (object) @Paper.set of elements that represents glow
3921
    \*/
3922
    elproto.glow = function (glow) {
3923
        if (this.type == "text") {
3924
            return null;
3925
        }
3926
        glow = glow || {};
3927
        var s = {
3928
            width: (glow.width || 10) + (+this.attr("stroke-width") || 1),
3929
            fill: glow.fill || false,
3930
            opacity: glow.opacity == null ? .5 : glow.opacity,
3931
            offsetx: glow.offsetx || 0,
3932
            offsety: glow.offsety || 0,
3933
            color: glow.color || "#000"
3934
        },
3935
            c = s.width / 2,
3936
            r = this.paper,
3937
            out = r.set(),
3938
            path = this.realPath || getPath[this.type](this);
3939
        path = this.matrix ? mapPath(path, this.matrix) : path;
3940
        for (var i = 1; i < c + 1; i++) {
3941
            out.push(r.path(path).attr({
3942
                stroke: s.color,
3943
                fill: s.fill ? s.color : "none",
3944
                "stroke-linejoin": "round",
3945
                "stroke-linecap": "round",
3946
                "stroke-width": +(s.width / c * i).toFixed(3),
3947
                opacity: +(s.opacity / c).toFixed(3)
3948
            }));
3949
        }
3950
        return out.insertBefore(this).translate(s.offsetx, s.offsety);
3951
    };
3952
    var curveslengths = {},
3953
    getPointAtSegmentLength = function (p1x, p1y, c1x, c1y, c2x, c2y, p2x, p2y, length) {
3954
        if (length == null) {
3955
            return bezlen(p1x, p1y, c1x, c1y, c2x, c2y, p2x, p2y);
3956
        } else {
3957
            return R.findDotsAtSegment(p1x, p1y, c1x, c1y, c2x, c2y, p2x, p2y, getTatLen(p1x, p1y, c1x, c1y, c2x, c2y, p2x, p2y, length));
3958
        }
3959
    },
3960
    getLengthFactory = function (istotal, subpath) {
3961
        return function (path, length, onlystart) {
3962
            path = path2curve(path);
3963
            var x, y, p, l, sp = "", subpaths = {}, point,
3964
                len = 0;
3965
            for (var i = 0, ii = path.length; i < ii; i++) {
3966
                p = path[i];
3967
                if (p[0] == "M") {
3968
                    x = +p[1];
3969
                    y = +p[2];
3970
                } else {
3971
                    l = getPointAtSegmentLength(x, y, p[1], p[2], p[3], p[4], p[5], p[6]);
3972
                    if (len + l > length) {
3973
                        if (subpath && !subpaths.start) {
3974
                            point = getPointAtSegmentLength(x, y, p[1], p[2], p[3], p[4], p[5], p[6], length - len);
3975
                            sp += ["C" + point.start.x, point.start.y, point.m.x, point.m.y, point.x, point.y];
3976
                            if (onlystart) {return sp;}
3977
                            subpaths.start = sp;
3978
                            sp = ["M" + point.x, point.y + "C" + point.n.x, point.n.y, point.end.x, point.end.y, p[5], p[6]].join();
3979
                            len += l;
3980
                            x = +p[5];
3981
                            y = +p[6];
3982
                            continue;
3983
                        }
3984
                        if (!istotal && !subpath) {
3985
                            point = getPointAtSegmentLength(x, y, p[1], p[2], p[3], p[4], p[5], p[6], length - len);
3986
                            return {x: point.x, y: point.y, alpha: point.alpha};
3987
                        }
3988
                    }
3989
                    len += l;
3990
                    x = +p[5];
3991
                    y = +p[6];
3992
                }
3993
                sp += p.shift() + p;
3994
            }
3995
            subpaths.end = sp;
3996
            point = istotal ? len : subpath ? subpaths : R.findDotsAtSegment(x, y, p[0], p[1], p[2], p[3], p[4], p[5], 1);
3997
            point.alpha && (point = {x: point.x, y: point.y, alpha: point.alpha});
3998
            return point;
3999
        };
4000
    };
4001
    var getTotalLength = getLengthFactory(1),
4002
        getPointAtLength = getLengthFactory(),
4003
        getSubpathsAtLength = getLengthFactory(0, 1);
4004
    /*\
4005
     * Raphael.getTotalLength
4006
     [ method ]
4007
     **
4008
     * Returns length of the given path in pixels.
4009
     **
4010
     > Parameters
4011
     **
4012
     - path (string) SVG path string.
4013
     **
4014
     = (number) length.
4015
    \*/
4016
    R.getTotalLength = getTotalLength;
4017
    /*\
4018
     * Raphael.getPointAtLength
4019
     [ method ]
4020
     **
4021
     * Return coordinates of the point located at the given length on the given path.
4022
     **
4023
     > Parameters
4024
     **
4025
     - path (string) SVG path string
4026
     - length (number)
4027
     **
4028
     = (object) representation of the point:
4029
     o {
4030
     o     x: (number) x coordinate
4031
     o     y: (number) y coordinate
4032
     o     alpha: (number) angle of derivative
4033
     o }
4034
    \*/
4035
    R.getPointAtLength = getPointAtLength;
4036
    /*\
4037
     * Raphael.getSubpath
4038
     [ method ]
4039
     **
4040
     * Return subpath of a given path from given length to given length.
4041
     **
4042
     > Parameters
4043
     **
4044
     - path (string) SVG path string
4045
     - from (number) position of the start of the segment
4046
     - to (number) position of the end of the segment
4047
     **
4048
     = (string) pathstring for the segment
4049
    \*/
4050
    R.getSubpath = function (path, from, to) {
4051
        if (this.getTotalLength(path) - to < 1e-6) {
4052
            return getSubpathsAtLength(path, from).end;
4053
        }
4054
        var a = getSubpathsAtLength(path, to, 1);
4055
        return from ? getSubpathsAtLength(a, from).end : a;
4056
    };
4057
    /*\
4058
     * Element.getTotalLength
4059
     [ method ]
4060
     **
4061
     * Returns length of the path in pixels. Only works for element of “path” type.
4062
     = (number) length.
4063
    \*/
4064
    elproto.getTotalLength = function () {
4065
        var path = this.getPath();
4066
        if (!path) {
4067
            return;
4068
        }
4069

4070
        if (this.node.getTotalLength) {
4071
            return this.node.getTotalLength();
4072
        }
4073

4074
        return getTotalLength(path);
4075
    };
4076
    /*\
4077
     * Element.getPointAtLength
4078
     [ method ]
4079
     **
4080
     * Return coordinates of the point located at the given length on the given path. Only works for element of “path” type.
4081
     **
4082
     > Parameters
4083
     **
4084
     - length (number)
4085
     **
4086
     = (object) representation of the point:
4087
     o {
4088
     o     x: (number) x coordinate
4089
     o     y: (number) y coordinate
4090
     o     alpha: (number) angle of derivative
4091
     o }
4092
    \*/
4093
    elproto.getPointAtLength = function (length) {
4094
        var path = this.getPath();
4095
        if (!path) {
4096
            return;
4097
        }
4098

4099
        return getPointAtLength(path, length);
4100
    };
4101
    /*\
4102
     * Element.getPath
4103
     [ method ]
4104
     **
4105
     * Returns path of the element. Only works for elements of “path” type and simple elements like circle.
4106
     = (object) path
4107
     **
4108
    \*/
4109
    elproto.getPath = function () {
4110
        var path,
4111
            getPath = R._getPath[this.type];
4112

4113
        if (this.type == "text" || this.type == "set") {
4114
            return;
4115
        }
4116

4117
        if (getPath) {
4118
            path = getPath(this);
4119
        }
4120

4121
        return path;
4122
    };
4123
    /*\
4124
     * Element.getSubpath
4125
     [ method ]
4126
     **
4127
     * Return subpath of a given element from given length to given length. Only works for element of “path” type.
4128
     **
4129
     > Parameters
4130
     **
4131
     - from (number) position of the start of the segment
4132
     - to (number) position of the end of the segment
4133
     **
4134
     = (string) pathstring for the segment
4135
    \*/
4136
    elproto.getSubpath = function (from, to) {
4137
        var path = this.getPath();
4138
        if (!path) {
4139
            return;
4140
        }
4141

4142
        return R.getSubpath(path, from, to);
4143
    };
4144
    /*\
4145
     * Raphael.easing_formulas
4146
     [ property ]
4147
     **
4148
     * Object that contains easing formulas for animation. You could extend it with your own. By default it has following list of easing:
4149
     # <ul>
4150
     #     <li>“linear”</li>
4151
     #     <li>“&lt;” or “easeIn” or “ease-in”</li>
4152
     #     <li>“>” or “easeOut” or “ease-out”</li>
4153
     #     <li>“&lt;>” or “easeInOut” or “ease-in-out”</li>
4154
     #     <li>“backIn” or “back-in”</li>
4155
     #     <li>“backOut” or “back-out”</li>
4156
     #     <li>“elastic”</li>
4157
     #     <li>“bounce”</li>
4158
     # </ul>
4159
     # <p>See also <a href="http://raphaeljs.com/easing.html">Easing demo</a>.</p>
4160
    \*/
4161
    var ef = R.easing_formulas = {
4162
        linear: function (n) {
4163
            return n;
4164
        },
4165
        "<": function (n) {
4166
            return pow(n, 1.7);
4167
        },
4168
        ">": function (n) {
4169
            return pow(n, .48);
4170
        },
4171
        "<>": function (n) {
4172
            var q = .48 - n / 1.04,
4173
                Q = math.sqrt(.1734 + q * q),
4174
                x = Q - q,
4175
                X = pow(abs(x), 1 / 3) * (x < 0 ? -1 : 1),
4176
                y = -Q - q,
4177
                Y = pow(abs(y), 1 / 3) * (y < 0 ? -1 : 1),
4178
                t = X + Y + .5;
4179
            return (1 - t) * 3 * t * t + t * t * t;
4180
        },
4181
        backIn: function (n) {
4182
            var s = 1.70158;
4183
            return n * n * ((s + 1) * n - s);
4184
        },
4185
        backOut: function (n) {
4186
            n = n - 1;
4187
            var s = 1.70158;
4188
            return n * n * ((s + 1) * n + s) + 1;
4189
        },
4190
        elastic: function (n) {
4191
            if (n == !!n) {
4192
                return n;
4193
            }
4194
            return pow(2, -10 * n) * math.sin((n - .075) * (2 * PI) / .3) + 1;
4195
        },
4196
        bounce: function (n) {
4197
            var s = 7.5625,
4198
                p = 2.75,
4199
                l;
4200
            if (n < (1 / p)) {
4201
                l = s * n * n;
4202
            } else {
4203
                if (n < (2 / p)) {
4204
                    n -= (1.5 / p);
4205
                    l = s * n * n + .75;
4206
                } else {
4207
                    if (n < (2.5 / p)) {
4208
                        n -= (2.25 / p);
4209
                        l = s * n * n + .9375;
4210
                    } else {
4211
                        n -= (2.625 / p);
4212
                        l = s * n * n + .984375;
4213
                    }
4214
                }
4215
            }
4216
            return l;
4217
        }
4218
    };
4219
    ef.easeIn = ef["ease-in"] = ef["<"];
4220
    ef.easeOut = ef["ease-out"] = ef[">"];
4221
    ef.easeInOut = ef["ease-in-out"] = ef["<>"];
4222
    ef["back-in"] = ef.backIn;
4223
    ef["back-out"] = ef.backOut;
4224

4225
    var animationElements = [],
4226
        requestAnimFrame = window.requestAnimationFrame       ||
4227
                           window.webkitRequestAnimationFrame ||
4228
                           window.mozRequestAnimationFrame    ||
4229
                           window.oRequestAnimationFrame      ||
4230
                           window.msRequestAnimationFrame     ||
4231
                           function (callback) {
4232
                               setTimeout(callback, 16);
4233
                           },
4234
        animation = function () {
4235
            var Now = +new Date,
4236
                l = 0;
4237
            for (; l < animationElements.length; l++) {
4238
                var e = animationElements[l];
4239
                if (e.el.removed || e.paused) {
4240
                    continue;
4241
                }
4242
                var time = Now - e.start,
4243
                    ms = e.ms,
4244
                    easing = e.easing,
4245
                    from = e.from,
4246
                    diff = e.diff,
4247
                    to = e.to,
4248
                    t = e.t,
4249
                    that = e.el,
4250
                    set = {},
4251
                    now,
4252
                    init = {},
4253
                    key;
4254
                if (e.initstatus) {
4255
                    time = (e.initstatus * e.anim.top - e.prev) / (e.percent - e.prev) * ms;
4256
                    e.status = e.initstatus;
4257
                    delete e.initstatus;
4258
                    e.stop && animationElements.splice(l--, 1);
4259
                } else {
4260
                    e.status = (e.prev + (e.percent - e.prev) * (time / ms)) / e.anim.top;
4261
                }
4262
                if (time < 0) {
4263
                    continue;
4264
                }
4265
                if (time < ms) {
4266
                    var pos = easing(time / ms);
4267
                    for (var attr in from) if (from[has](attr)) {
4268
                        switch (availableAnimAttrs[attr]) {
4269
                            case nu:
4270
                                now = +from[attr] + pos * ms * diff[attr];
4271
                                break;
4272
                            case "colour":
4273
                                now = "rgb(" + [
4274
                                    upto255(round(from[attr].r + pos * ms * diff[attr].r)),
4275
                                    upto255(round(from[attr].g + pos * ms * diff[attr].g)),
4276
                                    upto255(round(from[attr].b + pos * ms * diff[attr].b))
4277
                                ].join(",") + ")";
4278
                                break;
4279
                            case "path":
4280
                                now = [];
4281
                                for (var i = 0, ii = from[attr].length; i < ii; i++) {
4282
                                    now[i] = [from[attr][i][0]];
4283
                                    for (var j = 1, jj = from[attr][i].length; j < jj; j++) {
4284
                                        now[i][j] = +from[attr][i][j] + pos * ms * diff[attr][i][j];
4285
                                    }
4286
                                    now[i] = now[i].join(S);
4287
                                }
4288
                                now = now.join(S);
4289
                                break;
4290
                            case "transform":
4291
                                if (diff[attr].real) {
4292
                                    now = [];
4293
                                    for (i = 0, ii = from[attr].length; i < ii; i++) {
4294
                                        now[i] = [from[attr][i][0]];
4295
                                        for (j = 1, jj = from[attr][i].length; j < jj; j++) {
4296
                                            now[i][j] = from[attr][i][j] + pos * ms * diff[attr][i][j];
4297
                                        }
4298
                                    }
4299
                                } else {
4300
                                    var get = function (i) {
4301
                                        return +from[attr][i] + pos * ms * diff[attr][i];
4302
                                    };
4303
                                    // now = [["r", get(2), 0, 0], ["t", get(3), get(4)], ["s", get(0), get(1), 0, 0]];
4304
                                    now = [["m", get(0), get(1), get(2), get(3), get(4), get(5)]];
4305
                                }
4306
                                break;
4307
                            case "csv":
4308
                                if (attr == "clip-rect") {
4309
                                    now = [];
4310
                                    i = 4;
4311
                                    while (i--) {
4312
                                        now[i] = +from[attr][i] + pos * ms * diff[attr][i];
4313
                                    }
4314
                                }
4315
                                break;
4316
                            default:
4317
                                var from2 = [][concat](from[attr]);
4318
                                now = [];
4319
                                i = that.paper.customAttributes[attr].length;
4320
                                while (i--) {
4321
                                    now[i] = +from2[i] + pos * ms * diff[attr][i];
4322
                                }
4323
                                break;
4324
                        }
4325
                        set[attr] = now;
4326
                    }
4327
                    that.attr(set);
4328
                    (function (id, that, anim) {
4329
                        setTimeout(function () {
4330
                            eve("raphael.anim.frame." + id, that, anim);
4331
                        });
4332
                    })(that.id, that, e.anim);
4333
                } else {
4334
                    (function(f, el, a) {
4335
                        setTimeout(function() {
4336
                            eve("raphael.anim.frame." + el.id, el, a);
4337
                            eve("raphael.anim.finish." + el.id, el, a);
4338
                            R.is(f, "function") && f.call(el);
4339
                        });
4340
                    })(e.callback, that, e.anim);
4341
                    that.attr(to);
4342
                    animationElements.splice(l--, 1);
4343
                    if (e.repeat > 1 && !e.next) {
4344
                        for (key in to) if (to[has](key)) {
4345
                            init[key] = e.totalOrigin[key];
4346
                        }
4347
                        e.el.attr(init);
4348
                        runAnimation(e.anim, e.el, e.anim.percents[0], null, e.totalOrigin, e.repeat - 1);
4349
                    }
4350
                    if (e.next && !e.stop) {
4351
                        runAnimation(e.anim, e.el, e.next, null, e.totalOrigin, e.repeat);
4352
                    }
4353
                }
4354
            }
4355
            animationElements.length && requestAnimFrame(animation);
4356
        },
4357
        upto255 = function (color) {
4358
            return color > 255 ? 255 : color < 0 ? 0 : color;
4359
        };
4360
    /*\
4361
     * Element.animateWith
4362
     [ method ]
4363
     **
4364
     * Acts similar to @Element.animate, but ensure that given animation runs in sync with another given element.
4365
     **
4366
     > Parameters
4367
     **
4368
     - el (object) element to sync with
4369
     - anim (object) animation to sync with
4370
     - params (object) #optional final attributes for the element, see also @Element.attr
4371
     - ms (number) #optional number of milliseconds for animation to run
4372
     - easing (string) #optional easing type. Accept on of @Raphael.easing_formulas or CSS format: `cubic&#x2010;bezier(XX,&#160;XX,&#160;XX,&#160;XX)`
4373
     - callback (function) #optional callback function. Will be called at the end of animation.
4374
     * or
4375
     - element (object) element to sync with
4376
     - anim (object) animation to sync with
4377
     - animation (object) #optional animation object, see @Raphael.animation
4378
     **
4379
     = (object) original element
4380
    \*/
4381
    elproto.animateWith = function (el, anim, params, ms, easing, callback) {
4382
        var element = this;
4383
        if (element.removed) {
4384
            callback && callback.call(element);
4385
            return element;
4386
        }
4387
        var a = params instanceof Animation ? params : R.animation(params, ms, easing, callback),
4388
            x, y;
4389
        runAnimation(a, element, a.percents[0], null, element.attr());
4390
        for (var i = 0, ii = animationElements.length; i < ii; i++) {
4391
            if (animationElements[i].anim == anim && animationElements[i].el == el) {
4392
                animationElements[ii - 1].start = animationElements[i].start;
4393
                break;
4394
            }
4395
        }
4396
        return element;
4397
        //
4398
        //
4399
        // var a = params ? R.animation(params, ms, easing, callback) : anim,
4400
        //     status = element.status(anim);
4401
        // return this.animate(a).status(a, status * anim.ms / a.ms);
4402
    };
4403
    function CubicBezierAtTime(t, p1x, p1y, p2x, p2y, duration) {
4404
        var cx = 3 * p1x,
4405
            bx = 3 * (p2x - p1x) - cx,
4406
            ax = 1 - cx - bx,
4407
            cy = 3 * p1y,
4408
            by = 3 * (p2y - p1y) - cy,
4409
            ay = 1 - cy - by;
4410
        function sampleCurveX(t) {
4411
            return ((ax * t + bx) * t + cx) * t;
4412
        }
4413
        function solve(x, epsilon) {
4414
            var t = solveCurveX(x, epsilon);
4415
            return ((ay * t + by) * t + cy) * t;
4416
        }
4417
        function solveCurveX(x, epsilon) {
4418
            var t0, t1, t2, x2, d2, i;
4419
            for(t2 = x, i = 0; i < 8; i++) {
4420
                x2 = sampleCurveX(t2) - x;
4421
                if (abs(x2) < epsilon) {
4422
                    return t2;
4423
                }
4424
                d2 = (3 * ax * t2 + 2 * bx) * t2 + cx;
4425
                if (abs(d2) < 1e-6) {
4426
                    break;
4427
                }
4428
                t2 = t2 - x2 / d2;
4429
            }
4430
            t0 = 0;
4431
            t1 = 1;
4432
            t2 = x;
4433
            if (t2 < t0) {
4434
                return t0;
4435
            }
4436
            if (t2 > t1) {
4437
                return t1;
4438
            }
4439
            while (t0 < t1) {
4440
                x2 = sampleCurveX(t2);
4441
                if (abs(x2 - x) < epsilon) {
4442
                    return t2;
4443
                }
4444
                if (x > x2) {
4445
                    t0 = t2;
4446
                } else {
4447
                    t1 = t2;
4448
                }
4449
                t2 = (t1 - t0) / 2 + t0;
4450
            }
4451
            return t2;
4452
        }
4453
        return solve(t, 1 / (200 * duration));
4454
    }
4455
    elproto.onAnimation = function (f) {
4456
        f ? eve.on("raphael.anim.frame." + this.id, f) : eve.unbind("raphael.anim.frame." + this.id);
4457
        return this;
4458
    };
4459
    function Animation(anim, ms) {
4460
        var percents = [],
4461
            newAnim = {};
4462
        this.ms = ms;
4463
        this.times = 1;
4464
        if (anim) {
4465
            for (var attr in anim) if (anim[has](attr)) {
4466
                newAnim[toFloat(attr)] = anim[attr];
4467
                percents.push(toFloat(attr));
4468
            }
4469
            percents.sort(sortByNumber);
4470
        }
4471
        this.anim = newAnim;
4472
        this.top = percents[percents.length - 1];
4473
        this.percents = percents;
4474
    }
4475
    /*\
4476
     * Animation.delay
4477
     [ method ]
4478
     **
4479
     * Creates a copy of existing animation object with given delay.
4480
     **
4481
     > Parameters
4482
     **
4483
     - delay (number) number of ms to pass between animation start and actual animation
4484
     **
4485
     = (object) new altered Animation object
4486
     | var anim = Raphael.animation({cx: 10, cy: 20}, 2e3);
4487
     | circle1.animate(anim); // run the given animation immediately
4488
     | circle2.animate(anim.delay(500)); // run the given animation after 500 ms
4489
    \*/
4490
    Animation.prototype.delay = function (delay) {
4491
        var a = new Animation(this.anim, this.ms);
4492
        a.times = this.times;
4493
        a.del = +delay || 0;
4494
        return a;
4495
    };
4496
    /*\
4497
     * Animation.repeat
4498
     [ method ]
4499
     **
4500
     * Creates a copy of existing animation object with given repetition.
4501
     **
4502
     > Parameters
4503
     **
4504
     - repeat (number) number iterations of animation. For infinite animation pass `Infinity`
4505
     **
4506
     = (object) new altered Animation object
4507
    \*/
4508
    Animation.prototype.repeat = function (times) {
4509
        var a = new Animation(this.anim, this.ms);
4510
        a.del = this.del;
4511
        a.times = math.floor(mmax(times, 0)) || 1;
4512
        return a;
4513
    };
4514
    function runAnimation(anim, element, percent, status, totalOrigin, times) {
4515
        percent = toFloat(percent);
4516
        var params,
4517
            isInAnim,
4518
            isInAnimSet,
4519
            percents = [],
4520
            next,
4521
            prev,
4522
            timestamp,
4523
            ms = anim.ms,
4524
            from = {},
4525
            to = {},
4526
            diff = {};
4527
        if (status) {
4528
            for (i = 0, ii = animationElements.length; i < ii; i++) {
4529
                var e = animationElements[i];
4530
                if (e.el.id == element.id && e.anim == anim) {
4531
                    if (e.percent != percent) {
4532
                        animationElements.splice(i, 1);
4533
                        isInAnimSet = 1;
4534
                    } else {
4535
                        isInAnim = e;
4536
                    }
4537
                    element.attr(e.totalOrigin);
4538
                    break;
4539
                }
4540
            }
4541
        } else {
4542
            status = +to; // NaN
4543
        }
4544
        for (var i = 0, ii = anim.percents.length; i < ii; i++) {
4545
            if (anim.percents[i] == percent || anim.percents[i] > status * anim.top) {
4546
                percent = anim.percents[i];
4547
                prev = anim.percents[i - 1] || 0;
4548
                ms = ms / anim.top * (percent - prev);
4549
                next = anim.percents[i + 1];
4550
                params = anim.anim[percent];
4551
                break;
4552
            } else if (status) {
4553
                element.attr(anim.anim[anim.percents[i]]);
4554
            }
4555
        }
4556
        if (!params) {
4557
            return;
4558
        }
4559
        if (!isInAnim) {
4560
            for (var attr in params) if (params[has](attr)) {
4561
                if (availableAnimAttrs[has](attr) || element.paper.customAttributes[has](attr)) {
4562
                    from[attr] = element.attr(attr);
4563
                    (from[attr] == null) && (from[attr] = availableAttrs[attr]);
4564
                    to[attr] = params[attr];
4565
                    switch (availableAnimAttrs[attr]) {
4566
                        case nu:
4567
                            diff[attr] = (to[attr] - from[attr]) / ms;
4568
                            break;
4569
                        case "colour":
4570
                            from[attr] = R.getRGB(from[attr]);
4571
                            var toColour = R.getRGB(to[attr]);
4572
                            diff[attr] = {
4573
                                r: (toColour.r - from[attr].r) / ms,
4574
                                g: (toColour.g - from[attr].g) / ms,
4575
                                b: (toColour.b - from[attr].b) / ms
4576
                            };
4577
                            break;
4578
                        case "path":
4579
                            var pathes = path2curve(from[attr], to[attr]),
4580
                                toPath = pathes[1];
4581
                            from[attr] = pathes[0];
4582
                            diff[attr] = [];
4583
                            for (i = 0, ii = from[attr].length; i < ii; i++) {
4584
                                diff[attr][i] = [0];
4585
                                for (var j = 1, jj = from[attr][i].length; j < jj; j++) {
4586
                                    diff[attr][i][j] = (toPath[i][j] - from[attr][i][j]) / ms;
4587
                                }
4588
                            }
4589
                            break;
4590
                        case "transform":
4591
                            var _ = element._,
4592
                                eq = equaliseTransform(_[attr], to[attr]);
4593
                            if (eq) {
4594
                                from[attr] = eq.from;
4595
                                to[attr] = eq.to;
4596
                                diff[attr] = [];
4597
                                diff[attr].real = true;
4598
                                for (i = 0, ii = from[attr].length; i < ii; i++) {
4599
                                    diff[attr][i] = [from[attr][i][0]];
4600
                                    for (j = 1, jj = from[attr][i].length; j < jj; j++) {
4601
                                        diff[attr][i][j] = (to[attr][i][j] - from[attr][i][j]) / ms;
4602
                                    }
4603
                                }
4604
                            } else {
4605
                                var m = (element.matrix || new Matrix),
4606
                                    to2 = {
4607
                                        _: {transform: _.transform},
4608
                                        getBBox: function () {
4609
                                            return element.getBBox(1);
4610
                                        }
4611
                                    };
4612
                                from[attr] = [
4613
                                    m.a,
4614
                                    m.b,
4615
                                    m.c,
4616
                                    m.d,
4617
                                    m.e,
4618
                                    m.f
4619
                                ];
4620
                                extractTransform(to2, to[attr]);
4621
                                to[attr] = to2._.transform;
4622
                                diff[attr] = [
4623
                                    (to2.matrix.a - m.a) / ms,
4624
                                    (to2.matrix.b - m.b) / ms,
4625
                                    (to2.matrix.c - m.c) / ms,
4626
                                    (to2.matrix.d - m.d) / ms,
4627
                                    (to2.matrix.e - m.e) / ms,
4628
                                    (to2.matrix.f - m.f) / ms
4629
                                ];
4630
                                // from[attr] = [_.sx, _.sy, _.deg, _.dx, _.dy];
4631
                                // var to2 = {_:{}, getBBox: function () { return element.getBBox(); }};
4632
                                // extractTransform(to2, to[attr]);
4633
                                // diff[attr] = [
4634
                                //     (to2._.sx - _.sx) / ms,
4635
                                //     (to2._.sy - _.sy) / ms,
4636
                                //     (to2._.deg - _.deg) / ms,
4637
                                //     (to2._.dx - _.dx) / ms,
4638
                                //     (to2._.dy - _.dy) / ms
4639
                                // ];
4640
                            }
4641
                            break;
4642
                        case "csv":
4643
                            var values = Str(params[attr])[split](separator),
4644
                                from2 = Str(from[attr])[split](separator);
4645
                            if (attr == "clip-rect") {
4646
                                from[attr] = from2;
4647
                                diff[attr] = [];
4648
                                i = from2.length;
4649
                                while (i--) {
4650
                                    diff[attr][i] = (values[i] - from[attr][i]) / ms;
4651
                                }
4652
                            }
4653
                            to[attr] = values;
4654
                            break;
4655
                        default:
4656
                            values = [][concat](params[attr]);
4657
                            from2 = [][concat](from[attr]);
4658
                            diff[attr] = [];
4659
                            i = element.paper.customAttributes[attr].length;
4660
                            while (i--) {
4661
                                diff[attr][i] = ((values[i] || 0) - (from2[i] || 0)) / ms;
4662
                            }
4663
                            break;
4664
                    }
4665
                }
4666
            }
4667
            var easing = params.easing,
4668
                easyeasy = R.easing_formulas[easing];
4669
            if (!easyeasy) {
4670
                easyeasy = Str(easing).match(bezierrg);
4671
                if (easyeasy && easyeasy.length == 5) {
4672
                    var curve = easyeasy;
4673
                    easyeasy = function (t) {
4674
                        return CubicBezierAtTime(t, +curve[1], +curve[2], +curve[3], +curve[4], ms);
4675
                    };
4676
                } else {
4677
                    easyeasy = pipe;
4678
                }
4679
            }
4680
            timestamp = params.start || anim.start || +new Date;
4681
            e = {
4682
                anim: anim,
4683
                percent: percent,
4684
                timestamp: timestamp,
4685
                start: timestamp + (anim.del || 0),
4686
                status: 0,
4687
                initstatus: status || 0,
4688
                stop: false,
4689
                ms: ms,
4690
                easing: easyeasy,
4691
                from: from,
4692
                diff: diff,
4693
                to: to,
4694
                el: element,
4695
                callback: params.callback,
4696
                prev: prev,
4697
                next: next,
4698
                repeat: times || anim.times,
4699
                origin: element.attr(),
4700
                totalOrigin: totalOrigin
4701
            };
4702
            animationElements.push(e);
4703
            if (status && !isInAnim && !isInAnimSet) {
4704
                e.stop = true;
4705
                e.start = new Date - ms * status;
4706
                if (animationElements.length == 1) {
4707
                    return animation();
4708
                }
4709
            }
4710
            if (isInAnimSet) {
4711
                e.start = new Date - e.ms * status;
4712
            }
4713
            animationElements.length == 1 && requestAnimFrame(animation);
4714
        } else {
4715
            isInAnim.initstatus = status;
4716
            isInAnim.start = new Date - isInAnim.ms * status;
4717
        }
4718
        eve("raphael.anim.start." + element.id, element, anim);
4719
    }
4720
    /*\
4721
     * Raphael.animation
4722
     [ method ]
4723
     **
4724
     * Creates an animation object that can be passed to the @Element.animate or @Element.animateWith methods.
4725
     * See also @Animation.delay and @Animation.repeat methods.
4726
     **
4727
     > Parameters
4728
     **
4729
     - params (object) final attributes for the element, see also @Element.attr
4730
     - ms (number) number of milliseconds for animation to run
4731
     - easing (string) #optional easing type. Accept one of @Raphael.easing_formulas or CSS format: `cubic&#x2010;bezier(XX,&#160;XX,&#160;XX,&#160;XX)`
4732
     - callback (function) #optional callback function. Will be called at the end of animation.
4733
     **
4734
     = (object) @Animation
4735
    \*/
4736
    R.animation = function (params, ms, easing, callback) {
4737
        if (params instanceof Animation) {
4738
            return params;
4739
        }
4740
        if (R.is(easing, "function") || !easing) {
4741
            callback = callback || easing || null;
4742
            easing = null;
4743
        }
4744
        params = Object(params);
4745
        ms = +ms || 0;
4746
        var p = {},
4747
            json,
4748
            attr;
4749
        for (attr in params) if (params[has](attr) && toFloat(attr) != attr && toFloat(attr) + "%" != attr) {
4750
            json = true;
4751
            p[attr] = params[attr];
4752
        }
4753
        if (!json) {
4754
            // if percent-like syntax is used and end-of-all animation callback used
4755
            if(callback){
4756
                // find the last one
4757
                var lastKey = 0;
4758
                for(var i in params){
4759
                    var percent = toInt(i);
4760
                    if(params[has](i) && percent > lastKey){
4761
                        lastKey = percent;
4762
                    }
4763
                }
4764
                lastKey += '%';
4765
                // if already defined callback in the last keyframe, skip
4766
                !params[lastKey].callback && (params[lastKey].callback = callback);
4767
            }
4768
          return new Animation(params, ms);
4769
        } else {
4770
            easing && (p.easing = easing);
4771
            callback && (p.callback = callback);
4772
            return new Animation({100: p}, ms);
4773
        }
4774
    };
4775
    /*\
4776
     * Element.animate
4777
     [ method ]
4778
     **
4779
     * Creates and starts animation for given element.
4780
     **
4781
     > Parameters
4782
     **
4783
     - params (object) final attributes for the element, see also @Element.attr
4784
     - ms (number) number of milliseconds for animation to run
4785
     - easing (string) #optional easing type. Accept one of @Raphael.easing_formulas or CSS format: `cubic&#x2010;bezier(XX,&#160;XX,&#160;XX,&#160;XX)`
4786
     - callback (function) #optional callback function. Will be called at the end of animation.
4787
     * or
4788
     - animation (object) animation object, see @Raphael.animation
4789
     **
4790
     = (object) original element
4791
    \*/
4792
    elproto.animate = function (params, ms, easing, callback) {
4793
        var element = this;
4794
        if (element.removed) {
4795
            callback && callback.call(element);
4796
            return element;
4797
        }
4798
        var anim = params instanceof Animation ? params : R.animation(params, ms, easing, callback);
4799
        runAnimation(anim, element, anim.percents[0], null, element.attr());
4800
        return element;
4801
    };
4802
    /*\
4803
     * Element.setTime
4804
     [ method ]
4805
     **
4806
     * Sets the status of animation of the element in milliseconds. Similar to @Element.status method.
4807
     **
4808
     > Parameters
4809
     **
4810
     - anim (object) animation object
4811
     - value (number) number of milliseconds from the beginning of the animation
4812
     **
4813
     = (object) original element if `value` is specified
4814
     * Note, that during animation following events are triggered:
4815
     *
4816
     * On each animation frame event `anim.frame.<id>`, on start `anim.start.<id>` and on end `anim.finish.<id>`.
4817
    \*/
4818
    elproto.setTime = function (anim, value) {
4819
        if (anim && value != null) {
4820
            this.status(anim, mmin(value, anim.ms) / anim.ms);
4821
        }
4822
        return this;
4823
    };
4824
    /*\
4825
     * Element.status
4826
     [ method ]
4827
     **
4828
     * Gets or sets the status of animation of the element.
4829
     **
4830
     > Parameters
4831
     **
4832
     - anim (object) #optional animation object
4833
     - value (number) #optional 0 – 1. If specified, method works like a setter and sets the status of a given animation to the value. This will cause animation to jump to the given position.
4834
     **
4835
     = (number) status
4836
     * or
4837
     = (array) status if `anim` is not specified. Array of objects in format:
4838
     o {
4839
     o     anim: (object) animation object
4840
     o     status: (number) status
4841
     o }
4842
     * or
4843
     = (object) original element if `value` is specified
4844
    \*/
4845
    elproto.status = function (anim, value) {
4846
        var out = [],
4847
            i = 0,
4848
            len,
4849
            e;
4850
        if (value != null) {
4851
            runAnimation(anim, this, -1, mmin(value, 1));
4852
            return this;
4853
        } else {
4854
            len = animationElements.length;
4855
            for (; i < len; i++) {
4856
                e = animationElements[i];
4857
                if (e.el.id == this.id && (!anim || e.anim == anim)) {
4858
                    if (anim) {
4859
                        return e.status;
4860
                    }
4861
                    out.push({
4862
                        anim: e.anim,
4863
                        status: e.status
4864
                    });
4865
                }
4866
            }
4867
            if (anim) {
4868
                return 0;
4869
            }
4870
            return out;
4871
        }
4872
    };
4873
    /*\
4874
     * Element.pause
4875
     [ method ]
4876
     **
4877
     * Stops animation of the element with ability to resume it later on.
4878
     **
4879
     > Parameters
4880
     **
4881
     - anim (object) #optional animation object
4882
     **
4883
     = (object) original element
4884
    \*/
4885
    elproto.pause = function (anim) {
4886
        for (var i = 0; i < animationElements.length; i++) if (animationElements[i].el.id == this.id && (!anim || animationElements[i].anim == anim)) {
4887
            if (eve("raphael.anim.pause." + this.id, this, animationElements[i].anim) !== false) {
4888
                animationElements[i].paused = true;
4889
            }
4890
        }
4891
        return this;
4892
    };
4893
    /*\
4894
     * Element.resume
4895
     [ method ]
4896
     **
4897
     * Resumes animation if it was paused with @Element.pause method.
4898
     **
4899
     > Parameters
4900
     **
4901
     - anim (object) #optional animation object
4902
     **
4903
     = (object) original element
4904
    \*/
4905
    elproto.resume = function (anim) {
4906
        for (var i = 0; i < animationElements.length; i++) if (animationElements[i].el.id == this.id && (!anim || animationElements[i].anim == anim)) {
4907
            var e = animationElements[i];
4908
            if (eve("raphael.anim.resume." + this.id, this, e.anim) !== false) {
4909
                delete e.paused;
4910
                this.status(e.anim, e.status);
4911
            }
4912
        }
4913
        return this;
4914
    };
4915
    /*\
4916
     * Element.stop
4917
     [ method ]
4918
     **
4919
     * Stops animation of the element.
4920
     **
4921
     > Parameters
4922
     **
4923
     - anim (object) #optional animation object
4924
     **
4925
     = (object) original element
4926
    \*/
4927
    elproto.stop = function (anim) {
4928
        for (var i = 0; i < animationElements.length; i++) if (animationElements[i].el.id == this.id && (!anim || animationElements[i].anim == anim)) {
4929
            if (eve("raphael.anim.stop." + this.id, this, animationElements[i].anim) !== false) {
4930
                animationElements.splice(i--, 1);
4931
            }
4932
        }
4933
        return this;
4934
    };
4935
    function stopAnimation(paper) {
4936
        for (var i = 0; i < animationElements.length; i++) if (animationElements[i].el.paper == paper) {
4937
            animationElements.splice(i--, 1);
4938
        }
4939
    }
4940
    eve.on("raphael.remove", stopAnimation);
4941
    eve.on("raphael.clear", stopAnimation);
4942
    elproto.toString = function () {
4943
        return "Rapha\xebl\u2019s object";
4944
    };
4945

4946
    // Set
4947
    var Set = function (items) {
4948
        this.items = [];
4949
        this.length = 0;
4950
        this.type = "set";
4951
        if (items) {
4952
            for (var i = 0, ii = items.length; i < ii; i++) {
4953
                if (items[i] && (items[i].constructor == elproto.constructor || items[i].constructor == Set)) {
4954
                    this[this.items.length] = this.items[this.items.length] = items[i];
4955
                    this.length++;
4956
                }
4957
            }
4958
        }
4959
    },
4960
    setproto = Set.prototype;
4961
    /*\
4962
     * Set.push
4963
     [ method ]
4964
     **
4965
     * Adds each argument to the current set.
4966
     = (object) original element
4967
    \*/
4968
    setproto.push = function () {
4969
        var item,
4970
            len;
4971
        for (var i = 0, ii = arguments.length; i < ii; i++) {
4972
            item = arguments[i];
4973
            if (item && (item.constructor == elproto.constructor || item.constructor == Set)) {
4974
                len = this.items.length;
4975
                this[len] = this.items[len] = item;
4976
                this.length++;
4977
            }
4978
        }
4979
        return this;
4980
    };
4981
    /*\
4982
     * Set.pop
4983
     [ method ]
4984
     **
4985
     * Removes last element and returns it.
4986
     = (object) element
4987
    \*/
4988
    setproto.pop = function () {
4989
        this.length && delete this[this.length--];
4990
        return this.items.pop();
4991
    };
4992
    /*\
4993
     * Set.forEach
4994
     [ method ]
4995
     **
4996
     * Executes given function for each element in the set.
4997
     *
4998
     * If function returns `false` it will stop loop running.
4999
     **
5000
     > Parameters
5001
     **
5002
     - callback (function) function to run
5003
     - thisArg (object) context object for the callback
5004
     = (object) Set object
5005
    \*/
5006
    setproto.forEach = function (callback, thisArg) {
5007
        for (var i = 0, ii = this.items.length; i < ii; i++) {
5008
            if (callback.call(thisArg, this.items[i], i) === false) {
5009
                return this;
5010
            }
5011
        }
5012
        return this;
5013
    };
5014
    for (var method in elproto) if (elproto[has](method)) {
5015
        setproto[method] = (function (methodname) {
5016
            return function () {
5017
                var arg = arguments;
5018
                return this.forEach(function (el) {
5019
                    el[methodname][apply](el, arg);
5020
                });
5021
            };
5022
        })(method);
5023
    }
5024
    setproto.attr = function (name, value) {
5025
        if (name && R.is(name, array) && R.is(name[0], "object")) {
5026
            for (var j = 0, jj = name.length; j < jj; j++) {
5027
                this.items[j].attr(name[j]);
5028
            }
5029
        } else {
5030
            for (var i = 0, ii = this.items.length; i < ii; i++) {
5031
                this.items[i].attr(name, value);
5032
            }
5033
        }
5034
        return this;
5035
    };
5036
    /*\
5037
     * Set.clear
5038
     [ method ]
5039
     **
5040
     * Removes all elements from the set
5041
    \*/
5042
    setproto.clear = function () {
5043
        while (this.length) {
5044
            this.pop();
5045
        }
5046
    };
5047
    /*\
5048
     * Set.splice
5049
     [ method ]
5050
     **
5051
     * Removes given element from the set
5052
     **
5053
     > Parameters
5054
     **
5055
     - index (number) position of the deletion
5056
     - count (number) number of element to remove
5057
     - insertion… (object) #optional elements to insert
5058
     = (object) set elements that were deleted
5059
    \*/
5060
    setproto.splice = function (index, count, insertion) {
5061
        index = index < 0 ? mmax(this.length + index, 0) : index;
5062
        count = mmax(0, mmin(this.length - index, count));
5063
        var tail = [],
5064
            todel = [],
5065
            args = [],
5066
            i;
5067
        for (i = 2; i < arguments.length; i++) {
5068
            args.push(arguments[i]);
5069
        }
5070
        for (i = 0; i < count; i++) {
5071
            todel.push(this[index + i]);
5072
        }
5073
        for (; i < this.length - index; i++) {
5074
            tail.push(this[index + i]);
5075
        }
5076
        var arglen = args.length;
5077
        for (i = 0; i < arglen + tail.length; i++) {
5078
            this.items[index + i] = this[index + i] = i < arglen ? args[i] : tail[i - arglen];
5079
        }
5080
        i = this.items.length = this.length -= count - arglen;
5081
        while (this[i]) {
5082
            delete this[i++];
5083
        }
5084
        return new Set(todel);
5085
    };
5086
    /*\
5087
     * Set.exclude
5088
     [ method ]
5089
     **
5090
     * Removes given element from the set
5091
     **
5092
     > Parameters
5093
     **
5094
     - element (object) element to remove
5095
     = (boolean) `true` if object was found & removed from the set
5096
    \*/
5097
    setproto.exclude = function (el) {
5098
        for (var i = 0, ii = this.length; i < ii; i++) if (this[i] == el) {
5099
            this.splice(i, 1);
5100
            return true;
5101
        }
5102
    };
5103
    setproto.animate = function (params, ms, easing, callback) {
5104
        (R.is(easing, "function") || !easing) && (callback = easing || null);
5105
        var len = this.items.length,
5106
            i = len,
5107
            item,
5108
            set = this,
5109
            collector;
5110
        if (!len) {
5111
            return this;
5112
        }
5113
        callback && (collector = function () {
5114
            !--len && callback.call(set);
5115
        });
5116
        easing = R.is(easing, string) ? easing : collector;
5117
        var anim = R.animation(params, ms, easing, collector);
5118
        item = this.items[--i].animate(anim);
5119
        while (i--) {
5120
            this.items[i] && !this.items[i].removed && this.items[i].animateWith(item, anim, anim);
5121
            (this.items[i] && !this.items[i].removed) || len--;
5122
        }
5123
        return this;
5124
    };
5125
    setproto.insertAfter = function (el) {
5126
        var i = this.items.length;
5127
        while (i--) {
5128
            this.items[i].insertAfter(el);
5129
        }
5130
        return this;
5131
    };
5132
    setproto.getBBox = function () {
5133
        var x = [],
5134
            y = [],
5135
            x2 = [],
5136
            y2 = [];
5137
        for (var i = this.items.length; i--;) if (!this.items[i].removed) {
5138
            var box = this.items[i].getBBox();
5139
            x.push(box.x);
5140
            y.push(box.y);
5141
            x2.push(box.x + box.width);
5142
            y2.push(box.y + box.height);
5143
        }
5144
        x = mmin[apply](0, x);
5145
        y = mmin[apply](0, y);
5146
        x2 = mmax[apply](0, x2);
5147
        y2 = mmax[apply](0, y2);
5148
        return {
5149
            x: x,
5150
            y: y,
5151
            x2: x2,
5152
            y2: y2,
5153
            width: x2 - x,
5154
            height: y2 - y
5155
        };
5156
    };
5157
    setproto.clone = function (s) {
5158
        s = this.paper.set();
5159
        for (var i = 0, ii = this.items.length; i < ii; i++) {
5160
            s.push(this.items[i].clone());
5161
        }
5162
        return s;
5163
    };
5164
    setproto.toString = function () {
5165
        return "Rapha\xebl\u2018s set";
5166
    };
5167

5168
    setproto.glow = function(glowConfig) {
5169
        var ret = this.paper.set();
5170
        this.forEach(function(shape, index){
5171
            var g = shape.glow(glowConfig);
5172
            if(g != null){
5173
                g.forEach(function(shape2, index2){
5174
                    ret.push(shape2);
5175
                });
5176
            }
5177
        });
5178
        return ret;
5179
    };
5180

5181

5182
    /*\
5183
     * Set.isPointInside
5184
     [ method ]
5185
     **
5186
     * Determine if given point is inside this set’s elements
5187
     **
5188
     > Parameters
5189
     **
5190
     - x (number) x coordinate of the point
5191
     - y (number) y coordinate of the point
5192
     = (boolean) `true` if point is inside any of the set's elements
5193
     \*/
5194
    setproto.isPointInside = function (x, y) {
5195
        var isPointInside = false;
5196
        this.forEach(function (el) {
5197
            if (el.isPointInside(x, y)) {
5198
                isPointInside = true;
5199
                return false; // stop loop
5200
            }
5201
        });
5202
        return isPointInside;
5203
    };
5204

5205
    /*\
5206
     * Raphael.registerFont
5207
     [ method ]
5208
     **
5209
     * Adds given font to the registered set of fonts for Raphaël. Should be used as an internal call from within Cufón’s font file.
5210
     * Returns original parameter, so it could be used with chaining.
5211
     # <a href="http://wiki.github.com/sorccu/cufon/about">More about Cufón and how to convert your font form TTF, OTF, etc to JavaScript file.</a>
5212
     **
5213
     > Parameters
5214
     **
5215
     - font (object) the font to register
5216
     = (object) the font you passed in
5217
     > Usage
5218
     | Cufon.registerFont(Raphael.registerFont({…}));
5219
    \*/
5220
    R.registerFont = function (font) {
5221
        if (!font.face) {
5222
            return font;
5223
        }
5224
        this.fonts = this.fonts || {};
5225
        var fontcopy = {
5226
                w: font.w,
5227
                face: {},
5228
                glyphs: {}
5229
            },
5230
            family = font.face["font-family"];
5231
        for (var prop in font.face) if (font.face[has](prop)) {
5232
            fontcopy.face[prop] = font.face[prop];
5233
        }
5234
        if (this.fonts[family]) {
5235
            this.fonts[family].push(fontcopy);
5236
        } else {
5237
            this.fonts[family] = [fontcopy];
5238
        }
5239
        if (!font.svg) {
5240
            fontcopy.face["units-per-em"] = toInt(font.face["units-per-em"], 10);
5241
            for (var glyph in font.glyphs) if (font.glyphs[has](glyph)) {
5242
                var path = font.glyphs[glyph];
5243
                fontcopy.glyphs[glyph] = {
5244
                    w: path.w,
5245
                    k: {},
5246
                    d: path.d && "M" + path.d.replace(/[mlcxtrv]/g, function (command) {
5247
                            return {l: "L", c: "C", x: "z", t: "m", r: "l", v: "c"}[command] || "M";
5248
                        }) + "z"
5249
                };
5250
                if (path.k) {
5251
                    for (var k in path.k) if (path[has](k)) {
5252
                        fontcopy.glyphs[glyph].k[k] = path.k[k];
5253
                    }
5254
                }
5255
            }
5256
        }
5257
        return font;
5258
    };
5259
    /*\
5260
     * Paper.getFont
5261
     [ method ]
5262
     **
5263
     * Finds font object in the registered fonts by given parameters. You could specify only one word from the font name, like “Myriad” for “Myriad Pro”.
5264
     **
5265
     > Parameters
5266
     **
5267
     - family (string) font family name or any word from it
5268
     - weight (string) #optional font weight
5269
     - style (string) #optional font style
5270
     - stretch (string) #optional font stretch
5271
     = (object) the font object
5272
     > Usage
5273
     | paper.print(100, 100, "Test string", paper.getFont("Times", 800), 30);
5274
    \*/
5275
    paperproto.getFont = function (family, weight, style, stretch) {
5276
        stretch = stretch || "normal";
5277
        style = style || "normal";
5278
        weight = +weight || {normal: 400, bold: 700, lighter: 300, bolder: 800}[weight] || 400;
5279
        if (!R.fonts) {
5280
            return;
5281
        }
5282
        var font = R.fonts[family];
5283
        if (!font) {
5284
            var name = new RegExp("(^|\\s)" + family.replace(/[^\w\d\s+!~.:_-]/g, E) + "(\\s|$)", "i");
5285
            for (var fontName in R.fonts) if (R.fonts[has](fontName)) {
5286
                if (name.test(fontName)) {
5287
                    font = R.fonts[fontName];
5288
                    break;
5289
                }
5290
            }
5291
        }
5292
        var thefont;
5293
        if (font) {
5294
            for (var i = 0, ii = font.length; i < ii; i++) {
5295
                thefont = font[i];
5296
                if (thefont.face["font-weight"] == weight && (thefont.face["font-style"] == style || !thefont.face["font-style"]) && thefont.face["font-stretch"] == stretch) {
5297
                    break;
5298
                }
5299
            }
5300
        }
5301
        return thefont;
5302
    };
5303
    /*\
5304
     * Paper.print
5305
     [ method ]
5306
     **
5307
     * Creates path that represent given text written using given font at given position with given size.
5308
     * Result of the method is path element that contains whole text as a separate path.
5309
     **
5310
     > Parameters
5311
     **
5312
     - x (number) x position of the text
5313
     - y (number) y position of the text
5314
     - string (string) text to print
5315
     - font (object) font object, see @Paper.getFont
5316
     - size (number) #optional size of the font, default is `16`
5317
     - origin (string) #optional could be `"baseline"` or `"middle"`, default is `"middle"`
5318
     - letter_spacing (number) #optional number in range `-1..1`, default is `0`
5319
     - line_spacing (number) #optional number in range `1..3`, default is `1`
5320
     = (object) resulting path element, which consist of all letters
5321
     > Usage
5322
     | var txt = r.print(10, 50, "print", r.getFont("Museo"), 30).attr({fill: "#fff"});
5323
    \*/
5324
    paperproto.print = function (x, y, string, font, size, origin, letter_spacing, line_spacing) {
5325
        origin = origin || "middle"; // baseline|middle
5326
        letter_spacing = mmax(mmin(letter_spacing || 0, 1), -1);
5327
        line_spacing = mmax(mmin(line_spacing || 1, 3), 1);
5328
        var letters = Str(string)[split](E),
5329
            shift = 0,
5330
            notfirst = 0,
5331
            path = E,
5332
            scale;
5333
        R.is(font, "string") && (font = this.getFont(font));
5334
        if (font) {
5335
            scale = (size || 16) / font.face["units-per-em"];
5336
            var bb = font.face.bbox[split](separator),
5337
                top = +bb[0],
5338
                lineHeight = bb[3] - bb[1],
5339
                shifty = 0,
5340
                height = +bb[1] + (origin == "baseline" ? lineHeight + (+font.face.descent) : lineHeight / 2);
5341
            for (var i = 0, ii = letters.length; i < ii; i++) {
5342
                if (letters[i] == "\n") {
5343
                    shift = 0;
5344
                    curr = 0;
5345
                    notfirst = 0;
5346
                    shifty += lineHeight * line_spacing;
5347
                } else {
5348
                    var prev = notfirst && font.glyphs[letters[i - 1]] || {},
5349
                        curr = font.glyphs[letters[i]];
5350
                    shift += notfirst ? (prev.w || font.w) + (prev.k && prev.k[letters[i]] || 0) + (font.w * letter_spacing) : 0;
5351
                    notfirst = 1;
5352
                }
5353
                if (curr && curr.d) {
5354
                    path += R.transformPath(curr.d, ["t", shift * scale, shifty * scale, "s", scale, scale, top, height, "t", (x - top) / scale, (y - height) / scale]);
5355
                }
5356
            }
5357
        }
5358
        return this.path(path).attr({
5359
            fill: "#000",
5360
            stroke: "none"
5361
        });
5362
    };
5363

5364
    /*\
5365
     * Paper.add
5366
     [ method ]
5367
     **
5368
     * Imports elements in JSON array in format `{type: type, <attributes>}`
5369
     **
5370
     > Parameters
5371
     **
5372
     - json (array)
5373
     = (object) resulting set of imported elements
5374
     > Usage
5375
     | paper.add([
5376
     |     {
5377
     |         type: "circle",
5378
     |         cx: 10,
5379
     |         cy: 10,
5380
     |         r: 5
5381
     |     },
5382
     |     {
5383
     |         type: "rect",
5384
     |         x: 10,
5385
     |         y: 10,
5386
     |         width: 10,
5387
     |         height: 10,
5388
     |         fill: "#fc0"
5389
     |     }
5390
     | ]);
5391
    \*/
5392
    paperproto.add = function (json) {
5393
        if (R.is(json, "array")) {
5394
            var res = this.set(),
5395
                i = 0,
5396
                ii = json.length,
5397
                j;
5398
            for (; i < ii; i++) {
5399
                j = json[i] || {};
5400
                elements[has](j.type) && res.push(this[j.type]().attr(j));
5401
            }
5402
        }
5403
        return res;
5404
    };
5405

5406
    /*\
5407
     * Raphael.format
5408
     [ method ]
5409
     **
5410
     * Simple format function. Replaces construction of type “`{<number>}`” to the corresponding argument.
5411
     **
5412
     > Parameters
5413
     **
5414
     - token (string) string to format
5415
     - … (string) rest of arguments will be treated as parameters for replacement
5416
     = (string) formated string
5417
     > Usage
5418
     | var x = 10,
5419
     |     y = 20,
5420
     |     width = 40,
5421
     |     height = 50;
5422
     | // this will draw a rectangular shape equivalent to "M10,20h40v50h-40z"
5423
     | paper.path(Raphael.format("M{0},{1}h{2}v{3}h{4}z", x, y, width, height, -width));
5424
    \*/
5425
    R.format = function (token, params) {
5426
        var args = R.is(params, array) ? [0][concat](params) : arguments;
5427
        token && R.is(token, string) && args.length - 1 && (token = token.replace(formatrg, function (str, i) {
5428
            return args[++i] == null ? E : args[i];
5429
        }));
5430
        return token || E;
5431
    };
5432
    /*\
5433
     * Raphael.fullfill
5434
     [ method ]
5435
     **
5436
     * A little bit more advanced format function than @Raphael.format. Replaces construction of type “`{<name>}`” to the corresponding argument.
5437
     **
5438
     > Parameters
5439
     **
5440
     - token (string) string to format
5441
     - json (object) object which properties will be used as a replacement
5442
     = (string) formated string
5443
     > Usage
5444
     | // this will draw a rectangular shape equivalent to "M10,20h40v50h-40z"
5445
     | paper.path(Raphael.fullfill("M{x},{y}h{dim.width}v{dim.height}h{dim['negative width']}z", {
5446
     |     x: 10,
5447
     |     y: 20,
5448
     |     dim: {
5449
     |         width: 40,
5450
     |         height: 50,
5451
     |         "negative width": -40
5452
     |     }
5453
     | }));
5454
    \*/
5455
    R.fullfill = (function () {
5456
        var tokenRegex = /\{([^\}]+)\}/g,
5457
            objNotationRegex = /(?:(?:^|\.)(.+?)(?=\[|\.|$|\()|\[('|")(.+?)\2\])(\(\))?/g, // matches .xxxxx or ["xxxxx"] to run over object properties
5458
            replacer = function (all, key, obj) {
5459
                var res = obj;
5460
                key.replace(objNotationRegex, function (all, name, quote, quotedName, isFunc) {
5461
                    name = name || quotedName;
5462
                    if (res) {
5463
                        if (name in res) {
5464
                            res = res[name];
5465
                        }
5466
                        typeof res == "function" && isFunc && (res = res());
5467
                    }
5468
                });
5469
                res = (res == null || res == obj ? all : res) + "";
5470
                return res;
5471
            };
5472
        return function (str, obj) {
5473
            return String(str).replace(tokenRegex, function (all, key) {
5474
                return replacer(all, key, obj);
5475
            });
5476
        };
5477
    })();
5478
    /*\
5479
     * Raphael.ninja
5480
     [ method ]
5481
     **
5482
     * If you want to leave no trace of Raphaël (Well, Raphaël creates only one global variable `Raphael`, but anyway.) You can use `ninja` method.
5483
     * Beware, that in this case plugins could stop working, because they are depending on global variable existence.
5484
     **
5485
     = (object) Raphael object
5486
     > Usage
5487
     | (function (local_raphael) {
5488
     |     var paper = local_raphael(10, 10, 320, 200);
5489
     |     …
5490
     | })(Raphael.ninja());
5491
    \*/
5492
    R.ninja = function () {
5493
        if (oldRaphael.was) {
5494
            g.win.Raphael = oldRaphael.is;
5495
        } else {
5496
            // IE8 raises an error when deleting window property
5497
            window.Raphael = undefined;
5498
            try {
5499
                delete window.Raphael;
5500
            } catch(e) {}
5501
        }
5502
        return R;
5503
    };
5504
    /*\
5505
     * Raphael.st
5506
     [ property (object) ]
5507
     **
5508
     * You can add your own method to elements and sets. It is wise to add a set method for each element method
5509
     * you added, so you will be able to call the same method on sets too.
5510
     **
5511
     * See also @Raphael.el.
5512
     > Usage
5513
     | Raphael.el.red = function () {
5514
     |     this.attr({fill: "#f00"});
5515
     | };
5516
     | Raphael.st.red = function () {
5517
     |     this.forEach(function (el) {
5518
     |         el.red();
5519
     |     });
5520
     | };
5521
     | // then use it
5522
     | paper.set(paper.circle(100, 100, 20), paper.circle(110, 100, 20)).red();
5523
    \*/
5524
    R.st = setproto;
5525

5526
    eve.on("raphael.DOMload", function () {
5527
        loaded = true;
5528
    });
5529

5530
    // Firefox <3.6 fix: http://webreflection.blogspot.com/2009/11/195-chars-to-help-lazy-loading.html
5531
    (function (doc, loaded, f) {
5532
        if (doc.readyState == null && doc.addEventListener){
5533
            doc.addEventListener(loaded, f = function () {
5534
                doc.removeEventListener(loaded, f, false);
5535
                doc.readyState = "complete";
5536
            }, false);
5537
            doc.readyState = "loading";
5538
        }
5539
        function isLoaded() {
5540
            (/in/).test(doc.readyState) ? setTimeout(isLoaded, 9) : R.eve("raphael.DOMload");
5541
        }
5542
        isLoaded();
5543
    })(document, "DOMContentLoaded");
5544

5545
    return R;
5546
}).apply(exports, __WEBPACK_AMD_DEFINE_ARRAY__),
5547
				__WEBPACK_AMD_DEFINE_RESULT__ !== undefined && (module.exports = __WEBPACK_AMD_DEFINE_RESULT__));
5548

5549

5550
/***/ }),
5551

5552
/***/ "./dev/raphael.svg.js":
5553
/*!****************************!*\
5554
  !*** ./dev/raphael.svg.js ***!
5555
  \****************************/
5556
/*! no static exports found */
5557
/***/ (function(module, exports, __webpack_require__) {
5558

5559
var __WEBPACK_AMD_DEFINE_ARRAY__, __WEBPACK_AMD_DEFINE_RESULT__;!(__WEBPACK_AMD_DEFINE_ARRAY__ = [__webpack_require__(/*! ./raphael.core */ "./dev/raphael.core.js")], __WEBPACK_AMD_DEFINE_RESULT__ = (function(R) {
5560
    if (R && !R.svg) {
5561
        return;
5562
    }
5563

5564
    var has = "hasOwnProperty",
5565
        Str = String,
5566
        toFloat = parseFloat,
5567
        toInt = parseInt,
5568
        math = Math,
5569
        mmax = math.max,
5570
        abs = math.abs,
5571
        pow = math.pow,
5572
        separator = /[, ]+/,
5573
        eve = R.eve,
5574
        E = "",
5575
        S = " ";
5576
    var xlink = "http://www.w3.org/1999/xlink",
5577
        markers = {
5578
            block: "M5,0 0,2.5 5,5z",
5579
            classic: "M5,0 0,2.5 5,5 3.5,3 3.5,2z",
5580
            diamond: "M2.5,0 5,2.5 2.5,5 0,2.5z",
5581
            open: "M6,1 1,3.5 6,6",
5582
            oval: "M2.5,0A2.5,2.5,0,0,1,2.5,5 2.5,2.5,0,0,1,2.5,0z"
5583
        },
5584
        markerCounter = {};
5585
    R.toString = function () {
5586
        return  "Your browser supports SVG.\nYou are running Rapha\xebl " + this.version;
5587
    };
5588
    var $ = function (el, attr) {
5589
        if (attr) {
5590
            if (typeof el == "string") {
5591
                el = $(el);
5592
            }
5593
            for (var key in attr) if (attr[has](key)) {
5594
                if (key.substring(0, 6) == "xlink:") {
5595
                    el.setAttributeNS(xlink, key.substring(6), Str(attr[key]));
5596
                } else {
5597
                    el.setAttribute(key, Str(attr[key]));
5598
                }
5599
            }
5600
        } else {
5601
            el = R._g.doc.createElementNS("http://www.w3.org/2000/svg", el);
5602
            el.style && (el.style.webkitTapHighlightColor = "rgba(0,0,0,0)");
5603
        }
5604
        return el;
5605
    },
5606
    addGradientFill = function (element, gradient) {
5607
        var type = "linear",
5608
            id = element.id + gradient,
5609
            fx = .5, fy = .5,
5610
            o = element.node,
5611
            SVG = element.paper,
5612
            s = o.style,
5613
            el = R._g.doc.getElementById(id);
5614
        if (!el) {
5615
            gradient = Str(gradient).replace(R._radial_gradient, function (all, _fx, _fy) {
5616
                type = "radial";
5617
                if (_fx && _fy) {
5618
                    fx = toFloat(_fx);
5619
                    fy = toFloat(_fy);
5620
                    var dir = ((fy > .5) * 2 - 1);
5621
                    pow(fx - .5, 2) + pow(fy - .5, 2) > .25 &&
5622
                        (fy = math.sqrt(.25 - pow(fx - .5, 2)) * dir + .5) &&
5623
                        fy != .5 &&
5624
                        (fy = fy.toFixed(5) - 1e-5 * dir);
5625
                }
5626
                return E;
5627
            });
5628
            gradient = gradient.split(/\s*\-\s*/);
5629
            if (type == "linear") {
5630
                var angle = gradient.shift();
5631
                angle = -toFloat(angle);
5632
                if (isNaN(angle)) {
5633
                    return null;
5634
                }
5635
                var vector = [0, 0, math.cos(R.rad(angle)), math.sin(R.rad(angle))],
5636
                    max = 1 / (mmax(abs(vector[2]), abs(vector[3])) || 1);
5637
                vector[2] *= max;
5638
                vector[3] *= max;
5639
                if (vector[2] < 0) {
5640
                    vector[0] = -vector[2];
5641
                    vector[2] = 0;
5642
                }
5643
                if (vector[3] < 0) {
5644
                    vector[1] = -vector[3];
5645
                    vector[3] = 0;
5646
                }
5647
            }
5648
            var dots = R._parseDots(gradient);
5649
            if (!dots) {
5650
                return null;
5651
            }
5652
            id = id.replace(/[\(\)\s,\xb0#]/g, "_");
5653

5654
            if (element.gradient && id != element.gradient.id) {
5655
                SVG.defs.removeChild(element.gradient);
5656
                delete element.gradient;
5657
            }
5658

5659
            if (!element.gradient) {
5660
                el = $(type + "Gradient", {id: id});
5661
                element.gradient = el;
5662
                $(el, type == "radial" ? {
5663
                    fx: fx,
5664
                    fy: fy
5665
                } : {
5666
                    x1: vector[0],
5667
                    y1: vector[1],
5668
                    x2: vector[2],
5669
                    y2: vector[3],
5670
                    gradientTransform: element.matrix.invert()
5671
                });
5672
                SVG.defs.appendChild(el);
5673
                for (var i = 0, ii = dots.length; i < ii; i++) {
5674
                    el.appendChild($("stop", {
5675
                        offset: dots[i].offset ? dots[i].offset : i ? "100%" : "0%",
5676
                        "stop-color": dots[i].color || "#fff",
5677
                        "stop-opacity": isFinite(dots[i].opacity) ? dots[i].opacity : 1
5678
                    }));
5679
                }
5680
            }
5681
        }
5682
        $(o, {
5683
            fill: fillurl(id),
5684
            opacity: 1,
5685
            "fill-opacity": 1
5686
        });
5687
        s.fill = E;
5688
        s.opacity = 1;
5689
        s.fillOpacity = 1;
5690
        return 1;
5691
    },
5692
    isIE9or10 = function () {
5693
      var mode = document.documentMode;
5694
      return mode && (mode === 9 || mode === 10);
5695
    },
5696
    fillurl = function (id) {
5697
      if (isIE9or10()) {
5698
          return "url('#" + id + "')";
5699
      }
5700
      var location = document.location;
5701
      var locationString = (
5702
          location.protocol + '//' +
5703
          location.host +
5704
          location.pathname +
5705
          location.search
5706
      );
5707
      return "url('" + locationString + "#" + id + "')";
5708
    },
5709
    updatePosition = function (o) {
5710
        var bbox = o.getBBox(1);
5711
        $(o.pattern, {patternTransform: o.matrix.invert() + " translate(" + bbox.x + "," + bbox.y + ")"});
5712
    },
5713
    addArrow = function (o, value, isEnd) {
5714
        if (o.type == "path") {
5715
            var values = Str(value).toLowerCase().split("-"),
5716
                p = o.paper,
5717
                se = isEnd ? "end" : "start",
5718
                node = o.node,
5719
                attrs = o.attrs,
5720
                stroke = attrs["stroke-width"],
5721
                i = values.length,
5722
                type = "classic",
5723
                from,
5724
                to,
5725
                dx,
5726
                refX,
5727
                attr,
5728
                w = 3,
5729
                h = 3,
5730
                t = 5;
5731
            while (i--) {
5732
                switch (values[i]) {
5733
                    case "block":
5734
                    case "classic":
5735
                    case "oval":
5736
                    case "diamond":
5737
                    case "open":
5738
                    case "none":
5739
                        type = values[i];
5740
                        break;
5741
                    case "wide": h = 5; break;
5742
                    case "narrow": h = 2; break;
5743
                    case "long": w = 5; break;
5744
                    case "short": w = 2; break;
5745
                }
5746
            }
5747
            if (type == "open") {
5748
                w += 2;
5749
                h += 2;
5750
                t += 2;
5751
                dx = 1;
5752
                refX = isEnd ? 4 : 1;
5753
                attr = {
5754
                    fill: "none",
5755
                    stroke: attrs.stroke
5756
                };
5757
            } else {
5758
                refX = dx = w / 2;
5759
                attr = {
5760
                    fill: attrs.stroke,
5761
                    stroke: "none"
5762
                };
5763
            }
5764
            if (o._.arrows) {
5765
                if (isEnd) {
5766
                    o._.arrows.endPath && markerCounter[o._.arrows.endPath]--;
5767
                    o._.arrows.endMarker && markerCounter[o._.arrows.endMarker]--;
5768
                } else {
5769
                    o._.arrows.startPath && markerCounter[o._.arrows.startPath]--;
5770
                    o._.arrows.startMarker && markerCounter[o._.arrows.startMarker]--;
5771
                }
5772
            } else {
5773
                o._.arrows = {};
5774
            }
5775
            if (type != "none") {
5776
                var pathId = "raphael-marker-" + type,
5777
                    markerId = "raphael-marker-" + se + type + w + h + "-obj" + o.id;
5778
                if (!R._g.doc.getElementById(pathId)) {
5779
                    p.defs.appendChild($($("path"), {
5780
                        "stroke-linecap": "round",
5781
                        d: markers[type],
5782
                        id: pathId
5783
                    }));
5784
                    markerCounter[pathId] = 1;
5785
                } else {
5786
                    markerCounter[pathId]++;
5787
                }
5788
                var marker = R._g.doc.getElementById(markerId),
5789
                    use;
5790
                if (!marker) {
5791
                    marker = $($("marker"), {
5792
                        id: markerId,
5793
                        markerHeight: h,
5794
                        markerWidth: w,
5795
                        orient: "auto",
5796
                        refX: refX,
5797
                        refY: h / 2
5798
                    });
5799
                    use = $($("use"), {
5800
                        "xlink:href": "#" + pathId,
5801
                        transform: (isEnd ? "rotate(180 " + w / 2 + " " + h / 2 + ") " : E) + "scale(" + w / t + "," + h / t + ")",
5802
                        "stroke-width": (1 / ((w / t + h / t) / 2)).toFixed(4)
5803
                    });
5804
                    marker.appendChild(use);
5805
                    p.defs.appendChild(marker);
5806
                    markerCounter[markerId] = 1;
5807
                } else {
5808
                    markerCounter[markerId]++;
5809
                    use = marker.getElementsByTagName("use")[0];
5810
                }
5811
                $(use, attr);
5812
                var delta = dx * (type != "diamond" && type != "oval");
5813
                if (isEnd) {
5814
                    from = o._.arrows.startdx * stroke || 0;
5815
                    to = R.getTotalLength(attrs.path) - delta * stroke;
5816
                } else {
5817
                    from = delta * stroke;
5818
                    to = R.getTotalLength(attrs.path) - (o._.arrows.enddx * stroke || 0);
5819
                }
5820
                attr = {};
5821
                attr["marker-" + se] = "url(#" + markerId + ")";
5822
                if (to || from) {
5823
                    attr.d = R.getSubpath(attrs.path, from, to);
5824
                }
5825
                $(node, attr);
5826
                o._.arrows[se + "Path"] = pathId;
5827
                o._.arrows[se + "Marker"] = markerId;
5828
                o._.arrows[se + "dx"] = delta;
5829
                o._.arrows[se + "Type"] = type;
5830
                o._.arrows[se + "String"] = value;
5831
            } else {
5832
                if (isEnd) {
5833
                    from = o._.arrows.startdx * stroke || 0;
5834
                    to = R.getTotalLength(attrs.path) - from;
5835
                } else {
5836
                    from = 0;
5837
                    to = R.getTotalLength(attrs.path) - (o._.arrows.enddx * stroke || 0);
5838
                }
5839
                o._.arrows[se + "Path"] && $(node, {d: R.getSubpath(attrs.path, from, to)});
5840
                delete o._.arrows[se + "Path"];
5841
                delete o._.arrows[se + "Marker"];
5842
                delete o._.arrows[se + "dx"];
5843
                delete o._.arrows[se + "Type"];
5844
                delete o._.arrows[se + "String"];
5845
            }
5846
            for (attr in markerCounter) if (markerCounter[has](attr) && !markerCounter[attr]) {
5847
                var item = R._g.doc.getElementById(attr);
5848
                item && item.parentNode.removeChild(item);
5849
            }
5850
        }
5851
    },
5852
    dasharray = {
5853
        "-": [3, 1],
5854
        ".": [1, 1],
5855
        "-.": [3, 1, 1, 1],
5856
        "-..": [3, 1, 1, 1, 1, 1],
5857
        ". ": [1, 3],
5858
        "- ": [4, 3],
5859
        "--": [8, 3],
5860
        "- .": [4, 3, 1, 3],
5861
        "--.": [8, 3, 1, 3],
5862
        "--..": [8, 3, 1, 3, 1, 3]
5863
    },
5864
    addDashes = function (o, value, params) {
5865
        value = dasharray[Str(value).toLowerCase()];
5866
        if (value) {
5867
            var width = o.attrs["stroke-width"] || "1",
5868
                butt = {round: width, square: width, butt: 0}[o.attrs["stroke-linecap"] || params["stroke-linecap"]] || 0,
5869
                dashes = [],
5870
                i = value.length;
5871
            while (i--) {
5872
                dashes[i] = value[i] * width + ((i % 2) ? 1 : -1) * butt;
5873
            }
5874
            $(o.node, {"stroke-dasharray": dashes.join(",")});
5875
        }
5876
        else {
5877
          $(o.node, {"stroke-dasharray": "none"});
5878
        }
5879
    },
5880
    setFillAndStroke = function (o, params) {
5881
        var node = o.node,
5882
            attrs = o.attrs,
5883
            vis = node.style.visibility;
5884
        node.style.visibility = "hidden";
5885
        for (var att in params) {
5886
            if (params[has](att)) {
5887
                if (!R._availableAttrs[has](att)) {
5888
                    continue;
5889
                }
5890
                var value = params[att];
5891
                attrs[att] = value;
5892
                switch (att) {
5893
                    case "blur":
5894
                        o.blur(value);
5895
                        break;
5896
                    case "title":
5897
                        var title = node.getElementsByTagName("title");
5898

5899
                        // Use the existing <title>.
5900
                        if (title.length && (title = title[0])) {
5901
                          title.firstChild.nodeValue = value;
5902
                        } else {
5903
                          title = $("title");
5904
                          var val = R._g.doc.createTextNode(value);
5905
                          title.appendChild(val);
5906
                          node.appendChild(title);
5907
                        }
5908
                        break;
5909
                    case "href":
5910
                    case "target":
5911
                        var pn = node.parentNode;
5912
                        if (pn.tagName.toLowerCase() != "a") {
5913
                            var hl = $("a");
5914
                            pn.insertBefore(hl, node);
5915
                            hl.appendChild(node);
5916
                            pn = hl;
5917
                        }
5918
                        if (att == "target") {
5919
                            pn.setAttributeNS(xlink, "show", value == "blank" ? "new" : value);
5920
                        } else {
5921
                            pn.setAttributeNS(xlink, att, value);
5922
                        }
5923
                        break;
5924
                    case "cursor":
5925
                        node.style.cursor = value;
5926
                        break;
5927
                    case "transform":
5928
                        o.transform(value);
5929
                        break;
5930
                    case "arrow-start":
5931
                        addArrow(o, value);
5932
                        break;
5933
                    case "arrow-end":
5934
                        addArrow(o, value, 1);
5935
                        break;
5936
                    case "clip-rect":
5937
                        var rect = Str(value).split(separator);
5938
                        if (rect.length == 4) {
5939
                            o.clip && o.clip.parentNode.parentNode.removeChild(o.clip.parentNode);
5940
                            var el = $("clipPath"),
5941
                                rc = $("rect");
5942
                            el.id = R.createUUID();
5943
                            $(rc, {
5944
                                x: rect[0],
5945
                                y: rect[1],
5946
                                width: rect[2],
5947
                                height: rect[3]
5948
                            });
5949
                            el.appendChild(rc);
5950
                            o.paper.defs.appendChild(el);
5951
                            $(node, {"clip-path": "url(#" + el.id + ")"});
5952
                            o.clip = rc;
5953
                        }
5954
                        if (!value) {
5955
                            var path = node.getAttribute("clip-path");
5956
                            if (path) {
5957
                                var clip = R._g.doc.getElementById(path.replace(/(^url\(#|\)$)/g, E));
5958
                                clip && clip.parentNode.removeChild(clip);
5959
                                $(node, {"clip-path": E});
5960
                                delete o.clip;
5961
                            }
5962
                        }
5963
                    break;
5964
                    case "path":
5965
                        if (o.type == "path") {
5966
                            $(node, {d: value ? attrs.path = R._pathToAbsolute(value) : "M0,0"});
5967
                            o._.dirty = 1;
5968
                            if (o._.arrows) {
5969
                                "startString" in o._.arrows && addArrow(o, o._.arrows.startString);
5970
                                "endString" in o._.arrows && addArrow(o, o._.arrows.endString, 1);
5971
                            }
5972
                        }
5973
                        break;
5974
                    case "width":
5975
                        node.setAttribute(att, value);
5976
                        o._.dirty = 1;
5977
                        if (attrs.fx) {
5978
                            att = "x";
5979
                            value = attrs.x;
5980
                        } else {
5981
                            break;
5982
                        }
5983
                    case "x":
5984
                        if (attrs.fx) {
5985
                            value = -attrs.x - (attrs.width || 0);
5986
                        }
5987
                    case "rx":
5988
                        if (att == "rx" && o.type == "rect") {
5989
                            break;
5990
                        }
5991
                    case "cx":
5992
                        node.setAttribute(att, value);
5993
                        o.pattern && updatePosition(o);
5994
                        o._.dirty = 1;
5995
                        break;
5996
                    case "height":
5997
                        node.setAttribute(att, value);
5998
                        o._.dirty = 1;
5999
                        if (attrs.fy) {
6000
                            att = "y";
6001
                            value = attrs.y;
6002
                        } else {
6003
                            break;
6004
                        }
6005
                    case "y":
6006
                        if (attrs.fy) {
6007
                            value = -attrs.y - (attrs.height || 0);
6008
                        }
6009
                    case "ry":
6010
                        if (att == "ry" && o.type == "rect") {
6011
                            break;
6012
                        }
6013
                    case "cy":
6014
                        node.setAttribute(att, value);
6015
                        o.pattern && updatePosition(o);
6016
                        o._.dirty = 1;
6017
                        break;
6018
                    case "r":
6019
                        if (o.type == "rect") {
6020
                            $(node, {rx: value, ry: value});
6021
                        } else {
6022
                            node.setAttribute(att, value);
6023
                        }
6024
                        o._.dirty = 1;
6025
                        break;
6026
                    case "src":
6027
                        if (o.type == "image") {
6028
                            node.setAttributeNS(xlink, "href", value);
6029
                        }
6030
                        break;
6031
                    case "stroke-width":
6032
                        if (o._.sx != 1 || o._.sy != 1) {
6033
                            value /= mmax(abs(o._.sx), abs(o._.sy)) || 1;
6034
                        }
6035
                        node.setAttribute(att, value);
6036
                        if (attrs["stroke-dasharray"]) {
6037
                            addDashes(o, attrs["stroke-dasharray"], params);
6038
                        }
6039
                        if (o._.arrows) {
6040
                            "startString" in o._.arrows && addArrow(o, o._.arrows.startString);
6041
                            "endString" in o._.arrows && addArrow(o, o._.arrows.endString, 1);
6042
                        }
6043
                        break;
6044
                    case "stroke-dasharray":
6045
                        addDashes(o, value, params);
6046
                        break;
6047
                    case "fill":
6048
                        var isURL = Str(value).match(R._ISURL);
6049
                        if (isURL) {
6050
                            el = $("pattern");
6051
                            var ig = $("image");
6052
                            el.id = R.createUUID();
6053
                            $(el, {x: 0, y: 0, patternUnits: "userSpaceOnUse", height: 1, width: 1});
6054
                            $(ig, {x: 0, y: 0, "xlink:href": isURL[1]});
6055
                            el.appendChild(ig);
6056

6057
                            (function (el) {
6058
                                R._preload(isURL[1], function () {
6059
                                    var w = this.offsetWidth,
6060
                                        h = this.offsetHeight;
6061
                                    $(el, {width: w, height: h});
6062
                                    $(ig, {width: w, height: h});
6063
                                });
6064
                            })(el);
6065
                            o.paper.defs.appendChild(el);
6066
                            $(node, {fill: "url(#" + el.id + ")"});
6067
                            o.pattern = el;
6068
                            o.pattern && updatePosition(o);
6069
                            break;
6070
                        }
6071
                        var clr = R.getRGB(value);
6072
                        if (!clr.error) {
6073
                            delete params.gradient;
6074
                            delete attrs.gradient;
6075
                            !R.is(attrs.opacity, "undefined") &&
6076
                                R.is(params.opacity, "undefined") &&
6077
                                $(node, {opacity: attrs.opacity});
6078
                            !R.is(attrs["fill-opacity"], "undefined") &&
6079
                                R.is(params["fill-opacity"], "undefined") &&
6080
                                $(node, {"fill-opacity": attrs["fill-opacity"]});
6081
                        } else if ((o.type == "circle" || o.type == "ellipse" || Str(value).charAt() != "r") && addGradientFill(o, value)) {
6082
                            if ("opacity" in attrs || "fill-opacity" in attrs) {
6083
                                var gradient = R._g.doc.getElementById(node.getAttribute("fill").replace(/^url\(#|\)$/g, E));
6084
                                if (gradient) {
6085
                                    var stops = gradient.getElementsByTagName("stop");
6086
                                    $(stops[stops.length - 1], {"stop-opacity": ("opacity" in attrs ? attrs.opacity : 1) * ("fill-opacity" in attrs ? attrs["fill-opacity"] : 1)});
6087
                                }
6088
                            }
6089
                            attrs.gradient = value;
6090
                            attrs.fill = "none";
6091
                            break;
6092
                        }
6093
                        clr[has]("opacity") && $(node, {"fill-opacity": clr.opacity > 1 ? clr.opacity / 100 : clr.opacity});
6094
                    case "stroke":
6095
                        clr = R.getRGB(value);
6096
                        node.setAttribute(att, clr.hex);
6097
                        att == "stroke" && clr[has]("opacity") && $(node, {"stroke-opacity": clr.opacity > 1 ? clr.opacity / 100 : clr.opacity});
6098
                        if (att == "stroke" && o._.arrows) {
6099
                            "startString" in o._.arrows && addArrow(o, o._.arrows.startString);
6100
                            "endString" in o._.arrows && addArrow(o, o._.arrows.endString, 1);
6101
                        }
6102
                        break;
6103
                    case "gradient":
6104
                        (o.type == "circle" || o.type == "ellipse" || Str(value).charAt() != "r") && addGradientFill(o, value);
6105
                        break;
6106
                    case "opacity":
6107
                        if (attrs.gradient && !attrs[has]("stroke-opacity")) {
6108
                            $(node, {"stroke-opacity": value > 1 ? value / 100 : value});
6109
                        }
6110
                        // fall
6111
                    case "fill-opacity":
6112
                        if (attrs.gradient) {
6113
                            gradient = R._g.doc.getElementById(node.getAttribute("fill").replace(/^url\(#|\)$/g, E));
6114
                            if (gradient) {
6115
                                stops = gradient.getElementsByTagName("stop");
6116
                                $(stops[stops.length - 1], {"stop-opacity": value});
6117
                            }
6118
                            break;
6119
                        }
6120
                    default:
6121
                        att == "font-size" && (value = toInt(value, 10) + "px");
6122
                        var cssrule = att.replace(/(\-.)/g, function (w) {
6123
                            return w.substring(1).toUpperCase();
6124
                        });
6125
                        node.style[cssrule] = value;
6126
                        o._.dirty = 1;
6127
                        node.setAttribute(att, value);
6128
                        break;
6129
                }
6130
            }
6131
        }
6132

6133
        tuneText(o, params);
6134
        node.style.visibility = vis;
6135
    },
6136
    leading = 1.2,
6137
    tuneText = function (el, params) {
6138
        if (el.type != "text" || !(params[has]("text") || params[has]("font") || params[has]("font-size") || params[has]("x") || params[has]("y"))) {
6139
            return;
6140
        }
6141
        var a = el.attrs,
6142
            node = el.node,
6143
            fontSize = node.firstChild ? toInt(R._g.doc.defaultView.getComputedStyle(node.firstChild, E).getPropertyValue("font-size"), 10) : 10;
6144

6145
        if (params[has]("text")) {
6146
            a.text = params.text;
6147
            while (node.firstChild) {
6148
                node.removeChild(node.firstChild);
6149
            }
6150
            var texts = Str(params.text).split("\n"),
6151
                tspans = [],
6152
                tspan;
6153
            for (var i = 0, ii = texts.length; i < ii; i++) {
6154
                tspan = $("tspan");
6155
                i && $(tspan, {dy: fontSize * leading, x: a.x});
6156
                tspan.appendChild(R._g.doc.createTextNode(texts[i]));
6157
                node.appendChild(tspan);
6158
                tspans[i] = tspan;
6159
            }
6160
        } else {
6161
            tspans = node.getElementsByTagName("tspan");
6162
            for (i = 0, ii = tspans.length; i < ii; i++) if (i) {
6163
                $(tspans[i], {dy: fontSize * leading, x: a.x});
6164
            } else {
6165
                $(tspans[0], {dy: 0});
6166
            }
6167
        }
6168
        $(node, {x: a.x, y: a.y});
6169
        el._.dirty = 1;
6170
        var bb = el._getBBox(),
6171
            dif = a.y - (bb.y + bb.height / 2);
6172
        dif && R.is(dif, "finite") && $(tspans[0], {dy: dif});
6173
    },
6174
    getRealNode = function (node) {
6175
        if (node.parentNode && node.parentNode.tagName.toLowerCase() === "a") {
6176
            return node.parentNode;
6177
        } else {
6178
            return node;
6179
        }
6180
    },
6181
    Element = function (node, svg) {
6182
        var X = 0,
6183
            Y = 0;
6184
        /*\
6185
         * Element.node
6186
         [ property (object) ]
6187
         **
6188
         * Gives you a reference to the DOM object, so you can assign event handlers or just mess around.
6189
         **
6190
         * Note: Don’t mess with it.
6191
         > Usage
6192
         | // draw a circle at coordinate 10,10 with radius of 10
6193
         | var c = paper.circle(10, 10, 10);
6194
         | c.node.onclick = function () {
6195
         |     c.attr("fill", "red");
6196
         | };
6197
        \*/
6198
        this[0] = this.node = node;
6199
        /*\
6200
         * Element.raphael
6201
         [ property (object) ]
6202
         **
6203
         * Internal reference to @Raphael object. In case it is not available.
6204
         > Usage
6205
         | Raphael.el.red = function () {
6206
         |     var hsb = this.paper.raphael.rgb2hsb(this.attr("fill"));
6207
         |     hsb.h = 1;
6208
         |     this.attr({fill: this.paper.raphael.hsb2rgb(hsb).hex});
6209
         | }
6210
        \*/
6211
        node.raphael = true;
6212
        /*\
6213
         * Element.id
6214
         [ property (number) ]
6215
         **
6216
         * Unique id of the element. Especially useful when you want to listen to events of the element,
6217
         * because all events are fired in format `<module>.<action>.<id>`. Also useful for @Paper.getById method.
6218
        \*/
6219
        this.id = guid();
6220
        node.raphaelid = this.id;
6221

6222
        /**
6223
        * Method that returns a 5 letter/digit id, enough for 36^5 = 60466176 elements
6224
        * @returns {string} id
6225
        */
6226
        function guid() {
6227
            return ("0000" + (Math.random()*Math.pow(36,5) << 0).toString(36)).slice(-5);
6228
        }
6229

6230
        this.matrix = R.matrix();
6231
        this.realPath = null;
6232
        /*\
6233
         * Element.paper
6234
         [ property (object) ]
6235
         **
6236
         * Internal reference to “paper” where object drawn. Mainly for use in plugins and element extensions.
6237
         > Usage
6238
         | Raphael.el.cross = function () {
6239
         |     this.attr({fill: "red"});
6240
         |     this.paper.path("M10,10L50,50M50,10L10,50")
6241
         |         .attr({stroke: "red"});
6242
         | }
6243
        \*/
6244
        this.paper = svg;
6245
        this.attrs = this.attrs || {};
6246
        this._ = {
6247
            transform: [],
6248
            sx: 1,
6249
            sy: 1,
6250
            deg: 0,
6251
            dx: 0,
6252
            dy: 0,
6253
            dirty: 1
6254
        };
6255
        !svg.bottom && (svg.bottom = this);
6256
        /*\
6257
         * Element.prev
6258
         [ property (object) ]
6259
         **
6260
         * Reference to the previous element in the hierarchy.
6261
        \*/
6262
        this.prev = svg.top;
6263
        svg.top && (svg.top.next = this);
6264
        svg.top = this;
6265
        /*\
6266
         * Element.next
6267
         [ property (object) ]
6268
         **
6269
         * Reference to the next element in the hierarchy.
6270
        \*/
6271
        this.next = null;
6272
    },
6273
    elproto = R.el;
6274

6275
    Element.prototype = elproto;
6276
    elproto.constructor = Element;
6277

6278
    R._engine.path = function (pathString, SVG) {
6279
        var el = $("path");
6280
        SVG.canvas && SVG.canvas.appendChild(el);
6281
        var p = new Element(el, SVG);
6282
        p.type = "path";
6283
        setFillAndStroke(p, {
6284
            fill: "none",
6285
            stroke: "#000",
6286
            path: pathString
6287
        });
6288
        return p;
6289
    };
6290
    /*\
6291
     * Element.rotate
6292
     [ method ]
6293
     **
6294
     * Deprecated! Use @Element.transform instead.
6295
     * Adds rotation by given angle around given point to the list of
6296
     * transformations of the element.
6297
     > Parameters
6298
     - deg (number) angle in degrees
6299
     - cx (number) #optional x coordinate of the centre of rotation
6300
     - cy (number) #optional y coordinate of the centre of rotation
6301
     * If cx & cy aren’t specified centre of the shape is used as a point of rotation.
6302
     = (object) @Element
6303
    \*/
6304
    elproto.rotate = function (deg, cx, cy) {
6305
        if (this.removed) {
6306
            return this;
6307
        }
6308
        deg = Str(deg).split(separator);
6309
        if (deg.length - 1) {
6310
            cx = toFloat(deg[1]);
6311
            cy = toFloat(deg[2]);
6312
        }
6313
        deg = toFloat(deg[0]);
6314
        (cy == null) && (cx = cy);
6315
        if (cx == null || cy == null) {
6316
            var bbox = this.getBBox(1);
6317
            cx = bbox.x + bbox.width / 2;
6318
            cy = bbox.y + bbox.height / 2;
6319
        }
6320
        this.transform(this._.transform.concat([["r", deg, cx, cy]]));
6321
        return this;
6322
    };
6323
    /*\
6324
     * Element.scale
6325
     [ method ]
6326
     **
6327
     * Deprecated! Use @Element.transform instead.
6328
     * Adds scale by given amount relative to given point to the list of
6329
     * transformations of the element.
6330
     > Parameters
6331
     - sx (number) horisontal scale amount
6332
     - sy (number) vertical scale amount
6333
     - cx (number) #optional x coordinate of the centre of scale
6334
     - cy (number) #optional y coordinate of the centre of scale
6335
     * If cx & cy aren’t specified centre of the shape is used instead.
6336
     = (object) @Element
6337
    \*/
6338
    elproto.scale = function (sx, sy, cx, cy) {
6339
        if (this.removed) {
6340
            return this;
6341
        }
6342
        sx = Str(sx).split(separator);
6343
        if (sx.length - 1) {
6344
            sy = toFloat(sx[1]);
6345
            cx = toFloat(sx[2]);
6346
            cy = toFloat(sx[3]);
6347
        }
6348
        sx = toFloat(sx[0]);
6349
        (sy == null) && (sy = sx);
6350
        (cy == null) && (cx = cy);
6351
        if (cx == null || cy == null) {
6352
            var bbox = this.getBBox(1);
6353
        }
6354
        cx = cx == null ? bbox.x + bbox.width / 2 : cx;
6355
        cy = cy == null ? bbox.y + bbox.height / 2 : cy;
6356
        this.transform(this._.transform.concat([["s", sx, sy, cx, cy]]));
6357
        return this;
6358
    };
6359
    /*\
6360
     * Element.translate
6361
     [ method ]
6362
     **
6363
     * Deprecated! Use @Element.transform instead.
6364
     * Adds translation by given amount to the list of transformations of the element.
6365
     > Parameters
6366
     - dx (number) horisontal shift
6367
     - dy (number) vertical shift
6368
     = (object) @Element
6369
    \*/
6370
    elproto.translate = function (dx, dy) {
6371
        if (this.removed) {
6372
            return this;
6373
        }
6374
        dx = Str(dx).split(separator);
6375
        if (dx.length - 1) {
6376
            dy = toFloat(dx[1]);
6377
        }
6378
        dx = toFloat(dx[0]) || 0;
6379
        dy = +dy || 0;
6380
        this.transform(this._.transform.concat([["t", dx, dy]]));
6381
        return this;
6382
    };
6383
    /*\
6384
     * Element.transform
6385
     [ method ]
6386
     **
6387
     * Adds transformation to the element which is separate to other attributes,
6388
     * i.e. translation doesn’t change `x` or `y` of the rectange. The format
6389
     * of transformation string is similar to the path string syntax:
6390
     | "t100,100r30,100,100s2,2,100,100r45s1.5"
6391
     * Each letter is a command. There are four commands: `t` is for translate, `r` is for rotate, `s` is for
6392
     * scale and `m` is for matrix.
6393
     *
6394
     * There are also alternative “absolute” translation, rotation and scale: `T`, `R` and `S`. They will not take previous transformation into account. For example, `...T100,0` will always move element 100 px horisontally, while `...t100,0` could move it vertically if there is `r90` before. Just compare results of `r90t100,0` and `r90T100,0`.
6395
     *
6396
     * So, the example line above could be read like “translate by 100, 100; rotate 30° around 100, 100; scale twice around 100, 100;
6397
     * rotate 45° around centre; scale 1.5 times relative to centre”. As you can see rotate and scale commands have origin
6398
     * coordinates as optional parameters, the default is the centre point of the element.
6399
     * Matrix accepts six parameters.
6400
     > Usage
6401
     | var el = paper.rect(10, 20, 300, 200);
6402
     | // translate 100, 100, rotate 45°, translate -100, 0
6403
     | el.transform("t100,100r45t-100,0");
6404
     | // if you want you can append or prepend transformations
6405
     | el.transform("...t50,50");
6406
     | el.transform("s2...");
6407
     | // or even wrap
6408
     | el.transform("t50,50...t-50-50");
6409
     | // to reset transformation call method with empty string
6410
     | el.transform("");
6411
     | // to get current value call it without parameters
6412
     | console.log(el.transform());
6413
     > Parameters
6414
     - tstr (string) #optional transformation string
6415
     * If tstr isn’t specified
6416
     = (string) current transformation string
6417
     * else
6418
     = (object) @Element
6419
    \*/
6420
    elproto.transform = function (tstr) {
6421
        var _ = this._;
6422
        if (tstr == null) {
6423
            return _.transform;
6424
        }
6425
        R._extractTransform(this, tstr);
6426

6427
        this.clip && $(this.clip, {transform: this.matrix.invert()});
6428
        this.pattern && updatePosition(this);
6429
        this.node && $(this.node, {transform: this.matrix});
6430

6431
        if (_.sx != 1 || _.sy != 1) {
6432
            var sw = this.attrs[has]("stroke-width") ? this.attrs["stroke-width"] : 1;
6433
            this.attr({"stroke-width": sw});
6434
        }
6435

6436
        return this;
6437
    };
6438
    /*\
6439
     * Element.hide
6440
     [ method ]
6441
     **
6442
     * Makes element invisible. See @Element.show.
6443
     = (object) @Element
6444
    \*/
6445
    elproto.hide = function () {
6446
        if(!this.removed) this.node.style.display = "none";
6447
        return this;
6448
    };
6449
    /*\
6450
     * Element.show
6451
     [ method ]
6452
     **
6453
     * Makes element visible. See @Element.hide.
6454
     = (object) @Element
6455
    \*/
6456
    elproto.show = function () {
6457
        if(!this.removed) this.node.style.display = "";
6458
        return this;
6459
    };
6460
    /*\
6461
     * Element.remove
6462
     [ method ]
6463
     **
6464
     * Removes element from the paper.
6465
    \*/
6466
    elproto.remove = function () {
6467
        var node = getRealNode(this.node);
6468
        if (this.removed || !node.parentNode) {
6469
            return;
6470
        }
6471
        var paper = this.paper;
6472
        paper.__set__ && paper.__set__.exclude(this);
6473
        eve.unbind("raphael.*.*." + this.id);
6474
        if (this.gradient) {
6475
            paper.defs.removeChild(this.gradient);
6476
        }
6477
        R._tear(this, paper);
6478

6479
        node.parentNode.removeChild(node);
6480

6481
        // Remove custom data for element
6482
        this.removeData();
6483

6484
        for (var i in this) {
6485
            this[i] = typeof this[i] == "function" ? R._removedFactory(i) : null;
6486
        }
6487
        this.removed = true;
6488
    };
6489
    elproto._getBBox = function () {
6490
        if (this.node.style.display == "none") {
6491
            this.show();
6492
            var hide = true;
6493
        }
6494
        var canvasHidden = false,
6495
            containerStyle;
6496
        if (this.paper.canvas.parentElement) {
6497
          containerStyle = this.paper.canvas.parentElement.style;
6498
        } //IE10+ can't find parentElement
6499
        else if (this.paper.canvas.parentNode) {
6500
          containerStyle = this.paper.canvas.parentNode.style;
6501
        }
6502

6503
        if(containerStyle && containerStyle.display == "none") {
6504
          canvasHidden = true;
6505
          containerStyle.display = "";
6506
        }
6507
        var bbox = {};
6508
        try {
6509
            bbox = this.node.getBBox();
6510
        } catch(e) {
6511
            // Firefox 3.0.x, 25.0.1 (probably more versions affected) play badly here - possible fix
6512
            bbox = {
6513
                x: this.node.clientLeft,
6514
                y: this.node.clientTop,
6515
                width: this.node.clientWidth,
6516
                height: this.node.clientHeight
6517
            }
6518
        } finally {
6519
            bbox = bbox || {};
6520
            if(canvasHidden){
6521
              containerStyle.display = "none";
6522
            }
6523
        }
6524
        hide && this.hide();
6525
        return bbox;
6526
    };
6527
    /*\
6528
     * Element.attr
6529
     [ method ]
6530
     **
6531
     * Sets the attributes of the element.
6532
     > Parameters
6533
     - attrName (string) attribute’s name
6534
     - value (string) value
6535
     * or
6536
     - params (object) object of name/value pairs
6537
     * or
6538
     - attrName (string) attribute’s name
6539
     * or
6540
     - attrNames (array) in this case method returns array of current values for given attribute names
6541
     = (object) @Element if attrsName & value or params are passed in.
6542
     = (...) value of the attribute if only attrsName is passed in.
6543
     = (array) array of values of the attribute if attrsNames is passed in.
6544
     = (object) object of attributes if nothing is passed in.
6545
     > Possible parameters
6546
     # <p>Please refer to the <a href="http://www.w3.org/TR/SVG/" title="The W3C Recommendation for the SVG language describes these properties in detail.">SVG specification</a> for an explanation of these parameters.</p>
6547
     o arrow-end (string) arrowhead on the end of the path. The format for string is `<type>[-<width>[-<length>]]`. Possible types: `classic`, `block`, `open`, `oval`, `diamond`, `none`, width: `wide`, `narrow`, `medium`, length: `long`, `short`, `midium`.
6548
     o clip-rect (string) comma or space separated values: x, y, width and height
6549
     o cursor (string) CSS type of the cursor
6550
     o cx (number) the x-axis coordinate of the center of the circle, or ellipse
6551
     o cy (number) the y-axis coordinate of the center of the circle, or ellipse
6552
     o fill (string) colour, gradient or image
6553
     o fill-opacity (number)
6554
     o font (string)
6555
     o font-family (string)
6556
     o font-size (number) font size in pixels
6557
     o font-weight (string)
6558
     o height (number)
6559
     o href (string) URL, if specified element behaves as hyperlink
6560
     o opacity (number)
6561
     o path (string) SVG path string format
6562
     o r (number) radius of the circle, ellipse or rounded corner on the rect
6563
     o rx (number) horisontal radius of the ellipse
6564
     o ry (number) vertical radius of the ellipse
6565
     o src (string) image URL, only works for @Element.image element
6566
     o stroke (string) stroke colour
6567
     o stroke-dasharray (string) [“”, “none”, “`-`”, “`.`”, “`-.`”, “`-..`”, “`. `”, “`- `”, “`--`”, “`- .`”, “`--.`”, “`--..`”]
6568
     o stroke-linecap (string) [“`butt`”, “`square`”, “`round`”]
6569
     o stroke-linejoin (string) [“`bevel`”, “`round`”, “`miter`”]
6570
     o stroke-miterlimit (number)
6571
     o stroke-opacity (number)
6572
     o stroke-width (number) stroke width in pixels, default is '1'
6573
     o target (string) used with href
6574
     o text (string) contents of the text element. Use `\n` for multiline text
6575
     o text-anchor (string) [“`start`”, “`middle`”, “`end`”], default is “`middle`”
6576
     o title (string) will create tooltip with a given text
6577
     o transform (string) see @Element.transform
6578
     o width (number)
6579
     o x (number)
6580
     o y (number)
6581
     > Gradients
6582
     * Linear gradient format: “`‹angle›-‹colour›[-‹colour›[:‹offset›]]*-‹colour›`”, example: “`90-#fff-#000`” – 90°
6583
     * gradient from white to black or “`0-#fff-#f00:20-#000`” – 0° gradient from white via red (at 20%) to black.
6584
     *
6585
     * radial gradient: “`r[(‹fx›, ‹fy›)]‹colour›[-‹colour›[:‹offset›]]*-‹colour›`”, example: “`r#fff-#000`” –
6586
     * gradient from white to black or “`r(0.25, 0.75)#fff-#000`” – gradient from white to black with focus point
6587
     * at 0.25, 0.75. Focus point coordinates are in 0..1 range. Radial gradients can only be applied to circles and ellipses.
6588
     > Path String
6589
     # <p>Please refer to <a href="http://www.w3.org/TR/SVG/paths.html#PathData" title="Details of a path’s data attribute’s format are described in the SVG specification.">SVG documentation regarding path string</a>. Raphaël fully supports it.</p>
6590
     > Colour Parsing
6591
     # <ul>
6592
     #     <li>Colour name (“<code>red</code>”, “<code>green</code>”, “<code>cornflowerblue</code>”, etc)</li>
6593
     #     <li>#••• — shortened HTML colour: (“<code>#000</code>”, “<code>#fc0</code>”, etc)</li>
6594
     #     <li>#•••••• — full length HTML colour: (“<code>#000000</code>”, “<code>#bd2300</code>”)</li>
6595
     #     <li>rgb(•••, •••, •••) — red, green and blue channels’ values: (“<code>rgb(200,&nbsp;100,&nbsp;0)</code>”)</li>
6596
     #     <li>rgb(•••%, •••%, •••%) — same as above, but in %: (“<code>rgb(100%,&nbsp;175%,&nbsp;0%)</code>”)</li>
6597
     #     <li>rgba(•••, •••, •••, •••) — red, green and blue channels’ values: (“<code>rgba(200,&nbsp;100,&nbsp;0, .5)</code>”)</li>
6598
     #     <li>rgba(•••%, •••%, •••%, •••%) — same as above, but in %: (“<code>rgba(100%,&nbsp;175%,&nbsp;0%, 50%)</code>”)</li>
6599
     #     <li>hsb(•••, •••, •••) — hue, saturation and brightness values: (“<code>hsb(0.5,&nbsp;0.25,&nbsp;1)</code>”)</li>
6600
     #     <li>hsb(•••%, •••%, •••%) — same as above, but in %</li>
6601
     #     <li>hsba(•••, •••, •••, •••) — same as above, but with opacity</li>
6602
     #     <li>hsl(•••, •••, •••) — almost the same as hsb, see <a href="http://en.wikipedia.org/wiki/HSL_and_HSV" title="HSL and HSV - Wikipedia, the free encyclopedia">Wikipedia page</a></li>
6603
     #     <li>hsl(•••%, •••%, •••%) — same as above, but in %</li>
6604
     #     <li>hsla(•••, •••, •••, •••) — same as above, but with opacity</li>
6605
     #     <li>Optionally for hsb and hsl you could specify hue as a degree: “<code>hsl(240deg,&nbsp;1,&nbsp;.5)</code>” or, if you want to go fancy, “<code>hsl(240°,&nbsp;1,&nbsp;.5)</code>”</li>
6606
     # </ul>
6607
    \*/
6608
    elproto.attr = function (name, value) {
6609
        if (this.removed) {
6610
            return this;
6611
        }
6612
        if (name == null) {
6613
            var res = {};
6614
            for (var a in this.attrs) if (this.attrs[has](a)) {
6615
                res[a] = this.attrs[a];
6616
            }
6617
            res.gradient && res.fill == "none" && (res.fill = res.gradient) && delete res.gradient;
6618
            res.transform = this._.transform;
6619
            return res;
6620
        }
6621
        if (value == null && R.is(name, "string")) {
6622
            if (name == "fill" && this.attrs.fill == "none" && this.attrs.gradient) {
6623
                return this.attrs.gradient;
6624
            }
6625
            if (name == "transform") {
6626
                return this._.transform;
6627
            }
6628
            var names = name.split(separator),
6629
                out = {};
6630
            for (var i = 0, ii = names.length; i < ii; i++) {
6631
                name = names[i];
6632
                if (name in this.attrs) {
6633
                    out[name] = this.attrs[name];
6634
                } else if (R.is(this.paper.customAttributes[name], "function")) {
6635
                    out[name] = this.paper.customAttributes[name].def;
6636
                } else {
6637
                    out[name] = R._availableAttrs[name];
6638
                }
6639
            }
6640
            return ii - 1 ? out : out[names[0]];
6641
        }
6642
        if (value == null && R.is(name, "array")) {
6643
            out = {};
6644
            for (i = 0, ii = name.length; i < ii; i++) {
6645
                out[name[i]] = this.attr(name[i]);
6646
            }
6647
            return out;
6648
        }
6649
        if (value != null) {
6650
            var params = {};
6651
            params[name] = value;
6652
        } else if (name != null && R.is(name, "object")) {
6653
            params = name;
6654
        }
6655
        for (var key in params) {
6656
            eve("raphael.attr." + key + "." + this.id, this, params[key]);
6657
        }
6658
        for (key in this.paper.customAttributes) if (this.paper.customAttributes[has](key) && params[has](key) && R.is(this.paper.customAttributes[key], "function")) {
6659
            var par = this.paper.customAttributes[key].apply(this, [].concat(params[key]));
6660
            this.attrs[key] = params[key];
6661
            for (var subkey in par) if (par[has](subkey)) {
6662
                params[subkey] = par[subkey];
6663
            }
6664
        }
6665
        setFillAndStroke(this, params);
6666
        return this;
6667
    };
6668
    /*\
6669
     * Element.toFront
6670
     [ method ]
6671
     **
6672
     * Moves the element so it is the closest to the viewer’s eyes, on top of other elements.
6673
     = (object) @Element
6674
    \*/
6675
    elproto.toFront = function () {
6676
        if (this.removed) {
6677
            return this;
6678
        }
6679
        var node = getRealNode(this.node);
6680
        node.parentNode.appendChild(node);
6681
        var svg = this.paper;
6682
        svg.top != this && R._tofront(this, svg);
6683
        return this;
6684
    };
6685
    /*\
6686
     * Element.toBack
6687
     [ method ]
6688
     **
6689
     * Moves the element so it is the furthest from the viewer’s eyes, behind other elements.
6690
     = (object) @Element
6691
    \*/
6692
    elproto.toBack = function () {
6693
        if (this.removed) {
6694
            return this;
6695
        }
6696
        var node = getRealNode(this.node);
6697
        var parentNode = node.parentNode;
6698
        parentNode.insertBefore(node, parentNode.firstChild);
6699
        R._toback(this, this.paper);
6700
        var svg = this.paper;
6701
        return this;
6702
    };
6703
    /*\
6704
     * Element.insertAfter
6705
     [ method ]
6706
     **
6707
     * Inserts current object after the given one.
6708
     = (object) @Element
6709
    \*/
6710
    elproto.insertAfter = function (element) {
6711
        if (this.removed || !element) {
6712
            return this;
6713
        }
6714

6715
        var node = getRealNode(this.node);
6716
        var afterNode = getRealNode(element.node || element[element.length - 1].node);
6717
        if (afterNode.nextSibling) {
6718
            afterNode.parentNode.insertBefore(node, afterNode.nextSibling);
6719
        } else {
6720
            afterNode.parentNode.appendChild(node);
6721
        }
6722
        R._insertafter(this, element, this.paper);
6723
        return this;
6724
    };
6725
    /*\
6726
     * Element.insertBefore
6727
     [ method ]
6728
     **
6729
     * Inserts current object before the given one.
6730
     = (object) @Element
6731
    \*/
6732
    elproto.insertBefore = function (element) {
6733
        if (this.removed || !element) {
6734
            return this;
6735
        }
6736

6737
        var node = getRealNode(this.node);
6738
        var beforeNode = getRealNode(element.node || element[0].node);
6739
        beforeNode.parentNode.insertBefore(node, beforeNode);
6740
        R._insertbefore(this, element, this.paper);
6741
        return this;
6742
    };
6743
    elproto.blur = function (size) {
6744
        // Experimental. No Safari support. Use it on your own risk.
6745
        var t = this;
6746
        if (+size !== 0) {
6747
            var fltr = $("filter"),
6748
                blur = $("feGaussianBlur");
6749
            t.attrs.blur = size;
6750
            fltr.id = R.createUUID();
6751
            $(blur, {stdDeviation: +size || 1.5});
6752
            fltr.appendChild(blur);
6753
            t.paper.defs.appendChild(fltr);
6754
            t._blur = fltr;
6755
            $(t.node, {filter: "url(#" + fltr.id + ")"});
6756
        } else {
6757
            if (t._blur) {
6758
                t._blur.parentNode.removeChild(t._blur);
6759
                delete t._blur;
6760
                delete t.attrs.blur;
6761
            }
6762
            t.node.removeAttribute("filter");
6763
        }
6764
        return t;
6765
    };
6766
    R._engine.circle = function (svg, x, y, r) {
6767
        var el = $("circle");
6768
        svg.canvas && svg.canvas.appendChild(el);
6769
        var res = new Element(el, svg);
6770
        res.attrs = {cx: x, cy: y, r: r, fill: "none", stroke: "#000"};
6771
        res.type = "circle";
6772
        $(el, res.attrs);
6773
        return res;
6774
    };
6775
    R._engine.rect = function (svg, x, y, w, h, r) {
6776
        var el = $("rect");
6777
        svg.canvas && svg.canvas.appendChild(el);
6778
        var res = new Element(el, svg);
6779
        res.attrs = {x: x, y: y, width: w, height: h, rx: r || 0, ry: r || 0, fill: "none", stroke: "#000"};
6780
        res.type = "rect";
6781
        $(el, res.attrs);
6782
        return res;
6783
    };
6784
    R._engine.ellipse = function (svg, x, y, rx, ry) {
6785
        var el = $("ellipse");
6786
        svg.canvas && svg.canvas.appendChild(el);
6787
        var res = new Element(el, svg);
6788
        res.attrs = {cx: x, cy: y, rx: rx, ry: ry, fill: "none", stroke: "#000"};
6789
        res.type = "ellipse";
6790
        $(el, res.attrs);
6791
        return res;
6792
    };
6793
    R._engine.image = function (svg, src, x, y, w, h) {
6794
        var el = $("image");
6795
        $(el, {x: x, y: y, width: w, height: h, preserveAspectRatio: "none"});
6796
        el.setAttributeNS(xlink, "href", src);
6797
        svg.canvas && svg.canvas.appendChild(el);
6798
        var res = new Element(el, svg);
6799
        res.attrs = {x: x, y: y, width: w, height: h, src: src};
6800
        res.type = "image";
6801
        return res;
6802
    };
6803
    R._engine.text = function (svg, x, y, text) {
6804
        var el = $("text");
6805
        svg.canvas && svg.canvas.appendChild(el);
6806
        var res = new Element(el, svg);
6807
        res.attrs = {
6808
            x: x,
6809
            y: y,
6810
            "text-anchor": "middle",
6811
            text: text,
6812
            "font-family": R._availableAttrs["font-family"],
6813
            "font-size": R._availableAttrs["font-size"],
6814
            stroke: "none",
6815
            fill: "#000"
6816
        };
6817
        res.type = "text";
6818
        setFillAndStroke(res, res.attrs);
6819
        return res;
6820
    };
6821
    R._engine.setSize = function (width, height) {
6822
        this.width = width || this.width;
6823
        this.height = height || this.height;
6824
        this.canvas.setAttribute("width", this.width);
6825
        this.canvas.setAttribute("height", this.height);
6826
        if (this._viewBox) {
6827
            this.setViewBox.apply(this, this._viewBox);
6828
        }
6829
        return this;
6830
    };
6831
    R._engine.create = function () {
6832
        var con = R._getContainer.apply(0, arguments),
6833
            container = con && con.container;
6834
        if (!container) {
6835
            throw new Error("SVG container not found.");
6836
        }
6837
        var x = con.x,
6838
            y = con.y,
6839
            width = con.width,
6840
            height = con.height,
6841
            cnvs = $("svg"),
6842
            css = "overflow:hidden;",
6843
            isFloating;
6844
        x = x || 0;
6845
        y = y || 0;
6846
        width = width || 512;
6847
        height = height || 342;
6848
        $(cnvs, {
6849
            height: height,
6850
            version: 1.1,
6851
            width: width,
6852
            xmlns: "http://www.w3.org/2000/svg",
6853
            "xmlns:xlink": "http://www.w3.org/1999/xlink"
6854
        });
6855
        if (container == 1) {
6856
            cnvs.style.cssText = css + "position:absolute;left:" + x + "px;top:" + y + "px";
6857
            R._g.doc.body.appendChild(cnvs);
6858
            isFloating = 1;
6859
        } else {
6860
            cnvs.style.cssText = css + "position:relative";
6861
            if (container.firstChild) {
6862
                container.insertBefore(cnvs, container.firstChild);
6863
            } else {
6864
                container.appendChild(cnvs);
6865
            }
6866
        }
6867
        container = new R._Paper;
6868
        container.width = width;
6869
        container.height = height;
6870
        container.canvas = cnvs;
6871
        container.clear();
6872
        container._left = container._top = 0;
6873
        isFloating && (container.renderfix = function () {});
6874
        container.renderfix();
6875
        return container;
6876
    };
6877
    R._engine.setViewBox = function (x, y, w, h, fit) {
6878
        eve("raphael.setViewBox", this, this._viewBox, [x, y, w, h, fit]);
6879
        var paperSize = this.getSize(),
6880
            size = mmax(w / paperSize.width, h / paperSize.height),
6881
            top = this.top,
6882
            aspectRatio = fit ? "xMidYMid meet" : "xMinYMin",
6883
            vb,
6884
            sw;
6885
        if (x == null) {
6886
            if (this._vbSize) {
6887
                size = 1;
6888
            }
6889
            delete this._vbSize;
6890
            vb = "0 0 " + this.width + S + this.height;
6891
        } else {
6892
            this._vbSize = size;
6893
            vb = x + S + y + S + w + S + h;
6894
        }
6895
        $(this.canvas, {
6896
            viewBox: vb,
6897
            preserveAspectRatio: aspectRatio
6898
        });
6899
        while (size && top) {
6900
            sw = "stroke-width" in top.attrs ? top.attrs["stroke-width"] : 1;
6901
            top.attr({"stroke-width": sw});
6902
            top._.dirty = 1;
6903
            top._.dirtyT = 1;
6904
            top = top.prev;
6905
        }
6906
        this._viewBox = [x, y, w, h, !!fit];
6907
        return this;
6908
    };
6909
    /*\
6910
     * Paper.renderfix
6911
     [ method ]
6912
     **
6913
     * Fixes the issue of Firefox and IE9 regarding subpixel rendering. If paper is dependent
6914
     * on other elements after reflow it could shift half pixel which cause for lines to lost their crispness.
6915
     * This method fixes the issue.
6916
     **
6917
       Special thanks to Mariusz Nowak (http://www.medikoo.com/) for this method.
6918
    \*/
6919
    R.prototype.renderfix = function () {
6920
        var cnvs = this.canvas,
6921
            s = cnvs.style,
6922
            pos;
6923
        try {
6924
            pos = cnvs.getScreenCTM() || cnvs.createSVGMatrix();
6925
        } catch (e) {
6926
            pos = cnvs.createSVGMatrix();
6927
        }
6928
        var left = -pos.e % 1,
6929
            top = -pos.f % 1;
6930
        if (left || top) {
6931
            if (left) {
6932
                this._left = (this._left + left) % 1;
6933
                s.left = this._left + "px";
6934
            }
6935
            if (top) {
6936
                this._top = (this._top + top) % 1;
6937
                s.top = this._top + "px";
6938
            }
6939
        }
6940
    };
6941
    /*\
6942
     * Paper.clear
6943
     [ method ]
6944
     **
6945
     * Clears the paper, i.e. removes all the elements.
6946
    \*/
6947
    R.prototype.clear = function () {
6948
        R.eve("raphael.clear", this);
6949
        var c = this.canvas;
6950
        while (c.firstChild) {
6951
            c.removeChild(c.firstChild);
6952
        }
6953
        this.bottom = this.top = null;
6954
        (this.desc = $("desc")).appendChild(R._g.doc.createTextNode("Created with Rapha\xebl " + R.version));
6955
        c.appendChild(this.desc);
6956
        c.appendChild(this.defs = $("defs"));
6957
    };
6958
    /*\
6959
     * Paper.remove
6960
     [ method ]
6961
     **
6962
     * Removes the paper from the DOM.
6963
    \*/
6964
    R.prototype.remove = function () {
6965
        eve("raphael.remove", this);
6966
        this.canvas.parentNode && this.canvas.parentNode.removeChild(this.canvas);
6967
        for (var i in this) {
6968
            this[i] = typeof this[i] == "function" ? R._removedFactory(i) : null;
6969
        }
6970
    };
6971
    var setproto = R.st;
6972
    for (var method in elproto) if (elproto[has](method) && !setproto[has](method)) {
6973
        setproto[method] = (function (methodname) {
6974
            return function () {
6975
                var arg = arguments;
6976
                return this.forEach(function (el) {
6977
                    el[methodname].apply(el, arg);
6978
                });
6979
            };
6980
        })(method);
6981
    }
6982
}).apply(exports, __WEBPACK_AMD_DEFINE_ARRAY__),
6983
				__WEBPACK_AMD_DEFINE_RESULT__ !== undefined && (module.exports = __WEBPACK_AMD_DEFINE_RESULT__));
6984

6985

6986
/***/ }),
6987

6988
/***/ "./dev/raphael.vml.js":
6989
/*!****************************!*\
6990
  !*** ./dev/raphael.vml.js ***!
6991
  \****************************/
6992
/*! no static exports found */
6993
/***/ (function(module, exports, __webpack_require__) {
6994

6995
var __WEBPACK_AMD_DEFINE_ARRAY__, __WEBPACK_AMD_DEFINE_RESULT__;!(__WEBPACK_AMD_DEFINE_ARRAY__ = [__webpack_require__(/*! ./raphael.core */ "./dev/raphael.core.js")], __WEBPACK_AMD_DEFINE_RESULT__ = (function(R) {
6996
    if (R && !R.vml) {
6997
        return;
6998
    }
6999

7000
    var has = "hasOwnProperty",
7001
        Str = String,
7002
        toFloat = parseFloat,
7003
        math = Math,
7004
        round = math.round,
7005
        mmax = math.max,
7006
        mmin = math.min,
7007
        abs = math.abs,
7008
        fillString = "fill",
7009
        separator = /[, ]+/,
7010
        eve = R.eve,
7011
        ms = " progid:DXImageTransform.Microsoft",
7012
        S = " ",
7013
        E = "",
7014
        map = {M: "m", L: "l", C: "c", Z: "x", m: "t", l: "r", c: "v", z: "x"},
7015
        bites = /([clmz]),?([^clmz]*)/gi,
7016
        blurregexp = / progid:\S+Blur\([^\)]+\)/g,
7017
        val = /-?[^,\s-]+/g,
7018
        cssDot = "position:absolute;left:0;top:0;width:1px;height:1px;behavior:url(#default#VML)",
7019
        zoom = 21600,
7020
        pathTypes = {path: 1, rect: 1, image: 1},
7021
        ovalTypes = {circle: 1, ellipse: 1},
7022
        path2vml = function (path) {
7023
            var total =  /[ahqstv]/ig,
7024
                command = R._pathToAbsolute;
7025
            Str(path).match(total) && (command = R._path2curve);
7026
            total = /[clmz]/g;
7027
            if (command == R._pathToAbsolute && !Str(path).match(total)) {
7028
                var res = Str(path).replace(bites, function (all, command, args) {
7029
                    var vals = [],
7030
                        isMove = command.toLowerCase() == "m",
7031
                        res = map[command];
7032
                    args.replace(val, function (value) {
7033
                        if (isMove && vals.length == 2) {
7034
                            res += vals + map[command == "m" ? "l" : "L"];
7035
                            vals = [];
7036
                        }
7037
                        vals.push(round(value * zoom));
7038
                    });
7039
                    return res + vals;
7040
                });
7041
                return res;
7042
            }
7043
            var pa = command(path), p, r;
7044
            res = [];
7045
            for (var i = 0, ii = pa.length; i < ii; i++) {
7046
                p = pa[i];
7047
                r = pa[i][0].toLowerCase();
7048
                r == "z" && (r = "x");
7049
                for (var j = 1, jj = p.length; j < jj; j++) {
7050
                    r += round(p[j] * zoom) + (j != jj - 1 ? "," : E);
7051
                }
7052
                res.push(r);
7053
            }
7054
            return res.join(S);
7055
        },
7056
        compensation = function (deg, dx, dy) {
7057
            var m = R.matrix();
7058
            m.rotate(-deg, .5, .5);
7059
            return {
7060
                dx: m.x(dx, dy),
7061
                dy: m.y(dx, dy)
7062
            };
7063
        },
7064
        setCoords = function (p, sx, sy, dx, dy, deg) {
7065
            var _ = p._,
7066
                m = p.matrix,
7067
                fillpos = _.fillpos,
7068
                o = p.node,
7069
                s = o.style,
7070
                y = 1,
7071
                flip = "",
7072
                dxdy,
7073
                kx = zoom / sx,
7074
                ky = zoom / sy;
7075
            s.visibility = "hidden";
7076
            if (!sx || !sy) {
7077
                return;
7078
            }
7079
            o.coordsize = abs(kx) + S + abs(ky);
7080
            s.rotation = deg * (sx * sy < 0 ? -1 : 1);
7081
            if (deg) {
7082
                var c = compensation(deg, dx, dy);
7083
                dx = c.dx;
7084
                dy = c.dy;
7085
            }
7086
            sx < 0 && (flip += "x");
7087
            sy < 0 && (flip += " y") && (y = -1);
7088
            s.flip = flip;
7089
            o.coordorigin = (dx * -kx) + S + (dy * -ky);
7090
            if (fillpos || _.fillsize) {
7091
                var fill = o.getElementsByTagName(fillString);
7092
                fill = fill && fill[0];
7093
                o.removeChild(fill);
7094
                if (fillpos) {
7095
                    c = compensation(deg, m.x(fillpos[0], fillpos[1]), m.y(fillpos[0], fillpos[1]));
7096
                    fill.position = c.dx * y + S + c.dy * y;
7097
                }
7098
                if (_.fillsize) {
7099
                    fill.size = _.fillsize[0] * abs(sx) + S + _.fillsize[1] * abs(sy);
7100
                }
7101
                o.appendChild(fill);
7102
            }
7103
            s.visibility = "visible";
7104
        };
7105
    R.toString = function () {
7106
        return  "Your browser doesn\u2019t support SVG. Falling down to VML.\nYou are running Rapha\xebl " + this.version;
7107
    };
7108
    var addArrow = function (o, value, isEnd) {
7109
        var values = Str(value).toLowerCase().split("-"),
7110
            se = isEnd ? "end" : "start",
7111
            i = values.length,
7112
            type = "classic",
7113
            w = "medium",
7114
            h = "medium";
7115
        while (i--) {
7116
            switch (values[i]) {
7117
                case "block":
7118
                case "classic":
7119
                case "oval":
7120
                case "diamond":
7121
                case "open":
7122
                case "none":
7123
                    type = values[i];
7124
                    break;
7125
                case "wide":
7126
                case "narrow": h = values[i]; break;
7127
                case "long":
7128
                case "short": w = values[i]; break;
7129
            }
7130
        }
7131
        var stroke = o.node.getElementsByTagName("stroke")[0];
7132
        stroke[se + "arrow"] = type;
7133
        stroke[se + "arrowlength"] = w;
7134
        stroke[se + "arrowwidth"] = h;
7135
    },
7136
    setFillAndStroke = function (o, params) {
7137
        // o.paper.canvas.style.display = "none";
7138
        o.attrs = o.attrs || {};
7139
        var node = o.node,
7140
            a = o.attrs,
7141
            s = node.style,
7142
            xy,
7143
            newpath = pathTypes[o.type] && (params.x != a.x || params.y != a.y || params.width != a.width || params.height != a.height || params.cx != a.cx || params.cy != a.cy || params.rx != a.rx || params.ry != a.ry || params.r != a.r),
7144
            isOval = ovalTypes[o.type] && (a.cx != params.cx || a.cy != params.cy || a.r != params.r || a.rx != params.rx || a.ry != params.ry),
7145
            res = o;
7146

7147

7148
        for (var par in params) if (params[has](par)) {
7149
            a[par] = params[par];
7150
        }
7151
        if (newpath) {
7152
            a.path = R._getPath[o.type](o);
7153
            o._.dirty = 1;
7154
        }
7155
        params.href && (node.href = params.href);
7156
        params.title && (node.title = params.title);
7157
        params.target && (node.target = params.target);
7158
        params.cursor && (s.cursor = params.cursor);
7159
        "blur" in params && o.blur(params.blur);
7160
        if (params.path && o.type == "path" || newpath) {
7161
            node.path = path2vml(~Str(a.path).toLowerCase().indexOf("r") ? R._pathToAbsolute(a.path) : a.path);
7162
            o._.dirty = 1;
7163
            if (o.type == "image") {
7164
                o._.fillpos = [a.x, a.y];
7165
                o._.fillsize = [a.width, a.height];
7166
                setCoords(o, 1, 1, 0, 0, 0);
7167
            }
7168
        }
7169
        "transform" in params && o.transform(params.transform);
7170
        if (isOval) {
7171
            var cx = +a.cx,
7172
                cy = +a.cy,
7173
                rx = +a.rx || +a.r || 0,
7174
                ry = +a.ry || +a.r || 0;
7175
            node.path = R.format("ar{0},{1},{2},{3},{4},{1},{4},{1}x", round((cx - rx) * zoom), round((cy - ry) * zoom), round((cx + rx) * zoom), round((cy + ry) * zoom), round(cx * zoom));
7176
            o._.dirty = 1;
7177
        }
7178
        if ("clip-rect" in params) {
7179
            var rect = Str(params["clip-rect"]).split(separator);
7180
            if (rect.length == 4) {
7181
                rect[2] = +rect[2] + (+rect[0]);
7182
                rect[3] = +rect[3] + (+rect[1]);
7183
                var div = node.clipRect || R._g.doc.createElement("div"),
7184
                    dstyle = div.style;
7185
                dstyle.clip = R.format("rect({1}px {2}px {3}px {0}px)", rect);
7186
                if (!node.clipRect) {
7187
                    dstyle.position = "absolute";
7188
                    dstyle.top = 0;
7189
                    dstyle.left = 0;
7190
                    dstyle.width = o.paper.width + "px";
7191
                    dstyle.height = o.paper.height + "px";
7192
                    node.parentNode.insertBefore(div, node);
7193
                    div.appendChild(node);
7194
                    node.clipRect = div;
7195
                }
7196
            }
7197
            if (!params["clip-rect"]) {
7198
                node.clipRect && (node.clipRect.style.clip = "auto");
7199
            }
7200
        }
7201
        if (o.textpath) {
7202
            var textpathStyle = o.textpath.style;
7203
            params.font && (textpathStyle.font = params.font);
7204
            params["font-family"] && (textpathStyle.fontFamily = '"' + params["font-family"].split(",")[0].replace(/^['"]+|['"]+$/g, E) + '"');
7205
            params["font-size"] && (textpathStyle.fontSize = params["font-size"]);
7206
            params["font-weight"] && (textpathStyle.fontWeight = params["font-weight"]);
7207
            params["font-style"] && (textpathStyle.fontStyle = params["font-style"]);
7208
        }
7209
        if ("arrow-start" in params) {
7210
            addArrow(res, params["arrow-start"]);
7211
        }
7212
        if ("arrow-end" in params) {
7213
            addArrow(res, params["arrow-end"], 1);
7214
        }
7215
        if (params.opacity != null ||
7216
            params.fill != null ||
7217
            params.src != null ||
7218
            params.stroke != null ||
7219
            params["stroke-width"] != null ||
7220
            params["stroke-opacity"] != null ||
7221
            params["fill-opacity"] != null ||
7222
            params["stroke-dasharray"] != null ||
7223
            params["stroke-miterlimit"] != null ||
7224
            params["stroke-linejoin"] != null ||
7225
            params["stroke-linecap"] != null) {
7226
            var fill = node.getElementsByTagName(fillString),
7227
                newfill = false;
7228
            fill = fill && fill[0];
7229
            !fill && (newfill = fill = createNode(fillString));
7230
            if (o.type == "image" && params.src) {
7231
                fill.src = params.src;
7232
            }
7233
            params.fill && (fill.on = true);
7234
            if (fill.on == null || params.fill == "none" || params.fill === null) {
7235
                fill.on = false;
7236
            }
7237
            if (fill.on && params.fill) {
7238
                var isURL = Str(params.fill).match(R._ISURL);
7239
                if (isURL) {
7240
                    fill.parentNode == node && node.removeChild(fill);
7241
                    fill.rotate = true;
7242
                    fill.src = isURL[1];
7243
                    fill.type = "tile";
7244
                    var bbox = o.getBBox(1);
7245
                    fill.position = bbox.x + S + bbox.y;
7246
                    o._.fillpos = [bbox.x, bbox.y];
7247

7248
                    R._preload(isURL[1], function () {
7249
                        o._.fillsize = [this.offsetWidth, this.offsetHeight];
7250
                    });
7251
                } else {
7252
                    fill.color = R.getRGB(params.fill).hex;
7253
                    fill.src = E;
7254
                    fill.type = "solid";
7255
                    if (R.getRGB(params.fill).error && (res.type in {circle: 1, ellipse: 1} || Str(params.fill).charAt() != "r") && addGradientFill(res, params.fill, fill)) {
7256
                        a.fill = "none";
7257
                        a.gradient = params.fill;
7258
                        fill.rotate = false;
7259
                    }
7260
                }
7261
            }
7262
            if ("fill-opacity" in params || "opacity" in params) {
7263
                var opacity = ((+a["fill-opacity"] + 1 || 2) - 1) * ((+a.opacity + 1 || 2) - 1) * ((+R.getRGB(params.fill).o + 1 || 2) - 1);
7264
                opacity = mmin(mmax(opacity, 0), 1);
7265
                fill.opacity = opacity;
7266
                if (fill.src) {
7267
                    fill.color = "none";
7268
                }
7269
            }
7270
            node.appendChild(fill);
7271
            var stroke = (node.getElementsByTagName("stroke") && node.getElementsByTagName("stroke")[0]),
7272
            newstroke = false;
7273
            !stroke && (newstroke = stroke = createNode("stroke"));
7274
            if ((params.stroke && params.stroke != "none") ||
7275
                params["stroke-width"] ||
7276
                params["stroke-opacity"] != null ||
7277
                params["stroke-dasharray"] ||
7278
                params["stroke-miterlimit"] ||
7279
                params["stroke-linejoin"] ||
7280
                params["stroke-linecap"]) {
7281
                stroke.on = true;
7282
            }
7283
            (params.stroke == "none" || params.stroke === null || stroke.on == null || params.stroke == 0 || params["stroke-width"] == 0) && (stroke.on = false);
7284
            var strokeColor = R.getRGB(params.stroke);
7285
            stroke.on && params.stroke && (stroke.color = strokeColor.hex);
7286
            opacity = ((+a["stroke-opacity"] + 1 || 2) - 1) * ((+a.opacity + 1 || 2) - 1) * ((+strokeColor.o + 1 || 2) - 1);
7287
            var width = (toFloat(params["stroke-width"]) || 1) * .75;
7288
            opacity = mmin(mmax(opacity, 0), 1);
7289
            params["stroke-width"] == null && (width = a["stroke-width"]);
7290
            params["stroke-width"] && (stroke.weight = width);
7291
            width && width < 1 && (opacity *= width) && (stroke.weight = 1);
7292
            stroke.opacity = opacity;
7293

7294
            params["stroke-linejoin"] && (stroke.joinstyle = params["stroke-linejoin"] || "miter");
7295
            stroke.miterlimit = params["stroke-miterlimit"] || 8;
7296
            params["stroke-linecap"] && (stroke.endcap = params["stroke-linecap"] == "butt" ? "flat" : params["stroke-linecap"] == "square" ? "square" : "round");
7297
            if ("stroke-dasharray" in params) {
7298
                var dasharray = {
7299
                    "-": "shortdash",
7300
                    ".": "shortdot",
7301
                    "-.": "shortdashdot",
7302
                    "-..": "shortdashdotdot",
7303
                    ". ": "dot",
7304
                    "- ": "dash",
7305
                    "--": "longdash",
7306
                    "- .": "dashdot",
7307
                    "--.": "longdashdot",
7308
                    "--..": "longdashdotdot"
7309
                };
7310
                stroke.dashstyle = dasharray[has](params["stroke-dasharray"]) ? dasharray[params["stroke-dasharray"]] : E;
7311
            }
7312
            newstroke && node.appendChild(stroke);
7313
        }
7314
        if (res.type == "text") {
7315
            res.paper.canvas.style.display = E;
7316
            var span = res.paper.span,
7317
                m = 100,
7318
                fontSize = a.font && a.font.match(/\d+(?:\.\d*)?(?=px)/);
7319
            s = span.style;
7320
            a.font && (s.font = a.font);
7321
            a["font-family"] && (s.fontFamily = a["font-family"]);
7322
            a["font-weight"] && (s.fontWeight = a["font-weight"]);
7323
            a["font-style"] && (s.fontStyle = a["font-style"]);
7324
            fontSize = toFloat(a["font-size"] || fontSize && fontSize[0]) || 10;
7325
            s.fontSize = fontSize * m + "px";
7326
            res.textpath.string && (span.innerHTML = Str(res.textpath.string).replace(/</g, "&#60;").replace(/&/g, "&#38;").replace(/\n/g, "<br>"));
7327
            var brect = span.getBoundingClientRect();
7328
            res.W = a.w = (brect.right - brect.left) / m;
7329
            res.H = a.h = (brect.bottom - brect.top) / m;
7330
            // res.paper.canvas.style.display = "none";
7331
            res.X = a.x;
7332
            res.Y = a.y + res.H / 2;
7333

7334
            ("x" in params || "y" in params) && (res.path.v = R.format("m{0},{1}l{2},{1}", round(a.x * zoom), round(a.y * zoom), round(a.x * zoom) + 1));
7335
            var dirtyattrs = ["x", "y", "text", "font", "font-family", "font-weight", "font-style", "font-size"];
7336
            for (var d = 0, dd = dirtyattrs.length; d < dd; d++) if (dirtyattrs[d] in params) {
7337
                res._.dirty = 1;
7338
                break;
7339
            }
7340

7341
            // text-anchor emulation
7342
            switch (a["text-anchor"]) {
7343
                case "start":
7344
                    res.textpath.style["v-text-align"] = "left";
7345
                    res.bbx = res.W / 2;
7346
                break;
7347
                case "end":
7348
                    res.textpath.style["v-text-align"] = "right";
7349
                    res.bbx = -res.W / 2;
7350
                break;
7351
                default:
7352
                    res.textpath.style["v-text-align"] = "center";
7353
                    res.bbx = 0;
7354
                break;
7355
            }
7356
            res.textpath.style["v-text-kern"] = true;
7357
        }
7358
        // res.paper.canvas.style.display = E;
7359
    },
7360
    addGradientFill = function (o, gradient, fill) {
7361
        o.attrs = o.attrs || {};
7362
        var attrs = o.attrs,
7363
            pow = Math.pow,
7364
            opacity,
7365
            oindex,
7366
            type = "linear",
7367
            fxfy = ".5 .5";
7368
        o.attrs.gradient = gradient;
7369
        gradient = Str(gradient).replace(R._radial_gradient, function (all, fx, fy) {
7370
            type = "radial";
7371
            if (fx && fy) {
7372
                fx = toFloat(fx);
7373
                fy = toFloat(fy);
7374
                pow(fx - .5, 2) + pow(fy - .5, 2) > .25 && (fy = math.sqrt(.25 - pow(fx - .5, 2)) * ((fy > .5) * 2 - 1) + .5);
7375
                fxfy = fx + S + fy;
7376
            }
7377
            return E;
7378
        });
7379
        gradient = gradient.split(/\s*\-\s*/);
7380
        if (type == "linear") {
7381
            var angle = gradient.shift();
7382
            angle = -toFloat(angle);
7383
            if (isNaN(angle)) {
7384
                return null;
7385
            }
7386
        }
7387
        var dots = R._parseDots(gradient);
7388
        if (!dots) {
7389
            return null;
7390
        }
7391
        o = o.shape || o.node;
7392
        if (dots.length) {
7393
            o.removeChild(fill);
7394
            fill.on = true;
7395
            fill.method = "none";
7396
            fill.color = dots[0].color;
7397
            fill.color2 = dots[dots.length - 1].color;
7398
            var clrs = [];
7399
            for (var i = 0, ii = dots.length; i < ii; i++) {
7400
                dots[i].offset && clrs.push(dots[i].offset + S + dots[i].color);
7401
            }
7402
            fill.colors = clrs.length ? clrs.join() : "0% " + fill.color;
7403
            if (type == "radial") {
7404
                fill.type = "gradientTitle";
7405
                fill.focus = "100%";
7406
                fill.focussize = "0 0";
7407
                fill.focusposition = fxfy;
7408
                fill.angle = 0;
7409
            } else {
7410
                // fill.rotate= true;
7411
                fill.type = "gradient";
7412
                fill.angle = (270 - angle) % 360;
7413
            }
7414
            o.appendChild(fill);
7415
        }
7416
        return 1;
7417
    },
7418
    Element = function (node, vml) {
7419
        this[0] = this.node = node;
7420
        node.raphael = true;
7421
        this.id = R._oid++;
7422
        node.raphaelid = this.id;
7423
        this.X = 0;
7424
        this.Y = 0;
7425
        this.attrs = {};
7426
        this.paper = vml;
7427
        this.matrix = R.matrix();
7428
        this._ = {
7429
            transform: [],
7430
            sx: 1,
7431
            sy: 1,
7432
            dx: 0,
7433
            dy: 0,
7434
            deg: 0,
7435
            dirty: 1,
7436
            dirtyT: 1
7437
        };
7438
        !vml.bottom && (vml.bottom = this);
7439
        this.prev = vml.top;
7440
        vml.top && (vml.top.next = this);
7441
        vml.top = this;
7442
        this.next = null;
7443
    };
7444
    var elproto = R.el;
7445

7446
    Element.prototype = elproto;
7447
    elproto.constructor = Element;
7448
    elproto.transform = function (tstr) {
7449
        if (tstr == null) {
7450
            return this._.transform;
7451
        }
7452
        var vbs = this.paper._viewBoxShift,
7453
            vbt = vbs ? "s" + [vbs.scale, vbs.scale] + "-1-1t" + [vbs.dx, vbs.dy] : E,
7454
            oldt;
7455
        if (vbs) {
7456
            oldt = tstr = Str(tstr).replace(/\.{3}|\u2026/g, this._.transform || E);
7457
        }
7458
        R._extractTransform(this, vbt + tstr);
7459
        var matrix = this.matrix.clone(),
7460
            skew = this.skew,
7461
            o = this.node,
7462
            split,
7463
            isGrad = ~Str(this.attrs.fill).indexOf("-"),
7464
            isPatt = !Str(this.attrs.fill).indexOf("url(");
7465
        matrix.translate(1, 1);
7466
        if (isPatt || isGrad || this.type == "image") {
7467
            skew.matrix = "1 0 0 1";
7468
            skew.offset = "0 0";
7469
            split = matrix.split();
7470
            if ((isGrad && split.noRotation) || !split.isSimple) {
7471
                o.style.filter = matrix.toFilter();
7472
                var bb = this.getBBox(),
7473
                    bbt = this.getBBox(1),
7474
                    dx = bb.x - bbt.x,
7475
                    dy = bb.y - bbt.y;
7476
                o.coordorigin = (dx * -zoom) + S + (dy * -zoom);
7477
                setCoords(this, 1, 1, dx, dy, 0);
7478
            } else {
7479
                o.style.filter = E;
7480
                setCoords(this, split.scalex, split.scaley, split.dx, split.dy, split.rotate);
7481
            }
7482
        } else {
7483
            o.style.filter = E;
7484
            skew.matrix = Str(matrix);
7485
            skew.offset = matrix.offset();
7486
        }
7487
        if (oldt !== null) { // empty string value is true as well
7488
            this._.transform = oldt;
7489
            R._extractTransform(this, oldt);
7490
        }
7491
        return this;
7492
    };
7493
    elproto.rotate = function (deg, cx, cy) {
7494
        if (this.removed) {
7495
            return this;
7496
        }
7497
        if (deg == null) {
7498
            return;
7499
        }
7500
        deg = Str(deg).split(separator);
7501
        if (deg.length - 1) {
7502
            cx = toFloat(deg[1]);
7503
            cy = toFloat(deg[2]);
7504
        }
7505
        deg = toFloat(deg[0]);
7506
        (cy == null) && (cx = cy);
7507
        if (cx == null || cy == null) {
7508
            var bbox = this.getBBox(1);
7509
            cx = bbox.x + bbox.width / 2;
7510
            cy = bbox.y + bbox.height / 2;
7511
        }
7512
        this._.dirtyT = 1;
7513
        this.transform(this._.transform.concat([["r", deg, cx, cy]]));
7514
        return this;
7515
    };
7516
    elproto.translate = function (dx, dy) {
7517
        if (this.removed) {
7518
            return this;
7519
        }
7520
        dx = Str(dx).split(separator);
7521
        if (dx.length - 1) {
7522
            dy = toFloat(dx[1]);
7523
        }
7524
        dx = toFloat(dx[0]) || 0;
7525
        dy = +dy || 0;
7526
        if (this._.bbox) {
7527
            this._.bbox.x += dx;
7528
            this._.bbox.y += dy;
7529
        }
7530
        this.transform(this._.transform.concat([["t", dx, dy]]));
7531
        return this;
7532
    };
7533
    elproto.scale = function (sx, sy, cx, cy) {
7534
        if (this.removed) {
7535
            return this;
7536
        }
7537
        sx = Str(sx).split(separator);
7538
        if (sx.length - 1) {
7539
            sy = toFloat(sx[1]);
7540
            cx = toFloat(sx[2]);
7541
            cy = toFloat(sx[3]);
7542
            isNaN(cx) && (cx = null);
7543
            isNaN(cy) && (cy = null);
7544
        }
7545
        sx = toFloat(sx[0]);
7546
        (sy == null) && (sy = sx);
7547
        (cy == null) && (cx = cy);
7548
        if (cx == null || cy == null) {
7549
            var bbox = this.getBBox(1);
7550
        }
7551
        cx = cx == null ? bbox.x + bbox.width / 2 : cx;
7552
        cy = cy == null ? bbox.y + bbox.height / 2 : cy;
7553

7554
        this.transform(this._.transform.concat([["s", sx, sy, cx, cy]]));
7555
        this._.dirtyT = 1;
7556
        return this;
7557
    };
7558
    elproto.hide = function () {
7559
        !this.removed && (this.node.style.display = "none");
7560
        return this;
7561
    };
7562
    elproto.show = function () {
7563
        !this.removed && (this.node.style.display = E);
7564
        return this;
7565
    };
7566
    // Needed to fix the vml setViewBox issues
7567
    elproto.auxGetBBox = R.el.getBBox;
7568
    elproto.getBBox = function(){
7569
      var b = this.auxGetBBox();
7570
      if (this.paper && this.paper._viewBoxShift)
7571
      {
7572
        var c = {};
7573
        var z = 1/this.paper._viewBoxShift.scale;
7574
        c.x = b.x - this.paper._viewBoxShift.dx;
7575
        c.x *= z;
7576
        c.y = b.y - this.paper._viewBoxShift.dy;
7577
        c.y *= z;
7578
        c.width  = b.width  * z;
7579
        c.height = b.height * z;
7580
        c.x2 = c.x + c.width;
7581
        c.y2 = c.y + c.height;
7582
        return c;
7583
      }
7584
      return b;
7585
    };
7586
    elproto._getBBox = function () {
7587
        if (this.removed) {
7588
            return {};
7589
        }
7590
        return {
7591
            x: this.X + (this.bbx || 0) - this.W / 2,
7592
            y: this.Y - this.H,
7593
            width: this.W,
7594
            height: this.H
7595
        };
7596
    };
7597
    elproto.remove = function () {
7598
        if (this.removed || !this.node.parentNode) {
7599
            return;
7600
        }
7601
        this.paper.__set__ && this.paper.__set__.exclude(this);
7602
        R.eve.unbind("raphael.*.*." + this.id);
7603
        R._tear(this, this.paper);
7604
        this.node.parentNode.removeChild(this.node);
7605
        this.shape && this.shape.parentNode.removeChild(this.shape);
7606
        for (var i in this) {
7607
            this[i] = typeof this[i] == "function" ? R._removedFactory(i) : null;
7608
        }
7609
        this.removed = true;
7610
    };
7611
    elproto.attr = function (name, value) {
7612
        if (this.removed) {
7613
            return this;
7614
        }
7615
        if (name == null) {
7616
            var res = {};
7617
            for (var a in this.attrs) if (this.attrs[has](a)) {
7618
                res[a] = this.attrs[a];
7619
            }
7620
            res.gradient && res.fill == "none" && (res.fill = res.gradient) && delete res.gradient;
7621
            res.transform = this._.transform;
7622
            return res;
7623
        }
7624
        if (value == null && R.is(name, "string")) {
7625
            if (name == fillString && this.attrs.fill == "none" && this.attrs.gradient) {
7626
                return this.attrs.gradient;
7627
            }
7628
            var names = name.split(separator),
7629
                out = {};
7630
            for (var i = 0, ii = names.length; i < ii; i++) {
7631
                name = names[i];
7632
                if (name in this.attrs) {
7633
                    out[name] = this.attrs[name];
7634
                } else if (R.is(this.paper.customAttributes[name], "function")) {
7635
                    out[name] = this.paper.customAttributes[name].def;
7636
                } else {
7637
                    out[name] = R._availableAttrs[name];
7638
                }
7639
            }
7640
            return ii - 1 ? out : out[names[0]];
7641
        }
7642
        if (this.attrs && value == null && R.is(name, "array")) {
7643
            out = {};
7644
            for (i = 0, ii = name.length; i < ii; i++) {
7645
                out[name[i]] = this.attr(name[i]);
7646
            }
7647
            return out;
7648
        }
7649
        var params;
7650
        if (value != null) {
7651
            params = {};
7652
            params[name] = value;
7653
        }
7654
        value == null && R.is(name, "object") && (params = name);
7655
        for (var key in params) {
7656
            eve("raphael.attr." + key + "." + this.id, this, params[key]);
7657
        }
7658
        if (params) {
7659
            for (key in this.paper.customAttributes) if (this.paper.customAttributes[has](key) && params[has](key) && R.is(this.paper.customAttributes[key], "function")) {
7660
                var par = this.paper.customAttributes[key].apply(this, [].concat(params[key]));
7661
                this.attrs[key] = params[key];
7662
                for (var subkey in par) if (par[has](subkey)) {
7663
                    params[subkey] = par[subkey];
7664
                }
7665
            }
7666
            // this.paper.canvas.style.display = "none";
7667
            if (params.text && this.type == "text") {
7668
                this.textpath.string = params.text;
7669
            }
7670
            setFillAndStroke(this, params);
7671
            // this.paper.canvas.style.display = E;
7672
        }
7673
        return this;
7674
    };
7675
    elproto.toFront = function () {
7676
        !this.removed && this.node.parentNode.appendChild(this.node);
7677
        this.paper && this.paper.top != this && R._tofront(this, this.paper);
7678
        return this;
7679
    };
7680
    elproto.toBack = function () {
7681
        if (this.removed) {
7682
            return this;
7683
        }
7684
        if (this.node.parentNode.firstChild != this.node) {
7685
            this.node.parentNode.insertBefore(this.node, this.node.parentNode.firstChild);
7686
            R._toback(this, this.paper);
7687
        }
7688
        return this;
7689
    };
7690
    elproto.insertAfter = function (element) {
7691
        if (this.removed) {
7692
            return this;
7693
        }
7694
        if (element.constructor == R.st.constructor) {
7695
            element = element[element.length - 1];
7696
        }
7697
        if (element.node.nextSibling) {
7698
            element.node.parentNode.insertBefore(this.node, element.node.nextSibling);
7699
        } else {
7700
            element.node.parentNode.appendChild(this.node);
7701
        }
7702
        R._insertafter(this, element, this.paper);
7703
        return this;
7704
    };
7705
    elproto.insertBefore = function (element) {
7706
        if (this.removed) {
7707
            return this;
7708
        }
7709
        if (element.constructor == R.st.constructor) {
7710
            element = element[0];
7711
        }
7712
        element.node.parentNode.insertBefore(this.node, element.node);
7713
        R._insertbefore(this, element, this.paper);
7714
        return this;
7715
    };
7716
    elproto.blur = function (size) {
7717
        var s = this.node.runtimeStyle,
7718
            f = s.filter;
7719
        f = f.replace(blurregexp, E);
7720
        if (+size !== 0) {
7721
            this.attrs.blur = size;
7722
            s.filter = f + S + ms + ".Blur(pixelradius=" + (+size || 1.5) + ")";
7723
            s.margin = R.format("-{0}px 0 0 -{0}px", round(+size || 1.5));
7724
        } else {
7725
            s.filter = f;
7726
            s.margin = 0;
7727
            delete this.attrs.blur;
7728
        }
7729
        return this;
7730
    };
7731

7732
    R._engine.path = function (pathString, vml) {
7733
        var el = createNode("shape");
7734
        el.style.cssText = cssDot;
7735
        el.coordsize = zoom + S + zoom;
7736
        el.coordorigin = vml.coordorigin;
7737
        var p = new Element(el, vml),
7738
            attr = {fill: "none", stroke: "#000"};
7739
        pathString && (attr.path = pathString);
7740
        p.type = "path";
7741
        p.path = [];
7742
        p.Path = E;
7743
        setFillAndStroke(p, attr);
7744
        vml.canvas && vml.canvas.appendChild(el);
7745
        var skew = createNode("skew");
7746
        skew.on = true;
7747
        el.appendChild(skew);
7748
        p.skew = skew;
7749
        p.transform(E);
7750
        return p;
7751
    };
7752
    R._engine.rect = function (vml, x, y, w, h, r) {
7753
        var path = R._rectPath(x, y, w, h, r),
7754
            res = vml.path(path),
7755
            a = res.attrs;
7756
        res.X = a.x = x;
7757
        res.Y = a.y = y;
7758
        res.W = a.width = w;
7759
        res.H = a.height = h;
7760
        a.r = r;
7761
        a.path = path;
7762
        res.type = "rect";
7763
        return res;
7764
    };
7765
    R._engine.ellipse = function (vml, x, y, rx, ry) {
7766
        var res = vml.path(),
7767
            a = res.attrs;
7768
        res.X = x - rx;
7769
        res.Y = y - ry;
7770
        res.W = rx * 2;
7771
        res.H = ry * 2;
7772
        res.type = "ellipse";
7773
        setFillAndStroke(res, {
7774
            cx: x,
7775
            cy: y,
7776
            rx: rx,
7777
            ry: ry
7778
        });
7779
        return res;
7780
    };
7781
    R._engine.circle = function (vml, x, y, r) {
7782
        var res = vml.path(),
7783
            a = res.attrs;
7784
        res.X = x - r;
7785
        res.Y = y - r;
7786
        res.W = res.H = r * 2;
7787
        res.type = "circle";
7788
        setFillAndStroke(res, {
7789
            cx: x,
7790
            cy: y,
7791
            r: r
7792
        });
7793
        return res;
7794
    };
7795
    R._engine.image = function (vml, src, x, y, w, h) {
7796
        var path = R._rectPath(x, y, w, h),
7797
            res = vml.path(path).attr({stroke: "none"}),
7798
            a = res.attrs,
7799
            node = res.node,
7800
            fill = node.getElementsByTagName(fillString)[0];
7801
        a.src = src;
7802
        res.X = a.x = x;
7803
        res.Y = a.y = y;
7804
        res.W = a.width = w;
7805
        res.H = a.height = h;
7806
        a.path = path;
7807
        res.type = "image";
7808
        fill.parentNode == node && node.removeChild(fill);
7809
        fill.rotate = true;
7810
        fill.src = src;
7811
        fill.type = "tile";
7812
        res._.fillpos = [x, y];
7813
        res._.fillsize = [w, h];
7814
        node.appendChild(fill);
7815
        setCoords(res, 1, 1, 0, 0, 0);
7816
        return res;
7817
    };
7818
    R._engine.text = function (vml, x, y, text) {
7819
        var el = createNode("shape"),
7820
            path = createNode("path"),
7821
            o = createNode("textpath");
7822
        x = x || 0;
7823
        y = y || 0;
7824
        text = text || "";
7825
        path.v = R.format("m{0},{1}l{2},{1}", round(x * zoom), round(y * zoom), round(x * zoom) + 1);
7826
        path.textpathok = true;
7827
        o.string = Str(text);
7828
        o.on = true;
7829
        el.style.cssText = cssDot;
7830
        el.coordsize = zoom + S + zoom;
7831
        el.coordorigin = "0 0";
7832
        var p = new Element(el, vml),
7833
            attr = {
7834
                fill: "#000",
7835
                stroke: "none",
7836
                font: R._availableAttrs.font,
7837
                text: text
7838
            };
7839
        p.shape = el;
7840
        p.path = path;
7841
        p.textpath = o;
7842
        p.type = "text";
7843
        p.attrs.text = Str(text);
7844
        p.attrs.x = x;
7845
        p.attrs.y = y;
7846
        p.attrs.w = 1;
7847
        p.attrs.h = 1;
7848
        setFillAndStroke(p, attr);
7849
        el.appendChild(o);
7850
        el.appendChild(path);
7851
        vml.canvas.appendChild(el);
7852
        var skew = createNode("skew");
7853
        skew.on = true;
7854
        el.appendChild(skew);
7855
        p.skew = skew;
7856
        p.transform(E);
7857
        return p;
7858
    };
7859
    R._engine.setSize = function (width, height) {
7860
        var cs = this.canvas.style;
7861
        this.width = width;
7862
        this.height = height;
7863
        width == +width && (width += "px");
7864
        height == +height && (height += "px");
7865
        cs.width = width;
7866
        cs.height = height;
7867
        cs.clip = "rect(0 " + width + " " + height + " 0)";
7868
        if (this._viewBox) {
7869
            R._engine.setViewBox.apply(this, this._viewBox);
7870
        }
7871
        return this;
7872
    };
7873
    R._engine.setViewBox = function (x, y, w, h, fit) {
7874
        R.eve("raphael.setViewBox", this, this._viewBox, [x, y, w, h, fit]);
7875
        var paperSize = this.getSize(),
7876
            width = paperSize.width,
7877
            height = paperSize.height,
7878
            H, W;
7879
        if (fit) {
7880
            H = height / h;
7881
            W = width / w;
7882
            if (w * H < width) {
7883
                x -= (width - w * H) / 2 / H;
7884
            }
7885
            if (h * W < height) {
7886
                y -= (height - h * W) / 2 / W;
7887
            }
7888
        }
7889
        this._viewBox = [x, y, w, h, !!fit];
7890
        this._viewBoxShift = {
7891
            dx: -x,
7892
            dy: -y,
7893
            scale: paperSize
7894
        };
7895
        this.forEach(function (el) {
7896
            el.transform("...");
7897
        });
7898
        return this;
7899
    };
7900
    var createNode;
7901
    R._engine.initWin = function (win) {
7902
            var doc = win.document;
7903
            if (doc.styleSheets.length < 31) {
7904
                doc.createStyleSheet().addRule(".rvml", "behavior:url(#default#VML)");
7905
            } else {
7906
                // no more room, add to the existing one
7907
                // http://msdn.microsoft.com/en-us/library/ms531194%28VS.85%29.aspx
7908
                doc.styleSheets[0].addRule(".rvml", "behavior:url(#default#VML)");
7909
            }
7910
            try {
7911
                !doc.namespaces.rvml && doc.namespaces.add("rvml", "urn:schemas-microsoft-com:vml");
7912
                createNode = function (tagName) {
7913
                    return doc.createElement('<rvml:' + tagName + ' class="rvml">');
7914
                };
7915
            } catch (e) {
7916
                createNode = function (tagName) {
7917
                    return doc.createElement('<' + tagName + ' xmlns="urn:schemas-microsoft.com:vml" class="rvml">');
7918
                };
7919
            }
7920
        };
7921
    R._engine.initWin(R._g.win);
7922
    R._engine.create = function () {
7923
        var con = R._getContainer.apply(0, arguments),
7924
            container = con.container,
7925
            height = con.height,
7926
            s,
7927
            width = con.width,
7928
            x = con.x,
7929
            y = con.y;
7930
        if (!container) {
7931
            throw new Error("VML container not found.");
7932
        }
7933
        var res = new R._Paper,
7934
            c = res.canvas = R._g.doc.createElement("div"),
7935
            cs = c.style;
7936
        x = x || 0;
7937
        y = y || 0;
7938
        width = width || 512;
7939
        height = height || 342;
7940
        res.width = width;
7941
        res.height = height;
7942
        width == +width && (width += "px");
7943
        height == +height && (height += "px");
7944
        res.coordsize = zoom * 1e3 + S + zoom * 1e3;
7945
        res.coordorigin = "0 0";
7946
        res.span = R._g.doc.createElement("span");
7947
        res.span.style.cssText = "position:absolute;left:-9999em;top:-9999em;padding:0;margin:0;line-height:1;";
7948
        c.appendChild(res.span);
7949
        cs.cssText = R.format("top:0;left:0;width:{0};height:{1};display:inline-block;position:relative;clip:rect(0 {0} {1} 0);overflow:hidden", width, height);
7950
        if (container == 1) {
7951
            R._g.doc.body.appendChild(c);
7952
            cs.left = x + "px";
7953
            cs.top = y + "px";
7954
            cs.position = "absolute";
7955
        } else {
7956
            if (container.firstChild) {
7957
                container.insertBefore(c, container.firstChild);
7958
            } else {
7959
                container.appendChild(c);
7960
            }
7961
        }
7962
        res.renderfix = function () {};
7963
        return res;
7964
    };
7965
    R.prototype.clear = function () {
7966
        R.eve("raphael.clear", this);
7967
        this.canvas.innerHTML = E;
7968
        this.span = R._g.doc.createElement("span");
7969
        this.span.style.cssText = "position:absolute;left:-9999em;top:-9999em;padding:0;margin:0;line-height:1;display:inline;";
7970
        this.canvas.appendChild(this.span);
7971
        this.bottom = this.top = null;
7972
    };
7973
    R.prototype.remove = function () {
7974
        R.eve("raphael.remove", this);
7975
        this.canvas.parentNode.removeChild(this.canvas);
7976
        for (var i in this) {
7977
            this[i] = typeof this[i] == "function" ? R._removedFactory(i) : null;
7978
        }
7979
        return true;
7980
    };
7981

7982
    var setproto = R.st;
7983
    for (var method in elproto) if (elproto[has](method) && !setproto[has](method)) {
7984
        setproto[method] = (function (methodname) {
7985
            return function () {
7986
                var arg = arguments;
7987
                return this.forEach(function (el) {
7988
                    el[methodname].apply(el, arg);
7989
                });
7990
            };
7991
        })(method);
7992
    }
7993
}).apply(exports, __WEBPACK_AMD_DEFINE_ARRAY__),
7994
				__WEBPACK_AMD_DEFINE_RESULT__ !== undefined && (module.exports = __WEBPACK_AMD_DEFINE_RESULT__));
7995

7996

7997
/***/ }),
7998

7999
/***/ "./node_modules/eve-raphael/eve.js":
8000
/*!*****************************************!*\
8001
  !*** ./node_modules/eve-raphael/eve.js ***!
8002
  \*****************************************/
8003
/*! no static exports found */
8004
/***/ (function(module, exports, __webpack_require__) {
8005

8006
var __WEBPACK_AMD_DEFINE_ARRAY__, __WEBPACK_AMD_DEFINE_RESULT__;// Copyright (c) 2013 Adobe Systems Incorporated. All rights reserved.
8007
// 
8008
// Licensed under the Apache License, Version 2.0 (the "License");
8009
// you may not use this file except in compliance with the License.
8010
// You may obtain a copy of the License at
8011
// 
8012
// http://www.apache.org/licenses/LICENSE-2.0
8013
// 
8014
// Unless required by applicable law or agreed to in writing, software
8015
// distributed under the License is distributed on an "AS IS" BASIS,
8016
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
8017
// See the License for the specific language governing permissions and
8018
// limitations under the License.
8019
// ┌────────────────────────────────────────────────────────────┐ \\
8020
// │ Eve 0.5.0 - JavaScript Events Library                      │ \\
8021
// ├────────────────────────────────────────────────────────────┤ \\
8022
// │ Author Dmitry Baranovskiy (http://dmitry.baranovskiy.com/) │ \\
8023
// └────────────────────────────────────────────────────────────┘ \\
8024

8025
(function (glob) {
8026
    var version = "0.5.0",
8027
        has = "hasOwnProperty",
8028
        separator = /[\.\/]/,
8029
        comaseparator = /\s*,\s*/,
8030
        wildcard = "*",
8031
        fun = function () {},
8032
        numsort = function (a, b) {
8033
            return a - b;
8034
        },
8035
        current_event,
8036
        stop,
8037
        events = {n: {}},
8038
        firstDefined = function () {
8039
            for (var i = 0, ii = this.length; i < ii; i++) {
8040
                if (typeof this[i] != "undefined") {
8041
                    return this[i];
8042
                }
8043
            }
8044
        },
8045
        lastDefined = function () {
8046
            var i = this.length;
8047
            while (--i) {
8048
                if (typeof this[i] != "undefined") {
8049
                    return this[i];
8050
                }
8051
            }
8052
        },
8053
        objtos = Object.prototype.toString,
8054
        Str = String,
8055
        isArray = Array.isArray || function (ar) {
8056
            return ar instanceof Array || objtos.call(ar) == "[object Array]";
8057
        };
8058
    /*\
8059
     * eve
8060
     [ method ]
8061

8062
     * Fires event with given `name`, given scope and other parameters.
8063

8064
     > Arguments
8065

8066
     - name (string) name of the *event*, dot (`.`) or slash (`/`) separated
8067
     - scope (object) context for the event handlers
8068
     - varargs (...) the rest of arguments will be sent to event handlers
8069

8070
     = (object) array of returned values from the listeners. Array has two methods `.firstDefined()` and `.lastDefined()` to get first or last not `undefined` value.
8071
    \*/
8072
        var eve = function (name, scope) {
8073
            var e = events,
8074
                oldstop = stop,
8075
                args = Array.prototype.slice.call(arguments, 2),
8076
                listeners = eve.listeners(name),
8077
                z = 0,
8078
                f = false,
8079
                l,
8080
                indexed = [],
8081
                queue = {},
8082
                out = [],
8083
                ce = current_event,
8084
                errors = [];
8085
            out.firstDefined = firstDefined;
8086
            out.lastDefined = lastDefined;
8087
            current_event = name;
8088
            stop = 0;
8089
            for (var i = 0, ii = listeners.length; i < ii; i++) if ("zIndex" in listeners[i]) {
8090
                indexed.push(listeners[i].zIndex);
8091
                if (listeners[i].zIndex < 0) {
8092
                    queue[listeners[i].zIndex] = listeners[i];
8093
                }
8094
            }
8095
            indexed.sort(numsort);
8096
            while (indexed[z] < 0) {
8097
                l = queue[indexed[z++]];
8098
                out.push(l.apply(scope, args));
8099
                if (stop) {
8100
                    stop = oldstop;
8101
                    return out;
8102
                }
8103
            }
8104
            for (i = 0; i < ii; i++) {
8105
                l = listeners[i];
8106
                if ("zIndex" in l) {
8107
                    if (l.zIndex == indexed[z]) {
8108
                        out.push(l.apply(scope, args));
8109
                        if (stop) {
8110
                            break;
8111
                        }
8112
                        do {
8113
                            z++;
8114
                            l = queue[indexed[z]];
8115
                            l && out.push(l.apply(scope, args));
8116
                            if (stop) {
8117
                                break;
8118
                            }
8119
                        } while (l)
8120
                    } else {
8121
                        queue[l.zIndex] = l;
8122
                    }
8123
                } else {
8124
                    out.push(l.apply(scope, args));
8125
                    if (stop) {
8126
                        break;
8127
                    }
8128
                }
8129
            }
8130
            stop = oldstop;
8131
            current_event = ce;
8132
            return out;
8133
        };
8134
        // Undocumented. Debug only.
8135
        eve._events = events;
8136
    /*\
8137
     * eve.listeners
8138
     [ method ]
8139

8140
     * Internal method which gives you array of all event handlers that will be triggered by the given `name`.
8141

8142
     > Arguments
8143

8144
     - name (string) name of the event, dot (`.`) or slash (`/`) separated
8145

8146
     = (array) array of event handlers
8147
    \*/
8148
    eve.listeners = function (name) {
8149
        var names = isArray(name) ? name : name.split(separator),
8150
            e = events,
8151
            item,
8152
            items,
8153
            k,
8154
            i,
8155
            ii,
8156
            j,
8157
            jj,
8158
            nes,
8159
            es = [e],
8160
            out = [];
8161
        for (i = 0, ii = names.length; i < ii; i++) {
8162
            nes = [];
8163
            for (j = 0, jj = es.length; j < jj; j++) {
8164
                e = es[j].n;
8165
                items = [e[names[i]], e[wildcard]];
8166
                k = 2;
8167
                while (k--) {
8168
                    item = items[k];
8169
                    if (item) {
8170
                        nes.push(item);
8171
                        out = out.concat(item.f || []);
8172
                    }
8173
                }
8174
            }
8175
            es = nes;
8176
        }
8177
        return out;
8178
    };
8179
    /*\
8180
     * eve.separator
8181
     [ method ]
8182

8183
     * If for some reasons you don’t like default separators (`.` or `/`) you can specify yours
8184
     * here. Be aware that if you pass a string longer than one character it will be treated as
8185
     * a list of characters.
8186

8187
     - separator (string) new separator. Empty string resets to default: `.` or `/`.
8188
    \*/
8189
    eve.separator = function (sep) {
8190
        if (sep) {
8191
            sep = Str(sep).replace(/(?=[\.\^\]\[\-])/g, "\\");
8192
            sep = "[" + sep + "]";
8193
            separator = new RegExp(sep);
8194
        } else {
8195
            separator = /[\.\/]/;
8196
        }
8197
    };
8198
    /*\
8199
     * eve.on
8200
     [ method ]
8201
     **
8202
     * Binds given event handler with a given name. You can use wildcards “`*`” for the names:
8203
     | eve.on("*.under.*", f);
8204
     | eve("mouse.under.floor"); // triggers f
8205
     * Use @eve to trigger the listener.
8206
     **
8207
     - name (string) name of the event, dot (`.`) or slash (`/`) separated, with optional wildcards
8208
     - f (function) event handler function
8209
     **
8210
     - name (array) if you don’t want to use separators, you can use array of strings
8211
     - f (function) event handler function
8212
     **
8213
     = (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. 
8214
     > Example:
8215
     | eve.on("mouse", eatIt)(2);
8216
     | eve.on("mouse", scream);
8217
     | eve.on("mouse", catchIt)(1);
8218
     * This will ensure that `catchIt` function will be called before `eatIt`.
8219
     *
8220
     * If you want to put your handler before non-indexed handlers, specify a negative value.
8221
     * 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”.
8222
    \*/
8223
    eve.on = function (name, f) {
8224
        if (typeof f != "function") {
8225
            return function () {};
8226
        }
8227
        var names = isArray(name) ? (isArray(name[0]) ? name : [name]) : Str(name).split(comaseparator);
8228
        for (var i = 0, ii = names.length; i < ii; i++) {
8229
            (function (name) {
8230
                var names = isArray(name) ? name : Str(name).split(separator),
8231
                    e = events,
8232
                    exist;
8233
                for (var i = 0, ii = names.length; i < ii; i++) {
8234
                    e = e.n;
8235
                    e = e.hasOwnProperty(names[i]) && e[names[i]] || (e[names[i]] = {n: {}});
8236
                }
8237
                e.f = e.f || [];
8238
                for (i = 0, ii = e.f.length; i < ii; i++) if (e.f[i] == f) {
8239
                    exist = true;
8240
                    break;
8241
                }
8242
                !exist && e.f.push(f);
8243
            }(names[i]));
8244
        }
8245
        return function (zIndex) {
8246
            if (+zIndex == +zIndex) {
8247
                f.zIndex = +zIndex;
8248
            }
8249
        };
8250
    };
8251
    /*\
8252
     * eve.f
8253
     [ method ]
8254
     **
8255
     * Returns function that will fire given event with optional arguments.
8256
     * Arguments that will be passed to the result function will be also
8257
     * concated to the list of final arguments.
8258
     | el.onclick = eve.f("click", 1, 2);
8259
     | eve.on("click", function (a, b, c) {
8260
     |     console.log(a, b, c); // 1, 2, [event object]
8261
     | });
8262
     > Arguments
8263
     - event (string) event name
8264
     - varargs (…) and any other arguments
8265
     = (function) possible event handler function
8266
    \*/
8267
    eve.f = function (event) {
8268
        var attrs = [].slice.call(arguments, 1);
8269
        return function () {
8270
            eve.apply(null, [event, null].concat(attrs).concat([].slice.call(arguments, 0)));
8271
        };
8272
    };
8273
    /*\
8274
     * eve.stop
8275
     [ method ]
8276
     **
8277
     * Is used inside an event handler to stop the event, preventing any subsequent listeners from firing.
8278
    \*/
8279
    eve.stop = function () {
8280
        stop = 1;
8281
    };
8282
    /*\
8283
     * eve.nt
8284
     [ method ]
8285
     **
8286
     * Could be used inside event handler to figure out actual name of the event.
8287
     **
8288
     > Arguments
8289
     **
8290
     - subname (string) #optional subname of the event
8291
     **
8292
     = (string) name of the event, if `subname` is not specified
8293
     * or
8294
     = (boolean) `true`, if current event’s name contains `subname`
8295
    \*/
8296
    eve.nt = function (subname) {
8297
        var cur = isArray(current_event) ? current_event.join(".") : current_event;
8298
        if (subname) {
8299
            return new RegExp("(?:\\.|\\/|^)" + subname + "(?:\\.|\\/|$)").test(cur);
8300
        }
8301
        return cur;
8302
    };
8303
    /*\
8304
     * eve.nts
8305
     [ method ]
8306
     **
8307
     * Could be used inside event handler to figure out actual name of the event.
8308
     **
8309
     **
8310
     = (array) names of the event
8311
    \*/
8312
    eve.nts = function () {
8313
        return isArray(current_event) ? current_event : current_event.split(separator);
8314
    };
8315
    /*\
8316
     * eve.off
8317
     [ method ]
8318
     **
8319
     * Removes given function from the list of event listeners assigned to given name.
8320
     * If no arguments specified all the events will be cleared.
8321
     **
8322
     > Arguments
8323
     **
8324
     - name (string) name of the event, dot (`.`) or slash (`/`) separated, with optional wildcards
8325
     - f (function) event handler function
8326
    \*/
8327
    /*\
8328
     * eve.unbind
8329
     [ method ]
8330
     **
8331
     * See @eve.off
8332
    \*/
8333
    eve.off = eve.unbind = function (name, f) {
8334
        if (!name) {
8335
            eve._events = events = {n: {}};
8336
            return;
8337
        }
8338
        var names = isArray(name) ? (isArray(name[0]) ? name : [name]) : Str(name).split(comaseparator);
8339
        if (names.length > 1) {
8340
            for (var i = 0, ii = names.length; i < ii; i++) {
8341
                eve.off(names[i], f);
8342
            }
8343
            return;
8344
        }
8345
        names = isArray(name) ? name : Str(name).split(separator);
8346
        var e,
8347
            key,
8348
            splice,
8349
            i, ii, j, jj,
8350
            cur = [events];
8351
        for (i = 0, ii = names.length; i < ii; i++) {
8352
            for (j = 0; j < cur.length; j += splice.length - 2) {
8353
                splice = [j, 1];
8354
                e = cur[j].n;
8355
                if (names[i] != wildcard) {
8356
                    if (e[names[i]]) {
8357
                        splice.push(e[names[i]]);
8358
                    }
8359
                } else {
8360
                    for (key in e) if (e[has](key)) {
8361
                        splice.push(e[key]);
8362
                    }
8363
                }
8364
                cur.splice.apply(cur, splice);
8365
            }
8366
        }
8367
        for (i = 0, ii = cur.length; i < ii; i++) {
8368
            e = cur[i];
8369
            while (e.n) {
8370
                if (f) {
8371
                    if (e.f) {
8372
                        for (j = 0, jj = e.f.length; j < jj; j++) if (e.f[j] == f) {
8373
                            e.f.splice(j, 1);
8374
                            break;
8375
                        }
8376
                        !e.f.length && delete e.f;
8377
                    }
8378
                    for (key in e.n) if (e.n[has](key) && e.n[key].f) {
8379
                        var funcs = e.n[key].f;
8380
                        for (j = 0, jj = funcs.length; j < jj; j++) if (funcs[j] == f) {
8381
                            funcs.splice(j, 1);
8382
                            break;
8383
                        }
8384
                        !funcs.length && delete e.n[key].f;
8385
                    }
8386
                } else {
8387
                    delete e.f;
8388
                    for (key in e.n) if (e.n[has](key) && e.n[key].f) {
8389
                        delete e.n[key].f;
8390
                    }
8391
                }
8392
                e = e.n;
8393
            }
8394
        }
8395
    };
8396
    /*\
8397
     * eve.once
8398
     [ method ]
8399
     **
8400
     * Binds given event handler with a given name to only run once then unbind itself.
8401
     | eve.once("login", f);
8402
     | eve("login"); // triggers f
8403
     | eve("login"); // no listeners
8404
     * Use @eve to trigger the listener.
8405
     **
8406
     > Arguments
8407
     **
8408
     - name (string) name of the event, dot (`.`) or slash (`/`) separated, with optional wildcards
8409
     - f (function) event handler function
8410
     **
8411
     = (function) same return function as @eve.on
8412
    \*/
8413
    eve.once = function (name, f) {
8414
        var f2 = function () {
8415
            eve.off(name, f2);
8416
            return f.apply(this, arguments);
8417
        };
8418
        return eve.on(name, f2);
8419
    };
8420
    /*\
8421
     * eve.version
8422
     [ property (string) ]
8423
     **
8424
     * Current version of the library.
8425
    \*/
8426
    eve.version = version;
8427
    eve.toString = function () {
8428
        return "You are running Eve " + version;
8429
    };
8430
    ( true && module.exports) ? (module.exports = eve) : ( true ? (!(__WEBPACK_AMD_DEFINE_ARRAY__ = [], __WEBPACK_AMD_DEFINE_RESULT__ = (function() { return eve; }).apply(exports, __WEBPACK_AMD_DEFINE_ARRAY__),
8431
				__WEBPACK_AMD_DEFINE_RESULT__ !== undefined && (module.exports = __WEBPACK_AMD_DEFINE_RESULT__))) : (undefined));
8432
})(this);
8433

8434

8435
/***/ })
8436

8437
/******/ });
8438
});

Использование cookies

Мы используем файлы cookie в соответствии с Политикой конфиденциальности и Политикой использования cookies.

Нажимая кнопку «Принимаю», Вы даете АО «СберТех» согласие на обработку Ваших персональных данных в целях совершенствования нашего веб-сайта и Сервиса GitVerse, а также повышения удобства их использования.

Запретить использование cookies Вы можете самостоятельно в настройках Вашего браузера.