import updates to mdplayer into the platform + added a script to easily build mdplayer from repository + fix the mdplayer config page
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/sbin/build/compil-mdp-from-sources.sh Fri Oct 02 10:24:05 2015 +0200
@@ -0,0 +1,36 @@
+
+if [ $# -eq 0 ]
+ then
+ echo "No argument was provided, looking for mdplayer_path"
+ if [ ! -f "mdplayer_path" ]
+ then
+ echo "Error: mdplayer_path file does not exist and no argument was provided"
+ exit 1
+ fi
+ MDPLAYER_PATH=$(cat mdplayer_path)
+ if [ -z MDPLAYER_PATH ]
+ then
+ echo "File is empty"
+ exit 1
+ fi
+ else
+ MDPLAYER_PATH=$1
+fi
+
+echo "Compiling Metadataplayer"
+
+sh $MDPLAYER_PATH/sbin/res/ant/bin/ant -f $MDPLAYER_PATH/sbin/build/client.xml
+
+echo "Copying to Platform :"
+
+echo " Copying core files and widgets"
+
+cp -R $MDPLAYER_PATH/test/metadataplayer/* ../../src/ldt/ldt/static/ldt/metadataplayer
+
+echo " Copying JS libs"
+
+cp -R $MDPLAYER_PATH/src/js/libs/*.js ../../src/ldt/ldt/static/ldt/js
+
+echo " Copying SWF libs"
+
+cp -R $MDPLAYER_PATH/src/js/libs/*.swf ../../src/ldt/ldt/static/ldt/swf
--- a/src/ldt/README Fri Sep 18 16:10:29 2015 +0200
+++ b/src/ldt/README Fri Oct 02 10:24:05 2015 +0200
@@ -73,4 +73,16 @@
For example :
python manage.py test ldt_utils
-Will launch all the test defined in /ldt_utils/tests
\ No newline at end of file
+Will launch all the test defined in /ldt_utils/tests
+
+==============
+Building Metadataplayer
+==============
+
+Run the script in sbin/build/ folder to build the metadataplayer from the sources.
+ cd sbin/build
+ bash compil-mdp-from-sources <mdplayer_repo_path>
+
+Alternatively you can put a "mdplayer_path" file (containing the ABSOLUTE path to the metadataplayer repository) to the sbin/build repo then call the script without argument
+ cd sbin/build
+ bash compil-mdp-from-sources
\ No newline at end of file
--- a/src/ldt/ldt/static/ldt/js/ZeroClipboard.js Fri Sep 18 16:10:29 2015 +0200
+++ b/src/ldt/ldt/static/ldt/js/ZeroClipboard.js Fri Oct 02 10:24:05 2015 +0200
@@ -1,311 +1,2581 @@
-// Simple Set Clipboard System
-// Author: Joseph Huckaby
+/*!
+ * ZeroClipboard
+ * The ZeroClipboard library provides an easy way to copy text to the clipboard using an invisible Adobe Flash movie and a JavaScript interface.
+ * Copyright (c) 2009-2014 Jon Rohan, James M. Greene
+ * Licensed MIT
+ * http://zeroclipboard.org/
+ * v2.2.0
+ */
+(function(window, undefined) {
+ "use strict";
+ /**
+ * Store references to critically important global functions that may be
+ * overridden on certain web pages.
+ */
+ var _window = window, _document = _window.document, _navigator = _window.navigator, _setTimeout = _window.setTimeout, _clearTimeout = _window.clearTimeout, _setInterval = _window.setInterval, _clearInterval = _window.clearInterval, _getComputedStyle = _window.getComputedStyle, _encodeURIComponent = _window.encodeURIComponent, _ActiveXObject = _window.ActiveXObject, _Error = _window.Error, _parseInt = _window.Number.parseInt || _window.parseInt, _parseFloat = _window.Number.parseFloat || _window.parseFloat, _isNaN = _window.Number.isNaN || _window.isNaN, _now = _window.Date.now, _keys = _window.Object.keys, _defineProperty = _window.Object.defineProperty, _hasOwn = _window.Object.prototype.hasOwnProperty, _slice = _window.Array.prototype.slice, _unwrap = function() {
+ var unwrapper = function(el) {
+ return el;
+ };
+ if (typeof _window.wrap === "function" && typeof _window.unwrap === "function") {
+ try {
+ var div = _document.createElement("div");
+ var unwrappedDiv = _window.unwrap(div);
+ if (div.nodeType === 1 && unwrappedDiv && unwrappedDiv.nodeType === 1) {
+ unwrapper = _window.unwrap;
+ }
+ } catch (e) {}
+ }
+ return unwrapper;
+ }();
+ /**
+ * Convert an `arguments` object into an Array.
+ *
+ * @returns The arguments as an Array
+ * @private
+ */
+ var _args = function(argumentsObj) {
+ return _slice.call(argumentsObj, 0);
+ };
+ /**
+ * Shallow-copy the owned, enumerable properties of one object over to another, similar to jQuery's `$.extend`.
+ *
+ * @returns The target object, augmented
+ * @private
+ */
+ var _extend = function() {
+ var i, len, arg, prop, src, copy, args = _args(arguments), target = args[0] || {};
+ for (i = 1, len = args.length; i < len; i++) {
+ if ((arg = args[i]) != null) {
+ for (prop in arg) {
+ if (_hasOwn.call(arg, prop)) {
+ src = target[prop];
+ copy = arg[prop];
+ if (target !== copy && copy !== undefined) {
+ target[prop] = copy;
+ }
+ }
+ }
+ }
+ }
+ return target;
+ };
+ /**
+ * Return a deep copy of the source object or array.
+ *
+ * @returns Object or Array
+ * @private
+ */
+ var _deepCopy = function(source) {
+ var copy, i, len, prop;
+ if (typeof source !== "object" || source == null || typeof source.nodeType === "number") {
+ copy = source;
+ } else if (typeof source.length === "number") {
+ copy = [];
+ for (i = 0, len = source.length; i < len; i++) {
+ if (_hasOwn.call(source, i)) {
+ copy[i] = _deepCopy(source[i]);
+ }
+ }
+ } else {
+ copy = {};
+ for (prop in source) {
+ if (_hasOwn.call(source, prop)) {
+ copy[prop] = _deepCopy(source[prop]);
+ }
+ }
+ }
+ return copy;
+ };
+ /**
+ * Makes a shallow copy of `obj` (like `_extend`) but filters its properties based on a list of `keys` to keep.
+ * The inverse of `_omit`, mostly. The big difference is that these properties do NOT need to be enumerable to
+ * be kept.
+ *
+ * @returns A new filtered object.
+ * @private
+ */
+ var _pick = function(obj, keys) {
+ var newObj = {};
+ for (var i = 0, len = keys.length; i < len; i++) {
+ if (keys[i] in obj) {
+ newObj[keys[i]] = obj[keys[i]];
+ }
+ }
+ return newObj;
+ };
+ /**
+ * Makes a shallow copy of `obj` (like `_extend`) but filters its properties based on a list of `keys` to omit.
+ * The inverse of `_pick`.
+ *
+ * @returns A new filtered object.
+ * @private
+ */
+ var _omit = function(obj, keys) {
+ var newObj = {};
+ for (var prop in obj) {
+ if (keys.indexOf(prop) === -1) {
+ newObj[prop] = obj[prop];
+ }
+ }
+ return newObj;
+ };
+ /**
+ * Remove all owned, enumerable properties from an object.
+ *
+ * @returns The original object without its owned, enumerable properties.
+ * @private
+ */
+ var _deleteOwnProperties = function(obj) {
+ if (obj) {
+ for (var prop in obj) {
+ if (_hasOwn.call(obj, prop)) {
+ delete obj[prop];
+ }
+ }
+ }
+ return obj;
+ };
+ /**
+ * Determine if an element is contained within another element.
+ *
+ * @returns Boolean
+ * @private
+ */
+ var _containedBy = function(el, ancestorEl) {
+ if (el && el.nodeType === 1 && el.ownerDocument && ancestorEl && (ancestorEl.nodeType === 1 && ancestorEl.ownerDocument && ancestorEl.ownerDocument === el.ownerDocument || ancestorEl.nodeType === 9 && !ancestorEl.ownerDocument && ancestorEl === el.ownerDocument)) {
+ do {
+ if (el === ancestorEl) {
+ return true;
+ }
+ el = el.parentNode;
+ } while (el);
+ }
+ return false;
+ };
+ /**
+ * Get the URL path's parent directory.
+ *
+ * @returns String or `undefined`
+ * @private
+ */
+ var _getDirPathOfUrl = function(url) {
+ var dir;
+ if (typeof url === "string" && url) {
+ dir = url.split("#")[0].split("?")[0];
+ dir = url.slice(0, url.lastIndexOf("/") + 1);
+ }
+ return dir;
+ };
+ /**
+ * Get the current script's URL by throwing an `Error` and analyzing it.
+ *
+ * @returns String or `undefined`
+ * @private
+ */
+ var _getCurrentScriptUrlFromErrorStack = function(stack) {
+ var url, matches;
+ if (typeof stack === "string" && stack) {
+ matches = stack.match(/^(?:|[^:@]*@|.+\)@(?=http[s]?|file)|.+?\s+(?: at |@)(?:[^:\(]+ )*[\(]?)((?:http[s]?|file):\/\/[\/]?.+?\/[^:\)]*?)(?::\d+)(?::\d+)?/);
+ if (matches && matches[1]) {
+ url = matches[1];
+ } else {
+ matches = stack.match(/\)@((?:http[s]?|file):\/\/[\/]?.+?\/[^:\)]*?)(?::\d+)(?::\d+)?/);
+ if (matches && matches[1]) {
+ url = matches[1];
+ }
+ }
+ }
+ return url;
+ };
+ /**
+ * Get the current script's URL by throwing an `Error` and analyzing it.
+ *
+ * @returns String or `undefined`
+ * @private
+ */
+ var _getCurrentScriptUrlFromError = function() {
+ var url, err;
+ try {
+ throw new _Error();
+ } catch (e) {
+ err = e;
+ }
+ if (err) {
+ url = err.sourceURL || err.fileName || _getCurrentScriptUrlFromErrorStack(err.stack);
+ }
+ return url;
+ };
+ /**
+ * Get the current script's URL.
+ *
+ * @returns String or `undefined`
+ * @private
+ */
+ var _getCurrentScriptUrl = function() {
+ var jsPath, scripts, i;
+ if (_document.currentScript && (jsPath = _document.currentScript.src)) {
+ return jsPath;
+ }
+ scripts = _document.getElementsByTagName("script");
+ if (scripts.length === 1) {
+ return scripts[0].src || undefined;
+ }
+ if ("readyState" in scripts[0]) {
+ for (i = scripts.length; i--; ) {
+ if (scripts[i].readyState === "interactive" && (jsPath = scripts[i].src)) {
+ return jsPath;
+ }
+ }
+ }
+ if (_document.readyState === "loading" && (jsPath = scripts[scripts.length - 1].src)) {
+ return jsPath;
+ }
+ if (jsPath = _getCurrentScriptUrlFromError()) {
+ return jsPath;
+ }
+ return undefined;
+ };
+ /**
+ * Get the unanimous parent directory of ALL script tags.
+ * If any script tags are either (a) inline or (b) from differing parent
+ * directories, this method must return `undefined`.
+ *
+ * @returns String or `undefined`
+ * @private
+ */
+ var _getUnanimousScriptParentDir = function() {
+ var i, jsDir, jsPath, scripts = _document.getElementsByTagName("script");
+ for (i = scripts.length; i--; ) {
+ if (!(jsPath = scripts[i].src)) {
+ jsDir = null;
+ break;
+ }
+ jsPath = _getDirPathOfUrl(jsPath);
+ if (jsDir == null) {
+ jsDir = jsPath;
+ } else if (jsDir !== jsPath) {
+ jsDir = null;
+ break;
+ }
+ }
+ return jsDir || undefined;
+ };
+ /**
+ * Get the presumed location of the "ZeroClipboard.swf" file, based on the location
+ * of the executing JavaScript file (e.g. "ZeroClipboard.js", etc.).
+ *
+ * @returns String
+ * @private
+ */
+ var _getDefaultSwfPath = function() {
+ var jsDir = _getDirPathOfUrl(_getCurrentScriptUrl()) || _getUnanimousScriptParentDir() || "";
+ return jsDir + "ZeroClipboard.swf";
+ };
+ /**
+ * Keep track of if the page is framed (in an `iframe`). This can never change.
+ * @private
+ */
+ var _pageIsFramed = function() {
+ return window.opener == null && (!!window.top && window != window.top || !!window.parent && window != window.parent);
+ }();
+ /**
+ * Keep track of the state of the Flash object.
+ * @private
+ */
+ var _flashState = {
+ bridge: null,
+ version: "0.0.0",
+ pluginType: "unknown",
+ disabled: null,
+ outdated: null,
+ sandboxed: null,
+ unavailable: null,
+ degraded: null,
+ deactivated: null,
+ overdue: null,
+ ready: null
+ };
+ /**
+ * The minimum Flash Player version required to use ZeroClipboard completely.
+ * @readonly
+ * @private
+ */
+ var _minimumFlashVersion = "11.0.0";
+ /**
+ * The ZeroClipboard library version number, as reported by Flash, at the time the SWF was compiled.
+ */
+ var _zcSwfVersion;
+ /**
+ * Keep track of all event listener registrations.
+ * @private
+ */
+ var _handlers = {};
+ /**
+ * Keep track of the currently activated element.
+ * @private
+ */
+ var _currentElement;
+ /**
+ * Keep track of the element that was activated when a `copy` process started.
+ * @private
+ */
+ var _copyTarget;
+ /**
+ * Keep track of data for the pending clipboard transaction.
+ * @private
+ */
+ var _clipData = {};
+ /**
+ * Keep track of data formats for the pending clipboard transaction.
+ * @private
+ */
+ var _clipDataFormatMap = null;
+ /**
+ * Keep track of the Flash availability check timeout.
+ * @private
+ */
+ var _flashCheckTimeout = 0;
+ /**
+ * Keep track of SWF network errors interval polling.
+ * @private
+ */
+ var _swfFallbackCheckInterval = 0;
+ /**
+ * The `message` store for events
+ * @private
+ */
+ var _eventMessages = {
+ ready: "Flash communication is established",
+ error: {
+ "flash-disabled": "Flash is disabled or not installed. May also be attempting to run Flash in a sandboxed iframe, which is impossible.",
+ "flash-outdated": "Flash is too outdated to support ZeroClipboard",
+ "flash-sandboxed": "Attempting to run Flash in a sandboxed iframe, which is impossible",
+ "flash-unavailable": "Flash is unable to communicate bidirectionally with JavaScript",
+ "flash-degraded": "Flash is unable to preserve data fidelity when communicating with JavaScript",
+ "flash-deactivated": "Flash is too outdated for your browser and/or is configured as click-to-activate.\nThis may also mean that the ZeroClipboard SWF object could not be loaded, so please check your `swfPath` configuration and/or network connectivity.\nMay also be attempting to run Flash in a sandboxed iframe, which is impossible.",
+ "flash-overdue": "Flash communication was established but NOT within the acceptable time limit",
+ "version-mismatch": "ZeroClipboard JS version number does not match ZeroClipboard SWF version number",
+ "clipboard-error": "At least one error was thrown while ZeroClipboard was attempting to inject your data into the clipboard",
+ "config-mismatch": "ZeroClipboard configuration does not match Flash's reality",
+ "swf-not-found": "The ZeroClipboard SWF object could not be loaded, so please check your `swfPath` configuration and/or network connectivity"
+ }
+ };
+ /**
+ * The `name`s of `error` events that can only occur is Flash has at least
+ * been able to load the SWF successfully.
+ * @private
+ */
+ var _errorsThatOnlyOccurAfterFlashLoads = [ "flash-unavailable", "flash-degraded", "flash-overdue", "version-mismatch", "config-mismatch", "clipboard-error" ];
+ /**
+ * The `name`s of `error` events that should likely result in the `_flashState`
+ * variable's property values being updated.
+ * @private
+ */
+ var _flashStateErrorNames = [ "flash-disabled", "flash-outdated", "flash-sandboxed", "flash-unavailable", "flash-degraded", "flash-deactivated", "flash-overdue" ];
+ /**
+ * A RegExp to match the `name` property of `error` events related to Flash.
+ * @private
+ */
+ var _flashStateErrorNameMatchingRegex = new RegExp("^flash-(" + _flashStateErrorNames.map(function(errorName) {
+ return errorName.replace(/^flash-/, "");
+ }).join("|") + ")$");
+ /**
+ * A RegExp to match the `name` property of `error` events related to Flash,
+ * which is enabled.
+ * @private
+ */
+ var _flashStateEnabledErrorNameMatchingRegex = new RegExp("^flash-(" + _flashStateErrorNames.slice(1).map(function(errorName) {
+ return errorName.replace(/^flash-/, "");
+ }).join("|") + ")$");
+ /**
+ * ZeroClipboard configuration defaults for the Core module.
+ * @private
+ */
+ var _globalConfig = {
+ swfPath: _getDefaultSwfPath(),
+ trustedDomains: window.location.host ? [ window.location.host ] : [],
+ cacheBust: true,
+ forceEnhancedClipboard: false,
+ flashLoadTimeout: 3e4,
+ autoActivate: true,
+ bubbleEvents: true,
+ containerId: "global-zeroclipboard-html-bridge",
+ containerClass: "global-zeroclipboard-container",
+ swfObjectId: "global-zeroclipboard-flash-bridge",
+ hoverClass: "zeroclipboard-is-hover",
+ activeClass: "zeroclipboard-is-active",
+ forceHandCursor: false,
+ title: null,
+ zIndex: 999999999
+ };
+ /**
+ * The underlying implementation of `ZeroClipboard.config`.
+ * @private
+ */
+ var _config = function(options) {
+ if (typeof options === "object" && options !== null) {
+ for (var prop in options) {
+ if (_hasOwn.call(options, prop)) {
+ if (/^(?:forceHandCursor|title|zIndex|bubbleEvents)$/.test(prop)) {
+ _globalConfig[prop] = options[prop];
+ } else if (_flashState.bridge == null) {
+ if (prop === "containerId" || prop === "swfObjectId") {
+ if (_isValidHtml4Id(options[prop])) {
+ _globalConfig[prop] = options[prop];
+ } else {
+ throw new Error("The specified `" + prop + "` value is not valid as an HTML4 Element ID");
+ }
+ } else {
+ _globalConfig[prop] = options[prop];
+ }
+ }
+ }
+ }
+ }
+ if (typeof options === "string" && options) {
+ if (_hasOwn.call(_globalConfig, options)) {
+ return _globalConfig[options];
+ }
+ return;
+ }
+ return _deepCopy(_globalConfig);
+ };
+ /**
+ * The underlying implementation of `ZeroClipboard.state`.
+ * @private
+ */
+ var _state = function() {
+ _detectSandbox();
+ return {
+ browser: _pick(_navigator, [ "userAgent", "platform", "appName" ]),
+ flash: _omit(_flashState, [ "bridge" ]),
+ zeroclipboard: {
+ version: ZeroClipboard.version,
+ config: ZeroClipboard.config()
+ }
+ };
+ };
+ /**
+ * The underlying implementation of `ZeroClipboard.isFlashUnusable`.
+ * @private
+ */
+ var _isFlashUnusable = function() {
+ return !!(_flashState.disabled || _flashState.outdated || _flashState.sandboxed || _flashState.unavailable || _flashState.degraded || _flashState.deactivated);
+ };
+ /**
+ * The underlying implementation of `ZeroClipboard.on`.
+ * @private
+ */
+ var _on = function(eventType, listener) {
+ var i, len, events, added = {};
+ if (typeof eventType === "string" && eventType) {
+ events = eventType.toLowerCase().split(/\s+/);
+ } else if (typeof eventType === "object" && eventType && typeof listener === "undefined") {
+ for (i in eventType) {
+ if (_hasOwn.call(eventType, i) && typeof i === "string" && i && typeof eventType[i] === "function") {
+ ZeroClipboard.on(i, eventType[i]);
+ }
+ }
+ }
+ if (events && events.length) {
+ for (i = 0, len = events.length; i < len; i++) {
+ eventType = events[i].replace(/^on/, "");
+ added[eventType] = true;
+ if (!_handlers[eventType]) {
+ _handlers[eventType] = [];
+ }
+ _handlers[eventType].push(listener);
+ }
+ if (added.ready && _flashState.ready) {
+ ZeroClipboard.emit({
+ type: "ready"
+ });
+ }
+ if (added.error) {
+ for (i = 0, len = _flashStateErrorNames.length; i < len; i++) {
+ if (_flashState[_flashStateErrorNames[i].replace(/^flash-/, "")] === true) {
+ ZeroClipboard.emit({
+ type: "error",
+ name: _flashStateErrorNames[i]
+ });
+ break;
+ }
+ }
+ if (_zcSwfVersion !== undefined && ZeroClipboard.version !== _zcSwfVersion) {
+ ZeroClipboard.emit({
+ type: "error",
+ name: "version-mismatch",
+ jsVersion: ZeroClipboard.version,
+ swfVersion: _zcSwfVersion
+ });
+ }
+ }
+ }
+ return ZeroClipboard;
+ };
+ /**
+ * The underlying implementation of `ZeroClipboard.off`.
+ * @private
+ */
+ var _off = function(eventType, listener) {
+ var i, len, foundIndex, events, perEventHandlers;
+ if (arguments.length === 0) {
+ events = _keys(_handlers);
+ } else if (typeof eventType === "string" && eventType) {
+ events = eventType.split(/\s+/);
+ } else if (typeof eventType === "object" && eventType && typeof listener === "undefined") {
+ for (i in eventType) {
+ if (_hasOwn.call(eventType, i) && typeof i === "string" && i && typeof eventType[i] === "function") {
+ ZeroClipboard.off(i, eventType[i]);
+ }
+ }
+ }
+ if (events && events.length) {
+ for (i = 0, len = events.length; i < len; i++) {
+ eventType = events[i].toLowerCase().replace(/^on/, "");
+ perEventHandlers = _handlers[eventType];
+ if (perEventHandlers && perEventHandlers.length) {
+ if (listener) {
+ foundIndex = perEventHandlers.indexOf(listener);
+ while (foundIndex !== -1) {
+ perEventHandlers.splice(foundIndex, 1);
+ foundIndex = perEventHandlers.indexOf(listener, foundIndex);
+ }
+ } else {
+ perEventHandlers.length = 0;
+ }
+ }
+ }
+ }
+ return ZeroClipboard;
+ };
+ /**
+ * The underlying implementation of `ZeroClipboard.handlers`.
+ * @private
+ */
+ var _listeners = function(eventType) {
+ var copy;
+ if (typeof eventType === "string" && eventType) {
+ copy = _deepCopy(_handlers[eventType]) || null;
+ } else {
+ copy = _deepCopy(_handlers);
+ }
+ return copy;
+ };
+ /**
+ * The underlying implementation of `ZeroClipboard.emit`.
+ * @private
+ */
+ var _emit = function(event) {
+ var eventCopy, returnVal, tmp;
+ event = _createEvent(event);
+ if (!event) {
+ return;
+ }
+ if (_preprocessEvent(event)) {
+ return;
+ }
+ if (event.type === "ready" && _flashState.overdue === true) {
+ return ZeroClipboard.emit({
+ type: "error",
+ name: "flash-overdue"
+ });
+ }
+ eventCopy = _extend({}, event);
+ _dispatchCallbacks.call(this, eventCopy);
+ if (event.type === "copy") {
+ tmp = _mapClipDataToFlash(_clipData);
+ returnVal = tmp.data;
+ _clipDataFormatMap = tmp.formatMap;
+ }
+ return returnVal;
+ };
+ /**
+ * The underlying implementation of `ZeroClipboard.create`.
+ * @private
+ */
+ var _create = function() {
+ var previousState = _flashState.sandboxed;
+ _detectSandbox();
+ if (typeof _flashState.ready !== "boolean") {
+ _flashState.ready = false;
+ }
+ if (_flashState.sandboxed !== previousState && _flashState.sandboxed === true) {
+ _flashState.ready = false;
+ ZeroClipboard.emit({
+ type: "error",
+ name: "flash-sandboxed"
+ });
+ } else if (!ZeroClipboard.isFlashUnusable() && _flashState.bridge === null) {
+ var maxWait = _globalConfig.flashLoadTimeout;
+ if (typeof maxWait === "number" && maxWait >= 0) {
+ _flashCheckTimeout = _setTimeout(function() {
+ if (typeof _flashState.deactivated !== "boolean") {
+ _flashState.deactivated = true;
+ }
+ if (_flashState.deactivated === true) {
+ ZeroClipboard.emit({
+ type: "error",
+ name: "flash-deactivated"
+ });
+ }
+ }, maxWait);
+ }
+ _flashState.overdue = false;
+ _embedSwf();
+ }
+ };
+ /**
+ * The underlying implementation of `ZeroClipboard.destroy`.
+ * @private
+ */
+ var _destroy = function() {
+ ZeroClipboard.clearData();
+ ZeroClipboard.blur();
+ ZeroClipboard.emit("destroy");
+ _unembedSwf();
+ ZeroClipboard.off();
+ };
+ /**
+ * The underlying implementation of `ZeroClipboard.setData`.
+ * @private
+ */
+ var _setData = function(format, data) {
+ var dataObj;
+ if (typeof format === "object" && format && typeof data === "undefined") {
+ dataObj = format;
+ ZeroClipboard.clearData();
+ } else if (typeof format === "string" && format) {
+ dataObj = {};
+ dataObj[format] = data;
+ } else {
+ return;
+ }
+ for (var dataFormat in dataObj) {
+ if (typeof dataFormat === "string" && dataFormat && _hasOwn.call(dataObj, dataFormat) && typeof dataObj[dataFormat] === "string" && dataObj[dataFormat]) {
+ _clipData[dataFormat] = dataObj[dataFormat];
+ }
+ }
+ };
+ /**
+ * The underlying implementation of `ZeroClipboard.clearData`.
+ * @private
+ */
+ var _clearData = function(format) {
+ if (typeof format === "undefined") {
+ _deleteOwnProperties(_clipData);
+ _clipDataFormatMap = null;
+ } else if (typeof format === "string" && _hasOwn.call(_clipData, format)) {
+ delete _clipData[format];
+ }
+ };
+ /**
+ * The underlying implementation of `ZeroClipboard.getData`.
+ * @private
+ */
+ var _getData = function(format) {
+ if (typeof format === "undefined") {
+ return _deepCopy(_clipData);
+ } else if (typeof format === "string" && _hasOwn.call(_clipData, format)) {
+ return _clipData[format];
+ }
+ };
+ /**
+ * The underlying implementation of `ZeroClipboard.focus`/`ZeroClipboard.activate`.
+ * @private
+ */
+ var _focus = function(element) {
+ if (!(element && element.nodeType === 1)) {
+ return;
+ }
+ if (_currentElement) {
+ _removeClass(_currentElement, _globalConfig.activeClass);
+ if (_currentElement !== element) {
+ _removeClass(_currentElement, _globalConfig.hoverClass);
+ }
+ }
+ _currentElement = element;
+ _addClass(element, _globalConfig.hoverClass);
+ var newTitle = element.getAttribute("title") || _globalConfig.title;
+ if (typeof newTitle === "string" && newTitle) {
+ var htmlBridge = _getHtmlBridge(_flashState.bridge);
+ if (htmlBridge) {
+ htmlBridge.setAttribute("title", newTitle);
+ }
+ }
+ var useHandCursor = _globalConfig.forceHandCursor === true || _getStyle(element, "cursor") === "pointer";
+ _setHandCursor(useHandCursor);
+ _reposition();
+ };
+ /**
+ * The underlying implementation of `ZeroClipboard.blur`/`ZeroClipboard.deactivate`.
+ * @private
+ */
+ var _blur = function() {
+ var htmlBridge = _getHtmlBridge(_flashState.bridge);
+ if (htmlBridge) {
+ htmlBridge.removeAttribute("title");
+ htmlBridge.style.left = "0px";
+ htmlBridge.style.top = "-9999px";
+ htmlBridge.style.width = "1px";
+ htmlBridge.style.height = "1px";
+ }
+ if (_currentElement) {
+ _removeClass(_currentElement, _globalConfig.hoverClass);
+ _removeClass(_currentElement, _globalConfig.activeClass);
+ _currentElement = null;
+ }
+ };
+ /**
+ * The underlying implementation of `ZeroClipboard.activeElement`.
+ * @private
+ */
+ var _activeElement = function() {
+ return _currentElement || null;
+ };
+ /**
+ * Check if a value is a valid HTML4 `ID` or `Name` token.
+ * @private
+ */
+ var _isValidHtml4Id = function(id) {
+ return typeof id === "string" && id && /^[A-Za-z][A-Za-z0-9_:\-\.]*$/.test(id);
+ };
+ /**
+ * Create or update an `event` object, based on the `eventType`.
+ * @private
+ */
+ var _createEvent = function(event) {
+ var eventType;
+ if (typeof event === "string" && event) {
+ eventType = event;
+ event = {};
+ } else if (typeof event === "object" && event && typeof event.type === "string" && event.type) {
+ eventType = event.type;
+ }
+ if (!eventType) {
+ return;
+ }
+ eventType = eventType.toLowerCase();
+ if (!event.target && (/^(copy|aftercopy|_click)$/.test(eventType) || eventType === "error" && event.name === "clipboard-error")) {
+ event.target = _copyTarget;
+ }
+ _extend(event, {
+ type: eventType,
+ target: event.target || _currentElement || null,
+ relatedTarget: event.relatedTarget || null,
+ currentTarget: _flashState && _flashState.bridge || null,
+ timeStamp: event.timeStamp || _now() || null
+ });
+ var msg = _eventMessages[event.type];
+ if (event.type === "error" && event.name && msg) {
+ msg = msg[event.name];
+ }
+ if (msg) {
+ event.message = msg;
+ }
+ if (event.type === "ready") {
+ _extend(event, {
+ target: null,
+ version: _flashState.version
+ });
+ }
+ if (event.type === "error") {
+ if (_flashStateErrorNameMatchingRegex.test(event.name)) {
+ _extend(event, {
+ target: null,
+ minimumVersion: _minimumFlashVersion
+ });
+ }
+ if (_flashStateEnabledErrorNameMatchingRegex.test(event.name)) {
+ _extend(event, {
+ version: _flashState.version
+ });
+ }
+ }
+ if (event.type === "copy") {
+ event.clipboardData = {
+ setData: ZeroClipboard.setData,
+ clearData: ZeroClipboard.clearData
+ };
+ }
+ if (event.type === "aftercopy") {
+ event = _mapClipResultsFromFlash(event, _clipDataFormatMap);
+ }
+ if (event.target && !event.relatedTarget) {
+ event.relatedTarget = _getRelatedTarget(event.target);
+ }
+ return _addMouseData(event);
+ };
+ /**
+ * Get a relatedTarget from the target's `data-clipboard-target` attribute
+ * @private
+ */
+ var _getRelatedTarget = function(targetEl) {
+ var relatedTargetId = targetEl && targetEl.getAttribute && targetEl.getAttribute("data-clipboard-target");
+ return relatedTargetId ? _document.getElementById(relatedTargetId) : null;
+ };
+ /**
+ * Add element and position data to `MouseEvent` instances
+ * @private
+ */
+ var _addMouseData = function(event) {
+ if (event && /^_(?:click|mouse(?:over|out|down|up|move))$/.test(event.type)) {
+ var srcElement = event.target;
+ var fromElement = event.type === "_mouseover" && event.relatedTarget ? event.relatedTarget : undefined;
+ var toElement = event.type === "_mouseout" && event.relatedTarget ? event.relatedTarget : undefined;
+ var pos = _getElementPosition(srcElement);
+ var screenLeft = _window.screenLeft || _window.screenX || 0;
+ var screenTop = _window.screenTop || _window.screenY || 0;
+ var scrollLeft = _document.body.scrollLeft + _document.documentElement.scrollLeft;
+ var scrollTop = _document.body.scrollTop + _document.documentElement.scrollTop;
+ var pageX = pos.left + (typeof event._stageX === "number" ? event._stageX : 0);
+ var pageY = pos.top + (typeof event._stageY === "number" ? event._stageY : 0);
+ var clientX = pageX - scrollLeft;
+ var clientY = pageY - scrollTop;
+ var screenX = screenLeft + clientX;
+ var screenY = screenTop + clientY;
+ var moveX = typeof event.movementX === "number" ? event.movementX : 0;
+ var moveY = typeof event.movementY === "number" ? event.movementY : 0;
+ delete event._stageX;
+ delete event._stageY;
+ _extend(event, {
+ srcElement: srcElement,
+ fromElement: fromElement,
+ toElement: toElement,
+ screenX: screenX,
+ screenY: screenY,
+ pageX: pageX,
+ pageY: pageY,
+ clientX: clientX,
+ clientY: clientY,
+ x: clientX,
+ y: clientY,
+ movementX: moveX,
+ movementY: moveY,
+ offsetX: 0,
+ offsetY: 0,
+ layerX: 0,
+ layerY: 0
+ });
+ }
+ return event;
+ };
+ /**
+ * Determine if an event's registered handlers should be execute synchronously or asynchronously.
+ *
+ * @returns {boolean}
+ * @private
+ */
+ var _shouldPerformAsync = function(event) {
+ var eventType = event && typeof event.type === "string" && event.type || "";
+ return !/^(?:(?:before)?copy|destroy)$/.test(eventType);
+ };
+ /**
+ * Control if a callback should be executed asynchronously or not.
+ *
+ * @returns `undefined`
+ * @private
+ */
+ var _dispatchCallback = function(func, context, args, async) {
+ if (async) {
+ _setTimeout(function() {
+ func.apply(context, args);
+ }, 0);
+ } else {
+ func.apply(context, args);
+ }
+ };
+ /**
+ * Handle the actual dispatching of events to client instances.
+ *
+ * @returns `undefined`
+ * @private
+ */
+ var _dispatchCallbacks = function(event) {
+ if (!(typeof event === "object" && event && event.type)) {
+ return;
+ }
+ var async = _shouldPerformAsync(event);
+ var wildcardTypeHandlers = _handlers["*"] || [];
+ var specificTypeHandlers = _handlers[event.type] || [];
+ var handlers = wildcardTypeHandlers.concat(specificTypeHandlers);
+ if (handlers && handlers.length) {
+ var i, len, func, context, eventCopy, originalContext = this;
+ for (i = 0, len = handlers.length; i < len; i++) {
+ func = handlers[i];
+ context = originalContext;
+ if (typeof func === "string" && typeof _window[func] === "function") {
+ func = _window[func];
+ }
+ if (typeof func === "object" && func && typeof func.handleEvent === "function") {
+ context = func;
+ func = func.handleEvent;
+ }
+ if (typeof func === "function") {
+ eventCopy = _extend({}, event);
+ _dispatchCallback(func, context, [ eventCopy ], async);
+ }
+ }
+ }
+ return this;
+ };
+ /**
+ * Check an `error` event's `name` property to see if Flash has
+ * already loaded, which rules out possible `iframe` sandboxing.
+ * @private
+ */
+ var _getSandboxStatusFromErrorEvent = function(event) {
+ var isSandboxed = null;
+ if (_pageIsFramed === false || event && event.type === "error" && event.name && _errorsThatOnlyOccurAfterFlashLoads.indexOf(event.name) !== -1) {
+ isSandboxed = false;
+ }
+ return isSandboxed;
+ };
+ /**
+ * Preprocess any special behaviors, reactions, or state changes after receiving this event.
+ * Executes only once per event emitted, NOT once per client.
+ * @private
+ */
+ var _preprocessEvent = function(event) {
+ var element = event.target || _currentElement || null;
+ var sourceIsSwf = event._source === "swf";
+ delete event._source;
+ switch (event.type) {
+ case "error":
+ var isSandboxed = event.name === "flash-sandboxed" || _getSandboxStatusFromErrorEvent(event);
+ if (typeof isSandboxed === "boolean") {
+ _flashState.sandboxed = isSandboxed;
+ }
+ if (_flashStateErrorNames.indexOf(event.name) !== -1) {
+ _extend(_flashState, {
+ disabled: event.name === "flash-disabled",
+ outdated: event.name === "flash-outdated",
+ unavailable: event.name === "flash-unavailable",
+ degraded: event.name === "flash-degraded",
+ deactivated: event.name === "flash-deactivated",
+ overdue: event.name === "flash-overdue",
+ ready: false
+ });
+ } else if (event.name === "version-mismatch") {
+ _zcSwfVersion = event.swfVersion;
+ _extend(_flashState, {
+ disabled: false,
+ outdated: false,
+ unavailable: false,
+ degraded: false,
+ deactivated: false,
+ overdue: false,
+ ready: false
+ });
+ }
+ _clearTimeoutsAndPolling();
+ break;
-var ZeroClipboard = {
-
- version: "1.0.7",
- clients: {}, // registered upload clients on page, indexed by id
- moviePath: 'ZeroClipboard.swf', // URL to movie
- nextId: 1, // ID of next movie
-
- $: function(thingy) {
- // simple DOM lookup utility function
- if (typeof(thingy) == 'string') thingy = document.getElementById(thingy);
- if (!thingy.addClass) {
- // extend element with a few useful methods
- thingy.hide = function() { this.style.display = 'none'; };
- thingy.show = function() { this.style.display = ''; };
- thingy.addClass = function(name) { this.removeClass(name); this.className += ' ' + name; };
- thingy.removeClass = function(name) {
- var classes = this.className.split(/\s+/);
- var idx = -1;
- for (var k = 0; k < classes.length; k++) {
- if (classes[k] == name) { idx = k; k = classes.length; }
- }
- if (idx > -1) {
- classes.splice( idx, 1 );
- this.className = classes.join(' ');
- }
- return this;
- };
- thingy.hasClass = function(name) {
- return !!this.className.match( new RegExp("\\s*" + name + "\\s*") );
- };
- }
- return thingy;
- },
-
- setMoviePath: function(path) {
- // set path to ZeroClipboard.swf
- this.moviePath = path;
- },
-
- dispatch: function(id, eventName, args) {
- // receive event from flash movie, send to client
- var client = this.clients[id];
- if (client) {
- client.receiveEvent(eventName, args);
- }
- },
-
- register: function(id, client) {
- // register new client to receive events
- this.clients[id] = client;
- },
-
- getDOMObjectPosition: function(obj, stopObj) {
- // get absolute coordinates for dom element
- var info = {
- left: 0,
- top: 0,
- width: obj.width ? obj.width : obj.offsetWidth,
- height: obj.height ? obj.height : obj.offsetHeight
- };
+ case "ready":
+ _zcSwfVersion = event.swfVersion;
+ var wasDeactivated = _flashState.deactivated === true;
+ _extend(_flashState, {
+ disabled: false,
+ outdated: false,
+ sandboxed: false,
+ unavailable: false,
+ degraded: false,
+ deactivated: false,
+ overdue: wasDeactivated,
+ ready: !wasDeactivated
+ });
+ _clearTimeoutsAndPolling();
+ break;
+
+ case "beforecopy":
+ _copyTarget = element;
+ break;
+
+ case "copy":
+ var textContent, htmlContent, targetEl = event.relatedTarget;
+ if (!(_clipData["text/html"] || _clipData["text/plain"]) && targetEl && (htmlContent = targetEl.value || targetEl.outerHTML || targetEl.innerHTML) && (textContent = targetEl.value || targetEl.textContent || targetEl.innerText)) {
+ event.clipboardData.clearData();
+ event.clipboardData.setData("text/plain", textContent);
+ if (htmlContent !== textContent) {
+ event.clipboardData.setData("text/html", htmlContent);
+ }
+ } else if (!_clipData["text/plain"] && event.target && (textContent = event.target.getAttribute("data-clipboard-text"))) {
+ event.clipboardData.clearData();
+ event.clipboardData.setData("text/plain", textContent);
+ }
+ break;
+
+ case "aftercopy":
+ _queueEmitClipboardErrors(event);
+ ZeroClipboard.clearData();
+ if (element && element !== _safeActiveElement() && element.focus) {
+ element.focus();
+ }
+ break;
- while (obj && (obj != stopObj)) {
- info.left += obj.offsetLeft;
- info.top += obj.offsetTop;
- obj = obj.offsetParent;
- }
+ case "_mouseover":
+ ZeroClipboard.focus(element);
+ if (_globalConfig.bubbleEvents === true && sourceIsSwf) {
+ if (element && element !== event.relatedTarget && !_containedBy(event.relatedTarget, element)) {
+ _fireMouseEvent(_extend({}, event, {
+ type: "mouseenter",
+ bubbles: false,
+ cancelable: false
+ }));
+ }
+ _fireMouseEvent(_extend({}, event, {
+ type: "mouseover"
+ }));
+ }
+ break;
- return info;
- },
-
- Client: function(elem) {
- // constructor for new simple upload client
- this.handlers = {};
-
- // unique ID
- this.id = ZeroClipboard.nextId++;
- this.movieId = 'ZeroClipboardMovie_' + this.id;
-
- // register client with singleton to receive flash events
- ZeroClipboard.register(this.id, this);
-
- // create movie
- if (elem) this.glue(elem);
- }
-};
+ case "_mouseout":
+ ZeroClipboard.blur();
+ if (_globalConfig.bubbleEvents === true && sourceIsSwf) {
+ if (element && element !== event.relatedTarget && !_containedBy(event.relatedTarget, element)) {
+ _fireMouseEvent(_extend({}, event, {
+ type: "mouseleave",
+ bubbles: false,
+ cancelable: false
+ }));
+ }
+ _fireMouseEvent(_extend({}, event, {
+ type: "mouseout"
+ }));
+ }
+ break;
+
+ case "_mousedown":
+ _addClass(element, _globalConfig.activeClass);
+ if (_globalConfig.bubbleEvents === true && sourceIsSwf) {
+ _fireMouseEvent(_extend({}, event, {
+ type: event.type.slice(1)
+ }));
+ }
+ break;
+
+ case "_mouseup":
+ _removeClass(element, _globalConfig.activeClass);
+ if (_globalConfig.bubbleEvents === true && sourceIsSwf) {
+ _fireMouseEvent(_extend({}, event, {
+ type: event.type.slice(1)
+ }));
+ }
+ break;
+
+ case "_click":
+ _copyTarget = null;
+ if (_globalConfig.bubbleEvents === true && sourceIsSwf) {
+ _fireMouseEvent(_extend({}, event, {
+ type: event.type.slice(1)
+ }));
+ }
+ break;
-ZeroClipboard.Client.prototype = {
-
- id: 0, // unique ID for us
- ready: false, // whether movie is ready to receive events or not
- movie: null, // reference to movie object
- clipText: '', // text to copy to clipboard
- handCursorEnabled: true, // whether to show hand cursor, or default pointer cursor
- cssEffects: true, // enable CSS mouse effects on dom container
- handlers: null, // user event handlers
-
- glue: function(elem, appendElem, stylesToAdd) {
- // glue to DOM element
- // elem can be ID or actual DOM element object
- this.domElement = ZeroClipboard.$(elem);
-
- // float just above object, or zIndex 99 if dom element isn't set
- var zIndex = 99;
- if (this.domElement.style.zIndex) {
- zIndex = parseInt(this.domElement.style.zIndex, 10) + 1;
- }
-
- if (typeof(appendElem) == 'string') {
- appendElem = ZeroClipboard.$(appendElem);
- }
- else if (typeof(appendElem) == 'undefined') {
- appendElem = document.getElementsByTagName('body')[0];
- }
-
- // find X/Y position of domElement
- var box = ZeroClipboard.getDOMObjectPosition(this.domElement, appendElem);
-
- // create floating DIV above element
- this.div = document.createElement('div');
- var style = this.div.style;
- style.position = 'absolute';
- style.left = '' + box.left + 'px';
- style.top = '' + box.top + 'px';
- style.width = '' + box.width + 'px';
- style.height = '' + box.height + 'px';
- style.zIndex = zIndex;
-
- if (typeof(stylesToAdd) == 'object') {
- for (addedStyle in stylesToAdd) {
- style[addedStyle] = stylesToAdd[addedStyle];
- }
- }
-
- // style.backgroundColor = '#f00'; // debug
-
- appendElem.appendChild(this.div);
-
- this.div.innerHTML = this.getHTML( box.width, box.height );
- },
-
- getHTML: function(width, height) {
- // return HTML for movie
- var html = '';
- var flashvars = 'id=' + this.id +
- '&width=' + width +
- '&height=' + height;
-
- if (navigator.userAgent.match(/MSIE/)) {
- // IE gets an OBJECT tag
- var protocol = location.href.match(/^https/i) ? 'https://' : 'http://';
- html += '<object classid="clsid:d27cdb6e-ae6d-11cf-96b8-444553540000" codebase="'+protocol+'download.macromedia.com/pub/shockwave/cabs/flash/swflash.cab#version=9,0,0,0" width="'+width+'" height="'+height+'" id="'+this.movieId+'" align="middle"><param name="allowScriptAccess" value="always" /><param name="allowFullScreen" value="false" /><param name="movie" value="'+ZeroClipboard.moviePath+'" /><param name="loop" value="false" /><param name="menu" value="false" /><param name="quality" value="best" /><param name="bgcolor" value="#ffffff" /><param name="flashvars" value="'+flashvars+'"/><param name="wmode" value="transparent"/></object>';
- }
- else {
- // all other browsers get an EMBED tag
- html += '<embed id="'+this.movieId+'" src="'+ZeroClipboard.moviePath+'" loop="false" menu="false" quality="best" bgcolor="#ffffff" width="'+width+'" height="'+height+'" name="'+this.movieId+'" align="middle" allowScriptAccess="always" allowFullScreen="false" type="application/x-shockwave-flash" pluginspage="http://www.macromedia.com/go/getflashplayer" flashvars="'+flashvars+'" wmode="transparent" />';
- }
- return html;
- },
-
- hide: function() {
- // temporarily hide floater offscreen
- if (this.div) {
- this.div.style.left = '-2000px';
- }
- },
-
- show: function() {
- // show ourselves after a call to hide()
- this.reposition();
- },
-
- destroy: function() {
- // destroy control and floater
- if (this.domElement && this.div) {
- this.hide();
- this.div.innerHTML = '';
-
- var body = document.getElementsByTagName('body')[0];
- try { body.removeChild( this.div ); } catch(e) {;}
-
- this.domElement = null;
- this.div = null;
- }
- },
-
- reposition: function(elem) {
- // reposition our floating div, optionally to new container
- // warning: container CANNOT change size, only position
- if (elem) {
- this.domElement = ZeroClipboard.$(elem);
- if (!this.domElement) this.hide();
- }
-
- if (this.domElement && this.div) {
- var box = ZeroClipboard.getDOMObjectPosition(this.domElement);
- var style = this.div.style;
- style.left = '' + box.left + 'px';
- style.top = '' + box.top + 'px';
- }
- },
-
- setText: function(newText) {
- // set text to be copied to clipboard
- this.clipText = newText;
- if (this.ready) this.movie.setText(newText);
- },
-
- addEventListener: function(eventName, func) {
- // add user event listener for event
- // event types: load, queueStart, fileStart, fileComplete, queueComplete, progress, error, cancel
- eventName = eventName.toString().toLowerCase().replace(/^on/, '');
- if (!this.handlers[eventName]) this.handlers[eventName] = [];
- this.handlers[eventName].push(func);
- },
-
- setHandCursor: function(enabled) {
- // enable hand cursor (true), or default arrow cursor (false)
- this.handCursorEnabled = enabled;
- if (this.ready) this.movie.setHandCursor(enabled);
- },
-
- setCSSEffects: function(enabled) {
- // enable or disable CSS effects on DOM container
- this.cssEffects = !!enabled;
- },
-
- receiveEvent: function(eventName, args) {
- // receive event from flash
- eventName = eventName.toString().toLowerCase().replace(/^on/, '');
-
- // special behavior for certain events
- switch (eventName) {
- case 'load':
- // movie claims it is ready, but in IE this isn't always the case...
- // bug fix: Cannot extend EMBED DOM elements in Firefox, must use traditional function
- this.movie = document.getElementById(this.movieId);
- if (!this.movie) {
- var self = this;
- setTimeout( function() { self.receiveEvent('load', null); }, 1 );
- return;
- }
-
- // firefox on pc needs a "kick" in order to set these in certain cases
- if (!this.ready && navigator.userAgent.match(/Firefox/) && navigator.userAgent.match(/Windows/)) {
- var self = this;
- setTimeout( function() { self.receiveEvent('load', null); }, 100 );
- this.ready = true;
- return;
- }
-
- this.ready = true;
- this.movie.setText( this.clipText );
- this.movie.setHandCursor( this.handCursorEnabled );
- break;
-
- case 'mouseover':
- if (this.domElement && this.cssEffects) {
- this.domElement.addClass('hover');
- if (this.recoverActive) this.domElement.addClass('active');
- }
- break;
-
- case 'mouseout':
- if (this.domElement && this.cssEffects) {
- this.recoverActive = false;
- if (this.domElement.hasClass('active')) {
- this.domElement.removeClass('active');
- this.recoverActive = true;
- }
- this.domElement.removeClass('hover');
- }
- break;
-
- case 'mousedown':
- if (this.domElement && this.cssEffects) {
- this.domElement.addClass('active');
- }
- break;
-
- case 'mouseup':
- if (this.domElement && this.cssEffects) {
- this.domElement.removeClass('active');
- this.recoverActive = false;
- }
- break;
- } // switch eventName
-
- if (this.handlers[eventName]) {
- for (var idx = 0, len = this.handlers[eventName].length; idx < len; idx++) {
- var func = this.handlers[eventName][idx];
-
- if (typeof(func) == 'function') {
- // actual function reference
- func(this, args);
- }
- else if ((typeof(func) == 'object') && (func.length == 2)) {
- // PHP style object + method, i.e. [myObject, 'myMethod']
- func[0][ func[1] ](this, args);
- }
- else if (typeof(func) == 'string') {
- // name of function
- window[func](this, args);
- }
- } // foreach event handler defined
- } // user defined handler for event
- }
-
-};
+ case "_mousemove":
+ if (_globalConfig.bubbleEvents === true && sourceIsSwf) {
+ _fireMouseEvent(_extend({}, event, {
+ type: event.type.slice(1)
+ }));
+ }
+ break;
+ }
+ if (/^_(?:click|mouse(?:over|out|down|up|move))$/.test(event.type)) {
+ return true;
+ }
+ };
+ /**
+ * Check an "aftercopy" event for clipboard errors and emit a corresponding "error" event.
+ * @private
+ */
+ var _queueEmitClipboardErrors = function(aftercopyEvent) {
+ if (aftercopyEvent.errors && aftercopyEvent.errors.length > 0) {
+ var errorEvent = _deepCopy(aftercopyEvent);
+ _extend(errorEvent, {
+ type: "error",
+ name: "clipboard-error"
+ });
+ delete errorEvent.success;
+ _setTimeout(function() {
+ ZeroClipboard.emit(errorEvent);
+ }, 0);
+ }
+ };
+ /**
+ * Dispatch a synthetic MouseEvent.
+ *
+ * @returns `undefined`
+ * @private
+ */
+ var _fireMouseEvent = function(event) {
+ if (!(event && typeof event.type === "string" && event)) {
+ return;
+ }
+ var e, target = event.target || null, doc = target && target.ownerDocument || _document, defaults = {
+ view: doc.defaultView || _window,
+ canBubble: true,
+ cancelable: true,
+ detail: event.type === "click" ? 1 : 0,
+ button: typeof event.which === "number" ? event.which - 1 : typeof event.button === "number" ? event.button : doc.createEvent ? 0 : 1
+ }, args = _extend(defaults, event);
+ if (!target) {
+ return;
+ }
+ if (doc.createEvent && target.dispatchEvent) {
+ args = [ args.type, args.canBubble, args.cancelable, args.view, args.detail, args.screenX, args.screenY, args.clientX, args.clientY, args.ctrlKey, args.altKey, args.shiftKey, args.metaKey, args.button, args.relatedTarget ];
+ e = doc.createEvent("MouseEvents");
+ if (e.initMouseEvent) {
+ e.initMouseEvent.apply(e, args);
+ e._source = "js";
+ target.dispatchEvent(e);
+ }
+ }
+ };
+ /**
+ * Continuously poll the DOM until either:
+ * (a) the fallback content becomes visible, or
+ * (b) we receive an event from SWF (handled elsewhere)
+ *
+ * IMPORTANT:
+ * This is NOT a necessary check but it can result in significantly faster
+ * detection of bad `swfPath` configuration and/or network/server issues [in
+ * supported browsers] than waiting for the entire `flashLoadTimeout` duration
+ * to elapse before detecting that the SWF cannot be loaded. The detection
+ * duration can be anywhere from 10-30 times faster [in supported browsers] by
+ * using this approach.
+ *
+ * @returns `undefined`
+ * @private
+ */
+ var _watchForSwfFallbackContent = function() {
+ var maxWait = _globalConfig.flashLoadTimeout;
+ if (typeof maxWait === "number" && maxWait >= 0) {
+ var pollWait = Math.min(1e3, maxWait / 10);
+ var fallbackContentId = _globalConfig.swfObjectId + "_fallbackContent";
+ _swfFallbackCheckInterval = _setInterval(function() {
+ var el = _document.getElementById(fallbackContentId);
+ if (_isElementVisible(el)) {
+ _clearTimeoutsAndPolling();
+ _flashState.deactivated = null;
+ ZeroClipboard.emit({
+ type: "error",
+ name: "swf-not-found"
+ });
+ }
+ }, pollWait);
+ }
+ };
+ /**
+ * Create the HTML bridge element to embed the Flash object into.
+ * @private
+ */
+ var _createHtmlBridge = function() {
+ var container = _document.createElement("div");
+ container.id = _globalConfig.containerId;
+ container.className = _globalConfig.containerClass;
+ container.style.position = "absolute";
+ container.style.left = "0px";
+ container.style.top = "-9999px";
+ container.style.width = "1px";
+ container.style.height = "1px";
+ container.style.zIndex = "" + _getSafeZIndex(_globalConfig.zIndex);
+ return container;
+ };
+ /**
+ * Get the HTML element container that wraps the Flash bridge object/element.
+ * @private
+ */
+ var _getHtmlBridge = function(flashBridge) {
+ var htmlBridge = flashBridge && flashBridge.parentNode;
+ while (htmlBridge && htmlBridge.nodeName === "OBJECT" && htmlBridge.parentNode) {
+ htmlBridge = htmlBridge.parentNode;
+ }
+ return htmlBridge || null;
+ };
+ /**
+ * Create the SWF object.
+ *
+ * @returns The SWF object reference.
+ * @private
+ */
+ var _embedSwf = function() {
+ var len, flashBridge = _flashState.bridge, container = _getHtmlBridge(flashBridge);
+ if (!flashBridge) {
+ var allowScriptAccess = _determineScriptAccess(_window.location.host, _globalConfig);
+ var allowNetworking = allowScriptAccess === "never" ? "none" : "all";
+ var flashvars = _vars(_extend({
+ jsVersion: ZeroClipboard.version
+ }, _globalConfig));
+ var swfUrl = _globalConfig.swfPath + _cacheBust(_globalConfig.swfPath, _globalConfig);
+ container = _createHtmlBridge();
+ var divToBeReplaced = _document.createElement("div");
+ container.appendChild(divToBeReplaced);
+ _document.body.appendChild(container);
+ var tmpDiv = _document.createElement("div");
+ var usingActiveX = _flashState.pluginType === "activex";
+ tmpDiv.innerHTML = '<object id="' + _globalConfig.swfObjectId + '" name="' + _globalConfig.swfObjectId + '" ' + 'width="100%" height="100%" ' + (usingActiveX ? 'classid="clsid:d27cdb6e-ae6d-11cf-96b8-444553540000"' : 'type="application/x-shockwave-flash" data="' + swfUrl + '"') + ">" + (usingActiveX ? '<param name="movie" value="' + swfUrl + '"/>' : "") + '<param name="allowScriptAccess" value="' + allowScriptAccess + '"/>' + '<param name="allowNetworking" value="' + allowNetworking + '"/>' + '<param name="menu" value="false"/>' + '<param name="wmode" value="transparent"/>' + '<param name="flashvars" value="' + flashvars + '"/>' + '<div id="' + _globalConfig.swfObjectId + '_fallbackContent"> </div>' + "</object>";
+ flashBridge = tmpDiv.firstChild;
+ tmpDiv = null;
+ _unwrap(flashBridge).ZeroClipboard = ZeroClipboard;
+ container.replaceChild(flashBridge, divToBeReplaced);
+ _watchForSwfFallbackContent();
+ }
+ if (!flashBridge) {
+ flashBridge = _document[_globalConfig.swfObjectId];
+ if (flashBridge && (len = flashBridge.length)) {
+ flashBridge = flashBridge[len - 1];
+ }
+ if (!flashBridge && container) {
+ flashBridge = container.firstChild;
+ }
+ }
+ _flashState.bridge = flashBridge || null;
+ return flashBridge;
+ };
+ /**
+ * Destroy the SWF object.
+ * @private
+ */
+ var _unembedSwf = function() {
+ var flashBridge = _flashState.bridge;
+ if (flashBridge) {
+ var htmlBridge = _getHtmlBridge(flashBridge);
+ if (htmlBridge) {
+ if (_flashState.pluginType === "activex" && "readyState" in flashBridge) {
+ flashBridge.style.display = "none";
+ (function removeSwfFromIE() {
+ if (flashBridge.readyState === 4) {
+ for (var prop in flashBridge) {
+ if (typeof flashBridge[prop] === "function") {
+ flashBridge[prop] = null;
+ }
+ }
+ if (flashBridge.parentNode) {
+ flashBridge.parentNode.removeChild(flashBridge);
+ }
+ if (htmlBridge.parentNode) {
+ htmlBridge.parentNode.removeChild(htmlBridge);
+ }
+ } else {
+ _setTimeout(removeSwfFromIE, 10);
+ }
+ })();
+ } else {
+ if (flashBridge.parentNode) {
+ flashBridge.parentNode.removeChild(flashBridge);
+ }
+ if (htmlBridge.parentNode) {
+ htmlBridge.parentNode.removeChild(htmlBridge);
+ }
+ }
+ }
+ _clearTimeoutsAndPolling();
+ _flashState.ready = null;
+ _flashState.bridge = null;
+ _flashState.deactivated = null;
+ _zcSwfVersion = undefined;
+ }
+ };
+ /**
+ * Map the data format names of the "clipData" to Flash-friendly names.
+ *
+ * @returns A new transformed object.
+ * @private
+ */
+ var _mapClipDataToFlash = function(clipData) {
+ var newClipData = {}, formatMap = {};
+ if (!(typeof clipData === "object" && clipData)) {
+ return;
+ }
+ for (var dataFormat in clipData) {
+ if (dataFormat && _hasOwn.call(clipData, dataFormat) && typeof clipData[dataFormat] === "string" && clipData[dataFormat]) {
+ switch (dataFormat.toLowerCase()) {
+ case "text/plain":
+ case "text":
+ case "air:text":
+ case "flash:text":
+ newClipData.text = clipData[dataFormat];
+ formatMap.text = dataFormat;
+ break;
+
+ case "text/html":
+ case "html":
+ case "air:html":
+ case "flash:html":
+ newClipData.html = clipData[dataFormat];
+ formatMap.html = dataFormat;
+ break;
+
+ case "application/rtf":
+ case "text/rtf":
+ case "rtf":
+ case "richtext":
+ case "air:rtf":
+ case "flash:rtf":
+ newClipData.rtf = clipData[dataFormat];
+ formatMap.rtf = dataFormat;
+ break;
+
+ default:
+ break;
+ }
+ }
+ }
+ return {
+ data: newClipData,
+ formatMap: formatMap
+ };
+ };
+ /**
+ * Map the data format names from Flash-friendly names back to their original "clipData" names (via a format mapping).
+ *
+ * @returns A new transformed object.
+ * @private
+ */
+ var _mapClipResultsFromFlash = function(clipResults, formatMap) {
+ if (!(typeof clipResults === "object" && clipResults && typeof formatMap === "object" && formatMap)) {
+ return clipResults;
+ }
+ var newResults = {};
+ for (var prop in clipResults) {
+ if (_hasOwn.call(clipResults, prop)) {
+ if (prop === "errors") {
+ newResults[prop] = clipResults[prop] ? clipResults[prop].slice() : [];
+ for (var i = 0, len = newResults[prop].length; i < len; i++) {
+ newResults[prop][i].format = formatMap[newResults[prop][i].format];
+ }
+ } else if (prop !== "success" && prop !== "data") {
+ newResults[prop] = clipResults[prop];
+ } else {
+ newResults[prop] = {};
+ var tmpHash = clipResults[prop];
+ for (var dataFormat in tmpHash) {
+ if (dataFormat && _hasOwn.call(tmpHash, dataFormat) && _hasOwn.call(formatMap, dataFormat)) {
+ newResults[prop][formatMap[dataFormat]] = tmpHash[dataFormat];
+ }
+ }
+ }
+ }
+ }
+ return newResults;
+ };
+ /**
+ * Will look at a path, and will create a "?noCache={time}" or "&noCache={time}"
+ * query param string to return. Does NOT append that string to the original path.
+ * This is useful because ExternalInterface often breaks when a Flash SWF is cached.
+ *
+ * @returns The `noCache` query param with necessary "?"/"&" prefix.
+ * @private
+ */
+ var _cacheBust = function(path, options) {
+ var cacheBust = options == null || options && options.cacheBust === true;
+ if (cacheBust) {
+ return (path.indexOf("?") === -1 ? "?" : "&") + "noCache=" + _now();
+ } else {
+ return "";
+ }
+ };
+ /**
+ * Creates a query string for the FlashVars param.
+ * Does NOT include the cache-busting query param.
+ *
+ * @returns FlashVars query string
+ * @private
+ */
+ var _vars = function(options) {
+ var i, len, domain, domains, str = "", trustedOriginsExpanded = [];
+ if (options.trustedDomains) {
+ if (typeof options.trustedDomains === "string") {
+ domains = [ options.trustedDomains ];
+ } else if (typeof options.trustedDomains === "object" && "length" in options.trustedDomains) {
+ domains = options.trustedDomains;
+ }
+ }
+ if (domains && domains.length) {
+ for (i = 0, len = domains.length; i < len; i++) {
+ if (_hasOwn.call(domains, i) && domains[i] && typeof domains[i] === "string") {
+ domain = _extractDomain(domains[i]);
+ if (!domain) {
+ continue;
+ }
+ if (domain === "*") {
+ trustedOriginsExpanded.length = 0;
+ trustedOriginsExpanded.push(domain);
+ break;
+ }
+ trustedOriginsExpanded.push.apply(trustedOriginsExpanded, [ domain, "//" + domain, _window.location.protocol + "//" + domain ]);
+ }
+ }
+ }
+ if (trustedOriginsExpanded.length) {
+ str += "trustedOrigins=" + _encodeURIComponent(trustedOriginsExpanded.join(","));
+ }
+ if (options.forceEnhancedClipboard === true) {
+ str += (str ? "&" : "") + "forceEnhancedClipboard=true";
+ }
+ if (typeof options.swfObjectId === "string" && options.swfObjectId) {
+ str += (str ? "&" : "") + "swfObjectId=" + _encodeURIComponent(options.swfObjectId);
+ }
+ if (typeof options.jsVersion === "string" && options.jsVersion) {
+ str += (str ? "&" : "") + "jsVersion=" + _encodeURIComponent(options.jsVersion);
+ }
+ return str;
+ };
+ /**
+ * Extract the domain (e.g. "github.com") from an origin (e.g. "https://github.com") or
+ * URL (e.g. "https://github.com/zeroclipboard/zeroclipboard/").
+ *
+ * @returns the domain
+ * @private
+ */
+ var _extractDomain = function(originOrUrl) {
+ if (originOrUrl == null || originOrUrl === "") {
+ return null;
+ }
+ originOrUrl = originOrUrl.replace(/^\s+|\s+$/g, "");
+ if (originOrUrl === "") {
+ return null;
+ }
+ var protocolIndex = originOrUrl.indexOf("//");
+ originOrUrl = protocolIndex === -1 ? originOrUrl : originOrUrl.slice(protocolIndex + 2);
+ var pathIndex = originOrUrl.indexOf("/");
+ originOrUrl = pathIndex === -1 ? originOrUrl : protocolIndex === -1 || pathIndex === 0 ? null : originOrUrl.slice(0, pathIndex);
+ if (originOrUrl && originOrUrl.slice(-4).toLowerCase() === ".swf") {
+ return null;
+ }
+ return originOrUrl || null;
+ };
+ /**
+ * Set `allowScriptAccess` based on `trustedDomains` and `window.location.host` vs. `swfPath`.
+ *
+ * @returns The appropriate script access level.
+ * @private
+ */
+ var _determineScriptAccess = function() {
+ var _extractAllDomains = function(origins) {
+ var i, len, tmp, resultsArray = [];
+ if (typeof origins === "string") {
+ origins = [ origins ];
+ }
+ if (!(typeof origins === "object" && origins && typeof origins.length === "number")) {
+ return resultsArray;
+ }
+ for (i = 0, len = origins.length; i < len; i++) {
+ if (_hasOwn.call(origins, i) && (tmp = _extractDomain(origins[i]))) {
+ if (tmp === "*") {
+ resultsArray.length = 0;
+ resultsArray.push("*");
+ break;
+ }
+ if (resultsArray.indexOf(tmp) === -1) {
+ resultsArray.push(tmp);
+ }
+ }
+ }
+ return resultsArray;
+ };
+ return function(currentDomain, configOptions) {
+ var swfDomain = _extractDomain(configOptions.swfPath);
+ if (swfDomain === null) {
+ swfDomain = currentDomain;
+ }
+ var trustedDomains = _extractAllDomains(configOptions.trustedDomains);
+ var len = trustedDomains.length;
+ if (len > 0) {
+ if (len === 1 && trustedDomains[0] === "*") {
+ return "always";
+ }
+ if (trustedDomains.indexOf(currentDomain) !== -1) {
+ if (len === 1 && currentDomain === swfDomain) {
+ return "sameDomain";
+ }
+ return "always";
+ }
+ }
+ return "never";
+ };
+ }();
+ /**
+ * Get the currently active/focused DOM element.
+ *
+ * @returns the currently active/focused element, or `null`
+ * @private
+ */
+ var _safeActiveElement = function() {
+ try {
+ return _document.activeElement;
+ } catch (err) {
+ return null;
+ }
+ };
+ /**
+ * Add a class to an element, if it doesn't already have it.
+ *
+ * @returns The element, with its new class added.
+ * @private
+ */
+ var _addClass = function(element, value) {
+ var c, cl, className, classNames = [];
+ if (typeof value === "string" && value) {
+ classNames = value.split(/\s+/);
+ }
+ if (element && element.nodeType === 1 && classNames.length > 0) {
+ if (element.classList) {
+ for (c = 0, cl = classNames.length; c < cl; c++) {
+ element.classList.add(classNames[c]);
+ }
+ } else if (element.hasOwnProperty("className")) {
+ className = " " + element.className + " ";
+ for (c = 0, cl = classNames.length; c < cl; c++) {
+ if (className.indexOf(" " + classNames[c] + " ") === -1) {
+ className += classNames[c] + " ";
+ }
+ }
+ element.className = className.replace(/^\s+|\s+$/g, "");
+ }
+ }
+ return element;
+ };
+ /**
+ * Remove a class from an element, if it has it.
+ *
+ * @returns The element, with its class removed.
+ * @private
+ */
+ var _removeClass = function(element, value) {
+ var c, cl, className, classNames = [];
+ if (typeof value === "string" && value) {
+ classNames = value.split(/\s+/);
+ }
+ if (element && element.nodeType === 1 && classNames.length > 0) {
+ if (element.classList && element.classList.length > 0) {
+ for (c = 0, cl = classNames.length; c < cl; c++) {
+ element.classList.remove(classNames[c]);
+ }
+ } else if (element.className) {
+ className = (" " + element.className + " ").replace(/[\r\n\t]/g, " ");
+ for (c = 0, cl = classNames.length; c < cl; c++) {
+ className = className.replace(" " + classNames[c] + " ", " ");
+ }
+ element.className = className.replace(/^\s+|\s+$/g, "");
+ }
+ }
+ return element;
+ };
+ /**
+ * Attempt to interpret the element's CSS styling. If `prop` is `"cursor"`,
+ * then we assume that it should be a hand ("pointer") cursor if the element
+ * is an anchor element ("a" tag).
+ *
+ * @returns The computed style property.
+ * @private
+ */
+ var _getStyle = function(el, prop) {
+ var value = _getComputedStyle(el, null).getPropertyValue(prop);
+ if (prop === "cursor") {
+ if (!value || value === "auto") {
+ if (el.nodeName === "A") {
+ return "pointer";
+ }
+ }
+ }
+ return value;
+ };
+ /**
+ * Get the absolutely positioned coordinates of a DOM element.
+ *
+ * @returns Object containing the element's position, width, and height.
+ * @private
+ */
+ var _getElementPosition = function(el) {
+ var pos = {
+ left: 0,
+ top: 0,
+ width: 0,
+ height: 0
+ };
+ if (el.getBoundingClientRect) {
+ var elRect = el.getBoundingClientRect();
+ var pageXOffset = _window.pageXOffset;
+ var pageYOffset = _window.pageYOffset;
+ var leftBorderWidth = _document.documentElement.clientLeft || 0;
+ var topBorderWidth = _document.documentElement.clientTop || 0;
+ var leftBodyOffset = 0;
+ var topBodyOffset = 0;
+ if (_getStyle(_document.body, "position") === "relative") {
+ var bodyRect = _document.body.getBoundingClientRect();
+ var htmlRect = _document.documentElement.getBoundingClientRect();
+ leftBodyOffset = bodyRect.left - htmlRect.left || 0;
+ topBodyOffset = bodyRect.top - htmlRect.top || 0;
+ }
+ pos.left = elRect.left + pageXOffset - leftBorderWidth - leftBodyOffset;
+ pos.top = elRect.top + pageYOffset - topBorderWidth - topBodyOffset;
+ pos.width = "width" in elRect ? elRect.width : elRect.right - elRect.left;
+ pos.height = "height" in elRect ? elRect.height : elRect.bottom - elRect.top;
+ }
+ return pos;
+ };
+ /**
+ * Determine is an element is visible somewhere within the document (page).
+ *
+ * @returns Boolean
+ * @private
+ */
+ var _isElementVisible = function(el) {
+ if (!el) {
+ return false;
+ }
+ var styles = _getComputedStyle(el, null);
+ var hasCssHeight = _parseFloat(styles.height) > 0;
+ var hasCssWidth = _parseFloat(styles.width) > 0;
+ var hasCssTop = _parseFloat(styles.top) >= 0;
+ var hasCssLeft = _parseFloat(styles.left) >= 0;
+ var cssKnows = hasCssHeight && hasCssWidth && hasCssTop && hasCssLeft;
+ var rect = cssKnows ? null : _getElementPosition(el);
+ var isVisible = styles.display !== "none" && styles.visibility !== "collapse" && (cssKnows || !!rect && (hasCssHeight || rect.height > 0) && (hasCssWidth || rect.width > 0) && (hasCssTop || rect.top >= 0) && (hasCssLeft || rect.left >= 0));
+ return isVisible;
+ };
+ /**
+ * Clear all existing timeouts and interval polling delegates.
+ *
+ * @returns `undefined`
+ * @private
+ */
+ var _clearTimeoutsAndPolling = function() {
+ _clearTimeout(_flashCheckTimeout);
+ _flashCheckTimeout = 0;
+ _clearInterval(_swfFallbackCheckInterval);
+ _swfFallbackCheckInterval = 0;
+ };
+ /**
+ * Reposition the Flash object to cover the currently activated element.
+ *
+ * @returns `undefined`
+ * @private
+ */
+ var _reposition = function() {
+ var htmlBridge;
+ if (_currentElement && (htmlBridge = _getHtmlBridge(_flashState.bridge))) {
+ var pos = _getElementPosition(_currentElement);
+ _extend(htmlBridge.style, {
+ width: pos.width + "px",
+ height: pos.height + "px",
+ top: pos.top + "px",
+ left: pos.left + "px",
+ zIndex: "" + _getSafeZIndex(_globalConfig.zIndex)
+ });
+ }
+ };
+ /**
+ * Sends a signal to the Flash object to display the hand cursor if `true`.
+ *
+ * @returns `undefined`
+ * @private
+ */
+ var _setHandCursor = function(enabled) {
+ if (_flashState.ready === true) {
+ if (_flashState.bridge && typeof _flashState.bridge.setHandCursor === "function") {
+ _flashState.bridge.setHandCursor(enabled);
+ } else {
+ _flashState.ready = false;
+ }
+ }
+ };
+ /**
+ * Get a safe value for `zIndex`
+ *
+ * @returns an integer, or "auto"
+ * @private
+ */
+ var _getSafeZIndex = function(val) {
+ if (/^(?:auto|inherit)$/.test(val)) {
+ return val;
+ }
+ var zIndex;
+ if (typeof val === "number" && !_isNaN(val)) {
+ zIndex = val;
+ } else if (typeof val === "string") {
+ zIndex = _getSafeZIndex(_parseInt(val, 10));
+ }
+ return typeof zIndex === "number" ? zIndex : "auto";
+ };
+ /**
+ * Attempt to detect if ZeroClipboard is executing inside of a sandboxed iframe.
+ * If it is, Flash Player cannot be used, so ZeroClipboard is dead in the water.
+ *
+ * @see {@link http://lists.w3.org/Archives/Public/public-whatwg-archive/2014Dec/0002.html}
+ * @see {@link https://github.com/zeroclipboard/zeroclipboard/issues/511}
+ * @see {@link http://zeroclipboard.org/test-iframes.html}
+ *
+ * @returns `true` (is sandboxed), `false` (is not sandboxed), or `null` (uncertain)
+ * @private
+ */
+ var _detectSandbox = function(doNotReassessFlashSupport) {
+ var effectiveScriptOrigin, frame, frameError, previousState = _flashState.sandboxed, isSandboxed = null;
+ doNotReassessFlashSupport = doNotReassessFlashSupport === true;
+ if (_pageIsFramed === false) {
+ isSandboxed = false;
+ } else {
+ try {
+ frame = window.frameElement || null;
+ } catch (e) {
+ frameError = {
+ name: e.name,
+ message: e.message
+ };
+ }
+ if (frame && frame.nodeType === 1 && frame.nodeName === "IFRAME") {
+ try {
+ isSandboxed = frame.hasAttribute("sandbox");
+ } catch (e) {
+ isSandboxed = null;
+ }
+ } else {
+ try {
+ effectiveScriptOrigin = document.domain || null;
+ } catch (e) {
+ effectiveScriptOrigin = null;
+ }
+ if (effectiveScriptOrigin === null || frameError && frameError.name === "SecurityError" && /(^|[\s\(\[@])sandbox(es|ed|ing|[\s\.,!\)\]@]|$)/.test(frameError.message.toLowerCase())) {
+ isSandboxed = true;
+ }
+ }
+ }
+ _flashState.sandboxed = isSandboxed;
+ if (previousState !== isSandboxed && !doNotReassessFlashSupport) {
+ _detectFlashSupport(_ActiveXObject);
+ }
+ return isSandboxed;
+ };
+ /**
+ * Detect the Flash Player status, version, and plugin type.
+ *
+ * @see {@link https://code.google.com/p/doctype-mirror/wiki/ArticleDetectFlash#The_code}
+ * @see {@link http://stackoverflow.com/questions/12866060/detecting-pepper-ppapi-flash-with-javascript}
+ *
+ * @returns `undefined`
+ * @private
+ */
+ var _detectFlashSupport = function(ActiveXObject) {
+ var plugin, ax, mimeType, hasFlash = false, isActiveX = false, isPPAPI = false, flashVersion = "";
+ /**
+ * Derived from Apple's suggested sniffer.
+ * @param {String} desc e.g. "Shockwave Flash 7.0 r61"
+ * @returns {String} "7.0.61"
+ * @private
+ */
+ function parseFlashVersion(desc) {
+ var matches = desc.match(/[\d]+/g);
+ matches.length = 3;
+ return matches.join(".");
+ }
+ function isPepperFlash(flashPlayerFileName) {
+ return !!flashPlayerFileName && (flashPlayerFileName = flashPlayerFileName.toLowerCase()) && (/^(pepflashplayer\.dll|libpepflashplayer\.so|pepperflashplayer\.plugin)$/.test(flashPlayerFileName) || flashPlayerFileName.slice(-13) === "chrome.plugin");
+ }
+ function inspectPlugin(plugin) {
+ if (plugin) {
+ hasFlash = true;
+ if (plugin.version) {
+ flashVersion = parseFlashVersion(plugin.version);
+ }
+ if (!flashVersion && plugin.description) {
+ flashVersion = parseFlashVersion(plugin.description);
+ }
+ if (plugin.filename) {
+ isPPAPI = isPepperFlash(plugin.filename);
+ }
+ }
+ }
+ if (_navigator.plugins && _navigator.plugins.length) {
+ plugin = _navigator.plugins["Shockwave Flash"];
+ inspectPlugin(plugin);
+ if (_navigator.plugins["Shockwave Flash 2.0"]) {
+ hasFlash = true;
+ flashVersion = "2.0.0.11";
+ }
+ } else if (_navigator.mimeTypes && _navigator.mimeTypes.length) {
+ mimeType = _navigator.mimeTypes["application/x-shockwave-flash"];
+ plugin = mimeType && mimeType.enabledPlugin;
+ inspectPlugin(plugin);
+ } else if (typeof ActiveXObject !== "undefined") {
+ isActiveX = true;
+ try {
+ ax = new ActiveXObject("ShockwaveFlash.ShockwaveFlash.7");
+ hasFlash = true;
+ flashVersion = parseFlashVersion(ax.GetVariable("$version"));
+ } catch (e1) {
+ try {
+ ax = new ActiveXObject("ShockwaveFlash.ShockwaveFlash.6");
+ hasFlash = true;
+ flashVersion = "6.0.21";
+ } catch (e2) {
+ try {
+ ax = new ActiveXObject("ShockwaveFlash.ShockwaveFlash");
+ hasFlash = true;
+ flashVersion = parseFlashVersion(ax.GetVariable("$version"));
+ } catch (e3) {
+ isActiveX = false;
+ }
+ }
+ }
+ }
+ _flashState.disabled = hasFlash !== true;
+ _flashState.outdated = flashVersion && _parseFloat(flashVersion) < _parseFloat(_minimumFlashVersion);
+ _flashState.version = flashVersion || "0.0.0";
+ _flashState.pluginType = isPPAPI ? "pepper" : isActiveX ? "activex" : hasFlash ? "netscape" : "unknown";
+ };
+ /**
+ * Invoke the Flash detection algorithms immediately upon inclusion so we're not waiting later.
+ */
+ _detectFlashSupport(_ActiveXObject);
+ /**
+ * Always assess the `sandboxed` state of the page at important Flash-related moments.
+ */
+ _detectSandbox(true);
+ /**
+ * A shell constructor for `ZeroClipboard` client instances.
+ *
+ * @constructor
+ */
+ var ZeroClipboard = function() {
+ if (!(this instanceof ZeroClipboard)) {
+ return new ZeroClipboard();
+ }
+ if (typeof ZeroClipboard._createClient === "function") {
+ ZeroClipboard._createClient.apply(this, _args(arguments));
+ }
+ };
+ /**
+ * The ZeroClipboard library's version number.
+ *
+ * @static
+ * @readonly
+ * @property {string}
+ */
+ _defineProperty(ZeroClipboard, "version", {
+ value: "2.2.0",
+ writable: false,
+ configurable: true,
+ enumerable: true
+ });
+ /**
+ * Update or get a copy of the ZeroClipboard global configuration.
+ * Returns a copy of the current/updated configuration.
+ *
+ * @returns Object
+ * @static
+ */
+ ZeroClipboard.config = function() {
+ return _config.apply(this, _args(arguments));
+ };
+ /**
+ * Diagnostic method that describes the state of the browser, Flash Player, and ZeroClipboard.
+ *
+ * @returns Object
+ * @static
+ */
+ ZeroClipboard.state = function() {
+ return _state.apply(this, _args(arguments));
+ };
+ /**
+ * Check if Flash is unusable for any reason: disabled, outdated, deactivated, etc.
+ *
+ * @returns Boolean
+ * @static
+ */
+ ZeroClipboard.isFlashUnusable = function() {
+ return _isFlashUnusable.apply(this, _args(arguments));
+ };
+ /**
+ * Register an event listener.
+ *
+ * @returns `ZeroClipboard`
+ * @static
+ */
+ ZeroClipboard.on = function() {
+ return _on.apply(this, _args(arguments));
+ };
+ /**
+ * Unregister an event listener.
+ * If no `listener` function/object is provided, it will unregister all listeners for the provided `eventType`.
+ * If no `eventType` is provided, it will unregister all listeners for every event type.
+ *
+ * @returns `ZeroClipboard`
+ * @static
+ */
+ ZeroClipboard.off = function() {
+ return _off.apply(this, _args(arguments));
+ };
+ /**
+ * Retrieve event listeners for an `eventType`.
+ * If no `eventType` is provided, it will retrieve all listeners for every event type.
+ *
+ * @returns array of listeners for the `eventType`; if no `eventType`, then a map/hash object of listeners for all event types; or `null`
+ */
+ ZeroClipboard.handlers = function() {
+ return _listeners.apply(this, _args(arguments));
+ };
+ /**
+ * Event emission receiver from the Flash object, forwarding to any registered JavaScript event listeners.
+ *
+ * @returns For the "copy" event, returns the Flash-friendly "clipData" object; otherwise `undefined`.
+ * @static
+ */
+ ZeroClipboard.emit = function() {
+ return _emit.apply(this, _args(arguments));
+ };
+ /**
+ * Create and embed the Flash object.
+ *
+ * @returns The Flash object
+ * @static
+ */
+ ZeroClipboard.create = function() {
+ return _create.apply(this, _args(arguments));
+ };
+ /**
+ * Self-destruct and clean up everything, including the embedded Flash object.
+ *
+ * @returns `undefined`
+ * @static
+ */
+ ZeroClipboard.destroy = function() {
+ return _destroy.apply(this, _args(arguments));
+ };
+ /**
+ * Set the pending data for clipboard injection.
+ *
+ * @returns `undefined`
+ * @static
+ */
+ ZeroClipboard.setData = function() {
+ return _setData.apply(this, _args(arguments));
+ };
+ /**
+ * Clear the pending data for clipboard injection.
+ * If no `format` is provided, all pending data formats will be cleared.
+ *
+ * @returns `undefined`
+ * @static
+ */
+ ZeroClipboard.clearData = function() {
+ return _clearData.apply(this, _args(arguments));
+ };
+ /**
+ * Get a copy of the pending data for clipboard injection.
+ * If no `format` is provided, a copy of ALL pending data formats will be returned.
+ *
+ * @returns `String` or `Object`
+ * @static
+ */
+ ZeroClipboard.getData = function() {
+ return _getData.apply(this, _args(arguments));
+ };
+ /**
+ * Sets the current HTML object that the Flash object should overlay. This will put the global
+ * Flash object on top of the current element; depending on the setup, this may also set the
+ * pending clipboard text data as well as the Flash object's wrapping element's title attribute
+ * based on the underlying HTML element and ZeroClipboard configuration.
+ *
+ * @returns `undefined`
+ * @static
+ */
+ ZeroClipboard.focus = ZeroClipboard.activate = function() {
+ return _focus.apply(this, _args(arguments));
+ };
+ /**
+ * Un-overlays the Flash object. This will put the global Flash object off-screen; depending on
+ * the setup, this may also unset the Flash object's wrapping element's title attribute based on
+ * the underlying HTML element and ZeroClipboard configuration.
+ *
+ * @returns `undefined`
+ * @static
+ */
+ ZeroClipboard.blur = ZeroClipboard.deactivate = function() {
+ return _blur.apply(this, _args(arguments));
+ };
+ /**
+ * Returns the currently focused/"activated" HTML element that the Flash object is wrapping.
+ *
+ * @returns `HTMLElement` or `null`
+ * @static
+ */
+ ZeroClipboard.activeElement = function() {
+ return _activeElement.apply(this, _args(arguments));
+ };
+ /**
+ * Keep track of the ZeroClipboard client instance counter.
+ */
+ var _clientIdCounter = 0;
+ /**
+ * Keep track of the state of the client instances.
+ *
+ * Entry structure:
+ * _clientMeta[client.id] = {
+ * instance: client,
+ * elements: [],
+ * handlers: {}
+ * };
+ */
+ var _clientMeta = {};
+ /**
+ * Keep track of the ZeroClipboard clipped elements counter.
+ */
+ var _elementIdCounter = 0;
+ /**
+ * Keep track of the state of the clipped element relationships to clients.
+ *
+ * Entry structure:
+ * _elementMeta[element.zcClippingId] = [client1.id, client2.id];
+ */
+ var _elementMeta = {};
+ /**
+ * Keep track of the state of the mouse event handlers for clipped elements.
+ *
+ * Entry structure:
+ * _mouseHandlers[element.zcClippingId] = {
+ * mouseover: function(event) {},
+ * mouseout: function(event) {},
+ * mouseenter: function(event) {},
+ * mouseleave: function(event) {},
+ * mousemove: function(event) {}
+ * };
+ */
+ var _mouseHandlers = {};
+ /**
+ * Extending the ZeroClipboard configuration defaults for the Client module.
+ */
+ _extend(_globalConfig, {
+ autoActivate: true
+ });
+ /**
+ * The real constructor for `ZeroClipboard` client instances.
+ * @private
+ */
+ var _clientConstructor = function(elements) {
+ var client = this;
+ client.id = "" + _clientIdCounter++;
+ _clientMeta[client.id] = {
+ instance: client,
+ elements: [],
+ handlers: {}
+ };
+ if (elements) {
+ client.clip(elements);
+ }
+ ZeroClipboard.on("*", function(event) {
+ return client.emit(event);
+ });
+ ZeroClipboard.on("destroy", function() {
+ client.destroy();
+ });
+ ZeroClipboard.create();
+ };
+ /**
+ * The underlying implementation of `ZeroClipboard.Client.prototype.on`.
+ * @private
+ */
+ var _clientOn = function(eventType, listener) {
+ var i, len, events, added = {}, meta = _clientMeta[this.id], handlers = meta && meta.handlers;
+ if (!meta) {
+ throw new Error("Attempted to add new listener(s) to a destroyed ZeroClipboard client instance");
+ }
+ if (typeof eventType === "string" && eventType) {
+ events = eventType.toLowerCase().split(/\s+/);
+ } else if (typeof eventType === "object" && eventType && typeof listener === "undefined") {
+ for (i in eventType) {
+ if (_hasOwn.call(eventType, i) && typeof i === "string" && i && typeof eventType[i] === "function") {
+ this.on(i, eventType[i]);
+ }
+ }
+ }
+ if (events && events.length) {
+ for (i = 0, len = events.length; i < len; i++) {
+ eventType = events[i].replace(/^on/, "");
+ added[eventType] = true;
+ if (!handlers[eventType]) {
+ handlers[eventType] = [];
+ }
+ handlers[eventType].push(listener);
+ }
+ if (added.ready && _flashState.ready) {
+ this.emit({
+ type: "ready",
+ client: this
+ });
+ }
+ if (added.error) {
+ for (i = 0, len = _flashStateErrorNames.length; i < len; i++) {
+ if (_flashState[_flashStateErrorNames[i].replace(/^flash-/, "")]) {
+ this.emit({
+ type: "error",
+ name: _flashStateErrorNames[i],
+ client: this
+ });
+ break;
+ }
+ }
+ if (_zcSwfVersion !== undefined && ZeroClipboard.version !== _zcSwfVersion) {
+ this.emit({
+ type: "error",
+ name: "version-mismatch",
+ jsVersion: ZeroClipboard.version,
+ swfVersion: _zcSwfVersion
+ });
+ }
+ }
+ }
+ return this;
+ };
+ /**
+ * The underlying implementation of `ZeroClipboard.Client.prototype.off`.
+ * @private
+ */
+ var _clientOff = function(eventType, listener) {
+ var i, len, foundIndex, events, perEventHandlers, meta = _clientMeta[this.id], handlers = meta && meta.handlers;
+ if (!handlers) {
+ return this;
+ }
+ if (arguments.length === 0) {
+ events = _keys(handlers);
+ } else if (typeof eventType === "string" && eventType) {
+ events = eventType.split(/\s+/);
+ } else if (typeof eventType === "object" && eventType && typeof listener === "undefined") {
+ for (i in eventType) {
+ if (_hasOwn.call(eventType, i) && typeof i === "string" && i && typeof eventType[i] === "function") {
+ this.off(i, eventType[i]);
+ }
+ }
+ }
+ if (events && events.length) {
+ for (i = 0, len = events.length; i < len; i++) {
+ eventType = events[i].toLowerCase().replace(/^on/, "");
+ perEventHandlers = handlers[eventType];
+ if (perEventHandlers && perEventHandlers.length) {
+ if (listener) {
+ foundIndex = perEventHandlers.indexOf(listener);
+ while (foundIndex !== -1) {
+ perEventHandlers.splice(foundIndex, 1);
+ foundIndex = perEventHandlers.indexOf(listener, foundIndex);
+ }
+ } else {
+ perEventHandlers.length = 0;
+ }
+ }
+ }
+ }
+ return this;
+ };
+ /**
+ * The underlying implementation of `ZeroClipboard.Client.prototype.handlers`.
+ * @private
+ */
+ var _clientListeners = function(eventType) {
+ var copy = null, handlers = _clientMeta[this.id] && _clientMeta[this.id].handlers;
+ if (handlers) {
+ if (typeof eventType === "string" && eventType) {
+ copy = handlers[eventType] ? handlers[eventType].slice(0) : [];
+ } else {
+ copy = _deepCopy(handlers);
+ }
+ }
+ return copy;
+ };
+ /**
+ * The underlying implementation of `ZeroClipboard.Client.prototype.emit`.
+ * @private
+ */
+ var _clientEmit = function(event) {
+ if (_clientShouldEmit.call(this, event)) {
+ if (typeof event === "object" && event && typeof event.type === "string" && event.type) {
+ event = _extend({}, event);
+ }
+ var eventCopy = _extend({}, _createEvent(event), {
+ client: this
+ });
+ _clientDispatchCallbacks.call(this, eventCopy);
+ }
+ return this;
+ };
+ /**
+ * The underlying implementation of `ZeroClipboard.Client.prototype.clip`.
+ * @private
+ */
+ var _clientClip = function(elements) {
+ if (!_clientMeta[this.id]) {
+ throw new Error("Attempted to clip element(s) to a destroyed ZeroClipboard client instance");
+ }
+ elements = _prepClip(elements);
+ for (var i = 0; i < elements.length; i++) {
+ if (_hasOwn.call(elements, i) && elements[i] && elements[i].nodeType === 1) {
+ if (!elements[i].zcClippingId) {
+ elements[i].zcClippingId = "zcClippingId_" + _elementIdCounter++;
+ _elementMeta[elements[i].zcClippingId] = [ this.id ];
+ if (_globalConfig.autoActivate === true) {
+ _addMouseHandlers(elements[i]);
+ }
+ } else if (_elementMeta[elements[i].zcClippingId].indexOf(this.id) === -1) {
+ _elementMeta[elements[i].zcClippingId].push(this.id);
+ }
+ var clippedElements = _clientMeta[this.id] && _clientMeta[this.id].elements;
+ if (clippedElements.indexOf(elements[i]) === -1) {
+ clippedElements.push(elements[i]);
+ }
+ }
+ }
+ return this;
+ };
+ /**
+ * The underlying implementation of `ZeroClipboard.Client.prototype.unclip`.
+ * @private
+ */
+ var _clientUnclip = function(elements) {
+ var meta = _clientMeta[this.id];
+ if (!meta) {
+ return this;
+ }
+ var clippedElements = meta.elements;
+ var arrayIndex;
+ if (typeof elements === "undefined") {
+ elements = clippedElements.slice(0);
+ } else {
+ elements = _prepClip(elements);
+ }
+ for (var i = elements.length; i--; ) {
+ if (_hasOwn.call(elements, i) && elements[i] && elements[i].nodeType === 1) {
+ arrayIndex = 0;
+ while ((arrayIndex = clippedElements.indexOf(elements[i], arrayIndex)) !== -1) {
+ clippedElements.splice(arrayIndex, 1);
+ }
+ var clientIds = _elementMeta[elements[i].zcClippingId];
+ if (clientIds) {
+ arrayIndex = 0;
+ while ((arrayIndex = clientIds.indexOf(this.id, arrayIndex)) !== -1) {
+ clientIds.splice(arrayIndex, 1);
+ }
+ if (clientIds.length === 0) {
+ if (_globalConfig.autoActivate === true) {
+ _removeMouseHandlers(elements[i]);
+ }
+ delete elements[i].zcClippingId;
+ }
+ }
+ }
+ }
+ return this;
+ };
+ /**
+ * The underlying implementation of `ZeroClipboard.Client.prototype.elements`.
+ * @private
+ */
+ var _clientElements = function() {
+ var meta = _clientMeta[this.id];
+ return meta && meta.elements ? meta.elements.slice(0) : [];
+ };
+ /**
+ * The underlying implementation of `ZeroClipboard.Client.prototype.destroy`.
+ * @private
+ */
+ var _clientDestroy = function() {
+ if (!_clientMeta[this.id]) {
+ return;
+ }
+ this.unclip();
+ this.off();
+ delete _clientMeta[this.id];
+ };
+ /**
+ * Inspect an Event to see if the Client (`this`) should honor it for emission.
+ * @private
+ */
+ var _clientShouldEmit = function(event) {
+ if (!(event && event.type)) {
+ return false;
+ }
+ if (event.client && event.client !== this) {
+ return false;
+ }
+ var meta = _clientMeta[this.id];
+ var clippedEls = meta && meta.elements;
+ var hasClippedEls = !!clippedEls && clippedEls.length > 0;
+ var goodTarget = !event.target || hasClippedEls && clippedEls.indexOf(event.target) !== -1;
+ var goodRelTarget = event.relatedTarget && hasClippedEls && clippedEls.indexOf(event.relatedTarget) !== -1;
+ var goodClient = event.client && event.client === this;
+ if (!meta || !(goodTarget || goodRelTarget || goodClient)) {
+ return false;
+ }
+ return true;
+ };
+ /**
+ * Handle the actual dispatching of events to a client instance.
+ *
+ * @returns `undefined`
+ * @private
+ */
+ var _clientDispatchCallbacks = function(event) {
+ var meta = _clientMeta[this.id];
+ if (!(typeof event === "object" && event && event.type && meta)) {
+ return;
+ }
+ var async = _shouldPerformAsync(event);
+ var wildcardTypeHandlers = meta && meta.handlers["*"] || [];
+ var specificTypeHandlers = meta && meta.handlers[event.type] || [];
+ var handlers = wildcardTypeHandlers.concat(specificTypeHandlers);
+ if (handlers && handlers.length) {
+ var i, len, func, context, eventCopy, originalContext = this;
+ for (i = 0, len = handlers.length; i < len; i++) {
+ func = handlers[i];
+ context = originalContext;
+ if (typeof func === "string" && typeof _window[func] === "function") {
+ func = _window[func];
+ }
+ if (typeof func === "object" && func && typeof func.handleEvent === "function") {
+ context = func;
+ func = func.handleEvent;
+ }
+ if (typeof func === "function") {
+ eventCopy = _extend({}, event);
+ _dispatchCallback(func, context, [ eventCopy ], async);
+ }
+ }
+ }
+ };
+ /**
+ * Prepares the elements for clipping/unclipping.
+ *
+ * @returns An Array of elements.
+ * @private
+ */
+ var _prepClip = function(elements) {
+ if (typeof elements === "string") {
+ elements = [];
+ }
+ return typeof elements.length !== "number" ? [ elements ] : elements;
+ };
+ /**
+ * Add a `mouseover` handler function for a clipped element.
+ *
+ * @returns `undefined`
+ * @private
+ */
+ var _addMouseHandlers = function(element) {
+ if (!(element && element.nodeType === 1)) {
+ return;
+ }
+ var _suppressMouseEvents = function(event) {
+ if (!(event || (event = _window.event))) {
+ return;
+ }
+ if (event._source !== "js") {
+ event.stopImmediatePropagation();
+ event.preventDefault();
+ }
+ delete event._source;
+ };
+ var _elementMouseOver = function(event) {
+ if (!(event || (event = _window.event))) {
+ return;
+ }
+ _suppressMouseEvents(event);
+ ZeroClipboard.focus(element);
+ };
+ element.addEventListener("mouseover", _elementMouseOver, false);
+ element.addEventListener("mouseout", _suppressMouseEvents, false);
+ element.addEventListener("mouseenter", _suppressMouseEvents, false);
+ element.addEventListener("mouseleave", _suppressMouseEvents, false);
+ element.addEventListener("mousemove", _suppressMouseEvents, false);
+ _mouseHandlers[element.zcClippingId] = {
+ mouseover: _elementMouseOver,
+ mouseout: _suppressMouseEvents,
+ mouseenter: _suppressMouseEvents,
+ mouseleave: _suppressMouseEvents,
+ mousemove: _suppressMouseEvents
+ };
+ };
+ /**
+ * Remove a `mouseover` handler function for a clipped element.
+ *
+ * @returns `undefined`
+ * @private
+ */
+ var _removeMouseHandlers = function(element) {
+ if (!(element && element.nodeType === 1)) {
+ return;
+ }
+ var mouseHandlers = _mouseHandlers[element.zcClippingId];
+ if (!(typeof mouseHandlers === "object" && mouseHandlers)) {
+ return;
+ }
+ var key, val, mouseEvents = [ "move", "leave", "enter", "out", "over" ];
+ for (var i = 0, len = mouseEvents.length; i < len; i++) {
+ key = "mouse" + mouseEvents[i];
+ val = mouseHandlers[key];
+ if (typeof val === "function") {
+ element.removeEventListener(key, val, false);
+ }
+ }
+ delete _mouseHandlers[element.zcClippingId];
+ };
+ /**
+ * Creates a new ZeroClipboard client instance.
+ * Optionally, auto-`clip` an element or collection of elements.
+ *
+ * @constructor
+ */
+ ZeroClipboard._createClient = function() {
+ _clientConstructor.apply(this, _args(arguments));
+ };
+ /**
+ * Register an event listener to the client.
+ *
+ * @returns `this`
+ */
+ ZeroClipboard.prototype.on = function() {
+ return _clientOn.apply(this, _args(arguments));
+ };
+ /**
+ * Unregister an event handler from the client.
+ * If no `listener` function/object is provided, it will unregister all handlers for the provided `eventType`.
+ * If no `eventType` is provided, it will unregister all handlers for every event type.
+ *
+ * @returns `this`
+ */
+ ZeroClipboard.prototype.off = function() {
+ return _clientOff.apply(this, _args(arguments));
+ };
+ /**
+ * Retrieve event listeners for an `eventType` from the client.
+ * If no `eventType` is provided, it will retrieve all listeners for every event type.
+ *
+ * @returns array of listeners for the `eventType`; if no `eventType`, then a map/hash object of listeners for all event types; or `null`
+ */
+ ZeroClipboard.prototype.handlers = function() {
+ return _clientListeners.apply(this, _args(arguments));
+ };
+ /**
+ * Event emission receiver from the Flash object for this client's registered JavaScript event listeners.
+ *
+ * @returns For the "copy" event, returns the Flash-friendly "clipData" object; otherwise `undefined`.
+ */
+ ZeroClipboard.prototype.emit = function() {
+ return _clientEmit.apply(this, _args(arguments));
+ };
+ /**
+ * Register clipboard actions for new element(s) to the client.
+ *
+ * @returns `this`
+ */
+ ZeroClipboard.prototype.clip = function() {
+ return _clientClip.apply(this, _args(arguments));
+ };
+ /**
+ * Unregister the clipboard actions of previously registered element(s) on the page.
+ * If no elements are provided, ALL registered elements will be unregistered.
+ *
+ * @returns `this`
+ */
+ ZeroClipboard.prototype.unclip = function() {
+ return _clientUnclip.apply(this, _args(arguments));
+ };
+ /**
+ * Get all of the elements to which this client is clipped.
+ *
+ * @returns array of clipped elements
+ */
+ ZeroClipboard.prototype.elements = function() {
+ return _clientElements.apply(this, _args(arguments));
+ };
+ /**
+ * Self-destruct and clean up everything for a single client.
+ * This will NOT destroy the embedded Flash object.
+ *
+ * @returns `undefined`
+ */
+ ZeroClipboard.prototype.destroy = function() {
+ return _clientDestroy.apply(this, _args(arguments));
+ };
+ /**
+ * Stores the pending plain text to inject into the clipboard.
+ *
+ * @returns `this`
+ */
+ ZeroClipboard.prototype.setText = function(text) {
+ if (!_clientMeta[this.id]) {
+ throw new Error("Attempted to set pending clipboard data from a destroyed ZeroClipboard client instance");
+ }
+ ZeroClipboard.setData("text/plain", text);
+ return this;
+ };
+ /**
+ * Stores the pending HTML text to inject into the clipboard.
+ *
+ * @returns `this`
+ */
+ ZeroClipboard.prototype.setHtml = function(html) {
+ if (!_clientMeta[this.id]) {
+ throw new Error("Attempted to set pending clipboard data from a destroyed ZeroClipboard client instance");
+ }
+ ZeroClipboard.setData("text/html", html);
+ return this;
+ };
+ /**
+ * Stores the pending rich text (RTF) to inject into the clipboard.
+ *
+ * @returns `this`
+ */
+ ZeroClipboard.prototype.setRichText = function(richText) {
+ if (!_clientMeta[this.id]) {
+ throw new Error("Attempted to set pending clipboard data from a destroyed ZeroClipboard client instance");
+ }
+ ZeroClipboard.setData("application/rtf", richText);
+ return this;
+ };
+ /**
+ * Stores the pending data to inject into the clipboard.
+ *
+ * @returns `this`
+ */
+ ZeroClipboard.prototype.setData = function() {
+ if (!_clientMeta[this.id]) {
+ throw new Error("Attempted to set pending clipboard data from a destroyed ZeroClipboard client instance");
+ }
+ ZeroClipboard.setData.apply(this, _args(arguments));
+ return this;
+ };
+ /**
+ * Clears the pending data to inject into the clipboard.
+ * If no `format` is provided, all pending data formats will be cleared.
+ *
+ * @returns `this`
+ */
+ ZeroClipboard.prototype.clearData = function() {
+ if (!_clientMeta[this.id]) {
+ throw new Error("Attempted to clear pending clipboard data from a destroyed ZeroClipboard client instance");
+ }
+ ZeroClipboard.clearData.apply(this, _args(arguments));
+ return this;
+ };
+ /**
+ * Gets a copy of the pending data to inject into the clipboard.
+ * If no `format` is provided, a copy of ALL pending data formats will be returned.
+ *
+ * @returns `String` or `Object`
+ */
+ ZeroClipboard.prototype.getData = function() {
+ if (!_clientMeta[this.id]) {
+ throw new Error("Attempted to get pending clipboard data from a destroyed ZeroClipboard client instance");
+ }
+ return ZeroClipboard.getData.apply(this, _args(arguments));
+ };
+ if (typeof define === "function" && define.amd) {
+ define(function() {
+ return ZeroClipboard;
+ });
+ } else if (typeof module === "object" && module && typeof module.exports === "object" && module.exports) {
+ module.exports = ZeroClipboard;
+ } else {
+ window.ZeroClipboard = ZeroClipboard;
+ }
+})(function() {
+ return this || window;
+}());
\ No newline at end of file
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/src/ldt/ldt/static/ldt/js/backbone-min.js Fri Oct 02 10:24:05 2015 +0200
@@ -0,0 +1,2 @@
+(function(t){var e=typeof self=="object"&&self.self==self&&self||typeof global=="object"&&global.global==global&&global;if(typeof define==="function"&&define.amd){define(["underscore","jquery","exports"],function(i,r,n){e.Backbone=t(e,n,i,r)})}else if(typeof exports!=="undefined"){var i=require("underscore"),r;try{r=require("jquery")}catch(n){}t(e,exports,i,r)}else{e.Backbone=t(e,{},e._,e.jQuery||e.Zepto||e.ender||e.$)}})(function(t,e,i,r){var n=t.Backbone;var s=Array.prototype.slice;e.VERSION="1.2.3";e.$=r;e.noConflict=function(){t.Backbone=n;return this};e.emulateHTTP=false;e.emulateJSON=false;var a=function(t,e,r){switch(t){case 1:return function(){return i[e](this[r])};case 2:return function(t){return i[e](this[r],t)};case 3:return function(t,n){return i[e](this[r],h(t,this),n)};case 4:return function(t,n,s){return i[e](this[r],h(t,this),n,s)};default:return function(){var t=s.call(arguments);t.unshift(this[r]);return i[e].apply(i,t)}}};var o=function(t,e,r){i.each(e,function(e,n){if(i[n])t.prototype[n]=a(e,n,r)})};var h=function(t,e){if(i.isFunction(t))return t;if(i.isObject(t)&&!e._isModel(t))return u(t);if(i.isString(t))return function(e){return e.get(t)};return t};var u=function(t){var e=i.matches(t);return function(t){return e(t.attributes)}};var l=e.Events={};var c=/\s+/;var f=function(t,e,r,n,s){var a=0,o;if(r&&typeof r==="object"){if(n!==void 0&&"context"in s&&s.context===void 0)s.context=n;for(o=i.keys(r);a<o.length;a++){e=f(t,e,o[a],r[o[a]],s)}}else if(r&&c.test(r)){for(o=r.split(c);a<o.length;a++){e=t(e,o[a],n,s)}}else{e=t(e,r,n,s)}return e};l.on=function(t,e,i){return d(this,t,e,i)};var d=function(t,e,i,r,n){t._events=f(v,t._events||{},e,i,{context:r,ctx:t,listening:n});if(n){var s=t._listeners||(t._listeners={});s[n.id]=n}return t};l.listenTo=function(t,e,r){if(!t)return this;var n=t._listenId||(t._listenId=i.uniqueId("l"));var s=this._listeningTo||(this._listeningTo={});var a=s[n];if(!a){var o=this._listenId||(this._listenId=i.uniqueId("l"));a=s[n]={obj:t,objId:n,id:o,listeningTo:s,count:0}}d(t,e,r,this,a);return this};var v=function(t,e,i,r){if(i){var n=t[e]||(t[e]=[]);var s=r.context,a=r.ctx,o=r.listening;if(o)o.count++;n.push({callback:i,context:s,ctx:s||a,listening:o})}return t};l.off=function(t,e,i){if(!this._events)return this;this._events=f(g,this._events,t,e,{context:i,listeners:this._listeners});return this};l.stopListening=function(t,e,r){var n=this._listeningTo;if(!n)return this;var s=t?[t._listenId]:i.keys(n);for(var a=0;a<s.length;a++){var o=n[s[a]];if(!o)break;o.obj.off(e,r,this)}if(i.isEmpty(n))this._listeningTo=void 0;return this};var g=function(t,e,r,n){if(!t)return;var s=0,a;var o=n.context,h=n.listeners;if(!e&&!r&&!o){var u=i.keys(h);for(;s<u.length;s++){a=h[u[s]];delete h[a.id];delete a.listeningTo[a.objId]}return}var l=e?[e]:i.keys(t);for(;s<l.length;s++){e=l[s];var c=t[e];if(!c)break;var f=[];for(var d=0;d<c.length;d++){var v=c[d];if(r&&r!==v.callback&&r!==v.callback._callback||o&&o!==v.context){f.push(v)}else{a=v.listening;if(a&&--a.count===0){delete h[a.id];delete a.listeningTo[a.objId]}}}if(f.length){t[e]=f}else{delete t[e]}}if(i.size(t))return t};l.once=function(t,e,r){var n=f(p,{},t,e,i.bind(this.off,this));return this.on(n,void 0,r)};l.listenToOnce=function(t,e,r){var n=f(p,{},e,r,i.bind(this.stopListening,this,t));return this.listenTo(t,n)};var p=function(t,e,r,n){if(r){var s=t[e]=i.once(function(){n(e,s);r.apply(this,arguments)});s._callback=r}return t};l.trigger=function(t){if(!this._events)return this;var e=Math.max(0,arguments.length-1);var i=Array(e);for(var r=0;r<e;r++)i[r]=arguments[r+1];f(m,this._events,t,void 0,i);return this};var m=function(t,e,i,r){if(t){var n=t[e];var s=t.all;if(n&&s)s=s.slice();if(n)_(n,r);if(s)_(s,[e].concat(r))}return t};var _=function(t,e){var i,r=-1,n=t.length,s=e[0],a=e[1],o=e[2];switch(e.length){case 0:while(++r<n)(i=t[r]).callback.call(i.ctx);return;case 1:while(++r<n)(i=t[r]).callback.call(i.ctx,s);return;case 2:while(++r<n)(i=t[r]).callback.call(i.ctx,s,a);return;case 3:while(++r<n)(i=t[r]).callback.call(i.ctx,s,a,o);return;default:while(++r<n)(i=t[r]).callback.apply(i.ctx,e);return}};l.bind=l.on;l.unbind=l.off;i.extend(e,l);var y=e.Model=function(t,e){var r=t||{};e||(e={});this.cid=i.uniqueId(this.cidPrefix);this.attributes={};if(e.collection)this.collection=e.collection;if(e.parse)r=this.parse(r,e)||{};r=i.defaults({},r,i.result(this,"defaults"));this.set(r,e);this.changed={};this.initialize.apply(this,arguments)};i.extend(y.prototype,l,{changed:null,validationError:null,idAttribute:"id",cidPrefix:"c",initialize:function(){},toJSON:function(t){return i.clone(this.attributes)},sync:function(){return e.sync.apply(this,arguments)},get:function(t){return this.attributes[t]},escape:function(t){return i.escape(this.get(t))},has:function(t){return this.get(t)!=null},matches:function(t){return!!i.iteratee(t,this)(this.attributes)},set:function(t,e,r){if(t==null)return this;var n;if(typeof t==="object"){n=t;r=e}else{(n={})[t]=e}r||(r={});if(!this._validate(n,r))return false;var s=r.unset;var a=r.silent;var o=[];var h=this._changing;this._changing=true;if(!h){this._previousAttributes=i.clone(this.attributes);this.changed={}}var u=this.attributes;var l=this.changed;var c=this._previousAttributes;for(var f in n){e=n[f];if(!i.isEqual(u[f],e))o.push(f);if(!i.isEqual(c[f],e)){l[f]=e}else{delete l[f]}s?delete u[f]:u[f]=e}this.id=this.get(this.idAttribute);if(!a){if(o.length)this._pending=r;for(var d=0;d<o.length;d++){this.trigger("change:"+o[d],this,u[o[d]],r)}}if(h)return this;if(!a){while(this._pending){r=this._pending;this._pending=false;this.trigger("change",this,r)}}this._pending=false;this._changing=false;return this},unset:function(t,e){return this.set(t,void 0,i.extend({},e,{unset:true}))},clear:function(t){var e={};for(var r in this.attributes)e[r]=void 0;return this.set(e,i.extend({},t,{unset:true}))},hasChanged:function(t){if(t==null)return!i.isEmpty(this.changed);return i.has(this.changed,t)},changedAttributes:function(t){if(!t)return this.hasChanged()?i.clone(this.changed):false;var e=this._changing?this._previousAttributes:this.attributes;var r={};for(var n in t){var s=t[n];if(i.isEqual(e[n],s))continue;r[n]=s}return i.size(r)?r:false},previous:function(t){if(t==null||!this._previousAttributes)return null;return this._previousAttributes[t]},previousAttributes:function(){return i.clone(this._previousAttributes)},fetch:function(t){t=i.extend({parse:true},t);var e=this;var r=t.success;t.success=function(i){var n=t.parse?e.parse(i,t):i;if(!e.set(n,t))return false;if(r)r.call(t.context,e,i,t);e.trigger("sync",e,i,t)};z(this,t);return this.sync("read",this,t)},save:function(t,e,r){var n;if(t==null||typeof t==="object"){n=t;r=e}else{(n={})[t]=e}r=i.extend({validate:true,parse:true},r);var s=r.wait;if(n&&!s){if(!this.set(n,r))return false}else{if(!this._validate(n,r))return false}var a=this;var o=r.success;var h=this.attributes;r.success=function(t){a.attributes=h;var e=r.parse?a.parse(t,r):t;if(s)e=i.extend({},n,e);if(e&&!a.set(e,r))return false;if(o)o.call(r.context,a,t,r);a.trigger("sync",a,t,r)};z(this,r);if(n&&s)this.attributes=i.extend({},h,n);var u=this.isNew()?"create":r.patch?"patch":"update";if(u==="patch"&&!r.attrs)r.attrs=n;var l=this.sync(u,this,r);this.attributes=h;return l},destroy:function(t){t=t?i.clone(t):{};var e=this;var r=t.success;var n=t.wait;var s=function(){e.stopListening();e.trigger("destroy",e,e.collection,t)};t.success=function(i){if(n)s();if(r)r.call(t.context,e,i,t);if(!e.isNew())e.trigger("sync",e,i,t)};var a=false;if(this.isNew()){i.defer(t.success)}else{z(this,t);a=this.sync("delete",this,t)}if(!n)s();return a},url:function(){var t=i.result(this,"urlRoot")||i.result(this.collection,"url")||F();if(this.isNew())return t;var e=this.get(this.idAttribute);return t.replace(/[^\/]$/,"$&/")+encodeURIComponent(e)},parse:function(t,e){return t},clone:function(){return new this.constructor(this.attributes)},isNew:function(){return!this.has(this.idAttribute)},isValid:function(t){return this._validate({},i.defaults({validate:true},t))},_validate:function(t,e){if(!e.validate||!this.validate)return true;t=i.extend({},this.attributes,t);var r=this.validationError=this.validate(t,e)||null;if(!r)return true;this.trigger("invalid",this,r,i.extend(e,{validationError:r}));return false}});var b={keys:1,values:1,pairs:1,invert:1,pick:0,omit:0,chain:1,isEmpty:1};o(y,b,"attributes");var x=e.Collection=function(t,e){e||(e={});if(e.model)this.model=e.model;if(e.comparator!==void 0)this.comparator=e.comparator;this._reset();this.initialize.apply(this,arguments);if(t)this.reset(t,i.extend({silent:true},e))};var w={add:true,remove:true,merge:true};var E={add:true,remove:false};var k=function(t,e,i){i=Math.min(Math.max(i,0),t.length);var r=Array(t.length-i);var n=e.length;for(var s=0;s<r.length;s++)r[s]=t[s+i];for(s=0;s<n;s++)t[s+i]=e[s];for(s=0;s<r.length;s++)t[s+n+i]=r[s]};i.extend(x.prototype,l,{model:y,initialize:function(){},toJSON:function(t){return this.map(function(e){return e.toJSON(t)})},sync:function(){return e.sync.apply(this,arguments)},add:function(t,e){return this.set(t,i.extend({merge:false},e,E))},remove:function(t,e){e=i.extend({},e);var r=!i.isArray(t);t=r?[t]:i.clone(t);var n=this._removeModels(t,e);if(!e.silent&&n)this.trigger("update",this,e);return r?n[0]:n},set:function(t,e){if(t==null)return;e=i.defaults({},e,w);if(e.parse&&!this._isModel(t))t=this.parse(t,e);var r=!i.isArray(t);t=r?[t]:t.slice();var n=e.at;if(n!=null)n=+n;if(n<0)n+=this.length+1;var s=[];var a=[];var o=[];var h={};var u=e.add;var l=e.merge;var c=e.remove;var f=false;var d=this.comparator&&n==null&&e.sort!==false;var v=i.isString(this.comparator)?this.comparator:null;var g;for(var p=0;p<t.length;p++){g=t[p];var m=this.get(g);if(m){if(l&&g!==m){var _=this._isModel(g)?g.attributes:g;if(e.parse)_=m.parse(_,e);m.set(_,e);if(d&&!f)f=m.hasChanged(v)}if(!h[m.cid]){h[m.cid]=true;s.push(m)}t[p]=m}else if(u){g=t[p]=this._prepareModel(g,e);if(g){a.push(g);this._addReference(g,e);h[g.cid]=true;s.push(g)}}}if(c){for(p=0;p<this.length;p++){g=this.models[p];if(!h[g.cid])o.push(g)}if(o.length)this._removeModels(o,e)}var y=false;var b=!d&&u&&c;if(s.length&&b){y=this.length!=s.length||i.some(this.models,function(t,e){return t!==s[e]});this.models.length=0;k(this.models,s,0);this.length=this.models.length}else if(a.length){if(d)f=true;k(this.models,a,n==null?this.length:n);this.length=this.models.length}if(f)this.sort({silent:true});if(!e.silent){for(p=0;p<a.length;p++){if(n!=null)e.index=n+p;g=a[p];g.trigger("add",g,this,e)}if(f||y)this.trigger("sort",this,e);if(a.length||o.length)this.trigger("update",this,e)}return r?t[0]:t},reset:function(t,e){e=e?i.clone(e):{};for(var r=0;r<this.models.length;r++){this._removeReference(this.models[r],e)}e.previousModels=this.models;this._reset();t=this.add(t,i.extend({silent:true},e));if(!e.silent)this.trigger("reset",this,e);return t},push:function(t,e){return this.add(t,i.extend({at:this.length},e))},pop:function(t){var e=this.at(this.length-1);return this.remove(e,t)},unshift:function(t,e){return this.add(t,i.extend({at:0},e))},shift:function(t){var e=this.at(0);return this.remove(e,t)},slice:function(){return s.apply(this.models,arguments)},get:function(t){if(t==null)return void 0;var e=this.modelId(this._isModel(t)?t.attributes:t);return this._byId[t]||this._byId[e]||this._byId[t.cid]},at:function(t){if(t<0)t+=this.length;return this.models[t]},where:function(t,e){return this[e?"find":"filter"](t)},findWhere:function(t){return this.where(t,true)},sort:function(t){var e=this.comparator;if(!e)throw new Error("Cannot sort a set without a comparator");t||(t={});var r=e.length;if(i.isFunction(e))e=i.bind(e,this);if(r===1||i.isString(e)){this.models=this.sortBy(e)}else{this.models.sort(e)}if(!t.silent)this.trigger("sort",this,t);return this},pluck:function(t){return i.invoke(this.models,"get",t)},fetch:function(t){t=i.extend({parse:true},t);var e=t.success;var r=this;t.success=function(i){var n=t.reset?"reset":"set";r[n](i,t);if(e)e.call(t.context,r,i,t);r.trigger("sync",r,i,t)};z(this,t);return this.sync("read",this,t)},create:function(t,e){e=e?i.clone(e):{};var r=e.wait;t=this._prepareModel(t,e);if(!t)return false;if(!r)this.add(t,e);var n=this;var s=e.success;e.success=function(t,e,i){if(r)n.add(t,i);if(s)s.call(i.context,t,e,i)};t.save(null,e);return t},parse:function(t,e){return t},clone:function(){return new this.constructor(this.models,{model:this.model,comparator:this.comparator})},modelId:function(t){return t[this.model.prototype.idAttribute||"id"]},_reset:function(){this.length=0;this.models=[];this._byId={}},_prepareModel:function(t,e){if(this._isModel(t)){if(!t.collection)t.collection=this;return t}e=e?i.clone(e):{};e.collection=this;var r=new this.model(t,e);if(!r.validationError)return r;this.trigger("invalid",this,r.validationError,e);return false},_removeModels:function(t,e){var i=[];for(var r=0;r<t.length;r++){var n=this.get(t[r]);if(!n)continue;var s=this.indexOf(n);this.models.splice(s,1);this.length--;if(!e.silent){e.index=s;n.trigger("remove",n,this,e)}i.push(n);this._removeReference(n,e)}return i.length?i:false},_isModel:function(t){return t instanceof y},_addReference:function(t,e){this._byId[t.cid]=t;var i=this.modelId(t.attributes);if(i!=null)this._byId[i]=t;t.on("all",this._onModelEvent,this)},_removeReference:function(t,e){delete this._byId[t.cid];var i=this.modelId(t.attributes);if(i!=null)delete this._byId[i];if(this===t.collection)delete t.collection;t.off("all",this._onModelEvent,this)},_onModelEvent:function(t,e,i,r){if((t==="add"||t==="remove")&&i!==this)return;if(t==="destroy")this.remove(e,r);if(t==="change"){var n=this.modelId(e.previousAttributes());var s=this.modelId(e.attributes);if(n!==s){if(n!=null)delete this._byId[n];if(s!=null)this._byId[s]=e}}this.trigger.apply(this,arguments)}});var S={forEach:3,each:3,map:3,collect:3,reduce:4,foldl:4,inject:4,reduceRight:4,foldr:4,find:3,detect:3,filter:3,select:3,reject:3,every:3,all:3,some:3,any:3,include:3,includes:3,contains:3,invoke:0,max:3,min:3,toArray:1,size:1,first:3,head:3,take:3,initial:3,rest:3,tail:3,drop:3,last:3,without:0,difference:0,indexOf:3,shuffle:1,lastIndexOf:3,isEmpty:1,chain:1,sample:3,partition:3,groupBy:3,countBy:3,sortBy:3,indexBy:3};o(x,S,"models");var I=e.View=function(t){this.cid=i.uniqueId("view");i.extend(this,i.pick(t,P));this._ensureElement();this.initialize.apply(this,arguments)};var T=/^(\S+)\s*(.*)$/;var P=["model","collection","el","id","attributes","className","tagName","events"];i.extend(I.prototype,l,{tagName:"div",$:function(t){return this.$el.find(t)},initialize:function(){},render:function(){return this},remove:function(){this._removeElement();this.stopListening();return this},_removeElement:function(){this.$el.remove()},setElement:function(t){this.undelegateEvents();this._setElement(t);this.delegateEvents();return this},_setElement:function(t){this.$el=t instanceof e.$?t:e.$(t);this.el=this.$el[0]},delegateEvents:function(t){t||(t=i.result(this,"events"));if(!t)return this;this.undelegateEvents();for(var e in t){var r=t[e];if(!i.isFunction(r))r=this[r];if(!r)continue;var n=e.match(T);this.delegate(n[1],n[2],i.bind(r,this))}return this},delegate:function(t,e,i){this.$el.on(t+".delegateEvents"+this.cid,e,i);return this},undelegateEvents:function(){if(this.$el)this.$el.off(".delegateEvents"+this.cid);return this},undelegate:function(t,e,i){this.$el.off(t+".delegateEvents"+this.cid,e,i);return this},_createElement:function(t){return document.createElement(t)},_ensureElement:function(){if(!this.el){var t=i.extend({},i.result(this,"attributes"));if(this.id)t.id=i.result(this,"id");if(this.className)t["class"]=i.result(this,"className");this.setElement(this._createElement(i.result(this,"tagName")));this._setAttributes(t)}else{this.setElement(i.result(this,"el"))}},_setAttributes:function(t){this.$el.attr(t)}});e.sync=function(t,r,n){var s=H[t];i.defaults(n||(n={}),{emulateHTTP:e.emulateHTTP,emulateJSON:e.emulateJSON});var a={type:s,dataType:"json"};if(!n.url){a.url=i.result(r,"url")||F()}if(n.data==null&&r&&(t==="create"||t==="update"||t==="patch")){a.contentType="application/json";a.data=JSON.stringify(n.attrs||r.toJSON(n))}if(n.emulateJSON){a.contentType="application/x-www-form-urlencoded";a.data=a.data?{model:a.data}:{}}if(n.emulateHTTP&&(s==="PUT"||s==="DELETE"||s==="PATCH")){a.type="POST";if(n.emulateJSON)a.data._method=s;var o=n.beforeSend;n.beforeSend=function(t){t.setRequestHeader("X-HTTP-Method-Override",s);if(o)return o.apply(this,arguments)}}if(a.type!=="GET"&&!n.emulateJSON){a.processData=false}var h=n.error;n.error=function(t,e,i){n.textStatus=e;n.errorThrown=i;if(h)h.call(n.context,t,e,i)};var u=n.xhr=e.ajax(i.extend(a,n));r.trigger("request",r,u,n);return u};var H={create:"POST",update:"PUT",patch:"PATCH","delete":"DELETE",read:"GET"};e.ajax=function(){return e.$.ajax.apply(e.$,arguments)};var $=e.Router=function(t){t||(t={});if(t.routes)this.routes=t.routes;this._bindRoutes();this.initialize.apply(this,arguments)};var A=/\((.*?)\)/g;var C=/(\(\?)?:\w+/g;var R=/\*\w+/g;var j=/[\-{}\[\]+?.,\\\^$|#\s]/g;i.extend($.prototype,l,{initialize:function(){},route:function(t,r,n){if(!i.isRegExp(t))t=this._routeToRegExp(t);if(i.isFunction(r)){n=r;r=""}if(!n)n=this[r];var s=this;e.history.route(t,function(i){var a=s._extractParameters(t,i);if(s.execute(n,a,r)!==false){s.trigger.apply(s,["route:"+r].concat(a));s.trigger("route",r,a);e.history.trigger("route",s,r,a)}});return this},execute:function(t,e,i){if(t)t.apply(this,e)},navigate:function(t,i){e.history.navigate(t,i);return this},_bindRoutes:function(){if(!this.routes)return;this.routes=i.result(this,"routes");var t,e=i.keys(this.routes);while((t=e.pop())!=null){this.route(t,this.routes[t])}},_routeToRegExp:function(t){t=t.replace(j,"\\$&").replace(A,"(?:$1)?").replace(C,function(t,e){return e?t:"([^/?]+)"}).replace(R,"([^?]*?)");return new RegExp("^"+t+"(?:\\?([\\s\\S]*))?$")},_extractParameters:function(t,e){var r=t.exec(e).slice(1);return i.map(r,function(t,e){if(e===r.length-1)return t||null;return t?decodeURIComponent(t):null})}});var M=e.History=function(){this.handlers=[];this.checkUrl=i.bind(this.checkUrl,this);if(typeof window!=="undefined"){this.location=window.location;this.history=window.history}};var N=/^[#\/]|\s+$/g;var O=/^\/+|\/+$/g;var U=/#.*$/;M.started=false;i.extend(M.prototype,l,{interval:50,atRoot:function(){var t=this.location.pathname.replace(/[^\/]$/,"$&/");return t===this.root&&!this.getSearch()},matchRoot:function(){var t=this.decodeFragment(this.location.pathname);var e=t.slice(0,this.root.length-1)+"/";return e===this.root},decodeFragment:function(t){return decodeURI(t.replace(/%25/g,"%2525"))},getSearch:function(){var t=this.location.href.replace(/#.*/,"").match(/\?.+/);return t?t[0]:""},getHash:function(t){var e=(t||this).location.href.match(/#(.*)$/);return e?e[1]:""},getPath:function(){var t=this.decodeFragment(this.location.pathname+this.getSearch()).slice(this.root.length-1);return t.charAt(0)==="/"?t.slice(1):t},getFragment:function(t){if(t==null){if(this._usePushState||!this._wantsHashChange){t=this.getPath()}else{t=this.getHash()}}return t.replace(N,"")},start:function(t){if(M.started)throw new Error("Backbone.history has already been started");M.started=true;this.options=i.extend({root:"/"},this.options,t);this.root=this.options.root;this._wantsHashChange=this.options.hashChange!==false;this._hasHashChange="onhashchange"in window&&(document.documentMode===void 0||document.documentMode>7);this._useHashChange=this._wantsHashChange&&this._hasHashChange;this._wantsPushState=!!this.options.pushState;this._hasPushState=!!(this.history&&this.history.pushState);this._usePushState=this._wantsPushState&&this._hasPushState;this.fragment=this.getFragment();this.root=("/"+this.root+"/").replace(O,"/");if(this._wantsHashChange&&this._wantsPushState){if(!this._hasPushState&&!this.atRoot()){var e=this.root.slice(0,-1)||"/";this.location.replace(e+"#"+this.getPath());return true}else if(this._hasPushState&&this.atRoot()){this.navigate(this.getHash(),{replace:true})}}if(!this._hasHashChange&&this._wantsHashChange&&!this._usePushState){this.iframe=document.createElement("iframe");this.iframe.src="javascript:0";this.iframe.style.display="none";this.iframe.tabIndex=-1;var r=document.body;var n=r.insertBefore(this.iframe,r.firstChild).contentWindow;n.document.open();n.document.close();n.location.hash="#"+this.fragment}var s=window.addEventListener||function(t,e){return attachEvent("on"+t,e)};if(this._usePushState){s("popstate",this.checkUrl,false)}else if(this._useHashChange&&!this.iframe){s("hashchange",this.checkUrl,false)}else if(this._wantsHashChange){this._checkUrlInterval=setInterval(this.checkUrl,this.interval)}if(!this.options.silent)return this.loadUrl()},stop:function(){var t=window.removeEventListener||function(t,e){return detachEvent("on"+t,e)};if(this._usePushState){t("popstate",this.checkUrl,false)}else if(this._useHashChange&&!this.iframe){t("hashchange",this.checkUrl,false)}if(this.iframe){document.body.removeChild(this.iframe);this.iframe=null}if(this._checkUrlInterval)clearInterval(this._checkUrlInterval);M.started=false},route:function(t,e){this.handlers.unshift({route:t,callback:e})},checkUrl:function(t){var e=this.getFragment();if(e===this.fragment&&this.iframe){e=this.getHash(this.iframe.contentWindow)}if(e===this.fragment)return false;if(this.iframe)this.navigate(e);this.loadUrl()},loadUrl:function(t){if(!this.matchRoot())return false;t=this.fragment=this.getFragment(t);return i.some(this.handlers,function(e){if(e.route.test(t)){e.callback(t);return true}})},navigate:function(t,e){if(!M.started)return false;if(!e||e===true)e={trigger:!!e};t=this.getFragment(t||"");var i=this.root;if(t===""||t.charAt(0)==="?"){i=i.slice(0,-1)||"/"}var r=i+t;t=this.decodeFragment(t.replace(U,""));if(this.fragment===t)return;this.fragment=t;if(this._usePushState){this.history[e.replace?"replaceState":"pushState"]({},document.title,r)}else if(this._wantsHashChange){this._updateHash(this.location,t,e.replace);if(this.iframe&&t!==this.getHash(this.iframe.contentWindow)){var n=this.iframe.contentWindow;if(!e.replace){n.document.open();n.document.close()}this._updateHash(n.location,t,e.replace)}}else{return this.location.assign(r)}if(e.trigger)return this.loadUrl(t)},_updateHash:function(t,e,i){if(i){var r=t.href.replace(/(javascript:|#).*$/,"");t.replace(r+"#"+e)}else{t.hash="#"+e}}});e.history=new M;var q=function(t,e){var r=this;var n;if(t&&i.has(t,"constructor")){n=t.constructor}else{n=function(){return r.apply(this,arguments)}}i.extend(n,r,e);var s=function(){this.constructor=n};s.prototype=r.prototype;n.prototype=new s;if(t)i.extend(n.prototype,t);n.__super__=r.prototype;return n};y.extend=x.extend=$.extend=I.extend=M.extend=q;var F=function(){throw new Error('A "url" property or function must be specified')};var z=function(t,e){var i=e.error;e.error=function(r){if(i)i.call(e.context,t,r,e);t.trigger("error",t,r,e)}};return e});
+//# sourceMappingURL=backbone-min.map
\ No newline at end of file
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/src/ldt/ldt/static/ldt/js/backbone-relational.js Fri Oct 02 10:24:05 2015 +0200
@@ -0,0 +1,1860 @@
+/* vim: set tabstop=4 softtabstop=4 shiftwidth=4 noexpandtab: */
+/**
+ * Backbone-relational.js 0.8.5
+ * (c) 2011-2013 Paul Uithol and contributors (https://github.com/PaulUithol/Backbone-relational/graphs/contributors)
+ *
+ * Backbone-relational may be freely distributed under the MIT license; see the accompanying LICENSE.txt.
+ * For details and documentation: https://github.com/PaulUithol/Backbone-relational.
+ * Depends on Backbone (and thus on Underscore as well): https://github.com/documentcloud/backbone.
+ */
+( function( undefined ) {
+ "use strict";
+
+ /**
+ * CommonJS shim
+ **/
+ var _, Backbone, exports;
+ if ( typeof window === 'undefined' ) {
+ _ = require( 'underscore' );
+ Backbone = require( 'backbone' );
+ exports = module.exports = Backbone;
+ }
+ else {
+ _ = window._;
+ Backbone = window.Backbone;
+ exports = window;
+ }
+
+ Backbone.Relational = {
+ showWarnings: true
+ };
+
+ /**
+ * Semaphore mixin; can be used as both binary and counting.
+ **/
+ Backbone.Semaphore = {
+ _permitsAvailable: null,
+ _permitsUsed: 0,
+
+ acquire: function() {
+ if ( this._permitsAvailable && this._permitsUsed >= this._permitsAvailable ) {
+ throw new Error( 'Max permits acquired' );
+ }
+ else {
+ this._permitsUsed++;
+ }
+ },
+
+ release: function() {
+ if ( this._permitsUsed === 0 ) {
+ throw new Error( 'All permits released' );
+ }
+ else {
+ this._permitsUsed--;
+ }
+ },
+
+ isLocked: function() {
+ return this._permitsUsed > 0;
+ },
+
+ setAvailablePermits: function( amount ) {
+ if ( this._permitsUsed > amount ) {
+ throw new Error( 'Available permits cannot be less than used permits' );
+ }
+ this._permitsAvailable = amount;
+ }
+ };
+
+ /**
+ * A BlockingQueue that accumulates items while blocked (via 'block'),
+ * and processes them when unblocked (via 'unblock').
+ * Process can also be called manually (via 'process').
+ */
+ Backbone.BlockingQueue = function() {
+ this._queue = [];
+ };
+ _.extend( Backbone.BlockingQueue.prototype, Backbone.Semaphore, {
+ _queue: null,
+
+ add: function( func ) {
+ if ( this.isBlocked() ) {
+ this._queue.push( func );
+ }
+ else {
+ func();
+ }
+ },
+
+ process: function() {
+ while ( this._queue && this._queue.length ) {
+ this._queue.shift()();
+ }
+ },
+
+ block: function() {
+ this.acquire();
+ },
+
+ unblock: function() {
+ this.release();
+ if ( !this.isBlocked() ) {
+ this.process();
+ }
+ },
+
+ isBlocked: function() {
+ return this.isLocked();
+ }
+ });
+ /**
+ * Global event queue. Accumulates external events ('add:<key>', 'remove:<key>' and 'change:<key>')
+ * until the top-level object is fully initialized (see 'Backbone.RelationalModel').
+ */
+ Backbone.Relational.eventQueue = new Backbone.BlockingQueue();
+
+ /**
+ * Backbone.Store keeps track of all created (and destruction of) Backbone.RelationalModel.
+ * Handles lookup for relations.
+ */
+ Backbone.Store = function() {
+ this._collections = [];
+ this._reverseRelations = [];
+ this._orphanRelations = [];
+ this._subModels = [];
+ this._modelScopes = [ exports ];
+ };
+ _.extend( Backbone.Store.prototype, Backbone.Events, {
+ /**
+ * Create a new `Relation`.
+ * @param {Backbone.RelationalModel} [model]
+ * @param {Object} relation
+ * @param {Object} [options]
+ */
+ initializeRelation: function( model, relation, options ) {
+ var type = !_.isString( relation.type ) ? relation.type : Backbone[ relation.type ] || this.getObjectByName( relation.type );
+ if ( type && type.prototype instanceof Backbone.Relation ) {
+ new type( model, relation, options ); // Also pushes the new Relation into `model._relations`
+ }
+ else {
+ Backbone.Relational.showWarnings && typeof console !== 'undefined' && console.warn( 'Relation=%o; missing or invalid relation type!', relation );
+ }
+ },
+
+ /**
+ * Add a scope for `getObjectByName` to look for model types by name.
+ * @param {Object} scope
+ */
+ addModelScope: function( scope ) {
+ this._modelScopes.push( scope );
+ },
+
+ /**
+ * Remove a scope.
+ * @param {Object} scope
+ */
+ removeModelScope: function( scope ) {
+ this._modelScopes = _.without( this._modelScopes, scope );
+ },
+
+ /**
+ * Add a set of subModelTypes to the store, that can be used to resolve the '_superModel'
+ * for a model later in 'setupSuperModel'.
+ *
+ * @param {Backbone.RelationalModel} subModelTypes
+ * @param {Backbone.RelationalModel} superModelType
+ */
+ addSubModels: function( subModelTypes, superModelType ) {
+ this._subModels.push({
+ 'superModelType': superModelType,
+ 'subModels': subModelTypes
+ });
+ },
+
+ /**
+ * Check if the given modelType is registered as another model's subModel. If so, add it to the super model's
+ * '_subModels', and set the modelType's '_superModel', '_subModelTypeName', and '_subModelTypeAttribute'.
+ *
+ * @param {Backbone.RelationalModel} modelType
+ */
+ setupSuperModel: function( modelType ) {
+ _.find( this._subModels, function( subModelDef ) {
+ return _.find( subModelDef.subModels || [], function( subModelTypeName, typeValue ) {
+ var subModelType = this.getObjectByName( subModelTypeName );
+
+ if ( modelType === subModelType ) {
+ // Set 'modelType' as a child of the found superModel
+ subModelDef.superModelType._subModels[ typeValue ] = modelType;
+
+ // Set '_superModel', '_subModelTypeValue', and '_subModelTypeAttribute' on 'modelType'.
+ modelType._superModel = subModelDef.superModelType;
+ modelType._subModelTypeValue = typeValue;
+ modelType._subModelTypeAttribute = subModelDef.superModelType.prototype.subModelTypeAttribute;
+ return true;
+ }
+ }, this );
+ }, this );
+ },
+
+ /**
+ * Add a reverse relation. Is added to the 'relations' property on model's prototype, and to
+ * existing instances of 'model' in the store as well.
+ * @param {Object} relation
+ * @param {Backbone.RelationalModel} relation.model
+ * @param {String} relation.type
+ * @param {String} relation.key
+ * @param {String|Object} relation.relatedModel
+ */
+ addReverseRelation: function( relation ) {
+ var exists = _.any( this._reverseRelations, function( rel ) {
+ return _.all( relation || [], function( val, key ) {
+ return val === rel[ key ];
+ });
+ });
+
+ if ( !exists && relation.model && relation.type ) {
+ this._reverseRelations.push( relation );
+ this._addRelation( relation.model, relation );
+ this.retroFitRelation( relation );
+ }
+ },
+
+ /**
+ * Deposit a `relation` for which the `relatedModel` can't be resolved at the moment.
+ *
+ * @param {Object} relation
+ */
+ addOrphanRelation: function( relation ) {
+ var exists = _.any( this._orphanRelations, function( rel ) {
+ return _.all( relation || [], function( val, key ) {
+ return val === rel[ key ];
+ });
+ });
+
+ if ( !exists && relation.model && relation.type ) {
+ this._orphanRelations.push( relation );
+ }
+ },
+
+ /**
+ * Try to initialize any `_orphanRelation`s
+ */
+ processOrphanRelations: function() {
+ // Make sure to operate on a copy since we're removing while iterating
+ _.each( this._orphanRelations.slice( 0 ), function( rel ) {
+ var relatedModel = Backbone.Relational.store.getObjectByName( rel.relatedModel );
+ if ( relatedModel ) {
+ this.initializeRelation( null, rel );
+ this._orphanRelations = _.without( this._orphanRelations, rel );
+ }
+ }, this );
+ },
+
+ /**
+ *
+ * @param {Backbone.RelationalModel.constructor} type
+ * @param {Object} relation
+ * @private
+ */
+ _addRelation: function( type, relation ) {
+ if ( !type.prototype.relations ) {
+ type.prototype.relations = [];
+ }
+ type.prototype.relations.push( relation );
+
+ _.each( type._subModels || [], function( subModel ) {
+ this._addRelation( subModel, relation );
+ }, this );
+ },
+
+ /**
+ * Add a 'relation' to all existing instances of 'relation.model' in the store
+ * @param {Object} relation
+ */
+ retroFitRelation: function( relation ) {
+ var coll = this.getCollection( relation.model, false );
+ coll && coll.each( function( model ) {
+ if ( !( model instanceof relation.model ) ) {
+ return;
+ }
+
+ new relation.type( model, relation );
+ }, this );
+ },
+
+ /**
+ * Find the Store's collection for a certain type of model.
+ * @param {Backbone.RelationalModel} type
+ * @param {Boolean} [create=true] Should a collection be created if none is found?
+ * @return {Backbone.Collection} A collection if found (or applicable for 'model'), or null
+ */
+ getCollection: function( type, create ) {
+ if ( type instanceof Backbone.RelationalModel ) {
+ type = type.constructor;
+ }
+
+ var rootModel = type;
+ while ( rootModel._superModel ) {
+ rootModel = rootModel._superModel;
+ }
+
+ var coll = _.findWhere( this._collections, { model: rootModel } );
+
+ if ( !coll && create !== false ) {
+ coll = this._createCollection( rootModel );
+ }
+
+ return coll;
+ },
+
+ /**
+ * Find a model type on one of the modelScopes by name. Names are split on dots.
+ * @param {String} name
+ * @return {Object}
+ */
+ getObjectByName: function( name ) {
+ var parts = name.split( '.' ),
+ type = null;
+
+ _.find( this._modelScopes, function( scope ) {
+ type = _.reduce( parts || [], function( memo, val ) {
+ return memo ? memo[ val ] : undefined;
+ }, scope );
+
+ if ( type && type !== scope ) {
+ return true;
+ }
+ }, this );
+
+ return type;
+ },
+
+ _createCollection: function( type ) {
+ var coll;
+
+ // If 'type' is an instance, take its constructor
+ if ( type instanceof Backbone.RelationalModel ) {
+ type = type.constructor;
+ }
+
+ // Type should inherit from Backbone.RelationalModel.
+ if ( type.prototype instanceof Backbone.RelationalModel ) {
+ coll = new Backbone.Collection();
+ coll.model = type;
+
+ this._collections.push( coll );
+ }
+
+ return coll;
+ },
+
+ /**
+ * Find the attribute that is to be used as the `id` on a given object
+ * @param type
+ * @param {String|Number|Object|Backbone.RelationalModel} item
+ * @return {String|Number}
+ */
+ resolveIdForItem: function( type, item ) {
+ var id = _.isString( item ) || _.isNumber( item ) ? item : null;
+
+ if ( id === null ) {
+ if ( item instanceof Backbone.RelationalModel ) {
+ id = item.id;
+ }
+ else if ( _.isObject( item ) ) {
+ id = item[ type.prototype.idAttribute ];
+ }
+ }
+
+ // Make all falsy values `null` (except for 0, which could be an id.. see '/issues/179')
+ if ( !id && id !== 0 ) {
+ id = null;
+ }
+
+ return id;
+ },
+
+ /**
+ * Find a specific model of a certain `type` in the store
+ * @param type
+ * @param {String|Number|Object|Backbone.RelationalModel} item
+ */
+ find: function( type, item ) {
+ var id = this.resolveIdForItem( type, item );
+ var coll = this.getCollection( type );
+
+ // Because the found object could be of any of the type's superModel
+ // types, only return it if it's actually of the type asked for.
+ if ( coll ) {
+ var obj = coll.get( id );
+
+ if ( obj instanceof type ) {
+ return obj;
+ }
+ }
+
+ return null;
+ },
+
+ /**
+ * Add a 'model' to its appropriate collection. Retain the original contents of 'model.collection'.
+ * @param {Backbone.RelationalModel} model
+ */
+ register: function( model ) {
+ var coll = this.getCollection( model );
+
+ if ( coll ) {
+ var modelColl = model.collection;
+ coll.add( model );
+ this.listenTo( model, 'destroy', this.unregister, this );
+ model.collection = modelColl;
+ }
+ },
+
+ /**
+ * Check if the given model may use the given `id`
+ * @param model
+ * @param [id]
+ */
+ checkId: function( model, id ) {
+ var coll = this.getCollection( model ),
+ duplicate = coll && coll.get( id );
+
+ if ( duplicate && model !== duplicate ) {
+ if ( Backbone.Relational.showWarnings && typeof console !== 'undefined' ) {
+ console.warn( 'Duplicate id! Old RelationalModel=%o, new RelationalModel=%o', duplicate, model );
+ }
+
+ throw new Error( "Cannot instantiate more than one Backbone.RelationalModel with the same id per type!" );
+ }
+ },
+
+ /**
+ * Explicitly update a model's id in its store collection
+ * @param {Backbone.RelationalModel} model
+ */
+ update: function( model ) {
+ var coll = this.getCollection( model );
+ // This triggers updating the lookup indices kept in a collection
+ coll._onModelEvent( 'change:' + model.idAttribute, model, coll );
+
+ // Trigger an event on model so related models (having the model's new id in their keyContents) can add it.
+ model.trigger( 'relational:change:id', model, coll );
+ },
+
+ /**
+ * Remove a 'model' from the store.
+ * @param {Backbone.RelationalModel} model
+ */
+ unregister: function( model ) {
+ this.stopListening( model, 'destroy', this.unregister );
+ var coll = this.getCollection( model );
+ coll && coll.remove( model );
+ },
+
+ /**
+ * Reset the `store` to it's original state. The `reverseRelations` are kept though, since attempting to
+ * re-initialize these on models would lead to a large amount of warnings.
+ */
+ reset: function() {
+ this.stopListening();
+ this._collections = [];
+ this._subModels = [];
+ this._modelScopes = [ exports ];
+ }
+ });
+ Backbone.Relational.store = new Backbone.Store();
+
+ /**
+ * The main Relation class, from which 'HasOne' and 'HasMany' inherit. Internally, 'relational:<key>' events
+ * are used to regulate addition and removal of models from relations.
+ *
+ * @param {Backbone.RelationalModel} [instance] Model that this relation is created for. If no model is supplied,
+ * Relation just tries to instantiate it's `reverseRelation` if specified, and bails out after that.
+ * @param {Object} options
+ * @param {string} options.key
+ * @param {Backbone.RelationalModel.constructor} options.relatedModel
+ * @param {Boolean|String} [options.includeInJSON=true] Serialize the given attribute for related model(s)' in toJSON, or just their ids.
+ * @param {Boolean} [options.createModels=true] Create objects from the contents of keys if the object is not found in Backbone.store.
+ * @param {Object} [options.reverseRelation] Specify a bi-directional relation. If provided, Relation will reciprocate
+ * the relation to the 'relatedModel'. Required and optional properties match 'options', except that it also needs
+ * {Backbone.Relation|String} type ('HasOne' or 'HasMany').
+ * @param {Object} opts
+ */
+ Backbone.Relation = function( instance, options, opts ) {
+ this.instance = instance;
+ // Make sure 'options' is sane, and fill with defaults from subclasses and this object's prototype
+ options = _.isObject( options ) ? options : {};
+ this.reverseRelation = _.defaults( options.reverseRelation || {}, this.options.reverseRelation );
+ this.options = _.defaults( options, this.options, Backbone.Relation.prototype.options );
+
+ this.reverseRelation.type = !_.isString( this.reverseRelation.type ) ? this.reverseRelation.type :
+ Backbone[ this.reverseRelation.type ] || Backbone.Relational.store.getObjectByName( this.reverseRelation.type );
+
+ this.key = this.options.key;
+ this.keySource = this.options.keySource || this.key;
+ this.keyDestination = this.options.keyDestination || this.keySource || this.key;
+
+ this.model = this.options.model || this.instance.constructor;
+ this.relatedModel = this.options.relatedModel;
+ if ( _.isString( this.relatedModel ) ) {
+ this.relatedModel = Backbone.Relational.store.getObjectByName( this.relatedModel );
+ }
+
+ if ( !this.checkPreconditions() ) {
+ return;
+ }
+
+ // Add the reverse relation on 'relatedModel' to the store's reverseRelations
+ if ( !this.options.isAutoRelation && this.reverseRelation.type && this.reverseRelation.key ) {
+ Backbone.Relational.store.addReverseRelation( _.defaults( {
+ isAutoRelation: true,
+ model: this.relatedModel,
+ relatedModel: this.model,
+ reverseRelation: this.options // current relation is the 'reverseRelation' for its own reverseRelation
+ },
+ this.reverseRelation // Take further properties from this.reverseRelation (type, key, etc.)
+ ) );
+ }
+
+ if ( instance ) {
+ var contentKey = this.keySource;
+ if ( contentKey !== this.key && typeof this.instance.get( this.key ) === 'object' ) {
+ contentKey = this.key;
+ }
+
+ this.setKeyContents( this.instance.get( contentKey ) );
+ this.relatedCollection = Backbone.Relational.store.getCollection( this.relatedModel );
+
+ // Explicitly clear 'keySource', to prevent a leaky abstraction if 'keySource' differs from 'key'.
+ if ( this.keySource !== this.key ) {
+ this.instance.unset( this.keySource, { silent: true } );
+ }
+
+ // Add this Relation to instance._relations
+ this.instance._relations[ this.key ] = this;
+
+ this.initialize( opts );
+
+ if ( this.options.autoFetch ) {
+ this.instance.fetchRelated( this.key, _.isObject( this.options.autoFetch ) ? this.options.autoFetch : {} );
+ }
+
+ // When 'relatedModel' are created or destroyed, check if it affects this relation.
+ this.listenTo( this.instance, 'destroy', this.destroy )
+ .listenTo( this.relatedCollection, 'relational:add relational:change:id', this.tryAddRelated )
+ .listenTo( this.relatedCollection, 'relational:remove', this.removeRelated )
+ }
+ };
+ // Fix inheritance :\
+ Backbone.Relation.extend = Backbone.Model.extend;
+ // Set up all inheritable **Backbone.Relation** properties and methods.
+ _.extend( Backbone.Relation.prototype, Backbone.Events, Backbone.Semaphore, {
+ options: {
+ createModels: true,
+ includeInJSON: true,
+ isAutoRelation: false,
+ autoFetch: false,
+ parse: false
+ },
+
+ instance: null,
+ key: null,
+ keyContents: null,
+ relatedModel: null,
+ relatedCollection: null,
+ reverseRelation: null,
+ related: null,
+
+ /**
+ * Check several pre-conditions.
+ * @return {Boolean} True if pre-conditions are satisfied, false if they're not.
+ */
+ checkPreconditions: function() {
+ var i = this.instance,
+ k = this.key,
+ m = this.model,
+ rm = this.relatedModel,
+ warn = Backbone.Relational.showWarnings && typeof console !== 'undefined';
+
+ if ( !m || !k || !rm ) {
+ warn && console.warn( 'Relation=%o: missing model, key or relatedModel (%o, %o, %o).', this, m, k, rm );
+ return false;
+ }
+ // Check if the type in 'model' inherits from Backbone.RelationalModel
+ if ( !( m.prototype instanceof Backbone.RelationalModel ) ) {
+ warn && console.warn( 'Relation=%o: model does not inherit from Backbone.RelationalModel (%o).', this, i );
+ return false;
+ }
+ // Check if the type in 'relatedModel' inherits from Backbone.RelationalModel
+ if ( !( rm.prototype instanceof Backbone.RelationalModel ) ) {
+ warn && console.warn( 'Relation=%o: relatedModel does not inherit from Backbone.RelationalModel (%o).', this, rm );
+ return false;
+ }
+ // Check if this is not a HasMany, and the reverse relation is HasMany as well
+ if ( this instanceof Backbone.HasMany && this.reverseRelation.type === Backbone.HasMany ) {
+ warn && console.warn( 'Relation=%o: relation is a HasMany, and the reverseRelation is HasMany as well.', this );
+ return false;
+ }
+ // Check if we're not attempting to create a relationship on a `key` that's already used.
+ if ( i && _.keys( i._relations ).length ) {
+ var existing = _.find( i._relations, function( rel ) {
+ return rel.key === k;
+ }, this );
+
+ if ( existing ) {
+ warn && console.warn( 'Cannot create relation=%o on %o for model=%o: already taken by relation=%o.',
+ this, k, i, existing );
+ return false;
+ }
+ }
+
+ return true;
+ },
+
+ /**
+ * Set the related model(s) for this relation
+ * @param {Backbone.Model|Backbone.Collection} related
+ */
+ setRelated: function( related ) {
+ this.related = related;
+
+ this.instance.acquire();
+ this.instance.attributes[ this.key ] = related;
+ this.instance.release();
+ },
+
+ /**
+ * Determine if a relation (on a different RelationalModel) is the reverse
+ * relation of the current one.
+ * @param {Backbone.Relation} relation
+ * @return {Boolean}
+ */
+ _isReverseRelation: function( relation ) {
+ return relation.instance instanceof this.relatedModel && this.reverseRelation.key === relation.key &&
+ this.key === relation.reverseRelation.key;
+ },
+
+ /**
+ * Get the reverse relations (pointing back to 'this.key' on 'this.instance') for the currently related model(s).
+ * @param {Backbone.RelationalModel} [model] Get the reverse relations for a specific model.
+ * If not specified, 'this.related' is used.
+ * @return {Backbone.Relation[]}
+ */
+ getReverseRelations: function( model ) {
+ var reverseRelations = [];
+ // Iterate over 'model', 'this.related.models' (if this.related is a Backbone.Collection), or wrap 'this.related' in an array.
+ var models = !_.isUndefined( model ) ? [ model ] : this.related && ( this.related.models || [ this.related ] );
+ _.each( models || [], function( related ) {
+ _.each( related.getRelations() || [], function( relation ) {
+ if ( this._isReverseRelation( relation ) ) {
+ reverseRelations.push( relation );
+ }
+ }, this );
+ }, this );
+
+ return reverseRelations;
+ },
+
+ /**
+ * When `this.instance` is destroyed, cleanup our relations.
+ * Get reverse relation, call removeRelated on each.
+ */
+ destroy: function() {
+ this.stopListening();
+
+ if ( this instanceof Backbone.HasOne ) {
+ this.setRelated( null );
+ }
+ else if ( this instanceof Backbone.HasMany ) {
+ this.setRelated( this._prepareCollection() );
+ }
+
+ _.each( this.getReverseRelations(), function( relation ) {
+ relation.removeRelated( this.instance );
+ }, this );
+ }
+ });
+
+ Backbone.HasOne = Backbone.Relation.extend({
+ options: {
+ reverseRelation: { type: 'HasMany' }
+ },
+
+ initialize: function( opts ) {
+ this.listenTo( this.instance, 'relational:change:' + this.key, this.onChange );
+
+ var related = this.findRelated( opts );
+ this.setRelated( related );
+
+ // Notify new 'related' object of the new relation.
+ _.each( this.getReverseRelations(), function( relation ) {
+ relation.addRelated( this.instance, opts );
+ }, this );
+ },
+
+ /**
+ * Find related Models.
+ * @param {Object} [options]
+ * @return {Backbone.Model}
+ */
+ findRelated: function( options ) {
+ var related = null;
+
+ options = _.defaults( { parse: this.options.parse }, options );
+
+ if ( this.keyContents instanceof this.relatedModel ) {
+ related = this.keyContents;
+ }
+ else if ( this.keyContents || this.keyContents === 0 ) { // since 0 can be a valid `id` as well
+ var opts = _.defaults( { create: this.options.createModels }, options );
+ related = this.relatedModel.findOrCreate( this.keyContents, opts );
+ }
+
+ // Nullify `keyId` if we have a related model; in case it was already part of the relation
+ if ( this.related ) {
+ this.keyId = null;
+ }
+
+ return related;
+ },
+
+ /**
+ * Normalize and reduce `keyContents` to an `id`, for easier comparison
+ * @param {String|Number|Backbone.Model} keyContents
+ */
+ setKeyContents: function( keyContents ) {
+ this.keyContents = keyContents;
+ this.keyId = Backbone.Relational.store.resolveIdForItem( this.relatedModel, this.keyContents );
+ },
+
+ /**
+ * Event handler for `change:<key>`.
+ * If the key is changed, notify old & new reverse relations and initialize the new relation.
+ */
+ onChange: function( model, attr, options ) {
+ // Don't accept recursive calls to onChange (like onChange->findRelated->findOrCreate->initializeRelations->addRelated->onChange)
+ if ( this.isLocked() ) {
+ return;
+ }
+ this.acquire();
+ options = options ? _.clone( options ) : {};
+
+ // 'options.__related' is set by 'addRelated'/'removeRelated'. If it is set, the change
+ // is the result of a call from a relation. If it's not, the change is the result of
+ // a 'set' call on this.instance.
+ var changed = _.isUndefined( options.__related ),
+ oldRelated = changed ? this.related : options.__related;
+
+ if ( changed ) {
+ this.setKeyContents( attr );
+ var related = this.findRelated( options );
+ this.setRelated( related );
+ }
+
+ // Notify old 'related' object of the terminated relation
+ if ( oldRelated && this.related !== oldRelated ) {
+ _.each( this.getReverseRelations( oldRelated ), function( relation ) {
+ relation.removeRelated( this.instance, null, options );
+ }, this );
+ }
+
+ // Notify new 'related' object of the new relation. Note we do re-apply even if this.related is oldRelated;
+ // that can be necessary for bi-directional relations if 'this.instance' was created after 'this.related'.
+ // In that case, 'this.instance' will already know 'this.related', but the reverse might not exist yet.
+ _.each( this.getReverseRelations(), function( relation ) {
+ relation.addRelated( this.instance, options );
+ }, this );
+
+ // Fire the 'change:<key>' event if 'related' was updated
+ if ( !options.silent && this.related !== oldRelated ) {
+ var dit = this;
+ this.changed = true;
+ Backbone.Relational.eventQueue.add( function() {
+ dit.instance.trigger( 'change:' + dit.key, dit.instance, dit.related, options, true );
+ dit.changed = false;
+ });
+ }
+ this.release();
+ },
+
+ /**
+ * If a new 'this.relatedModel' appears in the 'store', try to match it to the last set 'keyContents'
+ */
+ tryAddRelated: function( model, coll, options ) {
+ if ( ( this.keyId || this.keyId === 0 ) && model.id === this.keyId ) { // since 0 can be a valid `id` as well
+ this.addRelated( model, options );
+ this.keyId = null;
+ }
+ },
+
+ addRelated: function( model, options ) {
+ // Allow 'model' to set up its relations before proceeding.
+ // (which can result in a call to 'addRelated' from a relation of 'model')
+ var dit = this;
+ model.queue( function() {
+ if ( model !== dit.related ) {
+ var oldRelated = dit.related || null;
+ dit.setRelated( model );
+ dit.onChange( dit.instance, model, _.defaults( { __related: oldRelated }, options ) );
+ }
+ });
+ },
+
+ removeRelated: function( model, coll, options ) {
+ if ( !this.related ) {
+ return;
+ }
+
+ if ( model === this.related ) {
+ var oldRelated = this.related || null;
+ this.setRelated( null );
+ this.onChange( this.instance, model, _.defaults( { __related: oldRelated }, options ) );
+ }
+ }
+ });
+
+ Backbone.HasMany = Backbone.Relation.extend({
+ collectionType: null,
+
+ options: {
+ reverseRelation: { type: 'HasOne' },
+ collectionType: Backbone.Collection,
+ collectionKey: true,
+ collectionOptions: {}
+ },
+
+ initialize: function( opts ) {
+ this.listenTo( this.instance, 'relational:change:' + this.key, this.onChange );
+
+ // Handle a custom 'collectionType'
+ this.collectionType = this.options.collectionType;
+ if ( _.isString( this.collectionType ) ) {
+ this.collectionType = Backbone.Relational.store.getObjectByName( this.collectionType );
+ }
+ if ( this.collectionType !== Backbone.Collection && !( this.collectionType.prototype instanceof Backbone.Collection ) ) {
+ throw new Error( '`collectionType` must inherit from Backbone.Collection' );
+ }
+
+ var related = this.findRelated( opts );
+ this.setRelated( related );
+ },
+
+ /**
+ * Bind events and setup collectionKeys for a collection that is to be used as the backing store for a HasMany.
+ * If no 'collection' is supplied, a new collection will be created of the specified 'collectionType' option.
+ * @param {Backbone.Collection} [collection]
+ * @return {Backbone.Collection}
+ */
+ _prepareCollection: function( collection ) {
+ if ( this.related ) {
+ this.stopListening( this.related );
+ }
+
+ if ( !collection || !( collection instanceof Backbone.Collection ) ) {
+ var options = _.isFunction( this.options.collectionOptions ) ?
+ this.options.collectionOptions( this.instance ) : this.options.collectionOptions;
+
+ collection = new this.collectionType( null, options );
+ }
+
+ collection.model = this.relatedModel;
+
+ if ( this.options.collectionKey ) {
+ var key = this.options.collectionKey === true ? this.options.reverseRelation.key : this.options.collectionKey;
+
+ if ( collection[ key ] && collection[ key ] !== this.instance ) {
+ if ( Backbone.Relational.showWarnings && typeof console !== 'undefined' ) {
+ console.warn( 'Relation=%o; collectionKey=%s already exists on collection=%o', this, key, this.options.collectionKey );
+ }
+ }
+ else if ( key ) {
+ collection[ key ] = this.instance;
+ }
+ }
+
+ this.listenTo( collection, 'relational:add', this.handleAddition )
+ .listenTo( collection, 'relational:remove', this.handleRemoval )
+ .listenTo( collection, 'relational:reset', this.handleReset );
+
+ return collection;
+ },
+
+ /**
+ * Find related Models.
+ * @param {Object} [options]
+ * @return {Backbone.Collection}
+ */
+ findRelated: function( options ) {
+ var related = null;
+
+ options = _.defaults( { parse: this.options.parse }, options );
+
+ // Replace 'this.related' by 'this.keyContents' if it is a Backbone.Collection
+ if ( this.keyContents instanceof Backbone.Collection ) {
+ this._prepareCollection( this.keyContents );
+ related = this.keyContents;
+ }
+ // Otherwise, 'this.keyContents' should be an array of related object ids.
+ // Re-use the current 'this.related' if it is a Backbone.Collection; otherwise, create a new collection.
+ else {
+ var toAdd = [];
+
+ _.each( this.keyContents, function( attributes ) {
+ if ( attributes instanceof this.relatedModel ) {
+ var model = attributes;
+ }
+ else {
+ // If `merge` is true, update models here, instead of during update.
+ model = this.relatedModel.findOrCreate( attributes,
+ _.extend( { merge: true }, options, { create: this.options.createModels } )
+ );
+ }
+
+ model && toAdd.push( model );
+ }, this );
+
+ if ( this.related instanceof Backbone.Collection ) {
+ related = this.related;
+ }
+ else {
+ related = this._prepareCollection();
+ }
+
+ // By now, both `merge` and `parse` will already have been executed for models if they were specified.
+ // Disable them to prevent additional calls.
+ related.set( toAdd, _.defaults( { merge: false, parse: false }, options ) );
+ }
+
+ // Remove entries from `keyIds` that were already part of the relation (and are thus 'unchanged')
+ this.keyIds = _.difference( this.keyIds, _.pluck( related.models, 'id' ) );
+
+ return related;
+ },
+
+ /**
+ * Normalize and reduce `keyContents` to a list of `ids`, for easier comparison
+ * @param {String|Number|String[]|Number[]|Backbone.Collection} keyContents
+ */
+ setKeyContents: function( keyContents ) {
+ this.keyContents = keyContents instanceof Backbone.Collection ? keyContents : null;
+ this.keyIds = [];
+
+ if ( !this.keyContents && ( keyContents || keyContents === 0 ) ) { // since 0 can be a valid `id` as well
+ // Handle cases the an API/user supplies just an Object/id instead of an Array
+ this.keyContents = _.isArray( keyContents ) ? keyContents : [ keyContents ];
+
+ _.each( this.keyContents, function( item ) {
+ var itemId = Backbone.Relational.store.resolveIdForItem( this.relatedModel, item );
+ if ( itemId || itemId === 0 ) {
+ this.keyIds.push( itemId );
+ }
+ }, this );
+ }
+ },
+
+ /**
+ * Event handler for `change:<key>`.
+ * If the contents of the key are changed, notify old & new reverse relations and initialize the new relation.
+ */
+ onChange: function( model, attr, options ) {
+ options = options ? _.clone( options ) : {};
+ this.setKeyContents( attr );
+ this.changed = false;
+
+ var related = this.findRelated( options );
+ this.setRelated( related );
+
+ if ( !options.silent ) {
+ var dit = this;
+ Backbone.Relational.eventQueue.add( function() {
+ // The `changed` flag can be set in `handleAddition` or `handleRemoval`
+ if ( dit.changed ) {
+ dit.instance.trigger( 'change:' + dit.key, dit.instance, dit.related, options, true );
+ dit.changed = false;
+ }
+ });
+ }
+ },
+
+ /**
+ * When a model is added to a 'HasMany', trigger 'add' on 'this.instance' and notify reverse relations.
+ * (should be 'HasOne', must set 'this.instance' as their related).
+ */
+ handleAddition: function( model, coll, options ) {
+ //console.debug('handleAddition called; args=%o', arguments);
+ options = options ? _.clone( options ) : {};
+ this.changed = true;
+
+ _.each( this.getReverseRelations( model ), function( relation ) {
+ relation.addRelated( this.instance, options );
+ }, this );
+
+ // Only trigger 'add' once the newly added model is initialized (so, has its relations set up)
+ var dit = this;
+ !options.silent && Backbone.Relational.eventQueue.add( function() {
+ dit.instance.trigger( 'add:' + dit.key, model, dit.related, options );
+ });
+ },
+
+ /**
+ * When a model is removed from a 'HasMany', trigger 'remove' on 'this.instance' and notify reverse relations.
+ * (should be 'HasOne', which should be nullified)
+ */
+ handleRemoval: function( model, coll, options ) {
+ //console.debug('handleRemoval called; args=%o', arguments);
+ options = options ? _.clone( options ) : {};
+ this.changed = true;
+
+ _.each( this.getReverseRelations( model ), function( relation ) {
+ relation.removeRelated( this.instance, null, options );
+ }, this );
+
+ var dit = this;
+ !options.silent && Backbone.Relational.eventQueue.add( function() {
+ dit.instance.trigger( 'remove:' + dit.key, model, dit.related, options );
+ });
+ },
+
+ handleReset: function( coll, options ) {
+ var dit = this;
+ options = options ? _.clone( options ) : {};
+ !options.silent && Backbone.Relational.eventQueue.add( function() {
+ dit.instance.trigger( 'reset:' + dit.key, dit.related, options );
+ });
+ },
+
+ tryAddRelated: function( model, coll, options ) {
+ var item = _.contains( this.keyIds, model.id );
+
+ if ( item ) {
+ this.addRelated( model, options );
+ this.keyIds = _.without( this.keyIds, model.id );
+ }
+ },
+
+ addRelated: function( model, options ) {
+ // Allow 'model' to set up its relations before proceeding.
+ // (which can result in a call to 'addRelated' from a relation of 'model')
+ var dit = this;
+ model.queue( function() {
+ if ( dit.related && !dit.related.get( model ) ) {
+ dit.related.add( model, _.defaults( { parse: false }, options ) );
+ }
+ });
+ },
+
+ removeRelated: function( model, coll, options ) {
+ if ( this.related.get( model ) ) {
+ this.related.remove( model, options );
+ }
+ }
+ });
+
+ /**
+ * A type of Backbone.Model that also maintains relations to other models and collections.
+ * New events when compared to the original:
+ * - 'add:<key>' (model, related collection, options)
+ * - 'remove:<key>' (model, related collection, options)
+ * - 'change:<key>' (model, related model or collection, options)
+ */
+ Backbone.RelationalModel = Backbone.Model.extend({
+ relations: null, // Relation descriptions on the prototype
+ _relations: null, // Relation instances
+ _isInitialized: false,
+ _deferProcessing: false,
+ _queue: null,
+
+ subModelTypeAttribute: 'type',
+ subModelTypes: null,
+
+ constructor: function( attributes, options ) {
+ // Nasty hack, for cases like 'model.get( <HasMany key> ).add( item )'.
+ // Defer 'processQueue', so that when 'Relation.createModels' is used we trigger 'HasMany'
+ // collection events only after the model is really fully set up.
+ // Example: event for "p.on( 'add:jobs' )" -> "p.get('jobs').add( { company: c.id, person: p.id } )".
+ if ( options && options.collection ) {
+ var dit = this,
+ collection = this.collection = options.collection;
+
+ // Prevent `collection` from cascading down to nested models; they shouldn't go into this `if` clause.
+ delete options.collection;
+
+ this._deferProcessing = true;
+
+ var processQueue = function( model ) {
+ if ( model === dit ) {
+ dit._deferProcessing = false;
+ dit.processQueue();
+ collection.off( 'relational:add', processQueue );
+ }
+ };
+ collection.on( 'relational:add', processQueue );
+
+ // So we do process the queue eventually, regardless of whether this model actually gets added to 'options.collection'.
+ _.defer( function() {
+ processQueue( dit );
+ });
+ }
+
+ Backbone.Relational.store.processOrphanRelations();
+
+ this._queue = new Backbone.BlockingQueue();
+ this._queue.block();
+ Backbone.Relational.eventQueue.block();
+
+ try {
+ Backbone.Model.apply( this, arguments );
+ }
+ finally {
+ // Try to run the global queue holding external events
+ Backbone.Relational.eventQueue.unblock();
+ }
+ },
+
+ /**
+ * Override 'trigger' to queue 'change' and 'change:*' events
+ */
+ trigger: function( eventName ) {
+ if ( eventName.length > 5 && eventName.indexOf( 'change' ) === 0 ) {
+ var dit = this,
+ args = arguments;
+
+ Backbone.Relational.eventQueue.add( function() {
+ if ( !dit._isInitialized ) {
+ return;
+ }
+
+ // Determine if the `change` event is still valid, now that all relations are populated
+ var changed = true;
+ if ( eventName === 'change' ) {
+ changed = dit.hasChanged();
+ }
+ else {
+ var attr = eventName.slice( 7 ),
+ rel = dit.getRelation( attr );
+
+ if ( rel ) {
+ // If `attr` is a relation, `change:attr` get triggered from `Relation.onChange`.
+ // These take precedence over `change:attr` events triggered by `Model.set`.
+ // The relation set a fourth attribute to `true`. If this attribute is present,
+ // continue triggering this event; otherwise, it's from `Model.set` and should be stopped.
+ changed = ( args[ 4 ] === true );
+
+ // If this event was triggered by a relation, set the right value in `this.changed`
+ // (a Collection or Model instead of raw data).
+ if ( changed ) {
+ dit.changed[ attr ] = args[ 2 ];
+ }
+ // Otherwise, this event is from `Model.set`. If the relation doesn't report a change,
+ // remove attr from `dit.changed` so `hasChanged` doesn't take it into account.
+ else if ( !rel.changed ) {
+ delete dit.changed[ attr ];
+ }
+ }
+ }
+
+ changed && Backbone.Model.prototype.trigger.apply( dit, args );
+ });
+ }
+ else {
+ Backbone.Model.prototype.trigger.apply( this, arguments );
+ }
+
+ return this;
+ },
+
+ /**
+ * Initialize Relations present in this.relations; determine the type (HasOne/HasMany), then creates a new instance.
+ * Invoked in the first call so 'set' (which is made from the Backbone.Model constructor).
+ */
+ initializeRelations: function( options ) {
+ this.acquire(); // Setting up relations often also involve calls to 'set', and we only want to enter this function once
+ this._relations = {};
+
+ _.each( this.relations || [], function( rel ) {
+ Backbone.Relational.store.initializeRelation( this, rel, options );
+ }, this );
+
+ this._isInitialized = true;
+ this.release();
+ this.processQueue();
+ },
+
+ /**
+ * When new values are set, notify this model's relations (also if options.silent is set).
+ * (Relation.setRelated locks this model before calling 'set' on it to prevent loops)
+ */
+ updateRelations: function( options ) {
+ if ( this._isInitialized && !this.isLocked() ) {
+ _.each( this._relations, function( rel ) {
+ // Update from data in `rel.keySource` if set, or `rel.key` otherwise
+ var val = this.attributes[ rel.keySource ] || this.attributes[ rel.key ];
+ if ( rel.related !== val ) {
+ this.trigger( 'relational:change:' + rel.key, this, val, options || {} );
+ }
+ }, this );
+ }
+ },
+
+ /**
+ * Either add to the queue (if we're not initialized yet), or execute right away.
+ */
+ queue: function( func ) {
+ this._queue.add( func );
+ },
+
+ /**
+ * Process _queue
+ */
+ processQueue: function() {
+ if ( this._isInitialized && !this._deferProcessing && this._queue.isBlocked() ) {
+ this._queue.unblock();
+ }
+ },
+
+ /**
+ * Get a specific relation.
+ * @param key {string} The relation key to look for.
+ * @return {Backbone.Relation} An instance of 'Backbone.Relation', if a relation was found for 'key', or null.
+ */
+ getRelation: function( key ) {
+ return this._relations[ key ];
+ },
+
+ /**
+ * Get all of the created relations.
+ * @return {Backbone.Relation[]}
+ */
+ getRelations: function() {
+ return _.values( this._relations );
+ },
+
+ /**
+ * Retrieve related objects.
+ * @param key {string} The relation key to fetch models for.
+ * @param [options] {Object} Options for 'Backbone.Model.fetch' and 'Backbone.sync'.
+ * @param [refresh=false] {boolean} Fetch existing models from the server as well (in order to update them).
+ * @return {jQuery.when[]} An array of request objects
+ */
+ fetchRelated: function( key, options, refresh ) {
+ // Set default `options` for fetch
+ options = _.extend( { update: true, remove: false }, options );
+
+ var setUrl,
+ requests = [],
+ rel = this.getRelation( key ),
+ idsToFetch = rel && ( rel.keyIds || ( ( rel.keyId || rel.keyId === 0 ) ? [ rel.keyId ] : [] ) );
+
+ // On `refresh`, add the ids for current models in the relation to `idsToFetch`
+ if ( refresh ) {
+ var models = rel.related instanceof Backbone.Collection ? rel.related.models : [ rel.related ];
+ _.each( models, function( model ) {
+ if ( model.id || model.id === 0 ) {
+ idsToFetch.push( model.id );
+ }
+ });
+ }
+
+ if ( idsToFetch && idsToFetch.length ) {
+ // Find (or create) a model for each one that is to be fetched
+ var created = [],
+ models = _.map( idsToFetch, function( id ) {
+ var model = Backbone.Relational.store.find( rel.relatedModel, id );
+
+ if ( !model ) {
+ var attrs = {};
+ attrs[ rel.relatedModel.prototype.idAttribute ] = id;
+ model = rel.relatedModel.findOrCreate( attrs, options );
+ created.push( model );
+ }
+
+ return model;
+ }, this );
+
+ // Try if the 'collection' can provide a url to fetch a set of models in one request.
+ if ( rel.related instanceof Backbone.Collection && _.isFunction( rel.related.url ) ) {
+ setUrl = rel.related.url( models );
+ }
+
+ // An assumption is that when 'Backbone.Collection.url' is a function, it can handle building of set urls.
+ // To make sure it can, test if the url we got by supplying a list of models to fetch is different from
+ // the one supplied for the default fetch action (without args to 'url').
+ if ( setUrl && setUrl !== rel.related.url() ) {
+ var opts = _.defaults(
+ {
+ error: function() {
+ var args = arguments;
+ _.each( created, function( model ) {
+ model.trigger( 'destroy', model, model.collection, options );
+ options.error && options.error.apply( model, args );
+ });
+ },
+ url: setUrl
+ },
+ options
+ );
+
+ requests = [ rel.related.fetch( opts ) ];
+ }
+ else {
+ requests = _.map( models, function( model ) {
+ var opts = _.defaults(
+ {
+ error: function() {
+ if ( _.contains( created, model ) ) {
+ model.trigger( 'destroy', model, model.collection, options );
+ options.error && options.error.apply( model, arguments );
+ }
+ }
+ },
+ options
+ );
+ return model.fetch( opts );
+ }, this );
+ }
+ }
+
+ return requests;
+ },
+
+ get: function( attr ) {
+ var originalResult = Backbone.Model.prototype.get.call( this, attr );
+
+ // Use `originalResult` get if dotNotation not enabled or not required because no dot is in `attr`
+ if ( !this.dotNotation || attr.indexOf( '.' ) === -1 ) {
+ return originalResult;
+ }
+
+ // Go through all splits and return the final result
+ var splits = attr.split( '.' );
+ var result = _.reduce(splits, function( model, split ) {
+ if ( !( model instanceof Backbone.Model ) ) {
+ throw new Error( 'Attribute must be an instanceof Backbone.Model. Is: ' + model + ', currentSplit: ' + split );
+ }
+
+ return Backbone.Model.prototype.get.call( model, split );
+ }, this );
+
+ if ( originalResult !== undefined && result !== undefined ) {
+ throw new Error( "Ambiguous result for '" + attr + "'. direct result: " + originalResult + ", dotNotation: " + result );
+ }
+
+ return originalResult || result;
+ },
+
+ set: function( key, value, options ) {
+ Backbone.Relational.eventQueue.block();
+
+ // Duplicate backbone's behavior to allow separate key/value parameters, instead of a single 'attributes' object
+ var attributes;
+ if ( _.isObject( key ) || key == null ) {
+ attributes = key;
+ options = value;
+ }
+ else {
+ attributes = {};
+ attributes[ key ] = value;
+ }
+
+ try {
+ var id = this.id,
+ newId = attributes && this.idAttribute in attributes && attributes[ this.idAttribute ];
+
+ // Check if we're not setting a duplicate id before actually calling `set`.
+ Backbone.Relational.store.checkId( this, newId );
+
+ var result = Backbone.Model.prototype.set.apply( this, arguments );
+
+ // Ideal place to set up relations, if this is the first time we're here for this model
+ if ( !this._isInitialized && !this.isLocked() ) {
+ this.constructor.initializeModelHierarchy();
+ Backbone.Relational.store.register( this );
+ this.initializeRelations( options );
+ }
+ // The store should know about an `id` update asap
+ else if ( newId && newId !== id ) {
+ Backbone.Relational.store.update( this );
+ }
+
+ if ( attributes ) {
+ this.updateRelations( options );
+ }
+ }
+ finally {
+ // Try to run the global queue holding external events
+ Backbone.Relational.eventQueue.unblock();
+ }
+
+ return result;
+ },
+
+ unset: function( attribute, options ) {
+ Backbone.Relational.eventQueue.block();
+
+ var result = Backbone.Model.prototype.unset.apply( this, arguments );
+ this.updateRelations( options );
+
+ // Try to run the global queue holding external events
+ Backbone.Relational.eventQueue.unblock();
+
+ return result;
+ },
+
+ clear: function( options ) {
+ Backbone.Relational.eventQueue.block();
+
+ var result = Backbone.Model.prototype.clear.apply( this, arguments );
+ this.updateRelations( options );
+
+ // Try to run the global queue holding external events
+ Backbone.Relational.eventQueue.unblock();
+
+ return result;
+ },
+
+ clone: function() {
+ var attributes = _.clone( this.attributes );
+ if ( !_.isUndefined( attributes[ this.idAttribute ] ) ) {
+ attributes[ this.idAttribute ] = null;
+ }
+
+ _.each( this.getRelations(), function( rel ) {
+ delete attributes[ rel.key ];
+ });
+
+ return new this.constructor( attributes );
+ },
+
+ /**
+ * Convert relations to JSON, omits them when required
+ */
+ toJSON: function( options ) {
+ // If this Model has already been fully serialized in this branch once, return to avoid loops
+ if ( this.isLocked() ) {
+ return this.id;
+ }
+
+ this.acquire();
+ var json = Backbone.Model.prototype.toJSON.call( this, options );
+
+ if ( this.constructor._superModel && !( this.constructor._subModelTypeAttribute in json ) ) {
+ json[ this.constructor._subModelTypeAttribute ] = this.constructor._subModelTypeValue;
+ }
+
+ _.each( this._relations, function( rel ) {
+ var related = json[ rel.key ],
+ includeInJSON = rel.options.includeInJSON,
+ value = null;
+
+ if ( includeInJSON === true ) {
+ if ( related && _.isFunction( related.toJSON ) ) {
+ value = related.toJSON( options );
+ }
+ }
+ else if ( _.isString( includeInJSON ) ) {
+ if ( related instanceof Backbone.Collection ) {
+ value = related.pluck( includeInJSON );
+ }
+ else if ( related instanceof Backbone.Model ) {
+ value = related.get( includeInJSON );
+ }
+
+ // Add ids for 'unfound' models if includeInJSON is equal to (only) the relatedModel's `idAttribute`
+ if ( includeInJSON === rel.relatedModel.prototype.idAttribute ) {
+ if ( rel instanceof Backbone.HasMany ) {
+ value = value.concat( rel.keyIds );
+ }
+ else if ( rel instanceof Backbone.HasOne ) {
+ value = value || rel.keyId;
+ }
+ }
+ }
+ else if ( _.isArray( includeInJSON ) ) {
+ if ( related instanceof Backbone.Collection ) {
+ value = [];
+ related.each( function( model ) {
+ var curJson = {};
+ _.each( includeInJSON, function( key ) {
+ curJson[ key ] = model.get( key );
+ });
+ value.push( curJson );
+ });
+ }
+ else if ( related instanceof Backbone.Model ) {
+ value = {};
+ _.each( includeInJSON, function( key ) {
+ value[ key ] = related.get( key );
+ });
+ }
+ }
+ else {
+ delete json[ rel.key ];
+ }
+
+ if ( includeInJSON ) {
+ json[ rel.keyDestination ] = value;
+ }
+
+ if ( rel.keyDestination !== rel.key ) {
+ delete json[ rel.key ];
+ }
+ });
+
+ this.release();
+ return json;
+ }
+ },
+ {
+ /**
+ *
+ * @param superModel
+ * @returns {Backbone.RelationalModel.constructor}
+ */
+ setup: function( superModel ) {
+ // We don't want to share a relations array with a parent, as this will cause problems with
+ // reverse relations.
+ this.prototype.relations = ( this.prototype.relations || [] ).slice( 0 );
+
+ this._subModels = {};
+ this._superModel = null;
+
+ // If this model has 'subModelTypes' itself, remember them in the store
+ if ( this.prototype.hasOwnProperty( 'subModelTypes' ) ) {
+ Backbone.Relational.store.addSubModels( this.prototype.subModelTypes, this );
+ }
+ // The 'subModelTypes' property should not be inherited, so reset it.
+ else {
+ this.prototype.subModelTypes = null;
+ }
+
+ // Initialize all reverseRelations that belong to this new model.
+ _.each( this.prototype.relations || [], function( rel ) {
+ if ( !rel.model ) {
+ rel.model = this;
+ }
+
+ if ( rel.reverseRelation && rel.model === this ) {
+ var preInitialize = true;
+ if ( _.isString( rel.relatedModel ) ) {
+ /**
+ * The related model might not be defined for two reasons
+ * 1. it is related to itself
+ * 2. it never gets defined, e.g. a typo
+ * 3. the model hasn't been defined yet, but will be later
+ * In neither of these cases do we need to pre-initialize reverse relations.
+ * However, for 3. (which is, to us, indistinguishable from 2.), we do need to attempt
+ * setting up this relation again later, in case the related model is defined later.
+ */
+ var relatedModel = Backbone.Relational.store.getObjectByName( rel.relatedModel );
+ preInitialize = relatedModel && ( relatedModel.prototype instanceof Backbone.RelationalModel );
+ }
+
+ if ( preInitialize ) {
+ Backbone.Relational.store.initializeRelation( null, rel );
+ }
+ else if ( _.isString( rel.relatedModel ) ) {
+ Backbone.Relational.store.addOrphanRelation( rel );
+ }
+ }
+ }, this );
+
+ return this;
+ },
+
+ /**
+ * Create a 'Backbone.Model' instance based on 'attributes'.
+ * @param {Object} attributes
+ * @param {Object} [options]
+ * @return {Backbone.Model}
+ */
+ build: function( attributes, options ) {
+ var model = this;
+
+ // 'build' is a possible entrypoint; it's possible no model hierarchy has been determined yet.
+ this.initializeModelHierarchy();
+
+ // Determine what type of (sub)model should be built if applicable.
+ // Lookup the proper subModelType in 'this._subModels'.
+ if ( this._subModels && this.prototype.subModelTypeAttribute in attributes ) {
+ var subModelTypeAttribute = attributes[ this.prototype.subModelTypeAttribute ];
+ var subModelType = this._subModels[ subModelTypeAttribute ];
+ if ( subModelType ) {
+ model = subModelType;
+ }
+ }
+
+ return new model( attributes, options );
+ },
+
+ /**
+ *
+ */
+ initializeModelHierarchy: function() {
+ // If we're here for the first time, try to determine if this modelType has a 'superModel'.
+ if ( _.isUndefined( this._superModel ) || _.isNull( this._superModel ) ) {
+ Backbone.Relational.store.setupSuperModel( this );
+
+ // If a superModel has been found, copy relations from the _superModel if they haven't been
+ // inherited automatically (due to a redefinition of 'relations').
+ // Otherwise, make sure we don't get here again for this type by making '_superModel' false so we fail
+ // the isUndefined/isNull check next time.
+ if ( this._superModel && this._superModel.prototype.relations ) {
+ // Find relations that exist on the `_superModel`, but not yet on this model.
+ var inheritedRelations = _.select( this._superModel.prototype.relations || [], function( superRel ) {
+ return !_.any( this.prototype.relations || [], function( rel ) {
+ return superRel.relatedModel === rel.relatedModel && superRel.key === rel.key;
+ }, this );
+ }, this );
+
+ this.prototype.relations = inheritedRelations.concat( this.prototype.relations );
+ }
+ else {
+ this._superModel = false;
+ }
+ }
+
+ // If we came here through 'build' for a model that has 'subModelTypes', and not all of them have been resolved yet, try to resolve each.
+ if ( this.prototype.subModelTypes && _.keys( this.prototype.subModelTypes ).length !== _.keys( this._subModels ).length ) {
+ _.each( this.prototype.subModelTypes || [], function( subModelTypeName ) {
+ var subModelType = Backbone.Relational.store.getObjectByName( subModelTypeName );
+ subModelType && subModelType.initializeModelHierarchy();
+ });
+ }
+ },
+
+ /**
+ * Find an instance of `this` type in 'Backbone.Relational.store'.
+ * - If `attributes` is a string or a number, `findOrCreate` will just query the `store` and return a model if found.
+ * - If `attributes` is an object and is found in the store, the model will be updated with `attributes` unless `options.update` is `false`.
+ * Otherwise, a new model is created with `attributes` (unless `options.create` is explicitly set to `false`).
+ * @param {Object|String|Number} attributes Either a model's id, or the attributes used to create or update a model.
+ * @param {Object} [options]
+ * @param {Boolean} [options.create=true]
+ * @param {Boolean} [options.merge=true]
+ * @param {Boolean} [options.parse=false]
+ * @return {Backbone.RelationalModel}
+ */
+ findOrCreate: function( attributes, options ) {
+ options || ( options = {} );
+ var parsedAttributes = ( _.isObject( attributes ) && options.parse && this.prototype.parse ) ?
+ this.prototype.parse( attributes ) : attributes;
+
+ // Try to find an instance of 'this' model type in the store
+ var model = Backbone.Relational.store.find( this, parsedAttributes );
+
+ // If we found an instance, update it with the data in 'item' (unless 'options.merge' is false).
+ // If not, create an instance (unless 'options.create' is false).
+ if ( _.isObject( attributes ) ) {
+ if ( model && options.merge !== false ) {
+ // Make sure `options.collection` doesn't cascade to nested models
+ delete options.collection;
+
+ model.set( parsedAttributes, options );
+ }
+ else if ( !model && options.create !== false ) {
+ model = this.build( attributes, options );
+ }
+ }
+
+ return model;
+ }
+ });
+ _.extend( Backbone.RelationalModel.prototype, Backbone.Semaphore );
+
+ /**
+ * Override Backbone.Collection._prepareModel, so objects will be built using the correct type
+ * if the collection.model has subModels.
+ * Attempts to find a model for `attrs` in Backbone.store through `findOrCreate`
+ * (which sets the new properties on it if found), or instantiates a new model.
+ */
+ Backbone.Collection.prototype.__prepareModel = Backbone.Collection.prototype._prepareModel;
+ Backbone.Collection.prototype._prepareModel = function ( attrs, options ) {
+ var model;
+
+ if ( attrs instanceof Backbone.Model ) {
+ if ( !attrs.collection ) {
+ attrs.collection = this;
+ }
+ model = attrs;
+ }
+ else {
+ options || ( options = {} );
+ options.collection = this;
+
+ if ( typeof this.model.findOrCreate !== 'undefined' ) {
+ model = this.model.findOrCreate( attrs, options );
+ }
+ else {
+ model = new this.model( attrs, options );
+ }
+
+ if ( model && model.isNew() && !model._validate( attrs, options ) ) {
+ this.trigger( 'invalid', this, attrs, options );
+ model = false;
+ }
+ }
+
+ return model;
+ };
+
+
+ /**
+ * Override Backbone.Collection.set, so we'll create objects from attributes where required,
+ * and update the existing models. Also, trigger 'relational:add'.
+ */
+ var set = Backbone.Collection.prototype.__set = Backbone.Collection.prototype.set;
+ Backbone.Collection.prototype.set = function( models, options ) {
+ // Short-circuit if this Collection doesn't hold RelationalModels
+ if ( !( this.model.prototype instanceof Backbone.RelationalModel ) ) {
+ return set.apply( this, arguments );
+ }
+
+ if ( options && options.parse ) {
+ models = this.parse( models, options );
+ }
+
+ if ( !_.isArray( models ) ) {
+ models = models ? [ models ] : [];
+ }
+
+ var newModels = [],
+ toAdd = [];
+
+ //console.debug( 'calling add on coll=%o; model=%o, options=%o', this, models, options );
+ _.each( models, function( model ) {
+ if ( !( model instanceof Backbone.Model ) ) {
+ model = Backbone.Collection.prototype._prepareModel.call( this, model, options );
+ }
+
+ if ( model ) {
+ toAdd.push( model );
+
+ if ( !( this.get( model ) || this.get( model.cid ) ) ) {
+ newModels.push( model );
+ }
+ // If we arrive in `add` while performing a `set` (after a create, so the model gains an `id`),
+ // we may get here before `_onModelEvent` has had the chance to update `_byId`.
+ else if ( model.id != null ) {
+ this._byId[ model.id ] = model;
+ }
+ }
+ }, this );
+
+ // Add 'models' in a single batch, so the original add will only be called once (and thus 'sort', etc).
+ // If `parse` was specified, the collection and contained models have been parsed now.
+ set.call( this, toAdd, _.defaults( { parse: false }, options ) );
+
+ _.each( newModels, function( model ) {
+ // Fire a `relational:add` event for any model in `newModels` that has actually been added to the collection.
+ if ( this.get( model ) || this.get( model.cid ) ) {
+ this.trigger( 'relational:add', model, this, options );
+ }
+ }, this );
+
+ return this;
+ };
+
+ /**
+ * Override 'Backbone.Collection.remove' to trigger 'relational:remove'.
+ */
+ var remove = Backbone.Collection.prototype.__remove = Backbone.Collection.prototype.remove;
+ Backbone.Collection.prototype.remove = function( models, options ) {
+ // Short-circuit if this Collection doesn't hold RelationalModels
+ if ( !( this.model.prototype instanceof Backbone.RelationalModel ) ) {
+ return remove.apply( this, arguments );
+ }
+
+ models = _.isArray( models ) ? models.slice() : [ models ];
+ options || ( options = {} );
+
+ var toRemove = [];
+
+ //console.debug('calling remove on coll=%o; models=%o, options=%o', this, models, options );
+ _.each( models, function( model ) {
+ model = this.get( model ) || this.get( model.cid );
+ model && toRemove.push( model );
+ }, this );
+
+ if ( toRemove.length ) {
+ remove.call( this, toRemove, options );
+
+ _.each( toRemove, function( model ) {
+ this.trigger('relational:remove', model, this, options);
+ }, this );
+ }
+
+ return this;
+ };
+
+ /**
+ * Override 'Backbone.Collection.reset' to trigger 'relational:reset'.
+ */
+ var reset = Backbone.Collection.prototype.__reset = Backbone.Collection.prototype.reset;
+ Backbone.Collection.prototype.reset = function( models, options ) {
+ options = _.extend( { merge: true }, options );
+ reset.call( this, models, options );
+
+ if ( this.model.prototype instanceof Backbone.RelationalModel ) {
+ this.trigger( 'relational:reset', this, options );
+ }
+
+ return this;
+ };
+
+ /**
+ * Override 'Backbone.Collection.sort' to trigger 'relational:reset'.
+ */
+ var sort = Backbone.Collection.prototype.__sort = Backbone.Collection.prototype.sort;
+ Backbone.Collection.prototype.sort = function( options ) {
+ sort.call( this, options );
+
+ if ( this.model.prototype instanceof Backbone.RelationalModel ) {
+ this.trigger( 'relational:reset', this, options );
+ }
+
+ return this;
+ };
+
+ /**
+ * Override 'Backbone.Collection.trigger' so 'add', 'remove' and 'reset' events are queued until relations
+ * are ready.
+ */
+ var trigger = Backbone.Collection.prototype.__trigger = Backbone.Collection.prototype.trigger;
+ Backbone.Collection.prototype.trigger = function( eventName ) {
+ // Short-circuit if this Collection doesn't hold RelationalModels
+ if ( !( this.model.prototype instanceof Backbone.RelationalModel ) ) {
+ return trigger.apply( this, arguments );
+ }
+
+ if ( eventName === 'add' || eventName === 'remove' || eventName === 'reset' ) {
+ var dit = this,
+ args = arguments;
+
+ if ( _.isObject( args[ 3 ] ) ) {
+ args = _.toArray( args );
+ // the fourth argument is the option object.
+ // we need to clone it, as it could be modified while we wait on the eventQueue to be unblocked
+ args[ 3 ] = _.clone( args[ 3 ] );
+ }
+
+ Backbone.Relational.eventQueue.add( function() {
+ trigger.apply( dit, args );
+ });
+ }
+ else {
+ trigger.apply( this, arguments );
+ }
+
+ return this;
+ };
+
+ // Override .extend() to automatically call .setup()
+ Backbone.RelationalModel.extend = function( protoProps, classProps ) {
+ var child = Backbone.Model.extend.apply( this, arguments );
+
+ child.setup( this );
+
+ return child;
+ };
+})();
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/src/ldt/ldt/static/ldt/js/backbone.js Fri Oct 02 10:24:05 2015 +0200
@@ -0,0 +1,1894 @@
+// Backbone.js 1.2.3
+
+// (c) 2010-2015 Jeremy Ashkenas, DocumentCloud and Investigative Reporters & Editors
+// Backbone may be freely distributed under the MIT license.
+// For all details and documentation:
+// http://backbonejs.org
+
+(function(factory) {
+
+ // Establish the root object, `window` (`self`) in the browser, or `global` on the server.
+ // We use `self` instead of `window` for `WebWorker` support.
+ var root = (typeof self == 'object' && self.self == self && self) ||
+ (typeof global == 'object' && global.global == global && global);
+
+ // Set up Backbone appropriately for the environment. Start with AMD.
+ if (typeof define === 'function' && define.amd) {
+ define(['underscore', 'jquery', 'exports'], function(_, $, exports) {
+ // Export global even in AMD case in case this script is loaded with
+ // others that may still expect a global Backbone.
+ root.Backbone = factory(root, exports, _, $);
+ });
+
+ // Next for Node.js or CommonJS. jQuery may not be needed as a module.
+ } else if (typeof exports !== 'undefined') {
+ var _ = require('underscore'), $;
+ try { $ = require('jquery'); } catch(e) {}
+ factory(root, exports, _, $);
+
+ // Finally, as a browser global.
+ } else {
+ root.Backbone = factory(root, {}, root._, (root.jQuery || root.Zepto || root.ender || root.$));
+ }
+
+}(function(root, Backbone, _, $) {
+
+ // Initial Setup
+ // -------------
+
+ // Save the previous value of the `Backbone` variable, so that it can be
+ // restored later on, if `noConflict` is used.
+ var previousBackbone = root.Backbone;
+
+ // Create a local reference to a common array method we'll want to use later.
+ var slice = Array.prototype.slice;
+
+ // Current version of the library. Keep in sync with `package.json`.
+ Backbone.VERSION = '1.2.3';
+
+ // For Backbone's purposes, jQuery, Zepto, Ender, or My Library (kidding) owns
+ // the `$` variable.
+ Backbone.$ = $;
+
+ // Runs Backbone.js in *noConflict* mode, returning the `Backbone` variable
+ // to its previous owner. Returns a reference to this Backbone object.
+ Backbone.noConflict = function() {
+ root.Backbone = previousBackbone;
+ return this;
+ };
+
+ // Turn on `emulateHTTP` to support legacy HTTP servers. Setting this option
+ // will fake `"PATCH"`, `"PUT"` and `"DELETE"` requests via the `_method` parameter and
+ // set a `X-Http-Method-Override` header.
+ Backbone.emulateHTTP = false;
+
+ // Turn on `emulateJSON` to support legacy servers that can't deal with direct
+ // `application/json` requests ... this will encode the body as
+ // `application/x-www-form-urlencoded` instead and will send the model in a
+ // form param named `model`.
+ Backbone.emulateJSON = false;
+
+ // Proxy Backbone class methods to Underscore functions, wrapping the model's
+ // `attributes` object or collection's `models` array behind the scenes.
+ //
+ // collection.filter(function(model) { return model.get('age') > 10 });
+ // collection.each(this.addView);
+ //
+ // `Function#apply` can be slow so we use the method's arg count, if we know it.
+ var addMethod = function(length, method, attribute) {
+ switch (length) {
+ case 1: return function() {
+ return _[method](this[attribute]);
+ };
+ case 2: return function(value) {
+ return _[method](this[attribute], value);
+ };
+ case 3: return function(iteratee, context) {
+ return _[method](this[attribute], cb(iteratee, this), context);
+ };
+ case 4: return function(iteratee, defaultVal, context) {
+ return _[method](this[attribute], cb(iteratee, this), defaultVal, context);
+ };
+ default: return function() {
+ var args = slice.call(arguments);
+ args.unshift(this[attribute]);
+ return _[method].apply(_, args);
+ };
+ }
+ };
+ var addUnderscoreMethods = function(Class, methods, attribute) {
+ _.each(methods, function(length, method) {
+ if (_[method]) Class.prototype[method] = addMethod(length, method, attribute);
+ });
+ };
+
+ // Support `collection.sortBy('attr')` and `collection.findWhere({id: 1})`.
+ var cb = function(iteratee, instance) {
+ if (_.isFunction(iteratee)) return iteratee;
+ if (_.isObject(iteratee) && !instance._isModel(iteratee)) return modelMatcher(iteratee);
+ if (_.isString(iteratee)) return function(model) { return model.get(iteratee); };
+ return iteratee;
+ };
+ var modelMatcher = function(attrs) {
+ var matcher = _.matches(attrs);
+ return function(model) {
+ return matcher(model.attributes);
+ };
+ };
+
+ // Backbone.Events
+ // ---------------
+
+ // A module that can be mixed in to *any object* in order to provide it with
+ // a custom event channel. You may bind a callback to an event with `on` or
+ // remove with `off`; `trigger`-ing an event fires all callbacks in
+ // succession.
+ //
+ // var object = {};
+ // _.extend(object, Backbone.Events);
+ // object.on('expand', function(){ alert('expanded'); });
+ // object.trigger('expand');
+ //
+ var Events = Backbone.Events = {};
+
+ // Regular expression used to split event strings.
+ var eventSplitter = /\s+/;
+
+ // Iterates over the standard `event, callback` (as well as the fancy multiple
+ // space-separated events `"change blur", callback` and jQuery-style event
+ // maps `{event: callback}`).
+ var eventsApi = function(iteratee, events, name, callback, opts) {
+ var i = 0, names;
+ if (name && typeof name === 'object') {
+ // Handle event maps.
+ if (callback !== void 0 && 'context' in opts && opts.context === void 0) opts.context = callback;
+ for (names = _.keys(name); i < names.length ; i++) {
+ events = eventsApi(iteratee, events, names[i], name[names[i]], opts);
+ }
+ } else if (name && eventSplitter.test(name)) {
+ // Handle space separated event names by delegating them individually.
+ for (names = name.split(eventSplitter); i < names.length; i++) {
+ events = iteratee(events, names[i], callback, opts);
+ }
+ } else {
+ // Finally, standard events.
+ events = iteratee(events, name, callback, opts);
+ }
+ return events;
+ };
+
+ // Bind an event to a `callback` function. Passing `"all"` will bind
+ // the callback to all events fired.
+ Events.on = function(name, callback, context) {
+ return internalOn(this, name, callback, context);
+ };
+
+ // Guard the `listening` argument from the public API.
+ var internalOn = function(obj, name, callback, context, listening) {
+ obj._events = eventsApi(onApi, obj._events || {}, name, callback, {
+ context: context,
+ ctx: obj,
+ listening: listening
+ });
+
+ if (listening) {
+ var listeners = obj._listeners || (obj._listeners = {});
+ listeners[listening.id] = listening;
+ }
+
+ return obj;
+ };
+
+ // Inversion-of-control versions of `on`. Tell *this* object to listen to
+ // an event in another object... keeping track of what it's listening to
+ // for easier unbinding later.
+ Events.listenTo = function(obj, name, callback) {
+ if (!obj) return this;
+ var id = obj._listenId || (obj._listenId = _.uniqueId('l'));
+ var listeningTo = this._listeningTo || (this._listeningTo = {});
+ var listening = listeningTo[id];
+
+ // This object is not listening to any other events on `obj` yet.
+ // Setup the necessary references to track the listening callbacks.
+ if (!listening) {
+ var thisId = this._listenId || (this._listenId = _.uniqueId('l'));
+ listening = listeningTo[id] = {obj: obj, objId: id, id: thisId, listeningTo: listeningTo, count: 0};
+ }
+
+ // Bind callbacks on obj, and keep track of them on listening.
+ internalOn(obj, name, callback, this, listening);
+ return this;
+ };
+
+ // The reducing API that adds a callback to the `events` object.
+ var onApi = function(events, name, callback, options) {
+ if (callback) {
+ var handlers = events[name] || (events[name] = []);
+ var context = options.context, ctx = options.ctx, listening = options.listening;
+ if (listening) listening.count++;
+
+ handlers.push({ callback: callback, context: context, ctx: context || ctx, listening: listening });
+ }
+ return events;
+ };
+
+ // Remove one or many callbacks. If `context` is null, removes all
+ // callbacks with that function. If `callback` is null, removes all
+ // callbacks for the event. If `name` is null, removes all bound
+ // callbacks for all events.
+ Events.off = function(name, callback, context) {
+ if (!this._events) return this;
+ this._events = eventsApi(offApi, this._events, name, callback, {
+ context: context,
+ listeners: this._listeners
+ });
+ return this;
+ };
+
+ // Tell this object to stop listening to either specific events ... or
+ // to every object it's currently listening to.
+ Events.stopListening = function(obj, name, callback) {
+ var listeningTo = this._listeningTo;
+ if (!listeningTo) return this;
+
+ var ids = obj ? [obj._listenId] : _.keys(listeningTo);
+
+ for (var i = 0; i < ids.length; i++) {
+ var listening = listeningTo[ids[i]];
+
+ // If listening doesn't exist, this object is not currently
+ // listening to obj. Break out early.
+ if (!listening) break;
+
+ listening.obj.off(name, callback, this);
+ }
+ if (_.isEmpty(listeningTo)) this._listeningTo = void 0;
+
+ return this;
+ };
+
+ // The reducing API that removes a callback from the `events` object.
+ var offApi = function(events, name, callback, options) {
+ if (!events) return;
+
+ var i = 0, listening;
+ var context = options.context, listeners = options.listeners;
+
+ // Delete all events listeners and "drop" events.
+ if (!name && !callback && !context) {
+ var ids = _.keys(listeners);
+ for (; i < ids.length; i++) {
+ listening = listeners[ids[i]];
+ delete listeners[listening.id];
+ delete listening.listeningTo[listening.objId];
+ }
+ return;
+ }
+
+ var names = name ? [name] : _.keys(events);
+ for (; i < names.length; i++) {
+ name = names[i];
+ var handlers = events[name];
+
+ // Bail out if there are no events stored.
+ if (!handlers) break;
+
+ // Replace events if there are any remaining. Otherwise, clean up.
+ var remaining = [];
+ for (var j = 0; j < handlers.length; j++) {
+ var handler = handlers[j];
+ if (
+ callback && callback !== handler.callback &&
+ callback !== handler.callback._callback ||
+ context && context !== handler.context
+ ) {
+ remaining.push(handler);
+ } else {
+ listening = handler.listening;
+ if (listening && --listening.count === 0) {
+ delete listeners[listening.id];
+ delete listening.listeningTo[listening.objId];
+ }
+ }
+ }
+
+ // Update tail event if the list has any events. Otherwise, clean up.
+ if (remaining.length) {
+ events[name] = remaining;
+ } else {
+ delete events[name];
+ }
+ }
+ if (_.size(events)) return events;
+ };
+
+ // Bind an event to only be triggered a single time. After the first time
+ // the callback is invoked, its listener will be removed. If multiple events
+ // are passed in using the space-separated syntax, the handler will fire
+ // once for each event, not once for a combination of all events.
+ Events.once = function(name, callback, context) {
+ // Map the event into a `{event: once}` object.
+ var events = eventsApi(onceMap, {}, name, callback, _.bind(this.off, this));
+ return this.on(events, void 0, context);
+ };
+
+ // Inversion-of-control versions of `once`.
+ Events.listenToOnce = function(obj, name, callback) {
+ // Map the event into a `{event: once}` object.
+ var events = eventsApi(onceMap, {}, name, callback, _.bind(this.stopListening, this, obj));
+ return this.listenTo(obj, events);
+ };
+
+ // Reduces the event callbacks into a map of `{event: onceWrapper}`.
+ // `offer` unbinds the `onceWrapper` after it has been called.
+ var onceMap = function(map, name, callback, offer) {
+ if (callback) {
+ var once = map[name] = _.once(function() {
+ offer(name, once);
+ callback.apply(this, arguments);
+ });
+ once._callback = callback;
+ }
+ return map;
+ };
+
+ // Trigger one or many events, firing all bound callbacks. Callbacks are
+ // passed the same arguments as `trigger` is, apart from the event name
+ // (unless you're listening on `"all"`, which will cause your callback to
+ // receive the true name of the event as the first argument).
+ Events.trigger = function(name) {
+ if (!this._events) return this;
+
+ var length = Math.max(0, arguments.length - 1);
+ var args = Array(length);
+ for (var i = 0; i < length; i++) args[i] = arguments[i + 1];
+
+ eventsApi(triggerApi, this._events, name, void 0, args);
+ return this;
+ };
+
+ // Handles triggering the appropriate event callbacks.
+ var triggerApi = function(objEvents, name, cb, args) {
+ if (objEvents) {
+ var events = objEvents[name];
+ var allEvents = objEvents.all;
+ if (events && allEvents) allEvents = allEvents.slice();
+ if (events) triggerEvents(events, args);
+ if (allEvents) triggerEvents(allEvents, [name].concat(args));
+ }
+ return objEvents;
+ };
+
+ // A difficult-to-believe, but optimized internal dispatch function for
+ // triggering events. Tries to keep the usual cases speedy (most internal
+ // Backbone events have 3 arguments).
+ var triggerEvents = function(events, args) {
+ var ev, i = -1, l = events.length, a1 = args[0], a2 = args[1], a3 = args[2];
+ switch (args.length) {
+ case 0: while (++i < l) (ev = events[i]).callback.call(ev.ctx); return;
+ case 1: while (++i < l) (ev = events[i]).callback.call(ev.ctx, a1); return;
+ case 2: while (++i < l) (ev = events[i]).callback.call(ev.ctx, a1, a2); return;
+ case 3: while (++i < l) (ev = events[i]).callback.call(ev.ctx, a1, a2, a3); return;
+ default: while (++i < l) (ev = events[i]).callback.apply(ev.ctx, args); return;
+ }
+ };
+
+ // Aliases for backwards compatibility.
+ Events.bind = Events.on;
+ Events.unbind = Events.off;
+
+ // Allow the `Backbone` object to serve as a global event bus, for folks who
+ // want global "pubsub" in a convenient place.
+ _.extend(Backbone, Events);
+
+ // Backbone.Model
+ // --------------
+
+ // Backbone **Models** are the basic data object in the framework --
+ // frequently representing a row in a table in a database on your server.
+ // A discrete chunk of data and a bunch of useful, related methods for
+ // performing computations and transformations on that data.
+
+ // Create a new model with the specified attributes. A client id (`cid`)
+ // is automatically generated and assigned for you.
+ var Model = Backbone.Model = function(attributes, options) {
+ var attrs = attributes || {};
+ options || (options = {});
+ this.cid = _.uniqueId(this.cidPrefix);
+ this.attributes = {};
+ if (options.collection) this.collection = options.collection;
+ if (options.parse) attrs = this.parse(attrs, options) || {};
+ attrs = _.defaults({}, attrs, _.result(this, 'defaults'));
+ this.set(attrs, options);
+ this.changed = {};
+ this.initialize.apply(this, arguments);
+ };
+
+ // Attach all inheritable methods to the Model prototype.
+ _.extend(Model.prototype, Events, {
+
+ // A hash of attributes whose current and previous value differ.
+ changed: null,
+
+ // The value returned during the last failed validation.
+ validationError: null,
+
+ // The default name for the JSON `id` attribute is `"id"`. MongoDB and
+ // CouchDB users may want to set this to `"_id"`.
+ idAttribute: 'id',
+
+ // The prefix is used to create the client id which is used to identify models locally.
+ // You may want to override this if you're experiencing name clashes with model ids.
+ cidPrefix: 'c',
+
+ // Initialize is an empty function by default. Override it with your own
+ // initialization logic.
+ initialize: function(){},
+
+ // Return a copy of the model's `attributes` object.
+ toJSON: function(options) {
+ return _.clone(this.attributes);
+ },
+
+ // Proxy `Backbone.sync` by default -- but override this if you need
+ // custom syncing semantics for *this* particular model.
+ sync: function() {
+ return Backbone.sync.apply(this, arguments);
+ },
+
+ // Get the value of an attribute.
+ get: function(attr) {
+ return this.attributes[attr];
+ },
+
+ // Get the HTML-escaped value of an attribute.
+ escape: function(attr) {
+ return _.escape(this.get(attr));
+ },
+
+ // Returns `true` if the attribute contains a value that is not null
+ // or undefined.
+ has: function(attr) {
+ return this.get(attr) != null;
+ },
+
+ // Special-cased proxy to underscore's `_.matches` method.
+ matches: function(attrs) {
+ return !!_.iteratee(attrs, this)(this.attributes);
+ },
+
+ // Set a hash of model attributes on the object, firing `"change"`. This is
+ // the core primitive operation of a model, updating the data and notifying
+ // anyone who needs to know about the change in state. The heart of the beast.
+ set: function(key, val, options) {
+ if (key == null) return this;
+
+ // Handle both `"key", value` and `{key: value}` -style arguments.
+ var attrs;
+ if (typeof key === 'object') {
+ attrs = key;
+ options = val;
+ } else {
+ (attrs = {})[key] = val;
+ }
+
+ options || (options = {});
+
+ // Run validation.
+ if (!this._validate(attrs, options)) return false;
+
+ // Extract attributes and options.
+ var unset = options.unset;
+ var silent = options.silent;
+ var changes = [];
+ var changing = this._changing;
+ this._changing = true;
+
+ if (!changing) {
+ this._previousAttributes = _.clone(this.attributes);
+ this.changed = {};
+ }
+
+ var current = this.attributes;
+ var changed = this.changed;
+ var prev = this._previousAttributes;
+
+ // For each `set` attribute, update or delete the current value.
+ for (var attr in attrs) {
+ val = attrs[attr];
+ if (!_.isEqual(current[attr], val)) changes.push(attr);
+ if (!_.isEqual(prev[attr], val)) {
+ changed[attr] = val;
+ } else {
+ delete changed[attr];
+ }
+ unset ? delete current[attr] : current[attr] = val;
+ }
+
+ // Update the `id`.
+ this.id = this.get(this.idAttribute);
+
+ // Trigger all relevant attribute changes.
+ if (!silent) {
+ if (changes.length) this._pending = options;
+ for (var i = 0; i < changes.length; i++) {
+ this.trigger('change:' + changes[i], this, current[changes[i]], options);
+ }
+ }
+
+ // You might be wondering why there's a `while` loop here. Changes can
+ // be recursively nested within `"change"` events.
+ if (changing) return this;
+ if (!silent) {
+ while (this._pending) {
+ options = this._pending;
+ this._pending = false;
+ this.trigger('change', this, options);
+ }
+ }
+ this._pending = false;
+ this._changing = false;
+ return this;
+ },
+
+ // Remove an attribute from the model, firing `"change"`. `unset` is a noop
+ // if the attribute doesn't exist.
+ unset: function(attr, options) {
+ return this.set(attr, void 0, _.extend({}, options, {unset: true}));
+ },
+
+ // Clear all attributes on the model, firing `"change"`.
+ clear: function(options) {
+ var attrs = {};
+ for (var key in this.attributes) attrs[key] = void 0;
+ return this.set(attrs, _.extend({}, options, {unset: true}));
+ },
+
+ // Determine if the model has changed since the last `"change"` event.
+ // If you specify an attribute name, determine if that attribute has changed.
+ hasChanged: function(attr) {
+ if (attr == null) return !_.isEmpty(this.changed);
+ return _.has(this.changed, attr);
+ },
+
+ // Return an object containing all the attributes that have changed, or
+ // false if there are no changed attributes. Useful for determining what
+ // parts of a view need to be updated and/or what attributes need to be
+ // persisted to the server. Unset attributes will be set to undefined.
+ // You can also pass an attributes object to diff against the model,
+ // determining if there *would be* a change.
+ changedAttributes: function(diff) {
+ if (!diff) return this.hasChanged() ? _.clone(this.changed) : false;
+ var old = this._changing ? this._previousAttributes : this.attributes;
+ var changed = {};
+ for (var attr in diff) {
+ var val = diff[attr];
+ if (_.isEqual(old[attr], val)) continue;
+ changed[attr] = val;
+ }
+ return _.size(changed) ? changed : false;
+ },
+
+ // Get the previous value of an attribute, recorded at the time the last
+ // `"change"` event was fired.
+ previous: function(attr) {
+ if (attr == null || !this._previousAttributes) return null;
+ return this._previousAttributes[attr];
+ },
+
+ // Get all of the attributes of the model at the time of the previous
+ // `"change"` event.
+ previousAttributes: function() {
+ return _.clone(this._previousAttributes);
+ },
+
+ // Fetch the model from the server, merging the response with the model's
+ // local attributes. Any changed attributes will trigger a "change" event.
+ fetch: function(options) {
+ options = _.extend({parse: true}, options);
+ var model = this;
+ var success = options.success;
+ options.success = function(resp) {
+ var serverAttrs = options.parse ? model.parse(resp, options) : resp;
+ if (!model.set(serverAttrs, options)) return false;
+ if (success) success.call(options.context, model, resp, options);
+ model.trigger('sync', model, resp, options);
+ };
+ wrapError(this, options);
+ return this.sync('read', this, options);
+ },
+
+ // Set a hash of model attributes, and sync the model to the server.
+ // If the server returns an attributes hash that differs, the model's
+ // state will be `set` again.
+ save: function(key, val, options) {
+ // Handle both `"key", value` and `{key: value}` -style arguments.
+ var attrs;
+ if (key == null || typeof key === 'object') {
+ attrs = key;
+ options = val;
+ } else {
+ (attrs = {})[key] = val;
+ }
+
+ options = _.extend({validate: true, parse: true}, options);
+ var wait = options.wait;
+
+ // If we're not waiting and attributes exist, save acts as
+ // `set(attr).save(null, opts)` with validation. Otherwise, check if
+ // the model will be valid when the attributes, if any, are set.
+ if (attrs && !wait) {
+ if (!this.set(attrs, options)) return false;
+ } else {
+ if (!this._validate(attrs, options)) return false;
+ }
+
+ // After a successful server-side save, the client is (optionally)
+ // updated with the server-side state.
+ var model = this;
+ var success = options.success;
+ var attributes = this.attributes;
+ options.success = function(resp) {
+ // Ensure attributes are restored during synchronous saves.
+ model.attributes = attributes;
+ var serverAttrs = options.parse ? model.parse(resp, options) : resp;
+ if (wait) serverAttrs = _.extend({}, attrs, serverAttrs);
+ if (serverAttrs && !model.set(serverAttrs, options)) return false;
+ if (success) success.call(options.context, model, resp, options);
+ model.trigger('sync', model, resp, options);
+ };
+ wrapError(this, options);
+
+ // Set temporary attributes if `{wait: true}` to properly find new ids.
+ if (attrs && wait) this.attributes = _.extend({}, attributes, attrs);
+
+ var method = this.isNew() ? 'create' : (options.patch ? 'patch' : 'update');
+ if (method === 'patch' && !options.attrs) options.attrs = attrs;
+ var xhr = this.sync(method, this, options);
+
+ // Restore attributes.
+ this.attributes = attributes;
+
+ return xhr;
+ },
+
+ // Destroy this model on the server if it was already persisted.
+ // Optimistically removes the model from its collection, if it has one.
+ // If `wait: true` is passed, waits for the server to respond before removal.
+ destroy: function(options) {
+ options = options ? _.clone(options) : {};
+ var model = this;
+ var success = options.success;
+ var wait = options.wait;
+
+ var destroy = function() {
+ model.stopListening();
+ model.trigger('destroy', model, model.collection, options);
+ };
+
+ options.success = function(resp) {
+ if (wait) destroy();
+ if (success) success.call(options.context, model, resp, options);
+ if (!model.isNew()) model.trigger('sync', model, resp, options);
+ };
+
+ var xhr = false;
+ if (this.isNew()) {
+ _.defer(options.success);
+ } else {
+ wrapError(this, options);
+ xhr = this.sync('delete', this, options);
+ }
+ if (!wait) destroy();
+ return xhr;
+ },
+
+ // Default URL for the model's representation on the server -- if you're
+ // using Backbone's restful methods, override this to change the endpoint
+ // that will be called.
+ url: function() {
+ var base =
+ _.result(this, 'urlRoot') ||
+ _.result(this.collection, 'url') ||
+ urlError();
+ if (this.isNew()) return base;
+ var id = this.get(this.idAttribute);
+ return base.replace(/[^\/]$/, '$&/') + encodeURIComponent(id);
+ },
+
+ // **parse** converts a response into the hash of attributes to be `set` on
+ // the model. The default implementation is just to pass the response along.
+ parse: function(resp, options) {
+ return resp;
+ },
+
+ // Create a new model with identical attributes to this one.
+ clone: function() {
+ return new this.constructor(this.attributes);
+ },
+
+ // A model is new if it has never been saved to the server, and lacks an id.
+ isNew: function() {
+ return !this.has(this.idAttribute);
+ },
+
+ // Check if the model is currently in a valid state.
+ isValid: function(options) {
+ return this._validate({}, _.defaults({validate: true}, options));
+ },
+
+ // Run validation against the next complete set of model attributes,
+ // returning `true` if all is well. Otherwise, fire an `"invalid"` event.
+ _validate: function(attrs, options) {
+ if (!options.validate || !this.validate) return true;
+ attrs = _.extend({}, this.attributes, attrs);
+ var error = this.validationError = this.validate(attrs, options) || null;
+ if (!error) return true;
+ this.trigger('invalid', this, error, _.extend(options, {validationError: error}));
+ return false;
+ }
+
+ });
+
+ // Underscore methods that we want to implement on the Model, mapped to the
+ // number of arguments they take.
+ var modelMethods = { keys: 1, values: 1, pairs: 1, invert: 1, pick: 0,
+ omit: 0, chain: 1, isEmpty: 1 };
+
+ // Mix in each Underscore method as a proxy to `Model#attributes`.
+ addUnderscoreMethods(Model, modelMethods, 'attributes');
+
+ // Backbone.Collection
+ // -------------------
+
+ // If models tend to represent a single row of data, a Backbone Collection is
+ // more analogous to a table full of data ... or a small slice or page of that
+ // table, or a collection of rows that belong together for a particular reason
+ // -- all of the messages in this particular folder, all of the documents
+ // belonging to this particular author, and so on. Collections maintain
+ // indexes of their models, both in order, and for lookup by `id`.
+
+ // Create a new **Collection**, perhaps to contain a specific type of `model`.
+ // If a `comparator` is specified, the Collection will maintain
+ // its models in sort order, as they're added and removed.
+ var Collection = Backbone.Collection = function(models, options) {
+ options || (options = {});
+ if (options.model) this.model = options.model;
+ if (options.comparator !== void 0) this.comparator = options.comparator;
+ this._reset();
+ this.initialize.apply(this, arguments);
+ if (models) this.reset(models, _.extend({silent: true}, options));
+ };
+
+ // Default options for `Collection#set`.
+ var setOptions = {add: true, remove: true, merge: true};
+ var addOptions = {add: true, remove: false};
+
+ // Splices `insert` into `array` at index `at`.
+ var splice = function(array, insert, at) {
+ at = Math.min(Math.max(at, 0), array.length);
+ var tail = Array(array.length - at);
+ var length = insert.length;
+ for (var i = 0; i < tail.length; i++) tail[i] = array[i + at];
+ for (i = 0; i < length; i++) array[i + at] = insert[i];
+ for (i = 0; i < tail.length; i++) array[i + length + at] = tail[i];
+ };
+
+ // Define the Collection's inheritable methods.
+ _.extend(Collection.prototype, Events, {
+
+ // The default model for a collection is just a **Backbone.Model**.
+ // This should be overridden in most cases.
+ model: Model,
+
+ // Initialize is an empty function by default. Override it with your own
+ // initialization logic.
+ initialize: function(){},
+
+ // The JSON representation of a Collection is an array of the
+ // models' attributes.
+ toJSON: function(options) {
+ return this.map(function(model) { return model.toJSON(options); });
+ },
+
+ // Proxy `Backbone.sync` by default.
+ sync: function() {
+ return Backbone.sync.apply(this, arguments);
+ },
+
+ // Add a model, or list of models to the set. `models` may be Backbone
+ // Models or raw JavaScript objects to be converted to Models, or any
+ // combination of the two.
+ add: function(models, options) {
+ return this.set(models, _.extend({merge: false}, options, addOptions));
+ },
+
+ // Remove a model, or a list of models from the set.
+ remove: function(models, options) {
+ options = _.extend({}, options);
+ var singular = !_.isArray(models);
+ models = singular ? [models] : _.clone(models);
+ var removed = this._removeModels(models, options);
+ if (!options.silent && removed) this.trigger('update', this, options);
+ return singular ? removed[0] : removed;
+ },
+
+ // Update a collection by `set`-ing a new list of models, adding new ones,
+ // removing models that are no longer present, and merging models that
+ // already exist in the collection, as necessary. Similar to **Model#set**,
+ // the core operation for updating the data contained by the collection.
+ set: function(models, options) {
+ if (models == null) return;
+
+ options = _.defaults({}, options, setOptions);
+ if (options.parse && !this._isModel(models)) models = this.parse(models, options);
+
+ var singular = !_.isArray(models);
+ models = singular ? [models] : models.slice();
+
+ var at = options.at;
+ if (at != null) at = +at;
+ if (at < 0) at += this.length + 1;
+
+ var set = [];
+ var toAdd = [];
+ var toRemove = [];
+ var modelMap = {};
+
+ var add = options.add;
+ var merge = options.merge;
+ var remove = options.remove;
+
+ var sort = false;
+ var sortable = this.comparator && (at == null) && options.sort !== false;
+ var sortAttr = _.isString(this.comparator) ? this.comparator : null;
+
+ // Turn bare objects into model references, and prevent invalid models
+ // from being added.
+ var model;
+ for (var i = 0; i < models.length; i++) {
+ model = models[i];
+
+ // If a duplicate is found, prevent it from being added and
+ // optionally merge it into the existing model.
+ var existing = this.get(model);
+ if (existing) {
+ if (merge && model !== existing) {
+ var attrs = this._isModel(model) ? model.attributes : model;
+ if (options.parse) attrs = existing.parse(attrs, options);
+ existing.set(attrs, options);
+ if (sortable && !sort) sort = existing.hasChanged(sortAttr);
+ }
+ if (!modelMap[existing.cid]) {
+ modelMap[existing.cid] = true;
+ set.push(existing);
+ }
+ models[i] = existing;
+
+ // If this is a new, valid model, push it to the `toAdd` list.
+ } else if (add) {
+ model = models[i] = this._prepareModel(model, options);
+ if (model) {
+ toAdd.push(model);
+ this._addReference(model, options);
+ modelMap[model.cid] = true;
+ set.push(model);
+ }
+ }
+ }
+
+ // Remove stale models.
+ if (remove) {
+ for (i = 0; i < this.length; i++) {
+ model = this.models[i];
+ if (!modelMap[model.cid]) toRemove.push(model);
+ }
+ if (toRemove.length) this._removeModels(toRemove, options);
+ }
+
+ // See if sorting is needed, update `length` and splice in new models.
+ var orderChanged = false;
+ var replace = !sortable && add && remove;
+ if (set.length && replace) {
+ orderChanged = this.length != set.length || _.some(this.models, function(model, index) {
+ return model !== set[index];
+ });
+ this.models.length = 0;
+ splice(this.models, set, 0);
+ this.length = this.models.length;
+ } else if (toAdd.length) {
+ if (sortable) sort = true;
+ splice(this.models, toAdd, at == null ? this.length : at);
+ this.length = this.models.length;
+ }
+
+ // Silently sort the collection if appropriate.
+ if (sort) this.sort({silent: true});
+
+ // Unless silenced, it's time to fire all appropriate add/sort events.
+ if (!options.silent) {
+ for (i = 0; i < toAdd.length; i++) {
+ if (at != null) options.index = at + i;
+ model = toAdd[i];
+ model.trigger('add', model, this, options);
+ }
+ if (sort || orderChanged) this.trigger('sort', this, options);
+ if (toAdd.length || toRemove.length) this.trigger('update', this, options);
+ }
+
+ // Return the added (or merged) model (or models).
+ return singular ? models[0] : models;
+ },
+
+ // When you have more items than you want to add or remove individually,
+ // you can reset the entire set with a new list of models, without firing
+ // any granular `add` or `remove` events. Fires `reset` when finished.
+ // Useful for bulk operations and optimizations.
+ reset: function(models, options) {
+ options = options ? _.clone(options) : {};
+ for (var i = 0; i < this.models.length; i++) {
+ this._removeReference(this.models[i], options);
+ }
+ options.previousModels = this.models;
+ this._reset();
+ models = this.add(models, _.extend({silent: true}, options));
+ if (!options.silent) this.trigger('reset', this, options);
+ return models;
+ },
+
+ // Add a model to the end of the collection.
+ push: function(model, options) {
+ return this.add(model, _.extend({at: this.length}, options));
+ },
+
+ // Remove a model from the end of the collection.
+ pop: function(options) {
+ var model = this.at(this.length - 1);
+ return this.remove(model, options);
+ },
+
+ // Add a model to the beginning of the collection.
+ unshift: function(model, options) {
+ return this.add(model, _.extend({at: 0}, options));
+ },
+
+ // Remove a model from the beginning of the collection.
+ shift: function(options) {
+ var model = this.at(0);
+ return this.remove(model, options);
+ },
+
+ // Slice out a sub-array of models from the collection.
+ slice: function() {
+ return slice.apply(this.models, arguments);
+ },
+
+ // Get a model from the set by id.
+ get: function(obj) {
+ if (obj == null) return void 0;
+ var id = this.modelId(this._isModel(obj) ? obj.attributes : obj);
+ return this._byId[obj] || this._byId[id] || this._byId[obj.cid];
+ },
+
+ // Get the model at the given index.
+ at: function(index) {
+ if (index < 0) index += this.length;
+ return this.models[index];
+ },
+
+ // Return models with matching attributes. Useful for simple cases of
+ // `filter`.
+ where: function(attrs, first) {
+ return this[first ? 'find' : 'filter'](attrs);
+ },
+
+ // Return the first model with matching attributes. Useful for simple cases
+ // of `find`.
+ findWhere: function(attrs) {
+ return this.where(attrs, true);
+ },
+
+ // Force the collection to re-sort itself. You don't need to call this under
+ // normal circumstances, as the set will maintain sort order as each item
+ // is added.
+ sort: function(options) {
+ var comparator = this.comparator;
+ if (!comparator) throw new Error('Cannot sort a set without a comparator');
+ options || (options = {});
+
+ var length = comparator.length;
+ if (_.isFunction(comparator)) comparator = _.bind(comparator, this);
+
+ // Run sort based on type of `comparator`.
+ if (length === 1 || _.isString(comparator)) {
+ this.models = this.sortBy(comparator);
+ } else {
+ this.models.sort(comparator);
+ }
+ if (!options.silent) this.trigger('sort', this, options);
+ return this;
+ },
+
+ // Pluck an attribute from each model in the collection.
+ pluck: function(attr) {
+ return _.invoke(this.models, 'get', attr);
+ },
+
+ // Fetch the default set of models for this collection, resetting the
+ // collection when they arrive. If `reset: true` is passed, the response
+ // data will be passed through the `reset` method instead of `set`.
+ fetch: function(options) {
+ options = _.extend({parse: true}, options);
+ var success = options.success;
+ var collection = this;
+ options.success = function(resp) {
+ var method = options.reset ? 'reset' : 'set';
+ collection[method](resp, options);
+ if (success) success.call(options.context, collection, resp, options);
+ collection.trigger('sync', collection, resp, options);
+ };
+ wrapError(this, options);
+ return this.sync('read', this, options);
+ },
+
+ // Create a new instance of a model in this collection. Add the model to the
+ // collection immediately, unless `wait: true` is passed, in which case we
+ // wait for the server to agree.
+ create: function(model, options) {
+ options = options ? _.clone(options) : {};
+ var wait = options.wait;
+ model = this._prepareModel(model, options);
+ if (!model) return false;
+ if (!wait) this.add(model, options);
+ var collection = this;
+ var success = options.success;
+ options.success = function(model, resp, callbackOpts) {
+ if (wait) collection.add(model, callbackOpts);
+ if (success) success.call(callbackOpts.context, model, resp, callbackOpts);
+ };
+ model.save(null, options);
+ return model;
+ },
+
+ // **parse** converts a response into a list of models to be added to the
+ // collection. The default implementation is just to pass it through.
+ parse: function(resp, options) {
+ return resp;
+ },
+
+ // Create a new collection with an identical list of models as this one.
+ clone: function() {
+ return new this.constructor(this.models, {
+ model: this.model,
+ comparator: this.comparator
+ });
+ },
+
+ // Define how to uniquely identify models in the collection.
+ modelId: function (attrs) {
+ return attrs[this.model.prototype.idAttribute || 'id'];
+ },
+
+ // Private method to reset all internal state. Called when the collection
+ // is first initialized or reset.
+ _reset: function() {
+ this.length = 0;
+ this.models = [];
+ this._byId = {};
+ },
+
+ // Prepare a hash of attributes (or other model) to be added to this
+ // collection.
+ _prepareModel: function(attrs, options) {
+ if (this._isModel(attrs)) {
+ if (!attrs.collection) attrs.collection = this;
+ return attrs;
+ }
+ options = options ? _.clone(options) : {};
+ options.collection = this;
+ var model = new this.model(attrs, options);
+ if (!model.validationError) return model;
+ this.trigger('invalid', this, model.validationError, options);
+ return false;
+ },
+
+ // Internal method called by both remove and set.
+ _removeModels: function(models, options) {
+ var removed = [];
+ for (var i = 0; i < models.length; i++) {
+ var model = this.get(models[i]);
+ if (!model) continue;
+
+ var index = this.indexOf(model);
+ this.models.splice(index, 1);
+ this.length--;
+
+ if (!options.silent) {
+ options.index = index;
+ model.trigger('remove', model, this, options);
+ }
+
+ removed.push(model);
+ this._removeReference(model, options);
+ }
+ return removed.length ? removed : false;
+ },
+
+ // Method for checking whether an object should be considered a model for
+ // the purposes of adding to the collection.
+ _isModel: function (model) {
+ return model instanceof Model;
+ },
+
+ // Internal method to create a model's ties to a collection.
+ _addReference: function(model, options) {
+ this._byId[model.cid] = model;
+ var id = this.modelId(model.attributes);
+ if (id != null) this._byId[id] = model;
+ model.on('all', this._onModelEvent, this);
+ },
+
+ // Internal method to sever a model's ties to a collection.
+ _removeReference: function(model, options) {
+ delete this._byId[model.cid];
+ var id = this.modelId(model.attributes);
+ if (id != null) delete this._byId[id];
+ if (this === model.collection) delete model.collection;
+ model.off('all', this._onModelEvent, this);
+ },
+
+ // Internal method called every time a model in the set fires an event.
+ // Sets need to update their indexes when models change ids. All other
+ // events simply proxy through. "add" and "remove" events that originate
+ // in other collections are ignored.
+ _onModelEvent: function(event, model, collection, options) {
+ if ((event === 'add' || event === 'remove') && collection !== this) return;
+ if (event === 'destroy') this.remove(model, options);
+ if (event === 'change') {
+ var prevId = this.modelId(model.previousAttributes());
+ var id = this.modelId(model.attributes);
+ if (prevId !== id) {
+ if (prevId != null) delete this._byId[prevId];
+ if (id != null) this._byId[id] = model;
+ }
+ }
+ this.trigger.apply(this, arguments);
+ }
+
+ });
+
+ // Underscore methods that we want to implement on the Collection.
+ // 90% of the core usefulness of Backbone Collections is actually implemented
+ // right here:
+ var collectionMethods = { forEach: 3, each: 3, map: 3, collect: 3, reduce: 4,
+ foldl: 4, inject: 4, reduceRight: 4, foldr: 4, find: 3, detect: 3, filter: 3,
+ select: 3, reject: 3, every: 3, all: 3, some: 3, any: 3, include: 3, includes: 3,
+ contains: 3, invoke: 0, max: 3, min: 3, toArray: 1, size: 1, first: 3,
+ head: 3, take: 3, initial: 3, rest: 3, tail: 3, drop: 3, last: 3,
+ without: 0, difference: 0, indexOf: 3, shuffle: 1, lastIndexOf: 3,
+ isEmpty: 1, chain: 1, sample: 3, partition: 3, groupBy: 3, countBy: 3,
+ sortBy: 3, indexBy: 3};
+
+ // Mix in each Underscore method as a proxy to `Collection#models`.
+ addUnderscoreMethods(Collection, collectionMethods, 'models');
+
+ // Backbone.View
+ // -------------
+
+ // Backbone Views are almost more convention than they are actual code. A View
+ // is simply a JavaScript object that represents a logical chunk of UI in the
+ // DOM. This might be a single item, an entire list, a sidebar or panel, or
+ // even the surrounding frame which wraps your whole app. Defining a chunk of
+ // UI as a **View** allows you to define your DOM events declaratively, without
+ // having to worry about render order ... and makes it easy for the view to
+ // react to specific changes in the state of your models.
+
+ // Creating a Backbone.View creates its initial element outside of the DOM,
+ // if an existing element is not provided...
+ var View = Backbone.View = function(options) {
+ this.cid = _.uniqueId('view');
+ _.extend(this, _.pick(options, viewOptions));
+ this._ensureElement();
+ this.initialize.apply(this, arguments);
+ };
+
+ // Cached regex to split keys for `delegate`.
+ var delegateEventSplitter = /^(\S+)\s*(.*)$/;
+
+ // List of view options to be set as properties.
+ var viewOptions = ['model', 'collection', 'el', 'id', 'attributes', 'className', 'tagName', 'events'];
+
+ // Set up all inheritable **Backbone.View** properties and methods.
+ _.extend(View.prototype, Events, {
+
+ // The default `tagName` of a View's element is `"div"`.
+ tagName: 'div',
+
+ // jQuery delegate for element lookup, scoped to DOM elements within the
+ // current view. This should be preferred to global lookups where possible.
+ $: function(selector) {
+ return this.$el.find(selector);
+ },
+
+ // Initialize is an empty function by default. Override it with your own
+ // initialization logic.
+ initialize: function(){},
+
+ // **render** is the core function that your view should override, in order
+ // to populate its element (`this.el`), with the appropriate HTML. The
+ // convention is for **render** to always return `this`.
+ render: function() {
+ return this;
+ },
+
+ // Remove this view by taking the element out of the DOM, and removing any
+ // applicable Backbone.Events listeners.
+ remove: function() {
+ this._removeElement();
+ this.stopListening();
+ return this;
+ },
+
+ // Remove this view's element from the document and all event listeners
+ // attached to it. Exposed for subclasses using an alternative DOM
+ // manipulation API.
+ _removeElement: function() {
+ this.$el.remove();
+ },
+
+ // Change the view's element (`this.el` property) and re-delegate the
+ // view's events on the new element.
+ setElement: function(element) {
+ this.undelegateEvents();
+ this._setElement(element);
+ this.delegateEvents();
+ return this;
+ },
+
+ // Creates the `this.el` and `this.$el` references for this view using the
+ // given `el`. `el` can be a CSS selector or an HTML string, a jQuery
+ // context or an element. Subclasses can override this to utilize an
+ // alternative DOM manipulation API and are only required to set the
+ // `this.el` property.
+ _setElement: function(el) {
+ this.$el = el instanceof Backbone.$ ? el : Backbone.$(el);
+ this.el = this.$el[0];
+ },
+
+ // Set callbacks, where `this.events` is a hash of
+ //
+ // *{"event selector": "callback"}*
+ //
+ // {
+ // 'mousedown .title': 'edit',
+ // 'click .button': 'save',
+ // 'click .open': function(e) { ... }
+ // }
+ //
+ // pairs. Callbacks will be bound to the view, with `this` set properly.
+ // Uses event delegation for efficiency.
+ // Omitting the selector binds the event to `this.el`.
+ delegateEvents: function(events) {
+ events || (events = _.result(this, 'events'));
+ if (!events) return this;
+ this.undelegateEvents();
+ for (var key in events) {
+ var method = events[key];
+ if (!_.isFunction(method)) method = this[method];
+ if (!method) continue;
+ var match = key.match(delegateEventSplitter);
+ this.delegate(match[1], match[2], _.bind(method, this));
+ }
+ return this;
+ },
+
+ // Add a single event listener to the view's element (or a child element
+ // using `selector`). This only works for delegate-able events: not `focus`,
+ // `blur`, and not `change`, `submit`, and `reset` in Internet Explorer.
+ delegate: function(eventName, selector, listener) {
+ this.$el.on(eventName + '.delegateEvents' + this.cid, selector, listener);
+ return this;
+ },
+
+ // Clears all callbacks previously bound to the view by `delegateEvents`.
+ // You usually don't need to use this, but may wish to if you have multiple
+ // Backbone views attached to the same DOM element.
+ undelegateEvents: function() {
+ if (this.$el) this.$el.off('.delegateEvents' + this.cid);
+ return this;
+ },
+
+ // A finer-grained `undelegateEvents` for removing a single delegated event.
+ // `selector` and `listener` are both optional.
+ undelegate: function(eventName, selector, listener) {
+ this.$el.off(eventName + '.delegateEvents' + this.cid, selector, listener);
+ return this;
+ },
+
+ // Produces a DOM element to be assigned to your view. Exposed for
+ // subclasses using an alternative DOM manipulation API.
+ _createElement: function(tagName) {
+ return document.createElement(tagName);
+ },
+
+ // Ensure that the View has a DOM element to render into.
+ // If `this.el` is a string, pass it through `$()`, take the first
+ // matching element, and re-assign it to `el`. Otherwise, create
+ // an element from the `id`, `className` and `tagName` properties.
+ _ensureElement: function() {
+ if (!this.el) {
+ var attrs = _.extend({}, _.result(this, 'attributes'));
+ if (this.id) attrs.id = _.result(this, 'id');
+ if (this.className) attrs['class'] = _.result(this, 'className');
+ this.setElement(this._createElement(_.result(this, 'tagName')));
+ this._setAttributes(attrs);
+ } else {
+ this.setElement(_.result(this, 'el'));
+ }
+ },
+
+ // Set attributes from a hash on this view's element. Exposed for
+ // subclasses using an alternative DOM manipulation API.
+ _setAttributes: function(attributes) {
+ this.$el.attr(attributes);
+ }
+
+ });
+
+ // Backbone.sync
+ // -------------
+
+ // Override this function to change the manner in which Backbone persists
+ // models to the server. You will be passed the type of request, and the
+ // model in question. By default, makes a RESTful Ajax request
+ // to the model's `url()`. Some possible customizations could be:
+ //
+ // * Use `setTimeout` to batch rapid-fire updates into a single request.
+ // * Send up the models as XML instead of JSON.
+ // * Persist models via WebSockets instead of Ajax.
+ //
+ // Turn on `Backbone.emulateHTTP` in order to send `PUT` and `DELETE` requests
+ // as `POST`, with a `_method` parameter containing the true HTTP method,
+ // as well as all requests with the body as `application/x-www-form-urlencoded`
+ // instead of `application/json` with the model in a param named `model`.
+ // Useful when interfacing with server-side languages like **PHP** that make
+ // it difficult to read the body of `PUT` requests.
+ Backbone.sync = function(method, model, options) {
+ var type = methodMap[method];
+
+ // Default options, unless specified.
+ _.defaults(options || (options = {}), {
+ emulateHTTP: Backbone.emulateHTTP,
+ emulateJSON: Backbone.emulateJSON
+ });
+
+ // Default JSON-request options.
+ var params = {type: type, dataType: 'json'};
+
+ // Ensure that we have a URL.
+ if (!options.url) {
+ params.url = _.result(model, 'url') || urlError();
+ }
+
+ // Ensure that we have the appropriate request data.
+ if (options.data == null && model && (method === 'create' || method === 'update' || method === 'patch')) {
+ params.contentType = 'application/json';
+ params.data = JSON.stringify(options.attrs || model.toJSON(options));
+ }
+
+ // For older servers, emulate JSON by encoding the request into an HTML-form.
+ if (options.emulateJSON) {
+ params.contentType = 'application/x-www-form-urlencoded';
+ params.data = params.data ? {model: params.data} : {};
+ }
+
+ // For older servers, emulate HTTP by mimicking the HTTP method with `_method`
+ // And an `X-HTTP-Method-Override` header.
+ if (options.emulateHTTP && (type === 'PUT' || type === 'DELETE' || type === 'PATCH')) {
+ params.type = 'POST';
+ if (options.emulateJSON) params.data._method = type;
+ var beforeSend = options.beforeSend;
+ options.beforeSend = function(xhr) {
+ xhr.setRequestHeader('X-HTTP-Method-Override', type);
+ if (beforeSend) return beforeSend.apply(this, arguments);
+ };
+ }
+
+ // Don't process data on a non-GET request.
+ if (params.type !== 'GET' && !options.emulateJSON) {
+ params.processData = false;
+ }
+
+ // Pass along `textStatus` and `errorThrown` from jQuery.
+ var error = options.error;
+ options.error = function(xhr, textStatus, errorThrown) {
+ options.textStatus = textStatus;
+ options.errorThrown = errorThrown;
+ if (error) error.call(options.context, xhr, textStatus, errorThrown);
+ };
+
+ // Make the request, allowing the user to override any Ajax options.
+ var xhr = options.xhr = Backbone.ajax(_.extend(params, options));
+ model.trigger('request', model, xhr, options);
+ return xhr;
+ };
+
+ // Map from CRUD to HTTP for our default `Backbone.sync` implementation.
+ var methodMap = {
+ 'create': 'POST',
+ 'update': 'PUT',
+ 'patch': 'PATCH',
+ 'delete': 'DELETE',
+ 'read': 'GET'
+ };
+
+ // Set the default implementation of `Backbone.ajax` to proxy through to `$`.
+ // Override this if you'd like to use a different library.
+ Backbone.ajax = function() {
+ return Backbone.$.ajax.apply(Backbone.$, arguments);
+ };
+
+ // Backbone.Router
+ // ---------------
+
+ // Routers map faux-URLs to actions, and fire events when routes are
+ // matched. Creating a new one sets its `routes` hash, if not set statically.
+ var Router = Backbone.Router = function(options) {
+ options || (options = {});
+ if (options.routes) this.routes = options.routes;
+ this._bindRoutes();
+ this.initialize.apply(this, arguments);
+ };
+
+ // Cached regular expressions for matching named param parts and splatted
+ // parts of route strings.
+ var optionalParam = /\((.*?)\)/g;
+ var namedParam = /(\(\?)?:\w+/g;
+ var splatParam = /\*\w+/g;
+ var escapeRegExp = /[\-{}\[\]+?.,\\\^$|#\s]/g;
+
+ // Set up all inheritable **Backbone.Router** properties and methods.
+ _.extend(Router.prototype, Events, {
+
+ // Initialize is an empty function by default. Override it with your own
+ // initialization logic.
+ initialize: function(){},
+
+ // Manually bind a single named route to a callback. For example:
+ //
+ // this.route('search/:query/p:num', 'search', function(query, num) {
+ // ...
+ // });
+ //
+ route: function(route, name, callback) {
+ if (!_.isRegExp(route)) route = this._routeToRegExp(route);
+ if (_.isFunction(name)) {
+ callback = name;
+ name = '';
+ }
+ if (!callback) callback = this[name];
+ var router = this;
+ Backbone.history.route(route, function(fragment) {
+ var args = router._extractParameters(route, fragment);
+ if (router.execute(callback, args, name) !== false) {
+ router.trigger.apply(router, ['route:' + name].concat(args));
+ router.trigger('route', name, args);
+ Backbone.history.trigger('route', router, name, args);
+ }
+ });
+ return this;
+ },
+
+ // Execute a route handler with the provided parameters. This is an
+ // excellent place to do pre-route setup or post-route cleanup.
+ execute: function(callback, args, name) {
+ if (callback) callback.apply(this, args);
+ },
+
+ // Simple proxy to `Backbone.history` to save a fragment into the history.
+ navigate: function(fragment, options) {
+ Backbone.history.navigate(fragment, options);
+ return this;
+ },
+
+ // Bind all defined routes to `Backbone.history`. We have to reverse the
+ // order of the routes here to support behavior where the most general
+ // routes can be defined at the bottom of the route map.
+ _bindRoutes: function() {
+ if (!this.routes) return;
+ this.routes = _.result(this, 'routes');
+ var route, routes = _.keys(this.routes);
+ while ((route = routes.pop()) != null) {
+ this.route(route, this.routes[route]);
+ }
+ },
+
+ // Convert a route string into a regular expression, suitable for matching
+ // against the current location hash.
+ _routeToRegExp: function(route) {
+ route = route.replace(escapeRegExp, '\\$&')
+ .replace(optionalParam, '(?:$1)?')
+ .replace(namedParam, function(match, optional) {
+ return optional ? match : '([^/?]+)';
+ })
+ .replace(splatParam, '([^?]*?)');
+ return new RegExp('^' + route + '(?:\\?([\\s\\S]*))?$');
+ },
+
+ // Given a route, and a URL fragment that it matches, return the array of
+ // extracted decoded parameters. Empty or unmatched parameters will be
+ // treated as `null` to normalize cross-browser behavior.
+ _extractParameters: function(route, fragment) {
+ var params = route.exec(fragment).slice(1);
+ return _.map(params, function(param, i) {
+ // Don't decode the search params.
+ if (i === params.length - 1) return param || null;
+ return param ? decodeURIComponent(param) : null;
+ });
+ }
+
+ });
+
+ // Backbone.History
+ // ----------------
+
+ // Handles cross-browser history management, based on either
+ // [pushState](http://diveintohtml5.info/history.html) and real URLs, or
+ // [onhashchange](https://developer.mozilla.org/en-US/docs/DOM/window.onhashchange)
+ // and URL fragments. If the browser supports neither (old IE, natch),
+ // falls back to polling.
+ var History = Backbone.History = function() {
+ this.handlers = [];
+ this.checkUrl = _.bind(this.checkUrl, this);
+
+ // Ensure that `History` can be used outside of the browser.
+ if (typeof window !== 'undefined') {
+ this.location = window.location;
+ this.history = window.history;
+ }
+ };
+
+ // Cached regex for stripping a leading hash/slash and trailing space.
+ var routeStripper = /^[#\/]|\s+$/g;
+
+ // Cached regex for stripping leading and trailing slashes.
+ var rootStripper = /^\/+|\/+$/g;
+
+ // Cached regex for stripping urls of hash.
+ var pathStripper = /#.*$/;
+
+ // Has the history handling already been started?
+ History.started = false;
+
+ // Set up all inheritable **Backbone.History** properties and methods.
+ _.extend(History.prototype, Events, {
+
+ // The default interval to poll for hash changes, if necessary, is
+ // twenty times a second.
+ interval: 50,
+
+ // Are we at the app root?
+ atRoot: function() {
+ var path = this.location.pathname.replace(/[^\/]$/, '$&/');
+ return path === this.root && !this.getSearch();
+ },
+
+ // Does the pathname match the root?
+ matchRoot: function() {
+ var path = this.decodeFragment(this.location.pathname);
+ var root = path.slice(0, this.root.length - 1) + '/';
+ return root === this.root;
+ },
+
+ // Unicode characters in `location.pathname` are percent encoded so they're
+ // decoded for comparison. `%25` should not be decoded since it may be part
+ // of an encoded parameter.
+ decodeFragment: function(fragment) {
+ return decodeURI(fragment.replace(/%25/g, '%2525'));
+ },
+
+ // In IE6, the hash fragment and search params are incorrect if the
+ // fragment contains `?`.
+ getSearch: function() {
+ var match = this.location.href.replace(/#.*/, '').match(/\?.+/);
+ return match ? match[0] : '';
+ },
+
+ // Gets the true hash value. Cannot use location.hash directly due to bug
+ // in Firefox where location.hash will always be decoded.
+ getHash: function(window) {
+ var match = (window || this).location.href.match(/#(.*)$/);
+ return match ? match[1] : '';
+ },
+
+ // Get the pathname and search params, without the root.
+ getPath: function() {
+ var path = this.decodeFragment(
+ this.location.pathname + this.getSearch()
+ ).slice(this.root.length - 1);
+ return path.charAt(0) === '/' ? path.slice(1) : path;
+ },
+
+ // Get the cross-browser normalized URL fragment from the path or hash.
+ getFragment: function(fragment) {
+ if (fragment == null) {
+ if (this._usePushState || !this._wantsHashChange) {
+ fragment = this.getPath();
+ } else {
+ fragment = this.getHash();
+ }
+ }
+ return fragment.replace(routeStripper, '');
+ },
+
+ // Start the hash change handling, returning `true` if the current URL matches
+ // an existing route, and `false` otherwise.
+ start: function(options) {
+ if (History.started) throw new Error('Backbone.history has already been started');
+ History.started = true;
+
+ // Figure out the initial configuration. Do we need an iframe?
+ // Is pushState desired ... is it available?
+ this.options = _.extend({root: '/'}, this.options, options);
+ this.root = this.options.root;
+ this._wantsHashChange = this.options.hashChange !== false;
+ this._hasHashChange = 'onhashchange' in window && (document.documentMode === void 0 || document.documentMode > 7);
+ this._useHashChange = this._wantsHashChange && this._hasHashChange;
+ this._wantsPushState = !!this.options.pushState;
+ this._hasPushState = !!(this.history && this.history.pushState);
+ this._usePushState = this._wantsPushState && this._hasPushState;
+ this.fragment = this.getFragment();
+
+ // Normalize root to always include a leading and trailing slash.
+ this.root = ('/' + this.root + '/').replace(rootStripper, '/');
+
+ // Transition from hashChange to pushState or vice versa if both are
+ // requested.
+ if (this._wantsHashChange && this._wantsPushState) {
+
+ // If we've started off with a route from a `pushState`-enabled
+ // browser, but we're currently in a browser that doesn't support it...
+ if (!this._hasPushState && !this.atRoot()) {
+ var root = this.root.slice(0, -1) || '/';
+ this.location.replace(root + '#' + this.getPath());
+ // Return immediately as browser will do redirect to new url
+ return true;
+
+ // Or if we've started out with a hash-based route, but we're currently
+ // in a browser where it could be `pushState`-based instead...
+ } else if (this._hasPushState && this.atRoot()) {
+ this.navigate(this.getHash(), {replace: true});
+ }
+
+ }
+
+ // Proxy an iframe to handle location events if the browser doesn't
+ // support the `hashchange` event, HTML5 history, or the user wants
+ // `hashChange` but not `pushState`.
+ if (!this._hasHashChange && this._wantsHashChange && !this._usePushState) {
+ this.iframe = document.createElement('iframe');
+ this.iframe.src = 'javascript:0';
+ this.iframe.style.display = 'none';
+ this.iframe.tabIndex = -1;
+ var body = document.body;
+ // Using `appendChild` will throw on IE < 9 if the document is not ready.
+ var iWindow = body.insertBefore(this.iframe, body.firstChild).contentWindow;
+ iWindow.document.open();
+ iWindow.document.close();
+ iWindow.location.hash = '#' + this.fragment;
+ }
+
+ // Add a cross-platform `addEventListener` shim for older browsers.
+ var addEventListener = window.addEventListener || function (eventName, listener) {
+ return attachEvent('on' + eventName, listener);
+ };
+
+ // Depending on whether we're using pushState or hashes, and whether
+ // 'onhashchange' is supported, determine how we check the URL state.
+ if (this._usePushState) {
+ addEventListener('popstate', this.checkUrl, false);
+ } else if (this._useHashChange && !this.iframe) {
+ addEventListener('hashchange', this.checkUrl, false);
+ } else if (this._wantsHashChange) {
+ this._checkUrlInterval = setInterval(this.checkUrl, this.interval);
+ }
+
+ if (!this.options.silent) return this.loadUrl();
+ },
+
+ // Disable Backbone.history, perhaps temporarily. Not useful in a real app,
+ // but possibly useful for unit testing Routers.
+ stop: function() {
+ // Add a cross-platform `removeEventListener` shim for older browsers.
+ var removeEventListener = window.removeEventListener || function (eventName, listener) {
+ return detachEvent('on' + eventName, listener);
+ };
+
+ // Remove window listeners.
+ if (this._usePushState) {
+ removeEventListener('popstate', this.checkUrl, false);
+ } else if (this._useHashChange && !this.iframe) {
+ removeEventListener('hashchange', this.checkUrl, false);
+ }
+
+ // Clean up the iframe if necessary.
+ if (this.iframe) {
+ document.body.removeChild(this.iframe);
+ this.iframe = null;
+ }
+
+ // Some environments will throw when clearing an undefined interval.
+ if (this._checkUrlInterval) clearInterval(this._checkUrlInterval);
+ History.started = false;
+ },
+
+ // Add a route to be tested when the fragment changes. Routes added later
+ // may override previous routes.
+ route: function(route, callback) {
+ this.handlers.unshift({route: route, callback: callback});
+ },
+
+ // Checks the current URL to see if it has changed, and if it has,
+ // calls `loadUrl`, normalizing across the hidden iframe.
+ checkUrl: function(e) {
+ var current = this.getFragment();
+
+ // If the user pressed the back button, the iframe's hash will have
+ // changed and we should use that for comparison.
+ if (current === this.fragment && this.iframe) {
+ current = this.getHash(this.iframe.contentWindow);
+ }
+
+ if (current === this.fragment) return false;
+ if (this.iframe) this.navigate(current);
+ this.loadUrl();
+ },
+
+ // Attempt to load the current URL fragment. If a route succeeds with a
+ // match, returns `true`. If no defined routes matches the fragment,
+ // returns `false`.
+ loadUrl: function(fragment) {
+ // If the root doesn't match, no routes can match either.
+ if (!this.matchRoot()) return false;
+ fragment = this.fragment = this.getFragment(fragment);
+ return _.some(this.handlers, function(handler) {
+ if (handler.route.test(fragment)) {
+ handler.callback(fragment);
+ return true;
+ }
+ });
+ },
+
+ // Save a fragment into the hash history, or replace the URL state if the
+ // 'replace' option is passed. You are responsible for properly URL-encoding
+ // the fragment in advance.
+ //
+ // The options object can contain `trigger: true` if you wish to have the
+ // route callback be fired (not usually desirable), or `replace: true`, if
+ // you wish to modify the current URL without adding an entry to the history.
+ navigate: function(fragment, options) {
+ if (!History.started) return false;
+ if (!options || options === true) options = {trigger: !!options};
+
+ // Normalize the fragment.
+ fragment = this.getFragment(fragment || '');
+
+ // Don't include a trailing slash on the root.
+ var root = this.root;
+ if (fragment === '' || fragment.charAt(0) === '?') {
+ root = root.slice(0, -1) || '/';
+ }
+ var url = root + fragment;
+
+ // Strip the hash and decode for matching.
+ fragment = this.decodeFragment(fragment.replace(pathStripper, ''));
+
+ if (this.fragment === fragment) return;
+ this.fragment = fragment;
+
+ // If pushState is available, we use it to set the fragment as a real URL.
+ if (this._usePushState) {
+ this.history[options.replace ? 'replaceState' : 'pushState']({}, document.title, url);
+
+ // If hash changes haven't been explicitly disabled, update the hash
+ // fragment to store history.
+ } else if (this._wantsHashChange) {
+ this._updateHash(this.location, fragment, options.replace);
+ if (this.iframe && (fragment !== this.getHash(this.iframe.contentWindow))) {
+ var iWindow = this.iframe.contentWindow;
+
+ // Opening and closing the iframe tricks IE7 and earlier to push a
+ // history entry on hash-tag change. When replace is true, we don't
+ // want this.
+ if (!options.replace) {
+ iWindow.document.open();
+ iWindow.document.close();
+ }
+
+ this._updateHash(iWindow.location, fragment, options.replace);
+ }
+
+ // If you've told us that you explicitly don't want fallback hashchange-
+ // based history, then `navigate` becomes a page refresh.
+ } else {
+ return this.location.assign(url);
+ }
+ if (options.trigger) return this.loadUrl(fragment);
+ },
+
+ // Update the hash location, either replacing the current entry, or adding
+ // a new one to the browser history.
+ _updateHash: function(location, fragment, replace) {
+ if (replace) {
+ var href = location.href.replace(/(javascript:|#).*$/, '');
+ location.replace(href + '#' + fragment);
+ } else {
+ // Some browsers require that `hash` contains a leading #.
+ location.hash = '#' + fragment;
+ }
+ }
+
+ });
+
+ // Create the default Backbone.history.
+ Backbone.history = new History;
+
+ // Helpers
+ // -------
+
+ // Helper function to correctly set up the prototype chain for subclasses.
+ // Similar to `goog.inherits`, but uses a hash of prototype properties and
+ // class properties to be extended.
+ var extend = function(protoProps, staticProps) {
+ var parent = this;
+ var child;
+
+ // The constructor function for the new subclass is either defined by you
+ // (the "constructor" property in your `extend` definition), or defaulted
+ // by us to simply call the parent constructor.
+ if (protoProps && _.has(protoProps, 'constructor')) {
+ child = protoProps.constructor;
+ } else {
+ child = function(){ return parent.apply(this, arguments); };
+ }
+
+ // Add static properties to the constructor function, if supplied.
+ _.extend(child, parent, staticProps);
+
+ // Set the prototype chain to inherit from `parent`, without calling
+ // `parent` constructor function.
+ var Surrogate = function(){ this.constructor = child; };
+ Surrogate.prototype = parent.prototype;
+ child.prototype = new Surrogate;
+
+ // Add prototype properties (instance properties) to the subclass,
+ // if supplied.
+ if (protoProps) _.extend(child.prototype, protoProps);
+
+ // Set a convenience property in case the parent's prototype is needed
+ // later.
+ child.__super__ = parent.prototype;
+
+ return child;
+ };
+
+ // Set up inheritance for the model, collection, router, view and history.
+ Model.extend = Collection.extend = Router.extend = View.extend = History.extend = extend;
+
+ // Throw an error when a URL is needed, and none is supplied.
+ var urlError = function() {
+ throw new Error('A "url" property or function must be specified');
+ };
+
+ // Wrap an optional error callback with a fallback error event.
+ var wrapError = function(model, options) {
+ var error = options.error;
+ options.error = function(resp) {
+ if (error) error.call(options.context, model, resp, options);
+ model.trigger('error', model, resp, options);
+ };
+ };
+
+ return Backbone;
+
+}));
--- a/src/ldt/ldt/static/ldt/js/embed/v2/embed.js Fri Sep 18 16:10:29 2015 +0200
+++ b/src/ldt/ldt/static/ldt/js/embed/v2/embed.js Fri Oct 02 10:24:05 2015 +0200
@@ -245,13 +245,13 @@
'}\n';
if (polemic_val.checked){
- defaultcolor= $j("#polemic_default_color").val();
- foundcolor=$j("#polemic_found_color").val();
- ok_color=$j("#polemic_ok_color").val();
- ko_color=$j("#polemic_ko_color").val();
- ref_color=$j("#polemic_ref_color").val();
- q_color=$j("#polemic_q_color").val();
- polemic_annotation_types_val=document.getElementById("polemic_annotation_types");
+ var defaultcolor= $j("#polemic_default_color").val(),
+ foundcolor=$j("#polemic_found_color").val(),
+ ok_color=$j("#polemic_ok_color").val(),
+ ko_color=$j("#polemic_ko_color").val(),
+ ref_color=$j("#polemic_ref_color").val(),
+ q_color=$j("#polemic_q_color").val(),
+ polemic_annotation_types_val=document.getElementById("polemic_annotation_types");
widget_code+='\
,{\n\
type: "Polemic",\n';
@@ -300,8 +300,8 @@
}
if(sparkline_val.checked){
- linecolor=$j("#sparkline_line_color").val();
- fillcolor=$j("#sparkline_fill_color").val();
+ var linecolor=$j("#sparkline_line_color").val(),
+ fillcolor=$j("#sparkline_fill_color").val();
widget_code+=',{\n\
type: "Sparkline",\n\
lineColor: "'+linecolor+'",\n\
@@ -370,11 +370,11 @@
}
if(social_val.checked){
- show_url=document.getElementById("show_url_checkbox");
- show_twitter=document.getElementById("show_twitter_checkbox");
- show_fb=document.getElementById("show_fb_checkbox");
- show_gplus=document.getElementById("show_gplus_checkbox");
- show_mail=document.getElementById("show_mail_checkbox");
+ var show_url=document.getElementById("show_url_checkbox"),
+ show_twitter=document.getElementById("show_twitter_checkbox"),
+ show_fb=document.getElementById("show_fb_checkbox"),
+ show_gplus=document.getElementById("show_gplus_checkbox"),
+ show_mail=document.getElementById("show_mail_checkbox");
widget_code+='\
,{\n\
@@ -773,24 +773,24 @@
else{
iframeUrl+="&polemic=all";
}
- polemic_defaultColor=$j("#polemic_default_color").val();
- defaultColor_code_array= polemic_defaultColor.split("#");
- defaultColor_code=defaultColor_code_array[1];
- polemic_foundColor=$j("#polemic_found_color").val();
- foundColor_code_array = polemic_foundColor.split("#");
- foundColor_code=foundColor_code_array[1];
- polemic_okColor =$j("#polemic_ok_color").val();
- polemic_okColor_code_array=polemic_okColor.split("#");
- okColor_code=polemic_okColor_code_array[1];
- polemic_koColor =$j("#polemic_ko_color").val();
- polemic_koColor_code_array=polemic_koColor.split("#");
- koColor_code=polemic_koColor_code_array[1];
- polemic_refColor =$j("#polemic_ref_color").val();
- polemic_refColor_code_array=polemic_refColor.split("#");
- refColor_code=polemic_refColor_code_array[1];
- polemic_qColor =$j("#polemic_q_color").val();
- polemic_qColor_code_array=polemic_qColor.split("#");
- qColor_code=polemic_qColor_code_array[1];
+ var polemic_defaultColor=$j("#polemic_default_color").val(),
+ defaultColor_code_array= polemic_defaultColor.split("#"),
+ defaultColor_code=defaultColor_code_array[1],
+ polemic_foundColor=$j("#polemic_found_color").val(),
+ foundColor_code_array = polemic_foundColor.split("#"),
+ foundColor_code=foundColor_code_array[1],
+ polemic_okColor =$j("#polemic_ok_color").val(),
+ polemic_okColor_code_array=polemic_okColor.split("#"),
+ okColor_code=polemic_okColor_code_array[1],
+ polemic_koColor =$j("#polemic_ko_color").val(),
+ polemic_koColor_code_array=polemic_koColor.split("#"),
+ koColor_code=polemic_koColor_code_array[1],
+ polemic_refColor =$j("#polemic_ref_color").val(),
+ polemic_refColor_code_array=polemic_refColor.split("#"),
+ refColor_code=polemic_refColor_code_array[1],
+ polemic_qColor =$j("#polemic_q_color").val(),
+ polemic_qColor_code_array=polemic_qColor.split("#"),
+ qColor_code=polemic_qColor_code_array[1];
if(defaultColor_code!="585858")
iframeUrl+="&polemic_defaultColor="+defaultColor_code;
if(foundColor_code!="fc00ff")
@@ -815,11 +815,11 @@
iframeUrl+="&slideshare=True";
}
if(social_val.checked){
- show_url=document.getElementById("show_url_checkbox");
- show_twitter=document.getElementById("show_twitter_checkbox");
- show_fb=document.getElementById("show_fb_checkbox");
- show_gplus=document.getElementById("show_gplus_checkbox");
- show_mail=document.getElementById("show_mail_checkbox");
+ var show_url=document.getElementById("show_url_checkbox"),
+ show_twitter=document.getElementById("show_twitter_checkbox"),
+ show_fb=document.getElementById("show_fb_checkbox"),
+ show_gplus=document.getElementById("show_gplus_checkbox"),
+ show_mail=document.getElementById("show_mail_checkbox");
iframeUrl+="&social=True";
if(!show_url.checked){
iframeUrl+="&show_url=False";
@@ -854,12 +854,12 @@
}
if(sparkline_val.checked){
iframeUrl+="&sparkline=True";
- sparkline_lineColor=$j("#sparkline_line_color").val();
- lineColor_code_array= sparkline_lineColor.split("#");
- lineColor_code=lineColor_code_array[1];
- sparkline_fillColor=$j("#sparkline_fill_color").val();
- fillColor_code_array = sparkline_fillColor.split("#");
- fillColor_code=fillColor_code_array[1];
+ var sparkline_lineColor=$j("#sparkline_line_color").val(),
+ lineColor_code_array= sparkline_lineColor.split("#"),
+ lineColor_code=lineColor_code_array[1],
+ sparkline_fillColor=$j("#sparkline_fill_color").val(),
+ fillColor_code_array = sparkline_fillColor.split("#"),
+ fillColor_code=fillColor_code_array[1];
if(lineColor_code!="7492b4")
iframeUrl+="&sparkline_lineColor="+lineColor_code;
if(fillColor_code!="aeaeb8")
--- a/src/ldt/ldt/static/ldt/js/jquery.min.js Fri Sep 18 16:10:29 2015 +0200
+++ b/src/ldt/ldt/static/ldt/js/jquery.min.js Fri Oct 02 10:24:05 2015 +0200
@@ -2,3 +2,4 @@
!function(a,b){"object"==typeof module&&"object"==typeof module.exports?module.exports=a.document?b(a,!0):function(a){if(!a.document)throw new Error("jQuery requires a window with a document");return b(a)}:b(a)}("undefined"!=typeof window?window:this,function(a,b){var c=[],d=c.slice,e=c.concat,f=c.push,g=c.indexOf,h={},i=h.toString,j=h.hasOwnProperty,k={},l=a.document,m="2.1.4",n=function(a,b){return new n.fn.init(a,b)},o=/^[\s\uFEFF\xA0]+|[\s\uFEFF\xA0]+$/g,p=/^-ms-/,q=/-([\da-z])/gi,r=function(a,b){return b.toUpperCase()};n.fn=n.prototype={jquery:m,constructor:n,selector:"",length:0,toArray:function(){return d.call(this)},get:function(a){return null!=a?0>a?this[a+this.length]:this[a]:d.call(this)},pushStack:function(a){var b=n.merge(this.constructor(),a);return b.prevObject=this,b.context=this.context,b},each:function(a,b){return n.each(this,a,b)},map:function(a){return this.pushStack(n.map(this,function(b,c){return a.call(b,c,b)}))},slice:function(){return this.pushStack(d.apply(this,arguments))},first:function(){return this.eq(0)},last:function(){return this.eq(-1)},eq:function(a){var b=this.length,c=+a+(0>a?b:0);return this.pushStack(c>=0&&b>c?[this[c]]:[])},end:function(){return this.prevObject||this.constructor(null)},push:f,sort:c.sort,splice:c.splice},n.extend=n.fn.extend=function(){var a,b,c,d,e,f,g=arguments[0]||{},h=1,i=arguments.length,j=!1;for("boolean"==typeof g&&(j=g,g=arguments[h]||{},h++),"object"==typeof g||n.isFunction(g)||(g={}),h===i&&(g=this,h--);i>h;h++)if(null!=(a=arguments[h]))for(b in a)c=g[b],d=a[b],g!==d&&(j&&d&&(n.isPlainObject(d)||(e=n.isArray(d)))?(e?(e=!1,f=c&&n.isArray(c)?c:[]):f=c&&n.isPlainObject(c)?c:{},g[b]=n.extend(j,f,d)):void 0!==d&&(g[b]=d));return g},n.extend({expando:"jQuery"+(m+Math.random()).replace(/\D/g,""),isReady:!0,error:function(a){throw new Error(a)},noop:function(){},isFunction:function(a){return"function"===n.type(a)},isArray:Array.isArray,isWindow:function(a){return null!=a&&a===a.window},isNumeric:function(a){return!n.isArray(a)&&a-parseFloat(a)+1>=0},isPlainObject:function(a){return"object"!==n.type(a)||a.nodeType||n.isWindow(a)?!1:a.constructor&&!j.call(a.constructor.prototype,"isPrototypeOf")?!1:!0},isEmptyObject:function(a){var b;for(b in a)return!1;return!0},type:function(a){return null==a?a+"":"object"==typeof a||"function"==typeof a?h[i.call(a)]||"object":typeof a},globalEval:function(a){var b,c=eval;a=n.trim(a),a&&(1===a.indexOf("use strict")?(b=l.createElement("script"),b.text=a,l.head.appendChild(b).parentNode.removeChild(b)):c(a))},camelCase:function(a){return a.replace(p,"ms-").replace(q,r)},nodeName:function(a,b){return a.nodeName&&a.nodeName.toLowerCase()===b.toLowerCase()},each:function(a,b,c){var d,e=0,f=a.length,g=s(a);if(c){if(g){for(;f>e;e++)if(d=b.apply(a[e],c),d===!1)break}else for(e in a)if(d=b.apply(a[e],c),d===!1)break}else if(g){for(;f>e;e++)if(d=b.call(a[e],e,a[e]),d===!1)break}else for(e in a)if(d=b.call(a[e],e,a[e]),d===!1)break;return a},trim:function(a){return null==a?"":(a+"").replace(o,"")},makeArray:function(a,b){var c=b||[];return null!=a&&(s(Object(a))?n.merge(c,"string"==typeof a?[a]:a):f.call(c,a)),c},inArray:function(a,b,c){return null==b?-1:g.call(b,a,c)},merge:function(a,b){for(var c=+b.length,d=0,e=a.length;c>d;d++)a[e++]=b[d];return a.length=e,a},grep:function(a,b,c){for(var d,e=[],f=0,g=a.length,h=!c;g>f;f++)d=!b(a[f],f),d!==h&&e.push(a[f]);return e},map:function(a,b,c){var d,f=0,g=a.length,h=s(a),i=[];if(h)for(;g>f;f++)d=b(a[f],f,c),null!=d&&i.push(d);else for(f in a)d=b(a[f],f,c),null!=d&&i.push(d);return e.apply([],i)},guid:1,proxy:function(a,b){var c,e,f;return"string"==typeof b&&(c=a[b],b=a,a=c),n.isFunction(a)?(e=d.call(arguments,2),f=function(){return a.apply(b||this,e.concat(d.call(arguments)))},f.guid=a.guid=a.guid||n.guid++,f):void 0},now:Date.now,support:k}),n.each("Boolean Number String Function Array Date RegExp Object Error".split(" "),function(a,b){h["[object "+b+"]"]=b.toLowerCase()});function s(a){var b="length"in a&&a.length,c=n.type(a);return"function"===c||n.isWindow(a)?!1:1===a.nodeType&&b?!0:"array"===c||0===b||"number"==typeof b&&b>0&&b-1 in a}var t=function(a){var b,c,d,e,f,g,h,i,j,k,l,m,n,o,p,q,r,s,t,u="sizzle"+1*new Date,v=a.document,w=0,x=0,y=ha(),z=ha(),A=ha(),B=function(a,b){return a===b&&(l=!0),0},C=1<<31,D={}.hasOwnProperty,E=[],F=E.pop,G=E.push,H=E.push,I=E.slice,J=function(a,b){for(var c=0,d=a.length;d>c;c++)if(a[c]===b)return c;return-1},K="checked|selected|async|autofocus|autoplay|controls|defer|disabled|hidden|ismap|loop|multiple|open|readonly|required|scoped",L="[\\x20\\t\\r\\n\\f]",M="(?:\\\\.|[\\w-]|[^\\x00-\\xa0])+",N=M.replace("w","w#"),O="\\["+L+"*("+M+")(?:"+L+"*([*^$|!~]?=)"+L+"*(?:'((?:\\\\.|[^\\\\'])*)'|\"((?:\\\\.|[^\\\\\"])*)\"|("+N+"))|)"+L+"*\\]",P=":("+M+")(?:\\((('((?:\\\\.|[^\\\\'])*)'|\"((?:\\\\.|[^\\\\\"])*)\")|((?:\\\\.|[^\\\\()[\\]]|"+O+")*)|.*)\\)|)",Q=new RegExp(L+"+","g"),R=new RegExp("^"+L+"+|((?:^|[^\\\\])(?:\\\\.)*)"+L+"+$","g"),S=new RegExp("^"+L+"*,"+L+"*"),T=new RegExp("^"+L+"*([>+~]|"+L+")"+L+"*"),U=new RegExp("="+L+"*([^\\]'\"]*?)"+L+"*\\]","g"),V=new RegExp(P),W=new RegExp("^"+N+"$"),X={ID:new RegExp("^#("+M+")"),CLASS:new RegExp("^\\.("+M+")"),TAG:new RegExp("^("+M.replace("w","w*")+")"),ATTR:new RegExp("^"+O),PSEUDO:new RegExp("^"+P),CHILD:new RegExp("^:(only|first|last|nth|nth-last)-(child|of-type)(?:\\("+L+"*(even|odd|(([+-]|)(\\d*)n|)"+L+"*(?:([+-]|)"+L+"*(\\d+)|))"+L+"*\\)|)","i"),bool:new RegExp("^(?:"+K+")$","i"),needsContext:new RegExp("^"+L+"*[>+~]|:(even|odd|eq|gt|lt|nth|first|last)(?:\\("+L+"*((?:-\\d)?\\d*)"+L+"*\\)|)(?=[^-]|$)","i")},Y=/^(?:input|select|textarea|button)$/i,Z=/^h\d$/i,$=/^[^{]+\{\s*\[native \w/,_=/^(?:#([\w-]+)|(\w+)|\.([\w-]+))$/,aa=/[+~]/,ba=/'|\\/g,ca=new RegExp("\\\\([\\da-f]{1,6}"+L+"?|("+L+")|.)","ig"),da=function(a,b,c){var d="0x"+b-65536;return d!==d||c?b:0>d?String.fromCharCode(d+65536):String.fromCharCode(d>>10|55296,1023&d|56320)},ea=function(){m()};try{H.apply(E=I.call(v.childNodes),v.childNodes),E[v.childNodes.length].nodeType}catch(fa){H={apply:E.length?function(a,b){G.apply(a,I.call(b))}:function(a,b){var c=a.length,d=0;while(a[c++]=b[d++]);a.length=c-1}}}function ga(a,b,d,e){var f,h,j,k,l,o,r,s,w,x;if((b?b.ownerDocument||b:v)!==n&&m(b),b=b||n,d=d||[],k=b.nodeType,"string"!=typeof a||!a||1!==k&&9!==k&&11!==k)return d;if(!e&&p){if(11!==k&&(f=_.exec(a)))if(j=f[1]){if(9===k){if(h=b.getElementById(j),!h||!h.parentNode)return d;if(h.id===j)return d.push(h),d}else if(b.ownerDocument&&(h=b.ownerDocument.getElementById(j))&&t(b,h)&&h.id===j)return d.push(h),d}else{if(f[2])return H.apply(d,b.getElementsByTagName(a)),d;if((j=f[3])&&c.getElementsByClassName)return H.apply(d,b.getElementsByClassName(j)),d}if(c.qsa&&(!q||!q.test(a))){if(s=r=u,w=b,x=1!==k&&a,1===k&&"object"!==b.nodeName.toLowerCase()){o=g(a),(r=b.getAttribute("id"))?s=r.replace(ba,"\\$&"):b.setAttribute("id",s),s="[id='"+s+"'] ",l=o.length;while(l--)o[l]=s+ra(o[l]);w=aa.test(a)&&pa(b.parentNode)||b,x=o.join(",")}if(x)try{return H.apply(d,w.querySelectorAll(x)),d}catch(y){}finally{r||b.removeAttribute("id")}}}return i(a.replace(R,"$1"),b,d,e)}function ha(){var a=[];function b(c,e){return a.push(c+" ")>d.cacheLength&&delete b[a.shift()],b[c+" "]=e}return b}function ia(a){return a[u]=!0,a}function ja(a){var b=n.createElement("div");try{return!!a(b)}catch(c){return!1}finally{b.parentNode&&b.parentNode.removeChild(b),b=null}}function ka(a,b){var c=a.split("|"),e=a.length;while(e--)d.attrHandle[c[e]]=b}function la(a,b){var c=b&&a,d=c&&1===a.nodeType&&1===b.nodeType&&(~b.sourceIndex||C)-(~a.sourceIndex||C);if(d)return d;if(c)while(c=c.nextSibling)if(c===b)return-1;return a?1:-1}function ma(a){return function(b){var c=b.nodeName.toLowerCase();return"input"===c&&b.type===a}}function na(a){return function(b){var c=b.nodeName.toLowerCase();return("input"===c||"button"===c)&&b.type===a}}function oa(a){return ia(function(b){return b=+b,ia(function(c,d){var e,f=a([],c.length,b),g=f.length;while(g--)c[e=f[g]]&&(c[e]=!(d[e]=c[e]))})})}function pa(a){return a&&"undefined"!=typeof a.getElementsByTagName&&a}c=ga.support={},f=ga.isXML=function(a){var b=a&&(a.ownerDocument||a).documentElement;return b?"HTML"!==b.nodeName:!1},m=ga.setDocument=function(a){var b,e,g=a?a.ownerDocument||a:v;return g!==n&&9===g.nodeType&&g.documentElement?(n=g,o=g.documentElement,e=g.defaultView,e&&e!==e.top&&(e.addEventListener?e.addEventListener("unload",ea,!1):e.attachEvent&&e.attachEvent("onunload",ea)),p=!f(g),c.attributes=ja(function(a){return a.className="i",!a.getAttribute("className")}),c.getElementsByTagName=ja(function(a){return a.appendChild(g.createComment("")),!a.getElementsByTagName("*").length}),c.getElementsByClassName=$.test(g.getElementsByClassName),c.getById=ja(function(a){return o.appendChild(a).id=u,!g.getElementsByName||!g.getElementsByName(u).length}),c.getById?(d.find.ID=function(a,b){if("undefined"!=typeof b.getElementById&&p){var c=b.getElementById(a);return c&&c.parentNode?[c]:[]}},d.filter.ID=function(a){var b=a.replace(ca,da);return function(a){return a.getAttribute("id")===b}}):(delete d.find.ID,d.filter.ID=function(a){var b=a.replace(ca,da);return function(a){var c="undefined"!=typeof a.getAttributeNode&&a.getAttributeNode("id");return c&&c.value===b}}),d.find.TAG=c.getElementsByTagName?function(a,b){return"undefined"!=typeof b.getElementsByTagName?b.getElementsByTagName(a):c.qsa?b.querySelectorAll(a):void 0}:function(a,b){var c,d=[],e=0,f=b.getElementsByTagName(a);if("*"===a){while(c=f[e++])1===c.nodeType&&d.push(c);return d}return f},d.find.CLASS=c.getElementsByClassName&&function(a,b){return p?b.getElementsByClassName(a):void 0},r=[],q=[],(c.qsa=$.test(g.querySelectorAll))&&(ja(function(a){o.appendChild(a).innerHTML="<a id='"+u+"'></a><select id='"+u+"-\f]' msallowcapture=''><option selected=''></option></select>",a.querySelectorAll("[msallowcapture^='']").length&&q.push("[*^$]="+L+"*(?:''|\"\")"),a.querySelectorAll("[selected]").length||q.push("\\["+L+"*(?:value|"+K+")"),a.querySelectorAll("[id~="+u+"-]").length||q.push("~="),a.querySelectorAll(":checked").length||q.push(":checked"),a.querySelectorAll("a#"+u+"+*").length||q.push(".#.+[+~]")}),ja(function(a){var b=g.createElement("input");b.setAttribute("type","hidden"),a.appendChild(b).setAttribute("name","D"),a.querySelectorAll("[name=d]").length&&q.push("name"+L+"*[*^$|!~]?="),a.querySelectorAll(":enabled").length||q.push(":enabled",":disabled"),a.querySelectorAll("*,:x"),q.push(",.*:")})),(c.matchesSelector=$.test(s=o.matches||o.webkitMatchesSelector||o.mozMatchesSelector||o.oMatchesSelector||o.msMatchesSelector))&&ja(function(a){c.disconnectedMatch=s.call(a,"div"),s.call(a,"[s!='']:x"),r.push("!=",P)}),q=q.length&&new RegExp(q.join("|")),r=r.length&&new RegExp(r.join("|")),b=$.test(o.compareDocumentPosition),t=b||$.test(o.contains)?function(a,b){var c=9===a.nodeType?a.documentElement:a,d=b&&b.parentNode;return a===d||!(!d||1!==d.nodeType||!(c.contains?c.contains(d):a.compareDocumentPosition&&16&a.compareDocumentPosition(d)))}:function(a,b){if(b)while(b=b.parentNode)if(b===a)return!0;return!1},B=b?function(a,b){if(a===b)return l=!0,0;var d=!a.compareDocumentPosition-!b.compareDocumentPosition;return d?d:(d=(a.ownerDocument||a)===(b.ownerDocument||b)?a.compareDocumentPosition(b):1,1&d||!c.sortDetached&&b.compareDocumentPosition(a)===d?a===g||a.ownerDocument===v&&t(v,a)?-1:b===g||b.ownerDocument===v&&t(v,b)?1:k?J(k,a)-J(k,b):0:4&d?-1:1)}:function(a,b){if(a===b)return l=!0,0;var c,d=0,e=a.parentNode,f=b.parentNode,h=[a],i=[b];if(!e||!f)return a===g?-1:b===g?1:e?-1:f?1:k?J(k,a)-J(k,b):0;if(e===f)return la(a,b);c=a;while(c=c.parentNode)h.unshift(c);c=b;while(c=c.parentNode)i.unshift(c);while(h[d]===i[d])d++;return d?la(h[d],i[d]):h[d]===v?-1:i[d]===v?1:0},g):n},ga.matches=function(a,b){return ga(a,null,null,b)},ga.matchesSelector=function(a,b){if((a.ownerDocument||a)!==n&&m(a),b=b.replace(U,"='$1']"),!(!c.matchesSelector||!p||r&&r.test(b)||q&&q.test(b)))try{var d=s.call(a,b);if(d||c.disconnectedMatch||a.document&&11!==a.document.nodeType)return d}catch(e){}return ga(b,n,null,[a]).length>0},ga.contains=function(a,b){return(a.ownerDocument||a)!==n&&m(a),t(a,b)},ga.attr=function(a,b){(a.ownerDocument||a)!==n&&m(a);var e=d.attrHandle[b.toLowerCase()],f=e&&D.call(d.attrHandle,b.toLowerCase())?e(a,b,!p):void 0;return void 0!==f?f:c.attributes||!p?a.getAttribute(b):(f=a.getAttributeNode(b))&&f.specified?f.value:null},ga.error=function(a){throw new Error("Syntax error, unrecognized expression: "+a)},ga.uniqueSort=function(a){var b,d=[],e=0,f=0;if(l=!c.detectDuplicates,k=!c.sortStable&&a.slice(0),a.sort(B),l){while(b=a[f++])b===a[f]&&(e=d.push(f));while(e--)a.splice(d[e],1)}return k=null,a},e=ga.getText=function(a){var b,c="",d=0,f=a.nodeType;if(f){if(1===f||9===f||11===f){if("string"==typeof a.textContent)return a.textContent;for(a=a.firstChild;a;a=a.nextSibling)c+=e(a)}else if(3===f||4===f)return a.nodeValue}else while(b=a[d++])c+=e(b);return c},d=ga.selectors={cacheLength:50,createPseudo:ia,match:X,attrHandle:{},find:{},relative:{">":{dir:"parentNode",first:!0}," ":{dir:"parentNode"},"+":{dir:"previousSibling",first:!0},"~":{dir:"previousSibling"}},preFilter:{ATTR:function(a){return a[1]=a[1].replace(ca,da),a[3]=(a[3]||a[4]||a[5]||"").replace(ca,da),"~="===a[2]&&(a[3]=" "+a[3]+" "),a.slice(0,4)},CHILD:function(a){return a[1]=a[1].toLowerCase(),"nth"===a[1].slice(0,3)?(a[3]||ga.error(a[0]),a[4]=+(a[4]?a[5]+(a[6]||1):2*("even"===a[3]||"odd"===a[3])),a[5]=+(a[7]+a[8]||"odd"===a[3])):a[3]&&ga.error(a[0]),a},PSEUDO:function(a){var b,c=!a[6]&&a[2];return X.CHILD.test(a[0])?null:(a[3]?a[2]=a[4]||a[5]||"":c&&V.test(c)&&(b=g(c,!0))&&(b=c.indexOf(")",c.length-b)-c.length)&&(a[0]=a[0].slice(0,b),a[2]=c.slice(0,b)),a.slice(0,3))}},filter:{TAG:function(a){var b=a.replace(ca,da).toLowerCase();return"*"===a?function(){return!0}:function(a){return a.nodeName&&a.nodeName.toLowerCase()===b}},CLASS:function(a){var b=y[a+" "];return b||(b=new RegExp("(^|"+L+")"+a+"("+L+"|$)"))&&y(a,function(a){return b.test("string"==typeof a.className&&a.className||"undefined"!=typeof a.getAttribute&&a.getAttribute("class")||"")})},ATTR:function(a,b,c){return function(d){var e=ga.attr(d,a);return null==e?"!="===b:b?(e+="","="===b?e===c:"!="===b?e!==c:"^="===b?c&&0===e.indexOf(c):"*="===b?c&&e.indexOf(c)>-1:"$="===b?c&&e.slice(-c.length)===c:"~="===b?(" "+e.replace(Q," ")+" ").indexOf(c)>-1:"|="===b?e===c||e.slice(0,c.length+1)===c+"-":!1):!0}},CHILD:function(a,b,c,d,e){var f="nth"!==a.slice(0,3),g="last"!==a.slice(-4),h="of-type"===b;return 1===d&&0===e?function(a){return!!a.parentNode}:function(b,c,i){var j,k,l,m,n,o,p=f!==g?"nextSibling":"previousSibling",q=b.parentNode,r=h&&b.nodeName.toLowerCase(),s=!i&&!h;if(q){if(f){while(p){l=b;while(l=l[p])if(h?l.nodeName.toLowerCase()===r:1===l.nodeType)return!1;o=p="only"===a&&!o&&"nextSibling"}return!0}if(o=[g?q.firstChild:q.lastChild],g&&s){k=q[u]||(q[u]={}),j=k[a]||[],n=j[0]===w&&j[1],m=j[0]===w&&j[2],l=n&&q.childNodes[n];while(l=++n&&l&&l[p]||(m=n=0)||o.pop())if(1===l.nodeType&&++m&&l===b){k[a]=[w,n,m];break}}else if(s&&(j=(b[u]||(b[u]={}))[a])&&j[0]===w)m=j[1];else while(l=++n&&l&&l[p]||(m=n=0)||o.pop())if((h?l.nodeName.toLowerCase()===r:1===l.nodeType)&&++m&&(s&&((l[u]||(l[u]={}))[a]=[w,m]),l===b))break;return m-=e,m===d||m%d===0&&m/d>=0}}},PSEUDO:function(a,b){var c,e=d.pseudos[a]||d.setFilters[a.toLowerCase()]||ga.error("unsupported pseudo: "+a);return e[u]?e(b):e.length>1?(c=[a,a,"",b],d.setFilters.hasOwnProperty(a.toLowerCase())?ia(function(a,c){var d,f=e(a,b),g=f.length;while(g--)d=J(a,f[g]),a[d]=!(c[d]=f[g])}):function(a){return e(a,0,c)}):e}},pseudos:{not:ia(function(a){var b=[],c=[],d=h(a.replace(R,"$1"));return d[u]?ia(function(a,b,c,e){var f,g=d(a,null,e,[]),h=a.length;while(h--)(f=g[h])&&(a[h]=!(b[h]=f))}):function(a,e,f){return b[0]=a,d(b,null,f,c),b[0]=null,!c.pop()}}),has:ia(function(a){return function(b){return ga(a,b).length>0}}),contains:ia(function(a){return a=a.replace(ca,da),function(b){return(b.textContent||b.innerText||e(b)).indexOf(a)>-1}}),lang:ia(function(a){return W.test(a||"")||ga.error("unsupported lang: "+a),a=a.replace(ca,da).toLowerCase(),function(b){var c;do if(c=p?b.lang:b.getAttribute("xml:lang")||b.getAttribute("lang"))return c=c.toLowerCase(),c===a||0===c.indexOf(a+"-");while((b=b.parentNode)&&1===b.nodeType);return!1}}),target:function(b){var c=a.location&&a.location.hash;return c&&c.slice(1)===b.id},root:function(a){return a===o},focus:function(a){return a===n.activeElement&&(!n.hasFocus||n.hasFocus())&&!!(a.type||a.href||~a.tabIndex)},enabled:function(a){return a.disabled===!1},disabled:function(a){return a.disabled===!0},checked:function(a){var b=a.nodeName.toLowerCase();return"input"===b&&!!a.checked||"option"===b&&!!a.selected},selected:function(a){return a.parentNode&&a.parentNode.selectedIndex,a.selected===!0},empty:function(a){for(a=a.firstChild;a;a=a.nextSibling)if(a.nodeType<6)return!1;return!0},parent:function(a){return!d.pseudos.empty(a)},header:function(a){return Z.test(a.nodeName)},input:function(a){return Y.test(a.nodeName)},button:function(a){var b=a.nodeName.toLowerCase();return"input"===b&&"button"===a.type||"button"===b},text:function(a){var b;return"input"===a.nodeName.toLowerCase()&&"text"===a.type&&(null==(b=a.getAttribute("type"))||"text"===b.toLowerCase())},first:oa(function(){return[0]}),last:oa(function(a,b){return[b-1]}),eq:oa(function(a,b,c){return[0>c?c+b:c]}),even:oa(function(a,b){for(var c=0;b>c;c+=2)a.push(c);return a}),odd:oa(function(a,b){for(var c=1;b>c;c+=2)a.push(c);return a}),lt:oa(function(a,b,c){for(var d=0>c?c+b:c;--d>=0;)a.push(d);return a}),gt:oa(function(a,b,c){for(var d=0>c?c+b:c;++d<b;)a.push(d);return a})}},d.pseudos.nth=d.pseudos.eq;for(b in{radio:!0,checkbox:!0,file:!0,password:!0,image:!0})d.pseudos[b]=ma(b);for(b in{submit:!0,reset:!0})d.pseudos[b]=na(b);function qa(){}qa.prototype=d.filters=d.pseudos,d.setFilters=new qa,g=ga.tokenize=function(a,b){var c,e,f,g,h,i,j,k=z[a+" "];if(k)return b?0:k.slice(0);h=a,i=[],j=d.preFilter;while(h){(!c||(e=S.exec(h)))&&(e&&(h=h.slice(e[0].length)||h),i.push(f=[])),c=!1,(e=T.exec(h))&&(c=e.shift(),f.push({value:c,type:e[0].replace(R," ")}),h=h.slice(c.length));for(g in d.filter)!(e=X[g].exec(h))||j[g]&&!(e=j[g](e))||(c=e.shift(),f.push({value:c,type:g,matches:e}),h=h.slice(c.length));if(!c)break}return b?h.length:h?ga.error(a):z(a,i).slice(0)};function ra(a){for(var b=0,c=a.length,d="";c>b;b++)d+=a[b].value;return d}function sa(a,b,c){var d=b.dir,e=c&&"parentNode"===d,f=x++;return b.first?function(b,c,f){while(b=b[d])if(1===b.nodeType||e)return a(b,c,f)}:function(b,c,g){var h,i,j=[w,f];if(g){while(b=b[d])if((1===b.nodeType||e)&&a(b,c,g))return!0}else while(b=b[d])if(1===b.nodeType||e){if(i=b[u]||(b[u]={}),(h=i[d])&&h[0]===w&&h[1]===f)return j[2]=h[2];if(i[d]=j,j[2]=a(b,c,g))return!0}}}function ta(a){return a.length>1?function(b,c,d){var e=a.length;while(e--)if(!a[e](b,c,d))return!1;return!0}:a[0]}function ua(a,b,c){for(var d=0,e=b.length;e>d;d++)ga(a,b[d],c);return c}function va(a,b,c,d,e){for(var f,g=[],h=0,i=a.length,j=null!=b;i>h;h++)(f=a[h])&&(!c||c(f,d,e))&&(g.push(f),j&&b.push(h));return g}function wa(a,b,c,d,e,f){return d&&!d[u]&&(d=wa(d)),e&&!e[u]&&(e=wa(e,f)),ia(function(f,g,h,i){var j,k,l,m=[],n=[],o=g.length,p=f||ua(b||"*",h.nodeType?[h]:h,[]),q=!a||!f&&b?p:va(p,m,a,h,i),r=c?e||(f?a:o||d)?[]:g:q;if(c&&c(q,r,h,i),d){j=va(r,n),d(j,[],h,i),k=j.length;while(k--)(l=j[k])&&(r[n[k]]=!(q[n[k]]=l))}if(f){if(e||a){if(e){j=[],k=r.length;while(k--)(l=r[k])&&j.push(q[k]=l);e(null,r=[],j,i)}k=r.length;while(k--)(l=r[k])&&(j=e?J(f,l):m[k])>-1&&(f[j]=!(g[j]=l))}}else r=va(r===g?r.splice(o,r.length):r),e?e(null,g,r,i):H.apply(g,r)})}function xa(a){for(var b,c,e,f=a.length,g=d.relative[a[0].type],h=g||d.relative[" "],i=g?1:0,k=sa(function(a){return a===b},h,!0),l=sa(function(a){return J(b,a)>-1},h,!0),m=[function(a,c,d){var e=!g&&(d||c!==j)||((b=c).nodeType?k(a,c,d):l(a,c,d));return b=null,e}];f>i;i++)if(c=d.relative[a[i].type])m=[sa(ta(m),c)];else{if(c=d.filter[a[i].type].apply(null,a[i].matches),c[u]){for(e=++i;f>e;e++)if(d.relative[a[e].type])break;return wa(i>1&&ta(m),i>1&&ra(a.slice(0,i-1).concat({value:" "===a[i-2].type?"*":""})).replace(R,"$1"),c,e>i&&xa(a.slice(i,e)),f>e&&xa(a=a.slice(e)),f>e&&ra(a))}m.push(c)}return ta(m)}function ya(a,b){var c=b.length>0,e=a.length>0,f=function(f,g,h,i,k){var l,m,o,p=0,q="0",r=f&&[],s=[],t=j,u=f||e&&d.find.TAG("*",k),v=w+=null==t?1:Math.random()||.1,x=u.length;for(k&&(j=g!==n&&g);q!==x&&null!=(l=u[q]);q++){if(e&&l){m=0;while(o=a[m++])if(o(l,g,h)){i.push(l);break}k&&(w=v)}c&&((l=!o&&l)&&p--,f&&r.push(l))}if(p+=q,c&&q!==p){m=0;while(o=b[m++])o(r,s,g,h);if(f){if(p>0)while(q--)r[q]||s[q]||(s[q]=F.call(i));s=va(s)}H.apply(i,s),k&&!f&&s.length>0&&p+b.length>1&&ga.uniqueSort(i)}return k&&(w=v,j=t),r};return c?ia(f):f}return h=ga.compile=function(a,b){var c,d=[],e=[],f=A[a+" "];if(!f){b||(b=g(a)),c=b.length;while(c--)f=xa(b[c]),f[u]?d.push(f):e.push(f);f=A(a,ya(e,d)),f.selector=a}return f},i=ga.select=function(a,b,e,f){var i,j,k,l,m,n="function"==typeof a&&a,o=!f&&g(a=n.selector||a);if(e=e||[],1===o.length){if(j=o[0]=o[0].slice(0),j.length>2&&"ID"===(k=j[0]).type&&c.getById&&9===b.nodeType&&p&&d.relative[j[1].type]){if(b=(d.find.ID(k.matches[0].replace(ca,da),b)||[])[0],!b)return e;n&&(b=b.parentNode),a=a.slice(j.shift().value.length)}i=X.needsContext.test(a)?0:j.length;while(i--){if(k=j[i],d.relative[l=k.type])break;if((m=d.find[l])&&(f=m(k.matches[0].replace(ca,da),aa.test(j[0].type)&&pa(b.parentNode)||b))){if(j.splice(i,1),a=f.length&&ra(j),!a)return H.apply(e,f),e;break}}}return(n||h(a,o))(f,b,!p,e,aa.test(a)&&pa(b.parentNode)||b),e},c.sortStable=u.split("").sort(B).join("")===u,c.detectDuplicates=!!l,m(),c.sortDetached=ja(function(a){return 1&a.compareDocumentPosition(n.createElement("div"))}),ja(function(a){return a.innerHTML="<a href='#'></a>","#"===a.firstChild.getAttribute("href")})||ka("type|href|height|width",function(a,b,c){return c?void 0:a.getAttribute(b,"type"===b.toLowerCase()?1:2)}),c.attributes&&ja(function(a){return a.innerHTML="<input/>",a.firstChild.setAttribute("value",""),""===a.firstChild.getAttribute("value")})||ka("value",function(a,b,c){return c||"input"!==a.nodeName.toLowerCase()?void 0:a.defaultValue}),ja(function(a){return null==a.getAttribute("disabled")})||ka(K,function(a,b,c){var d;return c?void 0:a[b]===!0?b.toLowerCase():(d=a.getAttributeNode(b))&&d.specified?d.value:null}),ga}(a);n.find=t,n.expr=t.selectors,n.expr[":"]=n.expr.pseudos,n.unique=t.uniqueSort,n.text=t.getText,n.isXMLDoc=t.isXML,n.contains=t.contains;var u=n.expr.match.needsContext,v=/^<(\w+)\s*\/?>(?:<\/\1>|)$/,w=/^.[^:#\[\.,]*$/;function x(a,b,c){if(n.isFunction(b))return n.grep(a,function(a,d){return!!b.call(a,d,a)!==c});if(b.nodeType)return n.grep(a,function(a){return a===b!==c});if("string"==typeof b){if(w.test(b))return n.filter(b,a,c);b=n.filter(b,a)}return n.grep(a,function(a){return g.call(b,a)>=0!==c})}n.filter=function(a,b,c){var d=b[0];return c&&(a=":not("+a+")"),1===b.length&&1===d.nodeType?n.find.matchesSelector(d,a)?[d]:[]:n.find.matches(a,n.grep(b,function(a){return 1===a.nodeType}))},n.fn.extend({find:function(a){var b,c=this.length,d=[],e=this;if("string"!=typeof a)return this.pushStack(n(a).filter(function(){for(b=0;c>b;b++)if(n.contains(e[b],this))return!0}));for(b=0;c>b;b++)n.find(a,e[b],d);return d=this.pushStack(c>1?n.unique(d):d),d.selector=this.selector?this.selector+" "+a:a,d},filter:function(a){return this.pushStack(x(this,a||[],!1))},not:function(a){return this.pushStack(x(this,a||[],!0))},is:function(a){return!!x(this,"string"==typeof a&&u.test(a)?n(a):a||[],!1).length}});var y,z=/^(?:\s*(<[\w\W]+>)[^>]*|#([\w-]*))$/,A=n.fn.init=function(a,b){var c,d;if(!a)return this;if("string"==typeof a){if(c="<"===a[0]&&">"===a[a.length-1]&&a.length>=3?[null,a,null]:z.exec(a),!c||!c[1]&&b)return!b||b.jquery?(b||y).find(a):this.constructor(b).find(a);if(c[1]){if(b=b instanceof n?b[0]:b,n.merge(this,n.parseHTML(c[1],b&&b.nodeType?b.ownerDocument||b:l,!0)),v.test(c[1])&&n.isPlainObject(b))for(c in b)n.isFunction(this[c])?this[c](b[c]):this.attr(c,b[c]);return this}return d=l.getElementById(c[2]),d&&d.parentNode&&(this.length=1,this[0]=d),this.context=l,this.selector=a,this}return a.nodeType?(this.context=this[0]=a,this.length=1,this):n.isFunction(a)?"undefined"!=typeof y.ready?y.ready(a):a(n):(void 0!==a.selector&&(this.selector=a.selector,this.context=a.context),n.makeArray(a,this))};A.prototype=n.fn,y=n(l);var B=/^(?:parents|prev(?:Until|All))/,C={children:!0,contents:!0,next:!0,prev:!0};n.extend({dir:function(a,b,c){var d=[],e=void 0!==c;while((a=a[b])&&9!==a.nodeType)if(1===a.nodeType){if(e&&n(a).is(c))break;d.push(a)}return d},sibling:function(a,b){for(var c=[];a;a=a.nextSibling)1===a.nodeType&&a!==b&&c.push(a);return c}}),n.fn.extend({has:function(a){var b=n(a,this),c=b.length;return this.filter(function(){for(var a=0;c>a;a++)if(n.contains(this,b[a]))return!0})},closest:function(a,b){for(var c,d=0,e=this.length,f=[],g=u.test(a)||"string"!=typeof a?n(a,b||this.context):0;e>d;d++)for(c=this[d];c&&c!==b;c=c.parentNode)if(c.nodeType<11&&(g?g.index(c)>-1:1===c.nodeType&&n.find.matchesSelector(c,a))){f.push(c);break}return this.pushStack(f.length>1?n.unique(f):f)},index:function(a){return a?"string"==typeof a?g.call(n(a),this[0]):g.call(this,a.jquery?a[0]:a):this[0]&&this[0].parentNode?this.first().prevAll().length:-1},add:function(a,b){return this.pushStack(n.unique(n.merge(this.get(),n(a,b))))},addBack:function(a){return this.add(null==a?this.prevObject:this.prevObject.filter(a))}});function D(a,b){while((a=a[b])&&1!==a.nodeType);return a}n.each({parent:function(a){var b=a.parentNode;return b&&11!==b.nodeType?b:null},parents:function(a){return n.dir(a,"parentNode")},parentsUntil:function(a,b,c){return n.dir(a,"parentNode",c)},next:function(a){return D(a,"nextSibling")},prev:function(a){return D(a,"previousSibling")},nextAll:function(a){return n.dir(a,"nextSibling")},prevAll:function(a){return n.dir(a,"previousSibling")},nextUntil:function(a,b,c){return n.dir(a,"nextSibling",c)},prevUntil:function(a,b,c){return n.dir(a,"previousSibling",c)},siblings:function(a){return n.sibling((a.parentNode||{}).firstChild,a)},children:function(a){return n.sibling(a.firstChild)},contents:function(a){return a.contentDocument||n.merge([],a.childNodes)}},function(a,b){n.fn[a]=function(c,d){var e=n.map(this,b,c);return"Until"!==a.slice(-5)&&(d=c),d&&"string"==typeof d&&(e=n.filter(d,e)),this.length>1&&(C[a]||n.unique(e),B.test(a)&&e.reverse()),this.pushStack(e)}});var E=/\S+/g,F={};function G(a){var b=F[a]={};return n.each(a.match(E)||[],function(a,c){b[c]=!0}),b}n.Callbacks=function(a){a="string"==typeof a?F[a]||G(a):n.extend({},a);var b,c,d,e,f,g,h=[],i=!a.once&&[],j=function(l){for(b=a.memory&&l,c=!0,g=e||0,e=0,f=h.length,d=!0;h&&f>g;g++)if(h[g].apply(l[0],l[1])===!1&&a.stopOnFalse){b=!1;break}d=!1,h&&(i?i.length&&j(i.shift()):b?h=[]:k.disable())},k={add:function(){if(h){var c=h.length;!function g(b){n.each(b,function(b,c){var d=n.type(c);"function"===d?a.unique&&k.has(c)||h.push(c):c&&c.length&&"string"!==d&&g(c)})}(arguments),d?f=h.length:b&&(e=c,j(b))}return this},remove:function(){return h&&n.each(arguments,function(a,b){var c;while((c=n.inArray(b,h,c))>-1)h.splice(c,1),d&&(f>=c&&f--,g>=c&&g--)}),this},has:function(a){return a?n.inArray(a,h)>-1:!(!h||!h.length)},empty:function(){return h=[],f=0,this},disable:function(){return h=i=b=void 0,this},disabled:function(){return!h},lock:function(){return i=void 0,b||k.disable(),this},locked:function(){return!i},fireWith:function(a,b){return!h||c&&!i||(b=b||[],b=[a,b.slice?b.slice():b],d?i.push(b):j(b)),this},fire:function(){return k.fireWith(this,arguments),this},fired:function(){return!!c}};return k},n.extend({Deferred:function(a){var b=[["resolve","done",n.Callbacks("once memory"),"resolved"],["reject","fail",n.Callbacks("once memory"),"rejected"],["notify","progress",n.Callbacks("memory")]],c="pending",d={state:function(){return c},always:function(){return e.done(arguments).fail(arguments),this},then:function(){var a=arguments;return n.Deferred(function(c){n.each(b,function(b,f){var g=n.isFunction(a[b])&&a[b];e[f[1]](function(){var a=g&&g.apply(this,arguments);a&&n.isFunction(a.promise)?a.promise().done(c.resolve).fail(c.reject).progress(c.notify):c[f[0]+"With"](this===d?c.promise():this,g?[a]:arguments)})}),a=null}).promise()},promise:function(a){return null!=a?n.extend(a,d):d}},e={};return d.pipe=d.then,n.each(b,function(a,f){var g=f[2],h=f[3];d[f[1]]=g.add,h&&g.add(function(){c=h},b[1^a][2].disable,b[2][2].lock),e[f[0]]=function(){return e[f[0]+"With"](this===e?d:this,arguments),this},e[f[0]+"With"]=g.fireWith}),d.promise(e),a&&a.call(e,e),e},when:function(a){var b=0,c=d.call(arguments),e=c.length,f=1!==e||a&&n.isFunction(a.promise)?e:0,g=1===f?a:n.Deferred(),h=function(a,b,c){return function(e){b[a]=this,c[a]=arguments.length>1?d.call(arguments):e,c===i?g.notifyWith(b,c):--f||g.resolveWith(b,c)}},i,j,k;if(e>1)for(i=new Array(e),j=new Array(e),k=new Array(e);e>b;b++)c[b]&&n.isFunction(c[b].promise)?c[b].promise().done(h(b,k,c)).fail(g.reject).progress(h(b,j,i)):--f;return f||g.resolveWith(k,c),g.promise()}});var H;n.fn.ready=function(a){return n.ready.promise().done(a),this},n.extend({isReady:!1,readyWait:1,holdReady:function(a){a?n.readyWait++:n.ready(!0)},ready:function(a){(a===!0?--n.readyWait:n.isReady)||(n.isReady=!0,a!==!0&&--n.readyWait>0||(H.resolveWith(l,[n]),n.fn.triggerHandler&&(n(l).triggerHandler("ready"),n(l).off("ready"))))}});function I(){l.removeEventListener("DOMContentLoaded",I,!1),a.removeEventListener("load",I,!1),n.ready()}n.ready.promise=function(b){return H||(H=n.Deferred(),"complete"===l.readyState?setTimeout(n.ready):(l.addEventListener("DOMContentLoaded",I,!1),a.addEventListener("load",I,!1))),H.promise(b)},n.ready.promise();var J=n.access=function(a,b,c,d,e,f,g){var h=0,i=a.length,j=null==c;if("object"===n.type(c)){e=!0;for(h in c)n.access(a,b,h,c[h],!0,f,g)}else if(void 0!==d&&(e=!0,n.isFunction(d)||(g=!0),j&&(g?(b.call(a,d),b=null):(j=b,b=function(a,b,c){return j.call(n(a),c)})),b))for(;i>h;h++)b(a[h],c,g?d:d.call(a[h],h,b(a[h],c)));return e?a:j?b.call(a):i?b(a[0],c):f};n.acceptData=function(a){return 1===a.nodeType||9===a.nodeType||!+a.nodeType};function K(){Object.defineProperty(this.cache={},0,{get:function(){return{}}}),this.expando=n.expando+K.uid++}K.uid=1,K.accepts=n.acceptData,K.prototype={key:function(a){if(!K.accepts(a))return 0;var b={},c=a[this.expando];if(!c){c=K.uid++;try{b[this.expando]={value:c},Object.defineProperties(a,b)}catch(d){b[this.expando]=c,n.extend(a,b)}}return this.cache[c]||(this.cache[c]={}),c},set:function(a,b,c){var d,e=this.key(a),f=this.cache[e];if("string"==typeof b)f[b]=c;else if(n.isEmptyObject(f))n.extend(this.cache[e],b);else for(d in b)f[d]=b[d];return f},get:function(a,b){var c=this.cache[this.key(a)];return void 0===b?c:c[b]},access:function(a,b,c){var d;return void 0===b||b&&"string"==typeof b&&void 0===c?(d=this.get(a,b),void 0!==d?d:this.get(a,n.camelCase(b))):(this.set(a,b,c),void 0!==c?c:b)},remove:function(a,b){var c,d,e,f=this.key(a),g=this.cache[f];if(void 0===b)this.cache[f]={};else{n.isArray(b)?d=b.concat(b.map(n.camelCase)):(e=n.camelCase(b),b in g?d=[b,e]:(d=e,d=d in g?[d]:d.match(E)||[])),c=d.length;while(c--)delete g[d[c]]}},hasData:function(a){return!n.isEmptyObject(this.cache[a[this.expando]]||{})},discard:function(a){a[this.expando]&&delete this.cache[a[this.expando]]}};var L=new K,M=new K,N=/^(?:\{[\w\W]*\}|\[[\w\W]*\])$/,O=/([A-Z])/g;function P(a,b,c){var d;if(void 0===c&&1===a.nodeType)if(d="data-"+b.replace(O,"-$1").toLowerCase(),c=a.getAttribute(d),"string"==typeof c){try{c="true"===c?!0:"false"===c?!1:"null"===c?null:+c+""===c?+c:N.test(c)?n.parseJSON(c):c}catch(e){}M.set(a,b,c)}else c=void 0;return c}n.extend({hasData:function(a){return M.hasData(a)||L.hasData(a)},data:function(a,b,c){
return M.access(a,b,c)},removeData:function(a,b){M.remove(a,b)},_data:function(a,b,c){return L.access(a,b,c)},_removeData:function(a,b){L.remove(a,b)}}),n.fn.extend({data:function(a,b){var c,d,e,f=this[0],g=f&&f.attributes;if(void 0===a){if(this.length&&(e=M.get(f),1===f.nodeType&&!L.get(f,"hasDataAttrs"))){c=g.length;while(c--)g[c]&&(d=g[c].name,0===d.indexOf("data-")&&(d=n.camelCase(d.slice(5)),P(f,d,e[d])));L.set(f,"hasDataAttrs",!0)}return e}return"object"==typeof a?this.each(function(){M.set(this,a)}):J(this,function(b){var c,d=n.camelCase(a);if(f&&void 0===b){if(c=M.get(f,a),void 0!==c)return c;if(c=M.get(f,d),void 0!==c)return c;if(c=P(f,d,void 0),void 0!==c)return c}else this.each(function(){var c=M.get(this,d);M.set(this,d,b),-1!==a.indexOf("-")&&void 0!==c&&M.set(this,a,b)})},null,b,arguments.length>1,null,!0)},removeData:function(a){return this.each(function(){M.remove(this,a)})}}),n.extend({queue:function(a,b,c){var d;return a?(b=(b||"fx")+"queue",d=L.get(a,b),c&&(!d||n.isArray(c)?d=L.access(a,b,n.makeArray(c)):d.push(c)),d||[]):void 0},dequeue:function(a,b){b=b||"fx";var c=n.queue(a,b),d=c.length,e=c.shift(),f=n._queueHooks(a,b),g=function(){n.dequeue(a,b)};"inprogress"===e&&(e=c.shift(),d--),e&&("fx"===b&&c.unshift("inprogress"),delete f.stop,e.call(a,g,f)),!d&&f&&f.empty.fire()},_queueHooks:function(a,b){var c=b+"queueHooks";return L.get(a,c)||L.access(a,c,{empty:n.Callbacks("once memory").add(function(){L.remove(a,[b+"queue",c])})})}}),n.fn.extend({queue:function(a,b){var c=2;return"string"!=typeof a&&(b=a,a="fx",c--),arguments.length<c?n.queue(this[0],a):void 0===b?this:this.each(function(){var c=n.queue(this,a,b);n._queueHooks(this,a),"fx"===a&&"inprogress"!==c[0]&&n.dequeue(this,a)})},dequeue:function(a){return this.each(function(){n.dequeue(this,a)})},clearQueue:function(a){return this.queue(a||"fx",[])},promise:function(a,b){var c,d=1,e=n.Deferred(),f=this,g=this.length,h=function(){--d||e.resolveWith(f,[f])};"string"!=typeof a&&(b=a,a=void 0),a=a||"fx";while(g--)c=L.get(f[g],a+"queueHooks"),c&&c.empty&&(d++,c.empty.add(h));return h(),e.promise(b)}});var Q=/[+-]?(?:\d*\.|)\d+(?:[eE][+-]?\d+|)/.source,R=["Top","Right","Bottom","Left"],S=function(a,b){return a=b||a,"none"===n.css(a,"display")||!n.contains(a.ownerDocument,a)},T=/^(?:checkbox|radio)$/i;!function(){var a=l.createDocumentFragment(),b=a.appendChild(l.createElement("div")),c=l.createElement("input");c.setAttribute("type","radio"),c.setAttribute("checked","checked"),c.setAttribute("name","t"),b.appendChild(c),k.checkClone=b.cloneNode(!0).cloneNode(!0).lastChild.checked,b.innerHTML="<textarea>x</textarea>",k.noCloneChecked=!!b.cloneNode(!0).lastChild.defaultValue}();var U="undefined";k.focusinBubbles="onfocusin"in a;var V=/^key/,W=/^(?:mouse|pointer|contextmenu)|click/,X=/^(?:focusinfocus|focusoutblur)$/,Y=/^([^.]*)(?:\.(.+)|)$/;function Z(){return!0}function $(){return!1}function _(){try{return l.activeElement}catch(a){}}n.event={global:{},add:function(a,b,c,d,e){var f,g,h,i,j,k,l,m,o,p,q,r=L.get(a);if(r){c.handler&&(f=c,c=f.handler,e=f.selector),c.guid||(c.guid=n.guid++),(i=r.events)||(i=r.events={}),(g=r.handle)||(g=r.handle=function(b){return typeof n!==U&&n.event.triggered!==b.type?n.event.dispatch.apply(a,arguments):void 0}),b=(b||"").match(E)||[""],j=b.length;while(j--)h=Y.exec(b[j])||[],o=q=h[1],p=(h[2]||"").split(".").sort(),o&&(l=n.event.special[o]||{},o=(e?l.delegateType:l.bindType)||o,l=n.event.special[o]||{},k=n.extend({type:o,origType:q,data:d,handler:c,guid:c.guid,selector:e,needsContext:e&&n.expr.match.needsContext.test(e),namespace:p.join(".")},f),(m=i[o])||(m=i[o]=[],m.delegateCount=0,l.setup&&l.setup.call(a,d,p,g)!==!1||a.addEventListener&&a.addEventListener(o,g,!1)),l.add&&(l.add.call(a,k),k.handler.guid||(k.handler.guid=c.guid)),e?m.splice(m.delegateCount++,0,k):m.push(k),n.event.global[o]=!0)}},remove:function(a,b,c,d,e){var f,g,h,i,j,k,l,m,o,p,q,r=L.hasData(a)&&L.get(a);if(r&&(i=r.events)){b=(b||"").match(E)||[""],j=b.length;while(j--)if(h=Y.exec(b[j])||[],o=q=h[1],p=(h[2]||"").split(".").sort(),o){l=n.event.special[o]||{},o=(d?l.delegateType:l.bindType)||o,m=i[o]||[],h=h[2]&&new RegExp("(^|\\.)"+p.join("\\.(?:.*\\.|)")+"(\\.|$)"),g=f=m.length;while(f--)k=m[f],!e&&q!==k.origType||c&&c.guid!==k.guid||h&&!h.test(k.namespace)||d&&d!==k.selector&&("**"!==d||!k.selector)||(m.splice(f,1),k.selector&&m.delegateCount--,l.remove&&l.remove.call(a,k));g&&!m.length&&(l.teardown&&l.teardown.call(a,p,r.handle)!==!1||n.removeEvent(a,o,r.handle),delete i[o])}else for(o in i)n.event.remove(a,o+b[j],c,d,!0);n.isEmptyObject(i)&&(delete r.handle,L.remove(a,"events"))}},trigger:function(b,c,d,e){var f,g,h,i,k,m,o,p=[d||l],q=j.call(b,"type")?b.type:b,r=j.call(b,"namespace")?b.namespace.split("."):[];if(g=h=d=d||l,3!==d.nodeType&&8!==d.nodeType&&!X.test(q+n.event.triggered)&&(q.indexOf(".")>=0&&(r=q.split("."),q=r.shift(),r.sort()),k=q.indexOf(":")<0&&"on"+q,b=b[n.expando]?b:new n.Event(q,"object"==typeof b&&b),b.isTrigger=e?2:3,b.namespace=r.join("."),b.namespace_re=b.namespace?new RegExp("(^|\\.)"+r.join("\\.(?:.*\\.|)")+"(\\.|$)"):null,b.result=void 0,b.target||(b.target=d),c=null==c?[b]:n.makeArray(c,[b]),o=n.event.special[q]||{},e||!o.trigger||o.trigger.apply(d,c)!==!1)){if(!e&&!o.noBubble&&!n.isWindow(d)){for(i=o.delegateType||q,X.test(i+q)||(g=g.parentNode);g;g=g.parentNode)p.push(g),h=g;h===(d.ownerDocument||l)&&p.push(h.defaultView||h.parentWindow||a)}f=0;while((g=p[f++])&&!b.isPropagationStopped())b.type=f>1?i:o.bindType||q,m=(L.get(g,"events")||{})[b.type]&&L.get(g,"handle"),m&&m.apply(g,c),m=k&&g[k],m&&m.apply&&n.acceptData(g)&&(b.result=m.apply(g,c),b.result===!1&&b.preventDefault());return b.type=q,e||b.isDefaultPrevented()||o._default&&o._default.apply(p.pop(),c)!==!1||!n.acceptData(d)||k&&n.isFunction(d[q])&&!n.isWindow(d)&&(h=d[k],h&&(d[k]=null),n.event.triggered=q,d[q](),n.event.triggered=void 0,h&&(d[k]=h)),b.result}},dispatch:function(a){a=n.event.fix(a);var b,c,e,f,g,h=[],i=d.call(arguments),j=(L.get(this,"events")||{})[a.type]||[],k=n.event.special[a.type]||{};if(i[0]=a,a.delegateTarget=this,!k.preDispatch||k.preDispatch.call(this,a)!==!1){h=n.event.handlers.call(this,a,j),b=0;while((f=h[b++])&&!a.isPropagationStopped()){a.currentTarget=f.elem,c=0;while((g=f.handlers[c++])&&!a.isImmediatePropagationStopped())(!a.namespace_re||a.namespace_re.test(g.namespace))&&(a.handleObj=g,a.data=g.data,e=((n.event.special[g.origType]||{}).handle||g.handler).apply(f.elem,i),void 0!==e&&(a.result=e)===!1&&(a.preventDefault(),a.stopPropagation()))}return k.postDispatch&&k.postDispatch.call(this,a),a.result}},handlers:function(a,b){var c,d,e,f,g=[],h=b.delegateCount,i=a.target;if(h&&i.nodeType&&(!a.button||"click"!==a.type))for(;i!==this;i=i.parentNode||this)if(i.disabled!==!0||"click"!==a.type){for(d=[],c=0;h>c;c++)f=b[c],e=f.selector+" ",void 0===d[e]&&(d[e]=f.needsContext?n(e,this).index(i)>=0:n.find(e,this,null,[i]).length),d[e]&&d.push(f);d.length&&g.push({elem:i,handlers:d})}return h<b.length&&g.push({elem:this,handlers:b.slice(h)}),g},props:"altKey bubbles cancelable ctrlKey currentTarget eventPhase metaKey relatedTarget shiftKey target timeStamp view which".split(" "),fixHooks:{},keyHooks:{props:"char charCode key keyCode".split(" "),filter:function(a,b){return null==a.which&&(a.which=null!=b.charCode?b.charCode:b.keyCode),a}},mouseHooks:{props:"button buttons clientX clientY offsetX offsetY pageX pageY screenX screenY toElement".split(" "),filter:function(a,b){var c,d,e,f=b.button;return null==a.pageX&&null!=b.clientX&&(c=a.target.ownerDocument||l,d=c.documentElement,e=c.body,a.pageX=b.clientX+(d&&d.scrollLeft||e&&e.scrollLeft||0)-(d&&d.clientLeft||e&&e.clientLeft||0),a.pageY=b.clientY+(d&&d.scrollTop||e&&e.scrollTop||0)-(d&&d.clientTop||e&&e.clientTop||0)),a.which||void 0===f||(a.which=1&f?1:2&f?3:4&f?2:0),a}},fix:function(a){if(a[n.expando])return a;var b,c,d,e=a.type,f=a,g=this.fixHooks[e];g||(this.fixHooks[e]=g=W.test(e)?this.mouseHooks:V.test(e)?this.keyHooks:{}),d=g.props?this.props.concat(g.props):this.props,a=new n.Event(f),b=d.length;while(b--)c=d[b],a[c]=f[c];return a.target||(a.target=l),3===a.target.nodeType&&(a.target=a.target.parentNode),g.filter?g.filter(a,f):a},special:{load:{noBubble:!0},focus:{trigger:function(){return this!==_()&&this.focus?(this.focus(),!1):void 0},delegateType:"focusin"},blur:{trigger:function(){return this===_()&&this.blur?(this.blur(),!1):void 0},delegateType:"focusout"},click:{trigger:function(){return"checkbox"===this.type&&this.click&&n.nodeName(this,"input")?(this.click(),!1):void 0},_default:function(a){return n.nodeName(a.target,"a")}},beforeunload:{postDispatch:function(a){void 0!==a.result&&a.originalEvent&&(a.originalEvent.returnValue=a.result)}}},simulate:function(a,b,c,d){var e=n.extend(new n.Event,c,{type:a,isSimulated:!0,originalEvent:{}});d?n.event.trigger(e,null,b):n.event.dispatch.call(b,e),e.isDefaultPrevented()&&c.preventDefault()}},n.removeEvent=function(a,b,c){a.removeEventListener&&a.removeEventListener(b,c,!1)},n.Event=function(a,b){return this instanceof n.Event?(a&&a.type?(this.originalEvent=a,this.type=a.type,this.isDefaultPrevented=a.defaultPrevented||void 0===a.defaultPrevented&&a.returnValue===!1?Z:$):this.type=a,b&&n.extend(this,b),this.timeStamp=a&&a.timeStamp||n.now(),void(this[n.expando]=!0)):new n.Event(a,b)},n.Event.prototype={isDefaultPrevented:$,isPropagationStopped:$,isImmediatePropagationStopped:$,preventDefault:function(){var a=this.originalEvent;this.isDefaultPrevented=Z,a&&a.preventDefault&&a.preventDefault()},stopPropagation:function(){var a=this.originalEvent;this.isPropagationStopped=Z,a&&a.stopPropagation&&a.stopPropagation()},stopImmediatePropagation:function(){var a=this.originalEvent;this.isImmediatePropagationStopped=Z,a&&a.stopImmediatePropagation&&a.stopImmediatePropagation(),this.stopPropagation()}},n.each({mouseenter:"mouseover",mouseleave:"mouseout",pointerenter:"pointerover",pointerleave:"pointerout"},function(a,b){n.event.special[a]={delegateType:b,bindType:b,handle:function(a){var c,d=this,e=a.relatedTarget,f=a.handleObj;return(!e||e!==d&&!n.contains(d,e))&&(a.type=f.origType,c=f.handler.apply(this,arguments),a.type=b),c}}}),k.focusinBubbles||n.each({focus:"focusin",blur:"focusout"},function(a,b){var c=function(a){n.event.simulate(b,a.target,n.event.fix(a),!0)};n.event.special[b]={setup:function(){var d=this.ownerDocument||this,e=L.access(d,b);e||d.addEventListener(a,c,!0),L.access(d,b,(e||0)+1)},teardown:function(){var d=this.ownerDocument||this,e=L.access(d,b)-1;e?L.access(d,b,e):(d.removeEventListener(a,c,!0),L.remove(d,b))}}}),n.fn.extend({on:function(a,b,c,d,e){var f,g;if("object"==typeof a){"string"!=typeof b&&(c=c||b,b=void 0);for(g in a)this.on(g,b,c,a[g],e);return this}if(null==c&&null==d?(d=b,c=b=void 0):null==d&&("string"==typeof b?(d=c,c=void 0):(d=c,c=b,b=void 0)),d===!1)d=$;else if(!d)return this;return 1===e&&(f=d,d=function(a){return n().off(a),f.apply(this,arguments)},d.guid=f.guid||(f.guid=n.guid++)),this.each(function(){n.event.add(this,a,d,c,b)})},one:function(a,b,c,d){return this.on(a,b,c,d,1)},off:function(a,b,c){var d,e;if(a&&a.preventDefault&&a.handleObj)return d=a.handleObj,n(a.delegateTarget).off(d.namespace?d.origType+"."+d.namespace:d.origType,d.selector,d.handler),this;if("object"==typeof a){for(e in a)this.off(e,b,a[e]);return this}return(b===!1||"function"==typeof b)&&(c=b,b=void 0),c===!1&&(c=$),this.each(function(){n.event.remove(this,a,c,b)})},trigger:function(a,b){return this.each(function(){n.event.trigger(a,b,this)})},triggerHandler:function(a,b){var c=this[0];return c?n.event.trigger(a,b,c,!0):void 0}});var aa=/<(?!area|br|col|embed|hr|img|input|link|meta|param)(([\w:]+)[^>]*)\/>/gi,ba=/<([\w:]+)/,ca=/<|&#?\w+;/,da=/<(?:script|style|link)/i,ea=/checked\s*(?:[^=]|=\s*.checked.)/i,fa=/^$|\/(?:java|ecma)script/i,ga=/^true\/(.*)/,ha=/^\s*<!(?:\[CDATA\[|--)|(?:\]\]|--)>\s*$/g,ia={option:[1,"<select multiple='multiple'>","</select>"],thead:[1,"<table>","</table>"],col:[2,"<table><colgroup>","</colgroup></table>"],tr:[2,"<table><tbody>","</tbody></table>"],td:[3,"<table><tbody><tr>","</tr></tbody></table>"],_default:[0,"",""]};ia.optgroup=ia.option,ia.tbody=ia.tfoot=ia.colgroup=ia.caption=ia.thead,ia.th=ia.td;function ja(a,b){return n.nodeName(a,"table")&&n.nodeName(11!==b.nodeType?b:b.firstChild,"tr")?a.getElementsByTagName("tbody")[0]||a.appendChild(a.ownerDocument.createElement("tbody")):a}function ka(a){return a.type=(null!==a.getAttribute("type"))+"/"+a.type,a}function la(a){var b=ga.exec(a.type);return b?a.type=b[1]:a.removeAttribute("type"),a}function ma(a,b){for(var c=0,d=a.length;d>c;c++)L.set(a[c],"globalEval",!b||L.get(b[c],"globalEval"))}function na(a,b){var c,d,e,f,g,h,i,j;if(1===b.nodeType){if(L.hasData(a)&&(f=L.access(a),g=L.set(b,f),j=f.events)){delete g.handle,g.events={};for(e in j)for(c=0,d=j[e].length;d>c;c++)n.event.add(b,e,j[e][c])}M.hasData(a)&&(h=M.access(a),i=n.extend({},h),M.set(b,i))}}function oa(a,b){var c=a.getElementsByTagName?a.getElementsByTagName(b||"*"):a.querySelectorAll?a.querySelectorAll(b||"*"):[];return void 0===b||b&&n.nodeName(a,b)?n.merge([a],c):c}function pa(a,b){var c=b.nodeName.toLowerCase();"input"===c&&T.test(a.type)?b.checked=a.checked:("input"===c||"textarea"===c)&&(b.defaultValue=a.defaultValue)}n.extend({clone:function(a,b,c){var d,e,f,g,h=a.cloneNode(!0),i=n.contains(a.ownerDocument,a);if(!(k.noCloneChecked||1!==a.nodeType&&11!==a.nodeType||n.isXMLDoc(a)))for(g=oa(h),f=oa(a),d=0,e=f.length;e>d;d++)pa(f[d],g[d]);if(b)if(c)for(f=f||oa(a),g=g||oa(h),d=0,e=f.length;e>d;d++)na(f[d],g[d]);else na(a,h);return g=oa(h,"script"),g.length>0&&ma(g,!i&&oa(a,"script")),h},buildFragment:function(a,b,c,d){for(var e,f,g,h,i,j,k=b.createDocumentFragment(),l=[],m=0,o=a.length;o>m;m++)if(e=a[m],e||0===e)if("object"===n.type(e))n.merge(l,e.nodeType?[e]:e);else if(ca.test(e)){f=f||k.appendChild(b.createElement("div")),g=(ba.exec(e)||["",""])[1].toLowerCase(),h=ia[g]||ia._default,f.innerHTML=h[1]+e.replace(aa,"<$1></$2>")+h[2],j=h[0];while(j--)f=f.lastChild;n.merge(l,f.childNodes),f=k.firstChild,f.textContent=""}else l.push(b.createTextNode(e));k.textContent="",m=0;while(e=l[m++])if((!d||-1===n.inArray(e,d))&&(i=n.contains(e.ownerDocument,e),f=oa(k.appendChild(e),"script"),i&&ma(f),c)){j=0;while(e=f[j++])fa.test(e.type||"")&&c.push(e)}return k},cleanData:function(a){for(var b,c,d,e,f=n.event.special,g=0;void 0!==(c=a[g]);g++){if(n.acceptData(c)&&(e=c[L.expando],e&&(b=L.cache[e]))){if(b.events)for(d in b.events)f[d]?n.event.remove(c,d):n.removeEvent(c,d,b.handle);L.cache[e]&&delete L.cache[e]}delete M.cache[c[M.expando]]}}}),n.fn.extend({text:function(a){return J(this,function(a){return void 0===a?n.text(this):this.empty().each(function(){(1===this.nodeType||11===this.nodeType||9===this.nodeType)&&(this.textContent=a)})},null,a,arguments.length)},append:function(){return this.domManip(arguments,function(a){if(1===this.nodeType||11===this.nodeType||9===this.nodeType){var b=ja(this,a);b.appendChild(a)}})},prepend:function(){return this.domManip(arguments,function(a){if(1===this.nodeType||11===this.nodeType||9===this.nodeType){var b=ja(this,a);b.insertBefore(a,b.firstChild)}})},before:function(){return this.domManip(arguments,function(a){this.parentNode&&this.parentNode.insertBefore(a,this)})},after:function(){return this.domManip(arguments,function(a){this.parentNode&&this.parentNode.insertBefore(a,this.nextSibling)})},remove:function(a,b){for(var c,d=a?n.filter(a,this):this,e=0;null!=(c=d[e]);e++)b||1!==c.nodeType||n.cleanData(oa(c)),c.parentNode&&(b&&n.contains(c.ownerDocument,c)&&ma(oa(c,"script")),c.parentNode.removeChild(c));return this},empty:function(){for(var a,b=0;null!=(a=this[b]);b++)1===a.nodeType&&(n.cleanData(oa(a,!1)),a.textContent="");return this},clone:function(a,b){return a=null==a?!1:a,b=null==b?a:b,this.map(function(){return n.clone(this,a,b)})},html:function(a){return J(this,function(a){var b=this[0]||{},c=0,d=this.length;if(void 0===a&&1===b.nodeType)return b.innerHTML;if("string"==typeof a&&!da.test(a)&&!ia[(ba.exec(a)||["",""])[1].toLowerCase()]){a=a.replace(aa,"<$1></$2>");try{for(;d>c;c++)b=this[c]||{},1===b.nodeType&&(n.cleanData(oa(b,!1)),b.innerHTML=a);b=0}catch(e){}}b&&this.empty().append(a)},null,a,arguments.length)},replaceWith:function(){var a=arguments[0];return this.domManip(arguments,function(b){a=this.parentNode,n.cleanData(oa(this)),a&&a.replaceChild(b,this)}),a&&(a.length||a.nodeType)?this:this.remove()},detach:function(a){return this.remove(a,!0)},domManip:function(a,b){a=e.apply([],a);var c,d,f,g,h,i,j=0,l=this.length,m=this,o=l-1,p=a[0],q=n.isFunction(p);if(q||l>1&&"string"==typeof p&&!k.checkClone&&ea.test(p))return this.each(function(c){var d=m.eq(c);q&&(a[0]=p.call(this,c,d.html())),d.domManip(a,b)});if(l&&(c=n.buildFragment(a,this[0].ownerDocument,!1,this),d=c.firstChild,1===c.childNodes.length&&(c=d),d)){for(f=n.map(oa(c,"script"),ka),g=f.length;l>j;j++)h=c,j!==o&&(h=n.clone(h,!0,!0),g&&n.merge(f,oa(h,"script"))),b.call(this[j],h,j);if(g)for(i=f[f.length-1].ownerDocument,n.map(f,la),j=0;g>j;j++)h=f[j],fa.test(h.type||"")&&!L.access(h,"globalEval")&&n.contains(i,h)&&(h.src?n._evalUrl&&n._evalUrl(h.src):n.globalEval(h.textContent.replace(ha,"")))}return this}}),n.each({appendTo:"append",prependTo:"prepend",insertBefore:"before",insertAfter:"after",replaceAll:"replaceWith"},function(a,b){n.fn[a]=function(a){for(var c,d=[],e=n(a),g=e.length-1,h=0;g>=h;h++)c=h===g?this:this.clone(!0),n(e[h])[b](c),f.apply(d,c.get());return this.pushStack(d)}});var qa,ra={};function sa(b,c){var d,e=n(c.createElement(b)).appendTo(c.body),f=a.getDefaultComputedStyle&&(d=a.getDefaultComputedStyle(e[0]))?d.display:n.css(e[0],"display");return e.detach(),f}function ta(a){var b=l,c=ra[a];return c||(c=sa(a,b),"none"!==c&&c||(qa=(qa||n("<iframe frameborder='0' width='0' height='0'/>")).appendTo(b.documentElement),b=qa[0].contentDocument,b.write(),b.close(),c=sa(a,b),qa.detach()),ra[a]=c),c}var ua=/^margin/,va=new RegExp("^("+Q+")(?!px)[a-z%]+$","i"),wa=function(b){return b.ownerDocument.defaultView.opener?b.ownerDocument.defaultView.getComputedStyle(b,null):a.getComputedStyle(b,null)};function xa(a,b,c){var d,e,f,g,h=a.style;return c=c||wa(a),c&&(g=c.getPropertyValue(b)||c[b]),c&&(""!==g||n.contains(a.ownerDocument,a)||(g=n.style(a,b)),va.test(g)&&ua.test(b)&&(d=h.width,e=h.minWidth,f=h.maxWidth,h.minWidth=h.maxWidth=h.width=g,g=c.width,h.width=d,h.minWidth=e,h.maxWidth=f)),void 0!==g?g+"":g}function ya(a,b){return{get:function(){return a()?void delete this.get:(this.get=b).apply(this,arguments)}}}!function(){var b,c,d=l.documentElement,e=l.createElement("div"),f=l.createElement("div");if(f.style){f.style.backgroundClip="content-box",f.cloneNode(!0).style.backgroundClip="",k.clearCloneStyle="content-box"===f.style.backgroundClip,e.style.cssText="border:0;width:0;height:0;top:0;left:-9999px;margin-top:1px;position:absolute",e.appendChild(f);function g(){f.style.cssText="-webkit-box-sizing:border-box;-moz-box-sizing:border-box;box-sizing:border-box;display:block;margin-top:1%;top:1%;border:1px;padding:1px;width:4px;position:absolute",f.innerHTML="",d.appendChild(e);var g=a.getComputedStyle(f,null);b="1%"!==g.top,c="4px"===g.width,d.removeChild(e)}a.getComputedStyle&&n.extend(k,{pixelPosition:function(){return g(),b},boxSizingReliable:function(){return null==c&&g(),c},reliableMarginRight:function(){var b,c=f.appendChild(l.createElement("div"));return c.style.cssText=f.style.cssText="-webkit-box-sizing:content-box;-moz-box-sizing:content-box;box-sizing:content-box;display:block;margin:0;border:0;padding:0",c.style.marginRight=c.style.width="0",f.style.width="1px",d.appendChild(e),b=!parseFloat(a.getComputedStyle(c,null).marginRight),d.removeChild(e),f.removeChild(c),b}})}}(),n.swap=function(a,b,c,d){var e,f,g={};for(f in b)g[f]=a.style[f],a.style[f]=b[f];e=c.apply(a,d||[]);for(f in b)a.style[f]=g[f];return e};var za=/^(none|table(?!-c[ea]).+)/,Aa=new RegExp("^("+Q+")(.*)$","i"),Ba=new RegExp("^([+-])=("+Q+")","i"),Ca={position:"absolute",visibility:"hidden",display:"block"},Da={letterSpacing:"0",fontWeight:"400"},Ea=["Webkit","O","Moz","ms"];function Fa(a,b){if(b in a)return b;var c=b[0].toUpperCase()+b.slice(1),d=b,e=Ea.length;while(e--)if(b=Ea[e]+c,b in a)return b;return d}function Ga(a,b,c){var d=Aa.exec(b);return d?Math.max(0,d[1]-(c||0))+(d[2]||"px"):b}function Ha(a,b,c,d,e){for(var f=c===(d?"border":"content")?4:"width"===b?1:0,g=0;4>f;f+=2)"margin"===c&&(g+=n.css(a,c+R[f],!0,e)),d?("content"===c&&(g-=n.css(a,"padding"+R[f],!0,e)),"margin"!==c&&(g-=n.css(a,"border"+R[f]+"Width",!0,e))):(g+=n.css(a,"padding"+R[f],!0,e),"padding"!==c&&(g+=n.css(a,"border"+R[f]+"Width",!0,e)));return g}function Ia(a,b,c){var d=!0,e="width"===b?a.offsetWidth:a.offsetHeight,f=wa(a),g="border-box"===n.css(a,"boxSizing",!1,f);if(0>=e||null==e){if(e=xa(a,b,f),(0>e||null==e)&&(e=a.style[b]),va.test(e))return e;d=g&&(k.boxSizingReliable()||e===a.style[b]),e=parseFloat(e)||0}return e+Ha(a,b,c||(g?"border":"content"),d,f)+"px"}function Ja(a,b){for(var c,d,e,f=[],g=0,h=a.length;h>g;g++)d=a[g],d.style&&(f[g]=L.get(d,"olddisplay"),c=d.style.display,b?(f[g]||"none"!==c||(d.style.display=""),""===d.style.display&&S(d)&&(f[g]=L.access(d,"olddisplay",ta(d.nodeName)))):(e=S(d),"none"===c&&e||L.set(d,"olddisplay",e?c:n.css(d,"display"))));for(g=0;h>g;g++)d=a[g],d.style&&(b&&"none"!==d.style.display&&""!==d.style.display||(d.style.display=b?f[g]||"":"none"));return a}n.extend({cssHooks:{opacity:{get:function(a,b){if(b){var c=xa(a,"opacity");return""===c?"1":c}}}},cssNumber:{columnCount:!0,fillOpacity:!0,flexGrow:!0,flexShrink:!0,fontWeight:!0,lineHeight:!0,opacity:!0,order:!0,orphans:!0,widows:!0,zIndex:!0,zoom:!0},cssProps:{"float":"cssFloat"},style:function(a,b,c,d){if(a&&3!==a.nodeType&&8!==a.nodeType&&a.style){var e,f,g,h=n.camelCase(b),i=a.style;return b=n.cssProps[h]||(n.cssProps[h]=Fa(i,h)),g=n.cssHooks[b]||n.cssHooks[h],void 0===c?g&&"get"in g&&void 0!==(e=g.get(a,!1,d))?e:i[b]:(f=typeof c,"string"===f&&(e=Ba.exec(c))&&(c=(e[1]+1)*e[2]+parseFloat(n.css(a,b)),f="number"),null!=c&&c===c&&("number"!==f||n.cssNumber[h]||(c+="px"),k.clearCloneStyle||""!==c||0!==b.indexOf("background")||(i[b]="inherit"),g&&"set"in g&&void 0===(c=g.set(a,c,d))||(i[b]=c)),void 0)}},css:function(a,b,c,d){var e,f,g,h=n.camelCase(b);return b=n.cssProps[h]||(n.cssProps[h]=Fa(a.style,h)),g=n.cssHooks[b]||n.cssHooks[h],g&&"get"in g&&(e=g.get(a,!0,c)),void 0===e&&(e=xa(a,b,d)),"normal"===e&&b in Da&&(e=Da[b]),""===c||c?(f=parseFloat(e),c===!0||n.isNumeric(f)?f||0:e):e}}),n.each(["height","width"],function(a,b){n.cssHooks[b]={get:function(a,c,d){return c?za.test(n.css(a,"display"))&&0===a.offsetWidth?n.swap(a,Ca,function(){return Ia(a,b,d)}):Ia(a,b,d):void 0},set:function(a,c,d){var e=d&&wa(a);return Ga(a,c,d?Ha(a,b,d,"border-box"===n.css(a,"boxSizing",!1,e),e):0)}}}),n.cssHooks.marginRight=ya(k.reliableMarginRight,function(a,b){return b?n.swap(a,{display:"inline-block"},xa,[a,"marginRight"]):void 0}),n.each({margin:"",padding:"",border:"Width"},function(a,b){n.cssHooks[a+b]={expand:function(c){for(var d=0,e={},f="string"==typeof c?c.split(" "):[c];4>d;d++)e[a+R[d]+b]=f[d]||f[d-2]||f[0];return e}},ua.test(a)||(n.cssHooks[a+b].set=Ga)}),n.fn.extend({css:function(a,b){return J(this,function(a,b,c){var d,e,f={},g=0;if(n.isArray(b)){for(d=wa(a),e=b.length;e>g;g++)f[b[g]]=n.css(a,b[g],!1,d);return f}return void 0!==c?n.style(a,b,c):n.css(a,b)},a,b,arguments.length>1)},show:function(){return Ja(this,!0)},hide:function(){return Ja(this)},toggle:function(a){return"boolean"==typeof a?a?this.show():this.hide():this.each(function(){S(this)?n(this).show():n(this).hide()})}});function Ka(a,b,c,d,e){return new Ka.prototype.init(a,b,c,d,e)}n.Tween=Ka,Ka.prototype={constructor:Ka,init:function(a,b,c,d,e,f){this.elem=a,this.prop=c,this.easing=e||"swing",this.options=b,this.start=this.now=this.cur(),this.end=d,this.unit=f||(n.cssNumber[c]?"":"px")},cur:function(){var a=Ka.propHooks[this.prop];return a&&a.get?a.get(this):Ka.propHooks._default.get(this)},run:function(a){var b,c=Ka.propHooks[this.prop];return this.options.duration?this.pos=b=n.easing[this.easing](a,this.options.duration*a,0,1,this.options.duration):this.pos=b=a,this.now=(this.end-this.start)*b+this.start,this.options.step&&this.options.step.call(this.elem,this.now,this),c&&c.set?c.set(this):Ka.propHooks._default.set(this),this}},Ka.prototype.init.prototype=Ka.prototype,Ka.propHooks={_default:{get:function(a){var b;return null==a.elem[a.prop]||a.elem.style&&null!=a.elem.style[a.prop]?(b=n.css(a.elem,a.prop,""),b&&"auto"!==b?b:0):a.elem[a.prop]},set:function(a){n.fx.step[a.prop]?n.fx.step[a.prop](a):a.elem.style&&(null!=a.elem.style[n.cssProps[a.prop]]||n.cssHooks[a.prop])?n.style(a.elem,a.prop,a.now+a.unit):a.elem[a.prop]=a.now}}},Ka.propHooks.scrollTop=Ka.propHooks.scrollLeft={set:function(a){a.elem.nodeType&&a.elem.parentNode&&(a.elem[a.prop]=a.now)}},n.easing={linear:function(a){return a},swing:function(a){return.5-Math.cos(a*Math.PI)/2}},n.fx=Ka.prototype.init,n.fx.step={};var La,Ma,Na=/^(?:toggle|show|hide)$/,Oa=new RegExp("^(?:([+-])=|)("+Q+")([a-z%]*)$","i"),Pa=/queueHooks$/,Qa=[Va],Ra={"*":[function(a,b){var c=this.createTween(a,b),d=c.cur(),e=Oa.exec(b),f=e&&e[3]||(n.cssNumber[a]?"":"px"),g=(n.cssNumber[a]||"px"!==f&&+d)&&Oa.exec(n.css(c.elem,a)),h=1,i=20;if(g&&g[3]!==f){f=f||g[3],e=e||[],g=+d||1;do h=h||".5",g/=h,n.style(c.elem,a,g+f);while(h!==(h=c.cur()/d)&&1!==h&&--i)}return e&&(g=c.start=+g||+d||0,c.unit=f,c.end=e[1]?g+(e[1]+1)*e[2]:+e[2]),c}]};function Sa(){return setTimeout(function(){La=void 0}),La=n.now()}function Ta(a,b){var c,d=0,e={height:a};for(b=b?1:0;4>d;d+=2-b)c=R[d],e["margin"+c]=e["padding"+c]=a;return b&&(e.opacity=e.width=a),e}function Ua(a,b,c){for(var d,e=(Ra[b]||[]).concat(Ra["*"]),f=0,g=e.length;g>f;f++)if(d=e[f].call(c,b,a))return d}function Va(a,b,c){var d,e,f,g,h,i,j,k,l=this,m={},o=a.style,p=a.nodeType&&S(a),q=L.get(a,"fxshow");c.queue||(h=n._queueHooks(a,"fx"),null==h.unqueued&&(h.unqueued=0,i=h.empty.fire,h.empty.fire=function(){h.unqueued||i()}),h.unqueued++,l.always(function(){l.always(function(){h.unqueued--,n.queue(a,"fx").length||h.empty.fire()})})),1===a.nodeType&&("height"in b||"width"in b)&&(c.overflow=[o.overflow,o.overflowX,o.overflowY],j=n.css(a,"display"),k="none"===j?L.get(a,"olddisplay")||ta(a.nodeName):j,"inline"===k&&"none"===n.css(a,"float")&&(o.display="inline-block")),c.overflow&&(o.overflow="hidden",l.always(function(){o.overflow=c.overflow[0],o.overflowX=c.overflow[1],o.overflowY=c.overflow[2]}));for(d in b)if(e=b[d],Na.exec(e)){if(delete b[d],f=f||"toggle"===e,e===(p?"hide":"show")){if("show"!==e||!q||void 0===q[d])continue;p=!0}m[d]=q&&q[d]||n.style(a,d)}else j=void 0;if(n.isEmptyObject(m))"inline"===("none"===j?ta(a.nodeName):j)&&(o.display=j);else{q?"hidden"in q&&(p=q.hidden):q=L.access(a,"fxshow",{}),f&&(q.hidden=!p),p?n(a).show():l.done(function(){n(a).hide()}),l.done(function(){var b;L.remove(a,"fxshow");for(b in m)n.style(a,b,m[b])});for(d in m)g=Ua(p?q[d]:0,d,l),d in q||(q[d]=g.start,p&&(g.end=g.start,g.start="width"===d||"height"===d?1:0))}}function Wa(a,b){var c,d,e,f,g;for(c in a)if(d=n.camelCase(c),e=b[d],f=a[c],n.isArray(f)&&(e=f[1],f=a[c]=f[0]),c!==d&&(a[d]=f,delete a[c]),g=n.cssHooks[d],g&&"expand"in g){f=g.expand(f),delete a[d];for(c in f)c in a||(a[c]=f[c],b[c]=e)}else b[d]=e}function Xa(a,b,c){var d,e,f=0,g=Qa.length,h=n.Deferred().always(function(){delete i.elem}),i=function(){if(e)return!1;for(var b=La||Sa(),c=Math.max(0,j.startTime+j.duration-b),d=c/j.duration||0,f=1-d,g=0,i=j.tweens.length;i>g;g++)j.tweens[g].run(f);return h.notifyWith(a,[j,f,c]),1>f&&i?c:(h.resolveWith(a,[j]),!1)},j=h.promise({elem:a,props:n.extend({},b),opts:n.extend(!0,{specialEasing:{}},c),originalProperties:b,originalOptions:c,startTime:La||Sa(),duration:c.duration,tweens:[],createTween:function(b,c){var d=n.Tween(a,j.opts,b,c,j.opts.specialEasing[b]||j.opts.easing);return j.tweens.push(d),d},stop:function(b){var c=0,d=b?j.tweens.length:0;if(e)return this;for(e=!0;d>c;c++)j.tweens[c].run(1);return b?h.resolveWith(a,[j,b]):h.rejectWith(a,[j,b]),this}}),k=j.props;for(Wa(k,j.opts.specialEasing);g>f;f++)if(d=Qa[f].call(j,a,k,j.opts))return d;return n.map(k,Ua,j),n.isFunction(j.opts.start)&&j.opts.start.call(a,j),n.fx.timer(n.extend(i,{elem:a,anim:j,queue:j.opts.queue})),j.progress(j.opts.progress).done(j.opts.done,j.opts.complete).fail(j.opts.fail).always(j.opts.always)}n.Animation=n.extend(Xa,{tweener:function(a,b){n.isFunction(a)?(b=a,a=["*"]):a=a.split(" ");for(var c,d=0,e=a.length;e>d;d++)c=a[d],Ra[c]=Ra[c]||[],Ra[c].unshift(b)},prefilter:function(a,b){b?Qa.unshift(a):Qa.push(a)}}),n.speed=function(a,b,c){var d=a&&"object"==typeof a?n.extend({},a):{complete:c||!c&&b||n.isFunction(a)&&a,duration:a,easing:c&&b||b&&!n.isFunction(b)&&b};return d.duration=n.fx.off?0:"number"==typeof d.duration?d.duration:d.duration in n.fx.speeds?n.fx.speeds[d.duration]:n.fx.speeds._default,(null==d.queue||d.queue===!0)&&(d.queue="fx"),d.old=d.complete,d.complete=function(){n.isFunction(d.old)&&d.old.call(this),d.queue&&n.dequeue(this,d.queue)},d},n.fn.extend({fadeTo:function(a,b,c,d){return this.filter(S).css("opacity",0).show().end().animate({opacity:b},a,c,d)},animate:function(a,b,c,d){var e=n.isEmptyObject(a),f=n.speed(b,c,d),g=function(){var b=Xa(this,n.extend({},a),f);(e||L.get(this,"finish"))&&b.stop(!0)};return g.finish=g,e||f.queue===!1?this.each(g):this.queue(f.queue,g)},stop:function(a,b,c){var d=function(a){var b=a.stop;delete a.stop,b(c)};return"string"!=typeof a&&(c=b,b=a,a=void 0),b&&a!==!1&&this.queue(a||"fx",[]),this.each(function(){var b=!0,e=null!=a&&a+"queueHooks",f=n.timers,g=L.get(this);if(e)g[e]&&g[e].stop&&d(g[e]);else for(e in g)g[e]&&g[e].stop&&Pa.test(e)&&d(g[e]);for(e=f.length;e--;)f[e].elem!==this||null!=a&&f[e].queue!==a||(f[e].anim.stop(c),b=!1,f.splice(e,1));(b||!c)&&n.dequeue(this,a)})},finish:function(a){return a!==!1&&(a=a||"fx"),this.each(function(){var b,c=L.get(this),d=c[a+"queue"],e=c[a+"queueHooks"],f=n.timers,g=d?d.length:0;for(c.finish=!0,n.queue(this,a,[]),e&&e.stop&&e.stop.call(this,!0),b=f.length;b--;)f[b].elem===this&&f[b].queue===a&&(f[b].anim.stop(!0),f.splice(b,1));for(b=0;g>b;b++)d[b]&&d[b].finish&&d[b].finish.call(this);delete c.finish})}}),n.each(["toggle","show","hide"],function(a,b){var c=n.fn[b];n.fn[b]=function(a,d,e){return null==a||"boolean"==typeof a?c.apply(this,arguments):this.animate(Ta(b,!0),a,d,e)}}),n.each({slideDown:Ta("show"),slideUp:Ta("hide"),slideToggle:Ta("toggle"),fadeIn:{opacity:"show"},fadeOut:{opacity:"hide"},fadeToggle:{opacity:"toggle"}},function(a,b){n.fn[a]=function(a,c,d){return this.animate(b,a,c,d)}}),n.timers=[],n.fx.tick=function(){var a,b=0,c=n.timers;for(La=n.now();b<c.length;b++)a=c[b],a()||c[b]!==a||c.splice(b--,1);c.length||n.fx.stop(),La=void 0},n.fx.timer=function(a){n.timers.push(a),a()?n.fx.start():n.timers.pop()},n.fx.interval=13,n.fx.start=function(){Ma||(Ma=setInterval(n.fx.tick,n.fx.interval))},n.fx.stop=function(){clearInterval(Ma),Ma=null},n.fx.speeds={slow:600,fast:200,_default:400},n.fn.delay=function(a,b){return a=n.fx?n.fx.speeds[a]||a:a,b=b||"fx",this.queue(b,function(b,c){var d=setTimeout(b,a);c.stop=function(){clearTimeout(d)}})},function(){var a=l.createElement("input"),b=l.createElement("select"),c=b.appendChild(l.createElement("option"));a.type="checkbox",k.checkOn=""!==a.value,k.optSelected=c.selected,b.disabled=!0,k.optDisabled=!c.disabled,a=l.createElement("input"),a.value="t",a.type="radio",k.radioValue="t"===a.value}();var Ya,Za,$a=n.expr.attrHandle;n.fn.extend({attr:function(a,b){return J(this,n.attr,a,b,arguments.length>1)},removeAttr:function(a){return this.each(function(){n.removeAttr(this,a)})}}),n.extend({attr:function(a,b,c){var d,e,f=a.nodeType;if(a&&3!==f&&8!==f&&2!==f)return typeof a.getAttribute===U?n.prop(a,b,c):(1===f&&n.isXMLDoc(a)||(b=b.toLowerCase(),d=n.attrHooks[b]||(n.expr.match.bool.test(b)?Za:Ya)),
void 0===c?d&&"get"in d&&null!==(e=d.get(a,b))?e:(e=n.find.attr(a,b),null==e?void 0:e):null!==c?d&&"set"in d&&void 0!==(e=d.set(a,c,b))?e:(a.setAttribute(b,c+""),c):void n.removeAttr(a,b))},removeAttr:function(a,b){var c,d,e=0,f=b&&b.match(E);if(f&&1===a.nodeType)while(c=f[e++])d=n.propFix[c]||c,n.expr.match.bool.test(c)&&(a[d]=!1),a.removeAttribute(c)},attrHooks:{type:{set:function(a,b){if(!k.radioValue&&"radio"===b&&n.nodeName(a,"input")){var c=a.value;return a.setAttribute("type",b),c&&(a.value=c),b}}}}}),Za={set:function(a,b,c){return b===!1?n.removeAttr(a,c):a.setAttribute(c,c),c}},n.each(n.expr.match.bool.source.match(/\w+/g),function(a,b){var c=$a[b]||n.find.attr;$a[b]=function(a,b,d){var e,f;return d||(f=$a[b],$a[b]=e,e=null!=c(a,b,d)?b.toLowerCase():null,$a[b]=f),e}});var _a=/^(?:input|select|textarea|button)$/i;n.fn.extend({prop:function(a,b){return J(this,n.prop,a,b,arguments.length>1)},removeProp:function(a){return this.each(function(){delete this[n.propFix[a]||a]})}}),n.extend({propFix:{"for":"htmlFor","class":"className"},prop:function(a,b,c){var d,e,f,g=a.nodeType;if(a&&3!==g&&8!==g&&2!==g)return f=1!==g||!n.isXMLDoc(a),f&&(b=n.propFix[b]||b,e=n.propHooks[b]),void 0!==c?e&&"set"in e&&void 0!==(d=e.set(a,c,b))?d:a[b]=c:e&&"get"in e&&null!==(d=e.get(a,b))?d:a[b]},propHooks:{tabIndex:{get:function(a){return a.hasAttribute("tabindex")||_a.test(a.nodeName)||a.href?a.tabIndex:-1}}}}),k.optSelected||(n.propHooks.selected={get:function(a){var b=a.parentNode;return b&&b.parentNode&&b.parentNode.selectedIndex,null}}),n.each(["tabIndex","readOnly","maxLength","cellSpacing","cellPadding","rowSpan","colSpan","useMap","frameBorder","contentEditable"],function(){n.propFix[this.toLowerCase()]=this});var ab=/[\t\r\n\f]/g;n.fn.extend({addClass:function(a){var b,c,d,e,f,g,h="string"==typeof a&&a,i=0,j=this.length;if(n.isFunction(a))return this.each(function(b){n(this).addClass(a.call(this,b,this.className))});if(h)for(b=(a||"").match(E)||[];j>i;i++)if(c=this[i],d=1===c.nodeType&&(c.className?(" "+c.className+" ").replace(ab," "):" ")){f=0;while(e=b[f++])d.indexOf(" "+e+" ")<0&&(d+=e+" ");g=n.trim(d),c.className!==g&&(c.className=g)}return this},removeClass:function(a){var b,c,d,e,f,g,h=0===arguments.length||"string"==typeof a&&a,i=0,j=this.length;if(n.isFunction(a))return this.each(function(b){n(this).removeClass(a.call(this,b,this.className))});if(h)for(b=(a||"").match(E)||[];j>i;i++)if(c=this[i],d=1===c.nodeType&&(c.className?(" "+c.className+" ").replace(ab," "):"")){f=0;while(e=b[f++])while(d.indexOf(" "+e+" ")>=0)d=d.replace(" "+e+" "," ");g=a?n.trim(d):"",c.className!==g&&(c.className=g)}return this},toggleClass:function(a,b){var c=typeof a;return"boolean"==typeof b&&"string"===c?b?this.addClass(a):this.removeClass(a):this.each(n.isFunction(a)?function(c){n(this).toggleClass(a.call(this,c,this.className,b),b)}:function(){if("string"===c){var b,d=0,e=n(this),f=a.match(E)||[];while(b=f[d++])e.hasClass(b)?e.removeClass(b):e.addClass(b)}else(c===U||"boolean"===c)&&(this.className&&L.set(this,"__className__",this.className),this.className=this.className||a===!1?"":L.get(this,"__className__")||"")})},hasClass:function(a){for(var b=" "+a+" ",c=0,d=this.length;d>c;c++)if(1===this[c].nodeType&&(" "+this[c].className+" ").replace(ab," ").indexOf(b)>=0)return!0;return!1}});var bb=/\r/g;n.fn.extend({val:function(a){var b,c,d,e=this[0];{if(arguments.length)return d=n.isFunction(a),this.each(function(c){var e;1===this.nodeType&&(e=d?a.call(this,c,n(this).val()):a,null==e?e="":"number"==typeof e?e+="":n.isArray(e)&&(e=n.map(e,function(a){return null==a?"":a+""})),b=n.valHooks[this.type]||n.valHooks[this.nodeName.toLowerCase()],b&&"set"in b&&void 0!==b.set(this,e,"value")||(this.value=e))});if(e)return b=n.valHooks[e.type]||n.valHooks[e.nodeName.toLowerCase()],b&&"get"in b&&void 0!==(c=b.get(e,"value"))?c:(c=e.value,"string"==typeof c?c.replace(bb,""):null==c?"":c)}}}),n.extend({valHooks:{option:{get:function(a){var b=n.find.attr(a,"value");return null!=b?b:n.trim(n.text(a))}},select:{get:function(a){for(var b,c,d=a.options,e=a.selectedIndex,f="select-one"===a.type||0>e,g=f?null:[],h=f?e+1:d.length,i=0>e?h:f?e:0;h>i;i++)if(c=d[i],!(!c.selected&&i!==e||(k.optDisabled?c.disabled:null!==c.getAttribute("disabled"))||c.parentNode.disabled&&n.nodeName(c.parentNode,"optgroup"))){if(b=n(c).val(),f)return b;g.push(b)}return g},set:function(a,b){var c,d,e=a.options,f=n.makeArray(b),g=e.length;while(g--)d=e[g],(d.selected=n.inArray(d.value,f)>=0)&&(c=!0);return c||(a.selectedIndex=-1),f}}}}),n.each(["radio","checkbox"],function(){n.valHooks[this]={set:function(a,b){return n.isArray(b)?a.checked=n.inArray(n(a).val(),b)>=0:void 0}},k.checkOn||(n.valHooks[this].get=function(a){return null===a.getAttribute("value")?"on":a.value})}),n.each("blur focus focusin focusout load resize scroll unload click dblclick mousedown mouseup mousemove mouseover mouseout mouseenter mouseleave change select submit keydown keypress keyup error contextmenu".split(" "),function(a,b){n.fn[b]=function(a,c){return arguments.length>0?this.on(b,null,a,c):this.trigger(b)}}),n.fn.extend({hover:function(a,b){return this.mouseenter(a).mouseleave(b||a)},bind:function(a,b,c){return this.on(a,null,b,c)},unbind:function(a,b){return this.off(a,null,b)},delegate:function(a,b,c,d){return this.on(b,a,c,d)},undelegate:function(a,b,c){return 1===arguments.length?this.off(a,"**"):this.off(b,a||"**",c)}});var cb=n.now(),db=/\?/;n.parseJSON=function(a){return JSON.parse(a+"")},n.parseXML=function(a){var b,c;if(!a||"string"!=typeof a)return null;try{c=new DOMParser,b=c.parseFromString(a,"text/xml")}catch(d){b=void 0}return(!b||b.getElementsByTagName("parsererror").length)&&n.error("Invalid XML: "+a),b};var eb=/#.*$/,fb=/([?&])_=[^&]*/,gb=/^(.*?):[ \t]*([^\r\n]*)$/gm,hb=/^(?:about|app|app-storage|.+-extension|file|res|widget):$/,ib=/^(?:GET|HEAD)$/,jb=/^\/\//,kb=/^([\w.+-]+:)(?:\/\/(?:[^\/?#]*@|)([^\/?#:]*)(?::(\d+)|)|)/,lb={},mb={},nb="*/".concat("*"),ob=a.location.href,pb=kb.exec(ob.toLowerCase())||[];function qb(a){return function(b,c){"string"!=typeof b&&(c=b,b="*");var d,e=0,f=b.toLowerCase().match(E)||[];if(n.isFunction(c))while(d=f[e++])"+"===d[0]?(d=d.slice(1)||"*",(a[d]=a[d]||[]).unshift(c)):(a[d]=a[d]||[]).push(c)}}function rb(a,b,c,d){var e={},f=a===mb;function g(h){var i;return e[h]=!0,n.each(a[h]||[],function(a,h){var j=h(b,c,d);return"string"!=typeof j||f||e[j]?f?!(i=j):void 0:(b.dataTypes.unshift(j),g(j),!1)}),i}return g(b.dataTypes[0])||!e["*"]&&g("*")}function sb(a,b){var c,d,e=n.ajaxSettings.flatOptions||{};for(c in b)void 0!==b[c]&&((e[c]?a:d||(d={}))[c]=b[c]);return d&&n.extend(!0,a,d),a}function tb(a,b,c){var d,e,f,g,h=a.contents,i=a.dataTypes;while("*"===i[0])i.shift(),void 0===d&&(d=a.mimeType||b.getResponseHeader("Content-Type"));if(d)for(e in h)if(h[e]&&h[e].test(d)){i.unshift(e);break}if(i[0]in c)f=i[0];else{for(e in c){if(!i[0]||a.converters[e+" "+i[0]]){f=e;break}g||(g=e)}f=f||g}return f?(f!==i[0]&&i.unshift(f),c[f]):void 0}function ub(a,b,c,d){var e,f,g,h,i,j={},k=a.dataTypes.slice();if(k[1])for(g in a.converters)j[g.toLowerCase()]=a.converters[g];f=k.shift();while(f)if(a.responseFields[f]&&(c[a.responseFields[f]]=b),!i&&d&&a.dataFilter&&(b=a.dataFilter(b,a.dataType)),i=f,f=k.shift())if("*"===f)f=i;else if("*"!==i&&i!==f){if(g=j[i+" "+f]||j["* "+f],!g)for(e in j)if(h=e.split(" "),h[1]===f&&(g=j[i+" "+h[0]]||j["* "+h[0]])){g===!0?g=j[e]:j[e]!==!0&&(f=h[0],k.unshift(h[1]));break}if(g!==!0)if(g&&a["throws"])b=g(b);else try{b=g(b)}catch(l){return{state:"parsererror",error:g?l:"No conversion from "+i+" to "+f}}}return{state:"success",data:b}}n.extend({active:0,lastModified:{},etag:{},ajaxSettings:{url:ob,type:"GET",isLocal:hb.test(pb[1]),global:!0,processData:!0,async:!0,contentType:"application/x-www-form-urlencoded; charset=UTF-8",accepts:{"*":nb,text:"text/plain",html:"text/html",xml:"application/xml, text/xml",json:"application/json, text/javascript"},contents:{xml:/xml/,html:/html/,json:/json/},responseFields:{xml:"responseXML",text:"responseText",json:"responseJSON"},converters:{"* text":String,"text html":!0,"text json":n.parseJSON,"text xml":n.parseXML},flatOptions:{url:!0,context:!0}},ajaxSetup:function(a,b){return b?sb(sb(a,n.ajaxSettings),b):sb(n.ajaxSettings,a)},ajaxPrefilter:qb(lb),ajaxTransport:qb(mb),ajax:function(a,b){"object"==typeof a&&(b=a,a=void 0),b=b||{};var c,d,e,f,g,h,i,j,k=n.ajaxSetup({},b),l=k.context||k,m=k.context&&(l.nodeType||l.jquery)?n(l):n.event,o=n.Deferred(),p=n.Callbacks("once memory"),q=k.statusCode||{},r={},s={},t=0,u="canceled",v={readyState:0,getResponseHeader:function(a){var b;if(2===t){if(!f){f={};while(b=gb.exec(e))f[b[1].toLowerCase()]=b[2]}b=f[a.toLowerCase()]}return null==b?null:b},getAllResponseHeaders:function(){return 2===t?e:null},setRequestHeader:function(a,b){var c=a.toLowerCase();return t||(a=s[c]=s[c]||a,r[a]=b),this},overrideMimeType:function(a){return t||(k.mimeType=a),this},statusCode:function(a){var b;if(a)if(2>t)for(b in a)q[b]=[q[b],a[b]];else v.always(a[v.status]);return this},abort:function(a){var b=a||u;return c&&c.abort(b),x(0,b),this}};if(o.promise(v).complete=p.add,v.success=v.done,v.error=v.fail,k.url=((a||k.url||ob)+"").replace(eb,"").replace(jb,pb[1]+"//"),k.type=b.method||b.type||k.method||k.type,k.dataTypes=n.trim(k.dataType||"*").toLowerCase().match(E)||[""],null==k.crossDomain&&(h=kb.exec(k.url.toLowerCase()),k.crossDomain=!(!h||h[1]===pb[1]&&h[2]===pb[2]&&(h[3]||("http:"===h[1]?"80":"443"))===(pb[3]||("http:"===pb[1]?"80":"443")))),k.data&&k.processData&&"string"!=typeof k.data&&(k.data=n.param(k.data,k.traditional)),rb(lb,k,b,v),2===t)return v;i=n.event&&k.global,i&&0===n.active++&&n.event.trigger("ajaxStart"),k.type=k.type.toUpperCase(),k.hasContent=!ib.test(k.type),d=k.url,k.hasContent||(k.data&&(d=k.url+=(db.test(d)?"&":"?")+k.data,delete k.data),k.cache===!1&&(k.url=fb.test(d)?d.replace(fb,"$1_="+cb++):d+(db.test(d)?"&":"?")+"_="+cb++)),k.ifModified&&(n.lastModified[d]&&v.setRequestHeader("If-Modified-Since",n.lastModified[d]),n.etag[d]&&v.setRequestHeader("If-None-Match",n.etag[d])),(k.data&&k.hasContent&&k.contentType!==!1||b.contentType)&&v.setRequestHeader("Content-Type",k.contentType),v.setRequestHeader("Accept",k.dataTypes[0]&&k.accepts[k.dataTypes[0]]?k.accepts[k.dataTypes[0]]+("*"!==k.dataTypes[0]?", "+nb+"; q=0.01":""):k.accepts["*"]);for(j in k.headers)v.setRequestHeader(j,k.headers[j]);if(k.beforeSend&&(k.beforeSend.call(l,v,k)===!1||2===t))return v.abort();u="abort";for(j in{success:1,error:1,complete:1})v[j](k[j]);if(c=rb(mb,k,b,v)){v.readyState=1,i&&m.trigger("ajaxSend",[v,k]),k.async&&k.timeout>0&&(g=setTimeout(function(){v.abort("timeout")},k.timeout));try{t=1,c.send(r,x)}catch(w){if(!(2>t))throw w;x(-1,w)}}else x(-1,"No Transport");function x(a,b,f,h){var j,r,s,u,w,x=b;2!==t&&(t=2,g&&clearTimeout(g),c=void 0,e=h||"",v.readyState=a>0?4:0,j=a>=200&&300>a||304===a,f&&(u=tb(k,v,f)),u=ub(k,u,v,j),j?(k.ifModified&&(w=v.getResponseHeader("Last-Modified"),w&&(n.lastModified[d]=w),w=v.getResponseHeader("etag"),w&&(n.etag[d]=w)),204===a||"HEAD"===k.type?x="nocontent":304===a?x="notmodified":(x=u.state,r=u.data,s=u.error,j=!s)):(s=x,(a||!x)&&(x="error",0>a&&(a=0))),v.status=a,v.statusText=(b||x)+"",j?o.resolveWith(l,[r,x,v]):o.rejectWith(l,[v,x,s]),v.statusCode(q),q=void 0,i&&m.trigger(j?"ajaxSuccess":"ajaxError",[v,k,j?r:s]),p.fireWith(l,[v,x]),i&&(m.trigger("ajaxComplete",[v,k]),--n.active||n.event.trigger("ajaxStop")))}return v},getJSON:function(a,b,c){return n.get(a,b,c,"json")},getScript:function(a,b){return n.get(a,void 0,b,"script")}}),n.each(["get","post"],function(a,b){n[b]=function(a,c,d,e){return n.isFunction(c)&&(e=e||d,d=c,c=void 0),n.ajax({url:a,type:b,dataType:e,data:c,success:d})}}),n._evalUrl=function(a){return n.ajax({url:a,type:"GET",dataType:"script",async:!1,global:!1,"throws":!0})},n.fn.extend({wrapAll:function(a){var b;return n.isFunction(a)?this.each(function(b){n(this).wrapAll(a.call(this,b))}):(this[0]&&(b=n(a,this[0].ownerDocument).eq(0).clone(!0),this[0].parentNode&&b.insertBefore(this[0]),b.map(function(){var a=this;while(a.firstElementChild)a=a.firstElementChild;return a}).append(this)),this)},wrapInner:function(a){return this.each(n.isFunction(a)?function(b){n(this).wrapInner(a.call(this,b))}:function(){var b=n(this),c=b.contents();c.length?c.wrapAll(a):b.append(a)})},wrap:function(a){var b=n.isFunction(a);return this.each(function(c){n(this).wrapAll(b?a.call(this,c):a)})},unwrap:function(){return this.parent().each(function(){n.nodeName(this,"body")||n(this).replaceWith(this.childNodes)}).end()}}),n.expr.filters.hidden=function(a){return a.offsetWidth<=0&&a.offsetHeight<=0},n.expr.filters.visible=function(a){return!n.expr.filters.hidden(a)};var vb=/%20/g,wb=/\[\]$/,xb=/\r?\n/g,yb=/^(?:submit|button|image|reset|file)$/i,zb=/^(?:input|select|textarea|keygen)/i;function Ab(a,b,c,d){var e;if(n.isArray(b))n.each(b,function(b,e){c||wb.test(a)?d(a,e):Ab(a+"["+("object"==typeof e?b:"")+"]",e,c,d)});else if(c||"object"!==n.type(b))d(a,b);else for(e in b)Ab(a+"["+e+"]",b[e],c,d)}n.param=function(a,b){var c,d=[],e=function(a,b){b=n.isFunction(b)?b():null==b?"":b,d[d.length]=encodeURIComponent(a)+"="+encodeURIComponent(b)};if(void 0===b&&(b=n.ajaxSettings&&n.ajaxSettings.traditional),n.isArray(a)||a.jquery&&!n.isPlainObject(a))n.each(a,function(){e(this.name,this.value)});else for(c in a)Ab(c,a[c],b,e);return d.join("&").replace(vb,"+")},n.fn.extend({serialize:function(){return n.param(this.serializeArray())},serializeArray:function(){return this.map(function(){var a=n.prop(this,"elements");return a?n.makeArray(a):this}).filter(function(){var a=this.type;return this.name&&!n(this).is(":disabled")&&zb.test(this.nodeName)&&!yb.test(a)&&(this.checked||!T.test(a))}).map(function(a,b){var c=n(this).val();return null==c?null:n.isArray(c)?n.map(c,function(a){return{name:b.name,value:a.replace(xb,"\r\n")}}):{name:b.name,value:c.replace(xb,"\r\n")}}).get()}}),n.ajaxSettings.xhr=function(){try{return new XMLHttpRequest}catch(a){}};var Bb=0,Cb={},Db={0:200,1223:204},Eb=n.ajaxSettings.xhr();a.attachEvent&&a.attachEvent("onunload",function(){for(var a in Cb)Cb[a]()}),k.cors=!!Eb&&"withCredentials"in Eb,k.ajax=Eb=!!Eb,n.ajaxTransport(function(a){var b;return k.cors||Eb&&!a.crossDomain?{send:function(c,d){var e,f=a.xhr(),g=++Bb;if(f.open(a.type,a.url,a.async,a.username,a.password),a.xhrFields)for(e in a.xhrFields)f[e]=a.xhrFields[e];a.mimeType&&f.overrideMimeType&&f.overrideMimeType(a.mimeType),a.crossDomain||c["X-Requested-With"]||(c["X-Requested-With"]="XMLHttpRequest");for(e in c)f.setRequestHeader(e,c[e]);b=function(a){return function(){b&&(delete Cb[g],b=f.onload=f.onerror=null,"abort"===a?f.abort():"error"===a?d(f.status,f.statusText):d(Db[f.status]||f.status,f.statusText,"string"==typeof f.responseText?{text:f.responseText}:void 0,f.getAllResponseHeaders()))}},f.onload=b(),f.onerror=b("error"),b=Cb[g]=b("abort");try{f.send(a.hasContent&&a.data||null)}catch(h){if(b)throw h}},abort:function(){b&&b()}}:void 0}),n.ajaxSetup({accepts:{script:"text/javascript, application/javascript, application/ecmascript, application/x-ecmascript"},contents:{script:/(?:java|ecma)script/},converters:{"text script":function(a){return n.globalEval(a),a}}}),n.ajaxPrefilter("script",function(a){void 0===a.cache&&(a.cache=!1),a.crossDomain&&(a.type="GET")}),n.ajaxTransport("script",function(a){if(a.crossDomain){var b,c;return{send:function(d,e){b=n("<script>").prop({async:!0,charset:a.scriptCharset,src:a.url}).on("load error",c=function(a){b.remove(),c=null,a&&e("error"===a.type?404:200,a.type)}),l.head.appendChild(b[0])},abort:function(){c&&c()}}}});var Fb=[],Gb=/(=)\?(?=&|$)|\?\?/;n.ajaxSetup({jsonp:"callback",jsonpCallback:function(){var a=Fb.pop()||n.expando+"_"+cb++;return this[a]=!0,a}}),n.ajaxPrefilter("json jsonp",function(b,c,d){var e,f,g,h=b.jsonp!==!1&&(Gb.test(b.url)?"url":"string"==typeof b.data&&!(b.contentType||"").indexOf("application/x-www-form-urlencoded")&&Gb.test(b.data)&&"data");return h||"jsonp"===b.dataTypes[0]?(e=b.jsonpCallback=n.isFunction(b.jsonpCallback)?b.jsonpCallback():b.jsonpCallback,h?b[h]=b[h].replace(Gb,"$1"+e):b.jsonp!==!1&&(b.url+=(db.test(b.url)?"&":"?")+b.jsonp+"="+e),b.converters["script json"]=function(){return g||n.error(e+" was not called"),g[0]},b.dataTypes[0]="json",f=a[e],a[e]=function(){g=arguments},d.always(function(){a[e]=f,b[e]&&(b.jsonpCallback=c.jsonpCallback,Fb.push(e)),g&&n.isFunction(f)&&f(g[0]),g=f=void 0}),"script"):void 0}),n.parseHTML=function(a,b,c){if(!a||"string"!=typeof a)return null;"boolean"==typeof b&&(c=b,b=!1),b=b||l;var d=v.exec(a),e=!c&&[];return d?[b.createElement(d[1])]:(d=n.buildFragment([a],b,e),e&&e.length&&n(e).remove(),n.merge([],d.childNodes))};var Hb=n.fn.load;n.fn.load=function(a,b,c){if("string"!=typeof a&&Hb)return Hb.apply(this,arguments);var d,e,f,g=this,h=a.indexOf(" ");return h>=0&&(d=n.trim(a.slice(h)),a=a.slice(0,h)),n.isFunction(b)?(c=b,b=void 0):b&&"object"==typeof b&&(e="POST"),g.length>0&&n.ajax({url:a,type:e,dataType:"html",data:b}).done(function(a){f=arguments,g.html(d?n("<div>").append(n.parseHTML(a)).find(d):a)}).complete(c&&function(a,b){g.each(c,f||[a.responseText,b,a])}),this},n.each(["ajaxStart","ajaxStop","ajaxComplete","ajaxError","ajaxSuccess","ajaxSend"],function(a,b){n.fn[b]=function(a){return this.on(b,a)}}),n.expr.filters.animated=function(a){return n.grep(n.timers,function(b){return a===b.elem}).length};var Ib=a.document.documentElement;function Jb(a){return n.isWindow(a)?a:9===a.nodeType&&a.defaultView}n.offset={setOffset:function(a,b,c){var d,e,f,g,h,i,j,k=n.css(a,"position"),l=n(a),m={};"static"===k&&(a.style.position="relative"),h=l.offset(),f=n.css(a,"top"),i=n.css(a,"left"),j=("absolute"===k||"fixed"===k)&&(f+i).indexOf("auto")>-1,j?(d=l.position(),g=d.top,e=d.left):(g=parseFloat(f)||0,e=parseFloat(i)||0),n.isFunction(b)&&(b=b.call(a,c,h)),null!=b.top&&(m.top=b.top-h.top+g),null!=b.left&&(m.left=b.left-h.left+e),"using"in b?b.using.call(a,m):l.css(m)}},n.fn.extend({offset:function(a){if(arguments.length)return void 0===a?this:this.each(function(b){n.offset.setOffset(this,a,b)});var b,c,d=this[0],e={top:0,left:0},f=d&&d.ownerDocument;if(f)return b=f.documentElement,n.contains(b,d)?(typeof d.getBoundingClientRect!==U&&(e=d.getBoundingClientRect()),c=Jb(f),{top:e.top+c.pageYOffset-b.clientTop,left:e.left+c.pageXOffset-b.clientLeft}):e},position:function(){if(this[0]){var a,b,c=this[0],d={top:0,left:0};return"fixed"===n.css(c,"position")?b=c.getBoundingClientRect():(a=this.offsetParent(),b=this.offset(),n.nodeName(a[0],"html")||(d=a.offset()),d.top+=n.css(a[0],"borderTopWidth",!0),d.left+=n.css(a[0],"borderLeftWidth",!0)),{top:b.top-d.top-n.css(c,"marginTop",!0),left:b.left-d.left-n.css(c,"marginLeft",!0)}}},offsetParent:function(){return this.map(function(){var a=this.offsetParent||Ib;while(a&&!n.nodeName(a,"html")&&"static"===n.css(a,"position"))a=a.offsetParent;return a||Ib})}}),n.each({scrollLeft:"pageXOffset",scrollTop:"pageYOffset"},function(b,c){var d="pageYOffset"===c;n.fn[b]=function(e){return J(this,function(b,e,f){var g=Jb(b);return void 0===f?g?g[c]:b[e]:void(g?g.scrollTo(d?a.pageXOffset:f,d?f:a.pageYOffset):b[e]=f)},b,e,arguments.length,null)}}),n.each(["top","left"],function(a,b){n.cssHooks[b]=ya(k.pixelPosition,function(a,c){return c?(c=xa(a,b),va.test(c)?n(a).position()[b]+"px":c):void 0})}),n.each({Height:"height",Width:"width"},function(a,b){n.each({padding:"inner"+a,content:b,"":"outer"+a},function(c,d){n.fn[d]=function(d,e){var f=arguments.length&&(c||"boolean"!=typeof d),g=c||(d===!0||e===!0?"margin":"border");return J(this,function(b,c,d){var e;return n.isWindow(b)?b.document.documentElement["client"+a]:9===b.nodeType?(e=b.documentElement,Math.max(b.body["scroll"+a],e["scroll"+a],b.body["offset"+a],e["offset"+a],e["client"+a])):void 0===d?n.css(b,c,g):n.style(b,c,d,g)},b,f?d:void 0,f,null)}})}),n.fn.size=function(){return this.length},n.fn.andSelf=n.fn.addBack,"function"==typeof define&&define.amd&&define("jquery",[],function(){return n});var Kb=a.jQuery,Lb=a.$;return n.noConflict=function(b){return a.$===n&&(a.$=Lb),b&&a.jQuery===n&&(a.jQuery=Kb),n},typeof b===U&&(a.jQuery=a.$=n),n});
+//# sourceMappingURL=jquery.min.map
\ No newline at end of file
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/src/ldt/ldt/static/ldt/js/jquery.mousewheel.js Fri Oct 02 10:24:05 2015 +0200
@@ -0,0 +1,221 @@
+/*!
+ * jQuery Mousewheel 3.1.13
+ *
+ * Copyright jQuery Foundation and other contributors
+ * Released under the MIT license
+ * http://jquery.org/license
+ */
+
+(function (factory) {
+ if ( typeof define === 'function' && define.amd ) {
+ // AMD. Register as an anonymous module.
+ define(['jquery'], factory);
+ } else if (typeof exports === 'object') {
+ // Node/CommonJS style for Browserify
+ module.exports = factory;
+ } else {
+ // Browser globals
+ factory(jQuery);
+ }
+}(function ($) {
+
+ var toFix = ['wheel', 'mousewheel', 'DOMMouseScroll', 'MozMousePixelScroll'],
+ toBind = ( 'onwheel' in document || document.documentMode >= 9 ) ?
+ ['wheel'] : ['mousewheel', 'DomMouseScroll', 'MozMousePixelScroll'],
+ slice = Array.prototype.slice,
+ nullLowestDeltaTimeout, lowestDelta;
+
+ if ( $.event.fixHooks ) {
+ for ( var i = toFix.length; i; ) {
+ $.event.fixHooks[ toFix[--i] ] = $.event.mouseHooks;
+ }
+ }
+
+ var special = $.event.special.mousewheel = {
+ version: '3.1.12',
+
+ setup: function() {
+ if ( this.addEventListener ) {
+ for ( var i = toBind.length; i; ) {
+ this.addEventListener( toBind[--i], handler, false );
+ }
+ } else {
+ this.onmousewheel = handler;
+ }
+ // Store the line height and page height for this particular element
+ $.data(this, 'mousewheel-line-height', special.getLineHeight(this));
+ $.data(this, 'mousewheel-page-height', special.getPageHeight(this));
+ },
+
+ teardown: function() {
+ if ( this.removeEventListener ) {
+ for ( var i = toBind.length; i; ) {
+ this.removeEventListener( toBind[--i], handler, false );
+ }
+ } else {
+ this.onmousewheel = null;
+ }
+ // Clean up the data we added to the element
+ $.removeData(this, 'mousewheel-line-height');
+ $.removeData(this, 'mousewheel-page-height');
+ },
+
+ getLineHeight: function(elem) {
+ var $elem = $(elem),
+ $parent = $elem['offsetParent' in $.fn ? 'offsetParent' : 'parent']();
+ if (!$parent.length) {
+ $parent = $('body');
+ }
+ return parseInt($parent.css('fontSize'), 10) || parseInt($elem.css('fontSize'), 10) || 16;
+ },
+
+ getPageHeight: function(elem) {
+ return $(elem).height();
+ },
+
+ settings: {
+ adjustOldDeltas: true, // see shouldAdjustOldDeltas() below
+ normalizeOffset: true // calls getBoundingClientRect for each event
+ }
+ };
+
+ $.fn.extend({
+ mousewheel: function(fn) {
+ return fn ? this.bind('mousewheel', fn) : this.trigger('mousewheel');
+ },
+
+ unmousewheel: function(fn) {
+ return this.unbind('mousewheel', fn);
+ }
+ });
+
+
+ function handler(event) {
+ var orgEvent = event || window.event,
+ args = slice.call(arguments, 1),
+ delta = 0,
+ deltaX = 0,
+ deltaY = 0,
+ absDelta = 0,
+ offsetX = 0,
+ offsetY = 0;
+ event = $.event.fix(orgEvent);
+ event.type = 'mousewheel';
+
+ // Old school scrollwheel delta
+ if ( 'detail' in orgEvent ) { deltaY = orgEvent.detail * -1; }
+ if ( 'wheelDelta' in orgEvent ) { deltaY = orgEvent.wheelDelta; }
+ if ( 'wheelDeltaY' in orgEvent ) { deltaY = orgEvent.wheelDeltaY; }
+ if ( 'wheelDeltaX' in orgEvent ) { deltaX = orgEvent.wheelDeltaX * -1; }
+
+ // Firefox < 17 horizontal scrolling related to DOMMouseScroll event
+ if ( 'axis' in orgEvent && orgEvent.axis === orgEvent.HORIZONTAL_AXIS ) {
+ deltaX = deltaY * -1;
+ deltaY = 0;
+ }
+
+ // Set delta to be deltaY or deltaX if deltaY is 0 for backwards compatabilitiy
+ delta = deltaY === 0 ? deltaX : deltaY;
+
+ // New school wheel delta (wheel event)
+ if ( 'deltaY' in orgEvent ) {
+ deltaY = orgEvent.deltaY * -1;
+ delta = deltaY;
+ }
+ if ( 'deltaX' in orgEvent ) {
+ deltaX = orgEvent.deltaX;
+ if ( deltaY === 0 ) { delta = deltaX * -1; }
+ }
+
+ // No change actually happened, no reason to go any further
+ if ( deltaY === 0 && deltaX === 0 ) { return; }
+
+ // Need to convert lines and pages to pixels if we aren't already in pixels
+ // There are three delta modes:
+ // * deltaMode 0 is by pixels, nothing to do
+ // * deltaMode 1 is by lines
+ // * deltaMode 2 is by pages
+ if ( orgEvent.deltaMode === 1 ) {
+ var lineHeight = $.data(this, 'mousewheel-line-height');
+ delta *= lineHeight;
+ deltaY *= lineHeight;
+ deltaX *= lineHeight;
+ } else if ( orgEvent.deltaMode === 2 ) {
+ var pageHeight = $.data(this, 'mousewheel-page-height');
+ delta *= pageHeight;
+ deltaY *= pageHeight;
+ deltaX *= pageHeight;
+ }
+
+ // Store lowest absolute delta to normalize the delta values
+ absDelta = Math.max( Math.abs(deltaY), Math.abs(deltaX) );
+
+ if ( !lowestDelta || absDelta < lowestDelta ) {
+ lowestDelta = absDelta;
+
+ // Adjust older deltas if necessary
+ if ( shouldAdjustOldDeltas(orgEvent, absDelta) ) {
+ lowestDelta /= 40;
+ }
+ }
+
+ // Adjust older deltas if necessary
+ if ( shouldAdjustOldDeltas(orgEvent, absDelta) ) {
+ // Divide all the things by 40!
+ delta /= 40;
+ deltaX /= 40;
+ deltaY /= 40;
+ }
+
+ // Get a whole, normalized value for the deltas
+ delta = Math[ delta >= 1 ? 'floor' : 'ceil' ](delta / lowestDelta);
+ deltaX = Math[ deltaX >= 1 ? 'floor' : 'ceil' ](deltaX / lowestDelta);
+ deltaY = Math[ deltaY >= 1 ? 'floor' : 'ceil' ](deltaY / lowestDelta);
+
+ // Normalise offsetX and offsetY properties
+ if ( special.settings.normalizeOffset && this.getBoundingClientRect ) {
+ var boundingRect = this.getBoundingClientRect();
+ offsetX = event.clientX - boundingRect.left;
+ offsetY = event.clientY - boundingRect.top;
+ }
+
+ // Add information to the event object
+ event.deltaX = deltaX;
+ event.deltaY = deltaY;
+ event.deltaFactor = lowestDelta;
+ event.offsetX = offsetX;
+ event.offsetY = offsetY;
+ // Go ahead and set deltaMode to 0 since we converted to pixels
+ // Although this is a little odd since we overwrite the deltaX/Y
+ // properties with normalized deltas.
+ event.deltaMode = 0;
+
+ // Add event and delta to the front of the arguments
+ args.unshift(event, delta, deltaX, deltaY);
+
+ // Clearout lowestDelta after sometime to better
+ // handle multiple device types that give different
+ // a different lowestDelta
+ // Ex: trackpad = 3 and mouse wheel = 120
+ if (nullLowestDeltaTimeout) { clearTimeout(nullLowestDeltaTimeout); }
+ nullLowestDeltaTimeout = setTimeout(nullLowestDelta, 200);
+
+ return ($.event.dispatch || $.event.handle).apply(this, args);
+ }
+
+ function nullLowestDelta() {
+ lowestDelta = null;
+ }
+
+ function shouldAdjustOldDeltas(orgEvent, absDelta) {
+ // If this is an older event and the delta is divisable by 120,
+ // then we are assuming that the browser is treating this as an
+ // older mouse wheel event and that we should divide the deltas
+ // by 40 to try and get a more usable deltaFactor.
+ // Side note, this actually impacts the reported scroll distance
+ // in older browsers and can cause scrolling to be slower than native.
+ // Turn this off by setting $.event.special.mousewheel.settings.adjustOldDeltas to false.
+ return special.settings.adjustOldDeltas && orgEvent.type === 'mousewheel' && absDelta % 120 === 0;
+ }
+
+}));
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/src/ldt/ldt/static/ldt/js/jquery.mousewheel.min.js Fri Oct 02 10:24:05 2015 +0200
@@ -0,0 +1,8 @@
+/*!
+ * jQuery Mousewheel 3.1.13
+ *
+ * Copyright 2015 jQuery Foundation and other contributors
+ * Released under the MIT license.
+ * http://jquery.org/license
+ */
+!function(a){"function"==typeof define&&define.amd?define(["jquery"],a):"object"==typeof exports?module.exports=a:a(jQuery)}(function(a){function b(b){var g=b||window.event,h=i.call(arguments,1),j=0,l=0,m=0,n=0,o=0,p=0;if(b=a.event.fix(g),b.type="mousewheel","detail"in g&&(m=-1*g.detail),"wheelDelta"in g&&(m=g.wheelDelta),"wheelDeltaY"in g&&(m=g.wheelDeltaY),"wheelDeltaX"in g&&(l=-1*g.wheelDeltaX),"axis"in g&&g.axis===g.HORIZONTAL_AXIS&&(l=-1*m,m=0),j=0===m?l:m,"deltaY"in g&&(m=-1*g.deltaY,j=m),"deltaX"in g&&(l=g.deltaX,0===m&&(j=-1*l)),0!==m||0!==l){if(1===g.deltaMode){var q=a.data(this,"mousewheel-line-height");j*=q,m*=q,l*=q}else if(2===g.deltaMode){var r=a.data(this,"mousewheel-page-height");j*=r,m*=r,l*=r}if(n=Math.max(Math.abs(m),Math.abs(l)),(!f||f>n)&&(f=n,d(g,n)&&(f/=40)),d(g,n)&&(j/=40,l/=40,m/=40),j=Math[j>=1?"floor":"ceil"](j/f),l=Math[l>=1?"floor":"ceil"](l/f),m=Math[m>=1?"floor":"ceil"](m/f),k.settings.normalizeOffset&&this.getBoundingClientRect){var s=this.getBoundingClientRect();o=b.clientX-s.left,p=b.clientY-s.top}return b.deltaX=l,b.deltaY=m,b.deltaFactor=f,b.offsetX=o,b.offsetY=p,b.deltaMode=0,h.unshift(b,j,l,m),e&&clearTimeout(e),e=setTimeout(c,200),(a.event.dispatch||a.event.handle).apply(this,h)}}function c(){f=null}function d(a,b){return k.settings.adjustOldDeltas&&"mousewheel"===a.type&&b%120===0}var e,f,g=["wheel","mousewheel","DOMMouseScroll","MozMousePixelScroll"],h="onwheel"in document||document.documentMode>=9?["wheel"]:["mousewheel","DomMouseScroll","MozMousePixelScroll"],i=Array.prototype.slice;if(a.event.fixHooks)for(var j=g.length;j;)a.event.fixHooks[g[--j]]=a.event.mouseHooks;var k=a.event.special.mousewheel={version:"3.1.12",setup:function(){if(this.addEventListener)for(var c=h.length;c;)this.addEventListener(h[--c],b,!1);else this.onmousewheel=b;a.data(this,"mousewheel-line-height",k.getLineHeight(this)),a.data(this,"mousewheel-page-height",k.getPageHeight(this))},teardown:function(){if(this.removeEventListener)for(var c=h.length;c;)this.removeEventListener(h[--c],b,!1);else this.onmousewheel=null;a.removeData(this,"mousewheel-line-height"),a.removeData(this,"mousewheel-page-height")},getLineHeight:function(b){var c=a(b),d=c["offsetParent"in a.fn?"offsetParent":"parent"]();return d.length||(d=a("body")),parseInt(d.css("fontSize"),10)||parseInt(c.css("fontSize"),10)||16},getPageHeight:function(b){return a(b).height()},settings:{adjustOldDeltas:!0,normalizeOffset:!0}};a.fn.extend({mousewheel:function(a){return a?this.bind("mousewheel",a):this.trigger("mousewheel")},unmousewheel:function(a){return this.unbind("mousewheel",a)}})});
\ No newline at end of file
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/src/ldt/ldt/static/ldt/js/jquery.splitter.js Fri Oct 02 10:24:05 2015 +0200
@@ -0,0 +1,167 @@
+/*!
+ * jQuery JavaScript Library v1.4.4
+ * http://jquery.com/
+ *
+ * Copyright 2010, John Resig
+ * Dual licensed under the MIT or GPL Version 2 licenses.
+ * http://jquery.org/license
+ *
+ * Includes Sizzle.js
+ * http://sizzlejs.com/
+ * Copyright 2010, The Dojo Foundation
+ * Released under the MIT, BSD, and GPL Licenses.
+ *
+ * Date: Thu Nov 11 19:04:53 2010 -0500
+ */
+(function(E,B){function ka(a,b,d){if(d===B&&a.nodeType===1){d=a.getAttribute("data-"+b);if(typeof d==="string"){try{d=d==="true"?true:d==="false"?false:d==="null"?null:!c.isNaN(d)?parseFloat(d):Ja.test(d)?c.parseJSON(d):d}catch(e){}c.data(a,b,d)}else d=B}return d}function U(){return false}function ca(){return true}function la(a,b,d){d[0].type=a;return c.event.handle.apply(b,d)}function Ka(a){var b,d,e,f,h,l,k,o,x,r,A,C=[];f=[];h=c.data(this,this.nodeType?"events":"__events__");if(typeof h==="function")h=
+h.events;if(!(a.liveFired===this||!h||!h.live||a.button&&a.type==="click")){if(a.namespace)A=RegExp("(^|\\.)"+a.namespace.split(".").join("\\.(?:.*\\.)?")+"(\\.|$)");a.liveFired=this;var J=h.live.slice(0);for(k=0;k<J.length;k++){h=J[k];h.origType.replace(X,"")===a.type?f.push(h.selector):J.splice(k--,1)}f=c(a.target).closest(f,a.currentTarget);o=0;for(x=f.length;o<x;o++){r=f[o];for(k=0;k<J.length;k++){h=J[k];if(r.selector===h.selector&&(!A||A.test(h.namespace))){l=r.elem;e=null;if(h.preType==="mouseenter"||
+h.preType==="mouseleave"){a.type=h.preType;e=c(a.relatedTarget).closest(h.selector)[0]}if(!e||e!==l)C.push({elem:l,handleObj:h,level:r.level})}}}o=0;for(x=C.length;o<x;o++){f=C[o];if(d&&f.level>d)break;a.currentTarget=f.elem;a.data=f.handleObj.data;a.handleObj=f.handleObj;A=f.handleObj.origHandler.apply(f.elem,arguments);if(A===false||a.isPropagationStopped()){d=f.level;if(A===false)b=false;if(a.isImmediatePropagationStopped())break}}return b}}function Y(a,b){return(a&&a!=="*"?a+".":"")+b.replace(La,
+"`").replace(Ma,"&")}function ma(a,b,d){if(c.isFunction(b))return c.grep(a,function(f,h){return!!b.call(f,h,f)===d});else if(b.nodeType)return c.grep(a,function(f){return f===b===d});else if(typeof b==="string"){var e=c.grep(a,function(f){return f.nodeType===1});if(Na.test(b))return c.filter(b,e,!d);else b=c.filter(b,e)}return c.grep(a,function(f){return c.inArray(f,b)>=0===d})}function na(a,b){var d=0;b.each(function(){if(this.nodeName===(a[d]&&a[d].nodeName)){var e=c.data(a[d++]),f=c.data(this,
+e);if(e=e&&e.events){delete f.handle;f.events={};for(var h in e)for(var l in e[h])c.event.add(this,h,e[h][l],e[h][l].data)}}})}function Oa(a,b){b.src?c.ajax({url:b.src,async:false,dataType:"script"}):c.globalEval(b.text||b.textContent||b.innerHTML||"");b.parentNode&&b.parentNode.removeChild(b)}function oa(a,b,d){var e=b==="width"?a.offsetWidth:a.offsetHeight;if(d==="border")return e;c.each(b==="width"?Pa:Qa,function(){d||(e-=parseFloat(c.css(a,"padding"+this))||0);if(d==="margin")e+=parseFloat(c.css(a,
+"margin"+this))||0;else e-=parseFloat(c.css(a,"border"+this+"Width"))||0});return e}function da(a,b,d,e){if(c.isArray(b)&&b.length)c.each(b,function(f,h){d||Ra.test(a)?e(a,h):da(a+"["+(typeof h==="object"||c.isArray(h)?f:"")+"]",h,d,e)});else if(!d&&b!=null&&typeof b==="object")c.isEmptyObject(b)?e(a,""):c.each(b,function(f,h){da(a+"["+f+"]",h,d,e)});else e(a,b)}function S(a,b){var d={};c.each(pa.concat.apply([],pa.slice(0,b)),function(){d[this]=a});return d}function qa(a){if(!ea[a]){var b=c("<"+
+a+">").appendTo("body"),d=b.css("display");b.remove();if(d==="none"||d==="")d="block";ea[a]=d}return ea[a]}function fa(a){return c.isWindow(a)?a:a.nodeType===9?a.defaultView||a.parentWindow:false}var t=E.document,c=function(){function a(){if(!b.isReady){try{t.documentElement.doScroll("left")}catch(j){setTimeout(a,1);return}b.ready()}}var b=function(j,s){return new b.fn.init(j,s)},d=E.jQuery,e=E.$,f,h=/^(?:[^<]*(<[\w\W]+>)[^>]*$|#([\w\-]+)$)/,l=/\S/,k=/^\s+/,o=/\s+$/,x=/\W/,r=/\d/,A=/^<(\w+)\s*\/?>(?:<\/\1>)?$/,
+C=/^[\],:{}\s]*$/,J=/\\(?:["\\\/bfnrt]|u[0-9a-fA-F]{4})/g,w=/"[^"\\\n\r]*"|true|false|null|-?\d+(?:\.\d*)?(?:[eE][+\-]?\d+)?/g,I=/(?:^|:|,)(?:\s*\[)+/g,L=/(webkit)[ \/]([\w.]+)/,g=/(opera)(?:.*version)?[ \/]([\w.]+)/,i=/(msie) ([\w.]+)/,n=/(mozilla)(?:.*? rv:([\w.]+))?/,m=navigator.userAgent,p=false,q=[],u,y=Object.prototype.toString,F=Object.prototype.hasOwnProperty,M=Array.prototype.push,N=Array.prototype.slice,O=String.prototype.trim,D=Array.prototype.indexOf,R={};b.fn=b.prototype={init:function(j,
+s){var v,z,H;if(!j)return this;if(j.nodeType){this.context=this[0]=j;this.length=1;return this}if(j==="body"&&!s&&t.body){this.context=t;this[0]=t.body;this.selector="body";this.length=1;return this}if(typeof j==="string")if((v=h.exec(j))&&(v[1]||!s))if(v[1]){H=s?s.ownerDocument||s:t;if(z=A.exec(j))if(b.isPlainObject(s)){j=[t.createElement(z[1])];b.fn.attr.call(j,s,true)}else j=[H.createElement(z[1])];else{z=b.buildFragment([v[1]],[H]);j=(z.cacheable?z.fragment.cloneNode(true):z.fragment).childNodes}return b.merge(this,
+j)}else{if((z=t.getElementById(v[2]))&&z.parentNode){if(z.id!==v[2])return f.find(j);this.length=1;this[0]=z}this.context=t;this.selector=j;return this}else if(!s&&!x.test(j)){this.selector=j;this.context=t;j=t.getElementsByTagName(j);return b.merge(this,j)}else return!s||s.jquery?(s||f).find(j):b(s).find(j);else if(b.isFunction(j))return f.ready(j);if(j.selector!==B){this.selector=j.selector;this.context=j.context}return b.makeArray(j,this)},selector:"",jquery:"1.4.4",length:0,size:function(){return this.length},
+toArray:function(){return N.call(this,0)},get:function(j){return j==null?this.toArray():j<0?this.slice(j)[0]:this[j]},pushStack:function(j,s,v){var z=b();b.isArray(j)?M.apply(z,j):b.merge(z,j);z.prevObject=this;z.context=this.context;if(s==="find")z.selector=this.selector+(this.selector?" ":"")+v;else if(s)z.selector=this.selector+"."+s+"("+v+")";return z},each:function(j,s){return b.each(this,j,s)},ready:function(j){b.bindReady();if(b.isReady)j.call(t,b);else q&&q.push(j);return this},eq:function(j){return j===
+-1?this.slice(j):this.slice(j,+j+1)},first:function(){return this.eq(0)},last:function(){return this.eq(-1)},slice:function(){return this.pushStack(N.apply(this,arguments),"slice",N.call(arguments).join(","))},map:function(j){return this.pushStack(b.map(this,function(s,v){return j.call(s,v,s)}))},end:function(){return this.prevObject||b(null)},push:M,sort:[].sort,splice:[].splice};b.fn.init.prototype=b.fn;b.extend=b.fn.extend=function(){var j,s,v,z,H,G=arguments[0]||{},K=1,Q=arguments.length,ga=false;
+if(typeof G==="boolean"){ga=G;G=arguments[1]||{};K=2}if(typeof G!=="object"&&!b.isFunction(G))G={};if(Q===K){G=this;--K}for(;K<Q;K++)if((j=arguments[K])!=null)for(s in j){v=G[s];z=j[s];if(G!==z)if(ga&&z&&(b.isPlainObject(z)||(H=b.isArray(z)))){if(H){H=false;v=v&&b.isArray(v)?v:[]}else v=v&&b.isPlainObject(v)?v:{};G[s]=b.extend(ga,v,z)}else if(z!==B)G[s]=z}return G};b.extend({noConflict:function(j){E.$=e;if(j)E.jQuery=d;return b},isReady:false,readyWait:1,ready:function(j){j===true&&b.readyWait--;
+if(!b.readyWait||j!==true&&!b.isReady){if(!t.body)return setTimeout(b.ready,1);b.isReady=true;if(!(j!==true&&--b.readyWait>0))if(q){var s=0,v=q;for(q=null;j=v[s++];)j.call(t,b);b.fn.trigger&&b(t).trigger("ready").unbind("ready")}}},bindReady:function(){if(!p){p=true;if(t.readyState==="complete")return setTimeout(b.ready,1);if(t.addEventListener){t.addEventListener("DOMContentLoaded",u,false);E.addEventListener("load",b.ready,false)}else if(t.attachEvent){t.attachEvent("onreadystatechange",u);E.attachEvent("onload",
+b.ready);var j=false;try{j=E.frameElement==null}catch(s){}t.documentElement.doScroll&&j&&a()}}},isFunction:function(j){return b.type(j)==="function"},isArray:Array.isArray||function(j){return b.type(j)==="array"},isWindow:function(j){return j&&typeof j==="object"&&"setInterval"in j},isNaN:function(j){return j==null||!r.test(j)||isNaN(j)},type:function(j){return j==null?String(j):R[y.call(j)]||"object"},isPlainObject:function(j){if(!j||b.type(j)!=="object"||j.nodeType||b.isWindow(j))return false;if(j.constructor&&
+!F.call(j,"constructor")&&!F.call(j.constructor.prototype,"isPrototypeOf"))return false;for(var s in j);return s===B||F.call(j,s)},isEmptyObject:function(j){for(var s in j)return false;return true},error:function(j){throw j;},parseJSON:function(j){if(typeof j!=="string"||!j)return null;j=b.trim(j);if(C.test(j.replace(J,"@").replace(w,"]").replace(I,"")))return E.JSON&&E.JSON.parse?E.JSON.parse(j):(new Function("return "+j))();else b.error("Invalid JSON: "+j)},noop:function(){},globalEval:function(j){if(j&&
+l.test(j)){var s=t.getElementsByTagName("head")[0]||t.documentElement,v=t.createElement("script");v.type="text/javascript";if(b.support.scriptEval)v.appendChild(t.createTextNode(j));else v.text=j;s.insertBefore(v,s.firstChild);s.removeChild(v)}},nodeName:function(j,s){return j.nodeName&&j.nodeName.toUpperCase()===s.toUpperCase()},each:function(j,s,v){var z,H=0,G=j.length,K=G===B||b.isFunction(j);if(v)if(K)for(z in j){if(s.apply(j[z],v)===false)break}else for(;H<G;){if(s.apply(j[H++],v)===false)break}else if(K)for(z in j){if(s.call(j[z],
+z,j[z])===false)break}else for(v=j[0];H<G&&s.call(v,H,v)!==false;v=j[++H]);return j},trim:O?function(j){return j==null?"":O.call(j)}:function(j){return j==null?"":j.toString().replace(k,"").replace(o,"")},makeArray:function(j,s){var v=s||[];if(j!=null){var z=b.type(j);j.length==null||z==="string"||z==="function"||z==="regexp"||b.isWindow(j)?M.call(v,j):b.merge(v,j)}return v},inArray:function(j,s){if(s.indexOf)return s.indexOf(j);for(var v=0,z=s.length;v<z;v++)if(s[v]===j)return v;return-1},merge:function(j,
+s){var v=j.length,z=0;if(typeof s.length==="number")for(var H=s.length;z<H;z++)j[v++]=s[z];else for(;s[z]!==B;)j[v++]=s[z++];j.length=v;return j},grep:function(j,s,v){var z=[],H;v=!!v;for(var G=0,K=j.length;G<K;G++){H=!!s(j[G],G);v!==H&&z.push(j[G])}return z},map:function(j,s,v){for(var z=[],H,G=0,K=j.length;G<K;G++){H=s(j[G],G,v);if(H!=null)z[z.length]=H}return z.concat.apply([],z)},guid:1,proxy:function(j,s,v){if(arguments.length===2)if(typeof s==="string"){v=j;j=v[s];s=B}else if(s&&!b.isFunction(s)){v=
+s;s=B}if(!s&&j)s=function(){return j.apply(v||this,arguments)};if(j)s.guid=j.guid=j.guid||s.guid||b.guid++;return s},access:function(j,s,v,z,H,G){var K=j.length;if(typeof s==="object"){for(var Q in s)b.access(j,Q,s[Q],z,H,v);return j}if(v!==B){z=!G&&z&&b.isFunction(v);for(Q=0;Q<K;Q++)H(j[Q],s,z?v.call(j[Q],Q,H(j[Q],s)):v,G);return j}return K?H(j[0],s):B},now:function(){return(new Date).getTime()},uaMatch:function(j){j=j.toLowerCase();j=L.exec(j)||g.exec(j)||i.exec(j)||j.indexOf("compatible")<0&&n.exec(j)||
+[];return{browser:j[1]||"",version:j[2]||"0"}},browser:{}});b.each("Boolean Number String Function Array Date RegExp Object".split(" "),function(j,s){R["[object "+s+"]"]=s.toLowerCase()});m=b.uaMatch(m);if(m.browser){b.browser[m.browser]=true;b.browser.version=m.version}if(b.browser.webkit)b.browser.safari=true;if(D)b.inArray=function(j,s){return D.call(s,j)};if(!/\s/.test("\u00a0")){k=/^[\s\xA0]+/;o=/[\s\xA0]+$/}f=b(t);if(t.addEventListener)u=function(){t.removeEventListener("DOMContentLoaded",u,
+false);b.ready()};else if(t.attachEvent)u=function(){if(t.readyState==="complete"){t.detachEvent("onreadystatechange",u);b.ready()}};return E.jQuery=E.$=b}();(function(){c.support={};var a=t.documentElement,b=t.createElement("script"),d=t.createElement("div"),e="script"+c.now();d.style.display="none";d.innerHTML=" <link/><table></table><a href='/a' style='color:red;float:left;opacity:.55;'>a</a><input type='checkbox'/>";var f=d.getElementsByTagName("*"),h=d.getElementsByTagName("a")[0],l=t.createElement("select"),
+k=l.appendChild(t.createElement("option"));if(!(!f||!f.length||!h)){c.support={leadingWhitespace:d.firstChild.nodeType===3,tbody:!d.getElementsByTagName("tbody").length,htmlSerialize:!!d.getElementsByTagName("link").length,style:/red/.test(h.getAttribute("style")),hrefNormalized:h.getAttribute("href")==="/a",opacity:/^0.55$/.test(h.style.opacity),cssFloat:!!h.style.cssFloat,checkOn:d.getElementsByTagName("input")[0].value==="on",optSelected:k.selected,deleteExpando:true,optDisabled:false,checkClone:false,
+scriptEval:false,noCloneEvent:true,boxModel:null,inlineBlockNeedsLayout:false,shrinkWrapBlocks:false,reliableHiddenOffsets:true};l.disabled=true;c.support.optDisabled=!k.disabled;b.type="text/javascript";try{b.appendChild(t.createTextNode("window."+e+"=1;"))}catch(o){}a.insertBefore(b,a.firstChild);if(E[e]){c.support.scriptEval=true;delete E[e]}try{delete b.test}catch(x){c.support.deleteExpando=false}a.removeChild(b);if(d.attachEvent&&d.fireEvent){d.attachEvent("onclick",function r(){c.support.noCloneEvent=
+false;d.detachEvent("onclick",r)});d.cloneNode(true).fireEvent("onclick")}d=t.createElement("div");d.innerHTML="<input type='radio' name='radiotest' checked='checked'/>";a=t.createDocumentFragment();a.appendChild(d.firstChild);c.support.checkClone=a.cloneNode(true).cloneNode(true).lastChild.checked;c(function(){var r=t.createElement("div");r.style.width=r.style.paddingLeft="1px";t.body.appendChild(r);c.boxModel=c.support.boxModel=r.offsetWidth===2;if("zoom"in r.style){r.style.display="inline";r.style.zoom=
+1;c.support.inlineBlockNeedsLayout=r.offsetWidth===2;r.style.display="";r.innerHTML="<div style='width:4px;'></div>";c.support.shrinkWrapBlocks=r.offsetWidth!==2}r.innerHTML="<table><tr><td style='padding:0;display:none'></td><td>t</td></tr></table>";var A=r.getElementsByTagName("td");c.support.reliableHiddenOffsets=A[0].offsetHeight===0;A[0].style.display="";A[1].style.display="none";c.support.reliableHiddenOffsets=c.support.reliableHiddenOffsets&&A[0].offsetHeight===0;r.innerHTML="";t.body.removeChild(r).style.display=
+"none"});a=function(r){var A=t.createElement("div");r="on"+r;var C=r in A;if(!C){A.setAttribute(r,"return;");C=typeof A[r]==="function"}return C};c.support.submitBubbles=a("submit");c.support.changeBubbles=a("change");a=b=d=f=h=null}})();var ra={},Ja=/^(?:\{.*\}|\[.*\])$/;c.extend({cache:{},uuid:0,expando:"jQuery"+c.now(),noData:{embed:true,object:"clsid:D27CDB6E-AE6D-11cf-96B8-444553540000",applet:true},data:function(a,b,d){if(c.acceptData(a)){a=a==E?ra:a;var e=a.nodeType,f=e?a[c.expando]:null,h=
+c.cache;if(!(e&&!f&&typeof b==="string"&&d===B)){if(e)f||(a[c.expando]=f=++c.uuid);else h=a;if(typeof b==="object")if(e)h[f]=c.extend(h[f],b);else c.extend(h,b);else if(e&&!h[f])h[f]={};a=e?h[f]:h;if(d!==B)a[b]=d;return typeof b==="string"?a[b]:a}}},removeData:function(a,b){if(c.acceptData(a)){a=a==E?ra:a;var d=a.nodeType,e=d?a[c.expando]:a,f=c.cache,h=d?f[e]:e;if(b){if(h){delete h[b];d&&c.isEmptyObject(h)&&c.removeData(a)}}else if(d&&c.support.deleteExpando)delete a[c.expando];else if(a.removeAttribute)a.removeAttribute(c.expando);
+else if(d)delete f[e];else for(var l in a)delete a[l]}},acceptData:function(a){if(a.nodeName){var b=c.noData[a.nodeName.toLowerCase()];if(b)return!(b===true||a.getAttribute("classid")!==b)}return true}});c.fn.extend({data:function(a,b){var d=null;if(typeof a==="undefined"){if(this.length){var e=this[0].attributes,f;d=c.data(this[0]);for(var h=0,l=e.length;h<l;h++){f=e[h].name;if(f.indexOf("data-")===0){f=f.substr(5);ka(this[0],f,d[f])}}}return d}else if(typeof a==="object")return this.each(function(){c.data(this,
+a)});var k=a.split(".");k[1]=k[1]?"."+k[1]:"";if(b===B){d=this.triggerHandler("getData"+k[1]+"!",[k[0]]);if(d===B&&this.length){d=c.data(this[0],a);d=ka(this[0],a,d)}return d===B&&k[1]?this.data(k[0]):d}else return this.each(function(){var o=c(this),x=[k[0],b];o.triggerHandler("setData"+k[1]+"!",x);c.data(this,a,b);o.triggerHandler("changeData"+k[1]+"!",x)})},removeData:function(a){return this.each(function(){c.removeData(this,a)})}});c.extend({queue:function(a,b,d){if(a){b=(b||"fx")+"queue";var e=
+c.data(a,b);if(!d)return e||[];if(!e||c.isArray(d))e=c.data(a,b,c.makeArray(d));else e.push(d);return e}},dequeue:function(a,b){b=b||"fx";var d=c.queue(a,b),e=d.shift();if(e==="inprogress")e=d.shift();if(e){b==="fx"&&d.unshift("inprogress");e.call(a,function(){c.dequeue(a,b)})}}});c.fn.extend({queue:function(a,b){if(typeof a!=="string"){b=a;a="fx"}if(b===B)return c.queue(this[0],a);return this.each(function(){var d=c.queue(this,a,b);a==="fx"&&d[0]!=="inprogress"&&c.dequeue(this,a)})},dequeue:function(a){return this.each(function(){c.dequeue(this,
+a)})},delay:function(a,b){a=c.fx?c.fx.speeds[a]||a:a;b=b||"fx";return this.queue(b,function(){var d=this;setTimeout(function(){c.dequeue(d,b)},a)})},clearQueue:function(a){return this.queue(a||"fx",[])}});var sa=/[\n\t]/g,ha=/\s+/,Sa=/\r/g,Ta=/^(?:href|src|style)$/,Ua=/^(?:button|input)$/i,Va=/^(?:button|input|object|select|textarea)$/i,Wa=/^a(?:rea)?$/i,ta=/^(?:radio|checkbox)$/i;c.props={"for":"htmlFor","class":"className",readonly:"readOnly",maxlength:"maxLength",cellspacing:"cellSpacing",rowspan:"rowSpan",
+colspan:"colSpan",tabindex:"tabIndex",usemap:"useMap",frameborder:"frameBorder"};c.fn.extend({attr:function(a,b){return c.access(this,a,b,true,c.attr)},removeAttr:function(a){return this.each(function(){c.attr(this,a,"");this.nodeType===1&&this.removeAttribute(a)})},addClass:function(a){if(c.isFunction(a))return this.each(function(x){var r=c(this);r.addClass(a.call(this,x,r.attr("class")))});if(a&&typeof a==="string")for(var b=(a||"").split(ha),d=0,e=this.length;d<e;d++){var f=this[d];if(f.nodeType===
+1)if(f.className){for(var h=" "+f.className+" ",l=f.className,k=0,o=b.length;k<o;k++)if(h.indexOf(" "+b[k]+" ")<0)l+=" "+b[k];f.className=c.trim(l)}else f.className=a}return this},removeClass:function(a){if(c.isFunction(a))return this.each(function(o){var x=c(this);x.removeClass(a.call(this,o,x.attr("class")))});if(a&&typeof a==="string"||a===B)for(var b=(a||"").split(ha),d=0,e=this.length;d<e;d++){var f=this[d];if(f.nodeType===1&&f.className)if(a){for(var h=(" "+f.className+" ").replace(sa," "),
+l=0,k=b.length;l<k;l++)h=h.replace(" "+b[l]+" "," ");f.className=c.trim(h)}else f.className=""}return this},toggleClass:function(a,b){var d=typeof a,e=typeof b==="boolean";if(c.isFunction(a))return this.each(function(f){var h=c(this);h.toggleClass(a.call(this,f,h.attr("class"),b),b)});return this.each(function(){if(d==="string")for(var f,h=0,l=c(this),k=b,o=a.split(ha);f=o[h++];){k=e?k:!l.hasClass(f);l[k?"addClass":"removeClass"](f)}else if(d==="undefined"||d==="boolean"){this.className&&c.data(this,
+"__className__",this.className);this.className=this.className||a===false?"":c.data(this,"__className__")||""}})},hasClass:function(a){a=" "+a+" ";for(var b=0,d=this.length;b<d;b++)if((" "+this[b].className+" ").replace(sa," ").indexOf(a)>-1)return true;return false},val:function(a){if(!arguments.length){var b=this[0];if(b){if(c.nodeName(b,"option")){var d=b.attributes.value;return!d||d.specified?b.value:b.text}if(c.nodeName(b,"select")){var e=b.selectedIndex;d=[];var f=b.options;b=b.type==="select-one";
+if(e<0)return null;var h=b?e:0;for(e=b?e+1:f.length;h<e;h++){var l=f[h];if(l.selected&&(c.support.optDisabled?!l.disabled:l.getAttribute("disabled")===null)&&(!l.parentNode.disabled||!c.nodeName(l.parentNode,"optgroup"))){a=c(l).val();if(b)return a;d.push(a)}}return d}if(ta.test(b.type)&&!c.support.checkOn)return b.getAttribute("value")===null?"on":b.value;return(b.value||"").replace(Sa,"")}return B}var k=c.isFunction(a);return this.each(function(o){var x=c(this),r=a;if(this.nodeType===1){if(k)r=
+a.call(this,o,x.val());if(r==null)r="";else if(typeof r==="number")r+="";else if(c.isArray(r))r=c.map(r,function(C){return C==null?"":C+""});if(c.isArray(r)&&ta.test(this.type))this.checked=c.inArray(x.val(),r)>=0;else if(c.nodeName(this,"select")){var A=c.makeArray(r);c("option",this).each(function(){this.selected=c.inArray(c(this).val(),A)>=0});if(!A.length)this.selectedIndex=-1}else this.value=r}})}});c.extend({attrFn:{val:true,css:true,html:true,text:true,data:true,width:true,height:true,offset:true},
+attr:function(a,b,d,e){if(!a||a.nodeType===3||a.nodeType===8)return B;if(e&&b in c.attrFn)return c(a)[b](d);e=a.nodeType!==1||!c.isXMLDoc(a);var f=d!==B;b=e&&c.props[b]||b;var h=Ta.test(b);if((b in a||a[b]!==B)&&e&&!h){if(f){b==="type"&&Ua.test(a.nodeName)&&a.parentNode&&c.error("type property can't be changed");if(d===null)a.nodeType===1&&a.removeAttribute(b);else a[b]=d}if(c.nodeName(a,"form")&&a.getAttributeNode(b))return a.getAttributeNode(b).nodeValue;if(b==="tabIndex")return(b=a.getAttributeNode("tabIndex"))&&
+b.specified?b.value:Va.test(a.nodeName)||Wa.test(a.nodeName)&&a.href?0:B;return a[b]}if(!c.support.style&&e&&b==="style"){if(f)a.style.cssText=""+d;return a.style.cssText}f&&a.setAttribute(b,""+d);if(!a.attributes[b]&&a.hasAttribute&&!a.hasAttribute(b))return B;a=!c.support.hrefNormalized&&e&&h?a.getAttribute(b,2):a.getAttribute(b);return a===null?B:a}});var X=/\.(.*)$/,ia=/^(?:textarea|input|select)$/i,La=/\./g,Ma=/ /g,Xa=/[^\w\s.|`]/g,Ya=function(a){return a.replace(Xa,"\\$&")},ua={focusin:0,focusout:0};
+c.event={add:function(a,b,d,e){if(!(a.nodeType===3||a.nodeType===8)){if(c.isWindow(a)&&a!==E&&!a.frameElement)a=E;if(d===false)d=U;else if(!d)return;var f,h;if(d.handler){f=d;d=f.handler}if(!d.guid)d.guid=c.guid++;if(h=c.data(a)){var l=a.nodeType?"events":"__events__",k=h[l],o=h.handle;if(typeof k==="function"){o=k.handle;k=k.events}else if(!k){a.nodeType||(h[l]=h=function(){});h.events=k={}}if(!o)h.handle=o=function(){return typeof c!=="undefined"&&!c.event.triggered?c.event.handle.apply(o.elem,
+arguments):B};o.elem=a;b=b.split(" ");for(var x=0,r;l=b[x++];){h=f?c.extend({},f):{handler:d,data:e};if(l.indexOf(".")>-1){r=l.split(".");l=r.shift();h.namespace=r.slice(0).sort().join(".")}else{r=[];h.namespace=""}h.type=l;if(!h.guid)h.guid=d.guid;var A=k[l],C=c.event.special[l]||{};if(!A){A=k[l]=[];if(!C.setup||C.setup.call(a,e,r,o)===false)if(a.addEventListener)a.addEventListener(l,o,false);else a.attachEvent&&a.attachEvent("on"+l,o)}if(C.add){C.add.call(a,h);if(!h.handler.guid)h.handler.guid=
+d.guid}A.push(h);c.event.global[l]=true}a=null}}},global:{},remove:function(a,b,d,e){if(!(a.nodeType===3||a.nodeType===8)){if(d===false)d=U;var f,h,l=0,k,o,x,r,A,C,J=a.nodeType?"events":"__events__",w=c.data(a),I=w&&w[J];if(w&&I){if(typeof I==="function"){w=I;I=I.events}if(b&&b.type){d=b.handler;b=b.type}if(!b||typeof b==="string"&&b.charAt(0)==="."){b=b||"";for(f in I)c.event.remove(a,f+b)}else{for(b=b.split(" ");f=b[l++];){r=f;k=f.indexOf(".")<0;o=[];if(!k){o=f.split(".");f=o.shift();x=RegExp("(^|\\.)"+
+c.map(o.slice(0).sort(),Ya).join("\\.(?:.*\\.)?")+"(\\.|$)")}if(A=I[f])if(d){r=c.event.special[f]||{};for(h=e||0;h<A.length;h++){C=A[h];if(d.guid===C.guid){if(k||x.test(C.namespace)){e==null&&A.splice(h--,1);r.remove&&r.remove.call(a,C)}if(e!=null)break}}if(A.length===0||e!=null&&A.length===1){if(!r.teardown||r.teardown.call(a,o)===false)c.removeEvent(a,f,w.handle);delete I[f]}}else for(h=0;h<A.length;h++){C=A[h];if(k||x.test(C.namespace)){c.event.remove(a,r,C.handler,h);A.splice(h--,1)}}}if(c.isEmptyObject(I)){if(b=
+w.handle)b.elem=null;delete w.events;delete w.handle;if(typeof w==="function")c.removeData(a,J);else c.isEmptyObject(w)&&c.removeData(a)}}}}},trigger:function(a,b,d,e){var f=a.type||a;if(!e){a=typeof a==="object"?a[c.expando]?a:c.extend(c.Event(f),a):c.Event(f);if(f.indexOf("!")>=0){a.type=f=f.slice(0,-1);a.exclusive=true}if(!d){a.stopPropagation();c.event.global[f]&&c.each(c.cache,function(){this.events&&this.events[f]&&c.event.trigger(a,b,this.handle.elem)})}if(!d||d.nodeType===3||d.nodeType===
+8)return B;a.result=B;a.target=d;b=c.makeArray(b);b.unshift(a)}a.currentTarget=d;(e=d.nodeType?c.data(d,"handle"):(c.data(d,"__events__")||{}).handle)&&e.apply(d,b);e=d.parentNode||d.ownerDocument;try{if(!(d&&d.nodeName&&c.noData[d.nodeName.toLowerCase()]))if(d["on"+f]&&d["on"+f].apply(d,b)===false){a.result=false;a.preventDefault()}}catch(h){}if(!a.isPropagationStopped()&&e)c.event.trigger(a,b,e,true);else if(!a.isDefaultPrevented()){var l;e=a.target;var k=f.replace(X,""),o=c.nodeName(e,"a")&&k===
+"click",x=c.event.special[k]||{};if((!x._default||x._default.call(d,a)===false)&&!o&&!(e&&e.nodeName&&c.noData[e.nodeName.toLowerCase()])){try{if(e[k]){if(l=e["on"+k])e["on"+k]=null;c.event.triggered=true;e[k]()}}catch(r){}if(l)e["on"+k]=l;c.event.triggered=false}}},handle:function(a){var b,d,e,f;d=[];var h=c.makeArray(arguments);a=h[0]=c.event.fix(a||E.event);a.currentTarget=this;b=a.type.indexOf(".")<0&&!a.exclusive;if(!b){e=a.type.split(".");a.type=e.shift();d=e.slice(0).sort();e=RegExp("(^|\\.)"+
+d.join("\\.(?:.*\\.)?")+"(\\.|$)")}a.namespace=a.namespace||d.join(".");f=c.data(this,this.nodeType?"events":"__events__");if(typeof f==="function")f=f.events;d=(f||{})[a.type];if(f&&d){d=d.slice(0);f=0;for(var l=d.length;f<l;f++){var k=d[f];if(b||e.test(k.namespace)){a.handler=k.handler;a.data=k.data;a.handleObj=k;k=k.handler.apply(this,h);if(k!==B){a.result=k;if(k===false){a.preventDefault();a.stopPropagation()}}if(a.isImmediatePropagationStopped())break}}}return a.result},props:"altKey attrChange attrName bubbles button cancelable charCode clientX clientY ctrlKey currentTarget data detail eventPhase fromElement handler keyCode layerX layerY metaKey newValue offsetX offsetY pageX pageY prevValue relatedNode relatedTarget screenX screenY shiftKey srcElement target toElement view wheelDelta which".split(" "),
+fix:function(a){if(a[c.expando])return a;var b=a;a=c.Event(b);for(var d=this.props.length,e;d;){e=this.props[--d];a[e]=b[e]}if(!a.target)a.target=a.srcElement||t;if(a.target.nodeType===3)a.target=a.target.parentNode;if(!a.relatedTarget&&a.fromElement)a.relatedTarget=a.fromElement===a.target?a.toElement:a.fromElement;if(a.pageX==null&&a.clientX!=null){b=t.documentElement;d=t.body;a.pageX=a.clientX+(b&&b.scrollLeft||d&&d.scrollLeft||0)-(b&&b.clientLeft||d&&d.clientLeft||0);a.pageY=a.clientY+(b&&b.scrollTop||
+d&&d.scrollTop||0)-(b&&b.clientTop||d&&d.clientTop||0)}if(a.which==null&&(a.charCode!=null||a.keyCode!=null))a.which=a.charCode!=null?a.charCode:a.keyCode;if(!a.metaKey&&a.ctrlKey)a.metaKey=a.ctrlKey;if(!a.which&&a.button!==B)a.which=a.button&1?1:a.button&2?3:a.button&4?2:0;return a},guid:1E8,proxy:c.proxy,special:{ready:{setup:c.bindReady,teardown:c.noop},live:{add:function(a){c.event.add(this,Y(a.origType,a.selector),c.extend({},a,{handler:Ka,guid:a.handler.guid}))},remove:function(a){c.event.remove(this,
+Y(a.origType,a.selector),a)}},beforeunload:{setup:function(a,b,d){if(c.isWindow(this))this.onbeforeunload=d},teardown:function(a,b){if(this.onbeforeunload===b)this.onbeforeunload=null}}}};c.removeEvent=t.removeEventListener?function(a,b,d){a.removeEventListener&&a.removeEventListener(b,d,false)}:function(a,b,d){a.detachEvent&&a.detachEvent("on"+b,d)};c.Event=function(a){if(!this.preventDefault)return new c.Event(a);if(a&&a.type){this.originalEvent=a;this.type=a.type}else this.type=a;this.timeStamp=
+c.now();this[c.expando]=true};c.Event.prototype={preventDefault:function(){this.isDefaultPrevented=ca;var a=this.originalEvent;if(a)if(a.preventDefault)a.preventDefault();else a.returnValue=false},stopPropagation:function(){this.isPropagationStopped=ca;var a=this.originalEvent;if(a){a.stopPropagation&&a.stopPropagation();a.cancelBubble=true}},stopImmediatePropagation:function(){this.isImmediatePropagationStopped=ca;this.stopPropagation()},isDefaultPrevented:U,isPropagationStopped:U,isImmediatePropagationStopped:U};
+var va=function(a){var b=a.relatedTarget;try{for(;b&&b!==this;)b=b.parentNode;if(b!==this){a.type=a.data;c.event.handle.apply(this,arguments)}}catch(d){}},wa=function(a){a.type=a.data;c.event.handle.apply(this,arguments)};c.each({mouseenter:"mouseover",mouseleave:"mouseout"},function(a,b){c.event.special[a]={setup:function(d){c.event.add(this,b,d&&d.selector?wa:va,a)},teardown:function(d){c.event.remove(this,b,d&&d.selector?wa:va)}}});if(!c.support.submitBubbles)c.event.special.submit={setup:function(){if(this.nodeName.toLowerCase()!==
+"form"){c.event.add(this,"click.specialSubmit",function(a){var b=a.target,d=b.type;if((d==="submit"||d==="image")&&c(b).closest("form").length){a.liveFired=B;return la("submit",this,arguments)}});c.event.add(this,"keypress.specialSubmit",function(a){var b=a.target,d=b.type;if((d==="text"||d==="password")&&c(b).closest("form").length&&a.keyCode===13){a.liveFired=B;return la("submit",this,arguments)}})}else return false},teardown:function(){c.event.remove(this,".specialSubmit")}};if(!c.support.changeBubbles){var V,
+xa=function(a){var b=a.type,d=a.value;if(b==="radio"||b==="checkbox")d=a.checked;else if(b==="select-multiple")d=a.selectedIndex>-1?c.map(a.options,function(e){return e.selected}).join("-"):"";else if(a.nodeName.toLowerCase()==="select")d=a.selectedIndex;return d},Z=function(a,b){var d=a.target,e,f;if(!(!ia.test(d.nodeName)||d.readOnly)){e=c.data(d,"_change_data");f=xa(d);if(a.type!=="focusout"||d.type!=="radio")c.data(d,"_change_data",f);if(!(e===B||f===e))if(e!=null||f){a.type="change";a.liveFired=
+B;return c.event.trigger(a,b,d)}}};c.event.special.change={filters:{focusout:Z,beforedeactivate:Z,click:function(a){var b=a.target,d=b.type;if(d==="radio"||d==="checkbox"||b.nodeName.toLowerCase()==="select")return Z.call(this,a)},keydown:function(a){var b=a.target,d=b.type;if(a.keyCode===13&&b.nodeName.toLowerCase()!=="textarea"||a.keyCode===32&&(d==="checkbox"||d==="radio")||d==="select-multiple")return Z.call(this,a)},beforeactivate:function(a){a=a.target;c.data(a,"_change_data",xa(a))}},setup:function(){if(this.type===
+"file")return false;for(var a in V)c.event.add(this,a+".specialChange",V[a]);return ia.test(this.nodeName)},teardown:function(){c.event.remove(this,".specialChange");return ia.test(this.nodeName)}};V=c.event.special.change.filters;V.focus=V.beforeactivate}t.addEventListener&&c.each({focus:"focusin",blur:"focusout"},function(a,b){function d(e){e=c.event.fix(e);e.type=b;return c.event.trigger(e,null,e.target)}c.event.special[b]={setup:function(){ua[b]++===0&&t.addEventListener(a,d,true)},teardown:function(){--ua[b]===
+0&&t.removeEventListener(a,d,true)}}});c.each(["bind","one"],function(a,b){c.fn[b]=function(d,e,f){if(typeof d==="object"){for(var h in d)this[b](h,e,d[h],f);return this}if(c.isFunction(e)||e===false){f=e;e=B}var l=b==="one"?c.proxy(f,function(o){c(this).unbind(o,l);return f.apply(this,arguments)}):f;if(d==="unload"&&b!=="one")this.one(d,e,f);else{h=0;for(var k=this.length;h<k;h++)c.event.add(this[h],d,l,e)}return this}});c.fn.extend({unbind:function(a,b){if(typeof a==="object"&&!a.preventDefault)for(var d in a)this.unbind(d,
+a[d]);else{d=0;for(var e=this.length;d<e;d++)c.event.remove(this[d],a,b)}return this},delegate:function(a,b,d,e){return this.live(b,d,e,a)},undelegate:function(a,b,d){return arguments.length===0?this.unbind("live"):this.die(b,null,d,a)},trigger:function(a,b){return this.each(function(){c.event.trigger(a,b,this)})},triggerHandler:function(a,b){if(this[0]){var d=c.Event(a);d.preventDefault();d.stopPropagation();c.event.trigger(d,b,this[0]);return d.result}},toggle:function(a){for(var b=arguments,d=
+1;d<b.length;)c.proxy(a,b[d++]);return this.click(c.proxy(a,function(e){var f=(c.data(this,"lastToggle"+a.guid)||0)%d;c.data(this,"lastToggle"+a.guid,f+1);e.preventDefault();return b[f].apply(this,arguments)||false}))},hover:function(a,b){return this.mouseenter(a).mouseleave(b||a)}});var ya={focus:"focusin",blur:"focusout",mouseenter:"mouseover",mouseleave:"mouseout"};c.each(["live","die"],function(a,b){c.fn[b]=function(d,e,f,h){var l,k=0,o,x,r=h||this.selector;h=h?this:c(this.context);if(typeof d===
+"object"&&!d.preventDefault){for(l in d)h[b](l,e,d[l],r);return this}if(c.isFunction(e)){f=e;e=B}for(d=(d||"").split(" ");(l=d[k++])!=null;){o=X.exec(l);x="";if(o){x=o[0];l=l.replace(X,"")}if(l==="hover")d.push("mouseenter"+x,"mouseleave"+x);else{o=l;if(l==="focus"||l==="blur"){d.push(ya[l]+x);l+=x}else l=(ya[l]||l)+x;if(b==="live"){x=0;for(var A=h.length;x<A;x++)c.event.add(h[x],"live."+Y(l,r),{data:e,selector:r,handler:f,origType:l,origHandler:f,preType:o})}else h.unbind("live."+Y(l,r),f)}}return this}});
+c.each("blur focus focusin focusout load resize scroll unload click dblclick mousedown mouseup mousemove mouseover mouseout mouseenter mouseleave change select submit keydown keypress keyup error".split(" "),function(a,b){c.fn[b]=function(d,e){if(e==null){e=d;d=null}return arguments.length>0?this.bind(b,d,e):this.trigger(b)};if(c.attrFn)c.attrFn[b]=true});E.attachEvent&&!E.addEventListener&&c(E).bind("unload",function(){for(var a in c.cache)if(c.cache[a].handle)try{c.event.remove(c.cache[a].handle.elem)}catch(b){}});
+(function(){function a(g,i,n,m,p,q){p=0;for(var u=m.length;p<u;p++){var y=m[p];if(y){var F=false;for(y=y[g];y;){if(y.sizcache===n){F=m[y.sizset];break}if(y.nodeType===1&&!q){y.sizcache=n;y.sizset=p}if(y.nodeName.toLowerCase()===i){F=y;break}y=y[g]}m[p]=F}}}function b(g,i,n,m,p,q){p=0;for(var u=m.length;p<u;p++){var y=m[p];if(y){var F=false;for(y=y[g];y;){if(y.sizcache===n){F=m[y.sizset];break}if(y.nodeType===1){if(!q){y.sizcache=n;y.sizset=p}if(typeof i!=="string"){if(y===i){F=true;break}}else if(k.filter(i,
+[y]).length>0){F=y;break}}y=y[g]}m[p]=F}}}var d=/((?:\((?:\([^()]+\)|[^()]+)+\)|\[(?:\[[^\[\]]*\]|['"][^'"]*['"]|[^\[\]'"]+)+\]|\\.|[^ >+~,(\[\\]+)+|[>+~])(\s*,\s*)?((?:.|\r|\n)*)/g,e=0,f=Object.prototype.toString,h=false,l=true;[0,0].sort(function(){l=false;return 0});var k=function(g,i,n,m){n=n||[];var p=i=i||t;if(i.nodeType!==1&&i.nodeType!==9)return[];if(!g||typeof g!=="string")return n;var q,u,y,F,M,N=true,O=k.isXML(i),D=[],R=g;do{d.exec("");if(q=d.exec(R)){R=q[3];D.push(q[1]);if(q[2]){F=q[3];
+break}}}while(q);if(D.length>1&&x.exec(g))if(D.length===2&&o.relative[D[0]])u=L(D[0]+D[1],i);else for(u=o.relative[D[0]]?[i]:k(D.shift(),i);D.length;){g=D.shift();if(o.relative[g])g+=D.shift();u=L(g,u)}else{if(!m&&D.length>1&&i.nodeType===9&&!O&&o.match.ID.test(D[0])&&!o.match.ID.test(D[D.length-1])){q=k.find(D.shift(),i,O);i=q.expr?k.filter(q.expr,q.set)[0]:q.set[0]}if(i){q=m?{expr:D.pop(),set:C(m)}:k.find(D.pop(),D.length===1&&(D[0]==="~"||D[0]==="+")&&i.parentNode?i.parentNode:i,O);u=q.expr?k.filter(q.expr,
+q.set):q.set;if(D.length>0)y=C(u);else N=false;for(;D.length;){q=M=D.pop();if(o.relative[M])q=D.pop();else M="";if(q==null)q=i;o.relative[M](y,q,O)}}else y=[]}y||(y=u);y||k.error(M||g);if(f.call(y)==="[object Array]")if(N)if(i&&i.nodeType===1)for(g=0;y[g]!=null;g++){if(y[g]&&(y[g]===true||y[g].nodeType===1&&k.contains(i,y[g])))n.push(u[g])}else for(g=0;y[g]!=null;g++)y[g]&&y[g].nodeType===1&&n.push(u[g]);else n.push.apply(n,y);else C(y,n);if(F){k(F,p,n,m);k.uniqueSort(n)}return n};k.uniqueSort=function(g){if(w){h=
+l;g.sort(w);if(h)for(var i=1;i<g.length;i++)g[i]===g[i-1]&&g.splice(i--,1)}return g};k.matches=function(g,i){return k(g,null,null,i)};k.matchesSelector=function(g,i){return k(i,null,null,[g]).length>0};k.find=function(g,i,n){var m;if(!g)return[];for(var p=0,q=o.order.length;p<q;p++){var u,y=o.order[p];if(u=o.leftMatch[y].exec(g)){var F=u[1];u.splice(1,1);if(F.substr(F.length-1)!=="\\"){u[1]=(u[1]||"").replace(/\\/g,"");m=o.find[y](u,i,n);if(m!=null){g=g.replace(o.match[y],"");break}}}}m||(m=i.getElementsByTagName("*"));
+return{set:m,expr:g}};k.filter=function(g,i,n,m){for(var p,q,u=g,y=[],F=i,M=i&&i[0]&&k.isXML(i[0]);g&&i.length;){for(var N in o.filter)if((p=o.leftMatch[N].exec(g))!=null&&p[2]){var O,D,R=o.filter[N];D=p[1];q=false;p.splice(1,1);if(D.substr(D.length-1)!=="\\"){if(F===y)y=[];if(o.preFilter[N])if(p=o.preFilter[N](p,F,n,y,m,M)){if(p===true)continue}else q=O=true;if(p)for(var j=0;(D=F[j])!=null;j++)if(D){O=R(D,p,j,F);var s=m^!!O;if(n&&O!=null)if(s)q=true;else F[j]=false;else if(s){y.push(D);q=true}}if(O!==
+B){n||(F=y);g=g.replace(o.match[N],"");if(!q)return[];break}}}if(g===u)if(q==null)k.error(g);else break;u=g}return F};k.error=function(g){throw"Syntax error, unrecognized expression: "+g;};var o=k.selectors={order:["ID","NAME","TAG"],match:{ID:/#((?:[\w\u00c0-\uFFFF\-]|\\.)+)/,CLASS:/\.((?:[\w\u00c0-\uFFFF\-]|\\.)+)/,NAME:/\[name=['"]*((?:[\w\u00c0-\uFFFF\-]|\\.)+)['"]*\]/,ATTR:/\[\s*((?:[\w\u00c0-\uFFFF\-]|\\.)+)\s*(?:(\S?=)\s*(['"]*)(.*?)\3|)\s*\]/,TAG:/^((?:[\w\u00c0-\uFFFF\*\-]|\\.)+)/,CHILD:/:(only|nth|last|first)-child(?:\((even|odd|[\dn+\-]*)\))?/,
+POS:/:(nth|eq|gt|lt|first|last|even|odd)(?:\((\d*)\))?(?=[^\-]|$)/,PSEUDO:/:((?:[\w\u00c0-\uFFFF\-]|\\.)+)(?:\((['"]?)((?:\([^\)]+\)|[^\(\)]*)+)\2\))?/},leftMatch:{},attrMap:{"class":"className","for":"htmlFor"},attrHandle:{href:function(g){return g.getAttribute("href")}},relative:{"+":function(g,i){var n=typeof i==="string",m=n&&!/\W/.test(i);n=n&&!m;if(m)i=i.toLowerCase();m=0;for(var p=g.length,q;m<p;m++)if(q=g[m]){for(;(q=q.previousSibling)&&q.nodeType!==1;);g[m]=n||q&&q.nodeName.toLowerCase()===
+i?q||false:q===i}n&&k.filter(i,g,true)},">":function(g,i){var n,m=typeof i==="string",p=0,q=g.length;if(m&&!/\W/.test(i))for(i=i.toLowerCase();p<q;p++){if(n=g[p]){n=n.parentNode;g[p]=n.nodeName.toLowerCase()===i?n:false}}else{for(;p<q;p++)if(n=g[p])g[p]=m?n.parentNode:n.parentNode===i;m&&k.filter(i,g,true)}},"":function(g,i,n){var m,p=e++,q=b;if(typeof i==="string"&&!/\W/.test(i)){m=i=i.toLowerCase();q=a}q("parentNode",i,p,g,m,n)},"~":function(g,i,n){var m,p=e++,q=b;if(typeof i==="string"&&!/\W/.test(i)){m=
+i=i.toLowerCase();q=a}q("previousSibling",i,p,g,m,n)}},find:{ID:function(g,i,n){if(typeof i.getElementById!=="undefined"&&!n)return(g=i.getElementById(g[1]))&&g.parentNode?[g]:[]},NAME:function(g,i){if(typeof i.getElementsByName!=="undefined"){for(var n=[],m=i.getElementsByName(g[1]),p=0,q=m.length;p<q;p++)m[p].getAttribute("name")===g[1]&&n.push(m[p]);return n.length===0?null:n}},TAG:function(g,i){return i.getElementsByTagName(g[1])}},preFilter:{CLASS:function(g,i,n,m,p,q){g=" "+g[1].replace(/\\/g,
+"")+" ";if(q)return g;q=0;for(var u;(u=i[q])!=null;q++)if(u)if(p^(u.className&&(" "+u.className+" ").replace(/[\t\n]/g," ").indexOf(g)>=0))n||m.push(u);else if(n)i[q]=false;return false},ID:function(g){return g[1].replace(/\\/g,"")},TAG:function(g){return g[1].toLowerCase()},CHILD:function(g){if(g[1]==="nth"){var i=/(-?)(\d*)n((?:\+|-)?\d*)/.exec(g[2]==="even"&&"2n"||g[2]==="odd"&&"2n+1"||!/\D/.test(g[2])&&"0n+"+g[2]||g[2]);g[2]=i[1]+(i[2]||1)-0;g[3]=i[3]-0}g[0]=e++;return g},ATTR:function(g,i,n,
+m,p,q){i=g[1].replace(/\\/g,"");if(!q&&o.attrMap[i])g[1]=o.attrMap[i];if(g[2]==="~=")g[4]=" "+g[4]+" ";return g},PSEUDO:function(g,i,n,m,p){if(g[1]==="not")if((d.exec(g[3])||"").length>1||/^\w/.test(g[3]))g[3]=k(g[3],null,null,i);else{g=k.filter(g[3],i,n,true^p);n||m.push.apply(m,g);return false}else if(o.match.POS.test(g[0])||o.match.CHILD.test(g[0]))return true;return g},POS:function(g){g.unshift(true);return g}},filters:{enabled:function(g){return g.disabled===false&&g.type!=="hidden"},disabled:function(g){return g.disabled===
+true},checked:function(g){return g.checked===true},selected:function(g){return g.selected===true},parent:function(g){return!!g.firstChild},empty:function(g){return!g.firstChild},has:function(g,i,n){return!!k(n[3],g).length},header:function(g){return/h\d/i.test(g.nodeName)},text:function(g){return"text"===g.type},radio:function(g){return"radio"===g.type},checkbox:function(g){return"checkbox"===g.type},file:function(g){return"file"===g.type},password:function(g){return"password"===g.type},submit:function(g){return"submit"===
+g.type},image:function(g){return"image"===g.type},reset:function(g){return"reset"===g.type},button:function(g){return"button"===g.type||g.nodeName.toLowerCase()==="button"},input:function(g){return/input|select|textarea|button/i.test(g.nodeName)}},setFilters:{first:function(g,i){return i===0},last:function(g,i,n,m){return i===m.length-1},even:function(g,i){return i%2===0},odd:function(g,i){return i%2===1},lt:function(g,i,n){return i<n[3]-0},gt:function(g,i,n){return i>n[3]-0},nth:function(g,i,n){return n[3]-
+0===i},eq:function(g,i,n){return n[3]-0===i}},filter:{PSEUDO:function(g,i,n,m){var p=i[1],q=o.filters[p];if(q)return q(g,n,i,m);else if(p==="contains")return(g.textContent||g.innerText||k.getText([g])||"").indexOf(i[3])>=0;else if(p==="not"){i=i[3];n=0;for(m=i.length;n<m;n++)if(i[n]===g)return false;return true}else k.error("Syntax error, unrecognized expression: "+p)},CHILD:function(g,i){var n=i[1],m=g;switch(n){case "only":case "first":for(;m=m.previousSibling;)if(m.nodeType===1)return false;if(n===
+"first")return true;m=g;case "last":for(;m=m.nextSibling;)if(m.nodeType===1)return false;return true;case "nth":n=i[2];var p=i[3];if(n===1&&p===0)return true;var q=i[0],u=g.parentNode;if(u&&(u.sizcache!==q||!g.nodeIndex)){var y=0;for(m=u.firstChild;m;m=m.nextSibling)if(m.nodeType===1)m.nodeIndex=++y;u.sizcache=q}m=g.nodeIndex-p;return n===0?m===0:m%n===0&&m/n>=0}},ID:function(g,i){return g.nodeType===1&&g.getAttribute("id")===i},TAG:function(g,i){return i==="*"&&g.nodeType===1||g.nodeName.toLowerCase()===
+i},CLASS:function(g,i){return(" "+(g.className||g.getAttribute("class"))+" ").indexOf(i)>-1},ATTR:function(g,i){var n=i[1];n=o.attrHandle[n]?o.attrHandle[n](g):g[n]!=null?g[n]:g.getAttribute(n);var m=n+"",p=i[2],q=i[4];return n==null?p==="!=":p==="="?m===q:p==="*="?m.indexOf(q)>=0:p==="~="?(" "+m+" ").indexOf(q)>=0:!q?m&&n!==false:p==="!="?m!==q:p==="^="?m.indexOf(q)===0:p==="$="?m.substr(m.length-q.length)===q:p==="|="?m===q||m.substr(0,q.length+1)===q+"-":false},POS:function(g,i,n,m){var p=o.setFilters[i[2]];
+if(p)return p(g,n,i,m)}}},x=o.match.POS,r=function(g,i){return"\\"+(i-0+1)},A;for(A in o.match){o.match[A]=RegExp(o.match[A].source+/(?![^\[]*\])(?![^\(]*\))/.source);o.leftMatch[A]=RegExp(/(^(?:.|\r|\n)*?)/.source+o.match[A].source.replace(/\\(\d+)/g,r))}var C=function(g,i){g=Array.prototype.slice.call(g,0);if(i){i.push.apply(i,g);return i}return g};try{Array.prototype.slice.call(t.documentElement.childNodes,0)}catch(J){C=function(g,i){var n=0,m=i||[];if(f.call(g)==="[object Array]")Array.prototype.push.apply(m,
+g);else if(typeof g.length==="number")for(var p=g.length;n<p;n++)m.push(g[n]);else for(;g[n];n++)m.push(g[n]);return m}}var w,I;if(t.documentElement.compareDocumentPosition)w=function(g,i){if(g===i){h=true;return 0}if(!g.compareDocumentPosition||!i.compareDocumentPosition)return g.compareDocumentPosition?-1:1;return g.compareDocumentPosition(i)&4?-1:1};else{w=function(g,i){var n,m,p=[],q=[];n=g.parentNode;m=i.parentNode;var u=n;if(g===i){h=true;return 0}else if(n===m)return I(g,i);else if(n){if(!m)return 1}else return-1;
+for(;u;){p.unshift(u);u=u.parentNode}for(u=m;u;){q.unshift(u);u=u.parentNode}n=p.length;m=q.length;for(u=0;u<n&&u<m;u++)if(p[u]!==q[u])return I(p[u],q[u]);return u===n?I(g,q[u],-1):I(p[u],i,1)};I=function(g,i,n){if(g===i)return n;for(g=g.nextSibling;g;){if(g===i)return-1;g=g.nextSibling}return 1}}k.getText=function(g){for(var i="",n,m=0;g[m];m++){n=g[m];if(n.nodeType===3||n.nodeType===4)i+=n.nodeValue;else if(n.nodeType!==8)i+=k.getText(n.childNodes)}return i};(function(){var g=t.createElement("div"),
+i="script"+(new Date).getTime(),n=t.documentElement;g.innerHTML="<a name='"+i+"'/>";n.insertBefore(g,n.firstChild);if(t.getElementById(i)){o.find.ID=function(m,p,q){if(typeof p.getElementById!=="undefined"&&!q)return(p=p.getElementById(m[1]))?p.id===m[1]||typeof p.getAttributeNode!=="undefined"&&p.getAttributeNode("id").nodeValue===m[1]?[p]:B:[]};o.filter.ID=function(m,p){var q=typeof m.getAttributeNode!=="undefined"&&m.getAttributeNode("id");return m.nodeType===1&&q&&q.nodeValue===p}}n.removeChild(g);
+n=g=null})();(function(){var g=t.createElement("div");g.appendChild(t.createComment(""));if(g.getElementsByTagName("*").length>0)o.find.TAG=function(i,n){var m=n.getElementsByTagName(i[1]);if(i[1]==="*"){for(var p=[],q=0;m[q];q++)m[q].nodeType===1&&p.push(m[q]);m=p}return m};g.innerHTML="<a href='#'></a>";if(g.firstChild&&typeof g.firstChild.getAttribute!=="undefined"&&g.firstChild.getAttribute("href")!=="#")o.attrHandle.href=function(i){return i.getAttribute("href",2)};g=null})();t.querySelectorAll&&
+function(){var g=k,i=t.createElement("div");i.innerHTML="<p class='TEST'></p>";if(!(i.querySelectorAll&&i.querySelectorAll(".TEST").length===0)){k=function(m,p,q,u){p=p||t;m=m.replace(/\=\s*([^'"\]]*)\s*\]/g,"='$1']");if(!u&&!k.isXML(p))if(p.nodeType===9)try{return C(p.querySelectorAll(m),q)}catch(y){}else if(p.nodeType===1&&p.nodeName.toLowerCase()!=="object"){var F=p.getAttribute("id"),M=F||"__sizzle__";F||p.setAttribute("id",M);try{return C(p.querySelectorAll("#"+M+" "+m),q)}catch(N){}finally{F||
+p.removeAttribute("id")}}return g(m,p,q,u)};for(var n in g)k[n]=g[n];i=null}}();(function(){var g=t.documentElement,i=g.matchesSelector||g.mozMatchesSelector||g.webkitMatchesSelector||g.msMatchesSelector,n=false;try{i.call(t.documentElement,"[test!='']:sizzle")}catch(m){n=true}if(i)k.matchesSelector=function(p,q){q=q.replace(/\=\s*([^'"\]]*)\s*\]/g,"='$1']");if(!k.isXML(p))try{if(n||!o.match.PSEUDO.test(q)&&!/!=/.test(q))return i.call(p,q)}catch(u){}return k(q,null,null,[p]).length>0}})();(function(){var g=
+t.createElement("div");g.innerHTML="<div class='test e'></div><div class='test'></div>";if(!(!g.getElementsByClassName||g.getElementsByClassName("e").length===0)){g.lastChild.className="e";if(g.getElementsByClassName("e").length!==1){o.order.splice(1,0,"CLASS");o.find.CLASS=function(i,n,m){if(typeof n.getElementsByClassName!=="undefined"&&!m)return n.getElementsByClassName(i[1])};g=null}}})();k.contains=t.documentElement.contains?function(g,i){return g!==i&&(g.contains?g.contains(i):true)}:t.documentElement.compareDocumentPosition?
+function(g,i){return!!(g.compareDocumentPosition(i)&16)}:function(){return false};k.isXML=function(g){return(g=(g?g.ownerDocument||g:0).documentElement)?g.nodeName!=="HTML":false};var L=function(g,i){for(var n,m=[],p="",q=i.nodeType?[i]:i;n=o.match.PSEUDO.exec(g);){p+=n[0];g=g.replace(o.match.PSEUDO,"")}g=o.relative[g]?g+"*":g;n=0;for(var u=q.length;n<u;n++)k(g,q[n],m);return k.filter(p,m)};c.find=k;c.expr=k.selectors;c.expr[":"]=c.expr.filters;c.unique=k.uniqueSort;c.text=k.getText;c.isXMLDoc=k.isXML;
+c.contains=k.contains})();var Za=/Until$/,$a=/^(?:parents|prevUntil|prevAll)/,ab=/,/,Na=/^.[^:#\[\.,]*$/,bb=Array.prototype.slice,cb=c.expr.match.POS;c.fn.extend({find:function(a){for(var b=this.pushStack("","find",a),d=0,e=0,f=this.length;e<f;e++){d=b.length;c.find(a,this[e],b);if(e>0)for(var h=d;h<b.length;h++)for(var l=0;l<d;l++)if(b[l]===b[h]){b.splice(h--,1);break}}return b},has:function(a){var b=c(a);return this.filter(function(){for(var d=0,e=b.length;d<e;d++)if(c.contains(this,b[d]))return true})},
+not:function(a){return this.pushStack(ma(this,a,false),"not",a)},filter:function(a){return this.pushStack(ma(this,a,true),"filter",a)},is:function(a){return!!a&&c.filter(a,this).length>0},closest:function(a,b){var d=[],e,f,h=this[0];if(c.isArray(a)){var l,k={},o=1;if(h&&a.length){e=0;for(f=a.length;e<f;e++){l=a[e];k[l]||(k[l]=c.expr.match.POS.test(l)?c(l,b||this.context):l)}for(;h&&h.ownerDocument&&h!==b;){for(l in k){e=k[l];if(e.jquery?e.index(h)>-1:c(h).is(e))d.push({selector:l,elem:h,level:o})}h=
+h.parentNode;o++}}return d}l=cb.test(a)?c(a,b||this.context):null;e=0;for(f=this.length;e<f;e++)for(h=this[e];h;)if(l?l.index(h)>-1:c.find.matchesSelector(h,a)){d.push(h);break}else{h=h.parentNode;if(!h||!h.ownerDocument||h===b)break}d=d.length>1?c.unique(d):d;return this.pushStack(d,"closest",a)},index:function(a){if(!a||typeof a==="string")return c.inArray(this[0],a?c(a):this.parent().children());return c.inArray(a.jquery?a[0]:a,this)},add:function(a,b){var d=typeof a==="string"?c(a,b||this.context):
+c.makeArray(a),e=c.merge(this.get(),d);return this.pushStack(!d[0]||!d[0].parentNode||d[0].parentNode.nodeType===11||!e[0]||!e[0].parentNode||e[0].parentNode.nodeType===11?e:c.unique(e))},andSelf:function(){return this.add(this.prevObject)}});c.each({parent:function(a){return(a=a.parentNode)&&a.nodeType!==11?a:null},parents:function(a){return c.dir(a,"parentNode")},parentsUntil:function(a,b,d){return c.dir(a,"parentNode",d)},next:function(a){return c.nth(a,2,"nextSibling")},prev:function(a){return c.nth(a,
+2,"previousSibling")},nextAll:function(a){return c.dir(a,"nextSibling")},prevAll:function(a){return c.dir(a,"previousSibling")},nextUntil:function(a,b,d){return c.dir(a,"nextSibling",d)},prevUntil:function(a,b,d){return c.dir(a,"previousSibling",d)},siblings:function(a){return c.sibling(a.parentNode.firstChild,a)},children:function(a){return c.sibling(a.firstChild)},contents:function(a){return c.nodeName(a,"iframe")?a.contentDocument||a.contentWindow.document:c.makeArray(a.childNodes)}},function(a,
+b){c.fn[a]=function(d,e){var f=c.map(this,b,d);Za.test(a)||(e=d);if(e&&typeof e==="string")f=c.filter(e,f);f=this.length>1?c.unique(f):f;if((this.length>1||ab.test(e))&&$a.test(a))f=f.reverse();return this.pushStack(f,a,bb.call(arguments).join(","))}});c.extend({filter:function(a,b,d){if(d)a=":not("+a+")";return b.length===1?c.find.matchesSelector(b[0],a)?[b[0]]:[]:c.find.matches(a,b)},dir:function(a,b,d){var e=[];for(a=a[b];a&&a.nodeType!==9&&(d===B||a.nodeType!==1||!c(a).is(d));){a.nodeType===1&&
+e.push(a);a=a[b]}return e},nth:function(a,b,d){b=b||1;for(var e=0;a;a=a[d])if(a.nodeType===1&&++e===b)break;return a},sibling:function(a,b){for(var d=[];a;a=a.nextSibling)a.nodeType===1&&a!==b&&d.push(a);return d}});var za=/ jQuery\d+="(?:\d+|null)"/g,$=/^\s+/,Aa=/<(?!area|br|col|embed|hr|img|input|link|meta|param)(([\w:]+)[^>]*)\/>/ig,Ba=/<([\w:]+)/,db=/<tbody/i,eb=/<|&#?\w+;/,Ca=/<(?:script|object|embed|option|style)/i,Da=/checked\s*(?:[^=]|=\s*.checked.)/i,fb=/\=([^="'>\s]+\/)>/g,P={option:[1,
+"<select multiple='multiple'>","</select>"],legend:[1,"<fieldset>","</fieldset>"],thead:[1,"<table>","</table>"],tr:[2,"<table><tbody>","</tbody></table>"],td:[3,"<table><tbody><tr>","</tr></tbody></table>"],col:[2,"<table><tbody></tbody><colgroup>","</colgroup></table>"],area:[1,"<map>","</map>"],_default:[0,"",""]};P.optgroup=P.option;P.tbody=P.tfoot=P.colgroup=P.caption=P.thead;P.th=P.td;if(!c.support.htmlSerialize)P._default=[1,"div<div>","</div>"];c.fn.extend({text:function(a){if(c.isFunction(a))return this.each(function(b){var d=
+c(this);d.text(a.call(this,b,d.text()))});if(typeof a!=="object"&&a!==B)return this.empty().append((this[0]&&this[0].ownerDocument||t).createTextNode(a));return c.text(this)},wrapAll:function(a){if(c.isFunction(a))return this.each(function(d){c(this).wrapAll(a.call(this,d))});if(this[0]){var b=c(a,this[0].ownerDocument).eq(0).clone(true);this[0].parentNode&&b.insertBefore(this[0]);b.map(function(){for(var d=this;d.firstChild&&d.firstChild.nodeType===1;)d=d.firstChild;return d}).append(this)}return this},
+wrapInner:function(a){if(c.isFunction(a))return this.each(function(b){c(this).wrapInner(a.call(this,b))});return this.each(function(){var b=c(this),d=b.contents();d.length?d.wrapAll(a):b.append(a)})},wrap:function(a){return this.each(function(){c(this).wrapAll(a)})},unwrap:function(){return this.parent().each(function(){c.nodeName(this,"body")||c(this).replaceWith(this.childNodes)}).end()},append:function(){return this.domManip(arguments,true,function(a){this.nodeType===1&&this.appendChild(a)})},
+prepend:function(){return this.domManip(arguments,true,function(a){this.nodeType===1&&this.insertBefore(a,this.firstChild)})},before:function(){if(this[0]&&this[0].parentNode)return this.domManip(arguments,false,function(b){this.parentNode.insertBefore(b,this)});else if(arguments.length){var a=c(arguments[0]);a.push.apply(a,this.toArray());return this.pushStack(a,"before",arguments)}},after:function(){if(this[0]&&this[0].parentNode)return this.domManip(arguments,false,function(b){this.parentNode.insertBefore(b,
+this.nextSibling)});else if(arguments.length){var a=this.pushStack(this,"after",arguments);a.push.apply(a,c(arguments[0]).toArray());return a}},remove:function(a,b){for(var d=0,e;(e=this[d])!=null;d++)if(!a||c.filter(a,[e]).length){if(!b&&e.nodeType===1){c.cleanData(e.getElementsByTagName("*"));c.cleanData([e])}e.parentNode&&e.parentNode.removeChild(e)}return this},empty:function(){for(var a=0,b;(b=this[a])!=null;a++)for(b.nodeType===1&&c.cleanData(b.getElementsByTagName("*"));b.firstChild;)b.removeChild(b.firstChild);
+return this},clone:function(a){var b=this.map(function(){if(!c.support.noCloneEvent&&!c.isXMLDoc(this)){var d=this.outerHTML,e=this.ownerDocument;if(!d){d=e.createElement("div");d.appendChild(this.cloneNode(true));d=d.innerHTML}return c.clean([d.replace(za,"").replace(fb,'="$1">').replace($,"")],e)[0]}else return this.cloneNode(true)});if(a===true){na(this,b);na(this.find("*"),b.find("*"))}return b},html:function(a){if(a===B)return this[0]&&this[0].nodeType===1?this[0].innerHTML.replace(za,""):null;
+else if(typeof a==="string"&&!Ca.test(a)&&(c.support.leadingWhitespace||!$.test(a))&&!P[(Ba.exec(a)||["",""])[1].toLowerCase()]){a=a.replace(Aa,"<$1></$2>");try{for(var b=0,d=this.length;b<d;b++)if(this[b].nodeType===1){c.cleanData(this[b].getElementsByTagName("*"));this[b].innerHTML=a}}catch(e){this.empty().append(a)}}else c.isFunction(a)?this.each(function(f){var h=c(this);h.html(a.call(this,f,h.html()))}):this.empty().append(a);return this},replaceWith:function(a){if(this[0]&&this[0].parentNode){if(c.isFunction(a))return this.each(function(b){var d=
+c(this),e=d.html();d.replaceWith(a.call(this,b,e))});if(typeof a!=="string")a=c(a).detach();return this.each(function(){var b=this.nextSibling,d=this.parentNode;c(this).remove();b?c(b).before(a):c(d).append(a)})}else return this.pushStack(c(c.isFunction(a)?a():a),"replaceWith",a)},detach:function(a){return this.remove(a,true)},domManip:function(a,b,d){var e,f,h,l=a[0],k=[];if(!c.support.checkClone&&arguments.length===3&&typeof l==="string"&&Da.test(l))return this.each(function(){c(this).domManip(a,
+b,d,true)});if(c.isFunction(l))return this.each(function(x){var r=c(this);a[0]=l.call(this,x,b?r.html():B);r.domManip(a,b,d)});if(this[0]){e=l&&l.parentNode;e=c.support.parentNode&&e&&e.nodeType===11&&e.childNodes.length===this.length?{fragment:e}:c.buildFragment(a,this,k);h=e.fragment;if(f=h.childNodes.length===1?h=h.firstChild:h.firstChild){b=b&&c.nodeName(f,"tr");f=0;for(var o=this.length;f<o;f++)d.call(b?c.nodeName(this[f],"table")?this[f].getElementsByTagName("tbody")[0]||this[f].appendChild(this[f].ownerDocument.createElement("tbody")):
+this[f]:this[f],f>0||e.cacheable||this.length>1?h.cloneNode(true):h)}k.length&&c.each(k,Oa)}return this}});c.buildFragment=function(a,b,d){var e,f,h;b=b&&b[0]?b[0].ownerDocument||b[0]:t;if(a.length===1&&typeof a[0]==="string"&&a[0].length<512&&b===t&&!Ca.test(a[0])&&(c.support.checkClone||!Da.test(a[0]))){f=true;if(h=c.fragments[a[0]])if(h!==1)e=h}if(!e){e=b.createDocumentFragment();c.clean(a,b,e,d)}if(f)c.fragments[a[0]]=h?e:1;return{fragment:e,cacheable:f}};c.fragments={};c.each({appendTo:"append",
+prependTo:"prepend",insertBefore:"before",insertAfter:"after",replaceAll:"replaceWith"},function(a,b){c.fn[a]=function(d){var e=[];d=c(d);var f=this.length===1&&this[0].parentNode;if(f&&f.nodeType===11&&f.childNodes.length===1&&d.length===1){d[b](this[0]);return this}else{f=0;for(var h=d.length;f<h;f++){var l=(f>0?this.clone(true):this).get();c(d[f])[b](l);e=e.concat(l)}return this.pushStack(e,a,d.selector)}}});c.extend({clean:function(a,b,d,e){b=b||t;if(typeof b.createElement==="undefined")b=b.ownerDocument||
+b[0]&&b[0].ownerDocument||t;for(var f=[],h=0,l;(l=a[h])!=null;h++){if(typeof l==="number")l+="";if(l){if(typeof l==="string"&&!eb.test(l))l=b.createTextNode(l);else if(typeof l==="string"){l=l.replace(Aa,"<$1></$2>");var k=(Ba.exec(l)||["",""])[1].toLowerCase(),o=P[k]||P._default,x=o[0],r=b.createElement("div");for(r.innerHTML=o[1]+l+o[2];x--;)r=r.lastChild;if(!c.support.tbody){x=db.test(l);k=k==="table"&&!x?r.firstChild&&r.firstChild.childNodes:o[1]==="<table>"&&!x?r.childNodes:[];for(o=k.length-
+1;o>=0;--o)c.nodeName(k[o],"tbody")&&!k[o].childNodes.length&&k[o].parentNode.removeChild(k[o])}!c.support.leadingWhitespace&&$.test(l)&&r.insertBefore(b.createTextNode($.exec(l)[0]),r.firstChild);l=r.childNodes}if(l.nodeType)f.push(l);else f=c.merge(f,l)}}if(d)for(h=0;f[h];h++)if(e&&c.nodeName(f[h],"script")&&(!f[h].type||f[h].type.toLowerCase()==="text/javascript"))e.push(f[h].parentNode?f[h].parentNode.removeChild(f[h]):f[h]);else{f[h].nodeType===1&&f.splice.apply(f,[h+1,0].concat(c.makeArray(f[h].getElementsByTagName("script"))));
+d.appendChild(f[h])}return f},cleanData:function(a){for(var b,d,e=c.cache,f=c.event.special,h=c.support.deleteExpando,l=0,k;(k=a[l])!=null;l++)if(!(k.nodeName&&c.noData[k.nodeName.toLowerCase()]))if(d=k[c.expando]){if((b=e[d])&&b.events)for(var o in b.events)f[o]?c.event.remove(k,o):c.removeEvent(k,o,b.handle);if(h)delete k[c.expando];else k.removeAttribute&&k.removeAttribute(c.expando);delete e[d]}}});var Ea=/alpha\([^)]*\)/i,gb=/opacity=([^)]*)/,hb=/-([a-z])/ig,ib=/([A-Z])/g,Fa=/^-?\d+(?:px)?$/i,
+jb=/^-?\d/,kb={position:"absolute",visibility:"hidden",display:"block"},Pa=["Left","Right"],Qa=["Top","Bottom"],W,Ga,aa,lb=function(a,b){return b.toUpperCase()};c.fn.css=function(a,b){if(arguments.length===2&&b===B)return this;return c.access(this,a,b,true,function(d,e,f){return f!==B?c.style(d,e,f):c.css(d,e)})};c.extend({cssHooks:{opacity:{get:function(a,b){if(b){var d=W(a,"opacity","opacity");return d===""?"1":d}else return a.style.opacity}}},cssNumber:{zIndex:true,fontWeight:true,opacity:true,
+zoom:true,lineHeight:true},cssProps:{"float":c.support.cssFloat?"cssFloat":"styleFloat"},style:function(a,b,d,e){if(!(!a||a.nodeType===3||a.nodeType===8||!a.style)){var f,h=c.camelCase(b),l=a.style,k=c.cssHooks[h];b=c.cssProps[h]||h;if(d!==B){if(!(typeof d==="number"&&isNaN(d)||d==null)){if(typeof d==="number"&&!c.cssNumber[h])d+="px";if(!k||!("set"in k)||(d=k.set(a,d))!==B)try{l[b]=d}catch(o){}}}else{if(k&&"get"in k&&(f=k.get(a,false,e))!==B)return f;return l[b]}}},css:function(a,b,d){var e,f=c.camelCase(b),
+h=c.cssHooks[f];b=c.cssProps[f]||f;if(h&&"get"in h&&(e=h.get(a,true,d))!==B)return e;else if(W)return W(a,b,f)},swap:function(a,b,d){var e={},f;for(f in b){e[f]=a.style[f];a.style[f]=b[f]}d.call(a);for(f in b)a.style[f]=e[f]},camelCase:function(a){return a.replace(hb,lb)}});c.curCSS=c.css;c.each(["height","width"],function(a,b){c.cssHooks[b]={get:function(d,e,f){var h;if(e){if(d.offsetWidth!==0)h=oa(d,b,f);else c.swap(d,kb,function(){h=oa(d,b,f)});if(h<=0){h=W(d,b,b);if(h==="0px"&&aa)h=aa(d,b,b);
+if(h!=null)return h===""||h==="auto"?"0px":h}if(h<0||h==null){h=d.style[b];return h===""||h==="auto"?"0px":h}return typeof h==="string"?h:h+"px"}},set:function(d,e){if(Fa.test(e)){e=parseFloat(e);if(e>=0)return e+"px"}else return e}}});if(!c.support.opacity)c.cssHooks.opacity={get:function(a,b){return gb.test((b&&a.currentStyle?a.currentStyle.filter:a.style.filter)||"")?parseFloat(RegExp.$1)/100+"":b?"1":""},set:function(a,b){var d=a.style;d.zoom=1;var e=c.isNaN(b)?"":"alpha(opacity="+b*100+")",f=
+d.filter||"";d.filter=Ea.test(f)?f.replace(Ea,e):d.filter+" "+e}};if(t.defaultView&&t.defaultView.getComputedStyle)Ga=function(a,b,d){var e;d=d.replace(ib,"-$1").toLowerCase();if(!(b=a.ownerDocument.defaultView))return B;if(b=b.getComputedStyle(a,null)){e=b.getPropertyValue(d);if(e===""&&!c.contains(a.ownerDocument.documentElement,a))e=c.style(a,d)}return e};if(t.documentElement.currentStyle)aa=function(a,b){var d,e,f=a.currentStyle&&a.currentStyle[b],h=a.style;if(!Fa.test(f)&&jb.test(f)){d=h.left;
+e=a.runtimeStyle.left;a.runtimeStyle.left=a.currentStyle.left;h.left=b==="fontSize"?"1em":f||0;f=h.pixelLeft+"px";h.left=d;a.runtimeStyle.left=e}return f===""?"auto":f};W=Ga||aa;if(c.expr&&c.expr.filters){c.expr.filters.hidden=function(a){var b=a.offsetHeight;return a.offsetWidth===0&&b===0||!c.support.reliableHiddenOffsets&&(a.style.display||c.css(a,"display"))==="none"};c.expr.filters.visible=function(a){return!c.expr.filters.hidden(a)}}var mb=c.now(),nb=/<script\b[^<]*(?:(?!<\/script>)<[^<]*)*<\/script>/gi,
+ob=/^(?:select|textarea)/i,pb=/^(?:color|date|datetime|email|hidden|month|number|password|range|search|tel|text|time|url|week)$/i,qb=/^(?:GET|HEAD)$/,Ra=/\[\]$/,T=/\=\?(&|$)/,ja=/\?/,rb=/([?&])_=[^&]*/,sb=/^(\w+:)?\/\/([^\/?#]+)/,tb=/%20/g,ub=/#.*$/,Ha=c.fn.load;c.fn.extend({load:function(a,b,d){if(typeof a!=="string"&&Ha)return Ha.apply(this,arguments);else if(!this.length)return this;var e=a.indexOf(" ");if(e>=0){var f=a.slice(e,a.length);a=a.slice(0,e)}e="GET";if(b)if(c.isFunction(b)){d=b;b=null}else if(typeof b===
+"object"){b=c.param(b,c.ajaxSettings.traditional);e="POST"}var h=this;c.ajax({url:a,type:e,dataType:"html",data:b,complete:function(l,k){if(k==="success"||k==="notmodified")h.html(f?c("<div>").append(l.responseText.replace(nb,"")).find(f):l.responseText);d&&h.each(d,[l.responseText,k,l])}});return this},serialize:function(){return c.param(this.serializeArray())},serializeArray:function(){return this.map(function(){return this.elements?c.makeArray(this.elements):this}).filter(function(){return this.name&&
+!this.disabled&&(this.checked||ob.test(this.nodeName)||pb.test(this.type))}).map(function(a,b){var d=c(this).val();return d==null?null:c.isArray(d)?c.map(d,function(e){return{name:b.name,value:e}}):{name:b.name,value:d}}).get()}});c.each("ajaxStart ajaxStop ajaxComplete ajaxError ajaxSuccess ajaxSend".split(" "),function(a,b){c.fn[b]=function(d){return this.bind(b,d)}});c.extend({get:function(a,b,d,e){if(c.isFunction(b)){e=e||d;d=b;b=null}return c.ajax({type:"GET",url:a,data:b,success:d,dataType:e})},
+getScript:function(a,b){return c.get(a,null,b,"script")},getJSON:function(a,b,d){return c.get(a,b,d,"json")},post:function(a,b,d,e){if(c.isFunction(b)){e=e||d;d=b;b={}}return c.ajax({type:"POST",url:a,data:b,success:d,dataType:e})},ajaxSetup:function(a){c.extend(c.ajaxSettings,a)},ajaxSettings:{url:location.href,global:true,type:"GET",contentType:"application/x-www-form-urlencoded",processData:true,async:true,xhr:function(){return new E.XMLHttpRequest},accepts:{xml:"application/xml, text/xml",html:"text/html",
+script:"text/javascript, application/javascript",json:"application/json, text/javascript",text:"text/plain",_default:"*/*"}},ajax:function(a){var b=c.extend(true,{},c.ajaxSettings,a),d,e,f,h=b.type.toUpperCase(),l=qb.test(h);b.url=b.url.replace(ub,"");b.context=a&&a.context!=null?a.context:b;if(b.data&&b.processData&&typeof b.data!=="string")b.data=c.param(b.data,b.traditional);if(b.dataType==="jsonp"){if(h==="GET")T.test(b.url)||(b.url+=(ja.test(b.url)?"&":"?")+(b.jsonp||"callback")+"=?");else if(!b.data||
+!T.test(b.data))b.data=(b.data?b.data+"&":"")+(b.jsonp||"callback")+"=?";b.dataType="json"}if(b.dataType==="json"&&(b.data&&T.test(b.data)||T.test(b.url))){d=b.jsonpCallback||"jsonp"+mb++;if(b.data)b.data=(b.data+"").replace(T,"="+d+"$1");b.url=b.url.replace(T,"="+d+"$1");b.dataType="script";var k=E[d];E[d]=function(m){if(c.isFunction(k))k(m);else{E[d]=B;try{delete E[d]}catch(p){}}f=m;c.handleSuccess(b,w,e,f);c.handleComplete(b,w,e,f);r&&r.removeChild(A)}}if(b.dataType==="script"&&b.cache===null)b.cache=
+false;if(b.cache===false&&l){var o=c.now(),x=b.url.replace(rb,"$1_="+o);b.url=x+(x===b.url?(ja.test(b.url)?"&":"?")+"_="+o:"")}if(b.data&&l)b.url+=(ja.test(b.url)?"&":"?")+b.data;b.global&&c.active++===0&&c.event.trigger("ajaxStart");o=(o=sb.exec(b.url))&&(o[1]&&o[1].toLowerCase()!==location.protocol||o[2].toLowerCase()!==location.host);if(b.dataType==="script"&&h==="GET"&&o){var r=t.getElementsByTagName("head")[0]||t.documentElement,A=t.createElement("script");if(b.scriptCharset)A.charset=b.scriptCharset;
+A.src=b.url;if(!d){var C=false;A.onload=A.onreadystatechange=function(){if(!C&&(!this.readyState||this.readyState==="loaded"||this.readyState==="complete")){C=true;c.handleSuccess(b,w,e,f);c.handleComplete(b,w,e,f);A.onload=A.onreadystatechange=null;r&&A.parentNode&&r.removeChild(A)}}}r.insertBefore(A,r.firstChild);return B}var J=false,w=b.xhr();if(w){b.username?w.open(h,b.url,b.async,b.username,b.password):w.open(h,b.url,b.async);try{if(b.data!=null&&!l||a&&a.contentType)w.setRequestHeader("Content-Type",
+b.contentType);if(b.ifModified){c.lastModified[b.url]&&w.setRequestHeader("If-Modified-Since",c.lastModified[b.url]);c.etag[b.url]&&w.setRequestHeader("If-None-Match",c.etag[b.url])}o||w.setRequestHeader("X-Requested-With","XMLHttpRequest");w.setRequestHeader("Accept",b.dataType&&b.accepts[b.dataType]?b.accepts[b.dataType]+", */*; q=0.01":b.accepts._default)}catch(I){}if(b.beforeSend&&b.beforeSend.call(b.context,w,b)===false){b.global&&c.active--===1&&c.event.trigger("ajaxStop");w.abort();return false}b.global&&
+c.triggerGlobal(b,"ajaxSend",[w,b]);var L=w.onreadystatechange=function(m){if(!w||w.readyState===0||m==="abort"){J||c.handleComplete(b,w,e,f);J=true;if(w)w.onreadystatechange=c.noop}else if(!J&&w&&(w.readyState===4||m==="timeout")){J=true;w.onreadystatechange=c.noop;e=m==="timeout"?"timeout":!c.httpSuccess(w)?"error":b.ifModified&&c.httpNotModified(w,b.url)?"notmodified":"success";var p;if(e==="success")try{f=c.httpData(w,b.dataType,b)}catch(q){e="parsererror";p=q}if(e==="success"||e==="notmodified")d||
+c.handleSuccess(b,w,e,f);else c.handleError(b,w,e,p);d||c.handleComplete(b,w,e,f);m==="timeout"&&w.abort();if(b.async)w=null}};try{var g=w.abort;w.abort=function(){w&&Function.prototype.call.call(g,w);L("abort")}}catch(i){}b.async&&b.timeout>0&&setTimeout(function(){w&&!J&&L("timeout")},b.timeout);try{w.send(l||b.data==null?null:b.data)}catch(n){c.handleError(b,w,null,n);c.handleComplete(b,w,e,f)}b.async||L();return w}},param:function(a,b){var d=[],e=function(h,l){l=c.isFunction(l)?l():l;d[d.length]=
+encodeURIComponent(h)+"="+encodeURIComponent(l)};if(b===B)b=c.ajaxSettings.traditional;if(c.isArray(a)||a.jquery)c.each(a,function(){e(this.name,this.value)});else for(var f in a)da(f,a[f],b,e);return d.join("&").replace(tb,"+")}});c.extend({active:0,lastModified:{},etag:{},handleError:function(a,b,d,e){a.error&&a.error.call(a.context,b,d,e);a.global&&c.triggerGlobal(a,"ajaxError",[b,a,e])},handleSuccess:function(a,b,d,e){a.success&&a.success.call(a.context,e,d,b);a.global&&c.triggerGlobal(a,"ajaxSuccess",
+[b,a])},handleComplete:function(a,b,d){a.complete&&a.complete.call(a.context,b,d);a.global&&c.triggerGlobal(a,"ajaxComplete",[b,a]);a.global&&c.active--===1&&c.event.trigger("ajaxStop")},triggerGlobal:function(a,b,d){(a.context&&a.context.url==null?c(a.context):c.event).trigger(b,d)},httpSuccess:function(a){try{return!a.status&&location.protocol==="file:"||a.status>=200&&a.status<300||a.status===304||a.status===1223}catch(b){}return false},httpNotModified:function(a,b){var d=a.getResponseHeader("Last-Modified"),
+e=a.getResponseHeader("Etag");if(d)c.lastModified[b]=d;if(e)c.etag[b]=e;return a.status===304},httpData:function(a,b,d){var e=a.getResponseHeader("content-type")||"",f=b==="xml"||!b&&e.indexOf("xml")>=0;a=f?a.responseXML:a.responseText;f&&a.documentElement.nodeName==="parsererror"&&c.error("parsererror");if(d&&d.dataFilter)a=d.dataFilter(a,b);if(typeof a==="string")if(b==="json"||!b&&e.indexOf("json")>=0)a=c.parseJSON(a);else if(b==="script"||!b&&e.indexOf("javascript")>=0)c.globalEval(a);return a}});
+if(E.ActiveXObject)c.ajaxSettings.xhr=function(){if(E.location.protocol!=="file:")try{return new E.XMLHttpRequest}catch(a){}try{return new E.ActiveXObject("Microsoft.XMLHTTP")}catch(b){}};c.support.ajax=!!c.ajaxSettings.xhr();var ea={},vb=/^(?:toggle|show|hide)$/,wb=/^([+\-]=)?([\d+.\-]+)(.*)$/,ba,pa=[["height","marginTop","marginBottom","paddingTop","paddingBottom"],["width","marginLeft","marginRight","paddingLeft","paddingRight"],["opacity"]];c.fn.extend({show:function(a,b,d){if(a||a===0)return this.animate(S("show",
+3),a,b,d);else{d=0;for(var e=this.length;d<e;d++){a=this[d];b=a.style.display;if(!c.data(a,"olddisplay")&&b==="none")b=a.style.display="";b===""&&c.css(a,"display")==="none"&&c.data(a,"olddisplay",qa(a.nodeName))}for(d=0;d<e;d++){a=this[d];b=a.style.display;if(b===""||b==="none")a.style.display=c.data(a,"olddisplay")||""}return this}},hide:function(a,b,d){if(a||a===0)return this.animate(S("hide",3),a,b,d);else{a=0;for(b=this.length;a<b;a++){d=c.css(this[a],"display");d!=="none"&&c.data(this[a],"olddisplay",
+d)}for(a=0;a<b;a++)this[a].style.display="none";return this}},_toggle:c.fn.toggle,toggle:function(a,b,d){var e=typeof a==="boolean";if(c.isFunction(a)&&c.isFunction(b))this._toggle.apply(this,arguments);else a==null||e?this.each(function(){var f=e?a:c(this).is(":hidden");c(this)[f?"show":"hide"]()}):this.animate(S("toggle",3),a,b,d);return this},fadeTo:function(a,b,d,e){return this.filter(":hidden").css("opacity",0).show().end().animate({opacity:b},a,d,e)},animate:function(a,b,d,e){var f=c.speed(b,
+d,e);if(c.isEmptyObject(a))return this.each(f.complete);return this[f.queue===false?"each":"queue"](function(){var h=c.extend({},f),l,k=this.nodeType===1,o=k&&c(this).is(":hidden"),x=this;for(l in a){var r=c.camelCase(l);if(l!==r){a[r]=a[l];delete a[l];l=r}if(a[l]==="hide"&&o||a[l]==="show"&&!o)return h.complete.call(this);if(k&&(l==="height"||l==="width")){h.overflow=[this.style.overflow,this.style.overflowX,this.style.overflowY];if(c.css(this,"display")==="inline"&&c.css(this,"float")==="none")if(c.support.inlineBlockNeedsLayout)if(qa(this.nodeName)===
+"inline")this.style.display="inline-block";else{this.style.display="inline";this.style.zoom=1}else this.style.display="inline-block"}if(c.isArray(a[l])){(h.specialEasing=h.specialEasing||{})[l]=a[l][1];a[l]=a[l][0]}}if(h.overflow!=null)this.style.overflow="hidden";h.curAnim=c.extend({},a);c.each(a,function(A,C){var J=new c.fx(x,h,A);if(vb.test(C))J[C==="toggle"?o?"show":"hide":C](a);else{var w=wb.exec(C),I=J.cur()||0;if(w){var L=parseFloat(w[2]),g=w[3]||"px";if(g!=="px"){c.style(x,A,(L||1)+g);I=(L||
+1)/J.cur()*I;c.style(x,A,I+g)}if(w[1])L=(w[1]==="-="?-1:1)*L+I;J.custom(I,L,g)}else J.custom(I,C,"")}});return true})},stop:function(a,b){var d=c.timers;a&&this.queue([]);this.each(function(){for(var e=d.length-1;e>=0;e--)if(d[e].elem===this){b&&d[e](true);d.splice(e,1)}});b||this.dequeue();return this}});c.each({slideDown:S("show",1),slideUp:S("hide",1),slideToggle:S("toggle",1),fadeIn:{opacity:"show"},fadeOut:{opacity:"hide"},fadeToggle:{opacity:"toggle"}},function(a,b){c.fn[a]=function(d,e,f){return this.animate(b,
+d,e,f)}});c.extend({speed:function(a,b,d){var e=a&&typeof a==="object"?c.extend({},a):{complete:d||!d&&b||c.isFunction(a)&&a,duration:a,easing:d&&b||b&&!c.isFunction(b)&&b};e.duration=c.fx.off?0:typeof e.duration==="number"?e.duration:e.duration in c.fx.speeds?c.fx.speeds[e.duration]:c.fx.speeds._default;e.old=e.complete;e.complete=function(){e.queue!==false&&c(this).dequeue();c.isFunction(e.old)&&e.old.call(this)};return e},easing:{linear:function(a,b,d,e){return d+e*a},swing:function(a,b,d,e){return(-Math.cos(a*
+Math.PI)/2+0.5)*e+d}},timers:[],fx:function(a,b,d){this.options=b;this.elem=a;this.prop=d;if(!b.orig)b.orig={}}});c.fx.prototype={update:function(){this.options.step&&this.options.step.call(this.elem,this.now,this);(c.fx.step[this.prop]||c.fx.step._default)(this)},cur:function(){if(this.elem[this.prop]!=null&&(!this.elem.style||this.elem.style[this.prop]==null))return this.elem[this.prop];var a=parseFloat(c.css(this.elem,this.prop));return a&&a>-1E4?a:0},custom:function(a,b,d){function e(l){return f.step(l)}
+var f=this,h=c.fx;this.startTime=c.now();this.start=a;this.end=b;this.unit=d||this.unit||"px";this.now=this.start;this.pos=this.state=0;e.elem=this.elem;if(e()&&c.timers.push(e)&&!ba)ba=setInterval(h.tick,h.interval)},show:function(){this.options.orig[this.prop]=c.style(this.elem,this.prop);this.options.show=true;this.custom(this.prop==="width"||this.prop==="height"?1:0,this.cur());c(this.elem).show()},hide:function(){this.options.orig[this.prop]=c.style(this.elem,this.prop);this.options.hide=true;
+this.custom(this.cur(),0)},step:function(a){var b=c.now(),d=true;if(a||b>=this.options.duration+this.startTime){this.now=this.end;this.pos=this.state=1;this.update();this.options.curAnim[this.prop]=true;for(var e in this.options.curAnim)if(this.options.curAnim[e]!==true)d=false;if(d){if(this.options.overflow!=null&&!c.support.shrinkWrapBlocks){var f=this.elem,h=this.options;c.each(["","X","Y"],function(k,o){f.style["overflow"+o]=h.overflow[k]})}this.options.hide&&c(this.elem).hide();if(this.options.hide||
+this.options.show)for(var l in this.options.curAnim)c.style(this.elem,l,this.options.orig[l]);this.options.complete.call(this.elem)}return false}else{a=b-this.startTime;this.state=a/this.options.duration;b=this.options.easing||(c.easing.swing?"swing":"linear");this.pos=c.easing[this.options.specialEasing&&this.options.specialEasing[this.prop]||b](this.state,a,0,1,this.options.duration);this.now=this.start+(this.end-this.start)*this.pos;this.update()}return true}};c.extend(c.fx,{tick:function(){for(var a=
+c.timers,b=0;b<a.length;b++)a[b]()||a.splice(b--,1);a.length||c.fx.stop()},interval:13,stop:function(){clearInterval(ba);ba=null},speeds:{slow:600,fast:200,_default:400},step:{opacity:function(a){c.style(a.elem,"opacity",a.now)},_default:function(a){if(a.elem.style&&a.elem.style[a.prop]!=null)a.elem.style[a.prop]=(a.prop==="width"||a.prop==="height"?Math.max(0,a.now):a.now)+a.unit;else a.elem[a.prop]=a.now}}});if(c.expr&&c.expr.filters)c.expr.filters.animated=function(a){return c.grep(c.timers,function(b){return a===
+b.elem}).length};var xb=/^t(?:able|d|h)$/i,Ia=/^(?:body|html)$/i;c.fn.offset="getBoundingClientRect"in t.documentElement?function(a){var b=this[0],d;if(a)return this.each(function(l){c.offset.setOffset(this,a,l)});if(!b||!b.ownerDocument)return null;if(b===b.ownerDocument.body)return c.offset.bodyOffset(b);try{d=b.getBoundingClientRect()}catch(e){}var f=b.ownerDocument,h=f.documentElement;if(!d||!c.contains(h,b))return d||{top:0,left:0};b=f.body;f=fa(f);return{top:d.top+(f.pageYOffset||c.support.boxModel&&
+h.scrollTop||b.scrollTop)-(h.clientTop||b.clientTop||0),left:d.left+(f.pageXOffset||c.support.boxModel&&h.scrollLeft||b.scrollLeft)-(h.clientLeft||b.clientLeft||0)}}:function(a){var b=this[0];if(a)return this.each(function(x){c.offset.setOffset(this,a,x)});if(!b||!b.ownerDocument)return null;if(b===b.ownerDocument.body)return c.offset.bodyOffset(b);c.offset.initialize();var d,e=b.offsetParent,f=b.ownerDocument,h=f.documentElement,l=f.body;d=(f=f.defaultView)?f.getComputedStyle(b,null):b.currentStyle;
+for(var k=b.offsetTop,o=b.offsetLeft;(b=b.parentNode)&&b!==l&&b!==h;){if(c.offset.supportsFixedPosition&&d.position==="fixed")break;d=f?f.getComputedStyle(b,null):b.currentStyle;k-=b.scrollTop;o-=b.scrollLeft;if(b===e){k+=b.offsetTop;o+=b.offsetLeft;if(c.offset.doesNotAddBorder&&!(c.offset.doesAddBorderForTableAndCells&&xb.test(b.nodeName))){k+=parseFloat(d.borderTopWidth)||0;o+=parseFloat(d.borderLeftWidth)||0}e=b.offsetParent}if(c.offset.subtractsBorderForOverflowNotVisible&&d.overflow!=="visible"){k+=
+parseFloat(d.borderTopWidth)||0;o+=parseFloat(d.borderLeftWidth)||0}d=d}if(d.position==="relative"||d.position==="static"){k+=l.offsetTop;o+=l.offsetLeft}if(c.offset.supportsFixedPosition&&d.position==="fixed"){k+=Math.max(h.scrollTop,l.scrollTop);o+=Math.max(h.scrollLeft,l.scrollLeft)}return{top:k,left:o}};c.offset={initialize:function(){var a=t.body,b=t.createElement("div"),d,e,f,h=parseFloat(c.css(a,"marginTop"))||0;c.extend(b.style,{position:"absolute",top:0,left:0,margin:0,border:0,width:"1px",
+height:"1px",visibility:"hidden"});b.innerHTML="<div style='position:absolute;top:0;left:0;margin:0;border:5px solid #000;padding:0;width:1px;height:1px;'><div></div></div><table style='position:absolute;top:0;left:0;margin:0;border:5px solid #000;padding:0;width:1px;height:1px;' cellpadding='0' cellspacing='0'><tr><td></td></tr></table>";a.insertBefore(b,a.firstChild);d=b.firstChild;e=d.firstChild;f=d.nextSibling.firstChild.firstChild;this.doesNotAddBorder=e.offsetTop!==5;this.doesAddBorderForTableAndCells=
+f.offsetTop===5;e.style.position="fixed";e.style.top="20px";this.supportsFixedPosition=e.offsetTop===20||e.offsetTop===15;e.style.position=e.style.top="";d.style.overflow="hidden";d.style.position="relative";this.subtractsBorderForOverflowNotVisible=e.offsetTop===-5;this.doesNotIncludeMarginInBodyOffset=a.offsetTop!==h;a.removeChild(b);c.offset.initialize=c.noop},bodyOffset:function(a){var b=a.offsetTop,d=a.offsetLeft;c.offset.initialize();if(c.offset.doesNotIncludeMarginInBodyOffset){b+=parseFloat(c.css(a,
+"marginTop"))||0;d+=parseFloat(c.css(a,"marginLeft"))||0}return{top:b,left:d}},setOffset:function(a,b,d){var e=c.css(a,"position");if(e==="static")a.style.position="relative";var f=c(a),h=f.offset(),l=c.css(a,"top"),k=c.css(a,"left"),o=e==="absolute"&&c.inArray("auto",[l,k])>-1;e={};var x={};if(o)x=f.position();l=o?x.top:parseInt(l,10)||0;k=o?x.left:parseInt(k,10)||0;if(c.isFunction(b))b=b.call(a,d,h);if(b.top!=null)e.top=b.top-h.top+l;if(b.left!=null)e.left=b.left-h.left+k;"using"in b?b.using.call(a,
+e):f.css(e)}};c.fn.extend({position:function(){if(!this[0])return null;var a=this[0],b=this.offsetParent(),d=this.offset(),e=Ia.test(b[0].nodeName)?{top:0,left:0}:b.offset();d.top-=parseFloat(c.css(a,"marginTop"))||0;d.left-=parseFloat(c.css(a,"marginLeft"))||0;e.top+=parseFloat(c.css(b[0],"borderTopWidth"))||0;e.left+=parseFloat(c.css(b[0],"borderLeftWidth"))||0;return{top:d.top-e.top,left:d.left-e.left}},offsetParent:function(){return this.map(function(){for(var a=this.offsetParent||t.body;a&&!Ia.test(a.nodeName)&&
+c.css(a,"position")==="static";)a=a.offsetParent;return a})}});c.each(["Left","Top"],function(a,b){var d="scroll"+b;c.fn[d]=function(e){var f=this[0],h;if(!f)return null;if(e!==B)return this.each(function(){if(h=fa(this))h.scrollTo(!a?e:c(h).scrollLeft(),a?e:c(h).scrollTop());else this[d]=e});else return(h=fa(f))?"pageXOffset"in h?h[a?"pageYOffset":"pageXOffset"]:c.support.boxModel&&h.document.documentElement[d]||h.document.body[d]:f[d]}});c.each(["Height","Width"],function(a,b){var d=b.toLowerCase();
+c.fn["inner"+b]=function(){return this[0]?parseFloat(c.css(this[0],d,"padding")):null};c.fn["outer"+b]=function(e){return this[0]?parseFloat(c.css(this[0],d,e?"margin":"border")):null};c.fn[d]=function(e){var f=this[0];if(!f)return e==null?null:this;if(c.isFunction(e))return this.each(function(l){var k=c(this);k[d](e.call(this,l,k[d]()))});if(c.isWindow(f))return f.document.compatMode==="CSS1Compat"&&f.document.documentElement["client"+b]||f.document.body["client"+b];else if(f.nodeType===9)return Math.max(f.documentElement["client"+
+b],f.body["scroll"+b],f.documentElement["scroll"+b],f.body["offset"+b],f.documentElement["offset"+b]);else if(e===B){f=c.css(f,d);var h=parseFloat(f);return c.isNaN(h)?f:h}else return this.css(d,typeof e==="string"?e:e+"px")}})})(window);
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/src/ldt/ldt/static/ldt/js/jquery.touchsplitter.js Fri Oct 02 10:24:05 2015 +0200
@@ -0,0 +1,444 @@
+// Generated by CoffeeScript 1.9.3
+
+/*
+ * Touch Splitter JQuery was created by Cole Lawrence(github:ZombieHippie)
+ * This work is licensed under the Creative Commons Attribution-ShareAlike 3.0
+ * Unported License. To view a copy of this license, visit http://creativecommons.org/licenses/by-sa/3.0/.
+ */
+
+(function() {
+ var bind = function(fn, me){ return function(){ return fn.apply(me, arguments); }; };
+
+ (function(mod) {
+ if (typeof exports === "object" && typeof module === "object") {
+ return mod(require("jquery"));
+ } else if (typeof define === "function" && define.amd) {
+ return define(["jquery"], mod);
+ } else {
+ return mod(jQuery);
+ }
+ })(function(jQuery) {
+ var $, TouchSplitter;
+ $ = jQuery;
+ $.fn.touchSplit = function(options) {
+ if (options == null) {
+ options = {};
+ }
+ if (this[0].touchSplitter != null) {
+ throw "Cannot make a splitter here! '" + this.selector + "' already has a splitter! Use $('" + this.selector + "')[0].touchSplitter.destroy(<optional side to remove>) to remove it!";
+ }
+ if (this.children().length !== 2 && this.children().length !== 0) {
+ throw "Cannot make a splitter here! Incorrect number of div children in '" + this.selector + "'";
+ }
+ return this[0].touchSplitter = new TouchSplitter(this, options);
+ };
+ return TouchSplitter = (function() {
+ function TouchSplitter(element, options) {
+ var barThick, firstdiv, inners, match, splitterHTML, testCalc, testEm, thickness, units;
+ this.element = element;
+ this.resize = bind(this.resize, this);
+ this.onResize = bind(this.onResize, this);
+ this.onResizeWindow = bind(this.onResizeWindow, this);
+ this.getSecond = bind(this.getSecond, this);
+ this.getFirst = bind(this.getFirst, this);
+ this.stopDragging = bind(this.stopDragging, this);
+ this.drag = bind(this.drag, this);
+ this.startDragging = bind(this.startDragging, this);
+ this.onTouchEnd = bind(this.onTouchEnd, this);
+ this.onTouchMove = bind(this.onTouchMove, this);
+ this.onTouchStart = bind(this.onTouchStart, this);
+ this.onMouseDown = bind(this.onMouseDown, this);
+ this.setPercentages = bind(this.setPercentages, this);
+ this.setDock = bind(this.setDock, this);
+ this.moveBar = bind(this.moveBar, this);
+ this.on = bind(this.on, this);
+ this.toggleDock = bind(this.toggleDock, this);
+ this.setRatios = bind(this.setRatios, this);
+ this.destroy = bind(this.destroy, this);
+ this.element.addClass('TouchSplitter');
+ this.support = {};
+ testEm = $('<div class="test-em"></div>');
+ testEm.appendTo(this.element);
+ barThick = testEm.width();
+ testEm.remove();
+ testCalc = $('<div class="test-calc"></div>');
+ testCalc.appendTo(this.element);
+ this.support.calc = true;
+ testCalc.remove();
+ if (options.orientation != null) {
+ if (options.orientation === "vertical") {
+ this.horizontal = false;
+ } else if (options.orientation === "horizontal") {
+
+ } else {
+ console.log("Touch Splitter ERROR: orientation cannot be:'" + options.orientation + "' defaulted to 'horizontal'");
+ }
+ }
+ if (this.horizontal !== false) {
+ this.horizontal = true;
+ }
+ this.element.addClass(this.horizontal ? "h-ts" : "v-ts");
+ this.firstMin = options.leftMin || options.topMin || options.firstMin || 0;
+ this.firstMax = options.leftMax || options.topMax || options.firstMax || false;
+ this.secondMin = options.rightMin || options.bottomMin || options.secondMin || 0;
+ this.secondMax = options.rightMax || options.bottomMax || options.secondMax || false;
+ if (this.firstMax && this.secondMax) {
+ console.log("Touch Splitter ERROR: cannot set max bounds of both first and second sections!");
+ this.secondMax = false;
+ }
+ if (options.dock != null) {
+ if (/both|left|top|first|right|bottom|second/i.test(options.dock)) {
+ this.docks = (function() {
+ switch (false) {
+ case !/both/i.test(options.dock):
+ return {
+ first: true,
+ second: true,
+ name: "both"
+ };
+ case !/left|top|first/i.test(options.dock):
+ return {
+ first: true,
+ second: false,
+ name: "first"
+ };
+ case !/right|bottom|second/i.test(options.dock):
+ return {
+ first: false,
+ second: true,
+ name: "second"
+ };
+ }
+ })();
+ }
+ }
+ if (this.docks) {
+ this.element.addClass('docks-' + this.docks.name);
+ } else {
+ this.docks = {
+ first: false,
+ second: false,
+ name: false
+ };
+ }
+ if (options.thickness != null) {
+ thickness = options.thickness;
+ units = "px";
+ if (typeof thickness === 'string') {
+ if (match = thickness.match(/^([\d\.]+)([a-zA-Z]+)$/)) {
+ thickness = match[1];
+ units = match[2];
+ }
+ thickness = parseFloat(thickness);
+ }
+ if (!thickness) {
+ throw "Unable to parse given thickness: " + options.thickness;
+ } else {
+ thickness = (function() {
+ switch (units) {
+ case "px":
+ return barThick = thickness;
+ case "em":
+ return barThick *= thickness;
+ default:
+ throw "Invalid unit used in given thickness: " + units;
+ }
+ })();
+ }
+ }
+ firstdiv = this.element.find(">div:first");
+ splitterHTML = "<div class=\"splitter-bar\">" + (this.docks.name && this.docks.name.match(/first|second/) ? '<div></div>' : '') + "</div>";
+ if (firstdiv.length === 0) {
+ inners = this.element.html();
+ this.element.html("<div></div> " + splitterHTML + " <div></div>");
+ this.element.find(">div:first").html(inners);
+ } else {
+ firstdiv.after(splitterHTML);
+ }
+ this.barThicknessPx = barThick / 2;
+ this.barThickness = .04;
+ this.barPosition = options.barPosition || 0.5;
+ this.dragging = false;
+ this.initMouse = 0;
+ this.initBarPosition = 0;
+ this.resize();
+ this.element.on('resize', this.onResize);
+ $(window).on('resize', this.onResizeWindow);
+ $(window).on('mouseup', this.stopDragging);
+ $(window).on('mousemove', this.drag);
+ this.element.find('>.splitter-bar').on('mousedown', this.onMouseDown);
+ this.element.find('>.splitter-bar').bind('touchstart', this.onTouchStart);
+ this.element.on('touchmove', this.onTouchMove);
+ this.element.on('touchend', this.onTouchEnd);
+ this.element.on('touchleave', this.onTouchEnd);
+ this.element.on('touchcancel', this.onTouchEnd);
+ }
+
+ TouchSplitter.prototype.destroy = function(side) {
+ var toRemove;
+ this.element.off('resize');
+ $(window).off('resize');
+ $(window).off('mouseup');
+ $(window).off('mousemove');
+ this.element.find('>.splitter-bar').off('mousedown');
+ this.element.find('>.splitter-bar').off('touchstart');
+ this.element.off('touchmove');
+ this.element.off('touchend');
+ this.element.off('touchleave');
+ this.element.off('touchcancel');
+ this.element.find('>.splitter-bar').remove();
+ this.element.removeClass('TouchSplitter h-ts v-ts docks-first docks-second docks-both');
+ if (side != null) {
+ toRemove = (function() {
+ switch (side) {
+ case 'left':
+ case 'top':
+ return '>div:first';
+ case 'right':
+ case 'bottom':
+ return '>div:last';
+ case 'both':
+ return '>div';
+ }
+ })();
+ this.element.find(toRemove).remove();
+ }
+ this.element.children().css({
+ width: "",
+ height: ""
+ });
+ return delete this.element[0].touchSplitter;
+ };
+
+ TouchSplitter.prototype.setRatios = function() {
+ var conv, ref, val;
+ this.splitDistance = this.horizontal ? this.element.width() : this.element.height();
+ ref = {
+ firstMin: this.firstMin,
+ firstMax: this.firstMax,
+ secondMin: this.secondMin,
+ secondMax: this.secondMax
+ };
+ for (conv in ref) {
+ val = ref[conv];
+ if (val) {
+ this[conv + 'Ratio'] = val / this.splitDistance;
+ }
+ }
+ return this.moveBar();
+ };
+
+ TouchSplitter.prototype.toggleDock = function() {
+ this.element.toggleClass('docked');
+ if (this.docked) {
+ return this.setDock(false);
+ } else {
+ return this.setDock(this.docks.name);
+ }
+ };
+
+ TouchSplitter.prototype.on = function(eventName, fn) {
+ return this.element.on(eventName, fn);
+ };
+
+ TouchSplitter.prototype.moveBar = function(newX) {
+ var cursorPos, cursorPos2;
+ cursorPos = this.barPosition;
+ if (newX != null) {
+ cursorPos = this.initBarPosition + (newX - this.initMouse) / this.splitDistance;
+ }
+ cursorPos2 = 1 - cursorPos;
+ if (this.docks.name) {
+ switch (this.docked) {
+ case 'first':
+ if (cursorPos > this.firstMinRatio / 2) {
+ this.setDock(false);
+ }
+ break;
+ case 'second':
+ if (cursorPos2 > this.secondMinRatio / 2) {
+ this.setDock(false);
+ }
+ break;
+ default:
+ if (this.docks.first && cursorPos < this.firstMinRatio / 2) {
+ this.setDock('first');
+ }
+ if (this.docks.second && cursorPos2 < this.secondMinRatio / 2) {
+ this.setDock('second');
+ }
+ }
+ }
+ if (!this.docked) {
+ this.barPosition = (function() {
+ switch (false) {
+ case !(this.firstMaxRatio && cursorPos > this.firstMaxRatio):
+ return this.firstMaxRatio;
+ case !(cursorPos < this.firstMinRatio):
+ return this.firstMinRatio;
+ case !(this.secondMaxRatio && cursorPos2 > this.secondMaxRatio):
+ return 1 - this.secondMaxRatio;
+ case !(cursorPos2 < this.secondMinRatio):
+ return 1 - this.secondMinRatio;
+ default:
+ return cursorPos;
+ }
+ }).call(this);
+ return this.setPercentages();
+ }
+ };
+
+ TouchSplitter.prototype.setDock = function(val, lastpos) {
+ if (lastpos == null) {
+ lastpos = this.barPosition;
+ }
+ this.docked = val;
+ this.barPosition = this.lastPosition;
+ this.lastPosition = lastpos;
+ return this.setPercentages();
+ };
+
+ TouchSplitter.prototype.setPercentages = function() {
+ var attr, first, firstCss, pos, second, secondCss, shave;
+ switch (this.docked) {
+ case 'first':
+ this.barPosition = 0;
+ break;
+ case 'second':
+ this.barPosition = 1;
+ }
+ pos = this.barPosition;
+ firstCss = secondCss = "";
+ if (!this.support.calc) {
+ if (pos < this.barThickness) {
+ pos = this.barThickness;
+ }
+ if (pos > 1 - this.barThickness) {
+ pos = 1 - this.barThickness;
+ }
+ first = pos - this.barThickness;
+ second = 1 - pos - this.barThickness;
+ firstCss = (100 * first - this.barThickness) + "%";
+ secondCss = (100 * second - this.barThickness) + "%";
+ } else {
+ shave = this.barThicknessPx;
+ if (this.docked) {
+ shave *= 2;
+ }
+ pos *= 100;
+ firstCss = "calc(" + pos + "% - " + shave + "px)";
+ secondCss = "calc(" + (100 - pos) + "% - " + shave + "px)";
+ }
+ attr = this.horizontal ? "width" : "height";
+ this.getFirst().css(attr, firstCss);
+ return this.getSecond().css(attr, secondCss);
+ };
+
+ TouchSplitter.prototype.onMouseDown = function(event) {
+ event.preventDefault();
+ this.initMouse = this.horizontal ? event.clientX : event.clientY;
+ return this.startDragging(event);
+ };
+
+ TouchSplitter.prototype.onTouchStart = function(event) {
+ var orig;
+ orig = event.originalEvent;
+ this.initMouse = this.horizontal ? orig.changedTouches[0].pageX : orig.changedTouches[0].pageY;
+ return this.startDragging(event);
+ };
+
+ TouchSplitter.prototype.onTouchMove = function(event) {
+ var orig, page;
+ if (!this.dragging) {
+ return;
+ }
+ event.preventDefault();
+ orig = event.originalEvent;
+ page = this.horizontal ? orig.changedTouches[0].pageX : orig.changedTouches[0].pageY;
+ return this.moveBar(page);
+ };
+
+ TouchSplitter.prototype.onTouchEnd = function(event) {
+ return this.stopDragging(event);
+ };
+
+ TouchSplitter.prototype.startDragging = function(event) {
+ this.initBarPosition = this.barPosition;
+ this.isToggler = !!event.target.parentNode.className.match(/\bsplitter-bar\b/);
+ this.dragging = true;
+ return this.element.trigger("dragstart");
+ };
+
+ TouchSplitter.prototype.drag = function(event) {
+ var client, whichM;
+ if (!this.dragging) {
+ return;
+ }
+ whichM = typeof event.buttons !== 'undefined' ? event.buttons : event.which;
+ if (whichM === 0) {
+ this.stopDragging();
+ }
+ client = this.horizontal ? event.clientX : event.clientY;
+ return this.moveBar(client);
+ };
+
+ TouchSplitter.prototype.stopDragging = function(event) {
+ if (this.dragging) {
+ this.dragging = false;
+ this.element.trigger("dragstop");
+ if (this.isToggler) {
+ return setTimeout((function(_this) {
+ return function() {
+ if ((_this.barPosition - _this.initBarPosition) === 0) {
+ return _this.toggleDock();
+ }
+ };
+ })(this), 0);
+ }
+ }
+ };
+
+ TouchSplitter.prototype.getFirst = function() {
+ return this.element.find('>div:first');
+ };
+
+ TouchSplitter.prototype.getSecond = function() {
+ return this.element.find('>div:last');
+ };
+
+ TouchSplitter.prototype.onResizeWindow = function(event) {
+ return this.resize();
+ };
+
+ TouchSplitter.prototype.onResize = function(event) {
+ if (event != null) {
+ event.stopPropagation();
+ if (!$(event.target).is(this.element)) {
+ return;
+ }
+ }
+ return this.resize();
+ };
+
+ TouchSplitter.prototype.resize = function() {
+ var attr;
+ this.setRatios();
+ attr = this.horizontal ? "width" : "height";
+ if (!this.support.calc) {
+ this.barThickness = this.barThicknessPx / this.splitDistance;
+ if (this.barThickness > 1) {
+ this.barThickness = 1;
+ }
+ this.element.find('>.splitter-bar').css(attr, this.barThickness * 200 + '%');
+ } else {
+ this.barThickness = 0;
+ }
+ return this.setPercentages();
+ };
+
+ return TouchSplitter;
+
+ })();
+ });
+
+}).call(this);
--- a/src/ldt/ldt/static/ldt/js/json2.js Fri Sep 18 16:10:29 2015 +0200
+++ b/src/ldt/ldt/static/ldt/js/json2.js Fri Oct 02 10:24:05 2015 +0200
@@ -1,6 +1,6 @@
/*
json2.js
- 2011-10-19
+ 2015-05-03
Public Domain.
@@ -17,7 +17,9 @@
This file creates a global JSON object containing two methods: stringify
- and parse.
+ and parse. This file is provides the ES5 JSON capability to ES3 systems.
+ If a project might run on IE8 or earlier, then this file should be included.
+ This file does nothing on ES5 systems.
JSON.stringify(value, replacer, space)
value any JavaScript value, usually an object or array.
@@ -48,7 +50,9 @@
Date.prototype.toJSON = function (key) {
function f(n) {
// Format integers to have at least two digits.
- return n < 10 ? '0' + n : n;
+ return n < 10
+ ? '0' + n
+ : n;
}
return this.getUTCFullYear() + '-' +
@@ -94,8 +98,9 @@
// text is '[\n\t"e",\n\t{\n\t\t"pluribus": "unum"\n\t}\n]'
text = JSON.stringify([new Date()], function (key, value) {
- return this[key] instanceof Date ?
- 'Date(' + this[key] + ')' : value;
+ return this[key] instanceof Date
+ ? 'Date(' + this[key] + ')'
+ : value;
});
// text is '["Date(---current time---)"]'
@@ -146,10 +151,12 @@
redistribute.
*/
-/*jslint evil: true, regexp: true */
+/*jslint
+ eval, for, this
+*/
-/*members "", "\b", "\t", "\n", "\f", "\r", "\"", JSON, "\\", apply,
- call, charCodeAt, getUTCDate, getUTCFullYear, getUTCHours,
+/*property
+ JSON, apply, call, charCodeAt, getUTCDate, getUTCFullYear, getUTCHours,
getUTCMinutes, getUTCMonth, getUTCSeconds, hasOwnProperty, join,
lastIndex, length, parse, prototype, push, replace, slice, stringify,
test, toJSON, toString, valueOf
@@ -159,53 +166,53 @@
// Create a JSON object only if one does not already exist. We create the
// methods in a closure to avoid creating global variables.
-var JSON;
-if (!JSON) {
+if (typeof JSON !== 'object') {
JSON = {};
}
(function () {
'use strict';
+
+ var rx_one = /^[\],:{}\s]*$/,
+ rx_two = /\\(?:["\\\/bfnrt]|u[0-9a-fA-F]{4})/g,
+ rx_three = /"[^"\\\n\r]*"|true|false|null|-?\d+(?:\.\d*)?(?:[eE][+\-]?\d+)?/g,
+ rx_four = /(?:^|:|,)(?:\s*\[)+/g,
+ rx_escapable = /[\\\"\u0000-\u001f\u007f-\u009f\u00ad\u0600-\u0604\u070f\u17b4\u17b5\u200c-\u200f\u2028-\u202f\u2060-\u206f\ufeff\ufff0-\uffff]/g,
+ rx_dangerous = /[\u0000\u00ad\u0600-\u0604\u070f\u17b4\u17b5\u200c-\u200f\u2028-\u202f\u2060-\u206f\ufeff\ufff0-\uffff]/g;
function f(n) {
// Format integers to have at least two digits.
- return n < 10 ? '0' + n : n;
+ return n < 10
+ ? '0' + n
+ : n;
+ }
+
+ function this_value() {
+ return this.valueOf();
}
if (typeof Date.prototype.toJSON !== 'function') {
- Date.prototype.toJSON = function (key) {
+ Date.prototype.toJSON = function () {
return isFinite(this.valueOf())
- ? this.getUTCFullYear() + '-' +
- f(this.getUTCMonth() + 1) + '-' +
- f(this.getUTCDate()) + 'T' +
- f(this.getUTCHours()) + ':' +
- f(this.getUTCMinutes()) + ':' +
- f(this.getUTCSeconds()) + 'Z'
+ ? this.getUTCFullYear() + '-' +
+ f(this.getUTCMonth() + 1) + '-' +
+ f(this.getUTCDate()) + 'T' +
+ f(this.getUTCHours()) + ':' +
+ f(this.getUTCMinutes()) + ':' +
+ f(this.getUTCSeconds()) + 'Z'
: null;
};
- String.prototype.toJSON =
- Number.prototype.toJSON =
- Boolean.prototype.toJSON = function (key) {
- return this.valueOf();
- };
+ Boolean.prototype.toJSON = this_value;
+ Number.prototype.toJSON = this_value;
+ String.prototype.toJSON = this_value;
}
- var cx = /[\u0000\u00ad\u0600-\u0604\u070f\u17b4\u17b5\u200c-\u200f\u2028-\u202f\u2060-\u206f\ufeff\ufff0-\uffff]/g,
- escapable = /[\\\"\x00-\x1f\x7f-\x9f\u00ad\u0600-\u0604\u070f\u17b4\u17b5\u200c-\u200f\u2028-\u202f\u2060-\u206f\ufeff\ufff0-\uffff]/g,
- gap,
+ var gap,
indent,
- meta = { // table of character substitutions
- '\b': '\\b',
- '\t': '\\t',
- '\n': '\\n',
- '\f': '\\f',
- '\r': '\\r',
- '"' : '\\"',
- '\\': '\\\\'
- },
+ meta,
rep;
@@ -216,13 +223,15 @@
// Otherwise we must also replace the offending characters with safe escape
// sequences.
- escapable.lastIndex = 0;
- return escapable.test(string) ? '"' + string.replace(escapable, function (a) {
- var c = meta[a];
- return typeof c === 'string'
- ? c
- : '\\u' + ('0000' + a.charCodeAt(0).toString(16)).slice(-4);
- }) + '"' : '"' + string + '"';
+ rx_escapable.lastIndex = 0;
+ return rx_escapable.test(string)
+ ? '"' + string.replace(rx_escapable, function (a) {
+ var c = meta[a];
+ return typeof c === 'string'
+ ? c
+ : '\\u' + ('0000' + a.charCodeAt(0).toString(16)).slice(-4);
+ }) + '"'
+ : '"' + string + '"';
}
@@ -262,7 +271,9 @@
// JSON numbers must be finite. Encode non-finite numbers as null.
- return isFinite(value) ? String(value) : 'null';
+ return isFinite(value)
+ ? String(value)
+ : 'null';
case 'boolean':
case 'null':
@@ -308,8 +319,8 @@
v = partial.length === 0
? '[]'
: gap
- ? '[\n' + gap + partial.join(',\n' + gap) + '\n' + mind + ']'
- : '[' + partial.join(',') + ']';
+ ? '[\n' + gap + partial.join(',\n' + gap) + '\n' + mind + ']'
+ : '[' + partial.join(',') + ']';
gap = mind;
return v;
}
@@ -323,7 +334,11 @@
k = rep[i];
v = str(k, value);
if (v) {
- partial.push(quote(k) + (gap ? ': ' : ':') + v);
+ partial.push(quote(k) + (
+ gap
+ ? ': '
+ : ':'
+ ) + v);
}
}
}
@@ -335,7 +350,11 @@
if (Object.prototype.hasOwnProperty.call(value, k)) {
v = str(k, value);
if (v) {
- partial.push(quote(k) + (gap ? ': ' : ':') + v);
+ partial.push(quote(k) + (
+ gap
+ ? ': '
+ : ':'
+ ) + v);
}
}
}
@@ -347,8 +366,8 @@
v = partial.length === 0
? '{}'
: gap
- ? '{\n' + gap + partial.join(',\n' + gap) + '\n' + mind + '}'
- : '{' + partial.join(',') + '}';
+ ? '{\n' + gap + partial.join(',\n' + gap) + '\n' + mind + '}'
+ : '{' + partial.join(',') + '}';
gap = mind;
return v;
}
@@ -357,6 +376,15 @@
// If the JSON object does not yet have a stringify method, give it one.
if (typeof JSON.stringify !== 'function') {
+ meta = { // table of character substitutions
+ '\b': '\\b',
+ '\t': '\\t',
+ '\n': '\\n',
+ '\f': '\\f',
+ '\r': '\\r',
+ '"': '\\"',
+ '\\': '\\\\'
+ };
JSON.stringify = function (value, replacer, space) {
// The stringify method takes a value and an optional replacer, and an optional
@@ -438,11 +466,11 @@
// incorrectly, either silently deleting them, or treating them as line endings.
text = String(text);
- cx.lastIndex = 0;
- if (cx.test(text)) {
- text = text.replace(cx, function (a) {
+ rx_dangerous.lastIndex = 0;
+ if (rx_dangerous.test(text)) {
+ text = text.replace(rx_dangerous, function (a) {
return '\\u' +
- ('0000' + a.charCodeAt(0).toString(16)).slice(-4);
+ ('0000' + a.charCodeAt(0).toString(16)).slice(-4);
});
}
@@ -459,10 +487,14 @@
// we look to see that the remaining characters are only whitespace or ']' or
// ',' or ':' or '{' or '}'. If that is so, then the text is safe for eval.
- if (/^[\],:{}\s]*$/
- .test(text.replace(/\\(?:["\\\/bfnrt]|u[0-9a-fA-F]{4})/g, '@')
- .replace(/"[^"\\\n\r]*"|true|false|null|-?\d+(?:\.\d*)?(?:[eE][+\-]?\d+)?/g, ']')
- .replace(/(?:^|:|,)(?:\s*\[)+/g, ''))) {
+ if (
+ rx_one.test(
+ text
+ .replace(rx_two, '@')
+ .replace(rx_three, ']')
+ .replace(rx_four, '')
+ )
+ ) {
// In the third stage we use the eval function to compile the text into a
// JavaScript structure. The '{' operator is subject to a syntactic ambiguity
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/src/ldt/ldt/static/ldt/js/mousetrap-global-bind.js Fri Oct 02 10:24:05 2015 +0200
@@ -0,0 +1,43 @@
+/**
+ * adds a bindGlobal method to Mousetrap that allows you to
+ * bind specific keyboard shortcuts that will still work
+ * inside a text input field
+ *
+ * usage:
+ * Mousetrap.bindGlobal('ctrl+s', _saveChanges);
+ */
+/* global Mousetrap:true */
+(function(Mousetrap) {
+ var _globalCallbacks = {};
+ var _originalStopCallback = Mousetrap.prototype.stopCallback;
+
+ Mousetrap.prototype.stopCallback = function(e, element, combo, sequence) {
+ var self = this;
+
+ if (self.paused) {
+ return true;
+ }
+
+ if (_globalCallbacks[combo] || _globalCallbacks[sequence]) {
+ return false;
+ }
+
+ return _originalStopCallback.call(self, e, element, combo);
+ };
+
+ Mousetrap.prototype.bindGlobal = function(keys, callback, action) {
+ var self = this;
+ self.bind(keys, callback, action);
+
+ if (keys instanceof Array) {
+ for (var i = 0; i < keys.length; i++) {
+ _globalCallbacks[keys[i]] = true;
+ }
+ return;
+ }
+
+ _globalCallbacks[keys] = true;
+ };
+
+ Mousetrap.init();
+}) (Mousetrap);
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/src/ldt/ldt/static/ldt/js/mousetrap.min.js Fri Oct 02 10:24:05 2015 +0200
@@ -0,0 +1,11 @@
+/* mousetrap v1.5.3 craig.is/killing/mice */
+(function(C,r,g){function t(a,b,h){a.addEventListener?a.addEventListener(b,h,!1):a.attachEvent("on"+b,h)}function x(a){if("keypress"==a.type){var b=String.fromCharCode(a.which);a.shiftKey||(b=b.toLowerCase());return b}return l[a.which]?l[a.which]:p[a.which]?p[a.which]:String.fromCharCode(a.which).toLowerCase()}function D(a){var b=[];a.shiftKey&&b.push("shift");a.altKey&&b.push("alt");a.ctrlKey&&b.push("ctrl");a.metaKey&&b.push("meta");return b}function u(a){return"shift"==a||"ctrl"==a||"alt"==a||
+"meta"==a}function y(a,b){var h,c,e,g=[];h=a;"+"===h?h=["+"]:(h=h.replace(/\+{2}/g,"+plus"),h=h.split("+"));for(e=0;e<h.length;++e)c=h[e],z[c]&&(c=z[c]),b&&"keypress"!=b&&A[c]&&(c=A[c],g.push("shift")),u(c)&&g.push(c);h=c;e=b;if(!e){if(!k){k={};for(var m in l)95<m&&112>m||l.hasOwnProperty(m)&&(k[l[m]]=m)}e=k[h]?"keydown":"keypress"}"keypress"==e&&g.length&&(e="keydown");return{key:c,modifiers:g,action:e}}function B(a,b){return null===a||a===r?!1:a===b?!0:B(a.parentNode,b)}function c(a){function b(a){a=
+a||{};var b=!1,n;for(n in q)a[n]?b=!0:q[n]=0;b||(v=!1)}function h(a,b,n,f,c,h){var g,e,l=[],m=n.type;if(!d._callbacks[a])return[];"keyup"==m&&u(a)&&(b=[a]);for(g=0;g<d._callbacks[a].length;++g)if(e=d._callbacks[a][g],(f||!e.seq||q[e.seq]==e.level)&&m==e.action){var k;(k="keypress"==m&&!n.metaKey&&!n.ctrlKey)||(k=e.modifiers,k=b.sort().join(",")===k.sort().join(","));k&&(k=f&&e.seq==f&&e.level==h,(!f&&e.combo==c||k)&&d._callbacks[a].splice(g,1),l.push(e))}return l}function g(a,b,n,f){d.stopCallback(b,
+b.target||b.srcElement,n,f)||!1!==a(b,n)||(b.preventDefault?b.preventDefault():b.returnValue=!1,b.stopPropagation?b.stopPropagation():b.cancelBubble=!0)}function e(a){"number"!==typeof a.which&&(a.which=a.keyCode);var b=x(a);b&&("keyup"==a.type&&w===b?w=!1:d.handleKey(b,D(a),a))}function l(a,c,n,f){function e(c){return function(){v=c;++q[a];clearTimeout(k);k=setTimeout(b,1E3)}}function h(c){g(n,c,a);"keyup"!==f&&(w=x(c));setTimeout(b,10)}for(var d=q[a]=0;d<c.length;++d){var p=d+1===c.length?h:e(f||
+y(c[d+1]).action);m(c[d],p,f,a,d)}}function m(a,b,c,f,e){d._directMap[a+":"+c]=b;a=a.replace(/\s+/g," ");var g=a.split(" ");1<g.length?l(a,g,b,c):(c=y(a,c),d._callbacks[c.key]=d._callbacks[c.key]||[],h(c.key,c.modifiers,{type:c.action},f,a,e),d._callbacks[c.key][f?"unshift":"push"]({callback:b,modifiers:c.modifiers,action:c.action,seq:f,level:e,combo:a}))}var d=this;a=a||r;if(!(d instanceof c))return new c(a);d.target=a;d._callbacks={};d._directMap={};var q={},k,w=!1,p=!1,v=!1;d._handleKey=function(a,
+c,e){var f=h(a,c,e),d;c={};var k=0,l=!1;for(d=0;d<f.length;++d)f[d].seq&&(k=Math.max(k,f[d].level));for(d=0;d<f.length;++d)f[d].seq?f[d].level==k&&(l=!0,c[f[d].seq]=1,g(f[d].callback,e,f[d].combo,f[d].seq)):l||g(f[d].callback,e,f[d].combo);f="keypress"==e.type&&p;e.type!=v||u(a)||f||b(c);p=l&&"keydown"==e.type};d._bindMultiple=function(a,b,c){for(var d=0;d<a.length;++d)m(a[d],b,c)};t(a,"keypress",e);t(a,"keydown",e);t(a,"keyup",e)}var l={8:"backspace",9:"tab",13:"enter",16:"shift",17:"ctrl",18:"alt",
+20:"capslock",27:"esc",32:"space",33:"pageup",34:"pagedown",35:"end",36:"home",37:"left",38:"up",39:"right",40:"down",45:"ins",46:"del",91:"meta",93:"meta",224:"meta"},p={106:"*",107:"+",109:"-",110:".",111:"/",186:";",187:"=",188:",",189:"-",190:".",191:"/",192:"`",219:"[",220:"\\",221:"]",222:"'"},A={"~":"`","!":"1","@":"2","#":"3",$:"4","%":"5","^":"6","&":"7","*":"8","(":"9",")":"0",_:"-","+":"=",":":";",'"':"'","<":",",">":".","?":"/","|":"\\"},z={option:"alt",command:"meta","return":"enter",
+escape:"esc",plus:"+",mod:/Mac|iPod|iPhone|iPad/.test(navigator.platform)?"meta":"ctrl"},k;for(g=1;20>g;++g)l[111+g]="f"+g;for(g=0;9>=g;++g)l[g+96]=g;c.prototype.bind=function(a,b,c){a=a instanceof Array?a:[a];this._bindMultiple.call(this,a,b,c);return this};c.prototype.unbind=function(a,b){return this.bind.call(this,a,function(){},b)};c.prototype.trigger=function(a,b){if(this._directMap[a+":"+b])this._directMap[a+":"+b]({},a);return this};c.prototype.reset=function(){this._callbacks={};this._directMap=
+{};return this};c.prototype.stopCallback=function(a,b){return-1<(" "+b.className+" ").indexOf(" mousetrap ")||B(b,this.target)?!1:"INPUT"==b.tagName||"SELECT"==b.tagName||"TEXTAREA"==b.tagName||b.isContentEditable};c.prototype.handleKey=function(){return this._handleKey.apply(this,arguments)};c.init=function(){var a=c(r),b;for(b in a)"_"!==b.charAt(0)&&(c[b]=function(b){return function(){return a[b].apply(a,arguments)}}(b))};c.init();C.Mousetrap=c;"undefined"!==typeof module&&module.exports&&(module.exports=
+c);"function"===typeof define&&define.amd&&define(function(){return c})})(window,document);
--- a/src/ldt/ldt/static/ldt/js/mustache.js Fri Sep 18 16:10:29 2015 +0200
+++ b/src/ldt/ldt/static/ldt/js/mustache.js Fri Oct 02 10:24:05 2015 +0200
@@ -3,369 +3,106 @@
* http://github.com/janl/mustache.js
*/
-/*global define: false*/
+/*global define: false Mustache: true*/
-(function (root, factory) {
- if (typeof exports === "object" && exports) {
+(function defineMustache (global, factory) {
+ if (typeof exports === 'object' && exports && typeof exports.nodeName !== 'string') {
factory(exports); // CommonJS
+ } else if (typeof define === 'function' && define.amd) {
+ define(['exports'], factory); // AMD
} else {
- var mustache = {};
- factory(mustache);
- if (typeof define === "function" && define.amd) {
- define(mustache); // AMD
- } else {
- root.Mustache = mustache; // <script>
- }
+ global.Mustache = {};
+ factory(Mustache); // script, wsh, asp
+ }
+}(this, function mustacheFactory (mustache) {
+
+ var objectToString = Object.prototype.toString;
+ var isArray = Array.isArray || function isArrayPolyfill (object) {
+ return objectToString.call(object) === '[object Array]';
+ };
+
+ function isFunction (object) {
+ return typeof object === 'function';
}
-}(this, function (mustache) {
+
+ /**
+ * More correct typeof string handling array
+ * which normally returns typeof 'object'
+ */
+ function typeStr (obj) {
+ return isArray(obj) ? 'array' : typeof obj;
+ }
- var whiteRe = /\s*/;
- var spaceRe = /\s+/;
- var nonSpaceRe = /\S/;
- var eqRe = /\s*=/;
- var curlyRe = /\s*\}/;
- var tagRe = /#|\^|\/|>|\{|&|=|!/;
+ function escapeRegExp (string) {
+ return string.replace(/[\-\[\]{}()*+?.,\\\^$|#\s]/g, '\\$&');
+ }
+
+ /**
+ * Null safe way of checking whether or not an object,
+ * including its prototype, has a given property
+ */
+ function hasProperty (obj, propName) {
+ return obj != null && typeof obj === 'object' && (propName in obj);
+ }
// Workaround for https://issues.apache.org/jira/browse/COUCHDB-577
// See https://github.com/janl/mustache.js/issues/189
- var RegExp_test = RegExp.prototype.test;
- function testRegExp(re, string) {
- return RegExp_test.call(re, string);
+ var regExpTest = RegExp.prototype.test;
+ function testRegExp (re, string) {
+ return regExpTest.call(re, string);
}
- function isWhitespace(string) {
+ var nonSpaceRe = /\S/;
+ function isWhitespace (string) {
return !testRegExp(nonSpaceRe, string);
}
- var Object_toString = Object.prototype.toString;
- var isArray = Array.isArray || function (obj) {
- return Object_toString.call(obj) === '[object Array]';
+ var entityMap = {
+ '&': '&',
+ '<': '<',
+ '>': '>',
+ '"': '"',
+ "'": ''',
+ '/': '/'
};
- function escapeRegExp(string) {
- return string.replace(/[\-\[\]{}()*+?.,\\\^$|#\s]/g, "\\$&");
- }
-
- var entityMap = {
- "&": "&",
- "<": "<",
- ">": ">",
- '"': '"',
- "'": ''',
- "/": '/'
- };
-
- function escapeHtml(string) {
- return String(string).replace(/[&<>"'\/]/g, function (s) {
+ function escapeHtml (string) {
+ return String(string).replace(/[&<>"'\/]/g, function fromEntityMap (s) {
return entityMap[s];
});
}
- function Scanner(string) {
- this.string = string;
- this.tail = string;
- this.pos = 0;
- }
-
- /**
- * Returns `true` if the tail is empty (end of string).
- */
- Scanner.prototype.eos = function () {
- return this.tail === "";
- };
-
- /**
- * Tries to match the given regular expression at the current position.
- * Returns the matched text if it can match, the empty string otherwise.
- */
- Scanner.prototype.scan = function (re) {
- var match = this.tail.match(re);
-
- if (match && match.index === 0) {
- this.tail = this.tail.substring(match[0].length);
- this.pos += match[0].length;
- return match[0];
- }
-
- return "";
- };
+ var whiteRe = /\s*/;
+ var spaceRe = /\s+/;
+ var equalsRe = /\s*=/;
+ var curlyRe = /\s*\}/;
+ var tagRe = /#|\^|\/|>|\{|&|=|!/;
/**
- * Skips all text until the given regular expression can be matched. Returns
- * the skipped string, which is the entire tail if no match can be made.
- */
- Scanner.prototype.scanUntil = function (re) {
- var match, pos = this.tail.search(re);
-
- switch (pos) {
- case -1:
- match = this.tail;
- this.pos += this.tail.length;
- this.tail = "";
- break;
- case 0:
- match = "";
- break;
- default:
- match = this.tail.substring(0, pos);
- this.tail = this.tail.substring(pos);
- this.pos += pos;
- }
-
- return match;
- };
-
- function Context(view, parent) {
- this.view = view || {};
- this.parent = parent;
- this._cache = {};
- }
-
- Context.make = function (view) {
- return (view instanceof Context) ? view : new Context(view);
- };
-
- Context.prototype.push = function (view) {
- return new Context(view, this);
- };
-
- Context.prototype.lookup = function (name) {
- var value = this._cache[name];
-
- if (!value) {
- if (name == '.') {
- value = this.view;
- } else {
- var context = this;
-
- while (context) {
- if (name.indexOf('.') > 0) {
- value = context.view;
- var names = name.split('.'), i = 0;
- while (value && i < names.length) {
- value = value[names[i++]];
- }
- } else {
- value = context.view[name];
- }
-
- if (value != null) break;
-
- context = context.parent;
- }
- }
-
- this._cache[name] = value;
- }
-
- if (typeof value === 'function') value = value.call(this.view);
-
- return value;
- };
-
- function Writer() {
- this.clearCache();
- }
-
- Writer.prototype.clearCache = function () {
- this._cache = {};
- this._partialCache = {};
- };
-
- Writer.prototype.compile = function (template, tags) {
- var fn = this._cache[template];
-
- if (!fn) {
- var tokens = mustache.parse(template, tags);
- fn = this._cache[template] = this.compileTokens(tokens, template);
- }
-
- return fn;
- };
-
- Writer.prototype.compilePartial = function (name, template, tags) {
- var fn = this.compile(template, tags);
- this._partialCache[name] = fn;
- return fn;
- };
-
- Writer.prototype.getPartial = function (name) {
- if (!(name in this._partialCache) && this._loadPartial) {
- this.compilePartial(name, this._loadPartial(name));
- }
-
- return this._partialCache[name];
- };
-
- Writer.prototype.compileTokens = function (tokens, template) {
- var self = this;
- return function (view, partials) {
- if (partials) {
- if (typeof partials === 'function') {
- self._loadPartial = partials;
- } else {
- for (var name in partials) {
- self.compilePartial(name, partials[name]);
- }
- }
- }
-
- return renderTokens(tokens, self, Context.make(view), template);
- };
- };
-
- Writer.prototype.render = function (template, view, partials) {
- return this.compile(template)(view, partials);
- };
-
- /**
- * Low-level function that renders the given `tokens` using the given `writer`
- * and `context`. The `template` string is only needed for templates that use
- * higher-order sections to extract the portion of the original template that
- * was contained in that section.
+ * Breaks up the given `template` string into a tree of tokens. If the `tags`
+ * argument is given here it must be an array with two string values: the
+ * opening and closing tags used in the template (e.g. [ "<%", "%>" ]). Of
+ * course, the default is to use mustaches (i.e. mustache.tags).
+ *
+ * A token is an array with at least 4 elements. The first element is the
+ * mustache symbol that was used inside the tag, e.g. "#" or "&". If the tag
+ * did not contain a symbol (i.e. {{myValue}}) this element is "name". For
+ * all text that appears outside a symbol this element is "text".
+ *
+ * The second element of a token is its "value". For mustache tags this is
+ * whatever else was inside the tag besides the opening symbol. For text tokens
+ * this is the text itself.
+ *
+ * The third and fourth elements of the token are the start and end indices,
+ * respectively, of the token in the original template.
+ *
+ * Tokens that are the root node of a subtree contain two more elements: 1) an
+ * array of tokens in the subtree and 2) the index in the original template at
+ * which the closing tag for that section begins.
*/
- function renderTokens(tokens, writer, context, template) {
- var buffer = '';
-
- var token, tokenValue, value;
- for (var i = 0, len = tokens.length; i < len; ++i) {
- token = tokens[i];
- tokenValue = token[1];
-
- switch (token[0]) {
- case '#':
- value = context.lookup(tokenValue);
-
- if (typeof value === 'object') {
- if (isArray(value)) {
- for (var j = 0, jlen = value.length; j < jlen; ++j) {
- buffer += renderTokens(token[4], writer, context.push(value[j]), template);
- }
- } else if (value) {
- buffer += renderTokens(token[4], writer, context.push(value), template);
- }
- } else if (typeof value === 'function') {
- var text = template == null ? null : template.slice(token[3], token[5]);
- value = value.call(context.view, text, function (template) {
- return writer.render(template, context);
- });
- if (value != null) buffer += value;
- } else if (value) {
- buffer += renderTokens(token[4], writer, context, template);
- }
-
- break;
- case '^':
- value = context.lookup(tokenValue);
-
- // Use JavaScript's definition of falsy. Include empty arrays.
- // See https://github.com/janl/mustache.js/issues/186
- if (!value || (isArray(value) && value.length === 0)) {
- buffer += renderTokens(token[4], writer, context, template);
- }
-
- break;
- case '>':
- value = writer.getPartial(tokenValue);
- if (typeof value === 'function') buffer += value(context);
- break;
- case '&':
- value = context.lookup(tokenValue);
- if (value != null) buffer += value;
- break;
- case 'name':
- value = context.lookup(tokenValue);
- if (value != null) buffer += mustache.escape(value);
- break;
- case 'text':
- buffer += tokenValue;
- break;
- }
- }
-
- return buffer;
- }
-
- /**
- * Forms the given array of `tokens` into a nested tree structure where
- * tokens that represent a section have two additional items: 1) an array of
- * all tokens that appear in that section and 2) the index in the original
- * template that represents the end of that section.
- */
- function nestTokens(tokens) {
- var tree = [];
- var collector = tree;
- var sections = [];
-
- var token;
- for (var i = 0, len = tokens.length; i < len; ++i) {
- token = tokens[i];
- switch (token[0]) {
- case '#':
- case '^':
- sections.push(token);
- collector.push(token);
- collector = token[4] = [];
- break;
- case '/':
- var section = sections.pop();
- section[5] = token[2];
- collector = sections.length > 0 ? sections[sections.length - 1][4] : tree;
- break;
- default:
- collector.push(token);
- }
- }
-
- return tree;
- }
-
- /**
- * Combines the values of consecutive text tokens in the given `tokens` array
- * to a single token.
- */
- function squashTokens(tokens) {
- var squashedTokens = [];
-
- var token, lastToken;
- for (var i = 0, len = tokens.length; i < len; ++i) {
- token = tokens[i];
- if (token) {
- if (token[0] === 'text' && lastToken && lastToken[0] === 'text') {
- lastToken[1] += token[1];
- lastToken[3] = token[3];
- } else {
- lastToken = token;
- squashedTokens.push(token);
- }
- }
- }
-
- return squashedTokens;
- }
-
- function escapeTags(tags) {
- return [
- new RegExp(escapeRegExp(tags[0]) + "\\s*"),
- new RegExp("\\s*" + escapeRegExp(tags[1]))
- ];
- }
-
- /**
- * Breaks up the given `template` string into a tree of token objects. If
- * `tags` is given here it must be an array with two string values: the
- * opening and closing tags used in the template (e.g. ["<%", "%>"]). Of
- * course, the default is to use mustaches (i.e. Mustache.tags).
- */
- function parseTemplate(template, tags) {
- template = template || '';
- tags = tags || mustache.tags;
-
- if (typeof tags === 'string') tags = tags.split(spaceRe);
- if (tags.length !== 2) throw new Error('Invalid tags: ' + tags.join(', '));
-
- var tagRes = escapeTags(tags);
- var scanner = new Scanner(template);
+ function parseTemplate (template, tags) {
+ if (!template)
+ return [];
var sections = []; // Stack to hold section tokens
var tokens = []; // Buffer to hold the tokens
@@ -375,11 +112,10 @@
// Strips all whitespace tokens array for the current line
// if there was a {{#tag}} on it and otherwise only space.
- function stripSpace() {
+ function stripSpace () {
if (hasTag && !nonSpace) {
- while (spaces.length) {
+ while (spaces.length)
delete tokens[spaces.pop()];
- }
} else {
spaces = [];
}
@@ -388,14 +124,32 @@
nonSpace = false;
}
- var start, type, value, chr, token;
+ var openingTagRe, closingTagRe, closingCurlyRe;
+ function compileTags (tagsToCompile) {
+ if (typeof tagsToCompile === 'string')
+ tagsToCompile = tagsToCompile.split(spaceRe, 2);
+
+ if (!isArray(tagsToCompile) || tagsToCompile.length !== 2)
+ throw new Error('Invalid tags: ' + tagsToCompile);
+
+ openingTagRe = new RegExp(escapeRegExp(tagsToCompile[0]) + '\\s*');
+ closingTagRe = new RegExp('\\s*' + escapeRegExp(tagsToCompile[1]));
+ closingCurlyRe = new RegExp('\\s*' + escapeRegExp('}' + tagsToCompile[1]));
+ }
+
+ compileTags(tags || mustache.tags);
+
+ var scanner = new Scanner(template);
+
+ var start, type, value, chr, token, openSection;
while (!scanner.eos()) {
start = scanner.pos;
// Match any text between tags.
- value = scanner.scanUntil(tagRes[0]);
+ value = scanner.scanUntil(openingTagRe);
+
if (value) {
- for (var i = 0, len = value.length; i < len; ++i) {
+ for (var i = 0, valueLength = value.length; i < valueLength; ++i) {
chr = value.charAt(i);
if (isWhitespace(chr)) {
@@ -404,16 +158,19 @@
nonSpace = true;
}
- tokens.push(['text', chr, start, start + 1]);
+ tokens.push([ 'text', chr, start, start + 1 ]);
start += 1;
// Check for whitespace on the current line.
- if (chr == '\n') stripSpace();
+ if (chr === '\n')
+ stripSpace();
}
}
// Match the opening tag.
- if (!scanner.scan(tagRes[0])) break;
+ if (!scanner.scan(openingTagRe))
+ break;
+
hasTag = true;
// Get the tag type.
@@ -422,115 +179,449 @@
// Get the tag value.
if (type === '=') {
- value = scanner.scanUntil(eqRe);
- scanner.scan(eqRe);
- scanner.scanUntil(tagRes[1]);
+ value = scanner.scanUntil(equalsRe);
+ scanner.scan(equalsRe);
+ scanner.scanUntil(closingTagRe);
} else if (type === '{') {
- value = scanner.scanUntil(new RegExp('\\s*' + escapeRegExp('}' + tags[1])));
+ value = scanner.scanUntil(closingCurlyRe);
scanner.scan(curlyRe);
- scanner.scanUntil(tagRes[1]);
+ scanner.scanUntil(closingTagRe);
type = '&';
} else {
- value = scanner.scanUntil(tagRes[1]);
+ value = scanner.scanUntil(closingTagRe);
}
// Match the closing tag.
- if (!scanner.scan(tagRes[1])) throw new Error('Unclosed tag at ' + scanner.pos);
+ if (!scanner.scan(closingTagRe))
+ throw new Error('Unclosed tag at ' + scanner.pos);
- token = [type, value, start, scanner.pos];
+ token = [ type, value, start, scanner.pos ];
tokens.push(token);
if (type === '#' || type === '^') {
sections.push(token);
} else if (type === '/') {
// Check section nesting.
- if (sections.length === 0) throw new Error('Unopened section "' + value + '" at ' + start);
- var openSection = sections.pop();
- if (openSection[1] !== value) throw new Error('Unclosed section "' + openSection[1] + '" at ' + start);
+ openSection = sections.pop();
+
+ if (!openSection)
+ throw new Error('Unopened section "' + value + '" at ' + start);
+
+ if (openSection[1] !== value)
+ throw new Error('Unclosed section "' + openSection[1] + '" at ' + start);
} else if (type === 'name' || type === '{' || type === '&') {
nonSpace = true;
} else if (type === '=') {
// Set the tags for the next time around.
- tags = value.split(spaceRe);
- if (tags.length !== 2) throw new Error('Invalid tags at ' + start + ': ' + tags.join(', '));
- tagRes = escapeTags(tags);
+ compileTags(value);
}
}
// Make sure there are no open sections when we're done.
- var openSection = sections.pop();
- if (openSection) throw new Error('Unclosed section "' + openSection[1] + '" at ' + scanner.pos);
+ openSection = sections.pop();
+
+ if (openSection)
+ throw new Error('Unclosed section "' + openSection[1] + '" at ' + scanner.pos);
+
+ return nestTokens(squashTokens(tokens));
+ }
+
+ /**
+ * Combines the values of consecutive text tokens in the given `tokens` array
+ * to a single token.
+ */
+ function squashTokens (tokens) {
+ var squashedTokens = [];
+
+ var token, lastToken;
+ for (var i = 0, numTokens = tokens.length; i < numTokens; ++i) {
+ token = tokens[i];
+
+ if (token) {
+ if (token[0] === 'text' && lastToken && lastToken[0] === 'text') {
+ lastToken[1] += token[1];
+ lastToken[3] = token[3];
+ } else {
+ squashedTokens.push(token);
+ lastToken = token;
+ }
+ }
+ }
+
+ return squashedTokens;
+ }
+
+ /**
+ * Forms the given array of `tokens` into a nested tree structure where
+ * tokens that represent a section have two additional items: 1) an array of
+ * all tokens that appear in that section and 2) the index in the original
+ * template that represents the end of that section.
+ */
+ function nestTokens (tokens) {
+ var nestedTokens = [];
+ var collector = nestedTokens;
+ var sections = [];
+
+ var token, section;
+ for (var i = 0, numTokens = tokens.length; i < numTokens; ++i) {
+ token = tokens[i];
+
+ switch (token[0]) {
+ case '#':
+ case '^':
+ collector.push(token);
+ sections.push(token);
+ collector = token[4] = [];
+ break;
+ case '/':
+ section = sections.pop();
+ section[5] = token[2];
+ collector = sections.length > 0 ? sections[sections.length - 1][4] : nestedTokens;
+ break;
+ default:
+ collector.push(token);
+ }
+ }
+
+ return nestedTokens;
+ }
- tokens = squashTokens(tokens);
+ /**
+ * A simple string scanner that is used by the template parser to find
+ * tokens in template strings.
+ */
+ function Scanner (string) {
+ this.string = string;
+ this.tail = string;
+ this.pos = 0;
+ }
+
+ /**
+ * Returns `true` if the tail is empty (end of string).
+ */
+ Scanner.prototype.eos = function eos () {
+ return this.tail === '';
+ };
+
+ /**
+ * Tries to match the given regular expression at the current position.
+ * Returns the matched text if it can match, the empty string otherwise.
+ */
+ Scanner.prototype.scan = function scan (re) {
+ var match = this.tail.match(re);
+
+ if (!match || match.index !== 0)
+ return '';
+
+ var string = match[0];
+
+ this.tail = this.tail.substring(string.length);
+ this.pos += string.length;
- return nestTokens(tokens);
+ return string;
+ };
+
+ /**
+ * Skips all text until the given regular expression can be matched. Returns
+ * the skipped string, which is the entire tail if no match can be made.
+ */
+ Scanner.prototype.scanUntil = function scanUntil (re) {
+ var index = this.tail.search(re), match;
+
+ switch (index) {
+ case -1:
+ match = this.tail;
+ this.tail = '';
+ break;
+ case 0:
+ match = '';
+ break;
+ default:
+ match = this.tail.substring(0, index);
+ this.tail = this.tail.substring(index);
+ }
+
+ this.pos += match.length;
+
+ return match;
+ };
+
+ /**
+ * Represents a rendering context by wrapping a view object and
+ * maintaining a reference to the parent context.
+ */
+ function Context (view, parentContext) {
+ this.view = view;
+ this.cache = { '.': this.view };
+ this.parent = parentContext;
}
- mustache.name = "mustache.js";
- mustache.version = "0.7.2";
- mustache.tags = ["{{", "}}"];
+ /**
+ * Creates a new context using the given view with this context
+ * as the parent.
+ */
+ Context.prototype.push = function push (view) {
+ return new Context(view, this);
+ };
+
+ /**
+ * Returns the value of the given name in this context, traversing
+ * up the context hierarchy if the value is absent in this context's view.
+ */
+ Context.prototype.lookup = function lookup (name) {
+ var cache = this.cache;
+
+ var value;
+ if (cache.hasOwnProperty(name)) {
+ value = cache[name];
+ } else {
+ var context = this, names, index, lookupHit = false;
+
+ while (context) {
+ if (name.indexOf('.') > 0) {
+ value = context.view;
+ names = name.split('.');
+ index = 0;
+
+ /**
+ * Using the dot notion path in `name`, we descend through the
+ * nested objects.
+ *
+ * To be certain that the lookup has been successful, we have to
+ * check if the last object in the path actually has the property
+ * we are looking for. We store the result in `lookupHit`.
+ *
+ * This is specially necessary for when the value has been set to
+ * `undefined` and we want to avoid looking up parent contexts.
+ **/
+ while (value != null && index < names.length) {
+ if (index === names.length - 1)
+ lookupHit = hasProperty(value, names[index]);
- mustache.Scanner = Scanner;
- mustache.Context = Context;
- mustache.Writer = Writer;
+ value = value[names[index++]];
+ }
+ } else {
+ value = context.view[name];
+ lookupHit = hasProperty(context.view, name);
+ }
+
+ if (lookupHit)
+ break;
+
+ context = context.parent;
+ }
+
+ cache[name] = value;
+ }
+
+ if (isFunction(value))
+ value = value.call(this.view);
+
+ return value;
+ };
+
+ /**
+ * A Writer knows how to take a stream of tokens and render them to a
+ * string, given a context. It also maintains a cache of templates to
+ * avoid the need to parse the same template twice.
+ */
+ function Writer () {
+ this.cache = {};
+ }
+
+ /**
+ * Clears all cached templates in this writer.
+ */
+ Writer.prototype.clearCache = function clearCache () {
+ this.cache = {};
+ };
+
+ /**
+ * Parses and caches the given `template` and returns the array of tokens
+ * that is generated from the parse.
+ */
+ Writer.prototype.parse = function parse (template, tags) {
+ var cache = this.cache;
+ var tokens = cache[template];
+
+ if (tokens == null)
+ tokens = cache[template] = parseTemplate(template, tags);
+
+ return tokens;
+ };
- mustache.parse = parseTemplate;
+ /**
+ * High-level method that is used to render the given `template` with
+ * the given `view`.
+ *
+ * The optional `partials` argument may be an object that contains the
+ * names and templates of partials that are used in the template. It may
+ * also be a function that is used to load partial templates on the fly
+ * that takes a single argument: the name of the partial.
+ */
+ Writer.prototype.render = function render (template, view, partials) {
+ var tokens = this.parse(template);
+ var context = (view instanceof Context) ? view : new Context(view);
+ return this.renderTokens(tokens, context, partials, template);
+ };
+
+ /**
+ * Low-level method that renders the given array of `tokens` using
+ * the given `context` and `partials`.
+ *
+ * Note: The `originalTemplate` is only ever used to extract the portion
+ * of the original template that was contained in a higher-order section.
+ * If the template doesn't use higher-order sections, this argument may
+ * be omitted.
+ */
+ Writer.prototype.renderTokens = function renderTokens (tokens, context, partials, originalTemplate) {
+ var buffer = '';
+
+ var token, symbol, value;
+ for (var i = 0, numTokens = tokens.length; i < numTokens; ++i) {
+ value = undefined;
+ token = tokens[i];
+ symbol = token[0];
+
+ if (symbol === '#') value = this.renderSection(token, context, partials, originalTemplate);
+ else if (symbol === '^') value = this.renderInverted(token, context, partials, originalTemplate);
+ else if (symbol === '>') value = this.renderPartial(token, context, partials, originalTemplate);
+ else if (symbol === '&') value = this.unescapedValue(token, context);
+ else if (symbol === 'name') value = this.escapedValue(token, context);
+ else if (symbol === 'text') value = this.rawValue(token);
+
+ if (value !== undefined)
+ buffer += value;
+ }
+
+ return buffer;
+ };
+
+ Writer.prototype.renderSection = function renderSection (token, context, partials, originalTemplate) {
+ var self = this;
+ var buffer = '';
+ var value = context.lookup(token[1]);
+
+ // This function is used to render an arbitrary template
+ // in the current context by higher-order sections.
+ function subRender (template) {
+ return self.render(template, context, partials);
+ }
+
+ if (!value) return;
- // Export the escaping function so that the user may override it.
- // See https://github.com/janl/mustache.js/issues/244
- mustache.escape = escapeHtml;
+ if (isArray(value)) {
+ for (var j = 0, valueLength = value.length; j < valueLength; ++j) {
+ buffer += this.renderTokens(token[4], context.push(value[j]), partials, originalTemplate);
+ }
+ } else if (typeof value === 'object' || typeof value === 'string' || typeof value === 'number') {
+ buffer += this.renderTokens(token[4], context.push(value), partials, originalTemplate);
+ } else if (isFunction(value)) {
+ if (typeof originalTemplate !== 'string')
+ throw new Error('Cannot use higher-order sections without the original template');
+
+ // Extract the portion of the original template that the section contains.
+ value = value.call(context.view, originalTemplate.slice(token[3], token[5]), subRender);
+
+ if (value != null)
+ buffer += value;
+ } else {
+ buffer += this.renderTokens(token[4], context, partials, originalTemplate);
+ }
+ return buffer;
+ };
+
+ Writer.prototype.renderInverted = function renderInverted (token, context, partials, originalTemplate) {
+ var value = context.lookup(token[1]);
+
+ // Use JavaScript's definition of falsy. Include empty arrays.
+ // See https://github.com/janl/mustache.js/issues/186
+ if (!value || (isArray(value) && value.length === 0))
+ return this.renderTokens(token[4], context, partials, originalTemplate);
+ };
- // All Mustache.* functions use this writer.
+ Writer.prototype.renderPartial = function renderPartial (token, context, partials) {
+ if (!partials) return;
+
+ var value = isFunction(partials) ? partials(token[1]) : partials[token[1]];
+ if (value != null)
+ return this.renderTokens(this.parse(value), context, partials, value);
+ };
+
+ Writer.prototype.unescapedValue = function unescapedValue (token, context) {
+ var value = context.lookup(token[1]);
+ if (value != null)
+ return value;
+ };
+
+ Writer.prototype.escapedValue = function escapedValue (token, context) {
+ var value = context.lookup(token[1]);
+ if (value != null)
+ return mustache.escape(value);
+ };
+
+ Writer.prototype.rawValue = function rawValue (token) {
+ return token[1];
+ };
+
+ mustache.name = 'mustache.js';
+ mustache.version = '2.1.3';
+ mustache.tags = [ '{{', '}}' ];
+
+ // All high-level mustache.* functions use this writer.
var defaultWriter = new Writer();
/**
- * Clears all cached templates and partials in the default writer.
+ * Clears all cached templates in the default writer.
*/
- mustache.clearCache = function () {
+ mustache.clearCache = function clearCache () {
return defaultWriter.clearCache();
};
/**
- * Compiles the given `template` to a reusable function using the default
- * writer.
- */
- mustache.compile = function (template, tags) {
- return defaultWriter.compile(template, tags);
- };
-
- /**
- * Compiles the partial with the given `name` and `template` to a reusable
- * function using the default writer.
+ * Parses and caches the given template in the default writer and returns the
+ * array of tokens it contains. Doing this ahead of time avoids the need to
+ * parse templates on the fly as they are rendered.
*/
- mustache.compilePartial = function (name, template, tags) {
- return defaultWriter.compilePartial(name, template, tags);
- };
-
- /**
- * Compiles the given array of tokens (the output of a parse) to a reusable
- * function using the default writer.
- */
- mustache.compileTokens = function (tokens, template) {
- return defaultWriter.compileTokens(tokens, template);
+ mustache.parse = function parse (template, tags) {
+ return defaultWriter.parse(template, tags);
};
/**
* Renders the `template` with the given `view` and `partials` using the
* default writer.
*/
- mustache.render = function (template, view, partials) {
+ mustache.render = function render (template, view, partials) {
+ if (typeof template !== 'string') {
+ throw new TypeError('Invalid template! Template should be a "string" ' +
+ 'but "' + typeStr(template) + '" was given as the first ' +
+ 'argument for mustache#render(template, view, partials)');
+ }
+
return defaultWriter.render(template, view, partials);
};
- // This is here for backwards compatibility with 0.4.x.
- mustache.to_html = function (template, view, partials, send) {
+ // This is here for backwards compatibility with 0.4.x.,
+ /*eslint-disable */ // eslint wants camel cased function name
+ mustache.to_html = function to_html (template, view, partials, send) {
+ /*eslint-enable*/
+
var result = mustache.render(template, view, partials);
- if (typeof send === "function") {
+ if (isFunction(send)) {
send(result);
} else {
return result;
}
};
+ // Export the escaping function so that the user may override it.
+ // See https://github.com/janl/mustache.js/issues/244
+ mustache.escape = escapeHtml;
+
+ // Export these mainly for testing, but also for advanced usage.
+ mustache.Scanner = Scanner;
+ mustache.Context = Context;
+ mustache.Writer = Writer;
+
}));
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/src/ldt/ldt/static/ldt/js/paper.js Fri Oct 02 10:24:05 2015 +0200
@@ -0,0 +1,13224 @@
+/*!
+ * Paper.js v0.9.24 - The Swiss Army Knife of Vector Graphics Scripting.
+ * http://paperjs.org/
+ *
+ * Copyright (c) 2011 - 2014, Juerg Lehni & Jonathan Puckey
+ * http://scratchdisk.com/ & http://jonathanpuckey.com/
+ *
+ * Distributed under the MIT license. See LICENSE file for details.
+ *
+ * All rights reserved.
+ *
+ * Date: Fri Aug 21 16:39:41 2015 +0200
+ *
+ ***
+ *
+ * Straps.js - Class inheritance library with support for bean-style accessors
+ *
+ * Copyright (c) 2006 - 2013 Juerg Lehni
+ * http://scratchdisk.com/
+ *
+ * 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|enumerable|beans|preserve)$/,
+
+ 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, beans, preserve) {
+ var beansNames = {};
+
+ function field(name, val) {
+ 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.base
+ ? (val && val.get ? name in dest : dest[name])
+ : null,
+ bean;
+ if (!preserve || !prev) {
+ if (isFunc && prev)
+ val.base = prev;
+ if (isFunc && beans !== false
+ && (bean = name.match(/^([gs]et|is)(([A-Z])(.*))$/)))
+ beansNames[bean[3].toLowerCase() + bean[4]] = bean[2];
+ if (!res || isFunc || !res.get || typeof res.get !== 'function'
+ || !Base.isPlainObject(res))
+ res = { value: res, writable: true };
+ if ((describe(dest, name)
+ || { configurable: true }).configurable) {
+ res.configurable = true;
+ res.enumerable = enumerable;
+ }
+ define(dest, name, res);
+ }
+ }
+ if (src) {
+ for (var name in src) {
+ if (src.hasOwnProperty(name) && !hidden.test(name))
+ field(name);
+ }
+ for (var name in beansNames) {
+ var part = beansNames[name],
+ set = dest['set' + part],
+ get = dest['get' + part] || set && dest['is' + part];
+ if (get && (beans === true || get.length === 0))
+ field(name, { get: get, set: set });
+ }
+ }
+ 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 set(obj, props, exclude) {
+ for (var key in props)
+ if (props.hasOwnProperty(key) && !(exclude && exclude[key]))
+ obj[key] = props[key];
+ return obj;
+ }
+
+ return inject(function Base() {
+ for (var i = 0, l = arguments.length; i < l; i++)
+ set(this, arguments[i]);
+ }, {
+ inject: function(src) {
+ if (src) {
+ var statics = src.statics === true ? src : src.statics,
+ beans = src.beans,
+ preserve = src.preserve;
+ if (statics !== src)
+ inject(this.prototype, src, src.enumerable, beans, preserve);
+ inject(this, statics, true, beans, preserve);
+ }
+ for (var i = 1, l = arguments.length; i < l; i++)
+ this.inject(arguments[i]);
+ return this;
+ },
+
+ extend: function() {
+ var base = this,
+ ctor,
+ proto;
+ for (var i = 0, l = arguments.length; i < l; i++)
+ if (ctor = arguments[i].initialize)
+ break;
+ ctor = ctor || function() {
+ base.apply(this, arguments);
+ };
+ proto = ctor.prototype = create(this.prototype);
+ define(proto, 'constructor',
+ { value: ctor, writable: true, configurable: true });
+ inject(ctor, this, true);
+ if (arguments.length)
+ this.inject.apply(ctor, arguments);
+ ctor.base = base;
+ return ctor;
+ }
+ }, true).inject({
+ inject: function() {
+ for (var i = 0, l = arguments.length; i < l; i++) {
+ var src = arguments[i];
+ if (src)
+ inject(this, src, src.enumerable, src.beans, src.preserve);
+ }
+ return this;
+ },
+
+ extend: function() {
+ var res = create(this);
+ return res.inject.apply(res, arguments);
+ },
+
+ each: function(iter, bind) {
+ return each(this, iter, bind);
+ },
+
+ set: function(props) {
+ return set(this, props);
+ },
+
+ clone: function() {
+ return new this.constructor(this);
+ },
+
+ statics: {
+ each: each,
+ create: create,
+ define: define,
+ describe: describe,
+ set: set,
+
+ clone: function(obj) {
+ return set(new obj.constructor(), obj);
+ },
+
+ isPlainObject: function(obj) {
+ var ctor = obj != null && obj.constructor;
+ return ctor && (ctor === Object || ctor === Base
+ || ctor.name === 'Object');
+ },
+
+ pick: function(a, b) {
+ return a !== undefined ? a : b;
+ }
+ }
+ });
+};
+
+if (typeof module !== 'undefined')
+ module.exports = Base;
+
+Base.inject({
+ 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(', ') + ' }';
+ },
+
+ getClassName: function() {
+ return this._class || '';
+ },
+
+ exportJSON: function(options) {
+ return Base.exportJSON(this, options);
+ },
+
+ toJSON: function() {
+ return Base.serialize(this);
+ },
+
+ _set: function(props, exclude, dontCheck) {
+ if (props && (dontCheck || Base.isPlainObject(props))) {
+ var keys = Object.keys(props._filtering || props);
+ for (var i = 0, l = keys.length; i < l; i++) {
+ var key = keys[i];
+ if (!(exclude && exclude[key])) {
+ var value = props[key];
+ if (value !== undefined)
+ this[key] = value;
+ }
+ }
+ return true;
+ }
+ },
+
+ statics: {
+
+ exports: {
+ enumerable: true
+ },
+
+ 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) {
+ if (obj1 === obj2)
+ return true;
+ if (obj1 && obj1.equals)
+ return obj1.equals(obj2);
+ if (obj2 && obj2.equals)
+ return obj2.equals(obj1);
+ if (obj1 && obj2
+ && typeof obj1 === 'object' && typeof obj2 === 'object') {
+ if (Array.isArray(obj1) && Array.isArray(obj2)) {
+ var length = obj1.length;
+ if (length !== obj2.length)
+ return false;
+ while (length--) {
+ if (!Base.equals(obj1[length], obj2[length]))
+ return false;
+ }
+ } else {
+ var keys = Object.keys(obj1),
+ length = keys.length;
+ if (length !== Object.keys(obj2).length)
+ return false;
+ while (length--) {
+ var key = keys[length];
+ if (!(obj2.hasOwnProperty(key)
+ && Base.equals(obj1[key], obj2[key])))
+ return false;
+ }
+ }
+ return true;
+ }
+ return false;
+ },
+
+ read: function(list, start, options, length) {
+ if (this === Base) {
+ var value = this.peek(list, start);
+ list.__index++;
+ 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;
+ 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;
+ obj.__read = undefined;
+ }
+ return obj;
+ },
+
+ peek: function(list, start) {
+ return list[list.__index = start || list.__index || 0];
+ },
+
+ remain: function(list) {
+ return list.length - (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, options)
+ : this.read(list, i, options, 1));
+ }
+ return res;
+ },
+
+ readNamed: function(list, name, start, options, length) {
+ 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, options, length);
+ },
+
+ 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, asString) {
+ return this.isPlainObject(obj) || Array.isArray(obj)
+ || asString && typeof obj === 'string';
+ },
+
+ 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 = {};
+ var keys = Object.keys(obj);
+ for (var i = 0, l = keys.length; i < l; i++) {
+ var key = keys[i];
+ res[key] = Base.serialize(obj[key], 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, _isDictionary) {
+ var res = json,
+ isRoot = !_data;
+ _data = _data || {};
+ if (Array.isArray(json)) {
+ var type = json[0],
+ isDictionary = type === 'dictionary';
+ if (json.length == 1 && /^#/.test(type))
+ return _data.dictionary[type];
+ type = Base.exports[type];
+ res = [];
+ if (_isDictionary)
+ _data.dictionary = res;
+ for (var i = type ? 1 : 0, l = json.length; i < l; i++)
+ res.push(Base.deserialize(json[i], create, _data,
+ isDictionary));
+ 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 = {};
+ if (_isDictionary)
+ _data.dictionary = res;
+ for (var key in json)
+ res[key] = Base.deserialize(json[key], create, _data);
+ }
+ return isRoot && json && json.length && json[0][0] === 'dictionary'
+ ? res[1]
+ : res;
+ },
+
+ exportJSON: function(obj, options) {
+ var json = Base.serialize(obj, options);
+ return options && options.asString === false
+ ? json
+ : JSON.stringify(json);
+ },
+
+ 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
+ && (isTarget || !(obj instanceof Layer))) {
+ 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++)
+ removed[i]._index = undefined;
+ 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 Emitter = {
+ on: function(type, func) {
+ if (typeof type !== 'string') {
+ Base.each(type, function(value, key) {
+ this.on(key, value);
+ }, this);
+ } else {
+ var types = this._eventTypes,
+ entry = types && types[type],
+ handlers = this._callbacks = this._callbacks || {};
+ handlers = handlers[type] = handlers[type] || [];
+ if (handlers.indexOf(func) === -1) {
+ handlers.push(func);
+ if (entry && entry.install && handlers.length == 1)
+ entry.install.call(this, type);
+ }
+ }
+ return this;
+ },
+
+ off: function(type, func) {
+ if (typeof type !== 'string') {
+ Base.each(type, function(value, key) {
+ this.off(key, value);
+ }, this);
+ return;
+ }
+ var types = this._eventTypes,
+ entry = types && types[type],
+ handlers = this._callbacks && this._callbacks[type],
+ index;
+ if (handlers) {
+ if (!func || (index = handlers.indexOf(func)) !== -1
+ && handlers.length === 1) {
+ if (entry && entry.uninstall)
+ entry.uninstall.call(this, type);
+ delete this._callbacks[type];
+ } else if (index !== -1) {
+ handlers.splice(index, 1);
+ }
+ }
+ return this;
+ },
+
+ once: function(type, func) {
+ return this.on(type, function() {
+ func.apply(this, arguments);
+ this.off(type, func);
+ });
+ },
+
+ emit: function(type, event) {
+ var handlers = this._callbacks && this._callbacks[type];
+ if (!handlers)
+ return false;
+ var args = [].slice.call(arguments, 1);
+ handlers = handlers.slice();
+ for (var i = 0, l = handlers.length; i < l; i++) {
+ if (handlers[i].apply(this, args) === false) {
+ if (event && event.stop)
+ event.stop();
+ break;
+ }
+ }
+ return true;
+ },
+
+ responds: function(type) {
+ return !!(this._callbacks && this._callbacks[type]);
+ },
+
+ attach: '#on',
+ detach: '#off',
+ fire: '#emit',
+
+ _installEvents: function(install) {
+ var handlers = this._callbacks,
+ key = install ? 'install' : 'uninstall';
+ for (var type in handlers) {
+ if (handlers[type].length > 0) {
+ var types = this._eventTypes,
+ entry = types && types[type],
+ func = entry && entry[key];
+ if (func)
+ func.call(this, type);
+ }
+ }
+ },
+
+ statics: {
+ inject: function inject(src) {
+ var 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) {
+ var prev = this[name];
+ if (prev)
+ this.off(type, prev);
+ if (func)
+ this.on(type, func);
+ this[name] = func;
+ };
+ });
+ src._eventTypes = types;
+ }
+ return inject.base.apply(this, arguments);
+ }
+ }
+};
+
+var PaperScope = Base.extend({
+ _class: 'PaperScope',
+
+ initialize: function PaperScope() {
+ paper = this;
+ this.settings = new Base({
+ applyMatrix: true,
+ handleSize: 4,
+ hitTolerance: 0
+ });
+ this.project = null;
+ this.projects = [];
+ this.tools = [];
+ this.palettes = [];
+ this._id = PaperScope._id++;
+ PaperScope._scopes[this._id] = this;
+ var proto = PaperScope.prototype;
+ if (!this.support) {
+ var ctx = CanvasProvider.getContext(1, 1);
+ proto.support = {
+ nativeDash: 'setLineDash' in ctx || 'mozDash' in ctx,
+ nativeBlendModes: BlendMode.nativeModes
+ };
+ CanvasProvider.release(ctx);
+ }
+
+ if (!this.browser) {
+ var agent = navigator.userAgent.toLowerCase(),
+ platform = (/(win)/.exec(agent)
+ || /(mac)/.exec(agent)
+ || /(linux)/.exec(agent)
+ || [])[0],
+ browser = proto.browser = { platform: platform };
+ if (platform)
+ browser[platform] = true;
+ agent.replace(
+ /(opera|chrome|safari|webkit|firefox|msie|trident|atom)\/?\s*([.\d]+)(?:.*version\/([.\d]+))?(?:.*rv\:([.\d]+))?/g,
+ function(all, n, v1, v2, rv) {
+ if (!browser.chrome) {
+ var v = n === 'opera' ? v2 : v1;
+ if (n === 'trident') {
+ v = rv;
+ n = 'msie';
+ }
+ browser.version = v;
+ browser.versionNumber = parseFloat(v);
+ browser.name = n;
+ browser[n] = true;
+ }
+ }
+ );
+ if (browser.chrome)
+ delete browser.webkit;
+ if (browser.atom)
+ delete browser.chrome;
+ }
+ },
+
+ version: '0.9.24',
+
+ getView: function() {
+ return this.project && this.project.getView();
+ },
+
+ getPaper: function() {
+ return this;
+ },
+
+ execute: function(code, url, options) {
+ paper.PaperScript.execute(code, this, url, options);
+ View.updateFocus();
+ },
+
+ 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 (!/^_/.test(key) && this[key])
+ scope[key] = this[key];
+ },
+
+ setup: function(element) {
+ paper = this;
+ this.project = new Project(element);
+ 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) {
+ return this._scopes[id] || null;
+ },
+
+ getAttribute: handleAttribute('get'),
+ hasAttribute: handleAttribute('has')
+ };
+ }
+});
+
+var PaperScopeItem = Base.extend(Emitter, {
+
+ 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.emit('deactivate');
+ this._scope[this._reference] = this;
+ this.emit('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;
+ },
+
+ pair: function(val1, val2, separator) {
+ return this.number(val1) + (separator || ',') + this.number(val2);
+ },
+
+ 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,
+ TOLERANCE = 1e-6,
+ EPSILON = 1e-12,
+ MACHINE_EPSILON = 1.12e-16;
+
+ return {
+ TOLERANCE: TOLERANCE,
+ EPSILON: EPSILON,
+ MACHINE_EPSILON: MACHINE_EPSILON,
+ KAPPA: 4 * (sqrt(2) - 1) / 3,
+
+ isZero: function(val) {
+ return abs(val) <= EPSILON;
+ },
+
+ integrate: function(f, a, b, n) {
+ var x = abscissas[n - 2],
+ w = weights[n - 2],
+ A = (b - a) * 0.5,
+ 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),
+ nx = x - dx;
+ if (abs(dx) < tolerance)
+ return nx;
+ if (fx > 0) {
+ b = x;
+ x = nx <= a ? (a + b) * 0.5 : nx;
+ } else {
+ a = x;
+ x = nx >= b ? (a + b) * 0.5 : nx;
+ }
+ }
+ return x;
+ },
+
+ solveQuadratic: function(a, b, c, roots, min, max) {
+ var count = 0,
+ x1, x2 = Infinity,
+ B = b,
+ D;
+ b /= 2;
+ D = b * b - a * c;
+ if (D !== 0 && abs(D) < MACHINE_EPSILON) {
+ var gmC = pow(abs(a * b * c), 1 / 3);
+ if (gmC < 1e-8) {
+ var mult = pow(10, abs(
+ Math.floor(Math.log(gmC) * Math.LOG10E)));
+ if (!isFinite(mult))
+ mult = 0;
+ a *= mult;
+ b *= mult;
+ c *= mult;
+ D = b * b - a * c;
+ }
+ }
+ if (abs(a) < EPSILON) {
+ if (abs(B) < EPSILON)
+ return abs(c) < EPSILON ? -1 : 0;
+ x1 = -c / B;
+ } else {
+ if (D >= -MACHINE_EPSILON) {
+ D = D < 0 ? 0 : D;
+ var R = sqrt(D);
+ if (b >= MACHINE_EPSILON && b <= MACHINE_EPSILON) {
+ x1 = abs(a) >= abs(c) ? R / a : -c / R;
+ x2 = -x1;
+ } else {
+ var q = -(b + (b < 0 ? -1 : 1) * R);
+ x1 = q / a;
+ x2 = c / q;
+ }
+ }
+ }
+ if (isFinite(x1) && (min == null || x1 >= min && x1 <= max))
+ roots[count++] = x1;
+ if (x2 !== x1
+ && isFinite(x2) && (min == null || x2 >= min && x2 <= max))
+ roots[count++] = x2;
+ return count;
+ },
+
+ solveCubic: function(a, b, c, d, roots, min, max) {
+ var count = 0,
+ x, b1, c2;
+ if (abs(a) < EPSILON) {
+ a = b;
+ b1 = c;
+ c2 = d;
+ x = Infinity;
+ } else if (abs(d) < EPSILON) {
+ b1 = b;
+ c2 = c;
+ x = 0;
+ } else {
+ var ec = 1 + MACHINE_EPSILON,
+ x0, q, qd, t, r, s, tmp;
+ x = -(b / a) / 3;
+ tmp = a * x,
+ b1 = tmp + b,
+ c2 = b1 * x + c,
+ qd = (tmp + b1) * x + c2,
+ q = c2 * x + d;
+ t = q /a;
+ r = pow(abs(t), 1/3);
+ s = t < 0 ? -1 : 1;
+ t = -qd / a;
+ r = t > 0 ? 1.3247179572 * Math.max(r, sqrt(t)) : r;
+ x0 = x - s * r;
+ if (x0 !== x) {
+ do {
+ x = x0;
+ tmp = a * x,
+ b1 = tmp + b,
+ c2 = b1 * x + c,
+ qd = (tmp + b1) * x + c2,
+ q = c2 * x + d;
+ x0 = qd === 0 ? x : x - q / qd / ec;
+ if (x0 === x) {
+ x = x0;
+ break;
+ }
+ } while (s * x0 > s * x);
+ if (abs(a) * x * x > abs(d / x)) {
+ c2 = -d / x;
+ b1 = (c2 - c) / x;
+ }
+ }
+ }
+ var count = Numerical.solveQuadratic(a, b1, c2, roots, min, max);
+ if (isFinite(x) && (count === 0 || x !== roots[count - 1])
+ && (min == null || x >= min && x <= max))
+ roots[count++] = x;
+ return count;
+ }
+ };
+};
+
+var UID = {
+ _id: 1,
+ _pools: {},
+
+ get: function(ctor) {
+ if (ctor) {
+ var name = ctor._class,
+ pool = this._pools[name];
+ if (!pool)
+ pool = this._pools[name] = { _id: 1 };
+ return pool._id++;
+ } else {
+ return this._id++;
+ }
+ }
+};
+
+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 this === point || 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)];
+ },
+
+ getLength: function() {
+ return Math.sqrt(this.x * this.x + this.y * this.y);
+ },
+
+ 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
+ );
+ }
+ },
+ getAngle: function() {
+ return this.getAngleInRadians.apply(this, arguments) * 180 / Math.PI;
+ },
+
+ setAngle: function(angle) {
+ this.setAngleInRadians.call(this, angle * Math.PI / 180);
+ },
+
+ getAngleInDegrees: '#getAngle',
+ setAngleInDegrees: '#setAngle',
+
+ getAngleInRadians: function() {
+ if (!arguments.length) {
+ 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 {
+ var a = this.dot(point) / div;
+ return Math.acos(a < -1 ? -1 : a > 1 ? 1 : a);
+ }
+ }
+ },
+
+ setAngleInRadians: function(angle) {
+ this._angle = angle;
+ if (!this.isZero()) {
+ var length = this.getLength();
+ this.set(
+ Math.cos(angle) * length,
+ Math.sin(angle) * length
+ );
+ }
+ },
+
+ getQuadrant: function() {
+ return this.x >= 0 ? this.y >= 0 ? 1 : 4 : this.y >= 0 ? 2 : 3;
+ }
+}, {
+ beans: false,
+
+ getDirectedAngle: function() {
+ var point = Point.read(arguments);
+ return Math.atan2(this.cross(point), this.dot(point)) * 180 / Math.PI;
+ },
+
+ getDistance: function() {
+ var point = Point.read(arguments),
+ x = point.x - this.x,
+ y = point.y - this.y,
+ d = x * x + y * y,
+ squared = Base.read(arguments);
+ return squared ? d : Math.sqrt(d);
+ },
+
+ 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);
+ if (scale >= 0)
+ point._angle = this._angle;
+ return point;
+ },
+
+ 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.x * s + point.y * c
+ );
+ return center ? point.add(center) : point;
+ },
+
+ transform: function(matrix) {
+ return matrix ? matrix._transformPoint(this) : this;
+ },
+
+ add: function() {
+ var point = Point.read(arguments);
+ return new Point(this.x + point.x, this.y + point.y);
+ },
+
+ subtract: function() {
+ var point = Point.read(arguments);
+ return new Point(this.x - point.x, this.y - point.y);
+ },
+
+ multiply: function() {
+ var point = Point.read(arguments);
+ return new Point(this.x * point.x, this.y * point.y);
+ },
+
+ divide: function() {
+ var point = Point.read(arguments);
+ return new Point(this.x / point.x, this.y / point.y);
+ },
+
+ modulo: function() {
+ var point = Point.read(arguments);
+ return new Point(this.x % point.x, this.y % point.y);
+ },
+
+ negate: function() {
+ return new Point(-this.x, -this.y);
+ },
+
+ isInside: function() {
+ return Rectangle.read(arguments).contains(this);
+ },
+
+ isClose: function(point, tolerance) {
+ return this.getDistance(point) < tolerance;
+ },
+
+ isCollinear: function(point) {
+ return Math.abs(this.cross(point)) < 0.000001;
+ },
+
+ isColinear: '#isCollinear',
+
+ isOrthogonal: function(point) {
+ return Math.abs(this.dot(point)) < 0.000001;
+ },
+
+ isZero: function() {
+ return Numerical.isZero(this.x) && Numerical.isZero(this.y);
+ },
+
+ isNaN: function() {
+ return isNaN(this.x) || isNaN(this.y);
+ },
+
+ dot: function() {
+ var point = Point.read(arguments);
+ return this.x * point.x + this.y * point.y;
+ },
+
+ cross: function() {
+ var point = Point.read(arguments);
+ return this.x * point.y - this.y * point.x;
+ },
+
+ project: function() {
+ var 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() {
+ var size = Size.read(arguments);
+ return new Size(this.width + size.width, this.height + size.height);
+ },
+
+ subtract: function() {
+ var size = Size.read(arguments);
+ return new Size(this.width - size.width, this.height - size.height);
+ },
+
+ multiply: function() {
+ var size = Size.read(arguments);
+ return new Size(this.width * size.width, this.height * size.height);
+ },
+
+ divide: function() {
+ var size = Size.read(arguments);
+ return new Size(this.width / size.width, this.height / size.height);
+ },
+
+ modulo: function() {
+ var 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,
+ beans: 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) {
+ var rt = Base.isPlainValue(rect)
+ ? Rectangle.read(arguments)
+ : rect;
+ return rt === this
+ || rt && this.x === rt.x && this.y === rt.y
+ && this.width === rt.width && this.height === rt.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(_dontLink) {
+ var ctor = _dontLink ? Point : LinkedPoint;
+ return new ctor(this.x, this.y, this, 'setPoint');
+ },
+
+ setPoint: function() {
+ var point = Point.read(arguments);
+ this.x = point.x;
+ this.y = point.y;
+ },
+
+ getSize: function(_dontLink) {
+ var ctor = _dontLink ? Size : LinkedSize;
+ return new ctor(this.width, this.height, this, 'setSize');
+ },
+
+ setSize: function() {
+ var 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(_dontLink) {
+ var ctor = _dontLink ? Point : LinkedPoint;
+ return new ctor(this.getCenterX(), this.getCenterY(), this, 'setCenter');
+ },
+
+ setCenter: function() {
+ var point = Point.read(arguments);
+ this.setCenterX(point.x);
+ this.setCenterY(point.y);
+ return this;
+ },
+
+ getArea: function() {
+ return this.width * this.height;
+ },
+
+ 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() {
+ var 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() {
+ var 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() {
+ var rect = Rectangle.read(arguments),
+ 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() {
+ var rect = Rectangle.read(arguments),
+ 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() {
+ var 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() {
+ var amount = Size.read(arguments),
+ hor = amount.width,
+ ver = amount.height;
+ 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);
+ }
+}, 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(_dontLink) {
+ var ctor = _dontLink ? Point : LinkedPoint;
+ return new ctor(this[getX](), this[getY](), this, set);
+ };
+ this[set] = function() {
+ var point = Point.read(arguments);
+ this[setX](point.x);
+ this[setY](point.y);
+ };
+ }, {
+ beans: true
+ }
+));
+
+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);
+ this._dontNotify = false;
+ 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() {
+ var owner = this._owner;
+ if (owner) {
+ if (owner._applyMatrix) {
+ owner.transform(null, true);
+ } else {
+ owner._changed(9);
+ }
+ }
+ },
+
+ 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(_dontNotify) {
+ this._a = this._d = 1;
+ this._c = this._b = this._tx = this._ty = 0;
+ if (!_dontNotify)
+ this._changed();
+ return this;
+ },
+
+ apply: function(recursively, _setApplyMatrix) {
+ var owner = this._owner;
+ if (owner) {
+ owner.transform(null, true, Base.pick(recursively, true),
+ _setApplyMatrix);
+ return this.isIdentity();
+ }
+ return false;
+ },
+
+ translate: function() {
+ var point = Point.read(arguments),
+ 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;
+ },
+
+ scale: function() {
+ var scale = Point.read(arguments),
+ center = Point.read(arguments, 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;
+ },
+
+ rotate: function(angle ) {
+ angle *= Math.PI / 180;
+ var center = Point.read(arguments, 1),
+ 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 shear = Point.read(arguments),
+ center = Point.read(arguments, 0, { readNull: true });
+ if (center)
+ this.translate(center);
+ var a = this._a,
+ c = this._c;
+ this._a += shear.y * this._b;
+ this._c += shear.y * this._d;
+ this._b += shear.x * a;
+ this._d += shear.x * c;
+ if (center)
+ this.translate(center.negate());
+ this._changed();
+ return this;
+ },
+
+ skew: function() {
+ var skew = Point.read(arguments),
+ center = Point.read(arguments, 0, { readNull: true }),
+ toRadians = Math.PI / 180,
+ shear = new Point(Math.tan(skew.x * toRadians),
+ Math.tan(skew.y * toRadians));
+ return this.shear(shear, center);
+ },
+
+ concatenate: function(mx) {
+ var a1 = this._a,
+ b1 = this._b,
+ c1 = this._c,
+ d1 = this._d,
+ a2 = mx._a,
+ b2 = mx._b,
+ c2 = mx._c,
+ d2 = mx._d,
+ tx2 = mx._tx,
+ ty2 = mx._ty;
+ this._a = a2 * a1 + c2 * b1;
+ this._b = b2 * a1 + d2 * b1;
+ this._c = a2 * c1 + c2 * d1;
+ this._d = b2 * c1 + d2 * d1;
+ this._tx += tx2 * a1 + ty2 * b1;
+ this._ty += tx2 * c1 + ty2 * d1;
+ this._changed();
+ return this;
+ },
+
+ preConcatenate: function(mx) {
+ var a1 = this._a,
+ b1 = this._b,
+ c1 = this._c,
+ d1 = this._d,
+ tx1 = this._tx,
+ ty1 = this._ty,
+ a2 = mx._a,
+ b2 = mx._b,
+ c2 = mx._c,
+ d2 = mx._d,
+ tx2 = mx._tx,
+ ty2 = mx._ty;
+ this._a = a2 * a1 + b2 * c1;
+ this._b = a2 * b1 + b2 * d1;
+ this._c = c2 * a1 + d2 * c1;
+ this._d = c2 * b1 + d2 * d1;
+ this._tx = a2 * tx1 + b2 * ty1 + tx2;
+ this._ty = c2 * tx1 + d2 * ty1 + ty2;
+ this._changed();
+ return this;
+ },
+
+ chain: function(mx) {
+ var a1 = this._a,
+ b1 = this._b,
+ c1 = this._c,
+ d1 = this._d,
+ tx1 = this._tx,
+ ty1 = this._ty,
+ a2 = mx._a,
+ b2 = mx._b,
+ c2 = mx._c,
+ d2 = mx._d,
+ tx2 = mx._tx,
+ ty2 = mx._ty;
+ return new Matrix(
+ a2 * a1 + c2 * b1,
+ a2 * c1 + c2 * d1,
+ b2 * a1 + d2 * b1,
+ b2 * c1 + d2 * d1,
+ tx1 + tx2 * a1 + ty2 * b1,
+ ty1 + tx2 * c1 + ty2 * d1);
+ },
+
+ isIdentity: function() {
+ return this._a === 1 && this._c === 0 && this._b === 0 && this._d === 1
+ && this._tx === 0 && this._ty === 0;
+ },
+
+ orNullIfIdentity: function() {
+ return this.isIdentity() ? null : this;
+ },
+
+ isInvertible: function() {
+ return !!this._getDeterminant();
+ },
+
+ isSingular: function() {
+ return !this._getDeterminant();
+ },
+
+ transform: function( src, dst, count) {
+ return arguments.length < 3
+ ? this._transformPoint(Point.read(arguments))
+ : this._transformCoordinates(src, dst, 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, dst, count) {
+ var i = 0,
+ j = 0,
+ max = 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, coords, 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 {
+ 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);
+ },
+
+ getScaling: function() {
+ return (this.decompose() || {}).scaling;
+ },
+
+ getRotation: function() {
+ return (this.decompose() || {}).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);
+ }
+}, Base.each(['a', 'c', 'b', 'd', 'tx', 'ty'], function(name) {
+ var part = Base.capitalize(name),
+ prop = '_' + name;
+ this['get' + part] = function() {
+ return this[prop];
+ };
+ this['set' + part] = 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 = avx * bvy - avy * bvx;
+ 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 && 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;
+ }
+ return Numerical.isZero(vx)
+ ? vy >= 0 ? px - x : x - px
+ : Numerical.isZero(vy)
+ ? vx >= 0 ? y - py : py - y
+ : (vx * (y - py) - vy * (x - px)) / Math.sqrt(vx * vx + vy * vy);
+ }
+ }
+});
+
+var Project = PaperScopeItem.extend({
+ _class: 'Project',
+ _list: 'projects',
+ _reference: 'project',
+
+ initialize: function Project(element) {
+ PaperScopeItem.call(this, true);
+ this.layers = [];
+ this._activeLayer = null;
+ this.symbols = [];
+ this._currentStyle = new Style(null, null, this);
+ this._view = View.create(this,
+ element || CanvasProvider.getCanvas(1, 1));
+ this._selectedItems = {};
+ this._selectedItemCount = 0;
+ this._updateVersion = 0;
+ },
+
+ _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 === 0;
+ },
+
+ remove: function remove() {
+ if (!remove.base.call(this))
+ return false;
+ if (this._view)
+ this._view.remove();
+ return true;
+ },
+
+ getView: function() {
+ return this._view;
+ },
+
+ getCurrentStyle: function() {
+ return this._currentStyle;
+ },
+
+ setCurrentStyle: function(style) {
+ this._currentStyle.initialize(style);
+ },
+
+ getIndex: function() {
+ return this._index;
+ },
+
+ getOptions: function() {
+ return this._scope.settings;
+ },
+
+ getActiveLayer: function() {
+ return this._activeLayer || new Layer({ project: this });
+ },
+
+ getSelectedItems: function() {
+ var items = [];
+ for (var id in this._selectedItems) {
+ var item = this._selectedItems[id];
+ if (item.isInserted())
+ items.push(item);
+ }
+ return items;
+ },
+
+ insertChild: function(index, item, _preserve) {
+ if (item instanceof Layer) {
+ item._remove(false, true);
+ Base.splice(this.layers, [item], index, 0);
+ item._setProject(this, true);
+ if (this._changes)
+ item._changed(5);
+ if (!this._activeLayer)
+ this._activeLayer = item;
+ } else if (item instanceof Item) {
+ (this._activeLayer
+ || this.insertChild(index, new Layer(Item.NO_INSERT)))
+ .insertChild(index, item, _preserve);
+ } else {
+ item = null;
+ }
+ return item;
+ },
+
+ addChild: function(item, _preserve) {
+ return this.insertChild(undefined, item, _preserve);
+ },
+
+ _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() {
+ var 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;
+ },
+
+ getItems: function(match) {
+ return Item._getItems(this.layers, match);
+ },
+
+ getItem: function(match) {
+ return Item._getItems(this.layers, match, null, null, true)[0] || null;
+ },
+
+ importJSON: function(json) {
+ this.activate();
+ var layer = this._activeLayer;
+ return Base.importJSON(json, layer && layer.isEmpty() && layer);
+ },
+
+ draw: function(ctx, matrix, pixelRatio) {
+ this._updateVersion++;
+ ctx.save();
+ matrix.applyToContext(ctx);
+ var param = new Base({
+ offset: new Point(0, 0),
+ pixelRatio: pixelRatio,
+ viewMatrix: matrix.isIdentity() ? null : matrix,
+ matrices: [new Matrix()],
+ updateMatrix: true
+ });
+ for (var i = 0, layers = this.layers, l = layers.length; i < l; i++)
+ layers[i].draw(ctx, param);
+ ctx.restore();
+
+ if (this._selectedItemCount > 0) {
+ ctx.save();
+ ctx.strokeWidth = 1;
+ var items = this._selectedItems,
+ size = this._scope.settings.handleSize,
+ version = this._updateVersion;
+ for (var id in items)
+ items[id]._drawSelection(ctx, matrix, size, items, version);
+ ctx.restore();
+ }
+ }
+});
+
+var Symbol = Base.extend({
+ _class: 'Symbol',
+
+ initialize: function Symbol(item, dontCenter) {
+ this._id = UID.get();
+ this.project = paper.project;
+ this.project.symbols.push(this);
+ if (item)
+ this.setDefinition(item, dontCenter);
+ },
+
+ _serialize: function(options, dictionary) {
+ return dictionary.add(this, function() {
+ return Base.serialize([this._class, this._definition],
+ options, false, dictionary);
+ });
+ },
+
+ _changed: function(flags) {
+ if (flags & 8) {
+ Item._clearBoundsCache(this);
+ }
+ if (flags & 1) {
+ this.project._needsUpdate = true;
+ }
+ },
+
+ getDefinition: function() {
+ return this._definition;
+ },
+
+ setDefinition: function(item, _dontCenter) {
+ if (item._parentSymbol)
+ item = item.clone();
+ if (this._definition)
+ this._definition._parentSymbol = null;
+ this._definition = item;
+ item.remove();
+ item.setSelected(false);
+ if (!_dontCenter)
+ item.setPosition(new Point());
+ item._parentSymbol = this;
+ this._changed(9);
+ },
+
+ place: function(position) {
+ return new PlacedSymbol(this, position);
+ },
+
+ clone: function() {
+ return new Symbol(this._definition.clone(false));
+ },
+
+ equals: function(symbol) {
+ return symbol === this
+ || symbol && this.definition.equals(symbol.definition)
+ || false;
+ }
+});
+
+var Item = Base.extend(Emitter, {
+ statics: {
+ extend: function extend(src) {
+ if (src._serializeFields)
+ src._serializeFields = new Base(
+ this.prototype._serializeFields, src._serializeFields);
+ return extend.base.apply(this, arguments);
+ },
+
+ NO_INSERT: { insert: false }
+ },
+
+ _class: 'Item',
+ _applyMatrix: true,
+ _canApplyMatrix: true,
+ _boundsSelected: false,
+ _selectChildren: false,
+ _serializeFields: {
+ name: null,
+ applyMatrix: null,
+ matrix: new Matrix(),
+ pivot: null,
+ locked: false,
+ visible: true,
+ blendMode: 'normal',
+ opacity: 1,
+ guide: false,
+ selected: false,
+ clipMask: false,
+ data: {}
+ },
+
+ initialize: function Item() {
+ },
+
+ _initialize: function(props, point) {
+ var hasProps = props && Base.isPlainObject(props),
+ internal = hasProps && props.internal === true,
+ matrix = this._matrix = new Matrix(),
+ project = hasProps && props.project || paper.project;
+ if (!internal)
+ this._id = UID.get();
+ this._applyMatrix = this._canApplyMatrix && paper.settings.applyMatrix;
+ if (point)
+ matrix.translate(point);
+ matrix._owner = this;
+ this._style = new Style(project._currentStyle, this, project);
+ if (!this._project) {
+ if (internal || hasProps && props.insert === false) {
+ this._setProject(project);
+ } else if (hasProps && props.parent) {
+ this.setParent(props.parent);
+ } else {
+ (project._activeLayer || new Layer()).addChild(this);
+ }
+ }
+ if (hasProps && props !== Item.NO_INSERT)
+ this._set(props, { insert: true, project: true, parent: true },
+ true);
+ return hasProps;
+ },
+
+ _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.getView()._eventCounters;
+ if (counters) {
+ for (var key in mouseFlags) {
+ counters[key] = (counters[key] || 0)
+ + (mouseFlags[key][type] || 0);
+ }
+ }
+ },
+ uninstall: function(type) {
+ var counters = this.getView()._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.getView()._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 symbol = this._parentSymbol,
+ cacheParent = this._parent || symbol,
+ project = this._project;
+ if (flags & 8) {
+ this._bounds = this._position = this._decomposed =
+ this._globalMatrix = this._currentPath = undefined;
+ }
+ if (cacheParent
+ && (flags & 40)) {
+ Item._clearBoundsCache(cacheParent);
+ }
+ if (flags & 2) {
+ Item._clearBoundsCache(this);
+ }
+ if (project) {
+ if (flags & 1) {
+ project._needsUpdate = 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;
+ },
+
+ 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.');
+ var parent = this._parent;
+ if (name && parent) {
+ var children = parent._children,
+ namedChildren = 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(128);
+ },
+
+ getStyle: function() {
+ return this._style;
+ },
+
+ setStyle: function(style) {
+ this.getStyle().set(style);
+ }
+}, 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'
+ ? 128 : 129);
+ }
+ };
+ },
+{}), {
+ beans: true,
+
+ _locked: false,
+
+ _visible: true,
+
+ _blendMode: 'normal',
+
+ _opacity: 1,
+
+ _guide: false,
+
+ isSelected: function() {
+ if (this._selectChildren) {
+ var children = this._children;
+ for (var i = 0, l = children.length; i < l; i++)
+ if (children[i].isSelected())
+ return true;
+ }
+ return this._selected;
+ },
+
+ setSelected: function(selected, noChildren) {
+ if (!noChildren && this._selectChildren) {
+ var children = this._children;
+ for (var i = 0, l = children.length; i < l; i++)
+ children[i].setSelected(selected);
+ }
+ if ((selected = !!selected) ^ this._selected) {
+ this._selected = selected;
+ this._project._updateSelection(this);
+ this._changed(129);
+ }
+ },
+
+ _selected: false,
+
+ isFullySelected: function() {
+ var children = this._children;
+ if (children && this._selected) {
+ for (var i = 0, l = children.length; i < l; i++)
+ if (!children[i].isFullySelected())
+ return false;
+ return true;
+ }
+ return this._selected;
+ },
+
+ setFullySelected: function(selected) {
+ var children = this._children;
+ if (children) {
+ for (var i = 0, l = children.length; i < l; i++)
+ 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(129);
+ if (this._parent)
+ this._parent._changed(1024);
+ }
+ },
+
+ _clipMask: false,
+
+ getData: function() {
+ if (!this._data)
+ this._data = {};
+ return this._data;
+ },
+
+ setData: function(data) {
+ this._data = data;
+ },
+
+ getPosition: function(_dontLink) {
+ var position = this._position,
+ ctor = _dontLink ? Point : LinkedPoint;
+ if (!position) {
+ var pivot = this._pivot;
+ position = this._position = pivot
+ ? this._matrix._transformPoint(pivot)
+ : this.getBounds().getCenter(true);
+ }
+ return new ctor(position.x, position.y, this, 'setPosition');
+ },
+
+ setPosition: function() {
+ this.translate(Point.read(arguments).subtract(this.getPosition(true)));
+ },
+
+ getPivot: function(_dontLink) {
+ var pivot = this._pivot;
+ if (pivot) {
+ var ctor = _dontLink ? Point : LinkedPoint;
+ pivot = new ctor(pivot.x, pivot.y, this, 'setPivot');
+ }
+ return pivot;
+ },
+
+ setPivot: function() {
+ this._pivot = Point.read(arguments, 0, { clone: true, readNull: true });
+ this._position = undefined;
+ },
+
+ _pivot: null,
+}, Base.each(['bounds', 'strokeBounds', 'handleBounds', 'roughBounds',
+ 'internalBounds', 'internalRoughBounds'],
+ function(key) {
+ var getter = 'get' + Base.capitalize(key),
+ match = key.match(/^internal(.*)$/),
+ internalGetter = match ? 'get' + match[1] : null;
+ this[getter] = function(_matrix) {
+ var boundsGetter = this._boundsGetter,
+ name = !internalGetter && (typeof boundsGetter === 'string'
+ ? boundsGetter : boundsGetter && boundsGetter[getter])
+ || getter,
+ bounds = this._getCachedBounds(name, _matrix, this,
+ internalGetter);
+ return key === 'bounds'
+ ? new LinkedRectangle(bounds.x, bounds.y, bounds.width,
+ bounds.height, this, 'setBounds')
+ : bounds;
+ };
+ },
+{
+ beans: true,
+
+ _getBounds: function(getter, matrix, cacheItem) {
+ var children = this._children;
+ if (!children || children.length == 0)
+ return new Rectangle();
+ Item._updateBoundsCache(this, cacheItem);
+ 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 && matrix.chain(child._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() {
+ var rect = Rectangle.read(arguments),
+ 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);
+ },
+
+ _getCachedBounds: function(getter, matrix, cacheItem, internalGetter) {
+ matrix = matrix && matrix.orNullIfIdentity();
+ var _matrix = internalGetter ? null : this._matrix.orNullIfIdentity(),
+ cache = (!matrix || matrix.equals(_matrix)) && getter;
+ Item._updateBoundsCache(this._parent || this._parentSymbol, cacheItem);
+ if (cache && this._bounds && this._bounds[cache])
+ return this._bounds[cache].clone();
+ var bounds = this._getBounds(internalGetter || getter,
+ matrix || _matrix, cacheItem);
+ if (cache) {
+ if (!this._bounds)
+ this._bounds = {};
+ var cached = this._bounds[cache] = bounds.clone();
+ cached._internal = !!internalGetter;
+ }
+ return bounds;
+ },
+
+ statics: {
+ _updateBoundsCache: function(parent, item) {
+ if (parent) {
+ var id = item._id,
+ ref = parent._boundsCache = parent._boundsCache || {
+ ids: {},
+ list: []
+ };
+ if (!ref.ids[id]) {
+ ref.list.push(item);
+ ref.ids[id] = item;
+ }
+ }
+ },
+
+ _clearBoundsCache: function(item) {
+ var cache = item._boundsCache;
+ if (cache) {
+ item._bounds = item._position = item._boundsCache = undefined;
+ for (var i = 0, list = cache.list, l = list.length; i < l; i++){
+ var other = list[i];
+ if (other !== item) {
+ other._bounds = other._position = undefined;
+ if (other._boundsCache)
+ Item._clearBoundsCache(other);
+ }
+ }
+ }
+ }
+ }
+
+}), {
+ beans: true,
+
+ _decompose: function() {
+ return this._decomposed = this._matrix.decompose();
+ },
+
+ getRotation: function() {
+ var decomposed = this._decomposed || this._decompose();
+ return decomposed && decomposed.rotation;
+ },
+
+ setRotation: function(rotation) {
+ var current = this.getRotation();
+ if (current != null && rotation != null) {
+ var decomposed = this._decomposed;
+ this.rotate(rotation - current);
+ decomposed.rotation = rotation;
+ this._decomposed = decomposed;
+ }
+ },
+
+ getScaling: function(_dontLink) {
+ var decomposed = this._decomposed || this._decompose(),
+ scaling = decomposed && decomposed.scaling,
+ ctor = _dontLink ? Point : LinkedPoint;
+ return scaling && new ctor(scaling.x, scaling.y, this, 'setScaling');
+ },
+
+ setScaling: function() {
+ var current = this.getScaling();
+ if (current) {
+ var scaling = Point.read(arguments, 0, { clone: true }),
+ decomposed = this._decomposed;
+ this.scale(scaling.x / current.x, scaling.y / current.y);
+ decomposed.scaling = scaling;
+ this._decomposed = decomposed;
+ }
+ },
+
+ getMatrix: function() {
+ return this._matrix;
+ },
+
+ setMatrix: function() {
+ var matrix = this._matrix;
+ matrix.initialize.apply(matrix, arguments);
+ if (this._applyMatrix) {
+ this.transform(null, true);
+ } else {
+ this._changed(9);
+ }
+ },
+
+ getGlobalMatrix: function(_dontClone) {
+ var matrix = this._globalMatrix,
+ updateVersion = this._project._updateVersion;
+ if (matrix && matrix._updateVersion !== updateVersion)
+ matrix = null;
+ if (!matrix) {
+ matrix = this._globalMatrix = this._matrix.clone();
+ var parent = this._parent;
+ if (parent)
+ matrix.preConcatenate(parent.getGlobalMatrix(true));
+ matrix._updateVersion = updateVersion;
+ }
+ return _dontClone ? matrix : matrix.clone();
+ },
+
+ getApplyMatrix: function() {
+ return this._applyMatrix;
+ },
+
+ setApplyMatrix: function(apply) {
+ if (this._applyMatrix = this._canApplyMatrix && !!apply)
+ this.transform(null, true);
+ },
+
+ getTransformContent: '#getApplyMatrix',
+ setTransformContent: '#setApplyMatrix',
+}, {
+ getProject: function() {
+ return this._project;
+ },
+
+ _setProject: function(project, installEvents) {
+ if (this._project !== project) {
+ if (this._project)
+ this._installEvents(false);
+ this._project = project;
+ var children = this._children;
+ for (var i = 0, l = children && children.length; i < l; i++)
+ children[i]._setProject(project);
+ installEvents = true;
+ }
+ if (installEvents)
+ this._installEvents(true);
+ },
+
+ getView: function() {
+ return this._project.getView();
+ },
+
+ _installEvents: function _installEvents(install) {
+ _installEvents.base.call(this, install);
+ var children = this._children;
+ for (var i = 0, l = children && children.length; i < l; i++)
+ children[i]._installEvents(install);
+ },
+
+ 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;
+ },
+
+ 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(Item.NO_INSERT), insert);
+ },
+
+ _clone: function(copy, insert, includeMatrix) {
+ var keys = ['_locked', '_visible', '_blendMode', '_opacity',
+ '_clipMask', '_guide'],
+ children = this._children;
+ copy.setStyle(this._style);
+ for (var i = 0, l = children && children.length; i < l; i++) {
+ copy.addChild(children[i].clone(false), true);
+ }
+ for (var i = 0, l = keys.length; i < l; i++) {
+ var key = keys[i];
+ if (this.hasOwnProperty(key))
+ copy[key] = this[key];
+ }
+ if (includeMatrix !== false)
+ copy._matrix.initialize(this._matrix);
+ copy.setApplyMatrix(this._applyMatrix);
+ copy.setPivot(this._pivot);
+ copy.setSelected(this._selected);
+ copy._data = this._data ? Base.clone(this._data) : null;
+ if (insert || insert === undefined)
+ copy.insertAbove(this);
+ 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 || this.getView().getResolution()) / 72,
+ topLeft = bounds.getTopLeft().floor(),
+ bottomRight = bounds.getBottomRight().ceil(),
+ size = new Size(bottomRight.subtract(topLeft)),
+ canvas = CanvasProvider.getCanvas(size.multiply(scale)),
+ ctx = canvas.getContext('2d'),
+ matrix = new Matrix().scale(scale).translate(topLeft.negate());
+ ctx.save();
+ matrix.applyToContext(ctx);
+ this.draw(ctx, new Base({ matrices: [matrix] }));
+ ctx.restore();
+ var raster = new Raster(Item.NO_INSERT);
+ raster.setCanvas(canvas);
+ raster.transform(new Matrix().translate(topLeft.add(size.divide(2)))
+ .scale(1 / scale));
+ 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.getInternalBounds());
+ },
+
+ isInside: function() {
+ return Rectangle.read(arguments).contains(this.getBounds());
+ },
+
+ _asPathItem: function() {
+ return new Path.Rectangle({
+ rectangle: this.getInternalBounds(),
+ matrix: this._matrix,
+ insert: false,
+ });
+ },
+
+ intersects: function(item, _matrix) {
+ if (!(item instanceof Item))
+ return false;
+ return this._asPathItem().getIntersections(item._asPathItem(),
+ _matrix || item._matrix).length > 0;
+ },
+
+ hitTest: function() {
+ return this._hitTest(
+ Point.read(arguments),
+ HitResult.getOptions(Base.read(arguments)));
+ },
+
+ _hitTest: function(point, options) {
+ if (this._locked || !this._visible || this._guide && !options.guides
+ || this.isEmpty())
+ return null;
+
+ var matrix = this._matrix,
+ parentTotalMatrix = options._totalMatrix,
+ view = this.getView(),
+ totalMatrix = options._totalMatrix = parentTotalMatrix
+ ? parentTotalMatrix.chain(matrix)
+ : this.getGlobalMatrix().preConcatenate(view._matrix),
+ tolerancePadding = options._tolerancePadding = new Size(
+ Path._getPenPadding(1, totalMatrix.inverted())
+ ).multiply(
+ Math.max(options.tolerance, 0.000001)
+ );
+ point = matrix._inverseTransform(point);
+
+ if (!this._children && !this.getInternalRoughBounds()
+ .expand(tolerancePadding.multiply(2))._containsPoint(point))
+ return null;
+ var checkSelf = !(options.guides && !this._guide
+ || options.selected && !this._selected
+ || options.type && options.type !== Base.hyphenate(this._class)
+ || options.class && !(this instanceof options.class)),
+ that = this,
+ res;
+
+ function checkBounds(type, part) {
+ var pt = bounds['get' + part]();
+ if (point.subtract(pt).divide(tolerancePadding).length <= 1)
+ return new HitResult(type, that,
+ { name: Base.hyphenate(part), point: pt });
+ }
+
+ if (checkSelf && (options.center || options.bounds) && this._parent) {
+ var bounds = this.getInternalBounds();
+ 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]);
+ }
+ }
+
+ var children = !res && this._children;
+ if (children) {
+ var opts = this._getChildHitTestOptions(options);
+ for (var i = children.length - 1; i >= 0 && !res; i--)
+ res = children[i]._hitTest(point, opts);
+ }
+ if (!res && checkSelf)
+ res = this._hitTestSelf(point, options);
+ if (res && res.point)
+ res.point = matrix.transform(res.point);
+ options._totalMatrix = parentTotalMatrix;
+ return res;
+ },
+
+ _getChildHitTestOptions: function(options) {
+ return options;
+ },
+
+ _hitTestSelf: function(point, options) {
+ if (options.fill && this.hasFill() && this._contains(point))
+ return new HitResult('fill', this);
+ },
+
+ matches: function(name, compare) {
+ 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;
+ }
+ var type = typeof name;
+ if (type === 'object') {
+ for (var key in name) {
+ if (name.hasOwnProperty(key) && !this.matches(key, name[key]))
+ return false;
+ }
+ } else if (type === 'function') {
+ return name(this);
+ } else {
+ var value = /^(empty|editable)$/.test(name)
+ ? this['is' + Base.capitalize(name)]()
+ : name === 'type'
+ ? Base.hyphenate(this._class)
+ : this[name];
+ if (/^(constructor|class)$/.test(name)) {
+ if (!(this instanceof compare))
+ return false;
+ } else 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;
+ },
+
+ getItems: function(match) {
+ return Item._getItems(this._children, match, this._matrix);
+ },
+
+ getItem: function(match) {
+ return Item._getItems(this._children, match, this._matrix, null, true)
+ [0] || null;
+ },
+
+ statics: {
+ _getItems: function _getItems(children, match, matrix, param,
+ firstOnly) {
+ if (!param && typeof match === 'object') {
+ var overlapping = match.overlapping,
+ inside = match.inside,
+ bounds = overlapping || inside,
+ rect = bounds && Rectangle.read([bounds]);
+ param = {
+ items: [],
+ inside: !!inside,
+ overlapping: !!overlapping,
+ rect: rect,
+ path: overlapping && new Path.Rectangle({
+ rectangle: rect,
+ insert: false
+ })
+ };
+ if (bounds)
+ match = Base.set({}, match,
+ { inside: true, overlapping: true });
+ }
+ var items = param && param.items,
+ rect = param && param.rect;
+ matrix = rect && (matrix || new Matrix());
+ for (var i = 0, l = children && children.length; i < l; i++) {
+ var child = children[i],
+ childMatrix = matrix && matrix.chain(child._matrix),
+ add = true;
+ if (rect) {
+ var bounds = child.getBounds(childMatrix);
+ if (!rect.intersects(bounds))
+ continue;
+ if (!(param.inside && rect.contains(bounds))
+ && !(param.overlapping && (bounds.contains(rect)
+ || param.path.intersects(child, childMatrix))))
+ add = false;
+ }
+ if (add && child.matches(match)) {
+ items.push(child);
+ if (firstOnly)
+ break;
+ }
+ _getItems(child._children, match,
+ childMatrix, param,
+ firstOnly);
+ if (firstOnly && items.length > 0)
+ break;
+ }
+ return items;
+ }
+ }
+}, {
+
+ 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 = item ? this.insertChildren(index, [item], _preserve) : null;
+ return res && res[0];
+ },
+
+ addChildren: function(items, _preserve) {
+ return this.insertChildren(this._children.length, items, _preserve);
+ },
+
+ insertChildren: function(index, items, _preserve, _proto) {
+ 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 (_proto && !(item instanceof _proto)) {
+ items.splice(i, 1);
+ } else {
+ var shift = item._parent === this && item._index < index;
+ if (item._remove(false, true) && shift)
+ index--;
+ }
+ }
+ Base.splice(children, items, index, 0);
+ var project = this._project,
+ notifySelf = project && project._changes;
+ for (var i = 0, l = items.length; i < l; i++) {
+ var item = items[i];
+ item._parent = this;
+ item._setProject(this._project, true);
+ if (item._name)
+ item.setName(item._name);
+ if (notifySelf)
+ this._changed(5);
+ }
+ this._changed(11);
+ } else {
+ items = null;
+ }
+ return items;
+ },
+
+ _insertSibling: function(index, item, _preserve) {
+ return this._parent
+ ? this._parent.insertChild(index, item, _preserve)
+ : null;
+ },
+
+ insertAbove: function(item, _preserve) {
+ return item._insertSibling(item._index + 1, this, _preserve);
+ },
+
+ insertBelow: function(item, _preserve) {
+ return item._insertSibling(item._index, this, _preserve);
+ },
+
+ sendToBack: function() {
+ return (this._parent || this instanceof Layer && this._project)
+ .insertChild(0, this);
+ },
+
+ bringToFront: function() {
+ return (this._parent || this instanceof Layer && this._project)
+ .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].reduce();
+ child.insertAbove(this);
+ child.setStyle(this._style);
+ this.remove();
+ return child;
+ }
+ return this;
+ },
+
+ _removeNamed: function() {
+ var parent = this._parent;
+ if (parent) {
+ var children = parent._children,
+ namedChildren = parent._namedChildren,
+ name = this._name,
+ namedArray = namedChildren[name],
+ index = namedArray ? namedArray.indexOf(this) : -1;
+ if (index !== -1) {
+ 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(notifySelf, notifyParent) {
+ var parent = this._parent;
+ if (parent) {
+ if (this._name)
+ this._removeNamed();
+ if (this._index != null)
+ Base.splice(parent._children, null, this._index, 1);
+ this._installEvents(false);
+ if (notifySelf) {
+ var project = this._project;
+ if (project && project._changes)
+ this._changed(5);
+ }
+ if (notifyParent)
+ parent._changed(11);
+ this._parent = null;
+ return true;
+ }
+ return false;
+ },
+
+ remove: function() {
+ return this._remove(true, true);
+ },
+
+ replaceWith: function(item) {
+ var ok = item && item.insertBelow(this);
+ if (ok)
+ this.remove();
+ return ok;
+ },
+
+ 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(true, false);
+ }
+ if (removed.length > 0)
+ this._changed(11);
+ 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(11);
+ }
+ },
+
+ 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;
+ },
+
+ hasFill: function() {
+ return this.getStyle().hasFill();
+ },
+
+ hasStroke: function() {
+ return this.getStyle().hasStroke();
+ },
+
+ hasShadow: function() {
+ return this.getStyle().hasShadow();
+ },
+
+ _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;
+ },
+
+ isInserted: function() {
+ return this._parent ? this._parent.isInserted() : false;
+ },
+
+ 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|CompoundPath)$/.test(parent._class)
+ && item.isDescendant(parent))
+ return true;
+ parent = parent._parent;
+ }
+ return false;
+ },
+
+ translate: function() {
+ var mx = new Matrix();
+ return this.transform(mx.translate.apply(mx, arguments));
+ },
+
+ rotate: function(angle ) {
+ return this.transform(new Matrix().rotate(angle,
+ Point.read(arguments, 1, { readNull: true })
+ || this.getPosition(true)));
+ }
+}, Base.each(['scale', 'shear', 'skew'], function(name) {
+ this[name] = function() {
+ var point = Point.read(arguments),
+ center = Point.read(arguments, 0, { readNull: true });
+ return this.transform(new Matrix()[name](point,
+ center || this.getPosition(true)));
+ };
+}, {
+
+}), {
+ transform: function(matrix, _applyMatrix, _applyRecursively,
+ _setApplyMatrix) {
+ if (matrix && matrix.isIdentity())
+ matrix = null;
+ var _matrix = this._matrix,
+ applyMatrix = (_applyMatrix || this._applyMatrix)
+ && ((!_matrix.isIdentity() || matrix)
+ || _applyMatrix && _applyRecursively && this._children);
+ if (!matrix && !applyMatrix)
+ return this;
+ if (matrix)
+ _matrix.preConcatenate(matrix);
+ if (applyMatrix = applyMatrix && this._transformContent(_matrix,
+ _applyRecursively, _setApplyMatrix)) {
+ var pivot = this._pivot,
+ style = this._style,
+ fillColor = style.getFillColor(true),
+ strokeColor = style.getStrokeColor(true);
+ if (pivot)
+ _matrix._transformPoint(pivot, pivot, true);
+ if (fillColor)
+ fillColor.transform(_matrix);
+ if (strokeColor)
+ strokeColor.transform(_matrix);
+ _matrix.reset(true);
+ if (_setApplyMatrix && this._canApplyMatrix)
+ this._applyMatrix = true;
+ }
+ var bounds = this._bounds,
+ position = this._position;
+ this._changed(9);
+ var decomp = bounds && matrix && matrix.decompose();
+ if (decomp && !decomp.shearing && decomp.rotation % 90 === 0) {
+ for (var key in bounds) {
+ var rect = bounds[key];
+ if (applyMatrix || !rect._internal)
+ 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 (matrix && position) {
+ this._position = matrix._transformPoint(position, position);
+ }
+ return this;
+ },
+
+ _transformContent: function(matrix, applyRecursively, setApplyMatrix) {
+ var children = this._children;
+ if (children) {
+ for (var i = 0, l = children.length; i < l; i++)
+ children[i].transform(matrix, true, applyRecursively,
+ setApplyMatrix);
+ return true;
+ }
+ },
+
+ globalToLocal: function() {
+ return this.getGlobalMatrix(true)._inverseTransform(
+ Point.read(arguments));
+ },
+
+ localToGlobal: function() {
+ return this.getGlobalMatrix(true)._transformPoint(
+ Point.read(arguments));
+ },
+
+ parentToLocal: function() {
+ return this._matrix._inverseTransform(Point.read(arguments));
+ },
+
+ localToParent: function() {
+ return this._matrix._transformPoint(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, parentStrokeMatrix) {
+ var updateVersion = this._updateVersion = this._project._updateVersion;
+ if (!this._visible || this._opacity === 0)
+ return;
+ var matrices = param.matrices,
+ viewMatrix = param.viewMatrix,
+ matrix = this._matrix,
+ globalMatrix = matrices[matrices.length - 1].chain(matrix);
+ if (!globalMatrix.isInvertible())
+ return;
+
+ function getViewMatrix(matrix) {
+ return viewMatrix ? viewMatrix.chain(matrix) : matrix;
+ }
+
+ matrices.push(globalMatrix);
+ if (param.updateMatrix) {
+ globalMatrix._updateVersion = updateVersion;
+ this._globalMatrix = globalMatrix;
+ }
+
+ var blendMode = this._blendMode,
+ opacity = this._opacity,
+ normalBlend = blendMode === 'normal',
+ nativeBlend = BlendMode.nativeModes[blendMode],
+ direct = normalBlend && opacity === 1
+ || param.dontStart
+ || param.clip
+ || (nativeBlend || normalBlend && opacity < 1)
+ && this._canComposite(),
+ pixelRatio = param.pixelRatio || 1,
+ mainCtx, itemOffset, prevOffset;
+ if (!direct) {
+ var bounds = this.getStrokeBounds(getViewMatrix(globalMatrix));
+ if (!bounds.width || !bounds.height)
+ return;
+ prevOffset = param.offset;
+ itemOffset = param.offset = bounds.getTopLeft().floor();
+ mainCtx = ctx;
+ ctx = CanvasProvider.getContext(bounds.getSize().ceil().add(1)
+ .multiply(pixelRatio));
+ if (pixelRatio !== 1)
+ ctx.scale(pixelRatio, pixelRatio);
+ }
+ ctx.save();
+ var strokeMatrix = parentStrokeMatrix
+ ? parentStrokeMatrix.chain(matrix)
+ : !this.getStrokeScaling(true) && getViewMatrix(globalMatrix),
+ clip = !direct && param.clipItem,
+ transform = !strokeMatrix || clip;
+ if (direct) {
+ ctx.globalAlpha = opacity;
+ if (nativeBlend)
+ ctx.globalCompositeOperation = blendMode;
+ } else if (transform) {
+ ctx.translate(-itemOffset.x, -itemOffset.y);
+ }
+ if (transform)
+ (direct ? matrix : getViewMatrix(globalMatrix)).applyToContext(ctx);
+ if (clip)
+ param.clipItem.draw(ctx, param.extend({ clip: true }));
+ if (strokeMatrix) {
+ ctx.setTransform(pixelRatio, 0, 0, pixelRatio, 0, 0);
+ var offset = param.offset;
+ if (offset)
+ ctx.translate(-offset.x, -offset.y);
+ }
+ this._draw(ctx, param, strokeMatrix);
+ ctx.restore();
+ matrices.pop();
+ if (param.clip && !param.dontFinish)
+ ctx.clip();
+ if (!direct) {
+ BlendMode.process(blendMode, ctx, mainCtx, opacity,
+ itemOffset.subtract(prevOffset).multiply(pixelRatio));
+ CanvasProvider.release(ctx);
+ param.offset = prevOffset;
+ }
+ },
+
+ _isUpdated: function(updateVersion) {
+ var parent = this._parent;
+ if (parent instanceof CompoundPath)
+ return parent._isUpdated(updateVersion);
+ var updated = this._updateVersion === updateVersion;
+ if (!updated && parent && parent._visible
+ && parent._isUpdated(updateVersion)) {
+ this._updateVersion = updateVersion;
+ updated = true;
+ }
+ return updated;
+ },
+
+ _drawSelection: function(ctx, matrix, size, selectedItems, updateVersion) {
+ if ((this._drawSelected || this._boundsSelected)
+ && this._isUpdated(updateVersion)) {
+ var color = this.getSelectedColor(true)
+ || this.getLayer().getSelectedColor(true),
+ mx = matrix.chain(this.getGlobalMatrix(true));
+ ctx.strokeStyle = ctx.fillStyle = color
+ ? color.toCanvasStyle(ctx) : '#009dec';
+ if (this._drawSelected)
+ this._drawSelected(ctx, mx, selectedItems);
+ if (this._boundsSelected) {
+ var half = size / 2;
+ coords = mx._transformCorners(this.getInternalBounds());
+ 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.fillRect(coords[i] - half, coords[++i] - half,
+ size, size);
+ }
+ }
+ },
+
+ _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',
+ _selectChildren: true,
+ _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 & 1026) {
+ this._clipItem = undefined;
+ }
+ },
+
+ _getClipItem: function() {
+ var clipItem = this._clipItem;
+ if (clipItem === undefined) {
+ clipItem = null;
+ for (var i = 0, l = this._children.length; i < l; i++) {
+ var child = this._children[i];
+ if (child._clipMask) {
+ clipItem = child;
+ break;
+ }
+ }
+ this._clipItem = clipItem;
+ }
+ return clipItem;
+ },
+
+ isClipped: function() {
+ return !!this._getClipItem();
+ },
+
+ setClipped: function(clipped) {
+ var child = this.getFirstChild();
+ if (child)
+ child.setClipMask(clipped);
+ },
+
+ _draw: function(ctx, param) {
+ var clip = param.clip,
+ clipItem = !clip && this._getClipItem(),
+ draw = true;
+ param = param.extend({ clipItem: clipItem, clip: false });
+ if (clip) {
+ if (this._currentPath) {
+ ctx.currentPath = this._currentPath;
+ draw = false;
+ } else {
+ ctx.beginPath();
+ param.dontStart = param.dontFinish = true;
+ }
+ } else if (clipItem) {
+ clipItem.draw(ctx, param.extend({ clip: true }));
+ }
+ if (draw) {
+ for (var i = 0, l = this._children.length; i < l; i++) {
+ var item = this._children[i];
+ if (item !== clipItem)
+ item.draw(ctx, param);
+ }
+ }
+ if (clip) {
+ this._currentPath = ctx.currentPath;
+ }
+ }
+});
+
+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(notifySelf, notifyParent) {
+ if (this._parent)
+ return _remove.base.call(this, notifySelf, notifyParent);
+ if (this._index != null) {
+ var project = this._project;
+ if (project._activeLayer === this)
+ project._activeLayer = this.getNextSibling()
+ || this.getPreviousSibling();
+ Base.splice(project.layers, null, this._index, 1);
+ this._installEvents(false);
+ if (notifySelf && project._changes)
+ this._changed(5);
+ if (notifyParent) {
+ project._needsUpdate = 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;
+ },
+
+ _insertSibling: function _insertSibling(index, item, _preserve) {
+ return !this._parent
+ ? this._project.insertChild(index, item, _preserve)
+ : _insertSibling.base.call(this, index, item, _preserve);
+ }
+});
+
+var Shape = Item.extend({
+ _class: 'Shape',
+ _applyMatrix: false,
+ _canApplyMatrix: false,
+ _boundsSelected: true,
+ _serializeFields: {
+ type: null,
+ size: null,
+ radius: null
+ },
+
+ initialize: function Shape(props) {
+ this._initialize(props);
+ },
+
+ _equals: function(item) {
+ return this._type === item._type
+ && this._size.equals(item._size)
+ && Base.equals(this._radius, item._radius);
+ },
+
+ clone: function(insert) {
+ var copy = new Shape(Item.NO_INSERT);
+ copy.setType(this._type);
+ copy.setSize(this._size);
+ copy.setRadius(this._radius);
+ return this._clone(copy, insert);
+ },
+
+ getType: function() {
+ return this._type;
+ },
+
+ setType: function(type) {
+ this._type = type;
+ },
+
+ getShape: '#getType',
+ setShape: '#setType',
+
+ 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) {
+ this._size = size.clone();
+ } else if (!this._size.equals(size)) {
+ var type = this._type,
+ width = size.width,
+ height = size.height;
+ if (type === 'rectangle') {
+ var radius = Size.min(this._radius, size.divide(2));
+ this._radius.set(radius.width, radius.height);
+ } else if (type === 'circle') {
+ width = height = (width + height) / 2;
+ this._radius = width / 2;
+ } else if (type === 'ellipse') {
+ this._radius.set(width / 2, height / 2);
+ }
+ this._size.set(width, height);
+ this._changed(9);
+ }
+ },
+
+ getRadius: function() {
+ var rad = this._radius;
+ return this._type === 'circle'
+ ? rad
+ : new LinkedSize(rad.width, rad.height, this, 'setRadius');
+ },
+
+ setRadius: function(radius) {
+ var type = this._type;
+ if (type === '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) {
+ this._radius = radius.clone();
+ } else {
+ if (this._radius.equals(radius))
+ return;
+ this._radius.set(radius.width, radius.height);
+ if (type === 'rectangle') {
+ var size = Size.max(this._size, radius.multiply(2));
+ this._size.set(size.width, size.height);
+ } else if (type === 'ellipse') {
+ this._size.set(radius.width * 2, radius.height * 2);
+ }
+ }
+ }
+ this._changed(9);
+ },
+
+ isEmpty: function() {
+ return false;
+ },
+
+ toPath: function(insert) {
+ var path = this._clone(new Path[Base.capitalize(this._type)]({
+ center: new Point(),
+ size: this._size,
+ radius: this._radius,
+ insert: false
+ }), insert);
+ if (paper.settings.applyMatrix)
+ path.setApplyMatrix(true);
+ return path;
+ },
+
+ _draw: function(ctx, param, strokeMatrix) {
+ var style = this._style,
+ hasFill = style.hasFill(),
+ hasStroke = style.hasStroke(),
+ dontPaint = param.dontFinish || param.clip,
+ untransformed = !strokeMatrix;
+ if (hasFill || hasStroke || dontPaint) {
+ var type = this._type,
+ radius = this._radius,
+ isCircle = type === 'circle';
+ if (!param.dontStart)
+ ctx.beginPath();
+ if (untransformed && isCircle) {
+ ctx.arc(0, 0, radius, 0, Math.PI * 2, true);
+ } else {
+ var rx = isCircle ? radius : radius.width,
+ ry = isCircle ? radius : radius.height,
+ size = this._size,
+ width = size.width,
+ height = size.height;
+ if (untransformed && type === 'rectangle' && rx === 0 && ry === 0) {
+ ctx.rect(-width / 2, -height / 2, width, height);
+ } else {
+ var x = width / 2,
+ y = height / 2,
+ kappa = 1 - 0.5522847498307936,
+ cx = rx * kappa,
+ cy = ry * kappa,
+ c = [
+ -x, -y + ry,
+ -x, -y + cy,
+ -x + cx, -y,
+ -x + rx, -y,
+ x - rx, -y,
+ x - cx, -y,
+ x, -y + cy,
+ x, -y + ry,
+ x, y - ry,
+ x, y - cy,
+ x - cx, y,
+ x - rx, y,
+ -x + rx, y,
+ -x + cx, y,
+ -x, y - cy,
+ -x, y - ry
+ ];
+ if (strokeMatrix)
+ strokeMatrix.transform(c, c, 32);
+ ctx.moveTo(c[0], c[1]);
+ ctx.bezierCurveTo(c[2], c[3], c[4], c[5], c[6], c[7]);
+ if (x !== rx)
+ ctx.lineTo(c[8], c[9]);
+ ctx.bezierCurveTo(c[10], c[11], c[12], c[13], c[14], c[15]);
+ if (y !== ry)
+ ctx.lineTo(c[16], c[17]);
+ ctx.bezierCurveTo(c[18], c[19], c[20], c[21], c[22], c[23]);
+ if (x !== rx)
+ ctx.lineTo(c[24], c[25]);
+ ctx.bezierCurveTo(c[26], c[27], c[28], c[29], c[30], c[31]);
+ }
+ }
+ ctx.closePath();
+ }
+ if (!dontPaint && (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._type === '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;
+ }
+ },
+
+ _hitTestSelf: function _hitTestSelf(point, options) {
+ var hit = false;
+ if (this.hasStroke()) {
+ var type = this._type,
+ radius = this._radius,
+ strokeWidth = this.getStrokeWidth() + 2 * options.tolerance;
+ if (type === '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 (type === 'ellipse')
+ radius = getEllipseRadius(point, radius);
+ hit = 2 * Math.abs(point.getLength() - radius)
+ <= strokeWidth;
+ }
+ }
+ return hit
+ ? new HitResult('stroke', this)
+ : _hitTestSelf.base.apply(this, arguments);
+ }
+ };
+}, {
+
+statics: new function() {
+ function createShape(type, point, size, radius, args) {
+ var item = new Shape(Base.getNamed(args));
+ item._type = type;
+ item._size = size;
+ item._radius = radius;
+ return item.translate(point);
+ }
+
+ 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',
+ _applyMatrix: false,
+ _canApplyMatrix: false,
+ _boundsGetter: 'getBounds',
+ _boundsSelected: true,
+ _serializeFields: {
+ crossOrigin: null,
+ 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();
+ this._loaded = false;
+ }
+ },
+
+ _equals: function(item) {
+ return this.getSource() === item.getSource();
+ },
+
+ clone: function(insert) {
+ var copy = new Raster(Item.NO_INSERT),
+ image = this._image,
+ canvas = this._canvas;
+ if (image) {
+ copy.setImage(image);
+ } else if (canvas) {
+ var copyCanvas = CanvasProvider.getCanvas(this._size);
+ copyCanvas.getContext('2d').drawImage(canvas, 0, 0);
+ copy.setImage(copyCanvas);
+ }
+ copy._crossOrigin = this._crossOrigin;
+ return this._clone(copy, insert);
+ },
+
+ getSize: function() {
+ var size = this._size;
+ return new LinkedSize(size ? size.width : 0, size ? size.height : 0,
+ this, 'setSize');
+ },
+
+ setSize: function() {
+ var size = Size.read(arguments);
+ if (!size.equals(this._size)) {
+ if (size.width > 0 && size.height > 0) {
+ var element = this.getElement();
+ this.setImage(CanvasProvider.getCanvas(size));
+ if (element)
+ this.getContext(true).drawImage(element, 0, 0,
+ size.width, size.height);
+ } else {
+ if (this._canvas)
+ CanvasProvider.release(this._canvas);
+ this._size = size.clone();
+ }
+ }
+ },
+
+ getWidth: function() {
+ return this._size ? this._size.width : 0;
+ },
+
+ setWidth: function(width) {
+ this.setSize(width, this.getHeight());
+ },
+
+ getHeight: function() {
+ return this._size ? this._size.height : 0;
+ },
+
+ setHeight: function(height) {
+ this.setSize(this.getWidth(), height);
+ },
+
+ isEmpty: function() {
+ var size = this._size;
+ return !size || size.width === 0 && size.height === 0;
+ },
+
+ getResolution: 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()
+ );
+ },
+
+ getPpi: '#getResolution',
+
+ getImage: function() {
+ return this._image;
+ },
+
+ setImage: function(image) {
+ if (this._canvas)
+ CanvasProvider.release(this._canvas);
+ if (image && image.getContext) {
+ this._image = null;
+ this._canvas = image;
+ this._loaded = true;
+ } else {
+ this._image = image;
+ this._canvas = null;
+ this._loaded = image && image.complete;
+ }
+ this._size = new Size(
+ image ? image.naturalWidth || image.width : 0,
+ image ? image.naturalHeight || image.height : 0);
+ this._context = null;
+ this._changed(521);
+ },
+
+ 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(modify) {
+ if (!this._context)
+ this._context = this.getCanvas().getContext('2d');
+ if (modify) {
+ this._image = null;
+ this._changed(513);
+ }
+ 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,
+ crossOrigin = this._crossOrigin,
+ image;
+
+ function loaded() {
+ var view = that.getView();
+ if (view) {
+ paper = view._scope;
+ that.setImage(image);
+ that.emit('load');
+ view.update();
+ }
+ }
+
+ image = document.getElementById(src) || new Image();
+ if (crossOrigin)
+ image.crossOrigin = crossOrigin;
+ if (image.naturalWidth && image.naturalHeight) {
+ setTimeout(loaded, 0);
+ } else {
+ DomEvent.add(image, { load: loaded });
+ if (!image.src)
+ image.src = src;
+ }
+ this.setImage(image);
+ },
+
+ getCrossOrigin: function() {
+ return this._image && this._image.crossOrigin || this._crossOrigin || '';
+ },
+
+ setCrossOrigin: function(crossOrigin) {
+ this._crossOrigin = crossOrigin;
+ if (this._image)
+ this._image.crossOrigin = crossOrigin;
+ },
+
+ getElement: function() {
+ return this._canvas || this._loaded && this._image;
+ }
+}, {
+ beans: false,
+
+ getSubCanvas: function() {
+ var rect = Rectangle.read(arguments),
+ 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() {
+ var rect = Rectangle.read(arguments),
+ raster = new Raster(Item.NO_INSERT);
+ raster.setImage(this.getSubCanvas(rect));
+ 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 ) {
+ var 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, matrices: [matrix] }));
+ this._matrix.applyToContext(ctx);
+ var element = this.getElement(),
+ size = this._size;
+ if (element)
+ ctx.drawImage(element, -size.width / 2, -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() {
+ var 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() {
+ var size = Size.read(arguments);
+ return this.getContext().createImageData(size.width, size.height);
+ },
+
+ getImageData: function() {
+ var 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 ) {
+ var 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;
+ },
+
+ _hitTestSelf: 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',
+ _applyMatrix: false,
+ _canApplyMatrix: 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) {
+ this._symbol = symbol;
+ this._changed(9);
+ },
+
+ clone: function(insert) {
+ var copy = new PlacedSymbol(Item.NO_INSERT);
+ copy.setSymbol(this._symbol);
+ return this._clone(copy, insert);
+ },
+
+ isEmpty: function() {
+ return this._symbol._definition.isEmpty();
+ },
+
+ _getBounds: function(getter, matrix, cacheItem) {
+ var definition = this.symbol._definition;
+ return definition._getCachedBounds(getter,
+ matrix && matrix.chain(definition._matrix), cacheItem);
+ },
+
+ _hitTestSelf: function(point, options) {
+ var res = this._symbol._definition._hitTest(point, options);
+ if (res)
+ res.item = this;
+ return res;
+ },
+
+ _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 new Base({
+ type: null,
+ tolerance: paper.settings.hitTolerance,
+ fill: !options,
+ stroke: !options,
+ segments: !options,
+ handles: false,
+ ends: false,
+ center: false,
+ bounds: false,
+ guides: false,
+ selected: false
+ }, options);
+ }
+ }
+});
+
+var Segment = Base.extend({
+ _class: 'Segment',
+ beans: true,
+
+ 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.isStraight() ? this._point
+ : [this._point, this._handleIn, this._handleOut],
+ options, true);
+ },
+
+ _changed: function(point) {
+ var path = this._path;
+ if (!path)
+ return;
+ var curves = path._curves,
+ index = this._index,
+ curve;
+ if (curves) {
+ if ((!point || point === this._point || point === this._handleIn)
+ && (curve = index > 0 ? curves[index - 1] : path._closed
+ ? curves[curves.length - 1] : null))
+ curve._changed();
+ if ((!point || point === this._point || point === this._handleOut)
+ && (curve = curves[index]))
+ curve._changed();
+ }
+ path._changed(25);
+ },
+
+ getPoint: function() {
+ return this._point;
+ },
+
+ setPoint: function() {
+ var point = Point.read(arguments);
+ this._point.set(point.x, point.y);
+ },
+
+ getHandleIn: function() {
+ return this._handleIn;
+ },
+
+ setHandleIn: function() {
+ var point = Point.read(arguments);
+ this._handleIn.set(point.x, point.y);
+ },
+
+ getHandleOut: function() {
+ return this._handleOut;
+ },
+
+ setHandleOut: function() {
+ var point = Point.read(arguments);
+ this._handleOut.set(point.x, point.y);
+ },
+
+ hasHandles: function() {
+ return !this.isStraight();
+ },
+
+ isStraight: function() {
+ return this._handleIn.isZero() && this._handleOut.isZero();
+ },
+
+ isLinear: function() {
+ return Segment.isLinear(this, this.getNext());
+ },
+
+ isCollinear: function(segment) {
+ return Segment.isCollinear(this, this.getNext(),
+ segment, segment.getNext());
+ },
+
+ isColinear: '#isCollinear',
+
+ isOrthogonal: function() {
+ return Segment.isOrthogonal(this.getPrevious(), this, this.getNext());
+ },
+
+ isOrthogonalArc: function() {
+ return Segment.isOrthogonalArc(this, this.getNext());
+ },
+
+ isArc: '#isOrthogonalArc',
+
+ _selectionState: 0,
+
+ isSelected: function(_point) {
+ var state = this._selectionState;
+ return !_point ? !!(state & 7)
+ : _point === this._point ? !!(state & 4)
+ : _point === this._handleIn ? !!(state & 1)
+ : _point === this._handleOut ? !!(state & 2)
+ : false;
+ },
+
+ setSelected: function(selected, _point) {
+ var path = this._path,
+ selected = !!selected,
+ state = this._selectionState,
+ oldState = state,
+ flag = !_point ? 7
+ : _point === this._point ? 4
+ : _point === this._handleIn ? 1
+ : _point === this._handleOut ? 2
+ : 0;
+ if (selected) {
+ state |= flag;
+ } else {
+ state &= ~flag;
+ }
+ this._selectionState = state;
+ if (path && state !== oldState) {
+ path._updateSelection(this, oldState, state);
+ path._changed(129);
+ }
+ },
+
+ 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 (index > 0 && !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, this === curve._segment1 ? 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(', ') + ' }';
+ },
+
+ transform: function(matrix) {
+ this._transformCoordinates(matrix, new Array(6), true);
+ this._changed();
+ },
+
+ _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, coords, 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;
+ },
+
+ statics: {
+
+ isLinear: function(seg1, seg2) {
+ var l = seg2._point.subtract(seg1._point);
+ return l.isCollinear(seg1._handleOut)
+ && l.isCollinear(seg2._handleIn);
+ },
+
+ isCollinear: function(seg1, seg2, seg3, seg4) {
+ return seg1._handleOut.isZero() && seg2._handleIn.isZero()
+ && seg3._handleOut.isZero() && seg4._handleIn.isZero()
+ && seg2._point.subtract(seg1._point).isCollinear(
+ seg4._point.subtract(seg3._point));
+ },
+
+ isOrthogonal: function(seg1, seg2, seg3) {
+ return seg1._handleOut.isZero() && seg2._handleIn.isZero()
+ && seg2._handleOut.isZero() && seg3._handleIn.isZero()
+ && seg2._point.subtract(seg1._point).isOrthogonal(
+ seg3._point.subtract(seg2._point));
+ },
+
+ isOrthogonalArc: function(seg1, seg2) {
+ var handle1 = seg1._handleOut,
+ handle2 = seg2._handleIn,
+ kappa = 0.5522847498307936;
+ if (handle1.isOrthogonal(handle2)) {
+ var pt1 = seg1._point,
+ pt2 = seg2._point,
+ corner = new Line(pt1, handle1, true).intersect(
+ new Line(pt2, handle2, true), true);
+ return corner && Numerical.isZero(handle1.getLength() /
+ corner.subtract(pt1).getLength() - kappa)
+ && Numerical.isZero(handle2.getLength() /
+ corner.subtract(pt2).getLength() - kappa);
+ }
+ return false;
+ },
+ }
+});
+
+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 {
+ var pt = point;
+ if ((x = pt.x) === undefined) {
+ pt = Point.read(arguments);
+ x = pt.x;
+ }
+ y = pt.y;
+ selected = pt.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(selected, this);
+ },
+
+ 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() {
+ this._length = this._bounds = undefined;
+ },
+
+ getPoint1: function() {
+ return this._segment1._point;
+ },
+
+ setPoint1: function() {
+ var point = Point.read(arguments);
+ this._segment1._point.set(point.x, point.y);
+ },
+
+ getPoint2: function() {
+ return this._segment2._point;
+ },
+
+ setPoint2: function() {
+ var point = Point.read(arguments);
+ this._segment2._point.set(point.x, point.y);
+ },
+
+ getHandle1: function() {
+ return this._segment1._handleOut;
+ },
+
+ setHandle1: function() {
+ var point = Point.read(arguments);
+ this._segment1._handleOut.set(point.x, point.y);
+ },
+
+ getHandle2: function() {
+ return this._segment2._handleIn;
+ },
+
+ setHandle2: function() {
+ var 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.getPoint1().isSelected()
+ && this.getHandle2().isSelected()
+ && this.getHandle2().isSelected()
+ && this.getPoint2().isSelected();
+ },
+
+ setSelected: function(selected) {
+ this.getPoint1().setSelected(selected);
+ this.getHandle1().setSelected(selected);
+ this.getHandle2().setSelected(selected);
+ this.getPoint2().setSelected(selected);
+ },
+
+ getValues: function(matrix) {
+ return Curve.getValues(this._segment1, this._segment2, matrix);
+ },
+
+ 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() {
+ if (this._length == null) {
+ this._length = this.isLinear()
+ ? this._segment2._point.getDistance(this._segment1._point)
+ : Curve.getLength(this.getValues(), 0, 1);
+ }
+ return this._length;
+ },
+
+ getArea: function() {
+ return Curve.getArea(this.getValues());
+ },
+
+ getPart: function(from, to) {
+ return new Curve(Curve.getPart(this.getValues(), from, to));
+ },
+
+ getPartLength: function(from, to) {
+ return Curve.getLength(this.getValues(), from, to);
+ },
+
+ hasHandles: function() {
+ return !this._segment1._handleOut.isZero()
+ || !this._segment2._handleIn.isZero();
+ },
+
+ isLinear: function() {
+ return Segment.isLinear(this._segment1, this._segment2);
+ },
+
+ isCollinear: function(curve) {
+ return Ssegment.isCollinear(this._segment1, this._segment2,
+ curve._segment1, curve._segment2);
+ },
+
+ isOrthogonalArc: function() {
+ return Segment.isOrthogonalArc(this._segment1, this._segment2);
+ },
+
+ getIntersections: function(curve) {
+ return Curve.filterIntersections(Curve.getIntersections(
+ this.getValues(), curve.getValues(), this, curve, []));
+ },
+
+ _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, ignoreLinear) {
+ var parameter = this._getParameter(offset, isParameter),
+ tolerance = 0.000001,
+ res = null;
+ if (parameter > tolerance && parameter < 1 - tolerance) {
+ var parts = Curve.subdivide(this.getValues(), parameter),
+ isLinear = ignoreLinear ? false : 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;
+ },
+
+ reverse: function() {
+ return new Curve(this._segment2.reverse(), this._segment1.reverse());
+ },
+
+ remove: function() {
+ var removed = false;
+ if (this._path) {
+ var segment2 = this._segment2,
+ handleOut = segment2._handleOut;
+ removed = segment2.remove();
+ if (removed)
+ this._segment1._handleOut.set(handleOut.x, handleOut.y);
+ }
+ return removed;
+ },
+
+ 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, matrix) {
+ var p1 = segment1._point,
+ h1 = segment1._handleOut,
+ h2 = segment2._handleIn,
+ p2 = segment2._point,
+ values = [
+ p1._x, p1._y,
+ p1._x + h1._x, p1._y + h1._y,
+ p2._x + h2._x, p2._y + h2._y,
+ p2._x, p2._y
+ ];
+ if (matrix)
+ matrix._transformCoordinates(values, values, 4);
+ return values;
+ },
+
+ 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) {
+ var tolerance = 0.000001;
+ if (Math.abs(v[0] - x) < tolerance && Math.abs(v[1] - y) < tolerance)
+ return 0;
+ if (Math.abs(v[6] - x) < tolerance && Math.abs(v[7] - y) < tolerance)
+ return 1;
+ var txs = [],
+ tys = [],
+ sx = Curve.solveCubic(v, 0, x, txs, 0, 1),
+ sy = Curve.solveCubic(v, 1, y, tys, 0, 1),
+ 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) < tolerance)
+ 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;
+ },
+
+ hasHandles: 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]));
+ },
+
+ isLinear: function(v) {
+ var p1x = v[0], p1y = v[1],
+ p2x = v[6], p2y = v[7],
+ l = new Point(p2x - p1x, p2y - p1y);
+ return l.isCollinear(new Point(v[2] - p1x, v[3] - p1y))
+ && l.isCollinear(new Point(v[4] - p2x, v[5] - p2y));
+ },
+
+ 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;
+ },
+
+ getEdgeSum: function(v) {
+ return (v[0] - v[2]) * (v[3] + v[1])
+ + (v[2] - v[4]) * (v[5] + v[3])
+ + (v[4] - v[6]) * (v[7] + v[5]);
+ },
+
+ 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.000001,
+ 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);
+ }
+ }
+}}, 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();
+ };
+ },
+{
+
+}), {
+ beans: false,
+
+ getParameterAt: function(offset, start) {
+ return Curve.getParameterAt(this.getValues(), offset, start);
+ },
+
+ getParameterOf: function() {
+ var point = Point.read(arguments);
+ return Curve.getParameterOf(this.getValues(), point.x, point.y);
+ },
+
+ getLocationAt: function(offset, isParameter) {
+ var t = isParameter ? offset : this.getParameterAt(offset);
+ return t != null && t >= 0 && t <= 1
+ ? new CurveLocation(this, t)
+ : null;
+ },
+
+ getLocationOf: function() {
+ return this.getLocationAt(this.getParameterOf(Point.read(arguments)),
+ true);
+ },
+
+ getOffsetOf: function() {
+ var loc = this.getLocationOf.apply(this, arguments);
+ return loc ? loc.getOffset() : null;
+ },
+
+ getNearestLocation: function() {
+ var point = Point.read(arguments),
+ values = this.getValues(),
+ count = 100,
+ minDist = Infinity,
+ minT = 0;
+
+ function refine(t) {
+ if (t >= 0 && t <= 1) {
+ var dist = point.getDistance(Curve.getPoint(values, t), 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 > 0.000001) {
+ if (!refine(minT - step) && !refine(minT + step))
+ step /= 2;
+ }
+ var pt = Curve.getPoint(values, minT);
+ return new CurveLocation(this, minT, pt, null, null, null,
+ point.getDistance(pt));
+ },
+
+ getNearestPoint: function() {
+ return this.getNearestLocation.apply(this, arguments).getPoint();
+ }
+
+},
+new function() {
+ var methods = ['getPoint', 'getTangent', 'getNormal', 'getWeightedTangent',
+ 'getWeightedNormal', 'getCurvature'];
+ return Base.each(methods,
+ function(name) {
+ this[name + 'At'] = function(offset, isParameter) {
+ var values = this.getValues();
+ return Curve[name](values, isParameter ? offset
+ : Curve.getParameterAt(values, offset, 0));
+ };
+ }, {
+ statics: {
+ evaluateMethods: methods
+ }
+ })
+},
+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)));
+ }
+
+ function evaluate(v, t, type, normalized) {
+ if (t == null || t < 0 || t > 1)
+ return null;
+ 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],
+ tolerance = 0.000001,
+ x, y;
+
+ if (type === 0 && (t < tolerance || t > 1 - tolerance)) {
+ var isZero = t < tolerance;
+ x = isZero ? p1x : p2x;
+ y = isZero ? 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 {
+ if (t < tolerance) {
+ x = cx;
+ y = cy;
+ } else if (t > 1 - tolerance) {
+ x = 3 * (p2x - c2x);
+ y = 3 * (p2y - c2y);
+ } else {
+ x = (3 * ax * t + 2 * bx) * t + cx;
+ y = (3 * ay * t + 2 * by) * t + cy;
+ }
+ if (normalized) {
+ if (x === 0 && y === 0
+ && (t < tolerance || t > 1 - tolerance)) {
+ x = c2x - c1x;
+ y = c2y - c1y;
+ }
+ var len = Math.sqrt(x * x + y * y);
+ x /= len;
+ y /= len;
+ }
+ if (type === 3) {
+ var x2 = 6 * ax * t + 2 * bx,
+ y2 = 6 * ay * t + 2 * by,
+ d = Math.pow(x * x + y * y, 3 / 2);
+ x = d !== 0 ? (x * y2 - y * x2) / d : 0;
+ y = 0;
+ }
+ }
+ }
+ return type === 2 ? new Point(y, -x) : new Point(x, y);
+ }
+
+ return {
+ statics: true,
+
+ getLength: function(v, a, b) {
+ if (a === undefined)
+ a = 0;
+ if (b === undefined)
+ b = 1;
+ var isZero = Numerical.isZero;
+ if (a === 0 && b === 1
+ && 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 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 (start === undefined)
+ start = offset < 0 ? 1 : 0
+ if (offset === 0)
+ return start;
+ var tolerance = 0.000001,
+ abs = Math.abs,
+ forward = offset > 0,
+ a = forward ? start : 0,
+ b = forward ? 1 : start,
+ ds = getLengthIntegrand(v),
+ rangeLength = Numerical.integrate(ds, a, b,
+ getIterations(a, b));
+ if (abs(offset - rangeLength) < tolerance) {
+ return forward ? b : a;
+ } else if (abs(offset) > rangeLength) {
+ return null;
+ }
+ var guess = offset / rangeLength,
+ length = 0;
+ function f(t) {
+ length += Numerical.integrate(ds, start, t,
+ getIterations(start, t));
+ start = t;
+ return length - offset;
+ }
+ return Numerical.findRoot(f, ds, start + guess, a, b, 16,
+ tolerance);
+ },
+
+ getPoint: function(v, t) {
+ return evaluate(v, t, 0, false);
+ },
+
+ getTangent: function(v, t) {
+ return evaluate(v, t, 1, true);
+ },
+
+ getWeightedTangent: function(v, t) {
+ return evaluate(v, t, 1, false);
+ },
+
+ getNormal: function(v, t) {
+ return evaluate(v, t, 2, true);
+ },
+
+ getWeightedNormal: function(v, t) {
+ return evaluate(v, t, 2, false);
+ },
+
+ getCurvature: function(v, t) {
+ return evaluate(v, t, 3, false).x;
+ }
+ };
+}, new function() {
+ function addLocation(locations, include, curve1, t1, point1, curve2, t2,
+ point2) {
+ var loc = new CurveLocation(curve1, t1, point1, curve2, t2, point2);
+ if (!include || include(loc))
+ locations.push(loc);
+ }
+
+ function addCurveIntersections(v1, v2, curve1, curve2, locations, include,
+ tMin, tMax, uMin, uMax, oldTDiff, reverse, recursion) {
+ if (recursion > 32)
+ return;
+ var q0x = v2[0], q0y = v2[1], q3x = v2[6], q3y = v2[7],
+ tolerance = 0.000001,
+ getSignedDistance = Line.getSignedDistance,
+ d1 = getSignedDistance(q0x, q0y, q3x, q3y, v2[2], v2[3]) || 0,
+ d2 = getSignedDistance(q0x, q0y, q3x, q3y, v2[4], v2[5]) || 0,
+ factor = d1 * d2 > 0 ? 3 / 4 : 4 / 9,
+ dMin = factor * Math.min(0, d1, d2),
+ dMax = factor * Math.max(0, d1, d2),
+ dp0 = getSignedDistance(q0x, q0y, q3x, q3y, v1[0], v1[1]),
+ dp1 = getSignedDistance(q0x, q0y, q3x, q3y, v1[2], v1[3]),
+ dp2 = getSignedDistance(q0x, q0y, q3x, q3y, v1[4], v1[5]),
+ dp3 = getSignedDistance(q0x, q0y, q3x, q3y, v1[6], v1[7]),
+ tMinNew, tMaxNew, tDiff;
+ if (q0x === q3x && uMax - uMin < tolerance && recursion > 3) {
+ tMaxNew = tMinNew = (tMax + tMin) / 2;
+ tDiff = 0;
+ } else {
+ var hull = getConvexHull(dp0, dp1, dp2, dp3),
+ top = hull[0],
+ bottom = hull[1],
+ tMinClip, tMaxClip;
+ tMinClip = clipConvexHull(top, bottom, dMin, dMax);
+ top.reverse();
+ bottom.reverse();
+ tMaxClip = clipConvexHull(top, bottom, dMin, dMax);
+ if (tMinClip == null || tMaxClip == null)
+ return;
+ v1 = Curve.getPart(v1, tMinClip, tMaxClip);
+ tDiff = tMaxClip - tMinClip;
+ tMinNew = tMax * tMinClip + tMin * (1 - tMinClip);
+ tMaxNew = tMax * tMaxClip + tMin * (1 - tMaxClip);
+ }
+ if (oldTDiff > 0.5 && tDiff > 0.5) {
+ if (tMaxNew - tMinNew > uMax - uMin) {
+ var parts = Curve.subdivide(v1, 0.5),
+ t = tMinNew + (tMaxNew - tMinNew) / 2;
+ addCurveIntersections(
+ v2, parts[0], curve2, curve1, locations, include,
+ uMin, uMax, tMinNew, t, tDiff, !reverse, ++recursion);
+ addCurveIntersections(
+ v2, parts[1], curve2, curve1, locations, include,
+ uMin, uMax, t, tMaxNew, tDiff, !reverse, recursion);
+ } else {
+ var parts = Curve.subdivide(v2, 0.5),
+ t = uMin + (uMax - uMin) / 2;
+ addCurveIntersections(
+ parts[0], v1, curve2, curve1, locations, include,
+ uMin, t, tMinNew, tMaxNew, tDiff, !reverse, ++recursion);
+ addCurveIntersections(
+ parts[1], v1, curve2, curve1, locations, include,
+ t, uMax, tMinNew, tMaxNew, tDiff, !reverse, recursion);
+ }
+ } else if (Math.max(uMax - uMin, tMaxNew - tMinNew) < tolerance) {
+ var t1 = tMinNew + (tMaxNew - tMinNew) / 2,
+ t2 = uMin + (uMax - uMin) / 2;
+ if (reverse) {
+ addLocation(locations, include,
+ curve2, t2, Curve.getPoint(v2, t2),
+ curve1, t1, Curve.getPoint(v1, t1));
+ } else {
+ addLocation(locations, include,
+ curve1, t1, Curve.getPoint(v1, t1),
+ curve2, t2, Curve.getPoint(v2, t2));
+ }
+ } else if (tDiff > 0) {
+ addCurveIntersections(v2, v1, curve2, curve1, locations, include,
+ uMin, uMax, tMinNew, tMaxNew, tDiff, !reverse, ++recursion);
+ }
+ }
+
+ 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),
+ flip = false,
+ hull;
+ if (dist1 * dist2 < 0) {
+ hull = [[p0, p1, p3], [p0, p2, p3]];
+ flip = dist1 < 0;
+ } else {
+ var pmax, cross = 0,
+ distZero = dist1 === 0 || dist2 === 0;
+ 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;
+ }
+ hull = cross < 0 || distZero
+ ? [[p0, pmax, p3], [p0, p3]]
+ : [[p0, p1, p2, p3], [p0, p3]];
+ flip = dist1 ? dist1 < 0 : dist2 < 0;
+ }
+ return flip ? hull.reverse() : hull;
+ }
+
+ function clipConvexHull(hullTop, hullBottom, dMin, dMax) {
+ if (hullTop[0][1] < dMin) {
+ return clipConvexHullPart(hullTop, true, dMin);
+ } else if (hullBottom[0][1] > dMax) {
+ return clipConvexHullPart(hullBottom, false, dMax);
+ } else {
+ return hullTop[0][0];
+ }
+ }
+
+ function clipConvexHullPart(part, top, threshold) {
+ var px = part[0][0],
+ py = part[0][1];
+ for (var i = 1, l = part.length; i < l; i++) {
+ var qx = part[i][0],
+ qy = part[i][1];
+ if (top ? qy >= threshold : qy <= threshold)
+ return px + (threshold - py) * (qx - px) / (qy - py);
+ px = qx;
+ py = qy;
+ }
+ return null;
+ }
+
+ function addCurveLineIntersections(v1, v2, curve1, curve2, locations,
+ include) {
+ 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.getPoint(rvc, tc).x;
+ if (x >= 0 && x <= rlx2) {
+ var tl = Curve.getParameterOf(rvl, x, 0),
+ t1 = flip ? tl : tc,
+ t2 = flip ? tc : tl;
+ addLocation(locations, include,
+ curve1, t1, Curve.getPoint(v1, t1),
+ curve2, t2, Curve.getPoint(v2, t2));
+ }
+ }
+ }
+
+ function addLineIntersection(v1, v2, curve1, curve2, locations, include) {
+ var point = Line.intersect(
+ v1[0], v1[1], v1[6], v1[7],
+ v2[0], v2[1], v2[6], v2[7]);
+ if (point) {
+ var x = point.x,
+ y = point.y;
+ addLocation(locations, include,
+ curve1, Curve.getParameterOf(v1, x, y), point,
+ curve2, Curve.getParameterOf(v2, x, y), point);
+ }
+ }
+
+ return { statics: {
+ getIntersections: function(v1, v2, c1, c2, locations, include) {
+ var linear1 = Curve.isLinear(v1),
+ linear2 = Curve.isLinear(v2),
+ c1p1 = c1.getPoint1(),
+ c1p2 = c1.getPoint2(),
+ c2p1 = c2.getPoint1(),
+ c2p2 = c2.getPoint2(),
+ tolerance = 0.000001;
+ if (c1p1.isClose(c2p1, tolerance))
+ addLocation(locations, include, c1, 0, c1p1, c2, 0, c1p1);
+ if (c1p1.isClose(c2p2, tolerance))
+ addLocation(locations, include, c1, 0, c1p1, c2, 1, c1p1);
+ (linear1 && linear2
+ ? addLineIntersection
+ : linear1 || linear2
+ ? addCurveLineIntersections
+ : addCurveIntersections)(
+ v1, v2, c1, c2, locations, include,
+ 0, 1, 0, 1, 0, false, 0);
+ if (c1p2.isClose(c2p1, tolerance))
+ addLocation(locations, include, c1, 1, c1p2, c2, 0, c1p2);
+ if (c1p2.isClose(c2p2, tolerance))
+ addLocation(locations, include, c1, 1, c1p2, c2, 1, c1p2);
+ return locations;
+ },
+
+ filterIntersections: function(locations, _expand) {
+ var last = locations.length - 1,
+ tMax = 1 - 0.000001;
+ for (var i = last; i >= 0; i--) {
+ var loc = locations[i],
+ next = loc._curve.getNext(),
+ next2 = loc._curve2.getNext();
+ if (next && loc._parameter >= tMax) {
+ loc._parameter = 0;
+ loc._curve = next;
+ }
+ if (next2 && loc._parameter2 >= tMax) {
+ loc._parameter2 = 0;
+ loc._curve2 = next2;
+ }
+ }
+
+ function compare(loc1, loc2) {
+ var path1 = loc1.getPath(),
+ path2 = loc2.getPath();
+ return path1 === path2
+ ? (loc1.getIndex() + loc1.getParameter())
+ - (loc2.getIndex() + loc2.getParameter())
+ : path1._id - path2._id;
+ }
+
+ if (last > 0) {
+ locations.sort(compare);
+ for (var i = last; i > 0; i--) {
+ if (locations[i].equals(locations[i - 1])) {
+ locations.splice(i, 1);
+ last--;
+ }
+ }
+ }
+ if (_expand) {
+ for (var i = last; i >= 0; i--)
+ locations.push(locations[i].getIntersection());
+ locations.sort(compare);
+ }
+ return locations;
+ }
+ }};
+});
+
+var CurveLocation = Base.extend({
+ _class: 'CurveLocation',
+ beans: true,
+
+ initialize: function CurveLocation(curve, parameter, point, _curve2,
+ _parameter2, _point2, _distance) {
+ this._id = UID.get(CurveLocation);
+ var path = curve._path;
+ this._version = path ? path._version : 0;
+ this._curve = curve;
+ this._parameter = parameter;
+ this._point = point || curve.getPointAt(parameter, true);
+ this._curve2 = _curve2;
+ this._parameter2 = _parameter2;
+ this._point2 = _point2;
+ this._distance = _distance;
+ this._segment1 = curve._segment1;
+ this._segment2 = curve._segment2;
+ },
+
+ getSegment: function(_preferFirst) {
+ if (!this._segment) {
+ var curve = this.getCurve(),
+ parameter = this.getParameter();
+ if (parameter === 1) {
+ this._segment = curve._segment2;
+ } else if (parameter === 0 || _preferFirst) {
+ this._segment = curve._segment1;
+ } else if (parameter == null) {
+ return null;
+ } else {
+ this._segment = curve.getPartLength(0, parameter)
+ < curve.getPartLength(parameter, 1)
+ ? curve._segment1
+ : curve._segment2;
+ }
+ }
+ return this._segment;
+ },
+
+ getCurve: function() {
+ var curve = this._curve,
+ path = curve && curve._path;
+ if (path && path._version !== this._version) {
+ curve = null;
+ this._parameter = null;
+ }
+ if (!curve) {
+ curve = this._segment1.getCurve();
+ if (curve.getParameterOf(this._point) == null)
+ curve = this._segment2.getPrevious().getCurve();
+ this._curve = curve;
+ path = curve._path;
+ this._version = path ? path._version : 0;
+ }
+ return curve;
+ },
+
+ getPath: function() {
+ var curve = this.getCurve();
+ return curve && curve._path;
+ },
+
+ getIndex: function() {
+ var curve = this.getCurve();
+ return curve && curve.getIndex();
+ },
+
+ getParameter: function() {
+ var curve = this.getCurve(),
+ parameter = this._parameter;
+ return curve && parameter == null
+ ? this._parameter = curve.getParameterOf(this._point)
+ : parameter;
+ },
+
+ getPoint: function() {
+ return this._point;
+ },
+
+ getOffset: function() {
+ var path = this.getPath();
+ return path ? path._getOffset(this) : this.getCurveOffset();
+ },
+
+ getCurveOffset: function() {
+ var curve = this.getCurve(),
+ parameter = this.getParameter();
+ return parameter != null && curve && curve.getPartLength(0, parameter);
+ },
+
+ getIntersection: function() {
+ var intersection = this._intersection;
+ if (!intersection && this._curve2) {
+ this._intersection = intersection = new CurveLocation(this._curve2,
+ this._parameter2, this._point2 || this._point, this);
+ intersection._intersection = this;
+ }
+ return intersection;
+ },
+
+ getDistance: function() {
+ return this._distance;
+ },
+
+ divide: function() {
+ var curve = this.getCurve();
+ return curve && curve.divide(this.getParameter(), true);
+ },
+
+ split: function() {
+ var curve = this.getCurve();
+ return curve && curve.split(this.getParameter(), true);
+ },
+
+ equals: function(loc) {
+ var abs = Math.abs,
+ tolerance = 0.000001;
+ return this === loc
+ || loc instanceof CurveLocation
+ && this.getCurve() === loc.getCurve()
+ && abs(this.getParameter() - loc.getParameter()) < tolerance
+ && this._curve2 === loc._curve2
+ && abs(this._parameter2 - loc._parameter2) < tolerance
+ || false;
+ },
+
+ 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(', ') + ' }';
+ }
+}, Base.each(Curve.evaluateMethods, function(name) {
+ if (name !== 'getPoint') {
+ var get = name + 'At';
+ this[name] = function() {
+ var parameter = this.getParameter(),
+ curve = this.getCurve();
+ return parameter != null && curve && curve[get](parameter, true);
+ };
+ }
+}, {}));
+
+var PathItem = Item.extend({
+ _class: 'PathItem',
+
+ initialize: function PathItem() {
+ },
+
+ getIntersections: function(path, _matrix, _expand) {
+ if (this === path)
+ path = null;
+ var locations = [],
+ curves1 = this.getCurves(),
+ curves2 = path ? path.getCurves() : curves1,
+ matrix1 = this._matrix.orNullIfIdentity(),
+ matrix2 = path ? (_matrix || path._matrix).orNullIfIdentity()
+ : matrix1,
+ length1 = curves1.length,
+ length2 = path ? curves2.length : length1,
+ values2 = [],
+ tMin = 0.000001,
+ tMax = 1 - tMin;
+ if (path && !this.getBounds(matrix1).touches(path.getBounds(matrix2)))
+ return [];
+ for (var i = 0; i < length2; i++)
+ values2[i] = curves2[i].getValues(matrix2);
+ for (var i = 0; i < length1; i++) {
+ var curve1 = curves1[i],
+ values1 = path ? curve1.getValues(matrix1) : values2[i];
+ if (!path) {
+ var seg1 = curve1.getSegment1(),
+ seg2 = curve1.getSegment2(),
+ h1 = seg1._handleOut,
+ h2 = seg2._handleIn;
+ if (new Line(seg1._point.subtract(h1), h1.multiply(2), true)
+ .intersect(new Line(seg2._point.subtract(h2),
+ h2.multiply(2), true), false)) {
+ var parts = Curve.subdivide(values1);
+ Curve.getIntersections(
+ parts[0], parts[1], curve1, curve1, locations,
+ function(loc) {
+ if (loc._parameter <= tMax) {
+ loc._parameter /= 2;
+ loc._parameter2 = 0.5 + loc._parameter2 / 2;
+ return true;
+ }
+ }
+ );
+ }
+ }
+ for (var j = path ? 0 : i + 1; j < length2; j++) {
+ Curve.getIntersections(
+ values1, values2[j], curve1, curves2[j], locations,
+ !path && (j === i + 1 || j === length2 - 1 && i === 0)
+ && function(loc) {
+ var t = loc._parameter;
+ return t >= tMin && t <= tMax;
+ }
+ );
+ }
+ }
+ return Curve.filterIntersections(locations, _expand);
+ },
+
+ _asPathItem: function() {
+ return this;
+ },
+
+ setPathData: function(data) {
+
+ var parts = data.match(/[mlhvcsqtaz][^mlhvcsqtaz]*/ig),
+ coords,
+ relative = false,
+ previous,
+ control,
+ current = new Point(),
+ start = new Point();
+
+ function getCoord(index, coord) {
+ var val = +coords[index];
+ if (relative)
+ val += current[coord];
+ return val;
+ }
+
+ function getPoint(index) {
+ return new Point(
+ getCoord(index, 'x'),
+ getCoord(index + 1, 'y')
+ );
+ }
+
+ this.clear();
+
+ for (var i = 0, l = parts && parts.length; i < l; i++) {
+ var part = parts[i],
+ command = part[0],
+ lower = command.toLowerCase();
+ coords = part.match(/[+-]?(?:\d*\.\d+|\d+\.?)(?:[eE][+-]?\d+)?/g);
+ var length = coords && coords.length;
+ relative = command === lower;
+ if (previous === 'z' && !/[mz]/.test(lower))
+ this.moveTo(current = start);
+ switch (lower) {
+ case 'm':
+ case 'l':
+ var move = lower === 'm';
+ for (var j = 0; j < length; j += 2)
+ this[j === 0 && move ? 'moveTo' : 'lineTo'](
+ current = getPoint(j));
+ control = current;
+ if (move)
+ start = current;
+ break;
+ case 'h':
+ case 'v':
+ var coord = lower === 'h' ? 'x' : 'y';
+ for (var j = 0; j < length; j++) {
+ current[coord] = getCoord(j, coord);
+ this.lineTo(current);
+ }
+ control = current;
+ break;
+ case 'c':
+ for (var j = 0; j < length; j += 6) {
+ this.cubicCurveTo(
+ getPoint(j),
+ control = getPoint(j + 2),
+ current = getPoint(j + 4));
+ }
+ break;
+ case 's':
+ for (var j = 0; j < length; j += 4) {
+ this.cubicCurveTo(
+ /[cs]/.test(previous)
+ ? current.multiply(2).subtract(control)
+ : current,
+ control = getPoint(j),
+ current = getPoint(j + 2));
+ previous = lower;
+ }
+ break;
+ case 'q':
+ for (var j = 0; j < length; j += 4) {
+ this.quadraticCurveTo(
+ control = getPoint(j),
+ current = getPoint(j + 2));
+ }
+ break;
+ case 't':
+ for (var j = 0; j < length; j += 2) {
+ this.quadraticCurveTo(
+ control = (/[qt]/.test(previous)
+ ? current.multiply(2).subtract(control)
+ : current),
+ current = getPoint(j));
+ previous = lower;
+ }
+ break;
+ case 'a':
+ for (var j = 0; j < length; j += 7) {
+ this.arcTo(current = getPoint(j + 5),
+ new Size(+coords[j], +coords[j + 1]),
+ +coords[j + 2], +coords[j + 4], +coords[j + 3]);
+ }
+ break;
+ case 'z':
+ this.closePath(true);
+ break;
+ }
+ previous = lower;
+ }
+ },
+
+ _canComposite: function() {
+ return !(this.hasFill() && this.hasStroke());
+ },
+
+ _contains: function(point) {
+ var winding = this._getWinding(point, false, true);
+ 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 = [];
+ this._version = 0;
+ var segments = Array.isArray(arg)
+ ? typeof arg[0] === 'object'
+ ? arg
+ : arguments
+ : arg && (arg.size === undefined && (arg.x !== undefined
+ || arg.point !== undefined))
+ ? arguments
+ : null;
+ if (segments && segments.length > 0) {
+ this.setSegments(segments);
+ } else {
+ this._curves = undefined;
+ this._selectedSegmentState = 0;
+ if (!segments && typeof arg === 'string') {
+ this.setPathData(arg);
+ arg = null;
+ }
+ }
+ this._initialize(!segments && arg);
+ },
+
+ _equals: function(item) {
+ return this._closed === item._closed
+ && Base.equals(this._segments, item._segments);
+ },
+
+ clone: function(insert) {
+ var copy = new Path(Item.NO_INSERT);
+ copy.setSegments(this._segments);
+ copy._closed = this._closed;
+ if (this._clockwise !== undefined)
+ copy._clockwise = this._clockwise;
+ return this._clone(copy, insert);
+ },
+
+ _changed: function _changed(flags) {
+ _changed.base.call(this, flags);
+ if (flags & 8) {
+ var parent = this._parent;
+ if (parent)
+ parent._currentPath = undefined;
+ this._length = this._clockwise = undefined;
+ if (flags & 16) {
+ this._version++;
+ } else if (this._curves) {
+ for (var i = 0, l = this._curves.length; i < l; i++)
+ this._curves[i]._changed();
+ }
+ this._monoCurves = undefined;
+ } else if (flags & 32) {
+ this._bounds = undefined;
+ }
+ },
+
+ getStyle: function() {
+ var parent = this._parent;
+ return (parent instanceof CompoundPath ? parent : this)._style;
+ },
+
+ getSegments: function() {
+ return this._segments;
+ },
+
+ setSegments: function(segments) {
+ var fullySelected = this.isFullySelected();
+ this._segments.length = 0;
+ this._selectedSegmentState = 0;
+ this._curves = undefined;
+ if (segments && segments.length > 0)
+ 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];
+ },
+
+ 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(25);
+ }
+ }
+}, {
+ beans: true,
+
+ getPathData: function(_matrix, _precision) {
+ var segments = this._segments,
+ length = segments.length,
+ f = new Formatter(_precision),
+ coords = new Array(6),
+ first = true,
+ curX, curY,
+ prevX, prevY,
+ inX, inY,
+ outX, outY,
+ parts = [];
+
+ function addSegment(segment, skipLine) {
+ segment._transformCoordinates(_matrix, coords, false);
+ curX = coords[0];
+ curY = coords[1];
+ if (first) {
+ parts.push('M' + f.pair(curX, curY));
+ first = false;
+ } else {
+ inX = coords[2];
+ inY = coords[3];
+ if (inX === curX && inY === curY
+ && outX === prevX && outY === prevY) {
+ if (!skipLine)
+ parts.push('l' + f.pair(curX - prevX, curY - prevY));
+ } else {
+ parts.push('c' + f.pair(outX - prevX, outY - prevY)
+ + ' ' + f.pair(inX - prevX, inY - prevY)
+ + ' ' + f.pair(curX - prevX, curY - prevY));
+ }
+ }
+ prevX = curX;
+ prevY = curY;
+ outX = coords[4];
+ outY = coords[5];
+ }
+
+ if (length === 0)
+ return '';
+
+ for (var i = 0; i < length; i++)
+ addSegment(segments[i]);
+ if (this._closed && length > 0) {
+ addSegment(segments[0], true);
+ parts.push('z');
+ }
+ return parts.join('');
+ }
+}, {
+
+ isEmpty: function() {
+ return this._segments.length === 0;
+ },
+
+ isLinear: function() {
+ var segments = this._segments;
+ for (var i = 0, l = segments.length; i < l; i++) {
+ if (!segments[i].isLinear())
+ return false;
+ }
+ return true;
+ },
+
+ hasHandles: function() {
+ var segments = this._segments;
+ for (var i = 0, l = segments.length; i < l; i++) {
+ if (segments[i].hasHandles())
+ return true;
+ }
+ return false;
+ },
+
+ _transformContent: 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(25);
+ 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];
+ curve._changed();
+ }
+ if (curve = curves[this._closed && from === 0 ? segments.length - 1
+ : from - 1]) {
+ curve._segment2 = segments[from] || segments[0];
+ curve._changed();
+ }
+ if (curve = curves[to]) {
+ curve._segment1 = segments[to];
+ curve._changed();
+ }
+ },
+
+ _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, _includeCurves) {
+ 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);
+ segment._index = segment._path = null;
+ }
+ 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 (_includeCurves)
+ removed._curves = curves.slice(1);
+ this._adjustCurves(index, index);
+ }
+ this._changed(25);
+ return removed;
+ },
+
+ clear: '#removeSegments',
+
+ 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;
+ },
+
+ isFullySelected: function() {
+ var length = this._segments.length;
+ return this._selected && length > 0 && this._selectedSegmentState
+ === length * 7;
+ },
+
+ 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 * 7 : 0;
+ for (var i = 0; i < length; i++)
+ this._segments[i]._selectionState = selected
+ ? 7 : 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 iterator = new PathIterator(this, 64, 0.1),
+ pos = 0,
+ step = iterator.length / Math.ceil(iterator.length / maxDistance),
+ end = iterator.length + (this._closed ? -step : step) / 2;
+ var segments = [];
+ while (pos <= end) {
+ segments.push(new Segment(iterator.getPointAt(pos)));
+ pos += step;
+ }
+ this.setSegments(segments);
+ },
+
+ reduce: function() {
+ var curves = this.getCurves();
+ for (var i = curves.length - 1; i >= 0; i--) {
+ var curve = curves[i];
+ if (curve.isLinear() && curve.getLength() === 0)
+ curve.remove();
+ }
+ return this;
+ },
+
+ 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 null;
+ if (arguments.length === 1) {
+ var arg = index;
+ if (typeof arg === 'number')
+ arg = this.getLocationAt(arg);
+ if (!arg)
+ return null
+ index = arg.index;
+ parameter = arg.parameter;
+ }
+ var tolerance = 0.000001;
+ if (parameter >= 1 - tolerance) {
+ index++;
+ parameter--;
+ }
+ var curves = this.getCurves();
+ if (index >= 0 && index < curves.length) {
+ if (parameter > tolerance) {
+ curves[index++].divide(parameter, true);
+ }
+ var segs = this.removeSegments(index, this._segments.length, true),
+ path;
+ if (this._closed) {
+ this.setClosed(false);
+ path = this;
+ } else {
+ 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;
+ }
+ this._curves = null;
+ if (this._clockwise !== undefined)
+ this._clockwise = !this._clockwise;
+ this._changed(9);
+ },
+
+ join: function(path) {
+ if (path) {
+ var segments = path._segments,
+ last1 = this.getLastSegment(),
+ last2 = path.getLastSegment();
+ if (!last2)
+ return this;
+ if (last1 && last1._point.equals(last2._point))
+ path.reverse();
+ var first2 = path.getFirstSegment();
+ if (last1 && last1._point.equals(first2._point)) {
+ last1.setHandleOut(first2._handleOut);
+ this._add(segments.slice(1));
+ } else {
+ var first1 = this.getFirstSegment();
+ if (first1 && first1._point.equals(first2._point))
+ path.reverse();
+ last2 = path.getLastSegment();
+ if (first1 && 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();
+ }
+ var first = this.getFirstSegment(),
+ last = this.getLastSegment();
+ if (first !== last && first._point.equals(last._point)) {
+ first.setHandleIn(last._handleIn);
+ last.remove();
+ this.setClosed(true);
+ }
+ return this;
+ },
+
+ toShape: function(insert) {
+ if (!this._closed)
+ return null;
+
+ var segments = this._segments,
+ type,
+ size,
+ radius,
+ topCenter;
+
+ function isCollinear(i, j) {
+ return segments[i].isCollinear(segments[j]);
+ }
+
+ function isOrthogonal(i) {
+ return segments[i].isOrthogonal();
+ }
+
+ function isArc(i) {
+ return segments[i].isOrthogonalArc();
+ }
+
+ function getDistance(i, j) {
+ return segments[i]._point.getDistance(segments[j]._point);
+ }
+
+ if (!this.hasHandles() && segments.length === 4
+ && isCollinear(0, 2) && isCollinear(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) && isCollinear(1, 5) && isCollinear(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 = this._clone(new type({
+ center: center,
+ size: size,
+ radius: radius,
+ insert: false
+ }), insert, false);
+ shape.rotate(topCenter.subtract(center).getAngle() + 90);
+ return shape;
+ }
+ return null;
+ },
+
+ _hitTestSelf: function(point, options) {
+ var that = this,
+ style = this.getStyle(),
+ segments = this._segments,
+ numSegments = segments.length,
+ closed = this._closed,
+ tolerancePadding = options._tolerancePadding,
+ strokePadding = tolerancePadding,
+ join, cap, miterLimit,
+ area, loc, res,
+ hitStroke = options.stroke && style.hasStroke(),
+ hitFill = options.fill && style.hasFill(),
+ hitCurves = options.curves,
+ radius = hitStroke
+ ? style.getStrokeWidth() / 2
+ : hitFill && options.tolerance > 0 || hitCurves
+ ? 0 : null;
+ if (radius !== null) {
+ if (radius > 0) {
+ join = style.getStrokeJoin();
+ cap = style.getStrokeCap();
+ miterLimit = radius * style.getMiterLimit();
+ strokePadding = tolerancePadding.add(new Point(radius, radius));
+ } else {
+ join = cap = 'round';
+ }
+ }
+
+ function isCloseEnough(pt, padding) {
+ return point.subtract(pt).divide(padding).length <= 1;
+ }
+
+ function checkSegmentPoint(seg, pt, name) {
+ if (!options.selected || pt.isSelected()) {
+ var anchor = seg._point;
+ if (pt !== anchor)
+ pt = pt.add(anchor);
+ if (isCloseEnough(pt, strokePadding)) {
+ return new HitResult(name, that, {
+ segment: seg,
+ point: pt
+ });
+ }
+ }
+ }
+
+ function checkSegmentPoints(seg, ends) {
+ return (ends || options.segments)
+ && checkSegmentPoint(seg, seg._point, 'segment')
+ || (!ends && options.handles) && (
+ checkSegmentPoint(seg, seg._handleIn, 'handle-in') ||
+ checkSegmentPoint(seg, seg._handleOut, 'handle-out'));
+ }
+
+ function addToArea(point) {
+ area.add(point);
+ }
+
+ function checkSegmentStroke(segment) {
+ if (join !== 'round' || cap !== 'round') {
+ area = new Path({ internal: true, closed: true });
+ if (closed || segment._index > 0
+ && segment._index < numSegments - 1) {
+ if (join !== 'round' && (segment._handleIn.isZero()
+ || segment._handleOut.isZero()))
+ Path._addBevelJoin(segment, join, radius, miterLimit,
+ addToArea, true);
+ } else if (cap !== 'round') {
+ Path._addSquareCap(segment, cap, radius, addToArea, true);
+ }
+ if (!area.isEmpty()) {
+ var loc;
+ return area.contains(point)
+ || (loc = area.getNearestLocation(point))
+ && isCloseEnough(loc.getPoint(), tolerancePadding);
+ }
+ }
+ return isCloseEnough(segment._point, strokePadding);
+ }
+
+ if (options.ends && !options.segments && !closed) {
+ if (res = checkSegmentPoints(segments[0], true)
+ || checkSegmentPoints(segments[numSegments - 1], true))
+ return res;
+ } else if (options.segments || options.handles) {
+ for (var i = 0; i < numSegments; i++)
+ if (res = checkSegmentPoints(segments[i]))
+ return res;
+ }
+ if (radius !== null) {
+ loc = this.getNearestLocation(point);
+ if (loc) {
+ var parameter = loc.getParameter();
+ if (parameter === 0 || parameter === 1 && numSegments > 1) {
+ if (!checkSegmentStroke(loc.getSegment()))
+ loc = null;
+ } else if (!isCloseEnough(loc.getPoint(), strokePadding)) {
+ loc = null;
+ }
+ }
+ if (!loc && join === 'miter' && numSegments > 1) {
+ for (var i = 0; i < numSegments; i++) {
+ var segment = segments[i];
+ if (point.getDistance(segment._point) <= miterLimit
+ && checkSegmentStroke(segment)) {
+ loc = segment.getLocation();
+ break;
+ }
+ }
+ }
+ }
+ return !loc && hitFill && this._contains(point)
+ || loc && !hitStroke && !hitCurves
+ ? new HitResult('fill', this)
+ : loc
+ ? new HitResult(hitStroke ? 'stroke' : 'curve', this, {
+ location: loc,
+ point: loc.getPoint()
+ })
+ : null;
+ }
+
+}, Base.each(Curve.evaluateMethods,
+ function(name) {
+ this[name + 'At'] = function(offset, isParameter) {
+ var loc = this.getLocationAt(offset, isParameter);
+ return loc && loc[name]();
+ };
+ },
+{
+ beans: false,
+
+ _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],
+ parameter = location.getParameter();
+ if (parameter > 0)
+ offset += curve.getPartLength(0, parameter);
+ return offset;
+ }
+ return null;
+ },
+
+ getLocationOf: function() {
+ var point = Point.read(arguments),
+ 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;
+ },
+
+ getOffsetOf: function() {
+ var loc = this.getLocationOf.apply(this, arguments);
+ return loc ? loc.getOffset() : null;
+ },
+
+ getLocationAt: function(offset, isParameter) {
+ var curves = this.getCurves(),
+ length = 0;
+ if (isParameter) {
+ var index = ~~offset,
+ curve = curves[index];
+ return curve ? curve.getLocationAt(offset - index, true) : null;
+ }
+ 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;
+ },
+
+ getNearestLocation: function() {
+ var point = Point.read(arguments),
+ 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() {
+ return this.getNearestLocation.apply(this, arguments).getPoint();
+ }
+}), 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,
+ pX = coords[0],
+ pY = coords[1];
+ if (state & 1)
+ drawHandle(2);
+ if (state & 2)
+ drawHandle(4);
+ ctx.fillRect(pX - half, pY - half, size, size);
+ if (!(state & 4)) {
+ var fillStyle = ctx.fillStyle;
+ ctx.fillStyle = '#ffffff';
+ ctx.fillRect(pX - half + 1, pY - half + 1, size - 2, size - 2);
+ ctx.fillStyle = fillStyle;
+ }
+ }
+ }
+
+ 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(segment) {
+ 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(segments[i]);
+ if (path._closed && length > 0)
+ drawSegment(segments[0]);
+ }
+
+ return {
+ _draw: function(ctx, param, strokeMatrix) {
+ var dontStart = param.dontStart,
+ dontPaint = param.dontFinish || param.clip,
+ style = this.getStyle(),
+ hasFill = style.hasFill(),
+ hasStroke = style.hasStroke(),
+ dashArray = style.getDashArray(),
+ dashLength = !paper.support.nativeDash && hasStroke
+ && dashArray && dashArray.length;
+
+ if (!dontStart)
+ ctx.beginPath();
+
+ if (!dontStart && this._currentPath) {
+ ctx.currentPath = this._currentPath;
+ } else if (hasFill || hasStroke && !dashLength || dontPaint) {
+ drawSegments(ctx, this, strokeMatrix);
+ if (this._closed)
+ ctx.closePath();
+ if (!dontStart)
+ this._currentPath = ctx.currentPath;
+ }
+
+ function getOffset(i) {
+ return dashArray[((i % dashLength) + dashLength) % dashLength];
+ }
+
+ if (!dontPaint && (hasFill || hasStroke)) {
+ this._setStyles(ctx);
+ if (hasFill) {
+ ctx.fill(style.getWindingRule());
+ ctx.shadowColor = 'rgba(0,0,0,0)';
+ }
+ if (hasStroke) {
+ if (dashLength) {
+ if (!dontStart)
+ ctx.beginPath();
+ var iterator = new PathIterator(this, 32, 0.25,
+ strokeMatrix),
+ length = iterator.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)
+ iterator.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, paper.settings.handleSize);
+ }
+ };
+}, 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() {
+ var segments = this._segments;
+ if (segments.length === 1)
+ this.removeSegment(0);
+ if (!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,
+ to = Point.read(arguments),
+ through,
+ peek = Base.peek(arguments),
+ clockwise = Base.pick(peek, true),
+ center, extent, vector, matrix;
+ if (typeof clockwise === 'boolean') {
+ var middle = from.add(to).divide(2),
+ through = middle.add(middle.subtract(from).rotate(
+ clockwise ? -90 : 90));
+ } else if (Base.remain(arguments) <= 2) {
+ through = to;
+ to = Point.read(arguments);
+ } else {
+ var radius = Size.read(arguments);
+ if (radius.isZero())
+ return this.lineTo(to);
+ var rotation = Base.read(arguments),
+ clockwise = !!Base.read(arguments),
+ large = !!Base.read(arguments),
+ middle = from.add(to).divide(2),
+ pt = from.subtract(middle).rotate(-rotation),
+ x = pt.x,
+ y = pt.y,
+ abs = Math.abs,
+ epsilon = 1e-12,
+ rx = abs(radius.width),
+ ry = abs(radius.height),
+ rxSq = rx * rx,
+ rySq = ry * ry,
+ xSq = x * x,
+ ySq = y * y;
+ var factor = Math.sqrt(xSq / rxSq + ySq / rySq);
+ if (factor > 1) {
+ rx *= factor;
+ ry *= factor;
+ rxSq = rx * rx;
+ rySq = ry * ry;
+ }
+ factor = (rxSq * rySq - rxSq * ySq - rySq * xSq) /
+ (rxSq * ySq + rySq * xSq);
+ if (abs(factor) < epsilon)
+ factor = 0;
+ if (factor < 0)
+ throw new Error(
+ 'Cannot create an arc with the given arguments');
+ center = new Point(rx * y / ry, -ry * x / rx)
+ .multiply((large === clockwise ? -1 : 1)
+ * Math.sqrt(factor))
+ .rotate(rotation).add(middle);
+ matrix = new Matrix().translate(center).rotate(rotation)
+ .scale(rx, ry);
+ vector = matrix._inverseTransform(from);
+ extent = vector.getDirectedAngle(matrix._inverseTransform(to));
+ if (!clockwise && extent > 0)
+ extent -= 360;
+ else if (clockwise && extent < 0)
+ extent += 360;
+ }
+ if (through) {
+ 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),
+ line = new Line(from, to),
+ throughSide = line.getSide(through);
+ center = l1.intersect(l2, true);
+ if (!center) {
+ if (!throughSide)
+ return this.lineTo(to);
+ throw new Error(
+ 'Cannot create an arc with the given arguments');
+ }
+ vector = from.subtract(center);
+ extent = vector.getDirectedAngle(to.subtract(center));
+ var centerSide = line.getSide(center);
+ if (centerSide === 0) {
+ extent = throughSide * Math.abs(extent);
+ } else if (throughSide === centerSide) {
+ extent += extent < 0 ? 360 : -360;
+ }
+ }
+ 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 = to,
+ out = null;
+ if (i < count) {
+ out = vector.rotate(90).multiply(z);
+ if (matrix) {
+ pt = matrix._transformPoint(vector);
+ out = matrix._transformPoint(vector.add(out))
+ .subtract(pt);
+ } else {
+ pt = center.add(vector);
+ }
+ }
+ if (i === 0) {
+ current.setHandleOut(out);
+ } else {
+ var _in = vector.rotate(-90).multiply(z);
+ if (matrix) {
+ _in = matrix._transformPoint(vector.add(_in))
+ .subtract(pt);
+ }
+ segments.push(new Segment(pt, _in, 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(join) {
+ this.setClosed(true);
+ if (join)
+ this.join();
+ }
+ };
+}, {
+
+ _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++)
+ sum += Curve.getEdgeSum(Curve.getValues(
+ segments[i], segments[i + 1 < l ? i + 1 : 0]));
+ 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) {
+ if (!style.hasStroke())
+ return Path.getBounds(segments, closed, style, matrix);
+ var length = segments.length - (closed ? 0 : 1),
+ radius = style.getStrokeWidth() / 2,
+ padding = Path._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 addRound(segment) {
+ bounds = bounds.unite(joinBounds.setCenter(matrix
+ ? matrix._transformPoint(segment._point) : segment._point));
+ }
+
+ function addJoin(segment, join) {
+ var handleIn = segment._handleIn,
+ handleOut = segment._handleOut;
+ if (join === 'round' || !handleIn.isZero() && !handleOut.isZero()
+ && handleIn.isCollinear(handleOut)) {
+ addRound(segment);
+ } else {
+ Path._addBevelJoin(segment, join, radius, miterLimit, add);
+ }
+ }
+
+ function addCap(segment, cap) {
+ if (cap === 'round') {
+ addRound(segment);
+ } else {
+ Path._addSquareCap(segment, cap, radius, add);
+ }
+ }
+
+ for (var i = 1; i < length; i++)
+ addJoin(segments[i], join);
+ if (closed) {
+ addJoin(segments[0], join);
+ } else if (length > 0) {
+ addCap(segments[0], cap);
+ addCap(segments[segments.length - 1], cap);
+ }
+ return bounds;
+ },
+
+ _getPenPadding: function(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)];
+ },
+
+ _addBevelJoin: 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().multiply(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;
+ 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,
+ paddingX = padding ? padding[0] : 0,
+ paddingY = padding ? padding[1] : 0,
+ x = coords[j],
+ y = coords[j + 1],
+ xn = x - paddingX,
+ xx = x + paddingX,
+ yn = y - paddingY,
+ yx = y + paddingY;
+ 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 strokeRadius = style.hasStroke() ? style.getStrokeWidth() / 2 : 0,
+ joinRadius = strokeRadius;
+ if (strokeRadius > 0) {
+ if (style.getStrokeJoin() === 'miter')
+ joinRadius = strokeRadius * style.getMiterLimit();
+ if (style.getStrokeCap() === 'square')
+ joinRadius = Math.max(joinRadius, strokeRadius * Math.sqrt(2));
+ }
+ return Path.getHandleBounds(segments, closed, style, matrix,
+ Path._getPenPadding(strokeRadius, matrix),
+ Path._getPenPadding(joinRadius, matrix));
+ }
+}});
+
+Path.inject({ statics: new function() {
+
+ var kappa = 0.5522847498307936,
+ 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 createPath(segments, closed, args) {
+ var props = Base.getNamed(args),
+ path = new Path(props && props.insert === false && Item.NO_INSERT);
+ path._add(segments);
+ path._closed = closed;
+ return path.set(props);
+ }
+
+ function createEllipse(center, radius, args) {
+ var 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)
+ );
+ }
+ return createPath(segments, true, args);
+ }
+
+ return {
+ Line: function() {
+ return createPath([
+ new Segment(Point.readNamed(arguments, 'from')),
+ new Segment(Point.readNamed(arguments, 'to'))
+ ], false, 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,
+ { readNull: true }),
+ bl = rect.getBottomLeft(true),
+ tl = rect.getTopLeft(true),
+ tr = rect.getTopRight(true),
+ br = rect.getBottomRight(true),
+ segments;
+ if (!radius || radius.isZero()) {
+ segments = [
+ 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;
+ segments = [
+ 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])
+ ];
+ }
+ return createPath(segments, true, 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'),
+ props = Base.getNamed(arguments),
+ path = new Path(props && props.insert === false
+ && Item.NO_INSERT);
+ path.moveTo(from);
+ path.arcTo(through, to);
+ return path.set(props);
+ },
+
+ RegularPolygon: function() {
+ var center = Point.readNamed(arguments, 'center'),
+ sides = Base.readNamed(arguments, 'sides'),
+ radius = Base.readNamed(arguments, 'radius'),
+ 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)));
+ return createPath(segments, true, 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'),
+ 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)));
+ return createPath(segments, true, arguments);
+ }
+ };
+}});
+
+var CompoundPath = PathItem.extend({
+ _class: 'CompoundPath',
+ _serializeFields: {
+ children: []
+ },
+
+ initialize: function CompoundPath(arg) {
+ this._children = [];
+ this._namedChildren = {};
+ if (!this._initialize(arg)) {
+ if (typeof arg === 'string') {
+ this.setPathData(arg);
+ } else {
+ 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();
+ },
+
+ reduce: function reduce() {
+ if (this._children.length === 0) {
+ var path = new Path(Item.NO_INSERT);
+ path.insertAbove(this);
+ path.setStyle(this._style);
+ this.remove();
+ return path;
+ } else {
+ return reduce.base.call(this);
+ }
+ },
+
+ 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.push.apply(curves, 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;
+ }
+}, {
+ beans: true,
+
+ getPathData: function(_matrix, _precision) {
+ var children = this._children,
+ paths = [];
+ for (var i = 0, l = children.length; i < l; i++) {
+ var child = children[i],
+ mx = child._matrix;
+ paths.push(child.getPathData(_matrix && !mx.isIdentity()
+ ? _matrix.chain(mx) : mx, _precision));
+ }
+ return paths.join(' ');
+ }
+}, {
+ _getChildHitTestOptions: function(options) {
+ return options.class === Path || options.type === 'path'
+ ? options
+ : new Base(options, { fill: false });
+ },
+
+ _draw: function(ctx, param, strokeMatrix) {
+ var children = this._children;
+ if (children.length === 0)
+ return;
+
+ if (this._currentPath) {
+ ctx.currentPath = this._currentPath;
+ } else {
+ param = param.extend({ dontStart: true, dontFinish: true });
+ ctx.beginPath();
+ for (var i = 0, l = children.length; i < l; i++)
+ children[i].draw(ctx, param, strokeMatrix);
+ this._currentPath = ctx.currentPath;
+ }
+
+ 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();
+ }
+ },
+
+ _drawSelected: function(ctx, matrix, selectedItems) {
+ var children = this._children;
+ for (var i = 0, l = children.length; i < l; i++) {
+ var child = children[i],
+ mx = child._matrix;
+ if (!selectedItems[child._id])
+ child._drawSelected(ctx, mx.isIdentity() ? matrix
+ : matrix.chain(mx));
+ }
+ }
+}, new function() {
+ function getCurrentPath(that, check) {
+ var children = that._children;
+ if (check && children.length === 0)
+ throw new Error('Use a moveTo() command first');
+ return children[children.length - 1];
+ }
+
+ var fields = {
+ moveTo: function() {
+ var current = getCurrentPath(this),
+ path = current && current.isEmpty() ? current : new Path();
+ if (path !== current)
+ this.addChild(path);
+ path.moveTo.apply(path, arguments);
+ },
+
+ moveBy: function() {
+ var current = getCurrentPath(this, true),
+ last = current && current.getLastSegment(),
+ point = Point.read(arguments);
+ this.moveTo(last ? point.add(last._point) : point);
+ },
+
+ closePath: function(join) {
+ getCurrentPath(this, true).closePath(join);
+ }
+ };
+
+ Base.each(['lineTo', 'cubicCurveTo', 'quadraticCurveTo', 'curveTo', 'arcTo',
+ 'lineBy', 'cubicCurveBy', 'quadraticCurveBy', 'curveBy', 'arcBy'],
+ function(key) {
+ fields[key] = function() {
+ var path = getCurrentPath(this, true);
+ path[key].apply(path, arguments);
+ };
+ }
+ );
+
+ return fields;
+});
+
+PathItem.inject(new function() {
+ var operators = {
+ unite: function(w) {
+ return w === 1 || w === 0;
+ },
+
+ intersect: function(w) {
+ return w === 2;
+ },
+
+ subtract: function(w) {
+ return w === 1;
+ },
+
+ exclude: function(w) {
+ return w === 1;
+ }
+ };
+
+ function computeBoolean(path1, path2, operation) {
+ var operator = operators[operation];
+ function preparePath(path) {
+ return path.clone(false).reduce().reorient().transform(null, true,
+ true);
+ }
+
+ var _path1 = preparePath(path1),
+ _path2 = path2 && path1 !== path2 && preparePath(path2);
+ if (_path2 && /^(subtract|exclude)$/.test(operation)
+ ^ (_path2.isClockwise() !== _path1.isClockwise()))
+ _path2.reverse();
+ splitPath(_path1.getIntersections(_path2, null, true));
+
+ var chain = [],
+ segments = [],
+ monoCurves = [],
+ tolerance = 0.000001;
+
+ function collect(paths) {
+ for (var i = 0, l = paths.length; i < l; i++) {
+ var path = paths[i];
+ segments.push.apply(segments, path._segments);
+ monoCurves.push.apply(monoCurves, path._getMonoCurves());
+ }
+ }
+
+ collect(_path1._children || [_path1]);
+ if (_path2)
+ collect(_path2._children || [_path2]);
+ segments.sort(function(a, b) {
+ var _a = a._intersection,
+ _b = b._intersection;
+ return !_a && !_b || _a && _b ? 0 : _a ? -1 : 1;
+ });
+ for (var i = 0, l = segments.length; i < l; i++) {
+ var segment = segments[i];
+ if (segment._winding != null)
+ continue;
+ chain.length = 0;
+ var startSeg = segment,
+ totalLength = 0,
+ windingSum = 0;
+ do {
+ var length = segment.getCurve().getLength();
+ chain.push({ segment: segment, length: length });
+ totalLength += length;
+ segment = segment.getNext();
+ } while (segment && !segment._intersection && segment !== startSeg);
+ for (var j = 0; j < 3; j++) {
+ var length = totalLength * (j + 1) / 4;
+ for (var k = 0, m = chain.length; k < m; k++) {
+ var node = chain[k],
+ curveLength = node.length;
+ if (length <= curveLength) {
+ if (length < tolerance
+ || curveLength - length < tolerance)
+ length = curveLength / 2;
+ var curve = node.segment.getCurve(),
+ pt = curve.getPointAt(length),
+ hor = curve.isLinear() && Math.abs(curve
+ .getTangentAt(0.5, true).y) < tolerance,
+ path = curve._path;
+ if (path._parent instanceof CompoundPath)
+ path = path._parent;
+ windingSum += operation === 'subtract' && _path2
+ && (path === _path1 && _path2._getWinding(pt, hor)
+ || path === _path2 && !_path1._getWinding(pt, hor))
+ ? 0
+ : getWinding(pt, monoCurves, hor);
+ break;
+ }
+ length -= curveLength;
+ }
+ }
+ var winding = Math.round(windingSum / 3);
+ for (var j = chain.length - 1; j >= 0; j--)
+ chain[j].segment._winding = winding;
+ }
+ var result = new CompoundPath(Item.NO_INSERT);
+ result.insertAbove(path1);
+ result.addChildren(tracePaths(segments, operator), true);
+ result = result.reduce();
+ result.setStyle(path1._style);
+ return result;
+ }
+
+ function splitPath(intersections) {
+ var tMin = 0.000001,
+ tMax = 1 - tMin,
+ linearHandles;
+
+ function resetLinear() {
+ for (var i = 0, l = linearHandles.length; i < l; i++)
+ linearHandles[i].set(0, 0);
+ }
+
+ for (var i = intersections.length - 1, curve, prev; i >= 0; i--) {
+ var loc = intersections[i],
+ t = loc._parameter;
+ if (prev && prev._curve === loc._curve && prev._parameter > 0) {
+ t /= prev._parameter;
+ } else {
+ curve = loc._curve;
+ if (linearHandles)
+ resetLinear();
+ linearHandles = curve.isLinear() ? [
+ curve._segment1._handleOut,
+ curve._segment2._handleIn
+ ] : null;
+ }
+ var newCurve,
+ segment;
+ if (newCurve = curve.divide(t, true, true)) {
+ segment = newCurve._segment1;
+ curve = newCurve.getPrevious();
+ if (linearHandles)
+ linearHandles.push(segment._handleOut, segment._handleIn);
+ } else {
+ segment = t < tMin
+ ? curve._segment1
+ : t > tMax
+ ? curve._segment2
+ : curve.getPartLength(0, t) < curve.getPartLength(t, 1)
+ ? curve._segment1
+ : curve._segment2;
+ }
+ segment._intersection = loc.getIntersection();
+ loc._segment = segment;
+ prev = loc;
+ }
+ if (linearHandles)
+ resetLinear();
+ }
+
+ function getWinding(point, curves, horizontal, testContains) {
+ var tolerance = 0.000001,
+ tMin = tolerance,
+ tMax = 1 - tMin,
+ px = point.x,
+ py = point.y,
+ windLeft = 0,
+ windRight = 0,
+ roots = [],
+ abs = Math.abs;
+ if (horizontal) {
+ var yTop = -Infinity,
+ yBottom = Infinity,
+ yBefore = py - tolerance,
+ yAfter = py + tolerance;
+ for (var i = 0, l = curves.length; i < l; i++) {
+ var values = curves[i].values;
+ if (Curve.solveCubic(values, 0, px, roots, 0, 1) > 0) {
+ for (var j = roots.length - 1; j >= 0; j--) {
+ var y = Curve.getPoint(values, roots[j]).y;
+ if (y < yBefore && y > yTop) {
+ yTop = y;
+ } else if (y > yAfter && y < yBottom) {
+ yBottom = y;
+ }
+ }
+ }
+ }
+ yTop = (yTop + py) / 2;
+ yBottom = (yBottom + py) / 2;
+ if (yTop > -Infinity)
+ windLeft = getWinding(new Point(px, yTop), curves);
+ if (yBottom < Infinity)
+ windRight = getWinding(new Point(px, yBottom), curves);
+ } else {
+ var xBefore = px - tolerance,
+ xAfter = px + tolerance;
+ var startCounted = false,
+ prevCurve,
+ prevT;
+ for (var i = 0, l = curves.length; i < l; i++) {
+ var curve = curves[i],
+ values = curve.values,
+ winding = curve.winding;
+ if (winding && (winding === 1
+ && py >= values[1] && py <= values[7]
+ || py >= values[7] && py <= values[1])
+ && Curve.solveCubic(values, 1, py, roots, 0, 1) === 1) {
+ var t = roots[0];
+ if (!(
+ t > tMax && startCounted && curve.next !== curves[i + 1]
+ || t < tMin && prevT > tMax
+ && curve.previous === prevCurve)) {
+ var x = Curve.getPoint(values, t).x,
+ slope = Curve.getTangent(values, t).y,
+ counted = false;
+ if (Numerical.isZero(slope) && !Curve.isLinear(values)
+ || t < tMin && slope * Curve.getTangent(
+ curve.previous.values, 1).y < 0
+ || t > tMax && slope * Curve.getTangent(
+ curve.next.values, 0).y < 0) {
+ if (testContains && x >= xBefore && x <= xAfter) {
+ ++windLeft;
+ ++windRight;
+ counted = true;
+ }
+ } else if (x <= xBefore) {
+ windLeft += winding;
+ counted = true;
+ } else if (x >= xAfter) {
+ windRight += winding;
+ counted = true;
+ }
+ if (curve.previous !== curves[i - 1])
+ startCounted = t < tMin && counted;
+ }
+ prevCurve = curve;
+ prevT = t;
+ }
+ }
+ }
+ return Math.max(abs(windLeft), abs(windRight));
+ }
+
+ function tracePaths(segments, operator, selfOp) {
+ var paths = [],
+ tMin = 0.000001,
+ tMax = 1 - tMin;
+ for (var i = 0, seg, startSeg, l = segments.length; i < l; i++) {
+ seg = startSeg = segments[i];
+ if (seg._visited || !operator(seg._winding))
+ continue;
+ var path = new Path(Item.NO_INSERT),
+ inter = seg._intersection,
+ startInterSeg = inter && inter._segment,
+ added = false,
+ dir = 1;
+ do {
+ var handleIn = dir > 0 ? seg._handleIn : seg._handleOut,
+ handleOut = dir > 0 ? seg._handleOut : seg._handleIn,
+ interSeg;
+ if (added && (!operator(seg._winding) || selfOp)
+ && (inter = seg._intersection)
+ && (interSeg = inter._segment)
+ && interSeg !== startSeg) {
+ if (selfOp) {
+ seg._visited = interSeg._visited;
+ seg = interSeg;
+ dir = 1;
+ } else {
+ var c1 = seg.getCurve();
+ if (dir > 0)
+ c1 = c1.getPrevious();
+ var t1 = c1.getTangentAt(dir < 1 ? tMin : tMax, true),
+ c4 = interSeg.getCurve(),
+ c3 = c4.getPrevious(),
+ t3 = c3.getTangentAt(tMax, true),
+ t4 = c4.getTangentAt(tMin, true),
+ w3 = t1.cross(t3),
+ w4 = t1.cross(t4);
+ if (w3 * w4 !== 0) {
+ var curve = w3 < w4 ? c3 : c4,
+ nextCurve = operator(curve._segment1._winding)
+ ? curve
+ : w3 < w4 ? c4 : c3,
+ nextSeg = nextCurve._segment1;
+ dir = nextCurve === c3 ? -1 : 1;
+ if (nextSeg._visited && seg._path !== nextSeg._path
+ || !operator(nextSeg._winding)) {
+ dir = 1;
+ } else {
+ seg._visited = interSeg._visited;
+ seg = interSeg;
+ if (nextSeg._visited)
+ dir = 1;
+ }
+ } else {
+ dir = 1;
+ }
+ }
+ handleOut = dir > 0 ? seg._handleOut : seg._handleIn;
+ }
+ path.add(new Segment(seg._point, added && handleIn, handleOut));
+ added = true;
+ seg._visited = true;
+ seg = dir > 0 ? seg.getNext() : seg. getPrevious();
+ } while (seg && !seg._visited
+ && seg !== startSeg && seg !== startInterSeg
+ && (seg._intersection || operator(seg._winding)));
+ if (seg && (seg === startSeg || seg === startInterSeg)) {
+ path.firstSegment.setHandleIn((seg === startInterSeg
+ ? startInterSeg : seg)._handleIn);
+ path.setClosed(true);
+ } else {
+ path.lastSegment._handleOut.set(0, 0);
+ }
+ if (path._segments.length >
+ (path._closed ? path.isLinear() ? 2 : 0 : 1))
+ paths.push(path);
+ }
+ return paths;
+ }
+
+ return {
+ _getWinding: function(point, horizontal, testContains) {
+ return getWinding(point, this._getMonoCurves(),
+ horizontal, testContains);
+ },
+
+ unite: function(path) {
+ return computeBoolean(this, path, 'unite');
+ },
+
+ intersect: function(path) {
+ return computeBoolean(this, path, 'intersect');
+ },
+
+ subtract: function(path) {
+ return computeBoolean(this, path, 'subtract');
+ },
+
+ exclude: function(path) {
+ return computeBoolean(this, path, 'exclude');
+ },
+
+ divide: function(path) {
+ return new Group([this.subtract(path), this.intersect(path)]);
+ }
+ };
+});
+
+Path.inject({
+ _getMonoCurves: function() {
+ var monoCurves = this._monoCurves,
+ prevCurve;
+
+ function insertCurve(v) {
+ var y0 = v[1],
+ y1 = v[7],
+ curve = {
+ values: v,
+ winding: y0 === y1
+ ? 0
+ : y0 > y1
+ ? -1
+ : 1,
+ previous: prevCurve,
+ next: null
+ };
+ if (prevCurve)
+ prevCurve.next = curve;
+ monoCurves.push(curve);
+ prevCurve = curve;
+ }
+
+ function handleCurve(v) {
+ if (Curve.getLength(v) === 0)
+ return;
+ var y0 = v[1],
+ y1 = v[3],
+ y2 = v[5],
+ y3 = v[7];
+ if (Curve.isLinear(v)) {
+ insertCurve(v);
+ } else {
+ var a = 3 * (y1 - y2) - y0 + y3,
+ b = 2 * (y0 + y2) - 4 * y1,
+ c = y1 - y0,
+ tolerance = 0.000001,
+ roots = [];
+ var count = Numerical.solveQuadratic(a, b, c, roots, tolerance,
+ 1 - tolerance);
+ if (count === 0) {
+ insertCurve(v);
+ } else {
+ roots.sort();
+ var t = roots[0],
+ parts = Curve.subdivide(v, t);
+ insertCurve(parts[0]);
+ if (count > 1) {
+ t = (roots[1] - t) / (1 - t);
+ parts = Curve.subdivide(parts[1], t);
+ insertCurve(parts[0]);
+ }
+ insertCurve(parts[1]);
+ }
+ }
+ }
+
+ if (!monoCurves) {
+ monoCurves = this._monoCurves = [];
+ var curves = this.getCurves(),
+ segments = this._segments;
+ for (var i = 0, l = curves.length; i < l; i++)
+ handleCurve(curves[i].getValues());
+ if (!this._closed && segments.length > 1) {
+ var p1 = segments[segments.length - 1]._point,
+ p2 = segments[0]._point,
+ p1x = p1._x, p1y = p1._y,
+ p2x = p2._x, p2y = p2._y;
+ handleCurve([p1x, p1y, p1x, p1y, p2x, p2y, p2x, p2y]);
+ }
+ if (monoCurves.length > 0) {
+ var first = monoCurves[0],
+ last = monoCurves[monoCurves.length - 1];
+ first.previous = last;
+ last.next = first;
+ }
+ }
+ return monoCurves;
+ },
+
+ getInteriorPoint: function() {
+ var bounds = this.getBounds(),
+ point = bounds.getCenter(true);
+ if (!this.contains(point)) {
+ var curves = this._getMonoCurves(),
+ roots = [],
+ y = point.y,
+ xIntercepts = [];
+ for (var i = 0, l = curves.length; i < l; i++) {
+ var values = curves[i].values;
+ if ((curves[i].winding === 1
+ && y >= values[1] && y <= values[7]
+ || y >= values[7] && y <= values[1])
+ && Curve.solveCubic(values, 1, y, roots, 0, 1) > 0) {
+ for (var j = roots.length - 1; j >= 0; j--)
+ xIntercepts.push(Curve.getPoint(values, roots[j]).x);
+ }
+ if (xIntercepts.length > 1)
+ break;
+ }
+ point.x = (xIntercepts[0] + xIntercepts[1]) / 2;
+ }
+ return point;
+ },
+
+ reorient: function() {
+ this.setClockwise(true);
+ return this;
+ }
+});
+
+CompoundPath.inject({
+ _getMonoCurves: function() {
+ var children = this._children,
+ monoCurves = [];
+ for (var i = 0, l = children.length; i < l; i++)
+ monoCurves.push.apply(monoCurves, children[i]._getMonoCurves());
+ return monoCurves;
+ },
+
+ reorient: function() {
+ var children = this.removeChildren().sort(function(a, b) {
+ return b.getBounds().getArea() - a.getBounds().getArea();
+ });
+ if (children.length > 0) {
+ this.addChildren(children);
+ var clockwise = children[0].isClockwise();
+ for (var i = 1, l = children.length; i < l; i++) {
+ var point = children[i].getInteriorPoint(),
+ counters = 0;
+ for (var j = i - 1; j >= 0; j--) {
+ if (children[j].contains(point))
+ counters++;
+ }
+ children[i].setClockwise(counters % 2 === 0 && clockwise);
+ }
+ }
+ return this;
+ }
+});
+
+var PathIterator = Base.extend({
+ _class: 'PathIterator',
+
+ initialize: function(path, maxRecursion, tolerance, matrix) {
+ var curves = [],
+ parts = [],
+ length = 0,
+ minDifference = 1 / (maxRecursion || 32),
+ segments = path._segments,
+ segment1 = segments[0],
+ segment2;
+
+ function addCurve(segment1, segment2) {
+ var curve = Curve.getValues(segment1, segment2, matrix);
+ curves.push(curve);
+ computeParts(curve, segment1._index, 0, 1);
+ }
+
+ function computeParts(curve, index, minT, maxT) {
+ if ((maxT - minT) > minDifference
+ && !Curve.isFlatEnough(curve, tolerance || 0.25)) {
+ var split = Curve.subdivide(curve),
+ halfT = (minT + maxT) / 2;
+ computeParts(split[0], index, minT, halfT);
+ computeParts(split[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.000001) {
+ length += dist;
+ parts.push({
+ offset: length,
+ value: maxT,
+ index: index
+ });
+ }
+ }
+ }
+
+ 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]);
+
+ this.curves = curves;
+ this.parts = parts;
+ this.length = length;
+ this.index = 0;
+ },
+
+ 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
+ };
+ },
+
+ 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));
+ }
+ }
+}, Base.each(Curve.evaluateMethods,
+ function(name) {
+ this[name + 'At'] = function(offset, weighted) {
+ var param = this.getParameterAt(offset);
+ return Curve[name](this.curves[param.index], param.value, weighted);
+ };
+ }, {})
+);
+
+var PathFitter = Base.extend({
+ initialize: function(path, error) {
+ var points = this.points = [],
+ 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)) {
+ points.push(point);
+ prev = point;
+ }
+ }
+
+ if (path._closed) {
+ this.closed = true;
+ points.unshift(points[points.length - 1]);
+ points.push(points[1]);
+ }
+
+ this.error = error;
+ },
+
+ fit: function() {
+ var points = this.points,
+ length = points.length,
+ segments = 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());
+
+ if (this.closed) {
+ segments.shift();
+ segments.pop();
+ }
+
+ return 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,
+ parametersInOrder = true;
+ 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 && parametersInOrder) {
+ this.addCurve(curve);
+ return;
+ }
+ split = max.index;
+ if (max.error >= maxError)
+ break;
+ parametersInOrder = 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-12,
+ 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),
+ eps = epsilon * segLength,
+ handle1,
+ handle2;
+ if (alpha1 < eps || alpha2 < eps) {
+ alpha1 = alpha2 = segLength / 3;
+ } else {
+ var line = pt2.subtract(pt1);
+ handle1 = tan1.normalize(alpha1);
+ handle2 = tan2.normalize(alpha2);
+ if (handle1.dot(line) - handle2.dot(line) > segLength * segLength) {
+ alpha1 = alpha2 = segLength / 3;
+ handle1 = handle2 = null;
+ }
+ }
+
+ return [pt1, pt1.add(handle1 || tan1.normalize(alpha1)),
+ pt2.add(handle2 || 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]);
+ }
+ for (var i = 1, l = u.length; i < l; i++) {
+ if (u[i] <= u[i - 1])
+ return false;
+ }
+ return true;
+ },
+
+ 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.000001)
+ 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
+ };
+ }
+});
+
+var TextItem = Item.extend({
+ _class: 'TextItem',
+ _boundsSelected: true,
+ _applyMatrix: false,
+ _canApplyMatrix: false,
+ _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, insert, includeMatrix) {
+ copy.setContent(this._content);
+ return _clone.base.call(this, copy, insert, includeMatrix);
+ },
+
+ getContent: function() {
+ return this._content;
+ },
+
+ setContent: function(content) {
+ this._content = '' + content;
+ this._lines = this._content.split(/\r\n|\n|\r/mg);
+ this._changed(265);
+ },
+
+ 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(Item.NO_INSERT), insert);
+ },
+
+ getPoint: function() {
+ var point = this._matrix.getTranslation();
+ return new LinkedPoint(point.x, point.y, this, 'setPoint');
+ },
+
+ setPoint: function() {
+ var 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);
+ }
+ },
+
+ _getBounds: function(getter, matrix) {
+ var style = this._style,
+ lines = this._lines,
+ numLines = lines.length,
+ justification = style.getJustification(),
+ leading = style.getLeading(),
+ width = this.getView().getTextWidth(style.getFontStyle(), lines),
+ x = 0;
+ if (justification !== 'left')
+ x -= width / (justification === 'center' ? 2: 1);
+ var bounds = new Rectangle(x,
+ numLines ? - 0.75 * leading : 0,
+ width, numLines * 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 = +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) {
+ h = (((h / 60) % 6) + 6) % 6;
+ var 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 = (((h / 360) % 1) + 1) % 1;
+ 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, { readNull: true });
+ if (current !== value) {
+ if (current)
+ current._removeOwner(this);
+ if (value)
+ value._addOwner(this);
+ }
+ return value;
+ }
+ : type === 'gradient'
+ ? function() {
+ return Point.read(arguments, 0, {
+ readNull: name === 'highlight',
+ clone: true
+ });
+ }
+ : function(value) {
+ return value == null || isNaN(value) ? 0 : value;
+ };
+
+ 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;
+ }
+ this._components[index] = parser.call(this, value);
+ this._changed();
+ };
+ }, this);
+ }, {
+ _class: 'Color',
+ _readIndex: true,
+
+ initialize: function Color(arg) {
+ var slice = Array.prototype.slice,
+ args = arguments,
+ read = 0,
+ 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) {
+ 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 = 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
+ };
+ }
+ 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';
+ this._id = UID.get(Color);
+ if (!components) {
+ this._components = components = [];
+ var parsers = componentParsers[this._type];
+ for (var i = 0, l = parsers.length; i < l; i++) {
+ var value = parsers[i].call(this, values && values[i]);
+ 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(65);
+ },
+
+ _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) {
+ var col = Base.isPlainValue(color, true)
+ ? Color.read(arguments)
+ : color;
+ return col === this || col && this._class === col._class
+ && this._type === col._type
+ && this._alpha === col._alpha
+ && Base.equals(this._components, col._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;
+ function convert(val) {
+ return Math.round((val < 0 ? 0 : val > 1 ? 1 : val) * 255);
+ }
+ components = [
+ convert(components[0]),
+ convert(components[1]),
+ convert(components[2])
+ ];
+ if (alpha < 1)
+ components.push(alpha < 0 ? 0 : 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() {
+ var operators = {
+ add: function(a, b) {
+ return a + b;
+ },
+
+ subtract: function(a, b) {
+ return a - b;
+ },
+
+ multiply: function(a, b) {
+ return a * b;
+ },
+
+ divide: function(a, b) {
+ return a / b;
+ }
+ };
+
+ return Base.each(operators, function(operator, name) {
+ this[name] = function(color) {
+ color = Color.read(arguments);
+ var type = this._type,
+ components1 = this._components,
+ components2 = color._convert(type);
+ for (var i = 0, l = components1.length; i < l; i++)
+ components2[i] = operator(components1[i], components2[i]);
+ 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 = UID.get();
+ 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)
+ this._owners = undefined;
+ }
+ },
+
+ 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, this._radial);
+ },
+
+ getStops: function() {
+ return this._stops;
+ },
+
+ setStops: function(stops) {
+ if (this.stops) {
+ for (var i = 0, l = this._stops.length; i < l; i++)
+ this._stops[i]._owner = undefined;
+ }
+ if (stops.length < 2)
+ throw new Error(
+ 'Gradient stop list needs to contain at least two stops.');
+ this._stops = GradientStop.readAll(stops, 0, { clone: 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(65);
+ },
+
+ 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',
+ strokeScaling: true,
+ miterLimit: 10,
+ dashOffset: 0,
+ dashArray: [],
+ windingRule: 'nonzero',
+ shadowColor: undefined,
+ shadowBlur: 0,
+ shadowOffset: new Point(),
+ selectedColor: undefined,
+ fontFamily: 'sans-serif',
+ fontWeight: 'normal',
+ fontSize: 12,
+ font: 'sans-serif',
+ leading: null,
+ justification: 'left'
+ };
+
+ var flags = {
+ strokeWidth: 97,
+ strokeCap: 97,
+ strokeJoin: 97,
+ strokeScaling: 105,
+ miterLimit: 97,
+ fontFamily: 9,
+ fontWeight: 9,
+ fontSize: 9,
+ font: 9,
+ leading: 9,
+ justification: 9
+ };
+
+ var item = { beans: true },
+ fields = {
+ _defaults: defaults,
+ _textDefaults: new Base(defaults, {
+ fillColor: new Color()
+ }),
+ beans: true
+ };
+
+ Base.each(defaults, function(value, key) {
+ var isColor = /Color$/.test(key),
+ isPoint = key === 'shadowOffset',
+ part = Base.capitalize(key),
+ flag = flags[key],
+ set = 'set' + part,
+ get = 'get' + part;
+
+ fields[set] = function(value) {
+ var owner = this._owner,
+ children = owner && owner._children;
+ if (children && children.length > 0
+ && !(owner instanceof CompoundPath)) {
+ 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)
+ old._owner = undefined;
+ if (value && value.constructor === Color) {
+ if (value._owner)
+ value = value.clone();
+ value._owner = owner;
+ }
+ }
+ this._values[key] = value;
+ if (owner)
+ owner._changed(flag || 65);
+ }
+ }
+ };
+
+ fields[get] = function(_dontMerge) {
+ var owner = this._owner,
+ children = owner && owner._children,
+ value;
+ if (!children || children.length === 0 || _dontMerge
+ || owner instanceof CompoundPath) {
+ var value = this._values[key];
+ if (value === undefined) {
+ value = this._defaults[key];
+ if (value && value.clone)
+ value = value.clone();
+ } else {
+ var ctor = isColor ? Color : isPoint ? Point : null;
+ if (ctor && !(value && value.constructor === ctor)) {
+ this._values[key] = value = ctor.read([value], 0,
+ { readNull: true, clone: true });
+ if (value && isColor)
+ value._owner = owner;
+ }
+ }
+ 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(_dontMerge) {
+ return this._style[get](_dontMerge);
+ };
+
+ item[set] = function(value) {
+ this._style[set](value);
+ };
+ });
+
+ Item.inject(item);
+ return fields;
+}, {
+ _class: 'Style',
+
+ initialize: function Style(style, _owner, _project) {
+ this._values = {};
+ this._owner = _owner;
+ this._project = _owner && _owner._project || _project || paper.project;
+ if (_owner 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;
+ },
+
+ getView: function() {
+ return this._project.getView();
+ },
+
+ getFontStyle: function() {
+ var fontSize = this.getFontSize();
+ return this.getFontWeight()
+ + ' ' + fontSize + (/[a-z]/i.test(fontSize + '') ? ' ' : 'px ')
+ + this.getFontFamily();
+ },
+
+ getFont: '#getFontFamily',
+ setFont: '#setFontFamily',
+
+ getLeading: function getLeading() {
+ var leading = getLeading.base.call(this),
+ fontSize = this.getFontSize();
+ if (/pt|em|%|px/.test(fontSize))
+ fontSize = this.getView().getPixelSize(fontSize);
+ return leading != null ? leading : fontSize * 1.2;
+ }
+
+});
+
+var DomElement = new function() {
+ function handlePrefix(el, name, set, value) {
+ var prefixes = ['', 'webkit', 'moz', 'Moz', 'ms', 'o'],
+ suffix = name[0].toUpperCase() + name.substring(1);
+ for (var i = 0; i < 6; i++) {
+ var prefix = prefixes[i],
+ key = prefix ? prefix + suffix : name;
+ if (key in el) {
+ if (set) {
+ el[key] = value;
+ } else {
+ return el[key];
+ }
+ break;
+ }
+ }
+ }
+
+ return {
+ getStyles: function(el) {
+ var doc = el && el.nodeType !== 9 ? el.ownerDocument : el,
+ view = doc && doc.defaultView;
+ return view && view.getComputedStyle(el, '');
+ },
+
+ 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 DomElement.getBounds(el, viewport).getPoint();
+ },
+
+ getSize: function(el) {
+ return DomElement.getBounds(el, true).getSize();
+ },
+
+ isInvisible: function(el) {
+ return DomElement.getSize(el).equals(new Size(0, 0));
+ },
+
+ isInView: function(el) {
+ return !DomElement.isInvisible(el)
+ && DomElement.getViewportBounds(el).intersects(
+ DomElement.getBounds(el, true));
+ },
+
+ getPrefixed: function(el, name) {
+ return handlePrefix(el, name);
+ },
+
+ setPrefixed: function(el, name, value) {
+ if (typeof name === 'object') {
+ for (var key in name)
+ handlePrefix(el, key, true, name[key]);
+ } else {
+ handlePrefix(el, name, true, value);
+ }
+ }
+ };
+};
+
+var DomEvent = {
+ add: function(el, events) {
+ for (var type in events) {
+ var func = events[type],
+ parts = type.split(/[\s,]+/g);
+ for (var i = 0, l = parts.length; i < l; i++)
+ el.addEventListener(parts[i], func, false);
+ }
+ },
+
+ remove: function(el, events) {
+ for (var type in events) {
+ var func = events[type],
+ parts = type.split(/[\s,]+/g);
+ for (var i = 0, l = parts.length; i < l; i++)
+ el.removeEventListener(parts[i], func, false);
+ }
+ },
+
+ 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;
+ },
+
+ getRelatedTarget: function(event) {
+ return event.relatedTarget || event.toElement;
+ },
+
+ getOffset: function(event, target) {
+ return DomEvent.getPoint(event).subtract(DomElement.getOffset(
+ target || DomEvent.getTarget(event)));
+ },
+
+ stop: function(event) {
+ event.stopPropagation();
+ event.preventDefault();
+ }
+};
+
+DomEvent.requestAnimationFrame = new function() {
+ var nativeRequest = DomElement.getPrefixed(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(Emitter, {
+ _class: 'View',
+
+ initialize: function View(project, element) {
+ this._project = project;
+ this._scope = project._scope;
+ this._element = element;
+ var size;
+ if (!this._pixelRatio)
+ this._pixelRatio = window.devicePixelRatio || 1;
+ this._id = element.getAttribute('id');
+ if (this._id == null)
+ element.setAttribute('id', this._id = 'view-' + View._id++);
+ DomEvent.add(element, this._viewEvents);
+ var none = 'none';
+ DomElement.setPrefixed(element.style, {
+ userSelect: none,
+ touchAction: none,
+ touchCallout: none,
+ contentZooming: none,
+ userDrag: none,
+ tapHighlightColor: 'rgba(0,0,0,0)'
+ });
+
+ function getSize(name) {
+ return element[name] || parseInt(element.getAttribute(name), 10);
+ };
+
+ function getCanvasSize() {
+ var size = DomElement.getSize(element);
+ return size.isNaN() || size.isZero()
+ ? new Size(getSize('width'), getSize('height'))
+ : size;
+ };
+
+ if (PaperScope.hasAttribute(element, 'resize')) {
+ var that = this;
+ DomEvent.add(window, this._windowEvents = {
+ resize: function() {
+ that.setViewSize(getCanvasSize());
+ }
+ });
+ }
+ this._setViewSize(size = getCanvasSize());
+ 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._viewEvents);
+ DomEvent.remove(window, this._windowEvents);
+ this._element = this._project = null;
+ this.off('frame');
+ this._animate = false;
+ this._frameItems = {};
+ return true;
+ },
+
+ _events: {
+ onFrame: {
+ install: function() {
+ this.play();
+ },
+
+ uninstall: function() {
+ this.pause();
+ }
+ },
+
+ 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.emit('frame', new Base({
+ delta: delta,
+ time: this._time += delta,
+ count: this._count++
+ }));
+ if (this._stats)
+ this._stats.update();
+ this._handlingFrame = false;
+ this.update();
+ },
+
+ _animateItem: function(item, animate) {
+ var items = this._frameItems;
+ if (animate) {
+ items[item._id] = {
+ item: item,
+ time: 0,
+ count: 0
+ };
+ if (++this._frameItemCount === 1)
+ this.on('frame', this._handleFrameItems);
+ } else {
+ delete items[item._id];
+ if (--this._frameItemCount === 0) {
+ this.off('frame', this._handleFrameItems);
+ }
+ }
+ },
+
+ _handleFrameItems: function(event) {
+ for (var i in this._frameItems) {
+ var entry = this._frameItems[i];
+ entry.item.emit('frame', new Base(event, {
+ time: entry.time += event.delta,
+ count: entry.count++
+ }));
+ }
+ },
+
+ _update: function() {
+ this._project._needsUpdate = true;
+ if (this._handlingFrame)
+ return;
+ if (this._animate) {
+ this._handleFrame();
+ } else {
+ this.update();
+ }
+ },
+
+ _changed: function(flags) {
+ if (flags & 1)
+ this._project._needsUpdate = true;
+ },
+
+ _transform: function(matrix) {
+ this._matrix.concatenate(matrix);
+ this._bounds = null;
+ this._update();
+ },
+
+ getElement: function() {
+ return this._element;
+ },
+
+ getPixelRatio: function() {
+ return this._pixelRatio;
+ },
+
+ getResolution: function() {
+ return this._pixelRatio * 72;
+ },
+
+ getViewSize: function() {
+ var size = this._viewSize;
+ return new LinkedSize(size.width, size.height, this, 'setViewSize');
+ },
+
+ setViewSize: function() {
+ var size = Size.read(arguments),
+ delta = size.subtract(this._viewSize);
+ if (delta.isZero())
+ return;
+ this._viewSize.set(size.width, size.height);
+ this._setViewSize(size);
+ this._bounds = null;
+ this.emit('resize', {
+ size: size,
+ delta: delta
+ });
+ this._update();
+ },
+
+ _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();
+ },
+
+ getCenter: function() {
+ return this.getBounds().getCenter();
+ },
+
+ setCenter: function() {
+ var 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()));
+ },
+
+ play: function() {
+ this._animate = true;
+ if (!this._requested)
+ this._requestFrame();
+ },
+
+ pause: function() {
+ this._animate = false;
+ },
+
+ draw: function() {
+ this.update();
+ },
+
+ 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(project, element) {
+ if (typeof element === 'string')
+ element = document.getElementById(element);
+ return new CanvasView(project, 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 handleMouseMove(view, point, event) {
+ view._handleEvent('mousemove', point, event);
+ var tool = view._scope.tool;
+ if (tool) {
+ tool._handleEvent(dragging && tool.responds('mousedrag')
+ ? 'mousedrag' : 'mousemove', point, event);
+ }
+ view.update();
+ return tool;
+ }
+
+ var navigator = window.navigator,
+ mousedown, mousemove, mouseup;
+ if (navigator.pointerEnabled || navigator.msPointerEnabled) {
+ mousedown = 'pointerdown MSPointerDown';
+ mousemove = 'pointermove MSPointerMove';
+ mouseup = 'pointerup pointercancel MSPointerUp MSPointerCancel';
+ } else {
+ mousedown = 'touchstart';
+ mousemove = 'touchmove';
+ mouseup = 'touchend touchcancel';
+ if (!('ontouchstart' in window && navigator.userAgent.match(
+ /mobile|tablet|ip(ad|hone|od)|android|silk/i))) {
+ mousedown += ' mousedown';
+ mousemove += ' mousemove';
+ mouseup += ' mouseup';
+ }
+ }
+
+ var viewEvents = {
+ 'selectstart dragstart': function(event) {
+ if (dragging)
+ event.preventDefault();
+ }
+ };
+
+ var docEvents = {
+ mouseout: function(event) {
+ var view = View._focused,
+ target = DomEvent.getRelatedTarget(event);
+ if (view && (!target || target.nodeName === 'HTML'))
+ handleMouseMove(view, viewToProject(view, event), event);
+ },
+
+ scroll: updateFocus
+ };
+
+ viewEvents[mousedown] = function(event) {
+ var view = View._focused = getView(event),
+ point = viewToProject(view, event);
+ dragging = true;
+ view._handleEvent('mousedown', point, event);
+ if (tool = view._scope.tool)
+ tool._handleEvent('mousedown', point, event);
+ view.update();
+ };
+
+ docEvents[mousemove] = function(event) {
+ var view = View._focused;
+ if (!dragging) {
+ var target = getView(event);
+ if (target) {
+ if (view !== target)
+ handleMouseMove(view, viewToProject(view, event), event);
+ prevFocus = view;
+ view = View._focused = tempFocus = target;
+ } else if (tempFocus && tempFocus === view) {
+ view = View._focused = prevFocus;
+ updateFocus();
+ }
+ }
+ if (view) {
+ var point = viewToProject(view, event);
+ if (dragging || view.getBounds().contains(point))
+ tool = handleMouseMove(view, point, event);
+ }
+ };
+
+ docEvents[mouseup] = function(event) {
+ var view = View._focused;
+ if (!view || !dragging)
+ return;
+ var point = viewToProject(view, event);
+ dragging = false;
+ view._handleEvent('mouseup', point, event);
+ if (tool)
+ tool._handleEvent('mouseup', point, event);
+ view.update();
+ };
+
+ DomEvent.add(document, docEvents);
+
+ DomEvent.add(window, {
+ load: updateFocus
+ });
+
+ return {
+ _viewEvents: viewEvents,
+
+ _handleEvent: function() {},
+
+ statics: {
+ updateFocus: updateFocus
+ }
+ };
+});
+
+var CanvasView = View.extend({
+ _class: 'CanvasView',
+
+ initialize: function CanvasView(project, canvas) {
+ if (!(canvas instanceof HTMLCanvasElement)) {
+ var size = Size.read(arguments, 1);
+ if (size.isZero())
+ throw new Error(
+ 'Cannot create CanvasView with the provided argument: '
+ + [].slice.call(arguments, 1));
+ canvas = CanvasProvider.getCanvas(size);
+ }
+ this._context = canvas.getContext('2d');
+ this._eventCounters = {};
+ this._pixelRatio = 1;
+ if (!/^off|false$/.test(PaperScope.getAttribute(canvas, 'hidpi'))) {
+ var deviceRatio = window.devicePixelRatio || 1,
+ backingStoreRatio = DomElement.getPrefixed(this._context,
+ 'backingStorePixelRatio') || 1;
+ this._pixelRatio = deviceRatio / backingStoreRatio;
+ }
+ View.call(this, project, canvas);
+ },
+
+ _setViewSize: function(size) {
+ var element = this._element,
+ pixelRatio = this._pixelRatio,
+ width = size.width,
+ height = size.height;
+ element.width = width * pixelRatio;
+ element.height = height * pixelRatio;
+ if (pixelRatio !== 1) {
+ if (!PaperScope.hasAttribute(element, 'resize')) {
+ var style = element.style;
+ style.width = width + 'px';
+ style.height = height + 'px';
+ }
+ this._context.scale(pixelRatio, pixelRatio);
+ }
+ },
+
+ getPixelSize: function(size) {
+ var browser = paper.browser,
+ pixels;
+ if (browser && browser.firefox) {
+ var parent = this._element.parentNode,
+ temp = document.createElement('div');
+ temp.style.fontSize = size;
+ parent.appendChild(temp);
+ pixels = parseFloat(DomElement.getStyles(temp).fontSize);
+ parent.removeChild(temp);
+ } else {
+ var ctx = this._context,
+ prevFont = ctx.font;
+ ctx.font = size + ' serif';
+ pixels = parseFloat(ctx.font);
+ ctx.font = prevFont;
+ }
+ return pixels;
+ },
+
+ getTextWidth: function(font, lines) {
+ var ctx = this._context,
+ prevFont = ctx.font,
+ width = 0;
+ ctx.font = font;
+ for (var i = 0, l = lines.length; i < l; i++)
+ width = Math.max(width, ctx.measureText(lines[i]).width);
+ ctx.font = prevFont;
+ return width;
+ },
+
+ update: function(force) {
+ var project = this._project;
+ if (!project || !force && !project._needsUpdate)
+ return false;
+ var ctx = this._context,
+ size = this._viewSize;
+ ctx.clearRect(0, 0, size.width + 1, size.height + 1);
+ project.draw(ctx, this._matrix, this._pixelRatio);
+ project._needsUpdate = false;
+ return true;
+ }
+}, new function() {
+
+ var downPoint,
+ lastPoint,
+ overPoint,
+ downItem,
+ lastItem,
+ overItem,
+ dragItem,
+ dblClick,
+ clickTime;
+
+ function callEvent(view, type, event, point, target, lastPoint) {
+ var item = target,
+ mouseEvent;
+
+ function call(obj) {
+ if (obj.responds(type)) {
+ if (!mouseEvent) {
+ mouseEvent = new MouseEvent(type, event, point, target,
+ lastPoint ? point.subtract(lastPoint) : null);
+ }
+ if (obj.emit(type, mouseEvent) && mouseEvent.isStopped) {
+ event.preventDefault();
+ return true;
+ }
+ }
+ }
+
+ while (item) {
+ if (call(item))
+ return true;
+ item = item.getParent();
+ }
+ if (call(view))
+ return true;
+ return false;
+ }
+
+ return {
+ _handleEvent: function(type, point, event) {
+ if (!this._eventCounters[type])
+ return;
+ var project = this._project,
+ hit = project.hitTest(point, {
+ tolerance: 0,
+ fill: true,
+ stroke: true
+ }),
+ item = hit && hit.item,
+ stopped = false;
+ switch (type) {
+ case 'mousedown':
+ stopped = callEvent(this, type, event, point, item);
+ dblClick = lastItem == item && (Date.now() - clickTime < 300);
+ downItem = lastItem = item;
+ downPoint = lastPoint = overPoint = point;
+ dragItem = !stopped && item;
+ while (dragItem && !dragItem.responds('mousedrag'))
+ dragItem = dragItem._parent;
+ break;
+ case 'mouseup':
+ stopped = callEvent(this, type, event, point, item, downPoint);
+ if (dragItem) {
+ if (lastPoint && !lastPoint.equals(point))
+ callEvent(this, 'mousedrag', event, point, dragItem,
+ lastPoint);
+ if (item !== dragItem) {
+ overPoint = point;
+ callEvent(this, 'mousemove', event, point, item,
+ overPoint);
+ }
+ }
+ if (!stopped && item && item === downItem) {
+ clickTime = Date.now();
+ callEvent(this, dblClick && downItem.responds('doubleclick')
+ ? 'doubleclick' : 'click', event, downPoint, item);
+ dblClick = false;
+ }
+ downItem = dragItem = null;
+ break;
+ case 'mousemove':
+ if (dragItem)
+ stopped = callEvent(this, 'mousedrag', event, point,
+ dragItem, lastPoint);
+ if (!stopped) {
+ if (item !== overItem)
+ overPoint = point;
+ stopped = callEvent(this, type, event, point, item,
+ overPoint);
+ }
+ lastPoint = overPoint = point;
+ if (item !== overItem) {
+ callEvent(this, 'mouseleave', event, point, overItem);
+ overItem = item;
+ callEvent(this, 'mouseenter', event, point, item);
+ }
+ break;
+ }
+ return stopped;
+ }
+ };
+});
+
+var Event = Base.extend({
+ _class: 'Event',
+
+ initialize: function Event(event) {
+ this.event = event;
+ },
+
+ isPrevented: false,
+ isStopped: false,
+
+ preventDefault: function() {
+ this.isPrevented = true;
+ this.event.preventDefault();
+ },
+
+ stopPropagation: function() {
+ this.isStopped = true;
+ this.event.stopPropagation();
+ },
+
+ 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 = {},
+ commandFixMap,
+ 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 (down) {
+ charCodeMap[keyCode] = charCode;
+ } else {
+ delete charCodeMap[keyCode];
+ }
+ if (specialKey && (name = Base.camelize(specialKey)) in modifiers) {
+ modifiers[name] = down;
+ var browser = paper.browser;
+ if (name === 'command' && browser && browser.mac) {
+ if (down) {
+ commandFixMap = {};
+ } else {
+ for (var code in commandFixMap) {
+ if (code in charCodeMap)
+ handleKey(false, code, commandFixMap[code], event);
+ }
+ commandFixMap = null;
+ }
+ }
+ } else if (down && commandFixMap) {
+ commandFixMap[keyCode] = charCode;
+ }
+ if (tool && tool.responds(type)) {
+ paper = scope;
+ tool.emit(type, new KeyEvent(down, key, character, event));
+ if (view)
+ view.update();
+ }
+ }
+
+ DomEvent.add(document, {
+ keydown: function(event) {
+ var code = event.which || event.keyCode;
+ if (code in specialKeys || modifiers.command) {
+ handleKey(true, code,
+ code in specialChars || modifiers.command ? 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()
+ + ' }';
+ }
+});
+
+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|CompoundPath)$/.test(parent._class)) {
+ 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 (minDistance != null && this._maxDistance != null
+ && minDistance > this._maxDistance) {
+ this._maxDistance = minDistance;
+ }
+ },
+
+ getMaxDistance: function() {
+ return this._maxDistance;
+ },
+
+ setMaxDistance: function(maxDistance) {
+ this._maxDistance = maxDistance;
+ if (this._minDistance != null && maxDistance != null
+ && 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;
+ if (maxDistance != null && maxDistance != 0) {
+ if (distance > maxDistance) {
+ point = this._point.add(vector.normalize(maxDistance));
+ } 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.emit(type, new ToolEvent(this, type, event));
+ },
+
+ _handleEvent: 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;
+ }
+ if (called)
+ event.preventDefault();
+ return called;
+ }
+
+});
+
+var Http = {
+ request: function(method, url, callback, async) {
+ async = (async === undefined) ? true : async;
+ var xhr = new (window.ActiveXObject || XMLHttpRequest)(
+ 'Microsoft.XMLHTTP');
+ xhr.open(method.toUpperCase(), url, async);
+ 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) {
+ var canvas,
+ clear = true;
+ if (typeof width === 'object') {
+ height = width.height;
+ width = width.width;
+ }
+ 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 (clear)
+ ctx.clearRect(0, 0, width + 1, height + 1);
+ } else {
+ canvas.width = width;
+ canvas.height = height;
+ }
+ ctx.save();
+ 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) {
+ var darken = mode === 'darken',
+ ok = false;
+ ctx.save();
+ try {
+ 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;
+ }
+ } catch (e) {}
+ ctx.restore();
+ nativeModes[mode] = ok;
+ });
+ 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'],
+ strokeScaling: ['vector-effect', 'lookup', {
+ true: 'none',
+ false: 'non-scaling-stroke'
+ }, function(item, value) {
+ return !value
+ && (item instanceof PathItem
+ || item instanceof Shape
+ || item instanceof TextItem);
+ }],
+ miterLimit: ['stroke-miterlimit', 'number'],
+ dashArray: ['stroke-dasharray', 'array'],
+ dashOffset: ['stroke-dashoffset', 'number'],
+ fontFamily: ['font-family', 'string'],
+ fontWeight: ['font-weight', '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;
+ }, {}),
+ exportFilter: entry[3],
+ 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(matrix, coordinates, center) {
+ var attrs = new Base(),
+ trans = matrix.getTranslation();
+ 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()) {
+ 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._matrix),
+ 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, options) {
+ var attrs = getTransform(item._matrix, true),
+ size = item.getSize(),
+ image = item.getImage();
+ attrs.x -= size.width / 2;
+ attrs.y -= size.height / 2;
+ attrs.width = size.width;
+ attrs.height = size.height;
+ attrs.href = options.embedImages === false && image && image.src
+ || item.toDataURL();
+ return createElement('image', attrs);
+ }
+
+ function exportPath(item, options) {
+ var matchShapes = options.matchShapes;
+ if (matchShapes) {
+ var shape = item.toShape(false);
+ if (shape)
+ return exportShape(shape, options);
+ }
+ var segments = item._segments,
+ type,
+ attrs = getTransform(item._matrix);
+ if (segments.length === 0)
+ return null;
+ if (matchShapes && !item.hasHandles()) {
+ if (segments.length >= 3) {
+ type = item._closed ? 'polygon' : 'polyline';
+ var parts = [];
+ for(var 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.set({
+ x1: first.x,
+ y1: first.y,
+ x2: last.x,
+ y2: last.y
+ });
+ }
+ } else {
+ type = 'path';
+ attrs.d = item.getPathData(null, options.precision);
+ }
+ return createElement(type, attrs);
+ }
+
+ function exportShape(item) {
+ var type = item._type,
+ radius = item._radius,
+ attrs = getTransform(item._matrix, true, type !== 'rectangle');
+ if (type === 'rectangle') {
+ type = '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 (type === 'circle') {
+ attrs.r = radius;
+ } else {
+ attrs.rx = radius.width;
+ attrs.ry = radius.height;
+ }
+ }
+ return createElement(type, attrs);
+ }
+
+ function exportCompoundPath(item, options) {
+ var attrs = getTransform(item._matrix);
+ var data = item.getPathData(null, options.precision);
+ if (data)
+ attrs.d = data;
+ return createElement('path', attrs);
+ }
+
+ function exportPlacedSymbol(item, options) {
+ var attrs = getTransform(item._matrix, 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);
+ attrs.overflow = 'visible';
+ 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._matrix, true));
+ node.textContent = item._content;
+ return node;
+ }
+
+ var exporters = {
+ Group: exportGroup,
+ Layer: exportGroup,
+ Raster: exportRaster,
+ Path: exportPath,
+ Shape: exportShape,
+ CompoundPath: exportCompoundPath,
+ PlacedSymbol: exportPlacedSymbol,
+ PointText: exportText
+ };
+
+ function applyStyle(item, node, isRoot) {
+ var attrs = {},
+ parent = !isRoot && 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 (entry.exportFilter
+ ? entry.exportFilter(item, value)
+ : !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._visible)
+ 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, isRoot) {
+ var exporter = exporters[item._class],
+ node = exporter && exporter(item, options);
+ if (node) {
+ var onExport = options.onExport;
+ if (onExport)
+ node = onExport(item, node, options) || node;
+ var data = JSON.stringify(item._data);
+ if (data && data !== '{}' && data !== 'null')
+ node.setAttribute('data-paper-data', data);
+ }
+ return node && applyStyle(item, node, isRoot);
+ }
+
+ 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, true), options);
+ }
+ });
+
+ Project.inject({
+ exportSVG: function(options) {
+ options = setOptions(options);
+ var layers = this.layers,
+ view = this.getView(),
+ size = view.getViewSize(),
+ 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'
+ }),
+ parent = node,
+ matrix = view._matrix;
+ if (!matrix.isIdentity())
+ parent = node.appendChild(
+ createElement('g', getTransform(matrix)));
+ for (var i = 0, l = layers.length; i < l; i++)
+ parent.appendChild(exportSVG(layers[i], options, true));
+ 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, options, isRoot) {
+ var nodes = node.childNodes,
+ isClip = type === 'clippath',
+ item = new Group(),
+ project = item._project,
+ currentStyle = project._currentStyle,
+ children = [];
+ if (!isClip) {
+ item = applyAttributes(item, node, isRoot);
+ project._currentStyle = item._style.clone();
+ }
+ if (isRoot) {
+ var defs = node.querySelectorAll('defs');
+ for (var i = 0, l = defs.length; i < l; i++) {
+ importSVG(defs[i], options, false);
+ }
+ }
+ for (var i = 0, l = nodes.length; i < l; i++) {
+ var childNode = nodes[i],
+ child;
+ if (childNode.nodeType === 1
+ && childNode.nodeName.toLowerCase() !== 'defs'
+ && (child = importSVG(childNode, options, false))
+ && !(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 coords = node.getAttribute('points').match(
+ /[+-]?(?:\d*\.\d+|\d+\.?)(?:[eE][+-]?\d+)?/g),
+ points = [];
+ for (var i = 0, l = coords.length; i < l; i += 2)
+ points.push(new Point(
+ parseFloat(coords[i]),
+ parseFloat(coords[i + 1])));
+ var path = new Path(points);
+ if (type === 'polygon')
+ path.closePath();
+ return path;
+ }
+
+ function importPath(node) {
+ var data = node.getAttribute('d'),
+ param = { pathData: data };
+ return (data.match(/m/gi) || []).length > 1 || /z\S+/i.test(data)
+ ? new CompoundPath(param)
+ : new Path(param);
+ }
+
+ function importGradient(node, type) {
+ var id = (getValue(node, 'href', true) || '').substring(1),
+ isRadial = type === 'radialgradient',
+ gradient;
+ if (id) {
+ gradient = definitions[id].getGradient();
+ } else {
+ 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));
+ }
+ gradient = new Gradient(stops, isRadial);
+ }
+ var 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, options, isRoot) {
+ 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, options, isRoot);
+ 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.on('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, options, isRoot) {
+ return new Symbol(importGroup(node, type, options, isRoot), 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(/\(\s*/),
+ 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':
+ matrix.skew(v[0], 0);
+ break;
+ case 'skewY':
+ matrix.skew(0, v[0]);
+ 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.set(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');
+ },
+
+ display: function(item, value) {
+ item.setVisible(value !== null);
+ },
+
+ '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, options, isRoot) {
+ 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, options, isRoot),
+ onLoad = options.onLoad,
+ view = scope.project && scope.getView();
+ if (onLoad)
+ onLoad.call(this, item);
+ view.update();
+ }
+
+ 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,
+ data = node.getAttribute && node.getAttribute('data-paper-data'),
+ settings = scope.settings,
+ applyMatrix = settings.applyMatrix;
+ settings.applyMatrix = false;
+ item = importer && importer(node, type, options, isRoot) || null;
+ settings.applyMatrix = applyMatrix;
+ if (item) {
+ if (type !== '#document' && !(item instanceof Group))
+ item = applyAttributes(item, node, isRoot);
+ var onImport = options.onImport;
+ if (onImport)
+ item = onImport(node, item, options) || item;
+ if (options.expandShapes && item instanceof Shape) {
+ item.remove();
+ item = item.toPath();
+ }
+ if (data)
+ item._data = JSON.parse(data);
+ }
+ if (isRoot) {
+ definitions = {};
+ if (item && Base.pick(options.applyMatrix, applyMatrix))
+ item.matrix.apply(true, true);
+ }
+ return item;
+ }
+
+ Item.inject({
+ importSVG: function(node, options) {
+ return this.addChild(importSVG(node, options, true));
+ }
+ });
+
+ Project.inject({
+ importSVG: function(node, options) {
+ this.activate();
+ return importSVG(node, options, true);
+ }
+ });
+};
+
+Base.exports.PaperScript = (function() {
+ var 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 mr)Object.prototype.hasOwnProperty.call(fr,r)||(fr[r]=mr[r]);hr=fr.sourceFile||null}function t(e,r){var t=vr(dr,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=dr.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(dr))&&o.index<br;)++Ar,Sr=o.index+o[0].length}fr.onComment&&fr.onComment(!0,dr.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=dr.charCodeAt(br+=2);pr>br&&10!==t&&13!==t&&8232!==t&&8233!==t;)++br,t=dr.charCodeAt(br);fr.onComment&&fr.onComment(!1,dr.slice(e+2,br),e,br,r,fr.locations&&new a)}function u(){for(;pr>br;){var e=dr.charCodeAt(br);if(32===e)++br;else if(13===e){++br;var r=dr.charCodeAt(br);10===r&&++br,fr.locations&&(++Ar,Sr=br)}else if(10===e||8232===e||8233===e)++br,fr.locations&&(++Ar,Sr=br);else if(e>8&&14>e)++br;else if(47===e){var r=dr.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=dr.charCodeAt(br+1);return e>=48&&57>=e?E(!0):(++br,i(xt))}function f(){var e=dr.charCodeAt(br+1);return Er?(++br,k()):61===e?x(Et,2):x(wt,1)}function d(){var e=dr.charCodeAt(br+1);return 61===e?x(Et,2):x(Dt,1)}function p(e){var r=dr.charCodeAt(br+1);return r===e?x(124===e?Lt:Ut,2):61===r?x(Et,2):x(124===e?Rt:Tt,1)}function h(){var e=dr.charCodeAt(br+1);return 61===e?x(Et,2):x(Vt,1)}function m(e){var r=dr.charCodeAt(br+1);return r===e?45==r&&62==dr.charCodeAt(br+2)&&Gt.test(dr.slice(Lr,br))?(br+=3,c(),u(),g()):x(St,2):61===r?x(Et,2):x(At,1)}function v(e){var r=dr.charCodeAt(br+1),t=1;return r===e?(t=62===e&&62===dr.charCodeAt(br+2)?3:2,61===dr.charCodeAt(br+t)?x(Et,t+1):x(jt,t)):33==r&&60==e&&45==dr.charCodeAt(br+2)&&45==dr.charCodeAt(br+3)?(br+=4,c(),u(),g()):(61===r&&(t=61===dr.charCodeAt(br+2)?3:2),x(Ot,t))}function b(e){var r=dr.charCodeAt(br+1);return 61===r?x(qt,61===dr.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(mt);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(dt);case 123:return++br,i(pt);case 125:return++br,i(ht);case 58:return++br,i(gt);case 63:return++br,i(kt);case 48:var r=dr.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 d();case 124:case 38:return p(e);case 94:return h();case 43:case 45:return m(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>=pr)return i(Br);var r=dr.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=dr.slice(br,br+r);br+=r,i(e,t)}function k(){for(var e,r,n="",a=br;;){br>=pr&&t(a,"Unterminated regular expression");var o=dr.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=dr.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=dr.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(dr.charCodeAt(br))&&t(br,"Identifier directly after number"),i(Or,e)}function E(e){var r=br,n=!1,a=48===dr.charCodeAt(br);e||null!==w(10)||t(r,"Invalid number"),46===dr.charCodeAt(br)&&(++br,w(10),n=!0);var o=dr.charCodeAt(br);(69===o||101===o)&&(o=dr.charCodeAt(++br),(43===o||45===o)&&++br,null===w(10)&&t(r,"Invalid number"),n=!0),Qt(dr.charCodeAt(br))&&t(br,"Identifier directly after number");var s,c=dr.slice(r,br);return n?s=parseFloat(c):a&&1!==c.length?/[89]/.test(c)||Tr?t(r,"Invalid number"):s=parseInt(c,8):s=parseInt(c,10),i(Or,s)}function A(e){br++;for(var r="";;){br>=pr&&t(yr,"Unterminated string constant");var n=dr.charCodeAt(br);if(n===e)return++br,i(Dr,r);if(92===n){n=dr.charCodeAt(++br);var a=/^[0-7]+/.exec(dr.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)Tr&&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===dr.charCodeAt(br)&&++br;case 10:fr.locations&&(Sr=br,++Ar);break;default:r+=String.fromCharCode(n)}}else(13===n||10===n||8232===n||8233===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=dr.charCodeAt(br);if(Yt(a))Bt&&(e+=dr.charAt(br)),++br;else{if(92!==a)break;Bt||(e=dr.slice(n,br)),Bt=!0,117!=dr.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:dr.slice(n,br)}function L(){var e=I(),r=Fr;return Bt||(Wt(e)?r=lt[e]:(fr.forbidReserved&&(3===fr.ecmaVersion?Mt:zt)(e)||Tr&&Xt(e))&&t(yr,"The keyword '"+e+"' is reserved")),i(r,e)}function U(){Ir=yr,Lr=gr,Ur=kr,g()}function R(e){if(Tr=e,br=Lr,fr.locations)for(;Sr>br;)Sr=dr.lastIndexOf("\n",Sr-2)+1,--Ar;u(),g()}function V(){this.type=null,this.start=yr,this.end=null}function T(){this.start=xr,this.end=null,null!==hr&&(this.source=hr)}function q(){var e=new V;return fr.locations&&(e.loc=new T),fr.ranges&&(e.range=[yr,0]),e}function O(e){var r=new V;return r.start=e.start,fr.locations&&(r.loc=new T,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 D(e){return fr.ecmaVersion>=5&&"ExpressionStatement"===e.type&&"Literal"===e.expression.type&&"use strict"===e.expression.value}function F(e){return wr===e?(U(),!0):void 0}function B(){return!fr.strictSemicolons&&(wr===Br||wr===ht||Gt.test(dr.slice(Lr,yr)))}function M(){F(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"),Tr&&"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=Tr=null,Vr=[],g();var r=e||q(),t=!0;for(e||(r.body=[]);wr!==Br;){var n=J();r.body.push(n),t&&D(n)&&R(!0),t=!1}return j(r,"Program")}function J(){(wr===wt||wr===Et&&"/="==Cr)&&g(!0);var e=wr,r=q();switch(e){case Mr:case Nr:U();var n=e===Mr;F(yt)||B()?r.label=null:wr!==Fr?X():(r.label=lr(),M());for(var a=0;a<Vr.length;++a){var o=Vr[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===Vr.length&&t(r.start,"Unsyntactic "+e.keyword),j(r,n?"BreakStatement":"ContinueStatement");case Wr:return U(),M(),j(r,"DebuggerStatement");case Pr:return U(),Vr.push(Zt),r.body=J(),Vr.pop(),z(tt),r.test=P(),M(),j(r,"DoWhileStatement");case _r:if(U(),Vr.push(Zt),z(mt),wr===yt)return $(r,null);if(wr===rt){var i=q();return U(),G(i,!0),j(i,"VariableDeclaration"),1===i.declarations.length&&F(ut)?_(r,i):$(r,i)}var i=K(!1,!0);return F(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=F(Hr)?J():null,j(r,"IfStatement");case Qr:return Rr||t(yr,"'return' outside of function"),U(),F(yt)||B()?r.argument=null:(r.argument=K(),M()),j(r,"ReturnStatement");case Yr:U(),r.discriminant=P(),r.cases=[],z(pt),Vr.push(en);for(var s,c;wr!=ht;)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(),Vr.pop(),j(r,"SwitchStatement");case Zr:return U(),Gt.test(dr.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(mt),l.param=lr(),Tr&&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=F($r)?H():null,r.handler||r.finalizer||t(r.start,"Missing catch or finally clause"),j(r,"TryStatement");case rt:return U(),G(r),M(),j(r,"VariableDeclaration");case tt:return U(),r.test=P(),Vr.push(Zt),r.body=J(),Vr.pop(),j(r,"WhileStatement");case nt:return Tr&&t(yr,"'with' in strict mode"),U(),r.object=P(),r.body=J(),j(r,"WithStatement");case pt:return H();case yt:return U(),j(r,"EmptyStatement");default:var f=Cr,d=K();if(e===Fr&&"Identifier"===d.type&&F(gt)){for(var a=0;a<Vr.length;++a)Vr[a].name===f&&t(d.start,"Label '"+f+"' is already declared");var p=wr.isLoop?"loop":wr===Yr?"switch":null;return Vr.push({name:f,kind:p}),r.body=J(),Vr.pop(),r.label=d,j(r,"LabeledStatement")}return r.expression=d,M(),j(r,"ExpressionStatement")}}function P(){z(mt);var e=K();return z(vt),e}function H(e){var r,t=q(),n=!0,a=!1;for(t.body=[],z(pt);!F(ht);){var o=J();t.body.push(o),n&&e&&D(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(),Vr.pop(),j(e,"ForStatement")}function _(e,r){return e.left=r,e.right=K(),z(vt),e.body=J(),Vr.pop(),j(e,"ForInStatement")}function G(e,r){for(e.declarations=[],e.kind="var";;){var n=q();if(n.id=lr(),Tr&&Nt(n.id.name)&&t(n.id.start,"Binding "+n.id.name+" in strict mode"),n.init=F(Ct)?K(!0,r):null,e.declarations.push(j(n,"VariableDeclarator")),!F(bt))break}return e}function K(e,r){var t=Q(r);if(!e&&wr===bt){var n=O(t);for(n.expressions=[t];F(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(F(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 o=j(a,/&&|\|\|/.test(a.operator)?"LogicalExpression":"BinaryExpression");return er(o,r,t)}return e}function rr(){if(wr.prefix){var e=q(),r=wr.isUpdate;return e.operator=Cr,e.prefix=!0,Er=!0,U(),e.argument=rr(),r?N(e.argument):Tr&&"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(F(xt)){var t=O(e);return t.object=e,t.property=lr(!0),t.computed=!1,nr(j(t,"MemberExpression"),r)}if(F(ft)){var t=O(e);return t.object=e,t.property=K(),t.computed=!0,z(dt),nr(j(t,"MemberExpression"),r)}if(!r&&F(mt)){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 Fr:return lr();case Or:case Dr:case jr:var e=q();return e.value=Cr,e.raw=dr.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 mt: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(dt,!0,!0),j(e,"ArrayExpression");case pt: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=F(mt)?ur(vt,!1):qr,j(e,"NewExpression")}function ir(){var e=q(),r=!0,n=!1;for(e.properties=[],U();!F(ht);){if(r)r=!1;else if(z(bt),fr.allowTrailingCommas&&F(ht))break;var a,o={key:sr()},i=!1;if(F(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!==mt&&X(),o.value=cr(q(),!1)):X(),"Identifier"===o.key.type&&(Tr||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&&!Tr&&"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===Dr?ar():lr(!0)}function cr(e,r){wr===Fr?e.id=lr():r?X():e.id=null,e.params=[];var n=!0;for(z(mt);!F(vt);)n?n=!1:z(bt),e.params.push(lr());var a=Rr,o=Vr;if(Rr=!0,Vr=[],e.body=H(!0),Rr=a,Vr=o,Tr||e.body.body.length&&D(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;!F(e);){if(a)a=!1;else if(z(bt),r&&fr.allowTrailingCommas&&F(e))break;t&&wr===bt?n.push(null):n.push(K(!0))}return n}function lr(e){var r=q();return r.name=wr===Fr?Cr:e&&!fr.forbidReserved&&wr.keyword||X(),Er=!1,U(),j(r,"Identifier")}e.version="0.4.0";var fr,dr,pr,hr;e.parse=function(e,t){return dr=String(e),pr=dr.length,r(t),o(),W(fr.program)};var mr=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}dr=String(e),pr=dr.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(dr))&&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,Vr,Tr,qr=[],Or={type:"num"},jr={type:"regexp"},Dr={type:"string"},Fr={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},dt={type:"]"},pt={type:"{",beforeExpr:!0},ht={type:"}"},mt={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},Vt={binop:4,beforeExpr:!0},Tt={binop:5,beforeExpr:!0},qt={binop:6,beforeExpr:!0},Ot={binop:7,beforeExpr:!0},jt={binop:8,beforeExpr:!0},Dt={binop:10,beforeExpr:!0};e.tokTypes={bracketL:ft,bracketR:dt,braceL:pt,braceR:ht,parenL:mt,parenR:vt,comma:bt,semi:yt,colon:gt,dot:xt,question:kt,slash:wt,eq:Ct,name:Fr,eof:Br,num:Or,regexp:jr,string:Dr};for(var Ft in lt)e.tokTypes["_"+Ft]=lt[Ft];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\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;
+ },
+ {}
+ );
+ Point.inject(fields);
+ Size.inject(fields);
+ 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 parse(code, options) {
+ return scope.acorn.parse(code, options);
+ }
+
+ function compile(code, url, options) {
+ if (!code)
+ return '';
+ options = options || {};
+ url = url || '';
+
+ 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 getBetween(left, right) {
+ return code.substring(getOffset(left.range[1]),
+ getOffset(right.range[0]));
+ }
+
+ function replaceCode(node, str) {
+ var start = getOffset(node.range[0]),
+ end = getOffset(node.range[1]),
+ 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' || key === 'loc')
+ 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.type) {
+ case 'UnaryExpression':
+ if (node.operator in unaryOperators
+ && node.argument.type !== 'Literal') {
+ var arg = getCode(node.argument);
+ replaceCode(node, '$__("' + node.operator + '", '
+ + arg + ')');
+ }
+ break;
+ case 'BinaryExpression':
+ if (node.operator in binaryOperators
+ && node.left.type !== 'Literal') {
+ var left = getCode(node.left),
+ right = getCode(node.right),
+ between = getBetween(node.left, node.right),
+ operator = node.operator;
+ replaceCode(node, '__$__(' + left + ','
+ + between.replace(new RegExp('\\' + operator),
+ '"' + operator + '"')
+ + ', ' + right + ')');
+ }
+ break;
+ case 'UpdateExpression':
+ case 'AssignmentExpression':
+ var parentType = parent && parent.type;
+ if (!(
+ parentType === 'ForStatement'
+ || parentType === 'BinaryExpression'
+ && /^[=!<>]/.test(parent.operator)
+ || parentType === 'MemberExpression' && parent.computed
+ )) {
+ if (node.type === 'UpdateExpression') {
+ var arg = getCode(node.argument),
+ exp = '__$__(' + arg + ', "' + node.operator[0]
+ + '", 1)',
+ str = arg + ' = ' + exp;
+ if (!node.prefix
+ && (parentType === 'AssignmentExpression'
+ || parentType === 'VariableDeclarator')) {
+ if (getCode(parent.left || parent.id) === arg)
+ str = exp;
+ str = arg + '; ' + str;
+ }
+ replaceCode(node, str);
+ } else {
+ 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;
+ }
+ }
+ var sourceMap = null,
+ browser = paper.browser,
+ version = browser.versionNumber,
+ lineBreaks = /\r\n|\n|\r/mg;
+ if (browser.chrome && version >= 30
+ || browser.webkit && version >= 537.76
+ || browser.firefox && version >= 23) {
+ var offset = 0;
+ if (window.location.href.indexOf(url) === 0) {
+ var html = document.getElementsByTagName('html')[0].innerHTML;
+ offset = html.substr(0, html.indexOf(code) + 1).match(
+ lineBreaks).length + 1;
+ }
+ var mappings = ['AAAA'];
+ mappings.length = (code.match(lineBreaks) || []).length + 1 + offset;
+ sourceMap = {
+ version: 3,
+ file: url,
+ names:[],
+ mappings: mappings.join(';AACA'),
+ sourceRoot: '',
+ sources: [url]
+ };
+ var source = options.source || !url && code;
+ if (source)
+ sourceMap.sourcesContent = [source];
+ }
+ walkAST(parse(code, { ranges: true }));
+ if (sourceMap) {
+ code = new Array(offset + 1).join('\n') + code
+ + "\n//# sourceMappingURL=data:application/json;base64,"
+ + (btoa(unescape(encodeURIComponent(
+ JSON.stringify(sourceMap)))))
+ + "\n//# sourceURL=" + (url || 'paperscript');
+ }
+ return code;
+ }
+
+ function execute(code, scope, url, options) {
+ paper = scope;
+ var view = scope.getView(),
+ tool = /\s+on(?:Key|Mouse)(?:Up|Down|Move|Drag)\b/.test(code)
+ ? new Tool()
+ : null,
+ toolHandlers = tool ? tool._events : [],
+ handlers = ['onFrame', 'onResize'].concat(toolHandlers),
+ params = [],
+ args = [],
+ func;
+ code = compile(code, url, options);
+ function expose(scope, hidden) {
+ for (var key in scope) {
+ if ((hidden || !/^_/.test(key)) && new RegExp('([\\b\\s\\W]|^)'
+ + key.replace(/\$/g, '\\$') + '\\b').test(code)) {
+ params.push(key);
+ args.push(scope[key]);
+ }
+ }
+ }
+ expose({ __$__: __$__, $__: $__, paper: scope, view: view, tool: tool },
+ true);
+ expose(scope);
+ handlers = Base.each(handlers, function(key) {
+ if (new RegExp('\\s+' + key + '\\b').test(code)) {
+ params.push(key);
+ this.push(key + ': ' + key);
+ }
+ }, []).join(', ');
+ if (handlers)
+ code += '\nreturn { ' + handlers + ' };';
+ var browser = paper.browser;
+ if (browser.chrome || browser.firefox) {
+ var script = document.createElement('script'),
+ head = document.head || document.getElementsByTagName('head')[0];
+ if (browser.firefox)
+ code = '\n' + code;
+ script.appendChild(document.createTextNode(
+ 'paper._execute = function(' + params + ') {' + code + '\n}'
+ ));
+ head.appendChild(script);
+ func = paper._execute;
+ delete paper._execute;
+ head.removeChild(script);
+ } else {
+ func = Function(params, code);
+ }
+ var res = func.apply(scope, args) || {};
+ Base.each(toolHandlers, function(key) {
+ var value = res[key];
+ if (value)
+ tool[key] = value;
+ });
+ if (view) {
+ if (res.onResize)
+ view.setOnResize(res.onResize);
+ view.emit('resize', {
+ size: view.size,
+ delta: new Point()
+ });
+ if (res.onFrame)
+ view.setOnFrame(res.onFrame);
+ view.update();
+ }
+ }
+
+ function loadScript(script) {
+ if (/^text\/(?:x-|)paperscript$/.test(script.type)
+ && PaperScope.getAttribute(script, 'ignore') !== 'true') {
+ var canvasId = PaperScope.getAttribute(script, 'canvas'),
+ canvas = document.getElementById(canvasId),
+ src = script.src || script.getAttribute('data-src'),
+ async = PaperScope.hasAttribute(script, 'async'),
+ scopeAttribute = 'data-paper-scope';
+ if (!canvas)
+ throw new Error('Unable to find canvas with id "'
+ + canvasId + '"');
+ var scope = PaperScope.get(canvas.getAttribute(scopeAttribute))
+ || new PaperScope().setup(canvas);
+ canvas.setAttribute(scopeAttribute, scope._id);
+ if (src) {
+ Http.request('get', src, function(code) {
+ execute(code, scope, src);
+ }, async);
+ } else {
+ execute(script.innerHTML, scope, script.baseURI);
+ }
+ script.setAttribute('data-paper-ignore', 'true');
+ return scope;
+ }
+ }
+
+ function loadAll() {
+ Base.each(document.getElementsByTagName('script'), loadScript);
+ }
+
+ function load(script) {
+ return script ? loadScript(script) : loadAll();
+ }
+
+ if (document.readyState === 'complete') {
+ setTimeout(loadAll);
+ } else {
+ DomEvent.add(window, { load: loadAll });
+ }
+
+ return {
+ compile: compile,
+ execute: execute,
+ load: load,
+ parse: parse
+ };
+
+}).call(this);
+
+paper = new (PaperScope.inject(Base.exports, {
+ enumerable: true,
+ Base: Base,
+ Numerical: Numerical,
+ Key: Key
+}))();
+
+if (typeof define === 'function' && define.amd) {
+ define('paper', paper);
+} else if (typeof module === 'object' && module) {
+ module.exports = paper;
+}
+
+return paper;
+};
--- a/src/ldt/ldt/static/ldt/js/popcorn-complete.min.js Fri Sep 18 16:10:29 2015 +0200
+++ b/src/ldt/ldt/static/ldt/js/popcorn-complete.min.js Fri Oct 02 10:24:05 2015 +0200
@@ -1,160 +1,209 @@
/*
- * popcorn.js version 1.3
+ * popcorn.js version 1.5.6
* http://popcornjs.org
*
* Copyright 2011, Mozilla Foundation
* Licensed under the MIT license
*/
-(function(r,f){function n(a,g){return function(){if(d.plugin.debug)return a.apply(this,arguments);try{return a.apply(this,arguments)}catch(l){d.plugin.errors.push({plugin:g,thrown:l,source:a.toString()});this.emit("pluginerror",d.plugin.errors)}}}if(f.addEventListener){var c=Array.prototype,b=Object.prototype,e=c.forEach,h=c.slice,i=b.hasOwnProperty,j=b.toString,p=r.Popcorn,m=[],o=false,q={events:{hash:{},apis:{}}},s=function(){return r.requestAnimationFrame||r.webkitRequestAnimationFrame||r.mozRequestAnimationFrame||
-r.oRequestAnimationFrame||r.msRequestAnimationFrame||function(a){r.setTimeout(a,16)}}(),d=function(a,g){return new d.p.init(a,g||null)};d.version="1.3";d.isSupported=true;d.instances=[];d.p=d.prototype={init:function(a,g){var l,k=this;if(typeof a==="function")if(f.readyState==="complete")a(f,d);else{m.push(a);if(!o){o=true;var t=function(){f.removeEventListener("DOMContentLoaded",t,false);for(var z=0,C=m.length;z<C;z++)m[z].call(f,d);m=null};f.addEventListener("DOMContentLoaded",t,false)}}else{if(typeof a===
-"string")try{l=f.querySelector(a)}catch(u){throw Error("Popcorn.js Error: Invalid media element selector: "+a);}this.media=l||a;l=this.media.nodeName&&this.media.nodeName.toLowerCase()||"video";this[l]=this.media;this.options=g||{};this.id=this.options.id||d.guid(l);if(d.byId(this.id))throw Error("Popcorn.js Error: Cannot use duplicate ID ("+this.id+")");this.isDestroyed=false;this.data={running:{cue:[]},timeUpdate:d.nop,disabled:{},events:{},hooks:{},history:[],state:{volume:this.media.volume},trackRefs:{},
-trackEvents:{byStart:[{start:-1,end:-1}],byEnd:[{start:-1,end:-1}],animating:[],startIndex:0,endIndex:0,previousUpdateTime:-1}};d.instances.push(this);var v=function(){if(k.media.currentTime<0)k.media.currentTime=0;k.media.removeEventListener("loadeddata",v,false);var z,C,E,B,w;z=k.media.duration;z=z!=z?Number.MAX_VALUE:z+1;d.addTrackEvent(k,{start:z,end:z});if(k.options.frameAnimation){k.data.timeUpdate=function(){d.timeUpdate(k,{});d.forEach(d.manifest,function(D,F){if(C=k.data.running[F]){B=C.length;
-for(var I=0;I<B;I++){E=C[I];(w=E._natives)&&w.frame&&w.frame.call(k,{},E,k.currentTime())}}});k.emit("timeupdate");!k.isDestroyed&&s(k.data.timeUpdate)};!k.isDestroyed&&s(k.data.timeUpdate)}else{k.data.timeUpdate=function(D){d.timeUpdate(k,D)};k.isDestroyed||k.media.addEventListener("timeupdate",k.data.timeUpdate,false)}};Object.defineProperty(this,"error",{get:function(){return k.media.error}});k.media.readyState>=2?v():k.media.addEventListener("loadeddata",v,false);return this}}};d.p.init.prototype=
-d.p;d.byId=function(a){for(var g=d.instances,l=g.length,k=0;k<l;k++)if(g[k].id===a)return g[k];return null};d.forEach=function(a,g,l){if(!a||!g)return{};l=l||this;var k,t;if(e&&a.forEach===e)return a.forEach(g,l);if(j.call(a)==="[object NodeList]"){k=0;for(t=a.length;k<t;k++)g.call(l,a[k],k,a);return a}for(k in a)i.call(a,k)&&g.call(l,a[k],k,a);return a};d.extend=function(a){var g=h.call(arguments,1);d.forEach(g,function(l){for(var k in l)a[k]=l[k]});return a};d.extend(d,{noConflict:function(a){if(a)r.Popcorn=
-p;return d},error:function(a){throw Error(a);},guid:function(a){d.guid.counter++;return(a?a:"")+(+new Date+d.guid.counter)},sizeOf:function(a){var g=0,l;for(l in a)g++;return g},isArray:Array.isArray||function(a){return j.call(a)==="[object Array]"},nop:function(){},position:function(a){a=a.getBoundingClientRect();var g={},l=f.documentElement,k=f.body,t,u,v;t=l.clientTop||k.clientTop||0;u=l.clientLeft||k.clientLeft||0;v=r.pageYOffset&&l.scrollTop||k.scrollTop;l=r.pageXOffset&&l.scrollLeft||k.scrollLeft;
-t=Math.ceil(a.top+v-t);u=Math.ceil(a.left+l-u);for(var z in a)g[z]=Math.round(a[z]);return d.extend({},g,{top:t,left:u})},disable:function(a,g){if(!a.data.disabled[g]){a.data.disabled[g]=true;for(var l=a.data.running[g].length-1,k;l>=0;l--){k=a.data.running[g][l];k._natives.end.call(a,null,k)}}return a},enable:function(a,g){if(a.data.disabled[g]){a.data.disabled[g]=false;for(var l=a.data.running[g].length-1,k;l>=0;l--){k=a.data.running[g][l];k._natives.start.call(a,null,k)}}return a},destroy:function(a){var g=
-a.data.events,l=a.data.trackEvents,k,t,u,v;for(t in g){k=g[t];for(u in k)delete k[u];g[t]=null}for(v in d.registryByName)d.removePlugin(a,v);l.byStart.length=0;l.byEnd.length=0;if(!a.isDestroyed){a.data.timeUpdate&&a.media.removeEventListener("timeupdate",a.data.timeUpdate,false);a.isDestroyed=true}}});d.guid.counter=1;d.extend(d.p,function(){var a={};d.forEach("load play pause currentTime playbackRate volume duration preload playbackRate autoplay loop controls muted buffered readyState seeking paused played seekable ended".split(/\s+/g),
-function(g){a[g]=function(l){var k;if(typeof this.media[g]==="function"){if(l!=null&&/play|pause/.test(g))this.media.currentTime=d.util.toSeconds(l);this.media[g]();return this}if(l!=null){k=this.media[g];this.media[g]=l;k!==l&&this.emit("attrchange",{attribute:g,previousValue:k,currentValue:l});return this}return this.media[g]}});return a}());d.forEach("enable disable".split(" "),function(a){d.p[a]=function(g){return d[a](this,g)}});d.extend(d.p,{roundTime:function(){return Math.round(this.media.currentTime)},
-exec:function(a,g,l){var k=arguments.length,t,u;try{u=d.util.toSeconds(a)}catch(v){}if(typeof u==="number")a=u;if(typeof a==="number"&&k===2){l=g;g=a;a=d.guid("cue")}else if(k===1)g=-1;else if(t=this.getTrackEvent(a)){if(typeof a==="string"&&k===2){if(typeof g==="number")l=t._natives.start;if(typeof g==="function"){l=g;g=t.start}}}else if(k>=2){if(typeof g==="string"){try{u=d.util.toSeconds(g)}catch(z){}g=u}if(typeof g==="number")l=d.nop();if(typeof g==="function"){l=g;g=-1}}d.addTrackEvent(this,
-{id:a,start:g,end:g+1,_running:false,_natives:{start:l||d.nop,end:d.nop,type:"cue"}});return this},mute:function(a){a=a==null||a===true?"muted":"unmuted";if(a==="unmuted"){this.media.muted=false;this.media.volume=this.data.state.volume}if(a==="muted"){this.data.state.volume=this.media.volume;this.media.muted=true}this.emit(a);return this},unmute:function(a){return this.mute(a==null?false:!a)},position:function(){return d.position(this.media)},toggle:function(a){return d[this.data.disabled[a]?"enable":
-"disable"](this,a)},defaults:function(a,g){if(d.isArray(a)){d.forEach(a,function(l){for(var k in l)this.defaults(k,l[k])},this);return this}if(!this.options.defaults)this.options.defaults={};this.options.defaults[a]||(this.options.defaults[a]={});d.extend(this.options.defaults[a],g);return this}});d.Events={UIEvents:"blur focus focusin focusout load resize scroll unload",MouseEvents:"mousedown mouseup mousemove mouseover mouseout mouseenter mouseleave click dblclick",Events:"loadstart progress suspend emptied stalled play pause error loadedmetadata loadeddata waiting playing canplay canplaythrough seeking seeked timeupdate ended ratechange durationchange volumechange"};
-d.Events.Natives=d.Events.UIEvents+" "+d.Events.MouseEvents+" "+d.Events.Events;q.events.apiTypes=["UIEvents","MouseEvents","Events"];(function(a,g){for(var l=q.events.apiTypes,k=a.Natives.split(/\s+/g),t=0,u=k.length;t<u;t++)g.hash[k[t]]=true;l.forEach(function(v){g.apis[v]={};for(var z=a[v].split(/\s+/g),C=z.length,E=0;E<C;E++)g.apis[v][z[E]]=true})})(d.Events,q.events);d.events={isNative:function(a){return!!q.events.hash[a]},getInterface:function(a){if(!d.events.isNative(a))return false;var g=
-q.events,l=g.apiTypes;g=g.apis;for(var k=0,t=l.length,u,v;k<t;k++){v=l[k];if(g[v][a]){u=v;break}}return u},all:d.Events.Natives.split(/\s+/g),fn:{trigger:function(a,g){var l;if(this.data.events[a]&&d.sizeOf(this.data.events[a])){if(l=d.events.getInterface(a)){l=f.createEvent(l);l.initEvent(a,true,true,r,1);this.media.dispatchEvent(l);return this}d.forEach(this.data.events[a],function(k){k.call(this,g)},this)}return this},listen:function(a,g){var l=this,k=true,t=d.events.hooks[a],u;if(!this.data.events[a]){this.data.events[a]=
-{};k=false}if(t){t.add&&t.add.call(this,{},g);if(t.bind)a=t.bind;if(t.handler){u=g;g=function(v){t.handler.call(l,v,u)}}k=true;if(!this.data.events[a]){this.data.events[a]={};k=false}}this.data.events[a][g.name||g.toString()+d.guid()]=g;!k&&d.events.all.indexOf(a)>-1&&this.media.addEventListener(a,function(v){d.forEach(l.data.events[a],function(z){typeof z==="function"&&z.call(l,v)})},false);return this},unlisten:function(a,g){if(this.data.events[a]&&this.data.events[a][g]){delete this.data.events[a][g];
-return this}this.data.events[a]=null;return this}},hooks:{canplayall:{bind:"canplaythrough",add:function(a,g){var l=false;if(this.media.readyState){g.call(this,a);l=true}this.data.hooks.canplayall={fired:l}},handler:function(a,g){if(!this.data.hooks.canplayall.fired){g.call(this,a);this.data.hooks.canplayall.fired=true}}}}};d.forEach([["trigger","emit"],["listen","on"],["unlisten","off"]],function(a){d.p[a[0]]=d.p[a[1]]=d.events.fn[a[0]]});d.addTrackEvent=function(a,g){var l,k;if(g.id)l=a.getTrackEvent(g.id);
-if(l){k=true;g=d.extend({},l,g);a.removeTrackEvent(g.id)}if(g&&g._natives&&g._natives.type&&a.options.defaults&&a.options.defaults[g._natives.type])g=d.extend({},a.options.defaults[g._natives.type],g);if(g._natives){g._id=g.id||g._id||d.guid(g._natives.type);a.data.history.push(g._id)}g.start=d.util.toSeconds(g.start,a.options.framerate);g.end=d.util.toSeconds(g.end,a.options.framerate);var t=a.data.trackEvents.byStart,u=a.data.trackEvents.byEnd,v;for(v=t.length-1;v>=0;v--)if(g.start>=t[v].start){t.splice(v+
-1,0,g);break}for(t=u.length-1;t>=0;t--)if(g.end>u[t].end){u.splice(t+1,0,g);break}if(g.end>a.media.currentTime&&g.start<=a.media.currentTime){g._running=true;a.data.running[g._natives.type].push(g);a.data.disabled[g._natives.type]||g._natives.start.call(a,null,g)}v<=a.data.trackEvents.startIndex&&g.start<=a.data.trackEvents.previousUpdateTime&&a.data.trackEvents.startIndex++;t<=a.data.trackEvents.endIndex&&g.end<a.data.trackEvents.previousUpdateTime&&a.data.trackEvents.endIndex++;this.timeUpdate(a,
-null,true);g._id&&d.addTrackEvent.ref(a,g);if(k){k=g._natives.type==="cue"?"cuechange":"trackchange";a.emit(k,{id:g.id,previousValue:{time:l.start,fn:l._natives.start},currentValue:{time:g.start,fn:g._natives.start}})}};d.addTrackEvent.ref=function(a,g){a.data.trackRefs[g._id]=g;return a};d.removeTrackEvent=function(a,g){for(var l,k,t=a.data.history.length,u=a.data.trackEvents.byStart.length,v=0,z=0,C=[],E=[],B=[],w=[];--u>-1;){l=a.data.trackEvents.byStart[v];k=a.data.trackEvents.byEnd[v];if(!l._id){C.push(l);
-E.push(k)}if(l._id){l._id!==g&&C.push(l);k._id!==g&&E.push(k);if(l._id===g){z=v;l._natives._teardown&&l._natives._teardown.call(a,l)}}v++}u=a.data.trackEvents.animating.length;v=0;if(u)for(;--u>-1;){l=a.data.trackEvents.animating[v];l._id||B.push(l);l._id&&l._id!==g&&B.push(l);v++}z<=a.data.trackEvents.startIndex&&a.data.trackEvents.startIndex--;z<=a.data.trackEvents.endIndex&&a.data.trackEvents.endIndex--;a.data.trackEvents.byStart=C;a.data.trackEvents.byEnd=E;a.data.trackEvents.animating=B;for(u=
-0;u<t;u++)a.data.history[u]!==g&&w.push(a.data.history[u]);a.data.history=w;d.removeTrackEvent.ref(a,g)};d.removeTrackEvent.ref=function(a,g){delete a.data.trackRefs[g];return a};d.getTrackEvents=function(a){var g=[];a=a.data.trackEvents.byStart;for(var l=a.length,k=0,t;k<l;k++){t=a[k];t._id&&g.push(t)}return g};d.getTrackEvents.ref=function(a){return a.data.trackRefs};d.getTrackEvent=function(a,g){return a.data.trackRefs[g]};d.getTrackEvent.ref=function(a,g){return a.data.trackRefs[g]};d.getLastTrackEventId=
-function(a){return a.data.history[a.data.history.length-1]};d.timeUpdate=function(a,g){var l=a.media.currentTime,k=a.data.trackEvents.previousUpdateTime,t=a.data.trackEvents,u=t.endIndex,v=t.startIndex,z=t.byStart.length,C=t.byEnd.length,E=d.registryByName,B,w,D;if(k<=l){for(;t.byEnd[u]&&t.byEnd[u].end<=l;){B=t.byEnd[u];w=(k=B._natives)&&k.type;if(!k||E[w]||a[w]){if(B._running===true){B._running=false;D=a.data.running[w];D.splice(D.indexOf(B),1);if(!a.data.disabled[w]){k.end.call(a,g,B);a.emit("trackend",
-d.extend({},B,{plugin:w,type:"trackend"}))}}u++}else{d.removeTrackEvent(a,B._id);return}}for(;t.byStart[v]&&t.byStart[v].start<=l;){B=t.byStart[v];w=(k=B._natives)&&k.type;if(!k||E[w]||a[w]){if(B.end>l&&B._running===false){B._running=true;a.data.running[w].push(B);if(!a.data.disabled[w]){k.start.call(a,g,B);a.emit("trackstart",d.extend({},B,{plugin:w,type:"trackstart"}))}}v++}else{d.removeTrackEvent(a,B._id);return}}}else if(k>l){for(;t.byStart[v]&&t.byStart[v].start>l;){B=t.byStart[v];w=(k=B._natives)&&
-k.type;if(!k||E[w]||a[w]){if(B._running===true){B._running=false;D=a.data.running[w];D.splice(D.indexOf(B),1);if(!a.data.disabled[w]){k.end.call(a,g,B);a.emit("trackend",d.extend({},B,{plugin:w,type:"trackend"}))}}v--}else{d.removeTrackEvent(a,B._id);return}}for(;t.byEnd[u]&&t.byEnd[u].end>l;){B=t.byEnd[u];w=(k=B._natives)&&k.type;if(!k||E[w]||a[w]){if(B.start<=l&&B._running===false){B._running=true;a.data.running[w].push(B);if(!a.data.disabled[w]){k.start.call(a,g,B);a.emit("trackstart",d.extend({},
-B,{plugin:w,type:"trackstart"}))}}u--}else{d.removeTrackEvent(a,B._id);return}}}t.endIndex=u;t.startIndex=v;t.previousUpdateTime=l;t.byStart.length<z&&t.startIndex--;t.byEnd.length<C&&t.endIndex--};d.extend(d.p,{getTrackEvents:function(){return d.getTrackEvents.call(null,this)},getTrackEvent:function(a){return d.getTrackEvent.call(null,this,a)},getLastTrackEventId:function(){return d.getLastTrackEventId.call(null,this)},removeTrackEvent:function(a){d.removeTrackEvent.call(null,this,a);return this},
-removePlugin:function(a){d.removePlugin.call(null,this,a);return this},timeUpdate:function(a){d.timeUpdate.call(null,this,a);return this},destroy:function(){d.destroy.call(null,this);return this}});d.manifest={};d.registry=[];d.registryByName={};d.plugin=function(a,g,l){if(d.protect.natives.indexOf(a.toLowerCase())>=0)d.error("'"+a+"' is a protected function name");else{var k=["start","end"],t={},u=typeof g==="function",v=["_setup","_teardown","start","end","frame"],z=function(B,w){B=B||d.nop;w=w||
-d.nop;return function(){B.apply(this,arguments);w.apply(this,arguments)}};d.manifest[a]=l=l||g.manifest||{};v.forEach(function(B){g[B]=n(g[B]||d.nop,a)});var C=function(B,w){if(!w)return this;if(w.ranges&&d.isArray(w.ranges)){d.forEach(w.ranges,function(G){G=d.extend({},w,G);delete G.ranges;this[a](G)},this);return this}var D=w._natives={},F="",I;d.extend(D,B);w._natives.type=a;w._running=false;D.start=D.start||D["in"];D.end=D.end||D.out;if(w.once)D.end=z(D.end,function(){this.removeTrackEvent(w._id)});
-D._teardown=z(function(){var G=h.call(arguments),H=this.data.running[D.type];G.unshift(null);G[1]._running&&H.splice(H.indexOf(w),1)&&D.end.apply(this,G)},D._teardown);w.compose=w.compose&&w.compose.split(" ")||[];w.effect=w.effect&&w.effect.split(" ")||[];w.compose=w.compose.concat(w.effect);w.compose.forEach(function(G){F=d.compositions[G]||{};v.forEach(function(H){D[H]=z(D[H],F[H])})});w._natives.manifest=l;if(!("start"in w))w.start=w["in"]||0;if(!w.end&&w.end!==0)w.end=w.out||Number.MAX_VALUE;
-if(!i.call(w,"toString"))w.toString=function(){var G=["start: "+w.start,"end: "+w.end,"id: "+(w.id||w._id)];w.target!=null&&G.push("target: "+w.target);return a+" ( "+G.join(", ")+" )"};if(!w.target){I="options"in l&&l.options;w.target=I&&"target"in I&&I.target}if(w._natives)w._id=d.guid(w._natives.type);w._natives._setup&&w._natives._setup.call(this,w);d.addTrackEvent(this,w);d.forEach(B,function(G,H){H!=="type"&&k.indexOf(H)===-1&&this.on(H,G)},this);return this};d.p[a]=t[a]=function(B,w){var D;
-if(B&&!w)w=B;else if(D=this.getTrackEvent(B)){w=d.extend({},D,w);d.addTrackEvent(this,w);return this}else w.id=B;this.data.running[a]=this.data.running[a]||[];D=d.extend({},this.options.defaults&&this.options.defaults[a]||{},w);return C.call(this,u?g.call(this,D):g,D)};l&&d.extend(g,{manifest:l});var E={fn:t[a],definition:g,base:g,parents:[],name:a};d.registry.push(d.extend(t,E,{type:a}));d.registryByName[a]=E;return t}};d.plugin.errors=[];d.plugin.debug=d.version==="1.3";d.removePlugin=function(a,
-g){if(!g){g=a;a=d.p;if(d.protect.natives.indexOf(g.toLowerCase())>=0){d.error("'"+g+"' is a protected function name");return}var l=d.registry.length,k;for(k=0;k<l;k++)if(d.registry[k].name===g){d.registry.splice(k,1);delete d.registryByName[g];delete d.manifest[g];delete a[g];return}}l=a.data.trackEvents.byStart;k=a.data.trackEvents.byEnd;var t=a.data.trackEvents.animating,u,v;u=0;for(v=l.length;u<v;u++){if(l[u]&&l[u]._natives&&l[u]._natives.type===g){l[u]._natives._teardown&&l[u]._natives._teardown.call(a,
-l[u]);l.splice(u,1);u--;v--;if(a.data.trackEvents.startIndex<=u){a.data.trackEvents.startIndex--;a.data.trackEvents.endIndex--}}k[u]&&k[u]._natives&&k[u]._natives.type===g&&k.splice(u,1)}u=0;for(v=t.length;u<v;u++)if(t[u]&&t[u]._natives&&t[u]._natives.type===g){t.splice(u,1);u--;v--}};d.compositions={};d.compose=function(a,g,l){d.manifest[a]=l||g.manifest||{};d.compositions[a]=g};d.plugin.effect=d.effect=d.compose;var A=/^(?:\.|#|\[)/;d.dom={debug:false,find:function(a,g){var l=null;a=a.trim();g=
-g||f;if(a){if(!A.test(a)){l=f.getElementById(a);if(l!==null)return l}try{l=g.querySelector(a)}catch(k){if(d.dom.debug)throw Error(k);}}return l}};var y=/\?/,x={url:"",data:"",dataType:"",success:d.nop,type:"GET",async:true,xhr:function(){return new r.XMLHttpRequest}};d.xhr=function(a){a.dataType=a.dataType&&a.dataType.toLowerCase()||null;if(a.dataType&&(a.dataType==="jsonp"||a.dataType==="script"))d.xhr.getJSONP(a.url,a.success,a.dataType==="script");else{a=d.extend({},x,a);a.ajax=a.xhr();if(a.ajax){if(a.type===
-"GET"&&a.data){a.url+=(y.test(a.url)?"&":"?")+a.data;a.data=null}a.ajax.open(a.type,a.url,a.async);a.ajax.send(a.data||null);return d.xhr.httpData(a)}}};d.xhr.httpData=function(a){var g,l=null,k,t=null;a.ajax.onreadystatechange=function(){if(a.ajax.readyState===4){try{l=JSON.parse(a.ajax.responseText)}catch(u){}g={xml:a.ajax.responseXML,text:a.ajax.responseText,json:l};if(!g.xml||!g.xml.documentElement){g.xml=null;try{k=new DOMParser;t=k.parseFromString(a.ajax.responseText,"text/xml");if(!t.getElementsByTagName("parsererror").length)g.xml=
-t}catch(v){}}if(a.dataType)g=g[a.dataType];a.success.call(a.ajax,g)}};return g};d.xhr.getJSONP=function(a,g,l){var k=f.head||f.getElementsByTagName("head")[0]||f.documentElement,t=f.createElement("script"),u=false,v=[];v=/(=)\?(?=&|$)|\?\?/;var z,C;if(!l){C=a.match(/(callback=[^&]*)/);if(C!==null&&C.length){v=C[1].split("=")[1];if(v==="?")v="jsonp";z=d.guid(v);a=a.replace(/(callback=[^&]*)/,"callback="+z)}else{z=d.guid("jsonp");if(v.test(a))a=a.replace(v,"$1"+z);v=a.split(/\?(.+)?/);a=v[0]+"?";if(v[1])a+=
-v[1]+"&";a+="callback="+z}window[z]=function(E){g&&g(E);u=true}}t.addEventListener("load",function(){l&&g&&g();u&&delete window[z];k.removeChild(t)},false);t.src=a;k.insertBefore(t,k.firstChild)};d.getJSONP=d.xhr.getJSONP;d.getScript=d.xhr.getScript=function(a,g){return d.xhr.getJSONP(a,g,true)};d.util={toSeconds:function(a,g){var l=/^([0-9]+:){0,2}[0-9]+([.;][0-9]+)?$/,k,t,u;if(typeof a==="number")return a;typeof a==="string"&&!l.test(a)&&d.error("Invalid time format");l=a.split(":");k=l.length-
-1;t=l[k];if(t.indexOf(";")>-1){t=t.split(";");u=0;if(g&&typeof g==="number")u=parseFloat(t[1],10)/g;l[k]=parseInt(t[0],10)+u}k=l[0];return{1:parseFloat(k,10),2:parseInt(k,10)*60+parseFloat(l[1],10),3:parseInt(k,10)*3600+parseInt(l[1],10)*60+parseFloat(l[2],10)}[l.length||1]}};d.p.cue=d.p.exec;d.protect={natives:function(a){return Object.keys?Object.keys(a):function(g){var l,k=[];for(l in g)i.call(g,l)&&k.push(l);return k}(a)}(d.p).map(function(a){return a.toLowerCase()})};d.forEach({listen:"on",unlisten:"off",
-trigger:"emit",exec:"cue"},function(a,g){var l=d.p[g];d.p[g]=function(){if(typeof console!=="undefined"&&console.warn){console.warn("Deprecated method '"+g+"', "+(a==null?"do not use.":"use '"+a+"' instead."));d.p[g]=l}return d.p[a].apply(this,[].slice.call(arguments))}});r.Popcorn=d}else{r.Popcorn={isSupported:false};for(c="byId forEach extend effects error guid sizeOf isArray nop position disable enable destroyaddTrackEvent removeTrackEvent getTrackEvents getTrackEvent getLastTrackEventId timeUpdate plugin removePlugin compose effect xhr getJSONP getScript".split(/\s+/);c.length;)r.Popcorn[c.shift()]=
-function(){}}})(window,window.document);(function(r,f){var n=r.document,c=r.location,b=/:\/\//,e=c.href.replace(c.href.split("/").slice(-1)[0],""),h=function(j,p,m){j=j||0;p=(p||j||0)+1;m=m||1;p=Math.ceil((p-j)/m)||0;var o=0,q=[];for(q.length=p;o<p;){q[o++]=j;j+=m}return q};f.sequence=function(j,p){return new f.sequence.init(j,p)};f.sequence.init=function(j,p){this.parent=n.getElementById(j);this.seqId=f.guid("__sequenced");this.queue=[];this.playlist=[];this.inOuts={ofVideos:[],ofClips:[]};this.dims={width:0,height:0};this.active=0;this.playing=
-this.cycling=false;this.times={last:0};this.events={};var m=this,o=0;f.forEach(p,function(q,s){var d=n.createElement("video");d.preload="auto";d.controls=true;d.style.display=s&&"none"||"";d.id=m.seqId+"-"+s;m.queue.push(d);var A=q["in"],y=q.out;m.inOuts.ofVideos.push({"in":A!==undefined&&A||1,out:y!==undefined&&y||0});m.inOuts.ofVideos[s].out=m.inOuts.ofVideos[s].out||m.inOuts.ofVideos[s]["in"]+2;d.src=!b.test(q.src)?e+q.src:q.src;d.setAttribute("data-sequence-owner",j);d.setAttribute("data-sequence-guid",
-m.seqId);d.setAttribute("data-sequence-id",s);d.setAttribute("data-sequence-clip",[m.inOuts.ofVideos[s]["in"],m.inOuts.ofVideos[s].out].join(":"));m.parent.appendChild(d);m.playlist.push(f("#"+d.id))});m.inOuts.ofVideos.forEach(function(q){q={"in":o,out:o+(q.out-q["in"])};m.inOuts.ofClips.push(q);o=q.out+1});f.forEach(this.queue,function(q,s){function d(){if(!s){m.dims.width=q.videoWidth;m.dims.height=q.videoHeight}q.currentTime=m.inOuts.ofVideos[s]["in"]-0.5;q.removeEventListener("canplaythrough",
-d,false);return true}q.addEventListener("canplaythrough",d,false);q.addEventListener("play",function(){m.playing=true},false);q.addEventListener("pause",function(){m.playing=false},false);q.addEventListener("timeupdate",function(A){A=A.srcElement||A.target;A=+(A.dataset&&A.dataset.sequenceId||A.getAttribute("data-sequence-id"));var y=Math.floor(q.currentTime);if(m.times.last!==y&&A===m.active){m.times.last=y;y===m.inOuts.ofVideos[A].out&&f.sequence.cycle.call(m,A)}},false)});return this};f.sequence.init.prototype=
-f.sequence.prototype;f.sequence.cycle=function(j){this.queue||f.error("Popcorn.sequence.cycle is not a public method");var p=this.queue,m=this.inOuts.ofVideos,o=p[j],q=0,s;if(p[j+1])q=j+1;if(p[j+1]){p=p[q];m=m[q];f.extend(p,{width:this.dims.width,height:this.dims.height});s=this.playlist[q];o.pause();this.active=q;this.times.last=m["in"]-1;s.currentTime(m["in"]);s[q?"play":"pause"]();this.trigger("cycle",{position:{previous:j,current:q}});if(q){o.style.display="none";p.style.display=""}this.cycling=
-false}else this.playlist[j].pause();return this};var i=["timeupdate","play","pause"];f.extend(f.sequence.prototype,{eq:function(j){return this.playlist[j]},remove:function(){this.parent.innerHTML=null},clip:function(j){return this.inOuts.ofVideos[j]},duration:function(){for(var j=0,p=this.inOuts.ofClips,m=0;m<p.length;m++)j+=p[m].out-p[m]["in"]+1;return j-1},play:function(){this.playlist[this.active].play();return this},exec:function(j,p){var m=this.active;this.inOuts.ofClips.forEach(function(o,q){if(j>=
-o["in"]&&j<=o.out)m=q});j+=this.inOuts.ofVideos[m]["in"]-this.inOuts.ofClips[m]["in"];f.addTrackEvent(this.playlist[m],{start:j-1,end:j,_running:false,_natives:{start:p||f.nop,end:f.nop,type:"exec"}});return this},listen:function(j,p){var m=this,o=this.playlist,q=o.length,s=0;if(!p)p=f.nop;if(f.Events.Natives.indexOf(j)>-1)f.forEach(o,function(d){d.listen(j,function(A){A.active=m;if(i.indexOf(j)>-1)p.call(d,A);else++s===q&&p.call(d,A)})});else{this.events[j]||(this.events[j]={});o=p.name||f.guid("__"+
-j);this.events[j][o]=p}return this},unlisten:function(){},trigger:function(j,p){var m=this;if(!(f.Events.Natives.indexOf(j)>-1)){this.events[j]&&f.forEach(this.events[j],function(o){o.call(m,{type:j},p)});return this}}});f.forEach(f.manifest,function(j,p){f.sequence.prototype[p]=function(m){var o={},q=[],s,d,A,y,x;for(s=0;s<this.inOuts.ofClips.length;s++){q=this.inOuts.ofClips[s];d=h(q["in"],q.out);A=d.indexOf(m.start);y=d.indexOf(m.end);if(A>-1)o[s]=f.extend({},q,{start:d[A],clipIdx:A});if(y>-1)o[s]=
-f.extend({},q,{end:d[y],clipIdx:y})}s=Object.keys(o).map(function(g){return+g});q=h(s[0],s[1]);for(s=0;s<q.length;s++){A={};y=q[s];var a=o[y];if(a){x=this.inOuts.ofVideos[y];d=a.clipIdx;x=h(x["in"],x.out);if(a.start){A.start=x[d];A.end=x[x.length-1]}if(a.end){A.start=x[0];A.end=x[d]}}else{A.start=this.inOuts.ofVideos[y]["in"];A.end=this.inOuts.ofVideos[y].out}this.playlist[y][p](f.extend({},m,A))}return this}})})(this,Popcorn);(function(r){document.addEventListener("DOMContentLoaded",function(){var f=document.querySelectorAll("[data-timeline-sources]");r.forEach(f,function(n,c){var b=f[c],e,h,i;if(!b.id)b.id=r.guid("__popcorn");if(b.nodeType&&b.nodeType===1){i=r("#"+b.id);e=(b.getAttribute("data-timeline-sources")||"").split(",");e[0]&&r.forEach(e,function(j){h=j.split("!");if(h.length===1){h=j.match(/(.*)[\/\\]([^\/\\]+\.\w+)$/)[2].split(".");h[0]="parse"+h[1].toUpperCase();h[1]=j}e[0]&&i[h[0]]&&i[h[0]](h[1])});i.autoplay()&&
-i.play()}})},false)})(Popcorn);(function(r,f){function n(e){e=typeof e==="string"?e:[e.language,e.region].join("-");var h=e.split("-");return{iso6391:e,language:h[0]||"",region:h[1]||""}}var c=r.navigator,b=n(c.userLanguage||c.language);f.locale={get:function(){return b},set:function(e){b=n(e);f.locale.broadcast();return b},broadcast:function(e){var h=f.instances,i=h.length,j=0,p;for(e=e||"locale:changed";j<i;j++){p=h[j];e in p.data.events&&p.trigger(e)}}}})(this,this.Popcorn);(function(r){var f=Object.prototype.hasOwnProperty;r.parsers={};r.parser=function(n,c,b){if(r.protect.natives.indexOf(n.toLowerCase())>=0)r.error("'"+n+"' is a protected function name");else{if(typeof c==="function"&&!b){b=c;c=""}if(!(typeof b!=="function"||typeof c!=="string")){var e={};e[n]=function(h,i){if(!h)return this;var j=this;r.xhr({url:h,dataType:c,success:function(p){var m,o,q=0;p=b(p).data||[];if(m=p.length){for(;q<m;q++){o=p[q];for(var s in o)f.call(o,s)&&j[s]&&j[s](o[s])}i&&i()}}});
-return this};r.extend(r.p,e);return e}}}})(Popcorn);(function(r){var f=function(b,e){b=b||r.nop;e=e||r.nop;return function(){b.apply(this,arguments);e.apply(this,arguments)}},n=/^.*\.(ogg|oga|aac|mp3|wav)($|\?)/,c=/^.*\.(ogg|oga|aac|mp3|wav|ogg|ogv|mp4|webm)($|\?)/;r.player=function(b,e){if(!r[b]){e=e||{};var h=function(i,j,p){p=p||{};var m=new Date/1E3,o=m,q=0,s=0,d=1,A=false,y={},x=typeof i==="string"?r.dom.find(i):i,a={};Object.prototype.__defineGetter__||(a=x||document.createElement("div"));for(var g in x)if(!(g in a))if(typeof x[g]==="object")a[g]=
-x[g];else if(typeof x[g]==="function")a[g]=function(k){return"length"in x[k]&&!x[k].call?x[k]:function(){return x[k].apply(x,arguments)}}(g);else r.player.defineProperty(a,g,{get:function(k){return function(){return x[k]}}(g),set:r.nop,configurable:true});var l=function(){m=new Date/1E3;if(!a.paused){a.currentTime+=m-o;a.dispatchEvent("timeupdate");setTimeout(l,10)}o=m};a.play=function(){this.paused=false;if(a.readyState>=4){o=new Date/1E3;a.dispatchEvent("play");l()}};a.pause=function(){this.paused=
-true;a.dispatchEvent("pause")};r.player.defineProperty(a,"currentTime",{get:function(){return q},set:function(k){q=+k;a.dispatchEvent("timeupdate");return q},configurable:true});r.player.defineProperty(a,"volume",{get:function(){return d},set:function(k){d=+k;a.dispatchEvent("volumechange");return d},configurable:true});r.player.defineProperty(a,"muted",{get:function(){return A},set:function(k){A=+k;a.dispatchEvent("volumechange");return A},configurable:true});r.player.defineProperty(a,"readyState",
-{get:function(){return s},set:function(k){return s=k},configurable:true});a.addEventListener=function(k,t){y[k]||(y[k]=[]);y[k].push(t);return t};a.removeEventListener=function(k,t){var u,v=y[k];if(v){for(u=y[k].length-1;u>=0;u--)t===v[u]&&v.splice(u,1);return t}};a.dispatchEvent=function(k){var t,u=k.type;if(!u){u=k;if(k=r.events.getInterface(u)){t=document.createEvent(k);t.initEvent(u,true,true,window,1)}}if(y[u])for(k=y[u].length-1;k>=0;k--)y[u][k].call(this,t,this)};a.src=j||"";a.duration=0;a.paused=
-true;a.ended=0;p&&p.events&&r.forEach(p.events,function(k,t){a.addEventListener(t,k,false)});if(e._canPlayType(x.nodeName,j)!==false)if(e._setup)e._setup.call(a,p);else{a.readyState=4;a.dispatchEvent("loadedmetadata");a.dispatchEvent("loadeddata");a.dispatchEvent("canplaythrough")}else setTimeout(function(){a.dispatchEvent("error")},0);i=new r.p.init(a,p);if(e._teardown)i.destroy=f(i.destroy,function(){e._teardown.call(a,p)});return i};h.canPlayType=e._canPlayType=e._canPlayType||r.nop;r[b]=r.player.registry[b]=
-h}};r.player.registry={};r.player.defineProperty=Object.defineProperty||function(b,e,h){b.__defineGetter__(e,h.get||r.nop);b.__defineSetter__(e,h.set||r.nop)};r.player.playerQueue=function(){var b=[],e=false;return{next:function(){e=false;b.shift();b[0]&&b[0]()},add:function(h){b.push(function(){e=true;h&&h()});!e&&b[0]()}}};r.smart=function(b,e,h){var i=["AUDIO","VIDEO"],j,p=r.dom.find(b),m;j=document.createElement("video");var o={ogg:"video/ogg",ogv:"video/ogg",oga:"audio/ogg",webm:"video/webm",
-mp4:"video/mp4",mp3:"audio/mp3"};if(p){if(i.indexOf(p.nodeName)>-1&&!e){if(typeof e==="object")h=e;return r(p,h)}if(typeof e==="string")e=[e];b=0;for(srcLength=e.length;b<srcLength;b++){m=c.exec(e[b]);m=!m||!m[1]?false:j.canPlayType(o[m[1]]);if(m){e=e[b];break}for(var q in r.player.registry)if(r.player.registry.hasOwnProperty(q))if(r.player.registry[q].canPlayType(p.nodeName,e[b]))return r[q](p,e[b],h)}if(i.indexOf(p.nodeName)===-1){j=typeof e==="string"?e:e.length?e[0]:e;b=document.createElement(n.exec(j)?
-i[0]:i[1]);b.controls=true;p.appendChild(b);p=b}h&&h.events&&h.events.error&&p.addEventListener("error",h.events.error,false);p.src=e;return r(p,h)}else r.error("Specified target "+b+" was not found.")}})(Popcorn);(function(r){var f=function(n,c){var b=0,e=0,h;r.forEach(c.classes,function(i,j){h=[];if(i==="parent")h[0]=document.querySelectorAll("#"+c.target)[0].parentNode;else h=document.querySelectorAll("#"+c.target+" "+i);b=0;for(e=h.length;b<e;b++)h[b].classList.toggle(j)})};r.compose("applyclass",{manifest:{about:{name:"Popcorn applyclass Effect",version:"0.1",author:"@scottdowne",website:"scottdowne.wordpress.com"},options:{}},_setup:function(n){n.classes={};n.applyclass=n.applyclass||"";for(var c=n.applyclass.replace(/\s/g,
-"").split(","),b=[],e=0,h=c.length;e<h;e++){b=c[e].split(":");if(b[0])n.classes[b[0]]=b[1]||""}},start:f,end:f})})(Popcorn);(function(r){var f=/(?:http:\/\/www\.|http:\/\/|www\.|\.|^)(youtu|vimeo|soundcloud|baseplayer)/,n={},c={vimeo:false,youtube:false,soundcloud:false,module:false};Object.defineProperty(n,void 0,{get:function(){return c[void 0]},set:function(b){c[void 0]=b}});r.plugin("mediaspawner",{manifest:{about:{name:"Popcorn Media Spawner Plugin",version:"0.1",author:"Matthew Schranz, @mjschranz",website:"mschranz.wordpress.com"},options:{source:{elem:"input",type:"text",label:"Media Source","default":"http://www.youtube.com/watch?v=CXDstfD9eJ0"},
-caption:{elem:"input",type:"text",label:"Media Caption","default":"Popcorn Popping",optional:true},target:"mediaspawner-container",start:{elem:"input",type:"number",label:"Start"},end:{elem:"input",type:"number",label:"End"},autoplay:{elem:"input",type:"checkbox",label:"Autoplay Video",optional:true},width:{elem:"input",type:"number",label:"Media Width","default":400,units:"px",optional:true},height:{elem:"input",type:"number",label:"Media Height","default":200,units:"px",optional:true}}},_setup:function(b){function e(){function o(){if(j!==
-"HTML5"&&!window.Popcorn[j])setTimeout(function(){o()},300);else{b.id=b._container.id;b._container.style.width=b.width+"px";b._container.style.height=b.height+"px";b.popcorn=r.smart("#"+b.id,b.source);j==="HTML5"&&b.popcorn.controls(true);b._container.style.width="0px";b._container.style.height="0px";b._container.style.visibility="hidden";b._container.style.overflow="hidden"}}if(j!=="HTML5"&&!window.Popcorn[j]&&!n[j]){n[j]=true;r.getScript("http://popcornjs.org/code/players/"+j+"/popcorn."+j+".js",
-function(){o()})}else o()}function h(){window.Popcorn.player?e():setTimeout(function(){h()},300)}var i=document.getElementById(b.target)||{},j,p,m;if(p=f.exec(b.source)){j=p[1];if(j==="youtu")j="youtube"}else j="HTML5";b._type=j;b._container=document.createElement("div");p=b._container;p.id="mediaSpawnerdiv-"+r.guid();b.width=b.width||400;b.height=b.height||200;if(b.caption){m=document.createElement("div");m.innerHTML=b.caption;m.style.display="none";b._capCont=m;p.appendChild(m)}i&&i.appendChild(p);
-if(!window.Popcorn.player&&!n.module){n.module=true;r.getScript("http://popcornjs.org/code/modules/player/popcorn.player.js",h)}else h()},start:function(b,e){if(e._capCont)e._capCont.style.display="";e._container.style.width=e.width+"px";e._container.style.height=e.height+"px";e._container.style.visibility="visible";e._container.style.overflow="visible";e.autoplay&&e.popcorn.play()},end:function(b,e){if(e._capCont)e._capCont.style.display="none";e._container.style.width="0px";e._container.style.height=
-"0px";e._container.style.visibility="hidden";e._container.style.overflow="hidden";e.popcorn.pause()},_teardown:function(b){b.popcorn&&b.popcorn.destory&&b.popcorn.destroy();document.getElementById(b.target)&&document.getElementById(b.target).removeChild(b._container)}})})(Popcorn,this);(function(r){r.plugin("code",function(f){var n=false,c=this,b=function(){var e=function(h){return function(i,j){var p=function(){n&&i.call(c,j);n&&h(p)};p()}};return window.webkitRequestAnimationFrame?e(window.webkitRequestAnimationFrame):window.mozRequestAnimationFrame?e(window.mozRequestAnimationFrame):e(function(h){window.setTimeout(h,16)})}();if(!f.onStart||typeof f.onStart!=="function")f.onStart=r.nop;if(f.onEnd&&typeof f.onEnd!=="function")f.onEnd=undefined;if(f.onFrame&&typeof f.onFrame!==
-"function")f.onFrame=undefined;return{start:function(e,h){h.onStart.call(c,h);if(h.onFrame){n=true;b(h.onFrame,h)}},end:function(e,h){if(h.onFrame)n=false;h.onEnd&&h.onEnd.call(c,h)}}},{about:{name:"Popcorn Code Plugin",version:"0.1",author:"David Humphrey (@humphd)",website:"http://vocamus.net/dave"},options:{start:{elem:"input",type:"number",label:"Start"},end:{elem:"input",type:"number",label:"End"},onStart:{elem:"input",type:"function",label:"onStart"},onFrame:{elem:"input",type:"function",label:"onFrame",
-optional:true},onEnd:{elem:"input",type:"function",label:"onEnd"}}})})(Popcorn);(function(r){var f=0;r.plugin("flickr",function(n){var c,b=document.getElementById(n.target),e,h,i,j,p=n.numberofimages||4,m=n.height||"50px",o=n.width||"50px",q=n.padding||"5px",s=n.border||"0px";c=document.createElement("div");c.id="flickr"+f;c.style.width="100%";c.style.height="100%";c.style.display="none";f++;b&&b.appendChild(c);var d=function(){if(e)setTimeout(function(){d()},5);else{h="http://api.flickr.com/services/rest/?method=flickr.people.findByUsername&";h+="username="+n.username+"&api_key="+
-n.apikey+"&format=json&jsoncallback=flickr";r.getJSONP(h,function(y){e=y.user.nsid;A()})}},A=function(){h="http://api.flickr.com/services/feeds/photos_public.gne?";if(e)h+="id="+e+"&";if(n.tags)h+="tags="+n.tags+"&";h+="lang=en-us&format=json&jsoncallback=flickr";r.xhr.getJSONP(h,function(y){var x=document.createElement("div");x.innerHTML="<p style='padding:"+q+";'>"+y.title+"<p/>";r.forEach(y.items,function(a,g){if(g<p){i=document.createElement("a");i.setAttribute("href",a.link);i.setAttribute("target",
-"_blank");j=document.createElement("img");j.setAttribute("src",a.media.m);j.setAttribute("height",m);j.setAttribute("width",o);j.setAttribute("style","border:"+s+";padding:"+q);i.appendChild(j);x.appendChild(i)}else return false});c.appendChild(x)})};if(n.username&&n.apikey)d();else{e=n.userid;A()}return{start:function(){c.style.display="inline"},end:function(){c.style.display="none"},_teardown:function(y){document.getElementById(y.target)&&document.getElementById(y.target).removeChild(c)}}},{about:{name:"Popcorn Flickr Plugin",
-version:"0.2",author:"Scott Downe, Steven Weerdenburg, Annasob",website:"http://scottdowne.wordpress.com/"},options:{start:{elem:"input",type:"number",label:"Start"},end:{elem:"input",type:"number",label:"End"},userid:{elem:"input",type:"text",label:"User ID",optional:true},tags:{elem:"input",type:"text",label:"Tags"},username:{elem:"input",type:"text",label:"Username",optional:true},apikey:{elem:"input",type:"text",label:"API Key",optional:true},target:"flickr-container",height:{elem:"input",type:"text",
-label:"Height","default":"50px",optional:true},width:{elem:"input",type:"text",label:"Width","default":"50px",optional:true},padding:{elem:"input",type:"text",label:"Padding",optional:true},border:{elem:"input",type:"text",label:"Border","default":"5px",optional:true},numberofimages:{elem:"input",type:"number","default":4,label:"Number of Images"}}})})(Popcorn);(function(r){r.plugin("footnote",{manifest:{about:{name:"Popcorn Footnote Plugin",version:"0.2",author:"@annasob, @rwaldron",website:"annasob.wordpress.com"},options:{start:{elem:"input",type:"number",label:"Start"},end:{elem:"input",type:"number",label:"End"},text:{elem:"input",type:"text",label:"Text"},target:"footnote-container"}},_setup:function(f){var n=r.dom.find(f.target);f._container=document.createElement("div");f._container.style.display="none";f._container.innerHTML=f.text;n.appendChild(f._container)},
-start:function(f,n){n._container.style.display="inline"},end:function(f,n){n._container.style.display="none"},_teardown:function(f){var n=r.dom.find(f.target);n&&n.removeChild(f._container)}})})(Popcorn);(function(r){function f(b){return String(b).replace(/&(?!\w+;)|[<>"']/g,function(e){return c[e]||e})}function n(b,e){var h=b.container=document.createElement("div"),i=h.style,j=b.media,p=function(){var m=b.position();i.fontSize="18px";i.width=j.offsetWidth+"px";i.top=m.top+j.offsetHeight-h.offsetHeight-40+"px";i.left=m.left+"px";setTimeout(p,10)};h.id=e||"";i.position="absolute";i.color="white";i.textShadow="black 2px 2px 6px";i.fontWeight="bold";i.textAlign="center";p();b.media.parentNode.appendChild(h);
-return h}var c={"&":"&","<":"<",">":">",'"':""","'":"'"};r.plugin("text",{manifest:{about:{name:"Popcorn Text Plugin",version:"0.1",author:"@humphd"},options:{start:{elem:"input",type:"number",label:"Start"},end:{elem:"input",type:"number",label:"End"},text:{elem:"input",type:"text",label:"Text","default":"Popcorn.js"},escape:{elem:"input",type:"checkbox",label:"Escape"},multiline:{elem:"input",type:"checkbox",label:"Multiline"}}},_setup:function(b){var e,h,i=b._container=document.createElement("div");
-i.style.display="none";if(b.target)if(e=r.dom.find(b.target)){if(["VIDEO","AUDIO"].indexOf(e.nodeName)>-1)e=n(this,b.target+"-overlay")}else e=n(this,b.target);else e=this.container?this.container:n(this);b._target=e;h=b.escape?f(b.text):b.text;h=b.multiline?h.replace(/\r?\n/gm,"<br>"):h;i.innerHTML=h||"";e.appendChild(i)},start:function(b,e){e._container.style.display="inline"},end:function(b,e){e._container.style.display="none"},_teardown:function(b){var e=b._target;e&&e.removeChild(b._container)}})})(Popcorn);var googleCallback;
-(function(r){function f(i,j,p){i=i.type?i.type.toUpperCase():"HYBRID";var m;if(i==="STAMEN-WATERCOLOR"||i==="STAMEN-TERRAIN"||i==="STAMEN-TONER")m=i.replace("STAMEN-","").toLowerCase();p=new google.maps.Map(p,{mapTypeId:m?m:google.maps.MapTypeId[i],mapTypeControlOptions:{mapTypeIds:[]}});m&&p.mapTypes.set(m,new google.maps.StamenMapType(m));p.getDiv().style.display="none";return p}var n=1,c=false,b=false,e,h;googleCallback=function(i){if(typeof google!=="undefined"&&google.maps&&google.maps.Geocoder&&
-google.maps.LatLng){e=new google.maps.Geocoder;r.getScript("//maps.stamen.com/js/tile.stamen.js",function(){b=true})}else setTimeout(function(){googleCallback(i)},1)};h=function(){if(document.body){c=true;r.getScript("//maps.google.com/maps/api/js?sensor=false&callback=googleCallback")}else setTimeout(function(){h()},1)};r.plugin("googlemap",function(i){var j,p,m,o=document.getElementById(i.target);i.type=i.type||"ROADMAP";i.zoom=i.zoom||1;i.lat=i.lat||0;i.lng=i.lng||0;c||h();j=document.createElement("div");
-j.id="actualmap"+n;j.style.width=i.width||"100%";j.style.height=i.height?i.height:o&&o.clientHeight?o.clientHeight+"px":"100%";n++;o&&o.appendChild(j);var q=function(){if(b){if(j)if(i.location)e.geocode({address:i.location},function(s,d){if(j&&d===google.maps.GeocoderStatus.OK){i.lat=s[0].geometry.location.lat();i.lng=s[0].geometry.location.lng();m=new google.maps.LatLng(i.lat,i.lng);p=f(i,m,j)}});else{m=new google.maps.LatLng(i.lat,i.lng);p=f(i,m,j)}}else setTimeout(function(){q()},5)};q();return{start:function(s,
-d){var A=this,y,x=function(){if(p){d._map=p;p.getDiv().style.display="block";google.maps.event.trigger(p,"resize");p.setCenter(m);if(d.zoom&&typeof d.zoom!=="number")d.zoom=+d.zoom;p.setZoom(d.zoom);if(d.heading&&typeof d.heading!=="number")d.heading=+d.heading;if(d.pitch&&typeof d.pitch!=="number")d.pitch=+d.pitch;if(d.type==="STREETVIEW"){p.setStreetView(y=new google.maps.StreetViewPanorama(j,{position:m,pov:{heading:d.heading=d.heading||0,pitch:d.pitch=d.pitch||0,zoom:d.zoom}}));var a=function(z,
-C){var E=google.maps.geometry.spherical.computeHeading;setTimeout(function(){var B=A.media.currentTime;if(typeof d.tween==="object"){for(var w=0,D=z.length;w<D;w++){var F=z[w];if(B>=F.interval*(w+1)/1E3&&(B<=F.interval*(w+2)/1E3||B>=F.interval*D/1E3)){u.setPosition(new google.maps.LatLng(F.position.lat,F.position.lng));u.setPov({heading:F.pov.heading||E(F,z[w+1])||0,zoom:F.pov.zoom||0,pitch:F.pov.pitch||0})}}a(z,z[0].interval)}else{w=0;for(D=z.length;w<D;w++){F=d.interval;if(B>=F*(w+1)/1E3&&(B<=F*
-(w+2)/1E3||B>=F*D/1E3)){g.setPov({heading:E(z[w],z[w+1])||0,zoom:d.zoom,pitch:d.pitch||0});g.setPosition(l[w])}}a(l,d.interval)}},C)};if(d.location&&typeof d.tween==="string"){var g=y,l=[],k=new google.maps.DirectionsService,t=new google.maps.DirectionsRenderer(g);k.route({origin:d.location,destination:d.tween,travelMode:google.maps.TravelMode.DRIVING},function(z,C){if(C==google.maps.DirectionsStatus.OK){t.setDirections(z);for(var E=z.routes[0].overview_path,B=0,w=E.length;B<w;B++)l.push(new google.maps.LatLng(E[B].lat(),
-E[B].lng()));d.interval=d.interval||1E3;a(l,10)}})}else if(typeof d.tween==="object"){var u=y;k=0;for(var v=d.tween.length;k<v;k++){d.tween[k].interval=d.tween[k].interval||1E3;a(d.tween,10)}}}d.onmaploaded&&d.onmaploaded(d,p)}else setTimeout(function(){x()},13)};x()},end:function(){if(p)p.getDiv().style.display="none"},_teardown:function(s){var d=document.getElementById(s.target);d&&d.removeChild(j);j=p=m=null;s._map=null}}},{about:{name:"Popcorn Google Map Plugin",version:"0.1",author:"@annasob",
-website:"annasob.wordpress.com"},options:{start:{elem:"input",type:"start",label:"Start"},end:{elem:"input",type:"start",label:"End"},target:"map-container",type:{elem:"select",options:["ROADMAP","SATELLITE","STREETVIEW","HYBRID","TERRAIN","STAMEN-WATERCOLOR","STAMEN-TERRAIN","STAMEN-TONER"],label:"Map Type",optional:true},zoom:{elem:"input",type:"text",label:"Zoom","default":0,optional:true},lat:{elem:"input",type:"text",label:"Lat",optional:true},lng:{elem:"input",type:"text",label:"Lng",optional:true},
-location:{elem:"input",type:"text",label:"Location","default":"Toronto, Ontario, Canada"},heading:{elem:"input",type:"text",label:"Heading","default":0,optional:true},pitch:{elem:"input",type:"text",label:"Pitch","default":1,optional:true}}})})(Popcorn);(function(r){function f(b){function e(){var p=b.getBoundingClientRect(),m=i.getBoundingClientRect();if(m.left!==p.left)i.style.left=p.left+"px";if(m.top!==p.top)i.style.top=p.top+"px"}var h=-1,i=document.createElement("div"),j=getComputedStyle(b).zIndex;i.setAttribute("data-popcorn-helper-container",true);i.style.position="absolute";i.style.zIndex=isNaN(j)?n:j+1;document.body.appendChild(i);return{element:i,start:function(){h=setInterval(e,c)},stop:function(){clearInterval(h);h=-1},destroy:function(){document.body.removeChild(i);
-h!==-1&&clearInterval(h)}}}var n=2E3,c=10;r.plugin("image",{manifest:{about:{name:"Popcorn image Plugin",version:"0.1",author:"Scott Downe",website:"http://scottdowne.wordpress.com/"},options:{start:{elem:"input",type:"number",label:"Start"},end:{elem:"input",type:"number",label:"End"},src:{elem:"input",type:"url",label:"Image URL","default":"http://mozillapopcorn.org/wp-content/themes/popcorn/images/for_developers.png"},href:{elem:"input",type:"url",label:"Link","default":"http://mozillapopcorn.org/wp-content/themes/popcorn/images/for_developers.png",
-optional:true},target:"image-container",text:{elem:"input",type:"text",label:"Caption","default":"Popcorn.js",optional:true}}},_setup:function(b){var e=document.createElement("img"),h=document.getElementById(b.target);b.anchor=document.createElement("a");b.anchor.style.position="relative";b.anchor.style.textDecoration="none";b.anchor.style.display="none";if(h)if(["VIDEO","AUDIO"].indexOf(h.nodeName)>-1){b.trackedContainer=f(h);b.trackedContainer.element.appendChild(b.anchor)}else h&&h.appendChild(b.anchor);
-e.addEventListener("load",function(){e.style.borderStyle="none";b.anchor.href=b.href||b.src||"#";b.anchor.target="_blank";var i,j;e.style.height=h.style.height;e.style.width=h.style.width;b.anchor.appendChild(e);if(b.text){i=e.height/12+"px";j=document.createElement("div");r.extend(j.style,{color:"black",fontSize:i,fontWeight:"bold",position:"relative",textAlign:"center",width:e.style.width||e.width+"px",zIndex:"10"});j.innerHTML=b.text||"";j.style.top=(e.style.height.replace("px","")||e.height)/
-2-j.offsetHeight/2+"px";b.anchor.insertBefore(j,e)}},false);e.src=b.src},start:function(b,e){e.anchor.style.display="inline";e.trackedContainer&&e.trackedContainer.start()},end:function(b,e){e.anchor.style.display="none";e.trackedContainer&&e.trackedContainer.stop()},_teardown:function(b){if(b.trackedContainer)b.trackedContainer.destroy();else b.anchor.parentNode&&b.anchor.parentNode.removeChild(b.anchor)}})})(Popcorn);(function(r){var f=1,n=false;r.plugin("googlefeed",function(c){var b=function(){var j=false,p=0,m=document.getElementsByTagName("link"),o=m.length,q=document.head||document.getElementsByTagName("head")[0],s=document.createElement("link");if(window.GFdynamicFeedControl)n=true;else r.getScript("//www.google.com/uds/solutions/dynamicfeed/gfdynamicfeedcontrol.js",function(){n=true});for(;p<o;p++)if(m[p].href==="//www.google.com/uds/solutions/dynamicfeed/gfdynamicfeedcontrol.css")j=true;if(!j){s.type=
-"text/css";s.rel="stylesheet";s.href="//www.google.com/uds/solutions/dynamicfeed/gfdynamicfeedcontrol.css";q.insertBefore(s,q.firstChild)}};window.google?b():r.getScript("//www.google.com/jsapi",function(){google.load("feeds","1",{callback:function(){b()}})});var e=document.createElement("div"),h=document.getElementById(c.target),i=function(){if(n)c.feed=new GFdynamicFeedControl(c.url,e,{vertical:c.orientation.toLowerCase()==="vertical"?true:false,horizontal:c.orientation.toLowerCase()==="horizontal"?
-true:false,title:c.title=c.title||"Blog"});else setTimeout(function(){i()},5)};if(!c.orientation||c.orientation.toLowerCase()!=="vertical"&&c.orientation.toLowerCase()!=="horizontal")c.orientation="vertical";e.style.display="none";e.id="_feed"+f;e.style.width="100%";e.style.height="100%";f++;h&&h.appendChild(e);i();return{start:function(){e.setAttribute("style","display:inline")},end:function(){e.setAttribute("style","display:none")},_teardown:function(j){document.getElementById(j.target)&&document.getElementById(j.target).removeChild(e);
-delete j.feed}}},{about:{name:"Popcorn Google Feed Plugin",version:"0.1",author:"David Seifried",website:"dseifried.wordpress.com"},options:{start:{elem:"input",type:"number",label:"Start"},end:{elem:"input",type:"number",label:"End"},target:"feed-container",url:{elem:"input",type:"url",label:"Feed URL","default":"http://planet.mozilla.org/rss20.xml"},title:{elem:"input",type:"text",label:"Title","default":"Planet Mozilla",optional:true},orientation:{elem:"select",options:["Vertical","Horizontal"],
-label:"Orientation","default":"Vertical",optional:true}}})})(Popcorn);(function(r){var f=0,n=function(c,b){var e=c.container=document.createElement("div"),h=e.style,i=c.media,j=function(){var p=c.position();h.fontSize="18px";h.width=i.offsetWidth+"px";h.top=p.top+i.offsetHeight-e.offsetHeight-40+"px";h.left=p.left+"px";setTimeout(j,10)};e.id=b||r.guid();h.position="absolute";h.color="white";h.textShadow="black 2px 2px 6px";h.fontWeight="bold";h.textAlign="center";j();c.media.parentNode.appendChild(e);return e};r.plugin("subtitle",{manifest:{about:{name:"Popcorn Subtitle Plugin",
-version:"0.1",author:"Scott Downe",website:"http://scottdowne.wordpress.com/"},options:{start:{elem:"input",type:"text",label:"Start"},end:{elem:"input",type:"text",label:"End"},target:"subtitle-container",text:{elem:"input",type:"text",label:"Text"}}},_setup:function(c){var b=document.createElement("div");b.id="subtitle-"+f++;b.style.display="none";!this.container&&(!c.target||c.target==="subtitle-container")&&n(this);c.container=c.target&&c.target!=="subtitle-container"?document.getElementById(c.target)||
-n(this,c.target):this.container;document.getElementById(c.container.id)&&document.getElementById(c.container.id).appendChild(b);c.innerContainer=b;c.showSubtitle=function(){c.innerContainer.innerHTML=c.text||""}},start:function(c,b){b.innerContainer.style.display="inline";b.showSubtitle(b,b.text)},end:function(c,b){b.innerContainer.style.display="none";b.innerContainer.innerHTML=""},_teardown:function(c){c.container.removeChild(c.innerContainer)}})})(Popcorn);(function(r){var f=false;r.plugin("twitter",{manifest:{about:{name:"Popcorn Twitter Plugin",version:"0.1",author:"Scott Downe",website:"http://scottdowne.wordpress.com/"},options:{start:{elem:"input",type:"number",label:"Start"},end:{elem:"input",type:"number",label:"End"},src:{elem:"input",type:"text",label:"Tweet Source (# or @)","default":"@popcornjs"},target:"twitter-container",height:{elem:"input",type:"number",label:"Height","default":"200",optional:true},width:{elem:"input",type:"number",label:"Width",
-"default":"250",optional:true}}},_setup:function(n){if(!window.TWTR&&!f){f=true;r.getScript("//widgets.twimg.com/j/2/widget.js")}var c=document.getElementById(n.target);n.container=document.createElement("div");n.container.setAttribute("id",r.guid());n.container.style.display="none";c&&c.appendChild(n.container);var b=n.src||"";c=n.width||250;var e=n.height||200,h=/^@/.test(b),i={version:2,id:n.container.getAttribute("id"),rpp:30,width:c,height:e,interval:6E3,theme:{shell:{background:"#ffffff",color:"#000000"},
-tweets:{background:"#ffffff",color:"#444444",links:"#1985b5"}},features:{loop:true,timestamp:true,avatars:true,hashtags:true,toptweets:true,live:true,scrollbar:false,behavior:"default"}},j=function(p){if(window.TWTR)if(h){i.type="profile";(new TWTR.Widget(i)).render().setUser(b).start()}else{i.type="search";i.search=b;i.subject=b;(new TWTR.Widget(i)).render().start()}else setTimeout(function(){j(p)},1)};j(this)},start:function(n,c){c.container.style.display="inline"},end:function(n,c){c.container.style.display=
-"none"},_teardown:function(n){document.getElementById(n.target)&&document.getElementById(n.target).removeChild(n.container)}})})(Popcorn);(function(r){r.plugin("webpage",{manifest:{about:{name:"Popcorn Webpage Plugin",version:"0.1",author:"@annasob",website:"annasob.wordpress.com"},options:{id:{elem:"input",type:"text",label:"Id",optional:true},start:{elem:"input",type:"number",label:"Start"},end:{elem:"input",type:"number",label:"End"},src:{elem:"input",type:"url",label:"Webpage URL","default":"http://mozillapopcorn.org"},target:"iframe-container"}},_setup:function(f){var n=document.getElementById(f.target);f.src=f.src.replace(/^(https?:)?(\/\/)?/,
-"//");f._iframe=document.createElement("iframe");f._iframe.setAttribute("width","100%");f._iframe.setAttribute("height","100%");f._iframe.id=f.id;f._iframe.src=f.src;f._iframe.style.display="none";n&&n.appendChild(f._iframe)},start:function(f,n){n._iframe.src=n.src;n._iframe.style.display="inline"},end:function(f,n){n._iframe.style.display="none"},_teardown:function(f){document.getElementById(f.target)&&document.getElementById(f.target).removeChild(f._iframe)}})})(Popcorn);var wikiCallback;
-(function(r){r.plugin("wikipedia",{manifest:{about:{name:"Popcorn Wikipedia Plugin",version:"0.1",author:"@annasob",website:"annasob.wordpress.com"},options:{start:{elem:"input",type:"number",label:"Start"},end:{elem:"input",type:"number",label:"End"},lang:{elem:"input",type:"text",label:"Language","default":"english",optional:true},src:{elem:"input",type:"url",label:"Wikipedia URL","default":"http://en.wikipedia.org/wiki/Cat"},title:{elem:"input",type:"text",label:"Title","default":"Cats",optional:true},
-numberofwords:{elem:"input",type:"number",label:"Number of Words","default":"200",optional:true},target:"wikipedia-container"}},_setup:function(f){var n,c=r.guid();if(!f.lang)f.lang="en";f.numberofwords=f.numberofwords||200;window["wikiCallback"+c]=function(b){f._link=document.createElement("a");f._link.setAttribute("href",f.src);f._link.setAttribute("target","_blank");f._link.innerHTML=f.title||b.parse.displaytitle;f._desc=document.createElement("p");n=b.parse.text["*"].substr(b.parse.text["*"].indexOf("<p>"));
-n=n.replace(/((<(.|\n)+?>)|(\((.*?)\) )|(\[(.*?)\]))/g,"");n=n.split(" ");f._desc.innerHTML=n.slice(0,n.length>=f.numberofwords?f.numberofwords:n.length).join(" ")+" ...";f._fired=true};f.src&&r.getScript("//"+f.lang+".wikipedia.org/w/api.php?action=parse&props=text&redirects&page="+f.src.slice(f.src.lastIndexOf("/")+1)+"&format=json&callback=wikiCallback"+c)},start:function(f,n){var c=function(){if(n._fired){if(n._link&&n._desc)if(document.getElementById(n.target)){document.getElementById(n.target).appendChild(n._link);
-document.getElementById(n.target).appendChild(n._desc);n._added=true}}else setTimeout(function(){c()},13)};c()},end:function(f,n){if(n._added){document.getElementById(n.target).removeChild(n._link);document.getElementById(n.target).removeChild(n._desc)}},_teardown:function(f){if(f._added){f._link.parentNode&&document.getElementById(f.target).removeChild(f._link);f._desc.parentNode&&document.getElementById(f.target).removeChild(f._desc);delete f.target}}})})(Popcorn);(function(r){r.plugin("mustache",function(f){var n,c,b,e;r.getScript("http://mustache.github.com/extras/mustache.js");var h=!!f.dynamic,i=typeof f.template,j=typeof f.data,p=document.getElementById(f.target);f.container=p||document.createElement("div");if(i==="function")if(h)b=f.template;else e=f.template(f);else e=i==="string"?f.template:"";if(j==="function")if(h)n=f.data;else c=f.data(f);else c=j==="string"?JSON.parse(f.data):j==="object"?f.data:"";return{start:function(m,o){var q=function(){if(window.Mustache){if(n)c=
-n(o);if(b)e=b(o);var s=Mustache.to_html(e,c).replace(/^\s*/mg,"");o.container.innerHTML=s}else setTimeout(function(){q()},10)};q()},end:function(m,o){o.container.innerHTML=""},_teardown:function(){n=c=b=e=null}}},{about:{name:"Popcorn Mustache Plugin",version:"0.1",author:"David Humphrey (@humphd)",website:"http://vocamus.net/dave"},options:{start:{elem:"input",type:"number",label:"Start"},end:{elem:"input",type:"number",label:"End"},target:"mustache-container",template:{elem:"input",type:"text",
-label:"Template"},data:{elem:"input",type:"text",label:"Data"},dynamic:{elem:"input",type:"checkbox",label:"Dynamic","default":true}}})})(Popcorn);(function(r){function f(c,b){if(c.map)c.map.div.style.display=b;else setTimeout(function(){f(c,b)},10)}var n=1;r.plugin("openmap",function(c){var b,e,h,i,j,p,m,o,q=document.getElementById(c.target);b=document.createElement("div");b.id="openmapdiv"+n;b.style.width="100%";b.style.height="100%";n++;q&&q.appendChild(b);o=function(){if(window.OpenLayers&&window.OpenLayers.Layer.Stamen){if(c.location){location=new OpenLayers.LonLat(0,0);r.getJSONP("//tinygeocoder.com/create-api.php?q="+c.location+"&callback=jsonp",
-function(d){e=new OpenLayers.LonLat(d[1],d[0])})}else e=new OpenLayers.LonLat(c.lng,c.lat);c.type=c.type||"ROADMAP";switch(c.type){case "SATELLITE":c.map=new OpenLayers.Map({div:b,maxResolution:0.28125,tileSize:new OpenLayers.Size(512,512)});var s=new OpenLayers.Layer.WorldWind("LANDSAT","//worldwind25.arc.nasa.gov/tile/tile.aspx",2.25,4,{T:"105"});c.map.addLayer(s);i=new OpenLayers.Projection("EPSG:4326");h=new OpenLayers.Projection("EPSG:4326");break;case "TERRAIN":i=new OpenLayers.Projection("EPSG:4326");
-h=new OpenLayers.Projection("EPSG:4326");c.map=new OpenLayers.Map({div:b,projection:h});s=new OpenLayers.Layer.WMS("USGS Terraserver","//terraserver-usa.org/ogcmap.ashx?",{layers:"DRG"});c.map.addLayer(s);break;case "STAMEN-TONER":case "STAMEN-WATERCOLOR":case "STAMEN-TERRAIN":s=c.type.replace("STAMEN-","").toLowerCase();s=new OpenLayers.Layer.Stamen(s);i=new OpenLayers.Projection("EPSG:4326");h=new OpenLayers.Projection("EPSG:900913");e=e.transform(i,h);c.map=new OpenLayers.Map({div:b,projection:h,
-displayProjection:i,controls:[new OpenLayers.Control.Navigation,new OpenLayers.Control.PanPanel,new OpenLayers.Control.ZoomPanel]});c.map.addLayer(s);break;default:h=new OpenLayers.Projection("EPSG:900913");i=new OpenLayers.Projection("EPSG:4326");e=e.transform(i,h);c.map=new OpenLayers.Map({div:b,projection:h,displayProjection:i});s=new OpenLayers.Layer.OSM;c.map.addLayer(s)}if(c.map){c.map.setCenter(e,c.zoom||10);c.map.div.style.display="none"}}else setTimeout(function(){o()},50)};o();return{_setup:function(s){window.OpenLayers||
-r.getScript("//openlayers.org/api/OpenLayers.js",function(){r.getScript("//maps.stamen.com/js/tile.stamen.js")});var d=function(){if(s.map){s.zoom=s.zoom||2;if(s.zoom&&typeof s.zoom!=="number")s.zoom=+s.zoom;s.map.setCenter(e,s.zoom);if(s.markers){var A=OpenLayers.Util.extend({},OpenLayers.Feature.Vector.style["default"]),y=function(v){clickedFeature=v.feature;if(clickedFeature.attributes.text){m=new OpenLayers.Popup.FramedCloud("featurePopup",clickedFeature.geometry.getBounds().getCenterLonLat(),
-new OpenLayers.Size(120,250),clickedFeature.attributes.text,null,true,function(){p.unselect(this.feature)});clickedFeature.popup=m;m.feature=clickedFeature;s.map.addPopup(m)}},x=function(v){feature=v.feature;if(feature.popup){m.feature=null;s.map.removePopup(feature.popup);feature.popup.destroy();feature.popup=null}},a=function(v){r.getJSONP("//tinygeocoder.com/create-api.php?q="+v.location+"&callback=jsonp",function(z){z=(new OpenLayers.Geometry.Point(z[1],z[0])).transform(i,h);var C=OpenLayers.Util.extend({},
-A);if(!v.size||isNaN(v.size))v.size=14;C.pointRadius=v.size;C.graphicOpacity=1;C.externalGraphic=v.icon;z=new OpenLayers.Feature.Vector(z,null,C);if(v.text)z.attributes={text:v.text};j.addFeatures([z])})};j=new OpenLayers.Layer.Vector("Point Layer",{style:A});s.map.addLayer(j);for(var g=0,l=s.markers.length;g<l;g++){var k=s.markers[g];if(k.text)if(!p){p=new OpenLayers.Control.SelectFeature(j);s.map.addControl(p);p.activate();j.events.on({featureselected:y,featureunselected:x})}if(k.location)a(k);
-else{var t=(new OpenLayers.Geometry.Point(k.lng,k.lat)).transform(i,h),u=OpenLayers.Util.extend({},A);if(!k.size||isNaN(k.size))k.size=14;u.pointRadius=k.size;u.graphicOpacity=1;u.externalGraphic=k.icon;t=new OpenLayers.Feature.Vector(t,null,u);if(k.text)t.attributes={text:k.text};j.addFeatures([t])}}}}else setTimeout(function(){d()},13)};d()},start:function(s,d){f(d,"block")},end:function(s,d){f(d,"none")},_teardown:function(){q&&q.removeChild(b);b=map=e=h=i=j=p=m=null}}},{about:{name:"Popcorn OpenMap Plugin",
+(function(p,e){function l(a){C.put.call(this,a)}function d(a){this.parent=a;this.byStart=[{start:-1,end:-1}];this.byEnd=[{start:-1,end:-1}];this.animating=[];this.endIndex=this.startIndex=0;this.previousUpdateTime=-1;this.count=1}function b(a,c){return function(){if(f.plugin.debug)return a.apply(this,arguments);try{return a.apply(this,arguments)}catch(n){f.plugin.errors.push({plugin:c,thrown:n,source:a.toString()});this.emit("pluginerror",f.plugin.errors)}}}if(e.addEventListener){var h=Array.prototype,
+i=Object.prototype,g=h.forEach,k=h.slice,r=i.hasOwnProperty,m=i.toString,t=p.Popcorn,q=[],o=false,u={events:{hash:{},apis:{}}},E=function(){return p.requestAnimationFrame||p.webkitRequestAnimationFrame||p.mozRequestAnimationFrame||p.oRequestAnimationFrame||p.msRequestAnimationFrame||function(a){p.setTimeout(a,16)}}(),C={put:function(a){for(var c in a)if(a.hasOwnProperty(c))this[c]=a[c]}},f=function(a,c){return new f.p.init(a,c||null)};f.version="1.5.6";f.isSupported=true;f.instances=[];f.p=f.prototype=
+{init:function(a,c){var n,j=this;if(typeof a==="function")if(e.readyState==="complete")a(e,f);else{q.push(a);if(!o){o=true;var w=function(){e.removeEventListener("DOMContentLoaded",w,false);for(var F=0,v=q.length;F<v;F++)q[F].call(e,f);q=null};e.addEventListener("DOMContentLoaded",w,false)}}else{if(typeof a==="string")try{n=e.querySelector(a)}catch(x){throw Error("Popcorn.js Error: Invalid media element selector: "+a);}this.media=n||a;n=this.media.nodeName&&this.media.nodeName.toLowerCase()||"video";
+this[n]=this.media;this.options=f.extend({},c)||{};this.id=this.options.id||f.guid(n);if(f.byId(this.id))throw Error("Popcorn.js Error: Cannot use duplicate ID ("+this.id+")");this.isDestroyed=false;this.data={running:{cue:[]},timeUpdate:f.nop,disabled:{},events:{},hooks:{},history:[],state:{volume:this.media.volume},trackRefs:{},trackEvents:new d(this)};f.instances.push(this);var z=function(){if(j.media.currentTime<0)j.media.currentTime=0;j.media.removeEventListener("loadedmetadata",z,false);var F,
+v,L,y,s;F=j.media.duration;F=F!=F?Number.MAX_VALUE:F+1;f.addTrackEvent(j,{start:F,end:F});if(!j.isDestroyed){j.data.durationChange=function(){var B=j.media.duration,Q=B+1,K=j.data.trackEvents.byStart,M=j.data.trackEvents.byEnd;K.pop();M.pop();for(var D=M.length-1;D>0;D--)M[D].end>B&&j.removeTrackEvent(M[D]._id);for(M=0;M<K.length;M++)K[M].end>B&&j.removeTrackEvent(K[M]._id);j.data.trackEvents.byEnd.push({start:Q,end:Q});j.data.trackEvents.byStart.push({start:Q,end:Q})};j.media.addEventListener("durationchange",
+j.data.durationChange,false)}if(j.options.frameAnimation){j.data.timeUpdate=function(){f.timeUpdate(j,{});f.forEach(f.manifest,function(B,Q){if(v=j.data.running[Q]){y=v.length;for(var K=0;K<y;K++){L=v[K];(s=L._natives)&&s.frame&&s.frame.call(j,{},L,j.currentTime())}}});j.emit("timeupdate");!j.isDestroyed&&E(j.data.timeUpdate)};!j.isDestroyed&&E(j.data.timeUpdate)}else{j.data.timeUpdate=function(B){f.timeUpdate(j,B)};j.isDestroyed||j.media.addEventListener("timeupdate",j.data.timeUpdate,false)}};j.media.addEventListener("error",
+function(){j.error=j.media.error},false);j.media.readyState>=1?z():j.media.addEventListener("loadedmetadata",z,false);return this}}};f.p.init.prototype=f.p;f.byId=function(a){for(var c=f.instances,n=c.length,j=0;j<n;j++)if(c[j].id===a)return c[j];return null};f.forEach=function(a,c,n){if(!a||!c)return{};n=n||this;var j,w;if(g&&a.forEach===g)return a.forEach(c,n);if(m.call(a)==="[object NodeList]"){j=0;for(w=a.length;j<w;j++)c.call(n,a[j],j,a);return a}for(j in a)r.call(a,j)&&c.call(n,a[j],j,a);return a};
+f.extend=function(a){var c=k.call(arguments,1);f.forEach(c,function(n){for(var j in n)a[j]=n[j]});return a};f.extend(f,{noConflict:function(a){if(a)p.Popcorn=t;return f},error:function(a){throw Error(a);},guid:function(a){f.guid.counter++;return(a?a:"")+(+new Date+f.guid.counter)},sizeOf:function(a){var c=0,n;for(n in a)c++;return c},isArray:Array.isArray||function(a){return m.call(a)==="[object Array]"},nop:function(){},position:function(a){if(!a.parentNode)return null;a=a.getBoundingClientRect();
+var c={},n=e.documentElement,j=e.body,w,x,z;w=n.clientTop||j.clientTop||0;x=n.clientLeft||j.clientLeft||0;z=p.pageYOffset&&n.scrollTop||j.scrollTop;n=p.pageXOffset&&n.scrollLeft||j.scrollLeft;w=Math.ceil(a.top+z-w);x=Math.ceil(a.left+n-x);for(var F in a)c[F]=Math.round(a[F]);return f.extend({},c,{top:w,left:x})},disable:function(a,c){if(!a.data.disabled[c]){a.data.disabled[c]=true;if(c in f.registryByName&&a.data.running[c])for(var n=a.data.running[c].length-1,j;n>=0;n--){j=a.data.running[c][n];j._natives.end.call(a,
+null,j);a.emit("trackend",f.extend({},j,{plugin:j.type,type:"trackend"}))}return a}},enable:function(a,c){if(a.data.disabled[c]){a.data.disabled[c]=false;if(c in f.registryByName&&a.data.running[c])for(var n=a.data.running[c].length-1,j;n>=0;n--){j=a.data.running[c][n];j._natives.start.call(a,null,j);a.emit("trackstart",f.extend({},j,{plugin:j.type,type:"trackstart",track:j}))}return a}},destroy:function(a){var c=a.data.events,n=a.data.trackEvents,j,w,x,z;for(w in c){j=c[w];for(x in j)delete j[x];
+c[w]=null}for(z in f.registryByName)f.removePlugin(a,z);n.byStart.length=0;n.byEnd.length=0;if(!a.isDestroyed){a.data.timeUpdate&&a.media.removeEventListener("timeupdate",a.data.timeUpdate,false);a.isDestroyed=true}f.instances.splice(f.instances.indexOf(a),1)}});f.guid.counter=1;f.extend(f.p,function(){var a={};f.forEach("load play pause currentTime playbackRate volume duration preload playbackRate autoplay loop controls muted buffered readyState seeking paused played seekable ended".split(/\s+/g),
+function(c){a[c]=function(n){var j;if(typeof this.media[c]==="function"){if(n!=null&&/play|pause/.test(c))this.media.currentTime=f.util.toSeconds(n);this.media[c]();return this}if(n!=null){j=this.media[c];this.media[c]=n;j!==n&&this.emit("attrchange",{attribute:c,previousValue:j,currentValue:n});return this}return this.media[c]}});return a}());f.forEach("enable disable".split(" "),function(a){f.p[a]=function(c){return f[a](this,c)}});f.extend(f.p,{roundTime:function(){return Math.round(this.media.currentTime)},
+exec:function(a,c,n){var j=arguments.length,w="trackadded",x,z;try{z=f.util.toSeconds(a)}catch(F){}if(typeof z==="number")a=z;if(typeof a==="number"&&j===2){n=c;c=a;a=f.guid("cue")}else if(j===1)c=-1;else if(x=this.getTrackEvent(a)){this.data.trackEvents.remove(a);l.end(this,x);f.removeTrackEvent.ref(this,a);w="cuechange";if(typeof a==="string"&&j===2){if(typeof c==="number")n=x._natives.start;if(typeof c==="function"){n=c;c=x.start}}}else if(j>=2){if(typeof c==="string"){try{z=f.util.toSeconds(c)}catch(v){}c=
+z}if(typeof c==="number")n=n||f.nop();if(typeof c==="function"){n=c;c=-1}}j={id:a,start:c,end:c+1,_running:false,_natives:{start:n||f.nop,end:f.nop,type:"cue"}};if(x)j=f.extend(x,j);if(w==="cuechange"){j._id=j.id||j._id||f.guid(j._natives.type);this.data.trackEvents.add(j);l.start(this,j);this.timeUpdate(this,null,true);f.addTrackEvent.ref(this,j);this.emit(w,f.extend({},j,{id:a,type:w,previousValue:{time:x.start,fn:x._natives.start},currentValue:{time:c,fn:n||f.nop},track:x}))}else f.addTrackEvent(this,
+j);return this},mute:function(a){a=a==null||a===true?"muted":"unmuted";if(a==="unmuted"){this.media.muted=false;this.media.volume=this.data.state.volume}if(a==="muted"){this.data.state.volume=this.media.volume;this.media.muted=true}this.emit(a);return this},unmute:function(a){return this.mute(a==null?false:!a)},position:function(){return f.position(this.media)},toggle:function(a){return f[this.data.disabled[a]?"enable":"disable"](this,a)},defaults:function(a,c){if(f.isArray(a)){f.forEach(a,function(n){for(var j in n)this.defaults(j,
+n[j])},this);return this}if(!this.options.defaults)this.options.defaults={};this.options.defaults[a]||(this.options.defaults[a]={});f.extend(this.options.defaults[a],c);return this}});f.Events={UIEvents:"blur focus focusin focusout load resize scroll unload",MouseEvents:"mousedown mouseup mousemove mouseover mouseout mouseenter mouseleave click dblclick",Events:"loadstart progress suspend emptied stalled play pause error loadedmetadata loadeddata waiting playing canplay canplaythrough seeking seeked timeupdate ended ratechange durationchange volumechange"};
+f.Events.Natives=f.Events.UIEvents+" "+f.Events.MouseEvents+" "+f.Events.Events;u.events.apiTypes=["UIEvents","MouseEvents","Events"];(function(a,c){for(var n=u.events.apiTypes,j=a.Natives.split(/\s+/g),w=0,x=j.length;w<x;w++)c.hash[j[w]]=true;n.forEach(function(z){c.apis[z]={};for(var F=a[z].split(/\s+/g),v=F.length,L=0;L<v;L++)c.apis[z][F[L]]=true})})(f.Events,u.events);f.events={isNative:function(a){return!!u.events.hash[a]},getInterface:function(a){if(!f.events.isNative(a))return false;var c=
+u.events,n=c.apiTypes;c=c.apis;for(var j=0,w=n.length,x,z;j<w;j++){z=n[j];if(c[z][a]){x=z;break}}return x},all:f.Events.Natives.split(/\s+/g),fn:{trigger:function(a,c){var n,j=this.data.events[a];if(j){if(n=f.events.getInterface(a)){n=e.createEvent(n);n.initEvent(a,true,true,p,1);this.media.dispatchEvent(n);return this}for(n=j.slice();n.length;)n.shift().call(this,c)}return this},listen:function(a,c){var n=this,j=true,w=f.events.hooks[a],x,z;if(typeof c!=="function")throw Error("Popcorn.js Error: Listener is not a function");
+if(!this.data.events[a]){this.data.events[a]=[];j=false}if(w){w.add&&w.add.call(this,{},c);if(w.bind)a=w.bind;if(w.handler){z=c;c=function(F){w.handler.call(n,F,z)}}j=true;if(!this.data.events[a]){this.data.events[a]=[];j=false}}this.data.events[a].push(c);!j&&f.events.all.indexOf(a)>-1&&this.media.addEventListener(a,function(F){if(n.data.events[a])for(x=n.data.events[a].slice();x.length;)x.shift().call(n,F)},false);return this},unlisten:function(a,c){var n,j=this.data.events[a];if(j){if(typeof c===
+"string"){for(n=0;n<j.length;n++)j[n].name===c&&j.splice(n--,1);return this}else if(typeof c==="function"){for(;n!==-1;){n=j.indexOf(c);n!==-1&&j.splice(n,1)}return this}this.data.events[a]=null;return this}}},hooks:{canplayall:{bind:"canplaythrough",add:function(a,c){var n=false;if(this.media.readyState){setTimeout(function(){c.call(this,a)}.bind(this),0);n=true}this.data.hooks.canplayall={fired:n}},handler:function(a,c){if(!this.data.hooks.canplayall.fired){c.call(this,a);this.data.hooks.canplayall.fired=
+true}}}}};f.forEach([["trigger","emit"],["listen","on"],["unlisten","off"]],function(a){f.p[a[0]]=f.p[a[1]]=f.events.fn[a[0]]});l.start=function(a,c){if(c.end>a.media.currentTime&&c.start<=a.media.currentTime&&!c._running){c._running=true;a.data.running[c._natives.type].push(c);if(!a.data.disabled[c._natives.type]){c._natives.start.call(a,null,c);a.emit("trackstart",f.extend({},c,{plugin:c._natives.type,type:"trackstart",track:c}))}}};l.end=function(a,c){var n;if((c.end<=a.media.currentTime||c.start>
+a.media.currentTime)&&c._running){n=a.data.running[c._natives.type];c._running=false;n.splice(n.indexOf(c),1);if(!a.data.disabled[c._natives.type]){c._natives.end.call(a,null,c);a.emit("trackend",f.extend({},c,{plugin:c._natives.type,type:"trackend",track:c}))}}};d.prototype.where=function(a){return(this.parent.getTrackEvents()||[]).filter(function(c){var n,j;if(!a)return true;for(n in a){j=a[n];if(c[n]&&c[n]===j||c._natives[n]&&c._natives[n]===j)return true}return false})};d.prototype.add=function(a){var c=
+this.byStart,n=this.byEnd,j;a&&a._id&&this.parent.data.history.push(a._id);a.start=f.util.toSeconds(a.start,this.parent.options.framerate);a.end=f.util.toSeconds(a.end,this.parent.options.framerate);for(j=c.length-1;j>=0;j--)if(a.start>=c[j].start){c.splice(j+1,0,a);break}for(c=n.length-1;c>=0;c--)if(a.end>n[c].end){n.splice(c+1,0,a);break}j<=this.parent.data.trackEvents.startIndex&&a.start<=this.parent.data.trackEvents.previousUpdateTime&&this.parent.data.trackEvents.startIndex++;c<=this.parent.data.trackEvents.endIndex&&
+a.end<this.parent.data.trackEvents.previousUpdateTime&&this.parent.data.trackEvents.endIndex++;this.count++};d.prototype.remove=function(a){if(a instanceof l)a=a.id;if(typeof a==="object"){this.where(a).forEach(function(y){this.removeTrackEvent(y._id)},this.parent);return this}var c,n,j;j=this.byStart.length;for(var w=0,x=0,z=[],F=[],v=[],L=[];--j>-1;){c=this.byStart[w];n=this.byEnd[w];if(!c._id){z.push(c);F.push(n)}if(c._id){c._id!==a&&z.push(c);n._id!==a&&F.push(n);if(c._id===a)x=w}w++}j=this.animating.length;
+w=0;if(j)for(;--j>-1;){c=this.animating[w];c._id||v.push(c);c._id&&c._id!==a&&v.push(c);w++}x<=this.startIndex&&this.startIndex--;x<=this.endIndex&&this.endIndex--;this.byStart=z;this.byEnd=F;this.animating=v;this.count--;j=this.parent.data.history.length;for(w=0;w<j;w++)this.parent.data.history[w]!==a&&L.push(this.parent.data.history[w]);this.parent.data.history=L};f.addTrackEvent=function(a,c){var n;if(!(c instanceof l)){if((c=new l(c))&&c._natives&&c._natives.type&&a.options.defaults&&a.options.defaults[c._natives.type]){n=
+f.extend({},c);f.extend(c,a.options.defaults[c._natives.type],n)}if(c._natives){c._id=c.id||c._id||f.guid(c._natives.type);if(c._natives._setup){c._natives._setup.call(a,c);a.emit("tracksetup",f.extend({},c,{plugin:c._natives.type,type:"tracksetup",track:c}))}}a.data.trackEvents.add(c);l.start(a,c);this.timeUpdate(a,null,true);c._id&&f.addTrackEvent.ref(a,c);a.emit("trackadded",f.extend({},c,c._natives?{plugin:c._natives.type}:{},{type:"trackadded",track:c}))}};f.addTrackEvent.ref=function(a,c){a.data.trackRefs[c._id]=
+c;return a};f.removeTrackEvent=function(a,c){var n=a.getTrackEvent(c);if(n){n._natives._teardown&&n._natives._teardown.call(a,n);a.data.trackEvents.remove(c);f.removeTrackEvent.ref(a,c);n._natives&&a.emit("trackremoved",f.extend({},n,{plugin:n._natives.type,type:"trackremoved",track:n}))}};f.removeTrackEvent.ref=function(a,c){delete a.data.trackRefs[c];return a};f.getTrackEvents=function(a){var c=[];a=a.data.trackEvents.byStart;for(var n=a.length,j=0,w;j<n;j++){w=a[j];w._id&&c.push(w)}return c};f.getTrackEvents.ref=
+function(a){return a.data.trackRefs};f.getTrackEvent=function(a,c){return a.data.trackRefs[c]};f.getTrackEvent.ref=function(a,c){return a.data.trackRefs[c]};f.getLastTrackEventId=function(a){return a.data.history[a.data.history.length-1]};f.timeUpdate=function(a,c){var n=a.media.currentTime,j=a.data.trackEvents.previousUpdateTime,w=a.data.trackEvents,x=w.endIndex,z=w.startIndex,F=w.byStart.length,v=w.byEnd.length,L=f.registryByName,y,s,B;if(j<=n){for(;w.byEnd[x]&&w.byEnd[x].end<=n;){y=w.byEnd[x];
+s=(j=y._natives)&&j.type;if(!j||L[s]||a[s]){if(y._running===true){y._running=false;B=a.data.running[s];B.splice(B.indexOf(y),1);if(!a.data.disabled[s]){j.end.call(a,c,y);a.emit("trackend",f.extend({},y,{plugin:s,type:"trackend",track:y}))}}x++}else{f.removeTrackEvent(a,y._id);return}}for(;w.byStart[z]&&w.byStart[z].start<=n;){y=w.byStart[z];s=(j=y._natives)&&j.type;if(!j||L[s]||a[s]){if(y.end>n&&y._running===false){y._running=true;a.data.running[s].push(y);if(!a.data.disabled[s]){j.start.call(a,c,
+y);a.emit("trackstart",f.extend({},y,{plugin:s,type:"trackstart",track:y}))}}z++}else{f.removeTrackEvent(a,y._id);return}}}else if(j>n){for(;w.byStart[z]&&w.byStart[z].start>n;){y=w.byStart[z];s=(j=y._natives)&&j.type;if(!j||L[s]||a[s]){if(y._running===true){y._running=false;B=a.data.running[s];B.splice(B.indexOf(y),1);if(!a.data.disabled[s]){j.end.call(a,c,y);a.emit("trackend",f.extend({},y,{plugin:s,type:"trackend",track:y}))}}z--}else{f.removeTrackEvent(a,y._id);return}}for(;w.byEnd[x]&&w.byEnd[x].end>
+n;){y=w.byEnd[x];s=(j=y._natives)&&j.type;if(!j||L[s]||a[s]){if(y.start<=n&&y._running===false){y._running=true;a.data.running[s].push(y);if(!a.data.disabled[s]){j.start.call(a,c,y);a.emit("trackstart",f.extend({},y,{plugin:s,type:"trackstart",track:y}))}}x--}else{f.removeTrackEvent(a,y._id);return}}}w.endIndex=x;w.startIndex=z;w.previousUpdateTime=n;w.byStart.length<F&&w.startIndex--;w.byEnd.length<v&&w.endIndex--};f.extend(f.p,{getTrackEvents:function(){return f.getTrackEvents.call(null,this)},
+getTrackEvent:function(a){return f.getTrackEvent.call(null,this,a)},getLastTrackEventId:function(){return f.getLastTrackEventId.call(null,this)},removeTrackEvent:function(a){f.removeTrackEvent.call(null,this,a);return this},removePlugin:function(a){f.removePlugin.call(null,this,a);return this},timeUpdate:function(a){f.timeUpdate.call(null,this,a);return this},destroy:function(){f.destroy.call(null,this);return this}});f.manifest={};f.registry=[];f.registryByName={};f.plugin=function(a,c,n){if(f.protect.natives.indexOf(a.toLowerCase())>=
+0)f.error("'"+a+"' is a protected function name");else{var j=typeof c==="function",w=["start","end","type","manifest"],x=["_setup","_teardown","start","end","frame"],z={},F=function(y,s){y=y||f.nop;s=s||f.nop;return function(){y.apply(this,arguments);s.apply(this,arguments)}};f.manifest[a]=n=n||c.manifest||{};x.forEach(function(y){c[y]=b(c[y]||f.nop,a)});var v=function(y,s){if(!s)return this;if(s.ranges&&f.isArray(s.ranges)){f.forEach(s.ranges,function(M){M=f.extend({},s,M);delete M.ranges;this[a](M)},
+this);return this}var B=s._natives={},Q="",K;f.extend(B,y);s._natives.type=s._natives.plugin=a;s._running=false;B.start=B.start||B["in"];B.end=B.end||B.out;if(s.once)B.end=F(B.end,function(){this.removeTrackEvent(s._id)});B._teardown=F(function(){var M=k.call(arguments),D=this.data.running[B.type];M.unshift(null);M[1]._running&&D.splice(D.indexOf(s),1)&&B.end.apply(this,M);M[1]._running=false;this.emit("trackend",f.extend({},s,{plugin:B.type,type:"trackend",track:f.getTrackEvent(this,s.id||s._id)}))},
+B._teardown);B._teardown=F(B._teardown,function(){this.emit("trackteardown",f.extend({},s,{plugin:a,type:"trackteardown",track:f.getTrackEvent(this,s.id||s._id)}))});s.compose=s.compose||[];if(typeof s.compose==="string")s.compose=s.compose.split(" ");s.effect=s.effect||[];if(typeof s.effect==="string")s.effect=s.effect.split(" ");s.compose=s.compose.concat(s.effect);s.compose.forEach(function(M){Q=f.compositions[M]||{};x.forEach(function(D){B[D]=F(B[D],Q[D])})});s._natives.manifest=n;if(!("start"in
+s))s.start=s["in"]||0;if(!s.end&&s.end!==0)s.end=s.out||Number.MAX_VALUE;if(!r.call(s,"toString"))s.toString=function(){var M=["start: "+s.start,"end: "+s.end,"id: "+(s.id||s._id)];s.target!=null&&M.push("target: "+s.target);return a+" ( "+M.join(", ")+" )"};if(!s.target){K="options"in n&&n.options;s.target=K&&"target"in K&&K.target}if(!s._id&&s._natives)s._id=f.guid(s._natives.type);if(s instanceof l){if(s._natives){s._id=s.id||s._id||f.guid(s._natives.type);if(s._natives._setup){s._natives._setup.call(this,
+s);this.emit("tracksetup",f.extend({},s,{plugin:s._natives.type,type:"tracksetup",track:s}))}}this.data.trackEvents.add(s);l.start(this,s);this.timeUpdate(this,null,true);s._id&&f.addTrackEvent.ref(this,s)}else f.addTrackEvent(this,s);f.forEach(y,function(M,D){w.indexOf(D)===-1&&this.on(D,M)},this);return this};f.p[a]=z[a]=function(y,s){var B,Q;if(y&&!s)s=y;else if(B=this.getTrackEvent(y)){Q=s;var K={},M;for(M in B)if(r.call(Q,M)&&r.call(B,M))K[M]=B[M];if(B._natives._update){this.data.trackEvents.remove(B);
+if(r.call(s,"start"))B.start=s.start;if(r.call(s,"end"))B.end=s.end;l.end(this,B);j&&c.call(this,B);B._natives._update.call(this,B,s);this.data.trackEvents.add(B);l.start(this,B)}else{f.extend(B,s);this.data.trackEvents.remove(y);B._natives._teardown&&B._natives._teardown.call(this,B);f.removeTrackEvent.ref(this,y);if(j)v.call(this,c.call(this,B),B);else{B._id=B.id||B._id||f.guid(B._natives.type);if(B._natives&&B._natives._setup){B._natives._setup.call(this,B);this.emit("tracksetup",f.extend({},B,
+{plugin:B._natives.type,type:"tracksetup",track:B}))}this.data.trackEvents.add(B);l.start(this,B);this.timeUpdate(this,null,true);f.addTrackEvent.ref(this,B)}this.emit("trackchange",{id:B.id,type:"trackchange",previousValue:K,currentValue:B,track:B});return this}B._natives.type!=="cue"&&this.emit("trackchange",{id:B.id,type:"trackchange",previousValue:K,currentValue:Q,track:B});return this}else s.id=y;this.data.running[a]=this.data.running[a]||[];B=f.extend({},this.options.defaults&&this.options.defaults[a]||
+{},s);v.call(this,j?c.call(this,B):c,B);return this};n&&f.extend(c,{manifest:n});var L={fn:z[a],definition:c,base:c,parents:[],name:a};f.registry.push(f.extend(z,L,{type:a}));f.registryByName[a]=L;return z}};f.plugin.errors=[];f.plugin.debug=f.version==="1.5.6";f.removePlugin=function(a,c){if(!c){c=a;a=f.p;if(f.protect.natives.indexOf(c.toLowerCase())>=0){f.error("'"+c+"' is a protected function name");return}var n=f.registry.length,j;for(j=0;j<n;j++)if(f.registry[j].name===c){f.registry.splice(j,
+1);delete f.registryByName[c];delete f.manifest[c];delete a[c];return}}n=a.data.trackEvents.byStart;j=a.data.trackEvents.byEnd;var w=a.data.trackEvents.animating,x,z;x=0;for(z=n.length;x<z;x++){if(n[x]&&n[x]._natives&&n[x]._natives.type===c){n[x]._natives._teardown&&n[x]._natives._teardown.call(a,n[x]);n.splice(x,1);x--;z--;if(a.data.trackEvents.startIndex<=x){a.data.trackEvents.startIndex--;a.data.trackEvents.endIndex--}}j[x]&&j[x]._natives&&j[x]._natives.type===c&&j.splice(x,1)}x=0;for(z=w.length;x<
+z;x++)if(w[x]&&w[x]._natives&&w[x]._natives.type===c){w.splice(x,1);x--;z--}};f.compositions={};f.compose=function(a,c,n){f.manifest[a]=n||c.manifest||{};f.compositions[a]=c};f.plugin.effect=f.effect=f.compose;var G=/^(?:\.|#|\[)/;f.dom={debug:false,find:function(a,c){var n=null;c=c||e;if(a){if(!G.test(a)){n=e.getElementById(a);if(n!==null)return n}try{n=c.querySelector(a)}catch(j){if(f.dom.debug)throw Error(j);}}return n}};var A=/\?/,O={ajax:null,url:"",data:"",dataType:"",success:f.nop,type:"GET",
+async:true,contentType:"application/x-www-form-urlencoded; charset=UTF-8"};f.xhr=function(a){a.dataType=a.dataType&&a.dataType.toLowerCase()||null;if(a.dataType&&(a.dataType==="jsonp"||a.dataType==="script"))f.xhr.getJSONP(a.url,a.success,a.dataType==="script");else{a=f.extend({},O,a);a.ajax=new XMLHttpRequest;if(a.ajax){if(a.type==="GET"&&a.data){a.url+=(A.test(a.url)?"&":"?")+a.data;a.data=null}a.ajax.open(a.type,a.url,a.async);a.type==="POST"&&a.ajax.setRequestHeader("Content-Type",a.contentType);
+a.ajax.send(a.data||null);return f.xhr.httpData(a)}}};f.xhr.httpData=function(a){var c,n=null,j,w=null;a.ajax.onreadystatechange=function(){if(a.ajax.readyState===4){try{n=JSON.parse(a.ajax.responseText)}catch(x){}c={xml:a.ajax.responseXML,text:a.ajax.responseText,json:n};if(!c.xml||!c.xml.documentElement){c.xml=null;try{j=new DOMParser;w=j.parseFromString(a.ajax.responseText,"text/xml");if(!w.getElementsByTagName("parsererror").length)c.xml=w}catch(z){}}if(a.dataType)c=c[a.dataType];a.success.call(a.ajax,
+c)}};return c};f.xhr.getJSONP=function(a,c,n){var j=e.head||e.getElementsByTagName("head")[0]||e.documentElement,w=e.createElement("script"),x=false,z=[];z=/(=)\?(?=&|$)|\?\?/;var F,v;if(!n){v=a.match(/(callback=[^&]*)/);if(v!==null&&v.length){z=v[1].split("=")[1];if(z==="?")z="jsonp";F=f.guid(z);a=a.replace(/(callback=[^&]*)/,"callback="+F)}else{F=f.guid("jsonp");if(z.test(a))a=a.replace(z,"$1"+F);z=a.split(/\?(.+)?/);a=z[0]+"?";if(z[1])a+=z[1]+"&";a+="callback="+F}window[F]=function(L){c&&c(L);
+x=true}}w.addEventListener("load",function(){n&&c&&c();x&&delete window[F];j.removeChild(w)},false);w.addEventListener("error",function(L){c&&c({error:L});n||delete window[F];j.removeChild(w)},false);w.src=a;j.insertBefore(w,j.firstChild)};f.getJSONP=f.xhr.getJSONP;f.getScript=f.xhr.getScript=function(a,c){return f.xhr.getJSONP(a,c,true)};f.util={toSeconds:function(a,c){var n=/^([0-9]+:){0,2}[0-9]+([.;][0-9]+)?$/,j,w,x;if(typeof a==="number")return a;typeof a==="string"&&!n.test(a)&&f.error("Invalid time format");
+n=a.split(":");j=n.length-1;w=n[j];if(w.indexOf(";")>-1){w=w.split(";");x=0;if(c&&typeof c==="number")x=parseFloat(w[1],10)/c;n[j]=parseInt(w[0],10)+x}j=n[0];return{1:parseFloat(j,10),2:parseInt(j,10)*60+parseFloat(n[1],10),3:parseInt(j,10)*3600+parseInt(n[1],10)*60+parseFloat(n[2],10)}[n.length||1]}};f.p.cue=f.p.exec;f.protect={natives:function(a){return Object.keys?Object.keys(a):function(c){var n,j=[];for(n in c)r.call(c,n)&&j.push(n);return j}(a)}(f.p).map(function(a){return a.toLowerCase()})};
+f.forEach({listen:"on",unlisten:"off",trigger:"emit",exec:"cue"},function(a,c){var n=f.p[c];f.p[c]=function(){if(typeof console!=="undefined"&&console.warn){console.warn("Deprecated method '"+c+"', "+(a==null?"do not use.":"use '"+a+"' instead."));f.p[c]=n}return f.p[a].apply(this,[].slice.call(arguments))}});p.Popcorn=f}else{p.Popcorn={isSupported:false};for(h="byId forEach extend effects error guid sizeOf isArray nop position disable enable destroyaddTrackEvent removeTrackEvent getTrackEvents getTrackEvent getLastTrackEventId timeUpdate plugin removePlugin compose effect xhr getJSONP getScript".split(/\s+/);h.length;)p.Popcorn[h.shift()]=
+function(){}}})(window,window.document);(function(p,e){var l=p.document,d=p.location,b=/:\/\//,h=d.href.replace(d.href.split("/").slice(-1)[0],""),i=function(k,r,m){k=k||0;r=(r||k||0)+1;m=m||1;r=Math.ceil((r-k)/m)||0;var t=0,q=[];for(q.length=r;t<r;){q[t++]=k;k+=m}return q};e.sequence=function(k,r){return new e.sequence.init(k,r)};e.sequence.init=function(k,r){this.parent=l.getElementById(k);this.seqId=e.guid("__sequenced");this.queue=[];this.playlist=[];this.inOuts={ofVideos:[],ofClips:[]};this.dims={width:0,height:0};this.active=0;this.playing=
+this.cycling=false;this.times={last:0};this.events={};var m=this,t=0;e.forEach(r,function(q,o){var u=l.createElement("video");u.preload="auto";u.controls=true;u.style.display=o&&"none"||"";u.id=m.seqId+"-"+o;m.queue.push(u);var E=q["in"],C=q.out;m.inOuts.ofVideos.push({"in":E!==undefined&&E||1,out:C!==undefined&&C||0});m.inOuts.ofVideos[o].out=m.inOuts.ofVideos[o].out||m.inOuts.ofVideos[o]["in"]+2;u.src=!b.test(q.src)?h+q.src:q.src;u.setAttribute("data-sequence-owner",k);u.setAttribute("data-sequence-guid",
+m.seqId);u.setAttribute("data-sequence-id",o);u.setAttribute("data-sequence-clip",[m.inOuts.ofVideos[o]["in"],m.inOuts.ofVideos[o].out].join(":"));m.parent.appendChild(u);m.playlist.push(e("#"+u.id))});m.inOuts.ofVideos.forEach(function(q){q={"in":t,out:t+(q.out-q["in"])};m.inOuts.ofClips.push(q);t=q.out+1});e.forEach(this.queue,function(q,o){function u(){if(!o){m.dims.width=q.videoWidth;m.dims.height=q.videoHeight}q.currentTime=m.inOuts.ofVideos[o]["in"]-0.5;q.removeEventListener("canplaythrough",
+u,false);return true}q.addEventListener("canplaythrough",u,false);q.addEventListener("play",function(){m.playing=true},false);q.addEventListener("pause",function(){m.playing=false},false);q.addEventListener("timeupdate",function(E){E=E.srcElement||E.target;E=+(E.dataset&&E.dataset.sequenceId||E.getAttribute("data-sequence-id"));var C=Math.floor(q.currentTime);if(m.times.last!==C&&E===m.active){m.times.last=C;C===m.inOuts.ofVideos[E].out&&e.sequence.cycle.call(m,E)}},false)});return this};e.sequence.init.prototype=
+e.sequence.prototype;e.sequence.cycle=function(k){this.queue||e.error("Popcorn.sequence.cycle is not a public method");var r=this.queue,m=this.inOuts.ofVideos,t=r[k],q=0,o;if(r[k+1])q=k+1;if(r[k+1]){r=r[q];m=m[q];e.extend(r,{width:this.dims.width,height:this.dims.height});o=this.playlist[q];t.pause();this.active=q;this.times.last=m["in"]-1;o.currentTime(m["in"]);o[q?"play":"pause"]();this.trigger("cycle",{position:{previous:k,current:q}});if(q){t.style.display="none";r.style.display=""}this.cycling=
+false}else this.playlist[k].pause();return this};var g=["timeupdate","play","pause"];e.extend(e.sequence.prototype,{eq:function(k){return this.playlist[k]},remove:function(){this.parent.innerHTML=null},clip:function(k){return this.inOuts.ofVideos[k]},duration:function(){for(var k=0,r=this.inOuts.ofClips,m=0;m<r.length;m++)k+=r[m].out-r[m]["in"]+1;return k-1},play:function(){this.playlist[this.active].play();return this},exec:function(k,r){var m=this.active;this.inOuts.ofClips.forEach(function(t,q){if(k>=
+t["in"]&&k<=t.out)m=q});k+=this.inOuts.ofVideos[m]["in"]-this.inOuts.ofClips[m]["in"];e.addTrackEvent(this.playlist[m],{start:k-1,end:k,_running:false,_natives:{start:r||e.nop,end:e.nop,type:"exec"}});return this},listen:function(k,r){var m=this,t=this.playlist,q=t.length,o=0;if(!r)r=e.nop;if(e.Events.Natives.indexOf(k)>-1)e.forEach(t,function(u){u.listen(k,function(E){E.active=m;if(g.indexOf(k)>-1)r.call(u,E);else++o===q&&r.call(u,E)})});else{this.events[k]||(this.events[k]={});t=r.name||e.guid("__"+
+k);this.events[k][t]=r}return this},unlisten:function(){},trigger:function(k,r){var m=this;if(!(e.Events.Natives.indexOf(k)>-1)){this.events[k]&&e.forEach(this.events[k],function(t){t.call(m,{type:k},r)});return this}}});e.forEach(e.manifest,function(k,r){e.sequence.prototype[r]=function(m){var t={},q=[],o,u,E,C,f;for(o=0;o<this.inOuts.ofClips.length;o++){q=this.inOuts.ofClips[o];u=i(q["in"],q.out);E=u.indexOf(m.start);C=u.indexOf(m.end);if(E>-1)t[o]=e.extend({},q,{start:u[E],clipIdx:E});if(C>-1)t[o]=
+e.extend({},q,{end:u[C],clipIdx:C})}o=Object.keys(t).map(function(A){return+A});q=i(o[0],o[1]);for(o=0;o<q.length;o++){E={};C=q[o];var G=t[C];if(G){f=this.inOuts.ofVideos[C];u=G.clipIdx;f=i(f["in"],f.out);if(G.start){E.start=f[u];E.end=f[f.length-1]}if(G.end){E.start=f[0];E.end=f[u]}}else{E.start=this.inOuts.ofVideos[C]["in"];E.end=this.inOuts.ofVideos[C].out}this.playlist[C][r](e.extend({},m,E))}return this}})})(this,Popcorn);(function(p,e){function l(h){h=typeof h==="string"?h:[h.language,h.region].join("-");var i=h.split("-");return{iso6391:h,language:i[0]||"",region:i[1]||""}}var d=p.navigator,b=l(d.userLanguage||d.language);e.locale={get:function(){return b},set:function(h){b=l(h);e.locale.broadcast();return b},broadcast:function(h){var i=e.instances,g=i.length,k=0,r;for(h=h||"locale:changed";k<g;k++){r=i[k];h in r.data.events&&r.trigger(h)}}}})(this,this.Popcorn);(function(p){document.addEventListener("DOMContentLoaded",function(){var e=document.querySelectorAll("[data-timeline-sources]");p.forEach(e,function(l,d){var b=e[d],h,i,g;if(!b.id)b.id=p.guid("__popcorn");if(b.nodeType&&b.nodeType===1){g=p("#"+b.id);h=(b.getAttribute("data-timeline-sources")||"").split(",");h[0]&&p.forEach(h,function(k){i=k.split("!");if(i.length===1){i=k.match(/(.*)[\/\\]([^\/\\]+\.\w+)$/)[2].split(".");i[0]="parse"+i[1].toUpperCase();i[1]=k}h[0]&&g[i[0]]&&g[i[0]](i[1])});g.autoplay()&&
+g.play()}})},false)})(Popcorn);(function(p){var e=function(l,d){l=l||p.nop;d=d||p.nop;return function(){l.apply(this,arguments);d.apply(this,arguments)}};p.player=function(l,d){if(!p[l]){d=d||{};var b=function(h,i,g){g=g||{};var k=new Date/1E3,r=k,m=0,t=0,q=1,o=false,u={},E=typeof h==="string"?p.dom.find(h):h,C={};Object.prototype.__defineGetter__||(C=E||document.createElement("div"));for(var f in E)if(!(f in C))if(typeof E[f]==="object")C[f]=E[f];else if(typeof E[f]==="function")C[f]=function(A){return"length"in E[A]&&!E[A].call?
+E[A]:function(){return E[A].apply(E,arguments)}}(f);else p.player.defineProperty(C,f,{get:function(A){return function(){return E[A]}}(f),set:p.nop,configurable:true});var G=function(){k=new Date/1E3;if(!C.paused){C.currentTime+=k-r;C.dispatchEvent("timeupdate");setTimeout(G,10)}r=k};C.play=function(){this.paused=false;if(C.readyState>=4){r=new Date/1E3;C.dispatchEvent("play");G()}};C.pause=function(){this.paused=true;C.dispatchEvent("pause")};p.player.defineProperty(C,"currentTime",{get:function(){return m},
+set:function(A){m=+A;C.dispatchEvent("timeupdate");return m},configurable:true});p.player.defineProperty(C,"volume",{get:function(){return q},set:function(A){q=+A;C.dispatchEvent("volumechange");return q},configurable:true});p.player.defineProperty(C,"muted",{get:function(){return o},set:function(A){o=+A;C.dispatchEvent("volumechange");return o},configurable:true});p.player.defineProperty(C,"readyState",{get:function(){return t},set:function(A){return t=A},configurable:true});C.addEventListener=function(A,
+O){u[A]||(u[A]=[]);u[A].push(O);return O};C.removeEventListener=function(A,O){var a,c=u[A];if(c){for(a=u[A].length-1;a>=0;a--)O===c[a]&&c.splice(a,1);return O}};C.dispatchEvent=function(A){var O,a=A.type;if(!a){a=A;if(A=p.events.getInterface(a)){O=document.createEvent(A);O.initEvent(a,true,true,window,1)}}if(u[a])for(A=u[a].length-1;A>=0;A--)u[a][A].call(this,O,this)};C.src=i||"";C.duration=0;C.paused=true;C.ended=0;g&&g.events&&p.forEach(g.events,function(A,O){C.addEventListener(O,A,false)});if(d._canPlayType(E.nodeName,
+i)!==false)if(d._setup)d._setup.call(C,g);else{C.readyState=4;C.dispatchEvent("loadedmetadata");C.dispatchEvent("loadeddata");C.dispatchEvent("canplaythrough")}else setTimeout(function(){C.dispatchEvent("error")},0);h=new p.p.init(C,g);if(d._teardown)h.destroy=e(h.destroy,function(){d._teardown.call(C,g)});return h};b.canPlayType=d._canPlayType=d._canPlayType||p.nop;p[l]=p.player.registry[l]=b}};p.player.registry={};p.player.defineProperty=Object.defineProperty||function(l,d,b){l.__defineGetter__(d,
+b.get||p.nop);l.__defineSetter__(d,b.set||p.nop)};p.player.playerQueue=function(){var l=[],d=false;return{next:function(){d=false;l.shift();l[0]&&l[0]()},add:function(b){l.push(function(){d=true;b&&b()});!d&&l[0]()}}};p.smart=function(l,d,b){var h=typeof l==="string"?p.dom.find(l):l,i,g,k,r,m,t="HTMLYouTubeVideoElement HTMLVimeoVideoElement HTMLSoundCloudAudioElement HTMLNullVideoElement".split(" ");if(h){d=typeof d==="string"?[d]:d;l=0;for(m=d.length;l<m;l++){i=d[l];for(g=0;g<t.length;g++)if((r=
+p[t[g]])&&r._canPlaySrc(i)==="probably"){k=r(h);b=p(k,b);setTimeout(function(){k.src=i},0);return b}for(var q in p.player.registry)if(p.player.registry.hasOwnProperty(q))if(p.player.registry[q].canPlayType(h.nodeName,i))return p[q](h,i,b)}var o;q=p.guid("popcorn-video-");g=document.createElement("div");g.style.width="100%";g.style.height="100%";if(d.length===1){o=document.createElement("video");o.id=q;h.appendChild(o);setTimeout(function(){var u=document.createElement("div");u.innerHTML=d[0];o.src=
+u.firstChild.nodeValue},0);return p("#"+q,b)}h.appendChild(g);t='<video id="'+q+'" preload=auto autobuffer>';l=0;for(m=d.length;l<m;l++)t+='<source src="'+d[l]+'">';t+="</video>";g.innerHTML=t;b&&b.events&&b.events.error&&h.addEventListener("error",b.events.error,false);return p("#"+q,b)}else p.error("Specified target `"+l+"` was not found.")}})(Popcorn);(function(p){var e=Object.prototype.hasOwnProperty;p.parsers={};p.parser=function(l,d,b){if(p.protect.natives.indexOf(l.toLowerCase())>=0)p.error("'"+l+"' is a protected function name");else{if(typeof d==="function"&&!b){b=d;d=""}if(!(typeof b!=="function"||typeof d!=="string")){var h={};h[l]=function(i,g,k){if(!i)return this;if(typeof g!=="function"&&!k){k=g;g=null}var r=this;p.xhr({url:i,dataType:d,success:function(m){var t,q,o=0;m=b(m,k).data||[];if(t=m.length){for(;o<t;o++){q=m[o];for(var u in q)e.call(q,
+u)&&r[u]&&r[u](q[u])}g&&g()}}});return this};p.extend(p.p,h);return h}}}})(Popcorn);(function(p,e){function l(b){var h=l.options;b=h.parser[h.strictMode?"strict":"loose"].exec(b);for(var i={},g=14;g--;)i[h.key[g]]=b[g]||"";i[h.q.name]={};i[h.key[12]].replace(h.q.parser,function(k,r,m){if(r)i[h.q.name][r]=m});return i}l.options={strictMode:false,key:["source","protocol","authority","userInfo","user","password","host","port","relative","path","directory","file","query","anchor"],q:{name:"queryKey",parser:/(?:^|&)([^&=]*)=?([^&]*)/g},parser:{strict:/^(?:([^:\/?#]+):)?(?:\/\/((?:(([^:@]*)(?::([^:@]*))?)?@)?([^:\/?#]*)(?::(\d*))?))?((((?:[^?#\/]*\/)*)([^?#]*))(?:\?([^#]*))?(?:#(.*))?)/,
+loose:/^(?:(?![^:@]+:[^:@\/]*@)([^:\/?#.]+):)?(?:\/\/)?((?:(([^:@]*)(?::([^:@]*))?)?@)?([^:\/?#]*)(?::(\d*))?)(((\/(?:[^?#](?![^?#\/]*\.[^?#\/.]+(?:[?#]|$)))*\/?)?([^?#\/]*))(?:\?([^#]*))?(?:#(.*))?)/}};var d={length:0,start:p.nop,end:p.nop};window.MediaError=window.MediaError||function(){function b(h,i){this.code=h||null;this.message=i||""}b.MEDIA_ERR_NONE_ACTIVE=0;b.MEDIA_ERR_ABORTED=1;b.MEDIA_ERR_NETWORK=2;b.MEDIA_ERR_DECODE=3;b.MEDIA_ERR_NONE_SUPPORTED=4;return b}();p._MediaElementProto=function(){var b=
+{},h;Object.prototype.__defineGetter__||(b=e.createElement("div"));b._util={type:"HTML5",TIMEUPDATE_MS:250,MIN_WIDTH:300,MIN_HEIGHT:150,isAttributeSet:function(i){return typeof i==="string"||i===true},parseUri:l};b.addEventListener=function(i,g,k){e.addEventListener(this._eventNamespace+i,g,k)};b.removeEventListener=function(i,g,k){e.removeEventListener(this._eventNamespace+i,g,k)};b.dispatchEvent=function(i){var g=e.createEvent("CustomEvent");g.initCustomEvent(this._eventNamespace+i,false,false,
+{type:i,target:this.parentNode,data:null});e.dispatchEvent(g)};b.load=p.nop;b.canPlayType=function(){return""};b.getBoundingClientRect=function(){return h.getBoundingClientRect()};b.NETWORK_EMPTY=0;b.NETWORK_IDLE=1;b.NETWORK_LOADING=2;b.NETWORK_NO_SOURCE=3;b.HAVE_NOTHING=0;b.HAVE_METADATA=1;b.HAVE_CURRENT_DATA=2;b.HAVE_FUTURE_DATA=3;b.HAVE_ENOUGH_DATA=4;Object.defineProperties(b,{currentSrc:{get:function(){return this.src!==undefined?this.src:""},configurable:true},parentNode:{get:function(){return h},
+set:function(i){h=i},configurable:true},preload:{get:function(){return"auto"},set:p.nop,configurable:true},controls:{get:function(){return true},set:p.nop,configurable:true},poster:{get:function(){return""},set:p.nop,configurable:true},crossorigin:{get:function(){return""},configurable:true},played:{get:function(){return d},configurable:true},seekable:{get:function(){return d},configurable:true},buffered:{get:function(){return d},configurable:true},defaultMuted:{get:function(){return false},configurable:true},
+defaultPlaybackRate:{get:function(){return 1},configurable:true},style:{get:function(){return this.parentNode.style},configurable:true},id:{get:function(){return this.parentNode.id},configurable:true}});return b}})(Popcorn,window.document);(function(p,e,l){function d(){if(e.jwplayer){k=true;for(var t=m.length;t--;){m[t]();delete m[t]}}else setTimeout(d,100)}function b(){if(!r){if(!e.jwplayer){var t=l.createElement("script");t.src="https://jwpsrv.com/library/zaIF4JI9EeK2FSIACpYGxA.js";var q=l.getElementsByTagName("script")[0];q.parentNode.insertBefore(t,q)}r=true;d()}return k}function h(t){m.unshift(t)}function i(t){function q(P){D.unshift(P)}function o(){setTimeout(function(){v.duration=K.getDuration();z.dispatchEvent("durationchange");
+v.readyState=z.HAVE_METADATA;z.dispatchEvent("loadedmetadata");z.dispatchEvent("loadeddata");v.readyState=z.HAVE_FUTURE_DATA;z.dispatchEvent("canplay");for(B=true;D.length;){D[0]();D.shift()}v.readyState=z.HAVE_ENOUGH_DATA;z.dispatchEvent("canplaythrough")},0)}function u(){if(y)y=false;else if(I){I=false;o()}else n()}function E(){if(v.seeking){v.ended=false;v.seeking=false;z.dispatchEvent("timeupdate");z.dispatchEvent("seeked");z.dispatchEvent("canplay");z.dispatchEvent("canplaythrough")}}function C(){K.onPause(u);
+K.onTime(function(){if(!v.ended&&!v.seeking){v.currentTime=K.getPosition();z.dispatchEvent("timeupdate")}});K.onSeek(E);K.onPlay(function(){if(!v.ended)if(T){T=false;if(v.autoplay||!v.paused){v.paused=false;q(a);o()}else{s=I=true;K.pause(true)}}else if(s){s=false;y=true;K.pause(true)}else a()});K.onBufferChange(c);K.onComplete(j);K.play(true)}function f(P){var S={name:"MediaError"};S.message=P.message;S.code=P.code||5;v.error=S;z.dispatchEvent("error")}function G(P){if(z._canPlaySrc(P)){var S=z._util.parseUri(P).queryKey;
+v.controls=S.controls=S.controls||v.controls;v.src=P;if(b()){if(L)L&&K&&K.destroy();jwplayer(F.id).setup({file:P,width:"100%",height:"100%",controls:v.controls});K=jwplayer(F.id);K.onReady(C);K.onError(f);jwplayer.utils.log=function(H,V){if(typeof console!=="undefined"&&typeof console.log!=="undefined")V?console.log(H,V):console.log(H);H==="No suitable players found and fallback enabled"&&f({message:H,code:4})};v.networkState=z.NETWORK_LOADING;z.dispatchEvent("loadstart");z.dispatchEvent("progress")}else h(function(){G(P)})}else{v.error=
+{name:"MediaError",message:"Media Source Not Supported",code:MediaError.MEDIA_ERR_SRC_NOT_SUPPORTED};z.dispatchEvent("error")}}function A(P){v.currentTime=P;if(B){O();K.seek(P)}else q(function(){O();K.seek(P)})}function O(){v.seeking=true;if(v.paused)s=true;z.dispatchEvent("seeking")}function a(){v.paused=false;if(M){M=false;if(v.loop&&!Q||!v.loop){Q=true;z.dispatchEvent("play")}z.dispatchEvent("playing")}}function c(){z.dispatchEvent("progress")}function n(){v.paused=true;if(!M){M=true;z.dispatchEvent("pause")}}
+function j(){if(v.loop)A(0);else{v.ended=true;n();z.dispatchEvent("timeupdate");z.dispatchEvent("ended")}}function w(P){v.volume=P;if(B){K.setVolume(v.volume*100);z.dispatchEvent("volumechange")}else q(function(){w(v.volume)})}function x(P){v.muted=P;if(B){K.setMute(P);z.dispatchEvent("volumechange")}else q(function(){x(v.muted)})}if(!e.postMessage)throw"ERROR: HTMLJWPlayerVideoElement requires window.postMessage";var z=new p._MediaElementProto,F=typeof t==="string"?l.querySelector(t):t,v={src:g,
+networkState:z.NETWORK_EMPTY,readyState:z.HAVE_NOTHING,seeking:false,autoplay:g,preload:g,controls:false,loop:false,poster:g,volume:1,muted:false,currentTime:0,duration:NaN,ended:false,paused:true,error:null},L=false,y=false,s=false,B=false,Q=false,K,M=true,D=[],T=true,I=false;z._eventNamespace=p.guid("HTMLJWPlayerVideoElement::");z.parentNode=F;z._util.type="JWPlayer";z.play=function(){z.dispatchEvent("play");v.paused=false;if(B){if(v.ended){A(0);v.ended=false}K.play(true)}else q(function(){z.play()})};
+z.pause=function(){v.paused=true;B?K.pause(true):q(function(){z.pause()})};Object.defineProperties(z,{src:{get:function(){return v.src},set:function(P){P&&P!==v.src&&G(P)}},autoplay:{get:function(){return v.autoplay},set:function(P){v.autoplay=z._util.isAttributeSet(P)}},loop:{get:function(){return v.loop},set:function(P){v.loop=z._util.isAttributeSet(P)}},width:{get:function(){return z.parentNode.offsetWidth}},height:{get:function(){return z.parentNode.offsetHeight}},currentTime:{get:function(){return v.currentTime},
+set:function(P){A(P)}},duration:{get:function(){return K.getDuration()}},ended:{get:function(){return v.ended}},paused:{get:function(){return v.paused}},seeking:{get:function(){return v.seeking}},readyState:{get:function(){return v.readyState}},networkState:{get:function(){return v.networkState}},volume:{get:function(){return v.volume},set:function(P){if(P<0||P>1)throw"Volume value must be between 0.0 and 1.0";w(P)}},muted:{get:function(){return v.muted},set:function(P){x(z._util.isAttributeSet(P))}},
+error:{get:function(){return v.error}},buffered:{get:function(){var P={start:function(S){if(S===0)return 0;throw"INDEX_SIZE_ERR: DOM Exception 1";},end:function(S){if(S===0){S=K.getDuration();if(!S)return 0;return S*(K.getBuffer()/100)}throw"INDEX_SIZE_ERR: DOM Exception 1";}};Object.defineProperties(P,{length:{get:function(){return 1}}});return P}}});z._canPlaySrc=p.HTMLJWPlayerVideoElement._canPlaySrc;z.canPlayType=p.HTMLJWPlayerVideoElement.canPlayType;return z}var g="",k=false,r=false,m=[];p.HTMLJWPlayerVideoElement=
+function(t){return new i(t)};p.HTMLJWPlayerVideoElement._canPlaySrc=function(){return"probably"};p.HTMLJWPlayerVideoElement.canPlayType=function(){return"probably"}})(Popcorn,window,document);(function(p,e){function l(i){this.startTime=0;this.currentTime=i.currentTime||0;this.duration=i.duration||NaN;this.playInterval=null;this.paused=true;this.playbackRate=this.defaultPlaybackRate=1;this.ended=i.endedCallback||p.nop}function d(i){function g(a){A.push(a)}function k(){if(!C)return 0;return f.currentTime}function r(a){if(a!==k())if(C){G.seeking=true;o.dispatchEvent("seeking");f.seekTo(a);G.ended=false;G.seeking=false;o.dispatchEvent("timeupdate");o.dispatchEvent("seeked");o.dispatchEvent("canplay");
+o.dispatchEvent("canplaythrough")}else g(function(){r(a)})}function m(){o.dispatchEvent("timeupdate")}function t(){G.paused=true;clearInterval(O);o.dispatchEvent("pause")}function q(){if(G.loop){r(0);o.play()}else{G.ended=true;t();o.dispatchEvent("timeupdate");o.dispatchEvent("ended")}}var o=new p._MediaElementProto,u=typeof i==="string"?e.querySelector(i):i,E=e.createElement("div"),C=false,f,G={src:b,networkState:o.NETWORK_EMPTY,readyState:o.HAVE_NOTHING,autoplay:b,preload:b,controls:b,loop:false,
+poster:b,volume:1,muted:false,width:u.width|0?u.width:o._util.MIN_WIDTH,height:u.height|0?u.height:o._util.MIN_HEIGHT,seeking:false,ended:false,paused:1,error:null},A=[],O;o._eventNamespace=p.guid("HTMLNullVideoElement::");o.parentNode=u;o._util.type="NullVideo";o.play=function(){if(C){f.play();if(G.paused){if(G.paused===1){G.paused=false;o.dispatchEvent("play");o.dispatchEvent("playing")}else{if(G.ended){r(0);G.ended=false}if(G.paused){G.paused=false;G.loop||o.dispatchEvent("play");o.dispatchEvent("playing")}}O=
+setInterval(m,o._util.TIMEUPDATE_MS)}}else g(function(){o.play()})};o.pause=function(){if(C){f.pause();G.paused||t()}else g(function(){o.pause()})};Object.defineProperties(o,{src:{get:function(){return G.src},set:function(a){if(a&&a!==G.src)if(o._canPlaySrc(a)){G.src=a;if(C)if(C&&f){f.pause();f=null;u.removeChild(E);E=e.createElement("div")}E.width=G.width;E.height=G.height;u.appendChild(E);a=h.exec(a);f=new l({currentTime:+a[1],duration:+a[2],endedCallback:q});o.dispatchEvent("loadstart");o.dispatchEvent("progress");
+o.dispatchEvent("durationchange");C=true;G.networkState=o.NETWORK_IDLE;G.readyState=o.HAVE_METADATA;o.dispatchEvent("loadedmetadata");o.dispatchEvent("loadeddata");G.readyState=o.HAVE_FUTURE_DATA;o.dispatchEvent("canplay");G.readyState=o.HAVE_ENOUGH_DATA;for(o.dispatchEvent("canplaythrough");A.length;){a=A.shift();a()}G.autoplay&&o.play()}else{G.error={name:"MediaError",message:"Media Source Not Supported",code:MediaError.MEDIA_ERR_SRC_NOT_SUPPORTED};o.dispatchEvent("error")}}},autoplay:{get:function(){return G.autoplay},
+set:function(a){G.autoplay=o._util.isAttributeSet(a)}},loop:{get:function(){return G.loop},set:function(a){G.loop=o._util.isAttributeSet(a)}},width:{get:function(){return E.width},set:function(a){E.width=a;G.width=E.width}},height:{get:function(){return E.height},set:function(a){E.height=a;G.height=E.height}},currentTime:{get:function(){return k()},set:function(a){r(a)}},duration:{get:function(){return f?f.duration:NaN}},ended:{get:function(){return G.ended}},paused:{get:function(){return G.paused}},
+seeking:{get:function(){return G.seeking}},readyState:{get:function(){return G.readyState}},networkState:{get:function(){return G.networkState}},volume:{get:function(){return G.volume},set:function(a){if(a<0||a>1)throw"Volume value must be between 0.0 and 1.0";G.volume=a;o.dispatchEvent("volumechange")}},muted:{get:function(){return G.muted},set:function(a){a=o._util.isAttributeSet(a);G.muted=a;o.dispatchEvent("volumechange")}},playbackRate:{get:function(){return f.playbackRate},set:function(a){f.playbackRate=
+a;o.dispatchEvent("ratechange")}},error:{get:function(){return G.error}}});o._canPlaySrc=p.HTMLNullVideoElement._canPlaySrc;o.canPlayType=p.HTMLNullVideoElement.canPlayType;return o}var b="",h=/#t=(\d+\.?\d*)?,?(\d+\.?\d*)/;l.prototype={play:function(){var i=this;if(this.paused){this.paused=false;this.startTime=Date.now();this.playInterval=setInterval(function(){i.currentTime+=(Date.now()-i.startTime)/(1E3/i.playbackRate);i.startTime=Date.now();if(i.currentTime>=i.duration){i.pause(i.duration);i.ended()}i.currentTime<
+0&&i.pause(0)},16)}},pause:function(){if(!this.paused){this.paused=true;clearInterval(this.playInterval)}},seekTo:function(i){i=i<0?0:i;this.currentTime=i=i>this.duration?this.duration:i}};p.HTMLNullVideoElement=function(i){return new d(i)};p.HTMLNullVideoElement._canPlaySrc=function(i){return h.test(i)?"probably":b};p.HTMLNullVideoElement.canPlayType=function(i){return i==="video/x-nullvideo"?"probably":b}})(Popcorn,document);(function(p,e,l){function d(k){var r=this,m=k.src.split("?")[0];if(m.substr(0,2)==="//")m=e.location.protocol+m;"play pause paused seekTo unload getCurrentTime getDuration getVideoEmbedCode getVideoHeight getVideoWidth getVideoUrl getColor setColor setLoop getVolume setVolume addEventListener".split(" ").forEach(function(t){r[t]=function(q){q=JSON.stringify({method:t,value:q});k.contentWindow&&k.contentWindow.postMessage(q,m)}})}function b(k){function r(y){z.unshift(y)}function m(y){var s=c.duration;
+if(s!==y){c.duration=y;A.dispatchEvent("durationchange");if(isNaN(s)){c.networkState=A.NETWORK_IDLE;c.readyState=A.HAVE_METADATA;A.dispatchEvent("loadedmetadata");A.dispatchEvent("loadeddata");c.readyState=A.HAVE_FUTURE_DATA;A.dispatchEvent("canplay");c.readyState=A.HAVE_ENOUGH_DATA;A.dispatchEvent("canplaythrough");c.autoplay&&A.play();for(y=z.length;y--;){z[y]();delete z[y]}}}}function t(y){if(n){c.seeking=true;A.dispatchEvent("seeking");w.seekTo(y)}else r(function(){t(y)})}function q(){A.dispatchEvent("timeupdate")}
+function o(y){(c.currentTime=y)!==L&&A.dispatchEvent("timeupdate");L=c.currentTime}function u(y){if(y.origin===g){var s;try{s=JSON.parse(y.data)}catch(B){console.warn(B)}if(s.player_id==j)switch(s.event){case "ready":w=new d(a);w.addEventListener("loadProgress");w.addEventListener("pause");w.setVolume(0);w.play();break;case "loadProgress":if(parseFloat(s.data.duration)>0&&!n){n=true;w.pause()}break;case "pause":w.setVolume(1);e.removeEventListener("message",u,false);e.addEventListener("message",E,
+false);w.addEventListener("loadProgress");w.addEventListener("playProgress");w.addEventListener("play");w.addEventListener("pause");w.addEventListener("finish");w.addEventListener("seek");w.getDuration();c.networkState=A.NETWORK_LOADING;A.dispatchEvent("loadstart");A.dispatchEvent("progress")}}}function E(y){if(y.origin===g){var s;try{s=JSON.parse(y.data)}catch(B){console.warn(B)}if(s.player_id==j){switch(s.method){case "getCurrentTime":o(parseFloat(s.value));break;case "getDuration":m(parseFloat(s.value));
+break;case "getVolume":y=parseFloat(s.value);if(c.volume!==y){c.volume=y;A.dispatchEvent("volumechange")}}switch(s.event){case "loadProgress":A.dispatchEvent("progress");m(parseFloat(s.data.duration));break;case "playProgress":o(parseFloat(s.data.seconds));break;case "play":c.ended&&t(0);if(!v){v=setInterval(C,h);c.loop&&A.dispatchEvent("play")}F=setInterval(q,A._util.TIMEUPDATE_MS);c.paused=false;if(x){x=false;c.loop||A.dispatchEvent("play");A.dispatchEvent("playing")}break;case "pause":c.paused=
+true;if(!x){x=true;clearInterval(F);A.dispatchEvent("pause")}break;case "finish":if(c.loop){t(0);A.play()}else{c.ended=true;A.dispatchEvent("ended")}break;case "seek":o(parseFloat(s.data.seconds));c.seeking=false;A.dispatchEvent("timeupdate");A.dispatchEvent("seeked");A.dispatchEvent("canplay");A.dispatchEvent("canplaythrough")}}}}function C(){w.getCurrentTime()}function f(y){c.volume=y;if(n){w.setVolume(y);A.dispatchEvent("volumechange")}else r(function(){f(y)})}function G(y){if(n)if(y){c.muted=
+c.volume;f(0)}else{c.muted=0;f(c.muted)}else{c.muted=y?1:0;r(function(){G(y)})}}if(!e.postMessage)throw"ERROR: HTMLVimeoVideoElement requires window.postMessage";var A=new p._MediaElementProto,O=typeof k==="string"?p.dom.find(k):k,a=l.createElement("iframe"),c={src:i,networkState:A.NETWORK_EMPTY,readyState:A.HAVE_NOTHING,seeking:false,autoplay:i,preload:i,controls:false,loop:false,poster:i,volume:1,muted:0,currentTime:0,duration:NaN,ended:false,paused:true,error:null},n=false,j=p.guid(),w,x=true,
+z=[],F,v,L=0;A._eventNamespace=p.guid("HTMLVimeoVideoElement::");A.parentNode=O;A._util.type="Vimeo";A.play=function(){c.paused=false;n?w.play():r(function(){A.play()})};A.pause=function(){c.paused=true;n?w.pause():r(function(){A.pause()})};Object.defineProperties(A,{src:{get:function(){return c.src},set:function(y){if(y&&y!==c.src)if(A._canPlaySrc(y)){c.src=y;if(n)if(n&&w){clearInterval(v);w.pause();e.removeEventListener("message",E,false);O.removeChild(a);a=l.createElement("iframe")}n=false;y=A._util.parseUri(y);
+var s=y.queryKey,B,Q=["api=1","player_id="+j,"title=0","byline=0","portrait=0"];c.loop=s.loop==="1"||c.loop;delete s.loop;c.autoplay=s.autoplay==="1"||c.autoplay;delete s.autoplay;y=g+"/video/"+/\d+$/.exec(y.path)+"?";for(B in s)s.hasOwnProperty(B)&&Q.push(encodeURIComponent(B)+"="+encodeURIComponent(s[B]));y+=Q.join("&");a.id=j;a.style.width="100%";a.style.height="100%";a.frameBorder=0;a.webkitAllowFullScreen=true;a.mozAllowFullScreen=true;a.allowFullScreen=true;O.appendChild(a);a.src=y;e.addEventListener("message",
+u,false)}else{c.error={name:"MediaError",message:"Media Source Not Supported",code:MediaError.MEDIA_ERR_SRC_NOT_SUPPORTED};A.dispatchEvent("error")}}},autoplay:{get:function(){return c.autoplay},set:function(y){c.autoplay=A._util.isAttributeSet(y)}},loop:{get:function(){return c.loop},set:function(y){c.loop=A._util.isAttributeSet(y)}},width:{get:function(){return A.parentNode.offsetWidth}},height:{get:function(){return A.parentNode.offsetHeight}},currentTime:{get:function(){return c.currentTime},
+set:function(y){t(y)}},duration:{get:function(){return c.duration}},ended:{get:function(){return c.ended}},paused:{get:function(){return c.paused}},seeking:{get:function(){return c.seeking}},readyState:{get:function(){return c.readyState}},networkState:{get:function(){return c.networkState}},volume:{get:function(){return c.muted>0?c.muted:c.volume},set:function(y){if(y<0||y>1)throw"Volume value must be between 0.0 and 1.0";f(y)}},muted:{get:function(){return c.muted>0},set:function(y){G(A._util.isAttributeSet(y))}},
+error:{get:function(){return c.error}}});A._canPlaySrc=p.HTMLVimeoVideoElement._canPlaySrc;A.canPlayType=p.HTMLVimeoVideoElement.canPlayType;return A}var h=16,i="",g="https://player.vimeo.com";p.HTMLVimeoVideoElement=function(k){return new b(k)};p.HTMLVimeoVideoElement._canPlaySrc=function(k){return/player.vimeo.com\/video\/\d+/.test(k)||/vimeo.com\/\d+/.test(k)?"probably":i};p.HTMLVimeoVideoElement.canPlayType=function(k){return k==="video/x-vimeo"?"probably":i}})(Popcorn,window,document);(function(p,e){function l(){return"maybe"}function d(b,h){var i=typeof b==="string"?e.querySelector(b):b,g=e.createElement(h);i.appendChild(g);g._canPlaySrc=l;return g}p.HTMLVideoElement=function(b){return d(b,"video")};p.HTMLVideoElement._canPlaySrc=l;p.HTMLAudioElement=function(b){return d(b,"audio")};p.HTMLAudioElement._canPlaySrc=l})(Popcorn,window.document);(function(p,e,l){function d(){var u;if(YT.loaded)for(t=true;o.length;){u=o.shift();u()}else setTimeout(d,250)}function b(){var u;if(!q){if(e.YT)d();else{u=l.createElement("script");u.addEventListener("load",d,false);u.src="https://www.youtube.com/iframe_api";l.head.appendChild(u)}q=true}return t}function h(u){o.push(u)}function i(u){function E(J){W.push(J)}function C(){R.pauseVideo();j("play",C);n("play",K)}function f(){n("pause",M);j("pause",f)}function G(){var J=function(){if(R.isMuted()){n("play",
+c);R.playVideo()}else setTimeout(J,0)};V=true;R.mute();J()}function A(J){var N={name:"MediaError"};switch(J.data){case 2:N.message="Invalid video parameter.";N.code=MediaError.MEDIA_ERR_ABORTED;break;case 5:N.message="The requested content cannot be played in an HTML5 player or another error related to the HTML5 player has occurred.";N.code=MediaError.MEDIA_ERR_DECODE;case 100:N.message="Video not found.";N.code=MediaError.MEDIA_ERR_NETWORK;break;case 101:case 150:N.message="Video not usable.";N.code=
+MediaError.MEDIA_ERR_SRC_NOT_SUPPORTED;break;default:N.message="Unknown error.";N.code=5}H.error=N;I.dispatchEvent("error")}function O(){n("play",K);n("pause",M);if(H.autoplay||!H.paused){j("play",O);H.paused=false;E(function(){H.paused||K()})}H.muted||R.unMute();H.readyState=I.HAVE_METADATA;I.dispatchEvent("loadedmetadata");aa=setInterval(v,g);I.dispatchEvent("loadeddata");H.readyState=I.HAVE_FUTURE_DATA;I.dispatchEvent("canplay");U=true;for(ba=setInterval(L,50);W.length;){W[0]();W.shift()}H.readyState=
+I.HAVE_ENOUGH_DATA;I.dispatchEvent("canplaythrough")}function a(){j("pause",a);if(R.getCurrentTime()>0)setTimeout(a,0);else if(H.autoplay||!H.paused){n("play",O);R.playVideo()}else O()}function c(){j("play",c);if(R.getCurrentTime()===0)setTimeout(c,0);else{n("pause",a);R.seekTo(0);R.pauseVideo()}}function n(J,N){I.addEventListener("youtube-"+J,N,false)}function j(J,N){I.removeEventListener("youtube-"+J,N,false)}function w(J){I.dispatchEvent("youtube-"+J)}function x(){H.networkState=I.NETWORK_LOADING;
+I.dispatchEvent("waiting")}function z(J){switch(J.data){case YT.PlayerState.ENDED:w("ended");break;case YT.PlayerState.PLAYING:w("play");break;case YT.PlayerState.PAUSED:R.getDuration()!==R.getCurrentTime()&&w("pause");break;case YT.PlayerState.BUFFERING:w("buffering")}J.data!==YT.PlayerState.BUFFERING&&ca===YT.PlayerState.BUFFERING&&I.dispatchEvent("progress");ca=J.data}function F(J){if(I._canPlaySrc(J)){H.src=J;if(b()){if(V)if(U){if(V&&R){j("buffering",x);j("ended",D);j("play",K);j("pause",M);M();
+Z=U=false;H.currentTime=0;W=[];clearInterval(aa);clearInterval(ba);R.stopVideo();R.clearVideo();R.destroy();S=l.createElement("div")}}else{E(function(){F(J)});return}P.appendChild(S);var N=I._util.parseUri(J).queryKey;delete N.v;H.autoplay=N.autoplay==="1"||H.autoplay;delete N.autoplay;H.loop=N.loop==="1"||H.loop;delete N.loop;N.rel=N.rel||0;N.modestbranding=N.modestbranding||1;N.iv_load_policy=N.iv_load_policy||3;N.disablekb=N.disablekb||1;N.showinfo=N.showinfo||0;var ea=e.location.protocol==="file:"?
+"*":e.location.protocol+"//"+e.location.host;N.origin=N.origin||ea;N.controls=N.controls||H.controls?2:0;H.controls=N.controls;N.wmode=N.wmode||"opaque";J=r.exec(J)[1];p.getJSONP("https://gdata.youtube.com/feeds/api/videos/"+J+"?v=2&alt=jsonc&callback=?",function(X){if(X.error)console.warn("failed to retreive duration data, reason: "+X.error.message);else if(X.data){H.duration=X.data.duration;I.dispatchEvent("durationchange");R=new YT.Player(S,{width:"100%",height:"100%",wmode:N.wmode,videoId:J,playerVars:N,
+events:{onReady:G,onError:A,onStateChange:z}});H.networkState=I.NETWORK_LOADING;I.dispatchEvent("loadstart");I.dispatchEvent("progress")}else console.warn("failed to retreive duration data, reason: no response data")})}else h(function(){F(J)})}else{H.error={name:"MediaError",message:"Media Source Not Supported",code:MediaError.MEDIA_ERR_SRC_NOT_SUPPORTED};I.dispatchEvent("error")}}function v(){var J=R.getCurrentTime();if(H.seeking)m(J-H.currentTime)<1&&Q();else{if(m(H.currentTime-J)>g){B();Q()}H.currentTime=
+J}}function L(){var J=R.getVideoLoadedFraction();if(J&&$!==J){$=J;I.dispatchEvent("progress")}}function y(J){if(J!==H.currentTime){H.currentTime=J;if(U){B();R.seekTo(J)}else E(function(){B();R.seekTo(J)})}}function s(){I.dispatchEvent("timeupdate")}function B(){n("pause",f);j("pause",M);H.seeking=true;I.dispatchEvent("seeking")}function Q(){H.ended=false;H.seeking=false;I.dispatchEvent("timeupdate");I.dispatchEvent("seeked");I.dispatchEvent("canplay");I.dispatchEvent("canplaythrough")}function K(){if(H.ended){y(0);
+H.ended=false}da=setInterval(s,I._util.TIMEUPDATE_MS);H.paused=false;if(Y){Y=false;if(H.loop&&!Z||!H.loop){Z=true;I.dispatchEvent("play")}I.dispatchEvent("playing")}}function M(){H.paused=true;if(!Y){Y=true;clearInterval(da);I.dispatchEvent("pause")}}function D(){if(H.loop){y(0);I.play()}else{H.ended=true;M();n("play",C);j("play",K);I.dispatchEvent("timeupdate");I.dispatchEvent("ended")}}function T(J){H.muted=J;if(U){R[J?"mute":"unMute"]();I.dispatchEvent("volumechange")}else E(function(){T(H.muted)})}
+if(!e.postMessage)throw"ERROR: HTMLYouTubeVideoElement requires window.postMessage";var I=new p._MediaElementProto,P=typeof u==="string"?l.querySelector(u):u,S=l.createElement("div"),H={src:k,networkState:I.NETWORK_EMPTY,readyState:I.HAVE_NOTHING,seeking:false,autoplay:k,preload:k,controls:false,loop:false,poster:k,volume:1,muted:false,currentTime:0,duration:NaN,ended:false,paused:true,error:null},V=false,U=false,Z=false,R,Y=true,W=[],ca=-1,ba,$=0,aa,da;I._eventNamespace=p.guid("HTMLYouTubeVideoElement::");
+I.parentNode=P;I._util.type="YouTube";n("buffering",x);n("ended",D);I.play=function(){H.paused=false;U?R.playVideo():E(function(){I.play()})};I.pause=function(){H.paused=true;if(U){f();R.pauseVideo()}else E(function(){I.pause()})};Object.defineProperties(I,{src:{get:function(){return H.src},set:function(J){J&&J!==H.src&&F(J)}},autoplay:{get:function(){return H.autoplay},set:function(J){H.autoplay=I._util.isAttributeSet(J)}},loop:{get:function(){return H.loop},set:function(J){H.loop=I._util.isAttributeSet(J)}},
+width:{get:function(){return I.parentNode.offsetWidth}},height:{get:function(){return I.parentNode.offsetHeight}},currentTime:{get:function(){return H.currentTime},set:function(J){y(J)}},duration:{get:function(){return H.duration}},ended:{get:function(){return H.ended}},paused:{get:function(){return H.paused}},seeking:{get:function(){return H.seeking}},readyState:{get:function(){return H.readyState}},networkState:{get:function(){return H.networkState}},volume:{get:function(){return H.volume},set:function(J){if(J<
+0||J>1)throw"Volume value must be between 0.0 and 1.0";H.volume=J;if(U){R.setVolume(H.volume*100);I.dispatchEvent("volumechange")}else E(function(){I.volume=J})}},muted:{get:function(){return H.muted},set:function(J){T(I._util.isAttributeSet(J))}},error:{get:function(){return H.error}},buffered:{get:function(){var J={start:function(N){if(N===0)return 0;throw"INDEX_SIZE_ERR: DOM Exception 1";},end:function(N){if(N===0){if(!H.duration)return 0;return H.duration*$}throw"INDEX_SIZE_ERR: DOM Exception 1";
+}};Object.defineProperties(J,{length:{get:function(){return 1}}});return J},configurable:true}});I._canPlaySrc=p.HTMLYouTubeVideoElement._canPlaySrc;I.canPlayType=p.HTMLYouTubeVideoElement.canPlayType;return I}var g=10,k="",r=/^.*(?:\/|v=)(.{11})/,m=Math.abs,t=false,q=false,o=[];p.HTMLYouTubeVideoElement=function(u){return new i(u)};p.HTMLYouTubeVideoElement._canPlaySrc=function(u){return/(?:http:\/\/www\.|http:\/\/|www\.|\.|^)(youtu).*(?:\/|v=)(.{11})/.test(u)?"probably":k};p.HTMLYouTubeVideoElement.canPlayType=
+function(u){return u==="video/x-youtube"?"probably":k}})(Popcorn,window,document);(function(p,e,l){function d(){if(!r){p.getScript("https://w.soundcloud.com/player/api.js",function(){p.getScript("https://connect.soundcloud.com/sdk.js",function(){k=true;SC.initialize({client_id:"PRaNFlda6Bhf5utPjUsptg"});for(var t=m.length;t--;){m[t]();delete m[t]}})});r=true}return k}function b(t){m.unshift(t)}function h(t){function q(D){B.unshift(D)}function o(){s.bind(SC.Widget.Events.LOAD_PROGRESS,function(D){O({type:"loadProgress",data:D.currentPosition/1E3})});s.bind(SC.Widget.Events.PLAY_PROGRESS,
+function(D){O({type:"playProgress",data:D.currentPosition/1E3})});s.bind(SC.Widget.Events.PLAY,function(){O({type:"play"})});s.bind(SC.Widget.Events.PAUSE,function(){O({type:"pause"})});s.bind(SC.Widget.Events.SEEK,function(){s.getPosition(function(D){D=D/1E3;if(v.seeking)if(Math.floor(D)!==Math.floor(v.currentTime))s.seekTo(v.currentTime*1E3);else{v.ended=false;v.seeking=false;x.dispatchEvent("timeupdate");x.dispatchEvent("seeked");x.dispatchEvent("canplay");x.dispatchEvent("canplaythrough")}else O({type:"seek",
+data:D})})});s.bind(SC.Widget.Events.FINISH,function(){O({type:"finish"})});L=true;s.getDuration(E)}function u(){s.bind(SC.Widget.Events.PLAY_PROGRESS,function(D){s.setVolume(0);if(D.currentPosition>0){s.unbind(SC.Widget.Events.PLAY_PROGRESS);s.bind(SC.Widget.Events.PAUSE,function(){s.unbind(SC.Widget.Events.PAUSE);s.setVolume(100);s.bind(SC.Widget.Events.SEEK,function(){s.unbind(SC.Widget.Events.SEEK);o()});s.seekTo(0)});s.pause()}});s.play()}function E(D){D/=1E3;var T=v.duration;if(T!==D){v.duration=
+D;x.dispatchEvent("durationchange");if(isNaN(T)){v.networkState=x.NETWORK_IDLE;v.readyState=x.HAVE_METADATA;x.dispatchEvent("loadedmetadata");x.dispatchEvent("loadeddata");v.readyState=x.HAVE_FUTURE_DATA;x.dispatchEvent("canplay");v.readyState=x.HAVE_ENOUGH_DATA;x.dispatchEvent("canplaythrough");for(D=B.length;D--;){B[D]();delete B[D]}v.paused&&v.autoplay&&x.play()}}}function C(D){function T(){v.seeking=true;x.dispatchEvent("seeking");s.seekTo(D)}v.currentTime=D;D*=1E3;L?T():addMediaReadyCallback(T)}
+function f(){v.paused=true;if(!y){y=true;clearInterval(Q);x.dispatchEvent("pause")}}function G(){x.dispatchEvent("timeupdate")}function A(D){v.currentTime=D;D!==M&&x.dispatchEvent("timeupdate");M=D}function O(D){switch(D.type){case "loadProgress":x.dispatchEvent("progress");break;case "playProgress":A(D.data);break;case "play":if(!K){K=setInterval(a,i);v.loop&&x.dispatchEvent("play")}Q=setInterval(G,x._util.TIMEUPDATE_MS);v.paused=false;if(y){y=false;v.loop||x.dispatchEvent("play");x.dispatchEvent("playing")}break;
+case "pause":f();break;case "finish":if(v.loop){C(0);x.play()}else{v.ended=true;x.pause();f();x.dispatchEvent("timeupdate");x.dispatchEvent("ended")}break;case "seek":A(D.data)}}function a(){v.ended||s.getPosition(function(D){A(D/1E3)})}function c(D){if(x._canPlaySrc(D)){v.src=D;if(L)if(L&&s){clearInterval(K);s.pause();s.unbind(SC.Widget.Events.READY);s.unbind(SC.Widget.Events.LOAD_PROGRESS);s.unbind(SC.Widget.Events.PLAY_PROGRESS);s.unbind(SC.Widget.Events.PLAY);s.unbind(SC.Widget.Events.PAUSE);
+s.unbind(SC.Widget.Events.SEEK);s.unbind(SC.Widget.Events.FINISH);z.removeChild(F);F=l.createElement("iframe")}if(d()){L=false;SC.get("/resolve",{url:D},function(T){var I;if(T.errors){I={name:"MediaError"};if(T.errors[0])if(T.errors[0].error_message==="404 - Not Found"){I.message="Video not found.";I.code=MediaError.MEDIA_ERR_NETWORK}v.error=I;x.dispatchEvent("error")}F.id=p.guid("soundcloud-");F.width=v.width;F.height=v.height;F.frameBorder=0;F.webkitAllowFullScreen=true;F.mozAllowFullScreen=true;
+F.allowFullScreen=true;w(v.controls);z.appendChild(F);F.onload=function(){F.onload=null;s=SC.Widget(F);s.bind(SC.Widget.Events.READY,u);v.networkState=x.NETWORK_LOADING;x.dispatchEvent("loadstart");x.dispatchEvent("progress")};F.src="https://w.soundcloud.com/player/?url="+T.uri+"&show_artwork=false&buying=false&liking=false&sharing=false&download=false&show_comments=false&show_user=false&single_active=false"})}else b(function(){c(D)})}else{v.error={name:"MediaError",message:"Media Source Not Supported",
+code:MediaError.MEDIA_ERR_SRC_NOT_SUPPORTED};x.dispatchEvent("error")}}function n(D){v.volume=D;if(L){s.setVolume(D);x.dispatchEvent("volumechange")}else q(function(){n(D)})}function j(D){if(L)if(D){v.muted=v.volume;n(0)}else{v.muted=0;n(v.muted)}else{v.muted=D?1:0;q(function(){j(D)})}}function w(D){if(L){F.style.position="absolute";F.style.visibility=D?"visible":"hidden"}else{F.style.opacity=D?"1":"0";F.style.pointerEvents=D?"auto":"none"}v.controls=D}if(!e.postMessage)throw"ERROR: HTMLSoundCloudAudioElement requires window.postMessage";
+var x=new p._MediaElementProto,z=typeof t==="string"?p.dom.find(t):t,F=l.createElement("iframe"),v={src:g,networkState:x.NETWORK_EMPTY,readyState:x.HAVE_NOTHING,seeking:false,autoplay:g,preload:g,controls:false,loop:false,poster:g,volume:100,muted:0,currentTime:0,duration:NaN,ended:false,paused:true,width:z.width|0?z.width:x._util.MIN_WIDTH,height:z.height|0?z.height:x._util.MIN_HEIGHT,error:null},L=false,y=true,s,B=[],Q,K,M=0;x._eventNamespace=p.guid("HTMLSoundCloudAudioElement::");x.parentNode=
+z;x._util.type="SoundCloud";x.play=function(){v.paused=false;if(L){v.ended&&C(0);s.play()}else q(function(){x.play()})};x.pause=function(){v.paused=true;L?s.pause():q(function(){x.pause()})};Object.defineProperties(x,{src:{get:function(){return v.src},set:function(D){D&&D!==v.src&&c(D)}},autoplay:{get:function(){return v.autoplay},set:function(D){v.autoplay=x._util.isAttributeSet(D)}},loop:{get:function(){return v.loop},set:function(D){v.loop=x._util.isAttributeSet(D)}},width:{get:function(){return F.width},
+set:function(D){F.width=D;v.width=F.width}},height:{get:function(){return F.height},set:function(D){F.height=D;v.height=F.height}},currentTime:{get:function(){return v.currentTime},set:function(D){C(D)}},duration:{get:function(){return v.duration}},ended:{get:function(){return v.ended}},paused:{get:function(){return v.paused}},seeking:{get:function(){return v.seeking}},readyState:{get:function(){return v.readyState}},networkState:{get:function(){return v.networkState}},volume:{get:function(){return(v.muted>
+0?v.muted:v.volume)/100},set:function(D){if(D<0||D>1)throw"Volume value must be between 0.0 and 1.0";D*=100;n(D)}},muted:{get:function(){return v.muted>0},set:function(D){j(x._util.isAttributeSet(D))}},error:{get:function(){return v.error}},controls:{get:function(){return v.controls},set:function(D){w(!!D)}}});x._canPlaySrc=p.HTMLSoundCloudAudioElement._canPlaySrc;x.canPlayType=p.HTMLSoundCloudAudioElement.canPlayType;return x}var i=16,g="",k=false,r=false,m=[];p.HTMLSoundCloudAudioElement=function(t){return new h(t)};
+p.HTMLSoundCloudAudioElement._canPlaySrc=function(t){return/(?:https?:\/\/www\.|https?:\/\/|www\.|\.|^)(soundcloud)/.test(t)?"probably":g};p.HTMLSoundCloudAudioElement.canPlayType=function(t){return t==="audio/x-soundcloud"?"probably":g}})(Popcorn,window,document);(function(p){var e=function(l,d){var b=0,h=0,i;p.forEach(d.classes,function(g,k){i=[];if(g==="parent")i[0]=document.querySelectorAll("#"+d.target)[0].parentNode;else i=document.querySelectorAll("#"+d.target+" "+g);b=0;for(h=i.length;b<h;b++)i[b].classList.toggle(k)})};p.compose("applyclass",{manifest:{about:{name:"Popcorn applyclass Effect",version:"0.1",author:"@scottdowne",website:"scottdowne.wordpress.com"},options:{}},_setup:function(l){l.classes={};l.applyclass=l.applyclass||"";for(var d=l.applyclass.replace(/\s/g,
+"").split(","),b=[],h=0,i=d.length;h<i;h++){b=d[h].split(":");if(b[0])l.classes[b[0]]=b[1]||""}},start:e,end:e})})(Popcorn);(function(p){function e(d,b){if(d.map)d.map.div.style.display=b;else setTimeout(function(){e(d,b)},10)}var l=1;p.plugin("openmap",function(d){var b,h,i,g,k,r,m,t,q=document.getElementById(d.target);b=document.createElement("div");b.id="openmapdiv"+l;b.style.width="100%";b.style.height="100%";l++;q&&q.appendChild(b);t=function(){if(window.OpenLayers&&window.OpenLayers.Layer.Stamen){if(d.location){location=new OpenLayers.LonLat(0,0);p.getJSONP("//tinygeocoder.com/create-api.php?q="+d.location+"&callback=jsonp",
+function(u){h=new OpenLayers.LonLat(u[1],u[0])})}else h=new OpenLayers.LonLat(d.lng,d.lat);d.type=d.type||"ROADMAP";switch(d.type){case "SATELLITE":d.map=new OpenLayers.Map({div:b,maxResolution:0.28125,tileSize:new OpenLayers.Size(512,512)});var o=new OpenLayers.Layer.WorldWind("LANDSAT","//worldwind25.arc.nasa.gov/tile/tile.aspx",2.25,4,{T:"105"});d.map.addLayer(o);g=new OpenLayers.Projection("EPSG:4326");i=new OpenLayers.Projection("EPSG:4326");break;case "TERRAIN":g=new OpenLayers.Projection("EPSG:4326");
+i=new OpenLayers.Projection("EPSG:4326");d.map=new OpenLayers.Map({div:b,projection:i});o=new OpenLayers.Layer.WMS("USGS Terraserver","//terraserver-usa.org/ogcmap.ashx?",{layers:"DRG"});d.map.addLayer(o);break;case "STAMEN-TONER":case "STAMEN-WATERCOLOR":case "STAMEN-TERRAIN":o=d.type.replace("STAMEN-","").toLowerCase();o=new OpenLayers.Layer.Stamen(o);g=new OpenLayers.Projection("EPSG:4326");i=new OpenLayers.Projection("EPSG:900913");h=h.transform(g,i);d.map=new OpenLayers.Map({div:b,projection:i,
+displayProjection:g,controls:[new OpenLayers.Control.Navigation,new OpenLayers.Control.PanPanel,new OpenLayers.Control.ZoomPanel]});d.map.addLayer(o);break;default:i=new OpenLayers.Projection("EPSG:900913");g=new OpenLayers.Projection("EPSG:4326");h=h.transform(g,i);d.map=new OpenLayers.Map({div:b,projection:i,displayProjection:g});o=new OpenLayers.Layer.OSM;d.map.addLayer(o)}if(d.map){d.map.setCenter(h,d.zoom||10);d.map.div.style.display="none"}}else setTimeout(function(){t()},50)};t();return{_setup:function(o){window.OpenLayers||
+p.getScript("//openlayers.org/api/OpenLayers.js",function(){p.getScript("//maps.stamen.com/js/tile.stamen.js")});var u=function(){if(o.map){o.zoom=o.zoom||2;if(o.zoom&&typeof o.zoom!=="number")o.zoom=+o.zoom;o.map.setCenter(h,o.zoom);if(o.markers){var E=OpenLayers.Util.extend({},OpenLayers.Feature.Vector.style["default"]),C=function(j){clickedFeature=j.feature;if(clickedFeature.attributes.text){m=new OpenLayers.Popup.FramedCloud("featurePopup",clickedFeature.geometry.getBounds().getCenterLonLat(),
+new OpenLayers.Size(120,250),clickedFeature.attributes.text,null,true,function(){r.unselect(this.feature)});clickedFeature.popup=m;m.feature=clickedFeature;o.map.addPopup(m)}},f=function(j){feature=j.feature;if(feature.popup){m.feature=null;o.map.removePopup(feature.popup);feature.popup.destroy();feature.popup=null}},G=function(j){p.getJSONP("//tinygeocoder.com/create-api.php?q="+j.location+"&callback=jsonp",function(w){w=(new OpenLayers.Geometry.Point(w[1],w[0])).transform(g,i);var x=OpenLayers.Util.extend({},
+E);if(!j.size||isNaN(j.size))j.size=14;x.pointRadius=j.size;x.graphicOpacity=1;x.externalGraphic=j.icon;w=new OpenLayers.Feature.Vector(w,null,x);if(j.text)w.attributes={text:j.text};k.addFeatures([w])})};k=new OpenLayers.Layer.Vector("Point Layer",{style:E});o.map.addLayer(k);for(var A=0,O=o.markers.length;A<O;A++){var a=o.markers[A];if(a.text)if(!r){r=new OpenLayers.Control.SelectFeature(k);o.map.addControl(r);r.activate();k.events.on({featureselected:C,featureunselected:f})}if(a.location)G(a);
+else{var c=(new OpenLayers.Geometry.Point(a.lng,a.lat)).transform(g,i),n=OpenLayers.Util.extend({},E);if(!a.size||isNaN(a.size))a.size=14;n.pointRadius=a.size;n.graphicOpacity=1;n.externalGraphic=a.icon;c=new OpenLayers.Feature.Vector(c,null,n);if(a.text)c.attributes={text:a.text};k.addFeatures([c])}}}}else setTimeout(function(){u()},13)};u()},start:function(o,u){e(u,"block")},end:function(o,u){e(u,"none")},_teardown:function(){q&&q.removeChild(b);b=map=h=i=g=k=r=m=null}}},{about:{name:"Popcorn OpenMap Plugin",
version:"0.3",author:"@mapmeld",website:"mapadelsur.blogspot.com"},options:{start:{elem:"input",type:"number",label:"Start"},end:{elem:"input",type:"number",label:"End"},target:"map-container",type:{elem:"select",options:["ROADMAP","SATELLITE","TERRAIN"],label:"Map Type",optional:true},zoom:{elem:"input",type:"number",label:"Zoom","default":2},lat:{elem:"input",type:"text",label:"Lat",optional:true},lng:{elem:"input",type:"text",label:"Lng",optional:true},location:{elem:"input",type:"text",label:"Location",
-"default":"Toronto, Ontario, Canada"},markers:{elem:"input",type:"text",label:"List Markers",optional:true}}})})(Popcorn);document.addEventListener("click",function(r){r=r.target;if(r.nodeName==="A"||r.parentNode&&r.parentNode.nodeName==="A")Popcorn.instances.forEach(function(f){f.options.pauseOnLinkClicked&&f.pause()})},false);(function(r){var f={},n=0,c=document.createElement("span"),b=["webkit","Moz","ms","O",""],e=["Transform","TransitionDuration","TransitionTimingFunction"],h={},i;document.getElementsByTagName("head")[0].appendChild(c);for(var j=0,p=e.length;j<p;j++)for(var m=0,o=b.length;m<o;m++){i=b[m]+e[j];if(i in c.style){h[e[j].toLowerCase()]=i;break}}document.getElementsByTagName("head")[0].appendChild(c);r.plugin("wordriver",{manifest:{about:{name:"Popcorn WordRiver Plugin"},options:{start:{elem:"input",type:"number",
-label:"Start"},end:{elem:"input",type:"number",label:"End"},target:"wordriver-container",text:{elem:"input",type:"text",label:"Text","default":"Popcorn.js"},color:{elem:"input",type:"text",label:"Color","default":"Green",optional:true}}},_setup:function(q){q._duration=q.end-q.start;var s;if(!(s=f[q.target])){s=q.target;f[s]=document.createElement("div");var d=document.getElementById(s);d&&d.appendChild(f[s]);f[s].style.height="100%";f[s].style.position="relative";s=f[s]}q._container=s;q.word=document.createElement("span");
-q.word.style.position="absolute";q.word.style.whiteSpace="nowrap";q.word.style.opacity=0;q.word.style.MozTransitionProperty="opacity, -moz-transform";q.word.style.webkitTransitionProperty="opacity, -webkit-transform";q.word.style.OTransitionProperty="opacity, -o-transform";q.word.style.transitionProperty="opacity, transform";q.word.style[h.transitionduration]="1s, "+q._duration+"s";q.word.style[h.transitiontimingfunction]="linear";q.word.innerHTML=q.text;q.word.style.color=q.color||"black"},start:function(q,
-s){s._container.appendChild(s.word);s.word.style[h.transform]="";s.word.style.fontSize=~~(30+20*Math.random())+"px";n%=s._container.offsetWidth-s.word.offsetWidth;s.word.style.left=n+"px";n+=s.word.offsetWidth+10;s.word.style[h.transform]="translateY("+(s._container.offsetHeight-s.word.offsetHeight)+"px)";s.word.style.opacity=1;setTimeout(function(){s.word.style.opacity=0},(s.end-s.start-1||1)*1E3)},end:function(q,s){s.word.style.opacity=0},_teardown:function(q){var s=document.getElementById(q.target);
-q.word.parentNode&&q._container.removeChild(q.word);f[q.target]&&!f[q.target].childElementCount&&s&&s.removeChild(f[q.target])&&delete f[q.target]}})})(Popcorn);(function(r){var f=1;r.plugin("timeline",function(n){var c=document.getElementById(n.target),b=document.createElement("div"),e,h=true;if(c&&!c.firstChild){c.appendChild(e=document.createElement("div"));e.style.width="inherit";e.style.height="inherit";e.style.overflow="auto"}else e=c.firstChild;b.style.display="none";b.id="timelineDiv"+f;n.direction=n.direction||"up";if(n.direction.toLowerCase()==="down")h=false;if(c&&e)h?e.insertBefore(b,e.firstChild):e.appendChild(b);f++;b.innerHTML="<p><span id='big' style='font-size:24px; line-height: 130%;' >"+
-n.title+"</span><br /><span id='mid' style='font-size: 16px;'>"+n.text+"</span><br />"+n.innerHTML;return{start:function(i,j){b.style.display="block";if(j.direction==="down")e.scrollTop=e.scrollHeight},end:function(){b.style.display="none"},_teardown:function(){e&&b&&e.removeChild(b)&&!e.firstChild&&c.removeChild(e)}}},{about:{name:"Popcorn Timeline Plugin",version:"0.1",author:"David Seifried @dcseifried",website:"dseifried.wordpress.com"},options:{start:{elem:"input",type:"number",label:"Start"},
-end:{elem:"input",type:"number",label:"End"},target:"feed-container",title:{elem:"input",type:"text",label:"Title"},text:{elem:"input",type:"text",label:"Text"},innerHTML:{elem:"input",type:"text",label:"HTML Code",optional:true},direction:{elem:"select",options:["DOWN","UP"],label:"Direction",optional:true}}})})(Popcorn);(function(r,f){var n={};r.plugin("documentcloud",{manifest:{about:{name:"Popcorn Document Cloud Plugin",version:"0.1",author:"@humphd, @ChrisDeCairos",website:"http://vocamus.net/dave"},options:{start:{elem:"input",type:"number",label:"Start"},end:{elem:"input",type:"number",label:"End"},target:"documentcloud-container",width:{elem:"input",type:"text",label:"Width",optional:true},height:{elem:"input",type:"text",label:"Height",optional:true},src:{elem:"input",type:"url",label:"PDF URL","default":"http://www.documentcloud.org/documents/70050-urbina-day-1-in-progress.html"},
-preload:{elem:"input",type:"checkbox",label:"Preload","default":true},page:{elem:"input",type:"number",label:"Page Number",optional:true},aid:{elem:"input",type:"number",label:"Annotation Id",optional:true}}},_setup:function(c){function b(){function m(v){c._key=v.api.getId();c._changeView=function(z){c.aid?z.pageSet.showAnnotation(z.api.getAnnotation(c.aid)):z.api.setCurrentPage(c.page)}}function o(){n[c._key]={num:1,id:c._containerId};h.loaded=true}h.loaded=false;var q=c.url.replace(/\.html$/,".js"),
-s=c.target,d=f.getElementById(s),A=f.createElement("div"),y=r.position(d),x=c.width||y.width;y=c.height||y.height;var a=c.sidebar||true,g=c.text||true,l=c.pdf||true,k=c.showAnnotations||true,t=c.zoom||700,u=c.search||true;if(!function(v){var z=false;r.forEach(h.viewers,function(C){if(C.api.getSchema().canonicalURL===v){m(C);C=n[c._key];c._containerId=C.id;C.num+=1;z=true;h.loaded=true}});return z}(c.url)){A.id=c._containerId=r.guid(s);s="#"+A.id;d.appendChild(A);i.trigger("documentready");h.load(q,
-{width:x,height:y,sidebar:a,text:g,pdf:l,showAnnotations:k,zoom:t,search:u,container:s,afterLoad:c.page||c.aid?function(v){m(v);c._changeView(v);A.style.visibility="hidden";v.elements.pages.hide();o()}:function(v){m(v);o();A.style.visibility="hidden";v.elements.pages.hide()}})}}function e(){window.DV.loaded?b():setTimeout(e,25)}var h=window.DV=window.DV||{},i=this;if(h.loading)e();else{h.loading=true;h.recordHit="//www.documentcloud.org/pixel.gif";var j=f.createElement("link"),p=f.getElementsByTagName("head")[0];
-j.rel="stylesheet";j.type="text/css";j.media="screen";j.href="//s3.documentcloud.org/viewer/viewer-datauri.css";p.appendChild(j);h.loaded=false;r.getScript("http://s3.documentcloud.org/viewer/viewer.js",function(){h.loading=false;b()})}},start:function(c,b){var e=f.getElementById(b._containerId),h=DV.viewers[b._key];(b.page||b.aid)&&h&&b._changeView(h);if(e&&h){e.style.visibility="visible";h.elements.pages.show()}},end:function(c,b){var e=f.getElementById(b._containerId);if(e&&DV.viewers[b._key]){e.style.visibility=
-"hidden";DV.viewers[b._key].elements.pages.hide()}},_teardown:function(c){var b=f.getElementById(c._containerId);if((c=c._key)&&DV.viewers[c]&&--n[c].num===0){for(DV.viewers[c].api.unload();b.hasChildNodes();)b.removeChild(b.lastChild);b.parentNode.removeChild(b)}}})})(Popcorn,window.document);(function(r){r.parser("parseJSON","JSON",function(f){var n={title:"",remote:"",data:[]};r.forEach(f.data,function(c){n.data.push(c)});return n})})(Popcorn);(function(r){r.parser("parseSBV",function(f){var n={title:"",remote:"",data:[]},c=[],b=0,e=0,h=function(q){q=q.split(":");var s=q.length-1,d;try{d=parseInt(q[s-1],10)*60+parseFloat(q[s],10);if(s===2)d+=parseInt(q[0],10)*3600}catch(A){throw"Bad cue";}return d},i=function(q,s){var d={};d[q]=s;return d};f=f.text.split(/(?:\r\n|\r|\n)/gm);for(e=f.length;b<e;){var j={},p=[],m=f[b++].split(",");try{j.start=h(m[0]);for(j.end=h(m[1]);b<e&&f[b];)p.push(f[b++]);j.text=p.join("<br />");c.push(i("subtitle",j))}catch(o){for(;b<
-e&&f[b];)b++}for(;b<e&&!f[b];)b++}n.data=c;return n})})(Popcorn);(function(r){function f(c,b){var e={};e[c]=b;return e}function n(c){c=c.split(":");try{var b=c[2].split(",");if(b.length===1)b=c[2].split(".");return parseFloat(c[0],10)*3600+parseFloat(c[1],10)*60+parseFloat(b[0],10)+parseFloat(b[1],10)/1E3}catch(e){return 0}}r.parser("parseSRT",function(c){var b={title:"",remote:"",data:[]},e=[],h=0,i=0,j,p,m,o;c=c.text.split(/(?:\r\n|\r|\n)/gm);for(h=c.length-1;h>=0&&!c[h];)h--;m=h+1;for(h=0;h<m;h++){o={};p=[];o.id=parseInt(c[h++],10);j=c[h++].split(/[\t ]*--\>[\t ]*/);
-o.start=n(j[0]);i=j[1].indexOf(" ");if(i!==-1)j[1]=j[1].substr(0,i);for(o.end=n(j[1]);h<m&&c[h];)p.push(c[h++]);o.text=p.join("\\N").replace(/\{(\\[\w]+\(?([\w\d]+,?)+\)?)+\}/gi,"");o.text=o.text.replace(/</g,"<").replace(/>/g,">");o.text=o.text.replace(/<(\/?(font|b|u|i|s))((\s+(\w|\w[\w\-]*\w)(\s*=\s*(?:\".*?\"|'.*?'|[^'\">\s]+))?)+\s*|\s*)(\/?)>/gi,"<$1$3$7>");o.text=o.text.replace(/\\N/gi,"<br />");e.push(f("subtitle",o))}b.data=e;return b})})(Popcorn);(function(r){function f(b,e){var h=b.substr(10).split(","),i;i={start:n(h[e.start]),end:n(h[e.end])};if(i.start===-1||i.end===-1)throw"Invalid time";var j=q.call(m,/\{(\\[\w]+\(?([\w\d]+,?)+\)?)+\}/gi,""),p=j.replace,m;m=h.length;q=[];for(var o=e.text;o<m;o++)q.push(h[o]);m=q.join(",");var q=m.replace;i.text=p.call(j,/\\N/gi,"<br />");return i}function n(b){var e=b.split(":");if(b.length!==10||e.length<3)return-1;return parseInt(e[0],10)*3600+parseInt(e[1],10)*60+parseFloat(e[2],10)}function c(b,
-e){var h={};h[b]=e;return h}r.parser("parseSSA",function(b){var e={title:"",remote:"",data:[]},h=[],i=0,j;b=b.text.split(/(?:\r\n|\r|\n)/gm);for(j=b.length;i<j&&b[i]!=="[Events]";)i++;var p=b[++i].substr(8).split(", "),m={},o,q;q=0;for(o=p.length;q<o;q++)if(p[q]==="Start")m.start=q;else if(p[q]==="End")m.end=q;else if(p[q]==="Text")m.text=q;for(;++i<j&&b[i]&&b[i][0]!=="[";)try{h.push(c("subtitle",f(b[i],m)))}catch(s){}e.data=h;return e})})(Popcorn);(function(r){function f(i,j,p){var m=i.firstChild;i=n(i,p);p=[];for(var o;m;){if(m.nodeType===1)if(m.nodeName==="p")p.push(c(m,j,i));else if(m.nodeName==="div"){o=b(m.getAttribute("begin"));if(o<0)o=j;p.push.apply(p,f(m,o,i))}m=m.nextSibling}return p}function n(i,j){var p=i.getAttribute("region");return p!==null?p:j||""}function c(i,j,p){var m={};m.text=(i.textContent||i.text).replace(e,"").replace(h,"<br />");m.id=i.getAttribute("xml:id")||i.getAttribute("id");m.start=b(i.getAttribute("begin"),j);
-m.end=b(i.getAttribute("end"),j);m.target=n(i,p);if(m.end<0){m.end=b(i.getAttribute("duration"),0);if(m.end>=0)m.end+=m.start;else m.end=Number.MAX_VALUE}return{subtitle:m}}function b(i,j){var p;if(!i)return-1;try{return r.util.toSeconds(i)}catch(m){for(var o=i.length-1;o>=0&&i[o]<="9"&&i[o]>="0";)o--;p=o;o=parseFloat(i.substring(0,p));p=i.substring(p);return o*({h:3600,m:60,s:1,ms:0.0010}[p]||-1)+(j||0)}}var e=/^[\s]+|[\s]+$/gm,h=/(?:\r\n|\r|\n)/gm;r.parser("parseTTML",function(i){var j={title:"",
-remote:"",data:[]};if(!i.xml||!i.xml.documentElement)return j;i=i.xml.documentElement.firstChild;if(!i)return j;for(;i.nodeName!=="body";)i=i.nextSibling;if(i)j.data=f(i,0);return j})})(Popcorn);(function(r){r.parser("parseTTXT",function(f){var n={title:"",remote:"",data:[]},c=function(j){j=j.split(":");var p=0;try{return parseFloat(j[0],10)*60*60+parseFloat(j[1],10)*60+parseFloat(j[2],10)}catch(m){p=0}return p},b=function(j,p){var m={};m[j]=p;return m};f=f.xml.lastChild.lastChild;for(var e=Number.MAX_VALUE,h=[];f;){if(f.nodeType===1&&f.nodeName==="TextSample"){var i={};i.start=c(f.getAttribute("sampleTime"));i.text=f.getAttribute("text");if(i.text){i.end=e-0.0010;h.push(b("subtitle",i))}e=
-i.start}f=f.previousSibling}n.data=h.reverse();return n})})(Popcorn);(function(r){function f(c){var b=c.split(":");c=c.length;var e;if(c!==12&&c!==9)throw"Bad cue";c=b.length-1;try{e=parseInt(b[c-1],10)*60+parseFloat(b[c],10);if(c===2)e+=parseInt(b[0],10)*3600}catch(h){throw"Bad cue";}return e}function n(c,b){var e={};e[c]=b;return e}r.parser("parseVTT",function(c){var b={title:"",remote:"",data:[]},e=[],h=0,i=0,j,p;c=c.text.split(/(?:\r\n|\r|\n)/gm);i=c.length;if(i===0||c[0]!=="WEBVTT")return b;for(h++;h<i;){j=[];try{for(var m=h;m<i&&!c[m];)m++;h=m;var o=c[h++];m=
-void 0;var q={};if(!o||o.indexOf("--\>")===-1)throw"Bad cue";m=o.replace(/--\>/," --\> ").split(/[\t ]+/);if(m.length<2)throw"Bad cue";q.id=o;q.start=f(m[0]);q.end=f(m[2]);for(p=q;h<i&&c[h];)j.push(c[h++]);p.text=j.join("<br />");e.push(n("subtitle",p))}catch(s){for(h=h;h<i&&c[h];)h++;h=h}}b.data=e;return b})})(Popcorn);(function(r){r.parser("parseXML","XML",function(f){var n={title:"",remote:"",data:[]},c={},b=function(m){m=m.split(":");if(m.length===1)return parseFloat(m[0],10);else if(m.length===2)return parseFloat(m[0],10)+parseFloat(m[1]/12,10);else if(m.length===3)return parseInt(m[0]*60,10)+parseFloat(m[1],10)+parseFloat(m[2]/12,10);else if(m.length===4)return parseInt(m[0]*3600,10)+parseInt(m[1]*60,10)+parseFloat(m[2],10)+parseFloat(m[3]/12,10)},e=function(m){for(var o={},q=0,s=m.length;q<s;q++){var d=m.item(q).nodeName,
-A=m.item(q).nodeValue,y=c[A];if(d==="in")o.start=b(A);else if(d==="out")o.end=b(A);else if(d==="resourceid")for(var x in y){if(y.hasOwnProperty(x))if(!o[x]&&x!=="id")o[x]=y[x]}else o[d]=A}return o},h=function(m,o){var q={};q[m]=o;return q},i=function(m,o,q){var s={};r.extend(s,o,e(m.attributes),{text:m.textContent||m.text});o=m.childNodes;if(o.length<1||o.length===1&&o[0].nodeType===3)if(q)c[s.id]=s;else n.data.push(h(m.nodeName,s));else for(m=0;m<o.length;m++)o[m].nodeType===1&&i(o[m],s,q)};f=f.documentElement.childNodes;
-for(var j=0,p=f.length;j<p;j++)if(f[j].nodeType===1)f[j].nodeName==="manifest"?i(f[j],{},true):i(f[j],{},false);return n})})(Popcorn);(function(){var r=false,f=false;Popcorn.player("soundcloud",{_canPlayType:function(n,c){return/(?:http:\/\/www\.|http:\/\/|www\.|\.|^)(soundcloud)/.test(c)&&n.toLowerCase()!=="video"},_setup:function(n){function c(){r=true;SC.initialize({client_id:"PRaNFlda6Bhf5utPjUsptg"});SC.get("/resolve",{url:e.src},function(A){e.width=e.style.width?""+e.offsetWidth:"560";e.height=e.style.height?""+e.offsetHeight:"315";h.scrolling="no";h.frameborder="no";h.id="soundcloud-"+Popcorn.guid();h.src="http://w.soundcloud.com/player/?url="+
-A.uri+"&show_artwork=false&buying=false&liking=false&sharing=false";h.width="100%";h.height="100%";n.loadListener=function(){n.widget=o=SC.Widget(h.id);o.bind(SC.Widget.Events.FINISH,function(){e.pause();e.dispatchEvent("ended")});o.bind(SC.Widget.Events.PLAY_PROGRESS,function(y){j=y.currentPosition/1E3;e.dispatchEvent("timeupdate")});o.bind(SC.Widget.Events.PLAY,function(){p=m=false;e.dispatchEvent("play");e.dispatchEvent("playing");e.currentTime=j;d.next()});o.bind(SC.Widget.Events.PAUSE,function(){p=
-m=true;e.dispatchEvent("pause");d.next()});o.bind(SC.Widget.Events.READY,function(){o.getDuration(function(y){q=y/1E3;e.style.visibility="visible";e.dispatchEvent("durationchange");e.readyState=4;e.dispatchEvent("readystatechange");e.dispatchEvent("loadedmetadata");e.dispatchEvent("loadeddata");e.dispatchEvent("canplaythrough");e.dispatchEvent("load");!e.paused&&e.play()});o.getVolume(function(y){i=y/100})})};h.addEventListener("load",n.loadListener,false);e.appendChild(h)})}function b(){if(f)(function A(){setTimeout(function(){r?
-c():A()},100)})();else{f=true;Popcorn.getScript("http://w.soundcloud.com/player/api.js",function(){Popcorn.getScript("http://connect.soundcloud.com/sdk.js",function(){c()})})}}var e=this,h=document.createElement("iframe"),i=1,j=0,p=true,m=true,o,q=0,s=false,d=Popcorn.player.playerQueue();n._container=h;e.style.visibility="hidden";e.play=function(){p=false;d.add(function(){if(m)o&&o.play();else d.next()})};e.pause=function(){p=true;d.add(function(){if(m)d.next();else o&&o.pause()})};Object.defineProperties(e,
-{muted:{set:function(A){if(A){o&&o.getVolume(function(y){i=y/100});o&&o.setVolume(0);s=true}else{o&&o.setVolume(i*100);s=false}e.dispatchEvent("volumechange")},get:function(){return s}},volume:{set:function(A){o&&o.setVolume(A*100);i=A;e.dispatchEvent("volumechange")},get:function(){return s?0:i}},currentTime:{set:function(A){j=A;o&&o.seekTo(A*1E3);e.dispatchEvent("seeked");e.dispatchEvent("timeupdate")},get:function(){return j}},duration:{get:function(){return q}},paused:{get:function(){return p}}});
-r?c():b()},_teardown:function(n){var c=n.widget,b=SC.Widget.Events,e=n._container;n.destroyed=true;if(c)for(var h in b)c&&c.unbind(b[h]);else e.removeEventListener("load",n.loadEventListener,false)}})})();(function(){function r(n){var c=r.options;n=c.parser[c.strictMode?"strict":"loose"].exec(n);for(var b={},e=14;e--;)b[c.key[e]]=n[e]||"";b[c.q.name]={};b[c.key[12]].replace(c.q.parser,function(h,i,j){if(i)b[c.q.name][i]=j});return b}function f(n,c){return/player.vimeo.com\/video\/\d+/.test(c)||/vimeo.com\/\d+/.test(c)}r.options={strictMode:false,key:["source","protocol","authority","userInfo","user","password","host","port","relative","path","directory","file","query","anchor"],q:{name:"queryKey",
-parser:/(?:^|&)([^&=]*)=?([^&]*)/g},parser:{strict:/^(?:([^:\/?#]+):)?(?:\/\/((?:(([^:@]*)(?::([^:@]*))?)?@)?([^:\/?#]*)(?::(\d*))?))?((((?:[^?#\/]*\/)*)([^?#]*))(?:\?([^#]*))?(?:#(.*))?)/,loose:/^(?:(?![^:@]+:[^:@\/]*@)([^:\/?#.]+):)?(?:\/\/)?((?:(([^:@]*)(?::([^:@]*))?)?@)?([^:\/?#]*)(?::(\d*))?)(((\/(?:[^?#](?![^?#\/]*\.[^?#\/.]+(?:[?#]|$)))*\/?)?([^?#\/]*))(?:\?([^#]*))?(?:#(.*))?)/}};Popcorn.player("vimeo",{_canPlayType:f,_setup:function(n){function c(l,k){var t=y.src.split("?")[0],u=JSON.stringify({method:l,
-value:k});if(t.substr(0,2)==="//")t=window.location.protocol+t;y.contentWindow?y.contentWindow.postMessage(u,t):o.unload()}function b(l){if(l.origin==="http://player.vimeo.com"){var k;try{k=JSON.parse(l.data)}catch(t){console.warn(t)}if(k.player_id==m){k.method&&a[k.method]&&a[k.method](k);k.event&&g[k.event]&&g[k.event](k)}}}function e(){d||(d=setInterval(function(){o.dispatchEvent("timeupdate")},i));s||(s=setInterval(function(){c("getCurrentTime")},j))}function h(){if(d){clearInterval(d);d=0}if(s){clearInterval(s);
-s=0}}var i=250,j=16,p={MEDIA_ERR_ABORTED:1,MEDIA_ERR_NETWORK:2,MEDIA_ERR_DECODE:3,MEDIA_ERR_SRC_NOT_SUPPORTED:4},m,o=this,q={q:[],queue:function(l){this.q.push(l);this.process()},process:function(){if(A)for(;this.q.length;)this.q.shift()()}},s,d,A,y=document.createElement("iframe"),x={error:null,src:o.src,NETWORK_EMPTY:0,NETWORK_IDLE:1,NETWORK_LOADING:2,NETWORK_NO_SOURCE:3,networkState:0,HAVE_NOTHING:0,HAVE_METADATA:1,HAVE_CURRENT_DATA:2,HAVE_FUTURE_DATA:3,HAVE_ENOUGH_DATA:4,readyState:0,seeking:false,
-currentTime:0,duration:NaN,paused:true,ended:false,autoplay:false,loop:false,volume:1,muted:false,width:0,height:0};Popcorn.forEach("error networkState readyState seeking duration paused ended".split(" "),function(l){Object.defineProperty(o,l,{get:function(){return x[l]}})});Object.defineProperties(o,{src:{get:function(){return x.src},set:function(l){x.src=l;o.load()}},currentTime:{get:function(){return x.currentTime},set:function(l){q.queue(function(){c("seekTo",l)});x.seeking=true;o.dispatchEvent("seeking")}},
-autoplay:{get:function(){return x.autoplay},set:function(l){x.autoplay=!!l}},loop:{get:function(){return x.loop},set:function(l){x.loop=!!l;q.queue(function(){c("setLoop",loop)})}},volume:{get:function(){return x.volume},set:function(l){x.volume=l;q.queue(function(){c("setVolume",x.muted?0:x.volume)});o.dispatchEvent("volumechange")}},muted:{get:function(){return x.muted},set:function(l){x.muted=!!l;q.queue(function(){c("setVolume",x.muted?0:x.volume)});o.dispatchEvent("volumechange")}},width:{get:function(){return y.width},
-set:function(l){y.width=l}},height:{get:function(){return y.height},set:function(l){y.height=l}}});var a={getCurrentTime:function(l){x.currentTime=parseFloat(l.value)},getDuration:function(l){x.duration=parseFloat(l.value);if(!isNaN(x.duration)){x.readyState=4;o.dispatchEvent("durationchange");o.dispatchEvent("loadedmetadata");o.dispatchEvent("loadeddata");o.dispatchEvent("canplay");o.dispatchEvent("canplaythrough")}},getVolume:function(l){x.volume=parseFloat(l.value)}},g={ready:function(){c("addEventListener",
-"loadProgress");c("addEventListener","playProgress");c("addEventListener","play");c("addEventListener","pause");c("addEventListener","finish");c("addEventListener","seek");c("getDuration");A=true;q.process();o.dispatchEvent("loadstart")},loadProgress:function(l){o.dispatchEvent("progress");x.duration=parseFloat(l.data.duration)},playProgress:function(l){x.currentTime=parseFloat(l.data.seconds)},play:function(){if(x.seeking){x.seeking=false;o.dispatchEvent("seeked")}x.paused=false;x.ended=false;e();
-o.dispatchEvent("play")},pause:function(){x.paused=true;h();o.dispatchEvent("pause")},finish:function(){x.ended=true;h();o.dispatchEvent("ended")},seek:function(l){x.currentTime=parseFloat(l.data.seconds);x.seeking=false;x.ended=false;o.dispatchEvent("timeupdate");o.dispatchEvent("seeked")}};o.load=function(){A=false;m=Popcorn.guid();var l=r(x.src),k={},t=[],u={api:1,player_id:m};if(f(o.nodeName,l.source)){Popcorn.extend(k,n);Popcorn.extend(k,l.queryKey);Popcorn.extend(k,u);l="http://player.vimeo.com/video/"+
-/\d+$/.exec(l.path)+"?";for(var v in k)k.hasOwnProperty(v)&&t.push(encodeURIComponent(v)+"="+encodeURIComponent(k[v]));l+=t.join("&");x.loop=!!l.match(/loop=1/);x.autoplay=!!l.match(/autoplay=1/);y.width=o.style.width?o.style.width:500;y.height=o.style.height?o.style.height:281;y.frameBorder=0;y.webkitAllowFullScreen=true;y.mozAllowFullScreen=true;y.allowFullScreen=true;y.src=l;o.appendChild(y)}else{l=x.MEDIA_ERR_SRC_NOT_SUPPORTED;x.error={};Popcorn.extend(x.error,p);x.error.code=l;o.dispatchEvent("error")}};
-o.unload=function(){h();window.removeEventListener("message",b,false)};o.play=function(){q.queue(function(){c("play")})};o.pause=function(){q.queue(function(){c("pause")})};setTimeout(function(){window.addEventListener("message",b,false);o.load()},0)},_teardown:function(){this.unload&&this.unload()}})})();(function(r,f){r.onYouTubePlayerAPIReady=function(){onYouTubePlayerAPIReady.ready=true;for(var c=0;c<onYouTubePlayerAPIReady.waiting.length;c++)onYouTubePlayerAPIReady.waiting[c]()};if(r.YT){r.quarantineYT=r.YT;r.YT=null}onYouTubePlayerAPIReady.waiting=[];var n=false;f.player("youtube",{_canPlayType:function(c,b){return typeof b==="string"&&/(?:http:\/\/www\.|http:\/\/|www\.|\.|^)(youtu)/.test(b)&&c.toLowerCase()!=="video"},_setup:function(c){if(!r.YT&&!n){n=true;f.getScript("//youtube.com/player_api")}var b=
-this,e=false,h=document.createElement("div"),i=0,j=true,p=false,m=0,o=false,q=100,s=f.player.playerQueue(),d=function(){f.player.defineProperty(b,"currentTime",{set:function(y){if(!c.destroyed){p=true;i=Math.round(+y*100)/100}},get:function(){return i}});f.player.defineProperty(b,"paused",{get:function(){return j}});f.player.defineProperty(b,"muted",{set:function(y){if(c.destroyed)return y;if(c.youtubeObject.isMuted()!==y){y?c.youtubeObject.mute():c.youtubeObject.unMute();o=c.youtubeObject.isMuted();
-b.dispatchEvent("volumechange")}return c.youtubeObject.isMuted()},get:function(){if(c.destroyed)return 0;return c.youtubeObject.isMuted()}});f.player.defineProperty(b,"volume",{set:function(y){if(c.destroyed)return y;if(c.youtubeObject.getVolume()/100!==y){c.youtubeObject.setVolume(y*100);q=c.youtubeObject.getVolume();b.dispatchEvent("volumechange")}return c.youtubeObject.getVolume()/100},get:function(){if(c.destroyed)return 0;return c.youtubeObject.getVolume()/100}});b.play=function(){if(!c.destroyed){j=
-false;s.add(function(){if(c.youtubeObject.getPlayerState()!==1){p=false;c.youtubeObject.playVideo()}else s.next()})}};b.pause=function(){if(!c.destroyed){j=true;s.add(function(){c.youtubeObject.getPlayerState()!==2?c.youtubeObject.pauseVideo():s.next()})}}};h.id=b.id+f.guid();c._container=h;b.appendChild(h);var A=function(){var y,x,a,g,l=true,k=function(){if(!c.destroyed){if(p)if(i===c.youtubeObject.getCurrentTime()){p=false;b.dispatchEvent("seeked");b.dispatchEvent("timeupdate")}else c.youtubeObject.seekTo(i);
-else{i=c.youtubeObject.getCurrentTime();b.dispatchEvent("timeupdate")}setTimeout(k,250)}},t=function(z){var C=c.youtubeObject.getDuration();if(isNaN(C)||C===0)setTimeout(function(){t(z*2)},z*1E3);else{b.duration=C;b.dispatchEvent("durationchange");b.dispatchEvent("loadedmetadata");b.dispatchEvent("loadeddata");b.readyState=4;k();b.dispatchEvent("canplaythrough")}};c.controls=+c.controls===0||+c.controls===1?c.controls:1;c.annotations=+c.annotations===1||+c.annotations===3?c.annotations:1;y=/^.*(?:\/|v=)(.{11})/.exec(b.src)[1];
-x=(b.src.split("?")[1]||"").replace(/v=.{11}/,"");x=x.replace(/&t=(?:(\d+)m)?(?:(\d+)s)?/,function(z,C,E){C|=0;E|=0;m=+E+C*60;return""});x=x.replace(/&start=(\d+)?/,function(z,C){C|=0;m=C;return""});e=/autoplay=1/.test(x);x=x.split(/[\&\?]/g);a={wmode:"transparent"};for(var u=0;u<x.length;u++){g=x[u].split("=");a[g[0]]=g[1]}c.youtubeObject=new YT.Player(h.id,{height:"100%",width:"100%",wmode:"transparent",playerVars:a,videoId:y,events:{onReady:function(){q=b.volume;o=b.muted;v();j=b.paused;d();c.youtubeObject.playVideo();
-b.currentTime=m},onStateChange:function(z){if(!(c.destroyed||z.data===-1))if(z.data===2){j=true;b.dispatchEvent("pause");s.next()}else if(z.data===1&&!l){j=false;b.dispatchEvent("play");b.dispatchEvent("playing");s.next()}else if(z.data===0)b.dispatchEvent("ended");else if(z.data===1&&l){l=false;if(e||!b.paused)j=false;j&&c.youtubeObject.pauseVideo();t(0.025)}},onError:function(z){if([2,100,101,150].indexOf(z.data)!==-1){b.error={customCode:z.data};b.dispatchEvent("error")}}}});var v=function(){if(!c.destroyed){if(o!==
-c.youtubeObject.isMuted()){o=c.youtubeObject.isMuted();b.dispatchEvent("volumechange")}if(q!==c.youtubeObject.getVolume()){q=c.youtubeObject.getVolume();b.dispatchEvent("volumechange")}setTimeout(v,250)}}};onYouTubePlayerAPIReady.ready?A():onYouTubePlayerAPIReady.waiting.push(A)},_teardown:function(c){c.destroyed=true;var b=c.youtubeObject;if(b){b.stopVideo();b.clearVideo&&b.clearVideo()}this.removeChild(document.getElementById(c._container.id))}})})(window,Popcorn);
+"default":"Toronto, Ontario, Canada"},markers:{elem:"input",type:"text",label:"List Markers",optional:true}}})})(Popcorn);var wikiCallback;
+(function(p){p.plugin("wikipedia",{manifest:{about:{name:"Popcorn Wikipedia Plugin",version:"0.1",author:"@annasob",website:"annasob.wordpress.com"},options:{start:{elem:"input",type:"number",label:"Start"},end:{elem:"input",type:"number",label:"End"},lang:{elem:"input",type:"text",label:"Language","default":"english",optional:true},src:{elem:"input",type:"url",label:"Wikipedia URL","default":"http://en.wikipedia.org/wiki/Cat"},title:{elem:"input",type:"text",label:"Title","default":"Cats",optional:true},
+numberofwords:{elem:"input",type:"number",label:"Number of Words","default":"200",optional:true},target:"wikipedia-container"}},_setup:function(e){var l,d=p.guid();if(!e.lang)e.lang="en";e.numberofwords=e.numberofwords||200;window["wikiCallback"+d]=function(b){e._link=document.createElement("a");e._link.setAttribute("href",e.src);e._link.setAttribute("target","_blank");e._link.innerHTML=e.title||b.parse.displaytitle;e._desc=document.createElement("p");l=b.parse.text["*"].substr(b.parse.text["*"].indexOf("<p>"));
+l=l.replace(/((<(.|\n)+?>)|(\((.*?)\) )|(\[(.*?)\]))/g,"");l=l.split(" ");e._desc.innerHTML=l.slice(0,l.length>=e.numberofwords?e.numberofwords:l.length).join(" ")+" ...";e._fired=true};e.src&&p.getScript("//"+e.lang+".wikipedia.org/w/api.php?action=parse&props=text&redirects&page="+e.src.slice(e.src.lastIndexOf("/")+1)+"&format=json&callback=wikiCallback"+d);e.toString=function(){return e.src||e._natives.manifest.options.src["default"]}},start:function(e,l){var d=function(){if(l._fired){if(l._link&&
+l._desc)if(document.getElementById(l.target)){document.getElementById(l.target).appendChild(l._link);document.getElementById(l.target).appendChild(l._desc);l._added=true}}else setTimeout(function(){d()},13)};d()},end:function(e,l){if(l._added){document.getElementById(l.target).removeChild(l._link);document.getElementById(l.target).removeChild(l._desc)}},_teardown:function(e){if(e._added){e._link.parentNode&&document.getElementById(e.target).removeChild(e._link);e._desc.parentNode&&document.getElementById(e.target).removeChild(e._desc);
+delete e.target}}})})(Popcorn);(function(p){var e=0,l=function(d,b){var h=d.container=document.createElement("div"),i=h.style,g=d.media,k=function(){var r=d.position();i.fontSize="18px";i.width=g.offsetWidth+"px";i.top=r.top+g.offsetHeight-h.offsetHeight-40+"px";i.left=r.left+"px";setTimeout(k,10)};h.id=b||p.guid();i.position="absolute";i.color="white";i.textShadow="black 2px 2px 6px";i.fontWeight="bold";i.textAlign="center";k();d.media.parentNode.appendChild(h);return h};p.plugin("subtitle",{manifest:{about:{name:"Popcorn Subtitle Plugin",
+version:"0.1",author:"Scott Downe",website:"http://scottdowne.wordpress.com/"},options:{start:{elem:"input",type:"text",label:"Start"},end:{elem:"input",type:"text",label:"End"},target:"subtitle-container",text:{elem:"input",type:"text",label:"Text"}}},_setup:function(d){var b=document.createElement("div");b.id="subtitle-"+e++;b.style.display="none";!this.container&&(!d.target||d.target==="subtitle-container")&&l(this);d.container=d.target&&d.target!=="subtitle-container"?document.getElementById(d.target)||
+l(this,d.target):this.container;document.getElementById(d.container.id)&&document.getElementById(d.container.id).appendChild(b);d.innerContainer=b;d.showSubtitle=function(){d.innerContainer.innerHTML=d.text||""}},start:function(d,b){b.innerContainer.style.display="inline";b.showSubtitle(b,b.text)},end:function(d,b){b.innerContainer.style.display="none";b.innerContainer.innerHTML=""},_teardown:function(d){d.container.removeChild(d.innerContainer)}})})(Popcorn);(function(p,e){var l={};p.plugin("documentcloud",{manifest:{about:{name:"Popcorn Document Cloud Plugin",version:"0.1",author:"@humphd, @ChrisDeCairos",website:"http://vocamus.net/dave"},options:{start:{elem:"input",type:"number",label:"Start"},end:{elem:"input",type:"number",label:"End"},target:"documentcloud-container",width:{elem:"input",type:"text",label:"Width",optional:true},height:{elem:"input",type:"text",label:"Height",optional:true},src:{elem:"input",type:"url",label:"PDF URL","default":"http://www.documentcloud.org/documents/70050-urbina-day-1-in-progress.html"},
+preload:{elem:"input",type:"checkbox",label:"Preload","default":true},page:{elem:"input",type:"number",label:"Page Number",optional:true},aid:{elem:"input",type:"number",label:"Annotation Id",optional:true}}},_setup:function(d){function b(){function m(j){d._key=j.api.getId();d._changeView=function(w){d.aid?w.pageSet.showAnnotation(w.api.getAnnotation(d.aid)):w.api.setCurrentPage(d.page)}}function t(){l[d._key]={num:1,id:d._containerId};i.loaded=true}i.loaded=false;var q=d.url.replace(/\.html$/,".js"),
+o=d.target,u=e.getElementById(o),E=e.createElement("div"),C=p.position(u),f=d.width||C.width;C=d.height||C.height;var G=d.sidebar||true,A=d.text||true,O=d.pdf||true,a=d.showAnnotations||true,c=d.zoom||700,n=d.search||true;if(!function(j){var w=false;p.forEach(i.viewers,function(x){if(x.api.getSchema().canonicalURL===j){m(x);x=l[d._key];d._containerId=x.id;x.num+=1;w=true;i.loaded=true}});return w}(d.url)){E.id=d._containerId=p.guid(o);o="#"+E.id;u.appendChild(E);g.trigger("documentready");i.load(q,
+{width:f,height:C,sidebar:G,text:A,pdf:O,showAnnotations:a,zoom:c,search:n,container:o,afterLoad:d.page||d.aid?function(j){m(j);d._changeView(j);E.style.visibility="hidden";j.elements.pages.hide();t()}:function(j){m(j);t();E.style.visibility="hidden";j.elements.pages.hide()}})}}function h(){window.DV.loaded?b():setTimeout(h,25)}var i=window.DV=window.DV||{},g=this;if(i.loading)h();else{i.loading=true;i.recordHit="//www.documentcloud.org/pixel.gif";var k=e.createElement("link"),r=e.getElementsByTagName("head")[0];
+k.rel="stylesheet";k.type="text/css";k.media="screen";k.href="//s3.documentcloud.org/viewer/viewer-datauri.css";r.appendChild(k);i.loaded=false;p.getScript("http://s3.documentcloud.org/viewer/viewer.js",function(){i.loading=false;b()})}d.toString=function(){return d.src||d._natives.manifest.options.src["default"]}},start:function(d,b){var h=e.getElementById(b._containerId),i=DV.viewers[b._key];(b.page||b.aid)&&i&&b._changeView(i);if(h&&i){h.style.visibility="visible";i.elements.pages.show()}},end:function(d,
+b){var h=e.getElementById(b._containerId);if(h&&DV.viewers[b._key]){h.style.visibility="hidden";DV.viewers[b._key].elements.pages.hide()}},_teardown:function(d){var b=e.getElementById(d._containerId);if((d=d._key)&&DV.viewers[d]&&--l[d].num===0){for(DV.viewers[d].api.unload();b.hasChildNodes();)b.removeChild(b.lastChild);b.parentNode.removeChild(b)}}})})(Popcorn,window.document);(function(p){var e=/(?:http:\/\/www\.|http:\/\/|www\.|\.|^)(youtu|vimeo|soundcloud|baseplayer)/,l={},d={vimeo:false,youtube:false,soundcloud:false,module:false};Object.defineProperty(l,void 0,{get:function(){return d[void 0]},set:function(b){d[void 0]=b}});p.plugin("mediaspawner",{manifest:{about:{name:"Popcorn Media Spawner Plugin",version:"0.1",author:"Matthew Schranz, @mjschranz",website:"mschranz.wordpress.com"},options:{source:{elem:"input",type:"text",label:"Media Source","default":"http://www.youtube.com/watch?v=CXDstfD9eJ0"},
+caption:{elem:"input",type:"text",label:"Media Caption","default":"Popcorn Popping",optional:true},target:"mediaspawner-container",start:{elem:"input",type:"number",label:"Start"},end:{elem:"input",type:"number",label:"End"},autoplay:{elem:"input",type:"checkbox",label:"Autoplay Video",optional:true},width:{elem:"input",type:"number",label:"Media Width","default":400,units:"px",optional:true},height:{elem:"input",type:"number",label:"Media Height","default":200,units:"px",optional:true}}},_setup:function(b){function h(){function t(){if(k!==
+"HTML5"&&!window.Popcorn[k])setTimeout(function(){t()},300);else{b.id=b._container.id;b._container.style.width=b.width+"px";b._container.style.height=b.height+"px";b.popcorn=p.smart("#"+b.id,b.source);k==="HTML5"&&b.popcorn.controls(true);b._container.style.width="0px";b._container.style.height="0px";b._container.style.visibility="hidden";b._container.style.overflow="hidden"}}if(k!=="HTML5"&&!window.Popcorn[k]&&!l[k]){l[k]=true;p.getScript("http://popcornjs.org/code/players/"+k+"/popcorn."+k+".js",
+function(){t()})}else t()}function i(){window.Popcorn.player?h():setTimeout(function(){i()},300)}var g=document.getElementById(b.target)||{},k,r,m;if(r=e.exec(b.source)){k=r[1];if(k==="youtu")k="youtube"}else k="HTML5";b._type=k;b._container=document.createElement("div");r=b._container;r.id="mediaSpawnerdiv-"+p.guid();b.width=b.width||400;b.height=b.height||200;if(b.caption){m=document.createElement("div");m.innerHTML=b.caption;m.style.display="none";b._capCont=m;r.appendChild(m)}g&&g.appendChild(r);
+if(!window.Popcorn.player&&!l.module){l.module=true;p.getScript("http://popcornjs.org/code/modules/player/popcorn.player.js",i)}else i();b.toString=function(){return b.source||b._natives.manifest.options.source["default"]}},start:function(b,h){if(h._capCont)h._capCont.style.display="";h._container.style.width=h.width+"px";h._container.style.height=h.height+"px";h._container.style.visibility="visible";h._container.style.overflow="visible";h.autoplay&&h.popcorn.play()},end:function(b,h){if(h._capCont)h._capCont.style.display=
+"none";h._container.style.width="0px";h._container.style.height="0px";h._container.style.visibility="hidden";h._container.style.overflow="hidden";h.popcorn.pause()},_teardown:function(b){b.popcorn&&b.popcorn.destory&&b.popcorn.destroy();document.getElementById(b.target)&&document.getElementById(b.target).removeChild(b._container)}})})(Popcorn,this);(function(p){var e=1;p.plugin("timeline",function(l){var d=document.getElementById(l.target),b=document.createElement("div"),h,i=true;if(d&&!d.firstChild){d.appendChild(h=document.createElement("div"));h.style.width="inherit";h.style.height="inherit";h.style.overflow="auto"}else h=d.firstChild;b.style.display="none";b.id="timelineDiv"+e;l.direction=l.direction||"up";if(l.direction.toLowerCase()==="down")i=false;if(d&&h)i?h.insertBefore(b,h.firstChild):h.appendChild(b);e++;b.innerHTML="<p><span id='big' style='font-size:24px; line-height: 130%;' >"+
+l.title+"</span><br /><span id='mid' style='font-size: 16px;'>"+l.text+"</span><br />"+l.innerHTML;return{start:function(g,k){b.style.display="block";if(k.direction==="down")h.scrollTop=h.scrollHeight},end:function(){b.style.display="none"},_teardown:function(){h&&b&&h.removeChild(b)&&!h.firstChild&&d.removeChild(h)}}},{about:{name:"Popcorn Timeline Plugin",version:"0.1",author:"David Seifried @dcseifried",website:"dseifried.wordpress.com"},options:{start:{elem:"input",type:"number",label:"Start"},
+end:{elem:"input",type:"number",label:"End"},target:"feed-container",title:{elem:"input",type:"text",label:"Title"},text:{elem:"input",type:"text",label:"Text"},innerHTML:{elem:"input",type:"text",label:"HTML Code",optional:true},direction:{elem:"select",options:["DOWN","UP"],label:"Direction",optional:true}}})})(Popcorn);(function(p){var e=0;p.plugin("flickr",function(l){var d,b=document.getElementById(l.target),h,i,g,k,r=l.numberofimages||4,m=l.height||"50px",t=l.width||"50px",q=l.padding||"5px",o=l.border||"0px";d=document.createElement("div");d.id="flickr"+e;d.style.width="100%";d.style.height="100%";d.style.display="none";e++;b&&b.appendChild(d);var u=function(){if(h)setTimeout(function(){u()},5);else{i="http://api.flickr.com/services/rest/?method=flickr.people.findByUsername&";i+="username="+l.username+"&api_key="+
+l.apikey+"&format=json&jsoncallback=flickr";p.getJSONP(i,function(C){h=C.user.nsid;E()})}},E=function(){i="http://api.flickr.com/services/feeds/photos_public.gne?";if(h)i+="id="+h+"&";if(l.tags)i+="tags="+l.tags+"&";i+="lang=en-us&format=json&jsoncallback=flickr";p.xhr.getJSONP(i,function(C){var f=document.createElement("div");f.innerHTML="<p style='padding:"+q+";'>"+C.title+"<p/>";p.forEach(C.items,function(G,A){if(A<r){g=document.createElement("a");g.setAttribute("href",G.link);g.setAttribute("target",
+"_blank");k=document.createElement("img");k.setAttribute("src",G.media.m);k.setAttribute("height",m);k.setAttribute("width",t);k.setAttribute("style","border:"+o+";padding:"+q);g.appendChild(k);f.appendChild(g)}else return false});d.appendChild(f)})};if(l.username&&l.apikey)u();else{h=l.userid;E()}l.toString=function(){return l.tags||l.username||"Flickr"};return{start:function(){d.style.display="inline"},end:function(){d.style.display="none"},_teardown:function(C){document.getElementById(C.target)&&
+document.getElementById(C.target).removeChild(d)}}},{about:{name:"Popcorn Flickr Plugin",version:"0.2",author:"Scott Downe, Steven Weerdenburg, Annasob",website:"http://scottdowne.wordpress.com/"},options:{start:{elem:"input",type:"number",label:"Start"},end:{elem:"input",type:"number",label:"End"},userid:{elem:"input",type:"text",label:"User ID",optional:true},tags:{elem:"input",type:"text",label:"Tags"},username:{elem:"input",type:"text",label:"Username",optional:true},apikey:{elem:"input",type:"text",
+label:"API Key",optional:true},target:"flickr-container",height:{elem:"input",type:"text",label:"Height","default":"50px",optional:true},width:{elem:"input",type:"text",label:"Width","default":"50px",optional:true},padding:{elem:"input",type:"text",label:"Padding",optional:true},border:{elem:"input",type:"text",label:"Border","default":"5px",optional:true},numberofimages:{elem:"input",type:"number","default":4,label:"Number of Images"}}})})(Popcorn);(function(p){p.plugin("webpage",{manifest:{about:{name:"Popcorn Webpage Plugin",version:"0.1",author:"@annasob",website:"annasob.wordpress.com"},options:{id:{elem:"input",type:"text",label:"Id",optional:true},start:{elem:"input",type:"number",label:"Start"},end:{elem:"input",type:"number",label:"End"},src:{elem:"input",type:"url",label:"Webpage URL","default":"http://mozillapopcorn.org"},target:"iframe-container"}},_setup:function(e){var l=document.getElementById(e.target);e.src=e.src.replace(/^(https?:)?(\/\/)?/,
+"//");e._iframe=document.createElement("iframe");e._iframe.setAttribute("width","100%");e._iframe.setAttribute("height","100%");e._iframe.id=e.id;e._iframe.src=e.src;e._iframe.style.display="none";l&&l.appendChild(e._iframe)},start:function(e,l){l._iframe.src=l.src;l._iframe.style.display="inline"},end:function(e,l){l._iframe.style.display="none"},_teardown:function(e){document.getElementById(e.target)&&document.getElementById(e.target).removeChild(e._iframe)}})})(Popcorn);(function(p){var e={},l=0,d=document.createElement("span"),b=["webkit","Moz","ms","O",""],h=["Transform","TransitionDuration","TransitionTimingFunction"],i={},g;document.getElementsByTagName("head")[0].appendChild(d);for(var k=0,r=h.length;k<r;k++)for(var m=0,t=b.length;m<t;m++){g=b[m]+h[k];if(g in d.style){i[h[k].toLowerCase()]=g;break}}document.getElementsByTagName("head")[0].appendChild(d);p.plugin("wordriver",{manifest:{about:{name:"Popcorn WordRiver Plugin"},options:{start:{elem:"input",type:"number",
+label:"Start"},end:{elem:"input",type:"number",label:"End"},target:"wordriver-container",text:{elem:"input",type:"text",label:"Text","default":"Popcorn.js"},color:{elem:"input",type:"text",label:"Color","default":"Green",optional:true}}},_setup:function(q){q._duration=q.end-q.start;var o;if(!(o=e[q.target])){o=q.target;e[o]=document.createElement("div");var u=document.getElementById(o);u&&u.appendChild(e[o]);e[o].style.height="100%";e[o].style.position="relative";o=e[o]}q._container=o;q.word=document.createElement("span");
+q.word.style.position="absolute";q.word.style.whiteSpace="nowrap";q.word.style.opacity=0;q.word.style.MozTransitionProperty="opacity, -moz-transform";q.word.style.webkitTransitionProperty="opacity, -webkit-transform";q.word.style.OTransitionProperty="opacity, -o-transform";q.word.style.transitionProperty="opacity, transform";q.word.style[i.transitionduration]="1s, "+q._duration+"s";q.word.style[i.transitiontimingfunction]="linear";q.word.innerHTML=q.text;q.word.style.color=q.color||"black"},start:function(q,
+o){o._container.appendChild(o.word);o.word.style[i.transform]="";o.word.style.fontSize=~~(30+20*Math.random())+"px";l%=o._container.offsetWidth-o.word.offsetWidth;o.word.style.left=l+"px";l+=o.word.offsetWidth+10;o.word.style[i.transform]="translateY("+(o._container.offsetHeight-o.word.offsetHeight)+"px)";o.word.style.opacity=1;setTimeout(function(){o.word.style.opacity=0},(o.end-o.start-1||1)*1E3)},end:function(q,o){o.word.style.opacity=0},_teardown:function(q){var o=document.getElementById(q.target);
+q.word.parentNode&&q._container.removeChild(q.word);e[q.target]&&!e[q.target].childElementCount&&o&&o.removeChild(e[q.target])&&delete e[q.target]}})})(Popcorn);var googleCallback;
+(function(p){function e(g,k,r){g=g.type?g.type.toUpperCase():"HYBRID";var m;if(g==="STAMEN-WATERCOLOR"||g==="STAMEN-TERRAIN"||g==="STAMEN-TONER")m=g.replace("STAMEN-","").toLowerCase();r=new google.maps.Map(r,{mapTypeId:m?m:google.maps.MapTypeId[g],mapTypeControlOptions:{mapTypeIds:[]}});m&&r.mapTypes.set(m,new google.maps.StamenMapType(m));r.getDiv().style.display="none";return r}var l=1,d=false,b=false,h,i;googleCallback=function(g){if(typeof google!=="undefined"&&google.maps&&google.maps.Geocoder&&
+google.maps.LatLng){h=new google.maps.Geocoder;p.getScript("//maps.stamen.com/js/tile.stamen.js",function(){b=true})}else setTimeout(function(){googleCallback(g)},1)};i=function(){if(document.body){d=true;p.getScript("//maps.google.com/maps/api/js?sensor=false&callback=googleCallback")}else setTimeout(function(){i()},1)};p.plugin("googlemap",function(g){var k,r,m,t=document.getElementById(g.target);g.type=g.type||"ROADMAP";g.zoom=g.zoom||1;g.lat=g.lat||0;g.lng=g.lng||0;d||i();k=document.createElement("div");
+k.id="actualmap"+l;k.style.width=g.width||"100%";k.style.height=g.height?g.height:t&&t.clientHeight?t.clientHeight+"px":"100%";l++;t&&t.appendChild(k);var q=function(){if(b){if(k)if(g.location)h.geocode({address:g.location},function(o,u){if(k&&u===google.maps.GeocoderStatus.OK){g.lat=o[0].geometry.location.lat();g.lng=o[0].geometry.location.lng();m=new google.maps.LatLng(g.lat,g.lng);r=e(g,m,k)}});else{m=new google.maps.LatLng(g.lat,g.lng);r=e(g,m,k)}}else setTimeout(function(){q()},5)};q();g.toString=
+function(){return g.location||(g.lat&&g.lng?g.lat+", "+g.lng:g._natives.manifest.options.location["default"])};return{start:function(o,u){var E=this,C,f=function(){if(r){u._map=r;r.getDiv().style.display="block";google.maps.event.trigger(r,"resize");r.setCenter(m);if(u.zoom&&typeof u.zoom!=="number")u.zoom=+u.zoom;r.setZoom(u.zoom);if(u.heading&&typeof u.heading!=="number")u.heading=+u.heading;if(u.pitch&&typeof u.pitch!=="number")u.pitch=+u.pitch;if(u.type==="STREETVIEW"){r.setStreetView(C=new google.maps.StreetViewPanorama(k,
+{position:m,pov:{heading:u.heading=u.heading||0,pitch:u.pitch=u.pitch||0,zoom:u.zoom}}));var G=function(w,x){var z=google.maps.geometry.spherical.computeHeading;setTimeout(function(){var F=E.media.currentTime;if(typeof u.tween==="object"){for(var v=0,L=w.length;v<L;v++){var y=w[v];if(F>=y.interval*(v+1)/1E3&&(F<=y.interval*(v+2)/1E3||F>=y.interval*L/1E3)){n.setPosition(new google.maps.LatLng(y.position.lat,y.position.lng));n.setPov({heading:y.pov.heading||z(y,w[v+1])||0,zoom:y.pov.zoom||0,pitch:y.pov.pitch||
+0})}}G(w,w[0].interval)}else{v=0;for(L=w.length;v<L;v++){y=u.interval;if(F>=y*(v+1)/1E3&&(F<=y*(v+2)/1E3||F>=y*L/1E3)){A.setPov({heading:z(w[v],w[v+1])||0,zoom:u.zoom,pitch:u.pitch||0});A.setPosition(O[v])}}G(O,u.interval)}},x)};if(u.location&&typeof u.tween==="string"){var A=C,O=[],a=new google.maps.DirectionsService,c=new google.maps.DirectionsRenderer(A);a.route({origin:u.location,destination:u.tween,travelMode:google.maps.TravelMode.DRIVING},function(w,x){if(x==google.maps.DirectionsStatus.OK){c.setDirections(w);
+for(var z=w.routes[0].overview_path,F=0,v=z.length;F<v;F++)O.push(new google.maps.LatLng(z[F].lat(),z[F].lng()));u.interval=u.interval||1E3;G(O,10)}})}else if(typeof u.tween==="object"){var n=C;a=0;for(var j=u.tween.length;a<j;a++){u.tween[a].interval=u.tween[a].interval||1E3;G(u.tween,10)}}}u.onmaploaded&&u.onmaploaded(u,r)}else setTimeout(function(){f()},13)};f()},end:function(){if(r)r.getDiv().style.display="none"},_teardown:function(o){var u=document.getElementById(o.target);u&&u.removeChild(k);
+k=r=m=null;o._map=null}}},{about:{name:"Popcorn Google Map Plugin",version:"0.1",author:"@annasob",website:"annasob.wordpress.com"},options:{start:{elem:"input",type:"start",label:"Start"},end:{elem:"input",type:"start",label:"End"},target:"map-container",type:{elem:"select",options:["ROADMAP","SATELLITE","STREETVIEW","HYBRID","TERRAIN","STAMEN-WATERCOLOR","STAMEN-TERRAIN","STAMEN-TONER"],label:"Map Type",optional:true},zoom:{elem:"input",type:"text",label:"Zoom","default":0,optional:true},lat:{elem:"input",
+type:"text",label:"Lat",optional:true},lng:{elem:"input",type:"text",label:"Lng",optional:true},location:{elem:"input",type:"text",label:"Location","default":"Toronto, Ontario, Canada"},heading:{elem:"input",type:"text",label:"Heading","default":0,optional:true},pitch:{elem:"input",type:"text",label:"Pitch","default":1,optional:true}}})})(Popcorn);(function(p){p.plugin("mustache",function(e){var l,d,b,h;p.getScript("http://mustache.github.com/extras/mustache.js");var i=!!e.dynamic,g=typeof e.template,k=typeof e.data,r=document.getElementById(e.target);e.container=r||document.createElement("div");if(g==="function")if(i)b=e.template;else h=e.template(e);else h=g==="string"?e.template:"";if(k==="function")if(i)l=e.data;else d=e.data(e);else d=k==="string"?JSON.parse(e.data):k==="object"?e.data:"";return{start:function(m,t){var q=function(){if(window.Mustache){if(l)d=
+l(t);if(b)h=b(t);var o=Mustache.to_html(h,d).replace(/^\s*/mg,"");t.container.innerHTML=o}else setTimeout(function(){q()},10)};q()},end:function(m,t){t.container.innerHTML=""},_teardown:function(){l=d=b=h=null}}},{about:{name:"Popcorn Mustache Plugin",version:"0.1",author:"David Humphrey (@humphd)",website:"http://vocamus.net/dave"},options:{start:{elem:"input",type:"number",label:"Start"},end:{elem:"input",type:"number",label:"End"},target:"mustache-container",template:{elem:"input",type:"text",
+label:"Template"},data:{elem:"input",type:"text",label:"Data"},dynamic:{elem:"input",type:"checkbox",label:"Dynamic","default":true}}})})(Popcorn);document.addEventListener("click",function(p){p=p.target;if(p.nodeName==="A"||p.parentNode&&p.parentNode.nodeName==="A")Popcorn.instances.forEach(function(e){e.options.pauseOnLinkClicked&&e.pause()})},false);(function(p){p.plugin("footnote",{manifest:{about:{name:"Popcorn Footnote Plugin",version:"0.2",author:"@annasob, @rwaldron",website:"annasob.wordpress.com"},options:{start:{elem:"input",type:"number",label:"Start"},end:{elem:"input",type:"number",label:"End"},text:{elem:"input",type:"text",label:"Text"},target:"footnote-container"}},_setup:function(e){var l=p.dom.find(e.target);e._container=document.createElement("div");e._container.style.display="none";e._container.innerHTML=e.text;l.appendChild(e._container)},
+start:function(e,l){l._container.style.display="inline"},end:function(e,l){l._container.style.display="none"},_teardown:function(e){var l=p.dom.find(e.target);l&&l.removeChild(e._container)}})})(Popcorn);(function(p){var e=1,l=false;p.plugin("googlefeed",function(d){var b=function(){var k=false,r=0,m=document.getElementsByTagName("link"),t=m.length,q=document.head||document.getElementsByTagName("head")[0],o=document.createElement("link");if(window.GFdynamicFeedControl)l=true;else p.getScript("//www.google.com/uds/solutions/dynamicfeed/gfdynamicfeedcontrol.js",function(){l=true});for(;r<t;r++)if(m[r].href==="//www.google.com/uds/solutions/dynamicfeed/gfdynamicfeedcontrol.css")k=true;if(!k){o.type=
+"text/css";o.rel="stylesheet";o.href="//www.google.com/uds/solutions/dynamicfeed/gfdynamicfeedcontrol.css";q.insertBefore(o,q.firstChild)}};window.google?b():p.getScript("//www.google.com/jsapi",function(){google.load("feeds","1",{callback:function(){b()}})});var h=document.createElement("div"),i=document.getElementById(d.target),g=function(){if(l)d.feed=new GFdynamicFeedControl(d.url,h,{vertical:d.orientation.toLowerCase()==="vertical"?true:false,horizontal:d.orientation.toLowerCase()==="horizontal"?
+true:false,title:d.title=d.title||"Blog"});else setTimeout(function(){g()},5)};if(!d.orientation||d.orientation.toLowerCase()!=="vertical"&&d.orientation.toLowerCase()!=="horizontal")d.orientation="vertical";h.style.display="none";h.id="_feed"+e;h.style.width="100%";h.style.height="100%";e++;i&&i.appendChild(h);g();d.toString=function(){return d.url||d._natives.manifest.options.url["default"]};return{start:function(){h.setAttribute("style","display:inline")},end:function(){h.setAttribute("style",
+"display:none")},_teardown:function(k){document.getElementById(k.target)&&document.getElementById(k.target).removeChild(h);delete k.feed}}},{about:{name:"Popcorn Google Feed Plugin",version:"0.1",author:"David Seifried",website:"dseifried.wordpress.com"},options:{start:{elem:"input",type:"number",label:"Start"},end:{elem:"input",type:"number",label:"End"},target:"feed-container",url:{elem:"input",type:"url",label:"Feed URL","default":"http://planet.mozilla.org/rss20.xml"},title:{elem:"input",type:"text",
+label:"Title","default":"Planet Mozilla",optional:true},orientation:{elem:"select",options:["Vertical","Horizontal"],label:"Orientation","default":"Vertical",optional:true}}})})(Popcorn);(function(p){function e(b){return String(b).replace(/&(?!\w+;)|[<>"']/g,function(h){return d[h]||h})}function l(b,h){var i=b.container=document.createElement("div"),g=i.style,k=b.media,r=function(){var m=b.position();g.fontSize="18px";g.width=k.offsetWidth+"px";g.top=m.top+k.offsetHeight-i.offsetHeight-40+"px";g.left=m.left+"px";setTimeout(r,10)};i.id=h||"";g.position="absolute";g.color="white";g.textShadow="black 2px 2px 6px";g.fontWeight="bold";g.textAlign="center";r();b.media.parentNode.appendChild(i);
+return i}var d={"&":"&","<":"<",">":">",'"':""","'":"'"};p.plugin("text",{manifest:{about:{name:"Popcorn Text Plugin",version:"0.1",author:"@humphd"},options:{start:{elem:"input",type:"number",label:"Start"},end:{elem:"input",type:"number",label:"End"},text:{elem:"input",type:"text",label:"Text","default":"Popcorn.js"},escape:{elem:"input",type:"checkbox",label:"Escape"},multiline:{elem:"input",type:"checkbox",label:"Multiline"}}},_setup:function(b){var h,i,g=b._container=document.createElement("div");
+g.style.display="none";if(b.target)if(h=p.dom.find(b.target)){if(["VIDEO","AUDIO"].indexOf(h.nodeName)>-1)h=l(this,b.target+"-overlay")}else h=l(this,b.target);else h=this.container?this.container:l(this);b._target=h;i=b.escape?e(b.text):b.text;i=b.multiline?i.replace(/\r?\n/gm,"<br>"):i;g.innerHTML=i||"";h.appendChild(g);b.toString=function(){return b.text||b._natives.manifest.options.text["default"]}},start:function(b,h){h._container.style.display="inline"},end:function(b,h){h._container.style.display=
+"none"},_teardown:function(b){var h=b._target;h&&h.removeChild(b._container)}})})(Popcorn);(function(p){p.plugin("code",function(e){var l=false,d=this,b=function(){var h=function(i){return function(g,k){var r=function(){l&&g.call(d,k);l&&i(r)};r()}};return window.webkitRequestAnimationFrame?h(window.webkitRequestAnimationFrame):window.mozRequestAnimationFrame?h(window.mozRequestAnimationFrame):h(function(i){window.setTimeout(i,16)})}();if(!e.onStart||typeof e.onStart!=="function")e.onStart=p.nop;if(e.onEnd&&typeof e.onEnd!=="function")e.onEnd=undefined;if(e.onFrame&&typeof e.onFrame!==
+"function")e.onFrame=undefined;return{start:function(h,i){i.onStart.call(d,i);if(i.onFrame){l=true;b(i.onFrame,i)}},end:function(h,i){if(i.onFrame)l=false;i.onEnd&&i.onEnd.call(d,i)}}},{about:{name:"Popcorn Code Plugin",version:"0.1",author:"David Humphrey (@humphd)",website:"http://vocamus.net/dave"},options:{start:{elem:"input",type:"number",label:"Start"},end:{elem:"input",type:"number",label:"End"},onStart:{elem:"input",type:"function",label:"onStart"},onFrame:{elem:"input",type:"function",label:"onFrame",
+optional:true},onEnd:{elem:"input",type:"function",label:"onEnd"}}})})(Popcorn);(function(p){function e(b){function h(){var r=b.getBoundingClientRect(),m=g.getBoundingClientRect();if(m.left!==r.left)g.style.left=r.left+"px";if(m.top!==r.top)g.style.top=r.top+"px"}var i=-1,g=document.createElement("div"),k=getComputedStyle(b).zIndex;g.setAttribute("data-popcorn-helper-container",true);g.style.position="absolute";g.style.zIndex=isNaN(k)?l:k+1;document.body.appendChild(g);return{element:g,start:function(){i=setInterval(h,d)},stop:function(){clearInterval(i);i=-1},destroy:function(){document.body.removeChild(g);
+i!==-1&&clearInterval(i)}}}var l=2E3,d=10;p.plugin("image",{manifest:{about:{name:"Popcorn image Plugin",version:"0.1",author:"Scott Downe",website:"http://scottdowne.wordpress.com/"},options:{start:{elem:"input",type:"number",label:"Start"},end:{elem:"input",type:"number",label:"End"},src:{elem:"input",type:"url",label:"Image URL","default":"http://mozillapopcorn.org/wp-content/themes/popcorn/images/for_developers.png"},href:{elem:"input",type:"url",label:"Link","default":"http://mozillapopcorn.org/wp-content/themes/popcorn/images/for_developers.png",
+optional:true},target:"image-container",text:{elem:"input",type:"text",label:"Caption","default":"Popcorn.js",optional:true}}},_setup:function(b){var h=document.createElement("img"),i=document.getElementById(b.target);b.anchor=document.createElement("a");b.anchor.style.position="relative";b.anchor.style.textDecoration="none";b.anchor.style.display="none";if(i)if(["VIDEO","AUDIO"].indexOf(i.nodeName)>-1){b.trackedContainer=e(i);b.trackedContainer.element.appendChild(b.anchor)}else i&&i.appendChild(b.anchor);
+h.addEventListener("load",function(){h.style.borderStyle="none";b.anchor.href=b.href||b.src||"#";b.anchor.target="_blank";var g,k;h.style.height=i.style.height;h.style.width=i.style.width;b.anchor.appendChild(h);if(b.text){g=h.height/12+"px";k=document.createElement("div");p.extend(k.style,{color:"black",fontSize:g,fontWeight:"bold",position:"relative",textAlign:"center",width:h.style.width||h.width+"px",zIndex:"10"});k.innerHTML=b.text||"";k.style.top=(h.style.height.replace("px","")||h.height)/
+2-k.offsetHeight/2+"px";b.anchor.insertBefore(k,h)}},false);h.src=b.src;b.toString=function(){var g=b.src||b._natives.manifest.options.src["default"],k=g.replace(/.*\//g,"");return k.length?k:g}},start:function(b,h){h.anchor.style.display="inline";h.trackedContainer&&h.trackedContainer.start()},end:function(b,h){h.anchor.style.display="none";h.trackedContainer&&h.trackedContainer.stop()},_teardown:function(b){if(b.trackedContainer)b.trackedContainer.destroy();else b.anchor.parentNode&&b.anchor.parentNode.removeChild(b.anchor)}})})(Popcorn);(function(p){p.parser("parseXML","XML",function(e){var l={title:"",remote:"",data:[]},d={},b=function(m){m=m.split(":");if(m.length===1)return parseFloat(m[0],10);else if(m.length===2)return parseFloat(m[0],10)+parseFloat(m[1]/12,10);else if(m.length===3)return parseInt(m[0]*60,10)+parseFloat(m[1],10)+parseFloat(m[2]/12,10);else if(m.length===4)return parseInt(m[0]*3600,10)+parseInt(m[1]*60,10)+parseFloat(m[2],10)+parseFloat(m[3]/12,10)},h=function(m){for(var t={},q=0,o=m.length;q<o;q++){var u=m.item(q).nodeName,
+E=m.item(q).nodeValue,C=d[E];if(u==="in")t.start=b(E);else if(u==="out")t.end=b(E);else if(u==="resourceid")for(var f in C){if(C.hasOwnProperty(f))if(!t[f]&&f!=="id")t[f]=C[f]}else t[u]=E}return t},i=function(m,t){var q={};q[m]=t;return q},g=function(m,t,q){var o={};p.extend(o,t,h(m.attributes),{text:m.textContent||m.text});t=m.childNodes;if(t.length<1||t.length===1&&t[0].nodeType===3)if(q)d[o.id]=o;else l.data.push(i(m.nodeName,o));else for(m=0;m<t.length;m++)t[m].nodeType===1&&g(t[m],o,q)};e=e.documentElement.childNodes;
+for(var k=0,r=e.length;k<r;k++)if(e[k].nodeType===1)e[k].nodeName==="manifest"?g(e[k],{},true):g(e[k],{},false);return l})})(Popcorn);(function(p){p.parser("parseSBV",function(e){var l={title:"",remote:"",data:[]},d=[],b=0,h=0,i=function(q){q=q.split(":");var o=q.length-1,u;try{u=parseInt(q[o-1],10)*60+parseFloat(q[o],10);if(o===2)u+=parseInt(q[0],10)*3600}catch(E){throw"Bad cue";}return u},g=function(q,o){var u={};u[q]=o;return u};e=e.text.split(/(?:\r\n|\r|\n)/gm);for(h=e.length;b<h;){var k={},r=[],m=e[b++].split(",");try{k.start=i(m[0]);for(k.end=i(m[1]);b<h&&e[b];)r.push(e[b++]);k.text=r.join("<br />");d.push(g("subtitle",k))}catch(t){for(;b<
+h&&e[b];)b++}for(;b<h&&!e[b];)b++}l.data=d;return l})})(Popcorn);(function(p){p.parser("parseJSON","JSON",function(e){var l={title:"",remote:"",data:[]};p.forEach(e.data,function(d){l.data.push(d)});return l})})(Popcorn);(function(p){p.parser("parseTTXT",function(e){var l={title:"",remote:"",data:[]},d=function(k){k=k.split(":");var r=0;try{return parseFloat(k[0],10)*60*60+parseFloat(k[1],10)*60+parseFloat(k[2],10)}catch(m){r=0}return r},b=function(k,r){var m={};m[k]=r;return m};e=e.xml.lastChild.lastChild;for(var h=Number.MAX_VALUE,i=[];e;){if(e.nodeType===1&&e.nodeName==="TextSample"){var g={};g.start=d(e.getAttribute("sampleTime"));g.text=e.getAttribute("text");if(g.text){g.end=h-0.0010;i.push(b("subtitle",g))}h=
+g.start}e=e.previousSibling}l.data=i.reverse();return l})})(Popcorn);(function(p){function e(g,k,r){var m=g.firstChild;g=l(g,r);r=[];for(var t;m;){if(m.nodeType===1)if(m.nodeName==="p")r.push(d(m,k,g));else if(m.nodeName==="div"){t=b(m.getAttribute("begin"));if(t<0)t=k;r.push.apply(r,e(m,t,g))}m=m.nextSibling}return r}function l(g,k){var r=g.getAttribute("region");return r!==null?r:k||""}function d(g,k,r){var m={};m.text=(g.textContent||g.text).replace(h,"").replace(i,"<br />");m.id=g.getAttribute("xml:id")||g.getAttribute("id");m.start=b(g.getAttribute("begin"),k);
+m.end=b(g.getAttribute("end"),k);m.target=l(g,r);if(m.end<0){m.end=b(g.getAttribute("duration"),0);if(m.end>=0)m.end+=m.start;else m.end=Number.MAX_VALUE}return{subtitle:m}}function b(g,k){var r;if(!g)return-1;try{return p.util.toSeconds(g)}catch(m){for(var t=g.length-1;t>=0&&g[t]<="9"&&g[t]>="0";)t--;r=t;t=parseFloat(g.substring(0,r));r=g.substring(r);return t*({h:3600,m:60,s:1,ms:0.0010}[r]||-1)+(k||0)}}var h=/^[\s]+|[\s]+$/gm,i=/(?:\r\n|\r|\n)/gm;p.parser("parseTTML",function(g){var k={title:"",
+remote:"",data:[]};if(!g.xml||!g.xml.documentElement)return k;g=g.xml.documentElement.firstChild;if(!g)return k;for(;g.nodeName!=="body";)g=g.nextSibling;if(g)k.data=e(g,0);return k})})(Popcorn);(function(p){function e(d){var b=d.split(":");d=d.length;var h;if(d!==12&&d!==9)throw"Bad cue";d=b.length-1;try{h=parseInt(b[d-1],10)*60+parseFloat(b[d],10);if(d===2)h+=parseInt(b[0],10)*3600}catch(i){throw"Bad cue";}return h}function l(d,b){var h={};h[d]=b;return h}p.parser("parseVTT",function(d){var b={title:"",remote:"",data:[]},h=[],i=0,g=0,k,r;d=d.text.split(/(?:\r\n|\r|\n)/gm);g=d.length;if(g===0||d[0]!=="WEBVTT")return b;for(i++;i<g;){k=[];try{for(var m=i;m<g&&!d[m];)m++;i=m;var t=d[i++];m=
+void 0;var q={};if(!t||t.indexOf("--\>")===-1)throw"Bad cue";m=t.replace(/--\>/," --\> ").split(/[\t ]+/);if(m.length<2)throw"Bad cue";q.id=t;q.start=e(m[0]);q.end=e(m[2]);for(r=q;i<g&&d[i];)k.push(d[i++]);r.text=k.join("<br />");h.push(l("subtitle",r))}catch(o){for(i=i;i<g&&d[i];)i++;i=i}}b.data=h;return b})})(Popcorn);(function(p){function e(b,h){var i=b.substr(10).split(","),g;g={start:l(i[h.start]),end:l(i[h.end])};if(g.start===-1||g.end===-1)throw"Invalid time";var k=q.call(m,/\{(\\[\w]+\(?([\w\d]+,?)+\)?)+\}/gi,""),r=k.replace,m;m=i.length;q=[];for(var t=h.text;t<m;t++)q.push(i[t]);m=q.join(",");var q=m.replace;g.text=r.call(k,/\\N/gi,"<br />");return g}function l(b){var h=b.split(":");if(b.length!==10||h.length<3)return-1;return parseInt(h[0],10)*3600+parseInt(h[1],10)*60+parseFloat(h[2],10)}function d(b,
+h){var i={};i[b]=h;return i}p.parser("parseSSA",function(b){var h={title:"",remote:"",data:[]},i=[],g=0,k;b=b.text.split(/(?:\r\n|\r|\n)/gm);for(k=b.length;g<k&&b[g]!=="[Events]";)g++;var r=b[++g].substr(8).split(", "),m={},t,q;q=0;for(t=r.length;q<t;q++)if(r[q]==="Start")m.start=q;else if(r[q]==="End")m.end=q;else if(r[q]==="Text")m.text=q;for(;++g<k&&b[g]&&b[g][0]!=="[";)try{i.push(d("subtitle",e(b[g],m)))}catch(o){}h.data=i;return h})})(Popcorn);(function(p){function e(d,b){var h={};h[d]=b;return h}function l(d){d=d.split(":");try{var b=d[2].split(",");if(b.length===1)b=d[2].split(".");return parseFloat(d[0],10)*3600+parseFloat(d[1],10)*60+parseFloat(b[0],10)+parseFloat(b[1],10)/1E3}catch(h){return 0}}p.parser("parseSRT",function(d,b){var h={title:"",remote:"",data:[]},i=[],g=0,k=0,r,m,t,q,o;r=d.text.split(/(?:\r\n|\r|\n)/gm);for(t=r.length-1;t>=0&&!r[t];)t--;q=t+1;for(g=0;g<q;g++){o={};t=[];for(g=g;!r[g];)g++;g=g;o.id=parseInt(r[g++],10);
+m=r[g++].split(/[\t ]*--\>[\t ]*/);o.start=l(m[0]);k=m[1].indexOf(" ");if(k!==-1)m[1]=m[1].substr(0,k);for(o.end=l(m[1]);g<q&&r[g];)t.push(r[g++]);o.text=t.join("\\N").replace(/\{(\\[\w]+\(?([\w\d]+,?)+\)?)+\}/gi,"");o.text=o.text.replace(/</g,"<").replace(/>/g,">");o.text=o.text.replace(/<(\/?(font|b|u|i|s))((\s+(\w|\w[\w\-]*\w)(\s*=\s*(?:\".*?\"|'.*?'|[^'\">\s]+))?)+\s*|\s*)(\/?)>/gi,"<$1$3$7>");o.text=o.text.replace(/\\N/gi,"<br />");if(b&&b.target)o.target=b.target;i.push(e("subtitle",
+o))}h.data=i;return h})})(Popcorn);(function(p,e){e.player("vimeo",{_canPlayType:function(l,d){return typeof d==="string"&&e.HTMLVimeoVideoElement._canPlaySrc(d)}});e.vimeo=function(l,d,b){typeof console!=="undefined"&&console.warn&&console.warn("Deprecated player 'vimeo'. Please use Popcorn.HTMLVimeoVideoElement directly.");var h=e.HTMLVimeoVideoElement(l);l=e(h,b);setTimeout(function(){h.src=d},0);return l}})(window,Popcorn);(function(p,e){var l=function(d,b){return typeof b==="string"&&e.HTMLYouTubeVideoElement._canPlaySrc(b)};e.player("youtube",{_canPlayType:l});e.youtube=function(d,b,h){typeof console!=="undefined"&&console.warn&&console.warn("Deprecated player 'youtube'. Please use Popcorn.HTMLYouTubeVideoElement directly.");var i=e.HTMLYouTubeVideoElement(d);d=e(i,h);setTimeout(function(){i.src=b},0);return d};e.youtube.canPlayType=l})(window,Popcorn);(function(p,e){e.player("soundcloud",{_canPlayType:function(l,d){return typeof d==="string"&&e.HTMLSoundCloudAudioElement._canPlaySrc(d)&&l.toLowerCase()!=="audio"}});e.soundcloud=function(l,d,b){typeof console!=="undefined"&&console.warn&&console.warn("Deprecated player 'soundcloud'. Please use Popcorn.HTMLSoundCloudAudioElement directly.");var h=e.HTMLSoundCloudAudioElement(l);l=e(h,b);setTimeout(function(){h.src=d},0);return l}})(window,Popcorn);
--- a/src/ldt/ldt/static/ldt/js/raphael-min.js Fri Sep 18 16:10:29 2015 +0200
+++ b/src/ldt/ldt/static/ldt/js/raphael-min.js Fri Oct 02 10:24:05 2015 +0200
@@ -1,10 +1,12 @@
// ┌────────────────────────────────────────────────────────────────────┐ \\
-// │ Raphaël 2.1.0 - JavaScript Vector Library │ \\
+// │ Raphaël 2.1.4 - JavaScript Vector Library │ \\
// ├────────────────────────────────────────────────────────────────────┤ \\
// │ Copyright © 2008-2012 Dmitry Baranovskiy (http://raphaeljs.com) │ \\
// │ Copyright © 2008-2012 Sencha Labs (http://sencha.com) │ \\
// ├────────────────────────────────────────────────────────────────────┤ \\
// │ Licensed under the MIT (http://raphaeljs.com/license.html) license.│ \\
// └────────────────────────────────────────────────────────────────────┘ \\
+!function(a,b){"function"==typeof define&&define.amd?define("eve",function(){return b()}):"object"==typeof exports?module.exports=b():a.eve=b()}(this,function(){var a,b,c="0.4.2",d="hasOwnProperty",e=/[\.\/]/,f="*",g=function(){},h=function(a,b){return a-b},i={n:{}},j=function(c,d){c=String(c);var e,f=b,g=Array.prototype.slice.call(arguments,2),i=j.listeners(c),k=0,l=[],m={},n=[],o=a;a=c,b=0;for(var p=0,q=i.length;q>p;p++)"zIndex"in i[p]&&(l.push(i[p].zIndex),i[p].zIndex<0&&(m[i[p].zIndex]=i[p]));for(l.sort(h);l[k]<0;)if(e=m[l[k++]],n.push(e.apply(d,g)),b)return b=f,n;for(p=0;q>p;p++)if(e=i[p],"zIndex"in e)if(e.zIndex==l[k]){if(n.push(e.apply(d,g)),b)break;do if(k++,e=m[l[k]],e&&n.push(e.apply(d,g)),b)break;while(e)}else m[e.zIndex]=e;else if(n.push(e.apply(d,g)),b)break;return b=f,a=o,n.length?n:null};return j._events=i,j.listeners=function(a){var b,c,d,g,h,j,k,l,m=a.split(e),n=i,o=[n],p=[];for(g=0,h=m.length;h>g;g++){for(l=[],j=0,k=o.length;k>j;j++)for(n=o[j].n,c=[n[m[g]],n[f]],d=2;d--;)b=c[d],b&&(l.push(b),p=p.concat(b.f||[]));o=l}return p},j.on=function(a,b){if(a=String(a),"function"!=typeof b)return function(){};for(var c=a.split(e),d=i,f=0,h=c.length;h>f;f++)d=d.n,d=d.hasOwnProperty(c[f])&&d[c[f]]||(d[c[f]]={n:{}});for(d.f=d.f||[],f=0,h=d.f.length;h>f;f++)if(d.f[f]==b)return g;return d.f.push(b),function(a){+a==+a&&(b.zIndex=+a)}},j.f=function(a){var b=[].slice.call(arguments,1);return function(){j.apply(null,[a,null].concat(b).concat([].slice.call(arguments,0)))}},j.stop=function(){b=1},j.nt=function(b){return b?new RegExp("(?:\\.|\\/|^)"+b+"(?:\\.|\\/|$)").test(a):a},j.nts=function(){return a.split(e)},j.off=j.unbind=function(a,b){if(!a)return void(j._events=i={n:{}});var c,g,h,k,l,m,n,o=a.split(e),p=[i];for(k=0,l=o.length;l>k;k++)for(m=0;m<p.length;m+=h.length-2){if(h=[m,1],c=p[m].n,o[k]!=f)c[o[k]]&&h.push(c[o[k]]);else for(g in c)c[d](g)&&h.push(c[g]);p.splice.apply(p,h)}for(k=0,l=p.length;l>k;k++)for(c=p[k];c.n;){if(b){if(c.f){for(m=0,n=c.f.length;n>m;m++)if(c.f[m]==b){c.f.splice(m,1);break}!c.f.length&&delete c.f}for(g in c.n)if(c.n[d](g)&&c.n[g].f){var q=c.n[g].f;for(m=0,n=q.length;n>m;m++)if(q[m]==b){q.splice(m,1);break}!q.length&&delete c.n[g].f}}else{delete c.f;for(g in c.n)c.n[d](g)&&c.n[g].f&&delete c.n[g].f}c=c.n}},j.once=function(a,b){var c=function(){return j.unbind(a,c),b.apply(this,arguments)};return j.on(a,c)},j.version=c,j.toString=function(){return"You are running Eve "+c},j}),function(a,b){"function"==typeof define&&define.amd?define("raphael.core",["eve"],function(a){return b(a)}):"object"==typeof exports?module.exports=b(require("eve")):a.Raphael=b(a.eve)}(this,function(a){function b(c){if(b.is(c,"function"))return t?c():a.on("raphael.DOMload",c);if(b.is(c,U))return b._engine.create[C](b,c.splice(0,3+b.is(c[0],S))).add(c);var d=Array.prototype.slice.call(arguments,0);if(b.is(d[d.length-1],"function")){var e=d.pop();return t?e.call(b._engine.create[C](b,d)):a.on("raphael.DOMload",function(){e.call(b._engine.create[C](b,d))})}return b._engine.create[C](b,arguments)}function c(a){if("function"==typeof a||Object(a)!==a)return a;var b=new a.constructor;for(var d in a)a[y](d)&&(b[d]=c(a[d]));return b}function d(a,b){for(var c=0,d=a.length;d>c;c++)if(a[c]===b)return a.push(a.splice(c,1)[0])}function e(a,b,c){function e(){var f=Array.prototype.slice.call(arguments,0),g=f.join("␀"),h=e.cache=e.cache||{},i=e.count=e.count||[];return h[y](g)?(d(i,g),c?c(h[g]):h[g]):(i.length>=1e3&&delete h[i.shift()],i.push(g),h[g]=a[C](b,f),c?c(h[g]):h[g])}return e}function f(){return this.hex}function g(a,b){for(var c=[],d=0,e=a.length;e-2*!b>d;d+=2){var f=[{x:+a[d-2],y:+a[d-1]},{x:+a[d],y:+a[d+1]},{x:+a[d+2],y:+a[d+3]},{x:+a[d+4],y:+a[d+5]}];b?d?e-4==d?f[3]={x:+a[0],y:+a[1]}:e-2==d&&(f[2]={x:+a[0],y:+a[1]},f[3]={x:+a[2],y:+a[3]}):f[0]={x:+a[e-2],y:+a[e-1]}:e-4==d?f[3]=f[2]:d||(f[0]={x:+a[d],y:+a[d+1]}),c.push(["C",(-f[0].x+6*f[1].x+f[2].x)/6,(-f[0].y+6*f[1].y+f[2].y)/6,(f[1].x+6*f[2].x-f[3].x)/6,(f[1].y+6*f[2].y-f[3].y)/6,f[2].x,f[2].y])}return c}function h(a,b,c,d,e){var f=-3*b+9*c-9*d+3*e,g=a*f+6*b-12*c+6*d;return a*g-3*b+3*c}function i(a,b,c,d,e,f,g,i,j){null==j&&(j=1),j=j>1?1:0>j?0:j;for(var k=j/2,l=12,m=[-.1252,.1252,-.3678,.3678,-.5873,.5873,-.7699,.7699,-.9041,.9041,-.9816,.9816],n=[.2491,.2491,.2335,.2335,.2032,.2032,.1601,.1601,.1069,.1069,.0472,.0472],o=0,p=0;l>p;p++){var q=k*m[p]+k,r=h(q,a,c,e,g),s=h(q,b,d,f,i),t=r*r+s*s;o+=n[p]*M.sqrt(t)}return k*o}function j(a,b,c,d,e,f,g,h,j){if(!(0>j||i(a,b,c,d,e,f,g,h)<j)){var k,l=1,m=l/2,n=l-m,o=.01;for(k=i(a,b,c,d,e,f,g,h,n);P(k-j)>o;)m/=2,n+=(j>k?1:-1)*m,k=i(a,b,c,d,e,f,g,h,n);return n}}function k(a,b,c,d,e,f,g,h){if(!(N(a,c)<O(e,g)||O(a,c)>N(e,g)||N(b,d)<O(f,h)||O(b,d)>N(f,h))){var i=(a*d-b*c)*(e-g)-(a-c)*(e*h-f*g),j=(a*d-b*c)*(f-h)-(b-d)*(e*h-f*g),k=(a-c)*(f-h)-(b-d)*(e-g);if(k){var l=i/k,m=j/k,n=+l.toFixed(2),o=+m.toFixed(2);if(!(n<+O(a,c).toFixed(2)||n>+N(a,c).toFixed(2)||n<+O(e,g).toFixed(2)||n>+N(e,g).toFixed(2)||o<+O(b,d).toFixed(2)||o>+N(b,d).toFixed(2)||o<+O(f,h).toFixed(2)||o>+N(f,h).toFixed(2)))return{x:l,y:m}}}}function l(a,c,d){var e=b.bezierBBox(a),f=b.bezierBBox(c);if(!b.isBBoxIntersect(e,f))return d?0:[];for(var g=i.apply(0,a),h=i.apply(0,c),j=N(~~(g/5),1),l=N(~~(h/5),1),m=[],n=[],o={},p=d?0:[],q=0;j+1>q;q++){var r=b.findDotsAtSegment.apply(b,a.concat(q/j));m.push({x:r.x,y:r.y,t:q/j})}for(q=0;l+1>q;q++)r=b.findDotsAtSegment.apply(b,c.concat(q/l)),n.push({x:r.x,y:r.y,t:q/l});for(q=0;j>q;q++)for(var s=0;l>s;s++){var t=m[q],u=m[q+1],v=n[s],w=n[s+1],x=P(u.x-t.x)<.001?"y":"x",y=P(w.x-v.x)<.001?"y":"x",z=k(t.x,t.y,u.x,u.y,v.x,v.y,w.x,w.y);if(z){if(o[z.x.toFixed(4)]==z.y.toFixed(4))continue;o[z.x.toFixed(4)]=z.y.toFixed(4);var A=t.t+P((z[x]-t[x])/(u[x]-t[x]))*(u.t-t.t),B=v.t+P((z[y]-v[y])/(w[y]-v[y]))*(w.t-v.t);A>=0&&1.001>=A&&B>=0&&1.001>=B&&(d?p++:p.push({x:z.x,y:z.y,t1:O(A,1),t2:O(B,1)}))}}return p}function m(a,c,d){a=b._path2curve(a),c=b._path2curve(c);for(var e,f,g,h,i,j,k,m,n,o,p=d?0:[],q=0,r=a.length;r>q;q++){var s=a[q];if("M"==s[0])e=i=s[1],f=j=s[2];else{"C"==s[0]?(n=[e,f].concat(s.slice(1)),e=n[6],f=n[7]):(n=[e,f,e,f,i,j,i,j],e=i,f=j);for(var t=0,u=c.length;u>t;t++){var v=c[t];if("M"==v[0])g=k=v[1],h=m=v[2];else{"C"==v[0]?(o=[g,h].concat(v.slice(1)),g=o[6],h=o[7]):(o=[g,h,g,h,k,m,k,m],g=k,h=m);var w=l(n,o,d);if(d)p+=w;else{for(var x=0,y=w.length;y>x;x++)w[x].segment1=q,w[x].segment2=t,w[x].bez1=n,w[x].bez2=o;p=p.concat(w)}}}}}return p}function n(a,b,c,d,e,f){null!=a?(this.a=+a,this.b=+b,this.c=+c,this.d=+d,this.e=+e,this.f=+f):(this.a=1,this.b=0,this.c=0,this.d=1,this.e=0,this.f=0)}function o(){return this.x+G+this.y+G+this.width+" × "+this.height}function p(a,b,c,d,e,f){function g(a){return((l*a+k)*a+j)*a}function h(a,b){var c=i(a,b);return((o*c+n)*c+m)*c}function i(a,b){var c,d,e,f,h,i;for(e=a,i=0;8>i;i++){if(f=g(e)-a,P(f)<b)return e;if(h=(3*l*e+2*k)*e+j,P(h)<1e-6)break;e-=f/h}if(c=0,d=1,e=a,c>e)return c;if(e>d)return d;for(;d>c;){if(f=g(e),P(f-a)<b)return e;a>f?c=e:d=e,e=(d-c)/2+c}return e}var j=3*b,k=3*(d-b)-j,l=1-j-k,m=3*c,n=3*(e-c)-m,o=1-m-n;return h(a,1/(200*f))}function q(a,b){var c=[],d={};if(this.ms=b,this.times=1,a){for(var e in a)a[y](e)&&(d[$(e)]=a[e],c.push($(e)));c.sort(ka)}this.anim=d,this.top=c[c.length-1],this.percents=c}function r(c,d,e,f,g,h){e=$(e);var i,j,k,l,m,o,q=c.ms,r={},s={},t={};if(f)for(w=0,x=fb.length;x>w;w++){var u=fb[w];if(u.el.id==d.id&&u.anim==c){u.percent!=e?(fb.splice(w,1),k=1):j=u,d.attr(u.totalOrigin);break}}else f=+s;for(var w=0,x=c.percents.length;x>w;w++){if(c.percents[w]==e||c.percents[w]>f*c.top){e=c.percents[w],m=c.percents[w-1]||0,q=q/c.top*(e-m),l=c.percents[w+1],i=c.anim[e];break}f&&d.attr(c.anim[c.percents[w]])}if(i){if(j)j.initstatus=f,j.start=new Date-j.ms*f;else{for(var z in i)if(i[y](z)&&(ca[y](z)||d.paper.customAttributes[y](z)))switch(r[z]=d.attr(z),null==r[z]&&(r[z]=ba[z]),s[z]=i[z],ca[z]){case S:t[z]=(s[z]-r[z])/q;break;case"colour":r[z]=b.getRGB(r[z]);var A=b.getRGB(s[z]);t[z]={r:(A.r-r[z].r)/q,g:(A.g-r[z].g)/q,b:(A.b-r[z].b)/q};break;case"path":var B=Ia(r[z],s[z]),C=B[1];for(r[z]=B[0],t[z]=[],w=0,x=r[z].length;x>w;w++){t[z][w]=[0];for(var E=1,F=r[z][w].length;F>E;E++)t[z][w][E]=(C[w][E]-r[z][w][E])/q}break;case"transform":var G=d._,J=Na(G[z],s[z]);if(J)for(r[z]=J.from,s[z]=J.to,t[z]=[],t[z].real=!0,w=0,x=r[z].length;x>w;w++)for(t[z][w]=[r[z][w][0]],E=1,F=r[z][w].length;F>E;E++)t[z][w][E]=(s[z][w][E]-r[z][w][E])/q;else{var K=d.matrix||new n,L={_:{transform:G.transform},getBBox:function(){return d.getBBox(1)}};r[z]=[K.a,K.b,K.c,K.d,K.e,K.f],La(L,s[z]),s[z]=L._.transform,t[z]=[(L.matrix.a-K.a)/q,(L.matrix.b-K.b)/q,(L.matrix.c-K.c)/q,(L.matrix.d-K.d)/q,(L.matrix.e-K.e)/q,(L.matrix.f-K.f)/q]}break;case"csv":var M=H(i[z])[I](v),N=H(r[z])[I](v);if("clip-rect"==z)for(r[z]=N,t[z]=[],w=N.length;w--;)t[z][w]=(M[w]-r[z][w])/q;s[z]=M;break;default:for(M=[][D](i[z]),N=[][D](r[z]),t[z]=[],w=d.paper.customAttributes[z].length;w--;)t[z][w]=((M[w]||0)-(N[w]||0))/q}var O=i.easing,P=b.easing_formulas[O];if(!P)if(P=H(O).match(Y),P&&5==P.length){var Q=P;P=function(a){return p(a,+Q[1],+Q[2],+Q[3],+Q[4],q)}}else P=la;if(o=i.start||c.start||+new Date,u={anim:c,percent:e,timestamp:o,start:o+(c.del||0),status:0,initstatus:f||0,stop:!1,ms:q,easing:P,from:r,diff:t,to:s,el:d,callback:i.callback,prev:m,next:l,repeat:h||c.times,origin:d.attr(),totalOrigin:g},fb.push(u),f&&!j&&!k&&(u.stop=!0,u.start=new Date-q*f,1==fb.length))return hb();k&&(u.start=new Date-u.ms*f),1==fb.length&&gb(hb)}a("raphael.anim.start."+d.id,d,c)}}function s(a){for(var b=0;b<fb.length;b++)fb[b].el.paper==a&&fb.splice(b--,1)}b.version="2.1.4",b.eve=a;var t,u,v=/[, ]+/,w={circle:1,rect:1,path:1,ellipse:1,text:1,image:1},x=/\{(\d+)\}/g,y="hasOwnProperty",z={doc:document,win:window},A={was:Object.prototype[y].call(z.win,"Raphael"),is:z.win.Raphael},B=function(){this.ca=this.customAttributes={}},C="apply",D="concat",E="ontouchstart"in z.win||z.win.DocumentTouch&&z.doc instanceof DocumentTouch,F="",G=" ",H=String,I="split",J="click dblclick mousedown mousemove mouseout mouseover mouseup touchstart touchmove touchend touchcancel"[I](G),K={mousedown:"touchstart",mousemove:"touchmove",mouseup:"touchend"},L=H.prototype.toLowerCase,M=Math,N=M.max,O=M.min,P=M.abs,Q=M.pow,R=M.PI,S="number",T="string",U="array",V=Object.prototype.toString,W=(b._ISURL=/^url\(['"]?(.+?)['"]?\)$/i,/^\s*((#[a-f\d]{6})|(#[a-f\d]{3})|rgba?\(\s*([\d\.]+%?\s*,\s*[\d\.]+%?\s*,\s*[\d\.]+%?(?:\s*,\s*[\d\.]+%?)?)\s*\)|hsba?\(\s*([\d\.]+(?:deg|\xb0|%)?\s*,\s*[\d\.]+%?\s*,\s*[\d\.]+(?:%?\s*,\s*[\d\.]+)?)%?\s*\)|hsla?\(\s*([\d\.]+(?:deg|\xb0|%)?\s*,\s*[\d\.]+%?\s*,\s*[\d\.]+(?:%?\s*,\s*[\d\.]+)?)%?\s*\))\s*$/i),X={NaN:1,Infinity:1,"-Infinity":1},Y=/^(?:cubic-)?bezier\(([^,]+),([^,]+),([^,]+),([^\)]+)\)/,Z=M.round,$=parseFloat,_=parseInt,aa=H.prototype.toUpperCase,ba=b._availableAttrs={"arrow-end":"none","arrow-start":"none",blur:0,"clip-rect":"0 0 1e9 1e9",cursor:"default",cx:0,cy:0,fill:"#fff","fill-opacity":1,font:'10px "Arial"',"font-family":'"Arial"',"font-size":"10","font-style":"normal","font-weight":400,gradient:0,height:0,href:"http://raphaeljs.com/","letter-spacing":0,opacity:1,path:"M0,0",r:0,rx:0,ry:0,src:"",stroke:"#000","stroke-dasharray":"","stroke-linecap":"butt","stroke-linejoin":"butt","stroke-miterlimit":0,"stroke-opacity":1,"stroke-width":1,target:"_blank","text-anchor":"middle",title:"Raphael",transform:"",width:0,x:0,y:0},ca=b._availableAnimAttrs={blur:S,"clip-rect":"csv",cx:S,cy:S,fill:"colour","fill-opacity":S,"font-size":S,height:S,opacity:S,path:"path",r:S,rx:S,ry:S,stroke:"colour","stroke-opacity":S,"stroke-width":S,transform:"transform",width:S,x:S,y:S},da=/[\x09\x0a\x0b\x0c\x0d\x20\xa0\u1680\u180e\u2000\u2001\u2002\u2003\u2004\u2005\u2006\u2007\u2008\u2009\u200a\u202f\u205f\u3000\u2028\u2029]*,[\x09\x0a\x0b\x0c\x0d\x20\xa0\u1680\u180e\u2000\u2001\u2002\u2003\u2004\u2005\u2006\u2007\u2008\u2009\u200a\u202f\u205f\u3000\u2028\u2029]*/,ea={hs:1,rg:1},fa=/,?([achlmqrstvxz]),?/gi,ga=/([achlmrqstvz])[\x09\x0a\x0b\x0c\x0d\x20\xa0\u1680\u180e\u2000\u2001\u2002\u2003\u2004\u2005\u2006\u2007\u2008\u2009\u200a\u202f\u205f\u3000\u2028\u2029,]*((-?\d*\.?\d*(?:e[\-+]?\d+)?[\x09\x0a\x0b\x0c\x0d\x20\xa0\u1680\u180e\u2000\u2001\u2002\u2003\u2004\u2005\u2006\u2007\u2008\u2009\u200a\u202f\u205f\u3000\u2028\u2029]*,?[\x09\x0a\x0b\x0c\x0d\x20\xa0\u1680\u180e\u2000\u2001\u2002\u2003\u2004\u2005\u2006\u2007\u2008\u2009\u200a\u202f\u205f\u3000\u2028\u2029]*)+)/gi,ha=/([rstm])[\x09\x0a\x0b\x0c\x0d\x20\xa0\u1680\u180e\u2000\u2001\u2002\u2003\u2004\u2005\u2006\u2007\u2008\u2009\u200a\u202f\u205f\u3000\u2028\u2029,]*((-?\d*\.?\d*(?:e[\-+]?\d+)?[\x09\x0a\x0b\x0c\x0d\x20\xa0\u1680\u180e\u2000\u2001\u2002\u2003\u2004\u2005\u2006\u2007\u2008\u2009\u200a\u202f\u205f\u3000\u2028\u2029]*,?[\x09\x0a\x0b\x0c\x0d\x20\xa0\u1680\u180e\u2000\u2001\u2002\u2003\u2004\u2005\u2006\u2007\u2008\u2009\u200a\u202f\u205f\u3000\u2028\u2029]*)+)/gi,ia=/(-?\d*\.?\d*(?:e[\-+]?\d+)?)[\x09\x0a\x0b\x0c\x0d\x20\xa0\u1680\u180e\u2000\u2001\u2002\u2003\u2004\u2005\u2006\u2007\u2008\u2009\u200a\u202f\u205f\u3000\u2028\u2029]*,?[\x09\x0a\x0b\x0c\x0d\x20\xa0\u1680\u180e\u2000\u2001\u2002\u2003\u2004\u2005\u2006\u2007\u2008\u2009\u200a\u202f\u205f\u3000\u2028\u2029]*/gi,ja=(b._radial_gradient=/^r(?:\(([^,]+?)[\x09\x0a\x0b\x0c\x0d\x20\xa0\u1680\u180e\u2000\u2001\u2002\u2003\u2004\u2005\u2006\u2007\u2008\u2009\u200a\u202f\u205f\u3000\u2028\u2029]*,[\x09\x0a\x0b\x0c\x0d\x20\xa0\u1680\u180e\u2000\u2001\u2002\u2003\u2004\u2005\u2006\u2007\u2008\u2009\u200a\u202f\u205f\u3000\u2028\u2029]*([^\)]+?)\))?/,{}),ka=function(a,b){return $(a)-$(b)},la=function(a){return a},ma=b._rectPath=function(a,b,c,d,e){return e?[["M",a+e,b],["l",c-2*e,0],["a",e,e,0,0,1,e,e],["l",0,d-2*e],["a",e,e,0,0,1,-e,e],["l",2*e-c,0],["a",e,e,0,0,1,-e,-e],["l",0,2*e-d],["a",e,e,0,0,1,e,-e],["z"]]:[["M",a,b],["l",c,0],["l",0,d],["l",-c,0],["z"]]},na=function(a,b,c,d){return null==d&&(d=c),[["M",a,b],["m",0,-d],["a",c,d,0,1,1,0,2*d],["a",c,d,0,1,1,0,-2*d],["z"]]},oa=b._getPath={path:function(a){return a.attr("path")},circle:function(a){var b=a.attrs;return na(b.cx,b.cy,b.r)},ellipse:function(a){var b=a.attrs;return na(b.cx,b.cy,b.rx,b.ry)},rect:function(a){var b=a.attrs;return ma(b.x,b.y,b.width,b.height,b.r)},image:function(a){var b=a.attrs;return ma(b.x,b.y,b.width,b.height)},text:function(a){var b=a._getBBox();return ma(b.x,b.y,b.width,b.height)},set:function(a){var b=a._getBBox();return ma(b.x,b.y,b.width,b.height)}},pa=b.mapPath=function(a,b){if(!b)return a;var c,d,e,f,g,h,i;for(a=Ia(a),e=0,g=a.length;g>e;e++)for(i=a[e],f=1,h=i.length;h>f;f+=2)c=b.x(i[f],i[f+1]),d=b.y(i[f],i[f+1]),i[f]=c,i[f+1]=d;return a};if(b._g=z,b.type=z.win.SVGAngle||z.doc.implementation.hasFeature("http://www.w3.org/TR/SVG11/feature#BasicStructure","1.1")?"SVG":"VML","VML"==b.type){var qa,ra=z.doc.createElement("div");if(ra.innerHTML='<v:shape adj="1"/>',qa=ra.firstChild,qa.style.behavior="url(#default#VML)",!qa||"object"!=typeof qa.adj)return b.type=F;ra=null}b.svg=!(b.vml="VML"==b.type),b._Paper=B,b.fn=u=B.prototype=b.prototype,b._id=0,b._oid=0,b.is=function(a,b){return b=L.call(b),"finite"==b?!X[y](+a):"array"==b?a instanceof Array:"null"==b&&null===a||b==typeof a&&null!==a||"object"==b&&a===Object(a)||"array"==b&&Array.isArray&&Array.isArray(a)||V.call(a).slice(8,-1).toLowerCase()==b},b.angle=function(a,c,d,e,f,g){if(null==f){var h=a-d,i=c-e;return h||i?(180+180*M.atan2(-i,-h)/R+360)%360:0}return b.angle(a,c,f,g)-b.angle(d,e,f,g)},b.rad=function(a){return a%360*R/180},b.deg=function(a){return Math.round(180*a/R%360*1e3)/1e3},b.snapTo=function(a,c,d){if(d=b.is(d,"finite")?d:10,b.is(a,U)){for(var e=a.length;e--;)if(P(a[e]-c)<=d)return a[e]}else{a=+a;var f=c%a;if(d>f)return c-f;if(f>a-d)return c-f+a}return c};b.createUUID=function(a,b){return function(){return"xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx".replace(a,b).toUpperCase()}}(/[xy]/g,function(a){var b=16*M.random()|0,c="x"==a?b:3&b|8;return c.toString(16)});b.setWindow=function(c){a("raphael.setWindow",b,z.win,c),z.win=c,z.doc=z.win.document,b._engine.initWin&&b._engine.initWin(z.win)};var sa=function(a){if(b.vml){var c,d=/^\s+|\s+$/g;try{var f=new ActiveXObject("htmlfile");f.write("<body>"),f.close(),c=f.body}catch(g){c=createPopup().document.body}var h=c.createTextRange();sa=e(function(a){try{c.style.color=H(a).replace(d,F);var b=h.queryCommandValue("ForeColor");return b=(255&b)<<16|65280&b|(16711680&b)>>>16,"#"+("000000"+b.toString(16)).slice(-6)}catch(e){return"none"}})}else{var i=z.doc.createElement("i");i.title="Raphaël Colour Picker",i.style.display="none",z.doc.body.appendChild(i),sa=e(function(a){return i.style.color=a,z.doc.defaultView.getComputedStyle(i,F).getPropertyValue("color")})}return sa(a)},ta=function(){return"hsb("+[this.h,this.s,this.b]+")"},ua=function(){return"hsl("+[this.h,this.s,this.l]+")"},va=function(){return this.hex},wa=function(a,c,d){if(null==c&&b.is(a,"object")&&"r"in a&&"g"in a&&"b"in a&&(d=a.b,c=a.g,a=a.r),null==c&&b.is(a,T)){var e=b.getRGB(a);a=e.r,c=e.g,d=e.b}return(a>1||c>1||d>1)&&(a/=255,c/=255,d/=255),[a,c,d]},xa=function(a,c,d,e){a*=255,c*=255,d*=255;var f={r:a,g:c,b:d,hex:b.rgb(a,c,d),toString:va};return b.is(e,"finite")&&(f.opacity=e),f};b.color=function(a){var c;return b.is(a,"object")&&"h"in a&&"s"in a&&"b"in a?(c=b.hsb2rgb(a),a.r=c.r,a.g=c.g,a.b=c.b,a.hex=c.hex):b.is(a,"object")&&"h"in a&&"s"in a&&"l"in a?(c=b.hsl2rgb(a),a.r=c.r,a.g=c.g,a.b=c.b,a.hex=c.hex):(b.is(a,"string")&&(a=b.getRGB(a)),b.is(a,"object")&&"r"in a&&"g"in a&&"b"in a?(c=b.rgb2hsl(a),a.h=c.h,a.s=c.s,a.l=c.l,c=b.rgb2hsb(a),a.v=c.b):(a={hex:"none"},a.r=a.g=a.b=a.h=a.s=a.v=a.l=-1)),a.toString=va,a},b.hsb2rgb=function(a,b,c,d){this.is(a,"object")&&"h"in a&&"s"in a&&"b"in a&&(c=a.b,b=a.s,d=a.o,a=a.h),a*=360;var e,f,g,h,i;return a=a%360/60,i=c*b,h=i*(1-P(a%2-1)),e=f=g=c-i,a=~~a,e+=[i,h,0,0,h,i][a],f+=[h,i,i,h,0,0][a],g+=[0,0,h,i,i,h][a],xa(e,f,g,d)},b.hsl2rgb=function(a,b,c,d){this.is(a,"object")&&"h"in a&&"s"in a&&"l"in a&&(c=a.l,b=a.s,a=a.h),(a>1||b>1||c>1)&&(a/=360,b/=100,c/=100),a*=360;var e,f,g,h,i;return a=a%360/60,i=2*b*(.5>c?c:1-c),h=i*(1-P(a%2-1)),e=f=g=c-i/2,a=~~a,e+=[i,h,0,0,h,i][a],f+=[h,i,i,h,0,0][a],g+=[0,0,h,i,i,h][a],xa(e,f,g,d)},b.rgb2hsb=function(a,b,c){c=wa(a,b,c),a=c[0],b=c[1],c=c[2];var d,e,f,g;return f=N(a,b,c),g=f-O(a,b,c),d=0==g?null:f==a?(b-c)/g:f==b?(c-a)/g+2:(a-b)/g+4,d=(d+360)%6*60/360,e=0==g?0:g/f,{h:d,s:e,b:f,toString:ta}},b.rgb2hsl=function(a,b,c){c=wa(a,b,c),a=c[0],b=c[1],c=c[2];var d,e,f,g,h,i;return g=N(a,b,c),h=O(a,b,c),i=g-h,d=0==i?null:g==a?(b-c)/i:g==b?(c-a)/i+2:(a-b)/i+4,d=(d+360)%6*60/360,f=(g+h)/2,e=0==i?0:.5>f?i/(2*f):i/(2-2*f),{h:d,s:e,l:f,toString:ua}},b._path2string=function(){return this.join(",").replace(fa,"$1")};b._preload=function(a,b){var c=z.doc.createElement("img");c.style.cssText="position:absolute;left:-9999em;top:-9999em",c.onload=function(){b.call(this),this.onload=null,z.doc.body.removeChild(this)},c.onerror=function(){z.doc.body.removeChild(this)},z.doc.body.appendChild(c),c.src=a};b.getRGB=e(function(a){if(!a||(a=H(a)).indexOf("-")+1)return{r:-1,g:-1,b:-1,hex:"none",error:1,toString:f};if("none"==a)return{r:-1,g:-1,b:-1,hex:"none",toString:f};!(ea[y](a.toLowerCase().substring(0,2))||"#"==a.charAt())&&(a=sa(a));var c,d,e,g,h,i,j=a.match(W);return j?(j[2]&&(e=_(j[2].substring(5),16),d=_(j[2].substring(3,5),16),c=_(j[2].substring(1,3),16)),j[3]&&(e=_((h=j[3].charAt(3))+h,16),d=_((h=j[3].charAt(2))+h,16),c=_((h=j[3].charAt(1))+h,16)),j[4]&&(i=j[4][I](da),c=$(i[0]),"%"==i[0].slice(-1)&&(c*=2.55),d=$(i[1]),"%"==i[1].slice(-1)&&(d*=2.55),e=$(i[2]),"%"==i[2].slice(-1)&&(e*=2.55),"rgba"==j[1].toLowerCase().slice(0,4)&&(g=$(i[3])),i[3]&&"%"==i[3].slice(-1)&&(g/=100)),j[5]?(i=j[5][I](da),c=$(i[0]),"%"==i[0].slice(-1)&&(c*=2.55),d=$(i[1]),"%"==i[1].slice(-1)&&(d*=2.55),e=$(i[2]),"%"==i[2].slice(-1)&&(e*=2.55),("deg"==i[0].slice(-3)||"°"==i[0].slice(-1))&&(c/=360),"hsba"==j[1].toLowerCase().slice(0,4)&&(g=$(i[3])),i[3]&&"%"==i[3].slice(-1)&&(g/=100),b.hsb2rgb(c,d,e,g)):j[6]?(i=j[6][I](da),c=$(i[0]),"%"==i[0].slice(-1)&&(c*=2.55),d=$(i[1]),"%"==i[1].slice(-1)&&(d*=2.55),e=$(i[2]),"%"==i[2].slice(-1)&&(e*=2.55),("deg"==i[0].slice(-3)||"°"==i[0].slice(-1))&&(c/=360),"hsla"==j[1].toLowerCase().slice(0,4)&&(g=$(i[3])),i[3]&&"%"==i[3].slice(-1)&&(g/=100),b.hsl2rgb(c,d,e,g)):(j={r:c,g:d,b:e,toString:f},j.hex="#"+(16777216|e|d<<8|c<<16).toString(16).slice(1),b.is(g,"finite")&&(j.opacity=g),j)):{r:-1,g:-1,b:-1,hex:"none",error:1,toString:f}},b),b.hsb=e(function(a,c,d){return b.hsb2rgb(a,c,d).hex}),b.hsl=e(function(a,c,d){return b.hsl2rgb(a,c,d).hex}),b.rgb=e(function(a,b,c){function d(a){return a+.5|0}return"#"+(16777216|d(c)|d(b)<<8|d(a)<<16).toString(16).slice(1)}),b.getColor=function(a){var b=this.getColor.start=this.getColor.start||{h:0,s:1,b:a||.75},c=this.hsb2rgb(b.h,b.s,b.b);return b.h+=.075,b.h>1&&(b.h=0,b.s-=.2,b.s<=0&&(this.getColor.start={h:0,s:1,b:b.b})),c.hex},b.getColor.reset=function(){delete this.start},b.parsePathString=function(a){if(!a)return null;var c=ya(a);if(c.arr)return Aa(c.arr);var d={a:7,c:6,h:1,l:2,m:2,r:4,q:4,s:4,t:2,v:1,z:0},e=[];return b.is(a,U)&&b.is(a[0],U)&&(e=Aa(a)),e.length||H(a).replace(ga,function(a,b,c){var f=[],g=b.toLowerCase();if(c.replace(ia,function(a,b){b&&f.push(+b)}),"m"==g&&f.length>2&&(e.push([b][D](f.splice(0,2))),g="l",b="m"==b?"l":"L"),"r"==g)e.push([b][D](f));else for(;f.length>=d[g]&&(e.push([b][D](f.splice(0,d[g]))),d[g]););}),e.toString=b._path2string,c.arr=Aa(e),e},b.parseTransformString=e(function(a){if(!a)return null;var c=[];return b.is(a,U)&&b.is(a[0],U)&&(c=Aa(a)),c.length||H(a).replace(ha,function(a,b,d){{var e=[];L.call(b)}d.replace(ia,function(a,b){b&&e.push(+b)}),c.push([b][D](e))}),c.toString=b._path2string,c});var ya=function(a){var b=ya.ps=ya.ps||{};return b[a]?b[a].sleep=100:b[a]={sleep:100},setTimeout(function(){for(var c in b)b[y](c)&&c!=a&&(b[c].sleep--,!b[c].sleep&&delete b[c])}),b[a]};b.findDotsAtSegment=function(a,b,c,d,e,f,g,h,i){var j=1-i,k=Q(j,3),l=Q(j,2),m=i*i,n=m*i,o=k*a+3*l*i*c+3*j*i*i*e+n*g,p=k*b+3*l*i*d+3*j*i*i*f+n*h,q=a+2*i*(c-a)+m*(e-2*c+a),r=b+2*i*(d-b)+m*(f-2*d+b),s=c+2*i*(e-c)+m*(g-2*e+c),t=d+2*i*(f-d)+m*(h-2*f+d),u=j*a+i*c,v=j*b+i*d,w=j*e+i*g,x=j*f+i*h,y=90-180*M.atan2(q-s,r-t)/R;return(q>s||t>r)&&(y+=180),{x:o,y:p,m:{x:q,y:r},n:{x:s,y:t},start:{x:u,y:v},end:{x:w,y:x},alpha:y}},b.bezierBBox=function(a,c,d,e,f,g,h,i){b.is(a,"array")||(a=[a,c,d,e,f,g,h,i]);var j=Ha.apply(null,a);return{x:j.min.x,y:j.min.y,x2:j.max.x,y2:j.max.y,width:j.max.x-j.min.x,height:j.max.y-j.min.y}},b.isPointInsideBBox=function(a,b,c){return b>=a.x&&b<=a.x2&&c>=a.y&&c<=a.y2},b.isBBoxIntersect=function(a,c){var d=b.isPointInsideBBox;return d(c,a.x,a.y)||d(c,a.x2,a.y)||d(c,a.x,a.y2)||d(c,a.x2,a.y2)||d(a,c.x,c.y)||d(a,c.x2,c.y)||d(a,c.x,c.y2)||d(a,c.x2,c.y2)||(a.x<c.x2&&a.x>c.x||c.x<a.x2&&c.x>a.x)&&(a.y<c.y2&&a.y>c.y||c.y<a.y2&&c.y>a.y)},b.pathIntersection=function(a,b){return m(a,b)},b.pathIntersectionNumber=function(a,b){return m(a,b,1)},b.isPointInsidePath=function(a,c,d){var e=b.pathBBox(a);return b.isPointInsideBBox(e,c,d)&&m(a,[["M",c,d],["H",e.x2+10]],1)%2==1},b._removedFactory=function(b){return function(){a("raphael.log",null,"Raphaël: you are calling to method “"+b+"” of removed object",b)}};var za=b.pathBBox=function(a){var b=ya(a);if(b.bbox)return c(b.bbox);if(!a)return{x:0,y:0,width:0,height:0,x2:0,y2:0};a=Ia(a);for(var d,e=0,f=0,g=[],h=[],i=0,j=a.length;j>i;i++)if(d=a[i],"M"==d[0])e=d[1],f=d[2],g.push(e),h.push(f);else{var k=Ha(e,f,d[1],d[2],d[3],d[4],d[5],d[6]);g=g[D](k.min.x,k.max.x),h=h[D](k.min.y,k.max.y),e=d[5],f=d[6]}var l=O[C](0,g),m=O[C](0,h),n=N[C](0,g),o=N[C](0,h),p=n-l,q=o-m,r={x:l,y:m,x2:n,y2:o,width:p,height:q,cx:l+p/2,cy:m+q/2};return b.bbox=c(r),r},Aa=function(a){var d=c(a);return d.toString=b._path2string,d},Ba=b._pathToRelative=function(a){var c=ya(a);if(c.rel)return Aa(c.rel);b.is(a,U)&&b.is(a&&a[0],U)||(a=b.parsePathString(a));var d=[],e=0,f=0,g=0,h=0,i=0;"M"==a[0][0]&&(e=a[0][1],f=a[0][2],g=e,h=f,i++,d.push(["M",e,f]));for(var j=i,k=a.length;k>j;j++){var l=d[j]=[],m=a[j];if(m[0]!=L.call(m[0]))switch(l[0]=L.call(m[0]),l[0]){case"a":l[1]=m[1],l[2]=m[2],l[3]=m[3],l[4]=m[4],l[5]=m[5],l[6]=+(m[6]-e).toFixed(3),l[7]=+(m[7]-f).toFixed(3);break;case"v":l[1]=+(m[1]-f).toFixed(3);break;case"m":g=m[1],h=m[2];default:for(var n=1,o=m.length;o>n;n++)l[n]=+(m[n]-(n%2?e:f)).toFixed(3)}else{l=d[j]=[],"m"==m[0]&&(g=m[1]+e,h=m[2]+f);for(var p=0,q=m.length;q>p;p++)d[j][p]=m[p]}var r=d[j].length;switch(d[j][0]){case"z":e=g,f=h;break;case"h":e+=+d[j][r-1];break;case"v":f+=+d[j][r-1];break;default:e+=+d[j][r-2],f+=+d[j][r-1]}}return d.toString=b._path2string,c.rel=Aa(d),d},Ca=b._pathToAbsolute=function(a){var c=ya(a);if(c.abs)return Aa(c.abs);if(b.is(a,U)&&b.is(a&&a[0],U)||(a=b.parsePathString(a)),!a||!a.length)return[["M",0,0]];var d=[],e=0,f=0,h=0,i=0,j=0;"M"==a[0][0]&&(e=+a[0][1],f=+a[0][2],h=e,i=f,j++,d[0]=["M",e,f]);for(var k,l,m=3==a.length&&"M"==a[0][0]&&"R"==a[1][0].toUpperCase()&&"Z"==a[2][0].toUpperCase(),n=j,o=a.length;o>n;n++){if(d.push(k=[]),l=a[n],l[0]!=aa.call(l[0]))switch(k[0]=aa.call(l[0]),k[0]){case"A":k[1]=l[1],k[2]=l[2],k[3]=l[3],k[4]=l[4],k[5]=l[5],k[6]=+(l[6]+e),k[7]=+(l[7]+f);break;case"V":k[1]=+l[1]+f;break;case"H":k[1]=+l[1]+e;break;case"R":for(var p=[e,f][D](l.slice(1)),q=2,r=p.length;r>q;q++)p[q]=+p[q]+e,p[++q]=+p[q]+f;d.pop(),d=d[D](g(p,m));break;case"M":h=+l[1]+e,i=+l[2]+f;default:for(q=1,r=l.length;r>q;q++)k[q]=+l[q]+(q%2?e:f)}else if("R"==l[0])p=[e,f][D](l.slice(1)),d.pop(),d=d[D](g(p,m)),k=["R"][D](l.slice(-2));else for(var s=0,t=l.length;t>s;s++)k[s]=l[s];switch(k[0]){case"Z":e=h,f=i;break;case"H":e=k[1];break;case"V":f=k[1];break;case"M":h=k[k.length-2],i=k[k.length-1];default:e=k[k.length-2],f=k[k.length-1]}}return d.toString=b._path2string,c.abs=Aa(d),d},Da=function(a,b,c,d){return[a,b,c,d,c,d]},Ea=function(a,b,c,d,e,f){var g=1/3,h=2/3;return[g*a+h*c,g*b+h*d,g*e+h*c,g*f+h*d,e,f]},Fa=function(a,b,c,d,f,g,h,i,j,k){var l,m=120*R/180,n=R/180*(+f||0),o=[],p=e(function(a,b,c){var d=a*M.cos(c)-b*M.sin(c),e=a*M.sin(c)+b*M.cos(c);return{x:d,y:e}});if(k)y=k[0],z=k[1],w=k[2],x=k[3];else{l=p(a,b,-n),a=l.x,b=l.y,l=p(i,j,-n),i=l.x,j=l.y;var q=(M.cos(R/180*f),M.sin(R/180*f),(a-i)/2),r=(b-j)/2,s=q*q/(c*c)+r*r/(d*d);s>1&&(s=M.sqrt(s),c=s*c,d=s*d);var t=c*c,u=d*d,v=(g==h?-1:1)*M.sqrt(P((t*u-t*r*r-u*q*q)/(t*r*r+u*q*q))),w=v*c*r/d+(a+i)/2,x=v*-d*q/c+(b+j)/2,y=M.asin(((b-x)/d).toFixed(9)),z=M.asin(((j-x)/d).toFixed(9));y=w>a?R-y:y,z=w>i?R-z:z,0>y&&(y=2*R+y),0>z&&(z=2*R+z),h&&y>z&&(y-=2*R),!h&&z>y&&(z-=2*R)}var A=z-y;if(P(A)>m){var B=z,C=i,E=j;z=y+m*(h&&z>y?1:-1),i=w+c*M.cos(z),j=x+d*M.sin(z),o=Fa(i,j,c,d,f,0,h,C,E,[z,B,w,x])}A=z-y;var F=M.cos(y),G=M.sin(y),H=M.cos(z),J=M.sin(z),K=M.tan(A/4),L=4/3*c*K,N=4/3*d*K,O=[a,b],Q=[a+L*G,b-N*F],S=[i+L*J,j-N*H],T=[i,j];if(Q[0]=2*O[0]-Q[0],Q[1]=2*O[1]-Q[1],k)return[Q,S,T][D](o);o=[Q,S,T][D](o).join()[I](",");for(var U=[],V=0,W=o.length;W>V;V++)U[V]=V%2?p(o[V-1],o[V],n).y:p(o[V],o[V+1],n).x;return U},Ga=function(a,b,c,d,e,f,g,h,i){var j=1-i;return{x:Q(j,3)*a+3*Q(j,2)*i*c+3*j*i*i*e+Q(i,3)*g,y:Q(j,3)*b+3*Q(j,2)*i*d+3*j*i*i*f+Q(i,3)*h}},Ha=e(function(a,b,c,d,e,f,g,h){var i,j=e-2*c+a-(g-2*e+c),k=2*(c-a)-2*(e-c),l=a-c,m=(-k+M.sqrt(k*k-4*j*l))/2/j,n=(-k-M.sqrt(k*k-4*j*l))/2/j,o=[b,h],p=[a,g];return P(m)>"1e12"&&(m=.5),P(n)>"1e12"&&(n=.5),m>0&&1>m&&(i=Ga(a,b,c,d,e,f,g,h,m),p.push(i.x),o.push(i.y)),n>0&&1>n&&(i=Ga(a,b,c,d,e,f,g,h,n),p.push(i.x),o.push(i.y)),j=f-2*d+b-(h-2*f+d),k=2*(d-b)-2*(f-d),l=b-d,m=(-k+M.sqrt(k*k-4*j*l))/2/j,n=(-k-M.sqrt(k*k-4*j*l))/2/j,P(m)>"1e12"&&(m=.5),P(n)>"1e12"&&(n=.5),m>0&&1>m&&(i=Ga(a,b,c,d,e,f,g,h,m),p.push(i.x),o.push(i.y)),n>0&&1>n&&(i=Ga(a,b,c,d,e,f,g,h,n),p.push(i.x),o.push(i.y)),{min:{x:O[C](0,p),y:O[C](0,o)},max:{x:N[C](0,p),y:N[C](0,o)}}}),Ia=b._path2curve=e(function(a,b){var c=!b&&ya(a);if(!b&&c.curve)return Aa(c.curve);for(var d=Ca(a),e=b&&Ca(b),f={x:0,y:0,bx:0,by:0,X:0,Y:0,qx:null,qy:null},g={x:0,y:0,bx:0,by:0,X:0,Y:0,qx:null,qy:null},h=(function(a,b,c){var d,e,f={T:1,Q:1};if(!a)return["C",b.x,b.y,b.x,b.y,b.x,b.y];switch(!(a[0]in f)&&(b.qx=b.qy=null),a[0]){case"M":b.X=a[1],b.Y=a[2];break;case"A":a=["C"][D](Fa[C](0,[b.x,b.y][D](a.slice(1))));break;case"S":"C"==c||"S"==c?(d=2*b.x-b.bx,e=2*b.y-b.by):(d=b.x,e=b.y),a=["C",d,e][D](a.slice(1));break;case"T":"Q"==c||"T"==c?(b.qx=2*b.x-b.qx,b.qy=2*b.y-b.qy):(b.qx=b.x,b.qy=b.y),a=["C"][D](Ea(b.x,b.y,b.qx,b.qy,a[1],a[2]));break;case"Q":b.qx=a[1],b.qy=a[2],a=["C"][D](Ea(b.x,b.y,a[1],a[2],a[3],a[4]));break;case"L":a=["C"][D](Da(b.x,b.y,a[1],a[2]));break;case"H":a=["C"][D](Da(b.x,b.y,a[1],b.y));break;case"V":a=["C"][D](Da(b.x,b.y,b.x,a[1]));break;case"Z":a=["C"][D](Da(b.x,b.y,b.X,b.Y))}return a}),i=function(a,b){if(a[b].length>7){a[b].shift();for(var c=a[b];c.length;)k[b]="A",e&&(l[b]="A"),a.splice(b++,0,["C"][D](c.splice(0,6)));a.splice(b,1),p=N(d.length,e&&e.length||0)}},j=function(a,b,c,f,g){a&&b&&"M"==a[g][0]&&"M"!=b[g][0]&&(b.splice(g,0,["M",f.x,f.y]),c.bx=0,c.by=0,c.x=a[g][1],c.y=a[g][2],p=N(d.length,e&&e.length||0))},k=[],l=[],m="",n="",o=0,p=N(d.length,e&&e.length||0);p>o;o++){d[o]&&(m=d[o][0]),"C"!=m&&(k[o]=m,o&&(n=k[o-1])),d[o]=h(d[o],f,n),"A"!=k[o]&&"C"==m&&(k[o]="C"),i(d,o),e&&(e[o]&&(m=e[o][0]),"C"!=m&&(l[o]=m,o&&(n=l[o-1])),e[o]=h(e[o],g,n),"A"!=l[o]&&"C"==m&&(l[o]="C"),i(e,o)),j(d,e,f,g,o),j(e,d,g,f,o);var q=d[o],r=e&&e[o],s=q.length,t=e&&r.length;f.x=q[s-2],f.y=q[s-1],f.bx=$(q[s-4])||f.x,f.by=$(q[s-3])||f.y,g.bx=e&&($(r[t-4])||g.x),g.by=e&&($(r[t-3])||g.y),g.x=e&&r[t-2],g.y=e&&r[t-1]}return e||(c.curve=Aa(d)),e?[d,e]:d},null,Aa),Ja=(b._parseDots=e(function(a){for(var c=[],d=0,e=a.length;e>d;d++){var f={},g=a[d].match(/^([^:]*):?([\d\.]*)/);if(f.color=b.getRGB(g[1]),f.color.error)return null;f.opacity=f.color.opacity,f.color=f.color.hex,g[2]&&(f.offset=g[2]+"%"),c.push(f)}for(d=1,e=c.length-1;e>d;d++)if(!c[d].offset){for(var h=$(c[d-1].offset||0),i=0,j=d+1;e>j;j++)if(c[j].offset){i=c[j].offset;break}i||(i=100,j=e),i=$(i);for(var k=(i-h)/(j-d+1);j>d;d++)h+=k,c[d].offset=h+"%"}return c}),b._tear=function(a,b){a==b.top&&(b.top=a.prev),a==b.bottom&&(b.bottom=a.next),a.next&&(a.next.prev=a.prev),a.prev&&(a.prev.next=a.next)}),Ka=(b._tofront=function(a,b){b.top!==a&&(Ja(a,b),a.next=null,a.prev=b.top,b.top.next=a,b.top=a)},b._toback=function(a,b){b.bottom!==a&&(Ja(a,b),a.next=b.bottom,a.prev=null,b.bottom.prev=a,b.bottom=a)},b._insertafter=function(a,b,c){Ja(a,c),b==c.top&&(c.top=a),b.next&&(b.next.prev=a),a.next=b.next,a.prev=b,b.next=a},b._insertbefore=function(a,b,c){Ja(a,c),b==c.bottom&&(c.bottom=a),b.prev&&(b.prev.next=a),a.prev=b.prev,b.prev=a,a.next=b},b.toMatrix=function(a,b){var c=za(a),d={_:{transform:F},getBBox:function(){return c}};return La(d,b),d.matrix}),La=(b.transformPath=function(a,b){return pa(a,Ka(a,b))},b._extractTransform=function(a,c){if(null==c)return a._.transform;c=H(c).replace(/\.{3}|\u2026/g,a._.transform||F);var d=b.parseTransformString(c),e=0,f=0,g=0,h=1,i=1,j=a._,k=new n;if(j.transform=d||[],d)for(var l=0,m=d.length;m>l;l++){var o,p,q,r,s,t=d[l],u=t.length,v=H(t[0]).toLowerCase(),w=t[0]!=v,x=w?k.invert():0;"t"==v&&3==u?w?(o=x.x(0,0),p=x.y(0,0),q=x.x(t[1],t[2]),r=x.y(t[1],t[2]),k.translate(q-o,r-p)):k.translate(t[1],t[2]):"r"==v?2==u?(s=s||a.getBBox(1),k.rotate(t[1],s.x+s.width/2,s.y+s.height/2),e+=t[1]):4==u&&(w?(q=x.x(t[2],t[3]),r=x.y(t[2],t[3]),k.rotate(t[1],q,r)):k.rotate(t[1],t[2],t[3]),e+=t[1]):"s"==v?2==u||3==u?(s=s||a.getBBox(1),k.scale(t[1],t[u-1],s.x+s.width/2,s.y+s.height/2),h*=t[1],i*=t[u-1]):5==u&&(w?(q=x.x(t[3],t[4]),r=x.y(t[3],t[4]),k.scale(t[1],t[2],q,r)):k.scale(t[1],t[2],t[3],t[4]),h*=t[1],i*=t[2]):"m"==v&&7==u&&k.add(t[1],t[2],t[3],t[4],t[5],t[6]),j.dirtyT=1,a.matrix=k}a.matrix=k,j.sx=h,j.sy=i,j.deg=e,j.dx=f=k.e,j.dy=g=k.f,1==h&&1==i&&!e&&j.bbox?(j.bbox.x+=+f,j.bbox.y+=+g):j.dirtyT=1}),Ma=function(a){var b=a[0];switch(b.toLowerCase()){case"t":return[b,0,0];case"m":return[b,1,0,0,1,0,0];case"r":return 4==a.length?[b,0,a[2],a[3]]:[b,0];case"s":return 5==a.length?[b,1,1,a[3],a[4]]:3==a.length?[b,1,1]:[b,1]}},Na=b._equaliseTransform=function(a,c){
+c=H(c).replace(/\.{3}|\u2026/g,a),a=b.parseTransformString(a)||[],c=b.parseTransformString(c)||[];for(var d,e,f,g,h=N(a.length,c.length),i=[],j=[],k=0;h>k;k++){if(f=a[k]||Ma(c[k]),g=c[k]||Ma(f),f[0]!=g[0]||"r"==f[0].toLowerCase()&&(f[2]!=g[2]||f[3]!=g[3])||"s"==f[0].toLowerCase()&&(f[3]!=g[3]||f[4]!=g[4]))return;for(i[k]=[],j[k]=[],d=0,e=N(f.length,g.length);e>d;d++)d in f&&(i[k][d]=f[d]),d in g&&(j[k][d]=g[d])}return{from:i,to:j}};b._getContainer=function(a,c,d,e){var f;return f=null!=e||b.is(a,"object")?a:z.doc.getElementById(a),null!=f?f.tagName?null==c?{container:f,width:f.style.pixelWidth||f.offsetWidth,height:f.style.pixelHeight||f.offsetHeight}:{container:f,width:c,height:d}:{container:1,x:a,y:c,width:d,height:e}:void 0},b.pathToRelative=Ba,b._engine={},b.path2curve=Ia,b.matrix=function(a,b,c,d,e,f){return new n(a,b,c,d,e,f)},function(a){function c(a){return a[0]*a[0]+a[1]*a[1]}function d(a){var b=M.sqrt(c(a));a[0]&&(a[0]/=b),a[1]&&(a[1]/=b)}a.add=function(a,b,c,d,e,f){var g,h,i,j,k=[[],[],[]],l=[[this.a,this.c,this.e],[this.b,this.d,this.f],[0,0,1]],m=[[a,c,e],[b,d,f],[0,0,1]];for(a&&a instanceof n&&(m=[[a.a,a.c,a.e],[a.b,a.d,a.f],[0,0,1]]),g=0;3>g;g++)for(h=0;3>h;h++){for(j=0,i=0;3>i;i++)j+=l[g][i]*m[i][h];k[g][h]=j}this.a=k[0][0],this.b=k[1][0],this.c=k[0][1],this.d=k[1][1],this.e=k[0][2],this.f=k[1][2]},a.invert=function(){var a=this,b=a.a*a.d-a.b*a.c;return new n(a.d/b,-a.b/b,-a.c/b,a.a/b,(a.c*a.f-a.d*a.e)/b,(a.b*a.e-a.a*a.f)/b)},a.clone=function(){return new n(this.a,this.b,this.c,this.d,this.e,this.f)},a.translate=function(a,b){this.add(1,0,0,1,a,b)},a.scale=function(a,b,c,d){null==b&&(b=a),(c||d)&&this.add(1,0,0,1,c,d),this.add(a,0,0,b,0,0),(c||d)&&this.add(1,0,0,1,-c,-d)},a.rotate=function(a,c,d){a=b.rad(a),c=c||0,d=d||0;var e=+M.cos(a).toFixed(9),f=+M.sin(a).toFixed(9);this.add(e,f,-f,e,c,d),this.add(1,0,0,1,-c,-d)},a.x=function(a,b){return a*this.a+b*this.c+this.e},a.y=function(a,b){return a*this.b+b*this.d+this.f},a.get=function(a){return+this[H.fromCharCode(97+a)].toFixed(4)},a.toString=function(){return b.svg?"matrix("+[this.get(0),this.get(1),this.get(2),this.get(3),this.get(4),this.get(5)].join()+")":[this.get(0),this.get(2),this.get(1),this.get(3),0,0].join()},a.toFilter=function(){return"progid:DXImageTransform.Microsoft.Matrix(M11="+this.get(0)+", M12="+this.get(2)+", M21="+this.get(1)+", M22="+this.get(3)+", Dx="+this.get(4)+", Dy="+this.get(5)+", sizingmethod='auto expand')"},a.offset=function(){return[this.e.toFixed(4),this.f.toFixed(4)]},a.split=function(){var a={};a.dx=this.e,a.dy=this.f;var e=[[this.a,this.c],[this.b,this.d]];a.scalex=M.sqrt(c(e[0])),d(e[0]),a.shear=e[0][0]*e[1][0]+e[0][1]*e[1][1],e[1]=[e[1][0]-e[0][0]*a.shear,e[1][1]-e[0][1]*a.shear],a.scaley=M.sqrt(c(e[1])),d(e[1]),a.shear/=a.scaley;var f=-e[0][1],g=e[1][1];return 0>g?(a.rotate=b.deg(M.acos(g)),0>f&&(a.rotate=360-a.rotate)):a.rotate=b.deg(M.asin(f)),a.isSimple=!(+a.shear.toFixed(9)||a.scalex.toFixed(9)!=a.scaley.toFixed(9)&&a.rotate),a.isSuperSimple=!+a.shear.toFixed(9)&&a.scalex.toFixed(9)==a.scaley.toFixed(9)&&!a.rotate,a.noRotation=!+a.shear.toFixed(9)&&!a.rotate,a},a.toTransformString=function(a){var b=a||this[I]();return b.isSimple?(b.scalex=+b.scalex.toFixed(4),b.scaley=+b.scaley.toFixed(4),b.rotate=+b.rotate.toFixed(4),(b.dx||b.dy?"t"+[b.dx,b.dy]:F)+(1!=b.scalex||1!=b.scaley?"s"+[b.scalex,b.scaley,0,0]:F)+(b.rotate?"r"+[b.rotate,0,0]:F)):"m"+[this.get(0),this.get(1),this.get(2),this.get(3),this.get(4),this.get(5)]}}(n.prototype);for(var Oa=function(){this.returnValue=!1},Pa=function(){return this.originalEvent.preventDefault()},Qa=function(){this.cancelBubble=!0},Ra=function(){return this.originalEvent.stopPropagation()},Sa=function(a){var b=z.doc.documentElement.scrollTop||z.doc.body.scrollTop,c=z.doc.documentElement.scrollLeft||z.doc.body.scrollLeft;return{x:a.clientX+c,y:a.clientY+b}},Ta=function(){return z.doc.addEventListener?function(a,b,c,d){var e=function(a){var b=Sa(a);return c.call(d,a,b.x,b.y)};if(a.addEventListener(b,e,!1),E&&K[b]){var f=function(b){for(var e=Sa(b),f=b,g=0,h=b.targetTouches&&b.targetTouches.length;h>g;g++)if(b.targetTouches[g].target==a){b=b.targetTouches[g],b.originalEvent=f,b.preventDefault=Pa,b.stopPropagation=Ra;break}return c.call(d,b,e.x,e.y)};a.addEventListener(K[b],f,!1)}return function(){return a.removeEventListener(b,e,!1),E&&K[b]&&a.removeEventListener(K[b],f,!1),!0}}:z.doc.attachEvent?function(a,b,c,d){var e=function(a){a=a||z.win.event;var b=z.doc.documentElement.scrollTop||z.doc.body.scrollTop,e=z.doc.documentElement.scrollLeft||z.doc.body.scrollLeft,f=a.clientX+e,g=a.clientY+b;return a.preventDefault=a.preventDefault||Oa,a.stopPropagation=a.stopPropagation||Qa,c.call(d,a,f,g)};a.attachEvent("on"+b,e);var f=function(){return a.detachEvent("on"+b,e),!0};return f}:void 0}(),Ua=[],Va=function(b){for(var c,d=b.clientX,e=b.clientY,f=z.doc.documentElement.scrollTop||z.doc.body.scrollTop,g=z.doc.documentElement.scrollLeft||z.doc.body.scrollLeft,h=Ua.length;h--;){if(c=Ua[h],E&&b.touches){for(var i,j=b.touches.length;j--;)if(i=b.touches[j],i.identifier==c.el._drag.id){d=i.clientX,e=i.clientY,(b.originalEvent?b.originalEvent:b).preventDefault();break}}else b.preventDefault();var k,l=c.el.node,m=l.nextSibling,n=l.parentNode,o=l.style.display;z.win.opera&&n.removeChild(l),l.style.display="none",k=c.el.paper.getElementByPoint(d,e),l.style.display=o,z.win.opera&&(m?n.insertBefore(l,m):n.appendChild(l)),k&&a("raphael.drag.over."+c.el.id,c.el,k),d+=g,e+=f,a("raphael.drag.move."+c.el.id,c.move_scope||c.el,d-c.el._drag.x,e-c.el._drag.y,d,e,b)}},Wa=function(c){b.unmousemove(Va).unmouseup(Wa);for(var d,e=Ua.length;e--;)d=Ua[e],d.el._drag={},a("raphael.drag.end."+d.el.id,d.end_scope||d.start_scope||d.move_scope||d.el,c);Ua=[]},Xa=b.el={},Ya=J.length;Ya--;)!function(a){b[a]=Xa[a]=function(c,d){return b.is(c,"function")&&(this.events=this.events||[],this.events.push({name:a,f:c,unbind:Ta(this.shape||this.node||z.doc,a,c,d||this)})),this},b["un"+a]=Xa["un"+a]=function(c){for(var d=this.events||[],e=d.length;e--;)d[e].name!=a||!b.is(c,"undefined")&&d[e].f!=c||(d[e].unbind(),d.splice(e,1),!d.length&&delete this.events);return this}}(J[Ya]);Xa.data=function(c,d){var e=ja[this.id]=ja[this.id]||{};if(0==arguments.length)return e;if(1==arguments.length){if(b.is(c,"object")){for(var f in c)c[y](f)&&this.data(f,c[f]);return this}return a("raphael.data.get."+this.id,this,e[c],c),e[c]}return e[c]=d,a("raphael.data.set."+this.id,this,d,c),this},Xa.removeData=function(a){return null==a?ja[this.id]={}:ja[this.id]&&delete ja[this.id][a],this},Xa.getData=function(){return c(ja[this.id]||{})},Xa.hover=function(a,b,c,d){return this.mouseover(a,c).mouseout(b,d||c)},Xa.unhover=function(a,b){return this.unmouseover(a).unmouseout(b)};var Za=[];Xa.drag=function(c,d,e,f,g,h){function i(i){(i.originalEvent||i).preventDefault();var j=i.clientX,k=i.clientY,l=z.doc.documentElement.scrollTop||z.doc.body.scrollTop,m=z.doc.documentElement.scrollLeft||z.doc.body.scrollLeft;if(this._drag.id=i.identifier,E&&i.touches)for(var n,o=i.touches.length;o--;)if(n=i.touches[o],this._drag.id=n.identifier,n.identifier==this._drag.id){j=n.clientX,k=n.clientY;break}this._drag.x=j+m,this._drag.y=k+l,!Ua.length&&b.mousemove(Va).mouseup(Wa),Ua.push({el:this,move_scope:f,start_scope:g,end_scope:h}),d&&a.on("raphael.drag.start."+this.id,d),c&&a.on("raphael.drag.move."+this.id,c),e&&a.on("raphael.drag.end."+this.id,e),a("raphael.drag.start."+this.id,g||f||this,i.clientX+m,i.clientY+l,i)}return this._drag={},Za.push({el:this,start:i}),this.mousedown(i),this},Xa.onDragOver=function(b){b?a.on("raphael.drag.over."+this.id,b):a.unbind("raphael.drag.over."+this.id)},Xa.undrag=function(){for(var c=Za.length;c--;)Za[c].el==this&&(this.unmousedown(Za[c].start),Za.splice(c,1),a.unbind("raphael.drag.*."+this.id));!Za.length&&b.unmousemove(Va).unmouseup(Wa),Ua=[]},u.circle=function(a,c,d){var e=b._engine.circle(this,a||0,c||0,d||0);return this.__set__&&this.__set__.push(e),e},u.rect=function(a,c,d,e,f){var g=b._engine.rect(this,a||0,c||0,d||0,e||0,f||0);return this.__set__&&this.__set__.push(g),g},u.ellipse=function(a,c,d,e){var f=b._engine.ellipse(this,a||0,c||0,d||0,e||0);return this.__set__&&this.__set__.push(f),f},u.path=function(a){a&&!b.is(a,T)&&!b.is(a[0],U)&&(a+=F);var c=b._engine.path(b.format[C](b,arguments),this);return this.__set__&&this.__set__.push(c),c},u.image=function(a,c,d,e,f){var g=b._engine.image(this,a||"about:blank",c||0,d||0,e||0,f||0);return this.__set__&&this.__set__.push(g),g},u.text=function(a,c,d){var e=b._engine.text(this,a||0,c||0,H(d));return this.__set__&&this.__set__.push(e),e},u.set=function(a){!b.is(a,"array")&&(a=Array.prototype.splice.call(arguments,0,arguments.length));var c=new jb(a);return this.__set__&&this.__set__.push(c),c.paper=this,c.type="set",c},u.setStart=function(a){this.__set__=a||this.set()},u.setFinish=function(a){var b=this.__set__;return delete this.__set__,b},u.getSize=function(){var a=this.canvas.parentNode;return{width:a.offsetWidth,height:a.offsetHeight}},u.setSize=function(a,c){return b._engine.setSize.call(this,a,c)},u.setViewBox=function(a,c,d,e,f){return b._engine.setViewBox.call(this,a,c,d,e,f)},u.top=u.bottom=null,u.raphael=b;var $a=function(a){var b=a.getBoundingClientRect(),c=a.ownerDocument,d=c.body,e=c.documentElement,f=e.clientTop||d.clientTop||0,g=e.clientLeft||d.clientLeft||0,h=b.top+(z.win.pageYOffset||e.scrollTop||d.scrollTop)-f,i=b.left+(z.win.pageXOffset||e.scrollLeft||d.scrollLeft)-g;return{y:h,x:i}};u.getElementByPoint=function(a,b){var c=this,d=c.canvas,e=z.doc.elementFromPoint(a,b);if(z.win.opera&&"svg"==e.tagName){var f=$a(d),g=d.createSVGRect();g.x=a-f.x,g.y=b-f.y,g.width=g.height=1;var h=d.getIntersectionList(g,null);h.length&&(e=h[h.length-1])}if(!e)return null;for(;e.parentNode&&e!=d.parentNode&&!e.raphael;)e=e.parentNode;return e==c.canvas.parentNode&&(e=d),e=e&&e.raphael?c.getById(e.raphaelid):null},u.getElementsByBBox=function(a){var c=this.set();return this.forEach(function(d){b.isBBoxIntersect(d.getBBox(),a)&&c.push(d)}),c},u.getById=function(a){for(var b=this.bottom;b;){if(b.id==a)return b;b=b.next}return null},u.forEach=function(a,b){for(var c=this.bottom;c;){if(a.call(b,c)===!1)return this;c=c.next}return this},u.getElementsByPoint=function(a,b){var c=this.set();return this.forEach(function(d){d.isPointInside(a,b)&&c.push(d)}),c},Xa.isPointInside=function(a,c){var d=this.realPath=oa[this.type](this);return this.attr("transform")&&this.attr("transform").length&&(d=b.transformPath(d,this.attr("transform"))),b.isPointInsidePath(d,a,c)},Xa.getBBox=function(a){if(this.removed)return{};var b=this._;return a?((b.dirty||!b.bboxwt)&&(this.realPath=oa[this.type](this),b.bboxwt=za(this.realPath),b.bboxwt.toString=o,b.dirty=0),b.bboxwt):((b.dirty||b.dirtyT||!b.bbox)&&((b.dirty||!this.realPath)&&(b.bboxwt=0,this.realPath=oa[this.type](this)),b.bbox=za(pa(this.realPath,this.matrix)),b.bbox.toString=o,b.dirty=b.dirtyT=0),b.bbox)},Xa.clone=function(){if(this.removed)return null;var a=this.paper[this.type]().attr(this.attr());return this.__set__&&this.__set__.push(a),a},Xa.glow=function(a){if("text"==this.type)return null;a=a||{};var b={width:(a.width||10)+(+this.attr("stroke-width")||1),fill:a.fill||!1,opacity:null==a.opacity?.5:a.opacity,offsetx:a.offsetx||0,offsety:a.offsety||0,color:a.color||"#000"},c=b.width/2,d=this.paper,e=d.set(),f=this.realPath||oa[this.type](this);f=this.matrix?pa(f,this.matrix):f;for(var g=1;c+1>g;g++)e.push(d.path(f).attr({stroke:b.color,fill:b.fill?b.color:"none","stroke-linejoin":"round","stroke-linecap":"round","stroke-width":+(b.width/c*g).toFixed(3),opacity:+(b.opacity/c).toFixed(3)}));return e.insertBefore(this).translate(b.offsetx,b.offsety)};var _a=function(a,c,d,e,f,g,h,k,l){return null==l?i(a,c,d,e,f,g,h,k):b.findDotsAtSegment(a,c,d,e,f,g,h,k,j(a,c,d,e,f,g,h,k,l))},ab=function(a,c){return function(d,e,f){d=Ia(d);for(var g,h,i,j,k,l="",m={},n=0,o=0,p=d.length;p>o;o++){if(i=d[o],"M"==i[0])g=+i[1],h=+i[2];else{if(j=_a(g,h,i[1],i[2],i[3],i[4],i[5],i[6]),n+j>e){if(c&&!m.start){if(k=_a(g,h,i[1],i[2],i[3],i[4],i[5],i[6],e-n),l+=["C"+k.start.x,k.start.y,k.m.x,k.m.y,k.x,k.y],f)return l;m.start=l,l=["M"+k.x,k.y+"C"+k.n.x,k.n.y,k.end.x,k.end.y,i[5],i[6]].join(),n+=j,g=+i[5],h=+i[6];continue}if(!a&&!c)return k=_a(g,h,i[1],i[2],i[3],i[4],i[5],i[6],e-n),{x:k.x,y:k.y,alpha:k.alpha}}n+=j,g=+i[5],h=+i[6]}l+=i.shift()+i}return m.end=l,k=a?n:c?m:b.findDotsAtSegment(g,h,i[0],i[1],i[2],i[3],i[4],i[5],1),k.alpha&&(k={x:k.x,y:k.y,alpha:k.alpha}),k}},bb=ab(1),cb=ab(),db=ab(0,1);b.getTotalLength=bb,b.getPointAtLength=cb,b.getSubpath=function(a,b,c){if(this.getTotalLength(a)-c<1e-6)return db(a,b).end;var d=db(a,c,1);return b?db(d,b).end:d},Xa.getTotalLength=function(){var a=this.getPath();if(a)return this.node.getTotalLength?this.node.getTotalLength():bb(a)},Xa.getPointAtLength=function(a){var b=this.getPath();if(b)return cb(b,a)},Xa.getPath=function(){var a,c=b._getPath[this.type];if("text"!=this.type&&"set"!=this.type)return c&&(a=c(this)),a},Xa.getSubpath=function(a,c){var d=this.getPath();if(d)return b.getSubpath(d,a,c)};var eb=b.easing_formulas={linear:function(a){return a},"<":function(a){return Q(a,1.7)},">":function(a){return Q(a,.48)},"<>":function(a){var b=.48-a/1.04,c=M.sqrt(.1734+b*b),d=c-b,e=Q(P(d),1/3)*(0>d?-1:1),f=-c-b,g=Q(P(f),1/3)*(0>f?-1:1),h=e+g+.5;return 3*(1-h)*h*h+h*h*h},backIn:function(a){var b=1.70158;return a*a*((b+1)*a-b)},backOut:function(a){a-=1;var b=1.70158;return a*a*((b+1)*a+b)+1},elastic:function(a){return a==!!a?a:Q(2,-10*a)*M.sin(2*(a-.075)*R/.3)+1},bounce:function(a){var b,c=7.5625,d=2.75;return 1/d>a?b=c*a*a:2/d>a?(a-=1.5/d,b=c*a*a+.75):2.5/d>a?(a-=2.25/d,b=c*a*a+.9375):(a-=2.625/d,b=c*a*a+.984375),b}};eb.easeIn=eb["ease-in"]=eb["<"],eb.easeOut=eb["ease-out"]=eb[">"],eb.easeInOut=eb["ease-in-out"]=eb["<>"],eb["back-in"]=eb.backIn,eb["back-out"]=eb.backOut;var fb=[],gb=window.requestAnimationFrame||window.webkitRequestAnimationFrame||window.mozRequestAnimationFrame||window.oRequestAnimationFrame||window.msRequestAnimationFrame||function(a){setTimeout(a,16)},hb=function(){for(var c=+new Date,d=0;d<fb.length;d++){var e=fb[d];if(!e.el.removed&&!e.paused){var f,g,h=c-e.start,i=e.ms,j=e.easing,k=e.from,l=e.diff,m=e.to,n=(e.t,e.el),o={},p={};if(e.initstatus?(h=(e.initstatus*e.anim.top-e.prev)/(e.percent-e.prev)*i,e.status=e.initstatus,delete e.initstatus,e.stop&&fb.splice(d--,1)):e.status=(e.prev+(e.percent-e.prev)*(h/i))/e.anim.top,!(0>h))if(i>h){var q=j(h/i);for(var s in k)if(k[y](s)){switch(ca[s]){case S:f=+k[s]+q*i*l[s];break;case"colour":f="rgb("+[ib(Z(k[s].r+q*i*l[s].r)),ib(Z(k[s].g+q*i*l[s].g)),ib(Z(k[s].b+q*i*l[s].b))].join(",")+")";break;case"path":f=[];for(var t=0,u=k[s].length;u>t;t++){f[t]=[k[s][t][0]];for(var v=1,w=k[s][t].length;w>v;v++)f[t][v]=+k[s][t][v]+q*i*l[s][t][v];f[t]=f[t].join(G)}f=f.join(G);break;case"transform":if(l[s].real)for(f=[],t=0,u=k[s].length;u>t;t++)for(f[t]=[k[s][t][0]],v=1,w=k[s][t].length;w>v;v++)f[t][v]=k[s][t][v]+q*i*l[s][t][v];else{var x=function(a){return+k[s][a]+q*i*l[s][a]};f=[["m",x(0),x(1),x(2),x(3),x(4),x(5)]]}break;case"csv":if("clip-rect"==s)for(f=[],t=4;t--;)f[t]=+k[s][t]+q*i*l[s][t];break;default:var z=[][D](k[s]);for(f=[],t=n.paper.customAttributes[s].length;t--;)f[t]=+z[t]+q*i*l[s][t]}o[s]=f}n.attr(o),function(b,c,d){setTimeout(function(){a("raphael.anim.frame."+b,c,d)})}(n.id,n,e.anim)}else{if(function(c,d,e){setTimeout(function(){a("raphael.anim.frame."+d.id,d,e),a("raphael.anim.finish."+d.id,d,e),b.is(c,"function")&&c.call(d)})}(e.callback,n,e.anim),n.attr(m),fb.splice(d--,1),e.repeat>1&&!e.next){for(g in m)m[y](g)&&(p[g]=e.totalOrigin[g]);e.el.attr(p),r(e.anim,e.el,e.anim.percents[0],null,e.totalOrigin,e.repeat-1)}e.next&&!e.stop&&r(e.anim,e.el,e.next,null,e.totalOrigin,e.repeat)}}}fb.length&&gb(hb)},ib=function(a){return a>255?255:0>a?0:a};Xa.animateWith=function(a,c,d,e,f,g){var h=this;if(h.removed)return g&&g.call(h),h;var i=d instanceof q?d:b.animation(d,e,f,g);r(i,h,i.percents[0],null,h.attr());for(var j=0,k=fb.length;k>j;j++)if(fb[j].anim==c&&fb[j].el==a){fb[k-1].start=fb[j].start;break}return h},Xa.onAnimation=function(b){return b?a.on("raphael.anim.frame."+this.id,b):a.unbind("raphael.anim.frame."+this.id),this},q.prototype.delay=function(a){var b=new q(this.anim,this.ms);return b.times=this.times,b.del=+a||0,b},q.prototype.repeat=function(a){var b=new q(this.anim,this.ms);return b.del=this.del,b.times=M.floor(N(a,0))||1,b},b.animation=function(a,c,d,e){if(a instanceof q)return a;(b.is(d,"function")||!d)&&(e=e||d||null,d=null),a=Object(a),c=+c||0;var f,g,h={};for(g in a)a[y](g)&&$(g)!=g&&$(g)+"%"!=g&&(f=!0,h[g]=a[g]);if(f)return d&&(h.easing=d),e&&(h.callback=e),new q({100:h},c);if(e){var i=0;for(var j in a){var k=_(j);a[y](j)&&k>i&&(i=k)}i+="%",!a[i].callback&&(a[i].callback=e)}return new q(a,c)},Xa.animate=function(a,c,d,e){var f=this;if(f.removed)return e&&e.call(f),f;var g=a instanceof q?a:b.animation(a,c,d,e);return r(g,f,g.percents[0],null,f.attr()),f},Xa.setTime=function(a,b){return a&&null!=b&&this.status(a,O(b,a.ms)/a.ms),this},Xa.status=function(a,b){var c,d,e=[],f=0;if(null!=b)return r(a,this,-1,O(b,1)),this;for(c=fb.length;c>f;f++)if(d=fb[f],d.el.id==this.id&&(!a||d.anim==a)){if(a)return d.status;e.push({anim:d.anim,status:d.status})}return a?0:e},Xa.pause=function(b){for(var c=0;c<fb.length;c++)fb[c].el.id!=this.id||b&&fb[c].anim!=b||a("raphael.anim.pause."+this.id,this,fb[c].anim)!==!1&&(fb[c].paused=!0);return this},Xa.resume=function(b){for(var c=0;c<fb.length;c++)if(fb[c].el.id==this.id&&(!b||fb[c].anim==b)){var d=fb[c];a("raphael.anim.resume."+this.id,this,d.anim)!==!1&&(delete d.paused,this.status(d.anim,d.status))}return this},Xa.stop=function(b){for(var c=0;c<fb.length;c++)fb[c].el.id!=this.id||b&&fb[c].anim!=b||a("raphael.anim.stop."+this.id,this,fb[c].anim)!==!1&&fb.splice(c--,1);return this},a.on("raphael.remove",s),a.on("raphael.clear",s),Xa.toString=function(){return"Raphaël’s object"};var jb=function(a){if(this.items=[],this.length=0,this.type="set",a)for(var b=0,c=a.length;c>b;b++)!a[b]||a[b].constructor!=Xa.constructor&&a[b].constructor!=jb||(this[this.items.length]=this.items[this.items.length]=a[b],this.length++)},kb=jb.prototype;kb.push=function(){for(var a,b,c=0,d=arguments.length;d>c;c++)a=arguments[c],!a||a.constructor!=Xa.constructor&&a.constructor!=jb||(b=this.items.length,this[b]=this.items[b]=a,this.length++);return this},kb.pop=function(){return this.length&&delete this[this.length--],this.items.pop()},kb.forEach=function(a,b){for(var c=0,d=this.items.length;d>c;c++)if(a.call(b,this.items[c],c)===!1)return this;return this};for(var lb in Xa)Xa[y](lb)&&(kb[lb]=function(a){return function(){var b=arguments;return this.forEach(function(c){c[a][C](c,b)})}}(lb));return kb.attr=function(a,c){if(a&&b.is(a,U)&&b.is(a[0],"object"))for(var d=0,e=a.length;e>d;d++)this.items[d].attr(a[d]);else for(var f=0,g=this.items.length;g>f;f++)this.items[f].attr(a,c);return this},kb.clear=function(){for(;this.length;)this.pop()},kb.splice=function(a,b,c){a=0>a?N(this.length+a,0):a,b=N(0,O(this.length-a,b));var d,e=[],f=[],g=[];for(d=2;d<arguments.length;d++)g.push(arguments[d]);for(d=0;b>d;d++)f.push(this[a+d]);for(;d<this.length-a;d++)e.push(this[a+d]);var h=g.length;for(d=0;d<h+e.length;d++)this.items[a+d]=this[a+d]=h>d?g[d]:e[d-h];for(d=this.items.length=this.length-=b-h;this[d];)delete this[d++];return new jb(f)},kb.exclude=function(a){for(var b=0,c=this.length;c>b;b++)if(this[b]==a)return this.splice(b,1),!0},kb.animate=function(a,c,d,e){(b.is(d,"function")||!d)&&(e=d||null);var f,g,h=this.items.length,i=h,j=this;if(!h)return this;e&&(g=function(){!--h&&e.call(j)}),d=b.is(d,T)?d:g;var k=b.animation(a,c,d,g);for(f=this.items[--i].animate(k);i--;)this.items[i]&&!this.items[i].removed&&this.items[i].animateWith(f,k,k),this.items[i]&&!this.items[i].removed||h--;return this},kb.insertAfter=function(a){for(var b=this.items.length;b--;)this.items[b].insertAfter(a);return this},kb.getBBox=function(){for(var a=[],b=[],c=[],d=[],e=this.items.length;e--;)if(!this.items[e].removed){var f=this.items[e].getBBox();a.push(f.x),b.push(f.y),c.push(f.x+f.width),d.push(f.y+f.height)}return a=O[C](0,a),b=O[C](0,b),c=N[C](0,c),d=N[C](0,d),{x:a,y:b,x2:c,y2:d,width:c-a,height:d-b}},kb.clone=function(a){a=this.paper.set();for(var b=0,c=this.items.length;c>b;b++)a.push(this.items[b].clone());return a},kb.toString=function(){return"Raphaël‘s set"},kb.glow=function(a){var b=this.paper.set();return this.forEach(function(c,d){var e=c.glow(a);null!=e&&e.forEach(function(a,c){b.push(a)})}),b},kb.isPointInside=function(a,b){var c=!1;return this.forEach(function(d){return d.isPointInside(a,b)?(c=!0,!1):void 0}),c},b.registerFont=function(a){if(!a.face)return a;this.fonts=this.fonts||{};var b={w:a.w,face:{},glyphs:{}},c=a.face["font-family"];for(var d in a.face)a.face[y](d)&&(b.face[d]=a.face[d]);if(this.fonts[c]?this.fonts[c].push(b):this.fonts[c]=[b],!a.svg){b.face["units-per-em"]=_(a.face["units-per-em"],10);for(var e in a.glyphs)if(a.glyphs[y](e)){var f=a.glyphs[e];if(b.glyphs[e]={w:f.w,k:{},d:f.d&&"M"+f.d.replace(/[mlcxtrv]/g,function(a){return{l:"L",c:"C",x:"z",t:"m",r:"l",v:"c"}[a]||"M"})+"z"},f.k)for(var g in f.k)f[y](g)&&(b.glyphs[e].k[g]=f.k[g])}}return a},u.getFont=function(a,c,d,e){if(e=e||"normal",d=d||"normal",c=+c||{normal:400,bold:700,lighter:300,bolder:800}[c]||400,b.fonts){var f=b.fonts[a];if(!f){var g=new RegExp("(^|\\s)"+a.replace(/[^\w\d\s+!~.:_-]/g,F)+"(\\s|$)","i");for(var h in b.fonts)if(b.fonts[y](h)&&g.test(h)){f=b.fonts[h];break}}var i;if(f)for(var j=0,k=f.length;k>j&&(i=f[j],i.face["font-weight"]!=c||i.face["font-style"]!=d&&i.face["font-style"]||i.face["font-stretch"]!=e);j++);return i}},u.print=function(a,c,d,e,f,g,h,i){g=g||"middle",h=N(O(h||0,1),-1),i=N(O(i||1,3),1);var j,k=H(d)[I](F),l=0,m=0,n=F;if(b.is(e,"string")&&(e=this.getFont(e)),e){j=(f||16)/e.face["units-per-em"];for(var o=e.face.bbox[I](v),p=+o[0],q=o[3]-o[1],r=0,s=+o[1]+("baseline"==g?q+ +e.face.descent:q/2),t=0,u=k.length;u>t;t++){if("\n"==k[t])l=0,x=0,m=0,r+=q*i;else{var w=m&&e.glyphs[k[t-1]]||{},x=e.glyphs[k[t]];l+=m?(w.w||e.w)+(w.k&&w.k[k[t]]||0)+e.w*h:0,m=1}x&&x.d&&(n+=b.transformPath(x.d,["t",l*j,r*j,"s",j,j,p,s,"t",(a-p)/j,(c-s)/j]))}}return this.path(n).attr({fill:"#000",stroke:"none"})},u.add=function(a){if(b.is(a,"array"))for(var c,d=this.set(),e=0,f=a.length;f>e;e++)c=a[e]||{},w[y](c.type)&&d.push(this[c.type]().attr(c));return d},b.format=function(a,c){var d=b.is(c,U)?[0][D](c):arguments;return a&&b.is(a,T)&&d.length-1&&(a=a.replace(x,function(a,b){return null==d[++b]?F:d[b]})),a||F},b.fullfill=function(){var a=/\{([^\}]+)\}/g,b=/(?:(?:^|\.)(.+?)(?=\[|\.|$|\()|\[('|")(.+?)\2\])(\(\))?/g,c=function(a,c,d){var e=d;return c.replace(b,function(a,b,c,d,f){b=b||d,e&&(b in e&&(e=e[b]),"function"==typeof e&&f&&(e=e()))}),e=(null==e||e==d?a:e)+""};return function(b,d){return String(b).replace(a,function(a,b){return c(a,b,d)})}}(),b.ninja=function(){return A.was?z.win.Raphael=A.is:delete Raphael,b},b.st=kb,a.on("raphael.DOMload",function(){t=!0}),function(a,c,d){function e(){/in/.test(a.readyState)?setTimeout(e,9):b.eve("raphael.DOMload")}null==a.readyState&&a.addEventListener&&(a.addEventListener(c,d=function(){a.removeEventListener(c,d,!1),a.readyState="complete"},!1),a.readyState="loading"),e()}(document,"DOMContentLoaded"),b}),function(a,b){"function"==typeof define&&define.amd?define("raphael.svg",["raphael.core"],function(a){return b(a)}):b("object"==typeof exports?require("./raphael.core"):a.Raphael)}(this,function(a){if(!a||a.svg){var b="hasOwnProperty",c=String,d=parseFloat,e=parseInt,f=Math,g=f.max,h=f.abs,i=f.pow,j=/[, ]+/,k=a.eve,l="",m=" ",n="http://www.w3.org/1999/xlink",o={block:"M5,0 0,2.5 5,5z",classic:"M5,0 0,2.5 5,5 3.5,3 3.5,2z",diamond:"M2.5,0 5,2.5 2.5,5 0,2.5z",open:"M6,1 1,3.5 6,6",oval:"M2.5,0A2.5,2.5,0,0,1,2.5,5 2.5,2.5,0,0,1,2.5,0z"},p={};a.toString=function(){return"Your browser supports SVG.\nYou are running Raphaël "+this.version};var q=function(d,e){if(e){"string"==typeof d&&(d=q(d));for(var f in e)e[b](f)&&("xlink:"==f.substring(0,6)?d.setAttributeNS(n,f.substring(6),c(e[f])):d.setAttribute(f,c(e[f])))}else d=a._g.doc.createElementNS("http://www.w3.org/2000/svg",d),d.style&&(d.style.webkitTapHighlightColor="rgba(0,0,0,0)");return d},r=function(b,e){var j="linear",k=b.id+e,m=.5,n=.5,o=b.node,p=b.paper,r=o.style,s=a._g.doc.getElementById(k);if(!s){if(e=c(e).replace(a._radial_gradient,function(a,b,c){if(j="radial",b&&c){m=d(b),n=d(c);var e=2*(n>.5)-1;i(m-.5,2)+i(n-.5,2)>.25&&(n=f.sqrt(.25-i(m-.5,2))*e+.5)&&.5!=n&&(n=n.toFixed(5)-1e-5*e)}return l}),e=e.split(/\s*\-\s*/),"linear"==j){var t=e.shift();if(t=-d(t),isNaN(t))return null;var u=[0,0,f.cos(a.rad(t)),f.sin(a.rad(t))],v=1/(g(h(u[2]),h(u[3]))||1);u[2]*=v,u[3]*=v,u[2]<0&&(u[0]=-u[2],u[2]=0),u[3]<0&&(u[1]=-u[3],u[3]=0)}var w=a._parseDots(e);if(!w)return null;if(k=k.replace(/[\(\)\s,\xb0#]/g,"_"),b.gradient&&k!=b.gradient.id&&(p.defs.removeChild(b.gradient),delete b.gradient),!b.gradient){s=q(j+"Gradient",{id:k}),b.gradient=s,q(s,"radial"==j?{fx:m,fy:n}:{x1:u[0],y1:u[1],x2:u[2],y2:u[3],gradientTransform:b.matrix.invert()}),p.defs.appendChild(s);for(var x=0,y=w.length;y>x;x++)s.appendChild(q("stop",{offset:w[x].offset?w[x].offset:x?"100%":"0%","stop-color":w[x].color||"#fff","stop-opacity":isFinite(w[x].opacity)?w[x].opacity:1}))}}return q(o,{fill:"url('"+document.location.origin+document.location.pathname+"#"+k+"')",opacity:1,"fill-opacity":1}),r.fill=l,r.opacity=1,r.fillOpacity=1,1},s=function(a){var b=a.getBBox(1);q(a.pattern,{patternTransform:a.matrix.invert()+" translate("+b.x+","+b.y+")"})},t=function(d,e,f){if("path"==d.type){for(var g,h,i,j,k,m=c(e).toLowerCase().split("-"),n=d.paper,r=f?"end":"start",s=d.node,t=d.attrs,u=t["stroke-width"],v=m.length,w="classic",x=3,y=3,z=5;v--;)switch(m[v]){case"block":case"classic":case"oval":case"diamond":case"open":case"none":w=m[v];break;case"wide":y=5;break;case"narrow":y=2;break;case"long":x=5;break;case"short":x=2}if("open"==w?(x+=2,y+=2,z+=2,i=1,j=f?4:1,k={fill:"none",stroke:t.stroke}):(j=i=x/2,k={fill:t.stroke,stroke:"none"}),d._.arrows?f?(d._.arrows.endPath&&p[d._.arrows.endPath]--,d._.arrows.endMarker&&p[d._.arrows.endMarker]--):(d._.arrows.startPath&&p[d._.arrows.startPath]--,d._.arrows.startMarker&&p[d._.arrows.startMarker]--):d._.arrows={},"none"!=w){var A="raphael-marker-"+w,B="raphael-marker-"+r+w+x+y+"-obj"+d.id;a._g.doc.getElementById(A)?p[A]++:(n.defs.appendChild(q(q("path"),{"stroke-linecap":"round",d:o[w],id:A})),p[A]=1);var C,D=a._g.doc.getElementById(B);D?(p[B]++,C=D.getElementsByTagName("use")[0]):(D=q(q("marker"),{id:B,markerHeight:y,markerWidth:x,orient:"auto",refX:j,refY:y/2}),C=q(q("use"),{"xlink:href":"#"+A,transform:(f?"rotate(180 "+x/2+" "+y/2+") ":l)+"scale("+x/z+","+y/z+")","stroke-width":(1/((x/z+y/z)/2)).toFixed(4)}),D.appendChild(C),n.defs.appendChild(D),p[B]=1),q(C,k);var E=i*("diamond"!=w&&"oval"!=w);f?(g=d._.arrows.startdx*u||0,h=a.getTotalLength(t.path)-E*u):(g=E*u,h=a.getTotalLength(t.path)-(d._.arrows.enddx*u||0)),k={},k["marker-"+r]="url(#"+B+")",(h||g)&&(k.d=a.getSubpath(t.path,g,h)),q(s,k),d._.arrows[r+"Path"]=A,d._.arrows[r+"Marker"]=B,d._.arrows[r+"dx"]=E,d._.arrows[r+"Type"]=w,d._.arrows[r+"String"]=e}else f?(g=d._.arrows.startdx*u||0,h=a.getTotalLength(t.path)-g):(g=0,h=a.getTotalLength(t.path)-(d._.arrows.enddx*u||0)),d._.arrows[r+"Path"]&&q(s,{d:a.getSubpath(t.path,g,h)}),delete d._.arrows[r+"Path"],delete d._.arrows[r+"Marker"],delete d._.arrows[r+"dx"],delete d._.arrows[r+"Type"],delete d._.arrows[r+"String"];for(k in p)if(p[b](k)&&!p[k]){var F=a._g.doc.getElementById(k);F&&F.parentNode.removeChild(F)}}},u={"-":[3,1],".":[1,1],"-.":[3,1,1,1],"-..":[3,1,1,1,1,1],". ":[1,3],"- ":[4,3],"--":[8,3],"- .":[4,3,1,3],"--.":[8,3,1,3],"--..":[8,3,1,3,1,3]},v=function(a,b,d){if(b=u[c(b).toLowerCase()]){for(var e=a.attrs["stroke-width"]||"1",f={round:e,square:e,butt:0}[a.attrs["stroke-linecap"]||d["stroke-linecap"]]||0,g=[],h=b.length;h--;)g[h]=b[h]*e+(h%2?1:-1)*f;q(a.node,{"stroke-dasharray":g.join(",")})}else q(a.node,{"stroke-dasharray":"none"})},w=function(d,f){var i=d.node,k=d.attrs,m=i.style.visibility;i.style.visibility="hidden";for(var o in f)if(f[b](o)){if(!a._availableAttrs[b](o))continue;var p=f[o];switch(k[o]=p,o){case"blur":d.blur(p);break;case"title":var u=i.getElementsByTagName("title");if(u.length&&(u=u[0]))u.firstChild.nodeValue=p;else{u=q("title");var w=a._g.doc.createTextNode(p);u.appendChild(w),i.appendChild(u)}break;case"href":case"target":var x=i.parentNode;if("a"!=x.tagName.toLowerCase()){var z=q("a");x.insertBefore(z,i),z.appendChild(i),x=z}"target"==o?x.setAttributeNS(n,"show","blank"==p?"new":p):x.setAttributeNS(n,o,p);break;case"cursor":i.style.cursor=p;break;case"transform":d.transform(p);break;case"arrow-start":t(d,p);break;case"arrow-end":t(d,p,1);break;case"clip-rect":var A=c(p).split(j);if(4==A.length){d.clip&&d.clip.parentNode.parentNode.removeChild(d.clip.parentNode);var B=q("clipPath"),C=q("rect");B.id=a.createUUID(),q(C,{x:A[0],y:A[1],width:A[2],height:A[3]}),B.appendChild(C),d.paper.defs.appendChild(B),q(i,{"clip-path":"url(#"+B.id+")"}),d.clip=C}if(!p){var D=i.getAttribute("clip-path");if(D){var E=a._g.doc.getElementById(D.replace(/(^url\(#|\)$)/g,l));E&&E.parentNode.removeChild(E),q(i,{"clip-path":l}),delete d.clip}}break;case"path":"path"==d.type&&(q(i,{d:p?k.path=a._pathToAbsolute(p):"M0,0"}),d._.dirty=1,d._.arrows&&("startString"in d._.arrows&&t(d,d._.arrows.startString),"endString"in d._.arrows&&t(d,d._.arrows.endString,1)));break;case"width":if(i.setAttribute(o,p),d._.dirty=1,!k.fx)break;o="x",p=k.x;case"x":k.fx&&(p=-k.x-(k.width||0));case"rx":if("rx"==o&&"rect"==d.type)break;case"cx":i.setAttribute(o,p),d.pattern&&s(d),d._.dirty=1;break;case"height":if(i.setAttribute(o,p),d._.dirty=1,!k.fy)break;o="y",p=k.y;case"y":k.fy&&(p=-k.y-(k.height||0));case"ry":if("ry"==o&&"rect"==d.type)break;case"cy":i.setAttribute(o,p),d.pattern&&s(d),d._.dirty=1;break;case"r":"rect"==d.type?q(i,{rx:p,ry:p}):i.setAttribute(o,p),d._.dirty=1;break;case"src":"image"==d.type&&i.setAttributeNS(n,"href",p);break;case"stroke-width":(1!=d._.sx||1!=d._.sy)&&(p/=g(h(d._.sx),h(d._.sy))||1),i.setAttribute(o,p),k["stroke-dasharray"]&&v(d,k["stroke-dasharray"],f),d._.arrows&&("startString"in d._.arrows&&t(d,d._.arrows.startString),"endString"in d._.arrows&&t(d,d._.arrows.endString,1));break;case"stroke-dasharray":v(d,p,f);break;case"fill":var F=c(p).match(a._ISURL);if(F){B=q("pattern");var G=q("image");B.id=a.createUUID(),q(B,{x:0,y:0,patternUnits:"userSpaceOnUse",height:1,width:1}),q(G,{x:0,y:0,"xlink:href":F[1]}),B.appendChild(G),function(b){a._preload(F[1],function(){var a=this.offsetWidth,c=this.offsetHeight;q(b,{width:a,height:c}),q(G,{width:a,height:c})})}(B),d.paper.defs.appendChild(B),q(i,{fill:"url(#"+B.id+")"}),d.pattern=B,d.pattern&&s(d);break}var H=a.getRGB(p);if(H.error){if(("circle"==d.type||"ellipse"==d.type||"r"!=c(p).charAt())&&r(d,p)){if("opacity"in k||"fill-opacity"in k){var I=a._g.doc.getElementById(i.getAttribute("fill").replace(/^url\(#|\)$/g,l));if(I){var J=I.getElementsByTagName("stop");q(J[J.length-1],{"stop-opacity":("opacity"in k?k.opacity:1)*("fill-opacity"in k?k["fill-opacity"]:1)})}}k.gradient=p,k.fill="none";break}}else delete f.gradient,delete k.gradient,!a.is(k.opacity,"undefined")&&a.is(f.opacity,"undefined")&&q(i,{opacity:k.opacity}),!a.is(k["fill-opacity"],"undefined")&&a.is(f["fill-opacity"],"undefined")&&q(i,{"fill-opacity":k["fill-opacity"]});H[b]("opacity")&&q(i,{"fill-opacity":H.opacity>1?H.opacity/100:H.opacity});case"stroke":H=a.getRGB(p),i.setAttribute(o,H.hex),"stroke"==o&&H[b]("opacity")&&q(i,{"stroke-opacity":H.opacity>1?H.opacity/100:H.opacity}),"stroke"==o&&d._.arrows&&("startString"in d._.arrows&&t(d,d._.arrows.startString),"endString"in d._.arrows&&t(d,d._.arrows.endString,1));break;case"gradient":("circle"==d.type||"ellipse"==d.type||"r"!=c(p).charAt())&&r(d,p);
-(function(a){var b="0.3.4",c="hasOwnProperty",d=/[\.\/]/,e="*",f=function(){},g=function(a,b){return a-b},h,i,j={n:{}},k=function(a,b){var c=j,d=i,e=Array.prototype.slice.call(arguments,2),f=k.listeners(a),l=0,m=!1,n,o=[],p={},q=[],r=h,s=[];h=a,i=0;for(var t=0,u=f.length;t<u;t++)"zIndex"in f[t]&&(o.push(f[t].zIndex),f[t].zIndex<0&&(p[f[t].zIndex]=f[t]));o.sort(g);while(o[l]<0){n=p[o[l++]],q.push(n.apply(b,e));if(i){i=d;return q}}for(t=0;t<u;t++){n=f[t];if("zIndex"in n)if(n.zIndex==o[l]){q.push(n.apply(b,e));if(i)break;do{l++,n=p[o[l]],n&&q.push(n.apply(b,e));if(i)break}while(n)}else p[n.zIndex]=n;else{q.push(n.apply(b,e));if(i)break}}i=d,h=r;return q.length?q:null};k.listeners=function(a){var b=a.split(d),c=j,f,g,h,i,k,l,m,n,o=[c],p=[];for(i=0,k=b.length;i<k;i++){n=[];for(l=0,m=o.length;l<m;l++){c=o[l].n,g=[c[b[i]],c[e]],h=2;while(h--)f=g[h],f&&(n.push(f),p=p.concat(f.f||[]))}o=n}return p},k.on=function(a,b){var c=a.split(d),e=j;for(var g=0,h=c.length;g<h;g++)e=e.n,!e[c[g]]&&(e[c[g]]={n:{}}),e=e[c[g]];e.f=e.f||[];for(g=0,h=e.f.length;g<h;g++)if(e.f[g]==b)return f;e.f.push(b);return function(a){+a==+a&&(b.zIndex=+a)}},k.stop=function(){i=1},k.nt=function(a){if(a)return(new RegExp("(?:\\.|\\/|^)"+a+"(?:\\.|\\/|$)")).test(h);return h},k.off=k.unbind=function(a,b){var f=a.split(d),g,h,i,k,l,m,n,o=[j];for(k=0,l=f.length;k<l;k++)for(m=0;m<o.length;m+=i.length-2){i=[m,1],g=o[m].n;if(f[k]!=e)g[f[k]]&&i.push(g[f[k]]);else for(h in g)g[c](h)&&i.push(g[h]);o.splice.apply(o,i)}for(k=0,l=o.length;k<l;k++){g=o[k];while(g.n){if(b){if(g.f){for(m=0,n=g.f.length;m<n;m++)if(g.f[m]==b){g.f.splice(m,1);break}!g.f.length&&delete g.f}for(h in g.n)if(g.n[c](h)&&g.n[h].f){var p=g.n[h].f;for(m=0,n=p.length;m<n;m++)if(p[m]==b){p.splice(m,1);break}!p.length&&delete g.n[h].f}}else{delete g.f;for(h in g.n)g.n[c](h)&&g.n[h].f&&delete g.n[h].f}g=g.n}}},k.once=function(a,b){var c=function(){var d=b.apply(this,arguments);k.unbind(a,c);return d};return k.on(a,c)},k.version=b,k.toString=function(){return"You are running Eve "+b},typeof module!="undefined"&&module.exports?module.exports=k:typeof define!="undefined"?define("eve",[],function(){return k}):a.eve=k})(this),function(){function cF(a){for(var b=0;b<cy.length;b++)cy[b].el.paper==a&&cy.splice(b--,1)}function cE(b,d,e,f,h,i){e=Q(e);var j,k,l,m=[],o,p,q,t=b.ms,u={},v={},w={};if(f)for(y=0,z=cy.length;y<z;y++){var x=cy[y];if(x.el.id==d.id&&x.anim==b){x.percent!=e?(cy.splice(y,1),l=1):k=x,d.attr(x.totalOrigin);break}}else f=+v;for(var y=0,z=b.percents.length;y<z;y++){if(b.percents[y]==e||b.percents[y]>f*b.top){e=b.percents[y],p=b.percents[y-1]||0,t=t/b.top*(e-p),o=b.percents[y+1],j=b.anim[e];break}f&&d.attr(b.anim[b.percents[y]])}if(!!j){if(!k){for(var A in j)if(j[g](A))if(U[g](A)||d.paper.customAttributes[g](A)){u[A]=d.attr(A),u[A]==null&&(u[A]=T[A]),v[A]=j[A];switch(U[A]){case C:w[A]=(v[A]-u[A])/t;break;case"colour":u[A]=a.getRGB(u[A]);var B=a.getRGB(v[A]);w[A]={r:(B.r-u[A].r)/t,g:(B.g-u[A].g)/t,b:(B.b-u[A].b)/t};break;case"path":var D=bR(u[A],v[A]),E=D[1];u[A]=D[0],w[A]=[];for(y=0,z=u[A].length;y<z;y++){w[A][y]=[0];for(var F=1,G=u[A][y].length;F<G;F++)w[A][y][F]=(E[y][F]-u[A][y][F])/t}break;case"transform":var H=d._,I=ca(H[A],v[A]);if(I){u[A]=I.from,v[A]=I.to,w[A]=[],w[A].real=!0;for(y=0,z=u[A].length;y<z;y++){w[A][y]=[u[A][y][0]];for(F=1,G=u[A][y].length;F<G;F++)w[A][y][F]=(v[A][y][F]-u[A][y][F])/t}}else{var J=d.matrix||new cb,K={_:{transform:H.transform},getBBox:function(){return d.getBBox(1)}};u[A]=[J.a,J.b,J.c,J.d,J.e,J.f],b$(K,v[A]),v[A]=K._.transform,w[A]=[(K.matrix.a-J.a)/t,(K.matrix.b-J.b)/t,(K.matrix.c-J.c)/t,(K.matrix.d-J.d)/t,(K.matrix.e-J.e)/t,(K.matrix.f-J.f)/t]}break;case"csv":var L=r(j[A])[s](c),M=r(u[A])[s](c);if(A=="clip-rect"){u[A]=M,w[A]=[],y=M.length;while(y--)w[A][y]=(L[y]-u[A][y])/t}v[A]=L;break;default:L=[][n](j[A]),M=[][n](u[A]),w[A]=[],y=d.paper.customAttributes[A].length;while(y--)w[A][y]=((L[y]||0)-(M[y]||0))/t}}var O=j.easing,P=a.easing_formulas[O];if(!P){P=r(O).match(N);if(P&&P.length==5){var R=P;P=function(a){return cC(a,+R[1],+R[2],+R[3],+R[4],t)}}else P=bf}q=j.start||b.start||+(new Date),x={anim:b,percent:e,timestamp:q,start:q+(b.del||0),status:0,initstatus:f||0,stop:!1,ms:t,easing:P,from:u,diff:w,to:v,el:d,callback:j.callback,prev:p,next:o,repeat:i||b.times,origin:d.attr(),totalOrigin:h},cy.push(x);if(f&&!k&&!l){x.stop=!0,x.start=new Date-t*f;if(cy.length==1)return cA()}l&&(x.start=new Date-x.ms*f),cy.length==1&&cz(cA)}else k.initstatus=f,k.start=new Date-k.ms*f;eve("raphael.anim.start."+d.id,d,b)}}function cD(a,b){var c=[],d={};this.ms=b,this.times=1;if(a){for(var e in a)a[g](e)&&(d[Q(e)]=a[e],c.push(Q(e)));c.sort(bd)}this.anim=d,this.top=c[c.length-1],this.percents=c}function cC(a,b,c,d,e,f){function o(a,b){var c,d,e,f,j,k;for(e=a,k=0;k<8;k++){f=m(e)-a;if(z(f)<b)return e;j=(3*i*e+2*h)*e+g;if(z(j)<1e-6)break;e=e-f/j}c=0,d=1,e=a;if(e<c)return c;if(e>d)return d;while(c<d){f=m(e);if(z(f-a)<b)return e;a>f?c=e:d=e,e=(d-c)/2+c}return e}function n(a,b){var c=o(a,b);return((l*c+k)*c+j)*c}function m(a){return((i*a+h)*a+g)*a}var g=3*b,h=3*(d-b)-g,i=1-g-h,j=3*c,k=3*(e-c)-j,l=1-j-k;return n(a,1/(200*f))}function cq(){return this.x+q+this.y+q+this.width+" × "+this.height}function cp(){return this.x+q+this.y}function cb(a,b,c,d,e,f){a!=null?(this.a=+a,this.b=+b,this.c=+c,this.d=+d,this.e=+e,this.f=+f):(this.a=1,this.b=0,this.c=0,this.d=1,this.e=0,this.f=0)}function bH(b,c,d){b=a._path2curve(b),c=a._path2curve(c);var e,f,g,h,i,j,k,l,m,n,o=d?0:[];for(var p=0,q=b.length;p<q;p++){var r=b[p];if(r[0]=="M")e=i=r[1],f=j=r[2];else{r[0]=="C"?(m=[e,f].concat(r.slice(1)),e=m[6],f=m[7]):(m=[e,f,e,f,i,j,i,j],e=i,f=j);for(var s=0,t=c.length;s<t;s++){var u=c[s];if(u[0]=="M")g=k=u[1],h=l=u[2];else{u[0]=="C"?(n=[g,h].concat(u.slice(1)),g=n[6],h=n[7]):(n=[g,h,g,h,k,l,k,l],g=k,h=l);var v=bG(m,n,d);if(d)o+=v;else{for(var w=0,x=v.length;w<x;w++)v[w].segment1=p,v[w].segment2=s,v[w].bez1=m,v[w].bez2=n;o=o.concat(v)}}}}}return o}function bG(b,c,d){var e=a.bezierBBox(b),f=a.bezierBBox(c);if(!a.isBBoxIntersect(e,f))return d?0:[];var g=bB.apply(0,b),h=bB.apply(0,c),i=~~(g/5),j=~~(h/5),k=[],l=[],m={},n=d?0:[];for(var o=0;o<i+1;o++){var p=a.findDotsAtSegment.apply(a,b.concat(o/i));k.push({x:p.x,y:p.y,t:o/i})}for(o=0;o<j+1;o++)p=a.findDotsAtSegment.apply(a,c.concat(o/j)),l.push({x:p.x,y:p.y,t:o/j});for(o=0;o<i;o++)for(var q=0;q<j;q++){var r=k[o],s=k[o+1],t=l[q],u=l[q+1],v=z(s.x-r.x)<.001?"y":"x",w=z(u.x-t.x)<.001?"y":"x",x=bD(r.x,r.y,s.x,s.y,t.x,t.y,u.x,u.y);if(x){if(m[x.x.toFixed(4)]==x.y.toFixed(4))continue;m[x.x.toFixed(4)]=x.y.toFixed(4);var y=r.t+z((x[v]-r[v])/(s[v]-r[v]))*(s.t-r.t),A=t.t+z((x[w]-t[w])/(u[w]-t[w]))*(u.t-t.t);y>=0&&y<=1&&A>=0&&A<=1&&(d?n++:n.push({x:x.x,y:x.y,t1:y,t2:A}))}}return n}function bF(a,b){return bG(a,b,1)}function bE(a,b){return bG(a,b)}function bD(a,b,c,d,e,f,g,h){if(!(x(a,c)<y(e,g)||y(a,c)>x(e,g)||x(b,d)<y(f,h)||y(b,d)>x(f,h))){var i=(a*d-b*c)*(e-g)-(a-c)*(e*h-f*g),j=(a*d-b*c)*(f-h)-(b-d)*(e*h-f*g),k=(a-c)*(f-h)-(b-d)*(e-g);if(!k)return;var l=i/k,m=j/k,n=+l.toFixed(2),o=+m.toFixed(2);if(n<+y(a,c).toFixed(2)||n>+x(a,c).toFixed(2)||n<+y(e,g).toFixed(2)||n>+x(e,g).toFixed(2)||o<+y(b,d).toFixed(2)||o>+x(b,d).toFixed(2)||o<+y(f,h).toFixed(2)||o>+x(f,h).toFixed(2))return;return{x:l,y:m}}}function bC(a,b,c,d,e,f,g,h,i){if(!(i<0||bB(a,b,c,d,e,f,g,h)<i)){var j=1,k=j/2,l=j-k,m,n=.01;m=bB(a,b,c,d,e,f,g,h,l);while(z(m-i)>n)k/=2,l+=(m<i?1:-1)*k,m=bB(a,b,c,d,e,f,g,h,l);return l}}function bB(a,b,c,d,e,f,g,h,i){i==null&&(i=1),i=i>1?1:i<0?0:i;var j=i/2,k=12,l=[-0.1252,.1252,-0.3678,.3678,-0.5873,.5873,-0.7699,.7699,-0.9041,.9041,-0.9816,.9816],m=[.2491,.2491,.2335,.2335,.2032,.2032,.1601,.1601,.1069,.1069,.0472,.0472],n=0;for(var o=0;o<k;o++){var p=j*l[o]+j,q=bA(p,a,c,e,g),r=bA(p,b,d,f,h),s=q*q+r*r;n+=m[o]*w.sqrt(s)}return j*n}function bA(a,b,c,d,e){var f=-3*b+9*c-9*d+3*e,g=a*f+6*b-12*c+6*d;return a*g-3*b+3*c}function by(a,b){var c=[];for(var d=0,e=a.length;e-2*!b>d;d+=2){var f=[{x:+a[d-2],y:+a[d-1]},{x:+a[d],y:+a[d+1]},{x:+a[d+2],y:+a[d+3]},{x:+a[d+4],y:+a[d+5]}];b?d?e-4==d?f[3]={x:+a[0],y:+a[1]}:e-2==d&&(f[2]={x:+a[0],y:+a[1]},f[3]={x:+a[2],y:+a[3]}):f[0]={x:+a[e-2],y:+a[e-1]}:e-4==d?f[3]=f[2]:d||(f[0]={x:+a[d],y:+a[d+1]}),c.push(["C",(-f[0].x+6*f[1].x+f[2].x)/6,(-f[0].y+6*f[1].y+f[2].y)/6,(f[1].x+6*f[2].x-f[3].x)/6,(f[1].y+6*f[2].y-f[3].y)/6,f[2].x,f[2].y])}return c}function bx(){return this.hex}function bv(a,b,c){function d(){var e=Array.prototype.slice.call(arguments,0),f=e.join("␀"),h=d.cache=d.cache||{},i=d.count=d.count||[];if(h[g](f)){bu(i,f);return c?c(h[f]):h[f]}i.length>=1e3&&delete h[i.shift()],i.push(f),h[f]=a[m](b,e);return c?c(h[f]):h[f]}return d}function bu(a,b){for(var c=0,d=a.length;c<d;c++)if(a[c]===b)return a.push(a.splice(c,1)[0])}function bm(a){if(Object(a)!==a)return a;var b=new a.constructor;for(var c in a)a[g](c)&&(b[c]=bm(a[c]));return b}function a(c){if(a.is(c,"function"))return b?c():eve.on("raphael.DOMload",c);if(a.is(c,E))return a._engine.create[m](a,c.splice(0,3+a.is(c[0],C))).add(c);var d=Array.prototype.slice.call(arguments,0);if(a.is(d[d.length-1],"function")){var e=d.pop();return b?e.call(a._engine.create[m](a,d)):eve.on("raphael.DOMload",function(){e.call(a._engine.create[m](a,d))})}return a._engine.create[m](a,arguments)}a.version="2.1.0",a.eve=eve;var b,c=/[, ]+/,d={circle:1,rect:1,path:1,ellipse:1,text:1,image:1},e=/\{(\d+)\}/g,f="prototype",g="hasOwnProperty",h={doc:document,win:window},i={was:Object.prototype[g].call(h.win,"Raphael"),is:h.win.Raphael},j=function(){this.ca=this.customAttributes={}},k,l="appendChild",m="apply",n="concat",o="createTouch"in h.doc,p="",q=" ",r=String,s="split",t="click dblclick mousedown mousemove mouseout mouseover mouseup touchstart touchmove touchend touchcancel"[s](q),u={mousedown:"touchstart",mousemove:"touchmove",mouseup:"touchend"},v=r.prototype.toLowerCase,w=Math,x=w.max,y=w.min,z=w.abs,A=w.pow,B=w.PI,C="number",D="string",E="array",F="toString",G="fill",H=Object.prototype.toString,I={},J="push",K=a._ISURL=/^url\(['"]?([^\)]+?)['"]?\)$/i,L=/^\s*((#[a-f\d]{6})|(#[a-f\d]{3})|rgba?\(\s*([\d\.]+%?\s*,\s*[\d\.]+%?\s*,\s*[\d\.]+%?(?:\s*,\s*[\d\.]+%?)?)\s*\)|hsba?\(\s*([\d\.]+(?:deg|\xb0|%)?\s*,\s*[\d\.]+%?\s*,\s*[\d\.]+(?:%?\s*,\s*[\d\.]+)?)%?\s*\)|hsla?\(\s*([\d\.]+(?:deg|\xb0|%)?\s*,\s*[\d\.]+%?\s*,\s*[\d\.]+(?:%?\s*,\s*[\d\.]+)?)%?\s*\))\s*$/i,M={NaN:1,Infinity:1,"-Infinity":1},N=/^(?:cubic-)?bezier\(([^,]+),([^,]+),([^,]+),([^\)]+)\)/,O=w.round,P="setAttribute",Q=parseFloat,R=parseInt,S=r.prototype.toUpperCase,T=a._availableAttrs={"arrow-end":"none","arrow-start":"none",blur:0,"clip-rect":"0 0 1e9 1e9",cursor:"default",cx:0,cy:0,fill:"#fff","fill-opacity":1,font:'10px "Arial"',"font-family":'"Arial"',"font-size":"10","font-style":"normal","font-weight":400,gradient:0,height:0,href:"http://raphaeljs.com/","letter-spacing":0,opacity:1,path:"M0,0",r:0,rx:0,ry:0,src:"",stroke:"#000","stroke-dasharray":"","stroke-linecap":"butt","stroke-linejoin":"butt","stroke-miterlimit":0,"stroke-opacity":1,"stroke-width":1,target:"_blank","text-anchor":"middle",title:"Raphael",transform:"",width:0,x:0,y:0},U=a._availableAnimAttrs={blur:C,"clip-rect":"csv",cx:C,cy:C,fill:"colour","fill-opacity":C,"font-size":C,height:C,opacity:C,path:"path",r:C,rx:C,ry:C,stroke:"colour","stroke-opacity":C,"stroke-width":C,transform:"transform",width:C,x:C,y:C},V=/[\x09\x0a\x0b\x0c\x0d\x20\xa0\u1680\u180e\u2000\u2001\u2002\u2003\u2004\u2005\u2006\u2007\u2008\u2009\u200a\u202f\u205f\u3000\u2028\u2029]/g,W=/[\x09\x0a\x0b\x0c\x0d\x20\xa0\u1680\u180e\u2000\u2001\u2002\u2003\u2004\u2005\u2006\u2007\u2008\u2009\u200a\u202f\u205f\u3000\u2028\u2029]*,[\x09\x0a\x0b\x0c\x0d\x20\xa0\u1680\u180e\u2000\u2001\u2002\u2003\u2004\u2005\u2006\u2007\u2008\u2009\u200a\u202f\u205f\u3000\u2028\u2029]*/,X={hs:1,rg:1},Y=/,?([achlmqrstvxz]),?/gi,Z=/([achlmrqstvz])[\x09\x0a\x0b\x0c\x0d\x20\xa0\u1680\u180e\u2000\u2001\u2002\u2003\u2004\u2005\u2006\u2007\u2008\u2009\u200a\u202f\u205f\u3000\u2028\u2029,]*((-?\d*\.?\d*(?:e[\-+]?\d+)?[\x09\x0a\x0b\x0c\x0d\x20\xa0\u1680\u180e\u2000\u2001\u2002\u2003\u2004\u2005\u2006\u2007\u2008\u2009\u200a\u202f\u205f\u3000\u2028\u2029]*,?[\x09\x0a\x0b\x0c\x0d\x20\xa0\u1680\u180e\u2000\u2001\u2002\u2003\u2004\u2005\u2006\u2007\u2008\u2009\u200a\u202f\u205f\u3000\u2028\u2029]*)+)/ig,$=/([rstm])[\x09\x0a\x0b\x0c\x0d\x20\xa0\u1680\u180e\u2000\u2001\u2002\u2003\u2004\u2005\u2006\u2007\u2008\u2009\u200a\u202f\u205f\u3000\u2028\u2029,]*((-?\d*\.?\d*(?:e[\-+]?\d+)?[\x09\x0a\x0b\x0c\x0d\x20\xa0\u1680\u180e\u2000\u2001\u2002\u2003\u2004\u2005\u2006\u2007\u2008\u2009\u200a\u202f\u205f\u3000\u2028\u2029]*,?[\x09\x0a\x0b\x0c\x0d\x20\xa0\u1680\u180e\u2000\u2001\u2002\u2003\u2004\u2005\u2006\u2007\u2008\u2009\u200a\u202f\u205f\u3000\u2028\u2029]*)+)/ig,_=/(-?\d*\.?\d*(?:e[\-+]?\d+)?)[\x09\x0a\x0b\x0c\x0d\x20\xa0\u1680\u180e\u2000\u2001\u2002\u2003\u2004\u2005\u2006\u2007\u2008\u2009\u200a\u202f\u205f\u3000\u2028\u2029]*,?[\x09\x0a\x0b\x0c\x0d\x20\xa0\u1680\u180e\u2000\u2001\u2002\u2003\u2004\u2005\u2006\u2007\u2008\u2009\u200a\u202f\u205f\u3000\u2028\u2029]*/ig,ba=a._radial_gradient=/^r(?:\(([^,]+?)[\x09\x0a\x0b\x0c\x0d\x20\xa0\u1680\u180e\u2000\u2001\u2002\u2003\u2004\u2005\u2006\u2007\u2008\u2009\u200a\u202f\u205f\u3000\u2028\u2029]*,[\x09\x0a\x0b\x0c\x0d\x20\xa0\u1680\u180e\u2000\u2001\u2002\u2003\u2004\u2005\u2006\u2007\u2008\u2009\u200a\u202f\u205f\u3000\u2028\u2029]*([^\)]+?)\))?/,bb={},bc=function(a,b){return a.key-b.key},bd=function(a,b){return Q(a)-Q(b)},be=function(){},bf=function(a){return a},bg=a._rectPath=function(a,b,c,d,e){if(e)return[["M",a+e,b],["l",c-e*2,0],["a",e,e,0,0,1,e,e],["l",0,d-e*2],["a",e,e,0,0,1,-e,e],["l",e*2-c,0],["a",e,e,0,0,1,-e,-e],["l",0,e*2-d],["a",e,e,0,0,1,e,-e],["z"]];return[["M",a,b],["l",c,0],["l",0,d],["l",-c,0],["z"]]},bh=function(a,b,c,d){d==null&&(d=c);return[["M",a,b],["m",0,-d],["a",c,d,0,1,1,0,2*d],["a",c,d,0,1,1,0,-2*d],["z"]]},bi=a._getPath={path:function(a){return a.attr("path")},circle:function(a){var b=a.attrs;return bh(b.cx,b.cy,b.r)},ellipse:function(a){var b=a.attrs;return bh(b.cx,b.cy,b.rx,b.ry)},rect:function(a){var b=a.attrs;return bg(b.x,b.y,b.width,b.height,b.r)},image:function(a){var b=a.attrs;return bg(b.x,b.y,b.width,b.height)},text:function(a){var b=a._getBBox();return bg(b.x,b.y,b.width,b.height)}},bj=a.mapPath=function(a,b){if(!b)return a;var c,d,e,f,g,h,i;a=bR(a);for(e=0,g=a.length;e<g;e++){i=a[e];for(f=1,h=i.length;f<h;f+=2)c=b.x(i[f],i[f+1]),d=b.y(i[f],i[f+1]),i[f]=c,i[f+1]=d}return a};a._g=h,a.type=h.win.SVGAngle||h.doc.implementation.hasFeature("http://www.w3.org/TR/SVG11/feature#BasicStructure","1.1")?"SVG":"VML";if(a.type=="VML"){var bk=h.doc.createElement("div"),bl;bk.innerHTML='<v:shape adj="1"/>',bl=bk.firstChild,bl.style.behavior="url(#default#VML)";if(!bl||typeof bl.adj!="object")return a.type=p;bk=null}a.svg=!(a.vml=a.type=="VML"),a._Paper=j,a.fn=k=j.prototype=a.prototype,a._id=0,a._oid=0,a.is=function(a,b){b=v.call(b);if(b=="finite")return!M[g](+a);if(b=="array")return a instanceof Array;return b=="null"&&a===null||b==typeof a&&a!==null||b=="object"&&a===Object(a)||b=="array"&&Array.isArray&&Array.isArray(a)||H.call(a).slice(8,-1).toLowerCase()==b},a.angle=function(b,c,d,e,f,g){if(f==null){var h=b-d,i=c-e;if(!h&&!i)return 0;return(180+w.atan2(-i,-h)*180/B+360)%360}return a.angle(b,c,f,g)-a.angle(d,e,f,g)},a.rad=function(a){return a%360*B/180},a.deg=function(a){return a*180/B%360},a.snapTo=function(b,c,d){d=a.is(d,"finite")?d:10;if(a.is(b,E)){var e=b.length;while(e--)if(z(b[e]-c)<=d)return b[e]}else{b=+b;var f=c%b;if(f<d)return c-f;if(f>b-d)return c-f+b}return c};var bn=a.createUUID=function(a,b){return function(){return"xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx".replace(a,b).toUpperCase()}}(/[xy]/g,function(a){var b=w.random()*16|0,c=a=="x"?b:b&3|8;return c.toString(16)});a.setWindow=function(b){eve("raphael.setWindow",a,h.win,b),h.win=b,h.doc=h.win.document,a._engine.initWin&&a._engine.initWin(h.win)};var bo=function(b){if(a.vml){var c=/^\s+|\s+$/g,d;try{var e=new ActiveXObject("htmlfile");e.write("<body>"),e.close(),d=e.body}catch(f){d=createPopup().document.body}var g=d.createTextRange();bo=bv(function(a){try{d.style.color=r(a).replace(c,p);var b=g.queryCommandValue("ForeColor");b=(b&255)<<16|b&65280|(b&16711680)>>>16;return"#"+("000000"+b.toString(16)).slice(-6)}catch(e){return"none"}})}else{var i=h.doc.createElement("i");i.title="Raphaël Colour Picker",i.style.display="none",h.doc.body.appendChild(i),bo=bv(function(a){i.style.color=a;return h.doc.defaultView.getComputedStyle(i,p).getPropertyValue("color")})}return bo(b)},bp=function(){return"hsb("+[this.h,this.s,this.b]+")"},bq=function(){return"hsl("+[this.h,this.s,this.l]+")"},br=function(){return this.hex},bs=function(b,c,d){c==null&&a.is(b,"object")&&"r"in b&&"g"in b&&"b"in b&&(d=b.b,c=b.g,b=b.r);if(c==null&&a.is(b,D)){var e=a.getRGB(b);b=e.r,c=e.g,d=e.b}if(b>1||c>1||d>1)b/=255,c/=255,d/=255;return[b,c,d]},bt=function(b,c,d,e){b*=255,c*=255,d*=255;var f={r:b,g:c,b:d,hex:a.rgb(b,c,d),toString:br};a.is(e,"finite")&&(f.opacity=e);return f};a.color=function(b){var c;a.is(b,"object")&&"h"in b&&"s"in b&&"b"in b?(c=a.hsb2rgb(b),b.r=c.r,b.g=c.g,b.b=c.b,b.hex=c.hex):a.is(b,"object")&&"h"in b&&"s"in b&&"l"in b?(c=a.hsl2rgb(b),b.r=c.r,b.g=c.g,b.b=c.b,b.hex=c.hex):(a.is(b,"string")&&(b=a.getRGB(b)),a.is(b,"object")&&"r"in b&&"g"in b&&"b"in b?(c=a.rgb2hsl(b),b.h=c.h,b.s=c.s,b.l=c.l,c=a.rgb2hsb(b),b.v=c.b):(b={hex:"none"},b.r=b.g=b.b=b.h=b.s=b.v=b.l=-1)),b.toString=br;return b},a.hsb2rgb=function(a,b,c,d){this.is(a,"object")&&"h"in a&&"s"in a&&"b"in a&&(c=a.b,b=a.s,a=a.h,d=a.o),a*=360;var e,f,g,h,i;a=a%360/60,i=c*b,h=i*(1-z(a%2-1)),e=f=g=c-i,a=~~a,e+=[i,h,0,0,h,i][a],f+=[h,i,i,h,0,0][a],g+=[0,0,h,i,i,h][a];return bt(e,f,g,d)},a.hsl2rgb=function(a,b,c,d){this.is(a,"object")&&"h"in a&&"s"in a&&"l"in a&&(c=a.l,b=a.s,a=a.h);if(a>1||b>1||c>1)a/=360,b/=100,c/=100;a*=360;var e,f,g,h,i;a=a%360/60,i=2*b*(c<.5?c:1-c),h=i*(1-z(a%2-1)),e=f=g=c-i/2,a=~~a,e+=[i,h,0,0,h,i][a],f+=[h,i,i,h,0,0][a],g+=[0,0,h,i,i,h][a];return bt(e,f,g,d)},a.rgb2hsb=function(a,b,c){c=bs(a,b,c),a=c[0],b=c[1],c=c[2];var d,e,f,g;f=x(a,b,c),g=f-y(a,b,c),d=g==0?null:f==a?(b-c)/g:f==b?(c-a)/g+2:(a-b)/g+4,d=(d+360)%6*60/360,e=g==0?0:g/f;return{h:d,s:e,b:f,toString:bp}},a.rgb2hsl=function(a,b,c){c=bs(a,b,c),a=c[0],b=c[1],c=c[2];var d,e,f,g,h,i;g=x(a,b,c),h=y(a,b,c),i=g-h,d=i==0?null:g==a?(b-c)/i:g==b?(c-a)/i+2:(a-b)/i+4,d=(d+360)%6*60/360,f=(g+h)/2,e=i==0?0:f<.5?i/(2*f):i/(2-2*f);return{h:d,s:e,l:f,toString:bq}},a._path2string=function(){return this.join(",").replace(Y,"$1")};var bw=a._preload=function(a,b){var c=h.doc.createElement("img");c.style.cssText="position:absolute;left:-9999em;top:-9999em",c.onload=function(){b.call(this),this.onload=null,h.doc.body.removeChild(this)},c.onerror=function(){h.doc.body.removeChild(this)},h.doc.body.appendChild(c),c.src=a};a.getRGB=bv(function(b){if(!b||!!((b=r(b)).indexOf("-")+1))return{r:-1,g:-1,b:-1,hex:"none",error:1,toString:bx};if(b=="none")return{r:-1,g:-1,b:-1,hex:"none",toString:bx};!X[g](b.toLowerCase().substring(0,2))&&b.charAt()!="#"&&(b=bo(b));var c,d,e,f,h,i,j,k=b.match(L);if(k){k[2]&&(f=R(k[2].substring(5),16),e=R(k[2].substring(3,5),16),d=R(k[2].substring(1,3),16)),k[3]&&(f=R((i=k[3].charAt(3))+i,16),e=R((i=k[3].charAt(2))+i,16),d=R((i=k[3].charAt(1))+i,16)),k[4]&&(j=k[4][s](W),d=Q(j[0]),j[0].slice(-1)=="%"&&(d*=2.55),e=Q(j[1]),j[1].slice(-1)=="%"&&(e*=2.55),f=Q(j[2]),j[2].slice(-1)=="%"&&(f*=2.55),k[1].toLowerCase().slice(0,4)=="rgba"&&(h=Q(j[3])),j[3]&&j[3].slice(-1)=="%"&&(h/=100));if(k[5]){j=k[5][s](W),d=Q(j[0]),j[0].slice(-1)=="%"&&(d*=2.55),e=Q(j[1]),j[1].slice(-1)=="%"&&(e*=2.55),f=Q(j[2]),j[2].slice(-1)=="%"&&(f*=2.55),(j[0].slice(-3)=="deg"||j[0].slice(-1)=="°")&&(d/=360),k[1].toLowerCase().slice(0,4)=="hsba"&&(h=Q(j[3])),j[3]&&j[3].slice(-1)=="%"&&(h/=100);return a.hsb2rgb(d,e,f,h)}if(k[6]){j=k[6][s](W),d=Q(j[0]),j[0].slice(-1)=="%"&&(d*=2.55),e=Q(j[1]),j[1].slice(-1)=="%"&&(e*=2.55),f=Q(j[2]),j[2].slice(-1)=="%"&&(f*=2.55),(j[0].slice(-3)=="deg"||j[0].slice(-1)=="°")&&(d/=360),k[1].toLowerCase().slice(0,4)=="hsla"&&(h=Q(j[3])),j[3]&&j[3].slice(-1)=="%"&&(h/=100);return a.hsl2rgb(d,e,f,h)}k={r:d,g:e,b:f,toString:bx},k.hex="#"+(16777216|f|e<<8|d<<16).toString(16).slice(1),a.is(h,"finite")&&(k.opacity=h);return k}return{r:-1,g:-1,b:-1,hex:"none",error:1,toString:bx}},a),a.hsb=bv(function(b,c,d){return a.hsb2rgb(b,c,d).hex}),a.hsl=bv(function(b,c,d){return a.hsl2rgb(b,c,d).hex}),a.rgb=bv(function(a,b,c){return"#"+(16777216|c|b<<8|a<<16).toString(16).slice(1)}),a.getColor=function(a){var b=this.getColor.start=this.getColor.start||{h:0,s:1,b:a||.75},c=this.hsb2rgb(b.h,b.s,b.b);b.h+=.075,b.h>1&&(b.h=0,b.s-=.2,b.s<=0&&(this.getColor.start={h:0,s:1,b:b.b}));return c.hex},a.getColor.reset=function(){delete this.start},a.parsePathString=function(b){if(!b)return null;var c=bz(b);if(c.arr)return bJ(c.arr);var d={a:7,c:6,h:1,l:2,m:2,r:4,q:4,s:4,t:2,v:1,z:0},e=[];a.is(b,E)&&a.is(b[0],E)&&(e=bJ(b)),e.length||r(b).replace(Z,function(a,b,c){var f=[],g=b.toLowerCase();c.replace(_,function(a,b){b&&f.push(+b)}),g=="m"&&f.length>2&&(e.push([b][n](f.splice(0,2))),g="l",b=b=="m"?"l":"L");if(g=="r")e.push([b][n](f));else while(f.length>=d[g]){e.push([b][n](f.splice(0,d[g])));if(!d[g])break}}),e.toString=a._path2string,c.arr=bJ(e);return e},a.parseTransformString=bv(function(b){if(!b)return null;var c={r:3,s:4,t:2,m:6},d=[];a.is(b,E)&&a.is(b[0],E)&&(d=bJ(b)),d.length||r(b).replace($,function(a,b,c){var e=[],f=v.call(b);c.replace(_,function(a,b){b&&e.push(+b)}),d.push([b][n](e))}),d.toString=a._path2string;return d});var bz=function(a){var b=bz.ps=bz.ps||{};b[a]?b[a].sleep=100:b[a]={sleep:100},setTimeout(function(){for(var c in b)b[g](c)&&c!=a&&(b[c].sleep--,!b[c].sleep&&delete b[c])});return b[a]};a.findDotsAtSegment=function(a,b,c,d,e,f,g,h,i){var j=1-i,k=A(j,3),l=A(j,2),m=i*i,n=m*i,o=k*a+l*3*i*c+j*3*i*i*e+n*g,p=k*b+l*3*i*d+j*3*i*i*f+n*h,q=a+2*i*(c-a)+m*(e-2*c+a),r=b+2*i*(d-b)+m*(f-2*d+b),s=c+2*i*(e-c)+m*(g-2*e+c),t=d+2*i*(f-d)+m*(h-2*f+d),u=j*a+i*c,v=j*b+i*d,x=j*e+i*g,y=j*f+i*h,z=90-w.atan2(q-s,r-t)*180/B;(q>s||r<t)&&(z+=180);return{x:o,y:p,m:{x:q,y:r},n:{x:s,y:t},start:{x:u,y:v},end:{x:x,y:y},alpha:z}},a.bezierBBox=function(b,c,d,e,f,g,h,i){a.is(b,"array")||(b=[b,c,d,e,f,g,h,i]);var j=bQ.apply(null,b);return{x:j.min.x,y:j.min.y,x2:j.max.x,y2:j.max.y,width:j.max.x-j.min.x,height:j.max.y-j.min.y}},a.isPointInsideBBox=function(a,b,c){return b>=a.x&&b<=a.x2&&c>=a.y&&c<=a.y2},a.isBBoxIntersect=function(b,c){var d=a.isPointInsideBBox;return d(c,b.x,b.y)||d(c,b.x2,b.y)||d(c,b.x,b.y2)||d(c,b.x2,b.y2)||d(b,c.x,c.y)||d(b,c.x2,c.y)||d(b,c.x,c.y2)||d(b,c.x2,c.y2)||(b.x<c.x2&&b.x>c.x||c.x<b.x2&&c.x>b.x)&&(b.y<c.y2&&b.y>c.y||c.y<b.y2&&c.y>b.y)},a.pathIntersection=function(a,b){return bH(a,b)},a.pathIntersectionNumber=function(a,b){return bH(a,b,1)},a.isPointInsidePath=function(b,c,d){var e=a.pathBBox(b);return a.isPointInsideBBox(e,c,d)&&bH(b,[["M",c,d],["H",e.x2+10]],1)%2==1},a._removedFactory=function(a){return function(){eve("raphael.log",null,"Raphaël: you are calling to method “"+a+"” of removed object",a)}};var bI=a.pathBBox=function(a){var b=bz(a);if(b.bbox)return b.bbox;if(!a)return{x:0,y:0,width:0,height:0,x2:0,y2:0};a=bR(a);var c=0,d=0,e=[],f=[],g;for(var h=0,i=a.length;h<i;h++){g=a[h];if(g[0]=="M")c=g[1],d=g[2],e.push(c),f.push(d);else{var j=bQ(c,d,g[1],g[2],g[3],g[4],g[5],g[6]);e=e[n](j.min.x,j.max.x),f=f[n](j.min.y,j.max.y),c=g[5],d=g[6]}}var k=y[m](0,e),l=y[m](0,f),o=x[m](0,e),p=x[m](0,f),q={x:k,y:l,x2:o,y2:p,width:o-k,height:p-l};b.bbox=bm(q);return q},bJ=function(b){var c=bm(b);c.toString=a._path2string;return c},bK=a._pathToRelative=function(b){var c=bz(b);if(c.rel)return bJ(c.rel);if(!a.is(b,E)||!a.is(b&&b[0],E))b=a.parsePathString(b);var d=[],e=0,f=0,g=0,h=0,i=0;b[0][0]=="M"&&(e=b[0][1],f=b[0][2],g=e,h=f,i++,d.push(["M",e,f]));for(var j=i,k=b.length;j<k;j++){var l=d[j]=[],m=b[j];if(m[0]!=v.call(m[0])){l[0]=v.call(m[0]);switch(l[0]){case"a":l[1]=m[1],l[2]=m[2],l[3]=m[3],l[4]=m[4],l[5]=m[5],l[6]=+(m[6]-e).toFixed(3),l[7]=+(m[7]-f).toFixed(3);break;case"v":l[1]=+(m[1]-f).toFixed(3);break;case"m":g=m[1],h=m[2];default:for(var n=1,o=m.length;n<o;n++)l[n]=+(m[n]-(n%2?e:f)).toFixed(3)}}else{l=d[j]=[],m[0]=="m"&&(g=m[1]+e,h=m[2]+f);for(var p=0,q=m.length;p<q;p++)d[j][p]=m[p]}var r=d[j].length;switch(d[j][0]){case"z":e=g,f=h;break;case"h":e+=+d[j][r-1];break;case"v":f+=+d[j][r-1];break;default:e+=+d[j][r-2],f+=+d[j][r-1]}}d.toString=a._path2string,c.rel=bJ(d);return d},bL=a._pathToAbsolute=function(b){var c=bz(b);if(c.abs)return bJ(c.abs);if(!a.is(b,E)||!a.is(b&&b[0],E))b=a.parsePathString(b);if(!b||!b.length)return[["M",0,0]];var d=[],e=0,f=0,g=0,h=0,i=0;b[0][0]=="M"&&(e=+b[0][1],f=+b[0][2],g=e,h=f,i++,d[0]=["M",e,f]);var j=b.length==3&&b[0][0]=="M"&&b[1][0].toUpperCase()=="R"&&b[2][0].toUpperCase()=="Z";for(var k,l,m=i,o=b.length;m<o;m++){d.push(k=[]),l=b[m];if(l[0]!=S.call(l[0])){k[0]=S.call(l[0]);switch(k[0]){case"A":k[1]=l[1],k[2]=l[2],k[3]=l[3],k[4]=l[4],k[5]=l[5],k[6]=+(l[6]+e),k[7]=+(l[7]+f);break;case"V":k[1]=+l[1]+f;break;case"H":k[1]=+l[1]+e;break;case"R":var p=[e,f][n](l.slice(1));for(var q=2,r=p.length;q<r;q++)p[q]=+p[q]+e,p[++q]=+p[q]+f;d.pop(),d=d[n](by(p,j));break;case"M":g=+l[1]+e,h=+l[2]+f;default:for(q=1,r=l.length;q<r;q++)k[q]=+l[q]+(q%2?e:f)}}else if(l[0]=="R")p=[e,f][n](l.slice(1)),d.pop(),d=d[n](by(p,j)),k=["R"][n](l.slice(-2));else for(var s=0,t=l.length;s<t;s++)k[s]=l[s];switch(k[0]){case"Z":e=g,f=h;break;case"H":e=k[1];break;case"V":f=k[1];break;case"M":g=k[k.length-2],h=k[k.length-1];default:e=k[k.length-2],f=k[k.length-1]}}d.toString=a._path2string,c.abs=bJ(d);return d},bM=function(a,b,c,d){return[a,b,c,d,c,d]},bN=function(a,b,c,d,e,f){var g=1/3,h=2/3;return[g*a+h*c,g*b+h*d,g*e+h*c,g*f+h*d,e,f]},bO=function(a,b,c,d,e,f,g,h,i,j){var k=B*120/180,l=B/180*(+e||0),m=[],o,p=bv(function(a,b,c){var d=a*w.cos(c)-b*w.sin(c),e=a*w.sin(c)+b*w.cos(c);return{x:d,y:e}});if(!j){o=p(a,b,-l),a=o.x,b=o.y,o=p(h,i,-l),h=o.x,i=o.y;var q=w.cos(B/180*e),r=w.sin(B/180*e),t=(a-h)/2,u=(b-i)/2,v=t*t/(c*c)+u*u/(d*d);v>1&&(v=w.sqrt(v),c=v*c,d=v*d);var x=c*c,y=d*d,A=(f==g?-1:1)*w.sqrt(z((x*y-x*u*u-y*t*t)/(x*u*u+y*t*t))),C=A*c*u/d+(a+h)/2,D=A*-d*t/c+(b+i)/2,E=w.asin(((b-D)/d).toFixed(9)),F=w.asin(((i-D)/d).toFixed(9));E=a<C?B-E:E,F=h<C?B-F:F,E<0&&(E=B*2+E),F<0&&(F=B*2+F),g&&E>F&&(E=E-B*2),!g&&F>E&&(F=F-B*2)}else E=j[0],F=j[1],C=j[2],D=j[3];var G=F-E;if(z(G)>k){var H=F,I=h,J=i;F=E+k*(g&&F>E?1:-1),h=C+c*w.cos(F),i=D+d*w.sin(F),m=bO(h,i,c,d,e,0,g,I,J,[F,H,C,D])}G=F-E;var K=w.cos(E),L=w.sin(E),M=w.cos(F),N=w.sin(F),O=w.tan(G/4),P=4/3*c*O,Q=4/3*d*O,R=[a,b],S=[a+P*L,b-Q*K],T=[h+P*N,i-Q*M],U=[h,i];S[0]=2*R[0]-S[0],S[1]=2*R[1]-S[1];if(j)return[S,T,U][n](m);m=[S,T,U][n](m).join()[s](",");var V=[];for(var W=0,X=m.length;W<X;W++)V[W]=W%2?p(m[W-1],m[W],l).y:p(m[W],m[W+1],l).x;return V},bP=function(a,b,c,d,e,f,g,h,i){var j=1-i;return{x:A(j,3)*a+A(j,2)*3*i*c+j*3*i*i*e+A(i,3)*g,y:A(j,3)*b+A(j,2)*3*i*d+j*3*i*i*f+A(i,3)*h}},bQ=bv(function(a,b,c,d,e,f,g,h){var i=e-2*c+a-(g-2*e+c),j=2*(c-a)-2*(e-c),k=a-c,l=(-j+w.sqrt(j*j-4*i*k))/2/i,n=(-j-w.sqrt(j*j-4*i*k))/2/i,o=[b,h],p=[a,g],q;z(l)>"1e12"&&(l=.5),z(n)>"1e12"&&(n=.5),l>0&&l<1&&(q=bP(a,b,c,d,e,f,g,h,l),p.push(q.x),o.push(q.y)),n>0&&n<1&&(q=bP(a,b,c,d,e,f,g,h,n),p.push(q.x),o.push(q.y)),i=f-2*d+b-(h-2*f+d),j=2*(d-b)-2*(f-d),k=b-d,l=(-j+w.sqrt(j*j-4*i*k))/2/i,n=(-j-w.sqrt(j*j-4*i*k))/2/i,z(l)>"1e12"&&(l=.5),z(n)>"1e12"&&(n=.5),l>0&&l<1&&(q=bP(a,b,c,d,e,f,g,h,l),p.push(q.x),o.push(q.y)),n>0&&n<1&&(q=bP(a,b,c,d,e,f,g,h,n),p.push(q.x),o.push(q.y));return{min:{x:y[m](0,p),y:y[m](0,o)},max:{x:x[m](0,p),y:x[m](0,o)}}}),bR=a._path2curve=bv(function(a,b){var c=!b&&bz(a);if(!b&&c.curve)return bJ(c.curve);var d=bL(a),e=b&&bL(b),f={x:0,y:0,bx:0,by:0,X:0,Y:0,qx:null,qy:null},g={x:0,y:0,bx:0,by:0,X:0,Y:0,qx:null,qy:null},h=function(a,b){var c,d;if(!a)return["C",b.x,b.y,b.x,b.y,b.x,b.y];!(a[0]in{T:1,Q:1})&&(b.qx=b.qy=null);switch(a[0]){case"M":b.X=a[1],b.Y=a[2];break;case"A":a=["C"][n](bO[m](0,[b.x,b.y][n](a.slice(1))));break;case"S":c=b.x+(b.x-(b.bx||b.x)),d=b.y+(b.y-(b.by||b.y)),a=["C",c,d][n](a.slice(1));break;case"T":b.qx=b.x+(b.x-(b.qx||b.x)),b.qy=b.y+(b.y-(b.qy||b.y)),a=["C"][n](bN(b.x,b.y,b.qx,b.qy,a[1],a[2]));break;case"Q":b.qx=a[1],b.qy=a[2],a=["C"][n](bN(b.x,b.y,a[1],a[2],a[3],a[4]));break;case"L":a=["C"][n](bM(b.x,b.y,a[1],a[2]));break;case"H":a=["C"][n](bM(b.x,b.y,a[1],b.y));break;case"V":a=["C"][n](bM(b.x,b.y,b.x,a[1]));break;case"Z":a=["C"][n](bM(b.x,b.y,b.X,b.Y))}return a},i=function(a,b){if(a[b].length>7){a[b].shift();var c=a[b];while(c.length)a.splice(b++,0,["C"][n](c.splice(0,6)));a.splice(b,1),l=x(d.length,e&&e.length||0)}},j=function(a,b,c,f,g){a&&b&&a[g][0]=="M"&&b[g][0]!="M"&&(b.splice(g,0,["M",f.x,f.y]),c.bx=0,c.by=0,c.x=a[g][1],c.y=a[g][2],l=x(d.length,e&&e.length||0))};for(var k=0,l=x(d.length,e&&e.length||0);k<l;k++){d[k]=h(d[k],f),i(d,k),e&&(e[k]=h(e[k],g)),e&&i(e,k),j(d,e,f,g,k),j(e,d,g,f,k);var o=d[k],p=e&&e[k],q=o.length,r=e&&p.length;f.x=o[q-2],f.y=o[q-1],f.bx=Q(o[q-4])||f.x,f.by=Q(o[q-3])||f.y,g.bx=e&&(Q(p[r-4])||g.x),g.by=e&&(Q(p[r-3])||g.y),g.x=e&&p[r-2],g.y=e&&p[r-1]}e||(c.curve=bJ(d));return e?[d,e]:d},null,bJ),bS=a._parseDots=bv(function(b){var c=[];for(var d=0,e=b.length;d<e;d++){var f={},g=b[d].match(/^([^:]*):?([\d\.]*)/);f.color=a.getRGB(g[1]);if(f.color.error)return null;f.color=f.color.hex,g[2]&&(f.offset=g[2]+"%"),c.push(f)}for(d=1,e=c.length-1;d<e;d++)if(!c[d].offset){var h=Q(c[d-1].offset||0),i=0;for(var j=d+1;j<e;j++)if(c[j].offset){i=c[j].offset;break}i||(i=100,j=e),i=Q(i);var k=(i-h)/(j-d+1);for(;d<j;d++)h+=k,c[d].offset=h+"%"}return c}),bT=a._tear=function(a,b){a==b.top&&(b.top=a.prev),a==b.bottom&&(b.bottom=a.next),a.next&&(a.next.prev=a.prev),a.prev&&(a.prev.next=a.next)},bU=a._tofront=function(a,b){b.top!==a&&(bT(a,b),a.next=null,a.prev=b.top,b.top.next=a,b.top=a)},bV=a._toback=function(a,b){b.bottom!==a&&(bT(a,b),a.next=b.bottom,a.prev=null,b.bottom.prev=a,b.bottom=a)},bW=a._insertafter=function(a,b,c){bT(a,c),b==c.top&&(c.top=a),b.next&&(b.next.prev=a),a.next=b.next,a.prev=b,b.next=a},bX=a._insertbefore=function(a,b,c){bT(a,c),b==c.bottom&&(c.bottom=a),b.prev&&(b.prev.next=a),a.prev=b.prev,b.prev=a,a.next=b},bY=a.toMatrix=function(a,b){var c=bI(a),d={_:{transform:p},getBBox:function(){return c}};b$(d,b);return d.matrix},bZ=a.transformPath=function(a,b){return bj(a,bY(a,b))},b$=a._extractTransform=function(b,c){if(c==null)return b._.transform;c=r(c).replace(/\.{3}|\u2026/g,b._.transform||p);var d=a.parseTransformString(c),e=0,f=0,g=0,h=1,i=1,j=b._,k=new cb;j.transform=d||[];if(d)for(var l=0,m=d.length;l<m;l++){var n=d[l],o=n.length,q=r(n[0]).toLowerCase(),s=n[0]!=q,t=s?k.invert():0,u,v,w,x,y;q=="t"&&o==3?s?(u=t.x(0,0),v=t.y(0,0),w=t.x(n[1],n[2]),x=t.y(n[1],n[2]),k.translate(w-u,x-v)):k.translate(n[1],n[2]):q=="r"?o==2?(y=y||b.getBBox(1),k.rotate(n[1],y.x+y.width/2,y.y+y.height/2),e+=n[1]):o==4&&(s?(w=t.x(n[2],n[3]),x=t.y(n[2],n[3]),k.rotate(n[1],w,x)):k.rotate(n[1],n[2],n[3]),e+=n[1]):q=="s"?o==2||o==3?(y=y||b.getBBox(1),k.scale(n[1],n[o-1],y.x+y.width/2,y.y+y.height/2),h*=n[1],i*=n[o-1]):o==5&&(s?(w=t.x(n[3],n[4]),x=t.y(n[3],n[4]),k.scale(n[1],n[2],w,x)):k.scale(n[1],n[2],n[3],n[4]),h*=n[1],i*=n[2]):q=="m"&&o==7&&k.add(n[1],n[2],n[3],n[4],n[5],n[6]),j.dirtyT=1,b.matrix=k}b.matrix=k,j.sx=h,j.sy=i,j.deg=e,j.dx=f=k.e,j.dy=g=k.f,h==1&&i==1&&!e&&j.bbox?(j.bbox.x+=+f,j.bbox.y+=+g):j.dirtyT=1},b_=function(a){var b=a[0];switch(b.toLowerCase()){case"t":return[b,0,0];case"m":return[b,1,0,0,1,0,0];case"r":return a.length==4?[b,0,a[2],a[3]]:[b,0];case"s":return a.length==5?[b,1,1,a[3],a[4]]:a.length==3?[b,1,1]:[b,1]}},ca=a._equaliseTransform=function(b,c){c=r(c).replace(/\.{3}|\u2026/g,b),b=a.parseTransformString(b)||[],c=a.parseTransformString(c)||[];var d=x(b.length,c.length),e=[],f=[],g=0,h,i,j,k;for(;g<d;g++){j=b[g]||b_(c[g]),k=c[g]||b_(j);if(j[0]!=k[0]||j[0].toLowerCase()=="r"&&(j[2]!=k[2]||j[3]!=k[3])||j[0].toLowerCase()=="s"&&(j[3]!=k[3]||j[4]!=k[4]))return;e[g]=[],f[g]=[];for(h=0,i=x(j.length,k.length);h<i;h++)h in j&&(e[g][h]=j[h]),h in k&&(f[g][h]=k[h])}return{from:e,to:f}};a._getContainer=function(b,c,d,e){var f;f=e==null&&!a.is(b,"object")?h.doc.getElementById(b):b;if(f!=null){if(f.tagName)return c==null?{container:f,width:f.style.pixelWidth||f.offsetWidth,height:f.style.pixelHeight||f.offsetHeight}:{container:f,width:c,height:d};return{container:1,x:b,y:c,width:d,height:e}}},a.pathToRelative=bK,a._engine={},a.path2curve=bR,a.matrix=function(a,b,c,d,e,f){return new cb(a,b,c,d,e,f)},function(b){function d(a){var b=w.sqrt(c(a));a[0]&&(a[0]/=b),a[1]&&(a[1]/=b)}function c(a){return a[0]*a[0]+a[1]*a[1]}b.add=function(a,b,c,d,e,f){var g=[[],[],[]],h=[[this.a,this.c,this.e],[this.b,this.d,this.f],[0,0,1]],i=[[a,c,e],[b,d,f],[0,0,1]],j,k,l,m;a&&a instanceof cb&&(i=[[a.a,a.c,a.e],[a.b,a.d,a.f],[0,0,1]]);for(j=0;j<3;j++)for(k=0;k<3;k++){m=0;for(l=0;l<3;l++)m+=h[j][l]*i[l][k];g[j][k]=m}this.a=g[0][0],this.b=g[1][0],this.c=g[0][1],this.d=g[1][1],this.e=g[0][2],this.f=g[1][2]},b.invert=function(){var a=this,b=a.a*a.d-a.b*a.c;return new cb(a.d/b,-a.b/b,-a.c/b,a.a/b,(a.c*a.f-a.d*a.e)/b,(a.b*a.e-a.a*a.f)/b)},b.clone=function(){return new cb(this.a,this.b,this.c,this.d,this.e,this.f)},b.translate=function(a,b){this.add(1,0,0,1,a,b)},b.scale=function(a,b,c,d){b==null&&(b=a),(c||d)&&this.add(1,0,0,1,c,d),this.add(a,0,0,b,0,0),(c||d)&&this.add(1,0,0,1,-c,-d)},b.rotate=function(b,c,d){b=a.rad(b),c=c||0,d=d||0;var e=+w.cos(b).toFixed(9),f=+w.sin(b).toFixed(9);this.add(e,f,-f,e,c,d),this.add(1,0,0,1,-c,-d)},b.x=function(a,b){return a*this.a+b*this.c+this.e},b.y=function(a,b){return a*this.b+b*this.d+this.f},b.get=function(a){return+this[r.fromCharCode(97+a)].toFixed(4)},b.toString=function(){return a.svg?"matrix("+[this.get(0),this.get(1),this.get(2),this.get(3),this.get(4),this.get(5)].join()+")":[this.get(0),this.get(2),this.get(1),this.get(3),0,0].join()},b.toFilter=function(){return"progid:DXImageTransform.Microsoft.Matrix(M11="+this.get(0)+", M12="+this.get(2)+", M21="+this.get(1)+", M22="+this.get(3)+", Dx="+this.get(4)+", Dy="+this.get(5)+", sizingmethod='auto expand')"},b.offset=function(){return[this.e.toFixed(4),this.f.toFixed(4)]},b.split=function(){var b={};b.dx=this.e,b.dy=this.f;var e=[[this.a,this.c],[this.b,this.d]];b.scalex=w.sqrt(c(e[0])),d(e[0]),b.shear=e[0][0]*e[1][0]+e[0][1]*e[1][1],e[1]=[e[1][0]-e[0][0]*b.shear,e[1][1]-e[0][1]*b.shear],b.scaley=w.sqrt(c(e[1])),d(e[1]),b.shear/=b.scaley;var f=-e[0][1],g=e[1][1];g<0?(b.rotate=a.deg(w.acos(g)),f<0&&(b.rotate=360-b.rotate)):b.rotate=a.deg(w.asin(f)),b.isSimple=!+b.shear.toFixed(9)&&(b.scalex.toFixed(9)==b.scaley.toFixed(9)||!b.rotate),b.isSuperSimple=!+b.shear.toFixed(9)&&b.scalex.toFixed(9)==b.scaley.toFixed(9)&&!b.rotate,b.noRotation=!+b.shear.toFixed(9)&&!b.rotate;return b},b.toTransformString=function(a){var b=a||this[s]();if(b.isSimple){b.scalex=+b.scalex.toFixed(4),b.scaley=+b.scaley.toFixed(4),b.rotate=+b.rotate.toFixed(4);return(b.dx||b.dy?"t"+[b.dx,b.dy]:p)+(b.scalex!=1||b.scaley!=1?"s"+[b.scalex,b.scaley,0,0]:p)+(b.rotate?"r"+[b.rotate,0,0]:p)}return"m"+[this.get(0),this.get(1),this.get(2),this.get(3),this.get(4),this.get(5)]}}(cb.prototype);var cc=navigator.userAgent.match(/Version\/(.*?)\s/)||navigator.userAgent.match(/Chrome\/(\d+)/);navigator.vendor=="Apple Computer, Inc."&&(cc&&cc[1]<4||navigator.platform.slice(0,2)=="iP")||navigator.vendor=="Google Inc."&&cc&&cc[1]<8?k.safari=function(){var a=this.rect(-99,-99,this.width+99,this.height+99).attr({stroke:"none"});setTimeout(function(){a.remove()})}:k.safari=be;var cd=function(){this.returnValue=!1},ce=function(){return this.originalEvent.preventDefault()},cf=function(){this.cancelBubble=!0},cg=function(){return this.originalEvent.stopPropagation()},ch=function(){if(h.doc.addEventListener)return function(a,b,c,d){var e=o&&u[b]?u[b]:b,f=function(e){var f=h.doc.documentElement.scrollTop||h.doc.body.scrollTop,i=h.doc.documentElement.scrollLeft||h.doc.body.scrollLeft,j=e.clientX+i,k=e.clientY+f;if(o&&u[g](b))for(var l=0,m=e.targetTouches&&e.targetTouches.length;l<m;l++)if(e.targetTouches[l].target==a){var n=e;e=e.targetTouches[l],e.originalEvent=n,e.preventDefault=ce,e.stopPropagation=cg;break}return c.call(d,e,j,k)};a.addEventListener(e,f,!1);return function(){a.removeEventListener(e,f,!1);return!0}};if(h.doc.attachEvent)return function(a,b,c,d){var e=function(a){a=a||h.win.event;var b=h.doc.documentElement.scrollTop||h.doc.body.scrollTop,e=h.doc.documentElement.scrollLeft||h.doc.body.scrollLeft,f=a.clientX+e,g=a.clientY+b;a.preventDefault=a.preventDefault||cd,a.stopPropagation=a.stopPropagation||cf;return c.call(d,a,f,g)};a.attachEvent("on"+b,e);var f=function(){a.detachEvent("on"+b,e);return!0};return f}}(),ci=[],cj=function(a){var b=a.clientX,c=a.clientY,d=h.doc.documentElement.scrollTop||h.doc.body.scrollTop,e=h.doc.documentElement.scrollLeft||h.doc.body.scrollLeft,f,g=ci.length;while(g--){f=ci[g];if(o){var i=a.touches.length,j;while(i--){j=a.touches[i];if(j.identifier==f.el._drag.id){b=j.clientX,c=j.clientY,(a.originalEvent?a.originalEvent:a).preventDefault();break}}}else a.preventDefault();var k=f.el.node,l,m=k.nextSibling,n=k.parentNode,p=k.style.display;h.win.opera&&n.removeChild(k),k.style.display="none",l=f.el.paper.getElementByPoint(b,c),k.style.display=p,h.win.opera&&(m?n.insertBefore(k,m):n.appendChild(k)),l&&eve("raphael.drag.over."+f.el.id,f.el,l),b+=e,c+=d,eve("raphael.drag.move."+f.el.id,f.move_scope||f.el,b-f.el._drag.x,c-f.el._drag.y,b,c,a)}},ck=function(b){a.unmousemove(cj).unmouseup(ck);var c=ci.length,d;while(c--)d=ci[c],d.el._drag={},eve("raphael.drag.end."+d.el.id,d.end_scope||d.start_scope||d.move_scope||d.el,b);ci=[]},cl=a.el={};for(var cm=t.length;cm--;)(function(b){a[b]=cl[b]=function(c,d){a.is(c,"function")&&(this.events=this.events||[],this.events.push({name:b,f:c,unbind:ch(this.shape||this.node||h.doc,b,c,d||this)}));return this},a["un"+b]=cl["un"+b]=function(a){var c=this.events||[],d=c.length;while(d--)if(c[d].name==b&&c[d].f==a){c[d].unbind(),c.splice(d,1),!c.length&&delete this.events;return this}return this}})(t[cm]);cl.data=function(b,c){var d=bb[this.id]=bb[this.id]||{};if(arguments.length==1){if(a.is(b,"object")){for(var e in b)b[g](e)&&this.data(e,b[e]);return this}eve("raphael.data.get."+this.id,this,d[b],b);return d[b]}d[b]=c,eve("raphael.data.set."+this.id,this,c,b);return this},cl.removeData=function(a){a==null?bb[this.id]={}:bb[this.id]&&delete bb[this.id][a];return this},cl.hover=function(a,b,c,d){return this.mouseover(a,c).mouseout(b,d||c)},cl.unhover=function(a,b){return this.unmouseover(a).unmouseout(b)};var cn=[];cl.drag=function(b,c,d,e,f,g){function i(i){(i.originalEvent||i).preventDefault();var j=h.doc.documentElement.scrollTop||h.doc.body.scrollTop,k=h.doc.documentElement.scrollLeft||h.doc.body.scrollLeft;this._drag.x=i.clientX+k,this._drag.y=i.clientY+j,this._drag.id=i.identifier,!ci.length&&a.mousemove(cj).mouseup(ck),ci.push({el:this,move_scope:e,start_scope:f,end_scope:g}),c&&eve.on("raphael.drag.start."+this.id,c),b&&eve.on("raphael.drag.move."+this.id,b),d&&eve.on("raphael.drag.end."+this.id,d),eve("raphael.drag.start."+this.id,f||e||this,i.clientX+k,i.clientY+j,i)}this._drag={},cn.push({el:this,start:i}),this.mousedown(i);return this},cl.onDragOver=function(a){a?eve.on("raphael.drag.over."+this.id,a):eve.unbind("raphael.drag.over."+this.id)},cl.undrag=function(){var b=cn.length;while(b--)cn[b].el==this&&(this.unmousedown(cn[b].start),cn.splice(b,1),eve.unbind("raphael.drag.*."+this.id));!cn.length&&a.unmousemove(cj).unmouseup(ck)},k.circle=function(b,c,d){var e=a._engine.circle(this,b||0,c||0,d||0);this.__set__&&this.__set__.push(e);return e},k.rect=function(b,c,d,e,f){var g=a._engine.rect(this,b||0,c||0,d||0,e||0,f||0);this.__set__&&this.__set__.push(g);return g},k.ellipse=function(b,c,d,e){var f=a._engine.ellipse(this,b||0,c||0,d||0,e||0);this.__set__&&this.__set__.push(f);return f},k.path=function(b){b&&!a.is(b,D)&&!a.is(b[0],E)&&(b+=p);var c=a._engine.path(a.format[m](a,arguments),this);this.__set__&&this.__set__.push(c);return c},k.image=function(b,c,d,e,f){var g=a._engine.image(this,b||"about:blank",c||0,d||0,e||0,f||0);this.__set__&&this.__set__.push(g);return g},k.text=function(b,c,d){var e=a._engine.text(this,b||0,c||0,r(d));this.__set__&&this.__set__.push(e);return e},k.set=function(b){!a.is(b,"array")&&(b=Array.prototype.splice.call(arguments,0,arguments.length));var c=new cG(b);this.__set__&&this.__set__.push(c);return c},k.setStart=function(a){this.__set__=a||this.set()},k.setFinish=function(a){var b=this.__set__;delete this.__set__;return b},k.setSize=function(b,c){return a._engine.setSize.call(this,b,c)},k.setViewBox=function(b,c,d,e,f){return a._engine.setViewBox.call(this,b,c,d,e,f)},k.top=k.bottom=null,k.raphael=a;var co=function(a){var b=a.getBoundingClientRect(),c=a.ownerDocument,d=c.body,e=c.documentElement,f=e.clientTop||d.clientTop||0,g=e.clientLeft||d.clientLeft||0,i=b.top+(h.win.pageYOffset||e.scrollTop||d.scrollTop)-f,j=b.left+(h.win.pageXOffset||e.scrollLeft||d.scrollLeft)-g;return{y:i,x:j}};k.getElementByPoint=function(a,b){var c=this,d=c.canvas,e=h.doc.elementFromPoint(a,b);if(h.win.opera&&e.tagName=="svg"){var f=co(d),g=d.createSVGRect();g.x=a-f.x,g.y=b-f.y,g.width=g.height=1;var i=d.getIntersectionList(g,null);i.length&&(e=i[i.length-1])}if(!e)return null;while(e.parentNode&&e!=d.parentNode&&!e.raphael)e=e.parentNode;e==c.canvas.parentNode&&(e=d),e=e&&e.raphael?c.getById(e.raphaelid):null;return e},k.getById=function(a){var b=this.bottom;while(b){if(b.id==a)return b;b=b.next}return null},k.forEach=function(a,b){var c=this.bottom;while(c){if(a.call(b,c)===!1)return this;c=c.next}return this},k.getElementsByPoint=function(a,b){var c=this.set();this.forEach(function(d){d.isPointInside(a,b)&&c.push(d)});return c},cl.isPointInside=function(b,c){var d=this.realPath=this.realPath||bi[this.type](this);return a.isPointInsidePath(d,b,c)},cl.getBBox=function(a){if(this.removed)return{};var b=this._;if(a){if(b.dirty||!b.bboxwt)this.realPath=bi[this.type](this),b.bboxwt=bI(this.realPath),b.bboxwt.toString=cq,b.dirty=0;return b.bboxwt}if(b.dirty||b.dirtyT||!b.bbox){if(b.dirty||!this.realPath)b.bboxwt=0,this.realPath=bi[this.type](this);b.bbox=bI(bj(this.realPath,this.matrix)),b.bbox.toString=cq,b.dirty=b.dirtyT=0}return b.bbox},cl.clone=function(){if(this.removed)return null;var a=this.paper[this.type]().attr(this.attr());this.__set__&&this.__set__.push(a);return a},cl.glow=function(a){if(this.type=="text")return null;a=a||{};var b={width:(a.width||10)+(+this.attr("stroke-width")||1),fill:a.fill||!1,opacity:a.opacity||.5,offsetx:a.offsetx||0,offsety:a.offsety||0,color:a.color||"#000"},c=b.width/2,d=this.paper,e=d.set(),f=this.realPath||bi[this.type](this);f=this.matrix?bj(f,this.matrix):f;for(var g=1;g<c+1;g++)e.push(d.path(f).attr({stroke:b.color,fill:b.fill?b.color:"none","stroke-linejoin":"round","stroke-linecap":"round","stroke-width":+(b.width/c*g).toFixed(3),opacity:+(b.opacity/c).toFixed(3)}));return e.insertBefore(this).translate(b.offsetx,b.offsety)};var cr={},cs=function(b,c,d,e,f,g,h,i,j){return j==null?bB(b,c,d,e,f,g,h,i):a.findDotsAtSegment(b,c,d,e,f,g,h,i,bC(b,c,d,e,f,g,h,i,j))},ct=function(b,c){return function(d,e,f){d=bR(d);var g,h,i,j,k="",l={},m,n=0;for(var o=0,p=d.length;o<p;o++){i=d[o];if(i[0]=="M")g=+i[1],h=+i[2];else{j=cs(g,h,i[1],i[2],i[3],i[4],i[5],i[6]);if(n+j>e){if(c&&!l.start){m=cs(g,h,i[1],i[2],i[3],i[4],i[5],i[6],e-n),k+=["C"+m.start.x,m.start.y,m.m.x,m.m.y,m.x,m.y];if(f)return k;l.start=k,k=["M"+m.x,m.y+"C"+m.n.x,m.n.y,m.end.x,m.end.y,i[5],i[6]].join(),n+=j,g=+i[5],h=+i[6];continue}if(!b&&!c){m=cs(g,h,i[1],i[2],i[3],i[4],i[5],i[6],e-n);return{x:m.x,y:m.y,alpha:m.alpha}}}n+=j,g=+i[5],h=+i[6]}k+=i.shift()+i}l.end=k,m=b?n:c?l:a.findDotsAtSegment(g,h,i[0],i[1],i[2],i[3],i[4],i[5],1),m.alpha&&(m={x:m.x,y:m.y,alpha:m.alpha});return m}},cu=ct(1),cv=ct(),cw=ct(0,1);a.getTotalLength=cu,a.getPointAtLength=cv,a.getSubpath=function(a,b,c){if(this.getTotalLength(a)-c<1e-6)return cw(a,b).end;var d=cw(a,c,1);return b?cw(d,b).end:d},cl.getTotalLength=function(){if(this.type=="path"){if(this.node.getTotalLength)return this.node.getTotalLength();return cu(this.attrs.path)}},cl.getPointAtLength=function(a){if(this.type=="path")return cv(this.attrs.path,a)},cl.getSubpath=function(b,c){if(this.type=="path")return a.getSubpath(this.attrs.path,b,c)};var cx=a.easing_formulas={linear:function(a){return a},"<":function(a){return A(a,1.7)},">":function(a){return A(a,.48)},"<>":function(a){var b=.48-a/1.04,c=w.sqrt(.1734+b*b),d=c-b,e=A(z(d),1/3)*(d<0?-1:1),f=-c-b,g=A(z(f),1/3)*(f<0?-1:1),h=e+g+.5;return(1-h)*3*h*h+h*h*h},backIn:function(a){var b=1.70158;return a*a*((b+1)*a-b)},backOut:function(a){a=a-1;var b=1.70158;return a*a*((b+1)*a+b)+1},elastic:function(a){if(a==!!a)return a;return A(2,-10*a)*w.sin((a-.075)*2*B/.3)+1},bounce:function(a){var b=7.5625,c=2.75,d;a<1/c?d=b*a*a:a<2/c?(a-=1.5/c,d=b*a*a+.75):a<2.5/c?(a-=2.25/c,d=b*a*a+.9375):(a-=2.625/c,d=b*a*a+.984375);return d}};cx.easeIn=cx["ease-in"]=cx["<"],cx.easeOut=cx["ease-out"]=cx[">"],cx.easeInOut=cx["ease-in-out"]=cx["<>"],cx["back-in"]=cx.backIn,cx["back-out"]=cx.backOut;var cy=[],cz=window.requestAnimationFrame||window.webkitRequestAnimationFrame||window.mozRequestAnimationFrame||window.oRequestAnimationFrame||window.msRequestAnimationFrame||function(a){setTimeout(a,16)},cA=function(){var b=+(new Date),c=0;for(;c<cy.length;c++){var d=cy[c];if(d.el.removed||d.paused)continue;var e=b-d.start,f=d.ms,h=d.easing,i=d.from,j=d.diff,k=d.to,l=d.t,m=d.el,o={},p,r={},s;d.initstatus?(e=(d.initstatus*d.anim.top-d.prev)/(d.percent-d.prev)*f,d.status=d.initstatus,delete d.initstatus,d.stop&&cy.splice(c--,1)):d.status=(d.prev+(d.percent-d.prev)*(e/f))/d.anim.top;if(e<0)continue;if(e<f){var t=h(e/f);for(var u in i)if(i[g](u)){switch(U[u]){case C:p=+i[u]+t*f*j[u];break;case"colour":p="rgb("+[cB(O(i[u].r+t*f*j[u].r)),cB(O(i[u].g+t*f*j[u].g)),cB(O(i[u].b+t*f*j[u].b))].join(",")+")";break;case"path":p=[];for(var v=0,w=i[u].length;v<w;v++){p[v]=[i[u][v][0]];for(var x=1,y=i[u][v].length;x<y;x++)p[v][x]=+i[u][v][x]+t*f*j[u][v][x];p[v]=p[v].join(q)}p=p.join(q);break;case"transform":if(j[u].real){p=[];for(v=0,w=i[u].length;v<w;v++){p[v]=[i[u][v][0]];for(x=1,y=i[u][v].length;x<y;x++)p[v][x]=i[u][v][x]+t*f*j[u][v][x]}}else{var z=function(a){return+i[u][a]+t*f*j[u][a]};p=[["m",z(0),z(1),z(2),z(3),z(4),z(5)]]}break;case"csv":if(u=="clip-rect"){p=[],v=4;while(v--)p[v]=+i[u][v]+t*f*j[u][v]}break;default:var A=[][n](i[u]);p=[],v=m.paper.customAttributes[u].length;while(v--)p[v]=+A[v]+t*f*j[u][v]}o[u]=p}m.attr(o),function(a,b,c){setTimeout(function(){eve("raphael.anim.frame."+a,b,c)})}(m.id,m,d.anim)}else{(function(b,c,d){setTimeout(function(){eve("raphael.anim.frame."+c.id,c,d),eve("raphael.anim.finish."+c.id,c,d),a.is(b,"function")&&b.call(c)})})(d.callback,m,d.anim),m.attr(k),cy.splice(c--,1);if(d.repeat>1&&!d.next){for(s in k)k[g](s)&&(r[s]=d.totalOrigin[s]);d.el.attr(r),cE(d.anim,d.el,d.anim.percents[0],null,d.totalOrigin,d.repeat-1)}d.next&&!d.stop&&cE(d.anim,d.el,d.next,null,d.totalOrigin,d.repeat)}}a.svg&&m&&m.paper&&m.paper.safari(),cy.length&&cz(cA)},cB=function(a){return a>255?255:a<0?0:a};cl.animateWith=function(b,c,d,e,f,g){var h=this;if(h.removed){g&&g.call(h);return h}var i=d instanceof cD?d:a.animation(d,e,f,g),j,k;cE(i,h,i.percents[0],null,h.attr());for(var l=0,m=cy.length;l<m;l++)if(cy[l].anim==c&&cy[l].el==b){cy[m-1].start=cy[l].start;break}return h},cl.onAnimation=function(a){a?eve.on("raphael.anim.frame."+this.id,a):eve.unbind("raphael.anim.frame."+this.id);return this},cD.prototype.delay=function(a){var b=new cD(this.anim,this.ms);b.times=this.times,b.del=+a||0;return b},cD.prototype.repeat=function(a){var b=new cD(this.anim,this.ms);b.del=this.del,b.times=w.floor(x(a,0))||1;return b},a.animation=function(b,c,d,e){if(b instanceof cD)return b;if(a.is(d,"function")||!d)e=e||d||null,d=null;b=Object(b),c=+c||0;var f={},h,i;for(i in b)b[g](i)&&Q(i)!=i&&Q(i)+"%"!=i&&(h=!0,f[i]=b[i]);if(!h)return new cD(b,c);d&&(f.easing=d),e&&(f.callback=e);return new cD({100:f},c)},cl.animate=function(b,c,d,e){var f=this;if(f.removed){e&&e.call(f);return f}var g=b instanceof cD?b:a.animation(b,c,d,e);cE(g,f,g.percents[0],null,f.attr());return f},cl.setTime=function(a,b){a&&b!=null&&this.status(a,y(b,a.ms)/a.ms);return this},cl.status=function(a,b){var c=[],d=0,e,f;if(b!=null){cE(a,this,-1,y(b,1));return this}e=cy.length;for(;d<e;d++){f=cy[d];if(f.el.id==this.id&&(!a||f.anim==a)){if(a)return f.status;c.push({anim:f.anim,status:f.status})}}if(a)return 0;return c},cl.pause=function(a){for(var b=0;b<cy.length;b++)cy[b].el.id==this.id&&(!a||cy[b].anim==a)&&eve("raphael.anim.pause."+this.id,this,cy[b].anim)!==!1&&(cy[b].paused=!0);return this},cl.resume=function(a){for(var b=0;b<cy.length;b++)if(cy[b].el.id==this.id&&(!a||cy[b].anim==a)){var c=cy[b];eve("raphael.anim.resume."+this.id,this,c.anim)!==!1&&(delete c.paused,this.status(c.anim,c.status))}return this},cl.stop=function(a){for(var b=0;b<cy.length;b++)cy[b].el.id==this.id&&(!a||cy[b].anim==a)&&eve("raphael.anim.stop."+this.id,this,cy[b].anim)!==!1&&cy.splice(b--,1);return this},eve.on("raphael.remove",cF),eve.on("raphael.clear",cF),cl.toString=function(){return"Raphaël’s object"};var cG=function(a){this.items=[],this.length=0,this.type="set";if(a)for(var b=0,c=a.length;b<c;b++)a[b]&&(a[b].constructor==cl.constructor||a[b].constructor==cG)&&(this[this.items.length]=this.items[this.items.length]=a[b],this.length++)},cH=cG.prototype;cH.push=function(){var a,b;for(var c=0,d=arguments.length;c<d;c++)a=arguments[c],a&&(a.constructor==cl.constructor||a.constructor==cG)&&(b=this.items.length,this[b]=this.items[b]=a,this.length++);return this},cH.pop=function(){this.length&&delete this[this.length--];return this.items.pop()},cH.forEach=function(a,b){for(var c=0,d=this.items.length;c<d;c++)if(a.call(b,this.items[c],c)===!1)return this;return this};for(var cI in cl)cl[g](cI)&&(cH[cI]=function(a){return function(){var b=arguments;return this.forEach(function(c){c[a][m](c,b)})}}(cI));cH.attr=function(b,c){if(b&&a.is(b,E)&&a.is(b[0],"object"))for(var d=0,e=b.length;d<e;d++)this.items[d].attr(b[d]);else for(var f=0,g=this.items.length;f<g;f++)this.items[f].attr(b,c);return this},cH.clear=function(){while(this.length)this.pop()},cH.splice=function(a,b,c){a=a<0?x(this.length+a,0):a,b=x(0,y(this.length-a,b));var d=[],e=[],f=[],g;for(g=2;g<arguments.length;g++)f.push(arguments[g]);for(g=0;g<b;g++)e.push(this[a+g]);for(;g<this.length-a;g++)d.push(this[a+g]);var h=f.length;for(g=0;g<h+d.length;g++)this.items[a+g]=this[a+g]=g<h?f[g]:d[g-h];g=this.items.length=this.length-=b-h;while(this[g])delete this[g++];return new cG(e)},cH.exclude=function(a){for(var b=0,c=this.length;b<c;b++)if(this[b]==a){this.splice(b,1);return!0}},cH.animate=function(b,c,d,e){(a.is(d,"function")||!d)&&(e=d||null);var f=this.items.length,g=f,h,i=this,j;if(!f)return this;e&&(j=function(){!--f&&e.call(i)}),d=a.is(d,D)?d:j;var k=a.animation(b,c,d,j);h=this.items[--g].animate(k);while(g--)this.items[g]&&!this.items[g].removed&&this.items[g].animateWith(h,k,k);return this},cH.insertAfter=function(a){var b=this.items.length;while(b--)this.items[b].insertAfter(a);return this},cH.getBBox=function(){var a=[],b=[],c=[],d=[];for(var e=this.items.length;e--;)if(!this.items[e].removed){var f=this.items[e].getBBox();a.push(f.x),b.push(f.y),c.push(f.x+f.width),d.push(f.y+f.height)}a=y[m](0,a),b=y[m](0,b),c=x[m](0,c),d=x[m](0,d);return{x:a,y:b,x2:c,y2:d,width:c-a,height:d-b}},cH.clone=function(a){a=new cG;for(var b=0,c=this.items.length;b<c;b++)a.push(this.items[b].clone());return a},cH.toString=function(){return"Raphaël‘s set"},a.registerFont=function(a){if(!a.face)return a;this.fonts=this.fonts||{};var b={w:a.w,face:{},glyphs:{}},c=a.face["font-family"];for(var d in a.face)a.face[g](d)&&(b.face[d]=a.face[d]);this.fonts[c]?this.fonts[c].push(b):this.fonts[c]=[b];if(!a.svg){b.face["units-per-em"]=R(a.face["units-per-em"],10);for(var e in a.glyphs)if(a.glyphs[g](e)){var f=a.glyphs[e];b.glyphs[e]={w:f.w,k:{},d:f.d&&"M"+f.d.replace(/[mlcxtrv]/g,function(a){return{l:"L",c:"C",x:"z",t:"m",r:"l",v:"c"}[a]||"M"})+"z"};if(f.k)for(var h in f.k)f[g](h)&&(b.glyphs[e].k[h]=f.k[h])}}return a},k.getFont=function(b,c,d,e){e=e||"normal",d=d||"normal",c=+c||{normal:400,bold:700,lighter:300,bolder:800}[c]||400;if(!!a.fonts){var f=a.fonts[b];if(!f){var h=new RegExp("(^|\\s)"+b.replace(/[^\w\d\s+!~.:_-]/g,p)+"(\\s|$)","i");for(var i in a.fonts)if(a.fonts[g](i)&&h.test(i)){f=a.fonts[i];break}}var j;if(f)for(var k=0,l=f.length;k<l;k++){j=f[k];if(j.face["font-weight"]==c&&(j.face["font-style"]==d||!j.face["font-style"])&&j.face["font-stretch"]==e)break}return j}},k.print=function(b,d,e,f,g,h,i){h=h||"middle",i=x(y(i||0,1),-1);var j=r(e)[s](p),k=0,l=0,m=p,n;a.is(f,e)&&(f=this.getFont(f));if(f){n=(g||16)/f.face["units-per-em"];var o=f.face.bbox[s](c),q=+o[0],t=o[3]-o[1],u=0,v=+o[1]+(h=="baseline"?t+ +f.face.descent:t/2);for(var w=0,z=j.length;w<z;w++){if(j[w]=="\n")k=0,B=0,l=0,u+=t;else{var A=l&&f.glyphs[j[w-1]]||{},B=f.glyphs[j[w]];k+=l?(A.w||f.w)+(A.k&&A.k[j[w]]||0)+f.w*i:0,l=1}B&&B.d&&(m+=a.transformPath(B.d,["t",k*n,u*n,"s",n,n,q,v,"t",(b-q)/n,(d-v)/n]))}}return this.path(m).attr({fill:"#000",stroke:"none"})},k.add=function(b){if(a.is(b,"array")){var c=this.set(),e=0,f=b.length,h;for(;e<f;e++)h=b[e]||{},d[g](h.type)&&c.push(this[h.type]().attr(h))}return c},a.format=function(b,c){var d=a.is(c,E)?[0][n](c):arguments;b&&a.is(b,D)&&d.length-1&&(b=b.replace(e,function(a,b){return d[++b]==null?p:d[b]}));return b||p},a.fullfill=function(){var a=/\{([^\}]+)\}/g,b=/(?:(?:^|\.)(.+?)(?=\[|\.|$|\()|\[('|")(.+?)\2\])(\(\))?/g,c=function(a,c,d){var e=d;c.replace(b,function(a,b,c,d,f){b=b||d,e&&(b in e&&(e=e[b]),typeof e=="function"&&f&&(e=e()))}),e=(e==null||e==d?a:e)+"";return e};return function(b,d){return String(b).replace(a,function(a,b){return c(a,b,d)})}}(),a.ninja=function(){i.was?h.win.Raphael=i.is:delete Raphael;return a},a.st=cH,function(b,c,d){function e(){/in/.test(b.readyState)?setTimeout(e,9):a.eve("raphael.DOMload")}b.readyState==null&&b.addEventListener&&(b.addEventListener(c,d=function(){b.removeEventListener(c,d,!1),b.readyState="complete"},!1),b.readyState="loading"),e()}(document,"DOMContentLoaded"),i.was?h.win.Raphael=a:Raphael=a,eve.on("raphael.DOMload",function(){b=!0})}(),window.Raphael.svg&&function(a){var b="hasOwnProperty",c=String,d=parseFloat,e=parseInt,f=Math,g=f.max,h=f.abs,i=f.pow,j=/[, ]+/,k=a.eve,l="",m=" ",n="http://www.w3.org/1999/xlink",o={block:"M5,0 0,2.5 5,5z",classic:"M5,0 0,2.5 5,5 3.5,3 3.5,2z",diamond:"M2.5,0 5,2.5 2.5,5 0,2.5z",open:"M6,1 1,3.5 6,6",oval:"M2.5,0A2.5,2.5,0,0,1,2.5,5 2.5,2.5,0,0,1,2.5,0z"},p={};a.toString=function(){return"Your browser supports SVG.\nYou are running Raphaël "+this.version};var q=function(d,e){if(e){typeof d=="string"&&(d=q(d));for(var f in e)e[b](f)&&(f.substring(0,6)=="xlink:"?d.setAttributeNS(n,f.substring(6),c(e[f])):d.setAttribute(f,c(e[f])))}else d=a._g.doc.createElementNS("http://www.w3.org/2000/svg",d),d.style&&(d.style.webkitTapHighlightColor="rgba(0,0,0,0)");return d},r=function(b,e){var j="linear",k=b.id+e,m=.5,n=.5,o=b.node,p=b.paper,r=o.style,s=a._g.doc.getElementById(k);if(!s){e=c(e).replace(a._radial_gradient,function(a,b,c){j="radial";if(b&&c){m=d(b),n=d(c);var e=(n>.5)*2-1;i(m-.5,2)+i(n-.5,2)>.25&&(n=f.sqrt(.25-i(m-.5,2))*e+.5)&&n!=.5&&(n=n.toFixed(5)-1e-5*e)}return l}),e=e.split(/\s*\-\s*/);if(j=="linear"){var t=e.shift();t=-d(t);if(isNaN(t))return null;var u=[0,0,f.cos(a.rad(t)),f.sin(a.rad(t))],v=1/(g(h(u[2]),h(u[3]))||1);u[2]*=v,u[3]*=v,u[2]<0&&(u[0]=-u[2],u[2]=0),u[3]<0&&(u[1]=-u[3],u[3]=0)}var w=a._parseDots(e);if(!w)return null;k=k.replace(/[\(\)\s,\xb0#]/g,"_"),b.gradient&&k!=b.gradient.id&&(p.defs.removeChild(b.gradient),delete b.gradient);if(!b.gradient){s=q(j+"Gradient",{id:k}),b.gradient=s,q(s,j=="radial"?{fx:m,fy:n}:{x1:u[0],y1:u[1],x2:u[2],y2:u[3],gradientTransform:b.matrix.invert()}),p.defs.appendChild(s);for(var x=0,y=w.length;x<y;x++)s.appendChild(q("stop",{offset:w[x].offset?w[x].offset:x?"100%":"0%","stop-color":w[x].color||"#fff"}))}}q(o,{fill:"url(#"+k+")",opacity:1,"fill-opacity":1}),r.fill=l,r.opacity=1,r.fillOpacity=1;return 1},s=function(a){var b=a.getBBox(1);q(a.pattern,{patternTransform:a.matrix.invert()+" translate("+b.x+","+b.y+")"})},t=function(d,e,f){if(d.type=="path"){var g=c(e).toLowerCase().split("-"),h=d.paper,i=f?"end":"start",j=d.node,k=d.attrs,m=k["stroke-width"],n=g.length,r="classic",s,t,u,v,w,x=3,y=3,z=5;while(n--)switch(g[n]){case"block":case"classic":case"oval":case"diamond":case"open":case"none":r=g[n];break;case"wide":y=5;break;case"narrow":y=2;break;case"long":x=5;break;case"short":x=2}r=="open"?(x+=2,y+=2,z+=2,u=1,v=f?4:1,w={fill:"none",stroke:k.stroke}):(v=u=x/2,w={fill:k.stroke,stroke:"none"}),d._.arrows?f?(d._.arrows.endPath&&p[d._.arrows.endPath]--,d._.arrows.endMarker&&p[d._.arrows.endMarker]--):(d._.arrows.startPath&&p[d._.arrows.startPath]--,d._.arrows.startMarker&&p[d._.arrows.startMarker]--):d._.arrows={};if(r!="none"){var A="raphael-marker-"+r,B="raphael-marker-"+i+r+x+y;a._g.doc.getElementById(A)?p[A]++:(h.defs.appendChild(q(q("path"),{"stroke-linecap":"round",d:o[r],id:A})),p[A]=1);var C=a._g.doc.getElementById(B),D;C?(p[B]++,D=C.getElementsByTagName("use")[0]):(C=q(q("marker"),{id:B,markerHeight:y,markerWidth:x,orient:"auto",refX:v,refY:y/2}),D=q(q("use"),{"xlink:href":"#"+A,transform:(f?"rotate(180 "+x/2+" "+y/2+") ":l)+"scale("+x/z+","+y/z+")","stroke-width":(1/((x/z+y/z)/2)).toFixed(4)}),C.appendChild(D),h.defs.appendChild(C),p[B]=1),q(D,w);var F=u*(r!="diamond"&&r!="oval");f?(s=d._.arrows.startdx*m||0,t=a.getTotalLength(k.path)-F*m):(s=F*m,t=a.getTotalLength(k.path)-(d._.arrows.enddx*m||0)),w={},w["marker-"+i]="url(#"+B+")";if(t||s)w.d=Raphael.getSubpath(k.path,s,t);q(j,w),d._.arrows[i+"Path"]=A,d._.arrows[i+"Marker"]=B,d._.arrows[i+"dx"]=F,d._.arrows[i+"Type"]=r,d._.arrows[i+"String"]=e}else f?(s=d._.arrows.startdx*m||0,t=a.getTotalLength(k.path)-s):(s=0,t=a.getTotalLength(k.path)-(d._.arrows.enddx*m||0)),d._.arrows[i+"Path"]&&q(j,{d:Raphael.getSubpath(k.path,s,t)}),delete d._.arrows[i+"Path"],delete d._.arrows[i+"Marker"],delete d._.arrows[i+"dx"],delete d._.arrows[i+"Type"],delete d._.arrows[i+"String"];for(w in p)if(p[b](w)&&!p[w]){var G=a._g.doc.getElementById(w);G&&G.parentNode.removeChild(G)}}},u={"":[0],none:[0],"-":[3,1],".":[1,1],"-.":[3,1,1,1],"-..":[3,1,1,1,1,1],". ":[1,3],"- ":[4,3],"--":[8,3],"- .":[4,3,1,3],"--.":[8,3,1,3],"--..":[8,3,1,3,1,3]},v=function(a,b,d){b=u[c(b).toLowerCase()];if(b){var e=a.attrs["stroke-width"]||"1",f={round:e,square:e,butt:0}[a.attrs["stroke-linecap"]||d["stroke-linecap"]]||0,g=[],h=b.length;while(h--)g[h]=b[h]*e+(h%2?1:-1)*f;q(a.node,{"stroke-dasharray":g.join(",")})}},w=function(d,f){var i=d.node,k=d.attrs,m=i.style.visibility;i.style.visibility="hidden";for(var o in f)if(f[b](o)){if(!a._availableAttrs[b](o))continue;var p=f[o];k[o]=p;switch(o){case"blur":d.blur(p);break;case"href":case"title":case"target":var u=i.parentNode;if(u.tagName.toLowerCase()!="a"){var w=q("a");u.insertBefore(w,i),w.appendChild(i),u=w}o=="target"?u.setAttributeNS(n,"show",p=="blank"?"new":p):u.setAttributeNS(n,o,p);break;case"cursor":i.style.cursor=p;break;case"transform":d.transform(p);break;case"arrow-start":t(d,p);break;case"arrow-end":t(d,p,1);break;case"clip-rect":var x=c(p).split(j);if(x.length==4){d.clip&&d.clip.parentNode.parentNode.removeChild(d.clip.parentNode);var z=q("clipPath"),A=q("rect");z.id=a.createUUID(),q(A,{x:x[0],y:x[1],width:x[2],height:x[3]}),z.appendChild(A),d.paper.defs.appendChild(z),q(i,{"clip-path":"url(#"+z.id+")"}),d.clip=A}if(!p){var B=i.getAttribute("clip-path");if(B){var C=a._g.doc.getElementById(B.replace(/(^url\(#|\)$)/g,l));C&&C.parentNode.removeChild(C),q(i,{"clip-path":l}),delete d.clip}}break;case"path":d.type=="path"&&(q(i,{d:p?k.path=a._pathToAbsolute(p):"M0,0"}),d._.dirty=1,d._.arrows&&("startString"in d._.arrows&&t(d,d._.arrows.startString),"endString"in d._.arrows&&t(d,d._.arrows.endString,1)));break;case"width":i.setAttribute(o,p),d._.dirty=1;if(k.fx)o="x",p=k.x;else break;case"x":k.fx&&(p=-k.x-(k.width||0));case"rx":if(o=="rx"&&d.type=="rect")break;case"cx":i.setAttribute(o,p),d.pattern&&s(d),d._.dirty=1;break;case"height":i.setAttribute(o,p),d._.dirty=1;if(k.fy)o="y",p=k.y;else break;case"y":k.fy&&(p=-k.y-(k.height||0));case"ry":if(o=="ry"&&d.type=="rect")break;case"cy":i.setAttribute(o,p),d.pattern&&s(d),d._.dirty=1;break;case"r":d.type=="rect"?q(i,{rx:p,ry:p}):i.setAttribute(o,p),d._.dirty=1;break;case"src":d.type=="image"&&i.setAttributeNS(n,"href",p);break;case"stroke-width":if(d._.sx!=1||d._.sy!=1)p/=g(h(d._.sx),h(d._.sy))||1;d.paper._vbSize&&(p*=d.paper._vbSize),i.setAttribute(o,p),k["stroke-dasharray"]&&v(d,k["stroke-dasharray"],f),d._.arrows&&("startString"in d._.arrows&&t(d,d._.arrows.startString),"endString"in d._.arrows&&t(d,d._.arrows.endString,1));break;case"stroke-dasharray":v(d,p,f);break;case"fill":var D=c(p).match(a._ISURL);if(D){z=q("pattern");var F=q("image");z.id=a.createUUID(),q(z,{x:0,y:0,patternUnits:"userSpaceOnUse",height:1,width:1}),q(F,{x:0,y:0,"xlink:href":D[1]}),z.appendChild(F),function(b){a._preload(D[1],function(){var a=this.offsetWidth,c=this.offsetHeight;q(b,{width:a,height:c}),q(F,{width:a,height:c}),d.paper.safari()})}(z),d.paper.defs.appendChild(z),q(i,{fill:"url(#"+z.id+")"}),d.pattern=z,d.pattern&&s(d);break}var G=a.getRGB(p);if(!G.error)delete f.gradient,delete k.gradient,!a.is(k.opacity,"undefined")&&a.is(f.opacity,"undefined")&&q(i,{opacity:k.opacity}),!a.is(k["fill-opacity"],"undefined")&&a.is(f["fill-opacity"],"undefined")&&q(i,{"fill-opacity":k["fill-opacity"]});else if((d.type=="circle"||d.type=="ellipse"||c(p).charAt()!="r")&&r(d,p)){if("opacity"in k||"fill-opacity"in k){var H=a._g.doc.getElementById(i.getAttribute("fill").replace(/^url\(#|\)$/g,l));if(H){var I=H.getElementsByTagName("stop");q(I[I.length-1],{"stop-opacity":("opacity"in k?k.opacity:1)*("fill-opacity"in k?k["fill-opacity"]:1)})}}k.gradient=p,k.fill="none";break}G[b]("opacity")&&q(i,{"fill-opacity":G.opacity>1?G.opacity/100:G.opacity});case"stroke":G=a.getRGB(p),i.setAttribute(o,G.hex),o=="stroke"&&G[b]("opacity")&&q(i,{"stroke-opacity":G.opacity>1?G.opacity/100:G.opacity}),o=="stroke"&&d._.arrows&&("startString"in d._.arrows&&t(d,d._.arrows.startString),"endString"in d._.arrows&&t(d,d._.arrows.endString,1));break;case"gradient":(d.type=="circle"||d.type=="ellipse"||c(p).charAt()!="r")&&r(d,p);break;case"opacity":k.gradient&&!k[b]("stroke-opacity")&&q(i,{"stroke-opacity":p>1?p/100:p});case"fill-opacity":if(k.gradient){H=a._g.doc.getElementById(i.getAttribute("fill").replace(/^url\(#|\)$/g,l)),H&&(I=H.getElementsByTagName("stop"),q(I[I.length-1],{"stop-opacity":p}));break};default:o=="font-size"&&(p=e(p,10)+"px");var J=o.replace(/(\-.)/g,function(a){return a.substring(1).toUpperCase()});i.style[J]=p,d._.dirty=1,i.setAttribute(o,p)}}y(d,f),i.style.visibility=m},x=1.2,y=function(d,f){if(d.type=="text"&&!!(f[b]("text")||f[b]("font")||f[b]("font-size")||f[b]("x")||f[b]("y"))){var g=d.attrs,h=d.node,i=h.firstChild?e(a._g.doc.defaultView.getComputedStyle(h.firstChild,l).getPropertyValue("font-size"),10):10;if(f[b]("text")){g.text=f.text;while(h.firstChild)h.removeChild(h.firstChild);var j=c(f.text).split("\n"),k=[],m;for(var n=0,o=j.length;n<o;n++)m=q("tspan"),n&&q(m,{dy:i*x,x:g.x}),m.appendChild(a._g.doc.createTextNode(j[n])),h.appendChild(m),k[n]=m}else{k=h.getElementsByTagName("tspan");for(n=0,o=k.length;n<o;n++)n?q(k[n],{dy:i*x,x:g.x}):q(k[0],{dy:0})}q(h,{x:g.x,y:g.y}),d._.dirty=1;var p=d._getBBox(),r=g.y-(p.y+p.height/2);r&&a.is(r,"finite")&&q(k[0],{dy:r})}},z=function(b,c){var d=0,e=0;this[0]=this.node=b,b.raphael=!0,this.id=a._oid++,b.raphaelid=this.id,this.matrix=a.matrix(),this.realPath=null,this.paper=c,this.attrs=this.attrs||{},this._={transform:[],sx:1,sy:1,deg:0,dx:0,dy:0,dirty:1},!c.bottom&&(c.bottom=this),this.prev=c.top,c.top&&(c.top.next=this),c.top=this,this.next=null},A=a.el;z.prototype=A,A.constructor=z,a._engine.path=function(a,b){var c=q("path");b.canvas&&b.canvas.appendChild(c);var d=new z(c,b);d.type="path",w(d,{fill:"none",stroke:"#000",path:a});return d},A.rotate=function(a,b,e){if(this.removed)return this;a=c(a).split(j),a.length-1&&(b=d(a[1]),e=d(a[2])),a=d(a[0]),e==null&&(b=e);if(b==null||e==null){var f=this.getBBox(1);b=f.x+f.width/2,e=f.y+f.height/2}this.transform(this._.transform.concat([["r",a,b,e]]));return this},A.scale=function(a,b,e,f){if(this.removed)return this;a=c(a).split(j),a.length-1&&(b=d(a[1]),e=d(a[2]),f=d(a[3])),a=d(a[0]),b==null&&(b=a),f==null&&(e=f);if(e==null||f==null)var g=this.getBBox(1);e=e==null?g.x+g.width/2:e,f=f==null?g.y+g.height/2:f,this.transform(this._.transform.concat([["s",a,b,e,f]]));return this},A.translate=function(a,b){if(this.removed)return this;a=c(a).split(j),a.length-1&&(b=d(a[1])),a=d(a[0])||0,b=+b||0,this.transform(this._.transform.concat([["t",a,b]]));return this},A.transform=function(c){var d=this._;if(c==null)return d.transform;a._extractTransform(this,c),this.clip&&q(this.clip,{transform:this.matrix.invert()}),this.pattern&&s(this),this.node&&q(this.node,{transform:this.matrix});if(d.sx!=1||d.sy!=1){var e=this.attrs[b]("stroke-width")?this.attrs["stroke-width"]:1;this.attr({"stroke-width":e})}return this},A.hide=function(){!this.removed&&this.paper.safari(this.node.style.display="none");return this},A.show=function(){!this.removed&&this.paper.safari(this.node.style.display="");return this},A.remove=function(){if(!this.removed&&!!this.node.parentNode){var b=this.paper;b.__set__&&b.__set__.exclude(this),k.unbind("raphael.*.*."+this.id),this.gradient&&b.defs.removeChild(this.gradient),a._tear(this,b),this.node.parentNode.tagName.toLowerCase()=="a"?this.node.parentNode.parentNode.removeChild(this.node.parentNode):this.node.parentNode.removeChild(this.node);for(var c in this)this[c]=typeof this[c]=="function"?a._removedFactory(c):null;this.removed=!0}},A._getBBox=function(){if(this.node.style.display=="none"){this.show();var a=!0}var b={};try{b=this.node.getBBox()}catch(c){}finally{b=b||{}}a&&this.hide();return b},A.attr=function(c,d){if(this.removed)return this;if(c==null){var e={};for(var f in this.attrs)this.attrs[b](f)&&(e[f]=this.attrs[f]);e.gradient&&e.fill=="none"&&(e.fill=e.gradient)&&delete e.gradient,e.transform=this._.transform;return e}if(d==null&&a.is(c,"string")){if(c=="fill"&&this.attrs.fill=="none"&&this.attrs.gradient)return this.attrs.gradient;if(c=="transform")return this._.transform;var g=c.split(j),h={};for(var i=0,l=g.length;i<l;i++)c=g[i],c in this.attrs?h[c]=this.attrs[c]:a.is(this.paper.customAttributes[c],"function")?h[c]=this.paper.customAttributes[c].def:h[c]=a._availableAttrs[c];return l-1?h:h[g[0]]}if(d==null&&a.is(c,"array")){h={};for(i=0,l=c.length;i<l;i++)h[c[i]]=this.attr(c[i]);return h}if(d!=null){var m={};m[c]=d}else c!=null&&a.is(c,"object")&&(m=c);for(var n in m)k("raphael.attr."+n+"."+this.id,this,m[n]);for(n in this.paper.customAttributes)if(this.paper.customAttributes[b](n)&&m[b](n)&&a.is(this.paper.customAttributes[n],"function")){var o=this.paper.customAttributes[n].apply(this,[].concat(m[n]));this.attrs[n]=m[n];for(var p in o)o[b](p)&&(m[p]=o[p])}w(this,m);return this},A.toFront=function(){if(this.removed)return this;this.node.parentNode.tagName.toLowerCase()=="a"?this.node.parentNode.parentNode.appendChild(this.node.parentNode):this.node.parentNode.appendChild(this.node);var b=this.paper;b.top!=this&&a._tofront(this,b);return this},A.toBack=function(){if(this.removed)return this;var b=this.node.parentNode;b.tagName.toLowerCase()=="a"?b.parentNode.insertBefore(this.node.parentNode,this.node.parentNode.parentNode.firstChild):b.firstChild!=this.node&&b.insertBefore(this.node,this.node.parentNode.firstChild),a._toback(this,this.paper);var c=this.paper;return this},A.insertAfter=function(b){if(this.removed)return this;var c=b.node||b[b.length-1].node;c.nextSibling?c.parentNode.insertBefore(this.node,c.nextSibling):c.parentNode.appendChild(this.node),a._insertafter(this,b,this.paper);return this},A.insertBefore=function(b){if(this.removed)return this;var c=b.node||b[0].node;c.parentNode.insertBefore(this.node,c),a._insertbefore(this,b,this.paper);return this},A.blur=function(b){var c=this;if(+b!==0){var d=q("filter"),e=q("feGaussianBlur");c.attrs.blur=b,d.id=a.createUUID(),q(e,{stdDeviation:+b||1.5}),d.appendChild(e),c.paper.defs.appendChild(d),c._blur=d,q(c.node,{filter:"url(#"+d.id+")"})}else c._blur&&(c._blur.parentNode.removeChild(c._blur),delete c._blur,delete c.attrs.blur),c.node.removeAttribute("filter")},a._engine.circle=function(a,b,c,d){var e=q("circle");a.canvas&&a.canvas.appendChild(e);var f=new z(e,a);f.attrs={cx:b,cy:c,r:d,fill:"none",stroke:"#000"},f.type="circle",q(e,f.attrs);return f},a._engine.rect=function(a,b,c,d,e,f){var g=q("rect");a.canvas&&a.canvas.appendChild(g);var h=new z(g,a);h.attrs={x:b,y:c,width:d,height:e,r:f||0,rx:f||0,ry:f||0,fill:"none",stroke:"#000"},h.type="rect",q(g,h.attrs);return h},a._engine.ellipse=function(a,b,c,d,e){var f=q("ellipse");a.canvas&&a.canvas.appendChild(f);var g=new z(f,a);g.attrs={cx:b,cy:c,rx:d,ry:e,fill:"none",stroke:"#000"},g.type="ellipse",q(f,g.attrs);return g},a._engine.image=function(a,b,c,d,e,f){var g=q("image");q(g,{x:c,y:d,width:e,height:f,preserveAspectRatio:"none"}),g.setAttributeNS(n,"href",b),a.canvas&&a.canvas.appendChild(g);var h=new z(g,a);h.attrs={x:c,y:d,width:e,height:f,src:b},h.type="image";return h},a._engine.text=function(b,c,d,e){var f=q("text");b.canvas&&b.canvas.appendChild(f);var g=new z(f,b);g.attrs={x:c,y:d,"text-anchor":"middle",text:e,font:a._availableAttrs.font,stroke:"none",fill:"#000"},g.type="text",w(g,g.attrs);return g},a._engine.setSize=function(a,b){this.width=a||this.width,this.height=b||this.height,this.canvas.setAttribute("width",this.width),this.canvas.setAttribute("height",this.height),this._viewBox&&this.setViewBox.apply(this,this._viewBox);return this},a._engine.create=function(){var b=a._getContainer.apply(0,arguments),c=b&&b.container,d=b.x,e=b.y,f=b.width,g=b.height;if(!c)throw new Error("SVG container not found.");var h=q("svg"),i="overflow:hidden;",j;d=d||0,e=e||0,f=f||512,g=g||342,q(h,{height:g,version:1.1,width:f,xmlns:"http://www.w3.org/2000/svg"}),c==1?(h.style.cssText=i+"position:absolute;left:"+d+"px;top:"+e+"px",a._g.doc.body.appendChild(h),j=1):(h.style.cssText=i+"position:relative",c.firstChild?c.insertBefore(h,c.firstChild):c.appendChild(h)),c=new a._Paper,c.width=f,c.height=g,c.canvas=h,c.clear(),c._left=c._top=0,j&&(c.renderfix=function(){}),c.renderfix();return c},a._engine.setViewBox=function(a,b,c,d,e){k("raphael.setViewBox",this,this._viewBox,[a,b,c,d,e]);var f=g(c/this.width,d/this.height),h=this.top,i=e?"meet":"xMinYMin",j,l;a==null?(this._vbSize&&(f=1),delete this._vbSize,j="0 0 "+this.width+m+this.height):(this._vbSize=f,j=a+m+b+m+c+m+d),q(this.canvas,{viewBox:j,preserveAspectRatio:i});while(f&&h)l="stroke-width"in h.attrs?h.attrs["stroke-width"]:1,h.attr({"stroke-width":l}),h._.dirty=1,h._.dirtyT=1,h=h.prev;this._viewBox=[a,b,c,d,!!e];return this},a.prototype.renderfix=function(){var a=this.canvas,b=a.style,c;try{c=a.getScreenCTM()||a.createSVGMatrix()}catch(d){c=a.createSVGMatrix()}var e=-c.e%1,f=-c.f%1;if(e||f)e&&(this._left=(this._left+e)%1,b.left=this._left+"px"),f&&(this._top=(this._top+f)%1,b.top=this._top+"px")},a.prototype.clear=function(){a.eve("raphael.clear",this);var b=this.canvas;while(b.firstChild)b.removeChild(b.firstChild);this.bottom=this.top=null,(this.desc=q("desc")).appendChild(a._g.doc.createTextNode("Created with Raphaël "+a.version)),b.appendChild(this.desc),b.appendChild(this.defs=q("defs"))},a.prototype.remove=function(){k("raphael.remove",this),this.canvas.parentNode&&this.canvas.parentNode.removeChild(this.canvas);for(var b in this)this[b]=typeof this[b]=="function"?a._removedFactory(b):null};var B=a.st;for(var C in A)A[b](C)&&!B[b](C)&&(B[C]=function(a){return function(){var b=arguments;return this.forEach(function(c){c[a].apply(c,b)})}}(C))}(window.Raphael),window.Raphael.vml&&function(a){var b="hasOwnProperty",c=String,d=parseFloat,e=Math,f=e.round,g=e.max,h=e.min,i=e.abs,j="fill",k=/[, ]+/,l=a.eve,m=" progid:DXImageTransform.Microsoft",n=" ",o="",p={M:"m",L:"l",C:"c",Z:"x",m:"t",l:"r",c:"v",z:"x"},q=/([clmz]),?([^clmz]*)/gi,r=/ progid:\S+Blur\([^\)]+\)/g,s=/-?[^,\s-]+/g,t="position:absolute;left:0;top:0;width:1px;height:1px",u=21600,v={path:1,rect:1,image:1},w={circle:1,ellipse:1},x=function(b){var d=/[ahqstv]/ig,e=a._pathToAbsolute;c(b).match(d)&&(e=a._path2curve),d=/[clmz]/g;if(e==a._pathToAbsolute&&!c(b).match(d)){var g=c(b).replace(q,function(a,b,c){var d=[],e=b.toLowerCase()=="m",g=p[b];c.replace(s,function(a){e&&d.length==2&&(g+=d+p[b=="m"?"l":"L"],d=[]),d.push(f(a*u))});return g+d});return g}var h=e(b),i,j;g=[];for(var k=0,l=h.length;k<l;k++){i=h[k],j=h[k][0].toLowerCase(),j=="z"&&(j="x");for(var m=1,r=i.length;m<r;m++)j+=f(i[m]*u)+(m!=r-1?",":o);g.push(j)}return g.join(n)},y=function(b,c,d){var e=a.matrix();e.rotate(-b,.5,.5);return{dx:e.x(c,d),dy:e.y(c,d)}},z=function(a,b,c,d,e,f){var g=a._,h=a.matrix,k=g.fillpos,l=a.node,m=l.style,o=1,p="",q,r=u/b,s=u/c;m.visibility="hidden";if(!!b&&!!c){l.coordsize=i(r)+n+i(s),m.rotation=f*(b*c<0?-1:1);if(f){var t=y(f,d,e);d=t.dx,e=t.dy}b<0&&(p+="x"),c<0&&(p+=" y")&&(o=-1),m.flip=p,l.coordorigin=d*-r+n+e*-s;if(k||g.fillsize){var v=l.getElementsByTagName(j);v=v&&v[0],l.removeChild(v),k&&(t=y(f,h.x(k[0],k[1]),h.y(k[0],k[1])),v.position=t.dx*o+n+t.dy*o),g.fillsize&&(v.size=g.fillsize[0]*i(b)+n+g.fillsize[1]*i(c)),l.appendChild(v)}m.visibility="visible"}};a.toString=function(){return"Your browser doesn’t support SVG. Falling down to VML.\nYou are running Raphaël "+this.version};var A=function(a,b,d){var e=c(b).toLowerCase().split("-"),f=d?"end":"start",g=e.length,h="classic",i="medium",j="medium";while(g--)switch(e[g]){case"block":case"classic":case"oval":case"diamond":case"open":case"none":h=e[g];break;case"wide":case"narrow":j=e[g];break;case"long":case"short":i=e[g]}var k=a.node.getElementsByTagName("stroke")[0];k[f+"arrow"]=h,k[f+"arrowlength"]=i,k[f+"arrowwidth"]=j},B=function(e,i){e.attrs=e.attrs||{};var l=e.node,m=e.attrs,p=l.style,q,r=v[e.type]&&(i.x!=m.x||i.y!=m.y||i.width!=m.width||i.height!=m.height||i.cx!=m.cx||i.cy!=m.cy||i.rx!=m.rx||i.ry!=m.ry||i.r!=m.r),s=w[e.type]&&(m.cx!=i.cx||m.cy!=i.cy||m.r!=i.r||m.rx!=i.rx||m.ry!=i.ry),t=e;for(var y in i)i[b](y)&&(m[y]=i[y]);r&&(m.path=a._getPath[e.type](e),e._.dirty=1),i.href&&(l.href=i.href),i.title&&(l.title=i.title),i.target&&(l.target=i.target),i.cursor&&(p.cursor=i.cursor),"blur"in i&&e.blur(i.blur);if(i.path&&e.type=="path"||r)l.path=x(~c(m.path).toLowerCase().indexOf("r")?a._pathToAbsolute(m.path):m.path),e.type=="image"&&(e._.fillpos=[m.x,m.y],e._.fillsize=[m.width,m.height],z(e,1,1,0,0,0));"transform"in i&&e.transform(i.transform);if(s){var B=+m.cx,D=+m.cy,E=+m.rx||+m.r||0,G=+m.ry||+m.r||0;l.path=a.format("ar{0},{1},{2},{3},{4},{1},{4},{1}x",f((B-E)*u),f((D-G)*u),f((B+E)*u),f((D+G)*u),f(B*u))}if("clip-rect"in i){var H=c(i["clip-rect"]).split(k);if(H.length==4){H[2]=+H[2]+ +H[0],H[3]=+H[3]+ +H[1];var I=l.clipRect||a._g.doc.createElement("div"),J=I.style;J.clip=a.format("rect({1}px {2}px {3}px {0}px)",H),l.clipRect||(J.position="absolute",J.top=0,J.left=0,J.width=e.paper.width+"px",J.height=e.paper.height+"px",l.parentNode.insertBefore(I,l),I.appendChild(l),l.clipRect=I)}i["clip-rect"]||l.clipRect&&(l.clipRect.style.clip="auto")}if(e.textpath){var K=e.textpath.style;i.font&&(K.font=i.font),i["font-family"]&&(K.fontFamily='"'+i["font-family"].split(",")[0].replace(/^['"]+|['"]+$/g,o)+'"'),i["font-size"]&&(K.fontSize=i["font-size"]),i["font-weight"]&&(K.fontWeight=i["font-weight"]),i["font-style"]&&(K.fontStyle=i["font-style"])}"arrow-start"in i&&A(t,i["arrow-start"]),"arrow-end"in i&&A(t,i["arrow-end"],1);if(i.opacity!=null||i["stroke-width"]!=null||i.fill!=null||i.src!=null||i.stroke!=null||i["stroke-width"]!=null||i["stroke-opacity"]!=null||i["fill-opacity"]!=null||i["stroke-dasharray"]!=null||i["stroke-miterlimit"]!=null||i["stroke-linejoin"]!=null||i["stroke-linecap"]!=null){var L=l.getElementsByTagName(j),M=!1;L=L&&L[0],!L&&(M=L=F(j)),e.type=="image"&&i.src&&(L.src=i.src),i.fill&&(L.on=!0);if(L.on==null||i.fill=="none"||i.fill===null)L.on=!1;if(L.on&&i.fill){var N=c(i.fill).match(a._ISURL);if(N){L.parentNode==l&&l.removeChild(L),L.rotate=!0,L.src=N[1],L.type="tile";var O=e.getBBox(1);L.position=O.x+n+O.y,e._.fillpos=[O.x,O.y],a._preload(N[1],function(){e._.fillsize=[this.offsetWidth,this.offsetHeight]})}else L.color=a.getRGB(i.fill).hex,L.src=o,L.type="solid",a.getRGB(i.fill).error&&(t.type in{circle:1,ellipse:1}||c(i.fill).charAt()!="r")&&C(t,i.fill,L)&&(m.fill="none",m.gradient=i.fill,L.rotate=!1)}if("fill-opacity"in i||"opacity"in i){var P=((+m["fill-opacity"]+1||2)-1)*((+m.opacity+1||2)-1)*((+a.getRGB(i.fill).o+1||2)-1);P=h(g(P,0),1),L.opacity=P,L.src&&(L.color="none")}l.appendChild(L);var Q=l.getElementsByTagName("stroke")&&l.getElementsByTagName("stroke")[0],T=!1;!Q&&(T=Q=F("stroke"));if(i.stroke&&i.stroke!="none"||i["stroke-width"]||i["stroke-opacity"]!=null||i["stroke-dasharray"]||i["stroke-miterlimit"]||i["stroke-linejoin"]||i["stroke-linecap"])Q.on=!0;(i.stroke=="none"||i.stroke===null||Q.on==null||i.stroke==0||i["stroke-width"]==0)&&(Q.on=!1);var U=a.getRGB(i.stroke);Q.on&&i.stroke&&(Q.color=U.hex),P=((+m["stroke-opacity"]+1||2)-1)*((+m.opacity+1||2)-1)*((+U.o+1||2)-1);var V=(d(i["stroke-width"])||1)*.75;P=h(g(P,0),1),i["stroke-width"]==null&&(V=m["stroke-width"]),i["stroke-width"]&&(Q.weight=V),V&&V<1&&(P*=V)&&(Q.weight=1),Q.opacity=P,i["stroke-linejoin"]&&(Q.joinstyle=i["stroke-linejoin"]||"miter"),Q.miterlimit=i["stroke-miterlimit"]||8,i["stroke-linecap"]&&(Q.endcap=i["stroke-linecap"]=="butt"?"flat":i["stroke-linecap"]=="square"?"square":"round");if(i["stroke-dasharray"]){var W={"-":"shortdash",".":"shortdot","-.":"shortdashdot","-..":"shortdashdotdot",". ":"dot","- ":"dash","--":"longdash","- .":"dashdot","--.":"longdashdot","--..":"longdashdotdot"};Q.dashstyle=W[b](i["stroke-dasharray"])?W[i["stroke-dasharray"]]:o}T&&l.appendChild(Q)}if(t.type=="text"){t.paper.canvas.style.display=o;var X=t.paper.span,Y=100,Z=m.font&&m.font.match(/\d+(?:\.\d*)?(?=px)/);p=X.style,m.font&&(p.font=m.font),m["font-family"]&&(p.fontFamily=m["font-family"]),m["font-weight"]&&(p.fontWeight=m["font-weight"]),m["font-style"]&&(p.fontStyle=m["font-style"]),Z=d(m["font-size"]||Z&&Z[0])||10,p.fontSize=Z*Y+"px",t.textpath.string&&(X.innerHTML=c(t.textpath.string).replace(/</g,"<").replace(/&/g,"&").replace(/\n/g,"<br>"));var $=X.getBoundingClientRect();t.W=m.w=($.right-$.left)/Y,t.H=m.h=($.bottom-$.top)/Y,t.X=m.x,t.Y=m.y+t.H/2,("x"in i||"y"in i)&&(t.path.v=a.format("m{0},{1}l{2},{1}",f(m.x*u),f(m.y*u),f(m.x*u)+1));var _=["x","y","text","font","font-family","font-weight","font-style","font-size"];for(var ba=0,bb=_.length;ba<bb;ba++)if(_[ba]in i){t._.dirty=1;break}switch(m["text-anchor"]){case"start":t.textpath.style["v-text-align"]="left",t.bbx=t.W/2;break;case"end":t.textpath.style["v-text-align"]="right",t.bbx=-t.W/2;break;default:t.textpath.style["v-text-align"]="center",t.bbx=0}t.textpath.style["v-text-kern"]=!0}},C=function(b,f,g){b.attrs=b.attrs||{};var h=b.attrs,i=Math.pow,j,k,l="linear",m=".5 .5";b.attrs.gradient=f,f=c(f).replace(a._radial_gradient,function(a,b,c){l="radial",b&&c&&(b=d(b),c=d(c),i(b-.5,2)+i(c-.5,2)>.25&&(c=e.sqrt(.25-i(b-.5,2))*((c>.5)*2-1)+.5),m=b+n+c);return o}),f=f.split(/\s*\-\s*/);if(l=="linear"){var p=f.shift();p=-d(p);if(isNaN(p))return null}var q=a._parseDots(f);if(!q)return null;b=b.shape||b.node;if(q.length){b.removeChild(g),g.on=!0,g.method="none",g.color=q[0].color,g.color2=q[q.length-1].color;var r=[];for(var s=0,t=q.length;s<t;s++)q[s].offset&&r.push(q[s].offset+n+q[s].color);g.colors=r.length?r.join():"0% "+g.color,l=="radial"?(g.type="gradientTitle",g.focus="100%",g.focussize="0 0",g.focusposition=m,g.angle=0):(g.type="gradient",g.angle=(270-p)%360),b.appendChild(g)}return 1},D=function(b,c){this[0]=this.node=b,b.raphael=!0,this.id=a._oid++,b.raphaelid=this.id,this.X=0,this.Y=0,this.attrs={},this.paper=c,this.matrix=a.matrix(),this._={transform:[],sx:1,sy:1,dx:0,dy:0,deg:0,dirty:1,dirtyT:1},!c.bottom&&(c.bottom=this),this.prev=c.top,c.top&&(c.top.next=this),c.top=this,this.next=null},E=a.el;D.prototype=E,E.constructor=D,E.transform=function(b){if(b==null)return this._.transform;var d=this.paper._viewBoxShift,e=d?"s"+[d.scale,d.scale]+"-1-1t"+[d.dx,d.dy]:o,f;d&&(f=b=c(b).replace(/\.{3}|\u2026/g,this._.transform||o)),a._extractTransform(this,e+b);var g=this.matrix.clone(),h=this.skew,i=this.node,j,k=~c(this.attrs.fill).indexOf("-"),l=!c(this.attrs.fill).indexOf("url(");g.translate(-0.5,-0.5);if(l||k||this.type=="image"){h.matrix="1 0 0 1",h.offset="0 0",j=g.split();if(k&&j.noRotation||!j.isSimple){i.style.filter=g.toFilter();var m=this.getBBox(),p=this.getBBox(1),q=m.x-p.x,r=m.y-p.y;i.coordorigin=q*-u+n+r*-u,z(this,1,1,q,r,0)}else i.style.filter=o,z(this,j.scalex,j.scaley,j.dx,j.dy,j.rotate)}else i.style.filter=o,h.matrix=c(g),h.offset=g.offset();f&&(this._.transform=f);return this},E.rotate=function(a,b,e){if(this.removed)return this;if(a!=null){a=c(a).split(k),a.length-1&&(b=d(a[1]),e=d(a[2])),a=d(a[0]),e==null&&(b=e);if(b==null||e==null){var f=this.getBBox(1);b=f.x+f.width/2,e=f.y+f.height/2}this._.dirtyT=1,this.transform(this._.transform.concat([["r",a,b,e]]));return this}},E.translate=function(a,b){if(this.removed)return this;a=c(a).split(k),a.length-1&&(b=d(a[1])),a=d(a[0])||0,b=+b||0,this._.bbox&&(this._.bbox.x+=a,this._.bbox.y+=b),this.transform(this._.transform.concat([["t",a,b]]));return this},E.scale=function(a,b,e,f){if(this.removed)return this;a=c(a).split(k),a.length-1&&(b=d(a[1]),e=d(a[2]),f=d(a[3]),isNaN(e)&&(e=null),isNaN(f)&&(f=null)),a=d(a[0]),b==null&&(b=a),f==null&&(e=f);if(e==null||f==null)var g=this.getBBox(1);e=e==null?g.x+g.width/2:e,f=f==null?g.y+g.height/2:f,this.transform(this._.transform.concat([["s",a,b,e,f]])),this._.dirtyT=1;return this},E.hide=function(){!this.removed&&(this.node.style.display="none");return this},E.show=function(){!this.removed&&(this.node.style.display=o);return this},E._getBBox=function(){if(this.removed)return{};return{x:this.X+(this.bbx||0)-this.W/2,y:this.Y-this.H,width:this.W,height:this.H}},E.remove=function(){if(!this.removed&&!!this.node.parentNode){this.paper.__set__&&this.paper.__set__.exclude(this),a.eve.unbind("raphael.*.*."+this.id),a._tear(this,this.paper),this.node.parentNode.removeChild(this.node),this.shape&&this.shape.parentNode.removeChild(this.shape);for(var b in this)this[b]=typeof this[b]=="function"?a._removedFactory(b):null;this.removed=!0}},E.attr=function(c,d){if(this.removed)return this;if(c==null){var e={};for(var f in this.attrs)this.attrs[b](f)&&(e[f]=this.attrs[f]);e.gradient&&e.fill=="none"&&(e.fill=e.gradient)&&delete e.gradient,e.transform=this._.transform;return e}if(d==null&&a.is(c,"string")){if(c==j&&this.attrs.fill=="none"&&this.attrs.gradient)return this.attrs.gradient;var g=c.split(k),h={};for(var i=0,m=g.length;i<m;i++)c=g[i],c in this.attrs?h[c]=this.attrs[c]:a.is(this.paper.customAttributes[c],"function")?h[c]=this.paper.customAttributes[c].def:h[c]=a._availableAttrs[c];return m-1?h:h[g[0]]}if(this.attrs&&d==null&&a.is(c,"array")){h={};for(i=0,m=c.length;i<m;i++)h[c[i]]=this.attr(c[i]);return h}var n;d!=null&&(n={},n[c]=d),d==null&&a.is(c,"object")&&(n=c);for(var o in n)l("raphael.attr."+o+"."+this.id,this,n[o]);if(n){for(o in this.paper.customAttributes)if(this.paper.customAttributes[b](o)&&n[b](o)&&a.is(this.paper.customAttributes[o],"function")){var p=this.paper.customAttributes[o].apply(this,[].concat(n[o]));this.attrs[o]=n[o];for(var q in p)p[b](q)&&(n[q]=p[q])}n.text&&this.type=="text"&&(this.textpath.string=n.text),B(this,n)}return this},E.toFront=function(){!this.removed&&this.node.parentNode.appendChild(this.node),this.paper&&this.paper.top!=this&&a._tofront(this,this.paper);return this},E.toBack=function(){if(this.removed)return this;this.node.parentNode.firstChild!=this.node&&(this.node.parentNode.insertBefore(this.node,this.node.parentNode.firstChild),a._toback(this,this.paper));return this},E.insertAfter=function(b){if(this.removed)return this;b.constructor==a.st.constructor&&(b=b[b.length-1]),b.node.nextSibling?b.node.parentNode.insertBefore(this.node,b.node.nextSibling):b.node.parentNode.appendChild(this.node),a._insertafter(this,b,this.paper);return this},E.insertBefore=function(b){if(this.removed)return this;b.constructor==a.st.constructor&&(b=b[0]),b.node.parentNode.insertBefore(this.node,b.node),a._insertbefore(this,b,this.paper);return this},E.blur=function(b){var c=this.node.runtimeStyle,d=c.filter;d=d.replace(r,o),+b!==0?(this.attrs.blur=b,c.filter=d+n+m+".Blur(pixelradius="+(+b||1.5)+")",c.margin=a.format("-{0}px 0 0 -{0}px",f(+b||1.5))):(c.filter=d,c.margin=0,delete this.attrs.blur)},a._engine.path=function(a,b){var c=F("shape");c.style.cssText=t,c.coordsize=u+n+u,c.coordorigin=b.coordorigin;var d=new D(c,b),e={fill:"none",stroke:"#000"};a&&(e.path=a),d.type="path",d.path=[],d.Path=o,B(d,e),b.canvas.appendChild(c);var f=F("skew");f.on=!0,c.appendChild(f),d.skew=f,d.transform(o);return d},a._engine.rect=function(b,c,d,e,f,g){var h=a._rectPath(c,d,e,f,g),i=b.path(h),j=i.attrs;i.X=j.x=c,i.Y=j.y=d,i.W=j.width=e,i.H=j.height=f,j.r=g,j.path=h,i.type="rect";return i},a._engine.ellipse=function(a,b,c,d,e){var f=a.path(),g=f.attrs;f.X=b-d,f.Y=c-e,f.W=d*2,f.H=e*2,f.type="ellipse",B(f,{cx:b,cy:c,rx:d,ry:e});return f},a._engine.circle=function(a,b,c,d){var e=a.path(),f=e.attrs;e.X=b-d,e.Y=c-d,e.W=e.H=d*2,e.type="circle",B(e,{cx:b,cy:c,r:d});return e},a._engine.image=function(b,c,d,e,f,g){var h=a._rectPath(d,e,f,g),i=b.path(h).attr({stroke:"none"}),k=i.attrs,l=i.node,m=l.getElementsByTagName(j)[0];k.src=c,i.X=k.x=d,i.Y=k.y=e,i.W=k.width=f,i.H=k.height=g,k.path=h,i.type="image",m.parentNode==l&&l.removeChild(m),m.rotate=!0,m.src=c,m.type="tile",i._.fillpos=[d,e],i._.fillsize=[f,g],l.appendChild(m),z(i,1,1,0,0,0);return i},a._engine.text=function(b,d,e,g){var h=F("shape"),i=F("path"),j=F("textpath");d=d||0,e=e||0,g=g||"",i.v=a.format("m{0},{1}l{2},{1}",f(d*u),f(e*u),f(d*u)+1),i.textpathok=!0,j.string=c(g),j.on=!0,h.style.cssText=t,h.coordsize=u+n+u,h.coordorigin="0 0";var k=new D(h,b),l={fill:"#000",stroke:"none",font:a._availableAttrs.font,text:g};k.shape=h,k.path=i,k.textpath=j,k.type="text",k.attrs.text=c(g),k.attrs.x=d,k.attrs.y=e,k.attrs.w=1,k.attrs.h=1,B(k,l),h.appendChild(j),h.appendChild(i),b.canvas.appendChild(h);var m=F("skew");m.on=!0,h.appendChild(m),k.skew=m,k.transform(o);return k},a._engine.setSize=function(b,c){var d=this.canvas.style;this.width=b,this.height=c,b==+b&&(b+="px"),c==+c&&(c+="px"),d.width=b,d.height=c,d.clip="rect(0 "+b+" "+c+" 0)",this._viewBox&&a._engine.setViewBox.apply(this,this._viewBox);return this},a._engine.setViewBox=function(b,c,d,e,f){a.eve("raphael.setViewBox",this,this._viewBox,[b,c,d,e,f]);var h=this.width,i=this.height,j=1/g(d/h,e/i),k,l;f&&(k=i/e,l=h/d,d*k<h&&(b-=(h-d*k)/2/k),e*l<i&&(c-=(i-e*l)/2/l)),this._viewBox=[b,c,d,e,!!f],this._viewBoxShift={dx:-b,dy:-c,scale:j},this.forEach(function(a){a.transform("...")});return this};var F;a._engine.initWin=function(a){var b=a.document;b.createStyleSheet().addRule(".rvml","behavior:url(#default#VML)");try{!b.namespaces.rvml&&b.namespaces.add("rvml","urn:schemas-microsoft-com:vml"),F=function(a){return b.createElement("<rvml:"+a+' class="rvml">')}}catch(c){F=function(a){return b.createElement("<"+a+' xmlns="urn:schemas-microsoft.com:vml" class="rvml">')}}},a._engine.initWin(a._g.win),a._engine.create=function(){var b=a._getContainer.apply(0,arguments),c=b.container,d=b.height,e,f=b.width,g=b.x,h=b.y;if(!c)throw new Error("VML container not found.");var i=new a._Paper,j=i.canvas=a._g.doc.createElement("div"),k=j.style;g=g||0,h=h||0,f=f||512,d=d||342,i.width=f,i.height=d,f==+f&&(f+="px"),d==+d&&(d+="px"),i.coordsize=u*1e3+n+u*1e3,i.coordorigin="0 0",i.span=a._g.doc.createElement("span"),i.span.style.cssText="position:absolute;left:-9999em;top:-9999em;padding:0;margin:0;line-height:1;",j.appendChild(i.span),k.cssText=a.format("top:0;left:0;width:{0};height:{1};display:inline-block;position:relative;clip:rect(0 {0} {1} 0);overflow:hidden",f,d),c==1?(a._g.doc.body.appendChild(j),k.left=g+"px",k.top=h+"px",k.position="absolute"):c.firstChild?c.insertBefore(j,c.firstChild):c.appendChild(j),i.renderfix=function(){};return i},a.prototype.clear=function(){a.eve("raphael.clear",this),this.canvas.innerHTML=o,this.span=a._g.doc.createElement("span"),this.span.style.cssText="position:absolute;left:-9999em;top:-9999em;padding:0;margin:0;line-height:1;display:inline;",this.canvas.appendChild(this.span),this.bottom=this.top=null},a.prototype.remove=function(){a.eve("raphael.remove",this),this.canvas.parentNode.removeChild(this.canvas);for(var b in this)this[b]=typeof this[b]=="function"?a._removedFactory(b):null;return!0};var G=a.st;for(var H in E)E[b](H)&&!G[b](H)&&(G[H]=function(a){return function(){var b=arguments;return this.forEach(function(c){c[a].apply(c,b)})}}(H))}(window.Raphael)
\ No newline at end of file
+break;case"opacity":k.gradient&&!k[b]("stroke-opacity")&&q(i,{"stroke-opacity":p>1?p/100:p});case"fill-opacity":if(k.gradient){I=a._g.doc.getElementById(i.getAttribute("fill").replace(/^url\(#|\)$/g,l)),I&&(J=I.getElementsByTagName("stop"),q(J[J.length-1],{"stop-opacity":p}));break}default:"font-size"==o&&(p=e(p,10)+"px");var K=o.replace(/(\-.)/g,function(a){return a.substring(1).toUpperCase()});i.style[K]=p,d._.dirty=1,i.setAttribute(o,p)}}y(d,f),i.style.visibility=m},x=1.2,y=function(d,f){if("text"==d.type&&(f[b]("text")||f[b]("font")||f[b]("font-size")||f[b]("x")||f[b]("y"))){var g=d.attrs,h=d.node,i=h.firstChild?e(a._g.doc.defaultView.getComputedStyle(h.firstChild,l).getPropertyValue("font-size"),10):10;if(f[b]("text")){for(g.text=f.text;h.firstChild;)h.removeChild(h.firstChild);for(var j,k=c(f.text).split("\n"),m=[],n=0,o=k.length;o>n;n++)j=q("tspan"),n&&q(j,{dy:i*x,x:g.x}),j.appendChild(a._g.doc.createTextNode(k[n])),h.appendChild(j),m[n]=j}else for(m=h.getElementsByTagName("tspan"),n=0,o=m.length;o>n;n++)n?q(m[n],{dy:i*x,x:g.x}):q(m[0],{dy:0});q(h,{x:g.x,y:g.y}),d._.dirty=1;var p=d._getBBox(),r=g.y-(p.y+p.height/2);r&&a.is(r,"finite")&&q(m[0],{dy:r})}},z=function(a){return a.parentNode&&"a"===a.parentNode.tagName.toLowerCase()?a.parentNode:a},A=function(b,c){this[0]=this.node=b,b.raphael=!0,this.id=a._oid++,b.raphaelid=this.id,this.matrix=a.matrix(),this.realPath=null,this.paper=c,this.attrs=this.attrs||{},this._={transform:[],sx:1,sy:1,deg:0,dx:0,dy:0,dirty:1},!c.bottom&&(c.bottom=this),this.prev=c.top,c.top&&(c.top.next=this),c.top=this,this.next=null},B=a.el;A.prototype=B,B.constructor=A,a._engine.path=function(a,b){var c=q("path");b.canvas&&b.canvas.appendChild(c);var d=new A(c,b);return d.type="path",w(d,{fill:"none",stroke:"#000",path:a}),d},B.rotate=function(a,b,e){if(this.removed)return this;if(a=c(a).split(j),a.length-1&&(b=d(a[1]),e=d(a[2])),a=d(a[0]),null==e&&(b=e),null==b||null==e){var f=this.getBBox(1);b=f.x+f.width/2,e=f.y+f.height/2}return this.transform(this._.transform.concat([["r",a,b,e]])),this},B.scale=function(a,b,e,f){if(this.removed)return this;if(a=c(a).split(j),a.length-1&&(b=d(a[1]),e=d(a[2]),f=d(a[3])),a=d(a[0]),null==b&&(b=a),null==f&&(e=f),null==e||null==f)var g=this.getBBox(1);return e=null==e?g.x+g.width/2:e,f=null==f?g.y+g.height/2:f,this.transform(this._.transform.concat([["s",a,b,e,f]])),this},B.translate=function(a,b){return this.removed?this:(a=c(a).split(j),a.length-1&&(b=d(a[1])),a=d(a[0])||0,b=+b||0,this.transform(this._.transform.concat([["t",a,b]])),this)},B.transform=function(c){var d=this._;if(null==c)return d.transform;if(a._extractTransform(this,c),this.clip&&q(this.clip,{transform:this.matrix.invert()}),this.pattern&&s(this),this.node&&q(this.node,{transform:this.matrix}),1!=d.sx||1!=d.sy){var e=this.attrs[b]("stroke-width")?this.attrs["stroke-width"]:1;this.attr({"stroke-width":e})}return d.transform=this.matrix.toTransformString(),this},B.hide=function(){return this.removed||(this.node.style.display="none"),this},B.show=function(){return this.removed||(this.node.style.display=""),this},B.remove=function(){var b=z(this.node);if(!this.removed&&b.parentNode){var c=this.paper;c.__set__&&c.__set__.exclude(this),k.unbind("raphael.*.*."+this.id),this.gradient&&c.defs.removeChild(this.gradient),a._tear(this,c),b.parentNode.removeChild(b),this.removeData();for(var d in this)this[d]="function"==typeof this[d]?a._removedFactory(d):null;this.removed=!0}},B._getBBox=function(){if("none"==this.node.style.display){this.show();var a=!0}var b,c=!1;this.paper.canvas.parentElement?b=this.paper.canvas.parentElement.style:this.paper.canvas.parentNode&&(b=this.paper.canvas.parentNode.style),b&&"none"==b.display&&(c=!0,b.display="");var d={};try{d=this.node.getBBox()}catch(e){d={x:this.node.clientLeft,y:this.node.clientTop,width:this.node.clientWidth,height:this.node.clientHeight}}finally{d=d||{},c&&(b.display="none")}return a&&this.hide(),d},B.attr=function(c,d){if(this.removed)return this;if(null==c){var e={};for(var f in this.attrs)this.attrs[b](f)&&(e[f]=this.attrs[f]);return e.gradient&&"none"==e.fill&&(e.fill=e.gradient)&&delete e.gradient,e.transform=this._.transform,e}if(null==d&&a.is(c,"string")){if("fill"==c&&"none"==this.attrs.fill&&this.attrs.gradient)return this.attrs.gradient;if("transform"==c)return this._.transform;for(var g=c.split(j),h={},i=0,l=g.length;l>i;i++)c=g[i],c in this.attrs?h[c]=this.attrs[c]:a.is(this.paper.customAttributes[c],"function")?h[c]=this.paper.customAttributes[c].def:h[c]=a._availableAttrs[c];return l-1?h:h[g[0]]}if(null==d&&a.is(c,"array")){for(h={},i=0,l=c.length;l>i;i++)h[c[i]]=this.attr(c[i]);return h}if(null!=d){var m={};m[c]=d}else null!=c&&a.is(c,"object")&&(m=c);for(var n in m)k("raphael.attr."+n+"."+this.id,this,m[n]);for(n in this.paper.customAttributes)if(this.paper.customAttributes[b](n)&&m[b](n)&&a.is(this.paper.customAttributes[n],"function")){var o=this.paper.customAttributes[n].apply(this,[].concat(m[n]));this.attrs[n]=m[n];for(var p in o)o[b](p)&&(m[p]=o[p])}return w(this,m),this},B.toFront=function(){if(this.removed)return this;var b=z(this.node);b.parentNode.appendChild(b);var c=this.paper;return c.top!=this&&a._tofront(this,c),this},B.toBack=function(){if(this.removed)return this;var b=z(this.node),c=b.parentNode;c.insertBefore(b,c.firstChild),a._toback(this,this.paper);this.paper;return this},B.insertAfter=function(b){if(this.removed||!b)return this;var c=z(this.node),d=z(b.node||b[b.length-1].node);return d.nextSibling?d.parentNode.insertBefore(c,d.nextSibling):d.parentNode.appendChild(c),a._insertafter(this,b,this.paper),this},B.insertBefore=function(b){if(this.removed||!b)return this;var c=z(this.node),d=z(b.node||b[0].node);return d.parentNode.insertBefore(c,d),a._insertbefore(this,b,this.paper),this},B.blur=function(b){var c=this;if(0!==+b){var d=q("filter"),e=q("feGaussianBlur");c.attrs.blur=b,d.id=a.createUUID(),q(e,{stdDeviation:+b||1.5}),d.appendChild(e),c.paper.defs.appendChild(d),c._blur=d,q(c.node,{filter:"url(#"+d.id+")"})}else c._blur&&(c._blur.parentNode.removeChild(c._blur),delete c._blur,delete c.attrs.blur),c.node.removeAttribute("filter");return c},a._engine.circle=function(a,b,c,d){var e=q("circle");a.canvas&&a.canvas.appendChild(e);var f=new A(e,a);return f.attrs={cx:b,cy:c,r:d,fill:"none",stroke:"#000"},f.type="circle",q(e,f.attrs),f},a._engine.rect=function(a,b,c,d,e,f){var g=q("rect");a.canvas&&a.canvas.appendChild(g);var h=new A(g,a);return h.attrs={x:b,y:c,width:d,height:e,rx:f||0,ry:f||0,fill:"none",stroke:"#000"},h.type="rect",q(g,h.attrs),h},a._engine.ellipse=function(a,b,c,d,e){var f=q("ellipse");a.canvas&&a.canvas.appendChild(f);var g=new A(f,a);return g.attrs={cx:b,cy:c,rx:d,ry:e,fill:"none",stroke:"#000"},g.type="ellipse",q(f,g.attrs),g},a._engine.image=function(a,b,c,d,e,f){var g=q("image");q(g,{x:c,y:d,width:e,height:f,preserveAspectRatio:"none"}),g.setAttributeNS(n,"href",b),a.canvas&&a.canvas.appendChild(g);var h=new A(g,a);return h.attrs={x:c,y:d,width:e,height:f,src:b},h.type="image",h},a._engine.text=function(b,c,d,e){var f=q("text");b.canvas&&b.canvas.appendChild(f);var g=new A(f,b);return g.attrs={x:c,y:d,"text-anchor":"middle",text:e,"font-family":a._availableAttrs["font-family"],"font-size":a._availableAttrs["font-size"],stroke:"none",fill:"#000"},g.type="text",w(g,g.attrs),g},a._engine.setSize=function(a,b){return this.width=a||this.width,this.height=b||this.height,this.canvas.setAttribute("width",this.width),this.canvas.setAttribute("height",this.height),this._viewBox&&this.setViewBox.apply(this,this._viewBox),this},a._engine.create=function(){var b=a._getContainer.apply(0,arguments),c=b&&b.container,d=b.x,e=b.y,f=b.width,g=b.height;if(!c)throw new Error("SVG container not found.");var h,i=q("svg"),j="overflow:hidden;";return d=d||0,e=e||0,f=f||512,g=g||342,q(i,{height:g,version:1.1,width:f,xmlns:"http://www.w3.org/2000/svg","xmlns:xlink":"http://www.w3.org/1999/xlink"}),1==c?(i.style.cssText=j+"position:absolute;left:"+d+"px;top:"+e+"px",a._g.doc.body.appendChild(i),h=1):(i.style.cssText=j+"position:relative",c.firstChild?c.insertBefore(i,c.firstChild):c.appendChild(i)),c=new a._Paper,c.width=f,c.height=g,c.canvas=i,c.clear(),c._left=c._top=0,h&&(c.renderfix=function(){}),c.renderfix(),c},a._engine.setViewBox=function(a,b,c,d,e){k("raphael.setViewBox",this,this._viewBox,[a,b,c,d,e]);var f,h,i=this.getSize(),j=g(c/i.width,d/i.height),l=this.top,n=e?"xMidYMid meet":"xMinYMin";for(null==a?(this._vbSize&&(j=1),delete this._vbSize,f="0 0 "+this.width+m+this.height):(this._vbSize=j,f=a+m+b+m+c+m+d),q(this.canvas,{viewBox:f,preserveAspectRatio:n});j&&l;)h="stroke-width"in l.attrs?l.attrs["stroke-width"]:1,l.attr({"stroke-width":h}),l._.dirty=1,l._.dirtyT=1,l=l.prev;return this._viewBox=[a,b,c,d,!!e],this},a.prototype.renderfix=function(){var a,b=this.canvas,c=b.style;try{a=b.getScreenCTM()||b.createSVGMatrix()}catch(d){a=b.createSVGMatrix()}var e=-a.e%1,f=-a.f%1;(e||f)&&(e&&(this._left=(this._left+e)%1,c.left=this._left+"px"),f&&(this._top=(this._top+f)%1,c.top=this._top+"px"))},a.prototype.clear=function(){a.eve("raphael.clear",this);for(var b=this.canvas;b.firstChild;)b.removeChild(b.firstChild);this.bottom=this.top=null,(this.desc=q("desc")).appendChild(a._g.doc.createTextNode("Created with Raphaël "+a.version)),b.appendChild(this.desc),b.appendChild(this.defs=q("defs"))},a.prototype.remove=function(){k("raphael.remove",this),this.canvas.parentNode&&this.canvas.parentNode.removeChild(this.canvas);for(var b in this)this[b]="function"==typeof this[b]?a._removedFactory(b):null};var C=a.st;for(var D in B)B[b](D)&&!C[b](D)&&(C[D]=function(a){return function(){var b=arguments;return this.forEach(function(c){c[a].apply(c,b)})}}(D))}}),function(a,b){"function"==typeof define&&define.amd?define("raphael.vml",["raphael.core"],function(a){return b(a)}):b("object"==typeof exports?require("./raphael.core"):a.Raphael)}(this,function(a){if(!a||a.vml){var b="hasOwnProperty",c=String,d=parseFloat,e=Math,f=e.round,g=e.max,h=e.min,i=e.abs,j="fill",k=/[, ]+/,l=a.eve,m=" progid:DXImageTransform.Microsoft",n=" ",o="",p={M:"m",L:"l",C:"c",Z:"x",m:"t",l:"r",c:"v",z:"x"},q=/([clmz]),?([^clmz]*)/gi,r=/ progid:\S+Blur\([^\)]+\)/g,s=/-?[^,\s-]+/g,t="position:absolute;left:0;top:0;width:1px;height:1px;behavior:url(#default#VML)",u=21600,v={path:1,rect:1,image:1},w={circle:1,ellipse:1},x=function(b){var d=/[ahqstv]/gi,e=a._pathToAbsolute;if(c(b).match(d)&&(e=a._path2curve),d=/[clmz]/g,e==a._pathToAbsolute&&!c(b).match(d)){var g=c(b).replace(q,function(a,b,c){var d=[],e="m"==b.toLowerCase(),g=p[b];return c.replace(s,function(a){e&&2==d.length&&(g+=d+p["m"==b?"l":"L"],d=[]),d.push(f(a*u))}),g+d});return g}var h,i,j=e(b);g=[];for(var k=0,l=j.length;l>k;k++){h=j[k],i=j[k][0].toLowerCase(),"z"==i&&(i="x");for(var m=1,r=h.length;r>m;m++)i+=f(h[m]*u)+(m!=r-1?",":o);g.push(i)}return g.join(n)},y=function(b,c,d){var e=a.matrix();return e.rotate(-b,.5,.5),{dx:e.x(c,d),dy:e.y(c,d)}},z=function(a,b,c,d,e,f){var g=a._,h=a.matrix,k=g.fillpos,l=a.node,m=l.style,o=1,p="",q=u/b,r=u/c;if(m.visibility="hidden",b&&c){if(l.coordsize=i(q)+n+i(r),m.rotation=f*(0>b*c?-1:1),f){var s=y(f,d,e);d=s.dx,e=s.dy}if(0>b&&(p+="x"),0>c&&(p+=" y")&&(o=-1),m.flip=p,l.coordorigin=d*-q+n+e*-r,k||g.fillsize){var t=l.getElementsByTagName(j);t=t&&t[0],l.removeChild(t),k&&(s=y(f,h.x(k[0],k[1]),h.y(k[0],k[1])),t.position=s.dx*o+n+s.dy*o),g.fillsize&&(t.size=g.fillsize[0]*i(b)+n+g.fillsize[1]*i(c)),l.appendChild(t)}m.visibility="visible"}};a.toString=function(){return"Your browser doesn’t support SVG. Falling down to VML.\nYou are running Raphaël "+this.version};var A=function(a,b,d){for(var e=c(b).toLowerCase().split("-"),f=d?"end":"start",g=e.length,h="classic",i="medium",j="medium";g--;)switch(e[g]){case"block":case"classic":case"oval":case"diamond":case"open":case"none":h=e[g];break;case"wide":case"narrow":j=e[g];break;case"long":case"short":i=e[g]}var k=a.node.getElementsByTagName("stroke")[0];k[f+"arrow"]=h,k[f+"arrowlength"]=i,k[f+"arrowwidth"]=j},B=function(e,i){e.attrs=e.attrs||{};var l=e.node,m=e.attrs,p=l.style,q=v[e.type]&&(i.x!=m.x||i.y!=m.y||i.width!=m.width||i.height!=m.height||i.cx!=m.cx||i.cy!=m.cy||i.rx!=m.rx||i.ry!=m.ry||i.r!=m.r),r=w[e.type]&&(m.cx!=i.cx||m.cy!=i.cy||m.r!=i.r||m.rx!=i.rx||m.ry!=i.ry),s=e;for(var t in i)i[b](t)&&(m[t]=i[t]);if(q&&(m.path=a._getPath[e.type](e),e._.dirty=1),i.href&&(l.href=i.href),i.title&&(l.title=i.title),i.target&&(l.target=i.target),i.cursor&&(p.cursor=i.cursor),"blur"in i&&e.blur(i.blur),(i.path&&"path"==e.type||q)&&(l.path=x(~c(m.path).toLowerCase().indexOf("r")?a._pathToAbsolute(m.path):m.path),e._.dirty=1,"image"==e.type&&(e._.fillpos=[m.x,m.y],e._.fillsize=[m.width,m.height],z(e,1,1,0,0,0))),"transform"in i&&e.transform(i.transform),r){var y=+m.cx,B=+m.cy,D=+m.rx||+m.r||0,E=+m.ry||+m.r||0;l.path=a.format("ar{0},{1},{2},{3},{4},{1},{4},{1}x",f((y-D)*u),f((B-E)*u),f((y+D)*u),f((B+E)*u),f(y*u)),e._.dirty=1}if("clip-rect"in i){var G=c(i["clip-rect"]).split(k);if(4==G.length){G[2]=+G[2]+ +G[0],G[3]=+G[3]+ +G[1];var H=l.clipRect||a._g.doc.createElement("div"),I=H.style;I.clip=a.format("rect({1}px {2}px {3}px {0}px)",G),l.clipRect||(I.position="absolute",I.top=0,I.left=0,I.width=e.paper.width+"px",I.height=e.paper.height+"px",l.parentNode.insertBefore(H,l),H.appendChild(l),l.clipRect=H)}i["clip-rect"]||l.clipRect&&(l.clipRect.style.clip="auto")}if(e.textpath){var J=e.textpath.style;i.font&&(J.font=i.font),i["font-family"]&&(J.fontFamily='"'+i["font-family"].split(",")[0].replace(/^['"]+|['"]+$/g,o)+'"'),i["font-size"]&&(J.fontSize=i["font-size"]),i["font-weight"]&&(J.fontWeight=i["font-weight"]),i["font-style"]&&(J.fontStyle=i["font-style"])}if("arrow-start"in i&&A(s,i["arrow-start"]),"arrow-end"in i&&A(s,i["arrow-end"],1),null!=i.opacity||null!=i["stroke-width"]||null!=i.fill||null!=i.src||null!=i.stroke||null!=i["stroke-width"]||null!=i["stroke-opacity"]||null!=i["fill-opacity"]||null!=i["stroke-dasharray"]||null!=i["stroke-miterlimit"]||null!=i["stroke-linejoin"]||null!=i["stroke-linecap"]){var K=l.getElementsByTagName(j),L=!1;if(K=K&&K[0],!K&&(L=K=F(j)),"image"==e.type&&i.src&&(K.src=i.src),i.fill&&(K.on=!0),(null==K.on||"none"==i.fill||null===i.fill)&&(K.on=!1),K.on&&i.fill){var M=c(i.fill).match(a._ISURL);if(M){K.parentNode==l&&l.removeChild(K),K.rotate=!0,K.src=M[1],K.type="tile";var N=e.getBBox(1);K.position=N.x+n+N.y,e._.fillpos=[N.x,N.y],a._preload(M[1],function(){e._.fillsize=[this.offsetWidth,this.offsetHeight]})}else K.color=a.getRGB(i.fill).hex,K.src=o,K.type="solid",a.getRGB(i.fill).error&&(s.type in{circle:1,ellipse:1}||"r"!=c(i.fill).charAt())&&C(s,i.fill,K)&&(m.fill="none",m.gradient=i.fill,K.rotate=!1)}if("fill-opacity"in i||"opacity"in i){var O=((+m["fill-opacity"]+1||2)-1)*((+m.opacity+1||2)-1)*((+a.getRGB(i.fill).o+1||2)-1);O=h(g(O,0),1),K.opacity=O,K.src&&(K.color="none")}l.appendChild(K);var P=l.getElementsByTagName("stroke")&&l.getElementsByTagName("stroke")[0],Q=!1;!P&&(Q=P=F("stroke")),(i.stroke&&"none"!=i.stroke||i["stroke-width"]||null!=i["stroke-opacity"]||i["stroke-dasharray"]||i["stroke-miterlimit"]||i["stroke-linejoin"]||i["stroke-linecap"])&&(P.on=!0),("none"==i.stroke||null===i.stroke||null==P.on||0==i.stroke||0==i["stroke-width"])&&(P.on=!1);var R=a.getRGB(i.stroke);P.on&&i.stroke&&(P.color=R.hex),O=((+m["stroke-opacity"]+1||2)-1)*((+m.opacity+1||2)-1)*((+R.o+1||2)-1);var S=.75*(d(i["stroke-width"])||1);if(O=h(g(O,0),1),null==i["stroke-width"]&&(S=m["stroke-width"]),i["stroke-width"]&&(P.weight=S),S&&1>S&&(O*=S)&&(P.weight=1),P.opacity=O,i["stroke-linejoin"]&&(P.joinstyle=i["stroke-linejoin"]||"miter"),P.miterlimit=i["stroke-miterlimit"]||8,i["stroke-linecap"]&&(P.endcap="butt"==i["stroke-linecap"]?"flat":"square"==i["stroke-linecap"]?"square":"round"),"stroke-dasharray"in i){var T={"-":"shortdash",".":"shortdot","-.":"shortdashdot","-..":"shortdashdotdot",". ":"dot","- ":"dash","--":"longdash","- .":"dashdot","--.":"longdashdot","--..":"longdashdotdot"};P.dashstyle=T[b](i["stroke-dasharray"])?T[i["stroke-dasharray"]]:o}Q&&l.appendChild(P)}if("text"==s.type){s.paper.canvas.style.display=o;var U=s.paper.span,V=100,W=m.font&&m.font.match(/\d+(?:\.\d*)?(?=px)/);p=U.style,m.font&&(p.font=m.font),m["font-family"]&&(p.fontFamily=m["font-family"]),m["font-weight"]&&(p.fontWeight=m["font-weight"]),m["font-style"]&&(p.fontStyle=m["font-style"]),W=d(m["font-size"]||W&&W[0])||10,p.fontSize=W*V+"px",s.textpath.string&&(U.innerHTML=c(s.textpath.string).replace(/</g,"<").replace(/&/g,"&").replace(/\n/g,"<br>"));var X=U.getBoundingClientRect();s.W=m.w=(X.right-X.left)/V,s.H=m.h=(X.bottom-X.top)/V,s.X=m.x,s.Y=m.y+s.H/2,("x"in i||"y"in i)&&(s.path.v=a.format("m{0},{1}l{2},{1}",f(m.x*u),f(m.y*u),f(m.x*u)+1));for(var Y=["x","y","text","font","font-family","font-weight","font-style","font-size"],Z=0,$=Y.length;$>Z;Z++)if(Y[Z]in i){s._.dirty=1;break}switch(m["text-anchor"]){case"start":s.textpath.style["v-text-align"]="left",s.bbx=s.W/2;break;case"end":s.textpath.style["v-text-align"]="right",s.bbx=-s.W/2;break;default:s.textpath.style["v-text-align"]="center",s.bbx=0}s.textpath.style["v-text-kern"]=!0}},C=function(b,f,g){b.attrs=b.attrs||{};var h=(b.attrs,Math.pow),i="linear",j=".5 .5";if(b.attrs.gradient=f,f=c(f).replace(a._radial_gradient,function(a,b,c){return i="radial",b&&c&&(b=d(b),c=d(c),h(b-.5,2)+h(c-.5,2)>.25&&(c=e.sqrt(.25-h(b-.5,2))*(2*(c>.5)-1)+.5),j=b+n+c),o}),f=f.split(/\s*\-\s*/),"linear"==i){var k=f.shift();if(k=-d(k),isNaN(k))return null}var l=a._parseDots(f);if(!l)return null;if(b=b.shape||b.node,l.length){b.removeChild(g),g.on=!0,g.method="none",g.color=l[0].color,g.color2=l[l.length-1].color;for(var m=[],p=0,q=l.length;q>p;p++)l[p].offset&&m.push(l[p].offset+n+l[p].color);g.colors=m.length?m.join():"0% "+g.color,"radial"==i?(g.type="gradientTitle",g.focus="100%",g.focussize="0 0",g.focusposition=j,g.angle=0):(g.type="gradient",g.angle=(270-k)%360),b.appendChild(g)}return 1},D=function(b,c){this[0]=this.node=b,b.raphael=!0,this.id=a._oid++,b.raphaelid=this.id,this.X=0,this.Y=0,this.attrs={},this.paper=c,this.matrix=a.matrix(),this._={transform:[],sx:1,sy:1,dx:0,dy:0,deg:0,dirty:1,dirtyT:1},!c.bottom&&(c.bottom=this),this.prev=c.top,c.top&&(c.top.next=this),c.top=this,this.next=null},E=a.el;D.prototype=E,E.constructor=D,E.transform=function(b){if(null==b)return this._.transform;var d,e=this.paper._viewBoxShift,f=e?"s"+[e.scale,e.scale]+"-1-1t"+[e.dx,e.dy]:o;e&&(d=b=c(b).replace(/\.{3}|\u2026/g,this._.transform||o)),a._extractTransform(this,f+b);var g,h=this.matrix.clone(),i=this.skew,j=this.node,k=~c(this.attrs.fill).indexOf("-"),l=!c(this.attrs.fill).indexOf("url(");if(h.translate(1,1),l||k||"image"==this.type)if(i.matrix="1 0 0 1",i.offset="0 0",g=h.split(),k&&g.noRotation||!g.isSimple){j.style.filter=h.toFilter();var m=this.getBBox(),p=this.getBBox(1),q=m.x-p.x,r=m.y-p.y;j.coordorigin=q*-u+n+r*-u,z(this,1,1,q,r,0)}else j.style.filter=o,z(this,g.scalex,g.scaley,g.dx,g.dy,g.rotate);else j.style.filter=o,i.matrix=c(h),i.offset=h.offset();return null!==d&&(this._.transform=d,a._extractTransform(this,d)),this},E.rotate=function(a,b,e){if(this.removed)return this;if(null!=a){if(a=c(a).split(k),a.length-1&&(b=d(a[1]),e=d(a[2])),a=d(a[0]),null==e&&(b=e),null==b||null==e){var f=this.getBBox(1);b=f.x+f.width/2,e=f.y+f.height/2}return this._.dirtyT=1,this.transform(this._.transform.concat([["r",a,b,e]])),this}},E.translate=function(a,b){return this.removed?this:(a=c(a).split(k),a.length-1&&(b=d(a[1])),a=d(a[0])||0,b=+b||0,this._.bbox&&(this._.bbox.x+=a,this._.bbox.y+=b),this.transform(this._.transform.concat([["t",a,b]])),this)},E.scale=function(a,b,e,f){if(this.removed)return this;if(a=c(a).split(k),a.length-1&&(b=d(a[1]),e=d(a[2]),f=d(a[3]),isNaN(e)&&(e=null),isNaN(f)&&(f=null)),a=d(a[0]),null==b&&(b=a),null==f&&(e=f),null==e||null==f)var g=this.getBBox(1);return e=null==e?g.x+g.width/2:e,f=null==f?g.y+g.height/2:f,this.transform(this._.transform.concat([["s",a,b,e,f]])),this._.dirtyT=1,this},E.hide=function(){return!this.removed&&(this.node.style.display="none"),this},E.show=function(){return!this.removed&&(this.node.style.display=o),this},E.auxGetBBox=a.el.getBBox,E.getBBox=function(){var a=this.auxGetBBox();if(this.paper&&this.paper._viewBoxShift){var b={},c=1/this.paper._viewBoxShift.scale;return b.x=a.x-this.paper._viewBoxShift.dx,b.x*=c,b.y=a.y-this.paper._viewBoxShift.dy,b.y*=c,b.width=a.width*c,b.height=a.height*c,b.x2=b.x+b.width,b.y2=b.y+b.height,b}return a},E._getBBox=function(){return this.removed?{}:{x:this.X+(this.bbx||0)-this.W/2,y:this.Y-this.H,width:this.W,height:this.H}},E.remove=function(){if(!this.removed&&this.node.parentNode){this.paper.__set__&&this.paper.__set__.exclude(this),a.eve.unbind("raphael.*.*."+this.id),a._tear(this,this.paper),this.node.parentNode.removeChild(this.node),this.shape&&this.shape.parentNode.removeChild(this.shape);for(var b in this)this[b]="function"==typeof this[b]?a._removedFactory(b):null;this.removed=!0}},E.attr=function(c,d){if(this.removed)return this;if(null==c){var e={};for(var f in this.attrs)this.attrs[b](f)&&(e[f]=this.attrs[f]);return e.gradient&&"none"==e.fill&&(e.fill=e.gradient)&&delete e.gradient,e.transform=this._.transform,e}if(null==d&&a.is(c,"string")){if(c==j&&"none"==this.attrs.fill&&this.attrs.gradient)return this.attrs.gradient;for(var g=c.split(k),h={},i=0,m=g.length;m>i;i++)c=g[i],c in this.attrs?h[c]=this.attrs[c]:a.is(this.paper.customAttributes[c],"function")?h[c]=this.paper.customAttributes[c].def:h[c]=a._availableAttrs[c];return m-1?h:h[g[0]]}if(this.attrs&&null==d&&a.is(c,"array")){for(h={},i=0,m=c.length;m>i;i++)h[c[i]]=this.attr(c[i]);return h}var n;null!=d&&(n={},n[c]=d),null==d&&a.is(c,"object")&&(n=c);for(var o in n)l("raphael.attr."+o+"."+this.id,this,n[o]);if(n){for(o in this.paper.customAttributes)if(this.paper.customAttributes[b](o)&&n[b](o)&&a.is(this.paper.customAttributes[o],"function")){var p=this.paper.customAttributes[o].apply(this,[].concat(n[o]));this.attrs[o]=n[o];for(var q in p)p[b](q)&&(n[q]=p[q])}n.text&&"text"==this.type&&(this.textpath.string=n.text),B(this,n)}return this},E.toFront=function(){return!this.removed&&this.node.parentNode.appendChild(this.node),this.paper&&this.paper.top!=this&&a._tofront(this,this.paper),this},E.toBack=function(){return this.removed?this:(this.node.parentNode.firstChild!=this.node&&(this.node.parentNode.insertBefore(this.node,this.node.parentNode.firstChild),a._toback(this,this.paper)),this)},E.insertAfter=function(b){return this.removed?this:(b.constructor==a.st.constructor&&(b=b[b.length-1]),b.node.nextSibling?b.node.parentNode.insertBefore(this.node,b.node.nextSibling):b.node.parentNode.appendChild(this.node),a._insertafter(this,b,this.paper),this)},E.insertBefore=function(b){return this.removed?this:(b.constructor==a.st.constructor&&(b=b[0]),b.node.parentNode.insertBefore(this.node,b.node),a._insertbefore(this,b,this.paper),this)},E.blur=function(b){var c=this.node.runtimeStyle,d=c.filter;return d=d.replace(r,o),0!==+b?(this.attrs.blur=b,c.filter=d+n+m+".Blur(pixelradius="+(+b||1.5)+")",c.margin=a.format("-{0}px 0 0 -{0}px",f(+b||1.5))):(c.filter=d,c.margin=0,delete this.attrs.blur),this},a._engine.path=function(a,b){var c=F("shape");c.style.cssText=t,c.coordsize=u+n+u,c.coordorigin=b.coordorigin;var d=new D(c,b),e={fill:"none",stroke:"#000"};a&&(e.path=a),d.type="path",d.path=[],d.Path=o,B(d,e),b.canvas.appendChild(c);var f=F("skew");return f.on=!0,c.appendChild(f),d.skew=f,d.transform(o),d},a._engine.rect=function(b,c,d,e,f,g){var h=a._rectPath(c,d,e,f,g),i=b.path(h),j=i.attrs;return i.X=j.x=c,i.Y=j.y=d,i.W=j.width=e,i.H=j.height=f,j.r=g,j.path=h,i.type="rect",i},a._engine.ellipse=function(a,b,c,d,e){{var f=a.path();f.attrs}return f.X=b-d,f.Y=c-e,f.W=2*d,f.H=2*e,f.type="ellipse",B(f,{cx:b,cy:c,rx:d,ry:e}),f},a._engine.circle=function(a,b,c,d){{var e=a.path();e.attrs}return e.X=b-d,e.Y=c-d,e.W=e.H=2*d,e.type="circle",B(e,{cx:b,cy:c,r:d}),e},a._engine.image=function(b,c,d,e,f,g){var h=a._rectPath(d,e,f,g),i=b.path(h).attr({stroke:"none"}),k=i.attrs,l=i.node,m=l.getElementsByTagName(j)[0];return k.src=c,i.X=k.x=d,i.Y=k.y=e,i.W=k.width=f,i.H=k.height=g,k.path=h,i.type="image",m.parentNode==l&&l.removeChild(m),m.rotate=!0,m.src=c,m.type="tile",i._.fillpos=[d,e],i._.fillsize=[f,g],l.appendChild(m),z(i,1,1,0,0,0),i},a._engine.text=function(b,d,e,g){var h=F("shape"),i=F("path"),j=F("textpath");d=d||0,e=e||0,g=g||"",i.v=a.format("m{0},{1}l{2},{1}",f(d*u),f(e*u),f(d*u)+1),i.textpathok=!0,j.string=c(g),j.on=!0,h.style.cssText=t,h.coordsize=u+n+u,h.coordorigin="0 0";var k=new D(h,b),l={fill:"#000",stroke:"none",font:a._availableAttrs.font,text:g};k.shape=h,k.path=i,k.textpath=j,k.type="text",k.attrs.text=c(g),k.attrs.x=d,k.attrs.y=e,k.attrs.w=1,k.attrs.h=1,B(k,l),h.appendChild(j),h.appendChild(i),b.canvas.appendChild(h);var m=F("skew");return m.on=!0,h.appendChild(m),k.skew=m,k.transform(o),k},a._engine.setSize=function(b,c){var d=this.canvas.style;return this.width=b,this.height=c,b==+b&&(b+="px"),c==+c&&(c+="px"),d.width=b,d.height=c,d.clip="rect(0 "+b+" "+c+" 0)",this._viewBox&&a._engine.setViewBox.apply(this,this._viewBox),this},a._engine.setViewBox=function(b,c,d,e,f){a.eve("raphael.setViewBox",this,this._viewBox,[b,c,d,e,f]);var g,h,i=this.getSize(),j=i.width,k=i.height;return f&&(g=k/e,h=j/d,j>d*g&&(b-=(j-d*g)/2/g),k>e*h&&(c-=(k-e*h)/2/h)),this._viewBox=[b,c,d,e,!!f],this._viewBoxShift={dx:-b,dy:-c,scale:i},this.forEach(function(a){a.transform("...")}),this};var F;a._engine.initWin=function(a){var b=a.document;b.styleSheets.length<31?b.createStyleSheet().addRule(".rvml","behavior:url(#default#VML)"):b.styleSheets[0].addRule(".rvml","behavior:url(#default#VML)");try{!b.namespaces.rvml&&b.namespaces.add("rvml","urn:schemas-microsoft-com:vml"),F=function(a){return b.createElement("<rvml:"+a+' class="rvml">')}}catch(c){F=function(a){return b.createElement("<"+a+' xmlns="urn:schemas-microsoft.com:vml" class="rvml">')}}},a._engine.initWin(a._g.win),a._engine.create=function(){var b=a._getContainer.apply(0,arguments),c=b.container,d=b.height,e=b.width,f=b.x,g=b.y;if(!c)throw new Error("VML container not found.");var h=new a._Paper,i=h.canvas=a._g.doc.createElement("div"),j=i.style;return f=f||0,g=g||0,e=e||512,d=d||342,h.width=e,h.height=d,e==+e&&(e+="px"),d==+d&&(d+="px"),h.coordsize=1e3*u+n+1e3*u,h.coordorigin="0 0",h.span=a._g.doc.createElement("span"),h.span.style.cssText="position:absolute;left:-9999em;top:-9999em;padding:0;margin:0;line-height:1;",i.appendChild(h.span),j.cssText=a.format("top:0;left:0;width:{0};height:{1};display:inline-block;position:relative;clip:rect(0 {0} {1} 0);overflow:hidden",e,d),1==c?(a._g.doc.body.appendChild(i),j.left=f+"px",j.top=g+"px",j.position="absolute"):c.firstChild?c.insertBefore(i,c.firstChild):c.appendChild(i),h.renderfix=function(){},h},a.prototype.clear=function(){a.eve("raphael.clear",this),this.canvas.innerHTML=o,this.span=a._g.doc.createElement("span"),this.span.style.cssText="position:absolute;left:-9999em;top:-9999em;padding:0;margin:0;line-height:1;display:inline;",this.canvas.appendChild(this.span),this.bottom=this.top=null},a.prototype.remove=function(){a.eve("raphael.remove",this),this.canvas.parentNode.removeChild(this.canvas);for(var b in this)this[b]="function"==typeof this[b]?a._removedFactory(b):null;return!0};var G=a.st;for(var H in E)E[b](H)&&!G[b](H)&&(G[H]=function(a){return function(){var b=arguments;return this.forEach(function(c){c[a].apply(c,b)})}}(H))}}),function(a,b){if("function"==typeof define&&define.amd)define("raphael",["raphael.core","raphael.svg","raphael.vml"],function(c){return a.Raphael=b(c)});else if("object"==typeof exports){var c=require("raphael.core");require("raphael.svg"),require("raphael.vml"),module.exports=b(c)}else a.Raphael=b(a.Raphael)}(this,function(a){return a.ninja()});
\ No newline at end of file
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/src/ldt/ldt/static/ldt/js/renkan.js Fri Oct 02 10:24:05 2015 +0200
@@ -0,0 +1,6699 @@
+/*!
+ * _____ _
+ * | __ \ | |
+ * | |__) |___ _ __ | | ____ _ _ __
+ * | _ // _ \ '_ \| |/ / _` | '_ \
+ * | | \ \ __/ | | | < (_| | | | |
+ * |_| \_\___|_| |_|_|\_\__,_|_| |_|
+ *
+ * Copyright 2012-2015 Institut de recherche et d'innovation
+ * contributor(s) : Yves-Marie Haussonne, Raphael Velt, Samuel Huron,
+ * Thibaut Cavalié, Julien Rougeron.
+ *
+ * contact@iri.centrepompidou.fr
+ * http://www.iri.centrepompidou.fr
+ *
+ * This software is a computer program whose purpose is to show and add annotations on a video .
+ * This software is governed by the CeCILL-C license under French law and
+ * abiding by the rules of distribution of free software. You can use,
+ * modify and/ or redistribute the software under the terms of the CeCILL-C
+ * license as circulated by CEA, CNRS and INRIA at the following URL
+ * "http://www.cecill.info".
+ *
+ * The fact that you are presently reading this means that you have had
+ * knowledge of the CeCILL-C license and that you accept its terms.
+ */
+
+/*! renkan - v0.12.4 - Copyright © IRI 2015 */
+
+this["renkanJST"] = this["renkanJST"] || {};
+
+this["renkanJST"]["templates/colorpicker.html"] = function(obj) {
+obj || (obj = {});
+var __t, __p = '', __e = _.escape;
+with (obj) {
+__p += '<li data-color="' +
+((__t = (c)) == null ? '' : __t) +
+'" style="background: ' +
+((__t = (c)) == null ? '' : __t) +
+'"></li>';
+
+}
+return __p
+};
+
+this["renkanJST"]["templates/edgeeditor.html"] = function(obj) {
+obj || (obj = {});
+var __t, __p = '', __e = _.escape, __j = Array.prototype.join;
+function print() { __p += __j.call(arguments, '') }
+with (obj) {
+__p += '<h2>\n <span class="Rk-CloseX">×</span>' +
+__e(renkan.translate("Edit Edge")) +
+'</span>\n</h2>\n<p>\n <label>' +
+__e(renkan.translate("Title:")) +
+'</label>\n <input class="Rk-Edit-Title" type="text" value="' +
+__e(edge.title) +
+'" />\n</p>\n';
+ if (options.show_edge_editor_uri) { ;
+__p += '\n <p>\n <label>' +
+__e(renkan.translate("URI:")) +
+'</label>\n <input class="Rk-Edit-URI" type="text" value="' +
+__e(edge.uri) +
+'" />\n <a class="Rk-Edit-Goto" href="' +
+__e(edge.uri) +
+'" target="_blank"></a>\n </p>\n ';
+ if (options.properties.length) { ;
+__p += '\n <p>\n <label>' +
+__e(renkan.translate("Choose from vocabulary:")) +
+'</label>\n <select class="Rk-Edit-Vocabulary">\n ';
+ _.each(options.properties, function(ontology) { ;
+__p += '\n <option class="Rk-Edit-Vocabulary-Class" value="">\n ' +
+__e( renkan.translate(ontology.label) ) +
+'\n </option>\n ';
+ _.each(ontology.properties, function(property) { var uri = ontology["base-uri"] + property.uri; ;
+__p += '\n <option class="Rk-Edit-Vocabulary-Property" value="' +
+__e( uri ) +
+'"\n ';
+ if (uri === edge.uri) { ;
+__p += ' selected';
+ } ;
+__p += '>\n ' +
+__e( renkan.translate(property.label) ) +
+'\n </option>\n ';
+ }) ;
+__p += '\n ';
+ }) ;
+__p += '\n </select>\n </p>\n';
+ } } ;
+__p += '\n';
+ if (options.show_edge_editor_style) { ;
+__p += '\n <div class="Rk-Editor-p">\n ';
+ if (options.show_edge_editor_style_color) { ;
+__p += '\n <div id="Rk-Editor-p-color">\n <span class="Rk-Editor-Label">' +
+__e(renkan.translate("Edge color:")) +
+'</span>\n <div class="Rk-Edit-ColorPicker-Wrapper">\n <span class="Rk-Edit-Color" style="background: <%-edge.color%>;">\n <span class="Rk-Edit-ColorTip"></span>\n </span>\n ' +
+((__t = ( renkan.colorPicker )) == null ? '' : __t) +
+'\n <span class="Rk-Edit-ColorPicker-Text">' +
+__e( renkan.translate("Choose color") ) +
+'</span>\n </div>\n </div>\n ';
+ } ;
+__p += '\n ';
+ if (options.show_edge_editor_style_dash) { ;
+__p += '\n <div id="Rk-Editor-p-dash">\n <span class="Rk-Editor-Label">' +
+__e(renkan.translate("Dash:")) +
+'</span>\n <input type="checkbox" name="Rk-Edit-Dash" class="Rk-Edit-Dash" ' +
+__e( edge.dash ) +
+' />\n </div>\n ';
+ } ;
+__p += '\n ';
+ if (options.show_edge_editor_style_thickness) { ;
+__p += '\n <div id="Rk-Editor-p-thickness">\n <span class="Rk-Editor-Label">' +
+__e(renkan.translate("Thickness:")) +
+'</span>\n <a href="#" class="Rk-Edit-Size-Btn" id="Rk-Edit-Thickness-Down">-</a>\n <span class="Rk-Edit-Size-Disp" id="Rk-Edit-Thickness-Value">' +
+__e( edge.thickness ) +
+'</span>\n <a href="#" class="Rk-Edit-Size-Btn" id="Rk-Edit-Thickness-Up">+</a>\n </div>\n ';
+ } ;
+__p += '\n ';
+ if (options.show_edge_editor_style_arrow) { ;
+__p += '\n <div id="Rk-Editor-p-arrow">\n <span class="Rk-Editor-Label">' +
+__e(renkan.translate("Arrow:")) +
+'</span>\n <input type="checkbox" name="Rk-Edit-Arrow" class="Rk-Edit-Arrow" ' +
+__e( edge.arrow ) +
+' />\n </div>\n ';
+ } ;
+__p += '\n </div>\n';
+ } ;
+__p += '\n';
+ if (options.show_edge_editor_direction) { ;
+__p += '\n <p>\n <span class="Rk-Edit-Direction">' +
+__e( renkan.translate("Change edge direction") ) +
+'</span>\n </p>\n';
+ } ;
+__p += '\n';
+ if (options.show_edge_editor_nodes) { ;
+__p += '\n <p>\n <span class="Rk-Editor-Label">' +
+__e(renkan.translate("From:")) +
+'</span>\n <span class="Rk-UserColor" style="background: ' +
+__e(edge.from_color) +
+';"></span>\n ' +
+__e( shortenText(edge.from_title, 25) ) +
+'\n </p>\n <p>\n <span class="Rk-Editor-Label">' +
+__e(renkan.translate("To:")) +
+'</span>\n <span class="Rk-UserColor" style="background: >%-edge.to_color%>;"></span>\n ' +
+__e( shortenText(edge.to_title, 25) ) +
+'\n </p>\n';
+ } ;
+__p += '\n';
+ if (options.show_edge_editor_creator && edge.has_creator) { ;
+__p += '\n <p>\n <span class="Rk-Editor-Label">' +
+__e(renkan.translate("Created by:")) +
+'</span>\n <span class="Rk-UserColor" style="background: <%-edge.created_by_color%>;"></span>\n ' +
+__e( shortenText(edge.created_by_title, 25) ) +
+'\n </p>\n';
+ } ;
+__p += '\n';
+
+}
+return __p
+};
+
+this["renkanJST"]["templates/edgeeditor_readonly.html"] = function(obj) {
+obj || (obj = {});
+var __t, __p = '', __e = _.escape, __j = Array.prototype.join;
+function print() { __p += __j.call(arguments, '') }
+with (obj) {
+__p += '<h2>\n <span class="Rk-CloseX">×</span>\n ';
+ if (options.show_edge_tooltip_color) { ;
+__p += '\n <span class="Rk-UserColor" style="background: ' +
+__e( edge.color ) +
+';"></span>\n ';
+ } ;
+__p += '\n <span class="Rk-Display-Title">\n ';
+ if (edge.uri) { ;
+__p += '\n <a href="' +
+__e(edge.uri) +
+'" target="_blank">\n ';
+ } ;
+__p += '\n ' +
+__e(edge.title) +
+'\n ';
+ if (edge.uri) { ;
+__p += ' </a> ';
+ } ;
+__p += '\n </span>\n</h2>\n';
+ if (options.show_edge_tooltip_uri && edge.uri) { ;
+__p += '\n <p class="Rk-Display-URI">\n <a href="' +
+__e(edge.uri) +
+'" target="_blank">' +
+__e( edge.short_uri ) +
+'</a>\n </p>\n';
+ } ;
+__p += '\n<p>' +
+((__t = (edge.description)) == null ? '' : __t) +
+'</p>\n';
+ if (options.show_edge_tooltip_nodes) { ;
+__p += '\n <p>\n <span class="Rk-Editor-Label">' +
+__e(renkan.translate("From:")) +
+'</span>\n <span class="Rk-UserColor" style="background: ' +
+__e( edge.from_color ) +
+';"></span>\n ' +
+__e( shortenText(edge.from_title, 25) ) +
+'\n </p>\n <p>\n <span class="Rk-Editor-Label">' +
+__e(renkan.translate("To:")) +
+'</span>\n <span class="Rk-UserColor" style="background: ' +
+__e( edge.to_color ) +
+';"></span>\n ' +
+__e( shortenText(edge.to_title, 25) ) +
+'\n </p>\n';
+ } ;
+__p += '\n';
+ if (options.show_edge_tooltip_creator && edge.has_creator) { ;
+__p += '\n <p>\n <span class="Rk-Editor-Label">' +
+__e(renkan.translate("Created by:")) +
+'</span>\n <span class="Rk-UserColor" style="background: ' +
+__e( edge.created_by_color ) +
+';"></span>\n ' +
+__e( shortenText(edge.created_by_title, 25) ) +
+'\n </p>\n';
+ } ;
+__p += '\n';
+
+}
+return __p
+};
+
+this["renkanJST"]["templates/ldtjson-bin/annotationtemplate.html"] = function(obj) {
+obj || (obj = {});
+var __t, __p = '', __e = _.escape;
+with (obj) {
+__p += '<li class="Rk-Bin-Item" draggable="true"\n data-image="' +
+__e( Rkns.Utils.getFullURL(image) ) +
+'"\n data-uri="' +
+((__t = (ldt_platform)) == null ? '' : __t) +
+'ldtplatform/ldt/front/player/' +
+((__t = (mediaid)) == null ? '' : __t) +
+'/#id=' +
+((__t = (annotationid)) == null ? '' : __t) +
+'"\n data-title="' +
+__e(title) +
+'" data-description="' +
+__e(description) +
+'">\n\n <img class="Rk-Ldt-Annotation-Icon" src="' +
+((__t = (image)) == null ? '' : __t) +
+'" />\n <h4>' +
+((__t = (htitle)) == null ? '' : __t) +
+'</h4>\n <p>' +
+((__t = (hdescription)) == null ? '' : __t) +
+'</p>\n <p>Start: ' +
+((__t = (start)) == null ? '' : __t) +
+', End: ' +
+((__t = (end)) == null ? '' : __t) +
+', Duration: ' +
+((__t = (duration)) == null ? '' : __t) +
+'</p>\n <div class="Rk-Clear"></div>\n</li>\n';
+
+}
+return __p
+};
+
+this["renkanJST"]["templates/ldtjson-bin/segmenttemplate.html"] = function(obj) {
+obj || (obj = {});
+var __t, __p = '', __e = _.escape;
+with (obj) {
+__p += '<li class="Rk-Bin-Item" draggable="true"\n data-image="' +
+__e( Rkns.Utils.getFullURL(image) ) +
+'"\n data-uri="' +
+((__t = (ldt_platform)) == null ? '' : __t) +
+'ldtplatform/ldt/front/player/' +
+((__t = (mediaid)) == null ? '' : __t) +
+'/#id=' +
+((__t = (annotationid)) == null ? '' : __t) +
+'"\n data-title="' +
+__e(title) +
+'" data-description="' +
+__e(description) +
+'">\n\n <img class="Rk-Ldt-Annotation-Icon" src="' +
+((__t = (image)) == null ? '' : __t) +
+'" />\n <h4>' +
+((__t = (htitle)) == null ? '' : __t) +
+'</h4>\n <p>' +
+((__t = (hdescription)) == null ? '' : __t) +
+'</p>\n <p>Start: ' +
+((__t = (start)) == null ? '' : __t) +
+', End: ' +
+((__t = (end)) == null ? '' : __t) +
+', Duration: ' +
+((__t = (duration)) == null ? '' : __t) +
+'</p>\n <div class="Rk-Clear"></div>\n</li>\n';
+
+}
+return __p
+};
+
+this["renkanJST"]["templates/ldtjson-bin/tagtemplate.html"] = function(obj) {
+obj || (obj = {});
+var __t, __p = '', __e = _.escape;
+with (obj) {
+__p += '<li class="Rk-Bin-Item" draggable="true"\n data-image="' +
+__e( Rkns.Utils.getFullURL(static_url+'img/ldt-tag.png') ) +
+'"\n data-uri="' +
+((__t = (ldt_platform)) == null ? '' : __t) +
+'ldtplatform/ldt/front/search/?search=' +
+((__t = (encodedtitle)) == null ? '' : __t) +
+'&field=all"\n data-title="' +
+__e(title) +
+'" data-description="Tag \'' +
+__e(title) +
+'\'">\n\n <img class="Rk-Ldt-Tag-Icon" src="' +
+__e(static_url) +
+'img/ldt-tag.png" />\n <h4>' +
+((__t = (htitle)) == null ? '' : __t) +
+'</h4>\n <div class="Rk-Clear"></div>\n</li>\n';
+
+}
+return __p
+};
+
+this["renkanJST"]["templates/list-bin.html"] = function(obj) {
+obj || (obj = {});
+var __t, __p = '', __e = _.escape, __j = Array.prototype.join;
+function print() { __p += __j.call(arguments, '') }
+with (obj) {
+__p += '<li class="Rk-Bin-Item Rk-ResourceList-Item" draggable="true"\n data-uri="' +
+__e(url) +
+'" data-title="' +
+__e(title) +
+'"\n data-description="' +
+__e(description) +
+'"\n ';
+ if (image) { ;
+__p += '\n data-image="' +
+__e( Rkns.Utils.getFullURL(image) ) +
+'"\n ';
+ } else { ;
+__p += '\n data-image=""\n ';
+ } ;
+__p += '\n>';
+ if (image) { ;
+__p += '\n <img class="Rk-ResourceList-Image" src="' +
+__e(image) +
+'" />\n';
+ } ;
+__p += '\n<h4 class="Rk-ResourceList-Title">\n ';
+ if (url) { ;
+__p += '\n <a href="' +
+__e(url) +
+'" target="_blank">\n ';
+ } ;
+__p += '\n ' +
+((__t = (htitle)) == null ? '' : __t) +
+'\n ';
+ if (url) { ;
+__p += '</a>';
+ } ;
+__p += '\n </h4>\n ';
+ if (description) { ;
+__p += '\n <p class="Rk-ResourceList-Description">' +
+((__t = (hdescription)) == null ? '' : __t) +
+'</p>\n ';
+ } ;
+__p += '\n ';
+ if (image) { ;
+__p += '\n <div style="clear: both;"></div>\n ';
+ } ;
+__p += '\n</li>\n';
+
+}
+return __p
+};
+
+this["renkanJST"]["templates/main.html"] = function(obj) {
+obj || (obj = {});
+var __t, __p = '', __e = _.escape, __j = Array.prototype.join;
+function print() { __p += __j.call(arguments, '') }
+with (obj) {
+
+ if (options.show_bins) { ;
+__p += '\n <div class="Rk-Bins">\n <div class="Rk-Bins-Head">\n <h2 class="Rk-Bins-Title">' +
+__e( translate("Select contents:")) +
+'</h2>\n <form class="Rk-Web-Search-Form Rk-Search-Form">\n <input class="Rk-Web-Search-Input Rk-Search-Input" type="search"\n placeholder="' +
+__e( translate('Search the Web') ) +
+'" />\n <div class="Rk-Search-Select">\n <div class="Rk-Search-Current"></div>\n <ul class="Rk-Search-List"></ul>\n </div>\n <input type="submit" value=""\n class="Rk-Web-Search-Submit Rk-Search-Submit" title="' +
+__e( translate('Search the Web') ) +
+'" />\n </form>\n <form class="Rk-Bins-Search-Form Rk-Search-Form">\n <input class="Rk-Bins-Search-Input Rk-Search-Input" type="search"\n placeholder="' +
+__e( translate('Search in Bins') ) +
+'" /> <input\n type="submit" value=""\n class="Rk-Bins-Search-Submit Rk-Search-Submit"\n title="' +
+__e( translate('Search in Bins') ) +
+'" />\n </form>\n </div>\n <ul class="Rk-Bin-List"></ul>\n </div>\n';
+ } ;
+__p += ' ';
+ if (options.show_editor) { ;
+__p += '\n <div class="Rk-Render Rk-Render-';
+ if (options.show_bins) { ;
+__p += 'Panel';
+ } else { ;
+__p += 'Full';
+ } ;
+__p += '"></div>\n';
+ } ;
+__p += '\n';
+
+}
+return __p
+};
+
+this["renkanJST"]["templates/nodeeditor.html"] = function(obj) {
+obj || (obj = {});
+var __t, __p = '', __e = _.escape, __j = Array.prototype.join;
+function print() { __p += __j.call(arguments, '') }
+with (obj) {
+
+ //TODO: change class to id ;
+__p += '\n<h2>\n <span class="Rk-CloseX">×</span>' +
+__e(renkan.translate("Edit Node")) +
+'</span>\n</h2>\n<p>\n <label>' +
+__e(renkan.translate("Title:")) +
+'</label>\n <input class="Rk-Edit-Title" type="text" value="' +
+__e(node.title) +
+'" />\n</p>\n';
+ if (options.show_node_editor_uri) { ;
+__p += '\n <p>\n <label>' +
+__e(renkan.translate("URI:")) +
+'</label>\n <input class="Rk-Edit-URI" type="text" value="' +
+__e(node.uri) +
+'" />\n <a class="Rk-Edit-Goto" href="' +
+__e(node.uri) +
+'" target="_blank"></a>\n </p>\n';
+ } ;
+__p += ' ';
+ if (options.change_types) { ;
+__p += '\n <p>\n <label>' +
+__e(renkan.translate("Types available")) +
+':</label>\n <select class="Rk-Edit-Type">\n ';
+ _.each(types, function(type) { ;
+__p += '\n <option class="Rk-Edit-Vocabulary-Property" value="' +
+__e( type ) +
+'"';
+ if (node.type === type) { ;
+__p += ' selected';
+ } ;
+__p += '>\n ' +
+__e( renkan.translate(type.charAt(0).toUpperCase() + type.substring(1)) ) +
+'\n </option>\n ';
+ }); ;
+__p += '\n </select>\n </p>\n';
+ } ;
+__p += ' ';
+ if (options.show_node_editor_description) { ;
+__p += '\n <p>\n <label>' +
+__e(renkan.translate("Description:")) +
+'</label>\n ';
+ if (options.show_node_editor_description_richtext) { ;
+__p += '\n <div class="Rk-Edit-Description" contenteditable="true">' +
+((__t = (node.description)) == null ? '' : __t) +
+'</div>\n ';
+ } else { ;
+__p += '\n <textarea class="Rk-Edit-Description">' +
+((__t = (node.description)) == null ? '' : __t) +
+'</textarea>\n ';
+ } ;
+__p += '\n </p>\n';
+ } ;
+__p += ' ';
+ if (options.show_node_editor_size) { ;
+__p += '\n <p>\n <span class="Rk-Editor-Label">' +
+__e(renkan.translate("Size:")) +
+'</span>\n <a href="#" class="Rk-Edit-Size-Btn" id="Rk-Edit-Size-Down">-</a>\n <span class="Rk-Edit-Size-Disp" id="Rk-Edit-Size-Value">' +
+__e(node.size) +
+'</span>\n <a href="#" class="Rk-Edit-Size-Btn" id="Rk-Edit-Size-Up">+</a>\n </p>\n';
+ } ;
+__p += ' ';
+ if (options.show_node_editor_style) { ;
+__p += '\n <div class="Rk-Editor-p">\n ';
+ if (options.show_node_editor_style_color) { ;
+__p += '\n <div id="Rk-Editor-p-color">\n <span class="Rk-Editor-Label">\n ' +
+__e(renkan.translate("Node color:")) +
+'</span>\n <div class="Rk-Edit-ColorPicker-Wrapper">\n <span class="Rk-Edit-Color" style="background: ' +
+__e(node.color) +
+';">\n <span class="Rk-Edit-ColorTip"></span>\n </span>\n ' +
+((__t = ( renkan.colorPicker )) == null ? '' : __t) +
+'\n <span class="Rk-Edit-ColorPicker-Text">' +
+__e( renkan.translate("Choose color") ) +
+'</span>\n </div>\n </div>\n ';
+ } ;
+__p += '\n ';
+ if (options.show_node_editor_style_dash) { ;
+__p += '\n <div id="Rk-Editor-p-dash">\n <span class="Rk-Editor-Label">' +
+__e(renkan.translate("Dash:")) +
+'</span>\n <input type="checkbox" name="Rk-Edit-Dash" class="Rk-Edit-Dash" ' +
+__e( node.dash ) +
+' />\n </div>\n ';
+ } ;
+__p += '\n ';
+ if (options.show_node_editor_style_thickness) { ;
+__p += '\n <div id="Rk-Editor-p-thickness">\n <span class="Rk-Editor-Label">' +
+__e(renkan.translate("Thickness:")) +
+'</span>\n <a href="#" class="Rk-Edit-Size-Btn" id="Rk-Edit-Thickness-Down">-</a>\n <span class="Rk-Edit-Size-Disp" id="Rk-Edit-Thickness-Value">' +
+__e(node.thickness) +
+'</span>\n <a href="#" class="Rk-Edit-Size-Btn" id="Rk-Edit-Thickness-Up">+</a>\n </div>\n ';
+ } ;
+__p += '\n </div>\n';
+ } ;
+__p += ' ';
+ if (options.show_node_editor_image) { ;
+__p += '\n <div class="Rk-Edit-ImgWrap">\n <div class="Rk-Edit-ImgPreview">\n <img src="' +
+__e(node.image || node.image_placeholder) +
+'" />\n ';
+ if (node.clip_path) { ;
+__p += '\n <svg xmlns="http://www.w3.org/2000/svg" version="1.1" viewbox="0 0 1 1" preserveAspectRatio="none">\n <path style="stroke-width: .02; stroke:red; fill-opacity:.3; fill:red;" d="' +
+__e( node.clip_path ) +
+'" />\n </svg>\n ';
+ };
+__p += '\n </div>\n </div>\n <p>\n <label>' +
+__e(renkan.translate("Image URL:")) +
+'</label>\n <div>\n <a class="Rk-Edit-Image-Del" href="#"></a>\n <input class="Rk-Edit-Image" type="text" value=\'' +
+__e(node.image) +
+'\' />\n </div>\n </p>\n';
+ if (options.allow_image_upload) { ;
+__p += '\n <p>\n <label>' +
+__e(renkan.translate("Choose Image File:")) +
+'</label>\n <input class="Rk-Edit-Image-File" type="file" accept="image/*" />\n </p>\n';
+ };
+
+ } ;
+__p += ' ';
+ if (options.show_node_editor_creator && node.has_creator) { ;
+__p += '\n <p>\n <span class="Rk-Editor-Label">' +
+__e(renkan.translate("Created by:")) +
+'</span>\n <span class="Rk-UserColor" style="background: ' +
+__e(node.created_by_color) +
+';"></span>\n ' +
+__e( shortenText(node.created_by_title, 25) ) +
+'\n </p>\n';
+ } ;
+__p += ' ';
+ if (options.change_shapes) { ;
+__p += '\n <p>\n <label>' +
+__e(renkan.translate("Shapes available")) +
+':</label>\n <select class="Rk-Edit-Shape">\n ';
+ _.each(shapes, function(shape) { ;
+__p += '\n <option class="Rk-Edit-Vocabulary-Property" value="' +
+__e( shape ) +
+'"';
+ if (node.shape === shape) { ;
+__p += ' selected';
+ } ;
+__p += '>\n ' +
+__e( renkan.translate(shape.charAt(0).toUpperCase() + shape.substring(1)) ) +
+'\n </option>\n ';
+ }); ;
+__p += '\n </select>\n </p>\n';
+ } ;
+__p += '\n';
+
+}
+return __p
+};
+
+this["renkanJST"]["templates/nodeeditor_readonly.html"] = function(obj) {
+obj || (obj = {});
+var __t, __p = '', __e = _.escape, __j = Array.prototype.join;
+function print() { __p += __j.call(arguments, '') }
+with (obj) {
+__p += '<h2>\n <span class="Rk-CloseX">×</span>\n ';
+ if (options.show_node_tooltip_color) { ;
+__p += '\n <span class="Rk-UserColor" style="background: ' +
+__e(node.color) +
+';"></span>\n ';
+ } ;
+__p += '\n <span class="Rk-Display-Title">\n ';
+ if (node.uri) { ;
+__p += '\n <a href="' +
+__e(node.uri) +
+'" target="_blank">\n ';
+ } ;
+__p += '\n ' +
+__e(node.title) +
+'\n ';
+ if (node.uri) { ;
+__p += '</a>';
+ } ;
+__p += '\n </span>\n</h2>\n';
+ if (node.uri && options.show_node_tooltip_uri) { ;
+__p += '\n <p class="Rk-Display-URI">\n <a href="' +
+__e(node.uri) +
+'" target="_blank">' +
+__e(node.short_uri) +
+'</a>\n </p>\n';
+ } ;
+__p += ' ';
+ if (options.show_node_tooltip_description) { ;
+__p += '\n <p class="Rk-Display-Description">' +
+((__t = (node.description)) == null ? '' : __t) +
+'</p>\n';
+ } ;
+__p += ' ';
+ if (node.image && options.show_node_tooltip_image) { ;
+__p += '\n <img class="Rk-Display-ImgPreview" src="' +
+__e(node.image) +
+'" />\n';
+ } ;
+__p += ' ';
+ if (node.has_creator && options.show_node_tooltip_creator) { ;
+__p += '\n <p>\n <span class="Rk-Editor-Label">' +
+__e(renkan.translate("Created by:")) +
+'</span>\n <span class="Rk-UserColor" style="background: ' +
+__e(node.created_by_color) +
+';"></span>\n ' +
+__e( shortenText(node.created_by_title, 25) ) +
+'\n </p>\n';
+ } ;
+__p += '\n <a href="#?idNode=' +
+__e(node._id) +
+'">' +
+__e(renkan.translate("Link to the node")) +
+'</a>\n';
+
+}
+return __p
+};
+
+this["renkanJST"]["templates/nodeeditor_video.html"] = function(obj) {
+obj || (obj = {});
+var __t, __p = '', __e = _.escape, __j = Array.prototype.join;
+function print() { __p += __j.call(arguments, '') }
+with (obj) {
+__p += '<h2>\n <span class="Rk-CloseX">×</span>\n ';
+ if (options.show_node_tooltip_color) { ;
+__p += '\n <span class="Rk-UserColor" style="background: ' +
+__e(node.color) +
+';"></span>\n ';
+ } ;
+__p += '\n <span class="Rk-Display-Title">\n ';
+ if (node.uri) { ;
+__p += '\n <a href="' +
+__e(node.uri) +
+'" target="_blank">\n ';
+ } ;
+__p += '\n ' +
+__e(node.title) +
+'\n ';
+ if (node.uri) { ;
+__p += '</a>';
+ } ;
+__p += '\n </span>\n</h2>\n';
+ if (node.uri && options.show_node_tooltip_uri) { ;
+__p += '\n <video width="320" height="240" controls>\n <source src="' +
+__e(node.uri) +
+'" type="video/mp4">\n </video> \n';
+ } ;
+__p += '\n <a href="#?idnode=' +
+__e(node._id) +
+'">' +
+__e(renkan.translate("Link to the node")) +
+'</a>\n';
+
+}
+return __p
+};
+
+this["renkanJST"]["templates/scene.html"] = function(obj) {
+obj || (obj = {});
+var __t, __p = '', __e = _.escape, __j = Array.prototype.join;
+function print() { __p += __j.call(arguments, '') }
+with (obj) {
+
+ if (options.show_top_bar) { ;
+__p += '\n <div class="Rk-TopBar">\n <div class="loader"></div>\n ';
+ if (!options.editor_mode) { ;
+__p += '\n <h2 class="Rk-PadTitle">\n ' +
+__e( project.get("title") || translate("Untitled project")) +
+'\n </h2>\n ';
+ } else { ;
+__p += '\n <input type="text" class="Rk-PadTitle" value="' +
+__e( project.get('title') || '' ) +
+'" placeholder="' +
+__e(translate('Untitled project')) +
+'" />\n ';
+ } ;
+__p += '\n ';
+ if (options.show_user_list) { ;
+__p += '\n <div class="Rk-Users">\n <div class="Rk-CurrentUser">\n ';
+ if (options.show_user_color) { ;
+__p += '\n <div class="Rk-Edit-ColorPicker-Wrapper">\n <span class="Rk-CurrentUser-Color">\n ';
+ if (options.user_color_editable) { ;
+__p += '\n <span class="Rk-Edit-ColorTip"></span>\n ';
+ } ;
+__p += '\n </span>\n ';
+ if (options.user_color_editable) { print(colorPicker) } ;
+__p += '\n </div>\n ';
+ } ;
+__p += '\n <span class="Rk-CurrentUser-Name"><unknown user></span>\n </div>\n <ul class="Rk-UserList"></ul>\n </div>\n ';
+ } ;
+__p += '\n ';
+ if (options.home_button_url) {;
+__p += '\n <div class="Rk-TopBar-Separator"></div>\n <a class="Rk-TopBar-Button Rk-Home-Button" href="' +
+__e( options.home_button_url ) +
+'">\n <div class="Rk-TopBar-Tooltip">\n <div class="Rk-TopBar-Tooltip-Contents">\n ' +
+__e( translate(options.home_button_title) ) +
+'\n </div>\n </div>\n </a>\n ';
+ } ;
+__p += '\n ';
+ if (options.show_fullscreen_button) { ;
+__p += '\n <div class="Rk-TopBar-Separator"></div>\n <div class="Rk-TopBar-Button Rk-FullScreen-Button">\n <div class="Rk-TopBar-Tooltip">\n <div class="Rk-TopBar-Tooltip-Contents">\n ' +
+__e(translate("Full Screen")) +
+'\n </div>\n </div>\n </div>\n ';
+ } ;
+__p += '\n ';
+ if (options.editor_mode) { ;
+__p += '\n ';
+ if (options.show_addnode_button) { ;
+__p += '\n <div class="Rk-TopBar-Separator"></div>\n <div class="Rk-TopBar-Button Rk-AddNode-Button">\n <div class="Rk-TopBar-Tooltip">\n <div class="Rk-TopBar-Tooltip-Contents">\n ' +
+__e(translate("Add Node")) +
+'\n </div>\n </div>\n </div>\n ';
+ } ;
+__p += '\n ';
+ if (options.show_addedge_button) { ;
+__p += '\n <div class="Rk-TopBar-Separator"></div>\n <div class="Rk-TopBar-Button Rk-AddEdge-Button">\n <div class="Rk-TopBar-Tooltip">\n <div class="Rk-TopBar-Tooltip-Contents">\n ' +
+__e(translate("Add Edge")) +
+'\n </div>\n </div>\n </div>\n ';
+ } ;
+__p += '\n ';
+ if (options.show_export_button) { ;
+__p += '\n <div class="Rk-TopBar-Separator"></div>\n <div class="Rk-TopBar-Button Rk-Export-Button">\n <div class="Rk-TopBar-Tooltip">\n <div class="Rk-TopBar-Tooltip-Contents">\n ' +
+__e(translate("Download Project")) +
+'\n </div>\n </div>\n </div>\n ';
+ } ;
+__p += '\n ';
+ if (options.show_save_button) { ;
+__p += '\n <div class="Rk-TopBar-Separator"></div>\n <div class="Rk-TopBar-Button Rk-Save-Button">\n <div class="Rk-TopBar-Tooltip">\n <div class="Rk-TopBar-Tooltip-Contents"></div>\n </div>\n </div>\n ';
+ } ;
+__p += '\n ';
+ if (options.show_open_button) { ;
+__p += '\n <div class="Rk-TopBar-Separator"></div>\n <div class="Rk-TopBar-Button Rk-Open-Button">\n <div class="Rk-TopBar-Tooltip">\n <div class="Rk-TopBar-Tooltip-Contents">\n ' +
+__e(translate("Open Project")) +
+'\n </div>\n </div>\n </div>\n ';
+ } ;
+__p += '\n ';
+ if (options.show_bookmarklet) { ;
+__p += '\n <div class="Rk-TopBar-Separator"></div>\n <a class="Rk-TopBar-Button Rk-Bookmarklet-Button" href="#">\n <div class="Rk-TopBar-Tooltip">\n <div class="Rk-TopBar-Tooltip-Contents">\n ' +
+__e(translate("Renkan \'Drag-to-Add\' bookmarklet")) +
+'\n </div>\n </div>\n </a>\n <div class="Rk-TopBar-Separator"></div>\n ';
+ } ;
+__p += '\n ';
+ } else { ;
+__p += '\n ';
+ if (options.show_export_button) { ;
+__p += '\n <div class="Rk-TopBar-Separator"></div>\n <div class="Rk-TopBar-Button Rk-Export-Button">\n <div class="Rk-TopBar-Tooltip">\n <div class="Rk-TopBar-Tooltip-Contents">\n ' +
+__e(translate("Download Project")) +
+'\n </div>\n </div>\n </div>\n <div class="Rk-TopBar-Separator"></div>\n ';
+ } ;
+__p += '\n ';
+ }; ;
+__p += '\n ';
+ if (options.show_search_field) { ;
+__p += '\n <form action="#" class="Rk-GraphSearch-Form">\n <input type="search" class="Rk-GraphSearch-Field" placeholder="' +
+__e( translate('Search in graph') ) +
+'" />\n </form>\n <div class="Rk-TopBar-Separator"></div>\n ';
+ } ;
+__p += '\n </div>\n';
+ } ;
+__p += '\n<div class="Rk-Editing-Space';
+ if (!options.show_top_bar) { ;
+__p += ' Rk-Editing-Space-Full';
+ } ;
+__p += '">\n <div class="Rk-Labels"></div>\n <canvas class="Rk-Canvas" ';
+ if (options.resize) { ;
+__p += ' resize="" ';
+ } ;
+__p += ' ></canvas>\n <div class="Rk-Notifications"></div>\n <div class="Rk-Editor">\n ';
+ if (options.show_bins) { ;
+__p += '\n <div class="Rk-Fold-Bins">«</div>\n ';
+ } ;
+__p += '\n ';
+ if (options.show_zoom) { ;
+__p += '\n <div class="Rk-ZoomButtons">\n <div class="Rk-ZoomIn" title="' +
+__e(translate('Zoom In')) +
+'"></div>\n <div class="Rk-ZoomFit" title="' +
+__e(translate('Zoom Fit')) +
+'"></div>\n <div class="Rk-ZoomOut" title="' +
+__e(translate('Zoom Out')) +
+'"></div>\n ';
+ if (options.editor_mode && options.save_view) { ;
+__p += '\n <div class="Rk-ZoomSave" title="' +
+__e(translate('Save view')) +
+'"></div>\n ';
+ } ;
+__p += '\n ';
+ if (options.save_view) { ;
+__p += '\n <div class="Rk-ZoomSetSaved" title="' +
+__e(translate('View saved view')) +
+'"></div>\n ';
+ if (options.hide_nodes) { ;
+__p += '\n \t <div class="Rk-ShowHiddenNodes" title="' +
+__e(translate('Show hidden nodes')) +
+'"></div>\n ';
+ } ;
+__p += ' \n ';
+ } ;
+__p += '\n </div>\n ';
+ } ;
+__p += '\n </div>\n</div>\n';
+
+}
+return __p
+};
+
+this["renkanJST"]["templates/search.html"] = function(obj) {
+obj || (obj = {});
+var __t, __p = '', __e = _.escape;
+with (obj) {
+__p += '<li class="' +
+((__t = ( className )) == null ? '' : __t) +
+'" data-key="' +
+((__t = ( key )) == null ? '' : __t) +
+'">' +
+((__t = ( title )) == null ? '' : __t) +
+'</li>';
+
+}
+return __p
+};
+
+this["renkanJST"]["templates/wikipedia-bin/resulttemplate.html"] = function(obj) {
+obj || (obj = {});
+var __t, __p = '', __e = _.escape;
+with (obj) {
+__p += '<li class="Rk-Wikipedia-Result Rk-Bin-Item" draggable="true"\n data-uri="' +
+__e(url) +
+'" data-title="Wikipedia: ' +
+__e(title) +
+'"\n data-description="' +
+__e(description) +
+'"\n data-image="' +
+__e( Rkns.Utils.getFullURL( static_url + 'img/wikipedia.png' ) ) +
+'">\n\n <img class="Rk-Wikipedia-Icon" src="' +
+__e(static_url) +
+'img/wikipedia.png">\n <h4 class="Rk-Wikipedia-Title">\n <a href="' +
+__e(url) +
+'" target="_blank">' +
+((__t = (htitle)) == null ? '' : __t) +
+'</a>\n </h4>\n <p class="Rk-Wikipedia-Snippet">' +
+((__t = (hdescription)) == null ? '' : __t) +
+'</p>\n</li>\n';
+
+}
+return __p
+};
+/* Declaring the Renkan Namespace Rkns and Default values */
+
+(function(root) {
+
+ "use strict";
+
+ if (typeof root.Rkns !== "object") {
+ root.Rkns = {};
+ }
+
+ var Rkns = root.Rkns;
+ var $ = Rkns.$ = root.jQuery;
+ var _ = Rkns._ = root._;
+
+ Rkns.pickerColors = ["#8f1919", "#a80000", "#d82626", "#ff0000", "#e87c7c", "#ff6565", "#f7d3d3", "#fecccc",
+ "#8f5419", "#a85400", "#d87f26", "#ff7f00", "#e8b27c", "#ffb265", "#f7e5d3", "#fee5cc",
+ "#8f8f19", "#a8a800", "#d8d826", "#feff00", "#e8e87c", "#feff65", "#f7f7d3", "#fefecc",
+ "#198f19", "#00a800", "#26d826", "#00ff00", "#7ce87c", "#65ff65", "#d3f7d3", "#ccfecc",
+ "#198f8f", "#00a8a8", "#26d8d8", "#00feff", "#7ce8e8", "#65feff", "#d3f7f7", "#ccfefe",
+ "#19198f", "#0000a8", "#2626d8", "#0000ff", "#7c7ce8", "#6565ff", "#d3d3f7", "#ccccfe",
+ "#8f198f", "#a800a8", "#d826d8", "#ff00fe", "#e87ce8", "#ff65fe", "#f7d3f7", "#feccfe",
+ "#000000", "#242424", "#484848", "#6d6d6d", "#919191", "#b6b6b6", "#dadada", "#ffffff"
+ ];
+
+ Rkns.__renkans = [];
+
+ var _BaseBin = Rkns._BaseBin = function(_renkan, _opts) {
+ if (typeof _renkan !== "undefined") {
+ this.renkan = _renkan;
+ this.renkan.$.find(".Rk-Bin-Main").hide();
+ this.$ = Rkns.$('<li>')
+ .addClass("Rk-Bin")
+ .appendTo(_renkan.$.find(".Rk-Bin-List"));
+ this.title_icon_$ = Rkns.$('<span>')
+ .addClass("Rk-Bin-Title-Icon")
+ .appendTo(this.$);
+
+ var _this = this;
+
+ Rkns.$('<a>')
+ .attr({
+ href: "#",
+ title: _renkan.translate("Close bin")
+ })
+ .addClass("Rk-Bin-Close")
+ .html('×')
+ .appendTo(this.$)
+ .click(function() {
+ _this.destroy();
+ if (!_renkan.$.find(".Rk-Bin-Main:visible").length) {
+ _renkan.$.find(".Rk-Bin-Main:last").slideDown();
+ }
+ _renkan.resizeBins();
+ return false;
+ });
+ Rkns.$('<a>')
+ .attr({
+ href: "#",
+ title: _renkan.translate("Refresh bin")
+ })
+ .addClass("Rk-Bin-Refresh")
+ .appendTo(this.$)
+ .click(function() {
+ _this.refresh();
+ return false;
+ });
+ this.count_$ = Rkns.$('<div>')
+ .addClass("Rk-Bin-Count")
+ .appendTo(this.$);
+ this.title_$ = Rkns.$('<h2>')
+ .addClass("Rk-Bin-Title")
+ .appendTo(this.$);
+ this.main_$ = Rkns.$('<div>')
+ .addClass("Rk-Bin-Main")
+ .appendTo(this.$)
+ .html('<h4 class="Rk-Bin-Loading">' + _renkan.translate("Loading, please wait") + '</h4>');
+ this.title_$.html(_opts.title || '(new bin)');
+ this.renkan.resizeBins();
+
+ if (_opts.auto_refresh) {
+ window.setInterval(function() {
+ _this.refresh();
+ }, _opts.auto_refresh);
+ }
+ }
+ };
+
+ _BaseBin.prototype.destroy = function() {
+ this.$.detach();
+ this.renkan.resizeBins();
+ };
+
+ /* Point of entry */
+
+ var Renkan = Rkns.Renkan = function(_opts) {
+ var _this = this;
+
+ Rkns.__renkans.push(this);
+
+ this.options = _.defaults(_opts, Rkns.defaults, {
+ templates: _.defaults(_opts.templates, renkanJST) || renkanJST,
+ node_editor_templates: _.defaults(_opts.node_editor_templates, Rkns.defaults.node_editor_templates)
+ });
+ this.template = renkanJST['templates/main.html'];
+
+ var types_templates = {};
+ _.each(this.options.node_editor_templates, function(value, key) {
+ types_templates[key] = _this.options.templates[value];
+ delete _this.options.templates[value];
+ });
+ this.options.node_editor_templates = types_templates;
+
+ _.each(this.options.property_files, function(f) {
+ Rkns.$.getJSON(f, function(data) {
+ _this.options.properties = _this.options.properties.concat(data);
+ });
+ });
+
+ this.read_only = this.options.read_only || !this.options.editor_mode;
+
+ this.router = new Rkns.Router();
+
+ this.project = new Rkns.Models.Project();
+ this.dataloader = new Rkns.DataLoader.Loader(this.project, this.options);
+
+ this.setCurrentUser = function(user_id, user_name) {
+ this.project.addUser({
+ _id: user_id,
+ title: user_name
+ });
+ this.current_user = user_id;
+ this.renderer.redrawUsers();
+ };
+
+ if (typeof this.options.user_id !== "undefined") {
+ this.current_user = this.options.user_id;
+ }
+ this.$ = Rkns.$("#" + this.options.container);
+ this.$
+ .addClass("Rk-Main")
+ .html(this.template(this));
+
+ this.tabs = [];
+ this.search_engines = [];
+
+ this.current_user_list = new Rkns.Models.UsersList();
+
+ this.current_user_list.on("add remove", function() {
+ if (this.renderer) {
+ this.renderer.redrawUsers();
+ }
+ });
+
+ this.colorPicker = (function() {
+ var _tmpl = renkanJST['templates/colorpicker.html'];
+ return '<ul class="Rk-Edit-ColorPicker">' + Rkns.pickerColors.map(function(c) {
+ return _tmpl({
+ c: c
+ });
+ }).join("") + '</ul>';
+ })();
+
+ if (this.options.show_editor) {
+ this.renderer = new Rkns.Renderer.Scene(this);
+ }
+
+ if (!this.options.search.length) {
+ this.$.find(".Rk-Web-Search-Form").detach();
+ } else {
+ var _tmpl = renkanJST['templates/search.html'],
+ _select = this.$.find(".Rk-Search-List"),
+ _input = this.$.find(".Rk-Web-Search-Input"),
+ _form = this.$.find(".Rk-Web-Search-Form");
+ _.each(this.options.search, function(_search, _key) {
+ if (Rkns[_search.type] && Rkns[_search.type].Search) {
+ _this.search_engines.push(new Rkns[_search.type].Search(_this, _search));
+ }
+ });
+ _select.html(
+ _(this.search_engines).map(function(_search, _key) {
+ return _tmpl({
+ key: _key,
+ title: _search.getSearchTitle(),
+ className: _search.getBgClass()
+ });
+ }).join("")
+ );
+ _select.find("li").click(function() {
+ var _el = Rkns.$(this);
+ _this.setSearchEngine(_el.attr("data-key"));
+ _form.submit();
+ });
+ _form.submit(function() {
+ if (_input.val()) {
+ var _search = _this.search_engine;
+ _search.search(_input.val());
+ }
+ return false;
+ });
+ this.$.find(".Rk-Search-Current").mouseenter(
+ function() {
+ _select.slideDown();
+ }
+ );
+ this.$.find(".Rk-Search-Select").mouseleave(
+ function() {
+ _select.hide();
+ }
+ );
+ this.setSearchEngine(0);
+ }
+ _.each(this.options.bins, function(_bin) {
+ if (Rkns[_bin.type] && Rkns[_bin.type].Bin) {
+ _this.tabs.push(new Rkns[_bin.type].Bin(_this, _bin));
+ }
+ });
+
+ var elementDropped = false;
+
+ this.$.find(".Rk-Bins")
+ .on("click", ".Rk-Bin-Title,.Rk-Bin-Title-Icon", function() {
+ var _mainDiv = Rkns.$(this).siblings(".Rk-Bin-Main");
+ if (_mainDiv.is(":hidden")) {
+ _this.$.find(".Rk-Bin-Main").slideUp();
+ _mainDiv.slideDown();
+ }
+ });
+
+ if (this.options.show_editor) {
+
+ this.$.find(".Rk-Bins").on("mouseover", ".Rk-Bin-Item", function(_e) {
+ var _t = Rkns.$(this);
+ if (_t && $(_t).attr("data-uri")) {
+ var _models = _this.project.get("nodes").where({
+ uri: $(_t).attr("data-uri")
+ });
+ _.each(_models, function(_model) {
+ _this.renderer.highlightModel(_model);
+ });
+ }
+ }).mouseout(function() {
+ _this.renderer.unhighlightAll();
+ }).on("mousemove", ".Rk-Bin-Item", function(e) {
+ try {
+ this.dragDrop();
+ } catch (err) {}
+ }).on("touchstart", ".Rk-Bin-Item", function(e) {
+ elementDropped = false;
+ }).on("touchmove", ".Rk-Bin-Item", function(e) {
+ e.preventDefault();
+ var touch = e.originalEvent.changedTouches[0],
+ off = _this.renderer.canvas_$.offset(),
+ w = _this.renderer.canvas_$.width(),
+ h = _this.renderer.canvas_$.height();
+ if (touch.pageX >= off.left && touch.pageX < (off.left + w) && touch.pageY >= off.top && touch.pageY < (off.top + h)) {
+ if (elementDropped) {
+ _this.renderer.onMouseMove(touch, true);
+ } else {
+ elementDropped = true;
+ var div = document.createElement('div');
+ div.appendChild(this.cloneNode(true));
+ _this.renderer.dropData({
+ "text/html": div.innerHTML
+ }, touch);
+ _this.renderer.onMouseDown(touch, true);
+ }
+ }
+ }).on("touchend", ".Rk-Bin-Item", function(e) {
+ if (elementDropped) {
+ _this.renderer.onMouseUp(e.originalEvent.changedTouches[0], true);
+ }
+ elementDropped = false;
+ }).on("dragstart", ".Rk-Bin-Item", function(e) {
+ var div = document.createElement('div');
+ div.appendChild(this.cloneNode(true));
+ try {
+ e.originalEvent.dataTransfer.setData("text/html", div.innerHTML);
+ } catch (err) {
+ e.originalEvent.dataTransfer.setData("text", div.innerHTML);
+ }
+ });
+
+ }
+
+ Rkns.$(window).resize(function() {
+ _this.resizeBins();
+ });
+
+ var lastsearch = false,
+ lastval = '';
+
+ this.$.find(".Rk-Bins-Search-Input").on("change keyup paste input", function() {
+ var val = Rkns.$(this).val();
+ if (val === lastval) {
+ return;
+ }
+ var search = Rkns.Utils.regexpFromTextOrArray(val.length > 1 ? val : null);
+ if (search.source === lastsearch) {
+ return;
+ }
+ lastsearch = search.source;
+ _.each(_this.tabs, function(tab) {
+ tab.render(search);
+ });
+
+ });
+ this.$.find(".Rk-Bins-Search-Form").submit(function() {
+ return false;
+ });
+ };
+
+ Renkan.prototype.translate = function(_text) {
+ if (Rkns.i18n[this.options.language] && Rkns.i18n[this.options.language][_text]) {
+ return Rkns.i18n[this.options.language][_text];
+ }
+ if (this.options.language.length > 2 && Rkns.i18n[this.options.language.substr(0, 2)] && Rkns.i18n[this.options.language.substr(0, 2)][_text]) {
+ return Rkns.i18n[this.options.language.substr(0, 2)][_text];
+ }
+ return _text;
+ };
+
+ Renkan.prototype.onStatusChange = function() {
+ this.renderer.onStatusChange();
+ };
+
+ Renkan.prototype.setSearchEngine = function(_key) {
+ this.search_engine = this.search_engines[_key];
+ this.$.find(".Rk-Search-Current").attr("class", "Rk-Search-Current " + this.search_engine.getBgClass());
+ var listClasses = this.search_engine.getBgClass().split(" ");
+ var classes = "";
+ for (var i = 0; i < listClasses.length; i++) {
+ classes += "." + listClasses[i];
+ }
+ this.$.find(".Rk-Web-Search-Input.Rk-Search-Input").attr("placeholder", this.translate("Search in ") + this.$.find(".Rk-Search-List " + classes).html());
+ };
+
+ Renkan.prototype.resizeBins = function() {
+ var _d = +this.$.find(".Rk-Bins-Head").outerHeight();
+ this.$.find(".Rk-Bin-Title:visible").each(function() {
+ _d += Rkns.$(this).outerHeight();
+ });
+ this.$.find(".Rk-Bin-Main").css({
+ height: this.$.find(".Rk-Bins").height() - _d
+ });
+ };
+
+ /* Utility functions */
+ var getUUID4 = function() {
+ return 'xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx'.replace(/[xy]/g, function(c) {
+ var r = Math.random() * 16 | 0,
+ v = c === 'x' ? r : (r & 0x3 | 0x8);
+ return v.toString(16);
+ });
+ };
+
+ Rkns.Utils = {
+ getUUID4: getUUID4,
+ getUID: (function() {
+ function pad(n) {
+ return n < 10 ? '0' + n : n;
+ }
+ var _d = new Date(),
+ ID_AUTO_INCREMENT = 0,
+ ID_BASE = _d.getUTCFullYear() + '-' +
+ pad(_d.getUTCMonth() + 1) + '-' +
+ pad(_d.getUTCDate()) + '-' +
+ getUUID4();
+ return function(_base) {
+ var _n = (++ID_AUTO_INCREMENT).toString(16),
+ _uidbase = (typeof _base === "undefined" ? "" : _base + "-");
+ while (_n.length < 4) {
+ _n = '0' + _n;
+ }
+ return _uidbase + ID_BASE + '-' + _n;
+ };
+ })(),
+ getFullURL: function(url) {
+
+ if (typeof(url) === 'undefined' || url == null) {
+ return "";
+ }
+ if (/https?:\/\//.test(url)) {
+ return url;
+ }
+ var img = new Image();
+ img.src = url;
+ var res = img.src;
+ img.src = null;
+ return res;
+
+ },
+ inherit: function(_baseClass, _callbefore) {
+
+ var _class = function(_arg) {
+ if (typeof _callbefore === "function") {
+ _callbefore.apply(this, Array.prototype.slice.call(arguments, 0));
+ }
+ _baseClass.apply(this, Array.prototype.slice.call(arguments, 0));
+ if (typeof this._init === "function" && !this._initialized) {
+ this._init.apply(this, Array.prototype.slice.call(arguments, 0));
+ this._initialized = true;
+ }
+ };
+ _.extend(_class.prototype, _baseClass.prototype);
+
+ return _class;
+
+ },
+ regexpFromTextOrArray: (function() {
+ var charsub = [
+ '[aáàâä]',
+ '[cç]',
+ '[eéèêë]',
+ '[iíìîï]',
+ '[oóòôö]',
+ '[uùûü]'
+ ],
+ removeChars = [
+ String.fromCharCode(768), String.fromCharCode(769), String.fromCharCode(770), String.fromCharCode(771), String.fromCharCode(807),
+ "{", "}", "(", ")", "[", "]", "【", "】", "、", "・", "‥", "。", "「", "」", "『", "』", "〜", ":", "!", "?", " ",
+ ",", " ", ";", "(", ")", ".", "*", "+", "\\", "?", "|", "{", "}", "[", "]", "^", "#", "/"
+ ],
+ remsrc = "[\\" + removeChars.join("\\") + "]",
+ remrx = new RegExp(remsrc, "gm"),
+ charsrx = _.map(charsub, function(c) {
+ return new RegExp(c);
+ });
+
+ function replaceText(_text) {
+ var txt = _text.toLowerCase().replace(remrx, ""),
+ src = "";
+
+ function makeReplaceFunc(l) {
+ return function(k, v) {
+ l = l.replace(charsrx[k], v);
+ };
+ }
+ for (var j = 0; j < txt.length; j++) {
+ if (j) {
+ src += remsrc + "*";
+ }
+ var l = txt[j];
+ _.each(charsub, makeReplaceFunc(l));
+ src += l;
+ }
+ return src;
+ }
+
+ function getSource(inp) {
+ switch (typeof inp) {
+ case "string":
+ return replaceText(inp);
+ case "object":
+ var src = '';
+ _.each(inp, function(v) {
+ var res = getSource(v);
+ if (res) {
+ if (src) {
+ src += '|';
+ }
+ src += res;
+ }
+ });
+ return src;
+ }
+ return '';
+ }
+
+ return function(_textOrArray) {
+ var source = getSource(_textOrArray);
+ if (source) {
+ var testrx = new RegExp(source, "im"),
+ replacerx = new RegExp('(' + source + ')', "igm");
+ return {
+ isempty: false,
+ source: source,
+ test: function(_t) {
+ return testrx.test(_t);
+ },
+ replace: function(_text, _replace) {
+ return _text.replace(replacerx, _replace);
+ }
+ };
+ } else {
+ return {
+ isempty: true,
+ source: '',
+ test: function() {
+ return true;
+ },
+ replace: function(_text) {
+ return text;
+ }
+ };
+ }
+ };
+ })(),
+ /* The minimum distance (in pixels) the mouse has to move to consider an element was dragged */
+ _MIN_DRAG_DISTANCE: 2,
+ /* Distance between the inner and outer radius of buttons that appear when hovering on a node */
+ _NODE_BUTTON_WIDTH: 40,
+
+ _EDGE_BUTTON_INNER: 2,
+ _EDGE_BUTTON_OUTER: 40,
+ /* Constants used to know if a specific action is to be performed when clicking on the canvas */
+ _CLICKMODE_ADDNODE: 1,
+ _CLICKMODE_STARTEDGE: 2,
+ _CLICKMODE_ENDEDGE: 3,
+ /* Node size step: Used to calculate the size change when clicking the +/- buttons */
+ _NODE_SIZE_STEP: Math.LN2 / 4,
+ _MIN_SCALE: 1 / 20,
+ _MAX_SCALE: 20,
+ _MOUSEMOVE_RATE: 80,
+ _DOUBLETAP_DELAY: 800,
+ /* Maximum distance in pixels (squared, to reduce calculations)
+ * between two taps when double-tapping on a touch terminal */
+ _DOUBLETAP_DISTANCE: 20 * 20,
+ /* A placeholder so a default colour is displayed when a node has a null value for its user property */
+ _USER_PLACEHOLDER: function(_renkan) {
+ return {
+ color: _renkan.options.default_user_color,
+ title: _renkan.translate("(unknown user)"),
+ get: function(attr) {
+ return this[attr] || false;
+ }
+ };
+ },
+ /* The code for the "Drag and Add Bookmarklet", slightly minified and with whitespaces removed, though
+ * it doesn't seem that it's still a requirement in newer browsers (i.e. the ones compatibles with canvas drawing)
+ */
+ _BOOKMARKLET_CODE: function(_renkan) {
+ 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;\">" +
+ _renkan.translate("Drag items from this website, drop them in Renkan").replace(/ /g, "_") +
+ "</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);})();";
+ },
+ /* Shortens text to the required length then adds ellipsis */
+ shortenText: function(_text, _maxlength) {
+ return (_text.length > _maxlength ? (_text.substr(0, _maxlength) + '…') : _text);
+ },
+ /* Drawing an edit box with an arrow and positioning the edit box according to the position of the node/edge being edited
+ * Called by Rkns.Renderer.NodeEditor and Rkns.Renderer.EdgeEditor */
+ drawEditBox: function(_options, _coords, _path, _xmargin, _selector) {
+ _selector.css({
+ width: (_options.tooltip_width - 2 * _options.tooltip_padding)
+ });
+ var _height = _selector.outerHeight() + 2 * _options.tooltip_padding,
+ _isLeft = (_coords.x < paper.view.center.x ? 1 : -1),
+ _left = _coords.x + _isLeft * (_xmargin + _options.tooltip_arrow_length),
+ _right = _coords.x + _isLeft * (_xmargin + _options.tooltip_arrow_length + _options.tooltip_width),
+ _top = _coords.y - _height / 2;
+ if (_top + _height > (paper.view.size.height - _options.tooltip_margin)) {
+ _top = Math.max(paper.view.size.height - _options.tooltip_margin, _coords.y + _options.tooltip_arrow_width / 2) - _height;
+ }
+ if (_top < _options.tooltip_margin) {
+ _top = Math.min(_options.tooltip_margin, _coords.y - _options.tooltip_arrow_width / 2);
+ }
+ var _bottom = _top + _height;
+ /* jshint laxbreak:true */
+ _path.segments[0].point = _path.segments[7].point = _coords.add([_isLeft * _xmargin, 0]);
+ _path.segments[1].point.x = _path.segments[2].point.x = _path.segments[5].point.x = _path.segments[6].point.x = _left;
+ _path.segments[3].point.x = _path.segments[4].point.x = _right;
+ _path.segments[2].point.y = _path.segments[3].point.y = _top;
+ _path.segments[4].point.y = _path.segments[5].point.y = _bottom;
+ _path.segments[1].point.y = _coords.y - _options.tooltip_arrow_width / 2;
+ _path.segments[6].point.y = _coords.y + _options.tooltip_arrow_width / 2;
+ _path.fillColor = new paper.Color(new paper.Gradient([_options.tooltip_top_color, _options.tooltip_bottom_color]), [0, _top], [0, _bottom]);
+ _selector.css({
+ left: (_options.tooltip_padding + Math.min(_left, _right)),
+ top: (_options.tooltip_padding + _top)
+ });
+ return _path;
+ },
+ // from http://stackoverflow.com/a/6444043
+ increaseBrightness: function (hex, percent){
+ // strip the leading # if it's there
+ hex = hex.replace(/^\s*#|\s*$/g, '');
+
+ // convert 3 char codes --> 6, e.g. `E0F` --> `EE00FF`
+ if(hex.length === 3){
+ hex = hex.replace(/(.)/g, '$1$1');
+ }
+
+ var r = parseInt(hex.substr(0, 2), 16),
+ g = parseInt(hex.substr(2, 2), 16),
+ b = parseInt(hex.substr(4, 2), 16);
+
+ return '#' +
+ ((0|(1<<8) + r + (256 - r) * percent / 100).toString(16)).substr(1) +
+ ((0|(1<<8) + g + (256 - g) * percent / 100).toString(16)).substr(1) +
+ ((0|(1<<8) + b + (256 - b) * percent / 100).toString(16)).substr(1);
+ }
+ };
+})(window);
+
+/* END main.js */
+
+(function(root) {
+ "use strict";
+
+ var Backbone = root.Backbone;
+
+ var Router = root.Rkns.Router = Backbone.Router.extend({
+ routes: {
+ '': 'index'
+ },
+
+ index: function (parameters) {
+
+ var result = {};
+ if (parameters !== null){
+ parameters.split("&").forEach(function(part) {
+ var item = part.split("=");
+ result[item[0]] = decodeURIComponent(item[1]);
+ });
+ }
+ this.trigger('router', result);
+ }
+ });
+
+})(window);
+(function(root) {
+
+ "use strict";
+
+ var DataLoader = root.Rkns.DataLoader = {
+ converters: {
+ from1to2: function(data) {
+
+ var i, len;
+ if(typeof data.nodes !== 'undefined') {
+ for(i=0, len=data.nodes.length; i<len; i++) {
+ var node = data.nodes[i];
+ if(node.color) {
+ node.style = {
+ color: node.color,
+ };
+ }
+ else {
+ node.style = {};
+ }
+ }
+ }
+ if(typeof data.edges !== 'undefined') {
+ for(i=0, len=data.edges.length; i<len; i++) {
+ var edge = data.edges[i];
+ if(edge.color) {
+ edge.style = {
+ color: edge.color,
+ };
+ }
+ else {
+ edge.style = {};
+ }
+ }
+ }
+
+ data.schema_version = "2";
+
+ return data;
+ },
+ }
+ };
+
+
+ DataLoader.Loader = function(project, options) {
+ this.project = project;
+ this.dataConverters = _.defaults(options.converters || {}, DataLoader.converters);
+ };
+
+
+ DataLoader.Loader.prototype.convert = function(data) {
+ var schemaVersionFrom = this.project.getSchemaVersion(data);
+ var schemaVersionTo = this.project.getSchemaVersion();
+
+ if (schemaVersionFrom !== schemaVersionTo) {
+ var converterName = "from" + schemaVersionFrom + "to" + schemaVersionTo;
+ if (typeof this.dataConverters[converterName] === 'function') {
+ data = this.dataConverters[converterName](data);
+ }
+ }
+ return data;
+ };
+
+ DataLoader.Loader.prototype.load = function(data) {
+ this.project.set(this.convert(data), {
+ validate: true
+ });
+ };
+
+})(window);
+
+(function(root) {
+ "use strict";
+
+ var Backbone = root.Backbone;
+
+ var Models = root.Rkns.Models = {};
+
+ Models.getUID = function(obj) {
+ var guid = 'xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx'.replace(/[xy]/g,
+ function(c) {
+ var r = Math.random() * 16 | 0, v = c === 'x' ? r
+ : (r & 0x3 | 0x8);
+ return v.toString(16);
+ });
+ if (typeof obj !== 'undefined') {
+ return obj.type + "-" + guid;
+ }
+ else {
+ return guid;
+ }
+ };
+
+ var RenkanModel = Backbone.RelationalModel.extend({
+ idAttribute : "_id",
+ constructor : function(options) {
+
+ if (typeof options !== "undefined") {
+ options._id = options._id || options.id || Models.getUID(this);
+ options.title = options.title || "";
+ options.description = options.description || "";
+ options.uri = options.uri || "";
+
+ if (typeof this.prepare === "function") {
+ options = this.prepare(options);
+ }
+ }
+ Backbone.RelationalModel.prototype.constructor.call(this, options);
+ },
+ validate : function() {
+ if (!this.type) {
+ return "object has no type";
+ }
+ },
+ addReference : function(_options, _propName, _list, _id, _default) {
+ var _element = _list.get(_id);
+ if (typeof _element === "undefined" &&
+ typeof _default !== "undefined") {
+ _options[_propName] = _default;
+ }
+ else {
+ _options[_propName] = _element;
+ }
+ }
+ });
+
+ // USER
+ var User = Models.User = RenkanModel.extend({
+ type : "user",
+ prepare : function(options) {
+ options.color = options.color || "#666666";
+ return options;
+ },
+ toJSON : function() {
+ return {
+ _id : this.get("_id"),
+ title : this.get("title"),
+ uri : this.get("uri"),
+ description : this.get("description"),
+ color : this.get("color")
+ };
+ }
+ });
+
+ // NODE
+ var Node = Models.Node = RenkanModel.extend({
+ type : "node",
+ relations : [ {
+ type : Backbone.HasOne,
+ key : "created_by",
+ relatedModel : User
+ } ],
+ prepare : function(options) {
+ var project = options.project;
+ this.addReference(options, "created_by", project.get("users"),
+ options.created_by, project.current_user);
+ options.description = options.description || "";
+ return options;
+ },
+ toJSON : function() {
+ return {
+ _id : this.get("_id"),
+ title : this.get("title"),
+ uri : this.get("uri"),
+ description : this.get("description"),
+ position : this.get("position"),
+ image : this.get("image"),
+ style : this.get("style"),
+ created_by : this.get("created_by") ? this.get("created_by")
+ .get("_id") : null,
+ size : this.get("size"),
+ clip_path : this.get("clip_path"),
+ shape : this.get("shape"),
+ type : this.get("type")
+ };
+ }
+ });
+
+ // EDGE
+ var Edge = Models.Edge = RenkanModel.extend({
+ type : "edge",
+ relations : [ {
+ type : Backbone.HasOne,
+ key : "created_by",
+ relatedModel : User
+ }, {
+ type : Backbone.HasOne,
+ key : "from",
+ relatedModel : Node
+ }, {
+ type : Backbone.HasOne,
+ key : "to",
+ relatedModel : Node
+ } ],
+ prepare : function(options) {
+ var project = options.project;
+ this.addReference(options, "created_by", project.get("users"),
+ options.created_by, project.current_user);
+ this.addReference(options, "from", project.get("nodes"),
+ options.from);
+ this.addReference(options, "to", project.get("nodes"), options.to);
+ return options;
+ },
+ toJSON : function() {
+ return {
+ _id : this.get("_id"),
+ title : this.get("title"),
+ uri : this.get("uri"),
+ description : this.get("description"),
+ from : this.get("from") ? this.get("from").get("_id") : null,
+ to : this.get("to") ? this.get("to").get("_id") : null,
+ style : this.get("style"),
+ created_by : this.get("created_by") ? this.get("created_by")
+ .get("_id") : null
+ };
+ }
+ });
+
+ // View
+ var View = Models.View = RenkanModel.extend({
+ type : "view",
+ relations : [ {
+ type : Backbone.HasOne,
+ key : "created_by",
+ relatedModel : User
+ } ],
+ prepare : function(options) {
+ var project = options.project;
+ this.addReference(options, "created_by", project.get("users"),
+ options.created_by, project.current_user);
+ options.description = options.description || "";
+ if (typeof options.offset !== "undefined") {
+ var offset = {};
+ if (Array.isArray(options.offset)) {
+ offset.x = options.offset[0];
+ offset.y = options.offset.length > 1 ? options.offset[1]
+ : options.offset[0];
+ }
+ else if (options.offset.x != null) {
+ offset.x = options.offset.x;
+ offset.y = options.offset.y;
+ }
+ options.offset = offset;
+ }
+ return options;
+ },
+ toJSON : function() {
+ return {
+ _id : this.get("_id"),
+ zoom_level : this.get("zoom_level"),
+ offset : this.get("offset"),
+ title : this.get("title"),
+ description : this.get("description"),
+ created_by : this.get("created_by") ? this.get("created_by")
+ .get("_id") : null,
+ hidden_nodes: this.get("hidden_nodes")
+ // Don't need project id
+ };
+ }
+ });
+
+ // PROJECT
+ var Project = Models.Project = RenkanModel.extend({
+ schema_version : "2",
+ type : "project",
+ blacklist : [ 'saveStatus', 'loadingStatus'],
+ relations : [ {
+ type : Backbone.HasMany,
+ key : "users",
+ relatedModel : User,
+ reverseRelation : {
+ key : 'project',
+ includeInJSON : '_id'
+ }
+ }, {
+ type : Backbone.HasMany,
+ key : "nodes",
+ relatedModel : Node,
+ reverseRelation : {
+ key : 'project',
+ includeInJSON : '_id'
+ }
+ }, {
+ type : Backbone.HasMany,
+ key : "edges",
+ relatedModel : Edge,
+ reverseRelation : {
+ key : 'project',
+ includeInJSON : '_id'
+ }
+ }, {
+ type : Backbone.HasMany,
+ key : "views",
+ relatedModel : View,
+ reverseRelation : {
+ key : 'project',
+ includeInJSON : '_id'
+ }
+ } ],
+ addUser : function(_props, _options) {
+ _props.project = this;
+ var _user = User.findOrCreate(_props);
+ this.get("users").push(_user, _options);
+ return _user;
+ },
+ addNode : function(_props, _options) {
+ _props.project = this;
+ var _node = Node.findOrCreate(_props);
+ this.get("nodes").push(_node, _options);
+ return _node;
+ },
+ addEdge : function(_props, _options) {
+ _props.project = this;
+ var _edge = Edge.findOrCreate(_props);
+ this.get("edges").push(_edge, _options);
+ return _edge;
+ },
+ addView : function(_props, _options) {
+ _props.project = this;
+ // TODO: check if need to replace with create only
+ var _view = View.findOrCreate(_props);
+ // TODO: Should we remember only one view?
+ this.get("views").push(_view, _options);
+ return _view;
+ },
+ removeNode : function(_model) {
+ this.get("nodes").remove(_model);
+ },
+ removeEdge : function(_model) {
+ this.get("edges").remove(_model);
+ },
+ validate : function(options) {
+ var _project = this;
+ _.each(
+ [].concat(options.users, options.nodes, options.edges,options.views),
+ function(_item) {
+ if (_item) {
+ _item.project = _project;
+ }
+ }
+ );
+ },
+ getSchemaVersion : function(data) {
+ var t = data;
+ if(typeof(t) === "undefined") {
+ t = this;
+ }
+ var version = t.schema_version;
+ if(!version) {
+ return 1;
+ }
+ else {
+ return version;
+ }
+ },
+ // Add event handler to remove edges when a node is removed
+ initialize : function() {
+ var _this = this;
+ this.on("remove:nodes", function(_node) {
+ _this.get("edges").remove(
+ _this.get("edges").filter(
+ function(_edge) {
+ return _edge.get("from") === _node ||
+ _edge.get("to") === _node;
+ }));
+ });
+ },
+ toJSON : function() {
+ var json = _.clone(this.attributes);
+ for ( var attr in json) {
+ if ((json[attr] instanceof Backbone.Model) ||
+ (json[attr] instanceof Backbone.Collection) ||
+ (json[attr] instanceof RenkanModel)) {
+ json[attr] = json[attr].toJSON();
+ }
+ }
+ return _.omit(json, this.blacklist);
+ }
+ });
+
+ var RosterUser = Models.RosterUser = Backbone.Model
+ .extend({
+ type : "roster_user",
+ idAttribute : "_id",
+
+ constructor : function(options) {
+
+ if (typeof options !== "undefined") {
+ options._id = options._id ||
+ options.id ||
+ Models.getUID(this);
+ options.title = options.title || "(untitled " + this.type + ")";
+ options.description = options.description || "";
+ options.uri = options.uri || "";
+ options.project = options.project || null;
+ options.site_id = options.site_id || 0;
+
+ if (typeof this.prepare === "function") {
+ options = this.prepare(options);
+ }
+ }
+ Backbone.Model.prototype.constructor.call(this, options);
+ },
+
+ validate : function() {
+ if (!this.type) {
+ return "object has no type";
+ }
+ },
+
+ prepare : function(options) {
+ options.color = options.color || "#666666";
+ return options;
+ },
+
+ toJSON : function() {
+ return {
+ _id : this.get("_id"),
+ title : this.get("title"),
+ uri : this.get("uri"),
+ description : this.get("description"),
+ color : this.get("color"),
+ project : (this.get("project") != null) ? this.get(
+ "project").get("id") : null,
+ site_id : this.get("site_id")
+ };
+ }
+ });
+
+ var UsersList = Models.UsersList = Backbone.Collection.extend({
+ model : RosterUser
+ });
+
+})(window);
+
+Rkns.defaults = {
+
+ language: (navigator.language || navigator.userLanguage || "en"),
+ /* GUI Language */
+ container: "renkan",
+ /* GUI Container DOM element ID */
+ search: [],
+ /* List of Search Engines */
+ bins: [],
+ /* List of Bins */
+ static_url: "",
+ /* URL for static resources */
+ popup_editor: true,
+ /* show the node editor as a popup inside the renkan view */
+ editor_panel: 'editor-panel',
+ /* GUI continer DOM element ID of the editor panel */
+ show_bins: true,
+ /* Show bins in left column */
+ properties: [],
+ /* Semantic properties for edges */
+ show_editor: true,
+ /* Show the graph editor... Setting this to "false" only shows the bins part ! */
+ read_only: false,
+ /* Allows editing of renkan without changing the rest of the GUI. Can be switched on/off on the fly to block/enable editing */
+ editor_mode: true,
+ /* Switch for Publish/Edit GUI. If editor_mode is false, read_only will be true. */
+ manual_save: false,
+ /* In snapshot mode, clicking on the floppy will save a snapshot. Otherwise, it will show the connection status */
+ show_top_bar: true,
+ /* Show the top bar, (title, buttons, users) */
+ default_user_color: "#303030",
+ size_bug_fix: false,
+ /* Resize the canvas after load (fixes a bug on iPad and FF Mac) */
+ force_resize: false,
+ allow_double_click: true,
+ /* Allows Double Click to create a node on an empty background */
+ zoom_on_scroll: true,
+ /* Allows to use the scrollwheel to zoom */
+ element_delete_delay: 0,
+ /* Delay between clicking on the bin on an element and really deleting it
+ Set to 0 for delete confirm */
+ autoscale_padding: 50,
+ resize: true,
+
+ /* zoom options */
+ show_zoom: true,
+ /* show zoom buttons */
+ save_view: true,
+ /* show buttons to save view */
+ default_view: false,
+ /* Allows to load default view (zoom+offset) at start on read_only mode, instead of autoScale. the default_view will be the last */
+ default_index_view: -1,
+
+ /* URL parsing */
+ update_url:true,
+ /* update the url each time the paper shift or on zoom in/out, with the serialized view (offset and scale) */
+
+
+ /* TOP BAR BUTTONS */
+ show_search_field: true,
+ show_user_list: true,
+ user_name_editable: true,
+ user_color_editable: true,
+ show_user_color: true,
+ show_save_button: true,
+ show_export_button: true,
+ show_open_button: false,
+ show_addnode_button: true,
+ show_addedge_button: true,
+ show_bookmarklet: true,
+ show_fullscreen_button: true,
+ home_button_url: false,
+ home_button_title: "Home",
+
+ /* MINI-MAP OPTIONS */
+
+ show_minimap: true,
+ /* Show a small map at the bottom right */
+ minimap_width: 160,
+ minimap_height: 120,
+ minimap_padding: 20,
+ minimap_background_color: "#ffffff",
+ minimap_border_color: "#cccccc",
+ minimap_highlight_color: "#ffff00",
+ minimap_highlight_weight: 5,
+
+
+ /* EDGE/NODE COMMON OPTIONS */
+
+ buttons_background: "#202020",
+ buttons_label_color: "#c000c0",
+ buttons_label_font_size: 9,
+
+ ghost_opacity : 0.3,
+ /* opacity when the hidden element is revealed */
+ default_dash_array : [4, 5],
+ /* dash line genometry */
+
+ /* NODE DISPLAY OPTIONS */
+
+ show_node_circles: true,
+ /* Show circles for nodes */
+ clip_node_images: true,
+ /* Constraint node images to circles */
+ node_images_fill_mode: false,
+ /* Set to false for "letterboxing" (height/width of node adapted to show full image)
+ Set to true for "crop" (adapted to fill circle) */
+ node_size_base: 25,
+ node_stroke_width: 2,
+ node_stroke_max_width: 12,
+ selected_node_stroke_width: 4,
+ selected_node_stroke_max_width: 24,
+ node_stroke_witdh_scale: 5,
+ node_fill_color: "#ffffff",
+ highlighted_node_fill_color: "#ffff00",
+ node_label_distance: 5,
+ /* Vertical distance between node and label */
+ node_label_max_length: 60,
+ /* Maximum displayed text length */
+ label_untitled_nodes: "(untitled)",
+ /* Label to display on untitled nodes */
+ hide_nodes: true,
+ /* allow hide/show nodes */
+ change_shapes: true,
+ /* Change shapes enabled */
+ change_types: true,
+ /* Change type enabled */
+
+ /* NODE EDITOR TEMPLATE*/
+
+ node_editor_templates: {
+ "default": "templates/nodeeditor_readonly.html",
+ "video": "templates/nodeeditor_video.html"
+ },
+
+ /* EDGE DISPLAY OPTIONS */
+
+ edge_stroke_width: 2,
+ edge_stroke_max_width: 12,
+ selected_edge_stroke_width: 4,
+ selected_edge_stroke_max_width: 24,
+ edge_stroke_witdh_scale: 5,
+
+ edge_label_distance: 0,
+ edge_label_max_length: 20,
+ edge_arrow_length: 18,
+ edge_arrow_width: 12,
+ edge_arrow_max_width: 32,
+ edge_gap_in_bundles: 12,
+ label_untitled_edges: "",
+
+ /* CONTEXTUAL DISPLAY (TOOLTIP OR EDITOR) OPTIONS */
+
+ tooltip_width: 275,
+ tooltip_padding: 10,
+ tooltip_margin: 15,
+ tooltip_arrow_length : 20,
+ tooltip_arrow_width : 40,
+ tooltip_top_color: "#f0f0f0",
+ tooltip_bottom_color: "#d0d0d0",
+ tooltip_border_color: "#808080",
+ tooltip_border_width: 1,
+ tooltip_opacity: 0.8,
+
+ richtext_editor_config: {
+ toolbarGroups: [
+ { name: 'basicstyles', groups: [ 'basicstyles', 'cleanup' ] },
+ { name: 'clipboard', groups: [ 'clipboard', 'undo' ] },
+ '/',
+ { name: 'styles'},
+ ],
+ removePlugins : 'colorbutton,find,flash,font,forms,iframe,image,newpage,smiley,specialchar,stylescombo,templates',
+ },
+
+ /* NODE EDITOR OPTIONS */
+
+ show_node_editor_uri: true,
+ show_node_editor_description: true,
+ show_node_editor_description_richtext: true,
+ show_node_editor_size: true,
+ show_node_editor_style: true,
+ show_node_editor_style_color: true,
+ show_node_editor_style_dash: true,
+ show_node_editor_style_thickness: true,
+ show_node_editor_image: true,
+ show_node_editor_creator: true,
+ allow_image_upload: true,
+ uploaded_image_max_kb: 500,
+
+
+ /* NODE TOOLTIP OPTIONS */
+
+ show_node_tooltip_uri: true,
+ show_node_tooltip_description: true,
+ show_node_tooltip_color: true,
+ show_node_tooltip_image: true,
+ show_node_tooltip_creator: true,
+
+ /* EDGE EDITOR OPTIONS */
+
+ show_edge_editor_uri: true,
+ show_edge_editor_style: true,
+ show_edge_editor_style_color: true,
+ show_edge_editor_style_dash: true,
+ show_edge_editor_style_thickness: true,
+ show_edge_editor_style_arrow: true,
+ show_edge_editor_direction: true,
+ show_edge_editor_nodes: true,
+ show_edge_editor_creator: true,
+
+ /* EDGE TOOLTIP OPTIONS */
+
+ show_edge_tooltip_uri: true,
+ show_edge_tooltip_color: true,
+ show_edge_tooltip_nodes: true,
+ show_edge_tooltip_creator: true,
+
+};
+
+Rkns.i18n = {
+ fr: {
+ "Edit Node": "Édition d’un nœud",
+ "Edit Edge": "Édition d’un lien",
+ "Title:": "Titre :",
+ "URI:": "URI :",
+ "Description:": "Description :",
+ "From:": "De :",
+ "To:": "Vers :",
+ "Image": "Image",
+ "Image URL:": "URL d'Image",
+ "Choose Image File:": "Choisir un fichier image",
+ "Full Screen": "Mode plein écran",
+ "Add Node": "Ajouter un nœud",
+ "Add Edge": "Ajouter un lien",
+ "Save Project": "Enregistrer le projet",
+ "Open Project": "Ouvrir un projet",
+ "Auto-save enabled": "Enregistrement automatique activé",
+ "Connection lost": "Connexion perdue",
+ "Created by:": "Créé par :",
+ "Zoom In": "Agrandir l’échelle",
+ "Zoom Out": "Rapetisser l’échelle",
+ "Edit": "Éditer",
+ "Remove": "Supprimer",
+ "Cancel deletion": "Annuler la suppression",
+ "Link to another node": "Créer un lien",
+ "Enlarge": "Agrandir",
+ "Shrink": "Rétrécir",
+ "Click on the background canvas to add a node": "Cliquer sur le fond du graphe pour rajouter un nœud",
+ "Click on a first node to start the edge": "Cliquer sur un premier nœud pour commencer le lien",
+ "Click on a second node to complete the edge": "Cliquer sur un second nœud pour terminer le lien",
+ "Wikipedia": "Wikipédia",
+ "Wikipedia in ": "Wikipédia en ",
+ "French": "Français",
+ "English": "Anglais",
+ "Japanese": "Japonais",
+ "Untitled project": "Projet sans titre",
+ "Lignes de Temps": "Lignes de Temps",
+ "Loading, please wait": "Chargement en cours, merci de patienter",
+ "Edge color:": "Couleur :",
+ "Dash:": "Point. :",
+ "Thickness:": "Epaisseur :",
+ "Arrow:": "Flèche :",
+ "Node color:": "Couleur :",
+ "Choose color": "Choisir une couleur",
+ "Change edge direction": "Changer le sens du lien",
+ "Do you really wish to remove node ": "Voulez-vous réellement supprimer le nœud ",
+ "Do you really wish to remove edge ": "Voulez-vous réellement supprimer le lien ",
+ "This file is not an image": "Ce fichier n'est pas une image",
+ "Image size must be under ": "L'image doit peser moins de ",
+ "Size:": "Taille :",
+ "KB": "ko",
+ "Choose from vocabulary:": "Choisir dans un vocabulaire :",
+ "SKOS Documentation properties": "SKOS: Propriétés documentaires",
+ "has note": "a pour note",
+ "has example": "a pour exemple",
+ "has definition": "a pour définition",
+ "SKOS Semantic relations": "SKOS: Relations sémantiques",
+ "has broader": "a pour concept plus large",
+ "has narrower": "a pour concept plus étroit",
+ "has related": "a pour concept apparenté",
+ "Dublin Core Metadata": "Métadonnées Dublin Core",
+ "has contributor": "a pour contributeur",
+ "covers": "couvre",
+ "created by": "créé par",
+ "has date": "a pour date",
+ "published by": "édité par",
+ "has source": "a pour source",
+ "has subject": "a pour sujet",
+ "Dragged resource": "Ressource glisée-déposée",
+ "Search the Web": "Rechercher en ligne",
+ "Search in Bins": "Rechercher dans les chutiers",
+ "Close bin": "Fermer le chutier",
+ "Refresh bin": "Rafraîchir le chutier",
+ "(untitled)": "(sans titre)",
+ "Select contents:": "Sélectionner des contenus :",
+ "Drag items from this website, drop them in Renkan": "Glissez des éléments de ce site web vers 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.": "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",
+ "Shapes available": "Formes disponibles",
+ "Circle": "Cercle",
+ "Square": "Carré",
+ "Diamond": "Losange",
+ "Hexagone": "Hexagone",
+ "Ellipse": "Ellipse",
+ "Star": "Étoile",
+ "Cloud": "Nuage",
+ "Triangle": "Triangle",
+ "Zoom Fit": "Ajuster le Zoom",
+ "Download Project": "Télécharger le projet",
+ "Save view": "Sauver la vue",
+ "View saved view": "Restaurer la Vue",
+ "Renkan \'Drag-to-Add\' bookmarklet": "Renkan \'Deplacer-Pour-Ajouter\' Signet",
+ "(unknown user)":"(non authentifié)",
+ "<unknown user>":"<non authentifié>",
+ "Search in graph":"Rechercher dans carte",
+ "Search in " : "Chercher dans "
+ }
+};
+
+/* Saves the Full JSON at each modification */
+
+Rkns.jsonIO = function(_renkan, _opts) {
+ var _proj = _renkan.project;
+ if (typeof _opts.http_method === "undefined") {
+ _opts.http_method = 'PUT';
+ }
+ var _load = function() {
+ _renkan.renderer.redrawActive = false;
+ _proj.set({
+ loadingStatus : true
+ });
+ Rkns.$.getJSON(_opts.url, function(_data) {
+ _renkan.dataloader.load(_data);
+ _proj.set({
+ loadingStatus : false
+ });
+ _proj.set({
+ saveStatus : 0
+ });
+ _renkan.renderer.redrawActive = true;
+ });
+ };
+ var _save = function() {
+ _proj.set({
+ saveStatus : 2
+ });
+ var _data = _proj.toJSON();
+ if (!_renkan.read_only) {
+ Rkns.$.ajax({
+ type : _opts.http_method,
+ url : _opts.url,
+ contentType : "application/json",
+ data : JSON.stringify(_data),
+ success : function(data, textStatus, jqXHR) {
+ _proj.set({
+ saveStatus : 0
+ });
+ }
+ });
+ }
+
+ };
+ var _thrSave = Rkns._.throttle(function() {
+ setTimeout(_save, 100);
+ }, 1000);
+
+ //TODO: Rearrange to avoid the 2 firts PUT due to a change in the project model
+ // Take car of setting up the listener correctly to listen the save action on the view
+ _proj.on("add:nodes add:edges add:users add:views", function(_model) {
+ _model.on("change remove", function(_model) {
+ _thrSave();
+ });
+ _thrSave();
+ });
+ _proj.on("change", function() {
+ if (!(_proj.changedAttributes.length === 1 && _proj
+ .hasChanged('saveStatus'))) {
+ _thrSave();
+ }
+ });
+
+ _load();
+};
+
+/* Saves the Full JSON once */
+
+Rkns.jsonIOSaveOnClick = function(_renkan, _opts) {
+ var _proj = _renkan.project,
+ _saveWarn = false,
+ _onLeave = function() {
+ return "Project not saved";
+ };
+ if (typeof _opts.http_method === "undefined") {
+ _opts.http_method = 'POST';
+ }
+ var _load = function() {
+ var getdata = {},
+ rx = /id=([^&#?=]+)/,
+ matches = document.location.hash.match(rx);
+ if (matches) {
+ getdata.id = matches[1];
+ }
+ Rkns.$.ajax({
+ url: _opts.url,
+ data: getdata,
+ beforeSend: function(){
+ _renkan.renderer.redrawActive = false;
+ _proj.set({loadingStatus:true});
+ },
+ success: function(_data) {
+ _renkan.dataloader.load(_data);
+ _proj.set({loadingStatus:false});
+ _proj.set({saveStatus:0});
+ _renkan.renderer.redrawActive = true;
+ }
+ });
+ };
+ var _save = function() {
+ _proj.set("saved_at", new Date());
+ var _data = _proj.toJSON();
+ Rkns.$.ajax({
+ type: _opts.http_method,
+ url: _opts.url,
+ contentType: "application/json",
+ data: JSON.stringify(_data),
+ beforeSend: function(){
+ _proj.set({saveStatus:2});
+ },
+ success: function(data, textStatus, jqXHR) {
+ $(window).off("beforeunload", _onLeave);
+ _saveWarn = false;
+ _proj.set({saveStatus:0});
+ //document.location.hash = "#id=" + data.id;
+ //$(".Rk-Notifications").text("Saved as "+document.location.href).fadeIn().delay(2000).fadeOut();
+ }
+ });
+ };
+ var _checkLeave = function() {
+ _proj.set({saveStatus:1});
+
+ var title = _proj.get("title");
+ if (title && _proj.get("nodes").length) {
+ $(".Rk-Save-Button").removeClass("disabled");
+ } else {
+ $(".Rk-Save-Button").addClass("disabled");
+ }
+ if (title) {
+ $(".Rk-PadTitle").css("border-color","#333333");
+ }
+ if (!_saveWarn) {
+ _saveWarn = true;
+ $(window).on("beforeunload", _onLeave);
+ }
+ };
+ _load();
+ _proj.on("add:nodes add:edges add:users change", function(_model) {
+ _model.on("change remove", function(_model) {
+ if(!(_model.changedAttributes.length === 1 && _model.hasChanged('saveStatus'))) {
+ _checkLeave();
+ }
+ });
+ if(!(_proj.changedAttributes.length === 1 && _proj.hasChanged('saveStatus'))) {
+ _checkLeave();
+ }
+ });
+ _renkan.renderer.save = function() {
+ if ($(".Rk-Save-Button").hasClass("disabled")) {
+ if (!_proj.get("title")) {
+ $(".Rk-PadTitle").css("border-color","#ff0000");
+ }
+ } else {
+ _save();
+ }
+ };
+};
+
+(function(Rkns) {
+"use strict";
+
+var _ = Rkns._;
+
+var Ldt = Rkns.Ldt = {};
+
+var Bin = Ldt.Bin = function(_renkan, _opts) {
+ if (_opts.ldt_type) {
+ var Resclass = Ldt[_opts.ldt_type+"Bin"];
+ if (Resclass) {
+ return new Resclass(_renkan, _opts);
+ }
+ }
+ console.error("No such LDT Bin Type");
+};
+
+var ProjectBin = Ldt.ProjectBin = Rkns.Utils.inherit(Rkns._BaseBin);
+
+ProjectBin.prototype.tagTemplate = renkanJST['templates/ldtjson-bin/tagtemplate.html'];
+
+ProjectBin.prototype.annotationTemplate = renkanJST['templates/ldtjson-bin/annotationtemplate.html'];
+
+ProjectBin.prototype._init = function(_renkan, _opts) {
+ this.renkan = _renkan;
+ this.proj_id = _opts.project_id;
+ this.ldt_platform = _opts.ldt_platform || "http://ldt.iri.centrepompidou.fr/";
+ this.title_$.html(_opts.title);
+ this.title_icon_$.addClass('Rk-Ldt-Title-Icon');
+ this.refresh();
+};
+
+ProjectBin.prototype.render = function(searchbase) {
+ var search = searchbase || Rkns.Utils.regexpFromTextOrArray();
+ function highlight(_text) {
+ var _e = _(_text).escape();
+ return search.isempty ? _e : search.replace(_e, "<span class='searchmatch'>$1</span>");
+ }
+ function convertTC(_ms) {
+ function pad(_n) {
+ var _res = _n.toString();
+ while (_res.length < 2) {
+ _res = '0' + _res;
+ }
+ return _res;
+ }
+ var _totalSeconds = Math.abs(Math.floor(_ms/1000)),
+ _hours = Math.floor(_totalSeconds / 3600),
+ _minutes = (Math.floor(_totalSeconds / 60) % 60),
+ _seconds = _totalSeconds % 60,
+ _res = '';
+ if (_hours) {
+ _res += pad(_hours) + ':';
+ }
+ _res += pad(_minutes) + ':' + pad(_seconds);
+ return _res;
+ }
+
+ var _html = '<li><h3>Tags</h3></li>',
+ _projtitle = this.data.meta["dc:title"],
+ _this = this,
+ count = 0;
+ _this.title_$.text('LDT Project: "' + _projtitle + '"');
+ _.map(_this.data.tags,function(_tag) {
+ var _title = _tag.meta["dc:title"];
+ if (!search.isempty && !search.test(_title)) {
+ return;
+ }
+ count++;
+ _html += _this.tagTemplate({
+ ldt_platform: _this.ldt_platform,
+ title: _title,
+ htitle: highlight(_title),
+ encodedtitle : encodeURIComponent(_title),
+ static_url: _this.renkan.options.static_url
+ });
+ });
+ _html += '<li><h3>Annotations</h3></li>';
+ _.map(_this.data.annotations,function(_annotation) {
+ var _description = _annotation.content.description,
+ _title = _annotation.content.title.replace(_description,"");
+ if (!search.isempty && !search.test(_title) && !search.test(_description)) {
+ return;
+ }
+ count++;
+ var _duration = _annotation.end - _annotation.begin,
+ _img = (
+ (_annotation.content && _annotation.content.img && _annotation.content.img.src) ?
+ _annotation.content.img.src :
+ ( _duration ? _this.renkan.options.static_url+"img/ldt-segment.png" : _this.renkan.options.static_url+"img/ldt-point.png" )
+ );
+ _html += _this.annotationTemplate({
+ ldt_platform: _this.ldt_platform,
+ title: _title,
+ htitle: highlight(_title),
+ description: _description,
+ hdescription: highlight(_description),
+ start: convertTC(_annotation.begin),
+ end: convertTC(_annotation.end),
+ duration: convertTC(_duration),
+ mediaid: _annotation.media,
+ annotationid: _annotation.id,
+ image: _img,
+ static_url: _this.renkan.options.static_url
+ });
+ });
+
+ this.main_$.html(_html);
+ if (!search.isempty && count) {
+ this.count_$.text(count).show();
+ } else {
+ this.count_$.hide();
+ }
+ if (!search.isempty && !count) {
+ this.$.hide();
+ } else {
+ this.$.show();
+ }
+ this.renkan.resizeBins();
+};
+
+ProjectBin.prototype.refresh = function() {
+ var _this = this;
+ Rkns.$.ajax({
+ url: this.ldt_platform + 'ldtplatform/ldt/cljson/id/' + this.proj_id,
+ dataType: "jsonp",
+ success: function(_data) {
+ _this.data = _data;
+ _this.render();
+ }
+ });
+};
+
+var Search = Ldt.Search = function(_renkan, _opts) {
+ this.renkan = _renkan;
+ this.lang = _opts.lang || "en";
+};
+
+Search.prototype.getBgClass = function() {
+ return "Rk-Ldt-Icon";
+};
+
+Search.prototype.getSearchTitle = function() {
+ return this.renkan.translate("Lignes de Temps");
+};
+
+Search.prototype.search = function(_q) {
+ this.renkan.tabs.push(
+ new ResultsBin(this.renkan, {
+ search: _q
+ })
+ );
+};
+
+var ResultsBin = Ldt.ResultsBin = Rkns.Utils.inherit(Rkns._BaseBin);
+
+ResultsBin.prototype.segmentTemplate = renkanJST['templates/ldtjson-bin/segmenttemplate.html'];
+
+ResultsBin.prototype._init = function(_renkan, _opts) {
+ this.renkan = _renkan;
+ this.ldt_platform = _opts.ldt_platform || "http://ldt.iri.centrepompidou.fr/";
+ this.max_results = _opts.max_results || 50;
+ this.search = _opts.search;
+ this.title_$.html('Lignes de Temps: "' + _opts.search + '"');
+ this.title_icon_$.addClass('Rk-Ldt-Title-Icon');
+ this.refresh();
+};
+
+ResultsBin.prototype.render = function(searchbase) {
+ if (!this.data) {
+ return;
+ }
+ var search = searchbase || Rkns.Utils.regexpFromTextOrArray();
+ var highlightrx = (search.isempty ? Rkns.Utils.regexpFromTextOrArray(this.search) : search);
+ function highlight(_text) {
+ return highlightrx.replace(_(_text).escape(), "<span class='searchmatch'>$1</span>");
+ }
+ function convertTC(_ms) {
+ function pad(_n) {
+ var _res = _n.toString();
+ while (_res.length < 2) {
+ _res = '0' + _res;
+ }
+ return _res;
+ }
+ var _totalSeconds = Math.abs(Math.floor(_ms/1000)),
+ _hours = Math.floor(_totalSeconds / 3600),
+ _minutes = (Math.floor(_totalSeconds / 60) % 60),
+ _seconds = _totalSeconds % 60,
+ _res = '';
+ if (_hours) {
+ _res += pad(_hours) + ':';
+ }
+ _res += pad(_minutes) + ':' + pad(_seconds);
+ return _res;
+ }
+
+ var _html = '',
+ _this = this,
+ count = 0;
+ _.each(this.data.objects,function(_segment) {
+ var _description = _segment.abstract,
+ _title = _segment.title;
+ if (!search.isempty && !search.test(_title) && !search.test(_description)) {
+ return;
+ }
+ count++;
+ var _duration = _segment.duration,
+ _begin = _segment.start_ts,
+ _end = + _segment.duration + _begin,
+ _img = (
+ _duration ?
+ _this.renkan.options.static_url + "img/ldt-segment.png" :
+ _this.renkan.options.static_url + "img/ldt-point.png"
+ );
+ _html += _this.segmentTemplate({
+ ldt_platform: _this.ldt_platform,
+ title: _title,
+ htitle: highlight(_title),
+ description: _description,
+ hdescription: highlight(_description),
+ start: convertTC(_begin),
+ end: convertTC(_end),
+ duration: convertTC(_duration),
+ mediaid: _segment.iri_id,
+ //projectid: _segment.project_id,
+ //cuttingid: _segment.cutting_id,
+ annotationid: _segment.element_id,
+ image: _img
+ });
+ });
+
+ this.main_$.html(_html);
+ if (!search.isempty && count) {
+ this.count_$.text(count).show();
+ } else {
+ this.count_$.hide();
+ }
+ if (!search.isempty && !count) {
+ this.$.hide();
+ } else {
+ this.$.show();
+ }
+ this.renkan.resizeBins();
+};
+
+ResultsBin.prototype.refresh = function() {
+ var _this = this;
+ Rkns.$.ajax({
+ url: this.ldt_platform + 'ldtplatform/api/ldt/1.0/segments/search/',
+ data: {
+ format: "jsonp",
+ q: this.search,
+ limit: this.max_results
+ },
+ dataType: "jsonp",
+ success: function(_data) {
+ _this.data = _data;
+ _this.render();
+ }
+ });
+};
+
+})(window.Rkns);
+
+Rkns.ResourceList = {};
+
+Rkns.ResourceList.Bin = Rkns.Utils.inherit(Rkns._BaseBin);
+
+Rkns.ResourceList.Bin.prototype.resultTemplate = renkanJST['templates/list-bin.html'];
+
+Rkns.ResourceList.Bin.prototype._init = function(_renkan, _opts) {
+ this.renkan = _renkan;
+ this.title_$.html(_opts.title);
+ if (_opts.list) {
+ this.data = _opts.list;
+ }
+ this.refresh();
+};
+
+Rkns.ResourceList.Bin.prototype.render = function(searchbase) {
+ var search = searchbase || Rkns.Utils.regexpFromTextOrArray();
+ function highlight(_text) {
+ var _e = _(_text).escape();
+ return search.isempty ? _e : search.replace(_e, "<span class='searchmatch'>$1</span>");
+ }
+ var _html = "",
+ _this = this,
+ count = 0;
+ Rkns._.each(this.data,function(_item) {
+ var _element;
+ if (typeof _item === "string") {
+ if (/^(https?:\/\/|www)/.test(_item)) {
+ _element = { url: _item };
+ } else {
+ _element = { title: _item.replace(/[:,]?\s?(https?:\/\/|www)[\d\w\/.&?=#%-_]+\s?/,'').trim() };
+ var _match = _item.match(/(https?:\/\/|www)[\d\w\/.&?=#%-_]+/);
+ if (_match) {
+ _element.url = _match[0];
+ }
+ if (_element.title.length > 80) {
+ _element.description = _element.title;
+ _element.title = _element.title.replace(/^(.{30,60})\s.+$/,'$1…');
+ }
+ }
+ } else {
+ _element = _item;
+ }
+ var title = _element.title || (_element.url || "").replace(/^https?:\/\/(www\.)?/,'').replace(/^(.{40}).+$/,'$1…'),
+ url = _element.url || "",
+ description = _element.description || "",
+ image = _element.image || "";
+ if (url && !/^https?:\/\//.test(url)) {
+ url = 'http://' + url;
+ }
+ if (!search.isempty && !search.test(title) && !search.test(description)) {
+ return;
+ }
+ count++;
+ _html += _this.resultTemplate({
+ url: url,
+ title: title,
+ htitle: highlight(title),
+ image: image,
+ description: description,
+ hdescription: highlight(description),
+ static_url: _this.renkan.options.static_url
+ });
+ });
+ _this.main_$.html(_html);
+ if (!search.isempty && count) {
+ this.count_$.text(count).show();
+ } else {
+ this.count_$.hide();
+ }
+ if (!search.isempty && !count) {
+ this.$.hide();
+ } else {
+ this.$.show();
+ }
+ this.renkan.resizeBins();
+};
+
+Rkns.ResourceList.Bin.prototype.refresh = function() {
+ if (this.data) {
+ this.render();
+ }
+};
+
+Rkns.Wikipedia = {
+};
+
+Rkns.Wikipedia.Search = function(_renkan, _opts) {
+ this.renkan = _renkan;
+ this.lang = _opts.lang || "en";
+};
+
+Rkns.Wikipedia.Search.prototype.getBgClass = function() {
+ return "Rk-Wikipedia-Search-Icon Rk-Wikipedia-Lang-" + this.lang;
+};
+
+Rkns.Wikipedia.Search.prototype.getSearchTitle = function() {
+ var langs = {
+ "fr": "French",
+ "en": "English",
+ "ja": "Japanese"
+ };
+ if (langs[this.lang]) {
+ return this.renkan.translate("Wikipedia in ") + this.renkan.translate(langs[this.lang]);
+ } else {
+ return this.renkan.translate("Wikipedia") + " [" + this.lang + "]";
+ }
+};
+
+Rkns.Wikipedia.Search.prototype.search = function(_q) {
+ this.renkan.tabs.push(
+ new Rkns.Wikipedia.Bin(this.renkan, {
+ lang: this.lang,
+ search: _q
+ })
+ );
+};
+
+Rkns.Wikipedia.Bin = Rkns.Utils.inherit(Rkns._BaseBin);
+
+Rkns.Wikipedia.Bin.prototype.resultTemplate = renkanJST['templates/wikipedia-bin/resulttemplate.html'];
+
+Rkns.Wikipedia.Bin.prototype._init = function(_renkan, _opts) {
+ this.renkan = _renkan;
+ this.search = _opts.search;
+ this.lang = _opts.lang || "en";
+ this.title_icon_$.addClass('Rk-Wikipedia-Title-Icon Rk-Wikipedia-Lang-' + this.lang);
+ this.title_$.html(this.search).addClass("Rk-Wikipedia-Title");
+ this.refresh();
+};
+
+Rkns.Wikipedia.Bin.prototype.render = function(searchbase) {
+ var search = searchbase || Rkns.Utils.regexpFromTextOrArray();
+ var highlightrx = (search.isempty ? Rkns.Utils.regexpFromTextOrArray(this.search) : search);
+ function highlight(_text) {
+ return highlightrx.replace(_(_text).escape(), "<span class='searchmatch'>$1</span>");
+ }
+ var _html = "",
+ _this = this,
+ count = 0;
+ Rkns._.each(this.data.query.search, function(_result) {
+ var title = _result.title,
+ url = "http://" + _this.lang + ".wikipedia.org/wiki/" + encodeURI(title.replace(/ /g,"_")),
+ description = Rkns.$('<div>').html(_result.snippet).text();
+ if (!search.isempty && !search.test(title) && !search.test(description)) {
+ return;
+ }
+ count++;
+ _html += _this.resultTemplate({
+ url: url,
+ title: title,
+ htitle: highlight(title),
+ description: description,
+ hdescription: highlight(description),
+ static_url: _this.renkan.options.static_url
+ });
+ });
+ _this.main_$.html(_html);
+ if (!search.isempty && count) {
+ this.count_$.text(count).show();
+ } else {
+ this.count_$.hide();
+ }
+ if (!search.isempty && !count) {
+ this.$.hide();
+ } else {
+ this.$.show();
+ }
+ this.renkan.resizeBins();
+};
+
+Rkns.Wikipedia.Bin.prototype.refresh = function() {
+ var _this = this;
+ Rkns.$.ajax({
+ url: "http://" + _this.lang + ".wikipedia.org/w/api.php?action=query&list=search&srsearch=" + encodeURIComponent(this.search) + "&format=json",
+ dataType: "jsonp",
+ success: function(_data) {
+ _this.data = _data;
+ _this.render();
+ }
+ });
+};
+
+
+define('renderer/baserepresentation',['jquery', 'underscore'], function ($, _) {
+ 'use strict';
+
+ /* Rkns.Renderer._BaseRepresentation Class */
+
+ /* In Renkan, a "Representation" is a sort of ViewModel (in the MVVM paradigm) and bridges the gap between
+ * models (written with Backbone.js) and the view (written with Paper.js)
+ * Renkan's representations all inherit from Rkns.Renderer._BaseRepresentation '*/
+
+ var _BaseRepresentation = function(_renderer, _model) {
+ if (typeof _renderer !== "undefined") {
+ this.renderer = _renderer;
+ this.renkan = _renderer.renkan;
+ this.project = _renderer.renkan.project;
+ this.options = _renderer.renkan.options;
+ this.model = _model;
+ if (this.model) {
+ var _this = this;
+ this._changeBinding = function() {
+ _this.redraw({change: true});
+ };
+ this._removeBinding = function() {
+ _renderer.removeRepresentation(_this);
+ _.defer(function() {
+ _renderer.redraw();
+ });
+ };
+ this._selectBinding = function() {
+ _this.select();
+ };
+ this._unselectBinding = function() {
+ _this.unselect();
+ };
+ this.model.on("change", this._changeBinding );
+ this.model.on("remove", this._removeBinding );
+ this.model.on("select", this._selectBinding );
+ this.model.on("unselect", this._unselectBinding );
+ }
+ }
+ };
+
+ /* Rkns.Renderer._BaseRepresentation Methods */
+
+ _(_BaseRepresentation.prototype).extend({
+ _super: function(_func) {
+ return _BaseRepresentation.prototype[_func].apply(this, Array.prototype.slice.call(arguments, 1));
+ },
+ redraw: function() {},
+ moveTo: function() {},
+ show: function() { return "BaseRepresentation.show"; },
+ hide: function() {},
+ select: function() {
+ if (this.model) {
+ this.model.trigger("selected");
+ }
+ },
+ unselect: function() {
+ if (this.model) {
+ this.model.trigger("unselected");
+ }
+ },
+ highlight: function() {},
+ unhighlight: function() {},
+ mousedown: function() {},
+ mouseup: function() {
+ if (this.model) {
+ this.model.trigger("clicked");
+ }
+ },
+ destroy: function() {
+ if (this.model) {
+ this.model.off("change", this._changeBinding );
+ this.model.off("remove", this._removeBinding );
+ this.model.off("select", this._selectBinding );
+ this.model.off("unselect", this._unselectBinding );
+ }
+ }
+ }).value();
+
+ /* End of Rkns.Renderer._BaseRepresentation Class */
+
+ return _BaseRepresentation;
+
+});
+
+define('requtils',[], function ($, _) {
+ 'use strict';
+ return {
+ getUtils: function(){
+ return window.Rkns.Utils;
+ },
+ getRenderer: function(){
+ return window.Rkns.Renderer;
+ }
+ };
+
+});
+
+
+define('renderer/basebutton',['jquery', 'underscore', 'requtils', 'renderer/baserepresentation'], function ($, _, requtils, BaseRepresentation) {
+ 'use strict';
+
+ var Utils = requtils.getUtils();
+
+ /* Rkns.Renderer._BaseButton Class */
+
+ /* BaseButton is extended by contextual buttons that appear when hovering on nodes and edges */
+
+ var _BaseButton = Utils.inherit(BaseRepresentation);
+
+ _(_BaseButton.prototype).extend({
+ moveTo: function(_pos) {
+ this.sector.moveTo(_pos);
+ },
+ show: function() {
+ this.sector.show();
+ },
+ hide: function() {
+ if (this.sector){
+ this.sector.hide();
+ }
+ },
+ select: function() {
+ this.sector.select();
+ },
+ unselect: function(_newTarget) {
+ this.sector.unselect();
+ if (!_newTarget || (_newTarget !== this.source_representation && _newTarget.source_representation !== this.source_representation)) {
+ this.source_representation.unselect();
+ }
+ },
+ destroy: function() {
+ this.sector.destroy();
+ }
+ }).value();
+
+ return _BaseButton;
+
+});
+
+
+define('renderer/shapebuilder',[], function () {
+ 'use strict';
+
+ var cloud_path = "M0,0c-0.1218516546,-0.0336420601 -0.2451649928,0.0048580836 -0.3302944641,0.0884969975c-0.0444763883,-0.0550844815 -0.1047003238,-0.0975985034 -0.1769360893,-0.1175406746c-0.1859066673,-0.0513257002 -0.3774236254,0.0626045858 -0.4272374613,0.2541588105c-0.0036603877,0.0140753132 -0.0046241235,0.028229722 -0.0065872453,0.042307536c-0.1674179627,-0.0179317735 -0.3276106855,0.0900599386 -0.3725537463,0.2628868425c-0.0445325077,0.1712456429 0.0395025693,0.3463497959 0.1905420475,0.4183458793c-0.0082101538,0.0183442886 -0.0158652506,0.0372432828 -0.0211098452,0.0574080693c-0.0498130336,0.1915540431 0.0608692569,0.3884647499 0.2467762814,0.4397904033c0.0910577256,0.0251434257 0.1830791813,0.0103792696 0.2594677475,-0.0334472349c0.042100113,0.0928009202 0.1205930075,0.1674914182 0.2240666796,0.1960572479c0.1476344161,0.0407610407 0.297446165,-0.0238077445 0.3783262342,-0.1475652419c0.0327623278,0.0238981846 0.0691792333,0.0436665447 0.1102008706,0.0549940004c0.1859065794,0.0513256592 0.3770116432,-0.0627203154 0.4268255671,-0.2542745401c0.0250490557,-0.0963230532 0.0095494076,-0.1938010889 -0.0356681889,-0.2736906101c0.0447507424,-0.0439678867 0.0797796014,-0.0996624318 0.0969425462,-0.1656617192c0.0498137481,-0.1915564561 -0.0608688118,-0.3884669813 -0.2467755669,-0.4397928163c-0.0195699622,-0.0054005426 -0.0391731675,-0.0084429542 -0.0586916488,-0.0102888295c0.0115683912,-0.1682147574 -0.0933564223,-0.3269222408 -0.2572937178,-0.3721841203z";
+ /* ShapeBuilder Begin */
+
+ var builders = {
+ "circle":{
+ getShape: function() {
+ return new paper.Path.Circle([0, 0], 1);
+ },
+ getImageShape: function(center, radius) {
+ return new paper.Path.Circle(center, radius);
+ }
+ },
+ "rectangle":{
+ getShape: function() {
+ return new paper.Path.Rectangle([-2, -2], [2, 2]);
+ },
+ getImageShape: function(center, radius) {
+ return new paper.Path.Rectangle([-radius, -radius], [radius*2, radius*2]);
+ }
+ },
+ "ellipse":{
+ getShape: function() {
+ return new paper.Path.Ellipse(new paper.Rectangle([-2, -1], [2, 1]));
+ },
+ getImageShape: function(center, radius) {
+ return new paper.Path.Ellipse(new paper.Rectangle([-radius, -radius/2], [radius*2, radius]));
+ }
+ },
+ "polygon":{
+ getShape: function() {
+ return new paper.Path.RegularPolygon([0, 0], 6, 1);
+ },
+ getImageShape: function(center, radius) {
+ return new paper.Path.RegularPolygon(center, 6, radius);
+ }
+ },
+ "diamond":{
+ getShape: function() {
+ var d = new paper.Path.Rectangle([-Math.SQRT2, -Math.SQRT2], [Math.SQRT2, Math.SQRT2]);
+ d.rotate(45);
+ return d;
+ },
+ getImageShape: function(center, radius) {
+ var d = new paper.Path.Rectangle([-radius*Math.SQRT2/2, -radius*Math.SQRT2/2], [radius*Math.SQRT2, radius*Math.SQRT2]);
+ d.rotate(45);
+ return d;
+ }
+ },
+ "star":{
+ getShape: function() {
+ return new paper.Path.Star([0, 0], 8, 1, 0.7);
+ },
+ getImageShape: function(center, radius) {
+ return new paper.Path.Star(center, 8, radius*1, radius*0.7);
+ }
+ },
+ "cloud": {
+ getShape: function() {
+ var path = new paper.Path(cloud_path);
+ return path;
+
+ },
+ getImageShape: function(center, radius) {
+ var path = new paper.Path(cloud_path);
+ path.scale(radius);
+ path.translate(center);
+ return path;
+ }
+ },
+ "triangle": {
+ getShape: function() {
+ return new paper.Path.RegularPolygon([0,0], 3, 1);
+ },
+ getImageShape: function(center, radius) {
+ var shape = new paper.Path.RegularPolygon([0,0], 3, 1);
+ shape.scale(radius);
+ shape.translate(center);
+ return shape;
+ }
+ },
+ "svg": function(path){
+ return {
+ getShape: function() {
+ return new paper.Path(path);
+ },
+ getImageShape: function(center, radius) {
+ // No calcul for the moment
+ return new paper.Path();
+ }
+ };
+ }
+ };
+
+ var ShapeBuilder = function (shape){
+ if(shape === null || typeof shape === "undefined"){
+ shape = "circle";
+ }
+ if(shape.substr(0,4)==="svg:"){
+ return builders.svg(shape.substr(4));
+ }
+ if(!(shape in builders)){
+ shape = "circle";
+ }
+ return builders[shape];
+ };
+
+ ShapeBuilder.builders = builders;
+
+ return ShapeBuilder;
+
+});
+
+define('renderer/noderepr',['jquery', 'underscore', 'requtils', 'renderer/baserepresentation', 'renderer/shapebuilder'], function ($, _, requtils, BaseRepresentation, ShapeBuilder) {
+ 'use strict';
+
+ var Utils = requtils.getUtils();
+
+ /* Rkns.Renderer.Node Class */
+
+ /* The representation for the node : A circle, with an image inside and a text label underneath.
+ * The circle and the image are drawn on canvas and managed by Paper.js.
+ * The text label is an HTML node, managed by jQuery. */
+
+ //var NodeRepr = Renderer.Node = Utils.inherit(Renderer._BaseRepresentation);
+ var NodeRepr = Utils.inherit(BaseRepresentation);
+
+ _(NodeRepr.prototype).extend({
+ _init: function() {
+ this.renderer.node_layer.activate();
+ this.type = "Node";
+ this.buildShape();
+ this.hidden = false;
+ this.ghost= false;
+ if (this.options.show_node_circles) {
+ this.circle.strokeWidth = this.options.node_stroke_width;
+ this.h_ratio = 1;
+ } else {
+ this.h_ratio = 0;
+ }
+ this.title = $('<div class="Rk-Label">').appendTo(this.renderer.labels_$);
+
+ if (this.options.editor_mode) {
+ var Renderer = requtils.getRenderer();
+ this.normal_buttons = [
+ new Renderer.NodeEditButton(this.renderer, null),
+ new Renderer.NodeRemoveButton(this.renderer, null),
+ new Renderer.NodeLinkButton(this.renderer, null),
+ new Renderer.NodeEnlargeButton(this.renderer, null),
+ new Renderer.NodeShrinkButton(this.renderer, null)
+ ];
+ if (this.options.hide_nodes){
+ this.normal_buttons.push(
+ new Renderer.NodeHideButton(this.renderer, null),
+ new Renderer.NodeShowButton(this.renderer, null)
+ );
+ }
+ this.pending_delete_buttons = [
+ new Renderer.NodeRevertButton(this.renderer, null)
+ ];
+ this.all_buttons = this.normal_buttons.concat(this.pending_delete_buttons);
+
+ for (var i = 0; i < this.all_buttons.length; i++) {
+ this.all_buttons[i].source_representation = this;
+ }
+ this.active_buttons = [];
+ } else {
+ this.active_buttons = this.all_buttons = [];
+ }
+ this.last_circle_radius = 1;
+
+ if (this.renderer.minimap) {
+ this.renderer.minimap.node_layer.activate();
+ this.minimap_circle = new paper.Path.Circle([0, 0], 1);
+ this.minimap_circle.__representation = this.renderer.minimap.miniframe.__representation;
+ this.renderer.minimap.node_group.addChild(this.minimap_circle);
+ }
+ },
+ _getStrokeWidth: function() {
+ var thickness = (this.model.has('style') && this.model.get('style').thickness) || 1;
+ return this.options.node_stroke_width + (thickness-1) * (this.options.node_stroke_max_width - this.options.node_stroke_width) / (this.options.node_stroke_witdh_scale-1);
+ },
+ _getSelectedStrokeWidth: function() {
+ var thickness = (this.model.has('style') && this.model.get('style').thickness) || 1;
+ return this.options.selected_node_stroke_width + (thickness-1) * (this.options.selected_node_stroke_max_width - this.options.selected_node_stroke_width) / (this.options.node_stroke_witdh_scale-1);
+ },
+ buildShape: function(){
+ if( 'shape' in this.model.changed ) {
+ delete this.img;
+ }
+ if(this.circle){
+ this.circle.remove();
+ delete this.circle;
+ }
+ // "circle" "rectangle" "ellipse" "polygon" "star" "diamond"
+ this.shapeBuilder = new ShapeBuilder(this.model.get("shape"));
+ this.circle = this.shapeBuilder.getShape();
+ this.circle.__representation = this;
+ this.circle.sendToBack();
+ this.last_circle_radius = 1;
+ },
+ redraw: function(options) {
+ if( 'shape' in this.model.changed && 'change' in options && options.change ) {
+ //if( 'shape' in this.model.changed ) {
+ this.buildShape();
+ }
+ var _model_coords = new paper.Point(this.model.get("position")),
+ _baseRadius = this.options.node_size_base * Math.exp((this.model.get("size") || 0) * Utils._NODE_SIZE_STEP);
+ if (!this.is_dragging || !this.paper_coords) {
+ this.paper_coords = this.renderer.toPaperCoords(_model_coords);
+ }
+ this.circle_radius = _baseRadius * this.renderer.view.scale;
+ if (this.last_circle_radius !== this.circle_radius) {
+ this.all_buttons.forEach(function(b) {
+ b.setSectorSize();
+ });
+ this.circle.scale(this.circle_radius / this.last_circle_radius);
+ if (this.node_image) {
+ this.node_image.scale(this.circle_radius / this.last_circle_radius);
+ }
+ }
+ this.circle.position = this.paper_coords;
+ if (this.node_image) {
+ this.node_image.position = this.paper_coords.subtract(this.image_delta.multiply(this.circle_radius));
+ }
+ this.last_circle_radius = this.circle_radius;
+
+ var old_act_btn = this.active_buttons;
+
+ var opacity = 1;
+ if (this.model.get("delete_scheduled")) {
+ opacity = 0.5;
+ this.active_buttons = this.pending_delete_buttons;
+ this.circle.dashArray = [2,2];
+ } else {
+ opacity = 1;
+ this.active_buttons = this.normal_buttons;
+ this.circle.dashArray = null;
+ }
+ if (this.selected && this.renderer.isEditable() && !this.ghost) {
+ if (old_act_btn !== this.active_buttons) {
+ old_act_btn.forEach(function(b) {
+ b.hide();
+ });
+ }
+ this.active_buttons.forEach(function(b) {
+ b.show();
+ });
+ }
+
+ if (this.node_image) {
+ this.node_image.opacity = this.highlighted ? opacity * 0.5 : (opacity - 0.01);
+ }
+
+ this.circle.fillColor = this.highlighted ? this.options.highlighted_node_fill_color : this.options.node_fill_color;
+
+ this.circle.opacity = this.options.show_node_circles ? opacity : 0.01;
+
+ var _text = this.model.get("title") || this.renkan.translate(this.options.label_untitled_nodes) || "";
+ _text = Utils.shortenText(_text, this.options.node_label_max_length);
+
+ if (typeof this.highlighted === "object") {
+ this.title.html(this.highlighted.replace(_(_text).escape(),'<span class="Rk-Highlighted">$1</span>'));
+ } else {
+ this.title.text(_text);
+ }
+
+ var _strokeWidth = this._getStrokeWidth();
+ this.title.css({
+ left: this.paper_coords.x,
+ top: this.paper_coords.y + this.circle_radius * this.h_ratio + this.options.node_label_distance + 0.5*_strokeWidth,
+ opacity: opacity
+ });
+ var _color = (this.model.has("style") && this.model.get("style").color) || (this.model.get("created_by") || Utils._USER_PLACEHOLDER(this.renkan)).get("color"),
+ _dash = (this.model.has("style") && this.model.get("style").dash) ? this.options.default_dash_array : null;
+ this.circle.strokeWidth = _strokeWidth;
+ this.circle.strokeColor = _color;
+ this.circle.dashArray = _dash;
+ var _pc = this.paper_coords;
+ this.all_buttons.forEach(function(b) {
+ b.moveTo(_pc);
+ });
+ var lastImage = this.img;
+ this.img = this.model.get("image");
+ if (this.img && this.img !== lastImage) {
+ this.showImage();
+ if(this.circle) {
+ this.circle.sendToBack();
+ }
+ }
+ if (this.node_image && !this.img) {
+ this.node_image.remove();
+ delete this.node_image;
+ }
+
+ if (this.renderer.minimap) {
+ this.minimap_circle.fillColor = _color;
+ var minipos = this.renderer.toMinimapCoords(_model_coords),
+ miniradius = this.renderer.minimap.scale * _baseRadius,
+ minisize = new paper.Size([miniradius, miniradius]);
+ this.minimap_circle.fitBounds(minipos.subtract(minisize), minisize.multiply(2));
+ }
+
+ if (typeof options === 'undefined' || !('dontRedrawEdges' in options) || !options.dontRedrawEdges) {
+ var _this = this;
+ _.each(
+ this.project.get("edges").filter(
+ function (ed) {
+ return ((ed.get("to") === _this.model) || (ed.get("from") === _this.model));
+ }
+ ),
+ function(edge, index, list) {
+ var repr = _this.renderer.getRepresentationByModel(edge);
+ 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") {
+ repr.redraw();
+ }
+ }
+ );
+ }
+ if (this.ghost){
+ this.show(true);
+ } else {
+ if (this.hidden) { this.hide(); }
+ }
+ },
+ showImage: function() {
+ var _image = null;
+ if (typeof this.renderer.image_cache[this.img] === "undefined") {
+ _image = new Image();
+ this.renderer.image_cache[this.img] = _image;
+ _image.src = this.img;
+ } else {
+ _image = this.renderer.image_cache[this.img];
+ }
+ if (_image.width) {
+ if (this.node_image) {
+ this.node_image.remove();
+ }
+ this.renderer.node_layer.activate();
+ var width = _image.width,
+ height = _image.height,
+ clipPath = this.model.get("clip_path"),
+ hasClipPath = (typeof clipPath !== "undefined" && clipPath),
+ _clip = null,
+ baseRadius = null,
+ centerPoint = null;
+
+ if (hasClipPath) {
+ _clip = new paper.Path();
+ var instructions = clipPath.match(/[a-z][^a-z]+/gi) || [],
+ lastCoords = [0,0],
+ minX = Infinity,
+ minY = Infinity,
+ maxX = -Infinity,
+ maxY = -Infinity;
+
+ var transformCoords = function(tabc, relative) {
+ var newCoords = tabc.slice(1).map(function(v, k) {
+ var res = parseFloat(v),
+ isY = k % 2;
+ if (isY) {
+ res = ( res - 0.5 ) * height;
+ } else {
+ res = ( res - 0.5 ) * width;
+ }
+ if (relative) {
+ res += lastCoords[isY];
+ }
+ if (isY) {
+ minY = Math.min(minY, res);
+ maxY = Math.max(maxY, res);
+ } else {
+ minX = Math.min(minX, res);
+ maxX = Math.max(maxX, res);
+ }
+ return res;
+ });
+ lastCoords = newCoords.slice(-2);
+ return newCoords;
+ };
+
+ instructions.forEach(function(instr) {
+ var coords = instr.match(/([a-z]|[0-9.-]+)/ig) || [""];
+ switch(coords[0]) {
+ case "M":
+ _clip.moveTo(transformCoords(coords));
+ break;
+ case "m":
+ _clip.moveTo(transformCoords(coords, true));
+ break;
+ case "L":
+ _clip.lineTo(transformCoords(coords));
+ break;
+ case "l":
+ _clip.lineTo(transformCoords(coords, true));
+ break;
+ case "C":
+ _clip.cubicCurveTo(transformCoords(coords));
+ break;
+ case "c":
+ _clip.cubicCurveTo(transformCoords(coords, true));
+ break;
+ case "Q":
+ _clip.quadraticCurveTo(transformCoords(coords));
+ break;
+ case "q":
+ _clip.quadraticCurveTo(transformCoords(coords, true));
+ break;
+ }
+ });
+
+ baseRadius = Math[this.options.node_images_fill_mode ? "min" : "max"](maxX - minX, maxY - minY) / 2;
+ centerPoint = new paper.Point((maxX + minX) / 2, (maxY + minY) / 2);
+ if (!this.options.show_node_circles) {
+ this.h_ratio = (maxY - minY) / (2 * baseRadius);
+ }
+ } else {
+ baseRadius = Math[this.options.node_images_fill_mode ? "min" : "max"](width, height) / 2;
+ centerPoint = new paper.Point(0,0);
+ if (!this.options.show_node_circles) {
+ this.h_ratio = height / (2 * baseRadius);
+ }
+ }
+ var _raster = new paper.Raster(_image);
+ _raster.locked = true; // Disable mouse events on icon
+ if (hasClipPath) {
+ _raster = new paper.Group(_clip, _raster);
+ _raster.opacity = 0.99;
+ /* This is a workaround to allow clipping at group level
+ * If opacity was set to 1, paper.js would merge all clipping groups in one (known bug).
+ */
+ _raster.clipped = true;
+ _clip.__representation = this;
+ }
+ if (this.options.clip_node_images) {
+ var _circleClip = this.shapeBuilder.getImageShape(centerPoint, baseRadius);
+ _raster = new paper.Group(_circleClip, _raster);
+ _raster.opacity = 0.99;
+ _raster.clipped = true;
+ _circleClip.__representation = this;
+ }
+ this.image_delta = centerPoint.divide(baseRadius);
+ this.node_image = _raster;
+ this.node_image.__representation = _this;
+ this.node_image.scale(this.circle_radius / baseRadius);
+ this.node_image.position = this.paper_coords.subtract(this.image_delta.multiply(this.circle_radius));
+ this.node_image.insertAbove(this.circle);
+ } else {
+ var _this = this;
+ $(_image).on("load", function() {
+ _this.showImage();
+ });
+ }
+ },
+ paperShift: function(_delta) {
+ if (this.options.editor_mode) {
+ if (!this.renkan.read_only) {
+ this.is_dragging = true;
+ this.paper_coords = this.paper_coords.add(_delta);
+ this.redraw();
+ }
+ } else {
+ this.renderer.view.paperShift(_delta);
+ }
+ },
+ openEditor: function() {
+ this.renderer.removeRepresentationsOfType("editor");
+ var _editor = this.renderer.addRepresentation("NodeEditor",null);
+ _editor.source_representation = this;
+ _editor.draw();
+ },
+ select: function() {
+ this.selected = true;
+ this.circle.strokeWidth = this._getSelectedStrokeWidth();
+ if (this.renderer.isEditable() && !this.hidden) {
+ this.active_buttons.forEach(function(b) {
+ b.show();
+ });
+ }
+ var _uri = this.model.get("uri");
+ if (_uri) {
+ $('.Rk-Bin-Item').each(function() {
+ var _el = $(this);
+ if (_el.attr("data-uri") === _uri) {
+ _el.addClass("selected");
+ }
+ });
+ }
+ if (!this.options.editor_mode) {
+ this.openEditor();
+ }
+
+ if (this.renderer.minimap) {
+ this.minimap_circle.strokeWidth = this.options.minimap_highlight_weight;
+ this.minimap_circle.strokeColor = this.options.minimap_highlight_color;
+ }
+ //if the node is hidden and the mouse hover it, it appears as a ghost
+ if (this.hidden) {
+ this.show(true);
+ }
+ else {
+ this.showNeighbors(true);
+ }
+ this._super("select");
+ },
+ hideButtons: function() {
+ this.all_buttons.forEach(function(b) {
+ b.hide();
+ });
+ delete(this.buttonTimeout);
+ },
+ unselect: function(_newTarget) {
+ if (!_newTarget || _newTarget.source_representation !== this) {
+ this.selected = false;
+ var _this = this;
+ this.buttons_timeout = setTimeout(function() { _this.hideButtons(); }, 200);
+ this.circle.strokeWidth = this._getStrokeWidth();
+ $('.Rk-Bin-Item').removeClass("selected");
+ if (this.renderer.minimap) {
+ this.minimap_circle.strokeColor = undefined;
+ }
+ //when the mouse don't hover the node anymore, we hide it
+ if (this.hidden) {
+ this.hide();
+ }
+ else {
+ this.hideNeighbors();
+ }
+ this._super("unselect");
+ }
+ },
+ hide: function(){
+ var _this = this;
+ this.ghost = false;
+ this.hidden = true;
+ if (typeof this.node_image !== 'undefined'){
+ this.node_image.opacity = 0;
+ }
+ this.hideButtons();
+ this.circle.opacity = 0;
+ this.title.css('opacity', 0);
+ this.minimap_circle.opacity = 0;
+
+
+ _.each(
+ this.project.get("edges").filter(
+ function (ed) {
+ return ((ed.get("to") === _this.model) || (ed.get("from") === _this.model));
+ }
+ ),
+ function(edge, index, list) {
+ var repr = _this.renderer.getRepresentationByModel(edge);
+ 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") {
+ repr.hide();
+ }
+ }
+ );
+ this.hideNeighbors();
+ },
+ show: function(ghost){
+ var _this = this;
+ this.ghost = ghost;
+ if (this.ghost){
+ if (typeof this.node_image !== 'undefined'){
+ this.node_image.opacity = this.options.ghost_opacity;
+ }
+ this.circle.opacity = this.options.ghost_opacity;
+ this.title.css('opacity', this.options.ghost_opacity);
+ this.minimap_circle.opacity = this.options.ghost_opacity;
+ } else {
+ this.minimap_circle.opacity = 1;
+ this.hidden = false;
+ this.redraw();
+ }
+
+ _.each(
+ this.project.get("edges").filter(
+ function (ed) {
+ return ((ed.get("to") === _this.model) || (ed.get("from") === _this.model));
+ }
+ ),
+ function(edge, index, list) {
+ var repr = _this.renderer.getRepresentationByModel(edge);
+ 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") {
+ repr.show(_this.ghost);
+ }
+ }
+ );
+ },
+ hideNeighbors: function(){
+ var _this = this;
+ _.each(
+ this.project.get("edges").filter(
+ function (ed) {
+ return (ed.get("from") === _this.model);
+ }
+ ),
+ function(edge, index, list) {
+ var repr = _this.renderer.getRepresentationByModel(edge.get("to"));
+ if (repr && repr.ghost) {
+ repr.hide();
+ }
+ }
+ );
+ },
+ showNeighbors: function(ghost){
+ var _this = this;
+ _.each(
+ this.project.get("edges").filter(
+ function (ed) {
+ return (ed.get("from") === _this.model);
+ }
+ ),
+ function(edge, index, list) {
+ var repr = _this.renderer.getRepresentationByModel(edge.get("to"));
+ if (repr && repr.hidden) {
+ repr.show(ghost);
+ if (!ghost){
+ var indexNode = _this.renderer.view.hiddenNodes.indexOf(repr.model.id);
+ if (indexNode !== -1){
+ _this.renderer.view.hiddenNodes.splice(indexNode, 1);
+ }
+ }
+ }
+ }
+ );
+ },
+ highlight: function(textToReplace) {
+ var hlvalue = textToReplace || true;
+ if (this.highlighted === hlvalue) {
+ return;
+ }
+ this.highlighted = hlvalue;
+ this.redraw();
+ this.renderer.throttledPaperDraw();
+ },
+ unhighlight: function() {
+ if (!this.highlighted) {
+ return;
+ }
+ this.highlighted = false;
+ this.redraw();
+ this.renderer.throttledPaperDraw();
+ },
+ saveCoords: function() {
+ var _coords = this.renderer.toModelCoords(this.paper_coords),
+ _data = {
+ position: {
+ x: _coords.x,
+ y: _coords.y
+ }
+ };
+ if (this.renderer.isEditable()) {
+ this.model.set(_data);
+ }
+ },
+ mousedown: function(_event, _isTouch) {
+ if (_isTouch) {
+ this.renderer.unselectAll();
+ this.select();
+ }
+ },
+ mouseup: function(_event, _isTouch) {
+ if (this.renderer.is_dragging && this.renderer.isEditable()) {
+ this.saveCoords();
+ } else {
+ if (this.hidden) {
+ var index = this.renderer.view.hiddenNodes.indexOf(this.model.id);
+ if (index !== -1){
+ this.renderer.view.hiddenNodes.splice(index, 1);
+ }
+ this.show(false);
+ this.select();
+ } else {
+ if (!_isTouch && !this.model.get("delete_scheduled")) {
+ this.openEditor();
+ }
+ this.model.trigger("clicked");
+ }
+ }
+ this.renderer.click_target = null;
+ this.renderer.is_dragging = false;
+ this.is_dragging = false;
+ },
+ destroy: function(_event) {
+ this._super("destroy");
+ this.all_buttons.forEach(function(b) {
+ b.destroy();
+ });
+ this.circle.remove();
+ this.title.remove();
+ if (this.renderer.minimap) {
+ this.minimap_circle.remove();
+ }
+ if (this.node_image) {
+ this.node_image.remove();
+ }
+ }
+ }).value();
+
+ return NodeRepr;
+
+});
+
+
+define('renderer/edge',['jquery', 'underscore', 'requtils', 'renderer/baserepresentation'], function ($, _, requtils, BaseRepresentation) {
+ 'use strict';
+
+ var Utils = requtils.getUtils();
+
+ /* Edge Class Begin */
+
+ //var Edge = Renderer.Edge = Utils.inherit(Renderer._BaseRepresentation);
+ var Edge = Utils.inherit(BaseRepresentation);
+
+ _(Edge.prototype).extend({
+ _init: function() {
+ this.renderer.edge_layer.activate();
+ this.type = "Edge";
+ this.hidden = false;
+ this.ghost = false;
+ this.from_representation = this.renderer.getRepresentationByModel(this.model.get("from"));
+ this.to_representation = this.renderer.getRepresentationByModel(this.model.get("to"));
+ this.bundle = this.renderer.addToBundles(this);
+ this.line = new paper.Path();
+ this.line.add([0,0],[0,0],[0,0]);
+ this.line.__representation = this;
+ this.line.strokeWidth = this.options.edge_stroke_width;
+ this.arrow_scale = 1;
+ this.arrow = new paper.Path();
+ this.arrow.add(
+ [ 0, 0 ],
+ [ this.options.edge_arrow_length, this.options.edge_arrow_width / 2 ],
+ [ 0, this.options.edge_arrow_width ]
+ );
+ this.arrow.pivot = new paper.Point([ this.options.edge_arrow_length / 2, this.options.edge_arrow_width / 2 ]);
+ this.arrow.__representation = this;
+ this.text = $('<div class="Rk-Label Rk-Edge-Label">').appendTo(this.renderer.labels_$);
+ this.arrow_angle = 0;
+ if (this.options.editor_mode) {
+ var Renderer = requtils.getRenderer();
+ this.normal_buttons = [
+ new Renderer.EdgeEditButton(this.renderer, null),
+ new Renderer.EdgeRemoveButton(this.renderer, null)
+ ];
+ this.pending_delete_buttons = [
+ new Renderer.EdgeRevertButton(this.renderer, null)
+ ];
+ this.all_buttons = this.normal_buttons.concat(this.pending_delete_buttons);
+ for (var i = 0; i < this.all_buttons.length; i++) {
+ this.all_buttons[i].source_representation = this;
+ }
+ this.active_buttons = [];
+ } else {
+ this.active_buttons = this.all_buttons = [];
+ }
+
+ if (this.renderer.minimap) {
+ this.renderer.minimap.edge_layer.activate();
+ this.minimap_line = new paper.Path();
+ this.minimap_line.add([0,0],[0,0]);
+ this.minimap_line.__representation = this.renderer.minimap.miniframe.__representation;
+ this.minimap_line.strokeWidth = 1;
+ }
+ },
+ _getStrokeWidth: function() {
+ var thickness = (this.model.has('style') && this.model.get('style').thickness) || 1;
+ return this.options.edge_stroke_width + (thickness-1) * (this.options.edge_stroke_max_width - this.options.edge_stroke_width) / (this.options.edge_stroke_witdh_scale-1);
+ },
+ _getSelectedStrokeWidth: function() {
+ var thickness = (this.model.has('style') && this.model.get('style').thickness) || 1;
+ return this.options.selected_edge_stroke_width + (thickness-1) * (this.options.selected_edge_stroke_max_width - this.options.selected_edge_stroke_width) / (this.options.edge_stroke_witdh_scale-1);
+ },
+ _getArrowScale: function() {
+ var thickness = (this.model.has('style') && this.model.get('style').thickness) || 1;
+ return 1 + (thickness-1) * ((this.options.edge_arrow_max_width / this.options.edge_arrow_width) - 1) / (this.options.edge_stroke_witdh_scale-1);
+ },
+ redraw: function() {
+ var from = this.model.get("from"),
+ to = this.model.get("to");
+ if (!from || !to || (this.hidden && !this.ghost)) {
+ return;
+ }
+ this.from_representation = this.renderer.getRepresentationByModel(from);
+ this.to_representation = this.renderer.getRepresentationByModel(to);
+ if (typeof this.from_representation === "undefined" || typeof this.to_representation === "undefined" ||
+ (this.from_representation.hidden && !this.from_representation.ghost) ||
+ (this.to_representation.hidden && !this.to_representation.ghost)) {
+ this.hide();
+ return;
+ }
+ var _strokeWidth = this._getStrokeWidth(),
+ _arrow_scale = this._getArrowScale(),
+ _p0a = this.from_representation.paper_coords,
+ _p1a = this.to_representation.paper_coords,
+ _v = _p1a.subtract(_p0a),
+ _r = _v.length,
+ _u = _v.divide(_r),
+ _ortho = new paper.Point([- _u.y, _u.x]),
+ _group_pos = this.bundle.getPosition(this),
+ _delta = _ortho.multiply( this.options.edge_gap_in_bundles * _group_pos ),
+ _p0b = _p0a.add(_delta), /* Adding a 4 px difference */
+ _p1b = _p1a.add(_delta), /* to differentiate bundled links */
+ _a = _v.angle,
+ _textdelta = _ortho.multiply(this.options.edge_label_distance + 0.5 * _arrow_scale * this.options.edge_arrow_width),
+ _handle = _v.divide(3),
+ _color = (this.model.has("style") && this.model.get("style").color) || (this.model.get("created_by") || Utils._USER_PLACEHOLDER(this.renkan)).get("color"),
+ _dash = (this.model.has("style") && this.model.get("style").dash) ? this.options.default_dash_array : null,
+ _opacity;
+
+ if (this.model.get("delete_scheduled") || this.from_representation.model.get("delete_scheduled") || this.to_representation.model.get("delete_scheduled")) {
+ _opacity = 0.5;
+ this.line.dashArray = [2, 2];
+ } else {
+ _opacity = this.ghost ? this.options.ghost_opacity : 1;
+ this.line.dashArray = null;
+ }
+
+ var old_act_btn = this.active_buttons;
+
+ this.arrow.visible =
+ (this.model.has("style") && this.model.get("style").arrow) ||
+ !this.model.has("style") ||
+ typeof this.model.get("style").arrow === 'undefined';
+
+ this.active_buttons = this.model.get("delete_scheduled") ? this.pending_delete_buttons : this.normal_buttons;
+
+ if (this.selected && this.renderer.isEditable() && old_act_btn !== this.active_buttons) {
+ old_act_btn.forEach(function(b) {
+ b.hide();
+ });
+ this.active_buttons.forEach(function(b) {
+ b.show();
+ });
+ }
+
+ this.paper_coords = _p0b.add(_p1b).divide(2);
+ this.line.strokeWidth = _strokeWidth;
+ this.line.strokeColor = _color;
+ this.line.dashArray = _dash;
+ this.line.opacity = _opacity;
+ this.line.segments[0].point = _p0a;
+ this.line.segments[1].point = this.paper_coords;
+ this.line.segments[1].handleIn = _handle.multiply(-1);
+ this.line.segments[1].handleOut = _handle;
+ this.line.segments[2].point = _p1a;
+ this.arrow.scale(_arrow_scale / this.arrow_scale);
+ this.arrow_scale = _arrow_scale;
+ this.arrow.fillColor = _color;
+ this.arrow.opacity = _opacity;
+ this.arrow.rotate(_a - this.arrow_angle, this.arrow.bounds.center);
+ this.arrow.position = this.paper_coords;
+
+ this.arrow_angle = _a;
+ if (_a > 90) {
+ _a -= 180;
+ _textdelta = _textdelta.multiply(-1);
+ }
+ if (_a < -90) {
+ _a += 180;
+ _textdelta = _textdelta.multiply(-1);
+ }
+ var _text = this.model.get("title") || this.renkan.translate(this.options.label_untitled_edges) || "";
+ _text = Utils.shortenText(_text, this.options.node_label_max_length);
+ this.text.text(_text);
+ var _textpos = this.paper_coords.add(_textdelta);
+ this.text.css({
+ left: _textpos.x,
+ top: _textpos.y,
+ transform: "rotate(" + _a + "deg)",
+ "-moz-transform": "rotate(" + _a + "deg)",
+ "-webkit-transform": "rotate(" + _a + "deg)",
+ opacity: _opacity
+ });
+ this.text_angle = _a;
+
+ var _pc = this.paper_coords;
+ this.all_buttons.forEach(function(b) {
+ b.moveTo(_pc);
+ });
+
+ if (this.renderer.minimap) {
+ this.minimap_line.strokeColor = _color;
+ this.minimap_line.segments[0].point = this.renderer.toMinimapCoords(new paper.Point(this.from_representation.model.get("position")));
+ this.minimap_line.segments[1].point = this.renderer.toMinimapCoords(new paper.Point(this.to_representation.model.get("position")));
+ }
+ },
+ hide: function(){
+ this.hidden = true;
+ this.ghost = false;
+
+ this.text.hide();
+ this.line.visible = false;
+ this.arrow.visible = false;
+ this.minimap_line.visible = false;
+ },
+ show: function(ghost){
+ this.ghost = ghost;
+ if (this.ghost) {
+ this.text.css('opacity', 0.3);
+ this.line.opacity = 0.3;
+ this.arrow.opacity = 0.3;
+ this.minimap_line.opacity = 0.3;
+ } else {
+ this.hidden = false;
+
+ this.text.css('opacity', 1);
+ this.line.opacity = 1;
+ this.arrow.opacity = 1;
+ this.minimap_line.opacity = 1;
+ }
+ this.text.show();
+ this.line.visible = true;
+ this.arrow.visible = true;
+ this.minimap_line.visible = true;
+ this.redraw();
+ },
+ openEditor: function() {
+ this.renderer.removeRepresentationsOfType("editor");
+ var _editor = this.renderer.addRepresentation("EdgeEditor",null);
+ _editor.source_representation = this;
+ _editor.draw();
+ },
+ select: function() {
+ this.selected = true;
+ this.line.strokeWidth = this._getSelectedStrokeWidth();
+ if (this.renderer.isEditable()) {
+ this.active_buttons.forEach(function(b) {
+ b.show();
+ });
+ }
+ if (!this.options.editor_mode) {
+ this.openEditor();
+ }
+ this._super("select");
+ },
+ unselect: function(_newTarget) {
+ if (!_newTarget || _newTarget.source_representation !== this) {
+ this.selected = false;
+ if (this.options.editor_mode) {
+ this.all_buttons.forEach(function(b) {
+ b.hide();
+ });
+ }
+ this.line.strokeWidth = this._getStrokeWidth();
+ this._super("unselect");
+ }
+ },
+ mousedown: function(_event, _isTouch) {
+ if (_isTouch) {
+ this.renderer.unselectAll();
+ this.select();
+ }
+ },
+ mouseup: function(_event, _isTouch) {
+ if (!this.renkan.read_only && this.renderer.is_dragging) {
+ this.from_representation.saveCoords();
+ this.to_representation.saveCoords();
+ this.from_representation.is_dragging = false;
+ this.to_representation.is_dragging = false;
+ } else {
+ if (!_isTouch) {
+ this.openEditor();
+ }
+ this.model.trigger("clicked");
+ }
+ this.renderer.click_target = null;
+ this.renderer.is_dragging = false;
+ },
+ paperShift: function(_delta) {
+ if (this.options.editor_mode) {
+ if (!this.options.read_only) {
+ this.from_representation.paperShift(_delta);
+ this.to_representation.paperShift(_delta);
+ }
+ } else {
+ this.renderer.paperShift(_delta);
+ }
+ },
+ destroy: function() {
+ this._super("destroy");
+ this.line.remove();
+ this.arrow.remove();
+ this.text.remove();
+ if (this.renderer.minimap) {
+ this.minimap_line.remove();
+ }
+ this.all_buttons.forEach(function(b) {
+ b.destroy();
+ });
+ var _this = this;
+ this.bundle.edges = _.reject(this.bundle.edges, function(_edge) {
+ return _this === _edge;
+ });
+ }
+ }).value();
+
+ return Edge;
+
+});
+
+
+
+define('renderer/tempedge',['jquery', 'underscore', 'requtils', 'renderer/baserepresentation'], function ($, _, requtils, BaseRepresentation) {
+ 'use strict';
+
+ var Utils = requtils.getUtils();
+
+ /* TempEdge Class Begin */
+
+ //var TempEdge = Renderer.TempEdge = Utils.inherit(Renderer._BaseRepresentation);
+ var TempEdge = Utils.inherit(BaseRepresentation);
+
+ _(TempEdge.prototype).extend({
+ _init: function() {
+ this.renderer.edge_layer.activate();
+ this.type = "Temp-edge";
+
+ var _color = (this.project.get("users").get(this.renkan.current_user) || Utils._USER_PLACEHOLDER(this.renkan)).get("color");
+ this.line = new paper.Path();
+ this.line.strokeColor = _color;
+ this.line.dashArray = [4, 2];
+ this.line.strokeWidth = this.options.selected_edge_stroke_width;
+ this.line.add([0,0],[0,0]);
+ this.line.__representation = this;
+ this.arrow = new paper.Path();
+ this.arrow.fillColor = _color;
+ this.arrow.add(
+ [ 0, 0 ],
+ [ this.options.edge_arrow_length, this.options.edge_arrow_width / 2 ],
+ [ 0, this.options.edge_arrow_width ]
+ );
+ this.arrow.__representation = this;
+ this.arrow_angle = 0;
+ },
+ redraw: function() {
+ var _p0 = this.from_representation.paper_coords,
+ _p1 = this.end_pos,
+ _a = _p1.subtract(_p0).angle,
+ _c = _p0.add(_p1).divide(2);
+ this.line.segments[0].point = _p0;
+ this.line.segments[1].point = _p1;
+ this.arrow.rotate(_a - this.arrow_angle);
+ this.arrow.position = _c;
+ this.arrow_angle = _a;
+ },
+ paperShift: function(_delta) {
+ if (!this.renderer.isEditable()) {
+ this.renderer.removeRepresentation(_this);
+ paper.view.draw();
+ return;
+ }
+ this.end_pos = this.end_pos.add(_delta);
+ var _hitResult = paper.project.hitTest(this.end_pos);
+ this.renderer.findTarget(_hitResult);
+ this.redraw();
+ },
+ mouseup: function(_event, _isTouch) {
+ var _hitResult = paper.project.hitTest(_event.point),
+ _model = this.from_representation.model,
+ _endDrag = true;
+ if (_hitResult && typeof _hitResult.item.__representation !== "undefined") {
+ var _target = _hitResult.item.__representation;
+ if (_target.type.substr(0,4) === "Node") {
+ var _destmodel = _target.model || _target.source_representation.model;
+ if (_model !== _destmodel) {
+ var _data = {
+ id: Utils.getUID('edge'),
+ created_by: this.renkan.current_user,
+ from: _model,
+ to: _destmodel
+ };
+ if (this.renderer.isEditable()) {
+ this.project.addEdge(_data);
+ }
+ }
+ }
+
+ if (_model === _target.model || (_target.source_representation && _target.source_representation.model === _model)) {
+ _endDrag = false;
+ this.renderer.is_dragging = true;
+ }
+ }
+ if (_endDrag) {
+ this.renderer.click_target = null;
+ this.renderer.is_dragging = false;
+ this.renderer.removeRepresentation(this);
+ paper.view.draw();
+ }
+ },
+ destroy: function() {
+ this.arrow.remove();
+ this.line.remove();
+ }
+ }).value();
+
+ /* TempEdge Class End */
+
+ return TempEdge;
+
+});
+
+
+define('renderer/baseeditor',['jquery', 'underscore', 'requtils', 'renderer/baserepresentation'], function ($, _, requtils, BaseRepresentation) {
+ 'use strict';
+
+ var Utils = requtils.getUtils();
+
+ /* _BaseEditor Begin */
+ //var _BaseEditor = Renderer._BaseEditor = Utils.inherit(Renderer._BaseRepresentation);
+ var _BaseEditor = Utils.inherit(BaseRepresentation);
+
+ _(_BaseEditor.prototype).extend({
+ _init: function() {
+ this.renderer.buttons_layer.activate();
+ this.type = "editor";
+ this.editor_block = new paper.Path();
+ var _pts = _.map(_.range(8), function() {return [0,0];});
+ this.editor_block.add.apply(this.editor_block, _pts);
+ this.editor_block.strokeWidth = this.options.tooltip_border_width;
+ this.editor_block.strokeColor = this.options.tooltip_border_color;
+ this.editor_block.opacity = this.options.tooltip_opacity;
+ this.editor_$ = $('<div>')
+ .appendTo(this.renderer.editor_$)
+ .css({
+ position: "absolute",
+ opacity: this.options.tooltip_opacity
+ })
+ .hide();
+ },
+ destroy: function() {
+ this.editor_block.remove();
+ this.editor_$.remove();
+ }
+ }).value();
+
+ /* _BaseEditor End */
+
+ return _BaseEditor;
+
+});
+
+
+define('renderer/nodeeditor',['jquery', 'underscore', 'requtils', 'renderer/baseeditor', 'renderer/shapebuilder', 'ckeditor-jquery'], function ($, _, requtils, BaseEditor, ShapeBuilder) {
+ 'use strict';
+
+ var Utils = requtils.getUtils();
+
+ /* NodeEditor Begin */
+ //var NodeEditor = Renderer.NodeEditor = Utils.inherit(Renderer._BaseEditor);
+ var NodeEditor = Utils.inherit(BaseEditor);
+
+ _(NodeEditor.prototype).extend({
+ _init: function() {
+ BaseEditor.prototype._init.apply(this);
+ this.template = this.options.templates['templates/nodeeditor.html'];
+ //this.templates['default']= this.options.templates['templates/nodeeditor.html'];
+ //fusionner avec this.options.node_editor_templates
+ this.readOnlyTemplate = this.options.node_editor_templates;
+ },
+ draw: function() {
+ var _model = this.source_representation.model,
+ _created_by = _model.get("created_by") || Utils._USER_PLACEHOLDER(this.renkan),
+ _template = (this.renderer.isEditable() ? this.template : this.readOnlyTemplate[_model.get("type")] || this.readOnlyTemplate["default"]),
+ _image_placeholder = this.options.static_url + "img/image-placeholder.png",
+ _size = (_model.get("size") || 0);
+ this.editor_$
+ .html(_template({
+ node: {
+ _id: _model.get("_id"),
+ has_creator: !!_model.get("created_by"),
+ title: _model.get("title"),
+ uri: _model.get("uri"),
+ type: _model.get("type") || "default",
+ short_uri: Utils.shortenText((_model.get("uri") || "").replace(/^(https?:\/\/)?(www\.)?/,'').replace(/\/$/,''),40),
+ description: _model.get("description"),
+ image: _model.get("image") || "",
+ image_placeholder: _image_placeholder,
+ color: (_model.has("style") && _model.get("style").color) || _created_by.get("color"),
+ thickness: (_model.has("style") && _model.get("style").thickness) || 1,
+ dash: _model.has("style") && _model.get("style").dash ? "checked" : "",
+ clip_path: _model.get("clip_path") || false,
+ created_by_color: _created_by.get("color"),
+ created_by_title: _created_by.get("title"),
+ size: (_size > 0 ? "+" : "") + _size,
+ shape: _model.get("shape") || "circle"
+ },
+ renkan: this.renkan,
+ options: this.options,
+ shortenText: Utils.shortenText,
+ shapes : _(ShapeBuilder.builders).omit('svg').keys().value(),
+ types : _(this.options.node_editor_templates).keys().value(),
+ }));
+ this.redraw();
+ var _this = this,
+ editorInstance = _this.options.show_node_editor_description_richtext ?
+ $(".Rk-Edit-Description").ckeditor(_this.options.richtext_editor_config) :
+ false,
+ closeEditor = function() {
+ _this.renderer.removeRepresentation(_this);
+ paper.view.draw();
+ };
+
+ _this.cleanEditor = function() {
+ _this.editor_$.off("keyup");
+ _this.editor_$.find("input, textarea, select").off("change keyup paste");
+ _this.editor_$.find(".Rk-Edit-Image-File").off('change');
+ _this.editor_$.find(".Rk-Edit-ColorPicker-Wrapper").off('hover');
+ _this.editor_$.find(".Rk-Edit-Size-Btn").off('click');
+ _this.editor_$.find(".Rk-Edit-Image-Del").off('click');
+ _this.editor_$.find(".Rk-Edit-ColorPicker").find("li").off('hover click');
+ _this.editor_$.find(".Rk-CloseX").off('click');
+ _this.editor_$.find(".Rk-Edit-Goto").off('click');
+
+ if(_this.options.show_node_editor_description_richtext) {
+ if(typeof editorInstance.editor !== 'undefined') {
+ var _editor = editorInstance.editor;
+ delete editorInstance.editor;
+ _editor.focusManager.blur(true);
+ _editor.destroy();
+ }
+ }
+ };
+
+ this.editor_$.find(".Rk-CloseX").click(function (e) {
+ e.preventDefault();
+ closeEditor();
+ });
+
+ this.editor_$.find(".Rk-Edit-Goto").click(function() {
+ if (!_model.get("uri")) {
+ return false;
+ }
+ });
+
+ if (this.renderer.isEditable()) {
+
+ var onFieldChange = _.throttle(function() {
+ _.defer(function() {
+ if (_this.renderer.isEditable()) {
+ var _data = {
+ title: _this.editor_$.find(".Rk-Edit-Title").val()
+ };
+ if (_this.options.show_node_editor_uri) {
+ _data.uri = _this.editor_$.find(".Rk-Edit-URI").val();
+ _this.editor_$.find(".Rk-Edit-Goto").attr("href",_data.uri || "#");
+ }
+ if (_this.options.show_node_editor_image) {
+ _data.image = _this.editor_$.find(".Rk-Edit-Image").val();
+ _this.editor_$.find(".Rk-Edit-ImgPreview").attr("src", _data.image || _image_placeholder);
+ }
+ if (_this.options.show_node_editor_description) {
+ if(_this.options.show_node_editor_description_richtext) {
+ if(typeof editorInstance.editor !== 'undefined' &&
+ editorInstance.editor.checkDirty()) {
+ _data.description = editorInstance.editor.getData();
+ editorInstance.editor.resetDirty();
+ }
+ }
+ else {
+ _data.description = _this.editor_$.find(".Rk-Edit-Description").val();
+ }
+ }
+ if (_this.options.show_node_editor_style) {
+ var dash = _this.editor_$.find(".Rk-Edit-Dash").is(':checked');
+ _data.style = _.assign( ((_model.has("style") && _.clone(_model.get("style"))) || {}), {dash: dash});
+ }
+ if (_this.options.change_shapes) {
+ if(_model.get("shape")!==_this.editor_$.find(".Rk-Edit-Shape").val()){
+ _data.shape = _this.editor_$.find(".Rk-Edit-Shape").val();
+ }
+ }
+ if (_this.options.change_types) {
+ if(_model.get("type")!==_this.editor_$.find(".Rk-Edit-Type").val()){
+ _data.type = _this.editor_$.find(".Rk-Edit-Type").val();
+ }
+ }
+ _model.set(_data);
+ _this.redraw();
+ } else {
+ closeEditor();
+ }
+ });
+ }, 1000);
+
+ this.editor_$.on("keyup", function(_e) {
+ if (_e.keyCode === 27) {
+ closeEditor();
+ }
+ });
+
+ this.editor_$.find("input, textarea, select").on("change keyup paste", onFieldChange);
+ if( _this.options.show_node_editor_description &&
+ _this.options.show_node_editor_description_richtext &&
+ typeof editorInstance.editor !== 'undefined')
+ {
+ editorInstance.editor.on("change", onFieldChange);
+ editorInstance.editor.on("blur", onFieldChange);
+ }
+
+ if(_this.options.allow_image_upload) {
+ this.editor_$.find(".Rk-Edit-Image-File").change(function() {
+ if (this.files.length) {
+ var f = this.files[0],
+ fr = new FileReader();
+ if (f.type.substr(0,5) !== "image") {
+ alert(_this.renkan.translate("This file is not an image"));
+ return;
+ }
+ if (f.size > (_this.options.uploaded_image_max_kb * 1024)) {
+ alert(_this.renkan.translate("Image size must be under ") + _this.options.uploaded_image_max_kb + _this.renkan.translate("KB"));
+ return;
+ }
+ fr.onload = function(e) {
+ _this.editor_$.find(".Rk-Edit-Image").val(e.target.result);
+ onFieldChange();
+ };
+ fr.readAsDataURL(f);
+ }
+ });
+ }
+ this.editor_$.find(".Rk-Edit-Title")[0].focus();
+
+ var _picker = _this.editor_$.find(".Rk-Edit-ColorPicker");
+
+ this.editor_$.find(".Rk-Edit-ColorPicker-Wrapper").hover(
+ function(_e) {
+ _e.preventDefault();
+ _picker.show();
+ },
+ function(_e) {
+ _e.preventDefault();
+ _picker.hide();
+ }
+ );
+
+ _picker.find("li").hover(
+ function(_e) {
+ _e.preventDefault();
+ _this.editor_$.find(".Rk-Edit-Color").css("background", $(this).attr("data-color"));
+ },
+ function(_e) {
+ _e.preventDefault();
+ _this.editor_$.find(".Rk-Edit-Color").css("background", (_model.has("style") && _model.get("style").color) || (_model.get("created_by") || Utils._USER_PLACEHOLDER(_this.renkan)).get("color"));
+ }
+ ).click(function(_e) {
+ _e.preventDefault();
+ if (_this.renderer.isEditable()) {
+ _model.set("style", _.assign( ((_model.has("style") && _.clone(_model.get("style"))) || {}), {color: $(this).attr("data-color")}));
+ _picker.hide();
+ paper.view.draw();
+ } else {
+ closeEditor();
+ }
+ });
+
+ var shiftSize = function(n) {
+ if (_this.renderer.isEditable()) {
+ var _newsize = n+(_model.get("size") || 0);
+ _this.editor_$.find("#Rk-Edit-Size-Value").text((_newsize > 0 ? "+" : "") + _newsize);
+ _model.set("size", _newsize);
+ paper.view.draw();
+ } else {
+ closeEditor();
+ }
+ };
+
+ this.editor_$.find("#Rk-Edit-Size-Down").click(function() {
+ shiftSize(-1);
+ return false;
+ });
+ this.editor_$.find("#Rk-Edit-Size-Up").click(function() {
+ shiftSize(1);
+ return false;
+ });
+
+ var shiftThickness = function(n) {
+ if (_this.renderer.isEditable()) {
+ var _oldThickness = ((_model.has('style') && _model.get('style').thickness) || 1),
+ _newThickness = n + _oldThickness;
+ if(_newThickness < 1 ) {
+ _newThickness = 1;
+ }
+ else if (_newThickness > _this.options.node_stroke_witdh_scale) {
+ _newThickness = _this.options.node_stroke_witdh_scale;
+ }
+ if (_newThickness !== _oldThickness) {
+ _this.editor_$.find("#Rk-Edit-Thickness-Value").text(_newThickness);
+ _model.set("style", _.assign( ((_model.has("style") && _.clone(_model.get("style"))) || {}), {thickness: _newThickness}));
+ paper.view.draw();
+ }
+ }
+ else {
+ closeEditor();
+ }
+ };
+
+ this.editor_$.find("#Rk-Edit-Thickness-Down").click(function() {
+ shiftThickness(-1);
+ return false;
+ });
+ this.editor_$.find("#Rk-Edit-Thickness-Up").click(function() {
+ shiftThickness(1);
+ return false;
+ });
+
+ this.editor_$.find(".Rk-Edit-Image-Del").click(function() {
+ _this.editor_$.find(".Rk-Edit-Image").val('');
+ onFieldChange();
+ return false;
+ });
+ } else {
+ if (typeof this.source_representation.highlighted === "object") {
+ var titlehtml = this.source_representation.highlighted.replace(_(_model.get("title")).escape(),'<span class="Rk-Highlighted">$1</span>');
+ this.editor_$.find(".Rk-Display-Title" + (_model.get("uri") ? " a" : "")).html(titlehtml);
+ if (this.options.show_node_tooltip_description) {
+ this.editor_$.find(".Rk-Display-Description").html(this.source_representation.highlighted.replace(_(_model.get("description")).escape(),'<span class="Rk-Highlighted">$1</span>'));
+ }
+ }
+ }
+ this.editor_$.find("img").load(function() {
+ _this.redraw();
+ });
+ },
+ redraw: function() {
+ if (this.options.popup_editor){
+ var _coords = this.source_representation.paper_coords;
+ Utils.drawEditBox(this.options, _coords, this.editor_block, this.source_representation.circle_radius * 0.75, this.editor_$);
+ }
+ this.editor_$.show();
+ paper.view.draw();
+ },
+ destroy: function() {
+ if(typeof this.cleanEditor !== 'undefined') {
+ this.cleanEditor();
+ }
+ this.editor_block.remove();
+ this.editor_$.remove();
+ }
+ }).value();
+
+ /* NodeEditor End */
+
+ return NodeEditor;
+
+});
+
+
+define('renderer/edgeeditor',['jquery', 'underscore', 'requtils', 'renderer/baseeditor'], function ($, _, requtils, BaseEditor) {
+ 'use strict';
+
+ var Utils = requtils.getUtils();
+
+ /* EdgeEditor Begin */
+
+ //var EdgeEditor = Renderer.EdgeEditor = Utils.inherit(Renderer._BaseEditor);
+ var EdgeEditor = Utils.inherit(BaseEditor);
+
+ _(EdgeEditor.prototype).extend({
+ _init: function() {
+ BaseEditor.prototype._init.apply(this);
+ this.template = this.options.templates['templates/edgeeditor.html'];
+ this.readOnlyTemplate = this.options.templates['templates/edgeeditor_readonly.html'];
+ },
+ draw: function() {
+ var _model = this.source_representation.model,
+ _from_model = _model.get("from"),
+ _to_model = _model.get("to"),
+ _created_by = _model.get("created_by") || Utils._USER_PLACEHOLDER(this.renkan),
+ _template = (this.renderer.isEditable() ? this.template : this.readOnlyTemplate);
+ this.editor_$
+ .html(_template({
+ edge: {
+ has_creator: !!_model.get("created_by"),
+ title: _model.get("title"),
+ uri: _model.get("uri"),
+ short_uri: Utils.shortenText((_model.get("uri") || "").replace(/^(https?:\/\/)?(www\.)?/,'').replace(/\/$/,''),40),
+ description: _model.get("description"),
+ color: (_model.has("style") && _model.get("style").color) || _created_by.get("color"),
+ dash: _model.has("style") && _model.get("style").dash ? "checked" : "",
+ arrow: (_model.has("style") && _model.get("style").arrow) || !_model.has("style") || (typeof _model.get("style").arrow === 'undefined') ? "checked" : "",
+ thickness: (_model.has("style") && _model.get("style").thickness) || 1,
+ from_title: _from_model.get("title"),
+ to_title: _to_model.get("title"),
+ from_color: (_from_model.has("style") && _from_model.get("style").color) || (_from_model.get("created_by") || Utils._USER_PLACEHOLDER(this.renkan)).get("color"),
+ to_color: (_to_model.has("style") && _to_model.get("style").color) || (_to_model.get("created_by") || Utils._USER_PLACEHOLDER(this.renkan)).get("color"),
+ created_by_color: _created_by.get("color"),
+ created_by_title: _created_by.get("title")
+ },
+ renkan: this.renkan,
+ shortenText: Utils.shortenText,
+ options: this.options
+ }));
+ this.redraw();
+ var _this = this,
+ closeEditor = function() {
+ _this.renderer.removeRepresentation(_this);
+ _this.editor_$.find(".Rk-Edit-Size-Btn").off('click');
+ paper.view.draw();
+ };
+ this.editor_$.find(".Rk-CloseX").click(closeEditor);
+ this.editor_$.find(".Rk-Edit-Goto").click(function() {
+ if (!_model.get("uri")) {
+ return false;
+ }
+ });
+
+ if (this.renderer.isEditable()) {
+
+ var onFieldChange = _.throttle(function() {
+ _.defer(function() {
+ if (_this.renderer.isEditable()) {
+ var _data = {
+ title: _this.editor_$.find(".Rk-Edit-Title").val()
+ };
+ if (_this.options.show_edge_editor_uri) {
+ _data.uri = _this.editor_$.find(".Rk-Edit-URI").val();
+ }
+ if (_this.options.show_node_editor_style) {
+ var dash = _this.editor_$.find(".Rk-Edit-Dash").is(':checked'),
+ arrow = _this.editor_$.find(".Rk-Edit-Arrow").is(':checked');
+ _data.style = _.assign( ((_model.has("style") && _.clone(_model.get("style"))) || {}), {dash: dash, arrow: arrow});
+ }
+ _this.editor_$.find(".Rk-Edit-Goto").attr("href",_data.uri || "#");
+ _model.set(_data);
+ paper.view.draw();
+ } else {
+ closeEditor();
+ }
+ });
+ },500);
+
+ this.editor_$.on("keyup", function(_e) {
+ if (_e.keyCode === 27) {
+ closeEditor();
+ }
+ });
+
+ this.editor_$.find("input").on("keyup change paste", onFieldChange);
+
+ this.editor_$.find(".Rk-Edit-Vocabulary").change(function() {
+ var e = $(this),
+ v = e.val();
+ if (v) {
+ _this.editor_$.find(".Rk-Edit-Title").val(e.find(":selected").text());
+ _this.editor_$.find(".Rk-Edit-URI").val(v);
+ onFieldChange();
+ }
+ });
+ this.editor_$.find(".Rk-Edit-Direction").click(function() {
+ if (_this.renderer.isEditable()) {
+ _model.set({
+ from: _model.get("to"),
+ to: _model.get("from")
+ });
+ _this.draw();
+ } else {
+ closeEditor();
+ }
+ });
+
+ var _picker = _this.editor_$.find(".Rk-Edit-ColorPicker");
+
+ this.editor_$.find(".Rk-Edit-ColorPicker-Wrapper").hover(
+ function(_e) {
+ _e.preventDefault();
+ _picker.show();
+ },
+ function(_e) {
+ _e.preventDefault();
+ _picker.hide();
+ }
+ );
+
+ _picker.find("li").hover(
+ function(_e) {
+ _e.preventDefault();
+ _this.editor_$.find(".Rk-Edit-Color").css("background", $(this).attr("data-color"));
+ },
+ function(_e) {
+ _e.preventDefault();
+ _this.editor_$.find(".Rk-Edit-Color").css("background", (_model.has("style") && _model.get("style").color)|| (_model.get("created_by") || Utils._USER_PLACEHOLDER(_this.renkan)).get("color"));
+ }
+ ).click(function(_e) {
+ _e.preventDefault();
+ if (_this.renderer.isEditable()) {
+ _model.set("style", _.assign( ((_model.has("style") && _.clone(_model.get("style"))) || {}), {color: $(this).attr("data-color")}));
+ _picker.hide();
+ paper.view.draw();
+ } else {
+ closeEditor();
+ }
+ });
+ var shiftThickness = function(n) {
+ if (_this.renderer.isEditable()) {
+ var _oldThickness = ((_model.has('style') && _model.get('style').thickness) || 1),
+ _newThickness = n + _oldThickness;
+ if(_newThickness < 1 ) {
+ _newThickness = 1;
+ }
+ else if (_newThickness > _this.options.node_stroke_witdh_scale) {
+ _newThickness = _this.options.node_stroke_witdh_scale;
+ }
+ if (_newThickness !== _oldThickness) {
+ _this.editor_$.find("#Rk-Edit-Thickness-Value").text(_newThickness);
+ _model.set("style", _.assign( ((_model.has("style") && _.clone(_model.get("style"))) || {}), {thickness: _newThickness}));
+ paper.view.draw();
+ }
+ }
+ else {
+ closeEditor();
+ }
+ };
+
+ this.editor_$.find("#Rk-Edit-Thickness-Down").click(function() {
+ shiftThickness(-1);
+ return false;
+ });
+ this.editor_$.find("#Rk-Edit-Thickness-Up").click(function() {
+ shiftThickness(1);
+ return false;
+ });
+ }
+ },
+ redraw: function() {
+ if (this.options.popup_editor){
+ var _coords = this.source_representation.paper_coords;
+ Utils.drawEditBox(this.options, _coords, this.editor_block, 5, this.editor_$);
+ }
+ this.editor_$.show();
+ paper.view.draw();
+ }
+ }).value();
+
+ /* EdgeEditor End */
+
+ return EdgeEditor;
+
+});
+
+
+define('renderer/nodebutton',['jquery', 'underscore', 'requtils', 'renderer/basebutton'], function ($, _, requtils, BaseButton) {
+ 'use strict';
+
+ var Utils = requtils.getUtils();
+
+ /* _NodeButton Begin */
+
+ //var _NodeButton = Renderer._NodeButton = Utils.inherit(Renderer._BaseButton);
+ var _NodeButton = Utils.inherit(BaseButton);
+
+ _(_NodeButton.prototype).extend({
+ setSectorSize: function() {
+ var sectorInner = this.source_representation.circle_radius;
+ if (sectorInner !== this.lastSectorInner) {
+ if (this.sector) {
+ this.sector.destroy();
+ }
+ this.sector = this.renderer.drawSector(
+ this, 1 + sectorInner,
+ Utils._NODE_BUTTON_WIDTH + sectorInner,
+ this.startAngle,
+ this.endAngle,
+ 1,
+ this.imageName,
+ this.renkan.translate(this.text)
+ );
+ this.lastSectorInner = sectorInner;
+ }
+ },
+ unselect: function() {
+ BaseButton.prototype.unselect.apply(this, Array.prototype.slice.call(arguments, 1));
+ if(this.source_representation && this.source_representation.buttons_timeout) {
+ clearTimeout(this.source_representation.buttons_timeout);
+ this.source_representation.hideButtons();
+ }
+ },
+ select: function() {
+ if(this.source_representation && this.source_representation.buttons_timeout) {
+ clearTimeout(this.source_representation.buttons_timeout);
+ }
+ this.sector.select();
+ },
+ }).value();
+
+
+ /* _NodeButton End */
+
+ return _NodeButton;
+
+});
+
+
+define('renderer/nodeeditbutton',['jquery', 'underscore', 'requtils', 'renderer/nodebutton'], function ($, _, requtils, NodeButton) {
+ 'use strict';
+
+ var Utils = requtils.getUtils();
+
+ /* NodeEditButton Begin */
+
+ //var NodeEditButton = Renderer.NodeEditButton = Utils.inherit(Renderer._NodeButton);
+ var NodeEditButton = Utils.inherit(NodeButton);
+
+ _(NodeEditButton.prototype).extend({
+ _init: function() {
+ this.type = "Node-edit-button";
+ this.lastSectorInner = 0;
+ this.startAngle = this.options.hide_nodes ? -125 : -135;
+ this.endAngle = this.options.hide_nodes ? -55 : -45;
+ this.imageName = "edit";
+ this.text = "Edit";
+ },
+ mouseup: function() {
+ if (!this.renderer.is_dragging) {
+ this.source_representation.openEditor();
+ }
+ }
+ }).value();
+
+ /* NodeEditButton End */
+
+ return NodeEditButton;
+
+});
+
+
+define('renderer/noderemovebutton',['jquery', 'underscore', 'requtils', 'renderer/nodebutton'], function ($, _, requtils, NodeButton) {
+ 'use strict';
+
+ var Utils = requtils.getUtils();
+
+ /* NodeRemoveButton Begin */
+
+ //var NodeRemoveButton = Renderer.NodeRemoveButton = Utils.inherit(Renderer._NodeButton);
+ var NodeRemoveButton = Utils.inherit(NodeButton);
+
+ _(NodeRemoveButton.prototype).extend({
+ _init: function() {
+ this.type = "Node-remove-button";
+ this.lastSectorInner = 0;
+ this.startAngle = this.options.hide_nodes ? -10 : 0;
+ this.endAngle = this.options.hide_nodes ? 45 : 90;
+ this.imageName = "remove";
+ this.text = "Remove";
+ },
+ mouseup: function() {
+ this.renderer.click_target = null;
+ this.renderer.is_dragging = false;
+ this.renderer.removeRepresentationsOfType("editor");
+ if (this.renderer.isEditable()) {
+ if (this.options.element_delete_delay) {
+ var delid = Utils.getUID("delete");
+ this.renderer.delete_list.push({
+ id: delid,
+ time: new Date().valueOf() + this.options.element_delete_delay
+ });
+ this.source_representation.model.set("delete_scheduled", delid);
+ } else {
+ if (confirm(this.renkan.translate('Do you really wish to remove node ') + '"' + this.source_representation.model.get("title") + '"?')) {
+ this.project.removeNode(this.source_representation.model);
+ }
+ }
+ }
+ }
+ }).value();
+
+ /* NodeRemoveButton End */
+
+ return NodeRemoveButton;
+
+});
+
+
+define('renderer/nodehidebutton',['jquery', 'underscore', 'requtils', 'renderer/nodebutton'], function ($, _, requtils, NodeButton) {
+ 'use strict';
+
+ var Utils = requtils.getUtils();
+
+ /* NodeRemoveButton Begin */
+
+ //var NodeRemoveButton = Renderer.NodeRemoveButton = Utils.inherit(Renderer._NodeButton);
+ var NodeHideButton = Utils.inherit(NodeButton);
+
+ _(NodeHideButton.prototype).extend({
+ _init: function() {
+ this.type = "Node-hide-button";
+ this.lastSectorInner = 0;
+ this.startAngle = 45;
+ this.endAngle = 90;
+ this.imageName = "hide";
+ this.text = "Hide";
+ },
+ mouseup: function() {
+ this.renderer.click_target = null;
+ this.renderer.is_dragging = false;
+ this.renderer.removeRepresentationsOfType("editor");
+ if (this.renderer.isEditable()) {
+ this.renderer.view.addHiddenNode(this.source_representation.model);
+ }
+ }
+ }).value();
+
+ /* NodeRemoveButton End */
+
+ return NodeHideButton;
+
+});
+
+
+define('renderer/nodeshowbutton',['jquery', 'underscore', 'requtils', 'renderer/nodebutton'], function ($, _, requtils, NodeButton) {
+ 'use strict';
+
+ var Utils = requtils.getUtils();
+
+ /* NodeRemoveButton Begin */
+
+ //var NodeRemoveButton = Renderer.NodeRemoveButton = Utils.inherit(Renderer._NodeButton);
+ var NodeShowButton = Utils.inherit(NodeButton);
+
+ _(NodeShowButton.prototype).extend({
+ _init: function() {
+ this.type = "Node-show-button";
+ this.lastSectorInner = 0;
+ this.startAngle = 90;
+ this.endAngle = 135;
+ this.imageName = "show";
+ this.text = "Show";
+ },
+ mouseup: function() {
+ this.renderer.click_target = null;
+ this.renderer.is_dragging = false;
+ this.renderer.removeRepresentationsOfType("editor");
+ if (this.renderer.isEditable()) {
+ this.source_representation.showNeighbors(false);
+ }
+ }
+ }).value();
+
+ /* NodeShowButton End */
+
+ return NodeShowButton;
+
+});
+
+
+define('renderer/noderevertbutton',['jquery', 'underscore', 'requtils', 'renderer/nodebutton'], function ($, _, requtils, NodeButton) {
+ 'use strict';
+
+ var Utils = requtils.getUtils();
+
+ /* NodeRevertButton Begin */
+
+ //var NodeRevertButton = Renderer.NodeRevertButton = Utils.inherit(Renderer._NodeButton);
+ var NodeRevertButton = Utils.inherit(NodeButton);
+
+ _(NodeRevertButton.prototype).extend({
+ _init: function() {
+ this.type = "Node-revert-button";
+ this.lastSectorInner = 0;
+ this.startAngle = -135;
+ this.endAngle = 135;
+ this.imageName = "revert";
+ this.text = "Cancel deletion";
+ },
+ mouseup: function() {
+ this.renderer.click_target = null;
+ this.renderer.is_dragging = false;
+ if (this.renderer.isEditable()) {
+ this.source_representation.model.unset("delete_scheduled");
+ }
+ }
+ }).value();
+
+ /* NodeRevertButton End */
+
+ return NodeRevertButton;
+
+});
+
+
+define('renderer/nodelinkbutton',['jquery', 'underscore', 'requtils', 'renderer/nodebutton'], function ($, _, requtils, NodeButton) {
+ 'use strict';
+
+ var Utils = requtils.getUtils();
+
+ /* NodeLinkButton Begin */
+
+ //var NodeLinkButton = Renderer.NodeLinkButton = Utils.inherit(Renderer._NodeButton);
+ var NodeLinkButton = Utils.inherit(NodeButton);
+
+ _(NodeLinkButton.prototype).extend({
+ _init: function() {
+ this.type = "Node-link-button";
+ this.lastSectorInner = 0;
+ this.startAngle = this.options.hide_nodes ? 135 : 90;
+ this.endAngle = this.options.hide_nodes ? 190 : 180;
+ this.imageName = "link";
+ this.text = "Link to another node";
+ },
+ mousedown: function(_event, _isTouch) {
+ if (this.renderer.isEditable()) {
+ var _off = this.renderer.canvas_$.offset(),
+ _point = new paper.Point([
+ _event.pageX - _off.left,
+ _event.pageY - _off.top
+ ]);
+ this.renderer.click_target = null;
+ this.renderer.removeRepresentationsOfType("editor");
+ this.renderer.addTempEdge(this.source_representation, _point);
+ }
+ }
+ }).value();
+
+ /* NodeLinkButton End */
+
+ return NodeLinkButton;
+
+});
+
+
+
+define('renderer/nodeenlargebutton',['jquery', 'underscore', 'requtils', 'renderer/nodebutton'], function ($, _, requtils, NodeButton) {
+ 'use strict';
+
+ var Utils = requtils.getUtils();
+
+ /* NodeEnlargeButton Begin */
+
+ //var NodeEnlargeButton = Renderer.NodeEnlargeButton = Utils.inherit(Renderer._NodeButton);
+ var NodeEnlargeButton = Utils.inherit(NodeButton);
+
+ _(NodeEnlargeButton.prototype).extend({
+ _init: function() {
+ this.type = "Node-enlarge-button";
+ this.lastSectorInner = 0;
+ this.startAngle = this.options.hide_nodes ? -55 : -45;
+ this.endAngle = this.options.hide_nodes ? -10 : 0;
+ this.imageName = "enlarge";
+ this.text = "Enlarge";
+ },
+ mouseup: function() {
+ var _newsize = 1 + (this.source_representation.model.get("size") || 0);
+ this.source_representation.model.set("size", _newsize);
+ this.source_representation.select();
+ this.select();
+ paper.view.draw();
+ }
+ }).value();
+
+ /* NodeEnlargeButton End */
+
+ return NodeEnlargeButton;
+
+});
+
+
+define('renderer/nodeshrinkbutton',['jquery', 'underscore', 'requtils', 'renderer/nodebutton'], function ($, _, requtils, NodeButton) {
+ 'use strict';
+
+ var Utils = requtils.getUtils();
+
+ /* NodeShrinkButton Begin */
+
+ //var NodeShrinkButton = Renderer.NodeShrinkButton = Utils.inherit(Renderer._NodeButton);
+ var NodeShrinkButton = Utils.inherit(NodeButton);
+
+ _(NodeShrinkButton.prototype).extend({
+ _init: function() {
+ this.type = "Node-shrink-button";
+ this.lastSectorInner = 0;
+ this.startAngle = this.options.hide_nodes ? -170 : -180;
+ this.endAngle = this.options.hide_nodes ? -125 : -135;
+ this.imageName = "shrink";
+ this.text = "Shrink";
+ },
+ mouseup: function() {
+ var _newsize = -1 + (this.source_representation.model.get("size") || 0);
+ this.source_representation.model.set("size", _newsize);
+ this.source_representation.select();
+ this.select();
+ paper.view.draw();
+ }
+ }).value();
+
+ /* NodeShrinkButton End */
+
+ return NodeShrinkButton;
+
+});
+
+
+define('renderer/edgeeditbutton',['jquery', 'underscore', 'requtils', 'renderer/basebutton'], function ($, _, requtils, BaseButton) {
+ 'use strict';
+
+ var Utils = requtils.getUtils();
+
+ /* EdgeEditButton Begin */
+
+ //var EdgeEditButton = Renderer.EdgeEditButton = Utils.inherit(Renderer._BaseButton);
+ var EdgeEditButton = Utils.inherit(BaseButton);
+
+ _(EdgeEditButton.prototype).extend({
+ _init: function() {
+ this.type = "Edge-edit-button";
+ this.sector = this.renderer.drawSector(this, Utils._EDGE_BUTTON_INNER, Utils._EDGE_BUTTON_OUTER, -270, -90, 1, "edit", this.renkan.translate("Edit"));
+ },
+ mouseup: function() {
+ if (!this.renderer.is_dragging) {
+ this.source_representation.openEditor();
+ }
+ }
+ }).value();
+
+ /* EdgeEditButton End */
+
+ return EdgeEditButton;
+
+});
+
+
+define('renderer/edgeremovebutton',['jquery', 'underscore', 'requtils', 'renderer/basebutton'], function ($, _, requtils, BaseButton) {
+ 'use strict';
+
+ var Utils = requtils.getUtils();
+
+ /* EdgeRemoveButton Begin */
+
+ //var EdgeRemoveButton = Renderer.EdgeRemoveButton = Utils.inherit(Renderer._BaseButton);
+ var EdgeRemoveButton = Utils.inherit(BaseButton);
+
+ _(EdgeRemoveButton.prototype).extend({
+ _init: function() {
+ this.type = "Edge-remove-button";
+ this.sector = this.renderer.drawSector(this, Utils._EDGE_BUTTON_INNER, Utils._EDGE_BUTTON_OUTER, -90, 90, 1, "remove", this.renkan.translate("Remove"));
+ },
+ mouseup: function() {
+ this.renderer.click_target = null;
+ this.renderer.is_dragging = false;
+ this.renderer.removeRepresentationsOfType("editor");
+ if (this.renderer.isEditable()) {
+ if (this.options.element_delete_delay) {
+ var delid = Utils.getUID("delete");
+ this.renderer.delete_list.push({
+ id: delid,
+ time: new Date().valueOf() + this.options.element_delete_delay
+ });
+ this.source_representation.model.set("delete_scheduled", delid);
+ } else {
+ if (confirm(this.renkan.translate('Do you really wish to remove edge ') + '"' + this.source_representation.model.get("title") + '"?')) {
+ this.project.removeEdge(this.source_representation.model);
+ }
+ }
+ }
+ }
+ }).value();
+
+ /* EdgeRemoveButton End */
+
+ return EdgeRemoveButton;
+
+});
+
+
+define('renderer/edgerevertbutton',['jquery', 'underscore', 'requtils', 'renderer/basebutton'], function ($, _, requtils, BaseButton) {
+ 'use strict';
+
+ var Utils = requtils.getUtils();
+
+ /* EdgeRevertButton Begin */
+
+ //var EdgeRevertButton = Renderer.EdgeRevertButton = Utils.inherit(Renderer._BaseButton);
+ var EdgeRevertButton = Utils.inherit(BaseButton);
+
+ _(EdgeRevertButton.prototype).extend({
+ _init: function() {
+ this.type = "Edge-revert-button";
+ this.sector = this.renderer.drawSector(this, Utils._EDGE_BUTTON_INNER, Utils._EDGE_BUTTON_OUTER, -135, 135, 1, "revert", this.renkan.translate("Cancel deletion"));
+ },
+ mouseup: function() {
+ this.renderer.click_target = null;
+ this.renderer.is_dragging = false;
+ if (this.renderer.isEditable()) {
+ this.source_representation.model.unset("delete_scheduled");
+ }
+ }
+ }).value();
+
+ /* EdgeRevertButton End */
+
+ return EdgeRevertButton;
+
+});
+
+
+define('renderer/miniframe',['jquery', 'underscore', 'requtils', 'renderer/baserepresentation'], function ($, _, requtils, BaseRepresentation) {
+ 'use strict';
+
+ var Utils = requtils.getUtils();
+
+ /* MiniFrame Begin */
+
+ //var MiniFrame = Renderer.MiniFrame = Utils.inherit(Renderer._BaseRepresentation);
+ var MiniFrame = Utils.inherit(BaseRepresentation);
+
+ _(MiniFrame.prototype).extend({
+ paperShift: function(_delta) {
+ this.renderer.offset = this.renderer.offset.subtract(_delta.divide(this.renderer.minimap.scale).multiply(this.renderer.scale));
+ this.renderer.redraw();
+ },
+ mouseup: function(_delta) {
+ this.renderer.click_target = null;
+ this.renderer.is_dragging = false;
+ }
+ }).value();
+
+
+ /* MiniFrame End */
+
+ return MiniFrame;
+
+});
+
+
+define('renderer/scene',['jquery', 'underscore', 'filesaver', 'requtils', 'renderer/miniframe'], function ($, _, filesaver, requtils, MiniFrame) {
+ 'use strict';
+
+ var Utils = requtils.getUtils();
+
+ /* Scene Begin */
+
+ var Scene = function(_renkan) {
+ this.renkan = _renkan;
+ this.$ = $(".Rk-Render");
+ this.representations = [];
+ this.$.html(_renkan.options.templates['templates/scene.html'](_renkan));
+ this.onStatusChange();
+ this.canvas_$ = this.$.find(".Rk-Canvas");
+ this.labels_$ = this.$.find(".Rk-Labels");
+ if (!_renkan.options.popup_editor){
+ this.editor_$ = $("#" + _renkan.options.editor_panel);
+ }else{
+ this.editor_$ = this.$.find(".Rk-Editor");
+ }
+ this.notif_$ = this.$.find(".Rk-Notifications");
+ paper.setup(this.canvas_$[0]);
+ this.totalScroll = 0;
+ this.mouse_down = false;
+ this.click_target = null;
+ this.selected_target = null;
+ this.edge_layer = new paper.Layer();
+ this.node_layer = new paper.Layer();
+ this.buttons_layer = new paper.Layer();
+ this.delete_list = [];
+ this.redrawActive = true;
+
+ if (_renkan.options.show_minimap) {
+ this.minimap = {
+ background_layer: new paper.Layer(),
+ edge_layer: new paper.Layer(),
+ node_layer: new paper.Layer(),
+ node_group: new paper.Group(),
+ size: new paper.Size( _renkan.options.minimap_width, _renkan.options.minimap_height )
+ };
+
+ this.minimap.background_layer.activate();
+ this.minimap.topleft = paper.view.bounds.bottomRight.subtract(this.minimap.size);
+ this.minimap.rectangle = new paper.Path.Rectangle(this.minimap.topleft.subtract([2,2]), this.minimap.size.add([4,4]));
+ this.minimap.rectangle.fillColor = _renkan.options.minimap_background_color;
+ this.minimap.rectangle.strokeColor = _renkan.options.minimap_border_color;
+ this.minimap.rectangle.strokeWidth = 4;
+ this.minimap.offset = new paper.Point(this.minimap.size.divide(2));
+ this.minimap.scale = 0.1;
+
+ this.minimap.node_layer.activate();
+ this.minimap.cliprectangle = new paper.Path.Rectangle(this.minimap.topleft, this.minimap.size);
+ this.minimap.node_group.addChild(this.minimap.cliprectangle);
+ this.minimap.node_group.clipped = true;
+ this.minimap.miniframe = new paper.Path.Rectangle(this.minimap.topleft, this.minimap.size);
+ this.minimap.node_group.addChild(this.minimap.miniframe);
+ this.minimap.miniframe.fillColor = '#c0c0ff';
+ this.minimap.miniframe.opacity = 0.3;
+ this.minimap.miniframe.strokeColor = '#000080';
+ this.minimap.miniframe.strokeWidth = 2;
+ this.minimap.miniframe.__representation = new MiniFrame(this, null);
+ }
+
+ this.throttledPaperDraw = _(function() {
+ paper.view.draw();
+ }).throttle(100).value();
+
+ this.bundles = [];
+ this.click_mode = false;
+
+ var _this = this,
+ _allowScroll = true,
+ _originalScale = 1,
+ _zooming = false,
+ _lastTapX = 0,
+ _lastTapY = 0;
+
+ this.image_cache = {};
+ this.icon_cache = {};
+
+ ['edit', 'remove', 'hide', 'show', 'link', 'enlarge', 'shrink', 'revert' ].forEach(function(imgname) {
+ var img = new Image();
+ img.src = _renkan.options.static_url + 'img/' + imgname + '.png';
+ _this.icon_cache[imgname] = img;
+ });
+
+ var throttledMouseMove = _.throttle(function(_event, _isTouch) {
+ _this.onMouseMove(_event, _isTouch);
+ }, Utils._MOUSEMOVE_RATE);
+
+ this.canvas_$.on({
+ mousedown: function(_event) {
+ _event.preventDefault();
+ _this.onMouseDown(_event, false);
+ },
+ mousemove: function(_event) {
+ _event.preventDefault();
+ throttledMouseMove(_event, false);
+ },
+ mouseup: function(_event) {
+ _event.preventDefault();
+ _this.onMouseUp(_event, false);
+ },
+ mousewheel: function(_event, _delta) {
+ if(_renkan.options.zoom_on_scroll) {
+ _event.preventDefault();
+ if (_allowScroll) {
+ _this.onScroll(_event, _delta);
+ }
+ }
+ },
+ touchstart: function(_event) {
+ _event.preventDefault();
+ var _touches = _event.originalEvent.touches[0];
+ if (
+ _renkan.options.allow_double_click &&
+ new Date() - _lastTap < Utils._DOUBLETAP_DELAY &&
+ ( Math.pow(_lastTapX - _touches.pageX, 2) + Math.pow(_lastTapY - _touches.pageY, 2) < Utils._DOUBLETAP_DISTANCE )
+ ) {
+ _lastTap = 0;
+ _this.onDoubleClick(_touches);
+ } else {
+ _lastTap = new Date();
+ _lastTapX = _touches.pageX;
+ _lastTapY = _touches.pageY;
+ _originalScale = _this.view.scale;
+ _zooming = false;
+ _this.onMouseDown(_touches, true);
+ }
+ },
+ touchmove: function(_event) {
+ _event.preventDefault();
+ _lastTap = 0;
+ if (_event.originalEvent.touches.length === 1) {
+ _this.onMouseMove(_event.originalEvent.touches[0], true);
+ } else {
+ if (!_zooming) {
+ _this.onMouseUp(_event.originalEvent.touches[0], true);
+ _this.click_target = null;
+ _this.is_dragging = false;
+ _zooming = true;
+ }
+ if (_event.originalEvent.scale === "undefined") {
+ return;
+ }
+ var _newScale = _event.originalEvent.scale * _originalScale,
+ _scaleRatio = _newScale / _this.view.scale,
+ _newOffset = new paper.Point([
+ _this.canvas_$.width(),
+ _this.canvas_$.height()
+ ]).multiply( 0.5 * ( 1 - _scaleRatio ) ).add(_this.view.offset.multiply( _scaleRatio ));
+ _this.view.setScale(_newScale, _newOffset);
+ }
+ },
+ touchend: function(_event) {
+ _event.preventDefault();
+ _this.onMouseUp(_event.originalEvent.changedTouches[0], true);
+ },
+ dblclick: function(_event) {
+ _event.preventDefault();
+ if (_renkan.options.allow_double_click) {
+ _this.onDoubleClick(_event);
+ }
+ },
+ mouseleave: function(_event) {
+ _event.preventDefault();
+ //_this.onMouseUp(_event, false);
+ _this.click_target = null;
+ _this.is_dragging = false;
+ },
+ dragover: function(_event) {
+ _event.preventDefault();
+ },
+ dragenter: function(_event) {
+ _event.preventDefault();
+ _allowScroll = false;
+ },
+ dragleave: function(_event) {
+ _event.preventDefault();
+ _allowScroll = true;
+ },
+ drop: function(_event) {
+ _event.preventDefault();
+ _allowScroll = true;
+ var res = {};
+ _.each(_event.originalEvent.dataTransfer.types, function(t) {
+ try {
+ res[t] = _event.originalEvent.dataTransfer.getData(t);
+ } catch(e) {}
+ });
+ var text = _event.originalEvent.dataTransfer.getData("Text");
+ if (typeof text === "string") {
+ switch(text[0]) {
+ case "{":
+ case "[":
+ try {
+ var data = JSON.parse(text);
+ _.extend(res,data);
+ }
+ catch(e) {
+ if (!res["text/plain"]) {
+ res["text/plain"] = text;
+ }
+ }
+ break;
+ case "<":
+ if (!res["text/html"]) {
+ res["text/html"] = text;
+ }
+ break;
+ default:
+ if (!res["text/plain"]) {
+ res["text/plain"] = text;
+ }
+ }
+ }
+ var url = _event.originalEvent.dataTransfer.getData("URL");
+ if (url && !res["text/uri-list"]) {
+ res["text/uri-list"] = url;
+ }
+ _this.dropData(res, _event.originalEvent);
+ }
+ });
+
+ var bindClick = function(selector, fname) {
+ _this.$.find(selector).click(function(evt) {
+ _this[fname](evt);
+ return false;
+ });
+ };
+
+ if(this.renkan.project.get("views").length > 0 && this.renkan.options.save_view){
+ this.$.find(".Rk-ZoomSetSaved").show();
+ }
+ this.$.find(".Rk-CurrentUser").mouseenter(
+ function() { _this.$.find(".Rk-UserList").slideDown(); }
+ );
+ this.$.find(".Rk-Users").mouseleave(
+ function() { _this.$.find(".Rk-UserList").slideUp(); }
+ );
+ bindClick(".Rk-FullScreen-Button", "fullScreen");
+ bindClick(".Rk-AddNode-Button", "addNodeBtn");
+ bindClick(".Rk-AddEdge-Button", "addEdgeBtn");
+ bindClick(".Rk-Save-Button", "save");
+ bindClick(".Rk-Open-Button", "open");
+ bindClick(".Rk-Export-Button", "exportProject");
+ this.$.find(".Rk-Bookmarklet-Button")
+ /*jshint scripturl:true */
+ .attr("href","javascript:" + Utils._BOOKMARKLET_CODE(_renkan))
+ .click(function(){
+ _this.notif_$
+ .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."))
+ .fadeIn()
+ .delay(5000)
+ .fadeOut();
+ return false;
+ });
+ this.$.find(".Rk-TopBar-Button").mouseover(function() {
+ $(this).find(".Rk-TopBar-Tooltip").show();
+ }).mouseout(function() {
+ $(this).find(".Rk-TopBar-Tooltip").hide();
+ });
+ bindClick(".Rk-Fold-Bins", "foldBins");
+
+ paper.view.onResize = function(_event) {
+ var _ratio,
+ newWidth = _event.width,
+ newHeight = _event.height;
+
+ if (_this.minimap) {
+ _this.minimap.topleft = paper.view.bounds.bottomRight.subtract(_this.minimap.size);
+ _this.minimap.rectangle.fitBounds(_this.minimap.topleft.subtract([2,2]), _this.minimap.size.add([4,4]));
+ _this.minimap.cliprectangle.fitBounds(_this.minimap.topleft, _this.minimap.size);
+ }
+
+ var ratioH = newHeight/(newHeight-_event.delta.height),
+ ratioW = newWidth/(newWidth-_event.delta.width);
+ if (newHeight < newWidth) {
+ _ratio = ratioH;
+ } else {
+ _ratio = ratioW;
+ }
+
+ _this.view.resizeZoom(ratioW, ratioH, _ratio);
+
+ _this.redraw();
+
+ };
+
+ var _thRedraw = _.throttle(function() {
+ _this.redraw();
+ },50);
+
+ this.addRepresentations("Node", this.renkan.project.get("nodes"));
+ this.addRepresentations("Edge", this.renkan.project.get("edges"));
+ this.renkan.project.on("change:title", function() {
+ _this.$.find(".Rk-PadTitle").val(_renkan.project.get("title"));
+ });
+
+ this.$.find(".Rk-PadTitle").on("keyup input paste", function() {
+ _renkan.project.set({"title": $(this).val()});
+ });
+
+ var _thRedrawUsers = _.throttle(function() {
+ _this.redrawUsers();
+ }, 100);
+
+ _thRedrawUsers();
+
+ // register model events
+ this.renkan.project.on("change:saveStatus", function(){
+ switch (_this.renkan.project.get("saveStatus")) {
+ case 0: //clean
+ _this.$.find(".Rk-Save-Button").removeClass("to-save");
+ _this.$.find(".Rk-Save-Button").removeClass("saving");
+ _this.$.find(".Rk-Save-Button").addClass("saved");
+ break;
+ case 1: //dirty
+ _this.$.find(".Rk-Save-Button").removeClass("saved");
+ _this.$.find(".Rk-Save-Button").removeClass("saving");
+ _this.$.find(".Rk-Save-Button").addClass("to-save");
+ break;
+ case 2: //saving
+ _this.$.find(".Rk-Save-Button").removeClass("saved");
+ _this.$.find(".Rk-Save-Button").removeClass("to-save");
+ _this.$.find(".Rk-Save-Button").addClass("saving");
+ break;
+ }
+ });
+
+ this.renkan.project.on("change:loadingStatus", function(){
+ if (_this.renkan.project.get("loadingStatus")){
+ var animate = _this.$.find(".loader").addClass("run");
+ var timer = setTimeout(function(){
+ _this.$.find(".loader").hide(250);
+ }, 3000);
+ }
+ else{
+ Backbone.history.start();
+ _thRedraw();
+ }
+ });
+
+ this.renkan.project.on("add:users remove:users", _thRedrawUsers);
+
+ this.renkan.project.on("add:views remove:views", function(_node) {
+ if(_this.renkan.project.get('views').length > 0) {
+ _this.$.find(".Rk-ZoomSetSaved").show();
+ }
+ else {
+ _this.$.find(".Rk-ZoomSetSaved").hide();
+ }
+ });
+
+ this.renkan.project.on("add:nodes", function(_node) {
+ _this.addRepresentation("Node", _node);
+ if (!_this.renkan.project.get("loadingStatus")){
+ _thRedraw();
+ }
+ });
+ this.renkan.project.on("add:edges", function(_edge) {
+ _this.addRepresentation("Edge", _edge);
+ if (!_this.renkan.project.get("loadingStatus")){
+ _thRedraw();
+ }
+ });
+ this.renkan.project.on("change:title", function(_model, _title) {
+ var el = _this.$.find(".Rk-PadTitle");
+ if (el.is("input")) {
+ if (el.val() !== _title) {
+ el.val(_title);
+ }
+ } else {
+ el.text(_title);
+ }
+ });
+
+ //register router events
+ this.renkan.router.on("router", function(_params){
+ _this.parameters(_params);
+ });
+
+ if (_renkan.options.size_bug_fix) {
+ var _delay = (
+ typeof _renkan.options.size_bug_fix === "number" ?
+ _renkan.options.size_bug_fix
+ : 500
+ );
+ window.setTimeout(
+ function() {
+ _this.fixSize();
+ },
+ _delay
+ );
+ }
+
+ if (_renkan.options.force_resize) {
+ $(window).resize(function() {
+ _this.autoScale();
+ });
+ }
+
+ if (_renkan.options.show_user_list && _renkan.options.user_color_editable) {
+ var $cpwrapper = this.$.find(".Rk-Users .Rk-Edit-ColorPicker-Wrapper"),
+ $cplist = this.$.find(".Rk-Users .Rk-Edit-ColorPicker");
+
+ $cpwrapper.hover(
+ function(_e) {
+ if (_this.isEditable()) {
+ _e.preventDefault();
+ $cplist.show();
+ }
+ },
+ function(_e) {
+ _e.preventDefault();
+ $cplist.hide();
+ }
+ );
+
+ $cplist.find("li").mouseenter(
+ function(_e) {
+ if (_this.isEditable()) {
+ _e.preventDefault();
+ _this.$.find(".Rk-CurrentUser-Color").css("background", $(this).attr("data-color"));
+ }
+ }
+ );
+ }
+
+ if (_renkan.options.show_search_field) {
+
+ var lastval = '';
+
+ this.$.find(".Rk-GraphSearch-Field").on("keyup change paste input", function() {
+ var $this = $(this),
+ val = $this.val();
+ if (val === lastval) {
+ return;
+ }
+ lastval = val;
+ if (val.length < 2) {
+ _renkan.project.get("nodes").each(function(n) {
+ _this.getRepresentationByModel(n).unhighlight();
+ });
+ } else {
+ var rxs = Utils.regexpFromTextOrArray(val);
+ _renkan.project.get("nodes").each(function(n) {
+ if (rxs.test(n.get("title")) || rxs.test(n.get("description"))) {
+ _this.getRepresentationByModel(n).highlight(rxs);
+ } else {
+ _this.getRepresentationByModel(n).unhighlight();
+ }
+ });
+ }
+ });
+ }
+
+ this.redraw();
+
+ window.setInterval(function() {
+ var _now = new Date().valueOf();
+ _this.delete_list.forEach(function(d) {
+ if (_now >= d.time) {
+ var el = _renkan.project.get("nodes").findWhere({"delete_scheduled":d.id});
+ if (el) {
+ project.removeNode(el);
+ }
+ el = _renkan.project.get("edges").findWhere({"delete_scheduled":d.id});
+ if (el) {
+ project.removeEdge(el);
+ }
+ }
+ });
+ _this.delete_list = _this.delete_list.filter(function(d) {
+ return _renkan.project.get("nodes").findWhere({"delete_scheduled":d.id}) || _renkan.project.get("edges").findWhere({"delete_scheduled":d.id});
+ });
+ }, 500);
+
+ if (this.minimap) {
+ window.setInterval(function() {
+ _this.rescaleMinimap();
+ }, 2000);
+ }
+
+ };
+
+ _(Scene.prototype).extend({
+ fixSize: function() {
+ if(typeof this.view === 'undefined') {
+ this.view = this.addRepresentation("View", this.renkan.project.get("views").last());
+ this.view.setScale(view.get("zoom_level"), new paper.Point(view.get("offset")));
+ }
+ else{
+ this.view.autoScale();
+ }
+ },
+ drawSector: function(_repr, _inR, _outR, _startAngle, _endAngle, _padding, _imgname, _caption) {
+ var _options = this.renkan.options,
+ _startRads = _startAngle * Math.PI / 180,
+ _endRads = _endAngle * Math.PI / 180,
+ _img = this.icon_cache[_imgname],
+ _startdx = - Math.sin(_startRads),
+ _startdy = Math.cos(_startRads),
+ _startXIn = Math.cos(_startRads) * _inR + _padding * _startdx,
+ _startYIn = Math.sin(_startRads) * _inR + _padding * _startdy,
+ _startXOut = Math.cos(_startRads) * _outR + _padding * _startdx,
+ _startYOut = Math.sin(_startRads) * _outR + _padding * _startdy,
+ _enddx = - Math.sin(_endRads),
+ _enddy = Math.cos(_endRads),
+ _endXIn = Math.cos(_endRads) * _inR - _padding * _enddx,
+ _endYIn = Math.sin(_endRads) * _inR - _padding * _enddy,
+ _endXOut = Math.cos(_endRads) * _outR - _padding * _enddx,
+ _endYOut = Math.sin(_endRads) * _outR - _padding * _enddy,
+ _centerR = (_inR + _outR) / 2,
+ _centerRads = (_startRads + _endRads) / 2,
+ _centerX = Math.cos(_centerRads) * _centerR,
+ _centerY = Math.sin(_centerRads) * _centerR,
+ _centerXIn = Math.cos(_centerRads) * _inR,
+ _centerXOut = Math.cos(_centerRads) * _outR,
+ _centerYIn = Math.sin(_centerRads) * _inR,
+ _centerYOut = Math.sin(_centerRads) * _outR,
+ _textX = Math.cos(_centerRads) * (_outR + 3),
+ _textY = Math.sin(_centerRads) * (_outR + _options.buttons_label_font_size) + _options.buttons_label_font_size / 2;
+ this.buttons_layer.activate();
+ var _path = new paper.Path();
+ _path.add([_startXIn, _startYIn]);
+ _path.arcTo([_centerXIn, _centerYIn], [_endXIn, _endYIn]);
+ _path.lineTo([_endXOut, _endYOut]);
+ _path.arcTo([_centerXOut, _centerYOut], [_startXOut, _startYOut]);
+ _path.fillColor = _options.buttons_background;
+ _path.opacity = 0.5;
+ _path.closed = true;
+ _path.__representation = _repr;
+ var _text = new paper.PointText(_textX,_textY);
+ _text.characterStyle = {
+ fontSize: _options.buttons_label_font_size,
+ fillColor: _options.buttons_label_color
+ };
+ if (_textX > 2) {
+ _text.paragraphStyle.justification = 'left';
+ } else if (_textX < -2) {
+ _text.paragraphStyle.justification = 'right';
+ } else {
+ _text.paragraphStyle.justification = 'center';
+ }
+ _text.visible = false;
+ var _visible = false,
+ _restPos = new paper.Point(-200, -200),
+ _grp = new paper.Group([_path, _text]),
+ //_grp = new paper.Group([_path]),
+ _delta = _grp.position,
+ _imgdelta = new paper.Point([_centerX, _centerY]),
+ _currentPos = new paper.Point(0,0);
+ _text.content = _caption;
+ // set group pivot to not depend on text visibility that changes the group bounding box.
+ _grp.pivot = _grp.bounds.center;
+ _grp.visible = false;
+ _grp.position = _restPos;
+ var _res = {
+ show: function() {
+ _visible = true;
+ _grp.position = _currentPos.add(_delta);
+ _grp.visible = true;
+ },
+ moveTo: function(_point) {
+ _currentPos = _point;
+ if (_visible) {
+ _grp.position = _point.add(_delta);
+ }
+ },
+ hide: function() {
+ _visible = false;
+ _grp.visible = false;
+ _grp.position = _restPos;
+ },
+ select: function() {
+ _path.opacity = 0.8;
+ _text.visible = true;
+ },
+ unselect: function() {
+ _path.opacity = 0.5;
+ _text.visible = false;
+ },
+ destroy: function() {
+ _grp.remove();
+ }
+ };
+ var showImage = function() {
+ var _raster = new paper.Raster(_img);
+ _raster.position = _imgdelta.add(_grp.position).subtract(_delta);
+ _raster.locked = true; // Disable mouse events on icon
+ _grp.addChild(_raster);
+ };
+ if (_img.width) {
+ showImage();
+ } else {
+ $(_img).on("load",showImage);
+ }
+
+ return _res;
+ },
+ addToBundles: function(_edgeRepr) {
+ var _bundle = _(this.bundles).find(function(_bundle) {
+ return (
+ ( _bundle.from === _edgeRepr.from_representation && _bundle.to === _edgeRepr.to_representation ) ||
+ ( _bundle.from === _edgeRepr.to_representation && _bundle.to === _edgeRepr.from_representation )
+ );
+ });
+ if (typeof _bundle !== "undefined") {
+ _bundle.edges.push(_edgeRepr);
+ } else {
+ _bundle = {
+ from: _edgeRepr.from_representation,
+ to: _edgeRepr.to_representation,
+ edges: [ _edgeRepr ],
+ getPosition: function(_er) {
+ var _dir = (_er.from_representation === this.from) ? 1 : -1;
+ return _dir * ( _(this.edges).indexOf(_er) - (this.edges.length - 1) / 2 );
+ }
+ };
+ this.bundles.push(_bundle);
+ }
+ return _bundle;
+ },
+ isEditable: function() {
+ return (this.renkan.options.editor_mode && !this.renkan.read_only);
+ },
+ onStatusChange: function() {
+ var savebtn = this.$.find(".Rk-Save-Button"),
+ tip = savebtn.find(".Rk-TopBar-Tooltip-Contents");
+ if (this.renkan.read_only) {
+ savebtn.removeClass("disabled Rk-Save-Online").addClass("Rk-Save-ReadOnly");
+ tip.text(this.renkan.translate("Connection lost"));
+ } else {
+ if (this.renkan.options.manual_save) {
+ savebtn.removeClass("Rk-Save-ReadOnly Rk-Save-Online");
+ tip.text(this.renkan.translate("Save Project"));
+ } else {
+ savebtn.removeClass("disabled Rk-Save-ReadOnly").addClass("Rk-Save-Online");
+ tip.text(this.renkan.translate("Auto-save enabled"));
+ }
+ }
+ this.redrawUsers();
+ },
+ redrawMiniframe: function() {
+ var topleft = this.toMinimapCoords(this.toModelCoords(new paper.Point([0,0]))),
+ bottomright = this.toMinimapCoords(this.toModelCoords(paper.view.bounds.bottomRight));
+ this.minimap.miniframe.fitBounds(topleft, bottomright);
+ },
+ rescaleMinimap: function() {
+ var nodes = this.renkan.project.get("nodes");
+ if (nodes.length > 1) {
+ var _xx = nodes.map(function(_node) { return _node.get("position").x; }),
+ _yy = nodes.map(function(_node) { return _node.get("position").y; }),
+ _minx = Math.min.apply(Math, _xx),
+ _miny = Math.min.apply(Math, _yy),
+ _maxx = Math.max.apply(Math, _xx),
+ _maxy = Math.max.apply(Math, _yy);
+ var _scale = Math.min(
+ this.view.scale * 0.8 * this.renkan.options.minimap_width / paper.view.bounds.width,
+ this.view.scale * 0.8 * this.renkan.options.minimap_height / paper.view.bounds.height,
+ ( this.renkan.options.minimap_width - 2 * this.renkan.options.minimap_padding ) / (_maxx - _minx),
+ ( this.renkan.options.minimap_height - 2 * this.renkan.options.minimap_padding ) / (_maxy - _miny)
+ );
+ this.minimap.offset = this.minimap.size.divide(2).subtract(new paper.Point([(_maxx + _minx) / 2, (_maxy + _miny) / 2]).multiply(_scale));
+ this.minimap.scale = _scale;
+ }
+ if (nodes.length === 1) {
+ this.minimap.scale = 0.1;
+ 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));
+ }
+ this.redraw();
+ },
+ toPaperCoords: function(_point) {
+ return _point.multiply(this.view.scale).add(this.view.offset);
+ },
+ toMinimapCoords: function(_point) {
+ return _point.multiply(this.minimap.scale).add(this.minimap.offset).add(this.minimap.topleft);
+ },
+ toModelCoords: function(_point) {
+ return _point.subtract(this.view.offset).divide(this.view.scale);
+ },
+ addRepresentation: function(_type, _model) {
+ var RendererType = requtils.getRenderer()[_type];
+ var _repr = new RendererType(this, _model);
+ this.representations.push(_repr);
+ return _repr;
+ },
+ addRepresentations: function(_type, _collection) {
+ var _this = this;
+ _collection.forEach(function(_model) {
+ _this.addRepresentation(_type, _model);
+ });
+ },
+ userTemplate: _.template(
+ '<li class="Rk-User"><span class="Rk-UserColor" style="background:<%=background%>;"></span><%=name%></li>'
+ ),
+ redrawUsers: function() {
+ if (!this.renkan.options.show_user_list) {
+ return;
+ }
+ var allUsers = [].concat((this.renkan.project.current_user_list || {}).models || [], (this.renkan.project.get("users") || {}).models || []),
+ ulistHtml = '',
+ $userpanel = this.$.find(".Rk-Users"),
+ $name = $userpanel.find(".Rk-CurrentUser-Name"),
+ $cpitems = $userpanel.find(".Rk-Edit-ColorPicker li"),
+ $colorsquare = $userpanel.find(".Rk-CurrentUser-Color"),
+ _this = this;
+ $name.off("click").text(this.renkan.translate("<unknown user>"));
+ $cpitems.off("mouseleave click");
+ allUsers.forEach(function(_user) {
+ if (_user.get("_id") === _this.renkan.current_user) {
+ $name.text(_user.get("title"));
+ $colorsquare.css("background", _user.get("color"));
+ if (_this.isEditable()) {
+
+ if (_this.renkan.options.user_name_editable) {
+ $name.click(function() {
+ var $this = $(this),
+ $input = $('<input>').val(_user.get("title")).blur(function() {
+ _user.set("title", $(this).val());
+ _this.redrawUsers();
+ _this.redraw();
+ });
+ $this.empty().html($input);
+ $input.select();
+ });
+ }
+
+ if (_this.renkan.options.user_color_editable) {
+ $cpitems.click(
+ function(_e) {
+ _e.preventDefault();
+ if (_this.isEditable()) {
+ _user.set("color", $(this).attr("data-color"));
+ }
+ $(this).parent().hide();
+ }
+ ).mouseleave(function() {
+ $colorsquare.css("background", _user.get("color"));
+ });
+ }
+ }
+
+ } else {
+ ulistHtml += _this.userTemplate({
+ name: _user.get("title"),
+ background: _user.get("color")
+ });
+ }
+ });
+ $userpanel.find(".Rk-UserList").html(ulistHtml);
+ },
+ removeRepresentation: function(_representation) {
+ _representation.destroy();
+ this.representations = _.reject(this.representations,
+ function(_repr) {
+ return _repr === _representation;
+ }
+ );
+ },
+ getRepresentationByModel: function(_model) {
+ if (!_model) {
+ return undefined;
+ }
+ return _.find(this.representations, function(_repr) {
+ return _repr.model === _model;
+ });
+ },
+ removeRepresentationsOfType: function(_type) {
+ var _representations = _.filter(this.representations,function(_repr) {
+ return _repr.type === _type;
+ }),
+ _this = this;
+ _.each(_representations, function(_repr) {
+ _this.removeRepresentation(_repr);
+ });
+ },
+ highlightModel: function(_model) {
+ var _repr = this.getRepresentationByModel(_model);
+ if (_repr) {
+ _repr.highlight();
+ }
+ },
+ unhighlightAll: function(_model) {
+ _.each(this.representations, function(_repr) {
+ _repr.unhighlight();
+ });
+ },
+ unselectAll: function(_model) {
+ _.each(this.representations, function(_repr) {
+ _repr.unselect();
+ });
+ },
+ redraw: function() {
+ var _this = this;
+ if(! this.redrawActive ) {
+ return;
+ }
+ _.each(this.representations, function(_representation) {
+ _representation.redraw({ dontRedrawEdges:true });
+ });
+ if (this.minimap && typeof this.view !== 'undefined') {
+ this.redrawMiniframe();
+ }
+ paper.view.draw();
+ },
+ addTempEdge: function(_from, _point) {
+ var _tmpEdge = this.addRepresentation("TempEdge",null);
+ _tmpEdge.end_pos = _point;
+ _tmpEdge.from_representation = _from;
+ _tmpEdge.redraw();
+ this.click_target = _tmpEdge;
+ },
+ findTarget: function(_hitResult) {
+ if (_hitResult && typeof _hitResult.item.__representation !== "undefined") {
+ var _newTarget = _hitResult.item.__representation;
+ if (this.selected_target !== _hitResult.item.__representation) {
+ if (this.selected_target) {
+ this.selected_target.unselect(_newTarget);
+ }
+ _newTarget.select(this.selected_target);
+ this.selected_target = _newTarget;
+ }
+ } else {
+ if (this.selected_target) {
+ this.selected_target.unselect();
+ }
+ this.selected_target = null;
+ }
+ },
+ onMouseMove: function(_event) {
+ var _off = this.canvas_$.offset(),
+ _point = new paper.Point([
+ _event.pageX - _off.left,
+ _event.pageY - _off.top
+ ]),
+ _delta = _point.subtract(this.last_point);
+ this.last_point = _point;
+ if (!this.is_dragging && this.mouse_down && _delta.length > Utils._MIN_DRAG_DISTANCE) {
+ this.is_dragging = true;
+ }
+ var _hitResult = paper.project.hitTest(_point);
+ if (this.is_dragging) {
+ if (this.click_target && typeof this.click_target.paperShift === "function") {
+ this.click_target.paperShift(_delta);
+ } else {
+ this.view.paperShift(_delta);
+ }
+ } else {
+ this.findTarget(_hitResult);
+ }
+ paper.view.draw();
+ },
+ onMouseDown: function(_event, _isTouch) {
+ var _off = this.canvas_$.offset(),
+ _point = new paper.Point([
+ _event.pageX - _off.left,
+ _event.pageY - _off.top
+ ]);
+ this.last_point = _point;
+ this.mouse_down = true;
+ if (!this.click_target || this.click_target.type !== "Temp-edge") {
+ this.removeRepresentationsOfType("editor");
+ this.is_dragging = false;
+ var _hitResult = paper.project.hitTest(_point);
+ if (_hitResult && typeof _hitResult.item.__representation !== "undefined") {
+ this.click_target = _hitResult.item.__representation;
+ this.click_target.mousedown(_event, _isTouch);
+ } else {
+ this.click_target = null;
+ if (this.isEditable() && this.click_mode === Utils._CLICKMODE_ADDNODE) {
+ var _coords = this.toModelCoords(_point),
+ _data = {
+ id: Utils.getUID('node'),
+ created_by: this.renkan.current_user,
+ position: {
+ x: _coords.x,
+ y: _coords.y
+ }
+ };
+ var _node = this.renkan.project.addNode(_data);
+ this.getRepresentationByModel(_node).openEditor();
+ }
+ }
+ }
+ if (this.click_mode) {
+ if (this.isEditable() && this.click_mode === Utils._CLICKMODE_STARTEDGE && this.click_target && this.click_target.type === "Node") {
+ this.removeRepresentationsOfType("editor");
+ this.addTempEdge(this.click_target, _point);
+ this.click_mode = Utils._CLICKMODE_ENDEDGE;
+ this.notif_$.fadeOut(function() {
+ $(this).html(this.renkan.translate("Click on a second node to complete the edge")).fadeIn();
+ });
+ } else {
+ this.notif_$.hide();
+ this.click_mode = false;
+ }
+ }
+ paper.view.draw();
+ },
+ onMouseUp: function(_event, _isTouch) {
+ this.mouse_down = false;
+ if (this.click_target) {
+ var _off = this.canvas_$.offset();
+ this.click_target.mouseup(
+ {
+ point: new paper.Point([
+ _event.pageX - _off.left,
+ _event.pageY - _off.top
+ ])
+ },
+ _isTouch
+ );
+ } else {
+ this.click_target = null;
+ this.is_dragging = false;
+ if (_isTouch) {
+ this.unselectAll();
+ }
+ this.view.updateUrl();
+ }
+ paper.view.draw();
+ },
+ onScroll: function(_event, _scrolldelta) {
+ this.totalScroll += _scrolldelta;
+ if (Math.abs(this.totalScroll) >= 1) {
+ var _off = this.canvas_$.offset(),
+ _delta = new paper.Point([
+ _event.pageX - _off.left,
+ _event.pageY - _off.top
+ ]).subtract(this.view.offset).multiply( Math.SQRT2 - 1 );
+ if (this.totalScroll > 0) {
+ this.view.setScale( this.view.scale * Math.SQRT2, this.view.offset.subtract(_delta) );
+ } else {
+ this.view.setScale( this.view.scale * Math.SQRT1_2, this.view.offset.add(_delta.divide(Math.SQRT2)));
+ }
+ this.totalScroll = 0;
+ }
+ },
+ onDoubleClick: function(_event) {
+ var _off = this.canvas_$.offset(),
+ _point = new paper.Point([
+ _event.pageX - _off.left,
+ _event.pageY - _off.top
+ ]);
+ var _hitResult = paper.project.hitTest(_point);
+
+ if (!this.isEditable()) {
+ if (_hitResult && typeof _hitResult.item.__representation !== "undefined") {
+ if (_hitResult.item.__representation.model.get('uri')){
+ window.open(_hitResult.item.__representation.model.get('uri'), '_blank');
+ }
+ }
+ return;
+ }
+ if (this.isEditable() && (!_hitResult || typeof _hitResult.item.__representation === "undefined")) {
+ var _coords = this.toModelCoords(_point),
+ _data = {
+ id: Utils.getUID('node'),
+ created_by: this.renkan.current_user,
+ position: {
+ x: _coords.x,
+ y: _coords.y
+ }
+ },
+ _node = this.renkan.project.addNode(_data);
+ this.getRepresentationByModel(_node).openEditor();
+ }
+ paper.view.draw();
+ },
+ defaultDropHandler: function(_data) {
+ var newNode = {};
+ var snippet = "";
+ switch(_data["text/x-iri-specific-site"]) {
+ case "twitter":
+ snippet = $('<div>').html(_data["text/x-iri-selected-html"]);
+ var tweetdiv = snippet.find(".tweet");
+ newNode.title = this.renkan.translate("Tweet by ") + tweetdiv.attr("data-name");
+ newNode.uri = "http://twitter.com/" + tweetdiv.attr("data-screen-name") + "/status/" + tweetdiv.attr("data-tweet-id");
+ newNode.image = tweetdiv.find(".avatar").attr("src");
+ newNode.description = tweetdiv.find(".js-tweet-text:first").text();
+ break;
+ case "google":
+ snippet = $('<div>').html(_data["text/x-iri-selected-html"]);
+ newNode.title = snippet.find("h3:first").text().trim();
+ newNode.uri = snippet.find("h3 a").attr("href");
+ newNode.description = snippet.find(".st:first").text().trim();
+ break;
+ default:
+ if (_data["text/x-iri-source-uri"]) {
+ newNode.uri = _data["text/x-iri-source-uri"];
+ }
+ }
+ if (_data["text/plain"] || _data["text/x-iri-selected-text"]) {
+ newNode.description = (_data["text/plain"] || _data["text/x-iri-selected-text"]).replace(/[\s\n]+/gm,' ').trim();
+ }
+ if (_data["text/html"] || _data["text/x-iri-selected-html"]) {
+ snippet = $('<div>').html(_data["text/html"] || _data["text/x-iri-selected-html"]);
+ var _svgimgs = snippet.find("image");
+ if (_svgimgs.length) {
+ newNode.image = _svgimgs.attr("xlink:href");
+ }
+ var _svgpaths = snippet.find("path");
+ if (_svgpaths.length) {
+ newNode.clipPath = _svgpaths.attr("d");
+ }
+ var _imgs = snippet.find("img");
+ if (_imgs.length) {
+ newNode.image = _imgs[0].src;
+ }
+ var _as = snippet.find("a");
+ if (_as.length) {
+ newNode.uri = _as[0].href;
+ }
+ newNode.title = snippet.find("[title]").attr("title") || newNode.title;
+ newNode.description = snippet.text().replace(/[\s\n]+/gm,' ').trim();
+ }
+ if (_data["text/uri-list"]) {
+ newNode.uri = _data["text/uri-list"];
+ }
+ if (_data["text/x-moz-url"] && !newNode.title) {
+ newNode.title = (_data["text/x-moz-url"].split("\n")[1] || "").trim();
+ if (newNode.title === newNode.uri) {
+ newNode.title = false;
+ }
+ }
+ if (_data["text/x-iri-source-title"] && !newNode.title) {
+ newNode.title = _data["text/x-iri-source-title"];
+ }
+ if (_data["text/html"] || _data["text/x-iri-selected-html"]) {
+ snippet = $('<div>').html(_data["text/html"] || _data["text/x-iri-selected-html"]);
+ newNode.image = snippet.find("[data-image]").attr("data-image") || newNode.image;
+ newNode.uri = snippet.find("[data-uri]").attr("data-uri") || newNode.uri;
+ newNode.title = snippet.find("[data-title]").attr("data-title") || newNode.title;
+ newNode.description = snippet.find("[data-description]").attr("data-description") || newNode.description;
+ newNode.clipPath = snippet.find("[data-clip-path]").attr("data-clip-path") || newNode.clipPath;
+ }
+
+ if (!newNode.title) {
+ newNode.title = this.renkan.translate("Dragged resource");
+ }
+ var fields = ["title", "description", "uri", "image"];
+ for (var i = 0; i < fields.length; i++) {
+ var f = fields[i];
+ if (_data["text/x-iri-" + f] || _data[f]) {
+ newNode[f] = _data["text/x-iri-" + f] || _data[f];
+ }
+ if (newNode[f] === "none" || newNode[f] === "null") {
+ newNode[f] = undefined;
+ }
+ }
+
+ if(typeof this.renkan.options.drop_enhancer === "function"){
+ newNode = this.renkan.options.drop_enhancer(newNode, _data);
+ }
+
+ return newNode;
+
+ },
+ dropData: function(_data, _event) {
+ if (!this.isEditable()) {
+ return;
+ }
+ if (_data["text/json"] || _data["application/json"]) {
+ try {
+ var jsondata = JSON.parse(_data["text/json"] || _data["application/json"]);
+ _.extend(_data,jsondata);
+ }
+ catch(e) {}
+ }
+
+ var newNode = (typeof this.renkan.options.drop_handler === "undefined")?this.defaultDropHandler(_data):this.renkan.options.drop_handler(_data);
+
+ var _off = this.canvas_$.offset(),
+ _point = new paper.Point([
+ _event.pageX - _off.left,
+ _event.pageY - _off.top
+ ]),
+ _coords = this.toModelCoords(_point),
+ _nodedata = {
+ id: Utils.getUID('node'),
+ created_by: this.renkan.current_user,
+ uri: newNode.uri || "",
+ title: newNode.title || "",
+ description: newNode.description || "",
+ image: newNode.image || "",
+ color: newNode.color || undefined,
+ clip_path: newNode.clipPath || undefined,
+ position: {
+ x: _coords.x,
+ y: _coords.y
+ }
+ };
+ var _node = this.renkan.project.addNode(_nodedata),
+ _repr = this.getRepresentationByModel(_node);
+ if (_event.type === "drop") {
+ _repr.openEditor();
+ }
+ },
+ fullScreen: function() {
+ var _isFull = document.fullScreen || document.mozFullScreen || document.webkitIsFullScreen,
+ _el = this.renkan.$[0],
+ _requestMethods = ["requestFullScreen","mozRequestFullScreen","webkitRequestFullScreen"],
+ _cancelMethods = ["cancelFullScreen","mozCancelFullScreen","webkitCancelFullScreen"],
+ i;
+ if (_isFull) {
+ for (i = 0; i < _cancelMethods.length; i++) {
+ if (typeof document[_cancelMethods[i]] === "function") {
+ document[_cancelMethods[i]]();
+ break;
+ }
+ }
+ var widthAft = this.$.width();
+ var heightAft = this.$.height();
+
+ if (this.renkan.options.show_top_bar) {
+ heightAft -= this.$.find(".Rk-TopBar").height();
+ }
+ if (this.renkan.options.show_bins && (this.renkan.$.find(".Rk-Bins").position().left > 0)) {
+ widthAft -= this.renkan.$.find(".Rk-Bins").width();
+ }
+
+ paper.view.viewSize = new paper.Size([widthAft, heightAft]);
+
+ } else {
+ for (i = 0; i < _requestMethods.length; i++) {
+ if (typeof _el[_requestMethods[i]] === "function") {
+ _el[_requestMethods[i]]();
+ break;
+ }
+ }
+ this.redraw();
+ }
+ },
+ addNodeBtn: function() {
+ if (this.click_mode === Utils._CLICKMODE_ADDNODE) {
+ this.click_mode = false;
+ this.notif_$.hide();
+ } else {
+ this.click_mode = Utils._CLICKMODE_ADDNODE;
+ this.notif_$.text(this.renkan.translate("Click on the background canvas to add a node")).fadeIn();
+ }
+ return false;
+ },
+ addEdgeBtn: function() {
+ if (this.click_mode === Utils._CLICKMODE_STARTEDGE || this.click_mode === Utils._CLICKMODE_ENDEDGE) {
+ this.click_mode = false;
+ this.notif_$.hide();
+ } else {
+ this.click_mode = Utils._CLICKMODE_STARTEDGE;
+ this.notif_$.text(this.renkan.translate("Click on a first node to start the edge")).fadeIn();
+ }
+ return false;
+ },
+ exportProject: function() {
+ var projectJSON = this.renkan.project.toJSON(),
+ downloadLink = document.createElement("a"),
+ projectId = projectJSON.id,
+ fileNameToSaveAs = projectId + ".json";
+
+ // clean ids
+ delete projectJSON.id;
+ delete projectJSON._id;
+ delete projectJSON.space_id;
+
+ var objId,
+ idsMap = {},
+ hiddenNodes;
+
+ _.each(projectJSON.nodes, function(e,i,l) {
+ objId = e.id || e._id;
+ delete e._id;
+ delete e.id;
+ idsMap[objId] = e['@id'] = Utils.getUUID4();
+ });
+ _.each(projectJSON.edges, function(e,i,l) {
+ delete e._id;
+ delete e.id;
+ e.to = idsMap[e.to];
+ e.from = idsMap[e.from];
+ });
+ _.each(projectJSON.views, function(e,i,l) {
+ delete e._id;
+ delete e.id;
+
+ if(e.hidden_nodes) {
+ hiddenNodes = e.hidden_nodes;
+ e.hidden_nodes = [];
+ _.each(hiddenNodes, function(h,j) {
+ e.hidden_nodes.push(idsMap[h]);
+ });
+ }
+ });
+ projectJSON.users = [];
+
+ var projectJSONStr = JSON.stringify(projectJSON, null, 2);
+ var blob = new Blob([projectJSONStr], {type: "application/json;charset=utf-8"});
+ filesaver(blob,fileNameToSaveAs);
+
+ },
+ parameters: function(_params){
+ this.removeRepresentationsOfType("View");
+ if ($.isEmptyObject(_params)){
+ this.view = this.addRepresentation("View", this.renkan.project.get("views").at(this.validViewIndex(this.renkan.options.default_index_view)));
+ if (!this.renkan.options.default_view){
+ this.view.autoScale();
+ }
+ return;
+ }
+ if (typeof _params.viewIndex !== 'undefined'){
+ this.view = this.addRepresentation("View", this.renkan.project.get("views").at(this.validViewIndex(_params.viewIndex)));
+ if (!this.renkan.options.default_view){
+ this.view.autoScale();
+ }
+ }
+ if (typeof _params.view !== 'undefined' && _params.view.split(",").length >= 3){
+ var viewParams = _params.view.split(",");
+ var params = {
+ "project": this.renkan.project,
+ "offset": {
+ "x": parseFloat(viewParams[0]),
+ "y": parseFloat(viewParams[1])
+ },
+ "zoom_level": parseFloat(viewParams[2])
+ };
+ if (this.view){
+ this.view.setScale(params.zoom_level, new paper.Point(params.offset));
+ } else{
+ this.view = this.addRepresentation("View", null);
+ this.view.params = params;
+ this.view.init();
+ }
+ }
+ if (!this.view){
+ this.view = this.addRepresentation("View", this.renkan.project.get("views").at(this.validViewIndex(this.renkan.options.default_index_view)));
+ this.view.autoScale();
+ }
+ //other parameters must go after because most of them depends on a view that must be initialize before
+ this.unhighlightAll();
+ if (typeof _params.idNode !== 'undefined'){
+ this.highlightModel(this.renkan.project.get("nodes").get(_params.idNode));
+ }
+ },
+ validViewIndex: function(index){
+ //check if the view index exist (negative index is from the end) and return the correct index or false if doesn't exist
+ var _index = parseInt(index);
+ var validIndex = 0;
+ if (_index < 0){
+ validIndex = this.renkan.project.get("views").length + _index;
+ } else {
+ validIndex = _index;
+ }
+ if (typeof this.renkan.project.get("views").at(_index) === 'undefined'){
+ validIndex = 0;
+ }
+ return validIndex;
+ },
+ foldBins: function() {
+ var foldBinsButton = this.$.find(".Rk-Fold-Bins"),
+ bins = this.renkan.$.find(".Rk-Bins");
+ var _this = this,
+ sizeBef = _this.canvas_$.width(),
+ sizeAft;
+ if (bins.position().left < 0) {
+ bins.animate({left: 0},250);
+ this.$.animate({left: 300},250,function() {
+ var w = _this.$.width();
+ paper.view.viewSize = new paper.Size([w, _this.canvas_$.height()]);
+ });
+ if ((sizeBef - bins.width()) < bins.height()){
+ sizeAft = sizeBef;
+ } else {
+ sizeAft = sizeBef - bins.width();
+ }
+ foldBinsButton.html("«");
+ } else {
+ bins.animate({left: -300},250);
+ this.$.animate({left: 0},250,function() {
+ var w = _this.$.width();
+ paper.view.viewSize = new paper.Size([w, _this.canvas_$.height()]);
+ });
+ sizeAft = sizeBef+300;
+ foldBinsButton.html("»");
+ }
+ _this.view.resizeZoom(1, 1, (sizeAft/sizeBef));
+ },
+ save: function() { },
+ open: function() { }
+ }).value();
+
+ /* Scene End */
+
+ return Scene;
+
+});
+
+define('renderer/viewrepr',['jquery', 'underscore', 'requtils', 'renderer/baserepresentation'], function ($, _, requtils, BaseRepresentation) {
+ 'use strict';
+
+ var Utils = requtils.getUtils();
+
+ /* Rkns.Renderer.View Class */
+
+ /* The representation for the view. */
+
+ var ViewRepr = Utils.inherit(BaseRepresentation);
+
+ _(ViewRepr.prototype).extend({
+ _init: function() {
+ var _this = this;
+ this.$ = $(".Rk-Render");
+ this.type = "View";
+ this.hiddenNodes = [];
+ this.scale = 1;
+ this.initialScale = 1;
+ this.offset = paper.view.center;
+ this.params = {};
+
+ if (this.model){
+ this.params = {
+ "zoom_level": _this.model.get("zoom_level"),
+ "offset": _this.model.get("offset"),
+ "hidden_nodes": _this.model.get("hidden_nodes")
+ };
+ }
+
+ this.init();
+
+ var bindClick = function(selector, fname) {
+ _this.$.find(selector).click(function(evt) {
+ _this[fname](evt);
+ return false;
+ });
+ };
+
+ bindClick(".Rk-ZoomOut", "zoomOut");
+ bindClick(".Rk-ZoomIn", "zoomIn");
+ bindClick(".Rk-ZoomFit", "autoScale");
+
+ this.$.find(".Rk-ZoomSave").click( function() {
+ var offset = {
+ "x": _this.offset.x,
+ "y": _this.offset.y
+ };
+ _this.model = _this.renkan.project.addView( { zoom_level:_this.scale, offset:offset, hidden_nodes: _this.hiddenNodes.concat() } );
+ _this.params = {
+ "zoom_level": _this.model.get("zoom_level"),
+ "offset": _this.model.get("offset"),
+ "hidden_nodes": _this.model.get("hidden_nodes")
+ };
+ _this.updateUrl();
+ });
+
+ this.$.find(".Rk-ZoomSetSaved").click( function() {
+ _this.model = _this.renkan.project.get("views").at(_this.renkan.project.get("views").length -1);
+ _this.params = {
+ "zoom_level": _this.model.get("zoom_level"),
+ "offset": _this.model.get("offset"),
+ "hidden_nodes": _this.model.get("hidden_nodes")
+ };
+ _this.setScale(_this.params.zoom_level, new paper.Point(_this.params.offset));
+ _this.showNodes(false);
+ if (_this.options.hide_nodes){
+ _this.hiddenNodes = (_this.params.hidden_nodes || []).concat();
+ _this.hideNodes();
+ }
+ _this.updateUrl();
+ });
+
+ this.$.find(".Rk-ShowHiddenNodes").mouseenter( function() {
+ _this.showNodes(true);
+ _this.$.find(".Rk-ShowHiddenNodes").mouseleave( function() {
+ _this.hideNodes();
+ });
+ });
+ this.$.find(".Rk-ShowHiddenNodes").click( function() {
+ _this.showNodes(false);
+ _this.$.find(".Rk-ShowHiddenNodes").off( "mouseleave" );
+ });
+ if(this.renkan.project.get("views").length > 0 && this.renkan.options.save_view){
+ this.$.find(".Rk-ZoomSetSaved").show();
+ }
+ },
+ redraw: function(options) {
+ //console.log("view : ", this.model.toJSON());
+ },
+ init: function(){
+ var _this = this;
+ _this.setScale(_this.params.zoom_level, new paper.Point(_this.params.offset));
+
+ if (_this.options.hide_nodes){
+ _this.hiddenNodes = (_this.params.hidden_nodes || []).concat();
+ _this.hideNodes();
+ }
+ },
+ addHiddenNode: function(_model){
+ this.hideNode(_model);
+ this.hiddenNodes.push(_model.id);
+ this.updateUrl();
+ },
+ hideNode: function(_model){
+ if (typeof this.renderer.getRepresentationByModel(_model) !== 'undefined'){
+ this.renderer.getRepresentationByModel(_model).hide();
+ }
+ },
+ hideNodes: function(){
+ var _this = this;
+ this.hiddenNodes.forEach(function(_id, index){
+ var node = _this.renkan.project.get("nodes").get(_id);
+ if (typeof node !== 'undefined'){
+ return _this.hideNode(_this.renkan.project.get("nodes").get(_id));
+ }else{
+ _this.hiddenNodes.splice(index, 1);
+ }
+ });
+ paper.view.draw();
+ },
+ showNodes: function(ghost){
+ var _this = this;
+ this.hiddenNodes.forEach(function(_id){
+ _this.renderer.getRepresentationByModel(_this.renkan.project.get("nodes").get(_id)).show(ghost);
+ });
+ if (!ghost){
+ this.hiddenNodes = [];
+ }
+ paper.view.draw();
+ },
+ setScale: function(_newScale, _offset) {
+ if ((_newScale/this.initialScale) > Utils._MIN_SCALE && (_newScale/this.initialScale) < Utils._MAX_SCALE) {
+ this.scale = _newScale;
+ if (_offset) {
+ this.offset = _offset;
+ }
+ this.renderer.redraw();
+ this.updateUrl();
+ }
+ },
+ zoomOut: function() {
+ var _newScale = this.scale * Math.SQRT1_2,
+ _offset = new paper.Point([
+ this.renderer.canvas_$.width(),
+ this.renderer.canvas_$.height()
+ ]).multiply( 0.5 * ( 1 - Math.SQRT1_2 ) ).add(this.offset.multiply( Math.SQRT1_2 ));
+ this.setScale( _newScale, _offset );
+ },
+ zoomIn: function() {
+ var _newScale = this.scale * Math.SQRT2,
+ _offset = new paper.Point([
+ this.renderer.canvas_$.width(),
+ this.renderer.canvas_$.height()
+ ]).multiply( 0.5 * ( 1 - Math.SQRT2 ) ).add(this.offset.multiply( Math.SQRT2 ));
+ this.setScale( _newScale, _offset );
+ },
+ resizeZoom: function(_scaleWidth, _scaleHeight, _ratio) {
+ var _newScale = this.scale * _ratio,
+ _offset = new paper.Point([
+ (this.offset.x * _scaleWidth),
+ (this.offset.y * _scaleHeight)
+ ]);
+ this.setScale( _newScale, _offset );
+ },
+ autoScale: function(force_view) {
+ var nodes = this.renkan.project.get("nodes");
+ if (nodes.length > 1) {
+ var _xx = nodes.map(function(_node) { return _node.get("position").x; }),
+ _yy = nodes.map(function(_node) { return _node.get("position").y; }),
+ _minx = Math.min.apply(Math, _xx),
+ _miny = Math.min.apply(Math, _yy),
+ _maxx = Math.max.apply(Math, _xx),
+ _maxy = Math.max.apply(Math, _yy);
+ 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));
+ this.initialScale = _scale;
+ // Override calculated scale if asked
+ if((typeof force_view !== "undefined") && parseFloat(force_view.zoom_level)>0 && parseFloat(force_view.offset.x)>0 && parseFloat(force_view.offset.y)>0){
+ this.setScale(parseFloat(force_view.zoom_level), new paper.Point(parseFloat(force_view.offset.x), parseFloat(force_view.offset.y)));
+ }
+ else{
+ this.setScale(_scale, paper.view.center.subtract(new paper.Point([(_maxx + _minx) / 2, (_maxy + _miny) / 2]).multiply(_scale)));
+ }
+ }
+ if (nodes.length === 1) {
+ this.setScale(1, paper.view.center.subtract(new paper.Point([nodes.at(0).get("position").x, nodes.at(0).get("position").y])));
+ }
+ },
+ paperShift: function(_delta) {
+ this.offset = this.offset.add(_delta);
+ this.renderer.redraw();
+ },
+ updateUrl: function(){
+ if(this.options.update_url){
+ var result = {};
+ var parameters = Backbone.history.getFragment().split('?');
+ if (parameters.length > 1){
+ parameters[1].split("&").forEach(function(part) {
+ var item = part.split("=");
+ result[item[0]] = decodeURIComponent(item[1]);
+ });
+ }
+ result.view = Math.round(this.offset.x*1000)/1000 + ',' + Math.round(this.offset.y*1000)/1000 + ',' + Math.round(this.scale*1000)/1000;
+
+ if (this.renkan.project.get("views").indexOf(this.model) > -1){
+ result.viewIndex = this.renkan.project.get("views").indexOf(this.model);
+ if (result.viewIndex === this.renkan.project.get("views").length - 1){
+ result.viewIndex = -1;
+ }
+ } else {
+ if (result.viewIndex){
+ delete result.viewIndex;
+ }
+ }
+ this.renkan.router.navigate("?" + decodeURIComponent($.param(result)), {trigger: false, replace: true});
+ }
+ },
+ destroy: function(_event) {
+ this._super("destroy");
+ this.showNodes(false);
+ }
+ }).value();
+
+ return ViewRepr;
+
+});
+
+
+//Load modules and use them
+if( typeof require.config === "function" ) {
+ require.config({
+ paths: {
+ 'jquery':'../lib/jquery/jquery',
+ 'underscore':'../lib/lodash/lodash',
+ 'filesaver' :'../lib/FileSaver/FileSaver',
+ 'requtils':'require-utils',
+ 'ckeditor-core':'../lib/ckeditor/ckeditor',
+ 'ckeditor-jquery':'../lib/ckeditor/adapters/jquery'
+ },
+ shim: {
+ 'ckeditor-jquery':{
+ deps:['jquery','ckeditor-core']
+ }
+ },
+ });
+}
+
+require(['renderer/baserepresentation',
+ 'renderer/basebutton',
+ 'renderer/noderepr',
+ 'renderer/edge',
+ 'renderer/tempedge',
+ 'renderer/baseeditor',
+ 'renderer/nodeeditor',
+ 'renderer/edgeeditor',
+ 'renderer/nodebutton',
+ 'renderer/nodeeditbutton',
+ 'renderer/noderemovebutton',
+ 'renderer/nodehidebutton',
+ 'renderer/nodeshowbutton',
+ 'renderer/noderevertbutton',
+ 'renderer/nodelinkbutton',
+ 'renderer/nodeenlargebutton',
+ 'renderer/nodeshrinkbutton',
+ 'renderer/edgeeditbutton',
+ 'renderer/edgeremovebutton',
+ 'renderer/edgerevertbutton',
+ 'renderer/miniframe',
+ 'renderer/scene',
+ 'renderer/viewrepr'
+ ], function(BaseRepresentation, BaseButton, NodeRepr, Edge, TempEdge, BaseEditor, NodeEditor, EdgeEditor, NodeButton, NodeEditButton, NodeRemoveButton, NodeHideButton, NodeShowButton, NodeRevertButton, NodeLinkButton, NodeEnlargeButton, NodeShrinkButton, EdgeEditButton, EdgeRemoveButton, EdgeRevertButton, MiniFrame, Scene, ViewRepr){
+
+ 'use strict';
+
+ var Rkns = window.Rkns;
+
+ if(typeof Rkns.Renderer === "undefined"){
+ Rkns.Renderer = {};
+ }
+ var Renderer = Rkns.Renderer;
+
+ Renderer._BaseRepresentation = BaseRepresentation;
+ Renderer._BaseButton = BaseButton;
+ Renderer.Node = NodeRepr;
+ Renderer.Edge = Edge;
+ Renderer.View = ViewRepr;
+ Renderer.TempEdge = TempEdge;
+ Renderer._BaseEditor = BaseEditor;
+ Renderer.NodeEditor = NodeEditor;
+ Renderer.EdgeEditor = EdgeEditor;
+ Renderer._NodeButton = NodeButton;
+ Renderer.NodeEditButton = NodeEditButton;
+ Renderer.NodeRemoveButton = NodeRemoveButton;
+ Renderer.NodeHideButton = NodeHideButton;
+ Renderer.NodeShowButton = NodeShowButton;
+ Renderer.NodeRevertButton = NodeRevertButton;
+ Renderer.NodeLinkButton = NodeLinkButton;
+ Renderer.NodeEnlargeButton = NodeEnlargeButton;
+ Renderer.NodeShrinkButton = NodeShrinkButton;
+ Renderer.EdgeEditButton = EdgeEditButton;
+ Renderer.EdgeRemoveButton = EdgeRemoveButton;
+ Renderer.EdgeRevertButton = EdgeRevertButton;
+ Renderer.MiniFrame = MiniFrame;
+ Renderer.Scene = Scene;
+
+ startRenkan();
+});
+
+define("main-renderer", function(){});
+
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/src/ldt/ldt/static/ldt/js/renkan.min.js Fri Oct 02 10:24:05 2015 +0200
@@ -0,0 +1,35 @@
+/*!
+ * _____ _
+ * | __ \ | |
+ * | |__) |___ _ __ | | ____ _ _ __
+ * | _ // _ \ '_ \| |/ / _` | '_ \
+ * | | \ \ __/ | | | < (_| | | | |
+ * |_| \_\___|_| |_|_|\_\__,_|_| |_|
+ *
+ * Copyright 2012-2015 Institut de recherche et d'innovation
+ * contributor(s) : Yves-Marie Haussonne, Raphael Velt, Samuel Huron,
+ * Thibaut Cavalié, Julien Rougeron.
+ *
+ * contact@iri.centrepompidou.fr
+ * http://www.iri.centrepompidou.fr
+ *
+ * This software is a computer program whose purpose is to show and add annotations on a video .
+ * This software is governed by the CeCILL-C license under French law and
+ * abiding by the rules of distribution of free software. You can use,
+ * modify and/ or redistribute the software under the terms of the CeCILL-C
+ * license as circulated by CEA, CNRS and INRIA at the following URL
+ * "http://www.cecill.info".
+ *
+ * The fact that you are presently reading this means that you have had
+ * knowledge of the CeCILL-C license and that you accept its terms.
+ */
+
+/*! renkan - v0.12.4 - Copyright © IRI 2015 */
+
+
+this.renkanJST=this.renkanJST||{},this.renkanJST["templates/colorpicker.html"]=function(obj){obj||(obj={});var __t,__p="";_.escape;with(obj)__p+='<li data-color="'+(null==(__t=c)?"":__t)+'" style="background: '+(null==(__t=c)?"":__t)+'"></li>';return __p},this.renkanJST["templates/edgeeditor.html"]=function(obj){obj||(obj={});var __t,__p="",__e=_.escape;Array.prototype.join;with(obj)__p+='<h2>\n <span class="Rk-CloseX">×</span>'+__e(renkan.translate("Edit Edge"))+"</span>\n</h2>\n<p>\n <label>"+__e(renkan.translate("Title:"))+'</label>\n <input class="Rk-Edit-Title" type="text" value="'+__e(edge.title)+'" />\n</p>\n',options.show_edge_editor_uri&&(__p+="\n <p>\n <label>"+__e(renkan.translate("URI:"))+'</label>\n <input class="Rk-Edit-URI" type="text" value="'+__e(edge.uri)+'" />\n <a class="Rk-Edit-Goto" href="'+__e(edge.uri)+'" target="_blank"></a>\n </p>\n ',options.properties.length&&(__p+="\n <p>\n <label>"+__e(renkan.translate("Choose from vocabulary:"))+'</label>\n <select class="Rk-Edit-Vocabulary">\n ',_.each(options.properties,function(a){__p+='\n <option class="Rk-Edit-Vocabulary-Class" value="">\n '+__e(renkan.translate(a.label))+"\n </option>\n ",_.each(a.properties,function(b){var c=a["base-uri"]+b.uri;__p+='\n <option class="Rk-Edit-Vocabulary-Property" value="'+__e(c)+'"\n ',c===edge.uri&&(__p+=" selected"),__p+=">\n "+__e(renkan.translate(b.label))+"\n </option>\n "}),__p+="\n "}),__p+="\n </select>\n </p>\n")),__p+="\n",options.show_edge_editor_style&&(__p+='\n <div class="Rk-Editor-p">\n ',options.show_edge_editor_style_color&&(__p+='\n <div id="Rk-Editor-p-color">\n <span class="Rk-Editor-Label">'+__e(renkan.translate("Edge color:"))+'</span>\n <div class="Rk-Edit-ColorPicker-Wrapper">\n <span class="Rk-Edit-Color" style="background: <%-edge.color%>;">\n <span class="Rk-Edit-ColorTip"></span>\n </span>\n '+(null==(__t=renkan.colorPicker)?"":__t)+'\n <span class="Rk-Edit-ColorPicker-Text">'+__e(renkan.translate("Choose color"))+"</span>\n </div>\n </div>\n "),__p+="\n ",options.show_edge_editor_style_dash&&(__p+='\n <div id="Rk-Editor-p-dash">\n <span class="Rk-Editor-Label">'+__e(renkan.translate("Dash:"))+'</span>\n <input type="checkbox" name="Rk-Edit-Dash" class="Rk-Edit-Dash" '+__e(edge.dash)+" />\n </div>\n "),__p+="\n ",options.show_edge_editor_style_thickness&&(__p+='\n <div id="Rk-Editor-p-thickness">\n <span class="Rk-Editor-Label">'+__e(renkan.translate("Thickness:"))+'</span>\n <a href="#" class="Rk-Edit-Size-Btn" id="Rk-Edit-Thickness-Down">-</a>\n <span class="Rk-Edit-Size-Disp" id="Rk-Edit-Thickness-Value">'+__e(edge.thickness)+'</span>\n <a href="#" class="Rk-Edit-Size-Btn" id="Rk-Edit-Thickness-Up">+</a>\n </div>\n '),__p+="\n ",options.show_edge_editor_style_arrow&&(__p+='\n <div id="Rk-Editor-p-arrow">\n <span class="Rk-Editor-Label">'+__e(renkan.translate("Arrow:"))+'</span>\n <input type="checkbox" name="Rk-Edit-Arrow" class="Rk-Edit-Arrow" '+__e(edge.arrow)+" />\n </div>\n "),__p+="\n </div>\n"),__p+="\n",options.show_edge_editor_direction&&(__p+='\n <p>\n <span class="Rk-Edit-Direction">'+__e(renkan.translate("Change edge direction"))+"</span>\n </p>\n"),__p+="\n",options.show_edge_editor_nodes&&(__p+='\n <p>\n <span class="Rk-Editor-Label">'+__e(renkan.translate("From:"))+'</span>\n <span class="Rk-UserColor" style="background: '+__e(edge.from_color)+';"></span>\n '+__e(shortenText(edge.from_title,25))+'\n </p>\n <p>\n <span class="Rk-Editor-Label">'+__e(renkan.translate("To:"))+'</span>\n <span class="Rk-UserColor" style="background: >%-edge.to_color%>;"></span>\n '+__e(shortenText(edge.to_title,25))+"\n </p>\n"),__p+="\n",options.show_edge_editor_creator&&edge.has_creator&&(__p+='\n <p>\n <span class="Rk-Editor-Label">'+__e(renkan.translate("Created by:"))+'</span>\n <span class="Rk-UserColor" style="background: <%-edge.created_by_color%>;"></span>\n '+__e(shortenText(edge.created_by_title,25))+"\n </p>\n"),__p+="\n";return __p},this.renkanJST["templates/edgeeditor_readonly.html"]=function(obj){obj||(obj={});var __t,__p="",__e=_.escape;Array.prototype.join;with(obj)__p+='<h2>\n <span class="Rk-CloseX">×</span>\n ',options.show_edge_tooltip_color&&(__p+='\n <span class="Rk-UserColor" style="background: '+__e(edge.color)+';"></span>\n '),__p+='\n <span class="Rk-Display-Title">\n ',edge.uri&&(__p+='\n <a href="'+__e(edge.uri)+'" target="_blank">\n '),__p+="\n "+__e(edge.title)+"\n ",edge.uri&&(__p+=" </a> "),__p+="\n </span>\n</h2>\n",options.show_edge_tooltip_uri&&edge.uri&&(__p+='\n <p class="Rk-Display-URI">\n <a href="'+__e(edge.uri)+'" target="_blank">'+__e(edge.short_uri)+"</a>\n </p>\n"),__p+="\n<p>"+(null==(__t=edge.description)?"":__t)+"</p>\n",options.show_edge_tooltip_nodes&&(__p+='\n <p>\n <span class="Rk-Editor-Label">'+__e(renkan.translate("From:"))+'</span>\n <span class="Rk-UserColor" style="background: '+__e(edge.from_color)+';"></span>\n '+__e(shortenText(edge.from_title,25))+'\n </p>\n <p>\n <span class="Rk-Editor-Label">'+__e(renkan.translate("To:"))+'</span>\n <span class="Rk-UserColor" style="background: '+__e(edge.to_color)+';"></span>\n '+__e(shortenText(edge.to_title,25))+"\n </p>\n"),__p+="\n",options.show_edge_tooltip_creator&&edge.has_creator&&(__p+='\n <p>\n <span class="Rk-Editor-Label">'+__e(renkan.translate("Created by:"))+'</span>\n <span class="Rk-UserColor" style="background: '+__e(edge.created_by_color)+';"></span>\n '+__e(shortenText(edge.created_by_title,25))+"\n </p>\n"),__p+="\n";return __p},this.renkanJST["templates/ldtjson-bin/annotationtemplate.html"]=function(obj){obj||(obj={});var __t,__p="",__e=_.escape;with(obj)__p+='<li class="Rk-Bin-Item" draggable="true"\n data-image="'+__e(Rkns.Utils.getFullURL(image))+'"\n data-uri="'+(null==(__t=ldt_platform)?"":__t)+"ldtplatform/ldt/front/player/"+(null==(__t=mediaid)?"":__t)+"/#id="+(null==(__t=annotationid)?"":__t)+'"\n data-title="'+__e(title)+'" data-description="'+__e(description)+'">\n\n <img class="Rk-Ldt-Annotation-Icon" src="'+(null==(__t=image)?"":__t)+'" />\n <h4>'+(null==(__t=htitle)?"":__t)+"</h4>\n <p>"+(null==(__t=hdescription)?"":__t)+"</p>\n <p>Start: "+(null==(__t=start)?"":__t)+", End: "+(null==(__t=end)?"":__t)+", Duration: "+(null==(__t=duration)?"":__t)+'</p>\n <div class="Rk-Clear"></div>\n</li>\n';return __p},this.renkanJST["templates/ldtjson-bin/segmenttemplate.html"]=function(obj){obj||(obj={});var __t,__p="",__e=_.escape;with(obj)__p+='<li class="Rk-Bin-Item" draggable="true"\n data-image="'+__e(Rkns.Utils.getFullURL(image))+'"\n data-uri="'+(null==(__t=ldt_platform)?"":__t)+"ldtplatform/ldt/front/player/"+(null==(__t=mediaid)?"":__t)+"/#id="+(null==(__t=annotationid)?"":__t)+'"\n data-title="'+__e(title)+'" data-description="'+__e(description)+'">\n\n <img class="Rk-Ldt-Annotation-Icon" src="'+(null==(__t=image)?"":__t)+'" />\n <h4>'+(null==(__t=htitle)?"":__t)+"</h4>\n <p>"+(null==(__t=hdescription)?"":__t)+"</p>\n <p>Start: "+(null==(__t=start)?"":__t)+", End: "+(null==(__t=end)?"":__t)+", Duration: "+(null==(__t=duration)?"":__t)+'</p>\n <div class="Rk-Clear"></div>\n</li>\n';return __p},this.renkanJST["templates/ldtjson-bin/tagtemplate.html"]=function(obj){obj||(obj={});var __t,__p="",__e=_.escape;with(obj)__p+='<li class="Rk-Bin-Item" draggable="true"\n data-image="'+__e(Rkns.Utils.getFullURL(static_url+"img/ldt-tag.png"))+'"\n data-uri="'+(null==(__t=ldt_platform)?"":__t)+"ldtplatform/ldt/front/search/?search="+(null==(__t=encodedtitle)?"":__t)+'&field=all"\n data-title="'+__e(title)+'" data-description="Tag \''+__e(title)+'\'">\n\n <img class="Rk-Ldt-Tag-Icon" src="'+__e(static_url)+'img/ldt-tag.png" />\n <h4>'+(null==(__t=htitle)?"":__t)+'</h4>\n <div class="Rk-Clear"></div>\n</li>\n';return __p},this.renkanJST["templates/list-bin.html"]=function(obj){obj||(obj={});var __t,__p="",__e=_.escape;Array.prototype.join;with(obj)__p+='<li class="Rk-Bin-Item Rk-ResourceList-Item" draggable="true"\n data-uri="'+__e(url)+'" data-title="'+__e(title)+'"\n data-description="'+__e(description)+'"\n ',__p+=image?'\n data-image="'+__e(Rkns.Utils.getFullURL(image))+'"\n ':'\n data-image=""\n ',__p+="\n>",image&&(__p+='\n <img class="Rk-ResourceList-Image" src="'+__e(image)+'" />\n'),__p+='\n<h4 class="Rk-ResourceList-Title">\n ',url&&(__p+='\n <a href="'+__e(url)+'" target="_blank">\n '),__p+="\n "+(null==(__t=htitle)?"":__t)+"\n ",url&&(__p+="</a>"),__p+="\n </h4>\n ",description&&(__p+='\n <p class="Rk-ResourceList-Description">'+(null==(__t=hdescription)?"":__t)+"</p>\n "),__p+="\n ",image&&(__p+='\n <div style="clear: both;"></div>\n '),__p+="\n</li>\n";return __p},this.renkanJST["templates/main.html"]=function(obj){obj||(obj={});var __p="",__e=_.escape;Array.prototype.join;with(obj)options.show_bins&&(__p+='\n <div class="Rk-Bins">\n <div class="Rk-Bins-Head">\n <h2 class="Rk-Bins-Title">'+__e(translate("Select contents:"))+'</h2>\n <form class="Rk-Web-Search-Form Rk-Search-Form">\n <input class="Rk-Web-Search-Input Rk-Search-Input" type="search"\n placeholder="'+__e(translate("Search the Web"))+'" />\n <div class="Rk-Search-Select">\n <div class="Rk-Search-Current"></div>\n <ul class="Rk-Search-List"></ul>\n </div>\n <input type="submit" value=""\n class="Rk-Web-Search-Submit Rk-Search-Submit" title="'+__e(translate("Search the Web"))+'" />\n </form>\n <form class="Rk-Bins-Search-Form Rk-Search-Form">\n <input class="Rk-Bins-Search-Input Rk-Search-Input" type="search"\n placeholder="'+__e(translate("Search in Bins"))+'" /> <input\n type="submit" value=""\n class="Rk-Bins-Search-Submit Rk-Search-Submit"\n title="'+__e(translate("Search in Bins"))+'" />\n </form>\n </div>\n <ul class="Rk-Bin-List"></ul>\n </div>\n'),__p+=" ",options.show_editor&&(__p+='\n <div class="Rk-Render Rk-Render-',__p+=options.show_bins?"Panel":"Full",__p+='"></div>\n'),__p+="\n";return __p},this.renkanJST["templates/nodeeditor.html"]=function(obj){obj||(obj={});var __t,__p="",__e=_.escape;Array.prototype.join;with(obj)__p+='\n<h2>\n <span class="Rk-CloseX">×</span>'+__e(renkan.translate("Edit Node"))+"</span>\n</h2>\n<p>\n <label>"+__e(renkan.translate("Title:"))+'</label>\n <input class="Rk-Edit-Title" type="text" value="'+__e(node.title)+'" />\n</p>\n',options.show_node_editor_uri&&(__p+="\n <p>\n <label>"+__e(renkan.translate("URI:"))+'</label>\n <input class="Rk-Edit-URI" type="text" value="'+__e(node.uri)+'" />\n <a class="Rk-Edit-Goto" href="'+__e(node.uri)+'" target="_blank"></a>\n </p>\n'),__p+=" ",options.change_types&&(__p+="\n <p>\n <label>"+__e(renkan.translate("Types available"))+':</label>\n <select class="Rk-Edit-Type">\n ',_.each(types,function(a){__p+='\n <option class="Rk-Edit-Vocabulary-Property" value="'+__e(a)+'"',node.type===a&&(__p+=" selected"),__p+=">\n "+__e(renkan.translate(a.charAt(0).toUpperCase()+a.substring(1)))+"\n </option>\n "}),__p+="\n </select>\n </p>\n"),__p+=" ",options.show_node_editor_description&&(__p+="\n <p>\n <label>"+__e(renkan.translate("Description:"))+"</label>\n ",__p+=options.show_node_editor_description_richtext?'\n <div class="Rk-Edit-Description" contenteditable="true">'+(null==(__t=node.description)?"":__t)+"</div>\n ":'\n <textarea class="Rk-Edit-Description">'+(null==(__t=node.description)?"":__t)+"</textarea>\n ",__p+="\n </p>\n"),__p+=" ",options.show_node_editor_size&&(__p+='\n <p>\n <span class="Rk-Editor-Label">'+__e(renkan.translate("Size:"))+'</span>\n <a href="#" class="Rk-Edit-Size-Btn" id="Rk-Edit-Size-Down">-</a>\n <span class="Rk-Edit-Size-Disp" id="Rk-Edit-Size-Value">'+__e(node.size)+'</span>\n <a href="#" class="Rk-Edit-Size-Btn" id="Rk-Edit-Size-Up">+</a>\n </p>\n'),__p+=" ",options.show_node_editor_style&&(__p+='\n <div class="Rk-Editor-p">\n ',options.show_node_editor_style_color&&(__p+='\n <div id="Rk-Editor-p-color">\n <span class="Rk-Editor-Label">\n '+__e(renkan.translate("Node color:"))+'</span>\n <div class="Rk-Edit-ColorPicker-Wrapper">\n <span class="Rk-Edit-Color" style="background: '+__e(node.color)+';">\n <span class="Rk-Edit-ColorTip"></span>\n </span>\n '+(null==(__t=renkan.colorPicker)?"":__t)+'\n <span class="Rk-Edit-ColorPicker-Text">'+__e(renkan.translate("Choose color"))+"</span>\n </div>\n </div>\n "),__p+="\n ",options.show_node_editor_style_dash&&(__p+='\n <div id="Rk-Editor-p-dash">\n <span class="Rk-Editor-Label">'+__e(renkan.translate("Dash:"))+'</span>\n <input type="checkbox" name="Rk-Edit-Dash" class="Rk-Edit-Dash" '+__e(node.dash)+" />\n </div>\n "),__p+="\n ",options.show_node_editor_style_thickness&&(__p+='\n <div id="Rk-Editor-p-thickness">\n <span class="Rk-Editor-Label">'+__e(renkan.translate("Thickness:"))+'</span>\n <a href="#" class="Rk-Edit-Size-Btn" id="Rk-Edit-Thickness-Down">-</a>\n <span class="Rk-Edit-Size-Disp" id="Rk-Edit-Thickness-Value">'+__e(node.thickness)+'</span>\n <a href="#" class="Rk-Edit-Size-Btn" id="Rk-Edit-Thickness-Up">+</a>\n </div>\n '),__p+="\n </div>\n"),__p+=" ",options.show_node_editor_image&&(__p+='\n <div class="Rk-Edit-ImgWrap">\n <div class="Rk-Edit-ImgPreview">\n <img src="'+__e(node.image||node.image_placeholder)+'" />\n ',node.clip_path&&(__p+='\n <svg xmlns="http://www.w3.org/2000/svg" version="1.1" viewbox="0 0 1 1" preserveAspectRatio="none">\n <path style="stroke-width: .02; stroke:red; fill-opacity:.3; fill:red;" d="'+__e(node.clip_path)+'" />\n </svg>\n '),__p+="\n </div>\n </div>\n <p>\n <label>"+__e(renkan.translate("Image URL:"))+'</label>\n <div>\n <a class="Rk-Edit-Image-Del" href="#"></a>\n <input class="Rk-Edit-Image" type="text" value=\''+__e(node.image)+"' />\n </div>\n </p>\n",options.allow_image_upload&&(__p+="\n <p>\n <label>"+__e(renkan.translate("Choose Image File:"))+'</label>\n <input class="Rk-Edit-Image-File" type="file" accept="image/*" />\n </p>\n')),__p+=" ",options.show_node_editor_creator&&node.has_creator&&(__p+='\n <p>\n <span class="Rk-Editor-Label">'+__e(renkan.translate("Created by:"))+'</span>\n <span class="Rk-UserColor" style="background: '+__e(node.created_by_color)+';"></span>\n '+__e(shortenText(node.created_by_title,25))+"\n </p>\n"),__p+=" ",options.change_shapes&&(__p+="\n <p>\n <label>"+__e(renkan.translate("Shapes available"))+':</label>\n <select class="Rk-Edit-Shape">\n ',_.each(shapes,function(a){__p+='\n <option class="Rk-Edit-Vocabulary-Property" value="'+__e(a)+'"',node.shape===a&&(__p+=" selected"),__p+=">\n "+__e(renkan.translate(a.charAt(0).toUpperCase()+a.substring(1)))+"\n </option>\n "}),__p+="\n </select>\n </p>\n"),__p+="\n";return __p},this.renkanJST["templates/nodeeditor_readonly.html"]=function(obj){obj||(obj={});var __t,__p="",__e=_.escape;Array.prototype.join;with(obj)__p+='<h2>\n <span class="Rk-CloseX">×</span>\n ',options.show_node_tooltip_color&&(__p+='\n <span class="Rk-UserColor" style="background: '+__e(node.color)+';"></span>\n '),__p+='\n <span class="Rk-Display-Title">\n ',node.uri&&(__p+='\n <a href="'+__e(node.uri)+'" target="_blank">\n '),__p+="\n "+__e(node.title)+"\n ",node.uri&&(__p+="</a>"),__p+="\n </span>\n</h2>\n",node.uri&&options.show_node_tooltip_uri&&(__p+='\n <p class="Rk-Display-URI">\n <a href="'+__e(node.uri)+'" target="_blank">'+__e(node.short_uri)+"</a>\n </p>\n"),__p+=" ",options.show_node_tooltip_description&&(__p+='\n <p class="Rk-Display-Description">'+(null==(__t=node.description)?"":__t)+"</p>\n"),__p+=" ",node.image&&options.show_node_tooltip_image&&(__p+='\n <img class="Rk-Display-ImgPreview" src="'+__e(node.image)+'" />\n'),__p+=" ",node.has_creator&&options.show_node_tooltip_creator&&(__p+='\n <p>\n <span class="Rk-Editor-Label">'+__e(renkan.translate("Created by:"))+'</span>\n <span class="Rk-UserColor" style="background: '+__e(node.created_by_color)+';"></span>\n '+__e(shortenText(node.created_by_title,25))+"\n </p>\n"),__p+='\n <a href="#?idNode='+__e(node._id)+'">'+__e(renkan.translate("Link to the node"))+"</a>\n";return __p},this.renkanJST["templates/nodeeditor_video.html"]=function(obj){obj||(obj={});var __p="",__e=_.escape;Array.prototype.join;with(obj)__p+='<h2>\n <span class="Rk-CloseX">×</span>\n ',options.show_node_tooltip_color&&(__p+='\n <span class="Rk-UserColor" style="background: '+__e(node.color)+';"></span>\n '),__p+='\n <span class="Rk-Display-Title">\n ',node.uri&&(__p+='\n <a href="'+__e(node.uri)+'" target="_blank">\n '),__p+="\n "+__e(node.title)+"\n ",node.uri&&(__p+="</a>"),__p+="\n </span>\n</h2>\n",node.uri&&options.show_node_tooltip_uri&&(__p+='\n <video width="320" height="240" controls>\n <source src="'+__e(node.uri)+'" type="video/mp4">\n </video> \n'),__p+='\n <a href="#?idnode='+__e(node._id)+'">'+__e(renkan.translate("Link to the node"))+"</a>\n";return __p},this.renkanJST["templates/scene.html"]=function(obj){function print(){__p+=__j.call(arguments,"")}obj||(obj={});var __p="",__e=_.escape,__j=Array.prototype.join;with(obj)options.show_top_bar&&(__p+='\n <div class="Rk-TopBar">\n <div class="loader"></div>\n ',__p+=options.editor_mode?'\n <input type="text" class="Rk-PadTitle" value="'+__e(project.get("title")||"")+'" placeholder="'+__e(translate("Untitled project"))+'" />\n ':'\n <h2 class="Rk-PadTitle">\n '+__e(project.get("title")||translate("Untitled project"))+"\n </h2>\n ",__p+="\n ",options.show_user_list&&(__p+='\n <div class="Rk-Users">\n <div class="Rk-CurrentUser">\n ',options.show_user_color&&(__p+='\n <div class="Rk-Edit-ColorPicker-Wrapper">\n <span class="Rk-CurrentUser-Color">\n ',options.user_color_editable&&(__p+='\n <span class="Rk-Edit-ColorTip"></span>\n '),__p+="\n </span>\n ",options.user_color_editable&&print(colorPicker),__p+="\n </div>\n "),__p+='\n <span class="Rk-CurrentUser-Name"><unknown user></span>\n </div>\n <ul class="Rk-UserList"></ul>\n </div>\n '),__p+="\n ",options.home_button_url&&(__p+='\n <div class="Rk-TopBar-Separator"></div>\n <a class="Rk-TopBar-Button Rk-Home-Button" href="'+__e(options.home_button_url)+'">\n <div class="Rk-TopBar-Tooltip">\n <div class="Rk-TopBar-Tooltip-Contents">\n '+__e(translate(options.home_button_title))+"\n </div>\n </div>\n </a>\n "),__p+="\n ",options.show_fullscreen_button&&(__p+='\n <div class="Rk-TopBar-Separator"></div>\n <div class="Rk-TopBar-Button Rk-FullScreen-Button">\n <div class="Rk-TopBar-Tooltip">\n <div class="Rk-TopBar-Tooltip-Contents">\n '+__e(translate("Full Screen"))+"\n </div>\n </div>\n </div>\n "),__p+="\n ",options.editor_mode?(__p+="\n ",options.show_addnode_button&&(__p+='\n <div class="Rk-TopBar-Separator"></div>\n <div class="Rk-TopBar-Button Rk-AddNode-Button">\n <div class="Rk-TopBar-Tooltip">\n <div class="Rk-TopBar-Tooltip-Contents">\n '+__e(translate("Add Node"))+"\n </div>\n </div>\n </div>\n "),__p+="\n ",options.show_addedge_button&&(__p+='\n <div class="Rk-TopBar-Separator"></div>\n <div class="Rk-TopBar-Button Rk-AddEdge-Button">\n <div class="Rk-TopBar-Tooltip">\n <div class="Rk-TopBar-Tooltip-Contents">\n '+__e(translate("Add Edge"))+"\n </div>\n </div>\n </div>\n "),__p+="\n ",options.show_export_button&&(__p+='\n <div class="Rk-TopBar-Separator"></div>\n <div class="Rk-TopBar-Button Rk-Export-Button">\n <div class="Rk-TopBar-Tooltip">\n <div class="Rk-TopBar-Tooltip-Contents">\n '+__e(translate("Download Project"))+"\n </div>\n </div>\n </div>\n "),__p+="\n ",options.show_save_button&&(__p+='\n <div class="Rk-TopBar-Separator"></div>\n <div class="Rk-TopBar-Button Rk-Save-Button">\n <div class="Rk-TopBar-Tooltip">\n <div class="Rk-TopBar-Tooltip-Contents"></div>\n </div>\n </div>\n '),__p+="\n ",options.show_open_button&&(__p+='\n <div class="Rk-TopBar-Separator"></div>\n <div class="Rk-TopBar-Button Rk-Open-Button">\n <div class="Rk-TopBar-Tooltip">\n <div class="Rk-TopBar-Tooltip-Contents">\n '+__e(translate("Open Project"))+"\n </div>\n </div>\n </div>\n "),__p+="\n ",options.show_bookmarklet&&(__p+='\n <div class="Rk-TopBar-Separator"></div>\n <a class="Rk-TopBar-Button Rk-Bookmarklet-Button" href="#">\n <div class="Rk-TopBar-Tooltip">\n <div class="Rk-TopBar-Tooltip-Contents">\n '+__e(translate("Renkan 'Drag-to-Add' bookmarklet"))+'\n </div>\n </div>\n </a>\n <div class="Rk-TopBar-Separator"></div>\n '),__p+="\n "):(__p+="\n ",options.show_export_button&&(__p+='\n <div class="Rk-TopBar-Separator"></div>\n <div class="Rk-TopBar-Button Rk-Export-Button">\n <div class="Rk-TopBar-Tooltip">\n <div class="Rk-TopBar-Tooltip-Contents">\n '+__e(translate("Download Project"))+'\n </div>\n </div>\n </div>\n <div class="Rk-TopBar-Separator"></div>\n '),__p+="\n "),__p+="\n ",options.show_search_field&&(__p+='\n <form action="#" class="Rk-GraphSearch-Form">\n <input type="search" class="Rk-GraphSearch-Field" placeholder="'+__e(translate("Search in graph"))+'" />\n </form>\n <div class="Rk-TopBar-Separator"></div>\n '),__p+="\n </div>\n"),__p+='\n<div class="Rk-Editing-Space',options.show_top_bar||(__p+=" Rk-Editing-Space-Full"),__p+='">\n <div class="Rk-Labels"></div>\n <canvas class="Rk-Canvas" ',options.resize&&(__p+=' resize="" '),__p+=' ></canvas>\n <div class="Rk-Notifications"></div>\n <div class="Rk-Editor">\n ',options.show_bins&&(__p+='\n <div class="Rk-Fold-Bins">«</div>\n '),__p+="\n ",options.show_zoom&&(__p+='\n <div class="Rk-ZoomButtons">\n <div class="Rk-ZoomIn" title="'+__e(translate("Zoom In"))+'"></div>\n <div class="Rk-ZoomFit" title="'+__e(translate("Zoom Fit"))+'"></div>\n <div class="Rk-ZoomOut" title="'+__e(translate("Zoom Out"))+'"></div>\n ',options.editor_mode&&options.save_view&&(__p+='\n <div class="Rk-ZoomSave" title="'+__e(translate("Save view"))+'"></div>\n '),__p+="\n ",options.save_view&&(__p+='\n <div class="Rk-ZoomSetSaved" title="'+__e(translate("View saved view"))+'"></div>\n ',options.hide_nodes&&(__p+='\n <div class="Rk-ShowHiddenNodes" title="'+__e(translate("Show hidden nodes"))+'"></div>\n '),__p+=" \n "),__p+="\n </div>\n "),__p+="\n </div>\n</div>\n";return __p},this.renkanJST["templates/search.html"]=function(obj){obj||(obj={});var __t,__p="";_.escape;with(obj)__p+='<li class="'+(null==(__t=className)?"":__t)+'" data-key="'+(null==(__t=key)?"":__t)+'">'+(null==(__t=title)?"":__t)+"</li>";return __p},this.renkanJST["templates/wikipedia-bin/resulttemplate.html"]=function(obj){obj||(obj={});var __t,__p="",__e=_.escape;with(obj)__p+='<li class="Rk-Wikipedia-Result Rk-Bin-Item" draggable="true"\n data-uri="'+__e(url)+'" data-title="Wikipedia: '+__e(title)+'"\n data-description="'+__e(description)+'"\n data-image="'+__e(Rkns.Utils.getFullURL(static_url+"img/wikipedia.png"))+'">\n\n <img class="Rk-Wikipedia-Icon" src="'+__e(static_url)+'img/wikipedia.png">\n <h4 class="Rk-Wikipedia-Title">\n <a href="'+__e(url)+'" target="_blank">'+(null==(__t=htitle)?"":__t)+'</a>\n </h4>\n <p class="Rk-Wikipedia-Snippet">'+(null==(__t=hdescription)?"":__t)+"</p>\n</li>\n";return __p},function(a){"use strict";"object"!=typeof a.Rkns&&(a.Rkns={});var b=a.Rkns,c=b.$=a.jQuery,d=b._=a._;b.pickerColors=["#8f1919","#a80000","#d82626","#ff0000","#e87c7c","#ff6565","#f7d3d3","#fecccc","#8f5419","#a85400","#d87f26","#ff7f00","#e8b27c","#ffb265","#f7e5d3","#fee5cc","#8f8f19","#a8a800","#d8d826","#feff00","#e8e87c","#feff65","#f7f7d3","#fefecc","#198f19","#00a800","#26d826","#00ff00","#7ce87c","#65ff65","#d3f7d3","#ccfecc","#198f8f","#00a8a8","#26d8d8","#00feff","#7ce8e8","#65feff","#d3f7f7","#ccfefe","#19198f","#0000a8","#2626d8","#0000ff","#7c7ce8","#6565ff","#d3d3f7","#ccccfe","#8f198f","#a800a8","#d826d8","#ff00fe","#e87ce8","#ff65fe","#f7d3f7","#feccfe","#000000","#242424","#484848","#6d6d6d","#919191","#b6b6b6","#dadada","#ffffff"],b.__renkans=[];var e=b._BaseBin=function(a,c){if("undefined"!=typeof a){this.renkan=a,this.renkan.$.find(".Rk-Bin-Main").hide(),this.$=b.$("<li>").addClass("Rk-Bin").appendTo(a.$.find(".Rk-Bin-List")),this.title_icon_$=b.$("<span>").addClass("Rk-Bin-Title-Icon").appendTo(this.$);var d=this;b.$("<a>").attr({href:"#",title:a.translate("Close bin")}).addClass("Rk-Bin-Close").html("×").appendTo(this.$).click(function(){return d.destroy(),a.$.find(".Rk-Bin-Main:visible").length||a.$.find(".Rk-Bin-Main:last").slideDown(),a.resizeBins(),!1}),b.$("<a>").attr({href:"#",title:a.translate("Refresh bin")}).addClass("Rk-Bin-Refresh").appendTo(this.$).click(function(){return d.refresh(),!1}),this.count_$=b.$("<div>").addClass("Rk-Bin-Count").appendTo(this.$),this.title_$=b.$("<h2>").addClass("Rk-Bin-Title").appendTo(this.$),this.main_$=b.$("<div>").addClass("Rk-Bin-Main").appendTo(this.$).html('<h4 class="Rk-Bin-Loading">'+a.translate("Loading, please wait")+"</h4>"),this.title_$.html(c.title||"(new bin)"),this.renkan.resizeBins(),c.auto_refresh&&window.setInterval(function(){d.refresh()},c.auto_refresh)}};e.prototype.destroy=function(){this.$.detach(),this.renkan.resizeBins()};var f=b.Renkan=function(a){var e=this;b.__renkans.push(this),this.options=d.defaults(a,b.defaults,{templates:d.defaults(a.templates,renkanJST)||renkanJST,node_editor_templates:d.defaults(a.node_editor_templates,b.defaults.node_editor_templates)}),this.template=renkanJST["templates/main.html"];var f={};if(d.each(this.options.node_editor_templates,function(a,b){f[b]=e.options.templates[a],delete e.options.templates[a]}),this.options.node_editor_templates=f,d.each(this.options.property_files,function(a){b.$.getJSON(a,function(a){e.options.properties=e.options.properties.concat(a)})}),this.read_only=this.options.read_only||!this.options.editor_mode,this.router=new b.Router,this.project=new b.Models.Project,this.dataloader=new b.DataLoader.Loader(this.project,this.options),this.setCurrentUser=function(a,b){this.project.addUser({_id:a,title:b}),this.current_user=a,this.renderer.redrawUsers()},"undefined"!=typeof this.options.user_id&&(this.current_user=this.options.user_id),this.$=b.$("#"+this.options.container),this.$.addClass("Rk-Main").html(this.template(this)),this.tabs=[],this.search_engines=[],this.current_user_list=new b.Models.UsersList,this.current_user_list.on("add remove",function(){this.renderer&&this.renderer.redrawUsers()}),this.colorPicker=function(){var a=renkanJST["templates/colorpicker.html"];return'<ul class="Rk-Edit-ColorPicker">'+b.pickerColors.map(function(b){return a({c:b})}).join("")+"</ul>"}(),this.options.show_editor&&(this.renderer=new b.Renderer.Scene(this)),this.options.search.length){var g=renkanJST["templates/search.html"],h=this.$.find(".Rk-Search-List"),i=this.$.find(".Rk-Web-Search-Input"),j=this.$.find(".Rk-Web-Search-Form");d.each(this.options.search,function(a,c){b[a.type]&&b[a.type].Search&&e.search_engines.push(new b[a.type].Search(e,a))}),h.html(d(this.search_engines).map(function(a,b){return g({key:b,title:a.getSearchTitle(),className:a.getBgClass()})}).join("")),h.find("li").click(function(){var a=b.$(this);e.setSearchEngine(a.attr("data-key")),j.submit()}),j.submit(function(){if(i.val()){var a=e.search_engine;a.search(i.val())}return!1}),this.$.find(".Rk-Search-Current").mouseenter(function(){h.slideDown()}),this.$.find(".Rk-Search-Select").mouseleave(function(){h.hide()}),this.setSearchEngine(0)}else this.$.find(".Rk-Web-Search-Form").detach();d.each(this.options.bins,function(a){b[a.type]&&b[a.type].Bin&&e.tabs.push(new b[a.type].Bin(e,a))});var k=!1;this.$.find(".Rk-Bins").on("click",".Rk-Bin-Title,.Rk-Bin-Title-Icon",function(){var a=b.$(this).siblings(".Rk-Bin-Main");a.is(":hidden")&&(e.$.find(".Rk-Bin-Main").slideUp(),a.slideDown())}),this.options.show_editor&&this.$.find(".Rk-Bins").on("mouseover",".Rk-Bin-Item",function(a){var f=b.$(this);if(f&&c(f).attr("data-uri")){var g=e.project.get("nodes").where({uri:c(f).attr("data-uri")});d.each(g,function(a){e.renderer.highlightModel(a)})}}).mouseout(function(){
+e.renderer.unhighlightAll()}).on("mousemove",".Rk-Bin-Item",function(a){try{this.dragDrop()}catch(b){}}).on("touchstart",".Rk-Bin-Item",function(a){k=!1}).on("touchmove",".Rk-Bin-Item",function(a){a.preventDefault();var b=a.originalEvent.changedTouches[0],c=e.renderer.canvas_$.offset(),d=e.renderer.canvas_$.width(),f=e.renderer.canvas_$.height();if(b.pageX>=c.left&&b.pageX<c.left+d&&b.pageY>=c.top&&b.pageY<c.top+f)if(k)e.renderer.onMouseMove(b,!0);else{k=!0;var g=document.createElement("div");g.appendChild(this.cloneNode(!0)),e.renderer.dropData({"text/html":g.innerHTML},b),e.renderer.onMouseDown(b,!0)}}).on("touchend",".Rk-Bin-Item",function(a){k&&e.renderer.onMouseUp(a.originalEvent.changedTouches[0],!0),k=!1}).on("dragstart",".Rk-Bin-Item",function(a){var b=document.createElement("div");b.appendChild(this.cloneNode(!0));try{a.originalEvent.dataTransfer.setData("text/html",b.innerHTML)}catch(c){a.originalEvent.dataTransfer.setData("text",b.innerHTML)}}),b.$(window).resize(function(){e.resizeBins()});var l=!1,m="";this.$.find(".Rk-Bins-Search-Input").on("change keyup paste input",function(){var a=b.$(this).val();if(a!==m){var c=b.Utils.regexpFromTextOrArray(a.length>1?a:null);c.source!==l&&(l=c.source,d.each(e.tabs,function(a){a.render(c)}))}}),this.$.find(".Rk-Bins-Search-Form").submit(function(){return!1})};f.prototype.translate=function(a){return b.i18n[this.options.language]&&b.i18n[this.options.language][a]?b.i18n[this.options.language][a]:this.options.language.length>2&&b.i18n[this.options.language.substr(0,2)]&&b.i18n[this.options.language.substr(0,2)][a]?b.i18n[this.options.language.substr(0,2)][a]:a},f.prototype.onStatusChange=function(){this.renderer.onStatusChange()},f.prototype.setSearchEngine=function(a){this.search_engine=this.search_engines[a],this.$.find(".Rk-Search-Current").attr("class","Rk-Search-Current "+this.search_engine.getBgClass());for(var b=this.search_engine.getBgClass().split(" "),c="",d=0;d<b.length;d++)c+="."+b[d];this.$.find(".Rk-Web-Search-Input.Rk-Search-Input").attr("placeholder",this.translate("Search in ")+this.$.find(".Rk-Search-List "+c).html())},f.prototype.resizeBins=function(){var a=+this.$.find(".Rk-Bins-Head").outerHeight();this.$.find(".Rk-Bin-Title:visible").each(function(){a+=b.$(this).outerHeight()}),this.$.find(".Rk-Bin-Main").css({height:this.$.find(".Rk-Bins").height()-a})};var g=function(){return"xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx".replace(/[xy]/g,function(a){var b=16*Math.random()|0,c="x"===a?b:3&b|8;return c.toString(16)})};b.Utils={getUUID4:g,getUID:function(){function a(a){return 10>a?"0"+a:a}var b=new Date,c=0,d=b.getUTCFullYear()+"-"+a(b.getUTCMonth()+1)+"-"+a(b.getUTCDate())+"-"+g();return function(a){for(var b=(++c).toString(16),e="undefined"==typeof a?"":a+"-";b.length<4;)b="0"+b;return e+d+"-"+b}}(),getFullURL:function(a){if("undefined"==typeof a||null==a)return"";if(/https?:\/\//.test(a))return a;var b=new Image;b.src=a;var c=b.src;return b.src=null,c},inherit:function(a,b){var c=function(c){"function"==typeof b&&b.apply(this,Array.prototype.slice.call(arguments,0)),a.apply(this,Array.prototype.slice.call(arguments,0)),"function"!=typeof this._init||this._initialized||(this._init.apply(this,Array.prototype.slice.call(arguments,0)),this._initialized=!0)};return d.extend(c.prototype,a.prototype),c},regexpFromTextOrArray:function(){function a(a){function b(a){return function(b,c){a=a.replace(h[b],c)}}for(var e=a.toLowerCase().replace(g,""),i="",j=0;j<e.length;j++){j&&(i+=f+"*");var k=e[j];d.each(c,b(k)),i+=k}return i}function b(c){switch(typeof c){case"string":return a(c);case"object":var e="";return d.each(c,function(a){var c=b(a);c&&(e&&(e+="|"),e+=c)}),e}return""}var c=["[aáàâä]","[cç]","[eéèêë]","[iíìîï]","[oóòôö]","[uùûü]"],e=[String.fromCharCode(768),String.fromCharCode(769),String.fromCharCode(770),String.fromCharCode(771),String.fromCharCode(807),"{","}","(",")","[","]","【","】","、","・","‥","。","「","」","『","』","〜",":","!","?"," ",","," ",";","(",")",".","*","+","\\","?","|","{","}","[","]","^","#","/"],f="[\\"+e.join("\\")+"]",g=new RegExp(f,"gm"),h=d.map(c,function(a){return new RegExp(a)});return function(a){var c=b(a);if(c){var d=new RegExp(c,"im"),e=new RegExp("("+c+")","igm");return{isempty:!1,source:c,test:function(a){return d.test(a)},replace:function(a,b){return a.replace(e,b)}}}return{isempty:!0,source:"",test:function(){return!0},replace:function(a){return text}}}}(),_MIN_DRAG_DISTANCE:2,_NODE_BUTTON_WIDTH:40,_EDGE_BUTTON_INNER:2,_EDGE_BUTTON_OUTER:40,_CLICKMODE_ADDNODE:1,_CLICKMODE_STARTEDGE:2,_CLICKMODE_ENDEDGE:3,_NODE_SIZE_STEP:Math.LN2/4,_MIN_SCALE:.05,_MAX_SCALE:20,_MOUSEMOVE_RATE:80,_DOUBLETAP_DELAY:800,_DOUBLETAP_DISTANCE:400,_USER_PLACEHOLDER:function(a){return{color:a.options.default_user_color,title:a.translate("(unknown user)"),get:function(a){return this[a]||!1}}},_BOOKMARKLET_CODE:function(a){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;\">"+a.translate("Drag items from this website, drop them in Renkan").replace(/ /g,"_")+"</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);})();"},shortenText:function(a,b){return a.length>b?a.substr(0,b)+"…":a},drawEditBox:function(a,b,c,d,e){e.css({width:a.tooltip_width-2*a.tooltip_padding});var f=e.outerHeight()+2*a.tooltip_padding,g=b.x<paper.view.center.x?1:-1,h=b.x+g*(d+a.tooltip_arrow_length),i=b.x+g*(d+a.tooltip_arrow_length+a.tooltip_width),j=b.y-f/2;j+f>paper.view.size.height-a.tooltip_margin&&(j=Math.max(paper.view.size.height-a.tooltip_margin,b.y+a.tooltip_arrow_width/2)-f),j<a.tooltip_margin&&(j=Math.min(a.tooltip_margin,b.y-a.tooltip_arrow_width/2));var k=j+f;return c.segments[0].point=c.segments[7].point=b.add([g*d,0]),c.segments[1].point.x=c.segments[2].point.x=c.segments[5].point.x=c.segments[6].point.x=h,c.segments[3].point.x=c.segments[4].point.x=i,c.segments[2].point.y=c.segments[3].point.y=j,c.segments[4].point.y=c.segments[5].point.y=k,c.segments[1].point.y=b.y-a.tooltip_arrow_width/2,c.segments[6].point.y=b.y+a.tooltip_arrow_width/2,c.fillColor=new paper.Color(new paper.Gradient([a.tooltip_top_color,a.tooltip_bottom_color]),[0,j],[0,k]),e.css({left:a.tooltip_padding+Math.min(h,i),top:a.tooltip_padding+j}),c},increaseBrightness:function(a,b){a=a.replace(/^\s*#|\s*$/g,""),3===a.length&&(a=a.replace(/(.)/g,"$1$1"));var c=parseInt(a.substr(0,2),16),d=parseInt(a.substr(2,2),16),e=parseInt(a.substr(4,2),16);return"#"+(0|256+c+(256-c)*b/100).toString(16).substr(1)+(0|256+d+(256-d)*b/100).toString(16).substr(1)+(0|256+e+(256-e)*b/100).toString(16).substr(1)}}}(window),function(a){"use strict";var b=a.Backbone;a.Rkns.Router=b.Router.extend({routes:{"":"index"},index:function(a){var b={};null!==a&&a.split("&").forEach(function(a){var c=a.split("=");b[c[0]]=decodeURIComponent(c[1])}),this.trigger("router",b)}})}(window),function(a){"use strict";var b=a.Rkns.DataLoader={converters:{from1to2:function(a){var b,c;if("undefined"!=typeof a.nodes)for(b=0,c=a.nodes.length;c>b;b++){var d=a.nodes[b];d.color?d.style={color:d.color}:d.style={}}if("undefined"!=typeof a.edges)for(b=0,c=a.edges.length;c>b;b++){var e=a.edges[b];e.color?e.style={color:e.color}:e.style={}}return a.schema_version="2",a}}};b.Loader=function(a,c){this.project=a,this.dataConverters=_.defaults(c.converters||{},b.converters)},b.Loader.prototype.convert=function(a){var b=this.project.getSchemaVersion(a),c=this.project.getSchemaVersion();if(b!==c){var d="from"+b+"to"+c;"function"==typeof this.dataConverters[d]&&(a=this.dataConverters[d](a))}return a},b.Loader.prototype.load=function(a){this.project.set(this.convert(a),{validate:!0})}}(window),function(a){"use strict";var b=a.Backbone,c=a.Rkns.Models={};c.getUID=function(a){var b="xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx".replace(/[xy]/g,function(a){var b=16*Math.random()|0,c="x"===a?b:3&b|8;return c.toString(16)});return"undefined"!=typeof a?a.type+"-"+b:b};var d=b.RelationalModel.extend({idAttribute:"_id",constructor:function(a){"undefined"!=typeof a&&(a._id=a._id||a.id||c.getUID(this),a.title=a.title||"",a.description=a.description||"",a.uri=a.uri||"","function"==typeof this.prepare&&(a=this.prepare(a))),b.RelationalModel.prototype.constructor.call(this,a)},validate:function(){return this.type?void 0:"object has no type"},addReference:function(a,b,c,d,e){var f=c.get(d);"undefined"==typeof f&&"undefined"!=typeof e?a[b]=e:a[b]=f}}),e=c.User=d.extend({type:"user",prepare:function(a){return a.color=a.color||"#666666",a},toJSON:function(){return{_id:this.get("_id"),title:this.get("title"),uri:this.get("uri"),description:this.get("description"),color:this.get("color")}}}),f=c.Node=d.extend({type:"node",relations:[{type:b.HasOne,key:"created_by",relatedModel:e}],prepare:function(a){var b=a.project;return this.addReference(a,"created_by",b.get("users"),a.created_by,b.current_user),a.description=a.description||"",a},toJSON:function(){return{_id:this.get("_id"),title:this.get("title"),uri:this.get("uri"),description:this.get("description"),position:this.get("position"),image:this.get("image"),style:this.get("style"),created_by:this.get("created_by")?this.get("created_by").get("_id"):null,size:this.get("size"),clip_path:this.get("clip_path"),shape:this.get("shape"),type:this.get("type")}}}),g=c.Edge=d.extend({type:"edge",relations:[{type:b.HasOne,key:"created_by",relatedModel:e},{type:b.HasOne,key:"from",relatedModel:f},{type:b.HasOne,key:"to",relatedModel:f}],prepare:function(a){var b=a.project;return this.addReference(a,"created_by",b.get("users"),a.created_by,b.current_user),this.addReference(a,"from",b.get("nodes"),a.from),this.addReference(a,"to",b.get("nodes"),a.to),a},toJSON:function(){return{_id:this.get("_id"),title:this.get("title"),uri:this.get("uri"),description:this.get("description"),from:this.get("from")?this.get("from").get("_id"):null,to:this.get("to")?this.get("to").get("_id"):null,style:this.get("style"),created_by:this.get("created_by")?this.get("created_by").get("_id"):null}}}),h=c.View=d.extend({type:"view",relations:[{type:b.HasOne,key:"created_by",relatedModel:e}],prepare:function(a){var b=a.project;if(this.addReference(a,"created_by",b.get("users"),a.created_by,b.current_user),a.description=a.description||"","undefined"!=typeof a.offset){var c={};Array.isArray(a.offset)?(c.x=a.offset[0],c.y=a.offset.length>1?a.offset[1]:a.offset[0]):null!=a.offset.x&&(c.x=a.offset.x,c.y=a.offset.y),a.offset=c}return a},toJSON:function(){return{_id:this.get("_id"),zoom_level:this.get("zoom_level"),offset:this.get("offset"),title:this.get("title"),description:this.get("description"),created_by:this.get("created_by")?this.get("created_by").get("_id"):null,hidden_nodes:this.get("hidden_nodes")}}}),i=(c.Project=d.extend({schema_version:"2",type:"project",blacklist:["saveStatus","loadingStatus"],relations:[{type:b.HasMany,key:"users",relatedModel:e,reverseRelation:{key:"project",includeInJSON:"_id"}},{type:b.HasMany,key:"nodes",relatedModel:f,reverseRelation:{key:"project",includeInJSON:"_id"}},{type:b.HasMany,key:"edges",relatedModel:g,reverseRelation:{key:"project",includeInJSON:"_id"}},{type:b.HasMany,key:"views",relatedModel:h,reverseRelation:{key:"project",includeInJSON:"_id"}}],addUser:function(a,b){a.project=this;var c=e.findOrCreate(a);return this.get("users").push(c,b),c},addNode:function(a,b){a.project=this;var c=f.findOrCreate(a);return this.get("nodes").push(c,b),c},addEdge:function(a,b){a.project=this;var c=g.findOrCreate(a);return this.get("edges").push(c,b),c},addView:function(a,b){a.project=this;var c=h.findOrCreate(a);return this.get("views").push(c,b),c},removeNode:function(a){this.get("nodes").remove(a)},removeEdge:function(a){this.get("edges").remove(a)},validate:function(a){var b=this;_.each([].concat(a.users,a.nodes,a.edges,a.views),function(a){a&&(a.project=b)})},getSchemaVersion:function(a){var b=a;"undefined"==typeof b&&(b=this);var c=b.schema_version;return c?c:1},initialize:function(){var a=this;this.on("remove:nodes",function(b){a.get("edges").remove(a.get("edges").filter(function(a){return a.get("from")===b||a.get("to")===b}))})},toJSON:function(){var a=_.clone(this.attributes);for(var c in a)(a[c]instanceof b.Model||a[c]instanceof b.Collection||a[c]instanceof d)&&(a[c]=a[c].toJSON());return _.omit(a,this.blacklist)}}),c.RosterUser=b.Model.extend({type:"roster_user",idAttribute:"_id",constructor:function(a){"undefined"!=typeof a&&(a._id=a._id||a.id||c.getUID(this),a.title=a.title||"(untitled "+this.type+")",a.description=a.description||"",a.uri=a.uri||"",a.project=a.project||null,a.site_id=a.site_id||0,"function"==typeof this.prepare&&(a=this.prepare(a))),b.Model.prototype.constructor.call(this,a)},validate:function(){return this.type?void 0:"object has no type"},prepare:function(a){return a.color=a.color||"#666666",a},toJSON:function(){return{_id:this.get("_id"),title:this.get("title"),uri:this.get("uri"),description:this.get("description"),color:this.get("color"),project:null!=this.get("project")?this.get("project").get("id"):null,site_id:this.get("site_id")}}}));c.UsersList=b.Collection.extend({model:i})}(window),Rkns.defaults={language:navigator.language||navigator.userLanguage||"en",container:"renkan",search:[],bins:[],static_url:"",popup_editor:!0,editor_panel:"editor-panel",show_bins:!0,properties:[],show_editor:!0,read_only:!1,editor_mode:!0,manual_save:!1,show_top_bar:!0,default_user_color:"#303030",size_bug_fix:!1,force_resize:!1,allow_double_click:!0,zoom_on_scroll:!0,element_delete_delay:0,autoscale_padding:50,resize:!0,show_zoom:!0,save_view:!0,default_view:!1,default_index_view:-1,update_url:!0,show_search_field:!0,show_user_list:!0,user_name_editable:!0,user_color_editable:!0,show_user_color:!0,show_save_button:!0,show_export_button:!0,show_open_button:!1,show_addnode_button:!0,show_addedge_button:!0,show_bookmarklet:!0,show_fullscreen_button:!0,home_button_url:!1,home_button_title:"Home",show_minimap:!0,minimap_width:160,minimap_height:120,minimap_padding:20,minimap_background_color:"#ffffff",minimap_border_color:"#cccccc",minimap_highlight_color:"#ffff00",minimap_highlight_weight:5,buttons_background:"#202020",buttons_label_color:"#c000c0",buttons_label_font_size:9,ghost_opacity:.3,default_dash_array:[4,5],show_node_circles:!0,clip_node_images:!0,node_images_fill_mode:!1,node_size_base:25,node_stroke_width:2,node_stroke_max_width:12,selected_node_stroke_width:4,selected_node_stroke_max_width:24,node_stroke_witdh_scale:5,node_fill_color:"#ffffff",highlighted_node_fill_color:"#ffff00",node_label_distance:5,node_label_max_length:60,label_untitled_nodes:"(untitled)",hide_nodes:!0,change_shapes:!0,change_types:!0,node_editor_templates:{"default":"templates/nodeeditor_readonly.html",video:"templates/nodeeditor_video.html"},edge_stroke_width:2,edge_stroke_max_width:12,selected_edge_stroke_width:4,selected_edge_stroke_max_width:24,edge_stroke_witdh_scale:5,edge_label_distance:0,edge_label_max_length:20,edge_arrow_length:18,edge_arrow_width:12,edge_arrow_max_width:32,edge_gap_in_bundles:12,label_untitled_edges:"",tooltip_width:275,tooltip_padding:10,tooltip_margin:15,tooltip_arrow_length:20,tooltip_arrow_width:40,tooltip_top_color:"#f0f0f0",tooltip_bottom_color:"#d0d0d0",tooltip_border_color:"#808080",tooltip_border_width:1,tooltip_opacity:.8,richtext_editor_config:{toolbarGroups:[{name:"basicstyles",groups:["basicstyles","cleanup"]},{name:"clipboard",groups:["clipboard","undo"]},"/",{name:"styles"}],removePlugins:"colorbutton,find,flash,font,forms,iframe,image,newpage,smiley,specialchar,stylescombo,templates"},show_node_editor_uri:!0,show_node_editor_description:!0,show_node_editor_description_richtext:!0,show_node_editor_size:!0,show_node_editor_style:!0,show_node_editor_style_color:!0,show_node_editor_style_dash:!0,show_node_editor_style_thickness:!0,show_node_editor_image:!0,show_node_editor_creator:!0,allow_image_upload:!0,uploaded_image_max_kb:500,show_node_tooltip_uri:!0,show_node_tooltip_description:!0,show_node_tooltip_color:!0,show_node_tooltip_image:!0,show_node_tooltip_creator:!0,show_edge_editor_uri:!0,show_edge_editor_style:!0,show_edge_editor_style_color:!0,show_edge_editor_style_dash:!0,show_edge_editor_style_thickness:!0,show_edge_editor_style_arrow:!0,show_edge_editor_direction:!0,show_edge_editor_nodes:!0,show_edge_editor_creator:!0,show_edge_tooltip_uri:!0,show_edge_tooltip_color:!0,show_edge_tooltip_nodes:!0,show_edge_tooltip_creator:!0},Rkns.i18n={fr:{"Edit Node":"Édition d’un nœud","Edit Edge":"Édition d’un lien","Title:":"Titre :","URI:":"URI :","Description:":"Description :","From:":"De :","To:":"Vers :",Image:"Image","Image URL:":"URL d'Image","Choose Image File:":"Choisir un fichier image","Full Screen":"Mode plein écran","Add Node":"Ajouter un nœud","Add Edge":"Ajouter un lien","Save Project":"Enregistrer le projet","Open Project":"Ouvrir un projet","Auto-save enabled":"Enregistrement automatique activé","Connection lost":"Connexion perdue","Created by:":"Créé par :","Zoom In":"Agrandir l’échelle","Zoom Out":"Rapetisser l’échelle",Edit:"Éditer",Remove:"Supprimer","Cancel deletion":"Annuler la suppression","Link to another node":"Créer un lien",Enlarge:"Agrandir",Shrink:"Rétrécir","Click on the background canvas to add a node":"Cliquer sur le fond du graphe pour rajouter un nœud","Click on a first node to start the edge":"Cliquer sur un premier nœud pour commencer le lien","Click on a second node to complete the edge":"Cliquer sur un second nœud pour terminer le lien",Wikipedia:"Wikipédia","Wikipedia in ":"Wikipédia en ",French:"Français",English:"Anglais",Japanese:"Japonais","Untitled project":"Projet sans titre","Lignes de Temps":"Lignes de Temps","Loading, please wait":"Chargement en cours, merci de patienter","Edge color:":"Couleur :","Dash:":"Point. :","Thickness:":"Epaisseur :","Arrow:":"Flèche :","Node color:":"Couleur :","Choose color":"Choisir une couleur","Change edge direction":"Changer le sens du lien","Do you really wish to remove node ":"Voulez-vous réellement supprimer le nœud ","Do you really wish to remove edge ":"Voulez-vous réellement supprimer le lien ","This file is not an image":"Ce fichier n'est pas une image","Image size must be under ":"L'image doit peser moins de ","Size:":"Taille :",KB:"ko","Choose from vocabulary:":"Choisir dans un vocabulaire :","SKOS Documentation properties":"SKOS: Propriétés documentaires","has note":"a pour note","has example":"a pour exemple","has definition":"a pour définition","SKOS Semantic relations":"SKOS: Relations sémantiques","has broader":"a pour concept plus large","has narrower":"a pour concept plus étroit","has related":"a pour concept apparenté","Dublin Core Metadata":"Métadonnées Dublin Core","has contributor":"a pour contributeur",covers:"couvre","created by":"créé par","has date":"a pour date","published by":"édité par","has source":"a pour source","has subject":"a pour sujet","Dragged resource":"Ressource glisée-déposée","Search the Web":"Rechercher en ligne","Search in Bins":"Rechercher dans les chutiers","Close bin":"Fermer le chutier","Refresh bin":"Rafraîchir le chutier","(untitled)":"(sans titre)","Select contents:":"Sélectionner des contenus :","Drag items from this website, drop them in Renkan":"Glissez des éléments de ce site web vers 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.":"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","Shapes available":"Formes disponibles",Circle:"Cercle",Square:"Carré",Diamond:"Losange",Hexagone:"Hexagone",Ellipse:"Ellipse",Star:"Étoile",Cloud:"Nuage",Triangle:"Triangle","Zoom Fit":"Ajuster le Zoom","Download Project":"Télécharger le projet","Save view":"Sauver la vue","View saved view":"Restaurer la Vue","Renkan 'Drag-to-Add' bookmarklet":"Renkan 'Deplacer-Pour-Ajouter' Signet","(unknown user)":"(non authentifié)","<unknown user>":"<non authentifié>","Search in graph":"Rechercher dans carte","Search in ":"Chercher dans "}},Rkns.jsonIO=function(a,b){var c=a.project;"undefined"==typeof b.http_method&&(b.http_method="PUT");var d=function(){a.renderer.redrawActive=!1,c.set({loadingStatus:!0}),Rkns.$.getJSON(b.url,function(b){a.dataloader.load(b),c.set({loadingStatus:!1}),c.set({saveStatus:0}),a.renderer.redrawActive=!0})},e=function(){c.set({saveStatus:2});var d=c.toJSON();a.read_only||Rkns.$.ajax({type:b.http_method,url:b.url,contentType:"application/json",data:JSON.stringify(d),success:function(a,b,d){c.set({saveStatus:0})}})},f=Rkns._.throttle(function(){setTimeout(e,100)},1e3);c.on("add:nodes add:edges add:users add:views",function(a){a.on("change remove",function(a){f()}),f()}),c.on("change",function(){1===c.changedAttributes.length&&c.hasChanged("saveStatus")||f()}),d()},Rkns.jsonIOSaveOnClick=function(a,b){var c=a.project,d=!1,e=function(){return"Project not saved"};"undefined"==typeof b.http_method&&(b.http_method="POST");var f=function(){var d={},e=/id=([^&#?=]+)/,f=document.location.hash.match(e);f&&(d.id=f[1]),Rkns.$.ajax({url:b.url,data:d,beforeSend:function(){a.renderer.redrawActive=!1,c.set({loadingStatus:!0})},success:function(b){a.dataloader.load(b),c.set({loadingStatus:!1}),c.set({saveStatus:0}),a.renderer.redrawActive=!0}})},g=function(){c.set("saved_at",new Date);var a=c.toJSON();Rkns.$.ajax({type:b.http_method,url:b.url,contentType:"application/json",data:JSON.stringify(a),beforeSend:function(){c.set({saveStatus:2})},success:function(a,b,f){$(window).off("beforeunload",e),d=!1,c.set({saveStatus:0})}})},h=function(){c.set({saveStatus:1});var a=c.get("title");a&&c.get("nodes").length?$(".Rk-Save-Button").removeClass("disabled"):$(".Rk-Save-Button").addClass("disabled"),a&&$(".Rk-PadTitle").css("border-color","#333333"),d||(d=!0,$(window).on("beforeunload",e))};f(),c.on("add:nodes add:edges add:users change",function(a){a.on("change remove",function(a){1===a.changedAttributes.length&&a.hasChanged("saveStatus")||h()}),1===c.changedAttributes.length&&c.hasChanged("saveStatus")||h()}),a.renderer.save=function(){$(".Rk-Save-Button").hasClass("disabled")?c.get("title")||$(".Rk-PadTitle").css("border-color","#ff0000"):g()}},function(a){"use strict";var b=a._,c=a.Ldt={},d=(c.Bin=function(a,b){if(b.ldt_type){var d=c[b.ldt_type+"Bin"];if(d)return new d(a,b)}console.error("No such LDT Bin Type")},c.ProjectBin=a.Utils.inherit(a._BaseBin));d.prototype.tagTemplate=renkanJST["templates/ldtjson-bin/tagtemplate.html"],d.prototype.annotationTemplate=renkanJST["templates/ldtjson-bin/annotationtemplate.html"],d.prototype._init=function(a,b){this.renkan=a,this.proj_id=b.project_id,this.ldt_platform=b.ldt_platform||"http://ldt.iri.centrepompidou.fr/",this.title_$.html(b.title),this.title_icon_$.addClass("Rk-Ldt-Title-Icon"),this.refresh()},d.prototype.render=function(c){function d(a){var c=b(a).escape();return f.isempty?c:f.replace(c,"<span class='searchmatch'>$1</span>")}function e(a){function b(a){for(var b=a.toString();b.length<2;)b="0"+b;return b}var c=Math.abs(Math.floor(a/1e3)),d=Math.floor(c/3600),e=Math.floor(c/60)%60,f=c%60,g="";return d&&(g+=b(d)+":"),g+=b(e)+":"+b(f)}var f=c||a.Utils.regexpFromTextOrArray(),g="<li><h3>Tags</h3></li>",h=this.data.meta["dc:title"],i=this,j=0;i.title_$.text('LDT Project: "'+h+'"'),b.map(i.data.tags,function(a){var b=a.meta["dc:title"];(f.isempty||f.test(b))&&(j++,g+=i.tagTemplate({ldt_platform:i.ldt_platform,title:b,htitle:d(b),encodedtitle:encodeURIComponent(b),static_url:i.renkan.options.static_url}))}),g+="<li><h3>Annotations</h3></li>",b.map(i.data.annotations,function(a){var b=a.content.description,c=a.content.title.replace(b,"");if(f.isempty||f.test(c)||f.test(b)){j++;var h=a.end-a.begin,k=a.content&&a.content.img&&a.content.img.src?a.content.img.src:h?i.renkan.options.static_url+"img/ldt-segment.png":i.renkan.options.static_url+"img/ldt-point.png";g+=i.annotationTemplate({ldt_platform:i.ldt_platform,title:c,htitle:d(c),description:b,hdescription:d(b),start:e(a.begin),end:e(a.end),duration:e(h),mediaid:a.media,annotationid:a.id,image:k,static_url:i.renkan.options.static_url})}}),this.main_$.html(g),!f.isempty&&j?this.count_$.text(j).show():this.count_$.hide(),f.isempty||j?this.$.show():this.$.hide(),this.renkan.resizeBins()},d.prototype.refresh=function(){var b=this;a.$.ajax({url:this.ldt_platform+"ldtplatform/ldt/cljson/id/"+this.proj_id,dataType:"jsonp",success:function(a){b.data=a,b.render()}})};var e=c.Search=function(a,b){this.renkan=a,this.lang=b.lang||"en"};e.prototype.getBgClass=function(){return"Rk-Ldt-Icon"},e.prototype.getSearchTitle=function(){return this.renkan.translate("Lignes de Temps")},e.prototype.search=function(a){this.renkan.tabs.push(new f(this.renkan,{search:a}))};var f=c.ResultsBin=a.Utils.inherit(a._BaseBin);f.prototype.segmentTemplate=renkanJST["templates/ldtjson-bin/segmenttemplate.html"],f.prototype._init=function(a,b){this.renkan=a,this.ldt_platform=b.ldt_platform||"http://ldt.iri.centrepompidou.fr/",this.max_results=b.max_results||50,this.search=b.search,this.title_$.html('Lignes de Temps: "'+b.search+'"'),this.title_icon_$.addClass("Rk-Ldt-Title-Icon"),this.refresh()},f.prototype.render=function(c){function d(a){return g.replace(b(a).escape(),"<span class='searchmatch'>$1</span>")}function e(a){function b(a){for(var b=a.toString();b.length<2;)b="0"+b;return b}var c=Math.abs(Math.floor(a/1e3)),d=Math.floor(c/3600),e=Math.floor(c/60)%60,f=c%60,g="";return d&&(g+=b(d)+":"),g+=b(e)+":"+b(f)}if(this.data){var f=c||a.Utils.regexpFromTextOrArray(),g=f.isempty?a.Utils.regexpFromTextOrArray(this.search):f,h="",i=this,j=0;b.each(this.data.objects,function(a){var b=a["abstract"],c=a.title;if(f.isempty||f.test(c)||f.test(b)){j++;var g=a.duration,k=a.start_ts,l=+a.duration+k,m=g?i.renkan.options.static_url+"img/ldt-segment.png":i.renkan.options.static_url+"img/ldt-point.png";h+=i.segmentTemplate({ldt_platform:i.ldt_platform,title:c,htitle:d(c),description:b,hdescription:d(b),start:e(k),end:e(l),duration:e(g),mediaid:a.iri_id,annotationid:a.element_id,image:m})}}),this.main_$.html(h),!f.isempty&&j?this.count_$.text(j).show():this.count_$.hide(),f.isempty||j?this.$.show():this.$.hide(),this.renkan.resizeBins()}},f.prototype.refresh=function(){var b=this;a.$.ajax({url:this.ldt_platform+"ldtplatform/api/ldt/1.0/segments/search/",data:{format:"jsonp",q:this.search,limit:this.max_results},dataType:"jsonp",success:function(a){b.data=a,b.render()}})}}(window.Rkns),Rkns.ResourceList={},Rkns.ResourceList.Bin=Rkns.Utils.inherit(Rkns._BaseBin),Rkns.ResourceList.Bin.prototype.resultTemplate=renkanJST["templates/list-bin.html"],Rkns.ResourceList.Bin.prototype._init=function(a,b){this.renkan=a,this.title_$.html(b.title),b.list&&(this.data=b.list),this.refresh()},Rkns.ResourceList.Bin.prototype.render=function(a){function b(a){var b=_(a).escape();return c.isempty?b:c.replace(b,"<span class='searchmatch'>$1</span>")}var c=a||Rkns.Utils.regexpFromTextOrArray(),d="",e=this,f=0;Rkns._.each(this.data,function(a){var g;if("string"==typeof a)if(/^(https?:\/\/|www)/.test(a))g={url:a};else{g={title:a.replace(/[:,]?\s?(https?:\/\/|www)[\d\w\/.&?=#%-_]+\s?/,"").trim()};var h=a.match(/(https?:\/\/|www)[\d\w\/.&?=#%-_]+/);h&&(g.url=h[0]),g.title.length>80&&(g.description=g.title,g.title=g.title.replace(/^(.{30,60})\s.+$/,"$1…"))}else g=a;var i=g.title||(g.url||"").replace(/^https?:\/\/(www\.)?/,"").replace(/^(.{40}).+$/,"$1…"),j=g.url||"",k=g.description||"",l=g.image||"";j&&!/^https?:\/\//.test(j)&&(j="http://"+j),(c.isempty||c.test(i)||c.test(k))&&(f++,d+=e.resultTemplate({url:j,title:i,htitle:b(i),image:l,description:k,hdescription:b(k),static_url:e.renkan.options.static_url}))}),e.main_$.html(d),!c.isempty&&f?this.count_$.text(f).show():this.count_$.hide(),c.isempty||f?this.$.show():this.$.hide(),this.renkan.resizeBins()},Rkns.ResourceList.Bin.prototype.refresh=function(){this.data&&this.render()},Rkns.Wikipedia={},Rkns.Wikipedia.Search=function(a,b){this.renkan=a,this.lang=b.lang||"en"},Rkns.Wikipedia.Search.prototype.getBgClass=function(){return"Rk-Wikipedia-Search-Icon Rk-Wikipedia-Lang-"+this.lang},Rkns.Wikipedia.Search.prototype.getSearchTitle=function(){var a={fr:"French",en:"English",ja:"Japanese"};return a[this.lang]?this.renkan.translate("Wikipedia in ")+this.renkan.translate(a[this.lang]):this.renkan.translate("Wikipedia")+" ["+this.lang+"]"},Rkns.Wikipedia.Search.prototype.search=function(a){this.renkan.tabs.push(new Rkns.Wikipedia.Bin(this.renkan,{lang:this.lang,search:a}))},Rkns.Wikipedia.Bin=Rkns.Utils.inherit(Rkns._BaseBin),Rkns.Wikipedia.Bin.prototype.resultTemplate=renkanJST["templates/wikipedia-bin/resulttemplate.html"],Rkns.Wikipedia.Bin.prototype._init=function(a,b){this.renkan=a,this.search=b.search,this.lang=b.lang||"en",this.title_icon_$.addClass("Rk-Wikipedia-Title-Icon Rk-Wikipedia-Lang-"+this.lang),this.title_$.html(this.search).addClass("Rk-Wikipedia-Title"),this.refresh()},Rkns.Wikipedia.Bin.prototype.render=function(a){function b(a){return d.replace(_(a).escape(),"<span class='searchmatch'>$1</span>")}var c=a||Rkns.Utils.regexpFromTextOrArray(),d=c.isempty?Rkns.Utils.regexpFromTextOrArray(this.search):c,e="",f=this,g=0;Rkns._.each(this.data.query.search,function(a){var d=a.title,h="http://"+f.lang+".wikipedia.org/wiki/"+encodeURI(d.replace(/ /g,"_")),i=Rkns.$("<div>").html(a.snippet).text();(c.isempty||c.test(d)||c.test(i))&&(g++,e+=f.resultTemplate({url:h,title:d,htitle:b(d),description:i,hdescription:b(i),static_url:f.renkan.options.static_url}))}),f.main_$.html(e),!c.isempty&&g?this.count_$.text(g).show():this.count_$.hide(),c.isempty||g?this.$.show():this.$.hide(),this.renkan.resizeBins()},Rkns.Wikipedia.Bin.prototype.refresh=function(){var a=this;Rkns.$.ajax({url:"http://"+a.lang+".wikipedia.org/w/api.php?action=query&list=search&srsearch="+encodeURIComponent(this.search)+"&format=json",dataType:"jsonp",success:function(b){a.data=b,a.render()}})},define("renderer/baserepresentation",["jquery","underscore"],function(a,b){"use strict";var c=function(a,c){if("undefined"!=typeof a&&(this.renderer=a,this.renkan=a.renkan,this.project=a.renkan.project,this.options=a.renkan.options,this.model=c,this.model)){var d=this;this._changeBinding=function(){d.redraw({change:!0})},this._removeBinding=function(){a.removeRepresentation(d),b.defer(function(){a.redraw()})},this._selectBinding=function(){d.select()},this._unselectBinding=function(){d.unselect()},this.model.on("change",this._changeBinding),this.model.on("remove",this._removeBinding),this.model.on("select",this._selectBinding),this.model.on("unselect",this._unselectBinding)}};return b(c.prototype).extend({_super:function(a){return c.prototype[a].apply(this,Array.prototype.slice.call(arguments,1));
+},redraw:function(){},moveTo:function(){},show:function(){return"BaseRepresentation.show"},hide:function(){},select:function(){this.model&&this.model.trigger("selected")},unselect:function(){this.model&&this.model.trigger("unselected")},highlight:function(){},unhighlight:function(){},mousedown:function(){},mouseup:function(){this.model&&this.model.trigger("clicked")},destroy:function(){this.model&&(this.model.off("change",this._changeBinding),this.model.off("remove",this._removeBinding),this.model.off("select",this._selectBinding),this.model.off("unselect",this._unselectBinding))}}).value(),c}),define("requtils",[],function(a,b){"use strict";return{getUtils:function(){return window.Rkns.Utils},getRenderer:function(){return window.Rkns.Renderer}}}),define("renderer/basebutton",["jquery","underscore","requtils","renderer/baserepresentation"],function(a,b,c,d){"use strict";var e=c.getUtils(),f=e.inherit(d);return b(f.prototype).extend({moveTo:function(a){this.sector.moveTo(a)},show:function(){this.sector.show()},hide:function(){this.sector&&this.sector.hide()},select:function(){this.sector.select()},unselect:function(a){this.sector.unselect(),(!a||a!==this.source_representation&&a.source_representation!==this.source_representation)&&this.source_representation.unselect()},destroy:function(){this.sector.destroy()}}).value(),f}),define("renderer/shapebuilder",[],function(){"use strict";var a="M0,0c-0.1218516546,-0.0336420601 -0.2451649928,0.0048580836 -0.3302944641,0.0884969975c-0.0444763883,-0.0550844815 -0.1047003238,-0.0975985034 -0.1769360893,-0.1175406746c-0.1859066673,-0.0513257002 -0.3774236254,0.0626045858 -0.4272374613,0.2541588105c-0.0036603877,0.0140753132 -0.0046241235,0.028229722 -0.0065872453,0.042307536c-0.1674179627,-0.0179317735 -0.3276106855,0.0900599386 -0.3725537463,0.2628868425c-0.0445325077,0.1712456429 0.0395025693,0.3463497959 0.1905420475,0.4183458793c-0.0082101538,0.0183442886 -0.0158652506,0.0372432828 -0.0211098452,0.0574080693c-0.0498130336,0.1915540431 0.0608692569,0.3884647499 0.2467762814,0.4397904033c0.0910577256,0.0251434257 0.1830791813,0.0103792696 0.2594677475,-0.0334472349c0.042100113,0.0928009202 0.1205930075,0.1674914182 0.2240666796,0.1960572479c0.1476344161,0.0407610407 0.297446165,-0.0238077445 0.3783262342,-0.1475652419c0.0327623278,0.0238981846 0.0691792333,0.0436665447 0.1102008706,0.0549940004c0.1859065794,0.0513256592 0.3770116432,-0.0627203154 0.4268255671,-0.2542745401c0.0250490557,-0.0963230532 0.0095494076,-0.1938010889 -0.0356681889,-0.2736906101c0.0447507424,-0.0439678867 0.0797796014,-0.0996624318 0.0969425462,-0.1656617192c0.0498137481,-0.1915564561 -0.0608688118,-0.3884669813 -0.2467755669,-0.4397928163c-0.0195699622,-0.0054005426 -0.0391731675,-0.0084429542 -0.0586916488,-0.0102888295c0.0115683912,-0.1682147574 -0.0933564223,-0.3269222408 -0.2572937178,-0.3721841203z",b={circle:{getShape:function(){return new paper.Path.Circle([0,0],1)},getImageShape:function(a,b){return new paper.Path.Circle(a,b)}},rectangle:{getShape:function(){return new paper.Path.Rectangle([-2,-2],[2,2])},getImageShape:function(a,b){return new paper.Path.Rectangle([-b,-b],[2*b,2*b])}},ellipse:{getShape:function(){return new paper.Path.Ellipse(new paper.Rectangle([-2,-1],[2,1]))},getImageShape:function(a,b){return new paper.Path.Ellipse(new paper.Rectangle([-b,-b/2],[2*b,b]))}},polygon:{getShape:function(){return new paper.Path.RegularPolygon([0,0],6,1)},getImageShape:function(a,b){return new paper.Path.RegularPolygon(a,6,b)}},diamond:{getShape:function(){var a=new paper.Path.Rectangle([-Math.SQRT2,-Math.SQRT2],[Math.SQRT2,Math.SQRT2]);return a.rotate(45),a},getImageShape:function(a,b){var c=new paper.Path.Rectangle([-b*Math.SQRT2/2,-b*Math.SQRT2/2],[b*Math.SQRT2,b*Math.SQRT2]);return c.rotate(45),c}},star:{getShape:function(){return new paper.Path.Star([0,0],8,1,.7)},getImageShape:function(a,b){return new paper.Path.Star(a,8,1*b,.7*b)}},cloud:{getShape:function(){var b=new paper.Path(a);return b},getImageShape:function(b,c){var d=new paper.Path(a);return d.scale(c),d.translate(b),d}},triangle:{getShape:function(){return new paper.Path.RegularPolygon([0,0],3,1)},getImageShape:function(a,b){var c=new paper.Path.RegularPolygon([0,0],3,1);return c.scale(b),c.translate(a),c}},svg:function(a){return{getShape:function(){return new paper.Path(a)},getImageShape:function(a,b){return new paper.Path}}}},c=function(a){return(null===a||"undefined"==typeof a)&&(a="circle"),"svg:"===a.substr(0,4)?b.svg(a.substr(4)):(a in b||(a="circle"),b[a])};return c.builders=b,c}),define("renderer/noderepr",["jquery","underscore","requtils","renderer/baserepresentation","renderer/shapebuilder"],function(a,b,c,d,e){"use strict";var f=c.getUtils(),g=f.inherit(d);return b(g.prototype).extend({_init:function(){if(this.renderer.node_layer.activate(),this.type="Node",this.buildShape(),this.hidden=!1,this.ghost=!1,this.options.show_node_circles?(this.circle.strokeWidth=this.options.node_stroke_width,this.h_ratio=1):this.h_ratio=0,this.title=a('<div class="Rk-Label">').appendTo(this.renderer.labels_$),this.options.editor_mode){var b=c.getRenderer();this.normal_buttons=[new b.NodeEditButton(this.renderer,null),new b.NodeRemoveButton(this.renderer,null),new b.NodeLinkButton(this.renderer,null),new b.NodeEnlargeButton(this.renderer,null),new b.NodeShrinkButton(this.renderer,null)],this.options.hide_nodes&&this.normal_buttons.push(new b.NodeHideButton(this.renderer,null),new b.NodeShowButton(this.renderer,null)),this.pending_delete_buttons=[new b.NodeRevertButton(this.renderer,null)],this.all_buttons=this.normal_buttons.concat(this.pending_delete_buttons);for(var d=0;d<this.all_buttons.length;d++)this.all_buttons[d].source_representation=this;this.active_buttons=[]}else this.active_buttons=this.all_buttons=[];this.last_circle_radius=1,this.renderer.minimap&&(this.renderer.minimap.node_layer.activate(),this.minimap_circle=new paper.Path.Circle([0,0],1),this.minimap_circle.__representation=this.renderer.minimap.miniframe.__representation,this.renderer.minimap.node_group.addChild(this.minimap_circle))},_getStrokeWidth:function(){var a=this.model.has("style")&&this.model.get("style").thickness||1;return this.options.node_stroke_width+(a-1)*(this.options.node_stroke_max_width-this.options.node_stroke_width)/(this.options.node_stroke_witdh_scale-1)},_getSelectedStrokeWidth:function(){var a=this.model.has("style")&&this.model.get("style").thickness||1;return this.options.selected_node_stroke_width+(a-1)*(this.options.selected_node_stroke_max_width-this.options.selected_node_stroke_width)/(this.options.node_stroke_witdh_scale-1)},buildShape:function(){"shape"in this.model.changed&&delete this.img,this.circle&&(this.circle.remove(),delete this.circle),this.shapeBuilder=new e(this.model.get("shape")),this.circle=this.shapeBuilder.getShape(),this.circle.__representation=this,this.circle.sendToBack(),this.last_circle_radius=1},redraw:function(a){"shape"in this.model.changed&&"change"in a&&a.change&&this.buildShape();var c=new paper.Point(this.model.get("position")),d=this.options.node_size_base*Math.exp((this.model.get("size")||0)*f._NODE_SIZE_STEP);this.is_dragging&&this.paper_coords||(this.paper_coords=this.renderer.toPaperCoords(c)),this.circle_radius=d*this.renderer.view.scale,this.last_circle_radius!==this.circle_radius&&(this.all_buttons.forEach(function(a){a.setSectorSize()}),this.circle.scale(this.circle_radius/this.last_circle_radius),this.node_image&&this.node_image.scale(this.circle_radius/this.last_circle_radius)),this.circle.position=this.paper_coords,this.node_image&&(this.node_image.position=this.paper_coords.subtract(this.image_delta.multiply(this.circle_radius))),this.last_circle_radius=this.circle_radius;var e=this.active_buttons,g=1;this.model.get("delete_scheduled")?(g=.5,this.active_buttons=this.pending_delete_buttons,this.circle.dashArray=[2,2]):(g=1,this.active_buttons=this.normal_buttons,this.circle.dashArray=null),this.selected&&this.renderer.isEditable()&&!this.ghost&&(e!==this.active_buttons&&e.forEach(function(a){a.hide()}),this.active_buttons.forEach(function(a){a.show()})),this.node_image&&(this.node_image.opacity=this.highlighted?.5*g:g-.01),this.circle.fillColor=this.highlighted?this.options.highlighted_node_fill_color:this.options.node_fill_color,this.circle.opacity=this.options.show_node_circles?g:.01;var h=this.model.get("title")||this.renkan.translate(this.options.label_untitled_nodes)||"";h=f.shortenText(h,this.options.node_label_max_length),"object"==typeof this.highlighted?this.title.html(this.highlighted.replace(b(h).escape(),'<span class="Rk-Highlighted">$1</span>')):this.title.text(h);var i=this._getStrokeWidth();this.title.css({left:this.paper_coords.x,top:this.paper_coords.y+this.circle_radius*this.h_ratio+this.options.node_label_distance+.5*i,opacity:g});var j=this.model.has("style")&&this.model.get("style").color||(this.model.get("created_by")||f._USER_PLACEHOLDER(this.renkan)).get("color"),k=this.model.has("style")&&this.model.get("style").dash?this.options.default_dash_array:null;this.circle.strokeWidth=i,this.circle.strokeColor=j,this.circle.dashArray=k;var l=this.paper_coords;this.all_buttons.forEach(function(a){a.moveTo(l)});var m=this.img;if(this.img=this.model.get("image"),this.img&&this.img!==m&&(this.showImage(),this.circle&&this.circle.sendToBack()),this.node_image&&!this.img&&(this.node_image.remove(),delete this.node_image),this.renderer.minimap){this.minimap_circle.fillColor=j;var n=this.renderer.toMinimapCoords(c),o=this.renderer.minimap.scale*d,p=new paper.Size([o,o]);this.minimap_circle.fitBounds(n.subtract(p),p.multiply(2))}if(!("undefined"!=typeof a&&"dontRedrawEdges"in a&&a.dontRedrawEdges)){var q=this;b.each(this.project.get("edges").filter(function(a){return a.get("to")===q.model||a.get("from")===q.model}),function(a,b,c){var d=q.renderer.getRepresentationByModel(a);d&&"undefined"!=typeof d.from_representation&&"undefined"!=typeof d.from_representation.paper_coords&&"undefined"!=typeof d.to_representation&&"undefined"!=typeof d.to_representation.paper_coords&&d.redraw()})}this.ghost?this.show(!0):this.hidden&&this.hide()},showImage:function(){var b=null;if("undefined"==typeof this.renderer.image_cache[this.img]?(b=new Image,this.renderer.image_cache[this.img]=b,b.src=this.img):b=this.renderer.image_cache[this.img],b.width){this.node_image&&this.node_image.remove(),this.renderer.node_layer.activate();var c=b.width,d=b.height,e=this.model.get("clip_path"),f="undefined"!=typeof e&&e,g=null,h=null,i=null;if(f){g=new paper.Path;var j=e.match(/[a-z][^a-z]+/gi)||[],k=[0,0],l=1/0,m=1/0,n=-(1/0),o=-(1/0),p=function(a,b){var e=a.slice(1).map(function(a,e){var f=parseFloat(a),g=e%2;return f=g?(f-.5)*d:(f-.5)*c,b&&(f+=k[g]),g?(m=Math.min(m,f),o=Math.max(o,f)):(l=Math.min(l,f),n=Math.max(n,f)),f});return k=e.slice(-2),e};j.forEach(function(a){var b=a.match(/([a-z]|[0-9.-]+)/gi)||[""];switch(b[0]){case"M":g.moveTo(p(b));break;case"m":g.moveTo(p(b,!0));break;case"L":g.lineTo(p(b));break;case"l":g.lineTo(p(b,!0));break;case"C":g.cubicCurveTo(p(b));break;case"c":g.cubicCurveTo(p(b,!0));break;case"Q":g.quadraticCurveTo(p(b));break;case"q":g.quadraticCurveTo(p(b,!0))}}),h=Math[this.options.node_images_fill_mode?"min":"max"](n-l,o-m)/2,i=new paper.Point((n+l)/2,(o+m)/2),this.options.show_node_circles||(this.h_ratio=(o-m)/(2*h))}else h=Math[this.options.node_images_fill_mode?"min":"max"](c,d)/2,i=new paper.Point(0,0),this.options.show_node_circles||(this.h_ratio=d/(2*h));var q=new paper.Raster(b);if(q.locked=!0,f&&(q=new paper.Group(g,q),q.opacity=.99,q.clipped=!0,g.__representation=this),this.options.clip_node_images){var r=this.shapeBuilder.getImageShape(i,h);q=new paper.Group(r,q),q.opacity=.99,q.clipped=!0,r.__representation=this}this.image_delta=i.divide(h),this.node_image=q,this.node_image.__representation=s,this.node_image.scale(this.circle_radius/h),this.node_image.position=this.paper_coords.subtract(this.image_delta.multiply(this.circle_radius)),this.node_image.insertAbove(this.circle)}else{var s=this;a(b).on("load",function(){s.showImage()})}},paperShift:function(a){this.options.editor_mode?this.renkan.read_only||(this.is_dragging=!0,this.paper_coords=this.paper_coords.add(a),this.redraw()):this.renderer.view.paperShift(a)},openEditor:function(){this.renderer.removeRepresentationsOfType("editor");var a=this.renderer.addRepresentation("NodeEditor",null);a.source_representation=this,a.draw()},select:function(){this.selected=!0,this.circle.strokeWidth=this._getSelectedStrokeWidth(),this.renderer.isEditable()&&!this.hidden&&this.active_buttons.forEach(function(a){a.show()});var b=this.model.get("uri");b&&a(".Rk-Bin-Item").each(function(){var c=a(this);c.attr("data-uri")===b&&c.addClass("selected")}),this.options.editor_mode||this.openEditor(),this.renderer.minimap&&(this.minimap_circle.strokeWidth=this.options.minimap_highlight_weight,this.minimap_circle.strokeColor=this.options.minimap_highlight_color),this.hidden?this.show(!0):this.showNeighbors(!0),this._super("select")},hideButtons:function(){this.all_buttons.forEach(function(a){a.hide()}),delete this.buttonTimeout},unselect:function(b){if(!b||b.source_representation!==this){this.selected=!1;var c=this;this.buttons_timeout=setTimeout(function(){c.hideButtons()},200),this.circle.strokeWidth=this._getStrokeWidth(),a(".Rk-Bin-Item").removeClass("selected"),this.renderer.minimap&&(this.minimap_circle.strokeColor=void 0),this.hidden?this.hide():this.hideNeighbors(),this._super("unselect")}},hide:function(){var a=this;this.ghost=!1,this.hidden=!0,"undefined"!=typeof this.node_image&&(this.node_image.opacity=0),this.hideButtons(),this.circle.opacity=0,this.title.css("opacity",0),this.minimap_circle.opacity=0,b.each(this.project.get("edges").filter(function(b){return b.get("to")===a.model||b.get("from")===a.model}),function(b,c,d){var e=a.renderer.getRepresentationByModel(b);e&&"undefined"!=typeof e.from_representation&&"undefined"!=typeof e.from_representation.paper_coords&&"undefined"!=typeof e.to_representation&&"undefined"!=typeof e.to_representation.paper_coords&&e.hide()}),this.hideNeighbors()},show:function(a){var c=this;this.ghost=a,this.ghost?("undefined"!=typeof this.node_image&&(this.node_image.opacity=this.options.ghost_opacity),this.circle.opacity=this.options.ghost_opacity,this.title.css("opacity",this.options.ghost_opacity),this.minimap_circle.opacity=this.options.ghost_opacity):(this.minimap_circle.opacity=1,this.hidden=!1,this.redraw()),b.each(this.project.get("edges").filter(function(a){return a.get("to")===c.model||a.get("from")===c.model}),function(a,b,d){var e=c.renderer.getRepresentationByModel(a);e&&"undefined"!=typeof e.from_representation&&"undefined"!=typeof e.from_representation.paper_coords&&"undefined"!=typeof e.to_representation&&"undefined"!=typeof e.to_representation.paper_coords&&e.show(c.ghost)})},hideNeighbors:function(){var a=this;b.each(this.project.get("edges").filter(function(b){return b.get("from")===a.model}),function(b,c,d){var e=a.renderer.getRepresentationByModel(b.get("to"));e&&e.ghost&&e.hide()})},showNeighbors:function(a){var c=this;b.each(this.project.get("edges").filter(function(a){return a.get("from")===c.model}),function(b,d,e){var f=c.renderer.getRepresentationByModel(b.get("to"));if(f&&f.hidden&&(f.show(a),!a)){var g=c.renderer.view.hiddenNodes.indexOf(f.model.id);-1!==g&&c.renderer.view.hiddenNodes.splice(g,1)}})},highlight:function(a){var b=a||!0;this.highlighted!==b&&(this.highlighted=b,this.redraw(),this.renderer.throttledPaperDraw())},unhighlight:function(){this.highlighted&&(this.highlighted=!1,this.redraw(),this.renderer.throttledPaperDraw())},saveCoords:function(){var a=this.renderer.toModelCoords(this.paper_coords),b={position:{x:a.x,y:a.y}};this.renderer.isEditable()&&this.model.set(b)},mousedown:function(a,b){b&&(this.renderer.unselectAll(),this.select())},mouseup:function(a,b){if(this.renderer.is_dragging&&this.renderer.isEditable())this.saveCoords();else if(this.hidden){var c=this.renderer.view.hiddenNodes.indexOf(this.model.id);-1!==c&&this.renderer.view.hiddenNodes.splice(c,1),this.show(!1),this.select()}else b||this.model.get("delete_scheduled")||this.openEditor(),this.model.trigger("clicked");this.renderer.click_target=null,this.renderer.is_dragging=!1,this.is_dragging=!1},destroy:function(a){this._super("destroy"),this.all_buttons.forEach(function(a){a.destroy()}),this.circle.remove(),this.title.remove(),this.renderer.minimap&&this.minimap_circle.remove(),this.node_image&&this.node_image.remove()}}).value(),g}),define("renderer/edge",["jquery","underscore","requtils","renderer/baserepresentation"],function(a,b,c,d){"use strict";var e=c.getUtils(),f=e.inherit(d);return b(f.prototype).extend({_init:function(){if(this.renderer.edge_layer.activate(),this.type="Edge",this.hidden=!1,this.ghost=!1,this.from_representation=this.renderer.getRepresentationByModel(this.model.get("from")),this.to_representation=this.renderer.getRepresentationByModel(this.model.get("to")),this.bundle=this.renderer.addToBundles(this),this.line=new paper.Path,this.line.add([0,0],[0,0],[0,0]),this.line.__representation=this,this.line.strokeWidth=this.options.edge_stroke_width,this.arrow_scale=1,this.arrow=new paper.Path,this.arrow.add([0,0],[this.options.edge_arrow_length,this.options.edge_arrow_width/2],[0,this.options.edge_arrow_width]),this.arrow.pivot=new paper.Point([this.options.edge_arrow_length/2,this.options.edge_arrow_width/2]),this.arrow.__representation=this,this.text=a('<div class="Rk-Label Rk-Edge-Label">').appendTo(this.renderer.labels_$),this.arrow_angle=0,this.options.editor_mode){var b=c.getRenderer();this.normal_buttons=[new b.EdgeEditButton(this.renderer,null),new b.EdgeRemoveButton(this.renderer,null)],this.pending_delete_buttons=[new b.EdgeRevertButton(this.renderer,null)],this.all_buttons=this.normal_buttons.concat(this.pending_delete_buttons);for(var d=0;d<this.all_buttons.length;d++)this.all_buttons[d].source_representation=this;this.active_buttons=[]}else this.active_buttons=this.all_buttons=[];this.renderer.minimap&&(this.renderer.minimap.edge_layer.activate(),this.minimap_line=new paper.Path,this.minimap_line.add([0,0],[0,0]),this.minimap_line.__representation=this.renderer.minimap.miniframe.__representation,this.minimap_line.strokeWidth=1)},_getStrokeWidth:function(){var a=this.model.has("style")&&this.model.get("style").thickness||1;return this.options.edge_stroke_width+(a-1)*(this.options.edge_stroke_max_width-this.options.edge_stroke_width)/(this.options.edge_stroke_witdh_scale-1)},_getSelectedStrokeWidth:function(){var a=this.model.has("style")&&this.model.get("style").thickness||1;return this.options.selected_edge_stroke_width+(a-1)*(this.options.selected_edge_stroke_max_width-this.options.selected_edge_stroke_width)/(this.options.edge_stroke_witdh_scale-1)},_getArrowScale:function(){var a=this.model.has("style")&&this.model.get("style").thickness||1;return 1+(a-1)*(this.options.edge_arrow_max_width/this.options.edge_arrow_width-1)/(this.options.edge_stroke_witdh_scale-1)},redraw:function(){var a=this.model.get("from"),b=this.model.get("to");if(a&&b&&(!this.hidden||this.ghost)){if(this.from_representation=this.renderer.getRepresentationByModel(a),this.to_representation=this.renderer.getRepresentationByModel(b),"undefined"==typeof this.from_representation||"undefined"==typeof this.to_representation||this.from_representation.hidden&&!this.from_representation.ghost||this.to_representation.hidden&&!this.to_representation.ghost)return void this.hide();var c,d=this._getStrokeWidth(),f=this._getArrowScale(),g=this.from_representation.paper_coords,h=this.to_representation.paper_coords,i=h.subtract(g),j=i.length,k=i.divide(j),l=new paper.Point([-k.y,k.x]),m=this.bundle.getPosition(this),n=l.multiply(this.options.edge_gap_in_bundles*m),o=g.add(n),p=h.add(n),q=i.angle,r=l.multiply(this.options.edge_label_distance+.5*f*this.options.edge_arrow_width),s=i.divide(3),t=this.model.has("style")&&this.model.get("style").color||(this.model.get("created_by")||e._USER_PLACEHOLDER(this.renkan)).get("color"),u=this.model.has("style")&&this.model.get("style").dash?this.options.default_dash_array:null;this.model.get("delete_scheduled")||this.from_representation.model.get("delete_scheduled")||this.to_representation.model.get("delete_scheduled")?(c=.5,this.line.dashArray=[2,2]):(c=this.ghost?this.options.ghost_opacity:1,this.line.dashArray=null);var v=this.active_buttons;this.arrow.visible=this.model.has("style")&&this.model.get("style").arrow||!this.model.has("style")||"undefined"==typeof this.model.get("style").arrow,this.active_buttons=this.model.get("delete_scheduled")?this.pending_delete_buttons:this.normal_buttons,this.selected&&this.renderer.isEditable()&&v!==this.active_buttons&&(v.forEach(function(a){a.hide()}),this.active_buttons.forEach(function(a){a.show()})),this.paper_coords=o.add(p).divide(2),this.line.strokeWidth=d,this.line.strokeColor=t,this.line.dashArray=u,this.line.opacity=c,this.line.segments[0].point=g,this.line.segments[1].point=this.paper_coords,this.line.segments[1].handleIn=s.multiply(-1),this.line.segments[1].handleOut=s,this.line.segments[2].point=h,this.arrow.scale(f/this.arrow_scale),this.arrow_scale=f,this.arrow.fillColor=t,this.arrow.opacity=c,this.arrow.rotate(q-this.arrow_angle,this.arrow.bounds.center),this.arrow.position=this.paper_coords,this.arrow_angle=q,q>90&&(q-=180,r=r.multiply(-1)),-90>q&&(q+=180,r=r.multiply(-1));var w=this.model.get("title")||this.renkan.translate(this.options.label_untitled_edges)||"";w=e.shortenText(w,this.options.node_label_max_length),this.text.text(w);var x=this.paper_coords.add(r);this.text.css({left:x.x,top:x.y,transform:"rotate("+q+"deg)","-moz-transform":"rotate("+q+"deg)","-webkit-transform":"rotate("+q+"deg)",opacity:c}),this.text_angle=q;var y=this.paper_coords;this.all_buttons.forEach(function(a){a.moveTo(y)}),this.renderer.minimap&&(this.minimap_line.strokeColor=t,this.minimap_line.segments[0].point=this.renderer.toMinimapCoords(new paper.Point(this.from_representation.model.get("position"))),this.minimap_line.segments[1].point=this.renderer.toMinimapCoords(new paper.Point(this.to_representation.model.get("position"))))}},hide:function(){this.hidden=!0,this.ghost=!1,this.text.hide(),this.line.visible=!1,this.arrow.visible=!1,this.minimap_line.visible=!1},show:function(a){this.ghost=a,this.ghost?(this.text.css("opacity",.3),this.line.opacity=.3,this.arrow.opacity=.3,this.minimap_line.opacity=.3):(this.hidden=!1,this.text.css("opacity",1),this.line.opacity=1,this.arrow.opacity=1,this.minimap_line.opacity=1),this.text.show(),this.line.visible=!0,this.arrow.visible=!0,this.minimap_line.visible=!0,this.redraw()},openEditor:function(){this.renderer.removeRepresentationsOfType("editor");var a=this.renderer.addRepresentation("EdgeEditor",null);a.source_representation=this,a.draw()},select:function(){this.selected=!0,this.line.strokeWidth=this._getSelectedStrokeWidth(),this.renderer.isEditable()&&this.active_buttons.forEach(function(a){a.show()}),this.options.editor_mode||this.openEditor(),this._super("select")},unselect:function(a){a&&a.source_representation===this||(this.selected=!1,this.options.editor_mode&&this.all_buttons.forEach(function(a){a.hide()}),this.line.strokeWidth=this._getStrokeWidth(),this._super("unselect"))},mousedown:function(a,b){b&&(this.renderer.unselectAll(),this.select())},mouseup:function(a,b){!this.renkan.read_only&&this.renderer.is_dragging?(this.from_representation.saveCoords(),this.to_representation.saveCoords(),this.from_representation.is_dragging=!1,this.to_representation.is_dragging=!1):(b||this.openEditor(),this.model.trigger("clicked")),this.renderer.click_target=null,this.renderer.is_dragging=!1},paperShift:function(a){this.options.editor_mode?this.options.read_only||(this.from_representation.paperShift(a),this.to_representation.paperShift(a)):this.renderer.paperShift(a)},destroy:function(){this._super("destroy"),this.line.remove(),this.arrow.remove(),this.text.remove(),this.renderer.minimap&&this.minimap_line.remove(),this.all_buttons.forEach(function(a){a.destroy()});var a=this;this.bundle.edges=b.reject(this.bundle.edges,function(b){return a===b})}}).value(),f}),define("renderer/tempedge",["jquery","underscore","requtils","renderer/baserepresentation"],function(a,b,c,d){"use strict";var e=c.getUtils(),f=e.inherit(d);return b(f.prototype).extend({_init:function(){this.renderer.edge_layer.activate(),this.type="Temp-edge";var a=(this.project.get("users").get(this.renkan.current_user)||e._USER_PLACEHOLDER(this.renkan)).get("color");this.line=new paper.Path,this.line.strokeColor=a,this.line.dashArray=[4,2],this.line.strokeWidth=this.options.selected_edge_stroke_width,this.line.add([0,0],[0,0]),this.line.__representation=this,this.arrow=new paper.Path,this.arrow.fillColor=a,this.arrow.add([0,0],[this.options.edge_arrow_length,this.options.edge_arrow_width/2],[0,this.options.edge_arrow_width]),this.arrow.__representation=this,this.arrow_angle=0},redraw:function(){var a=this.from_representation.paper_coords,b=this.end_pos,c=b.subtract(a).angle,d=a.add(b).divide(2);this.line.segments[0].point=a,this.line.segments[1].point=b,this.arrow.rotate(c-this.arrow_angle),this.arrow.position=d,this.arrow_angle=c},paperShift:function(a){if(!this.renderer.isEditable())return this.renderer.removeRepresentation(_this),void paper.view.draw();this.end_pos=this.end_pos.add(a);var b=paper.project.hitTest(this.end_pos);this.renderer.findTarget(b),this.redraw()},mouseup:function(a,b){var c=paper.project.hitTest(a.point),d=this.from_representation.model,f=!0;if(c&&"undefined"!=typeof c.item.__representation){var g=c.item.__representation;if("Node"===g.type.substr(0,4)){var h=g.model||g.source_representation.model;if(d!==h){var i={id:e.getUID("edge"),created_by:this.renkan.current_user,from:d,to:h};this.renderer.isEditable()&&this.project.addEdge(i)}}(d===g.model||g.source_representation&&g.source_representation.model===d)&&(f=!1,this.renderer.is_dragging=!0)}f&&(this.renderer.click_target=null,this.renderer.is_dragging=!1,this.renderer.removeRepresentation(this),paper.view.draw())},destroy:function(){this.arrow.remove(),this.line.remove()}}).value(),f}),define("renderer/baseeditor",["jquery","underscore","requtils","renderer/baserepresentation"],function(a,b,c,d){"use strict";var e=c.getUtils(),f=e.inherit(d);return b(f.prototype).extend({_init:function(){this.renderer.buttons_layer.activate(),this.type="editor",this.editor_block=new paper.Path;var c=b.map(b.range(8),function(){return[0,0]});this.editor_block.add.apply(this.editor_block,c),this.editor_block.strokeWidth=this.options.tooltip_border_width,this.editor_block.strokeColor=this.options.tooltip_border_color,this.editor_block.opacity=this.options.tooltip_opacity,this.editor_$=a("<div>").appendTo(this.renderer.editor_$).css({position:"absolute",opacity:this.options.tooltip_opacity}).hide()},destroy:function(){this.editor_block.remove(),this.editor_$.remove()}}).value(),f}),define("renderer/nodeeditor",["jquery","underscore","requtils","renderer/baseeditor","renderer/shapebuilder","ckeditor-jquery"],function(a,b,c,d,e){"use strict";var f=c.getUtils(),g=f.inherit(d);return b(g.prototype).extend({_init:function(){d.prototype._init.apply(this),this.template=this.options.templates["templates/nodeeditor.html"],this.readOnlyTemplate=this.options.node_editor_templates},draw:function(){var c=this.source_representation.model,d=c.get("created_by")||f._USER_PLACEHOLDER(this.renkan),g=this.renderer.isEditable()?this.template:this.readOnlyTemplate[c.get("type")]||this.readOnlyTemplate["default"],h=this.options.static_url+"img/image-placeholder.png",i=c.get("size")||0;this.editor_$.html(g({node:{_id:c.get("_id"),has_creator:!!c.get("created_by"),title:c.get("title"),uri:c.get("uri"),type:c.get("type")||"default",short_uri:f.shortenText((c.get("uri")||"").replace(/^(https?:\/\/)?(www\.)?/,"").replace(/\/$/,""),40),description:c.get("description"),image:c.get("image")||"",image_placeholder:h,color:c.has("style")&&c.get("style").color||d.get("color"),thickness:c.has("style")&&c.get("style").thickness||1,dash:c.has("style")&&c.get("style").dash?"checked":"",clip_path:c.get("clip_path")||!1,created_by_color:d.get("color"),created_by_title:d.get("title"),size:(i>0?"+":"")+i,shape:c.get("shape")||"circle"},renkan:this.renkan,options:this.options,shortenText:f.shortenText,shapes:b(e.builders).omit("svg").keys().value(),types:b(this.options.node_editor_templates).keys().value()})),this.redraw();var j=this,k=j.options.show_node_editor_description_richtext?a(".Rk-Edit-Description").ckeditor(j.options.richtext_editor_config):!1,l=function(){j.renderer.removeRepresentation(j),paper.view.draw()};if(j.cleanEditor=function(){if(j.editor_$.off("keyup"),j.editor_$.find("input, textarea, select").off("change keyup paste"),j.editor_$.find(".Rk-Edit-Image-File").off("change"),j.editor_$.find(".Rk-Edit-ColorPicker-Wrapper").off("hover"),j.editor_$.find(".Rk-Edit-Size-Btn").off("click"),j.editor_$.find(".Rk-Edit-Image-Del").off("click"),j.editor_$.find(".Rk-Edit-ColorPicker").find("li").off("hover click"),j.editor_$.find(".Rk-CloseX").off("click"),j.editor_$.find(".Rk-Edit-Goto").off("click"),j.options.show_node_editor_description_richtext&&"undefined"!=typeof k.editor){var a=k.editor;delete k.editor,a.focusManager.blur(!0),a.destroy()}},this.editor_$.find(".Rk-CloseX").click(function(a){a.preventDefault(),l()}),this.editor_$.find(".Rk-Edit-Goto").click(function(){return c.get("uri")?void 0:!1}),this.renderer.isEditable()){var m=b.throttle(function(){b.defer(function(){if(j.renderer.isEditable()){var a={title:j.editor_$.find(".Rk-Edit-Title").val()};if(j.options.show_node_editor_uri&&(a.uri=j.editor_$.find(".Rk-Edit-URI").val(),j.editor_$.find(".Rk-Edit-Goto").attr("href",a.uri||"#")),j.options.show_node_editor_image&&(a.image=j.editor_$.find(".Rk-Edit-Image").val(),j.editor_$.find(".Rk-Edit-ImgPreview").attr("src",a.image||h)),j.options.show_node_editor_description&&(j.options.show_node_editor_description_richtext?"undefined"!=typeof k.editor&&k.editor.checkDirty()&&(a.description=k.editor.getData(),k.editor.resetDirty()):a.description=j.editor_$.find(".Rk-Edit-Description").val()),j.options.show_node_editor_style){var d=j.editor_$.find(".Rk-Edit-Dash").is(":checked");a.style=b.assign(c.has("style")&&b.clone(c.get("style"))||{},{dash:d})}j.options.change_shapes&&c.get("shape")!==j.editor_$.find(".Rk-Edit-Shape").val()&&(a.shape=j.editor_$.find(".Rk-Edit-Shape").val()),j.options.change_types&&c.get("type")!==j.editor_$.find(".Rk-Edit-Type").val()&&(a.type=j.editor_$.find(".Rk-Edit-Type").val()),c.set(a),j.redraw()}else l()})},1e3);this.editor_$.on("keyup",function(a){27===a.keyCode&&l()}),this.editor_$.find("input, textarea, select").on("change keyup paste",m),j.options.show_node_editor_description&&j.options.show_node_editor_description_richtext&&"undefined"!=typeof k.editor&&(k.editor.on("change",m),k.editor.on("blur",m)),j.options.allow_image_upload&&this.editor_$.find(".Rk-Edit-Image-File").change(function(){if(this.files.length){var a=this.files[0],b=new FileReader;if("image"!==a.type.substr(0,5))return void alert(j.renkan.translate("This file is not an image"));if(a.size>1024*j.options.uploaded_image_max_kb)return void alert(j.renkan.translate("Image size must be under ")+j.options.uploaded_image_max_kb+j.renkan.translate("KB"));b.onload=function(a){j.editor_$.find(".Rk-Edit-Image").val(a.target.result),m()},b.readAsDataURL(a)}}),this.editor_$.find(".Rk-Edit-Title")[0].focus();var n=j.editor_$.find(".Rk-Edit-ColorPicker");this.editor_$.find(".Rk-Edit-ColorPicker-Wrapper").hover(function(a){a.preventDefault(),n.show()},function(a){a.preventDefault(),n.hide()}),n.find("li").hover(function(b){b.preventDefault(),j.editor_$.find(".Rk-Edit-Color").css("background",a(this).attr("data-color"))},function(a){a.preventDefault(),j.editor_$.find(".Rk-Edit-Color").css("background",c.has("style")&&c.get("style").color||(c.get("created_by")||f._USER_PLACEHOLDER(j.renkan)).get("color"));
+}).click(function(d){d.preventDefault(),j.renderer.isEditable()?(c.set("style",b.assign(c.has("style")&&b.clone(c.get("style"))||{},{color:a(this).attr("data-color")})),n.hide(),paper.view.draw()):l()});var o=function(a){if(j.renderer.isEditable()){var b=a+(c.get("size")||0);j.editor_$.find("#Rk-Edit-Size-Value").text((b>0?"+":"")+b),c.set("size",b),paper.view.draw()}else l()};this.editor_$.find("#Rk-Edit-Size-Down").click(function(){return o(-1),!1}),this.editor_$.find("#Rk-Edit-Size-Up").click(function(){return o(1),!1});var p=function(a){if(j.renderer.isEditable()){var d=c.has("style")&&c.get("style").thickness||1,e=a+d;1>e?e=1:e>j.options.node_stroke_witdh_scale&&(e=j.options.node_stroke_witdh_scale),e!==d&&(j.editor_$.find("#Rk-Edit-Thickness-Value").text(e),c.set("style",b.assign(c.has("style")&&b.clone(c.get("style"))||{},{thickness:e})),paper.view.draw())}else l()};this.editor_$.find("#Rk-Edit-Thickness-Down").click(function(){return p(-1),!1}),this.editor_$.find("#Rk-Edit-Thickness-Up").click(function(){return p(1),!1}),this.editor_$.find(".Rk-Edit-Image-Del").click(function(){return j.editor_$.find(".Rk-Edit-Image").val(""),m(),!1})}else if("object"==typeof this.source_representation.highlighted){var q=this.source_representation.highlighted.replace(b(c.get("title")).escape(),'<span class="Rk-Highlighted">$1</span>');this.editor_$.find(".Rk-Display-Title"+(c.get("uri")?" a":"")).html(q),this.options.show_node_tooltip_description&&this.editor_$.find(".Rk-Display-Description").html(this.source_representation.highlighted.replace(b(c.get("description")).escape(),'<span class="Rk-Highlighted">$1</span>'))}this.editor_$.find("img").load(function(){j.redraw()})},redraw:function(){if(this.options.popup_editor){var a=this.source_representation.paper_coords;f.drawEditBox(this.options,a,this.editor_block,.75*this.source_representation.circle_radius,this.editor_$)}this.editor_$.show(),paper.view.draw()},destroy:function(){"undefined"!=typeof this.cleanEditor&&this.cleanEditor(),this.editor_block.remove(),this.editor_$.remove()}}).value(),g}),define("renderer/edgeeditor",["jquery","underscore","requtils","renderer/baseeditor"],function(a,b,c,d){"use strict";var e=c.getUtils(),f=e.inherit(d);return b(f.prototype).extend({_init:function(){d.prototype._init.apply(this),this.template=this.options.templates["templates/edgeeditor.html"],this.readOnlyTemplate=this.options.templates["templates/edgeeditor_readonly.html"]},draw:function(){var c=this.source_representation.model,d=c.get("from"),f=c.get("to"),g=c.get("created_by")||e._USER_PLACEHOLDER(this.renkan),h=this.renderer.isEditable()?this.template:this.readOnlyTemplate;this.editor_$.html(h({edge:{has_creator:!!c.get("created_by"),title:c.get("title"),uri:c.get("uri"),short_uri:e.shortenText((c.get("uri")||"").replace(/^(https?:\/\/)?(www\.)?/,"").replace(/\/$/,""),40),description:c.get("description"),color:c.has("style")&&c.get("style").color||g.get("color"),dash:c.has("style")&&c.get("style").dash?"checked":"",arrow:c.has("style")&&c.get("style").arrow||!c.has("style")||"undefined"==typeof c.get("style").arrow?"checked":"",thickness:c.has("style")&&c.get("style").thickness||1,from_title:d.get("title"),to_title:f.get("title"),from_color:d.has("style")&&d.get("style").color||(d.get("created_by")||e._USER_PLACEHOLDER(this.renkan)).get("color"),to_color:f.has("style")&&f.get("style").color||(f.get("created_by")||e._USER_PLACEHOLDER(this.renkan)).get("color"),created_by_color:g.get("color"),created_by_title:g.get("title")},renkan:this.renkan,shortenText:e.shortenText,options:this.options})),this.redraw();var i=this,j=function(){i.renderer.removeRepresentation(i),i.editor_$.find(".Rk-Edit-Size-Btn").off("click"),paper.view.draw()};if(this.editor_$.find(".Rk-CloseX").click(j),this.editor_$.find(".Rk-Edit-Goto").click(function(){return c.get("uri")?void 0:!1}),this.renderer.isEditable()){var k=b.throttle(function(){b.defer(function(){if(i.renderer.isEditable()){var a={title:i.editor_$.find(".Rk-Edit-Title").val()};if(i.options.show_edge_editor_uri&&(a.uri=i.editor_$.find(".Rk-Edit-URI").val()),i.options.show_node_editor_style){var d=i.editor_$.find(".Rk-Edit-Dash").is(":checked"),e=i.editor_$.find(".Rk-Edit-Arrow").is(":checked");a.style=b.assign(c.has("style")&&b.clone(c.get("style"))||{},{dash:d,arrow:e})}i.editor_$.find(".Rk-Edit-Goto").attr("href",a.uri||"#"),c.set(a),paper.view.draw()}else j()})},500);this.editor_$.on("keyup",function(a){27===a.keyCode&&j()}),this.editor_$.find("input").on("keyup change paste",k),this.editor_$.find(".Rk-Edit-Vocabulary").change(function(){var b=a(this),c=b.val();c&&(i.editor_$.find(".Rk-Edit-Title").val(b.find(":selected").text()),i.editor_$.find(".Rk-Edit-URI").val(c),k())}),this.editor_$.find(".Rk-Edit-Direction").click(function(){i.renderer.isEditable()?(c.set({from:c.get("to"),to:c.get("from")}),i.draw()):j()});var l=i.editor_$.find(".Rk-Edit-ColorPicker");this.editor_$.find(".Rk-Edit-ColorPicker-Wrapper").hover(function(a){a.preventDefault(),l.show()},function(a){a.preventDefault(),l.hide()}),l.find("li").hover(function(b){b.preventDefault(),i.editor_$.find(".Rk-Edit-Color").css("background",a(this).attr("data-color"))},function(a){a.preventDefault(),i.editor_$.find(".Rk-Edit-Color").css("background",c.has("style")&&c.get("style").color||(c.get("created_by")||e._USER_PLACEHOLDER(i.renkan)).get("color"))}).click(function(d){d.preventDefault(),i.renderer.isEditable()?(c.set("style",b.assign(c.has("style")&&b.clone(c.get("style"))||{},{color:a(this).attr("data-color")})),l.hide(),paper.view.draw()):j()});var m=function(a){if(i.renderer.isEditable()){var d=c.has("style")&&c.get("style").thickness||1,e=a+d;1>e?e=1:e>i.options.node_stroke_witdh_scale&&(e=i.options.node_stroke_witdh_scale),e!==d&&(i.editor_$.find("#Rk-Edit-Thickness-Value").text(e),c.set("style",b.assign(c.has("style")&&b.clone(c.get("style"))||{},{thickness:e})),paper.view.draw())}else j()};this.editor_$.find("#Rk-Edit-Thickness-Down").click(function(){return m(-1),!1}),this.editor_$.find("#Rk-Edit-Thickness-Up").click(function(){return m(1),!1})}},redraw:function(){if(this.options.popup_editor){var a=this.source_representation.paper_coords;e.drawEditBox(this.options,a,this.editor_block,5,this.editor_$)}this.editor_$.show(),paper.view.draw()}}).value(),f}),define("renderer/nodebutton",["jquery","underscore","requtils","renderer/basebutton"],function(a,b,c,d){"use strict";var e=c.getUtils(),f=e.inherit(d);return b(f.prototype).extend({setSectorSize:function(){var a=this.source_representation.circle_radius;a!==this.lastSectorInner&&(this.sector&&this.sector.destroy(),this.sector=this.renderer.drawSector(this,1+a,e._NODE_BUTTON_WIDTH+a,this.startAngle,this.endAngle,1,this.imageName,this.renkan.translate(this.text)),this.lastSectorInner=a)},unselect:function(){d.prototype.unselect.apply(this,Array.prototype.slice.call(arguments,1)),this.source_representation&&this.source_representation.buttons_timeout&&(clearTimeout(this.source_representation.buttons_timeout),this.source_representation.hideButtons())},select:function(){this.source_representation&&this.source_representation.buttons_timeout&&clearTimeout(this.source_representation.buttons_timeout),this.sector.select()}}).value(),f}),define("renderer/nodeeditbutton",["jquery","underscore","requtils","renderer/nodebutton"],function(a,b,c,d){"use strict";var e=c.getUtils(),f=e.inherit(d);return b(f.prototype).extend({_init:function(){this.type="Node-edit-button",this.lastSectorInner=0,this.startAngle=this.options.hide_nodes?-125:-135,this.endAngle=this.options.hide_nodes?-55:-45,this.imageName="edit",this.text="Edit"},mouseup:function(){this.renderer.is_dragging||this.source_representation.openEditor()}}).value(),f}),define("renderer/noderemovebutton",["jquery","underscore","requtils","renderer/nodebutton"],function(a,b,c,d){"use strict";var e=c.getUtils(),f=e.inherit(d);return b(f.prototype).extend({_init:function(){this.type="Node-remove-button",this.lastSectorInner=0,this.startAngle=this.options.hide_nodes?-10:0,this.endAngle=this.options.hide_nodes?45:90,this.imageName="remove",this.text="Remove"},mouseup:function(){if(this.renderer.click_target=null,this.renderer.is_dragging=!1,this.renderer.removeRepresentationsOfType("editor"),this.renderer.isEditable())if(this.options.element_delete_delay){var a=e.getUID("delete");this.renderer.delete_list.push({id:a,time:(new Date).valueOf()+this.options.element_delete_delay}),this.source_representation.model.set("delete_scheduled",a)}else confirm(this.renkan.translate("Do you really wish to remove node ")+'"'+this.source_representation.model.get("title")+'"?')&&this.project.removeNode(this.source_representation.model)}}).value(),f}),define("renderer/nodehidebutton",["jquery","underscore","requtils","renderer/nodebutton"],function(a,b,c,d){"use strict";var e=c.getUtils(),f=e.inherit(d);return b(f.prototype).extend({_init:function(){this.type="Node-hide-button",this.lastSectorInner=0,this.startAngle=45,this.endAngle=90,this.imageName="hide",this.text="Hide"},mouseup:function(){this.renderer.click_target=null,this.renderer.is_dragging=!1,this.renderer.removeRepresentationsOfType("editor"),this.renderer.isEditable()&&this.renderer.view.addHiddenNode(this.source_representation.model)}}).value(),f}),define("renderer/nodeshowbutton",["jquery","underscore","requtils","renderer/nodebutton"],function(a,b,c,d){"use strict";var e=c.getUtils(),f=e.inherit(d);return b(f.prototype).extend({_init:function(){this.type="Node-show-button",this.lastSectorInner=0,this.startAngle=90,this.endAngle=135,this.imageName="show",this.text="Show"},mouseup:function(){this.renderer.click_target=null,this.renderer.is_dragging=!1,this.renderer.removeRepresentationsOfType("editor"),this.renderer.isEditable()&&this.source_representation.showNeighbors(!1)}}).value(),f}),define("renderer/noderevertbutton",["jquery","underscore","requtils","renderer/nodebutton"],function(a,b,c,d){"use strict";var e=c.getUtils(),f=e.inherit(d);return b(f.prototype).extend({_init:function(){this.type="Node-revert-button",this.lastSectorInner=0,this.startAngle=-135,this.endAngle=135,this.imageName="revert",this.text="Cancel deletion"},mouseup:function(){this.renderer.click_target=null,this.renderer.is_dragging=!1,this.renderer.isEditable()&&this.source_representation.model.unset("delete_scheduled")}}).value(),f}),define("renderer/nodelinkbutton",["jquery","underscore","requtils","renderer/nodebutton"],function(a,b,c,d){"use strict";var e=c.getUtils(),f=e.inherit(d);return b(f.prototype).extend({_init:function(){this.type="Node-link-button",this.lastSectorInner=0,this.startAngle=this.options.hide_nodes?135:90,this.endAngle=this.options.hide_nodes?190:180,this.imageName="link",this.text="Link to another node"},mousedown:function(a,b){if(this.renderer.isEditable()){var c=this.renderer.canvas_$.offset(),d=new paper.Point([a.pageX-c.left,a.pageY-c.top]);this.renderer.click_target=null,this.renderer.removeRepresentationsOfType("editor"),this.renderer.addTempEdge(this.source_representation,d)}}}).value(),f}),define("renderer/nodeenlargebutton",["jquery","underscore","requtils","renderer/nodebutton"],function(a,b,c,d){"use strict";var e=c.getUtils(),f=e.inherit(d);return b(f.prototype).extend({_init:function(){this.type="Node-enlarge-button",this.lastSectorInner=0,this.startAngle=this.options.hide_nodes?-55:-45,this.endAngle=this.options.hide_nodes?-10:0,this.imageName="enlarge",this.text="Enlarge"},mouseup:function(){var a=1+(this.source_representation.model.get("size")||0);this.source_representation.model.set("size",a),this.source_representation.select(),this.select(),paper.view.draw()}}).value(),f}),define("renderer/nodeshrinkbutton",["jquery","underscore","requtils","renderer/nodebutton"],function(a,b,c,d){"use strict";var e=c.getUtils(),f=e.inherit(d);return b(f.prototype).extend({_init:function(){this.type="Node-shrink-button",this.lastSectorInner=0,this.startAngle=this.options.hide_nodes?-170:-180,this.endAngle=this.options.hide_nodes?-125:-135,this.imageName="shrink",this.text="Shrink"},mouseup:function(){var a=-1+(this.source_representation.model.get("size")||0);this.source_representation.model.set("size",a),this.source_representation.select(),this.select(),paper.view.draw()}}).value(),f}),define("renderer/edgeeditbutton",["jquery","underscore","requtils","renderer/basebutton"],function(a,b,c,d){"use strict";var e=c.getUtils(),f=e.inherit(d);return b(f.prototype).extend({_init:function(){this.type="Edge-edit-button",this.sector=this.renderer.drawSector(this,e._EDGE_BUTTON_INNER,e._EDGE_BUTTON_OUTER,-270,-90,1,"edit",this.renkan.translate("Edit"))},mouseup:function(){this.renderer.is_dragging||this.source_representation.openEditor()}}).value(),f}),define("renderer/edgeremovebutton",["jquery","underscore","requtils","renderer/basebutton"],function(a,b,c,d){"use strict";var e=c.getUtils(),f=e.inherit(d);return b(f.prototype).extend({_init:function(){this.type="Edge-remove-button",this.sector=this.renderer.drawSector(this,e._EDGE_BUTTON_INNER,e._EDGE_BUTTON_OUTER,-90,90,1,"remove",this.renkan.translate("Remove"))},mouseup:function(){if(this.renderer.click_target=null,this.renderer.is_dragging=!1,this.renderer.removeRepresentationsOfType("editor"),this.renderer.isEditable())if(this.options.element_delete_delay){var a=e.getUID("delete");this.renderer.delete_list.push({id:a,time:(new Date).valueOf()+this.options.element_delete_delay}),this.source_representation.model.set("delete_scheduled",a)}else confirm(this.renkan.translate("Do you really wish to remove edge ")+'"'+this.source_representation.model.get("title")+'"?')&&this.project.removeEdge(this.source_representation.model)}}).value(),f}),define("renderer/edgerevertbutton",["jquery","underscore","requtils","renderer/basebutton"],function(a,b,c,d){"use strict";var e=c.getUtils(),f=e.inherit(d);return b(f.prototype).extend({_init:function(){this.type="Edge-revert-button",this.sector=this.renderer.drawSector(this,e._EDGE_BUTTON_INNER,e._EDGE_BUTTON_OUTER,-135,135,1,"revert",this.renkan.translate("Cancel deletion"))},mouseup:function(){this.renderer.click_target=null,this.renderer.is_dragging=!1,this.renderer.isEditable()&&this.source_representation.model.unset("delete_scheduled")}}).value(),f}),define("renderer/miniframe",["jquery","underscore","requtils","renderer/baserepresentation"],function(a,b,c,d){"use strict";var e=c.getUtils(),f=e.inherit(d);return b(f.prototype).extend({paperShift:function(a){this.renderer.offset=this.renderer.offset.subtract(a.divide(this.renderer.minimap.scale).multiply(this.renderer.scale)),this.renderer.redraw()},mouseup:function(a){this.renderer.click_target=null,this.renderer.is_dragging=!1}}).value(),f}),define("renderer/scene",["jquery","underscore","filesaver","requtils","renderer/miniframe"],function(a,b,c,d,e){"use strict";var f=d.getUtils(),g=function(c){this.renkan=c,this.$=a(".Rk-Render"),this.representations=[],this.$.html(c.options.templates["templates/scene.html"](c)),this.onStatusChange(),this.canvas_$=this.$.find(".Rk-Canvas"),this.labels_$=this.$.find(".Rk-Labels"),c.options.popup_editor?this.editor_$=this.$.find(".Rk-Editor"):this.editor_$=a("#"+c.options.editor_panel),this.notif_$=this.$.find(".Rk-Notifications"),paper.setup(this.canvas_$[0]),this.totalScroll=0,this.mouse_down=!1,this.click_target=null,this.selected_target=null,this.edge_layer=new paper.Layer,this.node_layer=new paper.Layer,this.buttons_layer=new paper.Layer,this.delete_list=[],this.redrawActive=!0,c.options.show_minimap&&(this.minimap={background_layer:new paper.Layer,edge_layer:new paper.Layer,node_layer:new paper.Layer,node_group:new paper.Group,size:new paper.Size(c.options.minimap_width,c.options.minimap_height)},this.minimap.background_layer.activate(),this.minimap.topleft=paper.view.bounds.bottomRight.subtract(this.minimap.size),this.minimap.rectangle=new paper.Path.Rectangle(this.minimap.topleft.subtract([2,2]),this.minimap.size.add([4,4])),this.minimap.rectangle.fillColor=c.options.minimap_background_color,this.minimap.rectangle.strokeColor=c.options.minimap_border_color,this.minimap.rectangle.strokeWidth=4,this.minimap.offset=new paper.Point(this.minimap.size.divide(2)),this.minimap.scale=.1,this.minimap.node_layer.activate(),this.minimap.cliprectangle=new paper.Path.Rectangle(this.minimap.topleft,this.minimap.size),this.minimap.node_group.addChild(this.minimap.cliprectangle),this.minimap.node_group.clipped=!0,this.minimap.miniframe=new paper.Path.Rectangle(this.minimap.topleft,this.minimap.size),this.minimap.node_group.addChild(this.minimap.miniframe),this.minimap.miniframe.fillColor="#c0c0ff",this.minimap.miniframe.opacity=.3,this.minimap.miniframe.strokeColor="#000080",this.minimap.miniframe.strokeWidth=2,this.minimap.miniframe.__representation=new e(this,null)),this.throttledPaperDraw=b(function(){paper.view.draw()}).throttle(100).value(),this.bundles=[],this.click_mode=!1;var d=this,g=!0,h=1,i=!1,j=0,k=0;this.image_cache={},this.icon_cache={},["edit","remove","hide","show","link","enlarge","shrink","revert"].forEach(function(a){var b=new Image;b.src=c.options.static_url+"img/"+a+".png",d.icon_cache[a]=b});var l=b.throttle(function(a,b){d.onMouseMove(a,b)},f._MOUSEMOVE_RATE);this.canvas_$.on({mousedown:function(a){a.preventDefault(),d.onMouseDown(a,!1)},mousemove:function(a){a.preventDefault(),l(a,!1)},mouseup:function(a){a.preventDefault(),d.onMouseUp(a,!1)},mousewheel:function(a,b){c.options.zoom_on_scroll&&(a.preventDefault(),g&&d.onScroll(a,b))},touchstart:function(a){a.preventDefault();var b=a.originalEvent.touches[0];c.options.allow_double_click&&new Date-_lastTap<f._DOUBLETAP_DELAY&&Math.pow(j-b.pageX,2)+Math.pow(k-b.pageY,2)<f._DOUBLETAP_DISTANCE?(_lastTap=0,d.onDoubleClick(b)):(_lastTap=new Date,j=b.pageX,k=b.pageY,h=d.view.scale,i=!1,d.onMouseDown(b,!0))},touchmove:function(a){if(a.preventDefault(),_lastTap=0,1===a.originalEvent.touches.length)d.onMouseMove(a.originalEvent.touches[0],!0);else{if(i||(d.onMouseUp(a.originalEvent.touches[0],!0),d.click_target=null,d.is_dragging=!1,i=!0),"undefined"===a.originalEvent.scale)return;var b=a.originalEvent.scale*h,c=b/d.view.scale,e=new paper.Point([d.canvas_$.width(),d.canvas_$.height()]).multiply(.5*(1-c)).add(d.view.offset.multiply(c));d.view.setScale(b,e)}},touchend:function(a){a.preventDefault(),d.onMouseUp(a.originalEvent.changedTouches[0],!0)},dblclick:function(a){a.preventDefault(),c.options.allow_double_click&&d.onDoubleClick(a)},mouseleave:function(a){a.preventDefault(),d.click_target=null,d.is_dragging=!1},dragover:function(a){a.preventDefault()},dragenter:function(a){a.preventDefault(),g=!1},dragleave:function(a){a.preventDefault(),g=!0},drop:function(a){a.preventDefault(),g=!0;var c={};b.each(a.originalEvent.dataTransfer.types,function(b){try{c[b]=a.originalEvent.dataTransfer.getData(b)}catch(d){}});var e=a.originalEvent.dataTransfer.getData("Text");if("string"==typeof e)switch(e[0]){case"{":case"[":try{var f=JSON.parse(e);b.extend(c,f)}catch(h){c["text/plain"]||(c["text/plain"]=e)}break;case"<":c["text/html"]||(c["text/html"]=e);break;default:c["text/plain"]||(c["text/plain"]=e)}var i=a.originalEvent.dataTransfer.getData("URL");i&&!c["text/uri-list"]&&(c["text/uri-list"]=i),d.dropData(c,a.originalEvent)}});var m=function(a,b){d.$.find(a).click(function(a){return d[b](a),!1})};this.renkan.project.get("views").length>0&&this.renkan.options.save_view&&this.$.find(".Rk-ZoomSetSaved").show(),this.$.find(".Rk-CurrentUser").mouseenter(function(){d.$.find(".Rk-UserList").slideDown()}),this.$.find(".Rk-Users").mouseleave(function(){d.$.find(".Rk-UserList").slideUp()}),m(".Rk-FullScreen-Button","fullScreen"),m(".Rk-AddNode-Button","addNodeBtn"),m(".Rk-AddEdge-Button","addEdgeBtn"),m(".Rk-Save-Button","save"),m(".Rk-Open-Button","open"),m(".Rk-Export-Button","exportProject"),this.$.find(".Rk-Bookmarklet-Button").attr("href","javascript:"+f._BOOKMARKLET_CODE(c)).click(function(){return d.notif_$.text(c.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.")).fadeIn().delay(5e3).fadeOut(),!1}),this.$.find(".Rk-TopBar-Button").mouseover(function(){a(this).find(".Rk-TopBar-Tooltip").show()}).mouseout(function(){a(this).find(".Rk-TopBar-Tooltip").hide()}),m(".Rk-Fold-Bins","foldBins"),paper.view.onResize=function(a){var b,c=a.width,e=a.height;d.minimap&&(d.minimap.topleft=paper.view.bounds.bottomRight.subtract(d.minimap.size),d.minimap.rectangle.fitBounds(d.minimap.topleft.subtract([2,2]),d.minimap.size.add([4,4])),d.minimap.cliprectangle.fitBounds(d.minimap.topleft,d.minimap.size));var f=e/(e-a.delta.height),g=c/(c-a.delta.width);b=c>e?f:g,d.view.resizeZoom(g,f,b),d.redraw()};var n=b.throttle(function(){d.redraw()},50);this.addRepresentations("Node",this.renkan.project.get("nodes")),this.addRepresentations("Edge",this.renkan.project.get("edges")),this.renkan.project.on("change:title",function(){d.$.find(".Rk-PadTitle").val(c.project.get("title"))}),this.$.find(".Rk-PadTitle").on("keyup input paste",function(){c.project.set({title:a(this).val()})});var o=b.throttle(function(){d.redrawUsers()},100);if(o(),this.renkan.project.on("change:saveStatus",function(){switch(d.renkan.project.get("saveStatus")){case 0:d.$.find(".Rk-Save-Button").removeClass("to-save"),d.$.find(".Rk-Save-Button").removeClass("saving"),d.$.find(".Rk-Save-Button").addClass("saved");break;case 1:d.$.find(".Rk-Save-Button").removeClass("saved"),d.$.find(".Rk-Save-Button").removeClass("saving"),d.$.find(".Rk-Save-Button").addClass("to-save");break;case 2:d.$.find(".Rk-Save-Button").removeClass("saved"),d.$.find(".Rk-Save-Button").removeClass("to-save"),d.$.find(".Rk-Save-Button").addClass("saving")}}),this.renkan.project.on("change:loadingStatus",function(){if(d.renkan.project.get("loadingStatus")){d.$.find(".loader").addClass("run"),setTimeout(function(){d.$.find(".loader").hide(250)},3e3)}else Backbone.history.start(),n()}),this.renkan.project.on("add:users remove:users",o),this.renkan.project.on("add:views remove:views",function(a){d.renkan.project.get("views").length>0?d.$.find(".Rk-ZoomSetSaved").show():d.$.find(".Rk-ZoomSetSaved").hide()}),this.renkan.project.on("add:nodes",function(a){d.addRepresentation("Node",a),d.renkan.project.get("loadingStatus")||n()}),this.renkan.project.on("add:edges",function(a){d.addRepresentation("Edge",a),d.renkan.project.get("loadingStatus")||n()}),this.renkan.project.on("change:title",function(a,b){var c=d.$.find(".Rk-PadTitle");c.is("input")?c.val()!==b&&c.val(b):c.text(b)}),this.renkan.router.on("router",function(a){d.parameters(a)}),c.options.size_bug_fix){var p="number"==typeof c.options.size_bug_fix?c.options.size_bug_fix:500;window.setTimeout(function(){d.fixSize()},p)}if(c.options.force_resize&&a(window).resize(function(){d.autoScale()}),c.options.show_user_list&&c.options.user_color_editable){var q=this.$.find(".Rk-Users .Rk-Edit-ColorPicker-Wrapper"),r=this.$.find(".Rk-Users .Rk-Edit-ColorPicker");q.hover(function(a){d.isEditable()&&(a.preventDefault(),r.show())},function(a){a.preventDefault(),r.hide()}),r.find("li").mouseenter(function(b){d.isEditable()&&(b.preventDefault(),d.$.find(".Rk-CurrentUser-Color").css("background",a(this).attr("data-color")))})}if(c.options.show_search_field){var s="";this.$.find(".Rk-GraphSearch-Field").on("keyup change paste input",function(){var b=a(this),e=b.val();if(e!==s)if(s=e,e.length<2)c.project.get("nodes").each(function(a){d.getRepresentationByModel(a).unhighlight()});else{var g=f.regexpFromTextOrArray(e);c.project.get("nodes").each(function(a){g.test(a.get("title"))||g.test(a.get("description"))?d.getRepresentationByModel(a).highlight(g):d.getRepresentationByModel(a).unhighlight()})}})}this.redraw(),window.setInterval(function(){var a=(new Date).valueOf();d.delete_list.forEach(function(b){if(a>=b.time){var d=c.project.get("nodes").findWhere({delete_scheduled:b.id});d&&project.removeNode(d),d=c.project.get("edges").findWhere({delete_scheduled:b.id}),d&&project.removeEdge(d)}}),d.delete_list=d.delete_list.filter(function(a){return c.project.get("nodes").findWhere({delete_scheduled:a.id})||c.project.get("edges").findWhere({delete_scheduled:a.id})})},500),this.minimap&&window.setInterval(function(){d.rescaleMinimap()},2e3)};return b(g.prototype).extend({fixSize:function(){"undefined"==typeof this.view?(this.view=this.addRepresentation("View",this.renkan.project.get("views").last()),this.view.setScale(view.get("zoom_level"),new paper.Point(view.get("offset")))):this.view.autoScale()},drawSector:function(b,c,d,e,f,g,h,i){var j=this.renkan.options,k=e*Math.PI/180,l=f*Math.PI/180,m=this.icon_cache[h],n=-Math.sin(k),o=Math.cos(k),p=Math.cos(k)*c+g*n,q=Math.sin(k)*c+g*o,r=Math.cos(k)*d+g*n,s=Math.sin(k)*d+g*o,t=-Math.sin(l),u=Math.cos(l),v=Math.cos(l)*c-g*t,w=Math.sin(l)*c-g*u,x=Math.cos(l)*d-g*t,y=Math.sin(l)*d-g*u,z=(c+d)/2,A=(k+l)/2,B=Math.cos(A)*z,C=Math.sin(A)*z,D=Math.cos(A)*c,E=Math.cos(A)*d,F=Math.sin(A)*c,G=Math.sin(A)*d,H=Math.cos(A)*(d+3),I=Math.sin(A)*(d+j.buttons_label_font_size)+j.buttons_label_font_size/2;this.buttons_layer.activate();var J=new paper.Path;J.add([p,q]),J.arcTo([D,F],[v,w]),J.lineTo([x,y]),J.arcTo([E,G],[r,s]),J.fillColor=j.buttons_background,J.opacity=.5,J.closed=!0,J.__representation=b;var K=new paper.PointText(H,I);K.characterStyle={fontSize:j.buttons_label_font_size,fillColor:j.buttons_label_color},H>2?K.paragraphStyle.justification="left":-2>H?K.paragraphStyle.justification="right":K.paragraphStyle.justification="center",K.visible=!1;var L=!1,M=new paper.Point(-200,-200),N=new paper.Group([J,K]),O=N.position,P=new paper.Point([B,C]),Q=new paper.Point(0,0);K.content=i,N.pivot=N.bounds.center,N.visible=!1,N.position=M;var R={show:function(){L=!0,N.position=Q.add(O),N.visible=!0},moveTo:function(a){Q=a,L&&(N.position=a.add(O))},hide:function(){L=!1,N.visible=!1,N.position=M},select:function(){J.opacity=.8,K.visible=!0},unselect:function(){J.opacity=.5,K.visible=!1},destroy:function(){N.remove()}},S=function(){var a=new paper.Raster(m);a.position=P.add(N.position).subtract(O),a.locked=!0,N.addChild(a)};return m.width?S():a(m).on("load",S),R},addToBundles:function(a){var c=b(this.bundles).find(function(b){return b.from===a.from_representation&&b.to===a.to_representation||b.from===a.to_representation&&b.to===a.from_representation});return"undefined"!=typeof c?c.edges.push(a):(c={from:a.from_representation,to:a.to_representation,edges:[a],getPosition:function(a){var c=a.from_representation===this.from?1:-1;return c*(b(this.edges).indexOf(a)-(this.edges.length-1)/2)}},this.bundles.push(c)),c},isEditable:function(){return this.renkan.options.editor_mode&&!this.renkan.read_only},onStatusChange:function(){var a=this.$.find(".Rk-Save-Button"),b=a.find(".Rk-TopBar-Tooltip-Contents");this.renkan.read_only?(a.removeClass("disabled Rk-Save-Online").addClass("Rk-Save-ReadOnly"),b.text(this.renkan.translate("Connection lost"))):this.renkan.options.manual_save?(a.removeClass("Rk-Save-ReadOnly Rk-Save-Online"),b.text(this.renkan.translate("Save Project"))):(a.removeClass("disabled Rk-Save-ReadOnly").addClass("Rk-Save-Online"),b.text(this.renkan.translate("Auto-save enabled"))),this.redrawUsers()},redrawMiniframe:function(){var a=this.toMinimapCoords(this.toModelCoords(new paper.Point([0,0]))),b=this.toMinimapCoords(this.toModelCoords(paper.view.bounds.bottomRight));this.minimap.miniframe.fitBounds(a,b)},rescaleMinimap:function(){var a=this.renkan.project.get("nodes");if(a.length>1){var b=a.map(function(a){return a.get("position").x}),c=a.map(function(a){return a.get("position").y}),d=Math.min.apply(Math,b),e=Math.min.apply(Math,c),f=Math.max.apply(Math,b),g=Math.max.apply(Math,c),h=Math.min(.8*this.view.scale*this.renkan.options.minimap_width/paper.view.bounds.width,.8*this.view.scale*this.renkan.options.minimap_height/paper.view.bounds.height,(this.renkan.options.minimap_width-2*this.renkan.options.minimap_padding)/(f-d),(this.renkan.options.minimap_height-2*this.renkan.options.minimap_padding)/(g-e));this.minimap.offset=this.minimap.size.divide(2).subtract(new paper.Point([(f+d)/2,(g+e)/2]).multiply(h)),this.minimap.scale=h}1===a.length&&(this.minimap.scale=.1,this.minimap.offset=this.minimap.size.divide(2).subtract(new paper.Point([a.at(0).get("position").x,a.at(0).get("position").y]).multiply(this.minimap.scale))),this.redraw()},toPaperCoords:function(a){return a.multiply(this.view.scale).add(this.view.offset)},toMinimapCoords:function(a){return a.multiply(this.minimap.scale).add(this.minimap.offset).add(this.minimap.topleft)},toModelCoords:function(a){return a.subtract(this.view.offset).divide(this.view.scale)},addRepresentation:function(a,b){var c=d.getRenderer()[a],e=new c(this,b);return this.representations.push(e),e},addRepresentations:function(a,b){var c=this;b.forEach(function(b){c.addRepresentation(a,b)})},userTemplate:b.template('<li class="Rk-User"><span class="Rk-UserColor" style="background:<%=background%>;"></span><%=name%></li>'),redrawUsers:function(){if(this.renkan.options.show_user_list){var b=[].concat((this.renkan.project.current_user_list||{}).models||[],(this.renkan.project.get("users")||{}).models||[]),c="",d=this.$.find(".Rk-Users"),e=d.find(".Rk-CurrentUser-Name"),f=d.find(".Rk-Edit-ColorPicker li"),g=d.find(".Rk-CurrentUser-Color"),h=this;e.off("click").text(this.renkan.translate("<unknown user>")),f.off("mouseleave click"),b.forEach(function(b){b.get("_id")===h.renkan.current_user?(e.text(b.get("title")),g.css("background",b.get("color")),h.isEditable()&&(h.renkan.options.user_name_editable&&e.click(function(){var c=a(this),d=a("<input>").val(b.get("title")).blur(function(){b.set("title",a(this).val()),h.redrawUsers(),h.redraw()});c.empty().html(d),d.select()}),h.renkan.options.user_color_editable&&f.click(function(c){c.preventDefault(),h.isEditable()&&b.set("color",a(this).attr("data-color")),a(this).parent().hide()}).mouseleave(function(){g.css("background",b.get("color"))}))):c+=h.userTemplate({name:b.get("title"),background:b.get("color")})}),d.find(".Rk-UserList").html(c)}},removeRepresentation:function(a){a.destroy(),this.representations=b.reject(this.representations,function(b){return b===a})},getRepresentationByModel:function(a){return a?b.find(this.representations,function(b){return b.model===a}):void 0},removeRepresentationsOfType:function(a){var c=b.filter(this.representations,function(b){return b.type===a}),d=this;b.each(c,function(a){d.removeRepresentation(a)})},highlightModel:function(a){var b=this.getRepresentationByModel(a);b&&b.highlight()},unhighlightAll:function(a){b.each(this.representations,function(a){a.unhighlight()})},unselectAll:function(a){b.each(this.representations,function(a){a.unselect()})},redraw:function(){this.redrawActive&&(b.each(this.representations,function(a){a.redraw({dontRedrawEdges:!0})}),this.minimap&&"undefined"!=typeof this.view&&this.redrawMiniframe(),paper.view.draw())},addTempEdge:function(a,b){var c=this.addRepresentation("TempEdge",null);c.end_pos=b,c.from_representation=a,c.redraw(),this.click_target=c},findTarget:function(a){if(a&&"undefined"!=typeof a.item.__representation){var b=a.item.__representation;this.selected_target!==a.item.__representation&&(this.selected_target&&this.selected_target.unselect(b),b.select(this.selected_target),this.selected_target=b)}else this.selected_target&&this.selected_target.unselect(),this.selected_target=null},onMouseMove:function(a){var b=this.canvas_$.offset(),c=new paper.Point([a.pageX-b.left,a.pageY-b.top]),d=c.subtract(this.last_point);this.last_point=c,!this.is_dragging&&this.mouse_down&&d.length>f._MIN_DRAG_DISTANCE&&(this.is_dragging=!0);var e=paper.project.hitTest(c);this.is_dragging?this.click_target&&"function"==typeof this.click_target.paperShift?this.click_target.paperShift(d):this.view.paperShift(d):this.findTarget(e),paper.view.draw()},onMouseDown:function(b,c){var d=this.canvas_$.offset(),e=new paper.Point([b.pageX-d.left,b.pageY-d.top]);
+if(this.last_point=e,this.mouse_down=!0,!this.click_target||"Temp-edge"!==this.click_target.type){this.removeRepresentationsOfType("editor"),this.is_dragging=!1;var g=paper.project.hitTest(e);if(g&&"undefined"!=typeof g.item.__representation)this.click_target=g.item.__representation,this.click_target.mousedown(b,c);else if(this.click_target=null,this.isEditable()&&this.click_mode===f._CLICKMODE_ADDNODE){var h=this.toModelCoords(e),i={id:f.getUID("node"),created_by:this.renkan.current_user,position:{x:h.x,y:h.y}},j=this.renkan.project.addNode(i);this.getRepresentationByModel(j).openEditor()}}this.click_mode&&(this.isEditable()&&this.click_mode===f._CLICKMODE_STARTEDGE&&this.click_target&&"Node"===this.click_target.type?(this.removeRepresentationsOfType("editor"),this.addTempEdge(this.click_target,e),this.click_mode=f._CLICKMODE_ENDEDGE,this.notif_$.fadeOut(function(){a(this).html(this.renkan.translate("Click on a second node to complete the edge")).fadeIn()})):(this.notif_$.hide(),this.click_mode=!1)),paper.view.draw()},onMouseUp:function(a,b){if(this.mouse_down=!1,this.click_target){var c=this.canvas_$.offset();this.click_target.mouseup({point:new paper.Point([a.pageX-c.left,a.pageY-c.top])},b)}else this.click_target=null,this.is_dragging=!1,b&&this.unselectAll(),this.view.updateUrl();paper.view.draw()},onScroll:function(a,b){if(this.totalScroll+=b,Math.abs(this.totalScroll)>=1){var c=this.canvas_$.offset(),d=new paper.Point([a.pageX-c.left,a.pageY-c.top]).subtract(this.view.offset).multiply(Math.SQRT2-1);this.totalScroll>0?this.view.setScale(this.view.scale*Math.SQRT2,this.view.offset.subtract(d)):this.view.setScale(this.view.scale*Math.SQRT1_2,this.view.offset.add(d.divide(Math.SQRT2))),this.totalScroll=0}},onDoubleClick:function(a){var b=this.canvas_$.offset(),c=new paper.Point([a.pageX-b.left,a.pageY-b.top]),d=paper.project.hitTest(c);if(!this.isEditable())return void(d&&"undefined"!=typeof d.item.__representation&&d.item.__representation.model.get("uri")&&window.open(d.item.__representation.model.get("uri"),"_blank"));if(this.isEditable()&&(!d||"undefined"==typeof d.item.__representation)){var e=this.toModelCoords(c),g={id:f.getUID("node"),created_by:this.renkan.current_user,position:{x:e.x,y:e.y}},h=this.renkan.project.addNode(g);this.getRepresentationByModel(h).openEditor()}paper.view.draw()},defaultDropHandler:function(b){var c={},d="";switch(b["text/x-iri-specific-site"]){case"twitter":d=a("<div>").html(b["text/x-iri-selected-html"]);var e=d.find(".tweet");c.title=this.renkan.translate("Tweet by ")+e.attr("data-name"),c.uri="http://twitter.com/"+e.attr("data-screen-name")+"/status/"+e.attr("data-tweet-id"),c.image=e.find(".avatar").attr("src"),c.description=e.find(".js-tweet-text:first").text();break;case"google":d=a("<div>").html(b["text/x-iri-selected-html"]),c.title=d.find("h3:first").text().trim(),c.uri=d.find("h3 a").attr("href"),c.description=d.find(".st:first").text().trim();break;default:b["text/x-iri-source-uri"]&&(c.uri=b["text/x-iri-source-uri"])}if((b["text/plain"]||b["text/x-iri-selected-text"])&&(c.description=(b["text/plain"]||b["text/x-iri-selected-text"]).replace(/[\s\n]+/gm," ").trim()),b["text/html"]||b["text/x-iri-selected-html"]){d=a("<div>").html(b["text/html"]||b["text/x-iri-selected-html"]);var f=d.find("image");f.length&&(c.image=f.attr("xlink:href"));var g=d.find("path");g.length&&(c.clipPath=g.attr("d"));var h=d.find("img");h.length&&(c.image=h[0].src);var i=d.find("a");i.length&&(c.uri=i[0].href),c.title=d.find("[title]").attr("title")||c.title,c.description=d.text().replace(/[\s\n]+/gm," ").trim()}b["text/uri-list"]&&(c.uri=b["text/uri-list"]),b["text/x-moz-url"]&&!c.title&&(c.title=(b["text/x-moz-url"].split("\n")[1]||"").trim(),c.title===c.uri&&(c.title=!1)),b["text/x-iri-source-title"]&&!c.title&&(c.title=b["text/x-iri-source-title"]),(b["text/html"]||b["text/x-iri-selected-html"])&&(d=a("<div>").html(b["text/html"]||b["text/x-iri-selected-html"]),c.image=d.find("[data-image]").attr("data-image")||c.image,c.uri=d.find("[data-uri]").attr("data-uri")||c.uri,c.title=d.find("[data-title]").attr("data-title")||c.title,c.description=d.find("[data-description]").attr("data-description")||c.description,c.clipPath=d.find("[data-clip-path]").attr("data-clip-path")||c.clipPath),c.title||(c.title=this.renkan.translate("Dragged resource"));for(var j=["title","description","uri","image"],k=0;k<j.length;k++){var l=j[k];(b["text/x-iri-"+l]||b[l])&&(c[l]=b["text/x-iri-"+l]||b[l]),("none"===c[l]||"null"===c[l])&&(c[l]=void 0)}return"function"==typeof this.renkan.options.drop_enhancer&&(c=this.renkan.options.drop_enhancer(c,b)),c},dropData:function(a,c){if(this.isEditable()){if(a["text/json"]||a["application/json"])try{var d=JSON.parse(a["text/json"]||a["application/json"]);b.extend(a,d)}catch(e){}var g="undefined"==typeof this.renkan.options.drop_handler?this.defaultDropHandler(a):this.renkan.options.drop_handler(a),h=this.canvas_$.offset(),i=new paper.Point([c.pageX-h.left,c.pageY-h.top]),j=this.toModelCoords(i),k={id:f.getUID("node"),created_by:this.renkan.current_user,uri:g.uri||"",title:g.title||"",description:g.description||"",image:g.image||"",color:g.color||void 0,clip_path:g.clipPath||void 0,position:{x:j.x,y:j.y}},l=this.renkan.project.addNode(k),m=this.getRepresentationByModel(l);"drop"===c.type&&m.openEditor()}},fullScreen:function(){var a,b=document.fullScreen||document.mozFullScreen||document.webkitIsFullScreen,c=this.renkan.$[0],d=["requestFullScreen","mozRequestFullScreen","webkitRequestFullScreen"],e=["cancelFullScreen","mozCancelFullScreen","webkitCancelFullScreen"];if(b){for(a=0;a<e.length;a++)if("function"==typeof document[e[a]]){document[e[a]]();break}var f=this.$.width(),g=this.$.height();this.renkan.options.show_top_bar&&(g-=this.$.find(".Rk-TopBar").height()),this.renkan.options.show_bins&&this.renkan.$.find(".Rk-Bins").position().left>0&&(f-=this.renkan.$.find(".Rk-Bins").width()),paper.view.viewSize=new paper.Size([f,g])}else{for(a=0;a<d.length;a++)if("function"==typeof c[d[a]]){c[d[a]]();break}this.redraw()}},addNodeBtn:function(){return this.click_mode===f._CLICKMODE_ADDNODE?(this.click_mode=!1,this.notif_$.hide()):(this.click_mode=f._CLICKMODE_ADDNODE,this.notif_$.text(this.renkan.translate("Click on the background canvas to add a node")).fadeIn()),!1},addEdgeBtn:function(){return this.click_mode===f._CLICKMODE_STARTEDGE||this.click_mode===f._CLICKMODE_ENDEDGE?(this.click_mode=!1,this.notif_$.hide()):(this.click_mode=f._CLICKMODE_STARTEDGE,this.notif_$.text(this.renkan.translate("Click on a first node to start the edge")).fadeIn()),!1},exportProject:function(){var a=this.renkan.project.toJSON(),d=(document.createElement("a"),a.id),e=d+".json";delete a.id,delete a._id,delete a.space_id;var g,h,i={};b.each(a.nodes,function(a,b,c){g=a.id||a._id,delete a._id,delete a.id,i[g]=a["@id"]=f.getUUID4()}),b.each(a.edges,function(a,b,c){delete a._id,delete a.id,a.to=i[a.to],a.from=i[a.from]}),b.each(a.views,function(a,c,d){delete a._id,delete a.id,a.hidden_nodes&&(h=a.hidden_nodes,a.hidden_nodes=[],b.each(h,function(b,c){a.hidden_nodes.push(i[b])}))}),a.users=[];var j=JSON.stringify(a,null,2),k=new Blob([j],{type:"application/json;charset=utf-8"});c(k,e)},parameters:function(b){if(this.removeRepresentationsOfType("View"),a.isEmptyObject(b))return this.view=this.addRepresentation("View",this.renkan.project.get("views").at(this.validViewIndex(this.renkan.options.default_index_view))),void(this.renkan.options.default_view||this.view.autoScale());if("undefined"!=typeof b.viewIndex&&(this.view=this.addRepresentation("View",this.renkan.project.get("views").at(this.validViewIndex(b.viewIndex))),this.renkan.options.default_view||this.view.autoScale()),"undefined"!=typeof b.view&&b.view.split(",").length>=3){var c=b.view.split(","),d={project:this.renkan.project,offset:{x:parseFloat(c[0]),y:parseFloat(c[1])},zoom_level:parseFloat(c[2])};this.view?this.view.setScale(d.zoom_level,new paper.Point(d.offset)):(this.view=this.addRepresentation("View",null),this.view.params=d,this.view.init())}this.view||(this.view=this.addRepresentation("View",this.renkan.project.get("views").at(this.validViewIndex(this.renkan.options.default_index_view))),this.view.autoScale()),this.unhighlightAll(),"undefined"!=typeof b.idNode&&this.highlightModel(this.renkan.project.get("nodes").get(b.idNode))},validViewIndex:function(a){var b=parseInt(a),c=0;return c=0>b?this.renkan.project.get("views").length+b:b,"undefined"==typeof this.renkan.project.get("views").at(b)&&(c=0),c},foldBins:function(){var a,b=this.$.find(".Rk-Fold-Bins"),c=this.renkan.$.find(".Rk-Bins"),d=this,e=d.canvas_$.width();c.position().left<0?(c.animate({left:0},250),this.$.animate({left:300},250,function(){var a=d.$.width();paper.view.viewSize=new paper.Size([a,d.canvas_$.height()])}),a=e-c.width()<c.height()?e:e-c.width(),b.html("«")):(c.animate({left:-300},250),this.$.animate({left:0},250,function(){var a=d.$.width();paper.view.viewSize=new paper.Size([a,d.canvas_$.height()])}),a=e+300,b.html("»")),d.view.resizeZoom(1,1,a/e)},save:function(){},open:function(){}}).value(),g}),define("renderer/viewrepr",["jquery","underscore","requtils","renderer/baserepresentation"],function(a,b,c,d){"use strict";var e=c.getUtils(),f=e.inherit(d);return b(f.prototype).extend({_init:function(){var b=this;this.$=a(".Rk-Render"),this.type="View",this.hiddenNodes=[],this.scale=1,this.initialScale=1,this.offset=paper.view.center,this.params={},this.model&&(this.params={zoom_level:b.model.get("zoom_level"),offset:b.model.get("offset"),hidden_nodes:b.model.get("hidden_nodes")}),this.init();var c=function(a,c){b.$.find(a).click(function(a){return b[c](a),!1})};c(".Rk-ZoomOut","zoomOut"),c(".Rk-ZoomIn","zoomIn"),c(".Rk-ZoomFit","autoScale"),this.$.find(".Rk-ZoomSave").click(function(){var a={x:b.offset.x,y:b.offset.y};b.model=b.renkan.project.addView({zoom_level:b.scale,offset:a,hidden_nodes:b.hiddenNodes.concat()}),b.params={zoom_level:b.model.get("zoom_level"),offset:b.model.get("offset"),hidden_nodes:b.model.get("hidden_nodes")},b.updateUrl()}),this.$.find(".Rk-ZoomSetSaved").click(function(){b.model=b.renkan.project.get("views").at(b.renkan.project.get("views").length-1),b.params={zoom_level:b.model.get("zoom_level"),offset:b.model.get("offset"),hidden_nodes:b.model.get("hidden_nodes")},b.setScale(b.params.zoom_level,new paper.Point(b.params.offset)),b.showNodes(!1),b.options.hide_nodes&&(b.hiddenNodes=(b.params.hidden_nodes||[]).concat(),b.hideNodes()),b.updateUrl()}),this.$.find(".Rk-ShowHiddenNodes").mouseenter(function(){b.showNodes(!0),b.$.find(".Rk-ShowHiddenNodes").mouseleave(function(){b.hideNodes()})}),this.$.find(".Rk-ShowHiddenNodes").click(function(){b.showNodes(!1),b.$.find(".Rk-ShowHiddenNodes").off("mouseleave")}),this.renkan.project.get("views").length>0&&this.renkan.options.save_view&&this.$.find(".Rk-ZoomSetSaved").show()},redraw:function(a){},init:function(){var a=this;a.setScale(a.params.zoom_level,new paper.Point(a.params.offset)),a.options.hide_nodes&&(a.hiddenNodes=(a.params.hidden_nodes||[]).concat(),a.hideNodes())},addHiddenNode:function(a){this.hideNode(a),this.hiddenNodes.push(a.id),this.updateUrl()},hideNode:function(a){"undefined"!=typeof this.renderer.getRepresentationByModel(a)&&this.renderer.getRepresentationByModel(a).hide()},hideNodes:function(){var a=this;this.hiddenNodes.forEach(function(b,c){var d=a.renkan.project.get("nodes").get(b);return"undefined"!=typeof d?a.hideNode(a.renkan.project.get("nodes").get(b)):void a.hiddenNodes.splice(c,1)}),paper.view.draw()},showNodes:function(a){var b=this;this.hiddenNodes.forEach(function(c){b.renderer.getRepresentationByModel(b.renkan.project.get("nodes").get(c)).show(a)}),a||(this.hiddenNodes=[]),paper.view.draw()},setScale:function(a,b){a/this.initialScale>e._MIN_SCALE&&a/this.initialScale<e._MAX_SCALE&&(this.scale=a,b&&(this.offset=b),this.renderer.redraw(),this.updateUrl())},zoomOut:function(){var a=this.scale*Math.SQRT1_2,b=new paper.Point([this.renderer.canvas_$.width(),this.renderer.canvas_$.height()]).multiply(.5*(1-Math.SQRT1_2)).add(this.offset.multiply(Math.SQRT1_2));this.setScale(a,b)},zoomIn:function(){var a=this.scale*Math.SQRT2,b=new paper.Point([this.renderer.canvas_$.width(),this.renderer.canvas_$.height()]).multiply(.5*(1-Math.SQRT2)).add(this.offset.multiply(Math.SQRT2));this.setScale(a,b)},resizeZoom:function(a,b,c){var d=this.scale*c,e=new paper.Point([this.offset.x*a,this.offset.y*b]);this.setScale(d,e)},autoScale:function(a){var b=this.renkan.project.get("nodes");if(b.length>1){var c=b.map(function(a){return a.get("position").x}),d=b.map(function(a){return a.get("position").y}),e=Math.min.apply(Math,c),f=Math.min.apply(Math,d),g=Math.max.apply(Math,c),h=Math.max.apply(Math,d),i=Math.min((paper.view.size.width-2*this.renkan.options.autoscale_padding)/(g-e),(paper.view.size.height-2*this.renkan.options.autoscale_padding)/(h-f));this.initialScale=i,"undefined"!=typeof a&&parseFloat(a.zoom_level)>0&&parseFloat(a.offset.x)>0&&parseFloat(a.offset.y)>0?this.setScale(parseFloat(a.zoom_level),new paper.Point(parseFloat(a.offset.x),parseFloat(a.offset.y))):this.setScale(i,paper.view.center.subtract(new paper.Point([(g+e)/2,(h+f)/2]).multiply(i)))}1===b.length&&this.setScale(1,paper.view.center.subtract(new paper.Point([b.at(0).get("position").x,b.at(0).get("position").y])))},paperShift:function(a){this.offset=this.offset.add(a),this.renderer.redraw()},updateUrl:function(){if(this.options.update_url){var b={},c=Backbone.history.getFragment().split("?");c.length>1&&c[1].split("&").forEach(function(a){var c=a.split("=");b[c[0]]=decodeURIComponent(c[1])}),b.view=Math.round(1e3*this.offset.x)/1e3+","+Math.round(1e3*this.offset.y)/1e3+","+Math.round(1e3*this.scale)/1e3,this.renkan.project.get("views").indexOf(this.model)>-1?(b.viewIndex=this.renkan.project.get("views").indexOf(this.model),b.viewIndex===this.renkan.project.get("views").length-1&&(b.viewIndex=-1)):b.viewIndex&&delete b.viewIndex,this.renkan.router.navigate("?"+decodeURIComponent(a.param(b)),{trigger:!1,replace:!0})}},destroy:function(a){this._super("destroy"),this.showNodes(!1)}}).value(),f}),"function"==typeof require.config&&require.config({paths:{jquery:"../lib/jquery/jquery",underscore:"../lib/lodash/lodash",filesaver:"../lib/FileSaver/FileSaver",requtils:"require-utils","ckeditor-core":"../lib/ckeditor/ckeditor","ckeditor-jquery":"../lib/ckeditor/adapters/jquery"},shim:{"ckeditor-jquery":{deps:["jquery","ckeditor-core"]}}}),require(["renderer/baserepresentation","renderer/basebutton","renderer/noderepr","renderer/edge","renderer/tempedge","renderer/baseeditor","renderer/nodeeditor","renderer/edgeeditor","renderer/nodebutton","renderer/nodeeditbutton","renderer/noderemovebutton","renderer/nodehidebutton","renderer/nodeshowbutton","renderer/noderevertbutton","renderer/nodelinkbutton","renderer/nodeenlargebutton","renderer/nodeshrinkbutton","renderer/edgeeditbutton","renderer/edgeremovebutton","renderer/edgerevertbutton","renderer/miniframe","renderer/scene","renderer/viewrepr"],function(a,b,c,d,e,f,g,h,i,j,k,l,m,n,o,p,q,r,s,t,u,v,w){"use strict";var x=window.Rkns;"undefined"==typeof x.Renderer&&(x.Renderer={});var y=x.Renderer;y._BaseRepresentation=a,y._BaseButton=b,y.Node=c,y.Edge=d,y.View=w,y.TempEdge=e,y._BaseEditor=f,y.NodeEditor=g,y.EdgeEditor=h,y._NodeButton=i,y.NodeEditButton=j,y.NodeRemoveButton=k,y.NodeHideButton=l,y.NodeShowButton=m,y.NodeRevertButton=n,y.NodeLinkButton=o,y.NodeEnlargeButton=p,y.NodeShrinkButton=q,y.EdgeEditButton=r,y.EdgeRemoveButton=s,y.EdgeRevertButton=t,y.MiniFrame=u,y.Scene=v,startRenkan()}),define("main-renderer",function(){});
+//# sourceMappingURL=renkan.min.map
\ No newline at end of file
--- a/src/ldt/ldt/static/ldt/js/tracemanager.js Fri Sep 18 16:10:29 2015 +0200
+++ b/src/ldt/ldt/static/ldt/js/tracemanager.js Fri Oct 02 10:24:05 2015 +0200
@@ -21,12 +21,19 @@
window.tracemanager = (function($) {
// If there are more than MAX_FAILURE_COUNT synchronisation
// failures, then disable synchronisation
- MAX_FAILURE_COUNT = 20;
+ var MAX_FAILURE_COUNT = 20;
// If there are more than MAX_BUFFER_SIZE obsels in the buffer,
// then "compress" them as a single "ktbsFullBuffer"
- MAX_BUFFER_SIZE = 500;
+ var MAX_BUFFER_SIZE = 500;
+ var _replacement = {
+ ';': '"',
+ '"': ';',
+ '#': '%23',
+ '&': '%26',
+ '?': '%3F'
+ };
var BufferedService_prototype = {
/*
* Buffered service for traces
@@ -60,7 +67,7 @@
// Swap " (very frequent, which will be
// serialized into %22) and ; (rather rare), this
// saves some bytes
- data = data.replace(/[;"#]/g, function(s){ return s == ';' ? '"' : ( s == '"' ? ';' : '%23'); });
+ data = data.replace(/[;"#?&]/g, function(s){ return _replacement[s]; });
// FIXME: check data length (< 2K is safe)
var request=$('<img />').error( function() { this.failureCount += 1; })
.load( function() { this.failureCount = 0; })
--- a/src/ldt/ldt/static/ldt/js/underscore-min.js Fri Sep 18 16:10:29 2015 +0200
+++ b/src/ldt/ldt/static/ldt/js/underscore-min.js Fri Oct 02 10:24:05 2015 +0200
@@ -1,1 +1,6 @@
-(function(){var n=this,t=n._,r={},e=Array.prototype,u=Object.prototype,i=Function.prototype,a=e.push,o=e.slice,c=e.concat,l=u.toString,f=u.hasOwnProperty,s=e.forEach,p=e.map,h=e.reduce,v=e.reduceRight,d=e.filter,g=e.every,m=e.some,y=e.indexOf,b=e.lastIndexOf,x=Array.isArray,_=Object.keys,j=i.bind,w=function(n){return n instanceof w?n:this instanceof w?(this._wrapped=n,void 0):new w(n)};"undefined"!=typeof exports?("undefined"!=typeof module&&module.exports&&(exports=module.exports=w),exports._=w):n._=w,w.VERSION="1.4.4";var A=w.each=w.forEach=function(n,t,e){if(null!=n)if(s&&n.forEach===s)n.forEach(t,e);else if(n.length===+n.length){for(var u=0,i=n.length;i>u;u++)if(t.call(e,n[u],u,n)===r)return}else for(var a in n)if(w.has(n,a)&&t.call(e,n[a],a,n)===r)return};w.map=w.collect=function(n,t,r){var e=[];return null==n?e:p&&n.map===p?n.map(t,r):(A(n,function(n,u,i){e[e.length]=t.call(r,n,u,i)}),e)};var O="Reduce of empty array with no initial value";w.reduce=w.foldl=w.inject=function(n,t,r,e){var u=arguments.length>2;if(null==n&&(n=[]),h&&n.reduce===h)return e&&(t=w.bind(t,e)),u?n.reduce(t,r):n.reduce(t);if(A(n,function(n,i,a){u?r=t.call(e,r,n,i,a):(r=n,u=!0)}),!u)throw new TypeError(O);return r},w.reduceRight=w.foldr=function(n,t,r,e){var u=arguments.length>2;if(null==n&&(n=[]),v&&n.reduceRight===v)return e&&(t=w.bind(t,e)),u?n.reduceRight(t,r):n.reduceRight(t);var i=n.length;if(i!==+i){var a=w.keys(n);i=a.length}if(A(n,function(o,c,l){c=a?a[--i]:--i,u?r=t.call(e,r,n[c],c,l):(r=n[c],u=!0)}),!u)throw new TypeError(O);return r},w.find=w.detect=function(n,t,r){var e;return E(n,function(n,u,i){return t.call(r,n,u,i)?(e=n,!0):void 0}),e},w.filter=w.select=function(n,t,r){var e=[];return null==n?e:d&&n.filter===d?n.filter(t,r):(A(n,function(n,u,i){t.call(r,n,u,i)&&(e[e.length]=n)}),e)},w.reject=function(n,t,r){return w.filter(n,function(n,e,u){return!t.call(r,n,e,u)},r)},w.every=w.all=function(n,t,e){t||(t=w.identity);var u=!0;return null==n?u:g&&n.every===g?n.every(t,e):(A(n,function(n,i,a){return(u=u&&t.call(e,n,i,a))?void 0:r}),!!u)};var E=w.some=w.any=function(n,t,e){t||(t=w.identity);var u=!1;return null==n?u:m&&n.some===m?n.some(t,e):(A(n,function(n,i,a){return u||(u=t.call(e,n,i,a))?r:void 0}),!!u)};w.contains=w.include=function(n,t){return null==n?!1:y&&n.indexOf===y?n.indexOf(t)!=-1:E(n,function(n){return n===t})},w.invoke=function(n,t){var r=o.call(arguments,2),e=w.isFunction(t);return w.map(n,function(n){return(e?t:n[t]).apply(n,r)})},w.pluck=function(n,t){return w.map(n,function(n){return n[t]})},w.where=function(n,t,r){return w.isEmpty(t)?r?null:[]:w[r?"find":"filter"](n,function(n){for(var r in t)if(t[r]!==n[r])return!1;return!0})},w.findWhere=function(n,t){return w.where(n,t,!0)},w.max=function(n,t,r){if(!t&&w.isArray(n)&&n[0]===+n[0]&&65535>n.length)return Math.max.apply(Math,n);if(!t&&w.isEmpty(n))return-1/0;var e={computed:-1/0,value:-1/0};return A(n,function(n,u,i){var a=t?t.call(r,n,u,i):n;a>=e.computed&&(e={value:n,computed:a})}),e.value},w.min=function(n,t,r){if(!t&&w.isArray(n)&&n[0]===+n[0]&&65535>n.length)return Math.min.apply(Math,n);if(!t&&w.isEmpty(n))return 1/0;var e={computed:1/0,value:1/0};return A(n,function(n,u,i){var a=t?t.call(r,n,u,i):n;e.computed>a&&(e={value:n,computed:a})}),e.value},w.shuffle=function(n){var t,r=0,e=[];return A(n,function(n){t=w.random(r++),e[r-1]=e[t],e[t]=n}),e};var k=function(n){return w.isFunction(n)?n:function(t){return t[n]}};w.sortBy=function(n,t,r){var e=k(t);return w.pluck(w.map(n,function(n,t,u){return{value:n,index:t,criteria:e.call(r,n,t,u)}}).sort(function(n,t){var r=n.criteria,e=t.criteria;if(r!==e){if(r>e||r===void 0)return 1;if(e>r||e===void 0)return-1}return n.index<t.index?-1:1}),"value")};var F=function(n,t,r,e){var u={},i=k(t||w.identity);return A(n,function(t,a){var o=i.call(r,t,a,n);e(u,o,t)}),u};w.groupBy=function(n,t,r){return F(n,t,r,function(n,t,r){(w.has(n,t)?n[t]:n[t]=[]).push(r)})},w.countBy=function(n,t,r){return F(n,t,r,function(n,t){w.has(n,t)||(n[t]=0),n[t]++})},w.sortedIndex=function(n,t,r,e){r=null==r?w.identity:k(r);for(var u=r.call(e,t),i=0,a=n.length;a>i;){var o=i+a>>>1;u>r.call(e,n[o])?i=o+1:a=o}return i},w.toArray=function(n){return n?w.isArray(n)?o.call(n):n.length===+n.length?w.map(n,w.identity):w.values(n):[]},w.size=function(n){return null==n?0:n.length===+n.length?n.length:w.keys(n).length},w.first=w.head=w.take=function(n,t,r){return null==n?void 0:null==t||r?n[0]:o.call(n,0,t)},w.initial=function(n,t,r){return o.call(n,0,n.length-(null==t||r?1:t))},w.last=function(n,t,r){return null==n?void 0:null==t||r?n[n.length-1]:o.call(n,Math.max(n.length-t,0))},w.rest=w.tail=w.drop=function(n,t,r){return o.call(n,null==t||r?1:t)},w.compact=function(n){return w.filter(n,w.identity)};var R=function(n,t,r){return A(n,function(n){w.isArray(n)?t?a.apply(r,n):R(n,t,r):r.push(n)}),r};w.flatten=function(n,t){return R(n,t,[])},w.without=function(n){return w.difference(n,o.call(arguments,1))},w.uniq=w.unique=function(n,t,r,e){w.isFunction(t)&&(e=r,r=t,t=!1);var u=r?w.map(n,r,e):n,i=[],a=[];return A(u,function(r,e){(t?e&&a[a.length-1]===r:w.contains(a,r))||(a.push(r),i.push(n[e]))}),i},w.union=function(){return w.uniq(c.apply(e,arguments))},w.intersection=function(n){var t=o.call(arguments,1);return w.filter(w.uniq(n),function(n){return w.every(t,function(t){return w.indexOf(t,n)>=0})})},w.difference=function(n){var t=c.apply(e,o.call(arguments,1));return w.filter(n,function(n){return!w.contains(t,n)})},w.zip=function(){for(var n=o.call(arguments),t=w.max(w.pluck(n,"length")),r=Array(t),e=0;t>e;e++)r[e]=w.pluck(n,""+e);return r},w.object=function(n,t){if(null==n)return{};for(var r={},e=0,u=n.length;u>e;e++)t?r[n[e]]=t[e]:r[n[e][0]]=n[e][1];return r},w.indexOf=function(n,t,r){if(null==n)return-1;var e=0,u=n.length;if(r){if("number"!=typeof r)return e=w.sortedIndex(n,t),n[e]===t?e:-1;e=0>r?Math.max(0,u+r):r}if(y&&n.indexOf===y)return n.indexOf(t,r);for(;u>e;e++)if(n[e]===t)return e;return-1},w.lastIndexOf=function(n,t,r){if(null==n)return-1;var e=null!=r;if(b&&n.lastIndexOf===b)return e?n.lastIndexOf(t,r):n.lastIndexOf(t);for(var u=e?r:n.length;u--;)if(n[u]===t)return u;return-1},w.range=function(n,t,r){1>=arguments.length&&(t=n||0,n=0),r=arguments[2]||1;for(var e=Math.max(Math.ceil((t-n)/r),0),u=0,i=Array(e);e>u;)i[u++]=n,n+=r;return i},w.bind=function(n,t){if(n.bind===j&&j)return j.apply(n,o.call(arguments,1));var r=o.call(arguments,2);return function(){return n.apply(t,r.concat(o.call(arguments)))}},w.partial=function(n){var t=o.call(arguments,1);return function(){return n.apply(this,t.concat(o.call(arguments)))}},w.bindAll=function(n){var t=o.call(arguments,1);return 0===t.length&&(t=w.functions(n)),A(t,function(t){n[t]=w.bind(n[t],n)}),n},w.memoize=function(n,t){var r={};return t||(t=w.identity),function(){var e=t.apply(this,arguments);return w.has(r,e)?r[e]:r[e]=n.apply(this,arguments)}},w.delay=function(n,t){var r=o.call(arguments,2);return setTimeout(function(){return n.apply(null,r)},t)},w.defer=function(n){return w.delay.apply(w,[n,1].concat(o.call(arguments,1)))},w.throttle=function(n,t){var r,e,u,i,a=0,o=function(){a=new Date,u=null,i=n.apply(r,e)};return function(){var c=new Date,l=t-(c-a);return r=this,e=arguments,0>=l?(clearTimeout(u),u=null,a=c,i=n.apply(r,e)):u||(u=setTimeout(o,l)),i}},w.debounce=function(n,t,r){var e,u;return function(){var i=this,a=arguments,o=function(){e=null,r||(u=n.apply(i,a))},c=r&&!e;return clearTimeout(e),e=setTimeout(o,t),c&&(u=n.apply(i,a)),u}},w.once=function(n){var t,r=!1;return function(){return r?t:(r=!0,t=n.apply(this,arguments),n=null,t)}},w.wrap=function(n,t){return function(){var r=[n];return a.apply(r,arguments),t.apply(this,r)}},w.compose=function(){var n=arguments;return function(){for(var t=arguments,r=n.length-1;r>=0;r--)t=[n[r].apply(this,t)];return t[0]}},w.after=function(n,t){return 0>=n?t():function(){return 1>--n?t.apply(this,arguments):void 0}},w.keys=_||function(n){if(n!==Object(n))throw new TypeError("Invalid object");var t=[];for(var r in n)w.has(n,r)&&(t[t.length]=r);return t},w.values=function(n){var t=[];for(var r in n)w.has(n,r)&&t.push(n[r]);return t},w.pairs=function(n){var t=[];for(var r in n)w.has(n,r)&&t.push([r,n[r]]);return t},w.invert=function(n){var t={};for(var r in n)w.has(n,r)&&(t[n[r]]=r);return t},w.functions=w.methods=function(n){var t=[];for(var r in n)w.isFunction(n[r])&&t.push(r);return t.sort()},w.extend=function(n){return A(o.call(arguments,1),function(t){if(t)for(var r in t)n[r]=t[r]}),n},w.pick=function(n){var t={},r=c.apply(e,o.call(arguments,1));return A(r,function(r){r in n&&(t[r]=n[r])}),t},w.omit=function(n){var t={},r=c.apply(e,o.call(arguments,1));for(var u in n)w.contains(r,u)||(t[u]=n[u]);return t},w.defaults=function(n){return A(o.call(arguments,1),function(t){if(t)for(var r in t)null==n[r]&&(n[r]=t[r])}),n},w.clone=function(n){return w.isObject(n)?w.isArray(n)?n.slice():w.extend({},n):n},w.tap=function(n,t){return t(n),n};var I=function(n,t,r,e){if(n===t)return 0!==n||1/n==1/t;if(null==n||null==t)return n===t;n instanceof w&&(n=n._wrapped),t instanceof w&&(t=t._wrapped);var u=l.call(n);if(u!=l.call(t))return!1;switch(u){case"[object String]":return n==t+"";case"[object Number]":return n!=+n?t!=+t:0==n?1/n==1/t:n==+t;case"[object Date]":case"[object Boolean]":return+n==+t;case"[object RegExp]":return n.source==t.source&&n.global==t.global&&n.multiline==t.multiline&&n.ignoreCase==t.ignoreCase}if("object"!=typeof n||"object"!=typeof t)return!1;for(var i=r.length;i--;)if(r[i]==n)return e[i]==t;r.push(n),e.push(t);var a=0,o=!0;if("[object Array]"==u){if(a=n.length,o=a==t.length)for(;a--&&(o=I(n[a],t[a],r,e)););}else{var c=n.constructor,f=t.constructor;if(c!==f&&!(w.isFunction(c)&&c instanceof c&&w.isFunction(f)&&f instanceof f))return!1;for(var s in n)if(w.has(n,s)&&(a++,!(o=w.has(t,s)&&I(n[s],t[s],r,e))))break;if(o){for(s in t)if(w.has(t,s)&&!a--)break;o=!a}}return r.pop(),e.pop(),o};w.isEqual=function(n,t){return I(n,t,[],[])},w.isEmpty=function(n){if(null==n)return!0;if(w.isArray(n)||w.isString(n))return 0===n.length;for(var t in n)if(w.has(n,t))return!1;return!0},w.isElement=function(n){return!(!n||1!==n.nodeType)},w.isArray=x||function(n){return"[object Array]"==l.call(n)},w.isObject=function(n){return n===Object(n)},A(["Arguments","Function","String","Number","Date","RegExp"],function(n){w["is"+n]=function(t){return l.call(t)=="[object "+n+"]"}}),w.isArguments(arguments)||(w.isArguments=function(n){return!(!n||!w.has(n,"callee"))}),"function"!=typeof/./&&(w.isFunction=function(n){return"function"==typeof n}),w.isFinite=function(n){return isFinite(n)&&!isNaN(parseFloat(n))},w.isNaN=function(n){return w.isNumber(n)&&n!=+n},w.isBoolean=function(n){return n===!0||n===!1||"[object Boolean]"==l.call(n)},w.isNull=function(n){return null===n},w.isUndefined=function(n){return n===void 0},w.has=function(n,t){return f.call(n,t)},w.noConflict=function(){return n._=t,this},w.identity=function(n){return n},w.times=function(n,t,r){for(var e=Array(n),u=0;n>u;u++)e[u]=t.call(r,u);return e},w.random=function(n,t){return null==t&&(t=n,n=0),n+Math.floor(Math.random()*(t-n+1))};var M={escape:{"&":"&","<":"<",">":">",'"':""","'":"'","/":"/"}};M.unescape=w.invert(M.escape);var S={escape:RegExp("["+w.keys(M.escape).join("")+"]","g"),unescape:RegExp("("+w.keys(M.unescape).join("|")+")","g")};w.each(["escape","unescape"],function(n){w[n]=function(t){return null==t?"":(""+t).replace(S[n],function(t){return M[n][t]})}}),w.result=function(n,t){if(null==n)return null;var r=n[t];return w.isFunction(r)?r.call(n):r},w.mixin=function(n){A(w.functions(n),function(t){var r=w[t]=n[t];w.prototype[t]=function(){var n=[this._wrapped];return a.apply(n,arguments),D.call(this,r.apply(w,n))}})};var N=0;w.uniqueId=function(n){var t=++N+"";return n?n+t:t},w.templateSettings={evaluate:/<%([\s\S]+?)%>/g,interpolate:/<%=([\s\S]+?)%>/g,escape:/<%-([\s\S]+?)%>/g};var T=/(.)^/,q={"'":"'","\\":"\\","\r":"r","\n":"n"," ":"t","\u2028":"u2028","\u2029":"u2029"},B=/\\|'|\r|\n|\t|\u2028|\u2029/g;w.template=function(n,t,r){var e;r=w.defaults({},r,w.templateSettings);var u=RegExp([(r.escape||T).source,(r.interpolate||T).source,(r.evaluate||T).source].join("|")+"|$","g"),i=0,a="__p+='";n.replace(u,function(t,r,e,u,o){return a+=n.slice(i,o).replace(B,function(n){return"\\"+q[n]}),r&&(a+="'+\n((__t=("+r+"))==null?'':_.escape(__t))+\n'"),e&&(a+="'+\n((__t=("+e+"))==null?'':__t)+\n'"),u&&(a+="';\n"+u+"\n__p+='"),i=o+t.length,t}),a+="';\n",r.variable||(a="with(obj||{}){\n"+a+"}\n"),a="var __t,__p='',__j=Array.prototype.join,"+"print=function(){__p+=__j.call(arguments,'');};\n"+a+"return __p;\n";try{e=Function(r.variable||"obj","_",a)}catch(o){throw o.source=a,o}if(t)return e(t,w);var c=function(n){return e.call(this,n,w)};return c.source="function("+(r.variable||"obj")+"){\n"+a+"}",c},w.chain=function(n){return w(n).chain()};var D=function(n){return this._chain?w(n).chain():n};w.mixin(w),A(["pop","push","reverse","shift","sort","splice","unshift"],function(n){var t=e[n];w.prototype[n]=function(){var r=this._wrapped;return t.apply(r,arguments),"shift"!=n&&"splice"!=n||0!==r.length||delete r[0],D.call(this,r)}}),A(["concat","join","slice"],function(n){var t=e[n];w.prototype[n]=function(){return D.call(this,t.apply(this._wrapped,arguments))}}),w.extend(w.prototype,{chain:function(){return this._chain=!0,this},value:function(){return this._wrapped}})}).call(this);
\ No newline at end of file
+// Underscore.js 1.8.3
+// http://underscorejs.org
+// (c) 2009-2015 Jeremy Ashkenas, DocumentCloud and Investigative Reporters & Editors
+// Underscore may be freely distributed under the MIT license.
+(function(){function n(n){function t(t,r,e,u,i,o){for(;i>=0&&o>i;i+=n){var a=u?u[i]:i;e=r(e,t[a],a,t)}return e}return function(r,e,u,i){e=b(e,i,4);var o=!k(r)&&m.keys(r),a=(o||r).length,c=n>0?0:a-1;return arguments.length<3&&(u=r[o?o[c]:c],c+=n),t(r,e,u,o,c,a)}}function t(n){return function(t,r,e){r=x(r,e);for(var u=O(t),i=n>0?0:u-1;i>=0&&u>i;i+=n)if(r(t[i],i,t))return i;return-1}}function r(n,t,r){return function(e,u,i){var o=0,a=O(e);if("number"==typeof i)n>0?o=i>=0?i:Math.max(i+a,o):a=i>=0?Math.min(i+1,a):i+a+1;else if(r&&i&&a)return i=r(e,u),e[i]===u?i:-1;if(u!==u)return i=t(l.call(e,o,a),m.isNaN),i>=0?i+o:-1;for(i=n>0?o:a-1;i>=0&&a>i;i+=n)if(e[i]===u)return i;return-1}}function e(n,t){var r=I.length,e=n.constructor,u=m.isFunction(e)&&e.prototype||a,i="constructor";for(m.has(n,i)&&!m.contains(t,i)&&t.push(i);r--;)i=I[r],i in n&&n[i]!==u[i]&&!m.contains(t,i)&&t.push(i)}var u=this,i=u._,o=Array.prototype,a=Object.prototype,c=Function.prototype,f=o.push,l=o.slice,s=a.toString,p=a.hasOwnProperty,h=Array.isArray,v=Object.keys,g=c.bind,y=Object.create,d=function(){},m=function(n){return n instanceof m?n:this instanceof m?void(this._wrapped=n):new m(n)};"undefined"!=typeof exports?("undefined"!=typeof module&&module.exports&&(exports=module.exports=m),exports._=m):u._=m,m.VERSION="1.8.3";var b=function(n,t,r){if(t===void 0)return n;switch(null==r?3:r){case 1:return function(r){return n.call(t,r)};case 2:return function(r,e){return n.call(t,r,e)};case 3:return function(r,e,u){return n.call(t,r,e,u)};case 4:return function(r,e,u,i){return n.call(t,r,e,u,i)}}return function(){return n.apply(t,arguments)}},x=function(n,t,r){return null==n?m.identity:m.isFunction(n)?b(n,t,r):m.isObject(n)?m.matcher(n):m.property(n)};m.iteratee=function(n,t){return x(n,t,1/0)};var _=function(n,t){return function(r){var e=arguments.length;if(2>e||null==r)return r;for(var u=1;e>u;u++)for(var i=arguments[u],o=n(i),a=o.length,c=0;a>c;c++){var f=o[c];t&&r[f]!==void 0||(r[f]=i[f])}return r}},j=function(n){if(!m.isObject(n))return{};if(y)return y(n);d.prototype=n;var t=new d;return d.prototype=null,t},w=function(n){return function(t){return null==t?void 0:t[n]}},A=Math.pow(2,53)-1,O=w("length"),k=function(n){var t=O(n);return"number"==typeof t&&t>=0&&A>=t};m.each=m.forEach=function(n,t,r){t=b(t,r);var e,u;if(k(n))for(e=0,u=n.length;u>e;e++)t(n[e],e,n);else{var i=m.keys(n);for(e=0,u=i.length;u>e;e++)t(n[i[e]],i[e],n)}return n},m.map=m.collect=function(n,t,r){t=x(t,r);for(var e=!k(n)&&m.keys(n),u=(e||n).length,i=Array(u),o=0;u>o;o++){var a=e?e[o]:o;i[o]=t(n[a],a,n)}return i},m.reduce=m.foldl=m.inject=n(1),m.reduceRight=m.foldr=n(-1),m.find=m.detect=function(n,t,r){var e;return e=k(n)?m.findIndex(n,t,r):m.findKey(n,t,r),e!==void 0&&e!==-1?n[e]:void 0},m.filter=m.select=function(n,t,r){var e=[];return t=x(t,r),m.each(n,function(n,r,u){t(n,r,u)&&e.push(n)}),e},m.reject=function(n,t,r){return m.filter(n,m.negate(x(t)),r)},m.every=m.all=function(n,t,r){t=x(t,r);for(var e=!k(n)&&m.keys(n),u=(e||n).length,i=0;u>i;i++){var o=e?e[i]:i;if(!t(n[o],o,n))return!1}return!0},m.some=m.any=function(n,t,r){t=x(t,r);for(var e=!k(n)&&m.keys(n),u=(e||n).length,i=0;u>i;i++){var o=e?e[i]:i;if(t(n[o],o,n))return!0}return!1},m.contains=m.includes=m.include=function(n,t,r,e){return k(n)||(n=m.values(n)),("number"!=typeof r||e)&&(r=0),m.indexOf(n,t,r)>=0},m.invoke=function(n,t){var r=l.call(arguments,2),e=m.isFunction(t);return m.map(n,function(n){var u=e?t:n[t];return null==u?u:u.apply(n,r)})},m.pluck=function(n,t){return m.map(n,m.property(t))},m.where=function(n,t){return m.filter(n,m.matcher(t))},m.findWhere=function(n,t){return m.find(n,m.matcher(t))},m.max=function(n,t,r){var e,u,i=-1/0,o=-1/0;if(null==t&&null!=n){n=k(n)?n:m.values(n);for(var a=0,c=n.length;c>a;a++)e=n[a],e>i&&(i=e)}else t=x(t,r),m.each(n,function(n,r,e){u=t(n,r,e),(u>o||u===-1/0&&i===-1/0)&&(i=n,o=u)});return i},m.min=function(n,t,r){var e,u,i=1/0,o=1/0;if(null==t&&null!=n){n=k(n)?n:m.values(n);for(var a=0,c=n.length;c>a;a++)e=n[a],i>e&&(i=e)}else t=x(t,r),m.each(n,function(n,r,e){u=t(n,r,e),(o>u||1/0===u&&1/0===i)&&(i=n,o=u)});return i},m.shuffle=function(n){for(var t,r=k(n)?n:m.values(n),e=r.length,u=Array(e),i=0;e>i;i++)t=m.random(0,i),t!==i&&(u[i]=u[t]),u[t]=r[i];return u},m.sample=function(n,t,r){return null==t||r?(k(n)||(n=m.values(n)),n[m.random(n.length-1)]):m.shuffle(n).slice(0,Math.max(0,t))},m.sortBy=function(n,t,r){return t=x(t,r),m.pluck(m.map(n,function(n,r,e){return{value:n,index:r,criteria:t(n,r,e)}}).sort(function(n,t){var r=n.criteria,e=t.criteria;if(r!==e){if(r>e||r===void 0)return 1;if(e>r||e===void 0)return-1}return n.index-t.index}),"value")};var F=function(n){return function(t,r,e){var u={};return r=x(r,e),m.each(t,function(e,i){var o=r(e,i,t);n(u,e,o)}),u}};m.groupBy=F(function(n,t,r){m.has(n,r)?n[r].push(t):n[r]=[t]}),m.indexBy=F(function(n,t,r){n[r]=t}),m.countBy=F(function(n,t,r){m.has(n,r)?n[r]++:n[r]=1}),m.toArray=function(n){return n?m.isArray(n)?l.call(n):k(n)?m.map(n,m.identity):m.values(n):[]},m.size=function(n){return null==n?0:k(n)?n.length:m.keys(n).length},m.partition=function(n,t,r){t=x(t,r);var e=[],u=[];return m.each(n,function(n,r,i){(t(n,r,i)?e:u).push(n)}),[e,u]},m.first=m.head=m.take=function(n,t,r){return null==n?void 0:null==t||r?n[0]:m.initial(n,n.length-t)},m.initial=function(n,t,r){return l.call(n,0,Math.max(0,n.length-(null==t||r?1:t)))},m.last=function(n,t,r){return null==n?void 0:null==t||r?n[n.length-1]:m.rest(n,Math.max(0,n.length-t))},m.rest=m.tail=m.drop=function(n,t,r){return l.call(n,null==t||r?1:t)},m.compact=function(n){return m.filter(n,m.identity)};var S=function(n,t,r,e){for(var u=[],i=0,o=e||0,a=O(n);a>o;o++){var c=n[o];if(k(c)&&(m.isArray(c)||m.isArguments(c))){t||(c=S(c,t,r));var f=0,l=c.length;for(u.length+=l;l>f;)u[i++]=c[f++]}else r||(u[i++]=c)}return u};m.flatten=function(n,t){return S(n,t,!1)},m.without=function(n){return m.difference(n,l.call(arguments,1))},m.uniq=m.unique=function(n,t,r,e){m.isBoolean(t)||(e=r,r=t,t=!1),null!=r&&(r=x(r,e));for(var u=[],i=[],o=0,a=O(n);a>o;o++){var c=n[o],f=r?r(c,o,n):c;t?(o&&i===f||u.push(c),i=f):r?m.contains(i,f)||(i.push(f),u.push(c)):m.contains(u,c)||u.push(c)}return u},m.union=function(){return m.uniq(S(arguments,!0,!0))},m.intersection=function(n){for(var t=[],r=arguments.length,e=0,u=O(n);u>e;e++){var i=n[e];if(!m.contains(t,i)){for(var o=1;r>o&&m.contains(arguments[o],i);o++);o===r&&t.push(i)}}return t},m.difference=function(n){var t=S(arguments,!0,!0,1);return m.filter(n,function(n){return!m.contains(t,n)})},m.zip=function(){return m.unzip(arguments)},m.unzip=function(n){for(var t=n&&m.max(n,O).length||0,r=Array(t),e=0;t>e;e++)r[e]=m.pluck(n,e);return r},m.object=function(n,t){for(var r={},e=0,u=O(n);u>e;e++)t?r[n[e]]=t[e]:r[n[e][0]]=n[e][1];return r},m.findIndex=t(1),m.findLastIndex=t(-1),m.sortedIndex=function(n,t,r,e){r=x(r,e,1);for(var u=r(t),i=0,o=O(n);o>i;){var a=Math.floor((i+o)/2);r(n[a])<u?i=a+1:o=a}return i},m.indexOf=r(1,m.findIndex,m.sortedIndex),m.lastIndexOf=r(-1,m.findLastIndex),m.range=function(n,t,r){null==t&&(t=n||0,n=0),r=r||1;for(var e=Math.max(Math.ceil((t-n)/r),0),u=Array(e),i=0;e>i;i++,n+=r)u[i]=n;return u};var E=function(n,t,r,e,u){if(!(e instanceof t))return n.apply(r,u);var i=j(n.prototype),o=n.apply(i,u);return m.isObject(o)?o:i};m.bind=function(n,t){if(g&&n.bind===g)return g.apply(n,l.call(arguments,1));if(!m.isFunction(n))throw new TypeError("Bind must be called on a function");var r=l.call(arguments,2),e=function(){return E(n,e,t,this,r.concat(l.call(arguments)))};return e},m.partial=function(n){var t=l.call(arguments,1),r=function(){for(var e=0,u=t.length,i=Array(u),o=0;u>o;o++)i[o]=t[o]===m?arguments[e++]:t[o];for(;e<arguments.length;)i.push(arguments[e++]);return E(n,r,this,this,i)};return r},m.bindAll=function(n){var t,r,e=arguments.length;if(1>=e)throw new Error("bindAll must be passed function names");for(t=1;e>t;t++)r=arguments[t],n[r]=m.bind(n[r],n);return n},m.memoize=function(n,t){var r=function(e){var u=r.cache,i=""+(t?t.apply(this,arguments):e);return m.has(u,i)||(u[i]=n.apply(this,arguments)),u[i]};return r.cache={},r},m.delay=function(n,t){var r=l.call(arguments,2);return setTimeout(function(){return n.apply(null,r)},t)},m.defer=m.partial(m.delay,m,1),m.throttle=function(n,t,r){var e,u,i,o=null,a=0;r||(r={});var c=function(){a=r.leading===!1?0:m.now(),o=null,i=n.apply(e,u),o||(e=u=null)};return function(){var f=m.now();a||r.leading!==!1||(a=f);var l=t-(f-a);return e=this,u=arguments,0>=l||l>t?(o&&(clearTimeout(o),o=null),a=f,i=n.apply(e,u),o||(e=u=null)):o||r.trailing===!1||(o=setTimeout(c,l)),i}},m.debounce=function(n,t,r){var e,u,i,o,a,c=function(){var f=m.now()-o;t>f&&f>=0?e=setTimeout(c,t-f):(e=null,r||(a=n.apply(i,u),e||(i=u=null)))};return function(){i=this,u=arguments,o=m.now();var f=r&&!e;return e||(e=setTimeout(c,t)),f&&(a=n.apply(i,u),i=u=null),a}},m.wrap=function(n,t){return m.partial(t,n)},m.negate=function(n){return function(){return!n.apply(this,arguments)}},m.compose=function(){var n=arguments,t=n.length-1;return function(){for(var r=t,e=n[t].apply(this,arguments);r--;)e=n[r].call(this,e);return e}},m.after=function(n,t){return function(){return--n<1?t.apply(this,arguments):void 0}},m.before=function(n,t){var r;return function(){return--n>0&&(r=t.apply(this,arguments)),1>=n&&(t=null),r}},m.once=m.partial(m.before,2);var M=!{toString:null}.propertyIsEnumerable("toString"),I=["valueOf","isPrototypeOf","toString","propertyIsEnumerable","hasOwnProperty","toLocaleString"];m.keys=function(n){if(!m.isObject(n))return[];if(v)return v(n);var t=[];for(var r in n)m.has(n,r)&&t.push(r);return M&&e(n,t),t},m.allKeys=function(n){if(!m.isObject(n))return[];var t=[];for(var r in n)t.push(r);return M&&e(n,t),t},m.values=function(n){for(var t=m.keys(n),r=t.length,e=Array(r),u=0;r>u;u++)e[u]=n[t[u]];return e},m.mapObject=function(n,t,r){t=x(t,r);for(var e,u=m.keys(n),i=u.length,o={},a=0;i>a;a++)e=u[a],o[e]=t(n[e],e,n);return o},m.pairs=function(n){for(var t=m.keys(n),r=t.length,e=Array(r),u=0;r>u;u++)e[u]=[t[u],n[t[u]]];return e},m.invert=function(n){for(var t={},r=m.keys(n),e=0,u=r.length;u>e;e++)t[n[r[e]]]=r[e];return t},m.functions=m.methods=function(n){var t=[];for(var r in n)m.isFunction(n[r])&&t.push(r);return t.sort()},m.extend=_(m.allKeys),m.extendOwn=m.assign=_(m.keys),m.findKey=function(n,t,r){t=x(t,r);for(var e,u=m.keys(n),i=0,o=u.length;o>i;i++)if(e=u[i],t(n[e],e,n))return e},m.pick=function(n,t,r){var e,u,i={},o=n;if(null==o)return i;m.isFunction(t)?(u=m.allKeys(o),e=b(t,r)):(u=S(arguments,!1,!1,1),e=function(n,t,r){return t in r},o=Object(o));for(var a=0,c=u.length;c>a;a++){var f=u[a],l=o[f];e(l,f,o)&&(i[f]=l)}return i},m.omit=function(n,t,r){if(m.isFunction(t))t=m.negate(t);else{var e=m.map(S(arguments,!1,!1,1),String);t=function(n,t){return!m.contains(e,t)}}return m.pick(n,t,r)},m.defaults=_(m.allKeys,!0),m.create=function(n,t){var r=j(n);return t&&m.extendOwn(r,t),r},m.clone=function(n){return m.isObject(n)?m.isArray(n)?n.slice():m.extend({},n):n},m.tap=function(n,t){return t(n),n},m.isMatch=function(n,t){var r=m.keys(t),e=r.length;if(null==n)return!e;for(var u=Object(n),i=0;e>i;i++){var o=r[i];if(t[o]!==u[o]||!(o in u))return!1}return!0};var N=function(n,t,r,e){if(n===t)return 0!==n||1/n===1/t;if(null==n||null==t)return n===t;n instanceof m&&(n=n._wrapped),t instanceof m&&(t=t._wrapped);var u=s.call(n);if(u!==s.call(t))return!1;switch(u){case"[object RegExp]":case"[object String]":return""+n==""+t;case"[object Number]":return+n!==+n?+t!==+t:0===+n?1/+n===1/t:+n===+t;case"[object Date]":case"[object Boolean]":return+n===+t}var i="[object Array]"===u;if(!i){if("object"!=typeof n||"object"!=typeof t)return!1;var o=n.constructor,a=t.constructor;if(o!==a&&!(m.isFunction(o)&&o instanceof o&&m.isFunction(a)&&a instanceof a)&&"constructor"in n&&"constructor"in t)return!1}r=r||[],e=e||[];for(var c=r.length;c--;)if(r[c]===n)return e[c]===t;if(r.push(n),e.push(t),i){if(c=n.length,c!==t.length)return!1;for(;c--;)if(!N(n[c],t[c],r,e))return!1}else{var f,l=m.keys(n);if(c=l.length,m.keys(t).length!==c)return!1;for(;c--;)if(f=l[c],!m.has(t,f)||!N(n[f],t[f],r,e))return!1}return r.pop(),e.pop(),!0};m.isEqual=function(n,t){return N(n,t)},m.isEmpty=function(n){return null==n?!0:k(n)&&(m.isArray(n)||m.isString(n)||m.isArguments(n))?0===n.length:0===m.keys(n).length},m.isElement=function(n){return!(!n||1!==n.nodeType)},m.isArray=h||function(n){return"[object Array]"===s.call(n)},m.isObject=function(n){var t=typeof n;return"function"===t||"object"===t&&!!n},m.each(["Arguments","Function","String","Number","Date","RegExp","Error"],function(n){m["is"+n]=function(t){return s.call(t)==="[object "+n+"]"}}),m.isArguments(arguments)||(m.isArguments=function(n){return m.has(n,"callee")}),"function"!=typeof/./&&"object"!=typeof Int8Array&&(m.isFunction=function(n){return"function"==typeof n||!1}),m.isFinite=function(n){return isFinite(n)&&!isNaN(parseFloat(n))},m.isNaN=function(n){return m.isNumber(n)&&n!==+n},m.isBoolean=function(n){return n===!0||n===!1||"[object Boolean]"===s.call(n)},m.isNull=function(n){return null===n},m.isUndefined=function(n){return n===void 0},m.has=function(n,t){return null!=n&&p.call(n,t)},m.noConflict=function(){return u._=i,this},m.identity=function(n){return n},m.constant=function(n){return function(){return n}},m.noop=function(){},m.property=w,m.propertyOf=function(n){return null==n?function(){}:function(t){return n[t]}},m.matcher=m.matches=function(n){return n=m.extendOwn({},n),function(t){return m.isMatch(t,n)}},m.times=function(n,t,r){var e=Array(Math.max(0,n));t=b(t,r,1);for(var u=0;n>u;u++)e[u]=t(u);return e},m.random=function(n,t){return null==t&&(t=n,n=0),n+Math.floor(Math.random()*(t-n+1))},m.now=Date.now||function(){return(new Date).getTime()};var B={"&":"&","<":"<",">":">",'"':""","'":"'","`":"`"},T=m.invert(B),R=function(n){var t=function(t){return n[t]},r="(?:"+m.keys(n).join("|")+")",e=RegExp(r),u=RegExp(r,"g");return function(n){return n=null==n?"":""+n,e.test(n)?n.replace(u,t):n}};m.escape=R(B),m.unescape=R(T),m.result=function(n,t,r){var e=null==n?void 0:n[t];return e===void 0&&(e=r),m.isFunction(e)?e.call(n):e};var q=0;m.uniqueId=function(n){var t=++q+"";return n?n+t:t},m.templateSettings={evaluate:/<%([\s\S]+?)%>/g,interpolate:/<%=([\s\S]+?)%>/g,escape:/<%-([\s\S]+?)%>/g};var K=/(.)^/,z={"'":"'","\\":"\\","\r":"r","\n":"n","\u2028":"u2028","\u2029":"u2029"},D=/\\|'|\r|\n|\u2028|\u2029/g,L=function(n){return"\\"+z[n]};m.template=function(n,t,r){!t&&r&&(t=r),t=m.defaults({},t,m.templateSettings);var e=RegExp([(t.escape||K).source,(t.interpolate||K).source,(t.evaluate||K).source].join("|")+"|$","g"),u=0,i="__p+='";n.replace(e,function(t,r,e,o,a){return i+=n.slice(u,a).replace(D,L),u=a+t.length,r?i+="'+\n((__t=("+r+"))==null?'':_.escape(__t))+\n'":e?i+="'+\n((__t=("+e+"))==null?'':__t)+\n'":o&&(i+="';\n"+o+"\n__p+='"),t}),i+="';\n",t.variable||(i="with(obj||{}){\n"+i+"}\n"),i="var __t,__p='',__j=Array.prototype.join,"+"print=function(){__p+=__j.call(arguments,'');};\n"+i+"return __p;\n";try{var o=new Function(t.variable||"obj","_",i)}catch(a){throw a.source=i,a}var c=function(n){return o.call(this,n,m)},f=t.variable||"obj";return c.source="function("+f+"){\n"+i+"}",c},m.chain=function(n){var t=m(n);return t._chain=!0,t};var P=function(n,t){return n._chain?m(t).chain():t};m.mixin=function(n){m.each(m.functions(n),function(t){var r=m[t]=n[t];m.prototype[t]=function(){var n=[this._wrapped];return f.apply(n,arguments),P(this,r.apply(m,n))}})},m.mixin(m),m.each(["pop","push","reverse","shift","sort","splice","unshift"],function(n){var t=o[n];m.prototype[n]=function(){var r=this._wrapped;return t.apply(r,arguments),"shift"!==n&&"splice"!==n||0!==r.length||delete r[0],P(this,r)}}),m.each(["concat","join","slice"],function(n){var t=o[n];m.prototype[n]=function(){return P(this,t.apply(this._wrapped,arguments))}}),m.prototype.value=function(){return this._wrapped},m.prototype.valueOf=m.prototype.toJSON=m.prototype.value,m.prototype.toString=function(){return""+this._wrapped},"function"==typeof define&&define.amd&&define("underscore",[],function(){return m})}).call(this);
+//# sourceMappingURL=underscore-min.map
\ No newline at end of file
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/src/ldt/ldt/static/ldt/js/underscore.js Fri Oct 02 10:24:05 2015 +0200
@@ -0,0 +1,1548 @@
+// Underscore.js 1.8.3
+// http://underscorejs.org
+// (c) 2009-2015 Jeremy Ashkenas, DocumentCloud and Investigative Reporters & Editors
+// Underscore may be freely distributed under the MIT license.
+
+(function() {
+
+ // Baseline setup
+ // --------------
+
+ // Establish the root object, `window` in the browser, or `exports` on the server.
+ var root = this;
+
+ // Save the previous value of the `_` variable.
+ var previousUnderscore = root._;
+
+ // Save bytes in the minified (but not gzipped) version:
+ var ArrayProto = Array.prototype, ObjProto = Object.prototype, FuncProto = Function.prototype;
+
+ // Create quick reference variables for speed access to core prototypes.
+ var
+ push = ArrayProto.push,
+ slice = ArrayProto.slice,
+ toString = ObjProto.toString,
+ hasOwnProperty = ObjProto.hasOwnProperty;
+
+ // All **ECMAScript 5** native function implementations that we hope to use
+ // are declared here.
+ var
+ nativeIsArray = Array.isArray,
+ nativeKeys = Object.keys,
+ nativeBind = FuncProto.bind,
+ nativeCreate = Object.create;
+
+ // Naked function reference for surrogate-prototype-swapping.
+ var Ctor = function(){};
+
+ // Create a safe reference to the Underscore object for use below.
+ var _ = function(obj) {
+ if (obj instanceof _) return obj;
+ if (!(this instanceof _)) return new _(obj);
+ this._wrapped = obj;
+ };
+
+ // Export the Underscore object for **Node.js**, with
+ // backwards-compatibility for the old `require()` API. If we're in
+ // the browser, add `_` as a global object.
+ if (typeof exports !== 'undefined') {
+ if (typeof module !== 'undefined' && module.exports) {
+ exports = module.exports = _;
+ }
+ exports._ = _;
+ } else {
+ root._ = _;
+ }
+
+ // Current version.
+ _.VERSION = '1.8.3';
+
+ // Internal function that returns an efficient (for current engines) version
+ // of the passed-in callback, to be repeatedly applied in other Underscore
+ // functions.
+ var optimizeCb = function(func, context, argCount) {
+ if (context === void 0) return func;
+ switch (argCount == null ? 3 : argCount) {
+ case 1: return function(value) {
+ return func.call(context, value);
+ };
+ case 2: return function(value, other) {
+ return func.call(context, value, other);
+ };
+ case 3: return function(value, index, collection) {
+ return func.call(context, value, index, collection);
+ };
+ case 4: return function(accumulator, value, index, collection) {
+ return func.call(context, accumulator, value, index, collection);
+ };
+ }
+ return function() {
+ return func.apply(context, arguments);
+ };
+ };
+
+ // A mostly-internal function to generate callbacks that can be applied
+ // to each element in a collection, returning the desired result — either
+ // identity, an arbitrary callback, a property matcher, or a property accessor.
+ var cb = function(value, context, argCount) {
+ if (value == null) return _.identity;
+ if (_.isFunction(value)) return optimizeCb(value, context, argCount);
+ if (_.isObject(value)) return _.matcher(value);
+ return _.property(value);
+ };
+ _.iteratee = function(value, context) {
+ return cb(value, context, Infinity);
+ };
+
+ // An internal function for creating assigner functions.
+ var createAssigner = function(keysFunc, undefinedOnly) {
+ return function(obj) {
+ var length = arguments.length;
+ if (length < 2 || obj == null) return obj;
+ for (var index = 1; index < length; index++) {
+ var source = arguments[index],
+ keys = keysFunc(source),
+ l = keys.length;
+ for (var i = 0; i < l; i++) {
+ var key = keys[i];
+ if (!undefinedOnly || obj[key] === void 0) obj[key] = source[key];
+ }
+ }
+ return obj;
+ };
+ };
+
+ // An internal function for creating a new object that inherits from another.
+ var baseCreate = function(prototype) {
+ if (!_.isObject(prototype)) return {};
+ if (nativeCreate) return nativeCreate(prototype);
+ Ctor.prototype = prototype;
+ var result = new Ctor;
+ Ctor.prototype = null;
+ return result;
+ };
+
+ var property = function(key) {
+ return function(obj) {
+ return obj == null ? void 0 : obj[key];
+ };
+ };
+
+ // Helper for collection methods to determine whether a collection
+ // should be iterated as an array or as an object
+ // Related: http://people.mozilla.org/~jorendorff/es6-draft.html#sec-tolength
+ // Avoids a very nasty iOS 8 JIT bug on ARM-64. #2094
+ var MAX_ARRAY_INDEX = Math.pow(2, 53) - 1;
+ var getLength = property('length');
+ var isArrayLike = function(collection) {
+ var length = getLength(collection);
+ return typeof length == 'number' && length >= 0 && length <= MAX_ARRAY_INDEX;
+ };
+
+ // Collection Functions
+ // --------------------
+
+ // The cornerstone, an `each` implementation, aka `forEach`.
+ // Handles raw objects in addition to array-likes. Treats all
+ // sparse array-likes as if they were dense.
+ _.each = _.forEach = function(obj, iteratee, context) {
+ iteratee = optimizeCb(iteratee, context);
+ var i, length;
+ if (isArrayLike(obj)) {
+ for (i = 0, length = obj.length; i < length; i++) {
+ iteratee(obj[i], i, obj);
+ }
+ } else {
+ var keys = _.keys(obj);
+ for (i = 0, length = keys.length; i < length; i++) {
+ iteratee(obj[keys[i]], keys[i], obj);
+ }
+ }
+ return obj;
+ };
+
+ // Return the results of applying the iteratee to each element.
+ _.map = _.collect = function(obj, iteratee, context) {
+ iteratee = cb(iteratee, context);
+ var keys = !isArrayLike(obj) && _.keys(obj),
+ length = (keys || obj).length,
+ results = Array(length);
+ for (var index = 0; index < length; index++) {
+ var currentKey = keys ? keys[index] : index;
+ results[index] = iteratee(obj[currentKey], currentKey, obj);
+ }
+ return results;
+ };
+
+ // Create a reducing function iterating left or right.
+ function createReduce(dir) {
+ // Optimized iterator function as using arguments.length
+ // in the main function will deoptimize the, see #1991.
+ function iterator(obj, iteratee, memo, keys, index, length) {
+ for (; index >= 0 && index < length; index += dir) {
+ var currentKey = keys ? keys[index] : index;
+ memo = iteratee(memo, obj[currentKey], currentKey, obj);
+ }
+ return memo;
+ }
+
+ return function(obj, iteratee, memo, context) {
+ iteratee = optimizeCb(iteratee, context, 4);
+ var keys = !isArrayLike(obj) && _.keys(obj),
+ length = (keys || obj).length,
+ index = dir > 0 ? 0 : length - 1;
+ // Determine the initial value if none is provided.
+ if (arguments.length < 3) {
+ memo = obj[keys ? keys[index] : index];
+ index += dir;
+ }
+ return iterator(obj, iteratee, memo, keys, index, length);
+ };
+ }
+
+ // **Reduce** builds up a single result from a list of values, aka `inject`,
+ // or `foldl`.
+ _.reduce = _.foldl = _.inject = createReduce(1);
+
+ // The right-associative version of reduce, also known as `foldr`.
+ _.reduceRight = _.foldr = createReduce(-1);
+
+ // Return the first value which passes a truth test. Aliased as `detect`.
+ _.find = _.detect = function(obj, predicate, context) {
+ var key;
+ if (isArrayLike(obj)) {
+ key = _.findIndex(obj, predicate, context);
+ } else {
+ key = _.findKey(obj, predicate, context);
+ }
+ if (key !== void 0 && key !== -1) return obj[key];
+ };
+
+ // Return all the elements that pass a truth test.
+ // Aliased as `select`.
+ _.filter = _.select = function(obj, predicate, context) {
+ var results = [];
+ predicate = cb(predicate, context);
+ _.each(obj, function(value, index, list) {
+ if (predicate(value, index, list)) results.push(value);
+ });
+ return results;
+ };
+
+ // Return all the elements for which a truth test fails.
+ _.reject = function(obj, predicate, context) {
+ return _.filter(obj, _.negate(cb(predicate)), context);
+ };
+
+ // Determine whether all of the elements match a truth test.
+ // Aliased as `all`.
+ _.every = _.all = function(obj, predicate, context) {
+ predicate = cb(predicate, context);
+ var keys = !isArrayLike(obj) && _.keys(obj),
+ length = (keys || obj).length;
+ for (var index = 0; index < length; index++) {
+ var currentKey = keys ? keys[index] : index;
+ if (!predicate(obj[currentKey], currentKey, obj)) return false;
+ }
+ return true;
+ };
+
+ // Determine if at least one element in the object matches a truth test.
+ // Aliased as `any`.
+ _.some = _.any = function(obj, predicate, context) {
+ predicate = cb(predicate, context);
+ var keys = !isArrayLike(obj) && _.keys(obj),
+ length = (keys || obj).length;
+ for (var index = 0; index < length; index++) {
+ var currentKey = keys ? keys[index] : index;
+ if (predicate(obj[currentKey], currentKey, obj)) return true;
+ }
+ return false;
+ };
+
+ // Determine if the array or object contains a given item (using `===`).
+ // Aliased as `includes` and `include`.
+ _.contains = _.includes = _.include = function(obj, item, fromIndex, guard) {
+ if (!isArrayLike(obj)) obj = _.values(obj);
+ if (typeof fromIndex != 'number' || guard) fromIndex = 0;
+ return _.indexOf(obj, item, fromIndex) >= 0;
+ };
+
+ // Invoke a method (with arguments) on every item in a collection.
+ _.invoke = function(obj, method) {
+ var args = slice.call(arguments, 2);
+ var isFunc = _.isFunction(method);
+ return _.map(obj, function(value) {
+ var func = isFunc ? method : value[method];
+ return func == null ? func : func.apply(value, args);
+ });
+ };
+
+ // Convenience version of a common use case of `map`: fetching a property.
+ _.pluck = function(obj, key) {
+ return _.map(obj, _.property(key));
+ };
+
+ // Convenience version of a common use case of `filter`: selecting only objects
+ // containing specific `key:value` pairs.
+ _.where = function(obj, attrs) {
+ return _.filter(obj, _.matcher(attrs));
+ };
+
+ // Convenience version of a common use case of `find`: getting the first object
+ // containing specific `key:value` pairs.
+ _.findWhere = function(obj, attrs) {
+ return _.find(obj, _.matcher(attrs));
+ };
+
+ // Return the maximum element (or element-based computation).
+ _.max = function(obj, iteratee, context) {
+ var result = -Infinity, lastComputed = -Infinity,
+ value, computed;
+ if (iteratee == null && obj != null) {
+ obj = isArrayLike(obj) ? obj : _.values(obj);
+ for (var i = 0, length = obj.length; i < length; i++) {
+ value = obj[i];
+ if (value > result) {
+ result = value;
+ }
+ }
+ } else {
+ iteratee = cb(iteratee, context);
+ _.each(obj, function(value, index, list) {
+ computed = iteratee(value, index, list);
+ if (computed > lastComputed || computed === -Infinity && result === -Infinity) {
+ result = value;
+ lastComputed = computed;
+ }
+ });
+ }
+ return result;
+ };
+
+ // Return the minimum element (or element-based computation).
+ _.min = function(obj, iteratee, context) {
+ var result = Infinity, lastComputed = Infinity,
+ value, computed;
+ if (iteratee == null && obj != null) {
+ obj = isArrayLike(obj) ? obj : _.values(obj);
+ for (var i = 0, length = obj.length; i < length; i++) {
+ value = obj[i];
+ if (value < result) {
+ result = value;
+ }
+ }
+ } else {
+ iteratee = cb(iteratee, context);
+ _.each(obj, function(value, index, list) {
+ computed = iteratee(value, index, list);
+ if (computed < lastComputed || computed === Infinity && result === Infinity) {
+ result = value;
+ lastComputed = computed;
+ }
+ });
+ }
+ return result;
+ };
+
+ // Shuffle a collection, using the modern version of the
+ // [Fisher-Yates shuffle](http://en.wikipedia.org/wiki/Fisher–Yates_shuffle).
+ _.shuffle = function(obj) {
+ var set = isArrayLike(obj) ? obj : _.values(obj);
+ var length = set.length;
+ var shuffled = Array(length);
+ for (var index = 0, rand; index < length; index++) {
+ rand = _.random(0, index);
+ if (rand !== index) shuffled[index] = shuffled[rand];
+ shuffled[rand] = set[index];
+ }
+ return shuffled;
+ };
+
+ // Sample **n** random values from a collection.
+ // If **n** is not specified, returns a single random element.
+ // The internal `guard` argument allows it to work with `map`.
+ _.sample = function(obj, n, guard) {
+ if (n == null || guard) {
+ if (!isArrayLike(obj)) obj = _.values(obj);
+ return obj[_.random(obj.length - 1)];
+ }
+ return _.shuffle(obj).slice(0, Math.max(0, n));
+ };
+
+ // Sort the object's values by a criterion produced by an iteratee.
+ _.sortBy = function(obj, iteratee, context) {
+ iteratee = cb(iteratee, context);
+ return _.pluck(_.map(obj, function(value, index, list) {
+ return {
+ value: value,
+ index: index,
+ criteria: iteratee(value, index, list)
+ };
+ }).sort(function(left, right) {
+ var a = left.criteria;
+ var b = right.criteria;
+ if (a !== b) {
+ if (a > b || a === void 0) return 1;
+ if (a < b || b === void 0) return -1;
+ }
+ return left.index - right.index;
+ }), 'value');
+ };
+
+ // An internal function used for aggregate "group by" operations.
+ var group = function(behavior) {
+ return function(obj, iteratee, context) {
+ var result = {};
+ iteratee = cb(iteratee, context);
+ _.each(obj, function(value, index) {
+ var key = iteratee(value, index, obj);
+ behavior(result, value, key);
+ });
+ return result;
+ };
+ };
+
+ // Groups the object's values by a criterion. Pass either a string attribute
+ // to group by, or a function that returns the criterion.
+ _.groupBy = group(function(result, value, key) {
+ if (_.has(result, key)) result[key].push(value); else result[key] = [value];
+ });
+
+ // Indexes the object's values by a criterion, similar to `groupBy`, but for
+ // when you know that your index values will be unique.
+ _.indexBy = group(function(result, value, key) {
+ result[key] = value;
+ });
+
+ // Counts instances of an object that group by a certain criterion. Pass
+ // either a string attribute to count by, or a function that returns the
+ // criterion.
+ _.countBy = group(function(result, value, key) {
+ if (_.has(result, key)) result[key]++; else result[key] = 1;
+ });
+
+ // Safely create a real, live array from anything iterable.
+ _.toArray = function(obj) {
+ if (!obj) return [];
+ if (_.isArray(obj)) return slice.call(obj);
+ if (isArrayLike(obj)) return _.map(obj, _.identity);
+ return _.values(obj);
+ };
+
+ // Return the number of elements in an object.
+ _.size = function(obj) {
+ if (obj == null) return 0;
+ return isArrayLike(obj) ? obj.length : _.keys(obj).length;
+ };
+
+ // Split a collection into two arrays: one whose elements all satisfy the given
+ // predicate, and one whose elements all do not satisfy the predicate.
+ _.partition = function(obj, predicate, context) {
+ predicate = cb(predicate, context);
+ var pass = [], fail = [];
+ _.each(obj, function(value, key, obj) {
+ (predicate(value, key, obj) ? pass : fail).push(value);
+ });
+ return [pass, fail];
+ };
+
+ // Array Functions
+ // ---------------
+
+ // Get the first element of an array. Passing **n** will return the first N
+ // values in the array. Aliased as `head` and `take`. The **guard** check
+ // allows it to work with `_.map`.
+ _.first = _.head = _.take = function(array, n, guard) {
+ if (array == null) return void 0;
+ if (n == null || guard) return array[0];
+ return _.initial(array, array.length - n);
+ };
+
+ // Returns everything but the last entry of the array. Especially useful on
+ // the arguments object. Passing **n** will return all the values in
+ // the array, excluding the last N.
+ _.initial = function(array, n, guard) {
+ return slice.call(array, 0, Math.max(0, array.length - (n == null || guard ? 1 : n)));
+ };
+
+ // Get the last element of an array. Passing **n** will return the last N
+ // values in the array.
+ _.last = function(array, n, guard) {
+ if (array == null) return void 0;
+ if (n == null || guard) return array[array.length - 1];
+ return _.rest(array, Math.max(0, array.length - n));
+ };
+
+ // Returns everything but the first entry of the array. Aliased as `tail` and `drop`.
+ // Especially useful on the arguments object. Passing an **n** will return
+ // the rest N values in the array.
+ _.rest = _.tail = _.drop = function(array, n, guard) {
+ return slice.call(array, n == null || guard ? 1 : n);
+ };
+
+ // Trim out all falsy values from an array.
+ _.compact = function(array) {
+ return _.filter(array, _.identity);
+ };
+
+ // Internal implementation of a recursive `flatten` function.
+ var flatten = function(input, shallow, strict, startIndex) {
+ var output = [], idx = 0;
+ for (var i = startIndex || 0, length = getLength(input); i < length; i++) {
+ var value = input[i];
+ if (isArrayLike(value) && (_.isArray(value) || _.isArguments(value))) {
+ //flatten current level of array or arguments object
+ if (!shallow) value = flatten(value, shallow, strict);
+ var j = 0, len = value.length;
+ output.length += len;
+ while (j < len) {
+ output[idx++] = value[j++];
+ }
+ } else if (!strict) {
+ output[idx++] = value;
+ }
+ }
+ return output;
+ };
+
+ // Flatten out an array, either recursively (by default), or just one level.
+ _.flatten = function(array, shallow) {
+ return flatten(array, shallow, false);
+ };
+
+ // Return a version of the array that does not contain the specified value(s).
+ _.without = function(array) {
+ return _.difference(array, slice.call(arguments, 1));
+ };
+
+ // Produce a duplicate-free version of the array. If the array has already
+ // been sorted, you have the option of using a faster algorithm.
+ // Aliased as `unique`.
+ _.uniq = _.unique = function(array, isSorted, iteratee, context) {
+ if (!_.isBoolean(isSorted)) {
+ context = iteratee;
+ iteratee = isSorted;
+ isSorted = false;
+ }
+ if (iteratee != null) iteratee = cb(iteratee, context);
+ var result = [];
+ var seen = [];
+ for (var i = 0, length = getLength(array); i < length; i++) {
+ var value = array[i],
+ computed = iteratee ? iteratee(value, i, array) : value;
+ if (isSorted) {
+ if (!i || seen !== computed) result.push(value);
+ seen = computed;
+ } else if (iteratee) {
+ if (!_.contains(seen, computed)) {
+ seen.push(computed);
+ result.push(value);
+ }
+ } else if (!_.contains(result, value)) {
+ result.push(value);
+ }
+ }
+ return result;
+ };
+
+ // Produce an array that contains the union: each distinct element from all of
+ // the passed-in arrays.
+ _.union = function() {
+ return _.uniq(flatten(arguments, true, true));
+ };
+
+ // Produce an array that contains every item shared between all the
+ // passed-in arrays.
+ _.intersection = function(array) {
+ var result = [];
+ var argsLength = arguments.length;
+ for (var i = 0, length = getLength(array); i < length; i++) {
+ var item = array[i];
+ if (_.contains(result, item)) continue;
+ for (var j = 1; j < argsLength; j++) {
+ if (!_.contains(arguments[j], item)) break;
+ }
+ if (j === argsLength) result.push(item);
+ }
+ return result;
+ };
+
+ // Take the difference between one array and a number of other arrays.
+ // Only the elements present in just the first array will remain.
+ _.difference = function(array) {
+ var rest = flatten(arguments, true, true, 1);
+ return _.filter(array, function(value){
+ return !_.contains(rest, value);
+ });
+ };
+
+ // Zip together multiple lists into a single array -- elements that share
+ // an index go together.
+ _.zip = function() {
+ return _.unzip(arguments);
+ };
+
+ // Complement of _.zip. Unzip accepts an array of arrays and groups
+ // each array's elements on shared indices
+ _.unzip = function(array) {
+ var length = array && _.max(array, getLength).length || 0;
+ var result = Array(length);
+
+ for (var index = 0; index < length; index++) {
+ result[index] = _.pluck(array, index);
+ }
+ return result;
+ };
+
+ // Converts lists into objects. Pass either a single array of `[key, value]`
+ // pairs, or two parallel arrays of the same length -- one of keys, and one of
+ // the corresponding values.
+ _.object = function(list, values) {
+ var result = {};
+ for (var i = 0, length = getLength(list); i < length; i++) {
+ if (values) {
+ result[list[i]] = values[i];
+ } else {
+ result[list[i][0]] = list[i][1];
+ }
+ }
+ return result;
+ };
+
+ // Generator function to create the findIndex and findLastIndex functions
+ function createPredicateIndexFinder(dir) {
+ return function(array, predicate, context) {
+ predicate = cb(predicate, context);
+ var length = getLength(array);
+ var index = dir > 0 ? 0 : length - 1;
+ for (; index >= 0 && index < length; index += dir) {
+ if (predicate(array[index], index, array)) return index;
+ }
+ return -1;
+ };
+ }
+
+ // Returns the first index on an array-like that passes a predicate test
+ _.findIndex = createPredicateIndexFinder(1);
+ _.findLastIndex = createPredicateIndexFinder(-1);
+
+ // Use a comparator function to figure out the smallest index at which
+ // an object should be inserted so as to maintain order. Uses binary search.
+ _.sortedIndex = function(array, obj, iteratee, context) {
+ iteratee = cb(iteratee, context, 1);
+ var value = iteratee(obj);
+ var low = 0, high = getLength(array);
+ while (low < high) {
+ var mid = Math.floor((low + high) / 2);
+ if (iteratee(array[mid]) < value) low = mid + 1; else high = mid;
+ }
+ return low;
+ };
+
+ // Generator function to create the indexOf and lastIndexOf functions
+ function createIndexFinder(dir, predicateFind, sortedIndex) {
+ return function(array, item, idx) {
+ var i = 0, length = getLength(array);
+ if (typeof idx == 'number') {
+ if (dir > 0) {
+ i = idx >= 0 ? idx : Math.max(idx + length, i);
+ } else {
+ length = idx >= 0 ? Math.min(idx + 1, length) : idx + length + 1;
+ }
+ } else if (sortedIndex && idx && length) {
+ idx = sortedIndex(array, item);
+ return array[idx] === item ? idx : -1;
+ }
+ if (item !== item) {
+ idx = predicateFind(slice.call(array, i, length), _.isNaN);
+ return idx >= 0 ? idx + i : -1;
+ }
+ for (idx = dir > 0 ? i : length - 1; idx >= 0 && idx < length; idx += dir) {
+ if (array[idx] === item) return idx;
+ }
+ return -1;
+ };
+ }
+
+ // Return the position of the first occurrence of an item in an array,
+ // or -1 if the item is not included in the array.
+ // If the array is large and already in sort order, pass `true`
+ // for **isSorted** to use binary search.
+ _.indexOf = createIndexFinder(1, _.findIndex, _.sortedIndex);
+ _.lastIndexOf = createIndexFinder(-1, _.findLastIndex);
+
+ // Generate an integer Array containing an arithmetic progression. A port of
+ // the native Python `range()` function. See
+ // [the Python documentation](http://docs.python.org/library/functions.html#range).
+ _.range = function(start, stop, step) {
+ if (stop == null) {
+ stop = start || 0;
+ start = 0;
+ }
+ step = step || 1;
+
+ var length = Math.max(Math.ceil((stop - start) / step), 0);
+ var range = Array(length);
+
+ for (var idx = 0; idx < length; idx++, start += step) {
+ range[idx] = start;
+ }
+
+ return range;
+ };
+
+ // Function (ahem) Functions
+ // ------------------
+
+ // Determines whether to execute a function as a constructor
+ // or a normal function with the provided arguments
+ var executeBound = function(sourceFunc, boundFunc, context, callingContext, args) {
+ if (!(callingContext instanceof boundFunc)) return sourceFunc.apply(context, args);
+ var self = baseCreate(sourceFunc.prototype);
+ var result = sourceFunc.apply(self, args);
+ if (_.isObject(result)) return result;
+ return self;
+ };
+
+ // Create a function bound to a given object (assigning `this`, and arguments,
+ // optionally). Delegates to **ECMAScript 5**'s native `Function.bind` if
+ // available.
+ _.bind = function(func, context) {
+ if (nativeBind && func.bind === nativeBind) return nativeBind.apply(func, slice.call(arguments, 1));
+ if (!_.isFunction(func)) throw new TypeError('Bind must be called on a function');
+ var args = slice.call(arguments, 2);
+ var bound = function() {
+ return executeBound(func, bound, context, this, args.concat(slice.call(arguments)));
+ };
+ return bound;
+ };
+
+ // Partially apply a function by creating a version that has had some of its
+ // arguments pre-filled, without changing its dynamic `this` context. _ acts
+ // as a placeholder, allowing any combination of arguments to be pre-filled.
+ _.partial = function(func) {
+ var boundArgs = slice.call(arguments, 1);
+ var bound = function() {
+ var position = 0, length = boundArgs.length;
+ var args = Array(length);
+ for (var i = 0; i < length; i++) {
+ args[i] = boundArgs[i] === _ ? arguments[position++] : boundArgs[i];
+ }
+ while (position < arguments.length) args.push(arguments[position++]);
+ return executeBound(func, bound, this, this, args);
+ };
+ return bound;
+ };
+
+ // Bind a number of an object's methods to that object. Remaining arguments
+ // are the method names to be bound. Useful for ensuring that all callbacks
+ // defined on an object belong to it.
+ _.bindAll = function(obj) {
+ var i, length = arguments.length, key;
+ if (length <= 1) throw new Error('bindAll must be passed function names');
+ for (i = 1; i < length; i++) {
+ key = arguments[i];
+ obj[key] = _.bind(obj[key], obj);
+ }
+ return obj;
+ };
+
+ // Memoize an expensive function by storing its results.
+ _.memoize = function(func, hasher) {
+ var memoize = function(key) {
+ var cache = memoize.cache;
+ var address = '' + (hasher ? hasher.apply(this, arguments) : key);
+ if (!_.has(cache, address)) cache[address] = func.apply(this, arguments);
+ return cache[address];
+ };
+ memoize.cache = {};
+ return memoize;
+ };
+
+ // Delays a function for the given number of milliseconds, and then calls
+ // it with the arguments supplied.
+ _.delay = function(func, wait) {
+ var args = slice.call(arguments, 2);
+ return setTimeout(function(){
+ return func.apply(null, args);
+ }, wait);
+ };
+
+ // Defers a function, scheduling it to run after the current call stack has
+ // cleared.
+ _.defer = _.partial(_.delay, _, 1);
+
+ // Returns a function, that, when invoked, will only be triggered at most once
+ // during a given window of time. Normally, the throttled function will run
+ // as much as it can, without ever going more than once per `wait` duration;
+ // but if you'd like to disable the execution on the leading edge, pass
+ // `{leading: false}`. To disable execution on the trailing edge, ditto.
+ _.throttle = function(func, wait, options) {
+ var context, args, result;
+ var timeout = null;
+ var previous = 0;
+ if (!options) options = {};
+ var later = function() {
+ previous = options.leading === false ? 0 : _.now();
+ timeout = null;
+ result = func.apply(context, args);
+ if (!timeout) context = args = null;
+ };
+ return function() {
+ var now = _.now();
+ if (!previous && options.leading === false) previous = now;
+ var remaining = wait - (now - previous);
+ context = this;
+ args = arguments;
+ if (remaining <= 0 || remaining > wait) {
+ if (timeout) {
+ clearTimeout(timeout);
+ timeout = null;
+ }
+ previous = now;
+ result = func.apply(context, args);
+ if (!timeout) context = args = null;
+ } else if (!timeout && options.trailing !== false) {
+ timeout = setTimeout(later, remaining);
+ }
+ return result;
+ };
+ };
+
+ // Returns a function, that, as long as it continues to be invoked, will not
+ // be triggered. The function will be called after it stops being called for
+ // N milliseconds. If `immediate` is passed, trigger the function on the
+ // leading edge, instead of the trailing.
+ _.debounce = function(func, wait, immediate) {
+ var timeout, args, context, timestamp, result;
+
+ var later = function() {
+ var last = _.now() - timestamp;
+
+ if (last < wait && last >= 0) {
+ timeout = setTimeout(later, wait - last);
+ } else {
+ timeout = null;
+ if (!immediate) {
+ result = func.apply(context, args);
+ if (!timeout) context = args = null;
+ }
+ }
+ };
+
+ return function() {
+ context = this;
+ args = arguments;
+ timestamp = _.now();
+ var callNow = immediate && !timeout;
+ if (!timeout) timeout = setTimeout(later, wait);
+ if (callNow) {
+ result = func.apply(context, args);
+ context = args = null;
+ }
+
+ return result;
+ };
+ };
+
+ // Returns the first function passed as an argument to the second,
+ // allowing you to adjust arguments, run code before and after, and
+ // conditionally execute the original function.
+ _.wrap = function(func, wrapper) {
+ return _.partial(wrapper, func);
+ };
+
+ // Returns a negated version of the passed-in predicate.
+ _.negate = function(predicate) {
+ return function() {
+ return !predicate.apply(this, arguments);
+ };
+ };
+
+ // Returns a function that is the composition of a list of functions, each
+ // consuming the return value of the function that follows.
+ _.compose = function() {
+ var args = arguments;
+ var start = args.length - 1;
+ return function() {
+ var i = start;
+ var result = args[start].apply(this, arguments);
+ while (i--) result = args[i].call(this, result);
+ return result;
+ };
+ };
+
+ // Returns a function that will only be executed on and after the Nth call.
+ _.after = function(times, func) {
+ return function() {
+ if (--times < 1) {
+ return func.apply(this, arguments);
+ }
+ };
+ };
+
+ // Returns a function that will only be executed up to (but not including) the Nth call.
+ _.before = function(times, func) {
+ var memo;
+ return function() {
+ if (--times > 0) {
+ memo = func.apply(this, arguments);
+ }
+ if (times <= 1) func = null;
+ return memo;
+ };
+ };
+
+ // Returns a function that will be executed at most one time, no matter how
+ // often you call it. Useful for lazy initialization.
+ _.once = _.partial(_.before, 2);
+
+ // Object Functions
+ // ----------------
+
+ // Keys in IE < 9 that won't be iterated by `for key in ...` and thus missed.
+ var hasEnumBug = !{toString: null}.propertyIsEnumerable('toString');
+ var nonEnumerableProps = ['valueOf', 'isPrototypeOf', 'toString',
+ 'propertyIsEnumerable', 'hasOwnProperty', 'toLocaleString'];
+
+ function collectNonEnumProps(obj, keys) {
+ var nonEnumIdx = nonEnumerableProps.length;
+ var constructor = obj.constructor;
+ var proto = (_.isFunction(constructor) && constructor.prototype) || ObjProto;
+
+ // Constructor is a special case.
+ var prop = 'constructor';
+ if (_.has(obj, prop) && !_.contains(keys, prop)) keys.push(prop);
+
+ while (nonEnumIdx--) {
+ prop = nonEnumerableProps[nonEnumIdx];
+ if (prop in obj && obj[prop] !== proto[prop] && !_.contains(keys, prop)) {
+ keys.push(prop);
+ }
+ }
+ }
+
+ // Retrieve the names of an object's own properties.
+ // Delegates to **ECMAScript 5**'s native `Object.keys`
+ _.keys = function(obj) {
+ if (!_.isObject(obj)) return [];
+ if (nativeKeys) return nativeKeys(obj);
+ var keys = [];
+ for (var key in obj) if (_.has(obj, key)) keys.push(key);
+ // Ahem, IE < 9.
+ if (hasEnumBug) collectNonEnumProps(obj, keys);
+ return keys;
+ };
+
+ // Retrieve all the property names of an object.
+ _.allKeys = function(obj) {
+ if (!_.isObject(obj)) return [];
+ var keys = [];
+ for (var key in obj) keys.push(key);
+ // Ahem, IE < 9.
+ if (hasEnumBug) collectNonEnumProps(obj, keys);
+ return keys;
+ };
+
+ // Retrieve the values of an object's properties.
+ _.values = function(obj) {
+ var keys = _.keys(obj);
+ var length = keys.length;
+ var values = Array(length);
+ for (var i = 0; i < length; i++) {
+ values[i] = obj[keys[i]];
+ }
+ return values;
+ };
+
+ // Returns the results of applying the iteratee to each element of the object
+ // In contrast to _.map it returns an object
+ _.mapObject = function(obj, iteratee, context) {
+ iteratee = cb(iteratee, context);
+ var keys = _.keys(obj),
+ length = keys.length,
+ results = {},
+ currentKey;
+ for (var index = 0; index < length; index++) {
+ currentKey = keys[index];
+ results[currentKey] = iteratee(obj[currentKey], currentKey, obj);
+ }
+ return results;
+ };
+
+ // Convert an object into a list of `[key, value]` pairs.
+ _.pairs = function(obj) {
+ var keys = _.keys(obj);
+ var length = keys.length;
+ var pairs = Array(length);
+ for (var i = 0; i < length; i++) {
+ pairs[i] = [keys[i], obj[keys[i]]];
+ }
+ return pairs;
+ };
+
+ // Invert the keys and values of an object. The values must be serializable.
+ _.invert = function(obj) {
+ var result = {};
+ var keys = _.keys(obj);
+ for (var i = 0, length = keys.length; i < length; i++) {
+ result[obj[keys[i]]] = keys[i];
+ }
+ return result;
+ };
+
+ // Return a sorted list of the function names available on the object.
+ // Aliased as `methods`
+ _.functions = _.methods = function(obj) {
+ var names = [];
+ for (var key in obj) {
+ if (_.isFunction(obj[key])) names.push(key);
+ }
+ return names.sort();
+ };
+
+ // Extend a given object with all the properties in passed-in object(s).
+ _.extend = createAssigner(_.allKeys);
+
+ // Assigns a given object with all the own properties in the passed-in object(s)
+ // (https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Object/assign)
+ _.extendOwn = _.assign = createAssigner(_.keys);
+
+ // Returns the first key on an object that passes a predicate test
+ _.findKey = function(obj, predicate, context) {
+ predicate = cb(predicate, context);
+ var keys = _.keys(obj), key;
+ for (var i = 0, length = keys.length; i < length; i++) {
+ key = keys[i];
+ if (predicate(obj[key], key, obj)) return key;
+ }
+ };
+
+ // Return a copy of the object only containing the whitelisted properties.
+ _.pick = function(object, oiteratee, context) {
+ var result = {}, obj = object, iteratee, keys;
+ if (obj == null) return result;
+ if (_.isFunction(oiteratee)) {
+ keys = _.allKeys(obj);
+ iteratee = optimizeCb(oiteratee, context);
+ } else {
+ keys = flatten(arguments, false, false, 1);
+ iteratee = function(value, key, obj) { return key in obj; };
+ obj = Object(obj);
+ }
+ for (var i = 0, length = keys.length; i < length; i++) {
+ var key = keys[i];
+ var value = obj[key];
+ if (iteratee(value, key, obj)) result[key] = value;
+ }
+ return result;
+ };
+
+ // Return a copy of the object without the blacklisted properties.
+ _.omit = function(obj, iteratee, context) {
+ if (_.isFunction(iteratee)) {
+ iteratee = _.negate(iteratee);
+ } else {
+ var keys = _.map(flatten(arguments, false, false, 1), String);
+ iteratee = function(value, key) {
+ return !_.contains(keys, key);
+ };
+ }
+ return _.pick(obj, iteratee, context);
+ };
+
+ // Fill in a given object with default properties.
+ _.defaults = createAssigner(_.allKeys, true);
+
+ // Creates an object that inherits from the given prototype object.
+ // If additional properties are provided then they will be added to the
+ // created object.
+ _.create = function(prototype, props) {
+ var result = baseCreate(prototype);
+ if (props) _.extendOwn(result, props);
+ return result;
+ };
+
+ // Create a (shallow-cloned) duplicate of an object.
+ _.clone = function(obj) {
+ if (!_.isObject(obj)) return obj;
+ return _.isArray(obj) ? obj.slice() : _.extend({}, obj);
+ };
+
+ // Invokes interceptor with the obj, and then returns obj.
+ // The primary purpose of this method is to "tap into" a method chain, in
+ // order to perform operations on intermediate results within the chain.
+ _.tap = function(obj, interceptor) {
+ interceptor(obj);
+ return obj;
+ };
+
+ // Returns whether an object has a given set of `key:value` pairs.
+ _.isMatch = function(object, attrs) {
+ var keys = _.keys(attrs), length = keys.length;
+ if (object == null) return !length;
+ var obj = Object(object);
+ for (var i = 0; i < length; i++) {
+ var key = keys[i];
+ if (attrs[key] !== obj[key] || !(key in obj)) return false;
+ }
+ return true;
+ };
+
+
+ // Internal recursive comparison function for `isEqual`.
+ var eq = function(a, b, aStack, bStack) {
+ // Identical objects are equal. `0 === -0`, but they aren't identical.
+ // See the [Harmony `egal` proposal](http://wiki.ecmascript.org/doku.php?id=harmony:egal).
+ if (a === b) return a !== 0 || 1 / a === 1 / b;
+ // A strict comparison is necessary because `null == undefined`.
+ if (a == null || b == null) return a === b;
+ // Unwrap any wrapped objects.
+ if (a instanceof _) a = a._wrapped;
+ if (b instanceof _) b = b._wrapped;
+ // Compare `[[Class]]` names.
+ var className = toString.call(a);
+ if (className !== toString.call(b)) return false;
+ switch (className) {
+ // Strings, numbers, regular expressions, dates, and booleans are compared by value.
+ case '[object RegExp]':
+ // RegExps are coerced to strings for comparison (Note: '' + /a/i === '/a/i')
+ case '[object String]':
+ // Primitives and their corresponding object wrappers are equivalent; thus, `"5"` is
+ // equivalent to `new String("5")`.
+ return '' + a === '' + b;
+ case '[object Number]':
+ // `NaN`s are equivalent, but non-reflexive.
+ // Object(NaN) is equivalent to NaN
+ if (+a !== +a) return +b !== +b;
+ // An `egal` comparison is performed for other numeric values.
+ return +a === 0 ? 1 / +a === 1 / b : +a === +b;
+ case '[object Date]':
+ case '[object Boolean]':
+ // Coerce dates and booleans to numeric primitive values. Dates are compared by their
+ // millisecond representations. Note that invalid dates with millisecond representations
+ // of `NaN` are not equivalent.
+ return +a === +b;
+ }
+
+ var areArrays = className === '[object Array]';
+ if (!areArrays) {
+ if (typeof a != 'object' || typeof b != 'object') return false;
+
+ // Objects with different constructors are not equivalent, but `Object`s or `Array`s
+ // from different frames are.
+ var aCtor = a.constructor, bCtor = b.constructor;
+ if (aCtor !== bCtor && !(_.isFunction(aCtor) && aCtor instanceof aCtor &&
+ _.isFunction(bCtor) && bCtor instanceof bCtor)
+ && ('constructor' in a && 'constructor' in b)) {
+ return false;
+ }
+ }
+ // Assume equality for cyclic structures. The algorithm for detecting cyclic
+ // structures is adapted from ES 5.1 section 15.12.3, abstract operation `JO`.
+
+ // Initializing stack of traversed objects.
+ // It's done here since we only need them for objects and arrays comparison.
+ aStack = aStack || [];
+ bStack = bStack || [];
+ var length = aStack.length;
+ while (length--) {
+ // Linear search. Performance is inversely proportional to the number of
+ // unique nested structures.
+ if (aStack[length] === a) return bStack[length] === b;
+ }
+
+ // Add the first object to the stack of traversed objects.
+ aStack.push(a);
+ bStack.push(b);
+
+ // Recursively compare objects and arrays.
+ if (areArrays) {
+ // Compare array lengths to determine if a deep comparison is necessary.
+ length = a.length;
+ if (length !== b.length) return false;
+ // Deep compare the contents, ignoring non-numeric properties.
+ while (length--) {
+ if (!eq(a[length], b[length], aStack, bStack)) return false;
+ }
+ } else {
+ // Deep compare objects.
+ var keys = _.keys(a), key;
+ length = keys.length;
+ // Ensure that both objects contain the same number of properties before comparing deep equality.
+ if (_.keys(b).length !== length) return false;
+ while (length--) {
+ // Deep compare each member
+ key = keys[length];
+ if (!(_.has(b, key) && eq(a[key], b[key], aStack, bStack))) return false;
+ }
+ }
+ // Remove the first object from the stack of traversed objects.
+ aStack.pop();
+ bStack.pop();
+ return true;
+ };
+
+ // Perform a deep comparison to check if two objects are equal.
+ _.isEqual = function(a, b) {
+ return eq(a, b);
+ };
+
+ // Is a given array, string, or object empty?
+ // An "empty" object has no enumerable own-properties.
+ _.isEmpty = function(obj) {
+ if (obj == null) return true;
+ if (isArrayLike(obj) && (_.isArray(obj) || _.isString(obj) || _.isArguments(obj))) return obj.length === 0;
+ return _.keys(obj).length === 0;
+ };
+
+ // Is a given value a DOM element?
+ _.isElement = function(obj) {
+ return !!(obj && obj.nodeType === 1);
+ };
+
+ // Is a given value an array?
+ // Delegates to ECMA5's native Array.isArray
+ _.isArray = nativeIsArray || function(obj) {
+ return toString.call(obj) === '[object Array]';
+ };
+
+ // Is a given variable an object?
+ _.isObject = function(obj) {
+ var type = typeof obj;
+ return type === 'function' || type === 'object' && !!obj;
+ };
+
+ // Add some isType methods: isArguments, isFunction, isString, isNumber, isDate, isRegExp, isError.
+ _.each(['Arguments', 'Function', 'String', 'Number', 'Date', 'RegExp', 'Error'], function(name) {
+ _['is' + name] = function(obj) {
+ return toString.call(obj) === '[object ' + name + ']';
+ };
+ });
+
+ // Define a fallback version of the method in browsers (ahem, IE < 9), where
+ // there isn't any inspectable "Arguments" type.
+ if (!_.isArguments(arguments)) {
+ _.isArguments = function(obj) {
+ return _.has(obj, 'callee');
+ };
+ }
+
+ // Optimize `isFunction` if appropriate. Work around some typeof bugs in old v8,
+ // IE 11 (#1621), and in Safari 8 (#1929).
+ if (typeof /./ != 'function' && typeof Int8Array != 'object') {
+ _.isFunction = function(obj) {
+ return typeof obj == 'function' || false;
+ };
+ }
+
+ // Is a given object a finite number?
+ _.isFinite = function(obj) {
+ return isFinite(obj) && !isNaN(parseFloat(obj));
+ };
+
+ // Is the given value `NaN`? (NaN is the only number which does not equal itself).
+ _.isNaN = function(obj) {
+ return _.isNumber(obj) && obj !== +obj;
+ };
+
+ // Is a given value a boolean?
+ _.isBoolean = function(obj) {
+ return obj === true || obj === false || toString.call(obj) === '[object Boolean]';
+ };
+
+ // Is a given value equal to null?
+ _.isNull = function(obj) {
+ return obj === null;
+ };
+
+ // Is a given variable undefined?
+ _.isUndefined = function(obj) {
+ return obj === void 0;
+ };
+
+ // Shortcut function for checking if an object has a given property directly
+ // on itself (in other words, not on a prototype).
+ _.has = function(obj, key) {
+ return obj != null && hasOwnProperty.call(obj, key);
+ };
+
+ // Utility Functions
+ // -----------------
+
+ // Run Underscore.js in *noConflict* mode, returning the `_` variable to its
+ // previous owner. Returns a reference to the Underscore object.
+ _.noConflict = function() {
+ root._ = previousUnderscore;
+ return this;
+ };
+
+ // Keep the identity function around for default iteratees.
+ _.identity = function(value) {
+ return value;
+ };
+
+ // Predicate-generating functions. Often useful outside of Underscore.
+ _.constant = function(value) {
+ return function() {
+ return value;
+ };
+ };
+
+ _.noop = function(){};
+
+ _.property = property;
+
+ // Generates a function for a given object that returns a given property.
+ _.propertyOf = function(obj) {
+ return obj == null ? function(){} : function(key) {
+ return obj[key];
+ };
+ };
+
+ // Returns a predicate for checking whether an object has a given set of
+ // `key:value` pairs.
+ _.matcher = _.matches = function(attrs) {
+ attrs = _.extendOwn({}, attrs);
+ return function(obj) {
+ return _.isMatch(obj, attrs);
+ };
+ };
+
+ // Run a function **n** times.
+ _.times = function(n, iteratee, context) {
+ var accum = Array(Math.max(0, n));
+ iteratee = optimizeCb(iteratee, context, 1);
+ for (var i = 0; i < n; i++) accum[i] = iteratee(i);
+ return accum;
+ };
+
+ // Return a random integer between min and max (inclusive).
+ _.random = function(min, max) {
+ if (max == null) {
+ max = min;
+ min = 0;
+ }
+ return min + Math.floor(Math.random() * (max - min + 1));
+ };
+
+ // A (possibly faster) way to get the current timestamp as an integer.
+ _.now = Date.now || function() {
+ return new Date().getTime();
+ };
+
+ // List of HTML entities for escaping.
+ var escapeMap = {
+ '&': '&',
+ '<': '<',
+ '>': '>',
+ '"': '"',
+ "'": ''',
+ '`': '`'
+ };
+ var unescapeMap = _.invert(escapeMap);
+
+ // Functions for escaping and unescaping strings to/from HTML interpolation.
+ var createEscaper = function(map) {
+ var escaper = function(match) {
+ return map[match];
+ };
+ // Regexes for identifying a key that needs to be escaped
+ var source = '(?:' + _.keys(map).join('|') + ')';
+ var testRegexp = RegExp(source);
+ var replaceRegexp = RegExp(source, 'g');
+ return function(string) {
+ string = string == null ? '' : '' + string;
+ return testRegexp.test(string) ? string.replace(replaceRegexp, escaper) : string;
+ };
+ };
+ _.escape = createEscaper(escapeMap);
+ _.unescape = createEscaper(unescapeMap);
+
+ // If the value of the named `property` is a function then invoke it with the
+ // `object` as context; otherwise, return it.
+ _.result = function(object, property, fallback) {
+ var value = object == null ? void 0 : object[property];
+ if (value === void 0) {
+ value = fallback;
+ }
+ return _.isFunction(value) ? value.call(object) : value;
+ };
+
+ // Generate a unique integer id (unique within the entire client session).
+ // Useful for temporary DOM ids.
+ var idCounter = 0;
+ _.uniqueId = function(prefix) {
+ var id = ++idCounter + '';
+ return prefix ? prefix + id : id;
+ };
+
+ // By default, Underscore uses ERB-style template delimiters, change the
+ // following template settings to use alternative delimiters.
+ _.templateSettings = {
+ evaluate : /<%([\s\S]+?)%>/g,
+ interpolate : /<%=([\s\S]+?)%>/g,
+ escape : /<%-([\s\S]+?)%>/g
+ };
+
+ // When customizing `templateSettings`, if you don't want to define an
+ // interpolation, evaluation or escaping regex, we need one that is
+ // guaranteed not to match.
+ var noMatch = /(.)^/;
+
+ // Certain characters need to be escaped so that they can be put into a
+ // string literal.
+ var escapes = {
+ "'": "'",
+ '\\': '\\',
+ '\r': 'r',
+ '\n': 'n',
+ '\u2028': 'u2028',
+ '\u2029': 'u2029'
+ };
+
+ var escaper = /\\|'|\r|\n|\u2028|\u2029/g;
+
+ var escapeChar = function(match) {
+ return '\\' + escapes[match];
+ };
+
+ // JavaScript micro-templating, similar to John Resig's implementation.
+ // Underscore templating handles arbitrary delimiters, preserves whitespace,
+ // and correctly escapes quotes within interpolated code.
+ // NB: `oldSettings` only exists for backwards compatibility.
+ _.template = function(text, settings, oldSettings) {
+ if (!settings && oldSettings) settings = oldSettings;
+ settings = _.defaults({}, settings, _.templateSettings);
+
+ // Combine delimiters into one regular expression via alternation.
+ var matcher = RegExp([
+ (settings.escape || noMatch).source,
+ (settings.interpolate || noMatch).source,
+ (settings.evaluate || noMatch).source
+ ].join('|') + '|$', 'g');
+
+ // Compile the template source, escaping string literals appropriately.
+ var index = 0;
+ var source = "__p+='";
+ text.replace(matcher, function(match, escape, interpolate, evaluate, offset) {
+ source += text.slice(index, offset).replace(escaper, escapeChar);
+ index = offset + match.length;
+
+ if (escape) {
+ source += "'+\n((__t=(" + escape + "))==null?'':_.escape(__t))+\n'";
+ } else if (interpolate) {
+ source += "'+\n((__t=(" + interpolate + "))==null?'':__t)+\n'";
+ } else if (evaluate) {
+ source += "';\n" + evaluate + "\n__p+='";
+ }
+
+ // Adobe VMs need the match returned to produce the correct offest.
+ return match;
+ });
+ source += "';\n";
+
+ // If a variable is not specified, place data values in local scope.
+ if (!settings.variable) source = 'with(obj||{}){\n' + source + '}\n';
+
+ source = "var __t,__p='',__j=Array.prototype.join," +
+ "print=function(){__p+=__j.call(arguments,'');};\n" +
+ source + 'return __p;\n';
+
+ try {
+ var render = new Function(settings.variable || 'obj', '_', source);
+ } catch (e) {
+ e.source = source;
+ throw e;
+ }
+
+ var template = function(data) {
+ return render.call(this, data, _);
+ };
+
+ // Provide the compiled source as a convenience for precompilation.
+ var argument = settings.variable || 'obj';
+ template.source = 'function(' + argument + '){\n' + source + '}';
+
+ return template;
+ };
+
+ // Add a "chain" function. Start chaining a wrapped Underscore object.
+ _.chain = function(obj) {
+ var instance = _(obj);
+ instance._chain = true;
+ return instance;
+ };
+
+ // OOP
+ // ---------------
+ // If Underscore is called as a function, it returns a wrapped object that
+ // can be used OO-style. This wrapper holds altered versions of all the
+ // underscore functions. Wrapped objects may be chained.
+
+ // Helper function to continue chaining intermediate results.
+ var result = function(instance, obj) {
+ return instance._chain ? _(obj).chain() : obj;
+ };
+
+ // Add your own custom functions to the Underscore object.
+ _.mixin = function(obj) {
+ _.each(_.functions(obj), function(name) {
+ var func = _[name] = obj[name];
+ _.prototype[name] = function() {
+ var args = [this._wrapped];
+ push.apply(args, arguments);
+ return result(this, func.apply(_, args));
+ };
+ });
+ };
+
+ // Add all of the Underscore functions to the wrapper object.
+ _.mixin(_);
+
+ // Add all mutator Array functions to the wrapper.
+ _.each(['pop', 'push', 'reverse', 'shift', 'sort', 'splice', 'unshift'], function(name) {
+ var method = ArrayProto[name];
+ _.prototype[name] = function() {
+ var obj = this._wrapped;
+ method.apply(obj, arguments);
+ if ((name === 'shift' || name === 'splice') && obj.length === 0) delete obj[0];
+ return result(this, obj);
+ };
+ });
+
+ // Add all accessor Array functions to the wrapper.
+ _.each(['concat', 'join', 'slice'], function(name) {
+ var method = ArrayProto[name];
+ _.prototype[name] = function() {
+ return result(this, method.apply(this._wrapped, arguments));
+ };
+ });
+
+ // Extracts the result from a wrapped and chained object.
+ _.prototype.value = function() {
+ return this._wrapped;
+ };
+
+ // Provide unwrapping proxy for some methods used in engine operations
+ // such as arithmetic and JSON stringification.
+ _.prototype.valueOf = _.prototype.toJSON = _.prototype.value;
+
+ _.prototype.toString = function() {
+ return '' + this._wrapped;
+ };
+
+ // AMD registration happens at the end for compatibility with AMD loaders
+ // that may not enforce next-turn semantics on modules. Even though general
+ // practice for AMD registration is to be anonymous, underscore registers
+ // as a named module because, like jQuery, it is a base library that is
+ // popular enough to be bundled in a third party lib, but not be part of
+ // an AMD load request. Those cases could generate an error when an
+ // anonymous define() is called outside of a loader request.
+ if (typeof define === 'function' && define.amd) {
+ define('underscore', [], function() {
+ return _;
+ });
+ }
+}.call(this));
--- a/src/ldt/ldt/static/ldt/metadataplayer/Annotation.js Fri Sep 18 16:10:29 2015 +0200
+++ b/src/ldt/ldt/static/ldt/metadataplayer/Annotation.js Fri Oct 02 10:24:05 2015 +0200
@@ -179,6 +179,9 @@
this.onMdpEvent("Annotation.maximize","maximize");
this.onMdpEvent("Annotation.getBounds","sendBounds");
this.$.find(".Ldt-Annotation-MaxMinButton").click(this.functionWrapper("toggleSize"));
+ this.$.on("resize", function () { _this.width = _this.$.parent().width();
+ _this.$.css({ width: _this.width });
+ });
this.getWidgetAnnotations().forEach(function(_a) {
_a.on("enter", function() {
drawAnnotation(_a);
@@ -194,7 +197,8 @@
image: currentAnnotation.thumbnail,
uri: (typeof currentAnnotation.url !== "undefined"
? currentAnnotation.url
- : (document.location.href.replace(/#.*$/,'') + '#id=' + currentAnnotation.id))
+ : (document.location.href.replace(/#.*$/,'') + '#id=' + currentAnnotation.id)),
+ text: '[' + currentAnnotation.begin.toString() + '] ' + currentAnnotation.title
};
});
};
--- a/src/ldt/ldt/static/ldt/metadataplayer/AnnotationsList.css Fri Sep 18 16:10:29 2015 +0200
+++ b/src/ldt/ldt/static/ldt/metadataplayer/AnnotationsList.css Fri Oct 02 10:24:05 2015 +0200
@@ -8,7 +8,6 @@
.Ldt-AnnotationsListWidget {
border: none; margin: 0; padding: 0;
overflow: auto;
- max-height: 380px;
}
.Ldt-AnnotationsListWidget a {
text-decoration: none;
@@ -56,7 +55,8 @@
clear: both;
margin: 2px 0;
padding: 2px 0;
- min-height: 60px;
+ min-height: 3em;
+ position: relative;
}
.Ldt-AnnotationsList-li.selected {
background-image: url(img/pinstripe-grey.png);
@@ -66,7 +66,8 @@
width: 80px;
height: 50px;
text-align: center;
- margin: 2px 0;
+ margin: 10px 2px;
+ box-shadow: #808080 0px 0px 2px;
}
.Ldt-AnnotationsList-Thumbnail {
border: none;
@@ -113,6 +114,10 @@
color: #0068c4;
}
+.Ldt-AnnotationsList-Creator {
+ color: #aaa;
+}
+
p.Ldt-AnnotationsList-Description {
margin: 2px 0 2px 82px;
font-size: 12px;
@@ -162,6 +167,50 @@
background-position: 0 bottom;
}
+.Ldt-AnnotationsList-EditControls {
+ opacity: 0;
+ position: absolute;
+ bottom: 2px;
+ right: 8px;
+}
+
+.Ldt-AnnotationsList-li:hover .Ldt-AnnotationsList-EditControls {
+ display: inline-block;
+ opacity: .8;
+ transition: opacity 1000ms ease-in-out;
+}
+
+.Ldt-AnnotationsList-EditControls > div {
+ display: inline-block;
+ width: 16px;
+ height: 16px;
+ cursor: pointer;
+ margin-left: 8px;
+}
+
+.Ldt-AnnotationsList-Delete {
+ background: url(img/delete.png);
+}
+
+.Ldt-AnnotationsList-Edit {
+ background: url(img/edit.png);
+}
+
+.Ldt-AnnotationsList-PublishAnnotation {
+ background: url(img/publish_annotation.png);
+}
+
+.published .Ldt-AnnotationsList-PublishAnnotation {
+ background: url(img/published_annotation.png);
+}
+
+.editing {
+ display: none;
+}
+
+.editableInput {
+ width: 80%;
+
.Ldt-AnnotationsList-ScreenMain{
margin: 0px;
padding: 0px;
--- a/src/ldt/ldt/static/ldt/metadataplayer/AnnotationsList.js Fri Sep 18 16:10:29 2015 +0200
+++ b/src/ldt/ldt/static/ldt/metadataplayer/AnnotationsList.js Fri Oct 02 10:24:05 2015 +0200
@@ -2,11 +2,12 @@
IriSP.Widgets.Widget.call(this, player, config);
this.lastIds = [];
var _this = this;
- this.throttledRefresh = IriSP._.throttle(function() {
- _this.refresh(false);
+ this.throttledRefresh = IriSP._.throttle(function(full) {
+ _this.refresh(full);
}, 800);
this.searchString = false;
this.lastSearch = false;
+ this.localSource = undefined;
};
IriSP.Widgets.AnnotationsList.prototype = new IriSP.Widgets.Widget();
@@ -25,7 +26,7 @@
* number of milliseconds before/after the current timecode when calling the
* segment API
*/
- ajax_granularity : 600000,
+ ajax_granularity : 600000,
default_thumbnail : "",
/*
* URL when the annotation is not in the current project, e.g.
@@ -36,6 +37,25 @@
refresh_interval : 0,
limit_count : 20,
newest_first : false,
+ show_title: true,
+ show_audio: true,
+ show_creator: true,
+ show_controls: false,
+ show_end_time: true,
+ show_publish: false,
+ show_twitter: false,
+ twitter_hashtag: '',
+ // Callback for Edit action. Leave undefined for default action.
+ on_edit: undefined,
+ publish_type: "PublicContribution",
+ // Used to publish annotations
+ api_endpoint_template: "",
+ api_serializer: "ldt_annotate",
+ api_method: "POST",
+ editable: false,
+ // Id that will be used as localStorage key
+ editable_storage: "",
+
always_visible : false,
start_visible: true,
show_audio : true,
@@ -51,6 +71,7 @@
annotations_count_header : true,
show_creation_date : false,
show_timecode : true,
+ project_id: "",
/*
* Only annotation in the current segment will be displayed. Designed to work with the Segments Widget.
*/
@@ -76,6 +97,7 @@
* Show a text field that filter annotations by username
*/
tags : true,
+
polemics : [{
keyword: "++",
background_color: "#c9ecc6"
@@ -92,12 +114,12 @@
};
IriSP.Widgets.AnnotationsList.prototype.importUsers = function(){
- if (!this.source.users_data){
+ if (!this.source.users_data && this.api_users_endpoint){
this.usernames = Array();
var _this = this,
_list = this.getWidgetAnnotations(),
usernames_list_string = "";
-
+
_list.forEach(function(_annotation){
if(_this.usernames.indexOf(_annotation.creator) == -1){
_this.usernames.push(_annotation.creator);
@@ -128,6 +150,16 @@
en: {
voice_annotation: "Voice Annotation",
now_playing: "Now playing...",
+ previous: "Previous",
+ next: "Next",
+ set_time: "Double-click to update to current player time",
+ edit_annotation: "Edit note",
+ delete_annotation: "Delete note",
+ publish_annotation: "Make note public",
+ import_annotations: "Paste or load notes in this field and press Import.",
+ confirm_delete_message: "You are about to delete {{ annotation.title }}. Are you sure you want to delete it?",
+ confirm_publish_message: "You are about to publish {{ annotation.title }}. Are you sure you want to make it public?",
+ tweet_annotation: "Tweet annotation",
everyone: "Everyone",
header: "Annotations for this content",
segment_filter: "All cuttings",
@@ -143,6 +175,16 @@
fr: {
voice_annotation: "Annotation Vocale",
now_playing: "Lecture en cours...",
+ previous: "Précédent",
+ next: "Suivant",
+ set_time: "Double-cliquer pour fixer au temps du lecteur",
+ edit_annotation: "Éditer la note",
+ delete_annotation: "Supprimer la note",
+ publish_annotation: "Rendre la note publique",
+ import_annotations: "Copiez ou chargez des notes dans ce champ et appuyez sur Import",
+ confirm_delete_message: "Vous allez supprimer {{ annotation.title }}. Êtes-vous certain(e) ?",
+ confirm_publish_message: "Vous allez publier {{ annotation.title }}. Êtes-vous certain(e) ?",
+ tweet_annotation: "Tweeter l'annotation",
everyone: "Tous",
header: "Annotations sur ce contenu",
segment_filter: "Tous les segments",
@@ -173,61 +215,69 @@
+ '{{#latest_contributions_filter}}<label class="Ldt-AnnotationsList-filter-checkbox"><input type="checkbox" id="Ldt-AnnotationsList-latestContributionsFilter">{{l10n.latest_contributions}}</label>{{/latest_contributions_filter}}'
+ '</div>'
+ '{{/show_filters}}'
+ + '{{#show_controls}}<div class="Ldt-AnnotationsList-Controls"><span class="Ldt-AnnotationsList-Control-Prev">{{ l10n.previous }}</span> | <span class="Ldt-AnnotationsList-Control-Next">{{ l10n.next }}</span></div>{{/show_controls}}'
+ '{{#show_audio}}<div class="Ldt-AnnotationsList-Audio"></div>{{/show_audio}}'
+ '<ul class="Ldt-AnnotationsList-ul">'
+ '</ul>'
+ '</div>'
+ '{{#allow_annotations_deletion}}'
- + '<div id="{{id}}" class="Ldt-AnnotationsList-Screen Ldt-AnnotationsList-ScreenDelete">'
+ + '<div data-annotation="{{id}}" class="Ldt-AnnotationsList-Screen Ldt-AnnotationsList-ScreenDelete">'
+ '<a title="{{l10n.close_widget}}" class="Ldt-AnnotationsList-Close" href="#"></a>'
+ '<ul class="Ldt-AnnotationsList-ul-ToDelete"></ul>'
+ '{{l10n.annotation_deletion_delete}} <a class="Ldt-AnnotationsList-ConfirmDelete">{{l10n.confirm}}</a> <a class="Ldt-AnnotationsList-CancelDelete">{{l10n.cancel}}</a>'
+ '</div>'
- + '<div id="{{id}}" class="Ldt-AnnotationsList-Screen Ldt-AnnotationsList-ScreenSending">'
+ + '<div data-annotation="{{id}}" class="Ldt-AnnotationsList-Screen Ldt-AnnotationsList-ScreenSending">'
+ '<a title="{{l10n.close_widget}}" class="Ldt-AnnotationsList-Close" href="#"></a>'
+ '{{l10n.annotation_deletion_sending}}'
+ '</div>'
- + '<div id="{{id}}" class="Ldt-AnnotationsList-Screen Ldt-AnnotationsList-ScreenSuccess">'
+ + '<div data-annotation="{{id}}" class="Ldt-AnnotationsList-Screen Ldt-AnnotationsList-ScreenSuccess">'
+ '<a title="{{l10n.close_widget}}" class="Ldt-AnnotationsList-Close" href="#"></a>'
+ '{{l10n.annotation_deletion_success}}'
+ '</div>'
- + '<div id="{{id}}" class="Ldt-AnnotationsList-Screen Ldt-AnnotationsList-ScreenError">'
+ + '<div data.annotation="{{id}}" class="Ldt-AnnotationsList-Screen Ldt-AnnotationsList-ScreenError">'
+ '<a title="{{l10n.close_widget}}" class="Ldt-AnnotationsList-Close" href="#"></a>'
+ '{{l10n.annotation_deletion_error}}'
+ '</div>'
+ '{{/allow_annotations_deletion}}'
+ '</div>';
-IriSP.Widgets.AnnotationsList.prototype.annotationTemplate =
- '<li class="Ldt-AnnotationsList-li Ldt-TraceMe" trace-info="annotation-id:{{id}}, media-id:{{media_id}}" style="{{specific_style}}">'
- + '<div id="{{id}}" class="Ldt-AnnotationsList-ThumbContainer Ldt-AnnotationsList-Annotation-Screen Ldt-AnnotationsList-Annotation-ScreenMain">'
- + '<a href="{{url}}" draggable="true">'
- + '<img class="Ldt-AnnotationsList-Thumbnail" src="{{thumbnail}}" />'
- + '</a>'
+IriSP.Widgets.AnnotationsList.prototype.annotationTemplate =
+ '<li class="Ldt-AnnotationsList-li Ldt-Highlighter-Annotation Ldt-TraceMe" data-annotation="{{ id }}" data-begin="{{ begin_ms }}" data-end="{{ end_ms }}" trace-info="annotation-id:{{id}}, media-id:{{media_id}}" style="{{specific_style}}">'
+ + '<div data-annotation="{{ id }}" class="Ldt-AnnotationsList-ThumbContainer Ldt-AnnotationsList-Annotation-Screen Ldt-AnnotationsList-Annotation-ScreenMain">'
+ + '<a href="{{url}}" draggable="true">'
+ + '<img title="{{ begin }} - {{ title }}" class="Ldt-AnnotationsList-Thumbnail" src="{{thumbnail}}" />'
+ + '</a>'
+ '</div>'
+ '{{#allow_annotations_deletion}}'
- + '<div id={{id}} class="Ldt-AnnotationsList-DeleteButton">✖</div>'
+ + '<div data-annotation="{{ id }}" class="Ldt-AnnotationsList-DeleteButton">✖</div>'
+ '{{/allow_annotations_deletion}}'
- + '{{#show_timecode}}<div class="Ldt-AnnotationsList-Duration">{{begin}} - {{end}}</div>{{/show_timecode}}'
- + '<h3 class="Ldt-AnnotationsList-Title" draggable="true">'
- + '<a {{#url}} href="{{url}}" {{/url}}>{{{htitle}}}</a>'
+ + '{{#show_timecode}}<div title="{{l10n.set_time}}" class="Ldt-AnnotationsList-Duration"><span class="Ldt-AnnotationsList-Begin Ldt-live-editable Ldt-AnnotationsList-TimeEdit" data-editable_value="{{begin}}" data-editable_id="{{id}}" data-editable_field="begin" data-editable_type="timestamp">{{begin}}</span>{{#show_end_time}} - <span class="Ldt-AnnotationsList-End Ldt-live-editable" data-editable_value="{{end}}" data-editable_id="{{id}}" data-editable_field="end" data-editable_type="timestamp">{{end}}</span>{{/show_end_time}}</div>{{/show_timecode}}'
+ + '<h3 class="Ldt-AnnotationsList-Title Ldt-Annotation-Timecode" data-timecode="{{ begin_ms }}" draggable="true">'
+ + '{{#show_title}}<span class="Ldt-AnnotationsList-TitleContent Ldt-live-editable" data-editable_value="{{title}}" data-editable_type="multiline" data-editable_id="{{id}}" data-editable_field="title">{{{htitle}}}</span>{{/show_title}}'
+ + '{{#show_creator}}<span class="Ldt-AnnotationsList-Creator">{{ creator }}</span>{{/show_creator}}'
+ '</h3>'
- + '<p class="Ldt-AnnotationsList-Description">{{{hdescription}}}</p>'
+ + '<p class="Ldt-AnnotationsList-Description Ldt-live-editable" data-editable_type="multiline" data-editable_value="{{description}}" data-editable_id="{{id}}" data-editable_field="description">{{{hdescription}}}</p>'
+ '{{#created}}'
+ '<div class="Ldt-AnnotationsList-CreationDate">{{{created}}}</div>'
+ '{{/created}}'
+ '{{#tags.length}}'
+ '<ul class="Ldt-AnnotationsList-Tags">'
- + '{{#tags}}'
- + '{{#.}}'
- + '<li class="Ldt-AnnotationsList-Tag-Li">'
- + '<span>{{.}}</span>'
- + '</li>'
- + '{{/.}}'
- + '{{/tags}}'
+ + '{{#tags}}'
+ + '{{#.}}'
+ + '<li class="Ldt-AnnotationsList-Tag-Li">'
+ + '<span>{{.}}</span>'
+ + '</li>'
+ + '{{/.}}'
+ + '{{/tags}}'
+ '</ul>'
+ '{{/tags.length}}'
- + '{{#audio}}<div class="Ldt-AnnotationsList-Play" data-annotation-id="{{id}}">{{l10n.voice_annotation}}</div>{{/audio}}'
+ + '{{#audio}}<div class="Ldt-AnnotationsList-Play" data-annotation-id="{{id}}">{{l10n.voice_annotation}}</div>{{/audio}}'
+ + '<div class="Ldt-AnnotationsList-EditControls">'
+ + '{{#show_twitter}}<a title="{{l10n.tweet_annotation}}" target="_blank" href="https://twitter.com/intent/tweet?{{twitter_param}}"><img width="16" height="16" src="metadataplayer/img/twitter.svg"></a>{{/show_twitter}}'
+ + '{{#show_publish}}<div title="{{l10n.publish_annotation}}" class="Ldt-AnnotationsList-PublishAnnotation" data-editable_id="{{id}}"></div>{{/show_publish}}'
+ + '{{#editable}}<div title="{{l10n.edit_annotation}}" class="Ldt-AnnotationsList-Edit" data-editable_id="{{id}}"></div>'
+ + '<div title="{{l10n.delete_annotation}}" class="Ldt-AnnotationsList-Delete" data-editable_id="{{id}}"></div>{{/editable}}'
+ + '</div>'
+ '</li>';
// obj.url = this.project_url + "/" + media + "/" + annotations[i].meta.project
@@ -269,6 +319,78 @@
}
};
+/*
+ * Import annotations
+ */
+IriSP.Widgets.AnnotationsList.prototype.importAnnotations = function () {
+ var widget = this;
+ var $ = IriSP.jQuery;
+ var textarea = $("<textarea>");
+ var el = $("<div>")
+ .append($("<span>")
+ .addClass("importAnnotationsLabel")
+ .text(widget.messages.import_annotations))
+ .addClass("importContainer")
+ .dialog({
+ title: "Annotation import",
+ autoOpen: true,
+ width: '80%',
+ minHeight: '400',
+ height: 400,
+ buttons: [ { text: "Close", click: function() { $( this ).dialog( "close" ); } },
+ // { text: "Load", click: function () {
+ // // TODO
+ // // http://www.html5rocks.com/en/tutorials/file/dndfiles/?redirect_from_locale=fr
+ // console.log("Load from a file");
+ // } },
+ { text: "Import", click: function () {
+ // FIXME: this should be a model.Source method
+ var time_regexp = /(\[[\d:]+\])/;
+ console.log("Import data");
+ // widget.localSource
+ // Dummy parsing for the moment
+ var data = textarea[0].value
+ .split(time_regexp)
+ .filter( function (s) { return ! s.match(/^\s*$/)});
+ var begin = null,
+ end = null,
+ content = null,
+ // Previous is either null, timestamp or text
+ previous = null;
+ for (var i = 0; i < data.length; i++) {
+ var el = data[i];
+ if (el.match(time_regexp)) {
+ if (previous == 'text') {
+ // Timestamp following text. Let's make it an annotation
+ end = IriSP.timestamp2ms(el.slice(1, -1));
+ TODO.createAnnotation(begin, end, content);
+ // Preserve the end value, which may be the begin value of the next annotation.
+ begin = end;
+ end = null;
+ content = null;
+ } else {
+ // (previous == 'timestamp' || previous == null)
+ // 2 consecutive timestamps. Let's start a new annotation
+ content = null;
+ begin = IriSP.timestamp2ms(el.slice(1, -1));
+ end = null;
+ };
+ previous = 'timestamp';
+ } else {
+ // Text content
+ content = el;
+ previous = 'text';
+ }
+ // Last textual value
+ if (previous == 'text' && begin !== null) {
+ TODO.createAnnotation(begin, begin, content);
+ }
+ }
+ } } ]
+ });
+
+}
+
IriSP.Widgets.AnnotationsList.prototype.refresh = function(_forceRedraw) {
_forceRedraw = (typeof _forceRedraw !== "undefined" && _forceRedraw);
if (this.currentSource.status !== IriSP.Model._SOURCE_STATUS_READY) {
@@ -389,7 +511,7 @@
}
var _ids = _list.idIndex;
-
+
if (_forceRedraw || !IriSP._.isEqual(_ids, this.lastIds) || this.searchString !== this.lastSearch) {
/* This part only gets executed if the list needs updating */
this.lastSearch = this.searchString;
@@ -410,33 +532,33 @@
annotationType : _annotation.annotationType.id
}
)
- : document.location.href.replace(/#.*$/,'') + '#id=' + _annotation.id
+ : document.location.href.replace(/#.*$/,'') + '#id=' + _annotation.id + '&t=' + (_annotation.begin / 1000.0)
)
);
var _title = "",
_description = _annotation.description,
- _thumbnail = (typeof _annotation.thumbnail !== "undefined" && _annotation.thumbnail ? _annotation.thumbnail : _this.default_thumbnail)
-
- // Update : display creator
- if (_annotation.creator) {
- var _users = _this.source.users_data.filter(function(_user_data){
- return _user_data.username == _annotation.creator
- }),
- _user = {};
- if (_users.length == 0){
- _user.username = _annotation.creator
+ _thumbnail = (typeof _annotation.thumbnail !== "undefined" && _annotation.thumbnail ? _annotation.thumbnail : _this.default_thumbnail);
+ if (_this.show_creator){
+ if (_annotation.creator) {
+ var _users = [],
+ _user = {},
+ _creator = "";
+ if (_this.source.users_data) {
+ _users = _this.source.users_data.filter(function(_user_data){
+ return _user_data.username == _annotation.creator;
+ });
+ }
+ if (_users.length == 0){
+ _user.username = _annotation.creator
+ }
+ else{
+ _user = _users[0]
+ }
+ _creator = _this.make_name_string_function(_user);
}
- else{
- _user = _users[0]
- }
- _title = _this.make_name_string_function(_user);
}
- if (_annotation.title) {
- var tempTitle = _annotation.title;
- if( tempTitle.substr(0, _title.length + 1) == (_title + ":") ){
- _title = "";
- }
- _title = _title + ( (_title=="") ? "" : ": ") + _annotation.title;
+ if (_this.show_title && _annotation.title){
+ var _title = _annotation.title;
}
var _bgcolor;
IriSP._(_this.polemics).each(function(_polemic) {
@@ -459,7 +581,10 @@
id : _annotation.id,
media_id : _annotation.getMedia().id,
htitle : IriSP.textFieldHtml(_title),
+ title: _title,
+ creator: _creator,
hdescription : IriSP.textFieldHtml(_description),
+ description: _description,
begin : _annotation.begin.toString(),
end : _annotation.end.toString(),
created : _created,
@@ -469,6 +594,11 @@
tags : _tags,
specific_style : (typeof _bgcolor !== "undefined" ? "background-color: " + _bgcolor : ""),
l10n: _this.l10n,
+ editable: _this.editable,
+ show_publish: _this.show_publish,
+ show_creator: _this.show_creator,
+ show_twitter: _this.show_twitter,
+ twitter_param: IriSP.jQuery.param({ url: _url, text: IriSP.textFieldHtml(_title) + (_this.twitter_hashtag ? ' #' + _this.twitter_hashtag : "") }),
allow_annotations_deletion: _this.allow_annotations_deletion
};
if (_this.show_audio && _annotation.audio && _annotation.audio.href && _annotation.audio.href != "null") {
@@ -520,10 +650,11 @@
})
.appendTo(_this.list_$);
IriSP.attachDndData(_el.find("[draggable]"), {
- title: _title,
- description: _description,
- uri: _url,
- image: _annotation.thumbnail
+ title: _title,
+ description: _description,
+ uri: _url,
+ image: _annotation.thumbnail,
+ text: '[' + _annotation.begin.toString() + '] ' + _title
});
_el.on("remove", function() {
_annotation.off("select", _onselect);
@@ -532,7 +663,7 @@
_annotation.on("select", _onselect);
_annotation.on("unselect", _onunselect);
});
-
+
/* Correct the empty tag bug */
this.$.find('.Ldt-AnnotationsList-Tag-Li').each(function() {
var _el = IriSP.jQuery(this);
@@ -540,11 +671,201 @@
_el.remove();
}
});
-
+
+ if (this.editable) {
+ var widget = _this;
+ var $ = IriSP.jQuery;
+
+ var edit_element = function (_this, insertion_point) {
+ var feedback_wrong = "#FF9999";
+ var feedback_ok = "#99FF99";
+
+ // insertion_point can be used to specify where to
+ // insert the input field. Firefox is buggy wrt input
+ // fields inside <a> or <h?> tags, it does not
+ // propagate mouse clicks. If _this is a <a> then we
+ // have to specify the ancestor before which we can
+ // insert the input widget.
+ if (insertion_point === undefined)
+ insertion_point = _this;
+
+ // Insert input element
+ var input_element = $(_this.dataset.editable_type === 'multiline' ? "<textarea>" : "<input>")
+ .addClass("editableInput")
+ .insertBefore($(insertion_point));
+ input_element[0].value = _this.dataset.editable_value;
+ $(input_element).show().focus();
+ $(_this).addClass("editing");
+
+ function feedback(color) {
+ // Give some feedback
+ $(_this).removeClass("editing");
+ input_element.remove();
+ var previous_color = $(_this).css("background-color");
+ $(_this).stop().css("background-color", color)
+ .animate({ backgroundColor: previous_color}, 1000);
+ }
+
+ function cancelChanges(s) {
+ feedback(feedback_wrong);
+ }
+ function validateChanges() {
+ var n = input_element[0].value;
+ if (n == _this.dataset.editable_value) {
+ // No change
+ feedback(feedback_ok);
+ return;
+ }
+ if (n == '') {
+ // Delete annotation
+ delete_local_annotation(_this.dataset.editable_id);
+ widget.player.trigger("Annotation.delete", _this.dataset.editable_id);
+ return;
+ } else {
+ // Convert value if necessary.
+ var val = n;
+ if (_this.dataset.editable_type == 'timestamp') {
+ val = IriSP.timestamp2ms(n);
+ if (Number.isNaN(val)) {
+ // Invalid value. Cancel changes
+ cancelChanges();
+ return;
+ }
+ }
+ _this.dataset.editable_value = n;
+ n = val;
+ $(_this).text(val);
+ }
+
+ // We cannot use .getElement since it fetches
+ // elements from the global Directory
+ var an = get_local_annotation(_this.dataset.editable_id);
+ if (an === undefined) {
+ console.log("Strange error: cannot find edited annotation");
+ feedback(feedback_wrong);
+ } else {
+ _this.dataset.editable_value = n;
+ // Update annotation for storage
+ if (_this.dataset.editable_field == 'begin')
+ an.setBegin(n);
+ else if (_this.dataset.editable_field == 'end')
+ an.setEnd(n);
+ else
+ an[_this.dataset.editable_field] = n;
+ an.modified = new Date();
+ // FIXME: use user name, when available
+ an.contributor = widget.player.config.username || "COCo User";
+ widget.player.addLocalAnnotation(an);
+ widget.player.trigger("Annotation.update", an);
+ feedback(feedback_ok);
+ }
+ }
+ $(input_element).bind('keydown', function(e) {
+ if (e.which == 13) {
+ e.preventDefault();
+ validateChanges();
+ } else if (e.which == 27) {
+ e.preventDefault();
+ cancelChanges();
+ }
+ }).bind("blur", function (e) {
+ validateChanges();
+ });
+ };
+
+ var get_local_annotation = function (ident) {
+ return widget.player.getLocalAnnotation(ident);
+ };
+
+ var save_local_annotations = function() {
+ widget.player.saveLocalAnnotations();
+ // Merge modifications into widget source
+ widget.source.merge(widget.player.localSource);
+ };
+
+ var delete_local_annotation = function(ident) {
+ widget.source.getAnnotations().removeId(ident, true);
+ widget.player.deleteLocalAnnotation(ident);
+ widget.refresh(true);
+ };
+
+ this.$.find('.Ldt-AnnotationsList-Delete').click(function(e) {
+ // Delete annotation
+ var _annotation = get_local_annotation(this.dataset.editable_id);
+ if (confirm(Mustache.to_html(widget.l10n.confirm_delete_message, { annotation: _annotation })))
+ delete_local_annotation(this.dataset.editable_id);
+ widget.refresh(true);
+ });
+ this.$.find('.Ldt-AnnotationsList-Edit').click(function(e) {
+ if (widget.on_edit) {
+ var _annotation = get_local_annotation(this.dataset.editable_id);
+ widget.on_edit(_annotation);
+ } else {
+ // Edit annotation title. We have to specify the insertion point.
+ var element = $(this).parents(".Ldt-AnnotationsList-li").find(".Ldt-AnnotationsList-TitleContent.Ldt-live-editable");
+ edit_element(element[0]);
+ }
+ });
+ this.$.find('.Ldt-AnnotationsList-PublishAnnotation').click(function(e) {
+ var _annotation = get_local_annotation(this.dataset.editable_id);
+ // Publish annotation to the server
+ if (!confirm(Mustache.to_html(widget.l10n.confirm_publish_message, { annotation: _annotation })))
+ return;
+ var _url = Mustache.to_html(widget.api_endpoint_template, {id: widget.source.projectId});
+ if (_url !== "") {
+ var _export = widget.player.sourceManager.newLocalSource({serializer: IriSP.serializers[widget.api_serializer]});
+
+ if (widget.publish_type) {
+ // If publish_type is specified, try to set the annotation type of the exported annotation
+ var at = widget.source.getAnnotationTypes().filter(function(at) { return at.title == widget.publish_type; });
+ if (at.length == 1) {
+ _annotation.setAnnotationType(at[0].id);
+ }
+ }
+ var _exportedAnnotations = new IriSP.Model.List(widget.player.sourceManager);
+ _exportedAnnotations.push(_annotation);
+ _export.addList("annotation", _exportedAnnotations);
+ IriSP.jQuery.ajax({
+ url: _url,
+ type: widget.api_method,
+ contentType: 'application/json',
+ data: _export.serialize(),
+ success: function(_data) {
+ $(this).addClass("published");
+ // Save the published information
+ var an = get_local_annotation(_annotation.id);
+ // FIXME: handle "published" tag
+ an.setTags( [ "published" ]);
+ save_local_annotations();
+ widget.player.trigger("Annotation.publish", _annotation);
+ },
+ error: function(_xhr, _error, _thrown) {
+ IriSP.log("Error when sending annotation", _thrown);
+ }
+ });
+ }
+ });
+ this.$.find('.Ldt-AnnotationsList-TimeEdit').dblclick(function(e) {
+ var _this = this;
+ // Use current player time
+ var an = get_local_annotation(_this.dataset.editable_id);
+ if (an !== undefined) {
+ // FIXME: implement Undo feature
+ an.setBegin(widget.media.getCurrentTime().milliseconds);
+ save_local_annotations();
+ widget.player.trigger("Annotation.update", an);
+ widget.refresh(true);
+ }
+ });
+ };
+
this.$.find('.Ldt-AnnotationsList-Tag-Li').click(function() {
_this.source.getAnnotations().search(IriSP.jQuery(this).text().replace(/(^\s+|\s+$)/g,''));
});
-
+ this.$.find('.Ldt-Annotation-Timecode').click(function () {
+ _this.media.setCurrentTime(Number(this.dataset.timecode));
+ });
+
this.$.find(".Ldt-AnnotationsList-Play").click(function() {
var _el = IriSP.jQuery(this),
_annid = _el.attr("data-annotation-id");
@@ -553,7 +874,7 @@
}
_this.media.pause();
});
-
+
if (this.source.getAnnotations().searching) {
var rx = _this.source.getAnnotations().regexp || false;
this.$.find(".Ldt-AnnotationsList-Title a, .Ldt-AnnotationsList-Description").each(function() {
@@ -564,7 +885,7 @@
this.$.find(".Ldt-AnnotationsList-DeleteButton").click(_this.functionWrapper("onDeleteClick"))
}
-
+
if (this.ajax_url) {
if (this.mashupMode) {
this.ajaxMashup();
@@ -580,7 +901,7 @@
IriSP.Widgets.AnnotationsList.prototype.onDeleteClick = function(event){
- ann_id = event.target.id;
+ ann_id = event.target.dataset.annotation;
delete_preview_$ = this.$.find(".Ldt-AnnotationsList-ul-ToDelete");
delete_preview_$.html("");
_list = this.getWidgetAnnotations()
@@ -591,10 +912,13 @@
_title = "",
_this = this;
if (_annotation.creator) {
- var _users = _this.source.users_data.filter(function(_user_data){
- return _user_data.username == _annotation.creator
- }),
+ var _users = [],
_user = {};
+ if (_this.source.users_data) {
+ _users = _this.source.users_data.filter(function(_user_data){
+ return _user_data.username == _annotation.creator;
+ });
+ }
if (_users.length == 0){
_user.username = _annotation.creator
}
@@ -684,7 +1008,7 @@
IriSP.Widgets.AnnotationsList.prototype.sendDelete = function(id){
var _this = this,
- _url = Mustache.to_html(this.api_delete_endpoint, {annotation_id: id})
+ _url = Mustache.to_html(this.api_delete_endpoint, {annotation_id: id, project_id: this.project_id})
IriSP.jQuery.ajax({
url: _url,
@@ -708,11 +1032,10 @@
IriSP.Widgets.AnnotationsList.prototype.draw = function() {
this.jwplayers = {};
this.mashupMode = (this.media.elementType === "mashup");
-
+
this.renderTemplate();
-
+
var _this = this;
-
this.list_$ = this.$.find(".Ldt-AnnotationsList-ul");
this.widget_$ = this.$.find(".Ldt-AnnotationsListWidget");
@@ -724,7 +1047,17 @@
});
this.userselect_$.html("<option selected value='false'>"+this.l10n.everyone+"</option>");
this.usernames.forEach(function(_user){
- _this.userselect_$.append("<option value='"+_user+"'>"+_user+"</option>");
+ var _users = _this.source.users_data.filter(function(_user_data){
+ return _user_data.username == _user;
+ }),
+ _user_data = {};
+ if (_users.length == 0){
+ _user_data.username = _user;
+ }
+ else{
+ _user_data = _users[0];
+ }
+ _this.userselect_$.append("<option value='"+_user+"'>"+_this.make_name_string_function(_user_data)+"</option>");
});
}
if (this.keyword_filter){
@@ -786,7 +1119,7 @@
this.source.getAnnotations().on("search-cleared", function() {
_this.throttledRefresh();
});
-
+
this.onMdpEvent("AnnotationsList.refresh", function() {
if (_this.ajax_url) {
if (_this.mashupMode) {
@@ -795,9 +1128,20 @@
_this.ajaxSource();
}
}
- _this.throttledRefresh();
+ _this.throttledRefresh(false);
});
-
+
+ this.onMdpEvent("AnnotationsList.update", function() {
+ if (_this.ajax_url) {
+ if (_this.mashupMode) {
+ _this.ajaxMashup();
+ } else {
+ _this.ajaxSource();
+ }
+ }
+ _this.throttledRefresh(true);
+ });
+
if (this.ajax_url) {
if (this.mashupMode) {
this.ajaxMashup();
@@ -807,7 +1151,7 @@
} else {
this.currentSource = this.source;
}
-
+
if (this.refresh_interval) {
window.setInterval(function() {
_this.currentSource.get();
@@ -832,7 +1176,7 @@
for (var _i = 0; _i < _events.length; _i++) {
this.onMediaEvent(_events[_i], this.throttledRefresh);
}
-
+
this.throttledRefresh();
this.showScreen("Main");
--- a/src/ldt/ldt/static/ldt/metadataplayer/Controller.css Fri Sep 18 16:10:29 2015 +0200
+++ b/src/ldt/ldt/static/ldt/metadataplayer/Controller.css Fri Oct 02 10:24:05 2015 +0200
@@ -1,176 +1,248 @@
/* Player Widget */
.Ldt-Ctrl {
- font-size: 10px;
- background:url('img/player_gradient.png') repeat-x transparent ;
- height: 25px;
- border: 1px solid #b6b8b8;
- position: relative;
+ font-size: 10px;
+ background: url('img/player_gradient.png') repeat-x transparent ;
+ height: 25px;
+ border: 1px solid #b6b8b8;
+ position: relative;
+ overflow: hidden;
}
.Ldt-Ctrl-Left {
- float:left; width: 300px;
+ float: left;
}
.Ldt-Ctrl-Right {
- float: right;
+ float: right;
}
.Ldt-Ctrl-button {
- float: left;
- width: 30px; height: 25px;
- background: url('img/player-sprites.png');
- cursor: pointer;
+ float: left;
+ width: 30px;
+ height: 25px;
+ background: url('img/player-sprites.png');
+ cursor: pointer;
}
.Ldt-Ctrl-spacer {
- float: left; width: 1px; height: 25px; background: #b6b8b8;
+ float: left;
+ width: 1px;
+ height: 25px;
+ background: #b6b8b8;
}
.Ldt-Ctrl-Play {
- margin: 0 15px;
+ margin: 100px 0;
+ margin: 0 15px;
}
.Ldt-Ctrl-Play-PlayState {
- background-position: 0 0;
+ background-position: 0 0;
}
.Ldt-Ctrl-Play-PlayState:hover {
- background-position: 0 -25px;
+ background-position: 0 -25px;
}
.Ldt-Ctrl-Play-PlayState:active {
- background-position: 0 -50px;
+ background-position: 0 -50px;
}
.Ldt-Ctrl-Play-PauseState {
- background-position: -30px 0;
+ background-position: -30px 0;
}
.Ldt-Ctrl-Play-PauseState:hover {
- background-position: -30px -25px;
+ background-position: -30px -25px;
}
.Ldt-Ctrl-Play-PauseState:active {
- background-position: -30px -50px;
+ background-position: -30px -50px;
}
.Ldt-Ctrl-Annotate {
- margin: 0 2px;
- background-position: -60px 0;
+ margin: 0 2px;
+ background-position: -60px 0;
}
.Ldt-Ctrl-Annotate:hover {
- background-position: -60px -25px;
+ background-position: -60px -25px;
}
.Ldt-Ctrl-Annotate:active {
- background-position: -60px -50px;
+ background-position: -60px -50px;
}
.Ldt-Ctrl-SearchBtn {
- margin: 0 2px;
- background-position: -90px 0;
+ margin: 0 2px;
+ background-position: -90px 0;
}
.Ldt-Ctrl-SearchBtn:hover {
- background-position: -90px -25px;
+ background-position: -90px -25px;
}
.Ldt-Ctrl-SearchBtn:active {
- background-position: -90px -50px;
+ background-position: -90px -50px;
}
.Ldt-Ctrl-Search {
- width: 0; float: left; overflow: hidden;
+ width: 0; float: left; overflow: hidden;
}
input.Ldt-Ctrl-SearchInput {
- width: 145px; height: 20px; margin: 2px; padding: 3px;
- border: 1px solid #8080a0; border-radius: 3px; font-size: 13px;
+ -moz-box-sizing: border-box;
+ width: 145px;
+ height: 20px;
+ margin: 2px;
+ padding: 3px;
+ border: 1px solid #8080a0;
+ border-radius: 3px;
+ font-size: 13px;
}
.Ldt-Ctrl-Time {
- float: left;
- margin: 5px;
- font-size: 12px;
- font-family: Arial, Verdana, sans-serif;
+ float: left;
+ margin: 5px;
+ font-size: 12px;
+ font-family: Arial, Verdana, sans-serif;
}
.Ldt-Ctrl-Time-Elapsed {
- float: left;
- color: #4a4a4a;
+ float: left;
+ color: #4a4a4a;
}
.Ldt-Ctrl-Time-Separator {
- margin: 0 4px;
- float: left;
+ margin: 0 4px;
+ float: left;
}
.Ldt-Ctrl-Time-Total {
- float: left;
- color: #b2b2b2;
+ float: left;
+ color: #b2b2b2;
}
.Ldt-Ctrl-Sound {
- margin: 0 2px;
+ margin: 0 2px;
}
.Ldt-Ctrl-Sound-Full {
- background-position: -120px 0;
+ background-position: -120px 0;
}
.Ldt-Ctrl-Sound-Full:hover {
- background-position: -120px -25px;
+ background-position: -120px -25px;
}
.Ldt-Ctrl-Sound-Full:active {
- background-position: -120px -50px;
+ background-position: -120px -50px;
}
.Ldt-Ctrl-Sound-Mute {
- background-position: -150px 0;
+ background-position: -150px 0;
}
.Ldt-Ctrl-Sound-Mute:hover {
- background-position: -150px -25px;
+ background-position: -150px -25px;
}
.Ldt-Ctrl-Sound-Mute:active {
- background-position: -150px -50px;
+ background-position: -150px -50px;
}
.Ldt-Ctrl-Sound-Half {
- background-position: -180px 0;
+ background-position: -180px 0;
}
.Ldt-Ctrl-Sound-Half:hover {
- background-position: -180px -25px;
+ background-position: -180px -25px;
}
.Ldt-Ctrl-Sound-Half:active {
- background-position: -180px -50px;
+ background-position: -180px -50px;
}
.Ldt-Ctrl-Volume-Control {
display: none;
- position: absolute;
- background:url('img/player_gradient.png') repeat-x transparent ;
- height: 25px;
- width: 100px; top: 25px; right: -1px; z-index: 100;
- padding: 0 2px;
- border: 1px solid #b6b8b8;
+ position: absolute;
+ background: url('img/player_gradient.png') repeat-x transparent ;
+ height: 25px;
+ width: 100px;
+ top: 25px;
+ right: -1px;
+ z-index: 100;
+ padding: 0 2px;
+ border: 1px solid #b6b8b8;
}
-.Ldt-Ctrl-Volume-Bar {
- height: 5px; margin: 9px 3px 0; background: #cccccc; border: 1px solid #999999; border-radius: 2px;
+.Ldt-Ctrl-Volume-Bar {
+ height: 5px;
+ margin: 9px 3px 0;
+ background: #cccccc;
+ border: 1px solid #999999;
+ border-radius: 2px;
}
.Ldt-Ctrl-Volume-Control .ui-slider-handle {
- width: 6px; height: 19px; background: #a8a8a8; border: 1px solid #999999; border-radius: 2px; top: -8px; margin-left: -4px;
+ width: 6px;
+ height: 19px;
+ background: #a8a8a8;
+ border: 1px solid #999999;
+ border-radius: 2px;
+ top: -8px;
+ margin-left: -4px;
cursor: pointer;
}
.Ldt-Ctrl-Volume-Control:hover .ui-slider-handle {
- background: #F7268E;
-}
\ No newline at end of file
+ background: #F7268E;
+}
+
+/* quiz */
+
+.Ldt-Ctrl-Quiz-Enable button, .Ldt-Ctrl-Quiz-Create button, .Ldt-Ctrl-Quiz-Disactivated button, .Ldt-Ctrl-Fullscreen-Button{
+ border: none;
+ background: transparent;
+}
+
+.Ldt-Ctrl-Quiz-Enable {
+ background-image: url("img/quiz_off.svg");
+ float: left;
+ height: 22px;
+ width: 22px;
+ background-repeat: no-repeat;
+}
+.Ldt-Ctrl-Quiz-Enable.Ldt-Ctrl-Quiz-Toggle-Active {
+ background-image: url("img/quiz_on.svg");
+}
+
+.Ldt-Ctrl-Quiz-Create {
+ background-image: url("img/quiz_add_question.svg");
+ float: left;
+ height: 23px;
+ width: 26px;
+ background-repeat: no-repeat;
+ margin-left: 4px;
+ margin-top: 0px;
+ display: none;
+}
+.Ldt-Ctrl-Quiz-Create.Ldt-Ctrl-Quiz-Toggle-Active {
+ display: inline-block;
+}
+
+.Ldt-Ctrl-Fullscreen-Button {
+ margin-top: 3px;
+}
+
+.Ldt-Ctrl-Fullscreen-Button {
+ float: left;
+ background-image: url("img/fullscreen.svg");
+ background-position: right;
+ margin-right: 6px;
+ margin-top: 1px;
+ height: 22px;
+ width: 22px;
+ border: none;
+}
--- a/src/ldt/ldt/static/ldt/metadataplayer/Controller.js Fri Sep 18 16:10:29 2015 +0200
+++ b/src/ldt/ldt/static/ldt/metadataplayer/Controller.js Fri Oct 02 10:24:05 2015 +0200
@@ -11,7 +11,8 @@
disable_annotate_btn: false,
disable_search_btn: false,
disable_ctrl_f: false,
- always_show_search: false
+ always_show_search: false,
+ enable_quiz_toggle: undefined
};
IriSP.Widgets.Controller.prototype.template =
@@ -25,13 +26,15 @@
+ '{{/disable_annotate_btn}}'
+ '{{^disable_search_btn}}'
+ '<div class="Ldt-Ctrl-button Ldt-Ctrl-SearchBtn Ldt-TraceMe" title="{{l10n.search}}"></div>'
- + '<div class="Ldt-Ctrl-spacer"></div>'
+ '{{/disable_search_btn}}'
+ '<div class="Ldt-Ctrl-Search">'
+ '<input placeholder="{{ l10n.search }}" type="search" class="Ldt-Ctrl-SearchInput Ldt-TraceMe"></input>'
+ '</div>'
+ + '<div class="Ldt-Ctrl-Quiz-Enable Ldt-TraceMe" title="Activer/Désactiver le quiz"></div>'
+ + '<div class="Ldt-Ctrl-Quiz-Create Ldt-TraceMe" ></div>'
+ '</div>'
+ '<div class="Ldt-Ctrl-Right">'
+ + '<div class="Ldt-Ctrl-Fullscreen-Button Ldt-TraceMe" title="Passer le lecteur en plein-écran"></div>'
+ '<div class="Ldt-Ctrl-spacer"></div>'
+ '<div class="Ldt-Ctrl-Time">'
+ '<div class="Ldt-Ctrl-Time-Elapsed" title="{{l10n.elapsed_time}}">00:00</div>'
@@ -59,7 +62,8 @@
elapsed_time: "Elapsed time",
total_time: "Total duration",
volume: "Volume",
- volume_control: "Volume control"
+ volume_control: "Volume control",
+ enable_quiz: "Enable quiz"
},
fr: {
play_pause: "Lecture/Pause",
@@ -73,39 +77,75 @@
elapsed_time: "Temps écoulé",
total_time: "Durée totale",
volume: "Niveau sonore",
- volume_control: "Réglage du niveau sonore"
+ volume_control: "Réglage du niveau sonore",
+ enable_quiz: "Activer le quiz"
}
};
IriSP.Widgets.Controller.prototype.draw = function() {
var _this = this;
this.renderTemplate();
-
+
// Define blocks
this.$playButton = this.$.find(".Ldt-Ctrl-Play");
this.$searchBlock = this.$.find(".Ldt-Ctrl-Search");
this.$searchInput = this.$.find(".Ldt-Ctrl-SearchInput");
this.$volumeBar = this.$.find(".Ldt-Ctrl-Volume-Bar");
-
+
// handle events
this.onMediaEvent("play","playButtonUpdater");
this.onMediaEvent("pause","playButtonUpdater");
this.onMediaEvent("volumechange","volumeUpdater");
this.onMediaEvent("timeupdate","timeDisplayUpdater");
this.onMediaEvent("loadedmetadata","volumeUpdater");
-
+
// handle clicks
this.$playButton.click(this.functionWrapper("playHandler"));
-
+
+ if (this.enable_quiz_toggle !== undefined) {
+ if (this.enable_quiz_toggle) {
+ $(".Ldt-Ctrl-Quiz-Enable").addClass("Ldt-Ctrl-Quiz-Toggle-Active");
+ $(".Ldt-Ctrl-Quiz-Create").addClass("Ldt-Ctrl-Quiz-Toggle-Active");
+ // this.player.trigger("QuizCreator.show");
+ $("#QuizEditContainer").show();
+ }
+ else
+ {
+ $(".Ldt-Ctrl-Quiz-Enable").removeClass("Ldt-Ctrl-Quiz-Toggle-Active");
+ $(".Ldt-Ctrl-Quiz-Create").removeClass("Ldt-Ctrl-Quiz-Toggle-Active");
+ this.player.trigger("QuizCreator.hide");
+ $("#QuizEditContainer").hide();
+ }
+ } else {
+ $(".Ldt-Ctrl-Quiz-Enable").hide();
+ }
+
this.$.find(".Ldt-Ctrl-Annotate").click(function() {
_this.player.trigger("CreateAnnotation.toggle");
});
this.$.find(".Ldt-Ctrl-SearchBtn").click(this.functionWrapper("searchButtonHandler"));
-
+
this.$searchInput.keyup(this.functionWrapper("searchHandler"));
this.$searchInput.on("search", this.functionWrapper("searchHandler"));
-
- var _volctrl = this.$.find(".Ldt-Ctrl-Volume-Control");
+
+ // Fullscreen handling
+ this.$.find(".Ldt-Ctrl-Fullscreen-Button").click(this.functionWrapper("toggleFullscreen"));
+ var fullscreen_event_name = IriSP.getFullscreenEventname();
+ if (fullscreen_event_name) {
+ document.addEventListener(fullscreen_event_name, function() {
+ if (IriSP.isFullscreen() && IriSP.getFullscreenElement() == _this.$[0]) {
+ _this.$.addClass("Ldt-Fullscreen-Element");
+ } else {
+ _this.$.removeClass("Ldt-Fullscreen-Element");
+ }
+ });
+ };
+
+ // Quiz activation
+ this.$.find(".Ldt-Ctrl-Quiz-Enable").click(this.functionWrapper("toggleQuiz"));
+ this.$.find(".Ldt-Ctrl-Quiz-Create").click(this.functionWrapper("createQuiz"));
+
+ var _volctrl = this.$.find(".Ldt-Ctrl-Volume-Control");
this.$.find('.Ldt-Ctrl-Sound')
.click(this.functionWrapper("muteHandler"))
.mouseover(function() {
@@ -119,7 +159,7 @@
}).mouseout(function() {
_volctrl.hide();
});
-
+
// Handle CTRL-F
if (!this.disable_ctrl_f) {
var _fKey = "F".charCodeAt(0),
@@ -135,7 +175,7 @@
}
});
}
-
+
// Allow Volume Cursor Dragging
this.$volumeBar.slider({
slide: function(event, ui) {
@@ -149,13 +189,13 @@
this.$.hover(
function() {
_this.player.trigger("Player.MouseOver");
- },
+ },
function() {
_this.player.trigger("Player.MouseOut");
});
-
+
this.timeDisplayUpdater(new IriSP.Model.Time(0));
-
+
var annotations = this.source.getAnnotations();
annotations.on("search", function(_text) {
_this.$searchInput.val(_text);
@@ -177,7 +217,7 @@
/* Update the elasped time div */
IriSP.Widgets.Controller.prototype.timeDisplayUpdater = function(_time) {
-
+
// we get it at each call because it may change.
var _totalTime = this.media.duration;
this.$.find(".Ldt-Ctrl-Time-Elapsed").html(_time.toString());
@@ -203,13 +243,44 @@
}
};
+//FullScreen
+IriSP.Widgets.Controller.prototype.toggleFullscreen = function() {
+ if (IriSP.isFullscreen()) {
+ IriSP.setFullScreen(this.$[0], false);
+ } else {
+ IriSP.setFullScreen(this.$[0], true);
+ }
+};
+
+//Quiz
+IriSP.Widgets.Controller.prototype.createQuiz = function() {
+ this.player.trigger("Quiz.hide");
+ this.media.pause();
+ this.player.trigger("QuizCreator.create");
+};
+
+IriSP.Widgets.Controller.prototype.toggleQuiz = function() {
+ this.enable_quiz_toggle = !this.enable_quiz_toggle;
+ if (this.enable_quiz_toggle) {
+ $(".Ldt-Ctrl-Quiz-Enable").addClass("Ldt-Ctrl-Quiz-Toggle-Active");
+ $(".Ldt-Ctrl-Quiz-Create").addClass("Ldt-Ctrl-Quiz-Toggle-Active");
+ this.player.trigger("Quiz.activate");
+ }
+ else
+ {
+ $(".Ldt-Ctrl-Quiz-Enable").removeClass("Ldt-Ctrl-Quiz-Toggle-Active");
+ $(".Ldt-Ctrl-Quiz-Create").removeClass("Ldt-Ctrl-Quiz-Toggle-Active");
+ this.player.trigger("Quiz.deactivate");
+ this.player.trigger("QuizCreator.hide");
+ }
+};
IriSP.Widgets.Controller.prototype.playHandler = function() {
- if (this.media.getPaused()) {
+ if (this.media.getPaused()) {
this.media.play();
} else {
this.media.pause();
- }
+ }
};
IriSP.Widgets.Controller.prototype.muteHandler = function() {
@@ -224,9 +295,9 @@
}
var _soundCtl = this.$.find(".Ldt-Ctrl-Sound");
_soundCtl.removeClass("Ldt-Ctrl-Sound-Mute Ldt-Ctrl-Sound-Half Ldt-Ctrl-Sound-Full");
- if (_muted) {
+ if (_muted) {
_soundCtl.attr("title", this.l10n.unmute)
- .addClass("Ldt-Ctrl-Sound-Mute");
+ .addClass("Ldt-Ctrl-Sound-Mute");
} else {
_soundCtl.attr("title", this.l10n.mute)
.addClass(_vol < .5 ? "Ldt-Ctrl-Sound-Half" : "Ldt-Ctrl-Sound-Full" );
@@ -268,7 +339,7 @@
}
var _val = this.$searchInput.val();
this._positiveMatch = false;
-
+
// do nothing if the search field is empty, instead of highlighting everything.
if (_val !== this.lastSearchValue) {
if (_val) {
@@ -280,4 +351,3 @@
}
this.lastSearchValue = _val;
};
-
--- a/src/ldt/ldt/static/ldt/metadataplayer/CreateAnnotation.css Fri Sep 18 16:10:29 2015 +0200
+++ b/src/ldt/ldt/static/ldt/metadataplayer/CreateAnnotation.css Fri Oct 02 10:24:05 2015 +0200
@@ -23,7 +23,7 @@
}
.Ldt-CreateAnnotation-Main {
- min-height: 150px;
+ min-height: 50px;
}
.Ldt-CreateAnnotation-Title, .Ldt-CreateAnnotation-Creator {
@@ -44,13 +44,12 @@
}
.Ldt-CreateAnnotation-Submit,
-.Ldt-CreateAnnotation-Cancel{
+.Ldt-CreateAnnotation-Cancel,
+.Ldt-CreateAnnotation-PreviewSubmit{
position: absolute;
bottom: 7px;
- right: 7px;
color: #ffffff;
cursor: pointer;
- background: url('img/submit_annotation.png');
height: 50px;
width: 50px;
padding: 28px 0 0;
@@ -60,15 +59,27 @@
cursor: pointer;
}
-.Ldt-CreateAnnotation-Submit:hover {
+
+.Ldt-CreateAnnotation-Cancel{
+ right: 7px;
+ background: url('img/cancel_annotation.png');
+}
+
+.Ldt-CreateAnnotation-Submit{
+ right: 67px;
+ background: url('img/submit_annotation.png');
+}
+
+.Ldt-CreateAnnotation-Submit:hover,
+.Ldt-CreateAnnotation-Cancel:hover{
background-position: -50px 0;
}
.Ldt-CreateAnnotation-Description {
- height: 56px;
+ height: 3em;
padding: 2px;
resize: none;
- width: 460px;
+ width: calc(100% - 122px);
border: 1px solid #666666;
border-radius: 2px;
}
@@ -104,6 +115,8 @@
.Ldt-CreateAnnotation-TagList, .Ldt-CreateAnnotation-PolemicList {
list-style: none;
+ width: calc(100% - 122px);
+ padding-left: 0px;
}
li.Ldt-CreateAnnotation-TagLi {
--- a/src/ldt/ldt/static/ldt/metadataplayer/CreateAnnotation.js Fri Sep 18 16:10:29 2015 +0200
+++ b/src/ldt/ldt/static/ldt/metadataplayer/CreateAnnotation.js Fri Oct 02 10:24:05 2015 +0200
@@ -2,6 +2,13 @@
IriSP.Widgets.CreateAnnotation = function(player, config) {
IriSP.Widgets.Widget.call(this, player, config);
+ if (_this.editable_storage != '' && window.localStorage[_this.editable_storage]) {
+ this.source.onLoad(function () {
+ var _export = _this.player.sourceManager.newLocalSource({serializer: IriSP.serializers['ldt_localstorage']});
+ _export.deSerialize(window.localStorage[_this.editable_storage]);
+ _this.source.merge(_export);
+ });
+ };
};
IriSP.Widgets.CreateAnnotation.prototype = new IriSP.Widgets.Widget();
@@ -48,6 +55,8 @@
api_serializer: "ldt_annotate",
api_endpoint_template: "",
api_method: "POST",
+ // Id that will be used as localStorage key
+ editable_storage: "",
project_id: "",
after_send_timeout: 0,
close_after_send: false,
@@ -55,6 +64,7 @@
pause_when_displaying: false,
custom_send_button: false,
custom_cancel_button: false,
+ preview_mode: false,
};
IriSP.Widgets.CreateAnnotation.prototype.messages = {
@@ -63,13 +73,14 @@
to_time: "to",
at_time: "at",
submit: "Submit",
+ preview_submit: "You cannot submit annotations in preview mode",
cancel: "Cancel",
add_keywords_: "Add keywords:",
add_polemic_keywords_: "Add polemic attributes :",
your_name_: "Your name:",
- annotate_video: "Annotate this video",
+ annotate_video: "New note",
type_title: "Annotation title",
- type_description: "Type the full contents of your annotation here.",
+ type_description: "Enter a new note...",
wait_while_processing: "Please wait while your annotation is being processed...",
error_while_contacting: "An error happened while contacting the server. Your annotation has not been saved.",
annotation_saved: "Thank you, your annotation has been saved.",
@@ -78,20 +89,24 @@
"polemic++": "Agree",
"polemic--": "Disagree",
"polemic??": "Question",
- "polemic==": "Reference"
+ "polemic==": "Reference",
+ "in_tooltip": "Set begin time to current player time",
+ "out_tooltip": "Set begin time to current player time",
+ "play_tooltip": "Play the fragment"
},
fr: {
from_time: "de",
to_time: "à",
at_time: "à",
submit: "Envoyer",
+ preview_submit: "Vous ne pouvez pas envoyer d'annotation en mode aperçu",
cancel: "Annuler",
add_keywords_: "Ajouter des mots-clés\u00a0:",
add_polemic_keywords_: "Ajouter des attributs polémiques\u00a0:",
your_name_: "Votre nom\u00a0:",
- annotate_video: "Annoter cette vidéo",
+ annotate_video: "Entrez une nouvelle note...",
type_title: "Titre de l'annotation",
- type_description: "Rédigez ici le contenu de votre annotation.",
+ type_description: "Prenez vos notes...",
wait_while_processing: "Veuillez patienter pendant le traitement de votre annotation...",
error_while_contacting: "Une erreur s'est produite en contactant le serveur. Votre annotation n'a pas été enregistrée.",
annotation_saved: "Merci, votre annotation a été enregistrée.",
@@ -100,12 +115,15 @@
"polemic++": "Accord",
"polemic--": "Désaccord",
"polemic??": "Question",
- "polemic==": "Référence"
+ "polemic==": "Référence",
+ "in_tooltip": "Utiliser le temps courant comme début",
+ "out_tooltip": "Utiliser le temps courant comme fin",
+ "play_tooltip": "Jouer le fragment"
}
};
IriSP.Widgets.CreateAnnotation.prototype.template =
- '{{#show_slice}}<div class="Ldt-CreateAnnotation-Slice"></div>{{/show_slice}}'
+ '{{#show_slice}}<div class="Ldt-CreateAnnotation-Slice Ldt-TraceMe"></div>{{/show_slice}}'
+ '{{^show_slice}}{{#show_arrow}}<div class="Ldt-CreateAnnotation-Arrow"></div>{{/show_arrow}}{{/show_slice}}'
+ '<div class="Ldt-CreateAnnotation"><div class="Ldt-CreateAnnotation-Inner">'
+ '<form class="Ldt-CreateAnnotation-Screen Ldt-CreateAnnotation-Main">'
@@ -114,10 +132,19 @@
+ '{{#show_time}}<span class="Ldt-CreateAnnotation-Times"> {{#show_slice}}{{l10n.from_time}} {{/show_slice}}{{^show_slice}}{{l10n.at_time}} {{/show_slice}} <span class="Ldt-CreateAnnotation-Begin">00:00</span>{{/show_time}}'
+ '{{#show_slice}} {{l10n.to_time}} <span class="Ldt-CreateAnnotation-End">{{end}}</span>{{/show_slice}}</span></span>'
+ '{{#show_creator_field}}{{l10n.your_name_}} <input class="Ldt-CreateAnnotation-Creator empty" value="{{creator_name}}" {{#creator_field_readonly}}readonly{{/creator_field_readonly}}/>{{/show_creator_field}}</h3>'
- + '<textarea class="Ldt-CreateAnnotation-Description empty" placeholder="{{l10n.type_description}}"></textarea>'
- + '<div class="Ldt-CreateAnnotation-Avatar"><img src="{{creator_avatar}}" title="{{creator_name}}"></img></div>'
- + '<input type="submit" class="Ldt-CreateAnnotation-Submit" value="{{#custom_send_button}}{{custom_send_button}}{{/custom_send_button}}{{^custom_send_button}}{{l10n.submit}}{{/custom_send_button}}" />'
- + '<input type="button" class="Ldt-CreateAnnotation-Cancel" value="{{#custom_cancel_button}}{{custom_cancel_button}}{{/custom_cancel_button}}{{^custom_cancel_button}}{{l10n.cancel}}{{/custom_cancel_button}}" />'
+ + '{{#show_controls}}<div class="Ldt-CreateAnnotation-Controls">'
+ + '<span title="{{l10n.in_tooltip}}" class="Ldt-CreateAnnotation-Control-In">In</span>'
+ + '<span title="{{l10n.out_tooltip}}" class="Ldt-CreateAnnotation-Control-Out">Out</span>'
+ + '<span title="{{l10n.play_tooltip}}" class="Ldt-CreateAnnotation-Control-Play">Play</span>'
+ + '</div>{{/show_controls}}'
+ + '<textarea class="Ldt-CreateAnnotation-Description Ldt-TraceMe empty" placeholder="{{l10n.type_description}}"></textarea>'
+ + '{{#show_creator_field}}<div class="Ldt-CreateAnnotation-Avatar"><img src="{{creator_avatar}}" title="{{creator_name}}"></img></div>{{/show_creator_field}}'
+ + '<div class="Ldt-CreateAnnotation-SubmitArea Ldt-TraceMe">'
+ + '{{#preview_mode}}<input type="button" class="Ldt-CreateAnnotation-PreviewSubmit" title="{{l10n.preview_submit}}" value="{{#custom_send_button}}{{custom_send_button}}{{/custom_send_button}}{{^custom_send_button}}{{l10n.submit}}{{/custom_send_button}}" />{{/preview_mode}}'
+ + '{{^preview_mode}}<input type="submit" class="Ldt-CreateAnnotation-Submit" value="{{#custom_send_button}}{{custom_send_button}}{{/custom_send_button}}{{^custom_send_button}}{{l10n.submit}}{{/custom_send_button}}" />{{/preview_mode}}'
+ + '<input type="button" class="Ldt-CreateAnnotation-Cancel" value="{{#custom_cancel_button}}{{custom_cancel_button}}{{/custom_cancel_button}}{{^custom_cancel_button}}{{l10n.cancel}}{{/custom_cancel_button}}" />'
+ + '<div class="Ldt-CreateAnnotation-Begin Ldt-CreateAnnotation-Times">00:00</div>'
+ + '</div>'
+ '{{#show_mic_record}}<div class="Ldt-CreateAnnotation-RecBlock"><div class="Ldt-CreateAnnotation-RecLabel">Add voice annotation</div>'
+ ' <object classid="clsid:d27cdb6e-ae6d-11cf-96b8-444553540000" width="220" height="160">'
+ ' <param name="movie" value="{{record_swf}}" />'
@@ -208,10 +235,7 @@
show_arrow: this.show_arrow,
annotation_type: this.slice_annotation_type,
onBoundsChanged: function(_from, _to) {
- _this.begin = new IriSP.Model.Time(_from || 0);
- _this.end = new IriSP.Model.Time(_to || 0);
- _this.$.find(".Ldt-CreateAnnotation-Begin").html(_this.begin.toString());
- _this.$.find(".Ldt-CreateAnnotation-End").html(_this.end.toString());
+ _this.setBeginEnd(_from, _to);
}
},
"slice"
@@ -221,12 +245,13 @@
this.insertSubwidget(this.$.find(".Ldt-CreateAnnotation-Arrow"), {type: "Arrow"},"arrow");
}
this.onMediaEvent("timeupdate", function(_time) {
- _this.begin = new IriSP.Model.Time(_time || 0);
- _this.end = new IriSP.Model.Time(_time || 0);
- _this.$.find(".Ldt-CreateAnnotation-Begin").html(_this.begin.toString());
- if (_this.arrow) {
- _this.arrow.moveToTime(_time);
- }
+ // Do not update timecode if description is not empty
+ if (_this.$.find(".Ldt-CreateAnnotation-Description").val().trim() == "") {
+ _this.setBeginEnd(_time, _time);
+ if (_this.arrow) {
+ _this.arrow.moveToTime(_time);
+ }
+ };
});
}
this.$.find(".Ldt-CreateAnnotation-Cancel").click(function() {
@@ -234,7 +259,7 @@
});
this.$.find(".Ldt-CreateAnnotation-Close").click(function() {
_this.close_after_send
- ? _this.hide()
+ ? _this.player.trigger("CreateAnnotation.hide")
: _this.showScreen("Main");
return false;
});
@@ -257,7 +282,25 @@
if (this.show_creator_field) {
this.$.find(".Ldt-CreateAnnotation-Creator").bind("change keyup input paste", this.functionWrapper("onCreatorChange"));
}
-
+ this.$.find("[class^='Ldt-CreateAnnotation-Control-']").click(function() {
+ var action = this.className.replace('Ldt-CreateAnnotation-Control-', '');
+ switch (action) {
+ case "In":
+ // Set In bound to current player time
+ this.setBegin(_this.media.getCurrentTime());
+ break;
+ case "Out":
+ // Set In bound to current player time
+ this.setEnd(_this.media.getCurrentTime() || _this.media.duration);
+ break;
+ case "Play":
+ this.media.setCurrentTime(_this.begin);
+ this.media.play();
+ break;
+ }
+ return false;
+ });
+
if (this.start_visible) {
this.show();
} else {
@@ -271,10 +314,25 @@
this.$.find("form").submit(this.functionWrapper("onSubmit"));
};
+IriSP.Widgets.CreateAnnotation.prototype.setBegin = function (t) {
+ this.begin = new IriSP.Model.Time(t || 0);
+ this.$.find(".Ldt-CreateAnnotation-Begin").html(this.begin.toString());
+};
+
+IriSP.Widgets.CreateAnnotation.prototype.setEnd = function (t) {
+ this.end = new IriSP.Model.Time(t || 0);
+ this.$.find(".Ldt-CreateAnnotation-End").html(this.end.toString());
+};
+
+IriSP.Widgets.CreateAnnotation.prototype.setBeginEnd = function (begin, end) {
+ this.setBegin(begin);
+ this.setEnd(end);
+};
+
IriSP.Widgets.CreateAnnotation.prototype.showScreen = function(_screenName) {
this.$.find('.Ldt-CreateAnnotation-' + _screenName).show()
.siblings().hide();
-}
+};
IriSP.Widgets.CreateAnnotation.prototype.show = function() {
if (!this.visible){
@@ -321,7 +379,14 @@
if (this.visible) {
this.hide();
} else {
+ var t = _this.media.getCurrentTime() || 0;
+ this.setBeginEnd(t, t);
+ if (this.slice_widget) {
+ this.slice_widget.setBounds(this.begin, this.end);
+ }
this.show();
+ // Set focus on textarea
+ this.$.find(".Ldt-CreateAnnotation-Description").focus();
}
}
};
@@ -344,7 +409,12 @@
}
};
-IriSP.Widgets.CreateAnnotation.prototype.onDescriptionChange = function() {
+IriSP.Widgets.CreateAnnotation.prototype.onDescriptionChange = function(e) {
+ if (e !== undefined && e.keyCode == 13 && !e.shiftKey) {
+ // Return: submit. Use shift-Return to insert a LF
+ this.onSubmit();
+ return true;
+ }
var _field = this.$.find(".Ldt-CreateAnnotation-Description"),
_contents = _field.val();
_field.css("border-color", !!_contents ? "#666666" : "#ff0000");
@@ -392,9 +462,8 @@
return !!_contents;
};
-/* Fonction effectuant l'envoi des annotations */
IriSP.Widgets.CreateAnnotation.prototype.onSubmit = function() {
- /* Si les champs obligatoires sont vides, on annule l'envoi */
+ /* If mandatory fields are empty, we cancel the sending */
if (!this.onDescriptionChange() || (this.show_title_field && !this.onTitleChange()) || (this.show_creator_field && !this.onCreatorChange())) {
return false;
}
@@ -404,26 +473,27 @@
}
var _this = this,
- _exportedAnnotations = new IriSP.Model.List(this.player.sourceManager), /* Création d'une liste d'annotations contenant une annotation afin de l'envoyer au serveur */
- _export = this.player.sourceManager.newLocalSource({serializer: IriSP.serializers[this.api_serializer]}), /* Création d'un objet source utilisant un sérialiseur spécifique pour l'export */
- _annotation = new IriSP.Model.Annotation(false, _export), /* Création d'une annotation dans cette source avec un ID généré à la volée (param. false) */
- _annotationTypes = this.source.getAnnotationTypes().searchByTitle(this.annotation_type, true), /* Récupération du type d'annotation dans lequel l'annotation doit être ajoutée */
- _annotationType = (_annotationTypes.length ? _annotationTypes[0] : new IriSP.Model.AnnotationType(false, _export)), /* Si le Type d'Annotation n'existe pas, il est créé à la volée */
- _url = Mustache.to_html(this.api_endpoint_template, {id: this.source.projectId}); /* Génération de l'URL à laquelle l'annotation doit être envoyée, qui doit inclure l'ID du projet */
+ _exportedAnnotations = new IriSP.Model.List(this.player.sourceManager), /* We create a List to send to the server that will contains the annotation */
+ _export = this.player.sourceManager.newLocalSource({serializer: IriSP.serializers[this.api_serializer]}), /* We create a source object using a specific serializer for export */
+ _local_export = this.player.sourceManager.newLocalSource({serializer: IriSP.serializers['ldt_localstorage']}), /* Source object using a specific serializer for local export */
+ _annotation = new IriSP.Model.Annotation(false, _export), /* We create an annotation in the source with a generated ID (param. false) */
+ _annotationTypes = this.source.getAnnotationTypes().searchByTitle(this.annotation_type, true), /* We get the AnnotationType in which the annotation will be added */
+ _annotationType = (_annotationTypes.length ? _annotationTypes[0] : new IriSP.Model.AnnotationType(false, _export)), /* If it doesn't already exists, we create it */
+ _url = Mustache.to_html(this.api_endpoint_template, {id: this.source.projectId}); /* We make the url to send the request to, must include project id */
- /* Si nous avons dû générer un ID d'annotationType à la volée... */
+ /* If we created an AnnotationType on the spot ... */
if (!_annotationTypes.length) {
- /* Il ne faudra pas envoyer l'ID généré au serveur */
+ /* ... We must not send its id to the server ... */
_annotationType.dont_send_id = true;
- /* Il faut inclure le titre dans le type d'annotation */
+ /* ... And we must include its title. */
_annotationType.title = this.annotation_type;
}
/*
- * Nous remplissons les données de l'annotation générée à la volée
- * ATTENTION: Si nous sommes sur un MASHUP, ces éléments doivent se référer AU MEDIA D'ORIGINE
+ * Will fill the generated annotation object's data
+ * WARNING: If we're on a MASHUP, these datas must refer the ORIGINAL MEDIA
* */
- _annotation.setMedia(this.source.currentMedia.id); /* Id du média annoté */
+ _annotation.setMedia(this.source.currentMedia.id); /* Annotated media ID */
if (this.post_at_segment_time){
var _currentTime = this.media.getCurrentTime()
@@ -432,32 +502,31 @@
return (_currentTime >= _segment.begin && _currentTime <= _segment.end)
});
if (_currentSegments.length == 0){
- _annotation.setBegin(this.begin); /* Timecode de début du widget */
- _annotation.setEnd(this.end); /* Timecode de fin du widget */
+ _annotation.setBegin(this.begin); /* Widget starting timecode */
+ _annotation.setEnd(this.end); /* Widget end timecode */
}
else {
- _annotation.setBegin(_currentSegments[0].begin); /* Timecode de début du segment */
- _annotation.setEnd(_currentSegments[0].end); /* Timecode de fin du segment */
+ _annotation.setBegin(_currentSegments[0].begin); /* Segment starting timecode */
+ _annotation.setEnd(_currentSegments[0].end); /* Segment end timecode */
}
}
else {
- _annotation.setBegin(this.begin); /*Timecode de début du widget */
- _annotation.setEnd(this.end); /* Timecode de fin du widget */
+ _annotation.setBeginEnd(this.begin, this.end); /* Widget end/start timecodes */
}
- _annotation.setAnnotationType(_annotationType.id); /* Id du type d'annotation */
+ _annotation.setAnnotationType(_annotationType.id); /* Annotation type ID */
if (this.show_title_field) {
- /* Champ titre, seulement s'il est visible */
+ /* Title field, only if it's visible */
_annotation.title = this.$.find(".Ldt-CreateAnnotation-Title").val();
}if (this.project_id != ""){
- /* Champ id projet, seulement si on l'a renseigné dans la config */
+ /* Project id, only if it's been specifiec in the config */
_annotation.project_id = this.project_id;
}
- _annotation.created = new Date(); /* Date de création de l'annotation */
- _annotation.description = this.$.find(".Ldt-CreateAnnotation-Description").val(); /* Champ description */
+ _annotation.created = new Date(); /* Annotation creation date */
+ _annotation.description = this.$.find(".Ldt-CreateAnnotation-Description").val(); /* Description field */
var tagIds = Array.prototype.map.call(
this.$.find(".Ldt-CreateAnnotation-TagLi.selected"),
- function(el) { return IriSP.jQuery(el).attr("tag-id")}
+ function(el) { return IriSP.jQuery(el).attr("tag-id"); }
);
IriSP._(_annotation.description.match(/#[^\s#.,;]+/g)).each(function(_tt) {
@@ -474,10 +543,8 @@
if (tagIds.indexOf(_tag.id) === -1) {
tagIds.push(_tag.id);
}
-
- })
-
- _annotation.setTags(IriSP._(tagIds).uniq()); /*Liste des ids de tags */
+ });
+ _annotation.setTags(IriSP._(tagIds).uniq()); /* Tag ids list */
if (this.audio_url) {
_annotation.audio = {
src: "mic",
@@ -491,46 +558,66 @@
_annotation.creator = this.creator_name;
}
_exportedAnnotations.push(_annotation); /* Ajout de l'annotation à la liste à exporter */
- _export.addList("annotation",_exportedAnnotations); /* Ajout de la liste à exporter à l'objet Source */
- var _this = this;
- /* Envoi de l'annotation via AJAX au serveur ! */
- IriSP.jQuery.ajax({
- url: _url,
- type: this.api_method,
- contentType: 'application/json',
- data: _export.serialize(), /* L'objet Source est sérialisé */
- success: function(_data) {
- _this.showScreen('Saved'); /* Si l'appel a fonctionné, on affiche l'écran "Annotation enregistrée" */
- if (_this.after_send_timeout) { /* Selon les options de configuration, on revient à l'écran principal ou on ferme le widget, ou rien */
- window.setTimeout(
- function() {
- _this.close_after_send
- ? _this.hide()
- : _this.show();
- },
- _this.after_send_timeout
- );
+
+ if (this.editable_storage != '') {
+ // Append to localStorage annotations
+
+ // FIXME: handle movie ids
+ _local_export.addList("annotation", _exportedAnnotations); /* Ajout de la liste à exporter à l'objet Source */
+ _this.source.merge(_local_export); /* On ajoute la nouvelle annotation au recueil original */
+ // Import previously saved local annotations
+ if (window.localStorage[this.editable_storage]) {
+ _local_export.deSerialize(window.localStorage[this.editable_storage]);
+ }
+ // Save everything back
+ window.localStorage[_this.editable_storage] = _local_export.serialize();
+ _this.player.trigger("AnnotationsList.refresh"); /* On force le rafraîchissement du widget AnnotationsList */
+ _this.player.trigger("Annotation.create", _annotation);
+ _this.$.find(".Ldt-CreateAnnotation-Description").val("");
+ }
+
+ if (_url !== "") {
+ _exportedAnnotations.push(_annotation); /* We add the annotation in the list to export */
+ _export.addList("annotation",_exportedAnnotations); /* We add the list to the source object */
+ var _this = this;
+ /* We send the AJAX request to the server ! */
+ IriSP.jQuery.ajax({
+ url: _url,
+ type: this.api_method,
+ contentType: 'application/json',
+ data: _export.serialize(), /* Source is serialized */
+ success: function(_data) {
+ _this.showScreen('Saved');
+ if (_this.after_send_timeout) {
+ window.setTimeout(
+ function() {
+ _this.close_after_send
+ ? _this.player.trigger("CreateAnnotation.hide")
+ : _this.player.trigger("CreateAnnotation.show");
+ },
+ _this.after_send_timeout
+ );
+ }
+ _export.getAnnotations().removeElement(_annotation, true); /* We delete the sent annotation to avoid redundancy */
+ _export.deSerialize(_data); /* Data deserialization */
+ _this.source.merge(_export); /* We merge the deserialized data with the current source data */
+ if (_this.pause_on_write && _this.media.getPaused()) {
+ _this.media.play();
+ }
+ _this.player.trigger("AnnotationsList.refresh");
+ },
+ error: function(_xhr, _error, _thrown) {
+ IriSP.log("Error when sending annotation", _thrown);
+ _export.getAnnotations().removeElement(_annotation, true);
+ _this.showScreen('Error');
+ window.setTimeout(function(){
+ _this.showScreen("Main")
+ },
+ (_this.after_send_timeout || 5000));
}
- _export.getAnnotations().removeElement(_annotation, true); /* Pour éviter les doublons, on supprime l'annotation qui a été envoyée */
- _export.deSerialize(_data); /* On désérialise les données reçues pour les réinjecter */
- _this.source.merge(_export); /* On récupère les données réimportées dans l'espace global des données */
- if (_this.pause_on_write && _this.media.getPaused()) {
- _this.media.play();
- }
- _this.player.trigger("AnnotationsList.refresh"); /* On force le rafraîchissement du widget AnnotationsList */
- },
- error: function(_xhr, _error, _thrown) {
- IriSP.log("Error when sending annotation", _thrown);
- _export.getAnnotations().removeElement(_annotation, true);
- _this.showScreen('Error');
- window.setTimeout(function(){
- _this.showScreen("Main")
- },
- (_this.after_send_timeout || 5000));
- }
- });
- this.showScreen('Wait');
-
+ });
+ this.showScreen('Wait');
+ };
return false;
};
--- a/src/ldt/ldt/static/ldt/metadataplayer/CurrentSegmentInfobox.css Fri Sep 18 16:10:29 2015 +0200
+++ b/src/ldt/ldt/static/ldt/metadataplayer/CurrentSegmentInfobox.css Fri Oct 02 10:24:05 2015 +0200
@@ -112,6 +112,33 @@
width: 80px;
}
+.Ldt-CurrentSegmentInfobox-EditButton{
+ float: right;
+ display: inline-block;
+ background-color: #d93c71;
+ color: #ffffff;
+ cursor: pointer;
+ height: 18px;
+ width: 95px;
+ font-size: 14px;
+ border: 1px solid;
+ border-color: #eca3bc #631e34 #36101c #e16e93;
+ cursor: pointer;
+ margin-right: 5px;
+ margin-left: 5px;
+ margin-bottom: 5px;
+ margin-top: 5px;
+ padding: 4px;
+ text-align: center;
+ vertical-align: middle;
+ line-height: 18px;
+}
+
+.Ldt-CurrentSegmentInfobox-EditButton:hover, .Ldt-CurrentSegmentInfobox-CreateTagInput-Add:hover{
+ background-color: #e15581;
+ border-color: #222222 #e87d9f #f0adc3 #68273c;
+}
+
.Ldt-CurrentSegmentInfobox-CreateTagButton:hover, .Ldt-CurrentSegmentInfobox-CancelButton:hover,
.Ldt-CurrentSegmentInfobox-SubmitButton:hover{
background-color: #e15581;
@@ -127,8 +154,37 @@
color: #e16e93
}
+.Ldt-CurrentSegmentInfobox-FieldsHeader{
+ margin: 5px;
+}
+
+.Ldt-CurrentSegmentInfobox-TagsHeader{
+ margin-top: 10px;
+ margin-left: 5px;
+}
+
.Ldt-CurrentSegmentInfobox-CreateTagInput{
border: 2px solid #848484;
margin: 5px 0;
padding: 4px;
+}
+
+.Ldt-CurrentSegmentInfobox-CreateTagInput-Add{
+ margin: 5px;
+ padding: 4px;
+ display: inline-block;
+ background-color: #d93c71;
+ color: #ffffff;
+ cursor: pointer;
+ height: 14px;
+ width: 14px;
+ font-size: 14px;
+ font-style: bold;
+ border: 1px solid;
+ border-color: #eca3bc #631e34 #36101c #e16e93;
+ cursor: pointer;
+ padding: 4px;
+ text-align: center;
+ vertical-align: middle;
+ line-height: 14px;
}
\ No newline at end of file
--- a/src/ldt/ldt/static/ldt/metadataplayer/CurrentSegmentInfobox.js Fri Sep 18 16:10:29 2015 +0200
+++ b/src/ldt/ldt/static/ldt/metadataplayer/CurrentSegmentInfobox.js Fri Oct 02 10:24:05 2015 +0200
@@ -15,10 +15,12 @@
api_method: "PUT",
api_endpoint_template: "",
new_tag_button: true,
+ show_headers: false,
};
IriSP.Widgets.CurrentSegmentInfobox.prototype.template =
'<div class="Ldt-CurrentSegmentInfobox">'
+ + '{{#editable_segments}}<div class="Ldt-CurrentSegmentInfobox-EditButton">{{edit}}</div>{{/editable_segments}}'
+ '<div class="Ldt-CurrentSegmentInfobox-Element Ldt-CurrentSegmentInfobox-Title">{{title}}</div>'
+ '<div class="Ldt-CurrentSegmentInfobox-Element Ldt-CurrentSegmentInfobox-Description">{{description}}</div>'
+ '<div class="Ldt-CurrentSegmentInfobox-Element Ldt-CurrentSegmentInfobox-Tags">'
@@ -38,16 +40,19 @@
IriSP.Widgets.CurrentSegmentInfobox.prototype.editTemplate =
'<div class="Ldt-CurrentSegmentInfobox">'
+ + '{{#headers}}<div class="Ldt-CurrentSegmentInfobox-FieldsHeader">{{fields_header}}</div>{{/headers}}'
+ '<input type="text" class="Ldt-CurrentSegmentInfobox-Element Ldt-CurrentSegmentInfobox-TitleInput Ldt-CurrentSegmentInfobox-Title" value="{{title}}"></input>'
+ '<div class="Ldt-CurrentSegmentInfobox-CancelButton">{{cancel}}</div>'
+ '<div class="Ldt-CurrentSegmentInfobox-SubmitButton">{{submit}}</div>'
+ '<textarea class="Ldt-CurrentSegmentInfobox-Element Ldt-CurrentSegmentInfobox-DescriptionInput Ldt-CurrentSegmentInfobox-Description">{{description}}</textarea>'
+ '<div class="Ldt-CurrentSegmentInfobox-Element Ldt-CurrentSegmentInfobox-Tags">'
+ + '{{#headers}}<div class="Ldt-CurrentSegmentInfobox-TagsHeader">{{tags_header}}</div>{{/headers}}'
+ '{{#new_tag_button}}'
+ '<div class="Ldt-CurrentSegmentInfobox-CreateTagButton">{{new_tag}}</div>'
+ '{{/new_tag_button}}'
+ '{{^new_tag_button}}'
+ '<input class="Ldt-CurrentSegmentInfobox-CreateTagInput" placeholder="{{new_tag}}"></input>'
+ + '<div class="Ldt-CurrentSegmentInfobox-CreateTagInput-Add">+</div>'
+ '{{/new_tag_button}}'
+ '{{#tags.length}}'
+ '<ul class="Ldt-CurrentSegmentInfobox-Tags-Ul">'
@@ -68,15 +73,21 @@
fr : {
submit : "Soumettre",
cancel : "Annuler",
+ edit : "Editer",
new_tag : "Nouveau tag",
delete_tag : "Supprimer",
+ fields_header : "Contenu du segment courant",
+ tags_header : "Mots-clés du segment courant",
empty : "Le player vidéo ne lit actuellement aucun segment"
},
en: {
submit : "Submit",
cancel : "Cancel",
+ edit : "Edit",
new_tag : "New tag",
delete_tag : "Delete tag",
+ fields_header : "Current segment content",
+ tags_header : "Current segment tags",
empty : "The player currently doesn't read any segment"
}
}
@@ -100,9 +111,11 @@
if (_this.currentSegment.id != _list[0].id){
_this.currentSegment = _list[0];
_data = {
- title: _this.currentSegment.title,
- description : _this.currentSegment.description,
- tags : _this.currentSegment.getTagTexts()
+ editable_segments: _this.editable_segments,
+ edit: _this.l10n.edit,
+ title: _this.currentSegment.title,
+ description : _this.currentSegment.description,
+ tags : _this.currentSegment.getTagTexts()
}
_this.$.html(Mustache.to_html(_this.template, _data))
if(_this.editable_segments&&_this.currentSegment){
@@ -126,6 +139,9 @@
tags : this.currentSegment.getTagTexts(),
submit : this.l10n.submit,
cancel : this.l10n.cancel,
+ headers : this.show_headers,
+ tags_header : this.custom_tags_header ? this.custom_tags_header : this.l10n.tags_header,
+ fields_header : this.custom_fields_header ? this.custom_fields_header : this.l10n.fields_header,
new_tag : this.l10n.new_tag,
delete_tag : this.l10n.delete_tag,
new_tag_button : this.new_tag_button,
@@ -136,7 +152,8 @@
if (this.new_tag_button){
this.$.find(".Ldt-CurrentSegmentInfobox-CreateTagButton").click(this.functionWrapper("insertTagInput"));
} else {
- this.$.find(".Ldt-CurrentSegmentInfobox-CreateTagInput").keypress(this.functionWrapper("insertTagInputKeypress"));
+ this.$.find(".Ldt-CurrentSegmentInfobox-CreateTagInput").keypress(this.functionWrapper("insertTagInputKeypress"));
+ this.$.find(".Ldt-CurrentSegmentInfobox-CreateTagInput-Add").click(this.functionWrapper("insertTagInputKeypress"));
}
this.$.find(".Ldt-CurrentSegmentInfobox-Tags-Li-DeleteTagButton").click(this.functionWrapper("deleteTagInput"));
this.$.find(".Ldt-CurrentSegmentInfobox-SubmitButton").click(this.functionWrapper("onSubmit"))
@@ -145,11 +162,13 @@
IriSP.Widgets.CurrentSegmentInfobox.prototype.disableEditMode = function() {
if(this.currentSegment){
- data = {
- title: this.currentSegment.title,
- description : this.currentSegment.description,
- tags : this.currentSegment.getTagTexts()
- }
+ _data = {
+ editable_segments: this.editable_segments,
+ edit: this.l10n.edit,
+ title: this.currentSegment.title,
+ description : this.currentSegment.description,
+ tags : this.currentSegment.getTagTexts()
+ }
this.$.toggleClass("editing", false);
this.$.html(Mustache.to_html(this.template, _data));
this.$.find(".Ldt-CurrentSegmentInfobox").click(this.functionWrapper("enableEditMode"));
@@ -170,7 +189,7 @@
IriSP.Widgets.CurrentSegmentInfobox.prototype.insertTagInputKeypress = function(event) {
var keycode = (event.keyCode ? event.keyCode : event.which);
- if(keycode == '13'){
+ if(keycode == '13' || event.type == 'click'){
if((!this.currentSegment.getTagTexts().length)&&(!this.$.find(".Ldt-CurrentSegmentInfobox-Tags-Ul").length)){
this.$.find(".Ldt-CurrentSegmentInfobox-Tags").prepend('<ul class="Ldt-CurrentSegmentInfobox-Tags-Ul"></ul>')
}
@@ -199,9 +218,9 @@
new_description = this.$.find(".Ldt-CurrentSegmentInfobox-DescriptionInput").val()
var _this = this,
- _exportedAnnotations = new IriSP.Model.List(this.player.sourceManager), /* Création d'une liste d'annotations contenant une annotation afin de l'envoyer au serveur */
- _export = this.player.sourceManager.newLocalSource({serializer: IriSP.serializers[this.api_serializer]}),
- _annotation = new IriSP.Model.Annotation(this.currentSegment.id, _export); /* Création d'une annotation dans cette source avec un ID généré à la volée (param. false) */
+ _exportedAnnotations = new IriSP.Model.List(this.player.sourceManager), /* We create an Annotations List to send to the server */
+ _export = this.player.sourceManager.newLocalSource({serializer: IriSP.serializers[this.api_serializer]}), /* We create a source object using a specific serializer for export */
+ _annotation = new IriSP.Model.Annotation(this.currentSegment.id, _export); /* We create an annotation in the source with a generated ID (param. false) */
_annotation.setAnnotationType(this.currentSegment.getAnnotationType().id);
_annotation.setMedia(this.currentSegment.getMedia().id);
@@ -209,8 +228,8 @@
_annotation.setEnd(this.currentSegment.end);
_annotation.created = this.currentSegment.created;
_annotation.creator = this.currentSegment.creator;
- _annotation.title = new_title /* Champ titre */
- _annotation.description = new_description /* Champ description */
+ _annotation.title = new_title /* Title field */
+ _annotation.description = new_description /* Description field */
var _tagIds = IriSP._(new_tags_titles).map(function(_title) {
var _tags = _this.source.getTags(true).searchByTitle(_title, true);
if (_tags.length) {
@@ -226,8 +245,8 @@
_annotation.setTags(_tagIds);
_annotation.project_id = this.project_id;
- _exportedAnnotations.push(_annotation); /* Ajout de l'annotation à la liste à exporter */
- _export.addList("annotation",_exportedAnnotations); /* Ajout de la liste à exporter à l'objet Source */
+ _exportedAnnotations.push(_annotation); /* We add the annotation in the list to export */
+ _export.addList("annotation",_exportedAnnotations); /* We add the list to the source object */
_url = Mustache.to_html(this.api_endpoint_template, {annotation_id: this.currentSegment.id});
@@ -235,11 +254,11 @@
url: _url,
type: this.api_method,
contentType: 'application/json',
- data: _export.serialize(), /* L'objet Source est sérialisé */
+ data: _export.serialize(), /* Source is serialized */
success: function(_data) {
- _export.getAnnotations().removeElement(_annotation, true); /* Pour éviter les doublons, on supprime l'annotation qui a été envoyée */
- _export.deSerialize(_data); /* On désérialise les données reçues pour les réinjecter */
- _this.source.merge(_export); /* On récupère les données réimportées dans l'espace global des données */
+ _export.getAnnotations().removeElement(_annotation, true); /* We delete the sent annotation to avoid redundancy */
+ _export.deSerialize(_data); /* Data deserialization */
+ _this.source.merge(_export); /* We merge the deserialized data with the current source data */
_this.segments.forEach(function(_segment){
if (_segment.id == _annotation.id){
_this.segments.removeElement(_segment)
@@ -248,16 +267,17 @@
_this.segments.push(_annotation)
_this.currentSegment = _annotation
_data = {
- title: _this.currentSegment.title,
- description : _this.currentSegment.description,
- tags : _this.currentSegment.getTagTexts()
- }
+ editable_segments: _this.editable_segments,
+ edit: _this.l10n.edit,
+ title: _this.currentSegment.title,
+ description : _this.currentSegment.description,
+ tags : _this.currentSegment.getTagTexts()
+ }
_this.$.html(Mustache.to_html(_this.template, _data))
if(_this.editable_segments&&_this.currentSegment){
_this.$.find(".Ldt-CurrentSegmentInfobox").click(_this.functionWrapper("enableEditMode"));
}
_this.$.toggleClass("editing", false);
- _this.player.trigger("AnnotationsList.refresh"); /* On force le rafraîchissement du widget AnnotationsList */
},
error: function(_xhr, _error, _thrown) {
IriSP.log("Error when sending annotation", _thrown);
@@ -277,6 +297,8 @@
if (this.currentSegment.id != _list[0].id){
this.currentSegment = _list[0];
_data = {
+ editable_segments: this.editable_segments,
+ edit: this.l10n.edit,
title: this.currentSegment.title,
description : this.currentSegment.description,
tags : this.currentSegment.getTagTexts()
--- a/src/ldt/ldt/static/ldt/metadataplayer/DailymotionPlayer.js Fri Sep 18 16:10:29 2015 +0200
+++ b/src/ldt/ldt/static/ldt/metadataplayer/DailymotionPlayer.js Fri Oct 02 10:24:05 2015 +0200
@@ -9,96 +9,142 @@
};
IriSP.Widgets.DailymotionPlayer.prototype.draw = function() {
-
+
if (typeof this.video === "undefined") {
this.video = this.media.video;
}
this.height = this.height || Math.floor(this.width / this.aspect_ratio);
-
+
var _media = this.media,
+ videoid = null,
_this = this,
- _pauseState = true;
-
- /* Dailymotion utilise un système de fonctions référencées dans
- * des variables globales pour la gestion des événements.
- */
-
- window.onDailymotionPlayerReady = function() {
+ state = {
+ pause: true,
+ apiready: false,
+ volume: 0,
+ time: 0,
+ duration: 0
+ };
+
+ var m = this.video.match(/www.dailymotion.com\/video\/(.+)/);
+ if (m) {
+ videoid = m[1];
+ }
- var _player = document.getElementById(_this.container);
-
+ var player_url = Mustache.to_html('{{ protocol }}//www.dailymotion.com/embed/video/{{ videoid }}', {
+ protocol: document.location.protocol.search('http') == 0 ? document.location.protocol : 'http:',
+ videoid: videoid
+ });
+ var params = {
+ 'api': 'postMessage',
+ 'chromeless': 1,
+ 'id': 'dm_player',
+ 'related': 0,
+ 'autoplay': 1
+ };
+
+ _this.$.html(Mustache.to_html('<iframe id="{{ id }}" src="{{ player_url }}?{{ params }}" width="{{ width }}" height="{{ height }}" frameborder="0"></iframe>', {
+ player_url: player_url,
+ params: Object.keys(params).reduce(function(a,k){a.push(k+'='+encodeURIComponent(params[k]));return a;},[]).join('&'),
+ width: this.width,
+ height: this.height,
+ id: params.id
+ }));
+
+ function setup_media_methods () {
+ var dest = _this.$.find("#" + params.id)[0].contentWindow;
+ var execute = function(c, v) {
+ if (v !== undefined)
+ c = c + "=" + v;
+ dest.postMessage(c, "*");
+ };
+
_media.getCurrentTime = function() {
- return new IriSP.Model.Time(1000*_player.getCurrentTime());
+ return state.time;
};
_media.getVolume = function() {
- return _player.getVolume() / 100;
+ return state.volume;
};
_media.getPaused = function() {
- return _pauseState;
+ return state.pause;
};
_media.getMuted = function() {
- return _player.isMuted();
+ return state.muted;
};
_media.setCurrentTime = function(_milliseconds) {
- _seekPause = _pauseState;
- return _player.seekTo(_milliseconds / 1000);
+ execute("seek", _milliseconds / 1000);
};
_media.setVolume = function(_vol) {
- return _player.setVolume(Math.floor(_vol*100));
+ execute("volume", _vol * 100);
};
_media.mute = function() {
- return _player.mute();
+ execute("muted", 1);
};
_media.unmute = function() {
- return _player.unMute();
+ execute("muted", 0);
};
_media.play = function() {
- return _player.playVideo();
+ execute("play");
};
_media.pause = function() {
- return _player.pauseVideo();
+ execute("pause");
};
-
- _player.addEventListener("onStateChange", "onDailymotionStateChange");
- _player.addEventListener("onVideoProgress", "onDailymotionVideoProgress");
-
- _player.cueVideoByUrl(_this.video);
-
- _media.trigger("loadedmetadata");
- };
-
- window.onDailymotionStateChange = function(_state) {
- switch(_state) {
- case 1:
- _media.trigger("play");
- _pauseState = false;
- break;
-
- case 2:
- _media.trigger("pause");
- _pauseState = true;
- break;
-
- case 3:
- _media.trigger("seeked");
- break;
- }
- };
-
- window.onDailymotionVideoProgress = function(_progress) {
- _media.trigger("timeupdate", new IriSP.Model.Time(_progress.mediaTime * 1000));
- };
-
- var params = {
- "allowScriptAccess" : "always",
- "wmode": "opaque"
- };
-
- var atts = {
- id : this.container
};
- swfobject.embedSWF("http://www.dailymotion.com/swf?chromeless=1&enableApi=1", this.container, this.width, this.height, "8", null, null, params, atts);
-
-};
\ No newline at end of file
+ window.addEventListener("message", function (event) {
+ // Parse event.data (query-string for to object)
+
+ // Duck-checking if event.data is a string
+ if (event.data.split === undefined)
+ return;
+
+ var info = event.data.split("&").map( function(s) { return s.split("="); }).reduce( function(o, v) { o[v[0]] = decodeURIComponent(v[1]); return o; }, {});
+
+ switch (info.event) {
+ case "apiready":
+ state.apiready = true;
+ setup_media_methods();
+ break;
+ //case "canplay":
+ // break;
+ case "durationchange":
+ if (info.duration.slice(-2) == "sc") {
+ state.duration = 1000 * Number(info.duration.slice(0, -2));
+ _media.setDuration(state.duration);
+ }
+ break;
+ case "ended":
+ state.pause = true;
+ break;
+ case "loadedmetadata":
+ _media.trigger("loadedmetadata");
+ break;
+ case "pause":
+ state.pause = true;
+ _media.trigger("pause");
+ break;
+ case "play":
+ state.pause = false;
+ _media.trigger("play");
+ break;
+ //case "playing":
+ // break;
+ //case "progress":
+ // Loading progress
+ // break;
+ case "seeked":
+ state.time = new IriSP.Model.Time(1000 * Number(info.time));
+ _media.trigger("seeked");
+ break;
+ case "timeupdate":
+ state.time = new IriSP.Model.Time(1000 * Number(info.time));
+ _media.trigger("timeupdate", state.time);
+ break;
+ case "volumechange":
+ state.muted = (info.muted == "true");
+ state.volume = Number(info.volume) / 100;
+ break;
+ }
+ }, false);
+};
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/src/ldt/ldt/static/ldt/metadataplayer/EnrichedPlan.css Fri Oct 02 10:24:05 2015 +0200
@@ -0,0 +1,207 @@
+.Ldt-EnrichedPlan-Slide {
+ border-bottom: 2px dotted #ccc;
+ padding-top: 4px;
+ cursor: pointer;
+}
+
+.Ldt-EnrichedPlan-SlideItem {
+ max-height: 3000px;
+ transition: max-height .6s;
+}
+
+.Ldt-EnrichedPlan-SlideItem.filtered_out {
+ max-height: 0px;
+ overflow: hidden;
+}
+
+.Ldt-EnrichedPlan-SlideTimecode {
+ display: inline-block;
+ width: 24px;
+ color: #999 !important;
+ font-size: 9px !important;
+ width: 24px;
+ vertical-align: top;
+}
+
+.Ldt-EnrichedPlan-SlideThumbnail {
+ display: inline-block;
+ width: 180px;
+ height: 100px;
+ padding-left: 10px;
+ margin: 0;
+ vertical-align: top;
+}
+
+.Ldt-EnrichedPlan-SlideThumbnail img {
+ max-width: 180px;
+ max-height: 100px;
+ margin: auto;
+ border: 1px solid #ccc;
+}
+
+.Ldt-EnrichedPlan-SlideContent {
+ display: inline-block;
+ width: calc(100% - 220px);
+ transition: width .4s;
+}
+
+.Ldt-EnrichedPlan-SlideThumbnail.filtered_out + .Ldt-EnrichedPlan-SlideContent {
+ width: calc(100% - 40px);
+}
+
+.Ldt-EnrichedPlan-SlideTitle {
+ display: inline-block;
+ font-size: 14px;
+ width: 100%;
+ height: 1em;
+ overflow: hidden;
+ white-space: nowrap;
+ text-overflow: ellipsis;
+}
+
+.Ldt-EnrichedPlan-SlideTitle1 {
+ text-transform: uppercase;
+ font-size: 13px;
+ font-weight: 600;
+}
+
+.Ldt-EnrichedPlan-Note {
+ font-weight: normal;
+ font-size: 14px;
+ font-family: Roboto-italic;
+}
+.Ldt-EnrichedPlan-Note:hover {
+ background-color: #eee;
+}
+
+.Ldt-EnrichedPlan-Note-Teacher {
+ color: #e5007e;
+ font-style: italic;
+}
+.Ldt-EnrichedPlan-Note-Own {
+ color: #66ccff;
+}
+.Ldt-EnrichedPlan-Note-Other {
+ color: #996633;
+}
+
+.Ldt-EnrichedPlan-Note-Text {
+ line-height: 22px;
+ word-wrap: break-word;
+}
+
+.Ldt-EnrichedPlan-Note-Author {
+ text-transform: uppercase;
+ font-size: 10px;
+}
+
+.Ldt-EnrichedPlan-Content {
+ margin-top: 37px;
+}
+
+.Ldt-EnrichedPlan-Controls {
+ height: 36px;
+ padding: 9px 0px 6px 0px;
+ border-bottom: 1px solid #000;
+ overflow-y: hidden;
+ overflow-x: hidden;
+ position: absolute;
+ top: 0px;
+ left: 0px;
+ right: 0px;
+ z-index: 1;
+ background-color: #fff;
+}
+
+.Ldt-EnrichedPlan-Control-Label {
+ display: inline-block;
+ text-transform: uppercase;
+ line-height: 10px;
+ font-family: Roboto;
+ font-size: 10px;
+ font-weight: 100;
+ width: 80px;
+ position: relative;
+}
+.Ldt-EnrichedPlan-Controls .Ldt-EnrichedPlan-Search-Input {
+ float: right;
+ font-family: Roboto;
+ font-size: 16px;
+ width: calc(100% - 340px);
+}
+
+.Ldt-EnrichedPlan-Note.non_matching {
+ display: none;
+}
+
+.Ldt-EnrichedPlan-Control- {
+ font-style: normal;
+}
+ /**********************************************************/
+/* Base for label styling */
+.Ldt-EnrichedPlan-Control-Checkbox:not(:checked),
+.Ldt-EnrichedPlan-Control-Checkbox:checked {
+ position: absolute;
+ left: -9999px;
+}
+.Ldt-EnrichedPlan-Control-Checkbox:not(:checked) + label,
+.Ldt-EnrichedPlan-Control-Checkbox:checked + label {
+ position: relative;
+ padding-left: 20px;
+ cursor: pointer;
+}
+
+/* checkbox aspect */
+.Ldt-EnrichedPlan-Control-Checkbox:not(:checked) + label:before,
+.Ldt-EnrichedPlan-Control-Checkbox:checked + label:before {
+ content: '';
+ position: absolute;
+ left:0; top: 2px;
+ width: 13px; height: 13px;
+ border: 1px solid #aaa;
+}
+/* checked mark aspect */
+.Ldt-EnrichedPlan-Control-Checkbox:not(:checked) + label:after,
+.Ldt-EnrichedPlan-Control-Checkbox:checked + label:after {
+ content: '\2a2f';
+ font-style: normal;
+ position: absolute;
+ top: 3px; left: -1px;
+ font-size: 20px;
+ transition: all .2s;
+}
+/* checked mark aspect changes */
+.Ldt-EnrichedPlan-Control-Checkbox:not(:checked) + label:after {
+ opacity: 0;
+}
+.Ldt-EnrichedPlan-Control-Checkbox:checked + label:after {
+ opacity: 1;
+}
+/* disabled checkbox */
+.Ldt-EnrichedPlan-Control-Checkbox:disabled:not(:checked) + label:before,
+.Ldt-EnrichedPlan-Control-Checkbox:disabled:checked + label:before {
+ box-shadow: none;
+ border-color: #bbb;
+ background-color: #ddd;
+}
+.Ldt-EnrichedPlan-Control-Checkbox:disabled:checked + label:after {
+ color: #999;
+}
+.Ldt-EnrichedPlan-Control-Checkbox:disabled + label {
+ color: #aaa;
+}
+/* accessibility */
+.Ldt-EnrichedPlan-Control-Checkbox:checked:focus + label:before,
+.Ldt-EnrichedPlan-Control-Checkbox:not(:checked):focus + label:before {
+ border: 1px dotted blue;
+}
+
+/* hover style just for information */
+label:hover:before {
+ border: 1px solid #4778d9!important;
+}
+
+/* hover style just for information */
+label:hover:before {
+ background-color: #ededed;
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/src/ldt/ldt/static/ldt/metadataplayer/EnrichedPlan.js Fri Oct 02 10:24:05 2015 +0200
@@ -0,0 +1,145 @@
+/* TODO
+- add callbacks
+ */
+
+IriSP.Widgets.EnrichedPlan = function(player, config) {
+ IriSP.Widgets.Widget.call(this, player, config);
+}
+
+IriSP.Widgets.EnrichedPlan.prototype = new IriSP.Widgets.Widget();
+
+IriSP.Widgets.EnrichedPlan.prototype.defaults = {
+ // Main type for slide segmentation
+ annotation_type: "Slides",
+ // If no annotation type list is specified, use all other types
+ annotation_types: [],
+ show_controls: true,
+ show_slides: true,
+ show_teacher_notes: true,
+ show_other_notes: true,
+ show_own_notes: true
+}
+
+IriSP.Widgets.EnrichedPlan.prototype.template =
+ '<div class="Ldt-EnrichedPlan-Container">'
+ + '{{#show_controls}}<form class="Ldt-EnrichedPlan-Controls">'
+ + ' <input id="{{prefix}}teacher_note_checkbox" class="Ldt-EnrichedPlan-Control-Checkbox Ldt-EnrichedPlan-Note-Teacher" {{#show_teacher_notes}}checked{{/show_teacher_notes}} type="checkbox">'
+ + ' <label for="{{prefix}}teacher_note_checkbox" class="Ldt-EnrichedPlan-Control-Label Ldt-EnrichedPlan-Note-Teacher">Notes Enseignant</label>'
+ + ' <input id="{{prefix}}other_note_checkbox" class="Ldt-EnrichedPlan-Control-Checkbox Ldt-EnrichedPlan-Note-Other" {{#show_other_notes}}checked{{/show_other_notes}} type="checkbox">'
+ + ' <label for="{{prefix}}other_note_checkbox" class="Ldt-EnrichedPlan-Control-Label Ldt-EnrichedPlan-Note-Other">Notes Autres</label>'
+ + ' <input id="{{prefix}}simplified_plan_checkbox" class="Ldt-EnrichedPlan-Control-Checkbox Ldt-EnrichedPlan-Note-Own" {{#show_own_notes}}checked{{/show_own_notes}} type="checkbox">'
+ + ' <label for="{{prefix}}simplified_plan_checkbox" class="Ldt-EnrichedPlan-Control-Label Ldt-EnrichedPlan-Note-Own">Notes perso.</label>'
+ + ' <input id="{{prefix}}slide_display_checkbox" class="Ldt-EnrichedPlan-Control-Checkbox Ldt-EnrichedPlan-Slide-Display" {{#show_slides}}checked{{/show_slides}} type="checkbox">'
+ + ' <label for="{{prefix}}slide_display_checkbox" class="Ldt-EnrichedPlan-Control-Label Ldt-EnrichedPlan-Slide-Display">Diapo<br/> </label>'
+ + ' <input class="Ldt-EnrichedPlan-Search-Input" type="search" incremental placeholder="Recherchez"/>'
+ + '</form>{{/show_controls}}'
+ + '<div class="Ldt-EnrichedPlan-Content"></div>'
+ + '</div>';
+
+IriSP.Widgets.EnrichedPlan.prototype.slideTemplate =
+ '<div data-id="{{ id }}" class="Ldt-EnrichedPlan-Slide">'
+ + ' <div class="Ldt-EnrichedPlan-SlideItem Ldt-EnrichedPlan-SlideTimecode">{{ begin }}</div>'
+ + ' <div data-timecode="{{begintc}}" class="Ldt-EnrichedPlan-SlideItem {{^show_slides}}filtered_out{{/show_slides}} Ldt-EnrichedPlan-SlideThumbnail Ldt-EnrichedPlan-Slide-Display"><img title="{{ begin }} - {{ atitle }}" src="{{ thumbnail }}"></div>'
+ + ' <div class="Ldt-EnrichedPlan-SlideContent">'
+ + ' <div data-timecode="{{begintc}}" class="Ldt-EnrichedPlan-SlideTitle Ldt-EnrichedPlan-SlideTitle{{ level }}">{{ atitle }}</div>'
+ + ' <div class="Ldt-EnrichedPlan-SlideNotes">{{{ notes }}}</div>'
+ + ' </div>'
+ + '</div>';
+
+IriSP.Widgets.EnrichedPlan.prototype.annotationTemplate = '<div title="{{ begin }} - {{ atitle }}" data-id="{{ id }}" data-timecode="{{begintc}}" class="Ldt-EnrichedPlan-SlideItem Ldt-EnrichedPlan-Note {{category}} {{filtered}}"><span class="Ldt-EnrichedPlan-Note-Text">{{{ text }}}</span> <span class="Ldt-EnrichedPlan-Note-Author">{{ author }}</span></div>';
+
+IriSP.Widgets.EnrichedPlan.prototype.draw = function() {
+ var _this = this;
+ // Generate a unique prefix, so that ids of input fields
+ // (necessary for label association) are unique too.
+ _this.prefix = "TODO";
+ // slides content: title, level (for toc)
+ var _slides = this.getWidgetAnnotations().sortBy(function(_annotation) {
+ return _annotation.begin;
+ });
+ // All other annotations
+ var _annotations = this.media.getAnnotations().filter( function (a) {
+ return a.getAnnotationType().title != _this.annotation_type;
+ }).sortBy(function(_annotation) {
+ return _annotation.begin;
+ });
+
+ // Reference annotations in each slide: assume that end time is
+ // correctly set.
+ _slides.forEach( function (slide) {
+ slide.annotations = _annotations.filter( function (a) {
+ return a.begin >= slide.begin && a.begin <= slide.end;
+ });
+ });
+
+ _this.renderTemplate();
+ var container = _this.$.find('.Ldt-EnrichedPlan-Container');
+ var content = _this.$.find('.Ldt-EnrichedPlan-Content');
+
+ // Returns the note category: Own, Other, Teacher
+ function note_category(a) {
+ return a.title.indexOf('Anonyme') < 0 ? "Own" : "Other";
+ };
+
+ _slides.forEach(function(slide) {
+ var _html = Mustache.to_html(_this.slideTemplate, {
+ id : slide.id,
+ atitle : IriSP.textFieldHtml(slide.title),
+ level: slide.content.level || 1,
+ begin : slide.begin.toString(),
+ begintc: slide.begin.milliseconds,
+ thumbnail: slide.thumbnail,
+ show_slides: _this.show_slides,
+ notes: slide.annotations.map( function (a) {
+ return Mustache.to_html(_this.annotationTemplate, {
+ id: a.id,
+ text: IriSP.textFieldHtml(a.description || a.title),
+ author: a.creator,
+ begin: a.begin.toString(),
+ begintc: a.begin.milliseconds,
+ atitle: a.title.slice(0, 20),
+ // FIXME: Temporary hack waiting for a proper metadata definition
+ category: "Ldt-EnrichedPlan-Note-" + note_category(a),
+ filtered: ( (note_category(a) == 'Own' && ! _this.show_own_notes)
+ || (note_category(a) == 'Other' && ! _this.show_other_notes)
+ || (note_category(a) == 'Teacher' && ! _this.show_teacher_notes) ) ? 'filtered_out' : ''
+ });
+ }).join("\n")
+ });
+ var _el = IriSP.jQuery(_html);
+ content.append(_el);
+ });
+
+ container.on("click", "[data-timecode]", function () {
+ _this.media.setCurrentTime(Number(this.dataset.timecode));
+ });
+
+ container.on("click", ".Ldt-EnrichedPlan-Control-Checkbox", function () {
+ var classname = _.first(_.filter(this.classList, function (s) { return s != "Ldt-EnrichedPlan-Control-Checkbox"; }));
+ if (classname !== undefined) {
+ if ($(this).is(':checked')) {
+ content.find(".Ldt-EnrichedPlan-Slide ." + classname).removeClass("filtered_out");
+ } else {
+ content.find(".Ldt-EnrichedPlan-Slide ." + classname).addClass("filtered_out");
+ }
+ }
+
+ });
+
+ container.find(".Ldt-EnrichedPlan-Search-Input").on("search", function () {
+ var q = $(this).val().toLocaleLowerCase();
+ if (q === "") {
+ // Show all
+ content.find(".Ldt-EnrichedPlan-Note").removeClass("non_matching");
+ } else {
+ $(".Ldt-EnrichedPlan-Note").each( function () {
+ var node = $(this);
+ if (node.text().toLocaleLowerCase().indexOf(q) > -1) {
+ node.removeClass("non_matching");
+ } else {
+ node.addClass("non_matching");
+ }
+ });
+ }
+ });
+};
--- a/src/ldt/ldt/static/ldt/metadataplayer/ImageDisplay.css Fri Sep 18 16:10:29 2015 +0200
+++ b/src/ldt/ldt/static/ldt/metadataplayer/ImageDisplay.css Fri Oct 02 10:24:05 2015 +0200
@@ -1,6 +1,10 @@
-/* Nothing */
.Ldt-ImageDisplay-Container {
- margin: auto;
+ width: 100%;
+ height: 100%;
+ background-color: white;
+ background-repeat: no-repeat;
+ background-position: center;
+ background-size: contain;
}
.Ldt-ImageDisplay-Image {
@@ -9,7 +13,7 @@
}
.Ldt-ImageDisplay-Overlay {
- width: 20%;
+ width: 30%;
min-width: 20px;
height: 100%;
opacity: 0.1;
@@ -23,10 +27,10 @@
.Ldt-ImageDisplay-Overlay-Left {
left: 0px;
- cursor: url(img/hand_left.png), pointer;
+ cursor: url(img/left_arrow.svg) 20 20, pointer;
}
.Ldt-ImageDisplay-Overlay-Right {
right: 0px;
- cursor: url(img/hand_right.png), pointer;
+ cursor: url(img/right_arrow.svg) 20 20, pointer;
}
--- a/src/ldt/ldt/static/ldt/metadataplayer/ImageDisplay.js Fri Sep 18 16:10:29 2015 +0200
+++ b/src/ldt/ldt/static/ldt/metadataplayer/ImageDisplay.js Fri Oct 02 10:24:05 2015 +0200
@@ -7,27 +7,27 @@
IriSP.Widgets.ImageDisplay.prototype = new IriSP.Widgets.Widget();
IriSP.Widgets.ImageDisplay.prototype.defaults = {
- annotation_type: "Slides",
+ annotation_type: "Slides"
// container: "imageContainer"
}
-IriSP.Widgets.ImageDisplay.prototype.template = '<div class="Ldt-ImageDisplay-Container"><img class="Ldt-ImageDisplay-Image" title="" alt="Slide Image" src=""/><div class="Ldt-ImageDisplay-Overlay Ldt-ImageDisplay-Overlay-Left"></div><div class="Ldt-ImageDisplay-Overlay Ldt-ImageDisplay-Overlay-Right"></div></div>';
+IriSP.Widgets.ImageDisplay.prototype.template = '<div class="Ldt-ImageDisplay-Container"><div class="Ldt-ImageDisplay-Overlay Ldt-ImageDisplay-Overlay-Left"></div><div class="Ldt-ImageDisplay-Overlay Ldt-ImageDisplay-Overlay-Right"></div></div>';
IriSP.Widgets.ImageDisplay.prototype.annotationTemplate = '';
IriSP.Widgets.ImageDisplay.prototype.update = function(annotation) {
// Update the widget with data corresponding to the annotation
- this.image.setAttribute("title", IriSP.textFieldHtml(annotation.title) + " - " + annotation.begin.toString());
- this.image.setAttribute("src", annotation.thumbnail);
+ this.image.css("background-image", "url(" + annotation.thumbnail + ")");
+ this.image.attr("title", IriSP.textFieldHtml(annotation.title) + " - " + annotation.begin.toString());
};
-IriSP.Widgets.ImageDisplay.prototype.draw = function() {
+IriSP.Widgets.ImageDisplay.prototype.draw = function() {
var _annotations = this.getWidgetAnnotations().sortBy(function(_annotation) {
return _annotation.begin;
});
var _this = this;
_this.renderTemplate();
- _this.image = _this.$.find("img")[0];
+ _this.image = _this.$.find(".Ldt-ImageDisplay-Container");
_this.$.find(".Ldt-ImageDisplay-Overlay-Left").on("click", function () { _this.navigate(-1); });
_this.$.find(".Ldt-ImageDisplay-Overlay-Right").on("click", function () { _this.navigate(+1); });
--- a/src/ldt/ldt/static/ldt/metadataplayer/LdtPlayer-core.js Fri Sep 18 16:10:29 2015 +0200
+++ b/src/ldt/ldt/static/ldt/metadataplayer/LdtPlayer-core.js Fri Oct 02 10:24:05 2015 +0200
@@ -82,7 +82,7 @@
var list = [],
positions = [],
text = _text.replace(/(^\s+|\s+$)/g,'');
-
+
function addToList(_rx, _startHtml, _endHtml) {
while(true) {
var result = _rx.exec(text);
@@ -101,11 +101,11 @@
positions.push(end);
}
}
-
+
if (_regexp) {
addToList(_regexp, '<span class="Ldt-Highlight">', '</span>');
}
-
+
addToList(/(https?:\/\/)?[\w\d\-]+\.[\w\d\-]+\S+/gm, function(matches) {
return '<a href="' + (matches[1] ? '' : 'http://') + matches[0] + '" target="_blank">';
}, '</a>');
@@ -114,19 +114,19 @@
}, '</a>');
addToList(/\*[^*]+\*/gm, '<b>', '</b>');
addToList(/[\n\r]+/gm, '', '<br />');
-
+
IriSP._(_extend).each(function(x) {
addToList.apply(null, x);
});
-
+
positions = IriSP._(positions)
.chain()
.uniq()
.sortBy(function(p) { return parseInt(p); })
.value();
-
+
var res = "", lastIndex = 0;
-
+
for (var i = 0; i < positions.length; i++) {
var pos = positions[i];
res += text.substring(lastIndex, pos);
@@ -144,11 +144,11 @@
}
lastIndex = pos;
}
-
+
res += text.substring(lastIndex);
-
+
return res;
-
+
};
IriSP.log = function() {
@@ -161,11 +161,27 @@
jqSel.attr("draggable", "true").on("dragstart", function(_event) {
var d = (typeof data === "function" ? data.call(this) : data);
try {
+ if (d.html === undefined && d.uri && d.text) {
+ d.html = '<a href="' + d.uri + '">' + d.text + '</a>';
+ }
IriSP._(d).each(function(v, k) {
- if (v) {
+ if (v && k != 'text' && k != 'html') {
_event.originalEvent.dataTransfer.setData("text/x-iri-" + k, v);
}
});
+ if (d.uri && d.text) {
+ _event.originalEvent.dataTransfer.setData("text/x-moz-url", d.uri + "\n" + d.text.replace("\n", " "));
+ _event.originalEvent.dataTransfer.setData("text/plain", d.text + " " + d.uri);
+ }
+ // Define generic text/html and text/plain last (least
+ // specific types, see
+ // https://developer.mozilla.org/en-US/docs/Web/Guide/HTML/Drag_operations#Drag_Data)
+ if (d.html !== undefined) {
+ _event.originalEvent.dataTransfer.setData("text/html", d.html);
+ }
+ if (d.text !== undefined && ! d.uri) {
+ _event.originalEvent.dataTransfer.setData("text/plain", d.text);
+ }
} catch(err) {
_event.originalEvent.dataTransfer.setData("Text", JSON.stringify(d));
}
@@ -180,6 +196,62 @@
});
};
+IriSP.timestamp2ms = function(t) {
+ // Convert timestamp to numeric value
+ // It accepts the following forms:
+ // [h:mm:ss] [mm:ss] [ss]
+ var s = t.split(":").reverse();
+ while (s.length < 3) {
+ s.push("0");
+ }
+ return 1000 * (3600 * parseInt(s[2], 10) + 60 * parseInt(s[1], 10) + parseInt(s[0], 10));
+};
+
+IriSP.setFullScreen= function(elem, value) {
+ // Set fullscreen on or off
+ if (value) {
+ if (elem.requestFullscreen) {
+ elem.requestFullscreen();
+ } else if (elem.mozRequestFullScreen) {
+ elem.mozRequestFullScreen();
+ } else if (elem.webkitRequestFullscreen) {
+ elem.webkitRequestFullscreen();
+ } else if (elem.msRequestFullscreen) {
+ elem.msRequestFullscreen();
+ }
+ } else {
+ if (document.exitFullscreen) {
+ document.exitFullscreen();
+ } else if (document.msExitFullscreen) {
+ document.msExitFullscreen();
+ } else if (document.mozCancelFullScreen) {
+ document.mozCancelFullScreen();
+ } else if (document.webkitExitFullscreen) {
+ document.webkitExitFullscreen();
+ }
+ }
+};
+
+IriSP.isFullscreen = function() {
+ return (document.fullscreenElement || document.webkitFullscreenElement || document.mozFullScreenElement || document.msFullscreenElement);
+};
+
+IriSP.getFullscreenElement = function () {
+ return (document.fullscreenElement
+ || document.webkitFullscreenElement
+ || document.mozFullScreenElement
+ || document.msFullscreenElement
+ || undefined);
+};
+
+IriSP.getFullscreenEventname = function () {
+ return ((document.exitFullscreen && "fullscreenchange")
+ || (document.webkitExitFullscreen && "webkitfullscreenchange")
+ || (document.mozExitFullScreen && "mozfullscreenchange")
+ || (document.msExitFullscreen && "msfullscreenchange")
+ || "");
+};
+
/* js is where data is stored in a standard form, whatever the serializer */
//TODO: Separate Project-specific data from Source
@@ -943,6 +1015,19 @@
extendPrototype(Annotation, BaseElement);
+/* Set begin and end in one go, to avoid undesired side-effects in
+ * setBegin/setEnd interaction */
+Annotation.prototype.setBeginEnd = function(_beginMs, _endMs) {
+ _beginMs = Math.max(0,_beginMs);
+ _endMs = Math.max(0,_endMs);
+ if (_endMs < _beginMs)
+ _endMs = _beginMs;
+ this.begin.setMilliseconds(_beginMs);
+ this.end.setMilliseconds(_endMs);
+ this.trigger("change-begin");
+ this.trigger("change-end");
+};
+
Annotation.prototype.setBegin = function(_beginMs) {
this.begin.setMilliseconds(Math.max(0,_beginMs));
this.trigger("change-begin");
@@ -1470,7 +1555,17 @@
videoEl.append(_srcNode);
}
}
-
+ if (opts.subtitle) {
+ var _trackNode = IriSP.jQuery('<track>');
+ _trackNode.attr({
+ label: "Subtitles",
+ kind: "subtitles",
+ srclang: "fr",
+ src: opts.subtitle,
+ default: ""
+ });
+ videoEl.append(_trackNode);
+ }
jqselector.html(videoEl);
var mediaEl = videoEl[0];
@@ -1569,6 +1664,13 @@
media.trigger("seeked");
});
+ videoEl.on("click", function() {
+ if (mediaEl.paused) {
+ media.play();
+ } else {
+ media.pause();
+ };
+ });
};
/* START contentapi-serializer.js */
@@ -1745,7 +1847,7 @@
if (typeof _data.content.img !== "undefined" && _data.content.img.src !== "undefined") {
_res.thumbnail = _data.content.img.src;
}
- _res.created = IriSP.Model.isoToDate(_data.created);
+ _res.created = IriSP.Model.isoToDate((_data.meta ? _data.meta['dc:created'] : "") ||_data.created);
if (typeof _data.color !== "undefined") {
var _c = parseInt(_data.color).toString(16);
while (_c.length < 6) {
@@ -1758,8 +1860,7 @@
_res.setAnnotationType(_data.meta["id-ref"]);
_res.setTags(IriSP._(_data.tags).pluck("id-ref"));
_res.keywords = _res.getTagTexts();
- _res.setBegin(_data.begin);
- _res.setEnd(_data.end);
+ _res.setBeginEnd(_data.begin, _data.end);
_res.creator = _data.meta["dc:creator"] || "";
_res.project = _data.meta.project || "";
if (typeof _data.meta["dc:source"] !== "undefined" && typeof _data.meta["dc:source"].content !== "undefined") {
@@ -1957,9 +2058,11 @@
serializeAnnotation : function(_data, _source) {
var _annType = _data.getAnnotationType();
return {
+ id: _data.id,
begin: _data.begin.milliseconds,
end: _data.end.milliseconds,
content: {
+ data: (_data.content ? _data.content.data || {} : {}),
description: _data.description,
title: _data.title,
audio: _data.audio
@@ -1972,7 +2075,9 @@
type: ( typeof _annType.dont_send_id !== "undefined" && _annType.dont_send_id ? "" : _annType.id ),
meta: {
created: _data.created,
- creator: _data.creator
+ creator: _data.creator,
+ modified: _data.modified,
+ contributor: _data.contributor
}
};
},
@@ -2003,11 +2108,13 @@
return _tag.id;
});
_ann.setTags(_tagIds);
- _ann.setBegin(_anndata.begin);
- _ann.setEnd(_anndata.end);
+ _ann.setBeginEnd(_anndata.begin, _anndata.end);
if (typeof _anndata.content.audio !== "undefined" && _anndata.content.audio.href) {
_ann.audio = _anndata.content.audio;
- }
+ };
+ if (_anndata.content.data) {
+ _ann.content = { data: _anndata.content.data };
+ };
_source.getAnnotations().push(_ann);
},
serialize : function(_source) {
@@ -2017,7 +2124,7 @@
if (typeof _data == "string") {
_data = JSON.parse(_data);
}
-
+
_source.addList('tag', new IriSP.Model.List(_source.directory));
_source.addList('annotationType', new IriSP.Model.List(_source.directory));
_source.addList('annotation', new IriSP.Model.List(_source.directory));
@@ -2025,7 +2132,8 @@
}
};
-/* End ldt_annotate serializer *//* ldt_localstorage serializer: Used to store personal annotations in local storage */
+/* End ldt_annotate serializer */
+/* ldt_localstorage serializer: Used to store personal annotations in local storage */
if (typeof IriSP.serializers === "undefined") {
IriSP.serializers = {};
@@ -2035,9 +2143,11 @@
serializeAnnotation : function(_data, _source) {
var _annType = _data.getAnnotationType();
return {
+ id: _data.id,
begin: _data.begin.milliseconds,
end: _data.end.milliseconds,
content: {
+ data: (_data.content ? _data.content.data || {} : {}),
description: _data.description,
title: _data.title,
audio: _data.audio
@@ -2048,7 +2158,9 @@
type: ( typeof _annType.dont_send_id !== "undefined" && _annType.dont_send_id ? "" : _annType.id ),
meta: {
created: _data.created,
- creator: _data.creator
+ creator: _data.creator,
+ modified: _data.modified,
+ contributor: _data.contributor
}
};
},
@@ -2058,6 +2170,8 @@
_ann.title = _anndata.content.title || "";
_ann.creator = _anndata.meta.creator || "";
_ann.created = new Date(_anndata.meta.created);
+ _ann.contributor = _anndata.meta.contributor || "";
+ _ann.modified = new Date(_anndata.meta.modified);
_ann.setMedia(_anndata.media, _source);
var _anntype = _source.getElement(_anndata.type);
if (!_anntype) {
@@ -2079,11 +2193,13 @@
return _tag.id;
});
_ann.setTags(_tagIds);
- _ann.setBegin(_anndata.begin);
- _ann.setEnd(_anndata.end);
+ _ann.setBeginEnd(_anndata.begin, _anndata.end);
if (typeof _anndata.content.audio !== "undefined" && _anndata.content.audio.href) {
_ann.audio = _anndata.content.audio;
- }
+ };
+ if (_anndata.content.data) {
+ _ann.content = { data: _anndata.content.data };
+ };
_source.getAnnotations().push(_ann);
},
serialize : function(_source) {
@@ -2168,8 +2284,8 @@
backboneRelational: "backbone-relational.js",
paper: "paper.js",
jqueryMousewheel: "jquery.mousewheel.min.js",
- splitter: "jquery.splitter.js",
- cssSplitter: "jquery.splitter.css",
+ splitter: "jquery.touchsplitter.js",
+ cssSplitter: "jquery.touchsplitter.css",
renkanPublish: "renkan.js",
processing: "processing-1.3.6.min.js",
recordMicSwf: "record_mic.swf",
@@ -2259,7 +2375,7 @@
};
IriSP.guiDefaults = {
- width : 640,
+ width : 640,
container : 'LdtPlayer',
spacer_div_height : 0,
widgets: []
@@ -2312,23 +2428,21 @@
ns.log("IriSP.Metadataplayer.prototype.loadLibs");
var $L = $LAB
.queueScript(ns.getLib("Mustache"));
-
formerJQuery = !!window.jQuery;
former$ = !!window.$;
formerUnderscore = !!window._;
-
+
if (typeof ns.jQuery === "undefined") {
$L.queueScript(ns.getLib("jQuery"));
}
-
+
if (typeof ns._ === "undefined") {
$L.queueScript(ns.getLib("underscore"));
}
-
+
if (typeof window.JSON == "undefined") {
$L.queueScript(ns.getLib("json"));
}
-
$L.queueWait().queueScript(ns.getLib("jQueryUI")).queueWait();
/* widget specific requirements */
@@ -2340,9 +2454,8 @@
}
}
}
-
+
var _this = this;
-
$L.queueWait(function() {
_this.onLibsLoaded();
});
@@ -2352,6 +2465,7 @@
Metadataplayer.prototype.onLibsLoaded = function() {
ns.log("IriSP.Metadataplayer.prototype.onLibsLoaded");
+
if (typeof ns.jQuery === "undefined" && typeof window.jQuery !== "undefined") {
ns.jQuery = window.jQuery;
if (former$ || formerJQuery) {
@@ -2364,9 +2478,10 @@
_.noConflict();
}
}
+
ns.loadCss(ns.getLib("cssjQueryUI"));
ns.loadCss(this.config.css);
-
+
this.$ = ns.jQuery('#' + this.config.container);
this.$.css({
"width": this.config.width,
@@ -2375,7 +2490,7 @@
if (typeof this.config.height !== "undefined") {
this.$.css("height", this.config.height);
}
-
+
this.widgets = [];
var _this = this;
ns._(this.config.widgets).each(function(widgetconf, key) {
@@ -2388,9 +2503,9 @@
});
});
this.$.find('.Ldt-Loader').detach();
-
+
this.widgetsLoaded = false;
-
+
this.on("widget-loaded", function() {
if (_this.widgetsLoaded) {
return;
@@ -2402,7 +2517,44 @@
_this.widgetsLoaded = true;
_this.trigger("widgets-loaded");
}
- });
+ });
+};
+
+Metadataplayer.prototype.loadLocalAnnotations = function(localsourceidentifier) {
+ if (this.localSource === undefined)
+ this.localSource = this.sourceManager.newLocalSource({serializer: IriSP.serializers['ldt_localstorage']});
+ // Load current local annotations
+ if (localsourceidentifier) {
+ // Allow to override localsourceidentifier when necessary (usually at init time)
+ this.localSource.identifier = localsourceidentifier;
+ }
+ this.localSource.deSerialize(window.localStorage[this.localSource.identifier] || "[]");
+ return this.localSource;
+};
+
+Metadataplayer.prototype.saveLocalAnnotations = function() {
+ // Save annotations back to localstorage
+ window.localStorage[this.localSource.identifier] = this.localSource.serialize();
+ // Merge modifications into widget source
+ // this.source.merge(this.localSource);
+};
+
+Metadataplayer.prototype.addLocalAnnotation = function(a) {
+ this.loadLocalAnnotations();
+ this.localSource.getAnnotations().push(a);
+ this.saveLocalAnnotations();
+};
+
+Metadataplayer.prototype.deleteLocalAnnotation = function(ident) {
+ this.localSource.getAnnotations().removeId(ident, true);
+ this.saveLocalAnnotations();
+};
+
+Metadataplayer.prototype.getLocalAnnotation = function (ident) {
+ this.loadLocalAnnotations();
+ // We cannot use .getElement since it fetches
+ // elements from the global Directory
+ return IriSP._.first(IriSP._.filter(this.localSource.getAnnotations(), function (a) { return a.id == ident; }));
};
Metadataplayer.prototype.loadMetadata = function(_metadataInfo) {
@@ -2425,9 +2577,9 @@
var _divs = this.layoutDivs(_widgetConfig.type);
_widgetConfig.container = _divs[0];
}
-
+
var _this = this;
-
+
if (typeof ns.Widgets[_widgetConfig.type] !== "undefined") {
ns._.defer(function() {
_callback(new ns.Widgets[_widgetConfig.type](_this, _widgetConfig));
@@ -2472,7 +2624,7 @@
if (typeof _height !== "undefined") {
divHtml.css("height", _height);
}
-
+
this.$.append(divHtml);
this.$.append(spacerHtml);
@@ -2481,7 +2633,8 @@
})(IriSP);
-/* End of widgets-container/metadataplayer.js *//* widgetsDefinition of an ancestor for the Widget classes */
+/* End of widgets-container/metadataplayer.js */
+/* widgetsDefinition of an ancestor for the Widget classes */
if (typeof IriSP.Widgets === "undefined") {
IriSP.Widgets = {};
@@ -2500,44 +2653,44 @@
IriSP.Widgets.Widget = function(player, config) {
-
+
if( typeof player === "undefined") {
/* Probably an abstract call of the class when
* individual widgets set their prototype */
return;
}
-
+
this.__subwidgets = [];
-
+
/* Setting all the configuration options */
var _type = config.type || "(unknown)",
_config = IriSP._.defaults({}, config, (player && player.config ? player.config.default_options : {}), this.defaults),
_this = this;
-
+
IriSP._(_config).forEach(function(_value, _key) {
_this[_key] = _value;
});
-
+
this.$ = IriSP.jQuery('#' + this.container);
-
+
if (typeof this.width === "undefined") {
this.width = this.$.width();
} else {
this.$.css("width", this.width);
}
-
+
if (typeof this.height !== "undefined") {
this.$.css("height", this.height);
}
-
+
/* Setting this.player at the end in case it's been overriden
* by a configuration option of the same name :-(
*/
this.player = player || new IriSP.FakeClass(["on","trigger","off","loadWidget","loadMetadata"]);
-
+
/* Adding classes and html attributes */
this.$.addClass("Ldt-TraceMe Ldt-Widget").attr("widget-type", _type);
-
+
this.l10n = (
typeof this.messages[IriSP.language] !== "undefined"
? this.messages[IriSP.language]
@@ -2547,10 +2700,14 @@
: this.messages["en"]
)
);
-
+
/* Loading Metadata if required */
-
+
function onsourceloaded() {
+ if (_this.localannotations) {
+ _this.localsource = player.loadLocalAnnotations(_this.localannotations);
+ _this.source.merge(_this.localsource);
+ }
if (_this.media_id) {
_this.media = this.getElement(_this.media_id);
} else {
@@ -2559,8 +2716,6 @@
};
_this.media = _this.source.getCurrentMedia(_mediaopts);
}
-
-
if (_this.pre_draw_callback){
IriSP.jQuery.when(_this.pre_draw_callback()).done(_this.draw());
}
@@ -2569,11 +2724,10 @@
}
_this.player.trigger("widget-loaded");
}
-
+
if (this.metadata) {
/* Getting metadata */
this.source = player.loadMetadata(this.metadata);
-
/* Call draw when loaded */
this.source.onLoad(onsourceloaded);
} else {
@@ -2581,8 +2735,8 @@
onsourceloaded();
}
}
-
-
+
+
};
IriSP.Widgets.Widget.prototype.defaults = {};
@@ -2700,7 +2854,7 @@
// offset is normally either -1 (previous slide) or +1 (next slide)
var _this = this;
var currentTime = _this.media.getCurrentTime();
- var annotations = _this.source.getAnnotations().sortBy(function(_annotation) {
+ var annotations = _this.getWidgetAnnotations().sortBy(function(_annotation) {
return _annotation.begin;
});
for (var i = 0; i < annotations.length; i++) {
@@ -2713,6 +2867,51 @@
};
};
+/*
+ * Propose an export of the widget's annotations
+ *
+ * Parameter: a list of annotations. If not specified, the widget's annotations will be exported.
+ */
+IriSP.Widgets.Widget.prototype.exportAnnotations = function(annotations) {
+ var widget = this;
+ if (annotations === undefined)
+ annotations = this.getWidgetAnnotations();
+ var $ = IriSP.jQuery;
+
+ // FIXME: this should belong to a proper serialize/deserialize component?
+ var content = Mustache.to_html("[video:{{url}}]\n", {url: widget.media.url}) + annotations.map( function(a) { return Mustache.to_html("[{{ a.begin }}]{{ a.title }} {{ a.description }}[{{ a.end }}]", { a: a }); }).join("\n");
+
+ var el = $("<pre>")
+ .addClass("exportContainer")
+ .text(content)
+ .dialog({
+ title: "Annotation export",
+ open: function( event, ui ) {
+ // Select text
+ var range;
+ if (document.selection) {
+ range = document.body.createTextRange();
+ range.moveToElementText(this[0]);
+ range.select();
+ } else if (window.getSelection) {
+ range = document.createRange();
+ range.selectNode(this[0]);
+ window.getSelection().addRange(range);
+ }
+ },
+ autoOpen: true,
+ width: '80%',
+ minHeight: '400',
+ height: 400,
+ buttons: [ { text: "Close", click: function() { $( this ).dialog( "close" ); } },
+ { text: "Download", click: function () {
+ a = document.createElement('a');
+ a.setAttribute('href', 'data:text/plain;base64,' + btoa(content));
+ a.setAttribute('download', 'Annotations - ' + widget.media.title.replace(/[^ \w]/g, '') + '.txt');
+ a.click();
+ } } ]
+ });
+};
/**
* This method responsible of drawing a widget on screen.
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/src/ldt/ldt/static/ldt/metadataplayer/Markers.css Fri Oct 02 10:24:05 2015 +0200
@@ -0,0 +1,185 @@
+
+.Ldt-Markers-Marker {
+ position: absolute;
+ margin-left: -1px;
+ border: 1px solid #ffffff;
+}
+
+.Ldt-Markers-MarkerBall {
+ background: #ffffff;
+}
+
+.Ldt-Markers-MarkerBall:hover {
+ background: #bebebe;
+}
+
+.Ldt-Markers-List{
+ overflow: hidden;
+}
+
+.Ldt-Markers-Position {
+ background: #fc00ff;
+ position: absolute;
+ top: -1px;
+ left: 0;
+ margin-left: -1px;
+ width: 2px;
+ bottom: -1px;
+ z-index: 80000;
+}
+
+.Ldt-Markers-Inputs{
+ background-color: #e0e0e0;
+ margin-top: 1px;
+}
+
+.Ldt-Markers-RoundButton{
+ display: inline-block;
+ background-color: #d93c71;
+ color: #ffffff;
+ cursor: pointer;
+ height: 20px;
+ width: 20px;
+ border-radius: 20px;
+ font-size: 25px;
+ font-style: bold;
+ border: 1px solid;
+ border-color: #eca3bc #631e34 #36101c #e16e93;
+ cursor: pointer;
+ margin-right: 0px;
+ margin-left: 13px;
+ margin-bottom: 10px;
+ margin-top: 10px;
+ padding: 4px;
+ text-align: center;
+ vertical-align: top;
+ line-height: 20px;
+}
+
+.Ldt-Markers-RoundButton.Ldt-Markers-CannotCreate{
+ background-color: #999999;
+ border-color: #797979 #444444 #222222 #696969;
+}
+
+.Ldt-Markers-RoundButton.Ldt-Markers-Delete{
+ line-height: 23px;
+ text-indent: 2px;
+}
+
+.Ldt-Markers-RoundButton.Ldt-Markers-PreviewDelete{
+ line-height: 23px;
+ text-indent: 2px;
+}
+
+.Ldt-Markers-Info{
+ height: 125px;
+ width: 90%;
+ display: inline-block;
+ margin: 0px;
+}
+
+.Ldt-Markers-Screen{
+ height: 125px;
+ margin: 0px;
+}
+
+.Ldt-Markers-ScreenSending, .Ldt-Markers-ScreenFailure, .Ldt-Markers-ScreenSuccess,
+.Ldt-Markers-ScreenConfirmDelete, .Ldt-Markers-ScreenDeleteSuccess{
+ text-align: center;
+ vertical-align: middle;
+ line-height: 125px;
+ font-size: 18px;
+ font-weight: bold;
+ color: #68273C;
+}
+
+.Ldt-Markers-Screen-InnerBox{
+ border: 1px solid #CCCCCC;
+ background: #FFFFFF;
+ color: #FF3B77; text-align: center;
+ font-size: 13px; font-weight: bold;
+}
+
+a.Ldt-Markers-Close {
+ position: absolute; right: 2px;
+ display: inline-block; width: 17px; height: 17px; margin: 4px;
+ background: url(img/widget-control.png);
+}
+
+a.Ldt-Markers-Screen-SubmitDelete, a.Ldt-Markers-Screen-CancelDelete {
+ color: #3366BB;
+ cursor: pointer;
+}
+
+a.Ldt-Markers-Screen-SubmitDelete:hover, a.Ldt-Markers-Screen-CancelDelete:hover {
+ color: #3a75ff;
+}
+
+.Ldt-Markers-MarkerDescription{
+ height: 45%;
+ width: 90%;
+ border: 1px solid #68273c;
+ margin: 10px;
+ padding: 10px;
+ background: #ffffff;
+}
+
+.Ldt-Markers-MarkerDescription:hover{
+ border: 2px solid #e87d9f;
+}
+
+.Ldt-Markers-MarkerEdit{
+ height: 70%;
+ width: 100%;
+ margin: 10px;
+}
+
+.Ldt-Markers-MarkerTextArea{
+ height: auto;
+ width: auto;
+ max-width: 82%;
+ max-height: 100%;
+ padding: 10px;
+ background: #ffffff;
+ border: 2px solid #e87d9f;
+ margin: 0px;
+}
+
+.Ldt-Markers-Buttons{
+ display: inline-block;
+ width: 17%;
+ vertical-align: top;
+}
+
+.Ldt-Markers-MarkerSend, .Ldt-Markers-MarkerPreviewSend, .Ldt-Markers-MarkerCancel{
+ display: inline-block;
+ background-color: #d93c71;
+ color: #ffffff;
+ cursor: pointer;
+ height: 20px;
+ width: 80px;
+ font-size: 11;
+ font-style: bold;
+ border: 1px solid;
+ border-color: #eca3bc #631e34 #36101c #e16e93;
+ cursor: pointer;
+ margin-right: 5px;
+ margin-left: 5px;
+ margin-bottom: 10px;
+ margin-top: 0px;
+ padding: 4px;
+ text-align: center;
+ vertical-align: top;
+ line-height: 20px;
+ vertical-align: top;
+}
+
+.Ldt-Markers-RoundButton:hover, .Ldt-Markers-MarkerSend:hover, .Ldt-Markers-MarkerPreviewSend:hover, .Ldt-Markers-MarkerCancel:hover{
+ background-color: #e15581;
+ border-color: #222222 #e87d9f #f0adc3 #68273c;
+}
+
+.Ldt-Markers-RoundButton.Ldt-Markers-CannotCreate:hover{
+ background-color: #999999;
+ border-color: #797979 #444444 #222222 #696969;
+}
\ No newline at end of file
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/src/ldt/ldt/static/ldt/metadataplayer/Markers.js Fri Oct 02 10:24:05 2015 +0200
@@ -0,0 +1,554 @@
+
+IriSP.Widgets.Markers = function(player, config) {
+ IriSP.Widgets.Widget.call(this, player, config);
+};
+
+IriSP.Widgets.Markers.prototype = new IriSP.Widgets.Widget();
+
+IriSP.Widgets.Markers.prototype.defaults = {
+ annotation_type: "markers",
+ line_height: 8,
+ background: "#e0e0e0",
+ marker_color: "#ff80fc",
+ placeholder_color: "#ffffff",
+ hover_color: "#e15581",
+ selected_color: "#74d600",
+ ball_radius: 4,
+ pause_on_write: true,
+ play_on_submit: true,
+ api_serializer: "ldt_annotate",
+ api_endpoint_template_create: "",
+ api_endpoint_template_edit: "",
+ api_endpoint_template_delete: "",
+ api_method_create: "POST",
+ api_method_edit: "PUT",
+ api_method_delete: "DELETE",
+ project_id: "",
+ creator_name: "",
+ after_send_timeout: 0,
+ markers_gap: 2000,
+ allow_empty_markers: false,
+ close_after_send: false,
+ custom_send_button: false,
+ custom_cancel_button: false,
+ preview_mode: false,
+};
+
+IriSP.Widgets.Markers.prototype.template =
+ '<div class="Ldt-Markers-Display" style="height:{{line_height}}px;">'
+ + '<div class="Ldt-Markers-List" style="height:{{line_height}}px; position: relative;"></div>'
+ + '<div class="Ldt-Markers-Position"></div>'
+ + '</div>'
+ + '<div class="Ldt-Markers-Inputs">'
+ + '<div class="Ldt-Markers-Screen Ldt-Markers-ScreenMain">'
+ + '<div class="Ldt-Markers-RoundButton Ldt-Markers-CannotCreate" title="{{#preview_mode}}{{l10n.preview_mode_submit}}{{/preview_mode}}{{^preview_mode}}{{l10n.cannot_create}}{{/preview_mode}}">+</div>'
+ + '<div class="Ldt-Markers-RoundButton Ldt-Markers-Create">+</div>'
+ + '{{^preview_mode}}<div class="Ldt-Markers-RoundButton Ldt-Markers-Delete">✖</div>{{/preview_mode}}'
+ + '{{#preview_mode}}<div class="Ldt-Markers-RoundButton Ldt-Markers-PreviewDelete" title="{{l10n.preview_mode_delete}}">✖</div>{{/preview_mode}}'
+ + '<div class="Ldt-Markers-Info"></div>'
+ + '</div>'
+ + '<div class="Ldt-Markers-Screen Ldt-Markers-ScreenSending">'
+ + '<div class="Ldt-Markers-Screen-InnerBox">{{l10n.wait_while_processing}}</div>'
+ + '</div>'
+ + '<div class="Ldt-Markers-Screen Ldt-Markers-ScreenSuccess">'
+ + '<a title="{{l10n.close_widget}}" class="Ldt-Markers-Close" href="#"></a>'
+ + '<div class="Ldt-Markers-Screen-InnerBox">{{l10n.annotation_saved}}</div>'
+ + '</div>'
+ + '<div class="Ldt-Markers-Screen Ldt-Markers-ScreenDeleteSuccess">'
+ + '<a title="{{l10n.close_widget}}" class="Ldt-Markers-Close" href="#"></a>'
+ + '<div class="Ldt-Markers-Screen-InnerBox">{{l10n.delete_saved}}</div>'
+ + '</div>'
+ + '<div class="Ldt-Markers-Screen Ldt-Markers-ScreenFailure">'
+ + '<a title="{{l10n.close_widget}}" class="Ldt-Markers-Close" href="#"></a>'
+ + '<div class="Ldt-Markers-Screen-InnerBox">{{l10n.error_while_contacting}}</div>'
+ + '</div>'
+ + '<div class="Ldt-Markers-Screen Ldt-Markers-ScreenConfirmDelete">'
+ + '<a title="{{l10n.close_widget}}" class="Ldt-Markers-Close" href="#"></a>'
+ + '<div class="Ldt-Markers-Screen-InnerBox">'
+ + '{{l10n.delete_text}} '
+ + '<a class="Ldt-Markers-Screen-SubmitDelete">{{l10n.submit_delete}}</a> '
+ + '<a class="Ldt-Markers-Screen-CancelDelete">{{l10n.cancel}}</a>'
+ + '</div>'
+ + '</div>'
+ + '</div>';
+
+
+IriSP.Widgets.Markers.prototype.markerTemplate =
+ '<div class="Ldt-Markers-Marker" style="height:{{height}}px; left:{{left}}px; width: 2px; background-color: black;">' +
+ '<div class="Ldt-Markers-MarkerBall" style="background-color: {{marker_color}}; position: relative; width: {{ball_diameter}}px; height: {{ball_diameter}}px; left: {{ball_left}}px; top: {{ball_top}}px; border: 1px solid; border-radius: {{ball_radius}}px"></div>' +
+ '</div>';
+
+IriSP.Widgets.Markers.prototype.markerPlaceholderTemplate =
+ '<div class="Ldt-Markers-Marker Ldt-Markers-PlaceholderMarker" style="height:{{height}}px; left:{{left}}px; width: 2px; background-color: black;">' +
+ '<div class="Ldt-Markers-MarkerBall" style="background-color: {{marker_color}}; position: relative; width: {{ball_diameter}}px; height: {{ball_diameter}}px; left: {{ball_left}}px; top: {{ball_top}}px; border: 1px solid; border-radius: {{ball_radius}}px"></div>' +
+ '</div>';
+
+IriSP.Widgets.Markers.prototype.infoTemplate =
+ '{{^edit}}<div class="Ldt-Markers-MarkerDescription">{{marker_info}}</div>{{/edit}}' +
+ '{{#edit}}<div class="Ldt-Markers-MarkerEdit">' +
+ '<textarea class="Ldt-Markers-MarkerTextArea" cols="60" rows="4">{{marker_info}}</textarea>' +
+ '<div class="Ldt-Markers-Buttons">' +
+ '{{^preview_mode}}<div class="Ldt-Markers-MarkerSend">{{send}}</div>{{/preview_mode}}' +
+ '{{#preview_mode}}<div class="Ldt-Markers-MarkerPreviewSend" title="{{preview_mode_text}}">{{send}}</div>{{/preview_mode}}' +
+ '<div class="Ldt-Markers-MarkerCancel">{{cancel}}</div>' +
+ '</div>' +
+ '</div>{{/edit}}'
+
+IriSP.Widgets.Markers.prototype.messages = {
+ en : {
+ send : "Send",
+ submit_delete: "Delete",
+ cancel : "Cancel",
+ preview_mode_submit: "You cannot submit a marker in preview mode.",
+ preview_mode_delete: "You cannot delete a marker in preview mode",
+ wait_while_processing: "Please wait while your annotation is being processed...",
+ delete_text: "The selected marker will be deleted. Continue?",
+ error_while_contacting: "An error happened while contacting the server. Your annotation has not been saved.",
+ annotation_saved: "Thank you, your annotation has been saved.",
+ delete_saved: "Thank you, your annotation has been deleted",
+ close_widget: "Close",
+ cannot_create: "Cannot create marker on this timecode"
+ },
+ fr : {
+ send : "Envoyer",
+ submit_delete: "Supprimer",
+ cancel : "Annuler",
+ preview_mode_submit: "Vous ne pouvez pas créer ou éditer de marqueur en mode aperçu",
+ preview_mode_delete: "Vous ne pouvez pas supprimer de marqueur en mode aperçu",
+ wait_while_processing: "Veuillez patienter pendant le traitement de votre annotation...",
+ delete_text: "Le marqueur sélectionné sera supprimé. Continuer?",
+ error_while_contacting: "Une erreur s'est produite en contactant le serveur. Votre annotation n'a pas été enregistrée.",
+ annotation_saved: "Merci, votre annotation a été enregistrée.",
+ delete_saved: "Merci, votre annotation a été supprimée",
+ close_widget: "Fermer",
+ cannot_create: "Impossible de créer un marqueur sur ce timecode"
+ }
+}
+
+IriSP.Widgets.Markers.prototype.draw = function(){
+ var _this = this;
+
+ this.renderTemplate();
+
+ this.markers = this.getWidgetAnnotations().filter(function(_ann) {
+ return ((_ann.getDuration() == 0) || (_ann.begin == _ann.end));
+ });
+ this.drawMarkers();
+
+ this.$.find(".Ldt-Markers-Create").click(this.functionWrapper("onCreateClick"));
+ this.$.find(".Ldt-Markers-Delete").click(this.functionWrapper("onDeleteClick"));
+ this.$.find(".Ldt-Markers-RoundButton").hide()
+ this.updateCreateButtonState(this.media.getCurrentTime())
+ this.$.find(".Ldt-Markers-Screen-SubmitDelete").click(this.functionWrapper("sendDelete"));
+ this.$.find(".Ldt-Markers-Screen-CancelDelete").click(function(){
+ _this.showScreen("Main");
+ _this.cancelEdit();
+ })
+ this.showScreen("Main");
+ this.$.css({
+ margin: "1px 0",
+ height: this.line_height,
+ background: this.background
+ });
+
+ this.$.find(".Ldt-Markers-Close").click(this.functionWrapper("revertToMainScreen"));
+
+ this.onMediaEvent("timeupdate", this.functionWrapper("updatePosition"));
+ this.onMediaEvent("timeupdate", this.functionWrapper("updateCreateButtonState"));
+ this.onMediaEvent("play", this.functionWrapper("clearSelectedMarker"));
+ this.onMdpEvent("Markers.refresh", this.functionWrapper("drawMarkers"));
+
+ this.newMarkerTimeCode = 0;
+ this.selectedMarker = false;
+}
+
+
+IriSP.Widgets.Markers.prototype.updatePosition = function(_time) {
+ var _x = Math.floor( this.width * _time / this.media.duration);
+ this.$.find('.Ldt-Markers-Position').css({
+ left: _x + "px"
+ });
+}
+
+IriSP.Widgets.Markers.prototype.updateCreateButtonState = function(_time){
+ _this = this
+ var can_create = this.preview_mode? false : this.markers.every(function(_marker){
+ return ((_time < (_marker.begin-_this.markers_gap))||(_time > (_marker.begin+_this.markers_gap)))
+ });
+ if (can_create){
+ if ((this.$.find(".Ldt-Markers-Create").is(":hidden"))&&(this.$.find(".Ldt-Markers-Delete").is(":hidden")||this.$.find(".Ldt-Markers-PreviewDelete").is(":hidden"))){
+ this.$.find(".Ldt-Markers-RoundButton").hide();
+ this.$.find(".Ldt-Markers-Create").show();
+ }
+ }
+ else {
+ if ((this.$.find(".Ldt-Markers-CannotCreate").is(":hidden"))&&(this.$.find(".Ldt-Markers-Delete").is(":hidden")||this.$.find(".Ldt-Markers-PreviewDelete").is(":hidden"))){
+ this.$.find(".Ldt-Markers-RoundButton").hide();
+ this.$.find(".Ldt-Markers-CannotCreate").show();
+ }
+ }
+}
+
+IriSP.Widgets.Markers.prototype.onCreateClick = function(){
+ this.pauseOnWrite();
+ if (!this.selectedMarker){
+ this.newMarkerCurrentTime = this.media.getCurrentTime();
+ this.showPlaceholder(this.media.getCurrentTime());
+ this.startEdit();
+ }
+}
+
+IriSP.Widgets.Markers.prototype.onDeleteClick = function(){
+ _this = this;
+ this.pauseOnWrite();
+ if(this.selectedMarker){
+ this.showScreen("ConfirmDelete");
+ }
+ else {
+ // Click on "x" without a selected marker: back to initial state
+ this.cancelEdit();
+ }
+}
+
+IriSP.Widgets.Markers.prototype.startEdit = function(){
+ if (this.selectedMarker){
+ _divHtml = Mustache.to_html(this.infoTemplate, {
+ edit: true,
+ preview_mode: this.preview_mode,
+ preview_mode_text: this.l10n.preview_mode_submit,
+ marker_info: this.selectedMarker.description,
+ send: this.custom_send_button? this.custom_send_button : this.l10n.send,
+ cancel: this.custom_cancel_button? this.custom_cancel_button :this.l10n.cancel
+ })
+ }
+ else {
+ _divHtml = Mustache.to_html(this.infoTemplate, {
+ edit: true,
+ marker_info: "",
+ preview_mode: this.preview_mode,
+ preview_mode_text: this.l10n.preview_mode_submit,
+ send: this.custom_send_button? this.custom_send_button : this.l10n.send,
+ cancel: this.custom_cancel_button? this.custom_cancel_button :this.l10n.cancel
+ })
+ }
+ this.$.find(".Ldt-Markers-Info").html(_divHtml);
+ this.$.find(".Ldt-Markers-MarkerSend").click(this.functionWrapper("onSubmit"));
+ this.$.find(".Ldt-Markers-MarkerCancel").click(this.functionWrapper("cancelEdit"));
+ this.$.find(".Ldt-Markers-MarkerTextArea").bind("change keyup input paste", this.functionWrapper("onDescriptionChange"));
+ this.$.find(".Ldt-Markers-RoundButton").hide();
+ if (this.preview_mode){
+ this.$.find(".Ldt-Markers-PreviewDelete").show();
+ }
+ else {
+ this.$.find(".Ldt-Markers-Delete").show();
+ }
+ this.editing = true;
+}
+
+IriSP.Widgets.Markers.prototype.cancelEdit = function(){
+ if (this.selectedMarker){
+ // Click on "cancel" while editing a marker: back to visualization state
+ _divHtml = Mustache.to_html(this.infoTemplate, {
+ edit: false,
+ marker_info: this.selectedMarker.description,
+ })
+ this.$.find(".Ldt-Markers-Info").html(_divHtml);
+ if (!this.preview_mode){
+ this.$.find(".Ldt-Markers-MarkerDescription").click(this.functionWrapper("startEdit"));
+ }
+ }
+ else {
+ // Click on "cancel" while editing a marker: back to initial state
+ this.hidePlaceholder();
+ this.$.find(".Ldt-Markers-Info").html("");
+ this.$.find(".Ldt-Markers-RoundButton").hide()
+ this.$.find(".Ldt-Markers-Create").show()
+ this.updateCreateButtonState(this.media.getCurrentTime())
+ }
+ this.editing = false;
+}
+
+IriSP.Widgets.Markers.prototype.onDescriptionChange = function(){
+ // Returns false if the textarea is empty, true if there is text in it
+ if(!this.allow_empty_markers){
+ var _field = this.$.find(".Ldt-Markers-MarkerTextArea"),
+ _contents = _field.val();
+ _field.css("border-color", !!_contents ? "#e87d9f" : "#ff0000");
+ if (!!_contents) {
+ _field.removeClass("empty");
+ } else {
+ _field.addClass("empty");
+ }
+ this.pauseOnWrite();
+ return !!_contents;
+ }
+ else {
+ // If the widget is configured to allow to post empty markers, it returns true
+ return true
+ }
+};
+
+IriSP.Widgets.Markers.prototype.pauseOnWrite = function(){
+ if (this.pause_on_write && !this.media.getPaused()) {
+ this.media.pause();
+ }
+};
+
+IriSP.Widgets.Markers.prototype.showScreen = function(_screenName) {
+ this.$.find('.Ldt-Markers-Screen' + _screenName).show()
+ .siblings().hide();
+}
+
+IriSP.Widgets.Markers.prototype.revertToMainScreen = function(){
+ if (this.$.find(".Ldt-Markers-ScreenMain").is(":hidden")){
+ this.showScreen("Main");
+ this.cancelEdit();
+ if (this.selectedMarker){
+ this.$.find(".Ldt-Markers-RoundButton").hide();
+ if (this.preview_mode){
+ this.$.find(".Ldt-Markers-PreviewDelete").show();
+ }
+ else {
+ this.$.find(".Ldt-Markers-Delete").show();
+ }
+ }
+ else {
+ this.$.find(".Ldt-Markers-RoundButton").hide();
+ this.$.find(".Ldt-Markers-Create").show();
+ this.updateCreateButtonState();
+ }
+ }
+}
+
+IriSP.Widgets.Markers.prototype.hidePlaceholder = function(){
+ this.$.find(".Ldt-Markers-PlaceholderMarker").remove();
+}
+
+IriSP.Widgets.Markers.prototype.showPlaceholder = function(_time){
+ var _scale = this.width / this.source.getDuration(),
+ _left = _time * _scale -1,
+ _data = {
+ left: _left,
+ height: this.line_height-1,
+ ball_top: (this.ball_radius*2 > this.line_height) ? 0 : ((this.line_height - this.ball_radius*2)/2)-1,
+ ball_radius: (this.ball_radius*2 > this.line_height) ? this.line_height/2 : this.ball_radius,
+ ball_diameter: (this.ball_radius*2 > this.line_height) ? this.line_height/2 : this.ball_radius*2,
+ ball_left: -this.ball_radius,
+ marker_color: this.placeholder_color
+ },
+ _html = Mustache.to_html(this.markerPlaceholderTemplate, _data),
+ _el = IriSP.jQuery(_html);
+
+ list_$ = this.$.find(".Ldt-Markers-List");
+ _el.appendTo(list_$);
+}
+
+IriSP.Widgets.Markers.prototype.clearSelectedMarker = function(){
+ if (this.selectedMarker){
+ var _divHtml = "";
+
+ this.selectedMarker = false;
+ this.$.find(".Ldt-Markers-Info").html(_divHtml);
+ this.$.find(".Ldt-Markers-RoundButton").hide();
+ this.$.find(".Ldt-Markers-Create").show();
+ this.$.find(".Ldt-Markers-MarkerBall").toggleClass("selected", false);
+ this.updateCreateButtonState(this.media.getCurrentTime())
+ }
+}
+
+IriSP.Widgets.Markers.prototype.drawMarkers = function(){
+ var _this = this,
+ _scale = this.width / this.source.getDuration(),
+ list_$ = this.$.find('.Ldt-Markers-List');
+
+ this.$.remove("Ldt-Markers-Marker");
+ list_$.html("");
+ this.markers.forEach(function(_marker){
+ var _left = _marker.begin * _scale -1,
+ _data = {
+ left: _left,
+ height: _this.line_height-1,
+ ball_top: (_this.ball_radius*2 > _this.line_height) ? 0 : ((_this.line_height - _this.ball_radius*2)/2)-1,
+ ball_radius: (_this.ball_radius*2 > _this.line_height) ? _this.line_height/2 : _this.ball_radius,
+ ball_diameter: (_this.ball_radius*2 > _this.line_height) ? _this.line_height/2 : _this.ball_radius*2,
+ ball_left: -_this.ball_radius,
+ marker_color: ((_this.selectedMarker)&&(_this.selectedMarker.id == _marker.id))? _this.selected_color : _this.marker_color
+ },
+ _html = Mustache.to_html(_this.markerTemplate, _data),
+ _el = IriSP.jQuery(_html);
+
+ if ((_this.selectedMarker)&&(_this.selectedMarker.id == _marker.id)){
+ _el.children().toggleClass("selected", true);
+ }
+
+ _el.mouseover(function(){
+ if (!((_this.selectedMarker)&&(_this.selectedMarker.id == _marker.id))){
+ _el.children().css("background-color", _this.hover_color);
+ };
+ })
+ .mouseout(function(){
+ if (!((_this.selectedMarker)&&(_this.selectedMarker.id == _marker.id))){
+ _el.children().css("background-color", _this.marker_color);
+ };
+ })
+ .click(function(){
+ _this.showScreen("Main");
+ _this.cancelEdit();
+ _this.hidePlaceholder();
+ if (!((_this.selectedMarker)&&(_this.selectedMarker.id == _marker.id))){
+ // if there either is no marker selected or we click a different marker
+ list_$.find(".Ldt-Markers-MarkerBall").css("background-color", _this.marker_color)
+ list_$.find(".Ldt-Markers-MarkerBall").toggleClass("selected", false);
+ _el.children().toggleClass("selected", true);
+ _el.children().css("background-color", _this.selected_color)
+ _this.selectedMarker = _marker;
+
+ _divHtml = Mustache.to_html(_this.infoTemplate, {
+ edit: false,
+ marker_info: _marker.description,
+ })
+
+ _this.$.find(".Ldt-Markers-Info").html(_divHtml);
+ if (!_this.preview_mode){
+ _this.$.find(".Ldt-Markers-MarkerDescription").click(_this.functionWrapper("startEdit"));
+ }
+ _this.$.find(".Ldt-Markers-RoundButton").hide();
+ if (_this.preview_mode){
+ _this.$.find(".Ldt-Markers-PreviewDelete").show();
+ }
+ else {
+ _this.$.find(".Ldt-Markers-Delete").show();
+ }
+
+ }
+ else {
+ // if we click the currently selected marker, we unselect it
+ _el.children().css("background-color", _this.hover_color);
+ _this.clearSelectedMarker();
+ }
+
+ if (_this.selectedMarker) {
+ // Only if we select a new marker do we pause video and time jump
+ _this.media.pause();
+ _marker.trigger("click");
+ }
+ })
+ .appendTo(list_$);
+ })
+}
+
+
+IriSP.Widgets.Markers.prototype.onSubmit = function(){
+
+ /* If mandatory fields are empty, we cancel the sending */
+ if (!this.allow_empty_markers && !this.onDescriptionChange()){
+ return false;
+ }
+
+ /* We pause the video if it's still playing */
+ if (!this.media.getPaused()){
+ this.media.pause();
+ }
+
+ var _this = this,
+ _exportedAnnotations = new IriSP.Model.List(this.player.sourceManager), /* We create a List to send to the server that will contains the annotation */
+ _export = this.player.sourceManager.newLocalSource({serializer: IriSP.serializers[this.api_serializer]}), /* We create a source object using a specific serializer for export */
+ _annotationTypes = this.source.getAnnotationTypes().searchByTitle(this.annotation_type, true), /* We get the AnnotationType in which the annotation will be added */
+ _annotationType = (_annotationTypes.length ? _annotationTypes[0] : new IriSP.Model.AnnotationType(false, _export)); /* If it doesn't already exists, we create it */
+ if (this.selectedMarker){
+ var _annotation = this.selectedMarker,
+ _url = Mustache.to_html(this.api_endpoint_template_edit, {annotation_id: this.selectedMarker ? this.selectedMarker.id : ""});
+ _annotation.source = _export
+ _annotation.description = this.$.find(".Ldt-Markers-MarkerTextArea").val(), /* Description field */
+ }
+ else {
+ var _annotation = new IriSP.Model.Annotation(false, _export),
+ _url = Mustache.to_html(this.api_endpoint_template_create);
+
+ /* If we created an AnnotationType on the spot ... */
+ if (!_annotationTypes.length) {
+ /* ... We must not send its id to the server ... */
+ _annotationType.dont_send_id = true;
+ /* ... And we must include its title. */
+ _annotationType.title = this.annotation_type;
+ }
+
+ _annotation.setMedia(this.source.currentMedia.id); /* Annotated media ID */
+ if (!this.selectedMarker){
+ _annotation.setBegin(this.newMarkerCurrentTime);
+ _annotation.setEnd(this.newMarkerCurrentTime);
+ }
+ _annotation.setAnnotationType(_annotationType.id); /* AnnotationType ID */
+ if (this.project_id != ""){
+ /* Project id, only if it's been specifiec in the config */
+ _annotation.project_id = this.project_id;
+ }
+ _annotation.created = new Date(); /* Creation date */
+ _annotation.description = this.$.find(".Ldt-Markers-MarkerTextArea").val(); /* Description field */
+ _annotation.creator = this.creator_name;
+ }
+ _annotation.project_id = this.project_id;
+
+ _exportedAnnotations.push(_annotation); /* We add the annotation in the list to export */
+ _export.addList("annotation",_exportedAnnotations); /* We add the list to the source object */
+
+ /* We send the AJAX request to the server ! */
+ IriSP.jQuery.ajax({
+ url: _url,
+ type: this.selectedMarker ? this.api_method_edit : this.api_method_create,
+ contentType: 'application/json',
+ data: _export.serialize(),
+ success: function(_data) {
+ _this.showScreen('Success');
+ window.setTimeout(_this.functionWrapper("revertToMainScreen"),(_this.after_send_timeout || 5000));
+ _export.getAnnotations().removeElement(_annotation, true); /* We delete the sent annotation to avoid redundancy */
+ _export.deSerialize(_data); /* Data deserialization */
+ _annotation.id = _data.id;
+ _this.source.merge(_export); /* We merge the deserialized data with the current source data */
+ if (_this.pause_on_write && _this.media.getPaused() && _this.play_on_submit) {
+ _this.media.play();
+ }
+ _this.markers.push(_annotation);
+ _this.selectedMarker = _annotation;
+ _this.drawMarkers();
+ _this.player.trigger("AnnotationsList.refresh");
+ _this.player.trigger("Markers.refresh");
+ },
+ error: function(_xhr, _error, _thrown) {
+ IriSP.log("Error when sending annotation", _thrown);
+ _export.getAnnotations().removeElement(_annotation, true);
+ _this.showScreen('Failure');
+ window.setTimeout(_this.functionWrapper("revertToMainScreen"),(_this.after_send_timeout || 5000));
+ }
+ });
+ this.showScreen('Sending');
+
+ return false;
+};
+
+IriSP.Widgets.Markers.prototype.sendDelete = function(){
+ _this = this;
+ _url = Mustache.to_html(this.api_endpoint_template_delete, {annotation_id: this.selectedMarker ? this.selectedMarker.id : "", project_id: this.selectedMarker.project_id? this.selectedMarker.project_id : this.project_id});
+ IriSP.jQuery.ajax({
+ url: _url,
+ type: this.api_method_delete,
+ contentType: 'application/json',
+ success: function(_data) {
+ _this.showScreen('DeleteSuccess');
+ window.setTimeout(_this.functionWrapper("revertToMainScreen"),(_this.after_send_timeout || 5000));
+ if (_this.pause_on_write && _this.media.getPaused() && _this.play_on_submit) {
+ _this.media.play();
+ }
+ _this.markers.removeElement(_this.selectedMarker);
+ _this.selectedMarker = false
+ _this.player.trigger("AnnotationsList.refresh");
+ _this.player.trigger("Markers.refresh");
+ },
+ error: function(_xhr, _error, _thrown) {
+ IriSP.log("Error when sending annotation", _thrown);
+ _this.showScreen('Failure');
+ window.setTimeout(_this.functionWrapper("revertToMainScreen"),(_this.after_send_timeout || 5000));
+ }
+ });
+ this.showScreen("Sending")
+}
\ No newline at end of file
--- a/src/ldt/ldt/static/ldt/metadataplayer/Mediafragment.js Fri Sep 18 16:10:29 2015 +0200
+++ b/src/ldt/ldt/static/ldt/metadataplayer/Mediafragment.js Fri Oct 02 10:24:05 2015 +0200
@@ -2,6 +2,9 @@
IriSP.Widgets.Widget.call(this, player, config);
this.last_hash_key = "";
this.last_hash_value = "";
+ this.last_extra_key = "";
+ this.last_extra_value = "";
+
window.onhashchange = this.functionWrapper("goToHash");
if (typeof window.addEventListener !== "undefined") {
var _this = this;
@@ -22,7 +25,7 @@
var _this = this;
this.getWidgetAnnotations().forEach(function(_annotation) {
_annotation.on("click", function() {
- _this.setHashToAnnotation(_annotation.id);
+ _this.setHashToAnnotation(_annotation);
});
});
if (this.media.loadedMetadata) {
@@ -48,6 +51,9 @@
if (this.last_hash_key) {
_tab.push(this.last_hash_key + '=' + this.last_hash_value);
}
+ if (this.last_extra_key) {
+ _tab.push(this.last_extra_key + '=' + this.last_extra_value);
+ }
return '#' + _tab.join('&');
};
@@ -63,10 +69,13 @@
var _annotation = this.source.getElement(this.last_hash_value);
if (typeof _annotation !== "undefined") {
this.media.setCurrentTime(_annotation.begin);
+ } else {
+ /* Proceed parsing elements, maybe a t was specified */
+ continue;
}
}
if (this.last_hash_key == "t") {
- this.media.setCurrentTime(1000*this.last_hash_value);
+ this.media.setCurrentTime(1000 * this.last_hash_value);
}
break;
}
@@ -74,18 +83,21 @@
}
};
-IriSP.Widgets.Mediafragment.prototype.setHashToAnnotation = function(_annotationId) {
- this.setHash( 'id', _annotationId );
+IriSP.Widgets.Mediafragment.prototype.setHashToAnnotation = function(_annotation) {
+ this.setHash( 'id', _annotation.id, 't', _annotation.begin / 1000.0 );
};
IriSP.Widgets.Mediafragment.prototype.setHashToTime = function() {
this.setHash( 't', this.media.getCurrentTime().getSeconds() );
};
-IriSP.Widgets.Mediafragment.prototype.setHash = function(_key, _value) {
+IriSP.Widgets.Mediafragment.prototype.setHash = function(_key, _value, _key2, _value2) {
if (!this.blocked && (this.last_hash_key !== _key || this.last_hash_value !== _value)) {
this.last_hash_key = _key;
this.last_hash_value = _value;
+ this.last_extra_key = _key2;
+ this.last_extra_value = _value2;
+
var _hash = this.getLastHash();
this.setWindowHash(_hash);
if (window.parent !== window) {
--- a/src/ldt/ldt/static/ldt/metadataplayer/MultiSegments.js Fri Sep 18 16:10:29 2015 +0200
+++ b/src/ldt/ldt/static/ldt/metadataplayer/MultiSegments.js Fri Oct 02 10:24:05 2015 +0200
@@ -80,7 +80,7 @@
IriSP._({
type: "Segments",
annotation_type: _anntype,
- width: _this.width
+ width: '100%'
}).extend(segmentsopts)
);
@@ -89,7 +89,7 @@
IriSP._({
type: "Annotation",
annotation_type: _anntype,
- width: _this.width
+ width: '100%'
}).extend(annotationopts)
);
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/src/ldt/ldt/static/ldt/metadataplayer/NoteTaking.css Fri Oct 02 10:24:05 2015 +0200
@@ -0,0 +1,5 @@
+/* NoteTaking widget */
+.Ldt-NoteTaking-Text {
+ width: 100%;
+ min-height: 360px;
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/src/ldt/ldt/static/ldt/metadataplayer/NoteTaking.js Fri Oct 02 10:24:05 2015 +0200
@@ -0,0 +1,91 @@
+/* This widget displays a note-taking view, that can be saved to localStorage */
+
+IriSP.Widgets.NoteTaking = function(player, config) {
+ IriSP.Widgets.Widget.call(this, player, config);
+}
+
+IriSP.Widgets.NoteTaking.prototype = new IriSP.Widgets.Widget();
+
+IriSP.Widgets.NoteTaking.prototype.defaults = {
+ // Id that will be used as localStorage key
+ editable_storage: ""
+}
+
+IriSP.Widgets.NoteTaking.prototype.template = '<textarea class="Ldt-NoteTaking-Text"></textarea>';
+
+IriSP.Widgets.NoteTaking.prototype.draw = function() {
+ var widget = this;
+ var content;
+ var $ = IriSP.jQuery;
+
+ widget.renderTemplate();
+ content = widget.$.find('.Ldt-NoteTaking-Text');
+
+ function load_content() {
+ $(content).val(window.localStorage[widget.editable_storage]);
+ }
+ function save_content() {
+ window.localStorage[widget.editable_storage] = $(content).val();
+ }
+
+ // Load current transcript
+ if (window.localStorage[widget.editable_storage]) {
+ load_content();
+ }
+
+ // Thanks to http://stackoverflow.com/questions/4456545/how-to-insert-text-at-the-current-caret-position-in-a-textarea
+ $.fn.insertAtCaret = function(text) {
+ return this.each(function() {
+ if (this.selectionStart !== undefined) {
+ // mozilla/netscape support
+ var startPos = this.selectionStart,
+ endPos = this.selectionEnd,
+ scrollTop = this.scrollTop;
+ this.value = this.value.substring(0, startPos) + text + this.value.substring(endPos, this.value.length);
+ this.focus();
+ this.selectionStart = startPos + text.length;
+ this.selectionEnd = startPos + text.length;
+ this.scrollTop = scrollTop;
+ } else {
+ // IE input[type=text] and other browsers
+ this.value += text;
+ this.focus();
+ this.value = this.value; // forces cursor to end
+ }
+ });
+ };
+
+ function getAroundCaret(el, length) {
+ // Return a selection of 2 * length characters around the caret
+ var startPos = el.selectionStart;
+ return el.value.substring(startPos - length, startPos + length);
+ };
+
+
+ $(content).keydown(function (_event) {
+ if (_event.keyCode == 13 && (_event.ctrlKey || _event.metaKey)) {
+ // Insert current timestamp
+ _event.preventDefault();
+ // Get current value
+ var match = /\[([\d:]+)\]/.exec(getAroundCaret(content[0], 8));
+ if (match) {
+ // Found a timecode. Go to position.
+ widget.media.setCurrentTime(IriSP.timestamp2ms(match[1]));
+ } else {
+ $(content).insertAtCaret("[" + (new IriSP.Model.Time(widget.media.getCurrentTime())).toString() + "]");
+ save_content();
+ }
+ }
+ }).on("input", function (_event) {
+ console.log("Change");
+ // Store updated value
+ save_content();
+ }).on("dblclick", function (_event) {
+ var match = /\[([\d:]+)\]/.exec(getAroundCaret(content[0], 8));
+ if (match) {
+ // Found a timecode. Go to position.
+ _event.preventDefault();
+ widget.media.setCurrentTime(IriSP.timestamp2ms(match[1]));
+ };
+ });
+};
--- a/src/ldt/ldt/static/ldt/metadataplayer/Polemic.js Fri Sep 18 16:10:29 2015 +0200
+++ b/src/ldt/ldt/static/ldt/metadataplayer/Polemic.js Fri Oct 02 10:24:05 2015 +0200
@@ -144,7 +144,8 @@
image: _annotation.thumbnail,
uri: (typeof _annotation.url !== "undefined"
? _annotation.url
- : (document.location.href.replace(/#.*$/,'') + '#id=' + _annotation.id))
+ : (document.location.href.replace(/#.*$/,'') + '#id=' + _annotation.id)),
+ text: '[' + _annotation.begin.toString() + '] ' + _annotation.title
});
// test if annotation has several colors.
var colAr = [];
--- a/src/ldt/ldt/static/ldt/metadataplayer/PopcornPlayer.js Fri Sep 18 16:10:29 2015 +0200
+++ b/src/ldt/ldt/static/ldt/metadataplayer/PopcornPlayer.js Fri Oct 02 10:24:05 2015 +0200
@@ -10,26 +10,19 @@
};
IriSP.Widgets.PopcornPlayer.prototype.draw = function() {
-
-
if (typeof this.video === "undefined") {
this.video = this.media.video;
}
-
+
if (this.url_transform) {
this.video = this.url_transform(this.video);
}
-
+
if (/^(https?:\/\/)?(www\.)?vimeo\.com/.test(this.video)) {
-
/* VIMEO */
-
var _popcorn = Popcorn.vimeo(this.container, this.video);
-
} else if (/^(https?:\/\/)?(www\.)?youtube\.com/.test(this.video)) {
-
/* YOUTUBE */
-
var _urlparts = this.video.split(/[?&]/),
_params = {};
for (var i = 1; i < _urlparts.length; i++) {
@@ -42,13 +35,11 @@
_params.autoplay = 1;
}
_url = _urlparts[0] + '?' + IriSP.jQuery.param(_params);
-
+
var _popcorn = Popcorn.youtube(this.container, _url);
-
+
} else {
-
/* DEFAULT HTML5 */
-
var _tmpId = IriSP._.uniqueId("popcorn"),
_videoEl = IriSP.jQuery('<video>');
_videoEl.attr({
@@ -74,33 +65,32 @@
_popcorn.autoplay(true);
}
}
-
+
var _media = this.media;
-
+
// Binding functions to Popcorn
-
+
_media.on("setcurrenttime", function(_milliseconds) {
_popcorn.currentTime(_milliseconds / 1000);
});
-
+
_media.on("setvolume", function(_vol) {
_popcorn.volume(_vol);
_media.volume = _vol;
});
-
+
_media.on("setmuted", function(_muted) {
_popcorn.muted(_muted);
_media.muted = _muted;
});
-
+
_media.on("setplay", function() {
_popcorn.play();
});
-
+
_media.on("setpause", function() {
_popcorn.pause();
});
-
_media.on("settimerange", function(_timeRange){
_media.timeRange = _timeRange;
try {
@@ -110,43 +100,41 @@
} catch (err) {
}
})
-
_media.on("resettimerange", function(){
_media.timeRange = false;
})
-
// Binding Popcorn events to media
-
+
function getVolume() {
_media.muted = _popcorn.muted();
_media.volume = _popcorn.volume();
}
-
+
_popcorn.on("loadedmetadata", function() {
getVolume();
_media.trigger("loadedmetadata");
_media.trigger("volumechange");
});
-
+
_popcorn.on("timeupdate", function() {
_media.trigger("timeupdate", new IriSP.Model.Time(1000*_popcorn.currentTime()));
});
-
+
_popcorn.on("volumechange", function() {
getVolume();
_media.trigger("volumechange");
});
-
+
_popcorn.on("play", function() {
_media.trigger("play");
});
-
+
_popcorn.on("pause", function() {
_media.trigger("pause");
});
-
+
_popcorn.on("seeked", function() {
_media.trigger("seeked");
});
-
-};
\ No newline at end of file
+
+};
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/src/ldt/ldt/static/ldt/metadataplayer/Quiz.css Fri Oct 02 10:24:05 2015 +0200
@@ -0,0 +1,224 @@
+/* Nothing */
+
+.Ldt-Quiz-Container {
+ position: absolute;
+ height: calc(100% - 4px);
+ top: 0px;
+ width: calc(100% - 20px);
+ margin: auto;
+ border: 1px solid black;
+ font-size: 18pt;
+}
+
+.Ldt-Quiz-Title {
+ line-height: 1;
+ padding-top: 10px;
+ text-align: center;
+}
+
+.Ldt-Quiz-Header {
+ font-size: 12px;
+ color: black;
+ border-bottom: 1px solid green;
+ padding: 2px;
+ height: 22px;
+}
+
+.Ldt-Quiz-Content {
+ height: calc(100% - 82px);
+ overflow-y: auto;
+}
+
+.Ldt-Quiz-Footer {
+ height: 60px;
+ width: 100%;
+ position: absolute;
+ bottom: 0px;
+ border-top: 2px solid black;
+ background-color: white;
+}
+
+
+.Ldt-Quiz-Score {
+ display: inline-block;
+ position: absolute;
+ right: 20px;
+}
+
+.Ldt-Quiz-Index {
+ display: inline-block;
+}
+
+.Ldt-Quiz-Image {
+ max-width: 100%;
+ max-height: 100%;
+}
+
+.Ldt-Quiz-Questions {
+ height: calc(100% - 2.5em);
+ margin: 10px;
+ padding: 10px;
+ border-left: 5px solid gray;
+}
+
+.quiz-question-block {
+ padding-top: 10px;
+}
+.quiz-resource-block {
+ padding-top: 10px;
+ float: right;
+ max-height: 100%;
+ height: 100%;
+}
+.quiz-resource-block img {
+ max-height: 100%;
+ max-width: 100%;
+}
+
+.quiz-question-feedback {
+ font-size: 15px;
+}
+
+.quiz-question-feedback div {
+ display: inline-block;
+ height: 100%;
+}
+
+.quiz-question-correct-feedback:before, .quiz-question-incorrect-feedback:before {
+ content: '';
+ vertical-align: middle;
+ display: inline-block;
+ width: 48px;
+ height: 48px;
+ }
+
+.quiz-question-correct-feedback:before {
+ background: url(img/valid_sprites.png) left top no-repeat;
+}
+
+.quiz-question-incorrect-feedback:before {
+ background: url(img/valid_sprites.png) -49px top no-repeat;
+}
+
+.Ldt-Quiz-Correct-Answer:before {
+ background: url(img/min_valid_sprites.png) left top no-repeat;
+}
+
+.Ldt-Quiz-Incorrect-Answer:before {
+ background: url(img/min_valid_sprites.png) -13px top no-repeat;
+}
+
+.Ldt-Quiz-Correct-Answer:before, .Ldt-Quiz-Incorrect-Answer:before {
+ content: '';
+ vertical-align: middle;
+ display: inline-block;
+ width: 12px;
+ height: 12px;
+ }
+
+.Ldt-Quiz-Submit {
+ margin: 10px;
+}
+
+.Ldt-Quiz-Submit .Ldt-Quiz-Submit-Skip-Link {
+ float: left;
+}
+
+.Ldt-Quiz-Submit-Skip-Link a {
+ text-decoration: none;
+ font-size: 16pt;
+}
+
+.Ldt-Quiz-Submit .Ldt-Quiz-Submit-Button {
+ float: right;
+}
+
+.Ldt-Quiz-Votes {
+ display: none;
+ height: 53px;
+ position: relative;
+}
+
+.Ldt-Quiz-Votes-Question {
+ font-size: 16px;
+ position: absolute;
+ top: 2px;
+ left: 0px;
+}
+
+.Ldt-Quiz-Votes-Buttons {
+ position: absolute;
+ bottom: 2px;
+ left: 0px;
+ right: 0px;
+}
+
+.Ldt-Quiz-Votes-Buttons div {
+ display: inline-block;
+ width: 33%;
+ text-align: center;
+}
+
+.Ldt-Quiz-Vote-Skip-Block {
+ width: 30% !important;
+ text-align: right;
+}
+
+.Ldt-Quiz-Vote-Skip-Block a {
+ text-decoration: none;
+}
+
+.Ldt-Quiz-Overlay {
+ position: absolute;
+ top: 0px;
+ background-color: white;
+ z-index: 5;
+ width: 100%;
+ height: 100%;
+}
+
+.Ldt-Pause-Add-Question {
+ background: url(img/quiz_add_question.svg) no-repeat;
+ background-position: center;
+ background-size: contain;
+ position: absolute;
+ bottom: 40px;
+ right: 0px;
+ height: 15%;
+ width: 15%;
+ max-width: 64px;
+ max-height: 64px;
+ z-index: 10;
+}
+
+.Ldt-Quiz-Result {
+ position: absolute;
+ height: 0px;
+ bottom: 0;
+ left: 0;
+ right: 0;
+ background: #fde073;
+ text-align: center;
+ line-height: 2.5;
+ overflow: hidden;
+ -webkit-box-shadow: 0 0 5px black;
+ -moz-box-shadow: 0 0 5px black;
+ box-shadow: 0 0 5px black;
+}
+
+input[type="button"] {
+ border: none;
+ font-size: 18pt;
+ text-align: center;
+ background-color: #5BCE5B;
+ color: #fff;
+ cursor: pointer;
+}
+
+input[value="Non"] {
+ background-color: #F86060;
+}
+
+input.quiz-question:checked + .quiz-question-label {
+ text-decoration: underline;
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/src/ldt/ldt/static/ldt/metadataplayer/Quiz.js Fri Oct 02 10:24:05 2015 +0200
@@ -0,0 +1,388 @@
+IriSP.Widgets.Quiz = function(player, config) {
+ IriSP.Widgets.Widget.call(this, player, config);
+}
+
+IriSP.Widgets.Quiz.prototype = new IriSP.Widgets.Widget();
+
+IriSP.Widgets.Quiz.prototype.defaults = {
+ // annotation_type: "at_quiz",
+ quiz_activated: true,
+ api_serializer: "ldt_annotate",
+ analytics_api: "",
+ api_method: "POST",
+ user: "",
+ userid:""
+}
+
+IriSP.Widgets.Quiz.prototype.template = '<div class="Ldt-Quiz-Container">'
+ + '<div class="Ldt-Quiz-Header">'
+ + ' <div class="Ldt-Quiz-Index"></div><div class="Ldt-Quiz-Score"></div>'
+ + '</div>'
+ + '<div class="Ldt-Quiz-Content">'
+ + ' <h1 class="Ldt-Quiz-Title">{{question}}</h1>'
+ + ' <div class="Ldt-Quiz-Questions">'
+ + ' </div>'
+ + '</div>'
+ + '<div class="Ldt-Quiz-Footer">'
+ + ' <div class="Ldt-Quiz-Votes">'
+ + ' <span class="Ldt-Quiz-Votes-Question">Avez-vous trouvé cette question utile ?</span>'
+ + ' <div class="Ldt-Quiz-Votes-Buttons">'
+ + ' <div class="Ldt-Quiz-Vote-Skip-Block"><a href="#" class="Ldt-Quiz-Vote-Skip">Passer</a></div>'
+ + ' <div><input type="button" value="Non" class="Ldt-Quiz-Vote-Useless" /></div>'
+ + ' <div><input type="button" value="Oui" class="Ldt-Quiz-Vote-Useful" /></div>'
+ + ' </div>'
+ + ' </div>'
+ + ' <div class="Ldt-Quiz-Submit">'
+ + ' <div class="Ldt-Quiz-Submit-Button"><input type="button" value="Valider" /></div>'
+ + ' <div class="Ldt-Quiz-Submit-Skip-Link"><a href="#">Passer</a></div><div style="clear:both;"></div>'
+ + ' </div>'
+ + ' <div class="Ldt-Quiz-Result">Bonne réponse</div>'
+ + '</div>'
+ + '</div>';
+
+IriSP.Widgets.Quiz.prototype.annotationTemplate = '';
+
+IriSP.Widgets.Quiz.prototype.update = function(annotation) {
+ var _this = this;
+
+ if (this.quiz_activated &&
+ this.correct[annotation.id] != 1 &&
+ this.correct[annotation.id] != 0) {
+
+ _this.quiz_displayed = true;
+
+ //Pause the current video
+ this.media.pause();
+
+ this.annotation = annotation;
+
+ var question = annotation.content.data.question;
+ var answers = annotation.content.data.answers;
+ var resource = annotation.content.data.resource;
+
+ $(".Ldt-Quiz-Votes").hide();
+ $(".Ldt-Pause-Add-Question").hide();
+ $(".Ldt-Quiz-Container .Ldt-Quiz-Title").html(question);
+
+ var i = 0;
+
+ var score = Mustache.to_html('<span class="Ldt-Quiz-Correct-Answer">{{ correctness.0 }}</span> / <span class="Ldt-Quiz-Incorrect-Answer">{{ correctness.1 }}</span>', { correctness: this.globalScore() });
+ $(".Ldt-Quiz-Index").html(Mustache.to_html("Q{{index}}/{{total}}", { index: annotation.number + 1,
+ total: this.totalAmount }));
+ $(".Ldt-Quiz-Score").html(score);
+ this.question = new IriSP.Widgets.UniqueChoiceQuestion(annotation);
+ this.resource = new IriSP.Widgets.UniqueChoiceQuestion(resource);
+
+ if (annotation.content.data.type == "multiple_choice") {
+ this.question = new IriSP.Widgets.MultipleChoiceQuestion(annotation);
+ this.resource = new IriSP.Widgets.MultipleChoiceQuestion(resource);
+ }
+ else if (annotation.content.data.type == "unique_choice") {
+ this.question = new IriSP.Widgets.UniqueChoiceQuestion(annotation);
+ this.resource = new IriSP.Widgets.UniqueChoiceQuestion(resource);
+ }
+
+ var output = "";
+ for (i = 0; i < answers.length; i++) {
+ output += '<div class="quiz-question-block"><p>' + this.question.renderQuizTemplate(answers[i], i) + '<span class="quiz-question-label">'+ answers[i].content + '</span></p></div>';
+ }
+
+
+ var QR = '';
+ //If there is an attached resource, display it on the resources overlay
+ if (resource != null) {
+ QR = '<div class="quiz-resource-block" id="resource" >' + resource + '</div>';
+ };
+ $(".Ldt-Quiz-Questions").html(QR + output);
+ $(".Ldt-Quiz-Overlay").fadeIn();
+
+ $(".Ldt-Quiz-Submit").fadeIn();
+
+ //Let's automatically check the checkbox/radio if we click on the label
+ $(".quiz-question-label").click(function() {
+ var input = $(this).siblings("input");
+ if (input.prop('checked') && input.prop('type') == 'radio') {
+ // Already checked. Consider a double click on unique question as a validation.
+ _this.answer();
+ } else {
+ input.prop('checked', !input.prop('checked'));
+ }
+ });
+
+ //In case we click on the first "Skip" link
+ $(".Ldt-Quiz-Submit-Skip-Link").click({media: this.media}, function(event) {
+ _this.hide();
+ _this.player.trigger("QuizCreator.skip");
+ event.data.media.play();
+ });
+ }
+};
+
+IriSP.Widgets.Quiz.prototype.hide = function() {
+ var _this = this;
+
+ $(".Ldt-Quiz-Votes").hide();
+ $(".Ldt-Quiz-Overlay").hide();
+ $(".Ldt-Pause-Add-Question").hide();
+ _this.quiz_displayed = false;
+}
+
+IriSP.Widgets.Quiz.prototype.answer = function() {
+ var _this = this;
+
+ function insert_timecode_links (s) {
+ return (s || "").replace(/\s(\d+:\d+)/, function (match, timecode) {
+ return ' <a href="#t=' + (IriSP.timestamp2ms(timecode) / 1000) + '">' + timecode + '</a>';
+ });
+ };
+
+ var answers = _this.annotation.content.data.answers;
+
+ // Augment answers with the correct feedback
+ var i = 0;
+ var wrong = 0;
+ // Signature is an array giving the answers signature: 1 for checked, 0 for unchecked
+ // We cannot simply store the right answer index, since there may be multiple-choice questions
+ var signature = [];
+ _this.$.find(".Ldt-Quiz-Question-Check").each( function (code) {
+ var checked = $(this).is(":checked");
+ signature.push(checked ? 1 : 0);
+ var ans = answers[i];
+ if ((ans.correct && !checked)
+ || (!ans.correct && checked)) {
+ wrong += 1;
+ IriSP.jQuery(this).parents(".quiz-question-block").append('<div class="quiz-question-feedback quiz-question-incorrect-feedback">'+ insert_timecode_links(ans.feedback) +'</div>');
+ } else {
+ IriSP.jQuery(this).parents(".quiz-question-block").append('<div class="quiz-question-feedback quiz-question-correct-feedback">'+ insert_timecode_links(ans.feedback) +'</div>');
+ }
+ i++;
+ });
+
+ if (wrong) {
+ $(".Ldt-Quiz-Result").html("Mauvaise réponse");
+ $(".Ldt-Quiz-Result").css({"background-color" : "red"});
+ this.correct[this.annotation.id] = 0;
+ } else {
+ $(".Ldt-Quiz-Result").html("Bonne réponse !");
+ $(".Ldt-Quiz-Result").css({"background-color" : "green"});
+ this.correct[this.annotation.id] = 1;
+ }
+
+ $(".Ldt-Quiz-Result").animate({height:"100%"},500, "linear", function() {
+ $(".Ldt-Quiz-Result").delay(2000).animate({ height:"0%" }, 500);
+ });
+
+ var question_number = this.annotation.number + 1;
+ var correctness = this.globalScore();
+ var score = "";
+ score += '<span class="Ldt-Quiz-Correct-Answer">' + correctness[0] +'</span> / <span class="Ldt-Quiz-Incorrect-Answer">' + correctness[1] + '</span>';
+ $(".Ldt-Quiz-Index").html("Q"+ question_number + "/" + this.totalAmount);
+ $(".Ldt-Quiz-Score").html(score);
+
+ this.submit(this.user, this.userid, this.annotation.id, wrong ? 'wrong_answer' : 'right_answer', signature.join(""));
+
+ //Hide the "Validate" button and display the UI dedicated to votes
+ $(".Ldt-Quiz-Submit").fadeOut(400, function () {
+ $(".Ldt-Quiz-Votes").show();
+ });
+};
+
+IriSP.Widgets.Quiz.prototype.globalScore = function() {
+ // Return 2 variables to know how many right and wrong answers there are
+ var values = _.values(this.correct);
+ var ok = values.filter( function (s) { return s == 1; }).length;
+ var not_ok = values.filter( function (s) { return s == 0; }).length;
+ return [ok, not_ok];
+};
+
+IriSP.Widgets.Quiz.prototype.refresh = function() {
+ var _annotations = this.getWidgetAnnotations().sortBy(function(_annotation) {
+ return _annotation.begin;
+ });
+
+ var _this = this;
+
+ _this.totalAmount = _annotations.length;
+ _this.number = 0;
+ _this.correct = {};
+ _this.keys = {};
+
+ _annotations.forEach(function(_a) {
+ //Fix each annotation as "non-answered yet"
+ _this.correct[_a.id] = -1;
+ _this.keys[_this.number] = _a.id;
+ _a.number = _this.number++;
+ });
+
+}
+
+IriSP.Widgets.Quiz.prototype.draw = function() {
+ var _this = this;
+ _this.quiz_displayed = false;
+ this.onMediaEvent("enter-annotation", function (annotation) {
+ var an = _this.getWidgetAnnotations().filter( function (a) { return a === annotation; });
+ if (an.number === undefined) {
+ _this.refresh();
+ }
+ if (an.length) {
+ _this.update(an[0]);
+ };
+ });
+ this.onMdpEvent("Quiz.activate", function() {
+ _this.quiz_activated = true;
+ });
+
+ this.onMdpEvent("Quiz.deactivate", function() {
+ _this.quiz_activated = false;
+ _this.hide();
+ });
+
+ this.onMdpEvent("Quiz.hide", function() {
+ _this.hide();
+ });
+
+ this.onMdpEvent("Quiz.refresh", function() {
+ _this.refresh();
+ });
+
+ this.onMediaEvent("pause", function() {
+ if (! _this.quiz_displayed) {
+ $(".Ldt-Pause-Add-Question").show();
+ }
+ });
+
+ this.onMediaEvent("play", function() {
+ $(".Ldt-Pause-Add-Question").hide();
+ });
+
+ // Add Ldt-Quiz-Overlay widget on top of video player
+ _this.overlay = $("<div class='Ldt-Quiz-Overlay'></div>").appendTo($('#' + _this.container));
+ _this.PauseAddQuestion = $("<div class='Ldt-Pause-Add-Question' title='Ajoutez une question !'>")
+ .on("click", function() { _this.player.trigger("QuizCreator.create"); })
+ .appendTo($('#' + _this.container));
+ _this.overlay.html(this.template);
+
+ $(".Ldt-Quiz-Overlay").hide();
+
+ $(".Ldt-Quiz-Submit input").click(function() {
+ _this.answer();
+ });
+
+ //In case we click on the first "Skip" link
+ $(".Ldt-Quiz-Submit-Skip-Link").click({ media: this.media }, function(event) {
+ _this.submit(_this.user, _this.userid, _this.annotation.id, "skipped_answer", 0);
+ _this.hide();
+ _this.player.trigger("QuizCreator.skip");
+ event.data.media.play();
+ });
+
+ $(".Ldt-Quiz-Votes-Buttons input[type=\"button\"], .Ldt-Quiz-Votes-Buttons a").click({media: this.media}, function(event) {
+ var vote_prop, vote_val;
+
+ if ($(this).hasClass("Ldt-Quiz-Vote-Useful")) {
+ vote_prop = "useful";
+ vote_val = 1;
+ } else if ($(this).hasClass("Ldt-Quiz-Vote-Useless")) {
+ vote_prop = "useless";
+ vote_val = -1;
+
+ $(".Ldt-Ctrl-Quiz-Create").addClass("button_highlight").delay(5000).queue(function() {
+ $(this).removeClass("button_highlight").dequeue();
+ });
+ }else{
+ vote_prop = "skipped_vote";
+ vote_val = 0;
+ }
+
+ _this.submit(_this.user, _this.userid, _this.annotation.id, vote_prop, vote_val);
+
+ //Resume the current video
+ event.data.media.play();
+
+ _this.hide();
+ $(".Ldt-Pause-Add-Question").hide();
+
+ _this.player.trigger("QuizCreator.skip");
+ });
+
+ _this.refresh();
+};
+
+//Generates uid
+//source : http://stackoverflow.com/questions/105034/create-guid-uuid-in-javascript
+IriSP.Widgets.Widget.prototype.generateUid = function () {
+ return 'xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx'.replace(/[xy]/g, function(c) {
+ var r = Math.random()*16|0, v = c === 'x' ? r : (r&0x3|0x8);
+ return v.toString(16);
+ });
+}
+
+//UniqueChoice Question
+IriSP.Widgets.UniqueChoiceQuestion = function(annotation) {
+ this.annotation = annotation;
+}
+
+IriSP.Widgets.UniqueChoiceQuestion.prototype = new IriSP.Widgets.Widget();
+
+IriSP.Widgets.UniqueChoiceQuestion.prototype.renderQuizTemplate = function(answer, identifier) {
+ return '<input type="radio" class="quiz-question Ldt-Quiz-Question-Check Ldt-Quiz-Question-Check-' + identifier + '" name="question" data-question="' + identifier + '" value="' + identifier + '" />';
+}
+
+IriSP.Widgets.UniqueChoiceQuestion.prototype.renderTemplate = function(answer, identifier) {
+ var id = this.generateUid();
+ return '<input type="radio" id="' + id + '" class="quiz-question-edition Ldt-Quiz-Question-Check Ldt-Quiz-Question-Check-'+ identifier +'" name="question" data-question="'+ identifier +'" value="' + identifier + '" /><label for="'+ id +'" title="Veuillez sélectionner la réponse correcte"></label>';
+}
+
+IriSP.Widgets.UniqueChoiceQuestion.prototype.renderFullTemplate = function(answer, identifier) {
+ var correct = (answer && answer.correct) ? "checked" : "";
+ var id = this.generateUid();
+ return '<input type="radio" id="'+ id +'" '+ correct +' class="quiz-question-edition Ldt-Quiz-Question-Check Ldt-Quiz-Question-Check-'+ identifier +'" name="question" data-question="'+ identifier +'" value="' + identifier + '" /><label for="'+ id +'"></label>';
+}
+
+
+//MultipleChoice Question
+IriSP.Widgets.MultipleChoiceQuestion = function(annotation) {
+ this.annotation = annotation;
+}
+
+IriSP.Widgets.MultipleChoiceQuestion.prototype = new IriSP.Widgets.Widget();
+
+IriSP.Widgets.MultipleChoiceQuestion.prototype.renderQuizTemplate = function(answer, identifier) {
+ return '<input type="checkbox" class="quiz-question Ldt-Quiz-Question-Check Ldt-Quiz-Question-Check-'+ identifier + '" name="question['+ identifier +']" data-question="'+ identifier +'" value="' + identifier + '" /> ';
+}
+
+IriSP.Widgets.MultipleChoiceQuestion.prototype.renderTemplate = function(answer, identifier) {
+ var id = this.generateUid();
+ return '<input type="checkbox" id="'+ id +'" class="quiz-question-edition Ldt-Quiz-Question-Check" name="question['+ identifier +']" data-question="'+ identifier +'" value="' + identifier + '" /><label for="'+ id +'" title="Veuillez sélectionner la ou les réponses correctes"></label>';
+}
+
+IriSP.Widgets.MultipleChoiceQuestion.prototype.renderFullTemplate = function(answer, identifier) {
+ var correct = (answer && answer.correct) ? "checked" : "";
+ var id = this.generateUid();
+ return '<input type="checkbox" id="'+ id +'" '+ correct +' class="quiz-question-edition Ldt-Quiz-Question-Check" name="question['+ identifier +']" data-question="'+ identifier +'" value="' + identifier + '" /><label for="'+ id +'"></label> ';
+}
+
+IriSP.Widgets.Quiz.prototype.submit = function(user,user_id,question,prop,val) {
+ var _this = this;
+ var _url = Mustache.to_html(this.analytics_api, {id: this.source.projectId}),
+ donnees = {
+ "username": user,
+ "useruuid": user_id,
+ "subject": question,
+ "property": prop,
+ "value": val,
+ "session": _this.session_id
+ };
+
+ IriSP.jQuery.ajax({
+ url: _url,
+ type: this.api_method,
+ contentType: 'application/json',
+ data: JSON.stringify(donnees),
+ success: function(_data) {
+ },
+ error: function(_xhr, _error, _thrown) {
+ IriSP.log("Error when sending annotation", _thrown);
+ }
+ });
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/src/ldt/ldt/static/ldt/metadataplayer/QuizCreator.css Fri Oct 02 10:24:05 2015 +0200
@@ -0,0 +1,75 @@
+.Ldt-QuizCreator-Ui {
+ width: 100%;
+ padding: 10px;
+}
+
+.Ldt-QuizCreator-Form {
+ width: 100%;
+}
+
+.Ldt-QuizCreator-Question-Type {
+}
+
+.Ldt-QuizCreator-Question-Area,
+.Ldt-QuizCreator-Resource-Area {
+ width: calc(100% - 20px);
+}
+
+.Ldt-QuizCreator-Questions-Block {
+ width: 100%;
+}
+
+.Ldt-QuizCreator-Questions-Answer {
+ margin-top: 5px;
+ border-top: 1px solid black;
+}
+
+.Ldt-QuizCreator-Questions-Answer div {
+ display: inline-block;
+ vertical-align: middle;
+}
+
+.Ldt-QuizCreator-Questions-Answer-Content {
+ width: calc(100% - 80px);
+}
+
+.Ldt-QuizCreator-Questions-Answer-Content input, .Ldt-QuizCreator-Questions-Answer-Content textarea {
+ width: calc(100% - 20px);
+}
+
+.Ldt-QuizCreator-Questions-Answer-Time input {
+ width: 60px;
+}
+
+.Ldt-QuizCreator-Questions-Answer-Delete {
+ width: 15px;
+ height: 15px;
+}
+
+.Ldt-QuizCreator-Remove {
+ width: 15px;
+ height: 15px;
+ margin-left: 8px;
+ cursor: pointer;
+ background: url(img/delete.png);
+}
+
+input.quiz-question-edition {
+ display: none;
+}
+
+input.quiz-question-edition[type='radio'] + label,
+input.quiz-question-edition[type='checkbox'] + label {
+ height: 12px;
+ width: 24px;
+ display: inline-block;
+ background: url(img/min_wrong_toggle.png);
+ cursor: pointer;
+ content: "Mauvaise";
+}
+
+input.quiz-question-edition[type='radio']:checked + label,
+input.quiz-question-edition[type='checkbox']:checked + label {
+ background: url(img/min_right_toggle.png);
+ content: "Bonne";
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/src/ldt/ldt/static/ldt/metadataplayer/QuizCreator.js Fri Oct 02 10:24:05 2015 +0200
@@ -0,0 +1,306 @@
+/* TODO: Add Social Network Sharing */
+
+IriSP.Widgets.QuizCreator = function(player, config) {
+ var _this = this;
+ IriSP.Widgets.Widget.call(this, player, config);
+};
+
+IriSP.Widgets.QuizCreator.prototype = new IriSP.Widgets.Widget();
+
+IriSP.Widgets.QuizCreator.prototype.defaults = {
+ creator_name : "",
+ tags : false,
+ tag_titles : false,
+ pause_on_write : true,
+ annotation_type: "Quiz",
+ api_serializer: "ldt_annotate",
+ api_endpoint_template: "",
+ api_method: "POST"
+};
+
+IriSP.Widgets.QuizCreator.prototype.messages = {
+ en: {
+ },
+ fr: {
+ }
+};
+
+IriSP.Widgets.QuizCreator.prototype.template =
+ '<div class="Ldt-QuizCreator-Ui Ldt-TraceMe">'
+ + '<div class="Ldt-QuizCreator-Question-Form">'
+ + '<textarea class="Ldt-QuizCreator-Question-Area" placeholder="Votre question"></textarea><br />'
+ + '<textarea class="Ldt-QuizCreator-Resource-Area" placeholder="Ressources (lien vers une image, etc.)"></textarea><br />'
+ + '</div>'
+ + '<p>Type de question '
+ + '<select name="type" class="Ldt-QuizCreator-Question-Type">'
+ + '<option value="unique_choice">Choix unique</option>'
+ + '<option value="multiple_choice">Choix multiple</option>'
+ + '</select>'
+ + ' à <input type="text" placeholder="hh:mm:ss" size="6" class="Ldt-QuizCreator-Time" />'
+ + '<div class="Ldt-QuizCreator-Questions-Block">'
+ + '</div>'
+ + '<div>'
+ + ' <button class="Ldt-QuizCreator-Question-Add">Ajouter une réponse</button><hr>'
+ + ' <button class="Ldt-QuizCreator-Question-Save">Sauvegarder</button>'
+ + '</div>'
+ + '</div>';
+
+/* Hide and clear the interface is case of someone skipped or answer the current question in the Quiz panel*/
+IriSP.Widgets.QuizCreator.prototype.skip = function() {
+ this.$.find(".Ldt-QuizCreator-Time").val("");
+ this.$.find(".Ldt-QuizCreator-Question-Area").val("");
+ this.$.find(".Ldt-QuizCreator-Resource-Area").val("");
+ this.$.find(".Ldt-QuizCreator-Questions-Block").html("");
+ this.current_annotation = undefined;
+};
+
+IriSP.Widgets.QuizCreator.prototype.nbAnswers = function(){
+ var numItems = this.$.find('.Ldt-QuizCreator-Questions-Answer').length;
+ return numItems;
+};
+
+IriSP.Widgets.QuizCreator.prototype.draw = function() {
+ var _this = this;
+
+ this.onMediaEvent("timeupdate", function(_time) {
+ _this.setBegin(_time);
+ });
+
+ this.onMdpEvent("QuizCreator.show", function() {
+ _this.setBegin(_this.media.currentTime);
+ });
+
+ this.onMdpEvent("QuizCreator.create", function() {
+ _this.skip();
+ _this.setBegin(_this.media.currentTime);
+ });
+
+ this.onMdpEvent("QuizCreator.skip", function() {
+ _this.skip();
+ });
+
+ this.onMdpEvent("QuizCreator.edit", function (_annotation) {
+ _this.skip();
+ _this.addQuestion(_annotation);
+ });
+
+ this.$.on("click", ".Ldt-QuizCreator-Remove", function() {
+ $(this).parents(".Ldt-QuizCreator-Questions-Answer").remove();
+ });
+
+ this.begin = new IriSP.Model.Time();
+ this.end = this.source.getDuration();
+ this.answers = [];
+
+ this.renderTemplate();
+
+ /* Quiz creator */
+
+ this.question = new IriSP.Widgets.UniqueChoiceQuestion();
+
+ this.$.find(".Ldt-QuizCreator-Question-Type").bind("change", this.functionWrapper("onQuestionTypeChange"));
+ this.$.find(".Ldt-QuizCreator-Question-Add").bind("click", this.functionWrapper("onQuestionAdd"));
+ this.$.find(".Ldt-QuizCreator-Question-Save").bind("click", this.functionWrapper("onSave"));
+
+ this.$.find(".Ldt-QuizCreator-Time").keyup(function() {
+ var str = _this.$.find(".Ldt-QuizCreator-Time").val();
+ _this.begin = IriSP.timestamp2ms(str);
+ _this.end = _this.begin + 1000;
+ });
+
+ this.onMediaEvent("timeupdate", function(_time) {
+ // Do not update timecode if description is not empty
+ if (_this.getDescription()) {
+ _this.setBegin(_time);
+ };
+ });
+};
+
+IriSP.Widgets.QuizCreator.prototype.getDescription = function() {
+ return this.$.find(".Ldt-QuizCreator-Question-Area").val().trim();
+};
+
+IriSP.Widgets.QuizCreator.prototype.addQuestion = function(annotation, number) {
+ var _this = this;
+
+ if (annotation.content.data.type == "multiple_choice") {
+ this.question = new IriSP.Widgets.MultipleChoiceQuestion(annotation);
+ }
+ else if (annotation.content.data.type == "unique_choice") {
+ this.question = new IriSP.Widgets.UniqueChoiceQuestion(annotation);
+ }
+
+ var answers = annotation.content.data.answers;
+
+ this.answers = [];
+
+
+ this.$.find(".Ldt-QuizCreator-Time").val(annotation.begin);
+ this.$.find(".Ldt-QuizCreator-Question-Area").val(annotation.content.data.question);
+ this.$.find(".Ldt-QuizCreator-Resource-Area").val(annotation.content.data.resource);
+ this.$.find(".Ldt-QuizCreator-Questions-Block").html('');
+ answers.forEach( function (ans) {
+ _this.onQuestionAdd(null, ans);
+ });
+ _this.current_annotation = annotation;
+};
+
+IriSP.Widgets.QuizCreator.prototype.onQuestionTypeChange = function(e) {
+
+ var _field = this.$.find(".Ldt-QuizCreator-Question-Type");
+ var _contents = _field.val();
+
+ var _this = this;
+ switch(_contents) {
+ case "unique_choice":
+ this.question = new IriSP.Widgets.UniqueChoiceQuestion();
+ break;
+
+ case "multiple_choice":
+ this.question = new IriSP.Widgets.MultipleChoiceQuestion();
+ break;
+ }
+
+ var output = "";
+
+ _this.$.find(".Ldt-QuizCreator-Questions-Block").html(output);
+
+ this.pauseOnWrite();
+};
+
+// Either e !== undefined, then it has been called by the interface and answer === undefined, generate an empty form.
+// Or e === null && answer !== undefined, an existing answer is provided.
+IriSP.Widgets.QuizCreator.prototype.onQuestionAdd = function(e, answer) {
+ var output = '<div class="Ldt-QuizCreator-Questions-Answer">'
+ + 'Réponse <div class="Ldt-QuizCreator-Questions-Answer-Correct">'+ this.question.renderFullTemplate(answer, this.nbAnswers()) +'</div><br />'
+ + '<div class="Ldt-QuizCreator-Questions-Answer-Content">'
+ + '<input type="text" class="Ldt-QuizCreator-Answer-Content" data-question="'+ this.nbAnswers() +'" id="question'+ this.nbAnswers() + '"' + (answer ? ' value="'+ answer.content + '"' : "") + '/><br />'
+ + 'Commentaire <br/><textarea class="Ldt-QuizCreator-Answer-Feedback" data-question="'+ this.nbAnswers() +'" id="feedback'+ this.nbAnswers() +'">' + (answer ? answer.feedback : "") + '</textarea>'
+ + '</div>'
+ + '<div class="Ldt-QuizCreator-Questions-Answer-Delete"><div class="Ldt-QuizCreator-Remove"> </div></div>'
+ + '</div>';
+ this.$.find(".Ldt-QuizCreator-Questions-Block").append(output);
+ this.$.find(".Ldt-QuizCreator-Answer-Content").last().focus();
+
+ this.pauseOnWrite();
+};
+
+IriSP.Widgets.QuizCreator.prototype.pauseOnWrite = function() {
+ if (this.pause_on_write && !this.media.getPaused()) {
+ this.media.pause();
+ }
+};
+
+IriSP.Widgets.QuizCreator.prototype.setBegin = function (t) {
+ this.begin = new IriSP.Model.Time(t || 0);
+ this.end = this.begin + 500;
+ this.$.find(".Ldt-QuizCreator-Time").val(this.begin.toString());
+};
+
+IriSP.Widgets.QuizCreator.prototype.get_local_annotation = function (ident) {
+ return this.player.getLocalAnnotation(ident);
+};
+
+IriSP.Widgets.QuizCreator.prototype.save_local_annotations = function() {
+ this.player.saveLocalAnnotations();
+ // Merge modifications into widget source
+ this.source.merge(this.player.localSource);
+};
+
+IriSP.Widgets.QuizCreator.prototype.delete_local_annotation = function(ident) {
+ this.source.getAnnotations().removeId(ident);
+ this.player.deleteLocalAnnotation(ident);
+ this.current_annotation = undefined;
+ this.refresh(true);
+};
+
+IriSP.Widgets.QuizCreator.prototype.show = function() {
+ this.$.find(".Ldt-QuizCreator-Question-Area").focus();
+};
+
+IriSP.Widgets.QuizCreator.prototype.hide = function() {
+ this.$.find(".Ldt-QuizCreator-Questions-Block").html("");
+ this.$.find(".Ldt-QuizCreator-Question-Area").val("");
+ this.$.find(".Ldt-QuizCreator-Resource-Area").val("");
+ this.$.find(".Ldt-QuizCreator-Time").val("");
+};
+
+/* Save a local annotation */
+IriSP.Widgets.QuizCreator.prototype.onSave = function(event, should_publish) {
+ // Either the annotation already exists (then we overwrite its
+ // content) or it must be created.
+ var is_created = false;
+
+ if (this.nbAnswers() <= 0) {
+ alert("Vous devez spécifier au moins une réponse à votre question !");
+ return false;
+ };
+ // Check that there is at least 1 valid answer
+ if (! this.$.find(".quiz-question-edition:checked").length) {
+ alert("Vous n'avez pas indiqué de bonne réponse.");
+ return false;
+ };
+ var _annotation;
+ if (this.current_annotation) {
+ is_created = false;
+ _annotation = this.current_annotation;
+ } else {
+ is_created = true;
+ var _annotationTypes = this.source.getAnnotationTypes().searchByTitle(this.annotation_type, true), /* Récupération du type d'annotation dans lequel l'annotation doit être ajoutée */
+ _annotationType = (_annotationTypes.length ? _annotationTypes[0] : new IriSP.Model.AnnotationType(false, this.player.localSource)); /* Si le Type d'Annotation n'existe pas, il est créé à la volée */
+
+ /* Si nous avons dû générer un ID d'annotationType à la volée... */
+ if (!_annotationTypes.length) {
+ /* Il ne faudra pas envoyer l'ID généré au serveur */
+ _annotationType.dont_send_id = true;
+ /* Il faut inclure le titre dans le type d'annotation */
+ _annotationType.title = this.annotation_type;
+ }
+
+ _annotation = new IriSP.Model.Annotation(false, this.player.localSource); /* Création d'une annotation dans cette source avec un ID généré à la volée (param. false) */
+
+ // Initialize some fields in case of creation
+ _annotation.created = new Date(); /* Date de création de l'annotation */
+ _annotation.creator = this.creator_name;
+ _annotation.setAnnotationType(_annotationType.id); /* Id du type d'annotation */
+ this.player.localSource.getMedias().push(this.source.currentMedia);
+ _annotation.setMedia(this.source.currentMedia.id); /* Id du média annoté */
+ }
+
+ /*
+ * Nous remplissons les données de l'annotation
+ * */
+ _annotation.setBeginEnd(this.begin, this.end);
+ _annotation.modified = new Date(); /* Date de modification de l'annotation */
+ _annotation.contributor = this.creator_name;
+ _annotation.description = this.getDescription();
+ _annotation.title = _annotation.description;
+ _annotation.content = {};
+ _annotation.content.data = {};
+ _annotation.content.data.type = this.$.find(".Ldt-QuizCreator-Question-Type").val();
+ _annotation.content.data.question = _annotation.description;
+ _annotation.content.data.resource = this.$.find(".Ldt-QuizCreator-Resource-Area").val();
+ _annotation.content.data.answers = $.makeArray($(".Ldt-QuizCreator-Questions-Answer")
+ .map(function (ans)
+ {
+ return {
+ content: $(this).find(".Ldt-QuizCreator-Answer-Content").val(),
+ feedback: $(this).find(".Ldt-QuizCreator-Answer-Feedback").val(),
+ correct: $(this).find(".Ldt-Quiz-Question-Check").is(':checked')
+ };
+ }));
+ this.current_annotation = _annotation;
+ if (is_created) {
+ // Add the annotation to the localSource
+ this.player.addLocalAnnotation(_annotation);
+ // Update also the remote source
+ this.source.merge([ _annotation ]);
+ this.player.trigger("Annotation.create", _annotation);
+ } else {
+ // Update the annotation
+ this.player.saveLocalAnnotations();
+ this.player.trigger("Annotation.update", _annotation);
+ };
+ this.player.trigger("AnnotationsList.update"); /* On force le rafraîchissement des widgets AnnotationsList */
+ this.player.trigger("Quiz.refresh"); /* On force le rafraîchissement des widgets Quiz */
+};
--- a/src/ldt/ldt/static/ldt/metadataplayer/Segments.js Fri Sep 18 16:10:29 2015 +0200
+++ b/src/ldt/ldt/static/ldt/metadataplayer/Segments.js Fri Oct 02 10:24:05 2015 +0200
@@ -30,13 +30,15 @@
+ 'style="top:{{top}}px; height:{{height}}px; left:{{left}}px; width:{{width}}px; background:{{medcolor}}" data-base-color="{{color}}" data-low-color="{{lowcolor}}" data-medium-color="{{medcolor}}"></div>';
-IriSP.Widgets.Segments.prototype.draw = function() {
- this.onMediaEvent("timeupdate", "onTimeupdate");
- this.renderTemplate();
-
+IriSP.Widgets.Segments.prototype.do_draw = function (isRedraw) {
+ if (this.width != this.$.parent().width()) {
+ // Reset width
+ this.width = this.$.parent().width();
+ this.$.css({ width : this.width + "px" });
+ }
var _list = this.getWidgetAnnotations().filter(function(_ann) {
- return _ann.getDuration() > 0;
- }),
+ return _ann.getDuration() > 0;
+ }),
_this = this,
_scale = this.width / this.source.getDuration(),
list_$ = this.$.find('.Ldt-Segments-List'),
@@ -54,7 +56,11 @@
}
return "#" + res;
}
-
+
+ if (isRedraw) {
+ // Remove all previous elements before recreating them. Not very efficient.
+ this.$.find('.Ldt-Segments-Segment').remove();
+ }
_list.forEach(function(_annotation, _k) {
var _left = _annotation.begin * _scale,
_width = ( _annotation.getDuration() ) * _scale,
@@ -102,7 +108,9 @@
.click(function() {
if(_this.use_timerange){
if(!_this.media.getTimeRange()){
- _this.media.setTimeRange(_annotation.begin, _annotation.end)
+ _this.media.setCurrentTime(_annotation.begin);
+ _this.media.setTimeRange(_annotation.begin, _annotation.end);
+ _this.media.play();
_this.$segments.each(function(){
var _segment = IriSP.jQuery(this);
_segment.css("background", lowcolor).removeClass("selected");
@@ -118,7 +126,9 @@
})
}
else {
+ _this.media.setCurrentTime(_annotation.begin);
_this.media.setTimeRange(_annotation.begin, _annotation.end);
+ _this.media.play();
_this.$segments.each(function(){
var _segment = IriSP.jQuery(this);
_segment.css("background", lowcolor).removeClass("selected");
@@ -135,7 +145,8 @@
uri: (typeof _annotation.url !== "undefined"
? _annotation.url
: (document.location.href.replace(/#.*$/,'') + '#id=' + _annotation.id)),
- image: _annotation.thumbnail
+ image: _annotation.thumbnail,
+ text: '[' + _annotation.begin.toString() + '] ' + _annotation.title
});
_annotation.on("select", function() {
_this.$segments.each(function() {
@@ -180,9 +191,17 @@
background : this.background,
margin: "1px 0"
});
- if (!this.no_tooltip){
- this.insertSubwidget(
- this.$.find(".Ldt-Segments-Tooltip"),
+ this.$segments = this.$.find('.Ldt-Segments-Segment');
+};
+
+IriSP.Widgets.Segments.prototype.draw = function() {
+ var widget = this;
+ widget.onMediaEvent("timeupdate", "onTimeupdate");
+ widget.renderTemplate();
+ widget.do_draw();
+ if (!this.no_tooltip) {
+ widget.insertSubwidget(
+ widget.$.find(".Ldt-Segments-Tooltip"),
{
type: "Tooltip",
min_x: 0,
@@ -190,18 +209,18 @@
},
"tooltip"
);
- }
- this.$segments = this.$.find('.Ldt-Segments-Segment');
- this.source.getAnnotations().on("search", function() {
+ };
+ widget.source.getAnnotations().on("search", function() {
searching = true;
});
- this.source.getAnnotations().on("search-cleared", function() {
+ widget.source.getAnnotations().on("search-cleared", function() {
searching = false;
_this.$segments.each(function() {
var _segment = IriSP.jQuery(this);
_segment.css("background", _segment.attr("data-medium-color")).removeClass("found");
});
});
+ this.$.on("resize", function () { widget.do_draw(true); });
};
IriSP.Widgets.Segments.prototype.onTimeupdate = function(_time) {
--- a/src/ldt/ldt/static/ldt/metadataplayer/Shortcuts.js Fri Sep 18 16:10:29 2015 +0200
+++ b/src/ldt/ldt/static/ldt/metadataplayer/Shortcuts.js Fri Oct 02 10:24:05 2015 +0200
@@ -6,7 +6,7 @@
* Keyboard shortcuts widget
* This widgets add global shortcuts for common actions.
* The default shortcuts are:
- * - Escape or Control-space for play/pause
+ * - Control-space for play/pause
* - Control-left for rewind (+shift to go faster)
* - Control-right for forward (+shift to go faster)
*/
@@ -21,7 +21,7 @@
var _this = this;
/* Standard shortcuts */
- Mousetrap.bindGlobal(["esc", "ctrl+space"], function (e) {
+ Mousetrap.bindGlobal("ctrl+space", function (e) {
e.preventDefault();
if (! _this.media.getPaused()) {
_this.media.pause();
@@ -54,5 +54,11 @@
_this.media.setCurrentTime(Math.min(_this.media.duration, _this.media.getCurrentTime() + 5 * _this.time_increment));
return false;
});
+ Mousetrap.bindGlobal("ctrl+a", function (e) {
+ // Annotate
+ e.preventDefault();
+ _this.player.trigger("CreateAnnotation.toggle");
+ return false;
+ });
};
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/src/ldt/ldt/static/ldt/metadataplayer/SlidePreview.css Fri Oct 02 10:24:05 2015 +0200
@@ -0,0 +1,43 @@
+.Ldt-SlidePreview-Container {
+ background-color: #999;
+ left: 0px;
+ right: 0px;
+ height: 36px;
+ padding-left: 4px;
+ overflow: hidden;
+}
+.Ldt-SlidePreview-Slides {
+ display: -webkit-inline-flex;
+ display: inline-flex;
+ -webkit-flex-direction: row;
+ flex-direction: row;
+ -webkit-flex-wrap: nowrap;
+ flex-wrap: nowrap;
+ overflow-x: hidden;
+ left: 0px;
+ right: 0px;
+ height: 36px;
+ padding: 0;
+ padding-top: 12px;
+ margin: 0;
+ overflow-y: hidden;
+}
+.Ldt-SlidePreview-Item {
+ display: inline-block;
+ width: 20px;
+ height: 12px;
+ background-color: #fff;
+ transition: transform .2s ease-in-out;
+}
+.Ldt-SlidePreview-Item img {
+ max-width: 100%;
+ max-height: 100%;
+}
+.Ldt-SlidePreview-Item:hover {
+ -webkit-transform: scale(2.8);
+ z-index: 4;
+}
+.Ldt-SlidePreview-Item:hover + .slidepreviewitem {
+ -webkit-transform: scale(1.8);
+ z-index: 1;
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/src/ldt/ldt/static/ldt/metadataplayer/SlidePreview.js Fri Oct 02 10:24:05 2015 +0200
@@ -0,0 +1,38 @@
+IriSP.Widgets.SlidePreview = function(player, config) {
+ IriSP.Widgets.Widget.call(this, player, config);
+}
+
+IriSP.Widgets.SlidePreview.prototype = new IriSP.Widgets.Widget();
+
+IriSP.Widgets.SlidePreview.prototype.defaults = {
+ annotation_type: "Slides"
+}
+
+IriSP.Widgets.SlidePreview.prototype.template = '<div class="Ldt-SlidePreview-Container"><div class="Ldt-SlidePreview-Slides"></div></div>';
+
+IriSP.Widgets.SlidePreview.prototype.annotationTemplate = '<div data-id="{{ id }}" data-timecode="{{ ms }}" class="Ldt-SlidePreview-Item"><img title="{{ begin }} - {{ atitle }}" class="Ldt-AnnotationsList-Thumbnail" src="{{ thumbnail }}"></div>';
+
+IriSP.Widgets.SlidePreview.prototype.draw = function() {
+ var _annotations = this.getWidgetAnnotations().sortBy(function(_annotation) {
+ return _annotation.begin;
+ });
+ var _this = this;
+ _this.renderTemplate();
+ var content = _this.$.find('.Ldt-SlidePreview-Slides');
+
+ this.getWidgetAnnotations().forEach(function(_a) {
+ var _data = {
+ id : _a.id,
+ content : IriSP.textFieldHtml(_a.title),
+ begin : _a.begin.toString(),
+ ms: _a.begin.milliseconds,
+ thumbnail: _a.thumbnail
+ };
+ var _html = Mustache.to_html(_this.annotationTemplate, _data);
+ var _el = IriSP.jQuery(_html);
+ content.append(_el);
+ });
+ _this.$.on("click", ".Ldt-SlidePreview-Item", function () {
+ _this.media.setCurrentTime(Number(this.dataset.timecode));
+ });
+};
--- a/src/ldt/ldt/static/ldt/metadataplayer/SlideVideoPlayer.css Fri Sep 18 16:10:29 2015 +0200
+++ b/src/ldt/ldt/static/ldt/metadataplayer/SlideVideoPlayer.css Fri Oct 02 10:24:05 2015 +0200
@@ -1,23 +1,56 @@
-/* Empty for now */
-
.Ldt-SlideVideoPlayer-panel {
+ display: -webkit-flex;
display: flex;
width: 50%;
float: left;
}
.Ldt-SlideVideoPlayer {
- min-height: 400px;
- max-height: 100%;
-}
-
-.Ldt-SlideVideoPlayer {
width: 100%;
max-width: 100%;
height: 100%;
max-height: 100%;
}
+.Ldt-SlideVideoPlayer-pip-main {
+ position: relative;
+ width: 100%;
+ height: 100%;
+ top: 0px;
+ left: 0px;
+ right: 0px;
+ bottom: 0px;
+ z-index: 1;
+}
+
+.Ldt-SlideVideoPlayer-pip-pip {
+ position: absolute;
+ width: 30%;
+ height: 30%;
+ right: 2px;
+ bottom: 2px;
+ z-index: 3;
+}
+
.Ldt-SlideVideoPlayer h2 {
display: none;
}
+.Ldt-SlideVideoPlayer-pip-menu {
+ position: absolute;
+ top: 0px;
+ right: 0px;
+ z-index: 10;
+ display: none;
+}
+.Ldt-SlideVideoPlayer-pip-pip:hover .Ldt-SlideVideoPlayer-pip-menu {
+ background-color: #000;
+ opacity: .5;
+ display: inline-block;
+}
+
+.Ldt-SlideVideoPlayer-pip-menu-toggle {
+ width: 18px;
+ height: 18px;
+ cursor: pointer;
+ background-image: url(img/pip_toggle.svg);
+}
--- a/src/ldt/ldt/static/ldt/metadataplayer/SlideVideoPlayer.js Fri Sep 18 16:10:29 2015 +0200
+++ b/src/ldt/ldt/static/ldt/metadataplayer/SlideVideoPlayer.js Fri Oct 02 10:24:05 2015 +0200
@@ -7,12 +7,16 @@
IriSP.Widgets.SlideVideoPlayer.prototype.defaults = {
+ playerModule: "HtmlPlayer",
+ // mode is either "sidebyside" or "pip"
+ mode: "sidebyside"
};
IriSP.Widgets.SlideVideoPlayer.prototype.template = '<div class="Ldt-SlideVideoPlayer">\
-<div class="Ldt-SlideVideoPlayer-slide Ldt-SlideVideoPlayer-panel">\
-</div>\
-<div class="Ldt-SlideVideoPlayer-video Ldt-SlideVideoPlayer-panel"></div>\
+ <div class="Ldt-SlideVideoPlayer-slide Ldt-SlideVideoPlayer-panel">\
+ </div>\
+ <div class="Ldt-SlideVideoPlayer-video Ldt-SlideVideoPlayer-panel">\
+ </div>\
</div>';
IriSP.Widgets.SlideVideoPlayer.prototype.draw = function() {
@@ -23,24 +27,60 @@
_this.$.find(".Ldt-SlideVideoPlayer-panel.Ldt-SlideVideoPlayer-slide"),
{
type: "ImageDisplay",
- annotation_type: _this.annotation_type,
- width: '100%'
+ annotation_type: _this.annotation_type
},
"slide"
);
this.insertSubwidget(
_this.$.find(".Ldt-SlideVideoPlayer-panel.Ldt-SlideVideoPlayer-video"),
{
- type: "HtmlPlayer",
+ type: _this.playerModule,
video: _this.video,
width: '100%',
url_transform: _this.url_transform
},
"player"
- );
- // FIXME: this should be better implemented through a signal sent
- // when widgets are ready (and not just loaded)
- window.setTimeout(function () {
- _this.$.find(".Ldt-SlideVideoPlayer").split({ orientation: 'vertical' });
- }, 1000);
+ );
+
+ if (_this.mode == 'pip') {
+ _this.$.find(".Ldt-SlideVideoPlayer-panel").append('<div class="Ldt-SlideVideoPlayer-pip-menu"><div class="Ldt-SlideVideoPlayer-pip-menu-toggle"></div></div>');
+ _this.$.on("click", ".Ldt-SlideVideoPlayer-pip-menu-toggle", function () {
+ _this.toggleMainDisplay();
+ });
+ window.setTimeout(function () {
+ _this.setMainDisplay('video');
+ }, 1500);
+ } else {
+ // Default : side by side
+ // FIXME: this should be better implemented through a signal sent
+ // when widgets are ready (and not just loaded)
+ window.setTimeout(function () {
+ _this.$.find(".Ldt-SlideVideoPlayer").touchSplit({ orientation: (screen.height > screen.width) ? 'vertical' : 'horizontal',
+ leftMin: 20,
+ topMin: 20
+ });
+ }, 1500);
+ }
+};
+
+IriSP.Widgets.SlideVideoPlayer.prototype.toggleMainDisplay = function() {
+ if (this.$.find(".Ldt-SlideVideoPlayer-panel.Ldt-SlideVideoPlayer-video").hasClass("Ldt-SlideVideoPlayer-pip-main")) {
+ this.setMainDisplay('slides');
+ } else {
+ this.setMainDisplay('video');
+ }
+};
+
+// Set main display (in case of a "switch" display mode)
+// main is either 'video' or 'slides'
+IriSP.Widgets.SlideVideoPlayer.prototype.setMainDisplay = function(video_or_slides) {
+ var main = this.$.find(".Ldt-SlideVideoPlayer-panel.Ldt-SlideVideoPlayer-video");
+ var pip = this.$.find(".Ldt-SlideVideoPlayer-panel.Ldt-SlideVideoPlayer-slide");
+ if (video_or_slides == 'slides') {
+ var temp = main;
+ main = pip;
+ pip = temp;
+ };
+ main.removeClass('Ldt-SlideVideoPlayer-pip-pip').addClass('Ldt-SlideVideoPlayer-pip-main');
+ pip.removeClass('Ldt-SlideVideoPlayer-pip-main').addClass('Ldt-SlideVideoPlayer-pip-pip');
}
--- a/src/ldt/ldt/static/ldt/metadataplayer/Slider.css Fri Sep 18 16:10:29 2015 +0200
+++ b/src/ldt/ldt/static/ldt/metadataplayer/Slider.css Fri Oct 02 10:24:05 2015 +0200
@@ -1,11 +1,18 @@
/* Slider Widget */
.Ldt-Slider {
- border: none; border-radius: 0; padding: 0; margin: 0; background: #B6B8B8;
+ border: none;
+ border-radius: 0;
+ padding: 0;
+ margin: 0;
+ background: #B6B8B8;
}
.Ldt-Slider .ui-slider-handle {
- border-radius: 8px; top: -2px; background: #fc00ff; border: 1px solid #ffffff;
+ border-radius: 8px;
+ top: -2px;
+ background: #fc00ff;
+ border: 1px solid #ffffff;
}
.Ldt-Slider .ui-slider-range {
@@ -13,7 +20,19 @@
}
.Ldt-Slider-Time {
- position: absolute; top: -16px; background: #ffffc0; color: #000000; border-radius: 3px; z-index: 8;
- font-size: 10px; width: 34px; border: 1px solid #999999; padding: 1px; margin-left: -20px;
- display: none; text-align: center; font-weight: bold; pointer-events: none;
+ position: absolute;
+ bottom: 32px;
+ background: #ffffc0;
+ color: #000000;
+ border-radius: 3px;
+ z-index: 8;
+ font-size: 10px;
+ width: 34px;
+ border: 1px solid #999999;
+ padding: 1px;
+ margin-left: -20px;
+ display: none;
+ text-align: center;
+ font-weight: bold;
+ pointer-events: none;
}
--- a/src/ldt/ldt/static/ldt/metadataplayer/Slider.js Fri Sep 18 16:10:29 2015 +0200
+++ b/src/ldt/ldt/static/ldt/metadataplayer/Slider.js Fri Oct 02 10:24:05 2015 +0200
@@ -19,15 +19,15 @@
'<div class="Ldt-Slider"></div><div class="Ldt-Slider-Time">00:00</div>';
IriSP.Widgets.Slider.prototype.draw = function() {
-
+
this.renderTemplate();
-
+
this.$time = this.$.find(".Ldt-Slider-Time");
-
+
this.$slider = this.$.find(".Ldt-Slider");
-
+
var _this = this;
-
+
this.$slider.slider({
range: "min",
value: 0,
@@ -38,22 +38,22 @@
_this.player.trigger("Mediafragment.setHashToTime");
}
});
-
+
this.$handle = this.$slider.find('.ui-slider-handle');
-
+
this.onMediaEvent("timeupdate","onTimeupdate");
this.onMdpEvent("Player.MouseOver","onMouseover");
this.onMdpEvent("Player.MouseOut","onMouseout");
-
+
if (this.minimize_timeout) {
this.$slider.css(this.calculateSliderCss(this.minimized_height));
this.$handle.css(this.calculateHandleCss(this.minimized_height));
-
+
this.maximized = false;
this.timeoutId = false;
}
-
- this.$
+
+ this.$slider
.mouseover(function() {
_this.$time.show();
_this.onMouseover();
@@ -128,6 +128,6 @@
return {
height: (2 + _size) + "px",
width: (2 + _size) + "px",
- "margin-left": -Math.ceil(2 + _size / 2) + "px"
+ "margin-left": -Math.ceil(2 + _size / 2) + "px"
};
-};
\ No newline at end of file
+};
--- a/src/ldt/ldt/static/ldt/metadataplayer/Trace.js Fri Sep 18 16:10:29 2015 +0200
+++ b/src/ldt/ldt/static/ldt/metadataplayer/Trace.js Fri Oct 02 10:24:05 2015 +0200
@@ -68,6 +68,21 @@
this.tracer.trace("TraceWidgetInit", {});
+
+ // Configure annotation creation/update/delete/publish tracing
+ _this.player.on("Annotation.create", function (a) {
+ _this.tracer.trace("AnnotationCreated", { id: a.id, annotation_begin: a.begin.milliseconds, annotation_end: a.end.milliseconds, annotation_media: a.media.id, content_length: a.title.length, content_words: a.title.split(/\s+/).length });
+ });
+ _this.player.on("Annotation.delete", function (aid) {
+ _this.tracer.trace("AnnotationDeleted", { id: aid });
+ });
+ _this.player.on("Annotation.update", function (a) {
+ _this.tracer.trace("AnnotationUpdated", { id: a.id, annotation_begin: a.begin.milliseconds, annotation_end: a.end.milliseconds, annotation_media: a.media.id, content_length: a.title.length, content_words: a.title.split(/\s+/).length });
+ });
+ _this.player.on("Annotation.publish", function (a) {
+ _this.tracer.trace("AnnotationPublished", { id: a.id, annotation_begin: a.begin.milliseconds, annotation_end: a.end.milliseconds, annotation_media: a.media.id, content_length: a.title.length, content_words: a.title.split(/\s+/).length });
+ });
+
_this.player.trigger("trace-ready");
this.mouseLocation = '';
IriSP.jQuery(".Ldt-Widget").on("mousedown mouseenter mouseleave", ".Ldt-TraceMe", function(_e) {
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/src/ldt/ldt/static/ldt/metadataplayer/Transcript.css Fri Oct 02 10:24:05 2015 +0200
@@ -0,0 +1,9 @@
+.Ldt-Transcript-Annotation {
+ margin-right: .5em;
+}
+.Ldt-Transcript-Annotation:hover {
+ background-color: #bbb;
+}
+.Ldt-Transcript-Annotation.active {
+ background-color: #ddd;
+}
--- a/src/ldt/ldt/static/ldt/metadataplayer/Transcript.js Fri Sep 18 16:10:29 2015 +0200
+++ b/src/ldt/ldt/static/ldt/metadataplayer/Transcript.js Fri Oct 02 10:24:05 2015 +0200
@@ -7,13 +7,13 @@
IriSP.Widgets.Transcript.prototype = new IriSP.Widgets.Widget();
IriSP.Widgets.Transcript.prototype.defaults = {
- annotation_type: "Caption"
- // container: "transcriptContainer"
+ annotation_type: "Caption",
+ use_vtt_track: false
}
IriSP.Widgets.Transcript.prototype.template = '<div class="Ldt-TranscriptWidget"></div>';
-IriSP.Widgets.Transcript.prototype.annotationTemplate = '<a data-begin="{{ begin }}" data-end="{{ end }}" data-id="{{ id }}" class="Ldt-Transcript-Annotation" href="#{{id}}">{{ content }}</a> ';
+IriSP.Widgets.Transcript.prototype.annotationTemplate = '<span data-begin="{{ begin }}" data-end="{{ end }}" data-id="{{ id }}" class="Ldt-Transcript-Annotation">{{ content }}</span> ';
IriSP.Widgets.Transcript.prototype.draw = function() {
var _annotations = this.getWidgetAnnotations();
@@ -23,15 +23,57 @@
_this.renderTemplate();
content = _this.$.find('.Ldt-TranscriptWidget');
- _annotations.forEach(function(_a) {
- var _data = {
- id : _a.id,
- content : IriSP.textFieldHtml(_a.title),
- begin : _a.begin.toString(),
- end : _a.end.toString()
- };
- var _html = Mustache.to_html(_this.annotationTemplate, _data);
- var _el = IriSP.jQuery(_html);
- content.append(_el);
- });
+ if (_this.use_vtt_track) {
+ // Use webvtt track. It will only work with native video player.
+ var widgets = _this.player.widgets.filter(function (w) { return w.type == "HtmlPlayer"; });
+ if (widgets) {
+ var v = widgets[0].$.find("video")[0];
+ // FIXME: allow to specify the used track
+ v.addEventListener("loadedmetadata", function () {
+ var track = v.textTracks[0];
+ var cues = track.cues;
+ var i = 1;
+ Array.prototype.forEach.apply(cues, [ function(_c) {
+ _c.id = "cue" + i;
+ var _html = Mustache.to_html(_this.annotationTemplate, {
+ id : _c.id,
+ content : _c.text,
+ begin : 1000 * _c.startTime,
+ end : 1000 * _c.endTime
+ });
+ i += 1;
+ var _el = IriSP.jQuery(_html);
+ content.append(_el);
+ } ]);
+ track.addEventListener("cuechange", function () {
+ var acues = track.activeCues;
+ if (acues.length > 0) {
+ // Update attributes for active cues
+ _this.$.find(".Ldt-Transcript-Annotation.active").removeClass("active");
+ Array.prototype.forEach.apply(acues, [ function(_c) {
+ _this.$.find("#" + _c.id).addClass("active");
+ } ]);
+ }
+ }, false);
+ content.on("click", ".Ldt-Transcript-Annotation", function () {
+ _this.media.setCurrentTime(this.dataset.begin);
+ });
+ });
+ } else {
+ console.log("cannot find a video object");
+ }
+ } else {
+ // Populate with annotation data
+ _annotations.forEach(function(_a) {
+ var _data = {
+ id : _a.id,
+ content : IriSP.textFieldHtml(_a.title),
+ begin : _a.begin.toString(),
+ end : _a.end.toString()
+ };
+ var _html = Mustache.to_html(_this.annotationTemplate, _data);
+ var _el = IriSP.jQuery(_html);
+ content.append(_el);
+ });
+ };
};
Binary file src/ldt/ldt/static/ldt/metadataplayer/img/cancel_annotation.png has changed
Binary file src/ldt/ldt/static/ldt/metadataplayer/img/delete.png has changed
Binary file src/ldt/ldt/static/ldt/metadataplayer/img/edit.png has changed
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/src/ldt/ldt/static/ldt/metadataplayer/img/fullscreen.svg Fri Oct 02 10:24:05 2015 +0200
@@ -0,0 +1,62 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<!-- Created with Inkscape (http://www.inkscape.org/) -->
+
+<svg
+ xmlns:dc="http://purl.org/dc/elements/1.1/"
+ xmlns:cc="http://creativecommons.org/ns#"
+ xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
+ xmlns:svg="http://www.w3.org/2000/svg"
+ xmlns="http://www.w3.org/2000/svg"
+ xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
+ xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
+ width="22"
+ height="22"
+ viewBox="0 0 22.000001 22.000001"
+ id="svg4208"
+ version="1.1"
+ inkscape:version="0.48.4 r9939"
+ sodipodi:docname="FS.svg">
+ <defs
+ id="defs4210" />
+ <sodipodi:namedview
+ id="base"
+ pagecolor="#ffffff"
+ bordercolor="#666666"
+ borderopacity="1.0"
+ inkscape:pageopacity="0.0"
+ inkscape:pageshadow="2"
+ inkscape:zoom="20.48"
+ inkscape:cx="10.91933"
+ inkscape:cy="15.686744"
+ inkscape:document-units="px"
+ inkscape:current-layer="layer1"
+ showgrid="false"
+ inkscape:window-width="1680"
+ inkscape:window-height="1028"
+ inkscape:window-x="75"
+ inkscape:window-y="24"
+ inkscape:window-maximized="0" />
+ <metadata
+ id="metadata4213">
+ <rdf:RDF>
+ <cc:Work
+ rdf:about="">
+ <dc:format>image/svg+xml</dc:format>
+ <dc:type
+ rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
+ <dc:title />
+ </cc:Work>
+ </rdf:RDF>
+ </metadata>
+ <g
+ inkscape:label="Calque 1"
+ inkscape:groupmode="layer"
+ id="layer1"
+ transform="translate(0,-1030.3622)">
+ <path
+ style="fill:#000000"
+ d="m 0.5522696,1051.6037 c -0.41889785,-0.4329 -0.41461065,-8.2715 0.00441,-8.2715 0.16357544,0 0.8770369,0.5915 1.5854719,1.3145 l 1.2880668,1.3142 1.0474543,-1.062 c 1.2537252,-1.2715 2.0021739,-1.362 2.9358328,-0.3551 0.9287537,1.0018 0.8386288,1.7291 -0.3721746,3.0037 l -1.0280047,1.0824 1.2720657,1.3309 c 0.6996343,0.732 1.2720656,1.4692 1.2720656,1.6382 0,0.433 -7.58640438,0.4375 -8.00530223,0.01 z m 12.8865874,-0.01 c 0,-0.169 0.572426,-0.9062 1.272067,-1.6382 l 1.27206,-1.3308 -1.027999,-1.0823 c -1.210804,-1.2748 -1.300935,-2.0022 -0.372175,-3.0039 0.933653,-1.0069 1.682103,-0.9164 2.935828,0.3551 l 1.047458,1.062 1.288068,-1.3143 c 0.708435,-0.7229 1.421896,-1.3144 1.585473,-1.3144 0.419128,0 0.423427,7.8386 0.0044,8.2715 -0.418887,0.4328 -8.005291,0.4283 -8.005291,-0.01 z M 0.25939424,1035.3076 c 0,-2.7627 0.0897934,-4.0772 0.29287536,-4.287 0.41889785,-0.4328 8.0053023,-0.4284 8.0053023,0.01 0,0.1691 -0.5724257,0.9063 -1.2720657,1.6383 l -1.2720656,1.3309 1.0280047,1.0823 c 1.2304351,1.2954 1.3179943,2.0686 0.3434664,3.0334 -0.9694075,0.9597 -1.6734008,0.8665 -2.907119,-0.3846 l -1.0474598,-1.0621 -1.2880668,1.3143 c -0.708435,0.723 -1.42189663,1.3143 -1.5854665,1.3143 -0.2212842,0 -0.29740536,-1.0197 -0.29740536,-3.9844 z m 19.58692376,2.6673 -1.274753,-1.3171 -1.050191,1.0649 c -1.236549,1.254 -1.939853,1.3476 -2.909856,0.3874 -0.974534,-0.9647 -0.886969,-1.738 0.343467,-3.0335 l 1.027999,-1.0821 -1.27206,-1.3311 c -0.699641,-0.732 -1.272067,-1.4691 -1.272067,-1.6382 0,-0.433 7.586405,-0.4374 8.005303,-0.01 0.427969,0.4422 0.413673,8.2714 -0.01511,8.2714 -0.169391,0 -0.881623,-0.5926 -1.582735,-1.3171 z"
+ id="path3020"
+ inkscape:connector-curvature="0" />
+ </g>
+</svg>
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/src/ldt/ldt/static/ldt/metadataplayer/img/left_arrow.svg Fri Oct 02 10:24:05 2015 +0200
@@ -0,0 +1,9 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<svg xmlns="http://www.w3.org/2000/svg" width="32" height="32" id="arrow">
+ <path style="fill:none;stroke:#fff;stroke-width:6;stroke-linecap:round;stroke-linejoin:bevel;stroke-miterlimit:4;"
+ d="M31,1 l-30,15 l30,15">
+ </path>
+ <path style="fill:none;stroke:#000;stroke-width:4;stroke-linecap:round;stroke-linejoin:bevel;stroke-miterlimit:4;"
+ d="M31,1 l-30,15 l30,15">
+ </path>
+</svg>
Binary file src/ldt/ldt/static/ldt/metadataplayer/img/min_right_toggle.png has changed
Binary file src/ldt/ldt/static/ldt/metadataplayer/img/min_valid_sprites.png has changed
Binary file src/ldt/ldt/static/ldt/metadataplayer/img/min_wrong_toggle.png has changed
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/src/ldt/ldt/static/ldt/metadataplayer/img/pip_toggle.svg Fri Oct 02 10:24:05 2015 +0200
@@ -0,0 +1,71 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<!-- Created with Inkscape (http://www.inkscape.org/) -->
+
+<svg xmlns:dc="http://purl.org/dc/elements/1.1/"
+ xmlns:cc="http://creativecommons.org/ns#"
+ xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
+ xmlns:svg="http://www.w3.org/2000/svg"
+ xmlns="http://www.w3.org/2000/svg"
+ xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
+ xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
+ width="5.0797176mm"
+ height="5.0799999mm"
+ viewBox="0 0 17.998999 18"
+ id="svg19931"
+ version="1.1"
+ inkscape:version="0.91 r13725"
+ sodipodi:docname="pip_toggle.svg">
+ <defs
+ id="defs19933" />
+ <g
+ inkscape:label="Layer 1"
+ inkscape:groupmode="layer"
+ id="layer1"
+ transform="translate(-245.28621,-280.50506)">
+ <polygon
+ transform="translate(232.09221,226.21106)"
+ style="fill:#ffffff"
+ points="23.586,59.714 22.193,57.364 20.805,59.714 "
+ id="polygon13969" />
+ <polygon
+ transform="translate(232.09221,226.21106)"
+ style="fill:#ffffff"
+ points="22.971,59.364 21.417,59.364 22.496,57.544 22.193,57.364 21.894,57.544 22.193,57.364 21.894,57.187 20.19,60.063 24.199,60.063 22.193,56.679 21.894,57.187 22.193,57.364 21.894,57.544 "
+ id="polygon13971" />
+ <polygon
+ transform="translate(232.09221,226.21106)"
+ style="fill:#ffffff"
+ points="20.805,66.874 22.193,69.224 23.586,66.874 "
+ id="polygon13973" />
+ <polygon
+ transform="translate(232.09221,226.21106)"
+ style="fill:#ffffff"
+ points="21.417,67.224 22.971,67.224 21.894,69.044 22.193,69.224 22.496,69.044 22.193,69.224 22.496,69.399 24.199,66.522 20.19,66.522 22.193,69.909 22.496,69.399 22.193,69.224 22.496,69.044 "
+ id="polygon13975" />
+ <polygon
+ transform="translate(232.09221,226.21106)"
+ style="fill:#ffffff"
+ points="25.818,64.685 28.168,63.294 25.818,61.903 "
+ id="polygon13977" />
+ <polygon
+ transform="translate(232.09221,226.21106)"
+ style="fill:#ffffff"
+ points="26.168,64.071 26.168,62.517 27.988,63.595 28.168,63.294 27.988,62.993 28.168,63.294 28.347,62.993 25.468,61.29 25.468,65.298 28.855,63.294 28.347,62.993 28.168,63.294 27.988,62.993 "
+ id="polygon13979" />
+ <polygon
+ transform="translate(232.09221,226.21106)"
+ style="fill:#ffffff"
+ points="18.659,61.903 16.31,63.294 18.659,64.685 "
+ id="polygon13981" />
+ <polygon
+ transform="translate(232.09221,226.21106)"
+ style="fill:#ffffff"
+ points="18.309,62.517 18.309,64.071 16.488,62.993 16.31,63.294 16.488,63.595 16.31,63.294 16.132,63.595 19.009,65.298 19.009,61.29 15.624,63.294 16.132,63.595 16.31,63.294 16.488,63.595 "
+ id="polygon13983" />
+ <path
+ inkscape:connector-curvature="0"
+ style="fill:#ffffff"
+ d="m 254.28521,298.00506 0,0.5 c 4.965,-0.002 9,-4.035 9,-9 0,-4.965 -4.035,-9 -9,-9 -4.963,0 -8.998,4.035 -8.999,9 10e-4,4.965 4.036,8.998 8.999,9 l 0,-0.5 0,-0.5 c -2.206,0 -4.202,-0.896 -5.653,-2.346 -1.45,-1.451 -2.346,-3.447 -2.346,-5.654 0,-2.207 0.896,-4.203 2.346,-5.654 1.451,-1.449 3.448,-2.346 5.653,-2.346 2.207,0 4.205,0.896 5.654,2.346 1.45,1.451 2.347,3.447 2.347,5.654 0,2.207 -0.896,4.203 -2.347,5.654 -1.449,1.449 -3.447,2.346 -5.654,2.346 l 0,0.5 0,0 z"
+ id="path13985" />
+ </g>
+</svg>
Binary file src/ldt/ldt/static/ldt/metadataplayer/img/publish_annotation.png has changed
Binary file src/ldt/ldt/static/ldt/metadataplayer/img/published_annotation.png has changed
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/src/ldt/ldt/static/ldt/metadataplayer/img/quiz_add_question.svg Fri Oct 02 10:24:05 2015 +0200
@@ -0,0 +1,272 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<!-- Created with Inkscape (http://www.inkscape.org/) -->
+
+<svg
+ xmlns:dc="http://purl.org/dc/elements/1.1/"
+ xmlns:cc="http://creativecommons.org/ns#"
+ xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
+ xmlns:svg="http://www.w3.org/2000/svg"
+ xmlns="http://www.w3.org/2000/svg"
+ xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
+ xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
+ width="26"
+ height="25"
+ viewBox="0 0 26.000001 25.000001"
+ id="svg4208"
+ version="1.1"
+ inkscape:version="0.48.4 r9939"
+ sodipodi:docname="buzz.svg">
+ <defs
+ id="defs4210" />
+ <sodipodi:namedview
+ id="base"
+ pagecolor="#ffffff"
+ bordercolor="#666666"
+ borderopacity="1.0"
+ inkscape:pageopacity="0.0"
+ inkscape:pageshadow="2"
+ inkscape:zoom="10.24"
+ inkscape:cx="28.406106"
+ inkscape:cy="5.347153"
+ inkscape:document-units="px"
+ inkscape:current-layer="layer1"
+ showgrid="false"
+ inkscape:window-width="1680"
+ inkscape:window-height="1028"
+ inkscape:window-x="75"
+ inkscape:window-y="24"
+ inkscape:window-maximized="0" />
+ <metadata
+ id="metadata4213">
+ <rdf:RDF>
+ <cc:Work
+ rdf:about="">
+ <dc:format>image/svg+xml</dc:format>
+ <dc:type
+ rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
+ <dc:title />
+ </cc:Work>
+ </rdf:RDF>
+ </metadata>
+ <g
+ inkscape:label="Calque 1"
+ inkscape:groupmode="layer"
+ id="layer1"
+ transform="translate(0,-1027.3622)">
+ <g
+ id="g3115"
+ transform="matrix(0.13764231,0,0,0.14585411,-0.10960999,900.2163)">
+ <path
+ inkscape:connector-curvature="0"
+ id="path4152"
+ d="m 88.762577,966.09408 a 64.442296,17.911566 52.208592 0 0 -53.76267,-40.24111 64.442296,17.911566 52.208592 0 0 25.08146,61.71245 64.442296,17.911566 52.208592 0 0 53.763283,40.24068 64.442296,17.911566 52.208592 0 0 -25.082073,-61.71202 z"
+ style="fill:#b3b3b3;fill-opacity:1;stroke:#000000;stroke-width:2.23528218;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;display:inline" />
+ <rect
+ transform="matrix(0.61175214,0.7910495,-0.80052922,0.59929372,0,0)"
+ y="517.45343"
+ x="875.27667"
+ height="20.941669"
+ width="15.681897"
+ id="rect4311"
+ style="fill:#b3b3b3;fill-opacity:1;stroke:none;display:inline" />
+ <rect
+ transform="matrix(0.61175214,0.7910495,-0.80052922,0.59929372,0,0)"
+ y="519.57574"
+ x="762.16467"
+ height="19.048025"
+ width="13.667582"
+ id="rect4309"
+ style="fill:#b3b3b3;fill-opacity:1;stroke:none;display:inline" />
+ <rect
+ transform="matrix(0.61175214,0.7910495,-0.80052922,0.59929372,0,0)"
+ y="518.66687"
+ x="889.6543"
+ height="0.94452941"
+ width="1.1967648"
+ id="rect4313"
+ style="fill:#b3b3b3;fill-opacity:1;stroke:none;display:inline" />
+ <path
+ sodipodi:nodetypes="ccc"
+ inkscape:connector-curvature="0"
+ id="path4156-3"
+ d="m 113.50338,1028.0563 9.89486,-7.4107 8.37707,-6.2729"
+ style="fill:none;stroke:#000000;stroke-width:2.23528218;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;display:inline" />
+ <ellipse
+ sodipodi:ry="18.476786"
+ sodipodi:rx="64.438011"
+ sodipodi:cy="516.2522"
+ sodipodi:cx="826.67413"
+ d="m 891.11214,516.2522 c 0,10.20444 -28.84988,18.47678 -64.43801,18.47678 -35.58813,0 -64.43801,-8.27234 -64.43801,-18.47678 0,-10.20445 28.84988,-18.47679 64.43801,-18.47679 35.58813,0 64.43801,8.27234 64.43801,18.47679 z"
+ transform="matrix(0.61175214,0.7910495,-0.80052922,0.59929372,0,0)"
+ ry="18.476786"
+ rx="64.438011"
+ cy="516.2522"
+ cx="826.67413"
+ id="path4150"
+ style="fill:#666666;stroke:#000000;stroke-width:2.23541927;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;display:inline" />
+ <path
+ sodipodi:nodetypes="ccc"
+ inkscape:connector-curvature="0"
+ id="path4156"
+ d="m 35.104607,925.77201 9.7327,-7.28939 8.23979,-6.17012"
+ style="fill:none;stroke:#000000;stroke-width:2.23528218;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;display:inline" />
+ <ellipse
+ sodipodi:ry="8.1607332"
+ sodipodi:rx="36.851326"
+ sodipodi:cy="517.20477"
+ sodipodi:cx="827.2381"
+ d="m 864.08942,517.20477 c 0,4.50705 -16.4989,8.16074 -36.85132,8.16074 -20.35243,0 -36.85133,-3.65369 -36.85133,-8.16074 0,-4.50705 16.4989,-8.16073 36.85133,-8.16073 20.35242,0 36.85132,3.65368 36.85132,8.16073 z"
+ transform="matrix(0.61175214,0.7910495,-0.80052922,0.59929372,0,0)"
+ ry="8.1607332"
+ rx="36.851326"
+ cy="517.20477"
+ cx="827.2381"
+ id="path4317"
+ style="fill:#e6e6e6;fill-opacity:1;stroke:#000000;stroke-width:1.30889452;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;display:inline" />
+ <rect
+ transform="matrix(0.98439737,0.17595972,-0.17595972,0.98439737,0,0)"
+ y="907.08124"
+ x="233.80257"
+ height="3.9420969"
+ width="24.027122"
+ id="rect5190"
+ style="fill:#e6e6e6;fill-opacity:1;stroke:none;display:inline" />
+ <rect
+ transform="matrix(0.98439737,0.17595972,-0.17595972,0.98439737,0,0)"
+ y="906.15369"
+ x="235.03923"
+ height="4.2899289"
+ width="24.027122"
+ id="rect5190-9"
+ style="fill:#e6e6e6;fill-opacity:1;stroke:none;display:inline" />
+ <rect
+ transform="matrix(0.98439737,0.17595972,-0.17595972,0.98439737,0,0)"
+ y="905.3421"
+ x="236.39369"
+ height="4.2899289"
+ width="24.027122"
+ id="rect5190-9-1"
+ style="fill:#e6e6e6;fill-opacity:1;stroke:none;display:inline" />
+ <rect
+ transform="matrix(0.98439737,0.17595972,-0.17595972,0.98439737,0,0)"
+ y="904.47247"
+ x="237.51262"
+ height="4.0000691"
+ width="2.1789296"
+ id="rect5190-9-4"
+ style="fill:#e6e6e6;fill-opacity:1;stroke:none;display:inline" />
+ <rect
+ transform="matrix(0.98439737,0.17595972,-0.17595972,0.98439737,0,0)"
+ y="903.92175"
+ x="237.95427"
+ height="4.0000691"
+ width="2.1789296"
+ id="rect5190-9-4-4"
+ style="fill:#e6e6e6;fill-opacity:1;stroke:none;display:inline" />
+ <rect
+ transform="matrix(0.98439737,0.17595972,-0.17595972,0.98439737,0,0)"
+ y="908.00873"
+ x="233.77309"
+ height="2.5362754"
+ width="18.712299"
+ id="rect5190-9-0"
+ style="fill:#e6e6e6;fill-opacity:1;stroke:none;display:inline" />
+ <path
+ sodipodi:nodetypes="ccc"
+ inkscape:connector-curvature="0"
+ id="path4156-4"
+ d="m 69.344687,935.29586 10.13887,-6.16215 8.58357,-5.21581"
+ style="fill:none;stroke:#000000;stroke-width:1.30881441;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;display:inline" />
+ <rect
+ transform="matrix(0.98439737,0.17595972,-0.17595972,0.98439737,0,0)"
+ y="954.03864"
+ x="285.80243"
+ height="3.3044052"
+ width="2.9445002"
+ id="rect5279"
+ style="fill:#e6e6e6;fill-opacity:1;stroke:none;display:inline" />
+ <rect
+ transform="matrix(0.98439737,0.17595972,-0.17595972,0.98439737,0,0)"
+ y="948.15442"
+ x="283.03458"
+ height="7.8841949"
+ width="6.0067806"
+ id="rect5279-2"
+ style="fill:#e6e6e6;fill-opacity:1;stroke:none;display:inline" />
+ <rect
+ transform="matrix(0.98439737,0.17595972,-0.17595972,0.98439737,0,0)"
+ y="951.83563"
+ x="286.62689"
+ height="2.3188813"
+ width="4.7700906"
+ id="rect5279-2-3"
+ style="fill:#e6e6e6;fill-opacity:1;stroke:none;display:inline" />
+ <rect
+ transform="matrix(0.98439737,0.17595972,-0.17595972,0.98439737,0,0)"
+ y="953.51678"
+ x="285.83188"
+ height="1.971049"
+ width="4.4167504"
+ id="rect5279-2-3-3"
+ style="fill:#e6e6e6;fill-opacity:1;stroke:none;display:inline" />
+ <path
+ sodipodi:nodetypes="ccc"
+ inkscape:connector-curvature="0"
+ id="path4156-4-5"
+ d="m 114.62982,993.43082 9.47784,-7.0986 8.02405,-6.00861"
+ style="fill:none;stroke:#000000;stroke-width:1.30881441;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;display:inline" />
+ <rect
+ transform="matrix(0.98439737,0.17595972,-0.17595972,0.98439737,0,0)"
+ y="909.45807"
+ x="241.51714"
+ height="4.2899289"
+ width="24.027122"
+ id="rect5190-9-3"
+ style="fill:#e6e6e6;fill-opacity:1;stroke:none;display:inline" />
+ <ellipse
+ sodipodi:ry="11.1082"
+ sodipodi:rx="36.846481"
+ sodipodi:cy="495.24258"
+ sodipodi:cx="824.92773"
+ d="m 861.77422,495.24258 c 0,6.13489 -16.49674,11.1082 -36.84649,11.1082 -20.34975,0 -36.84648,-4.97331 -36.84648,-11.1082 0,-6.13489 16.49673,-11.1082 36.84648,-11.1082 20.34975,0 36.84649,4.97331 36.84649,11.1082 z"
+ transform="matrix(0.61175214,0.7910495,-0.80052922,0.59929372,0,0)"
+ ry="11.1082"
+ rx="36.846481"
+ cy="495.24258"
+ cx="824.92773"
+ id="path4351"
+ style="fill:#800000;fill-opacity:1;stroke:#000000;stroke-width:0.924097;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;display:inline" />
+ <path
+ id="path4564"
+ d="m 76.182057,895.08255 c 28.049053,-21.23075 69.407013,-14.64926 92.435693,14.54291 23.02867,29.19218 19.04627,70.22994 -9.00275,91.46064 -27.96073,21.2524 -111.393663,-84.75115 -83.432943,-106.00355 z"
+ stroke-miterlimit="10"
+ style="fill:#b3b3b3;fill-opacity:1;stroke:#000000;stroke-width:4.48099518;stroke-miterlimit:10;stroke-dasharray:none;display:inline"
+ inkscape:connector-curvature="0" />
+ <g
+ id="flowRoot4822"
+ style="font-size:40px;font-style:normal;font-weight:normal;line-height:125%;letter-spacing:0px;word-spacing:0px;fill:#000000;fill-opacity:1;stroke:none;font-family:sans-serif"
+ transform="translate(2.4859224,821.53368)">
+ <path
+ inkscape:connector-curvature="0"
+ id="path6077"
+ style="font-size:90.00000763px;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-family:Franklin Gothic;-inkscape-font-specification:Franklin Gothic"
+ d="m 123.24902,138.67423 8.9209,0 0,11.16211 -8.9209,0 0,-11.16211 z m 8.65723,-6.45996 -8.39355,0 0,-6.76758 q 0,-4.43848 1.23047,-7.29492 1.23046,-2.85645 5.18554,-6.63575 l 3.95508,-3.91113 q 2.50488,-2.3291 3.60352,-4.39453 1.14258,-2.06543 1.14258,-4.218753 0,-3.911133 -2.9004,-6.328125 -2.85644,-2.416992 -7.60254,-2.416992 -3.47167,0 -7.42675,1.538086 -3.91114,1.538086 -8.17383,4.482422 l 0,-8.26172 q 4.13086,-2.504883 8.34961,-3.735351 4.26269,-1.230469 8.78906,-1.230469 8.08594,0 12.96387,4.262695 4.92187,4.262696 4.92187,11.250001 0,3.339846 -1.58203,6.372076 -1.58203,2.98828 -5.53711,6.76757 l -3.86718,3.7793 q -2.06543,2.06543 -2.94434,3.25195 -0.83496,1.14258 -1.18652,2.24122 -0.26368,0.92285 -0.39551,2.24121 -0.13184,1.31836 -0.13184,3.60351 l 0,5.40528 z" />
+ </g>
+ <rect
+ y="923.16681"
+ x="45.770191"
+ height="100.00001"
+ width="15.000001"
+ id="rect4834"
+ style="fill:#ff0000;fill-opacity:1;stroke:none" />
+ <rect
+ transform="matrix(-0.00595846,-0.99998225,0.99997419,-0.00718432,0,0)"
+ y="-2.488034"
+ x="-980.66632"
+ height="99.91748"
+ width="14.282415"
+ id="rect4834-6"
+ style="fill:#ff0000;fill-opacity:1;stroke:none" />
+ </g>
+ </g>
+</svg>
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/src/ldt/ldt/static/ldt/metadataplayer/img/quiz_off.svg Fri Oct 02 10:24:05 2015 +0200
@@ -0,0 +1,247 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<!-- Created with Inkscape (http://www.inkscape.org/) -->
+
+<svg
+ xmlns:dc="http://purl.org/dc/elements/1.1/"
+ xmlns:cc="http://creativecommons.org/ns#"
+ xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
+ xmlns:svg="http://www.w3.org/2000/svg"
+ xmlns="http://www.w3.org/2000/svg"
+ xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
+ xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
+ width="22"
+ height="22"
+ viewBox="0 0 22.000001 22.000001"
+ id="svg4208"
+ version="1.1"
+ inkscape:version="0.48.4 r9939"
+ sodipodi:docname="quizzOff.svg">
+ <defs
+ id="defs4210" />
+ <sodipodi:namedview
+ id="base"
+ pagecolor="#ffffff"
+ bordercolor="#666666"
+ borderopacity="1.0"
+ inkscape:pageopacity="0.0"
+ inkscape:pageshadow="2"
+ inkscape:zoom="20.48"
+ inkscape:cx="26.114676"
+ inkscape:cy="19.183621"
+ inkscape:document-units="px"
+ inkscape:current-layer="layer1"
+ showgrid="false"
+ inkscape:window-width="1855"
+ inkscape:window-height="1056"
+ inkscape:window-x="65"
+ inkscape:window-y="24"
+ inkscape:window-maximized="1" />
+ <metadata
+ id="metadata4213">
+ <rdf:RDF>
+ <cc:Work
+ rdf:about="">
+ <dc:format>image/svg+xml</dc:format>
+ <dc:type
+ rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
+ <dc:title />
+ </cc:Work>
+ </rdf:RDF>
+ </metadata>
+ <g
+ inkscape:label="Calque 1"
+ inkscape:groupmode="layer"
+ id="layer1"
+ transform="translate(0,-1030.3622)">
+ <g
+ id="g3090"
+ transform="matrix(0.13943692,0,0,0.1456598,-4.0481427,902.11583)">
+ <path
+ inkscape:connector-curvature="0"
+ id="path4152"
+ d="m 88.762577,966.09408 a 64.442296,17.911566 52.208592 0 0 -53.76267,-40.24111 64.442296,17.911566 52.208592 0 0 25.08146,61.71245 64.442296,17.911566 52.208592 0 0 53.763283,40.24068 64.442296,17.911566 52.208592 0 0 -25.082073,-61.71202 z"
+ style="fill:#b3b3b3;fill-opacity:1;stroke:#000000;stroke-width:2.23528218;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;display:inline" />
+ <rect
+ transform="matrix(0.61175214,0.7910495,-0.80052922,0.59929372,0,0)"
+ y="517.45343"
+ x="875.27667"
+ height="20.941669"
+ width="15.681897"
+ id="rect4311"
+ style="fill:#b3b3b3;fill-opacity:1;stroke:none;display:inline" />
+ <rect
+ transform="matrix(0.61175214,0.7910495,-0.80052922,0.59929372,0,0)"
+ y="519.57574"
+ x="762.16467"
+ height="19.048025"
+ width="13.667582"
+ id="rect4309"
+ style="fill:#b3b3b3;fill-opacity:1;stroke:none;display:inline" />
+ <rect
+ transform="matrix(0.61175214,0.7910495,-0.80052922,0.59929372,0,0)"
+ y="518.66687"
+ x="889.6543"
+ height="0.94452941"
+ width="1.1967648"
+ id="rect4313"
+ style="fill:#b3b3b3;fill-opacity:1;stroke:none;display:inline" />
+ <path
+ sodipodi:nodetypes="ccc"
+ inkscape:connector-curvature="0"
+ id="path4156-3"
+ d="m 113.50338,1028.0563 9.89486,-7.4107 8.37707,-6.2729"
+ style="fill:none;stroke:#000000;stroke-width:2.23528218;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;display:inline" />
+ <ellipse
+ sodipodi:ry="18.476786"
+ sodipodi:rx="64.438011"
+ sodipodi:cy="516.2522"
+ sodipodi:cx="826.67413"
+ d="m 891.11214,516.2522 c 0,10.20444 -28.84988,18.47678 -64.43801,18.47678 -35.58813,0 -64.43801,-8.27234 -64.43801,-18.47678 0,-10.20445 28.84988,-18.47679 64.43801,-18.47679 35.58813,0 64.43801,8.27234 64.43801,18.47679 z"
+ transform="matrix(0.61175214,0.7910495,-0.80052922,0.59929372,0,0)"
+ ry="18.476786"
+ rx="64.438011"
+ cy="516.2522"
+ cx="826.67413"
+ id="path4150"
+ style="fill:#666666;stroke:#000000;stroke-width:2.23541927;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;display:inline" />
+ <path
+ sodipodi:nodetypes="ccc"
+ inkscape:connector-curvature="0"
+ id="path4156"
+ d="m 35.104607,925.77201 9.7327,-7.28939 8.23979,-6.17012"
+ style="fill:none;stroke:#000000;stroke-width:2.23528218;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;display:inline" />
+ <ellipse
+ sodipodi:ry="8.1607332"
+ sodipodi:rx="36.851326"
+ sodipodi:cy="517.20477"
+ sodipodi:cx="827.2381"
+ d="m 864.08942,517.20477 c 0,4.50705 -16.4989,8.16074 -36.85132,8.16074 -20.35243,0 -36.85133,-3.65369 -36.85133,-8.16074 0,-4.50705 16.4989,-8.16073 36.85133,-8.16073 20.35242,0 36.85132,3.65368 36.85132,8.16073 z"
+ transform="matrix(0.61175214,0.7910495,-0.80052922,0.59929372,0,0)"
+ ry="8.1607332"
+ rx="36.851326"
+ cy="517.20477"
+ cx="827.2381"
+ id="path4317"
+ style="fill:#e6e6e6;fill-opacity:1;stroke:#000000;stroke-width:1.30889452;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;display:inline" />
+ <rect
+ transform="matrix(0.98439737,0.17595972,-0.17595972,0.98439737,0,0)"
+ y="907.08124"
+ x="233.80257"
+ height="3.9420969"
+ width="24.027122"
+ id="rect5190"
+ style="fill:#e6e6e6;fill-opacity:1;stroke:none;display:inline" />
+ <rect
+ transform="matrix(0.98439737,0.17595972,-0.17595972,0.98439737,0,0)"
+ y="906.15369"
+ x="235.03923"
+ height="4.2899289"
+ width="24.027122"
+ id="rect5190-9"
+ style="fill:#e6e6e6;fill-opacity:1;stroke:none;display:inline" />
+ <rect
+ transform="matrix(0.98439737,0.17595972,-0.17595972,0.98439737,0,0)"
+ y="905.3421"
+ x="236.39369"
+ height="4.2899289"
+ width="24.027122"
+ id="rect5190-9-1"
+ style="fill:#e6e6e6;fill-opacity:1;stroke:none;display:inline" />
+ <rect
+ transform="matrix(0.98439737,0.17595972,-0.17595972,0.98439737,0,0)"
+ y="904.47247"
+ x="237.51262"
+ height="4.0000691"
+ width="2.1789296"
+ id="rect5190-9-4"
+ style="fill:#e6e6e6;fill-opacity:1;stroke:none;display:inline" />
+ <rect
+ transform="matrix(0.98439737,0.17595972,-0.17595972,0.98439737,0,0)"
+ y="903.92175"
+ x="237.95427"
+ height="4.0000691"
+ width="2.1789296"
+ id="rect5190-9-4-4"
+ style="fill:#e6e6e6;fill-opacity:1;stroke:none;display:inline" />
+ <rect
+ transform="matrix(0.98439737,0.17595972,-0.17595972,0.98439737,0,0)"
+ y="908.00873"
+ x="233.77309"
+ height="2.5362754"
+ width="18.712299"
+ id="rect5190-9-0"
+ style="fill:#e6e6e6;fill-opacity:1;stroke:none;display:inline" />
+ <path
+ sodipodi:nodetypes="ccc"
+ inkscape:connector-curvature="0"
+ id="path4156-4"
+ d="m 69.344687,935.29586 10.13887,-6.16215 8.58357,-5.21581"
+ style="fill:none;stroke:#000000;stroke-width:1.30881441;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;display:inline" />
+ <rect
+ transform="matrix(0.98439737,0.17595972,-0.17595972,0.98439737,0,0)"
+ y="954.03864"
+ x="285.80243"
+ height="3.3044052"
+ width="2.9445002"
+ id="rect5279"
+ style="fill:#e6e6e6;fill-opacity:1;stroke:none;display:inline" />
+ <rect
+ transform="matrix(0.98439737,0.17595972,-0.17595972,0.98439737,0,0)"
+ y="948.15442"
+ x="283.03458"
+ height="7.8841949"
+ width="6.0067806"
+ id="rect5279-2"
+ style="fill:#e6e6e6;fill-opacity:1;stroke:none;display:inline" />
+ <rect
+ transform="matrix(0.98439737,0.17595972,-0.17595972,0.98439737,0,0)"
+ y="951.83563"
+ x="286.62689"
+ height="2.3188813"
+ width="4.7700906"
+ id="rect5279-2-3"
+ style="fill:#e6e6e6;fill-opacity:1;stroke:none;display:inline" />
+ <rect
+ transform="matrix(0.98439737,0.17595972,-0.17595972,0.98439737,0,0)"
+ y="953.51678"
+ x="285.83188"
+ height="1.971049"
+ width="4.4167504"
+ id="rect5279-2-3-3"
+ style="fill:#e6e6e6;fill-opacity:1;stroke:none;display:inline" />
+ <path
+ sodipodi:nodetypes="ccc"
+ inkscape:connector-curvature="0"
+ id="path4156-4-5"
+ d="m 114.62982,993.43082 9.47784,-7.0986 8.02405,-6.00861"
+ style="fill:none;stroke:#000000;stroke-width:1.30881441;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;display:inline" />
+ <rect
+ transform="matrix(0.98439737,0.17595972,-0.17595972,0.98439737,0,0)"
+ y="909.45807"
+ x="241.51714"
+ height="4.2899289"
+ width="24.027122"
+ id="rect5190-9-3"
+ style="fill:#e6e6e6;fill-opacity:1;stroke:none;display:inline" />
+ <ellipse
+ sodipodi:ry="11.1082"
+ sodipodi:rx="36.846481"
+ sodipodi:cy="495.24258"
+ sodipodi:cx="824.92773"
+ d="m 861.77422,495.24258 c 0,6.13489 -16.49674,11.1082 -36.84649,11.1082 -20.34975,0 -36.84648,-4.97331 -36.84648,-11.1082 0,-6.13489 16.49673,-11.1082 36.84648,-11.1082 20.34975,0 36.84649,4.97331 36.84649,11.1082 z"
+ transform="matrix(0.61175214,0.7910495,-0.80052922,0.59929372,0,0)"
+ ry="11.1082"
+ rx="36.846481"
+ cy="495.24258"
+ cx="824.92773"
+ id="path4351"
+ style="fill:#800000;fill-opacity:1;stroke:#000000;stroke-width:0.924097;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;display:inline" />
+ <path
+ id="path4564"
+ d="m 76.182057,895.08255 c 28.049053,-21.23075 69.407013,-14.64926 92.435693,14.54291 23.02867,29.19218 19.04627,70.22994 -9.00275,91.46064 -27.96073,21.2524 -111.393663,-84.75115 -83.432943,-106.00355 z"
+ stroke-miterlimit="10"
+ style="fill:#b3b3b3;fill-opacity:1;stroke:#000000;stroke-width:4.48099518;stroke-miterlimit:10;stroke-dasharray:none;display:inline"
+ inkscape:connector-curvature="0" />
+ </g>
+ </g>
+</svg>
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/src/ldt/ldt/static/ldt/metadataplayer/img/quiz_on.svg Fri Oct 02 10:24:05 2015 +0200
@@ -0,0 +1,247 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<!-- Created with Inkscape (http://www.inkscape.org/) -->
+
+<svg
+ xmlns:dc="http://purl.org/dc/elements/1.1/"
+ xmlns:cc="http://creativecommons.org/ns#"
+ xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
+ xmlns:svg="http://www.w3.org/2000/svg"
+ xmlns="http://www.w3.org/2000/svg"
+ xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
+ xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
+ width="22"
+ height="22"
+ viewBox="0 0 22.000001 22.000002"
+ id="svg4208"
+ version="1.1"
+ inkscape:version="0.48.4 r9939"
+ sodipodi:docname="quizzOn.svg">
+ <defs
+ id="defs4210" />
+ <sodipodi:namedview
+ id="base"
+ pagecolor="#ffffff"
+ bordercolor="#666666"
+ borderopacity="1.0"
+ inkscape:pageopacity="0.0"
+ inkscape:pageshadow="2"
+ inkscape:zoom="14.481547"
+ inkscape:cx="20.213132"
+ inkscape:cy="13.840792"
+ inkscape:document-units="px"
+ inkscape:current-layer="layer1"
+ showgrid="false"
+ inkscape:window-width="1855"
+ inkscape:window-height="1056"
+ inkscape:window-x="65"
+ inkscape:window-y="24"
+ inkscape:window-maximized="1" />
+ <metadata
+ id="metadata4213">
+ <rdf:RDF>
+ <cc:Work
+ rdf:about="">
+ <dc:format>image/svg+xml</dc:format>
+ <dc:type
+ rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
+ <dc:title />
+ </cc:Work>
+ </rdf:RDF>
+ </metadata>
+ <g
+ inkscape:label="Calque 1"
+ inkscape:groupmode="layer"
+ id="layer1"
+ transform="translate(0,-1030.3622)">
+ <g
+ id="g3065"
+ transform="matrix(0.13987874,0,0,0.14224716,-4.400635,906.61726)">
+ <path
+ inkscape:connector-curvature="0"
+ id="path4152"
+ d="m 91.229014,959.93306 a 64.4423,17.911567 52.208592 0 0 -53.76267,-40.2411 64.4423,17.911567 52.208592 0 0 25.08146,61.7124 64.4423,17.911567 52.208592 0 0 53.763276,40.24074 64.4423,17.911567 52.208592 0 0 -25.082066,-61.71204 z"
+ style="fill:#b3b3b3;fill-opacity:1;stroke:#000000;stroke-width:2.23528218;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;display:inline" />
+ <rect
+ transform="matrix(0.61175214,0.7910495,-0.80052922,0.59929372,0,0)"
+ y="511.73264"
+ x="871.82239"
+ height="20.941671"
+ width="15.681898"
+ id="rect4311"
+ style="fill:#b3b3b3;fill-opacity:1;stroke:none;display:inline" />
+ <rect
+ transform="matrix(0.61175214,0.7910495,-0.80052922,0.59929372,0,0)"
+ y="513.85492"
+ x="758.71033"
+ height="19.048027"
+ width="13.667583"
+ id="rect4309"
+ style="fill:#b3b3b3;fill-opacity:1;stroke:none;display:inline" />
+ <rect
+ transform="matrix(0.61175214,0.7910495,-0.80052922,0.59929372,0,0)"
+ y="512.94604"
+ x="886.19995"
+ height="0.94452947"
+ width="1.1967649"
+ id="rect4313"
+ style="fill:#b3b3b3;fill-opacity:1;stroke:none;display:inline" />
+ <path
+ sodipodi:nodetypes="ccc"
+ inkscape:connector-curvature="0"
+ id="path4156-3"
+ d="m 115.96981,1021.8953 9.89486,-7.4107 8.37708,-6.2729"
+ style="fill:none;stroke:#000000;stroke-width:2.23528218;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;display:inline" />
+ <ellipse
+ sodipodi:ry="18.476788"
+ sodipodi:rx="64.438011"
+ sodipodi:cy="510.5314"
+ sodipodi:cx="823.21979"
+ d="m 887.6578,510.5314 c 0,10.20445 -28.84988,18.47679 -64.43801,18.47679 -35.58813,0 -64.43801,-8.27234 -64.43801,-18.47679 0,-10.20445 28.84988,-18.47678 64.43801,-18.47678 35.58813,0 64.43801,8.27233 64.43801,18.47678 z"
+ transform="matrix(0.61175214,0.7910495,-0.80052922,0.59929372,0,0)"
+ ry="18.476788"
+ rx="64.438011"
+ cy="510.5314"
+ cx="823.21979"
+ id="path4150"
+ style="fill:#666666;stroke:#000000;stroke-width:2.23541927;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;display:inline" />
+ <path
+ sodipodi:nodetypes="ccc"
+ inkscape:connector-curvature="0"
+ id="path4156"
+ d="m 37.571044,919.61096 9.7327,-7.2894 8.23979,-6.1701"
+ style="fill:none;stroke:#000000;stroke-width:2.23528218;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;display:inline" />
+ <ellipse
+ sodipodi:ry="8.1607332"
+ sodipodi:rx="36.85133"
+ sodipodi:cy="511.48398"
+ sodipodi:cx="823.78375"
+ d="m 860.63508,511.48398 c 0,4.50705 -16.4989,8.16073 -36.85133,8.16073 -20.35243,0 -36.85133,-3.65368 -36.85133,-8.16073 0,-4.50705 16.4989,-8.16073 36.85133,-8.16073 20.35243,0 36.85133,3.65368 36.85133,8.16073 z"
+ transform="matrix(0.61175214,0.7910495,-0.80052922,0.59929372,0,0)"
+ ry="8.1607332"
+ rx="36.85133"
+ cy="511.48398"
+ cx="823.78375"
+ id="path4317"
+ style="fill:#e6e6e6;fill-opacity:1;stroke:#000000;stroke-width:1.30889452;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;display:inline" />
+ <rect
+ transform="matrix(0.98439737,0.17595972,-0.17595972,0.98439737,0,0)"
+ y="900.58234"
+ x="235.14644"
+ height="3.9420972"
+ width="24.027124"
+ id="rect5190"
+ style="fill:#e6e6e6;fill-opacity:1;stroke:none;display:inline" />
+ <rect
+ transform="matrix(0.98439737,0.17595972,-0.17595972,0.98439737,0,0)"
+ y="899.65472"
+ x="236.3831"
+ height="4.2899294"
+ width="24.027124"
+ id="rect5190-9"
+ style="fill:#e6e6e6;fill-opacity:1;stroke:none;display:inline" />
+ <rect
+ transform="matrix(0.98439737,0.17595972,-0.17595972,0.98439737,0,0)"
+ y="898.8432"
+ x="237.73756"
+ height="4.2899294"
+ width="24.027124"
+ id="rect5190-9-1"
+ style="fill:#e6e6e6;fill-opacity:1;stroke:none;display:inline" />
+ <rect
+ transform="matrix(0.98439737,0.17595972,-0.17595972,0.98439737,0,0)"
+ y="897.97357"
+ x="238.85649"
+ height="4.0000696"
+ width="2.1789298"
+ id="rect5190-9-4"
+ style="fill:#e6e6e6;fill-opacity:1;stroke:none;display:inline" />
+ <rect
+ transform="matrix(0.98439737,0.17595972,-0.17595972,0.98439737,0,0)"
+ y="897.42279"
+ x="239.29814"
+ height="4.0000696"
+ width="2.1789298"
+ id="rect5190-9-4-4"
+ style="fill:#e6e6e6;fill-opacity:1;stroke:none;display:inline" />
+ <rect
+ transform="matrix(0.98439737,0.17595972,-0.17595972,0.98439737,0,0)"
+ y="901.50983"
+ x="235.11696"
+ height="2.5362756"
+ width="18.712301"
+ id="rect5190-9-0"
+ style="fill:#e6e6e6;fill-opacity:1;stroke:none;display:inline" />
+ <path
+ sodipodi:nodetypes="ccc"
+ inkscape:connector-curvature="0"
+ id="path4156-4"
+ d="m 71.811124,929.13486 10.13887,-6.1622 8.58357,-5.2158"
+ style="fill:none;stroke:#000000;stroke-width:1.30881441;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;display:inline" />
+ <rect
+ transform="matrix(0.98439737,0.17595972,-0.17595972,0.98439737,0,0)"
+ y="947.53973"
+ x="287.14633"
+ height="3.3044055"
+ width="2.9445004"
+ id="rect5279"
+ style="fill:#e6e6e6;fill-opacity:1;stroke:none;display:inline" />
+ <rect
+ transform="matrix(0.98439737,0.17595972,-0.17595972,0.98439737,0,0)"
+ y="941.65546"
+ x="284.37848"
+ height="7.8841953"
+ width="6.0067811"
+ id="rect5279-2"
+ style="fill:#e6e6e6;fill-opacity:1;stroke:none;display:inline" />
+ <rect
+ transform="matrix(0.98439737,0.17595972,-0.17595972,0.98439737,0,0)"
+ y="945.33673"
+ x="287.97079"
+ height="2.3188815"
+ width="4.7700911"
+ id="rect5279-2-3"
+ style="fill:#e6e6e6;fill-opacity:1;stroke:none;display:inline" />
+ <rect
+ transform="matrix(0.98439737,0.17595972,-0.17595972,0.98439737,0,0)"
+ y="947.01788"
+ x="287.17575"
+ height="1.9710491"
+ width="4.4167509"
+ id="rect5279-2-3-3"
+ style="fill:#e6e6e6;fill-opacity:1;stroke:none;display:inline" />
+ <path
+ sodipodi:nodetypes="ccc"
+ inkscape:connector-curvature="0"
+ id="path4156-4-5"
+ d="m 117.09625,987.26976 9.47784,-7.0986 8.02406,-6.0086"
+ style="fill:none;stroke:#000000;stroke-width:1.30881441;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;display:inline" />
+ <rect
+ transform="matrix(0.98439737,0.17595972,-0.17595972,0.98439737,0,0)"
+ y="902.95917"
+ x="242.86101"
+ height="4.2899294"
+ width="24.027124"
+ id="rect5190-9-3"
+ style="fill:#e6e6e6;fill-opacity:1;stroke:none;display:inline" />
+ <ellipse
+ sodipodi:ry="11.108201"
+ sodipodi:rx="36.846485"
+ sodipodi:cy="489.52179"
+ sodipodi:cx="821.47339"
+ d="m 858.31987,489.52179 c 0,6.13489 -16.49673,11.1082 -36.84648,11.1082 -20.34975,0 -36.84649,-4.97331 -36.84649,-11.1082 0,-6.13489 16.49674,-11.1082 36.84649,-11.1082 20.34975,0 36.84648,4.97331 36.84648,11.1082 z"
+ transform="matrix(0.61175214,0.7910495,-0.80052922,0.59929372,0,0)"
+ ry="11.108201"
+ rx="36.846485"
+ cy="489.52179"
+ cx="821.47339"
+ id="path4351"
+ style="fill:#800000;fill-opacity:1;stroke:#000000;stroke-width:0.924097;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;display:inline" />
+ <path
+ id="path4564"
+ d="m 78.648494,888.92156 c 28.049046,-21.2308 69.407016,-14.6493 92.435696,14.5429 23.02867,29.1922 19.04627,70.2299 -9.00275,91.4606 -27.96073,21.25254 -111.393666,-84.7511 -83.432946,-106.0035 z"
+ stroke-miterlimit="10"
+ style="fill:#aa0000;fill-opacity:1;stroke:#000000;stroke-width:4.48099518;stroke-miterlimit:10;stroke-dasharray:none;display:inline"
+ inkscape:connector-curvature="0" />
+ </g>
+ </g>
+</svg>
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/src/ldt/ldt/static/ldt/metadataplayer/img/right_arrow.svg Fri Oct 02 10:24:05 2015 +0200
@@ -0,0 +1,9 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<svg xmlns="http://www.w3.org/2000/svg" width="32" height="32" id="arrow">
+ <path style="fill:none;stroke:#fff;stroke-width:6;stroke-linecap:round;stroke-linejoin:bevel;stroke-miterlimit:4;"
+ d="M1,1 l30,15 l-30,15">
+ </path>
+ <path style="fill:none;stroke:#000;stroke-width:4;stroke-linecap:round;stroke-linejoin:bevel;stroke-miterlimit:4;"
+ d="M1,1 l30,15 l-30,15">
+ </path>
+</svg>
Binary file src/ldt/ldt/static/ldt/metadataplayer/img/time_edit.png has changed
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/src/ldt/ldt/static/ldt/metadataplayer/img/twitter.svg Fri Oct 02 10:24:05 2015 +0200
@@ -0,0 +1,51 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<!-- Generator: Adobe Illustrator 16.0.4, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
+
+<svg
+ xmlns:dc="http://purl.org/dc/elements/1.1/"
+ xmlns:cc="http://creativecommons.org/ns#"
+ xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
+ xmlns:svg="http://www.w3.org/2000/svg"
+ xmlns="http://www.w3.org/2000/svg"
+ xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
+ xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
+ version="1.1"
+ id="twitter_logo"
+ x="0px"
+ y="0px"
+ width="42px"
+ height="42px"
+ viewBox="0 0 42 42"
+ xml:space="preserve"
+ inkscape:version="0.48.5 r10040"
+ sodipodi:docname="twitter.svg"><metadata
+ id="metadata11"><rdf:RDF><cc:Work
+ rdf:about=""><dc:format>image/svg+xml</dc:format><dc:type
+ rdf:resource="http://purl.org/dc/dcmitype/StillImage" /></cc:Work></rdf:RDF></metadata><defs
+ id="defs9" /><sodipodi:namedview
+ pagecolor="#ffffff"
+ bordercolor="#666666"
+ borderopacity="1"
+ objecttolerance="10"
+ gridtolerance="10"
+ guidetolerance="10"
+ inkscape:pageopacity="0"
+ inkscape:pageshadow="2"
+ inkscape:window-width="1680"
+ inkscape:window-height="1015"
+ id="namedview7"
+ showgrid="false"
+ inkscape:zoom="5.6190476"
+ inkscape:cx="-11.478814"
+ inkscape:cy="21"
+ inkscape:window-x="0"
+ inkscape:window-y="26"
+ inkscape:window-maximized="0"
+ inkscape:current-layer="g3" /><g
+ fill="#ddd"
+ stroke="black"
+ transform="matrix(.57079,0,0,-.57079,-42.80937,432.2052)"
+ id="g3"><path
+ d="M146.83,743.433c-0.469-0.979-1.341-2.217-2.618-3.711c-1.276-1.497-2.85-2.811-4.725-3.947 c0.051-0.411,0.091-0.799,0.116-1.158c0.202-5.559-1.143-11.324-3.008-16.127c-3.617-8.931-9.157-16.12-17.071-21 c-8.252-4.688-17.862-5.684-26.717-4.833c-5.879,0.667-11.673,2.568-16.055,6.149c8.014-0.948,15.494,1.75,21.407,6.11 c-6.57-0.164-11.34,4.541-13.595,9.98c1.016-0.265,2.079-0.234,3.047-0.157c1.193,0.113,2.325,0.222,3.437,0.465 c-4.188,1.338-7.853,3.797-9.766,7.502c-1.122,2.349-1.629,4.583-1.639,7.116c1.961-1.023,4.322-2.021,6.484-1.933 c-3.264,2.737-5.882,6.235-6.368,10.248c-0.308,3.345,0.539,6.4,1.759,9.242c4.881-5.311,10.359-9.685,16.678-12.375 c4.322-1.752,8.631-2.691,13.087-2.707c-0.515,3.94-0.115,7.749,1.757,10.982c2.204,3.477,5.42,5.492,9.023,6.498 c5.16,1.311,10.192-0.542,13.36-4.099c3.417,0.364,6.691,1.867,9.297,3.401c-1.107-3.319-3.263-6.619-6.407-8.199 C141.308,741.429,144.163,742.307,146.83,743.433z"
+ id="path5"
+ style="fill:#55acee;fill-opacity:1" /></g></svg>
\ No newline at end of file
Binary file src/ldt/ldt/static/ldt/metadataplayer/img/valid_sprites.png has changed
Binary file src/ldt/ldt/static/ldt/swf/ZeroClipboard.swf has changed