--- a/src/hdalab/static/hdalab/lib/paper.js Fri Jul 18 13:29:53 2014 +0200
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,12218 +0,0 @@
-/*!
- * Paper.js v0.9.15 - The Swiss Army Knife of Vector Graphics Scripting.
- * http://paperjs.org/
- *
- * Copyright (c) 2011 - 2013, Juerg Lehni & Jonathan Puckey
- * http://lehni.org/ & http://jonathanpuckey.com/
- *
- * Distributed under the MIT license. See LICENSE file for details.
- *
- * All rights reserved.
- *
- * Date: Sun Dec 1 23:54:52 2013 +0100
- *
- ***
- *
- * straps.js - Class inheritance library with support for bean-style accessors
- *
- * Copyright (c) 2006 - 2013 Juerg Lehni
- * http://lehni.org/
- *
- * Distributed under the MIT license.
- *
- ***
- *
- * acorn.js
- * http://marijnhaverbeke.nl/acorn/
- *
- * Acorn is a tiny, fast JavaScript parser written in JavaScript,
- * created by Marijn Haverbeke and released under an MIT license.
- *
- */
-
-var paper = new function(undefined) {
-
-var Base = new function() {
- var hidden = /^(statics|generics|preserve|enumerable|prototype|toString|valueOf)$/,
- slice = [].slice,
-
- forEach = [].forEach || function(iter, bind) {
- for (var i = 0, l = this.length; i < l; i++)
- iter.call(bind, this[i], i, this);
- },
-
- forIn = function(iter, bind) {
- for (var i in this)
- if (this.hasOwnProperty(i))
- iter.call(bind, this[i], i, this);
- },
-
- create = Object.create || function(proto) {
- return { __proto__: proto };
- },
-
- describe = Object.getOwnPropertyDescriptor || function(obj, name) {
- var get = obj.__lookupGetter__ && obj.__lookupGetter__(name);
- return get
- ? { get: get, set: obj.__lookupSetter__(name),
- enumerable: true, configurable: true }
- : obj.hasOwnProperty(name)
- ? { value: obj[name], enumerable: true,
- configurable: true, writable: true }
- : null;
- },
-
- _define = Object.defineProperty || function(obj, name, desc) {
- if ((desc.get || desc.set) && obj.__defineGetter__) {
- if (desc.get)
- obj.__defineGetter__(name, desc.get);
- if (desc.set)
- obj.__defineSetter__(name, desc.set);
- } else {
- obj[name] = desc.value;
- }
- return obj;
- },
-
- define = function(obj, name, desc) {
- delete obj[name];
- return _define(obj, name, desc);
- };
-
- function inject(dest, src, enumerable, base, preserve, generics) {
- var beans;
-
- function field(name, val, dontCheck, generics) {
- var val = val || (val = describe(src, name))
- && (val.get ? val : val.value);
- if (typeof val === 'string' && val[0] === '#')
- val = dest[val.substring(1)] || val;
- var isFunc = typeof val === 'function',
- res = val,
- prev = preserve || isFunc
- ? (val && val.get ? name in dest : dest[name]) : null,
- bean;
- if ((dontCheck || val !== undefined && src.hasOwnProperty(name))
- && (!preserve || !prev)) {
- if (isFunc && prev)
- val.base = prev;
- if (isFunc && beans && val.length === 0
- && (bean = name.match(/^(get|is)(([A-Z])(.*))$/)))
- beans.push([ bean[3].toLowerCase() + bean[4], bean[2] ]);
- if (!res || isFunc || !res.get || typeof res.get !== 'function'
- || res.get.length !== 0)
- res = { value: res, writable: true };
- if ((describe(dest, name)
- || { configurable: true }).configurable) {
- res.configurable = true;
- res.enumerable = enumerable;
- }
- define(dest, name, res);
- }
- if (generics && isFunc && (!preserve || !generics[name])) {
- generics[name] = function(bind) {
- return bind && dest[name].apply(bind,
- slice.call(arguments, 1));
- };
- }
- }
- if (src) {
- beans = [];
- for (var name in src)
- if (src.hasOwnProperty(name) && !hidden.test(name))
- field(name, null, true, generics);
- field('toString');
- field('valueOf');
- for (var i = 0, l = beans.length; i < l; i++) {
- var bean = beans[i],
- part = bean[1];
- field(bean[0], {
- get: dest['get' + part] || dest['is' + part],
- set: dest['set' + part]
- }, true);
- }
- }
- return dest;
- }
-
- function each(obj, iter, bind) {
- if (obj)
- ('length' in obj && !obj.getLength
- && typeof obj.length === 'number'
- ? forEach
- : forIn).call(obj, iter, bind = bind || obj);
- return bind;
- }
-
- function copy(dest, source) {
- for (var i in source)
- if (source.hasOwnProperty(i))
- dest[i] = source[i];
- return dest;
- }
-
- function clone(obj) {
- return copy(new obj.constructor(), obj);
- }
-
- return inject(function Base() {
- for (var i = 0, l = arguments.length; i < l; i++)
- copy(this, arguments[i]);
- }, {
- inject: function(src) {
- if (src) {
- var proto = this.prototype,
- base = Object.getPrototypeOf(proto).constructor,
- statics = src.statics === true ? src : src.statics;
- if (statics != src)
- inject(proto, src, src.enumerable, base && base.prototype,
- src.preserve, src.generics && this);
- inject(this, statics, true, base, src.preserve);
- }
- for (var i = 1, l = arguments.length; i < l; i++)
- this.inject(arguments[i]);
- return this;
- },
-
- extend: function() {
- var base = this,
- ctor;
- for (var i = 0, l = arguments.length; i < l; i++)
- if (ctor = arguments[i].initialize)
- break;
- ctor = ctor || function() {
- base.apply(this, arguments);
- };
- ctor.prototype = create(this.prototype);
- define(ctor.prototype, 'constructor',
- { value: ctor, writable: true, configurable: true });
- inject(ctor, this, true);
- return arguments.length ? this.inject.apply(ctor, arguments) : ctor;
- }
- }, true).inject({
- inject: function() {
- for (var i = 0, l = arguments.length; i < l; i++)
- inject(this, arguments[i], arguments[i].enumerable);
- return this;
- },
-
- extend: function() {
- var res = create(this);
- return res.inject.apply(res, arguments);
- },
-
- each: function(iter, bind) {
- return each(this, iter, bind);
- },
-
- clone: function() {
- return new this.constructor(this);
- },
-
- statics: {
- each: each,
- create: create,
- define: define,
- describe: describe,
- copy: copy,
-
- clone: function(obj) {
- return copy(new obj.constructor(), obj);
- },
-
- isPlainObject: function(obj) {
- var ctor = obj != null && obj.constructor;
- return ctor && (ctor === Object || ctor === Base
- || ctor.name === 'Object');
- },
-
- pick: function() {
- for (var i = 0, l = arguments.length; i < l; i++)
- if (arguments[i] !== undefined)
- return arguments[i];
- return null;
- }
- }
- });
-};
-
-if (typeof module !== 'undefined')
- module.exports = Base;
-
-Base.inject({
- generics: true,
-
- toString: function() {
- return this._id != null
- ? (this._class || 'Object') + (this._name
- ? " '" + this._name + "'"
- : ' @' + this._id)
- : '{ ' + Base.each(this, function(value, key) {
- if (!/^_/.test(key)) {
- var type = typeof value;
- this.push(key + ': ' + (type === 'number'
- ? Formatter.instance.number(value)
- : type === 'string' ? "'" + value + "'" : value));
- }
- }, []).join(', ') + ' }';
- },
-
- exportJSON: function(options) {
- return Base.exportJSON(this, options);
- },
-
- toJSON: function() {
- return Base.serialize(this);
- },
-
- _set: function(props, exclude) {
- if (props && Base.isPlainObject(props)) {
- var orig = props._filtering || props;
- for (var key in orig) {
- if (key in this && orig.hasOwnProperty(key)
- && (!exclude || !exclude[key])) {
- var value = props[key];
- if (value !== undefined)
- this[key] = value;
- }
- }
- return true;
- }
- },
-
- statics: {
-
- exports: {},
-
- extend: function extend() {
- var res = extend.base.apply(this, arguments),
- name = res.prototype._class;
- if (name && !Base.exports[name])
- Base.exports[name] = res;
- return res;
- },
-
- equals: function(obj1, obj2) {
- function checkKeys(o1, o2) {
- for (var i in o1)
- if (o1.hasOwnProperty(i) && !o2.hasOwnProperty(i))
- return false;
- return true;
- }
- if (obj1 === obj2)
- return true;
- if (obj1 && obj1.equals)
- return obj1.equals(obj2);
- if (obj2 && obj2.equals)
- return obj2.equals(obj1);
- if (Array.isArray(obj1) && Array.isArray(obj2)) {
- if (obj1.length !== obj2.length)
- return false;
- for (var i = 0, l = obj1.length; i < l; i++) {
- if (!Base.equals(obj1[i], obj2[i]))
- return false;
- }
- return true;
- }
- if (obj1 && typeof obj1 === 'object'
- && obj2 && typeof obj2 === 'object') {
- if (!checkKeys(obj1, obj2) || !checkKeys(obj2, obj1))
- return false;
- for (var i in obj1) {
- if (obj1.hasOwnProperty(i) && !Base.equals(obj1[i], obj2[i]))
- return false;
- }
- return true;
- }
- return false;
- },
-
- read: function(list, start, length, options) {
- if (this === Base) {
- var value = this.peek(list, start);
- list._index++;
- list.__read = 1;
- return value;
- }
- var proto = this.prototype,
- readIndex = proto._readIndex,
- index = start || readIndex && list._index || 0;
- if (!length)
- length = list.length - index;
- var obj = list[index];
- if (obj instanceof this
- || options && options.readNull && obj == null && length <= 1) {
- if (readIndex)
- list._index = index + 1;
- return obj && options && options.clone ? obj.clone() : obj;
- }
- obj = Base.create(this.prototype);
- if (readIndex)
- obj.__read = true;
- if (options)
- obj.__options = options;
- obj = obj.initialize.apply(obj, index > 0 || length < list.length
- ? Array.prototype.slice.call(list, index, index + length)
- : list) || obj;
- if (readIndex) {
- list._index = index + obj.__read;
- list.__read = obj.__read;
- delete obj.__read;
- if (options)
- delete obj.__options;
- }
- return obj;
- },
-
- peek: function(list, start) {
- return list[list._index = start || list._index || 0];
- },
-
- readAll: function(list, start, options) {
- var res = [], entry;
- for (var i = start || 0, l = list.length; i < l; i++) {
- res.push(Array.isArray(entry = list[i])
- ? this.read(entry, 0, 0, options)
- : this.read(list, i, 1, options));
- }
- return res;
- },
-
- readNamed: function(list, name, start, length, options) {
- var value = this.getNamed(list, name),
- hasObject = value !== undefined;
- if (hasObject) {
- var filtered = list._filtered;
- if (!filtered) {
- filtered = list._filtered = Base.create(list[0]);
- filtered._filtering = list[0];
- }
- filtered[name] = undefined;
- }
- return this.read(hasObject ? [value] : list, start, length, options);
- },
-
- getNamed: function(list, name) {
- var arg = list[0];
- if (list._hasObject === undefined)
- list._hasObject = list.length === 1 && Base.isPlainObject(arg);
- if (list._hasObject)
- return name ? arg[name] : list._filtered || arg;
- },
-
- hasNamed: function(list, name) {
- return !!this.getNamed(list, name);
- },
-
- isPlainValue: function(obj) {
- return this.isPlainObject(obj) || Array.isArray(obj);
- },
-
- serialize: function(obj, options, compact, dictionary) {
- options = options || {};
-
- var root = !dictionary,
- res;
- if (root) {
- options.formatter = new Formatter(options.precision);
- dictionary = {
- length: 0,
- definitions: {},
- references: {},
- add: function(item, create) {
- var id = '#' + item._id,
- ref = this.references[id];
- if (!ref) {
- this.length++;
- var res = create.call(item),
- name = item._class;
- if (name && res[0] !== name)
- res.unshift(name);
- this.definitions[id] = res;
- ref = this.references[id] = [id];
- }
- return ref;
- }
- };
- }
- if (obj && obj._serialize) {
- res = obj._serialize(options, dictionary);
- var name = obj._class;
- if (name && !compact && !res._compact && res[0] !== name)
- res.unshift(name);
- } else if (Array.isArray(obj)) {
- res = [];
- for (var i = 0, l = obj.length; i < l; i++)
- res[i] = Base.serialize(obj[i], options, compact,
- dictionary);
- if (compact)
- res._compact = true;
- } else if (Base.isPlainObject(obj)) {
- res = {};
- for (var i in obj)
- if (obj.hasOwnProperty(i))
- res[i] = Base.serialize(obj[i], options, compact,
- dictionary);
- } else if (typeof obj === 'number') {
- res = options.formatter.number(obj, options.precision);
- } else {
- res = obj;
- }
- return root && dictionary.length > 0
- ? [['dictionary', dictionary.definitions], res]
- : res;
- },
-
- deserialize: function(json, create, _data) {
- var res = json;
- _data = _data || {};
- if (Array.isArray(json)) {
- var type = json[0],
- isDictionary = type === 'dictionary';
- if (!isDictionary) {
- if (_data.dictionary && json.length == 1 && /^#/.test(type))
- return _data.dictionary[type];
- type = Base.exports[type];
- }
- res = [];
- for (var i = type ? 1 : 0, l = json.length; i < l; i++)
- res.push(Base.deserialize(json[i], create, _data));
- if (isDictionary) {
- _data.dictionary = res[0];
- } else if (type) {
- var args = res;
- if (create) {
- res = create(type, args);
- } else {
- res = Base.create(type.prototype);
- type.apply(res, args);
- }
- }
- } else if (Base.isPlainObject(json)) {
- res = {};
- for (var key in json)
- res[key] = Base.deserialize(json[key], create, _data);
- }
- return res;
- },
-
- exportJSON: function(obj, options) {
- return JSON.stringify(Base.serialize(obj, options));
- },
-
- importJSON: function(json, target) {
- return Base.deserialize(
- typeof json === 'string' ? JSON.parse(json) : json,
- function(type, args) {
- var obj = target && target.constructor === type
- ? target
- : Base.create(type.prototype),
- isTarget = obj === target;
- if (args.length === 1 && obj instanceof Item
- && (!(obj instanceof Layer) || isTarget)) {
- var arg = args[0];
- if (Base.isPlainObject(arg))
- arg.insert = false;
- }
- type.apply(obj, args);
- if (isTarget)
- target = null;
- return obj;
- });
- },
-
- splice: function(list, items, index, remove) {
- var amount = items && items.length,
- append = index === undefined;
- index = append ? list.length : index;
- if (index > list.length)
- index = list.length;
- for (var i = 0; i < amount; i++)
- items[i]._index = index + i;
- if (append) {
- list.push.apply(list, items);
- return [];
- } else {
- var args = [index, remove];
- if (items)
- args.push.apply(args, items);
- var removed = list.splice.apply(list, args);
- for (var i = 0, l = removed.length; i < l; i++)
- delete removed[i]._index;
- for (var i = index + amount, l = list.length; i < l; i++)
- list[i]._index = i;
- return removed;
- }
- },
-
- capitalize: function(str) {
- return str.replace(/\b[a-z]/g, function(match) {
- return match.toUpperCase();
- });
- },
-
- camelize: function(str) {
- return str.replace(/-(.)/g, function(all, chr) {
- return chr.toUpperCase();
- });
- },
-
- hyphenate: function(str) {
- return str.replace(/([a-z])([A-Z])/g, '$1-$2').toLowerCase();
- }
- }
-});
-
-var Callback = {
- attach: function(type, func) {
- if (typeof type !== 'string') {
- Base.each(type, function(value, key) {
- this.attach(key, value);
- }, this);
- return;
- }
- var entry = this._eventTypes[type];
- if (entry) {
- var handlers = this._handlers = this._handlers || {};
- handlers = handlers[type] = handlers[type] || [];
- if (handlers.indexOf(func) == -1) {
- handlers.push(func);
- if (entry.install && handlers.length == 1)
- entry.install.call(this, type);
- }
- }
- },
-
- detach: function(type, func) {
- if (typeof type !== 'string') {
- Base.each(type, function(value, key) {
- this.detach(key, value);
- }, this);
- return;
- }
- var entry = this._eventTypes[type],
- handlers = this._handlers && this._handlers[type],
- index;
- if (entry && handlers) {
- if (!func || (index = handlers.indexOf(func)) != -1
- && handlers.length == 1) {
- if (entry.uninstall)
- entry.uninstall.call(this, type);
- delete this._handlers[type];
- } else if (index != -1) {
- handlers.splice(index, 1);
- }
- }
- },
-
- once: function(type, func) {
- this.attach(type, function() {
- func.apply(this, arguments);
- this.detach(type, func);
- });
- },
-
- fire: function(type, event) {
- var handlers = this._handlers && this._handlers[type];
- if (!handlers)
- return false;
- var args = [].slice.call(arguments, 1),
- PaperScript = paper.PaperScript,
- handleException = PaperScript && PaperScript.handleException,
- that = this;
-
- function callHandlers() {
- for (var i in handlers) {
- if (handlers[i].apply(that, args) === false
- && event && event.stop)
- event.stop();
- }
- }
-
- if (handleException) {
- try {
- callHandlers();
- } catch (e) {
- handleException(e);
- }
- } else {
- callHandlers();
- }
- return true;
- },
-
- responds: function(type) {
- return !!(this._handlers && this._handlers[type]);
- },
-
- on: '#attach',
- off: '#detach',
- trigger: '#fire',
-
- statics: {
- inject: function inject() {
- for (var i = 0, l = arguments.length; i < l; i++) {
- var src = arguments[i],
- events = src._events;
- if (events) {
- var types = {};
- Base.each(events, function(entry, key) {
- var isString = typeof entry === 'string',
- name = isString ? entry : key,
- part = Base.capitalize(name),
- type = name.substring(2).toLowerCase();
- types[type] = isString ? {} : entry;
- name = '_' + name;
- src['get' + part] = function() {
- return this[name];
- };
- src['set' + part] = function(func) {
- if (func) {
- this.attach(type, func);
- } else if (this[name]) {
- this.detach(type, this[name]);
- }
- this[name] = func;
- };
- });
- src._eventTypes = types;
- }
- inject.base.call(this, src);
- }
- return this;
- }
- }
-};
-
-var PaperScope = Base.extend({
- _class: 'PaperScope',
-
- initialize: function PaperScope(script) {
- paper = this;
- this.project = null;
- this.projects = [];
- this.tools = [];
- this.palettes = [];
- this._id = script && (script.getAttribute('id') || script.src)
- || ('paperscope-' + (PaperScope._id++));
- if (script)
- script.setAttribute('id', this._id);
- PaperScope._scopes[this._id] = this;
- if (!this.support) {
- var ctx = CanvasProvider.getContext(1, 1);
- PaperScope.prototype.support = {
- nativeDash: 'setLineDash' in ctx || 'mozDash' in ctx,
- nativeBlendModes: BlendMode.nativeModes
- };
- CanvasProvider.release(ctx);
- }
- },
-
- version: '0.9.15',
-
- getView: function() {
- return this.project && this.project.view;
- },
-
- getTool: function() {
- if (!this._tool)
- this._tool = new Tool();
- return this._tool;
- },
-
- getPaper: function() {
- return this;
- },
-
- evaluate: function(code) {
- var res = paper.PaperScript.evaluate(code, this);
- View.updateFocus();
- return res;
- },
-
- install: function(scope) {
- var that = this;
- Base.each(['project', 'view', 'tool'], function(key) {
- Base.define(scope, key, {
- configurable: true,
- get: function() {
- return that[key];
- }
- });
- });
- for (var key in this) {
- if (!/^(version|_id)/.test(key))
- scope[key] = this[key];
- }
- },
-
- setup: function(canvas) {
- paper = this;
- this.project = new Project(canvas);
- return this;
- },
-
- activate: function() {
- paper = this;
- },
-
- clear: function() {
- for (var i = this.projects.length - 1; i >= 0; i--)
- this.projects[i].remove();
- for (var i = this.tools.length - 1; i >= 0; i--)
- this.tools[i].remove();
- for (var i = this.palettes.length - 1; i >= 0; i--)
- this.palettes[i].remove();
- },
-
- remove: function() {
- this.clear();
- delete PaperScope._scopes[this._id];
- },
-
- statics: new function() {
- function handleAttribute(name) {
- name += 'Attribute';
- return function(el, attr) {
- return el[name](attr) || el[name]('data-paper-' + attr);
- };
- }
-
- return {
- _scopes: {},
- _id: 0,
-
- get: function(id) {
- if (typeof id === 'object')
- id = id.getAttribute('id');
- return this._scopes[id] || null;
- },
-
- getAttribute: handleAttribute('get'),
- hasAttribute: handleAttribute('has')
- };
- }
-});
-
-var PaperScopeItem = Base.extend(Callback, {
-
- initialize: function(activate) {
- this._scope = paper;
- this._index = this._scope[this._list].push(this) - 1;
- if (activate || !this._scope[this._reference])
- this.activate();
- },
-
- activate: function() {
- if (!this._scope)
- return false;
- var prev = this._scope[this._reference];
- if (prev && prev !== this)
- prev.fire('deactivate');
- this._scope[this._reference] = this;
- this.fire('activate', prev);
- return true;
- },
-
- isActive: function() {
- return this._scope[this._reference] === this;
- },
-
- remove: function() {
- if (this._index == null)
- return false;
- Base.splice(this._scope[this._list], null, this._index, 1);
- if (this._scope[this._reference] == this)
- this._scope[this._reference] = null;
- this._scope = null;
- return true;
- }
-});
-
-var Formatter = Base.extend({
- initialize: function(precision) {
- this.precision = precision || 5;
- this.multiplier = Math.pow(10, this.precision);
- },
-
- number: function(val) {
- return Math.round(val * this.multiplier) / this.multiplier;
- },
-
- point: function(val, separator) {
- return this.number(val.x) + (separator || ',') + this.number(val.y);
- },
-
- size: function(val, separator) {
- return this.number(val.width) + (separator || ',')
- + this.number(val.height);
- },
-
- rectangle: function(val, separator) {
- return this.point(val, separator) + (separator || ',')
- + this.size(val, separator);
- }
-});
-
-Formatter.instance = new Formatter();
-
-var Numerical = new function() {
-
- var abscissas = [
- [ 0.5773502691896257645091488],
- [0,0.7745966692414833770358531],
- [ 0.3399810435848562648026658,0.8611363115940525752239465],
- [0,0.5384693101056830910363144,0.9061798459386639927976269],
- [ 0.2386191860831969086305017,0.6612093864662645136613996,0.9324695142031520278123016],
- [0,0.4058451513773971669066064,0.7415311855993944398638648,0.9491079123427585245261897],
- [ 0.1834346424956498049394761,0.5255324099163289858177390,0.7966664774136267395915539,0.9602898564975362316835609],
- [0,0.3242534234038089290385380,0.6133714327005903973087020,0.8360311073266357942994298,0.9681602395076260898355762],
- [ 0.1488743389816312108848260,0.4333953941292471907992659,0.6794095682990244062343274,0.8650633666889845107320967,0.9739065285171717200779640],
- [0,0.2695431559523449723315320,0.5190961292068118159257257,0.7301520055740493240934163,0.8870625997680952990751578,0.9782286581460569928039380],
- [ 0.1252334085114689154724414,0.3678314989981801937526915,0.5873179542866174472967024,0.7699026741943046870368938,0.9041172563704748566784659,0.9815606342467192506905491],
- [0,0.2304583159551347940655281,0.4484927510364468528779129,0.6423493394403402206439846,0.8015780907333099127942065,0.9175983992229779652065478,0.9841830547185881494728294],
- [ 0.1080549487073436620662447,0.3191123689278897604356718,0.5152486363581540919652907,0.6872929048116854701480198,0.8272013150697649931897947,0.9284348836635735173363911,0.9862838086968123388415973],
- [0,0.2011940939974345223006283,0.3941513470775633698972074,0.5709721726085388475372267,0.7244177313601700474161861,0.8482065834104272162006483,0.9372733924007059043077589,0.9879925180204854284895657],
- [ 0.0950125098376374401853193,0.2816035507792589132304605,0.4580167776572273863424194,0.6178762444026437484466718,0.7554044083550030338951012,0.8656312023878317438804679,0.9445750230732325760779884,0.9894009349916499325961542]
- ];
-
- var weights = [
- [1],
- [0.8888888888888888888888889,0.5555555555555555555555556],
- [0.6521451548625461426269361,0.3478548451374538573730639],
- [0.5688888888888888888888889,0.4786286704993664680412915,0.2369268850561890875142640],
- [0.4679139345726910473898703,0.3607615730481386075698335,0.1713244923791703450402961],
- [0.4179591836734693877551020,0.3818300505051189449503698,0.2797053914892766679014678,0.1294849661688696932706114],
- [0.3626837833783619829651504,0.3137066458778872873379622,0.2223810344533744705443560,0.1012285362903762591525314],
- [0.3302393550012597631645251,0.3123470770400028400686304,0.2606106964029354623187429,0.1806481606948574040584720,0.0812743883615744119718922],
- [0.2955242247147528701738930,0.2692667193099963550912269,0.2190863625159820439955349,0.1494513491505805931457763,0.0666713443086881375935688],
- [0.2729250867779006307144835,0.2628045445102466621806889,0.2331937645919904799185237,0.1862902109277342514260976,0.1255803694649046246346943,0.0556685671161736664827537],
- [0.2491470458134027850005624,0.2334925365383548087608499,0.2031674267230659217490645,0.1600783285433462263346525,0.1069393259953184309602547,0.0471753363865118271946160],
- [0.2325515532308739101945895,0.2262831802628972384120902,0.2078160475368885023125232,0.1781459807619457382800467,0.1388735102197872384636018,0.0921214998377284479144218,0.0404840047653158795200216],
- [0.2152638534631577901958764,0.2051984637212956039659241,0.1855383974779378137417166,0.1572031671581935345696019,0.1215185706879031846894148,0.0801580871597602098056333,0.0351194603317518630318329],
- [0.2025782419255612728806202,0.1984314853271115764561183,0.1861610000155622110268006,0.1662692058169939335532009,0.1395706779261543144478048,0.1071592204671719350118695,0.0703660474881081247092674,0.0307532419961172683546284],
- [0.1894506104550684962853967,0.1826034150449235888667637,0.1691565193950025381893121,0.1495959888165767320815017,0.1246289712555338720524763,0.0951585116824927848099251,0.0622535239386478928628438,0.0271524594117540948517806]
- ];
-
- var abs = Math.abs,
- sqrt = Math.sqrt,
- pow = Math.pow,
- cos = Math.cos,
- PI = Math.PI;
-
- return {
- TOLERANCE: 10e-6,
- EPSILON: 10e-12,
- KAPPA: 4 * (sqrt(2) - 1) / 3,
-
- isZero: function(val) {
- return abs(val) <= Numerical.EPSILON;
- },
-
- integrate: function(f, a, b, n) {
- var x = abscissas[n - 2],
- w = weights[n - 2],
- A = 0.5 * (b - a),
- B = A + a,
- i = 0,
- m = (n + 1) >> 1,
- sum = n & 1 ? w[i++] * f(B) : 0;
- while (i < m) {
- var Ax = A * x[i];
- sum += w[i++] * (f(B + Ax) + f(B - Ax));
- }
- return A * sum;
- },
-
- findRoot: function(f, df, x, a, b, n, tolerance) {
- for (var i = 0; i < n; i++) {
- var fx = f(x),
- dx = fx / df(x);
- if (abs(dx) < tolerance)
- return x;
- var nx = x - dx;
- if (fx > 0) {
- b = x;
- x = nx <= a ? 0.5 * (a + b) : nx;
- } else {
- a = x;
- x = nx >= b ? 0.5 * (a + b) : nx;
- }
- }
- },
-
- solveQuadratic: function(a, b, c, roots, min, max) {
- var epsilon = Numerical.EPSILON,
- unbound = min === undefined,
- minE = min - epsilon,
- maxE = max + epsilon,
- count = 0;
-
- function add(root) {
- if (unbound || root > minE && root < maxE)
- roots[count++] = root < min ? min : root > max ? max : root;
- return count;
- }
-
- if (abs(a) < epsilon) {
- if (abs(b) >= epsilon)
- return add(-c / b);
- return abs(c) < epsilon ? -1 : 0;
- }
- var p = b / (2 * a);
- var q = c / a;
- var p2 = p * p;
- if (p2 < q - epsilon)
- return 0;
- var s = p2 > q ? sqrt(p2 - q) : 0;
- add (s - p);
- if (s > 0)
- add(-s - p);
- return count;
- },
-
- solveCubic: function(a, b, c, d, roots, min, max) {
- var epsilon = Numerical.EPSILON;
- if (abs(a) < epsilon)
- return Numerical.solveQuadratic(b, c, d, roots, min, max);
-
- var unbound = min === undefined,
- minE = min - epsilon,
- maxE = max + epsilon,
- count = 0;
-
- function add(root) {
- if (unbound || root > minE && root < maxE)
- roots[count++] = root < min ? min : root > max ? max : root;
- return count;
- }
-
- b /= a;
- c /= a;
- d /= a;
- var bb = b * b,
- p = (bb - 3 * c) / 9,
- q = (2 * bb * b - 9 * b * c + 27 * d) / 54,
- ppp = p * p * p,
- D = q * q - ppp;
- b /= 3;
- if (abs(D) < epsilon) {
- if (abs(q) < epsilon)
- return add(-b);
- var sqp = sqrt(p),
- snq = q > 0 ? 1 : -1;
- add(-snq * 2 * sqp - b);
- return add(snq * sqp - b);
- }
- if (D < 0) {
- var sqp = sqrt(p),
- phi = Math.acos(q / (sqp * sqp * sqp)) / 3,
- t = -2 * sqp,
- o = 2 * PI / 3;
- add(t * cos(phi) - b);
- add(t * cos(phi + o) - b);
- return add(t * cos(phi - o) - b);
- }
- var A = (q > 0 ? -1 : 1) * pow(abs(q) + sqrt(D), 1 / 3);
- return add(A + p / A - b);
- }
- };
-};
-
-var Point = Base.extend({
- _class: 'Point',
- _readIndex: true,
-
- initialize: function Point(arg0, arg1) {
- var type = typeof arg0;
- if (type === 'number') {
- var hasY = typeof arg1 === 'number';
- this.x = arg0;
- this.y = hasY ? arg1 : arg0;
- if (this.__read)
- this.__read = hasY ? 2 : 1;
- } else if (type === 'undefined' || arg0 === null) {
- this.x = this.y = 0;
- if (this.__read)
- this.__read = arg0 === null ? 1 : 0;
- } else {
- if (Array.isArray(arg0)) {
- this.x = arg0[0];
- this.y = arg0.length > 1 ? arg0[1] : arg0[0];
- } else if (arg0.x != null) {
- this.x = arg0.x;
- this.y = arg0.y;
- } else if (arg0.width != null) {
- this.x = arg0.width;
- this.y = arg0.height;
- } else if (arg0.angle != null) {
- this.x = arg0.length;
- this.y = 0;
- this.setAngle(arg0.angle);
- } else {
- this.x = this.y = 0;
- if (this.__read)
- this.__read = 0;
- }
- if (this.__read)
- this.__read = 1;
- }
- },
-
- set: function(x, y) {
- this.x = x;
- this.y = y;
- return this;
- },
-
- equals: function(point) {
- return point === this || point && (this.x === point.x
- && this.y === point.y
- || Array.isArray(point) && this.x === point[0]
- && this.y === point[1]) || false;
- },
-
- clone: function() {
- return new Point(this.x, this.y);
- },
-
- toString: function() {
- var f = Formatter.instance;
- return '{ x: ' + f.number(this.x) + ', y: ' + f.number(this.y) + ' }';
- },
-
- _serialize: function(options) {
- var f = options.formatter;
- return [f.number(this.x), f.number(this.y)];
- },
-
- add: function(point) {
- point = Point.read(arguments);
- return new Point(this.x + point.x, this.y + point.y);
- },
-
- subtract: function(point) {
- point = Point.read(arguments);
- return new Point(this.x - point.x, this.y - point.y);
- },
-
- multiply: function(point) {
- point = Point.read(arguments);
- return new Point(this.x * point.x, this.y * point.y);
- },
-
- divide: function(point) {
- point = Point.read(arguments);
- return new Point(this.x / point.x, this.y / point.y);
- },
-
- modulo: function(point) {
- point = Point.read(arguments);
- return new Point(this.x % point.x, this.y % point.y);
- },
-
- negate: function() {
- return new Point(-this.x, -this.y);
- },
-
- transform: function(matrix) {
- return matrix ? matrix._transformPoint(this) : this;
- },
-
- getDistance: function(point, squared) {
- point = Point.read(arguments);
- var x = point.x - this.x,
- y = point.y - this.y,
- d = x * x + y * y;
- return squared ? d : Math.sqrt(d);
- },
-
- getLength: function() {
- var length = this.x * this.x + this.y * this.y;
- return arguments.length && arguments[0] ? length : Math.sqrt(length);
- },
-
- setLength: function(length) {
- if (this.isZero()) {
- var angle = this._angle || 0;
- this.set(
- Math.cos(angle) * length,
- Math.sin(angle) * length
- );
- } else {
- var scale = length / this.getLength();
- if (Numerical.isZero(scale))
- this.getAngle();
- this.set(
- this.x * scale,
- this.y * scale
- );
- }
- return this;
- },
-
- normalize: function(length) {
- if (length === undefined)
- length = 1;
- var current = this.getLength(),
- scale = current !== 0 ? length / current : 0,
- point = new Point(this.x * scale, this.y * scale);
- point._angle = this._angle;
- return point;
- },
-
- getAngle: function() {
- return this.getAngleInRadians(arguments[0]) * 180 / Math.PI;
- },
-
- setAngle: function(angle) {
- angle = this._angle = angle * Math.PI / 180;
- if (!this.isZero()) {
- var length = this.getLength();
- this.set(
- Math.cos(angle) * length,
- Math.sin(angle) * length
- );
- }
- return this;
- },
-
- getAngleInRadians: function() {
- if (arguments[0] === undefined) {
- return this.isZero()
- ? this._angle || 0
- : this._angle = Math.atan2(this.y, this.x);
- } else {
- var point = Point.read(arguments),
- div = this.getLength() * point.getLength();
- if (Numerical.isZero(div)) {
- return NaN;
- } else {
- return Math.acos(this.dot(point) / div);
- }
- }
- },
-
- getAngleInDegrees: function() {
- return this.getAngle(arguments[0]);
- },
-
- getQuadrant: function() {
- return this.x >= 0 ? this.y >= 0 ? 1 : 4 : this.y >= 0 ? 2 : 3;
- },
-
- getDirectedAngle: function(point) {
- point = Point.read(arguments);
- return Math.atan2(this.cross(point), this.dot(point)) * 180 / Math.PI;
- },
-
- rotate: function(angle, center) {
- if (angle === 0)
- return this.clone();
- angle = angle * Math.PI / 180;
- var point = center ? this.subtract(center) : this,
- s = Math.sin(angle),
- c = Math.cos(angle);
- point = new Point(
- point.x * c - point.y * s,
- point.y * c + point.x * s
- );
- return center ? point.add(center) : point;
- },
-
- isInside: function(rect) {
- return rect.contains(this);
- },
-
- isClose: function(point, tolerance) {
- return this.getDistance(point) < tolerance;
- },
-
- isColinear: function(point) {
- return this.cross(point) < 0.00001;
- },
-
- isOrthogonal: function(point) {
- return this.dot(point) < 0.00001;
- },
-
- isZero: function() {
- return Numerical.isZero(this.x) && Numerical.isZero(this.y);
- },
-
- isNaN: function() {
- return isNaN(this.x) || isNaN(this.y);
- },
-
- dot: function(point) {
- point = Point.read(arguments);
- return this.x * point.x + this.y * point.y;
- },
-
- cross: function(point) {
- point = Point.read(arguments);
- return this.x * point.y - this.y * point.x;
- },
-
- project: function(point) {
- point = Point.read(arguments);
- if (point.isZero()) {
- return new Point(0, 0);
- } else {
- var scale = this.dot(point) / point.dot(point);
- return new Point(
- point.x * scale,
- point.y * scale
- );
- }
- },
-
- statics: {
- min: function() {
- var point1 = Point.read(arguments);
- point2 = Point.read(arguments);
- return new Point(
- Math.min(point1.x, point2.x),
- Math.min(point1.y, point2.y)
- );
- },
-
- max: function() {
- var point1 = Point.read(arguments);
- point2 = Point.read(arguments);
- return new Point(
- Math.max(point1.x, point2.x),
- Math.max(point1.y, point2.y)
- );
- },
-
- random: function() {
- return new Point(Math.random(), Math.random());
- }
- }
-}, Base.each(['round', 'ceil', 'floor', 'abs'], function(name) {
- var op = Math[name];
- this[name] = function() {
- return new Point(op(this.x), op(this.y));
- };
-}, {}));
-
-var LinkedPoint = Point.extend({
- initialize: function Point(x, y, owner, setter) {
- this._x = x;
- this._y = y;
- this._owner = owner;
- this._setter = setter;
- },
-
- set: function(x, y, _dontNotify) {
- this._x = x;
- this._y = y;
- if (!_dontNotify)
- this._owner[this._setter](this);
- return this;
- },
-
- getX: function() {
- return this._x;
- },
-
- setX: function(x) {
- this._x = x;
- this._owner[this._setter](this);
- },
-
- getY: function() {
- return this._y;
- },
-
- setY: function(y) {
- this._y = y;
- this._owner[this._setter](this);
- }
-});
-
-var Size = Base.extend({
- _class: 'Size',
- _readIndex: true,
-
- initialize: function Size(arg0, arg1) {
- var type = typeof arg0;
- if (type === 'number') {
- var hasHeight = typeof arg1 === 'number';
- this.width = arg0;
- this.height = hasHeight ? arg1 : arg0;
- if (this.__read)
- this.__read = hasHeight ? 2 : 1;
- } else if (type === 'undefined' || arg0 === null) {
- this.width = this.height = 0;
- if (this.__read)
- this.__read = arg0 === null ? 1 : 0;
- } else {
- if (Array.isArray(arg0)) {
- this.width = arg0[0];
- this.height = arg0.length > 1 ? arg0[1] : arg0[0];
- } else if (arg0.width != null) {
- this.width = arg0.width;
- this.height = arg0.height;
- } else if (arg0.x != null) {
- this.width = arg0.x;
- this.height = arg0.y;
- } else {
- this.width = this.height = 0;
- if (this.__read)
- this.__read = 0;
- }
- if (this.__read)
- this.__read = 1;
- }
- },
-
- set: function(width, height) {
- this.width = width;
- this.height = height;
- return this;
- },
-
- equals: function(size) {
- return size === this || size && (this.width === size.width
- && this.height === size.height
- || Array.isArray(size) && this.width === size[0]
- && this.height === size[1]) || false;
- },
-
- clone: function() {
- return new Size(this.width, this.height);
- },
-
- toString: function() {
- var f = Formatter.instance;
- return '{ width: ' + f.number(this.width)
- + ', height: ' + f.number(this.height) + ' }';
- },
-
- _serialize: function(options) {
- var f = options.formatter;
- return [f.number(this.width),
- f.number(this.height)];
- },
-
- add: function(size) {
- size = Size.read(arguments);
- return new Size(this.width + size.width, this.height + size.height);
- },
-
- subtract: function(size) {
- size = Size.read(arguments);
- return new Size(this.width - size.width, this.height - size.height);
- },
-
- multiply: function(size) {
- size = Size.read(arguments);
- return new Size(this.width * size.width, this.height * size.height);
- },
-
- divide: function(size) {
- size = Size.read(arguments);
- return new Size(this.width / size.width, this.height / size.height);
- },
-
- modulo: function(size) {
- size = Size.read(arguments);
- return new Size(this.width % size.width, this.height % size.height);
- },
-
- negate: function() {
- return new Size(-this.width, -this.height);
- },
-
- isZero: function() {
- return Numerical.isZero(this.width) && Numerical.isZero(this.height);
- },
-
- isNaN: function() {
- return isNaN(this.width) || isNaN(this.height);
- },
-
- statics: {
- min: function(size1, size2) {
- return new Size(
- Math.min(size1.width, size2.width),
- Math.min(size1.height, size2.height));
- },
-
- max: function(size1, size2) {
- return new Size(
- Math.max(size1.width, size2.width),
- Math.max(size1.height, size2.height));
- },
-
- random: function() {
- return new Size(Math.random(), Math.random());
- }
- }
-}, Base.each(['round', 'ceil', 'floor', 'abs'], function(name) {
- var op = Math[name];
- this[name] = function() {
- return new Size(op(this.width), op(this.height));
- };
-}, {}));
-
-var LinkedSize = Size.extend({
- initialize: function Size(width, height, owner, setter) {
- this._width = width;
- this._height = height;
- this._owner = owner;
- this._setter = setter;
- },
-
- set: function(width, height, _dontNotify) {
- this._width = width;
- this._height = height;
- if (!_dontNotify)
- this._owner[this._setter](this);
- return this;
- },
-
- getWidth: function() {
- return this._width;
- },
-
- setWidth: function(width) {
- this._width = width;
- this._owner[this._setter](this);
- },
-
- getHeight: function() {
- return this._height;
- },
-
- setHeight: function(height) {
- this._height = height;
- this._owner[this._setter](this);
- }
-});
-
-var Rectangle = Base.extend({
- _class: 'Rectangle',
- _readIndex: true,
-
- initialize: function Rectangle(arg0, arg1, arg2, arg3) {
- var type = typeof arg0,
- read = 0;
- if (type === 'number') {
- this.x = arg0;
- this.y = arg1;
- this.width = arg2;
- this.height = arg3;
- read = 4;
- } else if (type === 'undefined' || arg0 === null) {
- this.x = this.y = this.width = this.height = 0;
- read = arg0 === null ? 1 : 0;
- } else if (arguments.length === 1) {
- if (Array.isArray(arg0)) {
- this.x = arg0[0];
- this.y = arg0[1];
- this.width = arg0[2];
- this.height = arg0[3];
- read = 1;
- } else if (arg0.x !== undefined || arg0.width !== undefined) {
- this.x = arg0.x || 0;
- this.y = arg0.y || 0;
- this.width = arg0.width || 0;
- this.height = arg0.height || 0;
- read = 1;
- } else if (arg0.from === undefined && arg0.to === undefined) {
- this.x = this.y = this.width = this.height = 0;
- this._set(arg0);
- read = 1;
- }
- }
- if (!read) {
- var point = Point.readNamed(arguments, 'from'),
- next = Base.peek(arguments);
- this.x = point.x;
- this.y = point.y;
- if (next && next.x !== undefined || Base.hasNamed(arguments, 'to')) {
- var to = Point.readNamed(arguments, 'to');
- this.width = to.x - point.x;
- this.height = to.y - point.y;
- if (this.width < 0) {
- this.x = to.x;
- this.width = -this.width;
- }
- if (this.height < 0) {
- this.y = to.y;
- this.height = -this.height;
- }
- } else {
- var size = Size.read(arguments);
- this.width = size.width;
- this.height = size.height;
- }
- read = arguments._index;
- }
- if (this.__read)
- this.__read = read;
- },
-
- set: function(x, y, width, height) {
- this.x = x;
- this.y = y;
- this.width = width;
- this.height = height;
- return this;
- },
-
- clone: function() {
- return new Rectangle(this.x, this.y, this.width, this.height);
- },
-
- equals: function(rect) {
- if (Base.isPlainValue(rect))
- rect = Rectangle.read(arguments);
- return rect === this
- || rect && this.x === rect.x && this.y === rect.y
- && this.width === rect.width && this.height === rect.height
- || false;
- },
-
- toString: function() {
- var f = Formatter.instance;
- return '{ x: ' + f.number(this.x)
- + ', y: ' + f.number(this.y)
- + ', width: ' + f.number(this.width)
- + ', height: ' + f.number(this.height)
- + ' }';
- },
-
- _serialize: function(options) {
- var f = options.formatter;
- return [f.number(this.x),
- f.number(this.y),
- f.number(this.width),
- f.number(this.height)];
- },
-
- getPoint: function() {
- return new (arguments[0] ? Point : LinkedPoint)
- (this.x, this.y, this, 'setPoint');
- },
-
- setPoint: function(point) {
- point = Point.read(arguments);
- this.x = point.x;
- this.y = point.y;
- },
-
- getSize: function() {
- return new (arguments[0] ? Size : LinkedSize)
- (this.width, this.height, this, 'setSize');
- },
-
- setSize: function(size) {
- size = Size.read(arguments);
- if (this._fixX)
- this.x += (this.width - size.width) * this._fixX;
- if (this._fixY)
- this.y += (this.height - size.height) * this._fixY;
- this.width = size.width;
- this.height = size.height;
- this._fixW = 1;
- this._fixH = 1;
- },
-
- getLeft: function() {
- return this.x;
- },
-
- setLeft: function(left) {
- if (!this._fixW)
- this.width -= left - this.x;
- this.x = left;
- this._fixX = 0;
- },
-
- getTop: function() {
- return this.y;
- },
-
- setTop: function(top) {
- if (!this._fixH)
- this.height -= top - this.y;
- this.y = top;
- this._fixY = 0;
- },
-
- getRight: function() {
- return this.x + this.width;
- },
-
- setRight: function(right) {
- if (this._fixX !== undefined && this._fixX !== 1)
- this._fixW = 0;
- if (this._fixW)
- this.x = right - this.width;
- else
- this.width = right - this.x;
- this._fixX = 1;
- },
-
- getBottom: function() {
- return this.y + this.height;
- },
-
- setBottom: function(bottom) {
- if (this._fixY !== undefined && this._fixY !== 1)
- this._fixH = 0;
- if (this._fixH)
- this.y = bottom - this.height;
- else
- this.height = bottom - this.y;
- this._fixY = 1;
- },
-
- getCenterX: function() {
- return this.x + this.width * 0.5;
- },
-
- setCenterX: function(x) {
- this.x = x - this.width * 0.5;
- this._fixX = 0.5;
- },
-
- getCenterY: function() {
- return this.y + this.height * 0.5;
- },
-
- setCenterY: function(y) {
- this.y = y - this.height * 0.5;
- this._fixY = 0.5;
- },
-
- getCenter: function() {
- return new (arguments[0] ? Point : LinkedPoint)
- (this.getCenterX(), this.getCenterY(), this, 'setCenter');
- },
-
- setCenter: function(point) {
- point = Point.read(arguments);
- this.setCenterX(point.x);
- this.setCenterY(point.y);
- return this;
- },
-
- isEmpty: function() {
- return this.width == 0 || this.height == 0;
- },
-
- contains: function(arg) {
- return arg && arg.width !== undefined
- || (Array.isArray(arg) ? arg : arguments).length == 4
- ? this._containsRectangle(Rectangle.read(arguments))
- : this._containsPoint(Point.read(arguments));
- },
-
- _containsPoint: function(point) {
- var x = point.x,
- y = point.y;
- return x >= this.x && y >= this.y
- && x <= this.x + this.width
- && y <= this.y + this.height;
- },
-
- _containsRectangle: function(rect) {
- var x = rect.x,
- y = rect.y;
- return x >= this.x && y >= this.y
- && x + rect.width <= this.x + this.width
- && y + rect.height <= this.y + this.height;
- },
-
- intersects: function(rect) {
- rect = Rectangle.read(arguments);
- return rect.x + rect.width > this.x
- && rect.y + rect.height > this.y
- && rect.x < this.x + this.width
- && rect.y < this.y + this.height;
- },
-
- touches: function(rect) {
- rect = Rectangle.read(arguments);
- return rect.x + rect.width >= this.x
- && rect.y + rect.height >= this.y
- && rect.x <= this.x + this.width
- && rect.y <= this.y + this.height;
- },
-
- intersect: function(rect) {
- rect = Rectangle.read(arguments);
- var x1 = Math.max(this.x, rect.x),
- y1 = Math.max(this.y, rect.y),
- x2 = Math.min(this.x + this.width, rect.x + rect.width),
- y2 = Math.min(this.y + this.height, rect.y + rect.height);
- return new Rectangle(x1, y1, x2 - x1, y2 - y1);
- },
-
- unite: function(rect) {
- rect = Rectangle.read(arguments);
- var x1 = Math.min(this.x, rect.x),
- y1 = Math.min(this.y, rect.y),
- x2 = Math.max(this.x + this.width, rect.x + rect.width),
- y2 = Math.max(this.y + this.height, rect.y + rect.height);
- return new Rectangle(x1, y1, x2 - x1, y2 - y1);
- },
-
- include: function(point) {
- point = Point.read(arguments);
- var x1 = Math.min(this.x, point.x),
- y1 = Math.min(this.y, point.y),
- x2 = Math.max(this.x + this.width, point.x),
- y2 = Math.max(this.y + this.height, point.y);
- return new Rectangle(x1, y1, x2 - x1, y2 - y1);
- },
-
- expand: function(hor, ver) {
- if (ver === undefined)
- ver = hor;
- return new Rectangle(this.x - hor / 2, this.y - ver / 2,
- this.width + hor, this.height + ver);
- },
-
- scale: function(hor, ver) {
- return this.expand(this.width * hor - this.width,
- this.height * (ver === undefined ? hor : ver) - this.height);
- }
-}, new function() {
- return Base.each([
- ['Top', 'Left'], ['Top', 'Right'],
- ['Bottom', 'Left'], ['Bottom', 'Right'],
- ['Left', 'Center'], ['Top', 'Center'],
- ['Right', 'Center'], ['Bottom', 'Center']
- ],
- function(parts, index) {
- var part = parts.join('');
- var xFirst = /^[RL]/.test(part);
- if (index >= 4)
- parts[1] += xFirst ? 'Y' : 'X';
- var x = parts[xFirst ? 0 : 1],
- y = parts[xFirst ? 1 : 0],
- getX = 'get' + x,
- getY = 'get' + y,
- setX = 'set' + x,
- setY = 'set' + y,
- get = 'get' + part,
- set = 'set' + part;
- this[get] = function() {
- return new (arguments[0] ? Point : LinkedPoint)
- (this[getX](), this[getY](), this, set);
- };
- this[set] = function(point) {
- point = Point.read(arguments);
- this[setX](point.x);
- this[setY](point.y);
- };
- }, {});
-});
-
-var LinkedRectangle = Rectangle.extend({
- initialize: function Rectangle(x, y, width, height, owner, setter) {
- this.set(x, y, width, height, true);
- this._owner = owner;
- this._setter = setter;
- },
-
- set: function(x, y, width, height, _dontNotify) {
- this._x = x;
- this._y = y;
- this._width = width;
- this._height = height;
- if (!_dontNotify)
- this._owner[this._setter](this);
- return this;
- }
-}, new function() {
- var proto = Rectangle.prototype;
-
- return Base.each(['x', 'y', 'width', 'height'], function(key) {
- var part = Base.capitalize(key);
- var internal = '_' + key;
- this['get' + part] = function() {
- return this[internal];
- };
-
- this['set' + part] = function(value) {
- this[internal] = value;
- if (!this._dontNotify)
- this._owner[this._setter](this);
- };
- }, Base.each(['Point', 'Size', 'Center',
- 'Left', 'Top', 'Right', 'Bottom', 'CenterX', 'CenterY',
- 'TopLeft', 'TopRight', 'BottomLeft', 'BottomRight',
- 'LeftCenter', 'TopCenter', 'RightCenter', 'BottomCenter'],
- function(key) {
- var name = 'set' + key;
- this[name] = function() {
- this._dontNotify = true;
- proto[name].apply(this, arguments);
- delete this._dontNotify;
- this._owner[this._setter](this);
- };
- }, {
- isSelected: function() {
- return this._owner._boundsSelected;
- },
-
- setSelected: function(selected) {
- var owner = this._owner;
- if (owner.setSelected) {
- owner._boundsSelected = selected;
- owner.setSelected(selected || owner._selectedSegmentState > 0);
- }
- }
- })
- );
-});
-
-var Matrix = Base.extend({
- _class: 'Matrix',
-
- initialize: function Matrix(arg) {
- var count = arguments.length,
- ok = true;
- if (count === 6) {
- this.set.apply(this, arguments);
- } else if (count === 1) {
- if (arg instanceof Matrix) {
- this.set(arg._a, arg._c, arg._b, arg._d, arg._tx, arg._ty);
- } else if (Array.isArray(arg)) {
- this.set.apply(this, arg);
- } else {
- ok = false;
- }
- } else if (count === 0) {
- this.reset();
- } else {
- ok = false;
- }
- if (!ok)
- throw new Error('Unsupported matrix parameters');
- },
-
- set: function(a, c, b, d, tx, ty, _dontNotify) {
- this._a = a;
- this._c = c;
- this._b = b;
- this._d = d;
- this._tx = tx;
- this._ty = ty;
- if (!_dontNotify)
- this._changed();
- return this;
- },
-
- _serialize: function(options) {
- return Base.serialize(this.getValues(), options);
- },
-
- _changed: function() {
- if (this._owner)
- this._owner._changed(5);
- },
-
- clone: function() {
- return new Matrix(this._a, this._c, this._b, this._d,
- this._tx, this._ty);
- },
-
- equals: function(mx) {
- return mx === this || mx && this._a === mx._a && this._b === mx._b
- && this._c === mx._c && this._d === mx._d
- && this._tx === mx._tx && this._ty === mx._ty
- || false;
- },
-
- toString: function() {
- var f = Formatter.instance;
- return '[[' + [f.number(this._a), f.number(this._b),
- f.number(this._tx)].join(', ') + '], ['
- + [f.number(this._c), f.number(this._d),
- f.number(this._ty)].join(', ') + ']]';
- },
-
- reset: function() {
- this._a = this._d = 1;
- this._c = this._b = this._tx = this._ty = 0;
- this._changed();
- return this;
- },
-
- scale: function() {
- var scale = Point.read(arguments),
- center = Point.read(arguments, 0, 0, { readNull: true });
- if (center)
- this.translate(center);
- this._a *= scale.x;
- this._c *= scale.x;
- this._b *= scale.y;
- this._d *= scale.y;
- if (center)
- this.translate(center.negate());
- this._changed();
- return this;
- },
-
- translate: function(point) {
- point = Point.read(arguments);
- var x = point.x,
- y = point.y;
- this._tx += x * this._a + y * this._b;
- this._ty += x * this._c + y * this._d;
- this._changed();
- return this;
- },
-
- rotate: function(angle, center) {
- center = Point.read(arguments, 1);
- angle = angle * Math.PI / 180;
- var x = center.x,
- y = center.y,
- cos = Math.cos(angle),
- sin = Math.sin(angle),
- tx = x - x * cos + y * sin,
- ty = y - x * sin - y * cos,
- a = this._a,
- b = this._b,
- c = this._c,
- d = this._d;
- this._a = cos * a + sin * b;
- this._b = -sin * a + cos * b;
- this._c = cos * c + sin * d;
- this._d = -sin * c + cos * d;
- this._tx += tx * a + ty * b;
- this._ty += tx * c + ty * d;
- this._changed();
- return this;
- },
-
- shear: function() {
- var point = Point.read(arguments),
- center = Point.read(arguments, 0, 0, { readNull: true });
- if (center)
- this.translate(center);
- var a = this._a,
- c = this._c;
- this._a += point.y * this._b;
- this._c += point.y * this._d;
- this._b += point.x * a;
- this._d += point.x * c;
- if (center)
- this.translate(center.negate());
- this._changed();
- return this;
- },
-
- concatenate: function(mx) {
- var a = this._a,
- b = this._b,
- c = this._c,
- d = this._d;
- this._a = mx._a * a + mx._c * b;
- this._b = mx._b * a + mx._d * b;
- this._c = mx._a * c + mx._c * d;
- this._d = mx._b * c + mx._d * d;
- this._tx += mx._tx * a + mx._ty * b;
- this._ty += mx._tx * c + mx._ty * d;
- this._changed();
- return this;
- },
-
- preConcatenate: function(mx) {
- var a = this._a,
- b = this._b,
- c = this._c,
- d = this._d,
- tx = this._tx,
- ty = this._ty;
- this._a = mx._a * a + mx._b * c;
- this._b = mx._a * b + mx._b * d;
- this._c = mx._c * a + mx._d * c;
- this._d = mx._c * b + mx._d * d;
- this._tx = mx._a * tx + mx._b * ty + mx._tx;
- this._ty = mx._c * tx + mx._d * ty + mx._ty;
- this._changed();
- return this;
- },
-
- isIdentity: function() {
- return this._a === 1 && this._c === 0 && this._b === 0 && this._d === 1
- && this._tx === 0 && this._ty === 0;
- },
-
- isInvertible: function() {
- return !!this._getDeterminant();
- },
-
- isSingular: function() {
- return !this._getDeterminant();
- },
-
- transform: function( src, srcOffset, dst, dstOffset, count) {
- return arguments.length < 5
- ? this._transformPoint(Point.read(arguments))
- : this._transformCoordinates(src, srcOffset, dst, dstOffset, count);
- },
-
- _transformPoint: function(point, dest, _dontNotify) {
- var x = point.x,
- y = point.y;
- if (!dest)
- dest = new Point();
- return dest.set(
- x * this._a + y * this._b + this._tx,
- x * this._c + y * this._d + this._ty,
- _dontNotify
- );
- },
-
- _transformCoordinates: function(src, srcOffset, dst, dstOffset, count) {
- var i = srcOffset,
- j = dstOffset,
- max = i + 2 * count;
- while (i < max) {
- var x = src[i++],
- y = src[i++];
- dst[j++] = x * this._a + y * this._b + this._tx;
- dst[j++] = x * this._c + y * this._d + this._ty;
- }
- return dst;
- },
-
- _transformCorners: function(rect) {
- var x1 = rect.x,
- y1 = rect.y,
- x2 = x1 + rect.width,
- y2 = y1 + rect.height,
- coords = [ x1, y1, x2, y1, x2, y2, x1, y2 ];
- return this._transformCoordinates(coords, 0, coords, 0, 4);
- },
-
- _transformBounds: function(bounds, dest, _dontNotify) {
- var coords = this._transformCorners(bounds),
- min = coords.slice(0, 2),
- max = coords.slice();
- for (var i = 2; i < 8; i++) {
- var val = coords[i],
- j = i & 1;
- if (val < min[j])
- min[j] = val;
- else if (val > max[j])
- max[j] = val;
- }
- if (!dest)
- dest = new Rectangle();
- return dest.set(min[0], min[1], max[0] - min[0], max[1] - min[1],
- _dontNotify);
- },
-
- inverseTransform: function() {
- return this._inverseTransform(Point.read(arguments));
- },
-
- _getDeterminant: function() {
- var det = this._a * this._d - this._b * this._c;
- return isFinite(det) && !Numerical.isZero(det)
- && isFinite(this._tx) && isFinite(this._ty)
- ? det : null;
- },
-
- _inverseTransform: function(point, dest, _dontNotify) {
- var det = this._getDeterminant();
- if (!det)
- return null;
- var x = point.x - this._tx,
- y = point.y - this._ty;
- if (!dest)
- dest = new Point();
- return dest.set(
- (x * this._d - y * this._b) / det,
- (y * this._a - x * this._c) / det,
- _dontNotify
- );
- },
-
- decompose: function() {
- var a = this._a, b = this._b, c = this._c, d = this._d;
- if (Numerical.isZero(a * d - b * c))
- return null;
-
- var scaleX = Math.sqrt(a * a + b * b);
- a /= scaleX;
- b /= scaleX;
-
- var shear = a * c + b * d;
- c -= a * shear;
- d -= b * shear;
-
- var scaleY = Math.sqrt(c * c + d * d);
- c /= scaleY;
- d /= scaleY;
- shear /= scaleY;
-
- if (a * d < b * c) {
- a = -a;
- b = -b;
- shear = -shear;
- scaleX = -scaleX;
- }
-
- return {
- translation: this.getTranslation(),
- scaling: new Point(scaleX, scaleY),
- rotation: -Math.atan2(b, a) * 180 / Math.PI,
- shearing: shear
- };
- },
-
- getValues: function() {
- return [ this._a, this._c, this._b, this._d, this._tx, this._ty ];
- },
-
- getTranslation: function() {
- return new Point(this._tx, this._ty);
- },
-
- setTranslation: function() {
- var point = Point.read(arguments);
- this._tx = point.x;
- this._ty = point.y;
- this._changed();
- },
-
- getScaling: function() {
- return (this.decompose() || {}).scaling;
- },
-
- setScaling: function() {
- var scaling = this.getScaling();
- if (scaling != null) {
- var scale = Point.read(arguments);
- (this._owner || this).scale(
- scale.x / scaling.x, scale.y / scaling.y);
- }
- },
-
- getRotation: function() {
- return (this.decompose() || {}).rotation;
- },
-
- setRotation: function(angle) {
- var rotation = this.getRotation();
- if (rotation != null)
- (this._owner || this).rotate(angle - rotation);
- },
-
- inverted: function() {
- var det = this._getDeterminant();
- return det && new Matrix(
- this._d / det,
- -this._c / det,
- -this._b / det,
- this._a / det,
- (this._b * this._ty - this._d * this._tx) / det,
- (this._c * this._tx - this._a * this._ty) / det);
- },
-
- shiftless: function() {
- return new Matrix(this._a, this._c, this._b, this._d, 0, 0);
- },
-
- applyToContext: function(ctx) {
- ctx.transform(this._a, this._c, this._b, this._d, this._tx, this._ty);
- }
-}, new function() {
- return Base.each({
- scaleX: '_a',
- scaleY: '_d',
- translateX: '_tx',
- translateY: '_ty',
- shearX: '_b',
- shearY: '_c'
- }, function(prop, name) {
- name = Base.capitalize(name);
- this['get' + name] = function() {
- return this[prop];
- };
- this['set' + name] = function(value) {
- this[prop] = value;
- this._changed();
- };
- }, {});
-});
-
-var Line = Base.extend({
- _class: 'Line',
-
- initialize: function Line(arg0, arg1, arg2, arg3, arg4) {
- var asVector = false;
- if (arguments.length >= 4) {
- this._px = arg0;
- this._py = arg1;
- this._vx = arg2;
- this._vy = arg3;
- asVector = arg4;
- } else {
- this._px = arg0.x;
- this._py = arg0.y;
- this._vx = arg1.x;
- this._vy = arg1.y;
- asVector = arg2;
- }
- if (!asVector) {
- this._vx -= this._px;
- this._vy -= this._py;
- }
- },
-
- getPoint: function() {
- return new Point(this._px, this._py);
- },
-
- getVector: function() {
- return new Point(this._vx, this._vy);
- },
-
- getLength: function() {
- return this.getVector().getLength();
- },
-
- intersect: function(line, isInfinite) {
- return Line.intersect(
- this._px, this._py, this._vx, this._vy,
- line._px, line._py, line._vx, line._vy,
- true, isInfinite);
- },
-
- getSide: function(point) {
- return Line.getSide(
- this._px, this._py, this._vx, this._vy,
- point.x, point.y, true);
- },
-
- getDistance: function(point) {
- return Math.abs(Line.getSignedDistance(
- this._px, this._py, this._vx, this._vy,
- point.x, point.y, true));
- },
-
- statics: {
- intersect: function(apx, apy, avx, avy, bpx, bpy, bvx, bvy, asVector,
- isInfinite) {
- if (!asVector) {
- avx -= apx;
- avy -= apy;
- bvx -= bpx;
- bvy -= bpy;
- }
- var cross = bvy * avx - bvx * avy;
- if (!Numerical.isZero(cross)) {
- var dx = apx - bpx,
- dy = apy - bpy,
- ta = (bvx * dy - bvy * dx) / cross,
- tb = (avx * dy - avy * dx) / cross;
- if ((isInfinite || 0 <= ta && ta <= 1)
- && (isInfinite || 0 <= tb && tb <= 1))
- return new Point(
- apx + ta * avx,
- apy + ta * avy);
- }
- },
-
- getSide: function(px, py, vx, vy, x, y, asVector) {
- if (!asVector) {
- vx -= px;
- vy -= py;
- }
- var v2x = x - px,
- v2y = y - py,
- ccw = v2x * vy - v2y * vx;
- if (ccw === 0) {
- ccw = v2x * vx + v2y * vy;
- if (ccw > 0) {
- v2x -= vx;
- v2y -= vy;
- ccw = v2x * vx + v2y * vy;
- if (ccw < 0)
- ccw = 0;
- }
- }
- return ccw < 0 ? -1 : ccw > 0 ? 1 : 0;
- },
-
- getSignedDistance: function(px, py, vx, vy, x, y, asVector) {
- if (!asVector) {
- vx -= px;
- vy -= py;
- }
- var m = vy / vx,
- b = py - m * px;
- return (y - (m * x) - b) / Math.sqrt(m * m + 1);
- }
- }
-});
-
-var Project = PaperScopeItem.extend({
- _class: 'Project',
- _list: 'projects',
- _reference: 'project',
-
- initialize: function Project(view) {
- PaperScopeItem.call(this, true);
- this.layers = [];
- this.symbols = [];
- this._currentStyle = new Style();
- this.activeLayer = new Layer();
- if (view)
- this.view = view instanceof View ? view : View.create(view);
- this._selectedItems = {};
- this._selectedItemCount = 0;
- this._drawCount = 0;
- this.options = {};
- },
-
- _serialize: function(options, dictionary) {
- return Base.serialize(this.layers, options, true, dictionary);
- },
-
- clear: function() {
- for (var i = this.layers.length - 1; i >= 0; i--)
- this.layers[i].remove();
- this.symbols = [];
- },
-
- isEmpty: function() {
- return this.layers.length <= 1
- && (!this.activeLayer || this.activeLayer.isEmpty());
- },
-
- remove: function remove() {
- if (!remove.base.call(this))
- return false;
- if (this.view)
- this.view.remove();
- return true;
- },
-
- getCurrentStyle: function() {
- return this._currentStyle;
- },
-
- setCurrentStyle: function(style) {
- this._currentStyle.initialize(style);
- },
-
- getIndex: function() {
- return this._index;
- },
-
- addChild: function(child) {
- if (child instanceof Layer) {
- Base.splice(this.layers, [child]);
- if (!this.activeLayer)
- this.activeLayer = child;
- } else if (child instanceof Item) {
- (this.activeLayer
- || this.addChild(new Layer({ insert: false }))).addChild(child);
- } else {
- child = null;
- }
- return child;
- },
-
- getSelectedItems: function() {
- var items = [];
- for (var id in this._selectedItems) {
- var item = this._selectedItems[id];
- if (item.isInserted())
- items.push(item);
- }
- return items;
- },
-
- _updateSelection: function(item) {
- var id = item._id,
- selectedItems = this._selectedItems;
- if (item._selected) {
- if (selectedItems[id] !== item) {
- this._selectedItemCount++;
- selectedItems[id] = item;
- }
- } else if (selectedItems[id] === item) {
- this._selectedItemCount--;
- delete selectedItems[id];
- }
- },
-
- selectAll: function() {
- var layers = this.layers;
- for (var i = 0, l = layers.length; i < l; i++)
- layers[i].setFullySelected(true);
- },
-
- deselectAll: function() {
- var selectedItems = this._selectedItems;
- for (var i in selectedItems)
- selectedItems[i].setFullySelected(false);
- },
-
- hitTest: function(point, options) {
- point = Point.read(arguments);
- options = HitResult.getOptions(Base.read(arguments));
- for (var i = this.layers.length - 1; i >= 0; i--) {
- var res = this.layers[i].hitTest(point, options);
- if (res) return res;
- }
- return null;
- }
-}, new function() {
- function getItems(project, match, list) {
- var layers = project.layers,
- items = list && [];
- for (var i = 0, l = layers.length; i < l; i++) {
- var res = layers[i][list ? 'getItems' : 'getItem'](match);
- if (list) {
- items.push.apply(items, res);
- } else if (res)
- return res;
- }
- return list ? items : null;
- }
-
- return {
- getItems: function(match) {
- return getItems(this, match, true);
- },
-
- getItem: function(match) {
- return getItems(this, match, false);
- }
- };
-}, {
-
- importJSON: function(json) {
- this.activate();
- var layer = this.activeLayer;
- return Base.importJSON(json, layer && layer.isEmpty() && layer);
- },
-
- draw: function(ctx, matrix, ratio) {
- this._drawCount++;
- ctx.save();
- matrix.applyToContext(ctx);
- var param = new Base({
- offset: new Point(0, 0),
- ratio: ratio,
- transforms: [matrix],
- trackTransforms: true
- });
- for (var i = 0, l = this.layers.length; i < l; i++)
- this.layers[i].draw(ctx, param);
- ctx.restore();
-
- if (this._selectedItemCount > 0) {
- ctx.save();
- ctx.strokeWidth = 1;
- for (var id in this._selectedItems) {
- var item = this._selectedItems[id];
- if (item._drawCount === this._drawCount
- && (item._drawSelected || item._boundsSelected)) {
- var color = item.getSelectedColor()
- || item.getLayer().getSelectedColor();
- ctx.strokeStyle = ctx.fillStyle = color
- ? color.toCanvasStyle(ctx) : '#009dec';
- var mx = item._globalMatrix;
- if (item._drawSelected)
- item._drawSelected(ctx, mx);
- if (item._boundsSelected) {
- var coords = mx._transformCorners(
- item._getBounds('getBounds'));
- ctx.beginPath();
- for (var i = 0; i < 8; i++)
- ctx[i === 0 ? 'moveTo' : 'lineTo'](
- coords[i], coords[++i]);
- ctx.closePath();
- ctx.stroke();
- for (var i = 0; i < 8; i++) {
- ctx.beginPath();
- ctx.rect(coords[i] - 2, coords[++i] - 2, 4, 4);
- ctx.fill();
- }
- }
- }
- }
- ctx.restore();
- }
- }
-});
-
-var Symbol = Base.extend({
- _class: 'Symbol',
-
- initialize: function Symbol(item, dontCenter) {
- this._id = Symbol._id = (Symbol._id || 0) + 1;
- this.project = paper.project;
- this.project.symbols.push(this);
- if (item)
- this.setDefinition(item, dontCenter);
- this._instances = {};
- },
-
- _serialize: function(options, dictionary) {
- return dictionary.add(this, function() {
- return Base.serialize([this._class, this._definition],
- options, false, dictionary);
- });
- },
-
- _changed: function(flags) {
- Base.each(this._instances, function(item) {
- item._changed(flags);
- });
- },
-
- getDefinition: function() {
- return this._definition;
- },
-
- setDefinition: function(item ) {
- if (item._parentSymbol)
- item = item.clone();
- if (this._definition)
- delete this._definition._parentSymbol;
- this._definition = item;
- item.remove();
- item.setSelected(false);
- if (!arguments[1])
- item.setPosition(new Point());
- item._parentSymbol = this;
- this._changed(5);
- },
-
- place: function(position) {
- return new PlacedSymbol(this, position);
- },
-
- clone: function() {
- return new Symbol(this._definition.clone(false));
- }
-});
-
-var Item = Base.extend(Callback, {
- statics: {
- extend: function extend(src) {
- if (src._serializeFields)
- src._serializeFields = new Base(
- this.prototype._serializeFields, src._serializeFields);
- var res = extend.base.apply(this, arguments),
- proto = res.prototype,
- name = proto._class;
- if (name)
- proto._type = Base.hyphenate(name);
- return res;
- }
- },
-
- _class: 'Item',
- _transformContent: true,
- _boundsSelected: false,
- _serializeFields: {
- name: null,
- matrix: new Matrix(),
- locked: false,
- visible: true,
- blendMode: 'normal',
- opacity: 1,
- guide: false,
- selected: false,
- clipMask: false,
- data: {}
- },
-
- initialize: function Item() {
- },
-
- _initialize: function(props, point) {
- this._id = Item._id = (Item._id || 0) + 1;
- if (!this._project) {
- var project = paper.project;
- if (props && props.insert === false) {
- this._setProject(project);
- } else {
- (project.activeLayer || new Layer()).addChild(this);
- }
- }
- this._style = new Style(this._project._currentStyle, this);
- var matrix = this._matrix = new Matrix();
- if (point)
- matrix.translate(point);
- matrix._owner = this;
- return props ? this._set(props, { insert: true }) : true;
- },
-
- _events: new function() {
-
- var mouseFlags = {
- mousedown: {
- mousedown: 1,
- mousedrag: 1,
- click: 1,
- doubleclick: 1
- },
- mouseup: {
- mouseup: 1,
- mousedrag: 1,
- click: 1,
- doubleclick: 1
- },
- mousemove: {
- mousedrag: 1,
- mousemove: 1,
- mouseenter: 1,
- mouseleave: 1
- }
- };
-
- var mouseEvent = {
- install: function(type) {
- var counters = this._project.view._eventCounters;
- if (counters) {
- for (var key in mouseFlags) {
- counters[key] = (counters[key] || 0)
- + (mouseFlags[key][type] || 0);
- }
- }
- },
- uninstall: function(type) {
- var counters = this._project.view._eventCounters;
- if (counters) {
- for (var key in mouseFlags)
- counters[key] -= mouseFlags[key][type] || 0;
- }
- }
- };
-
- return Base.each(['onMouseDown', 'onMouseUp', 'onMouseDrag', 'onClick',
- 'onDoubleClick', 'onMouseMove', 'onMouseEnter', 'onMouseLeave'],
- function(name) {
- this[name] = mouseEvent;
- }, {
- onFrame: {
- install: function() {
- this._animateItem(true);
- },
- uninstall: function() {
- this._animateItem(false);
- }
- },
-
- onLoad: {}
- }
- );
- },
-
- _animateItem: function(animate) {
- this._project.view._animateItem(this, animate);
- },
-
- _serialize: function(options, dictionary) {
- var props = {},
- that = this;
-
- function serialize(fields) {
- for (var key in fields) {
- var value = that[key];
- if (!Base.equals(value, key === 'leading'
- ? fields.fontSize * 1.2 : fields[key])) {
- props[key] = Base.serialize(value, options,
- key !== 'data', dictionary);
- }
- }
- }
-
- serialize(this._serializeFields);
- if (!(this instanceof Group))
- serialize(this._style._defaults);
- return [ this._class, props ];
- },
-
- _changed: function(flags) {
- var parent = this._parent,
- project = this._project,
- symbol = this._parentSymbol;
- this._drawCount = null;
- if (flags & 4) {
- delete this._bounds;
- delete this._position;
- }
- if (parent && (flags
- & (4 | 8))) {
- parent._clearBoundsCache();
- }
- if (flags & 2) {
- this._clearBoundsCache();
- }
- if (project) {
- if (flags & 1) {
- project._needsRedraw = true;
- }
- if (project._changes) {
- var entry = project._changesById[this._id];
- if (entry) {
- entry.flags |= flags;
- } else {
- entry = { item: this, flags: flags };
- project._changesById[this._id] = entry;
- project._changes.push(entry);
- }
- }
- }
- if (symbol)
- symbol._changed(flags);
- },
-
- set: function(props) {
- if (props)
- this._set(props);
- return this;
- },
-
- getId: function() {
- return this._id;
- },
-
- getType: function() {
- return this._type;
- },
-
- getName: function() {
- return this._name;
- },
-
- setName: function(name, unique) {
-
- if (this._name)
- this._removeNamed();
- if (name === (+name) + '')
- throw new Error(
- 'Names consisting only of numbers are not supported.');
- if (name && this._parent) {
- var children = this._parent._children,
- namedChildren = this._parent._namedChildren,
- orig = name,
- i = 1;
- while (unique && children[name])
- name = orig + ' ' + (i++);
- (namedChildren[name] = namedChildren[name] || []).push(this);
- children[name] = this;
- }
- this._name = name || undefined;
- this._changed(32);
- },
-
- getStyle: function() {
- return this._style;
- },
-
- setStyle: function(style) {
- this.getStyle().set(style);
- },
-
- hasFill: function() {
- return this.getStyle().hasFill();
- },
-
- hasStroke: function() {
- return this.getStyle().hasStroke();
- },
-
- hasShadow: function() {
- return this.getStyle().hasShadow();
- }
-}, Base.each(['locked', 'visible', 'blendMode', 'opacity', 'guide'],
- function(name) {
- var part = Base.capitalize(name),
- name = '_' + name;
- this['get' + part] = function() {
- return this[name];
- };
- this['set' + part] = function(value) {
- if (value != this[name]) {
- this[name] = value;
- this._changed(name === '_locked'
- ? 32 : 33);
- }
- };
-}, {}), {
-
- _locked: false,
-
- _visible: true,
-
- _blendMode: 'normal',
-
- _opacity: 1,
-
- _guide: false,
-
- isSelected: function() {
- if (this._children) {
- for (var i = 0, l = this._children.length; i < l; i++)
- if (this._children[i].isSelected())
- return true;
- }
- return this._selected;
- },
-
- setSelected: function(selected ) {
- if (this._children && !arguments[1]) {
- for (var i = 0, l = this._children.length; i < l; i++)
- this._children[i].setSelected(selected);
- }
- if ((selected = !!selected) != this._selected) {
- this._selected = selected;
- this._project._updateSelection(this);
- this._changed(33);
- }
- },
-
- _selected: false,
-
- isFullySelected: function() {
- if (this._children && this._selected) {
- for (var i = 0, l = this._children.length; i < l; i++)
- if (!this._children[i].isFullySelected())
- return false;
- return true;
- }
- return this._selected;
- },
-
- setFullySelected: function(selected) {
- if (this._children) {
- for (var i = 0, l = this._children.length; i < l; i++)
- this._children[i].setFullySelected(selected);
- }
- this.setSelected(selected, true);
- },
-
- isClipMask: function() {
- return this._clipMask;
- },
-
- setClipMask: function(clipMask) {
- if (this._clipMask != (clipMask = !!clipMask)) {
- this._clipMask = clipMask;
- if (clipMask) {
- this.setFillColor(null);
- this.setStrokeColor(null);
- }
- this._changed(33);
- if (this._parent)
- this._parent._changed(256);
- }
- },
-
- _clipMask: false,
-
- getData: function() {
- if (!this._data)
- this._data = {};
- return this._data;
- },
-
- setData: function(data) {
- this._data = data;
- },
-
- getPosition: function() {
- var pos = this._position
- || (this._position = this.getBounds().getCenter(true));
- return new (arguments[0] ? Point : LinkedPoint)
- (pos.x, pos.y, this, 'setPosition');
- },
-
- setPosition: function() {
- this.translate(Point.read(arguments).subtract(this.getPosition(true)));
- }
-}, Base.each(['getBounds', 'getStrokeBounds', 'getHandleBounds', 'getRoughBounds'],
- function(name) {
- this[name] = function() {
- var getter = this._boundsGetter,
- bounds = this._getCachedBounds(typeof getter == 'string'
- ? getter : getter && getter[name] || name, arguments[0]);
- return name === 'getBounds'
- ? new LinkedRectangle(bounds.x, bounds.y, bounds.width,
- bounds.height, this, 'setBounds')
- : bounds;
- };
- },
-{
- _getCachedBounds: function(getter, matrix, cacheItem) {
- var cache = (!matrix || matrix.equals(this._matrix)) && getter;
- if (cacheItem && this._parent) {
- var id = cacheItem._id,
- ref = this._parent._boundsCache
- = this._parent._boundsCache || {
- ids: {},
- list: []
- };
- if (!ref.ids[id]) {
- ref.list.push(cacheItem);
- ref.ids[id] = cacheItem;
- }
- }
- if (cache && this._bounds && this._bounds[cache])
- return this._bounds[cache].clone();
- var identity = this._matrix.isIdentity();
- matrix = !matrix || matrix.isIdentity()
- ? identity ? null : this._matrix
- : identity ? matrix : matrix.clone().concatenate(this._matrix);
- var bounds = this._getBounds(getter, matrix, cache ? this : cacheItem);
- if (cache) {
- if (!this._bounds)
- this._bounds = {};
- this._bounds[cache] = bounds.clone();
- }
- return bounds;
- },
-
- _clearBoundsCache: function() {
- if (this._boundsCache) {
- for (var i = 0, list = this._boundsCache.list, l = list.length;
- i < l; i++) {
- var item = list[i];
- delete item._bounds;
- if (item != this && item._boundsCache)
- item._clearBoundsCache();
- }
- delete this._boundsCache;
- }
- },
-
- _getBounds: function(getter, matrix, cacheItem) {
- var children = this._children;
- if (!children || children.length == 0)
- return new Rectangle();
- var x1 = Infinity,
- x2 = -x1,
- y1 = x1,
- y2 = x2;
- for (var i = 0, l = children.length; i < l; i++) {
- var child = children[i];
- if (child._visible && !child.isEmpty()) {
- var rect = child._getCachedBounds(getter, matrix, cacheItem);
- x1 = Math.min(rect.x, x1);
- y1 = Math.min(rect.y, y1);
- x2 = Math.max(rect.x + rect.width, x2);
- y2 = Math.max(rect.y + rect.height, y2);
- }
- }
- return isFinite(x1)
- ? new Rectangle(x1, y1, x2 - x1, y2 - y1)
- : new Rectangle();
- },
-
- setBounds: function(rect) {
- rect = Rectangle.read(arguments);
- var bounds = this.getBounds(),
- matrix = new Matrix(),
- center = rect.getCenter();
- matrix.translate(center);
- if (rect.width != bounds.width || rect.height != bounds.height) {
- matrix.scale(
- bounds.width != 0 ? rect.width / bounds.width : 1,
- bounds.height != 0 ? rect.height / bounds.height : 1);
- }
- center = bounds.getCenter();
- matrix.translate(-center.x, -center.y);
- this.transform(matrix);
- }
-
-}), {
- getMatrix: function() {
- return this._matrix;
- },
-
- setMatrix: function(matrix) {
- this._matrix.initialize(matrix);
- if (this._transformContent)
- this.applyMatrix(true);
- this._changed(5);
- },
-
- getGlobalMatrix: function() {
- return this._drawCount === this._project._drawCount
- && this._globalMatrix || null;
- },
-
- getTransformContent: function() {
- return this._transformContent;
- },
-
- setTransformContent: function(transform) {
- this._transformContent = transform;
- if (transform)
- this.applyMatrix();
- },
-
- getProject: function() {
- return this._project;
- },
-
- _setProject: function(project) {
- if (this._project != project) {
- var hasOnFrame = this.responds('frame');
- if (hasOnFrame)
- this._animateItem(false);
- this._project = project;
- if (hasOnFrame)
- this._animateItem(true);
- if (this._children) {
- for (var i = 0, l = this._children.length; i < l; i++) {
- this._children[i]._setProject(project);
- }
- }
- }
- },
-
- getLayer: function() {
- var parent = this;
- while (parent = parent._parent) {
- if (parent instanceof Layer)
- return parent;
- }
- return null;
- },
-
- getParent: function() {
- return this._parent;
- },
-
- setParent: function(item) {
- return item.addChild(this);
- },
-
- getChildren: function() {
- return this._children;
- },
-
- setChildren: function(items) {
- this.removeChildren();
- this.addChildren(items);
- },
-
- getFirstChild: function() {
- return this._children && this._children[0] || null;
- },
-
- getLastChild: function() {
- return this._children && this._children[this._children.length - 1]
- || null;
- },
-
- getNextSibling: function() {
- return this._parent && this._parent._children[this._index + 1] || null;
- },
-
- getPreviousSibling: function() {
- return this._parent && this._parent._children[this._index - 1] || null;
- },
-
- getIndex: function() {
- return this._index;
- },
-
- isInserted: function() {
- return this._parent ? this._parent.isInserted() : false;
- },
-
- equals: function(item) {
- return item === this || item && this._class === item._class
- && this._style.equals(item._style)
- && this._matrix.equals(item._matrix)
- && this._locked === item._locked
- && this._visible === item._visible
- && this._blendMode === item._blendMode
- && this._opacity === item._opacity
- && this._clipMask === item._clipMask
- && this._guide === item._guide
- && this._equals(item)
- || false;
- },
-
- _equals: function(item) {
- return Base.equals(this._children, item._children);
- },
-
- clone: function(insert) {
- return this._clone(new this.constructor({ insert: false }), insert);
- },
-
- _clone: function(copy, insert) {
- copy.setStyle(this._style);
- if (this._children) {
- for (var i = 0, l = this._children.length; i < l; i++)
- copy.addChild(this._children[i].clone(false), true);
- }
- if (insert || insert === undefined)
- copy.insertAbove(this);
- var keys = ['_locked', '_visible', '_blendMode', '_opacity',
- '_clipMask', '_guide'];
- for (var i = 0, l = keys.length; i < l; i++) {
- var key = keys[i];
- if (this.hasOwnProperty(key))
- copy[key] = this[key];
- }
- copy._matrix.initialize(this._matrix);
- copy._data = this._data ? Base.clone(this._data) : null;
- copy.setSelected(this._selected);
- if (this._name)
- copy.setName(this._name, true);
- return copy;
- },
-
- copyTo: function(itemOrProject) {
- return itemOrProject.addChild(this.clone(false));
- },
-
- rasterize: function(resolution) {
- var bounds = this.getStrokeBounds(),
- scale = (resolution || 72) / 72,
- topLeft = bounds.getTopLeft().floor(),
- bottomRight = bounds.getBottomRight().ceil()
- size = new Size(bottomRight.subtract(topLeft)),
- canvas = CanvasProvider.getCanvas(size),
- ctx = canvas.getContext('2d'),
- matrix = new Matrix().scale(scale).translate(topLeft.negate());
- ctx.save();
- matrix.applyToContext(ctx);
- this.draw(ctx, new Base({ transforms: [matrix] }));
- ctx.restore();
- var raster = new Raster({
- canvas: canvas,
- insert: false
- });
- raster.setPosition(topLeft.add(size.divide(2)));
- raster.insertAbove(this);
- return raster;
- },
-
- contains: function() {
- return !!this._contains(
- this._matrix._inverseTransform(Point.read(arguments)));
- },
-
- _contains: function(point) {
- if (this._children) {
- for (var i = this._children.length - 1; i >= 0; i--) {
- if (this._children[i].contains(point))
- return true;
- }
- return false;
- }
- return point.isInside(this._getBounds('getBounds'));
- },
-
- hitTest: function(point, options) {
- point = Point.read(arguments);
- options = HitResult.getOptions(Base.read(arguments));
-
- if (this._locked || !this._visible || this._guide && !options.guides)
- return null;
-
- if (!this._children && !this.getRoughBounds()
- .expand(2 * options.tolerance)._containsPoint(point))
- return null;
- point = this._matrix._inverseTransform(point);
-
- var that = this,
- res;
- function checkBounds(type, part) {
- var pt = bounds['get' + part]();
- if (point.getDistance(pt) < options.tolerance)
- return new HitResult(type, that,
- { name: Base.hyphenate(part), point: pt });
- }
-
- if ((options.center || options.bounds) &&
- !(this instanceof Layer && !this._parent)) {
- var bounds = this._getBounds('getBounds');
- if (options.center)
- res = checkBounds('center', 'Center');
- if (!res && options.bounds) {
- var points = [
- 'TopLeft', 'TopRight', 'BottomLeft', 'BottomRight',
- 'LeftCenter', 'TopCenter', 'RightCenter', 'BottomCenter'
- ];
- for (var i = 0; i < 8 && !res; i++)
- res = checkBounds('bounds', points[i]);
- }
- }
-
- if ((res || (res = this._children || !(options.guides && !this._guide
- || options.selected && !this._selected)
- ? this._hitTest(point, options) : null))
- && res.point) {
- res.point = that._matrix.transform(res.point);
- }
- return res;
- },
-
- _hitTest: function(point, options) {
- var children = this._children;
- if (children) {
- for (var i = children.length - 1, res; i >= 0; i--)
- if (res = children[i].hitTest(point, options))
- return res;
- } else if (options.fill && this.hasFill() && this._contains(point)) {
- return new HitResult('fill', this);
- }
- },
-
- matches: function(match) {
- function matchObject(obj1, obj2) {
- for (var i in obj1) {
- if (obj1.hasOwnProperty(i)) {
- var val1 = obj1[i],
- val2 = obj2[i];
- if (Base.isPlainObject(val1) && Base.isPlainObject(val2)) {
- if (!matchObject(val1, val2))
- return false;
- } else if (!Base.equals(val1, val2)) {
- return false;
- }
- }
- }
- return true;
- }
- for (var key in match) {
- if (match.hasOwnProperty(key)) {
- var value = this[key],
- compare = match[key];
- if (compare instanceof RegExp) {
- if (!compare.test(value))
- return false;
- } else if (typeof compare === 'function') {
- if (!compare(value))
- return false;
- } else if (Base.isPlainObject(compare)) {
- if (!matchObject(compare, value))
- return false;
- } else if (!Base.equals(value, compare)) {
- return false;
- }
- }
- }
- return true;
- }
-}, new function() {
- function getItems(item, match, list) {
- var children = item._children,
- items = list && [];
- for (var i = 0, l = children && children.length; i < l; i++) {
- var child = children[i];
- if (child.matches(match)) {
- if (list) {
- items.push(child);
- } else {
- return child;
- }
- }
- var res = getItems(child, match, list);
- if (list) {
- items.push.apply(items, res);
- } else if (res) {
- return res;
- }
- }
- return list ? items : null;
- }
-
- return {
- getItems: function(match) {
- return getItems(this, match, true);
- },
-
- getItem: function(match) {
- return getItems(this, match, false);
- }
- };
-}, {
-
- importJSON: function(json) {
- var res = Base.importJSON(json, this);
- return res !== this
- ? this.addChild(res)
- : res;
- },
-
- addChild: function(item, _preserve) {
- return this.insertChild(undefined, item, _preserve);
- },
-
- insertChild: function(index, item, _preserve) {
- var res = this.insertChildren(index, [item], _preserve);
- return res && res[0];
- },
-
- addChildren: function(items, _preserve) {
- return this.insertChildren(this._children.length, items, _preserve);
- },
-
- insertChildren: function(index, items, _preserve, _type) {
- var children = this._children;
- if (children && items && items.length > 0) {
- items = Array.prototype.slice.apply(items);
- for (var i = items.length - 1; i >= 0; i--) {
- var item = items[i];
- if (_type && item._type !== _type)
- items.splice(i, 1);
- else
- item._remove(true);
- }
- Base.splice(children, items, index, 0);
- for (var i = 0, l = items.length; i < l; i++) {
- var item = items[i];
- item._parent = this;
- item._setProject(this._project);
- if (item._name)
- item.setName(item._name);
- }
- this._changed(7);
- } else {
- items = null;
- }
- return items;
- },
-
- _insert: function(above, item, _preserve) {
- if (!item._parent)
- return null;
- var index = item._index + (above ? 1 : 0);
- if (item._parent === this._parent && index > this._index)
- index--;
- return item._parent.insertChild(index, this, _preserve);
- },
-
- insertAbove: function(item, _preserve) {
- return this._insert(true, item, _preserve);
- },
-
- insertBelow: function(item, _preserve) {
- return this._insert(false, item, _preserve);
- },
-
- sendToBack: function() {
- return this._parent.insertChild(0, this);
- },
-
- bringToFront: function() {
- return this._parent.addChild(this);
- },
-
- appendTop: '#addChild',
-
- appendBottom: function(item) {
- return this.insertChild(0, item);
- },
-
- moveAbove: '#insertAbove',
-
- moveBelow: '#insertBelow',
-
- reduce: function() {
- if (this._children && this._children.length === 1) {
- var child = this._children[0];
- child.insertAbove(this);
- child.setStyle(this._style);
- this.remove();
- return child;
- }
- return this;
- },
-
- _removeNamed: function() {
- var children = this._parent._children,
- namedChildren = this._parent._namedChildren,
- name = this._name,
- namedArray = namedChildren[name],
- index = namedArray ? namedArray.indexOf(this) : -1;
- if (index == -1)
- return;
- if (children[name] == this)
- delete children[name];
- namedArray.splice(index, 1);
- if (namedArray.length) {
- children[name] = namedArray[namedArray.length - 1];
- } else {
- delete namedChildren[name];
- }
- },
-
- _remove: function(notify) {
- if (this._parent) {
- if (this._name)
- this._removeNamed();
- if (this._index != null)
- Base.splice(this._parent._children, null, this._index, 1);
- if (this.responds('frame'))
- this._animateItem(false);
- if (notify)
- this._parent._changed(7);
- this._parent = null;
- return true;
- }
- return false;
- },
-
- remove: function() {
- return this._remove(true);
- },
-
- removeChildren: function(from, to) {
- if (!this._children)
- return null;
- from = from || 0;
- to = Base.pick(to, this._children.length);
- var removed = Base.splice(this._children, null, from, to - from);
- for (var i = removed.length - 1; i >= 0; i--)
- removed[i]._remove(false);
- if (removed.length > 0)
- this._changed(7);
- return removed;
- },
-
- clear: '#removeChildren',
-
- reverseChildren: function() {
- if (this._children) {
- this._children.reverse();
- for (var i = 0, l = this._children.length; i < l; i++)
- this._children[i]._index = i;
- this._changed(7);
- }
- },
-
- isEmpty: function() {
- return !this._children || this._children.length == 0;
- },
-
- isEditable: function() {
- var item = this;
- while (item) {
- if (!item._visible || item._locked)
- return false;
- item = item._parent;
- }
- return true;
- },
-
- _getOrder: function(item) {
- function getList(item) {
- var list = [];
- do {
- list.unshift(item);
- } while (item = item._parent);
- return list;
- }
- var list1 = getList(this),
- list2 = getList(item);
- for (var i = 0, l = Math.min(list1.length, list2.length); i < l; i++) {
- if (list1[i] != list2[i]) {
- return list1[i]._index < list2[i]._index ? 1 : -1;
- }
- }
- return 0;
- },
-
- hasChildren: function() {
- return this._children && this._children.length > 0;
- },
-
- isAbove: function(item) {
- return this._getOrder(item) === -1;
- },
-
- isBelow: function(item) {
- return this._getOrder(item) === 1;
- },
-
- isParent: function(item) {
- return this._parent === item;
- },
-
- isChild: function(item) {
- return item && item._parent === this;
- },
-
- isDescendant: function(item) {
- var parent = this;
- while (parent = parent._parent) {
- if (parent == item)
- return true;
- }
- return false;
- },
-
- isAncestor: function(item) {
- return item ? item.isDescendant(this) : false;
- },
-
- isGroupedWith: function(item) {
- var parent = this._parent;
- while (parent) {
- if (parent._parent
- && /^(group|layer|compound-path)$/.test(parent._type)
- && item.isDescendant(parent))
- return true;
- parent = parent._parent;
- }
- return false;
- },
-
- scale: function(hor, ver , center) {
- if (arguments.length < 2 || typeof ver === 'object') {
- center = ver;
- ver = hor;
- }
- return this.transform(new Matrix().scale(hor, ver,
- center || this.getPosition(true)));
- },
-
- translate: function() {
- var mx = new Matrix();
- return this.transform(mx.translate.apply(mx, arguments));
- },
-
- rotate: function(angle, center) {
- return this.transform(new Matrix().rotate(angle,
- center || this.getPosition(true)));
- },
-
- shear: function(hor, ver, center) {
- if (arguments.length < 2 || typeof ver === 'object') {
- center = ver;
- ver = hor;
- }
- return this.transform(new Matrix().shear(hor, ver,
- center || this.getPosition(true)));
- },
-
- transform: function(matrix ) {
- var bounds = this._bounds,
- position = this._position;
- this._matrix.preConcatenate(matrix);
- if (this._transformContent || arguments[1])
- this.applyMatrix(true);
- this._changed(5);
- if (bounds && matrix.getRotation() % 90 === 0) {
- for (var key in bounds) {
- var rect = bounds[key];
- matrix._transformBounds(rect, rect);
- }
- var getter = this._boundsGetter,
- rect = bounds[getter && getter.getBounds || getter || 'getBounds'];
- if (rect)
- this._position = rect.getCenter(true);
- this._bounds = bounds;
- } else if (position) {
- this._position = matrix._transformPoint(position, position);
- }
- return this;
- },
-
- _applyMatrix: function(matrix, applyMatrix) {
- var children = this._children;
- if (children && children.length > 0) {
- for (var i = 0, l = children.length; i < l; i++)
- children[i].transform(matrix, applyMatrix);
- return true;
- }
- },
-
- applyMatrix: function(_dontNotify) {
- var matrix = this._matrix;
- if (this._applyMatrix(matrix, true)) {
- var style = this._style,
- fillColor = style.getFillColor(true),
- strokeColor = style.getStrokeColor(true);
- if (fillColor)
- fillColor.transform(matrix);
- if (strokeColor)
- strokeColor.transform(matrix);
- matrix.reset();
- }
- if (!_dontNotify)
- this._changed(5);
- },
-
- globalToLocal: function() {
- var matrix = this.getGlobalMatrix();
- return matrix && matrix._transformPoint(Point.read(arguments));
- },
-
- localToGlobal: function() {
- var matrix = this.getGlobalMatrix();
- return matrix && matrix._inverseTransform(Point.read(arguments));
- },
-
- fitBounds: function(rectangle, fill) {
- rectangle = Rectangle.read(arguments);
- var bounds = this.getBounds(),
- itemRatio = bounds.height / bounds.width,
- rectRatio = rectangle.height / rectangle.width,
- scale = (fill ? itemRatio > rectRatio : itemRatio < rectRatio)
- ? rectangle.width / bounds.width
- : rectangle.height / bounds.height,
- newBounds = new Rectangle(new Point(),
- new Size(bounds.width * scale, bounds.height * scale));
- newBounds.setCenter(rectangle.getCenter());
- this.setBounds(newBounds);
- },
-
- _setStyles: function(ctx) {
- var style = this._style,
- fillColor = style.getFillColor(),
- strokeColor = style.getStrokeColor(),
- shadowColor = style.getShadowColor();
- if (fillColor)
- ctx.fillStyle = fillColor.toCanvasStyle(ctx);
- if (strokeColor) {
- var strokeWidth = style.getStrokeWidth();
- if (strokeWidth > 0) {
- ctx.strokeStyle = strokeColor.toCanvasStyle(ctx);
- ctx.lineWidth = strokeWidth;
- var strokeJoin = style.getStrokeJoin(),
- strokeCap = style.getStrokeCap(),
- miterLimit = style.getMiterLimit();
- if (strokeJoin)
- ctx.lineJoin = strokeJoin;
- if (strokeCap)
- ctx.lineCap = strokeCap;
- if (miterLimit)
- ctx.miterLimit = miterLimit;
- if (paper.support.nativeDash) {
- var dashArray = style.getDashArray(),
- dashOffset = style.getDashOffset();
- if (dashArray && dashArray.length) {
- if ('setLineDash' in ctx) {
- ctx.setLineDash(dashArray);
- ctx.lineDashOffset = dashOffset;
- } else {
- ctx.mozDash = dashArray;
- ctx.mozDashOffset = dashOffset;
- }
- }
- }
- }
- }
- if (shadowColor) {
- var shadowBlur = style.getShadowBlur();
- if (shadowBlur > 0) {
- ctx.shadowColor = shadowColor.toCanvasStyle(ctx);
- ctx.shadowBlur = shadowBlur;
- var offset = this.getShadowOffset();
- ctx.shadowOffsetX = offset.x;
- ctx.shadowOffsetY = offset.y;
- }
- }
- },
-
- draw: function(ctx, param) {
- if (!this._visible || this._opacity === 0)
- return;
- this._drawCount = this._project._drawCount;
- var trackTransforms = param.trackTransforms,
- transforms = param.transforms,
- parentMatrix = transforms[transforms.length - 1],
- globalMatrix = parentMatrix.clone().concatenate(this._matrix);
- if (trackTransforms)
- transforms.push(this._globalMatrix = globalMatrix);
- var blendMode = this._blendMode,
- opacity = this._opacity,
- normalBlend = blendMode === 'normal',
- nativeBlend = BlendMode.nativeModes[blendMode],
- direct = normalBlend && opacity === 1
- || (nativeBlend || normalBlend && opacity < 1)
- && this._canComposite(),
- mainCtx, itemOffset, prevOffset;
- if (!direct) {
- var bounds = this.getStrokeBounds(parentMatrix);
- if (!bounds.width || !bounds.height)
- return;
- prevOffset = param.offset;
- itemOffset = param.offset = bounds.getTopLeft().floor();
- mainCtx = ctx;
- ctx = CanvasProvider.getContext(
- bounds.getSize().ceil().add(new Size(1, 1)), param.ratio);
- }
- ctx.save();
- if (direct) {
- ctx.globalAlpha = opacity;
- if (nativeBlend)
- ctx.globalCompositeOperation = blendMode;
- } else {
- ctx.translate(-itemOffset.x, -itemOffset.y);
- }
- (direct ? this._matrix : globalMatrix).applyToContext(ctx);
- if (!direct && param.clipItem)
- param.clipItem.draw(ctx, param.extend({ clip: true }));
- this._draw(ctx, param);
- ctx.restore();
- if (trackTransforms)
- transforms.pop();
- if (param.clip)
- ctx.clip();
- if (!direct) {
- BlendMode.process(blendMode, ctx, mainCtx, opacity,
- itemOffset.subtract(prevOffset).multiply(param.ratio));
- CanvasProvider.release(ctx);
- param.offset = prevOffset;
- }
- },
-
- _canComposite: function() {
- return false;
- }
-}, Base.each(['down', 'drag', 'up', 'move'], function(name) {
- this['removeOn' + Base.capitalize(name)] = function() {
- var hash = {};
- hash[name] = true;
- return this.removeOn(hash);
- };
-}, {
-
- removeOn: function(obj) {
- for (var name in obj) {
- if (obj[name]) {
- var key = 'mouse' + name,
- project = this._project,
- sets = project._removeSets = project._removeSets || {};
- sets[key] = sets[key] || {};
- sets[key][this._id] = this;
- }
- }
- return this;
- }
-}));
-
-var Group = Item.extend({
- _class: 'Group',
- _serializeFields: {
- children: []
- },
-
- initialize: function Group(arg) {
- this._children = [];
- this._namedChildren = {};
- if (!this._initialize(arg))
- this.addChildren(Array.isArray(arg) ? arg : arguments);
- },
-
- _changed: function _changed(flags) {
- _changed.base.call(this, flags);
- if (flags & 2 && this._transformContent
- && !this._matrix.isIdentity()) {
- this.applyMatrix();
- }
- if (flags & (2 | 256)) {
- delete this._clipItem;
- }
- },
-
- _getClipItem: function() {
- if (this._clipItem !== undefined)
- return this._clipItem;
- for (var i = 0, l = this._children.length; i < l; i++) {
- var child = this._children[i];
- if (child._clipMask)
- return this._clipItem = child;
- }
- return this._clipItem = null;
- },
-
- isClipped: function() {
- return !!this._getClipItem();
- },
-
- setClipped: function(clipped) {
- var child = this.getFirstChild();
- if (child)
- child.setClipMask(clipped);
- },
-
- _draw: function(ctx, param) {
- var clipItem = param.clipItem = this._getClipItem();
- if (clipItem)
- clipItem.draw(ctx, param.extend({ clip: true }));
- for (var i = 0, l = this._children.length; i < l; i++) {
- var item = this._children[i];
- if (item !== clipItem)
- item.draw(ctx, param);
- }
- param.clipItem = null;
- }
-});
-
-var Layer = Group.extend({
- _class: 'Layer',
-
- initialize: function Layer(arg) {
- var props = Base.isPlainObject(arg)
- ? new Base(arg)
- : { children: Array.isArray(arg) ? arg : arguments },
- insert = props.insert;
- props.insert = false;
- Group.call(this, props);
- if (insert || insert === undefined) {
- this._project.addChild(this);
- this.activate();
- }
- },
-
- _remove: function _remove(notify) {
- if (this._parent)
- return _remove.base.call(this, notify);
- if (this._index != null) {
- if (this._project.activeLayer === this)
- this._project.activeLayer = this.getNextSibling()
- || this.getPreviousSibling();
- Base.splice(this._project.layers, null, this._index, 1);
- this._project._needsRedraw = true;
- return true;
- }
- return false;
- },
-
- getNextSibling: function getNextSibling() {
- return this._parent ? getNextSibling.base.call(this)
- : this._project.layers[this._index + 1] || null;
- },
-
- getPreviousSibling: function getPreviousSibling() {
- return this._parent ? getPreviousSibling.base.call(this)
- : this._project.layers[this._index - 1] || null;
- },
-
- isInserted: function isInserted() {
- return this._parent ? isInserted.base.call(this) : this._index != null;
- },
-
- activate: function() {
- this._project.activeLayer = this;
- },
-
- _insert: function _insert(above, item, _preserve) {
- if (item instanceof Layer && !item._parent) {
- this._remove(true);
- Base.splice(item._project.layers, [this],
- item._index + (above ? 1 : 0), 0);
- this._setProject(item._project);
- return this;
- }
- return _insert.base.call(this, above, item, _preserve);
- }
-});
-
-var Shape = Item.extend({
- _class: 'Shape',
- _transformContent: false,
- _boundsSelected: true,
-
- initialize: function Shape(shape, center, size, radius, props) {
- this._shape = shape;
- this._size = size;
- this._radius = radius;
- this._initialize(props, center);
- },
-
- _equals: function(item) {
- return this._shape === item._shape
- && this._size.equals(item._size)
- && Base.equals(this._radius, item._radius);
- },
-
- clone: function(insert) {
- return this._clone(new Shape(this._shape, this.getPosition(true),
- this._size.clone(),
- this._radius.clone ? this._radius.clone() : this._radius,
- { insert: false }), insert);
- },
-
- getShape: function() {
- return this._shape;
- },
-
- getSize: function() {
- var size = this._size;
- return new LinkedSize(size.width, size.height, this, 'setSize');
- },
-
- setSize: function() {
- var shape = this._shape,
- size = Size.read(arguments);
- if (!this._size.equals(size)) {
- var width = size.width,
- height = size.height;
- if (shape === 'rectangle') {
- var radius = Size.min(this._radius, size.divide(2));
- this._radius.set(radius.width, radius.height);
- } else if (shape === 'circle') {
- width = height = (width + height) / 2;
- this._radius = width / 2;
- } else if (shape === 'ellipse') {
- this._radius.set(width / 2, height / 2);
- }
- this._size.set(width, height);
- this._changed(5);
- }
- },
-
- getRadius: function() {
- var rad = this._radius;
- return this._shape === 'circle'
- ? rad
- : new LinkedSize(rad.width, rad.height, this, 'setRadius');
- },
-
- setRadius: function(radius) {
- var shape = this._shape;
- if (shape === 'circle') {
- if (radius === this._radius)
- return;
- var size = radius * 2;
- this._radius = radius;
- this._size.set(size, size);
- } else {
- radius = Size.read(arguments);
- if (this._radius.equals(radius))
- return;
- this._radius.set(radius.width, radius.height);
- if (shape === 'rectangle') {
- var size = Size.max(this._size, radius.multiply(2));
- this._size.set(size.width, size.height);
- } else if (shape === 'ellipse') {
- this._size.set(radius.width * 2, radius.height * 2);
- }
- }
- this._changed(5);
- },
-
- isEmpty: function() {
- return false;
- },
-
- toPath: function(insert) {
- var path = new Path[Base.capitalize(this._shape)]({
- center: new Point(),
- size: this._size,
- radius: this._radius,
- insert: false
- });
- path.setStyle(this._style);
- path.transform(this._matrix);
- if (insert || insert === undefined)
- path.insertAbove(this);
- return path;
- },
-
- _draw: function(ctx, param) {
- var style = this._style,
- hasFill = style.hasFill(),
- hasStroke = style.hasStroke(),
- clip = param.clip;
- if (hasFill || hasStroke || clip) {
- var radius = this._radius,
- shape = this._shape;
- ctx.beginPath();
- if (shape === 'circle') {
- ctx.arc(0, 0, radius, 0, Math.PI * 2, true);
- } else {
- var rx = radius.width,
- ry = radius.height,
- kappa = Numerical.KAPPA;
- if (shape === 'ellipse') {
- var cx = rx * kappa,
- cy = ry * kappa;
- ctx.moveTo(-rx, 0);
- ctx.bezierCurveTo(-rx, -cy, -cx, -ry, 0, -ry);
- ctx.bezierCurveTo(cx, -ry, rx, -cy, rx, 0);
- ctx.bezierCurveTo(rx, cy, cx, ry, 0, ry);
- ctx.bezierCurveTo(-cx, ry, -rx, cy, -rx, 0);
- } else {
- var size = this._size,
- width = size.width,
- height = size.height;
- if (rx === 0 && ry === 0) {
- ctx.rect(-width / 2, -height / 2, width, height);
- } else {
- kappa = 1 - kappa;
- var x = width / 2,
- y = height / 2,
- cx = rx * kappa,
- cy = ry * kappa;
- ctx.moveTo(-x, -y + ry);
- ctx.bezierCurveTo(-x, -y + cy, -x + cx, -y, -x + rx, -y);
- ctx.lineTo(x - rx, -y);
- ctx.bezierCurveTo(x - cx, -y, x, -y + cy, x, -y + ry);
- ctx.lineTo(x, y - ry);
- ctx.bezierCurveTo(x, y - cy, x - cx, y, x - rx, y);
- ctx.lineTo(-x + rx, y);
- ctx.bezierCurveTo(-x + cx, y, -x, y - cy, -x, y - ry);
- }
- }
- }
- ctx.closePath();
- }
- if (!clip && (hasFill || hasStroke)) {
- this._setStyles(ctx);
- if (hasFill) {
- ctx.fill(style.getWindingRule());
- ctx.shadowColor = 'rgba(0,0,0,0)';
- }
- if (hasStroke)
- ctx.stroke();
- }
- },
-
- _canComposite: function() {
- return !(this.hasFill() && this.hasStroke());
- },
-
- _getBounds: function(getter, matrix) {
- var rect = new Rectangle(this._size).setCenter(0, 0);
- if (getter !== 'getBounds' && this.hasStroke())
- rect = rect.expand(this.getStrokeWidth());
- return matrix ? matrix._transformBounds(rect) : rect;
- }
-},
-new function() {
-
- function getCornerCenter(that, point, expand) {
- var radius = that._radius;
- if (!radius.isZero()) {
- var halfSize = that._size.divide(2);
- for (var i = 0; i < 4; i++) {
- var dir = new Point(i & 1 ? 1 : -1, i > 1 ? 1 : -1),
- corner = dir.multiply(halfSize),
- center = corner.subtract(dir.multiply(radius)),
- rect = new Rectangle(corner, center);
- if ((expand ? rect.expand(expand) : rect).contains(point))
- return center;
- }
- }
- }
-
- function getEllipseRadius(point, radius) {
- var angle = point.getAngleInRadians(),
- width = radius.width * 2,
- height = radius.height * 2,
- x = width * Math.sin(angle),
- y = height * Math.cos(angle);
- return width * height / (2 * Math.sqrt(x * x + y * y));
- }
-
- return {
- _contains: function _contains(point) {
- if (this._shape === 'rectangle') {
- var center = getCornerCenter(this, point);
- return center
- ? point.subtract(center).divide(this._radius)
- .getLength() <= 1
- : _contains.base.call(this, point);
- } else {
- return point.divide(this.size).getLength() <= 0.5;
- }
- },
-
- _hitTest: function _hitTest(point, options) {
- var hit = false;
- if (this.hasStroke()) {
- var shape = this._shape,
- radius = this._radius,
- strokeWidth = this.getStrokeWidth() + 2 * options.tolerance;
- if (shape === 'rectangle') {
- var center = getCornerCenter(this, point, strokeWidth);
- if (center) {
- var pt = point.subtract(center);
- hit = 2 * Math.abs(pt.getLength()
- - getEllipseRadius(pt, radius)) <= strokeWidth;
- } else {
- var rect = new Rectangle(this._size).setCenter(0, 0),
- outer = rect.expand(strokeWidth),
- inner = rect.expand(-strokeWidth);
- hit = outer._containsPoint(point)
- && !inner._containsPoint(point);
- }
- } else {
- if (shape === 'ellipse')
- radius = getEllipseRadius(point, radius);
- hit = 2 * Math.abs(point.getLength() - radius)
- <= strokeWidth;
- }
- }
- return hit
- ? new HitResult('stroke', this)
- : _hitTest.base.apply(this, arguments);
- }
- };
-}, {
-
-statics: new function() {
- function createShape(shape, point, size, radius, args) {
- return new Shape(shape, point, size, radius, Base.getNamed(args));
- }
-
- return {
- Circle: function() {
- var center = Point.readNamed(arguments, 'center'),
- radius = Base.readNamed(arguments, 'radius');
- return createShape('circle', center, new Size(radius * 2), radius,
- arguments);
- },
-
- Rectangle: function() {
- var rect = Rectangle.readNamed(arguments, 'rectangle'),
- radius = Size.min(Size.readNamed(arguments, 'radius'),
- rect.getSize(true).divide(2));
- return createShape('rectangle', rect.getCenter(true),
- rect.getSize(true), radius, arguments);
- },
-
- Ellipse: function() {
- var ellipse = Shape._readEllipse(arguments);
- radius = ellipse.radius;
- return createShape('ellipse', ellipse.center, radius.multiply(2),
- radius, arguments);
- },
-
- _readEllipse: function(args) {
- var center,
- radius;
- if (Base.hasNamed(args, 'radius')) {
- center = Point.readNamed(args, 'center');
- radius = Size.readNamed(args, 'radius');
- } else {
- var rect = Rectangle.readNamed(args, 'rectangle');
- center = rect.getCenter(true);
- radius = rect.getSize(true).divide(2);
- }
- return { center: center, radius: radius };
- }
- };
-}});
-
-var Raster = Item.extend({
- _class: 'Raster',
- _transformContent: false,
- _boundsGetter: 'getBounds',
- _boundsSelected: true,
- _serializeFields: {
- source: null
- },
-
- initialize: function Raster(object, position) {
- if (!this._initialize(object,
- position !== undefined && Point.read(arguments, 1))) {
- if (typeof object === 'string') {
- this.setSource(object);
- } else {
- this.setImage(object);
- }
- }
- if (!this._size)
- this._size = new Size();
- },
-
- _equals: function(item) {
- return this.getSource() === item.getSource();
- },
-
- clone: function(insert) {
- var param = { insert: false },
- image = this._image;
- if (image) {
- param.image = image;
- } else if (this._canvas) {
- var canvas = param.canvas = CanvasProvider.getCanvas(this._size);
- canvas.getContext('2d').drawImage(this._canvas, 0, 0);
- }
- return this._clone(new Raster(param), insert);
- },
-
- getSize: function() {
- var size = this._size;
- return new LinkedSize(size.width, size.height, this, 'setSize');
- },
-
- setSize: function() {
- var size = Size.read(arguments);
- if (!this._size.equals(size)) {
- var element = this.getElement();
- this.setCanvas(CanvasProvider.getCanvas(size));
- if (element)
- this.getContext(true).drawImage(element, 0, 0,
- size.width, size.height);
- }
- },
-
- getWidth: function() {
- return this._size.width;
- },
-
- getHeight: function() {
- return this._size.height;
- },
-
- isEmpty: function() {
- return this._size.width == 0 && this._size.height == 0;
- },
-
- getPpi: function() {
- var matrix = this._matrix,
- orig = new Point(0, 0).transform(matrix),
- u = new Point(1, 0).transform(matrix).subtract(orig),
- v = new Point(0, 1).transform(matrix).subtract(orig);
- return new Size(
- 72 / u.getLength(),
- 72 / v.getLength()
- );
- },
-
- getImage: function() {
- return this._image;
- },
-
- setImage: function(image) {
- if (this._canvas)
- CanvasProvider.release(this._canvas);
- if (image.getContext) {
- this._image = null;
- this._canvas = image;
- } else {
- this._image = image;
- this._canvas = null;
- }
- this._size = new Size(
- image.naturalWidth || image.width,
- image.naturalHeight || image.height);
- this._context = null;
- this._changed(5 | 129);
- },
-
- getCanvas: function() {
- if (!this._canvas) {
- var ctx = CanvasProvider.getContext(this._size);
- try {
- if (this._image)
- ctx.drawImage(this._image, 0, 0);
- this._canvas = ctx.canvas;
- } catch (e) {
- CanvasProvider.release(ctx);
- }
- }
- return this._canvas;
- },
-
- setCanvas: '#setImage',
-
- getContext: function() {
- if (!this._context)
- this._context = this.getCanvas().getContext('2d');
- if (arguments[0]) {
- this._image = null;
- this._changed(129);
- }
- return this._context;
- },
-
- setContext: function(context) {
- this._context = context;
- },
-
- getSource: function() {
- return this._image && this._image.src || this.toDataURL();
- },
-
- setSource: function(src) {
- var that = this,
- image = document.getElementById(src) || new Image();
-
- function loaded() {
- var view = that._project.view;
- if (view)
- paper = view._scope;
- that.fire('load');
- if (view)
- view.draw(true);
- }
-
- if (image.naturalWidth && image.naturalHeight) {
- setTimeout(loaded, 0);
- } else {
- DomEvent.add(image, {
- load: function() {
- that.setImage(image);
- loaded();
- }
- });
- if (!image.src)
- image.src = src;
- }
- this.setImage(image);
- },
-
- getElement: function() {
- return this._canvas || this._image;
- },
-
- getSubCanvas: function(rect) {
- rect = Rectangle.read(arguments);
- var ctx = CanvasProvider.getContext(rect.getSize());
- ctx.drawImage(this.getCanvas(), rect.x, rect.y,
- rect.width, rect.height, 0, 0, rect.width, rect.height);
- return ctx.canvas;
- },
-
- getSubRaster: function(rect) {
- rect = Rectangle.read(arguments);
- var raster = new Raster({
- canvas: this.getSubCanvas(rect),
- insert: false
- });
- raster.translate(rect.getCenter().subtract(this.getSize().divide(2)));
- raster._matrix.preConcatenate(this._matrix);
- raster.insertAbove(this);
- return raster;
- },
-
- toDataURL: function() {
- var src = this._image && this._image.src;
- if (/^data:/.test(src))
- return src;
- var canvas = this.getCanvas();
- return canvas ? canvas.toDataURL() : null;
- },
-
- drawImage: function(image, point) {
- point = Point.read(arguments, 1);
- this.getContext(true).drawImage(image, point.x, point.y);
- },
-
- getAverageColor: function(object) {
- var bounds, path;
- if (!object) {
- bounds = this.getBounds();
- } else if (object instanceof PathItem) {
- path = object;
- bounds = object.getBounds();
- } else if (object.width) {
- bounds = new Rectangle(object);
- } else if (object.x) {
- bounds = new Rectangle(object.x - 0.5, object.y - 0.5, 1, 1);
- }
- var sampleSize = 32,
- width = Math.min(bounds.width, sampleSize),
- height = Math.min(bounds.height, sampleSize);
- var ctx = Raster._sampleContext;
- if (!ctx) {
- ctx = Raster._sampleContext = CanvasProvider.getContext(
- new Size(sampleSize));
- } else {
- ctx.clearRect(0, 0, sampleSize + 1, sampleSize + 1);
- }
- ctx.save();
- var matrix = new Matrix()
- .scale(width / bounds.width, height / bounds.height)
- .translate(-bounds.x, -bounds.y);
- matrix.applyToContext(ctx);
- if (path)
- path.draw(ctx, new Base({ clip: true, transforms: [matrix] }));
- this._matrix.applyToContext(ctx);
- ctx.drawImage(this.getElement(),
- -this._size.width / 2, -this._size.height / 2);
- ctx.restore();
- var pixels = ctx.getImageData(0.5, 0.5, Math.ceil(width),
- Math.ceil(height)).data,
- channels = [0, 0, 0],
- total = 0;
- for (var i = 0, l = pixels.length; i < l; i += 4) {
- var alpha = pixels[i + 3];
- total += alpha;
- alpha /= 255;
- channels[0] += pixels[i] * alpha;
- channels[1] += pixels[i + 1] * alpha;
- channels[2] += pixels[i + 2] * alpha;
- }
- for (var i = 0; i < 3; i++)
- channels[i] /= total;
- return total ? Color.read(channels) : null;
- },
-
- getPixel: function(point) {
- point = Point.read(arguments);
- var data = this.getContext().getImageData(point.x, point.y, 1, 1).data;
- return new Color('rgb', [data[0] / 255, data[1] / 255, data[2] / 255],
- data[3] / 255);
- },
-
- setPixel: function() {
- var point = Point.read(arguments),
- color = Color.read(arguments),
- components = color._convert('rgb'),
- alpha = color._alpha,
- ctx = this.getContext(true),
- imageData = ctx.createImageData(1, 1),
- data = imageData.data;
- data[0] = components[0] * 255;
- data[1] = components[1] * 255;
- data[2] = components[2] * 255;
- data[3] = alpha != null ? alpha * 255 : 255;
- ctx.putImageData(imageData, point.x, point.y);
- },
-
- createImageData: function(size) {
- size = Size.read(arguments);
- return this.getContext().createImageData(size.width, size.height);
- },
-
- getImageData: function(rect) {
- rect = Rectangle.read(arguments);
- if (rect.isEmpty())
- rect = new Rectangle(this._size);
- return this.getContext().getImageData(rect.x, rect.y,
- rect.width, rect.height);
- },
-
- setImageData: function(data, point) {
- point = Point.read(arguments, 1);
- this.getContext(true).putImageData(data, point.x, point.y);
- },
-
- _getBounds: function(getter, matrix) {
- var rect = new Rectangle(this._size).setCenter(0, 0);
- return matrix ? matrix._transformBounds(rect) : rect;
- },
-
- _hitTest: function(point) {
- if (this._contains(point)) {
- var that = this;
- return new HitResult('pixel', that, {
- offset: point.add(that._size.divide(2)).round(),
- color: {
- get: function() {
- return that.getPixel(this.offset);
- }
- }
- });
- }
- },
-
- _draw: function(ctx) {
- var element = this.getElement();
- if (element) {
- ctx.globalAlpha = this._opacity;
- ctx.drawImage(element,
- -this._size.width / 2, -this._size.height / 2);
- }
- },
-
- _canComposite: function() {
- return true;
- }
-});
-
-var PlacedSymbol = Item.extend({
- _class: 'PlacedSymbol',
- _transformContent: false,
- _boundsGetter: { getBounds: 'getStrokeBounds' },
- _boundsSelected: true,
- _serializeFields: {
- symbol: null
- },
-
- initialize: function PlacedSymbol(arg0, arg1) {
- if (!this._initialize(arg0,
- arg1 !== undefined && Point.read(arguments, 1)))
- this.setSymbol(arg0 instanceof Symbol ? arg0 : new Symbol(arg0));
- },
-
- _equals: function(item) {
- return this._symbol === item._symbol;
- },
-
- getSymbol: function() {
- return this._symbol;
- },
-
- setSymbol: function(symbol) {
- if (this._symbol)
- delete this._symbol._instances[this._id];
- this._symbol = symbol;
- symbol._instances[this._id] = this;
- },
-
- clone: function(insert) {
- return this._clone(new PlacedSymbol({
- symbol: this.symbol,
- insert: false
- }), insert);
- },
-
- isEmpty: function() {
- return this._symbol._definition.isEmpty();
- },
-
- _getBounds: function(getter, matrix) {
- return this.symbol._definition._getCachedBounds(getter, matrix);
- },
-
- _hitTest: function(point, options, matrix) {
- var result = this._symbol._definition._hitTest(point, options, matrix);
- if (result)
- result.item = this;
- return result;
- },
-
- _draw: function(ctx, param) {
- this.symbol._definition.draw(ctx, param);
- }
-
-});
-
-var HitResult = Base.extend({
- _class: 'HitResult',
-
- initialize: function HitResult(type, item, values) {
- this.type = type;
- this.item = item;
- if (values) {
- values.enumerable = true;
- this.inject(values);
- }
- },
-
- statics: {
- getOptions: function(options) {
- return options && options._merged ? options : new Base({
- type: null,
- tolerance: paper.project.options.hitTolerance || 2,
- fill: !options,
- stroke: !options,
- segments: !options,
- handles: false,
- ends: false,
- center: false,
- bounds: false,
- guides: false,
- selected: false,
- _merged: true
- }, options);
- }
- }
-});
-
-var Segment = Base.extend({
- _class: 'Segment',
-
- initialize: function Segment(arg0, arg1, arg2, arg3, arg4, arg5) {
- var count = arguments.length,
- point, handleIn, handleOut;
- if (count === 0) {
- } else if (count === 1) {
- if (arg0.point) {
- point = arg0.point;
- handleIn = arg0.handleIn;
- handleOut = arg0.handleOut;
- } else {
- point = arg0;
- }
- } else if (count === 2 && typeof arg0 === 'number') {
- point = arguments;
- } else if (count <= 3) {
- point = arg0;
- handleIn = arg1;
- handleOut = arg2;
- } else {
- point = arg0 !== undefined ? [ arg0, arg1 ] : null;
- handleIn = arg2 !== undefined ? [ arg2, arg3 ] : null;
- handleOut = arg4 !== undefined ? [ arg4, arg5 ] : null;
- }
- new SegmentPoint(point, this, '_point');
- new SegmentPoint(handleIn, this, '_handleIn');
- new SegmentPoint(handleOut, this, '_handleOut');
- },
-
- _serialize: function(options) {
- return Base.serialize(this.isLinear() ? this._point
- : [this._point, this._handleIn, this._handleOut], options, true);
- },
-
- _changed: function(point) {
- if (!this._path)
- return;
- var curve = this._path._curves && this.getCurve(),
- other;
- if (curve) {
- curve._changed();
- if (other = (curve[point == this._point
- || point == this._handleIn && curve._segment1 == this
- ? 'getPrevious' : 'getNext']())) {
- other._changed();
- }
- }
- this._path._changed(5);
- },
-
- getPoint: function() {
- return this._point;
- },
-
- setPoint: function(point) {
- point = Point.read(arguments);
- this._point.set(point.x, point.y);
- },
-
- getHandleIn: function() {
- return this._handleIn;
- },
-
- setHandleIn: function(point) {
- point = Point.read(arguments);
- this._handleIn.set(point.x, point.y);
- },
-
- getHandleOut: function() {
- return this._handleOut;
- },
-
- setHandleOut: function(point) {
- point = Point.read(arguments);
- this._handleOut.set(point.x, point.y);
- },
-
- isLinear: function() {
- return this._handleIn.isZero() && this._handleOut.isZero();
- },
-
- setLinear: function() {
- this._handleIn.set(0, 0);
- this._handleOut.set(0, 0);
- },
-
- isColinear: function(segment) {
- var next1 = this.getNext(),
- next2 = segment.getNext();
- return this._handleOut.isZero() && next1._handleIn.isZero()
- && segment._handleOut.isZero() && next2._handleIn.isZero()
- && next1._point.subtract(this._point).isColinear(
- next2._point.subtract(segment._point));
- },
-
- isOrthogonal: function() {
- var prev = this.getPrevious(),
- next = this.getNext();
- return prev._handleOut.isZero() && this._handleIn.isZero()
- && this._handleOut.isZero() && next._handleIn.isZero()
- && this._point.subtract(prev._point).isOrthogonal(
- next._point.subtract(this._point));
- },
-
- isArc: function() {
- var next = this.getNext(),
- handle1 = this._handleOut,
- handle2 = next._handleIn,
- kappa = Numerical.KAPPA;
- if (handle1.isOrthogonal(handle2)) {
- var from = this._point,
- to = next._point,
- corner = new Line(from, handle1, true).intersect(
- new Line(to, handle2, true), true);
- return corner && Numerical.isZero(handle1.getLength() /
- corner.subtract(from).getLength() - kappa)
- && Numerical.isZero(handle2.getLength() /
- corner.subtract(to).getLength() - kappa);
- }
- return false;
- },
-
- _isSelected: function(point) {
- var state = this._selectionState;
- return point == this._point ? !!(state & 4)
- : point == this._handleIn ? !!(state & 1)
- : point == this._handleOut ? !!(state & 2)
- : false;
- },
-
- _setSelected: function(point, selected) {
- var path = this._path,
- selected = !!selected,
- state = this._selectionState || 0,
- selection = [
- !!(state & 4),
- !!(state & 1),
- !!(state & 2)
- ];
- if (point === this._point) {
- if (selected) {
- selection[1] = selection[2] = false;
- } else {
- var previous = this.getPrevious(),
- next = this.getNext();
- selection[1] = previous && (previous._point.isSelected()
- || previous._handleOut.isSelected());
- selection[2] = next && (next._point.isSelected()
- || next._handleIn.isSelected());
- }
- selection[0] = selected;
- } else {
- var index = point === this._handleIn ? 1 : 2;
- if (selection[index] != selected) {
- if (selected)
- selection[0] = false;
- selection[index] = selected;
- }
- }
- this._selectionState = (selection[0] ? 4 : 0)
- | (selection[1] ? 1 : 0)
- | (selection[2] ? 2 : 0);
- if (path && state != this._selectionState) {
- path._updateSelection(this, state, this._selectionState);
- path._changed(33);
- }
- },
-
- isSelected: function() {
- return this._isSelected(this._point);
- },
-
- setSelected: function(selected) {
- this._setSelected(this._point, selected);
- },
-
- getIndex: function() {
- return this._index !== undefined ? this._index : null;
- },
-
- getPath: function() {
- return this._path || null;
- },
-
- getCurve: function() {
- var path = this._path,
- index = this._index;
- if (path) {
- if (!path._closed && index == path._segments.length - 1)
- index--;
- return path.getCurves()[index] || null;
- }
- return null;
- },
-
- getLocation: function() {
- var curve = this.getCurve();
- return curve ? new CurveLocation(curve, curve.getNext() ? 0 : 1) : null;
- },
-
- getNext: function() {
- var segments = this._path && this._path._segments;
- return segments && (segments[this._index + 1]
- || this._path._closed && segments[0]) || null;
- },
-
- getPrevious: function() {
- var segments = this._path && this._path._segments;
- return segments && (segments[this._index - 1]
- || this._path._closed && segments[segments.length - 1]) || null;
- },
-
- reverse: function() {
- return new Segment(this._point, this._handleOut, this._handleIn);
- },
-
- remove: function() {
- return this._path ? !!this._path.removeSegment(this._index) : false;
- },
-
- clone: function() {
- return new Segment(this._point, this._handleIn, this._handleOut);
- },
-
- equals: function(segment) {
- return segment === this || segment && this._class === segment._class
- && this._point.equals(segment._point)
- && this._handleIn.equals(segment._handleIn)
- && this._handleOut.equals(segment._handleOut)
- || false;
- },
-
- toString: function() {
- var parts = [ 'point: ' + this._point ];
- if (!this._handleIn.isZero())
- parts.push('handleIn: ' + this._handleIn);
- if (!this._handleOut.isZero())
- parts.push('handleOut: ' + this._handleOut);
- return '{ ' + parts.join(', ') + ' }';
- },
-
- _transformCoordinates: function(matrix, coords, change) {
- var point = this._point,
- handleIn = !change || !this._handleIn.isZero()
- ? this._handleIn : null,
- handleOut = !change || !this._handleOut.isZero()
- ? this._handleOut : null,
- x = point._x,
- y = point._y,
- i = 2;
- coords[0] = x;
- coords[1] = y;
- if (handleIn) {
- coords[i++] = handleIn._x + x;
- coords[i++] = handleIn._y + y;
- }
- if (handleOut) {
- coords[i++] = handleOut._x + x;
- coords[i++] = handleOut._y + y;
- }
- if (matrix) {
- matrix._transformCoordinates(coords, 0, coords, 0, i / 2);
- x = coords[0];
- y = coords[1];
- if (change) {
- point._x = x;
- point._y = y;
- i = 2;
- if (handleIn) {
- handleIn._x = coords[i++] - x;
- handleIn._y = coords[i++] - y;
- }
- if (handleOut) {
- handleOut._x = coords[i++] - x;
- handleOut._y = coords[i++] - y;
- }
- } else {
- if (!handleIn) {
- coords[i++] = x;
- coords[i++] = y;
- }
- if (!handleOut) {
- coords[i++] = x;
- coords[i++] = y;
- }
- }
- }
- return coords;
- }
-});
-
-var SegmentPoint = Point.extend({
- initialize: function SegmentPoint(point, owner, key) {
- var x, y, selected;
- if (!point) {
- x = y = 0;
- } else if ((x = point[0]) !== undefined) {
- y = point[1];
- } else {
- if ((x = point.x) === undefined) {
- point = Point.read(arguments);
- x = point.x;
- }
- y = point.y;
- selected = point.selected;
- }
- this._x = x;
- this._y = y;
- this._owner = owner;
- owner[key] = this;
- if (selected)
- this.setSelected(true);
- },
-
- set: function(x, y) {
- this._x = x;
- this._y = y;
- this._owner._changed(this);
- return this;
- },
-
- _serialize: function(options) {
- var f = options.formatter,
- x = f.number(this._x),
- y = f.number(this._y);
- return this.isSelected()
- ? { x: x, y: y, selected: true }
- : [x, y];
- },
-
- getX: function() {
- return this._x;
- },
-
- setX: function(x) {
- this._x = x;
- this._owner._changed(this);
- },
-
- getY: function() {
- return this._y;
- },
-
- setY: function(y) {
- this._y = y;
- this._owner._changed(this);
- },
-
- isZero: function() {
- return Numerical.isZero(this._x) && Numerical.isZero(this._y);
- },
-
- setSelected: function(selected) {
- this._owner._setSelected(this, selected);
- },
-
- isSelected: function() {
- return this._owner._isSelected(this);
- }
-});
-
-var Curve = Base.extend({
- _class: 'Curve',
- initialize: function Curve(arg0, arg1, arg2, arg3, arg4, arg5, arg6, arg7) {
- var count = arguments.length;
- if (count === 3) {
- this._path = arg0;
- this._segment1 = arg1;
- this._segment2 = arg2;
- } else if (count === 0) {
- this._segment1 = new Segment();
- this._segment2 = new Segment();
- } else if (count === 1) {
- this._segment1 = new Segment(arg0.segment1);
- this._segment2 = new Segment(arg0.segment2);
- } else if (count === 2) {
- this._segment1 = new Segment(arg0);
- this._segment2 = new Segment(arg1);
- } else {
- var point1, handle1, handle2, point2;
- if (count === 4) {
- point1 = arg0;
- handle1 = arg1;
- handle2 = arg2;
- point2 = arg3;
- } else if (count === 8) {
- point1 = [arg0, arg1];
- point2 = [arg6, arg7];
- handle1 = [arg2 - arg0, arg3 - arg1];
- handle2 = [arg4 - arg6, arg5 - arg7];
- }
- this._segment1 = new Segment(point1, null, handle1);
- this._segment2 = new Segment(point2, handle2, null);
- }
- },
-
- _changed: function() {
- delete this._length;
- delete this._bounds;
- },
-
- getPoint1: function() {
- return this._segment1._point;
- },
-
- setPoint1: function(point) {
- point = Point.read(arguments);
- this._segment1._point.set(point.x, point.y);
- },
-
- getPoint2: function() {
- return this._segment2._point;
- },
-
- setPoint2: function(point) {
- point = Point.read(arguments);
- this._segment2._point.set(point.x, point.y);
- },
-
- getHandle1: function() {
- return this._segment1._handleOut;
- },
-
- setHandle1: function(point) {
- point = Point.read(arguments);
- this._segment1._handleOut.set(point.x, point.y);
- },
-
- getHandle2: function() {
- return this._segment2._handleIn;
- },
-
- setHandle2: function(point) {
- point = Point.read(arguments);
- this._segment2._handleIn.set(point.x, point.y);
- },
-
- getSegment1: function() {
- return this._segment1;
- },
-
- getSegment2: function() {
- return this._segment2;
- },
-
- getPath: function() {
- return this._path;
- },
-
- getIndex: function() {
- return this._segment1._index;
- },
-
- getNext: function() {
- var curves = this._path && this._path._curves;
- return curves && (curves[this._segment1._index + 1]
- || this._path._closed && curves[0]) || null;
- },
-
- getPrevious: function() {
- var curves = this._path && this._path._curves;
- return curves && (curves[this._segment1._index - 1]
- || this._path._closed && curves[curves.length - 1]) || null;
- },
-
- isSelected: function() {
- return this.getHandle1().isSelected() && this.getHandle2().isSelected();
- },
-
- setSelected: function(selected) {
- this.getHandle1().setSelected(selected);
- this.getHandle2().setSelected(selected);
- },
-
- getValues: function() {
- return Curve.getValues(this._segment1, this._segment2);
- },
-
- getPoints: function() {
- var coords = this.getValues(),
- points = [];
- for (var i = 0; i < 8; i += 2)
- points.push(new Point(coords[i], coords[i + 1]));
- return points;
- },
-
- getLength: function() {
- var from = arguments[0],
- to = arguments[1],
- fullLength = arguments.length === 0 || from === 0 && to === 1;
- if (fullLength && this._length != null)
- return this._length;
- var length = Curve.getLength(this.getValues(), from, to);
- if (fullLength)
- this._length = length;
- return length;
- },
-
- getArea: function() {
- return Curve.getArea(this.getValues());
- },
-
- getPart: function(from, to) {
- return new Curve(Curve.getPart(this.getValues(), from, to));
- },
-
- isLinear: function() {
- return this._segment1._handleOut.isZero()
- && this._segment2._handleIn.isZero();
- },
-
- getIntersections: function(curve) {
- return Curve.getIntersections(this.getValues(), curve.getValues(),
- this, curve, []);
- },
-
- reverse: function() {
- return new Curve(this._segment2.reverse(), this._segment1.reverse());
- },
-
- _getParameter: function(offset, isParameter) {
- return isParameter
- ? offset
- : offset && offset.curve === this
- ? offset.parameter
- : offset === undefined && isParameter === undefined
- ? 0.5
- : this.getParameterAt(offset, 0);
- },
-
- divide: function(offset, isParameter) {
- var parameter = this._getParameter(offset, isParameter),
- tolerance = 0.00001,
- res = null;
- if (parameter > tolerance && parameter < 1 - tolerance) {
- var parts = Curve.subdivide(this.getValues(), parameter),
- isLinear = this.isLinear(),
- left = parts[0],
- right = parts[1];
-
- if (!isLinear) {
- this._segment1._handleOut.set(left[2] - left[0],
- left[3] - left[1]);
- this._segment2._handleIn.set(right[4] - right[6],
- right[5] - right[7]);
- }
-
- var x = left[6], y = left[7],
- segment = new Segment(new Point(x, y),
- !isLinear && new Point(left[4] - x, left[5] - y),
- !isLinear && new Point(right[2] - x, right[3] - y));
-
- if (this._path) {
- if (this._segment1._index > 0 && this._segment2._index === 0) {
- this._path.add(segment);
- } else {
- this._path.insert(this._segment2._index, segment);
- }
- res = this;
- } else {
- var end = this._segment2;
- this._segment2 = segment;
- res = new Curve(segment, end);
- }
- }
- return res;
- },
-
- split: function(offset, isParameter) {
- return this._path
- ? this._path.split(this._segment1._index,
- this._getParameter(offset, isParameter))
- : null;
- },
-
- clone: function() {
- return new Curve(this._segment1, this._segment2);
- },
-
- toString: function() {
- var parts = [ 'point1: ' + this._segment1._point ];
- if (!this._segment1._handleOut.isZero())
- parts.push('handle1: ' + this._segment1._handleOut);
- if (!this._segment2._handleIn.isZero())
- parts.push('handle2: ' + this._segment2._handleIn);
- parts.push('point2: ' + this._segment2._point);
- return '{ ' + parts.join(', ') + ' }';
- },
-
-statics: {
- getValues: function(segment1, segment2) {
- var p1 = segment1._point,
- h1 = segment1._handleOut,
- h2 = segment2._handleIn,
- p2 = segment2._point;
- return [
- p1._x, p1._y,
- p1._x + h1._x, p1._y + h1._y,
- p2._x + h2._x, p2._y + h2._y,
- p2._x, p2._y
- ];
- },
-
- evaluate: function(v, t, type) {
- var p1x = v[0], p1y = v[1],
- c1x = v[2], c1y = v[3],
- c2x = v[4], c2y = v[5],
- p2x = v[6], p2y = v[7],
- x, y;
-
- if (type === 0 && (t === 0 || t === 1)) {
- x = t === 0 ? p1x : p2x;
- y = t === 0 ? p1y : p2y;
- } else {
- var cx = 3 * (c1x - p1x),
- bx = 3 * (c2x - c1x) - cx,
- ax = p2x - p1x - cx - bx,
-
- cy = 3 * (c1y - p1y),
- by = 3 * (c2y - c1y) - cy,
- ay = p2y - p1y - cy - by;
- if (type === 0) {
- x = ((ax * t + bx) * t + cx) * t + p1x;
- y = ((ay * t + by) * t + cy) * t + p1y;
- } else {
- var tolerance = 0.00001;
- if (t < tolerance && c1x === p1x && c1y === p1y
- || t > 1 - tolerance && c2x === p2x && c2y === p2y) {
- x = p2x - p1x;
- y = p2y - p1y;
- } else {
- x = (3 * ax * t + 2 * bx) * t + cx;
- y = (3 * ay * t + 2 * by) * t + cy;
- }
- if (type === 3) {
- var x2 = 6 * ax * t + 2 * bx,
- y2 = 6 * ay * t + 2 * by;
- return (x * y2 - y * x2) / Math.pow(x * x + y * y, 3 / 2);
- }
- }
- }
- return type == 2 ? new Point(y, -x) : new Point(x, y);
- },
-
- subdivide: function(v, t) {
- var p1x = v[0], p1y = v[1],
- c1x = v[2], c1y = v[3],
- c2x = v[4], c2y = v[5],
- p2x = v[6], p2y = v[7];
- if (t === undefined)
- t = 0.5;
- var u = 1 - t,
- p3x = u * p1x + t * c1x, p3y = u * p1y + t * c1y,
- p4x = u * c1x + t * c2x, p4y = u * c1y + t * c2y,
- p5x = u * c2x + t * p2x, p5y = u * c2y + t * p2y,
- p6x = u * p3x + t * p4x, p6y = u * p3y + t * p4y,
- p7x = u * p4x + t * p5x, p7y = u * p4y + t * p5y,
- p8x = u * p6x + t * p7x, p8y = u * p6y + t * p7y;
- return [
- [p1x, p1y, p3x, p3y, p6x, p6y, p8x, p8y],
- [p8x, p8y, p7x, p7y, p5x, p5y, p2x, p2y]
- ];
- },
-
- solveCubic: function (v, coord, val, roots, min, max) {
- var p1 = v[coord],
- c1 = v[coord + 2],
- c2 = v[coord + 4],
- p2 = v[coord + 6],
- c = 3 * (c1 - p1),
- b = 3 * (c2 - c1) - c,
- a = p2 - p1 - c - b;
- return Numerical.solveCubic(a, b, c, p1 - val, roots, min, max);
- },
-
- getParameterOf: function(v, x, y) {
- if (Math.abs(v[0] - x) < 0.00001
- && Math.abs(v[1] - y) < 0.00001)
- return 0;
- if (Math.abs(v[6] - x) < 0.00001
- && Math.abs(v[7] - y) < 0.00001)
- return 1;
- var txs = [],
- tys = [],
- sx = Curve.solveCubic(v, 0, x, txs),
- sy = Curve.solveCubic(v, 1, y, tys),
- tx, ty;
- for (var cx = 0; sx == -1 || cx < sx;) {
- if (sx == -1 || (tx = txs[cx++]) >= 0 && tx <= 1) {
- for (var cy = 0; sy == -1 || cy < sy;) {
- if (sy == -1 || (ty = tys[cy++]) >= 0 && ty <= 1) {
- if (sx == -1) tx = ty;
- else if (sy == -1) ty = tx;
- if (Math.abs(tx - ty) < 0.00001)
- return (tx + ty) * 0.5;
- }
- }
- if (sx == -1)
- break;
- }
- }
- return null;
- },
-
- getPart: function(v, from, to) {
- if (from > 0)
- v = Curve.subdivide(v, from)[1];
- if (to < 1)
- v = Curve.subdivide(v, (to - from) / (1 - from))[0];
- return v;
- },
-
- isLinear: function(v) {
- var isZero = Numerical.isZero;
- return isZero(v[0] - v[2]) && isZero(v[1] - v[3])
- && isZero(v[4] - v[6]) && isZero(v[5] - v[7]);
- },
-
- isFlatEnough: function(v, tolerance) {
- var p1x = v[0], p1y = v[1],
- c1x = v[2], c1y = v[3],
- c2x = v[4], c2y = v[5],
- p2x = v[6], p2y = v[7],
- ux = 3 * c1x - 2 * p1x - p2x,
- uy = 3 * c1y - 2 * p1y - p2y,
- vx = 3 * c2x - 2 * p2x - p1x,
- vy = 3 * c2y - 2 * p2y - p1y;
- return Math.max(ux * ux, vx * vx) + Math.max(uy * uy, vy * vy)
- < 10 * tolerance * tolerance;
- },
-
- getArea: function(v) {
- var p1x = v[0], p1y = v[1],
- c1x = v[2], c1y = v[3],
- c2x = v[4], c2y = v[5],
- p2x = v[6], p2y = v[7];
- return ( 3.0 * c1y * p1x - 1.5 * c1y * c2x
- - 1.5 * c1y * p2x - 3.0 * p1y * c1x
- - 1.5 * p1y * c2x - 0.5 * p1y * p2x
- + 1.5 * c2y * p1x + 1.5 * c2y * c1x
- - 3.0 * c2y * p2x + 0.5 * p2y * p1x
- + 1.5 * p2y * c1x + 3.0 * p2y * c2x) / 10;
- },
-
- getBounds: function(v) {
- var min = v.slice(0, 2),
- max = min.slice(),
- roots = [0, 0];
- for (var i = 0; i < 2; i++)
- Curve._addBounds(v[i], v[i + 2], v[i + 4], v[i + 6],
- i, 0, min, max, roots);
- return new Rectangle(min[0], min[1], max[0] - min[0], max[1] - min[1]);
- },
-
- _addBounds: function(v0, v1, v2, v3, coord, padding, min, max, roots) {
- function add(value, padding) {
- var left = value - padding,
- right = value + padding;
- if (left < min[coord])
- min[coord] = left;
- if (right > max[coord])
- max[coord] = right;
- }
- var a = 3 * (v1 - v2) - v0 + v3,
- b = 2 * (v0 + v2) - 4 * v1,
- c = v1 - v0,
- count = Numerical.solveQuadratic(a, b, c, roots),
- tMin = 0.00001,
- tMax = 1 - tMin;
- add(v3, 0);
- for (var i = 0; i < count; i++) {
- var t = roots[i],
- u = 1 - t;
- if (tMin < t && t < tMax)
- add(u * u * u * v0
- + 3 * u * u * t * v1
- + 3 * u * t * t * v2
- + t * t * t * v3,
- padding);
- }
- },
-
- _getWinding: function(v, prev, x, y, roots1, roots2) {
- var tolerance = 0.00001,
- abs = Math.abs;
-
- function getDirection(v) {
- var y0 = v[1],
- y1 = v[7],
- dir = y0 > y1 ? -1 : 1;
- return dir === 1 && (y < y0 || y > y1)
- || dir === -1 && (y < y1 || y > y0)
- ? 0
- : dir;
- }
-
- if (Curve.isLinear(v)) {
- var dir = getDirection(v);
- if (!dir)
- return 0;
- var cross = (v[6] - v[0]) * (y - v[1]) - (v[7] - v[1]) * (x - v[0]);
- return (cross < -tolerance ? -1 : 1) == dir ? 0 : dir;
- }
-
- var y0 = v[1],
- y1 = v[3],
- y2 = v[5],
- y3 = v[7];
- var a = 3 * (y1 - y2) - y0 + y3,
- b = 2 * (y0 + y2) - 4 * y1,
- c = y1 - y0;
- var count = Numerical.solveQuadratic(a, b, c, roots1, tolerance,
- 1 - tolerance),
- part,
- rest = v,
- t1 = roots1[0],
- winding = 0;
- for (var i = 0; i <= count; i++) {
- if (i === count) {
- part = rest;
- } else {
- var curves = Curve.subdivide(rest, t1);
- part = curves[0];
- rest = curves[1];
- t1 = roots1[i];
- t1 = (roots1[i + 1] - t1) / (1 - t1);
- }
- if (i > 0)
- part[3] = part[1];
- if (i < count)
- part[5] = rest[1];
- var dir = getDirection(part);
- if (!dir)
- continue;
- var t2,
- px;
- if (Curve.solveCubic(part, 1, y, roots2, -tolerance, 1 + -tolerance)
- === 1) {
- t2 = roots2[0];
- px = Curve.evaluate(part, t2, 0).x;
- } else {
- var mid = (part[1] + part[7]) / 2;
- t2 = y < mid && dir > 0 ? 0 : 1;
- if (t2 === 1 && y == part[7])
- continue;
- px = t2 === 0 ? part[0] : part[6];
- }
- var slope = Curve.evaluate(part, t2, 1).y,
- stationary = abs(slope) < tolerance || t2 < tolerance
- && Curve.evaluate(prev, 1, 1).y * slope < 0;
- if (x >= px + (stationary ? -tolerance : tolerance * dir)
- && !(stationary && (abs(t2) < tolerance
- && abs(x - part[0]) > tolerance
- || abs(t2 - 1) < tolerance
- && abs(x - part[6]) > tolerance))) {
- winding += stationary && abs(t2 - (dir > 0 ? 1 : 0)) < tolerance
- ? -dir : dir;
- }
- prev = part;
- }
- return winding;
- }
-}}, Base.each(['getBounds', 'getStrokeBounds', 'getHandleBounds', 'getRoughBounds'],
- function(name) {
- this[name] = function() {
- if (!this._bounds)
- this._bounds = {};
- var bounds = this._bounds[name];
- if (!bounds) {
- bounds = this._bounds[name] = Path[name]([this._segment1,
- this._segment2], false, this._path.getStyle());
- }
- return bounds.clone();
- };
- },
-{
-
-}), Base.each(['getPoint', 'getTangent', 'getNormal', 'getCurvature'],
- function(name, index) {
- this[name + 'At'] = function(offset, isParameter) {
- var values = this.getValues();
- return Curve.evaluate(values, isParameter
- ? offset : Curve.getParameterAt(values, offset, 0), index);
- };
- this[name] = function(parameter) {
- return Curve.evaluate(this.getValues(), parameter, index);
- };
- },
-{
- getParameterAt: function(offset, start) {
- return Curve.getParameterAt(this.getValues(), offset,
- start !== undefined ? start : offset < 0 ? 1 : 0);
- },
-
- getParameterOf: function(point) {
- point = Point.read(arguments);
- return Curve.getParameterOf(this.getValues(), point.x, point.y);
- },
-
- getLocationAt: function(offset, isParameter) {
- if (!isParameter)
- offset = this.getParameterAt(offset);
- return new CurveLocation(this, offset);
- },
-
- getLocationOf: function(point) {
- point = Point.read(arguments);
- var t = this.getParameterOf(point);
- return t != null ? new CurveLocation(this, t) : null;
- },
-
- getNearestLocation: function(point) {
- point = Point.read(arguments);
- var values = this.getValues(),
- count = 100,
- tolerance = Numerical.TOLERANCE,
- minDist = Infinity,
- minT = 0;
-
- function refine(t) {
- if (t >= 0 && t <= 1) {
- var dist = point.getDistance(
- Curve.evaluate(values, t, 0), true);
- if (dist < minDist) {
- minDist = dist;
- minT = t;
- return true;
- }
- }
- }
-
- for (var i = 0; i <= count; i++)
- refine(i / count);
-
- var step = 1 / (count * 2);
- while (step > tolerance) {
- if (!refine(minT - step) && !refine(minT + step))
- step /= 2;
- }
- var pt = Curve.evaluate(values, minT, 0);
- return new CurveLocation(this, minT, pt, null, null, null,
- point.getDistance(pt));
- },
-
- getNearestPoint: function(point) {
- point = Point.read(arguments);
- return this.getNearestLocation(point).getPoint();
- }
-
-}),
-new function() {
-
- function getLengthIntegrand(v) {
- var p1x = v[0], p1y = v[1],
- c1x = v[2], c1y = v[3],
- c2x = v[4], c2y = v[5],
- p2x = v[6], p2y = v[7],
-
- ax = 9 * (c1x - c2x) + 3 * (p2x - p1x),
- bx = 6 * (p1x + c2x) - 12 * c1x,
- cx = 3 * (c1x - p1x),
-
- ay = 9 * (c1y - c2y) + 3 * (p2y - p1y),
- by = 6 * (p1y + c2y) - 12 * c1y,
- cy = 3 * (c1y - p1y);
-
- return function(t) {
- var dx = (ax * t + bx) * t + cx,
- dy = (ay * t + by) * t + cy;
- return Math.sqrt(dx * dx + dy * dy);
- };
- }
-
- function getIterations(a, b) {
- return Math.max(2, Math.min(16, Math.ceil(Math.abs(b - a) * 32)));
- }
-
- return {
- statics: true,
-
- getLength: function(v, a, b) {
- if (a === undefined)
- a = 0;
- if (b === undefined)
- b = 1;
- var isZero = Numerical.isZero;
- if (isZero(v[0] - v[2]) && isZero(v[1] - v[3])
- && isZero(v[6] - v[4]) && isZero(v[7] - v[5])) {
- var dx = v[6] - v[0],
- dy = v[7] - v[1];
- return (b - a) * Math.sqrt(dx * dx + dy * dy);
- }
- var ds = getLengthIntegrand(v);
- return Numerical.integrate(ds, a, b, getIterations(a, b));
- },
-
- getParameterAt: function(v, offset, start) {
- if (offset === 0)
- return start;
- var forward = offset > 0,
- a = forward ? start : 0,
- b = forward ? 1 : start,
- offset = Math.abs(offset),
- ds = getLengthIntegrand(v),
- rangeLength = Numerical.integrate(ds, a, b,
- getIterations(a, b));
- if (offset >= rangeLength)
- return forward ? b : a;
- var guess = offset / rangeLength,
- length = 0;
- function f(t) {
- var count = getIterations(start, t);
- length += start < t
- ? Numerical.integrate(ds, start, t, count)
- : -Numerical.integrate(ds, t, start, count);
- start = t;
- return length - offset;
- }
- return Numerical.findRoot(f, ds,
- forward ? a + guess : b - guess,
- a, b, 16, 0.00001);
- }
- };
-}, new function() {
- function addLocation(locations, curve1, t1, point1, curve2, t2, point2) {
- var first = locations[0],
- last = locations[locations.length - 1];
- if ((!first || !point1.isClose(first._point, Numerical.EPSILON))
- && (!last || !point1.isClose(last._point, Numerical.EPSILON)))
- locations.push(
- new CurveLocation(curve1, t1, point1, curve2, t2, point2));
- }
-
- function addCurveIntersections(v1, v2, curve1, curve2, locations,
- range1, range2, recursion) {
- recursion = (recursion || 0) + 1;
- if (recursion > 20)
- return;
- range1 = range1 || [ 0, 1 ];
- range2 = range2 || [ 0, 1 ];
- var part1 = Curve.getPart(v1, range1[0], range1[1]),
- part2 = Curve.getPart(v2, range2[0], range2[1]),
- iteration = 0;
- while (iteration++ < 20) {
- var range,
- intersects1 = clipFatLine(part1, part2, range = range2.slice()),
- intersects2 = 0;
- if (intersects1 === 0)
- break;
- if (intersects1 > 0) {
- range2 = range;
- part2 = Curve.getPart(v2, range2[0], range2[1]);
- intersects2 = clipFatLine(part2, part1, range = range1.slice());
- if (intersects2 === 0)
- break;
- if (intersects1 > 0) {
- range1 = range;
- part1 = Curve.getPart(v1, range1[0], range1[1]);
- }
- }
- if (intersects1 < 0 || intersects2 < 0) {
- if (range1[1] - range1[0] > range2[1] - range2[0]) {
- var t = (range1[0] + range1[1]) / 2;
- addCurveIntersections(v1, v2, curve1, curve2, locations,
- [ range1[0], t ], range2, recursion);
- addCurveIntersections(v1, v2, curve1, curve2, locations,
- [ t, range1[1] ], range2, recursion);
- break;
- } else {
- var t = (range2[0] + range2[1]) / 2;
- addCurveIntersections(v1, v2, curve1, curve2, locations,
- range1, [ range2[0], t ], recursion);
- addCurveIntersections(v1, v2, curve1, curve2, locations,
- range1, [ t, range2[1] ], recursion);
- break;
- }
- }
- if (Math.abs(range1[1] - range1[0]) <= 0.00001 &&
- Math.abs(range2[1] - range2[0]) <= 0.00001) {
- var t1 = (range1[0] + range1[1]) / 2,
- t2 = (range2[0] + range2[1]) / 2;
- addLocation(locations,
- curve1, t1, Curve.evaluate(v1, t1, 0),
- curve2, t2, Curve.evaluate(v2, t2, 0));
- break;
- }
- }
- }
-
- function clipFatLine(v1, v2, range2) {
- var p0x = v1[0], p0y = v1[1], p1x = v1[2], p1y = v1[3],
- p2x = v1[4], p2y = v1[5], p3x = v1[6], p3y = v1[7],
- q0x = v2[0], q0y = v2[1], q1x = v2[2], q1y = v2[3],
- q2x = v2[4], q2y = v2[5], q3x = v2[6], q3y = v2[7],
- getSignedDistance = Line.getSignedDistance,
- d1 = getSignedDistance(p0x, p0y, p3x, p3y, p1x, p1y) || 0,
- d2 = getSignedDistance(p0x, p0y, p3x, p3y, p2x, p2y) || 0,
- factor = d1 * d2 > 0 ? 3 / 4 : 4 / 9,
- dmin = factor * Math.min(0, d1, d2),
- dmax = factor * Math.max(0, d1, d2),
- dq0 = getSignedDistance(p0x, p0y, p3x, p3y, q0x, q0y),
- dq1 = getSignedDistance(p0x, p0y, p3x, p3y, q1x, q1y),
- dq2 = getSignedDistance(p0x, p0y, p3x, p3y, q2x, q2y),
- dq3 = getSignedDistance(p0x, p0y, p3x, p3y, q3x, q3y);
- if (dmin > Math.max(dq0, dq1, dq2, dq3)
- || dmax < Math.min(dq0, dq1, dq2, dq3))
- return 0;
- var hull = getConvexHull(dq0, dq1, dq2, dq3),
- swap;
- if (dq3 < dq0) {
- swap = dmin;
- dmin = dmax;
- dmax = swap;
- }
- var tmaxdmin = -Infinity,
- tmin = Infinity,
- tmax = -Infinity;
- for (var i = 0, l = hull.length; i < l; i++) {
- var p1 = hull[i],
- p2 = hull[(i + 1) % l];
- if (p2[1] < p1[1]) {
- swap = p2;
- p2 = p1;
- p1 = swap;
- }
- var x1 = p1[0],
- y1 = p1[1],
- x2 = p2[0],
- y2 = p2[1];
- var inv = (y2 - y1) / (x2 - x1);
- if (dmin >= y1 && dmin <= y2) {
- var ixdx = x1 + (dmin - y1) / inv;
- if (ixdx < tmin)
- tmin = ixdx;
- if (ixdx > tmaxdmin)
- tmaxdmin = ixdx;
- }
- if (dmax >= y1 && dmax <= y2) {
- var ixdx = x1 + (dmax - y1) / inv;
- if (ixdx > tmax)
- tmax = ixdx;
- if (ixdx < tmin)
- tmin = 0;
- }
- }
- if (tmin !== Infinity && tmax !== -Infinity) {
- var min = Math.min(dmin, dmax),
- max = Math.max(dmin, dmax);
- if (dq3 > min && dq3 < max)
- tmax = 1;
- if (dq0 > min && dq0 < max)
- tmin = 0;
- if (tmaxdmin > tmax)
- tmax = 1;
- var v2tmin = range2[0],
- tdiff = range2[1] - v2tmin;
- range2[0] = v2tmin + tmin * tdiff;
- range2[1] = v2tmin + tmax * tdiff;
- if ((tdiff - (range2[1] - range2[0])) / tdiff >= 0.2)
- return 1;
- }
- if (Curve.getBounds(v1).touches(Curve.getBounds(v2)))
- return -1;
- return 0;
- }
-
- function getConvexHull(dq0, dq1, dq2, dq3) {
- var p0 = [ 0, dq0 ],
- p1 = [ 1 / 3, dq1 ],
- p2 = [ 2 / 3, dq2 ],
- p3 = [ 1, dq3 ],
- getSignedDistance = Line.getSignedDistance,
- dist1 = getSignedDistance(0, dq0, 1, dq3, 1 / 3, dq1),
- dist2 = getSignedDistance(0, dq0, 1, dq3, 2 / 3, dq2);
- if (dist1 * dist2 < 0) {
- return [ p0, p1, p3, p2 ];
- }
- var pmax, cross;
- if (Math.abs(dist1) > Math.abs(dist2)) {
- pmax = p1;
- cross = (dq3 - dq2 - (dq3 - dq0) / 3)
- * (2 * (dq3 - dq2) - dq3 + dq1) / 3;
- } else {
- pmax = p2;
- cross = (dq1 - dq0 + (dq0 - dq3) / 3)
- * (-2 * (dq0 - dq1) + dq0 - dq2) / 3;
- }
- return cross < 0
- ? [ p0, pmax, p3 ]
- : [ p0, p1, p2, p3 ];
- }
-
- function addCurveLineIntersections(v1, v2, curve1, curve2, locations) {
- var flip = Curve.isLinear(v1),
- vc = flip ? v2 : v1,
- vl = flip ? v1 : v2,
- lx1 = vl[0], ly1 = vl[1],
- lx2 = vl[6], ly2 = vl[7],
- ldx = lx2 - lx1,
- ldy = ly2 - ly1,
- angle = Math.atan2(-ldy, ldx),
- sin = Math.sin(angle),
- cos = Math.cos(angle),
- rlx2 = ldx * cos - ldy * sin,
- rvl = [0, 0, 0, 0, rlx2, 0, rlx2, 0],
- rvc = [];
- for(var i = 0; i < 8; i += 2) {
- var x = vc[i] - lx1,
- y = vc[i + 1] - ly1;
- rvc.push(
- x * cos - y * sin,
- y * cos + x * sin);
- }
- var roots = [],
- count = Curve.solveCubic(rvc, 1, 0, roots, 0, 1);
- for (var i = 0; i < count; i++) {
- var tc = roots[i],
- x = Curve.evaluate(rvc, tc, 0).x;
- if (x >= 0 && x <= rlx2) {
- var tl = Curve.getParameterOf(rvl, x, 0),
- t1 = flip ? tl : tc,
- t2 = flip ? tc : tl;
- addLocation(locations,
- curve1, t1, Curve.evaluate(v1, t1, 0),
- curve2, t2, Curve.evaluate(v2, t2, 0));
- }
- }
- }
-
- function addLineIntersection(v1, v2, curve1, curve2, locations) {
- var point = Line.intersect(
- v1[0], v1[1], v1[6], v1[7],
- v2[0], v2[1], v2[6], v2[7]);
- if (point)
- addLocation(locations, curve1, null, point, curve2);
- }
-
- return { statics: {
- getIntersections: function(v1, v2, curve1, curve2, locations) {
- var linear1 = Curve.isLinear(v1),
- linear2 = Curve.isLinear(v2),
- c1p1 = curve1.getPoint1(),
- c1p2 = curve1.getPoint2(),
- c2p1 = curve2.getPoint1(),
- c2p2 = curve2.getPoint2(),
- tolerance = 0.00001;
- if (c1p1.isClose(c2p1, tolerance))
- addLocation(locations, curve1, 0, c1p1, curve2, 0, c1p1);
- if (c1p1.isClose(c2p2, tolerance))
- addLocation(locations, curve1, 0, c1p1, curve2, 1, c1p1);
- (linear1 && linear2
- ? addLineIntersection
- : linear1 || linear2
- ? addCurveLineIntersections
- : addCurveIntersections)(v1, v2, curve1, curve2, locations);
- if (c1p2.isClose(c2p1, tolerance))
- addLocation(locations, curve1, 1, c1p2, curve2, 0, c1p2);
- if (c1p2.isClose(c2p2, tolerance))
- addLocation(locations, curve1, 1, c1p2, curve2, 1, c1p2);
- return locations;
- }
- }};
-});
-
-var CurveLocation = Base.extend({
- _class: 'CurveLocation',
- initialize: function CurveLocation(curve, parameter, point, _curve2,
- _parameter2, _point2, _distance) {
- this._id = CurveLocation._id = (CurveLocation._id || 0) + 1;
- this._curve = curve;
- this._segment1 = curve._segment1;
- this._segment2 = curve._segment2;
- this._parameter = parameter;
- this._point = point;
- this._curve2 = _curve2;
- this._parameter2 = _parameter2;
- this._point2 = _point2;
- this._distance = _distance;
- },
-
- getSegment: function() {
- if (!this._segment) {
- var curve = this.getCurve(),
- parameter = this.getParameter();
- if (parameter === 1) {
- this._segment = curve._segment2;
- } else if (parameter === 0 || arguments[0]) {
- this._segment = curve._segment1;
- } else if (parameter == null) {
- return null;
- } else {
- this._segment = curve.getLength(0, parameter)
- < curve.getLength(parameter, 1)
- ? curve._segment1
- : curve._segment2;
- }
- }
- return this._segment;
- },
-
- getCurve: function() {
- if (!this._curve || arguments[0]) {
- this._curve = this._segment1.getCurve();
- if (this._curve.getParameterOf(this._point) == null)
- this._curve = this._segment2.getPrevious().getCurve();
- }
- return this._curve;
- },
-
- getIntersection: function() {
- var intersection = this._intersection;
- if (!intersection && this._curve2) {
- var param = this._parameter2;
- this._intersection = intersection = new CurveLocation(
- this._curve2, param, this._point2 || this._point, this);
- intersection._intersection = this;
- }
- return intersection;
- },
-
- getPath: function() {
- var curve = this.getCurve();
- return curve && curve._path;
- },
-
- getIndex: function() {
- var curve = this.getCurve();
- return curve && curve.getIndex();
- },
-
- getOffset: function() {
- var path = this.getPath();
- return path && path._getOffset(this);
- },
-
- getCurveOffset: function() {
- var curve = this.getCurve(),
- parameter = this.getParameter();
- return parameter != null && curve && curve.getLength(0, parameter);
- },
-
- getParameter: function() {
- if ((this._parameter == null || arguments[0]) && this._point) {
- var curve = this.getCurve(arguments[0] && this._point);
- this._parameter = curve && curve.getParameterOf(this._point);
- }
- return this._parameter;
- },
-
- getPoint: function() {
- if ((!this._point || arguments[0]) && this._parameter != null) {
- var curve = this.getCurve();
- this._point = curve && curve.getPointAt(this._parameter, true);
- }
- return this._point;
- },
-
- getTangent: function() {
- var parameter = this.getParameter(),
- curve = this.getCurve();
- return parameter != null && curve && curve.getTangentAt(parameter, true);
- },
-
- getNormal: function() {
- var parameter = this.getParameter(),
- curve = this.getCurve();
- return parameter != null && curve && curve.getNormalAt(parameter, true);
- },
-
- getDistance: function() {
- return this._distance;
- },
-
- divide: function() {
- var curve = this.getCurve(true);
- return curve && curve.divide(this.getParameter(true), true);
- },
-
- split: function() {
- var curve = this.getCurve(true);
- return curve && curve.split(this.getParameter(true), true);
- },
-
- toString: function() {
- var parts = [],
- point = this.getPoint(),
- f = Formatter.instance;
- if (point)
- parts.push('point: ' + point);
- var index = this.getIndex();
- if (index != null)
- parts.push('index: ' + index);
- var parameter = this.getParameter();
- if (parameter != null)
- parts.push('parameter: ' + f.number(parameter));
- if (this._distance != null)
- parts.push('distance: ' + f.number(this._distance));
- return '{ ' + parts.join(', ') + ' }';
- }
-});
-
-var PathItem = Item.extend({
- _class: 'PathItem',
-
- initialize: function PathItem() {
- },
-
- getIntersections: function(path) {
- if (!this.getBounds().touches(path.getBounds()))
- return [];
- var locations = [],
- curves1 = this.getCurves(),
- curves2 = path.getCurves(),
- length2 = curves2.length,
- values2 = [];
- for (var i = 0; i < length2; i++)
- values2[i] = curves2[i].getValues();
- for (var i = 0, l = curves1.length; i < l; i++) {
- var curve1 = curves1[i],
- values1 = curve1.getValues();
- for (var j = 0; j < length2; j++)
- Curve.getIntersections(values1, values2[j], curve1, curves2[j],
- locations);
- }
- return locations;
- },
-
- setPathData: function(data) {
-
- var parts = data.match(/[mlhvcsqtaz][^mlhvcsqtaz]*/ig),
- coords,
- relative = false,
- control,
- current = new Point();
-
- function getCoord(index, coord, isCurrent) {
- var val = parseFloat(coords[index]);
- if (relative)
- val += current[coord];
- if (isCurrent)
- current[coord] = val;
- return val;
- }
-
- function getPoint(index, isCurrent) {
- return new Point(
- getCoord(index, 'x', isCurrent),
- getCoord(index + 1, 'y', isCurrent)
- );
- }
-
- this.clear();
-
- for (var i = 0, l = parts.length; i < l; i++) {
- var part = parts[i],
- cmd = part[0],
- lower = cmd.toLowerCase();
- coords = part.match(/[+-]?(?:\d*\.\d+|\d+\.?)(?:[eE][+-]?\d+)?/g);
- var length = coords && coords.length;
- relative = cmd === lower;
- switch (lower) {
- case 'm':
- case 'l':
- for (var j = 0; j < length; j += 2)
- this[j === 0 && lower === 'm' ? 'moveTo' : 'lineTo'](
- getPoint(j, true));
- control = current;
- break;
- case 'h':
- case 'v':
- var coord = lower == 'h' ? 'x' : 'y';
- for (var j = 0; j < length; j++) {
- getCoord(j, coord, true);
- this.lineTo(current);
- }
- control = current;
- break;
- case 'c':
- for (var j = 0; j < length; j += 6) {
- this.cubicCurveTo(
- getPoint(j),
- control = getPoint(j + 2),
- getPoint(j + 4, true));
- }
- break;
- case 's':
- for (var j = 0; j < length; j += 4) {
- this.cubicCurveTo(
- current.multiply(2).subtract(control),
- control = getPoint(j),
- getPoint(j + 2, true));
- }
- break;
- case 'q':
- for (var j = 0; j < length; j += 4) {
- this.quadraticCurveTo(
- control = getPoint(j),
- getPoint(j + 2, true));
- }
- break;
- case 't':
- for (var j = 0; j < length; j += 2) {
- this.quadraticCurveTo(
- control = current.multiply(2).subtract(control),
- getPoint(j, true));
- }
- break;
- case 'a':
- break;
- case 'z':
- this.closePath();
- break;
- }
- }
- },
-
- _canComposite: function() {
- return !(this.hasFill() && this.hasStroke());
- },
-
- _contains: function(point) {
- var winding = this._getWinding(point);
- return !!(this.getWindingRule() === 'evenodd' ? winding & 1 : winding);
- }
-
-});
-
-var Path = PathItem.extend({
- _class: 'Path',
- _serializeFields: {
- segments: [],
- closed: false
- },
-
- initialize: function Path(arg) {
- this._closed = false;
- this._segments = [];
- var segments = Array.isArray(arg)
- ? typeof arg[0] === 'object'
- ? arg
- : arguments
- : arg && (arg.point !== undefined && arg.size === undefined
- || arg.x !== undefined)
- ? arguments
- : null;
- this.setSegments(segments || []);
- this._initialize(!segments && arg);
- },
-
- _equals: function(item) {
- return Base.equals(this._segments, item._segments);
- },
-
- clone: function(insert) {
- var copy = this._clone(new Path({
- segments: this._segments,
- insert: false
- }), insert);
- copy._closed = this._closed;
- if (this._clockwise !== undefined)
- copy._clockwise = this._clockwise;
- return copy;
- },
-
- _changed: function _changed(flags) {
- _changed.base.call(this, flags);
- if (flags & 4) {
- delete this._length;
- delete this._clockwise;
- if (this._curves) {
- for (var i = 0, l = this._curves.length; i < l; i++)
- this._curves[i]._changed(5);
- }
- } else if (flags & 8) {
- delete this._bounds;
- }
- },
-
- getSegments: function() {
- return this._segments;
- },
-
- setSegments: function(segments) {
- var fullySelected = this.isFullySelected();
- this._segments.length = 0;
- this._selectedSegmentState = 0;
- delete this._curves;
- this._add(Segment.readAll(segments));
- if (fullySelected)
- this.setFullySelected(true);
- },
-
- getFirstSegment: function() {
- return this._segments[0];
- },
-
- getLastSegment: function() {
- return this._segments[this._segments.length - 1];
- },
-
- getCurves: function() {
- var curves = this._curves,
- segments = this._segments;
- if (!curves) {
- var length = this._countCurves();
- curves = this._curves = new Array(length);
- for (var i = 0; i < length; i++)
- curves[i] = new Curve(this, segments[i],
- segments[i + 1] || segments[0]);
- }
- return curves;
- },
-
- getFirstCurve: function() {
- return this.getCurves()[0];
- },
-
- getLastCurve: function() {
- var curves = this.getCurves();
- return curves[curves.length - 1];
- },
-
- getPathData: function() {
- var segments = this._segments,
- precision = arguments[0],
- f = Formatter.instance,
- parts = [];
-
- function addCurve(seg1, seg2, skipLine) {
- var point1 = seg1._point,
- point2 = seg2._point,
- handle1 = seg1._handleOut,
- handle2 = seg2._handleIn;
- if (handle1.isZero() && handle2.isZero()) {
- if (!skipLine) {
- parts.push('L' + f.point(point2, precision));
- }
- } else {
- var end = point2.subtract(point1);
- parts.push('c' + f.point(handle1, precision)
- + ' ' + f.point(end.add(handle2), precision)
- + ' ' + f.point(end, precision));
- }
- }
-
- if (segments.length === 0)
- return '';
- parts.push('M' + f.point(segments[0]._point));
- for (var i = 0, l = segments.length - 1; i < l; i++)
- addCurve(segments[i], segments[i + 1], false);
- if (this._closed) {
- addCurve(segments[segments.length - 1], segments[0], true);
- parts.push('z');
- }
- return parts.join('');
- },
-
- isClosed: function() {
- return this._closed;
- },
-
- setClosed: function(closed) {
- if (this._closed != (closed = !!closed)) {
- this._closed = closed;
- if (this._curves) {
- var length = this._curves.length = this._countCurves();
- if (closed)
- this._curves[length - 1] = new Curve(this,
- this._segments[length - 1], this._segments[0]);
- }
- this._changed(5);
- }
- },
-
- isEmpty: function() {
- return this._segments.length === 0;
- },
-
- isPolygon: function() {
- for (var i = 0, l = this._segments.length; i < l; i++) {
- if (!this._segments[i].isLinear())
- return false;
- }
- return true;
- },
-
- _applyMatrix: function(matrix) {
- var coords = new Array(6);
- for (var i = 0, l = this._segments.length; i < l; i++)
- this._segments[i]._transformCoordinates(matrix, coords, true);
- return true;
- },
-
- _add: function(segs, index) {
- var segments = this._segments,
- curves = this._curves,
- amount = segs.length,
- append = index == null,
- index = append ? segments.length : index;
- for (var i = 0; i < amount; i++) {
- var segment = segs[i];
- if (segment._path)
- segment = segs[i] = segment.clone();
- segment._path = this;
- segment._index = index + i;
- if (segment._selectionState)
- this._updateSelection(segment, 0, segment._selectionState);
- }
- if (append) {
- segments.push.apply(segments, segs);
- } else {
- segments.splice.apply(segments, [index, 0].concat(segs));
- for (var i = index + amount, l = segments.length; i < l; i++)
- segments[i]._index = i;
- }
- if (curves || segs._curves) {
- if (!curves)
- curves = this._curves = [];
- var from = index > 0 ? index - 1 : index,
- start = from,
- to = Math.min(from + amount, this._countCurves());
- if (segs._curves) {
- curves.splice.apply(curves, [from, 0].concat(segs._curves));
- start += segs._curves.length;
- }
- for (var i = start; i < to; i++)
- curves.splice(i, 0, new Curve(this, null, null));
- this._adjustCurves(from, to);
- }
- this._changed(5);
- return segs;
- },
-
- _adjustCurves: function(from, to) {
- var segments = this._segments,
- curves = this._curves,
- curve;
- for (var i = from; i < to; i++) {
- curve = curves[i];
- curve._path = this;
- curve._segment1 = segments[i];
- curve._segment2 = segments[i + 1] || segments[0];
- }
- if (curve = curves[this._closed && from === 0 ? segments.length - 1
- : from - 1])
- curve._segment2 = segments[from] || segments[0];
- if (curve = curves[to])
- curve._segment1 = segments[to];
- },
-
- _countCurves: function() {
- var length = this._segments.length;
- return !this._closed && length > 0 ? length - 1 : length;
- },
-
- add: function(segment1 ) {
- return arguments.length > 1 && typeof segment1 !== 'number'
- ? this._add(Segment.readAll(arguments))
- : this._add([ Segment.read(arguments) ])[0];
- },
-
- insert: function(index, segment1 ) {
- return arguments.length > 2 && typeof segment1 !== 'number'
- ? this._add(Segment.readAll(arguments, 1), index)
- : this._add([ Segment.read(arguments, 1) ], index)[0];
- },
-
- addSegment: function() {
- return this._add([ Segment.read(arguments) ])[0];
- },
-
- insertSegment: function(index ) {
- return this._add([ Segment.read(arguments, 1) ], index)[0];
- },
-
- addSegments: function(segments) {
- return this._add(Segment.readAll(segments));
- },
-
- insertSegments: function(index, segments) {
- return this._add(Segment.readAll(segments), index);
- },
-
- removeSegment: function(index) {
- return this.removeSegments(index, index + 1)[0] || null;
- },
-
- removeSegments: function(from, to) {
- from = from || 0;
- to = Base.pick(to, this._segments.length);
- var segments = this._segments,
- curves = this._curves,
- count = segments.length,
- removed = segments.splice(from, to - from),
- amount = removed.length;
- if (!amount)
- return removed;
- for (var i = 0; i < amount; i++) {
- var segment = removed[i];
- if (segment._selectionState)
- this._updateSelection(segment, segment._selectionState, 0);
- delete segment._index;
- delete segment._path;
- }
- for (var i = from, l = segments.length; i < l; i++)
- segments[i]._index = i;
- if (curves) {
- var index = from > 0 && to === count + (this._closed ? 1 : 0)
- ? from - 1
- : from,
- curves = curves.splice(index, amount);
- if (arguments[2])
- removed._curves = curves.slice(1);
- this._adjustCurves(index, index);
- }
- this._changed(5);
- return removed;
- },
-
- clear: '#removeSegments',
-
- isFullySelected: function() {
- var length = this._segments.length;
- return this._selected && length > 0 && this._selectedSegmentState
- === length * 4;
- },
-
- setFullySelected: function(selected) {
- if (selected)
- this._selectSegments(true);
- this.setSelected(selected);
- },
-
- setSelected: function setSelected(selected) {
- if (!selected)
- this._selectSegments(false);
- setSelected.base.call(this, selected);
- },
-
- _selectSegments: function(selected) {
- var length = this._segments.length;
- this._selectedSegmentState = selected
- ? length * 4 : 0;
- for (var i = 0; i < length; i++)
- this._segments[i]._selectionState = selected
- ? 4 : 0;
- },
-
- _updateSelection: function(segment, oldState, newState) {
- segment._selectionState = newState;
- var total = this._selectedSegmentState += newState - oldState;
- if (total > 0)
- this.setSelected(true);
- },
-
- flatten: function(maxDistance) {
- var flattener = new PathFlattener(this),
- pos = 0,
- step = flattener.length / Math.ceil(flattener.length / maxDistance),
- end = flattener.length + (this._closed ? -step : step) / 2;
- var segments = [];
- while (pos <= end) {
- segments.push(new Segment(flattener.evaluate(pos, 0)));
- pos += step;
- }
- this.setSegments(segments);
- },
-
- simplify: function(tolerance) {
- if (this._segments.length > 2) {
- var fitter = new PathFitter(this, tolerance || 2.5);
- this.setSegments(fitter.fit());
- }
- },
-
- split: function(index, parameter) {
- if (parameter === null)
- return;
- if (arguments.length === 1) {
- var arg = index;
- if (typeof arg === 'number')
- arg = this.getLocationAt(arg);
- index = arg.index;
- parameter = arg.parameter;
- }
- if (parameter >= 1) {
- index++;
- parameter--;
- }
- var curves = this.getCurves();
- if (index >= 0 && index < curves.length) {
- if (parameter > 0) {
- curves[index++].divide(parameter, true);
- }
- var segs = this.removeSegments(index, this._segments.length, true),
- path;
- if (this._closed) {
- this.setClosed(false);
- path = this;
- } else if (index > 0) {
- path = this._clone(new Path().insertAbove(this, true));
- }
- path._add(segs, 0);
- this.addSegment(segs[0]);
- return path;
- }
- return null;
- },
-
- isClockwise: function() {
- if (this._clockwise !== undefined)
- return this._clockwise;
- return Path.isClockwise(this._segments);
- },
-
- setClockwise: function(clockwise) {
- if (this.isClockwise() != (clockwise = !!clockwise))
- this.reverse();
- this._clockwise = clockwise;
- },
-
- reverse: function() {
- this._segments.reverse();
- for (var i = 0, l = this._segments.length; i < l; i++) {
- var segment = this._segments[i];
- var handleIn = segment._handleIn;
- segment._handleIn = segment._handleOut;
- segment._handleOut = handleIn;
- segment._index = i;
- }
- delete this._curves;
- if (this._clockwise !== undefined)
- this._clockwise = !this._clockwise;
- },
-
- join: function(path) {
- if (path) {
- var segments = path._segments,
- last1 = this.getLastSegment(),
- last2 = path.getLastSegment();
- if (last1._point.equals(last2._point))
- path.reverse();
- var first1,
- first2 = path.getFirstSegment();
- if (last1._point.equals(first2._point)) {
- last1.setHandleOut(first2._handleOut);
- this._add(segments.slice(1));
- } else {
- first1 = this.getFirstSegment();
- if (first1._point.equals(first2._point))
- path.reverse();
- last2 = path.getLastSegment();
- if (first1._point.equals(last2._point)) {
- first1.setHandleIn(last2._handleIn);
- this._add(segments.slice(0, segments.length - 1), 0);
- } else {
- this._add(segments.slice());
- }
- }
- if (path.closed)
- this._add([segments[0]]);
- path.remove();
- first1 = this.getFirstSegment();
- last1 = this.getLastSegment();
- if (last1._point.equals(first1._point)) {
- first1.setHandleIn(last1._handleIn);
- last1.remove();
- this.setClosed(true);
- }
- this._changed(5);
- return true;
- }
- return false;
- },
-
- getLength: function() {
- if (this._length == null) {
- var curves = this.getCurves();
- this._length = 0;
- for (var i = 0, l = curves.length; i < l; i++)
- this._length += curves[i].getLength();
- }
- return this._length;
- },
-
- getArea: function() {
- var curves = this.getCurves();
- var area = 0;
- for (var i = 0, l = curves.length; i < l; i++)
- area += curves[i].getArea();
- return area;
- },
-
- _getOffset: function(location) {
- var index = location && location.getIndex();
- if (index != null) {
- var curves = this.getCurves(),
- offset = 0;
- for (var i = 0; i < index; i++)
- offset += curves[i].getLength();
- var curve = curves[index];
- return offset + curve.getLength(0, location.getParameter());
- }
- return null;
- },
-
- getLocationOf: function(point) {
- point = Point.read(arguments);
- var curves = this.getCurves();
- for (var i = 0, l = curves.length; i < l; i++) {
- var loc = curves[i].getLocationOf(point);
- if (loc)
- return loc;
- }
- return null;
- },
-
- getLocationAt: function(offset, isParameter) {
- var curves = this.getCurves(),
- length = 0;
- if (isParameter) {
- var index = ~~offset;
- return curves[index].getLocationAt(offset - index, true);
- }
- for (var i = 0, l = curves.length; i < l; i++) {
- var start = length,
- curve = curves[i];
- length += curve.getLength();
- if (length >= offset) {
- return curve.getLocationAt(offset - start);
- }
- }
- if (offset <= this.getLength())
- return new CurveLocation(curves[curves.length - 1], 1);
- return null;
- },
-
- getPointAt: function(offset, isParameter) {
- var loc = this.getLocationAt(offset, isParameter);
- return loc && loc.getPoint();
- },
-
- getTangentAt: function(offset, isParameter) {
- var loc = this.getLocationAt(offset, isParameter);
- return loc && loc.getTangent();
- },
-
- getNormalAt: function(offset, isParameter) {
- var loc = this.getLocationAt(offset, isParameter);
- return loc && loc.getNormal();
- },
-
- getNearestLocation: function(point) {
- point = Point.read(arguments);
- var curves = this.getCurves(),
- minDist = Infinity,
- minLoc = null;
- for (var i = 0, l = curves.length; i < l; i++) {
- var loc = curves[i].getNearestLocation(point);
- if (loc._distance < minDist) {
- minDist = loc._distance;
- minLoc = loc;
- }
- }
- return minLoc;
- },
-
- getNearestPoint: function(point) {
- point = Point.read(arguments);
- return this.getNearestLocation(point).getPoint();
- },
-
- getStyle: function() {
- var parent = this._parent;
- return (parent && parent._type === 'compound-path'
- ? parent : this)._style;
- },
-
- toShape: function(insert) {
- if (!this._closed)
- return null;
-
- var segments = this._segments,
- type,
- size,
- radius,
- topCenter;
-
- function isColinear(i, j) {
- return segments[i].isColinear(segments[j]);
- }
-
- function isOrthogonal(i) {
- return segments[i].isOrthogonal();
- }
-
- function isArc(i) {
- return segments[i].isArc();
- }
-
- function getDistance(i, j) {
- return segments[i]._point.getDistance(segments[j]._point);
- }
-
- if (this.isPolygon() && segments.length === 4
- && isColinear(0, 2) && isColinear(1, 3) && isOrthogonal(1)) {
- type = Shape.Rectangle;
- size = new Size(getDistance(0, 3), getDistance(0, 1));
- topCenter = segments[1]._point.add(segments[2]._point).divide(2);
- } else if (segments.length === 8 && isArc(0) && isArc(2) && isArc(4)
- && isArc(6) && isColinear(1, 5) && isColinear(3, 7)) {
- type = Shape.Rectangle;
- size = new Size(getDistance(1, 6), getDistance(0, 3));
- radius = size.subtract(new Size(getDistance(0, 7),
- getDistance(1, 2))).divide(2);
- topCenter = segments[3]._point.add(segments[4]._point).divide(2);
- } else if (segments.length === 4
- && isArc(0) && isArc(1) && isArc(2) && isArc(3)) {
- if (Numerical.isZero(getDistance(0, 2) - getDistance(1, 3))) {
- type = Shape.Circle;
- radius = getDistance(0, 2) / 2;
- } else {
- type = Shape.Ellipse;
- radius = new Size(getDistance(2, 0) / 2, getDistance(3, 1) / 2);
- }
- topCenter = segments[1]._point;
- }
-
- if (type) {
- var center = this.getPosition(true),
- shape = new type({
- center: center,
- size: size,
- radius: radius,
- insert: false
- });
- shape.rotate(topCenter.subtract(center).getAngle() + 90);
- shape.setStyle(this._style);
- if (insert || insert === undefined)
- shape.insertAbove(this);
- return shape;
- }
- return null;
- },
-
- _getWinding: function(point) {
- var closed = this._closed;
- if (!closed && !this.hasFill()
- || !this._getBounds('getRoughBounds')._containsPoint(point))
- return 0;
- var curves = this.getCurves(),
- segments = this._segments,
- winding = 0,
- roots1 = [],
- roots2 = [],
- last = (closed
- ? curves[curves.length - 1]
- : new Curve(segments[segments.length - 1]._point,
- segments[0]._point)).getValues(),
- previous = last;
- for (var i = 0, l = curves.length; i < l; i++) {
- var curve = curves[i].getValues(),
- x = curve[0],
- y = curve[1];
- if (!(x === curve[2] && y === curve[3] && x === curve[4]
- && y === curve[5] && x === curve[6] && y === curve[7])) {
- winding += Curve._getWinding(curve, previous, point.x, point.y,
- roots1, roots2);
- previous = curve;
- }
- }
- if (!closed) {
- winding += Curve._getWinding(last, previous, point.x, point.y,
- roots1, roots2);
- }
- return winding;
- },
-
- _hitTest: function(point, options) {
- var style = this.getStyle(),
- segments = this._segments,
- closed = this._closed,
- tolerance = options.tolerance,
- radius = 0, join, cap, miterLimit,
- that = this,
- area, loc, res;
-
- if (options.stroke) {
- radius = style.getStrokeWidth() / 2;
- if (radius > 0) {
- join = style.getStrokeJoin();
- cap = style.getStrokeCap();
- miterLimit = radius * style.getMiterLimit();
- } else {
- join = cap = 'round';
- }
- radius += tolerance;
- }
-
- function checkPoint(seg, pt, name) {
- if (point.getDistance(pt) < tolerance)
- return new HitResult(name, that, { segment: seg, point: pt });
- }
-
- function checkSegmentPoints(seg, ends) {
- var pt = seg._point;
- return (ends || options.segments) && checkPoint(seg, pt, 'segment')
- || (!ends && options.handles) && (
- checkPoint(seg, pt.add(seg._handleIn), 'handle-in') ||
- checkPoint(seg, pt.add(seg._handleOut), 'handle-out'));
- }
-
- function addAreaPoint(point) {
- area.push(point);
- }
-
- function getAreaCurve(index) {
- var p1 = area[index],
- p2 = area[(index + 1) % area.length];
- return [p1.x, p1.y, p1.x, p1.y, p2.x, p2.y, p2.x ,p2.y];
- }
-
- function isInArea(point) {
- var length = area.length,
- previous = getAreaCurve(length - 1),
- roots1 = [],
- roots2 = [],
- winding = 0;
- for (var i = 0; i < length; i++) {
- var curve = getAreaCurve(i);
- winding += Curve._getWinding(curve, previous, point.x, point.y,
- roots1, roots2);
- previous = curve;
- }
- return !!winding;
- }
-
- function checkSegmentStroke(segment) {
- if (join !== 'round' || cap !== 'round') {
- area = [];
- if (closed || segment._index > 0
- && segment._index < segments.length - 1) {
- if (join !== 'round' && (segment._handleIn.isZero()
- || segment._handleOut.isZero()))
- Path._addSquareJoin(segment, join, radius, miterLimit,
- addAreaPoint, true);
- } else if (cap !== 'round') {
- Path._addSquareCap(segment, cap, radius, addAreaPoint, true);
- }
- if (area.length > 0)
- return isInArea(point);
- }
- return point.getDistance(segment._point) <= radius;
- }
-
- if (options.ends && !options.segments && !closed) {
- if (res = checkSegmentPoints(segments[0], true)
- || checkSegmentPoints(segments[segments.length - 1], true))
- return res;
- } else if (options.segments || options.handles) {
- for (var i = 0, l = segments.length; i < l; i++) {
- if (res = checkSegmentPoints(segments[i]))
- return res;
- }
- }
- if (radius > 0) {
- loc = this.getNearestLocation(point);
- if (loc) {
- var parameter = loc.getParameter();
- if (parameter === 0 || parameter === 1) {
- if (!checkSegmentStroke(loc.getSegment()))
- loc = null;
- } else if (loc._distance > radius) {
- loc = null;
- }
- }
- if (!loc && join === 'miter') {
- for (var i = 0, l = segments.length; i < l; i++) {
- var segment = segments[i];
- if (point.getDistance(segment._point) <= miterLimit
- && checkSegmentStroke(segment)) {
- loc = segment.getLocation();
- break;
- }
- }
- }
- }
- return !loc && options.fill && this.hasFill() && this._contains(point)
- ? new HitResult('fill', this)
- : loc
- ? new HitResult('stroke', this, { location: loc })
- : null;
- }
-
-}, new function() {
-
- function drawHandles(ctx, segments, matrix, size) {
- var half = size / 2;
-
- function drawHandle(index) {
- var hX = coords[index],
- hY = coords[index + 1];
- if (pX != hX || pY != hY) {
- ctx.beginPath();
- ctx.moveTo(pX, pY);
- ctx.lineTo(hX, hY);
- ctx.stroke();
- ctx.beginPath();
- ctx.arc(hX, hY, half, 0, Math.PI * 2, true);
- ctx.fill();
- }
- }
-
- var coords = new Array(6);
- for (var i = 0, l = segments.length; i < l; i++) {
- var segment = segments[i];
- segment._transformCoordinates(matrix, coords, false);
- var state = segment._selectionState,
- selected = state & 4,
- pX = coords[0],
- pY = coords[1];
- if (selected || (state & 1))
- drawHandle(2);
- if (selected || (state & 2))
- drawHandle(4);
- ctx.save();
- ctx.beginPath();
- ctx.rect(pX - half, pY - half, size, size);
- ctx.fill();
- if (!selected) {
- ctx.beginPath();
- ctx.rect(pX - half + 1, pY - half + 1, size - 2, size - 2);
- ctx.fillStyle = '#ffffff';
- ctx.fill();
- }
- ctx.restore();
- }
- }
-
- function drawSegments(ctx, path, matrix) {
- var segments = path._segments,
- length = segments.length,
- coords = new Array(6),
- first = true,
- curX, curY,
- prevX, prevY,
- inX, inY,
- outX, outY;
-
- function drawSegment(i) {
- var segment = segments[i];
- if (matrix) {
- segment._transformCoordinates(matrix, coords, false);
- curX = coords[0];
- curY = coords[1];
- } else {
- var point = segment._point;
- curX = point._x;
- curY = point._y;
- }
- if (first) {
- ctx.moveTo(curX, curY);
- first = false;
- } else {
- if (matrix) {
- inX = coords[2];
- inY = coords[3];
- } else {
- var handle = segment._handleIn;
- inX = curX + handle._x;
- inY = curY + handle._y;
- }
- if (inX == curX && inY == curY && outX == prevX && outY == prevY) {
- ctx.lineTo(curX, curY);
- } else {
- ctx.bezierCurveTo(outX, outY, inX, inY, curX, curY);
- }
- }
- prevX = curX;
- prevY = curY;
- if (matrix) {
- outX = coords[4];
- outY = coords[5];
- } else {
- var handle = segment._handleOut;
- outX = prevX + handle._x;
- outY = prevY + handle._y;
- }
- }
-
- for (var i = 0; i < length; i++)
- drawSegment(i);
- if (path._closed && length > 1)
- drawSegment(0);
- }
-
- return {
- _draw: function(ctx, param) {
- var clip = param.clip,
- compound = param.compound;
- if (!compound)
- ctx.beginPath();
-
- var style = this.getStyle(),
- hasFill = style.hasFill(),
- hasStroke = style.hasStroke(),
- dashArray = style.getDashArray(),
- dashLength = !paper.support.nativeDash && hasStroke
- && dashArray && dashArray.length;
-
- function getOffset(i) {
- return dashArray[((i % dashLength) + dashLength) % dashLength];
- }
-
- if (hasFill || hasStroke && !dashLength || compound || clip)
- drawSegments(ctx, this);
- if (this._closed)
- ctx.closePath();
-
- if (!clip && !compound && (hasFill || hasStroke)) {
- this._setStyles(ctx);
- if (hasFill) {
- ctx.fill(style.getWindingRule());
- ctx.shadowColor = 'rgba(0,0,0,0)';
- }
- if (hasStroke) {
- if (dashLength) {
- ctx.beginPath();
- var flattener = new PathFlattener(this),
- length = flattener.length,
- from = -style.getDashOffset(), to,
- i = 0;
- from = from % length;
- while (from > 0) {
- from -= getOffset(i--) + getOffset(i--);
- }
- while (from < length) {
- to = from + getOffset(i++);
- if (from > 0 || to > 0)
- flattener.drawPart(ctx,
- Math.max(from, 0), Math.max(to, 0));
- from = to + getOffset(i++);
- }
- }
- ctx.stroke();
- }
- }
- },
-
- _drawSelected: function(ctx, matrix) {
- ctx.beginPath();
- drawSegments(ctx, this, matrix);
- ctx.stroke();
- drawHandles(ctx, this._segments, matrix,
- this._project.options.handleSize || 4);
- }
- };
-}, new function() {
-
- function getFirstControlPoints(rhs) {
- var n = rhs.length,
- x = [],
- tmp = [],
- b = 2;
- x[0] = rhs[0] / b;
- for (var i = 1; i < n; i++) {
- tmp[i] = 1 / b;
- b = (i < n - 1 ? 4 : 2) - tmp[i];
- x[i] = (rhs[i] - x[i - 1]) / b;
- }
- for (var i = 1; i < n; i++) {
- x[n - i - 1] -= tmp[n - i] * x[n - i];
- }
- return x;
- }
-
- return {
- smooth: function() {
- var segments = this._segments,
- size = segments.length,
- closed = this._closed,
- n = size,
- overlap = 0;
- if (size <= 2)
- return;
- if (closed) {
- overlap = Math.min(size, 4);
- n += Math.min(size, overlap) * 2;
- }
- var knots = [];
- for (var i = 0; i < size; i++)
- knots[i + overlap] = segments[i]._point;
- if (closed) {
- for (var i = 0; i < overlap; i++) {
- knots[i] = segments[i + size - overlap]._point;
- knots[i + size + overlap] = segments[i]._point;
- }
- } else {
- n--;
- }
- var rhs = [];
-
- for (var i = 1; i < n - 1; i++)
- rhs[i] = 4 * knots[i]._x + 2 * knots[i + 1]._x;
- rhs[0] = knots[0]._x + 2 * knots[1]._x;
- rhs[n - 1] = 3 * knots[n - 1]._x;
- var x = getFirstControlPoints(rhs);
-
- for (var i = 1; i < n - 1; i++)
- rhs[i] = 4 * knots[i]._y + 2 * knots[i + 1]._y;
- rhs[0] = knots[0]._y + 2 * knots[1]._y;
- rhs[n - 1] = 3 * knots[n - 1]._y;
- var y = getFirstControlPoints(rhs);
-
- if (closed) {
- for (var i = 0, j = size; i < overlap; i++, j++) {
- var f1 = i / overlap,
- f2 = 1 - f1,
- ie = i + overlap,
- je = j + overlap;
- x[j] = x[i] * f1 + x[j] * f2;
- y[j] = y[i] * f1 + y[j] * f2;
- x[je] = x[ie] * f2 + x[je] * f1;
- y[je] = y[ie] * f2 + y[je] * f1;
- }
- n--;
- }
- var handleIn = null;
- for (var i = overlap; i <= n - overlap; i++) {
- var segment = segments[i - overlap];
- if (handleIn)
- segment.setHandleIn(handleIn.subtract(segment._point));
- if (i < n) {
- segment.setHandleOut(
- new Point(x[i], y[i]).subtract(segment._point));
- handleIn = i < n - 1
- ? new Point(
- 2 * knots[i + 1]._x - x[i + 1],
- 2 * knots[i + 1]._y - y[i + 1])
- : new Point(
- (knots[n]._x + x[n - 1]) / 2,
- (knots[n]._y + y[n - 1]) / 2);
- }
- }
- if (closed && handleIn) {
- var segment = this._segments[0];
- segment.setHandleIn(handleIn.subtract(segment._point));
- }
- }
- };
-}, new function() {
- function getCurrentSegment(that) {
- var segments = that._segments;
- if (segments.length == 0)
- throw new Error('Use a moveTo() command first');
- return segments[segments.length - 1];
- }
-
- return {
- moveTo: function() {
- if (this._segments.length === 1)
- this.removeSegment(0);
- if (!this._segments.length)
- this._add([ new Segment(Point.read(arguments)) ]);
- },
-
- moveBy: function() {
- throw new Error('moveBy() is unsupported on Path items.');
- },
-
- lineTo: function() {
- this._add([ new Segment(Point.read(arguments)) ]);
- },
-
- cubicCurveTo: function() {
- var handle1 = Point.read(arguments),
- handle2 = Point.read(arguments),
- to = Point.read(arguments),
- current = getCurrentSegment(this);
- current.setHandleOut(handle1.subtract(current._point));
- this._add([ new Segment(to, handle2.subtract(to)) ]);
- },
-
- quadraticCurveTo: function() {
- var handle = Point.read(arguments),
- to = Point.read(arguments),
- current = getCurrentSegment(this)._point;
- this.cubicCurveTo(
- handle.add(current.subtract(handle).multiply(1 / 3)),
- handle.add(to.subtract(handle).multiply(1 / 3)),
- to
- );
- },
-
- curveTo: function() {
- var through = Point.read(arguments),
- to = Point.read(arguments),
- t = Base.pick(Base.read(arguments), 0.5),
- t1 = 1 - t,
- current = getCurrentSegment(this)._point,
- handle = through.subtract(current.multiply(t1 * t1))
- .subtract(to.multiply(t * t)).divide(2 * t * t1);
- if (handle.isNaN())
- throw new Error(
- 'Cannot put a curve through points with parameter = ' + t);
- this.quadraticCurveTo(handle, to);
- },
-
- arcTo: function() {
- var current = getCurrentSegment(this),
- from = current._point,
- through,
- to = Point.read(arguments),
- clockwise = Base.pick(Base.peek(arguments), true);
- if (typeof clockwise === 'boolean') {
- var middle = from.add(to).divide(2),
- through = middle.add(middle.subtract(from).rotate(
- clockwise ? -90 : 90));
- } else {
- through = to;
- to = Point.read(arguments);
- }
- var l1 = new Line(from.add(through).divide(2),
- through.subtract(from).rotate(90), true),
- l2 = new Line(through.add(to).divide(2),
- to.subtract(through).rotate(90), true),
- center = l1.intersect(l2, true),
- line = new Line(from, to),
- throughSide = line.getSide(through);
- if (!center) {
- if (!throughSide)
- return this.lineTo(to);
- throw new Error('Cannot put an arc through the given points: '
- + [from, through, to]);
- }
- var vector = from.subtract(center),
- extent = vector.getDirectedAngle(to.subtract(center)),
- centerSide = line.getSide(center);
- if (centerSide == 0) {
- extent = throughSide * Math.abs(extent);
- } else if (throughSide == centerSide) {
- extent -= 360 * (extent < 0 ? -1 : 1);
- }
- var ext = Math.abs(extent),
- count = ext >= 360 ? 4 : Math.ceil(ext / 90),
- inc = extent / count,
- half = inc * Math.PI / 360,
- z = 4 / 3 * Math.sin(half) / (1 + Math.cos(half)),
- segments = [];
- for (var i = 0; i <= count; i++) {
- var pt = i < count ? center.add(vector) : to;
- var out = i < count ? vector.rotate(90).multiply(z) : null;
- if (i == 0) {
- current.setHandleOut(out);
- } else {
- segments.push(
- new Segment(pt, vector.rotate(-90).multiply(z), out));
- }
- vector = vector.rotate(inc);
- }
- this._add(segments);
- },
-
- lineBy: function() {
- var to = Point.read(arguments),
- current = getCurrentSegment(this)._point;
- this.lineTo(current.add(to));
- },
-
- curveBy: function() {
- var through = Point.read(arguments),
- to = Point.read(arguments),
- parameter = Base.read(arguments),
- current = getCurrentSegment(this)._point;
- this.curveTo(current.add(through), current.add(to), parameter);
- },
-
- cubicCurveBy: function() {
- var handle1 = Point.read(arguments),
- handle2 = Point.read(arguments),
- to = Point.read(arguments),
- current = getCurrentSegment(this)._point;
- this.cubicCurveTo(current.add(handle1), current.add(handle2),
- current.add(to));
- },
-
- quadraticCurveBy: function() {
- var handle = Point.read(arguments),
- to = Point.read(arguments),
- current = getCurrentSegment(this)._point;
- this.quadraticCurveTo(current.add(handle), current.add(to));
- },
-
- arcBy: function() {
- var current = getCurrentSegment(this)._point,
- point = current.add(Point.read(arguments)),
- clockwise = Base.pick(Base.peek(arguments), true);
- if (typeof clockwise === 'boolean') {
- this.arcTo(point, clockwise);
- } else {
- this.arcTo(point, current.add(Point.read(arguments)));
- }
- },
-
- closePath: function() {
- var first = this.getFirstSegment(),
- last = this.getLastSegment();
- if (first._point.equals(last._point)) {
- first.setHandleIn(last._handleIn);
- last.remove();
- }
- this.setClosed(true);
- }
- };
-}, {
-
- _getBounds: function(getter, matrix) {
- return Path[getter](this._segments, this._closed, this.getStyle(),
- matrix);
- },
-
-statics: {
- isClockwise: function(segments) {
- var sum = 0;
- for (var i = 0, l = segments.length; i < l; i++) {
- var v = Curve.getValues(
- segments[i], segments[i + 1 < l ? i + 1 : 0]);
- for (var j = 2; j < 8; j += 2)
- sum += (v[j - 2] - v[j]) * (v[j + 1] + v[j - 1]);
- }
- return sum > 0;
- },
-
- getBounds: function(segments, closed, style, matrix, strokePadding) {
- var first = segments[0];
- if (!first)
- return new Rectangle();
- var coords = new Array(6),
- prevCoords = first._transformCoordinates(matrix, new Array(6), false),
- min = prevCoords.slice(0, 2),
- max = min.slice(),
- roots = new Array(2);
-
- function processSegment(segment) {
- segment._transformCoordinates(matrix, coords, false);
- for (var i = 0; i < 2; i++) {
- Curve._addBounds(
- prevCoords[i],
- prevCoords[i + 4],
- coords[i + 2],
- coords[i],
- i, strokePadding ? strokePadding[i] : 0, min, max, roots);
- }
- var tmp = prevCoords;
- prevCoords = coords;
- coords = tmp;
- }
-
- for (var i = 1, l = segments.length; i < l; i++)
- processSegment(segments[i]);
- if (closed)
- processSegment(first);
- return new Rectangle(min[0], min[1], max[0] - min[0], max[1] - min[1]);
- },
-
- getStrokeBounds: function(segments, closed, style, matrix) {
- function getPenPadding(radius, matrix) {
- if (!matrix)
- return [radius, radius];
- var mx = matrix.shiftless(),
- hor = mx.transform(new Point(radius, 0)),
- ver = mx.transform(new Point(0, radius)),
- phi = hor.getAngleInRadians(),
- a = hor.getLength(),
- b = ver.getLength();
- var sin = Math.sin(phi),
- cos = Math.cos(phi),
- tan = Math.tan(phi),
- tx = -Math.atan(b * tan / a),
- ty = Math.atan(b / (tan * a));
- return [Math.abs(a * Math.cos(tx) * cos - b * Math.sin(tx) * sin),
- Math.abs(b * Math.sin(ty) * cos + a * Math.cos(ty) * sin)];
- }
-
- if (!style.hasStroke())
- return Path.getBounds(segments, closed, style, matrix);
- var length = segments.length - (closed ? 0 : 1),
- radius = style.getStrokeWidth() / 2,
- padding = getPenPadding(radius, matrix),
- bounds = Path.getBounds(segments, closed, style, matrix, padding),
- join = style.getStrokeJoin(),
- cap = style.getStrokeCap(),
- miterLimit = radius * style.getMiterLimit();
- var joinBounds = new Rectangle(new Size(padding).multiply(2));
-
- function add(point) {
- bounds = bounds.include(matrix
- ? matrix._transformPoint(point, point) : point);
- }
-
- function addJoin(segment, join) {
- if (join === 'round' || !segment._handleIn.isZero()
- && !segment._handleOut.isZero()) {
- bounds = bounds.unite(joinBounds.setCenter(matrix
- ? matrix._transformPoint(segment._point) : segment._point));
- } else {
- Path._addSquareJoin(segment, join, radius, miterLimit, add);
- }
- }
-
- function addCap(segment, cap) {
- switch (cap) {
- case 'round':
- addJoin(segment, cap);
- break;
- case 'butt':
- case 'square':
- Path._addSquareCap(segment, cap, radius, add);
- break;
- }
- }
-
- for (var i = 1; i < length; i++)
- addJoin(segments[i], join);
- if (closed) {
- addJoin(segments[0], join);
- } else {
- addCap(segments[0], cap);
- addCap(segments[segments.length - 1], cap);
- }
- return bounds;
- },
-
- _addSquareJoin: function(segment, join, radius, miterLimit, addPoint, area) {
- var curve2 = segment.getCurve(),
- curve1 = curve2.getPrevious(),
- point = curve2.getPointAt(0, true),
- normal1 = curve1.getNormalAt(1, true),
- normal2 = curve2.getNormalAt(0, true),
- step = normal1.getDirectedAngle(normal2) < 0 ? -radius : radius;
- normal1.setLength(step);
- normal2.setLength(step);
- if (area) {
- addPoint(point);
- addPoint(point.add(normal1));
- }
- if (join === 'miter') {
- var corner = new Line(
- point.add(normal1),
- new Point(-normal1.y, normal1.x), true
- ).intersect(new Line(
- point.add(normal2),
- new Point(-normal2.y, normal2.x), true
- ), true);
- if (corner && point.getDistance(corner) <= miterLimit) {
- addPoint(corner);
- if (!area)
- return;
- }
- }
- if (!area)
- addPoint(point.add(normal1));
- addPoint(point.add(normal2));
- },
-
- _addSquareCap: function(segment, cap, radius, addPoint, area) {
- var point = segment._point,
- loc = segment.getLocation(),
- normal = loc.getNormal().normalize(radius);
- if (area) {
- addPoint(point.subtract(normal));
- addPoint(point.add(normal));
- }
- if (cap === 'square')
- point = point.add(normal.rotate(loc.getParameter() == 0 ? -90 : 90));
- addPoint(point.add(normal));
- addPoint(point.subtract(normal));
- },
-
- getHandleBounds: function(segments, closed, style, matrix, strokePadding,
- joinPadding) {
- var coords = new Array(6),
- x1 = Infinity,
- x2 = -x1,
- y1 = x1,
- y2 = x2;
- strokePadding = strokePadding / 2 || 0;
- joinPadding = joinPadding / 2 || 0;
- for (var i = 0, l = segments.length; i < l; i++) {
- var segment = segments[i];
- segment._transformCoordinates(matrix, coords, false);
- for (var j = 0; j < 6; j += 2) {
- var padding = j == 0 ? joinPadding : strokePadding,
- x = coords[j],
- y = coords[j + 1],
- xn = x - padding,
- xx = x + padding,
- yn = y - padding,
- yx = y + padding;
- if (xn < x1) x1 = xn;
- if (xx > x2) x2 = xx;
- if (yn < y1) y1 = yn;
- if (yx > y2) y2 = yx;
- }
- }
- return new Rectangle(x1, y1, x2 - x1, y2 - y1);
- },
-
- getRoughBounds: function(segments, closed, style, matrix) {
- var strokeWidth = style.getStrokeColor() ? style.getStrokeWidth() : 0,
- joinWidth = strokeWidth;
- if (strokeWidth === 0) {
- strokeWidth = 0.00001;
- } else {
- if (style.getStrokeJoin() === 'miter')
- joinWidth = strokeWidth * style.getMiterLimit();
- if (style.getStrokeCap() === 'square')
- joinWidth = Math.max(joinWidth, strokeWidth * Math.sqrt(2));
- }
- return Path.getHandleBounds(segments, closed, style, matrix,
- strokeWidth, joinWidth);
- }
-}});
-
-Path.inject({ statics: new function() {
-
- var kappa = Numerical.KAPPA,
- ellipseSegments = [
- new Segment([-1, 0], [0, kappa ], [0, -kappa]),
- new Segment([0, -1], [-kappa, 0], [kappa, 0 ]),
- new Segment([1, 0], [0, -kappa], [0, kappa ]),
- new Segment([0, 1], [kappa, 0 ], [-kappa, 0])
- ];
-
- function createEllipse(center, radius, args) {
- var path = new Path(),
- segments = new Array(4);
- for (var i = 0; i < 4; i++) {
- var segment = ellipseSegments[i];
- segments[i] = new Segment(
- segment._point.multiply(radius).add(center),
- segment._handleIn.multiply(radius),
- segment._handleOut.multiply(radius)
- );
- }
- path._add(segments);
- path._closed = true;
- return path.set(Base.getNamed(args));
- }
-
- return {
- Line: function() {
- return new Path(
- Point.readNamed(arguments, 'from'),
- Point.readNamed(arguments, 'to')
- ).set(Base.getNamed(arguments));
- },
-
- Circle: function() {
- var center = Point.readNamed(arguments, 'center'),
- radius = Base.readNamed(arguments, 'radius');
- return createEllipse(center, new Size(radius), arguments);
- },
-
- Rectangle: function() {
- var rect = Rectangle.readNamed(arguments, 'rectangle'),
- radius = Size.readNamed(arguments, 'radius', 0, 0,
- { readNull: true }),
- bl = rect.getBottomLeft(true),
- tl = rect.getTopLeft(true),
- tr = rect.getTopRight(true),
- br = rect.getBottomRight(true);
- path = new Path();
- if (!radius || radius.isZero()) {
- path._add([
- new Segment(bl),
- new Segment(tl),
- new Segment(tr),
- new Segment(br)
- ]);
- } else {
- radius = Size.min(radius, rect.getSize(true).divide(2));
- var rx = radius.width,
- ry = radius.height,
- hx = rx * kappa,
- hy = ry * kappa;
- path._add([
- new Segment(bl.add(rx, 0), null, [-hx, 0]),
- new Segment(bl.subtract(0, ry), [0, hy]),
- new Segment(tl.add(0, ry), null, [0, -hy]),
- new Segment(tl.add(rx, 0), [-hx, 0], null),
- new Segment(tr.subtract(rx, 0), null, [hx, 0]),
- new Segment(tr.add(0, ry), [0, -hy], null),
- new Segment(br.subtract(0, ry), null, [0, hy]),
- new Segment(br.subtract(rx, 0), [hx, 0])
- ]);
- }
- path._closed = true;
- return path.set(Base.getNamed(arguments));
- },
-
- RoundRectangle: '#Rectangle',
-
- Ellipse: function() {
- var ellipse = Shape._readEllipse(arguments);
- return createEllipse(ellipse.center, ellipse.radius, arguments);
- },
-
- Oval: '#Ellipse',
-
- Arc: function() {
- var from = Point.readNamed(arguments, 'from'),
- through = Point.readNamed(arguments, 'through'),
- to = Point.readNamed(arguments, 'to'),
- path = new Path();
- path.moveTo(from);
- path.arcTo(through, to);
- return path.set(Base.getNamed(arguments));
- },
-
- RegularPolygon: function() {
- var center = Point.readNamed(arguments, 'center'),
- sides = Base.readNamed(arguments, 'sides'),
- radius = Base.readNamed(arguments, 'radius'),
- path = new Path(),
- step = 360 / sides,
- three = !(sides % 3),
- vector = new Point(0, three ? -radius : radius),
- offset = three ? -1 : 0.5,
- segments = new Array(sides);
- for (var i = 0; i < sides; i++) {
- segments[i] = new Segment(center.add(
- vector.rotate((i + offset) * step)));
- }
- path._add(segments);
- path._closed = true;
- return path.set(Base.getNamed(arguments));
- },
-
- Star: function() {
- var center = Point.readNamed(arguments, 'center'),
- points = Base.readNamed(arguments, 'points') * 2,
- radius1 = Base.readNamed(arguments, 'radius1'),
- radius2 = Base.readNamed(arguments, 'radius2'),
- path = new Path(),
- step = 360 / points,
- vector = new Point(0, -1),
- segments = new Array(points);
- for (var i = 0; i < points; i++) {
- segments[i] = new Segment(center.add(
- vector.rotate(step * i).multiply(i % 2 ? radius2 : radius1)));
- }
- path._add(segments);
- path._closed = true;
- return path.set(Base.getNamed(arguments));
- }
- };
-}});
-
-var CompoundPath = PathItem.extend({
- _class: 'CompoundPath',
- _serializeFields: {
- children: []
- },
-
- initialize: function CompoundPath(arg) {
- this._children = [];
- this._namedChildren = {};
- if (!this._initialize(arg))
- this.addChildren(Array.isArray(arg) ? arg : arguments);
- },
-
- insertChildren: function insertChildren(index, items, _preserve) {
- items = insertChildren.base.call(this, index, items, _preserve, 'path');
- for (var i = 0, l = !_preserve && items && items.length; i < l; i++) {
- var item = items[i];
- if (item._clockwise === undefined)
- item.setClockwise(item._index === 0);
- }
- return items;
- },
-
- reverse: function() {
- var children = this._children;
- for (var i = 0, l = children.length; i < l; i++)
- children[i].reverse();
- },
-
- smooth: function() {
- for (var i = 0, l = this._children.length; i < l; i++)
- this._children[i].smooth();
- },
-
- isClockwise: function() {
- var child = this.getFirstChild();
- return child && child.isClockwise();
- },
-
- setClockwise: function(clockwise) {
- if (this.isClockwise() != !!clockwise)
- this.reverse();
- },
-
- getFirstSegment: function() {
- var first = this.getFirstChild();
- return first && first.getFirstSegment();
- },
-
- getLastSegment: function() {
- var last = this.getLastChild();
- return last && last.getLastSegment();
- },
-
- getCurves: function() {
- var children = this._children,
- curves = [];
- for (var i = 0, l = children.length; i < l; i++)
- curves = curves.concat(children[i].getCurves());
- return curves;
- },
-
- getFirstCurve: function() {
- var first = this.getFirstChild();
- return first && first.getFirstCurve();
- },
-
- getLastCurve: function() {
- var last = this.getLastChild();
- return last && last.getFirstCurve();
- },
-
- getArea: function() {
- var children = this._children,
- area = 0;
- for (var i = 0, l = children.length; i < l; i++)
- area += children[i].getArea();
- return area;
- },
-
- getPathData: function() {
- var children = this._children,
- paths = [];
- for (var i = 0, l = children.length; i < l; i++)
- paths.push(children[i].getPathData(arguments[0]));
- return paths.join(' ');
- },
-
- _getWinding: function(point) {
- var children = this._children,
- winding = 0;
- for (var i = 0, l = children.length; i < l; i++)
- winding += children[i]._getWinding(point);
- return winding;
- },
-
- _hitTest : function _hitTest(point, options) {
- var res = _hitTest.base.call(this, point,
- new Base(options, { fill: false }));
- if (!res) {
- if (options.compoundChildren) {
- var children = this._children;
- for (var i = children.length - 1; i >= 0 && !res; i--)
- res = children[i]._hitTest(point, options);
- } else if (options.fill && this.hasFill()
- && this._contains(point)) {
- res = new HitResult('fill', this);
- }
- }
- return res;
- },
-
- _draw: function(ctx, param) {
- var children = this._children;
- if (children.length === 0)
- return;
-
- ctx.beginPath();
- param = param.extend({ compound: true });
- for (var i = 0, l = children.length; i < l; i++)
- children[i].draw(ctx, param);
-
- if (!param.clip) {
- this._setStyles(ctx);
- var style = this._style;
- if (style.hasFill()) {
- ctx.fill(style.getWindingRule());
- ctx.shadowColor = 'rgba(0,0,0,0)';
- }
- if (style.hasStroke())
- ctx.stroke();
- }
- }
-}, new function() {
- function getCurrentPath(that) {
- if (!that._children.length)
- throw new Error('Use a moveTo() command first');
- return that._children[that._children.length - 1];
- }
-
- var fields = {
- moveTo: function() {
- var path = new Path();
- this.addChild(path);
- path.moveTo.apply(path, arguments);
- },
-
- moveBy: function() {
- this.moveTo(getCurrentPath(this).getLastSegment()._point.add(
- Point.read(arguments)));
- },
-
- closePath: function() {
- getCurrentPath(this).closePath();
- }
- };
-
- Base.each(['lineTo', 'cubicCurveTo', 'quadraticCurveTo', 'curveTo', 'arcTo',
- 'lineBy', 'cubicCurveBy', 'quadraticCurveBy', 'curveBy', 'arcBy'],
- function(key) {
- fields[key] = function() {
- var path = getCurrentPath(this);
- path[key].apply(path, arguments);
- };
- }
- );
-
- return fields;
-});
-
-var PathFlattener = Base.extend({
- initialize: function(path) {
- this.curves = [];
- this.parts = [];
- this.length = 0;
- this.index = 0;
-
- var segments = path._segments,
- segment1 = segments[0],
- segment2,
- that = this;
-
- function addCurve(segment1, segment2) {
- var curve = Curve.getValues(segment1, segment2);
- that.curves.push(curve);
- that._computeParts(curve, segment1._index, 0, 1);
- }
-
- for (var i = 1, l = segments.length; i < l; i++) {
- segment2 = segments[i];
- addCurve(segment1, segment2);
- segment1 = segment2;
- }
- if (path._closed)
- addCurve(segment2, segments[0]);
- },
-
- _computeParts: function(curve, index, minT, maxT) {
- if ((maxT - minT) > 1 / 32 && !Curve.isFlatEnough(curve, 0.25)) {
- var curves = Curve.subdivide(curve);
- var halfT = (minT + maxT) / 2;
- this._computeParts(curves[0], index, minT, halfT);
- this._computeParts(curves[1], index, halfT, maxT);
- } else {
- var x = curve[6] - curve[0],
- y = curve[7] - curve[1],
- dist = Math.sqrt(x * x + y * y);
- if (dist > 0.00001) {
- this.length += dist;
- this.parts.push({
- offset: this.length,
- value: maxT,
- index: index
- });
- }
- }
- },
-
- getParameterAt: function(offset) {
- var i, j = this.index;
- for (;;) {
- i = j;
- if (j == 0 || this.parts[--j].offset < offset)
- break;
- }
- for (var l = this.parts.length; i < l; i++) {
- var part = this.parts[i];
- if (part.offset >= offset) {
- this.index = i;
- var prev = this.parts[i - 1];
- var prevVal = prev && prev.index == part.index ? prev.value : 0,
- prevLen = prev ? prev.offset : 0;
- return {
- value: prevVal + (part.value - prevVal)
- * (offset - prevLen) / (part.offset - prevLen),
- index: part.index
- };
- }
- }
- var part = this.parts[this.parts.length - 1];
- return {
- value: 1,
- index: part.index
- };
- },
-
- evaluate: function(offset, type) {
- var param = this.getParameterAt(offset);
- return Curve.evaluate(this.curves[param.index], param.value, type);
- },
-
- drawPart: function(ctx, from, to) {
- from = this.getParameterAt(from);
- to = this.getParameterAt(to);
- for (var i = from.index; i <= to.index; i++) {
- var curve = Curve.getPart(this.curves[i],
- i == from.index ? from.value : 0,
- i == to.index ? to.value : 1);
- if (i == from.index)
- ctx.moveTo(curve[0], curve[1]);
- ctx.bezierCurveTo.apply(ctx, curve.slice(2));
- }
- }
-});
-
-var PathFitter = Base.extend({
- initialize: function(path, error) {
- this.points = [];
- var segments = path._segments,
- prev;
- for (var i = 0, l = segments.length; i < l; i++) {
- var point = segments[i].point.clone();
- if (!prev || !prev.equals(point)) {
- this.points.push(point);
- prev = point;
- }
- }
- this.error = error;
- },
-
- fit: function() {
- var points = this.points,
- length = points.length;
- this.segments = length > 0 ? [new Segment(points[0])] : [];
- if (length > 1)
- this.fitCubic(0, length - 1,
- points[1].subtract(points[0]).normalize(),
- points[length - 2].subtract(points[length - 1]).normalize());
- return this.segments;
- },
-
- fitCubic: function(first, last, tan1, tan2) {
- if (last - first == 1) {
- var pt1 = this.points[first],
- pt2 = this.points[last],
- dist = pt1.getDistance(pt2) / 3;
- this.addCurve([pt1, pt1.add(tan1.normalize(dist)),
- pt2.add(tan2.normalize(dist)), pt2]);
- return;
- }
- var uPrime = this.chordLengthParameterize(first, last),
- maxError = Math.max(this.error, this.error * this.error),
- split;
- for (var i = 0; i <= 4; i++) {
- var curve = this.generateBezier(first, last, uPrime, tan1, tan2);
- var max = this.findMaxError(first, last, curve, uPrime);
- if (max.error < this.error) {
- this.addCurve(curve);
- return;
- }
- split = max.index;
- if (max.error >= maxError)
- break;
- this.reparameterize(first, last, uPrime, curve);
- maxError = max.error;
- }
- var V1 = this.points[split - 1].subtract(this.points[split]),
- V2 = this.points[split].subtract(this.points[split + 1]),
- tanCenter = V1.add(V2).divide(2).normalize();
- this.fitCubic(first, split, tan1, tanCenter);
- this.fitCubic(split, last, tanCenter.negate(), tan2);
- },
-
- addCurve: function(curve) {
- var prev = this.segments[this.segments.length - 1];
- prev.setHandleOut(curve[1].subtract(curve[0]));
- this.segments.push(
- new Segment(curve[3], curve[2].subtract(curve[3])));
- },
-
- generateBezier: function(first, last, uPrime, tan1, tan2) {
- var epsilon = 1e-11,
- pt1 = this.points[first],
- pt2 = this.points[last],
- C = [[0, 0], [0, 0]],
- X = [0, 0];
-
- for (var i = 0, l = last - first + 1; i < l; i++) {
- var u = uPrime[i],
- t = 1 - u,
- b = 3 * u * t,
- b0 = t * t * t,
- b1 = b * t,
- b2 = b * u,
- b3 = u * u * u,
- a1 = tan1.normalize(b1),
- a2 = tan2.normalize(b2),
- tmp = this.points[first + i]
- .subtract(pt1.multiply(b0 + b1))
- .subtract(pt2.multiply(b2 + b3));
- C[0][0] += a1.dot(a1);
- C[0][1] += a1.dot(a2);
- C[1][0] = C[0][1];
- C[1][1] += a2.dot(a2);
- X[0] += a1.dot(tmp);
- X[1] += a2.dot(tmp);
- }
-
- var detC0C1 = C[0][0] * C[1][1] - C[1][0] * C[0][1],
- alpha1, alpha2;
- if (Math.abs(detC0C1) > epsilon) {
- var detC0X = C[0][0] * X[1] - C[1][0] * X[0],
- detXC1 = X[0] * C[1][1] - X[1] * C[0][1];
- alpha1 = detXC1 / detC0C1;
- alpha2 = detC0X / detC0C1;
- } else {
- var c0 = C[0][0] + C[0][1],
- c1 = C[1][0] + C[1][1];
- if (Math.abs(c0) > epsilon) {
- alpha1 = alpha2 = X[0] / c0;
- } else if (Math.abs(c1) > epsilon) {
- alpha1 = alpha2 = X[1] / c1;
- } else {
- alpha1 = alpha2 = 0;
- }
- }
-
- var segLength = pt2.getDistance(pt1);
- epsilon *= segLength;
- if (alpha1 < epsilon || alpha2 < epsilon) {
- alpha1 = alpha2 = segLength / 3;
- }
-
- return [pt1, pt1.add(tan1.normalize(alpha1)),
- pt2.add(tan2.normalize(alpha2)), pt2];
- },
-
- reparameterize: function(first, last, u, curve) {
- for (var i = first; i <= last; i++) {
- u[i - first] = this.findRoot(curve, this.points[i], u[i - first]);
- }
- },
-
- findRoot: function(curve, point, u) {
- var curve1 = [],
- curve2 = [];
- for (var i = 0; i <= 2; i++) {
- curve1[i] = curve[i + 1].subtract(curve[i]).multiply(3);
- }
- for (var i = 0; i <= 1; i++) {
- curve2[i] = curve1[i + 1].subtract(curve1[i]).multiply(2);
- }
- var pt = this.evaluate(3, curve, u),
- pt1 = this.evaluate(2, curve1, u),
- pt2 = this.evaluate(1, curve2, u),
- diff = pt.subtract(point),
- df = pt1.dot(pt1) + diff.dot(pt2);
- if (Math.abs(df) < 0.00001)
- return u;
- return u - diff.dot(pt1) / df;
- },
-
- evaluate: function(degree, curve, t) {
- var tmp = curve.slice();
- for (var i = 1; i <= degree; i++) {
- for (var j = 0; j <= degree - i; j++) {
- tmp[j] = tmp[j].multiply(1 - t).add(tmp[j + 1].multiply(t));
- }
- }
- return tmp[0];
- },
-
- chordLengthParameterize: function(first, last) {
- var u = [0];
- for (var i = first + 1; i <= last; i++) {
- u[i - first] = u[i - first - 1]
- + this.points[i].getDistance(this.points[i - 1]);
- }
- for (var i = 1, m = last - first; i <= m; i++) {
- u[i] /= u[m];
- }
- return u;
- },
-
- findMaxError: function(first, last, curve, u) {
- var index = Math.floor((last - first + 1) / 2),
- maxDist = 0;
- for (var i = first + 1; i < last; i++) {
- var P = this.evaluate(3, curve, u[i - first]);
- var v = P.subtract(this.points[i]);
- var dist = v.x * v.x + v.y * v.y;
- if (dist >= maxDist) {
- maxDist = dist;
- index = i;
- }
- }
- return {
- error: maxDist,
- index: index
- };
- }
-});
-
-PathItem.inject(new function() {
-
- function splitPath(intersections, collectOthers) {
- intersections.sort(function(loc1, loc2) {
- var path1 = loc1.getPath(),
- path2 = loc2.getPath();
- return path1 === path2
- ? (loc1.getIndex() + loc1.getParameter())
- - (loc2.getIndex() + loc2.getParameter())
- : path1._id - path2._id;
- });
- var others = collectOthers && [];
- for (var i = intersections.length - 1; i >= 0; i--) {
- var loc = intersections[i],
- other = loc.getIntersection(),
- curve = loc.divide(),
- segment = curve && curve.getSegment1() || loc.getSegment();
- if (others)
- others.push(other);
- segment._intersection = other;
- loc._segment = segment;
- }
- return others;
- }
-
- function reorientPath(path) {
- if (path instanceof CompoundPath) {
- var children = path.removeChildren(),
- length = children.length,
- bounds = new Array(length),
- counters = new Array(length),
- clockwise;
- children.sort(function(a, b){
- var b1 = a.getBounds(), b2 = b.getBounds();
- return b1._width * b1._height < b2._width * b2._height;
- });
- path.addChildren(children);
- clockwise = children[0].isClockwise();
- for (var i = 0; i < length; i++) {
- bounds[i] = children[i].getBounds();
- counters[i] = 0;
- }
- for (var i = 0; i < length; i++) {
- for (var j = 1; j < length; j++) {
- if (i !== j && bounds[i].contains(bounds[j]))
- counters[j]++;
- }
- if (i > 0 && counters[i] % 2 === 0)
- children[i].setClockwise(clockwise);
- }
- }
- return path;
- }
-
- function computeBoolean(path1, path2, operator, subtract) {
- path1 = reorientPath(path1.clone(false));
- path2 = reorientPath(path2.clone(false));
- var path1Clockwise = path1.isClockwise(),
- path2Clockwise = path2.isClockwise(),
- intersections = path1.getIntersections(path2);
- splitPath(splitPath(intersections, true));
- if (!path1Clockwise)
- path1.reverse();
- if (!(subtract ^ path2Clockwise))
- path2.reverse();
- path1Clockwise = true;
- path2Clockwise = !subtract;
- var paths = []
- .concat(path1._children || [path1])
- .concat(path2._children || [path2]),
- segments = [],
- result = new CompoundPath();
- for (var i = 0, l = paths.length; i < l; i++) {
- var path = paths[i],
- parent = path._parent,
- clockwise = path.isClockwise(),
- segs = path._segments;
- path = parent instanceof CompoundPath ? parent : path;
- for (var j = segs.length - 1; j >= 0; j--) {
- var segment = segs[j],
- midPoint = segment.getCurve().getPoint(0.5),
- insidePath1 = path !== path1 && path1.contains(midPoint)
- && (clockwise === path1Clockwise || subtract
- || !testOnCurve(path1, midPoint)),
- insidePath2 = path !== path2 && path2.contains(midPoint)
- && (clockwise === path2Clockwise
- || !testOnCurve(path2, midPoint));
- if (operator(path === path1, insidePath1, insidePath2)) {
- segment._invalid = true;
- } else {
- segments.push(segment);
- }
- }
- }
- for (var i = 0, l = segments.length; i < l; i++) {
- var segment = segments[i];
- if (segment._visited)
- continue;
- var path = new Path(),
- loc = segment._intersection,
- intersection = loc && loc.getSegment(true);
- if (segment.getPrevious()._invalid)
- segment.setHandleIn(intersection
- ? intersection._handleIn
- : new Point(0, 0));
- do {
- segment._visited = true;
- if (segment._invalid && segment._intersection) {
- var inter = segment._intersection.getSegment(true);
- path.add(new Segment(segment._point, segment._handleIn,
- inter._handleOut));
- inter._visited = true;
- segment = inter;
- } else {
- path.add(segment.clone());
- }
- segment = segment.getNext();
- } while (segment && !segment._visited && segment !== intersection);
- var amount = path._segments.length;
- if (amount > 1 && (amount > 2 || !path.isPolygon())) {
- path.setClosed(true);
- result.addChild(path, true);
- } else {
- path.remove();
- }
- }
- path1.remove();
- path2.remove();
- return result.reduce();
- }
-
- function testOnCurve(path, point) {
- var curves = path.getCurves(),
- bounds = path.getBounds();
- if (bounds.contains(point)) {
- for (var i = 0, l = curves.length; i < l; i++) {
- var curve = curves[i];
- if (curve.getBounds().contains(point)
- && curve.getParameterOf(point))
- return true;
- }
- }
- return false;
- }
-
- return {
- unite: function(path) {
- return computeBoolean(this, path,
- function(isPath1, isInPath1, isInPath2) {
- return isInPath1 || isInPath2;
- });
- },
-
- intersect: function(path) {
- return computeBoolean(this, path,
- function(isPath1, isInPath1, isInPath2) {
- return !(isInPath1 || isInPath2);
- });
- },
-
- subtract: function(path) {
- return computeBoolean(this, path,
- function(isPath1, isInPath1, isInPath2) {
- return isPath1 && isInPath2 || !isPath1 && !isInPath1;
- }, true);
- },
-
- exclude: function(path) {
- return new Group([this.subtract(path), path.subtract(this)]);
- },
-
- divide: function(path) {
- return new Group([this.subtract(path), this.intersect(path)]);
- }
- };
-});
-
-var TextItem = Item.extend({
- _class: 'TextItem',
- _boundsSelected: true,
- _serializeFields: {
- content: null
- },
- _boundsGetter: 'getBounds',
-
- initialize: function TextItem(arg) {
- this._content = '';
- this._lines = [];
- var hasProps = arg && Base.isPlainObject(arg)
- && arg.x === undefined && arg.y === undefined;
- this._initialize(hasProps && arg, !hasProps && Point.read(arguments));
- },
-
- _equals: function(item) {
- return this._content === item._content;
- },
-
- _clone: function _clone(copy) {
- copy.setContent(this._content);
- return _clone.base.call(this, copy);
- },
-
- getContent: function() {
- return this._content;
- },
-
- setContent: function(content) {
- this._content = '' + content;
- this._lines = this._content.split(/\r\n|\n|\r/mg);
- this._changed(69);
- },
-
- isEmpty: function() {
- return !this._content;
- },
-
- getCharacterStyle: '#getStyle',
- setCharacterStyle: '#setStyle',
-
- getParagraphStyle: '#getStyle',
- setParagraphStyle: '#setStyle'
-});
-
-var PointText = TextItem.extend({
- _class: 'PointText',
-
- initialize: function PointText() {
- TextItem.apply(this, arguments);
- },
-
- clone: function(insert) {
- return this._clone(new PointText({ insert: false }), insert);
- },
-
- getPoint: function() {
- var point = this._matrix.getTranslation();
- return new LinkedPoint(point.x, point.y, this, 'setPoint');
- },
-
- setPoint: function(point) {
- point = Point.read(arguments);
- this.translate(point.subtract(this._matrix.getTranslation()));
- },
-
- _draw: function(ctx) {
- if (!this._content)
- return;
- this._setStyles(ctx);
- var style = this._style,
- lines = this._lines,
- leading = style.getLeading(),
- shadowColor = ctx.shadowColor;
-
- ctx.font = style.getFontStyle();
- ctx.textAlign = style.getJustification();
- for (var i = 0, l = lines.length; i < l; i++) {
- ctx.shadowColor = shadowColor;
- var line = lines[i];
- if (style.hasFill()) {
- ctx.fillText(line, 0, 0);
- ctx.shadowColor = 'rgba(0,0,0,0)';
- }
- if (style.hasStroke())
- ctx.strokeText(line, 0, 0);
- ctx.translate(0, leading);
- }
- }
-}, new function() {
- var measureCtx = null;
-
- return {
- _getBounds: function(getter, matrix) {
- if (!measureCtx)
- measureCtx = CanvasProvider.getContext(1, 1);
- var style = this._style,
- lines = this._lines,
- count = lines.length,
- justification = style.getJustification(),
- leading = style.getLeading(),
- x = 0;
- measureCtx.font = style.getFontStyle();
- var width = 0;
- for (var i = 0; i < count; i++)
- width = Math.max(width, measureCtx.measureText(lines[i]).width);
- if (justification !== 'left')
- x -= width / (justification === 'center' ? 2: 1);
- var bounds = new Rectangle(x,
- count ? - 0.75 * leading : 0,
- width, count * leading);
- return matrix ? matrix._transformBounds(bounds, bounds) : bounds;
- }
- };
-});
-
-var Color = Base.extend(new function() {
-
- var types = {
- gray: ['gray'],
- rgb: ['red', 'green', 'blue'],
- hsb: ['hue', 'saturation', 'brightness'],
- hsl: ['hue', 'saturation', 'lightness'],
- gradient: ['gradient', 'origin', 'destination', 'highlight']
- };
-
- var componentParsers = {},
- colorCache = {},
- colorCtx;
-
- function fromCSS(string) {
- var match = string.match(/^#(\w{1,2})(\w{1,2})(\w{1,2})$/),
- components;
- if (match) {
- components = [0, 0, 0];
- for (var i = 0; i < 3; i++) {
- var value = match[i + 1];
- components[i] = parseInt(value.length == 1
- ? value + value : value, 16) / 255;
- }
- } else if (match = string.match(/^rgba?\((.*)\)$/)) {
- components = match[1].split(',');
- for (var i = 0, l = components.length; i < l; i++) {
- var value = parseFloat(components[i]);
- components[i] = i < 3 ? value / 255 : value;
- }
- } else {
- var cached = colorCache[string];
- if (!cached) {
- if (!colorCtx) {
- colorCtx = CanvasProvider.getContext(1, 1);
- colorCtx.globalCompositeOperation = 'copy';
- }
- colorCtx.fillStyle = 'rgba(0,0,0,0)';
- colorCtx.fillStyle = string;
- colorCtx.fillRect(0, 0, 1, 1);
- var data = colorCtx.getImageData(0, 0, 1, 1).data;
- cached = colorCache[string] = [
- data[0] / 255,
- data[1] / 255,
- data[2] / 255
- ];
- }
- components = cached.slice();
- }
- return components;
- }
-
- var hsbIndices = [
- [0, 3, 1],
- [2, 0, 1],
- [1, 0, 3],
- [1, 2, 0],
- [3, 1, 0],
- [0, 1, 2]
- ];
-
- var converters = {
- 'rgb-hsb': function(r, g, b) {
- var max = Math.max(r, g, b),
- min = Math.min(r, g, b),
- delta = max - min,
- h = delta === 0 ? 0
- : ( max == r ? (g - b) / delta + (g < b ? 6 : 0)
- : max == g ? (b - r) / delta + 2
- : (r - g) / delta + 4) * 60;
- return [h, max === 0 ? 0 : delta / max, max];
- },
-
- 'hsb-rgb': function(h, s, b) {
- var h = (h / 60) % 6,
- i = Math.floor(h),
- f = h - i,
- i = hsbIndices[i],
- v = [
- b,
- b * (1 - s),
- b * (1 - s * f),
- b * (1 - s * (1 - f))
- ];
- return [v[i[0]], v[i[1]], v[i[2]]];
- },
-
- 'rgb-hsl': function(r, g, b) {
- var max = Math.max(r, g, b),
- min = Math.min(r, g, b),
- delta = max - min,
- achromatic = delta === 0,
- h = achromatic ? 0
- : ( max == r ? (g - b) / delta + (g < b ? 6 : 0)
- : max == g ? (b - r) / delta + 2
- : (r - g) / delta + 4) * 60,
- l = (max + min) / 2,
- s = achromatic ? 0 : l < 0.5
- ? delta / (max + min)
- : delta / (2 - max - min);
- return [h, s, l];
- },
-
- 'hsl-rgb': function(h, s, l) {
- h /= 360;
- if (s === 0)
- return [l, l, l];
- var t3s = [ h + 1 / 3, h, h - 1 / 3 ],
- t2 = l < 0.5 ? l * (1 + s) : l + s - l * s,
- t1 = 2 * l - t2,
- c = [];
- for (var i = 0; i < 3; i++) {
- var t3 = t3s[i];
- if (t3 < 0) t3 += 1;
- if (t3 > 1) t3 -= 1;
- c[i] = 6 * t3 < 1
- ? t1 + (t2 - t1) * 6 * t3
- : 2 * t3 < 1
- ? t2
- : 3 * t3 < 2
- ? t1 + (t2 - t1) * ((2 / 3) - t3) * 6
- : t1;
- }
- return c;
- },
-
- 'rgb-gray': function(r, g, b) {
- return [r * 0.2989 + g * 0.587 + b * 0.114];
- },
-
- 'gray-rgb': function(g) {
- return [g, g, g];
- },
-
- 'gray-hsb': function(g) {
- return [0, 0, g];
- },
-
- 'gray-hsl': function(g) {
- return [0, 0, g];
- },
-
- 'gradient-rgb': function() {
- return [];
- },
-
- 'rgb-gradient': function() {
- return [];
- }
-
- };
-
- return Base.each(types, function(properties, type) {
- componentParsers[type] = [];
- Base.each(properties, function(name, index) {
- var part = Base.capitalize(name),
- hasOverlap = /^(hue|saturation)$/.test(name),
- parser = componentParsers[type][index] = name === 'gradient'
- ? function(value) {
- var current = this._components[0];
- value = Gradient.read(
- Array.isArray(value) ? value : arguments,
- 0, 0, { readNull: true });
- if (current !== value) {
- if (current)
- current._removeOwner(this);
- if (value)
- value._addOwner(this);
- }
- return value;
- }
- : name === 'hue'
- ? function(value) {
- return isNaN(value) ? 0
- : ((value % 360) + 360) % 360;
- }
- : type === 'gradient'
- ? function() {
- return Point.read(arguments, 0, 0, {
- readNull: name === 'highlight',
- clone: true
- });
- }
- : function(value) {
- return isNaN(value) ? 0
- : Math.min(Math.max(value, 0), 1);
- };
-
- this['get' + part] = function() {
- return this._type === type
- || hasOverlap && /^hs[bl]$/.test(this._type)
- ? this._components[index]
- : this._convert(type)[index];
- };
-
- this['set' + part] = function(value) {
- if (this._type !== type
- && !(hasOverlap && /^hs[bl]$/.test(this._type))) {
- this._components = this._convert(type);
- this._properties = types[type];
- this._type = type;
- }
- value = parser.call(this, value);
- if (value != null) {
- this._components[index] = value;
- this._changed();
- }
- };
- }, this);
- }, {
- _class: 'Color',
- _readIndex: true,
-
- initialize: function Color(arg) {
- var slice = Array.prototype.slice,
- args = arguments,
- read = 0,
- parse = true,
- type,
- components,
- alpha,
- values;
- if (Array.isArray(arg)) {
- args = arg;
- arg = args[0];
- }
- var argType = arg != null && typeof arg;
- if (argType === 'string' && arg in types) {
- type = arg;
- arg = args[1];
- if (Array.isArray(arg)) {
- components = arg;
- alpha = args[2];
- } else {
- if (this.__read)
- read = 1;
- args = slice.call(args, 1);
- argType = typeof arg;
- }
- }
- if (!components) {
- parse = !(this.__options && this.__options.dontParse);
- values = argType === 'number'
- ? args
- : argType === 'object' && arg.length != null
- ? arg
- : null;
- if (values) {
- if (!type)
- type = values.length >= 3
- ? 'rgb'
- : 'gray';
- var length = types[type].length;
- alpha = values[length];
- if (this.__read)
- read += values === arguments
- ? length + (alpha != null ? 1 : 0)
- : 1;
- if (values.length > length)
- values = slice.call(values, 0, length);
- } else if (argType === 'string') {
- type = 'rgb';
- components = fromCSS(arg);
- if (components.length === 4) {
- alpha = components[3];
- components.length--;
- }
- } else if (argType === 'object') {
- if (arg.constructor === Color) {
- type = arg._type;
- components = arg._components.slice();
- alpha = arg._alpha;
- if (type === 'gradient') {
- for (var i = 1, l = components.length; i < l; i++) {
- var point = components[i];
- if (point)
- components[i] = point.clone();
- }
- }
- } else if (arg.constructor === Gradient) {
- type = 'gradient';
- values = args;
- } else {
- type = 'hue' in arg
- ? 'lightness' in arg
- ? 'hsl'
- : 'hsb'
- : 'gradient' in arg || 'stops' in arg
- || 'radial' in arg
- ? 'gradient'
- : 'gray' in arg
- ? 'gray'
- : 'rgb';
- var properties = types[type];
- parsers = parse && componentParsers[type];
- this._components = components = [];
- for (var i = 0, l = properties.length; i < l; i++) {
- var value = arg[properties[i]];
- if (value == null && i === 0 && type === 'gradient'
- && 'stops' in arg) {
- value = {
- stops: arg.stops,
- radial: arg.radial
- };
- }
- if (parse)
- value = parsers[i].call(this, value);
- if (value != null)
- components[i] = value;
- }
- alpha = arg.alpha;
- }
- }
- if (this.__read && type)
- read = 1;
- }
- this._type = type || 'rgb';
- if (type === 'gradient')
- this._id = Color._id = (Color._id || 0) + 1;
- if (!components) {
- this._components = components = [];
- var parsers = componentParsers[this._type];
- for (var i = 0, l = parsers.length; i < l; i++) {
- var value = values && values[i];
- if (parse)
- value = parsers[i].call(this, value);
- if (value != null)
- components[i] = value;
- }
- }
- this._components = components;
- this._properties = types[this._type];
- this._alpha = alpha;
- if (this.__read)
- this.__read = read;
- },
-
- _serialize: function(options, dictionary) {
- var components = this.getComponents();
- return Base.serialize(
- /^(gray|rgb)$/.test(this._type)
- ? components
- : [this._type].concat(components),
- options, true, dictionary);
- },
-
- _changed: function() {
- this._canvasStyle = null;
- if (this._owner)
- this._owner._changed(17);
- },
-
- _convert: function(type) {
- var converter;
- return this._type === type
- ? this._components.slice()
- : (converter = converters[this._type + '-' + type])
- ? converter.apply(this, this._components)
- : converters['rgb-' + type].apply(this,
- converters[this._type + '-rgb'].apply(this,
- this._components));
- },
-
- convert: function(type) {
- return new Color(type, this._convert(type), this._alpha);
- },
-
- getType: function() {
- return this._type;
- },
-
- setType: function(type) {
- this._components = this._convert(type);
- this._properties = types[type];
- this._type = type;
- },
-
- getComponents: function() {
- var components = this._components.slice();
- if (this._alpha != null)
- components.push(this._alpha);
- return components;
- },
-
- getAlpha: function() {
- return this._alpha != null ? this._alpha : 1;
- },
-
- setAlpha: function(alpha) {
- this._alpha = alpha == null ? null : Math.min(Math.max(alpha, 0), 1);
- this._changed();
- },
-
- hasAlpha: function() {
- return this._alpha != null;
- },
-
- equals: function(color) {
- if (Base.isPlainValue(color))
- color = Color.read(arguments);
- return color === this || color && this._class === color._class
- && this._type === color._type
- && this._alpha === color._alpha
- && Base.equals(this._components, color._components)
- || false;
- },
-
- toString: function() {
- var properties = this._properties,
- parts = [],
- isGradient = this._type === 'gradient',
- f = Formatter.instance;
- for (var i = 0, l = properties.length; i < l; i++) {
- var value = this._components[i];
- if (value != null)
- parts.push(properties[i] + ': '
- + (isGradient ? value : f.number(value)));
- }
- if (this._alpha != null)
- parts.push('alpha: ' + f.number(this._alpha));
- return '{ ' + parts.join(', ') + ' }';
- },
-
- toCSS: function(hex) {
- var components = this._convert('rgb'),
- alpha = hex || this._alpha == null ? 1 : this._alpha;
- components = [
- Math.round(components[0] * 255),
- Math.round(components[1] * 255),
- Math.round(components[2] * 255)
- ];
- if (alpha < 1)
- components.push(alpha);
- return hex
- ? '#' + ((1 << 24) + (components[0] << 16)
- + (components[1] << 8)
- + components[2]).toString(16).slice(1)
- : (components.length == 4 ? 'rgba(' : 'rgb(')
- + components.join(',') + ')';
- },
-
- toCanvasStyle: function(ctx) {
- if (this._canvasStyle)
- return this._canvasStyle;
- if (this._type !== 'gradient')
- return this._canvasStyle = this.toCSS();
- var components = this._components,
- gradient = components[0],
- stops = gradient._stops,
- origin = components[1],
- destination = components[2],
- canvasGradient;
- if (gradient._radial) {
- var radius = destination.getDistance(origin),
- highlight = components[3];
- if (highlight) {
- var vector = highlight.subtract(origin);
- if (vector.getLength() > radius)
- highlight = origin.add(vector.normalize(radius - 0.1));
- }
- var start = highlight || origin;
- canvasGradient = ctx.createRadialGradient(start.x, start.y,
- 0, origin.x, origin.y, radius);
- } else {
- canvasGradient = ctx.createLinearGradient(origin.x, origin.y,
- destination.x, destination.y);
- }
- for (var i = 0, l = stops.length; i < l; i++) {
- var stop = stops[i];
- canvasGradient.addColorStop(stop._rampPoint,
- stop._color.toCanvasStyle());
- }
- return this._canvasStyle = canvasGradient;
- },
-
- transform: function(matrix) {
- if (this._type === 'gradient') {
- var components = this._components;
- for (var i = 1, l = components.length; i < l; i++) {
- var point = components[i];
- matrix._transformPoint(point, point, true);
- }
- this._changed();
- }
- },
-
- statics: {
- _types: types,
-
- random: function() {
- var random = Math.random;
- return new Color(random(), random(), random());
- }
- }
- });
-}, new function() {
- function clamp(value, hue) {
- return value < 0
- ? 0
- : hue && value > 360
- ? 360
- : !hue && value > 1
- ? 1
- : value;
- }
-
- var operators = {
- add: function(a, b, hue) {
- return clamp(a + b, hue);
- },
-
- subtract: function(a, b, hue) {
- return clamp(a - b, hue);
- },
-
- multiply: function(a, b, hue) {
- return clamp(a * b, hue);
- },
-
- divide: function(a, b, hue) {
- return clamp(a / b, hue);
- }
- };
-
- return Base.each(operators, function(operator, name) {
- var options = { dontParse: /^(multiply|divide)$/.test(name) };
-
- this[name] = function(color) {
- color = Color.read(arguments, 0, 0, options);
- var type = this._type,
- properties = this._properties,
- components1 = this._components,
- components2 = color._convert(type);
- for (var i = 0, l = components1.length; i < l; i++)
- components2[i] = operator(components1[i], components2[i],
- properties[i] === 'hue');
- return new Color(type, components2,
- this._alpha != null
- ? operator(this._alpha, color.getAlpha())
- : null);
- };
- }, {
- });
-});
-
-Base.each(Color._types, function(properties, type) {
- var ctor = this[Base.capitalize(type) + 'Color'] = function(arg) {
- var argType = arg != null && typeof arg,
- components = argType === 'object' && arg.length != null
- ? arg
- : argType === 'string'
- ? null
- : arguments;
- return components
- ? new Color(type, components)
- : new Color(arg);
- };
- if (type.length == 3) {
- var acronym = type.toUpperCase();
- Color[acronym] = this[acronym + 'Color'] = ctor;
- }
-}, Base.exports);
-
-var Gradient = Base.extend({
- _class: 'Gradient',
-
- initialize: function Gradient(stops, radial) {
- this._id = Gradient._id = (Gradient._id || 0) + 1;
- if (stops && this._set(stops))
- stops = radial = null;
- if (!this._stops)
- this.setStops(stops || ['white', 'black']);
- if (this._radial == null)
- this.setRadial(typeof radial === 'string' && radial === 'radial'
- || radial || false);
- },
-
- _serialize: function(options, dictionary) {
- return dictionary.add(this, function() {
- return Base.serialize([this._stops, this._radial],
- options, true, dictionary);
- });
- },
-
- _changed: function() {
- for (var i = 0, l = this._owners && this._owners.length; i < l; i++)
- this._owners[i]._changed();
- },
-
- _addOwner: function(color) {
- if (!this._owners)
- this._owners = [];
- this._owners.push(color);
- },
-
- _removeOwner: function(color) {
- var index = this._owners ? this._owners.indexOf(color) : -1;
- if (index != -1) {
- this._owners.splice(index, 1);
- if (this._owners.length === 0)
- delete this._owners;
- }
- },
-
- clone: function() {
- var stops = [];
- for (var i = 0, l = this._stops.length; i < l; i++)
- stops[i] = this._stops[i].clone();
- return new Gradient(stops);
- },
-
- getStops: function() {
- return this._stops;
- },
-
- setStops: function(stops) {
- if (this.stops) {
- for (var i = 0, l = this._stops.length; i < l; i++)
- delete this._stops[i]._owner;
- }
- if (stops.length < 2)
- throw new Error(
- 'Gradient stop list needs to contain at least two stops.');
- this._stops = GradientStop.readAll(stops, 0, false, true);
- for (var i = 0, l = this._stops.length; i < l; i++) {
- var stop = this._stops[i];
- stop._owner = this;
- if (stop._defaultRamp)
- stop.setRampPoint(i / (l - 1));
- }
- this._changed();
- },
-
- getRadial: function() {
- return this._radial;
- },
-
- setRadial: function(radial) {
- this._radial = radial;
- this._changed();
- },
-
- equals: function(gradient) {
- if (gradient === this)
- return true;
- if (gradient && this._class === gradient._class
- && this._stops.length === gradient._stops.length) {
- for (var i = 0, l = this._stops.length; i < l; i++) {
- if (!this._stops[i].equals(gradient._stops[i]))
- return false;
- }
- return true;
- }
- return false;
- }
-});
-
-var GradientStop = Base.extend({
- _class: 'GradientStop',
-
- initialize: function GradientStop(arg0, arg1) {
- if (arg0) {
- var color, rampPoint;
- if (arg1 === undefined && Array.isArray(arg0)) {
- color = arg0[0];
- rampPoint = arg0[1];
- } else if (arg0.color) {
- color = arg0.color;
- rampPoint = arg0.rampPoint;
- } else {
- color = arg0;
- rampPoint = arg1;
- }
- this.setColor(color);
- this.setRampPoint(rampPoint);
- }
- },
-
- clone: function() {
- return new GradientStop(this._color.clone(), this._rampPoint);
- },
-
- _serialize: function(options, dictionary) {
- return Base.serialize([this._color, this._rampPoint], options, true,
- dictionary);
- },
-
- _changed: function() {
- if (this._owner)
- this._owner._changed(17);
- },
-
- getRampPoint: function() {
- return this._rampPoint;
- },
-
- setRampPoint: function(rampPoint) {
- this._defaultRamp = rampPoint == null;
- this._rampPoint = rampPoint || 0;
- this._changed();
- },
-
- getColor: function() {
- return this._color;
- },
-
- setColor: function(color) {
- this._color = Color.read(arguments);
- if (this._color === color)
- this._color = color.clone();
- this._color._owner = this;
- this._changed();
- },
-
- equals: function(stop) {
- return stop === this || stop && this._class === stop._class
- && this._color.equals(stop._color)
- && this._rampPoint == stop._rampPoint
- || false;
- }
-});
-
-var Style = Base.extend(new function() {
- var defaults = {
- fillColor: undefined,
- strokeColor: undefined,
- strokeWidth: 1,
- strokeCap: 'butt',
- strokeJoin: 'miter',
- miterLimit: 10,
- dashOffset: 0,
- dashArray: [],
- windingRule: 'nonzero',
- shadowColor: undefined,
- shadowBlur: 0,
- shadowOffset: new Point(),
- selectedColor: undefined,
- font: 'sans-serif',
- fontSize: 12,
- leading: null,
- justification: 'left'
- };
-
- var flags = {
- strokeWidth: 25,
- strokeCap: 25,
- strokeJoin: 25,
- miterLimit: 25,
- font: 5,
- fontSize: 5,
- leading: 5,
- justification: 5
- };
-
- var item = {},
- fields = {
- _defaults: defaults,
- _textDefaults: new Base(defaults, {
- fillColor: new Color()
- })
- };
-
- Base.each(defaults, function(value, key) {
- var isColor = /Color$/.test(key),
- part = Base.capitalize(key),
- flag = flags[key],
- set = 'set' + part,
- get = 'get' + part;
-
- fields[set] = function(value) {
- var children = this._item && this._item._children;
- if (children && children.length > 0
- && this._item._type !== 'compound-path') {
- for (var i = 0, l = children.length; i < l; i++)
- children[i]._style[set](value);
- } else {
- var old = this._values[key];
- if (old != value) {
- if (isColor) {
- if (old)
- delete old._owner;
- if (value && value.constructor === Color) {
- if (value._owner)
- value = value.clone();
- value._owner = this._item;
- }
- }
- this._values[key] = value;
- if (this._item)
- this._item._changed(flag || 17);
- }
- }
- };
-
- fields[get] = function() {
- var value,
- children = this._item && this._item._children;
- if (!children || children.length === 0 || arguments[0]
- || this._item._type === 'compound-path') {
- var value = this._values[key];
- if (value === undefined) {
- value = this._defaults[key];
- if (value && value.clone)
- value = value.clone();
- this._values[key] = value;
- } else if (isColor && !(value && value.constructor === Color)) {
- this._values[key] = value = Color.read(
- [value], 0, 0, { readNull: true, clone: true });
- if (value)
- value._owner = this._item;
- }
- return value;
- }
- for (var i = 0, l = children.length; i < l; i++) {
- var childValue = children[i]._style[get]();
- if (i === 0) {
- value = childValue;
- } else if (!Base.equals(value, childValue)) {
- return undefined;
- }
- }
- return value;
- };
-
- item[get] = function() {
- return this._style[get]();
- };
-
- item[set] = function(value) {
- this._style[set](value);
- };
- });
-
- Item.inject(item);
- return fields;
-}, {
- _class: 'Style',
-
- initialize: function Style(style, _item) {
- this._values = {};
- this._item = _item;
- if (_item instanceof TextItem)
- this._defaults = this._textDefaults;
- if (style)
- this.set(style);
- },
-
- set: function(style) {
- var isStyle = style instanceof Style,
- values = isStyle ? style._values : style;
- if (values) {
- for (var key in values) {
- if (key in this._defaults) {
- var value = values[key];
- this[key] = value && isStyle && value.clone
- ? value.clone() : value;
- }
- }
- }
- },
-
- equals: function(style) {
- return style === this || style && this._class === style._class
- && Base.equals(this._values, style._values)
- || false;
- },
-
- hasFill: function() {
- return !!this.getFillColor();
- },
-
- hasStroke: function() {
- return !!this.getStrokeColor() && this.getStrokeWidth() > 0;
- },
-
- hasShadow: function() {
- return !!this.getShadowColor() && this.getShadowBlur() > 0;
- },
-
- getLeading: function getLeading() {
- var leading = getLeading.base.call(this);
- return leading != null ? leading : this.getFontSize() * 1.2;
- },
-
- getFontStyle: function() {
- var size = this.getFontSize();
- return size + (/[a-z]/i.test(size + '') ? ' ' : 'px ') + this.getFont();
- }
-
-});
-
-var DomElement = new function() {
-
- var special = /^(checked|value|selected|disabled)$/i,
- translated = { text: 'textContent', html: 'innerHTML' },
- unitless = { lineHeight: 1, zoom: 1, zIndex: 1, opacity: 1 };
-
- function create(nodes, parent) {
- var res = [];
- for (var i = 0, l = nodes && nodes.length; i < l;) {
- var el = nodes[i++];
- if (typeof el === 'string') {
- el = document.createElement(el);
- } else if (!el || !el.nodeType) {
- continue;
- }
- if (Base.isPlainObject(nodes[i]))
- DomElement.set(el, nodes[i++]);
- if (Array.isArray(nodes[i]))
- create(nodes[i++], el);
- if (parent)
- parent.appendChild(el);
- res.push(el);
- }
- return res;
- }
-
- return {
- create: function(nodes, parent) {
- var isArray = Array.isArray(nodes),
- res = create(isArray ? nodes : arguments, isArray ? parent : null);
- return res.length == 1 ? res[0] : res;
- },
-
- find: function(selector, root) {
- return (root || document).querySelector(selector);
- },
-
- findAll: function(selector, root) {
- return (root || document).querySelectorAll(selector);
- },
-
- get: function(el, key) {
- return el
- ? special.test(key)
- ? key === 'value' || typeof el[key] !== 'string'
- ? el[key]
- : true
- : key in translated
- ? el[translated[key]]
- : el.getAttribute(key)
- : null;
- },
-
- set: function(el, key, value) {
- if (typeof key !== 'string') {
- for (var name in key)
- if (key.hasOwnProperty(name))
- this.set(el, name, key[name]);
- } else if (!el || value === undefined) {
- return el;
- } else if (special.test(key)) {
- el[key] = value;
- } else if (key in translated) {
- el[translated[key]] = value;
- } else if (key === 'style') {
- this.setStyle(el, value);
- } else if (key === 'events') {
- DomEvent.add(el, value);
- } else {
- el.setAttribute(key, value);
- }
- return el;
- },
-
- getStyles: function(el) {
- var doc = el && el.nodeType !== 9 ? el.ownerDocument : el,
- view = doc && doc.defaultView;
- return view && view.getComputedStyle(el, '');
- },
-
- getStyle: function(el, key) {
- return el && el.style[key] || this.getStyles(el)[key] || null;
- },
-
- setStyle: function(el, key, value) {
- if (typeof key !== 'string') {
- for (var name in key)
- if (key.hasOwnProperty(name))
- this.setStyle(el, name, key[name]);
- } else {
- if (/^-?[\d\.]+$/.test(value) && !(key in unitless))
- value += 'px';
- el.style[key] = value;
- }
- return el;
- },
-
- hasClass: function(el, cls) {
- return new RegExp('\\s*' + cls + '\\s*').test(el.className);
- },
-
- addClass: function(el, cls) {
- el.className = (el.className + ' ' + cls).trim();
- },
-
- removeClass: function(el, cls) {
- el.className = el.className.replace(
- new RegExp('\\s*' + cls + '\\s*'), ' ').trim();
- },
-
- remove: function(el) {
- if (el.parentNode)
- el.parentNode.removeChild(el);
- },
-
- removeChildren: function(el) {
- while (el.firstChild)
- el.removeChild(el.firstChild);
- },
-
- getBounds: function(el, viewport) {
- var doc = el.ownerDocument,
- body = doc.body,
- html = doc.documentElement,
- rect;
- try {
- rect = el.getBoundingClientRect();
- } catch (e) {
- rect = { left: 0, top: 0, width: 0, height: 0 };
- }
- var x = rect.left - (html.clientLeft || body.clientLeft || 0),
- y = rect.top - (html.clientTop || body.clientTop || 0);
- if (!viewport) {
- var view = doc.defaultView;
- x += view.pageXOffset || html.scrollLeft || body.scrollLeft;
- y += view.pageYOffset || html.scrollTop || body.scrollTop;
- }
- return new Rectangle(x, y, rect.width, rect.height);
- },
-
- getViewportBounds: function(el) {
- var doc = el.ownerDocument,
- view = doc.defaultView,
- html = doc.documentElement;
- return new Rectangle(0, 0,
- view.innerWidth || html.clientWidth,
- view.innerHeight || html.clientHeight
- );
- },
-
- getOffset: function(el, viewport) {
- return this.getBounds(el, viewport).getPoint();
- },
-
- getSize: function(el) {
- return this.getBounds(el, true).getSize();
- },
-
- isInvisible: function(el) {
- return this.getSize(el).equals(new Size(0, 0));
- },
-
- isInView: function(el) {
- return !this.isInvisible(el) && this.getViewportBounds(el).intersects(
- this.getBounds(el, true));
- },
-
- getPrefixValue: function(el, name) {
- var value = el[name],
- prefixes = ['webkit', 'moz', 'ms', 'o'],
- suffix = name[0].toUpperCase() + name.substring(1);
- for (var i = 0; i < 4 && value == null; i++)
- value = el[prefixes[i] + suffix];
- return value;
- }
- };
-};
-
-var DomEvent = {
- add: function(el, events) {
- for (var type in events) {
- var func = events[type];
- if (el.addEventListener) {
- el.addEventListener(type, func, false);
- } else if (el.attachEvent) {
- el.attachEvent('on' + type, func.bound = function() {
- func.call(el, window.event);
- });
- }
- }
- },
-
- remove: function(el, events) {
- for (var type in events) {
- var func = events[type];
- if (el.removeEventListener) {
- el.removeEventListener(type, func, false);
- } else if (el.detachEvent) {
- el.detachEvent('on' + type, func.bound);
- }
- }
- },
-
- getPoint: function(event) {
- var pos = event.targetTouches
- ? event.targetTouches.length
- ? event.targetTouches[0]
- : event.changedTouches[0]
- : event;
- return new Point(
- pos.pageX || pos.clientX + document.documentElement.scrollLeft,
- pos.pageY || pos.clientY + document.documentElement.scrollTop
- );
- },
-
- getTarget: function(event) {
- return event.target || event.srcElement;
- },
-
- getOffset: function(event, target) {
- return DomEvent.getPoint(event).subtract(DomElement.getOffset(
- target || DomEvent.getTarget(event)));
- },
-
- preventDefault: function(event) {
- if (event.preventDefault) {
- event.preventDefault();
- } else {
- event.returnValue = false;
- }
- },
-
- stopPropagation: function(event) {
- if (event.stopPropagation) {
- event.stopPropagation();
- } else {
- event.cancelBubble = true;
- }
- },
-
- stop: function(event) {
- DomEvent.stopPropagation(event);
- DomEvent.preventDefault(event);
- }
-};
-
-DomEvent.requestAnimationFrame = new function() {
- var nativeRequest = DomElement.getPrefixValue(window,
- 'requestAnimationFrame'),
- requested = false,
- callbacks = [],
- focused = true,
- timer;
-
- DomEvent.add(window, {
- focus: function() {
- focused = true;
- },
- blur: function() {
- focused = false;
- }
- });
-
- function handleCallbacks() {
- for (var i = callbacks.length - 1; i >= 0; i--) {
- var entry = callbacks[i],
- func = entry[0],
- el = entry[1];
- if (!el || (PaperScope.getAttribute(el, 'keepalive') == 'true'
- || focused) && DomElement.isInView(el)) {
- callbacks.splice(i, 1);
- func();
- }
- }
- if (nativeRequest) {
- if (callbacks.length) {
- nativeRequest(handleCallbacks);
- } else {
- requested = false;
- }
- }
- }
-
- return function(callback, element) {
- callbacks.push([callback, element]);
- if (nativeRequest) {
- if (!requested) {
- nativeRequest(handleCallbacks);
- requested = true;
- }
- } else if (!timer) {
- timer = setInterval(handleCallbacks, 1000 / 60);
- }
- };
-};
-
-var View = Base.extend(Callback, {
- _class: 'View',
-
- initialize: function View(element) {
- this._scope = paper;
- this._project = paper.project;
- this._element = element;
- var size;
- this._id = element.getAttribute('id');
- if (this._id == null)
- element.setAttribute('id', this._id = 'view-' + View._id++);
- DomEvent.add(element, this._viewHandlers);
- if (PaperScope.hasAttribute(element, 'resize')) {
- var offset = DomElement.getOffset(element, true),
- that = this;
- size = DomElement.getViewportBounds(element)
- .getSize().subtract(offset);
- this._windowHandlers = {
- resize: function() {
- if (!DomElement.isInvisible(element))
- offset = DomElement.getOffset(element, true);
- that.setViewSize(DomElement.getViewportBounds(element)
- .getSize().subtract(offset));
- }
- };
- DomEvent.add(window, this._windowHandlers);
- } else {
- size = DomElement.getSize(element);
- if (size.isNaN() || size.isZero())
- size = new Size(parseInt(element.getAttribute('width'), 10),
- parseInt(element.getAttribute('height'), 10));
- }
- this._setViewSize(size);
- if (PaperScope.hasAttribute(element, 'stats')
- && typeof Stats !== 'undefined') {
- this._stats = new Stats();
- var stats = this._stats.domElement,
- style = stats.style,
- offset = DomElement.getOffset(element);
- style.position = 'absolute';
- style.left = offset.x + 'px';
- style.top = offset.y + 'px';
- document.body.appendChild(stats);
- }
- View._views.push(this);
- View._viewsById[this._id] = this;
- this._viewSize = size;
- (this._matrix = new Matrix())._owner = this;
- this._zoom = 1;
- if (!View._focused)
- View._focused = this;
- this._frameItems = {};
- this._frameItemCount = 0;
- },
-
- remove: function() {
- if (!this._project)
- return false;
- if (View._focused == this)
- View._focused = null;
- View._views.splice(View._views.indexOf(this), 1);
- delete View._viewsById[this._id];
- if (this._project.view == this)
- this._project.view = null;
- DomEvent.remove(this._element, this._viewHandlers);
- DomEvent.remove(window, this._windowHandlers);
- this._element = this._project = null;
- this.detach('frame');
- this._frameItems = {};
- return true;
- },
-
- _events: {
- onFrame: {
- install: function() {
- this._animate = true;
- if (!this._requested)
- this._requestFrame();
- },
-
- uninstall: function() {
- this._animate = false;
- }
- },
-
- onResize: {}
- },
-
- _animate: false,
- _time: 0,
- _count: 0,
-
- _requestFrame: function() {
- var that = this;
- DomEvent.requestAnimationFrame(function() {
- that._requested = false;
- if (!that._animate)
- return;
- that._requestFrame();
- that._handleFrame();
- }, this._element);
- this._requested = true;
- },
-
- _handleFrame: function() {
- paper = this._scope;
- var now = Date.now() / 1000,
- delta = this._before ? now - this._before : 0;
- this._before = now;
- this._handlingFrame = true;
- this.fire('frame', new Base({
- delta: delta,
- time: this._time += delta,
- count: this._count++
- }));
- if (this._stats)
- this._stats.update();
- this._handlingFrame = false;
- this.draw(true);
- },
-
- _animateItem: function(item, animate) {
- var items = this._frameItems;
- if (animate) {
- items[item._id] = {
- item: item,
- time: 0,
- count: 0
- };
- if (++this._frameItemCount === 1)
- this.attach('frame', this._handleFrameItems);
- } else {
- delete items[item._id];
- if (--this._frameItemCount === 0) {
- this.detach('frame', this._handleFrameItems);
- }
- }
- },
-
- _handleFrameItems: function(event) {
- for (var i in this._frameItems) {
- var entry = this._frameItems[i];
- entry.item.fire('frame', new Base(event, {
- time: entry.time += event.delta,
- count: entry.count++
- }));
- }
- },
-
- _redraw: function() {
- this._project._needsRedraw = true;
- if (this._handlingFrame)
- return;
- if (this._animate) {
- this._handleFrame();
- } else {
- this.draw();
- }
- },
-
- _changed: function(flags) {
- if (flags & 1)
- this._project._needsRedraw = true;
- },
-
- _transform: function(matrix) {
- this._matrix.concatenate(matrix);
- this._bounds = null;
- this._redraw();
- },
-
- getElement: function() {
- return this._element;
- },
-
- getViewSize: function() {
- var size = this._viewSize;
- return new LinkedSize(size.width, size.height, this, 'setViewSize');
- },
-
- setViewSize: function(size) {
- size = Size.read(arguments);
- var delta = size.subtract(this._viewSize);
- if (delta.isZero())
- return;
- this._viewSize.set(size.width, size.height);
- this._setViewSize(size);
- this._bounds = null;
- this.fire('resize', {
- size: size,
- delta: delta
- });
- this._redraw();
- },
-
- _setViewSize: function(size) {
- var element = this._element;
- element.width = size.width;
- element.height = size.height;
- },
-
- getBounds: function() {
- if (!this._bounds)
- this._bounds = this._matrix.inverted()._transformBounds(
- new Rectangle(new Point(), this._viewSize));
- return this._bounds;
- },
-
- getSize: function() {
- return this.getBounds().getSize(arguments[0]);
- },
-
- getCenter: function() {
- return this.getBounds().getCenter(arguments[0]);
- },
-
- setCenter: function(center) {
- center = Point.read(arguments);
- this.scrollBy(center.subtract(this.getCenter()));
- },
-
- getZoom: function() {
- return this._zoom;
- },
-
- setZoom: function(zoom) {
- this._transform(new Matrix().scale(zoom / this._zoom,
- this.getCenter()));
- this._zoom = zoom;
- },
-
- isVisible: function() {
- return DomElement.isInView(this._element);
- },
-
- scrollBy: function() {
- this._transform(new Matrix().translate(Point.read(arguments).negate()));
- },
-
- projectToView: function() {
- return this._matrix._transformPoint(Point.read(arguments));
- },
-
- viewToProject: function() {
- return this._matrix._inverseTransform(Point.read(arguments));
- },
-
-}, {
- statics: {
- _views: [],
- _viewsById: {},
- _id: 0,
-
- create: function(element) {
- if (typeof element === 'string')
- element = document.getElementById(element);
- return new CanvasView(element);
- }
- }
-}, new function() {
- var tool,
- prevFocus,
- tempFocus,
- dragging = false;
-
- function getView(event) {
- var target = DomEvent.getTarget(event);
- return target.getAttribute && View._viewsById[target.getAttribute('id')];
- }
-
- function viewToProject(view, event) {
- return view.viewToProject(DomEvent.getOffset(event, view._element));
- }
-
- function updateFocus() {
- if (!View._focused || !View._focused.isVisible()) {
- for (var i = 0, l = View._views.length; i < l; i++) {
- var view = View._views[i];
- if (view && view.isVisible()) {
- View._focused = tempFocus = view;
- break;
- }
- }
- }
- }
-
- function mousedown(event) {
- var view = View._focused = getView(event),
- point = viewToProject(view, event);
- dragging = true;
- if (view._onMouseDown)
- view._onMouseDown(event, point);
- if (tool = view._scope._tool)
- tool._onHandleEvent('mousedown', point, event);
- view.draw(true);
- }
-
- function mousemove(event) {
- var view;
- if (!dragging) {
- view = getView(event);
- if (view) {
- prevFocus = View._focused;
- View._focused = tempFocus = view;
- } else if (tempFocus && tempFocus == View._focused) {
- View._focused = prevFocus;
- updateFocus();
- }
- }
- if (!(view = view || View._focused))
- return;
- var point = event && viewToProject(view, event);
- if (view._onMouseMove)
- view._onMouseMove(event, point);
- if (tool = view._scope._tool) {
- if (tool._onHandleEvent(dragging && tool.responds('mousedrag')
- ? 'mousedrag' : 'mousemove', point, event))
- DomEvent.stop(event);
- }
- view.draw(true);
- }
-
- function mouseup(event) {
- var view = View._focused;
- if (!view || !dragging)
- return;
- var point = viewToProject(view, event);
- curPoint = null;
- dragging = false;
- if (view._onMouseUp)
- view._onMouseUp(event, point);
- if (tool && tool._onHandleEvent('mouseup', point, event))
- DomEvent.stop(event);
- view.draw(true);
- }
-
- function selectstart(event) {
- if (dragging)
- DomEvent.stop(event);
- }
-
- DomEvent.add(document, {
- mousemove: mousemove,
- mouseup: mouseup,
- touchmove: mousemove,
- touchend: mouseup,
- selectstart: selectstart,
- scroll: updateFocus
- });
-
- DomEvent.add(window, {
- load: updateFocus
- });
-
- return {
- _viewHandlers: {
- mousedown: mousedown,
- touchstart: mousedown,
- selectstart: selectstart
- },
-
- statics: {
- updateFocus: updateFocus
- }
- };
-});
-
-var CanvasView = View.extend({
- _class: 'CanvasView',
-
- initialize: function CanvasView(canvas) {
- if (!(canvas instanceof HTMLCanvasElement)) {
- var size = Size.read(arguments);
- if (size.isZero())
- throw new Error(
- 'Cannot create CanvasView with the provided argument: '
- + canvas);
- canvas = CanvasProvider.getCanvas(size);
- }
- this._context = canvas.getContext('2d');
- this._eventCounters = {};
- this._ratio = 1;
- if (PaperScope.getAttribute(canvas, 'hidpi') !== 'off') {
- var deviceRatio = window.devicePixelRatio || 1,
- backingStoreRatio = DomElement.getPrefixValue(this._context,
- 'backingStorePixelRatio') || 1;
- this._ratio = deviceRatio / backingStoreRatio;
- }
- View.call(this, canvas);
- },
-
- _setViewSize: function(size) {
- var width = size.width,
- height = size.height,
- ratio = this._ratio,
- element = this._element,
- style = element.style;
- element.width = width * ratio;
- element.height = height * ratio;
- if (ratio !== 1) {
- style.width = width + 'px';
- style.height = height + 'px';
- this._context.scale(ratio, ratio);
- }
- },
-
- draw: function(checkRedraw) {
- if (checkRedraw && !this._project._needsRedraw)
- return false;
- var ctx = this._context,
- size = this._viewSize;
- ctx.clearRect(0, 0, size.width + 1, size.height + 1);
- this._project.draw(ctx, this._matrix, this._ratio);
- this._project._needsRedraw = false;
- return true;
- }
-}, new function() {
-
- var downPoint,
- lastPoint,
- overPoint,
- downItem,
- lastItem,
- overItem,
- hasDrag,
- doubleClick,
- clickTime;
-
- function callEvent(type, event, point, target, lastPoint, bubble) {
- var item = target,
- mouseEvent;
- while (item) {
- if (item.responds(type)) {
- if (!mouseEvent)
- mouseEvent = new MouseEvent(type, event, point, target,
- lastPoint ? point.subtract(lastPoint) : null);
- if (item.fire(type, mouseEvent)
- && (!bubble || mouseEvent._stopped))
- return false;
- }
- item = item.getParent();
- }
- return true;
- }
-
- function handleEvent(view, type, event, point, lastPoint) {
- if (view._eventCounters[type]) {
- var project = view._project,
- hit = project.hitTest(point, {
- tolerance: project.options.hitTolerance || 0,
- fill: true,
- stroke: true
- }),
- item = hit && hit.item;
- if (item) {
- if (type === 'mousemove' && item != overItem)
- lastPoint = point;
- if (type !== 'mousemove' || !hasDrag)
- callEvent(type, event, point, item, lastPoint);
- return item;
- }
- }
- }
-
- return {
- _onMouseDown: function(event, point) {
- var item = handleEvent(this, 'mousedown', event, point);
- doubleClick = lastItem == item && (Date.now() - clickTime < 300);
- downItem = lastItem = item;
- downPoint = lastPoint = overPoint = point;
- hasDrag = downItem && downItem.responds('mousedrag');
- },
-
- _onMouseUp: function(event, point) {
- var item = handleEvent(this, 'mouseup', event, point);
- if (hasDrag) {
- if (lastPoint && !lastPoint.equals(point))
- callEvent('mousedrag', event, point, downItem, lastPoint);
- if (item != downItem) {
- overPoint = point;
- callEvent('mousemove', event, point, item, overPoint);
- }
- }
- if (item === downItem) {
- clickTime = Date.now();
- if (!doubleClick
- || callEvent('doubleclick', event, downPoint, item))
- callEvent('click', event, downPoint, item);
- doubleClick = false;
- }
- downItem = null;
- hasDrag = false;
- },
-
- _onMouseMove: function(event, point) {
- if (downItem)
- callEvent('mousedrag', event, point, downItem, lastPoint);
- var item = handleEvent(this, 'mousemove', event, point, overPoint);
- lastPoint = overPoint = point;
- if (item !== overItem) {
- callEvent('mouseleave', event, point, overItem);
- overItem = item;
- callEvent('mouseenter', event, point, item);
- }
- }
- };
-});
-
-var Event = Base.extend({
- _class: 'Event',
-
- initialize: function Event(event) {
- this.event = event;
- },
-
- preventDefault: function() {
- this._prevented = true;
- DomEvent.preventDefault(this.event);
- },
-
- stopPropagation: function() {
- this._stopped = true;
- DomEvent.stopPropagation(this.event);
- },
-
- stop: function() {
- this.stopPropagation();
- this.preventDefault();
- },
-
- getModifiers: function() {
- return Key.modifiers;
- }
-});
-
-var KeyEvent = Event.extend({
- _class: 'KeyEvent',
-
- initialize: function KeyEvent(down, key, character, event) {
- Event.call(this, event);
- this.type = down ? 'keydown' : 'keyup';
- this.key = key;
- this.character = character;
- },
-
- toString: function() {
- return "{ type: '" + this.type
- + "', key: '" + this.key
- + "', character: '" + this.character
- + "', modifiers: " + this.getModifiers()
- + " }";
- }
-});
-
-var Key = new function() {
-
- var specialKeys = {
- 8: 'backspace',
- 9: 'tab',
- 13: 'enter',
- 16: 'shift',
- 17: 'control',
- 18: 'option',
- 19: 'pause',
- 20: 'caps-lock',
- 27: 'escape',
- 32: 'space',
- 35: 'end',
- 36: 'home',
- 37: 'left',
- 38: 'up',
- 39: 'right',
- 40: 'down',
- 46: 'delete',
- 91: 'command',
- 93: 'command',
- 224: 'command'
- },
-
- specialChars = {
- 9: true,
- 13: true,
- 32: true
- },
-
- modifiers = new Base({
- shift: false,
- control: false,
- option: false,
- command: false,
- capsLock: false,
- space: false
- }),
-
- charCodeMap = {},
- keyMap = {},
- downCode;
-
- function handleKey(down, keyCode, charCode, event) {
- var character = charCode ? String.fromCharCode(charCode) : '',
- specialKey = specialKeys[keyCode],
- key = specialKey || character.toLowerCase(),
- type = down ? 'keydown' : 'keyup',
- view = View._focused,
- scope = view && view.isVisible() && view._scope,
- tool = scope && scope._tool,
- name;
- keyMap[key] = down;
- if (specialKey && (name = Base.camelize(specialKey)) in modifiers)
- modifiers[name] = down;
- if (down) {
- charCodeMap[keyCode] = charCode;
- } else {
- delete charCodeMap[keyCode];
- }
- if (tool && tool.responds(type)) {
- paper = scope;
- tool.fire(type, new KeyEvent(down, key, character, event));
- if (view)
- view.draw(true);
- }
- }
-
- DomEvent.add(document, {
- keydown: function(event) {
- var code = event.which || event.keyCode;
- if (code in specialKeys) {
- handleKey(true, code, code in specialChars ? code : 0, event);
- } else {
- downCode = code;
- }
- },
-
- keypress: function(event) {
- if (downCode != null) {
- handleKey(true, downCode, event.which || event.keyCode, event);
- downCode = null;
- }
- },
-
- keyup: function(event) {
- var code = event.which || event.keyCode;
- if (code in charCodeMap)
- handleKey(false, code, charCodeMap[code], event);
- }
- });
-
- DomEvent.add(window, {
- blur: function(event) {
- for (var code in charCodeMap)
- handleKey(false, code, charCodeMap[code], event);
- }
- });
-
- return {
- modifiers: modifiers,
-
- isDown: function(key) {
- return !!keyMap[key];
- }
- };
-};
-
-var MouseEvent = Event.extend({
- _class: 'MouseEvent',
-
- initialize: function MouseEvent(type, event, point, target, delta) {
- Event.call(this, event);
- this.type = type;
- this.point = point;
- this.target = target;
- this.delta = delta;
- },
-
- toString: function() {
- return "{ type: '" + this.type
- + "', point: " + this.point
- + ', target: ' + this.target
- + (this.delta ? ', delta: ' + this.delta : '')
- + ', modifiers: ' + this.getModifiers()
- + ' }';
- }
-});
-
- Base.extend(Callback, {
- _class: 'Palette',
- _events: [ 'onChange' ],
-
- initialize: function Palette(title, components, values) {
- var parent = DomElement.find('.palettejs-panel')
- || DomElement.find('body').appendChild(
- DomElement.create('div', { 'class': 'palettejs-panel' }));
- this._element = parent.appendChild(
- DomElement.create('table', { 'class': 'palettejs-pane' }));
- this._title = title;
- if (!values)
- values = {};
- for (var name in (this.components = components)) {
- var component = components[name];
- if (!(component instanceof Component)) {
- if (component.value == null)
- component.value = values[name];
- component.name = name;
- component = components[name] = new Component(component);
- }
- this._element.appendChild(component._element);
- component._palette = this;
- if (values[name] === undefined)
- values[name] = component.value;
- }
- this.values = Base.each(values, function(value, name) {
- var component = components[name];
- if (component) {
- Base.define(values, name, {
- enumerable: true,
- configurable: true,
- get: function() {
- return component._value;
- },
- set: function(val) {
- component.setValue(val);
- }
- });
- }
- });
- if (window.paper)
- paper.palettes.push(this);
- },
-
- reset: function() {
- for (var i in this.components)
- this.components[i].reset();
- },
-
- remove: function() {
- DomElement.remove(this._element);
- }
-});
-
-var Component = Base.extend(Callback, {
- _class: 'Component',
- _events: [ 'onChange', 'onClick' ],
-
- _types: {
- 'boolean': {
- type: 'checkbox',
- value: 'checked'
- },
-
- string: {
- type: 'text'
- },
-
- number: {
- type: 'number',
- number: true
- },
-
- button: {
- type: 'button'
- },
-
- text: {
- tag: 'div',
- value: 'text'
- },
-
- slider: {
- type: 'range',
- number: true
- },
-
- list: {
- tag: 'select',
-
- setOptions: function() {
- DomElement.removeChildren(this._input);
- DomElement.create(Base.each(this._options, function(option) {
- this.push('option', { value: option, text: option });
- }, []), this._input);
- }
- },
-
- color: {
- type: 'color',
-
- getValue: function(value) {
- return new Color(value);
- },
-
- setValue: function(value) {
- return new Color(value).toCSS(
- DomElement.get(this._input, 'type') === 'color');
- }
- }
- },
-
- initialize: function Component(obj) {
- this._id = Component._id = (Component._id || 0) + 1;
- this._type = obj.type in this._types
- ? obj.type
- : 'options' in obj
- ? 'list'
- : 'onClick' in obj
- ? 'button'
- : typeof obj.value;
- this._meta = this._types[this._type] || { type: this._type };
- var that = this,
- id = 'component-' + this._id;
- this._dontFire = true;
- this._input = DomElement.create(this._meta.tag || 'input', {
- id: id,
- type: this._meta.type,
- events: {
- change: function() {
- that.setValue(
- DomElement.get(this, that._meta.value || 'value'));
- },
- click: function() {
- that.fire('click');
- }
- }
- });
- this.attach('change', function(value) {
- if (!this._dontFire)
- this._palette.fire('change', this, this.name, value);
- });
- this._element = DomElement.create('tr', [
- 'td', [this._label = DomElement.create('label', { 'for': id })],
- 'td', [this._input]
- ]);
- Base.each(obj, function(value, key) {
- this[key] = value;
- }, this);
- this._defaultValue = this._value;
- this._dontFire = false;
- },
-
- getType: function() {
- return this._type;
- },
-
- getLabel: function() {
- return this.__label;
- },
-
- setLabel: function(label) {
- this.__label = label;
- DomElement.set(this._label, 'text', label + ':');
- },
-
- getOptions: function() {
- return this._options;
- },
-
- setOptions: function(options) {
- this._options = options;
- var setOptions = this._meta.setOptions;
- if (setOptions)
- setOptions.call(this);
- },
-
- getValue: function() {
- var value = this._value,
- getValue = this._meta.getValue;
- return getValue ? getValue.call(this, value) : value;
- },
-
- setValue: function(value) {
- var key = this._meta.value || 'value',
- setValue = this._meta.setValue;
- if (setValue)
- value = setValue.call(this, value);
- DomElement.set(this._input, key, value);
- value = DomElement.get(this._input, key);
- if (this._meta.number)
- value = parseFloat(value, 10);
- if (this._value !== value) {
- this._value = value;
- if (!this._dontFire)
- this.fire('change', this.getValue());
- }
- },
-
- getRange: function() {
- return [parseFloat(DomElement.get(this._input, 'min')),
- parseFloat(DomElement.get(this._input, 'max'))];
- },
-
- setRange: function(min, max) {
- var range = Array.isArray(min) ? min : [min, max];
- DomElement.set(this._input, { min: range[0], max: range[1] });
- },
-
- getMin: function() {
- return this.getRange()[0];
- },
-
- setMin: function(min) {
- this.setRange(min, this.getMax());
- },
-
- getMax: function() {
- return this.getRange()[1];
- },
-
- setMax: function(max) {
- this.setRange(this.getMin(), max);
- },
-
- getStep: function() {
- return parseFloat(DomElement.get(this._input, 'step'));
- },
-
- setStep: function(step) {
- DomElement.set(this._input, 'step', step);
- },
-
- reset: function() {
- this.setValue(this._defaultValue);
- }
-});
-
-var ToolEvent = Event.extend({
- _class: 'ToolEvent',
- _item: null,
-
- initialize: function ToolEvent(tool, type, event) {
- this.tool = tool;
- this.type = type;
- this.event = event;
- },
-
- _choosePoint: function(point, toolPoint) {
- return point ? point : toolPoint ? toolPoint.clone() : null;
- },
-
- getPoint: function() {
- return this._choosePoint(this._point, this.tool._point);
- },
-
- setPoint: function(point) {
- this._point = point;
- },
-
- getLastPoint: function() {
- return this._choosePoint(this._lastPoint, this.tool._lastPoint);
- },
-
- setLastPoint: function(lastPoint) {
- this._lastPoint = lastPoint;
- },
-
- getDownPoint: function() {
- return this._choosePoint(this._downPoint, this.tool._downPoint);
- },
-
- setDownPoint: function(downPoint) {
- this._downPoint = downPoint;
- },
-
- getMiddlePoint: function() {
- if (!this._middlePoint && this.tool._lastPoint) {
- return this.tool._point.add(this.tool._lastPoint).divide(2);
- }
- return this._middlePoint;
- },
-
- setMiddlePoint: function(middlePoint) {
- this._middlePoint = middlePoint;
- },
-
- getDelta: function() {
- return !this._delta && this.tool._lastPoint
- ? this.tool._point.subtract(this.tool._lastPoint)
- : this._delta;
- },
-
- setDelta: function(delta) {
- this._delta = delta;
- },
-
- getCount: function() {
- return /^mouse(down|up)$/.test(this.type)
- ? this.tool._downCount
- : this.tool._count;
- },
-
- setCount: function(count) {
- this.tool[/^mouse(down|up)$/.test(this.type) ? 'downCount' : 'count']
- = count;
- },
-
- getItem: function() {
- if (!this._item) {
- var result = this.tool._scope.project.hitTest(this.getPoint());
- if (result) {
- var item = result.item,
- parent = item._parent;
- while (/^(group|compound-path)$/.test(parent._type)) {
- item = parent;
- parent = parent._parent;
- }
- this._item = item;
- }
- }
- return this._item;
- },
- setItem: function(item) {
- this._item = item;
- },
-
- toString: function() {
- return '{ type: ' + this.type
- + ', point: ' + this.getPoint()
- + ', count: ' + this.getCount()
- + ', modifiers: ' + this.getModifiers()
- + ' }';
- }
-});
-
-var Tool = PaperScopeItem.extend({
- _class: 'Tool',
- _list: 'tools',
- _reference: '_tool',
- _events: [ 'onActivate', 'onDeactivate', 'onEditOptions',
- 'onMouseDown', 'onMouseUp', 'onMouseDrag', 'onMouseMove',
- 'onKeyDown', 'onKeyUp' ],
-
- initialize: function Tool(props) {
- PaperScopeItem.call(this);
- this._firstMove = true;
- this._count = 0;
- this._downCount = 0;
- this._set(props);
- },
-
- getMinDistance: function() {
- return this._minDistance;
- },
-
- setMinDistance: function(minDistance) {
- this._minDistance = minDistance;
- if (this._minDistance != null && this._maxDistance != null
- && this._minDistance > this._maxDistance) {
- this._maxDistance = this._minDistance;
- }
- },
-
- getMaxDistance: function() {
- return this._maxDistance;
- },
-
- setMaxDistance: function(maxDistance) {
- this._maxDistance = maxDistance;
- if (this._minDistance != null && this._maxDistance != null
- && this._maxDistance < this._minDistance) {
- this._minDistance = maxDistance;
- }
- },
-
- getFixedDistance: function() {
- return this._minDistance == this._maxDistance
- ? this._minDistance : null;
- },
-
- setFixedDistance: function(distance) {
- this._minDistance = distance;
- this._maxDistance = distance;
- },
-
- _updateEvent: function(type, point, minDistance, maxDistance, start,
- needsChange, matchMaxDistance) {
- if (!start) {
- if (minDistance != null || maxDistance != null) {
- var minDist = minDistance != null ? minDistance : 0,
- vector = point.subtract(this._point),
- distance = vector.getLength();
- if (distance < minDist)
- return false;
- var maxDist = maxDistance != null ? maxDistance : 0;
- if (maxDist != 0) {
- if (distance > maxDist) {
- point = this._point.add(vector.normalize(maxDist));
- } else if (matchMaxDistance) {
- return false;
- }
- }
- }
- if (needsChange && point.equals(this._point))
- return false;
- }
- this._lastPoint = start && type == 'mousemove' ? point : this._point;
- this._point = point;
- switch (type) {
- case 'mousedown':
- this._lastPoint = this._downPoint;
- this._downPoint = this._point;
- this._downCount++;
- break;
- case 'mouseup':
- this._lastPoint = this._downPoint;
- break;
- }
- this._count = start ? 0 : this._count + 1;
- return true;
- },
-
- _fireEvent: function(type, event) {
- var sets = paper.project._removeSets;
- if (sets) {
- if (type === 'mouseup')
- sets.mousedrag = null;
- var set = sets[type];
- if (set) {
- for (var id in set) {
- var item = set[id];
- for (var key in sets) {
- var other = sets[key];
- if (other && other != set)
- delete other[item._id];
- }
- item.remove();
- }
- sets[type] = null;
- }
- }
- return this.responds(type)
- && this.fire(type, new ToolEvent(this, type, event));
- },
-
- _onHandleEvent: function(type, point, event) {
- paper = this._scope;
- var called = false;
- switch (type) {
- case 'mousedown':
- this._updateEvent(type, point, null, null, true, false, false);
- called = this._fireEvent(type, event);
- break;
- case 'mousedrag':
- var needsChange = false,
- matchMaxDistance = false;
- while (this._updateEvent(type, point, this.minDistance,
- this.maxDistance, false, needsChange, matchMaxDistance)) {
- called = this._fireEvent(type, event) || called;
- needsChange = true;
- matchMaxDistance = true;
- }
- break;
- case 'mouseup':
- if (!point.equals(this._point)
- && this._updateEvent('mousedrag', point, this.minDistance,
- this.maxDistance, false, false, false)) {
- called = this._fireEvent('mousedrag', event);
- }
- this._updateEvent(type, point, null, this.maxDistance, false,
- false, false);
- called = this._fireEvent(type, event) || called;
- this._updateEvent(type, point, null, null, true, false, false);
- this._firstMove = true;
- break;
- case 'mousemove':
- while (this._updateEvent(type, point, this.minDistance,
- this.maxDistance, this._firstMove, true, false)) {
- called = this._fireEvent(type, event) || called;
- this._firstMove = false;
- }
- break;
- }
- return called;
- }
-
-});
-
-var Http = {
- request: function(method, url, callback) {
- var xhr = new (window.ActiveXObject || XMLHttpRequest)(
- 'Microsoft.XMLHTTP');
- xhr.open(method.toUpperCase(), url, true);
- if ('overrideMimeType' in xhr)
- xhr.overrideMimeType('text/plain');
- xhr.onreadystatechange = function() {
- if (xhr.readyState === 4) {
- var status = xhr.status;
- if (status === 0 || status === 200) {
- callback.call(xhr, xhr.responseText);
- } else {
- throw new Error('Could not load ' + url + ' (Error '
- + status + ')');
- }
- }
- };
- return xhr.send(null);
- }
-};
-
-var CanvasProvider = {
- canvases: [],
-
- getCanvas: function(width, height, ratio) {
- var canvas,
- init = true;
- if (typeof width === 'object') {
- ratio = height;
- height = width.height;
- width = width.width;
- }
- if (!ratio) {
- ratio = 1;
- } else if (ratio !== 1) {
- width *= ratio;
- height *= ratio;
- }
- if (this.canvases.length) {
- canvas = this.canvases.pop();
- } else {
- canvas = document.createElement('canvas');
- }
- var ctx = canvas.getContext('2d');
- if (canvas.width === width && canvas.height === height) {
- if (init)
- ctx.clearRect(0, 0, width + 1, height + 1);
- } else {
- canvas.width = width;
- canvas.height = height;
- }
- ctx.save();
- if (ratio !== 1)
- ctx.scale(ratio, ratio);
- return canvas;
- },
-
- getContext: function(width, height) {
- return this.getCanvas(width, height).getContext('2d');
- },
-
- release: function(obj) {
- var canvas = obj.canvas ? obj.canvas : obj;
- canvas.getContext('2d').restore();
- this.canvases.push(canvas);
- }
-};
-
-var BlendMode = new function() {
- var min = Math.min,
- max = Math.max,
- abs = Math.abs,
- sr, sg, sb, sa,
- br, bg, bb, ba,
- dr, dg, db;
-
- function getLum(r, g, b) {
- return 0.2989 * r + 0.587 * g + 0.114 * b;
- }
-
- function setLum(r, g, b, l) {
- var d = l - getLum(r, g, b);
- dr = r + d;
- dg = g + d;
- db = b + d;
- var l = getLum(dr, dg, db),
- mn = min(dr, dg, db),
- mx = max(dr, dg, db);
- if (mn < 0) {
- var lmn = l - mn;
- dr = l + (dr - l) * l / lmn;
- dg = l + (dg - l) * l / lmn;
- db = l + (db - l) * l / lmn;
- }
- if (mx > 255) {
- var ln = 255 - l,
- mxl = mx - l;
- dr = l + (dr - l) * ln / mxl;
- dg = l + (dg - l) * ln / mxl;
- db = l + (db - l) * ln / mxl;
- }
- }
-
- function getSat(r, g, b) {
- return max(r, g, b) - min(r, g, b);
- }
-
- function setSat(r, g, b, s) {
- var col = [r, g, b],
- mx = max(r, g, b),
- mn = min(r, g, b),
- md;
- mn = mn === r ? 0 : mn === g ? 1 : 2;
- mx = mx === r ? 0 : mx === g ? 1 : 2;
- md = min(mn, mx) === 0 ? max(mn, mx) === 1 ? 2 : 1 : 0;
- if (col[mx] > col[mn]) {
- col[md] = (col[md] - col[mn]) * s / (col[mx] - col[mn]);
- col[mx] = s;
- } else {
- col[md] = col[mx] = 0;
- }
- col[mn] = 0;
- dr = col[0];
- dg = col[1];
- db = col[2];
- }
-
- var modes = {
- multiply: function() {
- dr = br * sr / 255;
- dg = bg * sg / 255;
- db = bb * sb / 255;
- },
-
- screen: function() {
- dr = br + sr - (br * sr / 255);
- dg = bg + sg - (bg * sg / 255);
- db = bb + sb - (bb * sb / 255);
- },
-
- overlay: function() {
- dr = br < 128 ? 2 * br * sr / 255 : 255 - 2 * (255 - br) * (255 - sr) / 255;
- dg = bg < 128 ? 2 * bg * sg / 255 : 255 - 2 * (255 - bg) * (255 - sg) / 255;
- db = bb < 128 ? 2 * bb * sb / 255 : 255 - 2 * (255 - bb) * (255 - sb) / 255;
- },
-
- 'soft-light': function() {
- var t = sr * br / 255;
- dr = t + br * (255 - (255 - br) * (255 - sr) / 255 - t) / 255;
- t = sg * bg / 255;
- dg = t + bg * (255 - (255 - bg) * (255 - sg) / 255 - t) / 255;
- t = sb * bb / 255;
- db = t + bb * (255 - (255 - bb) * (255 - sb) / 255 - t) / 255;
- },
-
- 'hard-light': function() {
- dr = sr < 128 ? 2 * sr * br / 255 : 255 - 2 * (255 - sr) * (255 - br) / 255;
- dg = sg < 128 ? 2 * sg * bg / 255 : 255 - 2 * (255 - sg) * (255 - bg) / 255;
- db = sb < 128 ? 2 * sb * bb / 255 : 255 - 2 * (255 - sb) * (255 - bb) / 255;
- },
-
- 'color-dodge': function() {
- dr = br === 0 ? 0 : sr === 255 ? 255 : min(255, 255 * br / (255 - sr));
- dg = bg === 0 ? 0 : sg === 255 ? 255 : min(255, 255 * bg / (255 - sg));
- db = bb === 0 ? 0 : sb === 255 ? 255 : min(255, 255 * bb / (255 - sb));
- },
-
- 'color-burn': function() {
- dr = br === 255 ? 255 : sr === 0 ? 0 : max(0, 255 - (255 - br) * 255 / sr);
- dg = bg === 255 ? 255 : sg === 0 ? 0 : max(0, 255 - (255 - bg) * 255 / sg);
- db = bb === 255 ? 255 : sb === 0 ? 0 : max(0, 255 - (255 - bb) * 255 / sb);
- },
-
- darken: function() {
- dr = br < sr ? br : sr;
- dg = bg < sg ? bg : sg;
- db = bb < sb ? bb : sb;
- },
-
- lighten: function() {
- dr = br > sr ? br : sr;
- dg = bg > sg ? bg : sg;
- db = bb > sb ? bb : sb;
- },
-
- difference: function() {
- dr = br - sr;
- if (dr < 0)
- dr = -dr;
- dg = bg - sg;
- if (dg < 0)
- dg = -dg;
- db = bb - sb;
- if (db < 0)
- db = -db;
- },
-
- exclusion: function() {
- dr = br + sr * (255 - br - br) / 255;
- dg = bg + sg * (255 - bg - bg) / 255;
- db = bb + sb * (255 - bb - bb) / 255;
- },
-
- hue: function() {
- setSat(sr, sg, sb, getSat(br, bg, bb));
- setLum(dr, dg, db, getLum(br, bg, bb));
- },
-
- saturation: function() {
- setSat(br, bg, bb, getSat(sr, sg, sb));
- setLum(dr, dg, db, getLum(br, bg, bb));
- },
-
- luminosity: function() {
- setLum(br, bg, bb, getLum(sr, sg, sb));
- },
-
- color: function() {
- setLum(sr, sg, sb, getLum(br, bg, bb));
- },
-
- add: function() {
- dr = min(br + sr, 255);
- dg = min(bg + sg, 255);
- db = min(bb + sb, 255);
- },
-
- subtract: function() {
- dr = max(br - sr, 0);
- dg = max(bg - sg, 0);
- db = max(bb - sb, 0);
- },
-
- average: function() {
- dr = (br + sr) / 2;
- dg = (bg + sg) / 2;
- db = (bb + sb) / 2;
- },
-
- negation: function() {
- dr = 255 - abs(255 - sr - br);
- dg = 255 - abs(255 - sg - bg);
- db = 255 - abs(255 - sb - bb);
- }
- };
-
- var nativeModes = this.nativeModes = Base.each([
- 'source-over', 'source-in', 'source-out', 'source-atop',
- 'destination-over', 'destination-in', 'destination-out',
- 'destination-atop', 'lighter', 'darker', 'copy', 'xor'
- ], function(mode) {
- this[mode] = true;
- }, {});
-
- var ctx = CanvasProvider.getContext(1, 1);
- Base.each(modes, function(func, mode) {
- ctx.save();
- var darken = mode === 'darken',
- ok = false;
- ctx.fillStyle = darken ? '#300' : '#a00';
- ctx.fillRect(0, 0, 1, 1);
- ctx.globalCompositeOperation = mode;
- if (ctx.globalCompositeOperation === mode) {
- ctx.fillStyle = darken ? '#a00' : '#300';
- ctx.fillRect(0, 0, 1, 1);
- ok = ctx.getImageData(0, 0, 1, 1).data[0] !== (darken ? 170 : 51);
- }
- nativeModes[mode] = ok;
- ctx.restore();
- });
- CanvasProvider.release(ctx);
-
- this.process = function(mode, srcContext, dstContext, alpha, offset) {
- var srcCanvas = srcContext.canvas,
- normal = mode === 'normal';
- if (normal || nativeModes[mode]) {
- dstContext.save();
- dstContext.setTransform(1, 0, 0, 1, 0, 0);
- dstContext.globalAlpha = alpha;
- if (!normal)
- dstContext.globalCompositeOperation = mode;
- dstContext.drawImage(srcCanvas, offset.x, offset.y);
- dstContext.restore();
- } else {
- var process = modes[mode];
- if (!process)
- return;
- var dstData = dstContext.getImageData(offset.x, offset.y,
- srcCanvas.width, srcCanvas.height),
- dst = dstData.data,
- src = srcContext.getImageData(0, 0,
- srcCanvas.width, srcCanvas.height).data;
- for (var i = 0, l = dst.length; i < l; i += 4) {
- sr = src[i];
- br = dst[i];
- sg = src[i + 1];
- bg = dst[i + 1];
- sb = src[i + 2];
- bb = dst[i + 2];
- sa = src[i + 3];
- ba = dst[i + 3];
- process();
- var a1 = sa * alpha / 255,
- a2 = 1 - a1;
- dst[i] = a1 * dr + a2 * br;
- dst[i + 1] = a1 * dg + a2 * bg;
- dst[i + 2] = a1 * db + a2 * bb;
- dst[i + 3] = sa * alpha + a2 * ba;
- }
- dstContext.putImageData(dstData, offset.x, offset.y);
- }
- };
-};
-
-var SVGStyles = Base.each({
- fillColor: ['fill', 'color'],
- strokeColor: ['stroke', 'color'],
- strokeWidth: ['stroke-width', 'number'],
- strokeCap: ['stroke-linecap', 'string'],
- strokeJoin: ['stroke-linejoin', 'string'],
- miterLimit: ['stroke-miterlimit', 'number'],
- dashArray: ['stroke-dasharray', 'array'],
- dashOffset: ['stroke-dashoffset', 'number'],
- font: ['font-family', 'string'],
- fontSize: ['font-size', 'number'],
- justification: ['text-anchor', 'lookup', {
- left: 'start',
- center: 'middle',
- right: 'end'
- }],
- opacity: ['opacity', 'number'],
- blendMode: ['mix-blend-mode', 'string']
-}, function(entry, key) {
- var part = Base.capitalize(key),
- lookup = entry[2];
- this[key] = {
- type: entry[1],
- property: key,
- attribute: entry[0],
- toSVG: lookup,
- fromSVG: lookup && Base.each(lookup, function(value, name) {
- this[value] = name;
- }, {}),
- get: 'get' + part,
- set: 'set' + part
- };
-}, {});
-
-var SVGNamespaces = {
- href: 'http://www.w3.org/1999/xlink',
- xlink: 'http://www.w3.org/2000/xmlns'
-};
-
-new function() {
- var formatter;
-
- function setAttributes(node, attrs) {
- for (var key in attrs) {
- var val = attrs[key],
- namespace = SVGNamespaces[key];
- if (typeof val === 'number')
- val = formatter.number(val);
- if (namespace) {
- node.setAttributeNS(namespace, key, val);
- } else {
- node.setAttribute(key, val);
- }
- }
- return node;
- }
-
- function createElement(tag, attrs) {
- return setAttributes(
- document.createElementNS('http://www.w3.org/2000/svg', tag), attrs);
- }
-
- function getTransform(item, coordinates, center) {
- var matrix = item._matrix,
- trans = matrix.getTranslation(),
- attrs = {};
- if (coordinates) {
- matrix = matrix.shiftless();
- var point = matrix._inverseTransform(trans);
- attrs[center ? 'cx' : 'x'] = point.x;
- attrs[center ? 'cy' : 'y'] = point.y;
- trans = null;
- }
- if (matrix.isIdentity())
- return attrs;
- var decomposed = matrix.decompose();
- if (decomposed && !decomposed.shearing) {
- var parts = [],
- angle = decomposed.rotation,
- scale = decomposed.scaling;
- if (trans && !trans.isZero())
- parts.push('translate(' + formatter.point(trans) + ')');
- if (!Numerical.isZero(scale.x - 1) || !Numerical.isZero(scale.y - 1))
- parts.push('scale(' + formatter.point(scale) +')');
- if (angle)
- parts.push('rotate(' + formatter.number(angle) + ')');
- attrs.transform = parts.join(' ');
- } else {
- attrs.transform = 'matrix(' + matrix.getValues().join(',') + ')';
- }
- return attrs;
- }
-
- function exportGroup(item, options) {
- var attrs = getTransform(item),
- children = item._children;
- var node = createElement('g', attrs);
- for (var i = 0, l = children.length; i < l; i++) {
- var child = children[i];
- var childNode = exportSVG(child, options);
- if (childNode) {
- if (child.isClipMask()) {
- var clip = createElement('clipPath');
- clip.appendChild(childNode);
- setDefinition(child, clip, 'clip');
- setAttributes(node, {
- 'clip-path': 'url(#' + clip.id + ')'
- });
- } else {
- node.appendChild(childNode);
- }
- }
- }
- return node;
- }
-
- function exportRaster(item) {
- var attrs = getTransform(item, true),
- size = item.getSize();
- attrs.x -= size.width / 2;
- attrs.y -= size.height / 2;
- attrs.width = size.width;
- attrs.height = size.height;
- attrs.href = item.toDataURL();
- return createElement('image', attrs);
- }
-
- function exportPath(item, options) {
- if (options.matchShapes) {
- var shape = item.toShape(false);
- if (shape)
- return exportShape(shape, options);
- }
- var segments = item._segments,
- type,
- attrs;
- if (segments.length === 0)
- return null;
- if (item.isPolygon()) {
- if (segments.length >= 3) {
- type = item._closed ? 'polygon' : 'polyline';
- var parts = [];
- for(i = 0, l = segments.length; i < l; i++)
- parts.push(formatter.point(segments[i]._point));
- attrs = {
- points: parts.join(' ')
- };
- } else {
- type = 'line';
- var first = segments[0]._point,
- last = segments[segments.length - 1]._point;
- attrs = {
- x1: first.x,
- y1: first.y,
- x2: last.x,
- y2: last.y
- };
- }
- } else {
- type = 'path';
- var data = item.getPathData();
- attrs = data && { d: data };
- }
- return createElement(type, attrs);
- }
-
- function exportShape(item) {
- var shape = item._shape,
- radius = item._radius,
- attrs = getTransform(item, true, shape !== 'rectangle');
- if (shape === 'rectangle') {
- shape = 'rect';
- var size = item._size,
- width = size.width,
- height = size.height;
- attrs.x -= width / 2;
- attrs.y -= height / 2;
- attrs.width = width;
- attrs.height = height;
- if (radius.isZero())
- radius = null;
- }
- if (radius) {
- if (shape === 'circle') {
- attrs.r = radius;
- } else {
- attrs.rx = radius.width;
- attrs.ry = radius.height;
- }
- }
- return createElement(shape, attrs);
- }
-
- function exportCompoundPath(item) {
- var attrs = getTransform(item, true);
- var data = item.getPathData();
- if (data)
- attrs.d = data;
- return createElement('path', attrs);
- }
-
- function exportPlacedSymbol(item, options) {
- var attrs = getTransform(item, true),
- symbol = item.getSymbol(),
- symbolNode = getDefinition(symbol, 'symbol'),
- definition = symbol.getDefinition(),
- bounds = definition.getBounds();
- if (!symbolNode) {
- symbolNode = createElement('symbol', {
- viewBox: formatter.rectangle(bounds)
- });
- symbolNode.appendChild(exportSVG(definition, options));
- setDefinition(symbol, symbolNode, 'symbol');
- }
- attrs.href = '#' + symbolNode.id;
- attrs.x += bounds.x;
- attrs.y += bounds.y;
- attrs.width = formatter.number(bounds.width);
- attrs.height = formatter.number(bounds.height);
- return createElement('use', attrs);
- }
-
- function exportGradient(color) {
- var gradientNode = getDefinition(color, 'color');
- if (!gradientNode) {
- var gradient = color.getGradient(),
- radial = gradient._radial,
- origin = color.getOrigin().transform(),
- destination = color.getDestination().transform(),
- attrs;
- if (radial) {
- attrs = {
- cx: origin.x,
- cy: origin.y,
- r: origin.getDistance(destination)
- };
- var highlight = color.getHighlight();
- if (highlight) {
- highlight = highlight.transform();
- attrs.fx = highlight.x;
- attrs.fy = highlight.y;
- }
- } else {
- attrs = {
- x1: origin.x,
- y1: origin.y,
- x2: destination.x,
- y2: destination.y
- };
- }
- attrs.gradientUnits = 'userSpaceOnUse';
- gradientNode = createElement(
- (radial ? 'radial' : 'linear') + 'Gradient', attrs);
- var stops = gradient._stops;
- for (var i = 0, l = stops.length; i < l; i++) {
- var stop = stops[i],
- stopColor = stop._color,
- alpha = stopColor.getAlpha();
- attrs = {
- offset: stop._rampPoint,
- 'stop-color': stopColor.toCSS(true)
- };
- if (alpha < 1)
- attrs['stop-opacity'] = alpha;
- gradientNode.appendChild(createElement('stop', attrs));
- }
- setDefinition(color, gradientNode, 'color');
- }
- return 'url(#' + gradientNode.id + ')';
- }
-
- function exportText(item) {
- var node = createElement('text', getTransform(item, true));
- node.textContent = item._content;
- return node;
- }
-
- var exporters = {
- group: exportGroup,
- layer: exportGroup,
- raster: exportRaster,
- path: exportPath,
- shape: exportShape,
- 'compound-path': exportCompoundPath,
- 'placed-symbol': exportPlacedSymbol,
- 'point-text': exportText
- };
-
- function applyStyle(item, node) {
- var attrs = {},
- parent = item.getParent();
-
- if (item._name != null)
- attrs.id = item._name;
-
- Base.each(SVGStyles, function(entry) {
- var get = entry.get,
- type = entry.type,
- value = item[get]();
- if (!parent || !Base.equals(parent[get](), value)) {
- if (type === 'color' && value != null) {
- var alpha = value.getAlpha();
- if (alpha < 1)
- attrs[entry.attribute + '-opacity'] = alpha;
- }
- attrs[entry.attribute] = value == null
- ? 'none'
- : type === 'number'
- ? formatter.number(value)
- : type === 'color'
- ? value.gradient
- ? exportGradient(value, item)
- : value.toCSS(true)
- : type === 'array'
- ? value.join(',')
- : type === 'lookup'
- ? entry.toSVG[value]
- : value;
- }
- });
-
- if (attrs.opacity === 1)
- delete attrs.opacity;
-
- if (item._visibility != null && !item._visibility)
- attrs.visibility = 'hidden';
-
- return setAttributes(node, attrs);
- }
-
- var definitions;
- function getDefinition(item, type) {
- if (!definitions)
- definitions = { ids: {}, svgs: {} };
- return item && definitions.svgs[type + '-' + item._id];
- }
-
- function setDefinition(item, node, type) {
- if (!definitions)
- getDefinition();
- var id = definitions.ids[type] = (definitions.ids[type] || 0) + 1;
- node.id = type + '-' + id;
- definitions.svgs[type + '-' + item._id] = node;
- }
-
- function exportDefinitions(node, options) {
- var svg = node,
- defs = null;
- if (definitions) {
- svg = node.nodeName.toLowerCase() === 'svg' && node;
- for (var i in definitions.svgs) {
- if (!defs) {
- if (!svg) {
- svg = createElement('svg');
- svg.appendChild(node);
- }
- defs = svg.insertBefore(createElement('defs'),
- svg.firstChild);
- }
- defs.appendChild(definitions.svgs[i]);
- }
- definitions = null;
- }
- return options.asString
- ? new XMLSerializer().serializeToString(svg)
- : svg;
- }
-
- function exportSVG(item, options) {
- var exporter = exporters[item._type],
- node = exporter && exporter(item, options);
- if (node && item._data)
- node.setAttribute('data-paper-data', JSON.stringify(item._data));
- return node && applyStyle(item, node);
- }
-
- function setOptions(options) {
- if (!options)
- options = {};
- formatter = new Formatter(options.precision);
- return options;
- }
-
- Item.inject({
- exportSVG: function(options) {
- options = setOptions(options);
- return exportDefinitions(exportSVG(this, options), options);
- }
- });
-
- Project.inject({
- exportSVG: function(options) {
- options = setOptions(options);
- var layers = this.layers,
- size = this.view.getSize(),
- node = createElement('svg', {
- x: 0,
- y: 0,
- width: size.width,
- height: size.height,
- version: '1.1',
- xmlns: 'http://www.w3.org/2000/svg',
- 'xmlns:xlink': 'http://www.w3.org/1999/xlink'
- });
- for (var i = 0, l = layers.length; i < l; i++)
- node.appendChild(exportSVG(layers[i], options));
- return exportDefinitions(node, options);
- }
- });
-};
-
-new function() {
-
- function getValue(node, name, isString, allowNull) {
- var namespace = SVGNamespaces[name],
- value = namespace
- ? node.getAttributeNS(namespace, name)
- : node.getAttribute(name);
- if (value === 'null')
- value = null;
- return value == null
- ? allowNull
- ? null
- : isString
- ? ''
- : 0
- : isString
- ? value
- : parseFloat(value);
- }
-
- function getPoint(node, x, y, allowNull) {
- x = getValue(node, x, false, allowNull);
- y = getValue(node, y, false, allowNull);
- return allowNull && (x == null || y == null) ? null
- : new Point(x, y);
- }
-
- function getSize(node, w, h, allowNull) {
- w = getValue(node, w, false, allowNull);
- h = getValue(node, h, false, allowNull);
- return allowNull && (w == null || h == null) ? null
- : new Size(w, h);
- }
-
- function convertValue(value, type, lookup) {
- return value === 'none'
- ? null
- : type === 'number'
- ? parseFloat(value)
- : type === 'array'
- ? value ? value.split(/[\s,]+/g).map(parseFloat) : []
- : type === 'color'
- ? getDefinition(value) || value
- : type === 'lookup'
- ? lookup[value]
- : value;
- }
-
- function importGroup(node, type, isRoot, options) {
- var nodes = node.childNodes,
- isClip = type === 'clippath',
- item = new Group(),
- project = item._project,
- currentStyle = project._currentStyle,
- children = [];
- if (!isClip) {
- item._transformContent = false;
- item = applyAttributes(item, node, isRoot);
- project._currentStyle = item._style.clone();
- }
- for (var i = 0, l = nodes.length; i < l; i++) {
- var childNode = nodes[i],
- child;
- if (childNode.nodeType === 1
- && (child = importSVG(childNode, false, options))
- && !(child instanceof Symbol))
- children.push(child);
- }
- item.addChildren(children);
- if (isClip)
- item = applyAttributes(item.reduce(), node, isRoot);
- project._currentStyle = currentStyle;
- if (isClip || type === 'defs') {
- item.remove();
- item = null;
- }
- return item;
- }
-
- function importPoly(node, type) {
- var path = new Path(),
- points = node.points;
- path.moveTo(points.getItem(0));
- for (var i = 1, l = points.numberOfItems; i < l; i++)
- path.lineTo(points.getItem(i));
- if (type === 'polygon')
- path.closePath();
- return path;
- }
-
- function importPath(node) {
- var data = node.getAttribute('d'),
- path = data.match(/m/gi).length > 1
- ? new CompoundPath()
- : new Path();
- path.setPathData(data);
- return path;
- }
-
- function importGradient(node, type) {
- var nodes = node.childNodes,
- stops = [];
- for (var i = 0, l = nodes.length; i < l; i++) {
- var child = nodes[i];
- if (child.nodeType === 1)
- stops.push(applyAttributes(new GradientStop(), child));
- }
- var isRadial = type === 'radialgradient',
- gradient = new Gradient(stops, isRadial),
- origin, destination, highlight;
- if (isRadial) {
- origin = getPoint(node, 'cx', 'cy');
- destination = origin.add(getValue(node, 'r'), 0);
- highlight = getPoint(node, 'fx', 'fy', true);
- } else {
- origin = getPoint(node, 'x1', 'y1');
- destination = getPoint(node, 'x2', 'y2');
- }
- applyAttributes(
- new Color(gradient, origin, destination, highlight), node);
- return null;
- }
-
- var importers = {
- '#document': function (node, type, isRoot, options) {
- var nodes = node.childNodes;
- for (var i = 0, l = nodes.length; i < l; i++) {
- var child = nodes[i];
- if (child.nodeType === 1) {
- var next = child.nextSibling;
- document.body.appendChild(child);
- var item = importSVG(child, isRoot, options);
- if (next) {
- node.insertBefore(child, next);
- } else {
- node.appendChild(child);
- }
- return item;
- }
- }
- },
- g: importGroup,
- svg: importGroup,
- clippath: importGroup,
- polygon: importPoly,
- polyline: importPoly,
- path: importPath,
- lineargradient: importGradient,
- radialgradient: importGradient,
-
- image: function (node) {
- var raster = new Raster(getValue(node, 'href', true));
- raster.attach('load', function() {
- var size = getSize(node, 'width', 'height');
- this.setSize(size);
- var center = this._matrix._transformPoint(
- getPoint(node, 'x', 'y').add(size.divide(2)));
- this.translate(center);
- });
- return raster;
- },
-
- symbol: function(node, type, isRoot, options) {
- return new Symbol(importGroup(node, type, isRoot, options), true);
- },
-
- defs: importGroup,
-
- use: function(node) {
- var id = (getValue(node, 'href', true) || '').substring(1),
- definition = definitions[id],
- point = getPoint(node, 'x', 'y');
- return definition
- ? definition instanceof Symbol
- ? definition.place(point)
- : definition.clone().translate(point)
- : null;
- },
-
- circle: function(node) {
- return new Shape.Circle(getPoint(node, 'cx', 'cy'),
- getValue(node, 'r'));
- },
-
- ellipse: function(node) {
- return new Shape.Ellipse({
- center: getPoint(node, 'cx', 'cy'),
- radius: getSize(node, 'rx', 'ry')
- });
- },
-
- rect: function(node) {
- var point = getPoint(node, 'x', 'y'),
- size = getSize(node, 'width', 'height'),
- radius = getSize(node, 'rx', 'ry');
- return new Shape.Rectangle(new Rectangle(point, size), radius);
- },
-
- line: function(node) {
- return new Path.Line(getPoint(node, 'x1', 'y1'),
- getPoint(node, 'x2', 'y2'));
- },
-
- text: function(node) {
- var text = new PointText(getPoint(node, 'x', 'y')
- .add(getPoint(node, 'dx', 'dy')));
- text.setContent(node.textContent.trim() || '');
- return text;
- }
- };
-
- function applyTransform(item, value, name, node) {
- var transforms = (node.getAttribute(name) || '').split(/\)\s*/g),
- matrix = new Matrix();
- for (var i = 0, l = transforms.length; i < l; i++) {
- var transform = transforms[i];
- if (!transform)
- break;
- var parts = transform.split('('),
- command = parts[0],
- v = parts[1].split(/[\s,]+/g);
- for (var j = 0, m = v.length; j < m; j++)
- v[j] = parseFloat(v[j]);
- switch (command) {
- case 'matrix':
- matrix.concatenate(
- new Matrix(v[0], v[1], v[2], v[3], v[4], v[5]));
- break;
- case 'rotate':
- matrix.rotate(v[0], v[1], v[2]);
- break;
- case 'translate':
- matrix.translate(v[0], v[1]);
- break;
- case 'scale':
- matrix.scale(v);
- break;
- case 'skewX':
- case 'skewY':
- var value = Math.tan(v[0] * Math.PI / 180),
- isX = command == 'skewX';
- matrix.shear(isX ? value : 0, isX ? 0 : value);
- break;
- }
- }
- item.transform(matrix);
- }
-
- function applyOpacity(item, value, name) {
- var color = item[name === 'fill-opacity' ? 'getFillColor'
- : 'getStrokeColor']();
- if (color)
- color.setAlpha(parseFloat(value));
- }
-
- var attributes = Base.each(SVGStyles, function(entry) {
- this[entry.attribute] = function(item, value) {
- item[entry.set](convertValue(value, entry.type, entry.fromSVG));
- if (entry.type === 'color' && item instanceof Shape) {
- var color = item[entry.get]();
- if (color)
- color.transform(new Matrix().translate(
- item.getPosition(true).negate()));
- }
- };
- }, {
- id: function(item, value) {
- definitions[value] = item;
- if (item.setName)
- item.setName(value);
- },
-
- 'clip-path': function(item, value) {
- var clip = getDefinition(value);
- if (clip) {
- clip = clip.clone();
- clip.setClipMask(true);
- if (item instanceof Group) {
- item.insertChild(0, clip);
- } else {
- return new Group(clip, item);
- }
- }
- },
-
- gradientTransform: applyTransform,
- transform: applyTransform,
-
- 'fill-opacity': applyOpacity,
- 'stroke-opacity': applyOpacity,
-
- visibility: function(item, value) {
- item.setVisible(value === 'visible');
- },
-
- 'stop-color': function(item, value) {
- if (item.setColor)
- item.setColor(value);
- },
-
- 'stop-opacity': function(item, value) {
- if (item._color)
- item._color.setAlpha(parseFloat(value));
- },
-
- offset: function(item, value) {
- var percentage = value.match(/(.*)%$/);
- item.setRampPoint(percentage
- ? percentage[1] / 100
- : parseFloat(value));
- },
-
- viewBox: function(item, value, name, node, styles) {
- var rect = new Rectangle(convertValue(value, 'array')),
- size = getSize(node, 'width', 'height', true);
- if (item instanceof Group) {
- var scale = size ? rect.getSize().divide(size) : 1,
- matrix = new Matrix().translate(rect.getPoint()).scale(scale);
- item.transform(matrix.inverted());
- } else if (item instanceof Symbol) {
- if (size)
- rect.setSize(size);
- var clip = getAttribute(node, 'overflow', styles) != 'visible',
- group = item._definition;
- if (clip && !rect.contains(group.getBounds())) {
- clip = new Shape.Rectangle(rect).transform(group._matrix);
- clip.setClipMask(true);
- group.addChild(clip);
- }
- }
- }
- });
-
- function getAttribute(node, name, styles) {
- var attr = node.attributes[name],
- value = attr && attr.value;
- if (!value) {
- var style = Base.camelize(name);
- value = node.style[style];
- if (!value && styles.node[style] !== styles.parent[style])
- value = styles.node[style];
- }
- return !value
- ? undefined
- : value === 'none'
- ? null
- : value;
- }
-
- function applyAttributes(item, node, isRoot) {
- var styles = {
- node: DomElement.getStyles(node) || {},
- parent: !isRoot && DomElement.getStyles(node.parentNode) || {}
- };
- Base.each(attributes, function(apply, name) {
- var value = getAttribute(node, name, styles);
- if (value !== undefined)
- item = Base.pick(apply(item, value, name, node, styles), item);
- });
- return item;
- }
-
- var definitions = {};
- function getDefinition(value) {
- var match = value && value.match(/\((?:#|)([^)']+)/);
- return match && definitions[match[1]];
- }
-
- function importSVG(source, isRoot, options) {
- if (!source)
- return null;
- if (!options) {
- options = {};
- } else if (typeof options === 'function') {
- options = { onLoad: options };
- }
-
- var node = source,
- scope = paper;
-
- function onLoadCallback(svg) {
- paper = scope;
- var item = importSVG(svg, isRoot, options),
- onLoad = options.onLoad,
- view = scope.project && scope.project.view;
- if (onLoad)
- onLoad.call(this, item);
- view.draw(true);
- }
-
- if (isRoot) {
- if (typeof source === 'string' && !/^.*</.test(source)) {
- node = document.getElementById(source);
- if (node) {
- source = null;
- } else {
- return Http.request('get', source, onLoadCallback);
- }
- } else if (typeof File !== 'undefined' && source instanceof File) {
- var reader = new FileReader();
- reader.onload = function() {
- onLoadCallback(reader.result);
- };
- return reader.readAsText(source);
- }
- }
-
- if (typeof source === 'string')
- node = new DOMParser().parseFromString(source, 'image/svg+xml');
- if (!node.nodeName)
- throw new Error('Unsupported SVG source: ' + source);
- var type = node.nodeName.toLowerCase(),
- importer = importers[type],
- item = importer && importer(node, type, isRoot, options) || null,
- data = node.getAttribute && node.getAttribute('data-paper-data');
- if (item) {
- if (!(item instanceof Group))
- item = applyAttributes(item, node, isRoot);
- if (options.expandShapes && item instanceof Shape) {
- item.remove();
- item = item.toPath();
- }
- if (data)
- item._data = JSON.parse(data);
- }
- if (isRoot)
- definitions = {};
- return item;
- }
-
- Item.inject({
- importSVG: function(node, options) {
- return this.addChild(importSVG(node, true, options));
- }
- });
-
- Project.inject({
- importSVG: function(node, options) {
- this.activate();
- return importSVG(node, true, options);
- }
- });
-};
-
-paper = new (PaperScope.inject(new Base(Base.exports, {
- enumerable: true,
- Base: Base,
- Numerical: Numerical,
- DomElement: DomElement,
- DomEvent: DomEvent,
- Http: Http,
- Key: Key
-})))();
-
-if (typeof define === 'function' && define.amd)
- define('paper', paper);
-
-return paper;
-};
-
-paper.PaperScope.prototype.PaperScript = (function(root) {
- var Base = paper.Base,
- PaperScope = paper.PaperScope,
- PaperScript,
- exports, define,
- scope = this;
-!function(e,r){return"object"==typeof exports&&"object"==typeof module?r(exports):"function"==typeof define&&define.amd?define(["exports"],r):(r(e.acorn||(e.acorn={})),void 0)}(this,function(e){"use strict";function r(e){fr=e||{};for(var r in hr)Object.prototype.hasOwnProperty.call(fr,r)||(fr[r]=hr[r]);mr=fr.sourceFile||null}function t(e,r){var t=vr(pr,e);r+=" ("+t.line+":"+t.column+")";var n=new SyntaxError(r);throw n.pos=e,n.loc=t,n.raisedAt=br,n}function n(e){function r(e){if(1==e.length)return t+="return str === "+JSON.stringify(e[0])+";";t+="switch(str){";for(var r=0;r<e.length;++r)t+="case "+JSON.stringify(e[r])+":";t+="return true}return false;"}e=e.split(" ");var t="",n=[];e:for(var a=0;a<e.length;++a){for(var o=0;o<n.length;++o)if(n[o][0].length==e[a].length){n[o].push(e[a]);continue e}n.push([e[a]])}if(n.length>3){n.sort(function(e,r){return r.length-e.length}),t+="switch(str.length){";for(var a=0;a<n.length;++a){var i=n[a];t+="case "+i[0].length+":",r(i)}t+="}"}else r(e);return new Function("str",t)}function a(){this.line=Ar,this.column=br-Sr}function o(){Ar=1,br=Sr=0,Er=!0,u()}function i(e,r){gr=br,fr.locations&&(kr=new a),wr=e,u(),Cr=r,Er=e.beforeExpr}function s(){var e=fr.onComment&&fr.locations&&new a,r=br,n=pr.indexOf("*/",br+=2);if(-1===n&&t(br-2,"Unterminated comment"),br=n+2,fr.locations){Kt.lastIndex=r;for(var o;(o=Kt.exec(pr))&&o.index<br;)++Ar,Sr=o.index+o[0].length}fr.onComment&&fr.onComment(!0,pr.slice(r+2,n),r,br,e,fr.locations&&new a)}function c(){for(var e=br,r=fr.onComment&&fr.locations&&new a,t=pr.charCodeAt(br+=2);dr>br&&10!==t&&13!==t&&8232!==t&&8329!==t;)++br,t=pr.charCodeAt(br);fr.onComment&&fr.onComment(!1,pr.slice(e+2,br),e,br,r,fr.locations&&new a)}function u(){for(;dr>br;){var e=pr.charCodeAt(br);if(32===e)++br;else if(13===e){++br;var r=pr.charCodeAt(br);10===r&&++br,fr.locations&&(++Ar,Sr=br)}else if(10===e)++br,++Ar,Sr=br;else if(14>e&&e>8)++br;else if(47===e){var r=pr.charCodeAt(br+1);if(42===r)s();else{if(47!==r)break;c()}}else if(160===e)++br;else{if(!(e>=5760&&Jt.test(String.fromCharCode(e))))break;++br}}}function l(){var e=pr.charCodeAt(br+1);return e>=48&&57>=e?E(!0):(++br,i(xt))}function f(){var e=pr.charCodeAt(br+1);return Er?(++br,k()):61===e?x(Et,2):x(wt,1)}function p(){var e=pr.charCodeAt(br+1);return 61===e?x(Et,2):x(Ft,1)}function d(e){var r=pr.charCodeAt(br+1);return r===e?x(124===e?Lt:Ut,2):61===r?x(Et,2):x(124===e?Rt:Vt,1)}function m(){var e=pr.charCodeAt(br+1);return 61===e?x(Et,2):x(Tt,1)}function h(e){var r=pr.charCodeAt(br+1);return r===e?x(St,2):61===r?x(Et,2):x(At,1)}function v(e){var r=pr.charCodeAt(br+1),t=1;return r===e?(t=62===e&&62===pr.charCodeAt(br+2)?3:2,61===pr.charCodeAt(br+t)?x(Et,t+1):x(jt,t)):(61===r&&(t=61===pr.charCodeAt(br+2)?3:2),x(Ot,t))}function b(e){var r=pr.charCodeAt(br+1);return 61===r?x(qt,61===pr.charCodeAt(br+2)?3:2):x(61===e?Ct:It,1)}function y(e){switch(e){case 46:return l();case 40:return++br,i(ht);case 41:return++br,i(vt);case 59:return++br,i(yt);case 44:return++br,i(bt);case 91:return++br,i(ft);case 93:return++br,i(pt);case 123:return++br,i(dt);case 125:return++br,i(mt);case 58:return++br,i(gt);case 63:return++br,i(kt);case 48:var r=pr.charCodeAt(br+1);if(120===r||88===r)return C();case 49:case 50:case 51:case 52:case 53:case 54:case 55:case 56:case 57:return E(!1);case 34:case 39:return A(e);case 47:return f(e);case 37:case 42:return p();case 124:case 38:return d(e);case 94:return m();case 43:case 45:return h(e);case 60:case 62:return v(e);case 61:case 33:return b(e);case 126:return x(It,1)}return!1}function g(e){if(e?br=yr+1:yr=br,fr.locations&&(xr=new a),e)return k();if(br>=dr)return i(Br);var r=pr.charCodeAt(br);if(Qt(r)||92===r)return L();var n=y(r);if(n===!1){var o=String.fromCharCode(r);if("\\"===o||$t.test(o))return L();t(br,"Unexpected character '"+o+"'")}return n}function x(e,r){var t=pr.slice(br,br+r);br+=r,i(e,t)}function k(){for(var e,r,n="",a=br;;){br>=dr&&t(a,"Unterminated regular expression");var o=pr.charAt(br);if(Gt.test(o)&&t(a,"Unterminated regular expression"),e)e=!1;else{if("["===o)r=!0;else if("]"===o&&r)r=!1;else if("/"===o&&!r)break;e="\\"===o}++br}var n=pr.slice(a,br);++br;var s=I();return s&&!/^[gmsiy]*$/.test(s)&&t(a,"Invalid regexp flag"),i(jr,new RegExp(n,s))}function w(e,r){for(var t=br,n=0,a=0,o=null==r?1/0:r;o>a;++a){var i,s=pr.charCodeAt(br);if(i=s>=97?s-97+10:s>=65?s-65+10:s>=48&&57>=s?s-48:1/0,i>=e)break;++br,n=n*e+i}return br===t||null!=r&&br-t!==r?null:n}function C(){br+=2;var e=w(16);return null==e&&t(yr+2,"Expected hexadecimal number"),Qt(pr.charCodeAt(br))&&t(br,"Identifier directly after number"),i(Or,e)}function E(e){var r=br,n=!1,a=48===pr.charCodeAt(br);e||null!==w(10)||t(r,"Invalid number"),46===pr.charCodeAt(br)&&(++br,w(10),n=!0);var o=pr.charCodeAt(br);(69===o||101===o)&&(o=pr.charCodeAt(++br),(43===o||45===o)&&++br,null===w(10)&&t(r,"Invalid number"),n=!0),Qt(pr.charCodeAt(br))&&t(br,"Identifier directly after number");var s,c=pr.slice(r,br);return n?s=parseFloat(c):a&&1!==c.length?/[89]/.test(c)||Vr?t(r,"Invalid number"):s=parseInt(c,8):s=parseInt(c,10),i(Or,s)}function A(e){br++;for(var r="";;){br>=dr&&t(yr,"Unterminated string constant");var n=pr.charCodeAt(br);if(n===e)return++br,i(Fr,r);if(92===n){n=pr.charCodeAt(++br);var a=/^[0-7]+/.exec(pr.slice(br,br+3));for(a&&(a=a[0]);a&&parseInt(a,8)>255;)a=a.slice(0,a.length-1);if("0"===a&&(a=null),++br,a)Vr&&t(br-2,"Octal literal in strict mode"),r+=String.fromCharCode(parseInt(a,8)),br+=a.length-1;else switch(n){case 110:r+="\n";break;case 114:r+="\r";break;case 120:r+=String.fromCharCode(S(2));break;case 117:r+=String.fromCharCode(S(4));break;case 85:r+=String.fromCharCode(S(8));break;case 116:r+=" ";break;case 98:r+="\b";break;case 118:r+="";break;case 102:r+="\f";break;case 48:r+="\0";break;case 13:10===pr.charCodeAt(br)&&++br;case 10:fr.locations&&(Sr=br,++Ar);break;default:r+=String.fromCharCode(n)}}else(13===n||10===n||8232===n||8329===n)&&t(yr,"Unterminated string constant"),r+=String.fromCharCode(n),++br}}function S(e){var r=w(16,e);return null===r&&t(yr,"Bad character escape sequence"),r}function I(){Bt=!1;for(var e,r=!0,n=br;;){var a=pr.charCodeAt(br);if(Yt(a))Bt&&(e+=pr.charAt(br)),++br;else{if(92!==a)break;Bt||(e=pr.slice(n,br)),Bt=!0,117!=pr.charCodeAt(++br)&&t(br,"Expecting Unicode escape sequence \\uXXXX"),++br;var o=S(4),i=String.fromCharCode(o);i||t(br-1,"Invalid Unicode escape"),(r?Qt(o):Yt(o))||t(br-4,"Invalid Unicode escape"),e+=i}r=!1}return Bt?e:pr.slice(n,br)}function L(){var e=I(),r=Dr;return Bt||(Wt(e)?r=lt[e]:(fr.forbidReserved&&(3===fr.ecmaVersion?Mt:zt)(e)||Vr&&Xt(e))&&t(yr,"The keyword '"+e+"' is reserved")),i(r,e)}function U(){Ir=yr,Lr=gr,Ur=kr,g()}function R(e){for(Vr=e,br=Lr;Sr>br;)Sr=pr.lastIndexOf("\n",Sr-2)+1,--Ar;u(),g()}function T(){this.type=null,this.start=yr,this.end=null}function V(){this.start=xr,this.end=null,null!==mr&&(this.source=mr)}function q(){var e=new T;return fr.locations&&(e.loc=new V),fr.ranges&&(e.range=[yr,0]),e}function O(e){var r=new T;return r.start=e.start,fr.locations&&(r.loc=new V,r.loc.start=e.loc.start),fr.ranges&&(r.range=[e.range[0],0]),r}function j(e,r){return e.type=r,e.end=Lr,fr.locations&&(e.loc.end=Ur),fr.ranges&&(e.range[1]=Lr),e}function F(e){return fr.ecmaVersion>=5&&"ExpressionStatement"===e.type&&"Literal"===e.expression.type&&"use strict"===e.expression.value}function D(e){return wr===e?(U(),!0):void 0}function B(){return!fr.strictSemicolons&&(wr===Br||wr===mt||Gt.test(pr.slice(Lr,yr)))}function M(){D(yt)||B()||X()}function z(e){wr===e?U():X()}function X(){t(yr,"Unexpected token")}function N(e){"Identifier"!==e.type&&"MemberExpression"!==e.type&&t(e.start,"Assigning to rvalue"),Vr&&"Identifier"===e.type&&Nt(e.name)&&t(e.start,"Assigning to "+e.name+" in strict mode")}function W(e){Ir=Lr=br,fr.locations&&(Ur=new a),Rr=Vr=null,Tr=[],g();var r=e||q(),t=!0;for(e||(r.body=[]);wr!==Br;){var n=J();r.body.push(n),t&&F(n)&&R(!0),t=!1}return j(r,"Program")}function J(){wr===wt&&g(!0);var e=wr,r=q();switch(e){case Mr:case Nr:U();var n=e===Mr;D(yt)||B()?r.label=null:wr!==Dr?X():(r.label=lr(),M());for(var a=0;a<Tr.length;++a){var o=Tr[a];if(null==r.label||o.name===r.label.name){if(null!=o.kind&&(n||"loop"===o.kind))break;if(r.label&&n)break}}return a===Tr.length&&t(r.start,"Unsyntactic "+e.keyword),j(r,n?"BreakStatement":"ContinueStatement");case Wr:return U(),M(),j(r,"DebuggerStatement");case Pr:return U(),Tr.push(Zt),r.body=J(),Tr.pop(),z(tt),r.test=P(),M(),j(r,"DoWhileStatement");case _r:if(U(),Tr.push(Zt),z(ht),wr===yt)return $(r,null);if(wr===rt){var i=q();return U(),G(i,!0),1===i.declarations.length&&D(ut)?_(r,i):$(r,i)}var i=K(!1,!0);return D(ut)?(N(i),_(r,i)):$(r,i);case Gr:return U(),cr(r,!0);case Kr:return U(),r.test=P(),r.consequent=J(),r.alternate=D(Hr)?J():null,j(r,"IfStatement");case Qr:return Rr||t(yr,"'return' outside of function"),U(),D(yt)||B()?r.argument=null:(r.argument=K(),M()),j(r,"ReturnStatement");case Yr:U(),r.discriminant=P(),r.cases=[],z(dt),Tr.push(en);for(var s,c;wr!=mt;)if(wr===zr||wr===Jr){var u=wr===zr;s&&j(s,"SwitchCase"),r.cases.push(s=q()),s.consequent=[],U(),u?s.test=K():(c&&t(Ir,"Multiple default clauses"),c=!0,s.test=null),z(gt)}else s||X(),s.consequent.push(J());return s&&j(s,"SwitchCase"),U(),Tr.pop(),j(r,"SwitchStatement");case Zr:return U(),Gt.test(pr.slice(Lr,yr))&&t(Lr,"Illegal newline after throw"),r.argument=K(),M(),j(r,"ThrowStatement");case et:if(U(),r.block=H(),r.handler=null,wr===Xr){var l=q();U(),z(ht),l.param=lr(),Vr&&Nt(l.param.name)&&t(l.param.start,"Binding "+l.param.name+" in strict mode"),z(vt),l.guard=null,l.body=H(),r.handler=j(l,"CatchClause")}return r.guardedHandlers=qr,r.finalizer=D($r)?H():null,r.handler||r.finalizer||t(r.start,"Missing catch or finally clause"),j(r,"TryStatement");case rt:return U(),r=G(r),M(),r;case tt:return U(),r.test=P(),Tr.push(Zt),r.body=J(),Tr.pop(),j(r,"WhileStatement");case nt:return Vr&&t(yr,"'with' in strict mode"),U(),r.object=P(),r.body=J(),j(r,"WithStatement");case dt:return H();case yt:return U(),j(r,"EmptyStatement");default:var f=Cr,p=K();if(e===Dr&&"Identifier"===p.type&&D(gt)){for(var a=0;a<Tr.length;++a)Tr[a].name===f&&t(p.start,"Label '"+f+"' is already declared");var d=wr.isLoop?"loop":wr===Yr?"switch":null;return Tr.push({name:f,kind:d}),r.body=J(),Tr.pop(),r.label=p,j(r,"LabeledStatement")}return r.expression=p,M(),j(r,"ExpressionStatement")}}function P(){z(ht);var e=K();return z(vt),e}function H(e){var r,t=q(),n=!0,a=!1;for(t.body=[],z(dt);!D(mt);){var o=J();t.body.push(o),n&&e&&F(o)&&(r=a,R(a=!0)),n=!1}return a&&!r&&R(!1),j(t,"BlockStatement")}function $(e,r){return e.init=r,z(yt),e.test=wr===yt?null:K(),z(yt),e.update=wr===vt?null:K(),z(vt),e.body=J(),Tr.pop(),j(e,"ForStatement")}function _(e,r){return e.left=r,e.right=K(),z(vt),e.body=J(),Tr.pop(),j(e,"ForInStatement")}function G(e,r){for(e.declarations=[],e.kind="var";;){var n=q();if(n.id=lr(),Vr&&Nt(n.id.name)&&t(n.id.start,"Binding "+n.id.name+" in strict mode"),n.init=D(Ct)?K(!0,r):null,e.declarations.push(j(n,"VariableDeclarator")),!D(bt))break}return j(e,"VariableDeclaration")}function K(e,r){var t=Q(r);if(!e&&wr===bt){var n=O(t);for(n.expressions=[t];D(bt);)n.expressions.push(Q(r));return j(n,"SequenceExpression")}return t}function Q(e){var r=Y(e);if(wr.isAssign){var t=O(r);return t.operator=Cr,t.left=r,U(),t.right=Q(e),N(r),j(t,"AssignmentExpression")}return r}function Y(e){var r=Z(e);if(D(kt)){var t=O(r);return t.test=r,t.consequent=K(!0),z(gt),t.alternate=K(!0,e),j(t,"ConditionalExpression")}return r}function Z(e){return er(rr(),-1,e)}function er(e,r,t){var n=wr.binop;if(null!=n&&(!t||wr!==ut)&&n>r){var a=O(e);a.left=e,a.operator=Cr,U(),a.right=er(rr(),n,t);var a=j(a,/&&|\|\|/.test(a.operator)?"LogicalExpression":"BinaryExpression");return er(a,r,t)}return e}function rr(){if(wr.prefix){var e=q(),r=wr.isUpdate;return e.operator=Cr,e.prefix=!0,U(),e.argument=rr(),r?N(e.argument):Vr&&"delete"===e.operator&&"Identifier"===e.argument.type&&t(e.start,"Deleting local variable in strict mode"),j(e,r?"UpdateExpression":"UnaryExpression")}for(var n=tr();wr.postfix&&!B();){var e=O(n);e.operator=Cr,e.prefix=!1,e.argument=n,N(n),U(),n=j(e,"UpdateExpression")}return n}function tr(){return nr(ar())}function nr(e,r){if(D(xt)){var t=O(e);return t.object=e,t.property=lr(!0),t.computed=!1,nr(j(t,"MemberExpression"),r)}if(D(ft)){var t=O(e);return t.object=e,t.property=K(),t.computed=!0,z(pt),nr(j(t,"MemberExpression"),r)}if(!r&&D(ht)){var t=O(e);return t.callee=e,t.arguments=ur(vt,!1),nr(j(t,"CallExpression"),r)}return e}function ar(){switch(wr){case ot:var e=q();return U(),j(e,"ThisExpression");case Dr:return lr();case Or:case Fr:case jr:var e=q();return e.value=Cr,e.raw=pr.slice(yr,gr),U(),j(e,"Literal");case it:case st:case ct:var e=q();return e.value=wr.atomValue,e.raw=wr.keyword,U(),j(e,"Literal");case ht:var r=xr,t=yr;U();var n=K();return n.start=t,n.end=gr,fr.locations&&(n.loc.start=r,n.loc.end=kr),fr.ranges&&(n.range=[t,gr]),z(vt),n;case ft:var e=q();return U(),e.elements=ur(pt,!0,!0),j(e,"ArrayExpression");case dt:return ir();case Gr:var e=q();return U(),cr(e,!1);case at:return or();default:X()}}function or(){var e=q();return U(),e.callee=nr(ar(),!0),e.arguments=D(ht)?ur(vt,!1):qr,j(e,"NewExpression")}function ir(){var e=q(),r=!0,n=!1;for(e.properties=[],U();!D(mt);){if(r)r=!1;else if(z(bt),fr.allowTrailingCommas&&D(mt))break;var a,o={key:sr()},i=!1;if(D(gt)?(o.value=K(!0),a=o.kind="init"):fr.ecmaVersion>=5&&"Identifier"===o.key.type&&("get"===o.key.name||"set"===o.key.name)?(i=n=!0,a=o.kind=o.key.name,o.key=sr(),wr!==ht&&X(),o.value=cr(q(),!1)):X(),"Identifier"===o.key.type&&(Vr||n))for(var s=0;s<e.properties.length;++s){var c=e.properties[s];if(c.key.name===o.key.name){var u=a==c.kind||i&&"init"===c.kind||"init"===a&&("get"===c.kind||"set"===c.kind);u&&!Vr&&"init"===a&&"init"===c.kind&&(u=!1),u&&t(o.key.start,"Redefinition of property")}}e.properties.push(o)}return j(e,"ObjectExpression")}function sr(){return wr===Or||wr===Fr?ar():lr(!0)}function cr(e,r){wr===Dr?e.id=lr():r?X():e.id=null,e.params=[];var n=!0;for(z(ht);!D(vt);)n?n=!1:z(bt),e.params.push(lr());var a=Rr,o=Tr;if(Rr=!0,Tr=[],e.body=H(!0),Rr=a,Tr=o,Vr||e.body.body.length&&F(e.body.body[0]))for(var i=e.id?-1:0;i<e.params.length;++i){var s=0>i?e.id:e.params[i];if((Xt(s.name)||Nt(s.name))&&t(s.start,"Defining '"+s.name+"' in strict mode"),i>=0)for(var c=0;i>c;++c)s.name===e.params[c].name&&t(s.start,"Argument name clash in strict mode")}return j(e,r?"FunctionDeclaration":"FunctionExpression")}function ur(e,r,t){for(var n=[],a=!0;!D(e);){if(a)a=!1;else if(z(bt),r&&fr.allowTrailingCommas&&D(e))break;t&&wr===bt?n.push(null):n.push(K(!0))}return n}function lr(e){var r=q();return r.name=wr===Dr?Cr:e&&!fr.forbidReserved&&wr.keyword||X(),U(),j(r,"Identifier")}e.version="0.3.2";var fr,pr,dr,mr;e.parse=function(e,t){return pr=String(e),dr=pr.length,r(t),o(),W(fr.program)};var hr=e.defaultOptions={ecmaVersion:5,strictSemicolons:!1,allowTrailingCommas:!0,forbidReserved:!1,locations:!1,onComment:null,ranges:!1,program:null,sourceFile:null},vr=e.getLineInfo=function(e,r){for(var t=1,n=0;;){Kt.lastIndex=n;var a=Kt.exec(e);if(!(a&&a.index<r))break;++t,n=a.index+a[0].length}return{line:t,column:r-n}};e.tokenize=function(e,t){function n(e){return g(e),a.start=yr,a.end=gr,a.startLoc=xr,a.endLoc=kr,a.type=wr,a.value=Cr,a}pr=String(e),dr=pr.length,r(t),o();var a={};return n.jumpTo=function(e,r){if(br=e,fr.locations){Ar=1,Sr=Kt.lastIndex=0;for(var t;(t=Kt.exec(pr))&&t.index<e;)++Ar,Sr=t.index+t[0].length}Er=r,u()},n};var br,yr,gr,xr,kr,wr,Cr,Er,Ar,Sr,Ir,Lr,Ur,Rr,Tr,Vr,qr=[],Or={type:"num"},jr={type:"regexp"},Fr={type:"string"},Dr={type:"name"},Br={type:"eof"},Mr={keyword:"break"},zr={keyword:"case",beforeExpr:!0},Xr={keyword:"catch"},Nr={keyword:"continue"},Wr={keyword:"debugger"},Jr={keyword:"default"},Pr={keyword:"do",isLoop:!0},Hr={keyword:"else",beforeExpr:!0},$r={keyword:"finally"},_r={keyword:"for",isLoop:!0},Gr={keyword:"function"},Kr={keyword:"if"},Qr={keyword:"return",beforeExpr:!0},Yr={keyword:"switch"},Zr={keyword:"throw",beforeExpr:!0},et={keyword:"try"},rt={keyword:"var"},tt={keyword:"while",isLoop:!0},nt={keyword:"with"},at={keyword:"new",beforeExpr:!0},ot={keyword:"this"},it={keyword:"null",atomValue:null},st={keyword:"true",atomValue:!0},ct={keyword:"false",atomValue:!1},ut={keyword:"in",binop:7,beforeExpr:!0},lt={"break":Mr,"case":zr,"catch":Xr,"continue":Nr,"debugger":Wr,"default":Jr,"do":Pr,"else":Hr,"finally":$r,"for":_r,"function":Gr,"if":Kr,"return":Qr,"switch":Yr,"throw":Zr,"try":et,"var":rt,"while":tt,"with":nt,"null":it,"true":st,"false":ct,"new":at,"in":ut,"instanceof":{keyword:"instanceof",binop:7,beforeExpr:!0},"this":ot,"typeof":{keyword:"typeof",prefix:!0,beforeExpr:!0},"void":{keyword:"void",prefix:!0,beforeExpr:!0},"delete":{keyword:"delete",prefix:!0,beforeExpr:!0}},ft={type:"[",beforeExpr:!0},pt={type:"]"},dt={type:"{",beforeExpr:!0},mt={type:"}"},ht={type:"(",beforeExpr:!0},vt={type:")"},bt={type:",",beforeExpr:!0},yt={type:";",beforeExpr:!0},gt={type:":",beforeExpr:!0},xt={type:"."},kt={type:"?",beforeExpr:!0},wt={binop:10,beforeExpr:!0},Ct={isAssign:!0,beforeExpr:!0},Et={isAssign:!0,beforeExpr:!0},At={binop:9,prefix:!0,beforeExpr:!0},St={postfix:!0,prefix:!0,isUpdate:!0},It={prefix:!0,beforeExpr:!0},Lt={binop:1,beforeExpr:!0},Ut={binop:2,beforeExpr:!0},Rt={binop:3,beforeExpr:!0},Tt={binop:4,beforeExpr:!0},Vt={binop:5,beforeExpr:!0},qt={binop:6,beforeExpr:!0},Ot={binop:7,beforeExpr:!0},jt={binop:8,beforeExpr:!0},Ft={binop:10,beforeExpr:!0};e.tokTypes={bracketL:ft,bracketR:pt,braceL:dt,braceR:mt,parenL:ht,parenR:vt,comma:bt,semi:yt,colon:gt,dot:xt,question:kt,slash:wt,eq:Ct,name:Dr,eof:Br,num:Or,regexp:jr,string:Fr};for(var Dt in lt)e.tokTypes["_"+Dt]=lt[Dt];var Bt,Mt=n("abstract boolean byte char class double enum export extends final float goto implements import int interface long native package private protected public short static super synchronized throws transient volatile"),zt=n("class enum extends super const export import"),Xt=n("implements interface let package private protected public static yield"),Nt=n("eval arguments"),Wt=n("break case catch continue debugger default do else finally for function if return switch throw try var while with null true false instanceof typeof void delete new in this"),Jt=/[\u1680\u180e\u2000-\u200a\u2028\u2029\u202f\u205f\u3000\ufeff]/,Pt="\xaa\xb5\xba\xc0-\xd6\xd8-\xf6\xf8-\u02c1\u02c6-\u02d1\u02e0-\u02e4\u02ec\u02ee\u0370-\u0374\u0376\u0377\u037a-\u037d\u0386\u0388-\u038a\u038c\u038e-\u03a1\u03a3-\u03f5\u03f7-\u0481\u048a-\u0527\u0531-\u0556\u0559\u0561-\u0587\u05d0-\u05ea\u05f0-\u05f2\u0620-\u064a\u066e\u066f\u0671-\u06d3\u06d5\u06e5\u06e6\u06ee\u06ef\u06fa-\u06fc\u06ff\u0710\u0712-\u072f\u074d-\u07a5\u07b1\u07ca-\u07ea\u07f4\u07f5\u07fa\u0800-\u0815\u081a\u0824\u0828\u0840-\u0858\u08a0\u08a2-\u08ac\u0904-\u0939\u093d\u0950\u0958-\u0961\u0971-\u0977\u0979-\u097f\u0985-\u098c\u098f\u0990\u0993-\u09a8\u09aa-\u09b0\u09b2\u09b6-\u09b9\u09bd\u09ce\u09dc\u09dd\u09df-\u09e1\u09f0\u09f1\u0a05-\u0a0a\u0a0f\u0a10\u0a13-\u0a28\u0a2a-\u0a30\u0a32\u0a33\u0a35\u0a36\u0a38\u0a39\u0a59-\u0a5c\u0a5e\u0a72-\u0a74\u0a85-\u0a8d\u0a8f-\u0a91\u0a93-\u0aa8\u0aaa-\u0ab0\u0ab2\u0ab3\u0ab5-\u0ab9\u0abd\u0ad0\u0ae0\u0ae1\u0b05-\u0b0c\u0b0f\u0b10\u0b13-\u0b28\u0b2a-\u0b30\u0b32\u0b33\u0b35-\u0b39\u0b3d\u0b5c\u0b5d\u0b5f-\u0b61\u0b71\u0b83\u0b85-\u0b8a\u0b8e-\u0b90\u0b92-\u0b95\u0b99\u0b9a\u0b9c\u0b9e\u0b9f\u0ba3\u0ba4\u0ba8-\u0baa\u0bae-\u0bb9\u0bd0\u0c05-\u0c0c\u0c0e-\u0c10\u0c12-\u0c28\u0c2a-\u0c33\u0c35-\u0c39\u0c3d\u0c58\u0c59\u0c60\u0c61\u0c85-\u0c8c\u0c8e-\u0c90\u0c92-\u0ca8\u0caa-\u0cb3\u0cb5-\u0cb9\u0cbd\u0cde\u0ce0\u0ce1\u0cf1\u0cf2\u0d05-\u0d0c\u0d0e-\u0d10\u0d12-\u0d3a\u0d3d\u0d4e\u0d60\u0d61\u0d7a-\u0d7f\u0d85-\u0d96\u0d9a-\u0db1\u0db3-\u0dbb\u0dbd\u0dc0-\u0dc6\u0e01-\u0e30\u0e32\u0e33\u0e40-\u0e46\u0e81\u0e82\u0e84\u0e87\u0e88\u0e8a\u0e8d\u0e94-\u0e97\u0e99-\u0e9f\u0ea1-\u0ea3\u0ea5\u0ea7\u0eaa\u0eab\u0ead-\u0eb0\u0eb2\u0eb3\u0ebd\u0ec0-\u0ec4\u0ec6\u0edc-\u0edf\u0f00\u0f40-\u0f47\u0f49-\u0f6c\u0f88-\u0f8c\u1000-\u102a\u103f\u1050-\u1055\u105a-\u105d\u1061\u1065\u1066\u106e-\u1070\u1075-\u1081\u108e\u10a0-\u10c5\u10c7\u10cd\u10d0-\u10fa\u10fc-\u1248\u124a-\u124d\u1250-\u1256\u1258\u125a-\u125d\u1260-\u1288\u128a-\u128d\u1290-\u12b0\u12b2-\u12b5\u12b8-\u12be\u12c0\u12c2-\u12c5\u12c8-\u12d6\u12d8-\u1310\u1312-\u1315\u1318-\u135a\u1380-\u138f\u13a0-\u13f4\u1401-\u166c\u166f-\u167f\u1681-\u169a\u16a0-\u16ea\u16ee-\u16f0\u1700-\u170c\u170e-\u1711\u1720-\u1731\u1740-\u1751\u1760-\u176c\u176e-\u1770\u1780-\u17b3\u17d7\u17dc\u1820-\u1877\u1880-\u18a8\u18aa\u18b0-\u18f5\u1900-\u191c\u1950-\u196d\u1970-\u1974\u1980-\u19ab\u19c1-\u19c7\u1a00-\u1a16\u1a20-\u1a54\u1aa7\u1b05-\u1b33\u1b45-\u1b4b\u1b83-\u1ba0\u1bae\u1baf\u1bba-\u1be5\u1c00-\u1c23\u1c4d-\u1c4f\u1c5a-\u1c7d\u1ce9-\u1cec\u1cee-\u1cf1\u1cf5\u1cf6\u1d00-\u1dbf\u1e00-\u1f15\u1f18-\u1f1d\u1f20-\u1f45\u1f48-\u1f4d\u1f50-\u1f57\u1f59\u1f5b\u1f5d\u1f5f-\u1f7d\u1f80-\u1fb4\u1fb6-\u1fbc\u1fbe\u1fc2-\u1fc4\u1fc6-\u1fcc\u1fd0-\u1fd3\u1fd6-\u1fdb\u1fe0-\u1fec\u1ff2-\u1ff4\u1ff6-\u1ffc\u2071\u207f\u2090-\u209c\u2102\u2107\u210a-\u2113\u2115\u2119-\u211d\u2124\u2126\u2128\u212a-\u212d\u212f-\u2139\u213c-\u213f\u2145-\u2149\u214e\u2160-\u2188\u2c00-\u2c2e\u2c30-\u2c5e\u2c60-\u2ce4\u2ceb-\u2cee\u2cf2\u2cf3\u2d00-\u2d25\u2d27\u2d2d\u2d30-\u2d67\u2d6f\u2d80-\u2d96\u2da0-\u2da6\u2da8-\u2dae\u2db0-\u2db6\u2db8-\u2dbe\u2dc0-\u2dc6\u2dc8-\u2dce\u2dd0-\u2dd6\u2dd8-\u2dde\u2e2f\u3005-\u3007\u3021-\u3029\u3031-\u3035\u3038-\u303c\u3041-\u3096\u309d-\u309f\u30a1-\u30fa\u30fc-\u30ff\u3105-\u312d\u3131-\u318e\u31a0-\u31ba\u31f0-\u31ff\u3400-\u4db5\u4e00-\u9fcc\ua000-\ua48c\ua4d0-\ua4fd\ua500-\ua60c\ua610-\ua61f\ua62a\ua62b\ua640-\ua66e\ua67f-\ua697\ua6a0-\ua6ef\ua717-\ua71f\ua722-\ua788\ua78b-\ua78e\ua790-\ua793\ua7a0-\ua7aa\ua7f8-\ua801\ua803-\ua805\ua807-\ua80a\ua80c-\ua822\ua840-\ua873\ua882-\ua8b3\ua8f2-\ua8f7\ua8fb\ua90a-\ua925\ua930-\ua946\ua960-\ua97c\ua984-\ua9b2\ua9cf\uaa00-\uaa28\uaa40-\uaa42\uaa44-\uaa4b\uaa60-\uaa76\uaa7a\uaa80-\uaaaf\uaab1\uaab5\uaab6\uaab9-\uaabd\uaac0\uaac2\uaadb-\uaadd\uaae0-\uaaea\uaaf2-\uaaf4\uab01-\uab06\uab09-\uab0e\uab11-\uab16\uab20-\uab26\uab28-\uab2e\uabc0-\uabe2\uac00-\ud7a3\ud7b0-\ud7c6\ud7cb-\ud7fb\uf900-\ufa6d\ufa70-\ufad9\ufb00-\ufb06\ufb13-\ufb17\ufb1d\ufb1f-\ufb28\ufb2a-\ufb36\ufb38-\ufb3c\ufb3e\ufb40\ufb41\ufb43\ufb44\ufb46-\ufbb1\ufbd3-\ufd3d\ufd50-\ufd8f\ufd92-\ufdc7\ufdf0-\ufdfb\ufe70-\ufe74\ufe76-\ufefc\uff21-\uff3a\uff41-\uff5a\uff66-\uffbe\uffc2-\uffc7\uffca-\uffcf\uffd2-\uffd7\uffda-\uffdc",Ht="\u0300-\u036f\u0483-\u0487\u0591-\u05bd\u05bf\u05c1\u05c2\u05c4\u05c5\u05c7\u0610-\u061a\u0620-\u0649\u0672-\u06d3\u06e7-\u06e8\u06fb-\u06fc\u0730-\u074a\u0800-\u0814\u081b-\u0823\u0825-\u0827\u0829-\u082d\u0840-\u0857\u08e4-\u08fe\u0900-\u0903\u093a-\u093c\u093e-\u094f\u0951-\u0957\u0962-\u0963\u0966-\u096f\u0981-\u0983\u09bc\u09be-\u09c4\u09c7\u09c8\u09d7\u09df-\u09e0\u0a01-\u0a03\u0a3c\u0a3e-\u0a42\u0a47\u0a48\u0a4b-\u0a4d\u0a51\u0a66-\u0a71\u0a75\u0a81-\u0a83\u0abc\u0abe-\u0ac5\u0ac7-\u0ac9\u0acb-\u0acd\u0ae2-\u0ae3\u0ae6-\u0aef\u0b01-\u0b03\u0b3c\u0b3e-\u0b44\u0b47\u0b48\u0b4b-\u0b4d\u0b56\u0b57\u0b5f-\u0b60\u0b66-\u0b6f\u0b82\u0bbe-\u0bc2\u0bc6-\u0bc8\u0bca-\u0bcd\u0bd7\u0be6-\u0bef\u0c01-\u0c03\u0c46-\u0c48\u0c4a-\u0c4d\u0c55\u0c56\u0c62-\u0c63\u0c66-\u0c6f\u0c82\u0c83\u0cbc\u0cbe-\u0cc4\u0cc6-\u0cc8\u0cca-\u0ccd\u0cd5\u0cd6\u0ce2-\u0ce3\u0ce6-\u0cef\u0d02\u0d03\u0d46-\u0d48\u0d57\u0d62-\u0d63\u0d66-\u0d6f\u0d82\u0d83\u0dca\u0dcf-\u0dd4\u0dd6\u0dd8-\u0ddf\u0df2\u0df3\u0e34-\u0e3a\u0e40-\u0e45\u0e50-\u0e59\u0eb4-\u0eb9\u0ec8-\u0ecd\u0ed0-\u0ed9\u0f18\u0f19\u0f20-\u0f29\u0f35\u0f37\u0f39\u0f41-\u0f47\u0f71-\u0f84\u0f86-\u0f87\u0f8d-\u0f97\u0f99-\u0fbc\u0fc6\u1000-\u1029\u1040-\u1049\u1067-\u106d\u1071-\u1074\u1082-\u108d\u108f-\u109d\u135d-\u135f\u170e-\u1710\u1720-\u1730\u1740-\u1750\u1772\u1773\u1780-\u17b2\u17dd\u17e0-\u17e9\u180b-\u180d\u1810-\u1819\u1920-\u192b\u1930-\u193b\u1951-\u196d\u19b0-\u19c0\u19c8-\u19c9\u19d0-\u19d9\u1a00-\u1a15\u1a20-\u1a53\u1a60-\u1a7c\u1a7f-\u1a89\u1a90-\u1a99\u1b46-\u1b4b\u1b50-\u1b59\u1b6b-\u1b73\u1bb0-\u1bb9\u1be6-\u1bf3\u1c00-\u1c22\u1c40-\u1c49\u1c5b-\u1c7d\u1cd0-\u1cd2\u1d00-\u1dbe\u1e01-\u1f15\u200c\u200d\u203f\u2040\u2054\u20d0-\u20dc\u20e1\u20e5-\u20f0\u2d81-\u2d96\u2de0-\u2dff\u3021-\u3028\u3099\u309a\ua640-\ua66d\ua674-\ua67d\ua69f\ua6f0-\ua6f1\ua7f8-\ua800\ua806\ua80b\ua823-\ua827\ua880-\ua881\ua8b4-\ua8c4\ua8d0-\ua8d9\ua8f3-\ua8f7\ua900-\ua909\ua926-\ua92d\ua930-\ua945\ua980-\ua983\ua9b3-\ua9c0\uaa00-\uaa27\uaa40-\uaa41\uaa4c-\uaa4d\uaa50-\uaa59\uaa7b\uaae0-\uaae9\uaaf2-\uaaf3\uabc0-\uabe1\uabec\uabed\uabf0-\uabf9\ufb20-\ufb28\ufe00-\ufe0f\ufe20-\ufe26\ufe33\ufe34\ufe4d-\ufe4f\uff10-\uff19\uff3f",$t=new RegExp("["+Pt+"]"),_t=new RegExp("["+Pt+Ht+"]"),Gt=/[\n\r\u2028\u2029]/,Kt=/\r\n|[\n\r\u2028\u2029]/g,Qt=e.isIdentifierStart=function(e){return 65>e?36===e:91>e?!0:97>e?95===e:123>e?!0:e>=170&&$t.test(String.fromCharCode(e))},Yt=e.isIdentifierChar=function(e){return 48>e?36===e:58>e?!0:65>e?!1:91>e?!0:97>e?95===e:123>e?!0:e>=170&&_t.test(String.fromCharCode(e))},Zt={kind:"loop"},en={kind:"switch"}});
-
- var binaryOperators = {
- '+': '_add',
- '-': '_subtract',
- '*': '_multiply',
- '/': '_divide',
- '%': '_modulo',
- '==': 'equals',
- '!=': 'equals'
- };
-
- var unaryOperators = {
- '-': '_negate',
- '+': null
- };
-
- var fields = Base.each(
- ['add', 'subtract', 'multiply', 'divide', 'modulo', 'negate'],
- function(name) {
- this['_' + name] = '#' + name;
- },
- {}
- );
- paper.Point.inject(fields);
- paper.Size.inject(fields);
- paper.Color.inject(fields);
-
- function _$_(left, operator, right) {
- var handler = binaryOperators[operator];
- if (left && left[handler]) {
- var res = left[handler](right);
- return operator === '!=' ? !res : res;
- }
- switch (operator) {
- case '+': return left + right;
- case '-': return left - right;
- case '*': return left * right;
- case '/': return left / right;
- case '%': return left % right;
- case '==': return left == right;
- case '!=': return left != right;
- }
- }
-
- function $_(operator, value) {
- var handler = unaryOperators[operator];
- if (handler && value && value[handler])
- return value[handler]();
- switch (operator) {
- case '+': return +value;
- case '-': return -value;
- }
- }
-
- function compile(code) {
-
- var insertions = [];
-
- function getOffset(offset) {
- for (var i = 0, l = insertions.length; i < l; i++) {
- var insertion = insertions[i];
- if (insertion[0] >= offset)
- break;
- offset += insertion[1];
- }
- return offset;
- }
-
- function getCode(node) {
- return code.substring(getOffset(node.range[0]),
- getOffset(node.range[1]));
- }
-
- function replaceCode(node, str) {
- var start = getOffset(node.range[0]),
- end = getOffset(node.range[1]);
- var insert = 0;
- for (var i = insertions.length - 1; i >= 0; i--) {
- if (start > insertions[i][0]) {
- insert = i + 1;
- break;
- }
- }
- insertions.splice(insert, 0, [start, str.length - end + start]);
- code = code.substring(0, start) + str + code.substring(end);
- }
-
- function walkAST(node, parent) {
- if (!node)
- return;
- for (var key in node) {
- if (key === 'range')
- continue;
- var value = node[key];
- if (Array.isArray(value)) {
- for (var i = 0, l = value.length; i < l; i++)
- walkAST(value[i], node);
- } else if (value && typeof value === 'object') {
- walkAST(value, node);
- }
- }
- switch (node && node.type) {
- case 'BinaryExpression':
- if (node.operator in binaryOperators
- && node.left.type !== 'Literal') {
- var left = getCode(node.left),
- right = getCode(node.right);
- replaceCode(node, '_$_(' + left + ', "' + node.operator
- + '", ' + right + ')');
- }
- break;
- case 'AssignmentExpression':
- if (/^.=$/.test(node.operator)
- && node.left.type !== 'Literal') {
- var left = getCode(node.left),
- right = getCode(node.right);
- replaceCode(node, left + ' = _$_(' + left + ', "'
- + node.operator[0] + '", ' + right + ')');
- }
- break;
- case 'UpdateExpression':
- if (!node.prefix && !(parent && (
- parent.type === 'BinaryExpression'
- && /^[=!<>]/.test(parent.operator)
- || parent.type === 'MemberExpression'
- && parent.computed))) {
- var arg = getCode(node.argument);
- replaceCode(node, arg + ' = _$_(' + arg + ', "'
- + node.operator[0] + '", 1)');
- }
- break;
- case 'UnaryExpression':
- if (node.operator in unaryOperators
- && node.argument.type !== 'Literal') {
- var arg = getCode(node.argument);
- replaceCode(node, '$_("' + node.operator + '", '
- + arg + ')');
- }
- break;
- }
- }
- walkAST(scope.acorn.parse(code, { ranges: true }));
- return code;
- }
-
- function evaluate(code, scope) {
- paper = scope;
- var view = scope.project && scope.project.view,
- res;
- with (scope) {
- (function() {
- var onActivate, onDeactivate, onEditOptions,
- onMouseDown, onMouseUp, onMouseDrag, onMouseMove,
- onKeyDown, onKeyUp, onFrame, onResize;
- code = compile(code);
- if (root.InstallTrigger) {
- var handle = PaperScript.handleException;
- if (!handle) {
- handle = PaperScript.handleException = function(e) {
- throw e.lineNumber >= lineNumber
- ? new Error(e.message, e.fileName,
- e.lineNumber - lineNumber)
- : e;
- }
- var lineNumber = new Error().lineNumber;
- lineNumber += (new Error().lineNumber - lineNumber) * 3;
- }
- try {
- res = eval(';' + code);
- } catch (e) {
- handle(e);
- }
- } else {
- res = eval(code);
- }
- if (/on(?:Key|Mouse)(?:Up|Down|Move|Drag)/.test(code)) {
- Base.each(paper.Tool.prototype._events, function(key) {
- var value = eval(key);
- if (value) {
- scope.getTool()[key] = value;
- }
- });
- }
- if (view) {
- view.setOnResize(onResize);
- view.fire('resize', {
- size: view.size,
- delta: new Point()
- });
- if (onFrame)
- view.setOnFrame(onFrame);
- view.draw();
- }
- }).call(scope);
- }
- return res;
- }
-
- function load() {
- Base.each(document.getElementsByTagName('script'), function(script) {
- if (/^text\/(?:x-|)paperscript$/.test(script.type)
- && !script.getAttribute('data-paper-ignore')) {
- var canvas = PaperScope.getAttribute(script, 'canvas'),
- scope = PaperScope.get(canvas)
- || new PaperScope(script).setup(canvas),
- src = script.src;
- if (src) {
- paper.Http.request('get', src, function(code) {
- evaluate(code, scope);
- });
- } else {
- evaluate(script.innerHTML, scope);
- }
- script.setAttribute('data-paper-ignore', true);
- }
- }, this);
- }
-
- if (document.readyState === 'complete') {
- setTimeout(load);
- } else {
- paper.DomEvent.add(window, { load: load });
- }
-
- return PaperScript = {
- compile: compile,
- evaluate: evaluate,
- load: load,
- lineNumberBase: 0
- };
-
-})(this);
--- a/src/hdalab/static/hdalab/lib/renkan/renkan.min.map Fri Jul 18 13:29:53 2014 +0200
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,1 +0,0 @@
-{"version":3,"file":"renkan.min.js","sources":["../../js/main.js","../../js/models.js","../../js/defaults.js","../../js/i18n.js","../../js/full-json.js","../../js/ldtjson-bin.js","../../js/list-bin.js","../../js/wikipedia-bin.js","paper-renderer.js"],"names":["root","Rkns","$","jQuery","_","pickerColors","__renkans","_BaseBin","_renkan","_opts","this","renkan","find","hide","addClass","appendTo","title_icon_$","_this","attr","href","title","translate","html","click","destroy","length","slideDown","resizeBins","refresh","count_$","title_$","main_$","auto_refresh","window","setInterval","prototype","detach","Renkan","push","options","defaults","property_files","each","f","getJSON","data","properties","concat","read_only","editor_mode","project","Models","Project","user_id","current_user","container","template","tabs","search_engines","current_user_list","UsersList","on","renderer","redrawUsers","colorPicker","_tmpl","map","c","join","show_editor","Renderer","Scene","search","_select","_input","_form","_search","type","Search","_key","key","getSearchTitle","className","getBgClass","_el","setSearchEngine","submit","val","search_engine","mouseenter","mouseleave","bins","_bin","Bin","elementDropped","_mainDiv","siblings","is","slideUp","_t","_models","get","where","uri","_model","highlightModel","mouseout","unhighlightAll","dragDrop","err","e","preventDefault","touch","originalEvent","changedTouches","off","canvas_$","offset","w","width","h","height","pageX","left","pageY","top","onMouseMove","div","document","createElement","appendChild","cloneNode","dropData","text/html","innerHTML","onMouseDown","onMouseUp","dataTransfer","setData","resize","lastsearch","lastval","Utils","regexpFromTextOrArray","source","tab","render","_text","i18n","language","substr","onStatusChange","_d","outerHeight","css","getUUID4","replace","r","Math","random","v","toString","getUID","pad","n","Date","ID_AUTO_INCREMENT","ID_BASE","getUTCFullYear","getUTCMonth","getUTCDate","_base","_n","_uidbase","getFullURL","url","test","img","Image","src","res","inherit","_baseClass","_callbefore","_class","apply","Array","slice","call","arguments","_init","_initialized","extend","replaceText","makeReplaceFunc","l","k","charsrx","txt","toLowerCase","remrx","j","remsrc","charsub","getSource","inp","removeChars","String","fromCharCode","RegExp","_textOrArray","testrx","replacerx","isempty","_replace","text","_MIN_DRAG_DISTANCE","_NODE_BUTTON_WIDTH","_EDGE_BUTTON_INNER","_EDGE_BUTTON_OUTER","_CLICKMODE_ADDNODE","_CLICKMODE_STARTEDGE","_CLICKMODE_ENDEDGE","_NODE_SIZE_STEP","LN2","_MIN_SCALE","_MAX_SCALE","_MOUSEMOVE_RATE","_DOUBLETAP_DELAY","_DOUBLETAP_DISTANCE","_USER_PLACEHOLDER","color","default_user_color","_BOOKMARKLET_CODE","shortenText","_maxlength","drawEditBox","_options","_coords","_path","_xmargin","_selector","tooltip_width","tooltip_padding","_height","_isLeft","x","paper","view","center","_left","tooltip_arrow_length","_right","_top","y","size","tooltip_margin","max","tooltip_arrow_width","min","_bottom","segments","point","add","closed","fillColor","GradientColor","Gradient","tooltip_top_color","tooltip_bottom_color","Backbone","obj","guid","RenkanModel","RelationalModel","idAttribute","constructor","_id","id","description","prepare","validate","addReference","_propName","_list","_default","_element","User","toJSON","Node","relations","HasOne","relatedModel","created_by","position","image","clip_path","Edge","from","to","View","isArray","zoom_level","RosterUser","HasMany","reverseRelation","includeInJSON","addUser","_props","_user","findOrCreate","addNode","_node","addEdge","_edge","addView","_view","removeNode","remove","removeEdge","_project","users","nodes","edges","views","_item","initialize","filter","Model","site_id","Collection","model","navigator","userLanguage","static_url","show_bins","snapshot_mode","show_top_bar","size_bug_fix","force_resize","allow_double_click","zoom_on_scroll","element_delete_delay","autoscale_padding","default_view","show_search_field","show_user_list","user_name_editable","user_color_editable","show_save_button","show_export_button","show_open_button","show_addnode_button","show_addedge_button","show_bookmarklet","show_fullscreen_button","home_button_url","home_button_title","show_minimap","minimap_width","minimap_height","minimap_padding","minimap_background_color","minimap_border_color","minimap_highlight_color","minimap_highlight_weight","buttons_background","buttons_label_color","buttons_label_font_size","show_node_circles","clip_node_images","node_images_fill_mode","node_size_base","node_stroke_width","selected_node_stroke_width","node_fill_color","highlighted_node_fill_color","node_label_distance","node_label_max_length","label_untitled_nodes","edge_stroke_width","selected_edge_stroke_width","edge_label_distance","edge_label_max_length","edge_arrow_length","edge_arrow_width","edge_gap_in_bundles","label_untitled_edges","tooltip_border_color","tooltip_border_width","show_node_editor_uri","show_node_editor_description","show_node_editor_size","show_node_editor_color","show_node_editor_image","show_node_editor_creator","uploaded_image_max_kb","show_node_tooltip_uri","show_node_tooltip_description","show_node_tooltip_color","show_node_tooltip_image","show_node_tooltip_creator","show_edge_editor_uri","show_edge_editor_color","show_edge_editor_direction","show_edge_editor_nodes","show_edge_editor_creator","show_edge_tooltip_uri","show_edge_tooltip_color","show_edge_tooltip_nodes","show_edge_tooltip_creator","fr","Edit Node","Edit Edge","Title:","URI:","Description:","From:","To:","Image URL:","Choose Image File:","Full Screen","Add Node","Add Edge","Save Project","Open Project","Auto-save enabled","Connection lost","Created by:","Zoom In","Zoom Out","Edit","Remove","Cancel deletion","Link to another node","Enlarge","Shrink","Click on the background canvas to add a node","Click on a first node to start the edge","Click on a second node to complete the edge","Wikipedia","Wikipedia in ","French","English","Japanese","Untitled project","Lignes de Temps","Loading, please wait","Edge color:","Node color:","Choose color","Change edge direction","Do you really wish to remove node ","Do you really wish to remove edge ","This file is not an image","Image size must be under ","Size:","KB","Choose from vocabulary:","SKOS Documentation properties","has note","has example","has definition","SKOS Semantic relations","has broader","has narrower","has related","Dublin Core Metadata","has contributor","covers","created by","has date","published by","has source","has subject","Dragged resource","Search the Web","Search in Bins","Close bin","Refresh bin","(untitled)","Select contents:","Drag items from this website, drop them in Renkan","Drag this button to your bookmark bar. When on a third-party website, click it to enable drag-and-drop from the website to Renkan.","jsonIO","_proj","http_method","_load","redrawActive","_data","set","autoScale","_save","ajax","contentType","JSON","stringify","success","_thrSave","throttle","setTimeout","Ldt","ProjectBin","ldt_type","Resclass","console","error","tagTemplate","annotationTemplate","proj_id","project_id","ldt_platform","searchbase","highlight","_e","escape","convertTC","_ms","_res","_totalSeconds","abs","floor","_hours","_minutes","_seconds","_html","_projtitle","meta","count","tags","_tag","_title","htitle","encodedtitle","encodeURIComponent","annotations","_annotation","_description","content","_duration","end","begin","_img","hdescription","start","duration","mediaid","media","annotationid","show","dataType","lang","_q","ResultsBin","segmentTemplate","max_results","highlightrx","objects","_segment","abstract","_begin","start_ts","_end","iri_id","element_id","format","q","limit","ResourceList","resultTemplate","list","trim","_match","match","langs","en","ja","query","_result","encodeURI","snippet","define","_BaseRepresentation","_renderer","_changeBinding","redraw","_removeBinding","removeRepresentation","defer","_selectBinding","select","_unselectBinding","unselect","_super","_func","moveTo","trigger","unhighlight","mousedown","mouseup","getUtils","getRenderer","requtils","BaseRepresentation","_BaseButton","_pos","sector","_newTarget","source_representation","NodeRepr","node_layer","activate","circle","Path","Circle","__representation","strokeWidth","h_ratio","labels_$","normal_buttons","NodeEditButton","NodeRemoveButton","NodeLinkButton","NodeEnlargeButton","NodeShrinkButton","pending_delete_buttons","NodeRevertButton","all_buttons","i","active_buttons","last_circle_radius","minimap","minimap_circle","miniframe","node_group","addChild","_dontRedrawEdges","_model_coords","Point","_baseRadius","exp","is_dragging","paper_coords","toPaperCoords","circle_radius","scale","forEach","b","setSectorSize","node_image","subtract","image_delta","multiply","old_act_btn","opacity","dashArray","selected","isEditable","highlighted","_color","strokeColor","_pc","lastImage","showImage","minipos","toMinimapCoords","miniradius","minisize","Size","fitBounds","ed","edge","repr","getRepresentationByModel","from_representation","to_representation","_image","image_cache","clipPath","hasClipPath","_clip","baseRadius","centerPoint","instructions","lastCoords","minX","Infinity","minY","maxX","maxY","transformCoords","tabc","relative","newCoords","parseFloat","isY","instr","coords","lineTo","cubicCurveTo","quadraticCurveTo","_raster","Raster","locked","Group","clipped","_circleClip","divide","throttledPaperDraw","paperShift","_delta","openEditor","removeRepresentationsOfType","_editor","addRepresentation","draw","_uri","removeClass","undefined","textToReplace","hlvalue","saveCoords","toModelCoords","_event","_isTouch","unselectAll","click_target","edge_layer","bundle","addToBundles","line","arrow","arrow_angle","EdgeEditButton","EdgeRemoveButton","EdgeRevertButton","minimap_line","_p0a","_p1a","_v","_r","_u","_ortho","_group_pos","getPosition","_p0b","_p1b","_a","angle","_textdelta","_handle","handleIn","handleOut","rotate","_textpos","transform","-moz-transform","-webkit-transform","text_angle","reject","TempEdge","_p0","_p1","end_pos","_c","_hitResult","hitTest","findTarget","_endDrag","item","_target","_destmodel","_BaseEditor","buttons_layer","editor_block","_pts","range","editor_$","BaseEditor","NodeEditor","readOnlyTemplate","_created_by","_template","_image_placeholder","_size","node","has_creator","short_uri","image_placeholder","created_by_color","created_by_title","closeEditor","onFieldChange","keyCode","change","files","FileReader","alert","onload","target","result","readAsDataURL","focus","_picker","hover","shiftSize","_newsize","titlehtml","load","EdgeEditor","_from_model","_to_model","from_title","to_title","from_color","to_color","BaseButton","_NodeButton","sectorInner","lastSectorInner","drawSector","startAngle","endAngle","imageName","NodeButton","delid","delete_list","time","valueOf","confirm","unset","_off","_point","addTempEdge","MiniFrame","filesaver","representations","notif_$","setup","initialScale","totalScroll","mouse_down","selected_target","Layer","background_layer","topleft","bounds","bottomRight","rectangle","Rectangle","cliprectangle","bundles","click_mode","_allowScroll","_originalScale","_zooming","_lastTapX","_lastTapY","icon_cache","imgname","throttledMouseMove","mousemove","mousewheel","onScroll","touchstart","_touches","touches","_lastTap","pow","onDoubleClick","touchmove","_newScale","_scaleRatio","_newOffset","setScale","touchend","dblclick","dragover","dragenter","dragleave","drop","types","t","getData","parse","bindClick","selector","fname","evt","last","isNaN","parseInt","fadeIn","delay","fadeOut","mouseover","onResize","_viewSize","parent","_thRedraw","addRepresentations","_thRedrawUsers","el","_delay","fixSize","$cpwrapper","$cplist","$this","rxs","_now","d","findWhere","delete_scheduled","rescaleMinimap","_autoscale","viewSize","_repr","_inR","_outR","_startAngle","_endAngle","_padding","_imgname","_caption","_startRads","PI","_endRads","_startdx","sin","_startdy","cos","_startXIn","_startYIn","_startXOut","_startYOut","_enddx","_enddy","_endXIn","_endYIn","_endXOut","_endYOut","_centerR","_centerRads","_centerX","_centerY","_centerXIn","_centerXOut","_centerYIn","_centerYOut","_textX","_textY","arcTo","PointText","characterStyle","fontSize","paragraphStyle","justification","visible","_visible","_restPos","_grp","_imgdelta","_currentPos","_edgeRepr","_bundle","_er","_dir","indexOf","savebtn","tip","_offset","force_view","_xx","_yy","_minx","_miny","_maxx","_maxy","_scale","at","redrawMiniframe","bottomright","_type","RendererType","_collection","userTemplate","allUsers","models","ulistHtml","$userpanel","$name","$cpitems","$colorsquare","$input","blur","empty","name","background","_representation","_representations","_from","_tmpEdge","last_point","_scrolldelta","SQRT2","SQRT1_2","defaultDropHandler","newNode","tweetdiv","_svgimgs","_svgpaths","_imgs","_as","split","fields","drop_enhancer","jsondata","drop_handler","_nodedata","fullScreen","_isFull","mozFullScreen","webkitIsFullScreen","_requestMethods","_cancelMethods","zoomOut","zoomIn","addNodeBtn","addEdgeBtn","exportProject","projectJSON","projectId","fileNameToSaveAs","space_id","objId","idsMap","projectJSONStr","blob","Blob","foldBins","foldBinsButton","animate","save","open","require","config","paths","jquery","underscore","startRenkan"],"mappings":"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","sourcesContent":["\n/* Declaring the Renkan Namespace Rkns and Default values */\n\n(function(root) {\n\n\"use strict\";\n\nif (typeof root.Rkns !== \"object\") {\n root.Rkns = {};\n}\n\nvar Rkns = root.Rkns;\nvar $ = Rkns.$ = root.jQuery;\nvar _ = Rkns._ = root._;\n\nRkns.pickerColors = [\"#8f1919\", \"#a80000\", \"#d82626\", \"#ff0000\", \"#e87c7c\", \"#ff6565\", \"#f7d3d3\", \"#fecccc\",\n \"#8f5419\", \"#a85400\", \"#d87f26\", \"#ff7f00\", \"#e8b27c\", \"#ffb265\", \"#f7e5d3\", \"#fee5cc\",\n \"#8f8f19\", \"#a8a800\", \"#d8d826\", \"#feff00\", \"#e8e87c\", \"#feff65\", \"#f7f7d3\", \"#fefecc\",\n \"#198f19\", \"#00a800\", \"#26d826\", \"#00ff00\", \"#7ce87c\", \"#65ff65\", \"#d3f7d3\", \"#ccfecc\",\n \"#198f8f\", \"#00a8a8\", \"#26d8d8\", \"#00feff\", \"#7ce8e8\", \"#65feff\", \"#d3f7f7\", \"#ccfefe\",\n \"#19198f\", \"#0000a8\", \"#2626d8\", \"#0000ff\", \"#7c7ce8\", \"#6565ff\", \"#d3d3f7\", \"#ccccfe\",\n \"#8f198f\", \"#a800a8\", \"#d826d8\", \"#ff00fe\", \"#e87ce8\", \"#ff65fe\", \"#f7d3f7\", \"#feccfe\",\n \"#000000\", \"#242424\", \"#484848\", \"#6d6d6d\", \"#919191\", \"#b6b6b6\", \"#dadada\", \"#ffffff\"];\n\nRkns.__renkans = [];\n\nvar _BaseBin = Rkns._BaseBin = function(_renkan, _opts) {\n if (typeof _renkan !== \"undefined\") {\n this.renkan = _renkan;\n this.renkan.$.find(\".Rk-Bin-Main\").hide();\n this.$ = Rkns.$('<li>')\n .addClass(\"Rk-Bin\")\n .appendTo(_renkan.$.find(\".Rk-Bin-List\"));\n this.title_icon_$ = Rkns.$('<span>')\n .addClass(\"Rk-Bin-Title-Icon\")\n .appendTo(this.$);\n\n var _this = this;\n\n Rkns.$('<a>')\n .attr({\n href: \"#\",\n title: _renkan.translate(\"Close bin\")\n })\n .addClass(\"Rk-Bin-Close\")\n .html('×')\n .appendTo(this.$)\n .click(function() {\n _this.destroy();\n if (!_renkan.$.find(\".Rk-Bin-Main:visible\").length) {\n _renkan.$.find(\".Rk-Bin-Main:last\").slideDown();\n }\n _renkan.resizeBins();\n return false;\n });\n Rkns.$('<a>')\n .attr({\n href: \"#\",\n title: _renkan.translate(\"Refresh bin\")\n })\n .addClass(\"Rk-Bin-Refresh\")\n .appendTo(this.$)\n .click(function() {\n _this.refresh();\n return false;\n });\n this.count_$ = Rkns.$('<div>')\n .addClass(\"Rk-Bin-Count\")\n .appendTo(this.$);\n this.title_$ = Rkns.$('<h2>')\n .addClass(\"Rk-Bin-Title\")\n .appendTo(this.$);\n this.main_$ = Rkns.$('<div>')\n .addClass(\"Rk-Bin-Main\")\n .appendTo(this.$)\n .html('<h4 class=\"Rk-Bin-Loading\">' + _renkan.translate(\"Loading, please wait\") + '</h4>');\n this.title_$.html(_opts.title || '(new bin)');\n this.renkan.resizeBins();\n\n if (_opts.auto_refresh) {\n window.setInterval(function() {\n _this.refresh();\n },_opts.auto_refresh);\n }\n }\n};\n\n_BaseBin.prototype.destroy = function() {\n this.$.detach();\n this.renkan.resizeBins();\n};\n\n/* Point of entry */\n\nvar Renkan = Rkns.Renkan = function(_opts) {\n var _this = this;\n\n Rkns.__renkans.push(this);\n\n this.options = _.defaults(_opts, Rkns.defaults);\n\n _(this.options.property_files).each(function(f) {\n Rkns.$.getJSON(f, function(data) {\n _this.options.properties = _this.options.properties.concat(data);\n });\n });\n\n this.read_only = this.options.read_only || !this.options.editor_mode;\n\n this.project = new Rkns.Models.Project();\n\n if (typeof this.options.user_id !== \"undefined\") {\n this.current_user = this.options.user_id;\n }\n this.$ = Rkns.$(\"#\" + this.options.container);\n this.$\n .addClass(\"Rk-Main\")\n .html(this.template(this));\n\n this.tabs = [];\n this.search_engines = [];\n\n this.current_user_list = new Rkns.Models.UsersList();\n\n this.current_user_list.on(\"add remove\", function() {\n if (this.renderer) {\n this.renderer.redrawUsers();\n }\n });\n\n this.colorPicker = (function() {\n var _tmpl = _.template('<li data-color=\"<%=c%>\" style=\"background: <%=c%>\"></li>');\n return '<ul class=\"Rk-Edit-ColorPicker\">' + Rkns.pickerColors.map(function(c) { return _tmpl({c:c});}).join(\"\") + '</ul>';\n })();\n\n if (this.options.show_editor) {\n this.renderer = new Rkns.Renderer.Scene(this);\n }\n\n if (!this.options.search.length) {\n this.$.find(\".Rk-Web-Search-Form\").detach();\n } else {\n var _tmpl = _.template('<li class=\"<%= className %>\" data-key=\"<%= key %>\"><%= title %></li>'),\n _select = this.$.find(\".Rk-Search-List\"),\n _input = this.$.find(\".Rk-Web-Search-Input\"),\n _form = this.$.find(\".Rk-Web-Search-Form\");\n _(this.options.search).each(function(_search, _key) {\n if (Rkns[_search.type] && Rkns[_search.type].Search) {\n _this.search_engines.push(new Rkns[_search.type].Search(_this, _search));\n }\n });\n _select.html(\n _(this.search_engines).map(function(_search, _key) {\n return _tmpl({\n key: _key,\n title: _search.getSearchTitle(),\n className: _search.getBgClass()\n });\n }).join(\"\")\n );\n _select.find(\"li\").click(function() {\n var _el = Rkns.$(this);\n _this.setSearchEngine(_el.attr(\"data-key\"));\n _form.submit();\n });\n _form.submit(function() {\n if (_input.val()) {\n var _search = _this.search_engine;\n _search.search(_input.val());\n }\n return false;\n });\n this.$.find(\".Rk-Search-Current\").mouseenter(\n function() { _select.slideDown(); }\n );\n this.$.find(\".Rk-Search-Select\").mouseleave(\n function() { _select.hide(); }\n );\n this.setSearchEngine(0);\n }\n _(this.options.bins).each(function(_bin) {\n if (Rkns[_bin.type] && Rkns[_bin.type].Bin) {\n _this.tabs.push(new Rkns[_bin.type].Bin(_this, _bin));\n }\n });\n\n var elementDropped = false;\n\n this.$.find(\".Rk-Bins\")\n .on(\"click\",\".Rk-Bin-Title,.Rk-Bin-Title-Icon\", function() {\n var _mainDiv = Rkns.$(this).siblings(\".Rk-Bin-Main\");\n if (_mainDiv.is(\":hidden\")) {\n _this.$.find(\".Rk-Bin-Main\").slideUp();\n _mainDiv.slideDown();\n }\n });\n\n if (this.options.show_editor) {\n\n this.$.find(\".Rk-Bins\").on(\"mouseover\", \".Rk-Bin-Item\", function(_e) {\n var _t = Rkns.$(this);\n if (_t && $(_t).attr(\"data-uri\")) {\n var _models = _this.project.get(\"nodes\").where({\n uri: $(_t).attr(\"data-uri\")\n });\n _(_models).each(function(_model) {\n _this.renderer.highlightModel(_model);\n });\n }\n }).mouseout(function() {\n _this.renderer.unhighlightAll();\n }).on(\"mousemove\", \".Rk-Bin-Item\", function(e) {\n try {\n this.dragDrop();\n }\n catch(err) {}\n }).on(\"touchstart\", \".Rk-Bin-Item\", function(e) {\n elementDropped = false;\n }).on(\"touchmove\", \".Rk-Bin-Item\", function(e) {\n e.preventDefault();\n var touch = e.originalEvent.changedTouches[0],\n off = _this.renderer.canvas_$.offset(),\n w = _this.renderer.canvas_$.width(),\n h = _this.renderer.canvas_$.height();\n if (touch.pageX >= off.left && touch.pageX < (off.left + w) && touch.pageY >= off.top && touch.pageY < (off.top + h)) {\n if (elementDropped) {\n _this.renderer.onMouseMove(touch, true);\n } else {\n elementDropped = true;\n var div = document.createElement('div');\n div.appendChild(this.cloneNode(true));\n _this.renderer.dropData({\"text/html\": div.innerHTML}, touch);\n _this.renderer.onMouseDown(touch, true);\n }\n }\n }).on(\"touchend\", \".Rk-Bin-Item\", function(e) {\n if (elementDropped) {\n _this.renderer.onMouseUp(e.originalEvent.changedTouches[0], true);\n }\n elementDropped = false;\n }).on(\"dragstart\", \".Rk-Bin-Item\", function(e) {\n var div = document.createElement('div');\n div.appendChild(this.cloneNode(true));\n try {\n e.originalEvent.dataTransfer.setData(\"text/html\",div.innerHTML);\n }\n catch(err) {\n e.originalEvent.dataTransfer.setData(\"text\",div.innerHTML);\n }\n });\n\n }\n\n Rkns.$(window).resize(function() {\n _this.resizeBins();\n });\n\n var lastsearch = false, lastval = '';\n\n this.$.find(\".Rk-Bins-Search-Input\").on(\"change keyup paste input\", function() {\n var val = Rkns.$(this).val();\n if (val === lastval) {\n return;\n }\n var search = Rkns.Utils.regexpFromTextOrArray(val.length > 1 ? val: null);\n if (search.source === lastsearch) {\n return;\n }\n lastsearch = search.source;\n _(_this.tabs).each(function(tab) {\n tab.render(search);\n });\n\n });\n this.$.find(\".Rk-Bins-Search-Form\").submit(function() {\n return false;\n });\n\n};\n\nRenkan.prototype.template = _.template(\n '<% if (options.show_bins) { %><div class=\"Rk-Bins\"><div class=\"Rk-Bins-Head\"><h2 class=\"Rk-Bins-Title\"><%- translate(\"Select contents:\")%></h2>' +\n '<form class=\"Rk-Web-Search-Form Rk-Search-Form\"><input class=\"Rk-Web-Search-Input Rk-Search-Input\" type=\"search\" placeholder=\"<%- translate(\"Search the Web\") %>\" />' +\n '<div class=\"Rk-Search-Select\"><div class=\"Rk-Search-Current\"></div><ul class=\"Rk-Search-List\"></ul></div>' +\n '<input type=\"submit\" value=\"\" class=\"Rk-Web-Search-Submit Rk-Search-Submit\" title=\"<%- translate(\"Search the Web\") %>\" /></form>' +\n '<form class=\"Rk-Bins-Search-Form Rk-Search-Form\"><input class=\"Rk-Bins-Search-Input Rk-Search-Input\" type=\"search\" placeholder=\"<%- translate(\"Search in Bins\") %>\" />' +\n '<input type=\"submit\" value=\"\" class=\"Rk-Bins-Search-Submit Rk-Search-Submit\" title=\"<%- translate(\"Search in Bins\") %>\" /></form></div>' +\n '<ul class=\"Rk-Bin-List\"></ul></div><% } %>' +\n '<% if (options.show_editor) { %><div class=\"Rk-Render Rk-Render-<% if (options.show_bins) { %>Panel<% } else { %>Full<% } %>\"></div><% } %>'\n);\n\nRenkan.prototype.translate = function(_text) {\n if (Rkns.i18n[this.options.language] && Rkns.i18n[this.options.language][_text]) {\n return Rkns.i18n[this.options.language][_text];\n }\n if (this.options.language.length > 2 && Rkns.i18n[this.options.language.substr(0,2)] && Rkns.i18n[this.options.language.substr(0,2)][_text]) {\n return Rkns.i18n[this.options.language.substr(0,2)][_text];\n }\n return _text;\n};\n\nRenkan.prototype.onStatusChange = function() {\n this.renderer.onStatusChange();\n};\n\nRenkan.prototype.setSearchEngine = function(_key) {\n this.search_engine = this.search_engines[_key];\n this.$.find(\".Rk-Search-Current\").attr(\"class\",\"Rk-Search-Current \" + this.search_engine.getBgClass());\n};\n\nRenkan.prototype.resizeBins = function() {\n var _d = + this.$.find(\".Rk-Bins-Head\").outerHeight();\n this.$.find(\".Rk-Bin-Title:visible\").each(function() {\n _d += Rkns.$(this).outerHeight();\n });\n this.$.find(\".Rk-Bin-Main\").css({\n height: this.$.find(\".Rk-Bins\").height() - _d\n });\n};\n\n/* Utility functions */\nvar getUUID4 = function() {\n return 'xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx'.replace(/[xy]/g, function(c) {\n var r = Math.random()*16|0, v = c === 'x' ? r : (r&0x3|0x8);\n return v.toString(16);\n });\n};\n\nRkns.Utils = {\n getUUID4 : getUUID4,\n getUID : (function() {\n function pad(n){\n return n<10 ? '0'+n : n;\n }\n var _d = new Date(),\n ID_AUTO_INCREMENT = 0,\n ID_BASE = _d.getUTCFullYear() + '-' +\n pad(_d.getUTCMonth()+1) + '-' +\n pad(_d.getUTCDate()) + '-' +\n getUUID4();\n return function(_base) {\n var _n = (++ID_AUTO_INCREMENT).toString(16),\n _uidbase = (typeof _base === \"undefined\" ? \"\" : _base + \"-\" );\n while (_n.length < 4) { _n = '0' + _n; }\n return _uidbase + ID_BASE + '-' + _n;\n };\n })(),\n getFullURL : function(url) {\n\n if(typeof(url) === 'undefined' || url == null ) {\n return \"\";\n }\n if(/https?:\\/\\//.test(url)) {\n return url;\n }\n var img = new Image();\n img.src = url;\n var res = img.src;\n img.src = null;\n return res;\n\n },\n inherit : function(_baseClass, _callbefore) {\n\n var _class = function(_arg) {\n if (typeof _callbefore === \"function\") {\n _callbefore.apply(this, Array.prototype.slice.call(arguments, 0));\n }\n _baseClass.apply(this, Array.prototype.slice.call(arguments, 0));\n if (typeof this._init === \"function\" && !this._initialized) {\n this._init.apply(this, Array.prototype.slice.call(arguments, 0));\n this._initialized = true;\n }\n };\n _(_class.prototype).extend(_baseClass.prototype);\n\n return _class;\n\n },\n regexpFromTextOrArray: (function() {\n var charsub = [\n '[aáàâä]',\n '[cç]',\n '[eéèêë]',\n '[iíìîï]',\n '[oóòôö]',\n '[uùûü]'\n ],\n removeChars = [\n String.fromCharCode(768), String.fromCharCode(769), String.fromCharCode(770), String.fromCharCode(771), String.fromCharCode(807),\n \"{\", \"}\", \"(\", \")\", \"[\", \"]\", \"【\", \"】\", \"、\", \"・\", \"‥\", \"。\", \"「\", \"」\", \"『\", \"』\", \"〜\", \":\", \"!\", \"?\", \" \",\n \",\", \" \", \";\", \"(\", \")\", \".\", \"*\", \"+\", \"\\\\\", \"?\", \"|\", \"{\", \"}\", \"[\", \"]\", \"^\", \"#\", \"/\"\n ],\n remsrc = \"[\\\\\" + removeChars.join(\"\\\\\") + \"]\",\n remrx = new RegExp(remsrc, \"gm\"),\n charsrx = _(charsub).map(function(c) {\n return new RegExp(c);\n });\n\n function replaceText(_text) {\n var txt = _text.toLowerCase().replace(remrx,\"\"), src = \"\";\n function makeReplaceFunc(l) {\n return function(k,v) {\n l = l.replace(charsrx[k], v);\n };\n }\n for (var j = 0; j < txt.length; j++) {\n if (j) {\n src += remsrc + \"*\";\n }\n var l = txt[j];\n _(charsub).each(makeReplaceFunc(l));\n src += l;\n }\n return src;\n }\n\n function getSource(inp) {\n switch (typeof inp) {\n case \"string\":\n return replaceText(inp);\n case \"object\":\n var src = '';\n _(inp).each(function(v) {\n var res = getSource(v);\n if (res) {\n if (src) {\n src += '|';\n }\n src += res;\n }\n });\n return src;\n }\n return '';\n }\n\n return function(_textOrArray) {\n var source = getSource(_textOrArray);\n if (source) {\n var testrx = new RegExp( source, \"im\"),\n replacerx = new RegExp( '(' + source + ')', \"igm\");\n return {\n isempty: false,\n source: source,\n test: function(_t) { return testrx.test(_t); },\n replace: function(_text, _replace) { return _text.replace(replacerx, _replace); }\n };\n } else {\n return {\n isempty: true,\n source: '',\n test: function() { return true; },\n replace: function(_text) { return text; }\n };\n }\n };\n })(),\n /* The minimum distance (in pixels) the mouse has to move to consider an element was dragged */\n _MIN_DRAG_DISTANCE: 2,\n /* Distance between the inner and outer radius of buttons that appear when hovering on a node */\n _NODE_BUTTON_WIDTH: 40,\n\n _EDGE_BUTTON_INNER: 2,\n _EDGE_BUTTON_OUTER: 40,\n /* Constants used to know if a specific action is to be performed when clicking on the canvas */\n _CLICKMODE_ADDNODE: 1,\n _CLICKMODE_STARTEDGE: 2,\n _CLICKMODE_ENDEDGE: 3,\n /* Node size step: Used to calculate the size change when clicking the +/- buttons */\n _NODE_SIZE_STEP: Math.LN2/4,\n _MIN_SCALE: 1/20,\n _MAX_SCALE: 20,\n _MOUSEMOVE_RATE: 80,\n _DOUBLETAP_DELAY: 800,\n /* Maximum distance in pixels (squared, to reduce calculations)\n * between two taps when double-tapping on a touch terminal */\n _DOUBLETAP_DISTANCE: 20*20,\n /* A placeholder so a default colour is displayed when a node has a null value for its user property */\n _USER_PLACEHOLDER: function(_renkan) {\n return {\n color: _renkan.options.default_user_color,\n title: _renkan.translate(\"(unknown user)\"),\n get: function(attr) {\n return this[attr] || false;\n }\n };\n },\n /* The code for the \"Drag and Add Bookmarklet\", slightly minified and with whitespaces removed, though\n * it doesn't seem that it's still a requirement in newer browsers (i.e. the ones compatibles with canvas drawing)\n */\n _BOOKMARKLET_CODE: function(_renkan) {\n return \"(function(a,b,c,d,e,f,h,i,j,k,l,m,n,o,p,q,r){a=document;b=a.body;c=a.location.href;j='draggable';m='text/x-iri-';d=a.createElement('div');d.innerHTML='<p_style=\\\"position:fixed;top:0;right:0;font:bold_18px_sans-serif;color:#fff;background:#909;padding:10px;z-index:100000;\\\">\" +\n _renkan.translate(\"Drag items from this website, drop them in Renkan\").replace(/ /g,\"_\") +\n \"</p>'.replace(/_/g,String.fromCharCode(32));b.appendChild(d);e=[{r:/https?:\\\\/\\\\/[^\\\\/]*twitter\\\\.com\\\\//,s:'.tweet',n:'twitter'},{r:/https?:\\\\/\\\\/[^\\\\/]*google\\\\.[^\\\\/]+\\\\//,s:'.g',n:'google'},{r:/https?:\\\\/\\\\/[^\\\\/]*lemonde\\\\.fr\\\\//,s:'[data-vr-contentbox]',n:'lemonde'}];f=false;e.forEach(function(g){if(g.r.test(c)){f=g;}});if(f){h=function(){Array.prototype.forEach.call(a.querySelectorAll(f.s),function(i){i[j]=true;k=i.style;k.borderWidth='2px';k.borderColor='#909';k.borderStyle='solid';k.backgroundColor='rgba(200,0,180,.1)';})};window.setInterval(h,500);h();};a.addEventListener('dragstart',function(k){l=k.dataTransfer;l.setData(m+'source-uri',c);l.setData(m+'source-title',a.title);n=k.target;if(f){o=n;while(!o.attributes[j]){o=o.parentNode;if(o==b){break;}}}if(f&&o.attributes[j]){p=o.cloneNode(true);l.setData(m+'specific-site',f.n)}else{q=a.getSelection();if(q.type==='Range'||!q.type){p=q.getRangeAt(0).cloneContents();}else{p=n.cloneNode();}}r=a.createElement('div');r.appendChild(p);l.setData('text/x-iri-selected-text',r.textContent.trim());l.setData('text/x-iri-selected-html',r.innerHTML);},false);})();\";\n },\n /* Shortens text to the required length then adds ellipsis */\n shortenText: function(_text, _maxlength) {\n return (_text.length > _maxlength ? (_text.substr(0,_maxlength) + '…') : _text);\n },\n /* Drawing an edit box with an arrow and positioning the edit box according to the position of the node/edge being edited\n * Called by Rkns.Renderer.NodeEditor and Rkns.Renderer.EdgeEditor */\n drawEditBox: function(_options, _coords, _path, _xmargin, _selector) {\n _selector.css({\n width: ( _options.tooltip_width - 2* _options.tooltip_padding )\n });\n var _height = _selector.outerHeight() + 2* _options.tooltip_padding,\n _isLeft = (_coords.x < paper.view.center.x ? 1 : -1),\n _left = _coords.x + _isLeft * ( _xmargin + _options.tooltip_arrow_length ),\n _right = _coords.x + _isLeft * ( _xmargin + _options.tooltip_arrow_length + _options.tooltip_width ),\n _top = _coords.y - _height / 2;\n if (_top + _height > (paper.view.size.height - _options.tooltip_margin)) {\n _top = Math.max( paper.view.size.height - _options.tooltip_margin, _coords.y + _options.tooltip_arrow_width / 2 ) - _height;\n }\n if (_top < _options.tooltip_margin) {\n _top = Math.min( _options.tooltip_margin, _coords.y - _options.tooltip_arrow_width / 2 );\n }\n var _bottom = _top + _height;\n /* jshint laxbreak:true */\n _path.segments[0].point\n = _path.segments[7].point\n = _coords.add([_isLeft * _xmargin, 0]);\n _path.segments[1].point.x\n = _path.segments[2].point.x\n = _path.segments[5].point.x\n = _path.segments[6].point.x\n = _left;\n _path.segments[3].point.x\n = _path.segments[4].point.x\n = _right;\n _path.segments[2].point.y\n = _path.segments[3].point.y\n = _top;\n _path.segments[4].point.y\n = _path.segments[5].point.y\n = _bottom;\n _path.segments[1].point.y = _coords.y - _options.tooltip_arrow_width / 2;\n _path.segments[6].point.y = _coords.y + _options.tooltip_arrow_width / 2;\n _path.closed = true;\n _path.fillColor = new paper.GradientColor(new paper.Gradient([_options.tooltip_top_color, _options.tooltip_bottom_color]), [0,_top], [0, _bottom]);\n _selector.css({\n left: (_options.tooltip_padding + Math.min(_left, _right)),\n top: (_options.tooltip_padding + _top)\n });\n return _path;\n }\n};\n})(window);\n\n/* END main.js */\n","(function() {\n \"use strict\";\n var root = this;\n\n var Backbone = root.Backbone;\n\n var Models = root.Rkns.Models = {};\n\n\n Models.getUID = function(obj) {\n var guid = 'xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx'.replace(/[xy]/g, function(c) {\n var r = Math.random()*16|0, v = c === 'x' ? r : (r&0x3|0x8);\n return v.toString(16);\n });\n if(typeof obj !== 'undefined') {\n return obj.type + \"-\" + guid;\n }\n else {\n return guid;\n }\n };\n\n\n var RenkanModel = Backbone.RelationalModel.extend({\n idAttribute : \"_id\",\n constructor: function(options) {\n\n if (typeof options !== \"undefined\") {\n options._id = options._id || options.id || Models.getUID(this);\n options.title = options.title || \"\";\n options.description = options.description || \"\";\n options.uri = options.uri || \"\";\n\n if(typeof this.prepare === \"function\") {\n options = this.prepare(options);\n }\n }\n Backbone.RelationalModel.prototype.constructor.call(this, options);\n },\n validate: function() {\n if(!this.type) {\n return \"object has no type\";\n }\n },\n addReference : function(_options, _propName, _list, _id, _default) {\n var _element = _list.get(_id);\n if (typeof _element === \"undefined\" && typeof _default !== \"undefined\") {\n _options[_propName ] = _default;\n }\n else {\n _options[_propName ] = _element;\n }\n }\n });\n\n // USER\n var User = Models.User = RenkanModel.extend({\n type: \"user\",\n prepare: function(options) {\n options.color = options.color || \"#666666\";\n return options;\n },\n toJSON: function() {\n return {\n _id: this.get(\"_id\"),\n title: this.get(\"title\"),\n uri: this.get(\"uri\"),\n description: this.get(\"description\"),\n color: this.get(\"color\")\n };\n }\n });\n\n // NODE\n var Node = Models.Node = RenkanModel.extend({\n type: \"node\",\n relations: [{\n type: Backbone.HasOne,\n key: \"created_by\",\n relatedModel: User\n }],\n prepare: function(options) {\n var project = options.project;\n this.addReference(options, \"created_by\", project.get(\"users\"), options.created_by, project.current_user);\n options.description = options.description || \"\";\n return options;\n },\n toJSON: function() {\n return {\n _id: this.get(\"_id\"),\n title: this.get(\"title\"),\n uri: this.get(\"uri\"),\n description: this.get(\"description\"),\n position: this.get(\"position\"),\n image: this.get(\"image\"),\n color: this.get(\"color\"),\n created_by: this.get(\"created_by\") ? this.get(\"created_by\").get(\"_id\") : null,\n size: this.get(\"size\"),\n clip_path: this.get(\"clip_path\")\n };\n }\n });\n\n // EDGE\n var Edge = Models.Edge = RenkanModel.extend({\n type: \"edge\",\n relations: [\n {\n type: Backbone.HasOne,\n key: \"created_by\",\n relatedModel: User\n },\n {\n type: Backbone.HasOne,\n key: \"from\",\n relatedModel: Node\n },\n {\n type: Backbone.HasOne,\n key: \"to\",\n relatedModel: Node\n }\n ],\n prepare: function(options) {\n var project = options.project;\n this.addReference(options, \"created_by\", project.get(\"users\"), options.created_by, project.current_user);\n this.addReference(options, \"from\", project.get(\"nodes\"), options.from);\n this.addReference(options, \"to\", project.get(\"nodes\"), options.to);\n return options;\n },\n toJSON: function() {\n return {\n _id: this.get(\"_id\"),\n title: this.get(\"title\"),\n uri: this.get(\"uri\"),\n description: this.get(\"description\"),\n from: this.get(\"from\") ? this.get(\"from\").get(\"_id\") : null,\n to: this.get(\"to\") ? this.get(\"to\").get(\"_id\") : null,\n color: this.get(\"color\"),\n created_by: this.get(\"created_by\") ? this.get(\"created_by\").get(\"_id\") : null\n };\n }\n });\n\n // View\n var View = Models.View = RenkanModel.extend({\n type: \"view\",\n relations: [\n {\n type: Backbone.HasOne,\n key: \"created_by\",\n relatedModel: User\n }\n ],\n prepare: function(options) {\n var project = options.project;\n this.addReference(options, \"created_by\", project.get(\"users\"), options.created_by, project.current_user);\n options.description = options.description || \"\";\n if(typeof options.offset !== \"undefined\") {\n var offset = {};\n if (Array.isArray(options.offset)) {\n offset.x = options.offset[0];\n offset.y = options.offset.length > 1 ? options.offset[1] : options.offset[0];\n }\n else if (options.offset.x != null) {\n offset.x = options.offset.x;\n offset.y = options.offset.y;\n }\n options.offset = offset;\n }\n return options;\n },\n toJSON: function() {\n return {\n _id: this.get(\"_id\"),\n zoom_level: this.get(\"zoom_level\"),\n offset: this.get(\"offset\"),\n title: this.get(\"title\"),\n description: this.get(\"description\"),\n created_by: this.get(\"created_by\") ? this.get(\"created_by\").get(\"_id\") : null\n // Don't need project id\n };\n }\n });\n\n // PROJECT\n var Project = Models.Project = RenkanModel.extend({\n type: \"project\",\n relations: [\n {\n type: Backbone.HasMany,\n key: \"users\",\n relatedModel: User,\n reverseRelation: {\n key: 'project',\n includeInJSON: '_id'\n }\n },\n {\n type: Backbone.HasMany,\n key: \"nodes\",\n relatedModel: Node,\n reverseRelation: {\n key: 'project',\n includeInJSON: '_id'\n }\n },\n {\n type: Backbone.HasMany,\n key: \"edges\",\n relatedModel: Edge,\n reverseRelation: {\n key: 'project',\n includeInJSON: '_id'\n }\n },\n {\n type: Backbone.HasMany,\n key: \"views\",\n relatedModel: View,\n reverseRelation: {\n key: 'project',\n includeInJSON: '_id'\n }\n }\n ],\n addUser: function(_props, _options) {\n _props.project = this;\n var _user = User.findOrCreate(_props);\n this.get(\"users\").push(_user, _options);\n return _user;\n },\n addNode: function(_props, _options) {\n _props.project = this;\n var _node = Node.findOrCreate(_props);\n this.get(\"nodes\").push(_node, _options);\n return _node;\n },\n addEdge: function(_props, _options) {\n _props.project = this;\n var _edge = Edge.findOrCreate(_props);\n this.get(\"edges\").push(_edge, _options);\n return _edge;\n },\n addView: function(_props, _options) {\n _props.project = this;\n // TODO: check if need to replace with create only\n var _view = View.findOrCreate(_props);\n // TODO: Should we remember only one view?\n this.get(\"views\").push(_view, _options);\n return _view;\n },\n removeNode: function(_model) {\n this.get(\"nodes\").remove(_model);\n },\n removeEdge: function(_model) {\n this.get(\"edges\").remove(_model);\n },\n validate: function(options) {\n var _project = this;\n _([].concat(options.users, options.nodes, options.edges, options.views)).each(function(_item) {\n if(_item) {\n _item.project = _project;\n }\n });\n },\n // Add event handler to remove edges when a node is removed\n initialize: function() {\n var _this = this;\n this.on(\"remove:nodes\", function(_node) {\n _this.get(\"edges\").remove(\n _this.get(\"edges\").filter(function(_edge) {\n return _edge.get(\"from\") === _node || _edge.get(\"to\") === _node;\n })\n );\n });\n }\n });\n\n var RosterUser = Models.RosterUser = Backbone.Model.extend({\n type: \"roster_user\",\n idAttribute : \"_id\",\n\n constructor: function(options) {\n\n if (typeof options !== \"undefined\") {\n options._id = options._id || options.id || Models.getUID(this);\n options.title = options.title || \"(untitled \" + this.type + \")\";\n options.description = options.description || \"\";\n options.uri = options.uri || \"\";\n options.project = options.project || null;\n options.site_id = options.site_id || 0;\n\n if(typeof this.prepare === \"function\") {\n options = this.prepare(options);\n }\n }\n Backbone.Model.prototype.constructor.call(this, options);\n },\n\n validate: function() {\n if(!this.type) {\n return \"object has no type\";\n }\n },\n\n prepare: function(options) {\n options.color = options.color || \"#666666\";\n return options;\n },\n\n toJSON: function() {\n return {\n _id: this.get(\"_id\"),\n title: this.get(\"title\"),\n uri: this.get(\"uri\"),\n description: this.get(\"description\"),\n color: this.get(\"color\"),\n project: (this.get(\"project\") != null)?this.get(\"project\").get(\"id\"):null,\n site_id: this.get(\"site_id\")\n };\n }\n });\n\n var UsersList = Models.UsersList = Backbone.Collection.extend({\n model: RosterUser\n });\n\n\n}).call(window);\n","Rkns.defaults = {\n\n language: (navigator.language || navigator.userLanguage || \"en\"),\n /* GUI Language */\n container: \"renkan\",\n /* GUI Container DOM element ID */\n search: [],\n /* List of Search Engines */\n bins: [],\n /* List of Bins */\n static_url: \"\",\n /* URL for static resources */\n show_bins: true,\n /* Show bins in left column */\n properties: [],\n /* Semantic properties for edges */\n show_editor: true,\n /* Show the graph editor... Setting this to \"false\" only shows the bins part ! */\n read_only: false,\n /* Allows editing of renkan without changing the rest of the GUI. Can be switched on/off on the fly to block/enable editing */\n editor_mode: true,\n /* Switch for Publish/Edit GUI. If editor_mode is false, read_only will be true. */\n snapshot_mode: false,\n /* In snapshot mode, clicking on the floppy will save a snapshot. Otherwise, it will show the connection status */\n show_top_bar: true,\n /* Show the top bar, (title, buttons, users) */\n default_user_color: \"#303030\",\n size_bug_fix: true,\n /* Resize the canvas after load (fixes a bug on iPad and FF Mac) */\n force_resize: false,\n allow_double_click: true,\n /* Allows Double Click to create a node on an empty background */\n zoom_on_scroll: true,\n /* Allows to use the scrollwheel to zoom */\n element_delete_delay: 0,\n /* Delay between clicking on the bin on an element and really deleting it\n Set to 0 for delete confirm */\n autoscale_padding: 50,\n default_view: false,\n\t/* Allows to load default view (zoom+offset) at start on read_only mode, instead of autoScale. default_view has to be an integer 0,1,2... */\n\n /* TOP BAR BUTTONS */\n show_search_field: true,\n show_user_list: true,\n user_name_editable: true,\n user_color_editable: true,\n show_save_button: true,\n show_export_button: true,\n show_open_button: false,\n show_addnode_button: true,\n show_addedge_button: true,\n show_bookmarklet: true,\n show_fullscreen_button: true,\n home_button_url: false,\n home_button_title: \"Home\",\n\n /* MINI-MAP OPTIONS */\n\n show_minimap: true,\n /* Show a small map at the bottom right */\n minimap_width: 160,\n minimap_height: 120,\n minimap_padding: 20,\n minimap_background_color: \"#ffffff\",\n minimap_border_color: \"#cccccc\",\n minimap_highlight_color: \"#ffff00\",\n minimap_highlight_weight: 5,\n\n /* EDGE/NODE COMMON OPTIONS */\n\n buttons_background: \"#202020\",\n buttons_label_color: \"#c000c0\",\n buttons_label_font_size: 9,\n\n /* NODE DISPLAY OPTIONS */\n\n show_node_circles: true,\n /* Show circles for nodes */\n clip_node_images: true,\n /* Constraint node images to circles */\n node_images_fill_mode: false,\n /* Set to false for \"letterboxing\" (height/width of node adapted to show full image)\n Set to true for \"crop\" (adapted to fill circle) */\n node_size_base: 25,\n node_stroke_width: 2,\n selected_node_stroke_width: 4,\n node_fill_color: \"#ffffff\",\n highlighted_node_fill_color: \"#ffff00\",\n node_label_distance: 5,\n /* Vertical distance between node and label */\n node_label_max_length: 60,\n /* Maximum displayed text length */\n label_untitled_nodes: \"(untitled)\",\n /* Label to display on untitled nodes */\n\n /* EDGE DISPLAY OPTIONS */\n\n edge_stroke_width: 2,\n selected_edge_stroke_width: 4,\n edge_label_distance: 0,\n edge_label_max_length: 20,\n edge_arrow_length: 18,\n edge_arrow_width: 12,\n edge_gap_in_bundles: 12,\n label_untitled_edges: \"\",\n\n /* CONTEXTUAL DISPLAY (TOOLTIP OR EDITOR) OPTIONS */\n\n tooltip_width: 275,\n tooltip_padding: 10,\n tooltip_margin: 15,\n tooltip_arrow_length : 20,\n tooltip_arrow_width : 40,\n tooltip_top_color: \"#f0f0f0\",\n tooltip_bottom_color: \"#d0d0d0\",\n tooltip_border_color: \"#808080\",\n tooltip_border_width: 1,\n\n /* NODE EDITOR OPTIONS */\n\n show_node_editor_uri: true,\n show_node_editor_description: true,\n show_node_editor_size: true,\n show_node_editor_color: true,\n show_node_editor_image: true,\n show_node_editor_creator: true,\n uploaded_image_max_kb: 500,\n\n /* NODE TOOLTIP OPTIONS */\n\n show_node_tooltip_uri: true,\n show_node_tooltip_description: true,\n show_node_tooltip_color: true,\n show_node_tooltip_image: true,\n show_node_tooltip_creator: true,\n\n /* EDGE EDITOR OPTIONS */\n\n show_edge_editor_uri: true,\n show_edge_editor_color: true,\n show_edge_editor_direction: true,\n show_edge_editor_nodes: true,\n show_edge_editor_creator: true,\n\n /* EDGE TOOLTIP OPTIONS */\n\n show_edge_tooltip_uri: true,\n show_edge_tooltip_color: true,\n show_edge_tooltip_nodes: true,\n show_edge_tooltip_creator: true\n\n /* */\n\n};\n","Rkns.i18n = {\n fr: {\n \"Edit Node\": \"Édition d’un nœud\",\n \"Edit Edge\": \"Édition d’un lien\",\n \"Title:\": \"Titre :\",\n \"URI:\": \"URI :\",\n \"Description:\": \"Description :\",\n \"From:\": \"De :\",\n \"To:\": \"Vers :\",\n \"Image\": \"Image\",\n \"Image URL:\": \"URL d'Image\",\n \"Choose Image File:\": \"Choisir un fichier image\",\n \"Full Screen\": \"Mode plein écran\",\n \"Add Node\": \"Ajouter un nœud\",\n \"Add Edge\": \"Ajouter un lien\",\n \"Save Project\": \"Enregistrer le projet\",\n \"Open Project\": \"Ouvrir un projet\",\n \"Auto-save enabled\": \"Enregistrement automatique activé\",\n \"Connection lost\": \"Connexion perdue\",\n \"Created by:\": \"Créé par :\",\n \"Zoom In\": \"Agrandir l’échelle\",\n \"Zoom Out\": \"Rapetisser l’échelle\",\n \"Edit\": \"Éditer\",\n \"Remove\": \"Supprimer\",\n \"Cancel deletion\": \"Annuler la suppression\",\n \"Link to another node\": \"Créer un lien\",\n \"Enlarge\": \"Agrandir\",\n \"Shrink\": \"Rétrécir\",\n \"Click on the background canvas to add a node\": \"Cliquer sur le fond du graphe pour rajouter un nœud\",\n \"Click on a first node to start the edge\": \"Cliquer sur un premier nœud pour commencer le lien\",\n \"Click on a second node to complete the edge\": \"Cliquer sur un second nœud pour terminer le lien\",\n \"Wikipedia\": \"Wikipédia\",\n \"Wikipedia in \": \"Wikipédia en \",\n \"French\": \"Français\",\n \"English\": \"Anglais\",\n \"Japanese\": \"Japonais\",\n \"Untitled project\": \"Projet sans titre\",\n \"Lignes de Temps\": \"Lignes de Temps\",\n \"Loading, please wait\": \"Chargement en cours, merci de patienter\",\n \"Edge color:\": \"Couleur :\",\n \"Node color:\": \"Couleur :\",\n \"Choose color\": \"Choisir une couleur\",\n \"Change edge direction\": \"Changer le sens du lien\",\n \"Do you really wish to remove node \": \"Voulez-vous réellement supprimer le nœud \",\n \"Do you really wish to remove edge \": \"Voulez-vous réellement supprimer le lien \",\n \"This file is not an image\": \"Ce fichier n'est pas une image\",\n \"Image size must be under \": \"L'image doit peser moins de \",\n \"Size:\": \"Taille :\",\n \"KB\": \"ko\",\n \"Choose from vocabulary:\": \"Choisir dans un vocabulaire :\",\n \"SKOS Documentation properties\": \"SKOS: Propriétés documentaires\",\n \"has note\": \"a pour note\",\n \"has example\": \"a pour exemple\",\n \"has definition\": \"a pour définition\",\n \"SKOS Semantic relations\": \"SKOS: Relations sémantiques\",\n \"has broader\": \"a pour concept plus large\",\n \"has narrower\": \"a pour concept plus étroit\",\n \"has related\": \"a pour concept apparenté\",\n \"Dublin Core Metadata\": \"Métadonnées Dublin Core\",\n \"has contributor\": \"a pour contributeur\",\n \"covers\": \"couvre\",\n \"created by\": \"créé par\",\n \"has date\": \"a pour date\",\n \"published by\": \"édité par\",\n \"has source\": \"a pour source\",\n \"has subject\": \"a pour sujet\",\n \"Dragged resource\": \"Ressource glisée-déposée\",\n \"Search the Web\": \"Rechercher en ligne\",\n \"Search in Bins\": \"Rechercher dans les chutiers\",\n \"Close bin\": \"Fermer le chutier\",\n \"Refresh bin\": \"Rafraîchir le chutier\",\n \"(untitled)\": \"(sans titre)\",\n \"Select contents:\": \"Sélectionner des contenus :\",\n \"Drag items from this website, drop them in Renkan\": \"Glissez des éléments de ce site web vers Renkan\",\n \"Drag this button to your bookmark bar. When on a third-party website, click it to enable drag-and-drop from the website to Renkan.\": \"Glissez ce bouton vers votre barre de favoris. Ensuite, depuis un site tiers, cliquez dessus pour activer 'Drag-to-Add' puis glissez des éléments de ce site vers Renkan\"\n }\n};\n","/* Saves the Full JSON at each modification */\n\nRkns.jsonIO = function(_renkan, _opts) {\n var _proj = _renkan.project;\n if (typeof _opts.http_method === \"undefined\") {\n _opts.http_method = 'PUT';\n }\n var _load = function() {\n _renkan.renderer.redrawActive = false;\n Rkns.$.getJSON(_opts.url, function(_data) {\n _proj.set(_data, {validate: true});\n _renkan.renderer.redrawActive = true;\n _renkan.renderer.autoScale();\n });\n };\n var _save = function() {\n var _data = _proj.toJSON();\n if (!_renkan.read_only) {\n Rkns.$.ajax({\n type: _opts.http_method,\n url: _opts.url,\n contentType: \"application/json\",\n data: JSON.stringify(_data),\n success: function(data, textStatus, jqXHR) {\n }\n });\n }\n\n };\n var _thrSave = Rkns._.throttle(\n function() {\n setTimeout(_save, 100);\n }, 1000);\n _proj.on(\"add:nodes add:edges add:users add:views\", function(_model) {\n _model.on(\"change remove\", function(_model) {\n _thrSave();\n });\n _thrSave();\n });\n _proj.on(\"change\", function() {\n _thrSave();\n });\n\n _load();\n};\n","(function(Rkns) {\n\"use strict\";\n\nvar _ = Rkns._;\n\nvar Ldt = Rkns.Ldt = {};\n\nvar Bin = Ldt.Bin = function(_renkan, _opts) {\n if (_opts.ldt_type) {\n var Resclass = Ldt[_opts.ldt_type+\"Bin\"];\n if (Resclass) {\n return new Resclass(_renkan, _opts);\n }\n }\n console.error(\"No such LDT Bin Type\");\n};\n\nvar ProjectBin = Ldt.ProjectBin = Rkns.Utils.inherit(Rkns._BaseBin);\n\nProjectBin.prototype.tagTemplate = _.template(\n '<li class=\"Rk-Bin-Item\" draggable=\"true\" data-image=\"<%- Rkns.Utils.getFullURL(static_url+\\'img/ldt-tag.png\\') %>\" data-uri=\"<%=ldt_platform%>ldtplatform/ldt/front/search/?search=<%=encodedtitle%>&field=all\" data-title=\"<%-title%>\" data-description=\"Tag \\'<%-title%>\\'\">' +\n '<img class=\"Rk-Ldt-Tag-Icon\" src=\"<%-static_url%>img/ldt-tag.png\" /><h4><%=htitle%></h4><div class=\"Rk-Clear\"></div></li>'\n);\n\nProjectBin.prototype.annotationTemplate = _.template(\n '<li class=\"Rk-Bin-Item\" draggable=\"true\" data-image=\"<%- Rkns.Utils.getFullURL(image) %>\" data-uri=\"<%=ldt_platform%>ldtplatform/ldt/front/player/<%=mediaid%>/#id=<%=annotationid%>\" data-title=\"<%-title%>\" data-description=\"<%-description%>\">' +\n '<img class=\"Rk-Ldt-Annotation-Icon\" src=\"<%=image%>\"/><h4><%=htitle%></h4><p><%=hdescription%></p><p>Start: <%=start%>, End: <%=end%>, Duration: <%=duration%></p><div class=\"Rk-Clear\"></div></li>'\n);\n\nProjectBin.prototype._init = function(_renkan, _opts) {\n this.renkan = _renkan;\n this.proj_id = _opts.project_id;\n this.ldt_platform = _opts.ldt_platform || \"http://ldt.iri.centrepompidou.fr/\";\n this.title_$.html(_opts.title);\n this.title_icon_$.addClass('Rk-Ldt-Title-Icon');\n this.refresh();\n};\n\nProjectBin.prototype.render = function(searchbase) {\n var search = searchbase || Rkns.Utils.regexpFromTextOrArray();\n function highlight(_text) {\n var _e = _(_text).escape();\n return search.isempty ? _e : search.replace(_e, \"<span class='searchmatch'>$1</span>\");\n }\n function convertTC(_ms) {\n function pad(_n) {\n var _res = _n.toString();\n while (_res.length < 2) {\n _res = '0' + _res;\n }\n return _res;\n }\n var _totalSeconds = Math.abs(Math.floor(_ms/1000)),\n _hours = Math.floor(_totalSeconds / 3600),\n _minutes = (Math.floor(_totalSeconds / 60) % 60),\n _seconds = _totalSeconds % 60,\n _res = '';\n if (_hours) {\n _res += pad(_hours) + ':';\n }\n _res += pad(_minutes) + ':' + pad(_seconds);\n return _res;\n }\n\n var _html = '<li><h3>Tags</h3></li>',\n _projtitle = this.data.meta[\"dc:title\"],\n _this = this,\n count = 0;\n _this.title_$.text('LDT Project: \"' + _projtitle + '\"');\n _(_this.data.tags).map(function(_tag) {\n var _title = _tag.meta[\"dc:title\"];\n if (!search.isempty && !search.test(_title)) {\n return;\n }\n count++;\n _html += _this.tagTemplate({\n ldt_platform: _this.ldt_platform,\n title: _title,\n htitle: highlight(_title),\n encodedtitle : encodeURIComponent(_title),\n static_url: _this.renkan.options.static_url\n });\n });\n _html += '<li><h3>Annotations</h3></li>';\n _(_this.data.annotations).map(function(_annotation) {\n var _description = _annotation.content.description,\n _title = _annotation.content.title.replace(_description,\"\");\n if (!search.isempty && !search.test(_title) && !search.test(_description)) {\n return;\n }\n count++;\n var _duration = _annotation.end - _annotation.begin,\n _img = (\n (_annotation.content && _annotation.content.img && _annotation.content.img.src) ?\n _annotation.content.img.src :\n ( _duration ? _this.renkan.options.static_url+\"img/ldt-segment.png\" : _this.renkan.options.static_url+\"img/ldt-point.png\" )\n );\n _html += _this.annotationTemplate({\n ldt_platform: _this.ldt_platform,\n title: _title,\n htitle: highlight(_title),\n description: _description,\n hdescription: highlight(_description),\n start: convertTC(_annotation.begin),\n end: convertTC(_annotation.end),\n duration: convertTC(_duration),\n mediaid: _annotation.media,\n annotationid: _annotation.id,\n image: _img,\n static_url: _this.renkan.options.static_url\n });\n });\n\n this.main_$.html(_html);\n if (!search.isempty && count) {\n this.count_$.text(count).show();\n } else {\n this.count_$.hide();\n }\n if (!search.isempty && !count) {\n this.$.hide();\n } else {\n this.$.show();\n }\n this.renkan.resizeBins();\n};\n\nProjectBin.prototype.refresh = function() {\n var _this = this;\n Rkns.$.ajax({\n url: this.ldt_platform + 'ldtplatform/ldt/cljson/id/' + this.proj_id,\n dataType: \"jsonp\",\n success: function(_data) {\n _this.data = _data;\n _this.render();\n }\n });\n};\n\nvar Search = Ldt.Search = function(_renkan, _opts) {\n this.renkan = _renkan;\n this.lang = _opts.lang || \"en\";\n};\n\nSearch.prototype.getBgClass = function() {\n return \"Rk-Ldt-Icon\";\n};\n\nSearch.prototype.getSearchTitle = function() {\n return this.renkan.translate(\"Lignes de Temps\");\n};\n\nSearch.prototype.search = function(_q) {\n this.renkan.tabs.push(\n new ResultsBin(this.renkan, {\n search: _q\n })\n );\n};\n\nvar ResultsBin = Ldt.ResultsBin = Rkns.Utils.inherit(Rkns._BaseBin);\n\nResultsBin.prototype.segmentTemplate = _.template(\n '<li class=\"Rk-Bin-Item\" draggable=\"true\" data-image=\"<%- Rkns.Utils.getFullURL(image) %>\" data-uri=\"<%=ldt_platform%>ldtplatform/ldt/front/player/<%=mediaid%>/#id=<%=annotationid%>\" data-title=\"<%-title%>\" data-description=\"<%-description%>\">' +\n '<img class=\"Rk-Ldt-Annotation-Icon\" src=\"<%=image%>\"/><h4><%=htitle%></h4><p><%=hdescription%></p><p>Start: <%=start%>, End: <%=end%>, Duration: <%=duration%></p><div class=\"Rk-Clear\"></div></li>'\n);\n\nResultsBin.prototype._init = function(_renkan, _opts) {\n this.renkan = _renkan;\n this.ldt_platform = _opts.ldt_platform || \"http://ldt.iri.centrepompidou.fr/\";\n this.max_results = _opts.max_results || 50;\n this.search = _opts.search;\n this.title_$.html('Lignes de Temps: \"' + _opts.search + '\"');\n this.title_icon_$.addClass('Rk-Ldt-Title-Icon');\n this.refresh();\n};\n\nResultsBin.prototype.render = function(searchbase) {\n if (!this.data) {\n return;\n }\n var search = searchbase || Rkns.Utils.regexpFromTextOrArray();\n var highlightrx = (search.isempty ? Rkns.Utils.regexpFromTextOrArray(this.search) : search);\n function highlight(_text) {\n return highlightrx.replace(_(_text).escape(), \"<span class='searchmatch'>$1</span>\");\n }\n function convertTC(_ms) {\n function pad(_n) {\n var _res = _n.toString();\n while (_res.length < 2) {\n _res = '0' + _res;\n }\n return _res;\n }\n var _totalSeconds = Math.abs(Math.floor(_ms/1000)),\n _hours = Math.floor(_totalSeconds / 3600),\n _minutes = (Math.floor(_totalSeconds / 60) % 60),\n _seconds = _totalSeconds % 60,\n _res = '';\n if (_hours) {\n _res += pad(_hours) + ':';\n }\n _res += pad(_minutes) + ':' + pad(_seconds);\n return _res;\n }\n\n var _html = '',\n _this = this,\n count = 0;\n _(this.data.objects).each(function(_segment) {\n var _description = _segment.abstract,\n _title = _segment.title;\n if (!search.isempty && !search.test(_title) && !search.test(_description)) {\n return;\n }\n count++;\n var _duration = _segment.duration,\n _begin = _segment.start_ts,\n _end = + _segment.duration + _begin,\n _img = (\n _duration ?\n _this.renkan.options.static_url + \"img/ldt-segment.png\" :\n _this.renkan.options.static_url + \"img/ldt-point.png\"\n );\n _html += _this.segmentTemplate({\n ldt_platform: _this.ldt_platform,\n title: _title,\n htitle: highlight(_title),\n description: _description,\n hdescription: highlight(_description),\n start: convertTC(_begin),\n end: convertTC(_end),\n duration: convertTC(_duration),\n mediaid: _segment.iri_id,\n //projectid: _segment.project_id,\n //cuttingid: _segment.cutting_id,\n annotationid: _segment.element_id,\n image: _img\n });\n });\n\n this.main_$.html(_html);\n if (!search.isempty && count) {\n this.count_$.text(count).show();\n } else {\n this.count_$.hide();\n }\n if (!search.isempty && !count) {\n this.$.hide();\n } else {\n this.$.show();\n }\n this.renkan.resizeBins();\n};\n\nResultsBin.prototype.refresh = function() {\n var _this = this;\n Rkns.$.ajax({\n url: this.ldt_platform + 'ldtplatform/api/ldt/1.0/segments/search/',\n data: {\n format: \"jsonp\",\n q: this.search,\n limit: this.max_results\n },\n dataType: \"jsonp\",\n success: function(_data) {\n _this.data = _data;\n _this.render();\n }\n });\n};\n\n})(window.Rkns);\n","Rkns.ResourceList = {};\n\nRkns.ResourceList.Bin = Rkns.Utils.inherit(Rkns._BaseBin);\n\nRkns.ResourceList.Bin.prototype.resultTemplate = Rkns._.template(\n '<li class=\"Rk-Bin-Item Rk-ResourceList-Item\" draggable=\"true\" data-uri=\"<%-url%>\" ' +\n 'data-title=\"<%-title%>\" data-description=\"<%-description%>\" ' +\n '<% if (image) { %>data-image=\"<%- Rkns.Utils.getFullURL(image) %>\"<% } else { %>data-image=\"\"<% } %> >' +\n '<% if (image) { %><img class=\"Rk-ResourceList-Image\" src=\"<%-image%>\"/><% } %><h4 class=\"Rk-ResourceList-Title\">' +\n '<% if (url) { %><a href=\"<%-url%>\" target=\"_blank\"><% } %><%=htitle%><% if (url) { %></a><% } %></h4>' +\n '<% if (description) { %><p class=\"Rk-ResourceList-Description\"><%=hdescription%></p><% } %><% if (image) { %><div style=\"clear: both;\"></div><% } %></li>'\n);\n\nRkns.ResourceList.Bin.prototype._init = function(_renkan, _opts) {\n this.renkan = _renkan;\n this.title_$.html(_opts.title);\n if (_opts.list) {\n this.data = _opts.list;\n }\n this.refresh();\n};\n\nRkns.ResourceList.Bin.prototype.render = function(searchbase) {\n var search = searchbase || Rkns.Utils.regexpFromTextOrArray();\n function highlight(_text) {\n var _e = _(_text).escape();\n return search.isempty ? _e : search.replace(_e, \"<span class='searchmatch'>$1</span>\");\n }\n var _html = \"\",\n _this = this,\n count = 0;\n Rkns._(this.data).each(function(_item) {\n var _element;\n if (typeof _item === \"string\") {\n if (/^(https?:\\/\\/|www)/.test(_item)) {\n _element = { url: _item };\n } else {\n _element = { title: _item.replace(/[:,]?\\s?(https?:\\/\\/|www)[\\d\\w\\/.&?=#%-_]+\\s?/,'').trim() };\n var _match = _item.match(/(https?:\\/\\/|www)[\\d\\w\\/.&?=#%-_]+/);\n if (_match) {\n _element.url = _match[0];\n }\n if (_element.title.length > 80) {\n _element.description = _element.title;\n _element.title = _element.title.replace(/^(.{30,60})\\s.+$/,'$1…');\n }\n }\n } else {\n _element = _item;\n }\n var title = _element.title || (_element.url || \"\").replace(/^https?:\\/\\/(www\\.)?/,'').replace(/^(.{40}).+$/,'$1…'),\n url = _element.url || \"\",\n description = _element.description || \"\",\n image = _element.image || \"\";\n if (url && !/^https?:\\/\\//.test(url)) {\n url = 'http://' + url;\n }\n if (!search.isempty && !search.test(title) && !search.test(description)) {\n return;\n }\n count++;\n _html += _this.resultTemplate({\n url: url,\n title: title,\n htitle: highlight(title),\n image: image,\n description: description,\n hdescription: highlight(description),\n static_url: _this.renkan.options.static_url\n });\n });\n _this.main_$.html(_html);\n if (!search.isempty && count) {\n this.count_$.text(count).show();\n } else {\n this.count_$.hide();\n }\n if (!search.isempty && !count) {\n this.$.hide();\n } else {\n this.$.show();\n }\n this.renkan.resizeBins();\n};\n\nRkns.ResourceList.Bin.prototype.refresh = function() {\n if (this.data) {\n this.render();\n }\n};\n","Rkns.Wikipedia = {\n};\n\nRkns.Wikipedia.Search = function(_renkan, _opts) {\n this.renkan = _renkan;\n this.lang = _opts.lang || \"en\";\n};\n\nRkns.Wikipedia.Search.prototype.getBgClass = function() {\n return \"Rk-Wikipedia-Search-Icon Rk-Wikipedia-Lang-\" + this.lang;\n};\n\nRkns.Wikipedia.Search.prototype.getSearchTitle = function() {\n var langs = {\n \"fr\": \"French\",\n \"en\": \"English\",\n \"ja\": \"Japanese\"\n };\n if (langs[this.lang]) {\n return this.renkan.translate(\"Wikipedia in \") + this.renkan.translate(langs[this.lang]);\n } else {\n return this.renkan.translate(\"Wikipedia\") + \" [\" + this.lang + \"]\";\n }\n};\n\nRkns.Wikipedia.Search.prototype.search = function(_q) {\n this.renkan.tabs.push(\n new Rkns.Wikipedia.Bin(this.renkan, {\n lang: this.lang,\n search: _q\n })\n );\n};\n\nRkns.Wikipedia.Bin = Rkns.Utils.inherit(Rkns._BaseBin);\n\nRkns.Wikipedia.Bin.prototype.resultTemplate = Rkns._.template(\n '<li class=\"Rk-Wikipedia-Result Rk-Bin-Item\" draggable=\"true\" data-uri=\"<%-url%>\" ' +\n 'data-title=\"Wikipedia: <%-title%>\" data-description=\"<%-description%>\" data-image=\"<%- Rkns.Utils.getFullURL( static_url + \\'img/wikipedia.png\\' ) %>\">' +\n '<img class=\"Rk-Wikipedia-Icon\" src=\"<%-static_url%>img/wikipedia.png\"></div><h4 class=\"Rk-Wikipedia-Title\"><a href=\"<%-url%>\" target=\"_blank\"><%=htitle%></a></h4>' +\n '<p class=\"Rk-Wikipedia-Snippet\"><%=hdescription%></p></li>'\n);\n\nRkns.Wikipedia.Bin.prototype._init = function(_renkan, _opts) {\n this.renkan = _renkan;\n this.search = _opts.search;\n this.lang = _opts.lang || \"en\";\n this.title_icon_$.addClass('Rk-Wikipedia-Title-Icon Rk-Wikipedia-Lang-' + this.lang);\n this.title_$.html(this.search).addClass(\"Rk-Wikipedia-Title\");\n this.refresh();\n};\n\nRkns.Wikipedia.Bin.prototype.render = function(searchbase) {\n var search = searchbase || Rkns.Utils.regexpFromTextOrArray();\n var highlightrx = (search.isempty ? Rkns.Utils.regexpFromTextOrArray(this.search) : search);\n function highlight(_text) {\n return highlightrx.replace(_(_text).escape(), \"<span class='searchmatch'>$1</span>\");\n }\n var _html = \"\",\n _this = this,\n count = 0;\n Rkns._(this.data.query.search).each(function(_result) {\n var title = _result.title,\n url = \"http://\" + _this.lang + \".wikipedia.org/wiki/\" + encodeURI(title.replace(/ /g,\"_\")),\n description = Rkns.$('<div>').html(_result.snippet).text();\n if (!search.isempty && !search.test(title) && !search.test(description)) {\n return;\n }\n count++;\n _html += _this.resultTemplate({\n url: url,\n title: title,\n htitle: highlight(title),\n description: description,\n hdescription: highlight(description),\n static_url: _this.renkan.options.static_url\n });\n });\n _this.main_$.html(_html);\n if (!search.isempty && count) {\n this.count_$.text(count).show();\n } else {\n this.count_$.hide();\n }\n if (!search.isempty && !count) {\n this.$.hide();\n } else {\n this.$.show();\n }\n this.renkan.resizeBins();\n};\n\nRkns.Wikipedia.Bin.prototype.refresh = function() {\n var _this = this;\n Rkns.$.ajax({\n url: \"http://\" + _this.lang + \".wikipedia.org/w/api.php?action=query&list=search&srsearch=\" + encodeURIComponent(this.search) + \"&format=json\",\n dataType: \"jsonp\",\n success: function(_data) {\n _this.data = _data;\n _this.render();\n }\n });\n};\n","\ndefine('renderer/baserepresentation',['jquery', 'underscore'], function ($, _) {\n \n\n /* Rkns.Renderer._BaseRepresentation Class */\n\n /* In Renkan, a \"Representation\" is a sort of ViewModel (in the MVVM paradigm) and bridges the gap between\n * models (written with Backbone.js) and the view (written with Paper.js)\n * Renkan's representations all inherit from Rkns.Renderer._BaseRepresentation '*/\n\n var _BaseRepresentation = function(_renderer, _model) {\n if (typeof _renderer !== \"undefined\") {\n this.renderer = _renderer;\n this.renkan = _renderer.renkan;\n this.project = _renderer.renkan.project;\n this.options = _renderer.renkan.options;\n this.model = _model;\n if (this.model) {\n var _this = this;\n this._changeBinding = function() {\n _this.redraw();\n };\n this._removeBinding = function() {\n _renderer.removeRepresentation(_this);\n _(function() {\n _renderer.redraw();\n }).defer();\n };\n this._selectBinding = function() {\n _this.select();\n };\n this._unselectBinding = function() {\n _this.unselect();\n };\n this.model.on(\"change\", this._changeBinding );\n this.model.on(\"remove\", this._removeBinding );\n this.model.on(\"select\", this._selectBinding );\n this.model.on(\"unselect\", this._unselectBinding );\n }\n }\n };\n\n /* Rkns.Renderer._BaseRepresentation Methods */\n\n _(_BaseRepresentation.prototype).extend({\n _super: function(_func) {\n return _BaseRepresentation.prototype[_func].apply(this, Array.prototype.slice.call(arguments, 1));\n },\n redraw: function() {},\n moveTo: function() {},\n show: function() { return \"chaud cacao\"; },\n hide: function() {},\n select: function() {\n if (this.model) {\n this.model.trigger(\"selected\");\n }\n },\n unselect: function() {\n if (this.model) {\n this.model.trigger(\"unselected\");\n }\n },\n highlight: function() {},\n unhighlight: function() {},\n mousedown: function() {},\n mouseup: function() {\n if (this.model) {\n this.model.trigger(\"clicked\");\n }\n },\n destroy: function() {\n if (this.model) {\n this.model.off(\"change\", this._changeBinding );\n this.model.off(\"remove\", this._removeBinding );\n this.model.off(\"select\", this._selectBinding );\n this.model.off(\"unselect\", this._unselectBinding );\n }\n }\n });\n\n /* End of Rkns.Renderer._BaseRepresentation Class */\n\n return _BaseRepresentation;\n\n});\n\ndefine('requtils',[], function ($, _) {\n \n return {\n getUtils: function(){\n return window.Rkns.Utils;\n },\n getRenderer: function(){\n return window.Rkns.Renderer;\n }\n };\n\n});\n\n\ndefine('renderer/basebutton',['jquery', 'underscore', 'requtils', 'renderer/baserepresentation'], function ($, _, requtils, BaseRepresentation) {\n \n\n var Utils = requtils.getUtils();\n\n /* Rkns.Renderer._BaseButton Class */\n\n /* BaseButton is extended by contextual buttons that appear when hovering on nodes and edges */\n\n var _BaseButton = Utils.inherit(BaseRepresentation);\n\n _(_BaseButton.prototype).extend({\n moveTo: function(_pos) {\n this.sector.moveTo(_pos);\n },\n show: function() {\n this.sector.show();\n },\n hide: function() {\n this.sector.hide();\n },\n select: function() {\n this.sector.select();\n },\n unselect: function(_newTarget) {\n this.sector.unselect();\n if (!_newTarget || (_newTarget !== this.source_representation && _newTarget.source_representation !== this.source_representation)) {\n this.source_representation.unselect();\n }\n },\n destroy: function() {\n this.sector.destroy();\n }\n });\n\n return _BaseButton;\n\n});\n\n\n\ndefine('renderer/noderepr',['jquery', 'underscore', 'requtils', 'renderer/baserepresentation'], function ($, _, requtils, BaseRepresentation) {\n \n\n var Utils = requtils.getUtils();\n\n /* Rkns.Renderer.Node Class */\n\n /* The representation for the node : A circle, with an image inside and a text label underneath.\n * The circle and the image are drawn on canvas and managed by Paper.js.\n * The text label is an HTML node, managed by jQuery. */\n\n //var NodeRepr = Renderer.Node = Utils.inherit(Renderer._BaseRepresentation);\n var NodeRepr = Utils.inherit(BaseRepresentation);\n\n _(NodeRepr.prototype).extend({\n _init: function() {\n this.renderer.node_layer.activate();\n this.type = \"Node\";\n this.circle = new paper.Path.Circle([0, 0], 1);\n this.circle.__representation = this;\n if (this.options.show_node_circles) {\n this.circle.strokeWidth = this.options.node_stroke_width;\n this.h_ratio = 1;\n } else {\n this.h_ratio = 0;\n }\n this.title = $('<div class=\"Rk-Label\">').appendTo(this.renderer.labels_$);\n if (this.options.editor_mode) {\n var Renderer = requtils.getRenderer();\n this.normal_buttons = [\n new Renderer.NodeEditButton(this.renderer, null),\n new Renderer.NodeRemoveButton(this.renderer, null),\n new Renderer.NodeLinkButton(this.renderer, null),\n new Renderer.NodeEnlargeButton(this.renderer, null),\n new Renderer.NodeShrinkButton(this.renderer, null)\n ];\n this.pending_delete_buttons = [\n new Renderer.NodeRevertButton(this.renderer, null)\n ];\n this.all_buttons = this.normal_buttons.concat(this.pending_delete_buttons);\n for (var i = 0; i < this.all_buttons.length; i++) {\n this.all_buttons[i].source_representation = this;\n }\n this.active_buttons = [];\n } else {\n this.active_buttons = this.all_buttons = [];\n }\n this.last_circle_radius = 1;\n\n if (this.renderer.minimap) {\n this.renderer.minimap.node_layer.activate();\n this.minimap_circle = new paper.Path.Circle([0, 0], 1);\n this.minimap_circle.__representation = this.renderer.minimap.miniframe.__representation;\n this.renderer.minimap.node_group.addChild(this.minimap_circle);\n }\n },\n redraw: function(_dontRedrawEdges) {\n var _model_coords = new paper.Point(this.model.get(\"position\")),\n _baseRadius = this.options.node_size_base * Math.exp((this.model.get(\"size\") || 0) * Utils._NODE_SIZE_STEP);\n if (!this.is_dragging || !this.paper_coords) {\n this.paper_coords = this.renderer.toPaperCoords(_model_coords);\n }\n this.circle_radius = _baseRadius * this.renderer.scale;\n if (this.last_circle_radius !== this.circle_radius) {\n this.all_buttons.forEach(function(b) {\n b.setSectorSize();\n });\n this.circle.scale(this.circle_radius / this.last_circle_radius);\n if (this.node_image) {\n this.node_image.scale(this.circle_radius / this.last_circle_radius);\n }\n }\n this.circle.position = this.paper_coords;\n if (this.node_image) {\n this.node_image.position = this.paper_coords.subtract(this.image_delta.multiply(this.circle_radius));\n }\n this.last_circle_radius = this.circle_radius;\n\n var old_act_btn = this.active_buttons;\n\n var opacity = 1;\n if (this.model.get(\"delete_scheduled\")) {\n opacity = 0.5;\n this.active_buttons = this.pending_delete_buttons;\n this.circle.dashArray = [2,2];\n } else {\n opacity = 1;\n this.active_buttons = this.normal_buttons;\n this.circle.dashArray = null;\n }\n\n if (this.selected && this.renderer.isEditable()) {\n if (old_act_btn !== this.active_buttons) {\n old_act_btn.forEach(function(b) {\n b.hide();\n });\n }\n this.active_buttons.forEach(function(b) {\n b.show();\n });\n }\n\n if (this.node_image) {\n this.node_image.opacity = this.highlighted ? opacity * 0.5 : (opacity - 0.01);\n }\n\n this.circle.fillColor = this.highlighted ? this.options.highlighted_node_fill_color : this.options.node_fill_color;\n\n this.circle.opacity = this.options.show_node_circles ? opacity : 0.01;\n\n var _text = this.model.get(\"title\") || this.renkan.translate(this.options.label_untitled_nodes) || \"\";\n _text = Utils.shortenText(_text, this.options.node_label_max_length);\n\n if (typeof this.highlighted === \"object\") {\n this.title.html(this.highlighted.replace(_(_text).escape(),'<span class=\"Rk-Highlighted\">$1</span>'));\n } else {\n this.title.text(_text);\n }\n\n this.title.css({\n left: this.paper_coords.x,\n top: this.paper_coords.y + this.circle_radius * this.h_ratio + this.options.node_label_distance,\n opacity: opacity\n });\n var _color = this.model.get(\"color\") || (this.model.get(\"created_by\") || Utils._USER_PLACEHOLDER(this.renkan)).get(\"color\");\n this.circle.strokeColor = _color;\n var _pc = this.paper_coords;\n this.all_buttons.forEach(function(b) {\n b.moveTo(_pc);\n });\n var lastImage = this.img;\n this.img = this.model.get(\"image\");\n if (this.img && this.img !== lastImage) {\n this.showImage();\n }\n if (this.node_image && !this.img) {\n this.node_image.remove();\n delete this.node_image;\n }\n\n if (this.renderer.minimap) {\n this.minimap_circle.fillColor = _color;\n var minipos = this.renderer.toMinimapCoords(_model_coords),\n miniradius = this.renderer.minimap.scale * _baseRadius,\n minisize = new paper.Size([miniradius, miniradius]);\n this.minimap_circle.fitBounds(minipos.subtract(minisize), minisize.multiply(2));\n }\n\n if (!_dontRedrawEdges) {\n var _this = this;\n _.each(\n this.project.get(\"edges\").filter(\n function (ed) {\n return ((ed.get(\"to\") === _this.model) || (ed.get(\"from\") === _this.model));\n }\n ),\n function(edge, index, list) {\n var repr = _this.renderer.getRepresentationByModel(edge);\n if (repr && typeof repr.from_representation !== \"undefined\" && typeof repr.from_representation.paper_coords !== \"undefined\" && typeof repr.to_representation !== \"undefined\" && typeof repr.to_representation.paper_coords !== \"undefined\") {\n repr.redraw();\n }\n }\n );\n }\n\n },\n showImage: function() {\n var _image = null;\n if (typeof this.renderer.image_cache[this.img] === \"undefined\") {\n _image = new Image();\n this.renderer.image_cache[this.img] = _image;\n _image.src = this.img;\n } else {\n _image = this.renderer.image_cache[this.img];\n }\n if (_image.width) {\n if (this.node_image) {\n this.node_image.remove();\n }\n this.renderer.node_layer.activate();\n var width = _image.width,\n height = _image.height,\n clipPath = this.model.get(\"clip_path\"),\n hasClipPath = (typeof clipPath !== \"undefined\" && clipPath),\n _clip = null,\n baseRadius = null,\n centerPoint = null;\n\n if (hasClipPath) {\n _clip = new paper.Path();\n var instructions = clipPath.match(/[a-z][^a-z]+/gi) || [],\n lastCoords = [0,0],\n minX = Infinity,\n minY = Infinity,\n maxX = -Infinity,\n maxY = -Infinity;\n\n var transformCoords = function(tabc, relative) {\n var newCoords = tabc.slice(1).map(function(v, k) {\n var res = parseFloat(v),\n isY = k % 2;\n if (isY) {\n res = ( res - 0.5 ) * height;\n } else {\n res = ( res - 0.5 ) * width;\n }\n if (relative) {\n res += lastCoords[isY];\n }\n if (isY) {\n minY = Math.min(minY, res);\n maxY = Math.max(maxY, res);\n } else {\n minX = Math.min(minX, res);\n maxX = Math.max(maxX, res);\n }\n return res;\n });\n lastCoords = newCoords.slice(-2);\n return newCoords;\n };\n\n instructions.forEach(function(instr) {\n var coords = instr.match(/([a-z]|[0-9.-]+)/ig) || [\"\"];\n switch(coords[0]) {\n case \"M\":\n _clip.moveTo(transformCoords(coords));\n break;\n case \"m\":\n _clip.moveTo(transformCoords(coords, true));\n break;\n case \"L\":\n _clip.lineTo(transformCoords(coords));\n break;\n case \"l\":\n _clip.lineTo(transformCoords(coords, true));\n break;\n case \"C\":\n _clip.cubicCurveTo(transformCoords(coords));\n break;\n case \"c\":\n _clip.cubicCurveTo(transformCoords(coords, true));\n break;\n case \"Q\":\n _clip.quadraticCurveTo(transformCoords(coords));\n break;\n case \"q\":\n _clip.quadraticCurveTo(transformCoords(coords, true));\n break;\n }\n });\n\n baseRadius = Math[this.options.node_images_fill_mode ? \"min\" : \"max\"](maxX - minX, maxY - minY) / 2;\n centerPoint = new paper.Point((maxX + minX) / 2, (maxY + minY) / 2);\n if (!this.options.show_node_circles) {\n this.h_ratio = (maxY - minY) / (2 * baseRadius);\n }\n } else {\n baseRadius = Math[this.options.node_images_fill_mode ? \"min\" : \"max\"](width, height) / 2;\n centerPoint = new paper.Point(0,0);\n if (!this.options.show_node_circles) {\n this.h_ratio = height / (2 * baseRadius);\n }\n }\n var _raster = new paper.Raster(_image);\n _raster.locked = true; // Disable mouse events on icon\n if (hasClipPath) {\n _raster = new paper.Group(_clip, _raster);\n _raster.opacity = 0.99;\n /* This is a workaround to allow clipping at group level\n * If opacity was set to 1, paper.js would merge all clipping groups in one (known bug).\n */\n _raster.clipped = true;\n _clip.__representation = this;\n }\n if (this.options.clip_node_images) {\n var _circleClip = new paper.Path.Circle(centerPoint, baseRadius);\n _raster = new paper.Group(_circleClip, _raster);\n _raster.opacity = 0.99;\n _raster.clipped = true;\n _circleClip.__representation = this;\n }\n this.image_delta = centerPoint.divide(baseRadius);\n this.node_image = _raster;\n this.node_image.__representation = _this;\n this.node_image.scale(this.circle_radius / baseRadius);\n this.node_image.position = this.paper_coords.subtract(this.image_delta.multiply(this.circle_radius));\n this.redraw();\n this.renderer.throttledPaperDraw();\n } else {\n var _this = this;\n $(_image).on(\"load\", function() {\n _this.showImage();\n });\n }\n },\n paperShift: function(_delta) {\n if (this.options.editor_mode) {\n if (!this.renkan.read_only) {\n this.is_dragging = true;\n this.paper_coords = this.paper_coords.add(_delta);\n this.redraw();\n }\n } else {\n this.renderer.paperShift(_delta);\n }\n },\n openEditor: function() {\n this.renderer.removeRepresentationsOfType(\"editor\");\n var _editor = this.renderer.addRepresentation(\"NodeEditor\",null);\n _editor.source_representation = this;\n _editor.draw();\n },\n select: function() {\n this.selected = true;\n this.circle.strokeWidth = this.options.selected_node_stroke_width;\n if (this.renderer.isEditable()) {\n this.active_buttons.forEach(function(b) {\n b.show();\n });\n }\n var _uri = this.model.get(\"uri\");\n if (_uri) {\n $('.Rk-Bin-Item').each(function() {\n var _el = $(this);\n if (_el.attr(\"data-uri\") === _uri) {\n _el.addClass(\"selected\");\n }\n });\n }\n if (!this.options.editor_mode) {\n this.openEditor();\n }\n\n if (this.renderer.minimap) {\n this.minimap_circle.strokeWidth = this.options.minimap_highlight_weight;\n this.minimap_circle.strokeColor = this.options.minimap_highlight_color;\n }\n this._super(\"select\");\n },\n unselect: function(_newTarget) {\n if (!_newTarget || _newTarget.source_representation !== this) {\n this.selected = false;\n this.all_buttons.forEach(function(b) {\n b.hide();\n });\n this.circle.strokeWidth = this.options.node_stroke_width;\n $('.Rk-Bin-Item').removeClass(\"selected\");\n if (this.renderer.minimap) {\n this.minimap_circle.strokeColor = undefined;\n }\n this._super(\"unselect\");\n }\n },\n highlight: function(textToReplace) {\n var hlvalue = textToReplace || true;\n if (this.highlighted === hlvalue) {\n return;\n }\n this.highlighted = hlvalue;\n this.redraw();\n this.renderer.throttledPaperDraw();\n },\n unhighlight: function() {\n if (!this.highlighted) {\n return;\n }\n this.highlighted = false;\n this.redraw();\n this.renderer.throttledPaperDraw();\n },\n saveCoords: function() {\n var _coords = this.renderer.toModelCoords(this.paper_coords),\n _data = {\n position: {\n x: _coords.x,\n y: _coords.y\n }\n };\n if (this.renderer.isEditable()) {\n this.model.set(_data);\n }\n },\n mousedown: function(_event, _isTouch) {\n if (_isTouch) {\n this.renderer.unselectAll();\n this.select();\n }\n },\n mouseup: function(_event, _isTouch) {\n if (this.renderer.is_dragging && this.renderer.isEditable()) {\n this.saveCoords();\n } else {\n if (!_isTouch && !this.model.get(\"delete_scheduled\")) {\n this.openEditor();\n }\n this.model.trigger(\"clicked\");\n }\n this.renderer.click_target = null;\n this.renderer.is_dragging = false;\n this.is_dragging = false;\n },\n destroy: function(_event) {\n this._super(\"destroy\");\n this.all_buttons.forEach(function(b) {\n b.destroy();\n });\n this.circle.remove();\n this.title.remove();\n if (this.renderer.minimap) {\n this.minimap_circle.remove();\n }\n if (this.node_image) {\n this.node_image.remove();\n }\n }\n });\n\n return NodeRepr;\n\n});\n\n\ndefine('renderer/edge',['jquery', 'underscore', 'requtils', 'renderer/baserepresentation'], function ($, _, requtils, BaseRepresentation) {\n \n\n var Utils = requtils.getUtils();\n\n /* Edge Class Begin */\n\n //var Edge = Renderer.Edge = Utils.inherit(Renderer._BaseRepresentation);\n var Edge = Utils.inherit(BaseRepresentation);\n\n _(Edge.prototype).extend({\n _init: function() {\n this.renderer.edge_layer.activate();\n this.type = \"Edge\";\n this.from_representation = this.renderer.getRepresentationByModel(this.model.get(\"from\"));\n this.to_representation = this.renderer.getRepresentationByModel(this.model.get(\"to\"));\n this.bundle = this.renderer.addToBundles(this);\n this.line = new paper.Path();\n this.line.add([0,0],[0,0],[0,0]);\n this.line.__representation = this;\n this.line.strokeWidth = this.options.edge_stroke_width;\n this.arrow = new paper.Path();\n this.arrow.add(\n [ 0, 0 ],\n [ this.options.edge_arrow_length, this.options.edge_arrow_width / 2 ],\n [ 0, this.options.edge_arrow_width ]\n );\n this.arrow.__representation = this;\n this.text = $('<div class=\"Rk-Label Rk-Edge-Label\">').appendTo(this.renderer.labels_$);\n this.arrow_angle = 0;\n if (this.options.editor_mode) {\n var Renderer = requtils.getRenderer();\n this.normal_buttons = [\n new Renderer.EdgeEditButton(this.renderer, null),\n new Renderer.EdgeRemoveButton(this.renderer, null)\n ];\n this.pending_delete_buttons = [\n new Renderer.EdgeRevertButton(this.renderer, null)\n ];\n this.all_buttons = this.normal_buttons.concat(this.pending_delete_buttons);\n for (var i = 0; i < this.all_buttons.length; i++) {\n this.all_buttons[i].source_representation = this;\n }\n this.active_buttons = [];\n } else {\n this.active_buttons = this.all_buttons = [];\n }\n\n if (this.renderer.minimap) {\n this.renderer.minimap.edge_layer.activate();\n this.minimap_line = new paper.Path();\n this.minimap_line.add([0,0],[0,0]);\n this.minimap_line.__representation = this.renderer.minimap.miniframe.__representation;\n this.minimap_line.strokeWidth = 1;\n }\n },\n redraw: function() {\n var from = this.model.get(\"from\"),\n to = this.model.get(\"to\");\n if (!from || !to) {\n return;\n }\n this.from_representation = this.renderer.getRepresentationByModel(from);\n this.to_representation = this.renderer.getRepresentationByModel(to);\n if (typeof this.from_representation === \"undefined\" || typeof this.to_representation === \"undefined\") {\n return;\n }\n var _p0a = this.from_representation.paper_coords,\n _p1a = this.to_representation.paper_coords,\n _v = _p1a.subtract(_p0a),\n _r = _v.length,\n _u = _v.divide(_r),\n _ortho = new paper.Point([- _u.y, _u.x]),\n _group_pos = this.bundle.getPosition(this),\n _delta = _ortho.multiply( this.options.edge_gap_in_bundles * _group_pos ),\n _p0b = _p0a.add(_delta), /* Adding a 4 px difference */\n _p1b = _p1a.add(_delta), /* to differentiate bundled links */\n _a = _v.angle,\n _textdelta = _ortho.multiply(this.options.edge_label_distance),\n _handle = _v.divide(3),\n _color = this.model.get(\"color\") || this.model.get(\"color\") || (this.model.get(\"created_by\") || Utils._USER_PLACEHOLDER(this.renkan)).get(\"color\"),\n opacity = 1;\n\n if (this.model.get(\"delete_scheduled\") || this.from_representation.model.get(\"delete_scheduled\") || this.to_representation.model.get(\"delete_scheduled\")) {\n opacity = 0.5;\n this.line.dashArray = [2, 2];\n } else {\n opacity = 1;\n this.line.dashArray = null;\n }\n\n var old_act_btn = this.active_buttons;\n\n this.active_buttons = this.model.get(\"delete_scheduled\") ? this.pending_delete_buttons : this.normal_buttons;\n\n if (this.selected && this.renderer.isEditable() && old_act_btn !== this.active_buttons) {\n old_act_btn.forEach(function(b) {\n b.hide();\n });\n this.active_buttons.forEach(function(b) {\n b.show();\n });\n }\n\n this.paper_coords = _p0b.add(_p1b).divide(2);\n this.line.strokeColor = _color;\n this.line.opacity = opacity;\n this.line.segments[0].point = _p0a;\n this.line.segments[1].point = this.paper_coords;\n this.line.segments[1].handleIn = _handle.multiply(-1);\n this.line.segments[1].handleOut = _handle;\n this.line.segments[2].point = _p1a;\n this.arrow.rotate(_a - this.arrow_angle);\n this.arrow.fillColor = _color;\n this.arrow.opacity = opacity;\n this.arrow.position = this.paper_coords;\n this.arrow_angle = _a;\n if (_a > 90) {\n _a -= 180;\n _textdelta = _textdelta.multiply(-1);\n }\n if (_a < -90) {\n _a += 180;\n _textdelta = _textdelta.multiply(-1);\n }\n var _text = this.model.get(\"title\") || this.renkan.translate(this.options.label_untitled_edges) || \"\";\n _text = Utils.shortenText(_text, this.options.node_label_max_length);\n this.text.text(_text);\n var _textpos = this.paper_coords.add(_textdelta);\n this.text.css({\n left: _textpos.x,\n top: _textpos.y,\n transform: \"rotate(\" + _a + \"deg)\",\n \"-moz-transform\": \"rotate(\" + _a + \"deg)\",\n \"-webkit-transform\": \"rotate(\" + _a + \"deg)\",\n opacity: opacity\n });\n this.text_angle = _a;\n\n var _pc = this.paper_coords;\n this.all_buttons.forEach(function(b) {\n b.moveTo(_pc);\n });\n\n if (this.renderer.minimap) {\n this.minimap_line.strokeColor = _color;\n this.minimap_line.segments[0].point = this.renderer.toMinimapCoords(new paper.Point(this.from_representation.model.get(\"position\")));\n this.minimap_line.segments[1].point = this.renderer.toMinimapCoords(new paper.Point(this.to_representation.model.get(\"position\")));\n }\n },\n openEditor: function() {\n this.renderer.removeRepresentationsOfType(\"editor\");\n var _editor = this.renderer.addRepresentation(\"EdgeEditor\",null);\n _editor.source_representation = this;\n _editor.draw();\n },\n select: function() {\n this.selected = true;\n this.line.strokeWidth = this.options.selected_edge_stroke_width;\n if (this.renderer.isEditable()) {\n this.active_buttons.forEach(function(b) {\n b.show();\n });\n }\n if (!this.options.editor_mode) {\n this.openEditor();\n }\n this._super(\"select\");\n },\n unselect: function(_newTarget) {\n if (!_newTarget || _newTarget.source_representation !== this) {\n this.selected = false;\n if (this.options.editor_mode) {\n this.all_buttons.forEach(function(b) {\n b.hide();\n });\n }\n this.line.strokeWidth = this.options.edge_stroke_width;\n this._super(\"unselect\");\n }\n },\n mousedown: function(_event, _isTouch) {\n if (_isTouch) {\n this.renderer.unselectAll();\n this.select();\n }\n },\n mouseup: function(_event, _isTouch) {\n if (!this.renkan.read_only && this.renderer.is_dragging) {\n this.from_representation.saveCoords();\n this.to_representation.saveCoords();\n this.from_representation.is_dragging = false;\n this.to_representation.is_dragging = false;\n } else {\n if (!_isTouch) {\n this.openEditor();\n }\n this.model.trigger(\"clicked\");\n }\n this.renderer.click_target = null;\n this.renderer.is_dragging = false;\n },\n paperShift: function(_delta) {\n if (this.options.editor_mode) {\n if (!this.options.read_only) {\n this.from_representation.paperShift(_delta);\n this.to_representation.paperShift(_delta);\n }\n } else {\n this.renderer.paperShift(_delta);\n }\n },\n destroy: function() {\n this._super(\"destroy\");\n this.line.remove();\n this.arrow.remove();\n this.text.remove();\n if (this.renderer.minimap) {\n this.minimap_line.remove();\n }\n this.all_buttons.forEach(function(b) {\n b.destroy();\n });\n var _this = this;\n this.bundle.edges = _(this.bundle.edges).reject(function(_edge) {\n return _this === _edge;\n });\n }\n });\n\n return Edge;\n\n});\n\n\n\ndefine('renderer/tempedge',['jquery', 'underscore', 'requtils', 'renderer/baserepresentation'], function ($, _, requtils, BaseRepresentation) {\n \n\n var Utils = requtils.getUtils();\n\n /* TempEdge Class Begin */\n\n //var TempEdge = Renderer.TempEdge = Utils.inherit(Renderer._BaseRepresentation);\n var TempEdge = Utils.inherit(BaseRepresentation);\n\n _(TempEdge.prototype).extend({\n _init: function() {\n this.renderer.edge_layer.activate();\n this.type = \"Temp-edge\";\n\n var _color = (this.project.get(\"users\").get(this.renkan.current_user) || Utils._USER_PLACEHOLDER(this.renkan)).get(\"color\");\n this.line = new paper.Path();\n this.line.strokeColor = _color;\n this.line.dashArray = [4, 2];\n this.line.strokeWidth = this.options.selected_edge_stroke_width;\n this.line.add([0,0],[0,0]);\n this.line.__representation = this;\n this.arrow = new paper.Path();\n this.arrow.fillColor = _color;\n this.arrow.add(\n [ 0, 0 ],\n [ this.options.edge_arrow_length, this.options.edge_arrow_width / 2 ],\n [ 0, this.options.edge_arrow_width ]\n );\n this.arrow.__representation = this;\n this.arrow_angle = 0;\n },\n redraw: function() {\n var _p0 = this.from_representation.paper_coords,\n _p1 = this.end_pos,\n _a = _p1.subtract(_p0).angle,\n _c = _p0.add(_p1).divide(2);\n this.line.segments[0].point = _p0;\n this.line.segments[1].point = _p1;\n this.arrow.rotate(_a - this.arrow_angle);\n this.arrow.position = _c;\n this.arrow_angle = _a;\n },\n paperShift: function(_delta) {\n if (!this.renderer.isEditable()) {\n this.renderer.removeRepresentation(_this);\n paper.view.draw();\n return;\n }\n this.end_pos = this.end_pos.add(_delta);\n var _hitResult = paper.project.hitTest(this.end_pos);\n this.renderer.findTarget(_hitResult);\n this.redraw();\n },\n mouseup: function(_event, _isTouch) {\n var _hitResult = paper.project.hitTest(_event.point),\n _model = this.from_representation.model,\n _endDrag = true;\n if (_hitResult && typeof _hitResult.item.__representation !== \"undefined\") {\n var _target = _hitResult.item.__representation;\n if (_target.type.substr(0,4) === \"Node\") {\n var _destmodel = _target.model || _target.source_representation.model;\n if (_model !== _destmodel) {\n var _data = {\n id: Utils.getUID('edge'),\n created_by: this.renkan.current_user,\n from: _model,\n to: _destmodel\n };\n if (this.renderer.isEditable()) {\n this.project.addEdge(_data);\n }\n }\n }\n\n if (_model === _target.model || (_target.source_representation && _target.source_representation.model === _model)) {\n _endDrag = false;\n this.renderer.is_dragging = true;\n }\n }\n if (_endDrag) {\n this.renderer.click_target = null;\n this.renderer.is_dragging = false;\n this.renderer.removeRepresentation(this);\n paper.view.draw();\n }\n },\n destroy: function() {\n this.arrow.remove();\n this.line.remove();\n }\n });\n\n /* TempEdge Class End */\n\n return TempEdge;\n\n});\n\n\ndefine('renderer/baseeditor',['jquery', 'underscore', 'requtils', 'renderer/baserepresentation'], function ($, _, requtils, BaseRepresentation) {\n \n\n var Utils = requtils.getUtils();\n\n /* _BaseEditor Begin */\n //var _BaseEditor = Renderer._BaseEditor = Utils.inherit(Renderer._BaseRepresentation);\n var _BaseEditor = Utils.inherit(BaseRepresentation);\n\n _(_BaseEditor.prototype).extend({\n _init: function() {\n this.renderer.buttons_layer.activate();\n this.type = \"editor\";\n this.editor_block = new paper.Path();\n var _pts = _(_.range(8)).map(function() {return [0,0];});\n this.editor_block.add.apply(this.editor_block, _pts);\n this.editor_block.strokeWidth = this.options.tooltip_border_width;\n this.editor_block.strokeColor = this.options.tooltip_border_color;\n this.editor_block.opacity = 0.8;\n this.editor_$ = $('<div>')\n .appendTo(this.renderer.editor_$)\n .css({\n position: \"absolute\",\n opacity: 0.8\n })\n .hide();\n },\n destroy: function() {\n this.editor_block.remove();\n this.editor_$.remove();\n }\n });\n\n /* _BaseEditor End */\n\n return _BaseEditor;\n\n});\n\n\ndefine('renderer/nodeeditor',['jquery', 'underscore', 'requtils', 'renderer/baseeditor'], function ($, _, requtils, BaseEditor) {\n \n\n var Utils = requtils.getUtils();\n\n /* NodeEditor Begin */\n //var NodeEditor = Renderer.NodeEditor = Utils.inherit(Renderer._BaseEditor);\n var NodeEditor = Utils.inherit(BaseEditor);\n\n _(NodeEditor.prototype).extend({\n template: _.template(\n '<h2><span class=\"Rk-CloseX\">×</span><%-renkan.translate(\"Edit Node\")%></span></h2>' +\n '<p><label><%-renkan.translate(\"Title:\")%></label><input class=\"Rk-Edit-Title\" type=\"text\" value=\"<%-node.title%>\"/></p>' +\n '<% if (options.show_node_editor_uri) { %><p><label><%-renkan.translate(\"URI:\")%></label><input class=\"Rk-Edit-URI\" type=\"text\" value=\"<%-node.uri%>\"/><a class=\"Rk-Edit-Goto\" href=\"<%-node.uri%>\" target=\"_blank\"></a></p><% } %>' +\n '<% if (options.show_node_editor_description) { %><p><label><%-renkan.translate(\"Description:\")%></label><textarea class=\"Rk-Edit-Description\"><%-node.description%></textarea></p><% } %>' +\n '<% if (options.show_node_editor_size) { %><p><span class=\"Rk-Editor-Label\"><%-renkan.translate(\"Size:\")%></span><a href=\"#\" class=\"Rk-Edit-Size-Down\">-</a><span class=\"Rk-Edit-Size-Value\"><%-node.size%></span><a href=\"#\" class=\"Rk-Edit-Size-Up\">+</a></p><% } %>' +\n '<% if (options.show_node_editor_color) { %><div class=\"Rk-Editor-p\"><span class=\"Rk-Editor-Label\"><%-renkan.translate(\"Node color:\")%></span><div class=\"Rk-Edit-ColorPicker-Wrapper\"><span class=\"Rk-Edit-Color\" style=\"background:<%-node.color%>;\"><span class=\"Rk-Edit-ColorTip\"></span></span>' +\n '<%= renkan.colorPicker %><span class=\"Rk-Edit-ColorPicker-Text\"><%- renkan.translate(\"Choose color\") %></span></div></div><% } %>' +\n '<% if (options.show_node_editor_image) { %><div class=\"Rk-Edit-ImgWrap\"><div class=\"Rk-Edit-ImgPreview\"><img src=\"<%-node.image || node.image_placeholder%>\" />' +\n '<% if (node.clip_path) { %><svg xmlns=\"http://www.w3.org/2000/svg\" version=\"1.1\" viewbox=\"0 0 1 1\" preserveAspectRatio=\"none\"><path style=\"stroke-width: .02; stroke:red; fill-opacity:.3; fill:red;\" d=\"<%- node.clip_path %>\"/></svg><% }%>' +\n '</div></div><p><label><%-renkan.translate(\"Image URL:\")%></label><input class=\"Rk-Edit-Image\" type=\"text\" value=\"<%-node.image%>\"/></p>' +\n '<p><label><%-renkan.translate(\"Choose Image File:\")%></label><input class=\"Rk-Edit-Image-File\" type=\"file\" accept=\"image/*\"/></p><% } %>' +\n '<% if (options.show_node_editor_creator && node.has_creator) { %><p><span class=\"Rk-Editor-Label\"><%-renkan.translate(\"Created by:\")%></span> <span class=\"Rk-UserColor\" style=\"background:<%-node.created_by_color%>;\"></span><%- shortenText(node.created_by_title, 25) %></p><% } %>'\n ),\n readOnlyTemplate: _.template(\n '<h2><span class=\"Rk-CloseX\">×</span><% if (options.show_node_tooltip_color) { %><span class=\"Rk-UserColor\" style=\"background:<%-node.color%>;\"></span><% } %>' +\n '<span class=\"Rk-Display-Title\"><% if (node.uri) { %><a href=\"<%-node.uri%>\" target=\"_blank\"><% } %><%-node.title%><% if (node.uri) { %></a><% } %></span></h2>' +\n '<% if (node.uri && options.show_node_tooltip_uri) { %><p class=\"Rk-Display-URI\"><a href=\"<%-node.uri%>\" target=\"_blank\"><%-node.short_uri%></a></p><% } %>' +\n '<% if (options.show_node_tooltip_description) { %><p class=\"Rk-Display-Description\"><%-node.description%></p><% } %>' +\n '<% if (node.image && options.show_node_tooltip_image) { %><img class=\"Rk-Display-ImgPreview\" src=\"<%-node.image%>\" /><% } %>' +\n '<% if (node.has_creator && options.show_node_tooltip_creator) { %><p><span class=\"Rk-Editor-Label\"><%-renkan.translate(\"Created by:\")%></span><span class=\"Rk-UserColor\" style=\"background:<%-node.created_by_color%>;\"></span><%- shortenText(node.created_by_title, 25) %></p><% } %>'\n ),\n draw: function() {\n var _model = this.source_representation.model,\n _created_by = _model.get(\"created_by\") || Utils._USER_PLACEHOLDER(this.renkan),\n _template = (this.renderer.isEditable() ? this.template : this.readOnlyTemplate ),\n _image_placeholder = this.options.static_url + \"img/image-placeholder.png\",\n _size = (_model.get(\"size\") || 0);\n this.editor_$\n .html(_template({\n node: {\n has_creator: !!_model.get(\"created_by\"),\n title: _model.get(\"title\"),\n uri: _model.get(\"uri\"),\n short_uri: Utils.shortenText((_model.get(\"uri\") || \"\").replace(/^(https?:\\/\\/)?(www\\.)?/,'').replace(/\\/$/,''),40),\n description: _model.get(\"description\"),\n image: _model.get(\"image\") || \"\",\n image_placeholder: _image_placeholder,\n color: _model.get(\"color\") || _created_by.get(\"color\"),\n clip_path: _model.get(\"clip_path\") || false,\n created_by_color: _created_by.get(\"color\"),\n created_by_title: _created_by.get(\"title\"),\n size: (_size > 0 ? \"+\" : \"\") + _size\n },\n renkan: this.renkan,\n options: this.options,\n shortenText: Utils.shortenText\n }));\n this.redraw();\n var _this = this,\n closeEditor = function() {\n _this.renderer.removeRepresentation(_this);\n paper.view.draw();\n };\n\n this.editor_$.find(\".Rk-CloseX\").click(closeEditor);\n\n this.editor_$.find(\".Rk-Edit-Goto\").click(function() {\n if (!_model.get(\"uri\")) {\n return false;\n }\n });\n\n if (this.renderer.isEditable()) {\n\n var onFieldChange = _(function() {\n _(function() {\n if (_this.renderer.isEditable()) {\n var _data = {\n title: _this.editor_$.find(\".Rk-Edit-Title\").val()\n };\n if (_this.options.show_node_editor_uri) {\n _data.uri = _this.editor_$.find(\".Rk-Edit-URI\").val();\n _this.editor_$.find(\".Rk-Edit-Goto\").attr(\"href\",_data.uri || \"#\");\n }\n if (_this.options.show_node_editor_image) {\n _data.image = _this.editor_$.find(\".Rk-Edit-Image\").val();\n _this.editor_$.find(\".Rk-Edit-ImgPreview\").attr(\"src\", _data.image || _image_placeholder);\n }\n if (_this.options.show_node_editor_description) {\n _data.description = _this.editor_$.find(\".Rk-Edit-Description\").val();\n }\n _model.set(_data);\n _this.redraw();\n } else {\n closeEditor();\n }\n\n }).defer();\n }).throttle(500);\n\n this.editor_$.on(\"keyup\", function(_e) {\n if (_e.keyCode === 27) {\n closeEditor();\n }\n });\n\n this.editor_$.find(\"input, textarea\").on(\"change keyup paste\", onFieldChange);\n\n this.editor_$.find(\".Rk-Edit-Image-File\").change(function() {\n if (this.files.length) {\n var f = this.files[0],\n fr = new FileReader();\n if (f.type.substr(0,5) !== \"image\") {\n alert(_this.renkan.translate(\"This file is not an image\"));\n return;\n }\n if (f.size > (_this.options.uploaded_image_max_kb * 1024)) {\n alert(_this.renkan.translate(\"Image size must be under \") + _this.options.uploaded_image_max_kb + _this.renkan.translate(\"KB\"));\n return;\n }\n fr.onload = function(e) {\n _this.editor_$.find(\".Rk-Edit-Image\").val(e.target.result);\n onFieldChange();\n };\n fr.readAsDataURL(f);\n }\n });\n this.editor_$.find(\".Rk-Edit-Title\")[0].focus();\n\n var _picker = _this.editor_$.find(\".Rk-Edit-ColorPicker\");\n\n this.editor_$.find(\".Rk-Edit-ColorPicker-Wrapper\").hover(\n function(_e) {\n _e.preventDefault();\n _picker.show();\n },\n function(_e) {\n _e.preventDefault();\n _picker.hide();\n }\n );\n\n _picker.find(\"li\").hover(\n function(_e) {\n _e.preventDefault();\n _this.editor_$.find(\".Rk-Edit-Color\").css(\"background\", $(this).attr(\"data-color\"));\n },\n function(_e) {\n _e.preventDefault();\n _this.editor_$.find(\".Rk-Edit-Color\").css(\"background\", _model.get(\"color\") || (_model.get(\"created_by\") || Utils._USER_PLACEHOLDER(_this.renkan)).get(\"color\"));\n }\n ).click(function(_e) {\n _e.preventDefault();\n if (_this.renderer.isEditable()) {\n _model.set(\"color\", $(this).attr(\"data-color\"));\n _picker.hide();\n paper.view.draw();\n } else {\n closeEditor();\n }\n });\n\n var shiftSize = function(n) {\n if (_this.renderer.isEditable()) {\n var _newsize = n+(_model.get(\"size\") || 0);\n _this.editor_$.find(\".Rk-Edit-Size-Value\").text((_newsize > 0 ? \"+\" : \"\") + _newsize);\n _model.set(\"size\", _newsize);\n paper.view.draw();\n } else {\n closeEditor();\n }\n };\n\n this.editor_$.find(\".Rk-Edit-Size-Down\").click(function() {\n shiftSize(-1);\n return false;\n });\n this.editor_$.find(\".Rk-Edit-Size-Up\").click(function() {\n shiftSize(1);\n return false;\n });\n } else {\n if (typeof this.source_representation.highlighted === \"object\") {\n var titlehtml = this.source_representation.highlighted.replace(_(_model.get(\"title\")).escape(),'<span class=\"Rk-Highlighted\">$1</span>');\n this.editor_$.find(\".Rk-Display-Title\" + (_model.get(\"uri\") ? \" a\" : \"\")).html(titlehtml);\n if (this.options.show_node_tooltip_description) {\n this.editor_$.find(\".Rk-Display-Description\").html(this.source_representation.highlighted.replace(_(_model.get(\"description\")).escape(),'<span class=\"Rk-Highlighted\">$1</span>'));\n }\n }\n }\n this.editor_$.find(\"img\").load(function() {\n _this.redraw();\n });\n },\n redraw: function() {\n var _coords = this.source_representation.paper_coords;\n Utils.drawEditBox(this.options, _coords, this.editor_block, this.source_representation.circle_radius * 0.75, this.editor_$);\n this.editor_$.show();\n paper.view.draw();\n }\n });\n\n /* NodeEditor End */\n\n return NodeEditor;\n\n});\n\n\ndefine('renderer/edgeeditor',['jquery', 'underscore', 'requtils', 'renderer/baseeditor'], function ($, _, requtils, BaseEditor) {\n \n\n var Utils = requtils.getUtils();\n\n /* EdgeEditor Begin */\n\n //var EdgeEditor = Renderer.EdgeEditor = Utils.inherit(Renderer._BaseEditor);\n var EdgeEditor = Utils.inherit(BaseEditor);\n\n _(EdgeEditor.prototype).extend({\n template: _.template(\n '<h2><span class=\"Rk-CloseX\">×</span><%-renkan.translate(\"Edit Edge\")%></span></h2>' +\n '<p><label><%-renkan.translate(\"Title:\")%></label><input class=\"Rk-Edit-Title\" type=\"text\" value=\"<%-edge.title%>\"/></p>' +\n '<% if (options.show_edge_editor_uri) { %><p><label><%-renkan.translate(\"URI:\")%></label><input class=\"Rk-Edit-URI\" type=\"text\" value=\"<%-edge.uri%>\"/><a class=\"Rk-Edit-Goto\" href=\"<%-edge.uri%>\" target=\"_blank\"></a></p>' +\n '<% if (options.properties.length) { %><p><label><%-renkan.translate(\"Choose from vocabulary:\")%></label><select class=\"Rk-Edit-Vocabulary\">' +\n '<% _(options.properties).each(function(ontology) { %><option class=\"Rk-Edit-Vocabulary-Class\" value=\"\"><%- renkan.translate(ontology.label) %></option>' +\n '<% _(ontology.properties).each(function(property) { var uri = ontology[\"base-uri\"] + property.uri; %><option class=\"Rk-Edit-Vocabulary-Property\" value=\"<%- uri %>' +\n '\"<% if (uri === edge.uri) { %> selected<% } %>><%- renkan.translate(property.label) %></option>' +\n '<% }) %><% }) %></select></p><% } } %>' +\n '<% if (options.show_edge_editor_color) { %><div class=\"Rk-Editor-p\"><span class=\"Rk-Editor-Label\"><%-renkan.translate(\"Edge color:\")%></span><div class=\"Rk-Edit-ColorPicker-Wrapper\"><span class=\"Rk-Edit-Color\" style=\"background:<%-edge.color%>;\"><span class=\"Rk-Edit-ColorTip\"></span></span>' +\n '<%= renkan.colorPicker %><span class=\"Rk-Edit-ColorPicker-Text\"><%- renkan.translate(\"Choose color\") %></span></div></div><% } %>' +\n '<% if (options.show_edge_editor_direction) { %><p><span class=\"Rk-Edit-Direction\"><%- renkan.translate(\"Change edge direction\") %></span></p><% } %>' +\n '<% if (options.show_edge_editor_nodes) { %><p><span class=\"Rk-Editor-Label\"><%-renkan.translate(\"From:\")%></span><span class=\"Rk-UserColor\" style=\"background:<%-edge.from_color%>;\"></span><%- shortenText(edge.from_title, 25) %></p>' +\n '<p><span class=\"Rk-Editor-Label\"><%-renkan.translate(\"To:\")%></span><span class=\"Rk-UserColor\" style=\"background:<%-edge.to_color%>;\"></span><%- shortenText(edge.to_title, 25) %></p><% } %>' +\n '<% if (options.show_edge_editor_creator && edge.has_creator) { %><p><span class=\"Rk-Editor-Label\"><%-renkan.translate(\"Created by:\")%></span><span class=\"Rk-UserColor\" style=\"background:<%-edge.created_by_color%>;\"></span><%- shortenText(edge.created_by_title, 25) %></p><% } %>'\n ),\n readOnlyTemplate: _.template(\n '<h2><span class=\"Rk-CloseX\">×</span><% if (options.show_edge_tooltip_color) { %><span class=\"Rk-UserColor\" style=\"background:<%-edge.color%>;\"></span><% } %>' +\n '<span class=\"Rk-Display-Title\"><% if (edge.uri) { %><a href=\"<%-edge.uri%>\" target=\"_blank\"><% } %><%-edge.title%><% if (edge.uri) { %></a><% } %></span></h2>' +\n '<% if (options.show_edge_tooltip_uri && edge.uri) { %><p class=\"Rk-Display-URI\"><a href=\"<%-edge.uri%>\" target=\"_blank\"><%-edge.short_uri%></a></p><% } %>' +\n '<p><%-edge.description%></p>' +\n '<% if (options.show_edge_tooltip_nodes) { %><p><span class=\"Rk-Editor-Label\"><%-renkan.translate(\"From:\")%></span><span class=\"Rk-UserColor\" style=\"background:<%-edge.from_color%>;\"></span><%- shortenText(edge.from_title, 25) %></p>' +\n '<p><span class=\"Rk-Editor-Label\"><%-renkan.translate(\"To:\")%></span><span class=\"Rk-UserColor\" style=\"background:<%-edge.to_color%>;\"></span><%- shortenText(edge.to_title, 25) %></p><% } %>' +\n '<% if (options.show_edge_tooltip_creator && edge.has_creator) { %><p><span class=\"Rk-Editor-Label\"><%-renkan.translate(\"Created by:\")%></span><span class=\"Rk-UserColor\" style=\"background:<%-edge.created_by_color%>;\"></span><%- shortenText(edge.created_by_title, 25) %></p><% } %>'\n ),\n draw: function() {\n var _model = this.source_representation.model,\n _from_model = _model.get(\"from\"),\n _to_model = _model.get(\"to\"),\n _created_by = _model.get(\"created_by\") || Utils._USER_PLACEHOLDER(this.renkan),\n _template = (this.renderer.isEditable() ? this.template : this.readOnlyTemplate);\n this.editor_$\n .html(_template({\n edge: {\n has_creator: !!_model.get(\"created_by\"),\n title: _model.get(\"title\"),\n uri: _model.get(\"uri\"),\n short_uri: Utils.shortenText((_model.get(\"uri\") || \"\").replace(/^(https?:\\/\\/)?(www\\.)?/,'').replace(/\\/$/,''),40),\n description: _model.get(\"description\"),\n color: _model.get(\"color\") || _created_by.get(\"color\"),\n from_title: _from_model.get(\"title\"),\n to_title: _to_model.get(\"title\"),\n from_color: _from_model.get(\"color\") || (_from_model.get(\"created_by\") || Utils._USER_PLACEHOLDER(this.renkan)).get(\"color\"),\n to_color: _to_model.get(\"color\") || (_to_model.get(\"created_by\") || Utils._USER_PLACEHOLDER(this.renkan)).get(\"color\"),\n created_by_color: _created_by.get(\"color\"),\n created_by_title: _created_by.get(\"title\")\n },\n renkan: this.renkan,\n shortenText: Utils.shortenText,\n options: this.options\n }));\n this.redraw();\n var _this = this,\n closeEditor = function() {\n _this.renderer.removeRepresentation(_this);\n paper.view.draw();\n };\n this.editor_$.find(\".Rk-CloseX\").click(closeEditor);\n this.editor_$.find(\".Rk-Edit-Goto\").click(function() {\n if (!_model.get(\"uri\")) {\n return false;\n }\n });\n\n if (this.renderer.isEditable()) {\n\n var onFieldChange = _(function() {\n _(function() {\n if (_this.renderer.isEditable()) {\n var _data = {\n title: _this.editor_$.find(\".Rk-Edit-Title\").val()\n };\n if (_this.options.show_edge_editor_uri) {\n _data.uri = _this.editor_$.find(\".Rk-Edit-URI\").val();\n }\n _this.editor_$.find(\".Rk-Edit-Goto\").attr(\"href\",_data.uri || \"#\");\n _model.set(_data);\n paper.view.draw();\n } else {\n closeEditor();\n }\n }).defer();\n }).throttle(500);\n\n this.editor_$.on(\"keyup\", function(_e) {\n if (_e.keyCode === 27) {\n closeEditor();\n }\n });\n\n this.editor_$.find(\"input\").on(\"keyup change paste\", onFieldChange);\n\n this.editor_$.find(\".Rk-Edit-Vocabulary\").change(function() {\n var e = $(this),\n v = e.val();\n if (v) {\n _this.editor_$.find(\".Rk-Edit-Title\").val(e.find(\":selected\").text());\n _this.editor_$.find(\".Rk-Edit-URI\").val(v);\n onFieldChange();\n }\n });\n this.editor_$.find(\".Rk-Edit-Direction\").click(function() {\n if (_this.renderer.isEditable()) {\n _model.set({\n from: _model.get(\"to\"),\n to: _model.get(\"from\")\n });\n _this.draw();\n } else {\n closeEditor();\n }\n });\n\n var _picker = _this.editor_$.find(\".Rk-Edit-ColorPicker\");\n\n this.editor_$.find(\".Rk-Edit-ColorPicker-Wrapper\").hover(\n function(_e) {\n _e.preventDefault();\n _picker.show();\n },\n function(_e) {\n _e.preventDefault();\n _picker.hide();\n }\n );\n\n _picker.find(\"li\").hover(\n function(_e) {\n _e.preventDefault();\n _this.editor_$.find(\".Rk-Edit-Color\").css(\"background\", $(this).attr(\"data-color\"));\n },\n function(_e) {\n _e.preventDefault();\n _this.editor_$.find(\".Rk-Edit-Color\").css(\"background\", _model.get(\"color\") || (_model.get(\"created_by\") || Utils._USER_PLACEHOLDER(_this.renkan)).get(\"color\"));\n }\n ).click(function(_e) {\n _e.preventDefault();\n if (_this.renderer.isEditable()) {\n _model.set(\"color\", $(this).attr(\"data-color\"));\n _picker.hide();\n paper.view.draw();\n } else {\n closeEditor();\n }\n });\n }\n },\n redraw: function() {\n var _coords = this.source_representation.paper_coords;\n Utils.drawEditBox(this.options, _coords, this.editor_block, 5, this.editor_$);\n this.editor_$.show();\n paper.view.draw();\n }\n });\n\n /* EdgeEditor End */\n\n return EdgeEditor;\n\n});\n\n\ndefine('renderer/nodebutton',['jquery', 'underscore', 'requtils', 'renderer/basebutton'], function ($, _, requtils, BaseButton) {\n \n \n var Utils = requtils.getUtils();\n\n /* _NodeButton Begin */\n\n //var _NodeButton = Renderer._NodeButton = Utils.inherit(Renderer._BaseButton);\n var _NodeButton = Utils.inherit(BaseButton);\n\n _(_NodeButton.prototype).extend({\n setSectorSize: function() {\n var sectorInner = this.source_representation.circle_radius;\n if (sectorInner !== this.lastSectorInner) {\n if (this.sector) {\n this.sector.destroy();\n }\n this.sector = this.renderer.drawSector(\n this, 1 + sectorInner,\n Utils._NODE_BUTTON_WIDTH + sectorInner,\n this.startAngle,\n this.endAngle,\n 1,\n this.imageName,\n this.renkan.translate(this.text)\n );\n this.lastSectorInner = sectorInner;\n }\n }\n });\n\n /* _NodeButton End */\n\n return _NodeButton;\n\n});\n\n\ndefine('renderer/nodeeditbutton',['jquery', 'underscore', 'requtils', 'renderer/nodebutton'], function ($, _, requtils, NodeButton) {\n \n\n var Utils = requtils.getUtils();\n\n /* NodeEditButton Begin */\n\n //var NodeEditButton = Renderer.NodeEditButton = Utils.inherit(Renderer._NodeButton);\n var NodeEditButton = Utils.inherit(NodeButton);\n\n _(NodeEditButton.prototype).extend({\n _init: function() {\n this.type = \"Node-edit-button\";\n this.lastSectorInner = 0;\n this.startAngle = -135;\n this.endAngle = -45;\n this.imageName = \"edit\";\n this.text = \"Edit\";\n },\n mouseup: function() {\n if (!this.renderer.is_dragging) {\n this.source_representation.openEditor();\n }\n }\n });\n\n /* NodeEditButton End */\n\n return NodeEditButton;\n\n});\n\n\ndefine('renderer/noderemovebutton',['jquery', 'underscore', 'requtils', 'renderer/nodebutton'], function ($, _, requtils, NodeButton) {\n \n \n var Utils = requtils.getUtils();\n\n /* NodeRemoveButton Begin */\n\n //var NodeRemoveButton = Renderer.NodeRemoveButton = Utils.inherit(Renderer._NodeButton);\n var NodeRemoveButton = Utils.inherit(NodeButton);\n\n _(NodeRemoveButton.prototype).extend({\n _init: function() {\n this.type = \"Node-remove-button\";\n this.lastSectorInner = 0;\n this.startAngle = 0;\n this.endAngle = 90;\n this.imageName = \"remove\";\n this.text = \"Remove\";\n },\n mouseup: function() {\n this.renderer.click_target = null;\n this.renderer.is_dragging = false;\n this.renderer.removeRepresentationsOfType(\"editor\");\n if (this.renderer.isEditable()) {\n if (this.options.element_delete_delay) {\n var delid = Utils.getUID(\"delete\");\n this.renderer.delete_list.push({\n id: delid,\n time: new Date().valueOf() + this.options.element_delete_delay\n });\n this.source_representation.model.set(\"delete_scheduled\", delid);\n } else {\n if (confirm(this.renkan.translate('Do you really wish to remove node ') + '\"' + this.source_representation.model.get(\"title\") + '\"?')) {\n this.project.removeNode(this.source_representation.model);\n }\n }\n }\n }\n });\n\n /* NodeRemoveButton End */\n\n return NodeRemoveButton;\n\n});\n\n\ndefine('renderer/noderevertbutton',['jquery', 'underscore', 'requtils', 'renderer/nodebutton'], function ($, _, requtils, NodeButton) {\n \n\n var Utils = requtils.getUtils();\n\n /* NodeRevertButton Begin */\n\n //var NodeRevertButton = Renderer.NodeRevertButton = Utils.inherit(Renderer._NodeButton);\n var NodeRevertButton = Utils.inherit(NodeButton);\n\n _(NodeRevertButton.prototype).extend({\n _init: function() {\n this.type = \"Node-revert-button\";\n this.lastSectorInner = 0;\n this.startAngle = -135;\n this.endAngle = 135;\n this.imageName = \"revert\";\n this.text = \"Cancel deletion\";\n },\n mouseup: function() {\n this.renderer.click_target = null;\n this.renderer.is_dragging = false;\n if (this.renderer.isEditable()) {\n this.source_representation.model.unset(\"delete_scheduled\");\n }\n }\n });\n\n /* NodeRevertButton End */\n\n return NodeRevertButton;\n\n});\n\n\ndefine('renderer/nodelinkbutton',['jquery', 'underscore', 'requtils', 'renderer/nodebutton'], function ($, _, requtils, NodeButton) {\n \n\n var Utils = requtils.getUtils();\n\n /* NodeLinkButton Begin */\n\n //var NodeLinkButton = Renderer.NodeLinkButton = Utils.inherit(Renderer._NodeButton);\n var NodeLinkButton = Utils.inherit(NodeButton);\n\n _(NodeLinkButton.prototype).extend({\n _init: function() {\n this.type = \"Node-link-button\";\n this.lastSectorInner = 0;\n this.startAngle = 90;\n this.endAngle = 180;\n this.imageName = \"link\";\n this.text = \"Link to another node\";\n },\n mousedown: function(_event, _isTouch) {\n if (this.renderer.isEditable()) {\n var _off = this.renderer.canvas_$.offset(),\n _point = new paper.Point([\n _event.pageX - _off.left,\n _event.pageY - _off.top\n ]);\n this.renderer.click_target = null;\n this.renderer.removeRepresentationsOfType(\"editor\");\n this.renderer.addTempEdge(this.source_representation, _point);\n }\n }\n });\n\n /* NodeLinkButton End */\n\n return NodeLinkButton;\n\n});\n\n\n\ndefine('renderer/nodeenlargebutton',['jquery', 'underscore', 'requtils', 'renderer/nodebutton'], function ($, _, requtils, NodeButton) {\n \n \n var Utils = requtils.getUtils();\n\n /* NodeEnlargeButton Begin */\n\n //var NodeEnlargeButton = Renderer.NodeEnlargeButton = Utils.inherit(Renderer._NodeButton);\n var NodeEnlargeButton = Utils.inherit(NodeButton);\n\n _(NodeEnlargeButton.prototype).extend({\n _init: function() {\n this.type = \"Node-enlarge-button\";\n this.lastSectorInner = 0;\n this.startAngle = -45;\n this.endAngle = 0;\n this.imageName = \"enlarge\";\n this.text = \"Enlarge\";\n },\n mouseup: function() {\n var _newsize = 1 + (this.source_representation.model.get(\"size\") || 0);\n this.source_representation.model.set(\"size\", _newsize);\n this.source_representation.select();\n this.select();\n paper.view.draw();\n }\n });\n\n /* NodeEnlargeButton End */\n\n return NodeEnlargeButton;\n\n});\n\n\ndefine('renderer/nodeshrinkbutton',['jquery', 'underscore', 'requtils', 'renderer/nodebutton'], function ($, _, requtils, NodeButton) {\n \n\n var Utils = requtils.getUtils();\n\n /* NodeShrinkButton Begin */\n\n //var NodeShrinkButton = Renderer.NodeShrinkButton = Utils.inherit(Renderer._NodeButton);\n var NodeShrinkButton = Utils.inherit(NodeButton);\n\n _(NodeShrinkButton.prototype).extend({\n _init: function() {\n this.type = \"Node-shrink-button\";\n this.lastSectorInner = 0;\n this.startAngle = -180;\n this.endAngle = -135;\n this.imageName = \"shrink\";\n this.text = \"Shrink\";\n },\n mouseup: function() {\n var _newsize = -1 + (this.source_representation.model.get(\"size\") || 0);\n this.source_representation.model.set(\"size\", _newsize);\n this.source_representation.select();\n this.select();\n paper.view.draw();\n }\n });\n\n /* NodeShrinkButton End */\n\n return NodeShrinkButton;\n\n});\n\n\ndefine('renderer/edgeeditbutton',['jquery', 'underscore', 'requtils', 'renderer/basebutton'], function ($, _, requtils, BaseButton) {\n \n\n var Utils = requtils.getUtils();\n\n /* EdgeEditButton Begin */\n\n //var EdgeEditButton = Renderer.EdgeEditButton = Utils.inherit(Renderer._BaseButton);\n var EdgeEditButton = Utils.inherit(BaseButton);\n\n _(EdgeEditButton.prototype).extend({\n _init: function() {\n this.type = \"Edge-edit-button\";\n this.sector = this.renderer.drawSector(this, Utils._EDGE_BUTTON_INNER, Utils._EDGE_BUTTON_OUTER, -270, -90, 1, \"edit\", this.renkan.translate(\"Edit\"));\n },\n mouseup: function() {\n if (!this.renderer.is_dragging) {\n this.source_representation.openEditor();\n }\n }\n });\n\n /* EdgeEditButton End */\n\n return EdgeEditButton;\n\n});\n\n\ndefine('renderer/edgeremovebutton',['jquery', 'underscore', 'requtils', 'renderer/basebutton'], function ($, _, requtils, BaseButton) {\n \n\n var Utils = requtils.getUtils();\n\n /* EdgeRemoveButton Begin */\n\n //var EdgeRemoveButton = Renderer.EdgeRemoveButton = Utils.inherit(Renderer._BaseButton);\n var EdgeRemoveButton = Utils.inherit(BaseButton);\n\n _(EdgeRemoveButton.prototype).extend({\n _init: function() {\n this.type = \"Edge-remove-button\";\n this.sector = this.renderer.drawSector(this, Utils._EDGE_BUTTON_INNER, Utils._EDGE_BUTTON_OUTER, -90, 90, 1, \"remove\", this.renkan.translate(\"Remove\"));\n },\n mouseup: function() {\n this.renderer.click_target = null;\n this.renderer.is_dragging = false;\n this.renderer.removeRepresentationsOfType(\"editor\");\n if (this.renderer.isEditable()) {\n if (this.options.element_delete_delay) {\n var delid = Utils.getUID(\"delete\");\n this.renderer.delete_list.push({\n id: delid,\n time: new Date().valueOf() + this.options.element_delete_delay\n });\n this.source_representation.model.set(\"delete_scheduled\", delid);\n } else {\n if (confirm(this.renkan.translate('Do you really wish to remove edge ') + '\"' + this.source_representation.model.get(\"title\") + '\"?')) {\n this.project.removeEdge(this.source_representation.model);\n }\n }\n }\n }\n });\n\n /* EdgeRemoveButton End */\n\n return EdgeRemoveButton;\n\n});\n\n\ndefine('renderer/edgerevertbutton',['jquery', 'underscore', 'requtils', 'renderer/basebutton'], function ($, _, requtils, BaseButton) {\n \n\n var Utils = requtils.getUtils();\n\n /* EdgeRevertButton Begin */\n\n //var EdgeRevertButton = Renderer.EdgeRevertButton = Utils.inherit(Renderer._BaseButton);\n var EdgeRevertButton = Utils.inherit(BaseButton);\n\n _(EdgeRevertButton.prototype).extend({\n _init: function() {\n this.type = \"Edge-revert-button\";\n this.sector = this.renderer.drawSector(this, Utils._EDGE_BUTTON_INNER, Utils._EDGE_BUTTON_OUTER, -135, 135, 1, \"revert\", this.renkan.translate(\"Cancel deletion\"));\n },\n mouseup: function() {\n this.renderer.click_target = null;\n this.renderer.is_dragging = false;\n if (this.renderer.isEditable()) {\n this.source_representation.model.unset(\"delete_scheduled\");\n }\n }\n });\n\n /* EdgeRevertButton End */\n\n return EdgeRevertButton;\n\n});\n\n\ndefine('renderer/miniframe',['jquery', 'underscore', 'requtils', 'renderer/baserepresentation'], function ($, _, requtils, BaseRepresentation) {\n \n\n var Utils = requtils.getUtils();\n\n /* MiniFrame Begin */\n\n //var MiniFrame = Renderer.MiniFrame = Utils.inherit(Renderer._BaseRepresentation);\n var MiniFrame = Utils.inherit(BaseRepresentation);\n\n _(MiniFrame.prototype).extend({\n paperShift: function(_delta) {\n this.renderer.offset = this.renderer.offset.subtract(_delta.divide(this.renderer.minimap.scale).multiply(this.renderer.scale));\n this.renderer.redraw();\n },\n mouseup: function(_delta) {\n this.renderer.click_target = null;\n this.renderer.is_dragging = false;\n }\n });\n\n /* MiniFrame End */\n\n return MiniFrame;\n\n});\n\n\ndefine('renderer/scene',['jquery', 'underscore', 'filesaver', 'requtils', 'renderer/miniframe'], function ($, _, filesaver, requtils, MiniFrame) {\n \n\n var Utils = requtils.getUtils();\n\n /* Scene Begin */\n\n var Scene = function(_renkan) {\n this.renkan = _renkan;\n this.$ = $(\".Rk-Render\");\n this.representations = [];\n this.$.html(this.template(_renkan));\n this.onStatusChange();\n this.canvas_$ = this.$.find(\".Rk-Canvas\");\n this.labels_$ = this.$.find(\".Rk-Labels\");\n this.editor_$ = this.$.find(\".Rk-Editor\");\n this.notif_$ = this.$.find(\".Rk-Notifications\");\n paper.setup(this.canvas_$[0]);\n this.scale = 1;\n this.initialScale = 1;\n this.offset = paper.view.center;\n this.totalScroll = 0;\n this.mouse_down = false;\n this.click_target = null;\n this.selected_target = null;\n this.edge_layer = new paper.Layer();\n this.node_layer = new paper.Layer();\n this.buttons_layer = new paper.Layer();\n this.delete_list = [];\n this.redrawActive = true;\n\n if (_renkan.options.show_minimap) {\n this.minimap = {\n background_layer: new paper.Layer(),\n edge_layer: new paper.Layer(),\n node_layer: new paper.Layer(),\n node_group: new paper.Group(),\n size: new paper.Size( _renkan.options.minimap_width, _renkan.options.minimap_height )\n };\n\n this.minimap.background_layer.activate();\n this.minimap.topleft = paper.view.bounds.bottomRight.subtract(this.minimap.size);\n this.minimap.rectangle = new paper.Path.Rectangle(this.minimap.topleft.subtract([2,2]), this.minimap.size.add([4,4]));\n this.minimap.rectangle.fillColor = _renkan.options.minimap_background_color;\n this.minimap.rectangle.strokeColor = _renkan.options.minimap_border_color;\n this.minimap.rectangle.strokeWidth = 4;\n this.minimap.offset = new paper.Point(this.minimap.size.divide(2));\n this.minimap.scale = 0.1;\n\n this.minimap.node_layer.activate();\n this.minimap.cliprectangle = new paper.Path.Rectangle(this.minimap.topleft, this.minimap.size);\n this.minimap.node_group.addChild(this.minimap.cliprectangle);\n this.minimap.node_group.clipped = true;\n this.minimap.miniframe = new paper.Path.Rectangle(this.minimap.topleft, this.minimap.size);\n this.minimap.node_group.addChild(this.minimap.miniframe);\n this.minimap.miniframe.fillColor = '#c0c0ff';\n this.minimap.miniframe.opacity = 0.3;\n this.minimap.miniframe.strokeColor = '#000080';\n this.minimap.miniframe.strokeWidth = 3;\n this.minimap.miniframe.__representation = new MiniFrame(this, null);\n }\n\n this.throttledPaperDraw = _(function() {\n paper.view.draw();\n }).throttle(100);\n\n this.bundles = [];\n this.click_mode = false;\n\n var _this = this,\n _allowScroll = true,\n _originalScale = 1,\n _zooming = false,\n _lastTapX = 0,\n _lastTapY = 0;\n\n this.image_cache = {};\n this.icon_cache = {};\n\n ['edit', 'remove', 'link', 'enlarge', 'shrink', 'revert' ].forEach(function(imgname) {\n var img = new Image();\n img.src = _renkan.options.static_url + 'img/' + imgname + '.png';\n _this.icon_cache[imgname] = img;\n });\n\n var throttledMouseMove = _.throttle(function(_event, _isTouch) {\n _this.onMouseMove(_event, _isTouch);\n }, Utils._MOUSEMOVE_RATE);\n\n this.canvas_$.on({\n mousedown: function(_event) {\n _event.preventDefault();\n _this.onMouseDown(_event, false);\n },\n mousemove: function(_event) {\n _event.preventDefault();\n throttledMouseMove(_event, false);\n },\n mouseup: function(_event) {\n _event.preventDefault();\n _this.onMouseUp(_event, false);\n },\n mousewheel: function(_event, _delta) {\n if(_renkan.options.zoom_on_scroll) {\n _event.preventDefault();\n if (_allowScroll) {\n _this.onScroll(_event, _delta);\n }\n }\n },\n touchstart: function(_event) {\n _event.preventDefault();\n var _touches = _event.originalEvent.touches[0];\n if (\n _renkan.options.allow_double_click &&\n new Date() - _lastTap < Utils._DOUBLETAP_DELAY &&\n ( Math.pow(_lastTapX - _touches.pageX, 2) + Math.pow(_lastTapY - _touches.pageY, 2) < Utils._DOUBLETAP_DISTANCE )\n ) {\n _lastTap = 0;\n _this.onDoubleClick(_touches);\n } else {\n _lastTap = new Date();\n _lastTapX = _touches.pageX;\n _lastTapY = _touches.pageY;\n _originalScale = _this.scale;\n _zooming = false;\n _this.onMouseDown(_touches, true);\n }\n },\n touchmove: function(_event) {\n _event.preventDefault();\n _lastTap = 0;\n if (_event.originalEvent.touches.length === 1) {\n _this.onMouseMove(_event.originalEvent.touches[0], true);\n } else {\n if (!_zooming) {\n _this.onMouseUp(_event.originalEvent.touches[0], true);\n _this.click_target = null;\n _this.is_dragging = false;\n _zooming = true;\n }\n if (_event.originalEvent.scale === \"undefined\") {\n return;\n }\n var _newScale = _event.originalEvent.scale * _originalScale,\n _scaleRatio = _newScale / _this.scale,\n _newOffset = new paper.Point([\n _this.canvas_$.width(),\n _this.canvas_$.height()\n ]).multiply( 0.5 * ( 1 - _scaleRatio ) ).add(_this.offset.multiply( _scaleRatio ));\n _this.setScale(_newScale, _newOffset);\n }\n },\n touchend: function(_event) {\n _event.preventDefault();\n _this.onMouseUp(_event.originalEvent.changedTouches[0], true);\n },\n dblclick: function(_event) {\n _event.preventDefault();\n if (_renkan.options.allow_double_click) {\n _this.onDoubleClick(_event);\n }\n },\n mouseleave: function(_event) {\n _event.preventDefault();\n _this.onMouseUp(_event, false);\n _this.click_target = null;\n _this.is_dragging = false;\n },\n dragover: function(_event) {\n _event.preventDefault();\n },\n dragenter: function(_event) {\n _event.preventDefault();\n _allowScroll = false;\n },\n dragleave: function(_event) {\n _event.preventDefault();\n _allowScroll = true;\n },\n drop: function(_event) {\n _event.preventDefault();\n _allowScroll = true;\n var res = {};\n _(_event.originalEvent.dataTransfer.types).each(function(t) {\n try {\n res[t] = _event.originalEvent.dataTransfer.getData(t);\n } catch(e) {}\n });\n var text = _event.originalEvent.dataTransfer.getData(\"Text\");\n if (typeof text === \"string\") {\n switch(text[0]) {\n case \"{\":\n case \"[\":\n try {\n var data = JSON.parse(text);\n _(res).extend(data);\n }\n catch(e) {\n if (!res[\"text/plain\"]) {\n res[\"text/plain\"] = text;\n }\n }\n break;\n case \"<\":\n if (!res[\"text/html\"]) {\n res[\"text/html\"] = text;\n }\n break;\n default:\n if (!res[\"text/plain\"]) {\n res[\"text/plain\"] = text;\n }\n }\n }\n var url = _event.originalEvent.dataTransfer.getData(\"URL\");\n if (url && !res[\"text/uri-list\"]) {\n res[\"text/uri-list\"] = url;\n }\n _this.dropData(res, _event.originalEvent);\n }\n });\n\n var bindClick = function(selector, fname) {\n _this.$.find(selector).click(function(evt) {\n _this[fname](evt);\n return false;\n });\n };\n\n bindClick(\".Rk-ZoomOut\", \"zoomOut\");\n bindClick(\".Rk-ZoomIn\", \"zoomIn\");\n bindClick(\".Rk-ZoomFit\", \"autoScale\");\n this.$.find(\".Rk-ZoomSave\").click( function() {\n // Save scale and offset point\n _this.renkan.project.addView( { zoom_level:_this.scale, offset:_this.offset } );\n });\n this.$.find(\".Rk-ZoomSetSaved\").click( function() {\n var view = _this.renkan.project.get(\"views\").last();\n if(view){\n _this.setScale(view.get(\"zoom_level\"), new paper.Point(view.get(\"offset\")));\n }\n });\n if(this.renkan.read_only && !isNaN(parseInt(this.renkan.options.default_view))){\n this.$.find(\".Rk-ZoomSetSaved\").show();\n }\n this.$.find(\".Rk-CurrentUser\").mouseenter(\n function() { _this.$.find(\".Rk-UserList\").slideDown(); }\n );\n this.$.find(\".Rk-Users\").mouseleave(\n function() { _this.$.find(\".Rk-UserList\").slideUp(); }\n );\n bindClick(\".Rk-FullScreen-Button\", \"fullScreen\");\n bindClick(\".Rk-AddNode-Button\", \"addNodeBtn\");\n bindClick(\".Rk-AddEdge-Button\", \"addEdgeBtn\");\n bindClick(\".Rk-Save-Button\", \"save\");\n bindClick(\".Rk-Open-Button\", \"open\");\n bindClick(\".Rk-Export-Button\", \"exportProject\");\n this.$.find(\".Rk-Bookmarklet-Button\")\n /*jshint scripturl:true */\n .attr(\"href\",\"javascript:\" + Utils._BOOKMARKLET_CODE(_renkan))\n .click(function(){\n _this.notif_$\n .text(_renkan.translate(\"Drag this button to your bookmark bar. When on a third-party website, click it to enable drag-and-drop from the website to Renkan.\"))\n .fadeIn()\n .delay(5000)\n .fadeOut();\n return false;\n });\n this.$.find(\".Rk-TopBar-Button\").mouseover(function() {\n $(this).find(\".Rk-TopBar-Tooltip\").show();\n }).mouseout(function() {\n $(this).find(\".Rk-TopBar-Tooltip\").hide();\n });\n bindClick(\".Rk-Fold-Bins\", \"foldBins\");\n\n paper.view.onResize = function(_event) {\n // Because of paper bug which does not calculate the good height (and width a fortiori)\n // We have to update manually the canvas's height\n paper.view._viewSize.height = _event.size.height = _this.canvas_$.parent().height();\n\n if (_this.minimap) {\n _this.minimap.topleft = paper.view.bounds.bottomRight.subtract(_this.minimap.size);\n _this.minimap.rectangle.fitBounds(_this.minimap.topleft.subtract([2,2]), _this.minimap.size.add([4,4]));\n _this.minimap.cliprectangle.fitBounds(_this.minimap.topleft, _this.minimap.size);\n }\n _this.redraw();\n };\n\n var _thRedraw = _.throttle(function() {\n _this.redraw();\n },50);\n\n this.addRepresentations(\"Node\", this.renkan.project.get(\"nodes\"));\n this.addRepresentations(\"Edge\", this.renkan.project.get(\"edges\"));\n this.renkan.project.on(\"change:title\", function() {\n _this.$.find(\".Rk-PadTitle\").val(_renkan.project.get(\"title\"));\n });\n\n this.$.find(\".Rk-PadTitle\").on(\"keyup input paste\", function() {\n _renkan.project.set({\"title\": $(this).val()});\n });\n\n var _thRedrawUsers = _.throttle(function() {\n _this.redrawUsers();\n }, 100);\n\n _thRedrawUsers();\n\n // register model events\n this.renkan.project.on(\"add:users remove:users\", _thRedrawUsers);\n\n this.renkan.project.on(\"add:views remove:views\", function(_node) {\n if(_this.renkan.project.get('views').length > 0) {\n _this.$.find(\".Rk-ZoomSetSaved\").show();\n }\n else {\n _this.$.find(\".Rk-ZoomSetSaved\").hide();\n }\n });\n\n this.renkan.project.on(\"add:nodes\", function(_node) {\n _this.addRepresentation(\"Node\", _node);\n _thRedraw();\n });\n this.renkan.project.on(\"add:edges\", function(_edge) {\n _this.addRepresentation(\"Edge\", _edge);\n _thRedraw();\n });\n this.renkan.project.on(\"change:title\", function(_model, _title) {\n var el = _this.$.find(\".Rk-PadTitle\");\n if (el.is(\"input\")) {\n if (el.val() !== _title) {\n el.val(_title);\n }\n } else {\n el.text(_title);\n }\n });\n\n if (_renkan.options.size_bug_fix) {\n var _delay = (\n typeof _renkan.options.size_bug_fix === \"number\" ?\n _renkan.options.size_bug_fix\n : 500\n );\n window.setTimeout(\n function() {\n _this.fixSize(true);\n },\n _delay\n );\n }\n\n if (_renkan.options.force_resize) {\n $(window).resize(function() {\n _this.fixSize(false);\n });\n }\n\n if (_renkan.options.show_user_list && _renkan.options.user_color_editable) {\n var $cpwrapper = this.$.find(\".Rk-Users .Rk-Edit-ColorPicker-Wrapper\"),\n $cplist = this.$.find(\".Rk-Users .Rk-Edit-ColorPicker\");\n\n $cpwrapper.hover(\n function(_e) {\n if (_this.isEditable()) {\n _e.preventDefault();\n $cplist.show();\n }\n },\n function(_e) {\n _e.preventDefault();\n $cplist.hide();\n }\n );\n\n $cplist.find(\"li\").mouseenter(\n function(_e) {\n if (_this.isEditable()) {\n _e.preventDefault();\n _this.$.find(\".Rk-CurrentUser-Color\").css(\"background\", $(this).attr(\"data-color\"));\n }\n }\n );\n }\n\n if (_renkan.options.show_search_field) {\n\n var lastval = '';\n\n this.$.find(\".Rk-GraphSearch-Field\").on(\"keyup change paste input\", function() {\n var $this = $(this),\n val = $this.val();\n if (val === lastval) {\n return;\n }\n lastval = val;\n if (val.length < 2) {\n _renkan.project.get(\"nodes\").each(function(n) {\n _this.getRepresentationByModel(n).unhighlight();\n });\n } else {\n var rxs = Utils.regexpFromTextOrArray(val);\n _renkan.project.get(\"nodes\").each(function(n) {\n if (rxs.test(n.get(\"title\")) || rxs.test(n.get(\"description\"))) {\n _this.getRepresentationByModel(n).highlight(rxs);\n } else {\n _this.getRepresentationByModel(n).unhighlight();\n }\n });\n }\n });\n }\n\n this.redraw();\n\n window.setInterval(function() {\n var _now = new Date().valueOf();\n _this.delete_list.forEach(function(d) {\n if (_now >= d.time) {\n var el = _renkan.project.get(\"nodes\").findWhere({\"delete_scheduled\":d.id});\n if (el) {\n project.removeNode(el);\n }\n el = _renkan.project.get(\"edges\").findWhere({\"delete_scheduled\":d.id});\n if (el) {\n project.removeEdge(el);\n }\n }\n });\n _this.delete_list = _this.delete_list.filter(function(d) {\n return _renkan.project.get(\"nodes\").findWhere({\"delete_scheduled\":d.id}) || _renkan.project.get(\"edges\").findWhere({\"delete_scheduled\":d.id});\n });\n }, 500);\n\n if (this.minimap) {\n window.setInterval(function() {\n _this.rescaleMinimap();\n }, 2000);\n }\n\n };\n\n _(Scene.prototype).extend({\n template: _.template(\n '<% if (options.show_top_bar) { %><div class=\"Rk-TopBar\"><% if (!options.editor_mode) { %><h2 class=\"Rk-PadTitle\"><%- project.get(\"title\") || translate(\"Untitled project\")%></h2>' +\n '<% } else { %><input type=\"text\" class=\"Rk-PadTitle\" value=\"<%- project.get(\"title\") || \"\" %>\" placeholder=\"<%-translate(\"Untitled project\")%>\" /><% } %>' +\n '<% if (options.show_user_list) { %><div class=\"Rk-Users\"><div class=\"Rk-CurrentUser\"><div class=\"Rk-Edit-ColorPicker-Wrapper\"><span class=\"Rk-CurrentUser-Color\"><% if (options.user_color_editable) { %><span class=\"Rk-Edit-ColorTip\"></span><% } %></span>' +\n '<% if (options.user_color_editable) { print(colorPicker) } %></div><span class=\"Rk-CurrentUser-Name\"><unknown user></span></div><ul class=\"Rk-UserList\"></ul></div><% } %>' +\n '<% if (options.home_button_url) {%><div class=\"Rk-TopBar-Separator\"></div><a class=\"Rk-TopBar-Button Rk-Home-Button\" href=\"<%- options.home_button_url %>\"><div class=\"Rk-TopBar-Tooltip\"><div class=\"Rk-TopBar-Tooltip-Contents\">' +\n '<%- translate(options.home_button_title) %></div></div></a><% } %>' +\n '<% if (options.show_fullscreen_button) { %><div class=\"Rk-TopBar-Separator\"></div><div class=\"Rk-TopBar-Button Rk-FullScreen-Button\"><div class=\"Rk-TopBar-Tooltip\"><div class=\"Rk-TopBar-Tooltip-Contents\"><%-translate(\"Full Screen\")%></div></div></div><% } %>' +\n '<% if (options.editor_mode) { %>' +\n '<% if (options.show_addnode_button) { %><div class=\"Rk-TopBar-Separator\"></div><div class=\"Rk-TopBar-Button Rk-AddNode-Button\"><div class=\"Rk-TopBar-Tooltip\">' +\n '<div class=\"Rk-TopBar-Tooltip-Contents\"><%-translate(\"Add Node\")%></div></div></div><% } %>' +\n '<% if (options.show_addedge_button) { %><div class=\"Rk-TopBar-Separator\"></div><div class=\"Rk-TopBar-Button Rk-AddEdge-Button\"><div class=\"Rk-TopBar-Tooltip\">' +\n '<div class=\"Rk-TopBar-Tooltip-Contents\"><%-translate(\"Add Edge\")%></div></div></div><% } %>' +\n '<% if (options.show_export_button) { %><div class=\"Rk-TopBar-Separator\"></div><div class=\"Rk-TopBar-Button Rk-Export-Button\"><div class=\"Rk-TopBar-Tooltip\"><div class=\"Rk-TopBar-Tooltip-Contents\"><%-translate(\"Download Project\")%></div></div></div><% } %>' +\n '<% if (options.show_save_button) { %><div class=\"Rk-TopBar-Separator\"></div><div class=\"Rk-TopBar-Button Rk-Save-Button\"><div class=\"Rk-TopBar-Tooltip\"><div class=\"Rk-TopBar-Tooltip-Contents\"> </div></div></div><% } %>' +\n '<% if (options.show_open_button) { %><div class=\"Rk-TopBar-Separator\"></div><div class=\"Rk-TopBar-Button Rk-Open-Button\"><div class=\"Rk-TopBar-Tooltip\"><div class=\"Rk-TopBar-Tooltip-Contents\"><%-translate(\"Open Project\")%></div></div></div><% } %>' +\n '<% if (options.show_bookmarklet) { %><div class=\"Rk-TopBar-Separator\"></div><a class=\"Rk-TopBar-Button Rk-Bookmarklet-Button\" href=\"#\"><div class=\"Rk-TopBar-Tooltip\"><div class=\"Rk-TopBar-Tooltip-Contents\">' +\n '<%-translate(\"Renkan \\'Drag-to-Add\\' bookmarklet\")%></div></div></a><% } %>' +\n '<% } else { %>' +\n '<% if (options.show_export_button) { %><div class=\"Rk-TopBar-Separator\"></div><div class=\"Rk-TopBar-Button Rk-Export-Button\"><div class=\"Rk-TopBar-Tooltip\"><div class=\"Rk-TopBar-Tooltip-Contents\"><%-translate(\"Download Project\")%></div></div></div><div class=\"Rk-TopBar-Separator\"></div><% } %>' +\n '<% };' +\n 'if (options.show_search_field) { %>' +\n '<form action=\"#\" class=\"Rk-GraphSearch-Form\"><input type=\"search\" class=\"Rk-GraphSearch-Field\" placeholder=\"<%- translate(\"Search in graph\") %>\" /></form><div class=\"Rk-TopBar-Separator\"></div><% } %></div><% } %>' +\n '<div class=\"Rk-Editing-Space<% if (!options.show_top_bar) { %> Rk-Editing-Space-Full<% } %>\">' +\n '<div class=\"Rk-Labels\"></div><canvas class=\"Rk-Canvas\" resize></canvas><div class=\"Rk-Notifications\"></div><div class=\"Rk-Editor\">' +\n '<% if (options.show_bins) { %><div class=\"Rk-Fold-Bins\">«</div><% } %>' +\n '<div class=\"Rk-ZoomButtons\"><div class=\"Rk-ZoomIn\" title=\"<%-translate(\"Zoom In\")%>\"></div><div class=\"Rk-ZoomFit\" title=\"<%-translate(\"Zoom Fit\")%>\"></div><div class=\"Rk-ZoomOut\" title=\"<%-translate(\"Zoom Out\")%>\"></div>' +\n '<% if (options.editor_mode) { %><div class=\"Rk-ZoomSave\" title=\"<%-translate(\"Zoom Save\")%>\"></div><% } %>' +\n '<% if (options.editor_mode || !isNaN(parseInt(options.default_view))) { %><div class=\"Rk-ZoomSetSaved\" title=\"<%-translate(\"View saved zoom\")%>\"></div><% } %></div>' +\n '</div></div>'\n ),\n fixSize: function(_autoscale) {\n var w = this.$.width(),\n h = this.$.height();\n if (this.renkan.options.show_top_bar) {\n h -= this.$.find(\".Rk-TopBar\").height();\n }\n this.canvas_$.attr({\n width: w,\n height: h\n });\n\n paper.view.viewSize = new paper.Size([w, h]);\n\n if (_autoscale) {\n // If _autoscale, we get the initial view (zoom+offset) set in the project datas.\n if(this.renkan.read_only && !isNaN(parseInt(this.renkan.options.default_view))){\n this.autoScale(this.renkan.project.get(\"views\")[parseInt(this.renkan.options.default_view)]);\n }\n else{\n this.autoScale();\n }\n }\n },\n drawSector: function(_repr, _inR, _outR, _startAngle, _endAngle, _padding, _imgname, _caption) {\n var _options = this.renkan.options,\n _startRads = _startAngle * Math.PI / 180,\n _endRads = _endAngle * Math.PI / 180,\n _img = this.icon_cache[_imgname],\n _startdx = - Math.sin(_startRads),\n _startdy = Math.cos(_startRads),\n _startXIn = Math.cos(_startRads) * _inR + _padding * _startdx,\n _startYIn = Math.sin(_startRads) * _inR + _padding * _startdy,\n _startXOut = Math.cos(_startRads) * _outR + _padding * _startdx,\n _startYOut = Math.sin(_startRads) * _outR + _padding * _startdy,\n _enddx = - Math.sin(_endRads),\n _enddy = Math.cos(_endRads),\n _endXIn = Math.cos(_endRads) * _inR - _padding * _enddx,\n _endYIn = Math.sin(_endRads) * _inR - _padding * _enddy,\n _endXOut = Math.cos(_endRads) * _outR - _padding * _enddx,\n _endYOut = Math.sin(_endRads) * _outR - _padding * _enddy,\n _centerR = (_inR + _outR) / 2,\n _centerRads = (_startRads + _endRads) / 2,\n _centerX = Math.cos(_centerRads) * _centerR,\n _centerY = Math.sin(_centerRads) * _centerR,\n _centerXIn = Math.cos(_centerRads) * _inR,\n _centerXOut = Math.cos(_centerRads) * _outR,\n _centerYIn = Math.sin(_centerRads) * _inR,\n _centerYOut = Math.sin(_centerRads) * _outR,\n _textX = Math.cos(_centerRads) * (_outR + 3),\n _textY = Math.sin(_centerRads) * (_outR + _options.buttons_label_font_size) + _options.buttons_label_font_size / 2;\n this.buttons_layer.activate();\n var _path = new paper.Path();\n _path.add([_startXIn, _startYIn]);\n _path.arcTo([_centerXIn, _centerYIn], [_endXIn, _endYIn]);\n _path.lineTo([_endXOut, _endYOut]);\n _path.arcTo([_centerXOut, _centerYOut], [_startXOut, _startYOut]);\n _path.fillColor = _options.buttons_background;\n _path.opacity = 0.5;\n _path.closed = true;\n _path.__representation = _repr;\n var _text = new paper.PointText(_textX,_textY);\n _text.characterStyle = {\n fontSize: _options.buttons_label_font_size,\n fillColor: _options.buttons_label_color\n };\n if (_textX > 2) {\n _text.paragraphStyle.justification = 'left';\n } else if (_textX < -2) {\n _text.paragraphStyle.justification = 'right';\n } else {\n _text.paragraphStyle.justification = 'center';\n }\n _text.visible = false;\n var _visible = false,\n _restPos = new paper.Point(-200, -200),\n _grp = new paper.Group([_path, _text]),\n _delta = _grp.position,\n _imgdelta = new paper.Point([_centerX, _centerY]),\n _currentPos = new paper.Point(0,0);\n _text.content = _caption;\n _grp.visible = false;\n _grp.position = _restPos;\n var _res = {\n show: function() {\n _visible = true;\n _grp.position = _currentPos.add(_delta);\n _grp.visible = true;\n },\n moveTo: function(_point) {\n _currentPos = _point;\n if (_visible) {\n _grp.position = _point.add(_delta);\n }\n },\n hide: function() {\n _visible = false;\n _grp.visible = false;\n _grp.position = _restPos;\n },\n select: function() {\n _path.opacity = 0.8;\n _text.visible = true;\n },\n unselect: function() {\n _path.opacity = 0.5;\n _text.visible = false;\n },\n destroy: function() {\n _grp.remove();\n }\n };\n var showImage = function() {\n var _raster = new paper.Raster(_img);\n _raster.position = _imgdelta.add(_grp.position).subtract(_delta);\n _raster.locked = true; // Disable mouse events on icon\n _grp.addChild(_raster);\n };\n if (_img.width) {\n showImage();\n } else {\n $(_img).on(\"load\",showImage);\n }\n\n return _res;\n },\n addToBundles: function(_edgeRepr) {\n var _bundle = _(this.bundles).find(function(_bundle) {\n return (\n ( _bundle.from === _edgeRepr.from_representation && _bundle.to === _edgeRepr.to_representation ) ||\n ( _bundle.from === _edgeRepr.to_representation && _bundle.to === _edgeRepr.from_representation )\n );\n });\n if (typeof _bundle !== \"undefined\") {\n _bundle.edges.push(_edgeRepr);\n } else {\n _bundle = {\n from: _edgeRepr.from_representation,\n to: _edgeRepr.to_representation,\n edges: [ _edgeRepr ],\n getPosition: function(_er) {\n var _dir = (_er.from_representation === this.from) ? 1 : -1;\n return _dir * ( _(this.edges).indexOf(_er) - (this.edges.length - 1) / 2 );\n }\n };\n this.bundles.push(_bundle);\n }\n return _bundle;\n },\n isEditable: function() {\n return (this.renkan.options.editor_mode && !this.renkan.read_only);\n },\n onStatusChange: function() {\n var savebtn = this.$.find(\".Rk-Save-Button\"),\n tip = savebtn.find(\".Rk-TopBar-Tooltip-Contents\");\n if (this.renkan.read_only) {\n savebtn.removeClass(\"disabled Rk-Save-Online\").addClass(\"Rk-Save-ReadOnly\");\n tip.text(this.renkan.translate(\"Connection lost\"));\n } else {\n if (this.renkan.options.snapshot_mode) {\n savebtn.removeClass(\"Rk-Save-ReadOnly Rk-Save-Online\");\n tip.text(this.renkan.translate(\"Save Project\"));\n } else {\n savebtn.removeClass(\"disabled Rk-Save-ReadOnly\").addClass(\"Rk-Save-Online\");\n tip.text(this.renkan.translate(\"Auto-save enabled\"));\n }\n }\n this.redrawUsers();\n },\n setScale: function(_newScale, _offset) {\n if ((_newScale/this.initialScale) > Utils._MIN_SCALE && (_newScale/this.initialScale) < Utils._MAX_SCALE) {\n this.scale = _newScale;\n if (_offset) {\n this.offset = _offset;\n }\n this.redraw();\n }\n },\n autoScale: function(force_view) {\n var nodes = this.renkan.project.get(\"nodes\");\n if (nodes.length > 1) {\n var _xx = nodes.map(function(_node) { return _node.get(\"position\").x; }),\n _yy = nodes.map(function(_node) { return _node.get(\"position\").y; }),\n _minx = Math.min.apply(Math, _xx),\n _miny = Math.min.apply(Math, _yy),\n _maxx = Math.max.apply(Math, _xx),\n _maxy = Math.max.apply(Math, _yy);\n var _scale = Math.min( (paper.view.size.width - 2 * this.renkan.options.autoscale_padding) / (_maxx - _minx), (paper.view.size.height - 2 * this.renkan.options.autoscale_padding) / (_maxy - _miny));\n this.initialScale = _scale;\n // Override calculated scale if asked\n if((typeof force_view !== \"undefined\") && parseFloat(force_view.zoom_level)>0 && parseFloat(force_view.offset.x)>0 && parseFloat(force_view.offset.y)>0){\n this.setScale(parseFloat(force_view.zoom_level), new paper.Point(parseFloat(force_view.offset.x), parseFloat(force_view.offset.y)));\n }\n else{\n this.setScale(_scale, paper.view.center.subtract(new paper.Point([(_maxx + _minx) / 2, (_maxy + _miny) / 2]).multiply(_scale)));\n }\n }\n if (nodes.length === 1) {\n this.setScale(1, paper.view.center.subtract(new paper.Point([nodes.at(0).get(\"position\").x, nodes.at(0).get(\"position\").y])));\n }\n },\n redrawMiniframe: function() {\n var topleft = this.toMinimapCoords(this.toModelCoords(new paper.Point([0,0]))),\n bottomright = this.toMinimapCoords(this.toModelCoords(paper.view.bounds.bottomRight));\n this.minimap.miniframe.fitBounds(topleft, bottomright);\n },\n rescaleMinimap: function() {\n var nodes = this.renkan.project.get(\"nodes\");\n if (nodes.length > 1) {\n var _xx = nodes.map(function(_node) { return _node.get(\"position\").x; }),\n _yy = nodes.map(function(_node) { return _node.get(\"position\").y; }),\n _minx = Math.min.apply(Math, _xx),\n _miny = Math.min.apply(Math, _yy),\n _maxx = Math.max.apply(Math, _xx),\n _maxy = Math.max.apply(Math, _yy);\n var _scale = Math.min(\n this.scale * 0.8 * this.renkan.options.minimap_width / paper.view.bounds.width,\n this.scale * 0.8 * this.renkan.options.minimap_height / paper.view.bounds.height,\n ( this.renkan.options.minimap_width - 2 * this.renkan.options.minimap_padding ) / (_maxx - _minx),\n ( this.renkan.options.minimap_height - 2 * this.renkan.options.minimap_padding ) / (_maxy - _miny)\n );\n this.minimap.offset = this.minimap.size.divide(2).subtract(new paper.Point([(_maxx + _minx) / 2, (_maxy + _miny) / 2]).multiply(_scale));\n this.minimap.scale = _scale;\n }\n if (nodes.length === 1) {\n this.minimap.scale = 0.1;\n this.minimap.offset = this.minimap.size.divide(2).subtract(new paper.Point([nodes.at(0).get(\"position\").x, nodes.at(0).get(\"position\").y]).multiply(this.minimap.scale));\n }\n this.redraw();\n },\n toPaperCoords: function(_point) {\n return _point.multiply(this.scale).add(this.offset);\n },\n toMinimapCoords: function(_point) {\n return _point.multiply(this.minimap.scale).add(this.minimap.offset).add(this.minimap.topleft);\n },\n toModelCoords: function(_point) {\n return _point.subtract(this.offset).divide(this.scale);\n },\n addRepresentation: function(_type, _model) {\n var RendererType = requtils.getRenderer()[_type];\n var _repr = new RendererType(this, _model);\n this.representations.push(_repr);\n return _repr;\n },\n addRepresentations: function(_type, _collection) {\n var _this = this;\n _collection.forEach(function(_model) {\n _this.addRepresentation(_type, _model);\n });\n },\n userTemplate: _.template(\n '<li class=\"Rk-User\"><span class=\"Rk-UserColor\" style=\"background:<%=background%>;\"></span><%=name%></li>'\n ),\n redrawUsers: function() {\n if (!this.renkan.options.show_user_list) {\n return;\n }\n var allUsers = [].concat((this.renkan.project.current_user_list || {}).models || [], (this.renkan.project.get(\"users\") || {}).models || []),\n ulistHtml = '',\n $userpanel = this.$.find(\".Rk-Users\"),\n $name = $userpanel.find(\".Rk-CurrentUser-Name\"),\n $cpitems = $userpanel.find(\".Rk-Edit-ColorPicker li\"),\n $colorsquare = $userpanel.find(\".Rk-CurrentUser-Color\"),\n _this = this;\n $name.off(\"click\").text(this.renkan.translate(\"<unknown user>\"));\n $cpitems.off(\"mouseleave click\");\n allUsers.forEach(function(_user) {\n if (_user.get(\"_id\") === _this.renkan.current_user) {\n $name.text(_user.get(\"title\"));\n $colorsquare.css(\"background\", _user.get(\"color\"));\n if (_this.isEditable()) {\n\n if (_this.renkan.options.user_name_editable) {\n $name.click(function() {\n var $this = $(this),\n $input = $('<input>').val(_user.get(\"title\")).blur(function() {\n _user.set(\"title\", $(this).val());\n _this.redrawUsers();\n _this.redraw();\n });\n $this.empty().html($input);\n $input.select();\n });\n }\n\n if (_this.renkan.options.user_color_editable) {\n $cpitems.click(\n function(_e) {\n _e.preventDefault();\n if (_this.isEditable()) {\n _user.set(\"color\", $(this).attr(\"data-color\"));\n }\n $(this).parent().hide();\n }\n ).mouseleave(function() {\n $colorsquare.css(\"background\", _user.get(\"color\"));\n });\n }\n }\n\n } else {\n ulistHtml += _this.userTemplate({\n name: _user.get(\"title\"),\n background: _user.get(\"color\")\n });\n }\n });\n $userpanel.find(\".Rk-UserList\").html(ulistHtml);\n },\n removeRepresentation: function(_representation) {\n _representation.destroy();\n this.representations = _(this.representations).reject(\n function(_repr) {\n return _repr === _representation;\n }\n );\n },\n getRepresentationByModel: function(_model) {\n if (!_model) {\n return undefined;\n }\n return _(this.representations).find(function(_repr) {\n return _repr.model === _model;\n });\n },\n removeRepresentationsOfType: function(_type) {\n var _representations = _(this.representations).filter(function(_repr) {\n return _repr.type === _type;\n }),\n _this = this;\n _(_representations).each(function(_repr) {\n _this.removeRepresentation(_repr);\n });\n },\n highlightModel: function(_model) {\n var _repr = this.getRepresentationByModel(_model);\n if (_repr) {\n _repr.highlight();\n }\n },\n unhighlightAll: function(_model) {\n _(this.representations).each(function(_repr) {\n _repr.unhighlight();\n });\n },\n unselectAll: function(_model) {\n _(this.representations).each(function(_repr) {\n _repr.unselect();\n });\n },\n redraw: function() {\n if(! this.redrawActive ) {\n return;\n }\n _(this.representations).each(function(_representation) {\n _representation.redraw(true);\n });\n if (this.minimap) {\n this.redrawMiniframe();\n }\n paper.view.draw();\n },\n addTempEdge: function(_from, _point) {\n var _tmpEdge = this.addRepresentation(\"TempEdge\",null);\n _tmpEdge.end_pos = _point;\n _tmpEdge.from_representation = _from;\n _tmpEdge.redraw();\n this.click_target = _tmpEdge;\n },\n findTarget: function(_hitResult) {\n if (_hitResult && typeof _hitResult.item.__representation !== \"undefined\") {\n var _newTarget = _hitResult.item.__representation;\n if (this.selected_target !== _hitResult.item.__representation) {\n if (this.selected_target) {\n this.selected_target.unselect(_newTarget);\n }\n _newTarget.select(this.selected_target);\n this.selected_target = _newTarget;\n }\n } else {\n if (this.selected_target) {\n this.selected_target.unselect();\n }\n this.selected_target = null;\n }\n },\n paperShift: function(_delta) {\n this.offset = this.offset.add(_delta);\n this.redraw();\n },\n onMouseMove: function(_event) {\n var _off = this.canvas_$.offset(),\n _point = new paper.Point([\n _event.pageX - _off.left,\n _event.pageY - _off.top\n ]),\n _delta = _point.subtract(this.last_point);\n this.last_point = _point;\n if (!this.is_dragging && this.mouse_down && _delta.length > Utils._MIN_DRAG_DISTANCE) {\n this.is_dragging = true;\n }\n var _hitResult = paper.project.hitTest(_point);\n if (this.is_dragging) {\n if (this.click_target && typeof this.click_target.paperShift === \"function\") {\n this.click_target.paperShift(_delta);\n } else {\n this.paperShift(_delta);\n }\n } else {\n this.findTarget(_hitResult);\n }\n paper.view.draw();\n },\n onMouseDown: function(_event, _isTouch) {\n var _off = this.canvas_$.offset(),\n _point = new paper.Point([\n _event.pageX - _off.left,\n _event.pageY - _off.top\n ]);\n this.last_point = _point;\n this.mouse_down = true;\n if (!this.click_target || this.click_target.type !== \"Temp-edge\") {\n this.removeRepresentationsOfType(\"editor\");\n this.is_dragging = false;\n var _hitResult = paper.project.hitTest(_point);\n if (_hitResult && typeof _hitResult.item.__representation !== \"undefined\") {\n this.click_target = _hitResult.item.__representation;\n this.click_target.mousedown(_event, _isTouch);\n } else {\n this.click_target = null;\n if (this.isEditable() && this.click_mode === Utils._CLICKMODE_ADDNODE) {\n var _coords = this.toModelCoords(_point),\n _data = {\n id: Utils.getUID('node'),\n created_by: this.renkan.current_user,\n position: {\n x: _coords.x,\n y: _coords.y\n }\n };\n _node = this.renkan.project.addNode(_data);\n this.getRepresentationByModel(_node).openEditor();\n }\n }\n }\n if (this.click_mode) {\n if (this.isEditable() && this.click_mode === Utils._CLICKMODE_STARTEDGE && this.click_target && this.click_target.type === \"Node\") {\n this.removeRepresentationsOfType(\"editor\");\n this.addTempEdge(this.click_target, _point);\n this.click_mode = Utils._CLICKMODE_ENDEDGE;\n this.notif_$.fadeOut(function() {\n $(this).html(this.renkan.translate(\"Click on a second node to complete the edge\")).fadeIn();\n });\n } else {\n this.notif_$.hide();\n this.click_mode = false;\n }\n }\n paper.view.draw();\n },\n onMouseUp: function(_event, _isTouch) {\n this.mouse_down = false;\n if (this.click_target) {\n var _off = this.canvas_$.offset();\n this.click_target.mouseup(\n {\n point: new paper.Point([\n _event.pageX - _off.left,\n _event.pageY - _off.top\n ])\n },\n _isTouch\n );\n } else {\n this.click_target = null;\n this.is_dragging = false;\n if (_isTouch) {\n this.unselectAll();\n }\n }\n paper.view.draw();\n },\n onScroll: function(_event, _scrolldelta) {\n this.totalScroll += _scrolldelta;\n if (Math.abs(this.totalScroll) >= 1) {\n var _off = this.canvas_$.offset(),\n _delta = new paper.Point([\n _event.pageX - _off.left,\n _event.pageY - _off.top\n ]).subtract(this.offset).multiply( Math.SQRT2 - 1 );\n if (this.totalScroll > 0) {\n this.setScale( this.scale * Math.SQRT2, this.offset.subtract(_delta) );\n } else {\n this.setScale( this.scale * Math.SQRT1_2, this.offset.add(_delta.divide(Math.SQRT2)));\n }\n this.totalScroll = 0;\n }\n },\n onDoubleClick: function(_event) {\n if (!this.isEditable()) {\n return;\n }\n var _off = this.canvas_$.offset(),\n _point = new paper.Point([\n _event.pageX - _off.left,\n _event.pageY - _off.top\n ]);\n var _hitResult = paper.project.hitTest(_point);\n if (this.isEditable() && (!_hitResult || typeof _hitResult.item.__representation === \"undefined\")) {\n var _coords = this.toModelCoords(_point),\n _data = {\n id: Utils.getUID('node'),\n created_by: this.renkan.current_user,\n position: {\n x: _coords.x,\n y: _coords.y\n }\n },\n _node = this.renkan.project.addNode(_data);\n this.getRepresentationByModel(_node).openEditor();\n }\n paper.view.draw();\n },\n defaultDropHandler: function(_data) {\n var newNode = {};\n var snippet = \"\";\n switch(_data[\"text/x-iri-specific-site\"]) {\n case \"twitter\":\n snippet = $('<div>').html(_data[\"text/x-iri-selected-html\"]);\n var tweetdiv = snippet.find(\".tweet\");\n newNode.title = this.renkan.translate(\"Tweet by \") + tweetdiv.attr(\"data-name\");\n newNode.uri = \"http://twitter.com/\" + tweetdiv.attr(\"data-screen-name\") + \"/status/\" + tweetdiv.attr(\"data-tweet-id\");\n newNode.image = tweetdiv.find(\".avatar\").attr(\"src\");\n newNode.description = tweetdiv.find(\".js-tweet-text:first\").text();\n break;\n case \"google\":\n snippet = $('<div>').html(_data[\"text/x-iri-selected-html\"]);\n newNode.title = snippet.find(\"h3:first\").text().trim();\n newNode.uri = snippet.find(\"h3 a\").attr(\"href\");\n newNode.description = snippet.find(\".st:first\").text().trim();\n break;\n default:\n if (_data[\"text/x-iri-source-uri\"]) {\n newNode.uri = _data[\"text/x-iri-source-uri\"];\n }\n }\n if (_data[\"text/plain\"] || _data[\"text/x-iri-selected-text\"]) {\n newNode.description = (_data[\"text/plain\"] || _data[\"text/x-iri-selected-text\"]).replace(/[\\s\\n]+/gm,' ').trim();\n }\n if (_data[\"text/html\"] || _data[\"text/x-iri-selected-html\"]) {\n snippet = $('<div>').html(_data[\"text/html\"] || _data[\"text/x-iri-selected-html\"]);\n var _svgimgs = snippet.find(\"image\");\n if (_svgimgs.length) {\n newNode.image = _svgimgs.attr(\"xlink:href\");\n }\n var _svgpaths = snippet.find(\"path\");\n if (_svgpaths.length) {\n newNode.clipPath = _svgpaths.attr(\"d\");\n }\n var _imgs = snippet.find(\"img\");\n if (_imgs.length) {\n newNode.image = _imgs[0].src;\n }\n var _as = snippet.find(\"a\");\n if (_as.length) {\n newNode.uri = _as[0].href;\n }\n newNode.title = snippet.find(\"[title]\").attr(\"title\") || newNode.title;\n newNode.description = snippet.text().replace(/[\\s\\n]+/gm,' ').trim();\n }\n if (_data[\"text/uri-list\"]) {\n newNode.uri = _data[\"text/uri-list\"];\n }\n if (_data[\"text/x-moz-url\"] && !newNode.title) {\n newNode.title = (_data[\"text/x-moz-url\"].split(\"\\n\")[1] || \"\").trim();\n if (newNode.title === newNode.uri) {\n newNode.title = false;\n }\n }\n if (_data[\"text/x-iri-source-title\"] && !newNode.title) {\n newNode.title = _data[\"text/x-iri-source-title\"];\n }\n if (_data[\"text/html\"] || _data[\"text/x-iri-selected-html\"]) {\n snippet = $('<div>').html(_data[\"text/html\"] || _data[\"text/x-iri-selected-html\"]);\n newNode.image = snippet.find(\"[data-image]\").attr(\"data-image\") || newNode.image;\n newNode.uri = snippet.find(\"[data-uri]\").attr(\"data-uri\") || newNode.uri;\n newNode.title = snippet.find(\"[data-title]\").attr(\"data-title\") || newNode.title;\n newNode.description = snippet.find(\"[data-description]\").attr(\"data-description\") || newNode.description;\n newNode.clipPath = snippet.find(\"[data-clip-path]\").attr(\"data-clip-path\") || newNode.clipPath;\n }\n\n if (!newNode.title) {\n newNode.title = this.renkan.translate(\"Dragged resource\");\n }\n var fields = [\"title\", \"description\", \"uri\", \"image\"];\n for (var i = 0; i < fields.length; i++) {\n var f = fields[i];\n if (_data[\"text/x-iri-\" + f] || _data[f]) {\n newNode[f] = _data[\"text/x-iri-\" + f] || _data[f];\n }\n if (newNode[f] === \"none\" || newNode[f] === \"null\") {\n newNode[f] = undefined;\n }\n }\n\n if(typeof this.renkan.options.drop_enhancer === \"function\"){\n newNode = this.renkan.options.drop_enhancer(newNode, _data);\n }\n\n return newNode;\n\n },\n dropData: function(_data, _event) {\n if (!this.isEditable()) {\n return;\n }\n if (_data[\"text/json\"] || _data[\"application/json\"]) {\n try {\n var jsondata = JSON.parse(_data[\"text/json\"] || _data[\"application/json\"]);\n _(_data).extend(jsondata);\n }\n catch(e) {}\n }\n\n var newNode = (typeof this.renkan.options.drop_handler === \"undefined\")?this.defaultDropHandler(_data):this.renkan.options.drop_handler(_data);\n\n var _off = this.canvas_$.offset(),\n _point = new paper.Point([\n _event.pageX - _off.left,\n _event.pageY - _off.top\n ]),\n _coords = this.toModelCoords(_point),\n _nodedata = {\n id: Utils.getUID('node'),\n created_by: this.renkan.current_user,\n uri: newNode.uri || \"\",\n title: newNode.title || \"\",\n description: newNode.description || \"\",\n image: newNode.image || \"\",\n color: newNode.color || undefined,\n clip_path: newNode.clipPath || undefined,\n position: {\n x: _coords.x,\n y: _coords.y\n }\n };\n var _node = this.renkan.project.addNode(_nodedata),\n _repr = this.getRepresentationByModel(_node);\n if (_event.type === \"drop\") {\n _repr.openEditor();\n }\n },\n fullScreen: function() {\n var _isFull = document.fullScreen || document.mozFullScreen || document.webkitIsFullScreen,\n _el = this.renkan.$[0],\n _requestMethods = [\"requestFullScreen\",\"mozRequestFullScreen\",\"webkitRequestFullScreen\"],\n _cancelMethods = [\"cancelFullScreen\",\"mozCancelFullScreen\",\"webkitCancelFullScreen\"],\n i;\n if (_isFull) {\n for (i = 0; i < _cancelMethods.length; i++) {\n if (typeof document[_cancelMethods[i]] === \"function\") {\n document[_cancelMethods[i]]();\n break;\n }\n }\n } else {\n for (i = 0; i < _requestMethods.length; i++) {\n if (typeof _el[_requestMethods[i]] === \"function\") {\n _el[_requestMethods[i]]();\n break;\n }\n }\n }\n },\n zoomOut: function() {\n var _newScale = this.scale * Math.SQRT1_2,\n _offset = new paper.Point([\n this.canvas_$.width(),\n this.canvas_$.height()\n ]).multiply( 0.5 * ( 1 - Math.SQRT1_2 ) ).add(this.offset.multiply( Math.SQRT1_2 ));\n this.setScale( _newScale, _offset );\n },\n zoomIn: function() {\n var _newScale = this.scale * Math.SQRT2,\n _offset = new paper.Point([\n this.canvas_$.width(),\n this.canvas_$.height()\n ]).multiply( 0.5 * ( 1 - Math.SQRT2 ) ).add(this.offset.multiply( Math.SQRT2 ));\n this.setScale( _newScale, _offset );\n },\n addNodeBtn: function() {\n if (this.click_mode === Utils._CLICKMODE_ADDNODE) {\n this.click_mode = false;\n this.notif_$.hide();\n } else {\n this.click_mode = Utils._CLICKMODE_ADDNODE;\n this.notif_$.text(this.renkan.translate(\"Click on the background canvas to add a node\")).fadeIn();\n }\n return false;\n },\n addEdgeBtn: function() {\n if (this.click_mode === Utils._CLICKMODE_STARTEDGE || this.click_mode === Utils._CLICKMODE_ENDEDGE) {\n this.click_mode = false;\n this.notif_$.hide();\n } else {\n this.click_mode = Utils._CLICKMODE_STARTEDGE;\n this.notif_$.text(this.renkan.translate(\"Click on a first node to start the edge\")).fadeIn();\n }\n return false;\n },\n exportProject: function() {\n var projectJSON = this.renkan.project.toJSON(),\n downloadLink = document.createElement(\"a\"),\n projectId = projectJSON.id,\n fileNameToSaveAs = projectId + \".json\";\n\n // clean ids\n delete projectJSON.id;\n delete projectJSON._id;\n delete projectJSON.space_id;\n\n var objId;\n var idsMap = {};\n\n _.each(projectJSON.nodes, function(e,i,l) {\n objId = e.id || e._id;\n delete e._id;\n delete e.id;\n idsMap[objId] = e['@id'] = Utils.getUUID4();\n });\n _.each(projectJSON.edges, function(e,i,l) {\n delete e._id;\n delete e.id;\n e.to = idsMap[e.to];\n e.from = idsMap[e.from];\n });\n _.each(projectJSON.views, function(e,i,l) {\n objId = e.id || e._id;\n delete e._id;\n delete e.id;\n });\n projectJSON.users = [];\n\n var projectJSONStr = JSON.stringify(projectJSON, null, 2);\n var blob = new Blob([projectJSONStr], {type: \"application/json;charset=utf-8\"});\n filesaver(blob,fileNameToSaveAs);\n\n },\n foldBins: function() {\n var foldBinsButton = this.$.find(\".Rk-Fold-Bins\"),\n bins = this.renkan.$.find(\".Rk-Bins\");\n var _this = this;\n if (bins.offset().left < 0) {\n bins.animate({left: 0},250);\n this.$.animate({left: 300},250,function() {\n var w = _this.$.width();\n paper.view.viewSize = new paper.Size([w, _this.canvas_$.height()]);\n });\n foldBinsButton.html(\"«\");\n } else {\n bins.animate({left: -300},250);\n this.$.animate({left: 0},250,function() {\n var w = _this.$.width();\n paper.view.viewSize = new paper.Size([w, _this.canvas_$.height()]);\n });\n foldBinsButton.html(\"»\");\n }\n },\n save: function() { },\n open: function() { }\n });\n\n /* Scene End */\n\n return Scene;\n\n});\n\n\n//Load modules and use them\nif( typeof require.config === \"function\" ) {\n require.config({\n paths: {\n 'jquery':'../lib/jquery.min',\n 'underscore':'../lib/underscore-min',\n 'filesaver' :'../lib/FileSaver',\n 'requtils':'require-utils'\n }\n });\n}\n\nrequire(['renderer/baserepresentation',\n 'renderer/basebutton',\n 'renderer/noderepr',\n 'renderer/edge',\n 'renderer/tempedge',\n 'renderer/baseeditor',\n 'renderer/nodeeditor',\n 'renderer/edgeeditor',\n 'renderer/nodebutton',\n 'renderer/nodeeditbutton',\n 'renderer/noderemovebutton',\n 'renderer/noderevertbutton',\n 'renderer/nodelinkbutton',\n 'renderer/nodeenlargebutton',\n 'renderer/nodeshrinkbutton',\n 'renderer/edgeeditbutton',\n 'renderer/edgeremovebutton',\n 'renderer/edgerevertbutton',\n 'renderer/miniframe',\n 'renderer/scene'\n ], function(BaseRepresentation, BaseButton, NodeRepr, Edge, TempEdge, BaseEditor, NodeEditor, EdgeEditor, NodeButton, NodeEditButton, NodeRemoveButton, NodeRevertButton, NodeLinkButton, NodeEnlargeButton, NodeShrinkButton, EdgeEditButton, EdgeRemoveButton, EdgeRevertButton, MiniFrame, Scene){\n\n \n\n var Rkns = window.Rkns;\n\n if(typeof Rkns.Renderer === \"undefined\"){\n Rkns.Renderer = {};\n }\n var Renderer = Rkns.Renderer;\n\n Renderer._BaseRepresentation = BaseRepresentation;\n Renderer._BaseButton = BaseButton;\n Renderer.Node = NodeRepr;\n Renderer.Edge = Edge;\n Renderer.TempEdge = TempEdge;\n Renderer._BaseEditor = BaseEditor;\n Renderer.NodeEditor = NodeEditor;\n Renderer.EdgeEditor = EdgeEditor;\n Renderer._NodeButton = NodeButton;\n Renderer.NodeEditButton = NodeEditButton;\n Renderer.NodeRemoveButton = NodeRemoveButton;\n Renderer.NodeRevertButton = NodeRevertButton;\n Renderer.NodeLinkButton = NodeLinkButton;\n Renderer.NodeEnlargeButton = NodeEnlargeButton;\n Renderer.NodeShrinkButton = NodeShrinkButton;\n Renderer.EdgeEditButton = EdgeEditButton;\n Renderer.EdgeRemoveButton = EdgeRemoveButton;\n Renderer.EdgeRevertButton = EdgeRevertButton;\n Renderer.MiniFrame = MiniFrame;\n Renderer.Scene = Scene;\n \n startRenkan();\n});\n\ndefine(\"main-renderer\", function(){});\n\n"]}
\ No newline at end of file