From c6c8aab6699c958b119705ae38404697240c33f0 Mon Sep 17 00:00:00 2001 From: josdejong Date: Mon, 2 Sep 2013 08:51:59 +0200 Subject: [PATCH 01/18] Fixed missing space between className classes. (See #7) --- HISTORY.md | 5 ++++ src/timeline/Range.js | 1 + src/timeline/Timeline.js | 10 +++++++ src/timeline/component/item/ItemRange.js | 2 +- vis.js | 35 +++++++++++++++++++++--- vis.min.js | 10 +++---- 6 files changed, 53 insertions(+), 10 deletions(-) diff --git a/HISTORY.md b/HISTORY.md index d41120ff..0c7ab523 100644 --- a/HISTORY.md +++ b/HISTORY.md @@ -2,6 +2,11 @@ vis.js history http://visjs.org +## (not yet released), version 0.1.1 + +- Fixed field `className` not working for items. + + ## 2013-06-20, version 0.1.0 - Added support for DataSet to Graph. Graph now uses an id based set of nodes diff --git a/src/timeline/Range.js b/src/timeline/Range.js index ae9b43af..2215ea36 100644 --- a/src/timeline/Range.js +++ b/src/timeline/Range.js @@ -11,6 +11,7 @@ function Range(options) { this.start = 0; // Number this.end = 0; // Number + // this.options = options || {}; // TODO: fix range options this.options = { min: null, max: null, diff --git a/src/timeline/Timeline.js b/src/timeline/Timeline.js index 2d34e5b7..b7e07ea3 100644 --- a/src/timeline/Timeline.js +++ b/src/timeline/Timeline.js @@ -76,6 +76,14 @@ function Timeline (container, items, options) { start: now.clone().add('days', -3).valueOf(), end: now.clone().add('days', 4).valueOf() }); + /* TODO: fix range options + var rangeOptions = Object.create(this.options); + this.range = new Range(rangeOptions); + this.range.setRange( + now.clone().add('days', -3).valueOf(), + now.clone().add('days', 4).valueOf() + ); + */ // TODO: reckon with options moveable and zoomable this.range.subscribe(this.rootPanel, 'move', 'horizontal'); this.range.subscribe(this.rootPanel, 'zoom', 'horizontal'); @@ -122,6 +130,8 @@ Timeline.prototype.setOptions = function (options) { util.extend(this.options, options); } + // TODO: apply range min,max + this.controller.reflow(); this.controller.repaint(); }; diff --git a/src/timeline/component/item/ItemRange.js b/src/timeline/component/item/ItemRange.js index b8ede542..c42ffc03 100644 --- a/src/timeline/component/item/ItemRange.js +++ b/src/timeline/component/item/ItemRange.js @@ -86,7 +86,7 @@ ItemRange.prototype.repaint = function repaint() { } // update class - var className = this.data.className ? ('' + this.data.className) : ''; + var className = this.data.className ? (' ' + this.data.className) : ''; if (this.className != className) { this.className = className; dom.box.className = 'item range' + className; diff --git a/vis.js b/vis.js index 8e3c8f0c..c7bd01fd 100644 --- a/vis.js +++ b/vis.js @@ -5,7 +5,7 @@ * A dynamic, browser-based visualization library. * * @version 0.2.0-SNAPSHOT - * @date 2013-06-20 + * @date 2013-09-02 * * @license * Copyright (C) 2011-2013 Almende B.V, http://almende.com @@ -3002,6 +3002,7 @@ function Range(options) { this.start = 0; // Number this.end = 0; // Number + // this.options = options || {}; // TODO this.options = { min: null, max: null, @@ -3514,6 +3515,22 @@ Range.prototype.move = function(moveFactor) { this.end = newEnd; }; +/** + * Move the range to a new center point + * @param {Number} moveTo New center point of the range + */ +Range.prototype.moveTo = function(moveTo) { + var center = (this.start + this.end) / 2; + + var diff = center - moveTo; + + // calculate new start and end + var newStart = this.start - diff; + var newEnd = this.end - diff; + + this.setRange(newStart, newEnd); +} + /** * @constructor Controller * @@ -4875,9 +4892,9 @@ ItemSet.prototype.repaint = function repaint() { itemsData = this.itemsData, items = this.items, dataOptions = { - fields: [(itemsData && itemsData.fieldId || 'id'), 'start', 'end', 'content', 'type'] + // TODO: cleanup + //fields: [(itemsData && itemsData.fieldId || 'id'), 'start', 'end', 'content', 'type'] }; - // TODO: copy options from the itemset itself? // show/hide added/changed/removed items Object.keys(queue).forEach(function (id) { @@ -5942,7 +5959,7 @@ ItemRange.prototype.repaint = function repaint() { } // update class - var className = this.data.className ? ('' + this.data.className) : ''; + var className = this.data.className ? (' ' + this.data.className) : ''; if (this.className != className) { this.className = className; dom.box.className = 'item range' + className; @@ -6804,6 +6821,14 @@ function Timeline (container, items, options) { start: now.clone().add('days', -3).valueOf(), end: now.clone().add('days', 4).valueOf() }); + /* TODO: fix range options + var rangeOptions = Object.create(this.options); + this.range = new Range(rangeOptions); + this.range.setRange( + now.clone().add('days', -3).valueOf(), + now.clone().add('days', 4).valueOf() + ); + */ // TODO: reckon with options moveable and zoomable this.range.subscribe(this.rootPanel, 'move', 'horizontal'); this.range.subscribe(this.rootPanel, 'zoom', 'horizontal'); @@ -6850,6 +6875,8 @@ Timeline.prototype.setOptions = function (options) { util.extend(this.options, options); } + // TODO: apply range min,max + this.controller.reflow(); this.controller.repaint(); }; diff --git a/vis.min.js b/vis.min.js index 28292120..a4269367 100644 --- a/vis.min.js +++ b/vis.min.js @@ -5,7 +5,7 @@ * A dynamic, browser-based visualization library. * * @version 0.2.0-SNAPSHOT - * @date 2013-06-20 + * @date 2013-09-02 * * @license * Copyright (C) 2011-2013 Almende B.V, http://almende.com @@ -23,7 +23,7 @@ * the License. */ (function(t){if("function"==typeof bootstrap)bootstrap("vis",t);else if("object"==typeof exports)module.exports=t();else if("function"==typeof define&&define.amd)define(t);else if("undefined"!=typeof ses){if(!ses.ok())return;ses.makeVis=t}else"undefined"!=typeof window?window.vis=t():global.vis=t()})(function(){var t;return function(t,e,i){function s(i,o){if(!e[i]){if(!t[i]){var r="function"==typeof require&&require;if(!o&&r)return r(i,!0);if(n)return n(i,!0);throw Error("Cannot find module '"+i+"'")}var a=e[i]={exports:{}};t[i][0].call(a.exports,function(e){var n=t[i][1][e];return s(n?n:e)},a,a.exports)}return e[i].exports}for(var n="function"==typeof require&&require,o=0;i.length>o;o++)s(i[o]);return s}({1:[function(e,i,s){(function(){function n(){this.subscriptions=[]}function o(t){if(this.id=D.randomUUID(),this.options=t||{},this.data={},this.fieldId=this.options.fieldId||"id",this.convert={},this.options.convert)for(var e in this.options.convert)if(this.options.convert.hasOwnProperty(e)){var i=this.options.convert[e];this.convert[e]="Date"==i||"ISODate"==i||"ASPDate"==i?"Date":i}this.subscribers={},this.internalIds={}}function r(t,e){this.id=D.randomUUID(),this.data=null,this.ids={},this.options=e||{},this.fieldId="id",this.subscribers={};var i=this;this.listener=function(){i._onEvent.apply(i,arguments)},this.setData(t)}function a(t,e){this.parent=t,this.options=e||{},this.defaultOptions={order:function(t,e){if(t instanceof y){if(e instanceof y){var i=t.data.end-t.data.start,s=e.data.end-e.data.start;return i-s||t.data.start-e.data.start}return-1}return e instanceof y?1:t.data.start-e.data.start},margin:{item:10}},this.ordered=[]}function h(t){this.id=D.randomUUID(),this.start=0,this.end=0,this.options={min:null,max:null,zoomMin:null,zoomMax:null},this.listeners=[],this.setOptions(t)}function d(){this.id=D.randomUUID(),this.components={},this.repaintTimer=void 0,this.reflowTimer=void 0}function l(){this.id=null,this.parent=null,this.depends=null,this.controller=null,this.options=null,this.frame=null,this.top=0,this.left=0,this.width=0,this.height=0}function p(t,e,i){this.id=D.randomUUID(),this.parent=t,this.depends=e,this.options=i||{}}function c(t,e){this.id=D.randomUUID(),this.container=t,this.options=e||{},this.defaultOptions={autoResize:!0},this.listeners={}}function u(t,e,i){this.id=D.randomUUID(),this.parent=t,this.depends=e,this.dom={majorLines:[],majorTexts:[],minorLines:[],minorTexts:[],redundant:{majorLines:[],majorTexts:[],minorLines:[],minorTexts:[]}},this.props={range:{start:0,end:0,minimumStep:0},lineTop:0},this.options=i||{},this.defaultOptions={orientation:"bottom",showMinorLabels:!0,showMajorLabels:!0},this.conversion=null,this.range=null}function f(t,e,i){this.id=D.randomUUID(),this.parent=t,this.depends=e,this.options=i||{},this.defaultOptions={type:"box",align:"center",orientation:"bottom",margin:{axis:20,item:10},padding:5},this.dom={};var s=this;this.itemsData=null,this.range=null,this.listeners={add:function(t,e,i){i!=s.id&&s._onAdd(e.items)},update:function(t,e,i){i!=s.id&&s._onUpdate(e.items)},remove:function(t,e,i){i!=s.id&&s._onRemove(e.items)}},this.items={},this.queue={},this.stack=new a(this,Object.create(this.options)),this.conversion=null}function m(t,e,i,s){this.parent=t,this.data=e,this.dom=null,this.options=i||{},this.defaultOptions=s||{},this.selected=!1,this.visible=!1,this.top=0,this.left=0,this.width=0,this.height=0}function g(t,e,i,s){this.props={dot:{left:0,top:0,width:0,height:0},line:{top:0,left:0,width:0,height:0}},m.call(this,t,e,i,s)}function v(t,e,i,s){this.props={dot:{top:0,width:0,height:0},content:{height:0,marginLeft:0}},m.call(this,t,e,i,s)}function y(t,e,i,s){this.props={content:{left:0,width:0}},m.call(this,t,e,i,s)}function b(t,e,i){this.id=D.randomUUID(),this.parent=t,this.groupId=e,this.itemsData=null,this.itemset=null,this.options=i||{},this.options.top=0,this.props={label:{width:0,height:0}},this.top=0,this.left=0,this.width=0,this.height=0}function w(t,e,i){this.id=D.randomUUID(),this.parent=t,this.depends=e,this.options=i||{},this.range=null,this.itemsData=null,this.groupsData=null,this.groups={},this.dom={},this.props={labels:{width:0}},this.queue={};var s=this;this.listeners={add:function(t,e){s._onAdd(e.items)},update:function(t,e){s._onUpdate(e.items)},remove:function(t,e){s._onRemove(e.items)}}}function _(t,e,i){var s=this;if(this.options=D.extend({orientation:"bottom",min:null,max:null,zoomMin:10,zoomMax:31536e10,showMinorLabels:!0,showMajorLabels:!0,autoResize:!1},i),this.controller=new d,!t)throw Error("No container element provided");var n=Object.create(this.options);n.height=function(){return s.options.height?s.options.height:s.timeaxis.height+s.content.height},this.rootPanel=new c(t,n),this.controller.add(this.rootPanel);var o=Object.create(this.options);o.left=function(){return s.labelPanel.width},o.width=function(){return s.rootPanel.width-s.labelPanel.width},o.top=null,o.height=null,this.itemPanel=new p(this.rootPanel,[],o),this.controller.add(this.itemPanel);var r=Object.create(this.options);r.top=null,r.left=null,r.height=null,r.width=function(){return s.content&&"function"==typeof s.content.getLabelsWidth?s.content.getLabelsWidth():0},this.labelPanel=new p(this.rootPanel,[],r),this.controller.add(this.labelPanel);var a=E().hours(0).minutes(0).seconds(0).milliseconds(0);this.range=new h({start:a.clone().add("days",-3).valueOf(),end:a.clone().add("days",4).valueOf()}),this.range.subscribe(this.rootPanel,"move","horizontal"),this.range.subscribe(this.rootPanel,"zoom","horizontal"),this.range.on("rangechange",function(){var t=!0;s.controller.requestReflow(t)}),this.range.on("rangechanged",function(){var t=!0;s.controller.requestReflow(t)});var l=Object.create(n);l.range=this.range,l.left=null,l.top=null,l.width="100%",l.height=null,this.timeaxis=new u(this.itemPanel,[],l),this.timeaxis.setRange(this.range),this.controller.add(this.timeaxis),this.setGroups(null),this.itemsData=null,this.groupsData=null,e&&this.setItems(e)}function x(t,e,i,s){this.selected=!1,this.edges=[],this.group=s.nodes.group,this.fontSize=s.nodes.fontSize,this.fontFace=s.nodes.fontFace,this.fontColor=s.nodes.fontColor,this.color=s.nodes.color,this.id=void 0,this.shape=s.nodes.shape,this.image=s.nodes.image,this.x=0,this.y=0,this.xFixed=!1,this.yFixed=!1,this.radius=s.nodes.radius,this.radiusFixed=!1,this.radiusMin=s.nodes.radiusMin,this.radiusMax=s.nodes.radiusMax,this.imagelist=e,this.grouplist=i,this.setProperties(t,s),this.mass=50,this.fx=0,this.fy=0,this.vx=0,this.vy=0,this.minForce=s.minForce,this.damping=.9}function T(t,e,i){if(!e)throw"No graph provided";this.graph=e,this.widthMin=i.edges.widthMin,this.widthMax=i.edges.widthMax,this.id=void 0,this.fromId=void 0,this.toId=void 0,this.style=i.edges.style,this.title=void 0,this.width=i.edges.width,this.value=void 0,this.length=i.edges.length,this.from=null,this.to=null,this.connected=!1,this.dash=D.extend({},i.edges.dash),this.stiffness=void 0,this.color=i.edges.color,this.widthFixed=!1,this.lengthFixed=!1,this.setProperties(t,i)}function S(t,e,i,s){this.container=t?t:document.body,this.x=0,this.y=0,this.padding=5,void 0!==e&&void 0!==i&&this.setPosition(e,i),void 0!==s&&this.setText(s),this.frame=document.createElement("div");var n=this.frame.style;n.position="absolute",n.visibility="hidden",n.border="1px solid #666",n.color="black",n.padding=this.padding+"px",n.backgroundColor="#FFFFC6",n.borderRadius="3px",n.MozBorderRadius="3px",n.WebkitBorderRadius="3px",n.boxShadow="3px 3px 10px rgba(128, 128, 128, 0.5)",n.whiteSpace="nowrap",this.container.appendChild(this.frame)}function M(t,e,i){this.containerElement=t,this.width="100%",this.height="100%",this.refreshRate=50,this.stabilize=!0,this.selectable=!0,this.constants={nodes:{radiusMin:5,radiusMax:20,radius:5,distance:100,shape:"ellipse",image:void 0,widthMin:16,widthMax:64,fontColor:"black",fontSize:14,fontFace:"arial",color:{border:"#2B7CE9",background:"#97C2FC",highlight:{border:"#2B7CE9",background:"#D2E5FF"}},borderColor:"#2B7CE9",backgroundColor:"#97C2FC",highlightColor:"#D2E5FF",group:void 0},edges:{widthMin:1,widthMax:15,width:1,style:"line",color:"#343434",fontColor:"#343434",fontSize:14,fontFace:"arial",length:100,dash:{length:10,gap:5,altLength:void 0}},minForce:.05,minVelocity:.02,maxIterations:1e3};var s=this;this.nodes={},this.edges={},this.nodesData=null,this.edgesData=null;var n=this;this.nodesListeners={add:function(t,e){n._addNodes(e.items),n.start()},update:function(t,e){n._updateNodes(e.items),n.start()},remove:function(t,e){n._removeNodes(e.items),n.start()}},this.edgesListeners={add:function(t,e){n._addEdges(e.items),n.start()},update:function(t,e){n._updateEdges(e.items),n.start()},remove:function(t,e){n._removeEdges(e.items),n.start()}},this.groups=new Groups,this.images=new Images,this.images.setOnloadCallback(function(){s._redraw()}),this.moving=!1,this.selection=[],this.timer=void 0,this._create(),this.setOptions(i),this.setData(e)}var E=e("moment"),D={};D.isNumber=function(t){return t instanceof Number||"number"==typeof t},D.isString=function(t){return t instanceof String||"string"==typeof t},D.isDate=function(t){if(t instanceof Date)return!0;if(D.isString(t)){var e=C.exec(t);if(e)return!0;if(!isNaN(Date.parse(t)))return!0}return!1},D.isDataTable=function(t){return"undefined"!=typeof google&&google.visualization&&google.visualization.DataTable&&t instanceof google.visualization.DataTable},D.randomUUID=function(){var t=function(){return Math.floor(65536*Math.random()).toString(16)};return t()+t()+"-"+t()+"-"+t()+"-"+t()+"-"+t()+t()+t()},D.extend=function(t){for(var e=1,i=arguments.length;i>e;e++){var s=arguments[e];for(var n in s)s.hasOwnProperty(n)&&void 0!==s[n]&&(t[n]=s[n])}return t},D.convert=function(t,e){var i;if(void 0===t)return void 0;if(null===t)return null;if(!e)return t;if("string"!=typeof e&&!(e instanceof String))throw Error("Type must be a string");switch(e){case"boolean":case"Boolean":return Boolean(t);case"number":case"Number":return Number(t.valueOf());case"string":case"String":return t+"";case"Date":if(D.isNumber(t))return new Date(t);if(t instanceof Date)return new Date(t.valueOf());if(E.isMoment(t))return new Date(t.valueOf());if(D.isString(t))return i=C.exec(t),i?new Date(Number(i[1])):E(t).toDate();throw Error("Cannot convert object of type "+D.getType(t)+" to type Date");case"Moment":if(D.isNumber(t))return E(t);if(t instanceof Date)return E(t.valueOf());if(E.isMoment(t))return E.clone();if(D.isString(t))return i=C.exec(t),i?E(Number(i[1])):E(t);throw Error("Cannot convert object of type "+D.getType(t)+" to type Date");case"ISODate":if(D.isNumber(t))return new Date(t);if(t instanceof Date)return t.toISOString();if(E.isMoment(t))return t.toDate().toISOString();if(D.isString(t))return i=C.exec(t),i?new Date(Number(i[1])).toISOString():new Date(t).toISOString();throw Error("Cannot convert object of type "+D.getType(t)+" to type ISODate");case"ASPDate":if(D.isNumber(t))return"/Date("+t+")/";if(t instanceof Date)return"/Date("+t.valueOf()+")/";if(D.isString(t)){i=C.exec(t);var s;return s=i?new Date(Number(i[1])).valueOf():new Date(t).valueOf(),"/Date("+s+")/"}throw Error("Cannot convert object of type "+D.getType(t)+" to type ASPDate");default:throw Error("Cannot convert object of type "+D.getType(t)+' to type "'+e+'"')}};var C=/^\/?Date\((\-?\d+)/i;if(D.getType=function(t){var e=typeof t;return"object"==e?null==t?"null":t instanceof Boolean?"Boolean":t instanceof Number?"Number":t instanceof String?"String":t instanceof Array?"Array":t instanceof Date?"Date":"Object":"number"==e?"Number":"boolean"==e?"Boolean":"string"==e?"String":e},D.getAbsoluteLeft=function(t){for(var e=document.documentElement,i=document.body,s=t.offsetLeft,n=t.offsetParent;null!=n&&n!=i&&n!=e;)s+=n.offsetLeft,s-=n.scrollLeft,n=n.offsetParent;return s},D.getAbsoluteTop=function(t){for(var e=document.documentElement,i=document.body,s=t.offsetTop,n=t.offsetParent;null!=n&&n!=i&&n!=e;)s+=n.offsetTop,s-=n.scrollTop,n=n.offsetParent;return s},D.getPageY=function(t){if("pageY"in t)return t.pageY;var e;e="targetTouches"in t&&t.targetTouches.length?t.targetTouches[0].clientY:t.clientY;var i=document.documentElement,s=document.body;return e+(i&&i.scrollTop||s&&s.scrollTop||0)-(i&&i.clientTop||s&&s.clientTop||0)},D.getPageX=function(t){if("pageY"in t)return t.pageX;var e;e="targetTouches"in t&&t.targetTouches.length?t.targetTouches[0].clientX:t.clientX;var i=document.documentElement,s=document.body;return e+(i&&i.scrollLeft||s&&s.scrollLeft||0)-(i&&i.clientLeft||s&&s.clientLeft||0)},D.addClassName=function(t,e){var i=t.className.split(" ");-1==i.indexOf(e)&&(i.push(e),t.className=i.join(" "))},D.removeClassName=function(t,e){var i=t.className.split(" "),s=i.indexOf(e);-1!=s&&(i.splice(s,1),t.className=i.join(" "))},D.forEach=function(t,e){var i,s;if(t instanceof Array)for(i=0,s=t.length;s>i;i++)e(t[i],i,t);else for(i in t)t.hasOwnProperty(i)&&e(t[i],i,t)},D.updateProperty=function(t,e,i){return t[e]!==i?(t[e]=i,!0):!1},D.addEventListener=function(t,e,i,s){t.addEventListener?(void 0===s&&(s=!1),"mousewheel"===e&&navigator.userAgent.indexOf("Firefox")>=0&&(e="DOMMouseScroll"),t.addEventListener(e,i,s)):t.attachEvent("on"+e,i)},D.removeEventListener=function(t,e,i,s){t.removeEventListener?(void 0===s&&(s=!1),"mousewheel"===e&&navigator.userAgent.indexOf("Firefox")>=0&&(e="DOMMouseScroll"),t.removeEventListener(e,i,s)):t.detachEvent("on"+e,i)},D.getTarget=function(t){t||(t=window.event);var e;return t.target?e=t.target:t.srcElement&&(e=t.srcElement),void 0!=e.nodeType&&3==e.nodeType&&(e=e.parentNode),e},D.stopPropagation=function(t){t||(t=window.event),t.stopPropagation?t.stopPropagation():t.cancelBubble=!0},D.preventDefault=function(t){t||(t=window.event),t.preventDefault?t.preventDefault():t.returnValue=!1},D.option={},D.option.asBoolean=function(t,e){return"function"==typeof t&&(t=t()),null!=t?0!=t:e||null},D.option.asNumber=function(t,e){return"function"==typeof t&&(t=t()),null!=t?Number(t)||e||null:e||null},D.option.asString=function(t,e){return"function"==typeof t&&(t=t()),null!=t?t+"":e||null},D.option.asSize=function(t,e){return"function"==typeof t&&(t=t()),D.isString(t)?t:D.isNumber(t)?t+"px":e||null},D.option.asElement=function(t,e){return"function"==typeof t&&(t=t()),t||e||null},D.loadCss=function(t){if("undefined"!=typeof document){var e=document.createElement("style");e.type="text/css",e.styleSheet?e.styleSheet.cssText=t:e.appendChild(document.createTextNode(t)),document.getElementsByTagName("head")[0].appendChild(e)}},!Array.prototype.indexOf){Array.prototype.indexOf=function(t){for(var e=0;this.length>e;e++)if(this[e]==t)return e;return-1};try{console.log("Warning: Ancient browser detected. Please update your browser")}catch(L){}}Array.prototype.forEach||(Array.prototype.forEach=function(t,e){for(var i=0,s=this.length;s>i;++i)t.call(e||this,this[i],i,this)}),Array.prototype.map||(Array.prototype.map=function(t,e){var i,s,n;if(null==this)throw new TypeError(" this is null or not defined");var o=Object(this),r=o.length>>>0;if("function"!=typeof t)throw new TypeError(t+" is not a function");for(e&&(i=e),s=Array(r),n=0;r>n;){var a,h;n in o&&(a=o[n],h=t.call(i,a,n,o),s[n]=h),n++}return s}),Array.prototype.filter||(Array.prototype.filter=function(t){"use strict";if(null==this)throw new TypeError;var e=Object(this),i=e.length>>>0;if("function"!=typeof t)throw new TypeError;for(var s=[],n=arguments[1],o=0;i>o;o++)if(o in e){var r=e[o];t.call(n,r,o,e)&&s.push(r)}return s}),Object.keys||(Object.keys=function(){var t=Object.prototype.hasOwnProperty,e=!{toString:null}.propertyIsEnumerable("toString"),i=["toString","toLocaleString","valueOf","hasOwnProperty","isPrototypeOf","propertyIsEnumerable","constructor"],s=i.length;return function(n){if("object"!=typeof n&&"function"!=typeof n||null===n)throw new TypeError("Object.keys called on non-object");var o=[];for(var r in n)t.call(n,r)&&o.push(r);if(e)for(var a=0;s>a;a++)t.call(n,i[a])&&o.push(i[a]);return o}}()),Array.isArray||(Array.isArray=function(t){return"[object Array]"===Object.prototype.toString.call(t)}),Function.prototype.bind||(Function.prototype.bind=function(t){if("function"!=typeof this)throw new TypeError("Function.prototype.bind - what is trying to be bound is not callable");var e=Array.prototype.slice.call(arguments,1),i=this,s=function(){},n=function(){return i.apply(this instanceof s&&t?this:t,e.concat(Array.prototype.slice.call(arguments)))};return s.prototype=this.prototype,n.prototype=new s,n}),Object.create||(Object.create=function(t){function e(){}if(arguments.length>1)throw Error("Object.create implementation only accepts the first parameter.");return e.prototype=t,new e});var O={listeners:[],indexOf:function(t){for(var e=this.listeners,i=0,s=this.listeners.length;s>i;i++){var n=e[i];if(n&&n.object==t)return i}return-1},addListener:function(t,e,i){var s=this.indexOf(t),n=this.listeners[s];n||(n={object:t,events:{}},this.listeners.push(n));var o=n.events[e];o||(o=[],n.events[e]=o),-1==o.indexOf(i)&&o.push(i)},removeListener:function(t,e,i){var s=this.indexOf(t),n=this.listeners[s];if(n){var o=n.events[e];o&&(s=o.indexOf(i),-1!=s&&o.splice(s,1),0==o.length&&delete n.events[e]);var r=0,a=n.events;for(var h in a)a.hasOwnProperty(h)&&r++;0==r&&delete this.listeners[s]}},removeAllListeners:function(){this.listeners=[]},trigger:function(t,e,i){var s=this.indexOf(t),n=this.listeners[s];if(n){var o=n.events[e];if(o)for(var r=0,a=o.length;a>r;r++)o[r](i)}}};n.prototype.on=function(t,e,i){var s=t instanceof RegExp?t:RegExp(t.replace("*","\\w+")),n={id:D.randomUUID(),event:t,regexp:s,callback:"function"==typeof e?e:null,target:i};return this.subscriptions.push(n),n.id},n.prototype.off=function(t){for(var e=0;this.subscriptions.length>e;){var i=this.subscriptions[e],s=!0;if(t instanceof Object)for(var n in t)t.hasOwnProperty(n)&&t[n]!==i[n]&&(s=!1);else s=i.id==t;s?this.subscriptions.splice(e,1):e++}},n.prototype.emit=function(t,e,i){for(var s=0;this.subscriptions.length>s;s++){var n=this.subscriptions[s];n.regexp.test(t)&&n.callback&&n.callback(t,e,i)}},o.prototype.subscribe=function(t,e){var i=this.subscribers[t];i||(i=[],this.subscribers[t]=i),i.push({callback:e})},o.prototype.unsubscribe=function(t,e){var i=this.subscribers[t];i&&(this.subscribers[t]=i.filter(function(t){return t.callback!=e}))},o.prototype._trigger=function(t,e,i){if("*"==t)throw Error("Cannot trigger event *");var s=[];t in this.subscribers&&(s=s.concat(this.subscribers[t])),"*"in this.subscribers&&(s=s.concat(this.subscribers["*"]));for(var n=0;s.length>n;n++){var o=s[n];o.callback&&o.callback(t,e,i||null)}},o.prototype.add=function(t,e){var i,s=[],n=this;if(t instanceof Array)for(var o=0,r=t.length;r>o;o++)i=n._addItem(t[o]),s.push(i);else if(D.isDataTable(t))for(var a=this._getColumnNames(t),h=0,d=t.getNumberOfRows();d>h;h++){for(var l={},p=0,c=a.length;c>p;p++){var u=a[p];l[u]=t.getValue(h,p)}i=n._addItem(l),s.push(i)}else{if(!(t instanceof Object))throw Error("Unknown dataType");i=n._addItem(t),s.push(i)}return s.length&&this._trigger("add",{items:s},e),s},o.prototype.update=function(t,e){var i=[],s=[],n=this,o=n.fieldId,r=function(t){var e=t[o];n.data[e]?(e=n._updateItem(t),s.push(e)):(e=n._addItem(t),i.push(e))};if(t instanceof Array)for(var a=0,h=t.length;h>a;a++)r(t[a]);else if(D.isDataTable(t))for(var d=this._getColumnNames(t),l=0,p=t.getNumberOfRows();p>l;l++){for(var c={},u=0,f=d.length;f>u;u++){var m=d[u];c[m]=t.getValue(l,u)}r(c)}else{if(!(t instanceof Object))throw Error("Unknown dataType");r(t)}return i.length&&this._trigger("add",{items:i},e),s.length&&this._trigger("update",{items:s},e),i.concat(s)},o.prototype.get=function(){var t,e,i,s,n=this,o=D.getType(arguments[0]);"String"==o||"Number"==o?(t=arguments[0],i=arguments[1],s=arguments[2]):"Array"==o?(e=arguments[0],i=arguments[1],s=arguments[2]):(i=arguments[0],s=arguments[1]);var r;if(i&&i.type){if(r="DataTable"==i.type?"DataTable":"Array",s&&r!=D.getType(s))throw Error('Type of parameter "data" ('+D.getType(s)+") "+"does not correspond with specified options.type ("+i.type+")");if("DataTable"==r&&!D.isDataTable(s))throw Error('Parameter "data" must be a DataTable when options.type is "DataTable"')}else r=s?"DataTable"==D.getType(s)?"DataTable":"Array":"Array";var a,h,d,l,p=i&&i.convert||this.options.convert,c=i&&i.filter,u=[];if(void 0!=t)a=n._getItem(t,p),c&&!c(a)&&(a=null);else if(void 0!=e)for(d=0,l=e.length;l>d;d++)a=n._getItem(e[d],p),(!c||c(a))&&u.push(a);else for(h in this.data)this.data.hasOwnProperty(h)&&(a=n._getItem(h,p),(!c||c(a))&&u.push(a));if(i&&i.order&&void 0==t&&this._sort(u,i.order),i&&i.fields){var f=i.fields;if(void 0!=t)a=this._filterFields(a,f);else for(d=0,l=u.length;l>d;d++)u[d]=this._filterFields(u[d],f)}if("DataTable"==r){var m=this._getColumnNames(s);if(void 0!=t)n._appendRow(s,m,a);else for(d=0,l=u.length;l>d;d++)n._appendRow(s,m,u[d]);return s}if(void 0!=t)return a;if(s){for(d=0,l=u.length;l>d;d++)s.push(u[d]);return s}return u},o.prototype.getIds=function(t){var e,i,s,n,o,r=this.data,a=t&&t.filter,h=t&&t.order,d=t&&t.convert||this.options.convert,l=[];if(a)if(h){o=[];for(s in r)r.hasOwnProperty(s)&&(n=this._getItem(s,d),a(n)&&o.push(n));for(this._sort(o,h),e=0,i=o.length;i>e;e++)l[e]=o[e][this.fieldId]}else for(s in r)r.hasOwnProperty(s)&&(n=this._getItem(s,d),a(n)&&l.push(n[this.fieldId]));else if(h){o=[];for(s in r)r.hasOwnProperty(s)&&o.push(r[s]);for(this._sort(o,h),e=0,i=o.length;i>e;e++)l[e]=o[e][this.fieldId]}else for(s in r)r.hasOwnProperty(s)&&(n=r[s],l.push(n[this.fieldId]));return l},o.prototype.forEach=function(t,e){var i,s,n=e&&e.filter,o=e&&e.convert||this.options.convert,r=this.data;if(e&&e.order)for(var a=this.get(e),h=0,d=a.length;d>h;h++)i=a[h],s=i[this.fieldId],t(i,s);else for(s in r)r.hasOwnProperty(s)&&(i=this._getItem(s,o),(!n||n(i))&&t(i,s))},o.prototype.map=function(t,e){var i,s=e&&e.filter,n=e&&e.convert||this.options.convert,o=[],r=this.data;for(var a in r)r.hasOwnProperty(a)&&(i=this._getItem(a,n),(!s||s(i))&&o.push(t(i,a)));return e&&e.order&&this._sort(o,e.order),o},o.prototype._filterFields=function(t,e){var i={};for(var s in t)t.hasOwnProperty(s)&&-1!=e.indexOf(s)&&(i[s]=t[s]);return i},o.prototype._sort=function(t,e){if(D.isString(e)){var i=e;t.sort(function(t,e){var s=t[i],n=e[i];return s>n?1:n>s?-1:0})}else{if("function"!=typeof e)throw new TypeError("Order must be a function or a string");t.sort(e)}},o.prototype.remove=function(t,e){var i,s,n,o=[];if(t instanceof Array)for(i=0,s=t.length;s>i;i++)n=this._remove(t[i]),null!=n&&o.push(n);else n=this._remove(t),null!=n&&o.push(n);return o.length&&this._trigger("remove",{items:o},e),o},o.prototype._remove=function(t){if(D.isNumber(t)||D.isString(t)){if(this.data[t])return delete this.data[t],delete this.internalIds[t],t}else if(t instanceof Object){var e=t[this.fieldId];if(e&&this.data[e])return delete this.data[e],delete this.internalIds[e],e}return null},o.prototype.clear=function(t){var e=Object.keys(this.data);return this.data={},this.internalIds={},this._trigger("remove",{items:e},t),e},o.prototype.max=function(t){var e=this.data,i=null,s=null;for(var n in e)if(e.hasOwnProperty(n)){var o=e[n],r=o[t];null!=r&&(!i||r>s)&&(i=o,s=r)}return i},o.prototype.min=function(t){var e=this.data,i=null,s=null;for(var n in e)if(e.hasOwnProperty(n)){var o=e[n],r=o[t];null!=r&&(!i||s>r)&&(i=o,s=r)}return i},o.prototype.distinct=function(t){var e=this.data,i=[],s=this.options.convert[t],n=0;for(var o in e)if(e.hasOwnProperty(o)){for(var r=e[o],a=D.convert(r[t],s),h=!1,d=0;n>d;d++)if(i[d]==a){h=!0;break}h||(i[n]=a,n++)}return i},o.prototype._addItem=function(t){var e=t[this.fieldId];if(void 0!=e){if(this.data[e])throw Error("Cannot add item: item with id "+e+" already exists")}else e=D.randomUUID(),t[this.fieldId]=e,this.internalIds[e]=t;var i={};for(var s in t)if(t.hasOwnProperty(s)){var n=this.convert[s];i[s]=D.convert(t[s],n)}return this.data[e]=i,e},o.prototype._getItem=function(t,e){var i,s,n=this.data[t];if(!n)return null;var o={},r=this.fieldId,a=this.internalIds;if(e)for(i in n)n.hasOwnProperty(i)&&(s=n[i],i==r&&s in a||(o[i]=D.convert(s,e[i])));else for(i in n)n.hasOwnProperty(i)&&(s=n[i],i==r&&s in a||(o[i]=s));return o},o.prototype._updateItem=function(t){var e=t[this.fieldId];if(void 0==e)throw Error("Cannot update item: item has no id (item: "+JSON.stringify(t)+")");var i=this.data[e];if(!i)throw Error("Cannot update item: no item with id "+e+" found");for(var s in t)if(t.hasOwnProperty(s)){var n=this.convert[s];i[s]=D.convert(t[s],n)}return e},o.prototype._getColumnNames=function(t){for(var e=[],i=0,s=t.getNumberOfColumns();s>i;i++)e[i]=t.getColumnId(i)||t.getColumnLabel(i);return e},o.prototype._appendRow=function(t,e,i){for(var s=t.addRow(),n=0,o=e.length;o>n;n++){var r=e[n];t.setValue(s,n,i[r])}},r.prototype.setData=function(t){var e,i,s;if(this.data){this.data.unsubscribe&&this.data.unsubscribe("*",this.listener),e=[];for(var n in this.ids)this.ids.hasOwnProperty(n)&&e.push(n);this.ids={},this._trigger("remove",{items:e})}if(this.data=t,this.data){for(this.fieldId=this.options.fieldId||this.data&&this.data.options&&this.data.options.fieldId||"id",e=this.data.getIds({filter:this.options&&this.options.filter}),i=0,s=e.length;s>i;i++)n=e[i],this.ids[n]=!0;this._trigger("add",{items:e}),this.data.subscribe&&this.data.subscribe("*",this.listener)}},r.prototype.get=function(){var t,e,i,s=this,n=D.getType(arguments[0]);"String"==n||"Number"==n||"Array"==n?(t=arguments[0],e=arguments[1],i=arguments[2]):(e=arguments[0],i=arguments[1]);var o=D.extend({},this.options,e);this.options.filter&&e&&e.filter&&(o.filter=function(t){return s.options.filter(t)&&e.filter(t)});var r=[];return void 0!=t&&r.push(t),r.push(o),r.push(i),this.data&&this.data.get.apply(this.data,r)},r.prototype.getIds=function(t){var e;if(this.data){var i,s=this.options.filter;i=t&&t.filter?s?function(e){return s(e)&&t.filter(e)}:t.filter:s,e=this.data.getIds({filter:i,order:t&&t.order})}else e=[];return e},r.prototype._onEvent=function(t,e,i){var s,n,o,r,a=e&&e.items,h=this.data,d=[],l=[],p=[];if(a&&h){switch(t){case"add":for(s=0,n=a.length;n>s;s++)o=a[s],r=this.get(o),r&&(this.ids[o]=!0,d.push(o));break;case"update":for(s=0,n=a.length;n>s;s++)o=a[s],r=this.get(o),r?this.ids[o]?l.push(o):(this.ids[o]=!0,d.push(o)):this.ids[o]&&(delete this.ids[o],p.push(o));break;case"remove":for(s=0,n=a.length;n>s;s++)o=a[s],this.ids[o]&&(delete this.ids[o],p.push(o))}d.length&&this._trigger("add",{items:d},i),l.length&&this._trigger("update",{items:l},i),p.length&&this._trigger("remove",{items:p},i)}},r.prototype.subscribe=o.prototype.subscribe,r.prototype.unsubscribe=o.prototype.unsubscribe,r.prototype._trigger=o.prototype._trigger,TimeStep=function(t,e,i){this.current=new Date,this._start=new Date,this._end=new Date,this.autoScale=!0,this.scale=TimeStep.SCALE.DAY,this.step=1,this.setRange(t,e,i)},TimeStep.SCALE={MILLISECOND:1,SECOND:2,MINUTE:3,HOUR:4,DAY:5,WEEKDAY:6,MONTH:7,YEAR:8},TimeStep.prototype.setRange=function(t,e,i){t instanceof Date&&e instanceof Date&&(this._start=void 0!=t?new Date(t.valueOf()):new Date,this._end=void 0!=e?new Date(e.valueOf()):new Date,this.autoScale&&this.setMinimumStep(i))},TimeStep.prototype.first=function(){this.current=new Date(this._start.valueOf()),this.roundToMinor()},TimeStep.prototype.roundToMinor=function(){switch(this.scale){case TimeStep.SCALE.YEAR:this.current.setFullYear(this.step*Math.floor(this.current.getFullYear()/this.step)),this.current.setMonth(0);case TimeStep.SCALE.MONTH:this.current.setDate(1);case TimeStep.SCALE.DAY:case TimeStep.SCALE.WEEKDAY:this.current.setHours(0);case TimeStep.SCALE.HOUR:this.current.setMinutes(0);case TimeStep.SCALE.MINUTE:this.current.setSeconds(0);case TimeStep.SCALE.SECOND:this.current.setMilliseconds(0)}if(1!=this.step)switch(this.scale){case TimeStep.SCALE.MILLISECOND:this.current.setMilliseconds(this.current.getMilliseconds()-this.current.getMilliseconds()%this.step);break;case TimeStep.SCALE.SECOND:this.current.setSeconds(this.current.getSeconds()-this.current.getSeconds()%this.step);break;case TimeStep.SCALE.MINUTE:this.current.setMinutes(this.current.getMinutes()-this.current.getMinutes()%this.step);break;case TimeStep.SCALE.HOUR:this.current.setHours(this.current.getHours()-this.current.getHours()%this.step);break;case TimeStep.SCALE.WEEKDAY:case TimeStep.SCALE.DAY:this.current.setDate(this.current.getDate()-1-(this.current.getDate()-1)%this.step+1);break;case TimeStep.SCALE.MONTH:this.current.setMonth(this.current.getMonth()-this.current.getMonth()%this.step);break;case TimeStep.SCALE.YEAR:this.current.setFullYear(this.current.getFullYear()-this.current.getFullYear()%this.step);break;default:}},TimeStep.prototype.hasNext=function(){return this.current.valueOf()<=this._end.valueOf()},TimeStep.prototype.next=function(){var t=this.current.valueOf();if(6>this.current.getMonth())switch(this.scale){case TimeStep.SCALE.MILLISECOND:this.current=new Date(this.current.valueOf()+this.step);break;case TimeStep.SCALE.SECOND:this.current=new Date(this.current.valueOf()+1e3*this.step);break;case TimeStep.SCALE.MINUTE:this.current=new Date(this.current.valueOf()+60*1e3*this.step);break;case TimeStep.SCALE.HOUR:this.current=new Date(this.current.valueOf()+60*60*1e3*this.step);var e=this.current.getHours();this.current.setHours(e-e%this.step);break;case TimeStep.SCALE.WEEKDAY:case TimeStep.SCALE.DAY:this.current.setDate(this.current.getDate()+this.step);break;case TimeStep.SCALE.MONTH:this.current.setMonth(this.current.getMonth()+this.step);break;case TimeStep.SCALE.YEAR:this.current.setFullYear(this.current.getFullYear()+this.step);break;default:}else switch(this.scale){case TimeStep.SCALE.MILLISECOND:this.current=new Date(this.current.valueOf()+this.step);break;case TimeStep.SCALE.SECOND:this.current.setSeconds(this.current.getSeconds()+this.step);break;case TimeStep.SCALE.MINUTE:this.current.setMinutes(this.current.getMinutes()+this.step);break;case TimeStep.SCALE.HOUR:this.current.setHours(this.current.getHours()+this.step);break;case TimeStep.SCALE.WEEKDAY:case TimeStep.SCALE.DAY:this.current.setDate(this.current.getDate()+this.step);break;case TimeStep.SCALE.MONTH:this.current.setMonth(this.current.getMonth()+this.step);break;case TimeStep.SCALE.YEAR:this.current.setFullYear(this.current.getFullYear()+this.step);break;default:}if(1!=this.step)switch(this.scale){case TimeStep.SCALE.MILLISECOND:this.current.getMilliseconds()0&&(this.step=e),this.autoScale=!1},TimeStep.prototype.setAutoScale=function(t){this.autoScale=t},TimeStep.prototype.setMinimumStep=function(t){if(void 0!=t){var e=31104e6,i=2592e6,s=864e5,n=36e5,o=6e4,r=1e3,a=1;1e3*e>t&&(this.scale=TimeStep.SCALE.YEAR,this.step=1e3),500*e>t&&(this.scale=TimeStep.SCALE.YEAR,this.step=500),100*e>t&&(this.scale=TimeStep.SCALE.YEAR,this.step=100),50*e>t&&(this.scale=TimeStep.SCALE.YEAR,this.step=50),10*e>t&&(this.scale=TimeStep.SCALE.YEAR,this.step=10),5*e>t&&(this.scale=TimeStep.SCALE.YEAR,this.step=5),e>t&&(this.scale=TimeStep.SCALE.YEAR,this.step=1),3*i>t&&(this.scale=TimeStep.SCALE.MONTH,this.step=3),i>t&&(this.scale=TimeStep.SCALE.MONTH,this.step=1),5*s>t&&(this.scale=TimeStep.SCALE.DAY,this.step=5),2*s>t&&(this.scale=TimeStep.SCALE.DAY,this.step=2),s>t&&(this.scale=TimeStep.SCALE.DAY,this.step=1),s/2>t&&(this.scale=TimeStep.SCALE.WEEKDAY,this.step=1),4*n>t&&(this.scale=TimeStep.SCALE.HOUR,this.step=4),n>t&&(this.scale=TimeStep.SCALE.HOUR,this.step=1),15*o>t&&(this.scale=TimeStep.SCALE.MINUTE,this.step=15),10*o>t&&(this.scale=TimeStep.SCALE.MINUTE,this.step=10),5*o>t&&(this.scale=TimeStep.SCALE.MINUTE,this.step=5),o>t&&(this.scale=TimeStep.SCALE.MINUTE,this.step=1),15*r>t&&(this.scale=TimeStep.SCALE.SECOND,this.step=15),10*r>t&&(this.scale=TimeStep.SCALE.SECOND,this.step=10),5*r>t&&(this.scale=TimeStep.SCALE.SECOND,this.step=5),r>t&&(this.scale=TimeStep.SCALE.SECOND,this.step=1),200*a>t&&(this.scale=TimeStep.SCALE.MILLISECOND,this.step=200),100*a>t&&(this.scale=TimeStep.SCALE.MILLISECOND,this.step=100),50*a>t&&(this.scale=TimeStep.SCALE.MILLISECOND,this.step=50),10*a>t&&(this.scale=TimeStep.SCALE.MILLISECOND,this.step=10),5*a>t&&(this.scale=TimeStep.SCALE.MILLISECOND,this.step=5),a>t&&(this.scale=TimeStep.SCALE.MILLISECOND,this.step=1) -}},TimeStep.prototype.snap=function(t){if(this.scale==TimeStep.SCALE.YEAR){var e=t.getFullYear()+Math.round(t.getMonth()/12);t.setFullYear(Math.round(e/this.step)*this.step),t.setMonth(0),t.setDate(0),t.setHours(0),t.setMinutes(0),t.setSeconds(0),t.setMilliseconds(0)}else if(this.scale==TimeStep.SCALE.MONTH)t.getDate()>15?(t.setDate(1),t.setMonth(t.getMonth()+1)):t.setDate(1),t.setHours(0),t.setMinutes(0),t.setSeconds(0),t.setMilliseconds(0);else if(this.scale==TimeStep.SCALE.DAY||this.scale==TimeStep.SCALE.WEEKDAY){switch(this.step){case 5:case 2:t.setHours(24*Math.round(t.getHours()/24));break;default:t.setHours(12*Math.round(t.getHours()/12))}t.setMinutes(0),t.setSeconds(0),t.setMilliseconds(0)}else if(this.scale==TimeStep.SCALE.HOUR){switch(this.step){case 4:t.setMinutes(60*Math.round(t.getMinutes()/60));break;default:t.setMinutes(30*Math.round(t.getMinutes()/30))}t.setSeconds(0),t.setMilliseconds(0)}else if(this.scale==TimeStep.SCALE.MINUTE){switch(this.step){case 15:case 10:t.setMinutes(5*Math.round(t.getMinutes()/5)),t.setSeconds(0);break;case 5:t.setSeconds(60*Math.round(t.getSeconds()/60));break;default:t.setSeconds(30*Math.round(t.getSeconds()/30))}t.setMilliseconds(0)}else if(this.scale==TimeStep.SCALE.SECOND)switch(this.step){case 15:case 10:t.setSeconds(5*Math.round(t.getSeconds()/5)),t.setMilliseconds(0);break;case 5:t.setMilliseconds(1e3*Math.round(t.getMilliseconds()/1e3));break;default:t.setMilliseconds(500*Math.round(t.getMilliseconds()/500))}else if(this.scale==TimeStep.SCALE.MILLISECOND){var i=this.step>5?this.step/2:1;t.setMilliseconds(Math.round(t.getMilliseconds()/i)*i)}},TimeStep.prototype.isMajor=function(){switch(this.scale){case TimeStep.SCALE.MILLISECOND:return 0==this.current.getMilliseconds();case TimeStep.SCALE.SECOND:return 0==this.current.getSeconds();case TimeStep.SCALE.MINUTE:return 0==this.current.getHours()&&0==this.current.getMinutes();case TimeStep.SCALE.HOUR:return 0==this.current.getHours();case TimeStep.SCALE.WEEKDAY:case TimeStep.SCALE.DAY:return 1==this.current.getDate();case TimeStep.SCALE.MONTH:return 0==this.current.getMonth();case TimeStep.SCALE.YEAR:return!1;default:return!1}},TimeStep.prototype.getLabelMinor=function(t){switch(void 0==t&&(t=this.current),this.scale){case TimeStep.SCALE.MILLISECOND:return E(t).format("SSS");case TimeStep.SCALE.SECOND:return E(t).format("s");case TimeStep.SCALE.MINUTE:return E(t).format("HH:mm");case TimeStep.SCALE.HOUR:return E(t).format("HH:mm");case TimeStep.SCALE.WEEKDAY:return E(t).format("ddd D");case TimeStep.SCALE.DAY:return E(t).format("D");case TimeStep.SCALE.MONTH:return E(t).format("MMM");case TimeStep.SCALE.YEAR:return E(t).format("YYYY");default:return""}},TimeStep.prototype.getLabelMajor=function(t){switch(void 0==t&&(t=this.current),this.scale){case TimeStep.SCALE.MILLISECOND:return E(t).format("HH:mm:ss");case TimeStep.SCALE.SECOND:return E(t).format("D MMMM HH:mm");case TimeStep.SCALE.MINUTE:case TimeStep.SCALE.HOUR:return E(t).format("ddd D MMMM");case TimeStep.SCALE.WEEKDAY:case TimeStep.SCALE.DAY:return E(t).format("MMMM YYYY");case TimeStep.SCALE.MONTH:return E(t).format("YYYY");case TimeStep.SCALE.YEAR:return"";default:return""}},a.prototype.setOptions=function(t){D.extend(this.options,t)},a.prototype.update=function(){this._order(),this._stack()},a.prototype._order=function(){var t=this.parent.items;if(!t)throw Error("Cannot stack items: parent does not contain items");var e=[],i=0;D.forEach(t,function(t){t.visible&&(e[i]=t,i++)});var s=this.options.order||this.defaultOptions.order;if("function"!=typeof s)throw Error("Option order must be a function");e.sort(s),this.ordered=e},a.prototype._stack=function(){var t,e,i,s=this.ordered,n=this.options,o=n.orientation||this.defaultOptions.orientation,r="top"==o;for(i=n.margin&&void 0!==n.margin.item?n.margin.item:this.defaultOptions.margin.item,t=0,e=s.length;e>t;t++){var a=s[t],h=null;do h=this.checkOverlap(s,t,0,t-1,i),null!=h&&(a.top=r?h.top+h.height+i:h.top-a.height-i);while(h)}},a.prototype.checkOverlap=function(t,e,i,s,n){for(var o=this.collision,r=t[e],a=s;a>=i;a--){var h=t[a];if(o(r,h,n)&&a!=e)return h}return null},a.prototype.collision=function(t,e,i){return t.left-ie.left&&t.top-ie.top},h.prototype.setOptions=function(t){D.extend(this.options,t),(null!=t.start||null!=t.end)&&this.setRange(t.start,t.end)},h.prototype.subscribe=function(t,e,i){var s,n=this;if("horizontal"!=i&&"vertical"!=i)throw new TypeError('Unknown direction "'+i+'". '+'Choose "horizontal" or "vertical".');if("move"==e)s={component:t,event:e,direction:i,callback:function(t){n._onMouseDown(t,s)},params:{}},t.on("mousedown",s.callback),n.listeners.push(s);else{if("zoom"!=e)throw new TypeError('Unknown event "'+e+'". '+'Choose "move" or "zoom".');s={component:t,event:e,direction:i,callback:function(t){n._onMouseWheel(t,s)},params:{}},t.on("mousewheel",s.callback),n.listeners.push(s)}},h.prototype.on=function(t,e){O.addListener(this,t,e)},h.prototype._trigger=function(t){O.trigger(this,t,{start:this.start,end:this.end})},h.prototype.setRange=function(t,e){var i=this._applyRange(t,e);i&&(this._trigger("rangechange"),this._trigger("rangechanged"))},h.prototype._applyRange=function(t,e){var i,s=null!=t?D.convert(t,"Number"):this.start,n=null!=e?D.convert(e,"Number"):this.end;if(isNaN(s))throw Error('Invalid start "'+t+'"');if(isNaN(n))throw Error('Invalid end "'+e+'"');if(s>n&&(n=s),null!=this.options.min){var o=this.options.min.valueOf();o>s&&(i=o-s,s+=i,n+=i)}if(null!=this.options.max){var r=this.options.max.valueOf();n>r&&(i=n-r,s-=i,n-=i)}if(null!=this.options.zoomMin){var a=this.options.zoomMin.valueOf();0>a&&(a=0),a>n-s&&(this.end-this.start>a?(i=a-(n-s),s-=i/2,n+=i/2):(s=this.start,n=this.end))}if(null!=this.options.zoomMax){var h=this.options.zoomMax.valueOf();0>h&&(h=0),n-s>h&&(h>this.end-this.start?(i=n-s-h,s+=i/2,n-=i/2):(s=this.start,n=this.end))}var d=this.start!=s||this.end!=n;return this.start=s,this.end=n,d},h.prototype.getRange=function(){return{start:this.start,end:this.end}},h.prototype.conversion=function(t){return this.start,this.end,h.conversion(this.start,this.end,t)},h.conversion=function(t,e,i){return 0!=i&&0!=e-t?{offset:t,factor:i/(e-t)}:{offset:0,factor:1}},h.prototype._onMouseDown=function(t,e){t=t||window.event;var i=e.params,s=t.which?1==t.which:1==t.button;if(s){i.mouseX=D.getPageX(t),i.mouseY=D.getPageY(t),i.previousLeft=0,i.previousOffset=0,i.moved=!1,i.start=this.start,i.end=this.end;var n=e.component.frame;n&&(n.style.cursor="move");var o=this;i.onMouseMove||(i.onMouseMove=function(t){o._onMouseMove(t,e)},D.addEventListener(document,"mousemove",i.onMouseMove)),i.onMouseUp||(i.onMouseUp=function(t){o._onMouseUp(t,e)},D.addEventListener(document,"mouseup",i.onMouseUp)),D.preventDefault(t)}},h.prototype._onMouseMove=function(t,e){t=t||window.event;var i=e.params,s=D.getPageX(t),n=D.getPageY(t);void 0==i.mouseX&&(i.mouseX=s),void 0==i.mouseY&&(i.mouseY=n);var o=s-i.mouseX,r=n-i.mouseY,a="horizontal"==e.direction?o:r;Math.abs(a)>=1&&(i.moved=!0);var h=i.end-i.start,d="horizontal"==e.direction?e.component.width:e.component.height,l=-a/d*h;this._applyRange(i.start+l,i.end+l),this._trigger("rangechange"),D.preventDefault(t)},h.prototype._onMouseUp=function(t,e){t=t||window.event;var i=e.params;e.component.frame&&(e.component.frame.style.cursor="auto"),i.onMouseMove&&(D.removeEventListener(document,"mousemove",i.onMouseMove),i.onMouseMove=null),i.onMouseUp&&(D.removeEventListener(document,"mouseup",i.onMouseUp),i.onMouseUp=null),i.moved&&this._trigger("rangechanged")},h.prototype._onMouseWheel=function(t,e){t=t||window.event;var i=0;if(t.wheelDelta?i=t.wheelDelta/120:t.detail&&(i=-t.detail/3),i){var s=this,n=function(){var n=i/5,o=null,r=e.component.frame;if(r){var a,h;if("horizontal"==e.direction){a=e.component.width,h=s.conversion(a);var d=D.getAbsoluteLeft(r),l=D.getPageX(t);o=(l-d)/h.factor+h.offset}else{a=e.component.height,h=s.conversion(a);var p=D.getAbsoluteTop(r),c=D.getPageY(t);o=(p+a-c-p)/h.factor+h.offset}}s.zoom(n,o)};n()}D.preventDefault(t)},h.prototype.zoom=function(t,e){null==e&&(e=(this.start+this.end)/2),t>=1&&(t=.9),-1>=t&&(t=-.9),0>t&&(t/=1+t);var i=this.start-e,s=this.end-e,n=this.start-i*t,o=this.end-s*t;this.setRange(n,o)},h.prototype.move=function(t){var e=this.end-this.start,i=this.start+e*t,s=this.end+e*t;this.start=i,this.end=s},d.prototype.add=function(t){if(void 0==t.id)throw Error("Component has no field id");if(!(t instanceof l||t instanceof d))throw new TypeError("Component must be an instance of prototype Component or Controller");t.controller=this,this.components[t.id]=t},d.prototype.remove=function(t){var e;for(e in this.components)if(this.components.hasOwnProperty(e)&&(e==t||this.components[e]==t))break;e&&delete this.components[e]},d.prototype.requestReflow=function(t){if(t)this.reflow();else if(!this.reflowTimer){var e=this;this.reflowTimer=setTimeout(function(){e.reflowTimer=void 0,e.reflow()},0)}},d.prototype.requestRepaint=function(t){if(t)this.repaint();else if(!this.repaintTimer){var e=this;this.repaintTimer=setTimeout(function(){e.repaintTimer=void 0,e.repaint()},0)}},d.prototype.repaint=function(){function t(s,n){n in i||(s.depends&&s.depends.forEach(function(e){t(e,e.id)}),s.parent&&t(s.parent,s.parent.id),e=s.repaint()||e,i[n]=!0)}var e=!1;this.repaintTimer&&(clearTimeout(this.repaintTimer),this.repaintTimer=void 0);var i={};D.forEach(this.components,t),e&&this.reflow()},d.prototype.reflow=function(){function t(s,n){n in i||(s.depends&&s.depends.forEach(function(e){t(e,e.id)}),s.parent&&t(s.parent,s.parent.id),e=s.reflow()||e,i[n]=!0)}var e=!1;this.reflowTimer&&(clearTimeout(this.reflowTimer),this.reflowTimer=void 0);var i={};D.forEach(this.components,t),e&&this.repaint()},l.prototype.setOptions=function(t){t&&(D.extend(this.options,t),this.controller&&(this.requestRepaint(),this.requestReflow()))},l.prototype.getOption=function(t){var e;return this.options&&(e=this.options[t]),void 0===e&&this.defaultOptions&&(e=this.defaultOptions[t]),e},l.prototype.getContainer=function(){return null},l.prototype.getFrame=function(){return this.frame},l.prototype.repaint=function(){return!1},l.prototype.reflow=function(){return!1},l.prototype.hide=function(){return this.frame&&this.frame.parentNode?(this.frame.parentNode.removeChild(this.frame),!0):!1},l.prototype.show=function(){return this.frame&&this.frame.parentNode?!1:this.repaint()},l.prototype.requestRepaint=function(){if(!this.controller)throw Error("Cannot request a repaint: no controller configured");this.controller.requestRepaint()},l.prototype.requestReflow=function(){if(!this.controller)throw Error("Cannot request a reflow: no controller configured");this.controller.requestReflow()},p.prototype=new l,p.prototype.setOptions=l.prototype.setOptions,p.prototype.getContainer=function(){return this.frame},p.prototype.repaint=function(){var t=0,e=D.updateProperty,i=D.option.asSize,s=this.options,n=this.frame;if(!n){n=document.createElement("div"),n.className="panel";var o=s.className;o&&("function"==typeof o?D.addClassName(n,o()+""):D.addClassName(n,o+"")),this.frame=n,t+=1}if(!n.parentNode){if(!this.parent)throw Error("Cannot repaint panel: no parent attached");var r=this.parent.getContainer();if(!r)throw Error("Cannot repaint panel: parent has no container element");r.appendChild(n),t+=1}return t+=e(n.style,"top",i(s.top,"0px")),t+=e(n.style,"left",i(s.left,"0px")),t+=e(n.style,"width",i(s.width,"100%")),t+=e(n.style,"height",i(s.height,"100%")),t>0},p.prototype.reflow=function(){var t=0,e=D.updateProperty,i=this.frame;return i?(t+=e(this,"top",i.offsetTop),t+=e(this,"left",i.offsetLeft),t+=e(this,"width",i.offsetWidth),t+=e(this,"height",i.offsetHeight)):t+=1,t>0},c.prototype=new p,c.prototype.setOptions=l.prototype.setOptions,c.prototype.repaint=function(){var t=0,e=D.updateProperty,i=D.option.asSize,s=this.options,n=this.frame;if(!n){n=document.createElement("div"),n.className="vis timeline rootpanel";var o=s.className;o&&D.addClassName(n,D.option.asString(o)),this.frame=n,t+=1}if(!n.parentNode){if(!this.container)throw Error("Cannot repaint root panel: no container attached");this.container.appendChild(n),t+=1}return t+=e(n.style,"top",i(s.top,"0px")),t+=e(n.style,"left",i(s.left,"0px")),t+=e(n.style,"width",i(s.width,"100%")),t+=e(n.style,"height",i(s.height,"100%")),this._updateEventEmitters(),this._updateWatch(),t>0},c.prototype.reflow=function(){var t=0,e=D.updateProperty,i=this.frame;return i?(t+=e(this,"top",i.offsetTop),t+=e(this,"left",i.offsetLeft),t+=e(this,"width",i.offsetWidth),t+=e(this,"height",i.offsetHeight)):t+=1,t>0},c.prototype._updateWatch=function(){var t=this.getOption("autoResize");t?this._watch():this._unwatch()},c.prototype._watch=function(){var t=this;this._unwatch();var e=function(){var e=t.getOption("autoResize");return e?(t.frame&&(t.frame.clientWidth!=t.width||t.frame.clientHeight!=t.height)&&t.requestReflow(),void 0):(t._unwatch(),void 0)};D.addEventListener(window,"resize",e),this.watchTimer=setInterval(e,1e3)},c.prototype._unwatch=function(){this.watchTimer&&(clearInterval(this.watchTimer),this.watchTimer=void 0)},c.prototype.on=function(t,e){var i=this.listeners[t];i||(i=[],this.listeners[t]=i),i.push(e),this._updateEventEmitters()},c.prototype._updateEventEmitters=function(){if(this.listeners){var t=this;D.forEach(this.listeners,function(e,i){if(t.emitters||(t.emitters={}),!(i in t.emitters)){var s=t.frame;if(s){var n=function(t){e.forEach(function(e){e(t)})};t.emitters[i]=n,D.addEventListener(s,i,n)}}})}},u.prototype=new l,u.prototype.setOptions=l.prototype.setOptions,u.prototype.setRange=function(t){if(!(t instanceof h||t&&t.start&&t.end))throw new TypeError("Range must be an instance of Range, or an object containing start and end.");this.range=t},u.prototype.toTime=function(t){var e=this.conversion;return new Date(t/e.factor+e.offset)},u.prototype.toScreen=function(t){var e=this.conversion;return(t.valueOf()-e.offset)*e.factor},u.prototype.repaint=function(){var t=0,e=D.updateProperty,i=D.option.asSize,s=this.options,n=this.getOption("orientation"),o=this.props,r=this.step,a=this.frame;if(a||(a=document.createElement("div"),this.frame=a,t+=1),a.className="axis "+n,!a.parentNode){if(!this.parent)throw Error("Cannot repaint time axis: no parent attached");var h=this.parent.getContainer();if(!h)throw Error("Cannot repaint time axis: parent has no container element");h.appendChild(a),t+=1}var d=a.parentNode;if(d){var l=a.nextSibling;d.removeChild(a);var p="bottom"==n&&this.props.parentHeight&&this.height?this.props.parentHeight-this.height+"px":"0px";if(t+=e(a.style,"top",i(s.top,p)),t+=e(a.style,"left",i(s.left,"0px")),t+=e(a.style,"width",i(s.width,"100%")),t+=e(a.style,"height",i(s.height,this.height+"px")),this._repaintMeasureChars(),this.step){this._repaintStart(),r.first();for(var c=void 0,u=0;r.hasNext()&&1e3>u;){u++;var f=r.getCurrent(),m=this.toScreen(f),g=r.isMajor();this.getOption("showMinorLabels")&&this._repaintMinorText(m,r.getLabelMinor()),g&&this.getOption("showMajorLabels")?(m>0&&(void 0==c&&(c=m),this._repaintMajorText(m,r.getLabelMajor())),this._repaintMajorLine(m)):this._repaintMinorLine(m),r.next()}if(this.getOption("showMajorLabels")){var v=this.toTime(0),y=r.getLabelMajor(v),b=y.length*(o.majorCharWidth||10)+10;(void 0==c||c>b)&&this._repaintMajorText(0,y)}this._repaintEnd()}this._repaintLine(),l?d.insertBefore(a,l):d.appendChild(a)}return t>0},u.prototype._repaintStart=function(){var t=this.dom,e=t.redundant;e.majorLines=t.majorLines,e.majorTexts=t.majorTexts,e.minorLines=t.minorLines,e.minorTexts=t.minorTexts,t.majorLines=[],t.majorTexts=[],t.minorLines=[],t.minorTexts=[]},u.prototype._repaintEnd=function(){D.forEach(this.dom.redundant,function(t){for(;t.length;){var e=t.pop();e&&e.parentNode&&e.parentNode.removeChild(e)}})},u.prototype._repaintMinorText=function(t,e){var i=this.dom.redundant.minorTexts.shift();if(!i){var s=document.createTextNode("");i=document.createElement("div"),i.appendChild(s),i.className="text minor",this.frame.appendChild(i)}this.dom.minorTexts.push(i),i.childNodes[0].nodeValue=e,i.style.left=t+"px",i.style.top=this.props.minorLabelTop+"px"},u.prototype._repaintMajorText=function(t,e){var i=this.dom.redundant.majorTexts.shift();if(!i){var s=document.createTextNode(e);i=document.createElement("div"),i.className="text major",i.appendChild(s),this.frame.appendChild(i)}this.dom.majorTexts.push(i),i.childNodes[0].nodeValue=e,i.style.top=this.props.majorLabelTop+"px",i.style.left=t+"px"},u.prototype._repaintMinorLine=function(t){var e=this.dom.redundant.minorLines.shift();e||(e=document.createElement("div"),e.className="grid vertical minor",this.frame.appendChild(e)),this.dom.minorLines.push(e);var i=this.props;e.style.top=i.minorLineTop+"px",e.style.height=i.minorLineHeight+"px",e.style.left=t-i.minorLineWidth/2+"px"},u.prototype._repaintMajorLine=function(t){var e=this.dom.redundant.majorLines.shift();e||(e=document.createElement("DIV"),e.className="grid vertical major",this.frame.appendChild(e)),this.dom.majorLines.push(e);var i=this.props;e.style.top=i.majorLineTop+"px",e.style.left=t-i.majorLineWidth/2+"px",e.style.height=i.majorLineHeight+"px"},u.prototype._repaintLine=function(){var t=this.dom.line,e=this.frame;this.options,this.getOption("showMinorLabels")||this.getOption("showMajorLabels")?(t?(e.removeChild(t),e.appendChild(t)):(t=document.createElement("div"),t.className="grid horizontal major",e.appendChild(t),this.dom.line=t),t.style.top=this.props.lineTop+"px"):t&&axis.parentElement&&(e.removeChild(axis.line),delete this.dom.line)},u.prototype._repaintMeasureChars=function(){var t,e=this.dom;if(!e.measureCharMinor){t=document.createTextNode("0");var i=document.createElement("DIV");i.className="text minor measure",i.appendChild(t),this.frame.appendChild(i),e.measureCharMinor=i}if(!e.measureCharMajor){t=document.createTextNode("0");var s=document.createElement("DIV");s.className="text major measure",s.appendChild(t),this.frame.appendChild(s),e.measureCharMajor=s}},u.prototype.reflow=function(){var t=0,e=D.updateProperty,i=this.frame,s=this.range;if(!s)throw Error("Cannot repaint time axis: no range configured");if(i){t+=e(this,"top",i.offsetTop),t+=e(this,"left",i.offsetLeft);var n=this.props,o=this.getOption("showMinorLabels"),r=this.getOption("showMajorLabels"),a=this.dom.measureCharMinor,h=this.dom.measureCharMajor;a&&(n.minorCharHeight=a.clientHeight,n.minorCharWidth=a.clientWidth),h&&(n.majorCharHeight=h.clientHeight,n.majorCharWidth=h.clientWidth);var d=i.parentNode?i.parentNode.offsetHeight:0;switch(d!=n.parentHeight&&(n.parentHeight=d,t+=1),this.getOption("orientation")){case"bottom":n.minorLabelHeight=o?n.minorCharHeight:0,n.majorLabelHeight=r?n.majorCharHeight:0,n.minorLabelTop=0,n.majorLabelTop=n.minorLabelTop+n.minorLabelHeight,n.minorLineTop=-this.top,n.minorLineHeight=Math.max(this.top+n.majorLabelHeight,0),n.minorLineWidth=1,n.majorLineTop=-this.top,n.majorLineHeight=Math.max(this.top+n.minorLabelHeight+n.majorLabelHeight,0),n.majorLineWidth=1,n.lineTop=0;break;case"top":n.minorLabelHeight=o?n.minorCharHeight:0,n.majorLabelHeight=r?n.majorCharHeight:0,n.majorLabelTop=0,n.minorLabelTop=n.majorLabelTop+n.majorLabelHeight,n.minorLineTop=n.minorLabelTop,n.minorLineHeight=Math.max(d-n.majorLabelHeight-this.top),n.minorLineWidth=1,n.majorLineTop=0,n.majorLineHeight=Math.max(d-this.top),n.majorLineWidth=1,n.lineTop=n.majorLabelHeight+n.minorLabelHeight;break;default:throw Error('Unkown orientation "'+this.getOption("orientation")+'"')}var l=n.minorLabelHeight+n.majorLabelHeight;t+=e(this,"width",i.offsetWidth),t+=e(this,"height",l),this._updateConversion();var p=D.convert(s.start,"Date"),c=D.convert(s.end,"Date"),u=this.toTime(5*(n.minorCharWidth||10))-this.toTime(0);this.step=new TimeStep(p,c,u),t+=e(n.range,"start",p.valueOf()),t+=e(n.range,"end",c.valueOf()),t+=e(n.range,"minimumStep",u.valueOf())}return t>0},u.prototype._updateConversion=function(){var t=this.range;if(!t)throw Error("No range configured");this.conversion=t.conversion?t.conversion(this.width):h.conversion(t.start,t.end,this.width)},f.prototype=new p,f.types={box:g,range:y,point:v},f.prototype.setOptions=l.prototype.setOptions,f.prototype.setRange=function(t){if(!(t instanceof h||t&&t.start&&t.end))throw new TypeError("Range must be an instance of Range, or an object containing start and end.");this.range=t},f.prototype.repaint=function(){var t=0,e=D.updateProperty,i=D.option.asSize,s=this.options,n=this.getOption("orientation"),o=this.defaultOptions,r=this.frame;if(!r){r=document.createElement("div"),r.className="itemset";var a=s.className;a&&D.addClassName(r,D.option.asString(a));var h=document.createElement("div");h.className="background",r.appendChild(h),this.dom.background=h;var d=document.createElement("div");d.className="foreground",r.appendChild(d),this.dom.foreground=d;var l=document.createElement("div");l.className="itemset-axis",this.dom.axis=l,this.frame=r,t+=1}if(!this.parent)throw Error("Cannot repaint itemset: no parent attached");var p=this.parent.getContainer();if(!p)throw Error("Cannot repaint itemset: parent has no container element");r.parentNode||(p.appendChild(r),t+=1),this.dom.axis.parentNode||(p.appendChild(this.dom.axis),t+=1),t+=e(r.style,"left",i(s.left,"0px")),t+=e(r.style,"top",i(s.top,"0px")),t+=e(r.style,"width",i(s.width,"100%")),t+=e(r.style,"height",i(s.height,this.height+"px")),t+=e(this.dom.axis.style,"left",i(s.left,"0px")),t+=e(this.dom.axis.style,"width",i(s.width,"100%")),t+="bottom"==n?e(this.dom.axis.style,"top",this.height+this.top+"px"):e(this.dom.axis.style,"top",this.top+"px"),this._updateConversion();var c=this,u=this.queue,m=this.itemsData,g=this.items,v={fields:[m&&m.fieldId||"id","start","end","content","type"]};return Object.keys(u).forEach(function(e){var i=u[e],n=g[e];switch(i){case"add":case"update":var r=m&&m.get(e,v);if(r){var a=r.type||r.start&&r.end&&"range"||s.type||"box",h=f.types[a];if(n&&(h&&n instanceof h?(n.data=r,t++):(t+=n.hide(),n=null)),!n){if(!h)throw new TypeError('Unknown item type "'+a+'"');n=new h(c,r,s,o),t++}n.repaint(),g[e]=n}delete u[e];break;case"remove":n&&(t+=n.hide()),delete g[e],delete u[e];break;default:console.log('Error: unknown action "'+i+'"')}}),D.forEach(this.items,function(e){e.visible?(t+=e.show(),e.reposition()):t+=e.hide()}),t>0},f.prototype.getForeground=function(){return this.dom.foreground},f.prototype.getBackground=function(){return this.dom.background},f.prototype.getAxis=function(){return this.dom.axis},f.prototype.reflow=function(){var t=0,e=this.options,i=e.margin&&e.margin.axis||this.defaultOptions.margin.axis,s=e.margin&&e.margin.item||this.defaultOptions.margin.item,n=D.updateProperty,o=D.option.asNumber,r=D.option.asSize,a=this.frame;if(a){this._updateConversion(),D.forEach(this.items,function(e){t+=e.reflow()}),this.stack.update();var h,d=o(e.maxHeight),l=null!=r(e.height);if(l)h=a.offsetHeight;else{var p=this.stack.ordered;if(p.length){var c=p[0].top,u=p[0].top+p[0].height;D.forEach(p,function(t){c=Math.min(c,t.top),u=Math.max(u,t.top+t.height)}),h=u-c+i+s}else h=i+s}null!=d&&(h=Math.min(h,d)),t+=n(this,"height",h),t+=n(this,"top",a.offsetTop),t+=n(this,"left",a.offsetLeft),t+=n(this,"width",a.offsetWidth)}else t+=1;return t>0},f.prototype.hide=function(){var t=!1;return this.frame&&this.frame.parentNode&&(this.frame.parentNode.removeChild(this.frame),t=!0),this.dom.axis&&this.dom.axis.parentNode&&(this.dom.axis.parentNode.removeChild(this.dom.axis),t=!0),t},f.prototype.setItems=function(t){var e,i=this,s=this.itemsData;if(t){if(!(t instanceof o||t instanceof r))throw new TypeError("Data must be an instance of DataSet");this.itemsData=t}else this.itemsData=null;if(s&&(D.forEach(this.listeners,function(t,e){s.unsubscribe(e,t)}),e=s.getIds(),this._onRemove(e)),this.itemsData){var n=this.id;D.forEach(this.listeners,function(t,e){i.itemsData.subscribe(e,t,n)}),e=this.itemsData.getIds(),this._onAdd(e)}},f.prototype.getItems=function(){return this.itemsData},f.prototype._onUpdate=function(t){this._toQueue("update",t)},f.prototype._onAdd=function(t){this._toQueue("add",t)},f.prototype._onRemove=function(t){this._toQueue("remove",t)},f.prototype._toQueue=function(t,e){var i=this.queue;e.forEach(function(e){i[e]=t}),this.controller&&this.requestRepaint()},f.prototype._updateConversion=function(){var t=this.range;if(!t)throw Error("No range configured");this.conversion=t.conversion?t.conversion(this.width):h.conversion(t.start,t.end,this.width)},f.prototype.toTime=function(t){var e=this.conversion;return new Date(t/e.factor+e.offset)},f.prototype.toScreen=function(t){var e=this.conversion;return(t.valueOf()-e.offset)*e.factor},m.prototype.select=function(){this.selected=!0},m.prototype.unselect=function(){this.selected=!1},m.prototype.show=function(){return!1},m.prototype.hide=function(){return!1},m.prototype.repaint=function(){return!1},m.prototype.reflow=function(){return!1},g.prototype=new m(null,null),g.prototype.select=function(){this.selected=!0},g.prototype.unselect=function(){this.selected=!1},g.prototype.repaint=function(){var t=!1,e=this.dom;if(e||(this._create(),e=this.dom,t=!0),e){if(!this.parent)throw Error("Cannot repaint item: no parent attached");var i=this.parent.getForeground();if(!i)throw Error("Cannot repaint time axis: parent has no foreground container element");var s=this.parent.getBackground();if(!s)throw Error("Cannot repaint time axis: parent has no background container element");var n=this.parent.getAxis();if(!s)throw Error("Cannot repaint time axis: parent has no axis container element");if(e.box.parentNode||(i.appendChild(e.box),t=!0),e.line.parentNode||(s.appendChild(e.line),t=!0),e.dot.parentNode||(n.appendChild(e.dot),t=!0),this.data.content!=this.content){if(this.content=this.data.content,this.content instanceof Element)e.content.innerHTML="",e.content.appendChild(this.content);else{if(void 0==this.data.content)throw Error('Property "content" missing in item '+this.data.id);e.content.innerHTML=this.content}t=!0}var o=(this.data.className?" "+this.data.className:"")+(this.selected?" selected":"");this.className!=o&&(this.className=o,e.box.className="item box"+o,e.line.className="item line"+o,e.dot.className="item dot"+o,t=!0)}return t},g.prototype.show=function(){return this.dom&&this.dom.box.parentNode?!1:this.repaint()},g.prototype.hide=function(){var t=!1,e=this.dom;return e&&(e.box.parentNode&&(e.box.parentNode.removeChild(e.box),t=!0),e.line.parentNode&&e.line.parentNode.removeChild(e.line),e.dot.parentNode&&e.dot.parentNode.removeChild(e.dot)),t},g.prototype.reflow=function(){var t,e,i,s,n,o,r,a,h,d,l,p,c=0;if(void 0==this.data.start)throw Error('Property "start" missing in item '+this.data.id);if(l=this.data,p=this.parent&&this.parent.range,l&&p){var u=p.end-p.start;this.visible=l.start>p.start-u&&l.start0},g.prototype._create=function(){var t=this.dom;t||(this.dom=t={},t.box=document.createElement("DIV"),t.content=document.createElement("DIV"),t.content.className="content",t.box.appendChild(t.content),t.line=document.createElement("DIV"),t.line.className="line",t.dot=document.createElement("DIV"),t.dot.className="dot")},g.prototype.reposition=function(){var t=this.dom,e=this.props,i=this.options.orientation||this.defaultOptions.orientation;if(t){var s=t.box,n=t.line,o=t.dot;s.style.left=this.left+"px",s.style.top=this.top+"px",n.style.left=e.line.left+"px","top"==i?(n.style.top="0px",n.style.height=this.top+"px"):(n.style.top=this.top+this.height+"px",n.style.height=Math.max(this.parent.height-this.top-this.height+this.props.dot.height/2,0)+"px"),o.style.left=e.dot.left+"px",o.style.top=e.dot.top+"px"}},v.prototype=new m(null,null),v.prototype.select=function(){this.selected=!0},v.prototype.unselect=function(){this.selected=!1},v.prototype.repaint=function(){var t=!1,e=this.dom;if(e||(this._create(),e=this.dom,t=!0),e){if(!this.parent)throw Error("Cannot repaint item: no parent attached");var i=this.parent.getForeground();if(!i)throw Error("Cannot repaint time axis: parent has no foreground container element");if(e.point.parentNode||(i.appendChild(e.point),i.appendChild(e.point),t=!0),this.data.content!=this.content){if(this.content=this.data.content,this.content instanceof Element)e.content.innerHTML="",e.content.appendChild(this.content);else{if(void 0==this.data.content)throw Error('Property "content" missing in item '+this.data.id);e.content.innerHTML=this.content}t=!0}var s=(this.data.className?" "+this.data.className:"")+(this.selected?" selected":"");this.className!=s&&(this.className=s,e.point.className="item point"+s,t=!0)}return t},v.prototype.show=function(){return this.dom&&this.dom.point.parentNode?!1:this.repaint()},v.prototype.hide=function(){var t=!1,e=this.dom;return e&&e.point.parentNode&&(e.point.parentNode.removeChild(e.point),t=!0),t},v.prototype.reflow=function(){var t,e,i,s,n,o,r,a,h,d,l=0;if(void 0==this.data.start)throw Error('Property "start" missing in item '+this.data.id);if(h=this.data,d=this.parent&&this.parent.range,h&&d){var p=d.end-d.start;this.visible=h.start>d.start-p&&h.start0},v.prototype._create=function(){var t=this.dom;t||(this.dom=t={},t.point=document.createElement("div"),t.content=document.createElement("div"),t.content.className="content",t.point.appendChild(t.content),t.dot=document.createElement("div"),t.dot.className="dot",t.point.appendChild(t.dot))},v.prototype.reposition=function(){var t=this.dom,e=this.props;t&&(t.point.style.top=this.top+"px",t.point.style.left=this.left+"px",t.content.style.marginLeft=e.content.marginLeft+"px",t.dot.style.top=e.dot.top+"px")},y.prototype=new m(null,null),y.prototype.select=function(){this.selected=!0},y.prototype.unselect=function(){this.selected=!1},y.prototype.repaint=function(){var t=!1,e=this.dom;if(e||(this._create(),e=this.dom,t=!0),e){if(!this.parent)throw Error("Cannot repaint item: no parent attached");var i=this.parent.getForeground();if(!i)throw Error("Cannot repaint time axis: parent has no foreground container element");if(e.box.parentNode||(i.appendChild(e.box),t=!0),this.data.content!=this.content){if(this.content=this.data.content,this.content instanceof Element)e.content.innerHTML="",e.content.appendChild(this.content);else{if(void 0==this.data.content)throw Error('Property "content" missing in item '+this.data.id);e.content.innerHTML=this.content -}t=!0}var s=this.data.className?""+this.data.className:"";this.className!=s&&(this.className=s,e.box.className="item range"+s,t=!0)}return t},y.prototype.show=function(){return this.dom&&this.dom.box.parentNode?!1:this.repaint()},y.prototype.hide=function(){var t=!1,e=this.dom;return e&&e.box.parentNode&&(e.box.parentNode.removeChild(e.box),t=!0),t},y.prototype.reflow=function(){var t,e,i,s,n,o,r,a,h,d,l,p,c,u,f,m,g=0;if(void 0==this.data.start)throw Error('Property "start" missing in item '+this.data.id);if(void 0==this.data.end)throw Error('Property "end" missing in item '+this.data.id);return h=this.data,d=this.parent&&this.parent.range,this.visible=h&&d?h.startd.start:!1,this.visible&&(t=this.dom,t?(e=this.props,i=this.options,o=this.parent,r=o.toScreen(this.data.start),a=o.toScreen(this.data.end),l=D.updateProperty,p=t.box,c=o.width,f=i.orientation||this.defaultOptions.orientation,s=i.margin&&i.margin.axis||this.defaultOptions.margin.axis,n=i.padding||this.defaultOptions.padding,g+=l(e.content,"width",t.content.offsetWidth),g+=l(this,"height",p.offsetHeight),-c>r&&(r=-c),a>2*c&&(a=2*c),u=0>r?Math.min(-r,a-r-e.content.width-2*n):0,g+=l(e.content,"left",u),"top"==f?(m=s,g+=l(this,"top",m)):(m=o.height-this.height-s,g+=l(this,"top",m)),g+=l(this,"left",r),g+=l(this,"width",Math.max(a-r,1))):g+=1),g>0},y.prototype._create=function(){var t=this.dom;t||(this.dom=t={},t.box=document.createElement("div"),t.content=document.createElement("div"),t.content.className="content",t.box.appendChild(t.content))},y.prototype.reposition=function(){var t=this.dom,e=this.props;t&&(t.box.style.top=this.top+"px",t.box.style.left=this.left+"px",t.box.style.width=this.width+"px",t.content.style.left=e.content.left+"px")},b.prototype=new l,b.prototype.setOptions=l.prototype.setOptions,b.prototype.getContainer=function(){return this.parent.getContainer()},b.prototype.setItems=function(t){if(this.itemset&&(this.itemset.hide(),this.itemset.setItems(),this.parent.controller.remove(this.itemset),this.itemset=null),t){var e=this.groupId,i=Object.create(this.options);this.itemset=new f(this,null,i),this.itemset.setRange(this.parent.range),this.view=new r(t,{filter:function(t){return t.group==e}}),this.itemset.setItems(this.view),this.parent.controller.add(this.itemset)}},b.prototype.repaint=function(){return!1},b.prototype.reflow=function(){var t=0,e=D.updateProperty;if(t+=e(this,"top",this.itemset?this.itemset.top:0),t+=e(this,"height",this.itemset?this.itemset.height:0),this.label){var i=this.label.firstChild;t+=e(this.props.label,"width",i.clientWidth),t+=e(this.props.label,"height",i.clientHeight)}else t+=e(this.props.label,"width",0),t+=e(this.props.label,"height",0);return t>0},w.prototype=new p,w.prototype.setOptions=l.prototype.setOptions,w.prototype.setRange=function(){},w.prototype.setItems=function(t){this.itemsData=t;for(var e in this.groups)if(this.groups.hasOwnProperty(e)){var i=this.groups[e];i.setItems(t)}},w.prototype.getItems=function(){return this.itemsData},w.prototype.setRange=function(t){this.range=t},w.prototype.setGroups=function(t){var e,i=this;if(this.groupsData&&(D.forEach(this.listeners,function(t,e){i.groupsData.unsubscribe(e,t)}),e=this.groupsData.getIds(),this._onRemove(e)),t?t instanceof o?this.groupsData=t:(this.groupsData=new o({convert:{start:"Date",end:"Date"}}),this.groupsData.add(t)):this.groupsData=null,this.groupsData){var s=this.id;D.forEach(this.listeners,function(t,e){i.groupsData.subscribe(e,t,s)}),e=this.groupsData.getIds(),this._onAdd(e)}},w.prototype.getGroups=function(){return this.groupsData},w.prototype.repaint=function(){var t,e,i,s,n=0,o=D.updateProperty,r=D.option.asSize,a=D.option.asElement,h=this.options,d=this.dom.frame,l=this.dom.labels;if(!this.parent)throw Error("Cannot repaint groupset: no parent attached");var p=this.parent.getContainer();if(!p)throw Error("Cannot repaint groupset: parent has no container element");if(!d){d=document.createElement("div"),d.className="groupset",this.dom.frame=d;var c=h.className;c&&D.addClassName(d,D.option.asString(c)),n+=1}d.parentNode||(p.appendChild(d),n+=1);var u=a(h.labelContainer);if(!u)throw Error('Cannot repaint groupset: option "labelContainer" not defined');l||(l=document.createElement("div"),l.className="labels",this.dom.labels=l),l.parentNode&&l.parentNode==u||(l.parentNode&&l.parentNode.removeChild(l.parentNode),u.appendChild(l)),n+=o(d.style,"height",r(h.height,this.height+"px")),n+=o(d.style,"top",r(h.top,"0px")),n+=o(d.style,"left",r(h.left,"0px")),n+=o(d.style,"width",r(h.width,"100%")),n+=o(l.style,"top",r(h.top,"0px"));var f=this,m=this.queue,g=this.groups,v=this.groupsData,y=Object.keys(m);if(y.length){y.forEach(function(t){var e=m[t],i=g[t];switch(e){case"add":case"update":if(!i){var s=Object.create(f.options);i=new b(f,t,s),i.setItems(f.itemsData),g[t]=i,f.controller.add(i)}i.data=v.get(t),delete m[t];break;case"remove":i&&(i.setItems(),delete g[t],f.controller.remove(i)),delete m[t];break;default:console.log('Error: unknown action "'+e+'"')}});var w=this.groupsData.getIds({order:this.options.groupsOrder});for(t=0;w.length>t;t++)(function(t,e){var i=0;e&&(i=function(){return e.top+e.height}),t.setOptions({top:i})})(g[w[t]],g[w[t-1]]);for(;l.firstChild;)l.removeChild(l.firstChild);for(t=0;w.length>t;t++)e=w[t],s=this._createLabel(e),l.appendChild(s);n++}for(e in g)g.hasOwnProperty(e)&&(i=g[e],s=i.label,s&&(s.style.top=i.top+"px",s.style.height=i.height+"px"));return n>0},w.prototype._createLabel=function(t){var e=this.groups[t],i=document.createElement("div");i.className="label";var s=document.createElement("div");s.className="inner",i.appendChild(s);var n=e.data&&e.data.content;n instanceof Element?s.appendChild(n):void 0!=n&&(s.innerHTML=n);var o=e.data&&e.data.className;return o&&D.addClassName(i,o),e.label=i,i},w.prototype.getContainer=function(){return this.dom.frame},w.prototype.getLabelsWidth=function(){return this.props.labels.width},w.prototype.reflow=function(){var t,e,i=0,s=this.options,n=D.updateProperty,o=D.option.asNumber,r=D.option.asSize,a=this.dom.frame;if(a){var h,d=o(s.maxHeight),l=null!=r(s.height);if(l)h=a.offsetHeight;else{h=0;for(t in this.groups)this.groups.hasOwnProperty(t)&&(e=this.groups[t],h+=e.height)}null!=d&&(h=Math.min(h,d)),i+=n(this,"height",h),i+=n(this,"top",a.offsetTop),i+=n(this,"left",a.offsetLeft),i+=n(this,"width",a.offsetWidth)}var p=0;for(t in this.groups)if(this.groups.hasOwnProperty(t)){e=this.groups[t];var c=e.props&&e.props.label&&e.props.label.width||0;p=Math.max(p,c)}return i+=n(this.props.labels,"width",p),i>0},w.prototype.hide=function(){return this.dom.frame&&this.dom.frame.parentNode?(this.dom.frame.parentNode.removeChild(this.dom.frame),!0):!1},w.prototype.show=function(){return this.dom.frame&&this.dom.frame.parentNode?!1:this.repaint()},w.prototype._onUpdate=function(t){this._toQueue(t,"update")},w.prototype._onAdd=function(t){this._toQueue(t,"add")},w.prototype._onRemove=function(t){this._toQueue(t,"remove")},w.prototype._toQueue=function(t,e){var i=this.queue;t.forEach(function(t){i[t]=e}),this.controller&&this.requestRepaint()},_.prototype.setOptions=function(t){t&&D.extend(this.options,t),this.controller.reflow(),this.controller.repaint()},_.prototype.setItems=function(t){var e,i=null==this.itemsData;if(t?t instanceof o&&(e=t):e=null,t instanceof o||(e=new o({convert:{start:"Date",end:"Date"}}),e.add(t)),this.itemsData=e,this.content.setItems(e),i&&(void 0==this.options.start||void 0==this.options.end)){var s=this.getItemRange(),n=s.min,r=s.max;if(null!=n&&null!=r){var a=r.valueOf()-n.valueOf();n=new Date(n.valueOf()-.05*a),r=new Date(r.valueOf()+.05*a)}void 0!=this.options.start&&(n=new Date(this.options.start.valueOf())),void 0!=this.options.end&&(r=new Date(this.options.end.valueOf())),(null!=n||null!=r)&&this.range.setRange(n,r)}},_.prototype.setGroups=function(t){var e=this;this.groupsData=t;var i=this.groupsData?w:f;if(!(this.content instanceof i)){this.content&&(this.content.hide(),this.content.setItems&&this.content.setItems(),this.content.setGroups&&this.content.setGroups(),this.controller.remove(this.content));var s=Object.create(this.options);D.extend(s,{top:function(){return"top"==e.options.orientation?e.timeaxis.height:e.itemPanel.height-e.timeaxis.height-e.content.height},left:null,width:"100%",height:function(){return e.options.height?e.itemPanel.height-e.timeaxis.height:null},maxHeight:function(){if(e.options.maxHeight){if(!D.isNumber(e.options.maxHeight))throw new TypeError("Number expected for property maxHeight");return e.options.maxHeight-e.timeaxis.height}return null},labelContainer:function(){return e.labelPanel.getContainer()}}),this.content=new i(this.itemPanel,[this.timeaxis],s),this.content.setRange&&this.content.setRange(this.range),this.content.setItems&&this.content.setItems(this.itemsData),this.content.setGroups&&this.content.setGroups(this.groupsData),this.controller.add(this.content)}},_.prototype.getItemRange=function(){var t=this.itemsData,e=null,i=null;if(t){var s=t.min("start");e=s?s.start.valueOf():null;var n=t.max("start");n&&(i=n.start.valueOf());var o=t.max("end");o&&(i=null==i?o.end.valueOf():Math.max(i,o.end.valueOf()))}return{min:null!=e?new Date(e):null,max:null!=i?new Date(i):null}},function(t){function e(t){return E=t,c()}function i(){D=0,C=E.charAt(0)}function s(){D++,C=E.charAt(D)}function n(){return E.charAt(D+1)}function o(t){return N.test(t)}function r(t,e){if(t||(t={}),e)for(var i in e)e.hasOwnProperty(i)&&(t[i]=e[i]);return t}function a(t,e,i){for(var s=e.split("."),n=t;s.length;){var o=s.shift();s.length?(n[o]||(n[o]={}),n=n[o]):n[o]=i}}function h(t,e){for(var i,s,n=null,o=[t],a=t;a.parent;)o.push(a.parent),a=a.parent;if(a.nodes)for(i=0,s=a.nodes.length;s>i;i++)if(e.id===a.nodes[i].id){n=a.nodes[i];break}for(n||(n={id:e.id},t.node&&(n.attr=r(n.attr,t.node))),i=o.length-1;i>=0;i--){var h=o[i];h.nodes||(h.nodes=[]),-1==h.nodes.indexOf(n)&&h.nodes.push(n)}e.attr&&(n.attr=r(n.attr,e.attr))}function d(t,e){if(t.edges||(t.edges=[]),t.edges.push(e),t.edge){var i=r({},t.edge);e.attr=r(i,e.attr)}}function l(t,e,i,s,n){var o={from:e,to:i,type:s};return t.edge&&(o.attr=r({},t.edge)),o.attr=r(o.attr||{},n),o}function p(){for(O=S.NULL,L="";" "==C||" "==C||"\n"==C||"\r"==C;)s();do{var t=!1;if("#"==C){for(var e=D-1;" "==E.charAt(e)||" "==E.charAt(e);)e--;if("\n"==E.charAt(e)||""==E.charAt(e)){for(;""!=C&&"\n"!=C;)s();t=!0}}if("/"==C&&"/"==n()){for(;""!=C&&"\n"!=C;)s();t=!0}if("/"==C&&"*"==n()){for(;""!=C;){if("*"==C&&"/"==n()){s(),s();break}s()}t=!0}for(;" "==C||" "==C||"\n"==C||"\r"==C;)s()}while(t);if(""==C)return O=S.DELIMITER,void 0;var i=C+n();if(M[i])return O=S.DELIMITER,L=i,s(),s(),void 0;if(M[C])return O=S.DELIMITER,L=C,s(),void 0;if(o(C)||"-"==C){for(L+=C,s();o(C);)L+=C,s();return"false"==L?L=!1:"true"==L?L=!0:isNaN(Number(L))||(L=Number(L)),O=S.IDENTIFIER,void 0}if('"'==C){for(s();""!=C&&('"'!=C||'"'==C&&'"'==n());)L+=C,'"'==C&&s(),s();if('"'!=C)throw w('End of string " expected');return s(),O=S.IDENTIFIER,void 0}for(O=S.UNKNOWN;""!=C;)L+=C,s();throw new SyntaxError('Syntax error in part "'+_(L,30)+'"')}function c(){var t={};if(i(),p(),"strict"==L&&(t.strict=!0,p()),("graph"==L||"digraph"==L)&&(t.type=L,p()),O==S.IDENTIFIER&&(t.id=L,p()),"{"!=L)throw w("Angle bracket { expected");if(p(),u(t),"}"!=L)throw w("Angle bracket } expected");if(p(),""!==L)throw w("End of file expected");return p(),delete t.node,delete t.edge,delete t.graph,t}function u(t){for(;""!==L&&"}"!=L;)f(t),";"==L&&p()}function f(t){var e=m(t);if(e)return y(t,e),void 0;var i=g(t);if(!i){if(O!=S.IDENTIFIER)throw w("Identifier expected");var s=L;if(p(),"="==L){if(p(),O!=S.IDENTIFIER)throw w("Identifier expected");t[s]=L,p()}else v(t,s)}}function m(t){var e=null;if("subgraph"==L&&(e={},e.type="subgraph",p(),O==S.IDENTIFIER&&(e.id=L,p())),"{"==L){if(p(),e||(e={}),e.parent=t,e.node=t.node,e.edge=t.edge,e.graph=t.graph,u(e),"}"!=L)throw w("Angle bracket } expected");p(),delete e.node,delete e.edge,delete e.graph,delete e.parent,t.subgraphs||(t.subgraphs=[]),t.subgraphs.push(e)}return e}function g(t){return"node"==L?(p(),t.node=b(),"node"):"edge"==L?(p(),t.edge=b(),"edge"):"graph"==L?(p(),t.graph=b(),"graph"):null}function v(t,e){var i={id:e},s=b();s&&(i.attr=s),h(t,i),y(t,e)}function y(t,e){for(;"->"==L||"--"==L;){var i,s=L;p();var n=m(t);if(n)i=n;else{if(O!=S.IDENTIFIER)throw w("Identifier or subgraph expected");i=L,h(t,{id:i}),p()}var o=b(),r=l(t,e,i,s,o);d(t,r),e=i}}function b(){for(var t=null;"["==L;){for(p(),t={};""!==L&&"]"!=L;){if(O!=S.IDENTIFIER)throw w("Attribute name expected");var e=L;if(p(),"="!=L)throw w("Equal sign = expected");if(p(),O!=S.IDENTIFIER)throw w("Attribute value expected");var i=L;a(t,e,i),p(),","==L&&p()}if("]"!=L)throw w("Bracket ] expected");p()}return t}function w(t){return new SyntaxError(t+', got "'+_(L,30)+'" (char '+D+")")}function _(t,e){return e>=t.length?t:t.substr(0,27)+"..."}function x(t,e,i){t instanceof Array?t.forEach(function(t){e instanceof Array?e.forEach(function(e){i(t,e)}):i(t,e)}):e instanceof Array?e.forEach(function(e){i(t,e)}):i(t,e)}function T(t){function i(t){var e={from:t.from,to:t.to};return r(e,t.attr),e.style="->"==t.type?"arrow":"line",e}var s=e(t),n={nodes:[],edges:[],options:{}};return s.nodes&&s.nodes.forEach(function(t){var e={id:t.id,label:(t.label||t.id)+""};r(e,t.attr),e.image&&(e.shape="image"),n.nodes.push(e)}),s.edges&&s.edges.forEach(function(t){var e,s;e=t.from instanceof Object?t.from.nodes:{id:t.from},s=t.to instanceof Object?t.to.nodes:{id:t.to},t.from instanceof Object&&t.from.edges&&t.from.edges.forEach(function(t){var e=i(t);n.edges.push(e)}),x(e,s,function(e,s){var o=l(n,e.id,s.id,t.type,t.attr),r=i(o);n.edges.push(r)}),t.to instanceof Object&&t.to.edges&&t.to.edges.forEach(function(t){var e=i(t);n.edges.push(e)})}),s.attr&&(n.options=s.attr),n}var S={NULL:0,DELIMITER:1,IDENTIFIER:2,UNKNOWN:3},M={"{":!0,"}":!0,"[":!0,"]":!0,";":!0,"=":!0,",":!0,"->":!0,"--":!0},E="",D=0,C="",L="",O=S.NULL,N=/[a-zA-Z_0-9.:#]/;t.parseDOT=e,t.DOTToGraph=T}(D!==void 0?D:s),"undefined"!=typeof CanvasRenderingContext2D&&(CanvasRenderingContext2D.prototype.circle=function(t,e,i){this.beginPath(),this.arc(t,e,i,0,2*Math.PI,!1)},CanvasRenderingContext2D.prototype.square=function(t,e,i){this.beginPath(),this.rect(t-i,e-i,2*i,2*i)},CanvasRenderingContext2D.prototype.triangle=function(t,e,i){this.beginPath();var s=2*i,n=s/2,o=Math.sqrt(3)/6*s,r=Math.sqrt(s*s-n*n);this.moveTo(t,e-(r-o)),this.lineTo(t+n,e+o),this.lineTo(t-n,e+o),this.lineTo(t,e-(r-o)),this.closePath()},CanvasRenderingContext2D.prototype.triangleDown=function(t,e,i){this.beginPath();var s=2*i,n=s/2,o=Math.sqrt(3)/6*s,r=Math.sqrt(s*s-n*n);this.moveTo(t,e+(r-o)),this.lineTo(t+n,e-o),this.lineTo(t-n,e-o),this.lineTo(t,e+(r-o)),this.closePath()},CanvasRenderingContext2D.prototype.star=function(t,e,i){this.beginPath();for(var s=0;10>s;s++){var n=0===s%2?1.3*i:.5*i;this.lineTo(t+n*Math.sin(2*s*Math.PI/10),e-n*Math.cos(2*s*Math.PI/10))}this.closePath()},CanvasRenderingContext2D.prototype.roundRect=function(t,e,i,s,n){var o=Math.PI/180;0>i-2*n&&(n=i/2),0>s-2*n&&(n=s/2),this.beginPath(),this.moveTo(t+n,e),this.lineTo(t+i-n,e),this.arc(t+i-n,e+n,n,270*o,360*o,!1),this.lineTo(t+i,e+s-n),this.arc(t+i-n,e+s-n,n,0,90*o,!1),this.lineTo(t+n,e+s),this.arc(t+n,e+s-n,n,90*o,180*o,!1),this.lineTo(t,e+n),this.arc(t+n,e+n,n,180*o,270*o,!1)},CanvasRenderingContext2D.prototype.ellipse=function(t,e,i,s){var n=.5522848,o=i/2*n,r=s/2*n,a=t+i,h=e+s,d=t+i/2,l=e+s/2;this.beginPath(),this.moveTo(t,l),this.bezierCurveTo(t,l-r,d-o,e,d,e),this.bezierCurveTo(d+o,e,a,l-r,a,l),this.bezierCurveTo(a,l+r,d+o,h,d,h),this.bezierCurveTo(d-o,h,t,l+r,t,l)},CanvasRenderingContext2D.prototype.database=function(t,e,i,s){var n=1/3,o=i,r=s*n,a=.5522848,h=o/2*a,d=r/2*a,l=t+o,p=e+r,c=t+o/2,u=e+r/2,f=e+(s-r/2),m=e+s;this.beginPath(),this.moveTo(l,u),this.bezierCurveTo(l,u+d,c+h,p,c,p),this.bezierCurveTo(c-h,p,t,u+d,t,u),this.bezierCurveTo(t,u-d,c-h,e,c,e),this.bezierCurveTo(c+h,e,l,u-d,l,u),this.lineTo(l,f),this.bezierCurveTo(l,f+d,c+h,m,c,m),this.bezierCurveTo(c-h,m,t,f+d,t,f),this.lineTo(t,u)},CanvasRenderingContext2D.prototype.arrow=function(t,e,i,s){var n=t-s*Math.cos(i),o=e-s*Math.sin(i),r=t-.9*s*Math.cos(i),a=e-.9*s*Math.sin(i),h=n+s/3*Math.cos(i+.5*Math.PI),d=o+s/3*Math.sin(i+.5*Math.PI),l=n+s/3*Math.cos(i-.5*Math.PI),p=o+s/3*Math.sin(i-.5*Math.PI);this.beginPath(),this.moveTo(t,e),this.lineTo(h,d),this.lineTo(r,a),this.lineTo(l,p),this.closePath()},CanvasRenderingContext2D.prototype.dashedLine=function(t,e,i,s,n){n||(n=[10,5]),0==c&&(c=.001);var o=n.length;this.moveTo(t,e);for(var r=i-t,a=s-e,h=a/r,d=Math.sqrt(r*r+a*a),l=0,p=!0;d>=.1;){var c=n[l++%o];c>d&&(c=d);var u=Math.sqrt(c*c/(1+h*h));0>r&&(u=-u),t+=u,e+=h*u,this[p?"lineTo":"moveTo"](t,e),d-=c,p=!p}}),x.prototype.attachEdge=function(t){-1==this.edges.indexOf(t)&&this.edges.push(t),this._updateMass()},x.prototype.detachEdge=function(t){var e=this.edges.indexOf(t);-1!=e&&this.edges.splice(e,1),this._updateMass()},x.prototype._updateMass=function(){this.mass=50+20*this.edges.length},x.prototype.setProperties=function(t,e){if(t){if(void 0!=t.id&&(this.id=t.id),void 0!=t.label&&(this.label=t.label),void 0!=t.title&&(this.title=t.title),void 0!=t.group&&(this.group=t.group),void 0!=t.x&&(this.x=t.x),void 0!=t.y&&(this.y=t.y),void 0!=t.value&&(this.value=t.value),void 0===this.id)throw"Node must have an id";if(this.group){var i=this.grouplist.get(this.group);for(var s in i)i.hasOwnProperty(s)&&(this[s]=i[s])}if(void 0!=t.shape&&(this.shape=t.shape),void 0!=t.image&&(this.image=t.image),void 0!=t.radius&&(this.radius=t.radius),void 0!=t.color&&(this.color=x.parseColor(t.color)),void 0!=t.fontColor&&(this.fontColor=t.fontColor),void 0!=t.fontSize&&(this.fontSize=t.fontSize),void 0!=t.fontFace&&(this.fontFace=t.fontFace),void 0!=this.image){if(!this.imagelist)throw"No imagelist provided";this.imageObj=this.imagelist.load(this.image)}switch(this.xFixed=this.xFixed||void 0!=t.x,this.yFixed=this.yFixed||void 0!=t.y,this.radiusFixed=this.radiusFixed||void 0!=t.radius,"image"==this.shape&&(this.radiusMin=e.nodes.widthMin,this.radiusMax=e.nodes.widthMax),this.shape){case"database":this.draw=this._drawDatabase,this.resize=this._resizeDatabase;break;case"box":this.draw=this._drawBox,this.resize=this._resizeBox;break;case"circle":this.draw=this._drawCircle,this.resize=this._resizeCircle;break;case"ellipse":this.draw=this._drawEllipse,this.resize=this._resizeEllipse;break;case"image":this.draw=this._drawImage,this.resize=this._resizeImage;break;case"text":this.draw=this._drawText,this.resize=this._resizeText;break;case"dot":this.draw=this._drawDot,this.resize=this._resizeShape;break;case"square":this.draw=this._drawSquare,this.resize=this._resizeShape;break;case"triangle":this.draw=this._drawTriangle,this.resize=this._resizeShape;break;case"triangleDown":this.draw=this._drawTriangleDown,this.resize=this._resizeShape;break;case"star":this.draw=this._drawStar,this.resize=this._resizeShape;break;default:this.draw=this._drawEllipse,this.resize=this._resizeEllipse}this._reset()}},x.parseColor=function(t){var e;return D.isString(t)?e={border:t,background:t,highlight:{border:t,background:t}}:(e={},e.background=t.background||"white",e.border=t.border||e.background,D.isString(t.highlight)?e.highlight={border:t.highlight,background:t.highlight}:(e.highlight={},e.highlight.background=t.highlight&&t.highlight.background||e.background,e.highlight.border=t.highlight&&t.highlight.border||e.border)),e},x.prototype.select=function(){this.selected=!0,this._reset()},x.prototype.unselect=function(){this.selected=!1,this._reset()},x.prototype._reset=function(){this.width=void 0,this.height=void 0},x.prototype.getTitle=function(){return this.title},x.prototype.distanceToBorder=function(t,e){var i=1;switch(this.width||this.resize(t),this.shape){case"circle":case"dot":return this.radius+i;case"ellipse":var s=this.width/2,n=this.height/2,o=Math.sin(e)*s,r=Math.cos(e)*n;return s*n/Math.sqrt(o*o+r*r);case"box":case"image":case"text":default:return this.width?Math.min(Math.abs(this.width/2/Math.cos(e)),Math.abs(this.height/2/Math.sin(e)))+i:0}},x.prototype._setForce=function(t,e){this.fx=t,this.fy=e},x.prototype._addForce=function(t,e){this.fx+=t,this.fy+=e},x.prototype.discreteStep=function(t){if(!this.xFixed){var e=-this.damping*this.vx,i=(this.fx+e)/this.mass;this.vx+=i/t,this.x+=this.vx/t}if(!this.yFixed){var s=-this.damping*this.vy,n=(this.fy+s)/this.mass;this.vy+=n/t,this.y+=this.vy/t}},x.prototype.isFixed=function(){return this.xFixed&&this.yFixed},x.prototype.isMoving=function(t){return Math.abs(this.vx)>t||Math.abs(this.vy)>t||!this.xFixed&&Math.abs(this.fx)>this.minForce||!this.yFixed&&Math.abs(this.fy)>this.minForce},x.prototype.isSelected=function(){return this.selected},x.prototype.getValue=function(){return this.value},x.prototype.getDistance=function(t,e){var i=this.x-t,s=this.y-e;return Math.sqrt(i*i+s*s)},x.prototype.setValueRange=function(t,e){if(!this.radiusFixed&&void 0!==this.value){var i=(this.radiusMax-this.radiusMin)/(e-t);this.radius=(this.value-t)*i+this.radiusMin}},x.prototype.draw=function(){throw"Draw method not initialized for node"},x.prototype.resize=function(){throw"Resize method not initialized for node"},x.prototype.isOverlappingWith=function(t){return this.leftt.left&&this.topt.top},x.prototype._resizeImage=function(){if(!this.width){var t,e;if(this.value){var i=this.imageObj.height/this.imageObj.width;t=this.radius||this.imageObj.width,e=this.radius*i||this.imageObj.height}else t=this.imageObj.width,e=this.imageObj.height;this.width=t,this.height=e}},x.prototype._drawImage=function(t){this._resizeImage(t),this.left=this.x-this.width/2,this.top=this.y-this.height/2;var e;this.imageObj?(t.drawImage(this.imageObj,this.left,this.top,this.width,this.height),e=this.y+this.height/2):e=this.y,this._label(t,this.label,this.x,e,void 0,"top")},x.prototype._resizeBox=function(t){if(!this.width){var e=5,i=this.getTextSize(t);this.width=i.width+2*e,this.height=i.height+2*e}},x.prototype._drawBox=function(t){this._resizeBox(t),this.left=this.x-this.width/2,this.top=this.y-this.height/2,t.strokeStyle=this.selected?this.color.highlight.border:this.color.border,t.fillStyle=this.selected?this.color.highlight.background:this.color.background,t.lineWidth=this.selected?2:1,t.roundRect(this.left,this.top,this.width,this.height,this.radius),t.fill(),t.stroke(),this._label(t,this.label,this.x,this.y)},x.prototype._resizeDatabase=function(t){if(!this.width){var e=5,i=this.getTextSize(t),s=i.width+2*e;this.width=s,this.height=s}},x.prototype._drawDatabase=function(t){this._resizeDatabase(t),this.left=this.x-this.width/2,this.top=this.y-this.height/2,t.strokeStyle=this.selected?this.color.highlight.border:this.color.border,t.fillStyle=this.selected?this.color.highlight.background:this.color.background,t.lineWidth=this.selected?2:1,t.database(this.x-this.width/2,this.y-.5*this.height,this.width,this.height),t.fill(),t.stroke(),this._label(t,this.label,this.x,this.y)},x.prototype._resizeCircle=function(t){if(!this.width){var e=5,i=this.getTextSize(t),s=Math.max(i.width,i.height)+2*e;this.radius=s/2,this.width=s,this.height=s}},x.prototype._drawCircle=function(t){this._resizeCircle(t),this.left=this.x-this.width/2,this.top=this.y-this.height/2,t.strokeStyle=this.selected?this.color.highlight.border:this.color.border,t.fillStyle=this.selected?this.color.highlight.background:this.color.background,t.lineWidth=this.selected?2:1,t.circle(this.x,this.y,this.radius),t.fill(),t.stroke(),this._label(t,this.label,this.x,this.y)},x.prototype._resizeEllipse=function(t){if(!this.width){var e=this.getTextSize(t);this.width=1.5*e.width,this.height=2*e.height,this.widthl;l++)t.fillText(r[l],i,d),d+=h}},x.prototype.getTextSize=function(t){if(void 0!=this.label){t.font=(this.selected?"bold ":"")+this.fontSize+"px "+this.fontFace;for(var e=this.label.split("\n"),i=(this.fontSize+4)*e.length,s=0,n=0,o=e.length;o>n;n++)s=Math.max(s,t.measureText(e[n]).width);return{width:s,height:i}}return{width:0,height:0}},T.prototype.setProperties=function(t,e){if(t)switch(void 0!=t.from&&(this.fromId=t.from),void 0!=t.to&&(this.toId=t.to),void 0!=t.id&&(this.id=t.id),void 0!=t.style&&(this.style=t.style),void 0!=t.label&&(this.label=t.label),this.label&&(this.fontSize=e.edges.fontSize,this.fontFace=e.edges.fontFace,this.fontColor=e.edges.fontColor,void 0!=t.fontColor&&(this.fontColor=t.fontColor),void 0!=t.fontSize&&(this.fontSize=t.fontSize),void 0!=t.fontFace&&(this.fontFace=t.fontFace)),void 0!=t.title&&(this.title=t.title),void 0!=t.width&&(this.width=t.width),void 0!=t.value&&(this.value=t.value),void 0!=t.length&&(this.length=t.length),t.dash&&(void 0!=t.dash.length&&(this.dash.length=t.dash.length),void 0!=t.dash.gap&&(this.dash.gap=t.dash.gap),void 0!=t.dash.altLength&&(this.dash.altLength=t.dash.altLength)),void 0!=t.color&&(this.color=t.color),this.connect(),this.widthFixed=this.widthFixed||void 0!=t.width,this.lengthFixed=this.lengthFixed||void 0!=t.length,this.stiffness=1/this.length,this.style){case"line":this.draw=this._drawLine;break;case"arrow":this.draw=this._drawArrow;break;case"arrow-center":this.draw=this._drawArrowCenter;break;case"dash-line":this.draw=this._drawDashLine;break;default:this.draw=this._drawLine}},T.prototype.connect=function(){this.disconnect(),this.from=this.graph.nodes[this.fromId]||null,this.to=this.graph.nodes[this.toId]||null,this.connected=this.from&&this.to,this.connected?(this.from.attachEdge(this),this.to.attachEdge(this)):(this.from&&this.from.detachEdge(this),this.to&&this.to.detachEdge(this))},T.prototype.disconnect=function(){this.from&&(this.from.detachEdge(this),this.from=null),this.to&&(this.to.detachEdge(this),this.to=null),this.connected=!1},T.prototype.getTitle=function(){return this.title},T.prototype.getValue=function(){return this.value},T.prototype.setValueRange=function(t,e){if(!this.widthFixed&&void 0!==this.value){var i=(this.widthMax-this.widthMin)/(e-t);this.width=(this.value-t)*i+this.widthMin}},T.prototype.draw=function(){throw"Method draw not initialized in edge"},T.prototype.isOverlappingWith=function(t){var e=10,i=this.from.x,s=this.from.y,n=this.to.x,o=this.to.y,r=t.left,a=t.top,h=T._dist(i,s,n,o,r,a);return e>h},T.prototype._drawLine=function(t){t.strokeStyle=this.color,t.lineWidth=this._getLineWidth();var e;if(this.from!=this.to)this._line(t),this.label&&(e=this._pointOnLine(.5),this._label(t,this.label,e.x,e.y));else{var i,s,n=this.length/4,o=this.from;o.width||o.resize(t),o.width>o.height?(i=o.x+o.width/2,s=o.y-n):(i=o.x+n,s=o.y-o.height/2),this._circle(t,i,s,n),e=this._pointOnCircle(i,s,n,.5),this._label(t,this.label,e.x,e.y)}},T.prototype._getLineWidth=function(){return this.from.selected||this.to.selected?Math.min(2*this.width,this.widthMax):this.width},T.prototype._line=function(t){t.beginPath(),t.moveTo(this.from.x,this.from.y),t.lineTo(this.to.x,this.to.y),t.stroke()},T.prototype._circle=function(t,e,i,s){t.beginPath(),t.arc(e,i,s,0,2*Math.PI,!1),t.stroke()},T.prototype._label=function(t,e,i,s){if(e){t.font=(this.from.selected||this.to.selected?"bold ":"")+this.fontSize+"px "+this.fontFace,t.fillStyle="white";var n=t.measureText(e).width,o=this.fontSize,r=i-n/2,a=s-o/2;t.fillRect(r,a,n,o),t.fillStyle=this.fontColor||"black",t.textAlign="left",t.textBaseline="top",t.fillText(e,r,a)}},T.prototype._drawDashLine=function(t){if(t.strokeStyle=this.color,t.lineWidth=this._getLineWidth(),t.beginPath(),t.lineCap="round",void 0!=this.dash.altLength?t.dashedLine(this.from.x,this.from.y,this.to.x,this.to.y,[this.dash.length,this.dash.gap,this.dash.altLength,this.dash.gap]):void 0!=this.dash.length&&void 0!=this.dash.gap?t.dashedLine(this.from.x,this.from.y,this.to.x,this.to.y,[this.dash.length,this.dash.gap]):(t.moveTo(this.from.x,this.from.y),t.lineTo(this.to.x,this.to.y)),t.stroke(),this.label){var e=this._pointOnLine(.5);this._label(t,this.label,e.x,e.y)}},T.prototype._pointOnLine=function(t){return{x:(1-t)*this.from.x+t*this.to.x,y:(1-t)*this.from.y+t*this.to.y}},T.prototype._pointOnCircle=function(t,e,i,s){var n=2*(s-3/8)*Math.PI;return{x:t+i*Math.cos(n),y:e-i*Math.sin(n)}},T.prototype._drawArrowCenter=function(t){var e;if(t.strokeStyle=this.color,t.fillStyle=this.color,t.lineWidth=this._getLineWidth(),this.from!=this.to){this._line(t);var i=Math.atan2(this.to.y-this.from.y,this.to.x-this.from.x),s=10+5*this.width;e=this._pointOnLine(.5),t.arrow(e.x,e.y,i,s),t.fill(),t.stroke(),this.label&&(e=this._pointOnLine(.5),this._label(t,this.label,e.x,e.y))}else{var n,o,r=this.length/4,a=this.from;a.width||a.resize(t),a.width>a.height?(n=a.x+a.width/2,o=a.y-r):(n=a.x+r,o=a.y-a.height/2),this._circle(t,n,o,r);var i=.2*Math.PI,s=10+5*this.width;e=this._pointOnCircle(n,o,r,.5),t.arrow(e.x,e.y,i,s),t.fill(),t.stroke(),this.label&&(e=this._pointOnCircle(n,o,r,.5),this._label(t,this.label,e.x,e.y))}},T.prototype._drawArrow=function(t){t.strokeStyle=this.color,t.fillStyle=this.color,t.lineWidth=this._getLineWidth();var e,i;if(this.from!=this.to){e=Math.atan2(this.to.y-this.from.y,this.to.x-this.from.x);var s=this.to.x-this.from.x,n=this.to.y-this.from.y,o=Math.sqrt(s*s+n*n),r=this.from.distanceToBorder(t,e+Math.PI),a=(o-r)/o,h=a*this.from.x+(1-a)*this.to.x,d=a*this.from.y+(1-a)*this.to.y,l=this.to.distanceToBorder(t,e),p=(o-l)/o,c=(1-p)*this.from.x+p*this.to.x,u=(1-p)*this.from.y+p*this.to.y;if(t.beginPath(),t.moveTo(h,d),t.lineTo(c,u),t.stroke(),i=10+5*this.width,t.arrow(c,u,e,i),t.fill(),t.stroke(),this.label){var f=this._pointOnLine(.5);this._label(t,this.label,f.x,f.y)}}else{var m,g,v,y=this.from,b=this.length/4;y.width||y.resize(t),y.width>y.height?(m=y.x+y.width/2,g=y.y-b,v={x:m,y:y.y,angle:.9*Math.PI}):(m=y.x+b,g=y.y-y.height/2,v={x:y.x,y:g,angle:.6*Math.PI}),t.beginPath(),t.arc(m,g,b,0,2*Math.PI,!1),t.stroke(),i=10+5*this.width,t.arrow(v.x,v.y,v.angle,i),t.fill(),t.stroke(),this.label&&(f=this._pointOnCircle(m,g,b,.5),this._label(t,this.label,f.x,f.y))}},T._dist=function(t,e,i,s,n,o){var r=i-t,a=s-e,h=r*r+a*a,d=((n-t)*r+(o-e)*a)/h; -d>1?d=1:0>d&&(d=0);var l=t+d*r,p=e+d*a,c=l-n,u=p-o;return Math.sqrt(c*c+u*u)},S.prototype.setPosition=function(t,e){this.x=parseInt(t),this.y=parseInt(e)},S.prototype.setText=function(t){this.frame.innerHTML=t},S.prototype.show=function(t){if(void 0===t&&(t=!0),t){var e=this.frame.clientHeight,i=this.frame.clientWidth,s=this.frame.parentNode.clientHeight,n=this.frame.parentNode.clientWidth,o=this.y-e;o+e+this.padding>s&&(o=s-e-this.padding),this.padding>o&&(o=this.padding);var r=this.x;r+i+this.padding>n&&(r=n-i-this.padding),this.padding>r&&(r=this.padding),this.frame.style.left=r+"px",this.frame.style.top=o+"px",this.frame.style.visibility="visible"}else this.hide()},S.prototype.hide=function(){this.frame.style.visibility="hidden"},Groups=function(){this.clear(),this.defaultIndex=0},Groups.DEFAULT=[{border:"#2B7CE9",background:"#97C2FC",highlight:{border:"#2B7CE9",background:"#D2E5FF"}},{border:"#FFA500",background:"#FFFF00",highlight:{border:"#FFA500",background:"#FFFFA3"}},{border:"#FA0A10",background:"#FB7E81",highlight:{border:"#FA0A10",background:"#FFAFB1"}},{border:"#41A906",background:"#7BE141",highlight:{border:"#41A906",background:"#A1EC76"}},{border:"#E129F0",background:"#EB7DF4",highlight:{border:"#E129F0",background:"#F0B3F5"}},{border:"#7C29F0",background:"#AD85E4",highlight:{border:"#7C29F0",background:"#D3BDF0"}},{border:"#C37F00",background:"#FFA807",highlight:{border:"#C37F00",background:"#FFCA66"}},{border:"#4220FB",background:"#6E6EFD",highlight:{border:"#4220FB",background:"#9B9BFD"}},{border:"#FD5A77",background:"#FFC0CB",highlight:{border:"#FD5A77",background:"#FFD1D9"}},{border:"#4AD63A",background:"#C2FABC",highlight:{border:"#4AD63A",background:"#E6FFE3"}}],Groups.prototype.clear=function(){this.groups={},this.groups.length=function(){var t=0;for(var e in this)this.hasOwnProperty(e)&&t++;return t}},Groups.prototype.get=function(t){var e=this.groups[t];if(void 0==e){var i=this.defaultIndex%Groups.DEFAULT.length;this.defaultIndex++,e={},e.color=Groups.DEFAULT[i],this.groups[t]=e}return e},Groups.prototype.add=function(t,e){return this.groups[t]=e,e.color&&(e.color=x.parseColor(e.color)),e},Images=function(){this.images={},this.callback=void 0},Images.prototype.setOnloadCallback=function(t){this.callback=t},Images.prototype.load=function(t){var e=this.images[t];if(void 0==e){var i=this;e=new Image,this.images[t]=e,e.onload=function(){i.callback&&i.callback(this)},e.src=t}return e},M.prototype.setData=function(t){if(t&&t.dot&&(t.nodes||t.edges))throw new SyntaxError('Data must contain either parameter "dot" or parameter pair "nodes" and "edges", but not both.');if(this.setOptions(t&&t.options),t&&t.dot){if(t&&t.dot){var e=N.util.DOTToGraph(t.dot);return this.setData(e),void 0}}else this._setNodes(t&&t.nodes),this._setEdges(t&&t.edges);this.stabilize&&this._doStabilize(),this.start()},M.prototype.setOptions=function(t){if(t){if(void 0!=t.width&&(this.width=t.width),void 0!=t.height&&(this.height=t.height),void 0!=t.stabilize&&(this.stabilize=t.stabilize),void 0!=t.selectable&&(this.selectable=t.selectable),t.edges){for(var e in t.edges)t.edges.hasOwnProperty(e)&&(this.constants.edges[e]=t.edges[e]);void 0!=t.edges.length&&t.nodes&&void 0==t.nodes.distance&&(this.constants.edges.length=t.edges.length,this.constants.nodes.distance=1.25*t.edges.length),t.edges.fontColor||(this.constants.edges.fontColor=t.edges.color),t.edges.dash&&(void 0!=t.edges.dash.length&&(this.constants.edges.dash.length=t.edges.dash.length),void 0!=t.edges.dash.gap&&(this.constants.edges.dash.gap=t.edges.dash.gap),void 0!=t.edges.dash.altLength&&(this.constants.edges.dash.altLength=t.edges.dash.altLength))}if(t.nodes){for(e in t.nodes)t.nodes.hasOwnProperty(e)&&(this.constants.nodes[e]=t.nodes[e]);t.nodes.color&&(this.constants.nodes.color=x.parseColor(t.nodes.color))}if(t.groups)for(var i in t.groups)if(t.groups.hasOwnProperty(i)){var s=t.groups[i];this.groups.add(i,s)}}this.setSize(this.width,this.height),this._setTranslation(this.frame.clientWidth/2,this.frame.clientHeight/2),this._setScale(1)},M.prototype._trigger=function(t,e){O.trigger(this,t,e)},M.prototype._create=function(){for(;this.containerElement.hasChildNodes();)this.containerElement.removeChild(this.containerElement.firstChild);if(this.frame=document.createElement("div"),this.frame.className="graph-frame",this.frame.style.position="relative",this.frame.style.overflow="hidden",this.frame.canvas=document.createElement("canvas"),this.frame.canvas.style.position="relative",this.frame.appendChild(this.frame.canvas),!this.frame.canvas.getContext){var t=document.createElement("DIV");t.style.color="red",t.style.fontWeight="bold",t.style.padding="10px",t.innerHTML="Error: your browser does not support HTML canvas",this.frame.canvas.appendChild(t)}var e=this,i=function(t){e._onMouseDown(t)},s=function(t){e._onMouseMoveTitle(t)},n=function(t){e._onMouseWheel(t)},o=function(t){e._onTouchStart(t)};N.util.addEventListener(this.frame.canvas,"mousedown",i),N.util.addEventListener(this.frame.canvas,"mousemove",s),N.util.addEventListener(this.frame.canvas,"mousewheel",n),N.util.addEventListener(this.frame.canvas,"touchstart",o),this.containerElement.appendChild(this.frame)},M.prototype._onMouseDown=function(t){if(t=t||window.event,this.selectable&&(this.leftButtonDown&&this._onMouseUp(t),this.leftButtonDown=t.which?1==t.which:1==t.button,this.leftButtonDown||this.touchDown)){var e=this;this.onmousemove||(this.onmousemove=function(t){e._onMouseMove(t)},N.util.addEventListener(document,"mousemove",e.onmousemove)),this.onmouseup||(this.onmouseup=function(t){e._onMouseUp(t)},N.util.addEventListener(document,"mouseup",e.onmouseup)),N.util.preventDefault(t),this.startMouseX=D.getPageX(t),this.startMouseY=D.getPageY(t),this.startFrameLeft=N.util.getAbsoluteLeft(this.frame.canvas),this.startFrameTop=N.util.getAbsoluteTop(this.frame.canvas),this.startTranslation=this._getTranslation(),this.ctrlKeyDown=t.ctrlKey,this.shiftKeyDown=t.shiftKey;var i={left:this._xToCanvas(this.startMouseX-this.startFrameLeft),top:this._yToCanvas(this.startMouseY-this.startFrameTop),right:this._xToCanvas(this.startMouseX-this.startFrameLeft),bottom:this._yToCanvas(this.startMouseY-this.startFrameTop)},s=this._getNodesOverlappingWith(i);if(this.startClickedObj=s.length>0?s[s.length-1]:void 0,this.startClickedObj){var n=this.nodes[this.startClickedObj];this.startClickedObj.xFixed=n.xFixed,this.startClickedObj.yFixed=n.yFixed,n.xFixed=!0,n.yFixed=!0,this.ctrlKeyDown&&n.isSelected()?this._unselectNodes([this.startClickedObj]):this._selectNodes([this.startClickedObj],this.ctrlKeyDown),this.moving||this._redraw()}else this.shiftKeyDown||(this.moved=!1)}},M.prototype._onMouseMove=function(t){if(t=t||window.event,this.selectable){var e=D.getPageX(t),i=D.getPageY(t);if(this.mouseX=e,this.mouseY=i,this.startClickedObj){var s=this.nodes[this.startClickedObj];this.startClickedObj.xFixed||(s.x=this._xToCanvas(e-this.startFrameLeft)),this.startClickedObj.yFixed||(s.y=this._yToCanvas(i-this.startFrameTop)),this.moving||(this.moving=!0,this.start())}else if(this.shiftKeyDown){void 0==this.frame.selRect&&(this.frame.selRect=document.createElement("DIV"),this.frame.appendChild(this.frame.selRect),this.frame.selRect.style.position="absolute",this.frame.selRect.style.border="1px dashed red");var n=Math.min(this.startMouseX,e)-this.startFrameLeft,o=Math.min(this.startMouseY,i)-this.startFrameTop,r=Math.max(this.startMouseX,e)-this.startFrameLeft,a=Math.max(this.startMouseY,i)-this.startFrameTop;this.frame.selRect.style.left=n+"px",this.frame.selRect.style.top=o+"px",this.frame.selRect.style.width=r-n+"px",this.frame.selRect.style.height=a-o+"px"}else{var h=e-this.startMouseX,d=i-this.startMouseY;this._setTranslation(this.startTranslation.x+h,this.startTranslation.y+d),this._redraw(),this.moved=!0}N.util.preventDefault(t)}},M.prototype._onMouseUp=function(t){if(t=t||window.event,this.selectable){this.onmousemove&&(N.util.removeEventListener(document,"mousemove",this.onmousemove),this.onmousemove=void 0),this.onmouseup&&(N.util.removeEventListener(document,"mouseup",this.onmouseup),this.onmouseup=void 0),N.util.preventDefault(t);var e=D.getPageX(t)||this.mouseX||0,i=D.getPageY(t)||this.mouseY||0,s=t?t.ctrlKey:window.event.ctrlKey;if(this.startClickedObj){var n=this.nodes[this.startClickedObj];n.xFixed=this.startClickedObj.xFixed,n.yFixed=this.startClickedObj.yFixed}else if(this.shiftKeyDown){var o={left:this._xToCanvas(Math.min(this.startMouseX,e)-this.startFrameLeft),top:this._yToCanvas(Math.min(this.startMouseY,i)-this.startFrameTop),right:this._xToCanvas(Math.max(this.startMouseX,e)-this.startFrameLeft),bottom:this._yToCanvas(Math.max(this.startMouseY,i)-this.startFrameTop)},r=this._getNodesOverlappingWith(o);this._selectNodes(r,s),this.redraw(),this.frame.selRect&&(this.frame.removeChild(this.frame.selRect),this.frame.selRect=void 0)}else this.ctrlKeyDown||this.moved||(this._unselectNodes(),this._redraw());this.leftButtonDown=!1,this.ctrlKeyDown=!1}},M.prototype._onMouseWheel=function(t){t=t||window.event;var e=D.getPageX(t),i=D.getPageY(t),s=0;if(t.wheelDelta?s=t.wheelDelta/120:t.detail&&(s=-t.detail/3),s){var n=s/10;0>s&&(n/=1-n);var o=this._getScale(),r=o*(1+n);.01>r&&(r=.01),r>10&&(r=10);var a=N.util.getAbsoluteLeft(this.frame.canvas),h=N.util.getAbsoluteTop(this.frame.canvas),d=e-a,l=i-h,p=this._getTranslation(),c=r/o,u=(1-c)*d+p.x*c,f=(1-c)*l+p.y*c;this._setScale(r),this._setTranslation(u,f),this._redraw()}N.util.preventDefault(t)},M.prototype._onMouseMoveTitle=function(t){t=t||window.event;var e=D.getPageX(t),i=D.getPageY(t);this.startFrameLeft=this.startFrameLeft||N.util.getAbsoluteLeft(this.frame.canvas),this.startFrameTop=this.startFrameTop||N.util.getAbsoluteTop(this.frame.canvas);var s=e-this.startFrameLeft,n=i-this.startFrameTop;this.popupNode&&this._checkHidePopup(s,n);var o=this,r=function(){o._checkShowPopup(s,n)};this.popupTimer&&clearInterval(this.popupTimer),this.leftButtonDown||(this.popupTimer=setTimeout(r,300))},M.prototype._checkShowPopup=function(t,e){var i,s={left:this._xToCanvas(t),top:this._yToCanvas(e),right:this._xToCanvas(t),bottom:this._yToCanvas(e)},n=this.popupNode;if(void 0==this.popupNode){var o=this.nodes;for(i in o)if(o.hasOwnProperty(i)){var r=o[i];if(void 0!=r.getTitle()&&r.isOverlappingWith(s)){this.popupNode=r;break}}}if(void 0==this.popupNode){var a=this.edges;for(i in a)if(a.hasOwnProperty(i)){var h=a[i];if(h.connected&&void 0!=h.getTitle()&&h.isOverlappingWith(s)){this.popupNode=h;break}}}if(this.popupNode){if(this.popupNode!=n){var d=this;d.popup||(d.popup=new S(d.frame)),d.popup.setPosition(t-3,e-3),d.popup.setText(d.popupNode.getTitle()),d.popup.show()}}else this.popup&&this.popup.hide()},M.prototype._checkHidePopup=function(t,e){var i={left:t,top:e,right:t,bottom:e};this.popupNode&&this.popupNode.isOverlappingWith(i)||(this.popupNode=void 0,this.popup&&this.popup.hide())},M.prototype._onTouchStart=function(t){if(N.util.preventDefault(t),!this.touchDown){this.touchDown=!0;var e=this;this.ontouchmove||(this.ontouchmove=function(t){e._onTouchMove(t)},N.util.addEventListener(document,"touchmove",this.ontouchmove)),this.ontouchend||(this.ontouchend=function(t){e._onTouchEnd(t)},N.util.addEventListener(document,"touchend",this.ontouchend)),this._onMouseDown(t)}},M.prototype._onTouchMove=function(t){N.util.preventDefault(t),this._onMouseMove(t)},M.prototype._onTouchEnd=function(t){N.util.preventDefault(t),this.touchDown=!1,this.ontouchmove&&(N.util.removeEventListener(document,"touchmove",this.ontouchmove),this.ontouchmove=void 0),this.ontouchend&&(N.util.removeEventListener(document,"touchend",this.ontouchend),this.ontouchend=void 0),this._onMouseUp(t)},M.prototype._unselectNodes=function(t,e){var i,s,n,o=!1;if(t)for(i=0,s=t.length;s>i;i++){n=t[i],this.nodes[n].unselect();for(var r=0;this.selection.length>r;)this.selection[r]==n?(this.selection.splice(r,1),o=!0):r++}else if(this.selection&&this.selection.length){for(i=0,s=this.selection.length;s>i;i++)n=this.selection[i],this.nodes[n].unselect(),o=!0;this.selection=[]}return!o||1!=e&&void 0!=e||this._trigger("select"),o},M.prototype._selectNodes=function(t,e){var i,s,n=!1,o=!0;if(t.length!=this.selection.length)o=!1;else for(i=0,s=Math.min(t.length,this.selection.length);s>i;i++)if(t[i]!=this.selection[i]){o=!1;break}if(o)return n;if(void 0==e||0==e){var r=!1;n=this._unselectNodes(void 0,r)}for(i=0,s=t.length;s>i;i++){var a=t[i],h=-1!=this.selection.indexOf(a);h||(this.nodes[a].select(),this.selection.push(a),n=!0)}return n&&this._trigger("select"),n},M.prototype._getNodesOverlappingWith=function(t){var e=this.nodes,i=[];for(var s in e)e.hasOwnProperty(s)&&e[s].isOverlappingWith(t)&&i.push(s);return i},M.prototype.getSelection=function(){return this.selection.concat([])},M.prototype.setSelection=function(t){var e,i,s;if(void 0==t.length)throw"Selection must be an array with ids";for(e=0,i=this.selection.length;i>e;e++)s=this.selection[e],this.nodes[s].unselect();for(this.selection=[],e=0,i=t.length;i>e;e++){s=t[e];var n=this.nodes[s];if(!n)throw new RangeError('Node with id "'+s+'" not found');n.select(),this.selection.push(s)}this.redraw()},M.prototype._updateSelection=function(){for(var t=0;this.selection.length>t;){var e=this.selection[t];this.nodes[e]?t++:this.selection.splice(t,1)}},M.prototype._getConnectionCount=function(t){function e(t){for(var e=[],i=0,s=t.length;s>i;i++)for(var n=t[i],o=n.edges,r=0,a=o.length;a>r;r++){var h=o[r],d=null;h.from==n?d=h.to:h.to==n&&(d=h.from);var l,p;if(d)for(l=0,p=t.length;p>l;l++)if(t[l]==d){d=null;break}if(d)for(l=0,p=e.length;p>l;l++)if(e[l]==d){d=null;break}d&&e.push(d)}return e}void 0==t&&(t=1);var i=[],s=this.nodes;for(var n in s)if(s.hasOwnProperty(n)){for(var o=[s[n]],r=0;t>r;r++)o=o.concat(e(o));i.push(o)}for(var a=[],h=0,d=i.length;d>h;h++)a.push(i[h].length);return a},M.prototype.setSize=function(t,e){this.frame.style.width=t,this.frame.style.height=e,this.frame.canvas.style.width="100%",this.frame.canvas.style.height="100%",this.frame.canvas.width=this.frame.canvas.clientWidth,this.frame.canvas.height=this.frame.canvas.clientHeight},M.prototype._setNodes=function(t){var e=this.nodesData;if(t instanceof o||t instanceof r)this.nodesData=t;else if(t instanceof Array)this.nodesData=new o,this.nodesData.add(t);else{if(t)throw new TypeError("Array or DataSet expected");this.nodesData=new o}if(e&&D.forEach(this.nodesListeners,function(t,i){e.unsubscribe(i,t)}),this.nodes={},this.nodesData){var i=this;D.forEach(this.nodesListeners,function(t,e){i.nodesData.subscribe(e,t)});var s=this.nodesData.getIds();this._addNodes(s)}this._updateSelection()},M.prototype._addNodes=function(t){for(var e,i=0,s=t.length;s>i;i++){e=t[i];var n=this.nodesData.get(e),o=new x(n,this.images,this.groups,this.constants);if(this.nodes[e]=o,!o.isFixed()){var r=2*this.constants.edges.length,a=t.length,h=2*Math.PI*(i/a);o.x=r*Math.cos(h),o.y=r*Math.sin(h),this.moving=!0}}this._reconnectEdges(),this._updateValueRange(this.nodes)},M.prototype._updateNodes=function(t){for(var e=this.nodes,i=this.nodesData,s=0,n=t.length;n>s;s++){var o=t[s],r=e[o],a=i.get(o);r?r.setProperties(a,this.constants):(r=new x(properties,this.images,this.groups,this.constants),e[o]=r,r.isFixed()||(this.moving=!0))}this._reconnectEdges(),this._updateValueRange(e)},M.prototype._removeNodes=function(t){for(var e=this.nodes,i=0,s=t.length;s>i;i++){var n=t[i];delete e[n]}this._reconnectEdges(),this._updateSelection(),this._updateValueRange(e)},M.prototype._setEdges=function(t){var e=this.edgesData;if(t instanceof o||t instanceof r)this.edgesData=t;else if(t instanceof Array)this.edgesData=new o,this.edgesData.add(t);else{if(t)throw new TypeError("Array or DataSet expected");this.edgesData=new o}if(e&&D.forEach(this.edgesListeners,function(t,i){e.unsubscribe(i,t)}),this.edges={},this.edgesData){var i=this;D.forEach(this.edgesListeners,function(t,e){i.edgesData.subscribe(e,t)});var s=this.edgesData.getIds();this._addEdges(s)}this._reconnectEdges()},M.prototype._addEdges=function(t){for(var e=this.edges,i=this.edgesData,s=0,n=t.length;n>s;s++){var o=t[s],r=e[o];r&&r.disconnect();var a=i.get(o);e[o]=new T(a,this,this.constants)}this.moving=!0,this._updateValueRange(e)},M.prototype._updateEdges=function(t){for(var e=this.edges,i=this.edgesData,s=0,n=t.length;n>s;s++){var o=t[s],r=i.get(o),a=e[o];a?(a.disconnect(),a.setProperties(r,this.constants),a.connect()):(a=new T(r,this,this.constants),this.edges[o]=a)}this.moving=!0,this._updateValueRange(e)},M.prototype._removeEdges=function(t){for(var e=this.edges,i=0,s=t.length;s>i;i++){var n=t[i],o=e[n];o&&(o.disconnect(),delete e[n])}this.moving=!0,this._updateValueRange(e)},M.prototype._reconnectEdges=function(){var t,e=this.nodes,i=this.edges;for(t in e)e.hasOwnProperty(t)&&(e[t].edges=[]);for(t in i)if(i.hasOwnProperty(t)){var s=i[t];s.from=null,s.to=null,s.connect()}},M.prototype._updateValueRange=function(t){var e,i=void 0,s=void 0;for(e in t)if(t.hasOwnProperty(e)){var n=t[e].getValue();void 0!==n&&(i=void 0===i?n:Math.min(n,i),s=void 0===s?n:Math.max(n,s))}if(void 0!==i&&void 0!==s)for(e in t)t.hasOwnProperty(e)&&t[e].setValueRange(i,s)},M.prototype.redraw=function(){this.setSize(this.width,this.height),this._redraw()},M.prototype._redraw=function(){var t=this.frame.canvas.getContext("2d"),e=this.frame.canvas.width,i=this.frame.canvas.height;t.clearRect(0,0,e,i),t.save(),t.translate(this.translation.x,this.translation.y),t.scale(this.scale,this.scale),this._drawEdges(t),this._drawNodes(t),t.restore()},M.prototype._setTranslation=function(t,e){void 0===this.translation&&(this.translation={x:0,y:0}),void 0!==t&&(this.translation.x=t),void 0!==e&&(this.translation.y=e)},M.prototype._getTranslation=function(){return{x:this.translation.x,y:this.translation.y}},M.prototype._setScale=function(t){this.scale=t},M.prototype._getScale=function(){return this.scale},M.prototype._xToCanvas=function(t){return(t-this.translation.x)/this.scale},M.prototype._canvasToX=function(t){return t*this.scale+this.translation.x},M.prototype._yToCanvas=function(t){return(t-this.translation.y)/this.scale},M.prototype._canvasToY=function(t){return t*this.scale+this.translation.y},M.prototype._drawNodes=function(t){var e=this.nodes,i=[];for(var s in e)e.hasOwnProperty(s)&&(e[s].isSelected()?i.push(s):e[s].draw(t));for(var n=0,o=i.length;o>n;n++)e[i[n]].draw(t)},M.prototype._drawEdges=function(t){var e=this.edges;for(var i in e)if(e.hasOwnProperty(i)){var s=e[i];s.connected&&e[i].draw(t)}},M.prototype._doStabilize=function(){new Date;for(var t=0,e=this.constants.minVelocity,i=!1;!i&&this.constants.maxIterations>t;)this._calculateForces(),this._discreteStepNodes(),i=!this._isMoving(e),t++;new Date},M.prototype._calculateForces=function(){var t,e,i,s,n,o,r,a,h,d,l,p=this.nodes,c=this.edges,u=.01,f=this.frame.canvas.clientWidth/2,m=this.frame.canvas.clientHeight/2;for(t in p)if(p.hasOwnProperty(t)){var g=p[t];e=f-g.x,i=m-g.y,s=Math.atan2(i,e),o=Math.cos(s)*u,r=Math.sin(s)*u,g._setForce(o,r)}var v=this.constants.nodes.distance,y=10;for(var b in p)if(p.hasOwnProperty(b)){var w=p[b];for(var _ in p)if(p.hasOwnProperty(_)){var x=p[_];e=x.x-w.x,i=x.y-w.y,n=Math.sqrt(e*e+i*i),s=Math.atan2(i,e),a=1/(1+Math.exp((n/v-1)*y)),o=Math.cos(s)*a,r=Math.sin(s)*a,w._addForce(-o,-r),x._addForce(o,r)}}for(t in c)if(c.hasOwnProperty(t)){var T=c[t];T.connected&&(e=T.to.x-T.from.x,i=T.to.y-T.from.y,l=T.length,d=Math.sqrt(e*e+i*i),s=Math.atan2(i,e),h=T.stiffness*(l-d),o=Math.cos(s)*h,r=Math.sin(s)*h,T.from._addForce(-o,-r),T.to._addForce(o,r))}},M.prototype._isMoving=function(t){var e=this.nodes;for(var i in e)if(e.hasOwnProperty(i)&&e[i].isMoving(t))return!0;return!1},M.prototype._discreteStepNodes=function(){var t=this.refreshRate/1e3,e=this.nodes;for(var i in e)e.hasOwnProperty(i)&&e[i].discreteStep(t)},M.prototype.start=function(){if(this.moving){this._calculateForces(),this._discreteStepNodes();var t=this.constants.minVelocity;this.moving=this._isMoving(t)}if(this.moving){if(!this.timer){var e=this;this.timer=window.setTimeout(function(){e.timer=void 0,e.start(),e._redraw()},this.refreshRate)}}else this._redraw()},M.prototype.stop=function(){this.timer&&(window.clearInterval(this.timer),this.timer=void 0)};var N={util:D,events:O,Controller:d,DataSet:o,DataView:r,Range:h,Stack:a,TimeStep:TimeStep,EventBus:n,components:{items:{Item:m,ItemBox:g,ItemPoint:v,ItemRange:y},Component:l,Panel:p,RootPanel:c,ItemSet:f,TimeAxis:u},graph:{Node:x,Edge:T,Popup:S,Groups:Groups,Images:Images},Timeline:_,Graph:M};s!==void 0&&(s=N),i!==void 0&&i.exports!==void 0&&(i.exports=N),"function"==typeof t&&t(function(){return N}),"undefined"!=typeof window&&(window.vis=N),D.loadCss("/* vis.js stylesheet */\n.vis.timeline {\n}\n\n\n.vis.timeline.rootpanel {\n position: relative;\n overflow: hidden;\n\n border: 1px solid #bfbfbf;\n -moz-box-sizing: border-box;\n box-sizing: border-box;\n}\n\n.vis.timeline .panel {\n position: absolute;\n overflow: hidden;\n}\n\n\n.vis.timeline .groupset {\n position: absolute;\n padding: 0;\n margin: 0;\n}\n\n.vis.timeline .labels {\n position: absolute;\n top: 0;\n left: 0;\n width: 100%;\n height: 100%;\n\n padding: 0;\n margin: 0;\n\n border-right: 1px solid #bfbfbf;\n box-sizing: border-box;\n -moz-box-sizing: border-box;\n}\n\n.vis.timeline .labels .label {\n position: absolute;\n left: 0;\n top: 0;\n width: 100%;\n border-bottom: 1px solid #bfbfbf;\n color: #4d4d4d;\n}\n\n.vis.timeline .labels .label .inner {\n display: inline-block;\n padding: 5px;\n}\n\n\n.vis.timeline .itemset {\n position: absolute;\n padding: 0;\n margin: 0;\n overflow: hidden;\n}\n\n.vis.timeline .background {\n}\n\n.vis.timeline .foreground {\n}\n\n.vis.timeline .itemset-axis {\n position: absolute;\n}\n\n.vis.timeline .groupset .itemset-axis {\n border-top: 1px solid #bfbfbf;\n}\n\n/* TODO: with orientation=='bottom', this will more or less overlap with timeline axis\n.vis.timeline .groupset .itemset-axis:last-child {\n border-top: none;\n}\n*/\n\n\n.vis.timeline .item {\n position: absolute;\n color: #1A1A1A;\n border-color: #97B0F8;\n background-color: #D5DDF6;\n display: inline-block;\n}\n\n.vis.timeline .item.selected {\n border-color: #FFC200;\n background-color: #FFF785;\n z-index: 999;\n}\n\n.vis.timeline .item.cluster {\n /* TODO: use another color or pattern? */\n background: #97B0F8 url('img/cluster_bg.png');\n color: white;\n}\n.vis.timeline .item.cluster.point {\n border-color: #D5DDF6;\n}\n\n.vis.timeline .item.box {\n text-align: center;\n border-style: solid;\n border-width: 1px;\n border-radius: 5px;\n -moz-border-radius: 5px; /* For Firefox 3.6 and older */\n}\n\n.vis.timeline .item.point {\n background: none;\n}\n\n.vis.timeline .dot {\n border: 5px solid #97B0F8;\n position: absolute;\n border-radius: 5px;\n -moz-border-radius: 5px; /* For Firefox 3.6 and older */\n}\n\n.vis.timeline .item.range {\n overflow: hidden;\n border-style: solid;\n border-width: 1px;\n border-radius: 2px;\n -moz-border-radius: 2px; /* For Firefox 3.6 and older */\n}\n\n.vis.timeline .item.range .drag-left {\n cursor: w-resize;\n z-index: 1000;\n}\n\n.vis.timeline .item.range .drag-right {\n cursor: e-resize;\n z-index: 1000;\n}\n\n.vis.timeline .item.range .content {\n position: relative;\n display: inline-block;\n}\n\n.vis.timeline .item.line {\n position: absolute;\n width: 0;\n border-left-width: 1px;\n border-left-style: solid;\n}\n\n.vis.timeline .item .content {\n margin: 5px;\n white-space: nowrap;\n overflow: hidden;\n}\n\n.vis.timeline .axis {\n position: relative;\n}\n\n.vis.timeline .axis .text {\n position: absolute;\n color: #4d4d4d;\n padding: 3px;\n white-space: nowrap;\n}\n\n.vis.timeline .axis .text.measure {\n position: absolute;\n padding-left: 0;\n padding-right: 0;\n margin-left: 0;\n margin-right: 0;\n visibility: hidden;\n}\n\n.vis.timeline .axis .grid.vertical {\n position: absolute;\n width: 0;\n border-right: 1px solid;\n}\n\n.vis.timeline .axis .grid.horizontal {\n position: absolute;\n left: 0;\n width: 100%;\n height: 0;\n border-bottom: 1px solid;\n}\n\n.vis.timeline .axis .grid.minor {\n border-color: #e5e5e5;\n}\n\n.vis.timeline .axis .grid.major {\n border-color: #bfbfbf;\n}\n\n")})()},{moment:2}],2:[function(e,i){(function(){(function(s){function n(t,e){return function(i){return p(t.call(this,i),e)}}function o(t){return function(e){return this.lang().ordinal(t.call(this,e))}}function r(){}function a(t){d(this,t)}function h(t){var e=this._data={},i=t.years||t.year||t.y||0,s=t.months||t.month||t.M||0,n=t.weeks||t.week||t.w||0,o=t.days||t.day||t.d||0,r=t.hours||t.hour||t.h||0,a=t.minutes||t.minute||t.m||0,h=t.seconds||t.second||t.s||0,d=t.milliseconds||t.millisecond||t.ms||0;this._milliseconds=d+1e3*h+6e4*a+36e5*r,this._days=o+7*n,this._months=s+12*i,e.milliseconds=d%1e3,h+=l(d/1e3),e.seconds=h%60,a+=l(h/60),e.minutes=a%60,r+=l(a/60),e.hours=r%24,o+=l(r/24),o+=7*n,e.days=o%30,s+=l(o/30),e.months=s%12,i+=l(s/12),e.years=i}function d(t,e){for(var i in e)e.hasOwnProperty(i)&&(t[i]=e[i]);return t}function l(t){return 0>t?Math.ceil(t):Math.floor(t)}function p(t,e){for(var i=t+"";e>i.length;)i="0"+i;return i}function c(t,e,i){var s,n=e._milliseconds,o=e._days,r=e._months;n&&t._d.setTime(+t+n*i),o&&t.date(t.date()+o*i),r&&(s=t.date(),t.date(1).month(t.month()+r*i).date(Math.min(s,t.daysInMonth())))}function u(t){return"[object Array]"===Object.prototype.toString.call(t)}function f(t,e){var i,s=Math.min(t.length,e.length),n=Math.abs(t.length-e.length),o=0;for(i=0;s>i;i++)~~t[i]!==~~e[i]&&o++;return o+n}function m(t,e){return e.abbr=t,z[t]||(z[t]=new r),z[t].set(e),z[t]}function g(t){return t?(!z[t]&&H&&e("./lang/"+t),z[t]):I.fn._lang}function v(t){return t.match(/\[.*\]/)?t.replace(/^\[|\]$/g,""):t.replace(/\\/g,"")}function y(t){var e,i,s=t.match(j);for(e=0,i=s.length;i>e;e++)s[e]=ae[s[e]]?ae[s[e]]:v(s[e]);return function(n){var o="";for(e=0;i>e;e++)o+="function"==typeof s[e].call?s[e].call(n,t):s[e];return o}}function b(t,e){function i(e){return t.lang().longDateFormat(e)||e}for(var s=5;s--&&U.test(e);)e=e.replace(U,i);return ne[e]||(ne[e]=y(e)),ne[e](t)}function w(t){switch(t){case"DDDD":return q;case"YYYY":return V;case"YYYYY":return X;case"S":case"SS":case"SSS":case"DDD":return B;case"MMM":case"MMMM":case"dd":case"ddd":case"dddd":case"a":case"A":return K;case"X":return J;case"Z":case"ZZ":return G;case"T":return Z;case"MM":case"DD":case"YY":case"HH":case"hh":case"mm":case"ss":case"M":case"D":case"d":case"H":case"h":case"m":case"s":return W;default:return RegExp(t.replace("\\",""))}}function _(t,e,i){var s,n=i._a;switch(t){case"M":case"MM":n[1]=null==e?0:~~e-1;break;case"MMM":case"MMMM":s=g(i._l).monthsParse(e),null!=s?n[1]=s:i._isValid=!1;break;case"D":case"DD":case"DDD":case"DDDD":null!=e&&(n[2]=~~e);break;case"YY":n[0]=~~e+(~~e>68?1900:2e3);break;case"YYYY":case"YYYYY":n[0]=~~e;break;case"a":case"A":i._isPm="pm"===(e+"").toLowerCase();break;case"H":case"HH":case"h":case"hh":n[3]=~~e;break;case"m":case"mm":n[4]=~~e;break;case"s":case"ss":n[5]=~~e;break;case"S":case"SS":case"SSS":n[6]=~~(1e3*("0."+e));break;case"X":i._d=new Date(1e3*parseFloat(e));break;case"Z":case"ZZ":i._useUTC=!0,s=(e+"").match(ee),s&&s[1]&&(i._tzh=~~s[1]),s&&s[2]&&(i._tzm=~~s[2]),s&&"+"===s[0]&&(i._tzh=-i._tzh,i._tzm=-i._tzm)}null==e&&(i._isValid=!1)}function x(t){var e,i,s=[];if(!t._d){for(e=0;7>e;e++)t._a[e]=s[e]=null==t._a[e]?2===e?1:0:t._a[e];s[3]+=t._tzh||0,s[4]+=t._tzm||0,i=new Date(0),t._useUTC?(i.setUTCFullYear(s[0],s[1],s[2]),i.setUTCHours(s[3],s[4],s[5],s[6])):(i.setFullYear(s[0],s[1],s[2]),i.setHours(s[3],s[4],s[5],s[6])),t._d=i}}function T(t){var e,i,s=t._f.match(j),n=t._i;for(t._a=[],e=0;s.length>e;e++)i=(w(s[e]).exec(n)||[])[0],i&&(n=n.slice(n.indexOf(i)+i.length)),ae[s[e]]&&_(s[e],i,t);t._isPm&&12>t._a[3]&&(t._a[3]+=12),t._isPm===!1&&12===t._a[3]&&(t._a[3]=0),x(t)}function S(t){for(var e,i,s,n,o=99;t._f.length;){if(e=d({},t),e._f=t._f.pop(),T(e),i=new a(e),i.isValid()){s=i;break}n=f(e._a,i.toArray()),o>n&&(o=n,s=i)}d(t,s)}function M(t){var e,i=t._i;if(Q.exec(i)){for(t._f="YYYY-MM-DDT",e=0;4>e;e++)if(te[e][1].exec(i)){t._f+=te[e][0];break}G.exec(i)&&(t._f+=" Z"),T(t)}else t._d=new Date(i)}function E(t){var e=t._i,i=R.exec(e);e===s?t._d=new Date:i?t._d=new Date(+i[1]):"string"==typeof e?M(t):u(e)?(t._a=e.slice(0),x(t)):t._d=e instanceof Date?new Date(+e):new Date(e)}function D(t,e,i,s,n){return n.relativeTime(e||1,!!i,t,s)}function C(t,e,i){var s=Y(Math.abs(t)/1e3),n=Y(s/60),o=Y(n/60),r=Y(o/24),a=Y(r/365),h=45>s&&["s",s]||1===n&&["m"]||45>n&&["mm",n]||1===o&&["h"]||22>o&&["hh",o]||1===r&&["d"]||25>=r&&["dd",r]||45>=r&&["M"]||345>r&&["MM",Y(r/30)]||1===a&&["y"]||["yy",a];return h[2]=e,h[3]=t>0,h[4]=i,D.apply({},h)}function L(t,e,i){var s=i-e,n=i-t.day();return n>s&&(n-=7),s-7>n&&(n+=7),Math.ceil(I(t).add("d",n).dayOfYear()/7)}function O(t){var e=t._i,i=t._f;return null===e||""===e?null:("string"==typeof e&&(t._i=e=g().preparse(e)),I.isMoment(e)?(t=d({},e),t._d=new Date(+e._d)):i?u(i)?S(t):T(t):E(t),new a(t))}function N(t,e){I.fn[t]=I.fn[t+"s"]=function(t){var i=this._isUTC?"UTC":"";return null!=t?(this._d["set"+i+e](t),this):this._d["get"+i+e]()}}function A(t){I.duration.fn[t]=function(){return this._data[t]}}function k(t,e){I.duration.fn["as"+t]=function(){return+this/e}}for(var I,F,P="2.0.0",Y=Math.round,z={},H=i!==s&&i.exports,R=/^\/?Date\((\-?\d+)/i,j=/(\[[^\[]*\])|(\\)?(Mo|MM?M?M?|Do|DDDo|DD?D?D?|ddd?d?|do?|w[o|w]?|W[o|W]?|YYYYY|YYYY|YY|a|A|hh?|HH?|mm?|ss?|SS?S?|X|zz?|ZZ?|.)/g,U=/(\[[^\[]*\])|(\\)?(LT|LL?L?L?|l{1,4})/g,W=/\d\d?/,B=/\d{1,3}/,q=/\d{3}/,V=/\d{1,4}/,X=/[+\-]?\d{1,6}/,K=/[0-9]*[a-z\u00A0-\u05FF\u0700-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF]+|[\u0600-\u06FF]+\s*?[\u0600-\u06FF]+/i,G=/Z|[\+\-]\d\d:?\d\d/i,Z=/T/i,J=/[\+\-]?\d+(\.\d{1,3})?/,Q=/^\s*\d{4}-\d\d-\d\d((T| )(\d\d(:\d\d(:\d\d(\.\d\d?\d?)?)?)?)?([\+\-]\d\d:?\d\d)?)?/,$="YYYY-MM-DDTHH:mm:ssZ",te=[["HH:mm:ss.S",/(T| )\d\d:\d\d:\d\d\.\d{1,3}/],["HH:mm:ss",/(T| )\d\d:\d\d:\d\d/],["HH:mm",/(T| )\d\d:\d\d/],["HH",/(T| )\d\d/]],ee=/([\+\-]|\d\d)/gi,ie="Month|Date|Hours|Minutes|Seconds|Milliseconds".split("|"),se={Milliseconds:1,Seconds:1e3,Minutes:6e4,Hours:36e5,Days:864e5,Months:2592e6,Years:31536e6},ne={},oe="DDD w W M D d".split(" "),re="M D H h m s w W".split(" "),ae={M:function(){return this.month()+1},MMM:function(t){return this.lang().monthsShort(this,t)},MMMM:function(t){return this.lang().months(this,t)},D:function(){return this.date()},DDD:function(){return this.dayOfYear()},d:function(){return this.day()},dd:function(t){return this.lang().weekdaysMin(this,t)},ddd:function(t){return this.lang().weekdaysShort(this,t)},dddd:function(t){return this.lang().weekdays(this,t)},w:function(){return this.week()},W:function(){return this.isoWeek()},YY:function(){return p(this.year()%100,2)},YYYY:function(){return p(this.year(),4)},YYYYY:function(){return p(this.year(),5)},a:function(){return this.lang().meridiem(this.hours(),this.minutes(),!0)},A:function(){return this.lang().meridiem(this.hours(),this.minutes(),!1)},H:function(){return this.hours()},h:function(){return this.hours()%12||12},m:function(){return this.minutes()},s:function(){return this.seconds()},S:function(){return~~(this.milliseconds()/100)},SS:function(){return p(~~(this.milliseconds()/10),2)},SSS:function(){return p(this.milliseconds(),3)},Z:function(){var t=-this.zone(),e="+";return 0>t&&(t=-t,e="-"),e+p(~~(t/60),2)+":"+p(~~t%60,2)},ZZ:function(){var t=-this.zone(),e="+";return 0>t&&(t=-t,e="-"),e+p(~~(10*t/6),4)},X:function(){return this.unix()}};oe.length;)F=oe.pop(),ae[F+"o"]=o(ae[F]);for(;re.length;)F=re.pop(),ae[F+F]=n(ae[F],2);for(ae.DDDD=n(ae.DDD,3),r.prototype={set:function(t){var e,i;for(i in t)e=t[i],"function"==typeof e?this[i]=e:this["_"+i]=e -},_months:"January_February_March_April_May_June_July_August_September_October_November_December".split("_"),months:function(t){return this._months[t.month()]},_monthsShort:"Jan_Feb_Mar_Apr_May_Jun_Jul_Aug_Sep_Oct_Nov_Dec".split("_"),monthsShort:function(t){return this._monthsShort[t.month()]},monthsParse:function(t){var e,i,s;for(this._monthsParse||(this._monthsParse=[]),e=0;12>e;e++)if(this._monthsParse[e]||(i=I([2e3,e]),s="^"+this.months(i,"")+"|^"+this.monthsShort(i,""),this._monthsParse[e]=RegExp(s.replace(".",""),"i")),this._monthsParse[e].test(t))return e},_weekdays:"Sunday_Monday_Tuesday_Wednesday_Thursday_Friday_Saturday".split("_"),weekdays:function(t){return this._weekdays[t.day()]},_weekdaysShort:"Sun_Mon_Tue_Wed_Thu_Fri_Sat".split("_"),weekdaysShort:function(t){return this._weekdaysShort[t.day()]},_weekdaysMin:"Su_Mo_Tu_We_Th_Fr_Sa".split("_"),weekdaysMin:function(t){return this._weekdaysMin[t.day()]},_longDateFormat:{LT:"h:mm A",L:"MM/DD/YYYY",LL:"MMMM D YYYY",LLL:"MMMM D YYYY LT",LLLL:"dddd, MMMM D YYYY LT"},longDateFormat:function(t){var e=this._longDateFormat[t];return!e&&this._longDateFormat[t.toUpperCase()]&&(e=this._longDateFormat[t.toUpperCase()].replace(/MMMM|MM|DD|dddd/g,function(t){return t.slice(1)}),this._longDateFormat[t]=e),e},meridiem:function(t,e,i){return t>11?i?"pm":"PM":i?"am":"AM"},_calendar:{sameDay:"[Today at] LT",nextDay:"[Tomorrow at] LT",nextWeek:"dddd [at] LT",lastDay:"[Yesterday at] LT",lastWeek:"[last] dddd [at] LT",sameElse:"L"},calendar:function(t,e){var i=this._calendar[t];return"function"==typeof i?i.apply(e):i},_relativeTime:{future:"in %s",past:"%s ago",s:"a few seconds",m:"a minute",mm:"%d minutes",h:"an hour",hh:"%d hours",d:"a day",dd:"%d days",M:"a month",MM:"%d months",y:"a year",yy:"%d years"},relativeTime:function(t,e,i,s){var n=this._relativeTime[i];return"function"==typeof n?n(t,e,i,s):n.replace(/%d/i,t)},pastFuture:function(t,e){var i=this._relativeTime[t>0?"future":"past"];return"function"==typeof i?i(e):i.replace(/%s/i,e)},ordinal:function(t){return this._ordinal.replace("%d",t)},_ordinal:"%d",preparse:function(t){return t},postformat:function(t){return t},week:function(t){return L(t,this._week.dow,this._week.doy)},_week:{dow:0,doy:6}},I=function(t,e,i){return O({_i:t,_f:e,_l:i,_isUTC:!1})},I.utc=function(t,e,i){return O({_useUTC:!0,_isUTC:!0,_l:i,_i:t,_f:e})},I.unix=function(t){return I(1e3*t)},I.duration=function(t,e){var i,s=I.isDuration(t),n="number"==typeof t,o=s?t._data:n?{}:t;return n&&(e?o[e]=t:o.milliseconds=t),i=new h(o),s&&t.hasOwnProperty("_lang")&&(i._lang=t._lang),i},I.version=P,I.defaultFormat=$,I.lang=function(t,e){return t?(e?m(t,e):z[t]||g(t),I.duration.fn._lang=I.fn._lang=g(t),s):I.fn._lang._abbr},I.langData=function(t){return t&&t._lang&&t._lang._abbr&&(t=t._lang._abbr),g(t)},I.isMoment=function(t){return t instanceof a},I.isDuration=function(t){return t instanceof h},I.fn=a.prototype={clone:function(){return I(this)},valueOf:function(){return+this._d},unix:function(){return Math.floor(+this._d/1e3)},toString:function(){return this.format("ddd MMM DD YYYY HH:mm:ss [GMT]ZZ")},toDate:function(){return this._d},toJSON:function(){return I.utc(this).format("YYYY-MM-DD[T]HH:mm:ss.SSS[Z]")},toArray:function(){var t=this;return[t.year(),t.month(),t.date(),t.hours(),t.minutes(),t.seconds(),t.milliseconds()]},isValid:function(){return null==this._isValid&&(this._isValid=this._a?!f(this._a,(this._isUTC?I.utc(this._a):I(this._a)).toArray()):!isNaN(this._d.getTime())),!!this._isValid},utc:function(){return this._isUTC=!0,this},local:function(){return this._isUTC=!1,this},format:function(t){var e=b(this,t||I.defaultFormat);return this.lang().postformat(e)},add:function(t,e){var i;return i="string"==typeof t?I.duration(+e,t):I.duration(t,e),c(this,i,1),this},subtract:function(t,e){var i;return i="string"==typeof t?I.duration(+e,t):I.duration(t,e),c(this,i,-1),this},diff:function(t,e,i){var s,n,o=this._isUTC?I(t).utc():I(t).local(),r=6e4*(this.zone()-o.zone());return e&&(e=e.replace(/s$/,"")),"year"===e||"month"===e?(s=432e5*(this.daysInMonth()+o.daysInMonth()),n=12*(this.year()-o.year())+(this.month()-o.month()),n+=(this-I(this).startOf("month")-(o-I(o).startOf("month")))/s,"year"===e&&(n/=12)):(s=this-o-r,n="second"===e?s/1e3:"minute"===e?s/6e4:"hour"===e?s/36e5:"day"===e?s/864e5:"week"===e?s/6048e5:s),i?n:l(n)},from:function(t,e){return I.duration(this.diff(t)).lang(this.lang()._abbr).humanize(!e)},fromNow:function(t){return this.from(I(),t)},calendar:function(){var t=this.diff(I().startOf("day"),"days",!0),e=-6>t?"sameElse":-1>t?"lastWeek":0>t?"lastDay":1>t?"sameDay":2>t?"nextDay":7>t?"nextWeek":"sameElse";return this.format(this.lang().calendar(e,this))},isLeapYear:function(){var t=this.year();return 0===t%4&&0!==t%100||0===t%400},isDST:function(){return this.zone()+I(t).startOf(e)},isBefore:function(t,e){return e=e!==s?e:"millisecond",+this.clone().startOf(e)<+I(t).startOf(e)},isSame:function(t,e){return e=e!==s?e:"millisecond",+this.clone().startOf(e)===+I(t).startOf(e)},zone:function(){return this._isUTC?0:this._d.getTimezoneOffset()},daysInMonth:function(){return I.utc([this.year(),this.month()+1,0]).date()},dayOfYear:function(t){var e=Y((I(this).startOf("day")-I(this).startOf("year"))/864e5)+1;return null==t?e:this.add("d",t-e)},isoWeek:function(t){var e=L(this,1,4);return null==t?e:this.add("d",7*(t-e))},week:function(t){var e=this.lang().week(this);return null==t?e:this.add("d",7*(t-e))},lang:function(t){return t===s?this._lang:(this._lang=g(t),this)}},F=0;ie.length>F;F++)N(ie[F].toLowerCase().replace(/s$/,""),ie[F]);N("year","FullYear"),I.fn.days=I.fn.day,I.fn.weeks=I.fn.week,I.fn.isoWeeks=I.fn.isoWeek,I.duration.fn=h.prototype={weeks:function(){return l(this.days()/7)},valueOf:function(){return this._milliseconds+864e5*this._days+2592e6*this._months},humanize:function(t){var e=+this,i=C(e,!t,this.lang());return t&&(i=this.lang().pastFuture(e,i)),this.lang().postformat(i)},lang:I.fn.lang};for(F in se)se.hasOwnProperty(F)&&(k(F,se[F]),A(F.toLowerCase()));k("Weeks",6048e5),I.lang("en",{ordinal:function(t){var e=t%10,i=1===~~(t%100/10)?"th":1===e?"st":2===e?"nd":3===e?"rd":"th";return t+i}}),H&&(i.exports=I),"undefined"==typeof ender&&(this.moment=I),"function"==typeof t&&t.amd&&t("moment",[],function(){return I})}).call(this)})()},{}]},{},[1])(1)}); \ No newline at end of file +}},TimeStep.prototype.snap=function(t){if(this.scale==TimeStep.SCALE.YEAR){var e=t.getFullYear()+Math.round(t.getMonth()/12);t.setFullYear(Math.round(e/this.step)*this.step),t.setMonth(0),t.setDate(0),t.setHours(0),t.setMinutes(0),t.setSeconds(0),t.setMilliseconds(0)}else if(this.scale==TimeStep.SCALE.MONTH)t.getDate()>15?(t.setDate(1),t.setMonth(t.getMonth()+1)):t.setDate(1),t.setHours(0),t.setMinutes(0),t.setSeconds(0),t.setMilliseconds(0);else if(this.scale==TimeStep.SCALE.DAY||this.scale==TimeStep.SCALE.WEEKDAY){switch(this.step){case 5:case 2:t.setHours(24*Math.round(t.getHours()/24));break;default:t.setHours(12*Math.round(t.getHours()/12))}t.setMinutes(0),t.setSeconds(0),t.setMilliseconds(0)}else if(this.scale==TimeStep.SCALE.HOUR){switch(this.step){case 4:t.setMinutes(60*Math.round(t.getMinutes()/60));break;default:t.setMinutes(30*Math.round(t.getMinutes()/30))}t.setSeconds(0),t.setMilliseconds(0)}else if(this.scale==TimeStep.SCALE.MINUTE){switch(this.step){case 15:case 10:t.setMinutes(5*Math.round(t.getMinutes()/5)),t.setSeconds(0);break;case 5:t.setSeconds(60*Math.round(t.getSeconds()/60));break;default:t.setSeconds(30*Math.round(t.getSeconds()/30))}t.setMilliseconds(0)}else if(this.scale==TimeStep.SCALE.SECOND)switch(this.step){case 15:case 10:t.setSeconds(5*Math.round(t.getSeconds()/5)),t.setMilliseconds(0);break;case 5:t.setMilliseconds(1e3*Math.round(t.getMilliseconds()/1e3));break;default:t.setMilliseconds(500*Math.round(t.getMilliseconds()/500))}else if(this.scale==TimeStep.SCALE.MILLISECOND){var i=this.step>5?this.step/2:1;t.setMilliseconds(Math.round(t.getMilliseconds()/i)*i)}},TimeStep.prototype.isMajor=function(){switch(this.scale){case TimeStep.SCALE.MILLISECOND:return 0==this.current.getMilliseconds();case TimeStep.SCALE.SECOND:return 0==this.current.getSeconds();case TimeStep.SCALE.MINUTE:return 0==this.current.getHours()&&0==this.current.getMinutes();case TimeStep.SCALE.HOUR:return 0==this.current.getHours();case TimeStep.SCALE.WEEKDAY:case TimeStep.SCALE.DAY:return 1==this.current.getDate();case TimeStep.SCALE.MONTH:return 0==this.current.getMonth();case TimeStep.SCALE.YEAR:return!1;default:return!1}},TimeStep.prototype.getLabelMinor=function(t){switch(void 0==t&&(t=this.current),this.scale){case TimeStep.SCALE.MILLISECOND:return E(t).format("SSS");case TimeStep.SCALE.SECOND:return E(t).format("s");case TimeStep.SCALE.MINUTE:return E(t).format("HH:mm");case TimeStep.SCALE.HOUR:return E(t).format("HH:mm");case TimeStep.SCALE.WEEKDAY:return E(t).format("ddd D");case TimeStep.SCALE.DAY:return E(t).format("D");case TimeStep.SCALE.MONTH:return E(t).format("MMM");case TimeStep.SCALE.YEAR:return E(t).format("YYYY");default:return""}},TimeStep.prototype.getLabelMajor=function(t){switch(void 0==t&&(t=this.current),this.scale){case TimeStep.SCALE.MILLISECOND:return E(t).format("HH:mm:ss");case TimeStep.SCALE.SECOND:return E(t).format("D MMMM HH:mm");case TimeStep.SCALE.MINUTE:case TimeStep.SCALE.HOUR:return E(t).format("ddd D MMMM");case TimeStep.SCALE.WEEKDAY:case TimeStep.SCALE.DAY:return E(t).format("MMMM YYYY");case TimeStep.SCALE.MONTH:return E(t).format("YYYY");case TimeStep.SCALE.YEAR:return"";default:return""}},a.prototype.setOptions=function(t){D.extend(this.options,t)},a.prototype.update=function(){this._order(),this._stack()},a.prototype._order=function(){var t=this.parent.items;if(!t)throw Error("Cannot stack items: parent does not contain items");var e=[],i=0;D.forEach(t,function(t){t.visible&&(e[i]=t,i++)});var s=this.options.order||this.defaultOptions.order;if("function"!=typeof s)throw Error("Option order must be a function");e.sort(s),this.ordered=e},a.prototype._stack=function(){var t,e,i,s=this.ordered,n=this.options,o=n.orientation||this.defaultOptions.orientation,r="top"==o;for(i=n.margin&&void 0!==n.margin.item?n.margin.item:this.defaultOptions.margin.item,t=0,e=s.length;e>t;t++){var a=s[t],h=null;do h=this.checkOverlap(s,t,0,t-1,i),null!=h&&(a.top=r?h.top+h.height+i:h.top-a.height-i);while(h)}},a.prototype.checkOverlap=function(t,e,i,s,n){for(var o=this.collision,r=t[e],a=s;a>=i;a--){var h=t[a];if(o(r,h,n)&&a!=e)return h}return null},a.prototype.collision=function(t,e,i){return t.left-ie.left&&t.top-ie.top},h.prototype.setOptions=function(t){D.extend(this.options,t),(null!=t.start||null!=t.end)&&this.setRange(t.start,t.end)},h.prototype.subscribe=function(t,e,i){var s,n=this;if("horizontal"!=i&&"vertical"!=i)throw new TypeError('Unknown direction "'+i+'". '+'Choose "horizontal" or "vertical".');if("move"==e)s={component:t,event:e,direction:i,callback:function(t){n._onMouseDown(t,s)},params:{}},t.on("mousedown",s.callback),n.listeners.push(s);else{if("zoom"!=e)throw new TypeError('Unknown event "'+e+'". '+'Choose "move" or "zoom".');s={component:t,event:e,direction:i,callback:function(t){n._onMouseWheel(t,s)},params:{}},t.on("mousewheel",s.callback),n.listeners.push(s)}},h.prototype.on=function(t,e){O.addListener(this,t,e)},h.prototype._trigger=function(t){O.trigger(this,t,{start:this.start,end:this.end})},h.prototype.setRange=function(t,e){var i=this._applyRange(t,e);i&&(this._trigger("rangechange"),this._trigger("rangechanged"))},h.prototype._applyRange=function(t,e){var i,s=null!=t?D.convert(t,"Number"):this.start,n=null!=e?D.convert(e,"Number"):this.end;if(isNaN(s))throw Error('Invalid start "'+t+'"');if(isNaN(n))throw Error('Invalid end "'+e+'"');if(s>n&&(n=s),null!=this.options.min){var o=this.options.min.valueOf();o>s&&(i=o-s,s+=i,n+=i)}if(null!=this.options.max){var r=this.options.max.valueOf();n>r&&(i=n-r,s-=i,n-=i)}if(null!=this.options.zoomMin){var a=this.options.zoomMin.valueOf();0>a&&(a=0),a>n-s&&(this.end-this.start>a?(i=a-(n-s),s-=i/2,n+=i/2):(s=this.start,n=this.end))}if(null!=this.options.zoomMax){var h=this.options.zoomMax.valueOf();0>h&&(h=0),n-s>h&&(h>this.end-this.start?(i=n-s-h,s+=i/2,n-=i/2):(s=this.start,n=this.end))}var d=this.start!=s||this.end!=n;return this.start=s,this.end=n,d},h.prototype.getRange=function(){return{start:this.start,end:this.end}},h.prototype.conversion=function(t){return this.start,this.end,h.conversion(this.start,this.end,t)},h.conversion=function(t,e,i){return 0!=i&&0!=e-t?{offset:t,factor:i/(e-t)}:{offset:0,factor:1}},h.prototype._onMouseDown=function(t,e){t=t||window.event;var i=e.params,s=t.which?1==t.which:1==t.button;if(s){i.mouseX=D.getPageX(t),i.mouseY=D.getPageY(t),i.previousLeft=0,i.previousOffset=0,i.moved=!1,i.start=this.start,i.end=this.end;var n=e.component.frame;n&&(n.style.cursor="move");var o=this;i.onMouseMove||(i.onMouseMove=function(t){o._onMouseMove(t,e)},D.addEventListener(document,"mousemove",i.onMouseMove)),i.onMouseUp||(i.onMouseUp=function(t){o._onMouseUp(t,e)},D.addEventListener(document,"mouseup",i.onMouseUp)),D.preventDefault(t)}},h.prototype._onMouseMove=function(t,e){t=t||window.event;var i=e.params,s=D.getPageX(t),n=D.getPageY(t);void 0==i.mouseX&&(i.mouseX=s),void 0==i.mouseY&&(i.mouseY=n);var o=s-i.mouseX,r=n-i.mouseY,a="horizontal"==e.direction?o:r;Math.abs(a)>=1&&(i.moved=!0);var h=i.end-i.start,d="horizontal"==e.direction?e.component.width:e.component.height,l=-a/d*h;this._applyRange(i.start+l,i.end+l),this._trigger("rangechange"),D.preventDefault(t)},h.prototype._onMouseUp=function(t,e){t=t||window.event;var i=e.params;e.component.frame&&(e.component.frame.style.cursor="auto"),i.onMouseMove&&(D.removeEventListener(document,"mousemove",i.onMouseMove),i.onMouseMove=null),i.onMouseUp&&(D.removeEventListener(document,"mouseup",i.onMouseUp),i.onMouseUp=null),i.moved&&this._trigger("rangechanged")},h.prototype._onMouseWheel=function(t,e){t=t||window.event;var i=0;if(t.wheelDelta?i=t.wheelDelta/120:t.detail&&(i=-t.detail/3),i){var s=this,n=function(){var n=i/5,o=null,r=e.component.frame;if(r){var a,h;if("horizontal"==e.direction){a=e.component.width,h=s.conversion(a);var d=D.getAbsoluteLeft(r),l=D.getPageX(t);o=(l-d)/h.factor+h.offset}else{a=e.component.height,h=s.conversion(a);var p=D.getAbsoluteTop(r),c=D.getPageY(t);o=(p+a-c-p)/h.factor+h.offset}}s.zoom(n,o)};n()}D.preventDefault(t)},h.prototype.zoom=function(t,e){null==e&&(e=(this.start+this.end)/2),t>=1&&(t=.9),-1>=t&&(t=-.9),0>t&&(t/=1+t);var i=this.start-e,s=this.end-e,n=this.start-i*t,o=this.end-s*t;this.setRange(n,o)},h.prototype.move=function(t){var e=this.end-this.start,i=this.start+e*t,s=this.end+e*t;this.start=i,this.end=s},h.prototype.moveTo=function(t){var e=(this.start+this.end)/2,i=e-t,s=this.start-i,n=this.end-i;this.setRange(s,n)},d.prototype.add=function(t){if(void 0==t.id)throw Error("Component has no field id");if(!(t instanceof l||t instanceof d))throw new TypeError("Component must be an instance of prototype Component or Controller");t.controller=this,this.components[t.id]=t},d.prototype.remove=function(t){var e;for(e in this.components)if(this.components.hasOwnProperty(e)&&(e==t||this.components[e]==t))break;e&&delete this.components[e]},d.prototype.requestReflow=function(t){if(t)this.reflow();else if(!this.reflowTimer){var e=this;this.reflowTimer=setTimeout(function(){e.reflowTimer=void 0,e.reflow()},0)}},d.prototype.requestRepaint=function(t){if(t)this.repaint();else if(!this.repaintTimer){var e=this;this.repaintTimer=setTimeout(function(){e.repaintTimer=void 0,e.repaint()},0)}},d.prototype.repaint=function(){function t(s,n){n in i||(s.depends&&s.depends.forEach(function(e){t(e,e.id)}),s.parent&&t(s.parent,s.parent.id),e=s.repaint()||e,i[n]=!0)}var e=!1;this.repaintTimer&&(clearTimeout(this.repaintTimer),this.repaintTimer=void 0);var i={};D.forEach(this.components,t),e&&this.reflow()},d.prototype.reflow=function(){function t(s,n){n in i||(s.depends&&s.depends.forEach(function(e){t(e,e.id)}),s.parent&&t(s.parent,s.parent.id),e=s.reflow()||e,i[n]=!0)}var e=!1;this.reflowTimer&&(clearTimeout(this.reflowTimer),this.reflowTimer=void 0);var i={};D.forEach(this.components,t),e&&this.repaint()},l.prototype.setOptions=function(t){t&&(D.extend(this.options,t),this.controller&&(this.requestRepaint(),this.requestReflow()))},l.prototype.getOption=function(t){var e;return this.options&&(e=this.options[t]),void 0===e&&this.defaultOptions&&(e=this.defaultOptions[t]),e},l.prototype.getContainer=function(){return null},l.prototype.getFrame=function(){return this.frame},l.prototype.repaint=function(){return!1},l.prototype.reflow=function(){return!1},l.prototype.hide=function(){return this.frame&&this.frame.parentNode?(this.frame.parentNode.removeChild(this.frame),!0):!1},l.prototype.show=function(){return this.frame&&this.frame.parentNode?!1:this.repaint()},l.prototype.requestRepaint=function(){if(!this.controller)throw Error("Cannot request a repaint: no controller configured");this.controller.requestRepaint()},l.prototype.requestReflow=function(){if(!this.controller)throw Error("Cannot request a reflow: no controller configured");this.controller.requestReflow()},p.prototype=new l,p.prototype.setOptions=l.prototype.setOptions,p.prototype.getContainer=function(){return this.frame},p.prototype.repaint=function(){var t=0,e=D.updateProperty,i=D.option.asSize,s=this.options,n=this.frame;if(!n){n=document.createElement("div"),n.className="panel";var o=s.className;o&&("function"==typeof o?D.addClassName(n,o()+""):D.addClassName(n,o+"")),this.frame=n,t+=1}if(!n.parentNode){if(!this.parent)throw Error("Cannot repaint panel: no parent attached");var r=this.parent.getContainer();if(!r)throw Error("Cannot repaint panel: parent has no container element");r.appendChild(n),t+=1}return t+=e(n.style,"top",i(s.top,"0px")),t+=e(n.style,"left",i(s.left,"0px")),t+=e(n.style,"width",i(s.width,"100%")),t+=e(n.style,"height",i(s.height,"100%")),t>0},p.prototype.reflow=function(){var t=0,e=D.updateProperty,i=this.frame;return i?(t+=e(this,"top",i.offsetTop),t+=e(this,"left",i.offsetLeft),t+=e(this,"width",i.offsetWidth),t+=e(this,"height",i.offsetHeight)):t+=1,t>0},c.prototype=new p,c.prototype.setOptions=l.prototype.setOptions,c.prototype.repaint=function(){var t=0,e=D.updateProperty,i=D.option.asSize,s=this.options,n=this.frame;if(!n){n=document.createElement("div"),n.className="vis timeline rootpanel";var o=s.className;o&&D.addClassName(n,D.option.asString(o)),this.frame=n,t+=1}if(!n.parentNode){if(!this.container)throw Error("Cannot repaint root panel: no container attached");this.container.appendChild(n),t+=1}return t+=e(n.style,"top",i(s.top,"0px")),t+=e(n.style,"left",i(s.left,"0px")),t+=e(n.style,"width",i(s.width,"100%")),t+=e(n.style,"height",i(s.height,"100%")),this._updateEventEmitters(),this._updateWatch(),t>0},c.prototype.reflow=function(){var t=0,e=D.updateProperty,i=this.frame;return i?(t+=e(this,"top",i.offsetTop),t+=e(this,"left",i.offsetLeft),t+=e(this,"width",i.offsetWidth),t+=e(this,"height",i.offsetHeight)):t+=1,t>0},c.prototype._updateWatch=function(){var t=this.getOption("autoResize");t?this._watch():this._unwatch()},c.prototype._watch=function(){var t=this;this._unwatch();var e=function(){var e=t.getOption("autoResize");return e?(t.frame&&(t.frame.clientWidth!=t.width||t.frame.clientHeight!=t.height)&&t.requestReflow(),void 0):(t._unwatch(),void 0)};D.addEventListener(window,"resize",e),this.watchTimer=setInterval(e,1e3)},c.prototype._unwatch=function(){this.watchTimer&&(clearInterval(this.watchTimer),this.watchTimer=void 0)},c.prototype.on=function(t,e){var i=this.listeners[t];i||(i=[],this.listeners[t]=i),i.push(e),this._updateEventEmitters()},c.prototype._updateEventEmitters=function(){if(this.listeners){var t=this;D.forEach(this.listeners,function(e,i){if(t.emitters||(t.emitters={}),!(i in t.emitters)){var s=t.frame;if(s){var n=function(t){e.forEach(function(e){e(t)})};t.emitters[i]=n,D.addEventListener(s,i,n)}}})}},u.prototype=new l,u.prototype.setOptions=l.prototype.setOptions,u.prototype.setRange=function(t){if(!(t instanceof h||t&&t.start&&t.end))throw new TypeError("Range must be an instance of Range, or an object containing start and end.");this.range=t},u.prototype.toTime=function(t){var e=this.conversion;return new Date(t/e.factor+e.offset)},u.prototype.toScreen=function(t){var e=this.conversion;return(t.valueOf()-e.offset)*e.factor},u.prototype.repaint=function(){var t=0,e=D.updateProperty,i=D.option.asSize,s=this.options,n=this.getOption("orientation"),o=this.props,r=this.step,a=this.frame;if(a||(a=document.createElement("div"),this.frame=a,t+=1),a.className="axis "+n,!a.parentNode){if(!this.parent)throw Error("Cannot repaint time axis: no parent attached");var h=this.parent.getContainer();if(!h)throw Error("Cannot repaint time axis: parent has no container element");h.appendChild(a),t+=1}var d=a.parentNode;if(d){var l=a.nextSibling;d.removeChild(a);var p="bottom"==n&&this.props.parentHeight&&this.height?this.props.parentHeight-this.height+"px":"0px";if(t+=e(a.style,"top",i(s.top,p)),t+=e(a.style,"left",i(s.left,"0px")),t+=e(a.style,"width",i(s.width,"100%")),t+=e(a.style,"height",i(s.height,this.height+"px")),this._repaintMeasureChars(),this.step){this._repaintStart(),r.first();for(var c=void 0,u=0;r.hasNext()&&1e3>u;){u++;var f=r.getCurrent(),m=this.toScreen(f),g=r.isMajor();this.getOption("showMinorLabels")&&this._repaintMinorText(m,r.getLabelMinor()),g&&this.getOption("showMajorLabels")?(m>0&&(void 0==c&&(c=m),this._repaintMajorText(m,r.getLabelMajor())),this._repaintMajorLine(m)):this._repaintMinorLine(m),r.next()}if(this.getOption("showMajorLabels")){var v=this.toTime(0),y=r.getLabelMajor(v),b=y.length*(o.majorCharWidth||10)+10;(void 0==c||c>b)&&this._repaintMajorText(0,y)}this._repaintEnd()}this._repaintLine(),l?d.insertBefore(a,l):d.appendChild(a)}return t>0},u.prototype._repaintStart=function(){var t=this.dom,e=t.redundant;e.majorLines=t.majorLines,e.majorTexts=t.majorTexts,e.minorLines=t.minorLines,e.minorTexts=t.minorTexts,t.majorLines=[],t.majorTexts=[],t.minorLines=[],t.minorTexts=[]},u.prototype._repaintEnd=function(){D.forEach(this.dom.redundant,function(t){for(;t.length;){var e=t.pop();e&&e.parentNode&&e.parentNode.removeChild(e)}})},u.prototype._repaintMinorText=function(t,e){var i=this.dom.redundant.minorTexts.shift();if(!i){var s=document.createTextNode("");i=document.createElement("div"),i.appendChild(s),i.className="text minor",this.frame.appendChild(i)}this.dom.minorTexts.push(i),i.childNodes[0].nodeValue=e,i.style.left=t+"px",i.style.top=this.props.minorLabelTop+"px"},u.prototype._repaintMajorText=function(t,e){var i=this.dom.redundant.majorTexts.shift();if(!i){var s=document.createTextNode(e);i=document.createElement("div"),i.className="text major",i.appendChild(s),this.frame.appendChild(i)}this.dom.majorTexts.push(i),i.childNodes[0].nodeValue=e,i.style.top=this.props.majorLabelTop+"px",i.style.left=t+"px"},u.prototype._repaintMinorLine=function(t){var e=this.dom.redundant.minorLines.shift();e||(e=document.createElement("div"),e.className="grid vertical minor",this.frame.appendChild(e)),this.dom.minorLines.push(e);var i=this.props;e.style.top=i.minorLineTop+"px",e.style.height=i.minorLineHeight+"px",e.style.left=t-i.minorLineWidth/2+"px"},u.prototype._repaintMajorLine=function(t){var e=this.dom.redundant.majorLines.shift();e||(e=document.createElement("DIV"),e.className="grid vertical major",this.frame.appendChild(e)),this.dom.majorLines.push(e);var i=this.props;e.style.top=i.majorLineTop+"px",e.style.left=t-i.majorLineWidth/2+"px",e.style.height=i.majorLineHeight+"px"},u.prototype._repaintLine=function(){var t=this.dom.line,e=this.frame;this.options,this.getOption("showMinorLabels")||this.getOption("showMajorLabels")?(t?(e.removeChild(t),e.appendChild(t)):(t=document.createElement("div"),t.className="grid horizontal major",e.appendChild(t),this.dom.line=t),t.style.top=this.props.lineTop+"px"):t&&axis.parentElement&&(e.removeChild(axis.line),delete this.dom.line)},u.prototype._repaintMeasureChars=function(){var t,e=this.dom;if(!e.measureCharMinor){t=document.createTextNode("0");var i=document.createElement("DIV");i.className="text minor measure",i.appendChild(t),this.frame.appendChild(i),e.measureCharMinor=i}if(!e.measureCharMajor){t=document.createTextNode("0");var s=document.createElement("DIV");s.className="text major measure",s.appendChild(t),this.frame.appendChild(s),e.measureCharMajor=s}},u.prototype.reflow=function(){var t=0,e=D.updateProperty,i=this.frame,s=this.range;if(!s)throw Error("Cannot repaint time axis: no range configured");if(i){t+=e(this,"top",i.offsetTop),t+=e(this,"left",i.offsetLeft);var n=this.props,o=this.getOption("showMinorLabels"),r=this.getOption("showMajorLabels"),a=this.dom.measureCharMinor,h=this.dom.measureCharMajor;a&&(n.minorCharHeight=a.clientHeight,n.minorCharWidth=a.clientWidth),h&&(n.majorCharHeight=h.clientHeight,n.majorCharWidth=h.clientWidth);var d=i.parentNode?i.parentNode.offsetHeight:0;switch(d!=n.parentHeight&&(n.parentHeight=d,t+=1),this.getOption("orientation")){case"bottom":n.minorLabelHeight=o?n.minorCharHeight:0,n.majorLabelHeight=r?n.majorCharHeight:0,n.minorLabelTop=0,n.majorLabelTop=n.minorLabelTop+n.minorLabelHeight,n.minorLineTop=-this.top,n.minorLineHeight=Math.max(this.top+n.majorLabelHeight,0),n.minorLineWidth=1,n.majorLineTop=-this.top,n.majorLineHeight=Math.max(this.top+n.minorLabelHeight+n.majorLabelHeight,0),n.majorLineWidth=1,n.lineTop=0;break;case"top":n.minorLabelHeight=o?n.minorCharHeight:0,n.majorLabelHeight=r?n.majorCharHeight:0,n.majorLabelTop=0,n.minorLabelTop=n.majorLabelTop+n.majorLabelHeight,n.minorLineTop=n.minorLabelTop,n.minorLineHeight=Math.max(d-n.majorLabelHeight-this.top),n.minorLineWidth=1,n.majorLineTop=0,n.majorLineHeight=Math.max(d-this.top),n.majorLineWidth=1,n.lineTop=n.majorLabelHeight+n.minorLabelHeight;break;default:throw Error('Unkown orientation "'+this.getOption("orientation")+'"')}var l=n.minorLabelHeight+n.majorLabelHeight;t+=e(this,"width",i.offsetWidth),t+=e(this,"height",l),this._updateConversion();var p=D.convert(s.start,"Date"),c=D.convert(s.end,"Date"),u=this.toTime(5*(n.minorCharWidth||10))-this.toTime(0);this.step=new TimeStep(p,c,u),t+=e(n.range,"start",p.valueOf()),t+=e(n.range,"end",c.valueOf()),t+=e(n.range,"minimumStep",u.valueOf())}return t>0},u.prototype._updateConversion=function(){var t=this.range;if(!t)throw Error("No range configured");this.conversion=t.conversion?t.conversion(this.width):h.conversion(t.start,t.end,this.width)},f.prototype=new p,f.types={box:g,range:y,point:v},f.prototype.setOptions=l.prototype.setOptions,f.prototype.setRange=function(t){if(!(t instanceof h||t&&t.start&&t.end))throw new TypeError("Range must be an instance of Range, or an object containing start and end.");this.range=t},f.prototype.repaint=function(){var t=0,e=D.updateProperty,i=D.option.asSize,s=this.options,n=this.getOption("orientation"),o=this.defaultOptions,r=this.frame;if(!r){r=document.createElement("div"),r.className="itemset";var a=s.className;a&&D.addClassName(r,D.option.asString(a));var h=document.createElement("div");h.className="background",r.appendChild(h),this.dom.background=h;var d=document.createElement("div");d.className="foreground",r.appendChild(d),this.dom.foreground=d;var l=document.createElement("div");l.className="itemset-axis",this.dom.axis=l,this.frame=r,t+=1}if(!this.parent)throw Error("Cannot repaint itemset: no parent attached");var p=this.parent.getContainer();if(!p)throw Error("Cannot repaint itemset: parent has no container element");r.parentNode||(p.appendChild(r),t+=1),this.dom.axis.parentNode||(p.appendChild(this.dom.axis),t+=1),t+=e(r.style,"left",i(s.left,"0px")),t+=e(r.style,"top",i(s.top,"0px")),t+=e(r.style,"width",i(s.width,"100%")),t+=e(r.style,"height",i(s.height,this.height+"px")),t+=e(this.dom.axis.style,"left",i(s.left,"0px")),t+=e(this.dom.axis.style,"width",i(s.width,"100%")),t+="bottom"==n?e(this.dom.axis.style,"top",this.height+this.top+"px"):e(this.dom.axis.style,"top",this.top+"px"),this._updateConversion();var c=this,u=this.queue,m=this.itemsData,g=this.items,v={};return Object.keys(u).forEach(function(e){var i=u[e],n=g[e];switch(i){case"add":case"update":var r=m&&m.get(e,v);if(r){var a=r.type||r.start&&r.end&&"range"||s.type||"box",h=f.types[a];if(n&&(h&&n instanceof h?(n.data=r,t++):(t+=n.hide(),n=null)),!n){if(!h)throw new TypeError('Unknown item type "'+a+'"');n=new h(c,r,s,o),t++}n.repaint(),g[e]=n}delete u[e];break;case"remove":n&&(t+=n.hide()),delete g[e],delete u[e];break;default:console.log('Error: unknown action "'+i+'"')}}),D.forEach(this.items,function(e){e.visible?(t+=e.show(),e.reposition()):t+=e.hide()}),t>0},f.prototype.getForeground=function(){return this.dom.foreground},f.prototype.getBackground=function(){return this.dom.background},f.prototype.getAxis=function(){return this.dom.axis},f.prototype.reflow=function(){var t=0,e=this.options,i=e.margin&&e.margin.axis||this.defaultOptions.margin.axis,s=e.margin&&e.margin.item||this.defaultOptions.margin.item,n=D.updateProperty,o=D.option.asNumber,r=D.option.asSize,a=this.frame;if(a){this._updateConversion(),D.forEach(this.items,function(e){t+=e.reflow()}),this.stack.update();var h,d=o(e.maxHeight),l=null!=r(e.height);if(l)h=a.offsetHeight;else{var p=this.stack.ordered;if(p.length){var c=p[0].top,u=p[0].top+p[0].height;D.forEach(p,function(t){c=Math.min(c,t.top),u=Math.max(u,t.top+t.height)}),h=u-c+i+s}else h=i+s}null!=d&&(h=Math.min(h,d)),t+=n(this,"height",h),t+=n(this,"top",a.offsetTop),t+=n(this,"left",a.offsetLeft),t+=n(this,"width",a.offsetWidth)}else t+=1;return t>0},f.prototype.hide=function(){var t=!1;return this.frame&&this.frame.parentNode&&(this.frame.parentNode.removeChild(this.frame),t=!0),this.dom.axis&&this.dom.axis.parentNode&&(this.dom.axis.parentNode.removeChild(this.dom.axis),t=!0),t},f.prototype.setItems=function(t){var e,i=this,s=this.itemsData;if(t){if(!(t instanceof o||t instanceof r))throw new TypeError("Data must be an instance of DataSet");this.itemsData=t}else this.itemsData=null;if(s&&(D.forEach(this.listeners,function(t,e){s.unsubscribe(e,t)}),e=s.getIds(),this._onRemove(e)),this.itemsData){var n=this.id;D.forEach(this.listeners,function(t,e){i.itemsData.subscribe(e,t,n)}),e=this.itemsData.getIds(),this._onAdd(e)}},f.prototype.getItems=function(){return this.itemsData},f.prototype._onUpdate=function(t){this._toQueue("update",t)},f.prototype._onAdd=function(t){this._toQueue("add",t)},f.prototype._onRemove=function(t){this._toQueue("remove",t)},f.prototype._toQueue=function(t,e){var i=this.queue;e.forEach(function(e){i[e]=t}),this.controller&&this.requestRepaint()},f.prototype._updateConversion=function(){var t=this.range;if(!t)throw Error("No range configured");this.conversion=t.conversion?t.conversion(this.width):h.conversion(t.start,t.end,this.width)},f.prototype.toTime=function(t){var e=this.conversion;return new Date(t/e.factor+e.offset)},f.prototype.toScreen=function(t){var e=this.conversion;return(t.valueOf()-e.offset)*e.factor},m.prototype.select=function(){this.selected=!0},m.prototype.unselect=function(){this.selected=!1},m.prototype.show=function(){return!1},m.prototype.hide=function(){return!1},m.prototype.repaint=function(){return!1},m.prototype.reflow=function(){return!1},g.prototype=new m(null,null),g.prototype.select=function(){this.selected=!0},g.prototype.unselect=function(){this.selected=!1},g.prototype.repaint=function(){var t=!1,e=this.dom;if(e||(this._create(),e=this.dom,t=!0),e){if(!this.parent)throw Error("Cannot repaint item: no parent attached");var i=this.parent.getForeground();if(!i)throw Error("Cannot repaint time axis: parent has no foreground container element");var s=this.parent.getBackground();if(!s)throw Error("Cannot repaint time axis: parent has no background container element");var n=this.parent.getAxis();if(!s)throw Error("Cannot repaint time axis: parent has no axis container element");if(e.box.parentNode||(i.appendChild(e.box),t=!0),e.line.parentNode||(s.appendChild(e.line),t=!0),e.dot.parentNode||(n.appendChild(e.dot),t=!0),this.data.content!=this.content){if(this.content=this.data.content,this.content instanceof Element)e.content.innerHTML="",e.content.appendChild(this.content);else{if(void 0==this.data.content)throw Error('Property "content" missing in item '+this.data.id);e.content.innerHTML=this.content}t=!0}var o=(this.data.className?" "+this.data.className:"")+(this.selected?" selected":"");this.className!=o&&(this.className=o,e.box.className="item box"+o,e.line.className="item line"+o,e.dot.className="item dot"+o,t=!0)}return t},g.prototype.show=function(){return this.dom&&this.dom.box.parentNode?!1:this.repaint()},g.prototype.hide=function(){var t=!1,e=this.dom;return e&&(e.box.parentNode&&(e.box.parentNode.removeChild(e.box),t=!0),e.line.parentNode&&e.line.parentNode.removeChild(e.line),e.dot.parentNode&&e.dot.parentNode.removeChild(e.dot)),t},g.prototype.reflow=function(){var t,e,i,s,n,o,r,a,h,d,l,p,c=0;if(void 0==this.data.start)throw Error('Property "start" missing in item '+this.data.id);if(l=this.data,p=this.parent&&this.parent.range,l&&p){var u=p.end-p.start;this.visible=l.start>p.start-u&&l.start0},g.prototype._create=function(){var t=this.dom;t||(this.dom=t={},t.box=document.createElement("DIV"),t.content=document.createElement("DIV"),t.content.className="content",t.box.appendChild(t.content),t.line=document.createElement("DIV"),t.line.className="line",t.dot=document.createElement("DIV"),t.dot.className="dot")},g.prototype.reposition=function(){var t=this.dom,e=this.props,i=this.options.orientation||this.defaultOptions.orientation;if(t){var s=t.box,n=t.line,o=t.dot;s.style.left=this.left+"px",s.style.top=this.top+"px",n.style.left=e.line.left+"px","top"==i?(n.style.top="0px",n.style.height=this.top+"px"):(n.style.top=this.top+this.height+"px",n.style.height=Math.max(this.parent.height-this.top-this.height+this.props.dot.height/2,0)+"px"),o.style.left=e.dot.left+"px",o.style.top=e.dot.top+"px"}},v.prototype=new m(null,null),v.prototype.select=function(){this.selected=!0},v.prototype.unselect=function(){this.selected=!1},v.prototype.repaint=function(){var t=!1,e=this.dom;if(e||(this._create(),e=this.dom,t=!0),e){if(!this.parent)throw Error("Cannot repaint item: no parent attached");var i=this.parent.getForeground();if(!i)throw Error("Cannot repaint time axis: parent has no foreground container element");if(e.point.parentNode||(i.appendChild(e.point),i.appendChild(e.point),t=!0),this.data.content!=this.content){if(this.content=this.data.content,this.content instanceof Element)e.content.innerHTML="",e.content.appendChild(this.content);else{if(void 0==this.data.content)throw Error('Property "content" missing in item '+this.data.id);e.content.innerHTML=this.content}t=!0}var s=(this.data.className?" "+this.data.className:"")+(this.selected?" selected":"");this.className!=s&&(this.className=s,e.point.className="item point"+s,t=!0)}return t},v.prototype.show=function(){return this.dom&&this.dom.point.parentNode?!1:this.repaint()},v.prototype.hide=function(){var t=!1,e=this.dom;return e&&e.point.parentNode&&(e.point.parentNode.removeChild(e.point),t=!0),t},v.prototype.reflow=function(){var t,e,i,s,n,o,r,a,h,d,l=0;if(void 0==this.data.start)throw Error('Property "start" missing in item '+this.data.id);if(h=this.data,d=this.parent&&this.parent.range,h&&d){var p=d.end-d.start;this.visible=h.start>d.start-p&&h.start0},v.prototype._create=function(){var t=this.dom;t||(this.dom=t={},t.point=document.createElement("div"),t.content=document.createElement("div"),t.content.className="content",t.point.appendChild(t.content),t.dot=document.createElement("div"),t.dot.className="dot",t.point.appendChild(t.dot))},v.prototype.reposition=function(){var t=this.dom,e=this.props;t&&(t.point.style.top=this.top+"px",t.point.style.left=this.left+"px",t.content.style.marginLeft=e.content.marginLeft+"px",t.dot.style.top=e.dot.top+"px")},y.prototype=new m(null,null),y.prototype.select=function(){this.selected=!0},y.prototype.unselect=function(){this.selected=!1},y.prototype.repaint=function(){var t=!1,e=this.dom;if(e||(this._create(),e=this.dom,t=!0),e){if(!this.parent)throw Error("Cannot repaint item: no parent attached");var i=this.parent.getForeground();if(!i)throw Error("Cannot repaint time axis: parent has no foreground container element");if(e.box.parentNode||(i.appendChild(e.box),t=!0),this.data.content!=this.content){if(this.content=this.data.content,this.content instanceof Element)e.content.innerHTML="",e.content.appendChild(this.content);else{if(void 0==this.data.content)throw Error('Property "content" missing in item '+this.data.id); +e.content.innerHTML=this.content}t=!0}var s=this.data.className?" "+this.data.className:"";this.className!=s&&(this.className=s,e.box.className="item range"+s,t=!0)}return t},y.prototype.show=function(){return this.dom&&this.dom.box.parentNode?!1:this.repaint()},y.prototype.hide=function(){var t=!1,e=this.dom;return e&&e.box.parentNode&&(e.box.parentNode.removeChild(e.box),t=!0),t},y.prototype.reflow=function(){var t,e,i,s,n,o,r,a,h,d,l,p,c,u,f,m,g=0;if(void 0==this.data.start)throw Error('Property "start" missing in item '+this.data.id);if(void 0==this.data.end)throw Error('Property "end" missing in item '+this.data.id);return h=this.data,d=this.parent&&this.parent.range,this.visible=h&&d?h.startd.start:!1,this.visible&&(t=this.dom,t?(e=this.props,i=this.options,o=this.parent,r=o.toScreen(this.data.start),a=o.toScreen(this.data.end),l=D.updateProperty,p=t.box,c=o.width,f=i.orientation||this.defaultOptions.orientation,s=i.margin&&i.margin.axis||this.defaultOptions.margin.axis,n=i.padding||this.defaultOptions.padding,g+=l(e.content,"width",t.content.offsetWidth),g+=l(this,"height",p.offsetHeight),-c>r&&(r=-c),a>2*c&&(a=2*c),u=0>r?Math.min(-r,a-r-e.content.width-2*n):0,g+=l(e.content,"left",u),"top"==f?(m=s,g+=l(this,"top",m)):(m=o.height-this.height-s,g+=l(this,"top",m)),g+=l(this,"left",r),g+=l(this,"width",Math.max(a-r,1))):g+=1),g>0},y.prototype._create=function(){var t=this.dom;t||(this.dom=t={},t.box=document.createElement("div"),t.content=document.createElement("div"),t.content.className="content",t.box.appendChild(t.content))},y.prototype.reposition=function(){var t=this.dom,e=this.props;t&&(t.box.style.top=this.top+"px",t.box.style.left=this.left+"px",t.box.style.width=this.width+"px",t.content.style.left=e.content.left+"px")},b.prototype=new l,b.prototype.setOptions=l.prototype.setOptions,b.prototype.getContainer=function(){return this.parent.getContainer()},b.prototype.setItems=function(t){if(this.itemset&&(this.itemset.hide(),this.itemset.setItems(),this.parent.controller.remove(this.itemset),this.itemset=null),t){var e=this.groupId,i=Object.create(this.options);this.itemset=new f(this,null,i),this.itemset.setRange(this.parent.range),this.view=new r(t,{filter:function(t){return t.group==e}}),this.itemset.setItems(this.view),this.parent.controller.add(this.itemset)}},b.prototype.repaint=function(){return!1},b.prototype.reflow=function(){var t=0,e=D.updateProperty;if(t+=e(this,"top",this.itemset?this.itemset.top:0),t+=e(this,"height",this.itemset?this.itemset.height:0),this.label){var i=this.label.firstChild;t+=e(this.props.label,"width",i.clientWidth),t+=e(this.props.label,"height",i.clientHeight)}else t+=e(this.props.label,"width",0),t+=e(this.props.label,"height",0);return t>0},w.prototype=new p,w.prototype.setOptions=l.prototype.setOptions,w.prototype.setRange=function(){},w.prototype.setItems=function(t){this.itemsData=t;for(var e in this.groups)if(this.groups.hasOwnProperty(e)){var i=this.groups[e];i.setItems(t)}},w.prototype.getItems=function(){return this.itemsData},w.prototype.setRange=function(t){this.range=t},w.prototype.setGroups=function(t){var e,i=this;if(this.groupsData&&(D.forEach(this.listeners,function(t,e){i.groupsData.unsubscribe(e,t)}),e=this.groupsData.getIds(),this._onRemove(e)),t?t instanceof o?this.groupsData=t:(this.groupsData=new o({convert:{start:"Date",end:"Date"}}),this.groupsData.add(t)):this.groupsData=null,this.groupsData){var s=this.id;D.forEach(this.listeners,function(t,e){i.groupsData.subscribe(e,t,s)}),e=this.groupsData.getIds(),this._onAdd(e)}},w.prototype.getGroups=function(){return this.groupsData},w.prototype.repaint=function(){var t,e,i,s,n=0,o=D.updateProperty,r=D.option.asSize,a=D.option.asElement,h=this.options,d=this.dom.frame,l=this.dom.labels;if(!this.parent)throw Error("Cannot repaint groupset: no parent attached");var p=this.parent.getContainer();if(!p)throw Error("Cannot repaint groupset: parent has no container element");if(!d){d=document.createElement("div"),d.className="groupset",this.dom.frame=d;var c=h.className;c&&D.addClassName(d,D.option.asString(c)),n+=1}d.parentNode||(p.appendChild(d),n+=1);var u=a(h.labelContainer);if(!u)throw Error('Cannot repaint groupset: option "labelContainer" not defined');l||(l=document.createElement("div"),l.className="labels",this.dom.labels=l),l.parentNode&&l.parentNode==u||(l.parentNode&&l.parentNode.removeChild(l.parentNode),u.appendChild(l)),n+=o(d.style,"height",r(h.height,this.height+"px")),n+=o(d.style,"top",r(h.top,"0px")),n+=o(d.style,"left",r(h.left,"0px")),n+=o(d.style,"width",r(h.width,"100%")),n+=o(l.style,"top",r(h.top,"0px"));var f=this,m=this.queue,g=this.groups,v=this.groupsData,y=Object.keys(m);if(y.length){y.forEach(function(t){var e=m[t],i=g[t];switch(e){case"add":case"update":if(!i){var s=Object.create(f.options);i=new b(f,t,s),i.setItems(f.itemsData),g[t]=i,f.controller.add(i)}i.data=v.get(t),delete m[t];break;case"remove":i&&(i.setItems(),delete g[t],f.controller.remove(i)),delete m[t];break;default:console.log('Error: unknown action "'+e+'"')}});var w=this.groupsData.getIds({order:this.options.groupsOrder});for(t=0;w.length>t;t++)(function(t,e){var i=0;e&&(i=function(){return e.top+e.height}),t.setOptions({top:i})})(g[w[t]],g[w[t-1]]);for(;l.firstChild;)l.removeChild(l.firstChild);for(t=0;w.length>t;t++)e=w[t],s=this._createLabel(e),l.appendChild(s);n++}for(e in g)g.hasOwnProperty(e)&&(i=g[e],s=i.label,s&&(s.style.top=i.top+"px",s.style.height=i.height+"px"));return n>0},w.prototype._createLabel=function(t){var e=this.groups[t],i=document.createElement("div");i.className="label";var s=document.createElement("div");s.className="inner",i.appendChild(s);var n=e.data&&e.data.content;n instanceof Element?s.appendChild(n):void 0!=n&&(s.innerHTML=n);var o=e.data&&e.data.className;return o&&D.addClassName(i,o),e.label=i,i},w.prototype.getContainer=function(){return this.dom.frame},w.prototype.getLabelsWidth=function(){return this.props.labels.width},w.prototype.reflow=function(){var t,e,i=0,s=this.options,n=D.updateProperty,o=D.option.asNumber,r=D.option.asSize,a=this.dom.frame;if(a){var h,d=o(s.maxHeight),l=null!=r(s.height);if(l)h=a.offsetHeight;else{h=0;for(t in this.groups)this.groups.hasOwnProperty(t)&&(e=this.groups[t],h+=e.height)}null!=d&&(h=Math.min(h,d)),i+=n(this,"height",h),i+=n(this,"top",a.offsetTop),i+=n(this,"left",a.offsetLeft),i+=n(this,"width",a.offsetWidth)}var p=0;for(t in this.groups)if(this.groups.hasOwnProperty(t)){e=this.groups[t];var c=e.props&&e.props.label&&e.props.label.width||0;p=Math.max(p,c)}return i+=n(this.props.labels,"width",p),i>0},w.prototype.hide=function(){return this.dom.frame&&this.dom.frame.parentNode?(this.dom.frame.parentNode.removeChild(this.dom.frame),!0):!1},w.prototype.show=function(){return this.dom.frame&&this.dom.frame.parentNode?!1:this.repaint()},w.prototype._onUpdate=function(t){this._toQueue(t,"update")},w.prototype._onAdd=function(t){this._toQueue(t,"add")},w.prototype._onRemove=function(t){this._toQueue(t,"remove")},w.prototype._toQueue=function(t,e){var i=this.queue;t.forEach(function(t){i[t]=e}),this.controller&&this.requestRepaint()},_.prototype.setOptions=function(t){t&&D.extend(this.options,t),this.controller.reflow(),this.controller.repaint()},_.prototype.setItems=function(t){var e,i=null==this.itemsData;if(t?t instanceof o&&(e=t):e=null,t instanceof o||(e=new o({convert:{start:"Date",end:"Date"}}),e.add(t)),this.itemsData=e,this.content.setItems(e),i&&(void 0==this.options.start||void 0==this.options.end)){var s=this.getItemRange(),n=s.min,r=s.max;if(null!=n&&null!=r){var a=r.valueOf()-n.valueOf();n=new Date(n.valueOf()-.05*a),r=new Date(r.valueOf()+.05*a)}void 0!=this.options.start&&(n=new Date(this.options.start.valueOf())),void 0!=this.options.end&&(r=new Date(this.options.end.valueOf())),(null!=n||null!=r)&&this.range.setRange(n,r)}},_.prototype.setGroups=function(t){var e=this;this.groupsData=t;var i=this.groupsData?w:f;if(!(this.content instanceof i)){this.content&&(this.content.hide(),this.content.setItems&&this.content.setItems(),this.content.setGroups&&this.content.setGroups(),this.controller.remove(this.content));var s=Object.create(this.options);D.extend(s,{top:function(){return"top"==e.options.orientation?e.timeaxis.height:e.itemPanel.height-e.timeaxis.height-e.content.height},left:null,width:"100%",height:function(){return e.options.height?e.itemPanel.height-e.timeaxis.height:null},maxHeight:function(){if(e.options.maxHeight){if(!D.isNumber(e.options.maxHeight))throw new TypeError("Number expected for property maxHeight");return e.options.maxHeight-e.timeaxis.height}return null},labelContainer:function(){return e.labelPanel.getContainer()}}),this.content=new i(this.itemPanel,[this.timeaxis],s),this.content.setRange&&this.content.setRange(this.range),this.content.setItems&&this.content.setItems(this.itemsData),this.content.setGroups&&this.content.setGroups(this.groupsData),this.controller.add(this.content)}},_.prototype.getItemRange=function(){var t=this.itemsData,e=null,i=null;if(t){var s=t.min("start");e=s?s.start.valueOf():null;var n=t.max("start");n&&(i=n.start.valueOf());var o=t.max("end");o&&(i=null==i?o.end.valueOf():Math.max(i,o.end.valueOf()))}return{min:null!=e?new Date(e):null,max:null!=i?new Date(i):null}},function(t){function e(t){return E=t,c()}function i(){D=0,C=E.charAt(0)}function s(){D++,C=E.charAt(D)}function n(){return E.charAt(D+1)}function o(t){return N.test(t)}function r(t,e){if(t||(t={}),e)for(var i in e)e.hasOwnProperty(i)&&(t[i]=e[i]);return t}function a(t,e,i){for(var s=e.split("."),n=t;s.length;){var o=s.shift();s.length?(n[o]||(n[o]={}),n=n[o]):n[o]=i}}function h(t,e){for(var i,s,n=null,o=[t],a=t;a.parent;)o.push(a.parent),a=a.parent;if(a.nodes)for(i=0,s=a.nodes.length;s>i;i++)if(e.id===a.nodes[i].id){n=a.nodes[i];break}for(n||(n={id:e.id},t.node&&(n.attr=r(n.attr,t.node))),i=o.length-1;i>=0;i--){var h=o[i];h.nodes||(h.nodes=[]),-1==h.nodes.indexOf(n)&&h.nodes.push(n)}e.attr&&(n.attr=r(n.attr,e.attr))}function d(t,e){if(t.edges||(t.edges=[]),t.edges.push(e),t.edge){var i=r({},t.edge);e.attr=r(i,e.attr)}}function l(t,e,i,s,n){var o={from:e,to:i,type:s};return t.edge&&(o.attr=r({},t.edge)),o.attr=r(o.attr||{},n),o}function p(){for(O=S.NULL,L="";" "==C||" "==C||"\n"==C||"\r"==C;)s();do{var t=!1;if("#"==C){for(var e=D-1;" "==E.charAt(e)||" "==E.charAt(e);)e--;if("\n"==E.charAt(e)||""==E.charAt(e)){for(;""!=C&&"\n"!=C;)s();t=!0}}if("/"==C&&"/"==n()){for(;""!=C&&"\n"!=C;)s();t=!0}if("/"==C&&"*"==n()){for(;""!=C;){if("*"==C&&"/"==n()){s(),s();break}s()}t=!0}for(;" "==C||" "==C||"\n"==C||"\r"==C;)s()}while(t);if(""==C)return O=S.DELIMITER,void 0;var i=C+n();if(M[i])return O=S.DELIMITER,L=i,s(),s(),void 0;if(M[C])return O=S.DELIMITER,L=C,s(),void 0;if(o(C)||"-"==C){for(L+=C,s();o(C);)L+=C,s();return"false"==L?L=!1:"true"==L?L=!0:isNaN(Number(L))||(L=Number(L)),O=S.IDENTIFIER,void 0}if('"'==C){for(s();""!=C&&('"'!=C||'"'==C&&'"'==n());)L+=C,'"'==C&&s(),s();if('"'!=C)throw w('End of string " expected');return s(),O=S.IDENTIFIER,void 0}for(O=S.UNKNOWN;""!=C;)L+=C,s();throw new SyntaxError('Syntax error in part "'+_(L,30)+'"')}function c(){var t={};if(i(),p(),"strict"==L&&(t.strict=!0,p()),("graph"==L||"digraph"==L)&&(t.type=L,p()),O==S.IDENTIFIER&&(t.id=L,p()),"{"!=L)throw w("Angle bracket { expected");if(p(),u(t),"}"!=L)throw w("Angle bracket } expected");if(p(),""!==L)throw w("End of file expected");return p(),delete t.node,delete t.edge,delete t.graph,t}function u(t){for(;""!==L&&"}"!=L;)f(t),";"==L&&p()}function f(t){var e=m(t);if(e)return y(t,e),void 0;var i=g(t);if(!i){if(O!=S.IDENTIFIER)throw w("Identifier expected");var s=L;if(p(),"="==L){if(p(),O!=S.IDENTIFIER)throw w("Identifier expected");t[s]=L,p()}else v(t,s)}}function m(t){var e=null;if("subgraph"==L&&(e={},e.type="subgraph",p(),O==S.IDENTIFIER&&(e.id=L,p())),"{"==L){if(p(),e||(e={}),e.parent=t,e.node=t.node,e.edge=t.edge,e.graph=t.graph,u(e),"}"!=L)throw w("Angle bracket } expected");p(),delete e.node,delete e.edge,delete e.graph,delete e.parent,t.subgraphs||(t.subgraphs=[]),t.subgraphs.push(e)}return e}function g(t){return"node"==L?(p(),t.node=b(),"node"):"edge"==L?(p(),t.edge=b(),"edge"):"graph"==L?(p(),t.graph=b(),"graph"):null}function v(t,e){var i={id:e},s=b();s&&(i.attr=s),h(t,i),y(t,e)}function y(t,e){for(;"->"==L||"--"==L;){var i,s=L;p();var n=m(t);if(n)i=n;else{if(O!=S.IDENTIFIER)throw w("Identifier or subgraph expected");i=L,h(t,{id:i}),p()}var o=b(),r=l(t,e,i,s,o);d(t,r),e=i}}function b(){for(var t=null;"["==L;){for(p(),t={};""!==L&&"]"!=L;){if(O!=S.IDENTIFIER)throw w("Attribute name expected");var e=L;if(p(),"="!=L)throw w("Equal sign = expected");if(p(),O!=S.IDENTIFIER)throw w("Attribute value expected");var i=L;a(t,e,i),p(),","==L&&p()}if("]"!=L)throw w("Bracket ] expected");p()}return t}function w(t){return new SyntaxError(t+', got "'+_(L,30)+'" (char '+D+")")}function _(t,e){return e>=t.length?t:t.substr(0,27)+"..."}function x(t,e,i){t instanceof Array?t.forEach(function(t){e instanceof Array?e.forEach(function(e){i(t,e)}):i(t,e)}):e instanceof Array?e.forEach(function(e){i(t,e)}):i(t,e)}function T(t){function i(t){var e={from:t.from,to:t.to};return r(e,t.attr),e.style="->"==t.type?"arrow":"line",e}var s=e(t),n={nodes:[],edges:[],options:{}};return s.nodes&&s.nodes.forEach(function(t){var e={id:t.id,label:(t.label||t.id)+""};r(e,t.attr),e.image&&(e.shape="image"),n.nodes.push(e)}),s.edges&&s.edges.forEach(function(t){var e,s;e=t.from instanceof Object?t.from.nodes:{id:t.from},s=t.to instanceof Object?t.to.nodes:{id:t.to},t.from instanceof Object&&t.from.edges&&t.from.edges.forEach(function(t){var e=i(t);n.edges.push(e)}),x(e,s,function(e,s){var o=l(n,e.id,s.id,t.type,t.attr),r=i(o);n.edges.push(r)}),t.to instanceof Object&&t.to.edges&&t.to.edges.forEach(function(t){var e=i(t);n.edges.push(e)})}),s.attr&&(n.options=s.attr),n}var S={NULL:0,DELIMITER:1,IDENTIFIER:2,UNKNOWN:3},M={"{":!0,"}":!0,"[":!0,"]":!0,";":!0,"=":!0,",":!0,"->":!0,"--":!0},E="",D=0,C="",L="",O=S.NULL,N=/[a-zA-Z_0-9.:#]/;t.parseDOT=e,t.DOTToGraph=T}(D!==void 0?D:s),"undefined"!=typeof CanvasRenderingContext2D&&(CanvasRenderingContext2D.prototype.circle=function(t,e,i){this.beginPath(),this.arc(t,e,i,0,2*Math.PI,!1)},CanvasRenderingContext2D.prototype.square=function(t,e,i){this.beginPath(),this.rect(t-i,e-i,2*i,2*i)},CanvasRenderingContext2D.prototype.triangle=function(t,e,i){this.beginPath();var s=2*i,n=s/2,o=Math.sqrt(3)/6*s,r=Math.sqrt(s*s-n*n);this.moveTo(t,e-(r-o)),this.lineTo(t+n,e+o),this.lineTo(t-n,e+o),this.lineTo(t,e-(r-o)),this.closePath()},CanvasRenderingContext2D.prototype.triangleDown=function(t,e,i){this.beginPath();var s=2*i,n=s/2,o=Math.sqrt(3)/6*s,r=Math.sqrt(s*s-n*n);this.moveTo(t,e+(r-o)),this.lineTo(t+n,e-o),this.lineTo(t-n,e-o),this.lineTo(t,e+(r-o)),this.closePath()},CanvasRenderingContext2D.prototype.star=function(t,e,i){this.beginPath();for(var s=0;10>s;s++){var n=0===s%2?1.3*i:.5*i;this.lineTo(t+n*Math.sin(2*s*Math.PI/10),e-n*Math.cos(2*s*Math.PI/10))}this.closePath()},CanvasRenderingContext2D.prototype.roundRect=function(t,e,i,s,n){var o=Math.PI/180;0>i-2*n&&(n=i/2),0>s-2*n&&(n=s/2),this.beginPath(),this.moveTo(t+n,e),this.lineTo(t+i-n,e),this.arc(t+i-n,e+n,n,270*o,360*o,!1),this.lineTo(t+i,e+s-n),this.arc(t+i-n,e+s-n,n,0,90*o,!1),this.lineTo(t+n,e+s),this.arc(t+n,e+s-n,n,90*o,180*o,!1),this.lineTo(t,e+n),this.arc(t+n,e+n,n,180*o,270*o,!1)},CanvasRenderingContext2D.prototype.ellipse=function(t,e,i,s){var n=.5522848,o=i/2*n,r=s/2*n,a=t+i,h=e+s,d=t+i/2,l=e+s/2;this.beginPath(),this.moveTo(t,l),this.bezierCurveTo(t,l-r,d-o,e,d,e),this.bezierCurveTo(d+o,e,a,l-r,a,l),this.bezierCurveTo(a,l+r,d+o,h,d,h),this.bezierCurveTo(d-o,h,t,l+r,t,l)},CanvasRenderingContext2D.prototype.database=function(t,e,i,s){var n=1/3,o=i,r=s*n,a=.5522848,h=o/2*a,d=r/2*a,l=t+o,p=e+r,c=t+o/2,u=e+r/2,f=e+(s-r/2),m=e+s;this.beginPath(),this.moveTo(l,u),this.bezierCurveTo(l,u+d,c+h,p,c,p),this.bezierCurveTo(c-h,p,t,u+d,t,u),this.bezierCurveTo(t,u-d,c-h,e,c,e),this.bezierCurveTo(c+h,e,l,u-d,l,u),this.lineTo(l,f),this.bezierCurveTo(l,f+d,c+h,m,c,m),this.bezierCurveTo(c-h,m,t,f+d,t,f),this.lineTo(t,u)},CanvasRenderingContext2D.prototype.arrow=function(t,e,i,s){var n=t-s*Math.cos(i),o=e-s*Math.sin(i),r=t-.9*s*Math.cos(i),a=e-.9*s*Math.sin(i),h=n+s/3*Math.cos(i+.5*Math.PI),d=o+s/3*Math.sin(i+.5*Math.PI),l=n+s/3*Math.cos(i-.5*Math.PI),p=o+s/3*Math.sin(i-.5*Math.PI);this.beginPath(),this.moveTo(t,e),this.lineTo(h,d),this.lineTo(r,a),this.lineTo(l,p),this.closePath()},CanvasRenderingContext2D.prototype.dashedLine=function(t,e,i,s,n){n||(n=[10,5]),0==c&&(c=.001);var o=n.length;this.moveTo(t,e);for(var r=i-t,a=s-e,h=a/r,d=Math.sqrt(r*r+a*a),l=0,p=!0;d>=.1;){var c=n[l++%o];c>d&&(c=d);var u=Math.sqrt(c*c/(1+h*h));0>r&&(u=-u),t+=u,e+=h*u,this[p?"lineTo":"moveTo"](t,e),d-=c,p=!p}}),x.prototype.attachEdge=function(t){-1==this.edges.indexOf(t)&&this.edges.push(t),this._updateMass()},x.prototype.detachEdge=function(t){var e=this.edges.indexOf(t);-1!=e&&this.edges.splice(e,1),this._updateMass()},x.prototype._updateMass=function(){this.mass=50+20*this.edges.length},x.prototype.setProperties=function(t,e){if(t){if(void 0!=t.id&&(this.id=t.id),void 0!=t.label&&(this.label=t.label),void 0!=t.title&&(this.title=t.title),void 0!=t.group&&(this.group=t.group),void 0!=t.x&&(this.x=t.x),void 0!=t.y&&(this.y=t.y),void 0!=t.value&&(this.value=t.value),void 0===this.id)throw"Node must have an id";if(this.group){var i=this.grouplist.get(this.group);for(var s in i)i.hasOwnProperty(s)&&(this[s]=i[s])}if(void 0!=t.shape&&(this.shape=t.shape),void 0!=t.image&&(this.image=t.image),void 0!=t.radius&&(this.radius=t.radius),void 0!=t.color&&(this.color=x.parseColor(t.color)),void 0!=t.fontColor&&(this.fontColor=t.fontColor),void 0!=t.fontSize&&(this.fontSize=t.fontSize),void 0!=t.fontFace&&(this.fontFace=t.fontFace),void 0!=this.image){if(!this.imagelist)throw"No imagelist provided";this.imageObj=this.imagelist.load(this.image)}switch(this.xFixed=this.xFixed||void 0!=t.x,this.yFixed=this.yFixed||void 0!=t.y,this.radiusFixed=this.radiusFixed||void 0!=t.radius,"image"==this.shape&&(this.radiusMin=e.nodes.widthMin,this.radiusMax=e.nodes.widthMax),this.shape){case"database":this.draw=this._drawDatabase,this.resize=this._resizeDatabase;break;case"box":this.draw=this._drawBox,this.resize=this._resizeBox;break;case"circle":this.draw=this._drawCircle,this.resize=this._resizeCircle;break;case"ellipse":this.draw=this._drawEllipse,this.resize=this._resizeEllipse;break;case"image":this.draw=this._drawImage,this.resize=this._resizeImage;break;case"text":this.draw=this._drawText,this.resize=this._resizeText;break;case"dot":this.draw=this._drawDot,this.resize=this._resizeShape;break;case"square":this.draw=this._drawSquare,this.resize=this._resizeShape;break;case"triangle":this.draw=this._drawTriangle,this.resize=this._resizeShape;break;case"triangleDown":this.draw=this._drawTriangleDown,this.resize=this._resizeShape;break;case"star":this.draw=this._drawStar,this.resize=this._resizeShape;break;default:this.draw=this._drawEllipse,this.resize=this._resizeEllipse}this._reset()}},x.parseColor=function(t){var e;return D.isString(t)?e={border:t,background:t,highlight:{border:t,background:t}}:(e={},e.background=t.background||"white",e.border=t.border||e.background,D.isString(t.highlight)?e.highlight={border:t.highlight,background:t.highlight}:(e.highlight={},e.highlight.background=t.highlight&&t.highlight.background||e.background,e.highlight.border=t.highlight&&t.highlight.border||e.border)),e},x.prototype.select=function(){this.selected=!0,this._reset()},x.prototype.unselect=function(){this.selected=!1,this._reset()},x.prototype._reset=function(){this.width=void 0,this.height=void 0},x.prototype.getTitle=function(){return this.title},x.prototype.distanceToBorder=function(t,e){var i=1;switch(this.width||this.resize(t),this.shape){case"circle":case"dot":return this.radius+i;case"ellipse":var s=this.width/2,n=this.height/2,o=Math.sin(e)*s,r=Math.cos(e)*n;return s*n/Math.sqrt(o*o+r*r);case"box":case"image":case"text":default:return this.width?Math.min(Math.abs(this.width/2/Math.cos(e)),Math.abs(this.height/2/Math.sin(e)))+i:0}},x.prototype._setForce=function(t,e){this.fx=t,this.fy=e},x.prototype._addForce=function(t,e){this.fx+=t,this.fy+=e},x.prototype.discreteStep=function(t){if(!this.xFixed){var e=-this.damping*this.vx,i=(this.fx+e)/this.mass;this.vx+=i/t,this.x+=this.vx/t}if(!this.yFixed){var s=-this.damping*this.vy,n=(this.fy+s)/this.mass;this.vy+=n/t,this.y+=this.vy/t}},x.prototype.isFixed=function(){return this.xFixed&&this.yFixed},x.prototype.isMoving=function(t){return Math.abs(this.vx)>t||Math.abs(this.vy)>t||!this.xFixed&&Math.abs(this.fx)>this.minForce||!this.yFixed&&Math.abs(this.fy)>this.minForce},x.prototype.isSelected=function(){return this.selected},x.prototype.getValue=function(){return this.value},x.prototype.getDistance=function(t,e){var i=this.x-t,s=this.y-e;return Math.sqrt(i*i+s*s)},x.prototype.setValueRange=function(t,e){if(!this.radiusFixed&&void 0!==this.value){var i=(this.radiusMax-this.radiusMin)/(e-t);this.radius=(this.value-t)*i+this.radiusMin}},x.prototype.draw=function(){throw"Draw method not initialized for node"},x.prototype.resize=function(){throw"Resize method not initialized for node"},x.prototype.isOverlappingWith=function(t){return this.leftt.left&&this.topt.top},x.prototype._resizeImage=function(){if(!this.width){var t,e;if(this.value){var i=this.imageObj.height/this.imageObj.width;t=this.radius||this.imageObj.width,e=this.radius*i||this.imageObj.height}else t=this.imageObj.width,e=this.imageObj.height;this.width=t,this.height=e}},x.prototype._drawImage=function(t){this._resizeImage(t),this.left=this.x-this.width/2,this.top=this.y-this.height/2;var e;this.imageObj?(t.drawImage(this.imageObj,this.left,this.top,this.width,this.height),e=this.y+this.height/2):e=this.y,this._label(t,this.label,this.x,e,void 0,"top")},x.prototype._resizeBox=function(t){if(!this.width){var e=5,i=this.getTextSize(t);this.width=i.width+2*e,this.height=i.height+2*e}},x.prototype._drawBox=function(t){this._resizeBox(t),this.left=this.x-this.width/2,this.top=this.y-this.height/2,t.strokeStyle=this.selected?this.color.highlight.border:this.color.border,t.fillStyle=this.selected?this.color.highlight.background:this.color.background,t.lineWidth=this.selected?2:1,t.roundRect(this.left,this.top,this.width,this.height,this.radius),t.fill(),t.stroke(),this._label(t,this.label,this.x,this.y)},x.prototype._resizeDatabase=function(t){if(!this.width){var e=5,i=this.getTextSize(t),s=i.width+2*e;this.width=s,this.height=s}},x.prototype._drawDatabase=function(t){this._resizeDatabase(t),this.left=this.x-this.width/2,this.top=this.y-this.height/2,t.strokeStyle=this.selected?this.color.highlight.border:this.color.border,t.fillStyle=this.selected?this.color.highlight.background:this.color.background,t.lineWidth=this.selected?2:1,t.database(this.x-this.width/2,this.y-.5*this.height,this.width,this.height),t.fill(),t.stroke(),this._label(t,this.label,this.x,this.y)},x.prototype._resizeCircle=function(t){if(!this.width){var e=5,i=this.getTextSize(t),s=Math.max(i.width,i.height)+2*e;this.radius=s/2,this.width=s,this.height=s}},x.prototype._drawCircle=function(t){this._resizeCircle(t),this.left=this.x-this.width/2,this.top=this.y-this.height/2,t.strokeStyle=this.selected?this.color.highlight.border:this.color.border,t.fillStyle=this.selected?this.color.highlight.background:this.color.background,t.lineWidth=this.selected?2:1,t.circle(this.x,this.y,this.radius),t.fill(),t.stroke(),this._label(t,this.label,this.x,this.y)},x.prototype._resizeEllipse=function(t){if(!this.width){var e=this.getTextSize(t);this.width=1.5*e.width,this.height=2*e.height,this.widthl;l++)t.fillText(r[l],i,d),d+=h}},x.prototype.getTextSize=function(t){if(void 0!=this.label){t.font=(this.selected?"bold ":"")+this.fontSize+"px "+this.fontFace;for(var e=this.label.split("\n"),i=(this.fontSize+4)*e.length,s=0,n=0,o=e.length;o>n;n++)s=Math.max(s,t.measureText(e[n]).width);return{width:s,height:i}}return{width:0,height:0}},T.prototype.setProperties=function(t,e){if(t)switch(void 0!=t.from&&(this.fromId=t.from),void 0!=t.to&&(this.toId=t.to),void 0!=t.id&&(this.id=t.id),void 0!=t.style&&(this.style=t.style),void 0!=t.label&&(this.label=t.label),this.label&&(this.fontSize=e.edges.fontSize,this.fontFace=e.edges.fontFace,this.fontColor=e.edges.fontColor,void 0!=t.fontColor&&(this.fontColor=t.fontColor),void 0!=t.fontSize&&(this.fontSize=t.fontSize),void 0!=t.fontFace&&(this.fontFace=t.fontFace)),void 0!=t.title&&(this.title=t.title),void 0!=t.width&&(this.width=t.width),void 0!=t.value&&(this.value=t.value),void 0!=t.length&&(this.length=t.length),t.dash&&(void 0!=t.dash.length&&(this.dash.length=t.dash.length),void 0!=t.dash.gap&&(this.dash.gap=t.dash.gap),void 0!=t.dash.altLength&&(this.dash.altLength=t.dash.altLength)),void 0!=t.color&&(this.color=t.color),this.connect(),this.widthFixed=this.widthFixed||void 0!=t.width,this.lengthFixed=this.lengthFixed||void 0!=t.length,this.stiffness=1/this.length,this.style){case"line":this.draw=this._drawLine;break;case"arrow":this.draw=this._drawArrow;break;case"arrow-center":this.draw=this._drawArrowCenter;break;case"dash-line":this.draw=this._drawDashLine;break;default:this.draw=this._drawLine}},T.prototype.connect=function(){this.disconnect(),this.from=this.graph.nodes[this.fromId]||null,this.to=this.graph.nodes[this.toId]||null,this.connected=this.from&&this.to,this.connected?(this.from.attachEdge(this),this.to.attachEdge(this)):(this.from&&this.from.detachEdge(this),this.to&&this.to.detachEdge(this))},T.prototype.disconnect=function(){this.from&&(this.from.detachEdge(this),this.from=null),this.to&&(this.to.detachEdge(this),this.to=null),this.connected=!1},T.prototype.getTitle=function(){return this.title},T.prototype.getValue=function(){return this.value},T.prototype.setValueRange=function(t,e){if(!this.widthFixed&&void 0!==this.value){var i=(this.widthMax-this.widthMin)/(e-t);this.width=(this.value-t)*i+this.widthMin}},T.prototype.draw=function(){throw"Method draw not initialized in edge"},T.prototype.isOverlappingWith=function(t){var e=10,i=this.from.x,s=this.from.y,n=this.to.x,o=this.to.y,r=t.left,a=t.top,h=T._dist(i,s,n,o,r,a);return e>h},T.prototype._drawLine=function(t){t.strokeStyle=this.color,t.lineWidth=this._getLineWidth();var e;if(this.from!=this.to)this._line(t),this.label&&(e=this._pointOnLine(.5),this._label(t,this.label,e.x,e.y));else{var i,s,n=this.length/4,o=this.from;o.width||o.resize(t),o.width>o.height?(i=o.x+o.width/2,s=o.y-n):(i=o.x+n,s=o.y-o.height/2),this._circle(t,i,s,n),e=this._pointOnCircle(i,s,n,.5),this._label(t,this.label,e.x,e.y)}},T.prototype._getLineWidth=function(){return this.from.selected||this.to.selected?Math.min(2*this.width,this.widthMax):this.width},T.prototype._line=function(t){t.beginPath(),t.moveTo(this.from.x,this.from.y),t.lineTo(this.to.x,this.to.y),t.stroke()},T.prototype._circle=function(t,e,i,s){t.beginPath(),t.arc(e,i,s,0,2*Math.PI,!1),t.stroke()},T.prototype._label=function(t,e,i,s){if(e){t.font=(this.from.selected||this.to.selected?"bold ":"")+this.fontSize+"px "+this.fontFace,t.fillStyle="white";var n=t.measureText(e).width,o=this.fontSize,r=i-n/2,a=s-o/2;t.fillRect(r,a,n,o),t.fillStyle=this.fontColor||"black",t.textAlign="left",t.textBaseline="top",t.fillText(e,r,a)}},T.prototype._drawDashLine=function(t){if(t.strokeStyle=this.color,t.lineWidth=this._getLineWidth(),t.beginPath(),t.lineCap="round",void 0!=this.dash.altLength?t.dashedLine(this.from.x,this.from.y,this.to.x,this.to.y,[this.dash.length,this.dash.gap,this.dash.altLength,this.dash.gap]):void 0!=this.dash.length&&void 0!=this.dash.gap?t.dashedLine(this.from.x,this.from.y,this.to.x,this.to.y,[this.dash.length,this.dash.gap]):(t.moveTo(this.from.x,this.from.y),t.lineTo(this.to.x,this.to.y)),t.stroke(),this.label){var e=this._pointOnLine(.5);this._label(t,this.label,e.x,e.y)}},T.prototype._pointOnLine=function(t){return{x:(1-t)*this.from.x+t*this.to.x,y:(1-t)*this.from.y+t*this.to.y}},T.prototype._pointOnCircle=function(t,e,i,s){var n=2*(s-3/8)*Math.PI;return{x:t+i*Math.cos(n),y:e-i*Math.sin(n)}},T.prototype._drawArrowCenter=function(t){var e;if(t.strokeStyle=this.color,t.fillStyle=this.color,t.lineWidth=this._getLineWidth(),this.from!=this.to){this._line(t);var i=Math.atan2(this.to.y-this.from.y,this.to.x-this.from.x),s=10+5*this.width;e=this._pointOnLine(.5),t.arrow(e.x,e.y,i,s),t.fill(),t.stroke(),this.label&&(e=this._pointOnLine(.5),this._label(t,this.label,e.x,e.y))}else{var n,o,r=this.length/4,a=this.from;a.width||a.resize(t),a.width>a.height?(n=a.x+a.width/2,o=a.y-r):(n=a.x+r,o=a.y-a.height/2),this._circle(t,n,o,r);var i=.2*Math.PI,s=10+5*this.width;e=this._pointOnCircle(n,o,r,.5),t.arrow(e.x,e.y,i,s),t.fill(),t.stroke(),this.label&&(e=this._pointOnCircle(n,o,r,.5),this._label(t,this.label,e.x,e.y))}},T.prototype._drawArrow=function(t){t.strokeStyle=this.color,t.fillStyle=this.color,t.lineWidth=this._getLineWidth();var e,i;if(this.from!=this.to){e=Math.atan2(this.to.y-this.from.y,this.to.x-this.from.x);var s=this.to.x-this.from.x,n=this.to.y-this.from.y,o=Math.sqrt(s*s+n*n),r=this.from.distanceToBorder(t,e+Math.PI),a=(o-r)/o,h=a*this.from.x+(1-a)*this.to.x,d=a*this.from.y+(1-a)*this.to.y,l=this.to.distanceToBorder(t,e),p=(o-l)/o,c=(1-p)*this.from.x+p*this.to.x,u=(1-p)*this.from.y+p*this.to.y;if(t.beginPath(),t.moveTo(h,d),t.lineTo(c,u),t.stroke(),i=10+5*this.width,t.arrow(c,u,e,i),t.fill(),t.stroke(),this.label){var f=this._pointOnLine(.5);this._label(t,this.label,f.x,f.y)}}else{var m,g,v,y=this.from,b=this.length/4;y.width||y.resize(t),y.width>y.height?(m=y.x+y.width/2,g=y.y-b,v={x:m,y:y.y,angle:.9*Math.PI}):(m=y.x+b,g=y.y-y.height/2,v={x:y.x,y:g,angle:.6*Math.PI}),t.beginPath(),t.arc(m,g,b,0,2*Math.PI,!1),t.stroke(),i=10+5*this.width,t.arrow(v.x,v.y,v.angle,i),t.fill(),t.stroke(),this.label&&(f=this._pointOnCircle(m,g,b,.5),this._label(t,this.label,f.x,f.y))}},T._dist=function(t,e,i,s,n,o){var r=i-t,a=s-e,h=r*r+a*a,d=((n-t)*r+(o-e)*a)/h; +d>1?d=1:0>d&&(d=0);var l=t+d*r,p=e+d*a,c=l-n,u=p-o;return Math.sqrt(c*c+u*u)},S.prototype.setPosition=function(t,e){this.x=parseInt(t),this.y=parseInt(e)},S.prototype.setText=function(t){this.frame.innerHTML=t},S.prototype.show=function(t){if(void 0===t&&(t=!0),t){var e=this.frame.clientHeight,i=this.frame.clientWidth,s=this.frame.parentNode.clientHeight,n=this.frame.parentNode.clientWidth,o=this.y-e;o+e+this.padding>s&&(o=s-e-this.padding),this.padding>o&&(o=this.padding);var r=this.x;r+i+this.padding>n&&(r=n-i-this.padding),this.padding>r&&(r=this.padding),this.frame.style.left=r+"px",this.frame.style.top=o+"px",this.frame.style.visibility="visible"}else this.hide()},S.prototype.hide=function(){this.frame.style.visibility="hidden"},Groups=function(){this.clear(),this.defaultIndex=0},Groups.DEFAULT=[{border:"#2B7CE9",background:"#97C2FC",highlight:{border:"#2B7CE9",background:"#D2E5FF"}},{border:"#FFA500",background:"#FFFF00",highlight:{border:"#FFA500",background:"#FFFFA3"}},{border:"#FA0A10",background:"#FB7E81",highlight:{border:"#FA0A10",background:"#FFAFB1"}},{border:"#41A906",background:"#7BE141",highlight:{border:"#41A906",background:"#A1EC76"}},{border:"#E129F0",background:"#EB7DF4",highlight:{border:"#E129F0",background:"#F0B3F5"}},{border:"#7C29F0",background:"#AD85E4",highlight:{border:"#7C29F0",background:"#D3BDF0"}},{border:"#C37F00",background:"#FFA807",highlight:{border:"#C37F00",background:"#FFCA66"}},{border:"#4220FB",background:"#6E6EFD",highlight:{border:"#4220FB",background:"#9B9BFD"}},{border:"#FD5A77",background:"#FFC0CB",highlight:{border:"#FD5A77",background:"#FFD1D9"}},{border:"#4AD63A",background:"#C2FABC",highlight:{border:"#4AD63A",background:"#E6FFE3"}}],Groups.prototype.clear=function(){this.groups={},this.groups.length=function(){var t=0;for(var e in this)this.hasOwnProperty(e)&&t++;return t}},Groups.prototype.get=function(t){var e=this.groups[t];if(void 0==e){var i=this.defaultIndex%Groups.DEFAULT.length;this.defaultIndex++,e={},e.color=Groups.DEFAULT[i],this.groups[t]=e}return e},Groups.prototype.add=function(t,e){return this.groups[t]=e,e.color&&(e.color=x.parseColor(e.color)),e},Images=function(){this.images={},this.callback=void 0},Images.prototype.setOnloadCallback=function(t){this.callback=t},Images.prototype.load=function(t){var e=this.images[t];if(void 0==e){var i=this;e=new Image,this.images[t]=e,e.onload=function(){i.callback&&i.callback(this)},e.src=t}return e},M.prototype.setData=function(t){if(t&&t.dot&&(t.nodes||t.edges))throw new SyntaxError('Data must contain either parameter "dot" or parameter pair "nodes" and "edges", but not both.');if(this.setOptions(t&&t.options),t&&t.dot){if(t&&t.dot){var e=N.util.DOTToGraph(t.dot);return this.setData(e),void 0}}else this._setNodes(t&&t.nodes),this._setEdges(t&&t.edges);this.stabilize&&this._doStabilize(),this.start()},M.prototype.setOptions=function(t){if(t){if(void 0!=t.width&&(this.width=t.width),void 0!=t.height&&(this.height=t.height),void 0!=t.stabilize&&(this.stabilize=t.stabilize),void 0!=t.selectable&&(this.selectable=t.selectable),t.edges){for(var e in t.edges)t.edges.hasOwnProperty(e)&&(this.constants.edges[e]=t.edges[e]);void 0!=t.edges.length&&t.nodes&&void 0==t.nodes.distance&&(this.constants.edges.length=t.edges.length,this.constants.nodes.distance=1.25*t.edges.length),t.edges.fontColor||(this.constants.edges.fontColor=t.edges.color),t.edges.dash&&(void 0!=t.edges.dash.length&&(this.constants.edges.dash.length=t.edges.dash.length),void 0!=t.edges.dash.gap&&(this.constants.edges.dash.gap=t.edges.dash.gap),void 0!=t.edges.dash.altLength&&(this.constants.edges.dash.altLength=t.edges.dash.altLength))}if(t.nodes){for(e in t.nodes)t.nodes.hasOwnProperty(e)&&(this.constants.nodes[e]=t.nodes[e]);t.nodes.color&&(this.constants.nodes.color=x.parseColor(t.nodes.color))}if(t.groups)for(var i in t.groups)if(t.groups.hasOwnProperty(i)){var s=t.groups[i];this.groups.add(i,s)}}this.setSize(this.width,this.height),this._setTranslation(this.frame.clientWidth/2,this.frame.clientHeight/2),this._setScale(1)},M.prototype._trigger=function(t,e){O.trigger(this,t,e)},M.prototype._create=function(){for(;this.containerElement.hasChildNodes();)this.containerElement.removeChild(this.containerElement.firstChild);if(this.frame=document.createElement("div"),this.frame.className="graph-frame",this.frame.style.position="relative",this.frame.style.overflow="hidden",this.frame.canvas=document.createElement("canvas"),this.frame.canvas.style.position="relative",this.frame.appendChild(this.frame.canvas),!this.frame.canvas.getContext){var t=document.createElement("DIV");t.style.color="red",t.style.fontWeight="bold",t.style.padding="10px",t.innerHTML="Error: your browser does not support HTML canvas",this.frame.canvas.appendChild(t)}var e=this,i=function(t){e._onMouseDown(t)},s=function(t){e._onMouseMoveTitle(t)},n=function(t){e._onMouseWheel(t)},o=function(t){e._onTouchStart(t)};N.util.addEventListener(this.frame.canvas,"mousedown",i),N.util.addEventListener(this.frame.canvas,"mousemove",s),N.util.addEventListener(this.frame.canvas,"mousewheel",n),N.util.addEventListener(this.frame.canvas,"touchstart",o),this.containerElement.appendChild(this.frame)},M.prototype._onMouseDown=function(t){if(t=t||window.event,this.selectable&&(this.leftButtonDown&&this._onMouseUp(t),this.leftButtonDown=t.which?1==t.which:1==t.button,this.leftButtonDown||this.touchDown)){var e=this;this.onmousemove||(this.onmousemove=function(t){e._onMouseMove(t)},N.util.addEventListener(document,"mousemove",e.onmousemove)),this.onmouseup||(this.onmouseup=function(t){e._onMouseUp(t)},N.util.addEventListener(document,"mouseup",e.onmouseup)),N.util.preventDefault(t),this.startMouseX=D.getPageX(t),this.startMouseY=D.getPageY(t),this.startFrameLeft=N.util.getAbsoluteLeft(this.frame.canvas),this.startFrameTop=N.util.getAbsoluteTop(this.frame.canvas),this.startTranslation=this._getTranslation(),this.ctrlKeyDown=t.ctrlKey,this.shiftKeyDown=t.shiftKey;var i={left:this._xToCanvas(this.startMouseX-this.startFrameLeft),top:this._yToCanvas(this.startMouseY-this.startFrameTop),right:this._xToCanvas(this.startMouseX-this.startFrameLeft),bottom:this._yToCanvas(this.startMouseY-this.startFrameTop)},s=this._getNodesOverlappingWith(i);if(this.startClickedObj=s.length>0?s[s.length-1]:void 0,this.startClickedObj){var n=this.nodes[this.startClickedObj];this.startClickedObj.xFixed=n.xFixed,this.startClickedObj.yFixed=n.yFixed,n.xFixed=!0,n.yFixed=!0,this.ctrlKeyDown&&n.isSelected()?this._unselectNodes([this.startClickedObj]):this._selectNodes([this.startClickedObj],this.ctrlKeyDown),this.moving||this._redraw()}else this.shiftKeyDown||(this.moved=!1)}},M.prototype._onMouseMove=function(t){if(t=t||window.event,this.selectable){var e=D.getPageX(t),i=D.getPageY(t);if(this.mouseX=e,this.mouseY=i,this.startClickedObj){var s=this.nodes[this.startClickedObj];this.startClickedObj.xFixed||(s.x=this._xToCanvas(e-this.startFrameLeft)),this.startClickedObj.yFixed||(s.y=this._yToCanvas(i-this.startFrameTop)),this.moving||(this.moving=!0,this.start())}else if(this.shiftKeyDown){void 0==this.frame.selRect&&(this.frame.selRect=document.createElement("DIV"),this.frame.appendChild(this.frame.selRect),this.frame.selRect.style.position="absolute",this.frame.selRect.style.border="1px dashed red");var n=Math.min(this.startMouseX,e)-this.startFrameLeft,o=Math.min(this.startMouseY,i)-this.startFrameTop,r=Math.max(this.startMouseX,e)-this.startFrameLeft,a=Math.max(this.startMouseY,i)-this.startFrameTop;this.frame.selRect.style.left=n+"px",this.frame.selRect.style.top=o+"px",this.frame.selRect.style.width=r-n+"px",this.frame.selRect.style.height=a-o+"px"}else{var h=e-this.startMouseX,d=i-this.startMouseY;this._setTranslation(this.startTranslation.x+h,this.startTranslation.y+d),this._redraw(),this.moved=!0}N.util.preventDefault(t)}},M.prototype._onMouseUp=function(t){if(t=t||window.event,this.selectable){this.onmousemove&&(N.util.removeEventListener(document,"mousemove",this.onmousemove),this.onmousemove=void 0),this.onmouseup&&(N.util.removeEventListener(document,"mouseup",this.onmouseup),this.onmouseup=void 0),N.util.preventDefault(t);var e=D.getPageX(t)||this.mouseX||0,i=D.getPageY(t)||this.mouseY||0,s=t?t.ctrlKey:window.event.ctrlKey;if(this.startClickedObj){var n=this.nodes[this.startClickedObj];n.xFixed=this.startClickedObj.xFixed,n.yFixed=this.startClickedObj.yFixed}else if(this.shiftKeyDown){var o={left:this._xToCanvas(Math.min(this.startMouseX,e)-this.startFrameLeft),top:this._yToCanvas(Math.min(this.startMouseY,i)-this.startFrameTop),right:this._xToCanvas(Math.max(this.startMouseX,e)-this.startFrameLeft),bottom:this._yToCanvas(Math.max(this.startMouseY,i)-this.startFrameTop)},r=this._getNodesOverlappingWith(o);this._selectNodes(r,s),this.redraw(),this.frame.selRect&&(this.frame.removeChild(this.frame.selRect),this.frame.selRect=void 0)}else this.ctrlKeyDown||this.moved||(this._unselectNodes(),this._redraw());this.leftButtonDown=!1,this.ctrlKeyDown=!1}},M.prototype._onMouseWheel=function(t){t=t||window.event;var e=D.getPageX(t),i=D.getPageY(t),s=0;if(t.wheelDelta?s=t.wheelDelta/120:t.detail&&(s=-t.detail/3),s){var n=s/10;0>s&&(n/=1-n);var o=this._getScale(),r=o*(1+n);.01>r&&(r=.01),r>10&&(r=10);var a=N.util.getAbsoluteLeft(this.frame.canvas),h=N.util.getAbsoluteTop(this.frame.canvas),d=e-a,l=i-h,p=this._getTranslation(),c=r/o,u=(1-c)*d+p.x*c,f=(1-c)*l+p.y*c;this._setScale(r),this._setTranslation(u,f),this._redraw()}N.util.preventDefault(t)},M.prototype._onMouseMoveTitle=function(t){t=t||window.event;var e=D.getPageX(t),i=D.getPageY(t);this.startFrameLeft=this.startFrameLeft||N.util.getAbsoluteLeft(this.frame.canvas),this.startFrameTop=this.startFrameTop||N.util.getAbsoluteTop(this.frame.canvas);var s=e-this.startFrameLeft,n=i-this.startFrameTop;this.popupNode&&this._checkHidePopup(s,n);var o=this,r=function(){o._checkShowPopup(s,n)};this.popupTimer&&clearInterval(this.popupTimer),this.leftButtonDown||(this.popupTimer=setTimeout(r,300))},M.prototype._checkShowPopup=function(t,e){var i,s={left:this._xToCanvas(t),top:this._yToCanvas(e),right:this._xToCanvas(t),bottom:this._yToCanvas(e)},n=this.popupNode;if(void 0==this.popupNode){var o=this.nodes;for(i in o)if(o.hasOwnProperty(i)){var r=o[i];if(void 0!=r.getTitle()&&r.isOverlappingWith(s)){this.popupNode=r;break}}}if(void 0==this.popupNode){var a=this.edges;for(i in a)if(a.hasOwnProperty(i)){var h=a[i];if(h.connected&&void 0!=h.getTitle()&&h.isOverlappingWith(s)){this.popupNode=h;break}}}if(this.popupNode){if(this.popupNode!=n){var d=this;d.popup||(d.popup=new S(d.frame)),d.popup.setPosition(t-3,e-3),d.popup.setText(d.popupNode.getTitle()),d.popup.show()}}else this.popup&&this.popup.hide()},M.prototype._checkHidePopup=function(t,e){var i={left:t,top:e,right:t,bottom:e};this.popupNode&&this.popupNode.isOverlappingWith(i)||(this.popupNode=void 0,this.popup&&this.popup.hide())},M.prototype._onTouchStart=function(t){if(N.util.preventDefault(t),!this.touchDown){this.touchDown=!0;var e=this;this.ontouchmove||(this.ontouchmove=function(t){e._onTouchMove(t)},N.util.addEventListener(document,"touchmove",this.ontouchmove)),this.ontouchend||(this.ontouchend=function(t){e._onTouchEnd(t)},N.util.addEventListener(document,"touchend",this.ontouchend)),this._onMouseDown(t)}},M.prototype._onTouchMove=function(t){N.util.preventDefault(t),this._onMouseMove(t)},M.prototype._onTouchEnd=function(t){N.util.preventDefault(t),this.touchDown=!1,this.ontouchmove&&(N.util.removeEventListener(document,"touchmove",this.ontouchmove),this.ontouchmove=void 0),this.ontouchend&&(N.util.removeEventListener(document,"touchend",this.ontouchend),this.ontouchend=void 0),this._onMouseUp(t)},M.prototype._unselectNodes=function(t,e){var i,s,n,o=!1;if(t)for(i=0,s=t.length;s>i;i++){n=t[i],this.nodes[n].unselect();for(var r=0;this.selection.length>r;)this.selection[r]==n?(this.selection.splice(r,1),o=!0):r++}else if(this.selection&&this.selection.length){for(i=0,s=this.selection.length;s>i;i++)n=this.selection[i],this.nodes[n].unselect(),o=!0;this.selection=[]}return!o||1!=e&&void 0!=e||this._trigger("select"),o},M.prototype._selectNodes=function(t,e){var i,s,n=!1,o=!0;if(t.length!=this.selection.length)o=!1;else for(i=0,s=Math.min(t.length,this.selection.length);s>i;i++)if(t[i]!=this.selection[i]){o=!1;break}if(o)return n;if(void 0==e||0==e){var r=!1;n=this._unselectNodes(void 0,r)}for(i=0,s=t.length;s>i;i++){var a=t[i],h=-1!=this.selection.indexOf(a);h||(this.nodes[a].select(),this.selection.push(a),n=!0)}return n&&this._trigger("select"),n},M.prototype._getNodesOverlappingWith=function(t){var e=this.nodes,i=[];for(var s in e)e.hasOwnProperty(s)&&e[s].isOverlappingWith(t)&&i.push(s);return i},M.prototype.getSelection=function(){return this.selection.concat([])},M.prototype.setSelection=function(t){var e,i,s;if(void 0==t.length)throw"Selection must be an array with ids";for(e=0,i=this.selection.length;i>e;e++)s=this.selection[e],this.nodes[s].unselect();for(this.selection=[],e=0,i=t.length;i>e;e++){s=t[e];var n=this.nodes[s];if(!n)throw new RangeError('Node with id "'+s+'" not found');n.select(),this.selection.push(s)}this.redraw()},M.prototype._updateSelection=function(){for(var t=0;this.selection.length>t;){var e=this.selection[t];this.nodes[e]?t++:this.selection.splice(t,1)}},M.prototype._getConnectionCount=function(t){function e(t){for(var e=[],i=0,s=t.length;s>i;i++)for(var n=t[i],o=n.edges,r=0,a=o.length;a>r;r++){var h=o[r],d=null;h.from==n?d=h.to:h.to==n&&(d=h.from);var l,p;if(d)for(l=0,p=t.length;p>l;l++)if(t[l]==d){d=null;break}if(d)for(l=0,p=e.length;p>l;l++)if(e[l]==d){d=null;break}d&&e.push(d)}return e}void 0==t&&(t=1);var i=[],s=this.nodes;for(var n in s)if(s.hasOwnProperty(n)){for(var o=[s[n]],r=0;t>r;r++)o=o.concat(e(o));i.push(o)}for(var a=[],h=0,d=i.length;d>h;h++)a.push(i[h].length);return a},M.prototype.setSize=function(t,e){this.frame.style.width=t,this.frame.style.height=e,this.frame.canvas.style.width="100%",this.frame.canvas.style.height="100%",this.frame.canvas.width=this.frame.canvas.clientWidth,this.frame.canvas.height=this.frame.canvas.clientHeight},M.prototype._setNodes=function(t){var e=this.nodesData;if(t instanceof o||t instanceof r)this.nodesData=t;else if(t instanceof Array)this.nodesData=new o,this.nodesData.add(t);else{if(t)throw new TypeError("Array or DataSet expected");this.nodesData=new o}if(e&&D.forEach(this.nodesListeners,function(t,i){e.unsubscribe(i,t)}),this.nodes={},this.nodesData){var i=this;D.forEach(this.nodesListeners,function(t,e){i.nodesData.subscribe(e,t)});var s=this.nodesData.getIds();this._addNodes(s)}this._updateSelection()},M.prototype._addNodes=function(t){for(var e,i=0,s=t.length;s>i;i++){e=t[i];var n=this.nodesData.get(e),o=new x(n,this.images,this.groups,this.constants);if(this.nodes[e]=o,!o.isFixed()){var r=2*this.constants.edges.length,a=t.length,h=2*Math.PI*(i/a);o.x=r*Math.cos(h),o.y=r*Math.sin(h),this.moving=!0}}this._reconnectEdges(),this._updateValueRange(this.nodes)},M.prototype._updateNodes=function(t){for(var e=this.nodes,i=this.nodesData,s=0,n=t.length;n>s;s++){var o=t[s],r=e[o],a=i.get(o);r?r.setProperties(a,this.constants):(r=new x(properties,this.images,this.groups,this.constants),e[o]=r,r.isFixed()||(this.moving=!0))}this._reconnectEdges(),this._updateValueRange(e)},M.prototype._removeNodes=function(t){for(var e=this.nodes,i=0,s=t.length;s>i;i++){var n=t[i];delete e[n]}this._reconnectEdges(),this._updateSelection(),this._updateValueRange(e)},M.prototype._setEdges=function(t){var e=this.edgesData;if(t instanceof o||t instanceof r)this.edgesData=t;else if(t instanceof Array)this.edgesData=new o,this.edgesData.add(t);else{if(t)throw new TypeError("Array or DataSet expected");this.edgesData=new o}if(e&&D.forEach(this.edgesListeners,function(t,i){e.unsubscribe(i,t)}),this.edges={},this.edgesData){var i=this;D.forEach(this.edgesListeners,function(t,e){i.edgesData.subscribe(e,t)});var s=this.edgesData.getIds();this._addEdges(s)}this._reconnectEdges()},M.prototype._addEdges=function(t){for(var e=this.edges,i=this.edgesData,s=0,n=t.length;n>s;s++){var o=t[s],r=e[o];r&&r.disconnect();var a=i.get(o);e[o]=new T(a,this,this.constants)}this.moving=!0,this._updateValueRange(e)},M.prototype._updateEdges=function(t){for(var e=this.edges,i=this.edgesData,s=0,n=t.length;n>s;s++){var o=t[s],r=i.get(o),a=e[o];a?(a.disconnect(),a.setProperties(r,this.constants),a.connect()):(a=new T(r,this,this.constants),this.edges[o]=a)}this.moving=!0,this._updateValueRange(e)},M.prototype._removeEdges=function(t){for(var e=this.edges,i=0,s=t.length;s>i;i++){var n=t[i],o=e[n];o&&(o.disconnect(),delete e[n])}this.moving=!0,this._updateValueRange(e)},M.prototype._reconnectEdges=function(){var t,e=this.nodes,i=this.edges;for(t in e)e.hasOwnProperty(t)&&(e[t].edges=[]);for(t in i)if(i.hasOwnProperty(t)){var s=i[t];s.from=null,s.to=null,s.connect()}},M.prototype._updateValueRange=function(t){var e,i=void 0,s=void 0;for(e in t)if(t.hasOwnProperty(e)){var n=t[e].getValue();void 0!==n&&(i=void 0===i?n:Math.min(n,i),s=void 0===s?n:Math.max(n,s))}if(void 0!==i&&void 0!==s)for(e in t)t.hasOwnProperty(e)&&t[e].setValueRange(i,s)},M.prototype.redraw=function(){this.setSize(this.width,this.height),this._redraw()},M.prototype._redraw=function(){var t=this.frame.canvas.getContext("2d"),e=this.frame.canvas.width,i=this.frame.canvas.height;t.clearRect(0,0,e,i),t.save(),t.translate(this.translation.x,this.translation.y),t.scale(this.scale,this.scale),this._drawEdges(t),this._drawNodes(t),t.restore()},M.prototype._setTranslation=function(t,e){void 0===this.translation&&(this.translation={x:0,y:0}),void 0!==t&&(this.translation.x=t),void 0!==e&&(this.translation.y=e)},M.prototype._getTranslation=function(){return{x:this.translation.x,y:this.translation.y}},M.prototype._setScale=function(t){this.scale=t},M.prototype._getScale=function(){return this.scale},M.prototype._xToCanvas=function(t){return(t-this.translation.x)/this.scale},M.prototype._canvasToX=function(t){return t*this.scale+this.translation.x},M.prototype._yToCanvas=function(t){return(t-this.translation.y)/this.scale},M.prototype._canvasToY=function(t){return t*this.scale+this.translation.y},M.prototype._drawNodes=function(t){var e=this.nodes,i=[];for(var s in e)e.hasOwnProperty(s)&&(e[s].isSelected()?i.push(s):e[s].draw(t));for(var n=0,o=i.length;o>n;n++)e[i[n]].draw(t)},M.prototype._drawEdges=function(t){var e=this.edges;for(var i in e)if(e.hasOwnProperty(i)){var s=e[i];s.connected&&e[i].draw(t)}},M.prototype._doStabilize=function(){new Date;for(var t=0,e=this.constants.minVelocity,i=!1;!i&&this.constants.maxIterations>t;)this._calculateForces(),this._discreteStepNodes(),i=!this._isMoving(e),t++;new Date},M.prototype._calculateForces=function(){var t,e,i,s,n,o,r,a,h,d,l,p=this.nodes,c=this.edges,u=.01,f=this.frame.canvas.clientWidth/2,m=this.frame.canvas.clientHeight/2;for(t in p)if(p.hasOwnProperty(t)){var g=p[t];e=f-g.x,i=m-g.y,s=Math.atan2(i,e),o=Math.cos(s)*u,r=Math.sin(s)*u,g._setForce(o,r)}var v=this.constants.nodes.distance,y=10;for(var b in p)if(p.hasOwnProperty(b)){var w=p[b];for(var _ in p)if(p.hasOwnProperty(_)){var x=p[_];e=x.x-w.x,i=x.y-w.y,n=Math.sqrt(e*e+i*i),s=Math.atan2(i,e),a=1/(1+Math.exp((n/v-1)*y)),o=Math.cos(s)*a,r=Math.sin(s)*a,w._addForce(-o,-r),x._addForce(o,r)}}for(t in c)if(c.hasOwnProperty(t)){var T=c[t];T.connected&&(e=T.to.x-T.from.x,i=T.to.y-T.from.y,l=T.length,d=Math.sqrt(e*e+i*i),s=Math.atan2(i,e),h=T.stiffness*(l-d),o=Math.cos(s)*h,r=Math.sin(s)*h,T.from._addForce(-o,-r),T.to._addForce(o,r))}},M.prototype._isMoving=function(t){var e=this.nodes;for(var i in e)if(e.hasOwnProperty(i)&&e[i].isMoving(t))return!0;return!1},M.prototype._discreteStepNodes=function(){var t=this.refreshRate/1e3,e=this.nodes;for(var i in e)e.hasOwnProperty(i)&&e[i].discreteStep(t)},M.prototype.start=function(){if(this.moving){this._calculateForces(),this._discreteStepNodes();var t=this.constants.minVelocity;this.moving=this._isMoving(t)}if(this.moving){if(!this.timer){var e=this;this.timer=window.setTimeout(function(){e.timer=void 0,e.start(),e._redraw()},this.refreshRate)}}else this._redraw()},M.prototype.stop=function(){this.timer&&(window.clearInterval(this.timer),this.timer=void 0)};var N={util:D,events:O,Controller:d,DataSet:o,DataView:r,Range:h,Stack:a,TimeStep:TimeStep,EventBus:n,components:{items:{Item:m,ItemBox:g,ItemPoint:v,ItemRange:y},Component:l,Panel:p,RootPanel:c,ItemSet:f,TimeAxis:u},graph:{Node:x,Edge:T,Popup:S,Groups:Groups,Images:Images},Timeline:_,Graph:M};s!==void 0&&(s=N),i!==void 0&&i.exports!==void 0&&(i.exports=N),"function"==typeof t&&t(function(){return N}),"undefined"!=typeof window&&(window.vis=N),D.loadCss("/* vis.js stylesheet */\n.vis.timeline {\n}\n\n\n.vis.timeline.rootpanel {\n position: relative;\n overflow: hidden;\n\n border: 1px solid #bfbfbf;\n -moz-box-sizing: border-box;\n box-sizing: border-box;\n}\n\n.vis.timeline .panel {\n position: absolute;\n overflow: hidden;\n}\n\n\n.vis.timeline .groupset {\n position: absolute;\n padding: 0;\n margin: 0;\n}\n\n.vis.timeline .labels {\n position: absolute;\n top: 0;\n left: 0;\n width: 100%;\n height: 100%;\n\n padding: 0;\n margin: 0;\n\n border-right: 1px solid #bfbfbf;\n box-sizing: border-box;\n -moz-box-sizing: border-box;\n}\n\n.vis.timeline .labels .label {\n position: absolute;\n left: 0;\n top: 0;\n width: 100%;\n border-bottom: 1px solid #bfbfbf;\n color: #4d4d4d;\n}\n\n.vis.timeline .labels .label .inner {\n display: inline-block;\n padding: 5px;\n}\n\n\n.vis.timeline .itemset {\n position: absolute;\n padding: 0;\n margin: 0;\n overflow: hidden;\n}\n\n.vis.timeline .background {\n}\n\n.vis.timeline .foreground {\n}\n\n.vis.timeline .itemset-axis {\n position: absolute;\n}\n\n.vis.timeline .groupset .itemset-axis {\n border-top: 1px solid #bfbfbf;\n}\n\n/* TODO: with orientation=='bottom', this will more or less overlap with timeline axis\n.vis.timeline .groupset .itemset-axis:last-child {\n border-top: none;\n}\n*/\n\n\n.vis.timeline .item {\n position: absolute;\n color: #1A1A1A;\n border-color: #97B0F8;\n background-color: #D5DDF6;\n display: inline-block;\n}\n\n.vis.timeline .item.selected {\n border-color: #FFC200;\n background-color: #FFF785;\n z-index: 999;\n}\n\n.vis.timeline .item.cluster {\n /* TODO: use another color or pattern? */\n background: #97B0F8 url('img/cluster_bg.png');\n color: white;\n}\n.vis.timeline .item.cluster.point {\n border-color: #D5DDF6;\n}\n\n.vis.timeline .item.box {\n text-align: center;\n border-style: solid;\n border-width: 1px;\n border-radius: 5px;\n -moz-border-radius: 5px; /* For Firefox 3.6 and older */\n}\n\n.vis.timeline .item.point {\n background: none;\n}\n\n.vis.timeline .dot {\n border: 5px solid #97B0F8;\n position: absolute;\n border-radius: 5px;\n -moz-border-radius: 5px; /* For Firefox 3.6 and older */\n}\n\n.vis.timeline .item.range {\n overflow: hidden;\n border-style: solid;\n border-width: 1px;\n border-radius: 2px;\n -moz-border-radius: 2px; /* For Firefox 3.6 and older */\n}\n\n.vis.timeline .item.range .drag-left {\n cursor: w-resize;\n z-index: 1000;\n}\n\n.vis.timeline .item.range .drag-right {\n cursor: e-resize;\n z-index: 1000;\n}\n\n.vis.timeline .item.range .content {\n position: relative;\n display: inline-block;\n}\n\n.vis.timeline .item.line {\n position: absolute;\n width: 0;\n border-left-width: 1px;\n border-left-style: solid;\n}\n\n.vis.timeline .item .content {\n margin: 5px;\n white-space: nowrap;\n overflow: hidden;\n}\n\n.vis.timeline .axis {\n position: relative;\n}\n\n.vis.timeline .axis .text {\n position: absolute;\n color: #4d4d4d;\n padding: 3px;\n white-space: nowrap;\n}\n\n.vis.timeline .axis .text.measure {\n position: absolute;\n padding-left: 0;\n padding-right: 0;\n margin-left: 0;\n margin-right: 0;\n visibility: hidden;\n}\n\n.vis.timeline .axis .grid.vertical {\n position: absolute;\n width: 0;\n border-right: 1px solid;\n}\n\n.vis.timeline .axis .grid.horizontal {\n position: absolute;\n left: 0;\n width: 100%;\n height: 0;\n border-bottom: 1px solid;\n}\n\n.vis.timeline .axis .grid.minor {\n border-color: #e5e5e5;\n}\n\n.vis.timeline .axis .grid.major {\n border-color: #bfbfbf;\n}\n\n")})()},{moment:2}],2:[function(e,i){(function(){(function(s){function n(t,e){return function(i){return p(t.call(this,i),e)}}function o(t){return function(e){return this.lang().ordinal(t.call(this,e))}}function r(){}function a(t){d(this,t)}function h(t){var e=this._data={},i=t.years||t.year||t.y||0,s=t.months||t.month||t.M||0,n=t.weeks||t.week||t.w||0,o=t.days||t.day||t.d||0,r=t.hours||t.hour||t.h||0,a=t.minutes||t.minute||t.m||0,h=t.seconds||t.second||t.s||0,d=t.milliseconds||t.millisecond||t.ms||0;this._milliseconds=d+1e3*h+6e4*a+36e5*r,this._days=o+7*n,this._months=s+12*i,e.milliseconds=d%1e3,h+=l(d/1e3),e.seconds=h%60,a+=l(h/60),e.minutes=a%60,r+=l(a/60),e.hours=r%24,o+=l(r/24),o+=7*n,e.days=o%30,s+=l(o/30),e.months=s%12,i+=l(s/12),e.years=i}function d(t,e){for(var i in e)e.hasOwnProperty(i)&&(t[i]=e[i]);return t}function l(t){return 0>t?Math.ceil(t):Math.floor(t)}function p(t,e){for(var i=t+"";e>i.length;)i="0"+i;return i}function c(t,e,i){var s,n=e._milliseconds,o=e._days,r=e._months;n&&t._d.setTime(+t+n*i),o&&t.date(t.date()+o*i),r&&(s=t.date(),t.date(1).month(t.month()+r*i).date(Math.min(s,t.daysInMonth())))}function u(t){return"[object Array]"===Object.prototype.toString.call(t)}function f(t,e){var i,s=Math.min(t.length,e.length),n=Math.abs(t.length-e.length),o=0;for(i=0;s>i;i++)~~t[i]!==~~e[i]&&o++;return o+n}function m(t,e){return e.abbr=t,z[t]||(z[t]=new r),z[t].set(e),z[t]}function g(t){return t?(!z[t]&&R&&e("./lang/"+t),z[t]):I.fn._lang}function v(t){return t.match(/\[.*\]/)?t.replace(/^\[|\]$/g,""):t.replace(/\\/g,"")}function y(t){var e,i,s=t.match(j);for(e=0,i=s.length;i>e;e++)s[e]=ae[s[e]]?ae[s[e]]:v(s[e]);return function(n){var o="";for(e=0;i>e;e++)o+="function"==typeof s[e].call?s[e].call(n,t):s[e];return o}}function b(t,e){function i(e){return t.lang().longDateFormat(e)||e}for(var s=5;s--&&U.test(e);)e=e.replace(U,i);return ne[e]||(ne[e]=y(e)),ne[e](t)}function w(t){switch(t){case"DDDD":return q;case"YYYY":return V;case"YYYYY":return X;case"S":case"SS":case"SSS":case"DDD":return B;case"MMM":case"MMMM":case"dd":case"ddd":case"dddd":case"a":case"A":return K;case"X":return J;case"Z":case"ZZ":return G;case"T":return Z;case"MM":case"DD":case"YY":case"HH":case"hh":case"mm":case"ss":case"M":case"D":case"d":case"H":case"h":case"m":case"s":return W;default:return RegExp(t.replace("\\",""))}}function _(t,e,i){var s,n=i._a;switch(t){case"M":case"MM":n[1]=null==e?0:~~e-1;break;case"MMM":case"MMMM":s=g(i._l).monthsParse(e),null!=s?n[1]=s:i._isValid=!1;break;case"D":case"DD":case"DDD":case"DDDD":null!=e&&(n[2]=~~e);break;case"YY":n[0]=~~e+(~~e>68?1900:2e3);break;case"YYYY":case"YYYYY":n[0]=~~e;break;case"a":case"A":i._isPm="pm"===(e+"").toLowerCase();break;case"H":case"HH":case"h":case"hh":n[3]=~~e;break;case"m":case"mm":n[4]=~~e;break;case"s":case"ss":n[5]=~~e;break;case"S":case"SS":case"SSS":n[6]=~~(1e3*("0."+e));break;case"X":i._d=new Date(1e3*parseFloat(e));break;case"Z":case"ZZ":i._useUTC=!0,s=(e+"").match(ee),s&&s[1]&&(i._tzh=~~s[1]),s&&s[2]&&(i._tzm=~~s[2]),s&&"+"===s[0]&&(i._tzh=-i._tzh,i._tzm=-i._tzm)}null==e&&(i._isValid=!1)}function x(t){var e,i,s=[];if(!t._d){for(e=0;7>e;e++)t._a[e]=s[e]=null==t._a[e]?2===e?1:0:t._a[e];s[3]+=t._tzh||0,s[4]+=t._tzm||0,i=new Date(0),t._useUTC?(i.setUTCFullYear(s[0],s[1],s[2]),i.setUTCHours(s[3],s[4],s[5],s[6])):(i.setFullYear(s[0],s[1],s[2]),i.setHours(s[3],s[4],s[5],s[6])),t._d=i}}function T(t){var e,i,s=t._f.match(j),n=t._i;for(t._a=[],e=0;s.length>e;e++)i=(w(s[e]).exec(n)||[])[0],i&&(n=n.slice(n.indexOf(i)+i.length)),ae[s[e]]&&_(s[e],i,t);t._isPm&&12>t._a[3]&&(t._a[3]+=12),t._isPm===!1&&12===t._a[3]&&(t._a[3]=0),x(t)}function S(t){for(var e,i,s,n,o=99;t._f.length;){if(e=d({},t),e._f=t._f.pop(),T(e),i=new a(e),i.isValid()){s=i;break}n=f(e._a,i.toArray()),o>n&&(o=n,s=i)}d(t,s)}function M(t){var e,i=t._i;if(Q.exec(i)){for(t._f="YYYY-MM-DDT",e=0;4>e;e++)if(te[e][1].exec(i)){t._f+=te[e][0];break}G.exec(i)&&(t._f+=" Z"),T(t)}else t._d=new Date(i)}function E(t){var e=t._i,i=H.exec(e);e===s?t._d=new Date:i?t._d=new Date(+i[1]):"string"==typeof e?M(t):u(e)?(t._a=e.slice(0),x(t)):t._d=e instanceof Date?new Date(+e):new Date(e)}function D(t,e,i,s,n){return n.relativeTime(e||1,!!i,t,s)}function C(t,e,i){var s=Y(Math.abs(t)/1e3),n=Y(s/60),o=Y(n/60),r=Y(o/24),a=Y(r/365),h=45>s&&["s",s]||1===n&&["m"]||45>n&&["mm",n]||1===o&&["h"]||22>o&&["hh",o]||1===r&&["d"]||25>=r&&["dd",r]||45>=r&&["M"]||345>r&&["MM",Y(r/30)]||1===a&&["y"]||["yy",a];return h[2]=e,h[3]=t>0,h[4]=i,D.apply({},h)}function L(t,e,i){var s=i-e,n=i-t.day();return n>s&&(n-=7),s-7>n&&(n+=7),Math.ceil(I(t).add("d",n).dayOfYear()/7)}function O(t){var e=t._i,i=t._f;return null===e||""===e?null:("string"==typeof e&&(t._i=e=g().preparse(e)),I.isMoment(e)?(t=d({},e),t._d=new Date(+e._d)):i?u(i)?S(t):T(t):E(t),new a(t))}function N(t,e){I.fn[t]=I.fn[t+"s"]=function(t){var i=this._isUTC?"UTC":"";return null!=t?(this._d["set"+i+e](t),this):this._d["get"+i+e]()}}function A(t){I.duration.fn[t]=function(){return this._data[t]}}function k(t,e){I.duration.fn["as"+t]=function(){return+this/e}}for(var I,F,P="2.0.0",Y=Math.round,z={},R=i!==s&&i.exports,H=/^\/?Date\((\-?\d+)/i,j=/(\[[^\[]*\])|(\\)?(Mo|MM?M?M?|Do|DDDo|DD?D?D?|ddd?d?|do?|w[o|w]?|W[o|W]?|YYYYY|YYYY|YY|a|A|hh?|HH?|mm?|ss?|SS?S?|X|zz?|ZZ?|.)/g,U=/(\[[^\[]*\])|(\\)?(LT|LL?L?L?|l{1,4})/g,W=/\d\d?/,B=/\d{1,3}/,q=/\d{3}/,V=/\d{1,4}/,X=/[+\-]?\d{1,6}/,K=/[0-9]*[a-z\u00A0-\u05FF\u0700-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF]+|[\u0600-\u06FF]+\s*?[\u0600-\u06FF]+/i,G=/Z|[\+\-]\d\d:?\d\d/i,Z=/T/i,J=/[\+\-]?\d+(\.\d{1,3})?/,Q=/^\s*\d{4}-\d\d-\d\d((T| )(\d\d(:\d\d(:\d\d(\.\d\d?\d?)?)?)?)?([\+\-]\d\d:?\d\d)?)?/,$="YYYY-MM-DDTHH:mm:ssZ",te=[["HH:mm:ss.S",/(T| )\d\d:\d\d:\d\d\.\d{1,3}/],["HH:mm:ss",/(T| )\d\d:\d\d:\d\d/],["HH:mm",/(T| )\d\d:\d\d/],["HH",/(T| )\d\d/]],ee=/([\+\-]|\d\d)/gi,ie="Month|Date|Hours|Minutes|Seconds|Milliseconds".split("|"),se={Milliseconds:1,Seconds:1e3,Minutes:6e4,Hours:36e5,Days:864e5,Months:2592e6,Years:31536e6},ne={},oe="DDD w W M D d".split(" "),re="M D H h m s w W".split(" "),ae={M:function(){return this.month()+1},MMM:function(t){return this.lang().monthsShort(this,t)},MMMM:function(t){return this.lang().months(this,t)},D:function(){return this.date()},DDD:function(){return this.dayOfYear()},d:function(){return this.day()},dd:function(t){return this.lang().weekdaysMin(this,t)},ddd:function(t){return this.lang().weekdaysShort(this,t)},dddd:function(t){return this.lang().weekdays(this,t)},w:function(){return this.week()},W:function(){return this.isoWeek()},YY:function(){return p(this.year()%100,2)},YYYY:function(){return p(this.year(),4)},YYYYY:function(){return p(this.year(),5)},a:function(){return this.lang().meridiem(this.hours(),this.minutes(),!0)},A:function(){return this.lang().meridiem(this.hours(),this.minutes(),!1)},H:function(){return this.hours()},h:function(){return this.hours()%12||12},m:function(){return this.minutes()},s:function(){return this.seconds()},S:function(){return~~(this.milliseconds()/100)},SS:function(){return p(~~(this.milliseconds()/10),2)},SSS:function(){return p(this.milliseconds(),3)},Z:function(){var t=-this.zone(),e="+";return 0>t&&(t=-t,e="-"),e+p(~~(t/60),2)+":"+p(~~t%60,2)},ZZ:function(){var t=-this.zone(),e="+";return 0>t&&(t=-t,e="-"),e+p(~~(10*t/6),4)},X:function(){return this.unix()}};oe.length;)F=oe.pop(),ae[F+"o"]=o(ae[F]);for(;re.length;)F=re.pop(),ae[F+F]=n(ae[F],2);for(ae.DDDD=n(ae.DDD,3),r.prototype={set:function(t){var e,i;for(i in t)e=t[i],"function"==typeof e?this[i]=e:this["_"+i]=e +},_months:"January_February_March_April_May_June_July_August_September_October_November_December".split("_"),months:function(t){return this._months[t.month()]},_monthsShort:"Jan_Feb_Mar_Apr_May_Jun_Jul_Aug_Sep_Oct_Nov_Dec".split("_"),monthsShort:function(t){return this._monthsShort[t.month()]},monthsParse:function(t){var e,i,s;for(this._monthsParse||(this._monthsParse=[]),e=0;12>e;e++)if(this._monthsParse[e]||(i=I([2e3,e]),s="^"+this.months(i,"")+"|^"+this.monthsShort(i,""),this._monthsParse[e]=RegExp(s.replace(".",""),"i")),this._monthsParse[e].test(t))return e},_weekdays:"Sunday_Monday_Tuesday_Wednesday_Thursday_Friday_Saturday".split("_"),weekdays:function(t){return this._weekdays[t.day()]},_weekdaysShort:"Sun_Mon_Tue_Wed_Thu_Fri_Sat".split("_"),weekdaysShort:function(t){return this._weekdaysShort[t.day()]},_weekdaysMin:"Su_Mo_Tu_We_Th_Fr_Sa".split("_"),weekdaysMin:function(t){return this._weekdaysMin[t.day()]},_longDateFormat:{LT:"h:mm A",L:"MM/DD/YYYY",LL:"MMMM D YYYY",LLL:"MMMM D YYYY LT",LLLL:"dddd, MMMM D YYYY LT"},longDateFormat:function(t){var e=this._longDateFormat[t];return!e&&this._longDateFormat[t.toUpperCase()]&&(e=this._longDateFormat[t.toUpperCase()].replace(/MMMM|MM|DD|dddd/g,function(t){return t.slice(1)}),this._longDateFormat[t]=e),e},meridiem:function(t,e,i){return t>11?i?"pm":"PM":i?"am":"AM"},_calendar:{sameDay:"[Today at] LT",nextDay:"[Tomorrow at] LT",nextWeek:"dddd [at] LT",lastDay:"[Yesterday at] LT",lastWeek:"[last] dddd [at] LT",sameElse:"L"},calendar:function(t,e){var i=this._calendar[t];return"function"==typeof i?i.apply(e):i},_relativeTime:{future:"in %s",past:"%s ago",s:"a few seconds",m:"a minute",mm:"%d minutes",h:"an hour",hh:"%d hours",d:"a day",dd:"%d days",M:"a month",MM:"%d months",y:"a year",yy:"%d years"},relativeTime:function(t,e,i,s){var n=this._relativeTime[i];return"function"==typeof n?n(t,e,i,s):n.replace(/%d/i,t)},pastFuture:function(t,e){var i=this._relativeTime[t>0?"future":"past"];return"function"==typeof i?i(e):i.replace(/%s/i,e)},ordinal:function(t){return this._ordinal.replace("%d",t)},_ordinal:"%d",preparse:function(t){return t},postformat:function(t){return t},week:function(t){return L(t,this._week.dow,this._week.doy)},_week:{dow:0,doy:6}},I=function(t,e,i){return O({_i:t,_f:e,_l:i,_isUTC:!1})},I.utc=function(t,e,i){return O({_useUTC:!0,_isUTC:!0,_l:i,_i:t,_f:e})},I.unix=function(t){return I(1e3*t)},I.duration=function(t,e){var i,s=I.isDuration(t),n="number"==typeof t,o=s?t._data:n?{}:t;return n&&(e?o[e]=t:o.milliseconds=t),i=new h(o),s&&t.hasOwnProperty("_lang")&&(i._lang=t._lang),i},I.version=P,I.defaultFormat=$,I.lang=function(t,e){return t?(e?m(t,e):z[t]||g(t),I.duration.fn._lang=I.fn._lang=g(t),s):I.fn._lang._abbr},I.langData=function(t){return t&&t._lang&&t._lang._abbr&&(t=t._lang._abbr),g(t)},I.isMoment=function(t){return t instanceof a},I.isDuration=function(t){return t instanceof h},I.fn=a.prototype={clone:function(){return I(this)},valueOf:function(){return+this._d},unix:function(){return Math.floor(+this._d/1e3)},toString:function(){return this.format("ddd MMM DD YYYY HH:mm:ss [GMT]ZZ")},toDate:function(){return this._d},toJSON:function(){return I.utc(this).format("YYYY-MM-DD[T]HH:mm:ss.SSS[Z]")},toArray:function(){var t=this;return[t.year(),t.month(),t.date(),t.hours(),t.minutes(),t.seconds(),t.milliseconds()]},isValid:function(){return null==this._isValid&&(this._isValid=this._a?!f(this._a,(this._isUTC?I.utc(this._a):I(this._a)).toArray()):!isNaN(this._d.getTime())),!!this._isValid},utc:function(){return this._isUTC=!0,this},local:function(){return this._isUTC=!1,this},format:function(t){var e=b(this,t||I.defaultFormat);return this.lang().postformat(e)},add:function(t,e){var i;return i="string"==typeof t?I.duration(+e,t):I.duration(t,e),c(this,i,1),this},subtract:function(t,e){var i;return i="string"==typeof t?I.duration(+e,t):I.duration(t,e),c(this,i,-1),this},diff:function(t,e,i){var s,n,o=this._isUTC?I(t).utc():I(t).local(),r=6e4*(this.zone()-o.zone());return e&&(e=e.replace(/s$/,"")),"year"===e||"month"===e?(s=432e5*(this.daysInMonth()+o.daysInMonth()),n=12*(this.year()-o.year())+(this.month()-o.month()),n+=(this-I(this).startOf("month")-(o-I(o).startOf("month")))/s,"year"===e&&(n/=12)):(s=this-o-r,n="second"===e?s/1e3:"minute"===e?s/6e4:"hour"===e?s/36e5:"day"===e?s/864e5:"week"===e?s/6048e5:s),i?n:l(n)},from:function(t,e){return I.duration(this.diff(t)).lang(this.lang()._abbr).humanize(!e)},fromNow:function(t){return this.from(I(),t)},calendar:function(){var t=this.diff(I().startOf("day"),"days",!0),e=-6>t?"sameElse":-1>t?"lastWeek":0>t?"lastDay":1>t?"sameDay":2>t?"nextDay":7>t?"nextWeek":"sameElse";return this.format(this.lang().calendar(e,this))},isLeapYear:function(){var t=this.year();return 0===t%4&&0!==t%100||0===t%400},isDST:function(){return this.zone()+I(t).startOf(e)},isBefore:function(t,e){return e=e!==s?e:"millisecond",+this.clone().startOf(e)<+I(t).startOf(e)},isSame:function(t,e){return e=e!==s?e:"millisecond",+this.clone().startOf(e)===+I(t).startOf(e)},zone:function(){return this._isUTC?0:this._d.getTimezoneOffset()},daysInMonth:function(){return I.utc([this.year(),this.month()+1,0]).date()},dayOfYear:function(t){var e=Y((I(this).startOf("day")-I(this).startOf("year"))/864e5)+1;return null==t?e:this.add("d",t-e)},isoWeek:function(t){var e=L(this,1,4);return null==t?e:this.add("d",7*(t-e))},week:function(t){var e=this.lang().week(this);return null==t?e:this.add("d",7*(t-e))},lang:function(t){return t===s?this._lang:(this._lang=g(t),this)}},F=0;ie.length>F;F++)N(ie[F].toLowerCase().replace(/s$/,""),ie[F]);N("year","FullYear"),I.fn.days=I.fn.day,I.fn.weeks=I.fn.week,I.fn.isoWeeks=I.fn.isoWeek,I.duration.fn=h.prototype={weeks:function(){return l(this.days()/7)},valueOf:function(){return this._milliseconds+864e5*this._days+2592e6*this._months},humanize:function(t){var e=+this,i=C(e,!t,this.lang());return t&&(i=this.lang().pastFuture(e,i)),this.lang().postformat(i)},lang:I.fn.lang};for(F in se)se.hasOwnProperty(F)&&(k(F,se[F]),A(F.toLowerCase()));k("Weeks",6048e5),I.lang("en",{ordinal:function(t){var e=t%10,i=1===~~(t%100/10)?"th":1===e?"st":2===e?"nd":3===e?"rd":"th";return t+i}}),R&&(i.exports=I),"undefined"==typeof ender&&(this.moment=I),"function"==typeof t&&t.amd&&t("moment",[],function(){return I})}).call(this)})()},{}]},{},[1])(1)}); \ No newline at end of file From b8e8bf714141e214d8f6fef74bbf5eacbe2ef9eb Mon Sep 17 00:00:00 2001 From: josdejong Date: Mon, 9 Sep 2013 10:39:00 +0200 Subject: [PATCH 02/18] Fixed #11: initial empty range in the Timeline in case of a single item --- HISTORY.md | 1 + examples/graph/17_network_info.html | 6 +----- src/timeline/Timeline.js | 4 ++++ src/timeline/component/Group.js | 1 - src/timeline/component/ItemSet.js | 2 +- vis.js | 11 +++++++---- vis.min.js | 10 +++++----- 7 files changed, 19 insertions(+), 16 deletions(-) diff --git a/HISTORY.md b/HISTORY.md index 0c7ab523..f060ba8c 100644 --- a/HISTORY.md +++ b/HISTORY.md @@ -4,6 +4,7 @@ http://visjs.org ## (not yet released), version 0.1.1 +- Fixed initial empty range in the Timeline in case of a single item. - Fixed field `className` not working for items. diff --git a/examples/graph/17_network_info.html b/examples/graph/17_network_info.html index ebec84f8..80cd30ee 100644 --- a/examples/graph/17_network_info.html +++ b/examples/graph/17_network_info.html @@ -24,11 +24,7 @@ var edges = null; var graph = null; - var DIR = 'img/refresh-cl/', - SWITCH = DIR + 'Network-Pipe-icon.png', - COMPUTER = DIR + 'Hardware-My-Computer-3-icon.png', - PRINTER = DIR + 'Hardware-Printer-Blue-icon.png', - LENGTH_MAIN = 350, + var LENGTH_MAIN = 350, LENGTH_SERVER = 150, LENGTH_SUB = 50, GREEN = 'green', diff --git a/src/timeline/Timeline.js b/src/timeline/Timeline.js index b7e07ea3..10ea6add 100644 --- a/src/timeline/Timeline.js +++ b/src/timeline/Timeline.js @@ -174,6 +174,10 @@ Timeline.prototype.setItems = function(items) { var max = dataRange.max; if (min != null && max != null) { var interval = (max.valueOf() - min.valueOf()); + if (interval <= 0) { + // prevent an empty interval + interval = 24 * 60 * 60 * 1000; // 1 day + } min = new Date(min.valueOf() - interval * 0.05); max = new Date(max.valueOf() + interval * 0.05); } diff --git a/src/timeline/component/Group.js b/src/timeline/component/Group.js index d30b885d..1198cd3c 100644 --- a/src/timeline/component/Group.js +++ b/src/timeline/component/Group.js @@ -11,7 +11,6 @@ function Group (parent, groupId, options) { this.parent = parent; this.groupId = groupId; - this.itemsData = null; // DataSet this.itemset = null; // ItemSet this.options = options || {}; this.options.top = 0; diff --git a/src/timeline/component/ItemSet.js b/src/timeline/component/ItemSet.js index 5e643108..be407df4 100644 --- a/src/timeline/component/ItemSet.js +++ b/src/timeline/component/ItemSet.js @@ -193,7 +193,7 @@ ItemSet.prototype.repaint = function repaint() { items = this.items, dataOptions = { // TODO: cleanup - //fields: [(itemsData && itemsData.fieldId || 'id'), 'start', 'end', 'content', 'type'] + // fields: [(itemsData && itemsData.fieldId || 'id'), 'start', 'end', 'content', 'type', 'className'] }; // show/hide added/changed/removed items diff --git a/vis.js b/vis.js index c7bd01fd..0abe3d53 100644 --- a/vis.js +++ b/vis.js @@ -5,7 +5,7 @@ * A dynamic, browser-based visualization library. * * @version 0.2.0-SNAPSHOT - * @date 2013-09-02 + * @date 2013-09-09 * * @license * Copyright (C) 2011-2013 Almende B.V, http://almende.com @@ -3002,7 +3002,7 @@ function Range(options) { this.start = 0; // Number this.end = 0; // Number - // this.options = options || {}; // TODO + // this.options = options || {}; // TODO: fix range options this.options = { min: null, max: null, @@ -4893,7 +4893,7 @@ ItemSet.prototype.repaint = function repaint() { items = this.items, dataOptions = { // TODO: cleanup - //fields: [(itemsData && itemsData.fieldId || 'id'), 'start', 'end', 'content', 'type'] + // fields: [(itemsData && itemsData.fieldId || 'id'), 'start', 'end', 'content', 'type', 'className'] }; // show/hide added/changed/removed items @@ -6150,7 +6150,6 @@ function Group (parent, groupId, options) { this.parent = parent; this.groupId = groupId; - this.itemsData = null; // DataSet this.itemset = null; // ItemSet this.options = options || {}; this.options.top = 0; @@ -6919,6 +6918,10 @@ Timeline.prototype.setItems = function(items) { var max = dataRange.max; if (min != null && max != null) { var interval = (max.valueOf() - min.valueOf()); + if (interval <= 0) { + // prevent an empty interval + interval = 24 * 60 * 60 * 1000; // 1 day + } min = new Date(min.valueOf() - interval * 0.05); max = new Date(max.valueOf() + interval * 0.05); } diff --git a/vis.min.js b/vis.min.js index a4269367..caccd911 100644 --- a/vis.min.js +++ b/vis.min.js @@ -5,7 +5,7 @@ * A dynamic, browser-based visualization library. * * @version 0.2.0-SNAPSHOT - * @date 2013-09-02 + * @date 2013-09-09 * * @license * Copyright (C) 2011-2013 Almende B.V, http://almende.com @@ -22,8 +22,8 @@ * License for the specific language governing permissions and limitations under * the License. */ -(function(t){if("function"==typeof bootstrap)bootstrap("vis",t);else if("object"==typeof exports)module.exports=t();else if("function"==typeof define&&define.amd)define(t);else if("undefined"!=typeof ses){if(!ses.ok())return;ses.makeVis=t}else"undefined"!=typeof window?window.vis=t():global.vis=t()})(function(){var t;return function(t,e,i){function s(i,o){if(!e[i]){if(!t[i]){var r="function"==typeof require&&require;if(!o&&r)return r(i,!0);if(n)return n(i,!0);throw Error("Cannot find module '"+i+"'")}var a=e[i]={exports:{}};t[i][0].call(a.exports,function(e){var n=t[i][1][e];return s(n?n:e)},a,a.exports)}return e[i].exports}for(var n="function"==typeof require&&require,o=0;i.length>o;o++)s(i[o]);return s}({1:[function(e,i,s){(function(){function n(){this.subscriptions=[]}function o(t){if(this.id=D.randomUUID(),this.options=t||{},this.data={},this.fieldId=this.options.fieldId||"id",this.convert={},this.options.convert)for(var e in this.options.convert)if(this.options.convert.hasOwnProperty(e)){var i=this.options.convert[e];this.convert[e]="Date"==i||"ISODate"==i||"ASPDate"==i?"Date":i}this.subscribers={},this.internalIds={}}function r(t,e){this.id=D.randomUUID(),this.data=null,this.ids={},this.options=e||{},this.fieldId="id",this.subscribers={};var i=this;this.listener=function(){i._onEvent.apply(i,arguments)},this.setData(t)}function a(t,e){this.parent=t,this.options=e||{},this.defaultOptions={order:function(t,e){if(t instanceof y){if(e instanceof y){var i=t.data.end-t.data.start,s=e.data.end-e.data.start;return i-s||t.data.start-e.data.start}return-1}return e instanceof y?1:t.data.start-e.data.start},margin:{item:10}},this.ordered=[]}function h(t){this.id=D.randomUUID(),this.start=0,this.end=0,this.options={min:null,max:null,zoomMin:null,zoomMax:null},this.listeners=[],this.setOptions(t)}function d(){this.id=D.randomUUID(),this.components={},this.repaintTimer=void 0,this.reflowTimer=void 0}function l(){this.id=null,this.parent=null,this.depends=null,this.controller=null,this.options=null,this.frame=null,this.top=0,this.left=0,this.width=0,this.height=0}function p(t,e,i){this.id=D.randomUUID(),this.parent=t,this.depends=e,this.options=i||{}}function c(t,e){this.id=D.randomUUID(),this.container=t,this.options=e||{},this.defaultOptions={autoResize:!0},this.listeners={}}function u(t,e,i){this.id=D.randomUUID(),this.parent=t,this.depends=e,this.dom={majorLines:[],majorTexts:[],minorLines:[],minorTexts:[],redundant:{majorLines:[],majorTexts:[],minorLines:[],minorTexts:[]}},this.props={range:{start:0,end:0,minimumStep:0},lineTop:0},this.options=i||{},this.defaultOptions={orientation:"bottom",showMinorLabels:!0,showMajorLabels:!0},this.conversion=null,this.range=null}function f(t,e,i){this.id=D.randomUUID(),this.parent=t,this.depends=e,this.options=i||{},this.defaultOptions={type:"box",align:"center",orientation:"bottom",margin:{axis:20,item:10},padding:5},this.dom={};var s=this;this.itemsData=null,this.range=null,this.listeners={add:function(t,e,i){i!=s.id&&s._onAdd(e.items)},update:function(t,e,i){i!=s.id&&s._onUpdate(e.items)},remove:function(t,e,i){i!=s.id&&s._onRemove(e.items)}},this.items={},this.queue={},this.stack=new a(this,Object.create(this.options)),this.conversion=null}function m(t,e,i,s){this.parent=t,this.data=e,this.dom=null,this.options=i||{},this.defaultOptions=s||{},this.selected=!1,this.visible=!1,this.top=0,this.left=0,this.width=0,this.height=0}function g(t,e,i,s){this.props={dot:{left:0,top:0,width:0,height:0},line:{top:0,left:0,width:0,height:0}},m.call(this,t,e,i,s)}function v(t,e,i,s){this.props={dot:{top:0,width:0,height:0},content:{height:0,marginLeft:0}},m.call(this,t,e,i,s)}function y(t,e,i,s){this.props={content:{left:0,width:0}},m.call(this,t,e,i,s)}function b(t,e,i){this.id=D.randomUUID(),this.parent=t,this.groupId=e,this.itemsData=null,this.itemset=null,this.options=i||{},this.options.top=0,this.props={label:{width:0,height:0}},this.top=0,this.left=0,this.width=0,this.height=0}function w(t,e,i){this.id=D.randomUUID(),this.parent=t,this.depends=e,this.options=i||{},this.range=null,this.itemsData=null,this.groupsData=null,this.groups={},this.dom={},this.props={labels:{width:0}},this.queue={};var s=this;this.listeners={add:function(t,e){s._onAdd(e.items)},update:function(t,e){s._onUpdate(e.items)},remove:function(t,e){s._onRemove(e.items)}}}function _(t,e,i){var s=this;if(this.options=D.extend({orientation:"bottom",min:null,max:null,zoomMin:10,zoomMax:31536e10,showMinorLabels:!0,showMajorLabels:!0,autoResize:!1},i),this.controller=new d,!t)throw Error("No container element provided");var n=Object.create(this.options);n.height=function(){return s.options.height?s.options.height:s.timeaxis.height+s.content.height},this.rootPanel=new c(t,n),this.controller.add(this.rootPanel);var o=Object.create(this.options);o.left=function(){return s.labelPanel.width},o.width=function(){return s.rootPanel.width-s.labelPanel.width},o.top=null,o.height=null,this.itemPanel=new p(this.rootPanel,[],o),this.controller.add(this.itemPanel);var r=Object.create(this.options);r.top=null,r.left=null,r.height=null,r.width=function(){return s.content&&"function"==typeof s.content.getLabelsWidth?s.content.getLabelsWidth():0},this.labelPanel=new p(this.rootPanel,[],r),this.controller.add(this.labelPanel);var a=E().hours(0).minutes(0).seconds(0).milliseconds(0);this.range=new h({start:a.clone().add("days",-3).valueOf(),end:a.clone().add("days",4).valueOf()}),this.range.subscribe(this.rootPanel,"move","horizontal"),this.range.subscribe(this.rootPanel,"zoom","horizontal"),this.range.on("rangechange",function(){var t=!0;s.controller.requestReflow(t)}),this.range.on("rangechanged",function(){var t=!0;s.controller.requestReflow(t)});var l=Object.create(n);l.range=this.range,l.left=null,l.top=null,l.width="100%",l.height=null,this.timeaxis=new u(this.itemPanel,[],l),this.timeaxis.setRange(this.range),this.controller.add(this.timeaxis),this.setGroups(null),this.itemsData=null,this.groupsData=null,e&&this.setItems(e)}function x(t,e,i,s){this.selected=!1,this.edges=[],this.group=s.nodes.group,this.fontSize=s.nodes.fontSize,this.fontFace=s.nodes.fontFace,this.fontColor=s.nodes.fontColor,this.color=s.nodes.color,this.id=void 0,this.shape=s.nodes.shape,this.image=s.nodes.image,this.x=0,this.y=0,this.xFixed=!1,this.yFixed=!1,this.radius=s.nodes.radius,this.radiusFixed=!1,this.radiusMin=s.nodes.radiusMin,this.radiusMax=s.nodes.radiusMax,this.imagelist=e,this.grouplist=i,this.setProperties(t,s),this.mass=50,this.fx=0,this.fy=0,this.vx=0,this.vy=0,this.minForce=s.minForce,this.damping=.9}function T(t,e,i){if(!e)throw"No graph provided";this.graph=e,this.widthMin=i.edges.widthMin,this.widthMax=i.edges.widthMax,this.id=void 0,this.fromId=void 0,this.toId=void 0,this.style=i.edges.style,this.title=void 0,this.width=i.edges.width,this.value=void 0,this.length=i.edges.length,this.from=null,this.to=null,this.connected=!1,this.dash=D.extend({},i.edges.dash),this.stiffness=void 0,this.color=i.edges.color,this.widthFixed=!1,this.lengthFixed=!1,this.setProperties(t,i)}function S(t,e,i,s){this.container=t?t:document.body,this.x=0,this.y=0,this.padding=5,void 0!==e&&void 0!==i&&this.setPosition(e,i),void 0!==s&&this.setText(s),this.frame=document.createElement("div");var n=this.frame.style;n.position="absolute",n.visibility="hidden",n.border="1px solid #666",n.color="black",n.padding=this.padding+"px",n.backgroundColor="#FFFFC6",n.borderRadius="3px",n.MozBorderRadius="3px",n.WebkitBorderRadius="3px",n.boxShadow="3px 3px 10px rgba(128, 128, 128, 0.5)",n.whiteSpace="nowrap",this.container.appendChild(this.frame)}function M(t,e,i){this.containerElement=t,this.width="100%",this.height="100%",this.refreshRate=50,this.stabilize=!0,this.selectable=!0,this.constants={nodes:{radiusMin:5,radiusMax:20,radius:5,distance:100,shape:"ellipse",image:void 0,widthMin:16,widthMax:64,fontColor:"black",fontSize:14,fontFace:"arial",color:{border:"#2B7CE9",background:"#97C2FC",highlight:{border:"#2B7CE9",background:"#D2E5FF"}},borderColor:"#2B7CE9",backgroundColor:"#97C2FC",highlightColor:"#D2E5FF",group:void 0},edges:{widthMin:1,widthMax:15,width:1,style:"line",color:"#343434",fontColor:"#343434",fontSize:14,fontFace:"arial",length:100,dash:{length:10,gap:5,altLength:void 0}},minForce:.05,minVelocity:.02,maxIterations:1e3};var s=this;this.nodes={},this.edges={},this.nodesData=null,this.edgesData=null;var n=this;this.nodesListeners={add:function(t,e){n._addNodes(e.items),n.start()},update:function(t,e){n._updateNodes(e.items),n.start()},remove:function(t,e){n._removeNodes(e.items),n.start()}},this.edgesListeners={add:function(t,e){n._addEdges(e.items),n.start()},update:function(t,e){n._updateEdges(e.items),n.start()},remove:function(t,e){n._removeEdges(e.items),n.start()}},this.groups=new Groups,this.images=new Images,this.images.setOnloadCallback(function(){s._redraw()}),this.moving=!1,this.selection=[],this.timer=void 0,this._create(),this.setOptions(i),this.setData(e)}var E=e("moment"),D={};D.isNumber=function(t){return t instanceof Number||"number"==typeof t},D.isString=function(t){return t instanceof String||"string"==typeof t},D.isDate=function(t){if(t instanceof Date)return!0;if(D.isString(t)){var e=C.exec(t);if(e)return!0;if(!isNaN(Date.parse(t)))return!0}return!1},D.isDataTable=function(t){return"undefined"!=typeof google&&google.visualization&&google.visualization.DataTable&&t instanceof google.visualization.DataTable},D.randomUUID=function(){var t=function(){return Math.floor(65536*Math.random()).toString(16)};return t()+t()+"-"+t()+"-"+t()+"-"+t()+"-"+t()+t()+t()},D.extend=function(t){for(var e=1,i=arguments.length;i>e;e++){var s=arguments[e];for(var n in s)s.hasOwnProperty(n)&&void 0!==s[n]&&(t[n]=s[n])}return t},D.convert=function(t,e){var i;if(void 0===t)return void 0;if(null===t)return null;if(!e)return t;if("string"!=typeof e&&!(e instanceof String))throw Error("Type must be a string");switch(e){case"boolean":case"Boolean":return Boolean(t);case"number":case"Number":return Number(t.valueOf());case"string":case"String":return t+"";case"Date":if(D.isNumber(t))return new Date(t);if(t instanceof Date)return new Date(t.valueOf());if(E.isMoment(t))return new Date(t.valueOf());if(D.isString(t))return i=C.exec(t),i?new Date(Number(i[1])):E(t).toDate();throw Error("Cannot convert object of type "+D.getType(t)+" to type Date");case"Moment":if(D.isNumber(t))return E(t);if(t instanceof Date)return E(t.valueOf());if(E.isMoment(t))return E.clone();if(D.isString(t))return i=C.exec(t),i?E(Number(i[1])):E(t);throw Error("Cannot convert object of type "+D.getType(t)+" to type Date");case"ISODate":if(D.isNumber(t))return new Date(t);if(t instanceof Date)return t.toISOString();if(E.isMoment(t))return t.toDate().toISOString();if(D.isString(t))return i=C.exec(t),i?new Date(Number(i[1])).toISOString():new Date(t).toISOString();throw Error("Cannot convert object of type "+D.getType(t)+" to type ISODate");case"ASPDate":if(D.isNumber(t))return"/Date("+t+")/";if(t instanceof Date)return"/Date("+t.valueOf()+")/";if(D.isString(t)){i=C.exec(t);var s;return s=i?new Date(Number(i[1])).valueOf():new Date(t).valueOf(),"/Date("+s+")/"}throw Error("Cannot convert object of type "+D.getType(t)+" to type ASPDate");default:throw Error("Cannot convert object of type "+D.getType(t)+' to type "'+e+'"')}};var C=/^\/?Date\((\-?\d+)/i;if(D.getType=function(t){var e=typeof t;return"object"==e?null==t?"null":t instanceof Boolean?"Boolean":t instanceof Number?"Number":t instanceof String?"String":t instanceof Array?"Array":t instanceof Date?"Date":"Object":"number"==e?"Number":"boolean"==e?"Boolean":"string"==e?"String":e},D.getAbsoluteLeft=function(t){for(var e=document.documentElement,i=document.body,s=t.offsetLeft,n=t.offsetParent;null!=n&&n!=i&&n!=e;)s+=n.offsetLeft,s-=n.scrollLeft,n=n.offsetParent;return s},D.getAbsoluteTop=function(t){for(var e=document.documentElement,i=document.body,s=t.offsetTop,n=t.offsetParent;null!=n&&n!=i&&n!=e;)s+=n.offsetTop,s-=n.scrollTop,n=n.offsetParent;return s},D.getPageY=function(t){if("pageY"in t)return t.pageY;var e;e="targetTouches"in t&&t.targetTouches.length?t.targetTouches[0].clientY:t.clientY;var i=document.documentElement,s=document.body;return e+(i&&i.scrollTop||s&&s.scrollTop||0)-(i&&i.clientTop||s&&s.clientTop||0)},D.getPageX=function(t){if("pageY"in t)return t.pageX;var e;e="targetTouches"in t&&t.targetTouches.length?t.targetTouches[0].clientX:t.clientX;var i=document.documentElement,s=document.body;return e+(i&&i.scrollLeft||s&&s.scrollLeft||0)-(i&&i.clientLeft||s&&s.clientLeft||0)},D.addClassName=function(t,e){var i=t.className.split(" ");-1==i.indexOf(e)&&(i.push(e),t.className=i.join(" "))},D.removeClassName=function(t,e){var i=t.className.split(" "),s=i.indexOf(e);-1!=s&&(i.splice(s,1),t.className=i.join(" "))},D.forEach=function(t,e){var i,s;if(t instanceof Array)for(i=0,s=t.length;s>i;i++)e(t[i],i,t);else for(i in t)t.hasOwnProperty(i)&&e(t[i],i,t)},D.updateProperty=function(t,e,i){return t[e]!==i?(t[e]=i,!0):!1},D.addEventListener=function(t,e,i,s){t.addEventListener?(void 0===s&&(s=!1),"mousewheel"===e&&navigator.userAgent.indexOf("Firefox")>=0&&(e="DOMMouseScroll"),t.addEventListener(e,i,s)):t.attachEvent("on"+e,i)},D.removeEventListener=function(t,e,i,s){t.removeEventListener?(void 0===s&&(s=!1),"mousewheel"===e&&navigator.userAgent.indexOf("Firefox")>=0&&(e="DOMMouseScroll"),t.removeEventListener(e,i,s)):t.detachEvent("on"+e,i)},D.getTarget=function(t){t||(t=window.event);var e;return t.target?e=t.target:t.srcElement&&(e=t.srcElement),void 0!=e.nodeType&&3==e.nodeType&&(e=e.parentNode),e},D.stopPropagation=function(t){t||(t=window.event),t.stopPropagation?t.stopPropagation():t.cancelBubble=!0},D.preventDefault=function(t){t||(t=window.event),t.preventDefault?t.preventDefault():t.returnValue=!1},D.option={},D.option.asBoolean=function(t,e){return"function"==typeof t&&(t=t()),null!=t?0!=t:e||null},D.option.asNumber=function(t,e){return"function"==typeof t&&(t=t()),null!=t?Number(t)||e||null:e||null},D.option.asString=function(t,e){return"function"==typeof t&&(t=t()),null!=t?t+"":e||null},D.option.asSize=function(t,e){return"function"==typeof t&&(t=t()),D.isString(t)?t:D.isNumber(t)?t+"px":e||null},D.option.asElement=function(t,e){return"function"==typeof t&&(t=t()),t||e||null},D.loadCss=function(t){if("undefined"!=typeof document){var e=document.createElement("style");e.type="text/css",e.styleSheet?e.styleSheet.cssText=t:e.appendChild(document.createTextNode(t)),document.getElementsByTagName("head")[0].appendChild(e)}},!Array.prototype.indexOf){Array.prototype.indexOf=function(t){for(var e=0;this.length>e;e++)if(this[e]==t)return e;return-1};try{console.log("Warning: Ancient browser detected. Please update your browser")}catch(L){}}Array.prototype.forEach||(Array.prototype.forEach=function(t,e){for(var i=0,s=this.length;s>i;++i)t.call(e||this,this[i],i,this)}),Array.prototype.map||(Array.prototype.map=function(t,e){var i,s,n;if(null==this)throw new TypeError(" this is null or not defined");var o=Object(this),r=o.length>>>0;if("function"!=typeof t)throw new TypeError(t+" is not a function");for(e&&(i=e),s=Array(r),n=0;r>n;){var a,h;n in o&&(a=o[n],h=t.call(i,a,n,o),s[n]=h),n++}return s}),Array.prototype.filter||(Array.prototype.filter=function(t){"use strict";if(null==this)throw new TypeError;var e=Object(this),i=e.length>>>0;if("function"!=typeof t)throw new TypeError;for(var s=[],n=arguments[1],o=0;i>o;o++)if(o in e){var r=e[o];t.call(n,r,o,e)&&s.push(r)}return s}),Object.keys||(Object.keys=function(){var t=Object.prototype.hasOwnProperty,e=!{toString:null}.propertyIsEnumerable("toString"),i=["toString","toLocaleString","valueOf","hasOwnProperty","isPrototypeOf","propertyIsEnumerable","constructor"],s=i.length;return function(n){if("object"!=typeof n&&"function"!=typeof n||null===n)throw new TypeError("Object.keys called on non-object");var o=[];for(var r in n)t.call(n,r)&&o.push(r);if(e)for(var a=0;s>a;a++)t.call(n,i[a])&&o.push(i[a]);return o}}()),Array.isArray||(Array.isArray=function(t){return"[object Array]"===Object.prototype.toString.call(t)}),Function.prototype.bind||(Function.prototype.bind=function(t){if("function"!=typeof this)throw new TypeError("Function.prototype.bind - what is trying to be bound is not callable");var e=Array.prototype.slice.call(arguments,1),i=this,s=function(){},n=function(){return i.apply(this instanceof s&&t?this:t,e.concat(Array.prototype.slice.call(arguments)))};return s.prototype=this.prototype,n.prototype=new s,n}),Object.create||(Object.create=function(t){function e(){}if(arguments.length>1)throw Error("Object.create implementation only accepts the first parameter.");return e.prototype=t,new e});var O={listeners:[],indexOf:function(t){for(var e=this.listeners,i=0,s=this.listeners.length;s>i;i++){var n=e[i];if(n&&n.object==t)return i}return-1},addListener:function(t,e,i){var s=this.indexOf(t),n=this.listeners[s];n||(n={object:t,events:{}},this.listeners.push(n));var o=n.events[e];o||(o=[],n.events[e]=o),-1==o.indexOf(i)&&o.push(i)},removeListener:function(t,e,i){var s=this.indexOf(t),n=this.listeners[s];if(n){var o=n.events[e];o&&(s=o.indexOf(i),-1!=s&&o.splice(s,1),0==o.length&&delete n.events[e]);var r=0,a=n.events;for(var h in a)a.hasOwnProperty(h)&&r++;0==r&&delete this.listeners[s]}},removeAllListeners:function(){this.listeners=[]},trigger:function(t,e,i){var s=this.indexOf(t),n=this.listeners[s];if(n){var o=n.events[e];if(o)for(var r=0,a=o.length;a>r;r++)o[r](i)}}};n.prototype.on=function(t,e,i){var s=t instanceof RegExp?t:RegExp(t.replace("*","\\w+")),n={id:D.randomUUID(),event:t,regexp:s,callback:"function"==typeof e?e:null,target:i};return this.subscriptions.push(n),n.id},n.prototype.off=function(t){for(var e=0;this.subscriptions.length>e;){var i=this.subscriptions[e],s=!0;if(t instanceof Object)for(var n in t)t.hasOwnProperty(n)&&t[n]!==i[n]&&(s=!1);else s=i.id==t;s?this.subscriptions.splice(e,1):e++}},n.prototype.emit=function(t,e,i){for(var s=0;this.subscriptions.length>s;s++){var n=this.subscriptions[s];n.regexp.test(t)&&n.callback&&n.callback(t,e,i)}},o.prototype.subscribe=function(t,e){var i=this.subscribers[t];i||(i=[],this.subscribers[t]=i),i.push({callback:e})},o.prototype.unsubscribe=function(t,e){var i=this.subscribers[t];i&&(this.subscribers[t]=i.filter(function(t){return t.callback!=e}))},o.prototype._trigger=function(t,e,i){if("*"==t)throw Error("Cannot trigger event *");var s=[];t in this.subscribers&&(s=s.concat(this.subscribers[t])),"*"in this.subscribers&&(s=s.concat(this.subscribers["*"]));for(var n=0;s.length>n;n++){var o=s[n];o.callback&&o.callback(t,e,i||null)}},o.prototype.add=function(t,e){var i,s=[],n=this;if(t instanceof Array)for(var o=0,r=t.length;r>o;o++)i=n._addItem(t[o]),s.push(i);else if(D.isDataTable(t))for(var a=this._getColumnNames(t),h=0,d=t.getNumberOfRows();d>h;h++){for(var l={},p=0,c=a.length;c>p;p++){var u=a[p];l[u]=t.getValue(h,p)}i=n._addItem(l),s.push(i)}else{if(!(t instanceof Object))throw Error("Unknown dataType");i=n._addItem(t),s.push(i)}return s.length&&this._trigger("add",{items:s},e),s},o.prototype.update=function(t,e){var i=[],s=[],n=this,o=n.fieldId,r=function(t){var e=t[o];n.data[e]?(e=n._updateItem(t),s.push(e)):(e=n._addItem(t),i.push(e))};if(t instanceof Array)for(var a=0,h=t.length;h>a;a++)r(t[a]);else if(D.isDataTable(t))for(var d=this._getColumnNames(t),l=0,p=t.getNumberOfRows();p>l;l++){for(var c={},u=0,f=d.length;f>u;u++){var m=d[u];c[m]=t.getValue(l,u)}r(c)}else{if(!(t instanceof Object))throw Error("Unknown dataType");r(t)}return i.length&&this._trigger("add",{items:i},e),s.length&&this._trigger("update",{items:s},e),i.concat(s)},o.prototype.get=function(){var t,e,i,s,n=this,o=D.getType(arguments[0]);"String"==o||"Number"==o?(t=arguments[0],i=arguments[1],s=arguments[2]):"Array"==o?(e=arguments[0],i=arguments[1],s=arguments[2]):(i=arguments[0],s=arguments[1]);var r;if(i&&i.type){if(r="DataTable"==i.type?"DataTable":"Array",s&&r!=D.getType(s))throw Error('Type of parameter "data" ('+D.getType(s)+") "+"does not correspond with specified options.type ("+i.type+")");if("DataTable"==r&&!D.isDataTable(s))throw Error('Parameter "data" must be a DataTable when options.type is "DataTable"')}else r=s?"DataTable"==D.getType(s)?"DataTable":"Array":"Array";var a,h,d,l,p=i&&i.convert||this.options.convert,c=i&&i.filter,u=[];if(void 0!=t)a=n._getItem(t,p),c&&!c(a)&&(a=null);else if(void 0!=e)for(d=0,l=e.length;l>d;d++)a=n._getItem(e[d],p),(!c||c(a))&&u.push(a);else for(h in this.data)this.data.hasOwnProperty(h)&&(a=n._getItem(h,p),(!c||c(a))&&u.push(a));if(i&&i.order&&void 0==t&&this._sort(u,i.order),i&&i.fields){var f=i.fields;if(void 0!=t)a=this._filterFields(a,f);else for(d=0,l=u.length;l>d;d++)u[d]=this._filterFields(u[d],f)}if("DataTable"==r){var m=this._getColumnNames(s);if(void 0!=t)n._appendRow(s,m,a);else for(d=0,l=u.length;l>d;d++)n._appendRow(s,m,u[d]);return s}if(void 0!=t)return a;if(s){for(d=0,l=u.length;l>d;d++)s.push(u[d]);return s}return u},o.prototype.getIds=function(t){var e,i,s,n,o,r=this.data,a=t&&t.filter,h=t&&t.order,d=t&&t.convert||this.options.convert,l=[];if(a)if(h){o=[];for(s in r)r.hasOwnProperty(s)&&(n=this._getItem(s,d),a(n)&&o.push(n));for(this._sort(o,h),e=0,i=o.length;i>e;e++)l[e]=o[e][this.fieldId]}else for(s in r)r.hasOwnProperty(s)&&(n=this._getItem(s,d),a(n)&&l.push(n[this.fieldId]));else if(h){o=[];for(s in r)r.hasOwnProperty(s)&&o.push(r[s]);for(this._sort(o,h),e=0,i=o.length;i>e;e++)l[e]=o[e][this.fieldId]}else for(s in r)r.hasOwnProperty(s)&&(n=r[s],l.push(n[this.fieldId]));return l},o.prototype.forEach=function(t,e){var i,s,n=e&&e.filter,o=e&&e.convert||this.options.convert,r=this.data;if(e&&e.order)for(var a=this.get(e),h=0,d=a.length;d>h;h++)i=a[h],s=i[this.fieldId],t(i,s);else for(s in r)r.hasOwnProperty(s)&&(i=this._getItem(s,o),(!n||n(i))&&t(i,s))},o.prototype.map=function(t,e){var i,s=e&&e.filter,n=e&&e.convert||this.options.convert,o=[],r=this.data;for(var a in r)r.hasOwnProperty(a)&&(i=this._getItem(a,n),(!s||s(i))&&o.push(t(i,a)));return e&&e.order&&this._sort(o,e.order),o},o.prototype._filterFields=function(t,e){var i={};for(var s in t)t.hasOwnProperty(s)&&-1!=e.indexOf(s)&&(i[s]=t[s]);return i},o.prototype._sort=function(t,e){if(D.isString(e)){var i=e;t.sort(function(t,e){var s=t[i],n=e[i];return s>n?1:n>s?-1:0})}else{if("function"!=typeof e)throw new TypeError("Order must be a function or a string");t.sort(e)}},o.prototype.remove=function(t,e){var i,s,n,o=[];if(t instanceof Array)for(i=0,s=t.length;s>i;i++)n=this._remove(t[i]),null!=n&&o.push(n);else n=this._remove(t),null!=n&&o.push(n);return o.length&&this._trigger("remove",{items:o},e),o},o.prototype._remove=function(t){if(D.isNumber(t)||D.isString(t)){if(this.data[t])return delete this.data[t],delete this.internalIds[t],t}else if(t instanceof Object){var e=t[this.fieldId];if(e&&this.data[e])return delete this.data[e],delete this.internalIds[e],e}return null},o.prototype.clear=function(t){var e=Object.keys(this.data);return this.data={},this.internalIds={},this._trigger("remove",{items:e},t),e},o.prototype.max=function(t){var e=this.data,i=null,s=null;for(var n in e)if(e.hasOwnProperty(n)){var o=e[n],r=o[t];null!=r&&(!i||r>s)&&(i=o,s=r)}return i},o.prototype.min=function(t){var e=this.data,i=null,s=null;for(var n in e)if(e.hasOwnProperty(n)){var o=e[n],r=o[t];null!=r&&(!i||s>r)&&(i=o,s=r)}return i},o.prototype.distinct=function(t){var e=this.data,i=[],s=this.options.convert[t],n=0;for(var o in e)if(e.hasOwnProperty(o)){for(var r=e[o],a=D.convert(r[t],s),h=!1,d=0;n>d;d++)if(i[d]==a){h=!0;break}h||(i[n]=a,n++)}return i},o.prototype._addItem=function(t){var e=t[this.fieldId];if(void 0!=e){if(this.data[e])throw Error("Cannot add item: item with id "+e+" already exists")}else e=D.randomUUID(),t[this.fieldId]=e,this.internalIds[e]=t;var i={};for(var s in t)if(t.hasOwnProperty(s)){var n=this.convert[s];i[s]=D.convert(t[s],n)}return this.data[e]=i,e},o.prototype._getItem=function(t,e){var i,s,n=this.data[t];if(!n)return null;var o={},r=this.fieldId,a=this.internalIds;if(e)for(i in n)n.hasOwnProperty(i)&&(s=n[i],i==r&&s in a||(o[i]=D.convert(s,e[i])));else for(i in n)n.hasOwnProperty(i)&&(s=n[i],i==r&&s in a||(o[i]=s));return o},o.prototype._updateItem=function(t){var e=t[this.fieldId];if(void 0==e)throw Error("Cannot update item: item has no id (item: "+JSON.stringify(t)+")");var i=this.data[e];if(!i)throw Error("Cannot update item: no item with id "+e+" found");for(var s in t)if(t.hasOwnProperty(s)){var n=this.convert[s];i[s]=D.convert(t[s],n)}return e},o.prototype._getColumnNames=function(t){for(var e=[],i=0,s=t.getNumberOfColumns();s>i;i++)e[i]=t.getColumnId(i)||t.getColumnLabel(i);return e},o.prototype._appendRow=function(t,e,i){for(var s=t.addRow(),n=0,o=e.length;o>n;n++){var r=e[n];t.setValue(s,n,i[r])}},r.prototype.setData=function(t){var e,i,s;if(this.data){this.data.unsubscribe&&this.data.unsubscribe("*",this.listener),e=[];for(var n in this.ids)this.ids.hasOwnProperty(n)&&e.push(n);this.ids={},this._trigger("remove",{items:e})}if(this.data=t,this.data){for(this.fieldId=this.options.fieldId||this.data&&this.data.options&&this.data.options.fieldId||"id",e=this.data.getIds({filter:this.options&&this.options.filter}),i=0,s=e.length;s>i;i++)n=e[i],this.ids[n]=!0;this._trigger("add",{items:e}),this.data.subscribe&&this.data.subscribe("*",this.listener)}},r.prototype.get=function(){var t,e,i,s=this,n=D.getType(arguments[0]);"String"==n||"Number"==n||"Array"==n?(t=arguments[0],e=arguments[1],i=arguments[2]):(e=arguments[0],i=arguments[1]);var o=D.extend({},this.options,e);this.options.filter&&e&&e.filter&&(o.filter=function(t){return s.options.filter(t)&&e.filter(t)});var r=[];return void 0!=t&&r.push(t),r.push(o),r.push(i),this.data&&this.data.get.apply(this.data,r)},r.prototype.getIds=function(t){var e;if(this.data){var i,s=this.options.filter;i=t&&t.filter?s?function(e){return s(e)&&t.filter(e)}:t.filter:s,e=this.data.getIds({filter:i,order:t&&t.order})}else e=[];return e},r.prototype._onEvent=function(t,e,i){var s,n,o,r,a=e&&e.items,h=this.data,d=[],l=[],p=[];if(a&&h){switch(t){case"add":for(s=0,n=a.length;n>s;s++)o=a[s],r=this.get(o),r&&(this.ids[o]=!0,d.push(o));break;case"update":for(s=0,n=a.length;n>s;s++)o=a[s],r=this.get(o),r?this.ids[o]?l.push(o):(this.ids[o]=!0,d.push(o)):this.ids[o]&&(delete this.ids[o],p.push(o));break;case"remove":for(s=0,n=a.length;n>s;s++)o=a[s],this.ids[o]&&(delete this.ids[o],p.push(o))}d.length&&this._trigger("add",{items:d},i),l.length&&this._trigger("update",{items:l},i),p.length&&this._trigger("remove",{items:p},i)}},r.prototype.subscribe=o.prototype.subscribe,r.prototype.unsubscribe=o.prototype.unsubscribe,r.prototype._trigger=o.prototype._trigger,TimeStep=function(t,e,i){this.current=new Date,this._start=new Date,this._end=new Date,this.autoScale=!0,this.scale=TimeStep.SCALE.DAY,this.step=1,this.setRange(t,e,i)},TimeStep.SCALE={MILLISECOND:1,SECOND:2,MINUTE:3,HOUR:4,DAY:5,WEEKDAY:6,MONTH:7,YEAR:8},TimeStep.prototype.setRange=function(t,e,i){t instanceof Date&&e instanceof Date&&(this._start=void 0!=t?new Date(t.valueOf()):new Date,this._end=void 0!=e?new Date(e.valueOf()):new Date,this.autoScale&&this.setMinimumStep(i))},TimeStep.prototype.first=function(){this.current=new Date(this._start.valueOf()),this.roundToMinor()},TimeStep.prototype.roundToMinor=function(){switch(this.scale){case TimeStep.SCALE.YEAR:this.current.setFullYear(this.step*Math.floor(this.current.getFullYear()/this.step)),this.current.setMonth(0);case TimeStep.SCALE.MONTH:this.current.setDate(1);case TimeStep.SCALE.DAY:case TimeStep.SCALE.WEEKDAY:this.current.setHours(0);case TimeStep.SCALE.HOUR:this.current.setMinutes(0);case TimeStep.SCALE.MINUTE:this.current.setSeconds(0);case TimeStep.SCALE.SECOND:this.current.setMilliseconds(0)}if(1!=this.step)switch(this.scale){case TimeStep.SCALE.MILLISECOND:this.current.setMilliseconds(this.current.getMilliseconds()-this.current.getMilliseconds()%this.step);break;case TimeStep.SCALE.SECOND:this.current.setSeconds(this.current.getSeconds()-this.current.getSeconds()%this.step);break;case TimeStep.SCALE.MINUTE:this.current.setMinutes(this.current.getMinutes()-this.current.getMinutes()%this.step);break;case TimeStep.SCALE.HOUR:this.current.setHours(this.current.getHours()-this.current.getHours()%this.step);break;case TimeStep.SCALE.WEEKDAY:case TimeStep.SCALE.DAY:this.current.setDate(this.current.getDate()-1-(this.current.getDate()-1)%this.step+1);break;case TimeStep.SCALE.MONTH:this.current.setMonth(this.current.getMonth()-this.current.getMonth()%this.step);break;case TimeStep.SCALE.YEAR:this.current.setFullYear(this.current.getFullYear()-this.current.getFullYear()%this.step);break;default:}},TimeStep.prototype.hasNext=function(){return this.current.valueOf()<=this._end.valueOf()},TimeStep.prototype.next=function(){var t=this.current.valueOf();if(6>this.current.getMonth())switch(this.scale){case TimeStep.SCALE.MILLISECOND:this.current=new Date(this.current.valueOf()+this.step);break;case TimeStep.SCALE.SECOND:this.current=new Date(this.current.valueOf()+1e3*this.step);break;case TimeStep.SCALE.MINUTE:this.current=new Date(this.current.valueOf()+60*1e3*this.step);break;case TimeStep.SCALE.HOUR:this.current=new Date(this.current.valueOf()+60*60*1e3*this.step);var e=this.current.getHours();this.current.setHours(e-e%this.step);break;case TimeStep.SCALE.WEEKDAY:case TimeStep.SCALE.DAY:this.current.setDate(this.current.getDate()+this.step);break;case TimeStep.SCALE.MONTH:this.current.setMonth(this.current.getMonth()+this.step);break;case TimeStep.SCALE.YEAR:this.current.setFullYear(this.current.getFullYear()+this.step);break;default:}else switch(this.scale){case TimeStep.SCALE.MILLISECOND:this.current=new Date(this.current.valueOf()+this.step);break;case TimeStep.SCALE.SECOND:this.current.setSeconds(this.current.getSeconds()+this.step);break;case TimeStep.SCALE.MINUTE:this.current.setMinutes(this.current.getMinutes()+this.step);break;case TimeStep.SCALE.HOUR:this.current.setHours(this.current.getHours()+this.step);break;case TimeStep.SCALE.WEEKDAY:case TimeStep.SCALE.DAY:this.current.setDate(this.current.getDate()+this.step);break;case TimeStep.SCALE.MONTH:this.current.setMonth(this.current.getMonth()+this.step);break;case TimeStep.SCALE.YEAR:this.current.setFullYear(this.current.getFullYear()+this.step);break;default:}if(1!=this.step)switch(this.scale){case TimeStep.SCALE.MILLISECOND:this.current.getMilliseconds()0&&(this.step=e),this.autoScale=!1},TimeStep.prototype.setAutoScale=function(t){this.autoScale=t},TimeStep.prototype.setMinimumStep=function(t){if(void 0!=t){var e=31104e6,i=2592e6,s=864e5,n=36e5,o=6e4,r=1e3,a=1;1e3*e>t&&(this.scale=TimeStep.SCALE.YEAR,this.step=1e3),500*e>t&&(this.scale=TimeStep.SCALE.YEAR,this.step=500),100*e>t&&(this.scale=TimeStep.SCALE.YEAR,this.step=100),50*e>t&&(this.scale=TimeStep.SCALE.YEAR,this.step=50),10*e>t&&(this.scale=TimeStep.SCALE.YEAR,this.step=10),5*e>t&&(this.scale=TimeStep.SCALE.YEAR,this.step=5),e>t&&(this.scale=TimeStep.SCALE.YEAR,this.step=1),3*i>t&&(this.scale=TimeStep.SCALE.MONTH,this.step=3),i>t&&(this.scale=TimeStep.SCALE.MONTH,this.step=1),5*s>t&&(this.scale=TimeStep.SCALE.DAY,this.step=5),2*s>t&&(this.scale=TimeStep.SCALE.DAY,this.step=2),s>t&&(this.scale=TimeStep.SCALE.DAY,this.step=1),s/2>t&&(this.scale=TimeStep.SCALE.WEEKDAY,this.step=1),4*n>t&&(this.scale=TimeStep.SCALE.HOUR,this.step=4),n>t&&(this.scale=TimeStep.SCALE.HOUR,this.step=1),15*o>t&&(this.scale=TimeStep.SCALE.MINUTE,this.step=15),10*o>t&&(this.scale=TimeStep.SCALE.MINUTE,this.step=10),5*o>t&&(this.scale=TimeStep.SCALE.MINUTE,this.step=5),o>t&&(this.scale=TimeStep.SCALE.MINUTE,this.step=1),15*r>t&&(this.scale=TimeStep.SCALE.SECOND,this.step=15),10*r>t&&(this.scale=TimeStep.SCALE.SECOND,this.step=10),5*r>t&&(this.scale=TimeStep.SCALE.SECOND,this.step=5),r>t&&(this.scale=TimeStep.SCALE.SECOND,this.step=1),200*a>t&&(this.scale=TimeStep.SCALE.MILLISECOND,this.step=200),100*a>t&&(this.scale=TimeStep.SCALE.MILLISECOND,this.step=100),50*a>t&&(this.scale=TimeStep.SCALE.MILLISECOND,this.step=50),10*a>t&&(this.scale=TimeStep.SCALE.MILLISECOND,this.step=10),5*a>t&&(this.scale=TimeStep.SCALE.MILLISECOND,this.step=5),a>t&&(this.scale=TimeStep.SCALE.MILLISECOND,this.step=1) +(function(t){if("function"==typeof bootstrap)bootstrap("vis",t);else if("object"==typeof exports)module.exports=t();else if("function"==typeof define&&define.amd)define(t);else if("undefined"!=typeof ses){if(!ses.ok())return;ses.makeVis=t}else"undefined"!=typeof window?window.vis=t():global.vis=t()})(function(){var t;return function(t,e,i){function s(i,o){if(!e[i]){if(!t[i]){var r="function"==typeof require&&require;if(!o&&r)return r(i,!0);if(n)return n(i,!0);throw Error("Cannot find module '"+i+"'")}var a=e[i]={exports:{}};t[i][0].call(a.exports,function(e){var n=t[i][1][e];return s(n?n:e)},a,a.exports)}return e[i].exports}for(var n="function"==typeof require&&require,o=0;i.length>o;o++)s(i[o]);return s}({1:[function(e,i,s){(function(){function n(){this.subscriptions=[]}function o(t){if(this.id=D.randomUUID(),this.options=t||{},this.data={},this.fieldId=this.options.fieldId||"id",this.convert={},this.options.convert)for(var e in this.options.convert)if(this.options.convert.hasOwnProperty(e)){var i=this.options.convert[e];this.convert[e]="Date"==i||"ISODate"==i||"ASPDate"==i?"Date":i}this.subscribers={},this.internalIds={}}function r(t,e){this.id=D.randomUUID(),this.data=null,this.ids={},this.options=e||{},this.fieldId="id",this.subscribers={};var i=this;this.listener=function(){i._onEvent.apply(i,arguments)},this.setData(t)}function a(t,e){this.parent=t,this.options=e||{},this.defaultOptions={order:function(t,e){if(t instanceof y){if(e instanceof y){var i=t.data.end-t.data.start,s=e.data.end-e.data.start;return i-s||t.data.start-e.data.start}return-1}return e instanceof y?1:t.data.start-e.data.start},margin:{item:10}},this.ordered=[]}function h(t){this.id=D.randomUUID(),this.start=0,this.end=0,this.options={min:null,max:null,zoomMin:null,zoomMax:null},this.listeners=[],this.setOptions(t)}function d(){this.id=D.randomUUID(),this.components={},this.repaintTimer=void 0,this.reflowTimer=void 0}function l(){this.id=null,this.parent=null,this.depends=null,this.controller=null,this.options=null,this.frame=null,this.top=0,this.left=0,this.width=0,this.height=0}function p(t,e,i){this.id=D.randomUUID(),this.parent=t,this.depends=e,this.options=i||{}}function c(t,e){this.id=D.randomUUID(),this.container=t,this.options=e||{},this.defaultOptions={autoResize:!0},this.listeners={}}function u(t,e,i){this.id=D.randomUUID(),this.parent=t,this.depends=e,this.dom={majorLines:[],majorTexts:[],minorLines:[],minorTexts:[],redundant:{majorLines:[],majorTexts:[],minorLines:[],minorTexts:[]}},this.props={range:{start:0,end:0,minimumStep:0},lineTop:0},this.options=i||{},this.defaultOptions={orientation:"bottom",showMinorLabels:!0,showMajorLabels:!0},this.conversion=null,this.range=null}function f(t,e,i){this.id=D.randomUUID(),this.parent=t,this.depends=e,this.options=i||{},this.defaultOptions={type:"box",align:"center",orientation:"bottom",margin:{axis:20,item:10},padding:5},this.dom={};var s=this;this.itemsData=null,this.range=null,this.listeners={add:function(t,e,i){i!=s.id&&s._onAdd(e.items)},update:function(t,e,i){i!=s.id&&s._onUpdate(e.items)},remove:function(t,e,i){i!=s.id&&s._onRemove(e.items)}},this.items={},this.queue={},this.stack=new a(this,Object.create(this.options)),this.conversion=null}function m(t,e,i,s){this.parent=t,this.data=e,this.dom=null,this.options=i||{},this.defaultOptions=s||{},this.selected=!1,this.visible=!1,this.top=0,this.left=0,this.width=0,this.height=0}function g(t,e,i,s){this.props={dot:{left:0,top:0,width:0,height:0},line:{top:0,left:0,width:0,height:0}},m.call(this,t,e,i,s)}function v(t,e,i,s){this.props={dot:{top:0,width:0,height:0},content:{height:0,marginLeft:0}},m.call(this,t,e,i,s)}function y(t,e,i,s){this.props={content:{left:0,width:0}},m.call(this,t,e,i,s)}function b(t,e,i){this.id=D.randomUUID(),this.parent=t,this.groupId=e,this.itemset=null,this.options=i||{},this.options.top=0,this.props={label:{width:0,height:0}},this.top=0,this.left=0,this.width=0,this.height=0}function w(t,e,i){this.id=D.randomUUID(),this.parent=t,this.depends=e,this.options=i||{},this.range=null,this.itemsData=null,this.groupsData=null,this.groups={},this.dom={},this.props={labels:{width:0}},this.queue={};var s=this;this.listeners={add:function(t,e){s._onAdd(e.items)},update:function(t,e){s._onUpdate(e.items)},remove:function(t,e){s._onRemove(e.items)}}}function _(t,e,i){var s=this;if(this.options=D.extend({orientation:"bottom",min:null,max:null,zoomMin:10,zoomMax:31536e10,showMinorLabels:!0,showMajorLabels:!0,autoResize:!1},i),this.controller=new d,!t)throw Error("No container element provided");var n=Object.create(this.options);n.height=function(){return s.options.height?s.options.height:s.timeaxis.height+s.content.height},this.rootPanel=new c(t,n),this.controller.add(this.rootPanel);var o=Object.create(this.options);o.left=function(){return s.labelPanel.width},o.width=function(){return s.rootPanel.width-s.labelPanel.width},o.top=null,o.height=null,this.itemPanel=new p(this.rootPanel,[],o),this.controller.add(this.itemPanel);var r=Object.create(this.options);r.top=null,r.left=null,r.height=null,r.width=function(){return s.content&&"function"==typeof s.content.getLabelsWidth?s.content.getLabelsWidth():0},this.labelPanel=new p(this.rootPanel,[],r),this.controller.add(this.labelPanel);var a=E().hours(0).minutes(0).seconds(0).milliseconds(0);this.range=new h({start:a.clone().add("days",-3).valueOf(),end:a.clone().add("days",4).valueOf()}),this.range.subscribe(this.rootPanel,"move","horizontal"),this.range.subscribe(this.rootPanel,"zoom","horizontal"),this.range.on("rangechange",function(){var t=!0;s.controller.requestReflow(t)}),this.range.on("rangechanged",function(){var t=!0;s.controller.requestReflow(t)});var l=Object.create(n);l.range=this.range,l.left=null,l.top=null,l.width="100%",l.height=null,this.timeaxis=new u(this.itemPanel,[],l),this.timeaxis.setRange(this.range),this.controller.add(this.timeaxis),this.setGroups(null),this.itemsData=null,this.groupsData=null,e&&this.setItems(e)}function x(t,e,i,s){this.selected=!1,this.edges=[],this.group=s.nodes.group,this.fontSize=s.nodes.fontSize,this.fontFace=s.nodes.fontFace,this.fontColor=s.nodes.fontColor,this.color=s.nodes.color,this.id=void 0,this.shape=s.nodes.shape,this.image=s.nodes.image,this.x=0,this.y=0,this.xFixed=!1,this.yFixed=!1,this.radius=s.nodes.radius,this.radiusFixed=!1,this.radiusMin=s.nodes.radiusMin,this.radiusMax=s.nodes.radiusMax,this.imagelist=e,this.grouplist=i,this.setProperties(t,s),this.mass=50,this.fx=0,this.fy=0,this.vx=0,this.vy=0,this.minForce=s.minForce,this.damping=.9}function T(t,e,i){if(!e)throw"No graph provided";this.graph=e,this.widthMin=i.edges.widthMin,this.widthMax=i.edges.widthMax,this.id=void 0,this.fromId=void 0,this.toId=void 0,this.style=i.edges.style,this.title=void 0,this.width=i.edges.width,this.value=void 0,this.length=i.edges.length,this.from=null,this.to=null,this.connected=!1,this.dash=D.extend({},i.edges.dash),this.stiffness=void 0,this.color=i.edges.color,this.widthFixed=!1,this.lengthFixed=!1,this.setProperties(t,i)}function S(t,e,i,s){this.container=t?t:document.body,this.x=0,this.y=0,this.padding=5,void 0!==e&&void 0!==i&&this.setPosition(e,i),void 0!==s&&this.setText(s),this.frame=document.createElement("div");var n=this.frame.style;n.position="absolute",n.visibility="hidden",n.border="1px solid #666",n.color="black",n.padding=this.padding+"px",n.backgroundColor="#FFFFC6",n.borderRadius="3px",n.MozBorderRadius="3px",n.WebkitBorderRadius="3px",n.boxShadow="3px 3px 10px rgba(128, 128, 128, 0.5)",n.whiteSpace="nowrap",this.container.appendChild(this.frame)}function M(t,e,i){this.containerElement=t,this.width="100%",this.height="100%",this.refreshRate=50,this.stabilize=!0,this.selectable=!0,this.constants={nodes:{radiusMin:5,radiusMax:20,radius:5,distance:100,shape:"ellipse",image:void 0,widthMin:16,widthMax:64,fontColor:"black",fontSize:14,fontFace:"arial",color:{border:"#2B7CE9",background:"#97C2FC",highlight:{border:"#2B7CE9",background:"#D2E5FF"}},borderColor:"#2B7CE9",backgroundColor:"#97C2FC",highlightColor:"#D2E5FF",group:void 0},edges:{widthMin:1,widthMax:15,width:1,style:"line",color:"#343434",fontColor:"#343434",fontSize:14,fontFace:"arial",length:100,dash:{length:10,gap:5,altLength:void 0}},minForce:.05,minVelocity:.02,maxIterations:1e3};var s=this;this.nodes={},this.edges={},this.nodesData=null,this.edgesData=null;var n=this;this.nodesListeners={add:function(t,e){n._addNodes(e.items),n.start()},update:function(t,e){n._updateNodes(e.items),n.start()},remove:function(t,e){n._removeNodes(e.items),n.start()}},this.edgesListeners={add:function(t,e){n._addEdges(e.items),n.start()},update:function(t,e){n._updateEdges(e.items),n.start()},remove:function(t,e){n._removeEdges(e.items),n.start()}},this.groups=new Groups,this.images=new Images,this.images.setOnloadCallback(function(){s._redraw()}),this.moving=!1,this.selection=[],this.timer=void 0,this._create(),this.setOptions(i),this.setData(e)}var E=e("moment"),D={};D.isNumber=function(t){return t instanceof Number||"number"==typeof t},D.isString=function(t){return t instanceof String||"string"==typeof t},D.isDate=function(t){if(t instanceof Date)return!0;if(D.isString(t)){var e=C.exec(t);if(e)return!0;if(!isNaN(Date.parse(t)))return!0}return!1},D.isDataTable=function(t){return"undefined"!=typeof google&&google.visualization&&google.visualization.DataTable&&t instanceof google.visualization.DataTable},D.randomUUID=function(){var t=function(){return Math.floor(65536*Math.random()).toString(16)};return t()+t()+"-"+t()+"-"+t()+"-"+t()+"-"+t()+t()+t()},D.extend=function(t){for(var e=1,i=arguments.length;i>e;e++){var s=arguments[e];for(var n in s)s.hasOwnProperty(n)&&void 0!==s[n]&&(t[n]=s[n])}return t},D.convert=function(t,e){var i;if(void 0===t)return void 0;if(null===t)return null;if(!e)return t;if("string"!=typeof e&&!(e instanceof String))throw Error("Type must be a string");switch(e){case"boolean":case"Boolean":return Boolean(t);case"number":case"Number":return Number(t.valueOf());case"string":case"String":return t+"";case"Date":if(D.isNumber(t))return new Date(t);if(t instanceof Date)return new Date(t.valueOf());if(E.isMoment(t))return new Date(t.valueOf());if(D.isString(t))return i=C.exec(t),i?new Date(Number(i[1])):E(t).toDate();throw Error("Cannot convert object of type "+D.getType(t)+" to type Date");case"Moment":if(D.isNumber(t))return E(t);if(t instanceof Date)return E(t.valueOf());if(E.isMoment(t))return E.clone();if(D.isString(t))return i=C.exec(t),i?E(Number(i[1])):E(t);throw Error("Cannot convert object of type "+D.getType(t)+" to type Date");case"ISODate":if(D.isNumber(t))return new Date(t);if(t instanceof Date)return t.toISOString();if(E.isMoment(t))return t.toDate().toISOString();if(D.isString(t))return i=C.exec(t),i?new Date(Number(i[1])).toISOString():new Date(t).toISOString();throw Error("Cannot convert object of type "+D.getType(t)+" to type ISODate");case"ASPDate":if(D.isNumber(t))return"/Date("+t+")/";if(t instanceof Date)return"/Date("+t.valueOf()+")/";if(D.isString(t)){i=C.exec(t);var s;return s=i?new Date(Number(i[1])).valueOf():new Date(t).valueOf(),"/Date("+s+")/"}throw Error("Cannot convert object of type "+D.getType(t)+" to type ASPDate");default:throw Error("Cannot convert object of type "+D.getType(t)+' to type "'+e+'"')}};var C=/^\/?Date\((\-?\d+)/i;if(D.getType=function(t){var e=typeof t;return"object"==e?null==t?"null":t instanceof Boolean?"Boolean":t instanceof Number?"Number":t instanceof String?"String":t instanceof Array?"Array":t instanceof Date?"Date":"Object":"number"==e?"Number":"boolean"==e?"Boolean":"string"==e?"String":e},D.getAbsoluteLeft=function(t){for(var e=document.documentElement,i=document.body,s=t.offsetLeft,n=t.offsetParent;null!=n&&n!=i&&n!=e;)s+=n.offsetLeft,s-=n.scrollLeft,n=n.offsetParent;return s},D.getAbsoluteTop=function(t){for(var e=document.documentElement,i=document.body,s=t.offsetTop,n=t.offsetParent;null!=n&&n!=i&&n!=e;)s+=n.offsetTop,s-=n.scrollTop,n=n.offsetParent;return s},D.getPageY=function(t){if("pageY"in t)return t.pageY;var e;e="targetTouches"in t&&t.targetTouches.length?t.targetTouches[0].clientY:t.clientY;var i=document.documentElement,s=document.body;return e+(i&&i.scrollTop||s&&s.scrollTop||0)-(i&&i.clientTop||s&&s.clientTop||0)},D.getPageX=function(t){if("pageY"in t)return t.pageX;var e;e="targetTouches"in t&&t.targetTouches.length?t.targetTouches[0].clientX:t.clientX;var i=document.documentElement,s=document.body;return e+(i&&i.scrollLeft||s&&s.scrollLeft||0)-(i&&i.clientLeft||s&&s.clientLeft||0)},D.addClassName=function(t,e){var i=t.className.split(" ");-1==i.indexOf(e)&&(i.push(e),t.className=i.join(" "))},D.removeClassName=function(t,e){var i=t.className.split(" "),s=i.indexOf(e);-1!=s&&(i.splice(s,1),t.className=i.join(" "))},D.forEach=function(t,e){var i,s;if(t instanceof Array)for(i=0,s=t.length;s>i;i++)e(t[i],i,t);else for(i in t)t.hasOwnProperty(i)&&e(t[i],i,t)},D.updateProperty=function(t,e,i){return t[e]!==i?(t[e]=i,!0):!1},D.addEventListener=function(t,e,i,s){t.addEventListener?(void 0===s&&(s=!1),"mousewheel"===e&&navigator.userAgent.indexOf("Firefox")>=0&&(e="DOMMouseScroll"),t.addEventListener(e,i,s)):t.attachEvent("on"+e,i)},D.removeEventListener=function(t,e,i,s){t.removeEventListener?(void 0===s&&(s=!1),"mousewheel"===e&&navigator.userAgent.indexOf("Firefox")>=0&&(e="DOMMouseScroll"),t.removeEventListener(e,i,s)):t.detachEvent("on"+e,i)},D.getTarget=function(t){t||(t=window.event);var e;return t.target?e=t.target:t.srcElement&&(e=t.srcElement),void 0!=e.nodeType&&3==e.nodeType&&(e=e.parentNode),e},D.stopPropagation=function(t){t||(t=window.event),t.stopPropagation?t.stopPropagation():t.cancelBubble=!0},D.preventDefault=function(t){t||(t=window.event),t.preventDefault?t.preventDefault():t.returnValue=!1},D.option={},D.option.asBoolean=function(t,e){return"function"==typeof t&&(t=t()),null!=t?0!=t:e||null},D.option.asNumber=function(t,e){return"function"==typeof t&&(t=t()),null!=t?Number(t)||e||null:e||null},D.option.asString=function(t,e){return"function"==typeof t&&(t=t()),null!=t?t+"":e||null},D.option.asSize=function(t,e){return"function"==typeof t&&(t=t()),D.isString(t)?t:D.isNumber(t)?t+"px":e||null},D.option.asElement=function(t,e){return"function"==typeof t&&(t=t()),t||e||null},D.loadCss=function(t){if("undefined"!=typeof document){var e=document.createElement("style");e.type="text/css",e.styleSheet?e.styleSheet.cssText=t:e.appendChild(document.createTextNode(t)),document.getElementsByTagName("head")[0].appendChild(e)}},!Array.prototype.indexOf){Array.prototype.indexOf=function(t){for(var e=0;this.length>e;e++)if(this[e]==t)return e;return-1};try{console.log("Warning: Ancient browser detected. Please update your browser")}catch(L){}}Array.prototype.forEach||(Array.prototype.forEach=function(t,e){for(var i=0,s=this.length;s>i;++i)t.call(e||this,this[i],i,this)}),Array.prototype.map||(Array.prototype.map=function(t,e){var i,s,n;if(null==this)throw new TypeError(" this is null or not defined");var o=Object(this),r=o.length>>>0;if("function"!=typeof t)throw new TypeError(t+" is not a function");for(e&&(i=e),s=Array(r),n=0;r>n;){var a,h;n in o&&(a=o[n],h=t.call(i,a,n,o),s[n]=h),n++}return s}),Array.prototype.filter||(Array.prototype.filter=function(t){"use strict";if(null==this)throw new TypeError;var e=Object(this),i=e.length>>>0;if("function"!=typeof t)throw new TypeError;for(var s=[],n=arguments[1],o=0;i>o;o++)if(o in e){var r=e[o];t.call(n,r,o,e)&&s.push(r)}return s}),Object.keys||(Object.keys=function(){var t=Object.prototype.hasOwnProperty,e=!{toString:null}.propertyIsEnumerable("toString"),i=["toString","toLocaleString","valueOf","hasOwnProperty","isPrototypeOf","propertyIsEnumerable","constructor"],s=i.length;return function(n){if("object"!=typeof n&&"function"!=typeof n||null===n)throw new TypeError("Object.keys called on non-object");var o=[];for(var r in n)t.call(n,r)&&o.push(r);if(e)for(var a=0;s>a;a++)t.call(n,i[a])&&o.push(i[a]);return o}}()),Array.isArray||(Array.isArray=function(t){return"[object Array]"===Object.prototype.toString.call(t)}),Function.prototype.bind||(Function.prototype.bind=function(t){if("function"!=typeof this)throw new TypeError("Function.prototype.bind - what is trying to be bound is not callable");var e=Array.prototype.slice.call(arguments,1),i=this,s=function(){},n=function(){return i.apply(this instanceof s&&t?this:t,e.concat(Array.prototype.slice.call(arguments)))};return s.prototype=this.prototype,n.prototype=new s,n}),Object.create||(Object.create=function(t){function e(){}if(arguments.length>1)throw Error("Object.create implementation only accepts the first parameter.");return e.prototype=t,new e});var O={listeners:[],indexOf:function(t){for(var e=this.listeners,i=0,s=this.listeners.length;s>i;i++){var n=e[i];if(n&&n.object==t)return i}return-1},addListener:function(t,e,i){var s=this.indexOf(t),n=this.listeners[s];n||(n={object:t,events:{}},this.listeners.push(n));var o=n.events[e];o||(o=[],n.events[e]=o),-1==o.indexOf(i)&&o.push(i)},removeListener:function(t,e,i){var s=this.indexOf(t),n=this.listeners[s];if(n){var o=n.events[e];o&&(s=o.indexOf(i),-1!=s&&o.splice(s,1),0==o.length&&delete n.events[e]);var r=0,a=n.events;for(var h in a)a.hasOwnProperty(h)&&r++;0==r&&delete this.listeners[s]}},removeAllListeners:function(){this.listeners=[]},trigger:function(t,e,i){var s=this.indexOf(t),n=this.listeners[s];if(n){var o=n.events[e];if(o)for(var r=0,a=o.length;a>r;r++)o[r](i)}}};n.prototype.on=function(t,e,i){var s=t instanceof RegExp?t:RegExp(t.replace("*","\\w+")),n={id:D.randomUUID(),event:t,regexp:s,callback:"function"==typeof e?e:null,target:i};return this.subscriptions.push(n),n.id},n.prototype.off=function(t){for(var e=0;this.subscriptions.length>e;){var i=this.subscriptions[e],s=!0;if(t instanceof Object)for(var n in t)t.hasOwnProperty(n)&&t[n]!==i[n]&&(s=!1);else s=i.id==t;s?this.subscriptions.splice(e,1):e++}},n.prototype.emit=function(t,e,i){for(var s=0;this.subscriptions.length>s;s++){var n=this.subscriptions[s];n.regexp.test(t)&&n.callback&&n.callback(t,e,i)}},o.prototype.subscribe=function(t,e){var i=this.subscribers[t];i||(i=[],this.subscribers[t]=i),i.push({callback:e})},o.prototype.unsubscribe=function(t,e){var i=this.subscribers[t];i&&(this.subscribers[t]=i.filter(function(t){return t.callback!=e}))},o.prototype._trigger=function(t,e,i){if("*"==t)throw Error("Cannot trigger event *");var s=[];t in this.subscribers&&(s=s.concat(this.subscribers[t])),"*"in this.subscribers&&(s=s.concat(this.subscribers["*"]));for(var n=0;s.length>n;n++){var o=s[n];o.callback&&o.callback(t,e,i||null)}},o.prototype.add=function(t,e){var i,s=[],n=this;if(t instanceof Array)for(var o=0,r=t.length;r>o;o++)i=n._addItem(t[o]),s.push(i);else if(D.isDataTable(t))for(var a=this._getColumnNames(t),h=0,d=t.getNumberOfRows();d>h;h++){for(var l={},p=0,c=a.length;c>p;p++){var u=a[p];l[u]=t.getValue(h,p)}i=n._addItem(l),s.push(i)}else{if(!(t instanceof Object))throw Error("Unknown dataType");i=n._addItem(t),s.push(i)}return s.length&&this._trigger("add",{items:s},e),s},o.prototype.update=function(t,e){var i=[],s=[],n=this,o=n.fieldId,r=function(t){var e=t[o];n.data[e]?(e=n._updateItem(t),s.push(e)):(e=n._addItem(t),i.push(e))};if(t instanceof Array)for(var a=0,h=t.length;h>a;a++)r(t[a]);else if(D.isDataTable(t))for(var d=this._getColumnNames(t),l=0,p=t.getNumberOfRows();p>l;l++){for(var c={},u=0,f=d.length;f>u;u++){var m=d[u];c[m]=t.getValue(l,u)}r(c)}else{if(!(t instanceof Object))throw Error("Unknown dataType");r(t)}return i.length&&this._trigger("add",{items:i},e),s.length&&this._trigger("update",{items:s},e),i.concat(s)},o.prototype.get=function(){var t,e,i,s,n=this,o=D.getType(arguments[0]);"String"==o||"Number"==o?(t=arguments[0],i=arguments[1],s=arguments[2]):"Array"==o?(e=arguments[0],i=arguments[1],s=arguments[2]):(i=arguments[0],s=arguments[1]);var r;if(i&&i.type){if(r="DataTable"==i.type?"DataTable":"Array",s&&r!=D.getType(s))throw Error('Type of parameter "data" ('+D.getType(s)+") "+"does not correspond with specified options.type ("+i.type+")");if("DataTable"==r&&!D.isDataTable(s))throw Error('Parameter "data" must be a DataTable when options.type is "DataTable"')}else r=s?"DataTable"==D.getType(s)?"DataTable":"Array":"Array";var a,h,d,l,p=i&&i.convert||this.options.convert,c=i&&i.filter,u=[];if(void 0!=t)a=n._getItem(t,p),c&&!c(a)&&(a=null);else if(void 0!=e)for(d=0,l=e.length;l>d;d++)a=n._getItem(e[d],p),(!c||c(a))&&u.push(a);else for(h in this.data)this.data.hasOwnProperty(h)&&(a=n._getItem(h,p),(!c||c(a))&&u.push(a));if(i&&i.order&&void 0==t&&this._sort(u,i.order),i&&i.fields){var f=i.fields;if(void 0!=t)a=this._filterFields(a,f);else for(d=0,l=u.length;l>d;d++)u[d]=this._filterFields(u[d],f)}if("DataTable"==r){var m=this._getColumnNames(s);if(void 0!=t)n._appendRow(s,m,a);else for(d=0,l=u.length;l>d;d++)n._appendRow(s,m,u[d]);return s}if(void 0!=t)return a;if(s){for(d=0,l=u.length;l>d;d++)s.push(u[d]);return s}return u},o.prototype.getIds=function(t){var e,i,s,n,o,r=this.data,a=t&&t.filter,h=t&&t.order,d=t&&t.convert||this.options.convert,l=[];if(a)if(h){o=[];for(s in r)r.hasOwnProperty(s)&&(n=this._getItem(s,d),a(n)&&o.push(n));for(this._sort(o,h),e=0,i=o.length;i>e;e++)l[e]=o[e][this.fieldId]}else for(s in r)r.hasOwnProperty(s)&&(n=this._getItem(s,d),a(n)&&l.push(n[this.fieldId]));else if(h){o=[];for(s in r)r.hasOwnProperty(s)&&o.push(r[s]);for(this._sort(o,h),e=0,i=o.length;i>e;e++)l[e]=o[e][this.fieldId]}else for(s in r)r.hasOwnProperty(s)&&(n=r[s],l.push(n[this.fieldId]));return l},o.prototype.forEach=function(t,e){var i,s,n=e&&e.filter,o=e&&e.convert||this.options.convert,r=this.data;if(e&&e.order)for(var a=this.get(e),h=0,d=a.length;d>h;h++)i=a[h],s=i[this.fieldId],t(i,s);else for(s in r)r.hasOwnProperty(s)&&(i=this._getItem(s,o),(!n||n(i))&&t(i,s))},o.prototype.map=function(t,e){var i,s=e&&e.filter,n=e&&e.convert||this.options.convert,o=[],r=this.data;for(var a in r)r.hasOwnProperty(a)&&(i=this._getItem(a,n),(!s||s(i))&&o.push(t(i,a)));return e&&e.order&&this._sort(o,e.order),o},o.prototype._filterFields=function(t,e){var i={};for(var s in t)t.hasOwnProperty(s)&&-1!=e.indexOf(s)&&(i[s]=t[s]);return i},o.prototype._sort=function(t,e){if(D.isString(e)){var i=e;t.sort(function(t,e){var s=t[i],n=e[i];return s>n?1:n>s?-1:0})}else{if("function"!=typeof e)throw new TypeError("Order must be a function or a string");t.sort(e)}},o.prototype.remove=function(t,e){var i,s,n,o=[];if(t instanceof Array)for(i=0,s=t.length;s>i;i++)n=this._remove(t[i]),null!=n&&o.push(n);else n=this._remove(t),null!=n&&o.push(n);return o.length&&this._trigger("remove",{items:o},e),o},o.prototype._remove=function(t){if(D.isNumber(t)||D.isString(t)){if(this.data[t])return delete this.data[t],delete this.internalIds[t],t}else if(t instanceof Object){var e=t[this.fieldId];if(e&&this.data[e])return delete this.data[e],delete this.internalIds[e],e}return null},o.prototype.clear=function(t){var e=Object.keys(this.data);return this.data={},this.internalIds={},this._trigger("remove",{items:e},t),e},o.prototype.max=function(t){var e=this.data,i=null,s=null;for(var n in e)if(e.hasOwnProperty(n)){var o=e[n],r=o[t];null!=r&&(!i||r>s)&&(i=o,s=r)}return i},o.prototype.min=function(t){var e=this.data,i=null,s=null;for(var n in e)if(e.hasOwnProperty(n)){var o=e[n],r=o[t];null!=r&&(!i||s>r)&&(i=o,s=r)}return i},o.prototype.distinct=function(t){var e=this.data,i=[],s=this.options.convert[t],n=0;for(var o in e)if(e.hasOwnProperty(o)){for(var r=e[o],a=D.convert(r[t],s),h=!1,d=0;n>d;d++)if(i[d]==a){h=!0;break}h||(i[n]=a,n++)}return i},o.prototype._addItem=function(t){var e=t[this.fieldId];if(void 0!=e){if(this.data[e])throw Error("Cannot add item: item with id "+e+" already exists")}else e=D.randomUUID(),t[this.fieldId]=e,this.internalIds[e]=t;var i={};for(var s in t)if(t.hasOwnProperty(s)){var n=this.convert[s];i[s]=D.convert(t[s],n)}return this.data[e]=i,e},o.prototype._getItem=function(t,e){var i,s,n=this.data[t];if(!n)return null;var o={},r=this.fieldId,a=this.internalIds;if(e)for(i in n)n.hasOwnProperty(i)&&(s=n[i],i==r&&s in a||(o[i]=D.convert(s,e[i])));else for(i in n)n.hasOwnProperty(i)&&(s=n[i],i==r&&s in a||(o[i]=s));return o},o.prototype._updateItem=function(t){var e=t[this.fieldId];if(void 0==e)throw Error("Cannot update item: item has no id (item: "+JSON.stringify(t)+")");var i=this.data[e];if(!i)throw Error("Cannot update item: no item with id "+e+" found");for(var s in t)if(t.hasOwnProperty(s)){var n=this.convert[s];i[s]=D.convert(t[s],n)}return e},o.prototype._getColumnNames=function(t){for(var e=[],i=0,s=t.getNumberOfColumns();s>i;i++)e[i]=t.getColumnId(i)||t.getColumnLabel(i);return e},o.prototype._appendRow=function(t,e,i){for(var s=t.addRow(),n=0,o=e.length;o>n;n++){var r=e[n];t.setValue(s,n,i[r])}},r.prototype.setData=function(t){var e,i,s;if(this.data){this.data.unsubscribe&&this.data.unsubscribe("*",this.listener),e=[];for(var n in this.ids)this.ids.hasOwnProperty(n)&&e.push(n);this.ids={},this._trigger("remove",{items:e})}if(this.data=t,this.data){for(this.fieldId=this.options.fieldId||this.data&&this.data.options&&this.data.options.fieldId||"id",e=this.data.getIds({filter:this.options&&this.options.filter}),i=0,s=e.length;s>i;i++)n=e[i],this.ids[n]=!0;this._trigger("add",{items:e}),this.data.subscribe&&this.data.subscribe("*",this.listener)}},r.prototype.get=function(){var t,e,i,s=this,n=D.getType(arguments[0]);"String"==n||"Number"==n||"Array"==n?(t=arguments[0],e=arguments[1],i=arguments[2]):(e=arguments[0],i=arguments[1]);var o=D.extend({},this.options,e);this.options.filter&&e&&e.filter&&(o.filter=function(t){return s.options.filter(t)&&e.filter(t)});var r=[];return void 0!=t&&r.push(t),r.push(o),r.push(i),this.data&&this.data.get.apply(this.data,r)},r.prototype.getIds=function(t){var e;if(this.data){var i,s=this.options.filter;i=t&&t.filter?s?function(e){return s(e)&&t.filter(e)}:t.filter:s,e=this.data.getIds({filter:i,order:t&&t.order})}else e=[];return e},r.prototype._onEvent=function(t,e,i){var s,n,o,r,a=e&&e.items,h=this.data,d=[],l=[],p=[];if(a&&h){switch(t){case"add":for(s=0,n=a.length;n>s;s++)o=a[s],r=this.get(o),r&&(this.ids[o]=!0,d.push(o));break;case"update":for(s=0,n=a.length;n>s;s++)o=a[s],r=this.get(o),r?this.ids[o]?l.push(o):(this.ids[o]=!0,d.push(o)):this.ids[o]&&(delete this.ids[o],p.push(o));break;case"remove":for(s=0,n=a.length;n>s;s++)o=a[s],this.ids[o]&&(delete this.ids[o],p.push(o))}d.length&&this._trigger("add",{items:d},i),l.length&&this._trigger("update",{items:l},i),p.length&&this._trigger("remove",{items:p},i)}},r.prototype.subscribe=o.prototype.subscribe,r.prototype.unsubscribe=o.prototype.unsubscribe,r.prototype._trigger=o.prototype._trigger,TimeStep=function(t,e,i){this.current=new Date,this._start=new Date,this._end=new Date,this.autoScale=!0,this.scale=TimeStep.SCALE.DAY,this.step=1,this.setRange(t,e,i)},TimeStep.SCALE={MILLISECOND:1,SECOND:2,MINUTE:3,HOUR:4,DAY:5,WEEKDAY:6,MONTH:7,YEAR:8},TimeStep.prototype.setRange=function(t,e,i){t instanceof Date&&e instanceof Date&&(this._start=void 0!=t?new Date(t.valueOf()):new Date,this._end=void 0!=e?new Date(e.valueOf()):new Date,this.autoScale&&this.setMinimumStep(i))},TimeStep.prototype.first=function(){this.current=new Date(this._start.valueOf()),this.roundToMinor()},TimeStep.prototype.roundToMinor=function(){switch(this.scale){case TimeStep.SCALE.YEAR:this.current.setFullYear(this.step*Math.floor(this.current.getFullYear()/this.step)),this.current.setMonth(0);case TimeStep.SCALE.MONTH:this.current.setDate(1);case TimeStep.SCALE.DAY:case TimeStep.SCALE.WEEKDAY:this.current.setHours(0);case TimeStep.SCALE.HOUR:this.current.setMinutes(0);case TimeStep.SCALE.MINUTE:this.current.setSeconds(0);case TimeStep.SCALE.SECOND:this.current.setMilliseconds(0)}if(1!=this.step)switch(this.scale){case TimeStep.SCALE.MILLISECOND:this.current.setMilliseconds(this.current.getMilliseconds()-this.current.getMilliseconds()%this.step);break;case TimeStep.SCALE.SECOND:this.current.setSeconds(this.current.getSeconds()-this.current.getSeconds()%this.step);break;case TimeStep.SCALE.MINUTE:this.current.setMinutes(this.current.getMinutes()-this.current.getMinutes()%this.step);break;case TimeStep.SCALE.HOUR:this.current.setHours(this.current.getHours()-this.current.getHours()%this.step);break;case TimeStep.SCALE.WEEKDAY:case TimeStep.SCALE.DAY:this.current.setDate(this.current.getDate()-1-(this.current.getDate()-1)%this.step+1);break;case TimeStep.SCALE.MONTH:this.current.setMonth(this.current.getMonth()-this.current.getMonth()%this.step);break;case TimeStep.SCALE.YEAR:this.current.setFullYear(this.current.getFullYear()-this.current.getFullYear()%this.step);break;default:}},TimeStep.prototype.hasNext=function(){return this.current.valueOf()<=this._end.valueOf()},TimeStep.prototype.next=function(){var t=this.current.valueOf();if(6>this.current.getMonth())switch(this.scale){case TimeStep.SCALE.MILLISECOND:this.current=new Date(this.current.valueOf()+this.step);break;case TimeStep.SCALE.SECOND:this.current=new Date(this.current.valueOf()+1e3*this.step);break;case TimeStep.SCALE.MINUTE:this.current=new Date(this.current.valueOf()+60*1e3*this.step);break;case TimeStep.SCALE.HOUR:this.current=new Date(this.current.valueOf()+60*60*1e3*this.step);var e=this.current.getHours();this.current.setHours(e-e%this.step);break;case TimeStep.SCALE.WEEKDAY:case TimeStep.SCALE.DAY:this.current.setDate(this.current.getDate()+this.step);break;case TimeStep.SCALE.MONTH:this.current.setMonth(this.current.getMonth()+this.step);break;case TimeStep.SCALE.YEAR:this.current.setFullYear(this.current.getFullYear()+this.step);break;default:}else switch(this.scale){case TimeStep.SCALE.MILLISECOND:this.current=new Date(this.current.valueOf()+this.step);break;case TimeStep.SCALE.SECOND:this.current.setSeconds(this.current.getSeconds()+this.step);break;case TimeStep.SCALE.MINUTE:this.current.setMinutes(this.current.getMinutes()+this.step);break;case TimeStep.SCALE.HOUR:this.current.setHours(this.current.getHours()+this.step);break;case TimeStep.SCALE.WEEKDAY:case TimeStep.SCALE.DAY:this.current.setDate(this.current.getDate()+this.step);break;case TimeStep.SCALE.MONTH:this.current.setMonth(this.current.getMonth()+this.step);break;case TimeStep.SCALE.YEAR:this.current.setFullYear(this.current.getFullYear()+this.step);break;default:}if(1!=this.step)switch(this.scale){case TimeStep.SCALE.MILLISECOND:this.current.getMilliseconds()0&&(this.step=e),this.autoScale=!1},TimeStep.prototype.setAutoScale=function(t){this.autoScale=t},TimeStep.prototype.setMinimumStep=function(t){if(void 0!=t){var e=31104e6,i=2592e6,s=864e5,n=36e5,o=6e4,r=1e3,a=1;1e3*e>t&&(this.scale=TimeStep.SCALE.YEAR,this.step=1e3),500*e>t&&(this.scale=TimeStep.SCALE.YEAR,this.step=500),100*e>t&&(this.scale=TimeStep.SCALE.YEAR,this.step=100),50*e>t&&(this.scale=TimeStep.SCALE.YEAR,this.step=50),10*e>t&&(this.scale=TimeStep.SCALE.YEAR,this.step=10),5*e>t&&(this.scale=TimeStep.SCALE.YEAR,this.step=5),e>t&&(this.scale=TimeStep.SCALE.YEAR,this.step=1),3*i>t&&(this.scale=TimeStep.SCALE.MONTH,this.step=3),i>t&&(this.scale=TimeStep.SCALE.MONTH,this.step=1),5*s>t&&(this.scale=TimeStep.SCALE.DAY,this.step=5),2*s>t&&(this.scale=TimeStep.SCALE.DAY,this.step=2),s>t&&(this.scale=TimeStep.SCALE.DAY,this.step=1),s/2>t&&(this.scale=TimeStep.SCALE.WEEKDAY,this.step=1),4*n>t&&(this.scale=TimeStep.SCALE.HOUR,this.step=4),n>t&&(this.scale=TimeStep.SCALE.HOUR,this.step=1),15*o>t&&(this.scale=TimeStep.SCALE.MINUTE,this.step=15),10*o>t&&(this.scale=TimeStep.SCALE.MINUTE,this.step=10),5*o>t&&(this.scale=TimeStep.SCALE.MINUTE,this.step=5),o>t&&(this.scale=TimeStep.SCALE.MINUTE,this.step=1),15*r>t&&(this.scale=TimeStep.SCALE.SECOND,this.step=15),10*r>t&&(this.scale=TimeStep.SCALE.SECOND,this.step=10),5*r>t&&(this.scale=TimeStep.SCALE.SECOND,this.step=5),r>t&&(this.scale=TimeStep.SCALE.SECOND,this.step=1),200*a>t&&(this.scale=TimeStep.SCALE.MILLISECOND,this.step=200),100*a>t&&(this.scale=TimeStep.SCALE.MILLISECOND,this.step=100),50*a>t&&(this.scale=TimeStep.SCALE.MILLISECOND,this.step=50),10*a>t&&(this.scale=TimeStep.SCALE.MILLISECOND,this.step=10),5*a>t&&(this.scale=TimeStep.SCALE.MILLISECOND,this.step=5),a>t&&(this.scale=TimeStep.SCALE.MILLISECOND,this.step=1) }},TimeStep.prototype.snap=function(t){if(this.scale==TimeStep.SCALE.YEAR){var e=t.getFullYear()+Math.round(t.getMonth()/12);t.setFullYear(Math.round(e/this.step)*this.step),t.setMonth(0),t.setDate(0),t.setHours(0),t.setMinutes(0),t.setSeconds(0),t.setMilliseconds(0)}else if(this.scale==TimeStep.SCALE.MONTH)t.getDate()>15?(t.setDate(1),t.setMonth(t.getMonth()+1)):t.setDate(1),t.setHours(0),t.setMinutes(0),t.setSeconds(0),t.setMilliseconds(0);else if(this.scale==TimeStep.SCALE.DAY||this.scale==TimeStep.SCALE.WEEKDAY){switch(this.step){case 5:case 2:t.setHours(24*Math.round(t.getHours()/24));break;default:t.setHours(12*Math.round(t.getHours()/12))}t.setMinutes(0),t.setSeconds(0),t.setMilliseconds(0)}else if(this.scale==TimeStep.SCALE.HOUR){switch(this.step){case 4:t.setMinutes(60*Math.round(t.getMinutes()/60));break;default:t.setMinutes(30*Math.round(t.getMinutes()/30))}t.setSeconds(0),t.setMilliseconds(0)}else if(this.scale==TimeStep.SCALE.MINUTE){switch(this.step){case 15:case 10:t.setMinutes(5*Math.round(t.getMinutes()/5)),t.setSeconds(0);break;case 5:t.setSeconds(60*Math.round(t.getSeconds()/60));break;default:t.setSeconds(30*Math.round(t.getSeconds()/30))}t.setMilliseconds(0)}else if(this.scale==TimeStep.SCALE.SECOND)switch(this.step){case 15:case 10:t.setSeconds(5*Math.round(t.getSeconds()/5)),t.setMilliseconds(0);break;case 5:t.setMilliseconds(1e3*Math.round(t.getMilliseconds()/1e3));break;default:t.setMilliseconds(500*Math.round(t.getMilliseconds()/500))}else if(this.scale==TimeStep.SCALE.MILLISECOND){var i=this.step>5?this.step/2:1;t.setMilliseconds(Math.round(t.getMilliseconds()/i)*i)}},TimeStep.prototype.isMajor=function(){switch(this.scale){case TimeStep.SCALE.MILLISECOND:return 0==this.current.getMilliseconds();case TimeStep.SCALE.SECOND:return 0==this.current.getSeconds();case TimeStep.SCALE.MINUTE:return 0==this.current.getHours()&&0==this.current.getMinutes();case TimeStep.SCALE.HOUR:return 0==this.current.getHours();case TimeStep.SCALE.WEEKDAY:case TimeStep.SCALE.DAY:return 1==this.current.getDate();case TimeStep.SCALE.MONTH:return 0==this.current.getMonth();case TimeStep.SCALE.YEAR:return!1;default:return!1}},TimeStep.prototype.getLabelMinor=function(t){switch(void 0==t&&(t=this.current),this.scale){case TimeStep.SCALE.MILLISECOND:return E(t).format("SSS");case TimeStep.SCALE.SECOND:return E(t).format("s");case TimeStep.SCALE.MINUTE:return E(t).format("HH:mm");case TimeStep.SCALE.HOUR:return E(t).format("HH:mm");case TimeStep.SCALE.WEEKDAY:return E(t).format("ddd D");case TimeStep.SCALE.DAY:return E(t).format("D");case TimeStep.SCALE.MONTH:return E(t).format("MMM");case TimeStep.SCALE.YEAR:return E(t).format("YYYY");default:return""}},TimeStep.prototype.getLabelMajor=function(t){switch(void 0==t&&(t=this.current),this.scale){case TimeStep.SCALE.MILLISECOND:return E(t).format("HH:mm:ss");case TimeStep.SCALE.SECOND:return E(t).format("D MMMM HH:mm");case TimeStep.SCALE.MINUTE:case TimeStep.SCALE.HOUR:return E(t).format("ddd D MMMM");case TimeStep.SCALE.WEEKDAY:case TimeStep.SCALE.DAY:return E(t).format("MMMM YYYY");case TimeStep.SCALE.MONTH:return E(t).format("YYYY");case TimeStep.SCALE.YEAR:return"";default:return""}},a.prototype.setOptions=function(t){D.extend(this.options,t)},a.prototype.update=function(){this._order(),this._stack()},a.prototype._order=function(){var t=this.parent.items;if(!t)throw Error("Cannot stack items: parent does not contain items");var e=[],i=0;D.forEach(t,function(t){t.visible&&(e[i]=t,i++)});var s=this.options.order||this.defaultOptions.order;if("function"!=typeof s)throw Error("Option order must be a function");e.sort(s),this.ordered=e},a.prototype._stack=function(){var t,e,i,s=this.ordered,n=this.options,o=n.orientation||this.defaultOptions.orientation,r="top"==o;for(i=n.margin&&void 0!==n.margin.item?n.margin.item:this.defaultOptions.margin.item,t=0,e=s.length;e>t;t++){var a=s[t],h=null;do h=this.checkOverlap(s,t,0,t-1,i),null!=h&&(a.top=r?h.top+h.height+i:h.top-a.height-i);while(h)}},a.prototype.checkOverlap=function(t,e,i,s,n){for(var o=this.collision,r=t[e],a=s;a>=i;a--){var h=t[a];if(o(r,h,n)&&a!=e)return h}return null},a.prototype.collision=function(t,e,i){return t.left-ie.left&&t.top-ie.top},h.prototype.setOptions=function(t){D.extend(this.options,t),(null!=t.start||null!=t.end)&&this.setRange(t.start,t.end)},h.prototype.subscribe=function(t,e,i){var s,n=this;if("horizontal"!=i&&"vertical"!=i)throw new TypeError('Unknown direction "'+i+'". '+'Choose "horizontal" or "vertical".');if("move"==e)s={component:t,event:e,direction:i,callback:function(t){n._onMouseDown(t,s)},params:{}},t.on("mousedown",s.callback),n.listeners.push(s);else{if("zoom"!=e)throw new TypeError('Unknown event "'+e+'". '+'Choose "move" or "zoom".');s={component:t,event:e,direction:i,callback:function(t){n._onMouseWheel(t,s)},params:{}},t.on("mousewheel",s.callback),n.listeners.push(s)}},h.prototype.on=function(t,e){O.addListener(this,t,e)},h.prototype._trigger=function(t){O.trigger(this,t,{start:this.start,end:this.end})},h.prototype.setRange=function(t,e){var i=this._applyRange(t,e);i&&(this._trigger("rangechange"),this._trigger("rangechanged"))},h.prototype._applyRange=function(t,e){var i,s=null!=t?D.convert(t,"Number"):this.start,n=null!=e?D.convert(e,"Number"):this.end;if(isNaN(s))throw Error('Invalid start "'+t+'"');if(isNaN(n))throw Error('Invalid end "'+e+'"');if(s>n&&(n=s),null!=this.options.min){var o=this.options.min.valueOf();o>s&&(i=o-s,s+=i,n+=i)}if(null!=this.options.max){var r=this.options.max.valueOf();n>r&&(i=n-r,s-=i,n-=i)}if(null!=this.options.zoomMin){var a=this.options.zoomMin.valueOf();0>a&&(a=0),a>n-s&&(this.end-this.start>a?(i=a-(n-s),s-=i/2,n+=i/2):(s=this.start,n=this.end))}if(null!=this.options.zoomMax){var h=this.options.zoomMax.valueOf();0>h&&(h=0),n-s>h&&(h>this.end-this.start?(i=n-s-h,s+=i/2,n-=i/2):(s=this.start,n=this.end))}var d=this.start!=s||this.end!=n;return this.start=s,this.end=n,d},h.prototype.getRange=function(){return{start:this.start,end:this.end}},h.prototype.conversion=function(t){return this.start,this.end,h.conversion(this.start,this.end,t)},h.conversion=function(t,e,i){return 0!=i&&0!=e-t?{offset:t,factor:i/(e-t)}:{offset:0,factor:1}},h.prototype._onMouseDown=function(t,e){t=t||window.event;var i=e.params,s=t.which?1==t.which:1==t.button;if(s){i.mouseX=D.getPageX(t),i.mouseY=D.getPageY(t),i.previousLeft=0,i.previousOffset=0,i.moved=!1,i.start=this.start,i.end=this.end;var n=e.component.frame;n&&(n.style.cursor="move");var o=this;i.onMouseMove||(i.onMouseMove=function(t){o._onMouseMove(t,e)},D.addEventListener(document,"mousemove",i.onMouseMove)),i.onMouseUp||(i.onMouseUp=function(t){o._onMouseUp(t,e)},D.addEventListener(document,"mouseup",i.onMouseUp)),D.preventDefault(t)}},h.prototype._onMouseMove=function(t,e){t=t||window.event;var i=e.params,s=D.getPageX(t),n=D.getPageY(t);void 0==i.mouseX&&(i.mouseX=s),void 0==i.mouseY&&(i.mouseY=n);var o=s-i.mouseX,r=n-i.mouseY,a="horizontal"==e.direction?o:r;Math.abs(a)>=1&&(i.moved=!0);var h=i.end-i.start,d="horizontal"==e.direction?e.component.width:e.component.height,l=-a/d*h;this._applyRange(i.start+l,i.end+l),this._trigger("rangechange"),D.preventDefault(t)},h.prototype._onMouseUp=function(t,e){t=t||window.event;var i=e.params;e.component.frame&&(e.component.frame.style.cursor="auto"),i.onMouseMove&&(D.removeEventListener(document,"mousemove",i.onMouseMove),i.onMouseMove=null),i.onMouseUp&&(D.removeEventListener(document,"mouseup",i.onMouseUp),i.onMouseUp=null),i.moved&&this._trigger("rangechanged")},h.prototype._onMouseWheel=function(t,e){t=t||window.event;var i=0;if(t.wheelDelta?i=t.wheelDelta/120:t.detail&&(i=-t.detail/3),i){var s=this,n=function(){var n=i/5,o=null,r=e.component.frame;if(r){var a,h;if("horizontal"==e.direction){a=e.component.width,h=s.conversion(a);var d=D.getAbsoluteLeft(r),l=D.getPageX(t);o=(l-d)/h.factor+h.offset}else{a=e.component.height,h=s.conversion(a);var p=D.getAbsoluteTop(r),c=D.getPageY(t);o=(p+a-c-p)/h.factor+h.offset}}s.zoom(n,o)};n()}D.preventDefault(t)},h.prototype.zoom=function(t,e){null==e&&(e=(this.start+this.end)/2),t>=1&&(t=.9),-1>=t&&(t=-.9),0>t&&(t/=1+t);var i=this.start-e,s=this.end-e,n=this.start-i*t,o=this.end-s*t;this.setRange(n,o)},h.prototype.move=function(t){var e=this.end-this.start,i=this.start+e*t,s=this.end+e*t;this.start=i,this.end=s},h.prototype.moveTo=function(t){var e=(this.start+this.end)/2,i=e-t,s=this.start-i,n=this.end-i;this.setRange(s,n)},d.prototype.add=function(t){if(void 0==t.id)throw Error("Component has no field id");if(!(t instanceof l||t instanceof d))throw new TypeError("Component must be an instance of prototype Component or Controller");t.controller=this,this.components[t.id]=t},d.prototype.remove=function(t){var e;for(e in this.components)if(this.components.hasOwnProperty(e)&&(e==t||this.components[e]==t))break;e&&delete this.components[e]},d.prototype.requestReflow=function(t){if(t)this.reflow();else if(!this.reflowTimer){var e=this;this.reflowTimer=setTimeout(function(){e.reflowTimer=void 0,e.reflow()},0)}},d.prototype.requestRepaint=function(t){if(t)this.repaint();else if(!this.repaintTimer){var e=this;this.repaintTimer=setTimeout(function(){e.repaintTimer=void 0,e.repaint()},0)}},d.prototype.repaint=function(){function t(s,n){n in i||(s.depends&&s.depends.forEach(function(e){t(e,e.id)}),s.parent&&t(s.parent,s.parent.id),e=s.repaint()||e,i[n]=!0)}var e=!1;this.repaintTimer&&(clearTimeout(this.repaintTimer),this.repaintTimer=void 0);var i={};D.forEach(this.components,t),e&&this.reflow()},d.prototype.reflow=function(){function t(s,n){n in i||(s.depends&&s.depends.forEach(function(e){t(e,e.id)}),s.parent&&t(s.parent,s.parent.id),e=s.reflow()||e,i[n]=!0)}var e=!1;this.reflowTimer&&(clearTimeout(this.reflowTimer),this.reflowTimer=void 0);var i={};D.forEach(this.components,t),e&&this.repaint()},l.prototype.setOptions=function(t){t&&(D.extend(this.options,t),this.controller&&(this.requestRepaint(),this.requestReflow()))},l.prototype.getOption=function(t){var e;return this.options&&(e=this.options[t]),void 0===e&&this.defaultOptions&&(e=this.defaultOptions[t]),e},l.prototype.getContainer=function(){return null},l.prototype.getFrame=function(){return this.frame},l.prototype.repaint=function(){return!1},l.prototype.reflow=function(){return!1},l.prototype.hide=function(){return this.frame&&this.frame.parentNode?(this.frame.parentNode.removeChild(this.frame),!0):!1},l.prototype.show=function(){return this.frame&&this.frame.parentNode?!1:this.repaint()},l.prototype.requestRepaint=function(){if(!this.controller)throw Error("Cannot request a repaint: no controller configured");this.controller.requestRepaint()},l.prototype.requestReflow=function(){if(!this.controller)throw Error("Cannot request a reflow: no controller configured");this.controller.requestReflow()},p.prototype=new l,p.prototype.setOptions=l.prototype.setOptions,p.prototype.getContainer=function(){return this.frame},p.prototype.repaint=function(){var t=0,e=D.updateProperty,i=D.option.asSize,s=this.options,n=this.frame;if(!n){n=document.createElement("div"),n.className="panel";var o=s.className;o&&("function"==typeof o?D.addClassName(n,o()+""):D.addClassName(n,o+"")),this.frame=n,t+=1}if(!n.parentNode){if(!this.parent)throw Error("Cannot repaint panel: no parent attached");var r=this.parent.getContainer();if(!r)throw Error("Cannot repaint panel: parent has no container element");r.appendChild(n),t+=1}return t+=e(n.style,"top",i(s.top,"0px")),t+=e(n.style,"left",i(s.left,"0px")),t+=e(n.style,"width",i(s.width,"100%")),t+=e(n.style,"height",i(s.height,"100%")),t>0},p.prototype.reflow=function(){var t=0,e=D.updateProperty,i=this.frame;return i?(t+=e(this,"top",i.offsetTop),t+=e(this,"left",i.offsetLeft),t+=e(this,"width",i.offsetWidth),t+=e(this,"height",i.offsetHeight)):t+=1,t>0},c.prototype=new p,c.prototype.setOptions=l.prototype.setOptions,c.prototype.repaint=function(){var t=0,e=D.updateProperty,i=D.option.asSize,s=this.options,n=this.frame;if(!n){n=document.createElement("div"),n.className="vis timeline rootpanel";var o=s.className;o&&D.addClassName(n,D.option.asString(o)),this.frame=n,t+=1}if(!n.parentNode){if(!this.container)throw Error("Cannot repaint root panel: no container attached");this.container.appendChild(n),t+=1}return t+=e(n.style,"top",i(s.top,"0px")),t+=e(n.style,"left",i(s.left,"0px")),t+=e(n.style,"width",i(s.width,"100%")),t+=e(n.style,"height",i(s.height,"100%")),this._updateEventEmitters(),this._updateWatch(),t>0},c.prototype.reflow=function(){var t=0,e=D.updateProperty,i=this.frame;return i?(t+=e(this,"top",i.offsetTop),t+=e(this,"left",i.offsetLeft),t+=e(this,"width",i.offsetWidth),t+=e(this,"height",i.offsetHeight)):t+=1,t>0},c.prototype._updateWatch=function(){var t=this.getOption("autoResize");t?this._watch():this._unwatch()},c.prototype._watch=function(){var t=this;this._unwatch();var e=function(){var e=t.getOption("autoResize");return e?(t.frame&&(t.frame.clientWidth!=t.width||t.frame.clientHeight!=t.height)&&t.requestReflow(),void 0):(t._unwatch(),void 0)};D.addEventListener(window,"resize",e),this.watchTimer=setInterval(e,1e3)},c.prototype._unwatch=function(){this.watchTimer&&(clearInterval(this.watchTimer),this.watchTimer=void 0)},c.prototype.on=function(t,e){var i=this.listeners[t];i||(i=[],this.listeners[t]=i),i.push(e),this._updateEventEmitters()},c.prototype._updateEventEmitters=function(){if(this.listeners){var t=this;D.forEach(this.listeners,function(e,i){if(t.emitters||(t.emitters={}),!(i in t.emitters)){var s=t.frame;if(s){var n=function(t){e.forEach(function(e){e(t)})};t.emitters[i]=n,D.addEventListener(s,i,n)}}})}},u.prototype=new l,u.prototype.setOptions=l.prototype.setOptions,u.prototype.setRange=function(t){if(!(t instanceof h||t&&t.start&&t.end))throw new TypeError("Range must be an instance of Range, or an object containing start and end.");this.range=t},u.prototype.toTime=function(t){var e=this.conversion;return new Date(t/e.factor+e.offset)},u.prototype.toScreen=function(t){var e=this.conversion;return(t.valueOf()-e.offset)*e.factor},u.prototype.repaint=function(){var t=0,e=D.updateProperty,i=D.option.asSize,s=this.options,n=this.getOption("orientation"),o=this.props,r=this.step,a=this.frame;if(a||(a=document.createElement("div"),this.frame=a,t+=1),a.className="axis "+n,!a.parentNode){if(!this.parent)throw Error("Cannot repaint time axis: no parent attached");var h=this.parent.getContainer();if(!h)throw Error("Cannot repaint time axis: parent has no container element");h.appendChild(a),t+=1}var d=a.parentNode;if(d){var l=a.nextSibling;d.removeChild(a);var p="bottom"==n&&this.props.parentHeight&&this.height?this.props.parentHeight-this.height+"px":"0px";if(t+=e(a.style,"top",i(s.top,p)),t+=e(a.style,"left",i(s.left,"0px")),t+=e(a.style,"width",i(s.width,"100%")),t+=e(a.style,"height",i(s.height,this.height+"px")),this._repaintMeasureChars(),this.step){this._repaintStart(),r.first();for(var c=void 0,u=0;r.hasNext()&&1e3>u;){u++;var f=r.getCurrent(),m=this.toScreen(f),g=r.isMajor();this.getOption("showMinorLabels")&&this._repaintMinorText(m,r.getLabelMinor()),g&&this.getOption("showMajorLabels")?(m>0&&(void 0==c&&(c=m),this._repaintMajorText(m,r.getLabelMajor())),this._repaintMajorLine(m)):this._repaintMinorLine(m),r.next()}if(this.getOption("showMajorLabels")){var v=this.toTime(0),y=r.getLabelMajor(v),b=y.length*(o.majorCharWidth||10)+10;(void 0==c||c>b)&&this._repaintMajorText(0,y)}this._repaintEnd()}this._repaintLine(),l?d.insertBefore(a,l):d.appendChild(a)}return t>0},u.prototype._repaintStart=function(){var t=this.dom,e=t.redundant;e.majorLines=t.majorLines,e.majorTexts=t.majorTexts,e.minorLines=t.minorLines,e.minorTexts=t.minorTexts,t.majorLines=[],t.majorTexts=[],t.minorLines=[],t.minorTexts=[]},u.prototype._repaintEnd=function(){D.forEach(this.dom.redundant,function(t){for(;t.length;){var e=t.pop();e&&e.parentNode&&e.parentNode.removeChild(e)}})},u.prototype._repaintMinorText=function(t,e){var i=this.dom.redundant.minorTexts.shift();if(!i){var s=document.createTextNode("");i=document.createElement("div"),i.appendChild(s),i.className="text minor",this.frame.appendChild(i)}this.dom.minorTexts.push(i),i.childNodes[0].nodeValue=e,i.style.left=t+"px",i.style.top=this.props.minorLabelTop+"px"},u.prototype._repaintMajorText=function(t,e){var i=this.dom.redundant.majorTexts.shift();if(!i){var s=document.createTextNode(e);i=document.createElement("div"),i.className="text major",i.appendChild(s),this.frame.appendChild(i)}this.dom.majorTexts.push(i),i.childNodes[0].nodeValue=e,i.style.top=this.props.majorLabelTop+"px",i.style.left=t+"px"},u.prototype._repaintMinorLine=function(t){var e=this.dom.redundant.minorLines.shift();e||(e=document.createElement("div"),e.className="grid vertical minor",this.frame.appendChild(e)),this.dom.minorLines.push(e);var i=this.props;e.style.top=i.minorLineTop+"px",e.style.height=i.minorLineHeight+"px",e.style.left=t-i.minorLineWidth/2+"px"},u.prototype._repaintMajorLine=function(t){var e=this.dom.redundant.majorLines.shift();e||(e=document.createElement("DIV"),e.className="grid vertical major",this.frame.appendChild(e)),this.dom.majorLines.push(e);var i=this.props;e.style.top=i.majorLineTop+"px",e.style.left=t-i.majorLineWidth/2+"px",e.style.height=i.majorLineHeight+"px"},u.prototype._repaintLine=function(){var t=this.dom.line,e=this.frame;this.options,this.getOption("showMinorLabels")||this.getOption("showMajorLabels")?(t?(e.removeChild(t),e.appendChild(t)):(t=document.createElement("div"),t.className="grid horizontal major",e.appendChild(t),this.dom.line=t),t.style.top=this.props.lineTop+"px"):t&&axis.parentElement&&(e.removeChild(axis.line),delete this.dom.line)},u.prototype._repaintMeasureChars=function(){var t,e=this.dom;if(!e.measureCharMinor){t=document.createTextNode("0");var i=document.createElement("DIV");i.className="text minor measure",i.appendChild(t),this.frame.appendChild(i),e.measureCharMinor=i}if(!e.measureCharMajor){t=document.createTextNode("0");var s=document.createElement("DIV");s.className="text major measure",s.appendChild(t),this.frame.appendChild(s),e.measureCharMajor=s}},u.prototype.reflow=function(){var t=0,e=D.updateProperty,i=this.frame,s=this.range;if(!s)throw Error("Cannot repaint time axis: no range configured");if(i){t+=e(this,"top",i.offsetTop),t+=e(this,"left",i.offsetLeft);var n=this.props,o=this.getOption("showMinorLabels"),r=this.getOption("showMajorLabels"),a=this.dom.measureCharMinor,h=this.dom.measureCharMajor;a&&(n.minorCharHeight=a.clientHeight,n.minorCharWidth=a.clientWidth),h&&(n.majorCharHeight=h.clientHeight,n.majorCharWidth=h.clientWidth);var d=i.parentNode?i.parentNode.offsetHeight:0;switch(d!=n.parentHeight&&(n.parentHeight=d,t+=1),this.getOption("orientation")){case"bottom":n.minorLabelHeight=o?n.minorCharHeight:0,n.majorLabelHeight=r?n.majorCharHeight:0,n.minorLabelTop=0,n.majorLabelTop=n.minorLabelTop+n.minorLabelHeight,n.minorLineTop=-this.top,n.minorLineHeight=Math.max(this.top+n.majorLabelHeight,0),n.minorLineWidth=1,n.majorLineTop=-this.top,n.majorLineHeight=Math.max(this.top+n.minorLabelHeight+n.majorLabelHeight,0),n.majorLineWidth=1,n.lineTop=0;break;case"top":n.minorLabelHeight=o?n.minorCharHeight:0,n.majorLabelHeight=r?n.majorCharHeight:0,n.majorLabelTop=0,n.minorLabelTop=n.majorLabelTop+n.majorLabelHeight,n.minorLineTop=n.minorLabelTop,n.minorLineHeight=Math.max(d-n.majorLabelHeight-this.top),n.minorLineWidth=1,n.majorLineTop=0,n.majorLineHeight=Math.max(d-this.top),n.majorLineWidth=1,n.lineTop=n.majorLabelHeight+n.minorLabelHeight;break;default:throw Error('Unkown orientation "'+this.getOption("orientation")+'"')}var l=n.minorLabelHeight+n.majorLabelHeight;t+=e(this,"width",i.offsetWidth),t+=e(this,"height",l),this._updateConversion();var p=D.convert(s.start,"Date"),c=D.convert(s.end,"Date"),u=this.toTime(5*(n.minorCharWidth||10))-this.toTime(0);this.step=new TimeStep(p,c,u),t+=e(n.range,"start",p.valueOf()),t+=e(n.range,"end",c.valueOf()),t+=e(n.range,"minimumStep",u.valueOf())}return t>0},u.prototype._updateConversion=function(){var t=this.range;if(!t)throw Error("No range configured");this.conversion=t.conversion?t.conversion(this.width):h.conversion(t.start,t.end,this.width)},f.prototype=new p,f.types={box:g,range:y,point:v},f.prototype.setOptions=l.prototype.setOptions,f.prototype.setRange=function(t){if(!(t instanceof h||t&&t.start&&t.end))throw new TypeError("Range must be an instance of Range, or an object containing start and end.");this.range=t},f.prototype.repaint=function(){var t=0,e=D.updateProperty,i=D.option.asSize,s=this.options,n=this.getOption("orientation"),o=this.defaultOptions,r=this.frame;if(!r){r=document.createElement("div"),r.className="itemset";var a=s.className;a&&D.addClassName(r,D.option.asString(a));var h=document.createElement("div");h.className="background",r.appendChild(h),this.dom.background=h;var d=document.createElement("div");d.className="foreground",r.appendChild(d),this.dom.foreground=d;var l=document.createElement("div");l.className="itemset-axis",this.dom.axis=l,this.frame=r,t+=1}if(!this.parent)throw Error("Cannot repaint itemset: no parent attached");var p=this.parent.getContainer();if(!p)throw Error("Cannot repaint itemset: parent has no container element");r.parentNode||(p.appendChild(r),t+=1),this.dom.axis.parentNode||(p.appendChild(this.dom.axis),t+=1),t+=e(r.style,"left",i(s.left,"0px")),t+=e(r.style,"top",i(s.top,"0px")),t+=e(r.style,"width",i(s.width,"100%")),t+=e(r.style,"height",i(s.height,this.height+"px")),t+=e(this.dom.axis.style,"left",i(s.left,"0px")),t+=e(this.dom.axis.style,"width",i(s.width,"100%")),t+="bottom"==n?e(this.dom.axis.style,"top",this.height+this.top+"px"):e(this.dom.axis.style,"top",this.top+"px"),this._updateConversion();var c=this,u=this.queue,m=this.itemsData,g=this.items,v={};return Object.keys(u).forEach(function(e){var i=u[e],n=g[e];switch(i){case"add":case"update":var r=m&&m.get(e,v);if(r){var a=r.type||r.start&&r.end&&"range"||s.type||"box",h=f.types[a];if(n&&(h&&n instanceof h?(n.data=r,t++):(t+=n.hide(),n=null)),!n){if(!h)throw new TypeError('Unknown item type "'+a+'"');n=new h(c,r,s,o),t++}n.repaint(),g[e]=n}delete u[e];break;case"remove":n&&(t+=n.hide()),delete g[e],delete u[e];break;default:console.log('Error: unknown action "'+i+'"')}}),D.forEach(this.items,function(e){e.visible?(t+=e.show(),e.reposition()):t+=e.hide()}),t>0},f.prototype.getForeground=function(){return this.dom.foreground},f.prototype.getBackground=function(){return this.dom.background},f.prototype.getAxis=function(){return this.dom.axis},f.prototype.reflow=function(){var t=0,e=this.options,i=e.margin&&e.margin.axis||this.defaultOptions.margin.axis,s=e.margin&&e.margin.item||this.defaultOptions.margin.item,n=D.updateProperty,o=D.option.asNumber,r=D.option.asSize,a=this.frame;if(a){this._updateConversion(),D.forEach(this.items,function(e){t+=e.reflow()}),this.stack.update();var h,d=o(e.maxHeight),l=null!=r(e.height);if(l)h=a.offsetHeight;else{var p=this.stack.ordered;if(p.length){var c=p[0].top,u=p[0].top+p[0].height;D.forEach(p,function(t){c=Math.min(c,t.top),u=Math.max(u,t.top+t.height)}),h=u-c+i+s}else h=i+s}null!=d&&(h=Math.min(h,d)),t+=n(this,"height",h),t+=n(this,"top",a.offsetTop),t+=n(this,"left",a.offsetLeft),t+=n(this,"width",a.offsetWidth)}else t+=1;return t>0},f.prototype.hide=function(){var t=!1;return this.frame&&this.frame.parentNode&&(this.frame.parentNode.removeChild(this.frame),t=!0),this.dom.axis&&this.dom.axis.parentNode&&(this.dom.axis.parentNode.removeChild(this.dom.axis),t=!0),t},f.prototype.setItems=function(t){var e,i=this,s=this.itemsData;if(t){if(!(t instanceof o||t instanceof r))throw new TypeError("Data must be an instance of DataSet");this.itemsData=t}else this.itemsData=null;if(s&&(D.forEach(this.listeners,function(t,e){s.unsubscribe(e,t)}),e=s.getIds(),this._onRemove(e)),this.itemsData){var n=this.id;D.forEach(this.listeners,function(t,e){i.itemsData.subscribe(e,t,n)}),e=this.itemsData.getIds(),this._onAdd(e)}},f.prototype.getItems=function(){return this.itemsData},f.prototype._onUpdate=function(t){this._toQueue("update",t)},f.prototype._onAdd=function(t){this._toQueue("add",t)},f.prototype._onRemove=function(t){this._toQueue("remove",t)},f.prototype._toQueue=function(t,e){var i=this.queue;e.forEach(function(e){i[e]=t}),this.controller&&this.requestRepaint()},f.prototype._updateConversion=function(){var t=this.range;if(!t)throw Error("No range configured");this.conversion=t.conversion?t.conversion(this.width):h.conversion(t.start,t.end,this.width)},f.prototype.toTime=function(t){var e=this.conversion;return new Date(t/e.factor+e.offset)},f.prototype.toScreen=function(t){var e=this.conversion;return(t.valueOf()-e.offset)*e.factor},m.prototype.select=function(){this.selected=!0},m.prototype.unselect=function(){this.selected=!1},m.prototype.show=function(){return!1},m.prototype.hide=function(){return!1},m.prototype.repaint=function(){return!1},m.prototype.reflow=function(){return!1},g.prototype=new m(null,null),g.prototype.select=function(){this.selected=!0},g.prototype.unselect=function(){this.selected=!1},g.prototype.repaint=function(){var t=!1,e=this.dom;if(e||(this._create(),e=this.dom,t=!0),e){if(!this.parent)throw Error("Cannot repaint item: no parent attached");var i=this.parent.getForeground();if(!i)throw Error("Cannot repaint time axis: parent has no foreground container element");var s=this.parent.getBackground();if(!s)throw Error("Cannot repaint time axis: parent has no background container element");var n=this.parent.getAxis();if(!s)throw Error("Cannot repaint time axis: parent has no axis container element");if(e.box.parentNode||(i.appendChild(e.box),t=!0),e.line.parentNode||(s.appendChild(e.line),t=!0),e.dot.parentNode||(n.appendChild(e.dot),t=!0),this.data.content!=this.content){if(this.content=this.data.content,this.content instanceof Element)e.content.innerHTML="",e.content.appendChild(this.content);else{if(void 0==this.data.content)throw Error('Property "content" missing in item '+this.data.id);e.content.innerHTML=this.content}t=!0}var o=(this.data.className?" "+this.data.className:"")+(this.selected?" selected":"");this.className!=o&&(this.className=o,e.box.className="item box"+o,e.line.className="item line"+o,e.dot.className="item dot"+o,t=!0)}return t},g.prototype.show=function(){return this.dom&&this.dom.box.parentNode?!1:this.repaint()},g.prototype.hide=function(){var t=!1,e=this.dom;return e&&(e.box.parentNode&&(e.box.parentNode.removeChild(e.box),t=!0),e.line.parentNode&&e.line.parentNode.removeChild(e.line),e.dot.parentNode&&e.dot.parentNode.removeChild(e.dot)),t},g.prototype.reflow=function(){var t,e,i,s,n,o,r,a,h,d,l,p,c=0;if(void 0==this.data.start)throw Error('Property "start" missing in item '+this.data.id);if(l=this.data,p=this.parent&&this.parent.range,l&&p){var u=p.end-p.start;this.visible=l.start>p.start-u&&l.start0},g.prototype._create=function(){var t=this.dom;t||(this.dom=t={},t.box=document.createElement("DIV"),t.content=document.createElement("DIV"),t.content.className="content",t.box.appendChild(t.content),t.line=document.createElement("DIV"),t.line.className="line",t.dot=document.createElement("DIV"),t.dot.className="dot")},g.prototype.reposition=function(){var t=this.dom,e=this.props,i=this.options.orientation||this.defaultOptions.orientation;if(t){var s=t.box,n=t.line,o=t.dot;s.style.left=this.left+"px",s.style.top=this.top+"px",n.style.left=e.line.left+"px","top"==i?(n.style.top="0px",n.style.height=this.top+"px"):(n.style.top=this.top+this.height+"px",n.style.height=Math.max(this.parent.height-this.top-this.height+this.props.dot.height/2,0)+"px"),o.style.left=e.dot.left+"px",o.style.top=e.dot.top+"px"}},v.prototype=new m(null,null),v.prototype.select=function(){this.selected=!0},v.prototype.unselect=function(){this.selected=!1},v.prototype.repaint=function(){var t=!1,e=this.dom;if(e||(this._create(),e=this.dom,t=!0),e){if(!this.parent)throw Error("Cannot repaint item: no parent attached");var i=this.parent.getForeground();if(!i)throw Error("Cannot repaint time axis: parent has no foreground container element");if(e.point.parentNode||(i.appendChild(e.point),i.appendChild(e.point),t=!0),this.data.content!=this.content){if(this.content=this.data.content,this.content instanceof Element)e.content.innerHTML="",e.content.appendChild(this.content);else{if(void 0==this.data.content)throw Error('Property "content" missing in item '+this.data.id);e.content.innerHTML=this.content}t=!0}var s=(this.data.className?" "+this.data.className:"")+(this.selected?" selected":"");this.className!=s&&(this.className=s,e.point.className="item point"+s,t=!0)}return t},v.prototype.show=function(){return this.dom&&this.dom.point.parentNode?!1:this.repaint()},v.prototype.hide=function(){var t=!1,e=this.dom;return e&&e.point.parentNode&&(e.point.parentNode.removeChild(e.point),t=!0),t},v.prototype.reflow=function(){var t,e,i,s,n,o,r,a,h,d,l=0;if(void 0==this.data.start)throw Error('Property "start" missing in item '+this.data.id);if(h=this.data,d=this.parent&&this.parent.range,h&&d){var p=d.end-d.start;this.visible=h.start>d.start-p&&h.start0},v.prototype._create=function(){var t=this.dom;t||(this.dom=t={},t.point=document.createElement("div"),t.content=document.createElement("div"),t.content.className="content",t.point.appendChild(t.content),t.dot=document.createElement("div"),t.dot.className="dot",t.point.appendChild(t.dot))},v.prototype.reposition=function(){var t=this.dom,e=this.props;t&&(t.point.style.top=this.top+"px",t.point.style.left=this.left+"px",t.content.style.marginLeft=e.content.marginLeft+"px",t.dot.style.top=e.dot.top+"px")},y.prototype=new m(null,null),y.prototype.select=function(){this.selected=!0},y.prototype.unselect=function(){this.selected=!1},y.prototype.repaint=function(){var t=!1,e=this.dom;if(e||(this._create(),e=this.dom,t=!0),e){if(!this.parent)throw Error("Cannot repaint item: no parent attached");var i=this.parent.getForeground();if(!i)throw Error("Cannot repaint time axis: parent has no foreground container element");if(e.box.parentNode||(i.appendChild(e.box),t=!0),this.data.content!=this.content){if(this.content=this.data.content,this.content instanceof Element)e.content.innerHTML="",e.content.appendChild(this.content);else{if(void 0==this.data.content)throw Error('Property "content" missing in item '+this.data.id); -e.content.innerHTML=this.content}t=!0}var s=this.data.className?" "+this.data.className:"";this.className!=s&&(this.className=s,e.box.className="item range"+s,t=!0)}return t},y.prototype.show=function(){return this.dom&&this.dom.box.parentNode?!1:this.repaint()},y.prototype.hide=function(){var t=!1,e=this.dom;return e&&e.box.parentNode&&(e.box.parentNode.removeChild(e.box),t=!0),t},y.prototype.reflow=function(){var t,e,i,s,n,o,r,a,h,d,l,p,c,u,f,m,g=0;if(void 0==this.data.start)throw Error('Property "start" missing in item '+this.data.id);if(void 0==this.data.end)throw Error('Property "end" missing in item '+this.data.id);return h=this.data,d=this.parent&&this.parent.range,this.visible=h&&d?h.startd.start:!1,this.visible&&(t=this.dom,t?(e=this.props,i=this.options,o=this.parent,r=o.toScreen(this.data.start),a=o.toScreen(this.data.end),l=D.updateProperty,p=t.box,c=o.width,f=i.orientation||this.defaultOptions.orientation,s=i.margin&&i.margin.axis||this.defaultOptions.margin.axis,n=i.padding||this.defaultOptions.padding,g+=l(e.content,"width",t.content.offsetWidth),g+=l(this,"height",p.offsetHeight),-c>r&&(r=-c),a>2*c&&(a=2*c),u=0>r?Math.min(-r,a-r-e.content.width-2*n):0,g+=l(e.content,"left",u),"top"==f?(m=s,g+=l(this,"top",m)):(m=o.height-this.height-s,g+=l(this,"top",m)),g+=l(this,"left",r),g+=l(this,"width",Math.max(a-r,1))):g+=1),g>0},y.prototype._create=function(){var t=this.dom;t||(this.dom=t={},t.box=document.createElement("div"),t.content=document.createElement("div"),t.content.className="content",t.box.appendChild(t.content))},y.prototype.reposition=function(){var t=this.dom,e=this.props;t&&(t.box.style.top=this.top+"px",t.box.style.left=this.left+"px",t.box.style.width=this.width+"px",t.content.style.left=e.content.left+"px")},b.prototype=new l,b.prototype.setOptions=l.prototype.setOptions,b.prototype.getContainer=function(){return this.parent.getContainer()},b.prototype.setItems=function(t){if(this.itemset&&(this.itemset.hide(),this.itemset.setItems(),this.parent.controller.remove(this.itemset),this.itemset=null),t){var e=this.groupId,i=Object.create(this.options);this.itemset=new f(this,null,i),this.itemset.setRange(this.parent.range),this.view=new r(t,{filter:function(t){return t.group==e}}),this.itemset.setItems(this.view),this.parent.controller.add(this.itemset)}},b.prototype.repaint=function(){return!1},b.prototype.reflow=function(){var t=0,e=D.updateProperty;if(t+=e(this,"top",this.itemset?this.itemset.top:0),t+=e(this,"height",this.itemset?this.itemset.height:0),this.label){var i=this.label.firstChild;t+=e(this.props.label,"width",i.clientWidth),t+=e(this.props.label,"height",i.clientHeight)}else t+=e(this.props.label,"width",0),t+=e(this.props.label,"height",0);return t>0},w.prototype=new p,w.prototype.setOptions=l.prototype.setOptions,w.prototype.setRange=function(){},w.prototype.setItems=function(t){this.itemsData=t;for(var e in this.groups)if(this.groups.hasOwnProperty(e)){var i=this.groups[e];i.setItems(t)}},w.prototype.getItems=function(){return this.itemsData},w.prototype.setRange=function(t){this.range=t},w.prototype.setGroups=function(t){var e,i=this;if(this.groupsData&&(D.forEach(this.listeners,function(t,e){i.groupsData.unsubscribe(e,t)}),e=this.groupsData.getIds(),this._onRemove(e)),t?t instanceof o?this.groupsData=t:(this.groupsData=new o({convert:{start:"Date",end:"Date"}}),this.groupsData.add(t)):this.groupsData=null,this.groupsData){var s=this.id;D.forEach(this.listeners,function(t,e){i.groupsData.subscribe(e,t,s)}),e=this.groupsData.getIds(),this._onAdd(e)}},w.prototype.getGroups=function(){return this.groupsData},w.prototype.repaint=function(){var t,e,i,s,n=0,o=D.updateProperty,r=D.option.asSize,a=D.option.asElement,h=this.options,d=this.dom.frame,l=this.dom.labels;if(!this.parent)throw Error("Cannot repaint groupset: no parent attached");var p=this.parent.getContainer();if(!p)throw Error("Cannot repaint groupset: parent has no container element");if(!d){d=document.createElement("div"),d.className="groupset",this.dom.frame=d;var c=h.className;c&&D.addClassName(d,D.option.asString(c)),n+=1}d.parentNode||(p.appendChild(d),n+=1);var u=a(h.labelContainer);if(!u)throw Error('Cannot repaint groupset: option "labelContainer" not defined');l||(l=document.createElement("div"),l.className="labels",this.dom.labels=l),l.parentNode&&l.parentNode==u||(l.parentNode&&l.parentNode.removeChild(l.parentNode),u.appendChild(l)),n+=o(d.style,"height",r(h.height,this.height+"px")),n+=o(d.style,"top",r(h.top,"0px")),n+=o(d.style,"left",r(h.left,"0px")),n+=o(d.style,"width",r(h.width,"100%")),n+=o(l.style,"top",r(h.top,"0px"));var f=this,m=this.queue,g=this.groups,v=this.groupsData,y=Object.keys(m);if(y.length){y.forEach(function(t){var e=m[t],i=g[t];switch(e){case"add":case"update":if(!i){var s=Object.create(f.options);i=new b(f,t,s),i.setItems(f.itemsData),g[t]=i,f.controller.add(i)}i.data=v.get(t),delete m[t];break;case"remove":i&&(i.setItems(),delete g[t],f.controller.remove(i)),delete m[t];break;default:console.log('Error: unknown action "'+e+'"')}});var w=this.groupsData.getIds({order:this.options.groupsOrder});for(t=0;w.length>t;t++)(function(t,e){var i=0;e&&(i=function(){return e.top+e.height}),t.setOptions({top:i})})(g[w[t]],g[w[t-1]]);for(;l.firstChild;)l.removeChild(l.firstChild);for(t=0;w.length>t;t++)e=w[t],s=this._createLabel(e),l.appendChild(s);n++}for(e in g)g.hasOwnProperty(e)&&(i=g[e],s=i.label,s&&(s.style.top=i.top+"px",s.style.height=i.height+"px"));return n>0},w.prototype._createLabel=function(t){var e=this.groups[t],i=document.createElement("div");i.className="label";var s=document.createElement("div");s.className="inner",i.appendChild(s);var n=e.data&&e.data.content;n instanceof Element?s.appendChild(n):void 0!=n&&(s.innerHTML=n);var o=e.data&&e.data.className;return o&&D.addClassName(i,o),e.label=i,i},w.prototype.getContainer=function(){return this.dom.frame},w.prototype.getLabelsWidth=function(){return this.props.labels.width},w.prototype.reflow=function(){var t,e,i=0,s=this.options,n=D.updateProperty,o=D.option.asNumber,r=D.option.asSize,a=this.dom.frame;if(a){var h,d=o(s.maxHeight),l=null!=r(s.height);if(l)h=a.offsetHeight;else{h=0;for(t in this.groups)this.groups.hasOwnProperty(t)&&(e=this.groups[t],h+=e.height)}null!=d&&(h=Math.min(h,d)),i+=n(this,"height",h),i+=n(this,"top",a.offsetTop),i+=n(this,"left",a.offsetLeft),i+=n(this,"width",a.offsetWidth)}var p=0;for(t in this.groups)if(this.groups.hasOwnProperty(t)){e=this.groups[t];var c=e.props&&e.props.label&&e.props.label.width||0;p=Math.max(p,c)}return i+=n(this.props.labels,"width",p),i>0},w.prototype.hide=function(){return this.dom.frame&&this.dom.frame.parentNode?(this.dom.frame.parentNode.removeChild(this.dom.frame),!0):!1},w.prototype.show=function(){return this.dom.frame&&this.dom.frame.parentNode?!1:this.repaint()},w.prototype._onUpdate=function(t){this._toQueue(t,"update")},w.prototype._onAdd=function(t){this._toQueue(t,"add")},w.prototype._onRemove=function(t){this._toQueue(t,"remove")},w.prototype._toQueue=function(t,e){var i=this.queue;t.forEach(function(t){i[t]=e}),this.controller&&this.requestRepaint()},_.prototype.setOptions=function(t){t&&D.extend(this.options,t),this.controller.reflow(),this.controller.repaint()},_.prototype.setItems=function(t){var e,i=null==this.itemsData;if(t?t instanceof o&&(e=t):e=null,t instanceof o||(e=new o({convert:{start:"Date",end:"Date"}}),e.add(t)),this.itemsData=e,this.content.setItems(e),i&&(void 0==this.options.start||void 0==this.options.end)){var s=this.getItemRange(),n=s.min,r=s.max;if(null!=n&&null!=r){var a=r.valueOf()-n.valueOf();n=new Date(n.valueOf()-.05*a),r=new Date(r.valueOf()+.05*a)}void 0!=this.options.start&&(n=new Date(this.options.start.valueOf())),void 0!=this.options.end&&(r=new Date(this.options.end.valueOf())),(null!=n||null!=r)&&this.range.setRange(n,r)}},_.prototype.setGroups=function(t){var e=this;this.groupsData=t;var i=this.groupsData?w:f;if(!(this.content instanceof i)){this.content&&(this.content.hide(),this.content.setItems&&this.content.setItems(),this.content.setGroups&&this.content.setGroups(),this.controller.remove(this.content));var s=Object.create(this.options);D.extend(s,{top:function(){return"top"==e.options.orientation?e.timeaxis.height:e.itemPanel.height-e.timeaxis.height-e.content.height},left:null,width:"100%",height:function(){return e.options.height?e.itemPanel.height-e.timeaxis.height:null},maxHeight:function(){if(e.options.maxHeight){if(!D.isNumber(e.options.maxHeight))throw new TypeError("Number expected for property maxHeight");return e.options.maxHeight-e.timeaxis.height}return null},labelContainer:function(){return e.labelPanel.getContainer()}}),this.content=new i(this.itemPanel,[this.timeaxis],s),this.content.setRange&&this.content.setRange(this.range),this.content.setItems&&this.content.setItems(this.itemsData),this.content.setGroups&&this.content.setGroups(this.groupsData),this.controller.add(this.content)}},_.prototype.getItemRange=function(){var t=this.itemsData,e=null,i=null;if(t){var s=t.min("start");e=s?s.start.valueOf():null;var n=t.max("start");n&&(i=n.start.valueOf());var o=t.max("end");o&&(i=null==i?o.end.valueOf():Math.max(i,o.end.valueOf()))}return{min:null!=e?new Date(e):null,max:null!=i?new Date(i):null}},function(t){function e(t){return E=t,c()}function i(){D=0,C=E.charAt(0)}function s(){D++,C=E.charAt(D)}function n(){return E.charAt(D+1)}function o(t){return N.test(t)}function r(t,e){if(t||(t={}),e)for(var i in e)e.hasOwnProperty(i)&&(t[i]=e[i]);return t}function a(t,e,i){for(var s=e.split("."),n=t;s.length;){var o=s.shift();s.length?(n[o]||(n[o]={}),n=n[o]):n[o]=i}}function h(t,e){for(var i,s,n=null,o=[t],a=t;a.parent;)o.push(a.parent),a=a.parent;if(a.nodes)for(i=0,s=a.nodes.length;s>i;i++)if(e.id===a.nodes[i].id){n=a.nodes[i];break}for(n||(n={id:e.id},t.node&&(n.attr=r(n.attr,t.node))),i=o.length-1;i>=0;i--){var h=o[i];h.nodes||(h.nodes=[]),-1==h.nodes.indexOf(n)&&h.nodes.push(n)}e.attr&&(n.attr=r(n.attr,e.attr))}function d(t,e){if(t.edges||(t.edges=[]),t.edges.push(e),t.edge){var i=r({},t.edge);e.attr=r(i,e.attr)}}function l(t,e,i,s,n){var o={from:e,to:i,type:s};return t.edge&&(o.attr=r({},t.edge)),o.attr=r(o.attr||{},n),o}function p(){for(O=S.NULL,L="";" "==C||" "==C||"\n"==C||"\r"==C;)s();do{var t=!1;if("#"==C){for(var e=D-1;" "==E.charAt(e)||" "==E.charAt(e);)e--;if("\n"==E.charAt(e)||""==E.charAt(e)){for(;""!=C&&"\n"!=C;)s();t=!0}}if("/"==C&&"/"==n()){for(;""!=C&&"\n"!=C;)s();t=!0}if("/"==C&&"*"==n()){for(;""!=C;){if("*"==C&&"/"==n()){s(),s();break}s()}t=!0}for(;" "==C||" "==C||"\n"==C||"\r"==C;)s()}while(t);if(""==C)return O=S.DELIMITER,void 0;var i=C+n();if(M[i])return O=S.DELIMITER,L=i,s(),s(),void 0;if(M[C])return O=S.DELIMITER,L=C,s(),void 0;if(o(C)||"-"==C){for(L+=C,s();o(C);)L+=C,s();return"false"==L?L=!1:"true"==L?L=!0:isNaN(Number(L))||(L=Number(L)),O=S.IDENTIFIER,void 0}if('"'==C){for(s();""!=C&&('"'!=C||'"'==C&&'"'==n());)L+=C,'"'==C&&s(),s();if('"'!=C)throw w('End of string " expected');return s(),O=S.IDENTIFIER,void 0}for(O=S.UNKNOWN;""!=C;)L+=C,s();throw new SyntaxError('Syntax error in part "'+_(L,30)+'"')}function c(){var t={};if(i(),p(),"strict"==L&&(t.strict=!0,p()),("graph"==L||"digraph"==L)&&(t.type=L,p()),O==S.IDENTIFIER&&(t.id=L,p()),"{"!=L)throw w("Angle bracket { expected");if(p(),u(t),"}"!=L)throw w("Angle bracket } expected");if(p(),""!==L)throw w("End of file expected");return p(),delete t.node,delete t.edge,delete t.graph,t}function u(t){for(;""!==L&&"}"!=L;)f(t),";"==L&&p()}function f(t){var e=m(t);if(e)return y(t,e),void 0;var i=g(t);if(!i){if(O!=S.IDENTIFIER)throw w("Identifier expected");var s=L;if(p(),"="==L){if(p(),O!=S.IDENTIFIER)throw w("Identifier expected");t[s]=L,p()}else v(t,s)}}function m(t){var e=null;if("subgraph"==L&&(e={},e.type="subgraph",p(),O==S.IDENTIFIER&&(e.id=L,p())),"{"==L){if(p(),e||(e={}),e.parent=t,e.node=t.node,e.edge=t.edge,e.graph=t.graph,u(e),"}"!=L)throw w("Angle bracket } expected");p(),delete e.node,delete e.edge,delete e.graph,delete e.parent,t.subgraphs||(t.subgraphs=[]),t.subgraphs.push(e)}return e}function g(t){return"node"==L?(p(),t.node=b(),"node"):"edge"==L?(p(),t.edge=b(),"edge"):"graph"==L?(p(),t.graph=b(),"graph"):null}function v(t,e){var i={id:e},s=b();s&&(i.attr=s),h(t,i),y(t,e)}function y(t,e){for(;"->"==L||"--"==L;){var i,s=L;p();var n=m(t);if(n)i=n;else{if(O!=S.IDENTIFIER)throw w("Identifier or subgraph expected");i=L,h(t,{id:i}),p()}var o=b(),r=l(t,e,i,s,o);d(t,r),e=i}}function b(){for(var t=null;"["==L;){for(p(),t={};""!==L&&"]"!=L;){if(O!=S.IDENTIFIER)throw w("Attribute name expected");var e=L;if(p(),"="!=L)throw w("Equal sign = expected");if(p(),O!=S.IDENTIFIER)throw w("Attribute value expected");var i=L;a(t,e,i),p(),","==L&&p()}if("]"!=L)throw w("Bracket ] expected");p()}return t}function w(t){return new SyntaxError(t+', got "'+_(L,30)+'" (char '+D+")")}function _(t,e){return e>=t.length?t:t.substr(0,27)+"..."}function x(t,e,i){t instanceof Array?t.forEach(function(t){e instanceof Array?e.forEach(function(e){i(t,e)}):i(t,e)}):e instanceof Array?e.forEach(function(e){i(t,e)}):i(t,e)}function T(t){function i(t){var e={from:t.from,to:t.to};return r(e,t.attr),e.style="->"==t.type?"arrow":"line",e}var s=e(t),n={nodes:[],edges:[],options:{}};return s.nodes&&s.nodes.forEach(function(t){var e={id:t.id,label:(t.label||t.id)+""};r(e,t.attr),e.image&&(e.shape="image"),n.nodes.push(e)}),s.edges&&s.edges.forEach(function(t){var e,s;e=t.from instanceof Object?t.from.nodes:{id:t.from},s=t.to instanceof Object?t.to.nodes:{id:t.to},t.from instanceof Object&&t.from.edges&&t.from.edges.forEach(function(t){var e=i(t);n.edges.push(e)}),x(e,s,function(e,s){var o=l(n,e.id,s.id,t.type,t.attr),r=i(o);n.edges.push(r)}),t.to instanceof Object&&t.to.edges&&t.to.edges.forEach(function(t){var e=i(t);n.edges.push(e)})}),s.attr&&(n.options=s.attr),n}var S={NULL:0,DELIMITER:1,IDENTIFIER:2,UNKNOWN:3},M={"{":!0,"}":!0,"[":!0,"]":!0,";":!0,"=":!0,",":!0,"->":!0,"--":!0},E="",D=0,C="",L="",O=S.NULL,N=/[a-zA-Z_0-9.:#]/;t.parseDOT=e,t.DOTToGraph=T}(D!==void 0?D:s),"undefined"!=typeof CanvasRenderingContext2D&&(CanvasRenderingContext2D.prototype.circle=function(t,e,i){this.beginPath(),this.arc(t,e,i,0,2*Math.PI,!1)},CanvasRenderingContext2D.prototype.square=function(t,e,i){this.beginPath(),this.rect(t-i,e-i,2*i,2*i)},CanvasRenderingContext2D.prototype.triangle=function(t,e,i){this.beginPath();var s=2*i,n=s/2,o=Math.sqrt(3)/6*s,r=Math.sqrt(s*s-n*n);this.moveTo(t,e-(r-o)),this.lineTo(t+n,e+o),this.lineTo(t-n,e+o),this.lineTo(t,e-(r-o)),this.closePath()},CanvasRenderingContext2D.prototype.triangleDown=function(t,e,i){this.beginPath();var s=2*i,n=s/2,o=Math.sqrt(3)/6*s,r=Math.sqrt(s*s-n*n);this.moveTo(t,e+(r-o)),this.lineTo(t+n,e-o),this.lineTo(t-n,e-o),this.lineTo(t,e+(r-o)),this.closePath()},CanvasRenderingContext2D.prototype.star=function(t,e,i){this.beginPath();for(var s=0;10>s;s++){var n=0===s%2?1.3*i:.5*i;this.lineTo(t+n*Math.sin(2*s*Math.PI/10),e-n*Math.cos(2*s*Math.PI/10))}this.closePath()},CanvasRenderingContext2D.prototype.roundRect=function(t,e,i,s,n){var o=Math.PI/180;0>i-2*n&&(n=i/2),0>s-2*n&&(n=s/2),this.beginPath(),this.moveTo(t+n,e),this.lineTo(t+i-n,e),this.arc(t+i-n,e+n,n,270*o,360*o,!1),this.lineTo(t+i,e+s-n),this.arc(t+i-n,e+s-n,n,0,90*o,!1),this.lineTo(t+n,e+s),this.arc(t+n,e+s-n,n,90*o,180*o,!1),this.lineTo(t,e+n),this.arc(t+n,e+n,n,180*o,270*o,!1)},CanvasRenderingContext2D.prototype.ellipse=function(t,e,i,s){var n=.5522848,o=i/2*n,r=s/2*n,a=t+i,h=e+s,d=t+i/2,l=e+s/2;this.beginPath(),this.moveTo(t,l),this.bezierCurveTo(t,l-r,d-o,e,d,e),this.bezierCurveTo(d+o,e,a,l-r,a,l),this.bezierCurveTo(a,l+r,d+o,h,d,h),this.bezierCurveTo(d-o,h,t,l+r,t,l)},CanvasRenderingContext2D.prototype.database=function(t,e,i,s){var n=1/3,o=i,r=s*n,a=.5522848,h=o/2*a,d=r/2*a,l=t+o,p=e+r,c=t+o/2,u=e+r/2,f=e+(s-r/2),m=e+s;this.beginPath(),this.moveTo(l,u),this.bezierCurveTo(l,u+d,c+h,p,c,p),this.bezierCurveTo(c-h,p,t,u+d,t,u),this.bezierCurveTo(t,u-d,c-h,e,c,e),this.bezierCurveTo(c+h,e,l,u-d,l,u),this.lineTo(l,f),this.bezierCurveTo(l,f+d,c+h,m,c,m),this.bezierCurveTo(c-h,m,t,f+d,t,f),this.lineTo(t,u)},CanvasRenderingContext2D.prototype.arrow=function(t,e,i,s){var n=t-s*Math.cos(i),o=e-s*Math.sin(i),r=t-.9*s*Math.cos(i),a=e-.9*s*Math.sin(i),h=n+s/3*Math.cos(i+.5*Math.PI),d=o+s/3*Math.sin(i+.5*Math.PI),l=n+s/3*Math.cos(i-.5*Math.PI),p=o+s/3*Math.sin(i-.5*Math.PI);this.beginPath(),this.moveTo(t,e),this.lineTo(h,d),this.lineTo(r,a),this.lineTo(l,p),this.closePath()},CanvasRenderingContext2D.prototype.dashedLine=function(t,e,i,s,n){n||(n=[10,5]),0==c&&(c=.001);var o=n.length;this.moveTo(t,e);for(var r=i-t,a=s-e,h=a/r,d=Math.sqrt(r*r+a*a),l=0,p=!0;d>=.1;){var c=n[l++%o];c>d&&(c=d);var u=Math.sqrt(c*c/(1+h*h));0>r&&(u=-u),t+=u,e+=h*u,this[p?"lineTo":"moveTo"](t,e),d-=c,p=!p}}),x.prototype.attachEdge=function(t){-1==this.edges.indexOf(t)&&this.edges.push(t),this._updateMass()},x.prototype.detachEdge=function(t){var e=this.edges.indexOf(t);-1!=e&&this.edges.splice(e,1),this._updateMass()},x.prototype._updateMass=function(){this.mass=50+20*this.edges.length},x.prototype.setProperties=function(t,e){if(t){if(void 0!=t.id&&(this.id=t.id),void 0!=t.label&&(this.label=t.label),void 0!=t.title&&(this.title=t.title),void 0!=t.group&&(this.group=t.group),void 0!=t.x&&(this.x=t.x),void 0!=t.y&&(this.y=t.y),void 0!=t.value&&(this.value=t.value),void 0===this.id)throw"Node must have an id";if(this.group){var i=this.grouplist.get(this.group);for(var s in i)i.hasOwnProperty(s)&&(this[s]=i[s])}if(void 0!=t.shape&&(this.shape=t.shape),void 0!=t.image&&(this.image=t.image),void 0!=t.radius&&(this.radius=t.radius),void 0!=t.color&&(this.color=x.parseColor(t.color)),void 0!=t.fontColor&&(this.fontColor=t.fontColor),void 0!=t.fontSize&&(this.fontSize=t.fontSize),void 0!=t.fontFace&&(this.fontFace=t.fontFace),void 0!=this.image){if(!this.imagelist)throw"No imagelist provided";this.imageObj=this.imagelist.load(this.image)}switch(this.xFixed=this.xFixed||void 0!=t.x,this.yFixed=this.yFixed||void 0!=t.y,this.radiusFixed=this.radiusFixed||void 0!=t.radius,"image"==this.shape&&(this.radiusMin=e.nodes.widthMin,this.radiusMax=e.nodes.widthMax),this.shape){case"database":this.draw=this._drawDatabase,this.resize=this._resizeDatabase;break;case"box":this.draw=this._drawBox,this.resize=this._resizeBox;break;case"circle":this.draw=this._drawCircle,this.resize=this._resizeCircle;break;case"ellipse":this.draw=this._drawEllipse,this.resize=this._resizeEllipse;break;case"image":this.draw=this._drawImage,this.resize=this._resizeImage;break;case"text":this.draw=this._drawText,this.resize=this._resizeText;break;case"dot":this.draw=this._drawDot,this.resize=this._resizeShape;break;case"square":this.draw=this._drawSquare,this.resize=this._resizeShape;break;case"triangle":this.draw=this._drawTriangle,this.resize=this._resizeShape;break;case"triangleDown":this.draw=this._drawTriangleDown,this.resize=this._resizeShape;break;case"star":this.draw=this._drawStar,this.resize=this._resizeShape;break;default:this.draw=this._drawEllipse,this.resize=this._resizeEllipse}this._reset()}},x.parseColor=function(t){var e;return D.isString(t)?e={border:t,background:t,highlight:{border:t,background:t}}:(e={},e.background=t.background||"white",e.border=t.border||e.background,D.isString(t.highlight)?e.highlight={border:t.highlight,background:t.highlight}:(e.highlight={},e.highlight.background=t.highlight&&t.highlight.background||e.background,e.highlight.border=t.highlight&&t.highlight.border||e.border)),e},x.prototype.select=function(){this.selected=!0,this._reset()},x.prototype.unselect=function(){this.selected=!1,this._reset()},x.prototype._reset=function(){this.width=void 0,this.height=void 0},x.prototype.getTitle=function(){return this.title},x.prototype.distanceToBorder=function(t,e){var i=1;switch(this.width||this.resize(t),this.shape){case"circle":case"dot":return this.radius+i;case"ellipse":var s=this.width/2,n=this.height/2,o=Math.sin(e)*s,r=Math.cos(e)*n;return s*n/Math.sqrt(o*o+r*r);case"box":case"image":case"text":default:return this.width?Math.min(Math.abs(this.width/2/Math.cos(e)),Math.abs(this.height/2/Math.sin(e)))+i:0}},x.prototype._setForce=function(t,e){this.fx=t,this.fy=e},x.prototype._addForce=function(t,e){this.fx+=t,this.fy+=e},x.prototype.discreteStep=function(t){if(!this.xFixed){var e=-this.damping*this.vx,i=(this.fx+e)/this.mass;this.vx+=i/t,this.x+=this.vx/t}if(!this.yFixed){var s=-this.damping*this.vy,n=(this.fy+s)/this.mass;this.vy+=n/t,this.y+=this.vy/t}},x.prototype.isFixed=function(){return this.xFixed&&this.yFixed},x.prototype.isMoving=function(t){return Math.abs(this.vx)>t||Math.abs(this.vy)>t||!this.xFixed&&Math.abs(this.fx)>this.minForce||!this.yFixed&&Math.abs(this.fy)>this.minForce},x.prototype.isSelected=function(){return this.selected},x.prototype.getValue=function(){return this.value},x.prototype.getDistance=function(t,e){var i=this.x-t,s=this.y-e;return Math.sqrt(i*i+s*s)},x.prototype.setValueRange=function(t,e){if(!this.radiusFixed&&void 0!==this.value){var i=(this.radiusMax-this.radiusMin)/(e-t);this.radius=(this.value-t)*i+this.radiusMin}},x.prototype.draw=function(){throw"Draw method not initialized for node"},x.prototype.resize=function(){throw"Resize method not initialized for node"},x.prototype.isOverlappingWith=function(t){return this.leftt.left&&this.topt.top},x.prototype._resizeImage=function(){if(!this.width){var t,e;if(this.value){var i=this.imageObj.height/this.imageObj.width;t=this.radius||this.imageObj.width,e=this.radius*i||this.imageObj.height}else t=this.imageObj.width,e=this.imageObj.height;this.width=t,this.height=e}},x.prototype._drawImage=function(t){this._resizeImage(t),this.left=this.x-this.width/2,this.top=this.y-this.height/2;var e;this.imageObj?(t.drawImage(this.imageObj,this.left,this.top,this.width,this.height),e=this.y+this.height/2):e=this.y,this._label(t,this.label,this.x,e,void 0,"top")},x.prototype._resizeBox=function(t){if(!this.width){var e=5,i=this.getTextSize(t);this.width=i.width+2*e,this.height=i.height+2*e}},x.prototype._drawBox=function(t){this._resizeBox(t),this.left=this.x-this.width/2,this.top=this.y-this.height/2,t.strokeStyle=this.selected?this.color.highlight.border:this.color.border,t.fillStyle=this.selected?this.color.highlight.background:this.color.background,t.lineWidth=this.selected?2:1,t.roundRect(this.left,this.top,this.width,this.height,this.radius),t.fill(),t.stroke(),this._label(t,this.label,this.x,this.y)},x.prototype._resizeDatabase=function(t){if(!this.width){var e=5,i=this.getTextSize(t),s=i.width+2*e;this.width=s,this.height=s}},x.prototype._drawDatabase=function(t){this._resizeDatabase(t),this.left=this.x-this.width/2,this.top=this.y-this.height/2,t.strokeStyle=this.selected?this.color.highlight.border:this.color.border,t.fillStyle=this.selected?this.color.highlight.background:this.color.background,t.lineWidth=this.selected?2:1,t.database(this.x-this.width/2,this.y-.5*this.height,this.width,this.height),t.fill(),t.stroke(),this._label(t,this.label,this.x,this.y)},x.prototype._resizeCircle=function(t){if(!this.width){var e=5,i=this.getTextSize(t),s=Math.max(i.width,i.height)+2*e;this.radius=s/2,this.width=s,this.height=s}},x.prototype._drawCircle=function(t){this._resizeCircle(t),this.left=this.x-this.width/2,this.top=this.y-this.height/2,t.strokeStyle=this.selected?this.color.highlight.border:this.color.border,t.fillStyle=this.selected?this.color.highlight.background:this.color.background,t.lineWidth=this.selected?2:1,t.circle(this.x,this.y,this.radius),t.fill(),t.stroke(),this._label(t,this.label,this.x,this.y)},x.prototype._resizeEllipse=function(t){if(!this.width){var e=this.getTextSize(t);this.width=1.5*e.width,this.height=2*e.height,this.widthl;l++)t.fillText(r[l],i,d),d+=h}},x.prototype.getTextSize=function(t){if(void 0!=this.label){t.font=(this.selected?"bold ":"")+this.fontSize+"px "+this.fontFace;for(var e=this.label.split("\n"),i=(this.fontSize+4)*e.length,s=0,n=0,o=e.length;o>n;n++)s=Math.max(s,t.measureText(e[n]).width);return{width:s,height:i}}return{width:0,height:0}},T.prototype.setProperties=function(t,e){if(t)switch(void 0!=t.from&&(this.fromId=t.from),void 0!=t.to&&(this.toId=t.to),void 0!=t.id&&(this.id=t.id),void 0!=t.style&&(this.style=t.style),void 0!=t.label&&(this.label=t.label),this.label&&(this.fontSize=e.edges.fontSize,this.fontFace=e.edges.fontFace,this.fontColor=e.edges.fontColor,void 0!=t.fontColor&&(this.fontColor=t.fontColor),void 0!=t.fontSize&&(this.fontSize=t.fontSize),void 0!=t.fontFace&&(this.fontFace=t.fontFace)),void 0!=t.title&&(this.title=t.title),void 0!=t.width&&(this.width=t.width),void 0!=t.value&&(this.value=t.value),void 0!=t.length&&(this.length=t.length),t.dash&&(void 0!=t.dash.length&&(this.dash.length=t.dash.length),void 0!=t.dash.gap&&(this.dash.gap=t.dash.gap),void 0!=t.dash.altLength&&(this.dash.altLength=t.dash.altLength)),void 0!=t.color&&(this.color=t.color),this.connect(),this.widthFixed=this.widthFixed||void 0!=t.width,this.lengthFixed=this.lengthFixed||void 0!=t.length,this.stiffness=1/this.length,this.style){case"line":this.draw=this._drawLine;break;case"arrow":this.draw=this._drawArrow;break;case"arrow-center":this.draw=this._drawArrowCenter;break;case"dash-line":this.draw=this._drawDashLine;break;default:this.draw=this._drawLine}},T.prototype.connect=function(){this.disconnect(),this.from=this.graph.nodes[this.fromId]||null,this.to=this.graph.nodes[this.toId]||null,this.connected=this.from&&this.to,this.connected?(this.from.attachEdge(this),this.to.attachEdge(this)):(this.from&&this.from.detachEdge(this),this.to&&this.to.detachEdge(this))},T.prototype.disconnect=function(){this.from&&(this.from.detachEdge(this),this.from=null),this.to&&(this.to.detachEdge(this),this.to=null),this.connected=!1},T.prototype.getTitle=function(){return this.title},T.prototype.getValue=function(){return this.value},T.prototype.setValueRange=function(t,e){if(!this.widthFixed&&void 0!==this.value){var i=(this.widthMax-this.widthMin)/(e-t);this.width=(this.value-t)*i+this.widthMin}},T.prototype.draw=function(){throw"Method draw not initialized in edge"},T.prototype.isOverlappingWith=function(t){var e=10,i=this.from.x,s=this.from.y,n=this.to.x,o=this.to.y,r=t.left,a=t.top,h=T._dist(i,s,n,o,r,a);return e>h},T.prototype._drawLine=function(t){t.strokeStyle=this.color,t.lineWidth=this._getLineWidth();var e;if(this.from!=this.to)this._line(t),this.label&&(e=this._pointOnLine(.5),this._label(t,this.label,e.x,e.y));else{var i,s,n=this.length/4,o=this.from;o.width||o.resize(t),o.width>o.height?(i=o.x+o.width/2,s=o.y-n):(i=o.x+n,s=o.y-o.height/2),this._circle(t,i,s,n),e=this._pointOnCircle(i,s,n,.5),this._label(t,this.label,e.x,e.y)}},T.prototype._getLineWidth=function(){return this.from.selected||this.to.selected?Math.min(2*this.width,this.widthMax):this.width},T.prototype._line=function(t){t.beginPath(),t.moveTo(this.from.x,this.from.y),t.lineTo(this.to.x,this.to.y),t.stroke()},T.prototype._circle=function(t,e,i,s){t.beginPath(),t.arc(e,i,s,0,2*Math.PI,!1),t.stroke()},T.prototype._label=function(t,e,i,s){if(e){t.font=(this.from.selected||this.to.selected?"bold ":"")+this.fontSize+"px "+this.fontFace,t.fillStyle="white";var n=t.measureText(e).width,o=this.fontSize,r=i-n/2,a=s-o/2;t.fillRect(r,a,n,o),t.fillStyle=this.fontColor||"black",t.textAlign="left",t.textBaseline="top",t.fillText(e,r,a)}},T.prototype._drawDashLine=function(t){if(t.strokeStyle=this.color,t.lineWidth=this._getLineWidth(),t.beginPath(),t.lineCap="round",void 0!=this.dash.altLength?t.dashedLine(this.from.x,this.from.y,this.to.x,this.to.y,[this.dash.length,this.dash.gap,this.dash.altLength,this.dash.gap]):void 0!=this.dash.length&&void 0!=this.dash.gap?t.dashedLine(this.from.x,this.from.y,this.to.x,this.to.y,[this.dash.length,this.dash.gap]):(t.moveTo(this.from.x,this.from.y),t.lineTo(this.to.x,this.to.y)),t.stroke(),this.label){var e=this._pointOnLine(.5);this._label(t,this.label,e.x,e.y)}},T.prototype._pointOnLine=function(t){return{x:(1-t)*this.from.x+t*this.to.x,y:(1-t)*this.from.y+t*this.to.y}},T.prototype._pointOnCircle=function(t,e,i,s){var n=2*(s-3/8)*Math.PI;return{x:t+i*Math.cos(n),y:e-i*Math.sin(n)}},T.prototype._drawArrowCenter=function(t){var e;if(t.strokeStyle=this.color,t.fillStyle=this.color,t.lineWidth=this._getLineWidth(),this.from!=this.to){this._line(t);var i=Math.atan2(this.to.y-this.from.y,this.to.x-this.from.x),s=10+5*this.width;e=this._pointOnLine(.5),t.arrow(e.x,e.y,i,s),t.fill(),t.stroke(),this.label&&(e=this._pointOnLine(.5),this._label(t,this.label,e.x,e.y))}else{var n,o,r=this.length/4,a=this.from;a.width||a.resize(t),a.width>a.height?(n=a.x+a.width/2,o=a.y-r):(n=a.x+r,o=a.y-a.height/2),this._circle(t,n,o,r);var i=.2*Math.PI,s=10+5*this.width;e=this._pointOnCircle(n,o,r,.5),t.arrow(e.x,e.y,i,s),t.fill(),t.stroke(),this.label&&(e=this._pointOnCircle(n,o,r,.5),this._label(t,this.label,e.x,e.y))}},T.prototype._drawArrow=function(t){t.strokeStyle=this.color,t.fillStyle=this.color,t.lineWidth=this._getLineWidth();var e,i;if(this.from!=this.to){e=Math.atan2(this.to.y-this.from.y,this.to.x-this.from.x);var s=this.to.x-this.from.x,n=this.to.y-this.from.y,o=Math.sqrt(s*s+n*n),r=this.from.distanceToBorder(t,e+Math.PI),a=(o-r)/o,h=a*this.from.x+(1-a)*this.to.x,d=a*this.from.y+(1-a)*this.to.y,l=this.to.distanceToBorder(t,e),p=(o-l)/o,c=(1-p)*this.from.x+p*this.to.x,u=(1-p)*this.from.y+p*this.to.y;if(t.beginPath(),t.moveTo(h,d),t.lineTo(c,u),t.stroke(),i=10+5*this.width,t.arrow(c,u,e,i),t.fill(),t.stroke(),this.label){var f=this._pointOnLine(.5);this._label(t,this.label,f.x,f.y)}}else{var m,g,v,y=this.from,b=this.length/4;y.width||y.resize(t),y.width>y.height?(m=y.x+y.width/2,g=y.y-b,v={x:m,y:y.y,angle:.9*Math.PI}):(m=y.x+b,g=y.y-y.height/2,v={x:y.x,y:g,angle:.6*Math.PI}),t.beginPath(),t.arc(m,g,b,0,2*Math.PI,!1),t.stroke(),i=10+5*this.width,t.arrow(v.x,v.y,v.angle,i),t.fill(),t.stroke(),this.label&&(f=this._pointOnCircle(m,g,b,.5),this._label(t,this.label,f.x,f.y))}},T._dist=function(t,e,i,s,n,o){var r=i-t,a=s-e,h=r*r+a*a,d=((n-t)*r+(o-e)*a)/h; -d>1?d=1:0>d&&(d=0);var l=t+d*r,p=e+d*a,c=l-n,u=p-o;return Math.sqrt(c*c+u*u)},S.prototype.setPosition=function(t,e){this.x=parseInt(t),this.y=parseInt(e)},S.prototype.setText=function(t){this.frame.innerHTML=t},S.prototype.show=function(t){if(void 0===t&&(t=!0),t){var e=this.frame.clientHeight,i=this.frame.clientWidth,s=this.frame.parentNode.clientHeight,n=this.frame.parentNode.clientWidth,o=this.y-e;o+e+this.padding>s&&(o=s-e-this.padding),this.padding>o&&(o=this.padding);var r=this.x;r+i+this.padding>n&&(r=n-i-this.padding),this.padding>r&&(r=this.padding),this.frame.style.left=r+"px",this.frame.style.top=o+"px",this.frame.style.visibility="visible"}else this.hide()},S.prototype.hide=function(){this.frame.style.visibility="hidden"},Groups=function(){this.clear(),this.defaultIndex=0},Groups.DEFAULT=[{border:"#2B7CE9",background:"#97C2FC",highlight:{border:"#2B7CE9",background:"#D2E5FF"}},{border:"#FFA500",background:"#FFFF00",highlight:{border:"#FFA500",background:"#FFFFA3"}},{border:"#FA0A10",background:"#FB7E81",highlight:{border:"#FA0A10",background:"#FFAFB1"}},{border:"#41A906",background:"#7BE141",highlight:{border:"#41A906",background:"#A1EC76"}},{border:"#E129F0",background:"#EB7DF4",highlight:{border:"#E129F0",background:"#F0B3F5"}},{border:"#7C29F0",background:"#AD85E4",highlight:{border:"#7C29F0",background:"#D3BDF0"}},{border:"#C37F00",background:"#FFA807",highlight:{border:"#C37F00",background:"#FFCA66"}},{border:"#4220FB",background:"#6E6EFD",highlight:{border:"#4220FB",background:"#9B9BFD"}},{border:"#FD5A77",background:"#FFC0CB",highlight:{border:"#FD5A77",background:"#FFD1D9"}},{border:"#4AD63A",background:"#C2FABC",highlight:{border:"#4AD63A",background:"#E6FFE3"}}],Groups.prototype.clear=function(){this.groups={},this.groups.length=function(){var t=0;for(var e in this)this.hasOwnProperty(e)&&t++;return t}},Groups.prototype.get=function(t){var e=this.groups[t];if(void 0==e){var i=this.defaultIndex%Groups.DEFAULT.length;this.defaultIndex++,e={},e.color=Groups.DEFAULT[i],this.groups[t]=e}return e},Groups.prototype.add=function(t,e){return this.groups[t]=e,e.color&&(e.color=x.parseColor(e.color)),e},Images=function(){this.images={},this.callback=void 0},Images.prototype.setOnloadCallback=function(t){this.callback=t},Images.prototype.load=function(t){var e=this.images[t];if(void 0==e){var i=this;e=new Image,this.images[t]=e,e.onload=function(){i.callback&&i.callback(this)},e.src=t}return e},M.prototype.setData=function(t){if(t&&t.dot&&(t.nodes||t.edges))throw new SyntaxError('Data must contain either parameter "dot" or parameter pair "nodes" and "edges", but not both.');if(this.setOptions(t&&t.options),t&&t.dot){if(t&&t.dot){var e=N.util.DOTToGraph(t.dot);return this.setData(e),void 0}}else this._setNodes(t&&t.nodes),this._setEdges(t&&t.edges);this.stabilize&&this._doStabilize(),this.start()},M.prototype.setOptions=function(t){if(t){if(void 0!=t.width&&(this.width=t.width),void 0!=t.height&&(this.height=t.height),void 0!=t.stabilize&&(this.stabilize=t.stabilize),void 0!=t.selectable&&(this.selectable=t.selectable),t.edges){for(var e in t.edges)t.edges.hasOwnProperty(e)&&(this.constants.edges[e]=t.edges[e]);void 0!=t.edges.length&&t.nodes&&void 0==t.nodes.distance&&(this.constants.edges.length=t.edges.length,this.constants.nodes.distance=1.25*t.edges.length),t.edges.fontColor||(this.constants.edges.fontColor=t.edges.color),t.edges.dash&&(void 0!=t.edges.dash.length&&(this.constants.edges.dash.length=t.edges.dash.length),void 0!=t.edges.dash.gap&&(this.constants.edges.dash.gap=t.edges.dash.gap),void 0!=t.edges.dash.altLength&&(this.constants.edges.dash.altLength=t.edges.dash.altLength))}if(t.nodes){for(e in t.nodes)t.nodes.hasOwnProperty(e)&&(this.constants.nodes[e]=t.nodes[e]);t.nodes.color&&(this.constants.nodes.color=x.parseColor(t.nodes.color))}if(t.groups)for(var i in t.groups)if(t.groups.hasOwnProperty(i)){var s=t.groups[i];this.groups.add(i,s)}}this.setSize(this.width,this.height),this._setTranslation(this.frame.clientWidth/2,this.frame.clientHeight/2),this._setScale(1)},M.prototype._trigger=function(t,e){O.trigger(this,t,e)},M.prototype._create=function(){for(;this.containerElement.hasChildNodes();)this.containerElement.removeChild(this.containerElement.firstChild);if(this.frame=document.createElement("div"),this.frame.className="graph-frame",this.frame.style.position="relative",this.frame.style.overflow="hidden",this.frame.canvas=document.createElement("canvas"),this.frame.canvas.style.position="relative",this.frame.appendChild(this.frame.canvas),!this.frame.canvas.getContext){var t=document.createElement("DIV");t.style.color="red",t.style.fontWeight="bold",t.style.padding="10px",t.innerHTML="Error: your browser does not support HTML canvas",this.frame.canvas.appendChild(t)}var e=this,i=function(t){e._onMouseDown(t)},s=function(t){e._onMouseMoveTitle(t)},n=function(t){e._onMouseWheel(t)},o=function(t){e._onTouchStart(t)};N.util.addEventListener(this.frame.canvas,"mousedown",i),N.util.addEventListener(this.frame.canvas,"mousemove",s),N.util.addEventListener(this.frame.canvas,"mousewheel",n),N.util.addEventListener(this.frame.canvas,"touchstart",o),this.containerElement.appendChild(this.frame)},M.prototype._onMouseDown=function(t){if(t=t||window.event,this.selectable&&(this.leftButtonDown&&this._onMouseUp(t),this.leftButtonDown=t.which?1==t.which:1==t.button,this.leftButtonDown||this.touchDown)){var e=this;this.onmousemove||(this.onmousemove=function(t){e._onMouseMove(t)},N.util.addEventListener(document,"mousemove",e.onmousemove)),this.onmouseup||(this.onmouseup=function(t){e._onMouseUp(t)},N.util.addEventListener(document,"mouseup",e.onmouseup)),N.util.preventDefault(t),this.startMouseX=D.getPageX(t),this.startMouseY=D.getPageY(t),this.startFrameLeft=N.util.getAbsoluteLeft(this.frame.canvas),this.startFrameTop=N.util.getAbsoluteTop(this.frame.canvas),this.startTranslation=this._getTranslation(),this.ctrlKeyDown=t.ctrlKey,this.shiftKeyDown=t.shiftKey;var i={left:this._xToCanvas(this.startMouseX-this.startFrameLeft),top:this._yToCanvas(this.startMouseY-this.startFrameTop),right:this._xToCanvas(this.startMouseX-this.startFrameLeft),bottom:this._yToCanvas(this.startMouseY-this.startFrameTop)},s=this._getNodesOverlappingWith(i);if(this.startClickedObj=s.length>0?s[s.length-1]:void 0,this.startClickedObj){var n=this.nodes[this.startClickedObj];this.startClickedObj.xFixed=n.xFixed,this.startClickedObj.yFixed=n.yFixed,n.xFixed=!0,n.yFixed=!0,this.ctrlKeyDown&&n.isSelected()?this._unselectNodes([this.startClickedObj]):this._selectNodes([this.startClickedObj],this.ctrlKeyDown),this.moving||this._redraw()}else this.shiftKeyDown||(this.moved=!1)}},M.prototype._onMouseMove=function(t){if(t=t||window.event,this.selectable){var e=D.getPageX(t),i=D.getPageY(t);if(this.mouseX=e,this.mouseY=i,this.startClickedObj){var s=this.nodes[this.startClickedObj];this.startClickedObj.xFixed||(s.x=this._xToCanvas(e-this.startFrameLeft)),this.startClickedObj.yFixed||(s.y=this._yToCanvas(i-this.startFrameTop)),this.moving||(this.moving=!0,this.start())}else if(this.shiftKeyDown){void 0==this.frame.selRect&&(this.frame.selRect=document.createElement("DIV"),this.frame.appendChild(this.frame.selRect),this.frame.selRect.style.position="absolute",this.frame.selRect.style.border="1px dashed red");var n=Math.min(this.startMouseX,e)-this.startFrameLeft,o=Math.min(this.startMouseY,i)-this.startFrameTop,r=Math.max(this.startMouseX,e)-this.startFrameLeft,a=Math.max(this.startMouseY,i)-this.startFrameTop;this.frame.selRect.style.left=n+"px",this.frame.selRect.style.top=o+"px",this.frame.selRect.style.width=r-n+"px",this.frame.selRect.style.height=a-o+"px"}else{var h=e-this.startMouseX,d=i-this.startMouseY;this._setTranslation(this.startTranslation.x+h,this.startTranslation.y+d),this._redraw(),this.moved=!0}N.util.preventDefault(t)}},M.prototype._onMouseUp=function(t){if(t=t||window.event,this.selectable){this.onmousemove&&(N.util.removeEventListener(document,"mousemove",this.onmousemove),this.onmousemove=void 0),this.onmouseup&&(N.util.removeEventListener(document,"mouseup",this.onmouseup),this.onmouseup=void 0),N.util.preventDefault(t);var e=D.getPageX(t)||this.mouseX||0,i=D.getPageY(t)||this.mouseY||0,s=t?t.ctrlKey:window.event.ctrlKey;if(this.startClickedObj){var n=this.nodes[this.startClickedObj];n.xFixed=this.startClickedObj.xFixed,n.yFixed=this.startClickedObj.yFixed}else if(this.shiftKeyDown){var o={left:this._xToCanvas(Math.min(this.startMouseX,e)-this.startFrameLeft),top:this._yToCanvas(Math.min(this.startMouseY,i)-this.startFrameTop),right:this._xToCanvas(Math.max(this.startMouseX,e)-this.startFrameLeft),bottom:this._yToCanvas(Math.max(this.startMouseY,i)-this.startFrameTop)},r=this._getNodesOverlappingWith(o);this._selectNodes(r,s),this.redraw(),this.frame.selRect&&(this.frame.removeChild(this.frame.selRect),this.frame.selRect=void 0)}else this.ctrlKeyDown||this.moved||(this._unselectNodes(),this._redraw());this.leftButtonDown=!1,this.ctrlKeyDown=!1}},M.prototype._onMouseWheel=function(t){t=t||window.event;var e=D.getPageX(t),i=D.getPageY(t),s=0;if(t.wheelDelta?s=t.wheelDelta/120:t.detail&&(s=-t.detail/3),s){var n=s/10;0>s&&(n/=1-n);var o=this._getScale(),r=o*(1+n);.01>r&&(r=.01),r>10&&(r=10);var a=N.util.getAbsoluteLeft(this.frame.canvas),h=N.util.getAbsoluteTop(this.frame.canvas),d=e-a,l=i-h,p=this._getTranslation(),c=r/o,u=(1-c)*d+p.x*c,f=(1-c)*l+p.y*c;this._setScale(r),this._setTranslation(u,f),this._redraw()}N.util.preventDefault(t)},M.prototype._onMouseMoveTitle=function(t){t=t||window.event;var e=D.getPageX(t),i=D.getPageY(t);this.startFrameLeft=this.startFrameLeft||N.util.getAbsoluteLeft(this.frame.canvas),this.startFrameTop=this.startFrameTop||N.util.getAbsoluteTop(this.frame.canvas);var s=e-this.startFrameLeft,n=i-this.startFrameTop;this.popupNode&&this._checkHidePopup(s,n);var o=this,r=function(){o._checkShowPopup(s,n)};this.popupTimer&&clearInterval(this.popupTimer),this.leftButtonDown||(this.popupTimer=setTimeout(r,300))},M.prototype._checkShowPopup=function(t,e){var i,s={left:this._xToCanvas(t),top:this._yToCanvas(e),right:this._xToCanvas(t),bottom:this._yToCanvas(e)},n=this.popupNode;if(void 0==this.popupNode){var o=this.nodes;for(i in o)if(o.hasOwnProperty(i)){var r=o[i];if(void 0!=r.getTitle()&&r.isOverlappingWith(s)){this.popupNode=r;break}}}if(void 0==this.popupNode){var a=this.edges;for(i in a)if(a.hasOwnProperty(i)){var h=a[i];if(h.connected&&void 0!=h.getTitle()&&h.isOverlappingWith(s)){this.popupNode=h;break}}}if(this.popupNode){if(this.popupNode!=n){var d=this;d.popup||(d.popup=new S(d.frame)),d.popup.setPosition(t-3,e-3),d.popup.setText(d.popupNode.getTitle()),d.popup.show()}}else this.popup&&this.popup.hide()},M.prototype._checkHidePopup=function(t,e){var i={left:t,top:e,right:t,bottom:e};this.popupNode&&this.popupNode.isOverlappingWith(i)||(this.popupNode=void 0,this.popup&&this.popup.hide())},M.prototype._onTouchStart=function(t){if(N.util.preventDefault(t),!this.touchDown){this.touchDown=!0;var e=this;this.ontouchmove||(this.ontouchmove=function(t){e._onTouchMove(t)},N.util.addEventListener(document,"touchmove",this.ontouchmove)),this.ontouchend||(this.ontouchend=function(t){e._onTouchEnd(t)},N.util.addEventListener(document,"touchend",this.ontouchend)),this._onMouseDown(t)}},M.prototype._onTouchMove=function(t){N.util.preventDefault(t),this._onMouseMove(t)},M.prototype._onTouchEnd=function(t){N.util.preventDefault(t),this.touchDown=!1,this.ontouchmove&&(N.util.removeEventListener(document,"touchmove",this.ontouchmove),this.ontouchmove=void 0),this.ontouchend&&(N.util.removeEventListener(document,"touchend",this.ontouchend),this.ontouchend=void 0),this._onMouseUp(t)},M.prototype._unselectNodes=function(t,e){var i,s,n,o=!1;if(t)for(i=0,s=t.length;s>i;i++){n=t[i],this.nodes[n].unselect();for(var r=0;this.selection.length>r;)this.selection[r]==n?(this.selection.splice(r,1),o=!0):r++}else if(this.selection&&this.selection.length){for(i=0,s=this.selection.length;s>i;i++)n=this.selection[i],this.nodes[n].unselect(),o=!0;this.selection=[]}return!o||1!=e&&void 0!=e||this._trigger("select"),o},M.prototype._selectNodes=function(t,e){var i,s,n=!1,o=!0;if(t.length!=this.selection.length)o=!1;else for(i=0,s=Math.min(t.length,this.selection.length);s>i;i++)if(t[i]!=this.selection[i]){o=!1;break}if(o)return n;if(void 0==e||0==e){var r=!1;n=this._unselectNodes(void 0,r)}for(i=0,s=t.length;s>i;i++){var a=t[i],h=-1!=this.selection.indexOf(a);h||(this.nodes[a].select(),this.selection.push(a),n=!0)}return n&&this._trigger("select"),n},M.prototype._getNodesOverlappingWith=function(t){var e=this.nodes,i=[];for(var s in e)e.hasOwnProperty(s)&&e[s].isOverlappingWith(t)&&i.push(s);return i},M.prototype.getSelection=function(){return this.selection.concat([])},M.prototype.setSelection=function(t){var e,i,s;if(void 0==t.length)throw"Selection must be an array with ids";for(e=0,i=this.selection.length;i>e;e++)s=this.selection[e],this.nodes[s].unselect();for(this.selection=[],e=0,i=t.length;i>e;e++){s=t[e];var n=this.nodes[s];if(!n)throw new RangeError('Node with id "'+s+'" not found');n.select(),this.selection.push(s)}this.redraw()},M.prototype._updateSelection=function(){for(var t=0;this.selection.length>t;){var e=this.selection[t];this.nodes[e]?t++:this.selection.splice(t,1)}},M.prototype._getConnectionCount=function(t){function e(t){for(var e=[],i=0,s=t.length;s>i;i++)for(var n=t[i],o=n.edges,r=0,a=o.length;a>r;r++){var h=o[r],d=null;h.from==n?d=h.to:h.to==n&&(d=h.from);var l,p;if(d)for(l=0,p=t.length;p>l;l++)if(t[l]==d){d=null;break}if(d)for(l=0,p=e.length;p>l;l++)if(e[l]==d){d=null;break}d&&e.push(d)}return e}void 0==t&&(t=1);var i=[],s=this.nodes;for(var n in s)if(s.hasOwnProperty(n)){for(var o=[s[n]],r=0;t>r;r++)o=o.concat(e(o));i.push(o)}for(var a=[],h=0,d=i.length;d>h;h++)a.push(i[h].length);return a},M.prototype.setSize=function(t,e){this.frame.style.width=t,this.frame.style.height=e,this.frame.canvas.style.width="100%",this.frame.canvas.style.height="100%",this.frame.canvas.width=this.frame.canvas.clientWidth,this.frame.canvas.height=this.frame.canvas.clientHeight},M.prototype._setNodes=function(t){var e=this.nodesData;if(t instanceof o||t instanceof r)this.nodesData=t;else if(t instanceof Array)this.nodesData=new o,this.nodesData.add(t);else{if(t)throw new TypeError("Array or DataSet expected");this.nodesData=new o}if(e&&D.forEach(this.nodesListeners,function(t,i){e.unsubscribe(i,t)}),this.nodes={},this.nodesData){var i=this;D.forEach(this.nodesListeners,function(t,e){i.nodesData.subscribe(e,t)});var s=this.nodesData.getIds();this._addNodes(s)}this._updateSelection()},M.prototype._addNodes=function(t){for(var e,i=0,s=t.length;s>i;i++){e=t[i];var n=this.nodesData.get(e),o=new x(n,this.images,this.groups,this.constants);if(this.nodes[e]=o,!o.isFixed()){var r=2*this.constants.edges.length,a=t.length,h=2*Math.PI*(i/a);o.x=r*Math.cos(h),o.y=r*Math.sin(h),this.moving=!0}}this._reconnectEdges(),this._updateValueRange(this.nodes)},M.prototype._updateNodes=function(t){for(var e=this.nodes,i=this.nodesData,s=0,n=t.length;n>s;s++){var o=t[s],r=e[o],a=i.get(o);r?r.setProperties(a,this.constants):(r=new x(properties,this.images,this.groups,this.constants),e[o]=r,r.isFixed()||(this.moving=!0))}this._reconnectEdges(),this._updateValueRange(e)},M.prototype._removeNodes=function(t){for(var e=this.nodes,i=0,s=t.length;s>i;i++){var n=t[i];delete e[n]}this._reconnectEdges(),this._updateSelection(),this._updateValueRange(e)},M.prototype._setEdges=function(t){var e=this.edgesData;if(t instanceof o||t instanceof r)this.edgesData=t;else if(t instanceof Array)this.edgesData=new o,this.edgesData.add(t);else{if(t)throw new TypeError("Array or DataSet expected");this.edgesData=new o}if(e&&D.forEach(this.edgesListeners,function(t,i){e.unsubscribe(i,t)}),this.edges={},this.edgesData){var i=this;D.forEach(this.edgesListeners,function(t,e){i.edgesData.subscribe(e,t)});var s=this.edgesData.getIds();this._addEdges(s)}this._reconnectEdges()},M.prototype._addEdges=function(t){for(var e=this.edges,i=this.edgesData,s=0,n=t.length;n>s;s++){var o=t[s],r=e[o];r&&r.disconnect();var a=i.get(o);e[o]=new T(a,this,this.constants)}this.moving=!0,this._updateValueRange(e)},M.prototype._updateEdges=function(t){for(var e=this.edges,i=this.edgesData,s=0,n=t.length;n>s;s++){var o=t[s],r=i.get(o),a=e[o];a?(a.disconnect(),a.setProperties(r,this.constants),a.connect()):(a=new T(r,this,this.constants),this.edges[o]=a)}this.moving=!0,this._updateValueRange(e)},M.prototype._removeEdges=function(t){for(var e=this.edges,i=0,s=t.length;s>i;i++){var n=t[i],o=e[n];o&&(o.disconnect(),delete e[n])}this.moving=!0,this._updateValueRange(e)},M.prototype._reconnectEdges=function(){var t,e=this.nodes,i=this.edges;for(t in e)e.hasOwnProperty(t)&&(e[t].edges=[]);for(t in i)if(i.hasOwnProperty(t)){var s=i[t];s.from=null,s.to=null,s.connect()}},M.prototype._updateValueRange=function(t){var e,i=void 0,s=void 0;for(e in t)if(t.hasOwnProperty(e)){var n=t[e].getValue();void 0!==n&&(i=void 0===i?n:Math.min(n,i),s=void 0===s?n:Math.max(n,s))}if(void 0!==i&&void 0!==s)for(e in t)t.hasOwnProperty(e)&&t[e].setValueRange(i,s)},M.prototype.redraw=function(){this.setSize(this.width,this.height),this._redraw()},M.prototype._redraw=function(){var t=this.frame.canvas.getContext("2d"),e=this.frame.canvas.width,i=this.frame.canvas.height;t.clearRect(0,0,e,i),t.save(),t.translate(this.translation.x,this.translation.y),t.scale(this.scale,this.scale),this._drawEdges(t),this._drawNodes(t),t.restore()},M.prototype._setTranslation=function(t,e){void 0===this.translation&&(this.translation={x:0,y:0}),void 0!==t&&(this.translation.x=t),void 0!==e&&(this.translation.y=e)},M.prototype._getTranslation=function(){return{x:this.translation.x,y:this.translation.y}},M.prototype._setScale=function(t){this.scale=t},M.prototype._getScale=function(){return this.scale},M.prototype._xToCanvas=function(t){return(t-this.translation.x)/this.scale},M.prototype._canvasToX=function(t){return t*this.scale+this.translation.x},M.prototype._yToCanvas=function(t){return(t-this.translation.y)/this.scale},M.prototype._canvasToY=function(t){return t*this.scale+this.translation.y},M.prototype._drawNodes=function(t){var e=this.nodes,i=[];for(var s in e)e.hasOwnProperty(s)&&(e[s].isSelected()?i.push(s):e[s].draw(t));for(var n=0,o=i.length;o>n;n++)e[i[n]].draw(t)},M.prototype._drawEdges=function(t){var e=this.edges;for(var i in e)if(e.hasOwnProperty(i)){var s=e[i];s.connected&&e[i].draw(t)}},M.prototype._doStabilize=function(){new Date;for(var t=0,e=this.constants.minVelocity,i=!1;!i&&this.constants.maxIterations>t;)this._calculateForces(),this._discreteStepNodes(),i=!this._isMoving(e),t++;new Date},M.prototype._calculateForces=function(){var t,e,i,s,n,o,r,a,h,d,l,p=this.nodes,c=this.edges,u=.01,f=this.frame.canvas.clientWidth/2,m=this.frame.canvas.clientHeight/2;for(t in p)if(p.hasOwnProperty(t)){var g=p[t];e=f-g.x,i=m-g.y,s=Math.atan2(i,e),o=Math.cos(s)*u,r=Math.sin(s)*u,g._setForce(o,r)}var v=this.constants.nodes.distance,y=10;for(var b in p)if(p.hasOwnProperty(b)){var w=p[b];for(var _ in p)if(p.hasOwnProperty(_)){var x=p[_];e=x.x-w.x,i=x.y-w.y,n=Math.sqrt(e*e+i*i),s=Math.atan2(i,e),a=1/(1+Math.exp((n/v-1)*y)),o=Math.cos(s)*a,r=Math.sin(s)*a,w._addForce(-o,-r),x._addForce(o,r)}}for(t in c)if(c.hasOwnProperty(t)){var T=c[t];T.connected&&(e=T.to.x-T.from.x,i=T.to.y-T.from.y,l=T.length,d=Math.sqrt(e*e+i*i),s=Math.atan2(i,e),h=T.stiffness*(l-d),o=Math.cos(s)*h,r=Math.sin(s)*h,T.from._addForce(-o,-r),T.to._addForce(o,r))}},M.prototype._isMoving=function(t){var e=this.nodes;for(var i in e)if(e.hasOwnProperty(i)&&e[i].isMoving(t))return!0;return!1},M.prototype._discreteStepNodes=function(){var t=this.refreshRate/1e3,e=this.nodes;for(var i in e)e.hasOwnProperty(i)&&e[i].discreteStep(t)},M.prototype.start=function(){if(this.moving){this._calculateForces(),this._discreteStepNodes();var t=this.constants.minVelocity;this.moving=this._isMoving(t)}if(this.moving){if(!this.timer){var e=this;this.timer=window.setTimeout(function(){e.timer=void 0,e.start(),e._redraw()},this.refreshRate)}}else this._redraw()},M.prototype.stop=function(){this.timer&&(window.clearInterval(this.timer),this.timer=void 0)};var N={util:D,events:O,Controller:d,DataSet:o,DataView:r,Range:h,Stack:a,TimeStep:TimeStep,EventBus:n,components:{items:{Item:m,ItemBox:g,ItemPoint:v,ItemRange:y},Component:l,Panel:p,RootPanel:c,ItemSet:f,TimeAxis:u},graph:{Node:x,Edge:T,Popup:S,Groups:Groups,Images:Images},Timeline:_,Graph:M};s!==void 0&&(s=N),i!==void 0&&i.exports!==void 0&&(i.exports=N),"function"==typeof t&&t(function(){return N}),"undefined"!=typeof window&&(window.vis=N),D.loadCss("/* vis.js stylesheet */\n.vis.timeline {\n}\n\n\n.vis.timeline.rootpanel {\n position: relative;\n overflow: hidden;\n\n border: 1px solid #bfbfbf;\n -moz-box-sizing: border-box;\n box-sizing: border-box;\n}\n\n.vis.timeline .panel {\n position: absolute;\n overflow: hidden;\n}\n\n\n.vis.timeline .groupset {\n position: absolute;\n padding: 0;\n margin: 0;\n}\n\n.vis.timeline .labels {\n position: absolute;\n top: 0;\n left: 0;\n width: 100%;\n height: 100%;\n\n padding: 0;\n margin: 0;\n\n border-right: 1px solid #bfbfbf;\n box-sizing: border-box;\n -moz-box-sizing: border-box;\n}\n\n.vis.timeline .labels .label {\n position: absolute;\n left: 0;\n top: 0;\n width: 100%;\n border-bottom: 1px solid #bfbfbf;\n color: #4d4d4d;\n}\n\n.vis.timeline .labels .label .inner {\n display: inline-block;\n padding: 5px;\n}\n\n\n.vis.timeline .itemset {\n position: absolute;\n padding: 0;\n margin: 0;\n overflow: hidden;\n}\n\n.vis.timeline .background {\n}\n\n.vis.timeline .foreground {\n}\n\n.vis.timeline .itemset-axis {\n position: absolute;\n}\n\n.vis.timeline .groupset .itemset-axis {\n border-top: 1px solid #bfbfbf;\n}\n\n/* TODO: with orientation=='bottom', this will more or less overlap with timeline axis\n.vis.timeline .groupset .itemset-axis:last-child {\n border-top: none;\n}\n*/\n\n\n.vis.timeline .item {\n position: absolute;\n color: #1A1A1A;\n border-color: #97B0F8;\n background-color: #D5DDF6;\n display: inline-block;\n}\n\n.vis.timeline .item.selected {\n border-color: #FFC200;\n background-color: #FFF785;\n z-index: 999;\n}\n\n.vis.timeline .item.cluster {\n /* TODO: use another color or pattern? */\n background: #97B0F8 url('img/cluster_bg.png');\n color: white;\n}\n.vis.timeline .item.cluster.point {\n border-color: #D5DDF6;\n}\n\n.vis.timeline .item.box {\n text-align: center;\n border-style: solid;\n border-width: 1px;\n border-radius: 5px;\n -moz-border-radius: 5px; /* For Firefox 3.6 and older */\n}\n\n.vis.timeline .item.point {\n background: none;\n}\n\n.vis.timeline .dot {\n border: 5px solid #97B0F8;\n position: absolute;\n border-radius: 5px;\n -moz-border-radius: 5px; /* For Firefox 3.6 and older */\n}\n\n.vis.timeline .item.range {\n overflow: hidden;\n border-style: solid;\n border-width: 1px;\n border-radius: 2px;\n -moz-border-radius: 2px; /* For Firefox 3.6 and older */\n}\n\n.vis.timeline .item.range .drag-left {\n cursor: w-resize;\n z-index: 1000;\n}\n\n.vis.timeline .item.range .drag-right {\n cursor: e-resize;\n z-index: 1000;\n}\n\n.vis.timeline .item.range .content {\n position: relative;\n display: inline-block;\n}\n\n.vis.timeline .item.line {\n position: absolute;\n width: 0;\n border-left-width: 1px;\n border-left-style: solid;\n}\n\n.vis.timeline .item .content {\n margin: 5px;\n white-space: nowrap;\n overflow: hidden;\n}\n\n.vis.timeline .axis {\n position: relative;\n}\n\n.vis.timeline .axis .text {\n position: absolute;\n color: #4d4d4d;\n padding: 3px;\n white-space: nowrap;\n}\n\n.vis.timeline .axis .text.measure {\n position: absolute;\n padding-left: 0;\n padding-right: 0;\n margin-left: 0;\n margin-right: 0;\n visibility: hidden;\n}\n\n.vis.timeline .axis .grid.vertical {\n position: absolute;\n width: 0;\n border-right: 1px solid;\n}\n\n.vis.timeline .axis .grid.horizontal {\n position: absolute;\n left: 0;\n width: 100%;\n height: 0;\n border-bottom: 1px solid;\n}\n\n.vis.timeline .axis .grid.minor {\n border-color: #e5e5e5;\n}\n\n.vis.timeline .axis .grid.major {\n border-color: #bfbfbf;\n}\n\n")})()},{moment:2}],2:[function(e,i){(function(){(function(s){function n(t,e){return function(i){return p(t.call(this,i),e)}}function o(t){return function(e){return this.lang().ordinal(t.call(this,e))}}function r(){}function a(t){d(this,t)}function h(t){var e=this._data={},i=t.years||t.year||t.y||0,s=t.months||t.month||t.M||0,n=t.weeks||t.week||t.w||0,o=t.days||t.day||t.d||0,r=t.hours||t.hour||t.h||0,a=t.minutes||t.minute||t.m||0,h=t.seconds||t.second||t.s||0,d=t.milliseconds||t.millisecond||t.ms||0;this._milliseconds=d+1e3*h+6e4*a+36e5*r,this._days=o+7*n,this._months=s+12*i,e.milliseconds=d%1e3,h+=l(d/1e3),e.seconds=h%60,a+=l(h/60),e.minutes=a%60,r+=l(a/60),e.hours=r%24,o+=l(r/24),o+=7*n,e.days=o%30,s+=l(o/30),e.months=s%12,i+=l(s/12),e.years=i}function d(t,e){for(var i in e)e.hasOwnProperty(i)&&(t[i]=e[i]);return t}function l(t){return 0>t?Math.ceil(t):Math.floor(t)}function p(t,e){for(var i=t+"";e>i.length;)i="0"+i;return i}function c(t,e,i){var s,n=e._milliseconds,o=e._days,r=e._months;n&&t._d.setTime(+t+n*i),o&&t.date(t.date()+o*i),r&&(s=t.date(),t.date(1).month(t.month()+r*i).date(Math.min(s,t.daysInMonth())))}function u(t){return"[object Array]"===Object.prototype.toString.call(t)}function f(t,e){var i,s=Math.min(t.length,e.length),n=Math.abs(t.length-e.length),o=0;for(i=0;s>i;i++)~~t[i]!==~~e[i]&&o++;return o+n}function m(t,e){return e.abbr=t,z[t]||(z[t]=new r),z[t].set(e),z[t]}function g(t){return t?(!z[t]&&R&&e("./lang/"+t),z[t]):I.fn._lang}function v(t){return t.match(/\[.*\]/)?t.replace(/^\[|\]$/g,""):t.replace(/\\/g,"")}function y(t){var e,i,s=t.match(j);for(e=0,i=s.length;i>e;e++)s[e]=ae[s[e]]?ae[s[e]]:v(s[e]);return function(n){var o="";for(e=0;i>e;e++)o+="function"==typeof s[e].call?s[e].call(n,t):s[e];return o}}function b(t,e){function i(e){return t.lang().longDateFormat(e)||e}for(var s=5;s--&&U.test(e);)e=e.replace(U,i);return ne[e]||(ne[e]=y(e)),ne[e](t)}function w(t){switch(t){case"DDDD":return q;case"YYYY":return V;case"YYYYY":return X;case"S":case"SS":case"SSS":case"DDD":return B;case"MMM":case"MMMM":case"dd":case"ddd":case"dddd":case"a":case"A":return K;case"X":return J;case"Z":case"ZZ":return G;case"T":return Z;case"MM":case"DD":case"YY":case"HH":case"hh":case"mm":case"ss":case"M":case"D":case"d":case"H":case"h":case"m":case"s":return W;default:return RegExp(t.replace("\\",""))}}function _(t,e,i){var s,n=i._a;switch(t){case"M":case"MM":n[1]=null==e?0:~~e-1;break;case"MMM":case"MMMM":s=g(i._l).monthsParse(e),null!=s?n[1]=s:i._isValid=!1;break;case"D":case"DD":case"DDD":case"DDDD":null!=e&&(n[2]=~~e);break;case"YY":n[0]=~~e+(~~e>68?1900:2e3);break;case"YYYY":case"YYYYY":n[0]=~~e;break;case"a":case"A":i._isPm="pm"===(e+"").toLowerCase();break;case"H":case"HH":case"h":case"hh":n[3]=~~e;break;case"m":case"mm":n[4]=~~e;break;case"s":case"ss":n[5]=~~e;break;case"S":case"SS":case"SSS":n[6]=~~(1e3*("0."+e));break;case"X":i._d=new Date(1e3*parseFloat(e));break;case"Z":case"ZZ":i._useUTC=!0,s=(e+"").match(ee),s&&s[1]&&(i._tzh=~~s[1]),s&&s[2]&&(i._tzm=~~s[2]),s&&"+"===s[0]&&(i._tzh=-i._tzh,i._tzm=-i._tzm)}null==e&&(i._isValid=!1)}function x(t){var e,i,s=[];if(!t._d){for(e=0;7>e;e++)t._a[e]=s[e]=null==t._a[e]?2===e?1:0:t._a[e];s[3]+=t._tzh||0,s[4]+=t._tzm||0,i=new Date(0),t._useUTC?(i.setUTCFullYear(s[0],s[1],s[2]),i.setUTCHours(s[3],s[4],s[5],s[6])):(i.setFullYear(s[0],s[1],s[2]),i.setHours(s[3],s[4],s[5],s[6])),t._d=i}}function T(t){var e,i,s=t._f.match(j),n=t._i;for(t._a=[],e=0;s.length>e;e++)i=(w(s[e]).exec(n)||[])[0],i&&(n=n.slice(n.indexOf(i)+i.length)),ae[s[e]]&&_(s[e],i,t);t._isPm&&12>t._a[3]&&(t._a[3]+=12),t._isPm===!1&&12===t._a[3]&&(t._a[3]=0),x(t)}function S(t){for(var e,i,s,n,o=99;t._f.length;){if(e=d({},t),e._f=t._f.pop(),T(e),i=new a(e),i.isValid()){s=i;break}n=f(e._a,i.toArray()),o>n&&(o=n,s=i)}d(t,s)}function M(t){var e,i=t._i;if(Q.exec(i)){for(t._f="YYYY-MM-DDT",e=0;4>e;e++)if(te[e][1].exec(i)){t._f+=te[e][0];break}G.exec(i)&&(t._f+=" Z"),T(t)}else t._d=new Date(i)}function E(t){var e=t._i,i=H.exec(e);e===s?t._d=new Date:i?t._d=new Date(+i[1]):"string"==typeof e?M(t):u(e)?(t._a=e.slice(0),x(t)):t._d=e instanceof Date?new Date(+e):new Date(e)}function D(t,e,i,s,n){return n.relativeTime(e||1,!!i,t,s)}function C(t,e,i){var s=Y(Math.abs(t)/1e3),n=Y(s/60),o=Y(n/60),r=Y(o/24),a=Y(r/365),h=45>s&&["s",s]||1===n&&["m"]||45>n&&["mm",n]||1===o&&["h"]||22>o&&["hh",o]||1===r&&["d"]||25>=r&&["dd",r]||45>=r&&["M"]||345>r&&["MM",Y(r/30)]||1===a&&["y"]||["yy",a];return h[2]=e,h[3]=t>0,h[4]=i,D.apply({},h)}function L(t,e,i){var s=i-e,n=i-t.day();return n>s&&(n-=7),s-7>n&&(n+=7),Math.ceil(I(t).add("d",n).dayOfYear()/7)}function O(t){var e=t._i,i=t._f;return null===e||""===e?null:("string"==typeof e&&(t._i=e=g().preparse(e)),I.isMoment(e)?(t=d({},e),t._d=new Date(+e._d)):i?u(i)?S(t):T(t):E(t),new a(t))}function N(t,e){I.fn[t]=I.fn[t+"s"]=function(t){var i=this._isUTC?"UTC":"";return null!=t?(this._d["set"+i+e](t),this):this._d["get"+i+e]()}}function A(t){I.duration.fn[t]=function(){return this._data[t]}}function k(t,e){I.duration.fn["as"+t]=function(){return+this/e}}for(var I,F,P="2.0.0",Y=Math.round,z={},R=i!==s&&i.exports,H=/^\/?Date\((\-?\d+)/i,j=/(\[[^\[]*\])|(\\)?(Mo|MM?M?M?|Do|DDDo|DD?D?D?|ddd?d?|do?|w[o|w]?|W[o|W]?|YYYYY|YYYY|YY|a|A|hh?|HH?|mm?|ss?|SS?S?|X|zz?|ZZ?|.)/g,U=/(\[[^\[]*\])|(\\)?(LT|LL?L?L?|l{1,4})/g,W=/\d\d?/,B=/\d{1,3}/,q=/\d{3}/,V=/\d{1,4}/,X=/[+\-]?\d{1,6}/,K=/[0-9]*[a-z\u00A0-\u05FF\u0700-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF]+|[\u0600-\u06FF]+\s*?[\u0600-\u06FF]+/i,G=/Z|[\+\-]\d\d:?\d\d/i,Z=/T/i,J=/[\+\-]?\d+(\.\d{1,3})?/,Q=/^\s*\d{4}-\d\d-\d\d((T| )(\d\d(:\d\d(:\d\d(\.\d\d?\d?)?)?)?)?([\+\-]\d\d:?\d\d)?)?/,$="YYYY-MM-DDTHH:mm:ssZ",te=[["HH:mm:ss.S",/(T| )\d\d:\d\d:\d\d\.\d{1,3}/],["HH:mm:ss",/(T| )\d\d:\d\d:\d\d/],["HH:mm",/(T| )\d\d:\d\d/],["HH",/(T| )\d\d/]],ee=/([\+\-]|\d\d)/gi,ie="Month|Date|Hours|Minutes|Seconds|Milliseconds".split("|"),se={Milliseconds:1,Seconds:1e3,Minutes:6e4,Hours:36e5,Days:864e5,Months:2592e6,Years:31536e6},ne={},oe="DDD w W M D d".split(" "),re="M D H h m s w W".split(" "),ae={M:function(){return this.month()+1},MMM:function(t){return this.lang().monthsShort(this,t)},MMMM:function(t){return this.lang().months(this,t)},D:function(){return this.date()},DDD:function(){return this.dayOfYear()},d:function(){return this.day()},dd:function(t){return this.lang().weekdaysMin(this,t)},ddd:function(t){return this.lang().weekdaysShort(this,t)},dddd:function(t){return this.lang().weekdays(this,t)},w:function(){return this.week()},W:function(){return this.isoWeek()},YY:function(){return p(this.year()%100,2)},YYYY:function(){return p(this.year(),4)},YYYYY:function(){return p(this.year(),5)},a:function(){return this.lang().meridiem(this.hours(),this.minutes(),!0)},A:function(){return this.lang().meridiem(this.hours(),this.minutes(),!1)},H:function(){return this.hours()},h:function(){return this.hours()%12||12},m:function(){return this.minutes()},s:function(){return this.seconds()},S:function(){return~~(this.milliseconds()/100)},SS:function(){return p(~~(this.milliseconds()/10),2)},SSS:function(){return p(this.milliseconds(),3)},Z:function(){var t=-this.zone(),e="+";return 0>t&&(t=-t,e="-"),e+p(~~(t/60),2)+":"+p(~~t%60,2)},ZZ:function(){var t=-this.zone(),e="+";return 0>t&&(t=-t,e="-"),e+p(~~(10*t/6),4)},X:function(){return this.unix()}};oe.length;)F=oe.pop(),ae[F+"o"]=o(ae[F]);for(;re.length;)F=re.pop(),ae[F+F]=n(ae[F],2);for(ae.DDDD=n(ae.DDD,3),r.prototype={set:function(t){var e,i;for(i in t)e=t[i],"function"==typeof e?this[i]=e:this["_"+i]=e -},_months:"January_February_March_April_May_June_July_August_September_October_November_December".split("_"),months:function(t){return this._months[t.month()]},_monthsShort:"Jan_Feb_Mar_Apr_May_Jun_Jul_Aug_Sep_Oct_Nov_Dec".split("_"),monthsShort:function(t){return this._monthsShort[t.month()]},monthsParse:function(t){var e,i,s;for(this._monthsParse||(this._monthsParse=[]),e=0;12>e;e++)if(this._monthsParse[e]||(i=I([2e3,e]),s="^"+this.months(i,"")+"|^"+this.monthsShort(i,""),this._monthsParse[e]=RegExp(s.replace(".",""),"i")),this._monthsParse[e].test(t))return e},_weekdays:"Sunday_Monday_Tuesday_Wednesday_Thursday_Friday_Saturday".split("_"),weekdays:function(t){return this._weekdays[t.day()]},_weekdaysShort:"Sun_Mon_Tue_Wed_Thu_Fri_Sat".split("_"),weekdaysShort:function(t){return this._weekdaysShort[t.day()]},_weekdaysMin:"Su_Mo_Tu_We_Th_Fr_Sa".split("_"),weekdaysMin:function(t){return this._weekdaysMin[t.day()]},_longDateFormat:{LT:"h:mm A",L:"MM/DD/YYYY",LL:"MMMM D YYYY",LLL:"MMMM D YYYY LT",LLLL:"dddd, MMMM D YYYY LT"},longDateFormat:function(t){var e=this._longDateFormat[t];return!e&&this._longDateFormat[t.toUpperCase()]&&(e=this._longDateFormat[t.toUpperCase()].replace(/MMMM|MM|DD|dddd/g,function(t){return t.slice(1)}),this._longDateFormat[t]=e),e},meridiem:function(t,e,i){return t>11?i?"pm":"PM":i?"am":"AM"},_calendar:{sameDay:"[Today at] LT",nextDay:"[Tomorrow at] LT",nextWeek:"dddd [at] LT",lastDay:"[Yesterday at] LT",lastWeek:"[last] dddd [at] LT",sameElse:"L"},calendar:function(t,e){var i=this._calendar[t];return"function"==typeof i?i.apply(e):i},_relativeTime:{future:"in %s",past:"%s ago",s:"a few seconds",m:"a minute",mm:"%d minutes",h:"an hour",hh:"%d hours",d:"a day",dd:"%d days",M:"a month",MM:"%d months",y:"a year",yy:"%d years"},relativeTime:function(t,e,i,s){var n=this._relativeTime[i];return"function"==typeof n?n(t,e,i,s):n.replace(/%d/i,t)},pastFuture:function(t,e){var i=this._relativeTime[t>0?"future":"past"];return"function"==typeof i?i(e):i.replace(/%s/i,e)},ordinal:function(t){return this._ordinal.replace("%d",t)},_ordinal:"%d",preparse:function(t){return t},postformat:function(t){return t},week:function(t){return L(t,this._week.dow,this._week.doy)},_week:{dow:0,doy:6}},I=function(t,e,i){return O({_i:t,_f:e,_l:i,_isUTC:!1})},I.utc=function(t,e,i){return O({_useUTC:!0,_isUTC:!0,_l:i,_i:t,_f:e})},I.unix=function(t){return I(1e3*t)},I.duration=function(t,e){var i,s=I.isDuration(t),n="number"==typeof t,o=s?t._data:n?{}:t;return n&&(e?o[e]=t:o.milliseconds=t),i=new h(o),s&&t.hasOwnProperty("_lang")&&(i._lang=t._lang),i},I.version=P,I.defaultFormat=$,I.lang=function(t,e){return t?(e?m(t,e):z[t]||g(t),I.duration.fn._lang=I.fn._lang=g(t),s):I.fn._lang._abbr},I.langData=function(t){return t&&t._lang&&t._lang._abbr&&(t=t._lang._abbr),g(t)},I.isMoment=function(t){return t instanceof a},I.isDuration=function(t){return t instanceof h},I.fn=a.prototype={clone:function(){return I(this)},valueOf:function(){return+this._d},unix:function(){return Math.floor(+this._d/1e3)},toString:function(){return this.format("ddd MMM DD YYYY HH:mm:ss [GMT]ZZ")},toDate:function(){return this._d},toJSON:function(){return I.utc(this).format("YYYY-MM-DD[T]HH:mm:ss.SSS[Z]")},toArray:function(){var t=this;return[t.year(),t.month(),t.date(),t.hours(),t.minutes(),t.seconds(),t.milliseconds()]},isValid:function(){return null==this._isValid&&(this._isValid=this._a?!f(this._a,(this._isUTC?I.utc(this._a):I(this._a)).toArray()):!isNaN(this._d.getTime())),!!this._isValid},utc:function(){return this._isUTC=!0,this},local:function(){return this._isUTC=!1,this},format:function(t){var e=b(this,t||I.defaultFormat);return this.lang().postformat(e)},add:function(t,e){var i;return i="string"==typeof t?I.duration(+e,t):I.duration(t,e),c(this,i,1),this},subtract:function(t,e){var i;return i="string"==typeof t?I.duration(+e,t):I.duration(t,e),c(this,i,-1),this},diff:function(t,e,i){var s,n,o=this._isUTC?I(t).utc():I(t).local(),r=6e4*(this.zone()-o.zone());return e&&(e=e.replace(/s$/,"")),"year"===e||"month"===e?(s=432e5*(this.daysInMonth()+o.daysInMonth()),n=12*(this.year()-o.year())+(this.month()-o.month()),n+=(this-I(this).startOf("month")-(o-I(o).startOf("month")))/s,"year"===e&&(n/=12)):(s=this-o-r,n="second"===e?s/1e3:"minute"===e?s/6e4:"hour"===e?s/36e5:"day"===e?s/864e5:"week"===e?s/6048e5:s),i?n:l(n)},from:function(t,e){return I.duration(this.diff(t)).lang(this.lang()._abbr).humanize(!e)},fromNow:function(t){return this.from(I(),t)},calendar:function(){var t=this.diff(I().startOf("day"),"days",!0),e=-6>t?"sameElse":-1>t?"lastWeek":0>t?"lastDay":1>t?"sameDay":2>t?"nextDay":7>t?"nextWeek":"sameElse";return this.format(this.lang().calendar(e,this))},isLeapYear:function(){var t=this.year();return 0===t%4&&0!==t%100||0===t%400},isDST:function(){return this.zone()+I(t).startOf(e)},isBefore:function(t,e){return e=e!==s?e:"millisecond",+this.clone().startOf(e)<+I(t).startOf(e)},isSame:function(t,e){return e=e!==s?e:"millisecond",+this.clone().startOf(e)===+I(t).startOf(e)},zone:function(){return this._isUTC?0:this._d.getTimezoneOffset()},daysInMonth:function(){return I.utc([this.year(),this.month()+1,0]).date()},dayOfYear:function(t){var e=Y((I(this).startOf("day")-I(this).startOf("year"))/864e5)+1;return null==t?e:this.add("d",t-e)},isoWeek:function(t){var e=L(this,1,4);return null==t?e:this.add("d",7*(t-e))},week:function(t){var e=this.lang().week(this);return null==t?e:this.add("d",7*(t-e))},lang:function(t){return t===s?this._lang:(this._lang=g(t),this)}},F=0;ie.length>F;F++)N(ie[F].toLowerCase().replace(/s$/,""),ie[F]);N("year","FullYear"),I.fn.days=I.fn.day,I.fn.weeks=I.fn.week,I.fn.isoWeeks=I.fn.isoWeek,I.duration.fn=h.prototype={weeks:function(){return l(this.days()/7)},valueOf:function(){return this._milliseconds+864e5*this._days+2592e6*this._months},humanize:function(t){var e=+this,i=C(e,!t,this.lang());return t&&(i=this.lang().pastFuture(e,i)),this.lang().postformat(i)},lang:I.fn.lang};for(F in se)se.hasOwnProperty(F)&&(k(F,se[F]),A(F.toLowerCase()));k("Weeks",6048e5),I.lang("en",{ordinal:function(t){var e=t%10,i=1===~~(t%100/10)?"th":1===e?"st":2===e?"nd":3===e?"rd":"th";return t+i}}),R&&(i.exports=I),"undefined"==typeof ender&&(this.moment=I),"function"==typeof t&&t.amd&&t("moment",[],function(){return I})}).call(this)})()},{}]},{},[1])(1)}); \ No newline at end of file +e.content.innerHTML=this.content}t=!0}var s=this.data.className?" "+this.data.className:"";this.className!=s&&(this.className=s,e.box.className="item range"+s,t=!0)}return t},y.prototype.show=function(){return this.dom&&this.dom.box.parentNode?!1:this.repaint()},y.prototype.hide=function(){var t=!1,e=this.dom;return e&&e.box.parentNode&&(e.box.parentNode.removeChild(e.box),t=!0),t},y.prototype.reflow=function(){var t,e,i,s,n,o,r,a,h,d,l,p,c,u,f,m,g=0;if(void 0==this.data.start)throw Error('Property "start" missing in item '+this.data.id);if(void 0==this.data.end)throw Error('Property "end" missing in item '+this.data.id);return h=this.data,d=this.parent&&this.parent.range,this.visible=h&&d?h.startd.start:!1,this.visible&&(t=this.dom,t?(e=this.props,i=this.options,o=this.parent,r=o.toScreen(this.data.start),a=o.toScreen(this.data.end),l=D.updateProperty,p=t.box,c=o.width,f=i.orientation||this.defaultOptions.orientation,s=i.margin&&i.margin.axis||this.defaultOptions.margin.axis,n=i.padding||this.defaultOptions.padding,g+=l(e.content,"width",t.content.offsetWidth),g+=l(this,"height",p.offsetHeight),-c>r&&(r=-c),a>2*c&&(a=2*c),u=0>r?Math.min(-r,a-r-e.content.width-2*n):0,g+=l(e.content,"left",u),"top"==f?(m=s,g+=l(this,"top",m)):(m=o.height-this.height-s,g+=l(this,"top",m)),g+=l(this,"left",r),g+=l(this,"width",Math.max(a-r,1))):g+=1),g>0},y.prototype._create=function(){var t=this.dom;t||(this.dom=t={},t.box=document.createElement("div"),t.content=document.createElement("div"),t.content.className="content",t.box.appendChild(t.content))},y.prototype.reposition=function(){var t=this.dom,e=this.props;t&&(t.box.style.top=this.top+"px",t.box.style.left=this.left+"px",t.box.style.width=this.width+"px",t.content.style.left=e.content.left+"px")},b.prototype=new l,b.prototype.setOptions=l.prototype.setOptions,b.prototype.getContainer=function(){return this.parent.getContainer()},b.prototype.setItems=function(t){if(this.itemset&&(this.itemset.hide(),this.itemset.setItems(),this.parent.controller.remove(this.itemset),this.itemset=null),t){var e=this.groupId,i=Object.create(this.options);this.itemset=new f(this,null,i),this.itemset.setRange(this.parent.range),this.view=new r(t,{filter:function(t){return t.group==e}}),this.itemset.setItems(this.view),this.parent.controller.add(this.itemset)}},b.prototype.repaint=function(){return!1},b.prototype.reflow=function(){var t=0,e=D.updateProperty;if(t+=e(this,"top",this.itemset?this.itemset.top:0),t+=e(this,"height",this.itemset?this.itemset.height:0),this.label){var i=this.label.firstChild;t+=e(this.props.label,"width",i.clientWidth),t+=e(this.props.label,"height",i.clientHeight)}else t+=e(this.props.label,"width",0),t+=e(this.props.label,"height",0);return t>0},w.prototype=new p,w.prototype.setOptions=l.prototype.setOptions,w.prototype.setRange=function(){},w.prototype.setItems=function(t){this.itemsData=t;for(var e in this.groups)if(this.groups.hasOwnProperty(e)){var i=this.groups[e];i.setItems(t)}},w.prototype.getItems=function(){return this.itemsData},w.prototype.setRange=function(t){this.range=t},w.prototype.setGroups=function(t){var e,i=this;if(this.groupsData&&(D.forEach(this.listeners,function(t,e){i.groupsData.unsubscribe(e,t)}),e=this.groupsData.getIds(),this._onRemove(e)),t?t instanceof o?this.groupsData=t:(this.groupsData=new o({convert:{start:"Date",end:"Date"}}),this.groupsData.add(t)):this.groupsData=null,this.groupsData){var s=this.id;D.forEach(this.listeners,function(t,e){i.groupsData.subscribe(e,t,s)}),e=this.groupsData.getIds(),this._onAdd(e)}},w.prototype.getGroups=function(){return this.groupsData},w.prototype.repaint=function(){var t,e,i,s,n=0,o=D.updateProperty,r=D.option.asSize,a=D.option.asElement,h=this.options,d=this.dom.frame,l=this.dom.labels;if(!this.parent)throw Error("Cannot repaint groupset: no parent attached");var p=this.parent.getContainer();if(!p)throw Error("Cannot repaint groupset: parent has no container element");if(!d){d=document.createElement("div"),d.className="groupset",this.dom.frame=d;var c=h.className;c&&D.addClassName(d,D.option.asString(c)),n+=1}d.parentNode||(p.appendChild(d),n+=1);var u=a(h.labelContainer);if(!u)throw Error('Cannot repaint groupset: option "labelContainer" not defined');l||(l=document.createElement("div"),l.className="labels",this.dom.labels=l),l.parentNode&&l.parentNode==u||(l.parentNode&&l.parentNode.removeChild(l.parentNode),u.appendChild(l)),n+=o(d.style,"height",r(h.height,this.height+"px")),n+=o(d.style,"top",r(h.top,"0px")),n+=o(d.style,"left",r(h.left,"0px")),n+=o(d.style,"width",r(h.width,"100%")),n+=o(l.style,"top",r(h.top,"0px"));var f=this,m=this.queue,g=this.groups,v=this.groupsData,y=Object.keys(m);if(y.length){y.forEach(function(t){var e=m[t],i=g[t];switch(e){case"add":case"update":if(!i){var s=Object.create(f.options);i=new b(f,t,s),i.setItems(f.itemsData),g[t]=i,f.controller.add(i)}i.data=v.get(t),delete m[t];break;case"remove":i&&(i.setItems(),delete g[t],f.controller.remove(i)),delete m[t];break;default:console.log('Error: unknown action "'+e+'"')}});var w=this.groupsData.getIds({order:this.options.groupsOrder});for(t=0;w.length>t;t++)(function(t,e){var i=0;e&&(i=function(){return e.top+e.height}),t.setOptions({top:i})})(g[w[t]],g[w[t-1]]);for(;l.firstChild;)l.removeChild(l.firstChild);for(t=0;w.length>t;t++)e=w[t],s=this._createLabel(e),l.appendChild(s);n++}for(e in g)g.hasOwnProperty(e)&&(i=g[e],s=i.label,s&&(s.style.top=i.top+"px",s.style.height=i.height+"px"));return n>0},w.prototype._createLabel=function(t){var e=this.groups[t],i=document.createElement("div");i.className="label";var s=document.createElement("div");s.className="inner",i.appendChild(s);var n=e.data&&e.data.content;n instanceof Element?s.appendChild(n):void 0!=n&&(s.innerHTML=n);var o=e.data&&e.data.className;return o&&D.addClassName(i,o),e.label=i,i},w.prototype.getContainer=function(){return this.dom.frame},w.prototype.getLabelsWidth=function(){return this.props.labels.width},w.prototype.reflow=function(){var t,e,i=0,s=this.options,n=D.updateProperty,o=D.option.asNumber,r=D.option.asSize,a=this.dom.frame;if(a){var h,d=o(s.maxHeight),l=null!=r(s.height);if(l)h=a.offsetHeight;else{h=0;for(t in this.groups)this.groups.hasOwnProperty(t)&&(e=this.groups[t],h+=e.height)}null!=d&&(h=Math.min(h,d)),i+=n(this,"height",h),i+=n(this,"top",a.offsetTop),i+=n(this,"left",a.offsetLeft),i+=n(this,"width",a.offsetWidth)}var p=0;for(t in this.groups)if(this.groups.hasOwnProperty(t)){e=this.groups[t];var c=e.props&&e.props.label&&e.props.label.width||0;p=Math.max(p,c)}return i+=n(this.props.labels,"width",p),i>0},w.prototype.hide=function(){return this.dom.frame&&this.dom.frame.parentNode?(this.dom.frame.parentNode.removeChild(this.dom.frame),!0):!1},w.prototype.show=function(){return this.dom.frame&&this.dom.frame.parentNode?!1:this.repaint()},w.prototype._onUpdate=function(t){this._toQueue(t,"update")},w.prototype._onAdd=function(t){this._toQueue(t,"add")},w.prototype._onRemove=function(t){this._toQueue(t,"remove")},w.prototype._toQueue=function(t,e){var i=this.queue;t.forEach(function(t){i[t]=e}),this.controller&&this.requestRepaint()},_.prototype.setOptions=function(t){t&&D.extend(this.options,t),this.controller.reflow(),this.controller.repaint()},_.prototype.setItems=function(t){var e,i=null==this.itemsData;if(t?t instanceof o&&(e=t):e=null,t instanceof o||(e=new o({convert:{start:"Date",end:"Date"}}),e.add(t)),this.itemsData=e,this.content.setItems(e),i&&(void 0==this.options.start||void 0==this.options.end)){var s=this.getItemRange(),n=s.min,r=s.max;if(null!=n&&null!=r){var a=r.valueOf()-n.valueOf();0>=a&&(a=864e5),n=new Date(n.valueOf()-.05*a),r=new Date(r.valueOf()+.05*a)}void 0!=this.options.start&&(n=new Date(this.options.start.valueOf())),void 0!=this.options.end&&(r=new Date(this.options.end.valueOf())),(null!=n||null!=r)&&this.range.setRange(n,r)}},_.prototype.setGroups=function(t){var e=this;this.groupsData=t;var i=this.groupsData?w:f;if(!(this.content instanceof i)){this.content&&(this.content.hide(),this.content.setItems&&this.content.setItems(),this.content.setGroups&&this.content.setGroups(),this.controller.remove(this.content));var s=Object.create(this.options);D.extend(s,{top:function(){return"top"==e.options.orientation?e.timeaxis.height:e.itemPanel.height-e.timeaxis.height-e.content.height},left:null,width:"100%",height:function(){return e.options.height?e.itemPanel.height-e.timeaxis.height:null},maxHeight:function(){if(e.options.maxHeight){if(!D.isNumber(e.options.maxHeight))throw new TypeError("Number expected for property maxHeight");return e.options.maxHeight-e.timeaxis.height}return null},labelContainer:function(){return e.labelPanel.getContainer()}}),this.content=new i(this.itemPanel,[this.timeaxis],s),this.content.setRange&&this.content.setRange(this.range),this.content.setItems&&this.content.setItems(this.itemsData),this.content.setGroups&&this.content.setGroups(this.groupsData),this.controller.add(this.content)}},_.prototype.getItemRange=function(){var t=this.itemsData,e=null,i=null;if(t){var s=t.min("start");e=s?s.start.valueOf():null;var n=t.max("start");n&&(i=n.start.valueOf());var o=t.max("end");o&&(i=null==i?o.end.valueOf():Math.max(i,o.end.valueOf()))}return{min:null!=e?new Date(e):null,max:null!=i?new Date(i):null}},function(t){function e(t){return E=t,c()}function i(){D=0,C=E.charAt(0)}function s(){D++,C=E.charAt(D)}function n(){return E.charAt(D+1)}function o(t){return N.test(t)}function r(t,e){if(t||(t={}),e)for(var i in e)e.hasOwnProperty(i)&&(t[i]=e[i]);return t}function a(t,e,i){for(var s=e.split("."),n=t;s.length;){var o=s.shift();s.length?(n[o]||(n[o]={}),n=n[o]):n[o]=i}}function h(t,e){for(var i,s,n=null,o=[t],a=t;a.parent;)o.push(a.parent),a=a.parent;if(a.nodes)for(i=0,s=a.nodes.length;s>i;i++)if(e.id===a.nodes[i].id){n=a.nodes[i];break}for(n||(n={id:e.id},t.node&&(n.attr=r(n.attr,t.node))),i=o.length-1;i>=0;i--){var h=o[i];h.nodes||(h.nodes=[]),-1==h.nodes.indexOf(n)&&h.nodes.push(n)}e.attr&&(n.attr=r(n.attr,e.attr))}function d(t,e){if(t.edges||(t.edges=[]),t.edges.push(e),t.edge){var i=r({},t.edge);e.attr=r(i,e.attr)}}function l(t,e,i,s,n){var o={from:e,to:i,type:s};return t.edge&&(o.attr=r({},t.edge)),o.attr=r(o.attr||{},n),o}function p(){for(O=S.NULL,L="";" "==C||" "==C||"\n"==C||"\r"==C;)s();do{var t=!1;if("#"==C){for(var e=D-1;" "==E.charAt(e)||" "==E.charAt(e);)e--;if("\n"==E.charAt(e)||""==E.charAt(e)){for(;""!=C&&"\n"!=C;)s();t=!0}}if("/"==C&&"/"==n()){for(;""!=C&&"\n"!=C;)s();t=!0}if("/"==C&&"*"==n()){for(;""!=C;){if("*"==C&&"/"==n()){s(),s();break}s()}t=!0}for(;" "==C||" "==C||"\n"==C||"\r"==C;)s()}while(t);if(""==C)return O=S.DELIMITER,void 0;var i=C+n();if(M[i])return O=S.DELIMITER,L=i,s(),s(),void 0;if(M[C])return O=S.DELIMITER,L=C,s(),void 0;if(o(C)||"-"==C){for(L+=C,s();o(C);)L+=C,s();return"false"==L?L=!1:"true"==L?L=!0:isNaN(Number(L))||(L=Number(L)),O=S.IDENTIFIER,void 0}if('"'==C){for(s();""!=C&&('"'!=C||'"'==C&&'"'==n());)L+=C,'"'==C&&s(),s();if('"'!=C)throw w('End of string " expected');return s(),O=S.IDENTIFIER,void 0}for(O=S.UNKNOWN;""!=C;)L+=C,s();throw new SyntaxError('Syntax error in part "'+_(L,30)+'"')}function c(){var t={};if(i(),p(),"strict"==L&&(t.strict=!0,p()),("graph"==L||"digraph"==L)&&(t.type=L,p()),O==S.IDENTIFIER&&(t.id=L,p()),"{"!=L)throw w("Angle bracket { expected");if(p(),u(t),"}"!=L)throw w("Angle bracket } expected");if(p(),""!==L)throw w("End of file expected");return p(),delete t.node,delete t.edge,delete t.graph,t}function u(t){for(;""!==L&&"}"!=L;)f(t),";"==L&&p()}function f(t){var e=m(t);if(e)return y(t,e),void 0;var i=g(t);if(!i){if(O!=S.IDENTIFIER)throw w("Identifier expected");var s=L;if(p(),"="==L){if(p(),O!=S.IDENTIFIER)throw w("Identifier expected");t[s]=L,p()}else v(t,s)}}function m(t){var e=null;if("subgraph"==L&&(e={},e.type="subgraph",p(),O==S.IDENTIFIER&&(e.id=L,p())),"{"==L){if(p(),e||(e={}),e.parent=t,e.node=t.node,e.edge=t.edge,e.graph=t.graph,u(e),"}"!=L)throw w("Angle bracket } expected");p(),delete e.node,delete e.edge,delete e.graph,delete e.parent,t.subgraphs||(t.subgraphs=[]),t.subgraphs.push(e)}return e}function g(t){return"node"==L?(p(),t.node=b(),"node"):"edge"==L?(p(),t.edge=b(),"edge"):"graph"==L?(p(),t.graph=b(),"graph"):null}function v(t,e){var i={id:e},s=b();s&&(i.attr=s),h(t,i),y(t,e)}function y(t,e){for(;"->"==L||"--"==L;){var i,s=L;p();var n=m(t);if(n)i=n;else{if(O!=S.IDENTIFIER)throw w("Identifier or subgraph expected");i=L,h(t,{id:i}),p()}var o=b(),r=l(t,e,i,s,o);d(t,r),e=i}}function b(){for(var t=null;"["==L;){for(p(),t={};""!==L&&"]"!=L;){if(O!=S.IDENTIFIER)throw w("Attribute name expected");var e=L;if(p(),"="!=L)throw w("Equal sign = expected");if(p(),O!=S.IDENTIFIER)throw w("Attribute value expected");var i=L;a(t,e,i),p(),","==L&&p()}if("]"!=L)throw w("Bracket ] expected");p()}return t}function w(t){return new SyntaxError(t+', got "'+_(L,30)+'" (char '+D+")")}function _(t,e){return e>=t.length?t:t.substr(0,27)+"..."}function x(t,e,i){t instanceof Array?t.forEach(function(t){e instanceof Array?e.forEach(function(e){i(t,e)}):i(t,e)}):e instanceof Array?e.forEach(function(e){i(t,e)}):i(t,e)}function T(t){function i(t){var e={from:t.from,to:t.to};return r(e,t.attr),e.style="->"==t.type?"arrow":"line",e}var s=e(t),n={nodes:[],edges:[],options:{}};return s.nodes&&s.nodes.forEach(function(t){var e={id:t.id,label:(t.label||t.id)+""};r(e,t.attr),e.image&&(e.shape="image"),n.nodes.push(e)}),s.edges&&s.edges.forEach(function(t){var e,s;e=t.from instanceof Object?t.from.nodes:{id:t.from},s=t.to instanceof Object?t.to.nodes:{id:t.to},t.from instanceof Object&&t.from.edges&&t.from.edges.forEach(function(t){var e=i(t);n.edges.push(e)}),x(e,s,function(e,s){var o=l(n,e.id,s.id,t.type,t.attr),r=i(o);n.edges.push(r)}),t.to instanceof Object&&t.to.edges&&t.to.edges.forEach(function(t){var e=i(t);n.edges.push(e)})}),s.attr&&(n.options=s.attr),n}var S={NULL:0,DELIMITER:1,IDENTIFIER:2,UNKNOWN:3},M={"{":!0,"}":!0,"[":!0,"]":!0,";":!0,"=":!0,",":!0,"->":!0,"--":!0},E="",D=0,C="",L="",O=S.NULL,N=/[a-zA-Z_0-9.:#]/;t.parseDOT=e,t.DOTToGraph=T}(D!==void 0?D:s),"undefined"!=typeof CanvasRenderingContext2D&&(CanvasRenderingContext2D.prototype.circle=function(t,e,i){this.beginPath(),this.arc(t,e,i,0,2*Math.PI,!1)},CanvasRenderingContext2D.prototype.square=function(t,e,i){this.beginPath(),this.rect(t-i,e-i,2*i,2*i)},CanvasRenderingContext2D.prototype.triangle=function(t,e,i){this.beginPath();var s=2*i,n=s/2,o=Math.sqrt(3)/6*s,r=Math.sqrt(s*s-n*n);this.moveTo(t,e-(r-o)),this.lineTo(t+n,e+o),this.lineTo(t-n,e+o),this.lineTo(t,e-(r-o)),this.closePath()},CanvasRenderingContext2D.prototype.triangleDown=function(t,e,i){this.beginPath();var s=2*i,n=s/2,o=Math.sqrt(3)/6*s,r=Math.sqrt(s*s-n*n);this.moveTo(t,e+(r-o)),this.lineTo(t+n,e-o),this.lineTo(t-n,e-o),this.lineTo(t,e+(r-o)),this.closePath()},CanvasRenderingContext2D.prototype.star=function(t,e,i){this.beginPath();for(var s=0;10>s;s++){var n=0===s%2?1.3*i:.5*i;this.lineTo(t+n*Math.sin(2*s*Math.PI/10),e-n*Math.cos(2*s*Math.PI/10))}this.closePath()},CanvasRenderingContext2D.prototype.roundRect=function(t,e,i,s,n){var o=Math.PI/180;0>i-2*n&&(n=i/2),0>s-2*n&&(n=s/2),this.beginPath(),this.moveTo(t+n,e),this.lineTo(t+i-n,e),this.arc(t+i-n,e+n,n,270*o,360*o,!1),this.lineTo(t+i,e+s-n),this.arc(t+i-n,e+s-n,n,0,90*o,!1),this.lineTo(t+n,e+s),this.arc(t+n,e+s-n,n,90*o,180*o,!1),this.lineTo(t,e+n),this.arc(t+n,e+n,n,180*o,270*o,!1)},CanvasRenderingContext2D.prototype.ellipse=function(t,e,i,s){var n=.5522848,o=i/2*n,r=s/2*n,a=t+i,h=e+s,d=t+i/2,l=e+s/2;this.beginPath(),this.moveTo(t,l),this.bezierCurveTo(t,l-r,d-o,e,d,e),this.bezierCurveTo(d+o,e,a,l-r,a,l),this.bezierCurveTo(a,l+r,d+o,h,d,h),this.bezierCurveTo(d-o,h,t,l+r,t,l)},CanvasRenderingContext2D.prototype.database=function(t,e,i,s){var n=1/3,o=i,r=s*n,a=.5522848,h=o/2*a,d=r/2*a,l=t+o,p=e+r,c=t+o/2,u=e+r/2,f=e+(s-r/2),m=e+s;this.beginPath(),this.moveTo(l,u),this.bezierCurveTo(l,u+d,c+h,p,c,p),this.bezierCurveTo(c-h,p,t,u+d,t,u),this.bezierCurveTo(t,u-d,c-h,e,c,e),this.bezierCurveTo(c+h,e,l,u-d,l,u),this.lineTo(l,f),this.bezierCurveTo(l,f+d,c+h,m,c,m),this.bezierCurveTo(c-h,m,t,f+d,t,f),this.lineTo(t,u)},CanvasRenderingContext2D.prototype.arrow=function(t,e,i,s){var n=t-s*Math.cos(i),o=e-s*Math.sin(i),r=t-.9*s*Math.cos(i),a=e-.9*s*Math.sin(i),h=n+s/3*Math.cos(i+.5*Math.PI),d=o+s/3*Math.sin(i+.5*Math.PI),l=n+s/3*Math.cos(i-.5*Math.PI),p=o+s/3*Math.sin(i-.5*Math.PI);this.beginPath(),this.moveTo(t,e),this.lineTo(h,d),this.lineTo(r,a),this.lineTo(l,p),this.closePath()},CanvasRenderingContext2D.prototype.dashedLine=function(t,e,i,s,n){n||(n=[10,5]),0==c&&(c=.001);var o=n.length;this.moveTo(t,e);for(var r=i-t,a=s-e,h=a/r,d=Math.sqrt(r*r+a*a),l=0,p=!0;d>=.1;){var c=n[l++%o];c>d&&(c=d);var u=Math.sqrt(c*c/(1+h*h));0>r&&(u=-u),t+=u,e+=h*u,this[p?"lineTo":"moveTo"](t,e),d-=c,p=!p}}),x.prototype.attachEdge=function(t){-1==this.edges.indexOf(t)&&this.edges.push(t),this._updateMass()},x.prototype.detachEdge=function(t){var e=this.edges.indexOf(t);-1!=e&&this.edges.splice(e,1),this._updateMass()},x.prototype._updateMass=function(){this.mass=50+20*this.edges.length},x.prototype.setProperties=function(t,e){if(t){if(void 0!=t.id&&(this.id=t.id),void 0!=t.label&&(this.label=t.label),void 0!=t.title&&(this.title=t.title),void 0!=t.group&&(this.group=t.group),void 0!=t.x&&(this.x=t.x),void 0!=t.y&&(this.y=t.y),void 0!=t.value&&(this.value=t.value),void 0===this.id)throw"Node must have an id";if(this.group){var i=this.grouplist.get(this.group);for(var s in i)i.hasOwnProperty(s)&&(this[s]=i[s])}if(void 0!=t.shape&&(this.shape=t.shape),void 0!=t.image&&(this.image=t.image),void 0!=t.radius&&(this.radius=t.radius),void 0!=t.color&&(this.color=x.parseColor(t.color)),void 0!=t.fontColor&&(this.fontColor=t.fontColor),void 0!=t.fontSize&&(this.fontSize=t.fontSize),void 0!=t.fontFace&&(this.fontFace=t.fontFace),void 0!=this.image){if(!this.imagelist)throw"No imagelist provided";this.imageObj=this.imagelist.load(this.image)}switch(this.xFixed=this.xFixed||void 0!=t.x,this.yFixed=this.yFixed||void 0!=t.y,this.radiusFixed=this.radiusFixed||void 0!=t.radius,"image"==this.shape&&(this.radiusMin=e.nodes.widthMin,this.radiusMax=e.nodes.widthMax),this.shape){case"database":this.draw=this._drawDatabase,this.resize=this._resizeDatabase;break;case"box":this.draw=this._drawBox,this.resize=this._resizeBox;break;case"circle":this.draw=this._drawCircle,this.resize=this._resizeCircle;break;case"ellipse":this.draw=this._drawEllipse,this.resize=this._resizeEllipse;break;case"image":this.draw=this._drawImage,this.resize=this._resizeImage;break;case"text":this.draw=this._drawText,this.resize=this._resizeText;break;case"dot":this.draw=this._drawDot,this.resize=this._resizeShape;break;case"square":this.draw=this._drawSquare,this.resize=this._resizeShape;break;case"triangle":this.draw=this._drawTriangle,this.resize=this._resizeShape;break;case"triangleDown":this.draw=this._drawTriangleDown,this.resize=this._resizeShape;break;case"star":this.draw=this._drawStar,this.resize=this._resizeShape;break;default:this.draw=this._drawEllipse,this.resize=this._resizeEllipse}this._reset()}},x.parseColor=function(t){var e;return D.isString(t)?e={border:t,background:t,highlight:{border:t,background:t}}:(e={},e.background=t.background||"white",e.border=t.border||e.background,D.isString(t.highlight)?e.highlight={border:t.highlight,background:t.highlight}:(e.highlight={},e.highlight.background=t.highlight&&t.highlight.background||e.background,e.highlight.border=t.highlight&&t.highlight.border||e.border)),e},x.prototype.select=function(){this.selected=!0,this._reset()},x.prototype.unselect=function(){this.selected=!1,this._reset()},x.prototype._reset=function(){this.width=void 0,this.height=void 0},x.prototype.getTitle=function(){return this.title},x.prototype.distanceToBorder=function(t,e){var i=1;switch(this.width||this.resize(t),this.shape){case"circle":case"dot":return this.radius+i;case"ellipse":var s=this.width/2,n=this.height/2,o=Math.sin(e)*s,r=Math.cos(e)*n;return s*n/Math.sqrt(o*o+r*r);case"box":case"image":case"text":default:return this.width?Math.min(Math.abs(this.width/2/Math.cos(e)),Math.abs(this.height/2/Math.sin(e)))+i:0}},x.prototype._setForce=function(t,e){this.fx=t,this.fy=e},x.prototype._addForce=function(t,e){this.fx+=t,this.fy+=e},x.prototype.discreteStep=function(t){if(!this.xFixed){var e=-this.damping*this.vx,i=(this.fx+e)/this.mass;this.vx+=i/t,this.x+=this.vx/t}if(!this.yFixed){var s=-this.damping*this.vy,n=(this.fy+s)/this.mass;this.vy+=n/t,this.y+=this.vy/t}},x.prototype.isFixed=function(){return this.xFixed&&this.yFixed},x.prototype.isMoving=function(t){return Math.abs(this.vx)>t||Math.abs(this.vy)>t||!this.xFixed&&Math.abs(this.fx)>this.minForce||!this.yFixed&&Math.abs(this.fy)>this.minForce},x.prototype.isSelected=function(){return this.selected},x.prototype.getValue=function(){return this.value},x.prototype.getDistance=function(t,e){var i=this.x-t,s=this.y-e;return Math.sqrt(i*i+s*s)},x.prototype.setValueRange=function(t,e){if(!this.radiusFixed&&void 0!==this.value){var i=(this.radiusMax-this.radiusMin)/(e-t);this.radius=(this.value-t)*i+this.radiusMin}},x.prototype.draw=function(){throw"Draw method not initialized for node"},x.prototype.resize=function(){throw"Resize method not initialized for node"},x.prototype.isOverlappingWith=function(t){return this.leftt.left&&this.topt.top},x.prototype._resizeImage=function(){if(!this.width){var t,e;if(this.value){var i=this.imageObj.height/this.imageObj.width;t=this.radius||this.imageObj.width,e=this.radius*i||this.imageObj.height}else t=this.imageObj.width,e=this.imageObj.height;this.width=t,this.height=e}},x.prototype._drawImage=function(t){this._resizeImage(t),this.left=this.x-this.width/2,this.top=this.y-this.height/2;var e;this.imageObj?(t.drawImage(this.imageObj,this.left,this.top,this.width,this.height),e=this.y+this.height/2):e=this.y,this._label(t,this.label,this.x,e,void 0,"top")},x.prototype._resizeBox=function(t){if(!this.width){var e=5,i=this.getTextSize(t);this.width=i.width+2*e,this.height=i.height+2*e}},x.prototype._drawBox=function(t){this._resizeBox(t),this.left=this.x-this.width/2,this.top=this.y-this.height/2,t.strokeStyle=this.selected?this.color.highlight.border:this.color.border,t.fillStyle=this.selected?this.color.highlight.background:this.color.background,t.lineWidth=this.selected?2:1,t.roundRect(this.left,this.top,this.width,this.height,this.radius),t.fill(),t.stroke(),this._label(t,this.label,this.x,this.y)},x.prototype._resizeDatabase=function(t){if(!this.width){var e=5,i=this.getTextSize(t),s=i.width+2*e;this.width=s,this.height=s}},x.prototype._drawDatabase=function(t){this._resizeDatabase(t),this.left=this.x-this.width/2,this.top=this.y-this.height/2,t.strokeStyle=this.selected?this.color.highlight.border:this.color.border,t.fillStyle=this.selected?this.color.highlight.background:this.color.background,t.lineWidth=this.selected?2:1,t.database(this.x-this.width/2,this.y-.5*this.height,this.width,this.height),t.fill(),t.stroke(),this._label(t,this.label,this.x,this.y)},x.prototype._resizeCircle=function(t){if(!this.width){var e=5,i=this.getTextSize(t),s=Math.max(i.width,i.height)+2*e;this.radius=s/2,this.width=s,this.height=s}},x.prototype._drawCircle=function(t){this._resizeCircle(t),this.left=this.x-this.width/2,this.top=this.y-this.height/2,t.strokeStyle=this.selected?this.color.highlight.border:this.color.border,t.fillStyle=this.selected?this.color.highlight.background:this.color.background,t.lineWidth=this.selected?2:1,t.circle(this.x,this.y,this.radius),t.fill(),t.stroke(),this._label(t,this.label,this.x,this.y)},x.prototype._resizeEllipse=function(t){if(!this.width){var e=this.getTextSize(t);this.width=1.5*e.width,this.height=2*e.height,this.widthl;l++)t.fillText(r[l],i,d),d+=h}},x.prototype.getTextSize=function(t){if(void 0!=this.label){t.font=(this.selected?"bold ":"")+this.fontSize+"px "+this.fontFace;for(var e=this.label.split("\n"),i=(this.fontSize+4)*e.length,s=0,n=0,o=e.length;o>n;n++)s=Math.max(s,t.measureText(e[n]).width);return{width:s,height:i}}return{width:0,height:0}},T.prototype.setProperties=function(t,e){if(t)switch(void 0!=t.from&&(this.fromId=t.from),void 0!=t.to&&(this.toId=t.to),void 0!=t.id&&(this.id=t.id),void 0!=t.style&&(this.style=t.style),void 0!=t.label&&(this.label=t.label),this.label&&(this.fontSize=e.edges.fontSize,this.fontFace=e.edges.fontFace,this.fontColor=e.edges.fontColor,void 0!=t.fontColor&&(this.fontColor=t.fontColor),void 0!=t.fontSize&&(this.fontSize=t.fontSize),void 0!=t.fontFace&&(this.fontFace=t.fontFace)),void 0!=t.title&&(this.title=t.title),void 0!=t.width&&(this.width=t.width),void 0!=t.value&&(this.value=t.value),void 0!=t.length&&(this.length=t.length),t.dash&&(void 0!=t.dash.length&&(this.dash.length=t.dash.length),void 0!=t.dash.gap&&(this.dash.gap=t.dash.gap),void 0!=t.dash.altLength&&(this.dash.altLength=t.dash.altLength)),void 0!=t.color&&(this.color=t.color),this.connect(),this.widthFixed=this.widthFixed||void 0!=t.width,this.lengthFixed=this.lengthFixed||void 0!=t.length,this.stiffness=1/this.length,this.style){case"line":this.draw=this._drawLine;break;case"arrow":this.draw=this._drawArrow;break;case"arrow-center":this.draw=this._drawArrowCenter;break;case"dash-line":this.draw=this._drawDashLine;break;default:this.draw=this._drawLine}},T.prototype.connect=function(){this.disconnect(),this.from=this.graph.nodes[this.fromId]||null,this.to=this.graph.nodes[this.toId]||null,this.connected=this.from&&this.to,this.connected?(this.from.attachEdge(this),this.to.attachEdge(this)):(this.from&&this.from.detachEdge(this),this.to&&this.to.detachEdge(this))},T.prototype.disconnect=function(){this.from&&(this.from.detachEdge(this),this.from=null),this.to&&(this.to.detachEdge(this),this.to=null),this.connected=!1},T.prototype.getTitle=function(){return this.title},T.prototype.getValue=function(){return this.value},T.prototype.setValueRange=function(t,e){if(!this.widthFixed&&void 0!==this.value){var i=(this.widthMax-this.widthMin)/(e-t);this.width=(this.value-t)*i+this.widthMin}},T.prototype.draw=function(){throw"Method draw not initialized in edge"},T.prototype.isOverlappingWith=function(t){var e=10,i=this.from.x,s=this.from.y,n=this.to.x,o=this.to.y,r=t.left,a=t.top,h=T._dist(i,s,n,o,r,a);return e>h},T.prototype._drawLine=function(t){t.strokeStyle=this.color,t.lineWidth=this._getLineWidth();var e;if(this.from!=this.to)this._line(t),this.label&&(e=this._pointOnLine(.5),this._label(t,this.label,e.x,e.y));else{var i,s,n=this.length/4,o=this.from;o.width||o.resize(t),o.width>o.height?(i=o.x+o.width/2,s=o.y-n):(i=o.x+n,s=o.y-o.height/2),this._circle(t,i,s,n),e=this._pointOnCircle(i,s,n,.5),this._label(t,this.label,e.x,e.y)}},T.prototype._getLineWidth=function(){return this.from.selected||this.to.selected?Math.min(2*this.width,this.widthMax):this.width},T.prototype._line=function(t){t.beginPath(),t.moveTo(this.from.x,this.from.y),t.lineTo(this.to.x,this.to.y),t.stroke()},T.prototype._circle=function(t,e,i,s){t.beginPath(),t.arc(e,i,s,0,2*Math.PI,!1),t.stroke()},T.prototype._label=function(t,e,i,s){if(e){t.font=(this.from.selected||this.to.selected?"bold ":"")+this.fontSize+"px "+this.fontFace,t.fillStyle="white";var n=t.measureText(e).width,o=this.fontSize,r=i-n/2,a=s-o/2;t.fillRect(r,a,n,o),t.fillStyle=this.fontColor||"black",t.textAlign="left",t.textBaseline="top",t.fillText(e,r,a)}},T.prototype._drawDashLine=function(t){if(t.strokeStyle=this.color,t.lineWidth=this._getLineWidth(),t.beginPath(),t.lineCap="round",void 0!=this.dash.altLength?t.dashedLine(this.from.x,this.from.y,this.to.x,this.to.y,[this.dash.length,this.dash.gap,this.dash.altLength,this.dash.gap]):void 0!=this.dash.length&&void 0!=this.dash.gap?t.dashedLine(this.from.x,this.from.y,this.to.x,this.to.y,[this.dash.length,this.dash.gap]):(t.moveTo(this.from.x,this.from.y),t.lineTo(this.to.x,this.to.y)),t.stroke(),this.label){var e=this._pointOnLine(.5);this._label(t,this.label,e.x,e.y)}},T.prototype._pointOnLine=function(t){return{x:(1-t)*this.from.x+t*this.to.x,y:(1-t)*this.from.y+t*this.to.y}},T.prototype._pointOnCircle=function(t,e,i,s){var n=2*(s-3/8)*Math.PI;return{x:t+i*Math.cos(n),y:e-i*Math.sin(n)}},T.prototype._drawArrowCenter=function(t){var e;if(t.strokeStyle=this.color,t.fillStyle=this.color,t.lineWidth=this._getLineWidth(),this.from!=this.to){this._line(t);var i=Math.atan2(this.to.y-this.from.y,this.to.x-this.from.x),s=10+5*this.width;e=this._pointOnLine(.5),t.arrow(e.x,e.y,i,s),t.fill(),t.stroke(),this.label&&(e=this._pointOnLine(.5),this._label(t,this.label,e.x,e.y))}else{var n,o,r=this.length/4,a=this.from;a.width||a.resize(t),a.width>a.height?(n=a.x+a.width/2,o=a.y-r):(n=a.x+r,o=a.y-a.height/2),this._circle(t,n,o,r);var i=.2*Math.PI,s=10+5*this.width;e=this._pointOnCircle(n,o,r,.5),t.arrow(e.x,e.y,i,s),t.fill(),t.stroke(),this.label&&(e=this._pointOnCircle(n,o,r,.5),this._label(t,this.label,e.x,e.y))}},T.prototype._drawArrow=function(t){t.strokeStyle=this.color,t.fillStyle=this.color,t.lineWidth=this._getLineWidth();var e,i;if(this.from!=this.to){e=Math.atan2(this.to.y-this.from.y,this.to.x-this.from.x);var s=this.to.x-this.from.x,n=this.to.y-this.from.y,o=Math.sqrt(s*s+n*n),r=this.from.distanceToBorder(t,e+Math.PI),a=(o-r)/o,h=a*this.from.x+(1-a)*this.to.x,d=a*this.from.y+(1-a)*this.to.y,l=this.to.distanceToBorder(t,e),p=(o-l)/o,c=(1-p)*this.from.x+p*this.to.x,u=(1-p)*this.from.y+p*this.to.y;if(t.beginPath(),t.moveTo(h,d),t.lineTo(c,u),t.stroke(),i=10+5*this.width,t.arrow(c,u,e,i),t.fill(),t.stroke(),this.label){var f=this._pointOnLine(.5);this._label(t,this.label,f.x,f.y)}}else{var m,g,v,y=this.from,b=this.length/4;y.width||y.resize(t),y.width>y.height?(m=y.x+y.width/2,g=y.y-b,v={x:m,y:y.y,angle:.9*Math.PI}):(m=y.x+b,g=y.y-y.height/2,v={x:y.x,y:g,angle:.6*Math.PI}),t.beginPath(),t.arc(m,g,b,0,2*Math.PI,!1),t.stroke(),i=10+5*this.width,t.arrow(v.x,v.y,v.angle,i),t.fill(),t.stroke(),this.label&&(f=this._pointOnCircle(m,g,b,.5),this._label(t,this.label,f.x,f.y)) +}},T._dist=function(t,e,i,s,n,o){var r=i-t,a=s-e,h=r*r+a*a,d=((n-t)*r+(o-e)*a)/h;d>1?d=1:0>d&&(d=0);var l=t+d*r,p=e+d*a,c=l-n,u=p-o;return Math.sqrt(c*c+u*u)},S.prototype.setPosition=function(t,e){this.x=parseInt(t),this.y=parseInt(e)},S.prototype.setText=function(t){this.frame.innerHTML=t},S.prototype.show=function(t){if(void 0===t&&(t=!0),t){var e=this.frame.clientHeight,i=this.frame.clientWidth,s=this.frame.parentNode.clientHeight,n=this.frame.parentNode.clientWidth,o=this.y-e;o+e+this.padding>s&&(o=s-e-this.padding),this.padding>o&&(o=this.padding);var r=this.x;r+i+this.padding>n&&(r=n-i-this.padding),this.padding>r&&(r=this.padding),this.frame.style.left=r+"px",this.frame.style.top=o+"px",this.frame.style.visibility="visible"}else this.hide()},S.prototype.hide=function(){this.frame.style.visibility="hidden"},Groups=function(){this.clear(),this.defaultIndex=0},Groups.DEFAULT=[{border:"#2B7CE9",background:"#97C2FC",highlight:{border:"#2B7CE9",background:"#D2E5FF"}},{border:"#FFA500",background:"#FFFF00",highlight:{border:"#FFA500",background:"#FFFFA3"}},{border:"#FA0A10",background:"#FB7E81",highlight:{border:"#FA0A10",background:"#FFAFB1"}},{border:"#41A906",background:"#7BE141",highlight:{border:"#41A906",background:"#A1EC76"}},{border:"#E129F0",background:"#EB7DF4",highlight:{border:"#E129F0",background:"#F0B3F5"}},{border:"#7C29F0",background:"#AD85E4",highlight:{border:"#7C29F0",background:"#D3BDF0"}},{border:"#C37F00",background:"#FFA807",highlight:{border:"#C37F00",background:"#FFCA66"}},{border:"#4220FB",background:"#6E6EFD",highlight:{border:"#4220FB",background:"#9B9BFD"}},{border:"#FD5A77",background:"#FFC0CB",highlight:{border:"#FD5A77",background:"#FFD1D9"}},{border:"#4AD63A",background:"#C2FABC",highlight:{border:"#4AD63A",background:"#E6FFE3"}}],Groups.prototype.clear=function(){this.groups={},this.groups.length=function(){var t=0;for(var e in this)this.hasOwnProperty(e)&&t++;return t}},Groups.prototype.get=function(t){var e=this.groups[t];if(void 0==e){var i=this.defaultIndex%Groups.DEFAULT.length;this.defaultIndex++,e={},e.color=Groups.DEFAULT[i],this.groups[t]=e}return e},Groups.prototype.add=function(t,e){return this.groups[t]=e,e.color&&(e.color=x.parseColor(e.color)),e},Images=function(){this.images={},this.callback=void 0},Images.prototype.setOnloadCallback=function(t){this.callback=t},Images.prototype.load=function(t){var e=this.images[t];if(void 0==e){var i=this;e=new Image,this.images[t]=e,e.onload=function(){i.callback&&i.callback(this)},e.src=t}return e},M.prototype.setData=function(t){if(t&&t.dot&&(t.nodes||t.edges))throw new SyntaxError('Data must contain either parameter "dot" or parameter pair "nodes" and "edges", but not both.');if(this.setOptions(t&&t.options),t&&t.dot){if(t&&t.dot){var e=N.util.DOTToGraph(t.dot);return this.setData(e),void 0}}else this._setNodes(t&&t.nodes),this._setEdges(t&&t.edges);this.stabilize&&this._doStabilize(),this.start()},M.prototype.setOptions=function(t){if(t){if(void 0!=t.width&&(this.width=t.width),void 0!=t.height&&(this.height=t.height),void 0!=t.stabilize&&(this.stabilize=t.stabilize),void 0!=t.selectable&&(this.selectable=t.selectable),t.edges){for(var e in t.edges)t.edges.hasOwnProperty(e)&&(this.constants.edges[e]=t.edges[e]);void 0!=t.edges.length&&t.nodes&&void 0==t.nodes.distance&&(this.constants.edges.length=t.edges.length,this.constants.nodes.distance=1.25*t.edges.length),t.edges.fontColor||(this.constants.edges.fontColor=t.edges.color),t.edges.dash&&(void 0!=t.edges.dash.length&&(this.constants.edges.dash.length=t.edges.dash.length),void 0!=t.edges.dash.gap&&(this.constants.edges.dash.gap=t.edges.dash.gap),void 0!=t.edges.dash.altLength&&(this.constants.edges.dash.altLength=t.edges.dash.altLength))}if(t.nodes){for(e in t.nodes)t.nodes.hasOwnProperty(e)&&(this.constants.nodes[e]=t.nodes[e]);t.nodes.color&&(this.constants.nodes.color=x.parseColor(t.nodes.color))}if(t.groups)for(var i in t.groups)if(t.groups.hasOwnProperty(i)){var s=t.groups[i];this.groups.add(i,s)}}this.setSize(this.width,this.height),this._setTranslation(this.frame.clientWidth/2,this.frame.clientHeight/2),this._setScale(1)},M.prototype._trigger=function(t,e){O.trigger(this,t,e)},M.prototype._create=function(){for(;this.containerElement.hasChildNodes();)this.containerElement.removeChild(this.containerElement.firstChild);if(this.frame=document.createElement("div"),this.frame.className="graph-frame",this.frame.style.position="relative",this.frame.style.overflow="hidden",this.frame.canvas=document.createElement("canvas"),this.frame.canvas.style.position="relative",this.frame.appendChild(this.frame.canvas),!this.frame.canvas.getContext){var t=document.createElement("DIV");t.style.color="red",t.style.fontWeight="bold",t.style.padding="10px",t.innerHTML="Error: your browser does not support HTML canvas",this.frame.canvas.appendChild(t)}var e=this,i=function(t){e._onMouseDown(t)},s=function(t){e._onMouseMoveTitle(t)},n=function(t){e._onMouseWheel(t)},o=function(t){e._onTouchStart(t)};N.util.addEventListener(this.frame.canvas,"mousedown",i),N.util.addEventListener(this.frame.canvas,"mousemove",s),N.util.addEventListener(this.frame.canvas,"mousewheel",n),N.util.addEventListener(this.frame.canvas,"touchstart",o),this.containerElement.appendChild(this.frame)},M.prototype._onMouseDown=function(t){if(t=t||window.event,this.selectable&&(this.leftButtonDown&&this._onMouseUp(t),this.leftButtonDown=t.which?1==t.which:1==t.button,this.leftButtonDown||this.touchDown)){var e=this;this.onmousemove||(this.onmousemove=function(t){e._onMouseMove(t)},N.util.addEventListener(document,"mousemove",e.onmousemove)),this.onmouseup||(this.onmouseup=function(t){e._onMouseUp(t)},N.util.addEventListener(document,"mouseup",e.onmouseup)),N.util.preventDefault(t),this.startMouseX=D.getPageX(t),this.startMouseY=D.getPageY(t),this.startFrameLeft=N.util.getAbsoluteLeft(this.frame.canvas),this.startFrameTop=N.util.getAbsoluteTop(this.frame.canvas),this.startTranslation=this._getTranslation(),this.ctrlKeyDown=t.ctrlKey,this.shiftKeyDown=t.shiftKey;var i={left:this._xToCanvas(this.startMouseX-this.startFrameLeft),top:this._yToCanvas(this.startMouseY-this.startFrameTop),right:this._xToCanvas(this.startMouseX-this.startFrameLeft),bottom:this._yToCanvas(this.startMouseY-this.startFrameTop)},s=this._getNodesOverlappingWith(i);if(this.startClickedObj=s.length>0?s[s.length-1]:void 0,this.startClickedObj){var n=this.nodes[this.startClickedObj];this.startClickedObj.xFixed=n.xFixed,this.startClickedObj.yFixed=n.yFixed,n.xFixed=!0,n.yFixed=!0,this.ctrlKeyDown&&n.isSelected()?this._unselectNodes([this.startClickedObj]):this._selectNodes([this.startClickedObj],this.ctrlKeyDown),this.moving||this._redraw()}else this.shiftKeyDown||(this.moved=!1)}},M.prototype._onMouseMove=function(t){if(t=t||window.event,this.selectable){var e=D.getPageX(t),i=D.getPageY(t);if(this.mouseX=e,this.mouseY=i,this.startClickedObj){var s=this.nodes[this.startClickedObj];this.startClickedObj.xFixed||(s.x=this._xToCanvas(e-this.startFrameLeft)),this.startClickedObj.yFixed||(s.y=this._yToCanvas(i-this.startFrameTop)),this.moving||(this.moving=!0,this.start())}else if(this.shiftKeyDown){void 0==this.frame.selRect&&(this.frame.selRect=document.createElement("DIV"),this.frame.appendChild(this.frame.selRect),this.frame.selRect.style.position="absolute",this.frame.selRect.style.border="1px dashed red");var n=Math.min(this.startMouseX,e)-this.startFrameLeft,o=Math.min(this.startMouseY,i)-this.startFrameTop,r=Math.max(this.startMouseX,e)-this.startFrameLeft,a=Math.max(this.startMouseY,i)-this.startFrameTop;this.frame.selRect.style.left=n+"px",this.frame.selRect.style.top=o+"px",this.frame.selRect.style.width=r-n+"px",this.frame.selRect.style.height=a-o+"px"}else{var h=e-this.startMouseX,d=i-this.startMouseY;this._setTranslation(this.startTranslation.x+h,this.startTranslation.y+d),this._redraw(),this.moved=!0}N.util.preventDefault(t)}},M.prototype._onMouseUp=function(t){if(t=t||window.event,this.selectable){this.onmousemove&&(N.util.removeEventListener(document,"mousemove",this.onmousemove),this.onmousemove=void 0),this.onmouseup&&(N.util.removeEventListener(document,"mouseup",this.onmouseup),this.onmouseup=void 0),N.util.preventDefault(t);var e=D.getPageX(t)||this.mouseX||0,i=D.getPageY(t)||this.mouseY||0,s=t?t.ctrlKey:window.event.ctrlKey;if(this.startClickedObj){var n=this.nodes[this.startClickedObj];n.xFixed=this.startClickedObj.xFixed,n.yFixed=this.startClickedObj.yFixed}else if(this.shiftKeyDown){var o={left:this._xToCanvas(Math.min(this.startMouseX,e)-this.startFrameLeft),top:this._yToCanvas(Math.min(this.startMouseY,i)-this.startFrameTop),right:this._xToCanvas(Math.max(this.startMouseX,e)-this.startFrameLeft),bottom:this._yToCanvas(Math.max(this.startMouseY,i)-this.startFrameTop)},r=this._getNodesOverlappingWith(o);this._selectNodes(r,s),this.redraw(),this.frame.selRect&&(this.frame.removeChild(this.frame.selRect),this.frame.selRect=void 0)}else this.ctrlKeyDown||this.moved||(this._unselectNodes(),this._redraw());this.leftButtonDown=!1,this.ctrlKeyDown=!1}},M.prototype._onMouseWheel=function(t){t=t||window.event;var e=D.getPageX(t),i=D.getPageY(t),s=0;if(t.wheelDelta?s=t.wheelDelta/120:t.detail&&(s=-t.detail/3),s){var n=s/10;0>s&&(n/=1-n);var o=this._getScale(),r=o*(1+n);.01>r&&(r=.01),r>10&&(r=10);var a=N.util.getAbsoluteLeft(this.frame.canvas),h=N.util.getAbsoluteTop(this.frame.canvas),d=e-a,l=i-h,p=this._getTranslation(),c=r/o,u=(1-c)*d+p.x*c,f=(1-c)*l+p.y*c;this._setScale(r),this._setTranslation(u,f),this._redraw()}N.util.preventDefault(t)},M.prototype._onMouseMoveTitle=function(t){t=t||window.event;var e=D.getPageX(t),i=D.getPageY(t);this.startFrameLeft=this.startFrameLeft||N.util.getAbsoluteLeft(this.frame.canvas),this.startFrameTop=this.startFrameTop||N.util.getAbsoluteTop(this.frame.canvas);var s=e-this.startFrameLeft,n=i-this.startFrameTop;this.popupNode&&this._checkHidePopup(s,n);var o=this,r=function(){o._checkShowPopup(s,n)};this.popupTimer&&clearInterval(this.popupTimer),this.leftButtonDown||(this.popupTimer=setTimeout(r,300))},M.prototype._checkShowPopup=function(t,e){var i,s={left:this._xToCanvas(t),top:this._yToCanvas(e),right:this._xToCanvas(t),bottom:this._yToCanvas(e)},n=this.popupNode;if(void 0==this.popupNode){var o=this.nodes;for(i in o)if(o.hasOwnProperty(i)){var r=o[i];if(void 0!=r.getTitle()&&r.isOverlappingWith(s)){this.popupNode=r;break}}}if(void 0==this.popupNode){var a=this.edges;for(i in a)if(a.hasOwnProperty(i)){var h=a[i];if(h.connected&&void 0!=h.getTitle()&&h.isOverlappingWith(s)){this.popupNode=h;break}}}if(this.popupNode){if(this.popupNode!=n){var d=this;d.popup||(d.popup=new S(d.frame)),d.popup.setPosition(t-3,e-3),d.popup.setText(d.popupNode.getTitle()),d.popup.show()}}else this.popup&&this.popup.hide()},M.prototype._checkHidePopup=function(t,e){var i={left:t,top:e,right:t,bottom:e};this.popupNode&&this.popupNode.isOverlappingWith(i)||(this.popupNode=void 0,this.popup&&this.popup.hide())},M.prototype._onTouchStart=function(t){if(N.util.preventDefault(t),!this.touchDown){this.touchDown=!0;var e=this;this.ontouchmove||(this.ontouchmove=function(t){e._onTouchMove(t)},N.util.addEventListener(document,"touchmove",this.ontouchmove)),this.ontouchend||(this.ontouchend=function(t){e._onTouchEnd(t)},N.util.addEventListener(document,"touchend",this.ontouchend)),this._onMouseDown(t)}},M.prototype._onTouchMove=function(t){N.util.preventDefault(t),this._onMouseMove(t)},M.prototype._onTouchEnd=function(t){N.util.preventDefault(t),this.touchDown=!1,this.ontouchmove&&(N.util.removeEventListener(document,"touchmove",this.ontouchmove),this.ontouchmove=void 0),this.ontouchend&&(N.util.removeEventListener(document,"touchend",this.ontouchend),this.ontouchend=void 0),this._onMouseUp(t)},M.prototype._unselectNodes=function(t,e){var i,s,n,o=!1;if(t)for(i=0,s=t.length;s>i;i++){n=t[i],this.nodes[n].unselect();for(var r=0;this.selection.length>r;)this.selection[r]==n?(this.selection.splice(r,1),o=!0):r++}else if(this.selection&&this.selection.length){for(i=0,s=this.selection.length;s>i;i++)n=this.selection[i],this.nodes[n].unselect(),o=!0;this.selection=[]}return!o||1!=e&&void 0!=e||this._trigger("select"),o},M.prototype._selectNodes=function(t,e){var i,s,n=!1,o=!0;if(t.length!=this.selection.length)o=!1;else for(i=0,s=Math.min(t.length,this.selection.length);s>i;i++)if(t[i]!=this.selection[i]){o=!1;break}if(o)return n;if(void 0==e||0==e){var r=!1;n=this._unselectNodes(void 0,r)}for(i=0,s=t.length;s>i;i++){var a=t[i],h=-1!=this.selection.indexOf(a);h||(this.nodes[a].select(),this.selection.push(a),n=!0)}return n&&this._trigger("select"),n},M.prototype._getNodesOverlappingWith=function(t){var e=this.nodes,i=[];for(var s in e)e.hasOwnProperty(s)&&e[s].isOverlappingWith(t)&&i.push(s);return i},M.prototype.getSelection=function(){return this.selection.concat([])},M.prototype.setSelection=function(t){var e,i,s;if(void 0==t.length)throw"Selection must be an array with ids";for(e=0,i=this.selection.length;i>e;e++)s=this.selection[e],this.nodes[s].unselect();for(this.selection=[],e=0,i=t.length;i>e;e++){s=t[e];var n=this.nodes[s];if(!n)throw new RangeError('Node with id "'+s+'" not found');n.select(),this.selection.push(s)}this.redraw()},M.prototype._updateSelection=function(){for(var t=0;this.selection.length>t;){var e=this.selection[t];this.nodes[e]?t++:this.selection.splice(t,1)}},M.prototype._getConnectionCount=function(t){function e(t){for(var e=[],i=0,s=t.length;s>i;i++)for(var n=t[i],o=n.edges,r=0,a=o.length;a>r;r++){var h=o[r],d=null;h.from==n?d=h.to:h.to==n&&(d=h.from);var l,p;if(d)for(l=0,p=t.length;p>l;l++)if(t[l]==d){d=null;break}if(d)for(l=0,p=e.length;p>l;l++)if(e[l]==d){d=null;break}d&&e.push(d)}return e}void 0==t&&(t=1);var i=[],s=this.nodes;for(var n in s)if(s.hasOwnProperty(n)){for(var o=[s[n]],r=0;t>r;r++)o=o.concat(e(o));i.push(o)}for(var a=[],h=0,d=i.length;d>h;h++)a.push(i[h].length);return a},M.prototype.setSize=function(t,e){this.frame.style.width=t,this.frame.style.height=e,this.frame.canvas.style.width="100%",this.frame.canvas.style.height="100%",this.frame.canvas.width=this.frame.canvas.clientWidth,this.frame.canvas.height=this.frame.canvas.clientHeight},M.prototype._setNodes=function(t){var e=this.nodesData;if(t instanceof o||t instanceof r)this.nodesData=t;else if(t instanceof Array)this.nodesData=new o,this.nodesData.add(t);else{if(t)throw new TypeError("Array or DataSet expected");this.nodesData=new o}if(e&&D.forEach(this.nodesListeners,function(t,i){e.unsubscribe(i,t)}),this.nodes={},this.nodesData){var i=this;D.forEach(this.nodesListeners,function(t,e){i.nodesData.subscribe(e,t)});var s=this.nodesData.getIds();this._addNodes(s)}this._updateSelection()},M.prototype._addNodes=function(t){for(var e,i=0,s=t.length;s>i;i++){e=t[i];var n=this.nodesData.get(e),o=new x(n,this.images,this.groups,this.constants);if(this.nodes[e]=o,!o.isFixed()){var r=2*this.constants.edges.length,a=t.length,h=2*Math.PI*(i/a);o.x=r*Math.cos(h),o.y=r*Math.sin(h),this.moving=!0}}this._reconnectEdges(),this._updateValueRange(this.nodes)},M.prototype._updateNodes=function(t){for(var e=this.nodes,i=this.nodesData,s=0,n=t.length;n>s;s++){var o=t[s],r=e[o],a=i.get(o);r?r.setProperties(a,this.constants):(r=new x(properties,this.images,this.groups,this.constants),e[o]=r,r.isFixed()||(this.moving=!0))}this._reconnectEdges(),this._updateValueRange(e)},M.prototype._removeNodes=function(t){for(var e=this.nodes,i=0,s=t.length;s>i;i++){var n=t[i];delete e[n]}this._reconnectEdges(),this._updateSelection(),this._updateValueRange(e)},M.prototype._setEdges=function(t){var e=this.edgesData;if(t instanceof o||t instanceof r)this.edgesData=t;else if(t instanceof Array)this.edgesData=new o,this.edgesData.add(t);else{if(t)throw new TypeError("Array or DataSet expected");this.edgesData=new o}if(e&&D.forEach(this.edgesListeners,function(t,i){e.unsubscribe(i,t)}),this.edges={},this.edgesData){var i=this;D.forEach(this.edgesListeners,function(t,e){i.edgesData.subscribe(e,t)});var s=this.edgesData.getIds();this._addEdges(s)}this._reconnectEdges()},M.prototype._addEdges=function(t){for(var e=this.edges,i=this.edgesData,s=0,n=t.length;n>s;s++){var o=t[s],r=e[o];r&&r.disconnect();var a=i.get(o);e[o]=new T(a,this,this.constants)}this.moving=!0,this._updateValueRange(e)},M.prototype._updateEdges=function(t){for(var e=this.edges,i=this.edgesData,s=0,n=t.length;n>s;s++){var o=t[s],r=i.get(o),a=e[o];a?(a.disconnect(),a.setProperties(r,this.constants),a.connect()):(a=new T(r,this,this.constants),this.edges[o]=a)}this.moving=!0,this._updateValueRange(e)},M.prototype._removeEdges=function(t){for(var e=this.edges,i=0,s=t.length;s>i;i++){var n=t[i],o=e[n];o&&(o.disconnect(),delete e[n])}this.moving=!0,this._updateValueRange(e)},M.prototype._reconnectEdges=function(){var t,e=this.nodes,i=this.edges;for(t in e)e.hasOwnProperty(t)&&(e[t].edges=[]);for(t in i)if(i.hasOwnProperty(t)){var s=i[t];s.from=null,s.to=null,s.connect()}},M.prototype._updateValueRange=function(t){var e,i=void 0,s=void 0;for(e in t)if(t.hasOwnProperty(e)){var n=t[e].getValue();void 0!==n&&(i=void 0===i?n:Math.min(n,i),s=void 0===s?n:Math.max(n,s))}if(void 0!==i&&void 0!==s)for(e in t)t.hasOwnProperty(e)&&t[e].setValueRange(i,s)},M.prototype.redraw=function(){this.setSize(this.width,this.height),this._redraw()},M.prototype._redraw=function(){var t=this.frame.canvas.getContext("2d"),e=this.frame.canvas.width,i=this.frame.canvas.height;t.clearRect(0,0,e,i),t.save(),t.translate(this.translation.x,this.translation.y),t.scale(this.scale,this.scale),this._drawEdges(t),this._drawNodes(t),t.restore()},M.prototype._setTranslation=function(t,e){void 0===this.translation&&(this.translation={x:0,y:0}),void 0!==t&&(this.translation.x=t),void 0!==e&&(this.translation.y=e)},M.prototype._getTranslation=function(){return{x:this.translation.x,y:this.translation.y}},M.prototype._setScale=function(t){this.scale=t},M.prototype._getScale=function(){return this.scale},M.prototype._xToCanvas=function(t){return(t-this.translation.x)/this.scale},M.prototype._canvasToX=function(t){return t*this.scale+this.translation.x},M.prototype._yToCanvas=function(t){return(t-this.translation.y)/this.scale},M.prototype._canvasToY=function(t){return t*this.scale+this.translation.y},M.prototype._drawNodes=function(t){var e=this.nodes,i=[];for(var s in e)e.hasOwnProperty(s)&&(e[s].isSelected()?i.push(s):e[s].draw(t));for(var n=0,o=i.length;o>n;n++)e[i[n]].draw(t)},M.prototype._drawEdges=function(t){var e=this.edges;for(var i in e)if(e.hasOwnProperty(i)){var s=e[i];s.connected&&e[i].draw(t)}},M.prototype._doStabilize=function(){new Date;for(var t=0,e=this.constants.minVelocity,i=!1;!i&&this.constants.maxIterations>t;)this._calculateForces(),this._discreteStepNodes(),i=!this._isMoving(e),t++;new Date},M.prototype._calculateForces=function(){var t,e,i,s,n,o,r,a,h,d,l,p=this.nodes,c=this.edges,u=.01,f=this.frame.canvas.clientWidth/2,m=this.frame.canvas.clientHeight/2;for(t in p)if(p.hasOwnProperty(t)){var g=p[t];e=f-g.x,i=m-g.y,s=Math.atan2(i,e),o=Math.cos(s)*u,r=Math.sin(s)*u,g._setForce(o,r)}var v=this.constants.nodes.distance,y=10;for(var b in p)if(p.hasOwnProperty(b)){var w=p[b];for(var _ in p)if(p.hasOwnProperty(_)){var x=p[_];e=x.x-w.x,i=x.y-w.y,n=Math.sqrt(e*e+i*i),s=Math.atan2(i,e),a=1/(1+Math.exp((n/v-1)*y)),o=Math.cos(s)*a,r=Math.sin(s)*a,w._addForce(-o,-r),x._addForce(o,r)}}for(t in c)if(c.hasOwnProperty(t)){var T=c[t];T.connected&&(e=T.to.x-T.from.x,i=T.to.y-T.from.y,l=T.length,d=Math.sqrt(e*e+i*i),s=Math.atan2(i,e),h=T.stiffness*(l-d),o=Math.cos(s)*h,r=Math.sin(s)*h,T.from._addForce(-o,-r),T.to._addForce(o,r))}},M.prototype._isMoving=function(t){var e=this.nodes;for(var i in e)if(e.hasOwnProperty(i)&&e[i].isMoving(t))return!0;return!1},M.prototype._discreteStepNodes=function(){var t=this.refreshRate/1e3,e=this.nodes;for(var i in e)e.hasOwnProperty(i)&&e[i].discreteStep(t)},M.prototype.start=function(){if(this.moving){this._calculateForces(),this._discreteStepNodes();var t=this.constants.minVelocity;this.moving=this._isMoving(t)}if(this.moving){if(!this.timer){var e=this;this.timer=window.setTimeout(function(){e.timer=void 0,e.start(),e._redraw()},this.refreshRate)}}else this._redraw()},M.prototype.stop=function(){this.timer&&(window.clearInterval(this.timer),this.timer=void 0)};var N={util:D,events:O,Controller:d,DataSet:o,DataView:r,Range:h,Stack:a,TimeStep:TimeStep,EventBus:n,components:{items:{Item:m,ItemBox:g,ItemPoint:v,ItemRange:y},Component:l,Panel:p,RootPanel:c,ItemSet:f,TimeAxis:u},graph:{Node:x,Edge:T,Popup:S,Groups:Groups,Images:Images},Timeline:_,Graph:M};s!==void 0&&(s=N),i!==void 0&&i.exports!==void 0&&(i.exports=N),"function"==typeof t&&t(function(){return N}),"undefined"!=typeof window&&(window.vis=N),D.loadCss("/* vis.js stylesheet */\n.vis.timeline {\n}\n\n\n.vis.timeline.rootpanel {\n position: relative;\n overflow: hidden;\n\n border: 1px solid #bfbfbf;\n -moz-box-sizing: border-box;\n box-sizing: border-box;\n}\n\n.vis.timeline .panel {\n position: absolute;\n overflow: hidden;\n}\n\n\n.vis.timeline .groupset {\n position: absolute;\n padding: 0;\n margin: 0;\n}\n\n.vis.timeline .labels {\n position: absolute;\n top: 0;\n left: 0;\n width: 100%;\n height: 100%;\n\n padding: 0;\n margin: 0;\n\n border-right: 1px solid #bfbfbf;\n box-sizing: border-box;\n -moz-box-sizing: border-box;\n}\n\n.vis.timeline .labels .label {\n position: absolute;\n left: 0;\n top: 0;\n width: 100%;\n border-bottom: 1px solid #bfbfbf;\n color: #4d4d4d;\n}\n\n.vis.timeline .labels .label .inner {\n display: inline-block;\n padding: 5px;\n}\n\n\n.vis.timeline .itemset {\n position: absolute;\n padding: 0;\n margin: 0;\n overflow: hidden;\n}\n\n.vis.timeline .background {\n}\n\n.vis.timeline .foreground {\n}\n\n.vis.timeline .itemset-axis {\n position: absolute;\n}\n\n.vis.timeline .groupset .itemset-axis {\n border-top: 1px solid #bfbfbf;\n}\n\n/* TODO: with orientation=='bottom', this will more or less overlap with timeline axis\n.vis.timeline .groupset .itemset-axis:last-child {\n border-top: none;\n}\n*/\n\n\n.vis.timeline .item {\n position: absolute;\n color: #1A1A1A;\n border-color: #97B0F8;\n background-color: #D5DDF6;\n display: inline-block;\n}\n\n.vis.timeline .item.selected {\n border-color: #FFC200;\n background-color: #FFF785;\n z-index: 999;\n}\n\n.vis.timeline .item.cluster {\n /* TODO: use another color or pattern? */\n background: #97B0F8 url('img/cluster_bg.png');\n color: white;\n}\n.vis.timeline .item.cluster.point {\n border-color: #D5DDF6;\n}\n\n.vis.timeline .item.box {\n text-align: center;\n border-style: solid;\n border-width: 1px;\n border-radius: 5px;\n -moz-border-radius: 5px; /* For Firefox 3.6 and older */\n}\n\n.vis.timeline .item.point {\n background: none;\n}\n\n.vis.timeline .dot {\n border: 5px solid #97B0F8;\n position: absolute;\n border-radius: 5px;\n -moz-border-radius: 5px; /* For Firefox 3.6 and older */\n}\n\n.vis.timeline .item.range {\n overflow: hidden;\n border-style: solid;\n border-width: 1px;\n border-radius: 2px;\n -moz-border-radius: 2px; /* For Firefox 3.6 and older */\n}\n\n.vis.timeline .item.range .drag-left {\n cursor: w-resize;\n z-index: 1000;\n}\n\n.vis.timeline .item.range .drag-right {\n cursor: e-resize;\n z-index: 1000;\n}\n\n.vis.timeline .item.range .content {\n position: relative;\n display: inline-block;\n}\n\n.vis.timeline .item.line {\n position: absolute;\n width: 0;\n border-left-width: 1px;\n border-left-style: solid;\n}\n\n.vis.timeline .item .content {\n margin: 5px;\n white-space: nowrap;\n overflow: hidden;\n}\n\n.vis.timeline .axis {\n position: relative;\n}\n\n.vis.timeline .axis .text {\n position: absolute;\n color: #4d4d4d;\n padding: 3px;\n white-space: nowrap;\n}\n\n.vis.timeline .axis .text.measure {\n position: absolute;\n padding-left: 0;\n padding-right: 0;\n margin-left: 0;\n margin-right: 0;\n visibility: hidden;\n}\n\n.vis.timeline .axis .grid.vertical {\n position: absolute;\n width: 0;\n border-right: 1px solid;\n}\n\n.vis.timeline .axis .grid.horizontal {\n position: absolute;\n left: 0;\n width: 100%;\n height: 0;\n border-bottom: 1px solid;\n}\n\n.vis.timeline .axis .grid.minor {\n border-color: #e5e5e5;\n}\n\n.vis.timeline .axis .grid.major {\n border-color: #bfbfbf;\n}\n\n")})()},{moment:2}],2:[function(e,i){(function(){(function(s){function n(t,e){return function(i){return p(t.call(this,i),e)}}function o(t){return function(e){return this.lang().ordinal(t.call(this,e))}}function r(){}function a(t){d(this,t)}function h(t){var e=this._data={},i=t.years||t.year||t.y||0,s=t.months||t.month||t.M||0,n=t.weeks||t.week||t.w||0,o=t.days||t.day||t.d||0,r=t.hours||t.hour||t.h||0,a=t.minutes||t.minute||t.m||0,h=t.seconds||t.second||t.s||0,d=t.milliseconds||t.millisecond||t.ms||0;this._milliseconds=d+1e3*h+6e4*a+36e5*r,this._days=o+7*n,this._months=s+12*i,e.milliseconds=d%1e3,h+=l(d/1e3),e.seconds=h%60,a+=l(h/60),e.minutes=a%60,r+=l(a/60),e.hours=r%24,o+=l(r/24),o+=7*n,e.days=o%30,s+=l(o/30),e.months=s%12,i+=l(s/12),e.years=i}function d(t,e){for(var i in e)e.hasOwnProperty(i)&&(t[i]=e[i]);return t}function l(t){return 0>t?Math.ceil(t):Math.floor(t)}function p(t,e){for(var i=t+"";e>i.length;)i="0"+i;return i}function c(t,e,i){var s,n=e._milliseconds,o=e._days,r=e._months;n&&t._d.setTime(+t+n*i),o&&t.date(t.date()+o*i),r&&(s=t.date(),t.date(1).month(t.month()+r*i).date(Math.min(s,t.daysInMonth())))}function u(t){return"[object Array]"===Object.prototype.toString.call(t)}function f(t,e){var i,s=Math.min(t.length,e.length),n=Math.abs(t.length-e.length),o=0;for(i=0;s>i;i++)~~t[i]!==~~e[i]&&o++;return o+n}function m(t,e){return e.abbr=t,z[t]||(z[t]=new r),z[t].set(e),z[t]}function g(t){return t?(!z[t]&&R&&e("./lang/"+t),z[t]):I.fn._lang}function v(t){return t.match(/\[.*\]/)?t.replace(/^\[|\]$/g,""):t.replace(/\\/g,"")}function y(t){var e,i,s=t.match(j);for(e=0,i=s.length;i>e;e++)s[e]=ae[s[e]]?ae[s[e]]:v(s[e]);return function(n){var o="";for(e=0;i>e;e++)o+="function"==typeof s[e].call?s[e].call(n,t):s[e];return o}}function b(t,e){function i(e){return t.lang().longDateFormat(e)||e}for(var s=5;s--&&U.test(e);)e=e.replace(U,i);return ne[e]||(ne[e]=y(e)),ne[e](t)}function w(t){switch(t){case"DDDD":return q;case"YYYY":return V;case"YYYYY":return X;case"S":case"SS":case"SSS":case"DDD":return B;case"MMM":case"MMMM":case"dd":case"ddd":case"dddd":case"a":case"A":return K;case"X":return J;case"Z":case"ZZ":return G;case"T":return Z;case"MM":case"DD":case"YY":case"HH":case"hh":case"mm":case"ss":case"M":case"D":case"d":case"H":case"h":case"m":case"s":return W;default:return RegExp(t.replace("\\",""))}}function _(t,e,i){var s,n=i._a;switch(t){case"M":case"MM":n[1]=null==e?0:~~e-1;break;case"MMM":case"MMMM":s=g(i._l).monthsParse(e),null!=s?n[1]=s:i._isValid=!1;break;case"D":case"DD":case"DDD":case"DDDD":null!=e&&(n[2]=~~e);break;case"YY":n[0]=~~e+(~~e>68?1900:2e3);break;case"YYYY":case"YYYYY":n[0]=~~e;break;case"a":case"A":i._isPm="pm"===(e+"").toLowerCase();break;case"H":case"HH":case"h":case"hh":n[3]=~~e;break;case"m":case"mm":n[4]=~~e;break;case"s":case"ss":n[5]=~~e;break;case"S":case"SS":case"SSS":n[6]=~~(1e3*("0."+e));break;case"X":i._d=new Date(1e3*parseFloat(e));break;case"Z":case"ZZ":i._useUTC=!0,s=(e+"").match(ee),s&&s[1]&&(i._tzh=~~s[1]),s&&s[2]&&(i._tzm=~~s[2]),s&&"+"===s[0]&&(i._tzh=-i._tzh,i._tzm=-i._tzm)}null==e&&(i._isValid=!1)}function x(t){var e,i,s=[];if(!t._d){for(e=0;7>e;e++)t._a[e]=s[e]=null==t._a[e]?2===e?1:0:t._a[e];s[3]+=t._tzh||0,s[4]+=t._tzm||0,i=new Date(0),t._useUTC?(i.setUTCFullYear(s[0],s[1],s[2]),i.setUTCHours(s[3],s[4],s[5],s[6])):(i.setFullYear(s[0],s[1],s[2]),i.setHours(s[3],s[4],s[5],s[6])),t._d=i}}function T(t){var e,i,s=t._f.match(j),n=t._i;for(t._a=[],e=0;s.length>e;e++)i=(w(s[e]).exec(n)||[])[0],i&&(n=n.slice(n.indexOf(i)+i.length)),ae[s[e]]&&_(s[e],i,t);t._isPm&&12>t._a[3]&&(t._a[3]+=12),t._isPm===!1&&12===t._a[3]&&(t._a[3]=0),x(t)}function S(t){for(var e,i,s,n,o=99;t._f.length;){if(e=d({},t),e._f=t._f.pop(),T(e),i=new a(e),i.isValid()){s=i;break}n=f(e._a,i.toArray()),o>n&&(o=n,s=i)}d(t,s)}function M(t){var e,i=t._i;if(Q.exec(i)){for(t._f="YYYY-MM-DDT",e=0;4>e;e++)if(te[e][1].exec(i)){t._f+=te[e][0];break}G.exec(i)&&(t._f+=" Z"),T(t)}else t._d=new Date(i)}function E(t){var e=t._i,i=H.exec(e);e===s?t._d=new Date:i?t._d=new Date(+i[1]):"string"==typeof e?M(t):u(e)?(t._a=e.slice(0),x(t)):t._d=e instanceof Date?new Date(+e):new Date(e)}function D(t,e,i,s,n){return n.relativeTime(e||1,!!i,t,s)}function C(t,e,i){var s=Y(Math.abs(t)/1e3),n=Y(s/60),o=Y(n/60),r=Y(o/24),a=Y(r/365),h=45>s&&["s",s]||1===n&&["m"]||45>n&&["mm",n]||1===o&&["h"]||22>o&&["hh",o]||1===r&&["d"]||25>=r&&["dd",r]||45>=r&&["M"]||345>r&&["MM",Y(r/30)]||1===a&&["y"]||["yy",a];return h[2]=e,h[3]=t>0,h[4]=i,D.apply({},h)}function L(t,e,i){var s=i-e,n=i-t.day();return n>s&&(n-=7),s-7>n&&(n+=7),Math.ceil(I(t).add("d",n).dayOfYear()/7)}function O(t){var e=t._i,i=t._f;return null===e||""===e?null:("string"==typeof e&&(t._i=e=g().preparse(e)),I.isMoment(e)?(t=d({},e),t._d=new Date(+e._d)):i?u(i)?S(t):T(t):E(t),new a(t))}function N(t,e){I.fn[t]=I.fn[t+"s"]=function(t){var i=this._isUTC?"UTC":"";return null!=t?(this._d["set"+i+e](t),this):this._d["get"+i+e]()}}function A(t){I.duration.fn[t]=function(){return this._data[t]}}function k(t,e){I.duration.fn["as"+t]=function(){return+this/e}}for(var I,F,P="2.0.0",Y=Math.round,z={},R=i!==s&&i.exports,H=/^\/?Date\((\-?\d+)/i,j=/(\[[^\[]*\])|(\\)?(Mo|MM?M?M?|Do|DDDo|DD?D?D?|ddd?d?|do?|w[o|w]?|W[o|W]?|YYYYY|YYYY|YY|a|A|hh?|HH?|mm?|ss?|SS?S?|X|zz?|ZZ?|.)/g,U=/(\[[^\[]*\])|(\\)?(LT|LL?L?L?|l{1,4})/g,W=/\d\d?/,B=/\d{1,3}/,q=/\d{3}/,V=/\d{1,4}/,X=/[+\-]?\d{1,6}/,K=/[0-9]*[a-z\u00A0-\u05FF\u0700-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF]+|[\u0600-\u06FF]+\s*?[\u0600-\u06FF]+/i,G=/Z|[\+\-]\d\d:?\d\d/i,Z=/T/i,J=/[\+\-]?\d+(\.\d{1,3})?/,Q=/^\s*\d{4}-\d\d-\d\d((T| )(\d\d(:\d\d(:\d\d(\.\d\d?\d?)?)?)?)?([\+\-]\d\d:?\d\d)?)?/,$="YYYY-MM-DDTHH:mm:ssZ",te=[["HH:mm:ss.S",/(T| )\d\d:\d\d:\d\d\.\d{1,3}/],["HH:mm:ss",/(T| )\d\d:\d\d:\d\d/],["HH:mm",/(T| )\d\d:\d\d/],["HH",/(T| )\d\d/]],ee=/([\+\-]|\d\d)/gi,ie="Month|Date|Hours|Minutes|Seconds|Milliseconds".split("|"),se={Milliseconds:1,Seconds:1e3,Minutes:6e4,Hours:36e5,Days:864e5,Months:2592e6,Years:31536e6},ne={},oe="DDD w W M D d".split(" "),re="M D H h m s w W".split(" "),ae={M:function(){return this.month()+1},MMM:function(t){return this.lang().monthsShort(this,t)},MMMM:function(t){return this.lang().months(this,t)},D:function(){return this.date()},DDD:function(){return this.dayOfYear()},d:function(){return this.day()},dd:function(t){return this.lang().weekdaysMin(this,t)},ddd:function(t){return this.lang().weekdaysShort(this,t)},dddd:function(t){return this.lang().weekdays(this,t)},w:function(){return this.week()},W:function(){return this.isoWeek()},YY:function(){return p(this.year()%100,2)},YYYY:function(){return p(this.year(),4)},YYYYY:function(){return p(this.year(),5)},a:function(){return this.lang().meridiem(this.hours(),this.minutes(),!0)},A:function(){return this.lang().meridiem(this.hours(),this.minutes(),!1)},H:function(){return this.hours()},h:function(){return this.hours()%12||12},m:function(){return this.minutes()},s:function(){return this.seconds()},S:function(){return~~(this.milliseconds()/100)},SS:function(){return p(~~(this.milliseconds()/10),2)},SSS:function(){return p(this.milliseconds(),3)},Z:function(){var t=-this.zone(),e="+";return 0>t&&(t=-t,e="-"),e+p(~~(t/60),2)+":"+p(~~t%60,2)},ZZ:function(){var t=-this.zone(),e="+";return 0>t&&(t=-t,e="-"),e+p(~~(10*t/6),4)},X:function(){return this.unix()}};oe.length;)F=oe.pop(),ae[F+"o"]=o(ae[F]);for(;re.length;)F=re.pop(),ae[F+F]=n(ae[F],2);for(ae.DDDD=n(ae.DDD,3),r.prototype={set:function(t){var e,i; +for(i in t)e=t[i],"function"==typeof e?this[i]=e:this["_"+i]=e},_months:"January_February_March_April_May_June_July_August_September_October_November_December".split("_"),months:function(t){return this._months[t.month()]},_monthsShort:"Jan_Feb_Mar_Apr_May_Jun_Jul_Aug_Sep_Oct_Nov_Dec".split("_"),monthsShort:function(t){return this._monthsShort[t.month()]},monthsParse:function(t){var e,i,s;for(this._monthsParse||(this._monthsParse=[]),e=0;12>e;e++)if(this._monthsParse[e]||(i=I([2e3,e]),s="^"+this.months(i,"")+"|^"+this.monthsShort(i,""),this._monthsParse[e]=RegExp(s.replace(".",""),"i")),this._monthsParse[e].test(t))return e},_weekdays:"Sunday_Monday_Tuesday_Wednesday_Thursday_Friday_Saturday".split("_"),weekdays:function(t){return this._weekdays[t.day()]},_weekdaysShort:"Sun_Mon_Tue_Wed_Thu_Fri_Sat".split("_"),weekdaysShort:function(t){return this._weekdaysShort[t.day()]},_weekdaysMin:"Su_Mo_Tu_We_Th_Fr_Sa".split("_"),weekdaysMin:function(t){return this._weekdaysMin[t.day()]},_longDateFormat:{LT:"h:mm A",L:"MM/DD/YYYY",LL:"MMMM D YYYY",LLL:"MMMM D YYYY LT",LLLL:"dddd, MMMM D YYYY LT"},longDateFormat:function(t){var e=this._longDateFormat[t];return!e&&this._longDateFormat[t.toUpperCase()]&&(e=this._longDateFormat[t.toUpperCase()].replace(/MMMM|MM|DD|dddd/g,function(t){return t.slice(1)}),this._longDateFormat[t]=e),e},meridiem:function(t,e,i){return t>11?i?"pm":"PM":i?"am":"AM"},_calendar:{sameDay:"[Today at] LT",nextDay:"[Tomorrow at] LT",nextWeek:"dddd [at] LT",lastDay:"[Yesterday at] LT",lastWeek:"[last] dddd [at] LT",sameElse:"L"},calendar:function(t,e){var i=this._calendar[t];return"function"==typeof i?i.apply(e):i},_relativeTime:{future:"in %s",past:"%s ago",s:"a few seconds",m:"a minute",mm:"%d minutes",h:"an hour",hh:"%d hours",d:"a day",dd:"%d days",M:"a month",MM:"%d months",y:"a year",yy:"%d years"},relativeTime:function(t,e,i,s){var n=this._relativeTime[i];return"function"==typeof n?n(t,e,i,s):n.replace(/%d/i,t)},pastFuture:function(t,e){var i=this._relativeTime[t>0?"future":"past"];return"function"==typeof i?i(e):i.replace(/%s/i,e)},ordinal:function(t){return this._ordinal.replace("%d",t)},_ordinal:"%d",preparse:function(t){return t},postformat:function(t){return t},week:function(t){return L(t,this._week.dow,this._week.doy)},_week:{dow:0,doy:6}},I=function(t,e,i){return O({_i:t,_f:e,_l:i,_isUTC:!1})},I.utc=function(t,e,i){return O({_useUTC:!0,_isUTC:!0,_l:i,_i:t,_f:e})},I.unix=function(t){return I(1e3*t)},I.duration=function(t,e){var i,s=I.isDuration(t),n="number"==typeof t,o=s?t._data:n?{}:t;return n&&(e?o[e]=t:o.milliseconds=t),i=new h(o),s&&t.hasOwnProperty("_lang")&&(i._lang=t._lang),i},I.version=P,I.defaultFormat=$,I.lang=function(t,e){return t?(e?m(t,e):z[t]||g(t),I.duration.fn._lang=I.fn._lang=g(t),s):I.fn._lang._abbr},I.langData=function(t){return t&&t._lang&&t._lang._abbr&&(t=t._lang._abbr),g(t)},I.isMoment=function(t){return t instanceof a},I.isDuration=function(t){return t instanceof h},I.fn=a.prototype={clone:function(){return I(this)},valueOf:function(){return+this._d},unix:function(){return Math.floor(+this._d/1e3)},toString:function(){return this.format("ddd MMM DD YYYY HH:mm:ss [GMT]ZZ")},toDate:function(){return this._d},toJSON:function(){return I.utc(this).format("YYYY-MM-DD[T]HH:mm:ss.SSS[Z]")},toArray:function(){var t=this;return[t.year(),t.month(),t.date(),t.hours(),t.minutes(),t.seconds(),t.milliseconds()]},isValid:function(){return null==this._isValid&&(this._isValid=this._a?!f(this._a,(this._isUTC?I.utc(this._a):I(this._a)).toArray()):!isNaN(this._d.getTime())),!!this._isValid},utc:function(){return this._isUTC=!0,this},local:function(){return this._isUTC=!1,this},format:function(t){var e=b(this,t||I.defaultFormat);return this.lang().postformat(e)},add:function(t,e){var i;return i="string"==typeof t?I.duration(+e,t):I.duration(t,e),c(this,i,1),this},subtract:function(t,e){var i;return i="string"==typeof t?I.duration(+e,t):I.duration(t,e),c(this,i,-1),this},diff:function(t,e,i){var s,n,o=this._isUTC?I(t).utc():I(t).local(),r=6e4*(this.zone()-o.zone());return e&&(e=e.replace(/s$/,"")),"year"===e||"month"===e?(s=432e5*(this.daysInMonth()+o.daysInMonth()),n=12*(this.year()-o.year())+(this.month()-o.month()),n+=(this-I(this).startOf("month")-(o-I(o).startOf("month")))/s,"year"===e&&(n/=12)):(s=this-o-r,n="second"===e?s/1e3:"minute"===e?s/6e4:"hour"===e?s/36e5:"day"===e?s/864e5:"week"===e?s/6048e5:s),i?n:l(n)},from:function(t,e){return I.duration(this.diff(t)).lang(this.lang()._abbr).humanize(!e)},fromNow:function(t){return this.from(I(),t)},calendar:function(){var t=this.diff(I().startOf("day"),"days",!0),e=-6>t?"sameElse":-1>t?"lastWeek":0>t?"lastDay":1>t?"sameDay":2>t?"nextDay":7>t?"nextWeek":"sameElse";return this.format(this.lang().calendar(e,this))},isLeapYear:function(){var t=this.year();return 0===t%4&&0!==t%100||0===t%400},isDST:function(){return this.zone()+I(t).startOf(e)},isBefore:function(t,e){return e=e!==s?e:"millisecond",+this.clone().startOf(e)<+I(t).startOf(e)},isSame:function(t,e){return e=e!==s?e:"millisecond",+this.clone().startOf(e)===+I(t).startOf(e)},zone:function(){return this._isUTC?0:this._d.getTimezoneOffset()},daysInMonth:function(){return I.utc([this.year(),this.month()+1,0]).date()},dayOfYear:function(t){var e=Y((I(this).startOf("day")-I(this).startOf("year"))/864e5)+1;return null==t?e:this.add("d",t-e)},isoWeek:function(t){var e=L(this,1,4);return null==t?e:this.add("d",7*(t-e))},week:function(t){var e=this.lang().week(this);return null==t?e:this.add("d",7*(t-e))},lang:function(t){return t===s?this._lang:(this._lang=g(t),this)}},F=0;ie.length>F;F++)N(ie[F].toLowerCase().replace(/s$/,""),ie[F]);N("year","FullYear"),I.fn.days=I.fn.day,I.fn.weeks=I.fn.week,I.fn.isoWeeks=I.fn.isoWeek,I.duration.fn=h.prototype={weeks:function(){return l(this.days()/7)},valueOf:function(){return this._milliseconds+864e5*this._days+2592e6*this._months},humanize:function(t){var e=+this,i=C(e,!t,this.lang());return t&&(i=this.lang().pastFuture(e,i)),this.lang().postformat(i)},lang:I.fn.lang};for(F in se)se.hasOwnProperty(F)&&(k(F,se[F]),A(F.toLowerCase()));k("Weeks",6048e5),I.lang("en",{ordinal:function(t){var e=t%10,i=1===~~(t%100/10)?"th":1===e?"st":2===e?"nd":3===e?"rd":"th";return t+i}}),R&&(i.exports=I),"undefined"==typeof ender&&(this.moment=I),"function"==typeof t&&t.amd&&t("moment",[],function(){return I})}).call(this)})()},{}]},{},[1])(1)}); \ No newline at end of file From 7011fe20b3b8be735846ec4c3bdc69da2638f480 Mon Sep 17 00:00:00 2001 From: josdejong Date: Tue, 17 Sep 2013 11:36:29 +0200 Subject: [PATCH 03/18] Implemented full touch support for Graph using hammer.js --- Jakefile.js | 1 + examples/timeline/02_dataset.html | 3 + examples/timeline/03_much_data.html | 3 + examples/timeline/05_groups.html | 3 + package.json | 3 +- src/graph/Graph.js | 515 +- src/module/imports.js | 6 +- src/shim.js | 252 + src/util.js | 228 - vis.js | 22596 ++++++++++++++------------ vis.min.js | 12 +- 11 files changed, 12656 insertions(+), 10966 deletions(-) create mode 100644 src/shim.js diff --git a/Jakefile.js b/Jakefile.js index f583e98e..b54781e3 100644 --- a/Jakefile.js +++ b/Jakefile.js @@ -47,6 +47,7 @@ task('build', {async: true}, function () { src: [ './src/module/imports.js', + './src/shim.js', './src/util.js', './src/events.js', './src/EventBus.js', diff --git a/examples/timeline/02_dataset.html b/examples/timeline/02_dataset.html index c1987abd..ad74d2d5 100644 --- a/examples/timeline/02_dataset.html +++ b/examples/timeline/02_dataset.html @@ -19,6 +19,9 @@ } + + + diff --git a/examples/timeline/03_much_data.html b/examples/timeline/03_much_data.html index 5d778975..db94f807 100644 --- a/examples/timeline/03_much_data.html +++ b/examples/timeline/03_much_data.html @@ -10,6 +10,9 @@ } + + + diff --git a/examples/timeline/05_groups.html b/examples/timeline/05_groups.html index 880a7326..17b85200 100644 --- a/examples/timeline/05_groups.html +++ b/examples/timeline/05_groups.html @@ -16,6 +16,9 @@ } + + + diff --git a/package.json b/package.json index 29464d23..a9333fee 100644 --- a/package.json +++ b/package.json @@ -28,6 +28,7 @@ "jake": "latest", "jake-utils": "latest", "browserify": "latest", - "moment": "latest" + "moment": "latest", + "hammerjs": "latest" } } diff --git a/src/graph/Graph.js b/src/graph/Graph.js index c4c6b315..6e3ec79a 100644 --- a/src/graph/Graph.js +++ b/src/graph/Graph.js @@ -291,137 +291,116 @@ Graph.prototype._create = function () { this.frame.canvas.appendChild(noCanvas); } - // create event listeners var me = this; - var onmousedown = function (event) {me._onMouseDown(event);}; - var onmousemove = function (event) {me._onMouseMoveTitle(event);}; - var onmousewheel = function (event) {me._onMouseWheel(event);}; - var ontouchstart = function (event) {me._onTouchStart(event);}; - vis.util.addEventListener(this.frame.canvas, "mousedown", onmousedown); - vis.util.addEventListener(this.frame.canvas, "mousemove", onmousemove); - vis.util.addEventListener(this.frame.canvas, "mousewheel", onmousewheel); - vis.util.addEventListener(this.frame.canvas, "touchstart", ontouchstart); + this.drag = {}; + this.pinch = {}; + this.hammer = Hammer(this.frame.canvas, { + prevent_default: true + }); + this.hammer.on('tap', me._onTap.bind(me) ); + this.hammer.on('hold', me._onHold.bind(me) ); + this.hammer.on('pinch', me._onPinch.bind(me) ); + this.hammer.on('touch', me._onTouch.bind(me) ); + this.hammer.on('dragstart', me._onDragStart.bind(me) ); + this.hammer.on('drag', me._onDrag.bind(me) ); + this.hammer.on('dragend', me._onDragEnd.bind(me) ); + this.hammer.on('mousewheel',me._onMouseWheel.bind(me) ); + this.hammer.on('mousemove', me._onMouseMoveTitle.bind(me) ); // add the frame to the container element this.containerElement.appendChild(this.frame); }; /** - * handle on mouse down event + * + * @param {{x: Number, y: Number}} pointer + * @return {Number | null} node * @private */ -Graph.prototype._onMouseDown = function (event) { - event = event || window.event; +Graph.prototype._getNodeAt = function (pointer) { + var x = this._xToCanvas(pointer.x); + var y = this._yToCanvas(pointer.y); - if (!this.selectable) { - return; - } + var obj = { + left: x, + top: y, + right: x, + bottom: y + }; - // check if mouse is still down (may be up when focus is lost for example - // in an iframe) - if (this.leftButtonDown) { - this._onMouseUp(event); - } + // if there are overlapping nodes, select the last one, this is the + // one which is drawn on top of the others + var overlappingNodes = this._getNodesOverlappingWith(obj); + return (overlappingNodes.length > 0) ? + overlappingNodes[overlappingNodes.length - 1] : null; +}; - // only react on left mouse button down - this.leftButtonDown = event.which ? (event.which == 1) : (event.button == 1); - if (!this.leftButtonDown && !this.touchDown) { - return; - } +/** + * Get the pointer location from a touch location + * @param {{pageX: Number, pageY: Number}} touch + * @return {{x: Number, y: Number}} pointer + * @private + */ +Graph.prototype._getPointer = function (touch) { + return { + x: touch.pageX - vis.util.getAbsoluteLeft(this.frame.canvas), + y: touch.pageY - vis.util.getAbsoluteTop(this.frame.canvas) + }; +}; - // add event listeners to handle moving the contents - // we store the function onmousemove and onmouseup in the timeline, so we can - // remove the eventlisteners lateron in the function mouseUp() - var me = this; - if (!this.onmousemove) { - this.onmousemove = function (event) {me._onMouseMove(event);}; - vis.util.addEventListener(document, "mousemove", me.onmousemove); - } - if (!this.onmouseup) { - this.onmouseup = function (event) {me._onMouseUp(event);}; - vis.util.addEventListener(document, "mouseup", me.onmouseup); - } - vis.util.preventDefault(event); +/** + * On start of a touch gesture, store the pointer + * @param event + * @private + */ +Graph.prototype._onTouch = function (event) { + this.drag.pointer = this._getPointer(event.gesture.touches[0]); + this.drag.pinched = false; + this.pinch.scale = this._getScale(); +}; - // store the start x and y position of the mouse - this.startMouseX = util.getPageX(event); - this.startMouseY = util.getPageY(event); - this.startFrameLeft = vis.util.getAbsoluteLeft(this.frame.canvas); - this.startFrameTop = vis.util.getAbsoluteTop(this.frame.canvas); - this.startTranslation = this._getTranslation(); +/** + * handle drag start event + * @private + */ +Graph.prototype._onDragStart = function (event) { + var drag = this.drag; - this.ctrlKeyDown = event.ctrlKey; - this.shiftKeyDown = event.shiftKey; + drag.translation = this._getTranslation(); - var obj = { - left: this._xToCanvas(this.startMouseX - this.startFrameLeft), - top: this._yToCanvas(this.startMouseY - this.startFrameTop), - right: this._xToCanvas(this.startMouseX - this.startFrameLeft), - bottom: this._yToCanvas(this.startMouseY - this.startFrameTop) - }; - var overlappingNodes = this._getNodesOverlappingWith(obj); - // if there are overlapping nodes, select the last one, this is the - // one which is drawn on top of the others - this.startClickedObj = (overlappingNodes.length > 0) ? - overlappingNodes[overlappingNodes.length - 1] : undefined; - - if (this.startClickedObj) { - // move clicked node with the mouse - - // make the clicked node temporarily fixed, and store their original state - var node = this.nodes[this.startClickedObj]; - this.startClickedObj.xFixed = node.xFixed; - this.startClickedObj.yFixed = node.yFixed; - node.xFixed = true; - node.yFixed = true; - - if (!this.ctrlKeyDown || !node.isSelected()) { - // select this node - this._selectNodes([this.startClickedObj], this.ctrlKeyDown); - } - else { - // unselect this node - this._unselectNodes([this.startClickedObj]); - } + // note: drag.pointer is set in _onTouch to get the initial touch location + drag.nodeId = this._getNodeAt(drag.pointer); + drag.node = this.nodes[drag.nodeId]; + if (drag.node) { + this._selectNodes([drag.nodeId]); - if (!this.moving) { - this._redraw(); - } - } - else if (this.shiftKeyDown) { - // start selection of multiple nodes - } - else { - // start moving the graph - this.moved = false; + // store original xFixed and yFixed, make the node temporarily Fixed + drag.xFixed = drag.node.xFixed; + drag.yFixed = drag.node.yFixed; + drag.node.xFixed = true; + drag.node.yFixed = true; } }; /** - * handle on mouse move event - * @param {Event} event + * handle drag event * @private */ -Graph.prototype._onMouseMove = function (event) { - event = event || window.event; - - if (!this.selectable) { +Graph.prototype._onDrag = function (event) { + if (this.drag.pinched) { return; } - var mouseX = util.getPageX(event); - var mouseY = util.getPageY(event); - this.mouseX = mouseX; - this.mouseY = mouseY; - - if (this.startClickedObj) { - var node = this.nodes[this.startClickedObj]; + var pointer = this._getPointer(event.gesture.touches[0]); - if (!this.startClickedObj.xFixed) - node.x = this._xToCanvas(mouseX - this.startFrameLeft); + var drag= this.drag, + node = drag.node; + if (node) { + if (!drag.xFixed) + node.x = this._xToCanvas(pointer.x); - if (!this.startClickedObj.yFixed) - node.y = this._yToCanvas(mouseY - this.startFrameTop); + if (!drag.yFixed) + node.y = this._yToCanvas(pointer.y); // start animation if not yet running if (!this.moving) { @@ -429,119 +408,140 @@ Graph.prototype._onMouseMove = function (event) { this.start(); } } - else if (this.shiftKeyDown) { - // draw a rect from start mouse location to current mouse location - if (this.frame.selRect == undefined) { - this.frame.selRect = document.createElement("DIV"); - this.frame.appendChild(this.frame.selRect); - - this.frame.selRect.style.position = "absolute"; - this.frame.selRect.style.border = "1px dashed red"; - } - - var left = Math.min(this.startMouseX, mouseX) - this.startFrameLeft; - var top = Math.min(this.startMouseY, mouseY) - this.startFrameTop; - var right = Math.max(this.startMouseX, mouseX) - this.startFrameLeft; - var bottom = Math.max(this.startMouseY, mouseY) - this.startFrameTop; - - this.frame.selRect.style.left = left + "px"; - this.frame.selRect.style.top = top + "px"; - this.frame.selRect.style.width = (right - left) + "px"; - this.frame.selRect.style.height = (bottom - top) + "px"; - } else { // move the graph - var diffX = mouseX - this.startMouseX; - var diffY = mouseY - this.startMouseY; + var diffX = pointer.x - this.drag.pointer.x; + var diffY = pointer.y - this.drag.pointer.y; this._setTranslation( - this.startTranslation.x + diffX, - this.startTranslation.y + diffY); + this.drag.translation.x + diffX, + this.drag.translation.y + diffY); this._redraw(); this.moved = true; } - - vis.util.preventDefault(event); }; /** - * handle on mouse up event - * @param {Event} event + * handle drag start event * @private */ -Graph.prototype._onMouseUp = function (event) { - event = event || window.event; +Graph.prototype._onDragEnd = function () { + var drag = this.drag, + node = drag.node; - if (!this.selectable) { - return; - } - - // remove event listeners here, important for Safari - if (this.onmousemove) { - vis.util.removeEventListener(document, "mousemove", this.onmousemove); - this.onmousemove = undefined; + if (node) { + // restore orginal xFixed and yFixed + node.xFixed = drag.xFixed; + node.yFixed = drag.yFixed; } - if (this.onmouseup) { - vis.util.removeEventListener(document, "mouseup", this.onmouseup); - this.onmouseup = undefined; - } - vis.util.preventDefault(event); +}; - // check selected nodes - var endMouseX = util.getPageX(event) || this.mouseX || 0; - var endMouseY = util.getPageY(event) || this.mouseY || 0; +/** + * handle tap/click event: select/unselect a node + * @private + */ +Graph.prototype._onTap = function (event) { + var pointer = this._getPointer(event.gesture.touches[0]); - var ctrlKey = event ? event.ctrlKey : window.event.ctrlKey; + var nodeId = this._getNodeAt(pointer); + var node = this.nodes[nodeId]; + if (node) { + // select this node + this._selectNodes([nodeId]); - if (this.startClickedObj) { - // restore the original fixed state - var node = this.nodes[this.startClickedObj]; - node.xFixed = this.startClickedObj.xFixed; - node.yFixed = this.startClickedObj.yFixed; - } - else if (this.shiftKeyDown) { - // select nodes inside selection area - var obj = { - "left": this._xToCanvas(Math.min(this.startMouseX, endMouseX) - this.startFrameLeft), - "top": this._yToCanvas(Math.min(this.startMouseY, endMouseY) - this.startFrameTop), - "right": this._xToCanvas(Math.max(this.startMouseX, endMouseX) - this.startFrameLeft), - "bottom": this._yToCanvas(Math.max(this.startMouseY, endMouseY) - this.startFrameTop) - }; - var overlappingNodes = this._getNodesOverlappingWith(obj); - this._selectNodes(overlappingNodes, ctrlKey); - this.redraw(); - - // remove the selection rectangle - if (this.frame.selRect) { - this.frame.removeChild(this.frame.selRect); - this.frame.selRect = undefined; + if (!this.moving) { + this._redraw(); } } else { - if (!this.ctrlKeyDown && !this.moved) { - // remove selection - this._unselectNodes(); + // remove selection + this._unselectNodes(); + this._redraw(); + } +}; + +/** + * handle long tap event: multi select nodes + * @private + */ +Graph.prototype._onHold = function (event) { + var pointer = this._getPointer(event.gesture.touches[0]); + var nodeId = this._getNodeAt(pointer); + var node = this.nodes[nodeId]; + if (node) { + if (!node.isSelected()) { + // select this node, keep previous selection + var append = true; + this._selectNodes([nodeId], append); + } + else { + this._unselectNodes([nodeId]); + } + + if (!this.moving) { this._redraw(); } } + else { + // Do nothing + } +}; + +/** + * Handle pinch event + * @param event + * @private + */ +Graph.prototype._onPinch = function (event) { + var pointer = this._getPointer(event.gesture.center); + + this.drag.pinched = true; + if (!('scale' in this.pinch)) { + this.pinch.scale = 1; + } - this.leftButtonDown = false; - this.ctrlKeyDown = false; + // TODO: enable moving while pinching? + var scale = this.pinch.scale * event.gesture.scale; + this._zoom(scale, pointer) }; +/** + * Zoom the graph in or out + * @param {Number} scale a number around 1, and between 0.01 and 10 + * @param {{x: Number, y: Number}} pointer + * @return {Number} appliedScale scale is limited within the boundaries + * @private + */ +Graph.prototype._zoom = function(scale, pointer) { + var scaleOld = this._getScale(); + if (scale < 0.01) { + scale = 0.01; + } + if (scale > 10) { + scale = 10; + } + + var translation = this._getTranslation(); + var scaleFrac = scale / scaleOld; + var tx = (1 - scaleFrac) * pointer.x + translation.x * scaleFrac; + var ty = (1 - scaleFrac) * pointer.y + translation.y * scaleFrac; + + this._setScale(scale); + this._setTranslation(tx, ty); + this._redraw(); + + return scale; +}; /** * Event handler for mouse wheel event, used to zoom the timeline - * Code from http://adomas.org/javascript-mouse-wheel/ - * @param {Event} event + * See http://adomas.org/javascript-mouse-wheel/ + * https://github.com/EightMedia/hammer.js/issues/256 + * @param {MouseEvent} event * @private */ Graph.prototype._onMouseWheel = function(event) { - event = event || window.event; - var mouseX = util.getPageX(event); - var mouseY = util.getPageY(event); - // retrieve delta var delta = 0; if (event.wheelDelta) { /* IE/Opera. */ @@ -556,41 +556,31 @@ Graph.prototype._onMouseWheel = function(event) { // Basically, delta is now positive if wheel was scrolled up, // and negative, if wheel was scrolled down. if (delta) { - // determine zoom factor, and adjust the zoom factor such that zooming in - // and zooming out correspond wich each other + if (!('mouswheelScale' in this.pinch)) { + this.pinch.mouswheelScale = 1; + } + + // calculate the new scale + var scale = this.pinch.mouswheelScale; var zoom = delta / 10; if (delta < 0) { zoom = zoom / (1 - zoom); } + scale *= (1 + zoom); - var scaleOld = this._getScale(); - var scaleNew = scaleOld * (1 + zoom); - if (scaleNew < 0.01) { - scaleNew = 0.01; - } - if (scaleNew > 10) { - scaleNew = 10; - } - - var frameLeft = vis.util.getAbsoluteLeft(this.frame.canvas); - var frameTop = vis.util.getAbsoluteTop(this.frame.canvas); - var x = mouseX - frameLeft; - var y = mouseY - frameTop; + // calculate the pointer location + var gesture = Hammer.event.collectEventData(this, 'scroll', event); + var pointer = this._getPointer(gesture.center); - var translation = this._getTranslation(); - var scaleFrac = scaleNew / scaleOld; - var tx = (1 - scaleFrac) * x + translation.x * scaleFrac; - var ty = (1 - scaleFrac) * y + translation.y * scaleFrac; + // apply the new scale + scale = this._zoom(scale, pointer); - this._setScale(scaleNew); - this._setTranslation(tx, ty); - this._redraw(); + // store the new, applied scale + this.pinch.mouswheelScale = scale; } // Prevent default actions caused by mouse wheel. - // That might be ugly, but we handle scrolls somehow - // anyway, so don't bother here... - vis.util.preventDefault(event); + event.preventDefault(); }; @@ -600,26 +590,19 @@ Graph.prototype._onMouseWheel = function(event) { * @private */ Graph.prototype._onMouseMoveTitle = function (event) { - event = event || window.event; - - var startMouseX = util.getPageX(event); - var startMouseY = util.getPageY(event); - this.startFrameLeft = this.startFrameLeft || vis.util.getAbsoluteLeft(this.frame.canvas); - this.startFrameTop = this.startFrameTop || vis.util.getAbsoluteTop(this.frame.canvas); - - var x = startMouseX - this.startFrameLeft; - var y = startMouseY - this.startFrameTop; + var gesture = Hammer.event.collectEventData(this, 'mousemove', event); + var pointer = this._getPointer(gesture.center); // check if the previously selected node is still selected if (this.popupNode) { - this._checkHidePopup(x, y); + this._checkHidePopup(pointer); } // start a timeout that will check if the mouse is positioned above // an element var me = this; var checkShow = function() { - me._checkShowPopup(x, y); + me._checkShowPopup(pointer); }; if (this.popupTimer) { clearInterval(this.popupTimer); // stop any running timer @@ -634,16 +617,15 @@ Graph.prototype._onMouseMoveTitle = function (event) { * (a node or edge). If so, and if this element has a title, * show a popup window with its title. * - * @param {number} x - * @param {number} y + * @param {{x:Number, y:Number}} pointer * @private */ -Graph.prototype._checkShowPopup = function (x, y) { +Graph.prototype._checkShowPopup = function (pointer) { var obj = { - "left" : this._xToCanvas(x), - "top" : this._yToCanvas(y), - "right" : this._xToCanvas(x), - "bottom" : this._yToCanvas(y) + left: this._xToCanvas(pointer.x), + top: this._yToCanvas(pointer.y), + right: this._xToCanvas(pointer.x), + bottom: this._yToCanvas(pointer.y) }; var id; @@ -689,7 +671,7 @@ Graph.prototype._checkShowPopup = function (x, y) { // adjust a small offset such that the mouse cursor is located in the // bottom left location of the popup, and you can easily move over the // popup area - me.popup.setPosition(x - 3, y - 3); + me.popup.setPosition(pointer.x - 3, pointer.y - 3); me.popup.setText(me.popupNode.getTitle()); me.popup.show(); } @@ -704,19 +686,11 @@ Graph.prototype._checkShowPopup = function (x, y) { /** * Check if the popup must be hided, which is the case when the mouse is no * longer hovering on the object - * @param {number} x - * @param {number} y + * @param {{x:Number, y:Number}} pointer * @private */ -Graph.prototype._checkHidePopup = function (x, y) { - var obj = { - "left" : x, - "top" : y, - "right" : x, - "bottom" : y - }; - - if (!this.popupNode || !this.popupNode.isOverlappingWith(obj) ) { +Graph.prototype._checkHidePopup = function (pointer) { + if (!this.popupNode || !this._getNodeAt(pointer) ) { this.popupNode = undefined; if (this.popup) { this.popup.hide(); @@ -724,66 +698,6 @@ Graph.prototype._checkHidePopup = function (x, y) { } }; -/** - * Event handler for touchstart event on mobile devices - * @param {Event} event - * @private - */ -Graph.prototype._onTouchStart = function(event) { - vis.util.preventDefault(event); - - if (this.touchDown) { - // if already moving, return - return; - } - this.touchDown = true; - - var me = this; - if (!this.ontouchmove) { - this.ontouchmove = function (event) {me._onTouchMove(event);}; - vis.util.addEventListener(document, "touchmove", this.ontouchmove); - } - if (!this.ontouchend) { - this.ontouchend = function (event) {me._onTouchEnd(event);}; - vis.util.addEventListener(document, "touchend", this.ontouchend); - } - - this._onMouseDown(event); -}; - -/** - * Event handler for touchmove event on mobile devices - * @param {Event} event - * @private - */ -Graph.prototype._onTouchMove = function(event) { - vis.util.preventDefault(event); - this._onMouseMove(event); -}; - -/** - * Event handler for touchend event on mobile devices - * @param {Event} event - * @private - */ -Graph.prototype._onTouchEnd = function(event) { - vis.util.preventDefault(event); - - this.touchDown = false; - - if (this.ontouchmove) { - vis.util.removeEventListener(document, "touchmove", this.ontouchmove); - this.ontouchmove = undefined; - } - if (this.ontouchend) { - vis.util.removeEventListener(document, "touchend", this.ontouchend); - this.ontouchend = undefined; - } - - this._onMouseUp(event); -}; - - /** * Unselect selected nodes. If no selection array is provided, all nodes * are unselected @@ -893,8 +807,7 @@ Graph.prototype._selectNodes = function(selection, append) { /** * retrieve all nodes overlapping with given object * @param {Object} obj An object with parameters left, top, right, bottom - * @return {Object[]} An array with selection objects containing - * the parameter row. + * @return {Number[]} An array with id's of the overlapping nodes * @private */ Graph.prototype._getNodesOverlappingWith = function (obj) { @@ -929,7 +842,7 @@ Graph.prototype.getSelection = function() { Graph.prototype.setSelection = function(selection) { var i, iMax, id; - if (selection.length == undefined) + if (!selection || (selection.length == undefined)) throw "Selection must be an array with ids"; // first unselect any selected node diff --git a/src/module/imports.js b/src/module/imports.js index aa13337d..58aff1f0 100644 --- a/src/module/imports.js +++ b/src/module/imports.js @@ -1,4 +1,8 @@ /** * vis.js module imports */ -var moment = require('moment'); + +// Try to load dependencies from the global window object. +// If not available there, load via require. +var moment = (typeof window !== 'undefined') && window['moment'] || require('moment'); +var Hammer = (typeof window !== 'undefined') && window['Hammer'] || require('hammerjs'); diff --git a/src/shim.js b/src/shim.js new file mode 100644 index 00000000..3bb50d55 --- /dev/null +++ b/src/shim.js @@ -0,0 +1,252 @@ + +// Internet Explorer 8 and older does not support Array.indexOf, so we define +// it here in that case. +// http://soledadpenades.com/2007/05/17/arrayindexof-in-internet-explorer/ +if(!Array.prototype.indexOf) { + Array.prototype.indexOf = function(obj){ + for(var i = 0; i < this.length; i++){ + if(this[i] == obj){ + return i; + } + } + return -1; + }; + + try { + console.log("Warning: Ancient browser detected. Please update your browser"); + } + catch (err) { + } +} + +// Internet Explorer 8 and older does not support Array.forEach, so we define +// it here in that case. +// https://developer.mozilla.org/en-US/docs/JavaScript/Reference/Global_Objects/Array/forEach +if (!Array.prototype.forEach) { + Array.prototype.forEach = function(fn, scope) { + for(var i = 0, len = this.length; i < len; ++i) { + fn.call(scope || this, this[i], i, this); + } + } +} + +// Internet Explorer 8 and older does not support Array.map, so we define it +// here in that case. +// https://developer.mozilla.org/en-US/docs/JavaScript/Reference/Global_Objects/Array/map +// Production steps of ECMA-262, Edition 5, 15.4.4.19 +// Reference: http://es5.github.com/#x15.4.4.19 +if (!Array.prototype.map) { + Array.prototype.map = function(callback, thisArg) { + + var T, A, k; + + if (this == null) { + throw new TypeError(" this is null or not defined"); + } + + // 1. Let O be the result of calling ToObject passing the |this| value as the argument. + var O = Object(this); + + // 2. Let lenValue be the result of calling the Get internal method of O with the argument "length". + // 3. Let len be ToUint32(lenValue). + var len = O.length >>> 0; + + // 4. If IsCallable(callback) is false, throw a TypeError exception. + // See: http://es5.github.com/#x9.11 + if (typeof callback !== "function") { + throw new TypeError(callback + " is not a function"); + } + + // 5. If thisArg was supplied, let T be thisArg; else let T be undefined. + if (thisArg) { + T = thisArg; + } + + // 6. Let A be a new array created as if by the expression new Array(len) where Array is + // the standard built-in constructor with that name and len is the value of len. + A = new Array(len); + + // 7. Let k be 0 + k = 0; + + // 8. Repeat, while k < len + while(k < len) { + + var kValue, mappedValue; + + // a. Let Pk be ToString(k). + // This is implicit for LHS operands of the in operator + // b. Let kPresent be the result of calling the HasProperty internal method of O with argument Pk. + // This step can be combined with c + // c. If kPresent is true, then + if (k in O) { + + // i. Let kValue be the result of calling the Get internal method of O with argument Pk. + kValue = O[ k ]; + + // ii. Let mappedValue be the result of calling the Call internal method of callback + // with T as the this value and argument list containing kValue, k, and O. + mappedValue = callback.call(T, kValue, k, O); + + // iii. Call the DefineOwnProperty internal method of A with arguments + // Pk, Property Descriptor {Value: mappedValue, : true, Enumerable: true, Configurable: true}, + // and false. + + // In browsers that support Object.defineProperty, use the following: + // Object.defineProperty(A, Pk, { value: mappedValue, writable: true, enumerable: true, configurable: true }); + + // For best browser support, use the following: + A[ k ] = mappedValue; + } + // d. Increase k by 1. + k++; + } + + // 9. return A + return A; + }; +} + +// Internet Explorer 8 and older does not support Array.filter, so we define it +// here in that case. +// https://developer.mozilla.org/en-US/docs/JavaScript/Reference/Global_Objects/Array/filter +if (!Array.prototype.filter) { + Array.prototype.filter = function(fun /*, thisp */) { + "use strict"; + + if (this == null) { + throw new TypeError(); + } + + var t = Object(this); + var len = t.length >>> 0; + if (typeof fun != "function") { + throw new TypeError(); + } + + var res = []; + var thisp = arguments[1]; + for (var i = 0; i < len; i++) { + if (i in t) { + var val = t[i]; // in case fun mutates this + if (fun.call(thisp, val, i, t)) + res.push(val); + } + } + + return res; + }; +} + + +// Internet Explorer 8 and older does not support Object.keys, so we define it +// here in that case. +// https://developer.mozilla.org/en-US/docs/JavaScript/Reference/Global_Objects/Object/keys +if (!Object.keys) { + Object.keys = (function () { + var hasOwnProperty = Object.prototype.hasOwnProperty, + hasDontEnumBug = !({toString: null}).propertyIsEnumerable('toString'), + dontEnums = [ + 'toString', + 'toLocaleString', + 'valueOf', + 'hasOwnProperty', + 'isPrototypeOf', + 'propertyIsEnumerable', + 'constructor' + ], + dontEnumsLength = dontEnums.length; + + return function (obj) { + if (typeof obj !== 'object' && typeof obj !== 'function' || obj === null) { + throw new TypeError('Object.keys called on non-object'); + } + + var result = []; + + for (var prop in obj) { + if (hasOwnProperty.call(obj, prop)) result.push(prop); + } + + if (hasDontEnumBug) { + for (var i=0; i < dontEnumsLength; i++) { + if (hasOwnProperty.call(obj, dontEnums[i])) result.push(dontEnums[i]); + } + } + return result; + } + })() +} + +// Internet Explorer 8 and older does not support Array.isArray, +// so we define it here in that case. +// https://developer.mozilla.org/en-US/docs/JavaScript/Reference/Global_Objects/Array/isArray +if(!Array.isArray) { + Array.isArray = function (vArg) { + return Object.prototype.toString.call(vArg) === "[object Array]"; + }; +} + +// Internet Explorer 8 and older does not support Function.bind, +// so we define it here in that case. +// https://developer.mozilla.org/en-US/docs/JavaScript/Reference/Global_Objects/Function/bind +if (!Function.prototype.bind) { + Function.prototype.bind = function (oThis) { + if (typeof this !== "function") { + // closest thing possible to the ECMAScript 5 internal IsCallable function + throw new TypeError("Function.prototype.bind - what is trying to be bound is not callable"); + } + + var aArgs = Array.prototype.slice.call(arguments, 1), + fToBind = this, + fNOP = function () {}, + fBound = function () { + return fToBind.apply(this instanceof fNOP && oThis + ? this + : oThis, + aArgs.concat(Array.prototype.slice.call(arguments))); + }; + + fNOP.prototype = this.prototype; + fBound.prototype = new fNOP(); + + return fBound; + }; +} + +// https://developer.mozilla.org/en-US/docs/JavaScript/Reference/Global_Objects/Object/create +if (!Object.create) { + Object.create = function (o) { + if (arguments.length > 1) { + throw new Error('Object.create implementation only accepts the first parameter.'); + } + function F() {} + F.prototype = o; + return new F(); + }; +} + +// https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Function/bind +if (!Function.prototype.bind) { + Function.prototype.bind = function (oThis) { + if (typeof this !== "function") { + // closest thing possible to the ECMAScript 5 internal IsCallable function + throw new TypeError("Function.prototype.bind - what is trying to be bound is not callable"); + } + + var aArgs = Array.prototype.slice.call(arguments, 1), + fToBind = this, + fNOP = function () {}, + fBound = function () { + return fToBind.apply(this instanceof fNOP && oThis + ? this + : oThis, + aArgs.concat(Array.prototype.slice.call(arguments))); + }; + + fNOP.prototype = this.prototype; + fBound.prototype = new fNOP(); + + return fBound; + }; +} diff --git a/src/util.js b/src/util.js index d09a82a9..70c907a4 100644 --- a/src/util.js +++ b/src/util.js @@ -684,231 +684,3 @@ util.loadCss = function (css) { document.getElementsByTagName('head')[0].appendChild(style); }; - - -// Internet Explorer 8 and older does not support Array.indexOf, so we define -// it here in that case. -// http://soledadpenades.com/2007/05/17/arrayindexof-in-internet-explorer/ -if(!Array.prototype.indexOf) { - Array.prototype.indexOf = function(obj){ - for(var i = 0; i < this.length; i++){ - if(this[i] == obj){ - return i; - } - } - return -1; - }; - - try { - console.log("Warning: Ancient browser detected. Please update your browser"); - } - catch (err) { - } -} - -// Internet Explorer 8 and older does not support Array.forEach, so we define -// it here in that case. -// https://developer.mozilla.org/en-US/docs/JavaScript/Reference/Global_Objects/Array/forEach -if (!Array.prototype.forEach) { - Array.prototype.forEach = function(fn, scope) { - for(var i = 0, len = this.length; i < len; ++i) { - fn.call(scope || this, this[i], i, this); - } - } -} - -// Internet Explorer 8 and older does not support Array.map, so we define it -// here in that case. -// https://developer.mozilla.org/en-US/docs/JavaScript/Reference/Global_Objects/Array/map -// Production steps of ECMA-262, Edition 5, 15.4.4.19 -// Reference: http://es5.github.com/#x15.4.4.19 -if (!Array.prototype.map) { - Array.prototype.map = function(callback, thisArg) { - - var T, A, k; - - if (this == null) { - throw new TypeError(" this is null or not defined"); - } - - // 1. Let O be the result of calling ToObject passing the |this| value as the argument. - var O = Object(this); - - // 2. Let lenValue be the result of calling the Get internal method of O with the argument "length". - // 3. Let len be ToUint32(lenValue). - var len = O.length >>> 0; - - // 4. If IsCallable(callback) is false, throw a TypeError exception. - // See: http://es5.github.com/#x9.11 - if (typeof callback !== "function") { - throw new TypeError(callback + " is not a function"); - } - - // 5. If thisArg was supplied, let T be thisArg; else let T be undefined. - if (thisArg) { - T = thisArg; - } - - // 6. Let A be a new array created as if by the expression new Array(len) where Array is - // the standard built-in constructor with that name and len is the value of len. - A = new Array(len); - - // 7. Let k be 0 - k = 0; - - // 8. Repeat, while k < len - while(k < len) { - - var kValue, mappedValue; - - // a. Let Pk be ToString(k). - // This is implicit for LHS operands of the in operator - // b. Let kPresent be the result of calling the HasProperty internal method of O with argument Pk. - // This step can be combined with c - // c. If kPresent is true, then - if (k in O) { - - // i. Let kValue be the result of calling the Get internal method of O with argument Pk. - kValue = O[ k ]; - - // ii. Let mappedValue be the result of calling the Call internal method of callback - // with T as the this value and argument list containing kValue, k, and O. - mappedValue = callback.call(T, kValue, k, O); - - // iii. Call the DefineOwnProperty internal method of A with arguments - // Pk, Property Descriptor {Value: mappedValue, : true, Enumerable: true, Configurable: true}, - // and false. - - // In browsers that support Object.defineProperty, use the following: - // Object.defineProperty(A, Pk, { value: mappedValue, writable: true, enumerable: true, configurable: true }); - - // For best browser support, use the following: - A[ k ] = mappedValue; - } - // d. Increase k by 1. - k++; - } - - // 9. return A - return A; - }; -} - -// Internet Explorer 8 and older does not support Array.filter, so we define it -// here in that case. -// https://developer.mozilla.org/en-US/docs/JavaScript/Reference/Global_Objects/Array/filter -if (!Array.prototype.filter) { - Array.prototype.filter = function(fun /*, thisp */) { - "use strict"; - - if (this == null) { - throw new TypeError(); - } - - var t = Object(this); - var len = t.length >>> 0; - if (typeof fun != "function") { - throw new TypeError(); - } - - var res = []; - var thisp = arguments[1]; - for (var i = 0; i < len; i++) { - if (i in t) { - var val = t[i]; // in case fun mutates this - if (fun.call(thisp, val, i, t)) - res.push(val); - } - } - - return res; - }; -} - - -// Internet Explorer 8 and older does not support Object.keys, so we define it -// here in that case. -// https://developer.mozilla.org/en-US/docs/JavaScript/Reference/Global_Objects/Object/keys -if (!Object.keys) { - Object.keys = (function () { - var hasOwnProperty = Object.prototype.hasOwnProperty, - hasDontEnumBug = !({toString: null}).propertyIsEnumerable('toString'), - dontEnums = [ - 'toString', - 'toLocaleString', - 'valueOf', - 'hasOwnProperty', - 'isPrototypeOf', - 'propertyIsEnumerable', - 'constructor' - ], - dontEnumsLength = dontEnums.length; - - return function (obj) { - if (typeof obj !== 'object' && typeof obj !== 'function' || obj === null) { - throw new TypeError('Object.keys called on non-object'); - } - - var result = []; - - for (var prop in obj) { - if (hasOwnProperty.call(obj, prop)) result.push(prop); - } - - if (hasDontEnumBug) { - for (var i=0; i < dontEnumsLength; i++) { - if (hasOwnProperty.call(obj, dontEnums[i])) result.push(dontEnums[i]); - } - } - return result; - } - })() -} - -// Internet Explorer 8 and older does not support Array.isArray, -// so we define it here in that case. -// https://developer.mozilla.org/en-US/docs/JavaScript/Reference/Global_Objects/Array/isArray -if(!Array.isArray) { - Array.isArray = function (vArg) { - return Object.prototype.toString.call(vArg) === "[object Array]"; - }; -} - -// Internet Explorer 8 and older does not support Function.bind, -// so we define it here in that case. -// https://developer.mozilla.org/en-US/docs/JavaScript/Reference/Global_Objects/Function/bind -if (!Function.prototype.bind) { - Function.prototype.bind = function (oThis) { - if (typeof this !== "function") { - // closest thing possible to the ECMAScript 5 internal IsCallable function - throw new TypeError("Function.prototype.bind - what is trying to be bound is not callable"); - } - - var aArgs = Array.prototype.slice.call(arguments, 1), - fToBind = this, - fNOP = function () {}, - fBound = function () { - return fToBind.apply(this instanceof fNOP && oThis - ? this - : oThis, - aArgs.concat(Array.prototype.slice.call(arguments))); - }; - - fNOP.prototype = this.prototype; - fBound.prototype = new fNOP(); - - return fBound; - }; -} - -// https://developer.mozilla.org/en-US/docs/JavaScript/Reference/Global_Objects/Object/create -if (!Object.create) { - Object.create = function (o) { - if (arguments.length > 1) { - throw new Error('Object.create implementation only accepts the first parameter.'); - } - function F() {} - F.prototype = o; - return new F(); - }; -} diff --git a/vis.js b/vis.js index 0abe3d53..06b9fd3c 100644 --- a/vis.js +++ b/vis.js @@ -5,7 +5,7 @@ * A dynamic, browser-based visualization library. * * @version 0.2.0-SNAPSHOT - * @date 2013-09-09 + * @date 2013-09-17 * * @license * Copyright (C) 2011-2013 Almende B.V, http://almende.com @@ -23,12850 +23,14588 @@ * the License. */ (function(e){if("function"==typeof bootstrap)bootstrap("vis",e);else if("object"==typeof exports)module.exports=e();else if("function"==typeof define&&define.amd)define(e);else if("undefined"!=typeof ses){if(!ses.ok())return;ses.makeVis=e}else"undefined"!=typeof window?window.vis=e():global.vis=e()})(function(){var define,ses,bootstrap,module,exports; -return (function(e,t,n){function i(n,s){if(!t[n]){if(!e[n]){var o=typeof require=="function"&&require;if(!s&&o)return o(n,!0);if(r)return r(n,!0);throw new Error("Cannot find module '"+n+"'")}var u=t[n]={exports:{}};e[n][0].call(u.exports,function(t){var r=e[n][1][t];return i(r?r:t)},u,u.exports)}return t[n].exports}var r=typeof require=="function"&&require;for(var s=0;s; + * Licensed under the MIT license */ -/** - * utility functions - */ -var util = {}; +(function(window, undefined) { + 'use strict'; /** - * Test whether given object is a number - * @param {*} object - * @return {Boolean} isNumber + * Hammer + * use this to create instances + * @param {HTMLElement} element + * @param {Object} options + * @returns {Hammer.Instance} + * @constructor */ -util.isNumber = function isNumber(object) { - return (object instanceof Number || typeof object == 'number'); +var Hammer = function(element, options) { + return new Hammer.Instance(element, options || {}); }; -/** - * Test whether given object is a string - * @param {*} object - * @return {Boolean} isString - */ -util.isString = function isString(object) { - return (object instanceof String || typeof object == 'string'); +// default settings +Hammer.defaults = { + // add styles and attributes to the element to prevent the browser from doing + // its native behavior. this doesnt prevent the scrolling, but cancels + // the contextmenu, tap highlighting etc + // set to false to disable this + stop_browser_behavior: { + // this also triggers onselectstart=false for IE + userSelect: 'none', + // this makes the element blocking in IE10 >, you could experiment with the value + // see for more options this issue; https://github.com/EightMedia/hammer.js/issues/241 + touchAction: 'none', + touchCallout: 'none', + contentZooming: 'none', + userDrag: 'none', + tapHighlightColor: 'rgba(0,0,0,0)' + } + + // more settings are defined per gesture at gestures.js }; +// detect touchevents +Hammer.HAS_POINTEREVENTS = navigator.pointerEnabled || navigator.msPointerEnabled; +Hammer.HAS_TOUCHEVENTS = ('ontouchstart' in window); + +// dont use mouseevents on mobile devices +Hammer.MOBILE_REGEX = /mobile|tablet|ip(ad|hone|od)|android/i; +Hammer.NO_MOUSEEVENTS = Hammer.HAS_TOUCHEVENTS && navigator.userAgent.match(Hammer.MOBILE_REGEX); + +// eventtypes per touchevent (start, move, end) +// are filled by Hammer.event.determineEventTypes on setup +Hammer.EVENT_TYPES = {}; + +// direction defines +Hammer.DIRECTION_DOWN = 'down'; +Hammer.DIRECTION_LEFT = 'left'; +Hammer.DIRECTION_UP = 'up'; +Hammer.DIRECTION_RIGHT = 'right'; + +// pointer type +Hammer.POINTER_MOUSE = 'mouse'; +Hammer.POINTER_TOUCH = 'touch'; +Hammer.POINTER_PEN = 'pen'; + +// touch event defines +Hammer.EVENT_START = 'start'; +Hammer.EVENT_MOVE = 'move'; +Hammer.EVENT_END = 'end'; + +// hammer document where the base events are added at +Hammer.DOCUMENT = document; + +// plugins namespace +Hammer.plugins = {}; + +// if the window events are set... +Hammer.READY = false; + /** - * Test whether given object is a Date, or a String containing a Date - * @param {Date | String} object - * @return {Boolean} isDate + * setup events to detect gestures on the document */ -util.isDate = function isDate(object) { - if (object instanceof Date) { - return true; +function setup() { + if(Hammer.READY) { + return; } - else if (util.isString(object)) { - // test whether this string contains a date - var match = ASPDateRegex.exec(object); - if (match) { - return true; - } - else if (!isNaN(Date.parse(object))) { - return true; + + // find what eventtypes we add listeners to + Hammer.event.determineEventTypes(); + + // Register all gestures inside Hammer.gestures + for(var name in Hammer.gestures) { + if(Hammer.gestures.hasOwnProperty(name)) { + Hammer.detection.register(Hammer.gestures[name]); } } - return false; -}; + // Add touch events on the document + Hammer.event.onTouch(Hammer.DOCUMENT, Hammer.EVENT_MOVE, Hammer.detection.detect); + Hammer.event.onTouch(Hammer.DOCUMENT, Hammer.EVENT_END, Hammer.detection.detect); + + // Hammer is ready...! + Hammer.READY = true; +} /** - * Test whether given object is an instance of google.visualization.DataTable - * @param {*} object - * @return {Boolean} isDataTable + * create new hammer instance + * all methods should return the instance itself, so it is chainable. + * @param {HTMLElement} element + * @param {Object} [options={}] + * @returns {Hammer.Instance} + * @constructor */ -util.isDataTable = function isDataTable(object) { - return (typeof (google) !== 'undefined') && - (google.visualization) && - (google.visualization.DataTable) && - (object instanceof google.visualization.DataTable); +Hammer.Instance = function(element, options) { + var self = this; + + // setup HammerJS window events and register all gestures + // this also sets up the default options + setup(); + + this.element = element; + + // start/stop detection option + this.enabled = true; + + // merge options + this.options = Hammer.utils.extend( + Hammer.utils.extend({}, Hammer.defaults), + options || {}); + + // add some css to the element to prevent the browser from doing its native behavoir + if(this.options.stop_browser_behavior) { + Hammer.utils.stopDefaultBrowserBehavior(this.element, this.options.stop_browser_behavior); + } + + // start detection on touchstart + Hammer.event.onTouch(element, Hammer.EVENT_START, function(ev) { + if(self.enabled) { + Hammer.detection.startDetect(self, ev); + } + }); + + // return instance + return this; +}; + + +Hammer.Instance.prototype = { + /** + * bind events to the instance + * @param {String} gesture + * @param {Function} handler + * @returns {Hammer.Instance} + */ + on: function onEvent(gesture, handler){ + var gestures = gesture.split(' '); + for(var t=0; t 0 && eventType == Hammer.EVENT_END) { + eventType = Hammer.EVENT_MOVE; } - else { - return moment(object); // parse string + // no touches, force the end event + else if(!count_touches) { + eventType = Hammer.EVENT_END; } - } - else { - throw new Error( - 'Cannot convert object of type ' + util.getType(object) + - ' to type Date'); - } - case 'ISODate': - if (util.isNumber(object)) { - return new Date(object); - } - else if (object instanceof Date) { - return object.toISOString(); - } - else if (moment.isMoment(object)) { - return object.toDate().toISOString(); - } - else if (util.isString(object)) { - match = ASPDateRegex.exec(object); - if (match) { - // object is an ASP date - return new Date(Number(match[1])).toISOString(); // parse number + // because touchend has no touches, and we often want to use these in our gestures, + // we send the last move event as our eventData in touchend + if(!count_touches && last_move_event !== null) { + ev = last_move_event; } + // store the last move event else { - return new Date(object).toISOString(); // parse string + last_move_event = ev; } - } - else { - throw new Error( - 'Cannot convert object of type ' + util.getType(object) + - ' to type ISODate'); - } - case 'ASPDate': - if (util.isNumber(object)) { - return '/Date(' + object + ')/'; - } - else if (object instanceof Date) { - return '/Date(' + object.valueOf() + ')/'; - } - else if (util.isString(object)) { - match = ASPDateRegex.exec(object); - var value; - if (match) { - // object is an ASP date - value = new Date(Number(match[1])).valueOf(); // parse number - } - else { - value = new Date(object).valueOf(); // parse string + // trigger the handler + handler.call(Hammer.detection, self.collectEventData(element, eventType, ev)); + + // remove pointerevent from list + if(Hammer.HAS_POINTEREVENTS && eventType == Hammer.EVENT_END) { + count_touches = Hammer.PointerEvent.updatePointer(eventType, ev); } - return '/Date(' + value + ')/'; - } - else { - throw new Error( - 'Cannot convert object of type ' + util.getType(object) + - ' to type ASPDate'); } - default: - throw new Error('Cannot convert object of type ' + util.getType(object) + - ' to type "' + type + '"'); - } -}; + //debug(sourceEventType +" "+ eventType); -// parse ASP.Net Date pattern, -// for example '/Date(1198908717056)/' or '/Date(1198908717056-0700)/' -// code from http://momentjs.com/ -var ASPDateRegex = /^\/?Date\((\-?\d+)/i; + // on the end we reset everything + if(!count_touches) { + last_move_event = null; + enable_detect = false; + touch_triggered = false; + Hammer.PointerEvent.reset(); + } + }); + }, -/** - * Get the type of an object, for example util.getType([]) returns 'Array' - * @param {*} object - * @return {String} type - */ -util.getType = function getType(object) { - var type = typeof object; - if (type == 'object') { - if (object == null) { - return 'null'; - } - if (object instanceof Boolean) { - return 'Boolean'; + /** + * we have different events for each device/browser + * determine what we need and set them in the Hammer.EVENT_TYPES constant + */ + determineEventTypes: function determineEventTypes() { + // determine the eventtype we want to set + var types; + + // pointerEvents magic + if(Hammer.HAS_POINTEREVENTS) { + types = Hammer.PointerEvent.getEvents(); + } + // on Android, iOS, blackberry, windows mobile we dont want any mouseevents + else if(Hammer.NO_MOUSEEVENTS) { + types = [ + 'touchstart', + 'touchmove', + 'touchend touchcancel']; + } + // for non pointer events browsers and mixed browsers, + // like chrome on windows8 touch laptop + else { + types = [ + 'touchstart mousedown', + 'touchmove mousemove', + 'touchend touchcancel mouseup']; } - if (object instanceof Number) { - return 'Number'; + + Hammer.EVENT_TYPES[Hammer.EVENT_START] = types[0]; + Hammer.EVENT_TYPES[Hammer.EVENT_MOVE] = types[1]; + Hammer.EVENT_TYPES[Hammer.EVENT_END] = types[2]; + }, + + + /** + * create touchlist depending on the event + * @param {Object} ev + * @param {String} eventType used by the fakemultitouch plugin + */ + getTouchList: function getTouchList(ev/*, eventType*/) { + // get the fake pointerEvent touchlist + if(Hammer.HAS_POINTEREVENTS) { + return Hammer.PointerEvent.getTouchList(); } - if (object instanceof String) { - return 'String'; + // get the touchlist + else if(ev.touches) { + return ev.touches; } - if (object instanceof Array) { - return 'Array'; + // make fake touchlist from mouse position + else { + return [{ + identifier: 1, + pageX: ev.pageX, + pageY: ev.pageY, + target: ev.target + }]; } - if (object instanceof Date) { - return 'Date'; + }, + + + /** + * collect event data for Hammer js + * @param {HTMLElement} element + * @param {String} eventType like Hammer.EVENT_MOVE + * @param {Object} eventData + */ + collectEventData: function collectEventData(element, eventType, ev) { + var touches = this.getTouchList(ev, eventType); + + // find out pointerType + var pointerType = Hammer.POINTER_TOUCH; + if(ev.type.match(/mouse/) || Hammer.PointerEvent.matchType(Hammer.POINTER_MOUSE, ev)) { + pointerType = Hammer.POINTER_MOUSE; } - return 'Object'; - } - else if (type == 'number') { - return 'Number'; - } - else if (type == 'boolean') { - return 'Boolean'; - } - else if (type == 'string') { - return 'String'; - } - return type; -}; + return { + center : Hammer.utils.getCenter(touches), + timeStamp : new Date().getTime(), + target : ev.target, + touches : touches, + eventType : eventType, + pointerType : pointerType, + srcEvent : ev, -/** - * Retrieve the absolute left value of a DOM element - * @param {Element} elem A dom element, for example a div - * @return {number} left The absolute left position of this element - * in the browser page. - */ -util.getAbsoluteLeft = function getAbsoluteLeft (elem) { - var doc = document.documentElement; - var body = document.body; + /** + * prevent the browser default actions + * mostly used to disable scrolling of the browser + */ + preventDefault: function() { + if(this.srcEvent.preventManipulation) { + this.srcEvent.preventManipulation(); + } - var left = elem.offsetLeft; - var e = elem.offsetParent; - while (e != null && e != body && e != doc) { - left += e.offsetLeft; - left -= e.scrollLeft; - e = e.offsetParent; - } - return left; -}; + if(this.srcEvent.preventDefault) { + this.srcEvent.preventDefault(); + } + }, -/** - * Retrieve the absolute top value of a DOM element - * @param {Element} elem A dom element, for example a div - * @return {number} top The absolute top position of this element - * in the browser page. - */ -util.getAbsoluteTop = function getAbsoluteTop (elem) { - var doc = document.documentElement; - var body = document.body; + /** + * stop bubbling the event up to its parents + */ + stopPropagation: function() { + this.srcEvent.stopPropagation(); + }, - var top = elem.offsetTop; - var e = elem.offsetParent; - while (e != null && e != body && e != doc) { - top += e.offsetTop; - top -= e.scrollTop; - e = e.offsetParent; + /** + * immediately stop gesture detection + * might be useful after a swipe was detected + * @return {*} + */ + stopDetect: function() { + return Hammer.detection.stopDetect(); + } + }; } - return top; }; -/** - * Get the absolute, vertical mouse position from an event. - * @param {Event} event - * @return {Number} pageY - */ -util.getPageY = function getPageY (event) { - if ('pageY' in event) { - return event.pageY; - } - else { - var clientY; - if (('targetTouches' in event) && event.targetTouches.length) { - clientY = event.targetTouches[0].clientY; +Hammer.PointerEvent = { + /** + * holds all pointers + * @type {Object} + */ + pointers: {}, + + /** + * get a list of pointers + * @returns {Array} touchlist + */ + getTouchList: function() { + var self = this; + var touchlist = []; + + // we can use forEach since pointerEvents only is in IE10 + Object.keys(self.pointers).sort().forEach(function(id) { + touchlist.push(self.pointers[id]); + }); + return touchlist; + }, + + /** + * update the position of a pointer + * @param {String} type Hammer.EVENT_END + * @param {Object} pointerEvent + */ + updatePointer: function(type, pointerEvent) { + if(type == Hammer.EVENT_END) { + this.pointers = {}; } else { - clientY = event.clientY; + pointerEvent.identifier = pointerEvent.pointerId; + this.pointers[pointerEvent.pointerId] = pointerEvent; } - var doc = document.documentElement; - var body = document.body; - return clientY + - ( doc && doc.scrollTop || body && body.scrollTop || 0 ) - - ( doc && doc.clientTop || body && body.clientTop || 0 ); - } -}; + return Object.keys(this.pointers).length; + }, -/** - * Get the absolute, horizontal mouse position from an event. - * @param {Event} event - * @return {Number} pageX - */ -util.getPageX = function getPageX (event) { - if ('pageY' in event) { - return event.pageX; - } - else { - var clientX; - if (('targetTouches' in event) && event.targetTouches.length) { - clientX = event.targetTouches[0].clientX; - } - else { - clientX = event.clientX; + /** + * check if ev matches pointertype + * @param {String} pointerType Hammer.POINTER_MOUSE + * @param {PointerEvent} ev + */ + matchType: function(pointerType, ev) { + if(!ev.pointerType) { + return false; } - var doc = document.documentElement; - var body = document.body; - return clientX + - ( doc && doc.scrollLeft || body && body.scrollLeft || 0 ) - - ( doc && doc.clientLeft || body && body.clientLeft || 0 ); - } -}; + var types = {}; + types[Hammer.POINTER_MOUSE] = (ev.pointerType == ev.MSPOINTER_TYPE_MOUSE || ev.pointerType == Hammer.POINTER_MOUSE); + types[Hammer.POINTER_TOUCH] = (ev.pointerType == ev.MSPOINTER_TYPE_TOUCH || ev.pointerType == Hammer.POINTER_TOUCH); + types[Hammer.POINTER_PEN] = (ev.pointerType == ev.MSPOINTER_TYPE_PEN || ev.pointerType == Hammer.POINTER_PEN); + return types[pointerType]; + }, -/** - * add a className to the given elements style - * @param {Element} elem - * @param {String} className - */ -util.addClassName = function addClassName(elem, className) { - var classes = elem.className.split(' '); - if (classes.indexOf(className) == -1) { - classes.push(className); // add the class to the array - elem.className = classes.join(' '); - } -}; -/** - * add a className to the given elements style - * @param {Element} elem - * @param {String} className - */ -util.removeClassName = function removeClassname(elem, className) { - var classes = elem.className.split(' '); - var index = classes.indexOf(className); - if (index != -1) { - classes.splice(index, 1); // remove the class from the array - elem.className = classes.join(' '); + /** + * get events + */ + getEvents: function() { + return [ + 'pointerdown MSPointerDown', + 'pointermove MSPointerMove', + 'pointerup pointercancel MSPointerUp MSPointerCancel' + ]; + }, + + /** + * reset the list + */ + reset: function() { + this.pointers = {}; } }; -/** - * For each method for both arrays and objects. - * In case of an array, the built-in Array.forEach() is applied. - * In case of an Object, the method loops over all properties of the object. - * @param {Object | Array} object An Object or Array - * @param {function} callback Callback method, called for each item in - * the object or array with three parameters: - * callback(value, index, object) - */ -util.forEach = function forEach (object, callback) { - var i, - len; - if (object instanceof Array) { - // array - for (i = 0, len = object.length; i < len; i++) { - callback(object[i], i, object); - } - } - else { - // object - for (i in object) { - if (object.hasOwnProperty(i)) { - callback(object[i], i, object); + +Hammer.utils = { + /** + * extend method, + * also used for cloning when dest is an empty object + * @param {Object} dest + * @param {Object} src + * @parm {Boolean} merge do a merge + * @returns {Object} dest + */ + extend: function extend(dest, src, merge) { + for (var key in src) { + if(dest[key] !== undefined && merge) { + continue; + } + dest[key] = src[key]; + } + return dest; + }, + + + /** + * find if a node is in the given parent + * used for event delegation tricks + * @param {HTMLElement} node + * @param {HTMLElement} parent + * @returns {boolean} has_parent + */ + hasParent: function(node, parent) { + while(node){ + if(node == parent) { + return true; } + node = node.parentNode; } - } -}; - -/** - * Update a property in an object - * @param {Object} object - * @param {String} key - * @param {*} value - * @return {Boolean} changed - */ -util.updateProperty = function updateProp (object, key, value) { - if (object[key] !== value) { - object[key] = value; - return true; - } - else { return false; - } -}; + }, -/** - * Add and event listener. Works for all browsers - * @param {Element} element An html element - * @param {string} action The action, for example "click", - * without the prefix "on" - * @param {function} listener The callback function to be executed - * @param {boolean} [useCapture] - */ -util.addEventListener = function addEventListener(element, action, listener, useCapture) { - if (element.addEventListener) { - if (useCapture === undefined) - useCapture = false; - if (action === "mousewheel" && navigator.userAgent.indexOf("Firefox") >= 0) { - action = "DOMMouseScroll"; // For Firefox + /** + * get the center of all the touches + * @param {Array} touches + * @returns {Object} center + */ + getCenter: function getCenter(touches) { + var valuesX = [], valuesY = []; + + for(var t= 0,len=touches.length; t= 0) { - action = "DOMMouseScroll"; // For Firefox - } + /** + * calculate the velocity between two points + * @param {Number} delta_time + * @param {Number} delta_x + * @param {Number} delta_y + * @returns {Object} velocity + */ + getVelocity: function getVelocity(delta_time, delta_x, delta_y) { + return { + x: Math.abs(delta_x / delta_time) || 0, + y: Math.abs(delta_y / delta_time) || 0 + }; + }, - element.removeEventListener(action, listener, useCapture); - } else { - // IE browsers - element.detachEvent("on" + action, listener); - } -}; + /** + * calculate the angle between two coordinates + * @param {Touch} touch1 + * @param {Touch} touch2 + * @returns {Number} angle + */ + getAngle: function getAngle(touch1, touch2) { + var y = touch2.pageY - touch1.pageY, + x = touch2.pageX - touch1.pageX; + return Math.atan2(y, x) * 180 / Math.PI; + }, -/** - * Get HTML element which is the target of the event - * @param {Event} event - * @return {Element} target element - */ -util.getTarget = function getTarget(event) { - // code from http://www.quirksmode.org/js/events_properties.html - if (!event) { - event = window.event; - } - var target; + /** + * angle to direction define + * @param {Touch} touch1 + * @param {Touch} touch2 + * @returns {String} direction constant, like Hammer.DIRECTION_LEFT + */ + getDirection: function getDirection(touch1, touch2) { + var x = Math.abs(touch1.pageX - touch2.pageX), + y = Math.abs(touch1.pageY - touch2.pageY); - if (event.target) { - target = event.target; - } - else if (event.srcElement) { - target = event.srcElement; - } + if(x >= y) { + return touch1.pageX - touch2.pageX > 0 ? Hammer.DIRECTION_LEFT : Hammer.DIRECTION_RIGHT; + } + else { + return touch1.pageY - touch2.pageY > 0 ? Hammer.DIRECTION_UP : Hammer.DIRECTION_DOWN; + } + }, - if (target.nodeType != undefined && target.nodeType == 3) { - // defeat Safari bug - target = target.parentNode; - } - return target; -}; + /** + * calculate the distance between two touches + * @param {Touch} touch1 + * @param {Touch} touch2 + * @returns {Number} distance + */ + getDistance: function getDistance(touch1, touch2) { + var x = touch2.pageX - touch1.pageX, + y = touch2.pageY - touch1.pageY; + return Math.sqrt((x*x) + (y*y)); + }, -/** - * Stop event propagation - */ -util.stopPropagation = function stopPropagation(event) { - if (!event) - event = window.event; - if (event.stopPropagation) { - event.stopPropagation(); // non-IE browsers - } - else { - event.cancelBubble = true; // IE browsers - } -}; + /** + * calculate the scale factor between two touchLists (fingers) + * no scale is 1, and goes down to 0 when pinched together, and bigger when pinched out + * @param {Array} start + * @param {Array} end + * @returns {Number} scale + */ + getScale: function getScale(start, end) { + // need two fingers... + if(start.length >= 2 && end.length >= 2) { + return this.getDistance(end[0], end[1]) / + this.getDistance(start[0], start[1]); + } + return 1; + }, -/** - * Cancels the event if it is cancelable, without stopping further propagation of the event. - */ -util.preventDefault = function preventDefault (event) { - if (!event) - event = window.event; + /** + * calculate the rotation degrees between two touchLists (fingers) + * @param {Array} start + * @param {Array} end + * @returns {Number} rotation + */ + getRotation: function getRotation(start, end) { + // need two fingers + if(start.length >= 2 && end.length >= 2) { + return this.getAngle(end[1], end[0]) - + this.getAngle(start[1], start[0]); + } + return 0; + }, - if (event.preventDefault) { - event.preventDefault(); // non-IE browsers - } - else { - event.returnValue = false; // IE browsers - } -}; + /** + * boolean if the direction is vertical + * @param {String} direction + * @returns {Boolean} is_vertical + */ + isVertical: function isVertical(direction) { + return (direction == Hammer.DIRECTION_UP || direction == Hammer.DIRECTION_DOWN); + }, -util.option = {}; -/** - * Convert a value into a boolean - * @param {Boolean | function | undefined} value - * @param {Boolean} [defaultValue] - * @returns {Boolean} bool - */ -util.option.asBoolean = function (value, defaultValue) { - if (typeof value == 'function') { - value = value(); - } + /** + * stop browser default behavior with css props + * @param {HtmlElement} element + * @param {Object} css_props + */ + stopDefaultBrowserBehavior: function stopDefaultBrowserBehavior(element, css_props) { + var prop, + vendors = ['webkit','khtml','moz','ms','o','']; - if (value != null) { - return (value != false); - } + if(!css_props || !element.style) { + return; + } - return defaultValue || null; -}; + // with css properties for modern browsers + for(var i = 0; i < vendors.length; i++) { + for(var p in css_props) { + if(css_props.hasOwnProperty(p)) { + prop = p; -/** - * Convert a value into a number - * @param {Boolean | function | undefined} value - * @param {Number} [defaultValue] - * @returns {Number} number - */ -util.option.asNumber = function (value, defaultValue) { - if (typeof value == 'function') { - value = value(); - } + // vender prefix at the property + if(vendors[i]) { + prop = vendors[i] + prop.substring(0, 1).toUpperCase() + prop.substring(1); + } - if (value != null) { - return Number(value) || defaultValue || null; - } + // set the style + element.style[prop] = css_props[p]; + } + } + } - return defaultValue || null; + // also the disable onselectstart + if(css_props.userSelect == 'none') { + element.onselectstart = function() { + return false; + }; + } + } }; -/** - * Convert a value into a string - * @param {String | function | undefined} value - * @param {String} [defaultValue] - * @returns {String} str - */ -util.option.asString = function (value, defaultValue) { - if (typeof value == 'function') { - value = value(); - } +Hammer.detection = { + // contains all registred Hammer.gestures in the correct order + gestures: [], - if (value != null) { - return String(value); - } + // data of the current Hammer.gesture detection session + current: null, - return defaultValue || null; -}; + // the previous Hammer.gesture session data + // is a full clone of the previous gesture.current object + previous: null, -/** - * Convert a size or location into a string with pixels or a percentage - * @param {String | Number | function | undefined} value - * @param {String} [defaultValue] - * @returns {String} size - */ -util.option.asSize = function (value, defaultValue) { - if (typeof value == 'function') { - value = value(); - } + // when this becomes true, no gestures are fired + stopped: false, - if (util.isString(value)) { - return value; - } - else if (util.isNumber(value)) { - return value + 'px'; - } - else { - return defaultValue || null; - } -}; -/** - * Convert a value into a DOM element - * @param {HTMLElement | function | undefined} value - * @param {HTMLElement} [defaultValue] - * @returns {HTMLElement | null} dom - */ -util.option.asElement = function (value, defaultValue) { - if (typeof value == 'function') { - value = value(); - } + /** + * start Hammer.gesture detection + * @param {Hammer.Instance} inst + * @param {Object} eventData + */ + startDetect: function startDetect(inst, eventData) { + // already busy with a Hammer.gesture detection on an element + if(this.current) { + return; + } - return value || defaultValue || null; -}; + this.stopped = false; -/** - * load css from text - * @param {String} css Text containing css - */ -util.loadCss = function (css) { - if (typeof document === 'undefined') { - return; - } + this.current = { + inst : inst, // reference to HammerInstance we're working for + startEvent : Hammer.utils.extend({}, eventData), // start eventData for distances, timing etc + lastEvent : false, // last eventData + name : '' // current gesture we're in/detected, can be 'tap', 'hold' etc + }; - // get the script location, and built the css file name from the js file name - // http://stackoverflow.com/a/2161748/1262753 - // var scripts = document.getElementsByTagName('script'); - // var jsFile = scripts[scripts.length-1].src.split('?')[0]; - // var cssFile = jsFile.substring(0, jsFile.length - 2) + 'css'; + this.detect(eventData); + }, - // inject css - // http://stackoverflow.com/questions/524696/how-to-create-a-style-tag-with-javascript - var style = document.createElement('style'); - style.type = 'text/css'; - if (style.styleSheet){ - style.styleSheet.cssText = css; - } else { - style.appendChild(document.createTextNode(css)); - } - document.getElementsByTagName('head')[0].appendChild(style); -}; + /** + * Hammer.gesture detection + * @param {Object} eventData + * @param {Object} eventData + */ + detect: function detect(eventData) { + if(!this.current || this.stopped) { + return; + } + // extend event data with calculations about scale, distance etc + eventData = this.extendEventData(eventData); -// Internet Explorer 8 and older does not support Array.indexOf, so we define -// it here in that case. -// http://soledadpenades.com/2007/05/17/arrayindexof-in-internet-explorer/ -if(!Array.prototype.indexOf) { - Array.prototype.indexOf = function(obj){ - for(var i = 0; i < this.length; i++){ - if(this[i] == obj){ - return i; + // instance options + var inst_options = this.current.inst.options; + + // call Hammer.gesture handlers + for(var g=0,len=this.gestures.length; g>> 0; + // stopped! + this.stopped = true; + }, - // 4. If IsCallable(callback) is false, throw a TypeError exception. - // See: http://es5.github.com/#x9.11 - if (typeof callback !== "function") { - throw new TypeError(callback + " is not a function"); - } - // 5. If thisArg was supplied, let T be thisArg; else let T be undefined. - if (thisArg) { - T = thisArg; + /** + * extend eventData for Hammer.gestures + * @param {Object} ev + * @returns {Object} ev + */ + extendEventData: function extendEventData(ev) { + var startEv = this.current.startEvent; + + // if the touches change, set the new touches over the startEvent touches + // this because touchevents don't have all the touches on touchstart, or the + // user must place his fingers at the EXACT same time on the screen, which is not realistic + // but, sometimes it happens that both fingers are touching at the EXACT same time + if(startEv && (ev.touches.length != startEv.touches.length || ev.touches === startEv.touches)) { + // extend 1 level deep to get the touchlist with the touch objects + startEv.touches = []; + for(var i=0,len=ev.touches.length; i>> 0; - if (typeof fun != "function") { - throw new TypeError(); - } + // add Hammer.gesture to the list + this.gestures.push(gesture); - var res = []; - var thisp = arguments[1]; - for (var i = 0; i < len; i++) { - if (i in t) { - var val = t[i]; // in case fun mutates this - if (fun.call(thisp, val, i, t)) - res.push(val); + // sort the list by index + this.gestures.sort(function(a, b) { + if (a.index < b.index) { + return -1; } - } - - return res; - }; -} + if (a.index > b.index) { + return 1; + } + return 0; + }); + return this.gestures; + } +}; -// Internet Explorer 8 and older does not support Object.keys, so we define it -// here in that case. -// https://developer.mozilla.org/en-US/docs/JavaScript/Reference/Global_Objects/Object/keys -if (!Object.keys) { - Object.keys = (function () { - var hasOwnProperty = Object.prototype.hasOwnProperty, - hasDontEnumBug = !({toString: null}).propertyIsEnumerable('toString'), - dontEnums = [ - 'toString', - 'toLocaleString', - 'valueOf', - 'hasOwnProperty', - 'isPrototypeOf', - 'propertyIsEnumerable', - 'constructor' - ], - dontEnumsLength = dontEnums.length; - return function (obj) { - if (typeof obj !== 'object' && typeof obj !== 'function' || obj === null) { - throw new TypeError('Object.keys called on non-object'); - } +Hammer.gestures = Hammer.gestures || {}; - var result = []; +/** + * Custom gestures + * ============================== + * + * Gesture object + * -------------------- + * The object structure of a gesture: + * + * { name: 'mygesture', + * index: 1337, + * defaults: { + * mygesture_option: true + * } + * handler: function(type, ev, inst) { + * // trigger gesture event + * inst.trigger(this.name, ev); + * } + * } + + * @param {String} name + * this should be the name of the gesture, lowercase + * it is also being used to disable/enable the gesture per instance config. + * + * @param {Number} [index=1000] + * the index of the gesture, where it is going to be in the stack of gestures detection + * like when you build an gesture that depends on the drag gesture, it is a good + * idea to place it after the index of the drag gesture. + * + * @param {Object} [defaults={}] + * the default settings of the gesture. these are added to the instance settings, + * and can be overruled per instance. you can also add the name of the gesture, + * but this is also added by default (and set to true). + * + * @param {Function} handler + * this handles the gesture detection of your custom gesture and receives the + * following arguments: + * + * @param {Object} eventData + * event data containing the following properties: + * timeStamp {Number} time the event occurred + * target {HTMLElement} target element + * touches {Array} touches (fingers, pointers, mouse) on the screen + * pointerType {String} kind of pointer that was used. matches Hammer.POINTER_MOUSE|TOUCH + * center {Object} center position of the touches. contains pageX and pageY + * deltaTime {Number} the total time of the touches in the screen + * deltaX {Number} the delta on x axis we haved moved + * deltaY {Number} the delta on y axis we haved moved + * velocityX {Number} the velocity on the x + * velocityY {Number} the velocity on y + * angle {Number} the angle we are moving + * direction {String} the direction we are moving. matches Hammer.DIRECTION_UP|DOWN|LEFT|RIGHT + * distance {Number} the distance we haved moved + * scale {Number} scaling of the touches, needs 2 touches + * rotation {Number} rotation of the touches, needs 2 touches * + * eventType {String} matches Hammer.EVENT_START|MOVE|END + * srcEvent {Object} the source event, like TouchStart or MouseDown * + * startEvent {Object} contains the same properties as above, + * but from the first touch. this is used to calculate + * distances, deltaTime, scaling etc + * + * @param {Hammer.Instance} inst + * the instance we are doing the detection for. you can get the options from + * the inst.options object and trigger the gesture event by calling inst.trigger + * + * + * Handle gestures + * -------------------- + * inside the handler you can get/set Hammer.detection.current. This is the current + * detection session. It has the following properties + * @param {String} name + * contains the name of the gesture we have detected. it has not a real function, + * only to check in other gestures if something is detected. + * like in the drag gesture we set it to 'drag' and in the swipe gesture we can + * check if the current gesture is 'drag' by accessing Hammer.detection.current.name + * + * @readonly + * @param {Hammer.Instance} inst + * the instance we do the detection for + * + * @readonly + * @param {Object} startEvent + * contains the properties of the first gesture detection in this session. + * Used for calculations about timing, distance, etc. + * + * @readonly + * @param {Object} lastEvent + * contains all the properties of the last gesture detect in this session. + * + * after the gesture detection session has been completed (user has released the screen) + * the Hammer.detection.current object is copied into Hammer.detection.previous, + * this is usefull for gestures like doubletap, where you need to know if the + * previous gesture was a tap + * + * options that have been set by the instance can be received by calling inst.options + * + * You can trigger a gesture event by calling inst.trigger("mygesture", event). + * The first param is the name of your gesture, the second the event argument + * + * + * Register gestures + * -------------------- + * When an gesture is added to the Hammer.gestures object, it is auto registered + * at the setup of the first Hammer instance. You can also call Hammer.detection.register + * manually and pass your gesture object as a param + * + */ - for (var prop in obj) { - if (hasOwnProperty.call(obj, prop)) result.push(prop); - } +/** + * Hold + * Touch stays at the same place for x time + * @events hold + */ +Hammer.gestures.Hold = { + name: 'hold', + index: 10, + defaults: { + hold_timeout : 500, + hold_threshold : 1 + }, + timer: null, + handler: function holdGesture(ev, inst) { + switch(ev.eventType) { + case Hammer.EVENT_START: + // clear any running timers + clearTimeout(this.timer); + + // set the gesture so we can check in the timeout if it still is + Hammer.detection.current.name = this.name; + + // set timer and if after the timeout it still is hold, + // we trigger the hold event + this.timer = setTimeout(function() { + if(Hammer.detection.current.name == 'hold') { + inst.trigger('hold', ev); + } + }, inst.options.hold_timeout); + break; - if (hasDontEnumBug) { - for (var i=0; i < dontEnumsLength; i++) { - if (hasOwnProperty.call(obj, dontEnums[i])) result.push(dontEnums[i]); + // when you move or end we clear the timer + case Hammer.EVENT_MOVE: + if(ev.distance > inst.options.hold_threshold) { + clearTimeout(this.timer); } - } - return result; - } - })() -} - -// Internet Explorer 8 and older does not support Array.isArray, -// so we define it here in that case. -// https://developer.mozilla.org/en-US/docs/JavaScript/Reference/Global_Objects/Array/isArray -if(!Array.isArray) { - Array.isArray = function (vArg) { - return Object.prototype.toString.call(vArg) === "[object Array]"; - }; -} + break; -// Internet Explorer 8 and older does not support Function.bind, -// so we define it here in that case. -// https://developer.mozilla.org/en-US/docs/JavaScript/Reference/Global_Objects/Function/bind -if (!Function.prototype.bind) { - Function.prototype.bind = function (oThis) { - if (typeof this !== "function") { - // closest thing possible to the ECMAScript 5 internal IsCallable function - throw new TypeError("Function.prototype.bind - what is trying to be bound is not callable"); + case Hammer.EVENT_END: + clearTimeout(this.timer); + break; } + } +}; - var aArgs = Array.prototype.slice.call(arguments, 1), - fToBind = this, - fNOP = function () {}, - fBound = function () { - return fToBind.apply(this instanceof fNOP && oThis - ? this - : oThis, - aArgs.concat(Array.prototype.slice.call(arguments))); - }; - fNOP.prototype = this.prototype; - fBound.prototype = new fNOP(); +/** + * Tap/DoubleTap + * Quick touch at a place or double at the same place + * @events tap, doubletap + */ +Hammer.gestures.Tap = { + name: 'tap', + index: 100, + defaults: { + tap_max_touchtime : 250, + tap_max_distance : 10, + tap_always : true, + doubletap_distance : 20, + doubletap_interval : 300 + }, + handler: function tapGesture(ev, inst) { + if(ev.eventType == Hammer.EVENT_END) { + // previous gesture, for the double tap since these are two different gesture detections + var prev = Hammer.detection.previous, + did_doubletap = false; - return fBound; - }; -} + // when the touchtime is higher then the max touch time + // or when the moving distance is too much + if(ev.deltaTime > inst.options.tap_max_touchtime || + ev.distance > inst.options.tap_max_distance) { + return; + } -// https://developer.mozilla.org/en-US/docs/JavaScript/Reference/Global_Objects/Object/create -if (!Object.create) { - Object.create = function (o) { - if (arguments.length > 1) { - throw new Error('Object.create implementation only accepts the first parameter.'); + // check if double tap + if(prev && prev.name == 'tap' && + (ev.timeStamp - prev.lastEvent.timeStamp) < inst.options.doubletap_interval && + ev.distance < inst.options.doubletap_distance) { + inst.trigger('doubletap', ev); + did_doubletap = true; + } + + // do a single tap + if(!did_doubletap || inst.options.tap_always) { + Hammer.detection.current.name = 'tap'; + inst.trigger(Hammer.detection.current.name, ev); + } } - function F() {} - F.prototype = o; - return new F(); - }; -} + } +}; + /** - * Event listener (singleton) + * Swipe + * triggers swipe events when the end velocity is above the threshold + * @events swipe, swipeleft, swiperight, swipeup, swipedown */ -// TODO: replace usage of the event listener for the EventBus -var events = { - 'listeners': [], +Hammer.gestures.Swipe = { + name: 'swipe', + index: 40, + defaults: { + // set 0 for unlimited, but this can conflict with transform + swipe_max_touches : 1, + swipe_velocity : 0.7 + }, + handler: function swipeGesture(ev, inst) { + if(ev.eventType == Hammer.EVENT_END) { + // max touches + if(inst.options.swipe_max_touches > 0 && + ev.touches.length > inst.options.swipe_max_touches) { + return; + } + + // when the distance we moved is too small we skip this gesture + // or we can be already in dragging + if(ev.velocityX > inst.options.swipe_velocity || + ev.velocityY > inst.options.swipe_velocity) { + // trigger swipe events + inst.trigger(this.name, ev); + inst.trigger(this.name + ev.direction, ev); + } + } + } +}; + + +/** + * Drag + * Move with x fingers (default 1) around on the page. Blocking the scrolling when + * moving left and right is a good practice. When all the drag events are blocking + * you disable scrolling on that area. + * @events drag, drapleft, dragright, dragup, dragdown + */ +Hammer.gestures.Drag = { + name: 'drag', + index: 50, + defaults: { + drag_min_distance : 10, + // set 0 for unlimited, but this can conflict with transform + drag_max_touches : 1, + // prevent default browser behavior when dragging occurs + // be careful with it, it makes the element a blocking element + // when you are using the drag gesture, it is a good practice to set this true + drag_block_horizontal : false, + drag_block_vertical : false, + // drag_lock_to_axis keeps the drag gesture on the axis that it started on, + // It disallows vertical directions if the initial direction was horizontal, and vice versa. + drag_lock_to_axis : false, + // drag lock only kicks in when distance > drag_lock_min_distance + // This way, locking occurs only when the distance has become large enough to reliably determine the direction + drag_lock_min_distance : 25 + }, + triggered: false, + handler: function dragGesture(ev, inst) { + // current gesture isnt drag, but dragged is true + // this means an other gesture is busy. now call dragend + if(Hammer.detection.current.name != this.name && this.triggered) { + inst.trigger(this.name +'end', ev); + this.triggered = false; + return; + } - /** - * Find a single listener by its object - * @param {Object} object - * @return {Number} index -1 when not found - */ - 'indexOf': function (object) { - var listeners = this.listeners; - for (var i = 0, iMax = this.listeners.length; i < iMax; i++) { - var listener = listeners[i]; - if (listener && listener.object == object) { - return i; - } + // max touches + if(inst.options.drag_max_touches > 0 && + ev.touches.length > inst.options.drag_max_touches) { + return; } - return -1; - }, - /** - * Add an event listener - * @param {Object} object - * @param {String} event The name of an event, for example 'select' - * @param {function} callback The callback method, called when the - * event takes place - */ - 'addListener': function (object, event, callback) { - var index = this.indexOf(object); - var listener = this.listeners[index]; - if (!listener) { - listener = { - 'object': object, - 'events': {} - }; - this.listeners.push(listener); - } + switch(ev.eventType) { + case Hammer.EVENT_START: + this.triggered = false; + break; - var callbacks = listener.events[event]; - if (!callbacks) { - callbacks = []; - listener.events[event] = callbacks; - } + case Hammer.EVENT_MOVE: + // when the distance we moved is too small we skip this gesture + // or we can be already in dragging + if(ev.distance < inst.options.drag_min_distance && + Hammer.detection.current.name != this.name) { + return; + } - // add the callback if it does not yet exist - if (callbacks.indexOf(callback) == -1) { - callbacks.push(callback); - } - }, + // we are dragging! + Hammer.detection.current.name = this.name; - /** - * Remove an event listener - * @param {Object} object - * @param {String} event The name of an event, for example 'select' - * @param {function} callback The registered callback method - */ - 'removeListener': function (object, event, callback) { - var index = this.indexOf(object); - var listener = this.listeners[index]; - if (listener) { - var callbacks = listener.events[event]; - if (callbacks) { - index = callbacks.indexOf(callback); - if (index != -1) { - callbacks.splice(index, 1); + // lock drag to axis? + if(Hammer.detection.current.lastEvent.drag_locked_to_axis || (inst.options.drag_lock_to_axis && inst.options.drag_lock_min_distance<=ev.distance)) { + ev.drag_locked_to_axis = true; } - - // remove the array when empty - if (callbacks.length == 0) { - delete listener.events[event]; + var last_direction = Hammer.detection.current.lastEvent.direction; + if(ev.drag_locked_to_axis && last_direction !== ev.direction) { + // keep direction on the axis that the drag gesture started on + if(Hammer.utils.isVertical(last_direction)) { + ev.direction = (ev.deltaY < 0) ? Hammer.DIRECTION_UP : Hammer.DIRECTION_DOWN; + } + else { + ev.direction = (ev.deltaX < 0) ? Hammer.DIRECTION_LEFT : Hammer.DIRECTION_RIGHT; + } } - } - // count the number of registered events. remove listener when empty - var count = 0; - var events = listener.events; - for (var e in events) { - if (events.hasOwnProperty(e)) { - count++; + // first time, trigger dragstart event + if(!this.triggered) { + inst.trigger(this.name +'start', ev); + this.triggered = true; } - } - if (count == 0) { - delete this.listeners[index]; - } - } - }, - /** - * Remove all registered event listeners - */ - 'removeAllListeners': function () { - this.listeners = []; - }, + // trigger normal event + inst.trigger(this.name, ev); - /** - * Trigger an event. All registered event handlers will be called - * @param {Object} object - * @param {String} event - * @param {Object} properties (optional) - */ - 'trigger': function (object, event, properties) { - var index = this.indexOf(object); - var listener = this.listeners[index]; - if (listener) { - var callbacks = listener.events[event]; - if (callbacks) { - for (var i = 0, iMax = callbacks.length; i < iMax; i++) { - callbacks[i](properties); + // direction event, like dragdown + inst.trigger(this.name + ev.direction, ev); + + // block the browser events + if( (inst.options.drag_block_vertical && Hammer.utils.isVertical(ev.direction)) || + (inst.options.drag_block_horizontal && !Hammer.utils.isVertical(ev.direction))) { + ev.preventDefault(); } - } + break; + + case Hammer.EVENT_END: + // trigger dragend + if(this.triggered) { + inst.trigger(this.name +'end', ev); + } + + this.triggered = false; + break; } } }; -/** - * An event bus can be used to emit events, and to subscribe to events - * @constructor EventBus - */ -function EventBus() { - this.subscriptions = []; -} /** - * Subscribe to an event - * @param {String | RegExp} event The event can be a regular expression, or - * a string with wildcards, like 'server.*'. - * @param {function} callback. Callback are called with three parameters: - * {String} event, {*} [data], {*} [source] - * @param {*} [target] - * @returns {String} id A subscription id + * Transform + * User want to scale or rotate with 2 fingers + * @events transform, pinch, pinchin, pinchout, rotate */ -EventBus.prototype.on = function (event, callback, target) { - var regexp = (event instanceof RegExp) ? - event : - new RegExp(event.replace('*', '\\w+')); +Hammer.gestures.Transform = { + name: 'transform', + index: 45, + defaults: { + // factor, no scale is 1, zoomin is to 0 and zoomout until higher then 1 + transform_min_scale : 0.01, + // rotation in degrees + transform_min_rotation : 1, + // prevent default browser behavior when two touches are on the screen + // but it makes the element a blocking element + // when you are using the transform gesture, it is a good practice to set this true + transform_always_block : false + }, + triggered: false, + handler: function transformGesture(ev, inst) { + // current gesture isnt drag, but dragged is true + // this means an other gesture is busy. now call dragend + if(Hammer.detection.current.name != this.name && this.triggered) { + inst.trigger(this.name +'end', ev); + this.triggered = false; + return; + } - var subscription = { - id: util.randomUUID(), - event: event, - regexp: regexp, - callback: (typeof callback === 'function') ? callback : null, - target: target - }; + // atleast multitouch + if(ev.touches.length < 2) { + return; + } - this.subscriptions.push(subscription); + // prevent default when two fingers are on the screen + if(inst.options.transform_always_block) { + ev.preventDefault(); + } - return subscription.id; + switch(ev.eventType) { + case Hammer.EVENT_START: + this.triggered = false; + break; + + case Hammer.EVENT_MOVE: + var scale_threshold = Math.abs(1-ev.scale); + var rotation_threshold = Math.abs(ev.rotation); + + // when the distance we moved is too small we skip this gesture + // or we can be already in dragging + if(scale_threshold < inst.options.transform_min_scale && + rotation_threshold < inst.options.transform_min_rotation) { + return; + } + + // we are transforming! + Hammer.detection.current.name = this.name; + + // first time, trigger dragstart event + if(!this.triggered) { + inst.trigger(this.name +'start', ev); + this.triggered = true; + } + + inst.trigger(this.name, ev); // basic transform event + + // trigger rotate event + if(rotation_threshold > inst.options.transform_min_rotation) { + inst.trigger('rotate', ev); + } + + // trigger pinch event + if(scale_threshold > inst.options.transform_min_scale) { + inst.trigger('pinch', ev); + inst.trigger('pinch'+ ((ev.scale < 1) ? 'in' : 'out'), ev); + } + break; + + case Hammer.EVENT_END: + // trigger dragend + if(this.triggered) { + inst.trigger(this.name +'end', ev); + } + + this.triggered = false; + break; + } + } }; + /** - * Unsubscribe from an event - * @param {String | Object} filter Filter for subscriptions to be removed - * Filter can be a string containing a - * subscription id, or an object containing - * one or more of the fields id, event, - * callback, and target. + * Touch + * Called as first, tells the user has touched the screen + * @events touch */ -EventBus.prototype.off = function (filter) { - var i = 0; - while (i < this.subscriptions.length) { - var subscription = this.subscriptions[i]; +Hammer.gestures.Touch = { + name: 'touch', + index: -Infinity, + defaults: { + // call preventDefault at touchstart, and makes the element blocking by + // disabling the scrolling of the page, but it improves gestures like + // transforming and dragging. + // be careful with using this, it can be very annoying for users to be stuck + // on the page + prevent_default: false, - var match = true; - if (filter instanceof Object) { - // filter is an object. All fields must match - for (var prop in filter) { - if (filter.hasOwnProperty(prop)) { - if (filter[prop] !== subscription[prop]) { - match = false; - } - } - } - } - else { - // filter is a string, filter on id - match = (subscription.id == filter); + // disable mouse events, so only touch (or pen!) input triggers events + prevent_mouseevents: false + }, + handler: function touchGesture(ev, inst) { + if(inst.options.prevent_mouseevents && ev.pointerType == Hammer.POINTER_MOUSE) { + ev.stopDetect(); + return; } - if (match) { - this.subscriptions.splice(i, 1); + if(inst.options.prevent_default) { + ev.preventDefault(); } - else { - i++; + + if(ev.eventType == Hammer.EVENT_START) { + inst.trigger(this.name, ev); } } }; + /** - * Emit an event - * @param {String} event - * @param {*} [data] - * @param {*} [source] + * Release + * Called as last, tells the user has released the screen + * @events release */ -EventBus.prototype.emit = function (event, data, source) { - for (var i =0; i < this.subscriptions.length; i++) { - var subscription = this.subscriptions[i]; - if (subscription.regexp.test(event)) { - if (subscription.callback) { - subscription.callback(event, data, source); - } +Hammer.gestures.Release = { + name: 'release', + index: Infinity, + handler: function releaseGesture(ev, inst) { + if(ev.eventType == Hammer.EVENT_END) { + inst.trigger(this.name, ev); } } }; -/** - * DataSet - * - * Usage: - * var dataSet = new DataSet({ - * fieldId: '_id', - * convert: { - * // ... - * } - * }); - * - * dataSet.add(item); - * dataSet.add(data); - * dataSet.update(item); - * dataSet.update(data); - * dataSet.remove(id); - * dataSet.remove(ids); - * var data = dataSet.get(); - * var data = dataSet.get(id); - * var data = dataSet.get(ids); - * var data = dataSet.get(ids, options, data); - * dataSet.clear(); - * - * A data set can: - * - add/remove/update data - * - gives triggers upon changes in the data - * - can import/export data in various data formats - * - * @param {Object} [options] Available options: - * {String} fieldId Field name of the id in the - * items, 'id' by default. - * {Object. ["10", "00"] or "-1530" > ["-15", "30"] + parseTimezoneChunker = /([\+\-]|\d\d)/gi, - if (addedIds.length) { - this._trigger('add', {items: addedIds}, senderId); - } + // getter and setter names + proxyGettersAndSetters = 'Date|Hours|Minutes|Seconds|Milliseconds'.split('|'), + unitMillisecondFactors = { + 'Milliseconds' : 1, + 'Seconds' : 1e3, + 'Minutes' : 6e4, + 'Hours' : 36e5, + 'Days' : 864e5, + 'Months' : 2592e6, + 'Years' : 31536e6 + }, - return addedIds; -}; + unitAliases = { + ms : 'millisecond', + s : 'second', + m : 'minute', + h : 'hour', + d : 'day', + w : 'week', + W : 'isoweek', + M : 'month', + y : 'year' + }, -/** - * Update existing items. When an item does not exist, it will be created - * @param {Object | Array | DataTable} data - * @param {String} [senderId] Optional sender id - * @return {Array} updatedIds The ids of the added or updated items - */ -DataSet.prototype.update = function (data, senderId) { - var addedIds = [], - updatedIds = [], - me = this, - fieldId = me.fieldId; + // format function strings + formatFunctions = {}, - var addOrUpdate = function (item) { - var id = item[fieldId]; - if (me.data[id]) { - // update item - id = me._updateItem(item); - updatedIds.push(id); - } - else { - // add new item - id = me._addItem(item); - addedIds.push(id); - } - }; + // tokens to ordinalize and pad + ordinalizeTokens = 'DDD w W M D d'.split(' '), + paddedTokens = 'M D H h m s w W'.split(' '), - if (data instanceof Array) { - // Array - for (var i = 0, len = data.length; i < len; i++) { - addOrUpdate(data[i]); - } - } - else if (util.isDataTable(data)) { - // Google DataTable - var columns = this._getColumnNames(data); - for (var row = 0, rows = data.getNumberOfRows(); row < rows; row++) { - var item = {}; - for (var col = 0, cols = columns.length; col < cols; col++) { - var field = columns[col]; - item[field] = data.getValue(row, col); + formatTokenFunctions = { + M : function () { + return this.month() + 1; + }, + MMM : function (format) { + return this.lang().monthsShort(this, format); + }, + MMMM : function (format) { + return this.lang().months(this, format); + }, + D : function () { + return this.date(); + }, + DDD : function () { + return this.dayOfYear(); + }, + d : function () { + return this.day(); + }, + dd : function (format) { + return this.lang().weekdaysMin(this, format); + }, + ddd : function (format) { + return this.lang().weekdaysShort(this, format); + }, + dddd : function (format) { + return this.lang().weekdays(this, format); + }, + w : function () { + return this.week(); + }, + W : function () { + return this.isoWeek(); + }, + YY : function () { + return leftZeroFill(this.year() % 100, 2); + }, + YYYY : function () { + return leftZeroFill(this.year(), 4); + }, + YYYYY : function () { + return leftZeroFill(this.year(), 5); + }, + gg : function () { + return leftZeroFill(this.weekYear() % 100, 2); + }, + gggg : function () { + return this.weekYear(); + }, + ggggg : function () { + return leftZeroFill(this.weekYear(), 5); + }, + GG : function () { + return leftZeroFill(this.isoWeekYear() % 100, 2); + }, + GGGG : function () { + return this.isoWeekYear(); + }, + GGGGG : function () { + return leftZeroFill(this.isoWeekYear(), 5); + }, + e : function () { + return this.weekday(); + }, + E : function () { + return this.isoWeekday(); + }, + a : function () { + return this.lang().meridiem(this.hours(), this.minutes(), true); + }, + A : function () { + return this.lang().meridiem(this.hours(), this.minutes(), false); + }, + H : function () { + return this.hours(); + }, + h : function () { + return this.hours() % 12 || 12; + }, + m : function () { + return this.minutes(); + }, + s : function () { + return this.seconds(); + }, + S : function () { + return ~~(this.milliseconds() / 100); + }, + SS : function () { + return leftZeroFill(~~(this.milliseconds() / 10), 2); + }, + SSS : function () { + return leftZeroFill(this.milliseconds(), 3); + }, + Z : function () { + var a = -this.zone(), + b = "+"; + if (a < 0) { + a = -a; + b = "-"; + } + return b + leftZeroFill(~~(a / 60), 2) + ":" + leftZeroFill(~~a % 60, 2); + }, + ZZ : function () { + var a = -this.zone(), + b = "+"; + if (a < 0) { + a = -a; + b = "-"; + } + return b + leftZeroFill(~~(10 * a / 6), 4); + }, + z : function () { + return this.zoneAbbr(); + }, + zz : function () { + return this.zoneName(); + }, + X : function () { + return this.unix(); } + }; - addOrUpdate(item); - } - } - else if (data instanceof Object) { - // Single item - addOrUpdate(data); - } - else { - throw new Error('Unknown dataType'); - } - - if (addedIds.length) { - this._trigger('add', {items: addedIds}, senderId); - } - if (updatedIds.length) { - this._trigger('update', {items: updatedIds}, senderId); - } - - return addedIds.concat(updatedIds); -}; - -/** - * Get a data item or multiple items. - * - * Usage: - * - * get() - * get(options: Object) - * get(options: Object, data: Array | DataTable) - * - * get(id: Number | String) - * get(id: Number | String, options: Object) - * get(id: Number | String, options: Object, data: Array | DataTable) - * - * get(ids: Number[] | String[]) - * get(ids: Number[] | String[], options: Object) - * get(ids: Number[] | String[], options: Object, data: Array | DataTable) - * - * Where: - * - * {Number | String} id The id of an item - * {Number[] | String{}} ids An array with ids of items - * {Object} options An Object with options. Available options: - * {String} [type] Type of data to be returned. Can - * be 'DataTable' or 'Array' (default) - * {Object.} [convert] - * {String[]} [fields] field names to be returned - * {function} [filter] filter items - * {String | function} [order] Order the items by - * a field name or custom sort function. - * {Array | DataTable} [data] If provided, items will be appended to this - * array or table. Required in case of Google - * DataTable. - * - * @throws Error - */ -DataSet.prototype.get = function (args) { - var me = this; - - // parse the arguments - var id, ids, options, data; - var firstType = util.getType(arguments[0]); - if (firstType == 'String' || firstType == 'Number') { - // get(id [, options] [, data]) - id = arguments[0]; - options = arguments[1]; - data = arguments[2]; + function padToken(func, count) { + return function (a) { + return leftZeroFill(func.call(this, a), count); + }; } - else if (firstType == 'Array') { - // get(ids [, options] [, data]) - ids = arguments[0]; - options = arguments[1]; - data = arguments[2]; + function ordinalizeToken(func, period) { + return function (a) { + return this.lang().ordinal(func.call(this, a), period); + }; } - else { - // get([, options] [, data]) - options = arguments[0]; - data = arguments[1]; + + while (ordinalizeTokens.length) { + i = ordinalizeTokens.pop(); + formatTokenFunctions[i + 'o'] = ordinalizeToken(formatTokenFunctions[i], i); + } + while (paddedTokens.length) { + i = paddedTokens.pop(); + formatTokenFunctions[i + i] = padToken(formatTokenFunctions[i], 2); } + formatTokenFunctions.DDDD = padToken(formatTokenFunctions.DDD, 3); - // determine the return type - var type; - if (options && options.type) { - type = (options.type == 'DataTable') ? 'DataTable' : 'Array'; - if (data && (type != util.getType(data))) { - throw new Error('Type of parameter "data" (' + util.getType(data) + ') ' + - 'does not correspond with specified options.type (' + options.type + ')'); - } - if (type == 'DataTable' && !util.isDataTable(data)) { - throw new Error('Parameter "data" must be a DataTable ' + - 'when options.type is "DataTable"'); - } - } - else if (data) { - type = (util.getType(data) == 'DataTable') ? 'DataTable' : 'Array'; + /************************************ + Constructors + ************************************/ + + function Language() { + } - else { - type = 'Array'; + + // Moment prototype object + function Moment(config) { + extend(this, config); } - // build options - var convert = options && options.convert || this.options.convert; - var filter = options && options.filter; - var items = [], item, itemId, i, len; + // Duration Constructor + function Duration(duration) { + var years = duration.years || duration.year || duration.y || 0, + months = duration.months || duration.month || duration.M || 0, + weeks = duration.weeks || duration.week || duration.w || 0, + days = duration.days || duration.day || duration.d || 0, + hours = duration.hours || duration.hour || duration.h || 0, + minutes = duration.minutes || duration.minute || duration.m || 0, + seconds = duration.seconds || duration.second || duration.s || 0, + milliseconds = duration.milliseconds || duration.millisecond || duration.ms || 0; - // convert items - if (id != undefined) { - // return a single item - item = me._getItem(id, convert); - if (filter && !filter(item)) { - item = null; - } + // store reference to input for deterministic cloning + this._input = duration; + + // representation for dateAddRemove + this._milliseconds = +milliseconds + + seconds * 1e3 + // 1000 + minutes * 6e4 + // 1000 * 60 + hours * 36e5; // 1000 * 60 * 60 + // Because of dateAddRemove treats 24 hours as different from a + // day when working around DST, we need to store them separately + this._days = +days + + weeks * 7; + // It is impossible translate months into days without knowing + // which months you are are talking about, so we have to store + // it separately. + this._months = +months + + years * 12; + + this._data = {}; + + this._bubble(); } - else if (ids != undefined) { - // return a subset of items - for (i = 0, len = ids.length; i < len; i++) { - item = me._getItem(ids[i], convert); - if (!filter || filter(item)) { - items.push(item); + + + /************************************ + Helpers + ************************************/ + + + function extend(a, b) { + for (var i in b) { + if (b.hasOwnProperty(i)) { + a[i] = b[i]; } } + return a; } - else { - // return all items - for (itemId in this.data) { - if (this.data.hasOwnProperty(itemId)) { - item = me._getItem(itemId, convert); - if (!filter || filter(item)) { - items.push(item); - } - } + + function absRound(number) { + if (number < 0) { + return Math.ceil(number); + } else { + return Math.floor(number); } } - // order the results - if (options && options.order && id == undefined) { - this._sort(items, options.order); + // left zero fill a number + // see http://jsperf.com/left-zero-filling for performance comparison + function leftZeroFill(number, targetLength) { + var output = number + ''; + while (output.length < targetLength) { + output = '0' + output; + } + return output; } - // filter fields of the items - if (options && options.fields) { - var fields = options.fields; - if (id != undefined) { - item = this._filterFields(item, fields); + // helper function for _.addTime and _.subtractTime + function addOrSubtractDurationFromMoment(mom, duration, isAdding, ignoreUpdateOffset) { + var milliseconds = duration._milliseconds, + days = duration._days, + months = duration._months, + minutes, + hours; + + if (milliseconds) { + mom._d.setTime(+mom._d + milliseconds * isAdding); } - else { - for (i = 0, len = items.length; i < len; i++) { - items[i] = this._filterFields(items[i], fields); - } + // store the minutes and hours so we can restore them + if (days || months) { + minutes = mom.minute(); + hours = mom.hour(); + } + if (days) { + mom.date(mom.date() + days * isAdding); + } + if (months) { + mom.month(mom.month() + months * isAdding); + } + if (milliseconds && !ignoreUpdateOffset) { + moment.updateOffset(mom); + } + // restore the minutes and hours after possibly changing dst + if (days || months) { + mom.minute(minutes); + mom.hour(hours); } } - // return the results - if (type == 'DataTable') { - var columns = this._getColumnNames(data); - if (id != undefined) { - // append a single item to the data table - me._appendRow(data, columns, item); - } - else { - // copy the items to the provided data table - for (i = 0, len = items.length; i < len; i++) { - me._appendRow(data, columns, items[i]); + // check if is an array + function isArray(input) { + return Object.prototype.toString.call(input) === '[object Array]'; + } + + // compare two arrays, return the number of differences + function compareArrays(array1, array2) { + var len = Math.min(array1.length, array2.length), + lengthDiff = Math.abs(array1.length - array2.length), + diffs = 0, + i; + for (i = 0; i < len; i++) { + if (~~array1[i] !== ~~array2[i]) { + diffs++; } } - return data; + return diffs + lengthDiff; } - else { - // return an array - if (id != undefined) { - // a single item - return item; - } - else { - // multiple items - if (data) { - // copy the items to the provided array - for (i = 0, len = items.length; i < len; i++) { - data.push(items[i]); + + function normalizeUnits(units) { + return units ? unitAliases[units] || units.toLowerCase().replace(/(.)s$/, '$1') : units; + } + + + /************************************ + Languages + ************************************/ + + + extend(Language.prototype, { + + set : function (config) { + var prop, i; + for (i in config) { + prop = config[i]; + if (typeof prop === 'function') { + this[i] = prop; + } else { + this['_' + i] = prop; + } + } + }, + + _months : "January_February_March_April_May_June_July_August_September_October_November_December".split("_"), + months : function (m) { + return this._months[m.month()]; + }, + + _monthsShort : "Jan_Feb_Mar_Apr_May_Jun_Jul_Aug_Sep_Oct_Nov_Dec".split("_"), + monthsShort : function (m) { + return this._monthsShort[m.month()]; + }, + + monthsParse : function (monthName) { + var i, mom, regex; + + if (!this._monthsParse) { + this._monthsParse = []; + } + + for (i = 0; i < 12; i++) { + // make the regex if we don't have it already + if (!this._monthsParse[i]) { + mom = moment.utc([2000, i]); + regex = '^' + this.months(mom, '') + '|^' + this.monthsShort(mom, ''); + this._monthsParse[i] = new RegExp(regex.replace('.', ''), 'i'); + } + // test the regex + if (this._monthsParse[i].test(monthName)) { + return i; + } + } + }, + + _weekdays : "Sunday_Monday_Tuesday_Wednesday_Thursday_Friday_Saturday".split("_"), + weekdays : function (m) { + return this._weekdays[m.day()]; + }, + + _weekdaysShort : "Sun_Mon_Tue_Wed_Thu_Fri_Sat".split("_"), + weekdaysShort : function (m) { + return this._weekdaysShort[m.day()]; + }, + + _weekdaysMin : "Su_Mo_Tu_We_Th_Fr_Sa".split("_"), + weekdaysMin : function (m) { + return this._weekdaysMin[m.day()]; + }, + + weekdaysParse : function (weekdayName) { + var i, mom, regex; + + if (!this._weekdaysParse) { + this._weekdaysParse = []; + } + + for (i = 0; i < 7; i++) { + // make the regex if we don't have it already + if (!this._weekdaysParse[i]) { + mom = moment([2000, 1]).day(i); + regex = '^' + this.weekdays(mom, '') + '|^' + this.weekdaysShort(mom, '') + '|^' + this.weekdaysMin(mom, ''); + this._weekdaysParse[i] = new RegExp(regex.replace('.', ''), 'i'); + } + // test the regex + if (this._weekdaysParse[i].test(weekdayName)) { + return i; } - return data; } - else { - // just return our array - return items; + }, + + _longDateFormat : { + LT : "h:mm A", + L : "MM/DD/YYYY", + LL : "MMMM D YYYY", + LLL : "MMMM D YYYY LT", + LLLL : "dddd, MMMM D YYYY LT" + }, + longDateFormat : function (key) { + var output = this._longDateFormat[key]; + if (!output && this._longDateFormat[key.toUpperCase()]) { + output = this._longDateFormat[key.toUpperCase()].replace(/MMMM|MM|DD|dddd/g, function (val) { + return val.slice(1); + }); + this._longDateFormat[key] = output; } - } - } -}; + return output; + }, -/** - * Get ids of all items or from a filtered set of items. - * @param {Object} [options] An Object with options. Available options: - * {function} [filter] filter items - * {String | function} [order] Order the items by - * a field name or custom sort function. - * @return {Array} ids - */ -DataSet.prototype.getIds = function (options) { - var data = this.data, - filter = options && options.filter, - order = options && options.order, - convert = options && options.convert || this.options.convert, - i, - len, - id, - item, - items, - ids = []; + isPM : function (input) { + // IE8 Quirks Mode & IE7 Standards Mode do not allow accessing strings like arrays + // Using charAt should be more compatible. + return ((input + '').toLowerCase().charAt(0) === 'p'); + }, - if (filter) { - // get filtered items - if (order) { - // create ordered list - items = []; - for (id in data) { - if (data.hasOwnProperty(id)) { - item = this._getItem(id, convert); - if (filter(item)) { - items.push(item); - } - } + _meridiemParse : /[ap]\.?m?\.?/i, + meridiem : function (hours, minutes, isLower) { + if (hours > 11) { + return isLower ? 'pm' : 'PM'; + } else { + return isLower ? 'am' : 'AM'; } + }, - this._sort(items, order); + _calendar : { + sameDay : '[Today at] LT', + nextDay : '[Tomorrow at] LT', + nextWeek : 'dddd [at] LT', + lastDay : '[Yesterday at] LT', + lastWeek : '[Last] dddd [at] LT', + sameElse : 'L' + }, + calendar : function (key, mom) { + var output = this._calendar[key]; + return typeof output === 'function' ? output.apply(mom) : output; + }, - for (i = 0, len = items.length; i < len; i++) { - ids[i] = items[i][this.fieldId]; - } + _relativeTime : { + future : "in %s", + past : "%s ago", + s : "a few seconds", + m : "a minute", + mm : "%d minutes", + h : "an hour", + hh : "%d hours", + d : "a day", + dd : "%d days", + M : "a month", + MM : "%d months", + y : "a year", + yy : "%d years" + }, + relativeTime : function (number, withoutSuffix, string, isFuture) { + var output = this._relativeTime[string]; + return (typeof output === 'function') ? + output(number, withoutSuffix, string, isFuture) : + output.replace(/%d/i, number); + }, + pastFuture : function (diff, output) { + var format = this._relativeTime[diff > 0 ? 'future' : 'past']; + return typeof format === 'function' ? format(output) : format.replace(/%s/i, output); + }, + + ordinal : function (number) { + return this._ordinal.replace("%d", number); + }, + _ordinal : "%d", + + preparse : function (string) { + return string; + }, + + postformat : function (string) { + return string; + }, + + week : function (mom) { + return weekOfYear(mom, this._week.dow, this._week.doy).week; + }, + _week : { + dow : 0, // Sunday is the first day of the week. + doy : 6 // The week that contains Jan 1st is the first week of the year. } - else { - // create unordered list - for (id in data) { - if (data.hasOwnProperty(id)) { - item = this._getItem(id, convert); - if (filter(item)) { - ids.push(item[this.fieldId]); - } - } - } + }); + + // Loads a language definition into the `languages` cache. The function + // takes a key and optionally values. If not in the browser and no values + // are provided, it will load the language file module. As a convenience, + // this function also returns the language values. + function loadLang(key, values) { + values.abbr = key; + if (!languages[key]) { + languages[key] = new Language(); } + languages[key].set(values); + return languages[key]; } - else { - // get all items - if (order) { - // create an ordered list - items = []; - for (id in data) { - if (data.hasOwnProperty(id)) { - items.push(data[id]); - } - } - this._sort(items, order); + // Remove a language from the `languages` cache. Mostly useful in tests. + function unloadLang(key) { + delete languages[key]; + } - for (i = 0, len = items.length; i < len; i++) { - ids[i] = items[i][this.fieldId]; - } + // Determines which language definition to use and returns it. + // + // With no parameters, it will return the global language. If you + // pass in a language key, such as 'en', it will return the + // definition for 'en', so long as 'en' has already been loaded using + // moment.lang. + function getLangDefinition(key) { + if (!key) { + return moment.fn._lang; } - else { - // create unordered list - for (id in data) { - if (data.hasOwnProperty(id)) { - item = data[id]; - ids.push(item[this.fieldId]); - } + if (!languages[key] && hasModule) { + try { + require('./lang/' + key); + } catch (e) { + // call with no params to set to default + return moment.fn._lang; } } + return languages[key] || moment.fn._lang; } - return ids; -}; -/** - * Execute a callback function for every item in the dataset. - * The order of the items is not determined. - * @param {function} callback - * @param {Object} [options] Available options: - * {Object.} [convert] - * {String[]} [fields] filter fields - * {function} [filter] filter items - * {String | function} [order] Order the items by - * a field name or custom sort function. - */ -DataSet.prototype.forEach = function (callback, options) { - var filter = options && options.filter, - convert = options && options.convert || this.options.convert, - data = this.data, - item, - id; + /************************************ + Formatting + ************************************/ - if (options && options.order) { - // execute forEach on ordered list - var items = this.get(options); - for (var i = 0, len = items.length; i < len; i++) { - item = items[i]; - id = item[this.fieldId]; - callback(item, id); - } - } - else { - // unordered - for (id in data) { - if (data.hasOwnProperty(id)) { - item = this._getItem(id, convert); - if (!filter || filter(item)) { - callback(item, id); - } - } + function removeFormattingTokens(input) { + if (input.match(/\[.*\]/)) { + return input.replace(/^\[|\]$/g, ""); } + return input.replace(/\\/g, ""); } -}; -/** - * Map every item in the dataset. - * @param {function} callback - * @param {Object} [options] Available options: - * {Object.} [convert] - * {String[]} [fields] filter fields - * {function} [filter] filter items - * {String | function} [order] Order the items by - * a field name or custom sort function. - * @return {Object[]} mappedItems - */ -DataSet.prototype.map = function (callback, options) { - var filter = options && options.filter, - convert = options && options.convert || this.options.convert, - mappedItems = [], - data = this.data, - item; + function makeFormatFunction(format) { + var array = format.match(formattingTokens), i, length; - // convert and filter items - for (var id in data) { - if (data.hasOwnProperty(id)) { - item = this._getItem(id, convert); - if (!filter || filter(item)) { - mappedItems.push(callback(item, id)); + for (i = 0, length = array.length; i < length; i++) { + if (formatTokenFunctions[array[i]]) { + array[i] = formatTokenFunctions[array[i]]; + } else { + array[i] = removeFormattingTokens(array[i]); } } - } - // order items - if (options && options.order) { - this._sort(mappedItems, options.order); + return function (mom) { + var output = ""; + for (i = 0; i < length; i++) { + output += array[i] instanceof Function ? array[i].call(mom, format) : array[i]; + } + return output; + }; } - return mappedItems; -}; + // format date using native date object + function formatMoment(m, format) { -/** - * Filter the fields of an item - * @param {Object} item - * @param {String[]} fields Field names - * @return {Object} filteredItem - * @private - */ -DataSet.prototype._filterFields = function (item, fields) { - var filteredItem = {}; + format = expandFormat(format, m.lang()); - for (var field in item) { - if (item.hasOwnProperty(field) && (fields.indexOf(field) != -1)) { - filteredItem[field] = item[field]; + if (!formatFunctions[format]) { + formatFunctions[format] = makeFormatFunction(format); } - } - return filteredItem; -}; - -/** - * Sort the provided array with items - * @param {Object[]} items - * @param {String | function} order A field name or custom sort function. - * @private - */ -DataSet.prototype._sort = function (items, order) { - if (util.isString(order)) { - // order by provided field name - var name = order; // field name - items.sort(function (a, b) { - var av = a[name]; - var bv = b[name]; - return (av > bv) ? 1 : ((av < bv) ? -1 : 0); - }); - } - else if (typeof order === 'function') { - // order by sort function - items.sort(order); - } - // TODO: extend order by an Object {field:String, direction:String} - // where direction can be 'asc' or 'desc' - else { - throw new TypeError('Order must be a function or a string'); + return formatFunctions[format](m); } -}; -/** - * Remove an object by pointer or by id - * @param {String | Number | Object | Array} id Object or id, or an array with - * objects or ids to be removed - * @param {String} [senderId] Optional sender id - * @return {Array} removedIds - */ -DataSet.prototype.remove = function (id, senderId) { - var removedIds = [], - i, len, removedId; + function expandFormat(format, lang) { + var i = 5; - if (id instanceof Array) { - for (i = 0, len = id.length; i < len; i++) { - removedId = this._remove(id[i]); - if (removedId != null) { - removedIds.push(removedId); - } + function replaceLongDateFormatTokens(input) { + return lang.longDateFormat(input) || input; + } + + while (i-- && (localFormattingTokens.lastIndex = 0, + localFormattingTokens.test(format))) { + format = format.replace(localFormattingTokens, replaceLongDateFormatTokens); } + + return format; } - else { - removedId = this._remove(id); - if (removedId != null) { - removedIds.push(removedId); + + + /************************************ + Parsing + ************************************/ + + + // get the regex to find the next token + function getParseRegexForToken(token, config) { + switch (token) { + case 'DDDD': + return parseTokenThreeDigits; + case 'YYYY': + return parseTokenFourDigits; + case 'YYYYY': + return parseTokenSixDigits; + case 'S': + case 'SS': + case 'SSS': + case 'DDD': + return parseTokenOneToThreeDigits; + case 'MMM': + case 'MMMM': + case 'dd': + case 'ddd': + case 'dddd': + return parseTokenWord; + case 'a': + case 'A': + return getLangDefinition(config._l)._meridiemParse; + case 'X': + return parseTokenTimestampMs; + case 'Z': + case 'ZZ': + return parseTokenTimezone; + case 'T': + return parseTokenT; + case 'MM': + case 'DD': + case 'YY': + case 'HH': + case 'hh': + case 'mm': + case 'ss': + case 'M': + case 'D': + case 'd': + case 'H': + case 'h': + case 'm': + case 's': + return parseTokenOneOrTwoDigits; + default : + return new RegExp(token.replace('\\', '')); } } - if (removedIds.length) { - this._trigger('remove', {items: removedIds}, senderId); + function timezoneMinutesFromString(string) { + var tzchunk = (parseTokenTimezone.exec(string) || [])[0], + parts = (tzchunk + '').match(parseTimezoneChunker) || ['-', 0, 0], + minutes = +(parts[1] * 60) + ~~parts[2]; + + return parts[0] === '+' ? -minutes : minutes; } - return removedIds; -}; + // function to convert string input to date + function addTimeToArrayFromToken(token, input, config) { + var a, datePartArray = config._a; -/** - * Remove an item by its id - * @param {Number | String | Object} id id or item - * @returns {Number | String | null} id - * @private - */ -DataSet.prototype._remove = function (id) { - if (util.isNumber(id) || util.isString(id)) { - if (this.data[id]) { - delete this.data[id]; - delete this.internalIds[id]; - return id; + switch (token) { + // MONTH + case 'M' : // fall through to MM + case 'MM' : + if (input != null) { + datePartArray[1] = ~~input - 1; + } + break; + case 'MMM' : // fall through to MMMM + case 'MMMM' : + a = getLangDefinition(config._l).monthsParse(input); + // if we didn't find a month name, mark the date as invalid. + if (a != null) { + datePartArray[1] = a; + } else { + config._isValid = false; + } + break; + // DAY OF MONTH + case 'D' : // fall through to DD + case 'DD' : + if (input != null) { + datePartArray[2] = ~~input; + } + break; + // DAY OF YEAR + case 'DDD' : // fall through to DDDD + case 'DDDD' : + if (input != null) { + datePartArray[1] = 0; + datePartArray[2] = ~~input; + } + break; + // YEAR + case 'YY' : + datePartArray[0] = ~~input + (~~input > 68 ? 1900 : 2000); + break; + case 'YYYY' : + case 'YYYYY' : + datePartArray[0] = ~~input; + break; + // AM / PM + case 'a' : // fall through to A + case 'A' : + config._isPm = getLangDefinition(config._l).isPM(input); + break; + // 24 HOUR + case 'H' : // fall through to hh + case 'HH' : // fall through to hh + case 'h' : // fall through to hh + case 'hh' : + datePartArray[3] = ~~input; + break; + // MINUTE + case 'm' : // fall through to mm + case 'mm' : + datePartArray[4] = ~~input; + break; + // SECOND + case 's' : // fall through to ss + case 'ss' : + datePartArray[5] = ~~input; + break; + // MILLISECOND + case 'S' : + case 'SS' : + case 'SSS' : + datePartArray[6] = ~~ (('0.' + input) * 1000); + break; + // UNIX TIMESTAMP WITH MS + case 'X': + config._d = new Date(parseFloat(input) * 1000); + break; + // TIMEZONE + case 'Z' : // fall through to ZZ + case 'ZZ' : + config._useUTC = true; + config._tzm = timezoneMinutesFromString(input); + break; } - } - else if (id instanceof Object) { - var itemId = id[this.fieldId]; - if (itemId && this.data[itemId]) { - delete this.data[itemId]; - delete this.internalIds[itemId]; - return itemId; + + // if the input is null, the date is not valid + if (input == null) { + config._isValid = false; } } - return null; -}; -/** - * Clear the data - * @param {String} [senderId] Optional sender id - * @return {Array} removedIds The ids of all removed items - */ -DataSet.prototype.clear = function (senderId) { - var ids = Object.keys(this.data); + // convert an array to a date. + // the array should mirror the parameters below + // note: all values past the year are optional and will default to the lowest possible value. + // [year, month, day , hour, minute, second, millisecond] + function dateFromArray(config) { + var i, date, input = [], currentDate; + + if (config._d) { + return; + } - this.data = {}; - this.internalIds = {}; + // Default to current date. + // * if no year, month, day of month are given, default to today + // * if day of month is given, default month and year + // * if month is given, default only year + // * if year is given, don't default anything + currentDate = currentDateArray(config); + for (i = 0; i < 3 && config._a[i] == null; ++i) { + config._a[i] = input[i] = currentDate[i]; + } - this._trigger('remove', {items: ids}, senderId); + // Zero out whatever was not defaulted, including time + for (; i < 7; i++) { + config._a[i] = input[i] = (config._a[i] == null) ? (i === 2 ? 1 : 0) : config._a[i]; + } - return ids; -}; + // add the offsets to the time to be parsed so that we can have a clean array for checking isValid + input[3] += ~~((config._tzm || 0) / 60); + input[4] += ~~((config._tzm || 0) % 60); -/** - * Find the item with maximum value of a specified field - * @param {String} field - * @return {Object | null} item Item containing max value, or null if no items - */ -DataSet.prototype.max = function (field) { - var data = this.data, - max = null, - maxField = null; + date = new Date(0); - for (var id in data) { - if (data.hasOwnProperty(id)) { - var item = data[id]; - var itemField = item[field]; - if (itemField != null && (!max || itemField > maxField)) { - max = item; - maxField = itemField; - } + if (config._useUTC) { + date.setUTCFullYear(input[0], input[1], input[2]); + date.setUTCHours(input[3], input[4], input[5], input[6]); + } else { + date.setFullYear(input[0], input[1], input[2]); + date.setHours(input[3], input[4], input[5], input[6]); } + + config._d = date; } - return max; -}; + function dateFromObject(config) { + var o = config._i; -/** - * Find the item with minimum value of a specified field - * @param {String} field - * @return {Object | null} item Item containing max value, or null if no items - */ -DataSet.prototype.min = function (field) { - var data = this.data, - min = null, - minField = null; + if (config._d) { + return; + } - for (var id in data) { - if (data.hasOwnProperty(id)) { - var item = data[id]; - var itemField = item[field]; - if (itemField != null && (!min || itemField < minField)) { - min = item; - minField = itemField; - } + config._a = [ + o.years || o.year || o.y, + o.months || o.month || o.M, + o.days || o.day || o.d, + o.hours || o.hour || o.h, + o.minutes || o.minute || o.m, + o.seconds || o.second || o.s, + o.milliseconds || o.millisecond || o.ms + ]; + + dateFromArray(config); + } + + function currentDateArray(config) { + var now = new Date(); + if (config._useUTC) { + return [ + now.getUTCFullYear(), + now.getUTCMonth(), + now.getUTCDate() + ]; + } else { + return [now.getFullYear(), now.getMonth(), now.getDate()]; } } - return min; -}; + // date from string and format string + function makeDateFromStringAndFormat(config) { + // This array is used to make a Date, either with `new Date` or `Date.UTC` + var lang = getLangDefinition(config._l), + string = '' + config._i, + i, parsedInput, tokens; -/** - * Find all distinct values of a specified field - * @param {String} field - * @return {Array} values Array containing all distinct values. If the data - * items do not contain the specified field, an array - * containing a single value undefined is returned. - * The returned array is unordered. - */ -DataSet.prototype.distinct = function (field) { - var data = this.data, - values = [], - fieldType = this.options.convert[field], - count = 0; + tokens = expandFormat(config._f, lang).match(formattingTokens); - for (var prop in data) { - if (data.hasOwnProperty(prop)) { - var item = data[prop]; - var value = util.convert(item[field], fieldType); - var exists = false; - for (var i = 0; i < count; i++) { - if (values[i] == value) { - exists = true; - break; - } + config._a = []; + + for (i = 0; i < tokens.length; i++) { + parsedInput = (getParseRegexForToken(tokens[i], config).exec(string) || [])[0]; + if (parsedInput) { + string = string.slice(string.indexOf(parsedInput) + parsedInput.length); } - if (!exists) { - values[count] = value; - count++; + // don't parse if its not a known token + if (formatTokenFunctions[tokens[i]]) { + addTimeToArrayFromToken(tokens[i], parsedInput, config); } } - } - - return values; -}; - -/** - * Add a single item. Will fail when an item with the same id already exists. - * @param {Object} item - * @return {String} id - * @private - */ -DataSet.prototype._addItem = function (item) { - var id = item[this.fieldId]; - if (id != undefined) { - // check whether this id is already taken - if (this.data[id]) { - // item already exists - throw new Error('Cannot add item: item with id ' + id + ' already exists'); + // add remaining unparsed input to the string + if (string) { + config._il = string; } - } - else { - // generate an id - id = util.randomUUID(); - item[this.fieldId] = id; - this.internalIds[id] = item; - } - var d = {}; - for (var field in item) { - if (item.hasOwnProperty(field)) { - var fieldType = this.convert[field]; // type may be undefined - d[field] = util.convert(item[field], fieldType); + // handle am pm + if (config._isPm && config._a[3] < 12) { + config._a[3] += 12; + } + // if is 12 am, change hours to 0 + if (config._isPm === false && config._a[3] === 12) { + config._a[3] = 0; } + // return + dateFromArray(config); } - this.data[id] = d; - return id; -}; + // date from string and array of format strings + function makeDateFromStringAndArray(config) { + var tempConfig, + tempMoment, + bestMoment, -/** - * Get an item. Fields can be converted to a specific type - * @param {String} id - * @param {Object.} [convert] field types to convert - * @return {Object | null} item - * @private - */ -DataSet.prototype._getItem = function (id, convert) { - var field, value; + scoreToBeat = 99, + i, + currentScore; - // get the item from the dataset - var raw = this.data[id]; - if (!raw) { - return null; - } + for (i = 0; i < config._f.length; i++) { + tempConfig = extend({}, config); + tempConfig._f = config._f[i]; + makeDateFromStringAndFormat(tempConfig); + tempMoment = new Moment(tempConfig); - // convert the items field types - var converted = {}, - fieldId = this.fieldId, - internalIds = this.internalIds; - if (convert) { - for (field in raw) { - if (raw.hasOwnProperty(field)) { - value = raw[field]; - // output all fields, except internal ids - if ((field != fieldId) || !(value in internalIds)) { - converted[field] = util.convert(value, convert[field]); - } + currentScore = compareArrays(tempConfig._a, tempMoment.toArray()); + + // if there is any input that was not parsed + // add a penalty for that format + if (tempMoment._il) { + currentScore += tempMoment._il.length; + } + + if (currentScore < scoreToBeat) { + scoreToBeat = currentScore; + bestMoment = tempMoment; } } + + extend(config, bestMoment); } - else { - // no field types specified, no converting needed - for (field in raw) { - if (raw.hasOwnProperty(field)) { - value = raw[field]; - // output all fields, except internal ids - if ((field != fieldId) || !(value in internalIds)) { - converted[field] = value; + + // date from iso format + function makeDateFromString(config) { + var i, + string = config._i, + match = isoRegex.exec(string); + + if (match) { + // match[2] should be "T" or undefined + config._f = 'YYYY-MM-DD' + (match[2] || " "); + for (i = 0; i < 4; i++) { + if (isoTimes[i][1].exec(string)) { + config._f += isoTimes[i][0]; + break; } } + if (parseTokenTimezone.exec(string)) { + config._f += " Z"; + } + makeDateFromStringAndFormat(config); + } else { + config._d = new Date(string); } } - return converted; -}; - -/** - * Update a single item: merge with existing item. - * Will fail when the item has no id, or when there does not exist an item - * with the same id. - * @param {Object} item - * @return {String} id - * @private - */ -DataSet.prototype._updateItem = function (item) { - var id = item[this.fieldId]; - if (id == undefined) { - throw new Error('Cannot update item: item has no id (item: ' + JSON.stringify(item) + ')'); - } - var d = this.data[id]; - if (!d) { - // item doesn't exist - throw new Error('Cannot update item: no item with id ' + id + ' found'); - } + function makeDateFromInput(config) { + var input = config._i, + matched = aspNetJsonRegex.exec(input); - // merge with current item - for (var field in item) { - if (item.hasOwnProperty(field)) { - var fieldType = this.convert[field]; // type may be undefined - d[field] = util.convert(item[field], fieldType); + if (input === undefined) { + config._d = new Date(); + } else if (matched) { + config._d = new Date(+matched[1]); + } else if (typeof input === 'string') { + makeDateFromString(config); + } else if (isArray(input)) { + config._a = input.slice(0); + dateFromArray(config); + } else if (input instanceof Date) { + config._d = new Date(+input); + } else if (typeof(input) === 'object') { + dateFromObject(config); + } else { + config._d = new Date(input); } } - return id; -}; -/** - * Get an array with the column names of a Google DataTable - * @param {DataTable} dataTable - * @return {String[]} columnNames - * @private - */ -DataSet.prototype._getColumnNames = function (dataTable) { - var columns = []; - for (var col = 0, cols = dataTable.getNumberOfColumns(); col < cols; col++) { - columns[col] = dataTable.getColumnId(col) || dataTable.getColumnLabel(col); - } - return columns; -}; + /************************************ + Relative Time + ************************************/ -/** - * Append an item as a row to the dataTable - * @param dataTable - * @param columns - * @param item - * @private - */ -DataSet.prototype._appendRow = function (dataTable, columns, item) { - var row = dataTable.addRow(); - for (var col = 0, cols = columns.length; col < cols; col++) { - var field = columns[col]; - dataTable.setValue(row, col, item[field]); + // helper function for moment.fn.from, moment.fn.fromNow, and moment.duration.fn.humanize + function substituteTimeAgo(string, number, withoutSuffix, isFuture, lang) { + return lang.relativeTime(number || 1, !!withoutSuffix, string, isFuture); } -}; -/** - * DataView - * - * a dataview offers a filtered view on a dataset or an other dataview. - * - * @param {DataSet | DataView} data - * @param {Object} [options] Available options: see method get - * - * @constructor DataView - */ -function DataView (data, options) { - this.id = util.randomUUID(); + function relativeTime(milliseconds, withoutSuffix, lang) { + var seconds = round(Math.abs(milliseconds) / 1000), + minutes = round(seconds / 60), + hours = round(minutes / 60), + days = round(hours / 24), + years = round(days / 365), + args = seconds < 45 && ['s', seconds] || + minutes === 1 && ['m'] || + minutes < 45 && ['mm', minutes] || + hours === 1 && ['h'] || + hours < 22 && ['hh', hours] || + days === 1 && ['d'] || + days <= 25 && ['dd', days] || + days <= 45 && ['M'] || + days < 345 && ['MM', round(days / 30)] || + years === 1 && ['y'] || ['yy', years]; + args[2] = withoutSuffix; + args[3] = milliseconds > 0; + args[4] = lang; + return substituteTimeAgo.apply({}, args); + } - this.data = null; - this.ids = {}; // ids of the items currently in memory (just contains a boolean true) - this.options = options || {}; - this.fieldId = 'id'; // name of the field containing id - this.subscribers = {}; // event subscribers - var me = this; - this.listener = function () { - me._onEvent.apply(me, arguments); - }; + /************************************ + Week of Year + ************************************/ - this.setData(data); -} -/** - * Set a data source for the view - * @param {DataSet | DataView} data - */ -DataView.prototype.setData = function (data) { - var ids, dataItems, i, len; + // firstDayOfWeek 0 = sun, 6 = sat + // the day of the week that starts the week + // (usually sunday or monday) + // firstDayOfWeekOfYear 0 = sun, 6 = sat + // the first week is the week that contains the first + // of this day of the week + // (eg. ISO weeks use thursday (4)) + function weekOfYear(mom, firstDayOfWeek, firstDayOfWeekOfYear) { + var end = firstDayOfWeekOfYear - firstDayOfWeek, + daysToDayOfWeek = firstDayOfWeekOfYear - mom.day(), + adjustedMoment; - if (this.data) { - // unsubscribe from current dataset - if (this.data.unsubscribe) { - this.data.unsubscribe('*', this.listener); + + if (daysToDayOfWeek > end) { + daysToDayOfWeek -= 7; } - // trigger a remove of all items in memory - ids = []; - for (var id in this.ids) { - if (this.ids.hasOwnProperty(id)) { - ids.push(id); - } + if (daysToDayOfWeek < end - 7) { + daysToDayOfWeek += 7; } - this.ids = {}; - this._trigger('remove', {items: ids}); + + adjustedMoment = moment(mom).add('d', daysToDayOfWeek); + return { + week: Math.ceil(adjustedMoment.dayOfYear() / 7), + year: adjustedMoment.year() + }; } - this.data = data; - if (this.data) { - // update fieldId - this.fieldId = this.options.fieldId || - (this.data && this.data.options && this.data.options.fieldId) || - 'id'; + /************************************ + Top Level Functions + ************************************/ - // trigger an add of all added items - ids = this.data.getIds({filter: this.options && this.options.filter}); - for (i = 0, len = ids.length; i < len; i++) { - id = ids[i]; - this.ids[id] = true; + function makeMoment(config) { + var input = config._i, + format = config._f; + + if (input === null || input === '') { + return null; } - this._trigger('add', {items: ids}); - // subscribe to new dataset - if (this.data.subscribe) { - this.data.subscribe('*', this.listener); + if (typeof input === 'string') { + config._i = input = getLangDefinition().preparse(input); } - } -}; -/** - * Get data from the data view - * - * Usage: - * - * get() - * get(options: Object) - * get(options: Object, data: Array | DataTable) - * - * get(id: Number) - * get(id: Number, options: Object) - * get(id: Number, options: Object, data: Array | DataTable) - * - * get(ids: Number[]) - * get(ids: Number[], options: Object) - * get(ids: Number[], options: Object, data: Array | DataTable) - * - * Where: - * - * {Number | String} id The id of an item - * {Number[] | String{}} ids An array with ids of items - * {Object} options An Object with options. Available options: - * {String} [type] Type of data to be returned. Can - * be 'DataTable' or 'Array' (default) - * {Object.} [convert] - * {String[]} [fields] field names to be returned - * {function} [filter] filter items - * {String | function} [order] Order the items by - * a field name or custom sort function. - * {Array | DataTable} [data] If provided, items will be appended to this - * array or table. Required in case of Google - * DataTable. - * @param args - */ -DataView.prototype.get = function (args) { - var me = this; + if (moment.isMoment(input)) { + config = extend({}, input); + config._d = new Date(+input._d); + } else if (format) { + if (isArray(format)) { + makeDateFromStringAndArray(config); + } else { + makeDateFromStringAndFormat(config); + } + } else { + makeDateFromInput(config); + } - // parse the arguments - var ids, options, data; - var firstType = util.getType(arguments[0]); - if (firstType == 'String' || firstType == 'Number' || firstType == 'Array') { - // get(id(s) [, options] [, data]) - ids = arguments[0]; // can be a single id or an array with ids - options = arguments[1]; - data = arguments[2]; - } - else { - // get([, options] [, data]) - options = arguments[0]; - data = arguments[1]; + return new Moment(config); } - // extend the options with the default options and provided options - var viewOptions = util.extend({}, this.options, options); + moment = function (input, format, lang) { + return makeMoment({ + _i : input, + _f : format, + _l : lang, + _isUTC : false + }); + }; + + // creating with utc + moment.utc = function (input, format, lang) { + return makeMoment({ + _useUTC : true, + _isUTC : true, + _l : lang, + _i : input, + _f : format + }).utc(); + }; + + // creating with unix timestamp (in seconds) + moment.unix = function (input) { + return moment(input * 1000); + }; + + // duration + moment.duration = function (input, key) { + var isDuration = moment.isDuration(input), + isNumber = (typeof input === 'number'), + duration = (isDuration ? input._input : (isNumber ? {} : input)), + matched = aspNetTimeSpanJsonRegex.exec(input), + sign, + ret; + + if (isNumber) { + if (key) { + duration[key] = input; + } else { + duration.milliseconds = input; + } + } else if (matched) { + sign = (matched[1] === "-") ? -1 : 1; + duration = { + y: 0, + d: ~~matched[2] * sign, + h: ~~matched[3] * sign, + m: ~~matched[4] * sign, + s: ~~matched[5] * sign, + ms: ~~matched[6] * sign + }; + } + + ret = new Duration(duration); + + if (isDuration && input.hasOwnProperty('_lang')) { + ret._lang = input._lang; + } + + return ret; + }; + + // version number + moment.version = VERSION; - // create a combined filter method when needed - if (this.options.filter && options && options.filter) { - viewOptions.filter = function (item) { - return me.options.filter(item) && options.filter(item); + // default format + moment.defaultFormat = isoFormat; + + // This function will be called whenever a moment is mutated. + // It is intended to keep the offset in sync with the timezone. + moment.updateOffset = function () {}; + + // This function will load languages and then set the global language. If + // no arguments are passed in, it will simply return the current global + // language key. + moment.lang = function (key, values) { + if (!key) { + return moment.fn._lang._abbr; } - } + key = key.toLowerCase(); + key = key.replace('_', '-'); + if (values) { + loadLang(key, values); + } else if (values === null) { + unloadLang(key); + key = 'en'; + } else if (!languages[key]) { + getLangDefinition(key); + } + moment.duration.fn._lang = moment.fn._lang = getLangDefinition(key); + }; - // build up the call to the linked data set - var getArguments = []; - if (ids != undefined) { - getArguments.push(ids); - } - getArguments.push(viewOptions); - getArguments.push(data); + // returns language data + moment.langData = function (key) { + if (key && key._lang && key._lang._abbr) { + key = key._lang._abbr; + } + return getLangDefinition(key); + }; - return this.data && this.data.get.apply(this.data, getArguments); -}; + // compare moment object + moment.isMoment = function (obj) { + return obj instanceof Moment; + }; -/** - * Get ids of all items or from a filtered set of items. - * @param {Object} [options] An Object with options. Available options: - * {function} [filter] filter items - * {String | function} [order] Order the items by - * a field name or custom sort function. - * @return {Array} ids - */ -DataView.prototype.getIds = function (options) { - var ids; + // for typechecking Duration objects + moment.isDuration = function (obj) { + return obj instanceof Duration; + }; - if (this.data) { - var defaultFilter = this.options.filter; - var filter; - if (options && options.filter) { - if (defaultFilter) { - filter = function (item) { - return defaultFilter(item) && options.filter(item); + /************************************ + Moment Prototype + ************************************/ + + + extend(moment.fn = Moment.prototype, { + + clone : function () { + return moment(this); + }, + + valueOf : function () { + return +this._d + ((this._offset || 0) * 60000); + }, + + unix : function () { + return Math.floor(+this / 1000); + }, + + toString : function () { + return this.format("ddd MMM DD YYYY HH:mm:ss [GMT]ZZ"); + }, + + toDate : function () { + return this._offset ? new Date(+this) : this._d; + }, + + toISOString : function () { + return formatMoment(moment(this).utc(), 'YYYY-MM-DD[T]HH:mm:ss.SSS[Z]'); + }, + + toArray : function () { + var m = this; + return [ + m.year(), + m.month(), + m.date(), + m.hours(), + m.minutes(), + m.seconds(), + m.milliseconds() + ]; + }, + + isValid : function () { + if (this._isValid == null) { + if (this._a) { + this._isValid = !compareArrays(this._a, (this._isUTC ? moment.utc(this._a) : moment(this._a)).toArray()); + } else { + this._isValid = !isNaN(this._d.getTime()); } } - else { - filter = options.filter; + return !!this._isValid; + }, + + invalidAt: function () { + var i, arr1 = this._a, arr2 = (this._isUTC ? moment.utc(this._a) : moment(this._a)).toArray(); + for (i = 6; i >= 0 && arr1[i] === arr2[i]; --i) { + // empty loop body } - } - else { - filter = defaultFilter; - } + return i; + }, - ids = this.data.getIds({ - filter: filter, - order: options && options.order - }); - } - else { - ids = []; - } + utc : function () { + return this.zone(0); + }, - return ids; -}; + local : function () { + this.zone(0); + this._isUTC = false; + return this; + }, -/** - * Event listener. Will propagate all events from the connected data set to - * the subscribers of the DataView, but will filter the items and only trigger - * when there are changes in the filtered data set. - * @param {String} event - * @param {Object | null} params - * @param {String} senderId - * @private - */ -DataView.prototype._onEvent = function (event, params, senderId) { - var i, len, id, item, - ids = params && params.items, - data = this.data, - added = [], - updated = [], - removed = []; + format : function (inputString) { + var output = formatMoment(this, inputString || moment.defaultFormat); + return this.lang().postformat(output); + }, - if (ids && data) { - switch (event) { - case 'add': - // filter the ids of the added items - for (i = 0, len = ids.length; i < len; i++) { - id = ids[i]; - item = this.get(id); - if (item) { - this.ids[id] = true; - added.push(id); - } - } + add : function (input, val) { + var dur; + // switch args to support add('s', 1) and add(1, 's') + if (typeof input === 'string') { + dur = moment.duration(+val, input); + } else { + dur = moment.duration(input, val); + } + addOrSubtractDurationFromMoment(this, dur, 1); + return this; + }, - break; + subtract : function (input, val) { + var dur; + // switch args to support subtract('s', 1) and subtract(1, 's') + if (typeof input === 'string') { + dur = moment.duration(+val, input); + } else { + dur = moment.duration(input, val); + } + addOrSubtractDurationFromMoment(this, dur, -1); + return this; + }, - case 'update': - // determine the event from the views viewpoint: an updated - // item can be added, updated, or removed from this view. - for (i = 0, len = ids.length; i < len; i++) { - id = ids[i]; - item = this.get(id); + diff : function (input, units, asFloat) { + var that = this._isUTC ? moment(input).zone(this._offset || 0) : moment(input).local(), + zoneDiff = (this.zone() - that.zone()) * 6e4, + diff, output; - if (item) { - if (this.ids[id]) { - updated.push(id); - } - else { - this.ids[id] = true; - added.push(id); - } - } - else { - if (this.ids[id]) { - delete this.ids[id]; - removed.push(id); - } - else { - // nothing interesting for me :-( - } - } + units = normalizeUnits(units); + + if (units === 'year' || units === 'month') { + // average number of days in the months in the given dates + diff = (this.daysInMonth() + that.daysInMonth()) * 432e5; // 24 * 60 * 60 * 1000 / 2 + // difference in months + output = ((this.year() - that.year()) * 12) + (this.month() - that.month()); + // adjust by taking difference in days, average number of days + // and dst in the given months. + output += ((this - moment(this).startOf('month')) - + (that - moment(that).startOf('month'))) / diff; + // same as above but with zones, to negate all dst + output -= ((this.zone() - moment(this).startOf('month').zone()) - + (that.zone() - moment(that).startOf('month').zone())) * 6e4 / diff; + if (units === 'year') { + output = output / 12; } + } else { + diff = (this - that); + output = units === 'second' ? diff / 1e3 : // 1000 + units === 'minute' ? diff / 6e4 : // 1000 * 60 + units === 'hour' ? diff / 36e5 : // 1000 * 60 * 60 + units === 'day' ? (diff - zoneDiff) / 864e5 : // 1000 * 60 * 60 * 24, negate dst + units === 'week' ? (diff - zoneDiff) / 6048e5 : // 1000 * 60 * 60 * 24 * 7, negate dst + diff; + } + return asFloat ? output : absRound(output); + }, + + from : function (time, withoutSuffix) { + return moment.duration(this.diff(time)).lang(this.lang()._abbr).humanize(!withoutSuffix); + }, + + fromNow : function (withoutSuffix) { + return this.from(moment(), withoutSuffix); + }, + + calendar : function () { + var diff = this.diff(moment().zone(this.zone()).startOf('day'), 'days', true), + format = diff < -6 ? 'sameElse' : + diff < -1 ? 'lastWeek' : + diff < 0 ? 'lastDay' : + diff < 1 ? 'sameDay' : + diff < 2 ? 'nextDay' : + diff < 7 ? 'nextWeek' : 'sameElse'; + return this.format(this.lang().calendar(format, this)); + }, + + isLeapYear : function () { + var year = this.year(); + return (year % 4 === 0 && year % 100 !== 0) || year % 400 === 0; + }, - break; + isDST : function () { + return (this.zone() < this.clone().month(0).zone() || + this.zone() < this.clone().month(5).zone()); + }, - case 'remove': - // filter the ids of the removed items - for (i = 0, len = ids.length; i < len; i++) { - id = ids[i]; - if (this.ids[id]) { - delete this.ids[id]; - removed.push(id); + day : function (input) { + var day = this._isUTC ? this._d.getUTCDay() : this._d.getDay(); + if (input != null) { + if (typeof input === 'string') { + input = this.lang().weekdaysParse(input); + if (typeof input !== 'number') { + return this; } } + return this.add({ d : input - day }); + } else { + return day; + } + }, - break; - } - - if (added.length) { - this._trigger('add', {items: added}, senderId); - } - if (updated.length) { - this._trigger('update', {items: updated}, senderId); - } - if (removed.length) { - this._trigger('remove', {items: removed}, senderId); - } - } -}; - -// copy subscription functionality from DataSet -DataView.prototype.subscribe = DataSet.prototype.subscribe; -DataView.prototype.unsubscribe = DataSet.prototype.unsubscribe; -DataView.prototype._trigger = DataSet.prototype._trigger; - -/** - * @constructor TimeStep - * The class TimeStep is an iterator for dates. You provide a start date and an - * end date. The class itself determines the best scale (step size) based on the - * provided start Date, end Date, and minimumStep. - * - * If minimumStep is provided, the step size is chosen as close as possible - * to the minimumStep but larger than minimumStep. If minimumStep is not - * provided, the scale is set to 1 DAY. - * The minimumStep should correspond with the onscreen size of about 6 characters - * - * Alternatively, you can set a scale by hand. - * After creation, you can initialize the class by executing first(). Then you - * can iterate from the start date to the end date via next(). You can check if - * the end date is reached with the function hasNext(). After each step, you can - * retrieve the current date via getCurrent(). - * The TimeStep has scales ranging from milliseconds, seconds, minutes, hours, - * days, to years. - * - * Version: 1.2 - * - * @param {Date} [start] The start date, for example new Date(2010, 9, 21) - * or new Date(2010, 9, 21, 23, 45, 00) - * @param {Date} [end] The end date - * @param {Number} [minimumStep] Optional. Minimum step size in milliseconds - */ -TimeStep = function(start, end, minimumStep) { - // variables - this.current = new Date(); - this._start = new Date(); - this._end = new Date(); + month : function (input) { + var utc = this._isUTC ? 'UTC' : '', + dayOfMonth; - this.autoScale = true; - this.scale = TimeStep.SCALE.DAY; - this.step = 1; + if (input != null) { + if (typeof input === 'string') { + input = this.lang().monthsParse(input); + if (typeof input !== 'number') { + return this; + } + } - // initialize the range - this.setRange(start, end, minimumStep); -}; + dayOfMonth = this.date(); + this.date(1); + this._d['set' + utc + 'Month'](input); + this.date(Math.min(dayOfMonth, this.daysInMonth())); -/// enum scale -TimeStep.SCALE = { - MILLISECOND: 1, - SECOND: 2, - MINUTE: 3, - HOUR: 4, - DAY: 5, - WEEKDAY: 6, - MONTH: 7, - YEAR: 8 -}; + moment.updateOffset(this); + return this; + } else { + return this._d['get' + utc + 'Month'](); + } + }, + startOf: function (units) { + units = normalizeUnits(units); + // the following switch intentionally omits break keywords + // to utilize falling through the cases. + switch (units) { + case 'year': + this.month(0); + /* falls through */ + case 'month': + this.date(1); + /* falls through */ + case 'week': + case 'isoweek': + case 'day': + this.hours(0); + /* falls through */ + case 'hour': + this.minutes(0); + /* falls through */ + case 'minute': + this.seconds(0); + /* falls through */ + case 'second': + this.milliseconds(0); + /* falls through */ + } -/** - * Set a new range - * If minimumStep is provided, the step size is chosen as close as possible - * to the minimumStep but larger than minimumStep. If minimumStep is not - * provided, the scale is set to 1 DAY. - * The minimumStep should correspond with the onscreen size of about 6 characters - * @param {Date} [start] The start date and time. - * @param {Date} [end] The end date and time. - * @param {int} [minimumStep] Optional. Minimum step size in milliseconds - */ -TimeStep.prototype.setRange = function(start, end, minimumStep) { - if (!(start instanceof Date) || !(end instanceof Date)) { - //throw "No legal start or end date in method setRange"; - return; - } + // weeks are a special case + if (units === 'week') { + this.weekday(0); + } else if (units === 'isoweek') { + this.isoWeekday(1); + } - this._start = (start != undefined) ? new Date(start.valueOf()) : new Date(); - this._end = (end != undefined) ? new Date(end.valueOf()) : new Date(); + return this; + }, - if (this.autoScale) { - this.setMinimumStep(minimumStep); - } -}; + endOf: function (units) { + units = normalizeUnits(units); + return this.startOf(units).add((units === 'isoweek' ? 'week' : units), 1).subtract('ms', 1); + }, -/** - * Set the range iterator to the start date. - */ -TimeStep.prototype.first = function() { - this.current = new Date(this._start.valueOf()); - this.roundToMinor(); -}; + isAfter: function (input, units) { + units = typeof units !== 'undefined' ? units : 'millisecond'; + return +this.clone().startOf(units) > +moment(input).startOf(units); + }, -/** - * Round the current date to the first minor date value - * This must be executed once when the current date is set to start Date - */ -TimeStep.prototype.roundToMinor = function() { - // round to floor - // IMPORTANT: we have no breaks in this switch! (this is no bug) - //noinspection FallthroughInSwitchStatementJS - switch (this.scale) { - case TimeStep.SCALE.YEAR: - this.current.setFullYear(this.step * Math.floor(this.current.getFullYear() / this.step)); - this.current.setMonth(0); - case TimeStep.SCALE.MONTH: this.current.setDate(1); - case TimeStep.SCALE.DAY: // intentional fall through - case TimeStep.SCALE.WEEKDAY: this.current.setHours(0); - case TimeStep.SCALE.HOUR: this.current.setMinutes(0); - case TimeStep.SCALE.MINUTE: this.current.setSeconds(0); - case TimeStep.SCALE.SECOND: this.current.setMilliseconds(0); - //case TimeStep.SCALE.MILLISECOND: // nothing to do for milliseconds - } + isBefore: function (input, units) { + units = typeof units !== 'undefined' ? units : 'millisecond'; + return +this.clone().startOf(units) < +moment(input).startOf(units); + }, - if (this.step != 1) { - // round down to the first minor value that is a multiple of the current step size - switch (this.scale) { - case TimeStep.SCALE.MILLISECOND: this.current.setMilliseconds(this.current.getMilliseconds() - this.current.getMilliseconds() % this.step); break; - case TimeStep.SCALE.SECOND: this.current.setSeconds(this.current.getSeconds() - this.current.getSeconds() % this.step); break; - case TimeStep.SCALE.MINUTE: this.current.setMinutes(this.current.getMinutes() - this.current.getMinutes() % this.step); break; - case TimeStep.SCALE.HOUR: this.current.setHours(this.current.getHours() - this.current.getHours() % this.step); break; - case TimeStep.SCALE.WEEKDAY: // intentional fall through - case TimeStep.SCALE.DAY: this.current.setDate((this.current.getDate()-1) - (this.current.getDate()-1) % this.step + 1); break; - case TimeStep.SCALE.MONTH: this.current.setMonth(this.current.getMonth() - this.current.getMonth() % this.step); break; - case TimeStep.SCALE.YEAR: this.current.setFullYear(this.current.getFullYear() - this.current.getFullYear() % this.step); break; - default: break; - } - } -}; + isSame: function (input, units) { + units = typeof units !== 'undefined' ? units : 'millisecond'; + return +this.clone().startOf(units) === +moment(input).startOf(units); + }, -/** - * Check if the there is a next step - * @return {boolean} true if the current date has not passed the end date - */ -TimeStep.prototype.hasNext = function () { - return (this.current.valueOf() <= this._end.valueOf()); -}; + min: function (other) { + other = moment.apply(null, arguments); + return other < this ? this : other; + }, -/** - * Do the next step - */ -TimeStep.prototype.next = function() { - var prev = this.current.valueOf(); + max: function (other) { + other = moment.apply(null, arguments); + return other > this ? this : other; + }, - // Two cases, needed to prevent issues with switching daylight savings - // (end of March and end of October) - if (this.current.getMonth() < 6) { - switch (this.scale) { - case TimeStep.SCALE.MILLISECOND: + zone : function (input) { + var offset = this._offset || 0; + if (input != null) { + if (typeof input === "string") { + input = timezoneMinutesFromString(input); + } + if (Math.abs(input) < 16) { + input = input * 60; + } + this._offset = input; + this._isUTC = true; + if (offset !== input) { + addOrSubtractDurationFromMoment(this, moment.duration(offset - input, 'm'), 1, true); + } + } else { + return this._isUTC ? offset : this._d.getTimezoneOffset(); + } + return this; + }, - this.current = new Date(this.current.valueOf() + this.step); break; - case TimeStep.SCALE.SECOND: this.current = new Date(this.current.valueOf() + this.step * 1000); break; - case TimeStep.SCALE.MINUTE: this.current = new Date(this.current.valueOf() + this.step * 1000 * 60); break; - case TimeStep.SCALE.HOUR: - this.current = new Date(this.current.valueOf() + this.step * 1000 * 60 * 60); - // in case of skipping an hour for daylight savings, adjust the hour again (else you get: 0h 5h 9h ... instead of 0h 4h 8h ...) - var h = this.current.getHours(); - this.current.setHours(h - (h % this.step)); - break; - case TimeStep.SCALE.WEEKDAY: // intentional fall through - case TimeStep.SCALE.DAY: this.current.setDate(this.current.getDate() + this.step); break; - case TimeStep.SCALE.MONTH: this.current.setMonth(this.current.getMonth() + this.step); break; - case TimeStep.SCALE.YEAR: this.current.setFullYear(this.current.getFullYear() + this.step); break; - default: break; - } - } - else { - switch (this.scale) { - case TimeStep.SCALE.MILLISECOND: this.current = new Date(this.current.valueOf() + this.step); break; - case TimeStep.SCALE.SECOND: this.current.setSeconds(this.current.getSeconds() + this.step); break; - case TimeStep.SCALE.MINUTE: this.current.setMinutes(this.current.getMinutes() + this.step); break; - case TimeStep.SCALE.HOUR: this.current.setHours(this.current.getHours() + this.step); break; - case TimeStep.SCALE.WEEKDAY: // intentional fall through - case TimeStep.SCALE.DAY: this.current.setDate(this.current.getDate() + this.step); break; - case TimeStep.SCALE.MONTH: this.current.setMonth(this.current.getMonth() + this.step); break; - case TimeStep.SCALE.YEAR: this.current.setFullYear(this.current.getFullYear() + this.step); break; - default: break; - } - } + zoneAbbr : function () { + return this._isUTC ? "UTC" : ""; + }, - if (this.step != 1) { - // round down to the correct major value - switch (this.scale) { - case TimeStep.SCALE.MILLISECOND: if(this.current.getMilliseconds() < this.step) this.current.setMilliseconds(0); break; - case TimeStep.SCALE.SECOND: if(this.current.getSeconds() < this.step) this.current.setSeconds(0); break; - case TimeStep.SCALE.MINUTE: if(this.current.getMinutes() < this.step) this.current.setMinutes(0); break; - case TimeStep.SCALE.HOUR: if(this.current.getHours() < this.step) this.current.setHours(0); break; - case TimeStep.SCALE.WEEKDAY: // intentional fall through - case TimeStep.SCALE.DAY: if(this.current.getDate() < this.step+1) this.current.setDate(1); break; - case TimeStep.SCALE.MONTH: if(this.current.getMonth() < this.step) this.current.setMonth(0); break; - case TimeStep.SCALE.YEAR: break; // nothing to do for year - default: break; - } - } + zoneName : function () { + return this._isUTC ? "Coordinated Universal Time" : ""; + }, - // safety mechanism: if current time is still unchanged, move to the end - if (this.current.valueOf() == prev) { - this.current = new Date(this._end.valueOf()); - } -}; + hasAlignedHourOffset : function (input) { + if (!input) { + input = 0; + } + else { + input = moment(input).zone(); + } + return (this.zone() - input) % 60 === 0; + }, -/** - * Get the current datetime - * @return {Date} current The current date - */ -TimeStep.prototype.getCurrent = function() { - return this.current; -}; + daysInMonth : function () { + return moment.utc([this.year(), this.month() + 1, 0]).date(); + }, -/** - * Set a custom scale. Autoscaling will be disabled. - * For example setScale(SCALE.MINUTES, 5) will result - * in minor steps of 5 minutes, and major steps of an hour. - * - * @param {TimeStep.SCALE} newScale - * A scale. Choose from SCALE.MILLISECOND, - * SCALE.SECOND, SCALE.MINUTE, SCALE.HOUR, - * SCALE.WEEKDAY, SCALE.DAY, SCALE.MONTH, - * SCALE.YEAR. - * @param {Number} newStep A step size, by default 1. Choose for - * example 1, 2, 5, or 10. - */ -TimeStep.prototype.setScale = function(newScale, newStep) { - this.scale = newScale; + dayOfYear : function (input) { + var dayOfYear = round((moment(this).startOf('day') - moment(this).startOf('year')) / 864e5) + 1; + return input == null ? dayOfYear : this.add("d", (input - dayOfYear)); + }, - if (newStep > 0) { - this.step = newStep; - } + weekYear : function (input) { + var year = weekOfYear(this, this.lang()._week.dow, this.lang()._week.doy).year; + return input == null ? year : this.add("y", (input - year)); + }, - this.autoScale = false; -}; + isoWeekYear : function (input) { + var year = weekOfYear(this, 1, 4).year; + return input == null ? year : this.add("y", (input - year)); + }, -/** - * Enable or disable autoscaling - * @param {boolean} enable If true, autoascaling is set true - */ -TimeStep.prototype.setAutoScale = function (enable) { - this.autoScale = enable; -}; + week : function (input) { + var week = this.lang().week(this); + return input == null ? week : this.add("d", (input - week) * 7); + }, + isoWeek : function (input) { + var week = weekOfYear(this, 1, 4).week; + return input == null ? week : this.add("d", (input - week) * 7); + }, -/** - * Automatically determine the scale that bests fits the provided minimum step - * @param {Number} [minimumStep] The minimum step size in milliseconds - */ -TimeStep.prototype.setMinimumStep = function(minimumStep) { - if (minimumStep == undefined) { - return; - } + weekday : function (input) { + var weekday = (this._d.getDay() + 7 - this.lang()._week.dow) % 7; + return input == null ? weekday : this.add("d", input - weekday); + }, - var stepYear = (1000 * 60 * 60 * 24 * 30 * 12); - var stepMonth = (1000 * 60 * 60 * 24 * 30); - var stepDay = (1000 * 60 * 60 * 24); - var stepHour = (1000 * 60 * 60); - var stepMinute = (1000 * 60); - var stepSecond = (1000); - var stepMillisecond= (1); + isoWeekday : function (input) { + // behaves the same as moment#day except + // as a getter, returns 7 instead of 0 (1-7 range instead of 0-6) + // as a setter, sunday should belong to the previous week. + return input == null ? this.day() || 7 : this.day(this.day() % 7 ? input : input - 7); + }, - // find the smallest step that is larger than the provided minimumStep - if (stepYear*1000 > minimumStep) {this.scale = TimeStep.SCALE.YEAR; this.step = 1000;} - if (stepYear*500 > minimumStep) {this.scale = TimeStep.SCALE.YEAR; this.step = 500;} - if (stepYear*100 > minimumStep) {this.scale = TimeStep.SCALE.YEAR; this.step = 100;} - if (stepYear*50 > minimumStep) {this.scale = TimeStep.SCALE.YEAR; this.step = 50;} - if (stepYear*10 > minimumStep) {this.scale = TimeStep.SCALE.YEAR; this.step = 10;} - if (stepYear*5 > minimumStep) {this.scale = TimeStep.SCALE.YEAR; this.step = 5;} - if (stepYear > minimumStep) {this.scale = TimeStep.SCALE.YEAR; this.step = 1;} - if (stepMonth*3 > minimumStep) {this.scale = TimeStep.SCALE.MONTH; this.step = 3;} - if (stepMonth > minimumStep) {this.scale = TimeStep.SCALE.MONTH; this.step = 1;} - if (stepDay*5 > minimumStep) {this.scale = TimeStep.SCALE.DAY; this.step = 5;} - if (stepDay*2 > minimumStep) {this.scale = TimeStep.SCALE.DAY; this.step = 2;} - if (stepDay > minimumStep) {this.scale = TimeStep.SCALE.DAY; this.step = 1;} - if (stepDay/2 > minimumStep) {this.scale = TimeStep.SCALE.WEEKDAY; this.step = 1;} - if (stepHour*4 > minimumStep) {this.scale = TimeStep.SCALE.HOUR; this.step = 4;} - if (stepHour > minimumStep) {this.scale = TimeStep.SCALE.HOUR; this.step = 1;} - if (stepMinute*15 > minimumStep) {this.scale = TimeStep.SCALE.MINUTE; this.step = 15;} - if (stepMinute*10 > minimumStep) {this.scale = TimeStep.SCALE.MINUTE; this.step = 10;} - if (stepMinute*5 > minimumStep) {this.scale = TimeStep.SCALE.MINUTE; this.step = 5;} - if (stepMinute > minimumStep) {this.scale = TimeStep.SCALE.MINUTE; this.step = 1;} - if (stepSecond*15 > minimumStep) {this.scale = TimeStep.SCALE.SECOND; this.step = 15;} - if (stepSecond*10 > minimumStep) {this.scale = TimeStep.SCALE.SECOND; this.step = 10;} - if (stepSecond*5 > minimumStep) {this.scale = TimeStep.SCALE.SECOND; this.step = 5;} - if (stepSecond > minimumStep) {this.scale = TimeStep.SCALE.SECOND; this.step = 1;} - if (stepMillisecond*200 > minimumStep) {this.scale = TimeStep.SCALE.MILLISECOND; this.step = 200;} - if (stepMillisecond*100 > minimumStep) {this.scale = TimeStep.SCALE.MILLISECOND; this.step = 100;} - if (stepMillisecond*50 > minimumStep) {this.scale = TimeStep.SCALE.MILLISECOND; this.step = 50;} - if (stepMillisecond*10 > minimumStep) {this.scale = TimeStep.SCALE.MILLISECOND; this.step = 10;} - if (stepMillisecond*5 > minimumStep) {this.scale = TimeStep.SCALE.MILLISECOND; this.step = 5;} - if (stepMillisecond > minimumStep) {this.scale = TimeStep.SCALE.MILLISECOND; this.step = 1;} -}; + get : function (units) { + units = normalizeUnits(units); + return this[units.toLowerCase()](); + }, -/** - * Snap a date to a rounded value. The snap intervals are dependent on the - * current scale and step. - * @param {Date} date the date to be snapped - */ -TimeStep.prototype.snap = function(date) { - if (this.scale == TimeStep.SCALE.YEAR) { - var year = date.getFullYear() + Math.round(date.getMonth() / 12); - date.setFullYear(Math.round(year / this.step) * this.step); - date.setMonth(0); - date.setDate(0); - date.setHours(0); - date.setMinutes(0); - date.setSeconds(0); - date.setMilliseconds(0); - } - else if (this.scale == TimeStep.SCALE.MONTH) { - if (date.getDate() > 15) { - date.setDate(1); - date.setMonth(date.getMonth() + 1); - // important: first set Date to 1, after that change the month. - } - else { - date.setDate(1); - } + set : function (units, value) { + units = normalizeUnits(units); + this[units.toLowerCase()](value); + }, - date.setHours(0); - date.setMinutes(0); - date.setSeconds(0); - date.setMilliseconds(0); - } - else if (this.scale == TimeStep.SCALE.DAY || - this.scale == TimeStep.SCALE.WEEKDAY) { - //noinspection FallthroughInSwitchStatementJS - switch (this.step) { - case 5: - case 2: - date.setHours(Math.round(date.getHours() / 24) * 24); break; - default: - date.setHours(Math.round(date.getHours() / 12) * 12); break; - } - date.setMinutes(0); - date.setSeconds(0); - date.setMilliseconds(0); - } - else if (this.scale == TimeStep.SCALE.HOUR) { - switch (this.step) { - case 4: - date.setMinutes(Math.round(date.getMinutes() / 60) * 60); break; - default: - date.setMinutes(Math.round(date.getMinutes() / 30) * 30); break; - } - date.setSeconds(0); - date.setMilliseconds(0); - } else if (this.scale == TimeStep.SCALE.MINUTE) { - //noinspection FallthroughInSwitchStatementJS - switch (this.step) { - case 15: - case 10: - date.setMinutes(Math.round(date.getMinutes() / 5) * 5); - date.setSeconds(0); - break; - case 5: - date.setSeconds(Math.round(date.getSeconds() / 60) * 60); break; - default: - date.setSeconds(Math.round(date.getSeconds() / 30) * 30); break; - } - date.setMilliseconds(0); - } - else if (this.scale == TimeStep.SCALE.SECOND) { - //noinspection FallthroughInSwitchStatementJS - switch (this.step) { - case 15: - case 10: - date.setSeconds(Math.round(date.getSeconds() / 5) * 5); - date.setMilliseconds(0); - break; - case 5: - date.setMilliseconds(Math.round(date.getMilliseconds() / 1000) * 1000); break; - default: - date.setMilliseconds(Math.round(date.getMilliseconds() / 500) * 500); break; + // If passed a language key, it will set the language for this + // instance. Otherwise, it will return the language configuration + // variables for this instance. + lang : function (key) { + if (key === undefined) { + return this._lang; + } else { + this._lang = getLangDefinition(key); + return this; + } } - } - else if (this.scale == TimeStep.SCALE.MILLISECOND) { - var step = this.step > 5 ? this.step / 2 : 1; - date.setMilliseconds(Math.round(date.getMilliseconds() / step) * step); - } -}; + }); -/** - * Check if the current value is a major value (for example when the step - * is DAY, a major value is each first day of the MONTH) - * @return {boolean} true if current date is major, else false. - */ -TimeStep.prototype.isMajor = function() { - switch (this.scale) { - case TimeStep.SCALE.MILLISECOND: - return (this.current.getMilliseconds() == 0); - case TimeStep.SCALE.SECOND: - return (this.current.getSeconds() == 0); - case TimeStep.SCALE.MINUTE: - return (this.current.getHours() == 0) && (this.current.getMinutes() == 0); - // Note: this is no bug. Major label is equal for both minute and hour scale - case TimeStep.SCALE.HOUR: - return (this.current.getHours() == 0); - case TimeStep.SCALE.WEEKDAY: // intentional fall through - case TimeStep.SCALE.DAY: - return (this.current.getDate() == 1); - case TimeStep.SCALE.MONTH: - return (this.current.getMonth() == 0); - case TimeStep.SCALE.YEAR: - return false; - default: - return false; + // helper for adding shortcuts + function makeGetterAndSetter(name, key) { + moment.fn[name] = moment.fn[name + 's'] = function (input) { + var utc = this._isUTC ? 'UTC' : ''; + if (input != null) { + this._d['set' + utc + key](input); + moment.updateOffset(this); + return this; + } else { + return this._d['get' + utc + key](); + } + }; } -}; - -/** - * Returns formatted text for the minor axislabel, depending on the current - * date and the scale. For example when scale is MINUTE, the current time is - * formatted as "hh:mm". - * @param {Date} [date] custom date. if not provided, current date is taken - */ -TimeStep.prototype.getLabelMinor = function(date) { - if (date == undefined) { - date = this.current; + // loop through and add shortcuts (Month, Date, Hours, Minutes, Seconds, Milliseconds) + for (i = 0; i < proxyGettersAndSetters.length; i ++) { + makeGetterAndSetter(proxyGettersAndSetters[i].toLowerCase().replace(/s$/, ''), proxyGettersAndSetters[i]); } - switch (this.scale) { - case TimeStep.SCALE.MILLISECOND: return moment(date).format('SSS'); - case TimeStep.SCALE.SECOND: return moment(date).format('s'); - case TimeStep.SCALE.MINUTE: return moment(date).format('HH:mm'); - case TimeStep.SCALE.HOUR: return moment(date).format('HH:mm'); - case TimeStep.SCALE.WEEKDAY: return moment(date).format('ddd D'); - case TimeStep.SCALE.DAY: return moment(date).format('D'); - case TimeStep.SCALE.MONTH: return moment(date).format('MMM'); - case TimeStep.SCALE.YEAR: return moment(date).format('YYYY'); - default: return ''; - } -}; + // add shortcut for year (uses different syntax than the getter/setter 'year' == 'FullYear') + makeGetterAndSetter('year', 'FullYear'); + // add plural methods + moment.fn.days = moment.fn.day; + moment.fn.months = moment.fn.month; + moment.fn.weeks = moment.fn.week; + moment.fn.isoWeeks = moment.fn.isoWeek; -/** - * Returns formatted text for the major axis label, depending on the current - * date and the scale. For example when scale is MINUTE, the major scale is - * hours, and the hour will be formatted as "hh". - * @param {Date} [date] custom date. if not provided, current date is taken - */ -TimeStep.prototype.getLabelMajor = function(date) { - if (date == undefined) { - date = this.current; - } + // add aliased format methods + moment.fn.toJSON = moment.fn.toISOString; - //noinspection FallthroughInSwitchStatementJS - switch (this.scale) { - case TimeStep.SCALE.MILLISECOND:return moment(date).format('HH:mm:ss'); - case TimeStep.SCALE.SECOND: return moment(date).format('D MMMM HH:mm'); - case TimeStep.SCALE.MINUTE: - case TimeStep.SCALE.HOUR: return moment(date).format('ddd D MMMM'); - case TimeStep.SCALE.WEEKDAY: - case TimeStep.SCALE.DAY: return moment(date).format('MMMM YYYY'); - case TimeStep.SCALE.MONTH: return moment(date).format('YYYY'); - case TimeStep.SCALE.YEAR: return ''; - default: return ''; - } -}; + /************************************ + Duration Prototype + ************************************/ -/** - * @constructor Stack - * Stacks items on top of each other. - * @param {ItemSet} parent - * @param {Object} [options] - */ -function Stack (parent, options) { - this.parent = parent; - this.options = options || {}; - this.defaultOptions = { - order: function (a, b) { - //return (b.width - a.width) || (a.left - b.left); // TODO: cleanup - // Order: ranges over non-ranges, ranged ordered by width, and - // lastly ordered by start. - if (a instanceof ItemRange) { - if (b instanceof ItemRange) { - var aInt = (a.data.end - a.data.start); - var bInt = (b.data.end - b.data.start); - return (aInt - bInt) || (a.data.start - b.data.start); - } - else { - return -1; - } - } - else { - if (b instanceof ItemRange) { - return 1; - } - else { - return (a.data.start - b.data.start); - } + extend(moment.duration.fn = Duration.prototype, { + + _bubble : function () { + var milliseconds = this._milliseconds, + days = this._days, + months = this._months, + data = this._data, + seconds, minutes, hours, years; + + // The following code bubbles up values, see the tests for + // examples of what that means. + data.milliseconds = milliseconds % 1000; + + seconds = absRound(milliseconds / 1000); + data.seconds = seconds % 60; + + minutes = absRound(seconds / 60); + data.minutes = minutes % 60; + + hours = absRound(minutes / 60); + data.hours = hours % 24; + + days += absRound(hours / 24); + data.days = days % 30; + + months += absRound(days / 30); + data.months = months % 12; + + years = absRound(months / 12); + data.years = years; + }, + + weeks : function () { + return absRound(this.days() / 7); + }, + + valueOf : function () { + return this._milliseconds + + this._days * 864e5 + + (this._months % 12) * 2592e6 + + ~~(this._months / 12) * 31536e6; + }, + + humanize : function (withSuffix) { + var difference = +this, + output = relativeTime(difference, !withSuffix, this.lang()); + + if (withSuffix) { + output = this.lang().pastFuture(difference, output); } + + return this.lang().postformat(output); }, - margin: { - item: 10 - } - }; - this.ordered = []; // ordered items -} + add : function (input, val) { + // supports only 2.0-style add(1, 's') or add(moment) + var dur = moment.duration(input, val); -/** - * Set options for the stack - * @param {Object} options Available options: - * {ItemSet} parent - * {Number} margin - * {function} order Stacking order - */ -Stack.prototype.setOptions = function setOptions (options) { - util.extend(this.options, options); + this._milliseconds += dur._milliseconds; + this._days += dur._days; + this._months += dur._months; - // TODO: register on data changes at the connected parent itemset, and update the changed part only and immediately -}; + this._bubble(); -/** - * Stack the items such that they don't overlap. The items will have a minimal - * distance equal to options.margin.item. - */ -Stack.prototype.update = function update() { - this._order(); - this._stack(); -}; + return this; + }, -/** - * Order the items. The items are ordered by width first, and by left position - * second. - * If a custom order function has been provided via the options, then this will - * be used. - * @private - */ -Stack.prototype._order = function _order () { - var items = this.parent.items; - if (!items) { - throw new Error('Cannot stack items: parent does not contain items'); - } + subtract : function (input, val) { + var dur = moment.duration(input, val); - // TODO: store the sorted items, to have less work later on - var ordered = []; - var index = 0; - // items is a map (no array) - util.forEach(items, function (item) { - if (item.visible) { - ordered[index] = item; - index++; - } - }); + this._milliseconds -= dur._milliseconds; + this._days -= dur._days; + this._months -= dur._months; - //if a customer stack order function exists, use it. - var order = this.options.order || this.defaultOptions.order; - if (!(typeof order === 'function')) { - throw new Error('Option order must be a function'); - } + this._bubble(); - ordered.sort(order); + return this; + }, - this.ordered = ordered; -}; + get : function (units) { + units = normalizeUnits(units); + return this[units.toLowerCase() + 's'](); + }, -/** - * Adjust vertical positions of the events such that they don't overlap each - * other. - * @private - */ -Stack.prototype._stack = function _stack () { - var i, - iMax, - ordered = this.ordered, - options = this.options, - orientation = options.orientation || this.defaultOptions.orientation, - axisOnTop = (orientation == 'top'), - margin; + as : function (units) { + units = normalizeUnits(units); + return this['as' + units.charAt(0).toUpperCase() + units.slice(1) + 's'](); + }, - if (options.margin && options.margin.item !== undefined) { - margin = options.margin.item; - } - else { - margin = this.defaultOptions.margin.item - } + lang : moment.fn.lang + }); - // calculate new, non-overlapping positions - for (i = 0, iMax = ordered.length; i < iMax; i++) { - var item = ordered[i]; - var collidingItem = null; - do { - // TODO: optimize checking for overlap. when there is a gap without items, - // you only need to check for items from the next item on, not from zero - collidingItem = this.checkOverlap(ordered, i, 0, i - 1, margin); - if (collidingItem != null) { - // There is a collision. Reposition the event above the colliding element - if (axisOnTop) { - item.top = collidingItem.top + collidingItem.height + margin; - } - else { - item.top = collidingItem.top - item.height - margin; - } - } - } while (collidingItem); + function makeDurationGetter(name) { + moment.duration.fn[name] = function () { + return this._data[name]; + }; } -}; - -/** - * Check if the destiny position of given item overlaps with any - * of the other items from index itemStart to itemEnd. - * @param {Array} items Array with items - * @param {int} itemIndex Number of the item to be checked for overlap - * @param {int} itemStart First item to be checked. - * @param {int} itemEnd Last item to be checked. - * @return {Object | null} colliding item, or undefined when no collisions - * @param {Number} margin A minimum required margin. - * If margin is provided, the two items will be - * marked colliding when they overlap or - * when the margin between the two is smaller than - * the requested margin. - */ -Stack.prototype.checkOverlap = function checkOverlap (items, itemIndex, - itemStart, itemEnd, margin) { - var collision = this.collision; - // we loop from end to start, as we suppose that the chance of a - // collision is larger for items at the end, so check these first. - var a = items[itemIndex]; - for (var i = itemEnd; i >= itemStart; i--) { - var b = items[i]; - if (collision(a, b, margin)) { - if (i != itemIndex) { - return b; - } + function makeDurationAsGetter(name, factor) { + moment.duration.fn['as' + name] = function () { + return +this / factor; + }; + } + + for (i in unitMillisecondFactors) { + if (unitMillisecondFactors.hasOwnProperty(i)) { + makeDurationAsGetter(i, unitMillisecondFactors[i]); + makeDurationGetter(i.toLowerCase()); } } - return null; -}; + makeDurationAsGetter('Weeks', 6048e5); + moment.duration.fn.asMonths = function () { + return (+this - this.years() * 31536e6) / 2592e6 + this.years() * 12; + }; -/** - * Test if the two provided items collide - * The items must have parameters left, width, top, and height. - * @param {Component} a The first item - * @param {Component} b The second item - * @param {Number} margin A minimum required margin. - * If margin is provided, the two items will be - * marked colliding when they overlap or - * when the margin between the two is smaller than - * the requested margin. - * @return {boolean} true if a and b collide, else false - */ -Stack.prototype.collision = function collision (a, b, margin) { - return ((a.left - margin) < (b.left + b.width) && - (a.left + a.width + margin) > b.left && - (a.top - margin) < (b.top + b.height) && - (a.top + a.height + margin) > b.top); -}; -/** - * @constructor Range - * A Range controls a numeric range with a start and end value. - * The Range adjusts the range based on mouse events or programmatic changes, - * and triggers events when the range is changing or has been changed. - * @param {Object} [options] See description at Range.setOptions - * @extends Controller - */ -function Range(options) { - this.id = util.randomUUID(); - this.start = 0; // Number - this.end = 0; // Number + /************************************ + Default Lang + ************************************/ - // this.options = options || {}; // TODO: fix range options - this.options = { - min: null, - max: null, - zoomMin: null, - zoomMax: null - }; - this.listeners = []; + // Set default language, other languages will inherit from English. + moment.lang('en', { + ordinal : function (number) { + var b = number % 10, + output = (~~ (number % 100 / 10) === 1) ? 'th' : + (b === 1) ? 'st' : + (b === 2) ? 'nd' : + (b === 3) ? 'rd' : 'th'; + return number + output; + } + }); - this.setOptions(options); -} + /* EMBED_LANGUAGES */ -/** - * Set options for the range controller - * @param {Object} options Available options: - * {Number} start Set start value of the range - * {Number} end Set end value of the range - * {Number} min Minimum value for start - * {Number} max Maximum value for end - * {Number} zoomMin Set a minimum value for - * (end - start). - * {Number} zoomMax Set a maximum value for - * (end - start). - */ -Range.prototype.setOptions = function (options) { - util.extend(this.options, options); + /************************************ + Exposing Moment + ************************************/ - if (options.start != null || options.end != null) { - this.setRange(options.start, options.end); + + // CommonJS module is defined + if (hasModule) { + module.exports = moment; } -}; + /*global ender:false */ + if (typeof ender === 'undefined') { + // here, `this` means `window` in the browser, or `global` on the server + // add `moment` as a global object via a string identifier, + // for Closure Compiler "advanced" mode + this['moment'] = moment; + } + /*global define:false */ + if (typeof define === "function" && define.amd) { + define("moment", [], function () { + return moment; + }); + } +}).call(this); +},{}],3:[function(require,module,exports){ /** - * Add listeners for mouse and touch events to the component - * @param {Component} component - * @param {String} event Available events: 'move', 'zoom' - * @param {String} direction Available directions: 'horizontal', 'vertical' + * vis.js module imports */ -Range.prototype.subscribe = function (component, event, direction) { - var me = this; - var listener; - if (direction != 'horizontal' && direction != 'vertical') { - throw new TypeError('Unknown direction "' + direction + '". ' + - 'Choose "horizontal" or "vertical".'); - } +// Try to load dependencies from the global window object. +// If not available there, load via require. +var moment = (typeof window !== 'undefined') && window['moment'] || require('moment'); +var Hammer = (typeof window !== 'undefined') && window['Hammer'] || require('hammerjs'); - //noinspection FallthroughInSwitchStatementJS - if (event == 'move') { - listener = { - component: component, - event: event, - direction: direction, - callback: function (event) { - me._onMouseDown(event, listener); - }, - params: {} - }; - component.on('mousedown', listener.callback); - me.listeners.push(listener); - } - else if (event == 'zoom') { - listener = { - component: component, - event: event, - direction: direction, - callback: function (event) { - me._onMouseWheel(event, listener); - }, - params: {} - }; +// Internet Explorer 8 and older does not support Array.indexOf, so we define +// it here in that case. +// http://soledadpenades.com/2007/05/17/arrayindexof-in-internet-explorer/ +if(!Array.prototype.indexOf) { + Array.prototype.indexOf = function(obj){ + for(var i = 0; i < this.length; i++){ + if(this[i] == obj){ + return i; + } + } + return -1; + }; - component.on('mousewheel', listener.callback); - me.listeners.push(listener); + try { + console.log("Warning: Ancient browser detected. Please update your browser"); } - else { - throw new TypeError('Unknown event "' + event + '". ' + - 'Choose "move" or "zoom".'); + catch (err) { } -}; +} -/** - * Event handler - * @param {String} event name of the event, for example 'click', 'mousemove' - * @param {function} callback callback handler, invoked with the raw HTML Event - * as parameter. - */ -Range.prototype.on = function (event, callback) { - events.addListener(this, event, callback); -}; +// Internet Explorer 8 and older does not support Array.forEach, so we define +// it here in that case. +// https://developer.mozilla.org/en-US/docs/JavaScript/Reference/Global_Objects/Array/forEach +if (!Array.prototype.forEach) { + Array.prototype.forEach = function(fn, scope) { + for(var i = 0, len = this.length; i < len; ++i) { + fn.call(scope || this, this[i], i, this); + } + } +} -/** - * Trigger an event - * @param {String} event name of the event, available events: 'rangechange', - * 'rangechanged' - * @private - */ -Range.prototype._trigger = function (event) { - events.trigger(this, event, { - start: this.start, - end: this.end - }); -}; +// Internet Explorer 8 and older does not support Array.map, so we define it +// here in that case. +// https://developer.mozilla.org/en-US/docs/JavaScript/Reference/Global_Objects/Array/map +// Production steps of ECMA-262, Edition 5, 15.4.4.19 +// Reference: http://es5.github.com/#x15.4.4.19 +if (!Array.prototype.map) { + Array.prototype.map = function(callback, thisArg) { -/** - * Set a new start and end range - * @param {Number} start - * @param {Number} end - */ -Range.prototype.setRange = function(start, end) { - var changed = this._applyRange(start, end); - if (changed) { - this._trigger('rangechange'); - this._trigger('rangechanged'); - } -}; + var T, A, k; -/** - * Set a new start and end range. This method is the same as setRange, but - * does not trigger a range change and range changed event, and it returns - * true when the range is changed - * @param {Number} start - * @param {Number} end - * @return {Boolean} changed - * @private - */ -Range.prototype._applyRange = function(start, end) { - var newStart = (start != null) ? util.convert(start, 'Number') : this.start; - var newEnd = (end != null) ? util.convert(end, 'Number') : this.end; - var diff; + if (this == null) { + throw new TypeError(" this is null or not defined"); + } + + // 1. Let O be the result of calling ToObject passing the |this| value as the argument. + var O = Object(this); + + // 2. Let lenValue be the result of calling the Get internal method of O with the argument "length". + // 3. Let len be ToUint32(lenValue). + var len = O.length >>> 0; + + // 4. If IsCallable(callback) is false, throw a TypeError exception. + // See: http://es5.github.com/#x9.11 + if (typeof callback !== "function") { + throw new TypeError(callback + " is not a function"); + } + + // 5. If thisArg was supplied, let T be thisArg; else let T be undefined. + if (thisArg) { + T = thisArg; + } + + // 6. Let A be a new array created as if by the expression new Array(len) where Array is + // the standard built-in constructor with that name and len is the value of len. + A = new Array(len); + + // 7. Let k be 0 + k = 0; + + // 8. Repeat, while k < len + while(k < len) { + + var kValue, mappedValue; - // check for valid number - if (isNaN(newStart)) { - throw new Error('Invalid start "' + start + '"'); - } - if (isNaN(newEnd)) { - throw new Error('Invalid end "' + end + '"'); - } + // a. Let Pk be ToString(k). + // This is implicit for LHS operands of the in operator + // b. Let kPresent be the result of calling the HasProperty internal method of O with argument Pk. + // This step can be combined with c + // c. If kPresent is true, then + if (k in O) { - // prevent start < end - if (newEnd < newStart) { - newEnd = newStart; - } + // i. Let kValue be the result of calling the Get internal method of O with argument Pk. + kValue = O[ k ]; - // prevent start < min - if (this.options.min != null) { - var min = this.options.min.valueOf(); - if (newStart < min) { - diff = (min - newStart); - newStart += diff; - newEnd += diff; - } - } + // ii. Let mappedValue be the result of calling the Call internal method of callback + // with T as the this value and argument list containing kValue, k, and O. + mappedValue = callback.call(T, kValue, k, O); - // prevent end > max - if (this.options.max != null) { - var max = this.options.max.valueOf(); - if (newEnd > max) { - diff = (newEnd - max); - newStart -= diff; - newEnd -= diff; - } - } + // iii. Call the DefineOwnProperty internal method of A with arguments + // Pk, Property Descriptor {Value: mappedValue, : true, Enumerable: true, Configurable: true}, + // and false. - // prevent (end-start) > zoomMin - if (this.options.zoomMin != null) { - var zoomMin = this.options.zoomMin.valueOf(); - if (zoomMin < 0) { - zoomMin = 0; - } - if ((newEnd - newStart) < zoomMin) { - if ((this.end - this.start) > zoomMin) { - // zoom to the minimum - diff = (zoomMin - (newEnd - newStart)); - newStart -= diff / 2; - newEnd += diff / 2; - } - else { - // ingore this action, we are already zoomed to the minimum - newStart = this.start; - newEnd = this.end; - } - } - } + // In browsers that support Object.defineProperty, use the following: + // Object.defineProperty(A, Pk, { value: mappedValue, writable: true, enumerable: true, configurable: true }); - // prevent (end-start) > zoomMin - if (this.options.zoomMax != null) { - var zoomMax = this.options.zoomMax.valueOf(); - if (zoomMax < 0) { - zoomMax = 0; - } - if ((newEnd - newStart) > zoomMax) { - if ((this.end - this.start) < zoomMax) { - // zoom to the maximum - diff = ((newEnd - newStart) - zoomMax); - newStart += diff / 2; - newEnd -= diff / 2; - } - else { - // ingore this action, we are already zoomed to the maximum - newStart = this.start; - newEnd = this.end; + // For best browser support, use the following: + A[ k ] = mappedValue; } + // d. Increase k by 1. + k++; } - } - var changed = (this.start != newStart || this.end != newEnd); + // 9. return A + return A; + }; +} - this.start = newStart; - this.end = newEnd; +// Internet Explorer 8 and older does not support Array.filter, so we define it +// here in that case. +// https://developer.mozilla.org/en-US/docs/JavaScript/Reference/Global_Objects/Array/filter +if (!Array.prototype.filter) { + Array.prototype.filter = function(fun /*, thisp */) { + "use strict"; - return changed; -}; + if (this == null) { + throw new TypeError(); + } -/** - * Retrieve the current range. - * @return {Object} An object with start and end properties - */ -Range.prototype.getRange = function() { - return { - start: this.start, - end: this.end - }; -}; + var t = Object(this); + var len = t.length >>> 0; + if (typeof fun != "function") { + throw new TypeError(); + } -/** - * Calculate the conversion offset and factor for current range, based on - * the provided width - * @param {Number} width - * @returns {{offset: number, factor: number}} conversion - */ -Range.prototype.conversion = function (width) { - var start = this.start; - var end = this.end; + var res = []; + var thisp = arguments[1]; + for (var i = 0; i < len; i++) { + if (i in t) { + var val = t[i]; // in case fun mutates this + if (fun.call(thisp, val, i, t)) + res.push(val); + } + } - return Range.conversion(this.start, this.end, width); -}; + return res; + }; +} -/** - * Static method to calculate the conversion offset and factor for a range, - * based on the provided start, end, and width - * @param {Number} start - * @param {Number} end - * @param {Number} width - * @returns {{offset: number, factor: number}} conversion - */ -Range.conversion = function (start, end, width) { - if (width != 0 && (end - start != 0)) { - return { - offset: start, - factor: width / (end - start) - } - } - else { - return { - offset: 0, - factor: 1 - }; - } -}; -/** - * Start moving horizontally or vertically - * @param {Event} event - * @param {Object} listener Listener containing the component and params - * @private - */ -Range.prototype._onMouseDown = function(event, listener) { - event = event || window.event; - var params = listener.params; +// Internet Explorer 8 and older does not support Object.keys, so we define it +// here in that case. +// https://developer.mozilla.org/en-US/docs/JavaScript/Reference/Global_Objects/Object/keys +if (!Object.keys) { + Object.keys = (function () { + var hasOwnProperty = Object.prototype.hasOwnProperty, + hasDontEnumBug = !({toString: null}).propertyIsEnumerable('toString'), + dontEnums = [ + 'toString', + 'toLocaleString', + 'valueOf', + 'hasOwnProperty', + 'isPrototypeOf', + 'propertyIsEnumerable', + 'constructor' + ], + dontEnumsLength = dontEnums.length; - // only react on left mouse button down - var leftButtonDown = event.which ? (event.which == 1) : (event.button == 1); - if (!leftButtonDown) { - return; - } + return function (obj) { + if (typeof obj !== 'object' && typeof obj !== 'function' || obj === null) { + throw new TypeError('Object.keys called on non-object'); + } - // get mouse position - params.mouseX = util.getPageX(event); - params.mouseY = util.getPageY(event); - params.previousLeft = 0; - params.previousOffset = 0; + var result = []; - params.moved = false; - params.start = this.start; - params.end = this.end; + for (var prop in obj) { + if (hasOwnProperty.call(obj, prop)) result.push(prop); + } - var frame = listener.component.frame; - if (frame) { - frame.style.cursor = 'move'; - } + if (hasDontEnumBug) { + for (var i=0; i < dontEnumsLength; i++) { + if (hasOwnProperty.call(obj, dontEnums[i])) result.push(dontEnums[i]); + } + } + return result; + } + })() +} - // add event listeners to handle moving the contents - // we store the function onmousemove and onmouseup in the timeaxis, - // so we can remove the eventlisteners lateron in the function onmouseup - var me = this; - if (!params.onMouseMove) { - params.onMouseMove = function (event) { - me._onMouseMove(event, listener); - }; - util.addEventListener(document, "mousemove", params.onMouseMove); - } - if (!params.onMouseUp) { - params.onMouseUp = function (event) { - me._onMouseUp(event, listener); - }; - util.addEventListener(document, "mouseup", params.onMouseUp); - } +// Internet Explorer 8 and older does not support Array.isArray, +// so we define it here in that case. +// https://developer.mozilla.org/en-US/docs/JavaScript/Reference/Global_Objects/Array/isArray +if(!Array.isArray) { + Array.isArray = function (vArg) { + return Object.prototype.toString.call(vArg) === "[object Array]"; + }; +} + +// Internet Explorer 8 and older does not support Function.bind, +// so we define it here in that case. +// https://developer.mozilla.org/en-US/docs/JavaScript/Reference/Global_Objects/Function/bind +if (!Function.prototype.bind) { + Function.prototype.bind = function (oThis) { + if (typeof this !== "function") { + // closest thing possible to the ECMAScript 5 internal IsCallable function + throw new TypeError("Function.prototype.bind - what is trying to be bound is not callable"); + } - util.preventDefault(event); -}; + var aArgs = Array.prototype.slice.call(arguments, 1), + fToBind = this, + fNOP = function () {}, + fBound = function () { + return fToBind.apply(this instanceof fNOP && oThis + ? this + : oThis, + aArgs.concat(Array.prototype.slice.call(arguments))); + }; -/** - * Perform moving operating. - * This function activated from within the funcion TimeAxis._onMouseDown(). - * @param {Event} event - * @param {Object} listener - * @private - */ -Range.prototype._onMouseMove = function (event, listener) { - event = event || window.event; + fNOP.prototype = this.prototype; + fBound.prototype = new fNOP(); - var params = listener.params; + return fBound; + }; +} - // calculate change in mouse position - var mouseX = util.getPageX(event); - var mouseY = util.getPageY(event); +// https://developer.mozilla.org/en-US/docs/JavaScript/Reference/Global_Objects/Object/create +if (!Object.create) { + Object.create = function (o) { + if (arguments.length > 1) { + throw new Error('Object.create implementation only accepts the first parameter.'); + } + function F() {} + F.prototype = o; + return new F(); + }; +} - if (params.mouseX == undefined) { - params.mouseX = mouseX; - } - if (params.mouseY == undefined) { - params.mouseY = mouseY; - } +// https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Function/bind +if (!Function.prototype.bind) { + Function.prototype.bind = function (oThis) { + if (typeof this !== "function") { + // closest thing possible to the ECMAScript 5 internal IsCallable function + throw new TypeError("Function.prototype.bind - what is trying to be bound is not callable"); + } - var diffX = mouseX - params.mouseX; - var diffY = mouseY - params.mouseY; - var diff = (listener.direction == 'horizontal') ? diffX : diffY; + var aArgs = Array.prototype.slice.call(arguments, 1), + fToBind = this, + fNOP = function () {}, + fBound = function () { + return fToBind.apply(this instanceof fNOP && oThis + ? this + : oThis, + aArgs.concat(Array.prototype.slice.call(arguments))); + }; - // if mouse movement is big enough, register it as a "moved" event - if (Math.abs(diff) >= 1) { - params.moved = true; - } + fNOP.prototype = this.prototype; + fBound.prototype = new fNOP(); - var interval = (params.end - params.start); - var width = (listener.direction == 'horizontal') ? - listener.component.width : listener.component.height; - var diffRange = -diff / width * interval; - this._applyRange(params.start + diffRange, params.end + diffRange); + return fBound; + }; +} - // fire a rangechange event - this._trigger('rangechange'); +/** + * utility functions + */ +var util = {}; - util.preventDefault(event); +/** + * Test whether given object is a number + * @param {*} object + * @return {Boolean} isNumber + */ +util.isNumber = function isNumber(object) { + return (object instanceof Number || typeof object == 'number'); }; /** - * Stop moving operating. - * This function activated from within the function Range._onMouseDown(). - * @param {event} event - * @param {Object} listener - * @private + * Test whether given object is a string + * @param {*} object + * @return {Boolean} isString */ -Range.prototype._onMouseUp = function (event, listener) { - event = event || window.event; - - var params = listener.params; - - if (listener.component.frame) { - listener.component.frame.style.cursor = 'auto'; - } - - // remove event listeners here, important for Safari - if (params.onMouseMove) { - util.removeEventListener(document, "mousemove", params.onMouseMove); - params.onMouseMove = null; - } - if (params.onMouseUp) { - util.removeEventListener(document, "mouseup", params.onMouseUp); - params.onMouseUp = null; - } - //util.preventDefault(event); - - if (params.moved) { - // fire a rangechanged event - this._trigger('rangechanged'); - } +util.isString = function isString(object) { + return (object instanceof String || typeof object == 'string'); }; /** - * Event handler for mouse wheel event, used to zoom - * Code from http://adomas.org/javascript-mouse-wheel/ - * @param {Event} event - * @param {Object} listener - * @private + * Test whether given object is a Date, or a String containing a Date + * @param {Date | String} object + * @return {Boolean} isDate */ -Range.prototype._onMouseWheel = function(event, listener) { - event = event || window.event; - - // retrieve delta - var delta = 0; - if (event.wheelDelta) { /* IE/Opera. */ - delta = event.wheelDelta / 120; - } else if (event.detail) { /* Mozilla case. */ - // In Mozilla, sign of delta is different than in IE. - // Also, delta is multiple of 3. - delta = -event.detail / 3; +util.isDate = function isDate(object) { + if (object instanceof Date) { + return true; } - - // If delta is nonzero, handle it. - // Basically, delta is now positive if wheel was scrolled up, - // and negative, if wheel was scrolled down. - if (delta) { - var me = this; - var zoom = function () { - // perform the zoom action. Delta is normally 1 or -1 - var zoomFactor = delta / 5.0; - var zoomAround = null; - var frame = listener.component.frame; - if (frame) { - var size, conversion; - if (listener.direction == 'horizontal') { - size = listener.component.width; - conversion = me.conversion(size); - var frameLeft = util.getAbsoluteLeft(frame); - var mouseX = util.getPageX(event); - zoomAround = (mouseX - frameLeft) / conversion.factor + conversion.offset; - } - else { - size = listener.component.height; - conversion = me.conversion(size); - var frameTop = util.getAbsoluteTop(frame); - var mouseY = util.getPageY(event); - zoomAround = ((frameTop + size - mouseY) - frameTop) / conversion.factor + conversion.offset; - } - } - - me.zoom(zoomFactor, zoomAround); - }; - - zoom(); + else if (util.isString(object)) { + // test whether this string contains a date + var match = ASPDateRegex.exec(object); + if (match) { + return true; + } + else if (!isNaN(Date.parse(object))) { + return true; + } } - // Prevent default actions caused by mouse wheel. - // That might be ugly, but we handle scrolls somehow - // anyway, so don't bother here... - util.preventDefault(event); + return false; }; - /** - * Zoom the range the given zoomfactor in or out. Start and end date will - * be adjusted, and the timeline will be redrawn. You can optionally give a - * date around which to zoom. - * For example, try zoomfactor = 0.1 or -0.1 - * @param {Number} zoomFactor Zooming amount. Positive value will zoom in, - * negative value will zoom out - * @param {Number} zoomAround Value around which will be zoomed. Optional + * Test whether given object is an instance of google.visualization.DataTable + * @param {*} object + * @return {Boolean} isDataTable */ -Range.prototype.zoom = function(zoomFactor, zoomAround) { - // if zoomAroundDate is not provided, take it half between start Date and end Date - if (zoomAround == null) { - zoomAround = (this.start + this.end) / 2; - } - - // prevent zoom factor larger than 1 or smaller than -1 (larger than 1 will - // result in a start>=end ) - if (zoomFactor >= 1) { - zoomFactor = 0.9; - } - if (zoomFactor <= -1) { - zoomFactor = -0.9; - } +util.isDataTable = function isDataTable(object) { + return (typeof (google) !== 'undefined') && + (google.visualization) && + (google.visualization.DataTable) && + (object instanceof google.visualization.DataTable); +}; - // adjust a negative factor such that zooming in with 0.1 equals zooming - // out with a factor -0.1 - if (zoomFactor < 0) { - zoomFactor = zoomFactor / (1 + zoomFactor); - } +/** + * Create a semi UUID + * source: http://stackoverflow.com/a/105074/1262753 + * @return {String} uuid + */ +util.randomUUID = function randomUUID () { + var S4 = function () { + return Math.floor( + Math.random() * 0x10000 /* 65536 */ + ).toString(16); + }; - // zoom start and end relative to the zoomAround value - var startDiff = (this.start - zoomAround); - var endDiff = (this.end - zoomAround); + return ( + S4() + S4() + '-' + + S4() + '-' + + S4() + '-' + + S4() + '-' + + S4() + S4() + S4() + ); +}; - // calculate new start and end - var newStart = this.start - startDiff * zoomFactor; - var newEnd = this.end - endDiff * zoomFactor; +/** + * Extend object a with the properties of object b or a series of objects + * Only properties with defined values are copied + * @param {Object} a + * @param {... Object} b + * @return {Object} a + */ +util.extend = function (a, b) { + for (var i = 1, len = arguments.length; i < len; i++) { + var other = arguments[i]; + for (var prop in other) { + if (other.hasOwnProperty(prop) && other[prop] !== undefined) { + a[prop] = other[prop]; + } + } + } - this.setRange(newStart, newEnd); + return a; }; /** - * Move the range with a given factor to the left or right. Start and end - * value will be adjusted. For example, try moveFactor = 0.1 or -0.1 - * @param {Number} moveFactor Moving amount. Positive value will move right, - * negative value will move left + * Convert an object to another type + * @param {Boolean | Number | String | Date | Moment | Null | undefined} object + * @param {String | undefined} type Name of the type. Available types: + * 'Boolean', 'Number', 'String', + * 'Date', 'Moment', ISODate', 'ASPDate'. + * @return {*} object + * @throws Error */ -Range.prototype.move = function(moveFactor) { - // zoom start Date and end Date relative to the zoomAroundDate - var diff = (this.end - this.start); +util.convert = function convert(object, type) { + var match; - // apply new values - var newStart = this.start + diff * moveFactor; - var newEnd = this.end + diff * moveFactor; + if (object === undefined) { + return undefined; + } + if (object === null) { + return null; + } - // TODO: reckon with min and max range + if (!type) { + return object; + } + if (!(typeof type === 'string') && !(type instanceof String)) { + throw new Error('Type must be a string'); + } - this.start = newStart; - this.end = newEnd; -}; + //noinspection FallthroughInSwitchStatementJS + switch (type) { + case 'boolean': + case 'Boolean': + return Boolean(object); -/** - * Move the range to a new center point - * @param {Number} moveTo New center point of the range - */ -Range.prototype.moveTo = function(moveTo) { - var center = (this.start + this.end) / 2; + case 'number': + case 'Number': + return Number(object.valueOf()); - var diff = center - moveTo; + case 'string': + case 'String': + return String(object); - // calculate new start and end - var newStart = this.start - diff; - var newEnd = this.end - diff; + case 'Date': + if (util.isNumber(object)) { + return new Date(object); + } + if (object instanceof Date) { + return new Date(object.valueOf()); + } + else if (moment.isMoment(object)) { + return new Date(object.valueOf()); + } + if (util.isString(object)) { + match = ASPDateRegex.exec(object); + if (match) { + // object is an ASP date + return new Date(Number(match[1])); // parse number + } + else { + return moment(object).toDate(); // parse string + } + } + else { + throw new Error( + 'Cannot convert object of type ' + util.getType(object) + + ' to type Date'); + } - this.setRange(newStart, newEnd); -} + case 'Moment': + if (util.isNumber(object)) { + return moment(object); + } + if (object instanceof Date) { + return moment(object.valueOf()); + } + else if (moment.isMoment(object)) { + return moment.clone(); + } + if (util.isString(object)) { + match = ASPDateRegex.exec(object); + if (match) { + // object is an ASP date + return moment(Number(match[1])); // parse number + } + else { + return moment(object); // parse string + } + } + else { + throw new Error( + 'Cannot convert object of type ' + util.getType(object) + + ' to type Date'); + } -/** - * @constructor Controller - * - * A Controller controls the reflows and repaints of all visual components - */ -function Controller () { - this.id = util.randomUUID(); - this.components = {}; + case 'ISODate': + if (util.isNumber(object)) { + return new Date(object); + } + else if (object instanceof Date) { + return object.toISOString(); + } + else if (moment.isMoment(object)) { + return object.toDate().toISOString(); + } + else if (util.isString(object)) { + match = ASPDateRegex.exec(object); + if (match) { + // object is an ASP date + return new Date(Number(match[1])).toISOString(); // parse number + } + else { + return new Date(object).toISOString(); // parse string + } + } + else { + throw new Error( + 'Cannot convert object of type ' + util.getType(object) + + ' to type ISODate'); + } - this.repaintTimer = undefined; - this.reflowTimer = undefined; -} + case 'ASPDate': + if (util.isNumber(object)) { + return '/Date(' + object + ')/'; + } + else if (object instanceof Date) { + return '/Date(' + object.valueOf() + ')/'; + } + else if (util.isString(object)) { + match = ASPDateRegex.exec(object); + var value; + if (match) { + // object is an ASP date + value = new Date(Number(match[1])).valueOf(); // parse number + } + else { + value = new Date(object).valueOf(); // parse string + } + return '/Date(' + value + ')/'; + } + else { + throw new Error( + 'Cannot convert object of type ' + util.getType(object) + + ' to type ASPDate'); + } -/** - * Add a component to the controller - * @param {Component} component - */ -Controller.prototype.add = function add(component) { - // validate the component - if (component.id == undefined) { - throw new Error('Component has no field id'); - } - if (!(component instanceof Component) && !(component instanceof Controller)) { - throw new TypeError('Component must be an instance of ' + - 'prototype Component or Controller'); + default: + throw new Error('Cannot convert object of type ' + util.getType(object) + + ' to type "' + type + '"'); } - - // add the component - component.controller = this; - this.components[component.id] = component; }; +// parse ASP.Net Date pattern, +// for example '/Date(1198908717056)/' or '/Date(1198908717056-0700)/' +// code from http://momentjs.com/ +var ASPDateRegex = /^\/?Date\((\-?\d+)/i; + /** - * Remove a component from the controller - * @param {Component | String} component + * Get the type of an object, for example util.getType([]) returns 'Array' + * @param {*} object + * @return {String} type */ -Controller.prototype.remove = function remove(component) { - var id; - for (id in this.components) { - if (this.components.hasOwnProperty(id)) { - if (id == component || this.components[id] == component) { - break; - } +util.getType = function getType(object) { + var type = typeof object; + + if (type == 'object') { + if (object == null) { + return 'null'; + } + if (object instanceof Boolean) { + return 'Boolean'; + } + if (object instanceof Number) { + return 'Number'; + } + if (object instanceof String) { + return 'String'; + } + if (object instanceof Array) { + return 'Array'; } + if (object instanceof Date) { + return 'Date'; + } + return 'Object'; + } + else if (type == 'number') { + return 'Number'; + } + else if (type == 'boolean') { + return 'Boolean'; + } + else if (type == 'string') { + return 'String'; } - if (id) { - delete this.components[id]; - } + return type; }; /** - * Request a reflow. The controller will schedule a reflow - * @param {Boolean} [force] If true, an immediate reflow is forced. Default - * is false. + * Retrieve the absolute left value of a DOM element + * @param {Element} elem A dom element, for example a div + * @return {number} left The absolute left position of this element + * in the browser page. */ -Controller.prototype.requestReflow = function requestReflow(force) { - if (force) { - this.reflow(); - } - else { - if (!this.reflowTimer) { - var me = this; - this.reflowTimer = setTimeout(function () { - me.reflowTimer = undefined; - me.reflow(); - }, 0); - } +util.getAbsoluteLeft = function getAbsoluteLeft (elem) { + var doc = document.documentElement; + var body = document.body; + + var left = elem.offsetLeft; + var e = elem.offsetParent; + while (e != null && e != body && e != doc) { + left += e.offsetLeft; + left -= e.scrollLeft; + e = e.offsetParent; } + return left; }; /** - * Request a repaint. The controller will schedule a repaint - * @param {Boolean} [force] If true, an immediate repaint is forced. Default - * is false. + * Retrieve the absolute top value of a DOM element + * @param {Element} elem A dom element, for example a div + * @return {number} top The absolute top position of this element + * in the browser page. */ -Controller.prototype.requestRepaint = function requestRepaint(force) { - if (force) { - this.repaint(); - } - else { - if (!this.repaintTimer) { - var me = this; - this.repaintTimer = setTimeout(function () { - me.repaintTimer = undefined; - me.repaint(); - }, 0); - } +util.getAbsoluteTop = function getAbsoluteTop (elem) { + var doc = document.documentElement; + var body = document.body; + + var top = elem.offsetTop; + var e = elem.offsetParent; + while (e != null && e != body && e != doc) { + top += e.offsetTop; + top -= e.scrollTop; + e = e.offsetParent; } + return top; }; /** - * Repaint all components + * Get the absolute, vertical mouse position from an event. + * @param {Event} event + * @return {Number} pageY */ -Controller.prototype.repaint = function repaint() { - var changed = false; - - // cancel any running repaint request - if (this.repaintTimer) { - clearTimeout(this.repaintTimer); - this.repaintTimer = undefined; +util.getPageY = function getPageY (event) { + if ('pageY' in event) { + return event.pageY; } - - var done = {}; - - function repaint(component, id) { - if (!(id in done)) { - // first repaint the components on which this component is dependent - if (component.depends) { - component.depends.forEach(function (dep) { - repaint(dep, dep.id); - }); - } - if (component.parent) { - repaint(component.parent, component.parent.id); - } - - // repaint the component itself and mark as done - changed = component.repaint() || changed; - done[id] = true; + else { + var clientY; + if (('targetTouches' in event) && event.targetTouches.length) { + clientY = event.targetTouches[0].clientY; + } + else { + clientY = event.clientY; } - } - - util.forEach(this.components, repaint); - // immediately reflow when needed - if (changed) { - this.reflow(); + var doc = document.documentElement; + var body = document.body; + return clientY + + ( doc && doc.scrollTop || body && body.scrollTop || 0 ) - + ( doc && doc.clientTop || body && body.clientTop || 0 ); } - // TODO: limit the number of nested reflows/repaints, prevent loop }; /** - * Reflow all components + * Get the absolute, horizontal mouse position from an event. + * @param {Event} event + * @return {Number} pageX */ -Controller.prototype.reflow = function reflow() { - var resized = false; - - // cancel any running repaint request - if (this.reflowTimer) { - clearTimeout(this.reflowTimer); - this.reflowTimer = undefined; +util.getPageX = function getPageX (event) { + if ('pageY' in event) { + return event.pageX; } - - var done = {}; - - function reflow(component, id) { - if (!(id in done)) { - // first reflow the components on which this component is dependent - if (component.depends) { - component.depends.forEach(function (dep) { - reflow(dep, dep.id); - }); - } - if (component.parent) { - reflow(component.parent, component.parent.id); - } - - // reflow the component itself and mark as done - resized = component.reflow() || resized; - done[id] = true; + else { + var clientX; + if (('targetTouches' in event) && event.targetTouches.length) { + clientX = event.targetTouches[0].clientX; + } + else { + clientX = event.clientX; } - } - - util.forEach(this.components, reflow); - // immediately repaint when needed - if (resized) { - this.repaint(); + var doc = document.documentElement; + var body = document.body; + return clientX + + ( doc && doc.scrollLeft || body && body.scrollLeft || 0 ) - + ( doc && doc.clientLeft || body && body.clientLeft || 0 ); } - // TODO: limit the number of nested reflows/repaints, prevent loop }; /** - * Prototype for visual components - */ -function Component () { - this.id = null; - this.parent = null; - this.depends = null; - this.controller = null; - this.options = null; - - this.frame = null; // main DOM element - this.top = 0; - this.left = 0; - this.width = 0; - this.height = 0; -} - -/** - * Set parameters for the frame. Parameters will be merged in current parameter - * set. - * @param {Object} options Available parameters: - * {String | function} [className] - * {EventBus} [eventBus] - * {String | Number | function} [left] - * {String | Number | function} [top] - * {String | Number | function} [width] - * {String | Number | function} [height] + * add a className to the given elements style + * @param {Element} elem + * @param {String} className */ -Component.prototype.setOptions = function setOptions(options) { - if (options) { - util.extend(this.options, options); - - if (this.controller) { - this.requestRepaint(); - this.requestReflow(); - } +util.addClassName = function addClassName(elem, className) { + var classes = elem.className.split(' '); + if (classes.indexOf(className) == -1) { + classes.push(className); // add the class to the array + elem.className = classes.join(' '); } }; /** - * Get an option value by name - * The function will first check this.options object, and else will check - * this.defaultOptions. - * @param {String} name - * @return {*} value + * add a className to the given elements style + * @param {Element} elem + * @param {String} className */ -Component.prototype.getOption = function getOption(name) { - var value; - if (this.options) { - value = this.options[name]; - } - if (value === undefined && this.defaultOptions) { - value = this.defaultOptions[name]; +util.removeClassName = function removeClassname(elem, className) { + var classes = elem.className.split(' '); + var index = classes.indexOf(className); + if (index != -1) { + classes.splice(index, 1); // remove the class from the array + elem.className = classes.join(' '); } - return value; -}; - -/** - * Get the container element of the component, which can be used by a child to - * add its own widgets. Not all components do have a container for childs, in - * that case null is returned. - * @returns {HTMLElement | null} container - */ -// TODO: get rid of the getContainer and getFrame methods, provide these via the options -Component.prototype.getContainer = function getContainer() { - // should be implemented by the component - return null; }; /** - * Get the frame element of the component, the outer HTML DOM element. - * @returns {HTMLElement | null} frame + * For each method for both arrays and objects. + * In case of an array, the built-in Array.forEach() is applied. + * In case of an Object, the method loops over all properties of the object. + * @param {Object | Array} object An Object or Array + * @param {function} callback Callback method, called for each item in + * the object or array with three parameters: + * callback(value, index, object) */ -Component.prototype.getFrame = function getFrame() { - return this.frame; +util.forEach = function forEach (object, callback) { + var i, + len; + if (object instanceof Array) { + // array + for (i = 0, len = object.length; i < len; i++) { + callback(object[i], i, object); + } + } + else { + // object + for (i in object) { + if (object.hasOwnProperty(i)) { + callback(object[i], i, object); + } + } + } }; /** - * Repaint the component + * Update a property in an object + * @param {Object} object + * @param {String} key + * @param {*} value * @return {Boolean} changed */ -Component.prototype.repaint = function repaint() { - // should be implemented by the component - return false; +util.updateProperty = function updateProp (object, key, value) { + if (object[key] !== value) { + object[key] = value; + return true; + } + else { + return false; + } }; /** - * Reflow the component - * @return {Boolean} resized + * Add and event listener. Works for all browsers + * @param {Element} element An html element + * @param {string} action The action, for example "click", + * without the prefix "on" + * @param {function} listener The callback function to be executed + * @param {boolean} [useCapture] */ -Component.prototype.reflow = function reflow() { - // should be implemented by the component - return false; +util.addEventListener = function addEventListener(element, action, listener, useCapture) { + if (element.addEventListener) { + if (useCapture === undefined) + useCapture = false; + + if (action === "mousewheel" && navigator.userAgent.indexOf("Firefox") >= 0) { + action = "DOMMouseScroll"; // For Firefox + } + + element.addEventListener(action, listener, useCapture); + } else { + element.attachEvent("on" + action, listener); // IE browsers + } }; /** - * Hide the component from the DOM - * @return {Boolean} changed + * Remove an event listener from an element + * @param {Element} element An html dom element + * @param {string} action The name of the event, for example "mousedown" + * @param {function} listener The listener function + * @param {boolean} [useCapture] */ -Component.prototype.hide = function hide() { - if (this.frame && this.frame.parentNode) { - this.frame.parentNode.removeChild(this.frame); - return true; - } - else { - return false; +util.removeEventListener = function removeEventListener(element, action, listener, useCapture) { + if (element.removeEventListener) { + // non-IE browsers + if (useCapture === undefined) + useCapture = false; + + if (action === "mousewheel" && navigator.userAgent.indexOf("Firefox") >= 0) { + action = "DOMMouseScroll"; // For Firefox + } + + element.removeEventListener(action, listener, useCapture); + } else { + // IE browsers + element.detachEvent("on" + action, listener); } }; + /** - * Show the component in the DOM (when not already visible). - * A repaint will be executed when the component is not visible - * @return {Boolean} changed + * Get HTML element which is the target of the event + * @param {Event} event + * @return {Element} target element */ -Component.prototype.show = function show() { - if (!this.frame || !this.frame.parentNode) { - return this.repaint(); +util.getTarget = function getTarget(event) { + // code from http://www.quirksmode.org/js/events_properties.html + if (!event) { + event = window.event; } - else { - return false; + + var target; + + if (event.target) { + target = event.target; + } + else if (event.srcElement) { + target = event.srcElement; + } + + if (target.nodeType != undefined && target.nodeType == 3) { + // defeat Safari bug + target = target.parentNode; } + + return target; }; /** - * Request a repaint. The controller will schedule a repaint + * Stop event propagation */ -Component.prototype.requestRepaint = function requestRepaint() { - if (this.controller) { - this.controller.requestRepaint(); +util.stopPropagation = function stopPropagation(event) { + if (!event) + event = window.event; + + if (event.stopPropagation) { + event.stopPropagation(); // non-IE browsers } else { - throw new Error('Cannot request a repaint: no controller configured'); - // TODO: just do a repaint when no parent is configured? + event.cancelBubble = true; // IE browsers } }; + /** - * Request a reflow. The controller will schedule a reflow + * Cancels the event if it is cancelable, without stopping further propagation of the event. */ -Component.prototype.requestReflow = function requestReflow() { - if (this.controller) { - this.controller.requestReflow(); +util.preventDefault = function preventDefault (event) { + if (!event) + event = window.event; + + if (event.preventDefault) { + event.preventDefault(); // non-IE browsers } else { - throw new Error('Cannot request a reflow: no controller configured'); - // TODO: just do a reflow when no parent is configured? + event.returnValue = false; // IE browsers } }; + +util.option = {}; + /** - * A panel can contain components - * @param {Component} [parent] - * @param {Component[]} [depends] Components on which this components depends - * (except for the parent) - * @param {Object} [options] Available parameters: - * {String | Number | function} [left] - * {String | Number | function} [top] - * {String | Number | function} [width] - * {String | Number | function} [height] - * {String | function} [className] - * @constructor Panel - * @extends Component + * Convert a value into a boolean + * @param {Boolean | function | undefined} value + * @param {Boolean} [defaultValue] + * @returns {Boolean} bool */ -function Panel(parent, depends, options) { - this.id = util.randomUUID(); - this.parent = parent; - this.depends = depends; +util.option.asBoolean = function (value, defaultValue) { + if (typeof value == 'function') { + value = value(); + } - this.options = options || {}; -} + if (value != null) { + return (value != false); + } -Panel.prototype = new Component(); + return defaultValue || null; +}; /** - * Set options. Will extend the current options. - * @param {Object} [options] Available parameters: - * {String | function} [className] - * {String | Number | function} [left] - * {String | Number | function} [top] - * {String | Number | function} [width] - * {String | Number | function} [height] + * Convert a value into a number + * @param {Boolean | function | undefined} value + * @param {Number} [defaultValue] + * @returns {Number} number */ -Panel.prototype.setOptions = Component.prototype.setOptions; +util.option.asNumber = function (value, defaultValue) { + if (typeof value == 'function') { + value = value(); + } -/** - * Get the container element of the panel, which can be used by a child to - * add its own widgets. - * @returns {HTMLElement} container - */ -Panel.prototype.getContainer = function () { - return this.frame; + if (value != null) { + return Number(value) || defaultValue || null; + } + + return defaultValue || null; }; /** - * Repaint the component - * @return {Boolean} changed + * Convert a value into a string + * @param {String | function | undefined} value + * @param {String} [defaultValue] + * @returns {String} str */ -Panel.prototype.repaint = function () { - var changed = 0, - update = util.updateProperty, - asSize = util.option.asSize, - options = this.options, - frame = this.frame; - if (!frame) { - frame = document.createElement('div'); - frame.className = 'panel'; - - var className = options.className; - if (className) { - if (typeof className == 'function') { - util.addClassName(frame, String(className())); - } - else { - util.addClassName(frame, String(className)); - } - } - - this.frame = frame; - changed += 1; - } - if (!frame.parentNode) { - if (!this.parent) { - throw new Error('Cannot repaint panel: no parent attached'); - } - var parentContainer = this.parent.getContainer(); - if (!parentContainer) { - throw new Error('Cannot repaint panel: parent has no container element'); - } - parentContainer.appendChild(frame); - changed += 1; +util.option.asString = function (value, defaultValue) { + if (typeof value == 'function') { + value = value(); } - changed += update(frame.style, 'top', asSize(options.top, '0px')); - changed += update(frame.style, 'left', asSize(options.left, '0px')); - changed += update(frame.style, 'width', asSize(options.width, '100%')); - changed += update(frame.style, 'height', asSize(options.height, '100%')); + if (value != null) { + return String(value); + } - return (changed > 0); + return defaultValue || null; }; /** - * Reflow the component - * @return {Boolean} resized + * Convert a size or location into a string with pixels or a percentage + * @param {String | Number | function | undefined} value + * @param {String} [defaultValue] + * @returns {String} size */ -Panel.prototype.reflow = function () { - var changed = 0, - update = util.updateProperty, - frame = this.frame; +util.option.asSize = function (value, defaultValue) { + if (typeof value == 'function') { + value = value(); + } - if (frame) { - changed += update(this, 'top', frame.offsetTop); - changed += update(this, 'left', frame.offsetLeft); - changed += update(this, 'width', frame.offsetWidth); - changed += update(this, 'height', frame.offsetHeight); + if (util.isString(value)) { + return value; + } + else if (util.isNumber(value)) { + return value + 'px'; } else { - changed += 1; + return defaultValue || null; } +}; - return (changed > 0); +/** + * Convert a value into a DOM element + * @param {HTMLElement | function | undefined} value + * @param {HTMLElement} [defaultValue] + * @returns {HTMLElement | null} dom + */ +util.option.asElement = function (value, defaultValue) { + if (typeof value == 'function') { + value = value(); + } + + return value || defaultValue || null; }; /** - * A root panel can hold components. The root panel must be initialized with - * a DOM element as container. - * @param {HTMLElement} container - * @param {Object} [options] Available parameters: see RootPanel.setOptions. - * @constructor RootPanel - * @extends Panel + * load css from text + * @param {String} css Text containing css */ -function RootPanel(container, options) { - this.id = util.randomUUID(); - this.container = container; +util.loadCss = function (css) { + if (typeof document === 'undefined') { + return; + } - this.options = options || {}; - this.defaultOptions = { - autoResize: true - }; + // get the script location, and built the css file name from the js file name + // http://stackoverflow.com/a/2161748/1262753 + // var scripts = document.getElementsByTagName('script'); + // var jsFile = scripts[scripts.length-1].src.split('?')[0]; + // var cssFile = jsFile.substring(0, jsFile.length - 2) + 'css'; - this.listeners = {}; // event listeners -} + // inject css + // http://stackoverflow.com/questions/524696/how-to-create-a-style-tag-with-javascript + var style = document.createElement('style'); + style.type = 'text/css'; + if (style.styleSheet){ + style.styleSheet.cssText = css; + } else { + style.appendChild(document.createTextNode(css)); + } -RootPanel.prototype = new Panel(); + document.getElementsByTagName('head')[0].appendChild(style); +}; /** - * Set options. Will extend the current options. - * @param {Object} [options] Available parameters: - * {String | function} [className] - * {String | Number | function} [left] - * {String | Number | function} [top] - * {String | Number | function} [width] - * {String | Number | function} [height] - * {Boolean | function} [autoResize] + * Event listener (singleton) */ -RootPanel.prototype.setOptions = Component.prototype.setOptions; +// TODO: replace usage of the event listener for the EventBus +var events = { + 'listeners': [], -/** - * Repaint the component - * @return {Boolean} changed - */ -RootPanel.prototype.repaint = function () { - var changed = 0, - update = util.updateProperty, - asSize = util.option.asSize, - options = this.options, - frame = this.frame; + /** + * Find a single listener by its object + * @param {Object} object + * @return {Number} index -1 when not found + */ + 'indexOf': function (object) { + var listeners = this.listeners; + for (var i = 0, iMax = this.listeners.length; i < iMax; i++) { + var listener = listeners[i]; + if (listener && listener.object == object) { + return i; + } + } + return -1; + }, - if (!frame) { - frame = document.createElement('div'); - frame.className = 'vis timeline rootpanel'; + /** + * Add an event listener + * @param {Object} object + * @param {String} event The name of an event, for example 'select' + * @param {function} callback The callback method, called when the + * event takes place + */ + 'addListener': function (object, event, callback) { + var index = this.indexOf(object); + var listener = this.listeners[index]; + if (!listener) { + listener = { + 'object': object, + 'events': {} + }; + this.listeners.push(listener); + } - var className = options.className; - if (className) { - util.addClassName(frame, util.option.asString(className)); + var callbacks = listener.events[event]; + if (!callbacks) { + callbacks = []; + listener.events[event] = callbacks; } - this.frame = frame; + // add the callback if it does not yet exist + if (callbacks.indexOf(callback) == -1) { + callbacks.push(callback); + } + }, - changed += 1; - } - if (!frame.parentNode) { - if (!this.container) { - throw new Error('Cannot repaint root panel: no container attached'); + /** + * Remove an event listener + * @param {Object} object + * @param {String} event The name of an event, for example 'select' + * @param {function} callback The registered callback method + */ + 'removeListener': function (object, event, callback) { + var index = this.indexOf(object); + var listener = this.listeners[index]; + if (listener) { + var callbacks = listener.events[event]; + if (callbacks) { + index = callbacks.indexOf(callback); + if (index != -1) { + callbacks.splice(index, 1); + } + + // remove the array when empty + if (callbacks.length == 0) { + delete listener.events[event]; + } + } + + // count the number of registered events. remove listener when empty + var count = 0; + var events = listener.events; + for (var e in events) { + if (events.hasOwnProperty(e)) { + count++; + } + } + if (count == 0) { + delete this.listeners[index]; + } + } + }, + + /** + * Remove all registered event listeners + */ + 'removeAllListeners': function () { + this.listeners = []; + }, + + /** + * Trigger an event. All registered event handlers will be called + * @param {Object} object + * @param {String} event + * @param {Object} properties (optional) + */ + 'trigger': function (object, event, properties) { + var index = this.indexOf(object); + var listener = this.listeners[index]; + if (listener) { + var callbacks = listener.events[event]; + if (callbacks) { + for (var i = 0, iMax = callbacks.length; i < iMax; i++) { + callbacks[i](properties); + } + } } - this.container.appendChild(frame); - changed += 1; } +}; - changed += update(frame.style, 'top', asSize(options.top, '0px')); - changed += update(frame.style, 'left', asSize(options.left, '0px')); - changed += update(frame.style, 'width', asSize(options.width, '100%')); - changed += update(frame.style, 'height', asSize(options.height, '100%')); +/** + * An event bus can be used to emit events, and to subscribe to events + * @constructor EventBus + */ +function EventBus() { + this.subscriptions = []; +} - this._updateEventEmitters(); - this._updateWatch(); +/** + * Subscribe to an event + * @param {String | RegExp} event The event can be a regular expression, or + * a string with wildcards, like 'server.*'. + * @param {function} callback. Callback are called with three parameters: + * {String} event, {*} [data], {*} [source] + * @param {*} [target] + * @returns {String} id A subscription id + */ +EventBus.prototype.on = function (event, callback, target) { + var regexp = (event instanceof RegExp) ? + event : + new RegExp(event.replace('*', '\\w+')); - return (changed > 0); + var subscription = { + id: util.randomUUID(), + event: event, + regexp: regexp, + callback: (typeof callback === 'function') ? callback : null, + target: target + }; + + this.subscriptions.push(subscription); + + return subscription.id; }; /** - * Reflow the component - * @return {Boolean} resized + * Unsubscribe from an event + * @param {String | Object} filter Filter for subscriptions to be removed + * Filter can be a string containing a + * subscription id, or an object containing + * one or more of the fields id, event, + * callback, and target. */ -RootPanel.prototype.reflow = function () { - var changed = 0, - update = util.updateProperty, - frame = this.frame; +EventBus.prototype.off = function (filter) { + var i = 0; + while (i < this.subscriptions.length) { + var subscription = this.subscriptions[i]; - if (frame) { - changed += update(this, 'top', frame.offsetTop); - changed += update(this, 'left', frame.offsetLeft); - changed += update(this, 'width', frame.offsetWidth); - changed += update(this, 'height', frame.offsetHeight); - } - else { - changed += 1; - } + var match = true; + if (filter instanceof Object) { + // filter is an object. All fields must match + for (var prop in filter) { + if (filter.hasOwnProperty(prop)) { + if (filter[prop] !== subscription[prop]) { + match = false; + } + } + } + } + else { + // filter is a string, filter on id + match = (subscription.id == filter); + } - return (changed > 0); + if (match) { + this.subscriptions.splice(i, 1); + } + else { + i++; + } + } }; /** - * Update watching for resize, depending on the current option - * @private + * Emit an event + * @param {String} event + * @param {*} [data] + * @param {*} [source] */ -RootPanel.prototype._updateWatch = function () { - var autoResize = this.getOption('autoResize'); - if (autoResize) { - this._watch(); - } - else { - this._unwatch(); +EventBus.prototype.emit = function (event, data, source) { + for (var i =0; i < this.subscriptions.length; i++) { + var subscription = this.subscriptions[i]; + if (subscription.regexp.test(event)) { + if (subscription.callback) { + subscription.callback(event, data, source); + } + } } }; /** - * Watch for changes in the size of the frame. On resize, the Panel will - * automatically redraw itself. - * @private + * DataSet + * + * Usage: + * var dataSet = new DataSet({ + * fieldId: '_id', + * convert: { + * // ... + * } + * }); + * + * dataSet.add(item); + * dataSet.add(data); + * dataSet.update(item); + * dataSet.update(data); + * dataSet.remove(id); + * dataSet.remove(ids); + * var data = dataSet.get(); + * var data = dataSet.get(id); + * var data = dataSet.get(ids); + * var data = dataSet.get(ids, options, data); + * dataSet.clear(); + * + * A data set can: + * - add/remove/update data + * - gives triggers upon changes in the data + * - can import/export data in various data formats + * + * @param {Object} [options] Available options: + * {String} fieldId Field name of the id in the + * items, 'id' by default. + * {Object.} [convert] + * {String[]} [fields] field names to be returned + * {function} [filter] filter items + * {String | function} [order] Order the items by + * a field name or custom sort function. + * {Array | DataTable} [data] If provided, items will be appended to this + * array or table. Required in case of Google + * DataTable. + * + * @throws Error */ -TimeAxis.prototype.setRange = function (range) { - if (!(range instanceof Range) && (!range || !range.start || !range.end)) { - throw new TypeError('Range must be an instance of Range, ' + - 'or an object containing start and end.'); +DataSet.prototype.get = function (args) { + var me = this; + + // parse the arguments + var id, ids, options, data; + var firstType = util.getType(arguments[0]); + if (firstType == 'String' || firstType == 'Number') { + // get(id [, options] [, data]) + id = arguments[0]; + options = arguments[1]; + data = arguments[2]; + } + else if (firstType == 'Array') { + // get(ids [, options] [, data]) + ids = arguments[0]; + options = arguments[1]; + data = arguments[2]; + } + else { + // get([, options] [, data]) + options = arguments[0]; + data = arguments[1]; } - this.range = range; -}; -/** - * Convert a position on screen (pixels) to a datetime - * @param {int} x Position on the screen in pixels - * @return {Date} time The datetime the corresponds with given position x - */ -TimeAxis.prototype.toTime = function(x) { - var conversion = this.conversion; - return new Date(x / conversion.factor + conversion.offset); -}; + // determine the return type + var type; + if (options && options.type) { + type = (options.type == 'DataTable') ? 'DataTable' : 'Array'; -/** - * Convert a datetime (Date object) into a position on the screen - * @param {Date} time A date - * @return {int} x The position on the screen in pixels which corresponds - * with the given date. - * @private - */ -TimeAxis.prototype.toScreen = function(time) { - var conversion = this.conversion; - return (time.valueOf() - conversion.offset) * conversion.factor; -}; + if (data && (type != util.getType(data))) { + throw new Error('Type of parameter "data" (' + util.getType(data) + ') ' + + 'does not correspond with specified options.type (' + options.type + ')'); + } + if (type == 'DataTable' && !util.isDataTable(data)) { + throw new Error('Parameter "data" must be a DataTable ' + + 'when options.type is "DataTable"'); + } + } + else if (data) { + type = (util.getType(data) == 'DataTable') ? 'DataTable' : 'Array'; + } + else { + type = 'Array'; + } -/** - * Repaint the component - * @return {Boolean} changed - */ -TimeAxis.prototype.repaint = function () { - var changed = 0, - update = util.updateProperty, - asSize = util.option.asSize, - options = this.options, - orientation = this.getOption('orientation'), - props = this.props, - step = this.step; + // build options + var convert = options && options.convert || this.options.convert; + var filter = options && options.filter; + var items = [], item, itemId, i, len; - var frame = this.frame; - if (!frame) { - frame = document.createElement('div'); - this.frame = frame; - changed += 1; + // convert items + if (id != undefined) { + // return a single item + item = me._getItem(id, convert); + if (filter && !filter(item)) { + item = null; + } } - frame.className = 'axis ' + orientation; - // TODO: custom className? - - if (!frame.parentNode) { - if (!this.parent) { - throw new Error('Cannot repaint time axis: no parent attached'); + else if (ids != undefined) { + // return a subset of items + for (i = 0, len = ids.length; i < len; i++) { + item = me._getItem(ids[i], convert); + if (!filter || filter(item)) { + items.push(item); + } } - var parentContainer = this.parent.getContainer(); - if (!parentContainer) { - throw new Error('Cannot repaint time axis: parent has no container element'); + } + else { + // return all items + for (itemId in this.data) { + if (this.data.hasOwnProperty(itemId)) { + item = me._getItem(itemId, convert); + if (!filter || filter(item)) { + items.push(item); + } + } } - parentContainer.appendChild(frame); - - changed += 1; } - var parent = frame.parentNode; - if (parent) { - var beforeChild = frame.nextSibling; - parent.removeChild(frame); // take frame offline while updating (is almost twice as fast) - - var defaultTop = (orientation == 'bottom' && this.props.parentHeight && this.height) ? - (this.props.parentHeight - this.height) + 'px' : - '0px'; - changed += update(frame.style, 'top', asSize(options.top, defaultTop)); - changed += update(frame.style, 'left', asSize(options.left, '0px')); - changed += update(frame.style, 'width', asSize(options.width, '100%')); - changed += update(frame.style, 'height', asSize(options.height, this.height + 'px')); - - // get characters width and height - this._repaintMeasureChars(); + // order the results + if (options && options.order && id == undefined) { + this._sort(items, options.order); + } - if (this.step) { - this._repaintStart(); + // filter fields of the items + if (options && options.fields) { + var fields = options.fields; + if (id != undefined) { + item = this._filterFields(item, fields); + } + else { + for (i = 0, len = items.length; i < len; i++) { + items[i] = this._filterFields(items[i], fields); + } + } + } - step.first(); - var xFirstMajorLabel = undefined; - var max = 0; - while (step.hasNext() && max < 1000) { - max++; - var cur = step.getCurrent(), - x = this.toScreen(cur), - isMajor = step.isMajor(); + // return the results + if (type == 'DataTable') { + var columns = this._getColumnNames(data); + if (id != undefined) { + // append a single item to the data table + me._appendRow(data, columns, item); + } + else { + // copy the items to the provided data table + for (i = 0, len = items.length; i < len; i++) { + me._appendRow(data, columns, items[i]); + } + } + return data; + } + else { + // return an array + if (id != undefined) { + // a single item + return item; + } + else { + // multiple items + if (data) { + // copy the items to the provided array + for (i = 0, len = items.length; i < len; i++) { + data.push(items[i]); + } + return data; + } + else { + // just return our array + return items; + } + } + } +}; - // TODO: lines must have a width, such that we can create css backgrounds +/** + * Get ids of all items or from a filtered set of items. + * @param {Object} [options] An Object with options. Available options: + * {function} [filter] filter items + * {String | function} [order] Order the items by + * a field name or custom sort function. + * @return {Array} ids + */ +DataSet.prototype.getIds = function (options) { + var data = this.data, + filter = options && options.filter, + order = options && options.order, + convert = options && options.convert || this.options.convert, + i, + len, + id, + item, + items, + ids = []; - if (this.getOption('showMinorLabels')) { - this._repaintMinorText(x, step.getLabelMinor()); + if (filter) { + // get filtered items + if (order) { + // create ordered list + items = []; + for (id in data) { + if (data.hasOwnProperty(id)) { + item = this._getItem(id, convert); + if (filter(item)) { + items.push(item); + } } + } - if (isMajor && this.getOption('showMajorLabels')) { - if (x > 0) { - if (xFirstMajorLabel == undefined) { - xFirstMajorLabel = x; - } - this._repaintMajorText(x, step.getLabelMajor()); + this._sort(items, order); + + for (i = 0, len = items.length; i < len; i++) { + ids[i] = items[i][this.fieldId]; + } + } + else { + // create unordered list + for (id in data) { + if (data.hasOwnProperty(id)) { + item = this._getItem(id, convert); + if (filter(item)) { + ids.push(item[this.fieldId]); } - this._repaintMajorLine(x); } - else { - this._repaintMinorLine(x); + } + } + } + else { + // get all items + if (order) { + // create an ordered list + items = []; + for (id in data) { + if (data.hasOwnProperty(id)) { + items.push(data[id]); } + } - step.next(); + this._sort(items, order); + + for (i = 0, len = items.length; i < len; i++) { + ids[i] = items[i][this.fieldId]; + } + } + else { + // create unordered list + for (id in data) { + if (data.hasOwnProperty(id)) { + item = data[id]; + ids.push(item[this.fieldId]); + } } + } + } - // create a major label on the left when needed - if (this.getOption('showMajorLabels')) { - var leftTime = this.toTime(0), - leftText = step.getLabelMajor(leftTime), - widthText = leftText.length * (props.majorCharWidth || 10) + 10; // upper bound estimation + return ids; +}; - if (xFirstMajorLabel == undefined || widthText < xFirstMajorLabel) { - this._repaintMajorText(0, leftText); +/** + * Execute a callback function for every item in the dataset. + * The order of the items is not determined. + * @param {function} callback + * @param {Object} [options] Available options: + * {Object.} [convert] + * {String[]} [fields] filter fields + * {function} [filter] filter items + * {String | function} [order] Order the items by + * a field name or custom sort function. + */ +DataSet.prototype.forEach = function (callback, options) { + var filter = options && options.filter, + convert = options && options.convert || this.options.convert, + data = this.data, + item, + id; + + if (options && options.order) { + // execute forEach on ordered list + var items = this.get(options); + + for (var i = 0, len = items.length; i < len; i++) { + item = items[i]; + id = item[this.fieldId]; + callback(item, id); + } + } + else { + // unordered + for (id in data) { + if (data.hasOwnProperty(id)) { + item = this._getItem(id, convert); + if (!filter || filter(item)) { + callback(item, id); } } + } + } +}; + +/** + * Map every item in the dataset. + * @param {function} callback + * @param {Object} [options] Available options: + * {Object.} [convert] + * {String[]} [fields] filter fields + * {function} [filter] filter items + * {String | function} [order] Order the items by + * a field name or custom sort function. + * @return {Object[]} mappedItems + */ +DataSet.prototype.map = function (callback, options) { + var filter = options && options.filter, + convert = options && options.convert || this.options.convert, + mappedItems = [], + data = this.data, + item; - this._repaintEnd(); + // convert and filter items + for (var id in data) { + if (data.hasOwnProperty(id)) { + item = this._getItem(id, convert); + if (!filter || filter(item)) { + mappedItems.push(callback(item, id)); + } } + } - this._repaintLine(); - - // put frame online again - if (beforeChild) { - parent.insertBefore(frame, beforeChild); - } - else { - parent.appendChild(frame) - } + // order items + if (options && options.order) { + this._sort(mappedItems, options.order); } - return (changed > 0); + return mappedItems; }; /** - * Start a repaint. Move all DOM elements to a redundant list, where they - * can be picked for re-use, or can be cleaned up in the end + * Filter the fields of an item + * @param {Object} item + * @param {String[]} fields Field names + * @return {Object} filteredItem * @private */ -TimeAxis.prototype._repaintStart = function () { - var dom = this.dom, - redundant = dom.redundant; +DataSet.prototype._filterFields = function (item, fields) { + var filteredItem = {}; - redundant.majorLines = dom.majorLines; - redundant.majorTexts = dom.majorTexts; - redundant.minorLines = dom.minorLines; - redundant.minorTexts = dom.minorTexts; + for (var field in item) { + if (item.hasOwnProperty(field) && (fields.indexOf(field) != -1)) { + filteredItem[field] = item[field]; + } + } - dom.majorLines = []; - dom.majorTexts = []; - dom.minorLines = []; - dom.minorTexts = []; + return filteredItem; }; /** - * End a repaint. Cleanup leftover DOM elements in the redundant list + * Sort the provided array with items + * @param {Object[]} items + * @param {String | function} order A field name or custom sort function. * @private */ -TimeAxis.prototype._repaintEnd = function () { - util.forEach(this.dom.redundant, function (arr) { - while (arr.length) { - var elem = arr.pop(); - if (elem && elem.parentNode) { - elem.parentNode.removeChild(elem); +DataSet.prototype._sort = function (items, order) { + if (util.isString(order)) { + // order by provided field name + var name = order; // field name + items.sort(function (a, b) { + var av = a[name]; + var bv = b[name]; + return (av > bv) ? 1 : ((av < bv) ? -1 : 0); + }); + } + else if (typeof order === 'function') { + // order by sort function + items.sort(order); + } + // TODO: extend order by an Object {field:String, direction:String} + // where direction can be 'asc' or 'desc' + else { + throw new TypeError('Order must be a function or a string'); + } +}; + +/** + * Remove an object by pointer or by id + * @param {String | Number | Object | Array} id Object or id, or an array with + * objects or ids to be removed + * @param {String} [senderId] Optional sender id + * @return {Array} removedIds + */ +DataSet.prototype.remove = function (id, senderId) { + var removedIds = [], + i, len, removedId; + + if (id instanceof Array) { + for (i = 0, len = id.length; i < len; i++) { + removedId = this._remove(id[i]); + if (removedId != null) { + removedIds.push(removedId); } } - }); -}; + } + else { + removedId = this._remove(id); + if (removedId != null) { + removedIds.push(removedId); + } + } + + if (removedIds.length) { + this._trigger('remove', {items: removedIds}, senderId); + } + return removedIds; +}; /** - * Create a minor label for the axis at position x - * @param {Number} x - * @param {String} text + * Remove an item by its id + * @param {Number | String | Object} id id or item + * @returns {Number | String | null} id * @private */ -TimeAxis.prototype._repaintMinorText = function (x, text) { - // reuse redundant label - var label = this.dom.redundant.minorTexts.shift(); - - if (!label) { - // create new label - var content = document.createTextNode(''); - label = document.createElement('div'); - label.appendChild(content); - label.className = 'text minor'; - this.frame.appendChild(label); +DataSet.prototype._remove = function (id) { + if (util.isNumber(id) || util.isString(id)) { + if (this.data[id]) { + delete this.data[id]; + delete this.internalIds[id]; + return id; + } } - this.dom.minorTexts.push(label); + else if (id instanceof Object) { + var itemId = id[this.fieldId]; + if (itemId && this.data[itemId]) { + delete this.data[itemId]; + delete this.internalIds[itemId]; + return itemId; + } + } + return null; +}; - label.childNodes[0].nodeValue = text; - label.style.left = x + 'px'; - label.style.top = this.props.minorLabelTop + 'px'; - //label.title = title; // TODO: this is a heavy operation +/** + * Clear the data + * @param {String} [senderId] Optional sender id + * @return {Array} removedIds The ids of all removed items + */ +DataSet.prototype.clear = function (senderId) { + var ids = Object.keys(this.data); + + this.data = {}; + this.internalIds = {}; + + this._trigger('remove', {items: ids}, senderId); + + return ids; }; /** - * Create a Major label for the axis at position x - * @param {Number} x - * @param {String} text - * @private + * Find the item with maximum value of a specified field + * @param {String} field + * @return {Object | null} item Item containing max value, or null if no items */ -TimeAxis.prototype._repaintMajorText = function (x, text) { - // reuse redundant label - var label = this.dom.redundant.majorTexts.shift(); +DataSet.prototype.max = function (field) { + var data = this.data, + max = null, + maxField = null; - if (!label) { - // create label - var content = document.createTextNode(text); - label = document.createElement('div'); - label.className = 'text major'; - label.appendChild(content); - this.frame.appendChild(label); + for (var id in data) { + if (data.hasOwnProperty(id)) { + var item = data[id]; + var itemField = item[field]; + if (itemField != null && (!max || itemField > maxField)) { + max = item; + maxField = itemField; + } + } } - this.dom.majorTexts.push(label); - label.childNodes[0].nodeValue = text; - label.style.top = this.props.majorLabelTop + 'px'; - label.style.left = x + 'px'; - //label.title = title; // TODO: this is a heavy operation + return max; }; /** - * Create a minor line for the axis at position x - * @param {Number} x - * @private + * Find the item with minimum value of a specified field + * @param {String} field + * @return {Object | null} item Item containing max value, or null if no items */ -TimeAxis.prototype._repaintMinorLine = function (x) { - // reuse redundant line - var line = this.dom.redundant.minorLines.shift(); +DataSet.prototype.min = function (field) { + var data = this.data, + min = null, + minField = null; - if (!line) { - // create vertical line - line = document.createElement('div'); - line.className = 'grid vertical minor'; - this.frame.appendChild(line); + for (var id in data) { + if (data.hasOwnProperty(id)) { + var item = data[id]; + var itemField = item[field]; + if (itemField != null && (!min || itemField < minField)) { + min = item; + minField = itemField; + } + } } - this.dom.minorLines.push(line); - var props = this.props; - line.style.top = props.minorLineTop + 'px'; - line.style.height = props.minorLineHeight + 'px'; - line.style.left = (x - props.minorLineWidth / 2) + 'px'; + return min; }; /** - * Create a Major line for the axis at position x - * @param {Number} x - * @private + * Find all distinct values of a specified field + * @param {String} field + * @return {Array} values Array containing all distinct values. If the data + * items do not contain the specified field, an array + * containing a single value undefined is returned. + * The returned array is unordered. */ -TimeAxis.prototype._repaintMajorLine = function (x) { - // reuse redundant line - var line = this.dom.redundant.majorLines.shift(); - - if (!line) { - // create vertical line - line = document.createElement('DIV'); - line.className = 'grid vertical major'; - this.frame.appendChild(line); +DataSet.prototype.distinct = function (field) { + var data = this.data, + values = [], + fieldType = this.options.convert[field], + count = 0; + + for (var prop in data) { + if (data.hasOwnProperty(prop)) { + var item = data[prop]; + var value = util.convert(item[field], fieldType); + var exists = false; + for (var i = 0; i < count; i++) { + if (values[i] == value) { + exists = true; + break; + } + } + if (!exists) { + values[count] = value; + count++; + } + } } - this.dom.majorLines.push(line); - var props = this.props; - line.style.top = props.majorLineTop + 'px'; - line.style.left = (x - props.majorLineWidth / 2) + 'px'; - line.style.height = props.majorLineHeight + 'px'; + return values; }; - /** - * Repaint the horizontal line for the axis + * Add a single item. Will fail when an item with the same id already exists. + * @param {Object} item + * @return {String} id * @private */ -TimeAxis.prototype._repaintLine = function() { - var line = this.dom.line, - frame = this.frame, - options = this.options; +DataSet.prototype._addItem = function (item) { + var id = item[this.fieldId]; - // line before all axis elements - if (this.getOption('showMinorLabels') || this.getOption('showMajorLabels')) { - if (line) { - // put this line at the end of all childs - frame.removeChild(line); - frame.appendChild(line); - } - else { - // create the axis line - line = document.createElement('div'); - line.className = 'grid horizontal major'; - frame.appendChild(line); - this.dom.line = line; + if (id != undefined) { + // check whether this id is already taken + if (this.data[id]) { + // item already exists + throw new Error('Cannot add item: item with id ' + id + ' already exists'); } - - line.style.top = this.props.lineTop + 'px'; } else { - if (line && axis.parentElement) { - frame.removeChild(axis.line); - delete this.dom.line; + // generate an id + id = util.randomUUID(); + item[this.fieldId] = id; + this.internalIds[id] = item; + } + + var d = {}; + for (var field in item) { + if (item.hasOwnProperty(field)) { + var fieldType = this.convert[field]; // type may be undefined + d[field] = util.convert(item[field], fieldType); } } + this.data[id] = d; + + return id; }; /** - * Create characters used to determine the size of text on the axis + * Get an item. Fields can be converted to a specific type + * @param {String} id + * @param {Object.} [convert] field types to convert + * @return {Object | null} item * @private */ -TimeAxis.prototype._repaintMeasureChars = function () { - // calculate the width and height of a single character - // this is used to calculate the step size, and also the positioning of the - // axis - var dom = this.dom, - text; - - if (!dom.measureCharMinor) { - text = document.createTextNode('0'); - var measureCharMinor = document.createElement('DIV'); - measureCharMinor.className = 'text minor measure'; - measureCharMinor.appendChild(text); - this.frame.appendChild(measureCharMinor); +DataSet.prototype._getItem = function (id, convert) { + var field, value; - dom.measureCharMinor = measureCharMinor; + // get the item from the dataset + var raw = this.data[id]; + if (!raw) { + return null; } - if (!dom.measureCharMajor) { - text = document.createTextNode('0'); - var measureCharMajor = document.createElement('DIV'); - measureCharMajor.className = 'text major measure'; - measureCharMajor.appendChild(text); - this.frame.appendChild(measureCharMajor); - - dom.measureCharMajor = measureCharMajor; + // convert the items field types + var converted = {}, + fieldId = this.fieldId, + internalIds = this.internalIds; + if (convert) { + for (field in raw) { + if (raw.hasOwnProperty(field)) { + value = raw[field]; + // output all fields, except internal ids + if ((field != fieldId) || !(value in internalIds)) { + converted[field] = util.convert(value, convert[field]); + } + } + } + } + else { + // no field types specified, no converting needed + for (field in raw) { + if (raw.hasOwnProperty(field)) { + value = raw[field]; + // output all fields, except internal ids + if ((field != fieldId) || !(value in internalIds)) { + converted[field] = value; + } + } + } } + + return converted; }; /** - * Reflow the component - * @return {Boolean} resized + * Update a single item: merge with existing item. + * Will fail when the item has no id, or when there does not exist an item + * with the same id. + * @param {Object} item + * @return {String} id + * @private */ -TimeAxis.prototype.reflow = function () { - var changed = 0, - update = util.updateProperty, - frame = this.frame, - range = this.range; - - if (!range) { - throw new Error('Cannot repaint time axis: no range configured'); +DataSet.prototype._updateItem = function (item) { + var id = item[this.fieldId]; + if (id == undefined) { + throw new Error('Cannot update item: item has no id (item: ' + JSON.stringify(item) + ')'); + } + var d = this.data[id]; + if (!d) { + // item doesn't exist + throw new Error('Cannot update item: no item with id ' + id + ' found'); } - if (frame) { - changed += update(this, 'top', frame.offsetTop); - changed += update(this, 'left', frame.offsetLeft); - - // calculate size of a character - var props = this.props, - showMinorLabels = this.getOption('showMinorLabels'), - showMajorLabels = this.getOption('showMajorLabels'), - measureCharMinor = this.dom.measureCharMinor, - measureCharMajor = this.dom.measureCharMajor; - if (measureCharMinor) { - props.minorCharHeight = measureCharMinor.clientHeight; - props.minorCharWidth = measureCharMinor.clientWidth; - } - if (measureCharMajor) { - props.majorCharHeight = measureCharMajor.clientHeight; - props.majorCharWidth = measureCharMajor.clientWidth; - } - - var parentHeight = frame.parentNode ? frame.parentNode.offsetHeight : 0; - if (parentHeight != props.parentHeight) { - props.parentHeight = parentHeight; - changed += 1; - } - switch (this.getOption('orientation')) { - case 'bottom': - props.minorLabelHeight = showMinorLabels ? props.minorCharHeight : 0; - props.majorLabelHeight = showMajorLabels ? props.majorCharHeight : 0; - - props.minorLabelTop = 0; - props.majorLabelTop = props.minorLabelTop + props.minorLabelHeight; - - props.minorLineTop = -this.top; - props.minorLineHeight = Math.max(this.top + props.majorLabelHeight, 0); - props.minorLineWidth = 1; // TODO: really calculate width - - props.majorLineTop = -this.top; - props.majorLineHeight = Math.max(this.top + props.minorLabelHeight + props.majorLabelHeight, 0); - props.majorLineWidth = 1; // TODO: really calculate width - - props.lineTop = 0; - - break; - - case 'top': - props.minorLabelHeight = showMinorLabels ? props.minorCharHeight : 0; - props.majorLabelHeight = showMajorLabels ? props.majorCharHeight : 0; - - props.majorLabelTop = 0; - props.minorLabelTop = props.majorLabelTop + props.majorLabelHeight; - - props.minorLineTop = props.minorLabelTop; - props.minorLineHeight = Math.max(parentHeight - props.majorLabelHeight - this.top); - props.minorLineWidth = 1; // TODO: really calculate width - - props.majorLineTop = 0; - props.majorLineHeight = Math.max(parentHeight - this.top); - props.majorLineWidth = 1; // TODO: really calculate width - - props.lineTop = props.majorLabelHeight + props.minorLabelHeight; - - break; - - default: - throw new Error('Unkown orientation "' + this.getOption('orientation') + '"'); + // merge with current item + for (var field in item) { + if (item.hasOwnProperty(field)) { + var fieldType = this.convert[field]; // type may be undefined + d[field] = util.convert(item[field], fieldType); } + } - var height = props.minorLabelHeight + props.majorLabelHeight; - changed += update(this, 'width', frame.offsetWidth); - changed += update(this, 'height', height); - - // calculate range and step - this._updateConversion(); + return id; +}; - var start = util.convert(range.start, 'Date'), - end = util.convert(range.end, 'Date'), - minimumStep = this.toTime((props.minorCharWidth || 10) * 5) - this.toTime(0); - this.step = new TimeStep(start, end, minimumStep); - changed += update(props.range, 'start', start.valueOf()); - changed += update(props.range, 'end', end.valueOf()); - changed += update(props.range, 'minimumStep', minimumStep.valueOf()); +/** + * Get an array with the column names of a Google DataTable + * @param {DataTable} dataTable + * @return {String[]} columnNames + * @private + */ +DataSet.prototype._getColumnNames = function (dataTable) { + var columns = []; + for (var col = 0, cols = dataTable.getNumberOfColumns(); col < cols; col++) { + columns[col] = dataTable.getColumnId(col) || dataTable.getColumnLabel(col); } - - return (changed > 0); + return columns; }; /** - * Calculate the factor and offset to convert a position on screen to the - * corresponding date and vice versa. - * After the method _updateConversion is executed once, the methods toTime - * and toScreen can be used. + * Append an item as a row to the dataTable + * @param dataTable + * @param columns + * @param item * @private */ -TimeAxis.prototype._updateConversion = function() { - var range = this.range; - if (!range) { - throw new Error('No range configured'); - } +DataSet.prototype._appendRow = function (dataTable, columns, item) { + var row = dataTable.addRow(); - if (range.conversion) { - this.conversion = range.conversion(this.width); - } - else { - this.conversion = Range.conversion(range.start, range.end, this.width); + for (var col = 0, cols = columns.length; col < cols; col++) { + var field = columns[col]; + dataTable.setValue(row, col, item[field]); } }; /** - * An ItemSet holds a set of items and ranges which can be displayed in a - * range. The width is determined by the parent of the ItemSet, and the height - * is determined by the size of the items. - * @param {Component} parent - * @param {Component[]} [depends] Components on which this components depends - * (except for the parent) - * @param {Object} [options] See ItemSet.setOptions for the available - * options. - * @constructor ItemSet - * @extends Panel + * DataView + * + * a dataview offers a filtered view on a dataset or an other dataview. + * + * @param {DataSet | DataView} data + * @param {Object} [options] Available options: see method get + * + * @constructor DataView */ -// TODO: improve performance by replacing all Array.forEach with a for loop -function ItemSet(parent, depends, options) { +function DataView (data, options) { this.id = util.randomUUID(); - this.parent = parent; - this.depends = depends; - // one options object is shared by this itemset and all its items + this.data = null; + this.ids = {}; // ids of the items currently in memory (just contains a boolean true) this.options = options || {}; - this.defaultOptions = { - type: 'box', - align: 'center', - orientation: 'bottom', - margin: { - axis: 20, - item: 10 - }, - padding: 5 - }; - - this.dom = {}; + this.fieldId = 'id'; // name of the field containing id + this.subscribers = {}; // event subscribers var me = this; - this.itemsData = null; // DataSet - this.range = null; // Range or Object {start: number, end: number} - - this.listeners = { - 'add': function (event, params, senderId) { - if (senderId != me.id) { - me._onAdd(params.items); - } - }, - 'update': function (event, params, senderId) { - if (senderId != me.id) { - me._onUpdate(params.items); - } - }, - 'remove': function (event, params, senderId) { - if (senderId != me.id) { - me._onRemove(params.items); - } - } + this.listener = function () { + me._onEvent.apply(me, arguments); }; - this.items = {}; // object with an Item for every data item - this.queue = {}; // queue with id/actions: 'add', 'update', 'delete' - this.stack = new Stack(this, Object.create(this.options)); - this.conversion = null; - - // TODO: ItemSet should also attach event listeners for rangechange and rangechanged, like timeaxis + this.setData(data); } -ItemSet.prototype = new Panel(); - -// available item types will be registered here -ItemSet.types = { - box: ItemBox, - range: ItemRange, - point: ItemPoint -}; - /** - * Set options for the ItemSet. Existing options will be extended/overwritten. - * @param {Object} [options] The following options are available: - * {String | function} [className] - * class name for the itemset - * {String} [type] - * Default type for the items. Choose from 'box' - * (default), 'point', or 'range'. The default - * Style can be overwritten by individual items. - * {String} align - * Alignment for the items, only applicable for - * ItemBox. Choose 'center' (default), 'left', or - * 'right'. - * {String} orientation - * Orientation of the item set. Choose 'top' or - * 'bottom' (default). - * {Number} margin.axis - * Margin between the axis and the items in pixels. - * Default is 20. - * {Number} margin.item - * Margin between items in pixels. Default is 10. - * {Number} padding - * Padding of the contents of an item in pixels. - * Must correspond with the items css. Default is 5. + * Set a data source for the view + * @param {DataSet | DataView} data */ -ItemSet.prototype.setOptions = Component.prototype.setOptions; +DataView.prototype.setData = function (data) { + var ids, dataItems, i, len; -/** - * Set range (start and end). - * @param {Range | Object} range A Range or an object containing start and end. - */ -ItemSet.prototype.setRange = function setRange(range) { - if (!(range instanceof Range) && (!range || !range.start || !range.end)) { - throw new TypeError('Range must be an instance of Range, ' + - 'or an object containing start and end.'); + if (this.data) { + // unsubscribe from current dataset + if (this.data.unsubscribe) { + this.data.unsubscribe('*', this.listener); + } + + // trigger a remove of all items in memory + ids = []; + for (var id in this.ids) { + if (this.ids.hasOwnProperty(id)) { + ids.push(id); + } + } + this.ids = {}; + this._trigger('remove', {items: ids}); } - this.range = range; -}; -/** - * Repaint the component - * @return {Boolean} changed - */ -ItemSet.prototype.repaint = function repaint() { - var changed = 0, - update = util.updateProperty, - asSize = util.option.asSize, - options = this.options, - orientation = this.getOption('orientation'), - defaultOptions = this.defaultOptions, - frame = this.frame; + this.data = data; - if (!frame) { - frame = document.createElement('div'); - frame.className = 'itemset'; + if (this.data) { + // update fieldId + this.fieldId = this.options.fieldId || + (this.data && this.data.options && this.data.options.fieldId) || + 'id'; - var className = options.className; - if (className) { - util.addClassName(frame, util.option.asString(className)); + // trigger an add of all added items + ids = this.data.getIds({filter: this.options && this.options.filter}); + for (i = 0, len = ids.length; i < len; i++) { + id = ids[i]; + this.ids[id] = true; } + this._trigger('add', {items: ids}); - // create background panel - var background = document.createElement('div'); - background.className = 'background'; - frame.appendChild(background); - this.dom.background = background; - - // create foreground panel - var foreground = document.createElement('div'); - foreground.className = 'foreground'; - frame.appendChild(foreground); - this.dom.foreground = foreground; + // subscribe to new dataset + if (this.data.subscribe) { + this.data.subscribe('*', this.listener); + } + } +}; - // create axis panel - var axis = document.createElement('div'); - axis.className = 'itemset-axis'; - //frame.appendChild(axis); - this.dom.axis = axis; +/** + * Get data from the data view + * + * Usage: + * + * get() + * get(options: Object) + * get(options: Object, data: Array | DataTable) + * + * get(id: Number) + * get(id: Number, options: Object) + * get(id: Number, options: Object, data: Array | DataTable) + * + * get(ids: Number[]) + * get(ids: Number[], options: Object) + * get(ids: Number[], options: Object, data: Array | DataTable) + * + * Where: + * + * {Number | String} id The id of an item + * {Number[] | String{}} ids An array with ids of items + * {Object} options An Object with options. Available options: + * {String} [type] Type of data to be returned. Can + * be 'DataTable' or 'Array' (default) + * {Object.} [convert] + * {String[]} [fields] field names to be returned + * {function} [filter] filter items + * {String | function} [order] Order the items by + * a field name or custom sort function. + * {Array | DataTable} [data] If provided, items will be appended to this + * array or table. Required in case of Google + * DataTable. + * @param args + */ +DataView.prototype.get = function (args) { + var me = this; - this.frame = frame; - changed += 1; + // parse the arguments + var ids, options, data; + var firstType = util.getType(arguments[0]); + if (firstType == 'String' || firstType == 'Number' || firstType == 'Array') { + // get(id(s) [, options] [, data]) + ids = arguments[0]; // can be a single id or an array with ids + options = arguments[1]; + data = arguments[2]; + } + else { + // get([, options] [, data]) + options = arguments[0]; + data = arguments[1]; } - if (!this.parent) { - throw new Error('Cannot repaint itemset: no parent attached'); - } - var parentContainer = this.parent.getContainer(); - if (!parentContainer) { - throw new Error('Cannot repaint itemset: parent has no container element'); - } - if (!frame.parentNode) { - parentContainer.appendChild(frame); - changed += 1; + // extend the options with the default options and provided options + var viewOptions = util.extend({}, this.options, options); + + // create a combined filter method when needed + if (this.options.filter && options && options.filter) { + viewOptions.filter = function (item) { + return me.options.filter(item) && options.filter(item); + } } - if (!this.dom.axis.parentNode) { - parentContainer.appendChild(this.dom.axis); - changed += 1; + + // build up the call to the linked data set + var getArguments = []; + if (ids != undefined) { + getArguments.push(ids); } + getArguments.push(viewOptions); + getArguments.push(data); - // reposition frame - changed += update(frame.style, 'left', asSize(options.left, '0px')); - changed += update(frame.style, 'top', asSize(options.top, '0px')); - changed += update(frame.style, 'width', asSize(options.width, '100%')); - changed += update(frame.style, 'height', asSize(options.height, this.height + 'px')); + return this.data && this.data.get.apply(this.data, getArguments); +}; - // reposition axis - changed += update(this.dom.axis.style, 'left', asSize(options.left, '0px')); - changed += update(this.dom.axis.style, 'width', asSize(options.width, '100%')); - if (orientation == 'bottom') { - changed += update(this.dom.axis.style, 'top', (this.height + this.top) + 'px'); +/** + * Get ids of all items or from a filtered set of items. + * @param {Object} [options] An Object with options. Available options: + * {function} [filter] filter items + * {String | function} [order] Order the items by + * a field name or custom sort function. + * @return {Array} ids + */ +DataView.prototype.getIds = function (options) { + var ids; + + if (this.data) { + var defaultFilter = this.options.filter; + var filter; + + if (options && options.filter) { + if (defaultFilter) { + filter = function (item) { + return defaultFilter(item) && options.filter(item); + } + } + else { + filter = options.filter; + } + } + else { + filter = defaultFilter; + } + + ids = this.data.getIds({ + filter: filter, + order: options && options.order + }); } - else { // orientation == 'top' - changed += update(this.dom.axis.style, 'top', this.top + 'px'); + else { + ids = []; } - this._updateConversion(); + return ids; +}; - var me = this, - queue = this.queue, - itemsData = this.itemsData, - items = this.items, - dataOptions = { - // TODO: cleanup - // fields: [(itemsData && itemsData.fieldId || 'id'), 'start', 'end', 'content', 'type', 'className'] - }; +/** + * Event listener. Will propagate all events from the connected data set to + * the subscribers of the DataView, but will filter the items and only trigger + * when there are changes in the filtered data set. + * @param {String} event + * @param {Object | null} params + * @param {String} senderId + * @private + */ +DataView.prototype._onEvent = function (event, params, senderId) { + var i, len, id, item, + ids = params && params.items, + data = this.data, + added = [], + updated = [], + removed = []; - // show/hide added/changed/removed items - Object.keys(queue).forEach(function (id) { - //var entry = queue[id]; - var action = queue[id]; - var item = items[id]; - //var item = entry.item; - //noinspection FallthroughInSwitchStatementJS - switch (action) { + if (ids && data) { + switch (event) { case 'add': - case 'update': - var itemData = itemsData && itemsData.get(id, dataOptions); + // filter the ids of the added items + for (i = 0, len = ids.length; i < len; i++) { + id = ids[i]; + item = this.get(id); + if (item) { + this.ids[id] = true; + added.push(id); + } + } - if (itemData) { - var type = itemData.type || - (itemData.start && itemData.end && 'range') || - options.type || - 'box'; - var constructor = ItemSet.types[type]; + break; + + case 'update': + // determine the event from the views viewpoint: an updated + // item can be added, updated, or removed from this view. + for (i = 0, len = ids.length; i < len; i++) { + id = ids[i]; + item = this.get(id); - // TODO: how to handle items with invalid data? hide them and give a warning? or throw an error? if (item) { - // update item - if (!constructor || !(item instanceof constructor)) { - // item type has changed, hide and delete the item - changed += item.hide(); - item = null; + if (this.ids[id]) { + updated.push(id); } else { - item.data = itemData; // TODO: create a method item.setData ? - changed++; + this.ids[id] = true; + added.push(id); } } - - if (!item) { - // create item - if (constructor) { - item = new constructor(me, itemData, options, defaultOptions); - changed++; + else { + if (this.ids[id]) { + delete this.ids[id]; + removed.push(id); } else { - throw new TypeError('Unknown item type "' + type + '"'); + // nothing interesting for me :-( } } - - // force a repaint (not only a reposition) - item.repaint(); - - items[id] = item; } - // update queue - delete queue[id]; break; case 'remove': - if (item) { - // remove DOM of the item - changed += item.hide(); + // filter the ids of the removed items + for (i = 0, len = ids.length; i < len; i++) { + id = ids[i]; + if (this.ids[id]) { + delete this.ids[id]; + removed.push(id); + } } - // update lists - delete items[id]; - delete queue[id]; break; - - default: - console.log('Error: unknown action "' + action + '"'); } - }); - // reposition all items. Show items only when in the visible area - util.forEach(this.items, function (item) { - if (item.visible) { - changed += item.show(); - item.reposition(); + if (added.length) { + this._trigger('add', {items: added}, senderId); } - else { - changed += item.hide(); + if (updated.length) { + this._trigger('update', {items: updated}, senderId); } - }); + if (removed.length) { + this._trigger('remove', {items: removed}, senderId); + } + } +}; - return (changed > 0); +// copy subscription functionality from DataSet +DataView.prototype.subscribe = DataSet.prototype.subscribe; +DataView.prototype.unsubscribe = DataSet.prototype.unsubscribe; +DataView.prototype._trigger = DataSet.prototype._trigger; + +/** + * @constructor TimeStep + * The class TimeStep is an iterator for dates. You provide a start date and an + * end date. The class itself determines the best scale (step size) based on the + * provided start Date, end Date, and minimumStep. + * + * If minimumStep is provided, the step size is chosen as close as possible + * to the minimumStep but larger than minimumStep. If minimumStep is not + * provided, the scale is set to 1 DAY. + * The minimumStep should correspond with the onscreen size of about 6 characters + * + * Alternatively, you can set a scale by hand. + * After creation, you can initialize the class by executing first(). Then you + * can iterate from the start date to the end date via next(). You can check if + * the end date is reached with the function hasNext(). After each step, you can + * retrieve the current date via getCurrent(). + * The TimeStep has scales ranging from milliseconds, seconds, minutes, hours, + * days, to years. + * + * Version: 1.2 + * + * @param {Date} [start] The start date, for example new Date(2010, 9, 21) + * or new Date(2010, 9, 21, 23, 45, 00) + * @param {Date} [end] The end date + * @param {Number} [minimumStep] Optional. Minimum step size in milliseconds + */ +TimeStep = function(start, end, minimumStep) { + // variables + this.current = new Date(); + this._start = new Date(); + this._end = new Date(); + + this.autoScale = true; + this.scale = TimeStep.SCALE.DAY; + this.step = 1; + + // initialize the range + this.setRange(start, end, minimumStep); +}; + +/// enum scale +TimeStep.SCALE = { + MILLISECOND: 1, + SECOND: 2, + MINUTE: 3, + HOUR: 4, + DAY: 5, + WEEKDAY: 6, + MONTH: 7, + YEAR: 8 }; -/** - * Get the foreground container element - * @return {HTMLElement} foreground - */ -ItemSet.prototype.getForeground = function getForeground() { - return this.dom.foreground; -}; /** - * Get the background container element - * @return {HTMLElement} background + * Set a new range + * If minimumStep is provided, the step size is chosen as close as possible + * to the minimumStep but larger than minimumStep. If minimumStep is not + * provided, the scale is set to 1 DAY. + * The minimumStep should correspond with the onscreen size of about 6 characters + * @param {Date} [start] The start date and time. + * @param {Date} [end] The end date and time. + * @param {int} [minimumStep] Optional. Minimum step size in milliseconds */ -ItemSet.prototype.getBackground = function getBackground() { - return this.dom.background; +TimeStep.prototype.setRange = function(start, end, minimumStep) { + if (!(start instanceof Date) || !(end instanceof Date)) { + //throw "No legal start or end date in method setRange"; + return; + } + + this._start = (start != undefined) ? new Date(start.valueOf()) : new Date(); + this._end = (end != undefined) ? new Date(end.valueOf()) : new Date(); + + if (this.autoScale) { + this.setMinimumStep(minimumStep); + } }; /** - * Get the axis container element - * @return {HTMLElement} axis + * Set the range iterator to the start date. */ -ItemSet.prototype.getAxis = function getAxis() { - return this.dom.axis; +TimeStep.prototype.first = function() { + this.current = new Date(this._start.valueOf()); + this.roundToMinor(); }; /** - * Reflow the component - * @return {Boolean} resized + * Round the current date to the first minor date value + * This must be executed once when the current date is set to start Date */ -ItemSet.prototype.reflow = function reflow () { - var changed = 0, - options = this.options, - marginAxis = options.margin && options.margin.axis || this.defaultOptions.margin.axis, - marginItem = options.margin && options.margin.item || this.defaultOptions.margin.item, - update = util.updateProperty, - asNumber = util.option.asNumber, - asSize = util.option.asSize, - frame = this.frame; - - if (frame) { - this._updateConversion(); - - util.forEach(this.items, function (item) { - changed += item.reflow(); - }); - - // TODO: stack.update should be triggered via an event, in stack itself - // TODO: only update the stack when there are changed items - this.stack.update(); +TimeStep.prototype.roundToMinor = function() { + // round to floor + // IMPORTANT: we have no breaks in this switch! (this is no bug) + //noinspection FallthroughInSwitchStatementJS + switch (this.scale) { + case TimeStep.SCALE.YEAR: + this.current.setFullYear(this.step * Math.floor(this.current.getFullYear() / this.step)); + this.current.setMonth(0); + case TimeStep.SCALE.MONTH: this.current.setDate(1); + case TimeStep.SCALE.DAY: // intentional fall through + case TimeStep.SCALE.WEEKDAY: this.current.setHours(0); + case TimeStep.SCALE.HOUR: this.current.setMinutes(0); + case TimeStep.SCALE.MINUTE: this.current.setSeconds(0); + case TimeStep.SCALE.SECOND: this.current.setMilliseconds(0); + //case TimeStep.SCALE.MILLISECOND: // nothing to do for milliseconds + } - var maxHeight = asNumber(options.maxHeight); - var fixedHeight = (asSize(options.height) != null); - var height; - if (fixedHeight) { - height = frame.offsetHeight; - } - else { - // height is not specified, determine the height from the height and positioned items - var visibleItems = this.stack.ordered; // TODO: not so nice way to get the filtered items - if (visibleItems.length) { - var min = visibleItems[0].top; - var max = visibleItems[0].top + visibleItems[0].height; - util.forEach(visibleItems, function (item) { - min = Math.min(min, item.top); - max = Math.max(max, (item.top + item.height)); - }); - height = (max - min) + marginAxis + marginItem; - } - else { - height = marginAxis + marginItem; - } - } - if (maxHeight != null) { - height = Math.min(height, maxHeight); + if (this.step != 1) { + // round down to the first minor value that is a multiple of the current step size + switch (this.scale) { + case TimeStep.SCALE.MILLISECOND: this.current.setMilliseconds(this.current.getMilliseconds() - this.current.getMilliseconds() % this.step); break; + case TimeStep.SCALE.SECOND: this.current.setSeconds(this.current.getSeconds() - this.current.getSeconds() % this.step); break; + case TimeStep.SCALE.MINUTE: this.current.setMinutes(this.current.getMinutes() - this.current.getMinutes() % this.step); break; + case TimeStep.SCALE.HOUR: this.current.setHours(this.current.getHours() - this.current.getHours() % this.step); break; + case TimeStep.SCALE.WEEKDAY: // intentional fall through + case TimeStep.SCALE.DAY: this.current.setDate((this.current.getDate()-1) - (this.current.getDate()-1) % this.step + 1); break; + case TimeStep.SCALE.MONTH: this.current.setMonth(this.current.getMonth() - this.current.getMonth() % this.step); break; + case TimeStep.SCALE.YEAR: this.current.setFullYear(this.current.getFullYear() - this.current.getFullYear() % this.step); break; + default: break; } - changed += update(this, 'height', height); - - // calculate height from items - changed += update(this, 'top', frame.offsetTop); - changed += update(this, 'left', frame.offsetLeft); - changed += update(this, 'width', frame.offsetWidth); - } - else { - changed += 1; } - - return (changed > 0); }; /** - * Hide this component from the DOM - * @return {Boolean} changed + * Check if the there is a next step + * @return {boolean} true if the current date has not passed the end date */ -ItemSet.prototype.hide = function hide() { - var changed = false; - - // remove the DOM - if (this.frame && this.frame.parentNode) { - this.frame.parentNode.removeChild(this.frame); - changed = true; - } - if (this.dom.axis && this.dom.axis.parentNode) { - this.dom.axis.parentNode.removeChild(this.dom.axis); - changed = true; - } - - return changed; +TimeStep.prototype.hasNext = function () { + return (this.current.valueOf() <= this._end.valueOf()); }; /** - * Set items - * @param {vis.DataSet | null} items + * Do the next step */ -ItemSet.prototype.setItems = function setItems(items) { - var me = this, - ids, - oldItemsData = this.itemsData; +TimeStep.prototype.next = function() { + var prev = this.current.valueOf(); - // replace the dataset - if (!items) { - this.itemsData = null; - } - else if (items instanceof DataSet || items instanceof DataView) { - this.itemsData = items; + // Two cases, needed to prevent issues with switching daylight savings + // (end of March and end of October) + if (this.current.getMonth() < 6) { + switch (this.scale) { + case TimeStep.SCALE.MILLISECOND: + + this.current = new Date(this.current.valueOf() + this.step); break; + case TimeStep.SCALE.SECOND: this.current = new Date(this.current.valueOf() + this.step * 1000); break; + case TimeStep.SCALE.MINUTE: this.current = new Date(this.current.valueOf() + this.step * 1000 * 60); break; + case TimeStep.SCALE.HOUR: + this.current = new Date(this.current.valueOf() + this.step * 1000 * 60 * 60); + // in case of skipping an hour for daylight savings, adjust the hour again (else you get: 0h 5h 9h ... instead of 0h 4h 8h ...) + var h = this.current.getHours(); + this.current.setHours(h - (h % this.step)); + break; + case TimeStep.SCALE.WEEKDAY: // intentional fall through + case TimeStep.SCALE.DAY: this.current.setDate(this.current.getDate() + this.step); break; + case TimeStep.SCALE.MONTH: this.current.setMonth(this.current.getMonth() + this.step); break; + case TimeStep.SCALE.YEAR: this.current.setFullYear(this.current.getFullYear() + this.step); break; + default: break; + } } else { - throw new TypeError('Data must be an instance of DataSet'); + switch (this.scale) { + case TimeStep.SCALE.MILLISECOND: this.current = new Date(this.current.valueOf() + this.step); break; + case TimeStep.SCALE.SECOND: this.current.setSeconds(this.current.getSeconds() + this.step); break; + case TimeStep.SCALE.MINUTE: this.current.setMinutes(this.current.getMinutes() + this.step); break; + case TimeStep.SCALE.HOUR: this.current.setHours(this.current.getHours() + this.step); break; + case TimeStep.SCALE.WEEKDAY: // intentional fall through + case TimeStep.SCALE.DAY: this.current.setDate(this.current.getDate() + this.step); break; + case TimeStep.SCALE.MONTH: this.current.setMonth(this.current.getMonth() + this.step); break; + case TimeStep.SCALE.YEAR: this.current.setFullYear(this.current.getFullYear() + this.step); break; + default: break; + } } - if (oldItemsData) { - // unsubscribe from old dataset - util.forEach(this.listeners, function (callback, event) { - oldItemsData.unsubscribe(event, callback); - }); + if (this.step != 1) { + // round down to the correct major value + switch (this.scale) { + case TimeStep.SCALE.MILLISECOND: if(this.current.getMilliseconds() < this.step) this.current.setMilliseconds(0); break; + case TimeStep.SCALE.SECOND: if(this.current.getSeconds() < this.step) this.current.setSeconds(0); break; + case TimeStep.SCALE.MINUTE: if(this.current.getMinutes() < this.step) this.current.setMinutes(0); break; + case TimeStep.SCALE.HOUR: if(this.current.getHours() < this.step) this.current.setHours(0); break; + case TimeStep.SCALE.WEEKDAY: // intentional fall through + case TimeStep.SCALE.DAY: if(this.current.getDate() < this.step+1) this.current.setDate(1); break; + case TimeStep.SCALE.MONTH: if(this.current.getMonth() < this.step) this.current.setMonth(0); break; + case TimeStep.SCALE.YEAR: break; // nothing to do for year + default: break; + } + } - // remove all drawn items - ids = oldItemsData.getIds(); - this._onRemove(ids); + // safety mechanism: if current time is still unchanged, move to the end + if (this.current.valueOf() == prev) { + this.current = new Date(this._end.valueOf()); } +}; - if (this.itemsData) { - // subscribe to new dataset - var id = this.id; - util.forEach(this.listeners, function (callback, event) { - me.itemsData.subscribe(event, callback, id); - }); - // draw all new items - ids = this.itemsData.getIds(); - this._onAdd(ids); +/** + * Get the current datetime + * @return {Date} current The current date + */ +TimeStep.prototype.getCurrent = function() { + return this.current; +}; + +/** + * Set a custom scale. Autoscaling will be disabled. + * For example setScale(SCALE.MINUTES, 5) will result + * in minor steps of 5 minutes, and major steps of an hour. + * + * @param {TimeStep.SCALE} newScale + * A scale. Choose from SCALE.MILLISECOND, + * SCALE.SECOND, SCALE.MINUTE, SCALE.HOUR, + * SCALE.WEEKDAY, SCALE.DAY, SCALE.MONTH, + * SCALE.YEAR. + * @param {Number} newStep A step size, by default 1. Choose for + * example 1, 2, 5, or 10. + */ +TimeStep.prototype.setScale = function(newScale, newStep) { + this.scale = newScale; + + if (newStep > 0) { + this.step = newStep; } -}; -/** - * Get the current items items - * @returns {vis.DataSet | null} - */ -ItemSet.prototype.getItems = function getItems() { - return this.itemsData; + this.autoScale = false; }; /** - * Handle updated items - * @param {Number[]} ids - * @private + * Enable or disable autoscaling + * @param {boolean} enable If true, autoascaling is set true */ -ItemSet.prototype._onUpdate = function _onUpdate(ids) { - this._toQueue('update', ids); +TimeStep.prototype.setAutoScale = function (enable) { + this.autoScale = enable; }; + /** - * Handle changed items - * @param {Number[]} ids - * @private + * Automatically determine the scale that bests fits the provided minimum step + * @param {Number} [minimumStep] The minimum step size in milliseconds */ -ItemSet.prototype._onAdd = function _onAdd(ids) { - this._toQueue('add', ids); +TimeStep.prototype.setMinimumStep = function(minimumStep) { + if (minimumStep == undefined) { + return; + } + + var stepYear = (1000 * 60 * 60 * 24 * 30 * 12); + var stepMonth = (1000 * 60 * 60 * 24 * 30); + var stepDay = (1000 * 60 * 60 * 24); + var stepHour = (1000 * 60 * 60); + var stepMinute = (1000 * 60); + var stepSecond = (1000); + var stepMillisecond= (1); + + // find the smallest step that is larger than the provided minimumStep + if (stepYear*1000 > minimumStep) {this.scale = TimeStep.SCALE.YEAR; this.step = 1000;} + if (stepYear*500 > minimumStep) {this.scale = TimeStep.SCALE.YEAR; this.step = 500;} + if (stepYear*100 > minimumStep) {this.scale = TimeStep.SCALE.YEAR; this.step = 100;} + if (stepYear*50 > minimumStep) {this.scale = TimeStep.SCALE.YEAR; this.step = 50;} + if (stepYear*10 > minimumStep) {this.scale = TimeStep.SCALE.YEAR; this.step = 10;} + if (stepYear*5 > minimumStep) {this.scale = TimeStep.SCALE.YEAR; this.step = 5;} + if (stepYear > minimumStep) {this.scale = TimeStep.SCALE.YEAR; this.step = 1;} + if (stepMonth*3 > minimumStep) {this.scale = TimeStep.SCALE.MONTH; this.step = 3;} + if (stepMonth > minimumStep) {this.scale = TimeStep.SCALE.MONTH; this.step = 1;} + if (stepDay*5 > minimumStep) {this.scale = TimeStep.SCALE.DAY; this.step = 5;} + if (stepDay*2 > minimumStep) {this.scale = TimeStep.SCALE.DAY; this.step = 2;} + if (stepDay > minimumStep) {this.scale = TimeStep.SCALE.DAY; this.step = 1;} + if (stepDay/2 > minimumStep) {this.scale = TimeStep.SCALE.WEEKDAY; this.step = 1;} + if (stepHour*4 > minimumStep) {this.scale = TimeStep.SCALE.HOUR; this.step = 4;} + if (stepHour > minimumStep) {this.scale = TimeStep.SCALE.HOUR; this.step = 1;} + if (stepMinute*15 > minimumStep) {this.scale = TimeStep.SCALE.MINUTE; this.step = 15;} + if (stepMinute*10 > minimumStep) {this.scale = TimeStep.SCALE.MINUTE; this.step = 10;} + if (stepMinute*5 > minimumStep) {this.scale = TimeStep.SCALE.MINUTE; this.step = 5;} + if (stepMinute > minimumStep) {this.scale = TimeStep.SCALE.MINUTE; this.step = 1;} + if (stepSecond*15 > minimumStep) {this.scale = TimeStep.SCALE.SECOND; this.step = 15;} + if (stepSecond*10 > minimumStep) {this.scale = TimeStep.SCALE.SECOND; this.step = 10;} + if (stepSecond*5 > minimumStep) {this.scale = TimeStep.SCALE.SECOND; this.step = 5;} + if (stepSecond > minimumStep) {this.scale = TimeStep.SCALE.SECOND; this.step = 1;} + if (stepMillisecond*200 > minimumStep) {this.scale = TimeStep.SCALE.MILLISECOND; this.step = 200;} + if (stepMillisecond*100 > minimumStep) {this.scale = TimeStep.SCALE.MILLISECOND; this.step = 100;} + if (stepMillisecond*50 > minimumStep) {this.scale = TimeStep.SCALE.MILLISECOND; this.step = 50;} + if (stepMillisecond*10 > minimumStep) {this.scale = TimeStep.SCALE.MILLISECOND; this.step = 10;} + if (stepMillisecond*5 > minimumStep) {this.scale = TimeStep.SCALE.MILLISECOND; this.step = 5;} + if (stepMillisecond > minimumStep) {this.scale = TimeStep.SCALE.MILLISECOND; this.step = 1;} }; /** - * Handle removed items - * @param {Number[]} ids - * @private + * Snap a date to a rounded value. The snap intervals are dependent on the + * current scale and step. + * @param {Date} date the date to be snapped */ -ItemSet.prototype._onRemove = function _onRemove(ids) { - this._toQueue('remove', ids); +TimeStep.prototype.snap = function(date) { + if (this.scale == TimeStep.SCALE.YEAR) { + var year = date.getFullYear() + Math.round(date.getMonth() / 12); + date.setFullYear(Math.round(year / this.step) * this.step); + date.setMonth(0); + date.setDate(0); + date.setHours(0); + date.setMinutes(0); + date.setSeconds(0); + date.setMilliseconds(0); + } + else if (this.scale == TimeStep.SCALE.MONTH) { + if (date.getDate() > 15) { + date.setDate(1); + date.setMonth(date.getMonth() + 1); + // important: first set Date to 1, after that change the month. + } + else { + date.setDate(1); + } + + date.setHours(0); + date.setMinutes(0); + date.setSeconds(0); + date.setMilliseconds(0); + } + else if (this.scale == TimeStep.SCALE.DAY || + this.scale == TimeStep.SCALE.WEEKDAY) { + //noinspection FallthroughInSwitchStatementJS + switch (this.step) { + case 5: + case 2: + date.setHours(Math.round(date.getHours() / 24) * 24); break; + default: + date.setHours(Math.round(date.getHours() / 12) * 12); break; + } + date.setMinutes(0); + date.setSeconds(0); + date.setMilliseconds(0); + } + else if (this.scale == TimeStep.SCALE.HOUR) { + switch (this.step) { + case 4: + date.setMinutes(Math.round(date.getMinutes() / 60) * 60); break; + default: + date.setMinutes(Math.round(date.getMinutes() / 30) * 30); break; + } + date.setSeconds(0); + date.setMilliseconds(0); + } else if (this.scale == TimeStep.SCALE.MINUTE) { + //noinspection FallthroughInSwitchStatementJS + switch (this.step) { + case 15: + case 10: + date.setMinutes(Math.round(date.getMinutes() / 5) * 5); + date.setSeconds(0); + break; + case 5: + date.setSeconds(Math.round(date.getSeconds() / 60) * 60); break; + default: + date.setSeconds(Math.round(date.getSeconds() / 30) * 30); break; + } + date.setMilliseconds(0); + } + else if (this.scale == TimeStep.SCALE.SECOND) { + //noinspection FallthroughInSwitchStatementJS + switch (this.step) { + case 15: + case 10: + date.setSeconds(Math.round(date.getSeconds() / 5) * 5); + date.setMilliseconds(0); + break; + case 5: + date.setMilliseconds(Math.round(date.getMilliseconds() / 1000) * 1000); break; + default: + date.setMilliseconds(Math.round(date.getMilliseconds() / 500) * 500); break; + } + } + else if (this.scale == TimeStep.SCALE.MILLISECOND) { + var step = this.step > 5 ? this.step / 2 : 1; + date.setMilliseconds(Math.round(date.getMilliseconds() / step) * step); + } }; /** - * Put items in the queue to be added/updated/remove - * @param {String} action can be 'add', 'update', 'remove' - * @param {Number[]} ids + * Check if the current value is a major value (for example when the step + * is DAY, a major value is each first day of the MONTH) + * @return {boolean} true if current date is major, else false. */ -ItemSet.prototype._toQueue = function _toQueue(action, ids) { - var queue = this.queue; - ids.forEach(function (id) { - queue[id] = action; - }); - - if (this.controller) { - //this.requestReflow(); - this.requestRepaint(); +TimeStep.prototype.isMajor = function() { + switch (this.scale) { + case TimeStep.SCALE.MILLISECOND: + return (this.current.getMilliseconds() == 0); + case TimeStep.SCALE.SECOND: + return (this.current.getSeconds() == 0); + case TimeStep.SCALE.MINUTE: + return (this.current.getHours() == 0) && (this.current.getMinutes() == 0); + // Note: this is no bug. Major label is equal for both minute and hour scale + case TimeStep.SCALE.HOUR: + return (this.current.getHours() == 0); + case TimeStep.SCALE.WEEKDAY: // intentional fall through + case TimeStep.SCALE.DAY: + return (this.current.getDate() == 1); + case TimeStep.SCALE.MONTH: + return (this.current.getMonth() == 0); + case TimeStep.SCALE.YEAR: + return false; + default: + return false; } }; + /** - * Calculate the factor and offset to convert a position on screen to the - * corresponding date and vice versa. - * After the method _updateConversion is executed once, the methods toTime - * and toScreen can be used. - * @private + * Returns formatted text for the minor axislabel, depending on the current + * date and the scale. For example when scale is MINUTE, the current time is + * formatted as "hh:mm". + * @param {Date} [date] custom date. if not provided, current date is taken */ -ItemSet.prototype._updateConversion = function _updateConversion() { - var range = this.range; - if (!range) { - throw new Error('No range configured'); +TimeStep.prototype.getLabelMinor = function(date) { + if (date == undefined) { + date = this.current; } - if (range.conversion) { - this.conversion = range.conversion(this.width); - } - else { - this.conversion = Range.conversion(range.start, range.end, this.width); + switch (this.scale) { + case TimeStep.SCALE.MILLISECOND: return moment(date).format('SSS'); + case TimeStep.SCALE.SECOND: return moment(date).format('s'); + case TimeStep.SCALE.MINUTE: return moment(date).format('HH:mm'); + case TimeStep.SCALE.HOUR: return moment(date).format('HH:mm'); + case TimeStep.SCALE.WEEKDAY: return moment(date).format('ddd D'); + case TimeStep.SCALE.DAY: return moment(date).format('D'); + case TimeStep.SCALE.MONTH: return moment(date).format('MMM'); + case TimeStep.SCALE.YEAR: return moment(date).format('YYYY'); + default: return ''; } }; -/** - * Convert a position on screen (pixels) to a datetime - * Before this method can be used, the method _updateConversion must be - * executed once. - * @param {int} x Position on the screen in pixels - * @return {Date} time The datetime the corresponds with given position x - */ -ItemSet.prototype.toTime = function toTime(x) { - var conversion = this.conversion; - return new Date(x / conversion.factor + conversion.offset); -}; /** - * Convert a datetime (Date object) into a position on the screen - * Before this method can be used, the method _updateConversion must be - * executed once. - * @param {Date} time A date - * @return {int} x The position on the screen in pixels which corresponds - * with the given date. + * Returns formatted text for the major axis label, depending on the current + * date and the scale. For example when scale is MINUTE, the major scale is + * hours, and the hour will be formatted as "hh". + * @param {Date} [date] custom date. if not provided, current date is taken */ -ItemSet.prototype.toScreen = function toScreen(time) { - var conversion = this.conversion; - return (time.valueOf() - conversion.offset) * conversion.factor; +TimeStep.prototype.getLabelMajor = function(date) { + if (date == undefined) { + date = this.current; + } + + //noinspection FallthroughInSwitchStatementJS + switch (this.scale) { + case TimeStep.SCALE.MILLISECOND:return moment(date).format('HH:mm:ss'); + case TimeStep.SCALE.SECOND: return moment(date).format('D MMMM HH:mm'); + case TimeStep.SCALE.MINUTE: + case TimeStep.SCALE.HOUR: return moment(date).format('ddd D MMMM'); + case TimeStep.SCALE.WEEKDAY: + case TimeStep.SCALE.DAY: return moment(date).format('MMMM YYYY'); + case TimeStep.SCALE.MONTH: return moment(date).format('YYYY'); + case TimeStep.SCALE.YEAR: return ''; + default: return ''; + } }; /** - * @constructor Item + * @constructor Stack + * Stacks items on top of each other. * @param {ItemSet} parent - * @param {Object} data Object containing (optional) parameters type, - * start, end, content, group, className. - * @param {Object} [options] Options to set initial property values - * @param {Object} [defaultOptions] default options - * // TODO: describe available options + * @param {Object} [options] */ -function Item (parent, data, options, defaultOptions) { +function Stack (parent, options) { this.parent = parent; - this.data = data; - this.dom = null; + this.options = options || {}; - this.defaultOptions = defaultOptions || {}; + this.defaultOptions = { + order: function (a, b) { + //return (b.width - a.width) || (a.left - b.left); // TODO: cleanup + // Order: ranges over non-ranges, ranged ordered by width, and + // lastly ordered by start. + if (a instanceof ItemRange) { + if (b instanceof ItemRange) { + var aInt = (a.data.end - a.data.start); + var bInt = (b.data.end - b.data.start); + return (aInt - bInt) || (a.data.start - b.data.start); + } + else { + return -1; + } + } + else { + if (b instanceof ItemRange) { + return 1; + } + else { + return (a.data.start - b.data.start); + } + } + }, + margin: { + item: 10 + } + }; - this.selected = false; - this.visible = false; - this.top = 0; - this.left = 0; - this.width = 0; - this.height = 0; + this.ordered = []; // ordered items } /** - * Select current item + * Set options for the stack + * @param {Object} options Available options: + * {ItemSet} parent + * {Number} margin + * {function} order Stacking order */ -Item.prototype.select = function select() { - this.selected = true; +Stack.prototype.setOptions = function setOptions (options) { + util.extend(this.options, options); + + // TODO: register on data changes at the connected parent itemset, and update the changed part only and immediately }; /** - * Unselect current item + * Stack the items such that they don't overlap. The items will have a minimal + * distance equal to options.margin.item. */ -Item.prototype.unselect = function unselect() { - this.selected = false; +Stack.prototype.update = function update() { + this._order(); + this._stack(); }; /** - * Show the Item in the DOM (when not already visible) - * @return {Boolean} changed + * Order the items. The items are ordered by width first, and by left position + * second. + * If a custom order function has been provided via the options, then this will + * be used. + * @private */ -Item.prototype.show = function show() { - return false; +Stack.prototype._order = function _order () { + var items = this.parent.items; + if (!items) { + throw new Error('Cannot stack items: parent does not contain items'); + } + + // TODO: store the sorted items, to have less work later on + var ordered = []; + var index = 0; + // items is a map (no array) + util.forEach(items, function (item) { + if (item.visible) { + ordered[index] = item; + index++; + } + }); + + //if a customer stack order function exists, use it. + var order = this.options.order || this.defaultOptions.order; + if (!(typeof order === 'function')) { + throw new Error('Option order must be a function'); + } + + ordered.sort(order); + + this.ordered = ordered; }; /** - * Hide the Item from the DOM (when visible) - * @return {Boolean} changed + * Adjust vertical positions of the events such that they don't overlap each + * other. + * @private */ -Item.prototype.hide = function hide() { - return false; +Stack.prototype._stack = function _stack () { + var i, + iMax, + ordered = this.ordered, + options = this.options, + orientation = options.orientation || this.defaultOptions.orientation, + axisOnTop = (orientation == 'top'), + margin; + + if (options.margin && options.margin.item !== undefined) { + margin = options.margin.item; + } + else { + margin = this.defaultOptions.margin.item + } + + // calculate new, non-overlapping positions + for (i = 0, iMax = ordered.length; i < iMax; i++) { + var item = ordered[i]; + var collidingItem = null; + do { + // TODO: optimize checking for overlap. when there is a gap without items, + // you only need to check for items from the next item on, not from zero + collidingItem = this.checkOverlap(ordered, i, 0, i - 1, margin); + if (collidingItem != null) { + // There is a collision. Reposition the event above the colliding element + if (axisOnTop) { + item.top = collidingItem.top + collidingItem.height + margin; + } + else { + item.top = collidingItem.top - item.height - margin; + } + } + } while (collidingItem); + } }; /** - * Repaint the item - * @return {Boolean} changed + * Check if the destiny position of given item overlaps with any + * of the other items from index itemStart to itemEnd. + * @param {Array} items Array with items + * @param {int} itemIndex Number of the item to be checked for overlap + * @param {int} itemStart First item to be checked. + * @param {int} itemEnd Last item to be checked. + * @return {Object | null} colliding item, or undefined when no collisions + * @param {Number} margin A minimum required margin. + * If margin is provided, the two items will be + * marked colliding when they overlap or + * when the margin between the two is smaller than + * the requested margin. */ -Item.prototype.repaint = function repaint() { - // should be implemented by the item - return false; +Stack.prototype.checkOverlap = function checkOverlap (items, itemIndex, + itemStart, itemEnd, margin) { + var collision = this.collision; + + // we loop from end to start, as we suppose that the chance of a + // collision is larger for items at the end, so check these first. + var a = items[itemIndex]; + for (var i = itemEnd; i >= itemStart; i--) { + var b = items[i]; + if (collision(a, b, margin)) { + if (i != itemIndex) { + return b; + } + } + } + + return null; }; /** - * Reflow the item - * @return {Boolean} resized + * Test if the two provided items collide + * The items must have parameters left, width, top, and height. + * @param {Component} a The first item + * @param {Component} b The second item + * @param {Number} margin A minimum required margin. + * If margin is provided, the two items will be + * marked colliding when they overlap or + * when the margin between the two is smaller than + * the requested margin. + * @return {boolean} true if a and b collide, else false */ -Item.prototype.reflow = function reflow() { - // should be implemented by the item - return false; +Stack.prototype.collision = function collision (a, b, margin) { + return ((a.left - margin) < (b.left + b.width) && + (a.left + a.width + margin) > b.left && + (a.top - margin) < (b.top + b.height) && + (a.top + a.height + margin) > b.top); }; /** - * @constructor ItemBox - * @extends Item - * @param {ItemSet} parent - * @param {Object} data Object containing parameters start - * content, className. - * @param {Object} [options] Options to set initial property values - * @param {Object} [defaultOptions] default options - * // TODO: describe available options + * @constructor Range + * A Range controls a numeric range with a start and end value. + * The Range adjusts the range based on mouse events or programmatic changes, + * and triggers events when the range is changing or has been changed. + * @param {Object} [options] See description at Range.setOptions + * @extends Controller */ -function ItemBox (parent, data, options, defaultOptions) { - this.props = { - dot: { - left: 0, - top: 0, - width: 0, - height: 0 - }, - line: { - top: 0, - left: 0, - width: 0, - height: 0 - } +function Range(options) { + this.id = util.randomUUID(); + this.start = 0; // Number + this.end = 0; // Number + + // this.options = options || {}; // TODO: fix range options + this.options = { + min: null, + max: null, + zoomMin: null, + zoomMax: null }; - Item.call(this, parent, data, options, defaultOptions); -} + this.listeners = []; -ItemBox.prototype = new Item (null, null); + this.setOptions(options); +} /** - * Select the item - * @override + * Set options for the range controller + * @param {Object} options Available options: + * {Number} start Set start value of the range + * {Number} end Set end value of the range + * {Number} min Minimum value for start + * {Number} max Maximum value for end + * {Number} zoomMin Set a minimum value for + * (end - start). + * {Number} zoomMax Set a maximum value for + * (end - start). */ -ItemBox.prototype.select = function select() { - this.selected = true; - // TODO: select and unselect -}; +Range.prototype.setOptions = function (options) { + util.extend(this.options, options); -/** - * Unselect the item - * @override - */ -ItemBox.prototype.unselect = function unselect() { - this.selected = false; - // TODO: select and unselect + if (options.start != null || options.end != null) { + this.setRange(options.start, options.end); + } }; /** - * Repaint the item - * @return {Boolean} changed + * Add listeners for mouse and touch events to the component + * @param {Component} component + * @param {String} event Available events: 'move', 'zoom' + * @param {String} direction Available directions: 'horizontal', 'vertical' */ -ItemBox.prototype.repaint = function repaint() { - // TODO: make an efficient repaint - var changed = false; - var dom = this.dom; +Range.prototype.subscribe = function (component, event, direction) { + var me = this; + var listener; - if (!dom) { - this._create(); - dom = this.dom; - changed = true; + if (direction != 'horizontal' && direction != 'vertical') { + throw new TypeError('Unknown direction "' + direction + '". ' + + 'Choose "horizontal" or "vertical".'); } - if (dom) { - if (!this.parent) { - throw new Error('Cannot repaint item: no parent attached'); - } - var foreground = this.parent.getForeground(); - if (!foreground) { - throw new Error('Cannot repaint time axis: ' + - 'parent has no foreground container element'); - } - var background = this.parent.getBackground(); - if (!background) { - throw new Error('Cannot repaint time axis: ' + - 'parent has no background container element'); - } - var axis = this.parent.getAxis(); - if (!background) { - throw new Error('Cannot repaint time axis: ' + - 'parent has no axis container element'); - } - - if (!dom.box.parentNode) { - foreground.appendChild(dom.box); - changed = true; - } - if (!dom.line.parentNode) { - background.appendChild(dom.line); - changed = true; - } - if (!dom.dot.parentNode) { - axis.appendChild(dom.dot); - changed = true; - } + //noinspection FallthroughInSwitchStatementJS + if (event == 'move') { + listener = { + component: component, + event: event, + direction: direction, + callback: function (event) { + me._onMouseDown(event, listener); + }, + params: {} + }; - // update contents - if (this.data.content != this.content) { - this.content = this.data.content; - if (this.content instanceof Element) { - dom.content.innerHTML = ''; - dom.content.appendChild(this.content); - } - else if (this.data.content != undefined) { - dom.content.innerHTML = this.content; - } - else { - throw new Error('Property "content" missing in item ' + this.data.id); - } - changed = true; - } + component.on('mousedown', listener.callback); + me.listeners.push(listener); + } + else if (event == 'zoom') { + listener = { + component: component, + event: event, + direction: direction, + callback: function (event) { + me._onMouseWheel(event, listener); + }, + params: {} + }; - // update class - var className = (this.data.className? ' ' + this.data.className : '') + - (this.selected ? ' selected' : ''); - if (this.className != className) { - this.className = className; - dom.box.className = 'item box' + className; - dom.line.className = 'item line' + className; - dom.dot.className = 'item dot' + className; - changed = true; - } + component.on('mousewheel', listener.callback); + me.listeners.push(listener); + } + else { + throw new TypeError('Unknown event "' + event + '". ' + + 'Choose "move" or "zoom".'); } +}; - return changed; +/** + * Event handler + * @param {String} event name of the event, for example 'click', 'mousemove' + * @param {function} callback callback handler, invoked with the raw HTML Event + * as parameter. + */ +Range.prototype.on = function (event, callback) { + events.addListener(this, event, callback); }; /** - * Show the item in the DOM (when not already visible). The items DOM will - * be created when needed. - * @return {Boolean} changed + * Trigger an event + * @param {String} event name of the event, available events: 'rangechange', + * 'rangechanged' + * @private */ -ItemBox.prototype.show = function show() { - if (!this.dom || !this.dom.box.parentNode) { - return this.repaint(); - } - else { - return false; - } +Range.prototype._trigger = function (event) { + events.trigger(this, event, { + start: this.start, + end: this.end + }); }; /** - * Hide the item from the DOM (when visible) - * @return {Boolean} changed + * Set a new start and end range + * @param {Number} start + * @param {Number} end */ -ItemBox.prototype.hide = function hide() { - var changed = false, - dom = this.dom; - if (dom) { - if (dom.box.parentNode) { - dom.box.parentNode.removeChild(dom.box); - changed = true; - } - if (dom.line.parentNode) { - dom.line.parentNode.removeChild(dom.line); - } - if (dom.dot.parentNode) { - dom.dot.parentNode.removeChild(dom.dot); - } +Range.prototype.setRange = function(start, end) { + var changed = this._applyRange(start, end); + if (changed) { + this._trigger('rangechange'); + this._trigger('rangechanged'); } - return changed; }; /** - * Reflow the item: calculate its actual size and position from the DOM - * @return {boolean} resized returns true if the axis is resized - * @override + * Set a new start and end range. This method is the same as setRange, but + * does not trigger a range change and range changed event, and it returns + * true when the range is changed + * @param {Number} start + * @param {Number} end + * @return {Boolean} changed + * @private */ -ItemBox.prototype.reflow = function reflow() { - var changed = 0, - update, - dom, - props, - options, - margin, - start, - align, - orientation, - top, - left, - data, - range; +Range.prototype._applyRange = function(start, end) { + var newStart = (start != null) ? util.convert(start, 'Number') : this.start; + var newEnd = (end != null) ? util.convert(end, 'Number') : this.end; + var diff; - if (this.data.start == undefined) { - throw new Error('Property "start" missing in item ' + this.data.id); + // check for valid number + if (isNaN(newStart)) { + throw new Error('Invalid start "' + start + '"'); + } + if (isNaN(newEnd)) { + throw new Error('Invalid end "' + end + '"'); } - data = this.data; - range = this.parent && this.parent.range; - if (data && range) { - // TODO: account for the width of the item - var interval = (range.end - range.start); - this.visible = (data.start > range.start - interval) && (data.start < range.end + interval); + // prevent start < end + if (newEnd < newStart) { + newEnd = newStart; } - else { - this.visible = false; + + // prevent start < min + if (this.options.min != null) { + var min = this.options.min.valueOf(); + if (newStart < min) { + diff = (min - newStart); + newStart += diff; + newEnd += diff; + } + } + + // prevent end > max + if (this.options.max != null) { + var max = this.options.max.valueOf(); + if (newEnd > max) { + diff = (newEnd - max); + newStart -= diff; + newEnd -= diff; + } } - if (this.visible) { - dom = this.dom; - if (dom) { - update = util.updateProperty; - props = this.props; - options = this.options; - start = this.parent.toScreen(this.data.start); - align = options.align || this.defaultOptions.align; - margin = options.margin && options.margin.axis || this.defaultOptions.margin.axis; - orientation = options.orientation || this.defaultOptions.orientation; - - changed += update(props.dot, 'height', dom.dot.offsetHeight); - changed += update(props.dot, 'width', dom.dot.offsetWidth); - changed += update(props.line, 'width', dom.line.offsetWidth); - changed += update(props.line, 'height', dom.line.offsetHeight); - changed += update(props.line, 'top', dom.line.offsetTop); - changed += update(this, 'width', dom.box.offsetWidth); - changed += update(this, 'height', dom.box.offsetHeight); - if (align == 'right') { - left = start - this.width; - } - else if (align == 'left') { - left = start; + // prevent (end-start) > zoomMin + if (this.options.zoomMin != null) { + var zoomMin = this.options.zoomMin.valueOf(); + if (zoomMin < 0) { + zoomMin = 0; + } + if ((newEnd - newStart) < zoomMin) { + if ((this.end - this.start) > zoomMin) { + // zoom to the minimum + diff = (zoomMin - (newEnd - newStart)); + newStart -= diff / 2; + newEnd += diff / 2; } else { - // default or 'center' - left = start - this.width / 2; + // ingore this action, we are already zoomed to the minimum + newStart = this.start; + newEnd = this.end; } - changed += update(this, 'left', left); - - changed += update(props.line, 'left', start - props.line.width / 2); - changed += update(props.dot, 'left', start - props.dot.width / 2); - changed += update(props.dot, 'top', -props.dot.height / 2); - if (orientation == 'top') { - top = margin; + } + } - changed += update(this, 'top', top); + // prevent (end-start) > zoomMin + if (this.options.zoomMax != null) { + var zoomMax = this.options.zoomMax.valueOf(); + if (zoomMax < 0) { + zoomMax = 0; + } + if ((newEnd - newStart) > zoomMax) { + if ((this.end - this.start) < zoomMax) { + // zoom to the maximum + diff = ((newEnd - newStart) - zoomMax); + newStart += diff / 2; + newEnd -= diff / 2; } else { - // default or 'bottom' - var parentHeight = this.parent.height; - top = parentHeight - this.height - margin; - - changed += update(this, 'top', top); + // ingore this action, we are already zoomed to the maximum + newStart = this.start; + newEnd = this.end; } } - else { - changed += 1; - } } - return (changed > 0); + var changed = (this.start != newStart || this.end != newEnd); + + this.start = newStart; + this.end = newEnd; + + return changed; }; /** - * Create an items DOM - * @private + * Retrieve the current range. + * @return {Object} An object with start and end properties */ -ItemBox.prototype._create = function _create() { - var dom = this.dom; - if (!dom) { - this.dom = dom = {}; - - // create the box - dom.box = document.createElement('DIV'); - // className is updated in repaint() +Range.prototype.getRange = function() { + return { + start: this.start, + end: this.end + }; +}; - // contents box (inside the background box). used for making margins - dom.content = document.createElement('DIV'); - dom.content.className = 'content'; - dom.box.appendChild(dom.content); +/** + * Calculate the conversion offset and factor for current range, based on + * the provided width + * @param {Number} width + * @returns {{offset: number, factor: number}} conversion + */ +Range.prototype.conversion = function (width) { + var start = this.start; + var end = this.end; - // line to axis - dom.line = document.createElement('DIV'); - dom.line.className = 'line'; + return Range.conversion(this.start, this.end, width); +}; - // dot on axis - dom.dot = document.createElement('DIV'); - dom.dot.className = 'dot'; +/** + * Static method to calculate the conversion offset and factor for a range, + * based on the provided start, end, and width + * @param {Number} start + * @param {Number} end + * @param {Number} width + * @returns {{offset: number, factor: number}} conversion + */ +Range.conversion = function (start, end, width) { + if (width != 0 && (end - start != 0)) { + return { + offset: start, + factor: width / (end - start) + } + } + else { + return { + offset: 0, + factor: 1 + }; } }; /** - * Reposition the item, recalculate its left, top, and width, using the current - * range and size of the items itemset - * @override + * Start moving horizontally or vertically + * @param {Event} event + * @param {Object} listener Listener containing the component and params + * @private */ -ItemBox.prototype.reposition = function reposition() { - var dom = this.dom, - props = this.props, - orientation = this.options.orientation || this.defaultOptions.orientation; +Range.prototype._onMouseDown = function(event, listener) { + event = event || window.event; + var params = listener.params; - if (dom) { - var box = dom.box, - line = dom.line, - dot = dom.dot; + // only react on left mouse button down + var leftButtonDown = event.which ? (event.which == 1) : (event.button == 1); + if (!leftButtonDown) { + return; + } - box.style.left = this.left + 'px'; - box.style.top = this.top + 'px'; + // get mouse position + params.mouseX = util.getPageX(event); + params.mouseY = util.getPageY(event); + params.previousLeft = 0; + params.previousOffset = 0; - line.style.left = props.line.left + 'px'; - if (orientation == 'top') { - line.style.top = 0 + 'px'; - line.style.height = this.top + 'px'; - } - else { - // orientation 'bottom' - line.style.top = (this.top + this.height) + 'px'; - line.style.height = Math.max(this.parent.height - this.top - this.height + - this.props.dot.height / 2, 0) + 'px'; - } + params.moved = false; + params.start = this.start; + params.end = this.end; - dot.style.left = props.dot.left + 'px'; - dot.style.top = props.dot.top + 'px'; + var frame = listener.component.frame; + if (frame) { + frame.style.cursor = 'move'; + } + + // add event listeners to handle moving the contents + // we store the function onmousemove and onmouseup in the timeaxis, + // so we can remove the eventlisteners lateron in the function onmouseup + var me = this; + if (!params.onMouseMove) { + params.onMouseMove = function (event) { + me._onMouseMove(event, listener); + }; + util.addEventListener(document, "mousemove", params.onMouseMove); + } + if (!params.onMouseUp) { + params.onMouseUp = function (event) { + me._onMouseUp(event, listener); + }; + util.addEventListener(document, "mouseup", params.onMouseUp); } + + util.preventDefault(event); }; /** - * @constructor ItemPoint - * @extends Item - * @param {ItemSet} parent - * @param {Object} data Object containing parameters start - * content, className. - * @param {Object} [options] Options to set initial property values - * @param {Object} [defaultOptions] default options - * // TODO: describe available options + * Perform moving operating. + * This function activated from within the funcion TimeAxis._onMouseDown(). + * @param {Event} event + * @param {Object} listener + * @private */ -function ItemPoint (parent, data, options, defaultOptions) { - this.props = { - dot: { - top: 0, - width: 0, - height: 0 - }, - content: { - height: 0, - marginLeft: 0 - } - }; +Range.prototype._onMouseMove = function (event, listener) { + event = event || window.event; + + var params = listener.params; + + // calculate change in mouse position + var mouseX = util.getPageX(event); + var mouseY = util.getPageY(event); + + if (params.mouseX == undefined) { + params.mouseX = mouseX; + } + if (params.mouseY == undefined) { + params.mouseY = mouseY; + } + + var diffX = mouseX - params.mouseX; + var diffY = mouseY - params.mouseY; + var diff = (listener.direction == 'horizontal') ? diffX : diffY; + + // if mouse movement is big enough, register it as a "moved" event + if (Math.abs(diff) >= 1) { + params.moved = true; + } - Item.call(this, parent, data, options, defaultOptions); -} + var interval = (params.end - params.start); + var width = (listener.direction == 'horizontal') ? + listener.component.width : listener.component.height; + var diffRange = -diff / width * interval; + this._applyRange(params.start + diffRange, params.end + diffRange); -ItemPoint.prototype = new Item (null, null); + // fire a rangechange event + this._trigger('rangechange'); -/** - * Select the item - * @override - */ -ItemPoint.prototype.select = function select() { - this.selected = true; - // TODO: select and unselect + util.preventDefault(event); }; /** - * Unselect the item - * @override + * Stop moving operating. + * This function activated from within the function Range._onMouseDown(). + * @param {event} event + * @param {Object} listener + * @private */ -ItemPoint.prototype.unselect = function unselect() { - this.selected = false; - // TODO: select and unselect -}; +Range.prototype._onMouseUp = function (event, listener) { + event = event || window.event; -/** - * Repaint the item - * @return {Boolean} changed - */ -ItemPoint.prototype.repaint = function repaint() { - // TODO: make an efficient repaint - var changed = false; - var dom = this.dom; + var params = listener.params; - if (!dom) { - this._create(); - dom = this.dom; - changed = true; + if (listener.component.frame) { + listener.component.frame.style.cursor = 'auto'; } - if (dom) { - if (!this.parent) { - throw new Error('Cannot repaint item: no parent attached'); - } - var foreground = this.parent.getForeground(); - if (!foreground) { - throw new Error('Cannot repaint time axis: ' + - 'parent has no foreground container element'); - } - - if (!dom.point.parentNode) { - foreground.appendChild(dom.point); - foreground.appendChild(dom.point); - changed = true; - } - - // update contents - if (this.data.content != this.content) { - this.content = this.data.content; - if (this.content instanceof Element) { - dom.content.innerHTML = ''; - dom.content.appendChild(this.content); - } - else if (this.data.content != undefined) { - dom.content.innerHTML = this.content; - } - else { - throw new Error('Property "content" missing in item ' + this.data.id); - } - changed = true; - } - - // update class - var className = (this.data.className? ' ' + this.data.className : '') + - (this.selected ? ' selected' : ''); - if (this.className != className) { - this.className = className; - dom.point.className = 'item point' + className; - changed = true; - } + // remove event listeners here, important for Safari + if (params.onMouseMove) { + util.removeEventListener(document, "mousemove", params.onMouseMove); + params.onMouseMove = null; + } + if (params.onMouseUp) { + util.removeEventListener(document, "mouseup", params.onMouseUp); + params.onMouseUp = null; } + //util.preventDefault(event); - return changed; + if (params.moved) { + // fire a rangechanged event + this._trigger('rangechanged'); + } }; /** - * Show the item in the DOM (when not already visible). The items DOM will - * be created when needed. - * @return {Boolean} changed + * Event handler for mouse wheel event, used to zoom + * Code from http://adomas.org/javascript-mouse-wheel/ + * @param {Event} event + * @param {Object} listener + * @private */ -ItemPoint.prototype.show = function show() { - if (!this.dom || !this.dom.point.parentNode) { - return this.repaint(); - } - else { - return false; +Range.prototype._onMouseWheel = function(event, listener) { + event = event || window.event; + + // retrieve delta + var delta = 0; + if (event.wheelDelta) { /* IE/Opera. */ + delta = event.wheelDelta / 120; + } else if (event.detail) { /* Mozilla case. */ + // In Mozilla, sign of delta is different than in IE. + // Also, delta is multiple of 3. + delta = -event.detail / 3; } -}; -/** - * Hide the item from the DOM (when visible) - * @return {Boolean} changed - */ -ItemPoint.prototype.hide = function hide() { - var changed = false, - dom = this.dom; - if (dom) { - if (dom.point.parentNode) { - dom.point.parentNode.removeChild(dom.point); - changed = true; - } + // If delta is nonzero, handle it. + // Basically, delta is now positive if wheel was scrolled up, + // and negative, if wheel was scrolled down. + if (delta) { + var me = this; + var zoom = function () { + // perform the zoom action. Delta is normally 1 or -1 + var zoomFactor = delta / 5.0; + var zoomAround = null; + var frame = listener.component.frame; + if (frame) { + var size, conversion; + if (listener.direction == 'horizontal') { + size = listener.component.width; + conversion = me.conversion(size); + var frameLeft = util.getAbsoluteLeft(frame); + var mouseX = util.getPageX(event); + zoomAround = (mouseX - frameLeft) / conversion.factor + conversion.offset; + } + else { + size = listener.component.height; + conversion = me.conversion(size); + var frameTop = util.getAbsoluteTop(frame); + var mouseY = util.getPageY(event); + zoomAround = ((frameTop + size - mouseY) - frameTop) / conversion.factor + conversion.offset; + } + } + + me.zoom(zoomFactor, zoomAround); + }; + + zoom(); } - return changed; + + // Prevent default actions caused by mouse wheel. + // That might be ugly, but we handle scrolls somehow + // anyway, so don't bother here... + util.preventDefault(event); }; + /** - * Reflow the item: calculate its actual size from the DOM - * @return {boolean} resized returns true if the axis is resized - * @override + * Zoom the range the given zoomfactor in or out. Start and end date will + * be adjusted, and the timeline will be redrawn. You can optionally give a + * date around which to zoom. + * For example, try zoomfactor = 0.1 or -0.1 + * @param {Number} zoomFactor Zooming amount. Positive value will zoom in, + * negative value will zoom out + * @param {Number} zoomAround Value around which will be zoomed. Optional */ -ItemPoint.prototype.reflow = function reflow() { - var changed = 0, - update, - dom, - props, - options, - margin, - orientation, - start, - top, - data, - range; - - if (this.data.start == undefined) { - throw new Error('Property "start" missing in item ' + this.data.id); +Range.prototype.zoom = function(zoomFactor, zoomAround) { + // if zoomAroundDate is not provided, take it half between start Date and end Date + if (zoomAround == null) { + zoomAround = (this.start + this.end) / 2; } - data = this.data; - range = this.parent && this.parent.range; - if (data && range) { - // TODO: account for the width of the item - var interval = (range.end - range.start); - this.visible = (data.start > range.start - interval) && (data.start < range.end); + // prevent zoom factor larger than 1 or smaller than -1 (larger than 1 will + // result in a start>=end ) + if (zoomFactor >= 1) { + zoomFactor = 0.9; } - else { - this.visible = false; + if (zoomFactor <= -1) { + zoomFactor = -0.9; } - if (this.visible) { - dom = this.dom; - if (dom) { - update = util.updateProperty; - props = this.props; - options = this.options; - orientation = options.orientation || this.defaultOptions.orientation; - margin = options.margin && options.margin.axis || this.defaultOptions.margin.axis; - start = this.parent.toScreen(this.data.start); - - changed += update(this, 'width', dom.point.offsetWidth); - changed += update(this, 'height', dom.point.offsetHeight); - changed += update(props.dot, 'width', dom.dot.offsetWidth); - changed += update(props.dot, 'height', dom.dot.offsetHeight); - changed += update(props.content, 'height', dom.content.offsetHeight); - - if (orientation == 'top') { - top = margin; - } - else { - // default or 'bottom' - var parentHeight = this.parent.height; - top = Math.max(parentHeight - this.height - margin, 0); - } - changed += update(this, 'top', top); - changed += update(this, 'left', start - props.dot.width / 2); - changed += update(props.content, 'marginLeft', 1.5 * props.dot.width); - //changed += update(props.content, 'marginRight', 0.5 * props.dot.width); // TODO - - changed += update(props.dot, 'top', (this.height - props.dot.height) / 2); - } - else { - changed += 1; - } + // adjust a negative factor such that zooming in with 0.1 equals zooming + // out with a factor -0.1 + if (zoomFactor < 0) { + zoomFactor = zoomFactor / (1 + zoomFactor); } - return (changed > 0); + // zoom start and end relative to the zoomAround value + var startDiff = (this.start - zoomAround); + var endDiff = (this.end - zoomAround); + + // calculate new start and end + var newStart = this.start - startDiff * zoomFactor; + var newEnd = this.end - endDiff * zoomFactor; + + this.setRange(newStart, newEnd); }; /** - * Create an items DOM - * @private + * Move the range with a given factor to the left or right. Start and end + * value will be adjusted. For example, try moveFactor = 0.1 or -0.1 + * @param {Number} moveFactor Moving amount. Positive value will move right, + * negative value will move left */ -ItemPoint.prototype._create = function _create() { - var dom = this.dom; - if (!dom) { - this.dom = dom = {}; +Range.prototype.move = function(moveFactor) { + // zoom start Date and end Date relative to the zoomAroundDate + var diff = (this.end - this.start); - // background box - dom.point = document.createElement('div'); - // className is updated in repaint() + // apply new values + var newStart = this.start + diff * moveFactor; + var newEnd = this.end + diff * moveFactor; - // contents box, right from the dot - dom.content = document.createElement('div'); - dom.content.className = 'content'; - dom.point.appendChild(dom.content); + // TODO: reckon with min and max range - // dot at start - dom.dot = document.createElement('div'); - dom.dot.className = 'dot'; - dom.point.appendChild(dom.dot); - } + this.start = newStart; + this.end = newEnd; }; /** - * Reposition the item, recalculate its left, top, and width, using the current - * range and size of the items itemset - * @override + * Move the range to a new center point + * @param {Number} moveTo New center point of the range */ -ItemPoint.prototype.reposition = function reposition() { - var dom = this.dom, - props = this.props; +Range.prototype.moveTo = function(moveTo) { + var center = (this.start + this.end) / 2; - if (dom) { - dom.point.style.top = this.top + 'px'; - dom.point.style.left = this.left + 'px'; + var diff = center - moveTo; - dom.content.style.marginLeft = props.content.marginLeft + 'px'; - //dom.content.style.marginRight = props.content.marginRight + 'px'; // TODO + // calculate new start and end + var newStart = this.start - diff; + var newEnd = this.end - diff; - dom.dot.style.top = props.dot.top + 'px'; - } -}; + this.setRange(newStart, newEnd); +} /** - * @constructor ItemRange - * @extends Item - * @param {ItemSet} parent - * @param {Object} data Object containing parameters start, end - * content, className. - * @param {Object} [options] Options to set initial property values - * @param {Object} [defaultOptions] default options - * // TODO: describe available options + * @constructor Controller + * + * A Controller controls the reflows and repaints of all visual components */ -function ItemRange (parent, data, options, defaultOptions) { - this.props = { - content: { - left: 0, - width: 0 - } - }; +function Controller () { + this.id = util.randomUUID(); + this.components = {}; - Item.call(this, parent, data, options, defaultOptions); + this.repaintTimer = undefined; + this.reflowTimer = undefined; } -ItemRange.prototype = new Item (null, null); - /** - * Select the item - * @override + * Add a component to the controller + * @param {Component} component */ -ItemRange.prototype.select = function select() { - this.selected = true; - // TODO: select and unselect -}; +Controller.prototype.add = function add(component) { + // validate the component + if (component.id == undefined) { + throw new Error('Component has no field id'); + } + if (!(component instanceof Component) && !(component instanceof Controller)) { + throw new TypeError('Component must be an instance of ' + + 'prototype Component or Controller'); + } -/** - * Unselect the item - * @override - */ -ItemRange.prototype.unselect = function unselect() { - this.selected = false; - // TODO: select and unselect + // add the component + component.controller = this; + this.components[component.id] = component; }; /** - * Repaint the item - * @return {Boolean} changed + * Remove a component from the controller + * @param {Component | String} component */ -ItemRange.prototype.repaint = function repaint() { - // TODO: make an efficient repaint - var changed = false; - var dom = this.dom; - - if (!dom) { - this._create(); - dom = this.dom; - changed = true; - } - - if (dom) { - if (!this.parent) { - throw new Error('Cannot repaint item: no parent attached'); - } - var foreground = this.parent.getForeground(); - if (!foreground) { - throw new Error('Cannot repaint time axis: ' + - 'parent has no foreground container element'); - } - - if (!dom.box.parentNode) { - foreground.appendChild(dom.box); - changed = true; - } - - // update content - if (this.data.content != this.content) { - this.content = this.data.content; - if (this.content instanceof Element) { - dom.content.innerHTML = ''; - dom.content.appendChild(this.content); - } - else if (this.data.content != undefined) { - dom.content.innerHTML = this.content; - } - else { - throw new Error('Property "content" missing in item ' + this.data.id); +Controller.prototype.remove = function remove(component) { + var id; + for (id in this.components) { + if (this.components.hasOwnProperty(id)) { + if (id == component || this.components[id] == component) { + break; } - changed = true; - } - - // update class - var className = this.data.className ? (' ' + this.data.className) : ''; - if (this.className != className) { - this.className = className; - dom.box.className = 'item range' + className; - changed = true; } } - return changed; + if (id) { + delete this.components[id]; + } }; /** - * Show the item in the DOM (when not already visible). The items DOM will - * be created when needed. - * @return {Boolean} changed + * Request a reflow. The controller will schedule a reflow + * @param {Boolean} [force] If true, an immediate reflow is forced. Default + * is false. */ -ItemRange.prototype.show = function show() { - if (!this.dom || !this.dom.box.parentNode) { - return this.repaint(); +Controller.prototype.requestReflow = function requestReflow(force) { + if (force) { + this.reflow(); } else { - return false; - } -}; - -/** - * Hide the item from the DOM (when visible) - * @return {Boolean} changed - */ -ItemRange.prototype.hide = function hide() { - var changed = false, - dom = this.dom; - if (dom) { - if (dom.box.parentNode) { - dom.box.parentNode.removeChild(dom.box); - changed = true; + if (!this.reflowTimer) { + var me = this; + this.reflowTimer = setTimeout(function () { + me.reflowTimer = undefined; + me.reflow(); + }, 0); } } - return changed; }; /** - * Reflow the item: calculate its actual size from the DOM - * @return {boolean} resized returns true if the axis is resized - * @override + * Request a repaint. The controller will schedule a repaint + * @param {Boolean} [force] If true, an immediate repaint is forced. Default + * is false. */ -ItemRange.prototype.reflow = function reflow() { - var changed = 0, - dom, - props, - options, - margin, - padding, - parent, - start, - end, - data, - range, - update, - box, - parentWidth, - contentLeft, - orientation, - top; - - if (this.data.start == undefined) { - throw new Error('Property "start" missing in item ' + this.data.id); - } - if (this.data.end == undefined) { - throw new Error('Property "end" missing in item ' + this.data.id); - } - - data = this.data; - range = this.parent && this.parent.range; - if (data && range) { - // TODO: account for the width of the item. Take some margin - this.visible = (data.start < range.end) && (data.end > range.start); +Controller.prototype.requestRepaint = function requestRepaint(force) { + if (force) { + this.repaint(); } else { - this.visible = false; + if (!this.repaintTimer) { + var me = this; + this.repaintTimer = setTimeout(function () { + me.repaintTimer = undefined; + me.repaint(); + }, 0); + } } +}; - if (this.visible) { - dom = this.dom; - if (dom) { - props = this.props; - options = this.options; - parent = this.parent; - start = parent.toScreen(this.data.start); - end = parent.toScreen(this.data.end); - update = util.updateProperty; - box = dom.box; - parentWidth = parent.width; - orientation = options.orientation || this.defaultOptions.orientation; - margin = options.margin && options.margin.axis || this.defaultOptions.margin.axis; - padding = options.padding || this.defaultOptions.padding; - - changed += update(props.content, 'width', dom.content.offsetWidth); - - changed += update(this, 'height', box.offsetHeight); +/** + * Repaint all components + */ +Controller.prototype.repaint = function repaint() { + var changed = false; - // limit the width of the this, as browsers cannot draw very wide divs - if (start < -parentWidth) { - start = -parentWidth; - } - if (end > 2 * parentWidth) { - end = 2 * parentWidth; - } + // cancel any running repaint request + if (this.repaintTimer) { + clearTimeout(this.repaintTimer); + this.repaintTimer = undefined; + } - // when range exceeds left of the window, position the contents at the left of the visible area - if (start < 0) { - contentLeft = Math.min(-start, - (end - start - props.content.width - 2 * padding)); - // TODO: remove the need for options.padding. it's terrible. - } - else { - contentLeft = 0; - } - changed += update(props.content, 'left', contentLeft); + var done = {}; - if (orientation == 'top') { - top = margin; - changed += update(this, 'top', top); + function repaint(component, id) { + if (!(id in done)) { + // first repaint the components on which this component is dependent + if (component.depends) { + component.depends.forEach(function (dep) { + repaint(dep, dep.id); + }); } - else { - // default or 'bottom' - top = parent.height - this.height - margin; - changed += update(this, 'top', top); + if (component.parent) { + repaint(component.parent, component.parent.id); } - changed += update(this, 'left', start); - changed += update(this, 'width', Math.max(end - start, 1)); // TODO: reckon with border width; - } - else { - changed += 1; + // repaint the component itself and mark as done + changed = component.repaint() || changed; + done[id] = true; } } - return (changed > 0); + util.forEach(this.components, repaint); + + // immediately reflow when needed + if (changed) { + this.reflow(); + } + // TODO: limit the number of nested reflows/repaints, prevent loop }; /** - * Create an items DOM - * @private + * Reflow all components */ -ItemRange.prototype._create = function _create() { - var dom = this.dom; - if (!dom) { - this.dom = dom = {}; - // background box - dom.box = document.createElement('div'); - // className is updated in repaint() +Controller.prototype.reflow = function reflow() { + var resized = false; - // contents box - dom.content = document.createElement('div'); - dom.content.className = 'content'; - dom.box.appendChild(dom.content); + // cancel any running repaint request + if (this.reflowTimer) { + clearTimeout(this.reflowTimer); + this.reflowTimer = undefined; } -}; -/** - * Reposition the item, recalculate its left, top, and width, using the current - * range and size of the items itemset - * @override - */ -ItemRange.prototype.reposition = function reposition() { - var dom = this.dom, - props = this.props; + var done = {}; - if (dom) { - dom.box.style.top = this.top + 'px'; - dom.box.style.left = this.left + 'px'; - dom.box.style.width = this.width + 'px'; + function reflow(component, id) { + if (!(id in done)) { + // first reflow the components on which this component is dependent + if (component.depends) { + component.depends.forEach(function (dep) { + reflow(dep, dep.id); + }); + } + if (component.parent) { + reflow(component.parent, component.parent.id); + } - dom.content.style.left = props.content.left + 'px'; + // reflow the component itself and mark as done + resized = component.reflow() || resized; + done[id] = true; + } + } + + util.forEach(this.components, reflow); + + // immediately repaint when needed + if (resized) { + this.repaint(); } + // TODO: limit the number of nested reflows/repaints, prevent loop }; /** - * @constructor Group - * @param {GroupSet} parent - * @param {Number | String} groupId - * @param {Object} [options] Options to set initial property values - * // TODO: describe available options - * @extends Component + * Prototype for visual components */ -function Group (parent, groupId, options) { - this.id = util.randomUUID(); - this.parent = parent; - - this.groupId = groupId; - this.itemset = null; // ItemSet - this.options = options || {}; - this.options.top = 0; - - this.props = { - label: { - width: 0, - height: 0 - } - }; +function Component () { + this.id = null; + this.parent = null; + this.depends = null; + this.controller = null; + this.options = null; + this.frame = null; // main DOM element this.top = 0; this.left = 0; this.width = 0; this.height = 0; } -Group.prototype = new Component(); - -// TODO: comment -Group.prototype.setOptions = Component.prototype.setOptions; - /** - * Get the container element of the panel, which can be used by a child to - * add its own widgets. - * @returns {HTMLElement} container + * Set parameters for the frame. Parameters will be merged in current parameter + * set. + * @param {Object} options Available parameters: + * {String | function} [className] + * {EventBus} [eventBus] + * {String | Number | function} [left] + * {String | Number | function} [top] + * {String | Number | function} [width] + * {String | Number | function} [height] */ -Group.prototype.getContainer = function () { - return this.parent.getContainer(); +Component.prototype.setOptions = function setOptions(options) { + if (options) { + util.extend(this.options, options); + + if (this.controller) { + this.requestRepaint(); + this.requestReflow(); + } + } }; /** - * Set item set for the group. The group will create a view on the itemset, - * filtered by the groups id. - * @param {DataSet | DataView} items + * Get an option value by name + * The function will first check this.options object, and else will check + * this.defaultOptions. + * @param {String} name + * @return {*} value */ -Group.prototype.setItems = function setItems(items) { - if (this.itemset) { - // remove current item set - this.itemset.hide(); - this.itemset.setItems(); - - this.parent.controller.remove(this.itemset); - this.itemset = null; +Component.prototype.getOption = function getOption(name) { + var value; + if (this.options) { + value = this.options[name]; } + if (value === undefined && this.defaultOptions) { + value = this.defaultOptions[name]; + } + return value; +}; - if (items) { - var groupId = this.groupId; - - var itemsetOptions = Object.create(this.options); - this.itemset = new ItemSet(this, null, itemsetOptions); - this.itemset.setRange(this.parent.range); - - this.view = new DataView(items, { - filter: function (item) { - return item.group == groupId; - } - }); - this.itemset.setItems(this.view); +/** + * Get the container element of the component, which can be used by a child to + * add its own widgets. Not all components do have a container for childs, in + * that case null is returned. + * @returns {HTMLElement | null} container + */ +// TODO: get rid of the getContainer and getFrame methods, provide these via the options +Component.prototype.getContainer = function getContainer() { + // should be implemented by the component + return null; +}; - this.parent.controller.add(this.itemset); - } +/** + * Get the frame element of the component, the outer HTML DOM element. + * @returns {HTMLElement | null} frame + */ +Component.prototype.getFrame = function getFrame() { + return this.frame; }; /** - * Repaint the item + * Repaint the component * @return {Boolean} changed */ -Group.prototype.repaint = function repaint() { +Component.prototype.repaint = function repaint() { + // should be implemented by the component return false; }; /** - * Reflow the item + * Reflow the component * @return {Boolean} resized */ -Group.prototype.reflow = function reflow() { - var changed = 0, - update = util.updateProperty; +Component.prototype.reflow = function reflow() { + // should be implemented by the component + return false; +}; - changed += update(this, 'top', this.itemset ? this.itemset.top : 0); - changed += update(this, 'height', this.itemset ? this.itemset.height : 0); +/** + * Hide the component from the DOM + * @return {Boolean} changed + */ +Component.prototype.hide = function hide() { + if (this.frame && this.frame.parentNode) { + this.frame.parentNode.removeChild(this.frame); + return true; + } + else { + return false; + } +}; - // TODO: reckon with the height of the group label +/** + * Show the component in the DOM (when not already visible). + * A repaint will be executed when the component is not visible + * @return {Boolean} changed + */ +Component.prototype.show = function show() { + if (!this.frame || !this.frame.parentNode) { + return this.repaint(); + } + else { + return false; + } +}; - if (this.label) { - var inner = this.label.firstChild; - changed += update(this.props.label, 'width', inner.clientWidth); - changed += update(this.props.label, 'height', inner.clientHeight); +/** + * Request a repaint. The controller will schedule a repaint + */ +Component.prototype.requestRepaint = function requestRepaint() { + if (this.controller) { + this.controller.requestRepaint(); } else { - changed += update(this.props.label, 'width', 0); - changed += update(this.props.label, 'height', 0); + throw new Error('Cannot request a repaint: no controller configured'); + // TODO: just do a repaint when no parent is configured? } +}; - return (changed > 0); +/** + * Request a reflow. The controller will schedule a reflow + */ +Component.prototype.requestReflow = function requestReflow() { + if (this.controller) { + this.controller.requestReflow(); + } + else { + throw new Error('Cannot request a reflow: no controller configured'); + // TODO: just do a reflow when no parent is configured? + } }; /** - * An GroupSet holds a set of groups - * @param {Component} parent + * A panel can contain components + * @param {Component} [parent] * @param {Component[]} [depends] Components on which this components depends * (except for the parent) - * @param {Object} [options] See GroupSet.setOptions for the available - * options. - * @constructor GroupSet - * @extends Panel + * @param {Object} [options] Available parameters: + * {String | Number | function} [left] + * {String | Number | function} [top] + * {String | Number | function} [width] + * {String | Number | function} [height] + * {String | function} [className] + * @constructor Panel + * @extends Component */ -function GroupSet(parent, depends, options) { +function Panel(parent, depends, options) { this.id = util.randomUUID(); this.parent = parent; this.depends = depends; this.options = options || {}; - - this.range = null; // Range or Object {start: number, end: number} - this.itemsData = null; // DataSet with items - this.groupsData = null; // DataSet with groups - - this.groups = {}; // map with groups - - this.dom = {}; - this.props = { - labels: { - width: 0 - } - }; - - // TODO: implement right orientation of the labels - - // changes in groups are queued key/value map containing id/action - this.queue = {}; - - var me = this; - this.listeners = { - 'add': function (event, params) { - me._onAdd(params.items); - }, - 'update': function (event, params) { - me._onUpdate(params.items); - }, - 'remove': function (event, params) { - me._onRemove(params.items); - } - }; } -GroupSet.prototype = new Panel(); +Panel.prototype = new Component(); /** - * Set options for the GroupSet. Existing options will be extended/overwritten. - * @param {Object} [options] The following options are available: - * {String | function} groupsOrder - * TODO: describe options + * Set options. Will extend the current options. + * @param {Object} [options] Available parameters: + * {String | function} [className] + * {String | Number | function} [left] + * {String | Number | function} [top] + * {String | Number | function} [width] + * {String | Number | function} [height] */ -GroupSet.prototype.setOptions = Component.prototype.setOptions; +Panel.prototype.setOptions = Component.prototype.setOptions; -GroupSet.prototype.setRange = function (range) { - // TODO: implement setRange +/** + * Get the container element of the panel, which can be used by a child to + * add its own widgets. + * @returns {HTMLElement} container + */ +Panel.prototype.getContainer = function () { + return this.frame; }; /** - * Set items - * @param {vis.DataSet | null} items + * Repaint the component + * @return {Boolean} changed */ -GroupSet.prototype.setItems = function setItems(items) { - this.itemsData = items; +Panel.prototype.repaint = function () { + var changed = 0, + update = util.updateProperty, + asSize = util.option.asSize, + options = this.options, + frame = this.frame; + if (!frame) { + frame = document.createElement('div'); + frame.className = 'panel'; - for (var id in this.groups) { - if (this.groups.hasOwnProperty(id)) { - var group = this.groups[id]; - group.setItems(items); + var className = options.className; + if (className) { + if (typeof className == 'function') { + util.addClassName(frame, String(className())); + } + else { + util.addClassName(frame, String(className)); + } + } + + this.frame = frame; + changed += 1; + } + if (!frame.parentNode) { + if (!this.parent) { + throw new Error('Cannot repaint panel: no parent attached'); + } + var parentContainer = this.parent.getContainer(); + if (!parentContainer) { + throw new Error('Cannot repaint panel: parent has no container element'); } + parentContainer.appendChild(frame); + changed += 1; } -}; -/** - * Get items - * @return {vis.DataSet | null} items - */ -GroupSet.prototype.getItems = function getItems() { - return this.itemsData; -}; + changed += update(frame.style, 'top', asSize(options.top, '0px')); + changed += update(frame.style, 'left', asSize(options.left, '0px')); + changed += update(frame.style, 'width', asSize(options.width, '100%')); + changed += update(frame.style, 'height', asSize(options.height, '100%')); -/** - * Set range (start and end). - * @param {Range | Object} range A Range or an object containing start and end. - */ -GroupSet.prototype.setRange = function setRange(range) { - this.range = range; + return (changed > 0); }; /** - * Set groups - * @param {vis.DataSet} groups + * Reflow the component + * @return {Boolean} resized */ -GroupSet.prototype.setGroups = function setGroups(groups) { - var me = this, - ids; - - // unsubscribe from current dataset - if (this.groupsData) { - util.forEach(this.listeners, function (callback, event) { - me.groupsData.unsubscribe(event, callback); - }); - - // remove all drawn groups - ids = this.groupsData.getIds(); - this._onRemove(ids); - } - - // replace the dataset - if (!groups) { - this.groupsData = null; - } - else if (groups instanceof DataSet) { - this.groupsData = groups; - } - else { - this.groupsData = new DataSet({ - convert: { - start: 'Date', - end: 'Date' - } - }); - this.groupsData.add(groups); - } - - if (this.groupsData) { - // subscribe to new dataset - var id = this.id; - util.forEach(this.listeners, function (callback, event) { - me.groupsData.subscribe(event, callback, id); - }); +Panel.prototype.reflow = function () { + var changed = 0, + update = util.updateProperty, + frame = this.frame; - // draw all new groups - ids = this.groupsData.getIds(); - this._onAdd(ids); + if (frame) { + changed += update(this, 'top', frame.offsetTop); + changed += update(this, 'left', frame.offsetLeft); + changed += update(this, 'width', frame.offsetWidth); + changed += update(this, 'height', frame.offsetHeight); + } + else { + changed += 1; } + + return (changed > 0); }; /** - * Get groups - * @return {vis.DataSet | null} groups + * A root panel can hold components. The root panel must be initialized with + * a DOM element as container. + * @param {HTMLElement} container + * @param {Object} [options] Available parameters: see RootPanel.setOptions. + * @constructor RootPanel + * @extends Panel */ -GroupSet.prototype.getGroups = function getGroups() { - return this.groupsData; -}; +function RootPanel(container, options) { + this.id = util.randomUUID(); + this.container = container; + + this.options = options || {}; + this.defaultOptions = { + autoResize: true + }; + + this.listeners = {}; // event listeners +} + +RootPanel.prototype = new Panel(); + +/** + * Set options. Will extend the current options. + * @param {Object} [options] Available parameters: + * {String | function} [className] + * {String | Number | function} [left] + * {String | Number | function} [top] + * {String | Number | function} [width] + * {String | Number | function} [height] + * {Boolean | function} [autoResize] + */ +RootPanel.prototype.setOptions = Component.prototype.setOptions; /** * Repaint the component * @return {Boolean} changed */ -GroupSet.prototype.repaint = function repaint() { +RootPanel.prototype.repaint = function () { var changed = 0, - i, id, group, label, update = util.updateProperty, asSize = util.option.asSize, - asElement = util.option.asElement, options = this.options, - frame = this.dom.frame, - labels = this.dom.labels; + frame = this.frame; - // create frame - if (!this.parent) { - throw new Error('Cannot repaint groupset: no parent attached'); - } - var parentContainer = this.parent.getContainer(); - if (!parentContainer) { - throw new Error('Cannot repaint groupset: parent has no container element'); - } if (!frame) { frame = document.createElement('div'); - frame.className = 'groupset'; - this.dom.frame = frame; + frame.className = 'vis timeline rootpanel'; var className = options.className; if (className) { util.addClassName(frame, util.option.asString(className)); } + this.frame = frame; + changed += 1; } if (!frame.parentNode) { - parentContainer.appendChild(frame); - changed += 1; - } - - // create labels - var labelContainer = asElement(options.labelContainer); - if (!labelContainer) { - throw new Error('Cannot repaint groupset: option "labelContainer" not defined'); - } - if (!labels) { - labels = document.createElement('div'); - labels.className = 'labels'; - //frame.appendChild(labels); - this.dom.labels = labels; - } - if (!labels.parentNode || labels.parentNode != labelContainer) { - if (labels.parentNode) { - labels.parentNode.removeChild(labels.parentNode); + if (!this.container) { + throw new Error('Cannot repaint root panel: no container attached'); } - labelContainer.appendChild(labels); + this.container.appendChild(frame); + changed += 1; } - // reposition frame - changed += update(frame.style, 'height', asSize(options.height, this.height + 'px')); changed += update(frame.style, 'top', asSize(options.top, '0px')); changed += update(frame.style, 'left', asSize(options.left, '0px')); changed += update(frame.style, 'width', asSize(options.width, '100%')); + changed += update(frame.style, 'height', asSize(options.height, '100%')); - // reposition labels - changed += update(labels.style, 'top', asSize(options.top, '0px')); - - var me = this, - queue = this.queue, - groups = this.groups, - groupsData = this.groupsData; + this._updateEventEmitters(); + this._updateWatch(); - // show/hide added/changed/removed groups - var ids = Object.keys(queue); - if (ids.length) { - ids.forEach(function (id) { - var action = queue[id]; - var group = groups[id]; + return (changed > 0); +}; - //noinspection FallthroughInSwitchStatementJS - switch (action) { - case 'add': - case 'update': - if (!group) { - var groupOptions = Object.create(me.options); - group = new Group(me, id, groupOptions); - group.setItems(me.itemsData); // attach items data - groups[id] = group; +/** + * Reflow the component + * @return {Boolean} resized + */ +RootPanel.prototype.reflow = function () { + var changed = 0, + update = util.updateProperty, + frame = this.frame; - me.controller.add(group); - } + if (frame) { + changed += update(this, 'top', frame.offsetTop); + changed += update(this, 'left', frame.offsetLeft); + changed += update(this, 'width', frame.offsetWidth); + changed += update(this, 'height', frame.offsetHeight); + } + else { + changed += 1; + } - // TODO: update group data - group.data = groupsData.get(id); + return (changed > 0); +}; - delete queue[id]; - break; +/** + * Update watching for resize, depending on the current option + * @private + */ +RootPanel.prototype._updateWatch = function () { + var autoResize = this.getOption('autoResize'); + if (autoResize) { + this._watch(); + } + else { + this._unwatch(); + } +}; - case 'remove': - if (group) { - group.setItems(); // detach items data - delete groups[id]; +/** + * Watch for changes in the size of the frame. On resize, the Panel will + * automatically redraw itself. + * @private + */ +RootPanel.prototype._watch = function () { + var me = this; - me.controller.remove(group); - } + this._unwatch(); - // update lists - delete queue[id]; - break; + var checkSize = function () { + var autoResize = me.getOption('autoResize'); + if (!autoResize) { + // stop watching when the option autoResize is changed to false + me._unwatch(); + return; + } - default: - console.log('Error: unknown action "' + action + '"'); + if (me.frame) { + // check whether the frame is resized + if ((me.frame.clientWidth != me.width) || + (me.frame.clientHeight != me.height)) { + me.requestReflow(); } - }); - - // the groupset depends on each of the groups - //this.depends = this.groups; // TODO: gives a circular reference through the parent - - // TODO: apply dependencies of the groupset - - // update the top positions of the groups in the correct order - var orderedGroups = this.groupsData.getIds({ - order: this.options.groupsOrder - }); - for (i = 0; i < orderedGroups.length; i++) { - (function (group, prevGroup) { - var top = 0; - if (prevGroup) { - top = function () { - // TODO: top must reckon with options.maxHeight - return prevGroup.top + prevGroup.height; - } - } - group.setOptions({ - top: top - }); - })(groups[orderedGroups[i]], groups[orderedGroups[i - 1]]); } + }; - // (re)create the labels - while (labels.firstChild) { - labels.removeChild(labels.firstChild); - } - for (i = 0; i < orderedGroups.length; i++) { - id = orderedGroups[i]; - label = this._createLabel(id); - labels.appendChild(label); - } + // TODO: automatically cleanup the event listener when the frame is deleted + util.addEventListener(window, 'resize', checkSize); - changed++; + this.watchTimer = setInterval(checkSize, 1000); +}; + +/** + * Stop watching for a resize of the frame. + * @private + */ +RootPanel.prototype._unwatch = function () { + if (this.watchTimer) { + clearInterval(this.watchTimer); + this.watchTimer = undefined; } - // reposition the labels - // TODO: labels are not displayed correctly when orientation=='top' - // TODO: width of labelPanel is not immediately updated on a change in groups - for (id in groups) { - if (groups.hasOwnProperty(id)) { - group = groups[id]; - label = group.label; - if (label) { - label.style.top = group.top + 'px'; - label.style.height = group.height + 'px'; - } - } + // TODO: remove event listener on window.resize +}; + +/** + * Event handler + * @param {String} event name of the event, for example 'click', 'mousemove' + * @param {function} callback callback handler, invoked with the raw HTML Event + * as parameter. + */ +RootPanel.prototype.on = function (event, callback) { + // register the listener at this component + var arr = this.listeners[event]; + if (!arr) { + arr = []; + this.listeners[event] = arr; } + arr.push(callback); - return (changed > 0); + this._updateEventEmitters(); }; /** - * Create a label for group with given id - * @param {Number} id - * @return {Element} label + * Update the event listeners for all event emitters * @private */ -GroupSet.prototype._createLabel = function(id) { - var group = this.groups[id]; - var label = document.createElement('div'); - label.className = 'label'; - var inner = document.createElement('div'); - inner.className = 'inner'; - label.appendChild(inner); +RootPanel.prototype._updateEventEmitters = function () { + if (this.listeners) { + var me = this; + util.forEach(this.listeners, function (listeners, event) { + if (!me.emitters) { + me.emitters = {}; + } + if (!(event in me.emitters)) { + // create event + var frame = me.frame; + if (frame) { + //console.log('Created a listener for event ' + event + ' on component ' + me.id); // TODO: cleanup logging + var callback = function(event) { + listeners.forEach(function (listener) { + // TODO: filter on event target! + listener(event); + }); + }; + me.emitters[event] = callback; + util.addEventListener(frame, event, callback); + } + } + }); - var content = group.data && group.data.content; - if (content instanceof Element) { - inner.appendChild(content); - } - else if (content != undefined) { - inner.innerHTML = content; + // TODO: be able to delete event listeners + // TODO: be able to move event listeners to a parent when available } +}; - var className = group.data && group.data.className; - if (className) { - util.addClassName(label, className); - } +/** + * A horizontal time axis + * @param {Component} parent + * @param {Component[]} [depends] Components on which this components depends + * (except for the parent) + * @param {Object} [options] See TimeAxis.setOptions for the available + * options. + * @constructor TimeAxis + * @extends Component + */ +function TimeAxis (parent, depends, options) { + this.id = util.randomUUID(); + this.parent = parent; + this.depends = depends; - group.label = label; // TODO: not so nice, parking labels in the group this way!!! + this.dom = { + majorLines: [], + majorTexts: [], + minorLines: [], + minorTexts: [], + redundant: { + majorLines: [], + majorTexts: [], + minorLines: [], + minorTexts: [] + } + }; + this.props = { + range: { + start: 0, + end: 0, + minimumStep: 0 + }, + lineTop: 0 + }; - return label; + this.options = options || {}; + this.defaultOptions = { + orientation: 'bottom', // supported: 'top', 'bottom' + // TODO: implement timeaxis orientations 'left' and 'right' + showMinorLabels: true, + showMajorLabels: true + }; + + this.conversion = null; + this.range = null; +} + +TimeAxis.prototype = new Component(); + +// TODO: comment options +TimeAxis.prototype.setOptions = Component.prototype.setOptions; + +/** + * Set a range (start and end) + * @param {Range | Object} range A Range or an object containing start and end. + */ +TimeAxis.prototype.setRange = function (range) { + if (!(range instanceof Range) && (!range || !range.start || !range.end)) { + throw new TypeError('Range must be an instance of Range, ' + + 'or an object containing start and end.'); + } + this.range = range; }; /** - * Get container element - * @return {HTMLElement} container + * Convert a position on screen (pixels) to a datetime + * @param {int} x Position on the screen in pixels + * @return {Date} time The datetime the corresponds with given position x */ -GroupSet.prototype.getContainer = function getContainer() { - return this.dom.frame; +TimeAxis.prototype.toTime = function(x) { + var conversion = this.conversion; + return new Date(x / conversion.factor + conversion.offset); }; /** - * Get the width of the group labels - * @return {Number} width + * Convert a datetime (Date object) into a position on the screen + * @param {Date} time A date + * @return {int} x The position on the screen in pixels which corresponds + * with the given date. + * @private */ -GroupSet.prototype.getLabelsWidth = function getContainer() { - return this.props.labels.width; +TimeAxis.prototype.toScreen = function(time) { + var conversion = this.conversion; + return (time.valueOf() - conversion.offset) * conversion.factor; }; /** - * Reflow the component - * @return {Boolean} resized + * Repaint the component + * @return {Boolean} changed */ -GroupSet.prototype.reflow = function reflow() { +TimeAxis.prototype.repaint = function () { var changed = 0, - id, group, - options = this.options, update = util.updateProperty, - asNumber = util.option.asNumber, asSize = util.option.asSize, - frame = this.dom.frame; + options = this.options, + orientation = this.getOption('orientation'), + props = this.props, + step = this.step; - if (frame) { - var maxHeight = asNumber(options.maxHeight); - var fixedHeight = (asSize(options.height) != null); - var height; - if (fixedHeight) { - height = frame.offsetHeight; - } - else { - // height is not specified, calculate the sum of the height of all groups - height = 0; + var frame = this.frame; + if (!frame) { + frame = document.createElement('div'); + this.frame = frame; + changed += 1; + } + frame.className = 'axis ' + orientation; + // TODO: custom className? - for (id in this.groups) { - if (this.groups.hasOwnProperty(id)) { - group = this.groups[id]; - height += group.height; - } - } + if (!frame.parentNode) { + if (!this.parent) { + throw new Error('Cannot repaint time axis: no parent attached'); } - if (maxHeight != null) { - height = Math.min(height, maxHeight); + var parentContainer = this.parent.getContainer(); + if (!parentContainer) { + throw new Error('Cannot repaint time axis: parent has no container element'); } - changed += update(this, 'height', height); + parentContainer.appendChild(frame); - changed += update(this, 'top', frame.offsetTop); - changed += update(this, 'left', frame.offsetLeft); - changed += update(this, 'width', frame.offsetWidth); + changed += 1; } - // calculate the maximum width of the labels - var width = 0; - for (id in this.groups) { - if (this.groups.hasOwnProperty(id)) { - group = this.groups[id]; - var labelWidth = group.props && group.props.label && group.props.label.width || 0; - width = Math.max(width, labelWidth); + var parent = frame.parentNode; + if (parent) { + var beforeChild = frame.nextSibling; + parent.removeChild(frame); // take frame offline while updating (is almost twice as fast) + + var defaultTop = (orientation == 'bottom' && this.props.parentHeight && this.height) ? + (this.props.parentHeight - this.height) + 'px' : + '0px'; + changed += update(frame.style, 'top', asSize(options.top, defaultTop)); + changed += update(frame.style, 'left', asSize(options.left, '0px')); + changed += update(frame.style, 'width', asSize(options.width, '100%')); + changed += update(frame.style, 'height', asSize(options.height, this.height + 'px')); + + // get characters width and height + this._repaintMeasureChars(); + + if (this.step) { + this._repaintStart(); + + step.first(); + var xFirstMajorLabel = undefined; + var max = 0; + while (step.hasNext() && max < 1000) { + max++; + var cur = step.getCurrent(), + x = this.toScreen(cur), + isMajor = step.isMajor(); + + // TODO: lines must have a width, such that we can create css backgrounds + + if (this.getOption('showMinorLabels')) { + this._repaintMinorText(x, step.getLabelMinor()); + } + + if (isMajor && this.getOption('showMajorLabels')) { + if (x > 0) { + if (xFirstMajorLabel == undefined) { + xFirstMajorLabel = x; + } + this._repaintMajorText(x, step.getLabelMajor()); + } + this._repaintMajorLine(x); + } + else { + this._repaintMinorLine(x); + } + + step.next(); + } + + // create a major label on the left when needed + if (this.getOption('showMajorLabels')) { + var leftTime = this.toTime(0), + leftText = step.getLabelMajor(leftTime), + widthText = leftText.length * (props.majorCharWidth || 10) + 10; // upper bound estimation + + if (xFirstMajorLabel == undefined || widthText < xFirstMajorLabel) { + this._repaintMajorText(0, leftText); + } + } + + this._repaintEnd(); + } + + this._repaintLine(); + + // put frame online again + if (beforeChild) { + parent.insertBefore(frame, beforeChild); + } + else { + parent.appendChild(frame) } } - changed += update(this.props.labels, 'width', width); return (changed > 0); }; /** - * Hide the component from the DOM - * @return {Boolean} changed + * Start a repaint. Move all DOM elements to a redundant list, where they + * can be picked for re-use, or can be cleaned up in the end + * @private */ -GroupSet.prototype.hide = function hide() { - if (this.dom.frame && this.dom.frame.parentNode) { - this.dom.frame.parentNode.removeChild(this.dom.frame); - return true; - } - else { - return false; - } -}; +TimeAxis.prototype._repaintStart = function () { + var dom = this.dom, + redundant = dom.redundant; -/** - * Show the component in the DOM (when not already visible). - * A repaint will be executed when the component is not visible - * @return {Boolean} changed - */ -GroupSet.prototype.show = function show() { - if (!this.dom.frame || !this.dom.frame.parentNode) { - return this.repaint(); - } - else { - return false; - } -}; + redundant.majorLines = dom.majorLines; + redundant.majorTexts = dom.majorTexts; + redundant.minorLines = dom.minorLines; + redundant.minorTexts = dom.minorTexts; -/** - * Handle updated groups - * @param {Number[]} ids - * @private - */ -GroupSet.prototype._onUpdate = function _onUpdate(ids) { - this._toQueue(ids, 'update'); + dom.majorLines = []; + dom.majorTexts = []; + dom.minorLines = []; + dom.minorTexts = []; }; /** - * Handle changed groups - * @param {Number[]} ids + * End a repaint. Cleanup leftover DOM elements in the redundant list * @private */ -GroupSet.prototype._onAdd = function _onAdd(ids) { - this._toQueue(ids, 'add'); +TimeAxis.prototype._repaintEnd = function () { + util.forEach(this.dom.redundant, function (arr) { + while (arr.length) { + var elem = arr.pop(); + if (elem && elem.parentNode) { + elem.parentNode.removeChild(elem); + } + } + }); }; -/** - * Handle removed groups - * @param {Number[]} ids - * @private - */ -GroupSet.prototype._onRemove = function _onRemove(ids) { - this._toQueue(ids, 'remove'); -}; /** - * Put groups in the queue to be added/updated/remove - * @param {Number[]} ids - * @param {String} action can be 'add', 'update', 'remove' + * Create a minor label for the axis at position x + * @param {Number} x + * @param {String} text + * @private */ -GroupSet.prototype._toQueue = function _toQueue(ids, action) { - var queue = this.queue; - ids.forEach(function (id) { - queue[id] = action; - }); +TimeAxis.prototype._repaintMinorText = function (x, text) { + // reuse redundant label + var label = this.dom.redundant.minorTexts.shift(); - if (this.controller) { - //this.requestReflow(); - this.requestRepaint(); + if (!label) { + // create new label + var content = document.createTextNode(''); + label = document.createElement('div'); + label.appendChild(content); + label.className = 'text minor'; + this.frame.appendChild(label); } + this.dom.minorTexts.push(label); + + label.childNodes[0].nodeValue = text; + label.style.left = x + 'px'; + label.style.top = this.props.minorLabelTop + 'px'; + //label.title = title; // TODO: this is a heavy operation }; /** - * Create a timeline visualization - * @param {HTMLElement} container - * @param {vis.DataSet | Array | DataTable} [items] - * @param {Object} [options] See Timeline.setOptions for the available options. - * @constructor + * Create a Major label for the axis at position x + * @param {Number} x + * @param {String} text + * @private */ -function Timeline (container, items, options) { - var me = this; - this.options = util.extend({ - orientation: 'bottom', - min: null, - max: null, - zoomMin: 10, // milliseconds - zoomMax: 1000 * 60 * 60 * 24 * 365 * 10000, // milliseconds - // moveable: true, // TODO: option moveable - // zoomable: true, // TODO: option zoomable - showMinorLabels: true, - showMajorLabels: true, - autoResize: false - }, options); - - // controller - this.controller = new Controller(); +TimeAxis.prototype._repaintMajorText = function (x, text) { + // reuse redundant label + var label = this.dom.redundant.majorTexts.shift(); - // root panel - if (!container) { - throw new Error('No container element provided'); + if (!label) { + // create label + var content = document.createTextNode(text); + label = document.createElement('div'); + label.className = 'text major'; + label.appendChild(content); + this.frame.appendChild(label); } - var rootOptions = Object.create(this.options); - rootOptions.height = function () { - if (me.options.height) { - // fixed height - return me.options.height; - } - else { - // auto height - return me.timeaxis.height + me.content.height; - } - }; - this.rootPanel = new RootPanel(container, rootOptions); - this.controller.add(this.rootPanel); - - // item panel - var itemOptions = Object.create(this.options); - itemOptions.left = function () { - return me.labelPanel.width; - }; - itemOptions.width = function () { - return me.rootPanel.width - me.labelPanel.width; - }; - itemOptions.top = null; - itemOptions.height = null; - this.itemPanel = new Panel(this.rootPanel, [], itemOptions); - this.controller.add(this.itemPanel); - - // label panel - var labelOptions = Object.create(this.options); - labelOptions.top = null; - labelOptions.left = null; - labelOptions.height = null; - labelOptions.width = function () { - if (me.content && typeof me.content.getLabelsWidth === 'function') { - return me.content.getLabelsWidth(); - } - else { - return 0; - } - }; - this.labelPanel = new Panel(this.rootPanel, [], labelOptions); - this.controller.add(this.labelPanel); - - // range - var now = moment().hours(0).minutes(0).seconds(0).milliseconds(0); - this.range = new Range({ - start: now.clone().add('days', -3).valueOf(), - end: now.clone().add('days', 4).valueOf() - }); - /* TODO: fix range options - var rangeOptions = Object.create(this.options); - this.range = new Range(rangeOptions); - this.range.setRange( - now.clone().add('days', -3).valueOf(), - now.clone().add('days', 4).valueOf() - ); - */ - // TODO: reckon with options moveable and zoomable - this.range.subscribe(this.rootPanel, 'move', 'horizontal'); - this.range.subscribe(this.rootPanel, 'zoom', 'horizontal'); - this.range.on('rangechange', function () { - var force = true; - me.controller.requestReflow(force); - }); - this.range.on('rangechanged', function () { - var force = true; - me.controller.requestReflow(force); - }); - - // TODO: put the listeners in setOptions, be able to dynamically change with options moveable and zoomable - - // time axis - var timeaxisOptions = Object.create(rootOptions); - timeaxisOptions.range = this.range; - timeaxisOptions.left = null; - timeaxisOptions.top = null; - timeaxisOptions.width = '100%'; - timeaxisOptions.height = null; - this.timeaxis = new TimeAxis(this.itemPanel, [], timeaxisOptions); - this.timeaxis.setRange(this.range); - this.controller.add(this.timeaxis); - - // create itemset or groupset - this.setGroups(null); + this.dom.majorTexts.push(label); - this.itemsData = null; // DataSet - this.groupsData = null; // DataSet + label.childNodes[0].nodeValue = text; + label.style.top = this.props.majorLabelTop + 'px'; + label.style.left = x + 'px'; + //label.title = title; // TODO: this is a heavy operation +}; - // set data - if (items) { - this.setItems(items); +/** + * Create a minor line for the axis at position x + * @param {Number} x + * @private + */ +TimeAxis.prototype._repaintMinorLine = function (x) { + // reuse redundant line + var line = this.dom.redundant.minorLines.shift(); + + if (!line) { + // create vertical line + line = document.createElement('div'); + line.className = 'grid vertical minor'; + this.frame.appendChild(line); } -} + this.dom.minorLines.push(line); + + var props = this.props; + line.style.top = props.minorLineTop + 'px'; + line.style.height = props.minorLineHeight + 'px'; + line.style.left = (x - props.minorLineWidth / 2) + 'px'; +}; /** - * Set options - * @param {Object} options TODO: describe the available options + * Create a Major line for the axis at position x + * @param {Number} x + * @private */ -Timeline.prototype.setOptions = function (options) { - if (options) { - util.extend(this.options, options); - } +TimeAxis.prototype._repaintMajorLine = function (x) { + // reuse redundant line + var line = this.dom.redundant.majorLines.shift(); - // TODO: apply range min,max + if (!line) { + // create vertical line + line = document.createElement('DIV'); + line.className = 'grid vertical major'; + this.frame.appendChild(line); + } + this.dom.majorLines.push(line); - this.controller.reflow(); - this.controller.repaint(); + var props = this.props; + line.style.top = props.majorLineTop + 'px'; + line.style.left = (x - props.majorLineWidth / 2) + 'px'; + line.style.height = props.majorLineHeight + 'px'; }; + /** - * Set items - * @param {vis.DataSet | Array | DataTable | null} items + * Repaint the horizontal line for the axis + * @private */ -Timeline.prototype.setItems = function(items) { - var initialLoad = (this.itemsData == null); +TimeAxis.prototype._repaintLine = function() { + var line = this.dom.line, + frame = this.frame, + options = this.options; - // convert to type DataSet when needed - var newItemSet; - if (!items) { - newItemSet = null; - } - else if (items instanceof DataSet) { - newItemSet = items; + // line before all axis elements + if (this.getOption('showMinorLabels') || this.getOption('showMajorLabels')) { + if (line) { + // put this line at the end of all childs + frame.removeChild(line); + frame.appendChild(line); + } + else { + // create the axis line + line = document.createElement('div'); + line.className = 'grid horizontal major'; + frame.appendChild(line); + this.dom.line = line; + } + + line.style.top = this.props.lineTop + 'px'; } - if (!(items instanceof DataSet)) { - newItemSet = new DataSet({ - convert: { - start: 'Date', - end: 'Date' - } - }); - newItemSet.add(items); + else { + if (line && axis.parentElement) { + frame.removeChild(axis.line); + delete this.dom.line; + } } +}; - // set items - this.itemsData = newItemSet; - this.content.setItems(newItemSet); +/** + * Create characters used to determine the size of text on the axis + * @private + */ +TimeAxis.prototype._repaintMeasureChars = function () { + // calculate the width and height of a single character + // this is used to calculate the step size, and also the positioning of the + // axis + var dom = this.dom, + text; - if (initialLoad && (this.options.start == undefined || this.options.end == undefined)) { - // apply the data range as range - var dataRange = this.getItemRange(); + if (!dom.measureCharMinor) { + text = document.createTextNode('0'); + var measureCharMinor = document.createElement('DIV'); + measureCharMinor.className = 'text minor measure'; + measureCharMinor.appendChild(text); + this.frame.appendChild(measureCharMinor); - // add 5% on both sides - var min = dataRange.min; - var max = dataRange.max; - if (min != null && max != null) { - var interval = (max.valueOf() - min.valueOf()); - if (interval <= 0) { - // prevent an empty interval - interval = 24 * 60 * 60 * 1000; // 1 day - } - min = new Date(min.valueOf() - interval * 0.05); - max = new Date(max.valueOf() + interval * 0.05); - } + dom.measureCharMinor = measureCharMinor; + } - // override specified start and/or end date - if (this.options.start != undefined) { - min = new Date(this.options.start.valueOf()); - } - if (this.options.end != undefined) { - max = new Date(this.options.end.valueOf()); - } + if (!dom.measureCharMajor) { + text = document.createTextNode('0'); + var measureCharMajor = document.createElement('DIV'); + measureCharMajor.className = 'text major measure'; + measureCharMajor.appendChild(text); + this.frame.appendChild(measureCharMajor); - // apply range if there is a min or max available - if (min != null || max != null) { - this.range.setRange(min, max); - } + dom.measureCharMajor = measureCharMajor; } }; /** - * Set groups - * @param {vis.DataSet | Array | DataTable} groups + * Reflow the component + * @return {Boolean} resized */ -Timeline.prototype.setGroups = function(groups) { - var me = this; - this.groupsData = groups; +TimeAxis.prototype.reflow = function () { + var changed = 0, + update = util.updateProperty, + frame = this.frame, + range = this.range; - // switch content type between ItemSet or GroupSet when needed - var type = this.groupsData ? GroupSet : ItemSet; - if (!(this.content instanceof type)) { - // remove old content set - if (this.content) { - this.content.hide(); - if (this.content.setItems) { - this.content.setItems(); // disconnect from items - } - if (this.content.setGroups) { - this.content.setGroups(); // disconnect from groups - } - this.controller.remove(this.content); - } + if (!range) { + throw new Error('Cannot repaint time axis: no range configured'); + } - // create new content set - var options = Object.create(this.options); - util.extend(options, { - top: function () { - if (me.options.orientation == 'top') { - return me.timeaxis.height; - } - else { - return me.itemPanel.height - me.timeaxis.height - me.content.height; - } - }, - left: null, - width: '100%', - height: function () { - if (me.options.height) { - return me.itemPanel.height - me.timeaxis.height; - } - else { - return null; - } - }, - maxHeight: function () { - if (me.options.maxHeight) { - if (!util.isNumber(me.options.maxHeight)) { - throw new TypeError('Number expected for property maxHeight'); - } - return me.options.maxHeight - me.timeaxis.height; - } - else { - return null; - } - }, - labelContainer: function () { - return me.labelPanel.getContainer(); - } - }); - this.content = new type(this.itemPanel, [this.timeaxis], options); - if (this.content.setRange) { - this.content.setRange(this.range); + if (frame) { + changed += update(this, 'top', frame.offsetTop); + changed += update(this, 'left', frame.offsetLeft); + + // calculate size of a character + var props = this.props, + showMinorLabels = this.getOption('showMinorLabels'), + showMajorLabels = this.getOption('showMajorLabels'), + measureCharMinor = this.dom.measureCharMinor, + measureCharMajor = this.dom.measureCharMajor; + if (measureCharMinor) { + props.minorCharHeight = measureCharMinor.clientHeight; + props.minorCharWidth = measureCharMinor.clientWidth; } - if (this.content.setItems) { - this.content.setItems(this.itemsData); + if (measureCharMajor) { + props.majorCharHeight = measureCharMajor.clientHeight; + props.majorCharWidth = measureCharMajor.clientWidth; } - if (this.content.setGroups) { - this.content.setGroups(this.groupsData); + + var parentHeight = frame.parentNode ? frame.parentNode.offsetHeight : 0; + if (parentHeight != props.parentHeight) { + props.parentHeight = parentHeight; + changed += 1; + } + switch (this.getOption('orientation')) { + case 'bottom': + props.minorLabelHeight = showMinorLabels ? props.minorCharHeight : 0; + props.majorLabelHeight = showMajorLabels ? props.majorCharHeight : 0; + + props.minorLabelTop = 0; + props.majorLabelTop = props.minorLabelTop + props.minorLabelHeight; + + props.minorLineTop = -this.top; + props.minorLineHeight = Math.max(this.top + props.majorLabelHeight, 0); + props.minorLineWidth = 1; // TODO: really calculate width + + props.majorLineTop = -this.top; + props.majorLineHeight = Math.max(this.top + props.minorLabelHeight + props.majorLabelHeight, 0); + props.majorLineWidth = 1; // TODO: really calculate width + + props.lineTop = 0; + + break; + + case 'top': + props.minorLabelHeight = showMinorLabels ? props.minorCharHeight : 0; + props.majorLabelHeight = showMajorLabels ? props.majorCharHeight : 0; + + props.majorLabelTop = 0; + props.minorLabelTop = props.majorLabelTop + props.majorLabelHeight; + + props.minorLineTop = props.minorLabelTop; + props.minorLineHeight = Math.max(parentHeight - props.majorLabelHeight - this.top); + props.minorLineWidth = 1; // TODO: really calculate width + + props.majorLineTop = 0; + props.majorLineHeight = Math.max(parentHeight - this.top); + props.majorLineWidth = 1; // TODO: really calculate width + + props.lineTop = props.majorLabelHeight + props.minorLabelHeight; + + break; + + default: + throw new Error('Unkown orientation "' + this.getOption('orientation') + '"'); } - this.controller.add(this.content); + + var height = props.minorLabelHeight + props.majorLabelHeight; + changed += update(this, 'width', frame.offsetWidth); + changed += update(this, 'height', height); + + // calculate range and step + this._updateConversion(); + + var start = util.convert(range.start, 'Date'), + end = util.convert(range.end, 'Date'), + minimumStep = this.toTime((props.minorCharWidth || 10) * 5) - this.toTime(0); + this.step = new TimeStep(start, end, minimumStep); + changed += update(props.range, 'start', start.valueOf()); + changed += update(props.range, 'end', end.valueOf()); + changed += update(props.range, 'minimumStep', minimumStep.valueOf()); } + + return (changed > 0); }; /** - * Get the data range of the item set. - * @returns {{min: Date, max: Date}} range A range with a start and end Date. - * When no minimum is found, min==null - * When no maximum is found, max==null + * Calculate the factor and offset to convert a position on screen to the + * corresponding date and vice versa. + * After the method _updateConversion is executed once, the methods toTime + * and toScreen can be used. + * @private */ -Timeline.prototype.getItemRange = function getItemRange() { - // calculate min from start filed - var itemsData = this.itemsData, - min = null, - max = null; - - if (itemsData) { - // calculate the minimum value of the field 'start' - var minItem = itemsData.min('start'); - min = minItem ? minItem.start.valueOf() : null; - - // calculate maximum value of fields 'start' and 'end' - var maxStartItem = itemsData.max('start'); - if (maxStartItem) { - max = maxStartItem.start.valueOf(); - } - var maxEndItem = itemsData.max('end'); - if (maxEndItem) { - if (max == null) { - max = maxEndItem.end.valueOf(); - } - else { - max = Math.max(max, maxEndItem.end.valueOf()); - } - } +TimeAxis.prototype._updateConversion = function() { + var range = this.range; + if (!range) { + throw new Error('No range configured'); } - return { - min: (min != null) ? new Date(min) : null, - max: (max != null) ? new Date(max) : null - }; + if (range.conversion) { + this.conversion = range.conversion(this.width); + } + else { + this.conversion = Range.conversion(range.start, range.end, this.width); + } }; -(function(exports) { - /** - * Parse a text source containing data in DOT language into a JSON object. - * The object contains two lists: one with nodes and one with edges. - * - * DOT language reference: http://www.graphviz.org/doc/info/lang.html - * - * @param {String} data Text containing a graph in DOT-notation - * @return {Object} graph An object containing two parameters: - * {Object[]} nodes - * {Object[]} edges - */ - function parseDOT (data) { - dot = data; - return parseGraph(); - } +/** + * An ItemSet holds a set of items and ranges which can be displayed in a + * range. The width is determined by the parent of the ItemSet, and the height + * is determined by the size of the items. + * @param {Component} parent + * @param {Component[]} [depends] Components on which this components depends + * (except for the parent) + * @param {Object} [options] See ItemSet.setOptions for the available + * options. + * @constructor ItemSet + * @extends Panel + */ +// TODO: improve performance by replacing all Array.forEach with a for loop +function ItemSet(parent, depends, options) { + this.id = util.randomUUID(); + this.parent = parent; + this.depends = depends; - // token types enumeration - var TOKENTYPE = { - NULL : 0, - DELIMITER : 1, - IDENTIFIER: 2, - UNKNOWN : 3 + // one options object is shared by this itemset and all its items + this.options = options || {}; + this.defaultOptions = { + type: 'box', + align: 'center', + orientation: 'bottom', + margin: { + axis: 20, + item: 10 + }, + padding: 5 }; - // map with all delimiters - var DELIMITERS = { - '{': true, - '}': true, - '[': true, - ']': true, - ';': true, - '=': true, - ',': true, + this.dom = {}; - '->': true, - '--': true - }; + var me = this; + this.itemsData = null; // DataSet + this.range = null; // Range or Object {start: number, end: number} - var dot = ''; // current dot file - var index = 0; // current index in dot file - var c = ''; // current token character in expr - var token = ''; // current token - var tokenType = TOKENTYPE.NULL; // type of the token + this.listeners = { + 'add': function (event, params, senderId) { + if (senderId != me.id) { + me._onAdd(params.items); + } + }, + 'update': function (event, params, senderId) { + if (senderId != me.id) { + me._onUpdate(params.items); + } + }, + 'remove': function (event, params, senderId) { + if (senderId != me.id) { + me._onRemove(params.items); + } + } + }; - /** - * Get the first character from the dot file. - * The character is stored into the char c. If the end of the dot file is - * reached, the function puts an empty string in c. - */ - function first() { - index = 0; - c = dot.charAt(0); - } + this.items = {}; // object with an Item for every data item + this.queue = {}; // queue with id/actions: 'add', 'update', 'delete' + this.stack = new Stack(this, Object.create(this.options)); + this.conversion = null; - /** - * Get the next character from the dot file. - * The character is stored into the char c. If the end of the dot file is - * reached, the function puts an empty string in c. - */ - function next() { - index++; - c = dot.charAt(index); - } + // TODO: ItemSet should also attach event listeners for rangechange and rangechanged, like timeaxis +} - /** - * Preview the next character from the dot file. - * @return {String} cNext - */ - function nextPreview() { - return dot.charAt(index + 1); - } +ItemSet.prototype = new Panel(); - /** - * Test whether given character is alphabetic or numeric - * @param {String} c - * @return {Boolean} isAlphaNumeric - */ - var regexAlphaNumeric = /[a-zA-Z_0-9.:#]/; - function isAlphaNumeric(c) { - return regexAlphaNumeric.test(c); - } +// available item types will be registered here +ItemSet.types = { + box: ItemBox, + range: ItemRange, + point: ItemPoint +}; - /** - * Merge all properties of object b into object b - * @param {Object} a - * @param {Object} b - * @return {Object} a - */ - function merge (a, b) { - if (!a) { - a = {}; - } +/** + * Set options for the ItemSet. Existing options will be extended/overwritten. + * @param {Object} [options] The following options are available: + * {String | function} [className] + * class name for the itemset + * {String} [type] + * Default type for the items. Choose from 'box' + * (default), 'point', or 'range'. The default + * Style can be overwritten by individual items. + * {String} align + * Alignment for the items, only applicable for + * ItemBox. Choose 'center' (default), 'left', or + * 'right'. + * {String} orientation + * Orientation of the item set. Choose 'top' or + * 'bottom' (default). + * {Number} margin.axis + * Margin between the axis and the items in pixels. + * Default is 20. + * {Number} margin.item + * Margin between items in pixels. Default is 10. + * {Number} padding + * Padding of the contents of an item in pixels. + * Must correspond with the items css. Default is 5. + */ +ItemSet.prototype.setOptions = Component.prototype.setOptions; - if (b) { - for (var name in b) { - if (b.hasOwnProperty(name)) { - a[name] = b[name]; - } - } - } - return a; +/** + * Set range (start and end). + * @param {Range | Object} range A Range or an object containing start and end. + */ +ItemSet.prototype.setRange = function setRange(range) { + if (!(range instanceof Range) && (!range || !range.start || !range.end)) { + throw new TypeError('Range must be an instance of Range, ' + + 'or an object containing start and end.'); } + this.range = range; +}; - /** - * Set a value in an object, where the provided parameter name can be a - * path with nested parameters. For example: - * - * var obj = {a: 2}; - * setValue(obj, 'b.c', 3); // obj = {a: 2, b: {c: 3}} - * - * @param {Object} obj - * @param {String} path A parameter name or dot-separated parameter path, - * like "color.highlight.border". - * @param {*} value - */ - function setValue(obj, path, value) { - var keys = path.split('.'); - var o = obj; - while (keys.length) { - var key = keys.shift(); - if (keys.length) { - // this isn't the end point - if (!o[key]) { - o[key] = {}; - } - o = o[key]; - } - else { - // this is the end point - o[key] = value; - } - } - } +/** + * Repaint the component + * @return {Boolean} changed + */ +ItemSet.prototype.repaint = function repaint() { + var changed = 0, + update = util.updateProperty, + asSize = util.option.asSize, + options = this.options, + orientation = this.getOption('orientation'), + defaultOptions = this.defaultOptions, + frame = this.frame; - /** - * Add a node to a graph object. If there is already a node with - * the same id, their attributes will be merged. - * @param {Object} graph - * @param {Object} node - */ - function addNode(graph, node) { - var i, len; - var current = null; + if (!frame) { + frame = document.createElement('div'); + frame.className = 'itemset'; - // find root graph (in case of subgraph) - var graphs = [graph]; // list with all graphs from current graph to root graph - var root = graph; - while (root.parent) { - graphs.push(root.parent); - root = root.parent; + var className = options.className; + if (className) { + util.addClassName(frame, util.option.asString(className)); } - // find existing node (at root level) by its id - if (root.nodes) { - for (i = 0, len = root.nodes.length; i < len; i++) { - if (node.id === root.nodes[i].id) { - current = root.nodes[i]; - break; - } - } - } + // create background panel + var background = document.createElement('div'); + background.className = 'background'; + frame.appendChild(background); + this.dom.background = background; - if (!current) { - // this is a new node - current = { - id: node.id - }; - if (graph.node) { - // clone default attributes - current.attr = merge(current.attr, graph.node); - } - } + // create foreground panel + var foreground = document.createElement('div'); + foreground.className = 'foreground'; + frame.appendChild(foreground); + this.dom.foreground = foreground; - // add node to this (sub)graph and all its parent graphs - for (i = graphs.length - 1; i >= 0; i--) { - var g = graphs[i]; + // create axis panel + var axis = document.createElement('div'); + axis.className = 'itemset-axis'; + //frame.appendChild(axis); + this.dom.axis = axis; - if (!g.nodes) { - g.nodes = []; - } - if (g.nodes.indexOf(current) == -1) { - g.nodes.push(current); - } - } + this.frame = frame; + changed += 1; + } - // merge attributes - if (node.attr) { - current.attr = merge(current.attr, node.attr); - } + if (!this.parent) { + throw new Error('Cannot repaint itemset: no parent attached'); + } + var parentContainer = this.parent.getContainer(); + if (!parentContainer) { + throw new Error('Cannot repaint itemset: parent has no container element'); + } + if (!frame.parentNode) { + parentContainer.appendChild(frame); + changed += 1; + } + if (!this.dom.axis.parentNode) { + parentContainer.appendChild(this.dom.axis); + changed += 1; } - /** - * Add an edge to a graph object - * @param {Object} graph - * @param {Object} edge - */ - function addEdge(graph, edge) { - if (!graph.edges) { - graph.edges = []; - } - graph.edges.push(edge); - if (graph.edge) { - var attr = merge({}, graph.edge); // clone default attributes - edge.attr = merge(attr, edge.attr); // merge attributes - } + // reposition frame + changed += update(frame.style, 'left', asSize(options.left, '0px')); + changed += update(frame.style, 'top', asSize(options.top, '0px')); + changed += update(frame.style, 'width', asSize(options.width, '100%')); + changed += update(frame.style, 'height', asSize(options.height, this.height + 'px')); + + // reposition axis + changed += update(this.dom.axis.style, 'left', asSize(options.left, '0px')); + changed += update(this.dom.axis.style, 'width', asSize(options.width, '100%')); + if (orientation == 'bottom') { + changed += update(this.dom.axis.style, 'top', (this.height + this.top) + 'px'); + } + else { // orientation == 'top' + changed += update(this.dom.axis.style, 'top', this.top + 'px'); } - /** - * Create an edge to a graph object - * @param {Object} graph - * @param {String | Number | Object} from - * @param {String | Number | Object} to - * @param {String} type - * @param {Object | null} attr - * @return {Object} edge - */ - function createEdge(graph, from, to, type, attr) { - var edge = { - from: from, - to: to, - type: type + this._updateConversion(); + + var me = this, + queue = this.queue, + itemsData = this.itemsData, + items = this.items, + dataOptions = { + // TODO: cleanup + // fields: [(itemsData && itemsData.fieldId || 'id'), 'start', 'end', 'content', 'type', 'className'] }; - if (graph.edge) { - edge.attr = merge({}, graph.edge); // clone default attributes - } - edge.attr = merge(edge.attr || {}, attr); // merge attributes + // show/hide added/changed/removed items + Object.keys(queue).forEach(function (id) { + //var entry = queue[id]; + var action = queue[id]; + var item = items[id]; + //var item = entry.item; + //noinspection FallthroughInSwitchStatementJS + switch (action) { + case 'add': + case 'update': + var itemData = itemsData && itemsData.get(id, dataOptions); - return edge; - } + if (itemData) { + var type = itemData.type || + (itemData.start && itemData.end && 'range') || + options.type || + 'box'; + var constructor = ItemSet.types[type]; - /** - * Get next token in the current dot file. - * The token and token type are available as token and tokenType - */ - function getToken() { - tokenType = TOKENTYPE.NULL; - token = ''; + // TODO: how to handle items with invalid data? hide them and give a warning? or throw an error? + if (item) { + // update item + if (!constructor || !(item instanceof constructor)) { + // item type has changed, hide and delete the item + changed += item.hide(); + item = null; + } + else { + item.data = itemData; // TODO: create a method item.setData ? + changed++; + } + } - // skip over whitespaces - while (c == ' ' || c == '\t' || c == '\n' || c == '\r') { // space, tab, enter - next(); - } + if (!item) { + // create item + if (constructor) { + item = new constructor(me, itemData, options, defaultOptions); + changed++; + } + else { + throw new TypeError('Unknown item type "' + type + '"'); + } + } - do { - var isComment = false; + // force a repaint (not only a reposition) + item.repaint(); - // skip comment - if (c == '#') { - // find the previous non-space character - var i = index - 1; - while (dot.charAt(i) == ' ' || dot.charAt(i) == '\t') { - i--; - } - if (dot.charAt(i) == '\n' || dot.charAt(i) == '') { - // the # is at the start of a line, this is indeed a line comment - while (c != '' && c != '\n') { - next(); - } - isComment = true; - } - } - if (c == '/' && nextPreview() == '/') { - // skip line comment - while (c != '' && c != '\n') { - next(); + items[id] = item; } - isComment = true; - } - if (c == '/' && nextPreview() == '*') { - // skip block comment - while (c != '') { - if (c == '*' && nextPreview() == '/') { - // end of block comment found. skip these last two characters - next(); - next(); - break; - } - else { - next(); - } + + // update queue + delete queue[id]; + break; + + case 'remove': + if (item) { + // remove DOM of the item + changed += item.hide(); } - isComment = true; - } - // skip over whitespaces - while (c == ' ' || c == '\t' || c == '\n' || c == '\r') { // space, tab, enter - next(); - } - } - while (isComment); + // update lists + delete items[id]; + delete queue[id]; + break; - // check for end of dot file - if (c == '') { - // token is still empty - tokenType = TOKENTYPE.DELIMITER; - return; + default: + console.log('Error: unknown action "' + action + '"'); } + }); - // check for delimiters consisting of 2 characters - var c2 = c + nextPreview(); - if (DELIMITERS[c2]) { - tokenType = TOKENTYPE.DELIMITER; - token = c2; - next(); - next(); - return; + // reposition all items. Show items only when in the visible area + util.forEach(this.items, function (item) { + if (item.visible) { + changed += item.show(); + item.reposition(); } - - // check for delimiters consisting of 1 character - if (DELIMITERS[c]) { - tokenType = TOKENTYPE.DELIMITER; - token = c; - next(); - return; + else { + changed += item.hide(); } + }); - // check for an identifier (number or string) - // TODO: more precise parsing of numbers/strings (and the port separator ':') - if (isAlphaNumeric(c) || c == '-') { - token += c; - next(); + return (changed > 0); +}; - while (isAlphaNumeric(c)) { - token += c; - next(); - } - if (token == 'false') { - token = false; // convert to boolean - } - else if (token == 'true') { - token = true; // convert to boolean - } - else if (!isNaN(Number(token))) { - token = Number(token); // convert to number - } - tokenType = TOKENTYPE.IDENTIFIER; - return; - } +/** + * Get the foreground container element + * @return {HTMLElement} foreground + */ +ItemSet.prototype.getForeground = function getForeground() { + return this.dom.foreground; +}; - // check for a string enclosed by double quotes - if (c == '"') { - next(); - while (c != '' && (c != '"' || (c == '"' && nextPreview() == '"'))) { - token += c; - if (c == '"') { // skip the escape character - next(); - } - next(); - } - if (c != '"') { - throw newSyntaxError('End of string " expected'); - } - next(); - tokenType = TOKENTYPE.IDENTIFIER; - return; - } +/** + * Get the background container element + * @return {HTMLElement} background + */ +ItemSet.prototype.getBackground = function getBackground() { + return this.dom.background; +}; - // something unknown is found, wrong characters, a syntax error - tokenType = TOKENTYPE.UNKNOWN; - while (c != '') { - token += c; - next(); - } - throw new SyntaxError('Syntax error in part "' + chop(token, 30) + '"'); - } +/** + * Get the axis container element + * @return {HTMLElement} axis + */ +ItemSet.prototype.getAxis = function getAxis() { + return this.dom.axis; +}; - /** - * Parse a graph. - * @returns {Object} graph - */ - function parseGraph() { - var graph = {}; +/** + * Reflow the component + * @return {Boolean} resized + */ +ItemSet.prototype.reflow = function reflow () { + var changed = 0, + options = this.options, + marginAxis = options.margin && options.margin.axis || this.defaultOptions.margin.axis, + marginItem = options.margin && options.margin.item || this.defaultOptions.margin.item, + update = util.updateProperty, + asNumber = util.option.asNumber, + asSize = util.option.asSize, + frame = this.frame; - first(); - getToken(); + if (frame) { + this._updateConversion(); - // optional strict keyword - if (token == 'strict') { - graph.strict = true; - getToken(); - } + util.forEach(this.items, function (item) { + changed += item.reflow(); + }); - // graph or digraph keyword - if (token == 'graph' || token == 'digraph') { - graph.type = token; - getToken(); - } + // TODO: stack.update should be triggered via an event, in stack itself + // TODO: only update the stack when there are changed items + this.stack.update(); - // optional graph id - if (tokenType == TOKENTYPE.IDENTIFIER) { - graph.id = token; - getToken(); + var maxHeight = asNumber(options.maxHeight); + var fixedHeight = (asSize(options.height) != null); + var height; + if (fixedHeight) { + height = frame.offsetHeight; } - - // open angle bracket - if (token != '{') { - throw newSyntaxError('Angle bracket { expected'); + else { + // height is not specified, determine the height from the height and positioned items + var visibleItems = this.stack.ordered; // TODO: not so nice way to get the filtered items + if (visibleItems.length) { + var min = visibleItems[0].top; + var max = visibleItems[0].top + visibleItems[0].height; + util.forEach(visibleItems, function (item) { + min = Math.min(min, item.top); + max = Math.max(max, (item.top + item.height)); + }); + height = (max - min) + marginAxis + marginItem; + } + else { + height = marginAxis + marginItem; + } } - getToken(); + if (maxHeight != null) { + height = Math.min(height, maxHeight); + } + changed += update(this, 'height', height); - // statements - parseStatements(graph); + // calculate height from items + changed += update(this, 'top', frame.offsetTop); + changed += update(this, 'left', frame.offsetLeft); + changed += update(this, 'width', frame.offsetWidth); + } + else { + changed += 1; + } - // close angle bracket - if (token != '}') { - throw newSyntaxError('Angle bracket } expected'); - } - getToken(); + return (changed > 0); +}; + +/** + * Hide this component from the DOM + * @return {Boolean} changed + */ +ItemSet.prototype.hide = function hide() { + var changed = false; - // end of file - if (token !== '') { - throw newSyntaxError('End of file expected'); - } - getToken(); + // remove the DOM + if (this.frame && this.frame.parentNode) { + this.frame.parentNode.removeChild(this.frame); + changed = true; + } + if (this.dom.axis && this.dom.axis.parentNode) { + this.dom.axis.parentNode.removeChild(this.dom.axis); + changed = true; + } - // remove temporary default properties - delete graph.node; - delete graph.edge; - delete graph.graph; + return changed; +}; - return graph; - } +/** + * Set items + * @param {vis.DataSet | null} items + */ +ItemSet.prototype.setItems = function setItems(items) { + var me = this, + ids, + oldItemsData = this.itemsData; - /** - * Parse a list with statements. - * @param {Object} graph - */ - function parseStatements (graph) { - while (token !== '' && token != '}') { - parseStatement(graph); - if (token == ';') { - getToken(); - } - } + // replace the dataset + if (!items) { + this.itemsData = null; + } + else if (items instanceof DataSet || items instanceof DataView) { + this.itemsData = items; + } + else { + throw new TypeError('Data must be an instance of DataSet'); } - /** - * Parse a single statement. Can be a an attribute statement, node - * statement, a series of node statements and edge statements, or a - * parameter. - * @param {Object} graph - */ - function parseStatement(graph) { - // parse subgraph - var subgraph = parseSubgraph(graph); - if (subgraph) { - // edge statements - parseEdge(graph, subgraph); - - return; - } + if (oldItemsData) { + // unsubscribe from old dataset + util.forEach(this.listeners, function (callback, event) { + oldItemsData.unsubscribe(event, callback); + }); - // parse an attribute statement - var attr = parseAttributeStatement(graph); - if (attr) { - return; - } + // remove all drawn items + ids = oldItemsData.getIds(); + this._onRemove(ids); + } - // parse node - if (tokenType != TOKENTYPE.IDENTIFIER) { - throw newSyntaxError('Identifier expected'); - } - var id = token; // id can be a string or a number - getToken(); + if (this.itemsData) { + // subscribe to new dataset + var id = this.id; + util.forEach(this.listeners, function (callback, event) { + me.itemsData.subscribe(event, callback, id); + }); - if (token == '=') { - // id statement - getToken(); - if (tokenType != TOKENTYPE.IDENTIFIER) { - throw newSyntaxError('Identifier expected'); - } - graph[id] = token; - getToken(); - // TODO: implement comma separated list with "a_list: ID=ID [','] [a_list] " - } - else { - parseNodeStatement(graph, id); - } + // draw all new items + ids = this.itemsData.getIds(); + this._onAdd(ids); } +}; - /** - * Parse a subgraph - * @param {Object} graph parent graph object - * @return {Object | null} subgraph - */ - function parseSubgraph (graph) { - var subgraph = null; +/** + * Get the current items items + * @returns {vis.DataSet | null} + */ +ItemSet.prototype.getItems = function getItems() { + return this.itemsData; +}; - // optional subgraph keyword - if (token == 'subgraph') { - subgraph = {}; - subgraph.type = 'subgraph'; - getToken(); +/** + * Handle updated items + * @param {Number[]} ids + * @private + */ +ItemSet.prototype._onUpdate = function _onUpdate(ids) { + this._toQueue('update', ids); +}; - // optional graph id - if (tokenType == TOKENTYPE.IDENTIFIER) { - subgraph.id = token; - getToken(); - } - } +/** + * Handle changed items + * @param {Number[]} ids + * @private + */ +ItemSet.prototype._onAdd = function _onAdd(ids) { + this._toQueue('add', ids); +}; - // open angle bracket - if (token == '{') { - getToken(); +/** + * Handle removed items + * @param {Number[]} ids + * @private + */ +ItemSet.prototype._onRemove = function _onRemove(ids) { + this._toQueue('remove', ids); +}; - if (!subgraph) { - subgraph = {}; - } - subgraph.parent = graph; - subgraph.node = graph.node; - subgraph.edge = graph.edge; - subgraph.graph = graph.graph; +/** + * Put items in the queue to be added/updated/remove + * @param {String} action can be 'add', 'update', 'remove' + * @param {Number[]} ids + */ +ItemSet.prototype._toQueue = function _toQueue(action, ids) { + var queue = this.queue; + ids.forEach(function (id) { + queue[id] = action; + }); - // statements - parseStatements(subgraph); + if (this.controller) { + //this.requestReflow(); + this.requestRepaint(); + } +}; - // close angle bracket - if (token != '}') { - throw newSyntaxError('Angle bracket } expected'); - } - getToken(); +/** + * Calculate the factor and offset to convert a position on screen to the + * corresponding date and vice versa. + * After the method _updateConversion is executed once, the methods toTime + * and toScreen can be used. + * @private + */ +ItemSet.prototype._updateConversion = function _updateConversion() { + var range = this.range; + if (!range) { + throw new Error('No range configured'); + } - // remove temporary default properties - delete subgraph.node; - delete subgraph.edge; - delete subgraph.graph; - delete subgraph.parent; + if (range.conversion) { + this.conversion = range.conversion(this.width); + } + else { + this.conversion = Range.conversion(range.start, range.end, this.width); + } +}; - // register at the parent graph - if (!graph.subgraphs) { - graph.subgraphs = []; - } - graph.subgraphs.push(subgraph); - } +/** + * Convert a position on screen (pixels) to a datetime + * Before this method can be used, the method _updateConversion must be + * executed once. + * @param {int} x Position on the screen in pixels + * @return {Date} time The datetime the corresponds with given position x + */ +ItemSet.prototype.toTime = function toTime(x) { + var conversion = this.conversion; + return new Date(x / conversion.factor + conversion.offset); +}; + +/** + * Convert a datetime (Date object) into a position on the screen + * Before this method can be used, the method _updateConversion must be + * executed once. + * @param {Date} time A date + * @return {int} x The position on the screen in pixels which corresponds + * with the given date. + */ +ItemSet.prototype.toScreen = function toScreen(time) { + var conversion = this.conversion; + return (time.valueOf() - conversion.offset) * conversion.factor; +}; + +/** + * @constructor Item + * @param {ItemSet} parent + * @param {Object} data Object containing (optional) parameters type, + * start, end, content, group, className. + * @param {Object} [options] Options to set initial property values + * @param {Object} [defaultOptions] default options + * // TODO: describe available options + */ +function Item (parent, data, options, defaultOptions) { + this.parent = parent; + this.data = data; + this.dom = null; + this.options = options || {}; + this.defaultOptions = defaultOptions || {}; - return subgraph; - } + this.selected = false; + this.visible = false; + this.top = 0; + this.left = 0; + this.width = 0; + this.height = 0; +} - /** - * parse an attribute statement like "node [shape=circle fontSize=16]". - * Available keywords are 'node', 'edge', 'graph'. - * The previous list with default attributes will be replaced - * @param {Object} graph - * @returns {String | null} keyword Returns the name of the parsed attribute - * (node, edge, graph), or null if nothing - * is parsed. - */ - function parseAttributeStatement (graph) { - // attribute statements - if (token == 'node') { - getToken(); +/** + * Select current item + */ +Item.prototype.select = function select() { + this.selected = true; +}; - // node attributes - graph.node = parseAttributeList(); - return 'node'; - } - else if (token == 'edge') { - getToken(); +/** + * Unselect current item + */ +Item.prototype.unselect = function unselect() { + this.selected = false; +}; - // edge attributes - graph.edge = parseAttributeList(); - return 'edge'; - } - else if (token == 'graph') { - getToken(); +/** + * Show the Item in the DOM (when not already visible) + * @return {Boolean} changed + */ +Item.prototype.show = function show() { + return false; +}; - // graph attributes - graph.graph = parseAttributeList(); - return 'graph'; - } +/** + * Hide the Item from the DOM (when visible) + * @return {Boolean} changed + */ +Item.prototype.hide = function hide() { + return false; +}; - return null; - } +/** + * Repaint the item + * @return {Boolean} changed + */ +Item.prototype.repaint = function repaint() { + // should be implemented by the item + return false; +}; - /** - * parse a node statement - * @param {Object} graph - * @param {String | Number} id - */ - function parseNodeStatement(graph, id) { - // node statement - var node = { - id: id - }; - var attr = parseAttributeList(); - if (attr) { - node.attr = attr; +/** + * Reflow the item + * @return {Boolean} resized + */ +Item.prototype.reflow = function reflow() { + // should be implemented by the item + return false; +}; + +/** + * @constructor ItemBox + * @extends Item + * @param {ItemSet} parent + * @param {Object} data Object containing parameters start + * content, className. + * @param {Object} [options] Options to set initial property values + * @param {Object} [defaultOptions] default options + * // TODO: describe available options + */ +function ItemBox (parent, data, options, defaultOptions) { + this.props = { + dot: { + left: 0, + top: 0, + width: 0, + height: 0 + }, + line: { + top: 0, + left: 0, + width: 0, + height: 0 } - addNode(graph, node); + }; - // edge statements - parseEdge(graph, id); - } + Item.call(this, parent, data, options, defaultOptions); +} - /** - * Parse an edge or a series of edges - * @param {Object} graph - * @param {String | Number} from Id of the from node - */ - function parseEdge(graph, from) { - while (token == '->' || token == '--') { - var to; - var type = token; - getToken(); +ItemBox.prototype = new Item (null, null); - var subgraph = parseSubgraph(graph); - if (subgraph) { - to = subgraph; - } - else { - if (tokenType != TOKENTYPE.IDENTIFIER) { - throw newSyntaxError('Identifier or subgraph expected'); - } - to = token; - addNode(graph, { - id: to - }); - getToken(); - } +/** + * Select the item + * @override + */ +ItemBox.prototype.select = function select() { + this.selected = true; + // TODO: select and unselect +}; - // parse edge attributes - var attr = parseAttributeList(); +/** + * Unselect the item + * @override + */ +ItemBox.prototype.unselect = function unselect() { + this.selected = false; + // TODO: select and unselect +}; - // create edge - var edge = createEdge(graph, from, to, type, attr); - addEdge(graph, edge); +/** + * Repaint the item + * @return {Boolean} changed + */ +ItemBox.prototype.repaint = function repaint() { + // TODO: make an efficient repaint + var changed = false; + var dom = this.dom; - from = to; - } + if (!dom) { + this._create(); + dom = this.dom; + changed = true; } - /** - * Parse a set with attributes, - * for example [label="1.000", shape=solid] - * @return {Object | null} attr - */ - function parseAttributeList() { - var attr = null; - - while (token == '[') { - getToken(); - attr = {}; - while (token !== '' && token != ']') { - if (tokenType != TOKENTYPE.IDENTIFIER) { - throw newSyntaxError('Attribute name expected'); - } - var name = token; - - getToken(); - if (token != '=') { - throw newSyntaxError('Equal sign = expected'); - } - getToken(); + if (dom) { + if (!this.parent) { + throw new Error('Cannot repaint item: no parent attached'); + } + var foreground = this.parent.getForeground(); + if (!foreground) { + throw new Error('Cannot repaint time axis: ' + + 'parent has no foreground container element'); + } + var background = this.parent.getBackground(); + if (!background) { + throw new Error('Cannot repaint time axis: ' + + 'parent has no background container element'); + } + var axis = this.parent.getAxis(); + if (!background) { + throw new Error('Cannot repaint time axis: ' + + 'parent has no axis container element'); + } - if (tokenType != TOKENTYPE.IDENTIFIER) { - throw newSyntaxError('Attribute value expected'); - } - var value = token; - setValue(attr, name, value); // name can be a path + if (!dom.box.parentNode) { + foreground.appendChild(dom.box); + changed = true; + } + if (!dom.line.parentNode) { + background.appendChild(dom.line); + changed = true; + } + if (!dom.dot.parentNode) { + axis.appendChild(dom.dot); + changed = true; + } - getToken(); - if (token ==',') { - getToken(); - } + // update contents + if (this.data.content != this.content) { + this.content = this.data.content; + if (this.content instanceof Element) { + dom.content.innerHTML = ''; + dom.content.appendChild(this.content); } - - if (token != ']') { - throw newSyntaxError('Bracket ] expected'); + else if (this.data.content != undefined) { + dom.content.innerHTML = this.content; } - getToken(); + else { + throw new Error('Property "content" missing in item ' + this.data.id); + } + changed = true; } - return attr; + // update class + var className = (this.data.className? ' ' + this.data.className : '') + + (this.selected ? ' selected' : ''); + if (this.className != className) { + this.className = className; + dom.box.className = 'item box' + className; + dom.line.className = 'item line' + className; + dom.dot.className = 'item dot' + className; + changed = true; + } } - /** - * Create a syntax error with extra information on current token and index. - * @param {String} message - * @returns {SyntaxError} err - */ - function newSyntaxError(message) { - return new SyntaxError(message + ', got "' + chop(token, 30) + '" (char ' + index + ')'); - } + return changed; +}; - /** - * Chop off text after a maximum length - * @param {String} text - * @param {Number} maxLength - * @returns {String} - */ - function chop (text, maxLength) { - return (text.length <= maxLength) ? text : (text.substr(0, 27) + '...'); +/** + * Show the item in the DOM (when not already visible). The items DOM will + * be created when needed. + * @return {Boolean} changed + */ +ItemBox.prototype.show = function show() { + if (!this.dom || !this.dom.box.parentNode) { + return this.repaint(); } + else { + return false; + } +}; - /** - * Execute a function fn for each pair of elements in two arrays - * @param {Array | *} array1 - * @param {Array | *} array2 - * @param {function} fn - */ - function forEach2(array1, array2, fn) { - if (array1 instanceof Array) { - array1.forEach(function (elem1) { - if (array2 instanceof Array) { - array2.forEach(function (elem2) { - fn(elem1, elem2); - }); - } - else { - fn(elem1, array2); - } - }); - } - else { - if (array2 instanceof Array) { - array2.forEach(function (elem2) { - fn(array1, elem2); - }); - } - else { - fn(array1, array2); - } - } +/** + * Hide the item from the DOM (when visible) + * @return {Boolean} changed + */ +ItemBox.prototype.hide = function hide() { + var changed = false, + dom = this.dom; + if (dom) { + if (dom.box.parentNode) { + dom.box.parentNode.removeChild(dom.box); + changed = true; + } + if (dom.line.parentNode) { + dom.line.parentNode.removeChild(dom.line); + } + if (dom.dot.parentNode) { + dom.dot.parentNode.removeChild(dom.dot); + } } + return changed; +}; - /** - * Convert a string containing a graph in DOT language into a map containing - * with nodes and edges in the format of graph. - * @param {String} data Text containing a graph in DOT-notation - * @return {Object} graphData - */ - function DOTToGraph (data) { - // parse the DOT file - var dotData = parseDOT(data); - var graphData = { - nodes: [], - edges: [], - options: {} - }; +/** + * Reflow the item: calculate its actual size and position from the DOM + * @return {boolean} resized returns true if the axis is resized + * @override + */ +ItemBox.prototype.reflow = function reflow() { + var changed = 0, + update, + dom, + props, + options, + margin, + start, + align, + orientation, + top, + left, + data, + range; - // copy the nodes - if (dotData.nodes) { - dotData.nodes.forEach(function (dotNode) { - var graphNode = { - id: dotNode.id, - label: String(dotNode.label || dotNode.id) - }; - merge(graphNode, dotNode.attr); - if (graphNode.image) { - graphNode.shape = 'image'; - } - graphData.nodes.push(graphNode); - }); - } + if (this.data.start == undefined) { + throw new Error('Property "start" missing in item ' + this.data.id); + } - // copy the edges - if (dotData.edges) { - /** - * Convert an edge in DOT format to an edge with VisGraph format - * @param {Object} dotEdge - * @returns {Object} graphEdge - */ - function convertEdge(dotEdge) { - var graphEdge = { - from: dotEdge.from, - to: dotEdge.to - }; - merge(graphEdge, dotEdge.attr); - graphEdge.style = (dotEdge.type == '->') ? 'arrow' : 'line'; - return graphEdge; - } + data = this.data; + range = this.parent && this.parent.range; + if (data && range) { + // TODO: account for the width of the item + var interval = (range.end - range.start); + this.visible = (data.start > range.start - interval) && (data.start < range.end + interval); + } + else { + this.visible = false; + } - dotData.edges.forEach(function (dotEdge) { - var from, to; - if (dotEdge.from instanceof Object) { - from = dotEdge.from.nodes; - } - else { - from = { - id: dotEdge.from - } - } + if (this.visible) { + dom = this.dom; + if (dom) { + update = util.updateProperty; + props = this.props; + options = this.options; + start = this.parent.toScreen(this.data.start); + align = options.align || this.defaultOptions.align; + margin = options.margin && options.margin.axis || this.defaultOptions.margin.axis; + orientation = options.orientation || this.defaultOptions.orientation; - if (dotEdge.to instanceof Object) { - to = dotEdge.to.nodes; - } - else { - to = { - id: dotEdge.to - } - } + changed += update(props.dot, 'height', dom.dot.offsetHeight); + changed += update(props.dot, 'width', dom.dot.offsetWidth); + changed += update(props.line, 'width', dom.line.offsetWidth); + changed += update(props.line, 'height', dom.line.offsetHeight); + changed += update(props.line, 'top', dom.line.offsetTop); + changed += update(this, 'width', dom.box.offsetWidth); + changed += update(this, 'height', dom.box.offsetHeight); + if (align == 'right') { + left = start - this.width; + } + else if (align == 'left') { + left = start; + } + else { + // default or 'center' + left = start - this.width / 2; + } + changed += update(this, 'left', left); - if (dotEdge.from instanceof Object && dotEdge.from.edges) { - dotEdge.from.edges.forEach(function (subEdge) { - var graphEdge = convertEdge(subEdge); - graphData.edges.push(graphEdge); - }); - } + changed += update(props.line, 'left', start - props.line.width / 2); + changed += update(props.dot, 'left', start - props.dot.width / 2); + changed += update(props.dot, 'top', -props.dot.height / 2); + if (orientation == 'top') { + top = margin; - forEach2(from, to, function (from, to) { - var subEdge = createEdge(graphData, from.id, to.id, dotEdge.type, dotEdge.attr); - var graphEdge = convertEdge(subEdge); - graphData.edges.push(graphEdge); - }); + changed += update(this, 'top', top); + } + else { + // default or 'bottom' + var parentHeight = this.parent.height; + top = parentHeight - this.height - margin; - if (dotEdge.to instanceof Object && dotEdge.to.edges) { - dotEdge.to.edges.forEach(function (subEdge) { - var graphEdge = convertEdge(subEdge); - graphData.edges.push(graphEdge); - }); - } - }); + changed += update(this, 'top', top); + } + } + else { + changed += 1; } + } - // copy the options - if (dotData.attr) { - graphData.options = dotData.attr; - } + return (changed > 0); +}; - return graphData; - } +/** + * Create an items DOM + * @private + */ +ItemBox.prototype._create = function _create() { + var dom = this.dom; + if (!dom) { + this.dom = dom = {}; - // exports - exports.parseDOT = parseDOT; - exports.DOTToGraph = DOTToGraph; + // create the box + dom.box = document.createElement('DIV'); + // className is updated in repaint() -})(typeof util !== 'undefined' ? util : exports); + // contents box (inside the background box). used for making margins + dom.content = document.createElement('DIV'); + dom.content.className = 'content'; + dom.box.appendChild(dom.content); + + // line to axis + dom.line = document.createElement('DIV'); + dom.line.className = 'line'; + + // dot on axis + dom.dot = document.createElement('DIV'); + dom.dot.className = 'dot'; + } +}; /** - * Canvas shapes used by the Graph + * Reposition the item, recalculate its left, top, and width, using the current + * range and size of the items itemset + * @override */ -if (typeof CanvasRenderingContext2D !== 'undefined') { +ItemBox.prototype.reposition = function reposition() { + var dom = this.dom, + props = this.props, + orientation = this.options.orientation || this.defaultOptions.orientation; - /** - * Draw a circle shape - */ - CanvasRenderingContext2D.prototype.circle = function(x, y, r) { - this.beginPath(); - this.arc(x, y, r, 0, 2*Math.PI, false); - }; + if (dom) { + var box = dom.box, + line = dom.line, + dot = dom.dot; - /** - * Draw a square shape - * @param {Number} x horizontal center - * @param {Number} y vertical center - * @param {Number} r size, width and height of the square - */ - CanvasRenderingContext2D.prototype.square = function(x, y, r) { - this.beginPath(); - this.rect(x - r, y - r, r * 2, r * 2); - }; + box.style.left = this.left + 'px'; + box.style.top = this.top + 'px'; - /** - * Draw a triangle shape - * @param {Number} x horizontal center - * @param {Number} y vertical center - * @param {Number} r radius, half the length of the sides of the triangle - */ - CanvasRenderingContext2D.prototype.triangle = function(x, y, r) { - // http://en.wikipedia.org/wiki/Equilateral_triangle - this.beginPath(); + line.style.left = props.line.left + 'px'; + if (orientation == 'top') { + line.style.top = 0 + 'px'; + line.style.height = this.top + 'px'; + } + else { + // orientation 'bottom' + line.style.top = (this.top + this.height) + 'px'; + line.style.height = Math.max(this.parent.height - this.top - this.height + + this.props.dot.height / 2, 0) + 'px'; + } - var s = r * 2; - var s2 = s / 2; - var ir = Math.sqrt(3) / 6 * s; // radius of inner circle - var h = Math.sqrt(s * s - s2 * s2); // height + dot.style.left = props.dot.left + 'px'; + dot.style.top = props.dot.top + 'px'; + } +}; - this.moveTo(x, y - (h - ir)); - this.lineTo(x + s2, y + ir); - this.lineTo(x - s2, y + ir); - this.lineTo(x, y - (h - ir)); - this.closePath(); +/** + * @constructor ItemPoint + * @extends Item + * @param {ItemSet} parent + * @param {Object} data Object containing parameters start + * content, className. + * @param {Object} [options] Options to set initial property values + * @param {Object} [defaultOptions] default options + * // TODO: describe available options + */ +function ItemPoint (parent, data, options, defaultOptions) { + this.props = { + dot: { + top: 0, + width: 0, + height: 0 + }, + content: { + height: 0, + marginLeft: 0 + } }; - /** - * Draw a triangle shape in downward orientation - * @param {Number} x horizontal center - * @param {Number} y vertical center - * @param {Number} r radius - */ - CanvasRenderingContext2D.prototype.triangleDown = function(x, y, r) { - // http://en.wikipedia.org/wiki/Equilateral_triangle - this.beginPath(); + Item.call(this, parent, data, options, defaultOptions); +} - var s = r * 2; - var s2 = s / 2; - var ir = Math.sqrt(3) / 6 * s; // radius of inner circle - var h = Math.sqrt(s * s - s2 * s2); // height +ItemPoint.prototype = new Item (null, null); - this.moveTo(x, y + (h - ir)); - this.lineTo(x + s2, y - ir); - this.lineTo(x - s2, y - ir); - this.lineTo(x, y + (h - ir)); - this.closePath(); - }; +/** + * Select the item + * @override + */ +ItemPoint.prototype.select = function select() { + this.selected = true; + // TODO: select and unselect +}; - /** - * Draw a star shape, a star with 5 points - * @param {Number} x horizontal center - * @param {Number} y vertical center - * @param {Number} r radius, half the length of the sides of the triangle - */ - CanvasRenderingContext2D.prototype.star = function(x, y, r) { - // http://www.html5canvastutorials.com/labs/html5-canvas-star-spinner/ - this.beginPath(); +/** + * Unselect the item + * @override + */ +ItemPoint.prototype.unselect = function unselect() { + this.selected = false; + // TODO: select and unselect +}; - for (var n = 0; n < 10; n++) { - var radius = (n % 2 === 0) ? r * 1.3 : r * 0.5; - this.lineTo( - x + radius * Math.sin(n * 2 * Math.PI / 10), - y - radius * Math.cos(n * 2 * Math.PI / 10) - ); +/** + * Repaint the item + * @return {Boolean} changed + */ +ItemPoint.prototype.repaint = function repaint() { + // TODO: make an efficient repaint + var changed = false; + var dom = this.dom; + + if (!dom) { + this._create(); + dom = this.dom; + changed = true; + } + + if (dom) { + if (!this.parent) { + throw new Error('Cannot repaint item: no parent attached'); + } + var foreground = this.parent.getForeground(); + if (!foreground) { + throw new Error('Cannot repaint time axis: ' + + 'parent has no foreground container element'); } - this.closePath(); - }; + if (!dom.point.parentNode) { + foreground.appendChild(dom.point); + foreground.appendChild(dom.point); + changed = true; + } - /** - * http://stackoverflow.com/questions/1255512/how-to-draw-a-rounded-rectangle-on-html-canvas - */ - CanvasRenderingContext2D.prototype.roundRect = function(x, y, w, h, r) { - var r2d = Math.PI/180; - if( w - ( 2 * r ) < 0 ) { r = ( w / 2 ); } //ensure that the radius isn't too large for x - if( h - ( 2 * r ) < 0 ) { r = ( h / 2 ); } //ensure that the radius isn't too large for y - this.beginPath(); - this.moveTo(x+r,y); - this.lineTo(x+w-r,y); - this.arc(x+w-r,y+r,r,r2d*270,r2d*360,false); - this.lineTo(x+w,y+h-r); - this.arc(x+w-r,y+h-r,r,0,r2d*90,false); - this.lineTo(x+r,y+h); - this.arc(x+r,y+h-r,r,r2d*90,r2d*180,false); - this.lineTo(x,y+r); - this.arc(x+r,y+r,r,r2d*180,r2d*270,false); - }; + // update contents + if (this.data.content != this.content) { + this.content = this.data.content; + if (this.content instanceof Element) { + dom.content.innerHTML = ''; + dom.content.appendChild(this.content); + } + else if (this.data.content != undefined) { + dom.content.innerHTML = this.content; + } + else { + throw new Error('Property "content" missing in item ' + this.data.id); + } + changed = true; + } - /** - * http://stackoverflow.com/questions/2172798/how-to-draw-an-oval-in-html5-canvas - */ - CanvasRenderingContext2D.prototype.ellipse = function(x, y, w, h) { - var kappa = .5522848, - ox = (w / 2) * kappa, // control point offset horizontal - oy = (h / 2) * kappa, // control point offset vertical - xe = x + w, // x-end - ye = y + h, // y-end - xm = x + w / 2, // x-middle - ym = y + h / 2; // y-middle + // update class + var className = (this.data.className? ' ' + this.data.className : '') + + (this.selected ? ' selected' : ''); + if (this.className != className) { + this.className = className; + dom.point.className = 'item point' + className; + changed = true; + } + } - this.beginPath(); - this.moveTo(x, ym); - this.bezierCurveTo(x, ym - oy, xm - ox, y, xm, y); - this.bezierCurveTo(xm + ox, y, xe, ym - oy, xe, ym); - this.bezierCurveTo(xe, ym + oy, xm + ox, ye, xm, ye); - this.bezierCurveTo(xm - ox, ye, x, ym + oy, x, ym); - }; + return changed; +}; +/** + * Show the item in the DOM (when not already visible). The items DOM will + * be created when needed. + * @return {Boolean} changed + */ +ItemPoint.prototype.show = function show() { + if (!this.dom || !this.dom.point.parentNode) { + return this.repaint(); + } + else { + return false; + } +}; +/** + * Hide the item from the DOM (when visible) + * @return {Boolean} changed + */ +ItemPoint.prototype.hide = function hide() { + var changed = false, + dom = this.dom; + if (dom) { + if (dom.point.parentNode) { + dom.point.parentNode.removeChild(dom.point); + changed = true; + } + } + return changed; +}; - /** - * http://stackoverflow.com/questions/2172798/how-to-draw-an-oval-in-html5-canvas - */ - CanvasRenderingContext2D.prototype.database = function(x, y, w, h) { - var f = 1/3; - var wEllipse = w; - var hEllipse = h * f; +/** + * Reflow the item: calculate its actual size from the DOM + * @return {boolean} resized returns true if the axis is resized + * @override + */ +ItemPoint.prototype.reflow = function reflow() { + var changed = 0, + update, + dom, + props, + options, + margin, + orientation, + start, + top, + data, + range; - var kappa = .5522848, - ox = (wEllipse / 2) * kappa, // control point offset horizontal - oy = (hEllipse / 2) * kappa, // control point offset vertical - xe = x + wEllipse, // x-end - ye = y + hEllipse, // y-end - xm = x + wEllipse / 2, // x-middle - ym = y + hEllipse / 2, // y-middle - ymb = y + (h - hEllipse/2), // y-midlle, bottom ellipse - yeb = y + h; // y-end, bottom ellipse + if (this.data.start == undefined) { + throw new Error('Property "start" missing in item ' + this.data.id); + } - this.beginPath(); - this.moveTo(xe, ym); + data = this.data; + range = this.parent && this.parent.range; + if (data && range) { + // TODO: account for the width of the item + var interval = (range.end - range.start); + this.visible = (data.start > range.start - interval) && (data.start < range.end); + } + else { + this.visible = false; + } - this.bezierCurveTo(xe, ym + oy, xm + ox, ye, xm, ye); - this.bezierCurveTo(xm - ox, ye, x, ym + oy, x, ym); + if (this.visible) { + dom = this.dom; + if (dom) { + update = util.updateProperty; + props = this.props; + options = this.options; + orientation = options.orientation || this.defaultOptions.orientation; + margin = options.margin && options.margin.axis || this.defaultOptions.margin.axis; + start = this.parent.toScreen(this.data.start); - this.bezierCurveTo(x, ym - oy, xm - ox, y, xm, y); - this.bezierCurveTo(xm + ox, y, xe, ym - oy, xe, ym); + changed += update(this, 'width', dom.point.offsetWidth); + changed += update(this, 'height', dom.point.offsetHeight); + changed += update(props.dot, 'width', dom.dot.offsetWidth); + changed += update(props.dot, 'height', dom.dot.offsetHeight); + changed += update(props.content, 'height', dom.content.offsetHeight); - this.lineTo(xe, ymb); + if (orientation == 'top') { + top = margin; + } + else { + // default or 'bottom' + var parentHeight = this.parent.height; + top = Math.max(parentHeight - this.height - margin, 0); + } + changed += update(this, 'top', top); + changed += update(this, 'left', start - props.dot.width / 2); + changed += update(props.content, 'marginLeft', 1.5 * props.dot.width); + //changed += update(props.content, 'marginRight', 0.5 * props.dot.width); // TODO - this.bezierCurveTo(xe, ymb + oy, xm + ox, yeb, xm, yeb); - this.bezierCurveTo(xm - ox, yeb, x, ymb + oy, x, ymb); + changed += update(props.dot, 'top', (this.height - props.dot.height) / 2); + } + else { + changed += 1; + } + } - this.lineTo(x, ym); - }; + return (changed > 0); +}; +/** + * Create an items DOM + * @private + */ +ItemPoint.prototype._create = function _create() { + var dom = this.dom; + if (!dom) { + this.dom = dom = {}; - /** - * Draw an arrow point (no line) - */ - CanvasRenderingContext2D.prototype.arrow = function(x, y, angle, length) { - // tail - var xt = x - length * Math.cos(angle); - var yt = y - length * Math.sin(angle); + // background box + dom.point = document.createElement('div'); + // className is updated in repaint() - // inner tail - // TODO: allow to customize different shapes - var xi = x - length * 0.9 * Math.cos(angle); - var yi = y - length * 0.9 * Math.sin(angle); + // contents box, right from the dot + dom.content = document.createElement('div'); + dom.content.className = 'content'; + dom.point.appendChild(dom.content); - // left - var xl = xt + length / 3 * Math.cos(angle + 0.5 * Math.PI); - var yl = yt + length / 3 * Math.sin(angle + 0.5 * Math.PI); + // dot at start + dom.dot = document.createElement('div'); + dom.dot.className = 'dot'; + dom.point.appendChild(dom.dot); + } +}; - // right - var xr = xt + length / 3 * Math.cos(angle - 0.5 * Math.PI); - var yr = yt + length / 3 * Math.sin(angle - 0.5 * Math.PI); +/** + * Reposition the item, recalculate its left, top, and width, using the current + * range and size of the items itemset + * @override + */ +ItemPoint.prototype.reposition = function reposition() { + var dom = this.dom, + props = this.props; - this.beginPath(); - this.moveTo(x, y); - this.lineTo(xl, yl); - this.lineTo(xi, yi); - this.lineTo(xr, yr); - this.closePath(); - }; + if (dom) { + dom.point.style.top = this.top + 'px'; + dom.point.style.left = this.left + 'px'; - /** - * Sets up the dashedLine functionality for drawing - * Original code came from http://stackoverflow.com/questions/4576724/dotted-stroke-in-canvas - * @author David Jordan - * @date 2012-08-08 - */ - CanvasRenderingContext2D.prototype.dashedLine = function(x,y,x2,y2,dashArray){ - if (!dashArray) dashArray=[10,5]; - if (dashLength==0) dashLength = 0.001; // Hack for Safari - var dashCount = dashArray.length; - this.moveTo(x, y); - var dx = (x2-x), dy = (y2-y); - var slope = dy/dx; - var distRemaining = Math.sqrt( dx*dx + dy*dy ); - var dashIndex=0, draw=true; - while (distRemaining>=0.1){ - var dashLength = dashArray[dashIndex++%dashCount]; - if (dashLength > distRemaining) dashLength = distRemaining; - var xStep = Math.sqrt( dashLength*dashLength / (1 + slope*slope) ); - if (dx<0) xStep = -xStep; - x += xStep; - y += slope*xStep; - this[draw ? 'lineTo' : 'moveTo'](x,y); - distRemaining -= dashLength; - draw = !draw; - } - }; + dom.content.style.marginLeft = props.content.marginLeft + 'px'; + //dom.content.style.marginRight = props.content.marginRight + 'px'; // TODO - // TODO: add diamond shape -} + dom.dot.style.top = props.dot.top + 'px'; + } +}; /** - * @class Node - * A node. A node can be connected to other nodes via one or multiple edges. - * @param {object} properties An object containing properties for the node. All - * properties are optional, except for the id. - * {number} id Id of the node. Required - * {string} label Text label for the node - * {number} x Horizontal position of the node - * {number} y Vertical position of the node - * {string} shape Node shape, available: - * "database", "circle", "ellipse", - * "box", "image", "text", "dot", - * "star", "triangle", "triangleDown", - * "square" - * {string} image An image url - * {string} title An title text, can be HTML - * {anytype} group A group name or number - * @param {Graph.Images} imagelist A list with images. Only needed - * when the node has an image - * @param {Graph.Groups} grouplist A list with groups. Needed for - * retrieving group properties - * @param {Object} constants An object with default values for - * example for the color + * @constructor ItemRange + * @extends Item + * @param {ItemSet} parent + * @param {Object} data Object containing parameters start, end + * content, className. + * @param {Object} [options] Options to set initial property values + * @param {Object} [defaultOptions] default options + * // TODO: describe available options + */ +function ItemRange (parent, data, options, defaultOptions) { + this.props = { + content: { + left: 0, + width: 0 + } + }; + + Item.call(this, parent, data, options, defaultOptions); +} + +ItemRange.prototype = new Item (null, null); + +/** + * Select the item + * @override */ -function Node(properties, imagelist, grouplist, constants) { +ItemRange.prototype.select = function select() { + this.selected = true; + // TODO: select and unselect +}; + +/** + * Unselect the item + * @override + */ +ItemRange.prototype.unselect = function unselect() { this.selected = false; + // TODO: select and unselect +}; - this.edges = []; // all edges connected to this node - this.group = constants.nodes.group; +/** + * Repaint the item + * @return {Boolean} changed + */ +ItemRange.prototype.repaint = function repaint() { + // TODO: make an efficient repaint + var changed = false; + var dom = this.dom; - this.fontSize = constants.nodes.fontSize; - this.fontFace = constants.nodes.fontFace; - this.fontColor = constants.nodes.fontColor; + if (!dom) { + this._create(); + dom = this.dom; + changed = true; + } - this.color = constants.nodes.color; + if (dom) { + if (!this.parent) { + throw new Error('Cannot repaint item: no parent attached'); + } + var foreground = this.parent.getForeground(); + if (!foreground) { + throw new Error('Cannot repaint time axis: ' + + 'parent has no foreground container element'); + } - // set defaults for the properties - this.id = undefined; - this.shape = constants.nodes.shape; - this.image = constants.nodes.image; - this.x = 0; - this.y = 0; - this.xFixed = false; - this.yFixed = false; - this.radius = constants.nodes.radius; - this.radiusFixed = false; - this.radiusMin = constants.nodes.radiusMin; - this.radiusMax = constants.nodes.radiusMax; + if (!dom.box.parentNode) { + foreground.appendChild(dom.box); + changed = true; + } - this.imagelist = imagelist; - this.grouplist = grouplist; + // update content + if (this.data.content != this.content) { + this.content = this.data.content; + if (this.content instanceof Element) { + dom.content.innerHTML = ''; + dom.content.appendChild(this.content); + } + else if (this.data.content != undefined) { + dom.content.innerHTML = this.content; + } + else { + throw new Error('Property "content" missing in item ' + this.data.id); + } + changed = true; + } - this.setProperties(properties, constants); + // update class + var className = this.data.className ? (' ' + this.data.className) : ''; + if (this.className != className) { + this.className = className; + dom.box.className = 'item range' + className; + changed = true; + } + } - // mass, force, velocity - this.mass = 50; // kg (mass is adjusted for the number of connected edges) - this.fx = 0.0; // external force x - this.fy = 0.0; // external force y - this.vx = 0.0; // velocity x - this.vy = 0.0; // velocity y - this.minForce = constants.minForce; - this.damping = 0.9; // damping factor + return changed; }; /** - * Attach a edge to the node - * @param {Edge} edge + * Show the item in the DOM (when not already visible). The items DOM will + * be created when needed. + * @return {Boolean} changed */ -Node.prototype.attachEdge = function(edge) { - if (this.edges.indexOf(edge) == -1) { - this.edges.push(edge); +ItemRange.prototype.show = function show() { + if (!this.dom || !this.dom.box.parentNode) { + return this.repaint(); + } + else { + return false; } - this._updateMass(); }; /** - * Detach a edge from the node - * @param {Edge} edge + * Hide the item from the DOM (when visible) + * @return {Boolean} changed */ -Node.prototype.detachEdge = function(edge) { - var index = this.edges.indexOf(edge); - if (index != -1) { - this.edges.splice(index, 1); +ItemRange.prototype.hide = function hide() { + var changed = false, + dom = this.dom; + if (dom) { + if (dom.box.parentNode) { + dom.box.parentNode.removeChild(dom.box); + changed = true; + } } - this._updateMass(); + return changed; }; /** - * Update the nodes mass, which is determined by the number of edges connecting - * to it (more edges -> heavier node). - * @private + * Reflow the item: calculate its actual size from the DOM + * @return {boolean} resized returns true if the axis is resized + * @override */ -Node.prototype._updateMass = function() { - this.mass = 50 + 20 * this.edges.length; // kg -}; +ItemRange.prototype.reflow = function reflow() { + var changed = 0, + dom, + props, + options, + margin, + padding, + parent, + start, + end, + data, + range, + update, + box, + parentWidth, + contentLeft, + orientation, + top; -/** - * Set or overwrite properties for the node - * @param {Object} properties an object with properties - * @param {Object} constants and object with default, global properties - */ -Node.prototype.setProperties = function(properties, constants) { - if (!properties) { - return; + if (this.data.start == undefined) { + throw new Error('Property "start" missing in item ' + this.data.id); } - - // basic properties - if (properties.id != undefined) {this.id = properties.id;} - if (properties.label != undefined) {this.label = properties.label;} - if (properties.title != undefined) {this.title = properties.title;} - if (properties.group != undefined) {this.group = properties.group;} - if (properties.x != undefined) {this.x = properties.x;} - if (properties.y != undefined) {this.y = properties.y;} - if (properties.value != undefined) {this.value = properties.value;} - - if (this.id === undefined) { - throw "Node must have an id"; + if (this.data.end == undefined) { + throw new Error('Property "end" missing in item ' + this.data.id); } - // copy group properties - if (this.group) { - var groupObj = this.grouplist.get(this.group); - for (var prop in groupObj) { - if (groupObj.hasOwnProperty(prop)) { - this[prop] = groupObj[prop]; - } - } + data = this.data; + range = this.parent && this.parent.range; + if (data && range) { + // TODO: account for the width of the item. Take some margin + this.visible = (data.start < range.end) && (data.end > range.start); + } + else { + this.visible = false; } - // individual shape properties - if (properties.shape != undefined) {this.shape = properties.shape;} - if (properties.image != undefined) {this.image = properties.image;} - if (properties.radius != undefined) {this.radius = properties.radius;} - if (properties.color != undefined) {this.color = Node.parseColor(properties.color);} + if (this.visible) { + dom = this.dom; + if (dom) { + props = this.props; + options = this.options; + parent = this.parent; + start = parent.toScreen(this.data.start); + end = parent.toScreen(this.data.end); + update = util.updateProperty; + box = dom.box; + parentWidth = parent.width; + orientation = options.orientation || this.defaultOptions.orientation; + margin = options.margin && options.margin.axis || this.defaultOptions.margin.axis; + padding = options.padding || this.defaultOptions.padding; - if (properties.fontColor != undefined) {this.fontColor = properties.fontColor;} - if (properties.fontSize != undefined) {this.fontSize = properties.fontSize;} - if (properties.fontFace != undefined) {this.fontFace = properties.fontFace;} + changed += update(props.content, 'width', dom.content.offsetWidth); + + changed += update(this, 'height', box.offsetHeight); + + // limit the width of the this, as browsers cannot draw very wide divs + if (start < -parentWidth) { + start = -parentWidth; + } + if (end > 2 * parentWidth) { + end = 2 * parentWidth; + } + + // when range exceeds left of the window, position the contents at the left of the visible area + if (start < 0) { + contentLeft = Math.min(-start, + (end - start - props.content.width - 2 * padding)); + // TODO: remove the need for options.padding. it's terrible. + } + else { + contentLeft = 0; + } + changed += update(props.content, 'left', contentLeft); + if (orientation == 'top') { + top = margin; + changed += update(this, 'top', top); + } + else { + // default or 'bottom' + top = parent.height - this.height - margin; + changed += update(this, 'top', top); + } - if (this.image != undefined) { - if (this.imagelist) { - this.imageObj = this.imagelist.load(this.image); + changed += update(this, 'left', start); + changed += update(this, 'width', Math.max(end - start, 1)); // TODO: reckon with border width; } else { - throw "No imagelist provided"; + changed += 1; } } - this.xFixed = this.xFixed || (properties.x != undefined); - this.yFixed = this.yFixed || (properties.y != undefined); - this.radiusFixed = this.radiusFixed || (properties.radius != undefined); + return (changed > 0); +}; - if (this.shape == 'image') { - this.radiusMin = constants.nodes.widthMin; - this.radiusMax = constants.nodes.widthMax; - } +/** + * Create an items DOM + * @private + */ +ItemRange.prototype._create = function _create() { + var dom = this.dom; + if (!dom) { + this.dom = dom = {}; + // background box + dom.box = document.createElement('div'); + // className is updated in repaint() - // choose draw method depending on the shape - switch (this.shape) { - case 'database': this.draw = this._drawDatabase; this.resize = this._resizeDatabase; break; - case 'box': this.draw = this._drawBox; this.resize = this._resizeBox; break; - case 'circle': this.draw = this._drawCircle; this.resize = this._resizeCircle; break; - case 'ellipse': this.draw = this._drawEllipse; this.resize = this._resizeEllipse; break; - // TODO: add diamond shape - case 'image': this.draw = this._drawImage; this.resize = this._resizeImage; break; - case 'text': this.draw = this._drawText; this.resize = this._resizeText; break; - case 'dot': this.draw = this._drawDot; this.resize = this._resizeShape; break; - case 'square': this.draw = this._drawSquare; this.resize = this._resizeShape; break; - case 'triangle': this.draw = this._drawTriangle; this.resize = this._resizeShape; break; - case 'triangleDown': this.draw = this._drawTriangleDown; this.resize = this._resizeShape; break; - case 'star': this.draw = this._drawStar; this.resize = this._resizeShape; break; - default: this.draw = this._drawEllipse; this.resize = this._resizeEllipse; break; + // contents box + dom.content = document.createElement('div'); + dom.content.className = 'content'; + dom.box.appendChild(dom.content); } - - // reset the size of the node, this can be changed - this._reset(); }; /** - * Parse a color property into an object with border, background, and - * hightlight colors - * @param {Object | String} color - * @return {Object} colorObject + * Reposition the item, recalculate its left, top, and width, using the current + * range and size of the items itemset + * @override */ -Node.parseColor = function(color) { - var c; - if (util.isString(color)) { - c = { - border: color, - background: color, - highlight: { - border: color, - background: color - } - }; - // TODO: automatically generate a nice highlight color - } - else { - c = {}; - c.background = color.background || 'white'; - c.border = color.border || c.background; - if (util.isString(color.highlight)) { - c.highlight = { - border: color.highlight, - background: color.highlight - } - } - else { - c.highlight = {}; - c.highlight.background = color.highlight && color.highlight.background || c.background; - c.highlight.border = color.highlight && color.highlight.border || c.border; - } +ItemRange.prototype.reposition = function reposition() { + var dom = this.dom, + props = this.props; + + if (dom) { + dom.box.style.top = this.top + 'px'; + dom.box.style.left = this.left + 'px'; + dom.box.style.width = this.width + 'px'; + + dom.content.style.left = props.content.left + 'px'; } - return c; }; /** - * select this node + * @constructor Group + * @param {GroupSet} parent + * @param {Number | String} groupId + * @param {Object} [options] Options to set initial property values + * // TODO: describe available options + * @extends Component */ -Node.prototype.select = function() { - this.selected = true; - this._reset(); -}; +function Group (parent, groupId, options) { + this.id = util.randomUUID(); + this.parent = parent; + + this.groupId = groupId; + this.itemset = null; // ItemSet + this.options = options || {}; + this.options.top = 0; + + this.props = { + label: { + width: 0, + height: 0 + } + }; + + this.top = 0; + this.left = 0; + this.width = 0; + this.height = 0; +} + +Group.prototype = new Component(); + +// TODO: comment +Group.prototype.setOptions = Component.prototype.setOptions; /** - * unselect this node + * Get the container element of the panel, which can be used by a child to + * add its own widgets. + * @returns {HTMLElement} container */ -Node.prototype.unselect = function() { - this.selected = false; - this._reset(); +Group.prototype.getContainer = function () { + return this.parent.getContainer(); }; /** - * Reset the calculated size of the node, forces it to recalculate its size - * @private + * Set item set for the group. The group will create a view on the itemset, + * filtered by the groups id. + * @param {DataSet | DataView} items */ -Node.prototype._reset = function() { - this.width = undefined; - this.height = undefined; +Group.prototype.setItems = function setItems(items) { + if (this.itemset) { + // remove current item set + this.itemset.hide(); + this.itemset.setItems(); + + this.parent.controller.remove(this.itemset); + this.itemset = null; + } + + if (items) { + var groupId = this.groupId; + + var itemsetOptions = Object.create(this.options); + this.itemset = new ItemSet(this, null, itemsetOptions); + this.itemset.setRange(this.parent.range); + + this.view = new DataView(items, { + filter: function (item) { + return item.group == groupId; + } + }); + this.itemset.setItems(this.view); + + this.parent.controller.add(this.itemset); + } }; /** - * get the title of this node. - * @return {string} title The title of the node, or undefined when no title - * has been set. + * Repaint the item + * @return {Boolean} changed */ -Node.prototype.getTitle = function() { - return this.title; +Group.prototype.repaint = function repaint() { + return false; }; /** - * Calculate the distance to the border of the Node - * @param {CanvasRenderingContext2D} ctx - * @param {Number} angle Angle in radians - * @returns {number} distance Distance to the border in pixels + * Reflow the item + * @return {Boolean} resized */ -Node.prototype.distanceToBorder = function (ctx, angle) { - var borderWidth = 1; +Group.prototype.reflow = function reflow() { + var changed = 0, + update = util.updateProperty; - if (!this.width) { - this.resize(ctx); + changed += update(this, 'top', this.itemset ? this.itemset.top : 0); + changed += update(this, 'height', this.itemset ? this.itemset.height : 0); + + // TODO: reckon with the height of the group label + + if (this.label) { + var inner = this.label.firstChild; + changed += update(this.props.label, 'width', inner.clientWidth); + changed += update(this.props.label, 'height', inner.clientHeight); + } + else { + changed += update(this.props.label, 'width', 0); + changed += update(this.props.label, 'height', 0); } - //noinspection FallthroughInSwitchStatementJS - switch (this.shape) { - case 'circle': - case 'dot': - return this.radius + borderWidth; + return (changed > 0); +}; - case 'ellipse': - var a = this.width / 2; - var b = this.height / 2; - var w = (Math.sin(angle) * a); - var h = (Math.cos(angle) * b); - return a * b / Math.sqrt(w * w + h * h); +/** + * An GroupSet holds a set of groups + * @param {Component} parent + * @param {Component[]} [depends] Components on which this components depends + * (except for the parent) + * @param {Object} [options] See GroupSet.setOptions for the available + * options. + * @constructor GroupSet + * @extends Panel + */ +function GroupSet(parent, depends, options) { + this.id = util.randomUUID(); + this.parent = parent; + this.depends = depends; - // TODO: implement distanceToBorder for database - // TODO: implement distanceToBorder for triangle - // TODO: implement distanceToBorder for triangleDown + this.options = options || {}; + + this.range = null; // Range or Object {start: number, end: number} + this.itemsData = null; // DataSet with items + this.groupsData = null; // DataSet with groups + + this.groups = {}; // map with groups + + this.dom = {}; + this.props = { + labels: { + width: 0 + } + }; - case 'box': - case 'image': - case 'text': - default: - if (this.width) { - return Math.min( - Math.abs(this.width / 2 / Math.cos(angle)), - Math.abs(this.height / 2 / Math.sin(angle))) + borderWidth; - // TODO: reckon with border radius too in case of box - } - else { - return 0; - } + // TODO: implement right orientation of the labels - } + // changes in groups are queued key/value map containing id/action + this.queue = {}; - // TODO: implement calculation of distance to border for all shapes -}; + var me = this; + this.listeners = { + 'add': function (event, params) { + me._onAdd(params.items); + }, + 'update': function (event, params) { + me._onUpdate(params.items); + }, + 'remove': function (event, params) { + me._onRemove(params.items); + } + }; +} -/** - * Set forces acting on the node - * @param {number} fx Force in horizontal direction - * @param {number} fy Force in vertical direction - */ -Node.prototype._setForce = function(fx, fy) { - this.fx = fx; - this.fy = fy; -}; +GroupSet.prototype = new Panel(); /** - * Add forces acting on the node - * @param {number} fx Force in horizontal direction - * @param {number} fy Force in vertical direction - * @private + * Set options for the GroupSet. Existing options will be extended/overwritten. + * @param {Object} [options] The following options are available: + * {String | function} groupsOrder + * TODO: describe options */ -Node.prototype._addForce = function(fx, fy) { - this.fx += fx; - this.fy += fy; +GroupSet.prototype.setOptions = Component.prototype.setOptions; + +GroupSet.prototype.setRange = function (range) { + // TODO: implement setRange }; /** - * Perform one discrete step for the node - * @param {number} interval Time interval in seconds + * Set items + * @param {vis.DataSet | null} items */ -Node.prototype.discreteStep = function(interval) { - if (!this.xFixed) { - var dx = -this.damping * this.vx; // damping force - var ax = (this.fx + dx) / this.mass; // acceleration - this.vx += ax / interval; // velocity - this.x += this.vx / interval; // position - } +GroupSet.prototype.setItems = function setItems(items) { + this.itemsData = items; - if (!this.yFixed) { - var dy = -this.damping * this.vy; // damping force - var ay = (this.fy + dy) / this.mass; // acceleration - this.vy += ay / interval; // velocity - this.y += this.vy / interval; // position + for (var id in this.groups) { + if (this.groups.hasOwnProperty(id)) { + var group = this.groups[id]; + group.setItems(items); + } } }; - /** - * Check if this node has a fixed x and y position - * @return {boolean} true if fixed, false if not + * Get items + * @return {vis.DataSet | null} items */ -Node.prototype.isFixed = function() { - return (this.xFixed && this.yFixed); +GroupSet.prototype.getItems = function getItems() { + return this.itemsData; }; /** - * Check if this node is moving - * @param {number} vmin the minimum velocity considered as "moving" - * @return {boolean} true if moving, false if it has no velocity + * Set range (start and end). + * @param {Range | Object} range A Range or an object containing start and end. */ -// TODO: replace this method with calculating the kinetic energy -Node.prototype.isMoving = function(vmin) { - return (Math.abs(this.vx) > vmin || Math.abs(this.vy) > vmin || - (!this.xFixed && Math.abs(this.fx) > this.minForce) || - (!this.yFixed && Math.abs(this.fy) > this.minForce)); +GroupSet.prototype.setRange = function setRange(range) { + this.range = range; }; /** - * check if this node is selecte - * @return {boolean} selected True if node is selected, else false + * Set groups + * @param {vis.DataSet} groups */ -Node.prototype.isSelected = function() { - return this.selected; -}; +GroupSet.prototype.setGroups = function setGroups(groups) { + var me = this, + ids; -/** - * Retrieve the value of the node. Can be undefined - * @return {Number} value - */ -Node.prototype.getValue = function() { - return this.value; -}; + // unsubscribe from current dataset + if (this.groupsData) { + util.forEach(this.listeners, function (callback, event) { + me.groupsData.unsubscribe(event, callback); + }); -/** - * Calculate the distance from the nodes location to the given location (x,y) - * @param {Number} x - * @param {Number} y - * @return {Number} value - */ -Node.prototype.getDistance = function(x, y) { - var dx = this.x - x, - dy = this.y - y; - return Math.sqrt(dx * dx + dy * dy); -}; + // remove all drawn groups + ids = this.groupsData.getIds(); + this._onRemove(ids); + } + // replace the dataset + if (!groups) { + this.groupsData = null; + } + else if (groups instanceof DataSet) { + this.groupsData = groups; + } + else { + this.groupsData = new DataSet({ + convert: { + start: 'Date', + end: 'Date' + } + }); + this.groupsData.add(groups); + } -/** - * Adjust the value range of the node. The node will adjust it's radius - * based on its value. - * @param {Number} min - * @param {Number} max - */ -Node.prototype.setValueRange = function(min, max) { - if (!this.radiusFixed && this.value !== undefined) { - var scale = (this.radiusMax - this.radiusMin) / (max - min); - this.radius = (this.value - min) * scale + this.radiusMin; + if (this.groupsData) { + // subscribe to new dataset + var id = this.id; + util.forEach(this.listeners, function (callback, event) { + me.groupsData.subscribe(event, callback, id); + }); + + // draw all new groups + ids = this.groupsData.getIds(); + this._onAdd(ids); } }; /** - * Draw this node in the given canvas - * The 2d context of a HTML canvas can be retrieved by canvas.getContext("2d"); - * @param {CanvasRenderingContext2D} ctx + * Get groups + * @return {vis.DataSet | null} groups */ -Node.prototype.draw = function(ctx) { - throw "Draw method not initialized for node"; +GroupSet.prototype.getGroups = function getGroups() { + return this.groupsData; }; /** - * Recalculate the size of this node in the given canvas - * The 2d context of a HTML canvas can be retrieved by canvas.getContext("2d"); - * @param {CanvasRenderingContext2D} ctx + * Repaint the component + * @return {Boolean} changed */ -Node.prototype.resize = function(ctx) { - throw "Resize method not initialized for node"; -}; +GroupSet.prototype.repaint = function repaint() { + var changed = 0, + i, id, group, label, + update = util.updateProperty, + asSize = util.option.asSize, + asElement = util.option.asElement, + options = this.options, + frame = this.dom.frame, + labels = this.dom.labels; -/** - * Check if this object is overlapping with the provided object - * @param {Object} obj an object with parameters left, top, right, bottom - * @return {boolean} True if location is located on node - */ -Node.prototype.isOverlappingWith = function(obj) { - return (this.left < obj.right && - this.left + this.width > obj.left && - this.top < obj.bottom && - this.top + this.height > obj.top); -}; + // create frame + if (!this.parent) { + throw new Error('Cannot repaint groupset: no parent attached'); + } + var parentContainer = this.parent.getContainer(); + if (!parentContainer) { + throw new Error('Cannot repaint groupset: parent has no container element'); + } + if (!frame) { + frame = document.createElement('div'); + frame.className = 'groupset'; + this.dom.frame = frame; -Node.prototype._resizeImage = function (ctx) { - // TODO: pre calculate the image size - if (!this.width) { // undefined or 0 - var width, height; - if (this.value) { - var scale = this.imageObj.height / this.imageObj.width; - width = this.radius || this.imageObj.width; - height = this.radius * scale || this.imageObj.height; + var className = options.className; + if (className) { + util.addClassName(frame, util.option.asString(className)); } - else { - width = this.imageObj.width; - height = this.imageObj.height; + + changed += 1; + } + if (!frame.parentNode) { + parentContainer.appendChild(frame); + changed += 1; + } + + // create labels + var labelContainer = asElement(options.labelContainer); + if (!labelContainer) { + throw new Error('Cannot repaint groupset: option "labelContainer" not defined'); + } + if (!labels) { + labels = document.createElement('div'); + labels.className = 'labels'; + //frame.appendChild(labels); + this.dom.labels = labels; + } + if (!labels.parentNode || labels.parentNode != labelContainer) { + if (labels.parentNode) { + labels.parentNode.removeChild(labels.parentNode); } - this.width = width; - this.height = height; + labelContainer.appendChild(labels); } -}; -Node.prototype._drawImage = function (ctx) { - this._resizeImage(ctx); + // reposition frame + changed += update(frame.style, 'height', asSize(options.height, this.height + 'px')); + changed += update(frame.style, 'top', asSize(options.top, '0px')); + changed += update(frame.style, 'left', asSize(options.left, '0px')); + changed += update(frame.style, 'width', asSize(options.width, '100%')); - this.left = this.x - this.width / 2; - this.top = this.y - this.height / 2; + // reposition labels + changed += update(labels.style, 'top', asSize(options.top, '0px')); - var yLabel; - if (this.imageObj) { - ctx.drawImage(this.imageObj, this.left, this.top, this.width, this.height); - yLabel = this.y + this.height / 2; - } - else { - // image still loading... just draw the label for now - yLabel = this.y; - } + var me = this, + queue = this.queue, + groups = this.groups, + groupsData = this.groupsData; - this._label(ctx, this.label, this.x, yLabel, undefined, "top"); -}; + // show/hide added/changed/removed groups + var ids = Object.keys(queue); + if (ids.length) { + ids.forEach(function (id) { + var action = queue[id]; + var group = groups[id]; + //noinspection FallthroughInSwitchStatementJS + switch (action) { + case 'add': + case 'update': + if (!group) { + var groupOptions = Object.create(me.options); + group = new Group(me, id, groupOptions); + group.setItems(me.itemsData); // attach items data + groups[id] = group; -Node.prototype._resizeBox = function (ctx) { - if (!this.width) { - var margin = 5; - var textSize = this.getTextSize(ctx); - this.width = textSize.width + 2 * margin; - this.height = textSize.height + 2 * margin; - } -}; + me.controller.add(group); + } -Node.prototype._drawBox = function (ctx) { - this._resizeBox(ctx); + // TODO: update group data + group.data = groupsData.get(id); - this.left = this.x - this.width / 2; - this.top = this.y - this.height / 2; + delete queue[id]; + break; - ctx.strokeStyle = this.selected ? this.color.highlight.border : this.color.border; - ctx.fillStyle = this.selected ? this.color.highlight.background : this.color.background; - ctx.lineWidth = this.selected ? 2.0 : 1.0; - ctx.roundRect(this.left, this.top, this.width, this.height, this.radius); - ctx.fill(); - ctx.stroke(); + case 'remove': + if (group) { + group.setItems(); // detach items data + delete groups[id]; - this._label(ctx, this.label, this.x, this.y); -}; + me.controller.remove(group); + } + // update lists + delete queue[id]; + break; -Node.prototype._resizeDatabase = function (ctx) { - if (!this.width) { - var margin = 5; - var textSize = this.getTextSize(ctx); - var size = textSize.width + 2 * margin; - this.width = size; - this.height = size; - } -}; + default: + console.log('Error: unknown action "' + action + '"'); + } + }); -Node.prototype._drawDatabase = function (ctx) { - this._resizeDatabase(ctx); - this.left = this.x - this.width / 2; - this.top = this.y - this.height / 2; + // the groupset depends on each of the groups + //this.depends = this.groups; // TODO: gives a circular reference through the parent - ctx.strokeStyle = this.selected ? this.color.highlight.border : this.color.border; - ctx.fillStyle = this.selected ? this.color.highlight.background : this.color.background; - ctx.lineWidth = this.selected ? 2.0 : 1.0; - ctx.database(this.x - this.width/2, this.y - this.height*0.5, this.width, this.height); - ctx.fill(); - ctx.stroke(); + // TODO: apply dependencies of the groupset - this._label(ctx, this.label, this.x, this.y); -}; + // update the top positions of the groups in the correct order + var orderedGroups = this.groupsData.getIds({ + order: this.options.groupsOrder + }); + for (i = 0; i < orderedGroups.length; i++) { + (function (group, prevGroup) { + var top = 0; + if (prevGroup) { + top = function () { + // TODO: top must reckon with options.maxHeight + return prevGroup.top + prevGroup.height; + } + } + group.setOptions({ + top: top + }); + })(groups[orderedGroups[i]], groups[orderedGroups[i - 1]]); + } + // (re)create the labels + while (labels.firstChild) { + labels.removeChild(labels.firstChild); + } + for (i = 0; i < orderedGroups.length; i++) { + id = orderedGroups[i]; + label = this._createLabel(id); + labels.appendChild(label); + } -Node.prototype._resizeCircle = function (ctx) { - if (!this.width) { - var margin = 5; - var textSize = this.getTextSize(ctx); - var diameter = Math.max(textSize.width, textSize.height) + 2 * margin; - this.radius = diameter / 2; + changed++; + } - this.width = diameter; - this.height = diameter; + // reposition the labels + // TODO: labels are not displayed correctly when orientation=='top' + // TODO: width of labelPanel is not immediately updated on a change in groups + for (id in groups) { + if (groups.hasOwnProperty(id)) { + group = groups[id]; + label = group.label; + if (label) { + label.style.top = group.top + 'px'; + label.style.height = group.height + 'px'; + } + } } + + return (changed > 0); }; -Node.prototype._drawCircle = function (ctx) { - this._resizeCircle(ctx); - this.left = this.x - this.width / 2; - this.top = this.y - this.height / 2; +/** + * Create a label for group with given id + * @param {Number} id + * @return {Element} label + * @private + */ +GroupSet.prototype._createLabel = function(id) { + var group = this.groups[id]; + var label = document.createElement('div'); + label.className = 'label'; + var inner = document.createElement('div'); + inner.className = 'inner'; + label.appendChild(inner); - ctx.strokeStyle = this.selected ? this.color.highlight.border : this.color.border; - ctx.fillStyle = this.selected ? this.color.highlight.background : this.color.background; - ctx.lineWidth = this.selected ? 2.0 : 1.0; - ctx.circle(this.x, this.y, this.radius); - ctx.fill(); - ctx.stroke(); + var content = group.data && group.data.content; + if (content instanceof Element) { + inner.appendChild(content); + } + else if (content != undefined) { + inner.innerHTML = content; + } - this._label(ctx, this.label, this.x, this.y); + var className = group.data && group.data.className; + if (className) { + util.addClassName(label, className); + } + + group.label = label; // TODO: not so nice, parking labels in the group this way!!! + + return label; }; -Node.prototype._resizeEllipse = function (ctx) { - if (!this.width) { - var textSize = this.getTextSize(ctx); +/** + * Get container element + * @return {HTMLElement} container + */ +GroupSet.prototype.getContainer = function getContainer() { + return this.dom.frame; +}; - this.width = textSize.width * 1.5; - this.height = textSize.height * 2; - if (this.width < this.height) { - this.width = this.height; +/** + * Get the width of the group labels + * @return {Number} width + */ +GroupSet.prototype.getLabelsWidth = function getContainer() { + return this.props.labels.width; +}; + +/** + * Reflow the component + * @return {Boolean} resized + */ +GroupSet.prototype.reflow = function reflow() { + var changed = 0, + id, group, + options = this.options, + update = util.updateProperty, + asNumber = util.option.asNumber, + asSize = util.option.asSize, + frame = this.dom.frame; + + if (frame) { + var maxHeight = asNumber(options.maxHeight); + var fixedHeight = (asSize(options.height) != null); + var height; + if (fixedHeight) { + height = frame.offsetHeight; + } + else { + // height is not specified, calculate the sum of the height of all groups + height = 0; + + for (id in this.groups) { + if (this.groups.hasOwnProperty(id)) { + group = this.groups[id]; + height += group.height; + } + } + } + if (maxHeight != null) { + height = Math.min(height, maxHeight); } - } -}; - -Node.prototype._drawEllipse = function (ctx) { - this._resizeEllipse(ctx); - this.left = this.x - this.width / 2; - this.top = this.y - this.height / 2; + changed += update(this, 'height', height); - ctx.strokeStyle = this.selected ? this.color.highlight.border : this.color.border; - ctx.fillStyle = this.selected ? this.color.highlight.background : this.color.background; - ctx.lineWidth = this.selected ? 2.0 : 1.0; - ctx.ellipse(this.left, this.top, this.width, this.height); - ctx.fill(); - ctx.stroke(); + changed += update(this, 'top', frame.offsetTop); + changed += update(this, 'left', frame.offsetLeft); + changed += update(this, 'width', frame.offsetWidth); + } - this._label(ctx, this.label, this.x, this.y); -}; + // calculate the maximum width of the labels + var width = 0; + for (id in this.groups) { + if (this.groups.hasOwnProperty(id)) { + group = this.groups[id]; + var labelWidth = group.props && group.props.label && group.props.label.width || 0; + width = Math.max(width, labelWidth); + } + } + changed += update(this.props.labels, 'width', width); -Node.prototype._drawDot = function (ctx) { - this._drawShape(ctx, 'circle'); + return (changed > 0); }; -Node.prototype._drawTriangle = function (ctx) { - this._drawShape(ctx, 'triangle'); +/** + * Hide the component from the DOM + * @return {Boolean} changed + */ +GroupSet.prototype.hide = function hide() { + if (this.dom.frame && this.dom.frame.parentNode) { + this.dom.frame.parentNode.removeChild(this.dom.frame); + return true; + } + else { + return false; + } }; -Node.prototype._drawTriangleDown = function (ctx) { - this._drawShape(ctx, 'triangleDown'); +/** + * Show the component in the DOM (when not already visible). + * A repaint will be executed when the component is not visible + * @return {Boolean} changed + */ +GroupSet.prototype.show = function show() { + if (!this.dom.frame || !this.dom.frame.parentNode) { + return this.repaint(); + } + else { + return false; + } }; -Node.prototype._drawSquare = function (ctx) { - this._drawShape(ctx, 'square'); +/** + * Handle updated groups + * @param {Number[]} ids + * @private + */ +GroupSet.prototype._onUpdate = function _onUpdate(ids) { + this._toQueue(ids, 'update'); }; -Node.prototype._drawStar = function (ctx) { - this._drawShape(ctx, 'star'); +/** + * Handle changed groups + * @param {Number[]} ids + * @private + */ +GroupSet.prototype._onAdd = function _onAdd(ids) { + this._toQueue(ids, 'add'); }; -Node.prototype._resizeShape = function (ctx) { - if (!this.width) { - var size = 2 * this.radius; - this.width = size; - this.height = size; - } +/** + * Handle removed groups + * @param {Number[]} ids + * @private + */ +GroupSet.prototype._onRemove = function _onRemove(ids) { + this._toQueue(ids, 'remove'); }; -Node.prototype._drawShape = function (ctx, shape) { - this._resizeShape(ctx); - - this.left = this.x - this.width / 2; - this.top = this.y - this.height / 2; - - ctx.strokeStyle = this.selected ? this.color.highlight.border : this.color.border; - ctx.fillStyle = this.selected ? this.color.highlight.background : this.color.background; - ctx.lineWidth = this.selected ? 2.0 : 1.0; - - ctx[shape](this.x, this.y, this.radius); - ctx.fill(); - ctx.stroke(); - - if (this.label) { - this._label(ctx, this.label, this.x, this.y + this.height / 2, undefined, 'top'); - } -}; +/** + * Put groups in the queue to be added/updated/remove + * @param {Number[]} ids + * @param {String} action can be 'add', 'update', 'remove' + */ +GroupSet.prototype._toQueue = function _toQueue(ids, action) { + var queue = this.queue; + ids.forEach(function (id) { + queue[id] = action; + }); -Node.prototype._resizeText = function (ctx) { - if (!this.width) { - var margin = 5; - var textSize = this.getTextSize(ctx); - this.width = textSize.width + 2 * margin; - this.height = textSize.height + 2 * margin; + if (this.controller) { + //this.requestReflow(); + this.requestRepaint(); } }; -Node.prototype._drawText = function (ctx) { - this._resizeText(ctx); - this.left = this.x - this.width / 2; - this.top = this.y - this.height / 2; - - this._label(ctx, this.label, this.x, this.y); -}; +/** + * Create a timeline visualization + * @param {HTMLElement} container + * @param {vis.DataSet | Array | DataTable} [items] + * @param {Object} [options] See Timeline.setOptions for the available options. + * @constructor + */ +function Timeline (container, items, options) { + var me = this; + this.options = util.extend({ + orientation: 'bottom', + min: null, + max: null, + zoomMin: 10, // milliseconds + zoomMax: 1000 * 60 * 60 * 24 * 365 * 10000, // milliseconds + // moveable: true, // TODO: option moveable + // zoomable: true, // TODO: option zoomable + showMinorLabels: true, + showMajorLabels: true, + autoResize: false + }, options); + // controller + this.controller = new Controller(); -Node.prototype._label = function (ctx, text, x, y, align, baseline) { - if (text) { - ctx.font = (this.selected ? "bold " : "") + this.fontSize + "px " + this.fontFace; - ctx.fillStyle = this.fontColor || "black"; - ctx.textAlign = align || "center"; - ctx.textBaseline = baseline || "middle"; + // root panel + if (!container) { + throw new Error('No container element provided'); + } + var rootOptions = Object.create(this.options); + rootOptions.height = function () { + if (me.options.height) { + // fixed height + return me.options.height; + } + else { + // auto height + return me.timeaxis.height + me.content.height; + } + }; + this.rootPanel = new RootPanel(container, rootOptions); + this.controller.add(this.rootPanel); - var lines = text.split('\n'), - lineCount = lines.length, - fontSize = (this.fontSize + 4), - yLine = y + (1 - lineCount) / 2 * fontSize; + // item panel + var itemOptions = Object.create(this.options); + itemOptions.left = function () { + return me.labelPanel.width; + }; + itemOptions.width = function () { + return me.rootPanel.width - me.labelPanel.width; + }; + itemOptions.top = null; + itemOptions.height = null; + this.itemPanel = new Panel(this.rootPanel, [], itemOptions); + this.controller.add(this.itemPanel); - for (var i = 0; i < lineCount; i++) { - ctx.fillText(lines[i], x, yLine); - yLine += fontSize; + // label panel + var labelOptions = Object.create(this.options); + labelOptions.top = null; + labelOptions.left = null; + labelOptions.height = null; + labelOptions.width = function () { + if (me.content && typeof me.content.getLabelsWidth === 'function') { + return me.content.getLabelsWidth(); } - } -}; + else { + return 0; + } + }; + this.labelPanel = new Panel(this.rootPanel, [], labelOptions); + this.controller.add(this.labelPanel); + + // range + var now = moment().hours(0).minutes(0).seconds(0).milliseconds(0); + this.range = new Range({ + start: now.clone().add('days', -3).valueOf(), + end: now.clone().add('days', 4).valueOf() + }); + /* TODO: fix range options + var rangeOptions = Object.create(this.options); + this.range = new Range(rangeOptions); + this.range.setRange( + now.clone().add('days', -3).valueOf(), + now.clone().add('days', 4).valueOf() + ); + */ + // TODO: reckon with options moveable and zoomable + this.range.subscribe(this.rootPanel, 'move', 'horizontal'); + this.range.subscribe(this.rootPanel, 'zoom', 'horizontal'); + this.range.on('rangechange', function () { + var force = true; + me.controller.requestReflow(force); + }); + this.range.on('rangechanged', function () { + var force = true; + me.controller.requestReflow(force); + }); + // TODO: put the listeners in setOptions, be able to dynamically change with options moveable and zoomable -Node.prototype.getTextSize = function(ctx) { - if (this.label != undefined) { - ctx.font = (this.selected ? "bold " : "") + this.fontSize + "px " + this.fontFace; + // time axis + var timeaxisOptions = Object.create(rootOptions); + timeaxisOptions.range = this.range; + timeaxisOptions.left = null; + timeaxisOptions.top = null; + timeaxisOptions.width = '100%'; + timeaxisOptions.height = null; + this.timeaxis = new TimeAxis(this.itemPanel, [], timeaxisOptions); + this.timeaxis.setRange(this.range); + this.controller.add(this.timeaxis); - var lines = this.label.split('\n'), - height = (this.fontSize + 4) * lines.length, - width = 0; + // create itemset or groupset + this.setGroups(null); - for (var i = 0, iMax = lines.length; i < iMax; i++) { - width = Math.max(width, ctx.measureText(lines[i]).width); - } + this.itemsData = null; // DataSet + this.groupsData = null; // DataSet - return {"width": width, "height": height}; - } - else { - return {"width": 0, "height": 0}; + // set data + if (items) { + this.setItems(items); } -}; +} /** - * @class Edge - * - * A edge connects two nodes - * @param {Object} properties Object with properties. Must contain - * At least properties from and to. - * Available properties: from (number), - * to (number), label (string, color (string), - * width (number), style (string), - * length (number), title (string) - * @param {Graph} graph A graph object, used to find and edge to - * nodes. - * @param {Object} constants An object with default values for - * example for the color + * Set options + * @param {Object} options TODO: describe the available options */ -function Edge (properties, graph, constants) { - if (!graph) { - throw "No graph provided"; +Timeline.prototype.setOptions = function (options) { + if (options) { + util.extend(this.options, options); } - this.graph = graph; - - // initialize constants - this.widthMin = constants.edges.widthMin; - this.widthMax = constants.edges.widthMax; - - // initialize variables - this.id = undefined; - this.fromId = undefined; - this.toId = undefined; - this.style = constants.edges.style; - this.title = undefined; - this.width = constants.edges.width; - this.value = undefined; - this.length = constants.edges.length; - - this.from = null; // a node - this.to = null; // a node - this.connected = false; - - // Added to support dashed lines - // David Jordan - // 2012-08-08 - this.dash = util.extend({}, constants.edges.dash); // contains properties length, gap, altLength - this.stiffness = undefined; // depends on the length of the edge - this.color = constants.edges.color; - this.widthFixed = false; - this.lengthFixed = false; + // TODO: apply range min,max - this.setProperties(properties, constants); -} + this.controller.reflow(); + this.controller.repaint(); +}; /** - * Set or overwrite properties for the edge - * @param {Object} properties an object with properties - * @param {Object} constants and object with default, global properties + * Set items + * @param {vis.DataSet | Array | DataTable | null} items */ -Edge.prototype.setProperties = function(properties, constants) { - if (!properties) { - return; +Timeline.prototype.setItems = function(items) { + var initialLoad = (this.itemsData == null); + + // convert to type DataSet when needed + var newItemSet; + if (!items) { + newItemSet = null; + } + else if (items instanceof DataSet) { + newItemSet = items; + } + if (!(items instanceof DataSet)) { + newItemSet = new DataSet({ + convert: { + start: 'Date', + end: 'Date' + } + }); + newItemSet.add(items); } - if (properties.from != undefined) {this.fromId = properties.from;} - if (properties.to != undefined) {this.toId = properties.to;} + // set items + this.itemsData = newItemSet; + this.content.setItems(newItemSet); - if (properties.id != undefined) {this.id = properties.id;} - if (properties.style != undefined) {this.style = properties.style;} - if (properties.label != undefined) {this.label = properties.label;} - if (this.label) { - this.fontSize = constants.edges.fontSize; - this.fontFace = constants.edges.fontFace; - this.fontColor = constants.edges.fontColor; - if (properties.fontColor != undefined) {this.fontColor = properties.fontColor;} - if (properties.fontSize != undefined) {this.fontSize = properties.fontSize;} - if (properties.fontFace != undefined) {this.fontFace = properties.fontFace;} - } - if (properties.title != undefined) {this.title = properties.title;} - if (properties.width != undefined) {this.width = properties.width;} - if (properties.value != undefined) {this.value = properties.value;} - if (properties.length != undefined) {this.length = properties.length;} + if (initialLoad && (this.options.start == undefined || this.options.end == undefined)) { + // apply the data range as range + var dataRange = this.getItemRange(); - // Added to support dashed lines - // David Jordan - // 2012-08-08 - if (properties.dash) { - if (properties.dash.length != undefined) {this.dash.length = properties.dash.length;} - if (properties.dash.gap != undefined) {this.dash.gap = properties.dash.gap;} - if (properties.dash.altLength != undefined) {this.dash.altLength = properties.dash.altLength;} + // add 5% on both sides + var min = dataRange.min; + var max = dataRange.max; + if (min != null && max != null) { + var interval = (max.valueOf() - min.valueOf()); + if (interval <= 0) { + // prevent an empty interval + interval = 24 * 60 * 60 * 1000; // 1 day + } + min = new Date(min.valueOf() - interval * 0.05); + max = new Date(max.valueOf() + interval * 0.05); + } + + // override specified start and/or end date + if (this.options.start != undefined) { + min = new Date(this.options.start.valueOf()); + } + if (this.options.end != undefined) { + max = new Date(this.options.end.valueOf()); + } + + // apply range if there is a min or max available + if (min != null || max != null) { + this.range.setRange(min, max); + } } - - if (properties.color != undefined) {this.color = properties.color;} +}; - // A node is connected when it has a from and to node. - this.connect(); +/** + * Set groups + * @param {vis.DataSet | Array | DataTable} groups + */ +Timeline.prototype.setGroups = function(groups) { + var me = this; + this.groupsData = groups; - this.widthFixed = this.widthFixed || (properties.width != undefined); - this.lengthFixed = this.lengthFixed || (properties.length != undefined); - this.stiffness = 1 / this.length; + // switch content type between ItemSet or GroupSet when needed + var type = this.groupsData ? GroupSet : ItemSet; + if (!(this.content instanceof type)) { + // remove old content set + if (this.content) { + this.content.hide(); + if (this.content.setItems) { + this.content.setItems(); // disconnect from items + } + if (this.content.setGroups) { + this.content.setGroups(); // disconnect from groups + } + this.controller.remove(this.content); + } - // set draw method based on style - switch (this.style) { - case 'line': this.draw = this._drawLine; break; - case 'arrow': this.draw = this._drawArrow; break; - case 'arrow-center': this.draw = this._drawArrowCenter; break; - case 'dash-line': this.draw = this._drawDashLine; break; - default: this.draw = this._drawLine; break; + // create new content set + var options = Object.create(this.options); + util.extend(options, { + top: function () { + if (me.options.orientation == 'top') { + return me.timeaxis.height; + } + else { + return me.itemPanel.height - me.timeaxis.height - me.content.height; + } + }, + left: null, + width: '100%', + height: function () { + if (me.options.height) { + return me.itemPanel.height - me.timeaxis.height; + } + else { + return null; + } + }, + maxHeight: function () { + if (me.options.maxHeight) { + if (!util.isNumber(me.options.maxHeight)) { + throw new TypeError('Number expected for property maxHeight'); + } + return me.options.maxHeight - me.timeaxis.height; + } + else { + return null; + } + }, + labelContainer: function () { + return me.labelPanel.getContainer(); + } + }); + this.content = new type(this.itemPanel, [this.timeaxis], options); + if (this.content.setRange) { + this.content.setRange(this.range); + } + if (this.content.setItems) { + this.content.setItems(this.itemsData); + } + if (this.content.setGroups) { + this.content.setGroups(this.groupsData); + } + this.controller.add(this.content); } }; /** - * Connect an edge to its nodes + * Get the data range of the item set. + * @returns {{min: Date, max: Date}} range A range with a start and end Date. + * When no minimum is found, min==null + * When no maximum is found, max==null */ -Edge.prototype.connect = function () { - this.disconnect(); - - this.from = this.graph.nodes[this.fromId] || null; - this.to = this.graph.nodes[this.toId] || null; - this.connected = (this.from && this.to); +Timeline.prototype.getItemRange = function getItemRange() { + // calculate min from start filed + var itemsData = this.itemsData, + min = null, + max = null; - if (this.connected) { - this.from.attachEdge(this); - this.to.attachEdge(this); - } - else { - if (this.from) { - this.from.detachEdge(this); + if (itemsData) { + // calculate the minimum value of the field 'start' + var minItem = itemsData.min('start'); + min = minItem ? minItem.start.valueOf() : null; + + // calculate maximum value of fields 'start' and 'end' + var maxStartItem = itemsData.max('start'); + if (maxStartItem) { + max = maxStartItem.start.valueOf(); } - if (this.to) { - this.to.detachEdge(this); + var maxEndItem = itemsData.max('end'); + if (maxEndItem) { + if (max == null) { + max = maxEndItem.end.valueOf(); + } + else { + max = Math.max(max, maxEndItem.end.valueOf()); + } } } + + return { + min: (min != null) ? new Date(min) : null, + max: (max != null) ? new Date(max) : null + }; }; -/** - * Disconnect an edge from its nodes - */ -Edge.prototype.disconnect = function () { - if (this.from) { - this.from.detachEdge(this); - this.from = null; - } - if (this.to) { - this.to.detachEdge(this); - this.to = null; +(function(exports) { + /** + * Parse a text source containing data in DOT language into a JSON object. + * The object contains two lists: one with nodes and one with edges. + * + * DOT language reference: http://www.graphviz.org/doc/info/lang.html + * + * @param {String} data Text containing a graph in DOT-notation + * @return {Object} graph An object containing two parameters: + * {Object[]} nodes + * {Object[]} edges + */ + function parseDOT (data) { + dot = data; + return parseGraph(); } - this.connected = false; -}; + // token types enumeration + var TOKENTYPE = { + NULL : 0, + DELIMITER : 1, + IDENTIFIER: 2, + UNKNOWN : 3 + }; -/** - * get the title of this edge. - * @return {string} title The title of the edge, or undefined when no title - * has been set. - */ -Edge.prototype.getTitle = function() { - return this.title; -}; + // map with all delimiters + var DELIMITERS = { + '{': true, + '}': true, + '[': true, + ']': true, + ';': true, + '=': true, + ',': true, + '->': true, + '--': true + }; -/** - * Retrieve the value of the edge. Can be undefined - * @return {Number} value - */ -Edge.prototype.getValue = function() { - return this.value; -}; + var dot = ''; // current dot file + var index = 0; // current index in dot file + var c = ''; // current token character in expr + var token = ''; // current token + var tokenType = TOKENTYPE.NULL; // type of the token -/** - * Adjust the value range of the edge. The edge will adjust it's width - * based on its value. - * @param {Number} min - * @param {Number} max - */ -Edge.prototype.setValueRange = function(min, max) { - if (!this.widthFixed && this.value !== undefined) { - var factor = (this.widthMax - this.widthMin) / (max - min); - this.width = (this.value - min) * factor + this.widthMin; + /** + * Get the first character from the dot file. + * The character is stored into the char c. If the end of the dot file is + * reached, the function puts an empty string in c. + */ + function first() { + index = 0; + c = dot.charAt(0); } -}; - -/** - * Redraw a edge - * Draw this edge in the given canvas - * The 2d context of a HTML canvas can be retrieved by canvas.getContext("2d"); - * @param {CanvasRenderingContext2D} ctx - */ -Edge.prototype.draw = function(ctx) { - throw "Method draw not initialized in edge"; -}; -/** - * Check if this object is overlapping with the provided object - * @param {Object} obj an object with parameters left, top - * @return {boolean} True if location is located on the edge - */ -Edge.prototype.isOverlappingWith = function(obj) { - var distMax = 10; + /** + * Get the next character from the dot file. + * The character is stored into the char c. If the end of the dot file is + * reached, the function puts an empty string in c. + */ + function next() { + index++; + c = dot.charAt(index); + } - var xFrom = this.from.x; - var yFrom = this.from.y; - var xTo = this.to.x; - var yTo = this.to.y; - var xObj = obj.left; - var yObj = obj.top; + /** + * Preview the next character from the dot file. + * @return {String} cNext + */ + function nextPreview() { + return dot.charAt(index + 1); + } + /** + * Test whether given character is alphabetic or numeric + * @param {String} c + * @return {Boolean} isAlphaNumeric + */ + var regexAlphaNumeric = /[a-zA-Z_0-9.:#]/; + function isAlphaNumeric(c) { + return regexAlphaNumeric.test(c); + } - var dist = Edge._dist(xFrom, yFrom, xTo, yTo, xObj, yObj); + /** + * Merge all properties of object b into object b + * @param {Object} a + * @param {Object} b + * @return {Object} a + */ + function merge (a, b) { + if (!a) { + a = {}; + } - return (dist < distMax); -}; + if (b) { + for (var name in b) { + if (b.hasOwnProperty(name)) { + a[name] = b[name]; + } + } + } + return a; + } + /** + * Set a value in an object, where the provided parameter name can be a + * path with nested parameters. For example: + * + * var obj = {a: 2}; + * setValue(obj, 'b.c', 3); // obj = {a: 2, b: {c: 3}} + * + * @param {Object} obj + * @param {String} path A parameter name or dot-separated parameter path, + * like "color.highlight.border". + * @param {*} value + */ + function setValue(obj, path, value) { + var keys = path.split('.'); + var o = obj; + while (keys.length) { + var key = keys.shift(); + if (keys.length) { + // this isn't the end point + if (!o[key]) { + o[key] = {}; + } + o = o[key]; + } + else { + // this is the end point + o[key] = value; + } + } + } -/** - * Redraw a edge as a line - * Draw this edge in the given canvas - * The 2d context of a HTML canvas can be retrieved by canvas.getContext("2d"); - * @param {CanvasRenderingContext2D} ctx - * @private - */ -Edge.prototype._drawLine = function(ctx) { - // set style - ctx.strokeStyle = this.color; - ctx.lineWidth = this._getLineWidth(); + /** + * Add a node to a graph object. If there is already a node with + * the same id, their attributes will be merged. + * @param {Object} graph + * @param {Object} node + */ + function addNode(graph, node) { + var i, len; + var current = null; - var point; - if (this.from != this.to) { - // draw line - this._line(ctx); + // find root graph (in case of subgraph) + var graphs = [graph]; // list with all graphs from current graph to root graph + var root = graph; + while (root.parent) { + graphs.push(root.parent); + root = root.parent; + } - // draw label - if (this.label) { - point = this._pointOnLine(0.5); - this._label(ctx, this.label, point.x, point.y); + // find existing node (at root level) by its id + if (root.nodes) { + for (i = 0, len = root.nodes.length; i < len; i++) { + if (node.id === root.nodes[i].id) { + current = root.nodes[i]; + break; + } + } } - } - else { - var x, y; - var radius = this.length / 4; - var node = this.from; - if (!node.width) { - node.resize(ctx); + + if (!current) { + // this is a new node + current = { + id: node.id + }; + if (graph.node) { + // clone default attributes + current.attr = merge(current.attr, graph.node); + } } - if (node.width > node.height) { - x = node.x + node.width / 2; - y = node.y - radius; + + // add node to this (sub)graph and all its parent graphs + for (i = graphs.length - 1; i >= 0; i--) { + var g = graphs[i]; + + if (!g.nodes) { + g.nodes = []; + } + if (g.nodes.indexOf(current) == -1) { + g.nodes.push(current); + } } - else { - x = node.x + radius; - y = node.y - node.height / 2; + + // merge attributes + if (node.attr) { + current.attr = merge(current.attr, node.attr); } - this._circle(ctx, x, y, radius); - point = this._pointOnCircle(x, y, radius, 0.5); - this._label(ctx, this.label, point.x, point.y); } -}; -/** - * Get the line width of the edge. Depends on width and whether one of the - * connected nodes is selected. - * @return {Number} width - * @private - */ -Edge.prototype._getLineWidth = function() { - if (this.from.selected || this.to.selected) { - return Math.min(this.width * 2, this.widthMax); - } - else { - return this.width; + /** + * Add an edge to a graph object + * @param {Object} graph + * @param {Object} edge + */ + function addEdge(graph, edge) { + if (!graph.edges) { + graph.edges = []; + } + graph.edges.push(edge); + if (graph.edge) { + var attr = merge({}, graph.edge); // clone default attributes + edge.attr = merge(attr, edge.attr); // merge attributes + } } -}; - -/** - * Draw a line between two nodes - * @param {CanvasRenderingContext2D} ctx - * @private - */ -Edge.prototype._line = function (ctx) { - // draw a straight line - ctx.beginPath(); - ctx.moveTo(this.from.x, this.from.y); - ctx.lineTo(this.to.x, this.to.y); - ctx.stroke(); -}; - -/** - * Draw a line from a node to itself, a circle - * @param {CanvasRenderingContext2D} ctx - * @param {Number} x - * @param {Number} y - * @param {Number} radius - * @private - */ -Edge.prototype._circle = function (ctx, x, y, radius) { - // draw a circle - ctx.beginPath(); - ctx.arc(x, y, radius, 0, 2 * Math.PI, false); - ctx.stroke(); -}; -/** - * Draw label with white background and with the middle at (x, y) - * @param {CanvasRenderingContext2D} ctx - * @param {String} text - * @param {Number} x - * @param {Number} y - * @private - */ -Edge.prototype._label = function (ctx, text, x, y) { - if (text) { - // TODO: cache the calculated size - ctx.font = ((this.from.selected || this.to.selected) ? "bold " : "") + - this.fontSize + "px " + this.fontFace; - ctx.fillStyle = 'white'; - var width = ctx.measureText(text).width; - var height = this.fontSize; - var left = x - width / 2; - var top = y - height / 2; + /** + * Create an edge to a graph object + * @param {Object} graph + * @param {String | Number | Object} from + * @param {String | Number | Object} to + * @param {String} type + * @param {Object | null} attr + * @return {Object} edge + */ + function createEdge(graph, from, to, type, attr) { + var edge = { + from: from, + to: to, + type: type + }; - ctx.fillRect(left, top, width, height); + if (graph.edge) { + edge.attr = merge({}, graph.edge); // clone default attributes + } + edge.attr = merge(edge.attr || {}, attr); // merge attributes - // draw text - ctx.fillStyle = this.fontColor || "black"; - ctx.textAlign = "left"; - ctx.textBaseline = "top"; - ctx.fillText(text, left, top); + return edge; } -}; - -/** - * Redraw a edge as a dashed line - * Draw this edge in the given canvas - * @author David Jordan - * @date 2012-08-08 - * The 2d context of a HTML canvas can be retrieved by canvas.getContext("2d"); - * @param {CanvasRenderingContext2D} ctx - * @private - */ -Edge.prototype._drawDashLine = function(ctx) { - // set style - ctx.strokeStyle = this.color; - ctx.lineWidth = this._getLineWidth(); - // draw dashed line - ctx.beginPath(); - ctx.lineCap = 'round'; - if (this.dash.altLength != undefined) //If an alt dash value has been set add to the array this value - { - ctx.dashedLine(this.from.x,this.from.y,this.to.x,this.to.y, - [this.dash.length,this.dash.gap,this.dash.altLength,this.dash.gap]); - } - else if (this.dash.length != undefined && this.dash.gap != undefined) //If a dash and gap value has been set add to the array this value - { - ctx.dashedLine(this.from.x,this.from.y,this.to.x,this.to.y, - [this.dash.length,this.dash.gap]); - } - else //If all else fails draw a line - { - ctx.moveTo(this.from.x, this.from.y); - ctx.lineTo(this.to.x, this.to.y); - } - ctx.stroke(); + /** + * Get next token in the current dot file. + * The token and token type are available as token and tokenType + */ + function getToken() { + tokenType = TOKENTYPE.NULL; + token = ''; - // draw label - if (this.label) { - var point = this._pointOnLine(0.5); - this._label(ctx, this.label, point.x, point.y); - } -}; + // skip over whitespaces + while (c == ' ' || c == '\t' || c == '\n' || c == '\r') { // space, tab, enter + next(); + } -/** - * Get a point on a line - * @param {Number} percentage. Value between 0 (line start) and 1 (line end) - * @return {Object} point - * @private - */ -Edge.prototype._pointOnLine = function (percentage) { - return { - x: (1 - percentage) * this.from.x + percentage * this.to.x, - y: (1 - percentage) * this.from.y + percentage * this.to.y - } -}; + do { + var isComment = false; -/** - * Get a point on a circle - * @param {Number} x - * @param {Number} y - * @param {Number} radius - * @param {Number} percentage. Value between 0 (line start) and 1 (line end) - * @return {Object} point - * @private - */ -Edge.prototype._pointOnCircle = function (x, y, radius, percentage) { - var angle = (percentage - 3/8) * 2 * Math.PI; - return { - x: x + radius * Math.cos(angle), - y: y - radius * Math.sin(angle) - } -}; + // skip comment + if (c == '#') { + // find the previous non-space character + var i = index - 1; + while (dot.charAt(i) == ' ' || dot.charAt(i) == '\t') { + i--; + } + if (dot.charAt(i) == '\n' || dot.charAt(i) == '') { + // the # is at the start of a line, this is indeed a line comment + while (c != '' && c != '\n') { + next(); + } + isComment = true; + } + } + if (c == '/' && nextPreview() == '/') { + // skip line comment + while (c != '' && c != '\n') { + next(); + } + isComment = true; + } + if (c == '/' && nextPreview() == '*') { + // skip block comment + while (c != '') { + if (c == '*' && nextPreview() == '/') { + // end of block comment found. skip these last two characters + next(); + next(); + break; + } + else { + next(); + } + } + isComment = true; + } -/** - * Redraw a edge as a line with an arrow halfway the line - * Draw this edge in the given canvas - * The 2d context of a HTML canvas can be retrieved by canvas.getContext("2d"); - * @param {CanvasRenderingContext2D} ctx - * @private - */ -Edge.prototype._drawArrowCenter = function(ctx) { - var point; - // set style - ctx.strokeStyle = this.color; - ctx.fillStyle = this.color; - ctx.lineWidth = this._getLineWidth(); + // skip over whitespaces + while (c == ' ' || c == '\t' || c == '\n' || c == '\r') { // space, tab, enter + next(); + } + } + while (isComment); - if (this.from != this.to) { - // draw line - this._line(ctx); + // check for end of dot file + if (c == '') { + // token is still empty + tokenType = TOKENTYPE.DELIMITER; + return; + } - // draw an arrow halfway the line - var angle = Math.atan2((this.to.y - this.from.y), (this.to.x - this.from.x)); - var length = 10 + 5 * this.width; // TODO: make customizable? - point = this._pointOnLine(0.5); - ctx.arrow(point.x, point.y, angle, length); - ctx.fill(); - ctx.stroke(); + // check for delimiters consisting of 2 characters + var c2 = c + nextPreview(); + if (DELIMITERS[c2]) { + tokenType = TOKENTYPE.DELIMITER; + token = c2; + next(); + next(); + return; + } - // draw label - if (this.label) { - point = this._pointOnLine(0.5); - this._label(ctx, this.label, point.x, point.y); + // check for delimiters consisting of 1 character + if (DELIMITERS[c]) { + tokenType = TOKENTYPE.DELIMITER; + token = c; + next(); + return; } - } - else { - // draw circle - var x, y; - var radius = this.length / 4; - var node = this.from; - if (!node.width) { - node.resize(ctx); + + // check for an identifier (number or string) + // TODO: more precise parsing of numbers/strings (and the port separator ':') + if (isAlphaNumeric(c) || c == '-') { + token += c; + next(); + + while (isAlphaNumeric(c)) { + token += c; + next(); + } + if (token == 'false') { + token = false; // convert to boolean + } + else if (token == 'true') { + token = true; // convert to boolean + } + else if (!isNaN(Number(token))) { + token = Number(token); // convert to number + } + tokenType = TOKENTYPE.IDENTIFIER; + return; } - if (node.width > node.height) { - x = node.x + node.width / 2; - y = node.y - radius; + + // check for a string enclosed by double quotes + if (c == '"') { + next(); + while (c != '' && (c != '"' || (c == '"' && nextPreview() == '"'))) { + token += c; + if (c == '"') { // skip the escape character + next(); + } + next(); + } + if (c != '"') { + throw newSyntaxError('End of string " expected'); + } + next(); + tokenType = TOKENTYPE.IDENTIFIER; + return; } - else { - x = node.x + radius; - y = node.y - node.height / 2; + + // something unknown is found, wrong characters, a syntax error + tokenType = TOKENTYPE.UNKNOWN; + while (c != '') { + token += c; + next(); } - this._circle(ctx, x, y, radius); + throw new SyntaxError('Syntax error in part "' + chop(token, 30) + '"'); + } - // draw all arrows - var angle = 0.2 * Math.PI; - var length = 10 + 5 * this.width; // TODO: make customizable? - point = this._pointOnCircle(x, y, radius, 0.5); - ctx.arrow(point.x, point.y, angle, length); - ctx.fill(); - ctx.stroke(); + /** + * Parse a graph. + * @returns {Object} graph + */ + function parseGraph() { + var graph = {}; - // draw label - if (this.label) { - point = this._pointOnCircle(x, y, radius, 0.5); - this._label(ctx, this.label, point.x, point.y); + first(); + getToken(); + + // optional strict keyword + if (token == 'strict') { + graph.strict = true; + getToken(); } - } -}; + // graph or digraph keyword + if (token == 'graph' || token == 'digraph') { + graph.type = token; + getToken(); + } + // optional graph id + if (tokenType == TOKENTYPE.IDENTIFIER) { + graph.id = token; + getToken(); + } -/** - * Redraw a edge as a line with an arrow - * Draw this edge in the given canvas - * The 2d context of a HTML canvas can be retrieved by canvas.getContext("2d"); - * @param {CanvasRenderingContext2D} ctx - * @private - */ -Edge.prototype._drawArrow = function(ctx) { - // set style - ctx.strokeStyle = this.color; - ctx.fillStyle = this.color; - ctx.lineWidth = this._getLineWidth(); + // open angle bracket + if (token != '{') { + throw newSyntaxError('Angle bracket { expected'); + } + getToken(); - // draw line - var angle, length; - if (this.from != this.to) { - // calculate length and angle of the line - angle = Math.atan2((this.to.y - this.from.y), (this.to.x - this.from.x)); - var dx = (this.to.x - this.from.x); - var dy = (this.to.y - this.from.y); - var lEdge = Math.sqrt(dx * dx + dy * dy); + // statements + parseStatements(graph); - var lFrom = this.from.distanceToBorder(ctx, angle + Math.PI); - var pFrom = (lEdge - lFrom) / lEdge; - var xFrom = (pFrom) * this.from.x + (1 - pFrom) * this.to.x; - var yFrom = (pFrom) * this.from.y + (1 - pFrom) * this.to.y; + // close angle bracket + if (token != '}') { + throw newSyntaxError('Angle bracket } expected'); + } + getToken(); - var lTo = this.to.distanceToBorder(ctx, angle); - var pTo = (lEdge - lTo) / lEdge; - var xTo = (1 - pTo) * this.from.x + pTo * this.to.x; - var yTo = (1 - pTo) * this.from.y + pTo * this.to.y; + // end of file + if (token !== '') { + throw newSyntaxError('End of file expected'); + } + getToken(); - ctx.beginPath(); - ctx.moveTo(xFrom, yFrom); - ctx.lineTo(xTo, yTo); - ctx.stroke(); + // remove temporary default properties + delete graph.node; + delete graph.edge; + delete graph.graph; - // draw arrow at the end of the line - length = 10 + 5 * this.width; // TODO: make customizable? - ctx.arrow(xTo, yTo, angle, length); - ctx.fill(); - ctx.stroke(); + return graph; + } - // draw label - if (this.label) { - var point = this._pointOnLine(0.5); - this._label(ctx, this.label, point.x, point.y); + /** + * Parse a list with statements. + * @param {Object} graph + */ + function parseStatements (graph) { + while (token !== '' && token != '}') { + parseStatement(graph); + if (token == ';') { + getToken(); + } } } - else { - // draw circle - var node = this.from; - var x, y, arrow; - var radius = this.length / 4; - if (!node.width) { - node.resize(ctx); + + /** + * Parse a single statement. Can be a an attribute statement, node + * statement, a series of node statements and edge statements, or a + * parameter. + * @param {Object} graph + */ + function parseStatement(graph) { + // parse subgraph + var subgraph = parseSubgraph(graph); + if (subgraph) { + // edge statements + parseEdge(graph, subgraph); + + return; } - if (node.width > node.height) { - x = node.x + node.width / 2; - y = node.y - radius; - arrow = { - x: x, - y: node.y, - angle: 0.9 * Math.PI - }; + + // parse an attribute statement + var attr = parseAttributeStatement(graph); + if (attr) { + return; + } + + // parse node + if (tokenType != TOKENTYPE.IDENTIFIER) { + throw newSyntaxError('Identifier expected'); + } + var id = token; // id can be a string or a number + getToken(); + + if (token == '=') { + // id statement + getToken(); + if (tokenType != TOKENTYPE.IDENTIFIER) { + throw newSyntaxError('Identifier expected'); + } + graph[id] = token; + getToken(); + // TODO: implement comma separated list with "a_list: ID=ID [','] [a_list] " } else { - x = node.x + radius; - y = node.y - node.height / 2; - arrow = { - x: node.x, - y: y, - angle: 0.6 * Math.PI - }; + parseNodeStatement(graph, id); } - ctx.beginPath(); - // TODO: do not draw a circle, but an arc - // TODO: similarly, for a line without arrows, draw to the border of the nodes instead of the center - ctx.arc(x, y, radius, 0, 2 * Math.PI, false); - ctx.stroke(); + } - // draw all arrows - length = 10 + 5 * this.width; // TODO: make customizable? - ctx.arrow(arrow.x, arrow.y, arrow.angle, length); - ctx.fill(); - ctx.stroke(); + /** + * Parse a subgraph + * @param {Object} graph parent graph object + * @return {Object | null} subgraph + */ + function parseSubgraph (graph) { + var subgraph = null; - // draw label - if (this.label) { - point = this._pointOnCircle(x, y, radius, 0.5); - this._label(ctx, this.label, point.x, point.y); + // optional subgraph keyword + if (token == 'subgraph') { + subgraph = {}; + subgraph.type = 'subgraph'; + getToken(); + + // optional graph id + if (tokenType == TOKENTYPE.IDENTIFIER) { + subgraph.id = token; + getToken(); + } } - } -}; + // open angle bracket + if (token == '{') { + getToken(); + if (!subgraph) { + subgraph = {}; + } + subgraph.parent = graph; + subgraph.node = graph.node; + subgraph.edge = graph.edge; + subgraph.graph = graph.graph; -/** - * Calculate the distance between a point (x3,y3) and a line segment from - * (x1,y1) to (x2,y2). - * http://stackoverflow.com/questions/849211/shortest-distancae-between-a-point-and-a-line-segment - * @param {number} x1 - * @param {number} y1 - * @param {number} x2 - * @param {number} y2 - * @param {number} x3 - * @param {number} y3 - * @private - */ -Edge._dist = function (x1,y1, x2,y2, x3,y3) { // x3,y3 is the point - var px = x2-x1, - py = y2-y1, - something = px*px + py*py, - u = ((x3 - x1) * px + (y3 - y1) * py) / something; + // statements + parseStatements(subgraph); - if (u > 1) { - u = 1; - } - else if (u < 0) { - u = 0; + // close angle bracket + if (token != '}') { + throw newSyntaxError('Angle bracket } expected'); + } + getToken(); + + // remove temporary default properties + delete subgraph.node; + delete subgraph.edge; + delete subgraph.graph; + delete subgraph.parent; + + // register at the parent graph + if (!graph.subgraphs) { + graph.subgraphs = []; + } + graph.subgraphs.push(subgraph); + } + + return subgraph; } - var x = x1 + u * px, - y = y1 + u * py, - dx = x - x3, - dy = y - y3; + /** + * parse an attribute statement like "node [shape=circle fontSize=16]". + * Available keywords are 'node', 'edge', 'graph'. + * The previous list with default attributes will be replaced + * @param {Object} graph + * @returns {String | null} keyword Returns the name of the parsed attribute + * (node, edge, graph), or null if nothing + * is parsed. + */ + function parseAttributeStatement (graph) { + // attribute statements + if (token == 'node') { + getToken(); - //# Note: If the actual distance does not matter, - //# if you only want to compare what this function - //# returns to other results of this function, you - //# can just return the squared distance instead - //# (i.e. remove the sqrt) to gain a little performance + // node attributes + graph.node = parseAttributeList(); + return 'node'; + } + else if (token == 'edge') { + getToken(); - return Math.sqrt(dx*dx + dy*dy); -}; + // edge attributes + graph.edge = parseAttributeList(); + return 'edge'; + } + else if (token == 'graph') { + getToken(); -/** - * Popup is a class to create a popup window with some text - * @param {Element} container The container object. - * @param {Number} [x] - * @param {Number} [y] - * @param {String} [text] - */ -function Popup(container, x, y, text) { - if (container) { - this.container = container; - } - else { - this.container = document.body; - } - this.x = 0; - this.y = 0; - this.padding = 5; + // graph attributes + graph.graph = parseAttributeList(); + return 'graph'; + } - if (x !== undefined && y !== undefined ) { - this.setPosition(x, y); + return null; } - if (text !== undefined) { - this.setText(text); + + /** + * parse a node statement + * @param {Object} graph + * @param {String | Number} id + */ + function parseNodeStatement(graph, id) { + // node statement + var node = { + id: id + }; + var attr = parseAttributeList(); + if (attr) { + node.attr = attr; + } + addNode(graph, node); + + // edge statements + parseEdge(graph, id); } - // create the frame - this.frame = document.createElement("div"); - var style = this.frame.style; - style.position = "absolute"; - style.visibility = "hidden"; - style.border = "1px solid #666"; - style.color = "black"; - style.padding = this.padding + "px"; - style.backgroundColor = "#FFFFC6"; - style.borderRadius = "3px"; - style.MozBorderRadius = "3px"; - style.WebkitBorderRadius = "3px"; - style.boxShadow = "3px 3px 10px rgba(128, 128, 128, 0.5)"; - style.whiteSpace = "nowrap"; - this.container.appendChild(this.frame); -}; + /** + * Parse an edge or a series of edges + * @param {Object} graph + * @param {String | Number} from Id of the from node + */ + function parseEdge(graph, from) { + while (token == '->' || token == '--') { + var to; + var type = token; + getToken(); -/** - * @param {number} x Horizontal position of the popup window - * @param {number} y Vertical position of the popup window - */ -Popup.prototype.setPosition = function(x, y) { - this.x = parseInt(x); - this.y = parseInt(y); -}; + var subgraph = parseSubgraph(graph); + if (subgraph) { + to = subgraph; + } + else { + if (tokenType != TOKENTYPE.IDENTIFIER) { + throw newSyntaxError('Identifier or subgraph expected'); + } + to = token; + addNode(graph, { + id: to + }); + getToken(); + } -/** - * Set the text for the popup window. This can be HTML code - * @param {string} text - */ -Popup.prototype.setText = function(text) { - this.frame.innerHTML = text; -}; + // parse edge attributes + var attr = parseAttributeList(); -/** - * Show the popup window - * @param {boolean} show Optional. Show or hide the window - */ -Popup.prototype.show = function (show) { - if (show === undefined) { - show = true; + // create edge + var edge = createEdge(graph, from, to, type, attr); + addEdge(graph, edge); + + from = to; + } } - if (show) { - var height = this.frame.clientHeight; - var width = this.frame.clientWidth; - var maxHeight = this.frame.parentNode.clientHeight; - var maxWidth = this.frame.parentNode.clientWidth; + /** + * Parse a set with attributes, + * for example [label="1.000", shape=solid] + * @return {Object | null} attr + */ + function parseAttributeList() { + var attr = null; - var top = (this.y - height); - if (top + height + this.padding > maxHeight) { - top = maxHeight - height - this.padding; - } - if (top < this.padding) { - top = this.padding; - } + while (token == '[') { + getToken(); + attr = {}; + while (token !== '' && token != ']') { + if (tokenType != TOKENTYPE.IDENTIFIER) { + throw newSyntaxError('Attribute name expected'); + } + var name = token; - var left = this.x; - if (left + width + this.padding > maxWidth) { - left = maxWidth - width - this.padding; - } - if (left < this.padding) { - left = this.padding; + getToken(); + if (token != '=') { + throw newSyntaxError('Equal sign = expected'); + } + getToken(); + + if (tokenType != TOKENTYPE.IDENTIFIER) { + throw newSyntaxError('Attribute value expected'); + } + var value = token; + setValue(attr, name, value); // name can be a path + + getToken(); + if (token ==',') { + getToken(); + } + } + + if (token != ']') { + throw newSyntaxError('Bracket ] expected'); + } + getToken(); } - this.frame.style.left = left + "px"; - this.frame.style.top = top + "px"; - this.frame.style.visibility = "visible"; - } - else { - this.hide(); + return attr; } -}; -/** - * Hide the popup window - */ -Popup.prototype.hide = function () { - this.frame.style.visibility = "hidden"; -}; + /** + * Create a syntax error with extra information on current token and index. + * @param {String} message + * @returns {SyntaxError} err + */ + function newSyntaxError(message) { + return new SyntaxError(message + ', got "' + chop(token, 30) + '" (char ' + index + ')'); + } -/** - * @class Groups - * This class can store groups and properties specific for groups. - */ -Groups = function () { - this.clear(); - this.defaultIndex = 0; -}; + /** + * Chop off text after a maximum length + * @param {String} text + * @param {Number} maxLength + * @returns {String} + */ + function chop (text, maxLength) { + return (text.length <= maxLength) ? text : (text.substr(0, 27) + '...'); + } + /** + * Execute a function fn for each pair of elements in two arrays + * @param {Array | *} array1 + * @param {Array | *} array2 + * @param {function} fn + */ + function forEach2(array1, array2, fn) { + if (array1 instanceof Array) { + array1.forEach(function (elem1) { + if (array2 instanceof Array) { + array2.forEach(function (elem2) { + fn(elem1, elem2); + }); + } + else { + fn(elem1, array2); + } + }); + } + else { + if (array2 instanceof Array) { + array2.forEach(function (elem2) { + fn(array1, elem2); + }); + } + else { + fn(array1, array2); + } + } + } -/** - * default constants for group colors - */ -Groups.DEFAULT = [ - {border: "#2B7CE9", background: "#97C2FC", highlight: {border: "#2B7CE9", background: "#D2E5FF"}}, // blue - {border: "#FFA500", background: "#FFFF00", highlight: {border: "#FFA500", background: "#FFFFA3"}}, // yellow - {border: "#FA0A10", background: "#FB7E81", highlight: {border: "#FA0A10", background: "#FFAFB1"}}, // red - {border: "#41A906", background: "#7BE141", highlight: {border: "#41A906", background: "#A1EC76"}}, // green - {border: "#E129F0", background: "#EB7DF4", highlight: {border: "#E129F0", background: "#F0B3F5"}}, // magenta - {border: "#7C29F0", background: "#AD85E4", highlight: {border: "#7C29F0", background: "#D3BDF0"}}, // purple - {border: "#C37F00", background: "#FFA807", highlight: {border: "#C37F00", background: "#FFCA66"}}, // orange - {border: "#4220FB", background: "#6E6EFD", highlight: {border: "#4220FB", background: "#9B9BFD"}}, // darkblue - {border: "#FD5A77", background: "#FFC0CB", highlight: {border: "#FD5A77", background: "#FFD1D9"}}, // pink - {border: "#4AD63A", background: "#C2FABC", highlight: {border: "#4AD63A", background: "#E6FFE3"}} // mint -]; + /** + * Convert a string containing a graph in DOT language into a map containing + * with nodes and edges in the format of graph. + * @param {String} data Text containing a graph in DOT-notation + * @return {Object} graphData + */ + function DOTToGraph (data) { + // parse the DOT file + var dotData = parseDOT(data); + var graphData = { + nodes: [], + edges: [], + options: {} + }; + // copy the nodes + if (dotData.nodes) { + dotData.nodes.forEach(function (dotNode) { + var graphNode = { + id: dotNode.id, + label: String(dotNode.label || dotNode.id) + }; + merge(graphNode, dotNode.attr); + if (graphNode.image) { + graphNode.shape = 'image'; + } + graphData.nodes.push(graphNode); + }); + } -/** - * Clear all groups - */ -Groups.prototype.clear = function () { - this.groups = {}; - this.groups.length = function() - { - var i = 0; - for ( var p in this ) { - if (this.hasOwnProperty(p)) { - i++; + // copy the edges + if (dotData.edges) { + /** + * Convert an edge in DOT format to an edge with VisGraph format + * @param {Object} dotEdge + * @returns {Object} graphEdge + */ + function convertEdge(dotEdge) { + var graphEdge = { + from: dotEdge.from, + to: dotEdge.to + }; + merge(graphEdge, dotEdge.attr); + graphEdge.style = (dotEdge.type == '->') ? 'arrow' : 'line'; + return graphEdge; } + + dotData.edges.forEach(function (dotEdge) { + var from, to; + if (dotEdge.from instanceof Object) { + from = dotEdge.from.nodes; + } + else { + from = { + id: dotEdge.from + } + } + + if (dotEdge.to instanceof Object) { + to = dotEdge.to.nodes; + } + else { + to = { + id: dotEdge.to + } + } + + if (dotEdge.from instanceof Object && dotEdge.from.edges) { + dotEdge.from.edges.forEach(function (subEdge) { + var graphEdge = convertEdge(subEdge); + graphData.edges.push(graphEdge); + }); + } + + forEach2(from, to, function (from, to) { + var subEdge = createEdge(graphData, from.id, to.id, dotEdge.type, dotEdge.attr); + var graphEdge = convertEdge(subEdge); + graphData.edges.push(graphEdge); + }); + + if (dotEdge.to instanceof Object && dotEdge.to.edges) { + dotEdge.to.edges.forEach(function (subEdge) { + var graphEdge = convertEdge(subEdge); + graphData.edges.push(graphEdge); + }); + } + }); } - return i; + + // copy the options + if (dotData.attr) { + graphData.options = dotData.attr; + } + + return graphData; } -}; + // exports + exports.parseDOT = parseDOT; + exports.DOTToGraph = DOTToGraph; + +})(typeof util !== 'undefined' ? util : exports); /** - * get group properties of a groupname. If groupname is not found, a new group - * is added. - * @param {*} groupname Can be a number, string, Date, etc. - * @return {Object} group The created group, containing all group properties + * Canvas shapes used by the Graph */ -Groups.prototype.get = function (groupname) { - var group = this.groups[groupname]; +if (typeof CanvasRenderingContext2D !== 'undefined') { - if (group == undefined) { - // create new group - var index = this.defaultIndex % Groups.DEFAULT.length; - this.defaultIndex++; - group = {}; - group.color = Groups.DEFAULT[index]; - this.groups[groupname] = group; - } + /** + * Draw a circle shape + */ + CanvasRenderingContext2D.prototype.circle = function(x, y, r) { + this.beginPath(); + this.arc(x, y, r, 0, 2*Math.PI, false); + }; - return group; -}; + /** + * Draw a square shape + * @param {Number} x horizontal center + * @param {Number} y vertical center + * @param {Number} r size, width and height of the square + */ + CanvasRenderingContext2D.prototype.square = function(x, y, r) { + this.beginPath(); + this.rect(x - r, y - r, r * 2, r * 2); + }; -/** - * Add a custom group style - * @param {String} groupname - * @param {Object} style An object containing borderColor, - * backgroundColor, etc. - * @return {Object} group The created group object - */ -Groups.prototype.add = function (groupname, style) { - this.groups[groupname] = style; - if (style.color) { - style.color = Node.parseColor(style.color); - } - return style; -}; + /** + * Draw a triangle shape + * @param {Number} x horizontal center + * @param {Number} y vertical center + * @param {Number} r radius, half the length of the sides of the triangle + */ + CanvasRenderingContext2D.prototype.triangle = function(x, y, r) { + // http://en.wikipedia.org/wiki/Equilateral_triangle + this.beginPath(); -/** - * @class Images - * This class loads images and keeps them stored. - */ -Images = function () { - this.images = {}; + var s = r * 2; + var s2 = s / 2; + var ir = Math.sqrt(3) / 6 * s; // radius of inner circle + var h = Math.sqrt(s * s - s2 * s2); // height - this.callback = undefined; -}; + this.moveTo(x, y - (h - ir)); + this.lineTo(x + s2, y + ir); + this.lineTo(x - s2, y + ir); + this.lineTo(x, y - (h - ir)); + this.closePath(); + }; -/** - * Set an onload callback function. This will be called each time an image - * is loaded - * @param {function} callback - */ -Images.prototype.setOnloadCallback = function(callback) { - this.callback = callback; -}; + /** + * Draw a triangle shape in downward orientation + * @param {Number} x horizontal center + * @param {Number} y vertical center + * @param {Number} r radius + */ + CanvasRenderingContext2D.prototype.triangleDown = function(x, y, r) { + // http://en.wikipedia.org/wiki/Equilateral_triangle + this.beginPath(); -/** - * - * @param {string} url Url of the image - * @return {Image} img The image object - */ -Images.prototype.load = function(url) { - var img = this.images[url]; - if (img == undefined) { - // create the image - var images = this; - img = new Image(); - this.images[url] = img; - img.onload = function() { - if (images.callback) { - images.callback(this); - } - }; - img.src = url; - } + var s = r * 2; + var s2 = s / 2; + var ir = Math.sqrt(3) / 6 * s; // radius of inner circle + var h = Math.sqrt(s * s - s2 * s2); // height - return img; -}; + this.moveTo(x, y + (h - ir)); + this.lineTo(x + s2, y - ir); + this.lineTo(x - s2, y - ir); + this.lineTo(x, y + (h - ir)); + this.closePath(); + }; -/** - * @constructor Graph - * Create a graph visualization, displaying nodes and edges. - * - * @param {Element} container The DOM element in which the Graph will - * be created. Normally a div element. - * @param {Object} data An object containing parameters - * {Array} nodes - * {Array} edges - * @param {Object} options Options - */ -function Graph (container, data, options) { - // create variables and set default values - this.containerElement = container; - this.width = '100%'; - this.height = '100%'; - this.refreshRate = 50; // milliseconds - this.stabilize = true; // stabilize before displaying the graph - this.selectable = true; + /** + * Draw a star shape, a star with 5 points + * @param {Number} x horizontal center + * @param {Number} y vertical center + * @param {Number} r radius, half the length of the sides of the triangle + */ + CanvasRenderingContext2D.prototype.star = function(x, y, r) { + // http://www.html5canvastutorials.com/labs/html5-canvas-star-spinner/ + this.beginPath(); - // set constant values - this.constants = { - nodes: { - radiusMin: 5, - radiusMax: 20, - radius: 5, - distance: 100, // px - shape: 'ellipse', - image: undefined, - widthMin: 16, // px - widthMax: 64, // px - fontColor: 'black', - fontSize: 14, // px - //fontFace: verdana, - fontFace: 'arial', - color: { - border: '#2B7CE9', - background: '#97C2FC', - highlight: { - border: '#2B7CE9', - background: '#D2E5FF' - } - }, - borderColor: '#2B7CE9', - backgroundColor: '#97C2FC', - highlightColor: '#D2E5FF', - group: undefined - }, - edges: { - widthMin: 1, - widthMax: 15, - width: 1, - style: 'line', - color: '#343434', - fontColor: '#343434', - fontSize: 14, // px - fontFace: 'arial', - //distance: 100, //px - length: 100, // px - dash: { - length: 10, - gap: 5, - altLength: undefined - } - }, - minForce: 0.05, - minVelocity: 0.02, // px/s - maxIterations: 1000 // maximum number of iteration to stabilize + for (var n = 0; n < 10; n++) { + var radius = (n % 2 === 0) ? r * 1.3 : r * 0.5; + this.lineTo( + x + radius * Math.sin(n * 2 * Math.PI / 10), + y - radius * Math.cos(n * 2 * Math.PI / 10) + ); + } + + this.closePath(); + }; + + /** + * http://stackoverflow.com/questions/1255512/how-to-draw-a-rounded-rectangle-on-html-canvas + */ + CanvasRenderingContext2D.prototype.roundRect = function(x, y, w, h, r) { + var r2d = Math.PI/180; + if( w - ( 2 * r ) < 0 ) { r = ( w / 2 ); } //ensure that the radius isn't too large for x + if( h - ( 2 * r ) < 0 ) { r = ( h / 2 ); } //ensure that the radius isn't too large for y + this.beginPath(); + this.moveTo(x+r,y); + this.lineTo(x+w-r,y); + this.arc(x+w-r,y+r,r,r2d*270,r2d*360,false); + this.lineTo(x+w,y+h-r); + this.arc(x+w-r,y+h-r,r,0,r2d*90,false); + this.lineTo(x+r,y+h); + this.arc(x+r,y+h-r,r,r2d*90,r2d*180,false); + this.lineTo(x,y+r); + this.arc(x+r,y+r,r,r2d*180,r2d*270,false); + }; + + /** + * http://stackoverflow.com/questions/2172798/how-to-draw-an-oval-in-html5-canvas + */ + CanvasRenderingContext2D.prototype.ellipse = function(x, y, w, h) { + var kappa = .5522848, + ox = (w / 2) * kappa, // control point offset horizontal + oy = (h / 2) * kappa, // control point offset vertical + xe = x + w, // x-end + ye = y + h, // y-end + xm = x + w / 2, // x-middle + ym = y + h / 2; // y-middle + + this.beginPath(); + this.moveTo(x, ym); + this.bezierCurveTo(x, ym - oy, xm - ox, y, xm, y); + this.bezierCurveTo(xm + ox, y, xe, ym - oy, xe, ym); + this.bezierCurveTo(xe, ym + oy, xm + ox, ye, xm, ye); + this.bezierCurveTo(xm - ox, ye, x, ym + oy, x, ym); }; - var graph = this; - this.nodes = {}; // object with Node objects - this.edges = {}; // object with Edge objects - // TODO: create a counter to keep track on the number of nodes having values - // TODO: create a counter to keep track on the number of nodes currently moving - // TODO: create a counter to keep track on the number of edges having values - this.nodesData = null; // A DataSet or DataView - this.edgesData = null; // A DataSet or DataView - // create event listeners used to subscribe on the DataSets of the nodes and edges - var me = this; - this.nodesListeners = { - 'add': function (event, params) { - me._addNodes(params.items); - me.start(); - }, - 'update': function (event, params) { - me._updateNodes(params.items); - me.start(); - }, - 'remove': function (event, params) { - me._removeNodes(params.items); - me.start(); - } - }; - this.edgesListeners = { - 'add': function (event, params) { - me._addEdges(params.items); - me.start(); - }, - 'update': function (event, params) { - me._updateEdges(params.items); - me.start(); - }, - 'remove': function (event, params) { - me._removeEdges(params.items); - me.start(); - } - }; + /** + * http://stackoverflow.com/questions/2172798/how-to-draw-an-oval-in-html5-canvas + */ + CanvasRenderingContext2D.prototype.database = function(x, y, w, h) { + var f = 1/3; + var wEllipse = w; + var hEllipse = h * f; - this.groups = new Groups(); // object with groups - this.images = new Images(); // object with images - this.images.setOnloadCallback(function () { - graph._redraw(); - }); + var kappa = .5522848, + ox = (wEllipse / 2) * kappa, // control point offset horizontal + oy = (hEllipse / 2) * kappa, // control point offset vertical + xe = x + wEllipse, // x-end + ye = y + hEllipse, // y-end + xm = x + wEllipse / 2, // x-middle + ym = y + hEllipse / 2, // y-middle + ymb = y + (h - hEllipse/2), // y-midlle, bottom ellipse + yeb = y + h; // y-end, bottom ellipse - // properties of the data - this.moving = false; // True if any of the nodes have an undefined position + this.beginPath(); + this.moveTo(xe, ym); - this.selection = []; - this.timer = undefined; + this.bezierCurveTo(xe, ym + oy, xm + ox, ye, xm, ye); + this.bezierCurveTo(xm - ox, ye, x, ym + oy, x, ym); - // create a frame and canvas - this._create(); + this.bezierCurveTo(x, ym - oy, xm - ox, y, xm, y); + this.bezierCurveTo(xm + ox, y, xe, ym - oy, xe, ym); - // apply options - this.setOptions(options); + this.lineTo(xe, ymb); - // draw data - this.setData(data); -} + this.bezierCurveTo(xe, ymb + oy, xm + ox, yeb, xm, yeb); + this.bezierCurveTo(xm - ox, yeb, x, ymb + oy, x, ymb); -/** - * Set nodes and edges, and optionally options as well. - * - * @param {Object} data Object containing parameters: - * {Array | DataSet | DataView} [nodes] Array with nodes - * {Array | DataSet | DataView} [edges] Array with edges - * {String} [dot] String containing data in DOT format - * {Options} [options] Object with options - */ -Graph.prototype.setData = function(data) { - if (data && data.dot && (data.nodes || data.edges)) { - throw new SyntaxError('Data must contain either parameter "dot" or ' + - ' parameter pair "nodes" and "edges", but not both.'); - } + this.lineTo(x, ym); + }; - // set options - this.setOptions(data && data.options); - // set all data - if (data && data.dot) { - // parse DOT file - if(data && data.dot) { - var dotData = vis.util.DOTToGraph(data.dot); - this.setData(dotData); - return; - } - } - else { - this._setNodes(data && data.nodes); - this._setEdges(data && data.edges); - } + /** + * Draw an arrow point (no line) + */ + CanvasRenderingContext2D.prototype.arrow = function(x, y, angle, length) { + // tail + var xt = x - length * Math.cos(angle); + var yt = y - length * Math.sin(angle); + + // inner tail + // TODO: allow to customize different shapes + var xi = x - length * 0.9 * Math.cos(angle); + var yi = y - length * 0.9 * Math.sin(angle); + // left + var xl = xt + length / 3 * Math.cos(angle + 0.5 * Math.PI); + var yl = yt + length / 3 * Math.sin(angle + 0.5 * Math.PI); - // find a stable position or start animating to a stable position - if (this.stabilize) { - this._doStabilize(); - } - this.start(); -}; + // right + var xr = xt + length / 3 * Math.cos(angle - 0.5 * Math.PI); + var yr = yt + length / 3 * Math.sin(angle - 0.5 * Math.PI); -/** - * Set options - * @param {Object} options - */ -Graph.prototype.setOptions = function (options) { - if (options) { - // retrieve parameter values - if (options.width != undefined) {this.width = options.width;} - if (options.height != undefined) {this.height = options.height;} - if (options.stabilize != undefined) {this.stabilize = options.stabilize;} - if (options.selectable != undefined) {this.selectable = options.selectable;} + this.beginPath(); + this.moveTo(x, y); + this.lineTo(xl, yl); + this.lineTo(xi, yi); + this.lineTo(xr, yr); + this.closePath(); + }; - // TODO: work out these options and document them - if (options.edges) { - for (var prop in options.edges) { - if (options.edges.hasOwnProperty(prop)) { - this.constants.edges[prop] = options.edges[prop]; - } - } + /** + * Sets up the dashedLine functionality for drawing + * Original code came from http://stackoverflow.com/questions/4576724/dotted-stroke-in-canvas + * @author David Jordan + * @date 2012-08-08 + */ + CanvasRenderingContext2D.prototype.dashedLine = function(x,y,x2,y2,dashArray){ + if (!dashArray) dashArray=[10,5]; + if (dashLength==0) dashLength = 0.001; // Hack for Safari + var dashCount = dashArray.length; + this.moveTo(x, y); + var dx = (x2-x), dy = (y2-y); + var slope = dy/dx; + var distRemaining = Math.sqrt( dx*dx + dy*dy ); + var dashIndex=0, draw=true; + while (distRemaining>=0.1){ + var dashLength = dashArray[dashIndex++%dashCount]; + if (dashLength > distRemaining) dashLength = distRemaining; + var xStep = Math.sqrt( dashLength*dashLength / (1 + slope*slope) ); + if (dx<0) xStep = -xStep; + x += xStep; + y += slope*xStep; + this[draw ? 'lineTo' : 'moveTo'](x,y); + distRemaining -= dashLength; + draw = !draw; + } + }; - if (options.edges.length != undefined && - options.nodes && options.nodes.distance == undefined) { - this.constants.edges.length = options.edges.length; - this.constants.nodes.distance = options.edges.length * 1.25; - } + // TODO: add diamond shape +} - if (!options.edges.fontColor) { - this.constants.edges.fontColor = options.edges.color; - } +/** + * @class Node + * A node. A node can be connected to other nodes via one or multiple edges. + * @param {object} properties An object containing properties for the node. All + * properties are optional, except for the id. + * {number} id Id of the node. Required + * {string} label Text label for the node + * {number} x Horizontal position of the node + * {number} y Vertical position of the node + * {string} shape Node shape, available: + * "database", "circle", "ellipse", + * "box", "image", "text", "dot", + * "star", "triangle", "triangleDown", + * "square" + * {string} image An image url + * {string} title An title text, can be HTML + * {anytype} group A group name or number + * @param {Graph.Images} imagelist A list with images. Only needed + * when the node has an image + * @param {Graph.Groups} grouplist A list with groups. Needed for + * retrieving group properties + * @param {Object} constants An object with default values for + * example for the color + */ +function Node(properties, imagelist, grouplist, constants) { + this.selected = false; - // Added to support dashed lines - // David Jordan - // 2012-08-08 - if (options.edges.dash) { - if (options.edges.dash.length != undefined) { - this.constants.edges.dash.length = options.edges.dash.length; - } - if (options.edges.dash.gap != undefined) { - this.constants.edges.dash.gap = options.edges.dash.gap; - } - if (options.edges.dash.altLength != undefined) { - this.constants.edges.dash.altLength = options.edges.dash.altLength; - } - } - } + this.edges = []; // all edges connected to this node + this.group = constants.nodes.group; - if (options.nodes) { - for (prop in options.nodes) { - if (options.nodes.hasOwnProperty(prop)) { - this.constants.nodes[prop] = options.nodes[prop]; - } - } + this.fontSize = constants.nodes.fontSize; + this.fontFace = constants.nodes.fontFace; + this.fontColor = constants.nodes.fontColor; + + this.color = constants.nodes.color; - if (options.nodes.color) { - this.constants.nodes.color = Node.parseColor(options.nodes.color); - } + // set defaults for the properties + this.id = undefined; + this.shape = constants.nodes.shape; + this.image = constants.nodes.image; + this.x = 0; + this.y = 0; + this.xFixed = false; + this.yFixed = false; + this.radius = constants.nodes.radius; + this.radiusFixed = false; + this.radiusMin = constants.nodes.radiusMin; + this.radiusMax = constants.nodes.radiusMax; - /* - if (options.nodes.widthMin) this.constants.nodes.radiusMin = options.nodes.widthMin; - if (options.nodes.widthMax) this.constants.nodes.radiusMax = options.nodes.widthMax; - */ - } + this.imagelist = imagelist; + this.grouplist = grouplist; - if (options.groups) { - for (var groupname in options.groups) { - if (options.groups.hasOwnProperty(groupname)) { - var group = options.groups[groupname]; - this.groups.add(groupname, group); - } - } - } - } + this.setProperties(properties, constants); - this.setSize(this.width, this.height); - this._setTranslation(this.frame.clientWidth / 2, this.frame.clientHeight / 2); - this._setScale(1); + // mass, force, velocity + this.mass = 50; // kg (mass is adjusted for the number of connected edges) + this.fx = 0.0; // external force x + this.fy = 0.0; // external force y + this.vx = 0.0; // velocity x + this.vy = 0.0; // velocity y + this.minForce = constants.minForce; + this.damping = 0.9; // damping factor }; /** - * fire an event - * @param {String} event The name of an event, for example "select" - * @param {Object} params Optional object with event parameters - * @private + * Attach a edge to the node + * @param {Edge} edge */ -Graph.prototype._trigger = function (event, params) { - events.trigger(this, event, params); +Node.prototype.attachEdge = function(edge) { + if (this.edges.indexOf(edge) == -1) { + this.edges.push(edge); + } + this._updateMass(); }; - /** - * Create the main frame for the Graph. - * This function is executed once when a Graph object is created. The frame - * contains a canvas, and this canvas contains all objects like the axis and - * nodes. - * @private + * Detach a edge from the node + * @param {Edge} edge */ -Graph.prototype._create = function () { - // remove all elements from the container element. - while (this.containerElement.hasChildNodes()) { - this.containerElement.removeChild(this.containerElement.firstChild); - } - - this.frame = document.createElement("div"); - this.frame.className = "graph-frame"; - this.frame.style.position = "relative"; - this.frame.style.overflow = "hidden"; - - // create the graph canvas (HTML canvas element) - this.frame.canvas = document.createElement( "canvas" ); - this.frame.canvas.style.position = "relative"; - this.frame.appendChild(this.frame.canvas); - if (!this.frame.canvas.getContext) { - var noCanvas = document.createElement( "DIV" ); - noCanvas.style.color = "red"; - noCanvas.style.fontWeight = "bold" ; - noCanvas.style.padding = "10px"; - noCanvas.innerHTML = "Error: your browser does not support HTML canvas"; - this.frame.canvas.appendChild(noCanvas); +Node.prototype.detachEdge = function(edge) { + var index = this.edges.indexOf(edge); + if (index != -1) { + this.edges.splice(index, 1); } - - // create event listeners - var me = this; - var onmousedown = function (event) {me._onMouseDown(event);}; - var onmousemove = function (event) {me._onMouseMoveTitle(event);}; - var onmousewheel = function (event) {me._onMouseWheel(event);}; - var ontouchstart = function (event) {me._onTouchStart(event);}; - vis.util.addEventListener(this.frame.canvas, "mousedown", onmousedown); - vis.util.addEventListener(this.frame.canvas, "mousemove", onmousemove); - vis.util.addEventListener(this.frame.canvas, "mousewheel", onmousewheel); - vis.util.addEventListener(this.frame.canvas, "touchstart", ontouchstart); - - // add the frame to the container element - this.containerElement.appendChild(this.frame); + this._updateMass(); }; /** - * handle on mouse down event + * Update the nodes mass, which is determined by the number of edges connecting + * to it (more edges -> heavier node). * @private */ -Graph.prototype._onMouseDown = function (event) { - event = event || window.event; +Node.prototype._updateMass = function() { + this.mass = 50 + 20 * this.edges.length; // kg +}; - if (!this.selectable) { +/** + * Set or overwrite properties for the node + * @param {Object} properties an object with properties + * @param {Object} constants and object with default, global properties + */ +Node.prototype.setProperties = function(properties, constants) { + if (!properties) { return; } - // check if mouse is still down (may be up when focus is lost for example - // in an iframe) - if (this.leftButtonDown) { - this._onMouseUp(event); - } + // basic properties + if (properties.id != undefined) {this.id = properties.id;} + if (properties.label != undefined) {this.label = properties.label;} + if (properties.title != undefined) {this.title = properties.title;} + if (properties.group != undefined) {this.group = properties.group;} + if (properties.x != undefined) {this.x = properties.x;} + if (properties.y != undefined) {this.y = properties.y;} + if (properties.value != undefined) {this.value = properties.value;} - // only react on left mouse button down - this.leftButtonDown = event.which ? (event.which == 1) : (event.button == 1); - if (!this.leftButtonDown && !this.touchDown) { - return; + if (this.id === undefined) { + throw "Node must have an id"; } - // add event listeners to handle moving the contents - // we store the function onmousemove and onmouseup in the timeline, so we can - // remove the eventlisteners lateron in the function mouseUp() - var me = this; - if (!this.onmousemove) { - this.onmousemove = function (event) {me._onMouseMove(event);}; - vis.util.addEventListener(document, "mousemove", me.onmousemove); - } - if (!this.onmouseup) { - this.onmouseup = function (event) {me._onMouseUp(event);}; - vis.util.addEventListener(document, "mouseup", me.onmouseup); + // copy group properties + if (this.group) { + var groupObj = this.grouplist.get(this.group); + for (var prop in groupObj) { + if (groupObj.hasOwnProperty(prop)) { + this[prop] = groupObj[prop]; + } + } } - vis.util.preventDefault(event); - - // store the start x and y position of the mouse - this.startMouseX = util.getPageX(event); - this.startMouseY = util.getPageY(event); - this.startFrameLeft = vis.util.getAbsoluteLeft(this.frame.canvas); - this.startFrameTop = vis.util.getAbsoluteTop(this.frame.canvas); - this.startTranslation = this._getTranslation(); - - this.ctrlKeyDown = event.ctrlKey; - this.shiftKeyDown = event.shiftKey; - var obj = { - left: this._xToCanvas(this.startMouseX - this.startFrameLeft), - top: this._yToCanvas(this.startMouseY - this.startFrameTop), - right: this._xToCanvas(this.startMouseX - this.startFrameLeft), - bottom: this._yToCanvas(this.startMouseY - this.startFrameTop) - }; - var overlappingNodes = this._getNodesOverlappingWith(obj); - // if there are overlapping nodes, select the last one, this is the - // one which is drawn on top of the others - this.startClickedObj = (overlappingNodes.length > 0) ? - overlappingNodes[overlappingNodes.length - 1] : undefined; + // individual shape properties + if (properties.shape != undefined) {this.shape = properties.shape;} + if (properties.image != undefined) {this.image = properties.image;} + if (properties.radius != undefined) {this.radius = properties.radius;} + if (properties.color != undefined) {this.color = Node.parseColor(properties.color);} - if (this.startClickedObj) { - // move clicked node with the mouse + if (properties.fontColor != undefined) {this.fontColor = properties.fontColor;} + if (properties.fontSize != undefined) {this.fontSize = properties.fontSize;} + if (properties.fontFace != undefined) {this.fontFace = properties.fontFace;} - // make the clicked node temporarily fixed, and store their original state - var node = this.nodes[this.startClickedObj]; - this.startClickedObj.xFixed = node.xFixed; - this.startClickedObj.yFixed = node.yFixed; - node.xFixed = true; - node.yFixed = true; - if (!this.ctrlKeyDown || !node.isSelected()) { - // select this node - this._selectNodes([this.startClickedObj], this.ctrlKeyDown); + if (this.image != undefined) { + if (this.imagelist) { + this.imageObj = this.imagelist.load(this.image); } else { - // unselect this node - this._unselectNodes([this.startClickedObj]); + throw "No imagelist provided"; } + } - if (!this.moving) { - this._redraw(); - } + this.xFixed = this.xFixed || (properties.x != undefined); + this.yFixed = this.yFixed || (properties.y != undefined); + this.radiusFixed = this.radiusFixed || (properties.radius != undefined); + + if (this.shape == 'image') { + this.radiusMin = constants.nodes.widthMin; + this.radiusMax = constants.nodes.widthMax; + } + + // choose draw method depending on the shape + switch (this.shape) { + case 'database': this.draw = this._drawDatabase; this.resize = this._resizeDatabase; break; + case 'box': this.draw = this._drawBox; this.resize = this._resizeBox; break; + case 'circle': this.draw = this._drawCircle; this.resize = this._resizeCircle; break; + case 'ellipse': this.draw = this._drawEllipse; this.resize = this._resizeEllipse; break; + // TODO: add diamond shape + case 'image': this.draw = this._drawImage; this.resize = this._resizeImage; break; + case 'text': this.draw = this._drawText; this.resize = this._resizeText; break; + case 'dot': this.draw = this._drawDot; this.resize = this._resizeShape; break; + case 'square': this.draw = this._drawSquare; this.resize = this._resizeShape; break; + case 'triangle': this.draw = this._drawTriangle; this.resize = this._resizeShape; break; + case 'triangleDown': this.draw = this._drawTriangleDown; this.resize = this._resizeShape; break; + case 'star': this.draw = this._drawStar; this.resize = this._resizeShape; break; + default: this.draw = this._drawEllipse; this.resize = this._resizeEllipse; break; } - else if (this.shiftKeyDown) { - // start selection of multiple nodes + + // reset the size of the node, this can be changed + this._reset(); +}; + +/** + * Parse a color property into an object with border, background, and + * hightlight colors + * @param {Object | String} color + * @return {Object} colorObject + */ +Node.parseColor = function(color) { + var c; + if (util.isString(color)) { + c = { + border: color, + background: color, + highlight: { + border: color, + background: color + } + }; + // TODO: automatically generate a nice highlight color } else { - // start moving the graph - this.moved = false; + c = {}; + c.background = color.background || 'white'; + c.border = color.border || c.background; + if (util.isString(color.highlight)) { + c.highlight = { + border: color.highlight, + background: color.highlight + } + } + else { + c.highlight = {}; + c.highlight.background = color.highlight && color.highlight.background || c.background; + c.highlight.border = color.highlight && color.highlight.border || c.border; + } } + return c; }; /** - * handle on mouse move event - * @param {Event} event - * @private + * select this node */ -Graph.prototype._onMouseMove = function (event) { - event = event || window.event; - - if (!this.selectable) { - return; - } +Node.prototype.select = function() { + this.selected = true; + this._reset(); +}; - var mouseX = util.getPageX(event); - var mouseY = util.getPageY(event); - this.mouseX = mouseX; - this.mouseY = mouseY; +/** + * unselect this node + */ +Node.prototype.unselect = function() { + this.selected = false; + this._reset(); +}; - if (this.startClickedObj) { - var node = this.nodes[this.startClickedObj]; +/** + * Reset the calculated size of the node, forces it to recalculate its size + * @private + */ +Node.prototype._reset = function() { + this.width = undefined; + this.height = undefined; +}; - if (!this.startClickedObj.xFixed) - node.x = this._xToCanvas(mouseX - this.startFrameLeft); +/** + * get the title of this node. + * @return {string} title The title of the node, or undefined when no title + * has been set. + */ +Node.prototype.getTitle = function() { + return this.title; +}; - if (!this.startClickedObj.yFixed) - node.y = this._yToCanvas(mouseY - this.startFrameTop); +/** + * Calculate the distance to the border of the Node + * @param {CanvasRenderingContext2D} ctx + * @param {Number} angle Angle in radians + * @returns {number} distance Distance to the border in pixels + */ +Node.prototype.distanceToBorder = function (ctx, angle) { + var borderWidth = 1; - // start animation if not yet running - if (!this.moving) { - this.moving = true; - this.start(); - } + if (!this.width) { + this.resize(ctx); } - else if (this.shiftKeyDown) { - // draw a rect from start mouse location to current mouse location - if (this.frame.selRect == undefined) { - this.frame.selRect = document.createElement("DIV"); - this.frame.appendChild(this.frame.selRect); - this.frame.selRect.style.position = "absolute"; - this.frame.selRect.style.border = "1px dashed red"; - } + //noinspection FallthroughInSwitchStatementJS + switch (this.shape) { + case 'circle': + case 'dot': + return this.radius + borderWidth; - var left = Math.min(this.startMouseX, mouseX) - this.startFrameLeft; - var top = Math.min(this.startMouseY, mouseY) - this.startFrameTop; - var right = Math.max(this.startMouseX, mouseX) - this.startFrameLeft; - var bottom = Math.max(this.startMouseY, mouseY) - this.startFrameTop; + case 'ellipse': + var a = this.width / 2; + var b = this.height / 2; + var w = (Math.sin(angle) * a); + var h = (Math.cos(angle) * b); + return a * b / Math.sqrt(w * w + h * h); - this.frame.selRect.style.left = left + "px"; - this.frame.selRect.style.top = top + "px"; - this.frame.selRect.style.width = (right - left) + "px"; - this.frame.selRect.style.height = (bottom - top) + "px"; - } - else { - // move the graph - var diffX = mouseX - this.startMouseX; - var diffY = mouseY - this.startMouseY; + // TODO: implement distanceToBorder for database + // TODO: implement distanceToBorder for triangle + // TODO: implement distanceToBorder for triangleDown - this._setTranslation( - this.startTranslation.x + diffX, - this.startTranslation.y + diffY); - this._redraw(); + case 'box': + case 'image': + case 'text': + default: + if (this.width) { + return Math.min( + Math.abs(this.width / 2 / Math.cos(angle)), + Math.abs(this.height / 2 / Math.sin(angle))) + borderWidth; + // TODO: reckon with border radius too in case of box + } + else { + return 0; + } - this.moved = true; } - vis.util.preventDefault(event); + // TODO: implement calculation of distance to border for all shapes }; /** - * handle on mouse up event - * @param {Event} event - * @private + * Set forces acting on the node + * @param {number} fx Force in horizontal direction + * @param {number} fy Force in vertical direction */ -Graph.prototype._onMouseUp = function (event) { - event = event || window.event; - - if (!this.selectable) { - return; - } - - // remove event listeners here, important for Safari - if (this.onmousemove) { - vis.util.removeEventListener(document, "mousemove", this.onmousemove); - this.onmousemove = undefined; - } - if (this.onmouseup) { - vis.util.removeEventListener(document, "mouseup", this.onmouseup); - this.onmouseup = undefined; - } - vis.util.preventDefault(event); - - // check selected nodes - var endMouseX = util.getPageX(event) || this.mouseX || 0; - var endMouseY = util.getPageY(event) || this.mouseY || 0; - - var ctrlKey = event ? event.ctrlKey : window.event.ctrlKey; - - if (this.startClickedObj) { - // restore the original fixed state - var node = this.nodes[this.startClickedObj]; - node.xFixed = this.startClickedObj.xFixed; - node.yFixed = this.startClickedObj.yFixed; - } - else if (this.shiftKeyDown) { - // select nodes inside selection area - var obj = { - "left": this._xToCanvas(Math.min(this.startMouseX, endMouseX) - this.startFrameLeft), - "top": this._yToCanvas(Math.min(this.startMouseY, endMouseY) - this.startFrameTop), - "right": this._xToCanvas(Math.max(this.startMouseX, endMouseX) - this.startFrameLeft), - "bottom": this._yToCanvas(Math.max(this.startMouseY, endMouseY) - this.startFrameTop) - }; - var overlappingNodes = this._getNodesOverlappingWith(obj); - this._selectNodes(overlappingNodes, ctrlKey); - this.redraw(); - - // remove the selection rectangle - if (this.frame.selRect) { - this.frame.removeChild(this.frame.selRect); - this.frame.selRect = undefined; - } - } - else { - if (!this.ctrlKeyDown && !this.moved) { - // remove selection - this._unselectNodes(); - this._redraw(); - } - } - - this.leftButtonDown = false; - this.ctrlKeyDown = false; +Node.prototype._setForce = function(fx, fy) { + this.fx = fx; + this.fy = fy; }; - /** - * Event handler for mouse wheel event, used to zoom the timeline - * Code from http://adomas.org/javascript-mouse-wheel/ - * @param {Event} event + * Add forces acting on the node + * @param {number} fx Force in horizontal direction + * @param {number} fy Force in vertical direction * @private */ -Graph.prototype._onMouseWheel = function(event) { - event = event || window.event; - var mouseX = util.getPageX(event); - var mouseY = util.getPageY(event); +Node.prototype._addForce = function(fx, fy) { + this.fx += fx; + this.fy += fy; +}; - // retrieve delta - var delta = 0; - if (event.wheelDelta) { /* IE/Opera. */ - delta = event.wheelDelta/120; - } else if (event.detail) { /* Mozilla case. */ - // In Mozilla, sign of delta is different than in IE. - // Also, delta is multiple of 3. - delta = -event.detail/3; +/** + * Perform one discrete step for the node + * @param {number} interval Time interval in seconds + */ +Node.prototype.discreteStep = function(interval) { + if (!this.xFixed) { + var dx = -this.damping * this.vx; // damping force + var ax = (this.fx + dx) / this.mass; // acceleration + this.vx += ax / interval; // velocity + this.x += this.vx / interval; // position } - // If delta is nonzero, handle it. - // Basically, delta is now positive if wheel was scrolled up, - // and negative, if wheel was scrolled down. - if (delta) { - // determine zoom factor, and adjust the zoom factor such that zooming in - // and zooming out correspond wich each other - var zoom = delta / 10; - if (delta < 0) { - zoom = zoom / (1 - zoom); - } - - var scaleOld = this._getScale(); - var scaleNew = scaleOld * (1 + zoom); - if (scaleNew < 0.01) { - scaleNew = 0.01; - } - if (scaleNew > 10) { - scaleNew = 10; - } - - var frameLeft = vis.util.getAbsoluteLeft(this.frame.canvas); - var frameTop = vis.util.getAbsoluteTop(this.frame.canvas); - var x = mouseX - frameLeft; - var y = mouseY - frameTop; - - var translation = this._getTranslation(); - var scaleFrac = scaleNew / scaleOld; - var tx = (1 - scaleFrac) * x + translation.x * scaleFrac; - var ty = (1 - scaleFrac) * y + translation.y * scaleFrac; - - this._setScale(scaleNew); - this._setTranslation(tx, ty); - this._redraw(); + if (!this.yFixed) { + var dy = -this.damping * this.vy; // damping force + var ay = (this.fy + dy) / this.mass; // acceleration + this.vy += ay / interval; // velocity + this.y += this.vy / interval; // position } +}; - // Prevent default actions caused by mouse wheel. - // That might be ugly, but we handle scrolls somehow - // anyway, so don't bother here... - vis.util.preventDefault(event); + +/** + * Check if this node has a fixed x and y position + * @return {boolean} true if fixed, false if not + */ +Node.prototype.isFixed = function() { + return (this.xFixed && this.yFixed); }; +/** + * Check if this node is moving + * @param {number} vmin the minimum velocity considered as "moving" + * @return {boolean} true if moving, false if it has no velocity + */ +// TODO: replace this method with calculating the kinetic energy +Node.prototype.isMoving = function(vmin) { + return (Math.abs(this.vx) > vmin || Math.abs(this.vy) > vmin || + (!this.xFixed && Math.abs(this.fx) > this.minForce) || + (!this.yFixed && Math.abs(this.fy) > this.minForce)); +}; /** - * Mouse move handler for checking whether the title moves over a node with a title. - * @param {Event} event - * @private + * check if this node is selecte + * @return {boolean} selected True if node is selected, else false */ -Graph.prototype._onMouseMoveTitle = function (event) { - event = event || window.event; +Node.prototype.isSelected = function() { + return this.selected; +}; - var startMouseX = util.getPageX(event); - var startMouseY = util.getPageY(event); - this.startFrameLeft = this.startFrameLeft || vis.util.getAbsoluteLeft(this.frame.canvas); - this.startFrameTop = this.startFrameTop || vis.util.getAbsoluteTop(this.frame.canvas); +/** + * Retrieve the value of the node. Can be undefined + * @return {Number} value + */ +Node.prototype.getValue = function() { + return this.value; +}; - var x = startMouseX - this.startFrameLeft; - var y = startMouseY - this.startFrameTop; +/** + * Calculate the distance from the nodes location to the given location (x,y) + * @param {Number} x + * @param {Number} y + * @return {Number} value + */ +Node.prototype.getDistance = function(x, y) { + var dx = this.x - x, + dy = this.y - y; + return Math.sqrt(dx * dx + dy * dy); +}; - // check if the previously selected node is still selected - if (this.popupNode) { - this._checkHidePopup(x, y); - } - // start a timeout that will check if the mouse is positioned above - // an element - var me = this; - var checkShow = function() { - me._checkShowPopup(x, y); - }; - if (this.popupTimer) { - clearInterval(this.popupTimer); // stop any running timer - } - if (!this.leftButtonDown) { - this.popupTimer = setTimeout(checkShow, 300); +/** + * Adjust the value range of the node. The node will adjust it's radius + * based on its value. + * @param {Number} min + * @param {Number} max + */ +Node.prototype.setValueRange = function(min, max) { + if (!this.radiusFixed && this.value !== undefined) { + var scale = (this.radiusMax - this.radiusMin) / (max - min); + this.radius = (this.value - min) * scale + this.radiusMin; } }; /** - * Check if there is an element on the given position in the graph - * (a node or edge). If so, and if this element has a title, - * show a popup window with its title. - * - * @param {number} x - * @param {number} y - * @private + * Draw this node in the given canvas + * The 2d context of a HTML canvas can be retrieved by canvas.getContext("2d"); + * @param {CanvasRenderingContext2D} ctx */ -Graph.prototype._checkShowPopup = function (x, y) { - var obj = { - "left" : this._xToCanvas(x), - "top" : this._yToCanvas(y), - "right" : this._xToCanvas(x), - "bottom" : this._yToCanvas(y) - }; +Node.prototype.draw = function(ctx) { + throw "Draw method not initialized for node"; +}; - var id; - var lastPopupNode = this.popupNode; +/** + * Recalculate the size of this node in the given canvas + * The 2d context of a HTML canvas can be retrieved by canvas.getContext("2d"); + * @param {CanvasRenderingContext2D} ctx + */ +Node.prototype.resize = function(ctx) { + throw "Resize method not initialized for node"; +}; - if (this.popupNode == undefined) { - // search the nodes for overlap, select the top one in case of multiple nodes - var nodes = this.nodes; - for (id in nodes) { - if (nodes.hasOwnProperty(id)) { - var node = nodes[id]; - if (node.getTitle() != undefined && node.isOverlappingWith(obj)) { - this.popupNode = node; - break; - } - } - } - } +/** + * Check if this object is overlapping with the provided object + * @param {Object} obj an object with parameters left, top, right, bottom + * @return {boolean} True if location is located on node + */ +Node.prototype.isOverlappingWith = function(obj) { + return (this.left < obj.right && + this.left + this.width > obj.left && + this.top < obj.bottom && + this.top + this.height > obj.top); +}; - if (this.popupNode == undefined) { - // search the edges for overlap - var edges = this.edges; - for (id in edges) { - if (edges.hasOwnProperty(id)) { - var edge = edges[id]; - if (edge.connected && (edge.getTitle() != undefined) && - edge.isOverlappingWith(obj)) { - this.popupNode = edge; - break; - } - } +Node.prototype._resizeImage = function (ctx) { + // TODO: pre calculate the image size + if (!this.width) { // undefined or 0 + var width, height; + if (this.value) { + var scale = this.imageObj.height / this.imageObj.width; + width = this.radius || this.imageObj.width; + height = this.radius * scale || this.imageObj.height; + } + else { + width = this.imageObj.width; + height = this.imageObj.height; } + this.width = width; + this.height = height; } +}; - if (this.popupNode) { - // show popup message window - if (this.popupNode != lastPopupNode) { - var me = this; - if (!me.popup) { - me.popup = new Popup(me.frame); - } +Node.prototype._drawImage = function (ctx) { + this._resizeImage(ctx); - // adjust a small offset such that the mouse cursor is located in the - // bottom left location of the popup, and you can easily move over the - // popup area - me.popup.setPosition(x - 3, y - 3); - me.popup.setText(me.popupNode.getTitle()); - me.popup.show(); - } + this.left = this.x - this.width / 2; + this.top = this.y - this.height / 2; + + var yLabel; + if (this.imageObj) { + ctx.drawImage(this.imageObj, this.left, this.top, this.width, this.height); + yLabel = this.y + this.height / 2; } else { - if (this.popup) { - this.popup.hide(); - } + // image still loading... just draw the label for now + yLabel = this.y; } + + this._label(ctx, this.label, this.x, yLabel, undefined, "top"); }; -/** - * Check if the popup must be hided, which is the case when the mouse is no - * longer hovering on the object - * @param {number} x - * @param {number} y - * @private - */ -Graph.prototype._checkHidePopup = function (x, y) { - var obj = { - "left" : x, - "top" : y, - "right" : x, - "bottom" : y - }; - if (!this.popupNode || !this.popupNode.isOverlappingWith(obj) ) { - this.popupNode = undefined; - if (this.popup) { - this.popup.hide(); - } +Node.prototype._resizeBox = function (ctx) { + if (!this.width) { + var margin = 5; + var textSize = this.getTextSize(ctx); + this.width = textSize.width + 2 * margin; + this.height = textSize.height + 2 * margin; } }; -/** - * Event handler for touchstart event on mobile devices - * @param {Event} event - * @private - */ -Graph.prototype._onTouchStart = function(event) { - vis.util.preventDefault(event); +Node.prototype._drawBox = function (ctx) { + this._resizeBox(ctx); - if (this.touchDown) { - // if already moving, return - return; - } - this.touchDown = true; + this.left = this.x - this.width / 2; + this.top = this.y - this.height / 2; - var me = this; - if (!this.ontouchmove) { - this.ontouchmove = function (event) {me._onTouchMove(event);}; - vis.util.addEventListener(document, "touchmove", this.ontouchmove); - } - if (!this.ontouchend) { - this.ontouchend = function (event) {me._onTouchEnd(event);}; - vis.util.addEventListener(document, "touchend", this.ontouchend); - } + ctx.strokeStyle = this.selected ? this.color.highlight.border : this.color.border; + ctx.fillStyle = this.selected ? this.color.highlight.background : this.color.background; + ctx.lineWidth = this.selected ? 2.0 : 1.0; + ctx.roundRect(this.left, this.top, this.width, this.height, this.radius); + ctx.fill(); + ctx.stroke(); - this._onMouseDown(event); + this._label(ctx, this.label, this.x, this.y); }; -/** - * Event handler for touchmove event on mobile devices - * @param {Event} event - * @private - */ -Graph.prototype._onTouchMove = function(event) { - vis.util.preventDefault(event); - this._onMouseMove(event); + +Node.prototype._resizeDatabase = function (ctx) { + if (!this.width) { + var margin = 5; + var textSize = this.getTextSize(ctx); + var size = textSize.width + 2 * margin; + this.width = size; + this.height = size; + } }; -/** - * Event handler for touchend event on mobile devices - * @param {Event} event - * @private - */ -Graph.prototype._onTouchEnd = function(event) { - vis.util.preventDefault(event); +Node.prototype._drawDatabase = function (ctx) { + this._resizeDatabase(ctx); + this.left = this.x - this.width / 2; + this.top = this.y - this.height / 2; + + ctx.strokeStyle = this.selected ? this.color.highlight.border : this.color.border; + ctx.fillStyle = this.selected ? this.color.highlight.background : this.color.background; + ctx.lineWidth = this.selected ? 2.0 : 1.0; + ctx.database(this.x - this.width/2, this.y - this.height*0.5, this.width, this.height); + ctx.fill(); + ctx.stroke(); + + this._label(ctx, this.label, this.x, this.y); +}; - this.touchDown = false; - if (this.ontouchmove) { - vis.util.removeEventListener(document, "touchmove", this.ontouchmove); - this.ontouchmove = undefined; - } - if (this.ontouchend) { - vis.util.removeEventListener(document, "touchend", this.ontouchend); - this.ontouchend = undefined; - } +Node.prototype._resizeCircle = function (ctx) { + if (!this.width) { + var margin = 5; + var textSize = this.getTextSize(ctx); + var diameter = Math.max(textSize.width, textSize.height) + 2 * margin; + this.radius = diameter / 2; - this._onMouseUp(event); + this.width = diameter; + this.height = diameter; + } }; +Node.prototype._drawCircle = function (ctx) { + this._resizeCircle(ctx); + this.left = this.x - this.width / 2; + this.top = this.y - this.height / 2; -/** - * Unselect selected nodes. If no selection array is provided, all nodes - * are unselected - * @param {Object[]} selection Array with selection objects, each selection - * object has a parameter row. Optional - * @param {Boolean} triggerSelect If true (default), the select event - * is triggered when nodes are unselected - * @return {Boolean} changed True if the selection is changed - * @private - */ -Graph.prototype._unselectNodes = function(selection, triggerSelect) { - var changed = false; - var i, iMax, id; + ctx.strokeStyle = this.selected ? this.color.highlight.border : this.color.border; + ctx.fillStyle = this.selected ? this.color.highlight.background : this.color.background; + ctx.lineWidth = this.selected ? 2.0 : 1.0; + ctx.circle(this.x, this.y, this.radius); + ctx.fill(); + ctx.stroke(); - if (selection) { - // remove provided selections - for (i = 0, iMax = selection.length; i < iMax; i++) { - id = selection[i]; - this.nodes[id].unselect(); + this._label(ctx, this.label, this.x, this.y); +}; - var j = 0; - while (j < this.selection.length) { - if (this.selection[j] == id) { - this.selection.splice(j, 1); - changed = true; - } - else { - j++; - } - } - } - } - else if (this.selection && this.selection.length) { - // remove all selections - for (i = 0, iMax = this.selection.length; i < iMax; i++) { - id = this.selection[i]; - this.nodes[id].unselect(); - changed = true; +Node.prototype._resizeEllipse = function (ctx) { + if (!this.width) { + var textSize = this.getTextSize(ctx); + + this.width = textSize.width * 1.5; + this.height = textSize.height * 2; + if (this.width < this.height) { + this.width = this.height; } - this.selection = []; } +}; - if (changed && (triggerSelect == true || triggerSelect == undefined)) { - // fire the select event - this._trigger('select'); - } +Node.prototype._drawEllipse = function (ctx) { + this._resizeEllipse(ctx); + this.left = this.x - this.width / 2; + this.top = this.y - this.height / 2; - return changed; + ctx.strokeStyle = this.selected ? this.color.highlight.border : this.color.border; + ctx.fillStyle = this.selected ? this.color.highlight.background : this.color.background; + ctx.lineWidth = this.selected ? 2.0 : 1.0; + ctx.ellipse(this.left, this.top, this.width, this.height); + ctx.fill(); + ctx.stroke(); + + this._label(ctx, this.label, this.x, this.y); }; -/** - * select all nodes on given location x, y - * @param {Array} selection an array with node ids - * @param {boolean} append If true, the new selection will be appended to the - * current selection (except for duplicate entries) - * @return {Boolean} changed True if the selection is changed - * @private - */ -Graph.prototype._selectNodes = function(selection, append) { - var changed = false; - var i, iMax; +Node.prototype._drawDot = function (ctx) { + this._drawShape(ctx, 'circle'); +}; - // TODO: the selectNodes method is a little messy, rework this +Node.prototype._drawTriangle = function (ctx) { + this._drawShape(ctx, 'triangle'); +}; - // check if the current selection equals the desired selection - var selectionAlreadyThere = true; - if (selection.length != this.selection.length) { - selectionAlreadyThere = false; - } - else { - for (i = 0, iMax = Math.min(selection.length, this.selection.length); i < iMax; i++) { - if (selection[i] != this.selection[i]) { - selectionAlreadyThere = false; - break; - } - } - } - if (selectionAlreadyThere) { - return changed; - } +Node.prototype._drawTriangleDown = function (ctx) { + this._drawShape(ctx, 'triangleDown'); +}; - if (append == undefined || append == false) { - // first deselect any selected node - var triggerSelect = false; - changed = this._unselectNodes(undefined, triggerSelect); - } +Node.prototype._drawSquare = function (ctx) { + this._drawShape(ctx, 'square'); +}; - for (i = 0, iMax = selection.length; i < iMax; i++) { - // add each of the new selections, but only when they are not duplicate - var id = selection[i]; - var isDuplicate = (this.selection.indexOf(id) != -1); - if (!isDuplicate) { - this.nodes[id].select(); - this.selection.push(id); - changed = true; - } +Node.prototype._drawStar = function (ctx) { + this._drawShape(ctx, 'star'); +}; + +Node.prototype._resizeShape = function (ctx) { + if (!this.width) { + var size = 2 * this.radius; + this.width = size; + this.height = size; } +}; - if (changed) { - // fire the select event - this._trigger('select'); - } +Node.prototype._drawShape = function (ctx, shape) { + this._resizeShape(ctx); - return changed; -}; + this.left = this.x - this.width / 2; + this.top = this.y - this.height / 2; -/** - * retrieve all nodes overlapping with given object - * @param {Object} obj An object with parameters left, top, right, bottom - * @return {Object[]} An array with selection objects containing - * the parameter row. - * @private - */ -Graph.prototype._getNodesOverlappingWith = function (obj) { - var nodes = this.nodes, - overlappingNodes = []; + ctx.strokeStyle = this.selected ? this.color.highlight.border : this.color.border; + ctx.fillStyle = this.selected ? this.color.highlight.background : this.color.background; + ctx.lineWidth = this.selected ? 2.0 : 1.0; - for (var id in nodes) { - if (nodes.hasOwnProperty(id)) { - if (nodes[id].isOverlappingWith(obj)) { - overlappingNodes.push(id); - } - } - } + ctx[shape](this.x, this.y, this.radius); + ctx.fill(); + ctx.stroke(); - return overlappingNodes; + if (this.label) { + this._label(ctx, this.label, this.x, this.y + this.height / 2, undefined, 'top'); + } }; -/** - * retrieve the currently selected nodes - * @return {Number[] | String[]} selection An array with the ids of the - * selected nodes. - */ -Graph.prototype.getSelection = function() { - return this.selection.concat([]); +Node.prototype._resizeText = function (ctx) { + if (!this.width) { + var margin = 5; + var textSize = this.getTextSize(ctx); + this.width = textSize.width + 2 * margin; + this.height = textSize.height + 2 * margin; + } }; -/** - * select zero or more nodes - * @param {Number[] | String[]} selection An array with the ids of the - * selected nodes. - */ -Graph.prototype.setSelection = function(selection) { - var i, iMax, id; +Node.prototype._drawText = function (ctx) { + this._resizeText(ctx); + this.left = this.x - this.width / 2; + this.top = this.y - this.height / 2; - if (selection.length == undefined) - throw "Selection must be an array with ids"; + this._label(ctx, this.label, this.x, this.y); +}; - // first unselect any selected node - for (i = 0, iMax = this.selection.length; i < iMax; i++) { - id = this.selection[i]; - this.nodes[id].unselect(); - } - this.selection = []; +Node.prototype._label = function (ctx, text, x, y, align, baseline) { + if (text) { + ctx.font = (this.selected ? "bold " : "") + this.fontSize + "px " + this.fontFace; + ctx.fillStyle = this.fontColor || "black"; + ctx.textAlign = align || "center"; + ctx.textBaseline = baseline || "middle"; - for (i = 0, iMax = selection.length; i < iMax; i++) { - id = selection[i]; + var lines = text.split('\n'), + lineCount = lines.length, + fontSize = (this.fontSize + 4), + yLine = y + (1 - lineCount) / 2 * fontSize; - var node = this.nodes[id]; - if (!node) { - throw new RangeError('Node with id "' + id + '" not found'); + for (var i = 0; i < lineCount; i++) { + ctx.fillText(lines[i], x, yLine); + yLine += fontSize; } - node.select(); - this.selection.push(id); } - - this.redraw(); }; -/** - * Validate the selection: remove ids of nodes which no longer exist - * @private - */ -Graph.prototype._updateSelection = function () { - var i = 0; - while (i < this.selection.length) { - var id = this.selection[i]; - if (!this.nodes[id]) { - this.selection.splice(i, 1); - } - else { - i++; + +Node.prototype.getTextSize = function(ctx) { + if (this.label != undefined) { + ctx.font = (this.selected ? "bold " : "") + this.fontSize + "px " + this.fontFace; + + var lines = this.label.split('\n'), + height = (this.fontSize + 4) * lines.length, + width = 0; + + for (var i = 0, iMax = lines.length; i < iMax; i++) { + width = Math.max(width, ctx.measureText(lines[i]).width); } + + return {"width": width, "height": height}; + } + else { + return {"width": 0, "height": 0}; } }; /** - * Temporary method to test calculating a hub value for the nodes - * @param {number} level Maximum number edges between two nodes in order - * to call them connected. Optional, 1 by default - * @return {Number[]} connectioncount array with the connection count - * for each node - * @private + * @class Edge + * + * A edge connects two nodes + * @param {Object} properties Object with properties. Must contain + * At least properties from and to. + * Available properties: from (number), + * to (number), label (string, color (string), + * width (number), style (string), + * length (number), title (string) + * @param {Graph} graph A graph object, used to find and edge to + * nodes. + * @param {Object} constants An object with default values for + * example for the color */ -Graph.prototype._getConnectionCount = function(level) { - if (level == undefined) { - level = 1; +function Edge (properties, graph, constants) { + if (!graph) { + throw "No graph provided"; } + this.graph = graph; - // get the nodes connected to given nodes - function getConnectedNodes(nodes) { - var connectedNodes = []; + // initialize constants + this.widthMin = constants.edges.widthMin; + this.widthMax = constants.edges.widthMax; - for (var j = 0, jMax = nodes.length; j < jMax; j++) { - var node = nodes[j]; + // initialize variables + this.id = undefined; + this.fromId = undefined; + this.toId = undefined; + this.style = constants.edges.style; + this.title = undefined; + this.width = constants.edges.width; + this.value = undefined; + this.length = constants.edges.length; - // find all nodes connected to this node - var edges = node.edges; - for (var i = 0, iMax = edges.length; i < iMax; i++) { - var edge = edges[i]; - var other = null; + this.from = null; // a node + this.to = null; // a node + this.connected = false; - // check if connected - if (edge.from == node) - other = edge.to; - else if (edge.to == node) - other = edge.from; + // Added to support dashed lines + // David Jordan + // 2012-08-08 + this.dash = util.extend({}, constants.edges.dash); // contains properties length, gap, altLength - // check if the other node is not already in the list with nodes - var k, kMax; - if (other) { - for (k = 0, kMax = nodes.length; k < kMax; k++) { - if (nodes[k] == other) { - other = null; - break; - } - } - } - if (other) { - for (k = 0, kMax = connectedNodes.length; k < kMax; k++) { - if (connectedNodes[k] == other) { - other = null; - break; - } - } - } + this.stiffness = undefined; // depends on the length of the edge + this.color = constants.edges.color; + this.widthFixed = false; + this.lengthFixed = false; - if (other) - connectedNodes.push(other); - } - } + this.setProperties(properties, constants); +} - return connectedNodes; +/** + * Set or overwrite properties for the edge + * @param {Object} properties an object with properties + * @param {Object} constants and object with default, global properties + */ +Edge.prototype.setProperties = function(properties, constants) { + if (!properties) { + return; } - var connections = []; - var nodes = this.nodes; - for (var id in nodes) { - if (nodes.hasOwnProperty(id)) { - var c = [nodes[id]]; - for (var l = 0; l < level; l++) { - c = c.concat(getConnectedNodes(c)); - } - connections.push(c); - } + if (properties.from != undefined) {this.fromId = properties.from;} + if (properties.to != undefined) {this.toId = properties.to;} + + if (properties.id != undefined) {this.id = properties.id;} + if (properties.style != undefined) {this.style = properties.style;} + if (properties.label != undefined) {this.label = properties.label;} + if (this.label) { + this.fontSize = constants.edges.fontSize; + this.fontFace = constants.edges.fontFace; + this.fontColor = constants.edges.fontColor; + if (properties.fontColor != undefined) {this.fontColor = properties.fontColor;} + if (properties.fontSize != undefined) {this.fontSize = properties.fontSize;} + if (properties.fontFace != undefined) {this.fontFace = properties.fontFace;} } + if (properties.title != undefined) {this.title = properties.title;} + if (properties.width != undefined) {this.width = properties.width;} + if (properties.value != undefined) {this.value = properties.value;} + if (properties.length != undefined) {this.length = properties.length;} - var hubs = []; - for (var i = 0, len = connections.length; i < len; i++) { - hubs.push(connections[i].length); + // Added to support dashed lines + // David Jordan + // 2012-08-08 + if (properties.dash) { + if (properties.dash.length != undefined) {this.dash.length = properties.dash.length;} + if (properties.dash.gap != undefined) {this.dash.gap = properties.dash.gap;} + if (properties.dash.altLength != undefined) {this.dash.altLength = properties.dash.altLength;} } + + if (properties.color != undefined) {this.color = properties.color;} - return hubs; -}; - - -/** - * Set a new size for the graph - * @param {string} width Width in pixels or percentage (for example "800px" - * or "50%") - * @param {string} height Height in pixels or percentage (for example "400px" - * or "30%") - */ -Graph.prototype.setSize = function(width, height) { - this.frame.style.width = width; - this.frame.style.height = height; + // A node is connected when it has a from and to node. + this.connect(); - this.frame.canvas.style.width = "100%"; - this.frame.canvas.style.height = "100%"; + this.widthFixed = this.widthFixed || (properties.width != undefined); + this.lengthFixed = this.lengthFixed || (properties.length != undefined); + this.stiffness = 1 / this.length; - this.frame.canvas.width = this.frame.canvas.clientWidth; - this.frame.canvas.height = this.frame.canvas.clientHeight; + // set draw method based on style + switch (this.style) { + case 'line': this.draw = this._drawLine; break; + case 'arrow': this.draw = this._drawArrow; break; + case 'arrow-center': this.draw = this._drawArrowCenter; break; + case 'dash-line': this.draw = this._drawDashLine; break; + default: this.draw = this._drawLine; break; + } }; /** - * Set a data set with nodes for the graph - * @param {Array | DataSet | DataView} nodes The data containing the nodes. - * @private + * Connect an edge to its nodes */ -Graph.prototype._setNodes = function(nodes) { - var oldNodesData = this.nodesData; +Edge.prototype.connect = function () { + this.disconnect(); - if (nodes instanceof DataSet || nodes instanceof DataView) { - this.nodesData = nodes; - } - else if (nodes instanceof Array) { - this.nodesData = new DataSet(); - this.nodesData.add(nodes); - } - else if (!nodes) { - this.nodesData = new DataSet(); + this.from = this.graph.nodes[this.fromId] || null; + this.to = this.graph.nodes[this.toId] || null; + this.connected = (this.from && this.to); + + if (this.connected) { + this.from.attachEdge(this); + this.to.attachEdge(this); } else { - throw new TypeError('Array or DataSet expected'); + if (this.from) { + this.from.detachEdge(this); + } + if (this.to) { + this.to.detachEdge(this); + } } +}; - if (oldNodesData) { - // unsubscribe from old dataset - util.forEach(this.nodesListeners, function (callback, event) { - oldNodesData.unsubscribe(event, callback); - }); +/** + * Disconnect an edge from its nodes + */ +Edge.prototype.disconnect = function () { + if (this.from) { + this.from.detachEdge(this); + this.from = null; } - - // remove drawn nodes - this.nodes = {}; - - if (this.nodesData) { - // subscribe to new dataset - var me = this; - util.forEach(this.nodesListeners, function (callback, event) { - me.nodesData.subscribe(event, callback); - }); - - // draw all new nodes - var ids = this.nodesData.getIds(); - this._addNodes(ids); + if (this.to) { + this.to.detachEdge(this); + this.to = null; } - this._updateSelection(); + this.connected = false; }; /** - * Add nodes - * @param {Number[] | String[]} ids - * @private + * get the title of this edge. + * @return {string} title The title of the edge, or undefined when no title + * has been set. */ -Graph.prototype._addNodes = function(ids) { - var id; - for (var i = 0, len = ids.length; i < len; i++) { - id = ids[i]; - var data = this.nodesData.get(id); - var node = new Node(data, this.images, this.groups, this.constants); - this.nodes[id] = node; // note: this may replace an existing node - - if (!node.isFixed()) { - // TODO: position new nodes in a smarter way! - var radius = this.constants.edges.length * 2; - var count = ids.length; - var angle = 2 * Math.PI * (i / count); - node.x = radius * Math.cos(angle); - node.y = radius * Math.sin(angle); +Edge.prototype.getTitle = function() { + return this.title; +}; - // note: no not use node.isMoving() here, as that gives the current - // velocity of the node, which is zero after creation of the node. - this.moving = true; - } - } - this._reconnectEdges(); - this._updateValueRange(this.nodes); +/** + * Retrieve the value of the edge. Can be undefined + * @return {Number} value + */ +Edge.prototype.getValue = function() { + return this.value; }; /** - * Update existing nodes, or create them when not yet existing - * @param {Number[] | String[]} ids - * @private + * Adjust the value range of the edge. The edge will adjust it's width + * based on its value. + * @param {Number} min + * @param {Number} max */ -Graph.prototype._updateNodes = function(ids) { - var nodes = this.nodes, - nodesData = this.nodesData; - for (var i = 0, len = ids.length; i < len; i++) { - var id = ids[i]; - var node = nodes[id]; - var data = nodesData.get(id); - if (node) { - // update node - node.setProperties(data, this.constants); - } - else { - // create node - node = new Node(properties, this.images, this.groups, this.constants); - nodes[id] = node; - - if (!node.isFixed()) { - this.moving = true; - } - } +Edge.prototype.setValueRange = function(min, max) { + if (!this.widthFixed && this.value !== undefined) { + var factor = (this.widthMax - this.widthMin) / (max - min); + this.width = (this.value - min) * factor + this.widthMin; } +}; - this._reconnectEdges(); - this._updateValueRange(nodes); +/** + * Redraw a edge + * Draw this edge in the given canvas + * The 2d context of a HTML canvas can be retrieved by canvas.getContext("2d"); + * @param {CanvasRenderingContext2D} ctx + */ +Edge.prototype.draw = function(ctx) { + throw "Method draw not initialized in edge"; }; /** - * Remove existing nodes. If nodes do not exist, the method will just ignore it. - * @param {Number[] | String[]} ids - * @private + * Check if this object is overlapping with the provided object + * @param {Object} obj an object with parameters left, top + * @return {boolean} True if location is located on the edge */ -Graph.prototype._removeNodes = function(ids) { - var nodes = this.nodes; - for (var i = 0, len = ids.length; i < len; i++) { - var id = ids[i]; - delete nodes[id]; - } +Edge.prototype.isOverlappingWith = function(obj) { + var distMax = 10; - this._reconnectEdges(); - this._updateSelection(); - this._updateValueRange(nodes); + var xFrom = this.from.x; + var yFrom = this.from.y; + var xTo = this.to.x; + var yTo = this.to.y; + var xObj = obj.left; + var yObj = obj.top; + + + var dist = Edge._dist(xFrom, yFrom, xTo, yTo, xObj, yObj); + + return (dist < distMax); }; + /** - * Load edges by reading the data table - * @param {Array | DataSet | DataView} edges The data containing the edges. - * @private + * Redraw a edge as a line + * Draw this edge in the given canvas + * The 2d context of a HTML canvas can be retrieved by canvas.getContext("2d"); + * @param {CanvasRenderingContext2D} ctx * @private */ -Graph.prototype._setEdges = function(edges) { - var oldEdgesData = this.edgesData; +Edge.prototype._drawLine = function(ctx) { + // set style + ctx.strokeStyle = this.color; + ctx.lineWidth = this._getLineWidth(); - if (edges instanceof DataSet || edges instanceof DataView) { - this.edgesData = edges; - } - else if (edges instanceof Array) { - this.edgesData = new DataSet(); - this.edgesData.add(edges); - } - else if (!edges) { - this.edgesData = new DataSet(); + var point; + if (this.from != this.to) { + // draw line + this._line(ctx); + + // draw label + if (this.label) { + point = this._pointOnLine(0.5); + this._label(ctx, this.label, point.x, point.y); + } } else { - throw new TypeError('Array or DataSet expected'); + var x, y; + var radius = this.length / 4; + var node = this.from; + if (!node.width) { + node.resize(ctx); + } + if (node.width > node.height) { + x = node.x + node.width / 2; + y = node.y - radius; + } + else { + x = node.x + radius; + y = node.y - node.height / 2; + } + this._circle(ctx, x, y, radius); + point = this._pointOnCircle(x, y, radius, 0.5); + this._label(ctx, this.label, point.x, point.y); } +}; - if (oldEdgesData) { - // unsubscribe from old dataset - util.forEach(this.edgesListeners, function (callback, event) { - oldEdgesData.unsubscribe(event, callback); - }); +/** + * Get the line width of the edge. Depends on width and whether one of the + * connected nodes is selected. + * @return {Number} width + * @private + */ +Edge.prototype._getLineWidth = function() { + if (this.from.selected || this.to.selected) { + return Math.min(this.width * 2, this.widthMax); } - - // remove drawn edges - this.edges = {}; - - if (this.edgesData) { - // subscribe to new dataset - var me = this; - util.forEach(this.edgesListeners, function (callback, event) { - me.edgesData.subscribe(event, callback); - }); - - // draw all new nodes - var ids = this.edgesData.getIds(); - this._addEdges(ids); + else { + return this.width; } +}; - this._reconnectEdges(); +/** + * Draw a line between two nodes + * @param {CanvasRenderingContext2D} ctx + * @private + */ +Edge.prototype._line = function (ctx) { + // draw a straight line + ctx.beginPath(); + ctx.moveTo(this.from.x, this.from.y); + ctx.lineTo(this.to.x, this.to.y); + ctx.stroke(); }; /** - * Add edges - * @param {Number[] | String[]} ids + * Draw a line from a node to itself, a circle + * @param {CanvasRenderingContext2D} ctx + * @param {Number} x + * @param {Number} y + * @param {Number} radius * @private */ -Graph.prototype._addEdges = function (ids) { - var edges = this.edges, - edgesData = this.edgesData; - for (var i = 0, len = ids.length; i < len; i++) { - var id = ids[i]; +Edge.prototype._circle = function (ctx, x, y, radius) { + // draw a circle + ctx.beginPath(); + ctx.arc(x, y, radius, 0, 2 * Math.PI, false); + ctx.stroke(); +}; - var oldEdge = edges[id]; - if (oldEdge) { - oldEdge.disconnect(); - } +/** + * Draw label with white background and with the middle at (x, y) + * @param {CanvasRenderingContext2D} ctx + * @param {String} text + * @param {Number} x + * @param {Number} y + * @private + */ +Edge.prototype._label = function (ctx, text, x, y) { + if (text) { + // TODO: cache the calculated size + ctx.font = ((this.from.selected || this.to.selected) ? "bold " : "") + + this.fontSize + "px " + this.fontFace; + ctx.fillStyle = 'white'; + var width = ctx.measureText(text).width; + var height = this.fontSize; + var left = x - width / 2; + var top = y - height / 2; - var data = edgesData.get(id); - edges[id] = new Edge(data, this, this.constants); - } + ctx.fillRect(left, top, width, height); - this.moving = true; - this._updateValueRange(edges); + // draw text + ctx.fillStyle = this.fontColor || "black"; + ctx.textAlign = "left"; + ctx.textBaseline = "top"; + ctx.fillText(text, left, top); + } }; /** - * Update existing edges, or create them when not yet existing - * @param {Number[] | String[]} ids + * Redraw a edge as a dashed line + * Draw this edge in the given canvas + * @author David Jordan + * @date 2012-08-08 + * The 2d context of a HTML canvas can be retrieved by canvas.getContext("2d"); + * @param {CanvasRenderingContext2D} ctx * @private */ -Graph.prototype._updateEdges = function (ids) { - var edges = this.edges, - edgesData = this.edgesData; - for (var i = 0, len = ids.length; i < len; i++) { - var id = ids[i]; +Edge.prototype._drawDashLine = function(ctx) { + // set style + ctx.strokeStyle = this.color; + ctx.lineWidth = this._getLineWidth(); - var data = edgesData.get(id); - var edge = edges[id]; - if (edge) { - // update edge - edge.disconnect(); - edge.setProperties(data, this.constants); - edge.connect(); - } - else { - // create edge - edge = new Edge(data, this, this.constants); - this.edges[id] = edge; - } + // draw dashed line + ctx.beginPath(); + ctx.lineCap = 'round'; + if (this.dash.altLength != undefined) //If an alt dash value has been set add to the array this value + { + ctx.dashedLine(this.from.x,this.from.y,this.to.x,this.to.y, + [this.dash.length,this.dash.gap,this.dash.altLength,this.dash.gap]); + } + else if (this.dash.length != undefined && this.dash.gap != undefined) //If a dash and gap value has been set add to the array this value + { + ctx.dashedLine(this.from.x,this.from.y,this.to.x,this.to.y, + [this.dash.length,this.dash.gap]); + } + else //If all else fails draw a line + { + ctx.moveTo(this.from.x, this.from.y); + ctx.lineTo(this.to.x, this.to.y); } + ctx.stroke(); - this.moving = true; - this._updateValueRange(edges); + // draw label + if (this.label) { + var point = this._pointOnLine(0.5); + this._label(ctx, this.label, point.x, point.y); + } }; /** - * Remove existing edges. Non existing ids will be ignored - * @param {Number[] | String[]} ids + * Get a point on a line + * @param {Number} percentage. Value between 0 (line start) and 1 (line end) + * @return {Object} point * @private */ -Graph.prototype._removeEdges = function (ids) { - var edges = this.edges; - for (var i = 0, len = ids.length; i < len; i++) { - var id = ids[i]; - var edge = edges[id]; - if (edge) { - edge.disconnect(); - delete edges[id]; - } +Edge.prototype._pointOnLine = function (percentage) { + return { + x: (1 - percentage) * this.from.x + percentage * this.to.x, + y: (1 - percentage) * this.from.y + percentage * this.to.y } - - this.moving = true; - this._updateValueRange(edges); }; /** - * Reconnect all edges + * Get a point on a circle + * @param {Number} x + * @param {Number} y + * @param {Number} radius + * @param {Number} percentage. Value between 0 (line start) and 1 (line end) + * @return {Object} point * @private */ -Graph.prototype._reconnectEdges = function() { - var id, - nodes = this.nodes, - edges = this.edges; - for (id in nodes) { - if (nodes.hasOwnProperty(id)) { - nodes[id].edges = []; - } - } - - for (id in edges) { - if (edges.hasOwnProperty(id)) { - var edge = edges[id]; - edge.from = null; - edge.to = null; - edge.connect(); - } +Edge.prototype._pointOnCircle = function (x, y, radius, percentage) { + var angle = (percentage - 3/8) * 2 * Math.PI; + return { + x: x + radius * Math.cos(angle), + y: y - radius * Math.sin(angle) } }; /** - * Update the values of all object in the given array according to the current - * value range of the objects in the array. - * @param {Object} obj An object containing a set of Edges or Nodes - * The objects must have a method getValue() and - * setValueRange(min, max). + * Redraw a edge as a line with an arrow halfway the line + * Draw this edge in the given canvas + * The 2d context of a HTML canvas can be retrieved by canvas.getContext("2d"); + * @param {CanvasRenderingContext2D} ctx * @private */ -Graph.prototype._updateValueRange = function(obj) { - var id; +Edge.prototype._drawArrowCenter = function(ctx) { + var point; + // set style + ctx.strokeStyle = this.color; + ctx.fillStyle = this.color; + ctx.lineWidth = this._getLineWidth(); - // determine the range of the objects - var valueMin = undefined; - var valueMax = undefined; - for (id in obj) { - if (obj.hasOwnProperty(id)) { - var value = obj[id].getValue(); - if (value !== undefined) { - valueMin = (valueMin === undefined) ? value : Math.min(value, valueMin); - valueMax = (valueMax === undefined) ? value : Math.max(value, valueMax); - } + if (this.from != this.to) { + // draw line + this._line(ctx); + + // draw an arrow halfway the line + var angle = Math.atan2((this.to.y - this.from.y), (this.to.x - this.from.x)); + var length = 10 + 5 * this.width; // TODO: make customizable? + point = this._pointOnLine(0.5); + ctx.arrow(point.x, point.y, angle, length); + ctx.fill(); + ctx.stroke(); + + // draw label + if (this.label) { + point = this._pointOnLine(0.5); + this._label(ctx, this.label, point.x, point.y); + } + } + else { + // draw circle + var x, y; + var radius = this.length / 4; + var node = this.from; + if (!node.width) { + node.resize(ctx); + } + if (node.width > node.height) { + x = node.x + node.width / 2; + y = node.y - radius; } - } + else { + x = node.x + radius; + y = node.y - node.height / 2; + } + this._circle(ctx, x, y, radius); - // adjust the range of all objects - if (valueMin !== undefined && valueMax !== undefined) { - for (id in obj) { - if (obj.hasOwnProperty(id)) { - obj[id].setValueRange(valueMin, valueMax); - } + // draw all arrows + var angle = 0.2 * Math.PI; + var length = 10 + 5 * this.width; // TODO: make customizable? + point = this._pointOnCircle(x, y, radius, 0.5); + ctx.arrow(point.x, point.y, angle, length); + ctx.fill(); + ctx.stroke(); + + // draw label + if (this.label) { + point = this._pointOnCircle(x, y, radius, 0.5); + this._label(ctx, this.label, point.x, point.y); } } }; -/** - * Redraw the graph with the current data - * chart will be resized too. - */ -Graph.prototype.redraw = function() { - this.setSize(this.width, this.height); - this._redraw(); -}; /** - * Redraw the graph with the current data + * Redraw a edge as a line with an arrow + * Draw this edge in the given canvas + * The 2d context of a HTML canvas can be retrieved by canvas.getContext("2d"); + * @param {CanvasRenderingContext2D} ctx * @private */ -Graph.prototype._redraw = function() { - var ctx = this.frame.canvas.getContext("2d"); +Edge.prototype._drawArrow = function(ctx) { + // set style + ctx.strokeStyle = this.color; + ctx.fillStyle = this.color; + ctx.lineWidth = this._getLineWidth(); - // clear the canvas - var w = this.frame.canvas.width; - var h = this.frame.canvas.height; - ctx.clearRect(0, 0, w, h); + // draw line + var angle, length; + if (this.from != this.to) { + // calculate length and angle of the line + angle = Math.atan2((this.to.y - this.from.y), (this.to.x - this.from.x)); + var dx = (this.to.x - this.from.x); + var dy = (this.to.y - this.from.y); + var lEdge = Math.sqrt(dx * dx + dy * dy); - // set scaling and translation - ctx.save(); - ctx.translate(this.translation.x, this.translation.y); - ctx.scale(this.scale, this.scale); + var lFrom = this.from.distanceToBorder(ctx, angle + Math.PI); + var pFrom = (lEdge - lFrom) / lEdge; + var xFrom = (pFrom) * this.from.x + (1 - pFrom) * this.to.x; + var yFrom = (pFrom) * this.from.y + (1 - pFrom) * this.to.y; - this._drawEdges(ctx); - this._drawNodes(ctx); + var lTo = this.to.distanceToBorder(ctx, angle); + var pTo = (lEdge - lTo) / lEdge; + var xTo = (1 - pTo) * this.from.x + pTo * this.to.x; + var yTo = (1 - pTo) * this.from.y + pTo * this.to.y; - // restore original scaling and translation - ctx.restore(); -}; + ctx.beginPath(); + ctx.moveTo(xFrom, yFrom); + ctx.lineTo(xTo, yTo); + ctx.stroke(); -/** - * Set the translation of the graph - * @param {Number} offsetX Horizontal offset - * @param {Number} offsetY Vertical offset - * @private - */ -Graph.prototype._setTranslation = function(offsetX, offsetY) { - if (this.translation === undefined) { - this.translation = { - "x": 0, - "y": 0 - }; - } + // draw arrow at the end of the line + length = 10 + 5 * this.width; // TODO: make customizable? + ctx.arrow(xTo, yTo, angle, length); + ctx.fill(); + ctx.stroke(); - if (offsetX !== undefined) { - this.translation.x = offsetX; + // draw label + if (this.label) { + var point = this._pointOnLine(0.5); + this._label(ctx, this.label, point.x, point.y); + } } - if (offsetY !== undefined) { - this.translation.y = offsetY; + else { + // draw circle + var node = this.from; + var x, y, arrow; + var radius = this.length / 4; + if (!node.width) { + node.resize(ctx); + } + if (node.width > node.height) { + x = node.x + node.width / 2; + y = node.y - radius; + arrow = { + x: x, + y: node.y, + angle: 0.9 * Math.PI + }; + } + else { + x = node.x + radius; + y = node.y - node.height / 2; + arrow = { + x: node.x, + y: y, + angle: 0.6 * Math.PI + }; + } + ctx.beginPath(); + // TODO: do not draw a circle, but an arc + // TODO: similarly, for a line without arrows, draw to the border of the nodes instead of the center + ctx.arc(x, y, radius, 0, 2 * Math.PI, false); + ctx.stroke(); + + // draw all arrows + length = 10 + 5 * this.width; // TODO: make customizable? + ctx.arrow(arrow.x, arrow.y, arrow.angle, length); + ctx.fill(); + ctx.stroke(); + + // draw label + if (this.label) { + point = this._pointOnCircle(x, y, radius, 0.5); + this._label(ctx, this.label, point.x, point.y); + } } }; -/** - * Get the translation of the graph - * @return {Object} translation An object with parameters x and y, both a number - * @private - */ -Graph.prototype._getTranslation = function() { - return { - "x": this.translation.x, - "y": this.translation.y - }; -}; + /** - * Scale the graph - * @param {Number} scale Scaling factor 1.0 is unscaled - * @private - */ -Graph.prototype._setScale = function(scale) { - this.scale = scale; -}; -/** - * Get the current scale of the graph - * @return {Number} scale Scaling factor 1.0 is unscaled + * Calculate the distance between a point (x3,y3) and a line segment from + * (x1,y1) to (x2,y2). + * http://stackoverflow.com/questions/849211/shortest-distancae-between-a-point-and-a-line-segment + * @param {number} x1 + * @param {number} y1 + * @param {number} x2 + * @param {number} y2 + * @param {number} x3 + * @param {number} y3 * @private */ -Graph.prototype._getScale = function() { - return this.scale; -}; +Edge._dist = function (x1,y1, x2,y2, x3,y3) { // x3,y3 is the point + var px = x2-x1, + py = y2-y1, + something = px*px + py*py, + u = ((x3 - x1) * px + (y3 - y1) * py) / something; -Graph.prototype._xToCanvas = function(x) { - return (x - this.translation.x) / this.scale; -}; + if (u > 1) { + u = 1; + } + else if (u < 0) { + u = 0; + } -Graph.prototype._canvasToX = function(x) { - return x * this.scale + this.translation.x; -}; + var x = x1 + u * px, + y = y1 + u * py, + dx = x - x3, + dy = y - y3; -Graph.prototype._yToCanvas = function(y) { - return (y - this.translation.y) / this.scale; -}; + //# Note: If the actual distance does not matter, + //# if you only want to compare what this function + //# returns to other results of this function, you + //# can just return the squared distance instead + //# (i.e. remove the sqrt) to gain a little performance -Graph.prototype._canvasToY = function(y) { - return y * this.scale + this.translation.y ; + return Math.sqrt(dx*dx + dy*dy); }; /** - * Redraw all nodes - * The 2d context of a HTML canvas can be retrieved by canvas.getContext("2d"); - * @param {CanvasRenderingContext2D} ctx - * @private + * Popup is a class to create a popup window with some text + * @param {Element} container The container object. + * @param {Number} [x] + * @param {Number} [y] + * @param {String} [text] */ -Graph.prototype._drawNodes = function(ctx) { - // first draw the unselected nodes - var nodes = this.nodes; - var selected = []; - for (var id in nodes) { - if (nodes.hasOwnProperty(id)) { - if (nodes[id].isSelected()) { - selected.push(id); - } - else { - nodes[id].draw(ctx); - } - } +function Popup(container, x, y, text) { + if (container) { + this.container = container; + } + else { + this.container = document.body; } + this.x = 0; + this.y = 0; + this.padding = 5; - // draw the selected nodes on top - for (var s = 0, sMax = selected.length; s < sMax; s++) { - nodes[selected[s]].draw(ctx); + if (x !== undefined && y !== undefined ) { + this.setPosition(x, y); + } + if (text !== undefined) { + this.setText(text); } + + // create the frame + this.frame = document.createElement("div"); + var style = this.frame.style; + style.position = "absolute"; + style.visibility = "hidden"; + style.border = "1px solid #666"; + style.color = "black"; + style.padding = this.padding + "px"; + style.backgroundColor = "#FFFFC6"; + style.borderRadius = "3px"; + style.MozBorderRadius = "3px"; + style.WebkitBorderRadius = "3px"; + style.boxShadow = "3px 3px 10px rgba(128, 128, 128, 0.5)"; + style.whiteSpace = "nowrap"; + this.container.appendChild(this.frame); }; /** - * Redraw all edges - * The 2d context of a HTML canvas can be retrieved by canvas.getContext("2d"); - * @param {CanvasRenderingContext2D} ctx - * @private + * @param {number} x Horizontal position of the popup window + * @param {number} y Vertical position of the popup window */ -Graph.prototype._drawEdges = function(ctx) { - var edges = this.edges; - for (var id in edges) { - if (edges.hasOwnProperty(id)) { - var edge = edges[id]; - if (edge.connected) { - edges[id].draw(ctx); - } - } - } +Popup.prototype.setPosition = function(x, y) { + this.x = parseInt(x); + this.y = parseInt(y); }; /** - * Find a stable position for all nodes - * @private + * Set the text for the popup window. This can be HTML code + * @param {string} text */ -Graph.prototype._doStabilize = function() { - var start = new Date(); - - // find stable position - var count = 0; - var vmin = this.constants.minVelocity; - var stable = false; - while (!stable && count < this.constants.maxIterations) { - this._calculateForces(); - this._discreteStepNodes(); - stable = !this._isMoving(vmin); - count++; - } - - var end = new Date(); - - // console.log("Stabilized in " + (end-start) + " ms, " + count + " iterations" ); // TODO: cleanup +Popup.prototype.setText = function(text) { + this.frame.innerHTML = text; }; /** - * Calculate the external forces acting on the nodes - * Forces are caused by: edges, repulsing forces between nodes, gravity - * @private + * Show the popup window + * @param {boolean} show Optional. Show or hide the window */ -Graph.prototype._calculateForces = function() { - // create a local edge to the nodes and edges, that is faster - var id, dx, dy, angle, distance, fx, fy, - repulsingForce, springForce, length, edgeLength, - nodes = this.nodes, - edges = this.edges; - - // gravity, add a small constant force to pull the nodes towards the center of - // the graph - // Also, the forces are reset to zero in this loop by using _setForce instead - // of _addForce - var gravity = 0.01, - gx = this.frame.canvas.clientWidth / 2, - gy = this.frame.canvas.clientHeight / 2; - for (id in nodes) { - if (nodes.hasOwnProperty(id)) { - var node = nodes[id]; - dx = gx - node.x; - dy = gy - node.y; - angle = Math.atan2(dy, dx); - fx = Math.cos(angle) * gravity; - fy = Math.sin(angle) * gravity; - - node._setForce(fx, fy); - } +Popup.prototype.show = function (show) { + if (show === undefined) { + show = true; } - // repulsing forces between nodes - var minimumDistance = this.constants.nodes.distance, - steepness = 10; // higher value gives steeper slope of the force around the given minimumDistance - - for (var id1 in nodes) { - if (nodes.hasOwnProperty(id1)) { - var node1 = nodes[id1]; - for (var id2 in nodes) { - if (nodes.hasOwnProperty(id2)) { - var node2 = nodes[id2]; - // calculate normally distributed force - dx = node2.x - node1.x; - dy = node2.y - node1.y; - distance = Math.sqrt(dx * dx + dy * dy); - angle = Math.atan2(dy, dx); - - // TODO: correct factor for repulsing force - //repulsingForce = 2 * Math.exp(-5 * (distance * distance) / (dmin * dmin) ); // TODO: customize the repulsing force - //repulsingForce = Math.exp(-1 * (distance * distance) / (dmin * dmin) ); // TODO: customize the repulsing force - repulsingForce = 1 / (1 + Math.exp((distance / minimumDistance - 1) * steepness)); // TODO: customize the repulsing force - fx = Math.cos(angle) * repulsingForce; - fy = Math.sin(angle) * repulsingForce; + if (show) { + var height = this.frame.clientHeight; + var width = this.frame.clientWidth; + var maxHeight = this.frame.parentNode.clientHeight; + var maxWidth = this.frame.parentNode.clientWidth; - node1._addForce(-fx, -fy); - node2._addForce(fx, fy); - } - } + var top = (this.y - height); + if (top + height + this.padding > maxHeight) { + top = maxHeight - height - this.padding; + } + if (top < this.padding) { + top = this.padding; } - } - - /* TODO: re-implement repulsion of edges - for (var n = 0; n < nodes.length; n++) { - for (var l = 0; l < edges.length; l++) { - var lx = edges[l].from.x+(edges[l].to.x - edges[l].from.x)/2, - ly = edges[l].from.y+(edges[l].to.y - edges[l].from.y)/2, - - // calculate normally distributed force - dx = nodes[n].x - lx, - dy = nodes[n].y - ly, - distance = Math.sqrt(dx * dx + dy * dy), - angle = Math.atan2(dy, dx), + var left = this.x; + if (left + width + this.padding > maxWidth) { + left = maxWidth - width - this.padding; + } + if (left < this.padding) { + left = this.padding; + } - // TODO: correct factor for repulsing force - //var repulsingforce = 2 * Math.exp(-5 * (distance * distance) / (dmin * dmin) ); // TODO: customize the repulsing force - //repulsingforce = Math.exp(-1 * (distance * distance) / (dmin * dmin) ), // TODO: customize the repulsing force - repulsingforce = 1 / (1 + Math.exp((distance / (minimumDistance / 2) - 1) * steepness)), // TODO: customize the repulsing force - fx = Math.cos(angle) * repulsingforce, - fy = Math.sin(angle) * repulsingforce; - nodes[n]._addForce(fx, fy); - edges[l].from._addForce(-fx/2,-fy/2); - edges[l].to._addForce(-fx/2,-fy/2); - } + this.frame.style.left = left + "px"; + this.frame.style.top = top + "px"; + this.frame.style.visibility = "visible"; } - */ - - // forces caused by the edges, modelled as springs - for (id in edges) { - if (edges.hasOwnProperty(id)) { - var edge = edges[id]; - if (edge.connected) { - dx = (edge.to.x - edge.from.x); - dy = (edge.to.y - edge.from.y); - //edgeLength = (edge.from.width + edge.from.height + edge.to.width + edge.to.height)/2 || edge.length; // TODO: dmin - //edgeLength = (edge.from.width + edge.to.width)/2 || edge.length; // TODO: dmin - //edgeLength = 20 + ((edge.from.width + edge.to.width) || 0) / 2; - edgeLength = edge.length; - length = Math.sqrt(dx * dx + dy * dy); - angle = Math.atan2(dy, dx); - - springForce = edge.stiffness * (edgeLength - length); - - fx = Math.cos(angle) * springForce; - fy = Math.sin(angle) * springForce; - - edge.from._addForce(-fx, -fy); - edge.to._addForce(fx, fy); - } - } + else { + this.hide(); } +}; - /* TODO: re-implement repulsion of edges - // repulsing forces between edges - var minimumDistance = this.constants.edges.distance, - steepness = 10; // higher value gives steeper slope of the force around the given minimumDistance - for (var l = 0; l < edges.length; l++) { - //Keep distance from other edge centers - for (var l2 = l + 1; l2 < this.edges.length; l2++) { - //var dmin = (nodes[n].width + nodes[n].height + nodes[n2].width + nodes[n2].height) / 1 || minimumDistance, // TODO: dmin - //var dmin = (nodes[n].width + nodes[n2].width)/2 || minimumDistance, // TODO: dmin - //dmin = 40 + ((nodes[n].width/2 + nodes[n2].width/2) || 0), - var lx = edges[l].from.x+(edges[l].to.x - edges[l].from.x)/2, - ly = edges[l].from.y+(edges[l].to.y - edges[l].from.y)/2, - l2x = edges[l2].from.x+(edges[l2].to.x - edges[l2].from.x)/2, - l2y = edges[l2].from.y+(edges[l2].to.y - edges[l2].from.y)/2, +/** + * Hide the popup window + */ +Popup.prototype.hide = function () { + this.frame.style.visibility = "hidden"; +}; - // calculate normally distributed force - dx = l2x - lx, - dy = l2y - ly, - distance = Math.sqrt(dx * dx + dy * dy), - angle = Math.atan2(dy, dx), +/** + * @class Groups + * This class can store groups and properties specific for groups. + */ +Groups = function () { + this.clear(); + this.defaultIndex = 0; +}; - // TODO: correct factor for repulsing force - //var repulsingforce = 2 * Math.exp(-5 * (distance * distance) / (dmin * dmin) ); // TODO: customize the repulsing force - //repulsingforce = Math.exp(-1 * (distance * distance) / (dmin * dmin) ), // TODO: customize the repulsing force - repulsingforce = 1 / (1 + Math.exp((distance / minimumDistance - 1) * steepness)), // TODO: customize the repulsing force - fx = Math.cos(angle) * repulsingforce, - fy = Math.sin(angle) * repulsingforce; +/** + * default constants for group colors + */ +Groups.DEFAULT = [ + {border: "#2B7CE9", background: "#97C2FC", highlight: {border: "#2B7CE9", background: "#D2E5FF"}}, // blue + {border: "#FFA500", background: "#FFFF00", highlight: {border: "#FFA500", background: "#FFFFA3"}}, // yellow + {border: "#FA0A10", background: "#FB7E81", highlight: {border: "#FA0A10", background: "#FFAFB1"}}, // red + {border: "#41A906", background: "#7BE141", highlight: {border: "#41A906", background: "#A1EC76"}}, // green + {border: "#E129F0", background: "#EB7DF4", highlight: {border: "#E129F0", background: "#F0B3F5"}}, // magenta + {border: "#7C29F0", background: "#AD85E4", highlight: {border: "#7C29F0", background: "#D3BDF0"}}, // purple + {border: "#C37F00", background: "#FFA807", highlight: {border: "#C37F00", background: "#FFCA66"}}, // orange + {border: "#4220FB", background: "#6E6EFD", highlight: {border: "#4220FB", background: "#9B9BFD"}}, // darkblue + {border: "#FD5A77", background: "#FFC0CB", highlight: {border: "#FD5A77", background: "#FFD1D9"}}, // pink + {border: "#4AD63A", background: "#C2FABC", highlight: {border: "#4AD63A", background: "#E6FFE3"}} // mint +]; - edges[l].from._addForce(-fx, -fy); - edges[l].to._addForce(-fx, -fy); - edges[l2].from._addForce(fx, fy); - edges[l2].to._addForce(fx, fy); - } - } - */ + +/** + * Clear all groups + */ +Groups.prototype.clear = function () { + this.groups = {}; + this.groups.length = function() + { + var i = 0; + for ( var p in this ) { + if (this.hasOwnProperty(p)) { + i++; + } + } + return i; + } }; /** - * Check if any of the nodes is still moving - * @param {number} vmin the minimum velocity considered as "moving" - * @return {boolean} true if moving, false if non of the nodes is moving - * @private + * get group properties of a groupname. If groupname is not found, a new group + * is added. + * @param {*} groupname Can be a number, string, Date, etc. + * @return {Object} group The created group, containing all group properties */ -Graph.prototype._isMoving = function(vmin) { - // TODO: ismoving does not work well: should check the kinetic energy, not its velocity - var nodes = this.nodes; - for (var id in nodes) { - if (nodes.hasOwnProperty(id) && nodes[id].isMoving(vmin)) { - return true; - } +Groups.prototype.get = function (groupname) { + var group = this.groups[groupname]; + + if (group == undefined) { + // create new group + var index = this.defaultIndex % Groups.DEFAULT.length; + this.defaultIndex++; + group = {}; + group.color = Groups.DEFAULT[index]; + this.groups[groupname] = group; } - return false; -}; + return group; +}; /** - * Perform one discrete step for all nodes - * @private + * Add a custom group style + * @param {String} groupname + * @param {Object} style An object containing borderColor, + * backgroundColor, etc. + * @return {Object} group The created group object */ -Graph.prototype._discreteStepNodes = function() { - var interval = this.refreshRate / 1000.0; // in seconds - var nodes = this.nodes; - for (var id in nodes) { - if (nodes.hasOwnProperty(id)) { - nodes[id].discreteStep(interval); - } +Groups.prototype.add = function (groupname, style) { + this.groups[groupname] = style; + if (style.color) { + style.color = Node.parseColor(style.color); } + return style; }; /** - * Start animating nodes and edges + * @class Images + * This class loads images and keeps them stored. */ -Graph.prototype.start = function() { - if (this.moving) { - this._calculateForces(); - this._discreteStepNodes(); +Images = function () { + this.images = {}; - var vmin = this.constants.minVelocity; - this.moving = this._isMoving(vmin); - } + this.callback = undefined; +}; - if (this.moving) { - // start animation. only start timer if it is not already running - if (!this.timer) { - var graph = this; - this.timer = window.setTimeout(function () { - graph.timer = undefined; - graph.start(); - graph._redraw(); - }, this.refreshRate); - } - } - else { - this._redraw(); - } +/** + * Set an onload callback function. This will be called each time an image + * is loaded + * @param {function} callback + */ +Images.prototype.setOnloadCallback = function(callback) { + this.callback = callback; }; /** - * Stop animating nodes and edges. + * + * @param {string} url Url of the image + * @return {Image} img The image object */ -Graph.prototype.stop = function () { - if (this.timer) { - window.clearInterval(this.timer); - this.timer = undefined; +Images.prototype.load = function(url) { + var img = this.images[url]; + if (img == undefined) { + // create the image + var images = this; + img = new Image(); + this.images[url] = img; + img.onload = function() { + if (images.callback) { + images.callback(this); + } + }; + img.src = url; } + + return img; }; /** - * vis.js module exports + * @constructor Graph + * Create a graph visualization, displaying nodes and edges. + * + * @param {Element} container The DOM element in which the Graph will + * be created. Normally a div element. + * @param {Object} data An object containing parameters + * {Array} nodes + * {Array} edges + * @param {Object} options Options */ -var vis = { - util: util, - events: events, - - Controller: Controller, - DataSet: DataSet, - DataView: DataView, - Range: Range, - Stack: Stack, - TimeStep: TimeStep, - EventBus: EventBus, +function Graph (container, data, options) { + // create variables and set default values + this.containerElement = container; + this.width = '100%'; + this.height = '100%'; + this.refreshRate = 50; // milliseconds + this.stabilize = true; // stabilize before displaying the graph + this.selectable = true; - components: { - items: { - Item: Item, - ItemBox: ItemBox, - ItemPoint: ItemPoint, - ItemRange: ItemRange + // set constant values + this.constants = { + nodes: { + radiusMin: 5, + radiusMax: 20, + radius: 5, + distance: 100, // px + shape: 'ellipse', + image: undefined, + widthMin: 16, // px + widthMax: 64, // px + fontColor: 'black', + fontSize: 14, // px + //fontFace: verdana, + fontFace: 'arial', + color: { + border: '#2B7CE9', + background: '#97C2FC', + highlight: { + border: '#2B7CE9', + background: '#D2E5FF' + } + }, + borderColor: '#2B7CE9', + backgroundColor: '#97C2FC', + highlightColor: '#D2E5FF', + group: undefined }, + edges: { + widthMin: 1, + widthMax: 15, + width: 1, + style: 'line', + color: '#343434', + fontColor: '#343434', + fontSize: 14, // px + fontFace: 'arial', + //distance: 100, //px + length: 100, // px + dash: { + length: 10, + gap: 5, + altLength: undefined + } + }, + minForce: 0.05, + minVelocity: 0.02, // px/s + maxIterations: 1000 // maximum number of iteration to stabilize + }; - Component: Component, - Panel: Panel, - RootPanel: RootPanel, - ItemSet: ItemSet, - TimeAxis: TimeAxis - }, - - graph: { - Node: Node, - Edge: Edge, - Popup: Popup, - Groups: Groups, - Images: Images - }, + var graph = this; + this.nodes = {}; // object with Node objects + this.edges = {}; // object with Edge objects + // TODO: create a counter to keep track on the number of nodes having values + // TODO: create a counter to keep track on the number of nodes currently moving + // TODO: create a counter to keep track on the number of edges having values - Timeline: Timeline, - Graph: Graph -}; + this.nodesData = null; // A DataSet or DataView + this.edgesData = null; // A DataSet or DataView -/** - * CommonJS module exports - */ -if (typeof exports !== 'undefined') { - exports = vis; -} -if (typeof module !== 'undefined' && typeof module.exports !== 'undefined') { - module.exports = vis; -} + // create event listeners used to subscribe on the DataSets of the nodes and edges + var me = this; + this.nodesListeners = { + 'add': function (event, params) { + me._addNodes(params.items); + me.start(); + }, + 'update': function (event, params) { + me._updateNodes(params.items); + me.start(); + }, + 'remove': function (event, params) { + me._removeNodes(params.items); + me.start(); + } + }; + this.edgesListeners = { + 'add': function (event, params) { + me._addEdges(params.items); + me.start(); + }, + 'update': function (event, params) { + me._updateEdges(params.items); + me.start(); + }, + 'remove': function (event, params) { + me._removeEdges(params.items); + me.start(); + } + }; -/** - * AMD module exports - */ -if (typeof(define) === 'function') { - define(function () { - return vis; + this.groups = new Groups(); // object with groups + this.images = new Images(); // object with images + this.images.setOnloadCallback(function () { + graph._redraw(); }); -} - -/** - * Window exports - */ -if (typeof window !== 'undefined') { - // attach the module to the window, load as a regular javascript file - window['vis'] = vis; -} - -// inject css -util.loadCss("/* vis.js stylesheet */\n.vis.timeline {\n}\n\n\n.vis.timeline.rootpanel {\n position: relative;\n overflow: hidden;\n\n border: 1px solid #bfbfbf;\n -moz-box-sizing: border-box;\n box-sizing: border-box;\n}\n\n.vis.timeline .panel {\n position: absolute;\n overflow: hidden;\n}\n\n\n.vis.timeline .groupset {\n position: absolute;\n padding: 0;\n margin: 0;\n}\n\n.vis.timeline .labels {\n position: absolute;\n top: 0;\n left: 0;\n width: 100%;\n height: 100%;\n\n padding: 0;\n margin: 0;\n\n border-right: 1px solid #bfbfbf;\n box-sizing: border-box;\n -moz-box-sizing: border-box;\n}\n\n.vis.timeline .labels .label {\n position: absolute;\n left: 0;\n top: 0;\n width: 100%;\n border-bottom: 1px solid #bfbfbf;\n color: #4d4d4d;\n}\n\n.vis.timeline .labels .label .inner {\n display: inline-block;\n padding: 5px;\n}\n\n\n.vis.timeline .itemset {\n position: absolute;\n padding: 0;\n margin: 0;\n overflow: hidden;\n}\n\n.vis.timeline .background {\n}\n\n.vis.timeline .foreground {\n}\n\n.vis.timeline .itemset-axis {\n position: absolute;\n}\n\n.vis.timeline .groupset .itemset-axis {\n border-top: 1px solid #bfbfbf;\n}\n\n/* TODO: with orientation=='bottom', this will more or less overlap with timeline axis\n.vis.timeline .groupset .itemset-axis:last-child {\n border-top: none;\n}\n*/\n\n\n.vis.timeline .item {\n position: absolute;\n color: #1A1A1A;\n border-color: #97B0F8;\n background-color: #D5DDF6;\n display: inline-block;\n}\n\n.vis.timeline .item.selected {\n border-color: #FFC200;\n background-color: #FFF785;\n z-index: 999;\n}\n\n.vis.timeline .item.cluster {\n /* TODO: use another color or pattern? */\n background: #97B0F8 url('img/cluster_bg.png');\n color: white;\n}\n.vis.timeline .item.cluster.point {\n border-color: #D5DDF6;\n}\n\n.vis.timeline .item.box {\n text-align: center;\n border-style: solid;\n border-width: 1px;\n border-radius: 5px;\n -moz-border-radius: 5px; /* For Firefox 3.6 and older */\n}\n\n.vis.timeline .item.point {\n background: none;\n}\n\n.vis.timeline .dot {\n border: 5px solid #97B0F8;\n position: absolute;\n border-radius: 5px;\n -moz-border-radius: 5px; /* For Firefox 3.6 and older */\n}\n\n.vis.timeline .item.range {\n overflow: hidden;\n border-style: solid;\n border-width: 1px;\n border-radius: 2px;\n -moz-border-radius: 2px; /* For Firefox 3.6 and older */\n}\n\n.vis.timeline .item.range .drag-left {\n cursor: w-resize;\n z-index: 1000;\n}\n\n.vis.timeline .item.range .drag-right {\n cursor: e-resize;\n z-index: 1000;\n}\n\n.vis.timeline .item.range .content {\n position: relative;\n display: inline-block;\n}\n\n.vis.timeline .item.line {\n position: absolute;\n width: 0;\n border-left-width: 1px;\n border-left-style: solid;\n}\n\n.vis.timeline .item .content {\n margin: 5px;\n white-space: nowrap;\n overflow: hidden;\n}\n\n.vis.timeline .axis {\n position: relative;\n}\n\n.vis.timeline .axis .text {\n position: absolute;\n color: #4d4d4d;\n padding: 3px;\n white-space: nowrap;\n}\n\n.vis.timeline .axis .text.measure {\n position: absolute;\n padding-left: 0;\n padding-right: 0;\n margin-left: 0;\n margin-right: 0;\n visibility: hidden;\n}\n\n.vis.timeline .axis .grid.vertical {\n position: absolute;\n width: 0;\n border-right: 1px solid;\n}\n\n.vis.timeline .axis .grid.horizontal {\n position: absolute;\n left: 0;\n width: 100%;\n height: 0;\n border-bottom: 1px solid;\n}\n\n.vis.timeline .axis .grid.minor {\n border-color: #e5e5e5;\n}\n\n.vis.timeline .axis .grid.major {\n border-color: #bfbfbf;\n}\n\n"); -})() -},{"moment":2}],2:[function(require,module,exports){ -(function(){// moment.js -// version : 2.0.0 -// author : Tim Wood -// license : MIT -// momentjs.com - -(function (undefined) { + // properties of the data + this.moving = false; // True if any of the nodes have an undefined position - /************************************ - Constants - ************************************/ + this.selection = []; + this.timer = undefined; - var moment, - VERSION = "2.0.0", - round = Math.round, i, - // internal storage for language config files - languages = {}, + // create a frame and canvas + this._create(); - // check for nodeJS - hasModule = (typeof module !== 'undefined' && module.exports), + // apply options + this.setOptions(options); - // ASP.NET json date format regex - aspNetJsonRegex = /^\/?Date\((\-?\d+)/i, + // draw data + this.setData(data); +} - // format tokens - formattingTokens = /(\[[^\[]*\])|(\\)?(Mo|MM?M?M?|Do|DDDo|DD?D?D?|ddd?d?|do?|w[o|w]?|W[o|W]?|YYYYY|YYYY|YY|a|A|hh?|HH?|mm?|ss?|SS?S?|X|zz?|ZZ?|.)/g, - localFormattingTokens = /(\[[^\[]*\])|(\\)?(LT|LL?L?L?|l{1,4})/g, +/** + * Set nodes and edges, and optionally options as well. + * + * @param {Object} data Object containing parameters: + * {Array | DataSet | DataView} [nodes] Array with nodes + * {Array | DataSet | DataView} [edges] Array with edges + * {String} [dot] String containing data in DOT format + * {Options} [options] Object with options + */ +Graph.prototype.setData = function(data) { + if (data && data.dot && (data.nodes || data.edges)) { + throw new SyntaxError('Data must contain either parameter "dot" or ' + + ' parameter pair "nodes" and "edges", but not both.'); + } - // parsing tokens - parseMultipleFormatChunker = /([0-9a-zA-Z\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF]+)/gi, + // set options + this.setOptions(data && data.options); - // parsing token regexes - parseTokenOneOrTwoDigits = /\d\d?/, // 0 - 99 - parseTokenOneToThreeDigits = /\d{1,3}/, // 0 - 999 - parseTokenThreeDigits = /\d{3}/, // 000 - 999 - parseTokenFourDigits = /\d{1,4}/, // 0 - 9999 - parseTokenSixDigits = /[+\-]?\d{1,6}/, // -999,999 - 999,999 - parseTokenWord = /[0-9]*[a-z\u00A0-\u05FF\u0700-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF]+|[\u0600-\u06FF]+\s*?[\u0600-\u06FF]+/i, // any word (or two) characters or numbers including two word month in arabic. - parseTokenTimezone = /Z|[\+\-]\d\d:?\d\d/i, // +00:00 -00:00 +0000 -0000 or Z - parseTokenT = /T/i, // T (ISO seperator) - parseTokenTimestampMs = /[\+\-]?\d+(\.\d{1,3})?/, // 123456789 123456789.123 + // set all data + if (data && data.dot) { + // parse DOT file + if(data && data.dot) { + var dotData = vis.util.DOTToGraph(data.dot); + this.setData(dotData); + return; + } + } + else { + this._setNodes(data && data.nodes); + this._setEdges(data && data.edges); + } - // preliminary iso regex - // 0000-00-00 + T + 00 or 00:00 or 00:00:00 or 00:00:00.000 + +00:00 or +0000 - isoRegex = /^\s*\d{4}-\d\d-\d\d((T| )(\d\d(:\d\d(:\d\d(\.\d\d?\d?)?)?)?)?([\+\-]\d\d:?\d\d)?)?/, - isoFormat = 'YYYY-MM-DDTHH:mm:ssZ', - // iso time formats and regexes - isoTimes = [ - ['HH:mm:ss.S', /(T| )\d\d:\d\d:\d\d\.\d{1,3}/], - ['HH:mm:ss', /(T| )\d\d:\d\d:\d\d/], - ['HH:mm', /(T| )\d\d:\d\d/], - ['HH', /(T| )\d\d/] - ], + // find a stable position or start animating to a stable position + if (this.stabilize) { + this._doStabilize(); + } + this.start(); +}; - // timezone chunker "+10:00" > ["10", "00"] or "-1530" > ["-15", "30"] - parseTimezoneChunker = /([\+\-]|\d\d)/gi, +/** + * Set options + * @param {Object} options + */ +Graph.prototype.setOptions = function (options) { + if (options) { + // retrieve parameter values + if (options.width != undefined) {this.width = options.width;} + if (options.height != undefined) {this.height = options.height;} + if (options.stabilize != undefined) {this.stabilize = options.stabilize;} + if (options.selectable != undefined) {this.selectable = options.selectable;} - // getter and setter names - proxyGettersAndSetters = 'Month|Date|Hours|Minutes|Seconds|Milliseconds'.split('|'), - unitMillisecondFactors = { - 'Milliseconds' : 1, - 'Seconds' : 1e3, - 'Minutes' : 6e4, - 'Hours' : 36e5, - 'Days' : 864e5, - 'Months' : 2592e6, - 'Years' : 31536e6 - }, + // TODO: work out these options and document them + if (options.edges) { + for (var prop in options.edges) { + if (options.edges.hasOwnProperty(prop)) { + this.constants.edges[prop] = options.edges[prop]; + } + } - // format function strings - formatFunctions = {}, + if (options.edges.length != undefined && + options.nodes && options.nodes.distance == undefined) { + this.constants.edges.length = options.edges.length; + this.constants.nodes.distance = options.edges.length * 1.25; + } - // tokens to ordinalize and pad - ordinalizeTokens = 'DDD w W M D d'.split(' '), - paddedTokens = 'M D H h m s w W'.split(' '), + if (!options.edges.fontColor) { + this.constants.edges.fontColor = options.edges.color; + } - formatTokenFunctions = { - M : function () { - return this.month() + 1; - }, - MMM : function (format) { - return this.lang().monthsShort(this, format); - }, - MMMM : function (format) { - return this.lang().months(this, format); - }, - D : function () { - return this.date(); - }, - DDD : function () { - return this.dayOfYear(); - }, - d : function () { - return this.day(); - }, - dd : function (format) { - return this.lang().weekdaysMin(this, format); - }, - ddd : function (format) { - return this.lang().weekdaysShort(this, format); - }, - dddd : function (format) { - return this.lang().weekdays(this, format); - }, - w : function () { - return this.week(); - }, - W : function () { - return this.isoWeek(); - }, - YY : function () { - return leftZeroFill(this.year() % 100, 2); - }, - YYYY : function () { - return leftZeroFill(this.year(), 4); - }, - YYYYY : function () { - return leftZeroFill(this.year(), 5); - }, - a : function () { - return this.lang().meridiem(this.hours(), this.minutes(), true); - }, - A : function () { - return this.lang().meridiem(this.hours(), this.minutes(), false); - }, - H : function () { - return this.hours(); - }, - h : function () { - return this.hours() % 12 || 12; - }, - m : function () { - return this.minutes(); - }, - s : function () { - return this.seconds(); - }, - S : function () { - return ~~(this.milliseconds() / 100); - }, - SS : function () { - return leftZeroFill(~~(this.milliseconds() / 10), 2); - }, - SSS : function () { - return leftZeroFill(this.milliseconds(), 3); - }, - Z : function () { - var a = -this.zone(), - b = "+"; - if (a < 0) { - a = -a; - b = "-"; + // Added to support dashed lines + // David Jordan + // 2012-08-08 + if (options.edges.dash) { + if (options.edges.dash.length != undefined) { + this.constants.edges.dash.length = options.edges.dash.length; } - return b + leftZeroFill(~~(a / 60), 2) + ":" + leftZeroFill(~~a % 60, 2); - }, - ZZ : function () { - var a = -this.zone(), - b = "+"; - if (a < 0) { - a = -a; - b = "-"; + if (options.edges.dash.gap != undefined) { + this.constants.edges.dash.gap = options.edges.dash.gap; + } + if (options.edges.dash.altLength != undefined) { + this.constants.edges.dash.altLength = options.edges.dash.altLength; + } + } + } + + if (options.nodes) { + for (prop in options.nodes) { + if (options.nodes.hasOwnProperty(prop)) { + this.constants.nodes[prop] = options.nodes[prop]; } - return b + leftZeroFill(~~(10 * a / 6), 4); - }, - X : function () { - return this.unix(); } - }; - function padToken(func, count) { - return function (a) { - return leftZeroFill(func.call(this, a), count); - }; - } - function ordinalizeToken(func) { - return function (a) { - return this.lang().ordinal(func.call(this, a)); - }; - } + if (options.nodes.color) { + this.constants.nodes.color = Node.parseColor(options.nodes.color); + } - while (ordinalizeTokens.length) { - i = ordinalizeTokens.pop(); - formatTokenFunctions[i + 'o'] = ordinalizeToken(formatTokenFunctions[i]); - } - while (paddedTokens.length) { - i = paddedTokens.pop(); - formatTokenFunctions[i + i] = padToken(formatTokenFunctions[i], 2); + /* + if (options.nodes.widthMin) this.constants.nodes.radiusMin = options.nodes.widthMin; + if (options.nodes.widthMax) this.constants.nodes.radiusMax = options.nodes.widthMax; + */ + } + + if (options.groups) { + for (var groupname in options.groups) { + if (options.groups.hasOwnProperty(groupname)) { + var group = options.groups[groupname]; + this.groups.add(groupname, group); + } + } + } } - formatTokenFunctions.DDDD = padToken(formatTokenFunctions.DDD, 3); + this.setSize(this.width, this.height); + this._setTranslation(this.frame.clientWidth / 2, this.frame.clientHeight / 2); + this._setScale(1); +}; - /************************************ - Constructors - ************************************/ +/** + * fire an event + * @param {String} event The name of an event, for example "select" + * @param {Object} params Optional object with event parameters + * @private + */ +Graph.prototype._trigger = function (event, params) { + events.trigger(this, event, params); +}; - function Language() { +/** + * Create the main frame for the Graph. + * This function is executed once when a Graph object is created. The frame + * contains a canvas, and this canvas contains all objects like the axis and + * nodes. + * @private + */ +Graph.prototype._create = function () { + // remove all elements from the container element. + while (this.containerElement.hasChildNodes()) { + this.containerElement.removeChild(this.containerElement.firstChild); } - // Moment prototype object - function Moment(config) { - extend(this, config); + this.frame = document.createElement("div"); + this.frame.className = "graph-frame"; + this.frame.style.position = "relative"; + this.frame.style.overflow = "hidden"; + + // create the graph canvas (HTML canvas element) + this.frame.canvas = document.createElement( "canvas" ); + this.frame.canvas.style.position = "relative"; + this.frame.appendChild(this.frame.canvas); + if (!this.frame.canvas.getContext) { + var noCanvas = document.createElement( "DIV" ); + noCanvas.style.color = "red"; + noCanvas.style.fontWeight = "bold" ; + noCanvas.style.padding = "10px"; + noCanvas.innerHTML = "Error: your browser does not support HTML canvas"; + this.frame.canvas.appendChild(noCanvas); } - // Duration Constructor - function Duration(duration) { - var data = this._data = {}, - years = duration.years || duration.year || duration.y || 0, - months = duration.months || duration.month || duration.M || 0, - weeks = duration.weeks || duration.week || duration.w || 0, - days = duration.days || duration.day || duration.d || 0, - hours = duration.hours || duration.hour || duration.h || 0, - minutes = duration.minutes || duration.minute || duration.m || 0, - seconds = duration.seconds || duration.second || duration.s || 0, - milliseconds = duration.milliseconds || duration.millisecond || duration.ms || 0; + var me = this; + this.drag = {}; + this.pinch = {}; + this.hammer = Hammer(this.frame.canvas, { + prevent_default: true + }); + this.hammer.on('tap', me._onTap.bind(me) ); + this.hammer.on('hold', me._onHold.bind(me) ); + this.hammer.on('pinch', me._onPinch.bind(me) ); + this.hammer.on('touch', me._onTouch.bind(me) ); + this.hammer.on('dragstart', me._onDragStart.bind(me) ); + this.hammer.on('drag', me._onDrag.bind(me) ); + this.hammer.on('dragend', me._onDragEnd.bind(me) ); + this.hammer.on('mousewheel',me._onMouseWheel.bind(me) ); + this.hammer.on('mousemove', me._onMouseMoveTitle.bind(me) ); - // representation for dateAddRemove - this._milliseconds = milliseconds + - seconds * 1e3 + // 1000 - minutes * 6e4 + // 1000 * 60 - hours * 36e5; // 1000 * 60 * 60 - // Because of dateAddRemove treats 24 hours as different from a - // day when working around DST, we need to store them separately - this._days = days + - weeks * 7; - // It is impossible translate months into days without knowing - // which months you are are talking about, so we have to store - // it separately. - this._months = months + - years * 12; + // add the frame to the container element + this.containerElement.appendChild(this.frame); +}; + +/** + * + * @param {{x: Number, y: Number}} pointer + * @return {Number | null} node + * @private + */ +Graph.prototype._getNodeAt = function (pointer) { + var x = this._xToCanvas(pointer.x); + var y = this._yToCanvas(pointer.y); + + var obj = { + left: x, + top: y, + right: x, + bottom: y + }; - // The following code bubbles up values, see the tests for - // examples of what that means. - data.milliseconds = milliseconds % 1000; - seconds += absRound(milliseconds / 1000); + // if there are overlapping nodes, select the last one, this is the + // one which is drawn on top of the others + var overlappingNodes = this._getNodesOverlappingWith(obj); + return (overlappingNodes.length > 0) ? + overlappingNodes[overlappingNodes.length - 1] : null; +}; - data.seconds = seconds % 60; - minutes += absRound(seconds / 60); +/** + * Get the pointer location from a touch location + * @param {{pageX: Number, pageY: Number}} touch + * @return {{x: Number, y: Number}} pointer + * @private + */ +Graph.prototype._getPointer = function (touch) { + return { + x: touch.pageX - vis.util.getAbsoluteLeft(this.frame.canvas), + y: touch.pageY - vis.util.getAbsoluteTop(this.frame.canvas) + }; +}; - data.minutes = minutes % 60; - hours += absRound(minutes / 60); +/** + * On start of a touch gesture, store the pointer + * @param event + * @private + */ +Graph.prototype._onTouch = function (event) { + this.drag.pointer = this._getPointer(event.gesture.touches[0]); + this.drag.pinched = false; + this.pinch.scale = this._getScale(); +}; - data.hours = hours % 24; - days += absRound(hours / 24); +/** + * handle drag start event + * @private + */ +Graph.prototype._onDragStart = function (event) { + var drag = this.drag; - days += weeks * 7; - data.days = days % 30; + drag.translation = this._getTranslation(); - months += absRound(days / 30); + // note: drag.pointer is set in _onTouch to get the initial touch location + drag.nodeId = this._getNodeAt(drag.pointer); + drag.node = this.nodes[drag.nodeId]; + if (drag.node) { + this._selectNodes([drag.nodeId]); - data.months = months % 12; - years += absRound(months / 12); + // store original xFixed and yFixed, make the node temporarily Fixed + drag.xFixed = drag.node.xFixed; + drag.yFixed = drag.node.yFixed; + drag.node.xFixed = true; + drag.node.yFixed = true; + } +}; - data.years = years; +/** + * handle drag event + * @private + */ +Graph.prototype._onDrag = function (event) { + if (this.drag.pinched) { + return; } + var pointer = this._getPointer(event.gesture.touches[0]); - /************************************ - Helpers - ************************************/ + var drag= this.drag, + node = drag.node; + if (node) { + if (!drag.xFixed) + node.x = this._xToCanvas(pointer.x); + if (!drag.yFixed) + node.y = this._yToCanvas(pointer.y); - function extend(a, b) { - for (var i in b) { - if (b.hasOwnProperty(i)) { - a[i] = b[i]; - } + // start animation if not yet running + if (!this.moving) { + this.moving = true; + this.start(); } - return a; } + else { + // move the graph + var diffX = pointer.x - this.drag.pointer.x; + var diffY = pointer.y - this.drag.pointer.y; - function absRound(number) { - if (number < 0) { - return Math.ceil(number); - } else { - return Math.floor(number); - } + this._setTranslation( + this.drag.translation.x + diffX, + this.drag.translation.y + diffY); + this._redraw(); + + this.moved = true; } +}; - // left zero fill a number - // see http://jsperf.com/left-zero-filling for performance comparison - function leftZeroFill(number, targetLength) { - var output = number + ''; - while (output.length < targetLength) { - output = '0' + output; - } - return output; +/** + * handle drag start event + * @private + */ +Graph.prototype._onDragEnd = function () { + var drag = this.drag, + node = drag.node; + + if (node) { + // restore orginal xFixed and yFixed + node.xFixed = drag.xFixed; + node.yFixed = drag.yFixed; } +}; - // helper function for _.addTime and _.subtractTime - function addOrSubtractDurationFromMoment(mom, duration, isAdding) { - var ms = duration._milliseconds, - d = duration._days, - M = duration._months, - currentDate; +/** + * handle tap/click event: select/unselect a node + * @private + */ +Graph.prototype._onTap = function (event) { + var pointer = this._getPointer(event.gesture.touches[0]); + + var nodeId = this._getNodeAt(pointer); + var node = this.nodes[nodeId]; + if (node) { + // select this node + this._selectNodes([nodeId]); + + if (!this.moving) { + this._redraw(); + } + } + else { + // remove selection + this._unselectNodes(); + this._redraw(); + } +}; - if (ms) { - mom._d.setTime(+mom + ms * isAdding); +/** + * handle long tap event: multi select nodes + * @private + */ +Graph.prototype._onHold = function (event) { + var pointer = this._getPointer(event.gesture.touches[0]); + var nodeId = this._getNodeAt(pointer); + var node = this.nodes[nodeId]; + if (node) { + if (!node.isSelected()) { + // select this node, keep previous selection + var append = true; + this._selectNodes([nodeId], append); } - if (d) { - mom.date(mom.date() + d * isAdding); + else { + this._unselectNodes([nodeId]); } - if (M) { - currentDate = mom.date(); - mom.date(1) - .month(mom.month() + M * isAdding) - .date(Math.min(currentDate, mom.daysInMonth())); + + if (!this.moving) { + this._redraw(); } } + else { + // Do nothing + } +}; - // check if is an array - function isArray(input) { - return Object.prototype.toString.call(input) === '[object Array]'; +/** + * Handle pinch event + * @param event + * @private + */ +Graph.prototype._onPinch = function (event) { + var pointer = this._getPointer(event.gesture.center); + + this.drag.pinched = true; + if (!('scale' in this.pinch)) { + this.pinch.scale = 1; } - // compare two arrays, return the number of differences - function compareArrays(array1, array2) { - var len = Math.min(array1.length, array2.length), - lengthDiff = Math.abs(array1.length - array2.length), - diffs = 0, - i; - for (i = 0; i < len; i++) { - if (~~array1[i] !== ~~array2[i]) { - diffs++; - } - } - return diffs + lengthDiff; + // TODO: enable moving while pinching? + var scale = this.pinch.scale * event.gesture.scale; + this._zoom(scale, pointer) +}; + +/** + * Zoom the graph in or out + * @param {Number} scale a number around 1, and between 0.01 and 10 + * @param {{x: Number, y: Number}} pointer + * @return {Number} appliedScale scale is limited within the boundaries + * @private + */ +Graph.prototype._zoom = function(scale, pointer) { + var scaleOld = this._getScale(); + if (scale < 0.01) { + scale = 0.01; + } + if (scale > 10) { + scale = 10; } + var translation = this._getTranslation(); + var scaleFrac = scale / scaleOld; + var tx = (1 - scaleFrac) * pointer.x + translation.x * scaleFrac; + var ty = (1 - scaleFrac) * pointer.y + translation.y * scaleFrac; - /************************************ - Languages - ************************************/ + this._setScale(scale); + this._setTranslation(tx, ty); + this._redraw(); + + return scale; +}; + +/** + * Event handler for mouse wheel event, used to zoom the timeline + * See http://adomas.org/javascript-mouse-wheel/ + * https://github.com/EightMedia/hammer.js/issues/256 + * @param {MouseEvent} event + * @private + */ +Graph.prototype._onMouseWheel = function(event) { + // retrieve delta + var delta = 0; + if (event.wheelDelta) { /* IE/Opera. */ + delta = event.wheelDelta/120; + } else if (event.detail) { /* Mozilla case. */ + // In Mozilla, sign of delta is different than in IE. + // Also, delta is multiple of 3. + delta = -event.detail/3; + } + + // If delta is nonzero, handle it. + // Basically, delta is now positive if wheel was scrolled up, + // and negative, if wheel was scrolled down. + if (delta) { + if (!('mouswheelScale' in this.pinch)) { + this.pinch.mouswheelScale = 1; + } + + // calculate the new scale + var scale = this.pinch.mouswheelScale; + var zoom = delta / 10; + if (delta < 0) { + zoom = zoom / (1 - zoom); + } + scale *= (1 + zoom); + // calculate the pointer location + var gesture = Hammer.event.collectEventData(this, 'scroll', event); + var pointer = this._getPointer(gesture.center); - Language.prototype = { - set : function (config) { - var prop, i; - for (i in config) { - prop = config[i]; - if (typeof prop === 'function') { - this[i] = prop; - } else { - this['_' + i] = prop; - } - } - }, + // apply the new scale + scale = this._zoom(scale, pointer); - _months : "January_February_March_April_May_June_July_August_September_October_November_December".split("_"), - months : function (m) { - return this._months[m.month()]; - }, + // store the new, applied scale + this.pinch.mouswheelScale = scale; + } - _monthsShort : "Jan_Feb_Mar_Apr_May_Jun_Jul_Aug_Sep_Oct_Nov_Dec".split("_"), - monthsShort : function (m) { - return this._monthsShort[m.month()]; - }, + // Prevent default actions caused by mouse wheel. + event.preventDefault(); +}; - monthsParse : function (monthName) { - var i, mom, regex, output; - if (!this._monthsParse) { - this._monthsParse = []; - } +/** + * Mouse move handler for checking whether the title moves over a node with a title. + * @param {Event} event + * @private + */ +Graph.prototype._onMouseMoveTitle = function (event) { + var gesture = Hammer.event.collectEventData(this, 'mousemove', event); + var pointer = this._getPointer(gesture.center); - for (i = 0; i < 12; i++) { - // make the regex if we don't have it already - if (!this._monthsParse[i]) { - mom = moment([2000, i]); - regex = '^' + this.months(mom, '') + '|^' + this.monthsShort(mom, ''); - this._monthsParse[i] = new RegExp(regex.replace('.', ''), 'i'); - } - // test the regex - if (this._monthsParse[i].test(monthName)) { - return i; - } - } - }, + // check if the previously selected node is still selected + if (this.popupNode) { + this._checkHidePopup(pointer); + } - _weekdays : "Sunday_Monday_Tuesday_Wednesday_Thursday_Friday_Saturday".split("_"), - weekdays : function (m) { - return this._weekdays[m.day()]; - }, + // start a timeout that will check if the mouse is positioned above + // an element + var me = this; + var checkShow = function() { + me._checkShowPopup(pointer); + }; + if (this.popupTimer) { + clearInterval(this.popupTimer); // stop any running timer + } + if (!this.leftButtonDown) { + this.popupTimer = setTimeout(checkShow, 300); + } +}; - _weekdaysShort : "Sun_Mon_Tue_Wed_Thu_Fri_Sat".split("_"), - weekdaysShort : function (m) { - return this._weekdaysShort[m.day()]; - }, +/** + * Check if there is an element on the given position in the graph + * (a node or edge). If so, and if this element has a title, + * show a popup window with its title. + * + * @param {{x:Number, y:Number}} pointer + * @private + */ +Graph.prototype._checkShowPopup = function (pointer) { + var obj = { + left: this._xToCanvas(pointer.x), + top: this._yToCanvas(pointer.y), + right: this._xToCanvas(pointer.x), + bottom: this._yToCanvas(pointer.y) + }; - _weekdaysMin : "Su_Mo_Tu_We_Th_Fr_Sa".split("_"), - weekdaysMin : function (m) { - return this._weekdaysMin[m.day()]; - }, + var id; + var lastPopupNode = this.popupNode; - _longDateFormat : { - LT : "h:mm A", - L : "MM/DD/YYYY", - LL : "MMMM D YYYY", - LLL : "MMMM D YYYY LT", - LLLL : "dddd, MMMM D YYYY LT" - }, - longDateFormat : function (key) { - var output = this._longDateFormat[key]; - if (!output && this._longDateFormat[key.toUpperCase()]) { - output = this._longDateFormat[key.toUpperCase()].replace(/MMMM|MM|DD|dddd/g, function (val) { - return val.slice(1); - }); - this._longDateFormat[key] = output; + if (this.popupNode == undefined) { + // search the nodes for overlap, select the top one in case of multiple nodes + var nodes = this.nodes; + for (id in nodes) { + if (nodes.hasOwnProperty(id)) { + var node = nodes[id]; + if (node.getTitle() != undefined && node.isOverlappingWith(obj)) { + this.popupNode = node; + break; + } } - return output; - }, + } + } - meridiem : function (hours, minutes, isLower) { - if (hours > 11) { - return isLower ? 'pm' : 'PM'; - } else { - return isLower ? 'am' : 'AM'; + if (this.popupNode == undefined) { + // search the edges for overlap + var edges = this.edges; + for (id in edges) { + if (edges.hasOwnProperty(id)) { + var edge = edges[id]; + if (edge.connected && (edge.getTitle() != undefined) && + edge.isOverlappingWith(obj)) { + this.popupNode = edge; + break; + } } - }, + } + } - _calendar : { - sameDay : '[Today at] LT', - nextDay : '[Tomorrow at] LT', - nextWeek : 'dddd [at] LT', - lastDay : '[Yesterday at] LT', - lastWeek : '[last] dddd [at] LT', - sameElse : 'L' - }, - calendar : function (key, mom) { - var output = this._calendar[key]; - return typeof output === 'function' ? output.apply(mom) : output; - }, + if (this.popupNode) { + // show popup message window + if (this.popupNode != lastPopupNode) { + var me = this; + if (!me.popup) { + me.popup = new Popup(me.frame); + } - _relativeTime : { - future : "in %s", - past : "%s ago", - s : "a few seconds", - m : "a minute", - mm : "%d minutes", - h : "an hour", - hh : "%d hours", - d : "a day", - dd : "%d days", - M : "a month", - MM : "%d months", - y : "a year", - yy : "%d years" - }, - relativeTime : function (number, withoutSuffix, string, isFuture) { - var output = this._relativeTime[string]; - return (typeof output === 'function') ? - output(number, withoutSuffix, string, isFuture) : - output.replace(/%d/i, number); - }, - pastFuture : function (diff, output) { - var format = this._relativeTime[diff > 0 ? 'future' : 'past']; - return typeof format === 'function' ? format(output) : format.replace(/%s/i, output); - }, + // adjust a small offset such that the mouse cursor is located in the + // bottom left location of the popup, and you can easily move over the + // popup area + me.popup.setPosition(pointer.x - 3, pointer.y - 3); + me.popup.setText(me.popupNode.getTitle()); + me.popup.show(); + } + } + else { + if (this.popup) { + this.popup.hide(); + } + } +}; - ordinal : function (number) { - return this._ordinal.replace("%d", number); - }, - _ordinal : "%d", +/** + * Check if the popup must be hided, which is the case when the mouse is no + * longer hovering on the object + * @param {{x:Number, y:Number}} pointer + * @private + */ +Graph.prototype._checkHidePopup = function (pointer) { + if (!this.popupNode || !this._getNodeAt(pointer) ) { + this.popupNode = undefined; + if (this.popup) { + this.popup.hide(); + } + } +}; - preparse : function (string) { - return string; - }, +/** + * Unselect selected nodes. If no selection array is provided, all nodes + * are unselected + * @param {Object[]} selection Array with selection objects, each selection + * object has a parameter row. Optional + * @param {Boolean} triggerSelect If true (default), the select event + * is triggered when nodes are unselected + * @return {Boolean} changed True if the selection is changed + * @private + */ +Graph.prototype._unselectNodes = function(selection, triggerSelect) { + var changed = false; + var i, iMax, id; - postformat : function (string) { - return string; - }, + if (selection) { + // remove provided selections + for (i = 0, iMax = selection.length; i < iMax; i++) { + id = selection[i]; + this.nodes[id].unselect(); - week : function (mom) { - return weekOfYear(mom, this._week.dow, this._week.doy); - }, - _week : { - dow : 0, // Sunday is the first day of the week. - doy : 6 // The week that contains Jan 1st is the first week of the year. + var j = 0; + while (j < this.selection.length) { + if (this.selection[j] == id) { + this.selection.splice(j, 1); + changed = true; + } + else { + j++; + } + } } - }; - - // Loads a language definition into the `languages` cache. The function - // takes a key and optionally values. If not in the browser and no values - // are provided, it will load the language file module. As a convenience, - // this function also returns the language values. - function loadLang(key, values) { - values.abbr = key; - if (!languages[key]) { - languages[key] = new Language(); + } + else if (this.selection && this.selection.length) { + // remove all selections + for (i = 0, iMax = this.selection.length; i < iMax; i++) { + id = this.selection[i]; + this.nodes[id].unselect(); + changed = true; } - languages[key].set(values); - return languages[key]; + this.selection = []; } - // Determines which language definition to use and returns it. - // - // With no parameters, it will return the global language. If you - // pass in a language key, such as 'en', it will return the - // definition for 'en', so long as 'en' has already been loaded using - // moment.lang. - function getLangDefinition(key) { - if (!key) { - return moment.fn._lang; - } - if (!languages[key] && hasModule) { - require('./lang/' + key); - } - return languages[key]; + if (changed && (triggerSelect == true || triggerSelect == undefined)) { + // fire the select event + this._trigger('select'); } + return changed; +}; - /************************************ - Formatting - ************************************/ +/** + * select all nodes on given location x, y + * @param {Array} selection an array with node ids + * @param {boolean} append If true, the new selection will be appended to the + * current selection (except for duplicate entries) + * @return {Boolean} changed True if the selection is changed + * @private + */ +Graph.prototype._selectNodes = function(selection, append) { + var changed = false; + var i, iMax; + // TODO: the selectNodes method is a little messy, rework this - function removeFormattingTokens(input) { - if (input.match(/\[.*\]/)) { - return input.replace(/^\[|\]$/g, ""); - } - return input.replace(/\\/g, ""); + // check if the current selection equals the desired selection + var selectionAlreadyThere = true; + if (selection.length != this.selection.length) { + selectionAlreadyThere = false; } - - function makeFormatFunction(format) { - var array = format.match(formattingTokens), i, length; - - for (i = 0, length = array.length; i < length; i++) { - if (formatTokenFunctions[array[i]]) { - array[i] = formatTokenFunctions[array[i]]; - } else { - array[i] = removeFormattingTokens(array[i]); + else { + for (i = 0, iMax = Math.min(selection.length, this.selection.length); i < iMax; i++) { + if (selection[i] != this.selection[i]) { + selectionAlreadyThere = false; + break; } } - - return function (mom) { - var output = ""; - for (i = 0; i < length; i++) { - output += typeof array[i].call === 'function' ? array[i].call(mom, format) : array[i]; - } - return output; - }; + } + if (selectionAlreadyThere) { + return changed; } - // format date using native date object - function formatMoment(m, format) { - var i = 5; - - function replaceLongDateFormatTokens(input) { - return m.lang().longDateFormat(input) || input; - } - - while (i-- && localFormattingTokens.test(format)) { - format = format.replace(localFormattingTokens, replaceLongDateFormatTokens); - } + if (append == undefined || append == false) { + // first deselect any selected node + var triggerSelect = false; + changed = this._unselectNodes(undefined, triggerSelect); + } - if (!formatFunctions[format]) { - formatFunctions[format] = makeFormatFunction(format); + for (i = 0, iMax = selection.length; i < iMax; i++) { + // add each of the new selections, but only when they are not duplicate + var id = selection[i]; + var isDuplicate = (this.selection.indexOf(id) != -1); + if (!isDuplicate) { + this.nodes[id].select(); + this.selection.push(id); + changed = true; } - - return formatFunctions[format](m); } - - /************************************ - Parsing - ************************************/ - - - // get the regex to find the next token - function getParseRegexForToken(token) { - switch (token) { - case 'DDDD': - return parseTokenThreeDigits; - case 'YYYY': - return parseTokenFourDigits; - case 'YYYYY': - return parseTokenSixDigits; - case 'S': - case 'SS': - case 'SSS': - case 'DDD': - return parseTokenOneToThreeDigits; - case 'MMM': - case 'MMMM': - case 'dd': - case 'ddd': - case 'dddd': - case 'a': - case 'A': - return parseTokenWord; - case 'X': - return parseTokenTimestampMs; - case 'Z': - case 'ZZ': - return parseTokenTimezone; - case 'T': - return parseTokenT; - case 'MM': - case 'DD': - case 'YY': - case 'HH': - case 'hh': - case 'mm': - case 'ss': - case 'M': - case 'D': - case 'd': - case 'H': - case 'h': - case 'm': - case 's': - return parseTokenOneOrTwoDigits; - default : - return new RegExp(token.replace('\\', '')); - } + if (changed) { + // fire the select event + this._trigger('select'); } - // function to convert string input to date - function addTimeToArrayFromToken(token, input, config) { - var a, b, - datePartArray = config._a; + return changed; +}; - switch (token) { - // MONTH - case 'M' : // fall through to MM - case 'MM' : - datePartArray[1] = (input == null) ? 0 : ~~input - 1; - break; - case 'MMM' : // fall through to MMMM - case 'MMMM' : - a = getLangDefinition(config._l).monthsParse(input); - // if we didn't find a month name, mark the date as invalid. - if (a != null) { - datePartArray[1] = a; - } else { - config._isValid = false; - } - break; - // DAY OF MONTH - case 'D' : // fall through to DDDD - case 'DD' : // fall through to DDDD - case 'DDD' : // fall through to DDDD - case 'DDDD' : - if (input != null) { - datePartArray[2] = ~~input; - } - break; - // YEAR - case 'YY' : - datePartArray[0] = ~~input + (~~input > 68 ? 1900 : 2000); - break; - case 'YYYY' : - case 'YYYYY' : - datePartArray[0] = ~~input; - break; - // AM / PM - case 'a' : // fall through to A - case 'A' : - config._isPm = ((input + '').toLowerCase() === 'pm'); - break; - // 24 HOUR - case 'H' : // fall through to hh - case 'HH' : // fall through to hh - case 'h' : // fall through to hh - case 'hh' : - datePartArray[3] = ~~input; - break; - // MINUTE - case 'm' : // fall through to mm - case 'mm' : - datePartArray[4] = ~~input; - break; - // SECOND - case 's' : // fall through to ss - case 'ss' : - datePartArray[5] = ~~input; - break; - // MILLISECOND - case 'S' : - case 'SS' : - case 'SSS' : - datePartArray[6] = ~~ (('0.' + input) * 1000); - break; - // UNIX TIMESTAMP WITH MS - case 'X': - config._d = new Date(parseFloat(input) * 1000); - break; - // TIMEZONE - case 'Z' : // fall through to ZZ - case 'ZZ' : - config._useUTC = true; - a = (input + '').match(parseTimezoneChunker); - if (a && a[1]) { - config._tzh = ~~a[1]; - } - if (a && a[2]) { - config._tzm = ~~a[2]; - } - // reverse offsets - if (a && a[0] === '+') { - config._tzh = -config._tzh; - config._tzm = -config._tzm; - } - break; - } +/** + * retrieve all nodes overlapping with given object + * @param {Object} obj An object with parameters left, top, right, bottom + * @return {Number[]} An array with id's of the overlapping nodes + * @private + */ +Graph.prototype._getNodesOverlappingWith = function (obj) { + var nodes = this.nodes, + overlappingNodes = []; - // if the input is null, the date is not valid - if (input == null) { - config._isValid = false; + for (var id in nodes) { + if (nodes.hasOwnProperty(id)) { + if (nodes[id].isOverlappingWith(obj)) { + overlappingNodes.push(id); + } } } - // convert an array to a date. - // the array should mirror the parameters below - // note: all values past the year are optional and will default to the lowest possible value. - // [year, month, day , hour, minute, second, millisecond] - function dateFromArray(config) { - var i, date, input = []; + return overlappingNodes; +}; + +/** + * retrieve the currently selected nodes + * @return {Number[] | String[]} selection An array with the ids of the + * selected nodes. + */ +Graph.prototype.getSelection = function() { + return this.selection.concat([]); +}; - if (config._d) { - return; - } +/** + * select zero or more nodes + * @param {Number[] | String[]} selection An array with the ids of the + * selected nodes. + */ +Graph.prototype.setSelection = function(selection) { + var i, iMax, id; - for (i = 0; i < 7; i++) { - config._a[i] = input[i] = (config._a[i] == null) ? (i === 2 ? 1 : 0) : config._a[i]; - } + if (!selection || (selection.length == undefined)) + throw "Selection must be an array with ids"; - // add the offsets to the time to be parsed so that we can have a clean array for checking isValid - input[3] += config._tzh || 0; - input[4] += config._tzm || 0; + // first unselect any selected node + for (i = 0, iMax = this.selection.length; i < iMax; i++) { + id = this.selection[i]; + this.nodes[id].unselect(); + } - date = new Date(0); + this.selection = []; - if (config._useUTC) { - date.setUTCFullYear(input[0], input[1], input[2]); - date.setUTCHours(input[3], input[4], input[5], input[6]); - } else { - date.setFullYear(input[0], input[1], input[2]); - date.setHours(input[3], input[4], input[5], input[6]); - } + for (i = 0, iMax = selection.length; i < iMax; i++) { + id = selection[i]; - config._d = date; + var node = this.nodes[id]; + if (!node) { + throw new RangeError('Node with id "' + id + '" not found'); + } + node.select(); + this.selection.push(id); } - // date from string and format string - function makeDateFromStringAndFormat(config) { - // This array is used to make a Date, either with `new Date` or `Date.UTC` - var tokens = config._f.match(formattingTokens), - string = config._i, - i, parsedInput; - - config._a = []; + this.redraw(); +}; - for (i = 0; i < tokens.length; i++) { - parsedInput = (getParseRegexForToken(tokens[i]).exec(string) || [])[0]; - if (parsedInput) { - string = string.slice(string.indexOf(parsedInput) + parsedInput.length); - } - // don't parse if its not a known token - if (formatTokenFunctions[tokens[i]]) { - addTimeToArrayFromToken(tokens[i], parsedInput, config); - } - } - // handle am pm - if (config._isPm && config._a[3] < 12) { - config._a[3] += 12; +/** + * Validate the selection: remove ids of nodes which no longer exist + * @private + */ +Graph.prototype._updateSelection = function () { + var i = 0; + while (i < this.selection.length) { + var id = this.selection[i]; + if (!this.nodes[id]) { + this.selection.splice(i, 1); } - // if is 12 am, change hours to 0 - if (config._isPm === false && config._a[3] === 12) { - config._a[3] = 0; + else { + i++; } - // return - dateFromArray(config); } +}; - // date from string and array of format strings - function makeDateFromStringAndArray(config) { - var tempConfig, - tempMoment, - bestMoment, +/** + * Temporary method to test calculating a hub value for the nodes + * @param {number} level Maximum number edges between two nodes in order + * to call them connected. Optional, 1 by default + * @return {Number[]} connectioncount array with the connection count + * for each node + * @private + */ +Graph.prototype._getConnectionCount = function(level) { + if (level == undefined) { + level = 1; + } - scoreToBeat = 99, - i, - currentDate, - currentScore; + // get the nodes connected to given nodes + function getConnectedNodes(nodes) { + var connectedNodes = []; - while (config._f.length) { - tempConfig = extend({}, config); - tempConfig._f = config._f.pop(); - makeDateFromStringAndFormat(tempConfig); - tempMoment = new Moment(tempConfig); + for (var j = 0, jMax = nodes.length; j < jMax; j++) { + var node = nodes[j]; - if (tempMoment.isValid()) { - bestMoment = tempMoment; - break; - } + // find all nodes connected to this node + var edges = node.edges; + for (var i = 0, iMax = edges.length; i < iMax; i++) { + var edge = edges[i]; + var other = null; - currentScore = compareArrays(tempConfig._a, tempMoment.toArray()); + // check if connected + if (edge.from == node) + other = edge.to; + else if (edge.to == node) + other = edge.from; - if (currentScore < scoreToBeat) { - scoreToBeat = currentScore; - bestMoment = tempMoment; + // check if the other node is not already in the list with nodes + var k, kMax; + if (other) { + for (k = 0, kMax = nodes.length; k < kMax; k++) { + if (nodes[k] == other) { + other = null; + break; + } + } + } + if (other) { + for (k = 0, kMax = connectedNodes.length; k < kMax; k++) { + if (connectedNodes[k] == other) { + other = null; + break; + } + } + } + + if (other) + connectedNodes.push(other); } } - extend(config, bestMoment); + return connectedNodes; } - // date from iso format - function makeDateFromString(config) { - var i, - string = config._i; - if (isoRegex.exec(string)) { - config._f = 'YYYY-MM-DDT'; - for (i = 0; i < 4; i++) { - if (isoTimes[i][1].exec(string)) { - config._f += isoTimes[i][0]; - break; - } - } - if (parseTokenTimezone.exec(string)) { - config._f += " Z"; + var connections = []; + var nodes = this.nodes; + for (var id in nodes) { + if (nodes.hasOwnProperty(id)) { + var c = [nodes[id]]; + for (var l = 0; l < level; l++) { + c = c.concat(getConnectedNodes(c)); } - makeDateFromStringAndFormat(config); - } else { - config._d = new Date(string); + connections.push(c); } } - function makeDateFromInput(config) { - var input = config._i, - matched = aspNetJsonRegex.exec(input); - - if (input === undefined) { - config._d = new Date(); - } else if (matched) { - config._d = new Date(+matched[1]); - } else if (typeof input === 'string') { - makeDateFromString(config); - } else if (isArray(input)) { - config._a = input.slice(0); - dateFromArray(config); - } else { - config._d = input instanceof Date ? new Date(+input) : new Date(input); - } + var hubs = []; + for (var i = 0, len = connections.length; i < len; i++) { + hubs.push(connections[i].length); } + return hubs; +}; - /************************************ - Relative Time - ************************************/ - - - // helper function for moment.fn.from, moment.fn.fromNow, and moment.duration.fn.humanize - function substituteTimeAgo(string, number, withoutSuffix, isFuture, lang) { - return lang.relativeTime(number || 1, !!withoutSuffix, string, isFuture); - } - function relativeTime(milliseconds, withoutSuffix, lang) { - var seconds = round(Math.abs(milliseconds) / 1000), - minutes = round(seconds / 60), - hours = round(minutes / 60), - days = round(hours / 24), - years = round(days / 365), - args = seconds < 45 && ['s', seconds] || - minutes === 1 && ['m'] || - minutes < 45 && ['mm', minutes] || - hours === 1 && ['h'] || - hours < 22 && ['hh', hours] || - days === 1 && ['d'] || - days <= 25 && ['dd', days] || - days <= 45 && ['M'] || - days < 345 && ['MM', round(days / 30)] || - years === 1 && ['y'] || ['yy', years]; - args[2] = withoutSuffix; - args[3] = milliseconds > 0; - args[4] = lang; - return substituteTimeAgo.apply({}, args); - } +/** + * Set a new size for the graph + * @param {string} width Width in pixels or percentage (for example "800px" + * or "50%") + * @param {string} height Height in pixels or percentage (for example "400px" + * or "30%") + */ +Graph.prototype.setSize = function(width, height) { + this.frame.style.width = width; + this.frame.style.height = height; + this.frame.canvas.style.width = "100%"; + this.frame.canvas.style.height = "100%"; - /************************************ - Week of Year - ************************************/ + this.frame.canvas.width = this.frame.canvas.clientWidth; + this.frame.canvas.height = this.frame.canvas.clientHeight; +}; +/** + * Set a data set with nodes for the graph + * @param {Array | DataSet | DataView} nodes The data containing the nodes. + * @private + */ +Graph.prototype._setNodes = function(nodes) { + var oldNodesData = this.nodesData; - // firstDayOfWeek 0 = sun, 6 = sat - // the day of the week that starts the week - // (usually sunday or monday) - // firstDayOfWeekOfYear 0 = sun, 6 = sat - // the first week is the week that contains the first - // of this day of the week - // (eg. ISO weeks use thursday (4)) - function weekOfYear(mom, firstDayOfWeek, firstDayOfWeekOfYear) { - var end = firstDayOfWeekOfYear - firstDayOfWeek, - daysToDayOfWeek = firstDayOfWeekOfYear - mom.day(); + if (nodes instanceof DataSet || nodes instanceof DataView) { + this.nodesData = nodes; + } + else if (nodes instanceof Array) { + this.nodesData = new DataSet(); + this.nodesData.add(nodes); + } + else if (!nodes) { + this.nodesData = new DataSet(); + } + else { + throw new TypeError('Array or DataSet expected'); + } + if (oldNodesData) { + // unsubscribe from old dataset + util.forEach(this.nodesListeners, function (callback, event) { + oldNodesData.unsubscribe(event, callback); + }); + } - if (daysToDayOfWeek > end) { - daysToDayOfWeek -= 7; - } + // remove drawn nodes + this.nodes = {}; - if (daysToDayOfWeek < end - 7) { - daysToDayOfWeek += 7; - } + if (this.nodesData) { + // subscribe to new dataset + var me = this; + util.forEach(this.nodesListeners, function (callback, event) { + me.nodesData.subscribe(event, callback); + }); - return Math.ceil(moment(mom).add('d', daysToDayOfWeek).dayOfYear() / 7); + // draw all new nodes + var ids = this.nodesData.getIds(); + this._addNodes(ids); } + this._updateSelection(); +}; - /************************************ - Top Level Functions - ************************************/ +/** + * Add nodes + * @param {Number[] | String[]} ids + * @private + */ +Graph.prototype._addNodes = function(ids) { + var id; + for (var i = 0, len = ids.length; i < len; i++) { + id = ids[i]; + var data = this.nodesData.get(id); + var node = new Node(data, this.images, this.groups, this.constants); + this.nodes[id] = node; // note: this may replace an existing node - function makeMoment(config) { - var input = config._i, - format = config._f; + if (!node.isFixed()) { + // TODO: position new nodes in a smarter way! + var radius = this.constants.edges.length * 2; + var count = ids.length; + var angle = 2 * Math.PI * (i / count); + node.x = radius * Math.cos(angle); + node.y = radius * Math.sin(angle); - if (input === null || input === '') { - return null; + // note: no not use node.isMoving() here, as that gives the current + // velocity of the node, which is zero after creation of the node. + this.moving = true; } + } - if (typeof input === 'string') { - config._i = input = getLangDefinition().preparse(input); + this._reconnectEdges(); + this._updateValueRange(this.nodes); +}; + +/** + * Update existing nodes, or create them when not yet existing + * @param {Number[] | String[]} ids + * @private + */ +Graph.prototype._updateNodes = function(ids) { + var nodes = this.nodes, + nodesData = this.nodesData; + for (var i = 0, len = ids.length; i < len; i++) { + var id = ids[i]; + var node = nodes[id]; + var data = nodesData.get(id); + if (node) { + // update node + node.setProperties(data, this.constants); } + else { + // create node + node = new Node(properties, this.images, this.groups, this.constants); + nodes[id] = node; - if (moment.isMoment(input)) { - config = extend({}, input); - config._d = new Date(+input._d); - } else if (format) { - if (isArray(format)) { - makeDateFromStringAndArray(config); - } else { - makeDateFromStringAndFormat(config); + if (!node.isFixed()) { + this.moving = true; } - } else { - makeDateFromInput(config); } - - return new Moment(config); } - moment = function (input, format, lang) { - return makeMoment({ - _i : input, - _f : format, - _l : lang, - _isUTC : false - }); - }; - - // creating with utc - moment.utc = function (input, format, lang) { - return makeMoment({ - _useUTC : true, - _isUTC : true, - _l : lang, - _i : input, - _f : format - }); - }; + this._reconnectEdges(); + this._updateValueRange(nodes); +}; - // creating with unix timestamp (in seconds) - moment.unix = function (input) { - return moment(input * 1000); - }; +/** + * Remove existing nodes. If nodes do not exist, the method will just ignore it. + * @param {Number[] | String[]} ids + * @private + */ +Graph.prototype._removeNodes = function(ids) { + var nodes = this.nodes; + for (var i = 0, len = ids.length; i < len; i++) { + var id = ids[i]; + delete nodes[id]; + } - // duration - moment.duration = function (input, key) { - var isDuration = moment.isDuration(input), - isNumber = (typeof input === 'number'), - duration = (isDuration ? input._data : (isNumber ? {} : input)), - ret; + this._reconnectEdges(); + this._updateSelection(); + this._updateValueRange(nodes); +}; - if (isNumber) { - if (key) { - duration[key] = input; - } else { - duration.milliseconds = input; - } - } +/** + * Load edges by reading the data table + * @param {Array | DataSet | DataView} edges The data containing the edges. + * @private + * @private + */ +Graph.prototype._setEdges = function(edges) { + var oldEdgesData = this.edgesData; - ret = new Duration(duration); + if (edges instanceof DataSet || edges instanceof DataView) { + this.edgesData = edges; + } + else if (edges instanceof Array) { + this.edgesData = new DataSet(); + this.edgesData.add(edges); + } + else if (!edges) { + this.edgesData = new DataSet(); + } + else { + throw new TypeError('Array or DataSet expected'); + } - if (isDuration && input.hasOwnProperty('_lang')) { - ret._lang = input._lang; - } + if (oldEdgesData) { + // unsubscribe from old dataset + util.forEach(this.edgesListeners, function (callback, event) { + oldEdgesData.unsubscribe(event, callback); + }); + } - return ret; - }; + // remove drawn edges + this.edges = {}; - // version number - moment.version = VERSION; + if (this.edgesData) { + // subscribe to new dataset + var me = this; + util.forEach(this.edgesListeners, function (callback, event) { + me.edgesData.subscribe(event, callback); + }); - // default format - moment.defaultFormat = isoFormat; + // draw all new nodes + var ids = this.edgesData.getIds(); + this._addEdges(ids); + } - // This function will load languages and then set the global language. If - // no arguments are passed in, it will simply return the current global - // language key. - moment.lang = function (key, values) { - var i; + this._reconnectEdges(); +}; - if (!key) { - return moment.fn._lang._abbr; - } - if (values) { - loadLang(key, values); - } else if (!languages[key]) { - getLangDefinition(key); - } - moment.duration.fn._lang = moment.fn._lang = getLangDefinition(key); - }; +/** + * Add edges + * @param {Number[] | String[]} ids + * @private + */ +Graph.prototype._addEdges = function (ids) { + var edges = this.edges, + edgesData = this.edgesData; + for (var i = 0, len = ids.length; i < len; i++) { + var id = ids[i]; - // returns language data - moment.langData = function (key) { - if (key && key._lang && key._lang._abbr) { - key = key._lang._abbr; + var oldEdge = edges[id]; + if (oldEdge) { + oldEdge.disconnect(); } - return getLangDefinition(key); - }; - - // compare moment object - moment.isMoment = function (obj) { - return obj instanceof Moment; - }; - - // for typechecking Duration objects - moment.isDuration = function (obj) { - return obj instanceof Duration; - }; + var data = edgesData.get(id); + edges[id] = new Edge(data, this, this.constants); + } - /************************************ - Moment Prototype - ************************************/ + this.moving = true; + this._updateValueRange(edges); +}; +/** + * Update existing edges, or create them when not yet existing + * @param {Number[] | String[]} ids + * @private + */ +Graph.prototype._updateEdges = function (ids) { + var edges = this.edges, + edgesData = this.edgesData; + for (var i = 0, len = ids.length; i < len; i++) { + var id = ids[i]; - moment.fn = Moment.prototype = { + var data = edgesData.get(id); + var edge = edges[id]; + if (edge) { + // update edge + edge.disconnect(); + edge.setProperties(data, this.constants); + edge.connect(); + } + else { + // create edge + edge = new Edge(data, this, this.constants); + this.edges[id] = edge; + } + } - clone : function () { - return moment(this); - }, + this.moving = true; + this._updateValueRange(edges); +}; - valueOf : function () { - return +this._d; - }, +/** + * Remove existing edges. Non existing ids will be ignored + * @param {Number[] | String[]} ids + * @private + */ +Graph.prototype._removeEdges = function (ids) { + var edges = this.edges; + for (var i = 0, len = ids.length; i < len; i++) { + var id = ids[i]; + var edge = edges[id]; + if (edge) { + edge.disconnect(); + delete edges[id]; + } + } - unix : function () { - return Math.floor(+this._d / 1000); - }, + this.moving = true; + this._updateValueRange(edges); +}; - toString : function () { - return this.format("ddd MMM DD YYYY HH:mm:ss [GMT]ZZ"); - }, +/** + * Reconnect all edges + * @private + */ +Graph.prototype._reconnectEdges = function() { + var id, + nodes = this.nodes, + edges = this.edges; + for (id in nodes) { + if (nodes.hasOwnProperty(id)) { + nodes[id].edges = []; + } + } - toDate : function () { - return this._d; - }, + for (id in edges) { + if (edges.hasOwnProperty(id)) { + var edge = edges[id]; + edge.from = null; + edge.to = null; + edge.connect(); + } + } +}; - toJSON : function () { - return moment.utc(this).format('YYYY-MM-DD[T]HH:mm:ss.SSS[Z]'); - }, +/** + * Update the values of all object in the given array according to the current + * value range of the objects in the array. + * @param {Object} obj An object containing a set of Edges or Nodes + * The objects must have a method getValue() and + * setValueRange(min, max). + * @private + */ +Graph.prototype._updateValueRange = function(obj) { + var id; - toArray : function () { - var m = this; - return [ - m.year(), - m.month(), - m.date(), - m.hours(), - m.minutes(), - m.seconds(), - m.milliseconds() - ]; - }, + // determine the range of the objects + var valueMin = undefined; + var valueMax = undefined; + for (id in obj) { + if (obj.hasOwnProperty(id)) { + var value = obj[id].getValue(); + if (value !== undefined) { + valueMin = (valueMin === undefined) ? value : Math.min(value, valueMin); + valueMax = (valueMax === undefined) ? value : Math.max(value, valueMax); + } + } + } - isValid : function () { - if (this._isValid == null) { - if (this._a) { - this._isValid = !compareArrays(this._a, (this._isUTC ? moment.utc(this._a) : moment(this._a)).toArray()); - } else { - this._isValid = !isNaN(this._d.getTime()); - } + // adjust the range of all objects + if (valueMin !== undefined && valueMax !== undefined) { + for (id in obj) { + if (obj.hasOwnProperty(id)) { + obj[id].setValueRange(valueMin, valueMax); } - return !!this._isValid; - }, + } + } +}; - utc : function () { - this._isUTC = true; - return this; - }, +/** + * Redraw the graph with the current data + * chart will be resized too. + */ +Graph.prototype.redraw = function() { + this.setSize(this.width, this.height); - local : function () { - this._isUTC = false; - return this; - }, + this._redraw(); +}; - format : function (inputString) { - var output = formatMoment(this, inputString || moment.defaultFormat); - return this.lang().postformat(output); - }, +/** + * Redraw the graph with the current data + * @private + */ +Graph.prototype._redraw = function() { + var ctx = this.frame.canvas.getContext("2d"); - add : function (input, val) { - var dur; - // switch args to support add('s', 1) and add(1, 's') - if (typeof input === 'string') { - dur = moment.duration(+val, input); - } else { - dur = moment.duration(input, val); - } - addOrSubtractDurationFromMoment(this, dur, 1); - return this; - }, + // clear the canvas + var w = this.frame.canvas.width; + var h = this.frame.canvas.height; + ctx.clearRect(0, 0, w, h); - subtract : function (input, val) { - var dur; - // switch args to support subtract('s', 1) and subtract(1, 's') - if (typeof input === 'string') { - dur = moment.duration(+val, input); - } else { - dur = moment.duration(input, val); - } - addOrSubtractDurationFromMoment(this, dur, -1); - return this; - }, + // set scaling and translation + ctx.save(); + ctx.translate(this.translation.x, this.translation.y); + ctx.scale(this.scale, this.scale); - diff : function (input, units, asFloat) { - var that = this._isUTC ? moment(input).utc() : moment(input).local(), - zoneDiff = (this.zone() - that.zone()) * 6e4, - diff, output; + this._drawEdges(ctx); + this._drawNodes(ctx); - if (units) { - // standardize on singular form - units = units.replace(/s$/, ''); - } + // restore original scaling and translation + ctx.restore(); +}; - if (units === 'year' || units === 'month') { - diff = (this.daysInMonth() + that.daysInMonth()) * 432e5; // 24 * 60 * 60 * 1000 / 2 - output = ((this.year() - that.year()) * 12) + (this.month() - that.month()); - output += ((this - moment(this).startOf('month')) - (that - moment(that).startOf('month'))) / diff; - if (units === 'year') { - output = output / 12; - } - } else { - diff = (this - that) - zoneDiff; - output = units === 'second' ? diff / 1e3 : // 1000 - units === 'minute' ? diff / 6e4 : // 1000 * 60 - units === 'hour' ? diff / 36e5 : // 1000 * 60 * 60 - units === 'day' ? diff / 864e5 : // 1000 * 60 * 60 * 24 - units === 'week' ? diff / 6048e5 : // 1000 * 60 * 60 * 24 * 7 - diff; - } - return asFloat ? output : absRound(output); - }, +/** + * Set the translation of the graph + * @param {Number} offsetX Horizontal offset + * @param {Number} offsetY Vertical offset + * @private + */ +Graph.prototype._setTranslation = function(offsetX, offsetY) { + if (this.translation === undefined) { + this.translation = { + "x": 0, + "y": 0 + }; + } - from : function (time, withoutSuffix) { - return moment.duration(this.diff(time)).lang(this.lang()._abbr).humanize(!withoutSuffix); - }, + if (offsetX !== undefined) { + this.translation.x = offsetX; + } + if (offsetY !== undefined) { + this.translation.y = offsetY; + } +}; - fromNow : function (withoutSuffix) { - return this.from(moment(), withoutSuffix); - }, +/** + * Get the translation of the graph + * @return {Object} translation An object with parameters x and y, both a number + * @private + */ +Graph.prototype._getTranslation = function() { + return { + "x": this.translation.x, + "y": this.translation.y + }; +}; + +/** + * Scale the graph + * @param {Number} scale Scaling factor 1.0 is unscaled + * @private + */ +Graph.prototype._setScale = function(scale) { + this.scale = scale; +}; +/** + * Get the current scale of the graph + * @return {Number} scale Scaling factor 1.0 is unscaled + * @private + */ +Graph.prototype._getScale = function() { + return this.scale; +}; - calendar : function () { - var diff = this.diff(moment().startOf('day'), 'days', true), - format = diff < -6 ? 'sameElse' : - diff < -1 ? 'lastWeek' : - diff < 0 ? 'lastDay' : - diff < 1 ? 'sameDay' : - diff < 2 ? 'nextDay' : - diff < 7 ? 'nextWeek' : 'sameElse'; - return this.format(this.lang().calendar(format, this)); - }, +Graph.prototype._xToCanvas = function(x) { + return (x - this.translation.x) / this.scale; +}; - isLeapYear : function () { - var year = this.year(); - return (year % 4 === 0 && year % 100 !== 0) || year % 400 === 0; - }, +Graph.prototype._canvasToX = function(x) { + return x * this.scale + this.translation.x; +}; - isDST : function () { - return (this.zone() < moment([this.year()]).zone() || - this.zone() < moment([this.year(), 5]).zone()); - }, +Graph.prototype._yToCanvas = function(y) { + return (y - this.translation.y) / this.scale; +}; - day : function (input) { - var day = this._isUTC ? this._d.getUTCDay() : this._d.getDay(); - return input == null ? day : - this.add({ d : input - day }); - }, +Graph.prototype._canvasToY = function(y) { + return y * this.scale + this.translation.y ; +}; - startOf: function (units) { - units = units.replace(/s$/, ''); - // the following switch intentionally omits break keywords - // to utilize falling through the cases. - switch (units) { - case 'year': - this.month(0); - /* falls through */ - case 'month': - this.date(1); - /* falls through */ - case 'week': - case 'day': - this.hours(0); - /* falls through */ - case 'hour': - this.minutes(0); - /* falls through */ - case 'minute': - this.seconds(0); - /* falls through */ - case 'second': - this.milliseconds(0); - /* falls through */ +/** + * Redraw all nodes + * The 2d context of a HTML canvas can be retrieved by canvas.getContext("2d"); + * @param {CanvasRenderingContext2D} ctx + * @private + */ +Graph.prototype._drawNodes = function(ctx) { + // first draw the unselected nodes + var nodes = this.nodes; + var selected = []; + for (var id in nodes) { + if (nodes.hasOwnProperty(id)) { + if (nodes[id].isSelected()) { + selected.push(id); } + else { + nodes[id].draw(ctx); + } + } + } - // weeks are a special case - if (units === 'week') { - this.day(0); + // draw the selected nodes on top + for (var s = 0, sMax = selected.length; s < sMax; s++) { + nodes[selected[s]].draw(ctx); + } +}; + +/** + * Redraw all edges + * The 2d context of a HTML canvas can be retrieved by canvas.getContext("2d"); + * @param {CanvasRenderingContext2D} ctx + * @private + */ +Graph.prototype._drawEdges = function(ctx) { + var edges = this.edges; + for (var id in edges) { + if (edges.hasOwnProperty(id)) { + var edge = edges[id]; + if (edge.connected) { + edges[id].draw(ctx); } + } + } +}; - return this; - }, +/** + * Find a stable position for all nodes + * @private + */ +Graph.prototype._doStabilize = function() { + var start = new Date(); - endOf: function (units) { - return this.startOf(units).add(units.replace(/s?$/, 's'), 1).subtract('ms', 1); - }, + // find stable position + var count = 0; + var vmin = this.constants.minVelocity; + var stable = false; + while (!stable && count < this.constants.maxIterations) { + this._calculateForces(); + this._discreteStepNodes(); + stable = !this._isMoving(vmin); + count++; + } - isAfter: function (input, units) { - units = typeof units !== 'undefined' ? units : 'millisecond'; - return +this.clone().startOf(units) > +moment(input).startOf(units); - }, + var end = new Date(); - isBefore: function (input, units) { - units = typeof units !== 'undefined' ? units : 'millisecond'; - return +this.clone().startOf(units) < +moment(input).startOf(units); - }, + // console.log("Stabilized in " + (end-start) + " ms, " + count + " iterations" ); // TODO: cleanup +}; - isSame: function (input, units) { - units = typeof units !== 'undefined' ? units : 'millisecond'; - return +this.clone().startOf(units) === +moment(input).startOf(units); - }, +/** + * Calculate the external forces acting on the nodes + * Forces are caused by: edges, repulsing forces between nodes, gravity + * @private + */ +Graph.prototype._calculateForces = function() { + // create a local edge to the nodes and edges, that is faster + var id, dx, dy, angle, distance, fx, fy, + repulsingForce, springForce, length, edgeLength, + nodes = this.nodes, + edges = this.edges; - zone : function () { - return this._isUTC ? 0 : this._d.getTimezoneOffset(); - }, + // gravity, add a small constant force to pull the nodes towards the center of + // the graph + // Also, the forces are reset to zero in this loop by using _setForce instead + // of _addForce + var gravity = 0.01, + gx = this.frame.canvas.clientWidth / 2, + gy = this.frame.canvas.clientHeight / 2; + for (id in nodes) { + if (nodes.hasOwnProperty(id)) { + var node = nodes[id]; + dx = gx - node.x; + dy = gy - node.y; + angle = Math.atan2(dy, dx); + fx = Math.cos(angle) * gravity; + fy = Math.sin(angle) * gravity; - daysInMonth : function () { - return moment.utc([this.year(), this.month() + 1, 0]).date(); - }, + node._setForce(fx, fy); + } + } - dayOfYear : function (input) { - var dayOfYear = round((moment(this).startOf('day') - moment(this).startOf('year')) / 864e5) + 1; - return input == null ? dayOfYear : this.add("d", (input - dayOfYear)); - }, + // repulsing forces between nodes + var minimumDistance = this.constants.nodes.distance, + steepness = 10; // higher value gives steeper slope of the force around the given minimumDistance - isoWeek : function (input) { - var week = weekOfYear(this, 1, 4); - return input == null ? week : this.add("d", (input - week) * 7); - }, + for (var id1 in nodes) { + if (nodes.hasOwnProperty(id1)) { + var node1 = nodes[id1]; + for (var id2 in nodes) { + if (nodes.hasOwnProperty(id2)) { + var node2 = nodes[id2]; + // calculate normally distributed force + dx = node2.x - node1.x; + dy = node2.y - node1.y; + distance = Math.sqrt(dx * dx + dy * dy); + angle = Math.atan2(dy, dx); - week : function (input) { - var week = this.lang().week(this); - return input == null ? week : this.add("d", (input - week) * 7); - }, + // TODO: correct factor for repulsing force + //repulsingForce = 2 * Math.exp(-5 * (distance * distance) / (dmin * dmin) ); // TODO: customize the repulsing force + //repulsingForce = Math.exp(-1 * (distance * distance) / (dmin * dmin) ); // TODO: customize the repulsing force + repulsingForce = 1 / (1 + Math.exp((distance / minimumDistance - 1) * steepness)); // TODO: customize the repulsing force + fx = Math.cos(angle) * repulsingForce; + fy = Math.sin(angle) * repulsingForce; - // If passed a language key, it will set the language for this - // instance. Otherwise, it will return the language configuration - // variables for this instance. - lang : function (key) { - if (key === undefined) { - return this._lang; - } else { - this._lang = getLangDefinition(key); - return this; + node1._addForce(-fx, -fy); + node2._addForce(fx, fy); + } } } - }; + } + + /* TODO: re-implement repulsion of edges + for (var n = 0; n < nodes.length; n++) { + for (var l = 0; l < edges.length; l++) { + var lx = edges[l].from.x+(edges[l].to.x - edges[l].from.x)/2, + ly = edges[l].from.y+(edges[l].to.y - edges[l].from.y)/2, + + // calculate normally distributed force + dx = nodes[n].x - lx, + dy = nodes[n].y - ly, + distance = Math.sqrt(dx * dx + dy * dy), + angle = Math.atan2(dy, dx), + + + // TODO: correct factor for repulsing force + //var repulsingforce = 2 * Math.exp(-5 * (distance * distance) / (dmin * dmin) ); // TODO: customize the repulsing force + //repulsingforce = Math.exp(-1 * (distance * distance) / (dmin * dmin) ), // TODO: customize the repulsing force + repulsingforce = 1 / (1 + Math.exp((distance / (minimumDistance / 2) - 1) * steepness)), // TODO: customize the repulsing force + fx = Math.cos(angle) * repulsingforce, + fy = Math.sin(angle) * repulsingforce; + nodes[n]._addForce(fx, fy); + edges[l].from._addForce(-fx/2,-fy/2); + edges[l].to._addForce(-fx/2,-fy/2); + } + } + */ + + // forces caused by the edges, modelled as springs + for (id in edges) { + if (edges.hasOwnProperty(id)) { + var edge = edges[id]; + if (edge.connected) { + dx = (edge.to.x - edge.from.x); + dy = (edge.to.y - edge.from.y); + //edgeLength = (edge.from.width + edge.from.height + edge.to.width + edge.to.height)/2 || edge.length; // TODO: dmin + //edgeLength = (edge.from.width + edge.to.width)/2 || edge.length; // TODO: dmin + //edgeLength = 20 + ((edge.from.width + edge.to.width) || 0) / 2; + edgeLength = edge.length; + length = Math.sqrt(dx * dx + dy * dy); + angle = Math.atan2(dy, dx); - // helper for adding shortcuts - function makeGetterAndSetter(name, key) { - moment.fn[name] = moment.fn[name + 's'] = function (input) { - var utc = this._isUTC ? 'UTC' : ''; - if (input != null) { - this._d['set' + utc + key](input); - return this; - } else { - return this._d['get' + utc + key](); - } - }; - } + springForce = edge.stiffness * (edgeLength - length); - // loop through and add shortcuts (Month, Date, Hours, Minutes, Seconds, Milliseconds) - for (i = 0; i < proxyGettersAndSetters.length; i ++) { - makeGetterAndSetter(proxyGettersAndSetters[i].toLowerCase().replace(/s$/, ''), proxyGettersAndSetters[i]); + fx = Math.cos(angle) * springForce; + fy = Math.sin(angle) * springForce; + + edge.from._addForce(-fx, -fy); + edge.to._addForce(fx, fy); + } + } } - // add shortcut for year (uses different syntax than the getter/setter 'year' == 'FullYear') - makeGetterAndSetter('year', 'FullYear'); + /* TODO: re-implement repulsion of edges + // repulsing forces between edges + var minimumDistance = this.constants.edges.distance, + steepness = 10; // higher value gives steeper slope of the force around the given minimumDistance + for (var l = 0; l < edges.length; l++) { + //Keep distance from other edge centers + for (var l2 = l + 1; l2 < this.edges.length; l2++) { + //var dmin = (nodes[n].width + nodes[n].height + nodes[n2].width + nodes[n2].height) / 1 || minimumDistance, // TODO: dmin + //var dmin = (nodes[n].width + nodes[n2].width)/2 || minimumDistance, // TODO: dmin + //dmin = 40 + ((nodes[n].width/2 + nodes[n2].width/2) || 0), + var lx = edges[l].from.x+(edges[l].to.x - edges[l].from.x)/2, + ly = edges[l].from.y+(edges[l].to.y - edges[l].from.y)/2, + l2x = edges[l2].from.x+(edges[l2].to.x - edges[l2].from.x)/2, + l2y = edges[l2].from.y+(edges[l2].to.y - edges[l2].from.y)/2, - // add plural methods - moment.fn.days = moment.fn.day; - moment.fn.weeks = moment.fn.week; - moment.fn.isoWeeks = moment.fn.isoWeek; + // calculate normally distributed force + dx = l2x - lx, + dy = l2y - ly, + distance = Math.sqrt(dx * dx + dy * dy), + angle = Math.atan2(dy, dx), - /************************************ - Duration Prototype - ************************************/ + // TODO: correct factor for repulsing force + //var repulsingforce = 2 * Math.exp(-5 * (distance * distance) / (dmin * dmin) ); // TODO: customize the repulsing force + //repulsingforce = Math.exp(-1 * (distance * distance) / (dmin * dmin) ), // TODO: customize the repulsing force + repulsingforce = 1 / (1 + Math.exp((distance / minimumDistance - 1) * steepness)), // TODO: customize the repulsing force + fx = Math.cos(angle) * repulsingforce, + fy = Math.sin(angle) * repulsingforce; - moment.duration.fn = Duration.prototype = { - weeks : function () { - return absRound(this.days() / 7); - }, + edges[l].from._addForce(-fx, -fy); + edges[l].to._addForce(-fx, -fy); + edges[l2].from._addForce(fx, fy); + edges[l2].to._addForce(fx, fy); + } + } + */ +}; - valueOf : function () { - return this._milliseconds + - this._days * 864e5 + - this._months * 2592e6; - }, - humanize : function (withSuffix) { - var difference = +this, - output = relativeTime(difference, !withSuffix, this.lang()); +/** + * Check if any of the nodes is still moving + * @param {number} vmin the minimum velocity considered as "moving" + * @return {boolean} true if moving, false if non of the nodes is moving + * @private + */ +Graph.prototype._isMoving = function(vmin) { + // TODO: ismoving does not work well: should check the kinetic energy, not its velocity + var nodes = this.nodes; + for (var id in nodes) { + if (nodes.hasOwnProperty(id) && nodes[id].isMoving(vmin)) { + return true; + } + } + return false; +}; - if (withSuffix) { - output = this.lang().pastFuture(difference, output); - } - return this.lang().postformat(output); - }, +/** + * Perform one discrete step for all nodes + * @private + */ +Graph.prototype._discreteStepNodes = function() { + var interval = this.refreshRate / 1000.0; // in seconds + var nodes = this.nodes; + for (var id in nodes) { + if (nodes.hasOwnProperty(id)) { + nodes[id].discreteStep(interval); + } + } +}; - lang : moment.fn.lang - }; +/** + * Start animating nodes and edges + */ +Graph.prototype.start = function() { + if (this.moving) { + this._calculateForces(); + this._discreteStepNodes(); - function makeDurationGetter(name) { - moment.duration.fn[name] = function () { - return this._data[name]; - }; + var vmin = this.constants.minVelocity; + this.moving = this._isMoving(vmin); } - function makeDurationAsGetter(name, factor) { - moment.duration.fn['as' + name] = function () { - return +this / factor; - }; + if (this.moving) { + // start animation. only start timer if it is not already running + if (!this.timer) { + var graph = this; + this.timer = window.setTimeout(function () { + graph.timer = undefined; + graph.start(); + graph._redraw(); + }, this.refreshRate); + } } + else { + this._redraw(); + } +}; - for (i in unitMillisecondFactors) { - if (unitMillisecondFactors.hasOwnProperty(i)) { - makeDurationAsGetter(i, unitMillisecondFactors[i]); - makeDurationGetter(i.toLowerCase()); - } +/** + * Stop animating nodes and edges. + */ +Graph.prototype.stop = function () { + if (this.timer) { + window.clearInterval(this.timer); + this.timer = undefined; } +}; - makeDurationAsGetter('Weeks', 6048e5); +/** + * vis.js module exports + */ +var vis = { + util: util, + events: events, + Controller: Controller, + DataSet: DataSet, + DataView: DataView, + Range: Range, + Stack: Stack, + TimeStep: TimeStep, + EventBus: EventBus, - /************************************ - Default Lang - ************************************/ + components: { + items: { + Item: Item, + ItemBox: ItemBox, + ItemPoint: ItemPoint, + ItemRange: ItemRange + }, + Component: Component, + Panel: Panel, + RootPanel: RootPanel, + ItemSet: ItemSet, + TimeAxis: TimeAxis + }, - // Set default language, other languages will inherit from English. - moment.lang('en', { - ordinal : function (number) { - var b = number % 10, - output = (~~ (number % 100 / 10) === 1) ? 'th' : - (b === 1) ? 'st' : - (b === 2) ? 'nd' : - (b === 3) ? 'rd' : 'th'; - return number + output; - } - }); + graph: { + Node: Node, + Edge: Edge, + Popup: Popup, + Groups: Groups, + Images: Images + }, + + Timeline: Timeline, + Graph: Graph +}; +/** + * CommonJS module exports + */ +if (typeof exports !== 'undefined') { + exports = vis; +} +if (typeof module !== 'undefined' && typeof module.exports !== 'undefined') { + module.exports = vis; +} - /************************************ - Exposing Moment - ************************************/ +/** + * AMD module exports + */ +if (typeof(define) === 'function') { + define(function () { + return vis; + }); +} +/** + * Window exports + */ +if (typeof window !== 'undefined') { + // attach the module to the window, load as a regular javascript file + window['vis'] = vis; +} - // CommonJS module is defined - if (hasModule) { - module.exports = moment; - } - /*global ender:false */ - if (typeof ender === 'undefined') { - // here, `this` means `window` in the browser, or `global` on the server - // add `moment` as a global object via a string identifier, - // for Closure Compiler "advanced" mode - this['moment'] = moment; - } - /*global define:false */ - if (typeof define === "function" && define.amd) { - define("moment", [], function () { - return moment; - }); - } -}).call(this); +// inject css +util.loadCss("/* vis.js stylesheet */\n.vis.timeline {\n}\n\n\n.vis.timeline.rootpanel {\n position: relative;\n overflow: hidden;\n\n border: 1px solid #bfbfbf;\n -moz-box-sizing: border-box;\n box-sizing: border-box;\n}\n\n.vis.timeline .panel {\n position: absolute;\n overflow: hidden;\n}\n\n\n.vis.timeline .groupset {\n position: absolute;\n padding: 0;\n margin: 0;\n}\n\n.vis.timeline .labels {\n position: absolute;\n top: 0;\n left: 0;\n width: 100%;\n height: 100%;\n\n padding: 0;\n margin: 0;\n\n border-right: 1px solid #bfbfbf;\n box-sizing: border-box;\n -moz-box-sizing: border-box;\n}\n\n.vis.timeline .labels .label {\n position: absolute;\n left: 0;\n top: 0;\n width: 100%;\n border-bottom: 1px solid #bfbfbf;\n color: #4d4d4d;\n}\n\n.vis.timeline .labels .label .inner {\n display: inline-block;\n padding: 5px;\n}\n\n\n.vis.timeline .itemset {\n position: absolute;\n padding: 0;\n margin: 0;\n overflow: hidden;\n}\n\n.vis.timeline .background {\n}\n\n.vis.timeline .foreground {\n}\n\n.vis.timeline .itemset-axis {\n position: absolute;\n}\n\n.vis.timeline .groupset .itemset-axis {\n border-top: 1px solid #bfbfbf;\n}\n\n/* TODO: with orientation=='bottom', this will more or less overlap with timeline axis\n.vis.timeline .groupset .itemset-axis:last-child {\n border-top: none;\n}\n*/\n\n\n.vis.timeline .item {\n position: absolute;\n color: #1A1A1A;\n border-color: #97B0F8;\n background-color: #D5DDF6;\n display: inline-block;\n}\n\n.vis.timeline .item.selected {\n border-color: #FFC200;\n background-color: #FFF785;\n z-index: 999;\n}\n\n.vis.timeline .item.cluster {\n /* TODO: use another color or pattern? */\n background: #97B0F8 url('img/cluster_bg.png');\n color: white;\n}\n.vis.timeline .item.cluster.point {\n border-color: #D5DDF6;\n}\n\n.vis.timeline .item.box {\n text-align: center;\n border-style: solid;\n border-width: 1px;\n border-radius: 5px;\n -moz-border-radius: 5px; /* For Firefox 3.6 and older */\n}\n\n.vis.timeline .item.point {\n background: none;\n}\n\n.vis.timeline .dot {\n border: 5px solid #97B0F8;\n position: absolute;\n border-radius: 5px;\n -moz-border-radius: 5px; /* For Firefox 3.6 and older */\n}\n\n.vis.timeline .item.range {\n overflow: hidden;\n border-style: solid;\n border-width: 1px;\n border-radius: 2px;\n -moz-border-radius: 2px; /* For Firefox 3.6 and older */\n}\n\n.vis.timeline .item.range .drag-left {\n cursor: w-resize;\n z-index: 1000;\n}\n\n.vis.timeline .item.range .drag-right {\n cursor: e-resize;\n z-index: 1000;\n}\n\n.vis.timeline .item.range .content {\n position: relative;\n display: inline-block;\n}\n\n.vis.timeline .item.line {\n position: absolute;\n width: 0;\n border-left-width: 1px;\n border-left-style: solid;\n}\n\n.vis.timeline .item .content {\n margin: 5px;\n white-space: nowrap;\n overflow: hidden;\n}\n\n.vis.timeline .axis {\n position: relative;\n}\n\n.vis.timeline .axis .text {\n position: absolute;\n color: #4d4d4d;\n padding: 3px;\n white-space: nowrap;\n}\n\n.vis.timeline .axis .text.measure {\n position: absolute;\n padding-left: 0;\n padding-right: 0;\n margin-left: 0;\n margin-right: 0;\n visibility: hidden;\n}\n\n.vis.timeline .axis .grid.vertical {\n position: absolute;\n width: 0;\n border-right: 1px solid;\n}\n\n.vis.timeline .axis .grid.horizontal {\n position: absolute;\n left: 0;\n width: 100%;\n height: 0;\n border-bottom: 1px solid;\n}\n\n.vis.timeline .axis .grid.minor {\n border-color: #e5e5e5;\n}\n\n.vis.timeline .axis .grid.major {\n border-color: #bfbfbf;\n}\n\n"); -})() -},{}]},{},[1])(1) +},{"hammerjs":1,"moment":2}]},{},[3]) +(3) }); ; \ No newline at end of file diff --git a/vis.min.js b/vis.min.js index caccd911..490c0395 100644 --- a/vis.min.js +++ b/vis.min.js @@ -5,7 +5,7 @@ * A dynamic, browser-based visualization library. * * @version 0.2.0-SNAPSHOT - * @date 2013-09-09 + * @date 2013-09-16 * * @license * Copyright (C) 2011-2013 Almende B.V, http://almende.com @@ -22,8 +22,8 @@ * License for the specific language governing permissions and limitations under * the License. */ -(function(t){if("function"==typeof bootstrap)bootstrap("vis",t);else if("object"==typeof exports)module.exports=t();else if("function"==typeof define&&define.amd)define(t);else if("undefined"!=typeof ses){if(!ses.ok())return;ses.makeVis=t}else"undefined"!=typeof window?window.vis=t():global.vis=t()})(function(){var t;return function(t,e,i){function s(i,o){if(!e[i]){if(!t[i]){var r="function"==typeof require&&require;if(!o&&r)return r(i,!0);if(n)return n(i,!0);throw Error("Cannot find module '"+i+"'")}var a=e[i]={exports:{}};t[i][0].call(a.exports,function(e){var n=t[i][1][e];return s(n?n:e)},a,a.exports)}return e[i].exports}for(var n="function"==typeof require&&require,o=0;i.length>o;o++)s(i[o]);return s}({1:[function(e,i,s){(function(){function n(){this.subscriptions=[]}function o(t){if(this.id=D.randomUUID(),this.options=t||{},this.data={},this.fieldId=this.options.fieldId||"id",this.convert={},this.options.convert)for(var e in this.options.convert)if(this.options.convert.hasOwnProperty(e)){var i=this.options.convert[e];this.convert[e]="Date"==i||"ISODate"==i||"ASPDate"==i?"Date":i}this.subscribers={},this.internalIds={}}function r(t,e){this.id=D.randomUUID(),this.data=null,this.ids={},this.options=e||{},this.fieldId="id",this.subscribers={};var i=this;this.listener=function(){i._onEvent.apply(i,arguments)},this.setData(t)}function a(t,e){this.parent=t,this.options=e||{},this.defaultOptions={order:function(t,e){if(t instanceof y){if(e instanceof y){var i=t.data.end-t.data.start,s=e.data.end-e.data.start;return i-s||t.data.start-e.data.start}return-1}return e instanceof y?1:t.data.start-e.data.start},margin:{item:10}},this.ordered=[]}function h(t){this.id=D.randomUUID(),this.start=0,this.end=0,this.options={min:null,max:null,zoomMin:null,zoomMax:null},this.listeners=[],this.setOptions(t)}function d(){this.id=D.randomUUID(),this.components={},this.repaintTimer=void 0,this.reflowTimer=void 0}function l(){this.id=null,this.parent=null,this.depends=null,this.controller=null,this.options=null,this.frame=null,this.top=0,this.left=0,this.width=0,this.height=0}function p(t,e,i){this.id=D.randomUUID(),this.parent=t,this.depends=e,this.options=i||{}}function c(t,e){this.id=D.randomUUID(),this.container=t,this.options=e||{},this.defaultOptions={autoResize:!0},this.listeners={}}function u(t,e,i){this.id=D.randomUUID(),this.parent=t,this.depends=e,this.dom={majorLines:[],majorTexts:[],minorLines:[],minorTexts:[],redundant:{majorLines:[],majorTexts:[],minorLines:[],minorTexts:[]}},this.props={range:{start:0,end:0,minimumStep:0},lineTop:0},this.options=i||{},this.defaultOptions={orientation:"bottom",showMinorLabels:!0,showMajorLabels:!0},this.conversion=null,this.range=null}function f(t,e,i){this.id=D.randomUUID(),this.parent=t,this.depends=e,this.options=i||{},this.defaultOptions={type:"box",align:"center",orientation:"bottom",margin:{axis:20,item:10},padding:5},this.dom={};var s=this;this.itemsData=null,this.range=null,this.listeners={add:function(t,e,i){i!=s.id&&s._onAdd(e.items)},update:function(t,e,i){i!=s.id&&s._onUpdate(e.items)},remove:function(t,e,i){i!=s.id&&s._onRemove(e.items)}},this.items={},this.queue={},this.stack=new a(this,Object.create(this.options)),this.conversion=null}function m(t,e,i,s){this.parent=t,this.data=e,this.dom=null,this.options=i||{},this.defaultOptions=s||{},this.selected=!1,this.visible=!1,this.top=0,this.left=0,this.width=0,this.height=0}function g(t,e,i,s){this.props={dot:{left:0,top:0,width:0,height:0},line:{top:0,left:0,width:0,height:0}},m.call(this,t,e,i,s)}function v(t,e,i,s){this.props={dot:{top:0,width:0,height:0},content:{height:0,marginLeft:0}},m.call(this,t,e,i,s)}function y(t,e,i,s){this.props={content:{left:0,width:0}},m.call(this,t,e,i,s)}function b(t,e,i){this.id=D.randomUUID(),this.parent=t,this.groupId=e,this.itemset=null,this.options=i||{},this.options.top=0,this.props={label:{width:0,height:0}},this.top=0,this.left=0,this.width=0,this.height=0}function w(t,e,i){this.id=D.randomUUID(),this.parent=t,this.depends=e,this.options=i||{},this.range=null,this.itemsData=null,this.groupsData=null,this.groups={},this.dom={},this.props={labels:{width:0}},this.queue={};var s=this;this.listeners={add:function(t,e){s._onAdd(e.items)},update:function(t,e){s._onUpdate(e.items)},remove:function(t,e){s._onRemove(e.items)}}}function _(t,e,i){var s=this;if(this.options=D.extend({orientation:"bottom",min:null,max:null,zoomMin:10,zoomMax:31536e10,showMinorLabels:!0,showMajorLabels:!0,autoResize:!1},i),this.controller=new d,!t)throw Error("No container element provided");var n=Object.create(this.options);n.height=function(){return s.options.height?s.options.height:s.timeaxis.height+s.content.height},this.rootPanel=new c(t,n),this.controller.add(this.rootPanel);var o=Object.create(this.options);o.left=function(){return s.labelPanel.width},o.width=function(){return s.rootPanel.width-s.labelPanel.width},o.top=null,o.height=null,this.itemPanel=new p(this.rootPanel,[],o),this.controller.add(this.itemPanel);var r=Object.create(this.options);r.top=null,r.left=null,r.height=null,r.width=function(){return s.content&&"function"==typeof s.content.getLabelsWidth?s.content.getLabelsWidth():0},this.labelPanel=new p(this.rootPanel,[],r),this.controller.add(this.labelPanel);var a=E().hours(0).minutes(0).seconds(0).milliseconds(0);this.range=new h({start:a.clone().add("days",-3).valueOf(),end:a.clone().add("days",4).valueOf()}),this.range.subscribe(this.rootPanel,"move","horizontal"),this.range.subscribe(this.rootPanel,"zoom","horizontal"),this.range.on("rangechange",function(){var t=!0;s.controller.requestReflow(t)}),this.range.on("rangechanged",function(){var t=!0;s.controller.requestReflow(t)});var l=Object.create(n);l.range=this.range,l.left=null,l.top=null,l.width="100%",l.height=null,this.timeaxis=new u(this.itemPanel,[],l),this.timeaxis.setRange(this.range),this.controller.add(this.timeaxis),this.setGroups(null),this.itemsData=null,this.groupsData=null,e&&this.setItems(e)}function x(t,e,i,s){this.selected=!1,this.edges=[],this.group=s.nodes.group,this.fontSize=s.nodes.fontSize,this.fontFace=s.nodes.fontFace,this.fontColor=s.nodes.fontColor,this.color=s.nodes.color,this.id=void 0,this.shape=s.nodes.shape,this.image=s.nodes.image,this.x=0,this.y=0,this.xFixed=!1,this.yFixed=!1,this.radius=s.nodes.radius,this.radiusFixed=!1,this.radiusMin=s.nodes.radiusMin,this.radiusMax=s.nodes.radiusMax,this.imagelist=e,this.grouplist=i,this.setProperties(t,s),this.mass=50,this.fx=0,this.fy=0,this.vx=0,this.vy=0,this.minForce=s.minForce,this.damping=.9}function T(t,e,i){if(!e)throw"No graph provided";this.graph=e,this.widthMin=i.edges.widthMin,this.widthMax=i.edges.widthMax,this.id=void 0,this.fromId=void 0,this.toId=void 0,this.style=i.edges.style,this.title=void 0,this.width=i.edges.width,this.value=void 0,this.length=i.edges.length,this.from=null,this.to=null,this.connected=!1,this.dash=D.extend({},i.edges.dash),this.stiffness=void 0,this.color=i.edges.color,this.widthFixed=!1,this.lengthFixed=!1,this.setProperties(t,i)}function S(t,e,i,s){this.container=t?t:document.body,this.x=0,this.y=0,this.padding=5,void 0!==e&&void 0!==i&&this.setPosition(e,i),void 0!==s&&this.setText(s),this.frame=document.createElement("div");var n=this.frame.style;n.position="absolute",n.visibility="hidden",n.border="1px solid #666",n.color="black",n.padding=this.padding+"px",n.backgroundColor="#FFFFC6",n.borderRadius="3px",n.MozBorderRadius="3px",n.WebkitBorderRadius="3px",n.boxShadow="3px 3px 10px rgba(128, 128, 128, 0.5)",n.whiteSpace="nowrap",this.container.appendChild(this.frame)}function M(t,e,i){this.containerElement=t,this.width="100%",this.height="100%",this.refreshRate=50,this.stabilize=!0,this.selectable=!0,this.constants={nodes:{radiusMin:5,radiusMax:20,radius:5,distance:100,shape:"ellipse",image:void 0,widthMin:16,widthMax:64,fontColor:"black",fontSize:14,fontFace:"arial",color:{border:"#2B7CE9",background:"#97C2FC",highlight:{border:"#2B7CE9",background:"#D2E5FF"}},borderColor:"#2B7CE9",backgroundColor:"#97C2FC",highlightColor:"#D2E5FF",group:void 0},edges:{widthMin:1,widthMax:15,width:1,style:"line",color:"#343434",fontColor:"#343434",fontSize:14,fontFace:"arial",length:100,dash:{length:10,gap:5,altLength:void 0}},minForce:.05,minVelocity:.02,maxIterations:1e3};var s=this;this.nodes={},this.edges={},this.nodesData=null,this.edgesData=null;var n=this;this.nodesListeners={add:function(t,e){n._addNodes(e.items),n.start()},update:function(t,e){n._updateNodes(e.items),n.start()},remove:function(t,e){n._removeNodes(e.items),n.start()}},this.edgesListeners={add:function(t,e){n._addEdges(e.items),n.start()},update:function(t,e){n._updateEdges(e.items),n.start()},remove:function(t,e){n._removeEdges(e.items),n.start()}},this.groups=new Groups,this.images=new Images,this.images.setOnloadCallback(function(){s._redraw()}),this.moving=!1,this.selection=[],this.timer=void 0,this._create(),this.setOptions(i),this.setData(e)}var E=e("moment"),D={};D.isNumber=function(t){return t instanceof Number||"number"==typeof t},D.isString=function(t){return t instanceof String||"string"==typeof t},D.isDate=function(t){if(t instanceof Date)return!0;if(D.isString(t)){var e=C.exec(t);if(e)return!0;if(!isNaN(Date.parse(t)))return!0}return!1},D.isDataTable=function(t){return"undefined"!=typeof google&&google.visualization&&google.visualization.DataTable&&t instanceof google.visualization.DataTable},D.randomUUID=function(){var t=function(){return Math.floor(65536*Math.random()).toString(16)};return t()+t()+"-"+t()+"-"+t()+"-"+t()+"-"+t()+t()+t()},D.extend=function(t){for(var e=1,i=arguments.length;i>e;e++){var s=arguments[e];for(var n in s)s.hasOwnProperty(n)&&void 0!==s[n]&&(t[n]=s[n])}return t},D.convert=function(t,e){var i;if(void 0===t)return void 0;if(null===t)return null;if(!e)return t;if("string"!=typeof e&&!(e instanceof String))throw Error("Type must be a string");switch(e){case"boolean":case"Boolean":return Boolean(t);case"number":case"Number":return Number(t.valueOf());case"string":case"String":return t+"";case"Date":if(D.isNumber(t))return new Date(t);if(t instanceof Date)return new Date(t.valueOf());if(E.isMoment(t))return new Date(t.valueOf());if(D.isString(t))return i=C.exec(t),i?new Date(Number(i[1])):E(t).toDate();throw Error("Cannot convert object of type "+D.getType(t)+" to type Date");case"Moment":if(D.isNumber(t))return E(t);if(t instanceof Date)return E(t.valueOf());if(E.isMoment(t))return E.clone();if(D.isString(t))return i=C.exec(t),i?E(Number(i[1])):E(t);throw Error("Cannot convert object of type "+D.getType(t)+" to type Date");case"ISODate":if(D.isNumber(t))return new Date(t);if(t instanceof Date)return t.toISOString();if(E.isMoment(t))return t.toDate().toISOString();if(D.isString(t))return i=C.exec(t),i?new Date(Number(i[1])).toISOString():new Date(t).toISOString();throw Error("Cannot convert object of type "+D.getType(t)+" to type ISODate");case"ASPDate":if(D.isNumber(t))return"/Date("+t+")/";if(t instanceof Date)return"/Date("+t.valueOf()+")/";if(D.isString(t)){i=C.exec(t);var s;return s=i?new Date(Number(i[1])).valueOf():new Date(t).valueOf(),"/Date("+s+")/"}throw Error("Cannot convert object of type "+D.getType(t)+" to type ASPDate");default:throw Error("Cannot convert object of type "+D.getType(t)+' to type "'+e+'"')}};var C=/^\/?Date\((\-?\d+)/i;if(D.getType=function(t){var e=typeof t;return"object"==e?null==t?"null":t instanceof Boolean?"Boolean":t instanceof Number?"Number":t instanceof String?"String":t instanceof Array?"Array":t instanceof Date?"Date":"Object":"number"==e?"Number":"boolean"==e?"Boolean":"string"==e?"String":e},D.getAbsoluteLeft=function(t){for(var e=document.documentElement,i=document.body,s=t.offsetLeft,n=t.offsetParent;null!=n&&n!=i&&n!=e;)s+=n.offsetLeft,s-=n.scrollLeft,n=n.offsetParent;return s},D.getAbsoluteTop=function(t){for(var e=document.documentElement,i=document.body,s=t.offsetTop,n=t.offsetParent;null!=n&&n!=i&&n!=e;)s+=n.offsetTop,s-=n.scrollTop,n=n.offsetParent;return s},D.getPageY=function(t){if("pageY"in t)return t.pageY;var e;e="targetTouches"in t&&t.targetTouches.length?t.targetTouches[0].clientY:t.clientY;var i=document.documentElement,s=document.body;return e+(i&&i.scrollTop||s&&s.scrollTop||0)-(i&&i.clientTop||s&&s.clientTop||0)},D.getPageX=function(t){if("pageY"in t)return t.pageX;var e;e="targetTouches"in t&&t.targetTouches.length?t.targetTouches[0].clientX:t.clientX;var i=document.documentElement,s=document.body;return e+(i&&i.scrollLeft||s&&s.scrollLeft||0)-(i&&i.clientLeft||s&&s.clientLeft||0)},D.addClassName=function(t,e){var i=t.className.split(" ");-1==i.indexOf(e)&&(i.push(e),t.className=i.join(" "))},D.removeClassName=function(t,e){var i=t.className.split(" "),s=i.indexOf(e);-1!=s&&(i.splice(s,1),t.className=i.join(" "))},D.forEach=function(t,e){var i,s;if(t instanceof Array)for(i=0,s=t.length;s>i;i++)e(t[i],i,t);else for(i in t)t.hasOwnProperty(i)&&e(t[i],i,t)},D.updateProperty=function(t,e,i){return t[e]!==i?(t[e]=i,!0):!1},D.addEventListener=function(t,e,i,s){t.addEventListener?(void 0===s&&(s=!1),"mousewheel"===e&&navigator.userAgent.indexOf("Firefox")>=0&&(e="DOMMouseScroll"),t.addEventListener(e,i,s)):t.attachEvent("on"+e,i)},D.removeEventListener=function(t,e,i,s){t.removeEventListener?(void 0===s&&(s=!1),"mousewheel"===e&&navigator.userAgent.indexOf("Firefox")>=0&&(e="DOMMouseScroll"),t.removeEventListener(e,i,s)):t.detachEvent("on"+e,i)},D.getTarget=function(t){t||(t=window.event);var e;return t.target?e=t.target:t.srcElement&&(e=t.srcElement),void 0!=e.nodeType&&3==e.nodeType&&(e=e.parentNode),e},D.stopPropagation=function(t){t||(t=window.event),t.stopPropagation?t.stopPropagation():t.cancelBubble=!0},D.preventDefault=function(t){t||(t=window.event),t.preventDefault?t.preventDefault():t.returnValue=!1},D.option={},D.option.asBoolean=function(t,e){return"function"==typeof t&&(t=t()),null!=t?0!=t:e||null},D.option.asNumber=function(t,e){return"function"==typeof t&&(t=t()),null!=t?Number(t)||e||null:e||null},D.option.asString=function(t,e){return"function"==typeof t&&(t=t()),null!=t?t+"":e||null},D.option.asSize=function(t,e){return"function"==typeof t&&(t=t()),D.isString(t)?t:D.isNumber(t)?t+"px":e||null},D.option.asElement=function(t,e){return"function"==typeof t&&(t=t()),t||e||null},D.loadCss=function(t){if("undefined"!=typeof document){var e=document.createElement("style");e.type="text/css",e.styleSheet?e.styleSheet.cssText=t:e.appendChild(document.createTextNode(t)),document.getElementsByTagName("head")[0].appendChild(e)}},!Array.prototype.indexOf){Array.prototype.indexOf=function(t){for(var e=0;this.length>e;e++)if(this[e]==t)return e;return-1};try{console.log("Warning: Ancient browser detected. Please update your browser")}catch(L){}}Array.prototype.forEach||(Array.prototype.forEach=function(t,e){for(var i=0,s=this.length;s>i;++i)t.call(e||this,this[i],i,this)}),Array.prototype.map||(Array.prototype.map=function(t,e){var i,s,n;if(null==this)throw new TypeError(" this is null or not defined");var o=Object(this),r=o.length>>>0;if("function"!=typeof t)throw new TypeError(t+" is not a function");for(e&&(i=e),s=Array(r),n=0;r>n;){var a,h;n in o&&(a=o[n],h=t.call(i,a,n,o),s[n]=h),n++}return s}),Array.prototype.filter||(Array.prototype.filter=function(t){"use strict";if(null==this)throw new TypeError;var e=Object(this),i=e.length>>>0;if("function"!=typeof t)throw new TypeError;for(var s=[],n=arguments[1],o=0;i>o;o++)if(o in e){var r=e[o];t.call(n,r,o,e)&&s.push(r)}return s}),Object.keys||(Object.keys=function(){var t=Object.prototype.hasOwnProperty,e=!{toString:null}.propertyIsEnumerable("toString"),i=["toString","toLocaleString","valueOf","hasOwnProperty","isPrototypeOf","propertyIsEnumerable","constructor"],s=i.length;return function(n){if("object"!=typeof n&&"function"!=typeof n||null===n)throw new TypeError("Object.keys called on non-object");var o=[];for(var r in n)t.call(n,r)&&o.push(r);if(e)for(var a=0;s>a;a++)t.call(n,i[a])&&o.push(i[a]);return o}}()),Array.isArray||(Array.isArray=function(t){return"[object Array]"===Object.prototype.toString.call(t)}),Function.prototype.bind||(Function.prototype.bind=function(t){if("function"!=typeof this)throw new TypeError("Function.prototype.bind - what is trying to be bound is not callable");var e=Array.prototype.slice.call(arguments,1),i=this,s=function(){},n=function(){return i.apply(this instanceof s&&t?this:t,e.concat(Array.prototype.slice.call(arguments)))};return s.prototype=this.prototype,n.prototype=new s,n}),Object.create||(Object.create=function(t){function e(){}if(arguments.length>1)throw Error("Object.create implementation only accepts the first parameter.");return e.prototype=t,new e});var O={listeners:[],indexOf:function(t){for(var e=this.listeners,i=0,s=this.listeners.length;s>i;i++){var n=e[i];if(n&&n.object==t)return i}return-1},addListener:function(t,e,i){var s=this.indexOf(t),n=this.listeners[s];n||(n={object:t,events:{}},this.listeners.push(n));var o=n.events[e];o||(o=[],n.events[e]=o),-1==o.indexOf(i)&&o.push(i)},removeListener:function(t,e,i){var s=this.indexOf(t),n=this.listeners[s];if(n){var o=n.events[e];o&&(s=o.indexOf(i),-1!=s&&o.splice(s,1),0==o.length&&delete n.events[e]);var r=0,a=n.events;for(var h in a)a.hasOwnProperty(h)&&r++;0==r&&delete this.listeners[s]}},removeAllListeners:function(){this.listeners=[]},trigger:function(t,e,i){var s=this.indexOf(t),n=this.listeners[s];if(n){var o=n.events[e];if(o)for(var r=0,a=o.length;a>r;r++)o[r](i)}}};n.prototype.on=function(t,e,i){var s=t instanceof RegExp?t:RegExp(t.replace("*","\\w+")),n={id:D.randomUUID(),event:t,regexp:s,callback:"function"==typeof e?e:null,target:i};return this.subscriptions.push(n),n.id},n.prototype.off=function(t){for(var e=0;this.subscriptions.length>e;){var i=this.subscriptions[e],s=!0;if(t instanceof Object)for(var n in t)t.hasOwnProperty(n)&&t[n]!==i[n]&&(s=!1);else s=i.id==t;s?this.subscriptions.splice(e,1):e++}},n.prototype.emit=function(t,e,i){for(var s=0;this.subscriptions.length>s;s++){var n=this.subscriptions[s];n.regexp.test(t)&&n.callback&&n.callback(t,e,i)}},o.prototype.subscribe=function(t,e){var i=this.subscribers[t];i||(i=[],this.subscribers[t]=i),i.push({callback:e})},o.prototype.unsubscribe=function(t,e){var i=this.subscribers[t];i&&(this.subscribers[t]=i.filter(function(t){return t.callback!=e}))},o.prototype._trigger=function(t,e,i){if("*"==t)throw Error("Cannot trigger event *");var s=[];t in this.subscribers&&(s=s.concat(this.subscribers[t])),"*"in this.subscribers&&(s=s.concat(this.subscribers["*"]));for(var n=0;s.length>n;n++){var o=s[n];o.callback&&o.callback(t,e,i||null)}},o.prototype.add=function(t,e){var i,s=[],n=this;if(t instanceof Array)for(var o=0,r=t.length;r>o;o++)i=n._addItem(t[o]),s.push(i);else if(D.isDataTable(t))for(var a=this._getColumnNames(t),h=0,d=t.getNumberOfRows();d>h;h++){for(var l={},p=0,c=a.length;c>p;p++){var u=a[p];l[u]=t.getValue(h,p)}i=n._addItem(l),s.push(i)}else{if(!(t instanceof Object))throw Error("Unknown dataType");i=n._addItem(t),s.push(i)}return s.length&&this._trigger("add",{items:s},e),s},o.prototype.update=function(t,e){var i=[],s=[],n=this,o=n.fieldId,r=function(t){var e=t[o];n.data[e]?(e=n._updateItem(t),s.push(e)):(e=n._addItem(t),i.push(e))};if(t instanceof Array)for(var a=0,h=t.length;h>a;a++)r(t[a]);else if(D.isDataTable(t))for(var d=this._getColumnNames(t),l=0,p=t.getNumberOfRows();p>l;l++){for(var c={},u=0,f=d.length;f>u;u++){var m=d[u];c[m]=t.getValue(l,u)}r(c)}else{if(!(t instanceof Object))throw Error("Unknown dataType");r(t)}return i.length&&this._trigger("add",{items:i},e),s.length&&this._trigger("update",{items:s},e),i.concat(s)},o.prototype.get=function(){var t,e,i,s,n=this,o=D.getType(arguments[0]);"String"==o||"Number"==o?(t=arguments[0],i=arguments[1],s=arguments[2]):"Array"==o?(e=arguments[0],i=arguments[1],s=arguments[2]):(i=arguments[0],s=arguments[1]);var r;if(i&&i.type){if(r="DataTable"==i.type?"DataTable":"Array",s&&r!=D.getType(s))throw Error('Type of parameter "data" ('+D.getType(s)+") "+"does not correspond with specified options.type ("+i.type+")");if("DataTable"==r&&!D.isDataTable(s))throw Error('Parameter "data" must be a DataTable when options.type is "DataTable"')}else r=s?"DataTable"==D.getType(s)?"DataTable":"Array":"Array";var a,h,d,l,p=i&&i.convert||this.options.convert,c=i&&i.filter,u=[];if(void 0!=t)a=n._getItem(t,p),c&&!c(a)&&(a=null);else if(void 0!=e)for(d=0,l=e.length;l>d;d++)a=n._getItem(e[d],p),(!c||c(a))&&u.push(a);else for(h in this.data)this.data.hasOwnProperty(h)&&(a=n._getItem(h,p),(!c||c(a))&&u.push(a));if(i&&i.order&&void 0==t&&this._sort(u,i.order),i&&i.fields){var f=i.fields;if(void 0!=t)a=this._filterFields(a,f);else for(d=0,l=u.length;l>d;d++)u[d]=this._filterFields(u[d],f)}if("DataTable"==r){var m=this._getColumnNames(s);if(void 0!=t)n._appendRow(s,m,a);else for(d=0,l=u.length;l>d;d++)n._appendRow(s,m,u[d]);return s}if(void 0!=t)return a;if(s){for(d=0,l=u.length;l>d;d++)s.push(u[d]);return s}return u},o.prototype.getIds=function(t){var e,i,s,n,o,r=this.data,a=t&&t.filter,h=t&&t.order,d=t&&t.convert||this.options.convert,l=[];if(a)if(h){o=[];for(s in r)r.hasOwnProperty(s)&&(n=this._getItem(s,d),a(n)&&o.push(n));for(this._sort(o,h),e=0,i=o.length;i>e;e++)l[e]=o[e][this.fieldId]}else for(s in r)r.hasOwnProperty(s)&&(n=this._getItem(s,d),a(n)&&l.push(n[this.fieldId]));else if(h){o=[];for(s in r)r.hasOwnProperty(s)&&o.push(r[s]);for(this._sort(o,h),e=0,i=o.length;i>e;e++)l[e]=o[e][this.fieldId]}else for(s in r)r.hasOwnProperty(s)&&(n=r[s],l.push(n[this.fieldId]));return l},o.prototype.forEach=function(t,e){var i,s,n=e&&e.filter,o=e&&e.convert||this.options.convert,r=this.data;if(e&&e.order)for(var a=this.get(e),h=0,d=a.length;d>h;h++)i=a[h],s=i[this.fieldId],t(i,s);else for(s in r)r.hasOwnProperty(s)&&(i=this._getItem(s,o),(!n||n(i))&&t(i,s))},o.prototype.map=function(t,e){var i,s=e&&e.filter,n=e&&e.convert||this.options.convert,o=[],r=this.data;for(var a in r)r.hasOwnProperty(a)&&(i=this._getItem(a,n),(!s||s(i))&&o.push(t(i,a)));return e&&e.order&&this._sort(o,e.order),o},o.prototype._filterFields=function(t,e){var i={};for(var s in t)t.hasOwnProperty(s)&&-1!=e.indexOf(s)&&(i[s]=t[s]);return i},o.prototype._sort=function(t,e){if(D.isString(e)){var i=e;t.sort(function(t,e){var s=t[i],n=e[i];return s>n?1:n>s?-1:0})}else{if("function"!=typeof e)throw new TypeError("Order must be a function or a string");t.sort(e)}},o.prototype.remove=function(t,e){var i,s,n,o=[];if(t instanceof Array)for(i=0,s=t.length;s>i;i++)n=this._remove(t[i]),null!=n&&o.push(n);else n=this._remove(t),null!=n&&o.push(n);return o.length&&this._trigger("remove",{items:o},e),o},o.prototype._remove=function(t){if(D.isNumber(t)||D.isString(t)){if(this.data[t])return delete this.data[t],delete this.internalIds[t],t}else if(t instanceof Object){var e=t[this.fieldId];if(e&&this.data[e])return delete this.data[e],delete this.internalIds[e],e}return null},o.prototype.clear=function(t){var e=Object.keys(this.data);return this.data={},this.internalIds={},this._trigger("remove",{items:e},t),e},o.prototype.max=function(t){var e=this.data,i=null,s=null;for(var n in e)if(e.hasOwnProperty(n)){var o=e[n],r=o[t];null!=r&&(!i||r>s)&&(i=o,s=r)}return i},o.prototype.min=function(t){var e=this.data,i=null,s=null;for(var n in e)if(e.hasOwnProperty(n)){var o=e[n],r=o[t];null!=r&&(!i||s>r)&&(i=o,s=r)}return i},o.prototype.distinct=function(t){var e=this.data,i=[],s=this.options.convert[t],n=0;for(var o in e)if(e.hasOwnProperty(o)){for(var r=e[o],a=D.convert(r[t],s),h=!1,d=0;n>d;d++)if(i[d]==a){h=!0;break}h||(i[n]=a,n++)}return i},o.prototype._addItem=function(t){var e=t[this.fieldId];if(void 0!=e){if(this.data[e])throw Error("Cannot add item: item with id "+e+" already exists")}else e=D.randomUUID(),t[this.fieldId]=e,this.internalIds[e]=t;var i={};for(var s in t)if(t.hasOwnProperty(s)){var n=this.convert[s];i[s]=D.convert(t[s],n)}return this.data[e]=i,e},o.prototype._getItem=function(t,e){var i,s,n=this.data[t];if(!n)return null;var o={},r=this.fieldId,a=this.internalIds;if(e)for(i in n)n.hasOwnProperty(i)&&(s=n[i],i==r&&s in a||(o[i]=D.convert(s,e[i])));else for(i in n)n.hasOwnProperty(i)&&(s=n[i],i==r&&s in a||(o[i]=s));return o},o.prototype._updateItem=function(t){var e=t[this.fieldId];if(void 0==e)throw Error("Cannot update item: item has no id (item: "+JSON.stringify(t)+")");var i=this.data[e];if(!i)throw Error("Cannot update item: no item with id "+e+" found");for(var s in t)if(t.hasOwnProperty(s)){var n=this.convert[s];i[s]=D.convert(t[s],n)}return e},o.prototype._getColumnNames=function(t){for(var e=[],i=0,s=t.getNumberOfColumns();s>i;i++)e[i]=t.getColumnId(i)||t.getColumnLabel(i);return e},o.prototype._appendRow=function(t,e,i){for(var s=t.addRow(),n=0,o=e.length;o>n;n++){var r=e[n];t.setValue(s,n,i[r])}},r.prototype.setData=function(t){var e,i,s;if(this.data){this.data.unsubscribe&&this.data.unsubscribe("*",this.listener),e=[];for(var n in this.ids)this.ids.hasOwnProperty(n)&&e.push(n);this.ids={},this._trigger("remove",{items:e})}if(this.data=t,this.data){for(this.fieldId=this.options.fieldId||this.data&&this.data.options&&this.data.options.fieldId||"id",e=this.data.getIds({filter:this.options&&this.options.filter}),i=0,s=e.length;s>i;i++)n=e[i],this.ids[n]=!0;this._trigger("add",{items:e}),this.data.subscribe&&this.data.subscribe("*",this.listener)}},r.prototype.get=function(){var t,e,i,s=this,n=D.getType(arguments[0]);"String"==n||"Number"==n||"Array"==n?(t=arguments[0],e=arguments[1],i=arguments[2]):(e=arguments[0],i=arguments[1]);var o=D.extend({},this.options,e);this.options.filter&&e&&e.filter&&(o.filter=function(t){return s.options.filter(t)&&e.filter(t)});var r=[];return void 0!=t&&r.push(t),r.push(o),r.push(i),this.data&&this.data.get.apply(this.data,r)},r.prototype.getIds=function(t){var e;if(this.data){var i,s=this.options.filter;i=t&&t.filter?s?function(e){return s(e)&&t.filter(e)}:t.filter:s,e=this.data.getIds({filter:i,order:t&&t.order})}else e=[];return e},r.prototype._onEvent=function(t,e,i){var s,n,o,r,a=e&&e.items,h=this.data,d=[],l=[],p=[];if(a&&h){switch(t){case"add":for(s=0,n=a.length;n>s;s++)o=a[s],r=this.get(o),r&&(this.ids[o]=!0,d.push(o));break;case"update":for(s=0,n=a.length;n>s;s++)o=a[s],r=this.get(o),r?this.ids[o]?l.push(o):(this.ids[o]=!0,d.push(o)):this.ids[o]&&(delete this.ids[o],p.push(o));break;case"remove":for(s=0,n=a.length;n>s;s++)o=a[s],this.ids[o]&&(delete this.ids[o],p.push(o))}d.length&&this._trigger("add",{items:d},i),l.length&&this._trigger("update",{items:l},i),p.length&&this._trigger("remove",{items:p},i)}},r.prototype.subscribe=o.prototype.subscribe,r.prototype.unsubscribe=o.prototype.unsubscribe,r.prototype._trigger=o.prototype._trigger,TimeStep=function(t,e,i){this.current=new Date,this._start=new Date,this._end=new Date,this.autoScale=!0,this.scale=TimeStep.SCALE.DAY,this.step=1,this.setRange(t,e,i)},TimeStep.SCALE={MILLISECOND:1,SECOND:2,MINUTE:3,HOUR:4,DAY:5,WEEKDAY:6,MONTH:7,YEAR:8},TimeStep.prototype.setRange=function(t,e,i){t instanceof Date&&e instanceof Date&&(this._start=void 0!=t?new Date(t.valueOf()):new Date,this._end=void 0!=e?new Date(e.valueOf()):new Date,this.autoScale&&this.setMinimumStep(i))},TimeStep.prototype.first=function(){this.current=new Date(this._start.valueOf()),this.roundToMinor()},TimeStep.prototype.roundToMinor=function(){switch(this.scale){case TimeStep.SCALE.YEAR:this.current.setFullYear(this.step*Math.floor(this.current.getFullYear()/this.step)),this.current.setMonth(0);case TimeStep.SCALE.MONTH:this.current.setDate(1);case TimeStep.SCALE.DAY:case TimeStep.SCALE.WEEKDAY:this.current.setHours(0);case TimeStep.SCALE.HOUR:this.current.setMinutes(0);case TimeStep.SCALE.MINUTE:this.current.setSeconds(0);case TimeStep.SCALE.SECOND:this.current.setMilliseconds(0)}if(1!=this.step)switch(this.scale){case TimeStep.SCALE.MILLISECOND:this.current.setMilliseconds(this.current.getMilliseconds()-this.current.getMilliseconds()%this.step);break;case TimeStep.SCALE.SECOND:this.current.setSeconds(this.current.getSeconds()-this.current.getSeconds()%this.step);break;case TimeStep.SCALE.MINUTE:this.current.setMinutes(this.current.getMinutes()-this.current.getMinutes()%this.step);break;case TimeStep.SCALE.HOUR:this.current.setHours(this.current.getHours()-this.current.getHours()%this.step);break;case TimeStep.SCALE.WEEKDAY:case TimeStep.SCALE.DAY:this.current.setDate(this.current.getDate()-1-(this.current.getDate()-1)%this.step+1);break;case TimeStep.SCALE.MONTH:this.current.setMonth(this.current.getMonth()-this.current.getMonth()%this.step);break;case TimeStep.SCALE.YEAR:this.current.setFullYear(this.current.getFullYear()-this.current.getFullYear()%this.step);break;default:}},TimeStep.prototype.hasNext=function(){return this.current.valueOf()<=this._end.valueOf()},TimeStep.prototype.next=function(){var t=this.current.valueOf();if(6>this.current.getMonth())switch(this.scale){case TimeStep.SCALE.MILLISECOND:this.current=new Date(this.current.valueOf()+this.step);break;case TimeStep.SCALE.SECOND:this.current=new Date(this.current.valueOf()+1e3*this.step);break;case TimeStep.SCALE.MINUTE:this.current=new Date(this.current.valueOf()+60*1e3*this.step);break;case TimeStep.SCALE.HOUR:this.current=new Date(this.current.valueOf()+60*60*1e3*this.step);var e=this.current.getHours();this.current.setHours(e-e%this.step);break;case TimeStep.SCALE.WEEKDAY:case TimeStep.SCALE.DAY:this.current.setDate(this.current.getDate()+this.step);break;case TimeStep.SCALE.MONTH:this.current.setMonth(this.current.getMonth()+this.step);break;case TimeStep.SCALE.YEAR:this.current.setFullYear(this.current.getFullYear()+this.step);break;default:}else switch(this.scale){case TimeStep.SCALE.MILLISECOND:this.current=new Date(this.current.valueOf()+this.step);break;case TimeStep.SCALE.SECOND:this.current.setSeconds(this.current.getSeconds()+this.step);break;case TimeStep.SCALE.MINUTE:this.current.setMinutes(this.current.getMinutes()+this.step);break;case TimeStep.SCALE.HOUR:this.current.setHours(this.current.getHours()+this.step);break;case TimeStep.SCALE.WEEKDAY:case TimeStep.SCALE.DAY:this.current.setDate(this.current.getDate()+this.step);break;case TimeStep.SCALE.MONTH:this.current.setMonth(this.current.getMonth()+this.step);break;case TimeStep.SCALE.YEAR:this.current.setFullYear(this.current.getFullYear()+this.step);break;default:}if(1!=this.step)switch(this.scale){case TimeStep.SCALE.MILLISECOND:this.current.getMilliseconds()0&&(this.step=e),this.autoScale=!1},TimeStep.prototype.setAutoScale=function(t){this.autoScale=t},TimeStep.prototype.setMinimumStep=function(t){if(void 0!=t){var e=31104e6,i=2592e6,s=864e5,n=36e5,o=6e4,r=1e3,a=1;1e3*e>t&&(this.scale=TimeStep.SCALE.YEAR,this.step=1e3),500*e>t&&(this.scale=TimeStep.SCALE.YEAR,this.step=500),100*e>t&&(this.scale=TimeStep.SCALE.YEAR,this.step=100),50*e>t&&(this.scale=TimeStep.SCALE.YEAR,this.step=50),10*e>t&&(this.scale=TimeStep.SCALE.YEAR,this.step=10),5*e>t&&(this.scale=TimeStep.SCALE.YEAR,this.step=5),e>t&&(this.scale=TimeStep.SCALE.YEAR,this.step=1),3*i>t&&(this.scale=TimeStep.SCALE.MONTH,this.step=3),i>t&&(this.scale=TimeStep.SCALE.MONTH,this.step=1),5*s>t&&(this.scale=TimeStep.SCALE.DAY,this.step=5),2*s>t&&(this.scale=TimeStep.SCALE.DAY,this.step=2),s>t&&(this.scale=TimeStep.SCALE.DAY,this.step=1),s/2>t&&(this.scale=TimeStep.SCALE.WEEKDAY,this.step=1),4*n>t&&(this.scale=TimeStep.SCALE.HOUR,this.step=4),n>t&&(this.scale=TimeStep.SCALE.HOUR,this.step=1),15*o>t&&(this.scale=TimeStep.SCALE.MINUTE,this.step=15),10*o>t&&(this.scale=TimeStep.SCALE.MINUTE,this.step=10),5*o>t&&(this.scale=TimeStep.SCALE.MINUTE,this.step=5),o>t&&(this.scale=TimeStep.SCALE.MINUTE,this.step=1),15*r>t&&(this.scale=TimeStep.SCALE.SECOND,this.step=15),10*r>t&&(this.scale=TimeStep.SCALE.SECOND,this.step=10),5*r>t&&(this.scale=TimeStep.SCALE.SECOND,this.step=5),r>t&&(this.scale=TimeStep.SCALE.SECOND,this.step=1),200*a>t&&(this.scale=TimeStep.SCALE.MILLISECOND,this.step=200),100*a>t&&(this.scale=TimeStep.SCALE.MILLISECOND,this.step=100),50*a>t&&(this.scale=TimeStep.SCALE.MILLISECOND,this.step=50),10*a>t&&(this.scale=TimeStep.SCALE.MILLISECOND,this.step=10),5*a>t&&(this.scale=TimeStep.SCALE.MILLISECOND,this.step=5),a>t&&(this.scale=TimeStep.SCALE.MILLISECOND,this.step=1) -}},TimeStep.prototype.snap=function(t){if(this.scale==TimeStep.SCALE.YEAR){var e=t.getFullYear()+Math.round(t.getMonth()/12);t.setFullYear(Math.round(e/this.step)*this.step),t.setMonth(0),t.setDate(0),t.setHours(0),t.setMinutes(0),t.setSeconds(0),t.setMilliseconds(0)}else if(this.scale==TimeStep.SCALE.MONTH)t.getDate()>15?(t.setDate(1),t.setMonth(t.getMonth()+1)):t.setDate(1),t.setHours(0),t.setMinutes(0),t.setSeconds(0),t.setMilliseconds(0);else if(this.scale==TimeStep.SCALE.DAY||this.scale==TimeStep.SCALE.WEEKDAY){switch(this.step){case 5:case 2:t.setHours(24*Math.round(t.getHours()/24));break;default:t.setHours(12*Math.round(t.getHours()/12))}t.setMinutes(0),t.setSeconds(0),t.setMilliseconds(0)}else if(this.scale==TimeStep.SCALE.HOUR){switch(this.step){case 4:t.setMinutes(60*Math.round(t.getMinutes()/60));break;default:t.setMinutes(30*Math.round(t.getMinutes()/30))}t.setSeconds(0),t.setMilliseconds(0)}else if(this.scale==TimeStep.SCALE.MINUTE){switch(this.step){case 15:case 10:t.setMinutes(5*Math.round(t.getMinutes()/5)),t.setSeconds(0);break;case 5:t.setSeconds(60*Math.round(t.getSeconds()/60));break;default:t.setSeconds(30*Math.round(t.getSeconds()/30))}t.setMilliseconds(0)}else if(this.scale==TimeStep.SCALE.SECOND)switch(this.step){case 15:case 10:t.setSeconds(5*Math.round(t.getSeconds()/5)),t.setMilliseconds(0);break;case 5:t.setMilliseconds(1e3*Math.round(t.getMilliseconds()/1e3));break;default:t.setMilliseconds(500*Math.round(t.getMilliseconds()/500))}else if(this.scale==TimeStep.SCALE.MILLISECOND){var i=this.step>5?this.step/2:1;t.setMilliseconds(Math.round(t.getMilliseconds()/i)*i)}},TimeStep.prototype.isMajor=function(){switch(this.scale){case TimeStep.SCALE.MILLISECOND:return 0==this.current.getMilliseconds();case TimeStep.SCALE.SECOND:return 0==this.current.getSeconds();case TimeStep.SCALE.MINUTE:return 0==this.current.getHours()&&0==this.current.getMinutes();case TimeStep.SCALE.HOUR:return 0==this.current.getHours();case TimeStep.SCALE.WEEKDAY:case TimeStep.SCALE.DAY:return 1==this.current.getDate();case TimeStep.SCALE.MONTH:return 0==this.current.getMonth();case TimeStep.SCALE.YEAR:return!1;default:return!1}},TimeStep.prototype.getLabelMinor=function(t){switch(void 0==t&&(t=this.current),this.scale){case TimeStep.SCALE.MILLISECOND:return E(t).format("SSS");case TimeStep.SCALE.SECOND:return E(t).format("s");case TimeStep.SCALE.MINUTE:return E(t).format("HH:mm");case TimeStep.SCALE.HOUR:return E(t).format("HH:mm");case TimeStep.SCALE.WEEKDAY:return E(t).format("ddd D");case TimeStep.SCALE.DAY:return E(t).format("D");case TimeStep.SCALE.MONTH:return E(t).format("MMM");case TimeStep.SCALE.YEAR:return E(t).format("YYYY");default:return""}},TimeStep.prototype.getLabelMajor=function(t){switch(void 0==t&&(t=this.current),this.scale){case TimeStep.SCALE.MILLISECOND:return E(t).format("HH:mm:ss");case TimeStep.SCALE.SECOND:return E(t).format("D MMMM HH:mm");case TimeStep.SCALE.MINUTE:case TimeStep.SCALE.HOUR:return E(t).format("ddd D MMMM");case TimeStep.SCALE.WEEKDAY:case TimeStep.SCALE.DAY:return E(t).format("MMMM YYYY");case TimeStep.SCALE.MONTH:return E(t).format("YYYY");case TimeStep.SCALE.YEAR:return"";default:return""}},a.prototype.setOptions=function(t){D.extend(this.options,t)},a.prototype.update=function(){this._order(),this._stack()},a.prototype._order=function(){var t=this.parent.items;if(!t)throw Error("Cannot stack items: parent does not contain items");var e=[],i=0;D.forEach(t,function(t){t.visible&&(e[i]=t,i++)});var s=this.options.order||this.defaultOptions.order;if("function"!=typeof s)throw Error("Option order must be a function");e.sort(s),this.ordered=e},a.prototype._stack=function(){var t,e,i,s=this.ordered,n=this.options,o=n.orientation||this.defaultOptions.orientation,r="top"==o;for(i=n.margin&&void 0!==n.margin.item?n.margin.item:this.defaultOptions.margin.item,t=0,e=s.length;e>t;t++){var a=s[t],h=null;do h=this.checkOverlap(s,t,0,t-1,i),null!=h&&(a.top=r?h.top+h.height+i:h.top-a.height-i);while(h)}},a.prototype.checkOverlap=function(t,e,i,s,n){for(var o=this.collision,r=t[e],a=s;a>=i;a--){var h=t[a];if(o(r,h,n)&&a!=e)return h}return null},a.prototype.collision=function(t,e,i){return t.left-ie.left&&t.top-ie.top},h.prototype.setOptions=function(t){D.extend(this.options,t),(null!=t.start||null!=t.end)&&this.setRange(t.start,t.end)},h.prototype.subscribe=function(t,e,i){var s,n=this;if("horizontal"!=i&&"vertical"!=i)throw new TypeError('Unknown direction "'+i+'". '+'Choose "horizontal" or "vertical".');if("move"==e)s={component:t,event:e,direction:i,callback:function(t){n._onMouseDown(t,s)},params:{}},t.on("mousedown",s.callback),n.listeners.push(s);else{if("zoom"!=e)throw new TypeError('Unknown event "'+e+'". '+'Choose "move" or "zoom".');s={component:t,event:e,direction:i,callback:function(t){n._onMouseWheel(t,s)},params:{}},t.on("mousewheel",s.callback),n.listeners.push(s)}},h.prototype.on=function(t,e){O.addListener(this,t,e)},h.prototype._trigger=function(t){O.trigger(this,t,{start:this.start,end:this.end})},h.prototype.setRange=function(t,e){var i=this._applyRange(t,e);i&&(this._trigger("rangechange"),this._trigger("rangechanged"))},h.prototype._applyRange=function(t,e){var i,s=null!=t?D.convert(t,"Number"):this.start,n=null!=e?D.convert(e,"Number"):this.end;if(isNaN(s))throw Error('Invalid start "'+t+'"');if(isNaN(n))throw Error('Invalid end "'+e+'"');if(s>n&&(n=s),null!=this.options.min){var o=this.options.min.valueOf();o>s&&(i=o-s,s+=i,n+=i)}if(null!=this.options.max){var r=this.options.max.valueOf();n>r&&(i=n-r,s-=i,n-=i)}if(null!=this.options.zoomMin){var a=this.options.zoomMin.valueOf();0>a&&(a=0),a>n-s&&(this.end-this.start>a?(i=a-(n-s),s-=i/2,n+=i/2):(s=this.start,n=this.end))}if(null!=this.options.zoomMax){var h=this.options.zoomMax.valueOf();0>h&&(h=0),n-s>h&&(h>this.end-this.start?(i=n-s-h,s+=i/2,n-=i/2):(s=this.start,n=this.end))}var d=this.start!=s||this.end!=n;return this.start=s,this.end=n,d},h.prototype.getRange=function(){return{start:this.start,end:this.end}},h.prototype.conversion=function(t){return this.start,this.end,h.conversion(this.start,this.end,t)},h.conversion=function(t,e,i){return 0!=i&&0!=e-t?{offset:t,factor:i/(e-t)}:{offset:0,factor:1}},h.prototype._onMouseDown=function(t,e){t=t||window.event;var i=e.params,s=t.which?1==t.which:1==t.button;if(s){i.mouseX=D.getPageX(t),i.mouseY=D.getPageY(t),i.previousLeft=0,i.previousOffset=0,i.moved=!1,i.start=this.start,i.end=this.end;var n=e.component.frame;n&&(n.style.cursor="move");var o=this;i.onMouseMove||(i.onMouseMove=function(t){o._onMouseMove(t,e)},D.addEventListener(document,"mousemove",i.onMouseMove)),i.onMouseUp||(i.onMouseUp=function(t){o._onMouseUp(t,e)},D.addEventListener(document,"mouseup",i.onMouseUp)),D.preventDefault(t)}},h.prototype._onMouseMove=function(t,e){t=t||window.event;var i=e.params,s=D.getPageX(t),n=D.getPageY(t);void 0==i.mouseX&&(i.mouseX=s),void 0==i.mouseY&&(i.mouseY=n);var o=s-i.mouseX,r=n-i.mouseY,a="horizontal"==e.direction?o:r;Math.abs(a)>=1&&(i.moved=!0);var h=i.end-i.start,d="horizontal"==e.direction?e.component.width:e.component.height,l=-a/d*h;this._applyRange(i.start+l,i.end+l),this._trigger("rangechange"),D.preventDefault(t)},h.prototype._onMouseUp=function(t,e){t=t||window.event;var i=e.params;e.component.frame&&(e.component.frame.style.cursor="auto"),i.onMouseMove&&(D.removeEventListener(document,"mousemove",i.onMouseMove),i.onMouseMove=null),i.onMouseUp&&(D.removeEventListener(document,"mouseup",i.onMouseUp),i.onMouseUp=null),i.moved&&this._trigger("rangechanged")},h.prototype._onMouseWheel=function(t,e){t=t||window.event;var i=0;if(t.wheelDelta?i=t.wheelDelta/120:t.detail&&(i=-t.detail/3),i){var s=this,n=function(){var n=i/5,o=null,r=e.component.frame;if(r){var a,h;if("horizontal"==e.direction){a=e.component.width,h=s.conversion(a);var d=D.getAbsoluteLeft(r),l=D.getPageX(t);o=(l-d)/h.factor+h.offset}else{a=e.component.height,h=s.conversion(a);var p=D.getAbsoluteTop(r),c=D.getPageY(t);o=(p+a-c-p)/h.factor+h.offset}}s.zoom(n,o)};n()}D.preventDefault(t)},h.prototype.zoom=function(t,e){null==e&&(e=(this.start+this.end)/2),t>=1&&(t=.9),-1>=t&&(t=-.9),0>t&&(t/=1+t);var i=this.start-e,s=this.end-e,n=this.start-i*t,o=this.end-s*t;this.setRange(n,o)},h.prototype.move=function(t){var e=this.end-this.start,i=this.start+e*t,s=this.end+e*t;this.start=i,this.end=s},h.prototype.moveTo=function(t){var e=(this.start+this.end)/2,i=e-t,s=this.start-i,n=this.end-i;this.setRange(s,n)},d.prototype.add=function(t){if(void 0==t.id)throw Error("Component has no field id");if(!(t instanceof l||t instanceof d))throw new TypeError("Component must be an instance of prototype Component or Controller");t.controller=this,this.components[t.id]=t},d.prototype.remove=function(t){var e;for(e in this.components)if(this.components.hasOwnProperty(e)&&(e==t||this.components[e]==t))break;e&&delete this.components[e]},d.prototype.requestReflow=function(t){if(t)this.reflow();else if(!this.reflowTimer){var e=this;this.reflowTimer=setTimeout(function(){e.reflowTimer=void 0,e.reflow()},0)}},d.prototype.requestRepaint=function(t){if(t)this.repaint();else if(!this.repaintTimer){var e=this;this.repaintTimer=setTimeout(function(){e.repaintTimer=void 0,e.repaint()},0)}},d.prototype.repaint=function(){function t(s,n){n in i||(s.depends&&s.depends.forEach(function(e){t(e,e.id)}),s.parent&&t(s.parent,s.parent.id),e=s.repaint()||e,i[n]=!0)}var e=!1;this.repaintTimer&&(clearTimeout(this.repaintTimer),this.repaintTimer=void 0);var i={};D.forEach(this.components,t),e&&this.reflow()},d.prototype.reflow=function(){function t(s,n){n in i||(s.depends&&s.depends.forEach(function(e){t(e,e.id)}),s.parent&&t(s.parent,s.parent.id),e=s.reflow()||e,i[n]=!0)}var e=!1;this.reflowTimer&&(clearTimeout(this.reflowTimer),this.reflowTimer=void 0);var i={};D.forEach(this.components,t),e&&this.repaint()},l.prototype.setOptions=function(t){t&&(D.extend(this.options,t),this.controller&&(this.requestRepaint(),this.requestReflow()))},l.prototype.getOption=function(t){var e;return this.options&&(e=this.options[t]),void 0===e&&this.defaultOptions&&(e=this.defaultOptions[t]),e},l.prototype.getContainer=function(){return null},l.prototype.getFrame=function(){return this.frame},l.prototype.repaint=function(){return!1},l.prototype.reflow=function(){return!1},l.prototype.hide=function(){return this.frame&&this.frame.parentNode?(this.frame.parentNode.removeChild(this.frame),!0):!1},l.prototype.show=function(){return this.frame&&this.frame.parentNode?!1:this.repaint()},l.prototype.requestRepaint=function(){if(!this.controller)throw Error("Cannot request a repaint: no controller configured");this.controller.requestRepaint()},l.prototype.requestReflow=function(){if(!this.controller)throw Error("Cannot request a reflow: no controller configured");this.controller.requestReflow()},p.prototype=new l,p.prototype.setOptions=l.prototype.setOptions,p.prototype.getContainer=function(){return this.frame},p.prototype.repaint=function(){var t=0,e=D.updateProperty,i=D.option.asSize,s=this.options,n=this.frame;if(!n){n=document.createElement("div"),n.className="panel";var o=s.className;o&&("function"==typeof o?D.addClassName(n,o()+""):D.addClassName(n,o+"")),this.frame=n,t+=1}if(!n.parentNode){if(!this.parent)throw Error("Cannot repaint panel: no parent attached");var r=this.parent.getContainer();if(!r)throw Error("Cannot repaint panel: parent has no container element");r.appendChild(n),t+=1}return t+=e(n.style,"top",i(s.top,"0px")),t+=e(n.style,"left",i(s.left,"0px")),t+=e(n.style,"width",i(s.width,"100%")),t+=e(n.style,"height",i(s.height,"100%")),t>0},p.prototype.reflow=function(){var t=0,e=D.updateProperty,i=this.frame;return i?(t+=e(this,"top",i.offsetTop),t+=e(this,"left",i.offsetLeft),t+=e(this,"width",i.offsetWidth),t+=e(this,"height",i.offsetHeight)):t+=1,t>0},c.prototype=new p,c.prototype.setOptions=l.prototype.setOptions,c.prototype.repaint=function(){var t=0,e=D.updateProperty,i=D.option.asSize,s=this.options,n=this.frame;if(!n){n=document.createElement("div"),n.className="vis timeline rootpanel";var o=s.className;o&&D.addClassName(n,D.option.asString(o)),this.frame=n,t+=1}if(!n.parentNode){if(!this.container)throw Error("Cannot repaint root panel: no container attached");this.container.appendChild(n),t+=1}return t+=e(n.style,"top",i(s.top,"0px")),t+=e(n.style,"left",i(s.left,"0px")),t+=e(n.style,"width",i(s.width,"100%")),t+=e(n.style,"height",i(s.height,"100%")),this._updateEventEmitters(),this._updateWatch(),t>0},c.prototype.reflow=function(){var t=0,e=D.updateProperty,i=this.frame;return i?(t+=e(this,"top",i.offsetTop),t+=e(this,"left",i.offsetLeft),t+=e(this,"width",i.offsetWidth),t+=e(this,"height",i.offsetHeight)):t+=1,t>0},c.prototype._updateWatch=function(){var t=this.getOption("autoResize");t?this._watch():this._unwatch()},c.prototype._watch=function(){var t=this;this._unwatch();var e=function(){var e=t.getOption("autoResize");return e?(t.frame&&(t.frame.clientWidth!=t.width||t.frame.clientHeight!=t.height)&&t.requestReflow(),void 0):(t._unwatch(),void 0)};D.addEventListener(window,"resize",e),this.watchTimer=setInterval(e,1e3)},c.prototype._unwatch=function(){this.watchTimer&&(clearInterval(this.watchTimer),this.watchTimer=void 0)},c.prototype.on=function(t,e){var i=this.listeners[t];i||(i=[],this.listeners[t]=i),i.push(e),this._updateEventEmitters()},c.prototype._updateEventEmitters=function(){if(this.listeners){var t=this;D.forEach(this.listeners,function(e,i){if(t.emitters||(t.emitters={}),!(i in t.emitters)){var s=t.frame;if(s){var n=function(t){e.forEach(function(e){e(t)})};t.emitters[i]=n,D.addEventListener(s,i,n)}}})}},u.prototype=new l,u.prototype.setOptions=l.prototype.setOptions,u.prototype.setRange=function(t){if(!(t instanceof h||t&&t.start&&t.end))throw new TypeError("Range must be an instance of Range, or an object containing start and end.");this.range=t},u.prototype.toTime=function(t){var e=this.conversion;return new Date(t/e.factor+e.offset)},u.prototype.toScreen=function(t){var e=this.conversion;return(t.valueOf()-e.offset)*e.factor},u.prototype.repaint=function(){var t=0,e=D.updateProperty,i=D.option.asSize,s=this.options,n=this.getOption("orientation"),o=this.props,r=this.step,a=this.frame;if(a||(a=document.createElement("div"),this.frame=a,t+=1),a.className="axis "+n,!a.parentNode){if(!this.parent)throw Error("Cannot repaint time axis: no parent attached");var h=this.parent.getContainer();if(!h)throw Error("Cannot repaint time axis: parent has no container element");h.appendChild(a),t+=1}var d=a.parentNode;if(d){var l=a.nextSibling;d.removeChild(a);var p="bottom"==n&&this.props.parentHeight&&this.height?this.props.parentHeight-this.height+"px":"0px";if(t+=e(a.style,"top",i(s.top,p)),t+=e(a.style,"left",i(s.left,"0px")),t+=e(a.style,"width",i(s.width,"100%")),t+=e(a.style,"height",i(s.height,this.height+"px")),this._repaintMeasureChars(),this.step){this._repaintStart(),r.first();for(var c=void 0,u=0;r.hasNext()&&1e3>u;){u++;var f=r.getCurrent(),m=this.toScreen(f),g=r.isMajor();this.getOption("showMinorLabels")&&this._repaintMinorText(m,r.getLabelMinor()),g&&this.getOption("showMajorLabels")?(m>0&&(void 0==c&&(c=m),this._repaintMajorText(m,r.getLabelMajor())),this._repaintMajorLine(m)):this._repaintMinorLine(m),r.next()}if(this.getOption("showMajorLabels")){var v=this.toTime(0),y=r.getLabelMajor(v),b=y.length*(o.majorCharWidth||10)+10;(void 0==c||c>b)&&this._repaintMajorText(0,y)}this._repaintEnd()}this._repaintLine(),l?d.insertBefore(a,l):d.appendChild(a)}return t>0},u.prototype._repaintStart=function(){var t=this.dom,e=t.redundant;e.majorLines=t.majorLines,e.majorTexts=t.majorTexts,e.minorLines=t.minorLines,e.minorTexts=t.minorTexts,t.majorLines=[],t.majorTexts=[],t.minorLines=[],t.minorTexts=[]},u.prototype._repaintEnd=function(){D.forEach(this.dom.redundant,function(t){for(;t.length;){var e=t.pop();e&&e.parentNode&&e.parentNode.removeChild(e)}})},u.prototype._repaintMinorText=function(t,e){var i=this.dom.redundant.minorTexts.shift();if(!i){var s=document.createTextNode("");i=document.createElement("div"),i.appendChild(s),i.className="text minor",this.frame.appendChild(i)}this.dom.minorTexts.push(i),i.childNodes[0].nodeValue=e,i.style.left=t+"px",i.style.top=this.props.minorLabelTop+"px"},u.prototype._repaintMajorText=function(t,e){var i=this.dom.redundant.majorTexts.shift();if(!i){var s=document.createTextNode(e);i=document.createElement("div"),i.className="text major",i.appendChild(s),this.frame.appendChild(i)}this.dom.majorTexts.push(i),i.childNodes[0].nodeValue=e,i.style.top=this.props.majorLabelTop+"px",i.style.left=t+"px"},u.prototype._repaintMinorLine=function(t){var e=this.dom.redundant.minorLines.shift();e||(e=document.createElement("div"),e.className="grid vertical minor",this.frame.appendChild(e)),this.dom.minorLines.push(e);var i=this.props;e.style.top=i.minorLineTop+"px",e.style.height=i.minorLineHeight+"px",e.style.left=t-i.minorLineWidth/2+"px"},u.prototype._repaintMajorLine=function(t){var e=this.dom.redundant.majorLines.shift();e||(e=document.createElement("DIV"),e.className="grid vertical major",this.frame.appendChild(e)),this.dom.majorLines.push(e);var i=this.props;e.style.top=i.majorLineTop+"px",e.style.left=t-i.majorLineWidth/2+"px",e.style.height=i.majorLineHeight+"px"},u.prototype._repaintLine=function(){var t=this.dom.line,e=this.frame;this.options,this.getOption("showMinorLabels")||this.getOption("showMajorLabels")?(t?(e.removeChild(t),e.appendChild(t)):(t=document.createElement("div"),t.className="grid horizontal major",e.appendChild(t),this.dom.line=t),t.style.top=this.props.lineTop+"px"):t&&axis.parentElement&&(e.removeChild(axis.line),delete this.dom.line)},u.prototype._repaintMeasureChars=function(){var t,e=this.dom;if(!e.measureCharMinor){t=document.createTextNode("0");var i=document.createElement("DIV");i.className="text minor measure",i.appendChild(t),this.frame.appendChild(i),e.measureCharMinor=i}if(!e.measureCharMajor){t=document.createTextNode("0");var s=document.createElement("DIV");s.className="text major measure",s.appendChild(t),this.frame.appendChild(s),e.measureCharMajor=s}},u.prototype.reflow=function(){var t=0,e=D.updateProperty,i=this.frame,s=this.range;if(!s)throw Error("Cannot repaint time axis: no range configured");if(i){t+=e(this,"top",i.offsetTop),t+=e(this,"left",i.offsetLeft);var n=this.props,o=this.getOption("showMinorLabels"),r=this.getOption("showMajorLabels"),a=this.dom.measureCharMinor,h=this.dom.measureCharMajor;a&&(n.minorCharHeight=a.clientHeight,n.minorCharWidth=a.clientWidth),h&&(n.majorCharHeight=h.clientHeight,n.majorCharWidth=h.clientWidth);var d=i.parentNode?i.parentNode.offsetHeight:0;switch(d!=n.parentHeight&&(n.parentHeight=d,t+=1),this.getOption("orientation")){case"bottom":n.minorLabelHeight=o?n.minorCharHeight:0,n.majorLabelHeight=r?n.majorCharHeight:0,n.minorLabelTop=0,n.majorLabelTop=n.minorLabelTop+n.minorLabelHeight,n.minorLineTop=-this.top,n.minorLineHeight=Math.max(this.top+n.majorLabelHeight,0),n.minorLineWidth=1,n.majorLineTop=-this.top,n.majorLineHeight=Math.max(this.top+n.minorLabelHeight+n.majorLabelHeight,0),n.majorLineWidth=1,n.lineTop=0;break;case"top":n.minorLabelHeight=o?n.minorCharHeight:0,n.majorLabelHeight=r?n.majorCharHeight:0,n.majorLabelTop=0,n.minorLabelTop=n.majorLabelTop+n.majorLabelHeight,n.minorLineTop=n.minorLabelTop,n.minorLineHeight=Math.max(d-n.majorLabelHeight-this.top),n.minorLineWidth=1,n.majorLineTop=0,n.majorLineHeight=Math.max(d-this.top),n.majorLineWidth=1,n.lineTop=n.majorLabelHeight+n.minorLabelHeight;break;default:throw Error('Unkown orientation "'+this.getOption("orientation")+'"')}var l=n.minorLabelHeight+n.majorLabelHeight;t+=e(this,"width",i.offsetWidth),t+=e(this,"height",l),this._updateConversion();var p=D.convert(s.start,"Date"),c=D.convert(s.end,"Date"),u=this.toTime(5*(n.minorCharWidth||10))-this.toTime(0);this.step=new TimeStep(p,c,u),t+=e(n.range,"start",p.valueOf()),t+=e(n.range,"end",c.valueOf()),t+=e(n.range,"minimumStep",u.valueOf())}return t>0},u.prototype._updateConversion=function(){var t=this.range;if(!t)throw Error("No range configured");this.conversion=t.conversion?t.conversion(this.width):h.conversion(t.start,t.end,this.width)},f.prototype=new p,f.types={box:g,range:y,point:v},f.prototype.setOptions=l.prototype.setOptions,f.prototype.setRange=function(t){if(!(t instanceof h||t&&t.start&&t.end))throw new TypeError("Range must be an instance of Range, or an object containing start and end.");this.range=t},f.prototype.repaint=function(){var t=0,e=D.updateProperty,i=D.option.asSize,s=this.options,n=this.getOption("orientation"),o=this.defaultOptions,r=this.frame;if(!r){r=document.createElement("div"),r.className="itemset";var a=s.className;a&&D.addClassName(r,D.option.asString(a));var h=document.createElement("div");h.className="background",r.appendChild(h),this.dom.background=h;var d=document.createElement("div");d.className="foreground",r.appendChild(d),this.dom.foreground=d;var l=document.createElement("div");l.className="itemset-axis",this.dom.axis=l,this.frame=r,t+=1}if(!this.parent)throw Error("Cannot repaint itemset: no parent attached");var p=this.parent.getContainer();if(!p)throw Error("Cannot repaint itemset: parent has no container element");r.parentNode||(p.appendChild(r),t+=1),this.dom.axis.parentNode||(p.appendChild(this.dom.axis),t+=1),t+=e(r.style,"left",i(s.left,"0px")),t+=e(r.style,"top",i(s.top,"0px")),t+=e(r.style,"width",i(s.width,"100%")),t+=e(r.style,"height",i(s.height,this.height+"px")),t+=e(this.dom.axis.style,"left",i(s.left,"0px")),t+=e(this.dom.axis.style,"width",i(s.width,"100%")),t+="bottom"==n?e(this.dom.axis.style,"top",this.height+this.top+"px"):e(this.dom.axis.style,"top",this.top+"px"),this._updateConversion();var c=this,u=this.queue,m=this.itemsData,g=this.items,v={};return Object.keys(u).forEach(function(e){var i=u[e],n=g[e];switch(i){case"add":case"update":var r=m&&m.get(e,v);if(r){var a=r.type||r.start&&r.end&&"range"||s.type||"box",h=f.types[a];if(n&&(h&&n instanceof h?(n.data=r,t++):(t+=n.hide(),n=null)),!n){if(!h)throw new TypeError('Unknown item type "'+a+'"');n=new h(c,r,s,o),t++}n.repaint(),g[e]=n}delete u[e];break;case"remove":n&&(t+=n.hide()),delete g[e],delete u[e];break;default:console.log('Error: unknown action "'+i+'"')}}),D.forEach(this.items,function(e){e.visible?(t+=e.show(),e.reposition()):t+=e.hide()}),t>0},f.prototype.getForeground=function(){return this.dom.foreground},f.prototype.getBackground=function(){return this.dom.background},f.prototype.getAxis=function(){return this.dom.axis},f.prototype.reflow=function(){var t=0,e=this.options,i=e.margin&&e.margin.axis||this.defaultOptions.margin.axis,s=e.margin&&e.margin.item||this.defaultOptions.margin.item,n=D.updateProperty,o=D.option.asNumber,r=D.option.asSize,a=this.frame;if(a){this._updateConversion(),D.forEach(this.items,function(e){t+=e.reflow()}),this.stack.update();var h,d=o(e.maxHeight),l=null!=r(e.height);if(l)h=a.offsetHeight;else{var p=this.stack.ordered;if(p.length){var c=p[0].top,u=p[0].top+p[0].height;D.forEach(p,function(t){c=Math.min(c,t.top),u=Math.max(u,t.top+t.height)}),h=u-c+i+s}else h=i+s}null!=d&&(h=Math.min(h,d)),t+=n(this,"height",h),t+=n(this,"top",a.offsetTop),t+=n(this,"left",a.offsetLeft),t+=n(this,"width",a.offsetWidth)}else t+=1;return t>0},f.prototype.hide=function(){var t=!1;return this.frame&&this.frame.parentNode&&(this.frame.parentNode.removeChild(this.frame),t=!0),this.dom.axis&&this.dom.axis.parentNode&&(this.dom.axis.parentNode.removeChild(this.dom.axis),t=!0),t},f.prototype.setItems=function(t){var e,i=this,s=this.itemsData;if(t){if(!(t instanceof o||t instanceof r))throw new TypeError("Data must be an instance of DataSet");this.itemsData=t}else this.itemsData=null;if(s&&(D.forEach(this.listeners,function(t,e){s.unsubscribe(e,t)}),e=s.getIds(),this._onRemove(e)),this.itemsData){var n=this.id;D.forEach(this.listeners,function(t,e){i.itemsData.subscribe(e,t,n)}),e=this.itemsData.getIds(),this._onAdd(e)}},f.prototype.getItems=function(){return this.itemsData},f.prototype._onUpdate=function(t){this._toQueue("update",t)},f.prototype._onAdd=function(t){this._toQueue("add",t)},f.prototype._onRemove=function(t){this._toQueue("remove",t)},f.prototype._toQueue=function(t,e){var i=this.queue;e.forEach(function(e){i[e]=t}),this.controller&&this.requestRepaint()},f.prototype._updateConversion=function(){var t=this.range;if(!t)throw Error("No range configured");this.conversion=t.conversion?t.conversion(this.width):h.conversion(t.start,t.end,this.width)},f.prototype.toTime=function(t){var e=this.conversion;return new Date(t/e.factor+e.offset)},f.prototype.toScreen=function(t){var e=this.conversion;return(t.valueOf()-e.offset)*e.factor},m.prototype.select=function(){this.selected=!0},m.prototype.unselect=function(){this.selected=!1},m.prototype.show=function(){return!1},m.prototype.hide=function(){return!1},m.prototype.repaint=function(){return!1},m.prototype.reflow=function(){return!1},g.prototype=new m(null,null),g.prototype.select=function(){this.selected=!0},g.prototype.unselect=function(){this.selected=!1},g.prototype.repaint=function(){var t=!1,e=this.dom;if(e||(this._create(),e=this.dom,t=!0),e){if(!this.parent)throw Error("Cannot repaint item: no parent attached");var i=this.parent.getForeground();if(!i)throw Error("Cannot repaint time axis: parent has no foreground container element");var s=this.parent.getBackground();if(!s)throw Error("Cannot repaint time axis: parent has no background container element");var n=this.parent.getAxis();if(!s)throw Error("Cannot repaint time axis: parent has no axis container element");if(e.box.parentNode||(i.appendChild(e.box),t=!0),e.line.parentNode||(s.appendChild(e.line),t=!0),e.dot.parentNode||(n.appendChild(e.dot),t=!0),this.data.content!=this.content){if(this.content=this.data.content,this.content instanceof Element)e.content.innerHTML="",e.content.appendChild(this.content);else{if(void 0==this.data.content)throw Error('Property "content" missing in item '+this.data.id);e.content.innerHTML=this.content}t=!0}var o=(this.data.className?" "+this.data.className:"")+(this.selected?" selected":"");this.className!=o&&(this.className=o,e.box.className="item box"+o,e.line.className="item line"+o,e.dot.className="item dot"+o,t=!0)}return t},g.prototype.show=function(){return this.dom&&this.dom.box.parentNode?!1:this.repaint()},g.prototype.hide=function(){var t=!1,e=this.dom;return e&&(e.box.parentNode&&(e.box.parentNode.removeChild(e.box),t=!0),e.line.parentNode&&e.line.parentNode.removeChild(e.line),e.dot.parentNode&&e.dot.parentNode.removeChild(e.dot)),t},g.prototype.reflow=function(){var t,e,i,s,n,o,r,a,h,d,l,p,c=0;if(void 0==this.data.start)throw Error('Property "start" missing in item '+this.data.id);if(l=this.data,p=this.parent&&this.parent.range,l&&p){var u=p.end-p.start;this.visible=l.start>p.start-u&&l.start0},g.prototype._create=function(){var t=this.dom;t||(this.dom=t={},t.box=document.createElement("DIV"),t.content=document.createElement("DIV"),t.content.className="content",t.box.appendChild(t.content),t.line=document.createElement("DIV"),t.line.className="line",t.dot=document.createElement("DIV"),t.dot.className="dot")},g.prototype.reposition=function(){var t=this.dom,e=this.props,i=this.options.orientation||this.defaultOptions.orientation;if(t){var s=t.box,n=t.line,o=t.dot;s.style.left=this.left+"px",s.style.top=this.top+"px",n.style.left=e.line.left+"px","top"==i?(n.style.top="0px",n.style.height=this.top+"px"):(n.style.top=this.top+this.height+"px",n.style.height=Math.max(this.parent.height-this.top-this.height+this.props.dot.height/2,0)+"px"),o.style.left=e.dot.left+"px",o.style.top=e.dot.top+"px"}},v.prototype=new m(null,null),v.prototype.select=function(){this.selected=!0},v.prototype.unselect=function(){this.selected=!1},v.prototype.repaint=function(){var t=!1,e=this.dom;if(e||(this._create(),e=this.dom,t=!0),e){if(!this.parent)throw Error("Cannot repaint item: no parent attached");var i=this.parent.getForeground();if(!i)throw Error("Cannot repaint time axis: parent has no foreground container element");if(e.point.parentNode||(i.appendChild(e.point),i.appendChild(e.point),t=!0),this.data.content!=this.content){if(this.content=this.data.content,this.content instanceof Element)e.content.innerHTML="",e.content.appendChild(this.content);else{if(void 0==this.data.content)throw Error('Property "content" missing in item '+this.data.id);e.content.innerHTML=this.content}t=!0}var s=(this.data.className?" "+this.data.className:"")+(this.selected?" selected":"");this.className!=s&&(this.className=s,e.point.className="item point"+s,t=!0)}return t},v.prototype.show=function(){return this.dom&&this.dom.point.parentNode?!1:this.repaint()},v.prototype.hide=function(){var t=!1,e=this.dom;return e&&e.point.parentNode&&(e.point.parentNode.removeChild(e.point),t=!0),t},v.prototype.reflow=function(){var t,e,i,s,n,o,r,a,h,d,l=0;if(void 0==this.data.start)throw Error('Property "start" missing in item '+this.data.id);if(h=this.data,d=this.parent&&this.parent.range,h&&d){var p=d.end-d.start;this.visible=h.start>d.start-p&&h.start0},v.prototype._create=function(){var t=this.dom;t||(this.dom=t={},t.point=document.createElement("div"),t.content=document.createElement("div"),t.content.className="content",t.point.appendChild(t.content),t.dot=document.createElement("div"),t.dot.className="dot",t.point.appendChild(t.dot))},v.prototype.reposition=function(){var t=this.dom,e=this.props;t&&(t.point.style.top=this.top+"px",t.point.style.left=this.left+"px",t.content.style.marginLeft=e.content.marginLeft+"px",t.dot.style.top=e.dot.top+"px")},y.prototype=new m(null,null),y.prototype.select=function(){this.selected=!0},y.prototype.unselect=function(){this.selected=!1},y.prototype.repaint=function(){var t=!1,e=this.dom;if(e||(this._create(),e=this.dom,t=!0),e){if(!this.parent)throw Error("Cannot repaint item: no parent attached");var i=this.parent.getForeground();if(!i)throw Error("Cannot repaint time axis: parent has no foreground container element");if(e.box.parentNode||(i.appendChild(e.box),t=!0),this.data.content!=this.content){if(this.content=this.data.content,this.content instanceof Element)e.content.innerHTML="",e.content.appendChild(this.content);else{if(void 0==this.data.content)throw Error('Property "content" missing in item '+this.data.id); -e.content.innerHTML=this.content}t=!0}var s=this.data.className?" "+this.data.className:"";this.className!=s&&(this.className=s,e.box.className="item range"+s,t=!0)}return t},y.prototype.show=function(){return this.dom&&this.dom.box.parentNode?!1:this.repaint()},y.prototype.hide=function(){var t=!1,e=this.dom;return e&&e.box.parentNode&&(e.box.parentNode.removeChild(e.box),t=!0),t},y.prototype.reflow=function(){var t,e,i,s,n,o,r,a,h,d,l,p,c,u,f,m,g=0;if(void 0==this.data.start)throw Error('Property "start" missing in item '+this.data.id);if(void 0==this.data.end)throw Error('Property "end" missing in item '+this.data.id);return h=this.data,d=this.parent&&this.parent.range,this.visible=h&&d?h.startd.start:!1,this.visible&&(t=this.dom,t?(e=this.props,i=this.options,o=this.parent,r=o.toScreen(this.data.start),a=o.toScreen(this.data.end),l=D.updateProperty,p=t.box,c=o.width,f=i.orientation||this.defaultOptions.orientation,s=i.margin&&i.margin.axis||this.defaultOptions.margin.axis,n=i.padding||this.defaultOptions.padding,g+=l(e.content,"width",t.content.offsetWidth),g+=l(this,"height",p.offsetHeight),-c>r&&(r=-c),a>2*c&&(a=2*c),u=0>r?Math.min(-r,a-r-e.content.width-2*n):0,g+=l(e.content,"left",u),"top"==f?(m=s,g+=l(this,"top",m)):(m=o.height-this.height-s,g+=l(this,"top",m)),g+=l(this,"left",r),g+=l(this,"width",Math.max(a-r,1))):g+=1),g>0},y.prototype._create=function(){var t=this.dom;t||(this.dom=t={},t.box=document.createElement("div"),t.content=document.createElement("div"),t.content.className="content",t.box.appendChild(t.content))},y.prototype.reposition=function(){var t=this.dom,e=this.props;t&&(t.box.style.top=this.top+"px",t.box.style.left=this.left+"px",t.box.style.width=this.width+"px",t.content.style.left=e.content.left+"px")},b.prototype=new l,b.prototype.setOptions=l.prototype.setOptions,b.prototype.getContainer=function(){return this.parent.getContainer()},b.prototype.setItems=function(t){if(this.itemset&&(this.itemset.hide(),this.itemset.setItems(),this.parent.controller.remove(this.itemset),this.itemset=null),t){var e=this.groupId,i=Object.create(this.options);this.itemset=new f(this,null,i),this.itemset.setRange(this.parent.range),this.view=new r(t,{filter:function(t){return t.group==e}}),this.itemset.setItems(this.view),this.parent.controller.add(this.itemset)}},b.prototype.repaint=function(){return!1},b.prototype.reflow=function(){var t=0,e=D.updateProperty;if(t+=e(this,"top",this.itemset?this.itemset.top:0),t+=e(this,"height",this.itemset?this.itemset.height:0),this.label){var i=this.label.firstChild;t+=e(this.props.label,"width",i.clientWidth),t+=e(this.props.label,"height",i.clientHeight)}else t+=e(this.props.label,"width",0),t+=e(this.props.label,"height",0);return t>0},w.prototype=new p,w.prototype.setOptions=l.prototype.setOptions,w.prototype.setRange=function(){},w.prototype.setItems=function(t){this.itemsData=t;for(var e in this.groups)if(this.groups.hasOwnProperty(e)){var i=this.groups[e];i.setItems(t)}},w.prototype.getItems=function(){return this.itemsData},w.prototype.setRange=function(t){this.range=t},w.prototype.setGroups=function(t){var e,i=this;if(this.groupsData&&(D.forEach(this.listeners,function(t,e){i.groupsData.unsubscribe(e,t)}),e=this.groupsData.getIds(),this._onRemove(e)),t?t instanceof o?this.groupsData=t:(this.groupsData=new o({convert:{start:"Date",end:"Date"}}),this.groupsData.add(t)):this.groupsData=null,this.groupsData){var s=this.id;D.forEach(this.listeners,function(t,e){i.groupsData.subscribe(e,t,s)}),e=this.groupsData.getIds(),this._onAdd(e)}},w.prototype.getGroups=function(){return this.groupsData},w.prototype.repaint=function(){var t,e,i,s,n=0,o=D.updateProperty,r=D.option.asSize,a=D.option.asElement,h=this.options,d=this.dom.frame,l=this.dom.labels;if(!this.parent)throw Error("Cannot repaint groupset: no parent attached");var p=this.parent.getContainer();if(!p)throw Error("Cannot repaint groupset: parent has no container element");if(!d){d=document.createElement("div"),d.className="groupset",this.dom.frame=d;var c=h.className;c&&D.addClassName(d,D.option.asString(c)),n+=1}d.parentNode||(p.appendChild(d),n+=1);var u=a(h.labelContainer);if(!u)throw Error('Cannot repaint groupset: option "labelContainer" not defined');l||(l=document.createElement("div"),l.className="labels",this.dom.labels=l),l.parentNode&&l.parentNode==u||(l.parentNode&&l.parentNode.removeChild(l.parentNode),u.appendChild(l)),n+=o(d.style,"height",r(h.height,this.height+"px")),n+=o(d.style,"top",r(h.top,"0px")),n+=o(d.style,"left",r(h.left,"0px")),n+=o(d.style,"width",r(h.width,"100%")),n+=o(l.style,"top",r(h.top,"0px"));var f=this,m=this.queue,g=this.groups,v=this.groupsData,y=Object.keys(m);if(y.length){y.forEach(function(t){var e=m[t],i=g[t];switch(e){case"add":case"update":if(!i){var s=Object.create(f.options);i=new b(f,t,s),i.setItems(f.itemsData),g[t]=i,f.controller.add(i)}i.data=v.get(t),delete m[t];break;case"remove":i&&(i.setItems(),delete g[t],f.controller.remove(i)),delete m[t];break;default:console.log('Error: unknown action "'+e+'"')}});var w=this.groupsData.getIds({order:this.options.groupsOrder});for(t=0;w.length>t;t++)(function(t,e){var i=0;e&&(i=function(){return e.top+e.height}),t.setOptions({top:i})})(g[w[t]],g[w[t-1]]);for(;l.firstChild;)l.removeChild(l.firstChild);for(t=0;w.length>t;t++)e=w[t],s=this._createLabel(e),l.appendChild(s);n++}for(e in g)g.hasOwnProperty(e)&&(i=g[e],s=i.label,s&&(s.style.top=i.top+"px",s.style.height=i.height+"px"));return n>0},w.prototype._createLabel=function(t){var e=this.groups[t],i=document.createElement("div");i.className="label";var s=document.createElement("div");s.className="inner",i.appendChild(s);var n=e.data&&e.data.content;n instanceof Element?s.appendChild(n):void 0!=n&&(s.innerHTML=n);var o=e.data&&e.data.className;return o&&D.addClassName(i,o),e.label=i,i},w.prototype.getContainer=function(){return this.dom.frame},w.prototype.getLabelsWidth=function(){return this.props.labels.width},w.prototype.reflow=function(){var t,e,i=0,s=this.options,n=D.updateProperty,o=D.option.asNumber,r=D.option.asSize,a=this.dom.frame;if(a){var h,d=o(s.maxHeight),l=null!=r(s.height);if(l)h=a.offsetHeight;else{h=0;for(t in this.groups)this.groups.hasOwnProperty(t)&&(e=this.groups[t],h+=e.height)}null!=d&&(h=Math.min(h,d)),i+=n(this,"height",h),i+=n(this,"top",a.offsetTop),i+=n(this,"left",a.offsetLeft),i+=n(this,"width",a.offsetWidth)}var p=0;for(t in this.groups)if(this.groups.hasOwnProperty(t)){e=this.groups[t];var c=e.props&&e.props.label&&e.props.label.width||0;p=Math.max(p,c)}return i+=n(this.props.labels,"width",p),i>0},w.prototype.hide=function(){return this.dom.frame&&this.dom.frame.parentNode?(this.dom.frame.parentNode.removeChild(this.dom.frame),!0):!1},w.prototype.show=function(){return this.dom.frame&&this.dom.frame.parentNode?!1:this.repaint()},w.prototype._onUpdate=function(t){this._toQueue(t,"update")},w.prototype._onAdd=function(t){this._toQueue(t,"add")},w.prototype._onRemove=function(t){this._toQueue(t,"remove")},w.prototype._toQueue=function(t,e){var i=this.queue;t.forEach(function(t){i[t]=e}),this.controller&&this.requestRepaint()},_.prototype.setOptions=function(t){t&&D.extend(this.options,t),this.controller.reflow(),this.controller.repaint()},_.prototype.setItems=function(t){var e,i=null==this.itemsData;if(t?t instanceof o&&(e=t):e=null,t instanceof o||(e=new o({convert:{start:"Date",end:"Date"}}),e.add(t)),this.itemsData=e,this.content.setItems(e),i&&(void 0==this.options.start||void 0==this.options.end)){var s=this.getItemRange(),n=s.min,r=s.max;if(null!=n&&null!=r){var a=r.valueOf()-n.valueOf();0>=a&&(a=864e5),n=new Date(n.valueOf()-.05*a),r=new Date(r.valueOf()+.05*a)}void 0!=this.options.start&&(n=new Date(this.options.start.valueOf())),void 0!=this.options.end&&(r=new Date(this.options.end.valueOf())),(null!=n||null!=r)&&this.range.setRange(n,r)}},_.prototype.setGroups=function(t){var e=this;this.groupsData=t;var i=this.groupsData?w:f;if(!(this.content instanceof i)){this.content&&(this.content.hide(),this.content.setItems&&this.content.setItems(),this.content.setGroups&&this.content.setGroups(),this.controller.remove(this.content));var s=Object.create(this.options);D.extend(s,{top:function(){return"top"==e.options.orientation?e.timeaxis.height:e.itemPanel.height-e.timeaxis.height-e.content.height},left:null,width:"100%",height:function(){return e.options.height?e.itemPanel.height-e.timeaxis.height:null},maxHeight:function(){if(e.options.maxHeight){if(!D.isNumber(e.options.maxHeight))throw new TypeError("Number expected for property maxHeight");return e.options.maxHeight-e.timeaxis.height}return null},labelContainer:function(){return e.labelPanel.getContainer()}}),this.content=new i(this.itemPanel,[this.timeaxis],s),this.content.setRange&&this.content.setRange(this.range),this.content.setItems&&this.content.setItems(this.itemsData),this.content.setGroups&&this.content.setGroups(this.groupsData),this.controller.add(this.content)}},_.prototype.getItemRange=function(){var t=this.itemsData,e=null,i=null;if(t){var s=t.min("start");e=s?s.start.valueOf():null;var n=t.max("start");n&&(i=n.start.valueOf());var o=t.max("end");o&&(i=null==i?o.end.valueOf():Math.max(i,o.end.valueOf()))}return{min:null!=e?new Date(e):null,max:null!=i?new Date(i):null}},function(t){function e(t){return E=t,c()}function i(){D=0,C=E.charAt(0)}function s(){D++,C=E.charAt(D)}function n(){return E.charAt(D+1)}function o(t){return N.test(t)}function r(t,e){if(t||(t={}),e)for(var i in e)e.hasOwnProperty(i)&&(t[i]=e[i]);return t}function a(t,e,i){for(var s=e.split("."),n=t;s.length;){var o=s.shift();s.length?(n[o]||(n[o]={}),n=n[o]):n[o]=i}}function h(t,e){for(var i,s,n=null,o=[t],a=t;a.parent;)o.push(a.parent),a=a.parent;if(a.nodes)for(i=0,s=a.nodes.length;s>i;i++)if(e.id===a.nodes[i].id){n=a.nodes[i];break}for(n||(n={id:e.id},t.node&&(n.attr=r(n.attr,t.node))),i=o.length-1;i>=0;i--){var h=o[i];h.nodes||(h.nodes=[]),-1==h.nodes.indexOf(n)&&h.nodes.push(n)}e.attr&&(n.attr=r(n.attr,e.attr))}function d(t,e){if(t.edges||(t.edges=[]),t.edges.push(e),t.edge){var i=r({},t.edge);e.attr=r(i,e.attr)}}function l(t,e,i,s,n){var o={from:e,to:i,type:s};return t.edge&&(o.attr=r({},t.edge)),o.attr=r(o.attr||{},n),o}function p(){for(O=S.NULL,L="";" "==C||" "==C||"\n"==C||"\r"==C;)s();do{var t=!1;if("#"==C){for(var e=D-1;" "==E.charAt(e)||" "==E.charAt(e);)e--;if("\n"==E.charAt(e)||""==E.charAt(e)){for(;""!=C&&"\n"!=C;)s();t=!0}}if("/"==C&&"/"==n()){for(;""!=C&&"\n"!=C;)s();t=!0}if("/"==C&&"*"==n()){for(;""!=C;){if("*"==C&&"/"==n()){s(),s();break}s()}t=!0}for(;" "==C||" "==C||"\n"==C||"\r"==C;)s()}while(t);if(""==C)return O=S.DELIMITER,void 0;var i=C+n();if(M[i])return O=S.DELIMITER,L=i,s(),s(),void 0;if(M[C])return O=S.DELIMITER,L=C,s(),void 0;if(o(C)||"-"==C){for(L+=C,s();o(C);)L+=C,s();return"false"==L?L=!1:"true"==L?L=!0:isNaN(Number(L))||(L=Number(L)),O=S.IDENTIFIER,void 0}if('"'==C){for(s();""!=C&&('"'!=C||'"'==C&&'"'==n());)L+=C,'"'==C&&s(),s();if('"'!=C)throw w('End of string " expected');return s(),O=S.IDENTIFIER,void 0}for(O=S.UNKNOWN;""!=C;)L+=C,s();throw new SyntaxError('Syntax error in part "'+_(L,30)+'"')}function c(){var t={};if(i(),p(),"strict"==L&&(t.strict=!0,p()),("graph"==L||"digraph"==L)&&(t.type=L,p()),O==S.IDENTIFIER&&(t.id=L,p()),"{"!=L)throw w("Angle bracket { expected");if(p(),u(t),"}"!=L)throw w("Angle bracket } expected");if(p(),""!==L)throw w("End of file expected");return p(),delete t.node,delete t.edge,delete t.graph,t}function u(t){for(;""!==L&&"}"!=L;)f(t),";"==L&&p()}function f(t){var e=m(t);if(e)return y(t,e),void 0;var i=g(t);if(!i){if(O!=S.IDENTIFIER)throw w("Identifier expected");var s=L;if(p(),"="==L){if(p(),O!=S.IDENTIFIER)throw w("Identifier expected");t[s]=L,p()}else v(t,s)}}function m(t){var e=null;if("subgraph"==L&&(e={},e.type="subgraph",p(),O==S.IDENTIFIER&&(e.id=L,p())),"{"==L){if(p(),e||(e={}),e.parent=t,e.node=t.node,e.edge=t.edge,e.graph=t.graph,u(e),"}"!=L)throw w("Angle bracket } expected");p(),delete e.node,delete e.edge,delete e.graph,delete e.parent,t.subgraphs||(t.subgraphs=[]),t.subgraphs.push(e)}return e}function g(t){return"node"==L?(p(),t.node=b(),"node"):"edge"==L?(p(),t.edge=b(),"edge"):"graph"==L?(p(),t.graph=b(),"graph"):null}function v(t,e){var i={id:e},s=b();s&&(i.attr=s),h(t,i),y(t,e)}function y(t,e){for(;"->"==L||"--"==L;){var i,s=L;p();var n=m(t);if(n)i=n;else{if(O!=S.IDENTIFIER)throw w("Identifier or subgraph expected");i=L,h(t,{id:i}),p()}var o=b(),r=l(t,e,i,s,o);d(t,r),e=i}}function b(){for(var t=null;"["==L;){for(p(),t={};""!==L&&"]"!=L;){if(O!=S.IDENTIFIER)throw w("Attribute name expected");var e=L;if(p(),"="!=L)throw w("Equal sign = expected");if(p(),O!=S.IDENTIFIER)throw w("Attribute value expected");var i=L;a(t,e,i),p(),","==L&&p()}if("]"!=L)throw w("Bracket ] expected");p()}return t}function w(t){return new SyntaxError(t+', got "'+_(L,30)+'" (char '+D+")")}function _(t,e){return e>=t.length?t:t.substr(0,27)+"..."}function x(t,e,i){t instanceof Array?t.forEach(function(t){e instanceof Array?e.forEach(function(e){i(t,e)}):i(t,e)}):e instanceof Array?e.forEach(function(e){i(t,e)}):i(t,e)}function T(t){function i(t){var e={from:t.from,to:t.to};return r(e,t.attr),e.style="->"==t.type?"arrow":"line",e}var s=e(t),n={nodes:[],edges:[],options:{}};return s.nodes&&s.nodes.forEach(function(t){var e={id:t.id,label:(t.label||t.id)+""};r(e,t.attr),e.image&&(e.shape="image"),n.nodes.push(e)}),s.edges&&s.edges.forEach(function(t){var e,s;e=t.from instanceof Object?t.from.nodes:{id:t.from},s=t.to instanceof Object?t.to.nodes:{id:t.to},t.from instanceof Object&&t.from.edges&&t.from.edges.forEach(function(t){var e=i(t);n.edges.push(e)}),x(e,s,function(e,s){var o=l(n,e.id,s.id,t.type,t.attr),r=i(o);n.edges.push(r)}),t.to instanceof Object&&t.to.edges&&t.to.edges.forEach(function(t){var e=i(t);n.edges.push(e)})}),s.attr&&(n.options=s.attr),n}var S={NULL:0,DELIMITER:1,IDENTIFIER:2,UNKNOWN:3},M={"{":!0,"}":!0,"[":!0,"]":!0,";":!0,"=":!0,",":!0,"->":!0,"--":!0},E="",D=0,C="",L="",O=S.NULL,N=/[a-zA-Z_0-9.:#]/;t.parseDOT=e,t.DOTToGraph=T}(D!==void 0?D:s),"undefined"!=typeof CanvasRenderingContext2D&&(CanvasRenderingContext2D.prototype.circle=function(t,e,i){this.beginPath(),this.arc(t,e,i,0,2*Math.PI,!1)},CanvasRenderingContext2D.prototype.square=function(t,e,i){this.beginPath(),this.rect(t-i,e-i,2*i,2*i)},CanvasRenderingContext2D.prototype.triangle=function(t,e,i){this.beginPath();var s=2*i,n=s/2,o=Math.sqrt(3)/6*s,r=Math.sqrt(s*s-n*n);this.moveTo(t,e-(r-o)),this.lineTo(t+n,e+o),this.lineTo(t-n,e+o),this.lineTo(t,e-(r-o)),this.closePath()},CanvasRenderingContext2D.prototype.triangleDown=function(t,e,i){this.beginPath();var s=2*i,n=s/2,o=Math.sqrt(3)/6*s,r=Math.sqrt(s*s-n*n);this.moveTo(t,e+(r-o)),this.lineTo(t+n,e-o),this.lineTo(t-n,e-o),this.lineTo(t,e+(r-o)),this.closePath()},CanvasRenderingContext2D.prototype.star=function(t,e,i){this.beginPath();for(var s=0;10>s;s++){var n=0===s%2?1.3*i:.5*i;this.lineTo(t+n*Math.sin(2*s*Math.PI/10),e-n*Math.cos(2*s*Math.PI/10))}this.closePath()},CanvasRenderingContext2D.prototype.roundRect=function(t,e,i,s,n){var o=Math.PI/180;0>i-2*n&&(n=i/2),0>s-2*n&&(n=s/2),this.beginPath(),this.moveTo(t+n,e),this.lineTo(t+i-n,e),this.arc(t+i-n,e+n,n,270*o,360*o,!1),this.lineTo(t+i,e+s-n),this.arc(t+i-n,e+s-n,n,0,90*o,!1),this.lineTo(t+n,e+s),this.arc(t+n,e+s-n,n,90*o,180*o,!1),this.lineTo(t,e+n),this.arc(t+n,e+n,n,180*o,270*o,!1)},CanvasRenderingContext2D.prototype.ellipse=function(t,e,i,s){var n=.5522848,o=i/2*n,r=s/2*n,a=t+i,h=e+s,d=t+i/2,l=e+s/2;this.beginPath(),this.moveTo(t,l),this.bezierCurveTo(t,l-r,d-o,e,d,e),this.bezierCurveTo(d+o,e,a,l-r,a,l),this.bezierCurveTo(a,l+r,d+o,h,d,h),this.bezierCurveTo(d-o,h,t,l+r,t,l)},CanvasRenderingContext2D.prototype.database=function(t,e,i,s){var n=1/3,o=i,r=s*n,a=.5522848,h=o/2*a,d=r/2*a,l=t+o,p=e+r,c=t+o/2,u=e+r/2,f=e+(s-r/2),m=e+s;this.beginPath(),this.moveTo(l,u),this.bezierCurveTo(l,u+d,c+h,p,c,p),this.bezierCurveTo(c-h,p,t,u+d,t,u),this.bezierCurveTo(t,u-d,c-h,e,c,e),this.bezierCurveTo(c+h,e,l,u-d,l,u),this.lineTo(l,f),this.bezierCurveTo(l,f+d,c+h,m,c,m),this.bezierCurveTo(c-h,m,t,f+d,t,f),this.lineTo(t,u)},CanvasRenderingContext2D.prototype.arrow=function(t,e,i,s){var n=t-s*Math.cos(i),o=e-s*Math.sin(i),r=t-.9*s*Math.cos(i),a=e-.9*s*Math.sin(i),h=n+s/3*Math.cos(i+.5*Math.PI),d=o+s/3*Math.sin(i+.5*Math.PI),l=n+s/3*Math.cos(i-.5*Math.PI),p=o+s/3*Math.sin(i-.5*Math.PI);this.beginPath(),this.moveTo(t,e),this.lineTo(h,d),this.lineTo(r,a),this.lineTo(l,p),this.closePath()},CanvasRenderingContext2D.prototype.dashedLine=function(t,e,i,s,n){n||(n=[10,5]),0==c&&(c=.001);var o=n.length;this.moveTo(t,e);for(var r=i-t,a=s-e,h=a/r,d=Math.sqrt(r*r+a*a),l=0,p=!0;d>=.1;){var c=n[l++%o];c>d&&(c=d);var u=Math.sqrt(c*c/(1+h*h));0>r&&(u=-u),t+=u,e+=h*u,this[p?"lineTo":"moveTo"](t,e),d-=c,p=!p}}),x.prototype.attachEdge=function(t){-1==this.edges.indexOf(t)&&this.edges.push(t),this._updateMass()},x.prototype.detachEdge=function(t){var e=this.edges.indexOf(t);-1!=e&&this.edges.splice(e,1),this._updateMass()},x.prototype._updateMass=function(){this.mass=50+20*this.edges.length},x.prototype.setProperties=function(t,e){if(t){if(void 0!=t.id&&(this.id=t.id),void 0!=t.label&&(this.label=t.label),void 0!=t.title&&(this.title=t.title),void 0!=t.group&&(this.group=t.group),void 0!=t.x&&(this.x=t.x),void 0!=t.y&&(this.y=t.y),void 0!=t.value&&(this.value=t.value),void 0===this.id)throw"Node must have an id";if(this.group){var i=this.grouplist.get(this.group);for(var s in i)i.hasOwnProperty(s)&&(this[s]=i[s])}if(void 0!=t.shape&&(this.shape=t.shape),void 0!=t.image&&(this.image=t.image),void 0!=t.radius&&(this.radius=t.radius),void 0!=t.color&&(this.color=x.parseColor(t.color)),void 0!=t.fontColor&&(this.fontColor=t.fontColor),void 0!=t.fontSize&&(this.fontSize=t.fontSize),void 0!=t.fontFace&&(this.fontFace=t.fontFace),void 0!=this.image){if(!this.imagelist)throw"No imagelist provided";this.imageObj=this.imagelist.load(this.image)}switch(this.xFixed=this.xFixed||void 0!=t.x,this.yFixed=this.yFixed||void 0!=t.y,this.radiusFixed=this.radiusFixed||void 0!=t.radius,"image"==this.shape&&(this.radiusMin=e.nodes.widthMin,this.radiusMax=e.nodes.widthMax),this.shape){case"database":this.draw=this._drawDatabase,this.resize=this._resizeDatabase;break;case"box":this.draw=this._drawBox,this.resize=this._resizeBox;break;case"circle":this.draw=this._drawCircle,this.resize=this._resizeCircle;break;case"ellipse":this.draw=this._drawEllipse,this.resize=this._resizeEllipse;break;case"image":this.draw=this._drawImage,this.resize=this._resizeImage;break;case"text":this.draw=this._drawText,this.resize=this._resizeText;break;case"dot":this.draw=this._drawDot,this.resize=this._resizeShape;break;case"square":this.draw=this._drawSquare,this.resize=this._resizeShape;break;case"triangle":this.draw=this._drawTriangle,this.resize=this._resizeShape;break;case"triangleDown":this.draw=this._drawTriangleDown,this.resize=this._resizeShape;break;case"star":this.draw=this._drawStar,this.resize=this._resizeShape;break;default:this.draw=this._drawEllipse,this.resize=this._resizeEllipse}this._reset()}},x.parseColor=function(t){var e;return D.isString(t)?e={border:t,background:t,highlight:{border:t,background:t}}:(e={},e.background=t.background||"white",e.border=t.border||e.background,D.isString(t.highlight)?e.highlight={border:t.highlight,background:t.highlight}:(e.highlight={},e.highlight.background=t.highlight&&t.highlight.background||e.background,e.highlight.border=t.highlight&&t.highlight.border||e.border)),e},x.prototype.select=function(){this.selected=!0,this._reset()},x.prototype.unselect=function(){this.selected=!1,this._reset()},x.prototype._reset=function(){this.width=void 0,this.height=void 0},x.prototype.getTitle=function(){return this.title},x.prototype.distanceToBorder=function(t,e){var i=1;switch(this.width||this.resize(t),this.shape){case"circle":case"dot":return this.radius+i;case"ellipse":var s=this.width/2,n=this.height/2,o=Math.sin(e)*s,r=Math.cos(e)*n;return s*n/Math.sqrt(o*o+r*r);case"box":case"image":case"text":default:return this.width?Math.min(Math.abs(this.width/2/Math.cos(e)),Math.abs(this.height/2/Math.sin(e)))+i:0}},x.prototype._setForce=function(t,e){this.fx=t,this.fy=e},x.prototype._addForce=function(t,e){this.fx+=t,this.fy+=e},x.prototype.discreteStep=function(t){if(!this.xFixed){var e=-this.damping*this.vx,i=(this.fx+e)/this.mass;this.vx+=i/t,this.x+=this.vx/t}if(!this.yFixed){var s=-this.damping*this.vy,n=(this.fy+s)/this.mass;this.vy+=n/t,this.y+=this.vy/t}},x.prototype.isFixed=function(){return this.xFixed&&this.yFixed},x.prototype.isMoving=function(t){return Math.abs(this.vx)>t||Math.abs(this.vy)>t||!this.xFixed&&Math.abs(this.fx)>this.minForce||!this.yFixed&&Math.abs(this.fy)>this.minForce},x.prototype.isSelected=function(){return this.selected},x.prototype.getValue=function(){return this.value},x.prototype.getDistance=function(t,e){var i=this.x-t,s=this.y-e;return Math.sqrt(i*i+s*s)},x.prototype.setValueRange=function(t,e){if(!this.radiusFixed&&void 0!==this.value){var i=(this.radiusMax-this.radiusMin)/(e-t);this.radius=(this.value-t)*i+this.radiusMin}},x.prototype.draw=function(){throw"Draw method not initialized for node"},x.prototype.resize=function(){throw"Resize method not initialized for node"},x.prototype.isOverlappingWith=function(t){return this.leftt.left&&this.topt.top},x.prototype._resizeImage=function(){if(!this.width){var t,e;if(this.value){var i=this.imageObj.height/this.imageObj.width;t=this.radius||this.imageObj.width,e=this.radius*i||this.imageObj.height}else t=this.imageObj.width,e=this.imageObj.height;this.width=t,this.height=e}},x.prototype._drawImage=function(t){this._resizeImage(t),this.left=this.x-this.width/2,this.top=this.y-this.height/2;var e;this.imageObj?(t.drawImage(this.imageObj,this.left,this.top,this.width,this.height),e=this.y+this.height/2):e=this.y,this._label(t,this.label,this.x,e,void 0,"top")},x.prototype._resizeBox=function(t){if(!this.width){var e=5,i=this.getTextSize(t);this.width=i.width+2*e,this.height=i.height+2*e}},x.prototype._drawBox=function(t){this._resizeBox(t),this.left=this.x-this.width/2,this.top=this.y-this.height/2,t.strokeStyle=this.selected?this.color.highlight.border:this.color.border,t.fillStyle=this.selected?this.color.highlight.background:this.color.background,t.lineWidth=this.selected?2:1,t.roundRect(this.left,this.top,this.width,this.height,this.radius),t.fill(),t.stroke(),this._label(t,this.label,this.x,this.y)},x.prototype._resizeDatabase=function(t){if(!this.width){var e=5,i=this.getTextSize(t),s=i.width+2*e;this.width=s,this.height=s}},x.prototype._drawDatabase=function(t){this._resizeDatabase(t),this.left=this.x-this.width/2,this.top=this.y-this.height/2,t.strokeStyle=this.selected?this.color.highlight.border:this.color.border,t.fillStyle=this.selected?this.color.highlight.background:this.color.background,t.lineWidth=this.selected?2:1,t.database(this.x-this.width/2,this.y-.5*this.height,this.width,this.height),t.fill(),t.stroke(),this._label(t,this.label,this.x,this.y)},x.prototype._resizeCircle=function(t){if(!this.width){var e=5,i=this.getTextSize(t),s=Math.max(i.width,i.height)+2*e;this.radius=s/2,this.width=s,this.height=s}},x.prototype._drawCircle=function(t){this._resizeCircle(t),this.left=this.x-this.width/2,this.top=this.y-this.height/2,t.strokeStyle=this.selected?this.color.highlight.border:this.color.border,t.fillStyle=this.selected?this.color.highlight.background:this.color.background,t.lineWidth=this.selected?2:1,t.circle(this.x,this.y,this.radius),t.fill(),t.stroke(),this._label(t,this.label,this.x,this.y)},x.prototype._resizeEllipse=function(t){if(!this.width){var e=this.getTextSize(t);this.width=1.5*e.width,this.height=2*e.height,this.widthl;l++)t.fillText(r[l],i,d),d+=h}},x.prototype.getTextSize=function(t){if(void 0!=this.label){t.font=(this.selected?"bold ":"")+this.fontSize+"px "+this.fontFace;for(var e=this.label.split("\n"),i=(this.fontSize+4)*e.length,s=0,n=0,o=e.length;o>n;n++)s=Math.max(s,t.measureText(e[n]).width);return{width:s,height:i}}return{width:0,height:0}},T.prototype.setProperties=function(t,e){if(t)switch(void 0!=t.from&&(this.fromId=t.from),void 0!=t.to&&(this.toId=t.to),void 0!=t.id&&(this.id=t.id),void 0!=t.style&&(this.style=t.style),void 0!=t.label&&(this.label=t.label),this.label&&(this.fontSize=e.edges.fontSize,this.fontFace=e.edges.fontFace,this.fontColor=e.edges.fontColor,void 0!=t.fontColor&&(this.fontColor=t.fontColor),void 0!=t.fontSize&&(this.fontSize=t.fontSize),void 0!=t.fontFace&&(this.fontFace=t.fontFace)),void 0!=t.title&&(this.title=t.title),void 0!=t.width&&(this.width=t.width),void 0!=t.value&&(this.value=t.value),void 0!=t.length&&(this.length=t.length),t.dash&&(void 0!=t.dash.length&&(this.dash.length=t.dash.length),void 0!=t.dash.gap&&(this.dash.gap=t.dash.gap),void 0!=t.dash.altLength&&(this.dash.altLength=t.dash.altLength)),void 0!=t.color&&(this.color=t.color),this.connect(),this.widthFixed=this.widthFixed||void 0!=t.width,this.lengthFixed=this.lengthFixed||void 0!=t.length,this.stiffness=1/this.length,this.style){case"line":this.draw=this._drawLine;break;case"arrow":this.draw=this._drawArrow;break;case"arrow-center":this.draw=this._drawArrowCenter;break;case"dash-line":this.draw=this._drawDashLine;break;default:this.draw=this._drawLine}},T.prototype.connect=function(){this.disconnect(),this.from=this.graph.nodes[this.fromId]||null,this.to=this.graph.nodes[this.toId]||null,this.connected=this.from&&this.to,this.connected?(this.from.attachEdge(this),this.to.attachEdge(this)):(this.from&&this.from.detachEdge(this),this.to&&this.to.detachEdge(this))},T.prototype.disconnect=function(){this.from&&(this.from.detachEdge(this),this.from=null),this.to&&(this.to.detachEdge(this),this.to=null),this.connected=!1},T.prototype.getTitle=function(){return this.title},T.prototype.getValue=function(){return this.value},T.prototype.setValueRange=function(t,e){if(!this.widthFixed&&void 0!==this.value){var i=(this.widthMax-this.widthMin)/(e-t);this.width=(this.value-t)*i+this.widthMin}},T.prototype.draw=function(){throw"Method draw not initialized in edge"},T.prototype.isOverlappingWith=function(t){var e=10,i=this.from.x,s=this.from.y,n=this.to.x,o=this.to.y,r=t.left,a=t.top,h=T._dist(i,s,n,o,r,a);return e>h},T.prototype._drawLine=function(t){t.strokeStyle=this.color,t.lineWidth=this._getLineWidth();var e;if(this.from!=this.to)this._line(t),this.label&&(e=this._pointOnLine(.5),this._label(t,this.label,e.x,e.y));else{var i,s,n=this.length/4,o=this.from;o.width||o.resize(t),o.width>o.height?(i=o.x+o.width/2,s=o.y-n):(i=o.x+n,s=o.y-o.height/2),this._circle(t,i,s,n),e=this._pointOnCircle(i,s,n,.5),this._label(t,this.label,e.x,e.y)}},T.prototype._getLineWidth=function(){return this.from.selected||this.to.selected?Math.min(2*this.width,this.widthMax):this.width},T.prototype._line=function(t){t.beginPath(),t.moveTo(this.from.x,this.from.y),t.lineTo(this.to.x,this.to.y),t.stroke()},T.prototype._circle=function(t,e,i,s){t.beginPath(),t.arc(e,i,s,0,2*Math.PI,!1),t.stroke()},T.prototype._label=function(t,e,i,s){if(e){t.font=(this.from.selected||this.to.selected?"bold ":"")+this.fontSize+"px "+this.fontFace,t.fillStyle="white";var n=t.measureText(e).width,o=this.fontSize,r=i-n/2,a=s-o/2;t.fillRect(r,a,n,o),t.fillStyle=this.fontColor||"black",t.textAlign="left",t.textBaseline="top",t.fillText(e,r,a)}},T.prototype._drawDashLine=function(t){if(t.strokeStyle=this.color,t.lineWidth=this._getLineWidth(),t.beginPath(),t.lineCap="round",void 0!=this.dash.altLength?t.dashedLine(this.from.x,this.from.y,this.to.x,this.to.y,[this.dash.length,this.dash.gap,this.dash.altLength,this.dash.gap]):void 0!=this.dash.length&&void 0!=this.dash.gap?t.dashedLine(this.from.x,this.from.y,this.to.x,this.to.y,[this.dash.length,this.dash.gap]):(t.moveTo(this.from.x,this.from.y),t.lineTo(this.to.x,this.to.y)),t.stroke(),this.label){var e=this._pointOnLine(.5);this._label(t,this.label,e.x,e.y)}},T.prototype._pointOnLine=function(t){return{x:(1-t)*this.from.x+t*this.to.x,y:(1-t)*this.from.y+t*this.to.y}},T.prototype._pointOnCircle=function(t,e,i,s){var n=2*(s-3/8)*Math.PI;return{x:t+i*Math.cos(n),y:e-i*Math.sin(n)}},T.prototype._drawArrowCenter=function(t){var e;if(t.strokeStyle=this.color,t.fillStyle=this.color,t.lineWidth=this._getLineWidth(),this.from!=this.to){this._line(t);var i=Math.atan2(this.to.y-this.from.y,this.to.x-this.from.x),s=10+5*this.width;e=this._pointOnLine(.5),t.arrow(e.x,e.y,i,s),t.fill(),t.stroke(),this.label&&(e=this._pointOnLine(.5),this._label(t,this.label,e.x,e.y))}else{var n,o,r=this.length/4,a=this.from;a.width||a.resize(t),a.width>a.height?(n=a.x+a.width/2,o=a.y-r):(n=a.x+r,o=a.y-a.height/2),this._circle(t,n,o,r);var i=.2*Math.PI,s=10+5*this.width;e=this._pointOnCircle(n,o,r,.5),t.arrow(e.x,e.y,i,s),t.fill(),t.stroke(),this.label&&(e=this._pointOnCircle(n,o,r,.5),this._label(t,this.label,e.x,e.y))}},T.prototype._drawArrow=function(t){t.strokeStyle=this.color,t.fillStyle=this.color,t.lineWidth=this._getLineWidth();var e,i;if(this.from!=this.to){e=Math.atan2(this.to.y-this.from.y,this.to.x-this.from.x);var s=this.to.x-this.from.x,n=this.to.y-this.from.y,o=Math.sqrt(s*s+n*n),r=this.from.distanceToBorder(t,e+Math.PI),a=(o-r)/o,h=a*this.from.x+(1-a)*this.to.x,d=a*this.from.y+(1-a)*this.to.y,l=this.to.distanceToBorder(t,e),p=(o-l)/o,c=(1-p)*this.from.x+p*this.to.x,u=(1-p)*this.from.y+p*this.to.y;if(t.beginPath(),t.moveTo(h,d),t.lineTo(c,u),t.stroke(),i=10+5*this.width,t.arrow(c,u,e,i),t.fill(),t.stroke(),this.label){var f=this._pointOnLine(.5);this._label(t,this.label,f.x,f.y)}}else{var m,g,v,y=this.from,b=this.length/4;y.width||y.resize(t),y.width>y.height?(m=y.x+y.width/2,g=y.y-b,v={x:m,y:y.y,angle:.9*Math.PI}):(m=y.x+b,g=y.y-y.height/2,v={x:y.x,y:g,angle:.6*Math.PI}),t.beginPath(),t.arc(m,g,b,0,2*Math.PI,!1),t.stroke(),i=10+5*this.width,t.arrow(v.x,v.y,v.angle,i),t.fill(),t.stroke(),this.label&&(f=this._pointOnCircle(m,g,b,.5),this._label(t,this.label,f.x,f.y)) -}},T._dist=function(t,e,i,s,n,o){var r=i-t,a=s-e,h=r*r+a*a,d=((n-t)*r+(o-e)*a)/h;d>1?d=1:0>d&&(d=0);var l=t+d*r,p=e+d*a,c=l-n,u=p-o;return Math.sqrt(c*c+u*u)},S.prototype.setPosition=function(t,e){this.x=parseInt(t),this.y=parseInt(e)},S.prototype.setText=function(t){this.frame.innerHTML=t},S.prototype.show=function(t){if(void 0===t&&(t=!0),t){var e=this.frame.clientHeight,i=this.frame.clientWidth,s=this.frame.parentNode.clientHeight,n=this.frame.parentNode.clientWidth,o=this.y-e;o+e+this.padding>s&&(o=s-e-this.padding),this.padding>o&&(o=this.padding);var r=this.x;r+i+this.padding>n&&(r=n-i-this.padding),this.padding>r&&(r=this.padding),this.frame.style.left=r+"px",this.frame.style.top=o+"px",this.frame.style.visibility="visible"}else this.hide()},S.prototype.hide=function(){this.frame.style.visibility="hidden"},Groups=function(){this.clear(),this.defaultIndex=0},Groups.DEFAULT=[{border:"#2B7CE9",background:"#97C2FC",highlight:{border:"#2B7CE9",background:"#D2E5FF"}},{border:"#FFA500",background:"#FFFF00",highlight:{border:"#FFA500",background:"#FFFFA3"}},{border:"#FA0A10",background:"#FB7E81",highlight:{border:"#FA0A10",background:"#FFAFB1"}},{border:"#41A906",background:"#7BE141",highlight:{border:"#41A906",background:"#A1EC76"}},{border:"#E129F0",background:"#EB7DF4",highlight:{border:"#E129F0",background:"#F0B3F5"}},{border:"#7C29F0",background:"#AD85E4",highlight:{border:"#7C29F0",background:"#D3BDF0"}},{border:"#C37F00",background:"#FFA807",highlight:{border:"#C37F00",background:"#FFCA66"}},{border:"#4220FB",background:"#6E6EFD",highlight:{border:"#4220FB",background:"#9B9BFD"}},{border:"#FD5A77",background:"#FFC0CB",highlight:{border:"#FD5A77",background:"#FFD1D9"}},{border:"#4AD63A",background:"#C2FABC",highlight:{border:"#4AD63A",background:"#E6FFE3"}}],Groups.prototype.clear=function(){this.groups={},this.groups.length=function(){var t=0;for(var e in this)this.hasOwnProperty(e)&&t++;return t}},Groups.prototype.get=function(t){var e=this.groups[t];if(void 0==e){var i=this.defaultIndex%Groups.DEFAULT.length;this.defaultIndex++,e={},e.color=Groups.DEFAULT[i],this.groups[t]=e}return e},Groups.prototype.add=function(t,e){return this.groups[t]=e,e.color&&(e.color=x.parseColor(e.color)),e},Images=function(){this.images={},this.callback=void 0},Images.prototype.setOnloadCallback=function(t){this.callback=t},Images.prototype.load=function(t){var e=this.images[t];if(void 0==e){var i=this;e=new Image,this.images[t]=e,e.onload=function(){i.callback&&i.callback(this)},e.src=t}return e},M.prototype.setData=function(t){if(t&&t.dot&&(t.nodes||t.edges))throw new SyntaxError('Data must contain either parameter "dot" or parameter pair "nodes" and "edges", but not both.');if(this.setOptions(t&&t.options),t&&t.dot){if(t&&t.dot){var e=N.util.DOTToGraph(t.dot);return this.setData(e),void 0}}else this._setNodes(t&&t.nodes),this._setEdges(t&&t.edges);this.stabilize&&this._doStabilize(),this.start()},M.prototype.setOptions=function(t){if(t){if(void 0!=t.width&&(this.width=t.width),void 0!=t.height&&(this.height=t.height),void 0!=t.stabilize&&(this.stabilize=t.stabilize),void 0!=t.selectable&&(this.selectable=t.selectable),t.edges){for(var e in t.edges)t.edges.hasOwnProperty(e)&&(this.constants.edges[e]=t.edges[e]);void 0!=t.edges.length&&t.nodes&&void 0==t.nodes.distance&&(this.constants.edges.length=t.edges.length,this.constants.nodes.distance=1.25*t.edges.length),t.edges.fontColor||(this.constants.edges.fontColor=t.edges.color),t.edges.dash&&(void 0!=t.edges.dash.length&&(this.constants.edges.dash.length=t.edges.dash.length),void 0!=t.edges.dash.gap&&(this.constants.edges.dash.gap=t.edges.dash.gap),void 0!=t.edges.dash.altLength&&(this.constants.edges.dash.altLength=t.edges.dash.altLength))}if(t.nodes){for(e in t.nodes)t.nodes.hasOwnProperty(e)&&(this.constants.nodes[e]=t.nodes[e]);t.nodes.color&&(this.constants.nodes.color=x.parseColor(t.nodes.color))}if(t.groups)for(var i in t.groups)if(t.groups.hasOwnProperty(i)){var s=t.groups[i];this.groups.add(i,s)}}this.setSize(this.width,this.height),this._setTranslation(this.frame.clientWidth/2,this.frame.clientHeight/2),this._setScale(1)},M.prototype._trigger=function(t,e){O.trigger(this,t,e)},M.prototype._create=function(){for(;this.containerElement.hasChildNodes();)this.containerElement.removeChild(this.containerElement.firstChild);if(this.frame=document.createElement("div"),this.frame.className="graph-frame",this.frame.style.position="relative",this.frame.style.overflow="hidden",this.frame.canvas=document.createElement("canvas"),this.frame.canvas.style.position="relative",this.frame.appendChild(this.frame.canvas),!this.frame.canvas.getContext){var t=document.createElement("DIV");t.style.color="red",t.style.fontWeight="bold",t.style.padding="10px",t.innerHTML="Error: your browser does not support HTML canvas",this.frame.canvas.appendChild(t)}var e=this,i=function(t){e._onMouseDown(t)},s=function(t){e._onMouseMoveTitle(t)},n=function(t){e._onMouseWheel(t)},o=function(t){e._onTouchStart(t)};N.util.addEventListener(this.frame.canvas,"mousedown",i),N.util.addEventListener(this.frame.canvas,"mousemove",s),N.util.addEventListener(this.frame.canvas,"mousewheel",n),N.util.addEventListener(this.frame.canvas,"touchstart",o),this.containerElement.appendChild(this.frame)},M.prototype._onMouseDown=function(t){if(t=t||window.event,this.selectable&&(this.leftButtonDown&&this._onMouseUp(t),this.leftButtonDown=t.which?1==t.which:1==t.button,this.leftButtonDown||this.touchDown)){var e=this;this.onmousemove||(this.onmousemove=function(t){e._onMouseMove(t)},N.util.addEventListener(document,"mousemove",e.onmousemove)),this.onmouseup||(this.onmouseup=function(t){e._onMouseUp(t)},N.util.addEventListener(document,"mouseup",e.onmouseup)),N.util.preventDefault(t),this.startMouseX=D.getPageX(t),this.startMouseY=D.getPageY(t),this.startFrameLeft=N.util.getAbsoluteLeft(this.frame.canvas),this.startFrameTop=N.util.getAbsoluteTop(this.frame.canvas),this.startTranslation=this._getTranslation(),this.ctrlKeyDown=t.ctrlKey,this.shiftKeyDown=t.shiftKey;var i={left:this._xToCanvas(this.startMouseX-this.startFrameLeft),top:this._yToCanvas(this.startMouseY-this.startFrameTop),right:this._xToCanvas(this.startMouseX-this.startFrameLeft),bottom:this._yToCanvas(this.startMouseY-this.startFrameTop)},s=this._getNodesOverlappingWith(i);if(this.startClickedObj=s.length>0?s[s.length-1]:void 0,this.startClickedObj){var n=this.nodes[this.startClickedObj];this.startClickedObj.xFixed=n.xFixed,this.startClickedObj.yFixed=n.yFixed,n.xFixed=!0,n.yFixed=!0,this.ctrlKeyDown&&n.isSelected()?this._unselectNodes([this.startClickedObj]):this._selectNodes([this.startClickedObj],this.ctrlKeyDown),this.moving||this._redraw()}else this.shiftKeyDown||(this.moved=!1)}},M.prototype._onMouseMove=function(t){if(t=t||window.event,this.selectable){var e=D.getPageX(t),i=D.getPageY(t);if(this.mouseX=e,this.mouseY=i,this.startClickedObj){var s=this.nodes[this.startClickedObj];this.startClickedObj.xFixed||(s.x=this._xToCanvas(e-this.startFrameLeft)),this.startClickedObj.yFixed||(s.y=this._yToCanvas(i-this.startFrameTop)),this.moving||(this.moving=!0,this.start())}else if(this.shiftKeyDown){void 0==this.frame.selRect&&(this.frame.selRect=document.createElement("DIV"),this.frame.appendChild(this.frame.selRect),this.frame.selRect.style.position="absolute",this.frame.selRect.style.border="1px dashed red");var n=Math.min(this.startMouseX,e)-this.startFrameLeft,o=Math.min(this.startMouseY,i)-this.startFrameTop,r=Math.max(this.startMouseX,e)-this.startFrameLeft,a=Math.max(this.startMouseY,i)-this.startFrameTop;this.frame.selRect.style.left=n+"px",this.frame.selRect.style.top=o+"px",this.frame.selRect.style.width=r-n+"px",this.frame.selRect.style.height=a-o+"px"}else{var h=e-this.startMouseX,d=i-this.startMouseY;this._setTranslation(this.startTranslation.x+h,this.startTranslation.y+d),this._redraw(),this.moved=!0}N.util.preventDefault(t)}},M.prototype._onMouseUp=function(t){if(t=t||window.event,this.selectable){this.onmousemove&&(N.util.removeEventListener(document,"mousemove",this.onmousemove),this.onmousemove=void 0),this.onmouseup&&(N.util.removeEventListener(document,"mouseup",this.onmouseup),this.onmouseup=void 0),N.util.preventDefault(t);var e=D.getPageX(t)||this.mouseX||0,i=D.getPageY(t)||this.mouseY||0,s=t?t.ctrlKey:window.event.ctrlKey;if(this.startClickedObj){var n=this.nodes[this.startClickedObj];n.xFixed=this.startClickedObj.xFixed,n.yFixed=this.startClickedObj.yFixed}else if(this.shiftKeyDown){var o={left:this._xToCanvas(Math.min(this.startMouseX,e)-this.startFrameLeft),top:this._yToCanvas(Math.min(this.startMouseY,i)-this.startFrameTop),right:this._xToCanvas(Math.max(this.startMouseX,e)-this.startFrameLeft),bottom:this._yToCanvas(Math.max(this.startMouseY,i)-this.startFrameTop)},r=this._getNodesOverlappingWith(o);this._selectNodes(r,s),this.redraw(),this.frame.selRect&&(this.frame.removeChild(this.frame.selRect),this.frame.selRect=void 0)}else this.ctrlKeyDown||this.moved||(this._unselectNodes(),this._redraw());this.leftButtonDown=!1,this.ctrlKeyDown=!1}},M.prototype._onMouseWheel=function(t){t=t||window.event;var e=D.getPageX(t),i=D.getPageY(t),s=0;if(t.wheelDelta?s=t.wheelDelta/120:t.detail&&(s=-t.detail/3),s){var n=s/10;0>s&&(n/=1-n);var o=this._getScale(),r=o*(1+n);.01>r&&(r=.01),r>10&&(r=10);var a=N.util.getAbsoluteLeft(this.frame.canvas),h=N.util.getAbsoluteTop(this.frame.canvas),d=e-a,l=i-h,p=this._getTranslation(),c=r/o,u=(1-c)*d+p.x*c,f=(1-c)*l+p.y*c;this._setScale(r),this._setTranslation(u,f),this._redraw()}N.util.preventDefault(t)},M.prototype._onMouseMoveTitle=function(t){t=t||window.event;var e=D.getPageX(t),i=D.getPageY(t);this.startFrameLeft=this.startFrameLeft||N.util.getAbsoluteLeft(this.frame.canvas),this.startFrameTop=this.startFrameTop||N.util.getAbsoluteTop(this.frame.canvas);var s=e-this.startFrameLeft,n=i-this.startFrameTop;this.popupNode&&this._checkHidePopup(s,n);var o=this,r=function(){o._checkShowPopup(s,n)};this.popupTimer&&clearInterval(this.popupTimer),this.leftButtonDown||(this.popupTimer=setTimeout(r,300))},M.prototype._checkShowPopup=function(t,e){var i,s={left:this._xToCanvas(t),top:this._yToCanvas(e),right:this._xToCanvas(t),bottom:this._yToCanvas(e)},n=this.popupNode;if(void 0==this.popupNode){var o=this.nodes;for(i in o)if(o.hasOwnProperty(i)){var r=o[i];if(void 0!=r.getTitle()&&r.isOverlappingWith(s)){this.popupNode=r;break}}}if(void 0==this.popupNode){var a=this.edges;for(i in a)if(a.hasOwnProperty(i)){var h=a[i];if(h.connected&&void 0!=h.getTitle()&&h.isOverlappingWith(s)){this.popupNode=h;break}}}if(this.popupNode){if(this.popupNode!=n){var d=this;d.popup||(d.popup=new S(d.frame)),d.popup.setPosition(t-3,e-3),d.popup.setText(d.popupNode.getTitle()),d.popup.show()}}else this.popup&&this.popup.hide()},M.prototype._checkHidePopup=function(t,e){var i={left:t,top:e,right:t,bottom:e};this.popupNode&&this.popupNode.isOverlappingWith(i)||(this.popupNode=void 0,this.popup&&this.popup.hide())},M.prototype._onTouchStart=function(t){if(N.util.preventDefault(t),!this.touchDown){this.touchDown=!0;var e=this;this.ontouchmove||(this.ontouchmove=function(t){e._onTouchMove(t)},N.util.addEventListener(document,"touchmove",this.ontouchmove)),this.ontouchend||(this.ontouchend=function(t){e._onTouchEnd(t)},N.util.addEventListener(document,"touchend",this.ontouchend)),this._onMouseDown(t)}},M.prototype._onTouchMove=function(t){N.util.preventDefault(t),this._onMouseMove(t)},M.prototype._onTouchEnd=function(t){N.util.preventDefault(t),this.touchDown=!1,this.ontouchmove&&(N.util.removeEventListener(document,"touchmove",this.ontouchmove),this.ontouchmove=void 0),this.ontouchend&&(N.util.removeEventListener(document,"touchend",this.ontouchend),this.ontouchend=void 0),this._onMouseUp(t)},M.prototype._unselectNodes=function(t,e){var i,s,n,o=!1;if(t)for(i=0,s=t.length;s>i;i++){n=t[i],this.nodes[n].unselect();for(var r=0;this.selection.length>r;)this.selection[r]==n?(this.selection.splice(r,1),o=!0):r++}else if(this.selection&&this.selection.length){for(i=0,s=this.selection.length;s>i;i++)n=this.selection[i],this.nodes[n].unselect(),o=!0;this.selection=[]}return!o||1!=e&&void 0!=e||this._trigger("select"),o},M.prototype._selectNodes=function(t,e){var i,s,n=!1,o=!0;if(t.length!=this.selection.length)o=!1;else for(i=0,s=Math.min(t.length,this.selection.length);s>i;i++)if(t[i]!=this.selection[i]){o=!1;break}if(o)return n;if(void 0==e||0==e){var r=!1;n=this._unselectNodes(void 0,r)}for(i=0,s=t.length;s>i;i++){var a=t[i],h=-1!=this.selection.indexOf(a);h||(this.nodes[a].select(),this.selection.push(a),n=!0)}return n&&this._trigger("select"),n},M.prototype._getNodesOverlappingWith=function(t){var e=this.nodes,i=[];for(var s in e)e.hasOwnProperty(s)&&e[s].isOverlappingWith(t)&&i.push(s);return i},M.prototype.getSelection=function(){return this.selection.concat([])},M.prototype.setSelection=function(t){var e,i,s;if(void 0==t.length)throw"Selection must be an array with ids";for(e=0,i=this.selection.length;i>e;e++)s=this.selection[e],this.nodes[s].unselect();for(this.selection=[],e=0,i=t.length;i>e;e++){s=t[e];var n=this.nodes[s];if(!n)throw new RangeError('Node with id "'+s+'" not found');n.select(),this.selection.push(s)}this.redraw()},M.prototype._updateSelection=function(){for(var t=0;this.selection.length>t;){var e=this.selection[t];this.nodes[e]?t++:this.selection.splice(t,1)}},M.prototype._getConnectionCount=function(t){function e(t){for(var e=[],i=0,s=t.length;s>i;i++)for(var n=t[i],o=n.edges,r=0,a=o.length;a>r;r++){var h=o[r],d=null;h.from==n?d=h.to:h.to==n&&(d=h.from);var l,p;if(d)for(l=0,p=t.length;p>l;l++)if(t[l]==d){d=null;break}if(d)for(l=0,p=e.length;p>l;l++)if(e[l]==d){d=null;break}d&&e.push(d)}return e}void 0==t&&(t=1);var i=[],s=this.nodes;for(var n in s)if(s.hasOwnProperty(n)){for(var o=[s[n]],r=0;t>r;r++)o=o.concat(e(o));i.push(o)}for(var a=[],h=0,d=i.length;d>h;h++)a.push(i[h].length);return a},M.prototype.setSize=function(t,e){this.frame.style.width=t,this.frame.style.height=e,this.frame.canvas.style.width="100%",this.frame.canvas.style.height="100%",this.frame.canvas.width=this.frame.canvas.clientWidth,this.frame.canvas.height=this.frame.canvas.clientHeight},M.prototype._setNodes=function(t){var e=this.nodesData;if(t instanceof o||t instanceof r)this.nodesData=t;else if(t instanceof Array)this.nodesData=new o,this.nodesData.add(t);else{if(t)throw new TypeError("Array or DataSet expected");this.nodesData=new o}if(e&&D.forEach(this.nodesListeners,function(t,i){e.unsubscribe(i,t)}),this.nodes={},this.nodesData){var i=this;D.forEach(this.nodesListeners,function(t,e){i.nodesData.subscribe(e,t)});var s=this.nodesData.getIds();this._addNodes(s)}this._updateSelection()},M.prototype._addNodes=function(t){for(var e,i=0,s=t.length;s>i;i++){e=t[i];var n=this.nodesData.get(e),o=new x(n,this.images,this.groups,this.constants);if(this.nodes[e]=o,!o.isFixed()){var r=2*this.constants.edges.length,a=t.length,h=2*Math.PI*(i/a);o.x=r*Math.cos(h),o.y=r*Math.sin(h),this.moving=!0}}this._reconnectEdges(),this._updateValueRange(this.nodes)},M.prototype._updateNodes=function(t){for(var e=this.nodes,i=this.nodesData,s=0,n=t.length;n>s;s++){var o=t[s],r=e[o],a=i.get(o);r?r.setProperties(a,this.constants):(r=new x(properties,this.images,this.groups,this.constants),e[o]=r,r.isFixed()||(this.moving=!0))}this._reconnectEdges(),this._updateValueRange(e)},M.prototype._removeNodes=function(t){for(var e=this.nodes,i=0,s=t.length;s>i;i++){var n=t[i];delete e[n]}this._reconnectEdges(),this._updateSelection(),this._updateValueRange(e)},M.prototype._setEdges=function(t){var e=this.edgesData;if(t instanceof o||t instanceof r)this.edgesData=t;else if(t instanceof Array)this.edgesData=new o,this.edgesData.add(t);else{if(t)throw new TypeError("Array or DataSet expected");this.edgesData=new o}if(e&&D.forEach(this.edgesListeners,function(t,i){e.unsubscribe(i,t)}),this.edges={},this.edgesData){var i=this;D.forEach(this.edgesListeners,function(t,e){i.edgesData.subscribe(e,t)});var s=this.edgesData.getIds();this._addEdges(s)}this._reconnectEdges()},M.prototype._addEdges=function(t){for(var e=this.edges,i=this.edgesData,s=0,n=t.length;n>s;s++){var o=t[s],r=e[o];r&&r.disconnect();var a=i.get(o);e[o]=new T(a,this,this.constants)}this.moving=!0,this._updateValueRange(e)},M.prototype._updateEdges=function(t){for(var e=this.edges,i=this.edgesData,s=0,n=t.length;n>s;s++){var o=t[s],r=i.get(o),a=e[o];a?(a.disconnect(),a.setProperties(r,this.constants),a.connect()):(a=new T(r,this,this.constants),this.edges[o]=a)}this.moving=!0,this._updateValueRange(e)},M.prototype._removeEdges=function(t){for(var e=this.edges,i=0,s=t.length;s>i;i++){var n=t[i],o=e[n];o&&(o.disconnect(),delete e[n])}this.moving=!0,this._updateValueRange(e)},M.prototype._reconnectEdges=function(){var t,e=this.nodes,i=this.edges;for(t in e)e.hasOwnProperty(t)&&(e[t].edges=[]);for(t in i)if(i.hasOwnProperty(t)){var s=i[t];s.from=null,s.to=null,s.connect()}},M.prototype._updateValueRange=function(t){var e,i=void 0,s=void 0;for(e in t)if(t.hasOwnProperty(e)){var n=t[e].getValue();void 0!==n&&(i=void 0===i?n:Math.min(n,i),s=void 0===s?n:Math.max(n,s))}if(void 0!==i&&void 0!==s)for(e in t)t.hasOwnProperty(e)&&t[e].setValueRange(i,s)},M.prototype.redraw=function(){this.setSize(this.width,this.height),this._redraw()},M.prototype._redraw=function(){var t=this.frame.canvas.getContext("2d"),e=this.frame.canvas.width,i=this.frame.canvas.height;t.clearRect(0,0,e,i),t.save(),t.translate(this.translation.x,this.translation.y),t.scale(this.scale,this.scale),this._drawEdges(t),this._drawNodes(t),t.restore()},M.prototype._setTranslation=function(t,e){void 0===this.translation&&(this.translation={x:0,y:0}),void 0!==t&&(this.translation.x=t),void 0!==e&&(this.translation.y=e)},M.prototype._getTranslation=function(){return{x:this.translation.x,y:this.translation.y}},M.prototype._setScale=function(t){this.scale=t},M.prototype._getScale=function(){return this.scale},M.prototype._xToCanvas=function(t){return(t-this.translation.x)/this.scale},M.prototype._canvasToX=function(t){return t*this.scale+this.translation.x},M.prototype._yToCanvas=function(t){return(t-this.translation.y)/this.scale},M.prototype._canvasToY=function(t){return t*this.scale+this.translation.y},M.prototype._drawNodes=function(t){var e=this.nodes,i=[];for(var s in e)e.hasOwnProperty(s)&&(e[s].isSelected()?i.push(s):e[s].draw(t));for(var n=0,o=i.length;o>n;n++)e[i[n]].draw(t)},M.prototype._drawEdges=function(t){var e=this.edges;for(var i in e)if(e.hasOwnProperty(i)){var s=e[i];s.connected&&e[i].draw(t)}},M.prototype._doStabilize=function(){new Date;for(var t=0,e=this.constants.minVelocity,i=!1;!i&&this.constants.maxIterations>t;)this._calculateForces(),this._discreteStepNodes(),i=!this._isMoving(e),t++;new Date},M.prototype._calculateForces=function(){var t,e,i,s,n,o,r,a,h,d,l,p=this.nodes,c=this.edges,u=.01,f=this.frame.canvas.clientWidth/2,m=this.frame.canvas.clientHeight/2;for(t in p)if(p.hasOwnProperty(t)){var g=p[t];e=f-g.x,i=m-g.y,s=Math.atan2(i,e),o=Math.cos(s)*u,r=Math.sin(s)*u,g._setForce(o,r)}var v=this.constants.nodes.distance,y=10;for(var b in p)if(p.hasOwnProperty(b)){var w=p[b];for(var _ in p)if(p.hasOwnProperty(_)){var x=p[_];e=x.x-w.x,i=x.y-w.y,n=Math.sqrt(e*e+i*i),s=Math.atan2(i,e),a=1/(1+Math.exp((n/v-1)*y)),o=Math.cos(s)*a,r=Math.sin(s)*a,w._addForce(-o,-r),x._addForce(o,r)}}for(t in c)if(c.hasOwnProperty(t)){var T=c[t];T.connected&&(e=T.to.x-T.from.x,i=T.to.y-T.from.y,l=T.length,d=Math.sqrt(e*e+i*i),s=Math.atan2(i,e),h=T.stiffness*(l-d),o=Math.cos(s)*h,r=Math.sin(s)*h,T.from._addForce(-o,-r),T.to._addForce(o,r))}},M.prototype._isMoving=function(t){var e=this.nodes;for(var i in e)if(e.hasOwnProperty(i)&&e[i].isMoving(t))return!0;return!1},M.prototype._discreteStepNodes=function(){var t=this.refreshRate/1e3,e=this.nodes;for(var i in e)e.hasOwnProperty(i)&&e[i].discreteStep(t)},M.prototype.start=function(){if(this.moving){this._calculateForces(),this._discreteStepNodes();var t=this.constants.minVelocity;this.moving=this._isMoving(t)}if(this.moving){if(!this.timer){var e=this;this.timer=window.setTimeout(function(){e.timer=void 0,e.start(),e._redraw()},this.refreshRate)}}else this._redraw()},M.prototype.stop=function(){this.timer&&(window.clearInterval(this.timer),this.timer=void 0)};var N={util:D,events:O,Controller:d,DataSet:o,DataView:r,Range:h,Stack:a,TimeStep:TimeStep,EventBus:n,components:{items:{Item:m,ItemBox:g,ItemPoint:v,ItemRange:y},Component:l,Panel:p,RootPanel:c,ItemSet:f,TimeAxis:u},graph:{Node:x,Edge:T,Popup:S,Groups:Groups,Images:Images},Timeline:_,Graph:M};s!==void 0&&(s=N),i!==void 0&&i.exports!==void 0&&(i.exports=N),"function"==typeof t&&t(function(){return N}),"undefined"!=typeof window&&(window.vis=N),D.loadCss("/* vis.js stylesheet */\n.vis.timeline {\n}\n\n\n.vis.timeline.rootpanel {\n position: relative;\n overflow: hidden;\n\n border: 1px solid #bfbfbf;\n -moz-box-sizing: border-box;\n box-sizing: border-box;\n}\n\n.vis.timeline .panel {\n position: absolute;\n overflow: hidden;\n}\n\n\n.vis.timeline .groupset {\n position: absolute;\n padding: 0;\n margin: 0;\n}\n\n.vis.timeline .labels {\n position: absolute;\n top: 0;\n left: 0;\n width: 100%;\n height: 100%;\n\n padding: 0;\n margin: 0;\n\n border-right: 1px solid #bfbfbf;\n box-sizing: border-box;\n -moz-box-sizing: border-box;\n}\n\n.vis.timeline .labels .label {\n position: absolute;\n left: 0;\n top: 0;\n width: 100%;\n border-bottom: 1px solid #bfbfbf;\n color: #4d4d4d;\n}\n\n.vis.timeline .labels .label .inner {\n display: inline-block;\n padding: 5px;\n}\n\n\n.vis.timeline .itemset {\n position: absolute;\n padding: 0;\n margin: 0;\n overflow: hidden;\n}\n\n.vis.timeline .background {\n}\n\n.vis.timeline .foreground {\n}\n\n.vis.timeline .itemset-axis {\n position: absolute;\n}\n\n.vis.timeline .groupset .itemset-axis {\n border-top: 1px solid #bfbfbf;\n}\n\n/* TODO: with orientation=='bottom', this will more or less overlap with timeline axis\n.vis.timeline .groupset .itemset-axis:last-child {\n border-top: none;\n}\n*/\n\n\n.vis.timeline .item {\n position: absolute;\n color: #1A1A1A;\n border-color: #97B0F8;\n background-color: #D5DDF6;\n display: inline-block;\n}\n\n.vis.timeline .item.selected {\n border-color: #FFC200;\n background-color: #FFF785;\n z-index: 999;\n}\n\n.vis.timeline .item.cluster {\n /* TODO: use another color or pattern? */\n background: #97B0F8 url('img/cluster_bg.png');\n color: white;\n}\n.vis.timeline .item.cluster.point {\n border-color: #D5DDF6;\n}\n\n.vis.timeline .item.box {\n text-align: center;\n border-style: solid;\n border-width: 1px;\n border-radius: 5px;\n -moz-border-radius: 5px; /* For Firefox 3.6 and older */\n}\n\n.vis.timeline .item.point {\n background: none;\n}\n\n.vis.timeline .dot {\n border: 5px solid #97B0F8;\n position: absolute;\n border-radius: 5px;\n -moz-border-radius: 5px; /* For Firefox 3.6 and older */\n}\n\n.vis.timeline .item.range {\n overflow: hidden;\n border-style: solid;\n border-width: 1px;\n border-radius: 2px;\n -moz-border-radius: 2px; /* For Firefox 3.6 and older */\n}\n\n.vis.timeline .item.range .drag-left {\n cursor: w-resize;\n z-index: 1000;\n}\n\n.vis.timeline .item.range .drag-right {\n cursor: e-resize;\n z-index: 1000;\n}\n\n.vis.timeline .item.range .content {\n position: relative;\n display: inline-block;\n}\n\n.vis.timeline .item.line {\n position: absolute;\n width: 0;\n border-left-width: 1px;\n border-left-style: solid;\n}\n\n.vis.timeline .item .content {\n margin: 5px;\n white-space: nowrap;\n overflow: hidden;\n}\n\n.vis.timeline .axis {\n position: relative;\n}\n\n.vis.timeline .axis .text {\n position: absolute;\n color: #4d4d4d;\n padding: 3px;\n white-space: nowrap;\n}\n\n.vis.timeline .axis .text.measure {\n position: absolute;\n padding-left: 0;\n padding-right: 0;\n margin-left: 0;\n margin-right: 0;\n visibility: hidden;\n}\n\n.vis.timeline .axis .grid.vertical {\n position: absolute;\n width: 0;\n border-right: 1px solid;\n}\n\n.vis.timeline .axis .grid.horizontal {\n position: absolute;\n left: 0;\n width: 100%;\n height: 0;\n border-bottom: 1px solid;\n}\n\n.vis.timeline .axis .grid.minor {\n border-color: #e5e5e5;\n}\n\n.vis.timeline .axis .grid.major {\n border-color: #bfbfbf;\n}\n\n")})()},{moment:2}],2:[function(e,i){(function(){(function(s){function n(t,e){return function(i){return p(t.call(this,i),e)}}function o(t){return function(e){return this.lang().ordinal(t.call(this,e))}}function r(){}function a(t){d(this,t)}function h(t){var e=this._data={},i=t.years||t.year||t.y||0,s=t.months||t.month||t.M||0,n=t.weeks||t.week||t.w||0,o=t.days||t.day||t.d||0,r=t.hours||t.hour||t.h||0,a=t.minutes||t.minute||t.m||0,h=t.seconds||t.second||t.s||0,d=t.milliseconds||t.millisecond||t.ms||0;this._milliseconds=d+1e3*h+6e4*a+36e5*r,this._days=o+7*n,this._months=s+12*i,e.milliseconds=d%1e3,h+=l(d/1e3),e.seconds=h%60,a+=l(h/60),e.minutes=a%60,r+=l(a/60),e.hours=r%24,o+=l(r/24),o+=7*n,e.days=o%30,s+=l(o/30),e.months=s%12,i+=l(s/12),e.years=i}function d(t,e){for(var i in e)e.hasOwnProperty(i)&&(t[i]=e[i]);return t}function l(t){return 0>t?Math.ceil(t):Math.floor(t)}function p(t,e){for(var i=t+"";e>i.length;)i="0"+i;return i}function c(t,e,i){var s,n=e._milliseconds,o=e._days,r=e._months;n&&t._d.setTime(+t+n*i),o&&t.date(t.date()+o*i),r&&(s=t.date(),t.date(1).month(t.month()+r*i).date(Math.min(s,t.daysInMonth())))}function u(t){return"[object Array]"===Object.prototype.toString.call(t)}function f(t,e){var i,s=Math.min(t.length,e.length),n=Math.abs(t.length-e.length),o=0;for(i=0;s>i;i++)~~t[i]!==~~e[i]&&o++;return o+n}function m(t,e){return e.abbr=t,z[t]||(z[t]=new r),z[t].set(e),z[t]}function g(t){return t?(!z[t]&&R&&e("./lang/"+t),z[t]):I.fn._lang}function v(t){return t.match(/\[.*\]/)?t.replace(/^\[|\]$/g,""):t.replace(/\\/g,"")}function y(t){var e,i,s=t.match(j);for(e=0,i=s.length;i>e;e++)s[e]=ae[s[e]]?ae[s[e]]:v(s[e]);return function(n){var o="";for(e=0;i>e;e++)o+="function"==typeof s[e].call?s[e].call(n,t):s[e];return o}}function b(t,e){function i(e){return t.lang().longDateFormat(e)||e}for(var s=5;s--&&U.test(e);)e=e.replace(U,i);return ne[e]||(ne[e]=y(e)),ne[e](t)}function w(t){switch(t){case"DDDD":return q;case"YYYY":return V;case"YYYYY":return X;case"S":case"SS":case"SSS":case"DDD":return B;case"MMM":case"MMMM":case"dd":case"ddd":case"dddd":case"a":case"A":return K;case"X":return J;case"Z":case"ZZ":return G;case"T":return Z;case"MM":case"DD":case"YY":case"HH":case"hh":case"mm":case"ss":case"M":case"D":case"d":case"H":case"h":case"m":case"s":return W;default:return RegExp(t.replace("\\",""))}}function _(t,e,i){var s,n=i._a;switch(t){case"M":case"MM":n[1]=null==e?0:~~e-1;break;case"MMM":case"MMMM":s=g(i._l).monthsParse(e),null!=s?n[1]=s:i._isValid=!1;break;case"D":case"DD":case"DDD":case"DDDD":null!=e&&(n[2]=~~e);break;case"YY":n[0]=~~e+(~~e>68?1900:2e3);break;case"YYYY":case"YYYYY":n[0]=~~e;break;case"a":case"A":i._isPm="pm"===(e+"").toLowerCase();break;case"H":case"HH":case"h":case"hh":n[3]=~~e;break;case"m":case"mm":n[4]=~~e;break;case"s":case"ss":n[5]=~~e;break;case"S":case"SS":case"SSS":n[6]=~~(1e3*("0."+e));break;case"X":i._d=new Date(1e3*parseFloat(e));break;case"Z":case"ZZ":i._useUTC=!0,s=(e+"").match(ee),s&&s[1]&&(i._tzh=~~s[1]),s&&s[2]&&(i._tzm=~~s[2]),s&&"+"===s[0]&&(i._tzh=-i._tzh,i._tzm=-i._tzm)}null==e&&(i._isValid=!1)}function x(t){var e,i,s=[];if(!t._d){for(e=0;7>e;e++)t._a[e]=s[e]=null==t._a[e]?2===e?1:0:t._a[e];s[3]+=t._tzh||0,s[4]+=t._tzm||0,i=new Date(0),t._useUTC?(i.setUTCFullYear(s[0],s[1],s[2]),i.setUTCHours(s[3],s[4],s[5],s[6])):(i.setFullYear(s[0],s[1],s[2]),i.setHours(s[3],s[4],s[5],s[6])),t._d=i}}function T(t){var e,i,s=t._f.match(j),n=t._i;for(t._a=[],e=0;s.length>e;e++)i=(w(s[e]).exec(n)||[])[0],i&&(n=n.slice(n.indexOf(i)+i.length)),ae[s[e]]&&_(s[e],i,t);t._isPm&&12>t._a[3]&&(t._a[3]+=12),t._isPm===!1&&12===t._a[3]&&(t._a[3]=0),x(t)}function S(t){for(var e,i,s,n,o=99;t._f.length;){if(e=d({},t),e._f=t._f.pop(),T(e),i=new a(e),i.isValid()){s=i;break}n=f(e._a,i.toArray()),o>n&&(o=n,s=i)}d(t,s)}function M(t){var e,i=t._i;if(Q.exec(i)){for(t._f="YYYY-MM-DDT",e=0;4>e;e++)if(te[e][1].exec(i)){t._f+=te[e][0];break}G.exec(i)&&(t._f+=" Z"),T(t)}else t._d=new Date(i)}function E(t){var e=t._i,i=H.exec(e);e===s?t._d=new Date:i?t._d=new Date(+i[1]):"string"==typeof e?M(t):u(e)?(t._a=e.slice(0),x(t)):t._d=e instanceof Date?new Date(+e):new Date(e)}function D(t,e,i,s,n){return n.relativeTime(e||1,!!i,t,s)}function C(t,e,i){var s=Y(Math.abs(t)/1e3),n=Y(s/60),o=Y(n/60),r=Y(o/24),a=Y(r/365),h=45>s&&["s",s]||1===n&&["m"]||45>n&&["mm",n]||1===o&&["h"]||22>o&&["hh",o]||1===r&&["d"]||25>=r&&["dd",r]||45>=r&&["M"]||345>r&&["MM",Y(r/30)]||1===a&&["y"]||["yy",a];return h[2]=e,h[3]=t>0,h[4]=i,D.apply({},h)}function L(t,e,i){var s=i-e,n=i-t.day();return n>s&&(n-=7),s-7>n&&(n+=7),Math.ceil(I(t).add("d",n).dayOfYear()/7)}function O(t){var e=t._i,i=t._f;return null===e||""===e?null:("string"==typeof e&&(t._i=e=g().preparse(e)),I.isMoment(e)?(t=d({},e),t._d=new Date(+e._d)):i?u(i)?S(t):T(t):E(t),new a(t))}function N(t,e){I.fn[t]=I.fn[t+"s"]=function(t){var i=this._isUTC?"UTC":"";return null!=t?(this._d["set"+i+e](t),this):this._d["get"+i+e]()}}function A(t){I.duration.fn[t]=function(){return this._data[t]}}function k(t,e){I.duration.fn["as"+t]=function(){return+this/e}}for(var I,F,P="2.0.0",Y=Math.round,z={},R=i!==s&&i.exports,H=/^\/?Date\((\-?\d+)/i,j=/(\[[^\[]*\])|(\\)?(Mo|MM?M?M?|Do|DDDo|DD?D?D?|ddd?d?|do?|w[o|w]?|W[o|W]?|YYYYY|YYYY|YY|a|A|hh?|HH?|mm?|ss?|SS?S?|X|zz?|ZZ?|.)/g,U=/(\[[^\[]*\])|(\\)?(LT|LL?L?L?|l{1,4})/g,W=/\d\d?/,B=/\d{1,3}/,q=/\d{3}/,V=/\d{1,4}/,X=/[+\-]?\d{1,6}/,K=/[0-9]*[a-z\u00A0-\u05FF\u0700-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF]+|[\u0600-\u06FF]+\s*?[\u0600-\u06FF]+/i,G=/Z|[\+\-]\d\d:?\d\d/i,Z=/T/i,J=/[\+\-]?\d+(\.\d{1,3})?/,Q=/^\s*\d{4}-\d\d-\d\d((T| )(\d\d(:\d\d(:\d\d(\.\d\d?\d?)?)?)?)?([\+\-]\d\d:?\d\d)?)?/,$="YYYY-MM-DDTHH:mm:ssZ",te=[["HH:mm:ss.S",/(T| )\d\d:\d\d:\d\d\.\d{1,3}/],["HH:mm:ss",/(T| )\d\d:\d\d:\d\d/],["HH:mm",/(T| )\d\d:\d\d/],["HH",/(T| )\d\d/]],ee=/([\+\-]|\d\d)/gi,ie="Month|Date|Hours|Minutes|Seconds|Milliseconds".split("|"),se={Milliseconds:1,Seconds:1e3,Minutes:6e4,Hours:36e5,Days:864e5,Months:2592e6,Years:31536e6},ne={},oe="DDD w W M D d".split(" "),re="M D H h m s w W".split(" "),ae={M:function(){return this.month()+1},MMM:function(t){return this.lang().monthsShort(this,t)},MMMM:function(t){return this.lang().months(this,t)},D:function(){return this.date()},DDD:function(){return this.dayOfYear()},d:function(){return this.day()},dd:function(t){return this.lang().weekdaysMin(this,t)},ddd:function(t){return this.lang().weekdaysShort(this,t)},dddd:function(t){return this.lang().weekdays(this,t)},w:function(){return this.week()},W:function(){return this.isoWeek()},YY:function(){return p(this.year()%100,2)},YYYY:function(){return p(this.year(),4)},YYYYY:function(){return p(this.year(),5)},a:function(){return this.lang().meridiem(this.hours(),this.minutes(),!0)},A:function(){return this.lang().meridiem(this.hours(),this.minutes(),!1)},H:function(){return this.hours()},h:function(){return this.hours()%12||12},m:function(){return this.minutes()},s:function(){return this.seconds()},S:function(){return~~(this.milliseconds()/100)},SS:function(){return p(~~(this.milliseconds()/10),2)},SSS:function(){return p(this.milliseconds(),3)},Z:function(){var t=-this.zone(),e="+";return 0>t&&(t=-t,e="-"),e+p(~~(t/60),2)+":"+p(~~t%60,2)},ZZ:function(){var t=-this.zone(),e="+";return 0>t&&(t=-t,e="-"),e+p(~~(10*t/6),4)},X:function(){return this.unix()}};oe.length;)F=oe.pop(),ae[F+"o"]=o(ae[F]);for(;re.length;)F=re.pop(),ae[F+F]=n(ae[F],2);for(ae.DDDD=n(ae.DDD,3),r.prototype={set:function(t){var e,i; -for(i in t)e=t[i],"function"==typeof e?this[i]=e:this["_"+i]=e},_months:"January_February_March_April_May_June_July_August_September_October_November_December".split("_"),months:function(t){return this._months[t.month()]},_monthsShort:"Jan_Feb_Mar_Apr_May_Jun_Jul_Aug_Sep_Oct_Nov_Dec".split("_"),monthsShort:function(t){return this._monthsShort[t.month()]},monthsParse:function(t){var e,i,s;for(this._monthsParse||(this._monthsParse=[]),e=0;12>e;e++)if(this._monthsParse[e]||(i=I([2e3,e]),s="^"+this.months(i,"")+"|^"+this.monthsShort(i,""),this._monthsParse[e]=RegExp(s.replace(".",""),"i")),this._monthsParse[e].test(t))return e},_weekdays:"Sunday_Monday_Tuesday_Wednesday_Thursday_Friday_Saturday".split("_"),weekdays:function(t){return this._weekdays[t.day()]},_weekdaysShort:"Sun_Mon_Tue_Wed_Thu_Fri_Sat".split("_"),weekdaysShort:function(t){return this._weekdaysShort[t.day()]},_weekdaysMin:"Su_Mo_Tu_We_Th_Fr_Sa".split("_"),weekdaysMin:function(t){return this._weekdaysMin[t.day()]},_longDateFormat:{LT:"h:mm A",L:"MM/DD/YYYY",LL:"MMMM D YYYY",LLL:"MMMM D YYYY LT",LLLL:"dddd, MMMM D YYYY LT"},longDateFormat:function(t){var e=this._longDateFormat[t];return!e&&this._longDateFormat[t.toUpperCase()]&&(e=this._longDateFormat[t.toUpperCase()].replace(/MMMM|MM|DD|dddd/g,function(t){return t.slice(1)}),this._longDateFormat[t]=e),e},meridiem:function(t,e,i){return t>11?i?"pm":"PM":i?"am":"AM"},_calendar:{sameDay:"[Today at] LT",nextDay:"[Tomorrow at] LT",nextWeek:"dddd [at] LT",lastDay:"[Yesterday at] LT",lastWeek:"[last] dddd [at] LT",sameElse:"L"},calendar:function(t,e){var i=this._calendar[t];return"function"==typeof i?i.apply(e):i},_relativeTime:{future:"in %s",past:"%s ago",s:"a few seconds",m:"a minute",mm:"%d minutes",h:"an hour",hh:"%d hours",d:"a day",dd:"%d days",M:"a month",MM:"%d months",y:"a year",yy:"%d years"},relativeTime:function(t,e,i,s){var n=this._relativeTime[i];return"function"==typeof n?n(t,e,i,s):n.replace(/%d/i,t)},pastFuture:function(t,e){var i=this._relativeTime[t>0?"future":"past"];return"function"==typeof i?i(e):i.replace(/%s/i,e)},ordinal:function(t){return this._ordinal.replace("%d",t)},_ordinal:"%d",preparse:function(t){return t},postformat:function(t){return t},week:function(t){return L(t,this._week.dow,this._week.doy)},_week:{dow:0,doy:6}},I=function(t,e,i){return O({_i:t,_f:e,_l:i,_isUTC:!1})},I.utc=function(t,e,i){return O({_useUTC:!0,_isUTC:!0,_l:i,_i:t,_f:e})},I.unix=function(t){return I(1e3*t)},I.duration=function(t,e){var i,s=I.isDuration(t),n="number"==typeof t,o=s?t._data:n?{}:t;return n&&(e?o[e]=t:o.milliseconds=t),i=new h(o),s&&t.hasOwnProperty("_lang")&&(i._lang=t._lang),i},I.version=P,I.defaultFormat=$,I.lang=function(t,e){return t?(e?m(t,e):z[t]||g(t),I.duration.fn._lang=I.fn._lang=g(t),s):I.fn._lang._abbr},I.langData=function(t){return t&&t._lang&&t._lang._abbr&&(t=t._lang._abbr),g(t)},I.isMoment=function(t){return t instanceof a},I.isDuration=function(t){return t instanceof h},I.fn=a.prototype={clone:function(){return I(this)},valueOf:function(){return+this._d},unix:function(){return Math.floor(+this._d/1e3)},toString:function(){return this.format("ddd MMM DD YYYY HH:mm:ss [GMT]ZZ")},toDate:function(){return this._d},toJSON:function(){return I.utc(this).format("YYYY-MM-DD[T]HH:mm:ss.SSS[Z]")},toArray:function(){var t=this;return[t.year(),t.month(),t.date(),t.hours(),t.minutes(),t.seconds(),t.milliseconds()]},isValid:function(){return null==this._isValid&&(this._isValid=this._a?!f(this._a,(this._isUTC?I.utc(this._a):I(this._a)).toArray()):!isNaN(this._d.getTime())),!!this._isValid},utc:function(){return this._isUTC=!0,this},local:function(){return this._isUTC=!1,this},format:function(t){var e=b(this,t||I.defaultFormat);return this.lang().postformat(e)},add:function(t,e){var i;return i="string"==typeof t?I.duration(+e,t):I.duration(t,e),c(this,i,1),this},subtract:function(t,e){var i;return i="string"==typeof t?I.duration(+e,t):I.duration(t,e),c(this,i,-1),this},diff:function(t,e,i){var s,n,o=this._isUTC?I(t).utc():I(t).local(),r=6e4*(this.zone()-o.zone());return e&&(e=e.replace(/s$/,"")),"year"===e||"month"===e?(s=432e5*(this.daysInMonth()+o.daysInMonth()),n=12*(this.year()-o.year())+(this.month()-o.month()),n+=(this-I(this).startOf("month")-(o-I(o).startOf("month")))/s,"year"===e&&(n/=12)):(s=this-o-r,n="second"===e?s/1e3:"minute"===e?s/6e4:"hour"===e?s/36e5:"day"===e?s/864e5:"week"===e?s/6048e5:s),i?n:l(n)},from:function(t,e){return I.duration(this.diff(t)).lang(this.lang()._abbr).humanize(!e)},fromNow:function(t){return this.from(I(),t)},calendar:function(){var t=this.diff(I().startOf("day"),"days",!0),e=-6>t?"sameElse":-1>t?"lastWeek":0>t?"lastDay":1>t?"sameDay":2>t?"nextDay":7>t?"nextWeek":"sameElse";return this.format(this.lang().calendar(e,this))},isLeapYear:function(){var t=this.year();return 0===t%4&&0!==t%100||0===t%400},isDST:function(){return this.zone()+I(t).startOf(e)},isBefore:function(t,e){return e=e!==s?e:"millisecond",+this.clone().startOf(e)<+I(t).startOf(e)},isSame:function(t,e){return e=e!==s?e:"millisecond",+this.clone().startOf(e)===+I(t).startOf(e)},zone:function(){return this._isUTC?0:this._d.getTimezoneOffset()},daysInMonth:function(){return I.utc([this.year(),this.month()+1,0]).date()},dayOfYear:function(t){var e=Y((I(this).startOf("day")-I(this).startOf("year"))/864e5)+1;return null==t?e:this.add("d",t-e)},isoWeek:function(t){var e=L(this,1,4);return null==t?e:this.add("d",7*(t-e))},week:function(t){var e=this.lang().week(this);return null==t?e:this.add("d",7*(t-e))},lang:function(t){return t===s?this._lang:(this._lang=g(t),this)}},F=0;ie.length>F;F++)N(ie[F].toLowerCase().replace(/s$/,""),ie[F]);N("year","FullYear"),I.fn.days=I.fn.day,I.fn.weeks=I.fn.week,I.fn.isoWeeks=I.fn.isoWeek,I.duration.fn=h.prototype={weeks:function(){return l(this.days()/7)},valueOf:function(){return this._milliseconds+864e5*this._days+2592e6*this._months},humanize:function(t){var e=+this,i=C(e,!t,this.lang());return t&&(i=this.lang().pastFuture(e,i)),this.lang().postformat(i)},lang:I.fn.lang};for(F in se)se.hasOwnProperty(F)&&(k(F,se[F]),A(F.toLowerCase()));k("Weeks",6048e5),I.lang("en",{ordinal:function(t){var e=t%10,i=1===~~(t%100/10)?"th":1===e?"st":2===e?"nd":3===e?"rd":"th";return t+i}}),R&&(i.exports=I),"undefined"==typeof ender&&(this.moment=I),"function"==typeof t&&t.amd&&t("moment",[],function(){return I})}).call(this)})()},{}]},{},[1])(1)}); \ No newline at end of file +(function(t){if("function"==typeof bootstrap)bootstrap("vis",t);else if("object"==typeof exports)module.exports=t();else if("function"==typeof define&&define.amd)define(t);else if("undefined"!=typeof ses){if(!ses.ok())return;ses.makeVis=t}else"undefined"!=typeof window?window.vis=t():global.vis=t()})(function(){var t;return function e(t,i,n){function s(r,a){if(!i[r]){if(!t[r]){var h="function"==typeof require&&require;if(!a&&h)return h(r,!0);if(o)return o(r,!0);throw Error("Cannot find module '"+r+"'")}var d=i[r]={exports:{}};t[r][0].call(d.exports,function(e){var i=t[r][1][e];return s(i?i:e)},d,d.exports,e,t,i,n)}return i[r].exports}for(var o="function"==typeof require&&require,r=0;n.length>r;r++)s(n[r]);return s}({1:[function(t,e){(function(t,i){"use strict";function n(){if(!s.READY){s.event.determineEventTypes();for(var t in s.gestures)s.gestures.hasOwnProperty(t)&&s.detection.register(s.gestures[t]);s.event.onTouch(s.DOCUMENT,s.EVENT_MOVE,s.detection.detect),s.event.onTouch(s.DOCUMENT,s.EVENT_END,s.detection.detect),s.READY=!0}}var s=function(t,e){return new s.Instance(t,e||{})};s.defaults={stop_browser_behavior:{userSelect:"none",touchAction:"none",touchCallout:"none",contentZooming:"none",userDrag:"none",tapHighlightColor:"rgba(0,0,0,0)"}},s.HAS_POINTEREVENTS=navigator.pointerEnabled||navigator.msPointerEnabled,s.HAS_TOUCHEVENTS="ontouchstart"in t,s.MOBILE_REGEX=/mobile|tablet|ip(ad|hone|od)|android/i,s.NO_MOUSEEVENTS=s.HAS_TOUCHEVENTS&&navigator.userAgent.match(s.MOBILE_REGEX),s.EVENT_TYPES={},s.DIRECTION_DOWN="down",s.DIRECTION_LEFT="left",s.DIRECTION_UP="up",s.DIRECTION_RIGHT="right",s.POINTER_MOUSE="mouse",s.POINTER_TOUCH="touch",s.POINTER_PEN="pen",s.EVENT_START="start",s.EVENT_MOVE="move",s.EVENT_END="end",s.DOCUMENT=document,s.plugins={},s.READY=!1,s.Instance=function(t,e){var i=this;return n(),this.element=t,this.enabled=!0,this.options=s.utils.extend(s.utils.extend({},s.defaults),e||{}),this.options.stop_browser_behavior&&s.utils.stopDefaultBrowserBehavior(this.element,this.options.stop_browser_behavior),s.event.onTouch(t,s.EVENT_START,function(t){i.enabled&&s.detection.startDetect(i,t)}),this},s.Instance.prototype={on:function(t,e){for(var i=t.split(" "),n=0;i.length>n;n++)this.element.addEventListener(i[n],e,!1);return this},off:function(t,e){for(var i=t.split(" "),n=0;i.length>n;n++)this.element.removeEventListener(i[n],e,!1);return this},trigger:function(t,e){var i=s.DOCUMENT.createEvent("Event");i.initEvent(t,!0,!0),i.gesture=e;var n=this.element;return s.utils.hasParent(e.target,n)&&(n=e.target),n.dispatchEvent(i),this},enable:function(t){return this.enabled=t,this}};var o=null,r=!1,a=!1;s.event={bindDom:function(t,e,i){for(var n=e.split(" "),s=0;n.length>s;s++)t.addEventListener(n[s],i,!1)},onTouch:function(t,e,i){var n=this;this.bindDom(t,s.EVENT_TYPES[e],function(h){var d=h.type.toLowerCase();if(!d.match(/mouse/)||!a){(d.match(/touch/)||d.match(/pointerdown/)||d.match(/mouse/)&&1===h.which)&&(r=!0),d.match(/touch|pointer/)&&(a=!0);var l=0;r&&(s.HAS_POINTEREVENTS&&e!=s.EVENT_END?l=s.PointerEvent.updatePointer(e,h):d.match(/touch/)?l=h.touches.length:a||(l=d.match(/up/)?0:1),l>0&&e==s.EVENT_END?e=s.EVENT_MOVE:l||(e=s.EVENT_END),l||null===o?o=h:h=o,i.call(s.detection,n.collectEventData(t,e,h)),s.HAS_POINTEREVENTS&&e==s.EVENT_END&&(l=s.PointerEvent.updatePointer(e,h))),l||(o=null,r=!1,a=!1,s.PointerEvent.reset())}})},determineEventTypes:function(){var t;t=s.HAS_POINTEREVENTS?s.PointerEvent.getEvents():s.NO_MOUSEEVENTS?["touchstart","touchmove","touchend touchcancel"]:["touchstart mousedown","touchmove mousemove","touchend touchcancel mouseup"],s.EVENT_TYPES[s.EVENT_START]=t[0],s.EVENT_TYPES[s.EVENT_MOVE]=t[1],s.EVENT_TYPES[s.EVENT_END]=t[2]},getTouchList:function(t){return s.HAS_POINTEREVENTS?s.PointerEvent.getTouchList():t.touches?t.touches:[{identifier:1,pageX:t.pageX,pageY:t.pageY,target:t.target}]},collectEventData:function(t,e,i){var n=this.getTouchList(i,e),o=s.POINTER_TOUCH;return(i.type.match(/mouse/)||s.PointerEvent.matchType(s.POINTER_MOUSE,i))&&(o=s.POINTER_MOUSE),{center:s.utils.getCenter(n),timeStamp:(new Date).getTime(),target:i.target,touches:n,eventType:e,pointerType:o,srcEvent:i,preventDefault:function(){this.srcEvent.preventManipulation&&this.srcEvent.preventManipulation(),this.srcEvent.preventDefault&&this.srcEvent.preventDefault()},stopPropagation:function(){this.srcEvent.stopPropagation()},stopDetect:function(){return s.detection.stopDetect()}}}},s.PointerEvent={pointers:{},getTouchList:function(){var t=this,e=[];return Object.keys(t.pointers).sort().forEach(function(i){e.push(t.pointers[i])}),e},updatePointer:function(t,e){return t==s.EVENT_END?this.pointers={}:(e.identifier=e.pointerId,this.pointers[e.pointerId]=e),Object.keys(this.pointers).length},matchType:function(t,e){if(!e.pointerType)return!1;var i={};return i[s.POINTER_MOUSE]=e.pointerType==e.MSPOINTER_TYPE_MOUSE||e.pointerType==s.POINTER_MOUSE,i[s.POINTER_TOUCH]=e.pointerType==e.MSPOINTER_TYPE_TOUCH||e.pointerType==s.POINTER_TOUCH,i[s.POINTER_PEN]=e.pointerType==e.MSPOINTER_TYPE_PEN||e.pointerType==s.POINTER_PEN,i[t]},getEvents:function(){return["pointerdown MSPointerDown","pointermove MSPointerMove","pointerup pointercancel MSPointerUp MSPointerCancel"]},reset:function(){this.pointers={}}},s.utils={extend:function(t,e,n){for(var s in e)t[s]!==i&&n||(t[s]=e[s]);return t},hasParent:function(t,e){for(;t;){if(t==e)return!0;t=t.parentNode}return!1},getCenter:function(t){for(var e=[],i=[],n=0,s=t.length;s>n;n++)e.push(t[n].pageX),i.push(t[n].pageY);return{pageX:(Math.min.apply(Math,e)+Math.max.apply(Math,e))/2,pageY:(Math.min.apply(Math,i)+Math.max.apply(Math,i))/2}},getVelocity:function(t,e,i){return{x:Math.abs(e/t)||0,y:Math.abs(i/t)||0}},getAngle:function(t,e){var i=e.pageY-t.pageY,n=e.pageX-t.pageX;return 180*Math.atan2(i,n)/Math.PI},getDirection:function(t,e){var i=Math.abs(t.pageX-e.pageX),n=Math.abs(t.pageY-e.pageY);return i>=n?t.pageX-e.pageX>0?s.DIRECTION_LEFT:s.DIRECTION_RIGHT:t.pageY-e.pageY>0?s.DIRECTION_UP:s.DIRECTION_DOWN},getDistance:function(t,e){var i=e.pageX-t.pageX,n=e.pageY-t.pageY;return Math.sqrt(i*i+n*n)},getScale:function(t,e){return t.length>=2&&e.length>=2?this.getDistance(e[0],e[1])/this.getDistance(t[0],t[1]):1},getRotation:function(t,e){return t.length>=2&&e.length>=2?this.getAngle(e[1],e[0])-this.getAngle(t[1],t[0]):0},isVertical:function(t){return t==s.DIRECTION_UP||t==s.DIRECTION_DOWN},stopDefaultBrowserBehavior:function(t,e){var i,n=["webkit","khtml","moz","ms","o",""];if(e&&t.style){for(var s=0;n.length>s;s++)for(var o in e)e.hasOwnProperty(o)&&(i=o,n[s]&&(i=n[s]+i.substring(0,1).toUpperCase()+i.substring(1)),t.style[i]=e[o]);"none"==e.userSelect&&(t.onselectstart=function(){return!1})}}},s.detection={gestures:[],current:null,previous:null,stopped:!1,startDetect:function(t,e){this.current||(this.stopped=!1,this.current={inst:t,startEvent:s.utils.extend({},e),lastEvent:!1,name:""},this.detect(e))},detect:function(t){if(this.current&&!this.stopped){t=this.extendEventData(t);for(var e=this.current.inst.options,i=0,n=this.gestures.length;n>i;i++){var o=this.gestures[i];if(!this.stopped&&e[o.name]!==!1&&o.handler.call(o,t,this.current.inst)===!1){this.stopDetect();break}}return this.current&&(this.current.lastEvent=t),t.eventType==s.EVENT_END&&!t.touches.length-1&&this.stopDetect(),t}},stopDetect:function(){this.previous=s.utils.extend({},this.current),this.current=null,this.stopped=!0},extendEventData:function(t){var e=this.current.startEvent;if(e&&(t.touches.length!=e.touches.length||t.touches===e.touches)){e.touches=[];for(var i=0,n=t.touches.length;n>i;i++)e.touches.push(s.utils.extend({},t.touches[i]))}var o=t.timeStamp-e.timeStamp,r=t.center.pageX-e.center.pageX,a=t.center.pageY-e.center.pageY,h=s.utils.getVelocity(o,r,a);return s.utils.extend(t,{deltaTime:o,deltaX:r,deltaY:a,velocityX:h.x,velocityY:h.y,distance:s.utils.getDistance(e.center,t.center),angle:s.utils.getAngle(e.center,t.center),direction:s.utils.getDirection(e.center,t.center),scale:s.utils.getScale(e.touches,t.touches),rotation:s.utils.getRotation(e.touches,t.touches),startEvent:e}),t},register:function(t){var e=t.defaults||{};return e[t.name]===i&&(e[t.name]=!0),s.utils.extend(s.defaults,e,!0),t.index=t.index||1e3,this.gestures.push(t),this.gestures.sort(function(t,e){return t.indexe.index?1:0}),this.gestures}},s.gestures=s.gestures||{},s.gestures.Hold={name:"hold",index:10,defaults:{hold_timeout:500,hold_threshold:1},timer:null,handler:function(t,e){switch(t.eventType){case s.EVENT_START:clearTimeout(this.timer),s.detection.current.name=this.name,this.timer=setTimeout(function(){"hold"==s.detection.current.name&&e.trigger("hold",t)},e.options.hold_timeout);break;case s.EVENT_MOVE:t.distance>e.options.hold_threshold&&clearTimeout(this.timer);break;case s.EVENT_END:clearTimeout(this.timer)}}},s.gestures.Tap={name:"tap",index:100,defaults:{tap_max_touchtime:250,tap_max_distance:10,tap_always:!0,doubletap_distance:20,doubletap_interval:300},handler:function(t,e){if(t.eventType==s.EVENT_END){var i=s.detection.previous,n=!1;if(t.deltaTime>e.options.tap_max_touchtime||t.distance>e.options.tap_max_distance)return;i&&"tap"==i.name&&t.timeStamp-i.lastEvent.timeStamp0&&t.touches.length>e.options.swipe_max_touches)return;(t.velocityX>e.options.swipe_velocity||t.velocityY>e.options.swipe_velocity)&&(e.trigger(this.name,t),e.trigger(this.name+t.direction,t))}}},s.gestures.Drag={name:"drag",index:50,defaults:{drag_min_distance:10,drag_max_touches:1,drag_block_horizontal:!1,drag_block_vertical:!1,drag_lock_to_axis:!1,drag_lock_min_distance:25},triggered:!1,handler:function(t,e){if(s.detection.current.name!=this.name&&this.triggered)return e.trigger(this.name+"end",t),this.triggered=!1,i;if(!(e.options.drag_max_touches>0&&t.touches.length>e.options.drag_max_touches))switch(t.eventType){case s.EVENT_START:this.triggered=!1;break;case s.EVENT_MOVE:if(t.distancet.deltaY?s.DIRECTION_UP:s.DIRECTION_DOWN:0>t.deltaX?s.DIRECTION_LEFT:s.DIRECTION_RIGHT),this.triggered||(e.trigger(this.name+"start",t),this.triggered=!0),e.trigger(this.name,t),e.trigger(this.name+t.direction,t),(e.options.drag_block_vertical&&s.utils.isVertical(t.direction)||e.options.drag_block_horizontal&&!s.utils.isVertical(t.direction))&&t.preventDefault();break;case s.EVENT_END:this.triggered&&e.trigger(this.name+"end",t),this.triggered=!1}}},s.gestures.Transform={name:"transform",index:45,defaults:{transform_min_scale:.01,transform_min_rotation:1,transform_always_block:!1},triggered:!1,handler:function(t,e){if(s.detection.current.name!=this.name&&this.triggered)return e.trigger(this.name+"end",t),this.triggered=!1,i;if(!(2>t.touches.length))switch(e.options.transform_always_block&&t.preventDefault(),t.eventType){case s.EVENT_START:this.triggered=!1;break;case s.EVENT_MOVE:var n=Math.abs(1-t.scale),o=Math.abs(t.rotation);if(e.options.transform_min_scale>n&&e.options.transform_min_rotation>o)return;s.detection.current.name=this.name,this.triggered||(e.trigger(this.name+"start",t),this.triggered=!0),e.trigger(this.name,t),o>e.options.transform_min_rotation&&e.trigger("rotate",t),n>e.options.transform_min_scale&&(e.trigger("pinch",t),e.trigger("pinch"+(1>t.scale?"in":"out"),t));break;case s.EVENT_END:this.triggered&&e.trigger(this.name+"end",t),this.triggered=!1}}},s.gestures.Touch={name:"touch",index:-1/0,defaults:{prevent_default:!1,prevent_mouseevents:!1},handler:function(t,e){return e.options.prevent_mouseevents&&t.pointerType==s.POINTER_MOUSE?(t.stopDetect(),i):(e.options.prevent_default&&t.preventDefault(),t.eventType==s.EVENT_START&&e.trigger(this.name,t),i)}},s.gestures.Release={name:"release",index:1/0,handler:function(t,e){t.eventType==s.EVENT_END&&e.trigger(this.name,t)}},"object"==typeof e&&"object"==typeof e.exports?e.exports=s:(t.Hammer=s,"function"==typeof t.define&&t.define.amd&&t.define("hammer",[],function(){return s}))})(this)},{}],2:[function(e,i){(function(n){function s(t,e){return function(i){return u(t.call(this,i),e)}}function o(t,e){return function(i){return this.lang().ordinal(t.call(this,i),e)}}function r(){}function a(t){d(this,t)}function h(t){var e=t.years||t.year||t.y||0,i=t.months||t.month||t.M||0,n=t.weeks||t.week||t.w||0,s=t.days||t.day||t.d||0,o=t.hours||t.hour||t.h||0,r=t.minutes||t.minute||t.m||0,a=t.seconds||t.second||t.s||0,h=t.milliseconds||t.millisecond||t.ms||0;this._input=t,this._milliseconds=+h+1e3*a+6e4*r+36e5*o,this._days=+s+7*n,this._months=+i+12*e,this._data={},this._bubble()}function d(t,e){for(var i in e)e.hasOwnProperty(i)&&(t[i]=e[i]);return t}function l(t){return 0>t?Math.ceil(t):Math.floor(t)}function u(t,e){for(var i=t+"";e>i.length;)i="0"+i;return i}function c(t,e,i,n){var s,o,r=e._milliseconds,a=e._days,h=e._months;r&&t._d.setTime(+t._d+r*i),(a||h)&&(s=t.minute(),o=t.hour()),a&&t.date(t.date()+a*i),h&&t.month(t.month()+h*i),r&&!n&&H.updateOffset(t),(a||h)&&(t.minute(s),t.hour(o))}function p(t){return"[object Array]"===Object.prototype.toString.call(t)}function f(t,e){var i,n=Math.min(t.length,e.length),s=Math.abs(t.length-e.length),o=0;for(i=0;n>i;i++)~~t[i]!==~~e[i]&&o++;return o+s}function m(t){return t?ue[t]||t.toLowerCase().replace(/(.)s$/,"$1"):t}function g(t,e){return e.abbr=t,V[t]||(V[t]=new r),V[t].set(e),V[t]}function v(t){delete V[t]}function y(t){if(!t)return H.fn._lang;if(!V[t]&&B)try{e("./lang/"+t)}catch(i){return H.fn._lang}return V[t]||H.fn._lang}function b(t){return t.match(/\[.*\]/)?t.replace(/^\[|\]$/g,""):t.replace(/\\/g,"")}function w(t){var e,i,n=t.match(G);for(e=0,i=n.length;i>e;e++)n[e]=me[n[e]]?me[n[e]]:b(n[e]);return function(s){var o="";for(e=0;i>e;e++)o+=n[e]instanceof Function?n[e].call(s,t):n[e];return o}}function _(t,e){return e=E(e,t.lang()),ce[e]||(ce[e]=w(e)),ce[e](t)}function E(t,e){function i(t){return e.longDateFormat(t)||t}for(var n=5;n--&&(K.lastIndex=0,K.test(t));)t=t.replace(K,i);return t}function T(t,e){switch(t){case"DDDD":return Q;case"YYYY":return $;case"YYYYY":return te;case"S":case"SS":case"SSS":case"DDD":return J;case"MMM":case"MMMM":case"dd":case"ddd":case"dddd":return ee;case"a":case"A":return y(e._l)._meridiemParse;case"X":return se;case"Z":case"ZZ":return ie;case"T":return ne;case"MM":case"DD":case"YY":case"HH":case"hh":case"mm":case"ss":case"M":case"D":case"d":case"H":case"h":case"m":case"s":return Z;default:return RegExp(t.replace("\\",""))}}function x(t){var e=(ie.exec(t)||[])[0],i=(e+"").match(he)||["-",0,0],n=+(60*i[1])+~~i[2];return"+"===i[0]?-n:n}function S(t,e,i){var n,s=i._a;switch(t){case"M":case"MM":null!=e&&(s[1]=~~e-1);break;case"MMM":case"MMMM":n=y(i._l).monthsParse(e),null!=n?s[1]=n:i._isValid=!1;break;case"D":case"DD":null!=e&&(s[2]=~~e);break;case"DDD":case"DDDD":null!=e&&(s[1]=0,s[2]=~~e);break;case"YY":s[0]=~~e+(~~e>68?1900:2e3);break;case"YYYY":case"YYYYY":s[0]=~~e;break;case"a":case"A":i._isPm=y(i._l).isPM(e);break;case"H":case"HH":case"h":case"hh":s[3]=~~e;break;case"m":case"mm":s[4]=~~e;break;case"s":case"ss":s[5]=~~e;break;case"S":case"SS":case"SSS":s[6]=~~(1e3*("0."+e));break;case"X":i._d=new Date(1e3*parseFloat(e));break;case"Z":case"ZZ":i._useUTC=!0,i._tzm=x(e)}null==e&&(i._isValid=!1)}function M(t){var e,i,n,s=[];if(!t._d){for(n=C(t),e=0;3>e&&null==t._a[e];++e)t._a[e]=s[e]=n[e];for(;7>e;e++)t._a[e]=s[e]=null==t._a[e]?2===e?1:0:t._a[e];s[3]+=~~((t._tzm||0)/60),s[4]+=~~((t._tzm||0)%60),i=new Date(0),t._useUTC?(i.setUTCFullYear(s[0],s[1],s[2]),i.setUTCHours(s[3],s[4],s[5],s[6])):(i.setFullYear(s[0],s[1],s[2]),i.setHours(s[3],s[4],s[5],s[6])),t._d=i}}function D(t){var e=t._i;t._d||(t._a=[e.years||e.year||e.y,e.months||e.month||e.M,e.days||e.day||e.d,e.hours||e.hour||e.h,e.minutes||e.minute||e.m,e.seconds||e.second||e.s,e.milliseconds||e.millisecond||e.ms],M(t))}function C(t){var e=new Date;return t._useUTC?[e.getUTCFullYear(),e.getUTCMonth(),e.getUTCDate()]:[e.getFullYear(),e.getMonth(),e.getDate()]}function O(t){var e,i,n,s=y(t._l),o=""+t._i;for(n=E(t._f,s).match(G),t._a=[],e=0;n.length>e;e++)i=(T(n[e],t).exec(o)||[])[0],i&&(o=o.slice(o.indexOf(i)+i.length)),me[n[e]]&&S(n[e],i,t);o&&(t._il=o),t._isPm&&12>t._a[3]&&(t._a[3]+=12),t._isPm===!1&&12===t._a[3]&&(t._a[3]=0),M(t)}function N(t){var e,i,n,s,o,r=99;for(s=0;t._f.length>s;s++)e=d({},t),e._f=t._f[s],O(e),i=new a(e),o=f(e._a,i.toArray()),i._il&&(o+=i._il.length),r>o&&(r=o,n=i);d(t,n)}function L(t){var e,i=t._i,n=oe.exec(i);if(n){for(t._f="YYYY-MM-DD"+(n[2]||" "),e=0;4>e;e++)if(ae[e][1].exec(i)){t._f+=ae[e][0];break}ie.exec(i)&&(t._f+=" Z"),O(t)}else t._d=new Date(i)}function k(t){var e=t._i,i=X.exec(e);e===n?t._d=new Date:i?t._d=new Date(+i[1]):"string"==typeof e?L(t):p(e)?(t._a=e.slice(0),M(t)):e instanceof Date?t._d=new Date(+e):"object"==typeof e?D(t):t._d=new Date(e)}function I(t,e,i,n,s){return s.relativeTime(e||1,!!i,t,n)}function A(t,e,i){var n=W(Math.abs(t)/1e3),s=W(n/60),o=W(s/60),r=W(o/24),a=W(r/365),h=45>n&&["s",n]||1===s&&["m"]||45>s&&["mm",s]||1===o&&["h"]||22>o&&["hh",o]||1===r&&["d"]||25>=r&&["dd",r]||45>=r&&["M"]||345>r&&["MM",W(r/30)]||1===a&&["y"]||["yy",a];return h[2]=e,h[3]=t>0,h[4]=i,I.apply({},h)}function P(t,e,i){var n,s=i-e,o=i-t.day();return o>s&&(o-=7),s-7>o&&(o+=7),n=H(t).add("d",o),{week:Math.ceil(n.dayOfYear()/7),year:n.year()}}function F(t){var e=t._i,i=t._f;return null===e||""===e?null:("string"==typeof e&&(t._i=e=y().preparse(e)),H.isMoment(e)?(t=d({},e),t._d=new Date(+e._d)):i?p(i)?N(t):O(t):k(t),new a(t))}function Y(t,e){H.fn[t]=H.fn[t+"s"]=function(t){var i=this._isUTC?"UTC":"";return null!=t?(this._d["set"+i+e](t),H.updateOffset(this),this):this._d["get"+i+e]()}}function R(t){H.duration.fn[t]=function(){return this._data[t]}}function z(t,e){H.duration.fn["as"+t]=function(){return+this/e}}for(var H,j,U="2.2.1",W=Math.round,V={},B=i!==n&&i.exports,X=/^\/?Date\((\-?\d+)/i,q=/(\-)?(?:(\d*)\.)?(\d+)\:(\d+)\:(\d+)\.?(\d{3})?/,G=/(\[[^\[]*\])|(\\)?(Mo|MM?M?M?|Do|DDDo|DD?D?D?|ddd?d?|do?|w[o|w]?|W[o|W]?|YYYYY|YYYY|YY|gg(ggg?)?|GG(GGG?)?|e|E|a|A|hh?|HH?|mm?|ss?|SS?S?|X|zz?|ZZ?|.)/g,K=/(\[[^\[]*\])|(\\)?(LT|LL?L?L?|l{1,4})/g,Z=/\d\d?/,J=/\d{1,3}/,Q=/\d{3}/,$=/\d{1,4}/,te=/[+\-]?\d{1,6}/,ee=/[0-9]*['a-z\u00A0-\u05FF\u0700-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF]+|[\u0600-\u06FF\/]+(\s*?[\u0600-\u06FF]+){1,2}/i,ie=/Z|[\+\-]\d\d:?\d\d/i,ne=/T/i,se=/[\+\-]?\d+(\.\d{1,3})?/,oe=/^\s*\d{4}-\d\d-\d\d((T| )(\d\d(:\d\d(:\d\d(\.\d\d?\d?)?)?)?)?([\+\-]\d\d:?\d\d)?)?/,re="YYYY-MM-DDTHH:mm:ssZ",ae=[["HH:mm:ss.S",/(T| )\d\d:\d\d:\d\d\.\d{1,3}/],["HH:mm:ss",/(T| )\d\d:\d\d:\d\d/],["HH:mm",/(T| )\d\d:\d\d/],["HH",/(T| )\d\d/]],he=/([\+\-]|\d\d)/gi,de="Date|Hours|Minutes|Seconds|Milliseconds".split("|"),le={Milliseconds:1,Seconds:1e3,Minutes:6e4,Hours:36e5,Days:864e5,Months:2592e6,Years:31536e6},ue={ms:"millisecond",s:"second",m:"minute",h:"hour",d:"day",w:"week",W:"isoweek",M:"month",y:"year"},ce={},pe="DDD w W M D d".split(" "),fe="M D H h m s w W".split(" "),me={M:function(){return this.month()+1},MMM:function(t){return this.lang().monthsShort(this,t)},MMMM:function(t){return this.lang().months(this,t)},D:function(){return this.date()},DDD:function(){return this.dayOfYear()},d:function(){return this.day()},dd:function(t){return this.lang().weekdaysMin(this,t)},ddd:function(t){return this.lang().weekdaysShort(this,t)},dddd:function(t){return this.lang().weekdays(this,t)},w:function(){return this.week()},W:function(){return this.isoWeek()},YY:function(){return u(this.year()%100,2)},YYYY:function(){return u(this.year(),4)},YYYYY:function(){return u(this.year(),5)},gg:function(){return u(this.weekYear()%100,2)},gggg:function(){return this.weekYear()},ggggg:function(){return u(this.weekYear(),5)},GG:function(){return u(this.isoWeekYear()%100,2)},GGGG:function(){return this.isoWeekYear()},GGGGG:function(){return u(this.isoWeekYear(),5)},e:function(){return this.weekday()},E:function(){return this.isoWeekday()},a:function(){return this.lang().meridiem(this.hours(),this.minutes(),!0)},A:function(){return this.lang().meridiem(this.hours(),this.minutes(),!1)},H:function(){return this.hours()},h:function(){return this.hours()%12||12},m:function(){return this.minutes()},s:function(){return this.seconds()},S:function(){return~~(this.milliseconds()/100)},SS:function(){return u(~~(this.milliseconds()/10),2)},SSS:function(){return u(this.milliseconds(),3)},Z:function(){var t=-this.zone(),e="+";return 0>t&&(t=-t,e="-"),e+u(~~(t/60),2)+":"+u(~~t%60,2)},ZZ:function(){var t=-this.zone(),e="+";return 0>t&&(t=-t,e="-"),e+u(~~(10*t/6),4)},z:function(){return this.zoneAbbr()},zz:function(){return this.zoneName()},X:function(){return this.unix()}};pe.length;)j=pe.pop(),me[j+"o"]=o(me[j],j);for(;fe.length;)j=fe.pop(),me[j+j]=s(me[j],2);for(me.DDDD=s(me.DDD,3),d(r.prototype,{set:function(t){var e,i;for(i in t)e=t[i],"function"==typeof e?this[i]=e:this["_"+i]=e},_months:"January_February_March_April_May_June_July_August_September_October_November_December".split("_"),months:function(t){return this._months[t.month()]},_monthsShort:"Jan_Feb_Mar_Apr_May_Jun_Jul_Aug_Sep_Oct_Nov_Dec".split("_"),monthsShort:function(t){return this._monthsShort[t.month()]},monthsParse:function(t){var e,i,n;for(this._monthsParse||(this._monthsParse=[]),e=0;12>e;e++)if(this._monthsParse[e]||(i=H.utc([2e3,e]),n="^"+this.months(i,"")+"|^"+this.monthsShort(i,""),this._monthsParse[e]=RegExp(n.replace(".",""),"i")),this._monthsParse[e].test(t))return e},_weekdays:"Sunday_Monday_Tuesday_Wednesday_Thursday_Friday_Saturday".split("_"),weekdays:function(t){return this._weekdays[t.day()]},_weekdaysShort:"Sun_Mon_Tue_Wed_Thu_Fri_Sat".split("_"),weekdaysShort:function(t){return this._weekdaysShort[t.day()]},_weekdaysMin:"Su_Mo_Tu_We_Th_Fr_Sa".split("_"),weekdaysMin:function(t){return this._weekdaysMin[t.day()]},weekdaysParse:function(t){var e,i,n;for(this._weekdaysParse||(this._weekdaysParse=[]),e=0;7>e;e++)if(this._weekdaysParse[e]||(i=H([2e3,1]).day(e),n="^"+this.weekdays(i,"")+"|^"+this.weekdaysShort(i,"")+"|^"+this.weekdaysMin(i,""),this._weekdaysParse[e]=RegExp(n.replace(".",""),"i")),this._weekdaysParse[e].test(t))return e},_longDateFormat:{LT:"h:mm A",L:"MM/DD/YYYY",LL:"MMMM D YYYY",LLL:"MMMM D YYYY LT",LLLL:"dddd, MMMM D YYYY LT"},longDateFormat:function(t){var e=this._longDateFormat[t];return!e&&this._longDateFormat[t.toUpperCase()]&&(e=this._longDateFormat[t.toUpperCase()].replace(/MMMM|MM|DD|dddd/g,function(t){return t.slice(1)}),this._longDateFormat[t]=e),e},isPM:function(t){return"p"===(t+"").toLowerCase().charAt(0)},_meridiemParse:/[ap]\.?m?\.?/i,meridiem:function(t,e,i){return t>11?i?"pm":"PM":i?"am":"AM"},_calendar:{sameDay:"[Today at] LT",nextDay:"[Tomorrow at] LT",nextWeek:"dddd [at] LT",lastDay:"[Yesterday at] LT",lastWeek:"[Last] dddd [at] LT",sameElse:"L"},calendar:function(t,e){var i=this._calendar[t];return"function"==typeof i?i.apply(e):i},_relativeTime:{future:"in %s",past:"%s ago",s:"a few seconds",m:"a minute",mm:"%d minutes",h:"an hour",hh:"%d hours",d:"a day",dd:"%d days",M:"a month",MM:"%d months",y:"a year",yy:"%d years"},relativeTime:function(t,e,i,n){var s=this._relativeTime[i];return"function"==typeof s?s(t,e,i,n):s.replace(/%d/i,t)},pastFuture:function(t,e){var i=this._relativeTime[t>0?"future":"past"];return"function"==typeof i?i(e):i.replace(/%s/i,e)},ordinal:function(t){return this._ordinal.replace("%d",t)},_ordinal:"%d",preparse:function(t){return t},postformat:function(t){return t},week:function(t){return P(t,this._week.dow,this._week.doy).week},_week:{dow:0,doy:6}}),H=function(t,e,i){return F({_i:t,_f:e,_l:i,_isUTC:!1})},H.utc=function(t,e,i){return F({_useUTC:!0,_isUTC:!0,_l:i,_i:t,_f:e}).utc()},H.unix=function(t){return H(1e3*t)},H.duration=function(t,e){var i,n,s=H.isDuration(t),o="number"==typeof t,r=s?t._input:o?{}:t,a=q.exec(t);return o?e?r[e]=t:r.milliseconds=t:a&&(i="-"===a[1]?-1:1,r={y:0,d:~~a[2]*i,h:~~a[3]*i,m:~~a[4]*i,s:~~a[5]*i,ms:~~a[6]*i}),n=new h(r),s&&t.hasOwnProperty("_lang")&&(n._lang=t._lang),n},H.version=U,H.defaultFormat=re,H.updateOffset=function(){},H.lang=function(t,e){return t?(t=t.toLowerCase(),t=t.replace("_","-"),e?g(t,e):null===e?(v(t),t="en"):V[t]||y(t),H.duration.fn._lang=H.fn._lang=y(t),n):H.fn._lang._abbr},H.langData=function(t){return t&&t._lang&&t._lang._abbr&&(t=t._lang._abbr),y(t)},H.isMoment=function(t){return t instanceof a},H.isDuration=function(t){return t instanceof h},d(H.fn=a.prototype,{clone:function(){return H(this)},valueOf:function(){return+this._d+6e4*(this._offset||0)},unix:function(){return Math.floor(+this/1e3)},toString:function(){return this.format("ddd MMM DD YYYY HH:mm:ss [GMT]ZZ")},toDate:function(){return this._offset?new Date(+this):this._d},toISOString:function(){return _(H(this).utc(),"YYYY-MM-DD[T]HH:mm:ss.SSS[Z]")},toArray:function(){var t=this;return[t.year(),t.month(),t.date(),t.hours(),t.minutes(),t.seconds(),t.milliseconds()]},isValid:function(){return null==this._isValid&&(this._isValid=this._a?!f(this._a,(this._isUTC?H.utc(this._a):H(this._a)).toArray()):!isNaN(this._d.getTime())),!!this._isValid},invalidAt:function(){var t,e=this._a,i=(this._isUTC?H.utc(this._a):H(this._a)).toArray();for(t=6;t>=0&&e[t]===i[t];--t);return t},utc:function(){return this.zone(0)},local:function(){return this.zone(0),this._isUTC=!1,this},format:function(t){var e=_(this,t||H.defaultFormat);return this.lang().postformat(e)},add:function(t,e){var i;return i="string"==typeof t?H.duration(+e,t):H.duration(t,e),c(this,i,1),this},subtract:function(t,e){var i;return i="string"==typeof t?H.duration(+e,t):H.duration(t,e),c(this,i,-1),this},diff:function(t,e,i){var n,s,o=this._isUTC?H(t).zone(this._offset||0):H(t).local(),r=6e4*(this.zone()-o.zone());return e=m(e),"year"===e||"month"===e?(n=432e5*(this.daysInMonth()+o.daysInMonth()),s=12*(this.year()-o.year())+(this.month()-o.month()),s+=(this-H(this).startOf("month")-(o-H(o).startOf("month")))/n,s-=6e4*(this.zone()-H(this).startOf("month").zone()-(o.zone()-H(o).startOf("month").zone()))/n,"year"===e&&(s/=12)):(n=this-o,s="second"===e?n/1e3:"minute"===e?n/6e4:"hour"===e?n/36e5:"day"===e?(n-r)/864e5:"week"===e?(n-r)/6048e5:n),i?s:l(s)},from:function(t,e){return H.duration(this.diff(t)).lang(this.lang()._abbr).humanize(!e)},fromNow:function(t){return this.from(H(),t)},calendar:function(){var t=this.diff(H().zone(this.zone()).startOf("day"),"days",!0),e=-6>t?"sameElse":-1>t?"lastWeek":0>t?"lastDay":1>t?"sameDay":2>t?"nextDay":7>t?"nextWeek":"sameElse";return this.format(this.lang().calendar(e,this))},isLeapYear:function(){var t=this.year();return 0===t%4&&0!==t%100||0===t%400},isDST:function(){return this.zone()+H(t).startOf(e)},isBefore:function(t,e){return e=e!==n?e:"millisecond",+this.clone().startOf(e)<+H(t).startOf(e)},isSame:function(t,e){return e=e!==n?e:"millisecond",+this.clone().startOf(e)===+H(t).startOf(e)},min:function(t){return t=H.apply(null,arguments),this>t?this:t},max:function(t){return t=H.apply(null,arguments),t>this?this:t},zone:function(t){var e=this._offset||0;return null==t?this._isUTC?e:this._d.getTimezoneOffset():("string"==typeof t&&(t=x(t)),16>Math.abs(t)&&(t=60*t),this._offset=t,this._isUTC=!0,e!==t&&c(this,H.duration(e-t,"m"),1,!0),this)},zoneAbbr:function(){return this._isUTC?"UTC":""},zoneName:function(){return this._isUTC?"Coordinated Universal Time":""},hasAlignedHourOffset:function(t){return t=t?H(t).zone():0,0===(this.zone()-t)%60},daysInMonth:function(){return H.utc([this.year(),this.month()+1,0]).date()},dayOfYear:function(t){var e=W((H(this).startOf("day")-H(this).startOf("year"))/864e5)+1;return null==t?e:this.add("d",t-e)},weekYear:function(t){var e=P(this,this.lang()._week.dow,this.lang()._week.doy).year;return null==t?e:this.add("y",t-e)},isoWeekYear:function(t){var e=P(this,1,4).year;return null==t?e:this.add("y",t-e)},week:function(t){var e=this.lang().week(this);return null==t?e:this.add("d",7*(t-e))},isoWeek:function(t){var e=P(this,1,4).week;return null==t?e:this.add("d",7*(t-e))},weekday:function(t){var e=(this._d.getDay()+7-this.lang()._week.dow)%7;return null==t?e:this.add("d",t-e)},isoWeekday:function(t){return null==t?this.day()||7:this.day(this.day()%7?t:t-7)},get:function(t){return t=m(t),this[t.toLowerCase()]()},set:function(t,e){t=m(t),this[t.toLowerCase()](e)},lang:function(t){return t===n?this._lang:(this._lang=y(t),this)}}),j=0;de.length>j;j++)Y(de[j].toLowerCase().replace(/s$/,""),de[j]);Y("year","FullYear"),H.fn.days=H.fn.day,H.fn.months=H.fn.month,H.fn.weeks=H.fn.week,H.fn.isoWeeks=H.fn.isoWeek,H.fn.toJSON=H.fn.toISOString,d(H.duration.fn=h.prototype,{_bubble:function(){var t,e,i,n,s=this._milliseconds,o=this._days,r=this._months,a=this._data;a.milliseconds=s%1e3,t=l(s/1e3),a.seconds=t%60,e=l(t/60),a.minutes=e%60,i=l(e/60),a.hours=i%24,o+=l(i/24),a.days=o%30,r+=l(o/30),a.months=r%12,n=l(r/12),a.years=n},weeks:function(){return l(this.days()/7)},valueOf:function(){return this._milliseconds+864e5*this._days+2592e6*(this._months%12)+31536e6*~~(this._months/12)},humanize:function(t){var e=+this,i=A(e,!t,this.lang());return t&&(i=this.lang().pastFuture(e,i)),this.lang().postformat(i)},add:function(t,e){var i=H.duration(t,e);return this._milliseconds+=i._milliseconds,this._days+=i._days,this._months+=i._months,this._bubble(),this},subtract:function(t,e){var i=H.duration(t,e);return this._milliseconds-=i._milliseconds,this._days-=i._days,this._months-=i._months,this._bubble(),this},get:function(t){return t=m(t),this[t.toLowerCase()+"s"]()},as:function(t){return t=m(t),this["as"+t.charAt(0).toUpperCase()+t.slice(1)+"s"]()},lang:H.fn.lang});for(j in le)le.hasOwnProperty(j)&&(z(j,le[j]),R(j.toLowerCase()));z("Weeks",6048e5),H.duration.fn.asMonths=function(){return(+this-31536e6*this.years())/2592e6+12*this.years()},H.lang("en",{ordinal:function(t){var e=t%10,i=1===~~(t%100/10)?"th":1===e?"st":2===e?"nd":3===e?"rd":"th";return t+i}}),B&&(i.exports=H),"undefined"==typeof ender&&(this.moment=H),"function"==typeof t&&t.amd&&t("moment",[],function(){return H})}).call(this)},{}],3:[function(e,i,n){function s(){this.subscriptions=[]}function o(t){if(this.id=C.randomUUID(),this.options=t||{},this.data={},this.fieldId=this.options.fieldId||"id",this.convert={},this.options.convert)for(var e in this.options.convert)if(this.options.convert.hasOwnProperty(e)){var i=this.options.convert[e];this.convert[e]="Date"==i||"ISODate"==i||"ASPDate"==i?"Date":i +}this.subscribers={},this.internalIds={}}function r(t,e){this.id=C.randomUUID(),this.data=null,this.ids={},this.options=e||{},this.fieldId="id",this.subscribers={};var i=this;this.listener=function(){i._onEvent.apply(i,arguments)},this.setData(t)}function a(t,e){this.parent=t,this.options=e||{},this.defaultOptions={order:function(t,e){if(t instanceof y){if(e instanceof y){var i=t.data.end-t.data.start,n=e.data.end-e.data.start;return i-n||t.data.start-e.data.start}return-1}return e instanceof y?1:t.data.start-e.data.start},margin:{item:10}},this.ordered=[]}function h(t){this.id=C.randomUUID(),this.start=0,this.end=0,this.options={min:null,max:null,zoomMin:null,zoomMax:null},this.listeners=[],this.setOptions(t)}function d(){this.id=C.randomUUID(),this.components={},this.repaintTimer=void 0,this.reflowTimer=void 0}function l(){this.id=null,this.parent=null,this.depends=null,this.controller=null,this.options=null,this.frame=null,this.top=0,this.left=0,this.width=0,this.height=0}function u(t,e,i){this.id=C.randomUUID(),this.parent=t,this.depends=e,this.options=i||{}}function c(t,e){this.id=C.randomUUID(),this.container=t,this.options=e||{},this.defaultOptions={autoResize:!0},this.listeners={}}function p(t,e,i){this.id=C.randomUUID(),this.parent=t,this.depends=e,this.dom={majorLines:[],majorTexts:[],minorLines:[],minorTexts:[],redundant:{majorLines:[],majorTexts:[],minorLines:[],minorTexts:[]}},this.props={range:{start:0,end:0,minimumStep:0},lineTop:0},this.options=i||{},this.defaultOptions={orientation:"bottom",showMinorLabels:!0,showMajorLabels:!0},this.conversion=null,this.range=null}function f(t,e,i){this.id=C.randomUUID(),this.parent=t,this.depends=e,this.options=i||{},this.defaultOptions={type:"box",align:"center",orientation:"bottom",margin:{axis:20,item:10},padding:5},this.dom={};var n=this;this.itemsData=null,this.range=null,this.listeners={add:function(t,e,i){i!=n.id&&n._onAdd(e.items)},update:function(t,e,i){i!=n.id&&n._onUpdate(e.items)},remove:function(t,e,i){i!=n.id&&n._onRemove(e.items)}},this.items={},this.queue={},this.stack=new a(this,Object.create(this.options)),this.conversion=null}function m(t,e,i,n){this.parent=t,this.data=e,this.dom=null,this.options=i||{},this.defaultOptions=n||{},this.selected=!1,this.visible=!1,this.top=0,this.left=0,this.width=0,this.height=0}function g(t,e,i,n){this.props={dot:{left:0,top:0,width:0,height:0},line:{top:0,left:0,width:0,height:0}},m.call(this,t,e,i,n)}function v(t,e,i,n){this.props={dot:{top:0,width:0,height:0},content:{height:0,marginLeft:0}},m.call(this,t,e,i,n)}function y(t,e,i,n){this.props={content:{left:0,width:0}},m.call(this,t,e,i,n)}function b(t,e,i){this.id=C.randomUUID(),this.parent=t,this.groupId=e,this.itemset=null,this.options=i||{},this.options.top=0,this.props={label:{width:0,height:0}},this.top=0,this.left=0,this.width=0,this.height=0}function w(t,e,i){this.id=C.randomUUID(),this.parent=t,this.depends=e,this.options=i||{},this.range=null,this.itemsData=null,this.groupsData=null,this.groups={},this.dom={},this.props={labels:{width:0}},this.queue={};var n=this;this.listeners={add:function(t,e){n._onAdd(e.items)},update:function(t,e){n._onUpdate(e.items)},remove:function(t,e){n._onRemove(e.items)}}}function _(t,e,i){var n=this;if(this.options=C.extend({orientation:"bottom",min:null,max:null,zoomMin:10,zoomMax:31536e10,showMinorLabels:!0,showMajorLabels:!0,autoResize:!1},i),this.controller=new d,!t)throw Error("No container element provided");var s=Object.create(this.options);s.height=function(){return n.options.height?n.options.height:n.timeaxis.height+n.content.height},this.rootPanel=new c(t,s),this.controller.add(this.rootPanel);var o=Object.create(this.options);o.left=function(){return n.labelPanel.width},o.width=function(){return n.rootPanel.width-n.labelPanel.width},o.top=null,o.height=null,this.itemPanel=new u(this.rootPanel,[],o),this.controller.add(this.itemPanel);var r=Object.create(this.options);r.top=null,r.left=null,r.height=null,r.width=function(){return n.content&&"function"==typeof n.content.getLabelsWidth?n.content.getLabelsWidth():0},this.labelPanel=new u(this.rootPanel,[],r),this.controller.add(this.labelPanel);var a=M().hours(0).minutes(0).seconds(0).milliseconds(0);this.range=new h({start:a.clone().add("days",-3).valueOf(),end:a.clone().add("days",4).valueOf()}),this.range.subscribe(this.rootPanel,"move","horizontal"),this.range.subscribe(this.rootPanel,"zoom","horizontal"),this.range.on("rangechange",function(){var t=!0;n.controller.requestReflow(t)}),this.range.on("rangechanged",function(){var t=!0;n.controller.requestReflow(t)});var l=Object.create(s);l.range=this.range,l.left=null,l.top=null,l.width="100%",l.height=null,this.timeaxis=new p(this.itemPanel,[],l),this.timeaxis.setRange(this.range),this.controller.add(this.timeaxis),this.setGroups(null),this.itemsData=null,this.groupsData=null,e&&this.setItems(e)}function E(t,e,i,n){this.selected=!1,this.edges=[],this.group=n.nodes.group,this.fontSize=n.nodes.fontSize,this.fontFace=n.nodes.fontFace,this.fontColor=n.nodes.fontColor,this.color=n.nodes.color,this.id=void 0,this.shape=n.nodes.shape,this.image=n.nodes.image,this.x=0,this.y=0,this.xFixed=!1,this.yFixed=!1,this.radius=n.nodes.radius,this.radiusFixed=!1,this.radiusMin=n.nodes.radiusMin,this.radiusMax=n.nodes.radiusMax,this.imagelist=e,this.grouplist=i,this.setProperties(t,n),this.mass=50,this.fx=0,this.fy=0,this.vx=0,this.vy=0,this.minForce=n.minForce,this.damping=.9}function T(t,e,i){if(!e)throw"No graph provided";this.graph=e,this.widthMin=i.edges.widthMin,this.widthMax=i.edges.widthMax,this.id=void 0,this.fromId=void 0,this.toId=void 0,this.style=i.edges.style,this.title=void 0,this.width=i.edges.width,this.value=void 0,this.length=i.edges.length,this.from=null,this.to=null,this.connected=!1,this.dash=C.extend({},i.edges.dash),this.stiffness=void 0,this.color=i.edges.color,this.widthFixed=!1,this.lengthFixed=!1,this.setProperties(t,i)}function x(t,e,i,n){this.container=t?t:document.body,this.x=0,this.y=0,this.padding=5,void 0!==e&&void 0!==i&&this.setPosition(e,i),void 0!==n&&this.setText(n),this.frame=document.createElement("div");var s=this.frame.style;s.position="absolute",s.visibility="hidden",s.border="1px solid #666",s.color="black",s.padding=this.padding+"px",s.backgroundColor="#FFFFC6",s.borderRadius="3px",s.MozBorderRadius="3px",s.WebkitBorderRadius="3px",s.boxShadow="3px 3px 10px rgba(128, 128, 128, 0.5)",s.whiteSpace="nowrap",this.container.appendChild(this.frame)}function S(t,e,i){this.containerElement=t,this.width="100%",this.height="100%",this.refreshRate=50,this.stabilize=!0,this.selectable=!0,this.constants={nodes:{radiusMin:5,radiusMax:20,radius:5,distance:100,shape:"ellipse",image:void 0,widthMin:16,widthMax:64,fontColor:"black",fontSize:14,fontFace:"arial",color:{border:"#2B7CE9",background:"#97C2FC",highlight:{border:"#2B7CE9",background:"#D2E5FF"}},borderColor:"#2B7CE9",backgroundColor:"#97C2FC",highlightColor:"#D2E5FF",group:void 0},edges:{widthMin:1,widthMax:15,width:1,style:"line",color:"#343434",fontColor:"#343434",fontSize:14,fontFace:"arial",length:100,dash:{length:10,gap:5,altLength:void 0}},minForce:.05,minVelocity:.02,maxIterations:1e3};var n=this;this.nodes={},this.edges={},this.nodesData=null,this.edgesData=null;var s=this;this.nodesListeners={add:function(t,e){s._addNodes(e.items),s.start()},update:function(t,e){s._updateNodes(e.items),s.start()},remove:function(t,e){s._removeNodes(e.items),s.start()}},this.edgesListeners={add:function(t,e){s._addEdges(e.items),s.start()},update:function(t,e){s._updateEdges(e.items),s.start()},remove:function(t,e){s._removeEdges(e.items),s.start()}},this.groups=new Groups,this.images=new Images,this.images.setOnloadCallback(function(){n._redraw()}),this.moving=!1,this.selection=[],this.timer=void 0,this._create(),this.setOptions(i),this.setData(e)}var M,D;"undefined"!=typeof window?(M=window.moment=window.moment?window.moment:e("moment"),D=window.hammerjs=window.hammerjs?window.hammerjs:e("hammerjs")):(M=e("moment"),D=e("hammerjs"));var C={};C.isNumber=function(t){return t instanceof Number||"number"==typeof t},C.isString=function(t){return t instanceof String||"string"==typeof t},C.isDate=function(t){if(t instanceof Date)return!0;if(C.isString(t)){var e=O.exec(t);if(e)return!0;if(!isNaN(Date.parse(t)))return!0}return!1},C.isDataTable=function(t){return"undefined"!=typeof google&&google.visualization&&google.visualization.DataTable&&t instanceof google.visualization.DataTable},C.randomUUID=function(){var t=function(){return Math.floor(65536*Math.random()).toString(16)};return t()+t()+"-"+t()+"-"+t()+"-"+t()+"-"+t()+t()+t()},C.extend=function(t){for(var e=1,i=arguments.length;i>e;e++){var n=arguments[e];for(var s in n)n.hasOwnProperty(s)&&void 0!==n[s]&&(t[s]=n[s])}return t},C.convert=function(t,e){var i;if(void 0===t)return void 0;if(null===t)return null;if(!e)return t;if("string"!=typeof e&&!(e instanceof String))throw Error("Type must be a string");switch(e){case"boolean":case"Boolean":return Boolean(t);case"number":case"Number":return Number(t.valueOf());case"string":case"String":return t+"";case"Date":if(C.isNumber(t))return new Date(t);if(t instanceof Date)return new Date(t.valueOf());if(M.isMoment(t))return new Date(t.valueOf());if(C.isString(t))return i=O.exec(t),i?new Date(Number(i[1])):M(t).toDate();throw Error("Cannot convert object of type "+C.getType(t)+" to type Date");case"Moment":if(C.isNumber(t))return M(t);if(t instanceof Date)return M(t.valueOf());if(M.isMoment(t))return M.clone();if(C.isString(t))return i=O.exec(t),i?M(Number(i[1])):M(t);throw Error("Cannot convert object of type "+C.getType(t)+" to type Date");case"ISODate":if(C.isNumber(t))return new Date(t);if(t instanceof Date)return t.toISOString();if(M.isMoment(t))return t.toDate().toISOString();if(C.isString(t))return i=O.exec(t),i?new Date(Number(i[1])).toISOString():new Date(t).toISOString();throw Error("Cannot convert object of type "+C.getType(t)+" to type ISODate");case"ASPDate":if(C.isNumber(t))return"/Date("+t+")/";if(t instanceof Date)return"/Date("+t.valueOf()+")/";if(C.isString(t)){i=O.exec(t);var n;return n=i?new Date(Number(i[1])).valueOf():new Date(t).valueOf(),"/Date("+n+")/"}throw Error("Cannot convert object of type "+C.getType(t)+" to type ASPDate");default:throw Error("Cannot convert object of type "+C.getType(t)+' to type "'+e+'"')}};var O=/^\/?Date\((\-?\d+)/i;if(C.getType=function(t){var e=typeof t;return"object"==e?null==t?"null":t instanceof Boolean?"Boolean":t instanceof Number?"Number":t instanceof String?"String":t instanceof Array?"Array":t instanceof Date?"Date":"Object":"number"==e?"Number":"boolean"==e?"Boolean":"string"==e?"String":e},C.getAbsoluteLeft=function(t){for(var e=document.documentElement,i=document.body,n=t.offsetLeft,s=t.offsetParent;null!=s&&s!=i&&s!=e;)n+=s.offsetLeft,n-=s.scrollLeft,s=s.offsetParent;return n},C.getAbsoluteTop=function(t){for(var e=document.documentElement,i=document.body,n=t.offsetTop,s=t.offsetParent;null!=s&&s!=i&&s!=e;)n+=s.offsetTop,n-=s.scrollTop,s=s.offsetParent;return n},C.getPageY=function(t){if("pageY"in t)return t.pageY;var e;e="targetTouches"in t&&t.targetTouches.length?t.targetTouches[0].clientY:t.clientY;var i=document.documentElement,n=document.body;return e+(i&&i.scrollTop||n&&n.scrollTop||0)-(i&&i.clientTop||n&&n.clientTop||0)},C.getPageX=function(t){if("pageY"in t)return t.pageX;var e;e="targetTouches"in t&&t.targetTouches.length?t.targetTouches[0].clientX:t.clientX;var i=document.documentElement,n=document.body;return e+(i&&i.scrollLeft||n&&n.scrollLeft||0)-(i&&i.clientLeft||n&&n.clientLeft||0)},C.addClassName=function(t,e){var i=t.className.split(" ");-1==i.indexOf(e)&&(i.push(e),t.className=i.join(" "))},C.removeClassName=function(t,e){var i=t.className.split(" "),n=i.indexOf(e);-1!=n&&(i.splice(n,1),t.className=i.join(" "))},C.forEach=function(t,e){var i,n;if(t instanceof Array)for(i=0,n=t.length;n>i;i++)e(t[i],i,t);else for(i in t)t.hasOwnProperty(i)&&e(t[i],i,t)},C.updateProperty=function(t,e,i){return t[e]!==i?(t[e]=i,!0):!1},C.addEventListener=function(t,e,i,n){t.addEventListener?(void 0===n&&(n=!1),"mousewheel"===e&&navigator.userAgent.indexOf("Firefox")>=0&&(e="DOMMouseScroll"),t.addEventListener(e,i,n)):t.attachEvent("on"+e,i)},C.removeEventListener=function(t,e,i,n){t.removeEventListener?(void 0===n&&(n=!1),"mousewheel"===e&&navigator.userAgent.indexOf("Firefox")>=0&&(e="DOMMouseScroll"),t.removeEventListener(e,i,n)):t.detachEvent("on"+e,i)},C.getTarget=function(t){t||(t=window.event);var e;return t.target?e=t.target:t.srcElement&&(e=t.srcElement),void 0!=e.nodeType&&3==e.nodeType&&(e=e.parentNode),e},C.stopPropagation=function(t){t||(t=window.event),t.stopPropagation?t.stopPropagation():t.cancelBubble=!0},C.preventDefault=function(t){t||(t=window.event),t.preventDefault?t.preventDefault():t.returnValue=!1},C.option={},C.option.asBoolean=function(t,e){return"function"==typeof t&&(t=t()),null!=t?0!=t:e||null},C.option.asNumber=function(t,e){return"function"==typeof t&&(t=t()),null!=t?Number(t)||e||null:e||null},C.option.asString=function(t,e){return"function"==typeof t&&(t=t()),null!=t?t+"":e||null},C.option.asSize=function(t,e){return"function"==typeof t&&(t=t()),C.isString(t)?t:C.isNumber(t)?t+"px":e||null},C.option.asElement=function(t,e){return"function"==typeof t&&(t=t()),t||e||null},C.loadCss=function(t){if("undefined"!=typeof document){var e=document.createElement("style");e.type="text/css",e.styleSheet?e.styleSheet.cssText=t:e.appendChild(document.createTextNode(t)),document.getElementsByTagName("head")[0].appendChild(e)}},!Array.prototype.indexOf){Array.prototype.indexOf=function(t){for(var e=0;this.length>e;e++)if(this[e]==t)return e;return-1};try{console.log("Warning: Ancient browser detected. Please update your browser")}catch(N){}}Array.prototype.forEach||(Array.prototype.forEach=function(t,e){for(var i=0,n=this.length;n>i;++i)t.call(e||this,this[i],i,this)}),Array.prototype.map||(Array.prototype.map=function(t,e){var i,n,s;if(null==this)throw new TypeError(" this is null or not defined");var o=Object(this),r=o.length>>>0;if("function"!=typeof t)throw new TypeError(t+" is not a function");for(e&&(i=e),n=Array(r),s=0;r>s;){var a,h;s in o&&(a=o[s],h=t.call(i,a,s,o),n[s]=h),s++}return n}),Array.prototype.filter||(Array.prototype.filter=function(t){"use strict";if(null==this)throw new TypeError;var e=Object(this),i=e.length>>>0;if("function"!=typeof t)throw new TypeError;for(var n=[],s=arguments[1],o=0;i>o;o++)if(o in e){var r=e[o];t.call(s,r,o,e)&&n.push(r)}return n}),Object.keys||(Object.keys=function(){var t=Object.prototype.hasOwnProperty,e=!{toString:null}.propertyIsEnumerable("toString"),i=["toString","toLocaleString","valueOf","hasOwnProperty","isPrototypeOf","propertyIsEnumerable","constructor"],n=i.length;return function(s){if("object"!=typeof s&&"function"!=typeof s||null===s)throw new TypeError("Object.keys called on non-object");var o=[];for(var r in s)t.call(s,r)&&o.push(r);if(e)for(var a=0;n>a;a++)t.call(s,i[a])&&o.push(i[a]);return o}}()),Array.isArray||(Array.isArray=function(t){return"[object Array]"===Object.prototype.toString.call(t)}),Function.prototype.bind||(Function.prototype.bind=function(t){if("function"!=typeof this)throw new TypeError("Function.prototype.bind - what is trying to be bound is not callable");var e=Array.prototype.slice.call(arguments,1),i=this,n=function(){},s=function(){return i.apply(this instanceof n&&t?this:t,e.concat(Array.prototype.slice.call(arguments)))};return n.prototype=this.prototype,s.prototype=new n,s}),Object.create||(Object.create=function(t){function e(){}if(arguments.length>1)throw Error("Object.create implementation only accepts the first parameter.");return e.prototype=t,new e});var L={listeners:[],indexOf:function(t){for(var e=this.listeners,i=0,n=this.listeners.length;n>i;i++){var s=e[i];if(s&&s.object==t)return i}return-1},addListener:function(t,e,i){var n=this.indexOf(t),s=this.listeners[n];s||(s={object:t,events:{}},this.listeners.push(s));var o=s.events[e];o||(o=[],s.events[e]=o),-1==o.indexOf(i)&&o.push(i)},removeListener:function(t,e,i){var n=this.indexOf(t),s=this.listeners[n];if(s){var o=s.events[e];o&&(n=o.indexOf(i),-1!=n&&o.splice(n,1),0==o.length&&delete s.events[e]);var r=0,a=s.events;for(var h in a)a.hasOwnProperty(h)&&r++;0==r&&delete this.listeners[n]}},removeAllListeners:function(){this.listeners=[]},trigger:function(t,e,i){var n=this.indexOf(t),s=this.listeners[n];if(s){var o=s.events[e];if(o)for(var r=0,a=o.length;a>r;r++)o[r](i)}}};s.prototype.on=function(t,e,i){var n=t instanceof RegExp?t:RegExp(t.replace("*","\\w+")),s={id:C.randomUUID(),event:t,regexp:n,callback:"function"==typeof e?e:null,target:i};return this.subscriptions.push(s),s.id},s.prototype.off=function(t){for(var e=0;this.subscriptions.length>e;){var i=this.subscriptions[e],n=!0;if(t instanceof Object)for(var s in t)t.hasOwnProperty(s)&&t[s]!==i[s]&&(n=!1);else n=i.id==t;n?this.subscriptions.splice(e,1):e++}},s.prototype.emit=function(t,e,i){for(var n=0;this.subscriptions.length>n;n++){var s=this.subscriptions[n];s.regexp.test(t)&&s.callback&&s.callback(t,e,i)}},o.prototype.subscribe=function(t,e){var i=this.subscribers[t];i||(i=[],this.subscribers[t]=i),i.push({callback:e})},o.prototype.unsubscribe=function(t,e){var i=this.subscribers[t];i&&(this.subscribers[t]=i.filter(function(t){return t.callback!=e}))},o.prototype._trigger=function(t,e,i){if("*"==t)throw Error("Cannot trigger event *");var n=[];t in this.subscribers&&(n=n.concat(this.subscribers[t])),"*"in this.subscribers&&(n=n.concat(this.subscribers["*"]));for(var s=0;n.length>s;s++){var o=n[s];o.callback&&o.callback(t,e,i||null)}},o.prototype.add=function(t,e){var i,n=[],s=this;if(t instanceof Array)for(var o=0,r=t.length;r>o;o++)i=s._addItem(t[o]),n.push(i);else if(C.isDataTable(t))for(var a=this._getColumnNames(t),h=0,d=t.getNumberOfRows();d>h;h++){for(var l={},u=0,c=a.length;c>u;u++){var p=a[u];l[p]=t.getValue(h,u)}i=s._addItem(l),n.push(i)}else{if(!(t instanceof Object))throw Error("Unknown dataType");i=s._addItem(t),n.push(i)}return n.length&&this._trigger("add",{items:n},e),n},o.prototype.update=function(t,e){var i=[],n=[],s=this,o=s.fieldId,r=function(t){var e=t[o];s.data[e]?(e=s._updateItem(t),n.push(e)):(e=s._addItem(t),i.push(e))};if(t instanceof Array)for(var a=0,h=t.length;h>a;a++)r(t[a]);else if(C.isDataTable(t))for(var d=this._getColumnNames(t),l=0,u=t.getNumberOfRows();u>l;l++){for(var c={},p=0,f=d.length;f>p;p++){var m=d[p];c[m]=t.getValue(l,p)}r(c)}else{if(!(t instanceof Object))throw Error("Unknown dataType");r(t)}return i.length&&this._trigger("add",{items:i},e),n.length&&this._trigger("update",{items:n},e),i.concat(n)},o.prototype.get=function(){var t,e,i,n,s=this,o=C.getType(arguments[0]);"String"==o||"Number"==o?(t=arguments[0],i=arguments[1],n=arguments[2]):"Array"==o?(e=arguments[0],i=arguments[1],n=arguments[2]):(i=arguments[0],n=arguments[1]);var r;if(i&&i.type){if(r="DataTable"==i.type?"DataTable":"Array",n&&r!=C.getType(n))throw Error('Type of parameter "data" ('+C.getType(n)+") "+"does not correspond with specified options.type ("+i.type+")");if("DataTable"==r&&!C.isDataTable(n))throw Error('Parameter "data" must be a DataTable when options.type is "DataTable"')}else r=n?"DataTable"==C.getType(n)?"DataTable":"Array":"Array";var a,h,d,l,u=i&&i.convert||this.options.convert,c=i&&i.filter,p=[];if(void 0!=t)a=s._getItem(t,u),c&&!c(a)&&(a=null);else if(void 0!=e)for(d=0,l=e.length;l>d;d++)a=s._getItem(e[d],u),(!c||c(a))&&p.push(a);else for(h in this.data)this.data.hasOwnProperty(h)&&(a=s._getItem(h,u),(!c||c(a))&&p.push(a));if(i&&i.order&&void 0==t&&this._sort(p,i.order),i&&i.fields){var f=i.fields;if(void 0!=t)a=this._filterFields(a,f);else for(d=0,l=p.length;l>d;d++)p[d]=this._filterFields(p[d],f)}if("DataTable"==r){var m=this._getColumnNames(n);if(void 0!=t)s._appendRow(n,m,a);else for(d=0,l=p.length;l>d;d++)s._appendRow(n,m,p[d]);return n}if(void 0!=t)return a;if(n){for(d=0,l=p.length;l>d;d++)n.push(p[d]);return n}return p},o.prototype.getIds=function(t){var e,i,n,s,o,r=this.data,a=t&&t.filter,h=t&&t.order,d=t&&t.convert||this.options.convert,l=[];if(a)if(h){o=[];for(n in r)r.hasOwnProperty(n)&&(s=this._getItem(n,d),a(s)&&o.push(s));for(this._sort(o,h),e=0,i=o.length;i>e;e++)l[e]=o[e][this.fieldId]}else for(n in r)r.hasOwnProperty(n)&&(s=this._getItem(n,d),a(s)&&l.push(s[this.fieldId]));else if(h){o=[];for(n in r)r.hasOwnProperty(n)&&o.push(r[n]);for(this._sort(o,h),e=0,i=o.length;i>e;e++)l[e]=o[e][this.fieldId]}else for(n in r)r.hasOwnProperty(n)&&(s=r[n],l.push(s[this.fieldId]));return l},o.prototype.forEach=function(t,e){var i,n,s=e&&e.filter,o=e&&e.convert||this.options.convert,r=this.data;if(e&&e.order)for(var a=this.get(e),h=0,d=a.length;d>h;h++)i=a[h],n=i[this.fieldId],t(i,n);else for(n in r)r.hasOwnProperty(n)&&(i=this._getItem(n,o),(!s||s(i))&&t(i,n))},o.prototype.map=function(t,e){var i,n=e&&e.filter,s=e&&e.convert||this.options.convert,o=[],r=this.data;for(var a in r)r.hasOwnProperty(a)&&(i=this._getItem(a,s),(!n||n(i))&&o.push(t(i,a)));return e&&e.order&&this._sort(o,e.order),o},o.prototype._filterFields=function(t,e){var i={};for(var n in t)t.hasOwnProperty(n)&&-1!=e.indexOf(n)&&(i[n]=t[n]);return i},o.prototype._sort=function(t,e){if(C.isString(e)){var i=e;t.sort(function(t,e){var n=t[i],s=e[i];return n>s?1:s>n?-1:0})}else{if("function"!=typeof e)throw new TypeError("Order must be a function or a string");t.sort(e)}},o.prototype.remove=function(t,e){var i,n,s,o=[];if(t instanceof Array)for(i=0,n=t.length;n>i;i++)s=this._remove(t[i]),null!=s&&o.push(s);else s=this._remove(t),null!=s&&o.push(s);return o.length&&this._trigger("remove",{items:o},e),o},o.prototype._remove=function(t){if(C.isNumber(t)||C.isString(t)){if(this.data[t])return delete this.data[t],delete this.internalIds[t],t}else if(t instanceof Object){var e=t[this.fieldId];if(e&&this.data[e])return delete this.data[e],delete this.internalIds[e],e}return null},o.prototype.clear=function(t){var e=Object.keys(this.data);return this.data={},this.internalIds={},this._trigger("remove",{items:e},t),e},o.prototype.max=function(t){var e=this.data,i=null,n=null;for(var s in e)if(e.hasOwnProperty(s)){var o=e[s],r=o[t];null!=r&&(!i||r>n)&&(i=o,n=r)}return i},o.prototype.min=function(t){var e=this.data,i=null,n=null;for(var s in e)if(e.hasOwnProperty(s)){var o=e[s],r=o[t];null!=r&&(!i||n>r)&&(i=o,n=r)}return i},o.prototype.distinct=function(t){var e=this.data,i=[],n=this.options.convert[t],s=0;for(var o in e)if(e.hasOwnProperty(o)){for(var r=e[o],a=C.convert(r[t],n),h=!1,d=0;s>d;d++)if(i[d]==a){h=!0;break}h||(i[s]=a,s++)}return i},o.prototype._addItem=function(t){var e=t[this.fieldId];if(void 0!=e){if(this.data[e])throw Error("Cannot add item: item with id "+e+" already exists")}else e=C.randomUUID(),t[this.fieldId]=e,this.internalIds[e]=t;var i={};for(var n in t)if(t.hasOwnProperty(n)){var s=this.convert[n];i[n]=C.convert(t[n],s)}return this.data[e]=i,e},o.prototype._getItem=function(t,e){var i,n,s=this.data[t];if(!s)return null;var o={},r=this.fieldId,a=this.internalIds;if(e)for(i in s)s.hasOwnProperty(i)&&(n=s[i],i==r&&n in a||(o[i]=C.convert(n,e[i])));else for(i in s)s.hasOwnProperty(i)&&(n=s[i],i==r&&n in a||(o[i]=n));return o},o.prototype._updateItem=function(t){var e=t[this.fieldId];if(void 0==e)throw Error("Cannot update item: item has no id (item: "+JSON.stringify(t)+")");var i=this.data[e];if(!i)throw Error("Cannot update item: no item with id "+e+" found");for(var n in t)if(t.hasOwnProperty(n)){var s=this.convert[n];i[n]=C.convert(t[n],s)}return e},o.prototype._getColumnNames=function(t){for(var e=[],i=0,n=t.getNumberOfColumns();n>i;i++)e[i]=t.getColumnId(i)||t.getColumnLabel(i);return e},o.prototype._appendRow=function(t,e,i){for(var n=t.addRow(),s=0,o=e.length;o>s;s++){var r=e[s];t.setValue(n,s,i[r])}},r.prototype.setData=function(t){var e,i,n;if(this.data){this.data.unsubscribe&&this.data.unsubscribe("*",this.listener),e=[];for(var s in this.ids)this.ids.hasOwnProperty(s)&&e.push(s);this.ids={},this._trigger("remove",{items:e})}if(this.data=t,this.data){for(this.fieldId=this.options.fieldId||this.data&&this.data.options&&this.data.options.fieldId||"id",e=this.data.getIds({filter:this.options&&this.options.filter}),i=0,n=e.length;n>i;i++)s=e[i],this.ids[s]=!0;this._trigger("add",{items:e}),this.data.subscribe&&this.data.subscribe("*",this.listener)}},r.prototype.get=function(){var t,e,i,n=this,s=C.getType(arguments[0]);"String"==s||"Number"==s||"Array"==s?(t=arguments[0],e=arguments[1],i=arguments[2]):(e=arguments[0],i=arguments[1]);var o=C.extend({},this.options,e);this.options.filter&&e&&e.filter&&(o.filter=function(t){return n.options.filter(t)&&e.filter(t)});var r=[];return void 0!=t&&r.push(t),r.push(o),r.push(i),this.data&&this.data.get.apply(this.data,r)},r.prototype.getIds=function(t){var e;if(this.data){var i,n=this.options.filter;i=t&&t.filter?n?function(e){return n(e)&&t.filter(e)}:t.filter:n,e=this.data.getIds({filter:i,order:t&&t.order})}else e=[];return e},r.prototype._onEvent=function(t,e,i){var n,s,o,r,a=e&&e.items,h=this.data,d=[],l=[],u=[];if(a&&h){switch(t){case"add":for(n=0,s=a.length;s>n;n++)o=a[n],r=this.get(o),r&&(this.ids[o]=!0,d.push(o));break;case"update":for(n=0,s=a.length;s>n;n++)o=a[n],r=this.get(o),r?this.ids[o]?l.push(o):(this.ids[o]=!0,d.push(o)):this.ids[o]&&(delete this.ids[o],u.push(o));break;case"remove":for(n=0,s=a.length;s>n;n++)o=a[n],this.ids[o]&&(delete this.ids[o],u.push(o))}d.length&&this._trigger("add",{items:d},i),l.length&&this._trigger("update",{items:l},i),u.length&&this._trigger("remove",{items:u},i)}},r.prototype.subscribe=o.prototype.subscribe,r.prototype.unsubscribe=o.prototype.unsubscribe,r.prototype._trigger=o.prototype._trigger,TimeStep=function(t,e,i){this.current=new Date,this._start=new Date,this._end=new Date,this.autoScale=!0,this.scale=TimeStep.SCALE.DAY,this.step=1,this.setRange(t,e,i)},TimeStep.SCALE={MILLISECOND:1,SECOND:2,MINUTE:3,HOUR:4,DAY:5,WEEKDAY:6,MONTH:7,YEAR:8},TimeStep.prototype.setRange=function(t,e,i){t instanceof Date&&e instanceof Date&&(this._start=void 0!=t?new Date(t.valueOf()):new Date,this._end=void 0!=e?new Date(e.valueOf()):new Date,this.autoScale&&this.setMinimumStep(i))},TimeStep.prototype.first=function(){this.current=new Date(this._start.valueOf()),this.roundToMinor()},TimeStep.prototype.roundToMinor=function(){switch(this.scale){case TimeStep.SCALE.YEAR:this.current.setFullYear(this.step*Math.floor(this.current.getFullYear()/this.step)),this.current.setMonth(0);case TimeStep.SCALE.MONTH:this.current.setDate(1);case TimeStep.SCALE.DAY:case TimeStep.SCALE.WEEKDAY:this.current.setHours(0);case TimeStep.SCALE.HOUR:this.current.setMinutes(0);case TimeStep.SCALE.MINUTE:this.current.setSeconds(0);case TimeStep.SCALE.SECOND:this.current.setMilliseconds(0)}if(1!=this.step)switch(this.scale){case TimeStep.SCALE.MILLISECOND:this.current.setMilliseconds(this.current.getMilliseconds()-this.current.getMilliseconds()%this.step);break;case TimeStep.SCALE.SECOND:this.current.setSeconds(this.current.getSeconds()-this.current.getSeconds()%this.step);break;case TimeStep.SCALE.MINUTE:this.current.setMinutes(this.current.getMinutes()-this.current.getMinutes()%this.step);break;case TimeStep.SCALE.HOUR:this.current.setHours(this.current.getHours()-this.current.getHours()%this.step);break;case TimeStep.SCALE.WEEKDAY:case TimeStep.SCALE.DAY:this.current.setDate(this.current.getDate()-1-(this.current.getDate()-1)%this.step+1);break;case TimeStep.SCALE.MONTH:this.current.setMonth(this.current.getMonth()-this.current.getMonth()%this.step);break;case TimeStep.SCALE.YEAR:this.current.setFullYear(this.current.getFullYear()-this.current.getFullYear()%this.step);break;default:}},TimeStep.prototype.hasNext=function(){return this.current.valueOf()<=this._end.valueOf()},TimeStep.prototype.next=function(){var t=this.current.valueOf();if(6>this.current.getMonth())switch(this.scale){case TimeStep.SCALE.MILLISECOND:this.current=new Date(this.current.valueOf()+this.step);break;case TimeStep.SCALE.SECOND:this.current=new Date(this.current.valueOf()+1e3*this.step);break;case TimeStep.SCALE.MINUTE:this.current=new Date(this.current.valueOf()+60*1e3*this.step);break;case TimeStep.SCALE.HOUR:this.current=new Date(this.current.valueOf()+60*60*1e3*this.step);var e=this.current.getHours();this.current.setHours(e-e%this.step);break;case TimeStep.SCALE.WEEKDAY:case TimeStep.SCALE.DAY:this.current.setDate(this.current.getDate()+this.step);break;case TimeStep.SCALE.MONTH:this.current.setMonth(this.current.getMonth()+this.step);break;case TimeStep.SCALE.YEAR:this.current.setFullYear(this.current.getFullYear()+this.step);break;default:}else switch(this.scale){case TimeStep.SCALE.MILLISECOND:this.current=new Date(this.current.valueOf()+this.step);break;case TimeStep.SCALE.SECOND:this.current.setSeconds(this.current.getSeconds()+this.step);break;case TimeStep.SCALE.MINUTE:this.current.setMinutes(this.current.getMinutes()+this.step);break;case TimeStep.SCALE.HOUR:this.current.setHours(this.current.getHours()+this.step);break;case TimeStep.SCALE.WEEKDAY:case TimeStep.SCALE.DAY:this.current.setDate(this.current.getDate()+this.step);break;case TimeStep.SCALE.MONTH:this.current.setMonth(this.current.getMonth()+this.step);break;case TimeStep.SCALE.YEAR:this.current.setFullYear(this.current.getFullYear()+this.step);break;default:}if(1!=this.step)switch(this.scale){case TimeStep.SCALE.MILLISECOND:this.current.getMilliseconds()0&&(this.step=e),this.autoScale=!1},TimeStep.prototype.setAutoScale=function(t){this.autoScale=t},TimeStep.prototype.setMinimumStep=function(t){if(void 0!=t){var e=31104e6,i=2592e6,n=864e5,s=36e5,o=6e4,r=1e3,a=1;1e3*e>t&&(this.scale=TimeStep.SCALE.YEAR,this.step=1e3),500*e>t&&(this.scale=TimeStep.SCALE.YEAR,this.step=500),100*e>t&&(this.scale=TimeStep.SCALE.YEAR,this.step=100),50*e>t&&(this.scale=TimeStep.SCALE.YEAR,this.step=50),10*e>t&&(this.scale=TimeStep.SCALE.YEAR,this.step=10),5*e>t&&(this.scale=TimeStep.SCALE.YEAR,this.step=5),e>t&&(this.scale=TimeStep.SCALE.YEAR,this.step=1),3*i>t&&(this.scale=TimeStep.SCALE.MONTH,this.step=3),i>t&&(this.scale=TimeStep.SCALE.MONTH,this.step=1),5*n>t&&(this.scale=TimeStep.SCALE.DAY,this.step=5),2*n>t&&(this.scale=TimeStep.SCALE.DAY,this.step=2),n>t&&(this.scale=TimeStep.SCALE.DAY,this.step=1),n/2>t&&(this.scale=TimeStep.SCALE.WEEKDAY,this.step=1),4*s>t&&(this.scale=TimeStep.SCALE.HOUR,this.step=4),s>t&&(this.scale=TimeStep.SCALE.HOUR,this.step=1),15*o>t&&(this.scale=TimeStep.SCALE.MINUTE,this.step=15),10*o>t&&(this.scale=TimeStep.SCALE.MINUTE,this.step=10),5*o>t&&(this.scale=TimeStep.SCALE.MINUTE,this.step=5),o>t&&(this.scale=TimeStep.SCALE.MINUTE,this.step=1),15*r>t&&(this.scale=TimeStep.SCALE.SECOND,this.step=15),10*r>t&&(this.scale=TimeStep.SCALE.SECOND,this.step=10),5*r>t&&(this.scale=TimeStep.SCALE.SECOND,this.step=5),r>t&&(this.scale=TimeStep.SCALE.SECOND,this.step=1),200*a>t&&(this.scale=TimeStep.SCALE.MILLISECOND,this.step=200),100*a>t&&(this.scale=TimeStep.SCALE.MILLISECOND,this.step=100),50*a>t&&(this.scale=TimeStep.SCALE.MILLISECOND,this.step=50),10*a>t&&(this.scale=TimeStep.SCALE.MILLISECOND,this.step=10),5*a>t&&(this.scale=TimeStep.SCALE.MILLISECOND,this.step=5),a>t&&(this.scale=TimeStep.SCALE.MILLISECOND,this.step=1) +}},TimeStep.prototype.snap=function(t){if(this.scale==TimeStep.SCALE.YEAR){var e=t.getFullYear()+Math.round(t.getMonth()/12);t.setFullYear(Math.round(e/this.step)*this.step),t.setMonth(0),t.setDate(0),t.setHours(0),t.setMinutes(0),t.setSeconds(0),t.setMilliseconds(0)}else if(this.scale==TimeStep.SCALE.MONTH)t.getDate()>15?(t.setDate(1),t.setMonth(t.getMonth()+1)):t.setDate(1),t.setHours(0),t.setMinutes(0),t.setSeconds(0),t.setMilliseconds(0);else if(this.scale==TimeStep.SCALE.DAY||this.scale==TimeStep.SCALE.WEEKDAY){switch(this.step){case 5:case 2:t.setHours(24*Math.round(t.getHours()/24));break;default:t.setHours(12*Math.round(t.getHours()/12))}t.setMinutes(0),t.setSeconds(0),t.setMilliseconds(0)}else if(this.scale==TimeStep.SCALE.HOUR){switch(this.step){case 4:t.setMinutes(60*Math.round(t.getMinutes()/60));break;default:t.setMinutes(30*Math.round(t.getMinutes()/30))}t.setSeconds(0),t.setMilliseconds(0)}else if(this.scale==TimeStep.SCALE.MINUTE){switch(this.step){case 15:case 10:t.setMinutes(5*Math.round(t.getMinutes()/5)),t.setSeconds(0);break;case 5:t.setSeconds(60*Math.round(t.getSeconds()/60));break;default:t.setSeconds(30*Math.round(t.getSeconds()/30))}t.setMilliseconds(0)}else if(this.scale==TimeStep.SCALE.SECOND)switch(this.step){case 15:case 10:t.setSeconds(5*Math.round(t.getSeconds()/5)),t.setMilliseconds(0);break;case 5:t.setMilliseconds(1e3*Math.round(t.getMilliseconds()/1e3));break;default:t.setMilliseconds(500*Math.round(t.getMilliseconds()/500))}else if(this.scale==TimeStep.SCALE.MILLISECOND){var i=this.step>5?this.step/2:1;t.setMilliseconds(Math.round(t.getMilliseconds()/i)*i)}},TimeStep.prototype.isMajor=function(){switch(this.scale){case TimeStep.SCALE.MILLISECOND:return 0==this.current.getMilliseconds();case TimeStep.SCALE.SECOND:return 0==this.current.getSeconds();case TimeStep.SCALE.MINUTE:return 0==this.current.getHours()&&0==this.current.getMinutes();case TimeStep.SCALE.HOUR:return 0==this.current.getHours();case TimeStep.SCALE.WEEKDAY:case TimeStep.SCALE.DAY:return 1==this.current.getDate();case TimeStep.SCALE.MONTH:return 0==this.current.getMonth();case TimeStep.SCALE.YEAR:return!1;default:return!1}},TimeStep.prototype.getLabelMinor=function(t){switch(void 0==t&&(t=this.current),this.scale){case TimeStep.SCALE.MILLISECOND:return M(t).format("SSS");case TimeStep.SCALE.SECOND:return M(t).format("s");case TimeStep.SCALE.MINUTE:return M(t).format("HH:mm");case TimeStep.SCALE.HOUR:return M(t).format("HH:mm");case TimeStep.SCALE.WEEKDAY:return M(t).format("ddd D");case TimeStep.SCALE.DAY:return M(t).format("D");case TimeStep.SCALE.MONTH:return M(t).format("MMM");case TimeStep.SCALE.YEAR:return M(t).format("YYYY");default:return""}},TimeStep.prototype.getLabelMajor=function(t){switch(void 0==t&&(t=this.current),this.scale){case TimeStep.SCALE.MILLISECOND:return M(t).format("HH:mm:ss");case TimeStep.SCALE.SECOND:return M(t).format("D MMMM HH:mm");case TimeStep.SCALE.MINUTE:case TimeStep.SCALE.HOUR:return M(t).format("ddd D MMMM");case TimeStep.SCALE.WEEKDAY:case TimeStep.SCALE.DAY:return M(t).format("MMMM YYYY");case TimeStep.SCALE.MONTH:return M(t).format("YYYY");case TimeStep.SCALE.YEAR:return"";default:return""}},a.prototype.setOptions=function(t){C.extend(this.options,t)},a.prototype.update=function(){this._order(),this._stack()},a.prototype._order=function(){var t=this.parent.items;if(!t)throw Error("Cannot stack items: parent does not contain items");var e=[],i=0;C.forEach(t,function(t){t.visible&&(e[i]=t,i++)});var n=this.options.order||this.defaultOptions.order;if("function"!=typeof n)throw Error("Option order must be a function");e.sort(n),this.ordered=e},a.prototype._stack=function(){var t,e,i,n=this.ordered,s=this.options,o=s.orientation||this.defaultOptions.orientation,r="top"==o;for(i=s.margin&&void 0!==s.margin.item?s.margin.item:this.defaultOptions.margin.item,t=0,e=n.length;e>t;t++){var a=n[t],h=null;do h=this.checkOverlap(n,t,0,t-1,i),null!=h&&(a.top=r?h.top+h.height+i:h.top-a.height-i);while(h)}},a.prototype.checkOverlap=function(t,e,i,n,s){for(var o=this.collision,r=t[e],a=n;a>=i;a--){var h=t[a];if(o(r,h,s)&&a!=e)return h}return null},a.prototype.collision=function(t,e,i){return t.left-ie.left&&t.top-ie.top},h.prototype.setOptions=function(t){C.extend(this.options,t),(null!=t.start||null!=t.end)&&this.setRange(t.start,t.end)},h.prototype.subscribe=function(t,e,i){var n,s=this;if("horizontal"!=i&&"vertical"!=i)throw new TypeError('Unknown direction "'+i+'". '+'Choose "horizontal" or "vertical".');if("move"==e)n={component:t,event:e,direction:i,callback:function(t){s._onMouseDown(t,n)},params:{}},t.on("mousedown",n.callback),s.listeners.push(n);else{if("zoom"!=e)throw new TypeError('Unknown event "'+e+'". '+'Choose "move" or "zoom".');n={component:t,event:e,direction:i,callback:function(t){s._onMouseWheel(t,n)},params:{}},t.on("mousewheel",n.callback),s.listeners.push(n)}},h.prototype.on=function(t,e){L.addListener(this,t,e)},h.prototype._trigger=function(t){L.trigger(this,t,{start:this.start,end:this.end})},h.prototype.setRange=function(t,e){var i=this._applyRange(t,e);i&&(this._trigger("rangechange"),this._trigger("rangechanged"))},h.prototype._applyRange=function(t,e){var i,n=null!=t?C.convert(t,"Number"):this.start,s=null!=e?C.convert(e,"Number"):this.end;if(isNaN(n))throw Error('Invalid start "'+t+'"');if(isNaN(s))throw Error('Invalid end "'+e+'"');if(n>s&&(s=n),null!=this.options.min){var o=this.options.min.valueOf();o>n&&(i=o-n,n+=i,s+=i)}if(null!=this.options.max){var r=this.options.max.valueOf();s>r&&(i=s-r,n-=i,s-=i)}if(null!=this.options.zoomMin){var a=this.options.zoomMin.valueOf();0>a&&(a=0),a>s-n&&(this.end-this.start>a?(i=a-(s-n),n-=i/2,s+=i/2):(n=this.start,s=this.end))}if(null!=this.options.zoomMax){var h=this.options.zoomMax.valueOf();0>h&&(h=0),s-n>h&&(h>this.end-this.start?(i=s-n-h,n+=i/2,s-=i/2):(n=this.start,s=this.end))}var d=this.start!=n||this.end!=s;return this.start=n,this.end=s,d},h.prototype.getRange=function(){return{start:this.start,end:this.end}},h.prototype.conversion=function(t){return this.start,this.end,h.conversion(this.start,this.end,t)},h.conversion=function(t,e,i){return 0!=i&&0!=e-t?{offset:t,factor:i/(e-t)}:{offset:0,factor:1}},h.prototype._onMouseDown=function(t,e){t=t||window.event;var i=e.params,n=t.which?1==t.which:1==t.button;if(n){i.mouseX=C.getPageX(t),i.mouseY=C.getPageY(t),i.previousLeft=0,i.previousOffset=0,i.moved=!1,i.start=this.start,i.end=this.end;var s=e.component.frame;s&&(s.style.cursor="move");var o=this;i.onMouseMove||(i.onMouseMove=function(t){o._onMouseMove(t,e)},C.addEventListener(document,"mousemove",i.onMouseMove)),i.onMouseUp||(i.onMouseUp=function(t){o._onMouseUp(t,e)},C.addEventListener(document,"mouseup",i.onMouseUp)),C.preventDefault(t)}},h.prototype._onMouseMove=function(t,e){t=t||window.event;var i=e.params,n=C.getPageX(t),s=C.getPageY(t);void 0==i.mouseX&&(i.mouseX=n),void 0==i.mouseY&&(i.mouseY=s);var o=n-i.mouseX,r=s-i.mouseY,a="horizontal"==e.direction?o:r;Math.abs(a)>=1&&(i.moved=!0);var h=i.end-i.start,d="horizontal"==e.direction?e.component.width:e.component.height,l=-a/d*h;this._applyRange(i.start+l,i.end+l),this._trigger("rangechange"),C.preventDefault(t)},h.prototype._onMouseUp=function(t,e){t=t||window.event;var i=e.params;e.component.frame&&(e.component.frame.style.cursor="auto"),i.onMouseMove&&(C.removeEventListener(document,"mousemove",i.onMouseMove),i.onMouseMove=null),i.onMouseUp&&(C.removeEventListener(document,"mouseup",i.onMouseUp),i.onMouseUp=null),i.moved&&this._trigger("rangechanged")},h.prototype._onMouseWheel=function(t,e){t=t||window.event;var i=0;if(t.wheelDelta?i=t.wheelDelta/120:t.detail&&(i=-t.detail/3),i){var n=this,s=function(){var s=i/5,o=null,r=e.component.frame;if(r){var a,h;if("horizontal"==e.direction){a=e.component.width,h=n.conversion(a);var d=C.getAbsoluteLeft(r),l=C.getPageX(t);o=(l-d)/h.factor+h.offset}else{a=e.component.height,h=n.conversion(a);var u=C.getAbsoluteTop(r),c=C.getPageY(t);o=(u+a-c-u)/h.factor+h.offset}}n.zoom(s,o)};s()}C.preventDefault(t)},h.prototype.zoom=function(t,e){null==e&&(e=(this.start+this.end)/2),t>=1&&(t=.9),-1>=t&&(t=-.9),0>t&&(t/=1+t);var i=this.start-e,n=this.end-e,s=this.start-i*t,o=this.end-n*t;this.setRange(s,o)},h.prototype.move=function(t){var e=this.end-this.start,i=this.start+e*t,n=this.end+e*t;this.start=i,this.end=n},h.prototype.moveTo=function(t){var e=(this.start+this.end)/2,i=e-t,n=this.start-i,s=this.end-i;this.setRange(n,s)},d.prototype.add=function(t){if(void 0==t.id)throw Error("Component has no field id");if(!(t instanceof l||t instanceof d))throw new TypeError("Component must be an instance of prototype Component or Controller");t.controller=this,this.components[t.id]=t},d.prototype.remove=function(t){var e;for(e in this.components)if(this.components.hasOwnProperty(e)&&(e==t||this.components[e]==t))break;e&&delete this.components[e]},d.prototype.requestReflow=function(t){if(t)this.reflow();else if(!this.reflowTimer){var e=this;this.reflowTimer=setTimeout(function(){e.reflowTimer=void 0,e.reflow()},0)}},d.prototype.requestRepaint=function(t){if(t)this.repaint();else if(!this.repaintTimer){var e=this;this.repaintTimer=setTimeout(function(){e.repaintTimer=void 0,e.repaint()},0)}},d.prototype.repaint=function(){function t(n,s){s in i||(n.depends&&n.depends.forEach(function(e){t(e,e.id)}),n.parent&&t(n.parent,n.parent.id),e=n.repaint()||e,i[s]=!0)}var e=!1;this.repaintTimer&&(clearTimeout(this.repaintTimer),this.repaintTimer=void 0);var i={};C.forEach(this.components,t),e&&this.reflow()},d.prototype.reflow=function(){function t(n,s){s in i||(n.depends&&n.depends.forEach(function(e){t(e,e.id)}),n.parent&&t(n.parent,n.parent.id),e=n.reflow()||e,i[s]=!0)}var e=!1;this.reflowTimer&&(clearTimeout(this.reflowTimer),this.reflowTimer=void 0);var i={};C.forEach(this.components,t),e&&this.repaint()},l.prototype.setOptions=function(t){t&&(C.extend(this.options,t),this.controller&&(this.requestRepaint(),this.requestReflow()))},l.prototype.getOption=function(t){var e;return this.options&&(e=this.options[t]),void 0===e&&this.defaultOptions&&(e=this.defaultOptions[t]),e},l.prototype.getContainer=function(){return null},l.prototype.getFrame=function(){return this.frame},l.prototype.repaint=function(){return!1},l.prototype.reflow=function(){return!1},l.prototype.hide=function(){return this.frame&&this.frame.parentNode?(this.frame.parentNode.removeChild(this.frame),!0):!1},l.prototype.show=function(){return this.frame&&this.frame.parentNode?!1:this.repaint()},l.prototype.requestRepaint=function(){if(!this.controller)throw Error("Cannot request a repaint: no controller configured");this.controller.requestRepaint()},l.prototype.requestReflow=function(){if(!this.controller)throw Error("Cannot request a reflow: no controller configured");this.controller.requestReflow()},u.prototype=new l,u.prototype.setOptions=l.prototype.setOptions,u.prototype.getContainer=function(){return this.frame},u.prototype.repaint=function(){var t=0,e=C.updateProperty,i=C.option.asSize,n=this.options,s=this.frame;if(!s){s=document.createElement("div"),s.className="panel";var o=n.className;o&&("function"==typeof o?C.addClassName(s,o()+""):C.addClassName(s,o+"")),this.frame=s,t+=1}if(!s.parentNode){if(!this.parent)throw Error("Cannot repaint panel: no parent attached");var r=this.parent.getContainer();if(!r)throw Error("Cannot repaint panel: parent has no container element");r.appendChild(s),t+=1}return t+=e(s.style,"top",i(n.top,"0px")),t+=e(s.style,"left",i(n.left,"0px")),t+=e(s.style,"width",i(n.width,"100%")),t+=e(s.style,"height",i(n.height,"100%")),t>0},u.prototype.reflow=function(){var t=0,e=C.updateProperty,i=this.frame;return i?(t+=e(this,"top",i.offsetTop),t+=e(this,"left",i.offsetLeft),t+=e(this,"width",i.offsetWidth),t+=e(this,"height",i.offsetHeight)):t+=1,t>0},c.prototype=new u,c.prototype.setOptions=l.prototype.setOptions,c.prototype.repaint=function(){var t=0,e=C.updateProperty,i=C.option.asSize,n=this.options,s=this.frame;if(!s){s=document.createElement("div"),s.className="vis timeline rootpanel";var o=n.className;o&&C.addClassName(s,C.option.asString(o)),this.frame=s,t+=1}if(!s.parentNode){if(!this.container)throw Error("Cannot repaint root panel: no container attached");this.container.appendChild(s),t+=1}return t+=e(s.style,"top",i(n.top,"0px")),t+=e(s.style,"left",i(n.left,"0px")),t+=e(s.style,"width",i(n.width,"100%")),t+=e(s.style,"height",i(n.height,"100%")),this._updateEventEmitters(),this._updateWatch(),t>0},c.prototype.reflow=function(){var t=0,e=C.updateProperty,i=this.frame;return i?(t+=e(this,"top",i.offsetTop),t+=e(this,"left",i.offsetLeft),t+=e(this,"width",i.offsetWidth),t+=e(this,"height",i.offsetHeight)):t+=1,t>0},c.prototype._updateWatch=function(){var t=this.getOption("autoResize");t?this._watch():this._unwatch()},c.prototype._watch=function(){var t=this;this._unwatch();var e=function(){var e=t.getOption("autoResize");return e?(t.frame&&(t.frame.clientWidth!=t.width||t.frame.clientHeight!=t.height)&&t.requestReflow(),void 0):(t._unwatch(),void 0)};C.addEventListener(window,"resize",e),this.watchTimer=setInterval(e,1e3)},c.prototype._unwatch=function(){this.watchTimer&&(clearInterval(this.watchTimer),this.watchTimer=void 0)},c.prototype.on=function(t,e){var i=this.listeners[t];i||(i=[],this.listeners[t]=i),i.push(e),this._updateEventEmitters()},c.prototype._updateEventEmitters=function(){if(this.listeners){var t=this;C.forEach(this.listeners,function(e,i){if(t.emitters||(t.emitters={}),!(i in t.emitters)){var n=t.frame;if(n){var s=function(t){e.forEach(function(e){e(t)})};t.emitters[i]=s,C.addEventListener(n,i,s)}}})}},p.prototype=new l,p.prototype.setOptions=l.prototype.setOptions,p.prototype.setRange=function(t){if(!(t instanceof h||t&&t.start&&t.end))throw new TypeError("Range must be an instance of Range, or an object containing start and end.");this.range=t},p.prototype.toTime=function(t){var e=this.conversion;return new Date(t/e.factor+e.offset)},p.prototype.toScreen=function(t){var e=this.conversion;return(t.valueOf()-e.offset)*e.factor},p.prototype.repaint=function(){var t=0,e=C.updateProperty,i=C.option.asSize,n=this.options,s=this.getOption("orientation"),o=this.props,r=this.step,a=this.frame;if(a||(a=document.createElement("div"),this.frame=a,t+=1),a.className="axis "+s,!a.parentNode){if(!this.parent)throw Error("Cannot repaint time axis: no parent attached");var h=this.parent.getContainer();if(!h)throw Error("Cannot repaint time axis: parent has no container element");h.appendChild(a),t+=1}var d=a.parentNode;if(d){var l=a.nextSibling;d.removeChild(a);var u="bottom"==s&&this.props.parentHeight&&this.height?this.props.parentHeight-this.height+"px":"0px";if(t+=e(a.style,"top",i(n.top,u)),t+=e(a.style,"left",i(n.left,"0px")),t+=e(a.style,"width",i(n.width,"100%")),t+=e(a.style,"height",i(n.height,this.height+"px")),this._repaintMeasureChars(),this.step){this._repaintStart(),r.first();for(var c=void 0,p=0;r.hasNext()&&1e3>p;){p++;var f=r.getCurrent(),m=this.toScreen(f),g=r.isMajor();this.getOption("showMinorLabels")&&this._repaintMinorText(m,r.getLabelMinor()),g&&this.getOption("showMajorLabels")?(m>0&&(void 0==c&&(c=m),this._repaintMajorText(m,r.getLabelMajor())),this._repaintMajorLine(m)):this._repaintMinorLine(m),r.next()}if(this.getOption("showMajorLabels")){var v=this.toTime(0),y=r.getLabelMajor(v),b=y.length*(o.majorCharWidth||10)+10;(void 0==c||c>b)&&this._repaintMajorText(0,y)}this._repaintEnd()}this._repaintLine(),l?d.insertBefore(a,l):d.appendChild(a)}return t>0},p.prototype._repaintStart=function(){var t=this.dom,e=t.redundant;e.majorLines=t.majorLines,e.majorTexts=t.majorTexts,e.minorLines=t.minorLines,e.minorTexts=t.minorTexts,t.majorLines=[],t.majorTexts=[],t.minorLines=[],t.minorTexts=[]},p.prototype._repaintEnd=function(){C.forEach(this.dom.redundant,function(t){for(;t.length;){var e=t.pop();e&&e.parentNode&&e.parentNode.removeChild(e)}})},p.prototype._repaintMinorText=function(t,e){var i=this.dom.redundant.minorTexts.shift();if(!i){var n=document.createTextNode("");i=document.createElement("div"),i.appendChild(n),i.className="text minor",this.frame.appendChild(i)}this.dom.minorTexts.push(i),i.childNodes[0].nodeValue=e,i.style.left=t+"px",i.style.top=this.props.minorLabelTop+"px"},p.prototype._repaintMajorText=function(t,e){var i=this.dom.redundant.majorTexts.shift();if(!i){var n=document.createTextNode(e);i=document.createElement("div"),i.className="text major",i.appendChild(n),this.frame.appendChild(i)}this.dom.majorTexts.push(i),i.childNodes[0].nodeValue=e,i.style.top=this.props.majorLabelTop+"px",i.style.left=t+"px"},p.prototype._repaintMinorLine=function(t){var e=this.dom.redundant.minorLines.shift();e||(e=document.createElement("div"),e.className="grid vertical minor",this.frame.appendChild(e)),this.dom.minorLines.push(e);var i=this.props;e.style.top=i.minorLineTop+"px",e.style.height=i.minorLineHeight+"px",e.style.left=t-i.minorLineWidth/2+"px"},p.prototype._repaintMajorLine=function(t){var e=this.dom.redundant.majorLines.shift();e||(e=document.createElement("DIV"),e.className="grid vertical major",this.frame.appendChild(e)),this.dom.majorLines.push(e);var i=this.props;e.style.top=i.majorLineTop+"px",e.style.left=t-i.majorLineWidth/2+"px",e.style.height=i.majorLineHeight+"px"},p.prototype._repaintLine=function(){var t=this.dom.line,e=this.frame;this.options,this.getOption("showMinorLabels")||this.getOption("showMajorLabels")?(t?(e.removeChild(t),e.appendChild(t)):(t=document.createElement("div"),t.className="grid horizontal major",e.appendChild(t),this.dom.line=t),t.style.top=this.props.lineTop+"px"):t&&axis.parentElement&&(e.removeChild(axis.line),delete this.dom.line)},p.prototype._repaintMeasureChars=function(){var t,e=this.dom;if(!e.measureCharMinor){t=document.createTextNode("0");var i=document.createElement("DIV");i.className="text minor measure",i.appendChild(t),this.frame.appendChild(i),e.measureCharMinor=i}if(!e.measureCharMajor){t=document.createTextNode("0");var n=document.createElement("DIV");n.className="text major measure",n.appendChild(t),this.frame.appendChild(n),e.measureCharMajor=n}},p.prototype.reflow=function(){var t=0,e=C.updateProperty,i=this.frame,n=this.range;if(!n)throw Error("Cannot repaint time axis: no range configured");if(i){t+=e(this,"top",i.offsetTop),t+=e(this,"left",i.offsetLeft);var s=this.props,o=this.getOption("showMinorLabels"),r=this.getOption("showMajorLabels"),a=this.dom.measureCharMinor,h=this.dom.measureCharMajor;a&&(s.minorCharHeight=a.clientHeight,s.minorCharWidth=a.clientWidth),h&&(s.majorCharHeight=h.clientHeight,s.majorCharWidth=h.clientWidth);var d=i.parentNode?i.parentNode.offsetHeight:0;switch(d!=s.parentHeight&&(s.parentHeight=d,t+=1),this.getOption("orientation")){case"bottom":s.minorLabelHeight=o?s.minorCharHeight:0,s.majorLabelHeight=r?s.majorCharHeight:0,s.minorLabelTop=0,s.majorLabelTop=s.minorLabelTop+s.minorLabelHeight,s.minorLineTop=-this.top,s.minorLineHeight=Math.max(this.top+s.majorLabelHeight,0),s.minorLineWidth=1,s.majorLineTop=-this.top,s.majorLineHeight=Math.max(this.top+s.minorLabelHeight+s.majorLabelHeight,0),s.majorLineWidth=1,s.lineTop=0;break;case"top":s.minorLabelHeight=o?s.minorCharHeight:0,s.majorLabelHeight=r?s.majorCharHeight:0,s.majorLabelTop=0,s.minorLabelTop=s.majorLabelTop+s.majorLabelHeight,s.minorLineTop=s.minorLabelTop,s.minorLineHeight=Math.max(d-s.majorLabelHeight-this.top),s.minorLineWidth=1,s.majorLineTop=0,s.majorLineHeight=Math.max(d-this.top),s.majorLineWidth=1,s.lineTop=s.majorLabelHeight+s.minorLabelHeight;break;default:throw Error('Unkown orientation "'+this.getOption("orientation")+'"')}var l=s.minorLabelHeight+s.majorLabelHeight;t+=e(this,"width",i.offsetWidth),t+=e(this,"height",l),this._updateConversion();var u=C.convert(n.start,"Date"),c=C.convert(n.end,"Date"),p=this.toTime(5*(s.minorCharWidth||10))-this.toTime(0);this.step=new TimeStep(u,c,p),t+=e(s.range,"start",u.valueOf()),t+=e(s.range,"end",c.valueOf()),t+=e(s.range,"minimumStep",p.valueOf())}return t>0},p.prototype._updateConversion=function(){var t=this.range;if(!t)throw Error("No range configured");this.conversion=t.conversion?t.conversion(this.width):h.conversion(t.start,t.end,this.width)},f.prototype=new u,f.types={box:g,range:y,point:v},f.prototype.setOptions=l.prototype.setOptions,f.prototype.setRange=function(t){if(!(t instanceof h||t&&t.start&&t.end))throw new TypeError("Range must be an instance of Range, or an object containing start and end.");this.range=t},f.prototype.repaint=function(){var t=0,e=C.updateProperty,i=C.option.asSize,n=this.options,s=this.getOption("orientation"),o=this.defaultOptions,r=this.frame;if(!r){r=document.createElement("div"),r.className="itemset";var a=n.className;a&&C.addClassName(r,C.option.asString(a));var h=document.createElement("div");h.className="background",r.appendChild(h),this.dom.background=h;var d=document.createElement("div");d.className="foreground",r.appendChild(d),this.dom.foreground=d;var l=document.createElement("div");l.className="itemset-axis",this.dom.axis=l,this.frame=r,t+=1}if(!this.parent)throw Error("Cannot repaint itemset: no parent attached");var u=this.parent.getContainer();if(!u)throw Error("Cannot repaint itemset: parent has no container element");r.parentNode||(u.appendChild(r),t+=1),this.dom.axis.parentNode||(u.appendChild(this.dom.axis),t+=1),t+=e(r.style,"left",i(n.left,"0px")),t+=e(r.style,"top",i(n.top,"0px")),t+=e(r.style,"width",i(n.width,"100%")),t+=e(r.style,"height",i(n.height,this.height+"px")),t+=e(this.dom.axis.style,"left",i(n.left,"0px")),t+=e(this.dom.axis.style,"width",i(n.width,"100%")),t+="bottom"==s?e(this.dom.axis.style,"top",this.height+this.top+"px"):e(this.dom.axis.style,"top",this.top+"px"),this._updateConversion();var c=this,p=this.queue,m=this.itemsData,g=this.items,v={};return Object.keys(p).forEach(function(e){var i=p[e],s=g[e];switch(i){case"add":case"update":var r=m&&m.get(e,v);if(r){var a=r.type||r.start&&r.end&&"range"||n.type||"box",h=f.types[a];if(s&&(h&&s instanceof h?(s.data=r,t++):(t+=s.hide(),s=null)),!s){if(!h)throw new TypeError('Unknown item type "'+a+'"');s=new h(c,r,n,o),t++}s.repaint(),g[e]=s}delete p[e];break;case"remove":s&&(t+=s.hide()),delete g[e],delete p[e];break;default:console.log('Error: unknown action "'+i+'"')}}),C.forEach(this.items,function(e){e.visible?(t+=e.show(),e.reposition()):t+=e.hide()}),t>0},f.prototype.getForeground=function(){return this.dom.foreground},f.prototype.getBackground=function(){return this.dom.background},f.prototype.getAxis=function(){return this.dom.axis},f.prototype.reflow=function(){var t=0,e=this.options,i=e.margin&&e.margin.axis||this.defaultOptions.margin.axis,n=e.margin&&e.margin.item||this.defaultOptions.margin.item,s=C.updateProperty,o=C.option.asNumber,r=C.option.asSize,a=this.frame;if(a){this._updateConversion(),C.forEach(this.items,function(e){t+=e.reflow()}),this.stack.update();var h,d=o(e.maxHeight),l=null!=r(e.height);if(l)h=a.offsetHeight;else{var u=this.stack.ordered;if(u.length){var c=u[0].top,p=u[0].top+u[0].height;C.forEach(u,function(t){c=Math.min(c,t.top),p=Math.max(p,t.top+t.height)}),h=p-c+i+n}else h=i+n}null!=d&&(h=Math.min(h,d)),t+=s(this,"height",h),t+=s(this,"top",a.offsetTop),t+=s(this,"left",a.offsetLeft),t+=s(this,"width",a.offsetWidth)}else t+=1;return t>0},f.prototype.hide=function(){var t=!1;return this.frame&&this.frame.parentNode&&(this.frame.parentNode.removeChild(this.frame),t=!0),this.dom.axis&&this.dom.axis.parentNode&&(this.dom.axis.parentNode.removeChild(this.dom.axis),t=!0),t},f.prototype.setItems=function(t){var e,i=this,n=this.itemsData;if(t){if(!(t instanceof o||t instanceof r))throw new TypeError("Data must be an instance of DataSet");this.itemsData=t}else this.itemsData=null;if(n&&(C.forEach(this.listeners,function(t,e){n.unsubscribe(e,t)}),e=n.getIds(),this._onRemove(e)),this.itemsData){var s=this.id;C.forEach(this.listeners,function(t,e){i.itemsData.subscribe(e,t,s)}),e=this.itemsData.getIds(),this._onAdd(e)}},f.prototype.getItems=function(){return this.itemsData},f.prototype._onUpdate=function(t){this._toQueue("update",t)},f.prototype._onAdd=function(t){this._toQueue("add",t)},f.prototype._onRemove=function(t){this._toQueue("remove",t)},f.prototype._toQueue=function(t,e){var i=this.queue;e.forEach(function(e){i[e]=t}),this.controller&&this.requestRepaint()},f.prototype._updateConversion=function(){var t=this.range;if(!t)throw Error("No range configured");this.conversion=t.conversion?t.conversion(this.width):h.conversion(t.start,t.end,this.width)},f.prototype.toTime=function(t){var e=this.conversion;return new Date(t/e.factor+e.offset)},f.prototype.toScreen=function(t){var e=this.conversion;return(t.valueOf()-e.offset)*e.factor},m.prototype.select=function(){this.selected=!0},m.prototype.unselect=function(){this.selected=!1},m.prototype.show=function(){return!1},m.prototype.hide=function(){return!1},m.prototype.repaint=function(){return!1},m.prototype.reflow=function(){return!1},g.prototype=new m(null,null),g.prototype.select=function(){this.selected=!0},g.prototype.unselect=function(){this.selected=!1},g.prototype.repaint=function(){var t=!1,e=this.dom;if(e||(this._create(),e=this.dom,t=!0),e){if(!this.parent)throw Error("Cannot repaint item: no parent attached");var i=this.parent.getForeground();if(!i)throw Error("Cannot repaint time axis: parent has no foreground container element");var n=this.parent.getBackground();if(!n)throw Error("Cannot repaint time axis: parent has no background container element");var s=this.parent.getAxis();if(!n)throw Error("Cannot repaint time axis: parent has no axis container element");if(e.box.parentNode||(i.appendChild(e.box),t=!0),e.line.parentNode||(n.appendChild(e.line),t=!0),e.dot.parentNode||(s.appendChild(e.dot),t=!0),this.data.content!=this.content){if(this.content=this.data.content,this.content instanceof Element)e.content.innerHTML="",e.content.appendChild(this.content);else{if(void 0==this.data.content)throw Error('Property "content" missing in item '+this.data.id);e.content.innerHTML=this.content}t=!0}var o=(this.data.className?" "+this.data.className:"")+(this.selected?" selected":"");this.className!=o&&(this.className=o,e.box.className="item box"+o,e.line.className="item line"+o,e.dot.className="item dot"+o,t=!0)}return t},g.prototype.show=function(){return this.dom&&this.dom.box.parentNode?!1:this.repaint()},g.prototype.hide=function(){var t=!1,e=this.dom;return e&&(e.box.parentNode&&(e.box.parentNode.removeChild(e.box),t=!0),e.line.parentNode&&e.line.parentNode.removeChild(e.line),e.dot.parentNode&&e.dot.parentNode.removeChild(e.dot)),t},g.prototype.reflow=function(){var t,e,i,n,s,o,r,a,h,d,l,u,c=0;if(void 0==this.data.start)throw Error('Property "start" missing in item '+this.data.id);if(l=this.data,u=this.parent&&this.parent.range,l&&u){var p=u.end-u.start;this.visible=l.start>u.start-p&&l.start0},g.prototype._create=function(){var t=this.dom;t||(this.dom=t={},t.box=document.createElement("DIV"),t.content=document.createElement("DIV"),t.content.className="content",t.box.appendChild(t.content),t.line=document.createElement("DIV"),t.line.className="line",t.dot=document.createElement("DIV"),t.dot.className="dot")},g.prototype.reposition=function(){var t=this.dom,e=this.props,i=this.options.orientation||this.defaultOptions.orientation;if(t){var n=t.box,s=t.line,o=t.dot;n.style.left=this.left+"px",n.style.top=this.top+"px",s.style.left=e.line.left+"px","top"==i?(s.style.top="0px",s.style.height=this.top+"px"):(s.style.top=this.top+this.height+"px",s.style.height=Math.max(this.parent.height-this.top-this.height+this.props.dot.height/2,0)+"px"),o.style.left=e.dot.left+"px",o.style.top=e.dot.top+"px"}},v.prototype=new m(null,null),v.prototype.select=function(){this.selected=!0},v.prototype.unselect=function(){this.selected=!1},v.prototype.repaint=function(){var t=!1,e=this.dom;if(e||(this._create(),e=this.dom,t=!0),e){if(!this.parent)throw Error("Cannot repaint item: no parent attached");var i=this.parent.getForeground();if(!i)throw Error("Cannot repaint time axis: parent has no foreground container element");if(e.point.parentNode||(i.appendChild(e.point),i.appendChild(e.point),t=!0),this.data.content!=this.content){if(this.content=this.data.content,this.content instanceof Element)e.content.innerHTML="",e.content.appendChild(this.content);else{if(void 0==this.data.content)throw Error('Property "content" missing in item '+this.data.id);e.content.innerHTML=this.content}t=!0}var n=(this.data.className?" "+this.data.className:"")+(this.selected?" selected":"");this.className!=n&&(this.className=n,e.point.className="item point"+n,t=!0)}return t},v.prototype.show=function(){return this.dom&&this.dom.point.parentNode?!1:this.repaint()},v.prototype.hide=function(){var t=!1,e=this.dom;return e&&e.point.parentNode&&(e.point.parentNode.removeChild(e.point),t=!0),t},v.prototype.reflow=function(){var t,e,i,n,s,o,r,a,h,d,l=0;if(void 0==this.data.start)throw Error('Property "start" missing in item '+this.data.id);if(h=this.data,d=this.parent&&this.parent.range,h&&d){var u=d.end-d.start;this.visible=h.start>d.start-u&&h.start0},v.prototype._create=function(){var t=this.dom;t||(this.dom=t={},t.point=document.createElement("div"),t.content=document.createElement("div"),t.content.className="content",t.point.appendChild(t.content),t.dot=document.createElement("div"),t.dot.className="dot",t.point.appendChild(t.dot))},v.prototype.reposition=function(){var t=this.dom,e=this.props;t&&(t.point.style.top=this.top+"px",t.point.style.left=this.left+"px",t.content.style.marginLeft=e.content.marginLeft+"px",t.dot.style.top=e.dot.top+"px")},y.prototype=new m(null,null),y.prototype.select=function(){this.selected=!0},y.prototype.unselect=function(){this.selected=!1},y.prototype.repaint=function(){var t=!1,e=this.dom;if(e||(this._create(),e=this.dom,t=!0),e){if(!this.parent)throw Error("Cannot repaint item: no parent attached");var i=this.parent.getForeground();if(!i)throw Error("Cannot repaint time axis: parent has no foreground container element");if(e.box.parentNode||(i.appendChild(e.box),t=!0),this.data.content!=this.content){if(this.content=this.data.content,this.content instanceof Element)e.content.innerHTML="",e.content.appendChild(this.content);else{if(void 0==this.data.content)throw Error('Property "content" missing in item '+this.data.id); +e.content.innerHTML=this.content}t=!0}var n=this.data.className?" "+this.data.className:"";this.className!=n&&(this.className=n,e.box.className="item range"+n,t=!0)}return t},y.prototype.show=function(){return this.dom&&this.dom.box.parentNode?!1:this.repaint()},y.prototype.hide=function(){var t=!1,e=this.dom;return e&&e.box.parentNode&&(e.box.parentNode.removeChild(e.box),t=!0),t},y.prototype.reflow=function(){var t,e,i,n,s,o,r,a,h,d,l,u,c,p,f,m,g=0;if(void 0==this.data.start)throw Error('Property "start" missing in item '+this.data.id);if(void 0==this.data.end)throw Error('Property "end" missing in item '+this.data.id);return h=this.data,d=this.parent&&this.parent.range,this.visible=h&&d?h.startd.start:!1,this.visible&&(t=this.dom,t?(e=this.props,i=this.options,o=this.parent,r=o.toScreen(this.data.start),a=o.toScreen(this.data.end),l=C.updateProperty,u=t.box,c=o.width,f=i.orientation||this.defaultOptions.orientation,n=i.margin&&i.margin.axis||this.defaultOptions.margin.axis,s=i.padding||this.defaultOptions.padding,g+=l(e.content,"width",t.content.offsetWidth),g+=l(this,"height",u.offsetHeight),-c>r&&(r=-c),a>2*c&&(a=2*c),p=0>r?Math.min(-r,a-r-e.content.width-2*s):0,g+=l(e.content,"left",p),"top"==f?(m=n,g+=l(this,"top",m)):(m=o.height-this.height-n,g+=l(this,"top",m)),g+=l(this,"left",r),g+=l(this,"width",Math.max(a-r,1))):g+=1),g>0},y.prototype._create=function(){var t=this.dom;t||(this.dom=t={},t.box=document.createElement("div"),t.content=document.createElement("div"),t.content.className="content",t.box.appendChild(t.content))},y.prototype.reposition=function(){var t=this.dom,e=this.props;t&&(t.box.style.top=this.top+"px",t.box.style.left=this.left+"px",t.box.style.width=this.width+"px",t.content.style.left=e.content.left+"px")},b.prototype=new l,b.prototype.setOptions=l.prototype.setOptions,b.prototype.getContainer=function(){return this.parent.getContainer()},b.prototype.setItems=function(t){if(this.itemset&&(this.itemset.hide(),this.itemset.setItems(),this.parent.controller.remove(this.itemset),this.itemset=null),t){var e=this.groupId,i=Object.create(this.options);this.itemset=new f(this,null,i),this.itemset.setRange(this.parent.range),this.view=new r(t,{filter:function(t){return t.group==e}}),this.itemset.setItems(this.view),this.parent.controller.add(this.itemset)}},b.prototype.repaint=function(){return!1},b.prototype.reflow=function(){var t=0,e=C.updateProperty;if(t+=e(this,"top",this.itemset?this.itemset.top:0),t+=e(this,"height",this.itemset?this.itemset.height:0),this.label){var i=this.label.firstChild;t+=e(this.props.label,"width",i.clientWidth),t+=e(this.props.label,"height",i.clientHeight)}else t+=e(this.props.label,"width",0),t+=e(this.props.label,"height",0);return t>0},w.prototype=new u,w.prototype.setOptions=l.prototype.setOptions,w.prototype.setRange=function(){},w.prototype.setItems=function(t){this.itemsData=t;for(var e in this.groups)if(this.groups.hasOwnProperty(e)){var i=this.groups[e];i.setItems(t)}},w.prototype.getItems=function(){return this.itemsData},w.prototype.setRange=function(t){this.range=t},w.prototype.setGroups=function(t){var e,i=this;if(this.groupsData&&(C.forEach(this.listeners,function(t,e){i.groupsData.unsubscribe(e,t)}),e=this.groupsData.getIds(),this._onRemove(e)),t?t instanceof o?this.groupsData=t:(this.groupsData=new o({convert:{start:"Date",end:"Date"}}),this.groupsData.add(t)):this.groupsData=null,this.groupsData){var n=this.id;C.forEach(this.listeners,function(t,e){i.groupsData.subscribe(e,t,n)}),e=this.groupsData.getIds(),this._onAdd(e)}},w.prototype.getGroups=function(){return this.groupsData},w.prototype.repaint=function(){var t,e,i,n,s=0,o=C.updateProperty,r=C.option.asSize,a=C.option.asElement,h=this.options,d=this.dom.frame,l=this.dom.labels;if(!this.parent)throw Error("Cannot repaint groupset: no parent attached");var u=this.parent.getContainer();if(!u)throw Error("Cannot repaint groupset: parent has no container element");if(!d){d=document.createElement("div"),d.className="groupset",this.dom.frame=d;var c=h.className;c&&C.addClassName(d,C.option.asString(c)),s+=1}d.parentNode||(u.appendChild(d),s+=1);var p=a(h.labelContainer);if(!p)throw Error('Cannot repaint groupset: option "labelContainer" not defined');l||(l=document.createElement("div"),l.className="labels",this.dom.labels=l),l.parentNode&&l.parentNode==p||(l.parentNode&&l.parentNode.removeChild(l.parentNode),p.appendChild(l)),s+=o(d.style,"height",r(h.height,this.height+"px")),s+=o(d.style,"top",r(h.top,"0px")),s+=o(d.style,"left",r(h.left,"0px")),s+=o(d.style,"width",r(h.width,"100%")),s+=o(l.style,"top",r(h.top,"0px"));var f=this,m=this.queue,g=this.groups,v=this.groupsData,y=Object.keys(m);if(y.length){y.forEach(function(t){var e=m[t],i=g[t];switch(e){case"add":case"update":if(!i){var n=Object.create(f.options);i=new b(f,t,n),i.setItems(f.itemsData),g[t]=i,f.controller.add(i)}i.data=v.get(t),delete m[t];break;case"remove":i&&(i.setItems(),delete g[t],f.controller.remove(i)),delete m[t];break;default:console.log('Error: unknown action "'+e+'"')}});var w=this.groupsData.getIds({order:this.options.groupsOrder});for(t=0;w.length>t;t++)(function(t,e){var i=0;e&&(i=function(){return e.top+e.height}),t.setOptions({top:i})})(g[w[t]],g[w[t-1]]);for(;l.firstChild;)l.removeChild(l.firstChild);for(t=0;w.length>t;t++)e=w[t],n=this._createLabel(e),l.appendChild(n);s++}for(e in g)g.hasOwnProperty(e)&&(i=g[e],n=i.label,n&&(n.style.top=i.top+"px",n.style.height=i.height+"px"));return s>0},w.prototype._createLabel=function(t){var e=this.groups[t],i=document.createElement("div");i.className="label";var n=document.createElement("div");n.className="inner",i.appendChild(n);var s=e.data&&e.data.content;s instanceof Element?n.appendChild(s):void 0!=s&&(n.innerHTML=s);var o=e.data&&e.data.className;return o&&C.addClassName(i,o),e.label=i,i},w.prototype.getContainer=function(){return this.dom.frame},w.prototype.getLabelsWidth=function(){return this.props.labels.width},w.prototype.reflow=function(){var t,e,i=0,n=this.options,s=C.updateProperty,o=C.option.asNumber,r=C.option.asSize,a=this.dom.frame;if(a){var h,d=o(n.maxHeight),l=null!=r(n.height);if(l)h=a.offsetHeight;else{h=0;for(t in this.groups)this.groups.hasOwnProperty(t)&&(e=this.groups[t],h+=e.height)}null!=d&&(h=Math.min(h,d)),i+=s(this,"height",h),i+=s(this,"top",a.offsetTop),i+=s(this,"left",a.offsetLeft),i+=s(this,"width",a.offsetWidth)}var u=0;for(t in this.groups)if(this.groups.hasOwnProperty(t)){e=this.groups[t];var c=e.props&&e.props.label&&e.props.label.width||0;u=Math.max(u,c)}return i+=s(this.props.labels,"width",u),i>0},w.prototype.hide=function(){return this.dom.frame&&this.dom.frame.parentNode?(this.dom.frame.parentNode.removeChild(this.dom.frame),!0):!1},w.prototype.show=function(){return this.dom.frame&&this.dom.frame.parentNode?!1:this.repaint()},w.prototype._onUpdate=function(t){this._toQueue(t,"update")},w.prototype._onAdd=function(t){this._toQueue(t,"add")},w.prototype._onRemove=function(t){this._toQueue(t,"remove")},w.prototype._toQueue=function(t,e){var i=this.queue;t.forEach(function(t){i[t]=e}),this.controller&&this.requestRepaint()},_.prototype.setOptions=function(t){t&&C.extend(this.options,t),this.controller.reflow(),this.controller.repaint()},_.prototype.setItems=function(t){var e,i=null==this.itemsData;if(t?t instanceof o&&(e=t):e=null,t instanceof o||(e=new o({convert:{start:"Date",end:"Date"}}),e.add(t)),this.itemsData=e,this.content.setItems(e),i&&(void 0==this.options.start||void 0==this.options.end)){var n=this.getItemRange(),s=n.min,r=n.max;if(null!=s&&null!=r){var a=r.valueOf()-s.valueOf();0>=a&&(a=864e5),s=new Date(s.valueOf()-.05*a),r=new Date(r.valueOf()+.05*a)}void 0!=this.options.start&&(s=new Date(this.options.start.valueOf())),void 0!=this.options.end&&(r=new Date(this.options.end.valueOf())),(null!=s||null!=r)&&this.range.setRange(s,r)}},_.prototype.setGroups=function(t){var e=this;this.groupsData=t;var i=this.groupsData?w:f;if(!(this.content instanceof i)){this.content&&(this.content.hide(),this.content.setItems&&this.content.setItems(),this.content.setGroups&&this.content.setGroups(),this.controller.remove(this.content));var n=Object.create(this.options);C.extend(n,{top:function(){return"top"==e.options.orientation?e.timeaxis.height:e.itemPanel.height-e.timeaxis.height-e.content.height},left:null,width:"100%",height:function(){return e.options.height?e.itemPanel.height-e.timeaxis.height:null},maxHeight:function(){if(e.options.maxHeight){if(!C.isNumber(e.options.maxHeight))throw new TypeError("Number expected for property maxHeight");return e.options.maxHeight-e.timeaxis.height}return null},labelContainer:function(){return e.labelPanel.getContainer()}}),this.content=new i(this.itemPanel,[this.timeaxis],n),this.content.setRange&&this.content.setRange(this.range),this.content.setItems&&this.content.setItems(this.itemsData),this.content.setGroups&&this.content.setGroups(this.groupsData),this.controller.add(this.content)}},_.prototype.getItemRange=function(){var t=this.itemsData,e=null,i=null;if(t){var n=t.min("start");e=n?n.start.valueOf():null;var s=t.max("start");s&&(i=s.start.valueOf());var o=t.max("end");o&&(i=null==i?o.end.valueOf():Math.max(i,o.end.valueOf()))}return{min:null!=e?new Date(e):null,max:null!=i?new Date(i):null}},function(t){function e(t){return M=t,c()}function i(){D=0,C=M.charAt(0)}function n(){D++,C=M.charAt(D)}function s(){return M.charAt(D+1)}function o(t){return L.test(t)}function r(t,e){if(t||(t={}),e)for(var i in e)e.hasOwnProperty(i)&&(t[i]=e[i]);return t}function a(t,e,i){for(var n=e.split("."),s=t;n.length;){var o=n.shift();n.length?(s[o]||(s[o]={}),s=s[o]):s[o]=i}}function h(t,e){for(var i,n,s=null,o=[t],a=t;a.parent;)o.push(a.parent),a=a.parent;if(a.nodes)for(i=0,n=a.nodes.length;n>i;i++)if(e.id===a.nodes[i].id){s=a.nodes[i];break}for(s||(s={id:e.id},t.node&&(s.attr=r(s.attr,t.node))),i=o.length-1;i>=0;i--){var h=o[i];h.nodes||(h.nodes=[]),-1==h.nodes.indexOf(s)&&h.nodes.push(s)}e.attr&&(s.attr=r(s.attr,e.attr))}function d(t,e){if(t.edges||(t.edges=[]),t.edges.push(e),t.edge){var i=r({},t.edge);e.attr=r(i,e.attr)}}function l(t,e,i,n,s){var o={from:e,to:i,type:n};return t.edge&&(o.attr=r({},t.edge)),o.attr=r(o.attr||{},s),o}function u(){for(N=x.NULL,O="";" "==C||" "==C||"\n"==C||"\r"==C;)n();do{var t=!1;if("#"==C){for(var e=D-1;" "==M.charAt(e)||" "==M.charAt(e);)e--;if("\n"==M.charAt(e)||""==M.charAt(e)){for(;""!=C&&"\n"!=C;)n();t=!0}}if("/"==C&&"/"==s()){for(;""!=C&&"\n"!=C;)n();t=!0}if("/"==C&&"*"==s()){for(;""!=C;){if("*"==C&&"/"==s()){n(),n();break}n()}t=!0}for(;" "==C||" "==C||"\n"==C||"\r"==C;)n()}while(t);if(""==C)return N=x.DELIMITER,void 0;var i=C+s();if(S[i])return N=x.DELIMITER,O=i,n(),n(),void 0;if(S[C])return N=x.DELIMITER,O=C,n(),void 0;if(o(C)||"-"==C){for(O+=C,n();o(C);)O+=C,n();return"false"==O?O=!1:"true"==O?O=!0:isNaN(Number(O))||(O=Number(O)),N=x.IDENTIFIER,void 0}if('"'==C){for(n();""!=C&&('"'!=C||'"'==C&&'"'==s());)O+=C,'"'==C&&n(),n();if('"'!=C)throw w('End of string " expected');return n(),N=x.IDENTIFIER,void 0}for(N=x.UNKNOWN;""!=C;)O+=C,n();throw new SyntaxError('Syntax error in part "'+_(O,30)+'"')}function c(){var t={};if(i(),u(),"strict"==O&&(t.strict=!0,u()),("graph"==O||"digraph"==O)&&(t.type=O,u()),N==x.IDENTIFIER&&(t.id=O,u()),"{"!=O)throw w("Angle bracket { expected");if(u(),p(t),"}"!=O)throw w("Angle bracket } expected");if(u(),""!==O)throw w("End of file expected");return u(),delete t.node,delete t.edge,delete t.graph,t}function p(t){for(;""!==O&&"}"!=O;)f(t),";"==O&&u()}function f(t){var e=m(t);if(e)return y(t,e),void 0;var i=g(t);if(!i){if(N!=x.IDENTIFIER)throw w("Identifier expected");var n=O;if(u(),"="==O){if(u(),N!=x.IDENTIFIER)throw w("Identifier expected");t[n]=O,u()}else v(t,n)}}function m(t){var e=null;if("subgraph"==O&&(e={},e.type="subgraph",u(),N==x.IDENTIFIER&&(e.id=O,u())),"{"==O){if(u(),e||(e={}),e.parent=t,e.node=t.node,e.edge=t.edge,e.graph=t.graph,p(e),"}"!=O)throw w("Angle bracket } expected");u(),delete e.node,delete e.edge,delete e.graph,delete e.parent,t.subgraphs||(t.subgraphs=[]),t.subgraphs.push(e)}return e}function g(t){return"node"==O?(u(),t.node=b(),"node"):"edge"==O?(u(),t.edge=b(),"edge"):"graph"==O?(u(),t.graph=b(),"graph"):null}function v(t,e){var i={id:e},n=b();n&&(i.attr=n),h(t,i),y(t,e)}function y(t,e){for(;"->"==O||"--"==O;){var i,n=O;u();var s=m(t);if(s)i=s;else{if(N!=x.IDENTIFIER)throw w("Identifier or subgraph expected");i=O,h(t,{id:i}),u()}var o=b(),r=l(t,e,i,n,o);d(t,r),e=i}}function b(){for(var t=null;"["==O;){for(u(),t={};""!==O&&"]"!=O;){if(N!=x.IDENTIFIER)throw w("Attribute name expected");var e=O;if(u(),"="!=O)throw w("Equal sign = expected");if(u(),N!=x.IDENTIFIER)throw w("Attribute value expected");var i=O;a(t,e,i),u(),","==O&&u()}if("]"!=O)throw w("Bracket ] expected");u()}return t}function w(t){return new SyntaxError(t+', got "'+_(O,30)+'" (char '+D+")")}function _(t,e){return e>=t.length?t:t.substr(0,27)+"..."}function E(t,e,i){t instanceof Array?t.forEach(function(t){e instanceof Array?e.forEach(function(e){i(t,e)}):i(t,e)}):e instanceof Array?e.forEach(function(e){i(t,e)}):i(t,e)}function T(t){function i(t){var e={from:t.from,to:t.to};return r(e,t.attr),e.style="->"==t.type?"arrow":"line",e}var n=e(t),s={nodes:[],edges:[],options:{}};return n.nodes&&n.nodes.forEach(function(t){var e={id:t.id,label:(t.label||t.id)+""};r(e,t.attr),e.image&&(e.shape="image"),s.nodes.push(e)}),n.edges&&n.edges.forEach(function(t){var e,n;e=t.from instanceof Object?t.from.nodes:{id:t.from},n=t.to instanceof Object?t.to.nodes:{id:t.to},t.from instanceof Object&&t.from.edges&&t.from.edges.forEach(function(t){var e=i(t);s.edges.push(e)}),E(e,n,function(e,n){var o=l(s,e.id,n.id,t.type,t.attr),r=i(o);s.edges.push(r)}),t.to instanceof Object&&t.to.edges&&t.to.edges.forEach(function(t){var e=i(t);s.edges.push(e)})}),n.attr&&(s.options=n.attr),s}var x={NULL:0,DELIMITER:1,IDENTIFIER:2,UNKNOWN:3},S={"{":!0,"}":!0,"[":!0,"]":!0,";":!0,"=":!0,",":!0,"->":!0,"--":!0},M="",D=0,C="",O="",N=x.NULL,L=/[a-zA-Z_0-9.:#]/;t.parseDOT=e,t.DOTToGraph=T}(C!==void 0?C:n),"undefined"!=typeof CanvasRenderingContext2D&&(CanvasRenderingContext2D.prototype.circle=function(t,e,i){this.beginPath(),this.arc(t,e,i,0,2*Math.PI,!1)},CanvasRenderingContext2D.prototype.square=function(t,e,i){this.beginPath(),this.rect(t-i,e-i,2*i,2*i)},CanvasRenderingContext2D.prototype.triangle=function(t,e,i){this.beginPath();var n=2*i,s=n/2,o=Math.sqrt(3)/6*n,r=Math.sqrt(n*n-s*s);this.moveTo(t,e-(r-o)),this.lineTo(t+s,e+o),this.lineTo(t-s,e+o),this.lineTo(t,e-(r-o)),this.closePath()},CanvasRenderingContext2D.prototype.triangleDown=function(t,e,i){this.beginPath();var n=2*i,s=n/2,o=Math.sqrt(3)/6*n,r=Math.sqrt(n*n-s*s);this.moveTo(t,e+(r-o)),this.lineTo(t+s,e-o),this.lineTo(t-s,e-o),this.lineTo(t,e+(r-o)),this.closePath()},CanvasRenderingContext2D.prototype.star=function(t,e,i){this.beginPath();for(var n=0;10>n;n++){var s=0===n%2?1.3*i:.5*i;this.lineTo(t+s*Math.sin(2*n*Math.PI/10),e-s*Math.cos(2*n*Math.PI/10))}this.closePath()},CanvasRenderingContext2D.prototype.roundRect=function(t,e,i,n,s){var o=Math.PI/180;0>i-2*s&&(s=i/2),0>n-2*s&&(s=n/2),this.beginPath(),this.moveTo(t+s,e),this.lineTo(t+i-s,e),this.arc(t+i-s,e+s,s,270*o,360*o,!1),this.lineTo(t+i,e+n-s),this.arc(t+i-s,e+n-s,s,0,90*o,!1),this.lineTo(t+s,e+n),this.arc(t+s,e+n-s,s,90*o,180*o,!1),this.lineTo(t,e+s),this.arc(t+s,e+s,s,180*o,270*o,!1)},CanvasRenderingContext2D.prototype.ellipse=function(t,e,i,n){var s=.5522848,o=i/2*s,r=n/2*s,a=t+i,h=e+n,d=t+i/2,l=e+n/2;this.beginPath(),this.moveTo(t,l),this.bezierCurveTo(t,l-r,d-o,e,d,e),this.bezierCurveTo(d+o,e,a,l-r,a,l),this.bezierCurveTo(a,l+r,d+o,h,d,h),this.bezierCurveTo(d-o,h,t,l+r,t,l)},CanvasRenderingContext2D.prototype.database=function(t,e,i,n){var s=1/3,o=i,r=n*s,a=.5522848,h=o/2*a,d=r/2*a,l=t+o,u=e+r,c=t+o/2,p=e+r/2,f=e+(n-r/2),m=e+n;this.beginPath(),this.moveTo(l,p),this.bezierCurveTo(l,p+d,c+h,u,c,u),this.bezierCurveTo(c-h,u,t,p+d,t,p),this.bezierCurveTo(t,p-d,c-h,e,c,e),this.bezierCurveTo(c+h,e,l,p-d,l,p),this.lineTo(l,f),this.bezierCurveTo(l,f+d,c+h,m,c,m),this.bezierCurveTo(c-h,m,t,f+d,t,f),this.lineTo(t,p)},CanvasRenderingContext2D.prototype.arrow=function(t,e,i,n){var s=t-n*Math.cos(i),o=e-n*Math.sin(i),r=t-.9*n*Math.cos(i),a=e-.9*n*Math.sin(i),h=s+n/3*Math.cos(i+.5*Math.PI),d=o+n/3*Math.sin(i+.5*Math.PI),l=s+n/3*Math.cos(i-.5*Math.PI),u=o+n/3*Math.sin(i-.5*Math.PI);this.beginPath(),this.moveTo(t,e),this.lineTo(h,d),this.lineTo(r,a),this.lineTo(l,u),this.closePath()},CanvasRenderingContext2D.prototype.dashedLine=function(t,e,i,n,s){s||(s=[10,5]),0==c&&(c=.001);var o=s.length;this.moveTo(t,e);for(var r=i-t,a=n-e,h=a/r,d=Math.sqrt(r*r+a*a),l=0,u=!0;d>=.1;){var c=s[l++%o];c>d&&(c=d);var p=Math.sqrt(c*c/(1+h*h));0>r&&(p=-p),t+=p,e+=h*p,this[u?"lineTo":"moveTo"](t,e),d-=c,u=!u}}),E.prototype.attachEdge=function(t){-1==this.edges.indexOf(t)&&this.edges.push(t),this._updateMass()},E.prototype.detachEdge=function(t){var e=this.edges.indexOf(t);-1!=e&&this.edges.splice(e,1),this._updateMass()},E.prototype._updateMass=function(){this.mass=50+20*this.edges.length},E.prototype.setProperties=function(t,e){if(t){if(void 0!=t.id&&(this.id=t.id),void 0!=t.label&&(this.label=t.label),void 0!=t.title&&(this.title=t.title),void 0!=t.group&&(this.group=t.group),void 0!=t.x&&(this.x=t.x),void 0!=t.y&&(this.y=t.y),void 0!=t.value&&(this.value=t.value),void 0===this.id)throw"Node must have an id";if(this.group){var i=this.grouplist.get(this.group);for(var n in i)i.hasOwnProperty(n)&&(this[n]=i[n])}if(void 0!=t.shape&&(this.shape=t.shape),void 0!=t.image&&(this.image=t.image),void 0!=t.radius&&(this.radius=t.radius),void 0!=t.color&&(this.color=E.parseColor(t.color)),void 0!=t.fontColor&&(this.fontColor=t.fontColor),void 0!=t.fontSize&&(this.fontSize=t.fontSize),void 0!=t.fontFace&&(this.fontFace=t.fontFace),void 0!=this.image){if(!this.imagelist)throw"No imagelist provided";this.imageObj=this.imagelist.load(this.image)}switch(this.xFixed=this.xFixed||void 0!=t.x,this.yFixed=this.yFixed||void 0!=t.y,this.radiusFixed=this.radiusFixed||void 0!=t.radius,"image"==this.shape&&(this.radiusMin=e.nodes.widthMin,this.radiusMax=e.nodes.widthMax),this.shape){case"database":this.draw=this._drawDatabase,this.resize=this._resizeDatabase;break;case"box":this.draw=this._drawBox,this.resize=this._resizeBox;break;case"circle":this.draw=this._drawCircle,this.resize=this._resizeCircle;break;case"ellipse":this.draw=this._drawEllipse,this.resize=this._resizeEllipse;break;case"image":this.draw=this._drawImage,this.resize=this._resizeImage;break;case"text":this.draw=this._drawText,this.resize=this._resizeText;break;case"dot":this.draw=this._drawDot,this.resize=this._resizeShape;break;case"square":this.draw=this._drawSquare,this.resize=this._resizeShape;break;case"triangle":this.draw=this._drawTriangle,this.resize=this._resizeShape;break;case"triangleDown":this.draw=this._drawTriangleDown,this.resize=this._resizeShape;break;case"star":this.draw=this._drawStar,this.resize=this._resizeShape;break;default:this.draw=this._drawEllipse,this.resize=this._resizeEllipse}this._reset()}},E.parseColor=function(t){var e;return C.isString(t)?e={border:t,background:t,highlight:{border:t,background:t}}:(e={},e.background=t.background||"white",e.border=t.border||e.background,C.isString(t.highlight)?e.highlight={border:t.highlight,background:t.highlight}:(e.highlight={},e.highlight.background=t.highlight&&t.highlight.background||e.background,e.highlight.border=t.highlight&&t.highlight.border||e.border)),e},E.prototype.select=function(){this.selected=!0,this._reset()},E.prototype.unselect=function(){this.selected=!1,this._reset()},E.prototype._reset=function(){this.width=void 0,this.height=void 0},E.prototype.getTitle=function(){return this.title},E.prototype.distanceToBorder=function(t,e){var i=1;switch(this.width||this.resize(t),this.shape){case"circle":case"dot":return this.radius+i;case"ellipse":var n=this.width/2,s=this.height/2,o=Math.sin(e)*n,r=Math.cos(e)*s;return n*s/Math.sqrt(o*o+r*r);case"box":case"image":case"text":default:return this.width?Math.min(Math.abs(this.width/2/Math.cos(e)),Math.abs(this.height/2/Math.sin(e)))+i:0}},E.prototype._setForce=function(t,e){this.fx=t,this.fy=e},E.prototype._addForce=function(t,e){this.fx+=t,this.fy+=e},E.prototype.discreteStep=function(t){if(!this.xFixed){var e=-this.damping*this.vx,i=(this.fx+e)/this.mass;this.vx+=i/t,this.x+=this.vx/t}if(!this.yFixed){var n=-this.damping*this.vy,s=(this.fy+n)/this.mass;this.vy+=s/t,this.y+=this.vy/t}},E.prototype.isFixed=function(){return this.xFixed&&this.yFixed},E.prototype.isMoving=function(t){return Math.abs(this.vx)>t||Math.abs(this.vy)>t||!this.xFixed&&Math.abs(this.fx)>this.minForce||!this.yFixed&&Math.abs(this.fy)>this.minForce},E.prototype.isSelected=function(){return this.selected},E.prototype.getValue=function(){return this.value},E.prototype.getDistance=function(t,e){var i=this.x-t,n=this.y-e;return Math.sqrt(i*i+n*n)},E.prototype.setValueRange=function(t,e){if(!this.radiusFixed&&void 0!==this.value){var i=(this.radiusMax-this.radiusMin)/(e-t);this.radius=(this.value-t)*i+this.radiusMin}},E.prototype.draw=function(){throw"Draw method not initialized for node"},E.prototype.resize=function(){throw"Resize method not initialized for node"},E.prototype.isOverlappingWith=function(t){return this.leftt.left&&this.topt.top},E.prototype._resizeImage=function(){if(!this.width){var t,e;if(this.value){var i=this.imageObj.height/this.imageObj.width;t=this.radius||this.imageObj.width,e=this.radius*i||this.imageObj.height}else t=this.imageObj.width,e=this.imageObj.height;this.width=t,this.height=e}},E.prototype._drawImage=function(t){this._resizeImage(t),this.left=this.x-this.width/2,this.top=this.y-this.height/2;var e;this.imageObj?(t.drawImage(this.imageObj,this.left,this.top,this.width,this.height),e=this.y+this.height/2):e=this.y,this._label(t,this.label,this.x,e,void 0,"top")},E.prototype._resizeBox=function(t){if(!this.width){var e=5,i=this.getTextSize(t);this.width=i.width+2*e,this.height=i.height+2*e}},E.prototype._drawBox=function(t){this._resizeBox(t),this.left=this.x-this.width/2,this.top=this.y-this.height/2,t.strokeStyle=this.selected?this.color.highlight.border:this.color.border,t.fillStyle=this.selected?this.color.highlight.background:this.color.background,t.lineWidth=this.selected?2:1,t.roundRect(this.left,this.top,this.width,this.height,this.radius),t.fill(),t.stroke(),this._label(t,this.label,this.x,this.y)},E.prototype._resizeDatabase=function(t){if(!this.width){var e=5,i=this.getTextSize(t),n=i.width+2*e;this.width=n,this.height=n}},E.prototype._drawDatabase=function(t){this._resizeDatabase(t),this.left=this.x-this.width/2,this.top=this.y-this.height/2,t.strokeStyle=this.selected?this.color.highlight.border:this.color.border,t.fillStyle=this.selected?this.color.highlight.background:this.color.background,t.lineWidth=this.selected?2:1,t.database(this.x-this.width/2,this.y-.5*this.height,this.width,this.height),t.fill(),t.stroke(),this._label(t,this.label,this.x,this.y)},E.prototype._resizeCircle=function(t){if(!this.width){var e=5,i=this.getTextSize(t),n=Math.max(i.width,i.height)+2*e;this.radius=n/2,this.width=n,this.height=n}},E.prototype._drawCircle=function(t){this._resizeCircle(t),this.left=this.x-this.width/2,this.top=this.y-this.height/2,t.strokeStyle=this.selected?this.color.highlight.border:this.color.border,t.fillStyle=this.selected?this.color.highlight.background:this.color.background,t.lineWidth=this.selected?2:1,t.circle(this.x,this.y,this.radius),t.fill(),t.stroke(),this._label(t,this.label,this.x,this.y)},E.prototype._resizeEllipse=function(t){if(!this.width){var e=this.getTextSize(t);this.width=1.5*e.width,this.height=2*e.height,this.widthl;l++)t.fillText(r[l],i,d),d+=h}},E.prototype.getTextSize=function(t){if(void 0!=this.label){t.font=(this.selected?"bold ":"")+this.fontSize+"px "+this.fontFace;for(var e=this.label.split("\n"),i=(this.fontSize+4)*e.length,n=0,s=0,o=e.length;o>s;s++)n=Math.max(n,t.measureText(e[s]).width);return{width:n,height:i}}return{width:0,height:0}},T.prototype.setProperties=function(t,e){if(t)switch(void 0!=t.from&&(this.fromId=t.from),void 0!=t.to&&(this.toId=t.to),void 0!=t.id&&(this.id=t.id),void 0!=t.style&&(this.style=t.style),void 0!=t.label&&(this.label=t.label),this.label&&(this.fontSize=e.edges.fontSize,this.fontFace=e.edges.fontFace,this.fontColor=e.edges.fontColor,void 0!=t.fontColor&&(this.fontColor=t.fontColor),void 0!=t.fontSize&&(this.fontSize=t.fontSize),void 0!=t.fontFace&&(this.fontFace=t.fontFace)),void 0!=t.title&&(this.title=t.title),void 0!=t.width&&(this.width=t.width),void 0!=t.value&&(this.value=t.value),void 0!=t.length&&(this.length=t.length),t.dash&&(void 0!=t.dash.length&&(this.dash.length=t.dash.length),void 0!=t.dash.gap&&(this.dash.gap=t.dash.gap),void 0!=t.dash.altLength&&(this.dash.altLength=t.dash.altLength)),void 0!=t.color&&(this.color=t.color),this.connect(),this.widthFixed=this.widthFixed||void 0!=t.width,this.lengthFixed=this.lengthFixed||void 0!=t.length,this.stiffness=1/this.length,this.style){case"line":this.draw=this._drawLine;break;case"arrow":this.draw=this._drawArrow;break;case"arrow-center":this.draw=this._drawArrowCenter;break;case"dash-line":this.draw=this._drawDashLine;break;default:this.draw=this._drawLine}},T.prototype.connect=function(){this.disconnect(),this.from=this.graph.nodes[this.fromId]||null,this.to=this.graph.nodes[this.toId]||null,this.connected=this.from&&this.to,this.connected?(this.from.attachEdge(this),this.to.attachEdge(this)):(this.from&&this.from.detachEdge(this),this.to&&this.to.detachEdge(this))},T.prototype.disconnect=function(){this.from&&(this.from.detachEdge(this),this.from=null),this.to&&(this.to.detachEdge(this),this.to=null),this.connected=!1},T.prototype.getTitle=function(){return this.title},T.prototype.getValue=function(){return this.value},T.prototype.setValueRange=function(t,e){if(!this.widthFixed&&void 0!==this.value){var i=(this.widthMax-this.widthMin)/(e-t);this.width=(this.value-t)*i+this.widthMin}},T.prototype.draw=function(){throw"Method draw not initialized in edge"},T.prototype.isOverlappingWith=function(t){var e=10,i=this.from.x,n=this.from.y,s=this.to.x,o=this.to.y,r=t.left,a=t.top,h=T._dist(i,n,s,o,r,a);return e>h},T.prototype._drawLine=function(t){t.strokeStyle=this.color,t.lineWidth=this._getLineWidth();var e;if(this.from!=this.to)this._line(t),this.label&&(e=this._pointOnLine(.5),this._label(t,this.label,e.x,e.y));else{var i,n,s=this.length/4,o=this.from;o.width||o.resize(t),o.width>o.height?(i=o.x+o.width/2,n=o.y-s):(i=o.x+s,n=o.y-o.height/2),this._circle(t,i,n,s),e=this._pointOnCircle(i,n,s,.5),this._label(t,this.label,e.x,e.y)}},T.prototype._getLineWidth=function(){return this.from.selected||this.to.selected?Math.min(2*this.width,this.widthMax):this.width},T.prototype._line=function(t){t.beginPath(),t.moveTo(this.from.x,this.from.y),t.lineTo(this.to.x,this.to.y),t.stroke()},T.prototype._circle=function(t,e,i,n){t.beginPath(),t.arc(e,i,n,0,2*Math.PI,!1),t.stroke()},T.prototype._label=function(t,e,i,n){if(e){t.font=(this.from.selected||this.to.selected?"bold ":"")+this.fontSize+"px "+this.fontFace,t.fillStyle="white";var s=t.measureText(e).width,o=this.fontSize,r=i-s/2,a=n-o/2;t.fillRect(r,a,s,o),t.fillStyle=this.fontColor||"black",t.textAlign="left",t.textBaseline="top",t.fillText(e,r,a)}},T.prototype._drawDashLine=function(t){if(t.strokeStyle=this.color,t.lineWidth=this._getLineWidth(),t.beginPath(),t.lineCap="round",void 0!=this.dash.altLength?t.dashedLine(this.from.x,this.from.y,this.to.x,this.to.y,[this.dash.length,this.dash.gap,this.dash.altLength,this.dash.gap]):void 0!=this.dash.length&&void 0!=this.dash.gap?t.dashedLine(this.from.x,this.from.y,this.to.x,this.to.y,[this.dash.length,this.dash.gap]):(t.moveTo(this.from.x,this.from.y),t.lineTo(this.to.x,this.to.y)),t.stroke(),this.label){var e=this._pointOnLine(.5);this._label(t,this.label,e.x,e.y)}},T.prototype._pointOnLine=function(t){return{x:(1-t)*this.from.x+t*this.to.x,y:(1-t)*this.from.y+t*this.to.y}},T.prototype._pointOnCircle=function(t,e,i,n){var s=2*(n-3/8)*Math.PI;return{x:t+i*Math.cos(s),y:e-i*Math.sin(s)}},T.prototype._drawArrowCenter=function(t){var e;if(t.strokeStyle=this.color,t.fillStyle=this.color,t.lineWidth=this._getLineWidth(),this.from!=this.to){this._line(t);var i=Math.atan2(this.to.y-this.from.y,this.to.x-this.from.x),n=10+5*this.width;e=this._pointOnLine(.5),t.arrow(e.x,e.y,i,n),t.fill(),t.stroke(),this.label&&(e=this._pointOnLine(.5),this._label(t,this.label,e.x,e.y))}else{var s,o,r=this.length/4,a=this.from;a.width||a.resize(t),a.width>a.height?(s=a.x+a.width/2,o=a.y-r):(s=a.x+r,o=a.y-a.height/2),this._circle(t,s,o,r);var i=.2*Math.PI,n=10+5*this.width;e=this._pointOnCircle(s,o,r,.5),t.arrow(e.x,e.y,i,n),t.fill(),t.stroke(),this.label&&(e=this._pointOnCircle(s,o,r,.5),this._label(t,this.label,e.x,e.y))}},T.prototype._drawArrow=function(t){t.strokeStyle=this.color,t.fillStyle=this.color,t.lineWidth=this._getLineWidth();var e,i;if(this.from!=this.to){e=Math.atan2(this.to.y-this.from.y,this.to.x-this.from.x);var n=this.to.x-this.from.x,s=this.to.y-this.from.y,o=Math.sqrt(n*n+s*s),r=this.from.distanceToBorder(t,e+Math.PI),a=(o-r)/o,h=a*this.from.x+(1-a)*this.to.x,d=a*this.from.y+(1-a)*this.to.y,l=this.to.distanceToBorder(t,e),u=(o-l)/o,c=(1-u)*this.from.x+u*this.to.x,p=(1-u)*this.from.y+u*this.to.y;if(t.beginPath(),t.moveTo(h,d),t.lineTo(c,p),t.stroke(),i=10+5*this.width,t.arrow(c,p,e,i),t.fill(),t.stroke(),this.label){var f=this._pointOnLine(.5);this._label(t,this.label,f.x,f.y)}}else{var m,g,v,y=this.from,b=this.length/4;y.width||y.resize(t),y.width>y.height?(m=y.x+y.width/2,g=y.y-b,v={x:m,y:y.y,angle:.9*Math.PI}):(m=y.x+b,g=y.y-y.height/2,v={x:y.x,y:g,angle:.6*Math.PI}),t.beginPath(),t.arc(m,g,b,0,2*Math.PI,!1),t.stroke(),i=10+5*this.width,t.arrow(v.x,v.y,v.angle,i),t.fill(),t.stroke(),this.label&&(f=this._pointOnCircle(m,g,b,.5),this._label(t,this.label,f.x,f.y)) +}},T._dist=function(t,e,i,n,s,o){var r=i-t,a=n-e,h=r*r+a*a,d=((s-t)*r+(o-e)*a)/h;d>1?d=1:0>d&&(d=0);var l=t+d*r,u=e+d*a,c=l-s,p=u-o;return Math.sqrt(c*c+p*p)},x.prototype.setPosition=function(t,e){this.x=parseInt(t),this.y=parseInt(e)},x.prototype.setText=function(t){this.frame.innerHTML=t},x.prototype.show=function(t){if(void 0===t&&(t=!0),t){var e=this.frame.clientHeight,i=this.frame.clientWidth,n=this.frame.parentNode.clientHeight,s=this.frame.parentNode.clientWidth,o=this.y-e;o+e+this.padding>n&&(o=n-e-this.padding),this.padding>o&&(o=this.padding);var r=this.x;r+i+this.padding>s&&(r=s-i-this.padding),this.padding>r&&(r=this.padding),this.frame.style.left=r+"px",this.frame.style.top=o+"px",this.frame.style.visibility="visible"}else this.hide()},x.prototype.hide=function(){this.frame.style.visibility="hidden"},Groups=function(){this.clear(),this.defaultIndex=0},Groups.DEFAULT=[{border:"#2B7CE9",background:"#97C2FC",highlight:{border:"#2B7CE9",background:"#D2E5FF"}},{border:"#FFA500",background:"#FFFF00",highlight:{border:"#FFA500",background:"#FFFFA3"}},{border:"#FA0A10",background:"#FB7E81",highlight:{border:"#FA0A10",background:"#FFAFB1"}},{border:"#41A906",background:"#7BE141",highlight:{border:"#41A906",background:"#A1EC76"}},{border:"#E129F0",background:"#EB7DF4",highlight:{border:"#E129F0",background:"#F0B3F5"}},{border:"#7C29F0",background:"#AD85E4",highlight:{border:"#7C29F0",background:"#D3BDF0"}},{border:"#C37F00",background:"#FFA807",highlight:{border:"#C37F00",background:"#FFCA66"}},{border:"#4220FB",background:"#6E6EFD",highlight:{border:"#4220FB",background:"#9B9BFD"}},{border:"#FD5A77",background:"#FFC0CB",highlight:{border:"#FD5A77",background:"#FFD1D9"}},{border:"#4AD63A",background:"#C2FABC",highlight:{border:"#4AD63A",background:"#E6FFE3"}}],Groups.prototype.clear=function(){this.groups={},this.groups.length=function(){var t=0;for(var e in this)this.hasOwnProperty(e)&&t++;return t}},Groups.prototype.get=function(t){var e=this.groups[t];if(void 0==e){var i=this.defaultIndex%Groups.DEFAULT.length;this.defaultIndex++,e={},e.color=Groups.DEFAULT[i],this.groups[t]=e}return e},Groups.prototype.add=function(t,e){return this.groups[t]=e,e.color&&(e.color=E.parseColor(e.color)),e},Images=function(){this.images={},this.callback=void 0},Images.prototype.setOnloadCallback=function(t){this.callback=t},Images.prototype.load=function(t){var e=this.images[t];if(void 0==e){var i=this;e=new Image,this.images[t]=e,e.onload=function(){i.callback&&i.callback(this)},e.src=t}return e},S.prototype.setData=function(t){if(t&&t.dot&&(t.nodes||t.edges))throw new SyntaxError('Data must contain either parameter "dot" or parameter pair "nodes" and "edges", but not both.');if(this.setOptions(t&&t.options),t&&t.dot){if(t&&t.dot){var e=k.util.DOTToGraph(t.dot);return this.setData(e),void 0}}else this._setNodes(t&&t.nodes),this._setEdges(t&&t.edges);this.stabilize&&this._doStabilize(),this.start()},S.prototype.setOptions=function(t){if(t){if(void 0!=t.width&&(this.width=t.width),void 0!=t.height&&(this.height=t.height),void 0!=t.stabilize&&(this.stabilize=t.stabilize),void 0!=t.selectable&&(this.selectable=t.selectable),t.edges){for(var e in t.edges)t.edges.hasOwnProperty(e)&&(this.constants.edges[e]=t.edges[e]);void 0!=t.edges.length&&t.nodes&&void 0==t.nodes.distance&&(this.constants.edges.length=t.edges.length,this.constants.nodes.distance=1.25*t.edges.length),t.edges.fontColor||(this.constants.edges.fontColor=t.edges.color),t.edges.dash&&(void 0!=t.edges.dash.length&&(this.constants.edges.dash.length=t.edges.dash.length),void 0!=t.edges.dash.gap&&(this.constants.edges.dash.gap=t.edges.dash.gap),void 0!=t.edges.dash.altLength&&(this.constants.edges.dash.altLength=t.edges.dash.altLength))}if(t.nodes){for(e in t.nodes)t.nodes.hasOwnProperty(e)&&(this.constants.nodes[e]=t.nodes[e]);t.nodes.color&&(this.constants.nodes.color=E.parseColor(t.nodes.color))}if(t.groups)for(var i in t.groups)if(t.groups.hasOwnProperty(i)){var n=t.groups[i];this.groups.add(i,n)}}this.setSize(this.width,this.height),this._setTranslation(this.frame.clientWidth/2,this.frame.clientHeight/2),this._setScale(1)},S.prototype._trigger=function(t,e){L.trigger(this,t,e)},S.prototype._create=function(){for(;this.containerElement.hasChildNodes();)this.containerElement.removeChild(this.containerElement.firstChild);if(this.frame=document.createElement("div"),this.frame.className="graph-frame",this.frame.style.position="relative",this.frame.style.overflow="hidden",this.frame.canvas=document.createElement("canvas"),this.frame.canvas.style.position="relative",this.frame.appendChild(this.frame.canvas),!this.frame.canvas.getContext){var t=document.createElement("DIV");t.style.color="red",t.style.fontWeight="bold",t.style.padding="10px",t.innerHTML="Error: your browser does not support HTML canvas",this.frame.canvas.appendChild(t)}var e=this;this.hammer=D(this.frame.canvas),this.hammer.on("tap",function(t){e._onTap(t)}),this.containerElement.appendChild(this.frame)},S.prototype._onDragStart=function(){},S.prototype._onDrag=function(){},S.prototype._onDragEnd=function(){},S.prototype._onTap=function(t){var e=t.gesture.center;this.ctrlKeyDown=t.ctrlKey,this.shiftKeyDown=t.shiftKey;var i={left:this._xToCanvas(e.pageX),top:this._yToCanvas(e.pageY),right:this._xToCanvas(e.pageX),bottom:this._yToCanvas(e.pageY)},n=this._getNodesOverlappingWith(i);if(this.startClickedObj=n.length>0?n[n.length-1]:void 0,console.log(this.startClickedObj,i,this.nodes),this.startClickedObj){var s=this.nodes[this.startClickedObj];this.startClickedObj.xFixed=s.xFixed,this.startClickedObj.yFixed=s.yFixed,s.xFixed=!0,s.yFixed=!0,this.ctrlKeyDown&&s.isSelected()?this._unselectNodes([this.startClickedObj]):this._selectNodes([this.startClickedObj],this.ctrlKeyDown),this.moving||this._redraw()}else this.shiftKeyDown},S.prototype._onZoom=function(){},S.prototype._onMouseDown=function(t){if(t=t||window.event,this.selectable&&(this.leftButtonDown&&this._onMouseUp(t),this.leftButtonDown=t.which?1==t.which:1==t.button,this.leftButtonDown||this.touchDown)){var e=this;this.onmousemove||(this.onmousemove=function(t){e._onMouseMove(t)},k.util.addEventListener(document,"mousemove",e.onmousemove)),this.onmouseup||(this.onmouseup=function(t){e._onMouseUp(t)},k.util.addEventListener(document,"mouseup",e.onmouseup)),k.util.preventDefault(t),this.startMouseX=C.getPageX(t),this.startMouseY=C.getPageY(t),this.startFrameLeft=k.util.getAbsoluteLeft(this.frame.canvas),this.startFrameTop=k.util.getAbsoluteTop(this.frame.canvas),this.startTranslation=this._getTranslation(),this.ctrlKeyDown=t.ctrlKey,this.shiftKeyDown=t.shiftKey;var i={left:this._xToCanvas(this.startMouseX-this.startFrameLeft),top:this._yToCanvas(this.startMouseY-this.startFrameTop),right:this._xToCanvas(this.startMouseX-this.startFrameLeft),bottom:this._yToCanvas(this.startMouseY-this.startFrameTop)},n=this._getNodesOverlappingWith(i);if(this.startClickedObj=n.length>0?n[n.length-1]:void 0,this.startClickedObj){var s=this.nodes[this.startClickedObj];this.startClickedObj.xFixed=s.xFixed,this.startClickedObj.yFixed=s.yFixed,s.xFixed=!0,s.yFixed=!0,this.ctrlKeyDown&&s.isSelected()?this._unselectNodes([this.startClickedObj]):this._selectNodes([this.startClickedObj],this.ctrlKeyDown),this.moving||this._redraw()}else this.shiftKeyDown||(this.moved=!1)}},S.prototype._onMouseMove=function(t){if(t=t||window.event,this.selectable){var e=C.getPageX(t),i=C.getPageY(t);if(this.mouseX=e,this.mouseY=i,this.startClickedObj){var n=this.nodes[this.startClickedObj];this.startClickedObj.xFixed||(n.x=this._xToCanvas(e-this.startFrameLeft)),this.startClickedObj.yFixed||(n.y=this._yToCanvas(i-this.startFrameTop)),this.moving||(this.moving=!0,this.start())}else if(this.shiftKeyDown){void 0==this.frame.selRect&&(this.frame.selRect=document.createElement("DIV"),this.frame.appendChild(this.frame.selRect),this.frame.selRect.style.position="absolute",this.frame.selRect.style.border="1px dashed red");var s=Math.min(this.startMouseX,e)-this.startFrameLeft,o=Math.min(this.startMouseY,i)-this.startFrameTop,r=Math.max(this.startMouseX,e)-this.startFrameLeft,a=Math.max(this.startMouseY,i)-this.startFrameTop;this.frame.selRect.style.left=s+"px",this.frame.selRect.style.top=o+"px",this.frame.selRect.style.width=r-s+"px",this.frame.selRect.style.height=a-o+"px"}else{var h=e-this.startMouseX,d=i-this.startMouseY;this._setTranslation(this.startTranslation.x+h,this.startTranslation.y+d),this._redraw(),this.moved=!0}k.util.preventDefault(t)}},S.prototype._onMouseUp=function(t){if(t=t||window.event,this.selectable){this.onmousemove&&(k.util.removeEventListener(document,"mousemove",this.onmousemove),this.onmousemove=void 0),this.onmouseup&&(k.util.removeEventListener(document,"mouseup",this.onmouseup),this.onmouseup=void 0),k.util.preventDefault(t);var e=C.getPageX(t)||this.mouseX||0,i=C.getPageY(t)||this.mouseY||0,n=t?t.ctrlKey:window.event.ctrlKey;if(this.startClickedObj){var s=this.nodes[this.startClickedObj];s.xFixed=this.startClickedObj.xFixed,s.yFixed=this.startClickedObj.yFixed}else if(this.shiftKeyDown){var o={left:this._xToCanvas(Math.min(this.startMouseX,e)-this.startFrameLeft),top:this._yToCanvas(Math.min(this.startMouseY,i)-this.startFrameTop),right:this._xToCanvas(Math.max(this.startMouseX,e)-this.startFrameLeft),bottom:this._yToCanvas(Math.max(this.startMouseY,i)-this.startFrameTop)},r=this._getNodesOverlappingWith(o);this._selectNodes(r,n),this.redraw(),this.frame.selRect&&(this.frame.removeChild(this.frame.selRect),this.frame.selRect=void 0)}else this.ctrlKeyDown||this.moved||(this._unselectNodes(),this._redraw());this.leftButtonDown=!1,this.ctrlKeyDown=!1}},S.prototype._onMouseWheel=function(t){t=t||window.event;var e=C.getPageX(t),i=C.getPageY(t),n=0;if(t.wheelDelta?n=t.wheelDelta/120:t.detail&&(n=-t.detail/3),n){var s=n/10;0>n&&(s/=1-s);var o=this._getScale(),r=o*(1+s);.01>r&&(r=.01),r>10&&(r=10);var a=k.util.getAbsoluteLeft(this.frame.canvas),h=k.util.getAbsoluteTop(this.frame.canvas),d=e-a,l=i-h,u=this._getTranslation(),c=r/o,p=(1-c)*d+u.x*c,f=(1-c)*l+u.y*c;this._setScale(r),this._setTranslation(p,f),this._redraw()}k.util.preventDefault(t)},S.prototype._onMouseMoveTitle=function(t){t=t||window.event;var e=C.getPageX(t),i=C.getPageY(t);this.startFrameLeft=this.startFrameLeft||k.util.getAbsoluteLeft(this.frame.canvas),this.startFrameTop=this.startFrameTop||k.util.getAbsoluteTop(this.frame.canvas);var n=e-this.startFrameLeft,s=i-this.startFrameTop;this.popupNode&&this._checkHidePopup(n,s);var o=this,r=function(){o._checkShowPopup(n,s)};this.popupTimer&&clearInterval(this.popupTimer),this.leftButtonDown||(this.popupTimer=setTimeout(r,300))},S.prototype._checkShowPopup=function(t,e){var i,n={left:this._xToCanvas(t),top:this._yToCanvas(e),right:this._xToCanvas(t),bottom:this._yToCanvas(e)},s=this.popupNode;if(void 0==this.popupNode){var o=this.nodes;for(i in o)if(o.hasOwnProperty(i)){var r=o[i];if(void 0!=r.getTitle()&&r.isOverlappingWith(n)){this.popupNode=r;break}}}if(void 0==this.popupNode){var a=this.edges;for(i in a)if(a.hasOwnProperty(i)){var h=a[i];if(h.connected&&void 0!=h.getTitle()&&h.isOverlappingWith(n)){this.popupNode=h;break}}}if(this.popupNode){if(this.popupNode!=s){var d=this;d.popup||(d.popup=new x(d.frame)),d.popup.setPosition(t-3,e-3),d.popup.setText(d.popupNode.getTitle()),d.popup.show()}}else this.popup&&this.popup.hide()},S.prototype._checkHidePopup=function(t,e){var i={left:t,top:e,right:t,bottom:e};this.popupNode&&this.popupNode.isOverlappingWith(i)||(this.popupNode=void 0,this.popup&&this.popup.hide())},S.prototype._onTouchStart=function(t){if(k.util.preventDefault(t),!this.touchDown){this.touchDown=!0;var e=this;this.ontouchmove||(this.ontouchmove=function(t){e._onTouchMove(t)},k.util.addEventListener(document,"touchmove",this.ontouchmove)),this.ontouchend||(this.ontouchend=function(t){e._onTouchEnd(t)},k.util.addEventListener(document,"touchend",this.ontouchend)),this._onMouseDown(t)}},S.prototype._onTouchMove=function(t){k.util.preventDefault(t),this._onMouseMove(t)},S.prototype._onTouchEnd=function(t){k.util.preventDefault(t),this.touchDown=!1,this.ontouchmove&&(k.util.removeEventListener(document,"touchmove",this.ontouchmove),this.ontouchmove=void 0),this.ontouchend&&(k.util.removeEventListener(document,"touchend",this.ontouchend),this.ontouchend=void 0),this._onMouseUp(t)},S.prototype._unselectNodes=function(t,e){var i,n,s,o=!1;if(t)for(i=0,n=t.length;n>i;i++){s=t[i],this.nodes[s].unselect();for(var r=0;this.selection.length>r;)this.selection[r]==s?(this.selection.splice(r,1),o=!0):r++}else if(this.selection&&this.selection.length){for(i=0,n=this.selection.length;n>i;i++)s=this.selection[i],this.nodes[s].unselect(),o=!0;this.selection=[]}return!o||1!=e&&void 0!=e||this._trigger("select"),o},S.prototype._selectNodes=function(t,e){var i,n,s=!1,o=!0;if(t.length!=this.selection.length)o=!1;else for(i=0,n=Math.min(t.length,this.selection.length);n>i;i++)if(t[i]!=this.selection[i]){o=!1;break}if(o)return s;if(void 0==e||0==e){var r=!1;s=this._unselectNodes(void 0,r)}for(i=0,n=t.length;n>i;i++){var a=t[i],h=-1!=this.selection.indexOf(a);h||(this.nodes[a].select(),this.selection.push(a),s=!0)}return s&&this._trigger("select"),s},S.prototype._getNodesOverlappingWith=function(t){var e=this.nodes,i=[];for(var n in e)e.hasOwnProperty(n)&&e[n].isOverlappingWith(t)&&i.push(n);return i},S.prototype.getSelection=function(){return this.selection.concat([])},S.prototype.setSelection=function(t){var e,i,n;if(void 0==t.length)throw"Selection must be an array with ids";for(e=0,i=this.selection.length;i>e;e++)n=this.selection[e],this.nodes[n].unselect();for(this.selection=[],e=0,i=t.length;i>e;e++){n=t[e];var s=this.nodes[n];if(!s)throw new RangeError('Node with id "'+n+'" not found');s.select(),this.selection.push(n)}this.redraw()},S.prototype._updateSelection=function(){for(var t=0;this.selection.length>t;){var e=this.selection[t];this.nodes[e]?t++:this.selection.splice(t,1)}},S.prototype._getConnectionCount=function(t){function e(t){for(var e=[],i=0,n=t.length;n>i;i++)for(var s=t[i],o=s.edges,r=0,a=o.length;a>r;r++){var h=o[r],d=null;h.from==s?d=h.to:h.to==s&&(d=h.from);var l,u;if(d)for(l=0,u=t.length;u>l;l++)if(t[l]==d){d=null;break}if(d)for(l=0,u=e.length;u>l;l++)if(e[l]==d){d=null;break}d&&e.push(d)}return e}void 0==t&&(t=1);var i=[],n=this.nodes;for(var s in n)if(n.hasOwnProperty(s)){for(var o=[n[s]],r=0;t>r;r++)o=o.concat(e(o));i.push(o)}for(var a=[],h=0,d=i.length;d>h;h++)a.push(i[h].length);return a},S.prototype.setSize=function(t,e){this.frame.style.width=t,this.frame.style.height=e,this.frame.canvas.style.width="100%",this.frame.canvas.style.height="100%",this.frame.canvas.width=this.frame.canvas.clientWidth,this.frame.canvas.height=this.frame.canvas.clientHeight},S.prototype._setNodes=function(t){var e=this.nodesData;if(t instanceof o||t instanceof r)this.nodesData=t;else if(t instanceof Array)this.nodesData=new o,this.nodesData.add(t);else{if(t)throw new TypeError("Array or DataSet expected");this.nodesData=new o}if(e&&C.forEach(this.nodesListeners,function(t,i){e.unsubscribe(i,t)}),this.nodes={},this.nodesData){var i=this;C.forEach(this.nodesListeners,function(t,e){i.nodesData.subscribe(e,t)});var n=this.nodesData.getIds();this._addNodes(n)}this._updateSelection()},S.prototype._addNodes=function(t){for(var e,i=0,n=t.length;n>i;i++){e=t[i];var s=this.nodesData.get(e),o=new E(s,this.images,this.groups,this.constants);if(this.nodes[e]=o,!o.isFixed()){var r=2*this.constants.edges.length,a=t.length,h=2*Math.PI*(i/a);o.x=r*Math.cos(h),o.y=r*Math.sin(h),this.moving=!0}}this._reconnectEdges(),this._updateValueRange(this.nodes)},S.prototype._updateNodes=function(t){for(var e=this.nodes,i=this.nodesData,n=0,s=t.length;s>n;n++){var o=t[n],r=e[o],a=i.get(o);r?r.setProperties(a,this.constants):(r=new E(properties,this.images,this.groups,this.constants),e[o]=r,r.isFixed()||(this.moving=!0))}this._reconnectEdges(),this._updateValueRange(e)},S.prototype._removeNodes=function(t){for(var e=this.nodes,i=0,n=t.length;n>i;i++){var s=t[i];delete e[s]}this._reconnectEdges(),this._updateSelection(),this._updateValueRange(e)},S.prototype._setEdges=function(t){var e=this.edgesData;if(t instanceof o||t instanceof r)this.edgesData=t;else if(t instanceof Array)this.edgesData=new o,this.edgesData.add(t);else{if(t)throw new TypeError("Array or DataSet expected");this.edgesData=new o}if(e&&C.forEach(this.edgesListeners,function(t,i){e.unsubscribe(i,t)}),this.edges={},this.edgesData){var i=this;C.forEach(this.edgesListeners,function(t,e){i.edgesData.subscribe(e,t)});var n=this.edgesData.getIds();this._addEdges(n)}this._reconnectEdges()},S.prototype._addEdges=function(t){for(var e=this.edges,i=this.edgesData,n=0,s=t.length;s>n;n++){var o=t[n],r=e[o];r&&r.disconnect();var a=i.get(o);e[o]=new T(a,this,this.constants)}this.moving=!0,this._updateValueRange(e)},S.prototype._updateEdges=function(t){for(var e=this.edges,i=this.edgesData,n=0,s=t.length;s>n;n++){var o=t[n],r=i.get(o),a=e[o];a?(a.disconnect(),a.setProperties(r,this.constants),a.connect()):(a=new T(r,this,this.constants),this.edges[o]=a)}this.moving=!0,this._updateValueRange(e)},S.prototype._removeEdges=function(t){for(var e=this.edges,i=0,n=t.length;n>i;i++){var s=t[i],o=e[s];o&&(o.disconnect(),delete e[s])}this.moving=!0,this._updateValueRange(e)},S.prototype._reconnectEdges=function(){var t,e=this.nodes,i=this.edges;for(t in e)e.hasOwnProperty(t)&&(e[t].edges=[]);for(t in i)if(i.hasOwnProperty(t)){var n=i[t];n.from=null,n.to=null,n.connect()}},S.prototype._updateValueRange=function(t){var e,i=void 0,n=void 0;for(e in t)if(t.hasOwnProperty(e)){var s=t[e].getValue();void 0!==s&&(i=void 0===i?s:Math.min(s,i),n=void 0===n?s:Math.max(s,n))}if(void 0!==i&&void 0!==n)for(e in t)t.hasOwnProperty(e)&&t[e].setValueRange(i,n)},S.prototype.redraw=function(){this.setSize(this.width,this.height),this._redraw()},S.prototype._redraw=function(){var t=this.frame.canvas.getContext("2d"),e=this.frame.canvas.width,i=this.frame.canvas.height;t.clearRect(0,0,e,i),t.save(),t.translate(this.translation.x,this.translation.y),t.scale(this.scale,this.scale),this._drawEdges(t),this._drawNodes(t),t.restore()},S.prototype._setTranslation=function(t,e){void 0===this.translation&&(this.translation={x:0,y:0}),void 0!==t&&(this.translation.x=t),void 0!==e&&(this.translation.y=e)},S.prototype._getTranslation=function(){return{x:this.translation.x,y:this.translation.y}},S.prototype._setScale=function(t){this.scale=t},S.prototype._getScale=function(){return this.scale},S.prototype._xToCanvas=function(t){return(t-this.translation.x)/this.scale},S.prototype._canvasToX=function(t){return t*this.scale+this.translation.x},S.prototype._yToCanvas=function(t){return(t-this.translation.y)/this.scale},S.prototype._canvasToY=function(t){return t*this.scale+this.translation.y},S.prototype._drawNodes=function(t){var e=this.nodes,i=[];for(var n in e)e.hasOwnProperty(n)&&(e[n].isSelected()?i.push(n):e[n].draw(t));for(var s=0,o=i.length;o>s;s++)e[i[s]].draw(t)},S.prototype._drawEdges=function(t){var e=this.edges;for(var i in e)if(e.hasOwnProperty(i)){var n=e[i];n.connected&&e[i].draw(t)}},S.prototype._doStabilize=function(){new Date;for(var t=0,e=this.constants.minVelocity,i=!1;!i&&this.constants.maxIterations>t;)this._calculateForces(),this._discreteStepNodes(),i=!this._isMoving(e),t++;new Date},S.prototype._calculateForces=function(){var t,e,i,n,s,o,r,a,h,d,l,u=this.nodes,c=this.edges,p=.01,f=this.frame.canvas.clientWidth/2,m=this.frame.canvas.clientHeight/2;for(t in u)if(u.hasOwnProperty(t)){var g=u[t];e=f-g.x,i=m-g.y,n=Math.atan2(i,e),o=Math.cos(n)*p,r=Math.sin(n)*p,g._setForce(o,r)}var v=this.constants.nodes.distance,y=10;for(var b in u)if(u.hasOwnProperty(b)){var w=u[b];for(var _ in u)if(u.hasOwnProperty(_)){var E=u[_];e=E.x-w.x,i=E.y-w.y,s=Math.sqrt(e*e+i*i),n=Math.atan2(i,e),a=1/(1+Math.exp((s/v-1)*y)),o=Math.cos(n)*a,r=Math.sin(n)*a,w._addForce(-o,-r),E._addForce(o,r)}}for(t in c)if(c.hasOwnProperty(t)){var T=c[t];T.connected&&(e=T.to.x-T.from.x,i=T.to.y-T.from.y,l=T.length,d=Math.sqrt(e*e+i*i),n=Math.atan2(i,e),h=T.stiffness*(l-d),o=Math.cos(n)*h,r=Math.sin(n)*h,T.from._addForce(-o,-r),T.to._addForce(o,r))}},S.prototype._isMoving=function(t){var e=this.nodes;for(var i in e)if(e.hasOwnProperty(i)&&e[i].isMoving(t))return!0;return!1},S.prototype._discreteStepNodes=function(){var t=this.refreshRate/1e3,e=this.nodes;for(var i in e)e.hasOwnProperty(i)&&e[i].discreteStep(t)},S.prototype.start=function(){if(this.moving){this._calculateForces(),this._discreteStepNodes();var t=this.constants.minVelocity;this.moving=this._isMoving(t)}if(this.moving){if(!this.timer){var e=this;this.timer=window.setTimeout(function(){e.timer=void 0,e.start(),e._redraw()},this.refreshRate)}}else this._redraw()},S.prototype.stop=function(){this.timer&&(window.clearInterval(this.timer),this.timer=void 0)};var k={util:C,events:L,Controller:d,DataSet:o,DataView:r,Range:h,Stack:a,TimeStep:TimeStep,EventBus:s,components:{items:{Item:m,ItemBox:g,ItemPoint:v,ItemRange:y},Component:l,Panel:u,RootPanel:c,ItemSet:f,TimeAxis:p},graph:{Node:E,Edge:T,Popup:x,Groups:Groups,Images:Images},Timeline:_,Graph:S};n!==void 0&&(n=k),i!==void 0&&i.exports!==void 0&&(i.exports=k),"function"==typeof t&&t(function(){return k}),"undefined"!=typeof window&&(window.vis=k),C.loadCss("/* vis.js stylesheet */\n.vis.timeline {\n}\n\n\n.vis.timeline.rootpanel {\n position: relative;\n overflow: hidden;\n\n border: 1px solid #bfbfbf;\n -moz-box-sizing: border-box;\n box-sizing: border-box;\n}\n\n.vis.timeline .panel {\n position: absolute;\n overflow: hidden;\n}\n\n\n.vis.timeline .groupset {\n position: absolute;\n padding: 0;\n margin: 0;\n}\n\n.vis.timeline .labels {\n position: absolute;\n top: 0;\n left: 0;\n width: 100%;\n height: 100%;\n\n padding: 0;\n margin: 0;\n\n border-right: 1px solid #bfbfbf;\n box-sizing: border-box;\n -moz-box-sizing: border-box;\n}\n\n.vis.timeline .labels .label {\n position: absolute;\n left: 0;\n top: 0;\n width: 100%;\n border-bottom: 1px solid #bfbfbf;\n color: #4d4d4d;\n}\n\n.vis.timeline .labels .label .inner {\n display: inline-block;\n padding: 5px;\n}\n\n\n.vis.timeline .itemset {\n position: absolute;\n padding: 0;\n margin: 0;\n overflow: hidden;\n}\n\n.vis.timeline .background {\n}\n\n.vis.timeline .foreground {\n}\n\n.vis.timeline .itemset-axis {\n position: absolute;\n}\n\n.vis.timeline .groupset .itemset-axis {\n border-top: 1px solid #bfbfbf;\n}\n\n/* TODO: with orientation=='bottom', this will more or less overlap with timeline axis\n.vis.timeline .groupset .itemset-axis:last-child {\n border-top: none;\n}\n*/\n\n\n.vis.timeline .item {\n position: absolute;\n color: #1A1A1A;\n border-color: #97B0F8;\n background-color: #D5DDF6;\n display: inline-block;\n}\n\n.vis.timeline .item.selected {\n border-color: #FFC200;\n background-color: #FFF785;\n z-index: 999;\n}\n\n.vis.timeline .item.cluster {\n /* TODO: use another color or pattern? */\n background: #97B0F8 url('img/cluster_bg.png');\n color: white;\n}\n.vis.timeline .item.cluster.point {\n border-color: #D5DDF6;\n}\n\n.vis.timeline .item.box {\n text-align: center;\n border-style: solid;\n border-width: 1px;\n border-radius: 5px;\n -moz-border-radius: 5px; /* For Firefox 3.6 and older */\n}\n\n.vis.timeline .item.point {\n background: none;\n}\n\n.vis.timeline .dot {\n border: 5px solid #97B0F8;\n position: absolute;\n border-radius: 5px;\n -moz-border-radius: 5px; /* For Firefox 3.6 and older */\n}\n\n.vis.timeline .item.range {\n overflow: hidden;\n border-style: solid;\n border-width: 1px;\n border-radius: 2px;\n -moz-border-radius: 2px; /* For Firefox 3.6 and older */\n}\n\n.vis.timeline .item.range .drag-left {\n cursor: w-resize;\n z-index: 1000;\n}\n\n.vis.timeline .item.range .drag-right {\n cursor: e-resize;\n z-index: 1000;\n}\n\n.vis.timeline .item.range .content {\n position: relative;\n display: inline-block;\n}\n\n.vis.timeline .item.line {\n position: absolute;\n width: 0;\n border-left-width: 1px;\n border-left-style: solid;\n}\n\n.vis.timeline .item .content {\n margin: 5px;\n white-space: nowrap;\n overflow: hidden;\n}\n\n.vis.timeline .axis {\n position: relative;\n}\n\n.vis.timeline .axis .text {\n position: absolute;\n color: #4d4d4d;\n padding: 3px;\n white-space: nowrap;\n}\n\n.vis.timeline .axis .text.measure {\n position: absolute;\n padding-left: 0;\n padding-right: 0;\n margin-left: 0;\n margin-right: 0;\n visibility: hidden;\n}\n\n.vis.timeline .axis .grid.vertical {\n position: absolute;\n width: 0;\n border-right: 1px solid;\n}\n\n.vis.timeline .axis .grid.horizontal {\n position: absolute;\n left: 0;\n width: 100%;\n height: 0;\n border-bottom: 1px solid;\n}\n\n.vis.timeline .axis .grid.minor {\n border-color: #e5e5e5;\n}\n\n.vis.timeline .axis .grid.major {\n border-color: #bfbfbf;\n}\n\n")},{hammerjs:1,moment:2}]},{},[3])(3)}); \ No newline at end of file From 430361a4911418a2c1d97f8571f1f1bb5ee3fb78 Mon Sep 17 00:00:00 2001 From: josdejong Date: Tue, 17 Sep 2013 12:02:36 +0200 Subject: [PATCH 04/18] Implemented multi select nodes in graph using long press --- docs/graph.html | 6 ++-- src/graph/Graph.js | 76 ++++++++++++++++++++++++++++++++++++---------- vis.js | 76 ++++++++++++++++++++++++++++++++++++---------- vis.min.js | 12 ++++---- 4 files changed, 128 insertions(+), 42 deletions(-) diff --git a/docs/graph.html b/docs/graph.html index 0ccc5e4e..f196a732 100644 --- a/docs/graph.html +++ b/docs/graph.html @@ -831,10 +831,8 @@ var options = { selectable Boolean true - If true, nodes in the graph can be selected by clicking them, or - by keeping the Shift key down and dragging a selection area around them. - When the Ctrl key is down, the new selection is appended to the - previous selection. If not, the new selection replaces the previous selection. + If true, nodes in the graph can be selected by clicking them. + Long press can be used to select multiple nodes. diff --git a/src/graph/Graph.js b/src/graph/Graph.js index 6e3ec79a..751a8d80 100644 --- a/src/graph/Graph.js +++ b/src/graph/Graph.js @@ -363,14 +363,45 @@ Graph.prototype._onTouch = function (event) { * handle drag start event * @private */ -Graph.prototype._onDragStart = function (event) { +Graph.prototype._onDragStart = function () { var drag = this.drag; drag.translation = this._getTranslation(); // note: drag.pointer is set in _onTouch to get the initial touch location drag.nodeId = this._getNodeAt(drag.pointer); - drag.node = this.nodes[drag.nodeId]; + + // select the clicked node if not yet selected + var node = this.nodes[drag.nodeId]; + if (node && !node.isSelected()) { + this._selectNodes([drag.nodeId]); + } + + // creat an array with the selected nodes and their original location and status + var me = this; + drag.selection = []; + this.selection.forEach(function (id) { + var node = me.nodes[id]; + if (node) { + var s = { + id: id, + node: node, + + // store original x, y, xFixed and yFixed, make the node temporarily Fixed + x: node.x, + y: node.y, + xFixed: node.xFixed, + yFixed: node.yFixed + }; + + node.xFixed = true; + node.yFixed = true; + + drag.selection.push(s); + } + }); + + /* TODO: cleanup if (drag.node) { this._selectNodes([drag.nodeId]); @@ -380,6 +411,7 @@ Graph.prototype._onDragStart = function (event) { drag.node.xFixed = true; drag.node.yFixed = true; } + */ }; /** @@ -393,14 +425,26 @@ Graph.prototype._onDrag = function (event) { var pointer = this._getPointer(event.gesture.touches[0]); - var drag= this.drag, - node = drag.node; - if (node) { - if (!drag.xFixed) - node.x = this._xToCanvas(pointer.x); + var me = this, + drag = this.drag, + selection = drag.selection; + if (selection && selection.length) { + // calculate delta's and new location + var deltaX = pointer.x - drag.pointer.x, + deltaY = pointer.y - drag.pointer.y; + + // update position of all selected nodes + selection.forEach(function (s) { + var node = s.node; - if (!drag.yFixed) - node.y = this._yToCanvas(pointer.y); + if (!s.xFixed) { + node.x = me._xToCanvas(me._canvasToX(s.x) + deltaX); + } + + if (!s.yFixed) { + node.y = me._yToCanvas(me._canvasToX(s.y) + deltaY); + } + }); // start animation if not yet running if (!this.moving) { @@ -427,13 +471,13 @@ Graph.prototype._onDrag = function (event) { * @private */ Graph.prototype._onDragEnd = function () { - var drag = this.drag, - node = drag.node; - - if (node) { - // restore orginal xFixed and yFixed - node.xFixed = drag.xFixed; - node.yFixed = drag.yFixed; + var selection = this.drag.selection; + if (selection) { + selection.forEach(function (s) { + // restore original xFixed and yFixed + s.node.xFixed = s.xFixed; + s.node.yFixed = s.yFixed; + }); } }; diff --git a/vis.js b/vis.js index 06b9fd3c..48e0fa3a 100644 --- a/vis.js +++ b/vis.js @@ -13216,14 +13216,45 @@ Graph.prototype._onTouch = function (event) { * handle drag start event * @private */ -Graph.prototype._onDragStart = function (event) { +Graph.prototype._onDragStart = function () { var drag = this.drag; drag.translation = this._getTranslation(); // note: drag.pointer is set in _onTouch to get the initial touch location drag.nodeId = this._getNodeAt(drag.pointer); - drag.node = this.nodes[drag.nodeId]; + + // select the clicked node if not yet selected + var node = this.nodes[drag.nodeId]; + if (node && !node.isSelected()) { + this._selectNodes([drag.nodeId]); + } + + // creat an array with the selected nodes and their original location and status + var me = this; + drag.selection = []; + this.selection.forEach(function (id) { + var node = me.nodes[id]; + if (node) { + var s = { + id: id, + node: node, + + // store original x, y, xFixed and yFixed, make the node temporarily Fixed + x: node.x, + y: node.y, + xFixed: node.xFixed, + yFixed: node.yFixed + }; + + node.xFixed = true; + node.yFixed = true; + + drag.selection.push(s); + } + }); + + /* TODO: cleanup if (drag.node) { this._selectNodes([drag.nodeId]); @@ -13233,6 +13264,7 @@ Graph.prototype._onDragStart = function (event) { drag.node.xFixed = true; drag.node.yFixed = true; } + */ }; /** @@ -13246,14 +13278,26 @@ Graph.prototype._onDrag = function (event) { var pointer = this._getPointer(event.gesture.touches[0]); - var drag= this.drag, - node = drag.node; - if (node) { - if (!drag.xFixed) - node.x = this._xToCanvas(pointer.x); + var me = this, + drag = this.drag, + selection = drag.selection; + if (selection && selection.length) { + // calculate delta's and new location + var deltaX = pointer.x - drag.pointer.x, + deltaY = pointer.y - drag.pointer.y; - if (!drag.yFixed) - node.y = this._yToCanvas(pointer.y); + // update position of all selected nodes + selection.forEach(function (s) { + var node = s.node; + + if (!s.xFixed) { + node.x = me._xToCanvas(me._canvasToX(s.x) + deltaX); + } + + if (!s.yFixed) { + node.y = me._yToCanvas(me._canvasToX(s.y) + deltaY); + } + }); // start animation if not yet running if (!this.moving) { @@ -13280,13 +13324,13 @@ Graph.prototype._onDrag = function (event) { * @private */ Graph.prototype._onDragEnd = function () { - var drag = this.drag, - node = drag.node; - - if (node) { - // restore orginal xFixed and yFixed - node.xFixed = drag.xFixed; - node.yFixed = drag.yFixed; + var selection = this.drag.selection; + if (selection) { + selection.forEach(function (s) { + // restore original xFixed and yFixed + s.node.xFixed = s.xFixed; + s.node.yFixed = s.yFixed; + }); } }; diff --git a/vis.min.js b/vis.min.js index 490c0395..3f532e20 100644 --- a/vis.min.js +++ b/vis.min.js @@ -5,7 +5,7 @@ * A dynamic, browser-based visualization library. * * @version 0.2.0-SNAPSHOT - * @date 2013-09-16 + * @date 2013-09-17 * * @license * Copyright (C) 2011-2013 Almende B.V, http://almende.com @@ -22,8 +22,8 @@ * License for the specific language governing permissions and limitations under * the License. */ -(function(t){if("function"==typeof bootstrap)bootstrap("vis",t);else if("object"==typeof exports)module.exports=t();else if("function"==typeof define&&define.amd)define(t);else if("undefined"!=typeof ses){if(!ses.ok())return;ses.makeVis=t}else"undefined"!=typeof window?window.vis=t():global.vis=t()})(function(){var t;return function e(t,i,n){function s(r,a){if(!i[r]){if(!t[r]){var h="function"==typeof require&&require;if(!a&&h)return h(r,!0);if(o)return o(r,!0);throw Error("Cannot find module '"+r+"'")}var d=i[r]={exports:{}};t[r][0].call(d.exports,function(e){var i=t[r][1][e];return s(i?i:e)},d,d.exports,e,t,i,n)}return i[r].exports}for(var o="function"==typeof require&&require,r=0;n.length>r;r++)s(n[r]);return s}({1:[function(t,e){(function(t,i){"use strict";function n(){if(!s.READY){s.event.determineEventTypes();for(var t in s.gestures)s.gestures.hasOwnProperty(t)&&s.detection.register(s.gestures[t]);s.event.onTouch(s.DOCUMENT,s.EVENT_MOVE,s.detection.detect),s.event.onTouch(s.DOCUMENT,s.EVENT_END,s.detection.detect),s.READY=!0}}var s=function(t,e){return new s.Instance(t,e||{})};s.defaults={stop_browser_behavior:{userSelect:"none",touchAction:"none",touchCallout:"none",contentZooming:"none",userDrag:"none",tapHighlightColor:"rgba(0,0,0,0)"}},s.HAS_POINTEREVENTS=navigator.pointerEnabled||navigator.msPointerEnabled,s.HAS_TOUCHEVENTS="ontouchstart"in t,s.MOBILE_REGEX=/mobile|tablet|ip(ad|hone|od)|android/i,s.NO_MOUSEEVENTS=s.HAS_TOUCHEVENTS&&navigator.userAgent.match(s.MOBILE_REGEX),s.EVENT_TYPES={},s.DIRECTION_DOWN="down",s.DIRECTION_LEFT="left",s.DIRECTION_UP="up",s.DIRECTION_RIGHT="right",s.POINTER_MOUSE="mouse",s.POINTER_TOUCH="touch",s.POINTER_PEN="pen",s.EVENT_START="start",s.EVENT_MOVE="move",s.EVENT_END="end",s.DOCUMENT=document,s.plugins={},s.READY=!1,s.Instance=function(t,e){var i=this;return n(),this.element=t,this.enabled=!0,this.options=s.utils.extend(s.utils.extend({},s.defaults),e||{}),this.options.stop_browser_behavior&&s.utils.stopDefaultBrowserBehavior(this.element,this.options.stop_browser_behavior),s.event.onTouch(t,s.EVENT_START,function(t){i.enabled&&s.detection.startDetect(i,t)}),this},s.Instance.prototype={on:function(t,e){for(var i=t.split(" "),n=0;i.length>n;n++)this.element.addEventListener(i[n],e,!1);return this},off:function(t,e){for(var i=t.split(" "),n=0;i.length>n;n++)this.element.removeEventListener(i[n],e,!1);return this},trigger:function(t,e){var i=s.DOCUMENT.createEvent("Event");i.initEvent(t,!0,!0),i.gesture=e;var n=this.element;return s.utils.hasParent(e.target,n)&&(n=e.target),n.dispatchEvent(i),this},enable:function(t){return this.enabled=t,this}};var o=null,r=!1,a=!1;s.event={bindDom:function(t,e,i){for(var n=e.split(" "),s=0;n.length>s;s++)t.addEventListener(n[s],i,!1)},onTouch:function(t,e,i){var n=this;this.bindDom(t,s.EVENT_TYPES[e],function(h){var d=h.type.toLowerCase();if(!d.match(/mouse/)||!a){(d.match(/touch/)||d.match(/pointerdown/)||d.match(/mouse/)&&1===h.which)&&(r=!0),d.match(/touch|pointer/)&&(a=!0);var l=0;r&&(s.HAS_POINTEREVENTS&&e!=s.EVENT_END?l=s.PointerEvent.updatePointer(e,h):d.match(/touch/)?l=h.touches.length:a||(l=d.match(/up/)?0:1),l>0&&e==s.EVENT_END?e=s.EVENT_MOVE:l||(e=s.EVENT_END),l||null===o?o=h:h=o,i.call(s.detection,n.collectEventData(t,e,h)),s.HAS_POINTEREVENTS&&e==s.EVENT_END&&(l=s.PointerEvent.updatePointer(e,h))),l||(o=null,r=!1,a=!1,s.PointerEvent.reset())}})},determineEventTypes:function(){var t;t=s.HAS_POINTEREVENTS?s.PointerEvent.getEvents():s.NO_MOUSEEVENTS?["touchstart","touchmove","touchend touchcancel"]:["touchstart mousedown","touchmove mousemove","touchend touchcancel mouseup"],s.EVENT_TYPES[s.EVENT_START]=t[0],s.EVENT_TYPES[s.EVENT_MOVE]=t[1],s.EVENT_TYPES[s.EVENT_END]=t[2]},getTouchList:function(t){return s.HAS_POINTEREVENTS?s.PointerEvent.getTouchList():t.touches?t.touches:[{identifier:1,pageX:t.pageX,pageY:t.pageY,target:t.target}]},collectEventData:function(t,e,i){var n=this.getTouchList(i,e),o=s.POINTER_TOUCH;return(i.type.match(/mouse/)||s.PointerEvent.matchType(s.POINTER_MOUSE,i))&&(o=s.POINTER_MOUSE),{center:s.utils.getCenter(n),timeStamp:(new Date).getTime(),target:i.target,touches:n,eventType:e,pointerType:o,srcEvent:i,preventDefault:function(){this.srcEvent.preventManipulation&&this.srcEvent.preventManipulation(),this.srcEvent.preventDefault&&this.srcEvent.preventDefault()},stopPropagation:function(){this.srcEvent.stopPropagation()},stopDetect:function(){return s.detection.stopDetect()}}}},s.PointerEvent={pointers:{},getTouchList:function(){var t=this,e=[];return Object.keys(t.pointers).sort().forEach(function(i){e.push(t.pointers[i])}),e},updatePointer:function(t,e){return t==s.EVENT_END?this.pointers={}:(e.identifier=e.pointerId,this.pointers[e.pointerId]=e),Object.keys(this.pointers).length},matchType:function(t,e){if(!e.pointerType)return!1;var i={};return i[s.POINTER_MOUSE]=e.pointerType==e.MSPOINTER_TYPE_MOUSE||e.pointerType==s.POINTER_MOUSE,i[s.POINTER_TOUCH]=e.pointerType==e.MSPOINTER_TYPE_TOUCH||e.pointerType==s.POINTER_TOUCH,i[s.POINTER_PEN]=e.pointerType==e.MSPOINTER_TYPE_PEN||e.pointerType==s.POINTER_PEN,i[t]},getEvents:function(){return["pointerdown MSPointerDown","pointermove MSPointerMove","pointerup pointercancel MSPointerUp MSPointerCancel"]},reset:function(){this.pointers={}}},s.utils={extend:function(t,e,n){for(var s in e)t[s]!==i&&n||(t[s]=e[s]);return t},hasParent:function(t,e){for(;t;){if(t==e)return!0;t=t.parentNode}return!1},getCenter:function(t){for(var e=[],i=[],n=0,s=t.length;s>n;n++)e.push(t[n].pageX),i.push(t[n].pageY);return{pageX:(Math.min.apply(Math,e)+Math.max.apply(Math,e))/2,pageY:(Math.min.apply(Math,i)+Math.max.apply(Math,i))/2}},getVelocity:function(t,e,i){return{x:Math.abs(e/t)||0,y:Math.abs(i/t)||0}},getAngle:function(t,e){var i=e.pageY-t.pageY,n=e.pageX-t.pageX;return 180*Math.atan2(i,n)/Math.PI},getDirection:function(t,e){var i=Math.abs(t.pageX-e.pageX),n=Math.abs(t.pageY-e.pageY);return i>=n?t.pageX-e.pageX>0?s.DIRECTION_LEFT:s.DIRECTION_RIGHT:t.pageY-e.pageY>0?s.DIRECTION_UP:s.DIRECTION_DOWN},getDistance:function(t,e){var i=e.pageX-t.pageX,n=e.pageY-t.pageY;return Math.sqrt(i*i+n*n)},getScale:function(t,e){return t.length>=2&&e.length>=2?this.getDistance(e[0],e[1])/this.getDistance(t[0],t[1]):1},getRotation:function(t,e){return t.length>=2&&e.length>=2?this.getAngle(e[1],e[0])-this.getAngle(t[1],t[0]):0},isVertical:function(t){return t==s.DIRECTION_UP||t==s.DIRECTION_DOWN},stopDefaultBrowserBehavior:function(t,e){var i,n=["webkit","khtml","moz","ms","o",""];if(e&&t.style){for(var s=0;n.length>s;s++)for(var o in e)e.hasOwnProperty(o)&&(i=o,n[s]&&(i=n[s]+i.substring(0,1).toUpperCase()+i.substring(1)),t.style[i]=e[o]);"none"==e.userSelect&&(t.onselectstart=function(){return!1})}}},s.detection={gestures:[],current:null,previous:null,stopped:!1,startDetect:function(t,e){this.current||(this.stopped=!1,this.current={inst:t,startEvent:s.utils.extend({},e),lastEvent:!1,name:""},this.detect(e))},detect:function(t){if(this.current&&!this.stopped){t=this.extendEventData(t);for(var e=this.current.inst.options,i=0,n=this.gestures.length;n>i;i++){var o=this.gestures[i];if(!this.stopped&&e[o.name]!==!1&&o.handler.call(o,t,this.current.inst)===!1){this.stopDetect();break}}return this.current&&(this.current.lastEvent=t),t.eventType==s.EVENT_END&&!t.touches.length-1&&this.stopDetect(),t}},stopDetect:function(){this.previous=s.utils.extend({},this.current),this.current=null,this.stopped=!0},extendEventData:function(t){var e=this.current.startEvent;if(e&&(t.touches.length!=e.touches.length||t.touches===e.touches)){e.touches=[];for(var i=0,n=t.touches.length;n>i;i++)e.touches.push(s.utils.extend({},t.touches[i]))}var o=t.timeStamp-e.timeStamp,r=t.center.pageX-e.center.pageX,a=t.center.pageY-e.center.pageY,h=s.utils.getVelocity(o,r,a);return s.utils.extend(t,{deltaTime:o,deltaX:r,deltaY:a,velocityX:h.x,velocityY:h.y,distance:s.utils.getDistance(e.center,t.center),angle:s.utils.getAngle(e.center,t.center),direction:s.utils.getDirection(e.center,t.center),scale:s.utils.getScale(e.touches,t.touches),rotation:s.utils.getRotation(e.touches,t.touches),startEvent:e}),t},register:function(t){var e=t.defaults||{};return e[t.name]===i&&(e[t.name]=!0),s.utils.extend(s.defaults,e,!0),t.index=t.index||1e3,this.gestures.push(t),this.gestures.sort(function(t,e){return t.indexe.index?1:0}),this.gestures}},s.gestures=s.gestures||{},s.gestures.Hold={name:"hold",index:10,defaults:{hold_timeout:500,hold_threshold:1},timer:null,handler:function(t,e){switch(t.eventType){case s.EVENT_START:clearTimeout(this.timer),s.detection.current.name=this.name,this.timer=setTimeout(function(){"hold"==s.detection.current.name&&e.trigger("hold",t)},e.options.hold_timeout);break;case s.EVENT_MOVE:t.distance>e.options.hold_threshold&&clearTimeout(this.timer);break;case s.EVENT_END:clearTimeout(this.timer)}}},s.gestures.Tap={name:"tap",index:100,defaults:{tap_max_touchtime:250,tap_max_distance:10,tap_always:!0,doubletap_distance:20,doubletap_interval:300},handler:function(t,e){if(t.eventType==s.EVENT_END){var i=s.detection.previous,n=!1;if(t.deltaTime>e.options.tap_max_touchtime||t.distance>e.options.tap_max_distance)return;i&&"tap"==i.name&&t.timeStamp-i.lastEvent.timeStamp0&&t.touches.length>e.options.swipe_max_touches)return;(t.velocityX>e.options.swipe_velocity||t.velocityY>e.options.swipe_velocity)&&(e.trigger(this.name,t),e.trigger(this.name+t.direction,t))}}},s.gestures.Drag={name:"drag",index:50,defaults:{drag_min_distance:10,drag_max_touches:1,drag_block_horizontal:!1,drag_block_vertical:!1,drag_lock_to_axis:!1,drag_lock_min_distance:25},triggered:!1,handler:function(t,e){if(s.detection.current.name!=this.name&&this.triggered)return e.trigger(this.name+"end",t),this.triggered=!1,i;if(!(e.options.drag_max_touches>0&&t.touches.length>e.options.drag_max_touches))switch(t.eventType){case s.EVENT_START:this.triggered=!1;break;case s.EVENT_MOVE:if(t.distancet.deltaY?s.DIRECTION_UP:s.DIRECTION_DOWN:0>t.deltaX?s.DIRECTION_LEFT:s.DIRECTION_RIGHT),this.triggered||(e.trigger(this.name+"start",t),this.triggered=!0),e.trigger(this.name,t),e.trigger(this.name+t.direction,t),(e.options.drag_block_vertical&&s.utils.isVertical(t.direction)||e.options.drag_block_horizontal&&!s.utils.isVertical(t.direction))&&t.preventDefault();break;case s.EVENT_END:this.triggered&&e.trigger(this.name+"end",t),this.triggered=!1}}},s.gestures.Transform={name:"transform",index:45,defaults:{transform_min_scale:.01,transform_min_rotation:1,transform_always_block:!1},triggered:!1,handler:function(t,e){if(s.detection.current.name!=this.name&&this.triggered)return e.trigger(this.name+"end",t),this.triggered=!1,i;if(!(2>t.touches.length))switch(e.options.transform_always_block&&t.preventDefault(),t.eventType){case s.EVENT_START:this.triggered=!1;break;case s.EVENT_MOVE:var n=Math.abs(1-t.scale),o=Math.abs(t.rotation);if(e.options.transform_min_scale>n&&e.options.transform_min_rotation>o)return;s.detection.current.name=this.name,this.triggered||(e.trigger(this.name+"start",t),this.triggered=!0),e.trigger(this.name,t),o>e.options.transform_min_rotation&&e.trigger("rotate",t),n>e.options.transform_min_scale&&(e.trigger("pinch",t),e.trigger("pinch"+(1>t.scale?"in":"out"),t));break;case s.EVENT_END:this.triggered&&e.trigger(this.name+"end",t),this.triggered=!1}}},s.gestures.Touch={name:"touch",index:-1/0,defaults:{prevent_default:!1,prevent_mouseevents:!1},handler:function(t,e){return e.options.prevent_mouseevents&&t.pointerType==s.POINTER_MOUSE?(t.stopDetect(),i):(e.options.prevent_default&&t.preventDefault(),t.eventType==s.EVENT_START&&e.trigger(this.name,t),i)}},s.gestures.Release={name:"release",index:1/0,handler:function(t,e){t.eventType==s.EVENT_END&&e.trigger(this.name,t)}},"object"==typeof e&&"object"==typeof e.exports?e.exports=s:(t.Hammer=s,"function"==typeof t.define&&t.define.amd&&t.define("hammer",[],function(){return s}))})(this)},{}],2:[function(e,i){(function(n){function s(t,e){return function(i){return u(t.call(this,i),e)}}function o(t,e){return function(i){return this.lang().ordinal(t.call(this,i),e)}}function r(){}function a(t){d(this,t)}function h(t){var e=t.years||t.year||t.y||0,i=t.months||t.month||t.M||0,n=t.weeks||t.week||t.w||0,s=t.days||t.day||t.d||0,o=t.hours||t.hour||t.h||0,r=t.minutes||t.minute||t.m||0,a=t.seconds||t.second||t.s||0,h=t.milliseconds||t.millisecond||t.ms||0;this._input=t,this._milliseconds=+h+1e3*a+6e4*r+36e5*o,this._days=+s+7*n,this._months=+i+12*e,this._data={},this._bubble()}function d(t,e){for(var i in e)e.hasOwnProperty(i)&&(t[i]=e[i]);return t}function l(t){return 0>t?Math.ceil(t):Math.floor(t)}function u(t,e){for(var i=t+"";e>i.length;)i="0"+i;return i}function c(t,e,i,n){var s,o,r=e._milliseconds,a=e._days,h=e._months;r&&t._d.setTime(+t._d+r*i),(a||h)&&(s=t.minute(),o=t.hour()),a&&t.date(t.date()+a*i),h&&t.month(t.month()+h*i),r&&!n&&H.updateOffset(t),(a||h)&&(t.minute(s),t.hour(o))}function p(t){return"[object Array]"===Object.prototype.toString.call(t)}function f(t,e){var i,n=Math.min(t.length,e.length),s=Math.abs(t.length-e.length),o=0;for(i=0;n>i;i++)~~t[i]!==~~e[i]&&o++;return o+s}function m(t){return t?ue[t]||t.toLowerCase().replace(/(.)s$/,"$1"):t}function g(t,e){return e.abbr=t,V[t]||(V[t]=new r),V[t].set(e),V[t]}function v(t){delete V[t]}function y(t){if(!t)return H.fn._lang;if(!V[t]&&B)try{e("./lang/"+t)}catch(i){return H.fn._lang}return V[t]||H.fn._lang}function b(t){return t.match(/\[.*\]/)?t.replace(/^\[|\]$/g,""):t.replace(/\\/g,"")}function w(t){var e,i,n=t.match(G);for(e=0,i=n.length;i>e;e++)n[e]=me[n[e]]?me[n[e]]:b(n[e]);return function(s){var o="";for(e=0;i>e;e++)o+=n[e]instanceof Function?n[e].call(s,t):n[e];return o}}function _(t,e){return e=E(e,t.lang()),ce[e]||(ce[e]=w(e)),ce[e](t)}function E(t,e){function i(t){return e.longDateFormat(t)||t}for(var n=5;n--&&(K.lastIndex=0,K.test(t));)t=t.replace(K,i);return t}function T(t,e){switch(t){case"DDDD":return Q;case"YYYY":return $;case"YYYYY":return te;case"S":case"SS":case"SSS":case"DDD":return J;case"MMM":case"MMMM":case"dd":case"ddd":case"dddd":return ee;case"a":case"A":return y(e._l)._meridiemParse;case"X":return se;case"Z":case"ZZ":return ie;case"T":return ne;case"MM":case"DD":case"YY":case"HH":case"hh":case"mm":case"ss":case"M":case"D":case"d":case"H":case"h":case"m":case"s":return Z;default:return RegExp(t.replace("\\",""))}}function x(t){var e=(ie.exec(t)||[])[0],i=(e+"").match(he)||["-",0,0],n=+(60*i[1])+~~i[2];return"+"===i[0]?-n:n}function S(t,e,i){var n,s=i._a;switch(t){case"M":case"MM":null!=e&&(s[1]=~~e-1);break;case"MMM":case"MMMM":n=y(i._l).monthsParse(e),null!=n?s[1]=n:i._isValid=!1;break;case"D":case"DD":null!=e&&(s[2]=~~e);break;case"DDD":case"DDDD":null!=e&&(s[1]=0,s[2]=~~e);break;case"YY":s[0]=~~e+(~~e>68?1900:2e3);break;case"YYYY":case"YYYYY":s[0]=~~e;break;case"a":case"A":i._isPm=y(i._l).isPM(e);break;case"H":case"HH":case"h":case"hh":s[3]=~~e;break;case"m":case"mm":s[4]=~~e;break;case"s":case"ss":s[5]=~~e;break;case"S":case"SS":case"SSS":s[6]=~~(1e3*("0."+e));break;case"X":i._d=new Date(1e3*parseFloat(e));break;case"Z":case"ZZ":i._useUTC=!0,i._tzm=x(e)}null==e&&(i._isValid=!1)}function M(t){var e,i,n,s=[];if(!t._d){for(n=C(t),e=0;3>e&&null==t._a[e];++e)t._a[e]=s[e]=n[e];for(;7>e;e++)t._a[e]=s[e]=null==t._a[e]?2===e?1:0:t._a[e];s[3]+=~~((t._tzm||0)/60),s[4]+=~~((t._tzm||0)%60),i=new Date(0),t._useUTC?(i.setUTCFullYear(s[0],s[1],s[2]),i.setUTCHours(s[3],s[4],s[5],s[6])):(i.setFullYear(s[0],s[1],s[2]),i.setHours(s[3],s[4],s[5],s[6])),t._d=i}}function D(t){var e=t._i;t._d||(t._a=[e.years||e.year||e.y,e.months||e.month||e.M,e.days||e.day||e.d,e.hours||e.hour||e.h,e.minutes||e.minute||e.m,e.seconds||e.second||e.s,e.milliseconds||e.millisecond||e.ms],M(t))}function C(t){var e=new Date;return t._useUTC?[e.getUTCFullYear(),e.getUTCMonth(),e.getUTCDate()]:[e.getFullYear(),e.getMonth(),e.getDate()]}function O(t){var e,i,n,s=y(t._l),o=""+t._i;for(n=E(t._f,s).match(G),t._a=[],e=0;n.length>e;e++)i=(T(n[e],t).exec(o)||[])[0],i&&(o=o.slice(o.indexOf(i)+i.length)),me[n[e]]&&S(n[e],i,t);o&&(t._il=o),t._isPm&&12>t._a[3]&&(t._a[3]+=12),t._isPm===!1&&12===t._a[3]&&(t._a[3]=0),M(t)}function N(t){var e,i,n,s,o,r=99;for(s=0;t._f.length>s;s++)e=d({},t),e._f=t._f[s],O(e),i=new a(e),o=f(e._a,i.toArray()),i._il&&(o+=i._il.length),r>o&&(r=o,n=i);d(t,n)}function L(t){var e,i=t._i,n=oe.exec(i);if(n){for(t._f="YYYY-MM-DD"+(n[2]||" "),e=0;4>e;e++)if(ae[e][1].exec(i)){t._f+=ae[e][0];break}ie.exec(i)&&(t._f+=" Z"),O(t)}else t._d=new Date(i)}function k(t){var e=t._i,i=X.exec(e);e===n?t._d=new Date:i?t._d=new Date(+i[1]):"string"==typeof e?L(t):p(e)?(t._a=e.slice(0),M(t)):e instanceof Date?t._d=new Date(+e):"object"==typeof e?D(t):t._d=new Date(e)}function I(t,e,i,n,s){return s.relativeTime(e||1,!!i,t,n)}function A(t,e,i){var n=W(Math.abs(t)/1e3),s=W(n/60),o=W(s/60),r=W(o/24),a=W(r/365),h=45>n&&["s",n]||1===s&&["m"]||45>s&&["mm",s]||1===o&&["h"]||22>o&&["hh",o]||1===r&&["d"]||25>=r&&["dd",r]||45>=r&&["M"]||345>r&&["MM",W(r/30)]||1===a&&["y"]||["yy",a];return h[2]=e,h[3]=t>0,h[4]=i,I.apply({},h)}function P(t,e,i){var n,s=i-e,o=i-t.day();return o>s&&(o-=7),s-7>o&&(o+=7),n=H(t).add("d",o),{week:Math.ceil(n.dayOfYear()/7),year:n.year()}}function F(t){var e=t._i,i=t._f;return null===e||""===e?null:("string"==typeof e&&(t._i=e=y().preparse(e)),H.isMoment(e)?(t=d({},e),t._d=new Date(+e._d)):i?p(i)?N(t):O(t):k(t),new a(t))}function Y(t,e){H.fn[t]=H.fn[t+"s"]=function(t){var i=this._isUTC?"UTC":"";return null!=t?(this._d["set"+i+e](t),H.updateOffset(this),this):this._d["get"+i+e]()}}function R(t){H.duration.fn[t]=function(){return this._data[t]}}function z(t,e){H.duration.fn["as"+t]=function(){return+this/e}}for(var H,j,U="2.2.1",W=Math.round,V={},B=i!==n&&i.exports,X=/^\/?Date\((\-?\d+)/i,q=/(\-)?(?:(\d*)\.)?(\d+)\:(\d+)\:(\d+)\.?(\d{3})?/,G=/(\[[^\[]*\])|(\\)?(Mo|MM?M?M?|Do|DDDo|DD?D?D?|ddd?d?|do?|w[o|w]?|W[o|W]?|YYYYY|YYYY|YY|gg(ggg?)?|GG(GGG?)?|e|E|a|A|hh?|HH?|mm?|ss?|SS?S?|X|zz?|ZZ?|.)/g,K=/(\[[^\[]*\])|(\\)?(LT|LL?L?L?|l{1,4})/g,Z=/\d\d?/,J=/\d{1,3}/,Q=/\d{3}/,$=/\d{1,4}/,te=/[+\-]?\d{1,6}/,ee=/[0-9]*['a-z\u00A0-\u05FF\u0700-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF]+|[\u0600-\u06FF\/]+(\s*?[\u0600-\u06FF]+){1,2}/i,ie=/Z|[\+\-]\d\d:?\d\d/i,ne=/T/i,se=/[\+\-]?\d+(\.\d{1,3})?/,oe=/^\s*\d{4}-\d\d-\d\d((T| )(\d\d(:\d\d(:\d\d(\.\d\d?\d?)?)?)?)?([\+\-]\d\d:?\d\d)?)?/,re="YYYY-MM-DDTHH:mm:ssZ",ae=[["HH:mm:ss.S",/(T| )\d\d:\d\d:\d\d\.\d{1,3}/],["HH:mm:ss",/(T| )\d\d:\d\d:\d\d/],["HH:mm",/(T| )\d\d:\d\d/],["HH",/(T| )\d\d/]],he=/([\+\-]|\d\d)/gi,de="Date|Hours|Minutes|Seconds|Milliseconds".split("|"),le={Milliseconds:1,Seconds:1e3,Minutes:6e4,Hours:36e5,Days:864e5,Months:2592e6,Years:31536e6},ue={ms:"millisecond",s:"second",m:"minute",h:"hour",d:"day",w:"week",W:"isoweek",M:"month",y:"year"},ce={},pe="DDD w W M D d".split(" "),fe="M D H h m s w W".split(" "),me={M:function(){return this.month()+1},MMM:function(t){return this.lang().monthsShort(this,t)},MMMM:function(t){return this.lang().months(this,t)},D:function(){return this.date()},DDD:function(){return this.dayOfYear()},d:function(){return this.day()},dd:function(t){return this.lang().weekdaysMin(this,t)},ddd:function(t){return this.lang().weekdaysShort(this,t)},dddd:function(t){return this.lang().weekdays(this,t)},w:function(){return this.week()},W:function(){return this.isoWeek()},YY:function(){return u(this.year()%100,2)},YYYY:function(){return u(this.year(),4)},YYYYY:function(){return u(this.year(),5)},gg:function(){return u(this.weekYear()%100,2)},gggg:function(){return this.weekYear()},ggggg:function(){return u(this.weekYear(),5)},GG:function(){return u(this.isoWeekYear()%100,2)},GGGG:function(){return this.isoWeekYear()},GGGGG:function(){return u(this.isoWeekYear(),5)},e:function(){return this.weekday()},E:function(){return this.isoWeekday()},a:function(){return this.lang().meridiem(this.hours(),this.minutes(),!0)},A:function(){return this.lang().meridiem(this.hours(),this.minutes(),!1)},H:function(){return this.hours()},h:function(){return this.hours()%12||12},m:function(){return this.minutes()},s:function(){return this.seconds()},S:function(){return~~(this.milliseconds()/100)},SS:function(){return u(~~(this.milliseconds()/10),2)},SSS:function(){return u(this.milliseconds(),3)},Z:function(){var t=-this.zone(),e="+";return 0>t&&(t=-t,e="-"),e+u(~~(t/60),2)+":"+u(~~t%60,2)},ZZ:function(){var t=-this.zone(),e="+";return 0>t&&(t=-t,e="-"),e+u(~~(10*t/6),4)},z:function(){return this.zoneAbbr()},zz:function(){return this.zoneName()},X:function(){return this.unix()}};pe.length;)j=pe.pop(),me[j+"o"]=o(me[j],j);for(;fe.length;)j=fe.pop(),me[j+j]=s(me[j],2);for(me.DDDD=s(me.DDD,3),d(r.prototype,{set:function(t){var e,i;for(i in t)e=t[i],"function"==typeof e?this[i]=e:this["_"+i]=e},_months:"January_February_March_April_May_June_July_August_September_October_November_December".split("_"),months:function(t){return this._months[t.month()]},_monthsShort:"Jan_Feb_Mar_Apr_May_Jun_Jul_Aug_Sep_Oct_Nov_Dec".split("_"),monthsShort:function(t){return this._monthsShort[t.month()]},monthsParse:function(t){var e,i,n;for(this._monthsParse||(this._monthsParse=[]),e=0;12>e;e++)if(this._monthsParse[e]||(i=H.utc([2e3,e]),n="^"+this.months(i,"")+"|^"+this.monthsShort(i,""),this._monthsParse[e]=RegExp(n.replace(".",""),"i")),this._monthsParse[e].test(t))return e},_weekdays:"Sunday_Monday_Tuesday_Wednesday_Thursday_Friday_Saturday".split("_"),weekdays:function(t){return this._weekdays[t.day()]},_weekdaysShort:"Sun_Mon_Tue_Wed_Thu_Fri_Sat".split("_"),weekdaysShort:function(t){return this._weekdaysShort[t.day()]},_weekdaysMin:"Su_Mo_Tu_We_Th_Fr_Sa".split("_"),weekdaysMin:function(t){return this._weekdaysMin[t.day()]},weekdaysParse:function(t){var e,i,n;for(this._weekdaysParse||(this._weekdaysParse=[]),e=0;7>e;e++)if(this._weekdaysParse[e]||(i=H([2e3,1]).day(e),n="^"+this.weekdays(i,"")+"|^"+this.weekdaysShort(i,"")+"|^"+this.weekdaysMin(i,""),this._weekdaysParse[e]=RegExp(n.replace(".",""),"i")),this._weekdaysParse[e].test(t))return e},_longDateFormat:{LT:"h:mm A",L:"MM/DD/YYYY",LL:"MMMM D YYYY",LLL:"MMMM D YYYY LT",LLLL:"dddd, MMMM D YYYY LT"},longDateFormat:function(t){var e=this._longDateFormat[t];return!e&&this._longDateFormat[t.toUpperCase()]&&(e=this._longDateFormat[t.toUpperCase()].replace(/MMMM|MM|DD|dddd/g,function(t){return t.slice(1)}),this._longDateFormat[t]=e),e},isPM:function(t){return"p"===(t+"").toLowerCase().charAt(0)},_meridiemParse:/[ap]\.?m?\.?/i,meridiem:function(t,e,i){return t>11?i?"pm":"PM":i?"am":"AM"},_calendar:{sameDay:"[Today at] LT",nextDay:"[Tomorrow at] LT",nextWeek:"dddd [at] LT",lastDay:"[Yesterday at] LT",lastWeek:"[Last] dddd [at] LT",sameElse:"L"},calendar:function(t,e){var i=this._calendar[t];return"function"==typeof i?i.apply(e):i},_relativeTime:{future:"in %s",past:"%s ago",s:"a few seconds",m:"a minute",mm:"%d minutes",h:"an hour",hh:"%d hours",d:"a day",dd:"%d days",M:"a month",MM:"%d months",y:"a year",yy:"%d years"},relativeTime:function(t,e,i,n){var s=this._relativeTime[i];return"function"==typeof s?s(t,e,i,n):s.replace(/%d/i,t)},pastFuture:function(t,e){var i=this._relativeTime[t>0?"future":"past"];return"function"==typeof i?i(e):i.replace(/%s/i,e)},ordinal:function(t){return this._ordinal.replace("%d",t)},_ordinal:"%d",preparse:function(t){return t},postformat:function(t){return t},week:function(t){return P(t,this._week.dow,this._week.doy).week},_week:{dow:0,doy:6}}),H=function(t,e,i){return F({_i:t,_f:e,_l:i,_isUTC:!1})},H.utc=function(t,e,i){return F({_useUTC:!0,_isUTC:!0,_l:i,_i:t,_f:e}).utc()},H.unix=function(t){return H(1e3*t)},H.duration=function(t,e){var i,n,s=H.isDuration(t),o="number"==typeof t,r=s?t._input:o?{}:t,a=q.exec(t);return o?e?r[e]=t:r.milliseconds=t:a&&(i="-"===a[1]?-1:1,r={y:0,d:~~a[2]*i,h:~~a[3]*i,m:~~a[4]*i,s:~~a[5]*i,ms:~~a[6]*i}),n=new h(r),s&&t.hasOwnProperty("_lang")&&(n._lang=t._lang),n},H.version=U,H.defaultFormat=re,H.updateOffset=function(){},H.lang=function(t,e){return t?(t=t.toLowerCase(),t=t.replace("_","-"),e?g(t,e):null===e?(v(t),t="en"):V[t]||y(t),H.duration.fn._lang=H.fn._lang=y(t),n):H.fn._lang._abbr},H.langData=function(t){return t&&t._lang&&t._lang._abbr&&(t=t._lang._abbr),y(t)},H.isMoment=function(t){return t instanceof a},H.isDuration=function(t){return t instanceof h},d(H.fn=a.prototype,{clone:function(){return H(this)},valueOf:function(){return+this._d+6e4*(this._offset||0)},unix:function(){return Math.floor(+this/1e3)},toString:function(){return this.format("ddd MMM DD YYYY HH:mm:ss [GMT]ZZ")},toDate:function(){return this._offset?new Date(+this):this._d},toISOString:function(){return _(H(this).utc(),"YYYY-MM-DD[T]HH:mm:ss.SSS[Z]")},toArray:function(){var t=this;return[t.year(),t.month(),t.date(),t.hours(),t.minutes(),t.seconds(),t.milliseconds()]},isValid:function(){return null==this._isValid&&(this._isValid=this._a?!f(this._a,(this._isUTC?H.utc(this._a):H(this._a)).toArray()):!isNaN(this._d.getTime())),!!this._isValid},invalidAt:function(){var t,e=this._a,i=(this._isUTC?H.utc(this._a):H(this._a)).toArray();for(t=6;t>=0&&e[t]===i[t];--t);return t},utc:function(){return this.zone(0)},local:function(){return this.zone(0),this._isUTC=!1,this},format:function(t){var e=_(this,t||H.defaultFormat);return this.lang().postformat(e)},add:function(t,e){var i;return i="string"==typeof t?H.duration(+e,t):H.duration(t,e),c(this,i,1),this},subtract:function(t,e){var i;return i="string"==typeof t?H.duration(+e,t):H.duration(t,e),c(this,i,-1),this},diff:function(t,e,i){var n,s,o=this._isUTC?H(t).zone(this._offset||0):H(t).local(),r=6e4*(this.zone()-o.zone());return e=m(e),"year"===e||"month"===e?(n=432e5*(this.daysInMonth()+o.daysInMonth()),s=12*(this.year()-o.year())+(this.month()-o.month()),s+=(this-H(this).startOf("month")-(o-H(o).startOf("month")))/n,s-=6e4*(this.zone()-H(this).startOf("month").zone()-(o.zone()-H(o).startOf("month").zone()))/n,"year"===e&&(s/=12)):(n=this-o,s="second"===e?n/1e3:"minute"===e?n/6e4:"hour"===e?n/36e5:"day"===e?(n-r)/864e5:"week"===e?(n-r)/6048e5:n),i?s:l(s)},from:function(t,e){return H.duration(this.diff(t)).lang(this.lang()._abbr).humanize(!e)},fromNow:function(t){return this.from(H(),t)},calendar:function(){var t=this.diff(H().zone(this.zone()).startOf("day"),"days",!0),e=-6>t?"sameElse":-1>t?"lastWeek":0>t?"lastDay":1>t?"sameDay":2>t?"nextDay":7>t?"nextWeek":"sameElse";return this.format(this.lang().calendar(e,this))},isLeapYear:function(){var t=this.year();return 0===t%4&&0!==t%100||0===t%400},isDST:function(){return this.zone()+H(t).startOf(e)},isBefore:function(t,e){return e=e!==n?e:"millisecond",+this.clone().startOf(e)<+H(t).startOf(e)},isSame:function(t,e){return e=e!==n?e:"millisecond",+this.clone().startOf(e)===+H(t).startOf(e)},min:function(t){return t=H.apply(null,arguments),this>t?this:t},max:function(t){return t=H.apply(null,arguments),t>this?this:t},zone:function(t){var e=this._offset||0;return null==t?this._isUTC?e:this._d.getTimezoneOffset():("string"==typeof t&&(t=x(t)),16>Math.abs(t)&&(t=60*t),this._offset=t,this._isUTC=!0,e!==t&&c(this,H.duration(e-t,"m"),1,!0),this)},zoneAbbr:function(){return this._isUTC?"UTC":""},zoneName:function(){return this._isUTC?"Coordinated Universal Time":""},hasAlignedHourOffset:function(t){return t=t?H(t).zone():0,0===(this.zone()-t)%60},daysInMonth:function(){return H.utc([this.year(),this.month()+1,0]).date()},dayOfYear:function(t){var e=W((H(this).startOf("day")-H(this).startOf("year"))/864e5)+1;return null==t?e:this.add("d",t-e)},weekYear:function(t){var e=P(this,this.lang()._week.dow,this.lang()._week.doy).year;return null==t?e:this.add("y",t-e)},isoWeekYear:function(t){var e=P(this,1,4).year;return null==t?e:this.add("y",t-e)},week:function(t){var e=this.lang().week(this);return null==t?e:this.add("d",7*(t-e))},isoWeek:function(t){var e=P(this,1,4).week;return null==t?e:this.add("d",7*(t-e))},weekday:function(t){var e=(this._d.getDay()+7-this.lang()._week.dow)%7;return null==t?e:this.add("d",t-e)},isoWeekday:function(t){return null==t?this.day()||7:this.day(this.day()%7?t:t-7)},get:function(t){return t=m(t),this[t.toLowerCase()]()},set:function(t,e){t=m(t),this[t.toLowerCase()](e)},lang:function(t){return t===n?this._lang:(this._lang=y(t),this)}}),j=0;de.length>j;j++)Y(de[j].toLowerCase().replace(/s$/,""),de[j]);Y("year","FullYear"),H.fn.days=H.fn.day,H.fn.months=H.fn.month,H.fn.weeks=H.fn.week,H.fn.isoWeeks=H.fn.isoWeek,H.fn.toJSON=H.fn.toISOString,d(H.duration.fn=h.prototype,{_bubble:function(){var t,e,i,n,s=this._milliseconds,o=this._days,r=this._months,a=this._data;a.milliseconds=s%1e3,t=l(s/1e3),a.seconds=t%60,e=l(t/60),a.minutes=e%60,i=l(e/60),a.hours=i%24,o+=l(i/24),a.days=o%30,r+=l(o/30),a.months=r%12,n=l(r/12),a.years=n},weeks:function(){return l(this.days()/7)},valueOf:function(){return this._milliseconds+864e5*this._days+2592e6*(this._months%12)+31536e6*~~(this._months/12)},humanize:function(t){var e=+this,i=A(e,!t,this.lang());return t&&(i=this.lang().pastFuture(e,i)),this.lang().postformat(i)},add:function(t,e){var i=H.duration(t,e);return this._milliseconds+=i._milliseconds,this._days+=i._days,this._months+=i._months,this._bubble(),this},subtract:function(t,e){var i=H.duration(t,e);return this._milliseconds-=i._milliseconds,this._days-=i._days,this._months-=i._months,this._bubble(),this},get:function(t){return t=m(t),this[t.toLowerCase()+"s"]()},as:function(t){return t=m(t),this["as"+t.charAt(0).toUpperCase()+t.slice(1)+"s"]()},lang:H.fn.lang});for(j in le)le.hasOwnProperty(j)&&(z(j,le[j]),R(j.toLowerCase()));z("Weeks",6048e5),H.duration.fn.asMonths=function(){return(+this-31536e6*this.years())/2592e6+12*this.years()},H.lang("en",{ordinal:function(t){var e=t%10,i=1===~~(t%100/10)?"th":1===e?"st":2===e?"nd":3===e?"rd":"th";return t+i}}),B&&(i.exports=H),"undefined"==typeof ender&&(this.moment=H),"function"==typeof t&&t.amd&&t("moment",[],function(){return H})}).call(this)},{}],3:[function(e,i,n){function s(){this.subscriptions=[]}function o(t){if(this.id=C.randomUUID(),this.options=t||{},this.data={},this.fieldId=this.options.fieldId||"id",this.convert={},this.options.convert)for(var e in this.options.convert)if(this.options.convert.hasOwnProperty(e)){var i=this.options.convert[e];this.convert[e]="Date"==i||"ISODate"==i||"ASPDate"==i?"Date":i -}this.subscribers={},this.internalIds={}}function r(t,e){this.id=C.randomUUID(),this.data=null,this.ids={},this.options=e||{},this.fieldId="id",this.subscribers={};var i=this;this.listener=function(){i._onEvent.apply(i,arguments)},this.setData(t)}function a(t,e){this.parent=t,this.options=e||{},this.defaultOptions={order:function(t,e){if(t instanceof y){if(e instanceof y){var i=t.data.end-t.data.start,n=e.data.end-e.data.start;return i-n||t.data.start-e.data.start}return-1}return e instanceof y?1:t.data.start-e.data.start},margin:{item:10}},this.ordered=[]}function h(t){this.id=C.randomUUID(),this.start=0,this.end=0,this.options={min:null,max:null,zoomMin:null,zoomMax:null},this.listeners=[],this.setOptions(t)}function d(){this.id=C.randomUUID(),this.components={},this.repaintTimer=void 0,this.reflowTimer=void 0}function l(){this.id=null,this.parent=null,this.depends=null,this.controller=null,this.options=null,this.frame=null,this.top=0,this.left=0,this.width=0,this.height=0}function u(t,e,i){this.id=C.randomUUID(),this.parent=t,this.depends=e,this.options=i||{}}function c(t,e){this.id=C.randomUUID(),this.container=t,this.options=e||{},this.defaultOptions={autoResize:!0},this.listeners={}}function p(t,e,i){this.id=C.randomUUID(),this.parent=t,this.depends=e,this.dom={majorLines:[],majorTexts:[],minorLines:[],minorTexts:[],redundant:{majorLines:[],majorTexts:[],minorLines:[],minorTexts:[]}},this.props={range:{start:0,end:0,minimumStep:0},lineTop:0},this.options=i||{},this.defaultOptions={orientation:"bottom",showMinorLabels:!0,showMajorLabels:!0},this.conversion=null,this.range=null}function f(t,e,i){this.id=C.randomUUID(),this.parent=t,this.depends=e,this.options=i||{},this.defaultOptions={type:"box",align:"center",orientation:"bottom",margin:{axis:20,item:10},padding:5},this.dom={};var n=this;this.itemsData=null,this.range=null,this.listeners={add:function(t,e,i){i!=n.id&&n._onAdd(e.items)},update:function(t,e,i){i!=n.id&&n._onUpdate(e.items)},remove:function(t,e,i){i!=n.id&&n._onRemove(e.items)}},this.items={},this.queue={},this.stack=new a(this,Object.create(this.options)),this.conversion=null}function m(t,e,i,n){this.parent=t,this.data=e,this.dom=null,this.options=i||{},this.defaultOptions=n||{},this.selected=!1,this.visible=!1,this.top=0,this.left=0,this.width=0,this.height=0}function g(t,e,i,n){this.props={dot:{left:0,top:0,width:0,height:0},line:{top:0,left:0,width:0,height:0}},m.call(this,t,e,i,n)}function v(t,e,i,n){this.props={dot:{top:0,width:0,height:0},content:{height:0,marginLeft:0}},m.call(this,t,e,i,n)}function y(t,e,i,n){this.props={content:{left:0,width:0}},m.call(this,t,e,i,n)}function b(t,e,i){this.id=C.randomUUID(),this.parent=t,this.groupId=e,this.itemset=null,this.options=i||{},this.options.top=0,this.props={label:{width:0,height:0}},this.top=0,this.left=0,this.width=0,this.height=0}function w(t,e,i){this.id=C.randomUUID(),this.parent=t,this.depends=e,this.options=i||{},this.range=null,this.itemsData=null,this.groupsData=null,this.groups={},this.dom={},this.props={labels:{width:0}},this.queue={};var n=this;this.listeners={add:function(t,e){n._onAdd(e.items)},update:function(t,e){n._onUpdate(e.items)},remove:function(t,e){n._onRemove(e.items)}}}function _(t,e,i){var n=this;if(this.options=C.extend({orientation:"bottom",min:null,max:null,zoomMin:10,zoomMax:31536e10,showMinorLabels:!0,showMajorLabels:!0,autoResize:!1},i),this.controller=new d,!t)throw Error("No container element provided");var s=Object.create(this.options);s.height=function(){return n.options.height?n.options.height:n.timeaxis.height+n.content.height},this.rootPanel=new c(t,s),this.controller.add(this.rootPanel);var o=Object.create(this.options);o.left=function(){return n.labelPanel.width},o.width=function(){return n.rootPanel.width-n.labelPanel.width},o.top=null,o.height=null,this.itemPanel=new u(this.rootPanel,[],o),this.controller.add(this.itemPanel);var r=Object.create(this.options);r.top=null,r.left=null,r.height=null,r.width=function(){return n.content&&"function"==typeof n.content.getLabelsWidth?n.content.getLabelsWidth():0},this.labelPanel=new u(this.rootPanel,[],r),this.controller.add(this.labelPanel);var a=M().hours(0).minutes(0).seconds(0).milliseconds(0);this.range=new h({start:a.clone().add("days",-3).valueOf(),end:a.clone().add("days",4).valueOf()}),this.range.subscribe(this.rootPanel,"move","horizontal"),this.range.subscribe(this.rootPanel,"zoom","horizontal"),this.range.on("rangechange",function(){var t=!0;n.controller.requestReflow(t)}),this.range.on("rangechanged",function(){var t=!0;n.controller.requestReflow(t)});var l=Object.create(s);l.range=this.range,l.left=null,l.top=null,l.width="100%",l.height=null,this.timeaxis=new p(this.itemPanel,[],l),this.timeaxis.setRange(this.range),this.controller.add(this.timeaxis),this.setGroups(null),this.itemsData=null,this.groupsData=null,e&&this.setItems(e)}function E(t,e,i,n){this.selected=!1,this.edges=[],this.group=n.nodes.group,this.fontSize=n.nodes.fontSize,this.fontFace=n.nodes.fontFace,this.fontColor=n.nodes.fontColor,this.color=n.nodes.color,this.id=void 0,this.shape=n.nodes.shape,this.image=n.nodes.image,this.x=0,this.y=0,this.xFixed=!1,this.yFixed=!1,this.radius=n.nodes.radius,this.radiusFixed=!1,this.radiusMin=n.nodes.radiusMin,this.radiusMax=n.nodes.radiusMax,this.imagelist=e,this.grouplist=i,this.setProperties(t,n),this.mass=50,this.fx=0,this.fy=0,this.vx=0,this.vy=0,this.minForce=n.minForce,this.damping=.9}function T(t,e,i){if(!e)throw"No graph provided";this.graph=e,this.widthMin=i.edges.widthMin,this.widthMax=i.edges.widthMax,this.id=void 0,this.fromId=void 0,this.toId=void 0,this.style=i.edges.style,this.title=void 0,this.width=i.edges.width,this.value=void 0,this.length=i.edges.length,this.from=null,this.to=null,this.connected=!1,this.dash=C.extend({},i.edges.dash),this.stiffness=void 0,this.color=i.edges.color,this.widthFixed=!1,this.lengthFixed=!1,this.setProperties(t,i)}function x(t,e,i,n){this.container=t?t:document.body,this.x=0,this.y=0,this.padding=5,void 0!==e&&void 0!==i&&this.setPosition(e,i),void 0!==n&&this.setText(n),this.frame=document.createElement("div");var s=this.frame.style;s.position="absolute",s.visibility="hidden",s.border="1px solid #666",s.color="black",s.padding=this.padding+"px",s.backgroundColor="#FFFFC6",s.borderRadius="3px",s.MozBorderRadius="3px",s.WebkitBorderRadius="3px",s.boxShadow="3px 3px 10px rgba(128, 128, 128, 0.5)",s.whiteSpace="nowrap",this.container.appendChild(this.frame)}function S(t,e,i){this.containerElement=t,this.width="100%",this.height="100%",this.refreshRate=50,this.stabilize=!0,this.selectable=!0,this.constants={nodes:{radiusMin:5,radiusMax:20,radius:5,distance:100,shape:"ellipse",image:void 0,widthMin:16,widthMax:64,fontColor:"black",fontSize:14,fontFace:"arial",color:{border:"#2B7CE9",background:"#97C2FC",highlight:{border:"#2B7CE9",background:"#D2E5FF"}},borderColor:"#2B7CE9",backgroundColor:"#97C2FC",highlightColor:"#D2E5FF",group:void 0},edges:{widthMin:1,widthMax:15,width:1,style:"line",color:"#343434",fontColor:"#343434",fontSize:14,fontFace:"arial",length:100,dash:{length:10,gap:5,altLength:void 0}},minForce:.05,minVelocity:.02,maxIterations:1e3};var n=this;this.nodes={},this.edges={},this.nodesData=null,this.edgesData=null;var s=this;this.nodesListeners={add:function(t,e){s._addNodes(e.items),s.start()},update:function(t,e){s._updateNodes(e.items),s.start()},remove:function(t,e){s._removeNodes(e.items),s.start()}},this.edgesListeners={add:function(t,e){s._addEdges(e.items),s.start()},update:function(t,e){s._updateEdges(e.items),s.start()},remove:function(t,e){s._removeEdges(e.items),s.start()}},this.groups=new Groups,this.images=new Images,this.images.setOnloadCallback(function(){n._redraw()}),this.moving=!1,this.selection=[],this.timer=void 0,this._create(),this.setOptions(i),this.setData(e)}var M,D;"undefined"!=typeof window?(M=window.moment=window.moment?window.moment:e("moment"),D=window.hammerjs=window.hammerjs?window.hammerjs:e("hammerjs")):(M=e("moment"),D=e("hammerjs"));var C={};C.isNumber=function(t){return t instanceof Number||"number"==typeof t},C.isString=function(t){return t instanceof String||"string"==typeof t},C.isDate=function(t){if(t instanceof Date)return!0;if(C.isString(t)){var e=O.exec(t);if(e)return!0;if(!isNaN(Date.parse(t)))return!0}return!1},C.isDataTable=function(t){return"undefined"!=typeof google&&google.visualization&&google.visualization.DataTable&&t instanceof google.visualization.DataTable},C.randomUUID=function(){var t=function(){return Math.floor(65536*Math.random()).toString(16)};return t()+t()+"-"+t()+"-"+t()+"-"+t()+"-"+t()+t()+t()},C.extend=function(t){for(var e=1,i=arguments.length;i>e;e++){var n=arguments[e];for(var s in n)n.hasOwnProperty(s)&&void 0!==n[s]&&(t[s]=n[s])}return t},C.convert=function(t,e){var i;if(void 0===t)return void 0;if(null===t)return null;if(!e)return t;if("string"!=typeof e&&!(e instanceof String))throw Error("Type must be a string");switch(e){case"boolean":case"Boolean":return Boolean(t);case"number":case"Number":return Number(t.valueOf());case"string":case"String":return t+"";case"Date":if(C.isNumber(t))return new Date(t);if(t instanceof Date)return new Date(t.valueOf());if(M.isMoment(t))return new Date(t.valueOf());if(C.isString(t))return i=O.exec(t),i?new Date(Number(i[1])):M(t).toDate();throw Error("Cannot convert object of type "+C.getType(t)+" to type Date");case"Moment":if(C.isNumber(t))return M(t);if(t instanceof Date)return M(t.valueOf());if(M.isMoment(t))return M.clone();if(C.isString(t))return i=O.exec(t),i?M(Number(i[1])):M(t);throw Error("Cannot convert object of type "+C.getType(t)+" to type Date");case"ISODate":if(C.isNumber(t))return new Date(t);if(t instanceof Date)return t.toISOString();if(M.isMoment(t))return t.toDate().toISOString();if(C.isString(t))return i=O.exec(t),i?new Date(Number(i[1])).toISOString():new Date(t).toISOString();throw Error("Cannot convert object of type "+C.getType(t)+" to type ISODate");case"ASPDate":if(C.isNumber(t))return"/Date("+t+")/";if(t instanceof Date)return"/Date("+t.valueOf()+")/";if(C.isString(t)){i=O.exec(t);var n;return n=i?new Date(Number(i[1])).valueOf():new Date(t).valueOf(),"/Date("+n+")/"}throw Error("Cannot convert object of type "+C.getType(t)+" to type ASPDate");default:throw Error("Cannot convert object of type "+C.getType(t)+' to type "'+e+'"')}};var O=/^\/?Date\((\-?\d+)/i;if(C.getType=function(t){var e=typeof t;return"object"==e?null==t?"null":t instanceof Boolean?"Boolean":t instanceof Number?"Number":t instanceof String?"String":t instanceof Array?"Array":t instanceof Date?"Date":"Object":"number"==e?"Number":"boolean"==e?"Boolean":"string"==e?"String":e},C.getAbsoluteLeft=function(t){for(var e=document.documentElement,i=document.body,n=t.offsetLeft,s=t.offsetParent;null!=s&&s!=i&&s!=e;)n+=s.offsetLeft,n-=s.scrollLeft,s=s.offsetParent;return n},C.getAbsoluteTop=function(t){for(var e=document.documentElement,i=document.body,n=t.offsetTop,s=t.offsetParent;null!=s&&s!=i&&s!=e;)n+=s.offsetTop,n-=s.scrollTop,s=s.offsetParent;return n},C.getPageY=function(t){if("pageY"in t)return t.pageY;var e;e="targetTouches"in t&&t.targetTouches.length?t.targetTouches[0].clientY:t.clientY;var i=document.documentElement,n=document.body;return e+(i&&i.scrollTop||n&&n.scrollTop||0)-(i&&i.clientTop||n&&n.clientTop||0)},C.getPageX=function(t){if("pageY"in t)return t.pageX;var e;e="targetTouches"in t&&t.targetTouches.length?t.targetTouches[0].clientX:t.clientX;var i=document.documentElement,n=document.body;return e+(i&&i.scrollLeft||n&&n.scrollLeft||0)-(i&&i.clientLeft||n&&n.clientLeft||0)},C.addClassName=function(t,e){var i=t.className.split(" ");-1==i.indexOf(e)&&(i.push(e),t.className=i.join(" "))},C.removeClassName=function(t,e){var i=t.className.split(" "),n=i.indexOf(e);-1!=n&&(i.splice(n,1),t.className=i.join(" "))},C.forEach=function(t,e){var i,n;if(t instanceof Array)for(i=0,n=t.length;n>i;i++)e(t[i],i,t);else for(i in t)t.hasOwnProperty(i)&&e(t[i],i,t)},C.updateProperty=function(t,e,i){return t[e]!==i?(t[e]=i,!0):!1},C.addEventListener=function(t,e,i,n){t.addEventListener?(void 0===n&&(n=!1),"mousewheel"===e&&navigator.userAgent.indexOf("Firefox")>=0&&(e="DOMMouseScroll"),t.addEventListener(e,i,n)):t.attachEvent("on"+e,i)},C.removeEventListener=function(t,e,i,n){t.removeEventListener?(void 0===n&&(n=!1),"mousewheel"===e&&navigator.userAgent.indexOf("Firefox")>=0&&(e="DOMMouseScroll"),t.removeEventListener(e,i,n)):t.detachEvent("on"+e,i)},C.getTarget=function(t){t||(t=window.event);var e;return t.target?e=t.target:t.srcElement&&(e=t.srcElement),void 0!=e.nodeType&&3==e.nodeType&&(e=e.parentNode),e},C.stopPropagation=function(t){t||(t=window.event),t.stopPropagation?t.stopPropagation():t.cancelBubble=!0},C.preventDefault=function(t){t||(t=window.event),t.preventDefault?t.preventDefault():t.returnValue=!1},C.option={},C.option.asBoolean=function(t,e){return"function"==typeof t&&(t=t()),null!=t?0!=t:e||null},C.option.asNumber=function(t,e){return"function"==typeof t&&(t=t()),null!=t?Number(t)||e||null:e||null},C.option.asString=function(t,e){return"function"==typeof t&&(t=t()),null!=t?t+"":e||null},C.option.asSize=function(t,e){return"function"==typeof t&&(t=t()),C.isString(t)?t:C.isNumber(t)?t+"px":e||null},C.option.asElement=function(t,e){return"function"==typeof t&&(t=t()),t||e||null},C.loadCss=function(t){if("undefined"!=typeof document){var e=document.createElement("style");e.type="text/css",e.styleSheet?e.styleSheet.cssText=t:e.appendChild(document.createTextNode(t)),document.getElementsByTagName("head")[0].appendChild(e)}},!Array.prototype.indexOf){Array.prototype.indexOf=function(t){for(var e=0;this.length>e;e++)if(this[e]==t)return e;return-1};try{console.log("Warning: Ancient browser detected. Please update your browser")}catch(N){}}Array.prototype.forEach||(Array.prototype.forEach=function(t,e){for(var i=0,n=this.length;n>i;++i)t.call(e||this,this[i],i,this)}),Array.prototype.map||(Array.prototype.map=function(t,e){var i,n,s;if(null==this)throw new TypeError(" this is null or not defined");var o=Object(this),r=o.length>>>0;if("function"!=typeof t)throw new TypeError(t+" is not a function");for(e&&(i=e),n=Array(r),s=0;r>s;){var a,h;s in o&&(a=o[s],h=t.call(i,a,s,o),n[s]=h),s++}return n}),Array.prototype.filter||(Array.prototype.filter=function(t){"use strict";if(null==this)throw new TypeError;var e=Object(this),i=e.length>>>0;if("function"!=typeof t)throw new TypeError;for(var n=[],s=arguments[1],o=0;i>o;o++)if(o in e){var r=e[o];t.call(s,r,o,e)&&n.push(r)}return n}),Object.keys||(Object.keys=function(){var t=Object.prototype.hasOwnProperty,e=!{toString:null}.propertyIsEnumerable("toString"),i=["toString","toLocaleString","valueOf","hasOwnProperty","isPrototypeOf","propertyIsEnumerable","constructor"],n=i.length;return function(s){if("object"!=typeof s&&"function"!=typeof s||null===s)throw new TypeError("Object.keys called on non-object");var o=[];for(var r in s)t.call(s,r)&&o.push(r);if(e)for(var a=0;n>a;a++)t.call(s,i[a])&&o.push(i[a]);return o}}()),Array.isArray||(Array.isArray=function(t){return"[object Array]"===Object.prototype.toString.call(t)}),Function.prototype.bind||(Function.prototype.bind=function(t){if("function"!=typeof this)throw new TypeError("Function.prototype.bind - what is trying to be bound is not callable");var e=Array.prototype.slice.call(arguments,1),i=this,n=function(){},s=function(){return i.apply(this instanceof n&&t?this:t,e.concat(Array.prototype.slice.call(arguments)))};return n.prototype=this.prototype,s.prototype=new n,s}),Object.create||(Object.create=function(t){function e(){}if(arguments.length>1)throw Error("Object.create implementation only accepts the first parameter.");return e.prototype=t,new e});var L={listeners:[],indexOf:function(t){for(var e=this.listeners,i=0,n=this.listeners.length;n>i;i++){var s=e[i];if(s&&s.object==t)return i}return-1},addListener:function(t,e,i){var n=this.indexOf(t),s=this.listeners[n];s||(s={object:t,events:{}},this.listeners.push(s));var o=s.events[e];o||(o=[],s.events[e]=o),-1==o.indexOf(i)&&o.push(i)},removeListener:function(t,e,i){var n=this.indexOf(t),s=this.listeners[n];if(s){var o=s.events[e];o&&(n=o.indexOf(i),-1!=n&&o.splice(n,1),0==o.length&&delete s.events[e]);var r=0,a=s.events;for(var h in a)a.hasOwnProperty(h)&&r++;0==r&&delete this.listeners[n]}},removeAllListeners:function(){this.listeners=[]},trigger:function(t,e,i){var n=this.indexOf(t),s=this.listeners[n];if(s){var o=s.events[e];if(o)for(var r=0,a=o.length;a>r;r++)o[r](i)}}};s.prototype.on=function(t,e,i){var n=t instanceof RegExp?t:RegExp(t.replace("*","\\w+")),s={id:C.randomUUID(),event:t,regexp:n,callback:"function"==typeof e?e:null,target:i};return this.subscriptions.push(s),s.id},s.prototype.off=function(t){for(var e=0;this.subscriptions.length>e;){var i=this.subscriptions[e],n=!0;if(t instanceof Object)for(var s in t)t.hasOwnProperty(s)&&t[s]!==i[s]&&(n=!1);else n=i.id==t;n?this.subscriptions.splice(e,1):e++}},s.prototype.emit=function(t,e,i){for(var n=0;this.subscriptions.length>n;n++){var s=this.subscriptions[n];s.regexp.test(t)&&s.callback&&s.callback(t,e,i)}},o.prototype.subscribe=function(t,e){var i=this.subscribers[t];i||(i=[],this.subscribers[t]=i),i.push({callback:e})},o.prototype.unsubscribe=function(t,e){var i=this.subscribers[t];i&&(this.subscribers[t]=i.filter(function(t){return t.callback!=e}))},o.prototype._trigger=function(t,e,i){if("*"==t)throw Error("Cannot trigger event *");var n=[];t in this.subscribers&&(n=n.concat(this.subscribers[t])),"*"in this.subscribers&&(n=n.concat(this.subscribers["*"]));for(var s=0;n.length>s;s++){var o=n[s];o.callback&&o.callback(t,e,i||null)}},o.prototype.add=function(t,e){var i,n=[],s=this;if(t instanceof Array)for(var o=0,r=t.length;r>o;o++)i=s._addItem(t[o]),n.push(i);else if(C.isDataTable(t))for(var a=this._getColumnNames(t),h=0,d=t.getNumberOfRows();d>h;h++){for(var l={},u=0,c=a.length;c>u;u++){var p=a[u];l[p]=t.getValue(h,u)}i=s._addItem(l),n.push(i)}else{if(!(t instanceof Object))throw Error("Unknown dataType");i=s._addItem(t),n.push(i)}return n.length&&this._trigger("add",{items:n},e),n},o.prototype.update=function(t,e){var i=[],n=[],s=this,o=s.fieldId,r=function(t){var e=t[o];s.data[e]?(e=s._updateItem(t),n.push(e)):(e=s._addItem(t),i.push(e))};if(t instanceof Array)for(var a=0,h=t.length;h>a;a++)r(t[a]);else if(C.isDataTable(t))for(var d=this._getColumnNames(t),l=0,u=t.getNumberOfRows();u>l;l++){for(var c={},p=0,f=d.length;f>p;p++){var m=d[p];c[m]=t.getValue(l,p)}r(c)}else{if(!(t instanceof Object))throw Error("Unknown dataType");r(t)}return i.length&&this._trigger("add",{items:i},e),n.length&&this._trigger("update",{items:n},e),i.concat(n)},o.prototype.get=function(){var t,e,i,n,s=this,o=C.getType(arguments[0]);"String"==o||"Number"==o?(t=arguments[0],i=arguments[1],n=arguments[2]):"Array"==o?(e=arguments[0],i=arguments[1],n=arguments[2]):(i=arguments[0],n=arguments[1]);var r;if(i&&i.type){if(r="DataTable"==i.type?"DataTable":"Array",n&&r!=C.getType(n))throw Error('Type of parameter "data" ('+C.getType(n)+") "+"does not correspond with specified options.type ("+i.type+")");if("DataTable"==r&&!C.isDataTable(n))throw Error('Parameter "data" must be a DataTable when options.type is "DataTable"')}else r=n?"DataTable"==C.getType(n)?"DataTable":"Array":"Array";var a,h,d,l,u=i&&i.convert||this.options.convert,c=i&&i.filter,p=[];if(void 0!=t)a=s._getItem(t,u),c&&!c(a)&&(a=null);else if(void 0!=e)for(d=0,l=e.length;l>d;d++)a=s._getItem(e[d],u),(!c||c(a))&&p.push(a);else for(h in this.data)this.data.hasOwnProperty(h)&&(a=s._getItem(h,u),(!c||c(a))&&p.push(a));if(i&&i.order&&void 0==t&&this._sort(p,i.order),i&&i.fields){var f=i.fields;if(void 0!=t)a=this._filterFields(a,f);else for(d=0,l=p.length;l>d;d++)p[d]=this._filterFields(p[d],f)}if("DataTable"==r){var m=this._getColumnNames(n);if(void 0!=t)s._appendRow(n,m,a);else for(d=0,l=p.length;l>d;d++)s._appendRow(n,m,p[d]);return n}if(void 0!=t)return a;if(n){for(d=0,l=p.length;l>d;d++)n.push(p[d]);return n}return p},o.prototype.getIds=function(t){var e,i,n,s,o,r=this.data,a=t&&t.filter,h=t&&t.order,d=t&&t.convert||this.options.convert,l=[];if(a)if(h){o=[];for(n in r)r.hasOwnProperty(n)&&(s=this._getItem(n,d),a(s)&&o.push(s));for(this._sort(o,h),e=0,i=o.length;i>e;e++)l[e]=o[e][this.fieldId]}else for(n in r)r.hasOwnProperty(n)&&(s=this._getItem(n,d),a(s)&&l.push(s[this.fieldId]));else if(h){o=[];for(n in r)r.hasOwnProperty(n)&&o.push(r[n]);for(this._sort(o,h),e=0,i=o.length;i>e;e++)l[e]=o[e][this.fieldId]}else for(n in r)r.hasOwnProperty(n)&&(s=r[n],l.push(s[this.fieldId]));return l},o.prototype.forEach=function(t,e){var i,n,s=e&&e.filter,o=e&&e.convert||this.options.convert,r=this.data;if(e&&e.order)for(var a=this.get(e),h=0,d=a.length;d>h;h++)i=a[h],n=i[this.fieldId],t(i,n);else for(n in r)r.hasOwnProperty(n)&&(i=this._getItem(n,o),(!s||s(i))&&t(i,n))},o.prototype.map=function(t,e){var i,n=e&&e.filter,s=e&&e.convert||this.options.convert,o=[],r=this.data;for(var a in r)r.hasOwnProperty(a)&&(i=this._getItem(a,s),(!n||n(i))&&o.push(t(i,a)));return e&&e.order&&this._sort(o,e.order),o},o.prototype._filterFields=function(t,e){var i={};for(var n in t)t.hasOwnProperty(n)&&-1!=e.indexOf(n)&&(i[n]=t[n]);return i},o.prototype._sort=function(t,e){if(C.isString(e)){var i=e;t.sort(function(t,e){var n=t[i],s=e[i];return n>s?1:s>n?-1:0})}else{if("function"!=typeof e)throw new TypeError("Order must be a function or a string");t.sort(e)}},o.prototype.remove=function(t,e){var i,n,s,o=[];if(t instanceof Array)for(i=0,n=t.length;n>i;i++)s=this._remove(t[i]),null!=s&&o.push(s);else s=this._remove(t),null!=s&&o.push(s);return o.length&&this._trigger("remove",{items:o},e),o},o.prototype._remove=function(t){if(C.isNumber(t)||C.isString(t)){if(this.data[t])return delete this.data[t],delete this.internalIds[t],t}else if(t instanceof Object){var e=t[this.fieldId];if(e&&this.data[e])return delete this.data[e],delete this.internalIds[e],e}return null},o.prototype.clear=function(t){var e=Object.keys(this.data);return this.data={},this.internalIds={},this._trigger("remove",{items:e},t),e},o.prototype.max=function(t){var e=this.data,i=null,n=null;for(var s in e)if(e.hasOwnProperty(s)){var o=e[s],r=o[t];null!=r&&(!i||r>n)&&(i=o,n=r)}return i},o.prototype.min=function(t){var e=this.data,i=null,n=null;for(var s in e)if(e.hasOwnProperty(s)){var o=e[s],r=o[t];null!=r&&(!i||n>r)&&(i=o,n=r)}return i},o.prototype.distinct=function(t){var e=this.data,i=[],n=this.options.convert[t],s=0;for(var o in e)if(e.hasOwnProperty(o)){for(var r=e[o],a=C.convert(r[t],n),h=!1,d=0;s>d;d++)if(i[d]==a){h=!0;break}h||(i[s]=a,s++)}return i},o.prototype._addItem=function(t){var e=t[this.fieldId];if(void 0!=e){if(this.data[e])throw Error("Cannot add item: item with id "+e+" already exists")}else e=C.randomUUID(),t[this.fieldId]=e,this.internalIds[e]=t;var i={};for(var n in t)if(t.hasOwnProperty(n)){var s=this.convert[n];i[n]=C.convert(t[n],s)}return this.data[e]=i,e},o.prototype._getItem=function(t,e){var i,n,s=this.data[t];if(!s)return null;var o={},r=this.fieldId,a=this.internalIds;if(e)for(i in s)s.hasOwnProperty(i)&&(n=s[i],i==r&&n in a||(o[i]=C.convert(n,e[i])));else for(i in s)s.hasOwnProperty(i)&&(n=s[i],i==r&&n in a||(o[i]=n));return o},o.prototype._updateItem=function(t){var e=t[this.fieldId];if(void 0==e)throw Error("Cannot update item: item has no id (item: "+JSON.stringify(t)+")");var i=this.data[e];if(!i)throw Error("Cannot update item: no item with id "+e+" found");for(var n in t)if(t.hasOwnProperty(n)){var s=this.convert[n];i[n]=C.convert(t[n],s)}return e},o.prototype._getColumnNames=function(t){for(var e=[],i=0,n=t.getNumberOfColumns();n>i;i++)e[i]=t.getColumnId(i)||t.getColumnLabel(i);return e},o.prototype._appendRow=function(t,e,i){for(var n=t.addRow(),s=0,o=e.length;o>s;s++){var r=e[s];t.setValue(n,s,i[r])}},r.prototype.setData=function(t){var e,i,n;if(this.data){this.data.unsubscribe&&this.data.unsubscribe("*",this.listener),e=[];for(var s in this.ids)this.ids.hasOwnProperty(s)&&e.push(s);this.ids={},this._trigger("remove",{items:e})}if(this.data=t,this.data){for(this.fieldId=this.options.fieldId||this.data&&this.data.options&&this.data.options.fieldId||"id",e=this.data.getIds({filter:this.options&&this.options.filter}),i=0,n=e.length;n>i;i++)s=e[i],this.ids[s]=!0;this._trigger("add",{items:e}),this.data.subscribe&&this.data.subscribe("*",this.listener)}},r.prototype.get=function(){var t,e,i,n=this,s=C.getType(arguments[0]);"String"==s||"Number"==s||"Array"==s?(t=arguments[0],e=arguments[1],i=arguments[2]):(e=arguments[0],i=arguments[1]);var o=C.extend({},this.options,e);this.options.filter&&e&&e.filter&&(o.filter=function(t){return n.options.filter(t)&&e.filter(t)});var r=[];return void 0!=t&&r.push(t),r.push(o),r.push(i),this.data&&this.data.get.apply(this.data,r)},r.prototype.getIds=function(t){var e;if(this.data){var i,n=this.options.filter;i=t&&t.filter?n?function(e){return n(e)&&t.filter(e)}:t.filter:n,e=this.data.getIds({filter:i,order:t&&t.order})}else e=[];return e},r.prototype._onEvent=function(t,e,i){var n,s,o,r,a=e&&e.items,h=this.data,d=[],l=[],u=[];if(a&&h){switch(t){case"add":for(n=0,s=a.length;s>n;n++)o=a[n],r=this.get(o),r&&(this.ids[o]=!0,d.push(o));break;case"update":for(n=0,s=a.length;s>n;n++)o=a[n],r=this.get(o),r?this.ids[o]?l.push(o):(this.ids[o]=!0,d.push(o)):this.ids[o]&&(delete this.ids[o],u.push(o));break;case"remove":for(n=0,s=a.length;s>n;n++)o=a[n],this.ids[o]&&(delete this.ids[o],u.push(o))}d.length&&this._trigger("add",{items:d},i),l.length&&this._trigger("update",{items:l},i),u.length&&this._trigger("remove",{items:u},i)}},r.prototype.subscribe=o.prototype.subscribe,r.prototype.unsubscribe=o.prototype.unsubscribe,r.prototype._trigger=o.prototype._trigger,TimeStep=function(t,e,i){this.current=new Date,this._start=new Date,this._end=new Date,this.autoScale=!0,this.scale=TimeStep.SCALE.DAY,this.step=1,this.setRange(t,e,i)},TimeStep.SCALE={MILLISECOND:1,SECOND:2,MINUTE:3,HOUR:4,DAY:5,WEEKDAY:6,MONTH:7,YEAR:8},TimeStep.prototype.setRange=function(t,e,i){t instanceof Date&&e instanceof Date&&(this._start=void 0!=t?new Date(t.valueOf()):new Date,this._end=void 0!=e?new Date(e.valueOf()):new Date,this.autoScale&&this.setMinimumStep(i))},TimeStep.prototype.first=function(){this.current=new Date(this._start.valueOf()),this.roundToMinor()},TimeStep.prototype.roundToMinor=function(){switch(this.scale){case TimeStep.SCALE.YEAR:this.current.setFullYear(this.step*Math.floor(this.current.getFullYear()/this.step)),this.current.setMonth(0);case TimeStep.SCALE.MONTH:this.current.setDate(1);case TimeStep.SCALE.DAY:case TimeStep.SCALE.WEEKDAY:this.current.setHours(0);case TimeStep.SCALE.HOUR:this.current.setMinutes(0);case TimeStep.SCALE.MINUTE:this.current.setSeconds(0);case TimeStep.SCALE.SECOND:this.current.setMilliseconds(0)}if(1!=this.step)switch(this.scale){case TimeStep.SCALE.MILLISECOND:this.current.setMilliseconds(this.current.getMilliseconds()-this.current.getMilliseconds()%this.step);break;case TimeStep.SCALE.SECOND:this.current.setSeconds(this.current.getSeconds()-this.current.getSeconds()%this.step);break;case TimeStep.SCALE.MINUTE:this.current.setMinutes(this.current.getMinutes()-this.current.getMinutes()%this.step);break;case TimeStep.SCALE.HOUR:this.current.setHours(this.current.getHours()-this.current.getHours()%this.step);break;case TimeStep.SCALE.WEEKDAY:case TimeStep.SCALE.DAY:this.current.setDate(this.current.getDate()-1-(this.current.getDate()-1)%this.step+1);break;case TimeStep.SCALE.MONTH:this.current.setMonth(this.current.getMonth()-this.current.getMonth()%this.step);break;case TimeStep.SCALE.YEAR:this.current.setFullYear(this.current.getFullYear()-this.current.getFullYear()%this.step);break;default:}},TimeStep.prototype.hasNext=function(){return this.current.valueOf()<=this._end.valueOf()},TimeStep.prototype.next=function(){var t=this.current.valueOf();if(6>this.current.getMonth())switch(this.scale){case TimeStep.SCALE.MILLISECOND:this.current=new Date(this.current.valueOf()+this.step);break;case TimeStep.SCALE.SECOND:this.current=new Date(this.current.valueOf()+1e3*this.step);break;case TimeStep.SCALE.MINUTE:this.current=new Date(this.current.valueOf()+60*1e3*this.step);break;case TimeStep.SCALE.HOUR:this.current=new Date(this.current.valueOf()+60*60*1e3*this.step);var e=this.current.getHours();this.current.setHours(e-e%this.step);break;case TimeStep.SCALE.WEEKDAY:case TimeStep.SCALE.DAY:this.current.setDate(this.current.getDate()+this.step);break;case TimeStep.SCALE.MONTH:this.current.setMonth(this.current.getMonth()+this.step);break;case TimeStep.SCALE.YEAR:this.current.setFullYear(this.current.getFullYear()+this.step);break;default:}else switch(this.scale){case TimeStep.SCALE.MILLISECOND:this.current=new Date(this.current.valueOf()+this.step);break;case TimeStep.SCALE.SECOND:this.current.setSeconds(this.current.getSeconds()+this.step);break;case TimeStep.SCALE.MINUTE:this.current.setMinutes(this.current.getMinutes()+this.step);break;case TimeStep.SCALE.HOUR:this.current.setHours(this.current.getHours()+this.step);break;case TimeStep.SCALE.WEEKDAY:case TimeStep.SCALE.DAY:this.current.setDate(this.current.getDate()+this.step);break;case TimeStep.SCALE.MONTH:this.current.setMonth(this.current.getMonth()+this.step);break;case TimeStep.SCALE.YEAR:this.current.setFullYear(this.current.getFullYear()+this.step);break;default:}if(1!=this.step)switch(this.scale){case TimeStep.SCALE.MILLISECOND:this.current.getMilliseconds()0&&(this.step=e),this.autoScale=!1},TimeStep.prototype.setAutoScale=function(t){this.autoScale=t},TimeStep.prototype.setMinimumStep=function(t){if(void 0!=t){var e=31104e6,i=2592e6,n=864e5,s=36e5,o=6e4,r=1e3,a=1;1e3*e>t&&(this.scale=TimeStep.SCALE.YEAR,this.step=1e3),500*e>t&&(this.scale=TimeStep.SCALE.YEAR,this.step=500),100*e>t&&(this.scale=TimeStep.SCALE.YEAR,this.step=100),50*e>t&&(this.scale=TimeStep.SCALE.YEAR,this.step=50),10*e>t&&(this.scale=TimeStep.SCALE.YEAR,this.step=10),5*e>t&&(this.scale=TimeStep.SCALE.YEAR,this.step=5),e>t&&(this.scale=TimeStep.SCALE.YEAR,this.step=1),3*i>t&&(this.scale=TimeStep.SCALE.MONTH,this.step=3),i>t&&(this.scale=TimeStep.SCALE.MONTH,this.step=1),5*n>t&&(this.scale=TimeStep.SCALE.DAY,this.step=5),2*n>t&&(this.scale=TimeStep.SCALE.DAY,this.step=2),n>t&&(this.scale=TimeStep.SCALE.DAY,this.step=1),n/2>t&&(this.scale=TimeStep.SCALE.WEEKDAY,this.step=1),4*s>t&&(this.scale=TimeStep.SCALE.HOUR,this.step=4),s>t&&(this.scale=TimeStep.SCALE.HOUR,this.step=1),15*o>t&&(this.scale=TimeStep.SCALE.MINUTE,this.step=15),10*o>t&&(this.scale=TimeStep.SCALE.MINUTE,this.step=10),5*o>t&&(this.scale=TimeStep.SCALE.MINUTE,this.step=5),o>t&&(this.scale=TimeStep.SCALE.MINUTE,this.step=1),15*r>t&&(this.scale=TimeStep.SCALE.SECOND,this.step=15),10*r>t&&(this.scale=TimeStep.SCALE.SECOND,this.step=10),5*r>t&&(this.scale=TimeStep.SCALE.SECOND,this.step=5),r>t&&(this.scale=TimeStep.SCALE.SECOND,this.step=1),200*a>t&&(this.scale=TimeStep.SCALE.MILLISECOND,this.step=200),100*a>t&&(this.scale=TimeStep.SCALE.MILLISECOND,this.step=100),50*a>t&&(this.scale=TimeStep.SCALE.MILLISECOND,this.step=50),10*a>t&&(this.scale=TimeStep.SCALE.MILLISECOND,this.step=10),5*a>t&&(this.scale=TimeStep.SCALE.MILLISECOND,this.step=5),a>t&&(this.scale=TimeStep.SCALE.MILLISECOND,this.step=1) -}},TimeStep.prototype.snap=function(t){if(this.scale==TimeStep.SCALE.YEAR){var e=t.getFullYear()+Math.round(t.getMonth()/12);t.setFullYear(Math.round(e/this.step)*this.step),t.setMonth(0),t.setDate(0),t.setHours(0),t.setMinutes(0),t.setSeconds(0),t.setMilliseconds(0)}else if(this.scale==TimeStep.SCALE.MONTH)t.getDate()>15?(t.setDate(1),t.setMonth(t.getMonth()+1)):t.setDate(1),t.setHours(0),t.setMinutes(0),t.setSeconds(0),t.setMilliseconds(0);else if(this.scale==TimeStep.SCALE.DAY||this.scale==TimeStep.SCALE.WEEKDAY){switch(this.step){case 5:case 2:t.setHours(24*Math.round(t.getHours()/24));break;default:t.setHours(12*Math.round(t.getHours()/12))}t.setMinutes(0),t.setSeconds(0),t.setMilliseconds(0)}else if(this.scale==TimeStep.SCALE.HOUR){switch(this.step){case 4:t.setMinutes(60*Math.round(t.getMinutes()/60));break;default:t.setMinutes(30*Math.round(t.getMinutes()/30))}t.setSeconds(0),t.setMilliseconds(0)}else if(this.scale==TimeStep.SCALE.MINUTE){switch(this.step){case 15:case 10:t.setMinutes(5*Math.round(t.getMinutes()/5)),t.setSeconds(0);break;case 5:t.setSeconds(60*Math.round(t.getSeconds()/60));break;default:t.setSeconds(30*Math.round(t.getSeconds()/30))}t.setMilliseconds(0)}else if(this.scale==TimeStep.SCALE.SECOND)switch(this.step){case 15:case 10:t.setSeconds(5*Math.round(t.getSeconds()/5)),t.setMilliseconds(0);break;case 5:t.setMilliseconds(1e3*Math.round(t.getMilliseconds()/1e3));break;default:t.setMilliseconds(500*Math.round(t.getMilliseconds()/500))}else if(this.scale==TimeStep.SCALE.MILLISECOND){var i=this.step>5?this.step/2:1;t.setMilliseconds(Math.round(t.getMilliseconds()/i)*i)}},TimeStep.prototype.isMajor=function(){switch(this.scale){case TimeStep.SCALE.MILLISECOND:return 0==this.current.getMilliseconds();case TimeStep.SCALE.SECOND:return 0==this.current.getSeconds();case TimeStep.SCALE.MINUTE:return 0==this.current.getHours()&&0==this.current.getMinutes();case TimeStep.SCALE.HOUR:return 0==this.current.getHours();case TimeStep.SCALE.WEEKDAY:case TimeStep.SCALE.DAY:return 1==this.current.getDate();case TimeStep.SCALE.MONTH:return 0==this.current.getMonth();case TimeStep.SCALE.YEAR:return!1;default:return!1}},TimeStep.prototype.getLabelMinor=function(t){switch(void 0==t&&(t=this.current),this.scale){case TimeStep.SCALE.MILLISECOND:return M(t).format("SSS");case TimeStep.SCALE.SECOND:return M(t).format("s");case TimeStep.SCALE.MINUTE:return M(t).format("HH:mm");case TimeStep.SCALE.HOUR:return M(t).format("HH:mm");case TimeStep.SCALE.WEEKDAY:return M(t).format("ddd D");case TimeStep.SCALE.DAY:return M(t).format("D");case TimeStep.SCALE.MONTH:return M(t).format("MMM");case TimeStep.SCALE.YEAR:return M(t).format("YYYY");default:return""}},TimeStep.prototype.getLabelMajor=function(t){switch(void 0==t&&(t=this.current),this.scale){case TimeStep.SCALE.MILLISECOND:return M(t).format("HH:mm:ss");case TimeStep.SCALE.SECOND:return M(t).format("D MMMM HH:mm");case TimeStep.SCALE.MINUTE:case TimeStep.SCALE.HOUR:return M(t).format("ddd D MMMM");case TimeStep.SCALE.WEEKDAY:case TimeStep.SCALE.DAY:return M(t).format("MMMM YYYY");case TimeStep.SCALE.MONTH:return M(t).format("YYYY");case TimeStep.SCALE.YEAR:return"";default:return""}},a.prototype.setOptions=function(t){C.extend(this.options,t)},a.prototype.update=function(){this._order(),this._stack()},a.prototype._order=function(){var t=this.parent.items;if(!t)throw Error("Cannot stack items: parent does not contain items");var e=[],i=0;C.forEach(t,function(t){t.visible&&(e[i]=t,i++)});var n=this.options.order||this.defaultOptions.order;if("function"!=typeof n)throw Error("Option order must be a function");e.sort(n),this.ordered=e},a.prototype._stack=function(){var t,e,i,n=this.ordered,s=this.options,o=s.orientation||this.defaultOptions.orientation,r="top"==o;for(i=s.margin&&void 0!==s.margin.item?s.margin.item:this.defaultOptions.margin.item,t=0,e=n.length;e>t;t++){var a=n[t],h=null;do h=this.checkOverlap(n,t,0,t-1,i),null!=h&&(a.top=r?h.top+h.height+i:h.top-a.height-i);while(h)}},a.prototype.checkOverlap=function(t,e,i,n,s){for(var o=this.collision,r=t[e],a=n;a>=i;a--){var h=t[a];if(o(r,h,s)&&a!=e)return h}return null},a.prototype.collision=function(t,e,i){return t.left-ie.left&&t.top-ie.top},h.prototype.setOptions=function(t){C.extend(this.options,t),(null!=t.start||null!=t.end)&&this.setRange(t.start,t.end)},h.prototype.subscribe=function(t,e,i){var n,s=this;if("horizontal"!=i&&"vertical"!=i)throw new TypeError('Unknown direction "'+i+'". '+'Choose "horizontal" or "vertical".');if("move"==e)n={component:t,event:e,direction:i,callback:function(t){s._onMouseDown(t,n)},params:{}},t.on("mousedown",n.callback),s.listeners.push(n);else{if("zoom"!=e)throw new TypeError('Unknown event "'+e+'". '+'Choose "move" or "zoom".');n={component:t,event:e,direction:i,callback:function(t){s._onMouseWheel(t,n)},params:{}},t.on("mousewheel",n.callback),s.listeners.push(n)}},h.prototype.on=function(t,e){L.addListener(this,t,e)},h.prototype._trigger=function(t){L.trigger(this,t,{start:this.start,end:this.end})},h.prototype.setRange=function(t,e){var i=this._applyRange(t,e);i&&(this._trigger("rangechange"),this._trigger("rangechanged"))},h.prototype._applyRange=function(t,e){var i,n=null!=t?C.convert(t,"Number"):this.start,s=null!=e?C.convert(e,"Number"):this.end;if(isNaN(n))throw Error('Invalid start "'+t+'"');if(isNaN(s))throw Error('Invalid end "'+e+'"');if(n>s&&(s=n),null!=this.options.min){var o=this.options.min.valueOf();o>n&&(i=o-n,n+=i,s+=i)}if(null!=this.options.max){var r=this.options.max.valueOf();s>r&&(i=s-r,n-=i,s-=i)}if(null!=this.options.zoomMin){var a=this.options.zoomMin.valueOf();0>a&&(a=0),a>s-n&&(this.end-this.start>a?(i=a-(s-n),n-=i/2,s+=i/2):(n=this.start,s=this.end))}if(null!=this.options.zoomMax){var h=this.options.zoomMax.valueOf();0>h&&(h=0),s-n>h&&(h>this.end-this.start?(i=s-n-h,n+=i/2,s-=i/2):(n=this.start,s=this.end))}var d=this.start!=n||this.end!=s;return this.start=n,this.end=s,d},h.prototype.getRange=function(){return{start:this.start,end:this.end}},h.prototype.conversion=function(t){return this.start,this.end,h.conversion(this.start,this.end,t)},h.conversion=function(t,e,i){return 0!=i&&0!=e-t?{offset:t,factor:i/(e-t)}:{offset:0,factor:1}},h.prototype._onMouseDown=function(t,e){t=t||window.event;var i=e.params,n=t.which?1==t.which:1==t.button;if(n){i.mouseX=C.getPageX(t),i.mouseY=C.getPageY(t),i.previousLeft=0,i.previousOffset=0,i.moved=!1,i.start=this.start,i.end=this.end;var s=e.component.frame;s&&(s.style.cursor="move");var o=this;i.onMouseMove||(i.onMouseMove=function(t){o._onMouseMove(t,e)},C.addEventListener(document,"mousemove",i.onMouseMove)),i.onMouseUp||(i.onMouseUp=function(t){o._onMouseUp(t,e)},C.addEventListener(document,"mouseup",i.onMouseUp)),C.preventDefault(t)}},h.prototype._onMouseMove=function(t,e){t=t||window.event;var i=e.params,n=C.getPageX(t),s=C.getPageY(t);void 0==i.mouseX&&(i.mouseX=n),void 0==i.mouseY&&(i.mouseY=s);var o=n-i.mouseX,r=s-i.mouseY,a="horizontal"==e.direction?o:r;Math.abs(a)>=1&&(i.moved=!0);var h=i.end-i.start,d="horizontal"==e.direction?e.component.width:e.component.height,l=-a/d*h;this._applyRange(i.start+l,i.end+l),this._trigger("rangechange"),C.preventDefault(t)},h.prototype._onMouseUp=function(t,e){t=t||window.event;var i=e.params;e.component.frame&&(e.component.frame.style.cursor="auto"),i.onMouseMove&&(C.removeEventListener(document,"mousemove",i.onMouseMove),i.onMouseMove=null),i.onMouseUp&&(C.removeEventListener(document,"mouseup",i.onMouseUp),i.onMouseUp=null),i.moved&&this._trigger("rangechanged")},h.prototype._onMouseWheel=function(t,e){t=t||window.event;var i=0;if(t.wheelDelta?i=t.wheelDelta/120:t.detail&&(i=-t.detail/3),i){var n=this,s=function(){var s=i/5,o=null,r=e.component.frame;if(r){var a,h;if("horizontal"==e.direction){a=e.component.width,h=n.conversion(a);var d=C.getAbsoluteLeft(r),l=C.getPageX(t);o=(l-d)/h.factor+h.offset}else{a=e.component.height,h=n.conversion(a);var u=C.getAbsoluteTop(r),c=C.getPageY(t);o=(u+a-c-u)/h.factor+h.offset}}n.zoom(s,o)};s()}C.preventDefault(t)},h.prototype.zoom=function(t,e){null==e&&(e=(this.start+this.end)/2),t>=1&&(t=.9),-1>=t&&(t=-.9),0>t&&(t/=1+t);var i=this.start-e,n=this.end-e,s=this.start-i*t,o=this.end-n*t;this.setRange(s,o)},h.prototype.move=function(t){var e=this.end-this.start,i=this.start+e*t,n=this.end+e*t;this.start=i,this.end=n},h.prototype.moveTo=function(t){var e=(this.start+this.end)/2,i=e-t,n=this.start-i,s=this.end-i;this.setRange(n,s)},d.prototype.add=function(t){if(void 0==t.id)throw Error("Component has no field id");if(!(t instanceof l||t instanceof d))throw new TypeError("Component must be an instance of prototype Component or Controller");t.controller=this,this.components[t.id]=t},d.prototype.remove=function(t){var e;for(e in this.components)if(this.components.hasOwnProperty(e)&&(e==t||this.components[e]==t))break;e&&delete this.components[e]},d.prototype.requestReflow=function(t){if(t)this.reflow();else if(!this.reflowTimer){var e=this;this.reflowTimer=setTimeout(function(){e.reflowTimer=void 0,e.reflow()},0)}},d.prototype.requestRepaint=function(t){if(t)this.repaint();else if(!this.repaintTimer){var e=this;this.repaintTimer=setTimeout(function(){e.repaintTimer=void 0,e.repaint()},0)}},d.prototype.repaint=function(){function t(n,s){s in i||(n.depends&&n.depends.forEach(function(e){t(e,e.id)}),n.parent&&t(n.parent,n.parent.id),e=n.repaint()||e,i[s]=!0)}var e=!1;this.repaintTimer&&(clearTimeout(this.repaintTimer),this.repaintTimer=void 0);var i={};C.forEach(this.components,t),e&&this.reflow()},d.prototype.reflow=function(){function t(n,s){s in i||(n.depends&&n.depends.forEach(function(e){t(e,e.id)}),n.parent&&t(n.parent,n.parent.id),e=n.reflow()||e,i[s]=!0)}var e=!1;this.reflowTimer&&(clearTimeout(this.reflowTimer),this.reflowTimer=void 0);var i={};C.forEach(this.components,t),e&&this.repaint()},l.prototype.setOptions=function(t){t&&(C.extend(this.options,t),this.controller&&(this.requestRepaint(),this.requestReflow()))},l.prototype.getOption=function(t){var e;return this.options&&(e=this.options[t]),void 0===e&&this.defaultOptions&&(e=this.defaultOptions[t]),e},l.prototype.getContainer=function(){return null},l.prototype.getFrame=function(){return this.frame},l.prototype.repaint=function(){return!1},l.prototype.reflow=function(){return!1},l.prototype.hide=function(){return this.frame&&this.frame.parentNode?(this.frame.parentNode.removeChild(this.frame),!0):!1},l.prototype.show=function(){return this.frame&&this.frame.parentNode?!1:this.repaint()},l.prototype.requestRepaint=function(){if(!this.controller)throw Error("Cannot request a repaint: no controller configured");this.controller.requestRepaint()},l.prototype.requestReflow=function(){if(!this.controller)throw Error("Cannot request a reflow: no controller configured");this.controller.requestReflow()},u.prototype=new l,u.prototype.setOptions=l.prototype.setOptions,u.prototype.getContainer=function(){return this.frame},u.prototype.repaint=function(){var t=0,e=C.updateProperty,i=C.option.asSize,n=this.options,s=this.frame;if(!s){s=document.createElement("div"),s.className="panel";var o=n.className;o&&("function"==typeof o?C.addClassName(s,o()+""):C.addClassName(s,o+"")),this.frame=s,t+=1}if(!s.parentNode){if(!this.parent)throw Error("Cannot repaint panel: no parent attached");var r=this.parent.getContainer();if(!r)throw Error("Cannot repaint panel: parent has no container element");r.appendChild(s),t+=1}return t+=e(s.style,"top",i(n.top,"0px")),t+=e(s.style,"left",i(n.left,"0px")),t+=e(s.style,"width",i(n.width,"100%")),t+=e(s.style,"height",i(n.height,"100%")),t>0},u.prototype.reflow=function(){var t=0,e=C.updateProperty,i=this.frame;return i?(t+=e(this,"top",i.offsetTop),t+=e(this,"left",i.offsetLeft),t+=e(this,"width",i.offsetWidth),t+=e(this,"height",i.offsetHeight)):t+=1,t>0},c.prototype=new u,c.prototype.setOptions=l.prototype.setOptions,c.prototype.repaint=function(){var t=0,e=C.updateProperty,i=C.option.asSize,n=this.options,s=this.frame;if(!s){s=document.createElement("div"),s.className="vis timeline rootpanel";var o=n.className;o&&C.addClassName(s,C.option.asString(o)),this.frame=s,t+=1}if(!s.parentNode){if(!this.container)throw Error("Cannot repaint root panel: no container attached");this.container.appendChild(s),t+=1}return t+=e(s.style,"top",i(n.top,"0px")),t+=e(s.style,"left",i(n.left,"0px")),t+=e(s.style,"width",i(n.width,"100%")),t+=e(s.style,"height",i(n.height,"100%")),this._updateEventEmitters(),this._updateWatch(),t>0},c.prototype.reflow=function(){var t=0,e=C.updateProperty,i=this.frame;return i?(t+=e(this,"top",i.offsetTop),t+=e(this,"left",i.offsetLeft),t+=e(this,"width",i.offsetWidth),t+=e(this,"height",i.offsetHeight)):t+=1,t>0},c.prototype._updateWatch=function(){var t=this.getOption("autoResize");t?this._watch():this._unwatch()},c.prototype._watch=function(){var t=this;this._unwatch();var e=function(){var e=t.getOption("autoResize");return e?(t.frame&&(t.frame.clientWidth!=t.width||t.frame.clientHeight!=t.height)&&t.requestReflow(),void 0):(t._unwatch(),void 0)};C.addEventListener(window,"resize",e),this.watchTimer=setInterval(e,1e3)},c.prototype._unwatch=function(){this.watchTimer&&(clearInterval(this.watchTimer),this.watchTimer=void 0)},c.prototype.on=function(t,e){var i=this.listeners[t];i||(i=[],this.listeners[t]=i),i.push(e),this._updateEventEmitters()},c.prototype._updateEventEmitters=function(){if(this.listeners){var t=this;C.forEach(this.listeners,function(e,i){if(t.emitters||(t.emitters={}),!(i in t.emitters)){var n=t.frame;if(n){var s=function(t){e.forEach(function(e){e(t)})};t.emitters[i]=s,C.addEventListener(n,i,s)}}})}},p.prototype=new l,p.prototype.setOptions=l.prototype.setOptions,p.prototype.setRange=function(t){if(!(t instanceof h||t&&t.start&&t.end))throw new TypeError("Range must be an instance of Range, or an object containing start and end.");this.range=t},p.prototype.toTime=function(t){var e=this.conversion;return new Date(t/e.factor+e.offset)},p.prototype.toScreen=function(t){var e=this.conversion;return(t.valueOf()-e.offset)*e.factor},p.prototype.repaint=function(){var t=0,e=C.updateProperty,i=C.option.asSize,n=this.options,s=this.getOption("orientation"),o=this.props,r=this.step,a=this.frame;if(a||(a=document.createElement("div"),this.frame=a,t+=1),a.className="axis "+s,!a.parentNode){if(!this.parent)throw Error("Cannot repaint time axis: no parent attached");var h=this.parent.getContainer();if(!h)throw Error("Cannot repaint time axis: parent has no container element");h.appendChild(a),t+=1}var d=a.parentNode;if(d){var l=a.nextSibling;d.removeChild(a);var u="bottom"==s&&this.props.parentHeight&&this.height?this.props.parentHeight-this.height+"px":"0px";if(t+=e(a.style,"top",i(n.top,u)),t+=e(a.style,"left",i(n.left,"0px")),t+=e(a.style,"width",i(n.width,"100%")),t+=e(a.style,"height",i(n.height,this.height+"px")),this._repaintMeasureChars(),this.step){this._repaintStart(),r.first();for(var c=void 0,p=0;r.hasNext()&&1e3>p;){p++;var f=r.getCurrent(),m=this.toScreen(f),g=r.isMajor();this.getOption("showMinorLabels")&&this._repaintMinorText(m,r.getLabelMinor()),g&&this.getOption("showMajorLabels")?(m>0&&(void 0==c&&(c=m),this._repaintMajorText(m,r.getLabelMajor())),this._repaintMajorLine(m)):this._repaintMinorLine(m),r.next()}if(this.getOption("showMajorLabels")){var v=this.toTime(0),y=r.getLabelMajor(v),b=y.length*(o.majorCharWidth||10)+10;(void 0==c||c>b)&&this._repaintMajorText(0,y)}this._repaintEnd()}this._repaintLine(),l?d.insertBefore(a,l):d.appendChild(a)}return t>0},p.prototype._repaintStart=function(){var t=this.dom,e=t.redundant;e.majorLines=t.majorLines,e.majorTexts=t.majorTexts,e.minorLines=t.minorLines,e.minorTexts=t.minorTexts,t.majorLines=[],t.majorTexts=[],t.minorLines=[],t.minorTexts=[]},p.prototype._repaintEnd=function(){C.forEach(this.dom.redundant,function(t){for(;t.length;){var e=t.pop();e&&e.parentNode&&e.parentNode.removeChild(e)}})},p.prototype._repaintMinorText=function(t,e){var i=this.dom.redundant.minorTexts.shift();if(!i){var n=document.createTextNode("");i=document.createElement("div"),i.appendChild(n),i.className="text minor",this.frame.appendChild(i)}this.dom.minorTexts.push(i),i.childNodes[0].nodeValue=e,i.style.left=t+"px",i.style.top=this.props.minorLabelTop+"px"},p.prototype._repaintMajorText=function(t,e){var i=this.dom.redundant.majorTexts.shift();if(!i){var n=document.createTextNode(e);i=document.createElement("div"),i.className="text major",i.appendChild(n),this.frame.appendChild(i)}this.dom.majorTexts.push(i),i.childNodes[0].nodeValue=e,i.style.top=this.props.majorLabelTop+"px",i.style.left=t+"px"},p.prototype._repaintMinorLine=function(t){var e=this.dom.redundant.minorLines.shift();e||(e=document.createElement("div"),e.className="grid vertical minor",this.frame.appendChild(e)),this.dom.minorLines.push(e);var i=this.props;e.style.top=i.minorLineTop+"px",e.style.height=i.minorLineHeight+"px",e.style.left=t-i.minorLineWidth/2+"px"},p.prototype._repaintMajorLine=function(t){var e=this.dom.redundant.majorLines.shift();e||(e=document.createElement("DIV"),e.className="grid vertical major",this.frame.appendChild(e)),this.dom.majorLines.push(e);var i=this.props;e.style.top=i.majorLineTop+"px",e.style.left=t-i.majorLineWidth/2+"px",e.style.height=i.majorLineHeight+"px"},p.prototype._repaintLine=function(){var t=this.dom.line,e=this.frame;this.options,this.getOption("showMinorLabels")||this.getOption("showMajorLabels")?(t?(e.removeChild(t),e.appendChild(t)):(t=document.createElement("div"),t.className="grid horizontal major",e.appendChild(t),this.dom.line=t),t.style.top=this.props.lineTop+"px"):t&&axis.parentElement&&(e.removeChild(axis.line),delete this.dom.line)},p.prototype._repaintMeasureChars=function(){var t,e=this.dom;if(!e.measureCharMinor){t=document.createTextNode("0");var i=document.createElement("DIV");i.className="text minor measure",i.appendChild(t),this.frame.appendChild(i),e.measureCharMinor=i}if(!e.measureCharMajor){t=document.createTextNode("0");var n=document.createElement("DIV");n.className="text major measure",n.appendChild(t),this.frame.appendChild(n),e.measureCharMajor=n}},p.prototype.reflow=function(){var t=0,e=C.updateProperty,i=this.frame,n=this.range;if(!n)throw Error("Cannot repaint time axis: no range configured");if(i){t+=e(this,"top",i.offsetTop),t+=e(this,"left",i.offsetLeft);var s=this.props,o=this.getOption("showMinorLabels"),r=this.getOption("showMajorLabels"),a=this.dom.measureCharMinor,h=this.dom.measureCharMajor;a&&(s.minorCharHeight=a.clientHeight,s.minorCharWidth=a.clientWidth),h&&(s.majorCharHeight=h.clientHeight,s.majorCharWidth=h.clientWidth);var d=i.parentNode?i.parentNode.offsetHeight:0;switch(d!=s.parentHeight&&(s.parentHeight=d,t+=1),this.getOption("orientation")){case"bottom":s.minorLabelHeight=o?s.minorCharHeight:0,s.majorLabelHeight=r?s.majorCharHeight:0,s.minorLabelTop=0,s.majorLabelTop=s.minorLabelTop+s.minorLabelHeight,s.minorLineTop=-this.top,s.minorLineHeight=Math.max(this.top+s.majorLabelHeight,0),s.minorLineWidth=1,s.majorLineTop=-this.top,s.majorLineHeight=Math.max(this.top+s.minorLabelHeight+s.majorLabelHeight,0),s.majorLineWidth=1,s.lineTop=0;break;case"top":s.minorLabelHeight=o?s.minorCharHeight:0,s.majorLabelHeight=r?s.majorCharHeight:0,s.majorLabelTop=0,s.minorLabelTop=s.majorLabelTop+s.majorLabelHeight,s.minorLineTop=s.minorLabelTop,s.minorLineHeight=Math.max(d-s.majorLabelHeight-this.top),s.minorLineWidth=1,s.majorLineTop=0,s.majorLineHeight=Math.max(d-this.top),s.majorLineWidth=1,s.lineTop=s.majorLabelHeight+s.minorLabelHeight;break;default:throw Error('Unkown orientation "'+this.getOption("orientation")+'"')}var l=s.minorLabelHeight+s.majorLabelHeight;t+=e(this,"width",i.offsetWidth),t+=e(this,"height",l),this._updateConversion();var u=C.convert(n.start,"Date"),c=C.convert(n.end,"Date"),p=this.toTime(5*(s.minorCharWidth||10))-this.toTime(0);this.step=new TimeStep(u,c,p),t+=e(s.range,"start",u.valueOf()),t+=e(s.range,"end",c.valueOf()),t+=e(s.range,"minimumStep",p.valueOf())}return t>0},p.prototype._updateConversion=function(){var t=this.range;if(!t)throw Error("No range configured");this.conversion=t.conversion?t.conversion(this.width):h.conversion(t.start,t.end,this.width)},f.prototype=new u,f.types={box:g,range:y,point:v},f.prototype.setOptions=l.prototype.setOptions,f.prototype.setRange=function(t){if(!(t instanceof h||t&&t.start&&t.end))throw new TypeError("Range must be an instance of Range, or an object containing start and end.");this.range=t},f.prototype.repaint=function(){var t=0,e=C.updateProperty,i=C.option.asSize,n=this.options,s=this.getOption("orientation"),o=this.defaultOptions,r=this.frame;if(!r){r=document.createElement("div"),r.className="itemset";var a=n.className;a&&C.addClassName(r,C.option.asString(a));var h=document.createElement("div");h.className="background",r.appendChild(h),this.dom.background=h;var d=document.createElement("div");d.className="foreground",r.appendChild(d),this.dom.foreground=d;var l=document.createElement("div");l.className="itemset-axis",this.dom.axis=l,this.frame=r,t+=1}if(!this.parent)throw Error("Cannot repaint itemset: no parent attached");var u=this.parent.getContainer();if(!u)throw Error("Cannot repaint itemset: parent has no container element");r.parentNode||(u.appendChild(r),t+=1),this.dom.axis.parentNode||(u.appendChild(this.dom.axis),t+=1),t+=e(r.style,"left",i(n.left,"0px")),t+=e(r.style,"top",i(n.top,"0px")),t+=e(r.style,"width",i(n.width,"100%")),t+=e(r.style,"height",i(n.height,this.height+"px")),t+=e(this.dom.axis.style,"left",i(n.left,"0px")),t+=e(this.dom.axis.style,"width",i(n.width,"100%")),t+="bottom"==s?e(this.dom.axis.style,"top",this.height+this.top+"px"):e(this.dom.axis.style,"top",this.top+"px"),this._updateConversion();var c=this,p=this.queue,m=this.itemsData,g=this.items,v={};return Object.keys(p).forEach(function(e){var i=p[e],s=g[e];switch(i){case"add":case"update":var r=m&&m.get(e,v);if(r){var a=r.type||r.start&&r.end&&"range"||n.type||"box",h=f.types[a];if(s&&(h&&s instanceof h?(s.data=r,t++):(t+=s.hide(),s=null)),!s){if(!h)throw new TypeError('Unknown item type "'+a+'"');s=new h(c,r,n,o),t++}s.repaint(),g[e]=s}delete p[e];break;case"remove":s&&(t+=s.hide()),delete g[e],delete p[e];break;default:console.log('Error: unknown action "'+i+'"')}}),C.forEach(this.items,function(e){e.visible?(t+=e.show(),e.reposition()):t+=e.hide()}),t>0},f.prototype.getForeground=function(){return this.dom.foreground},f.prototype.getBackground=function(){return this.dom.background},f.prototype.getAxis=function(){return this.dom.axis},f.prototype.reflow=function(){var t=0,e=this.options,i=e.margin&&e.margin.axis||this.defaultOptions.margin.axis,n=e.margin&&e.margin.item||this.defaultOptions.margin.item,s=C.updateProperty,o=C.option.asNumber,r=C.option.asSize,a=this.frame;if(a){this._updateConversion(),C.forEach(this.items,function(e){t+=e.reflow()}),this.stack.update();var h,d=o(e.maxHeight),l=null!=r(e.height);if(l)h=a.offsetHeight;else{var u=this.stack.ordered;if(u.length){var c=u[0].top,p=u[0].top+u[0].height;C.forEach(u,function(t){c=Math.min(c,t.top),p=Math.max(p,t.top+t.height)}),h=p-c+i+n}else h=i+n}null!=d&&(h=Math.min(h,d)),t+=s(this,"height",h),t+=s(this,"top",a.offsetTop),t+=s(this,"left",a.offsetLeft),t+=s(this,"width",a.offsetWidth)}else t+=1;return t>0},f.prototype.hide=function(){var t=!1;return this.frame&&this.frame.parentNode&&(this.frame.parentNode.removeChild(this.frame),t=!0),this.dom.axis&&this.dom.axis.parentNode&&(this.dom.axis.parentNode.removeChild(this.dom.axis),t=!0),t},f.prototype.setItems=function(t){var e,i=this,n=this.itemsData;if(t){if(!(t instanceof o||t instanceof r))throw new TypeError("Data must be an instance of DataSet");this.itemsData=t}else this.itemsData=null;if(n&&(C.forEach(this.listeners,function(t,e){n.unsubscribe(e,t)}),e=n.getIds(),this._onRemove(e)),this.itemsData){var s=this.id;C.forEach(this.listeners,function(t,e){i.itemsData.subscribe(e,t,s)}),e=this.itemsData.getIds(),this._onAdd(e)}},f.prototype.getItems=function(){return this.itemsData},f.prototype._onUpdate=function(t){this._toQueue("update",t)},f.prototype._onAdd=function(t){this._toQueue("add",t)},f.prototype._onRemove=function(t){this._toQueue("remove",t)},f.prototype._toQueue=function(t,e){var i=this.queue;e.forEach(function(e){i[e]=t}),this.controller&&this.requestRepaint()},f.prototype._updateConversion=function(){var t=this.range;if(!t)throw Error("No range configured");this.conversion=t.conversion?t.conversion(this.width):h.conversion(t.start,t.end,this.width)},f.prototype.toTime=function(t){var e=this.conversion;return new Date(t/e.factor+e.offset)},f.prototype.toScreen=function(t){var e=this.conversion;return(t.valueOf()-e.offset)*e.factor},m.prototype.select=function(){this.selected=!0},m.prototype.unselect=function(){this.selected=!1},m.prototype.show=function(){return!1},m.prototype.hide=function(){return!1},m.prototype.repaint=function(){return!1},m.prototype.reflow=function(){return!1},g.prototype=new m(null,null),g.prototype.select=function(){this.selected=!0},g.prototype.unselect=function(){this.selected=!1},g.prototype.repaint=function(){var t=!1,e=this.dom;if(e||(this._create(),e=this.dom,t=!0),e){if(!this.parent)throw Error("Cannot repaint item: no parent attached");var i=this.parent.getForeground();if(!i)throw Error("Cannot repaint time axis: parent has no foreground container element");var n=this.parent.getBackground();if(!n)throw Error("Cannot repaint time axis: parent has no background container element");var s=this.parent.getAxis();if(!n)throw Error("Cannot repaint time axis: parent has no axis container element");if(e.box.parentNode||(i.appendChild(e.box),t=!0),e.line.parentNode||(n.appendChild(e.line),t=!0),e.dot.parentNode||(s.appendChild(e.dot),t=!0),this.data.content!=this.content){if(this.content=this.data.content,this.content instanceof Element)e.content.innerHTML="",e.content.appendChild(this.content);else{if(void 0==this.data.content)throw Error('Property "content" missing in item '+this.data.id);e.content.innerHTML=this.content}t=!0}var o=(this.data.className?" "+this.data.className:"")+(this.selected?" selected":"");this.className!=o&&(this.className=o,e.box.className="item box"+o,e.line.className="item line"+o,e.dot.className="item dot"+o,t=!0)}return t},g.prototype.show=function(){return this.dom&&this.dom.box.parentNode?!1:this.repaint()},g.prototype.hide=function(){var t=!1,e=this.dom;return e&&(e.box.parentNode&&(e.box.parentNode.removeChild(e.box),t=!0),e.line.parentNode&&e.line.parentNode.removeChild(e.line),e.dot.parentNode&&e.dot.parentNode.removeChild(e.dot)),t},g.prototype.reflow=function(){var t,e,i,n,s,o,r,a,h,d,l,u,c=0;if(void 0==this.data.start)throw Error('Property "start" missing in item '+this.data.id);if(l=this.data,u=this.parent&&this.parent.range,l&&u){var p=u.end-u.start;this.visible=l.start>u.start-p&&l.start0},g.prototype._create=function(){var t=this.dom;t||(this.dom=t={},t.box=document.createElement("DIV"),t.content=document.createElement("DIV"),t.content.className="content",t.box.appendChild(t.content),t.line=document.createElement("DIV"),t.line.className="line",t.dot=document.createElement("DIV"),t.dot.className="dot")},g.prototype.reposition=function(){var t=this.dom,e=this.props,i=this.options.orientation||this.defaultOptions.orientation;if(t){var n=t.box,s=t.line,o=t.dot;n.style.left=this.left+"px",n.style.top=this.top+"px",s.style.left=e.line.left+"px","top"==i?(s.style.top="0px",s.style.height=this.top+"px"):(s.style.top=this.top+this.height+"px",s.style.height=Math.max(this.parent.height-this.top-this.height+this.props.dot.height/2,0)+"px"),o.style.left=e.dot.left+"px",o.style.top=e.dot.top+"px"}},v.prototype=new m(null,null),v.prototype.select=function(){this.selected=!0},v.prototype.unselect=function(){this.selected=!1},v.prototype.repaint=function(){var t=!1,e=this.dom;if(e||(this._create(),e=this.dom,t=!0),e){if(!this.parent)throw Error("Cannot repaint item: no parent attached");var i=this.parent.getForeground();if(!i)throw Error("Cannot repaint time axis: parent has no foreground container element");if(e.point.parentNode||(i.appendChild(e.point),i.appendChild(e.point),t=!0),this.data.content!=this.content){if(this.content=this.data.content,this.content instanceof Element)e.content.innerHTML="",e.content.appendChild(this.content);else{if(void 0==this.data.content)throw Error('Property "content" missing in item '+this.data.id);e.content.innerHTML=this.content}t=!0}var n=(this.data.className?" "+this.data.className:"")+(this.selected?" selected":"");this.className!=n&&(this.className=n,e.point.className="item point"+n,t=!0)}return t},v.prototype.show=function(){return this.dom&&this.dom.point.parentNode?!1:this.repaint()},v.prototype.hide=function(){var t=!1,e=this.dom;return e&&e.point.parentNode&&(e.point.parentNode.removeChild(e.point),t=!0),t},v.prototype.reflow=function(){var t,e,i,n,s,o,r,a,h,d,l=0;if(void 0==this.data.start)throw Error('Property "start" missing in item '+this.data.id);if(h=this.data,d=this.parent&&this.parent.range,h&&d){var u=d.end-d.start;this.visible=h.start>d.start-u&&h.start0},v.prototype._create=function(){var t=this.dom;t||(this.dom=t={},t.point=document.createElement("div"),t.content=document.createElement("div"),t.content.className="content",t.point.appendChild(t.content),t.dot=document.createElement("div"),t.dot.className="dot",t.point.appendChild(t.dot))},v.prototype.reposition=function(){var t=this.dom,e=this.props;t&&(t.point.style.top=this.top+"px",t.point.style.left=this.left+"px",t.content.style.marginLeft=e.content.marginLeft+"px",t.dot.style.top=e.dot.top+"px")},y.prototype=new m(null,null),y.prototype.select=function(){this.selected=!0},y.prototype.unselect=function(){this.selected=!1},y.prototype.repaint=function(){var t=!1,e=this.dom;if(e||(this._create(),e=this.dom,t=!0),e){if(!this.parent)throw Error("Cannot repaint item: no parent attached");var i=this.parent.getForeground();if(!i)throw Error("Cannot repaint time axis: parent has no foreground container element");if(e.box.parentNode||(i.appendChild(e.box),t=!0),this.data.content!=this.content){if(this.content=this.data.content,this.content instanceof Element)e.content.innerHTML="",e.content.appendChild(this.content);else{if(void 0==this.data.content)throw Error('Property "content" missing in item '+this.data.id); -e.content.innerHTML=this.content}t=!0}var n=this.data.className?" "+this.data.className:"";this.className!=n&&(this.className=n,e.box.className="item range"+n,t=!0)}return t},y.prototype.show=function(){return this.dom&&this.dom.box.parentNode?!1:this.repaint()},y.prototype.hide=function(){var t=!1,e=this.dom;return e&&e.box.parentNode&&(e.box.parentNode.removeChild(e.box),t=!0),t},y.prototype.reflow=function(){var t,e,i,n,s,o,r,a,h,d,l,u,c,p,f,m,g=0;if(void 0==this.data.start)throw Error('Property "start" missing in item '+this.data.id);if(void 0==this.data.end)throw Error('Property "end" missing in item '+this.data.id);return h=this.data,d=this.parent&&this.parent.range,this.visible=h&&d?h.startd.start:!1,this.visible&&(t=this.dom,t?(e=this.props,i=this.options,o=this.parent,r=o.toScreen(this.data.start),a=o.toScreen(this.data.end),l=C.updateProperty,u=t.box,c=o.width,f=i.orientation||this.defaultOptions.orientation,n=i.margin&&i.margin.axis||this.defaultOptions.margin.axis,s=i.padding||this.defaultOptions.padding,g+=l(e.content,"width",t.content.offsetWidth),g+=l(this,"height",u.offsetHeight),-c>r&&(r=-c),a>2*c&&(a=2*c),p=0>r?Math.min(-r,a-r-e.content.width-2*s):0,g+=l(e.content,"left",p),"top"==f?(m=n,g+=l(this,"top",m)):(m=o.height-this.height-n,g+=l(this,"top",m)),g+=l(this,"left",r),g+=l(this,"width",Math.max(a-r,1))):g+=1),g>0},y.prototype._create=function(){var t=this.dom;t||(this.dom=t={},t.box=document.createElement("div"),t.content=document.createElement("div"),t.content.className="content",t.box.appendChild(t.content))},y.prototype.reposition=function(){var t=this.dom,e=this.props;t&&(t.box.style.top=this.top+"px",t.box.style.left=this.left+"px",t.box.style.width=this.width+"px",t.content.style.left=e.content.left+"px")},b.prototype=new l,b.prototype.setOptions=l.prototype.setOptions,b.prototype.getContainer=function(){return this.parent.getContainer()},b.prototype.setItems=function(t){if(this.itemset&&(this.itemset.hide(),this.itemset.setItems(),this.parent.controller.remove(this.itemset),this.itemset=null),t){var e=this.groupId,i=Object.create(this.options);this.itemset=new f(this,null,i),this.itemset.setRange(this.parent.range),this.view=new r(t,{filter:function(t){return t.group==e}}),this.itemset.setItems(this.view),this.parent.controller.add(this.itemset)}},b.prototype.repaint=function(){return!1},b.prototype.reflow=function(){var t=0,e=C.updateProperty;if(t+=e(this,"top",this.itemset?this.itemset.top:0),t+=e(this,"height",this.itemset?this.itemset.height:0),this.label){var i=this.label.firstChild;t+=e(this.props.label,"width",i.clientWidth),t+=e(this.props.label,"height",i.clientHeight)}else t+=e(this.props.label,"width",0),t+=e(this.props.label,"height",0);return t>0},w.prototype=new u,w.prototype.setOptions=l.prototype.setOptions,w.prototype.setRange=function(){},w.prototype.setItems=function(t){this.itemsData=t;for(var e in this.groups)if(this.groups.hasOwnProperty(e)){var i=this.groups[e];i.setItems(t)}},w.prototype.getItems=function(){return this.itemsData},w.prototype.setRange=function(t){this.range=t},w.prototype.setGroups=function(t){var e,i=this;if(this.groupsData&&(C.forEach(this.listeners,function(t,e){i.groupsData.unsubscribe(e,t)}),e=this.groupsData.getIds(),this._onRemove(e)),t?t instanceof o?this.groupsData=t:(this.groupsData=new o({convert:{start:"Date",end:"Date"}}),this.groupsData.add(t)):this.groupsData=null,this.groupsData){var n=this.id;C.forEach(this.listeners,function(t,e){i.groupsData.subscribe(e,t,n)}),e=this.groupsData.getIds(),this._onAdd(e)}},w.prototype.getGroups=function(){return this.groupsData},w.prototype.repaint=function(){var t,e,i,n,s=0,o=C.updateProperty,r=C.option.asSize,a=C.option.asElement,h=this.options,d=this.dom.frame,l=this.dom.labels;if(!this.parent)throw Error("Cannot repaint groupset: no parent attached");var u=this.parent.getContainer();if(!u)throw Error("Cannot repaint groupset: parent has no container element");if(!d){d=document.createElement("div"),d.className="groupset",this.dom.frame=d;var c=h.className;c&&C.addClassName(d,C.option.asString(c)),s+=1}d.parentNode||(u.appendChild(d),s+=1);var p=a(h.labelContainer);if(!p)throw Error('Cannot repaint groupset: option "labelContainer" not defined');l||(l=document.createElement("div"),l.className="labels",this.dom.labels=l),l.parentNode&&l.parentNode==p||(l.parentNode&&l.parentNode.removeChild(l.parentNode),p.appendChild(l)),s+=o(d.style,"height",r(h.height,this.height+"px")),s+=o(d.style,"top",r(h.top,"0px")),s+=o(d.style,"left",r(h.left,"0px")),s+=o(d.style,"width",r(h.width,"100%")),s+=o(l.style,"top",r(h.top,"0px"));var f=this,m=this.queue,g=this.groups,v=this.groupsData,y=Object.keys(m);if(y.length){y.forEach(function(t){var e=m[t],i=g[t];switch(e){case"add":case"update":if(!i){var n=Object.create(f.options);i=new b(f,t,n),i.setItems(f.itemsData),g[t]=i,f.controller.add(i)}i.data=v.get(t),delete m[t];break;case"remove":i&&(i.setItems(),delete g[t],f.controller.remove(i)),delete m[t];break;default:console.log('Error: unknown action "'+e+'"')}});var w=this.groupsData.getIds({order:this.options.groupsOrder});for(t=0;w.length>t;t++)(function(t,e){var i=0;e&&(i=function(){return e.top+e.height}),t.setOptions({top:i})})(g[w[t]],g[w[t-1]]);for(;l.firstChild;)l.removeChild(l.firstChild);for(t=0;w.length>t;t++)e=w[t],n=this._createLabel(e),l.appendChild(n);s++}for(e in g)g.hasOwnProperty(e)&&(i=g[e],n=i.label,n&&(n.style.top=i.top+"px",n.style.height=i.height+"px"));return s>0},w.prototype._createLabel=function(t){var e=this.groups[t],i=document.createElement("div");i.className="label";var n=document.createElement("div");n.className="inner",i.appendChild(n);var s=e.data&&e.data.content;s instanceof Element?n.appendChild(s):void 0!=s&&(n.innerHTML=s);var o=e.data&&e.data.className;return o&&C.addClassName(i,o),e.label=i,i},w.prototype.getContainer=function(){return this.dom.frame},w.prototype.getLabelsWidth=function(){return this.props.labels.width},w.prototype.reflow=function(){var t,e,i=0,n=this.options,s=C.updateProperty,o=C.option.asNumber,r=C.option.asSize,a=this.dom.frame;if(a){var h,d=o(n.maxHeight),l=null!=r(n.height);if(l)h=a.offsetHeight;else{h=0;for(t in this.groups)this.groups.hasOwnProperty(t)&&(e=this.groups[t],h+=e.height)}null!=d&&(h=Math.min(h,d)),i+=s(this,"height",h),i+=s(this,"top",a.offsetTop),i+=s(this,"left",a.offsetLeft),i+=s(this,"width",a.offsetWidth)}var u=0;for(t in this.groups)if(this.groups.hasOwnProperty(t)){e=this.groups[t];var c=e.props&&e.props.label&&e.props.label.width||0;u=Math.max(u,c)}return i+=s(this.props.labels,"width",u),i>0},w.prototype.hide=function(){return this.dom.frame&&this.dom.frame.parentNode?(this.dom.frame.parentNode.removeChild(this.dom.frame),!0):!1},w.prototype.show=function(){return this.dom.frame&&this.dom.frame.parentNode?!1:this.repaint()},w.prototype._onUpdate=function(t){this._toQueue(t,"update")},w.prototype._onAdd=function(t){this._toQueue(t,"add")},w.prototype._onRemove=function(t){this._toQueue(t,"remove")},w.prototype._toQueue=function(t,e){var i=this.queue;t.forEach(function(t){i[t]=e}),this.controller&&this.requestRepaint()},_.prototype.setOptions=function(t){t&&C.extend(this.options,t),this.controller.reflow(),this.controller.repaint()},_.prototype.setItems=function(t){var e,i=null==this.itemsData;if(t?t instanceof o&&(e=t):e=null,t instanceof o||(e=new o({convert:{start:"Date",end:"Date"}}),e.add(t)),this.itemsData=e,this.content.setItems(e),i&&(void 0==this.options.start||void 0==this.options.end)){var n=this.getItemRange(),s=n.min,r=n.max;if(null!=s&&null!=r){var a=r.valueOf()-s.valueOf();0>=a&&(a=864e5),s=new Date(s.valueOf()-.05*a),r=new Date(r.valueOf()+.05*a)}void 0!=this.options.start&&(s=new Date(this.options.start.valueOf())),void 0!=this.options.end&&(r=new Date(this.options.end.valueOf())),(null!=s||null!=r)&&this.range.setRange(s,r)}},_.prototype.setGroups=function(t){var e=this;this.groupsData=t;var i=this.groupsData?w:f;if(!(this.content instanceof i)){this.content&&(this.content.hide(),this.content.setItems&&this.content.setItems(),this.content.setGroups&&this.content.setGroups(),this.controller.remove(this.content));var n=Object.create(this.options);C.extend(n,{top:function(){return"top"==e.options.orientation?e.timeaxis.height:e.itemPanel.height-e.timeaxis.height-e.content.height},left:null,width:"100%",height:function(){return e.options.height?e.itemPanel.height-e.timeaxis.height:null},maxHeight:function(){if(e.options.maxHeight){if(!C.isNumber(e.options.maxHeight))throw new TypeError("Number expected for property maxHeight");return e.options.maxHeight-e.timeaxis.height}return null},labelContainer:function(){return e.labelPanel.getContainer()}}),this.content=new i(this.itemPanel,[this.timeaxis],n),this.content.setRange&&this.content.setRange(this.range),this.content.setItems&&this.content.setItems(this.itemsData),this.content.setGroups&&this.content.setGroups(this.groupsData),this.controller.add(this.content)}},_.prototype.getItemRange=function(){var t=this.itemsData,e=null,i=null;if(t){var n=t.min("start");e=n?n.start.valueOf():null;var s=t.max("start");s&&(i=s.start.valueOf());var o=t.max("end");o&&(i=null==i?o.end.valueOf():Math.max(i,o.end.valueOf()))}return{min:null!=e?new Date(e):null,max:null!=i?new Date(i):null}},function(t){function e(t){return M=t,c()}function i(){D=0,C=M.charAt(0)}function n(){D++,C=M.charAt(D)}function s(){return M.charAt(D+1)}function o(t){return L.test(t)}function r(t,e){if(t||(t={}),e)for(var i in e)e.hasOwnProperty(i)&&(t[i]=e[i]);return t}function a(t,e,i){for(var n=e.split("."),s=t;n.length;){var o=n.shift();n.length?(s[o]||(s[o]={}),s=s[o]):s[o]=i}}function h(t,e){for(var i,n,s=null,o=[t],a=t;a.parent;)o.push(a.parent),a=a.parent;if(a.nodes)for(i=0,n=a.nodes.length;n>i;i++)if(e.id===a.nodes[i].id){s=a.nodes[i];break}for(s||(s={id:e.id},t.node&&(s.attr=r(s.attr,t.node))),i=o.length-1;i>=0;i--){var h=o[i];h.nodes||(h.nodes=[]),-1==h.nodes.indexOf(s)&&h.nodes.push(s)}e.attr&&(s.attr=r(s.attr,e.attr))}function d(t,e){if(t.edges||(t.edges=[]),t.edges.push(e),t.edge){var i=r({},t.edge);e.attr=r(i,e.attr)}}function l(t,e,i,n,s){var o={from:e,to:i,type:n};return t.edge&&(o.attr=r({},t.edge)),o.attr=r(o.attr||{},s),o}function u(){for(N=x.NULL,O="";" "==C||" "==C||"\n"==C||"\r"==C;)n();do{var t=!1;if("#"==C){for(var e=D-1;" "==M.charAt(e)||" "==M.charAt(e);)e--;if("\n"==M.charAt(e)||""==M.charAt(e)){for(;""!=C&&"\n"!=C;)n();t=!0}}if("/"==C&&"/"==s()){for(;""!=C&&"\n"!=C;)n();t=!0}if("/"==C&&"*"==s()){for(;""!=C;){if("*"==C&&"/"==s()){n(),n();break}n()}t=!0}for(;" "==C||" "==C||"\n"==C||"\r"==C;)n()}while(t);if(""==C)return N=x.DELIMITER,void 0;var i=C+s();if(S[i])return N=x.DELIMITER,O=i,n(),n(),void 0;if(S[C])return N=x.DELIMITER,O=C,n(),void 0;if(o(C)||"-"==C){for(O+=C,n();o(C);)O+=C,n();return"false"==O?O=!1:"true"==O?O=!0:isNaN(Number(O))||(O=Number(O)),N=x.IDENTIFIER,void 0}if('"'==C){for(n();""!=C&&('"'!=C||'"'==C&&'"'==s());)O+=C,'"'==C&&n(),n();if('"'!=C)throw w('End of string " expected');return n(),N=x.IDENTIFIER,void 0}for(N=x.UNKNOWN;""!=C;)O+=C,n();throw new SyntaxError('Syntax error in part "'+_(O,30)+'"')}function c(){var t={};if(i(),u(),"strict"==O&&(t.strict=!0,u()),("graph"==O||"digraph"==O)&&(t.type=O,u()),N==x.IDENTIFIER&&(t.id=O,u()),"{"!=O)throw w("Angle bracket { expected");if(u(),p(t),"}"!=O)throw w("Angle bracket } expected");if(u(),""!==O)throw w("End of file expected");return u(),delete t.node,delete t.edge,delete t.graph,t}function p(t){for(;""!==O&&"}"!=O;)f(t),";"==O&&u()}function f(t){var e=m(t);if(e)return y(t,e),void 0;var i=g(t);if(!i){if(N!=x.IDENTIFIER)throw w("Identifier expected");var n=O;if(u(),"="==O){if(u(),N!=x.IDENTIFIER)throw w("Identifier expected");t[n]=O,u()}else v(t,n)}}function m(t){var e=null;if("subgraph"==O&&(e={},e.type="subgraph",u(),N==x.IDENTIFIER&&(e.id=O,u())),"{"==O){if(u(),e||(e={}),e.parent=t,e.node=t.node,e.edge=t.edge,e.graph=t.graph,p(e),"}"!=O)throw w("Angle bracket } expected");u(),delete e.node,delete e.edge,delete e.graph,delete e.parent,t.subgraphs||(t.subgraphs=[]),t.subgraphs.push(e)}return e}function g(t){return"node"==O?(u(),t.node=b(),"node"):"edge"==O?(u(),t.edge=b(),"edge"):"graph"==O?(u(),t.graph=b(),"graph"):null}function v(t,e){var i={id:e},n=b();n&&(i.attr=n),h(t,i),y(t,e)}function y(t,e){for(;"->"==O||"--"==O;){var i,n=O;u();var s=m(t);if(s)i=s;else{if(N!=x.IDENTIFIER)throw w("Identifier or subgraph expected");i=O,h(t,{id:i}),u()}var o=b(),r=l(t,e,i,n,o);d(t,r),e=i}}function b(){for(var t=null;"["==O;){for(u(),t={};""!==O&&"]"!=O;){if(N!=x.IDENTIFIER)throw w("Attribute name expected");var e=O;if(u(),"="!=O)throw w("Equal sign = expected");if(u(),N!=x.IDENTIFIER)throw w("Attribute value expected");var i=O;a(t,e,i),u(),","==O&&u()}if("]"!=O)throw w("Bracket ] expected");u()}return t}function w(t){return new SyntaxError(t+', got "'+_(O,30)+'" (char '+D+")")}function _(t,e){return e>=t.length?t:t.substr(0,27)+"..."}function E(t,e,i){t instanceof Array?t.forEach(function(t){e instanceof Array?e.forEach(function(e){i(t,e)}):i(t,e)}):e instanceof Array?e.forEach(function(e){i(t,e)}):i(t,e)}function T(t){function i(t){var e={from:t.from,to:t.to};return r(e,t.attr),e.style="->"==t.type?"arrow":"line",e}var n=e(t),s={nodes:[],edges:[],options:{}};return n.nodes&&n.nodes.forEach(function(t){var e={id:t.id,label:(t.label||t.id)+""};r(e,t.attr),e.image&&(e.shape="image"),s.nodes.push(e)}),n.edges&&n.edges.forEach(function(t){var e,n;e=t.from instanceof Object?t.from.nodes:{id:t.from},n=t.to instanceof Object?t.to.nodes:{id:t.to},t.from instanceof Object&&t.from.edges&&t.from.edges.forEach(function(t){var e=i(t);s.edges.push(e)}),E(e,n,function(e,n){var o=l(s,e.id,n.id,t.type,t.attr),r=i(o);s.edges.push(r)}),t.to instanceof Object&&t.to.edges&&t.to.edges.forEach(function(t){var e=i(t);s.edges.push(e)})}),n.attr&&(s.options=n.attr),s}var x={NULL:0,DELIMITER:1,IDENTIFIER:2,UNKNOWN:3},S={"{":!0,"}":!0,"[":!0,"]":!0,";":!0,"=":!0,",":!0,"->":!0,"--":!0},M="",D=0,C="",O="",N=x.NULL,L=/[a-zA-Z_0-9.:#]/;t.parseDOT=e,t.DOTToGraph=T}(C!==void 0?C:n),"undefined"!=typeof CanvasRenderingContext2D&&(CanvasRenderingContext2D.prototype.circle=function(t,e,i){this.beginPath(),this.arc(t,e,i,0,2*Math.PI,!1)},CanvasRenderingContext2D.prototype.square=function(t,e,i){this.beginPath(),this.rect(t-i,e-i,2*i,2*i)},CanvasRenderingContext2D.prototype.triangle=function(t,e,i){this.beginPath();var n=2*i,s=n/2,o=Math.sqrt(3)/6*n,r=Math.sqrt(n*n-s*s);this.moveTo(t,e-(r-o)),this.lineTo(t+s,e+o),this.lineTo(t-s,e+o),this.lineTo(t,e-(r-o)),this.closePath()},CanvasRenderingContext2D.prototype.triangleDown=function(t,e,i){this.beginPath();var n=2*i,s=n/2,o=Math.sqrt(3)/6*n,r=Math.sqrt(n*n-s*s);this.moveTo(t,e+(r-o)),this.lineTo(t+s,e-o),this.lineTo(t-s,e-o),this.lineTo(t,e+(r-o)),this.closePath()},CanvasRenderingContext2D.prototype.star=function(t,e,i){this.beginPath();for(var n=0;10>n;n++){var s=0===n%2?1.3*i:.5*i;this.lineTo(t+s*Math.sin(2*n*Math.PI/10),e-s*Math.cos(2*n*Math.PI/10))}this.closePath()},CanvasRenderingContext2D.prototype.roundRect=function(t,e,i,n,s){var o=Math.PI/180;0>i-2*s&&(s=i/2),0>n-2*s&&(s=n/2),this.beginPath(),this.moveTo(t+s,e),this.lineTo(t+i-s,e),this.arc(t+i-s,e+s,s,270*o,360*o,!1),this.lineTo(t+i,e+n-s),this.arc(t+i-s,e+n-s,s,0,90*o,!1),this.lineTo(t+s,e+n),this.arc(t+s,e+n-s,s,90*o,180*o,!1),this.lineTo(t,e+s),this.arc(t+s,e+s,s,180*o,270*o,!1)},CanvasRenderingContext2D.prototype.ellipse=function(t,e,i,n){var s=.5522848,o=i/2*s,r=n/2*s,a=t+i,h=e+n,d=t+i/2,l=e+n/2;this.beginPath(),this.moveTo(t,l),this.bezierCurveTo(t,l-r,d-o,e,d,e),this.bezierCurveTo(d+o,e,a,l-r,a,l),this.bezierCurveTo(a,l+r,d+o,h,d,h),this.bezierCurveTo(d-o,h,t,l+r,t,l)},CanvasRenderingContext2D.prototype.database=function(t,e,i,n){var s=1/3,o=i,r=n*s,a=.5522848,h=o/2*a,d=r/2*a,l=t+o,u=e+r,c=t+o/2,p=e+r/2,f=e+(n-r/2),m=e+n;this.beginPath(),this.moveTo(l,p),this.bezierCurveTo(l,p+d,c+h,u,c,u),this.bezierCurveTo(c-h,u,t,p+d,t,p),this.bezierCurveTo(t,p-d,c-h,e,c,e),this.bezierCurveTo(c+h,e,l,p-d,l,p),this.lineTo(l,f),this.bezierCurveTo(l,f+d,c+h,m,c,m),this.bezierCurveTo(c-h,m,t,f+d,t,f),this.lineTo(t,p)},CanvasRenderingContext2D.prototype.arrow=function(t,e,i,n){var s=t-n*Math.cos(i),o=e-n*Math.sin(i),r=t-.9*n*Math.cos(i),a=e-.9*n*Math.sin(i),h=s+n/3*Math.cos(i+.5*Math.PI),d=o+n/3*Math.sin(i+.5*Math.PI),l=s+n/3*Math.cos(i-.5*Math.PI),u=o+n/3*Math.sin(i-.5*Math.PI);this.beginPath(),this.moveTo(t,e),this.lineTo(h,d),this.lineTo(r,a),this.lineTo(l,u),this.closePath()},CanvasRenderingContext2D.prototype.dashedLine=function(t,e,i,n,s){s||(s=[10,5]),0==c&&(c=.001);var o=s.length;this.moveTo(t,e);for(var r=i-t,a=n-e,h=a/r,d=Math.sqrt(r*r+a*a),l=0,u=!0;d>=.1;){var c=s[l++%o];c>d&&(c=d);var p=Math.sqrt(c*c/(1+h*h));0>r&&(p=-p),t+=p,e+=h*p,this[u?"lineTo":"moveTo"](t,e),d-=c,u=!u}}),E.prototype.attachEdge=function(t){-1==this.edges.indexOf(t)&&this.edges.push(t),this._updateMass()},E.prototype.detachEdge=function(t){var e=this.edges.indexOf(t);-1!=e&&this.edges.splice(e,1),this._updateMass()},E.prototype._updateMass=function(){this.mass=50+20*this.edges.length},E.prototype.setProperties=function(t,e){if(t){if(void 0!=t.id&&(this.id=t.id),void 0!=t.label&&(this.label=t.label),void 0!=t.title&&(this.title=t.title),void 0!=t.group&&(this.group=t.group),void 0!=t.x&&(this.x=t.x),void 0!=t.y&&(this.y=t.y),void 0!=t.value&&(this.value=t.value),void 0===this.id)throw"Node must have an id";if(this.group){var i=this.grouplist.get(this.group);for(var n in i)i.hasOwnProperty(n)&&(this[n]=i[n])}if(void 0!=t.shape&&(this.shape=t.shape),void 0!=t.image&&(this.image=t.image),void 0!=t.radius&&(this.radius=t.radius),void 0!=t.color&&(this.color=E.parseColor(t.color)),void 0!=t.fontColor&&(this.fontColor=t.fontColor),void 0!=t.fontSize&&(this.fontSize=t.fontSize),void 0!=t.fontFace&&(this.fontFace=t.fontFace),void 0!=this.image){if(!this.imagelist)throw"No imagelist provided";this.imageObj=this.imagelist.load(this.image)}switch(this.xFixed=this.xFixed||void 0!=t.x,this.yFixed=this.yFixed||void 0!=t.y,this.radiusFixed=this.radiusFixed||void 0!=t.radius,"image"==this.shape&&(this.radiusMin=e.nodes.widthMin,this.radiusMax=e.nodes.widthMax),this.shape){case"database":this.draw=this._drawDatabase,this.resize=this._resizeDatabase;break;case"box":this.draw=this._drawBox,this.resize=this._resizeBox;break;case"circle":this.draw=this._drawCircle,this.resize=this._resizeCircle;break;case"ellipse":this.draw=this._drawEllipse,this.resize=this._resizeEllipse;break;case"image":this.draw=this._drawImage,this.resize=this._resizeImage;break;case"text":this.draw=this._drawText,this.resize=this._resizeText;break;case"dot":this.draw=this._drawDot,this.resize=this._resizeShape;break;case"square":this.draw=this._drawSquare,this.resize=this._resizeShape;break;case"triangle":this.draw=this._drawTriangle,this.resize=this._resizeShape;break;case"triangleDown":this.draw=this._drawTriangleDown,this.resize=this._resizeShape;break;case"star":this.draw=this._drawStar,this.resize=this._resizeShape;break;default:this.draw=this._drawEllipse,this.resize=this._resizeEllipse}this._reset()}},E.parseColor=function(t){var e;return C.isString(t)?e={border:t,background:t,highlight:{border:t,background:t}}:(e={},e.background=t.background||"white",e.border=t.border||e.background,C.isString(t.highlight)?e.highlight={border:t.highlight,background:t.highlight}:(e.highlight={},e.highlight.background=t.highlight&&t.highlight.background||e.background,e.highlight.border=t.highlight&&t.highlight.border||e.border)),e},E.prototype.select=function(){this.selected=!0,this._reset()},E.prototype.unselect=function(){this.selected=!1,this._reset()},E.prototype._reset=function(){this.width=void 0,this.height=void 0},E.prototype.getTitle=function(){return this.title},E.prototype.distanceToBorder=function(t,e){var i=1;switch(this.width||this.resize(t),this.shape){case"circle":case"dot":return this.radius+i;case"ellipse":var n=this.width/2,s=this.height/2,o=Math.sin(e)*n,r=Math.cos(e)*s;return n*s/Math.sqrt(o*o+r*r);case"box":case"image":case"text":default:return this.width?Math.min(Math.abs(this.width/2/Math.cos(e)),Math.abs(this.height/2/Math.sin(e)))+i:0}},E.prototype._setForce=function(t,e){this.fx=t,this.fy=e},E.prototype._addForce=function(t,e){this.fx+=t,this.fy+=e},E.prototype.discreteStep=function(t){if(!this.xFixed){var e=-this.damping*this.vx,i=(this.fx+e)/this.mass;this.vx+=i/t,this.x+=this.vx/t}if(!this.yFixed){var n=-this.damping*this.vy,s=(this.fy+n)/this.mass;this.vy+=s/t,this.y+=this.vy/t}},E.prototype.isFixed=function(){return this.xFixed&&this.yFixed},E.prototype.isMoving=function(t){return Math.abs(this.vx)>t||Math.abs(this.vy)>t||!this.xFixed&&Math.abs(this.fx)>this.minForce||!this.yFixed&&Math.abs(this.fy)>this.minForce},E.prototype.isSelected=function(){return this.selected},E.prototype.getValue=function(){return this.value},E.prototype.getDistance=function(t,e){var i=this.x-t,n=this.y-e;return Math.sqrt(i*i+n*n)},E.prototype.setValueRange=function(t,e){if(!this.radiusFixed&&void 0!==this.value){var i=(this.radiusMax-this.radiusMin)/(e-t);this.radius=(this.value-t)*i+this.radiusMin}},E.prototype.draw=function(){throw"Draw method not initialized for node"},E.prototype.resize=function(){throw"Resize method not initialized for node"},E.prototype.isOverlappingWith=function(t){return this.leftt.left&&this.topt.top},E.prototype._resizeImage=function(){if(!this.width){var t,e;if(this.value){var i=this.imageObj.height/this.imageObj.width;t=this.radius||this.imageObj.width,e=this.radius*i||this.imageObj.height}else t=this.imageObj.width,e=this.imageObj.height;this.width=t,this.height=e}},E.prototype._drawImage=function(t){this._resizeImage(t),this.left=this.x-this.width/2,this.top=this.y-this.height/2;var e;this.imageObj?(t.drawImage(this.imageObj,this.left,this.top,this.width,this.height),e=this.y+this.height/2):e=this.y,this._label(t,this.label,this.x,e,void 0,"top")},E.prototype._resizeBox=function(t){if(!this.width){var e=5,i=this.getTextSize(t);this.width=i.width+2*e,this.height=i.height+2*e}},E.prototype._drawBox=function(t){this._resizeBox(t),this.left=this.x-this.width/2,this.top=this.y-this.height/2,t.strokeStyle=this.selected?this.color.highlight.border:this.color.border,t.fillStyle=this.selected?this.color.highlight.background:this.color.background,t.lineWidth=this.selected?2:1,t.roundRect(this.left,this.top,this.width,this.height,this.radius),t.fill(),t.stroke(),this._label(t,this.label,this.x,this.y)},E.prototype._resizeDatabase=function(t){if(!this.width){var e=5,i=this.getTextSize(t),n=i.width+2*e;this.width=n,this.height=n}},E.prototype._drawDatabase=function(t){this._resizeDatabase(t),this.left=this.x-this.width/2,this.top=this.y-this.height/2,t.strokeStyle=this.selected?this.color.highlight.border:this.color.border,t.fillStyle=this.selected?this.color.highlight.background:this.color.background,t.lineWidth=this.selected?2:1,t.database(this.x-this.width/2,this.y-.5*this.height,this.width,this.height),t.fill(),t.stroke(),this._label(t,this.label,this.x,this.y)},E.prototype._resizeCircle=function(t){if(!this.width){var e=5,i=this.getTextSize(t),n=Math.max(i.width,i.height)+2*e;this.radius=n/2,this.width=n,this.height=n}},E.prototype._drawCircle=function(t){this._resizeCircle(t),this.left=this.x-this.width/2,this.top=this.y-this.height/2,t.strokeStyle=this.selected?this.color.highlight.border:this.color.border,t.fillStyle=this.selected?this.color.highlight.background:this.color.background,t.lineWidth=this.selected?2:1,t.circle(this.x,this.y,this.radius),t.fill(),t.stroke(),this._label(t,this.label,this.x,this.y)},E.prototype._resizeEllipse=function(t){if(!this.width){var e=this.getTextSize(t);this.width=1.5*e.width,this.height=2*e.height,this.widthl;l++)t.fillText(r[l],i,d),d+=h}},E.prototype.getTextSize=function(t){if(void 0!=this.label){t.font=(this.selected?"bold ":"")+this.fontSize+"px "+this.fontFace;for(var e=this.label.split("\n"),i=(this.fontSize+4)*e.length,n=0,s=0,o=e.length;o>s;s++)n=Math.max(n,t.measureText(e[s]).width);return{width:n,height:i}}return{width:0,height:0}},T.prototype.setProperties=function(t,e){if(t)switch(void 0!=t.from&&(this.fromId=t.from),void 0!=t.to&&(this.toId=t.to),void 0!=t.id&&(this.id=t.id),void 0!=t.style&&(this.style=t.style),void 0!=t.label&&(this.label=t.label),this.label&&(this.fontSize=e.edges.fontSize,this.fontFace=e.edges.fontFace,this.fontColor=e.edges.fontColor,void 0!=t.fontColor&&(this.fontColor=t.fontColor),void 0!=t.fontSize&&(this.fontSize=t.fontSize),void 0!=t.fontFace&&(this.fontFace=t.fontFace)),void 0!=t.title&&(this.title=t.title),void 0!=t.width&&(this.width=t.width),void 0!=t.value&&(this.value=t.value),void 0!=t.length&&(this.length=t.length),t.dash&&(void 0!=t.dash.length&&(this.dash.length=t.dash.length),void 0!=t.dash.gap&&(this.dash.gap=t.dash.gap),void 0!=t.dash.altLength&&(this.dash.altLength=t.dash.altLength)),void 0!=t.color&&(this.color=t.color),this.connect(),this.widthFixed=this.widthFixed||void 0!=t.width,this.lengthFixed=this.lengthFixed||void 0!=t.length,this.stiffness=1/this.length,this.style){case"line":this.draw=this._drawLine;break;case"arrow":this.draw=this._drawArrow;break;case"arrow-center":this.draw=this._drawArrowCenter;break;case"dash-line":this.draw=this._drawDashLine;break;default:this.draw=this._drawLine}},T.prototype.connect=function(){this.disconnect(),this.from=this.graph.nodes[this.fromId]||null,this.to=this.graph.nodes[this.toId]||null,this.connected=this.from&&this.to,this.connected?(this.from.attachEdge(this),this.to.attachEdge(this)):(this.from&&this.from.detachEdge(this),this.to&&this.to.detachEdge(this))},T.prototype.disconnect=function(){this.from&&(this.from.detachEdge(this),this.from=null),this.to&&(this.to.detachEdge(this),this.to=null),this.connected=!1},T.prototype.getTitle=function(){return this.title},T.prototype.getValue=function(){return this.value},T.prototype.setValueRange=function(t,e){if(!this.widthFixed&&void 0!==this.value){var i=(this.widthMax-this.widthMin)/(e-t);this.width=(this.value-t)*i+this.widthMin}},T.prototype.draw=function(){throw"Method draw not initialized in edge"},T.prototype.isOverlappingWith=function(t){var e=10,i=this.from.x,n=this.from.y,s=this.to.x,o=this.to.y,r=t.left,a=t.top,h=T._dist(i,n,s,o,r,a);return e>h},T.prototype._drawLine=function(t){t.strokeStyle=this.color,t.lineWidth=this._getLineWidth();var e;if(this.from!=this.to)this._line(t),this.label&&(e=this._pointOnLine(.5),this._label(t,this.label,e.x,e.y));else{var i,n,s=this.length/4,o=this.from;o.width||o.resize(t),o.width>o.height?(i=o.x+o.width/2,n=o.y-s):(i=o.x+s,n=o.y-o.height/2),this._circle(t,i,n,s),e=this._pointOnCircle(i,n,s,.5),this._label(t,this.label,e.x,e.y)}},T.prototype._getLineWidth=function(){return this.from.selected||this.to.selected?Math.min(2*this.width,this.widthMax):this.width},T.prototype._line=function(t){t.beginPath(),t.moveTo(this.from.x,this.from.y),t.lineTo(this.to.x,this.to.y),t.stroke()},T.prototype._circle=function(t,e,i,n){t.beginPath(),t.arc(e,i,n,0,2*Math.PI,!1),t.stroke()},T.prototype._label=function(t,e,i,n){if(e){t.font=(this.from.selected||this.to.selected?"bold ":"")+this.fontSize+"px "+this.fontFace,t.fillStyle="white";var s=t.measureText(e).width,o=this.fontSize,r=i-s/2,a=n-o/2;t.fillRect(r,a,s,o),t.fillStyle=this.fontColor||"black",t.textAlign="left",t.textBaseline="top",t.fillText(e,r,a)}},T.prototype._drawDashLine=function(t){if(t.strokeStyle=this.color,t.lineWidth=this._getLineWidth(),t.beginPath(),t.lineCap="round",void 0!=this.dash.altLength?t.dashedLine(this.from.x,this.from.y,this.to.x,this.to.y,[this.dash.length,this.dash.gap,this.dash.altLength,this.dash.gap]):void 0!=this.dash.length&&void 0!=this.dash.gap?t.dashedLine(this.from.x,this.from.y,this.to.x,this.to.y,[this.dash.length,this.dash.gap]):(t.moveTo(this.from.x,this.from.y),t.lineTo(this.to.x,this.to.y)),t.stroke(),this.label){var e=this._pointOnLine(.5);this._label(t,this.label,e.x,e.y)}},T.prototype._pointOnLine=function(t){return{x:(1-t)*this.from.x+t*this.to.x,y:(1-t)*this.from.y+t*this.to.y}},T.prototype._pointOnCircle=function(t,e,i,n){var s=2*(n-3/8)*Math.PI;return{x:t+i*Math.cos(s),y:e-i*Math.sin(s)}},T.prototype._drawArrowCenter=function(t){var e;if(t.strokeStyle=this.color,t.fillStyle=this.color,t.lineWidth=this._getLineWidth(),this.from!=this.to){this._line(t);var i=Math.atan2(this.to.y-this.from.y,this.to.x-this.from.x),n=10+5*this.width;e=this._pointOnLine(.5),t.arrow(e.x,e.y,i,n),t.fill(),t.stroke(),this.label&&(e=this._pointOnLine(.5),this._label(t,this.label,e.x,e.y))}else{var s,o,r=this.length/4,a=this.from;a.width||a.resize(t),a.width>a.height?(s=a.x+a.width/2,o=a.y-r):(s=a.x+r,o=a.y-a.height/2),this._circle(t,s,o,r);var i=.2*Math.PI,n=10+5*this.width;e=this._pointOnCircle(s,o,r,.5),t.arrow(e.x,e.y,i,n),t.fill(),t.stroke(),this.label&&(e=this._pointOnCircle(s,o,r,.5),this._label(t,this.label,e.x,e.y))}},T.prototype._drawArrow=function(t){t.strokeStyle=this.color,t.fillStyle=this.color,t.lineWidth=this._getLineWidth();var e,i;if(this.from!=this.to){e=Math.atan2(this.to.y-this.from.y,this.to.x-this.from.x);var n=this.to.x-this.from.x,s=this.to.y-this.from.y,o=Math.sqrt(n*n+s*s),r=this.from.distanceToBorder(t,e+Math.PI),a=(o-r)/o,h=a*this.from.x+(1-a)*this.to.x,d=a*this.from.y+(1-a)*this.to.y,l=this.to.distanceToBorder(t,e),u=(o-l)/o,c=(1-u)*this.from.x+u*this.to.x,p=(1-u)*this.from.y+u*this.to.y;if(t.beginPath(),t.moveTo(h,d),t.lineTo(c,p),t.stroke(),i=10+5*this.width,t.arrow(c,p,e,i),t.fill(),t.stroke(),this.label){var f=this._pointOnLine(.5);this._label(t,this.label,f.x,f.y)}}else{var m,g,v,y=this.from,b=this.length/4;y.width||y.resize(t),y.width>y.height?(m=y.x+y.width/2,g=y.y-b,v={x:m,y:y.y,angle:.9*Math.PI}):(m=y.x+b,g=y.y-y.height/2,v={x:y.x,y:g,angle:.6*Math.PI}),t.beginPath(),t.arc(m,g,b,0,2*Math.PI,!1),t.stroke(),i=10+5*this.width,t.arrow(v.x,v.y,v.angle,i),t.fill(),t.stroke(),this.label&&(f=this._pointOnCircle(m,g,b,.5),this._label(t,this.label,f.x,f.y)) -}},T._dist=function(t,e,i,n,s,o){var r=i-t,a=n-e,h=r*r+a*a,d=((s-t)*r+(o-e)*a)/h;d>1?d=1:0>d&&(d=0);var l=t+d*r,u=e+d*a,c=l-s,p=u-o;return Math.sqrt(c*c+p*p)},x.prototype.setPosition=function(t,e){this.x=parseInt(t),this.y=parseInt(e)},x.prototype.setText=function(t){this.frame.innerHTML=t},x.prototype.show=function(t){if(void 0===t&&(t=!0),t){var e=this.frame.clientHeight,i=this.frame.clientWidth,n=this.frame.parentNode.clientHeight,s=this.frame.parentNode.clientWidth,o=this.y-e;o+e+this.padding>n&&(o=n-e-this.padding),this.padding>o&&(o=this.padding);var r=this.x;r+i+this.padding>s&&(r=s-i-this.padding),this.padding>r&&(r=this.padding),this.frame.style.left=r+"px",this.frame.style.top=o+"px",this.frame.style.visibility="visible"}else this.hide()},x.prototype.hide=function(){this.frame.style.visibility="hidden"},Groups=function(){this.clear(),this.defaultIndex=0},Groups.DEFAULT=[{border:"#2B7CE9",background:"#97C2FC",highlight:{border:"#2B7CE9",background:"#D2E5FF"}},{border:"#FFA500",background:"#FFFF00",highlight:{border:"#FFA500",background:"#FFFFA3"}},{border:"#FA0A10",background:"#FB7E81",highlight:{border:"#FA0A10",background:"#FFAFB1"}},{border:"#41A906",background:"#7BE141",highlight:{border:"#41A906",background:"#A1EC76"}},{border:"#E129F0",background:"#EB7DF4",highlight:{border:"#E129F0",background:"#F0B3F5"}},{border:"#7C29F0",background:"#AD85E4",highlight:{border:"#7C29F0",background:"#D3BDF0"}},{border:"#C37F00",background:"#FFA807",highlight:{border:"#C37F00",background:"#FFCA66"}},{border:"#4220FB",background:"#6E6EFD",highlight:{border:"#4220FB",background:"#9B9BFD"}},{border:"#FD5A77",background:"#FFC0CB",highlight:{border:"#FD5A77",background:"#FFD1D9"}},{border:"#4AD63A",background:"#C2FABC",highlight:{border:"#4AD63A",background:"#E6FFE3"}}],Groups.prototype.clear=function(){this.groups={},this.groups.length=function(){var t=0;for(var e in this)this.hasOwnProperty(e)&&t++;return t}},Groups.prototype.get=function(t){var e=this.groups[t];if(void 0==e){var i=this.defaultIndex%Groups.DEFAULT.length;this.defaultIndex++,e={},e.color=Groups.DEFAULT[i],this.groups[t]=e}return e},Groups.prototype.add=function(t,e){return this.groups[t]=e,e.color&&(e.color=E.parseColor(e.color)),e},Images=function(){this.images={},this.callback=void 0},Images.prototype.setOnloadCallback=function(t){this.callback=t},Images.prototype.load=function(t){var e=this.images[t];if(void 0==e){var i=this;e=new Image,this.images[t]=e,e.onload=function(){i.callback&&i.callback(this)},e.src=t}return e},S.prototype.setData=function(t){if(t&&t.dot&&(t.nodes||t.edges))throw new SyntaxError('Data must contain either parameter "dot" or parameter pair "nodes" and "edges", but not both.');if(this.setOptions(t&&t.options),t&&t.dot){if(t&&t.dot){var e=k.util.DOTToGraph(t.dot);return this.setData(e),void 0}}else this._setNodes(t&&t.nodes),this._setEdges(t&&t.edges);this.stabilize&&this._doStabilize(),this.start()},S.prototype.setOptions=function(t){if(t){if(void 0!=t.width&&(this.width=t.width),void 0!=t.height&&(this.height=t.height),void 0!=t.stabilize&&(this.stabilize=t.stabilize),void 0!=t.selectable&&(this.selectable=t.selectable),t.edges){for(var e in t.edges)t.edges.hasOwnProperty(e)&&(this.constants.edges[e]=t.edges[e]);void 0!=t.edges.length&&t.nodes&&void 0==t.nodes.distance&&(this.constants.edges.length=t.edges.length,this.constants.nodes.distance=1.25*t.edges.length),t.edges.fontColor||(this.constants.edges.fontColor=t.edges.color),t.edges.dash&&(void 0!=t.edges.dash.length&&(this.constants.edges.dash.length=t.edges.dash.length),void 0!=t.edges.dash.gap&&(this.constants.edges.dash.gap=t.edges.dash.gap),void 0!=t.edges.dash.altLength&&(this.constants.edges.dash.altLength=t.edges.dash.altLength))}if(t.nodes){for(e in t.nodes)t.nodes.hasOwnProperty(e)&&(this.constants.nodes[e]=t.nodes[e]);t.nodes.color&&(this.constants.nodes.color=E.parseColor(t.nodes.color))}if(t.groups)for(var i in t.groups)if(t.groups.hasOwnProperty(i)){var n=t.groups[i];this.groups.add(i,n)}}this.setSize(this.width,this.height),this._setTranslation(this.frame.clientWidth/2,this.frame.clientHeight/2),this._setScale(1)},S.prototype._trigger=function(t,e){L.trigger(this,t,e)},S.prototype._create=function(){for(;this.containerElement.hasChildNodes();)this.containerElement.removeChild(this.containerElement.firstChild);if(this.frame=document.createElement("div"),this.frame.className="graph-frame",this.frame.style.position="relative",this.frame.style.overflow="hidden",this.frame.canvas=document.createElement("canvas"),this.frame.canvas.style.position="relative",this.frame.appendChild(this.frame.canvas),!this.frame.canvas.getContext){var t=document.createElement("DIV");t.style.color="red",t.style.fontWeight="bold",t.style.padding="10px",t.innerHTML="Error: your browser does not support HTML canvas",this.frame.canvas.appendChild(t)}var e=this;this.hammer=D(this.frame.canvas),this.hammer.on("tap",function(t){e._onTap(t)}),this.containerElement.appendChild(this.frame)},S.prototype._onDragStart=function(){},S.prototype._onDrag=function(){},S.prototype._onDragEnd=function(){},S.prototype._onTap=function(t){var e=t.gesture.center;this.ctrlKeyDown=t.ctrlKey,this.shiftKeyDown=t.shiftKey;var i={left:this._xToCanvas(e.pageX),top:this._yToCanvas(e.pageY),right:this._xToCanvas(e.pageX),bottom:this._yToCanvas(e.pageY)},n=this._getNodesOverlappingWith(i);if(this.startClickedObj=n.length>0?n[n.length-1]:void 0,console.log(this.startClickedObj,i,this.nodes),this.startClickedObj){var s=this.nodes[this.startClickedObj];this.startClickedObj.xFixed=s.xFixed,this.startClickedObj.yFixed=s.yFixed,s.xFixed=!0,s.yFixed=!0,this.ctrlKeyDown&&s.isSelected()?this._unselectNodes([this.startClickedObj]):this._selectNodes([this.startClickedObj],this.ctrlKeyDown),this.moving||this._redraw()}else this.shiftKeyDown},S.prototype._onZoom=function(){},S.prototype._onMouseDown=function(t){if(t=t||window.event,this.selectable&&(this.leftButtonDown&&this._onMouseUp(t),this.leftButtonDown=t.which?1==t.which:1==t.button,this.leftButtonDown||this.touchDown)){var e=this;this.onmousemove||(this.onmousemove=function(t){e._onMouseMove(t)},k.util.addEventListener(document,"mousemove",e.onmousemove)),this.onmouseup||(this.onmouseup=function(t){e._onMouseUp(t)},k.util.addEventListener(document,"mouseup",e.onmouseup)),k.util.preventDefault(t),this.startMouseX=C.getPageX(t),this.startMouseY=C.getPageY(t),this.startFrameLeft=k.util.getAbsoluteLeft(this.frame.canvas),this.startFrameTop=k.util.getAbsoluteTop(this.frame.canvas),this.startTranslation=this._getTranslation(),this.ctrlKeyDown=t.ctrlKey,this.shiftKeyDown=t.shiftKey;var i={left:this._xToCanvas(this.startMouseX-this.startFrameLeft),top:this._yToCanvas(this.startMouseY-this.startFrameTop),right:this._xToCanvas(this.startMouseX-this.startFrameLeft),bottom:this._yToCanvas(this.startMouseY-this.startFrameTop)},n=this._getNodesOverlappingWith(i);if(this.startClickedObj=n.length>0?n[n.length-1]:void 0,this.startClickedObj){var s=this.nodes[this.startClickedObj];this.startClickedObj.xFixed=s.xFixed,this.startClickedObj.yFixed=s.yFixed,s.xFixed=!0,s.yFixed=!0,this.ctrlKeyDown&&s.isSelected()?this._unselectNodes([this.startClickedObj]):this._selectNodes([this.startClickedObj],this.ctrlKeyDown),this.moving||this._redraw()}else this.shiftKeyDown||(this.moved=!1)}},S.prototype._onMouseMove=function(t){if(t=t||window.event,this.selectable){var e=C.getPageX(t),i=C.getPageY(t);if(this.mouseX=e,this.mouseY=i,this.startClickedObj){var n=this.nodes[this.startClickedObj];this.startClickedObj.xFixed||(n.x=this._xToCanvas(e-this.startFrameLeft)),this.startClickedObj.yFixed||(n.y=this._yToCanvas(i-this.startFrameTop)),this.moving||(this.moving=!0,this.start())}else if(this.shiftKeyDown){void 0==this.frame.selRect&&(this.frame.selRect=document.createElement("DIV"),this.frame.appendChild(this.frame.selRect),this.frame.selRect.style.position="absolute",this.frame.selRect.style.border="1px dashed red");var s=Math.min(this.startMouseX,e)-this.startFrameLeft,o=Math.min(this.startMouseY,i)-this.startFrameTop,r=Math.max(this.startMouseX,e)-this.startFrameLeft,a=Math.max(this.startMouseY,i)-this.startFrameTop;this.frame.selRect.style.left=s+"px",this.frame.selRect.style.top=o+"px",this.frame.selRect.style.width=r-s+"px",this.frame.selRect.style.height=a-o+"px"}else{var h=e-this.startMouseX,d=i-this.startMouseY;this._setTranslation(this.startTranslation.x+h,this.startTranslation.y+d),this._redraw(),this.moved=!0}k.util.preventDefault(t)}},S.prototype._onMouseUp=function(t){if(t=t||window.event,this.selectable){this.onmousemove&&(k.util.removeEventListener(document,"mousemove",this.onmousemove),this.onmousemove=void 0),this.onmouseup&&(k.util.removeEventListener(document,"mouseup",this.onmouseup),this.onmouseup=void 0),k.util.preventDefault(t);var e=C.getPageX(t)||this.mouseX||0,i=C.getPageY(t)||this.mouseY||0,n=t?t.ctrlKey:window.event.ctrlKey;if(this.startClickedObj){var s=this.nodes[this.startClickedObj];s.xFixed=this.startClickedObj.xFixed,s.yFixed=this.startClickedObj.yFixed}else if(this.shiftKeyDown){var o={left:this._xToCanvas(Math.min(this.startMouseX,e)-this.startFrameLeft),top:this._yToCanvas(Math.min(this.startMouseY,i)-this.startFrameTop),right:this._xToCanvas(Math.max(this.startMouseX,e)-this.startFrameLeft),bottom:this._yToCanvas(Math.max(this.startMouseY,i)-this.startFrameTop)},r=this._getNodesOverlappingWith(o);this._selectNodes(r,n),this.redraw(),this.frame.selRect&&(this.frame.removeChild(this.frame.selRect),this.frame.selRect=void 0)}else this.ctrlKeyDown||this.moved||(this._unselectNodes(),this._redraw());this.leftButtonDown=!1,this.ctrlKeyDown=!1}},S.prototype._onMouseWheel=function(t){t=t||window.event;var e=C.getPageX(t),i=C.getPageY(t),n=0;if(t.wheelDelta?n=t.wheelDelta/120:t.detail&&(n=-t.detail/3),n){var s=n/10;0>n&&(s/=1-s);var o=this._getScale(),r=o*(1+s);.01>r&&(r=.01),r>10&&(r=10);var a=k.util.getAbsoluteLeft(this.frame.canvas),h=k.util.getAbsoluteTop(this.frame.canvas),d=e-a,l=i-h,u=this._getTranslation(),c=r/o,p=(1-c)*d+u.x*c,f=(1-c)*l+u.y*c;this._setScale(r),this._setTranslation(p,f),this._redraw()}k.util.preventDefault(t)},S.prototype._onMouseMoveTitle=function(t){t=t||window.event;var e=C.getPageX(t),i=C.getPageY(t);this.startFrameLeft=this.startFrameLeft||k.util.getAbsoluteLeft(this.frame.canvas),this.startFrameTop=this.startFrameTop||k.util.getAbsoluteTop(this.frame.canvas);var n=e-this.startFrameLeft,s=i-this.startFrameTop;this.popupNode&&this._checkHidePopup(n,s);var o=this,r=function(){o._checkShowPopup(n,s)};this.popupTimer&&clearInterval(this.popupTimer),this.leftButtonDown||(this.popupTimer=setTimeout(r,300))},S.prototype._checkShowPopup=function(t,e){var i,n={left:this._xToCanvas(t),top:this._yToCanvas(e),right:this._xToCanvas(t),bottom:this._yToCanvas(e)},s=this.popupNode;if(void 0==this.popupNode){var o=this.nodes;for(i in o)if(o.hasOwnProperty(i)){var r=o[i];if(void 0!=r.getTitle()&&r.isOverlappingWith(n)){this.popupNode=r;break}}}if(void 0==this.popupNode){var a=this.edges;for(i in a)if(a.hasOwnProperty(i)){var h=a[i];if(h.connected&&void 0!=h.getTitle()&&h.isOverlappingWith(n)){this.popupNode=h;break}}}if(this.popupNode){if(this.popupNode!=s){var d=this;d.popup||(d.popup=new x(d.frame)),d.popup.setPosition(t-3,e-3),d.popup.setText(d.popupNode.getTitle()),d.popup.show()}}else this.popup&&this.popup.hide()},S.prototype._checkHidePopup=function(t,e){var i={left:t,top:e,right:t,bottom:e};this.popupNode&&this.popupNode.isOverlappingWith(i)||(this.popupNode=void 0,this.popup&&this.popup.hide())},S.prototype._onTouchStart=function(t){if(k.util.preventDefault(t),!this.touchDown){this.touchDown=!0;var e=this;this.ontouchmove||(this.ontouchmove=function(t){e._onTouchMove(t)},k.util.addEventListener(document,"touchmove",this.ontouchmove)),this.ontouchend||(this.ontouchend=function(t){e._onTouchEnd(t)},k.util.addEventListener(document,"touchend",this.ontouchend)),this._onMouseDown(t)}},S.prototype._onTouchMove=function(t){k.util.preventDefault(t),this._onMouseMove(t)},S.prototype._onTouchEnd=function(t){k.util.preventDefault(t),this.touchDown=!1,this.ontouchmove&&(k.util.removeEventListener(document,"touchmove",this.ontouchmove),this.ontouchmove=void 0),this.ontouchend&&(k.util.removeEventListener(document,"touchend",this.ontouchend),this.ontouchend=void 0),this._onMouseUp(t)},S.prototype._unselectNodes=function(t,e){var i,n,s,o=!1;if(t)for(i=0,n=t.length;n>i;i++){s=t[i],this.nodes[s].unselect();for(var r=0;this.selection.length>r;)this.selection[r]==s?(this.selection.splice(r,1),o=!0):r++}else if(this.selection&&this.selection.length){for(i=0,n=this.selection.length;n>i;i++)s=this.selection[i],this.nodes[s].unselect(),o=!0;this.selection=[]}return!o||1!=e&&void 0!=e||this._trigger("select"),o},S.prototype._selectNodes=function(t,e){var i,n,s=!1,o=!0;if(t.length!=this.selection.length)o=!1;else for(i=0,n=Math.min(t.length,this.selection.length);n>i;i++)if(t[i]!=this.selection[i]){o=!1;break}if(o)return s;if(void 0==e||0==e){var r=!1;s=this._unselectNodes(void 0,r)}for(i=0,n=t.length;n>i;i++){var a=t[i],h=-1!=this.selection.indexOf(a);h||(this.nodes[a].select(),this.selection.push(a),s=!0)}return s&&this._trigger("select"),s},S.prototype._getNodesOverlappingWith=function(t){var e=this.nodes,i=[];for(var n in e)e.hasOwnProperty(n)&&e[n].isOverlappingWith(t)&&i.push(n);return i},S.prototype.getSelection=function(){return this.selection.concat([])},S.prototype.setSelection=function(t){var e,i,n;if(void 0==t.length)throw"Selection must be an array with ids";for(e=0,i=this.selection.length;i>e;e++)n=this.selection[e],this.nodes[n].unselect();for(this.selection=[],e=0,i=t.length;i>e;e++){n=t[e];var s=this.nodes[n];if(!s)throw new RangeError('Node with id "'+n+'" not found');s.select(),this.selection.push(n)}this.redraw()},S.prototype._updateSelection=function(){for(var t=0;this.selection.length>t;){var e=this.selection[t];this.nodes[e]?t++:this.selection.splice(t,1)}},S.prototype._getConnectionCount=function(t){function e(t){for(var e=[],i=0,n=t.length;n>i;i++)for(var s=t[i],o=s.edges,r=0,a=o.length;a>r;r++){var h=o[r],d=null;h.from==s?d=h.to:h.to==s&&(d=h.from);var l,u;if(d)for(l=0,u=t.length;u>l;l++)if(t[l]==d){d=null;break}if(d)for(l=0,u=e.length;u>l;l++)if(e[l]==d){d=null;break}d&&e.push(d)}return e}void 0==t&&(t=1);var i=[],n=this.nodes;for(var s in n)if(n.hasOwnProperty(s)){for(var o=[n[s]],r=0;t>r;r++)o=o.concat(e(o));i.push(o)}for(var a=[],h=0,d=i.length;d>h;h++)a.push(i[h].length);return a},S.prototype.setSize=function(t,e){this.frame.style.width=t,this.frame.style.height=e,this.frame.canvas.style.width="100%",this.frame.canvas.style.height="100%",this.frame.canvas.width=this.frame.canvas.clientWidth,this.frame.canvas.height=this.frame.canvas.clientHeight},S.prototype._setNodes=function(t){var e=this.nodesData;if(t instanceof o||t instanceof r)this.nodesData=t;else if(t instanceof Array)this.nodesData=new o,this.nodesData.add(t);else{if(t)throw new TypeError("Array or DataSet expected");this.nodesData=new o}if(e&&C.forEach(this.nodesListeners,function(t,i){e.unsubscribe(i,t)}),this.nodes={},this.nodesData){var i=this;C.forEach(this.nodesListeners,function(t,e){i.nodesData.subscribe(e,t)});var n=this.nodesData.getIds();this._addNodes(n)}this._updateSelection()},S.prototype._addNodes=function(t){for(var e,i=0,n=t.length;n>i;i++){e=t[i];var s=this.nodesData.get(e),o=new E(s,this.images,this.groups,this.constants);if(this.nodes[e]=o,!o.isFixed()){var r=2*this.constants.edges.length,a=t.length,h=2*Math.PI*(i/a);o.x=r*Math.cos(h),o.y=r*Math.sin(h),this.moving=!0}}this._reconnectEdges(),this._updateValueRange(this.nodes)},S.prototype._updateNodes=function(t){for(var e=this.nodes,i=this.nodesData,n=0,s=t.length;s>n;n++){var o=t[n],r=e[o],a=i.get(o);r?r.setProperties(a,this.constants):(r=new E(properties,this.images,this.groups,this.constants),e[o]=r,r.isFixed()||(this.moving=!0))}this._reconnectEdges(),this._updateValueRange(e)},S.prototype._removeNodes=function(t){for(var e=this.nodes,i=0,n=t.length;n>i;i++){var s=t[i];delete e[s]}this._reconnectEdges(),this._updateSelection(),this._updateValueRange(e)},S.prototype._setEdges=function(t){var e=this.edgesData;if(t instanceof o||t instanceof r)this.edgesData=t;else if(t instanceof Array)this.edgesData=new o,this.edgesData.add(t);else{if(t)throw new TypeError("Array or DataSet expected");this.edgesData=new o}if(e&&C.forEach(this.edgesListeners,function(t,i){e.unsubscribe(i,t)}),this.edges={},this.edgesData){var i=this;C.forEach(this.edgesListeners,function(t,e){i.edgesData.subscribe(e,t)});var n=this.edgesData.getIds();this._addEdges(n)}this._reconnectEdges()},S.prototype._addEdges=function(t){for(var e=this.edges,i=this.edgesData,n=0,s=t.length;s>n;n++){var o=t[n],r=e[o];r&&r.disconnect();var a=i.get(o);e[o]=new T(a,this,this.constants)}this.moving=!0,this._updateValueRange(e)},S.prototype._updateEdges=function(t){for(var e=this.edges,i=this.edgesData,n=0,s=t.length;s>n;n++){var o=t[n],r=i.get(o),a=e[o];a?(a.disconnect(),a.setProperties(r,this.constants),a.connect()):(a=new T(r,this,this.constants),this.edges[o]=a)}this.moving=!0,this._updateValueRange(e)},S.prototype._removeEdges=function(t){for(var e=this.edges,i=0,n=t.length;n>i;i++){var s=t[i],o=e[s];o&&(o.disconnect(),delete e[s])}this.moving=!0,this._updateValueRange(e)},S.prototype._reconnectEdges=function(){var t,e=this.nodes,i=this.edges;for(t in e)e.hasOwnProperty(t)&&(e[t].edges=[]);for(t in i)if(i.hasOwnProperty(t)){var n=i[t];n.from=null,n.to=null,n.connect()}},S.prototype._updateValueRange=function(t){var e,i=void 0,n=void 0;for(e in t)if(t.hasOwnProperty(e)){var s=t[e].getValue();void 0!==s&&(i=void 0===i?s:Math.min(s,i),n=void 0===n?s:Math.max(s,n))}if(void 0!==i&&void 0!==n)for(e in t)t.hasOwnProperty(e)&&t[e].setValueRange(i,n)},S.prototype.redraw=function(){this.setSize(this.width,this.height),this._redraw()},S.prototype._redraw=function(){var t=this.frame.canvas.getContext("2d"),e=this.frame.canvas.width,i=this.frame.canvas.height;t.clearRect(0,0,e,i),t.save(),t.translate(this.translation.x,this.translation.y),t.scale(this.scale,this.scale),this._drawEdges(t),this._drawNodes(t),t.restore()},S.prototype._setTranslation=function(t,e){void 0===this.translation&&(this.translation={x:0,y:0}),void 0!==t&&(this.translation.x=t),void 0!==e&&(this.translation.y=e)},S.prototype._getTranslation=function(){return{x:this.translation.x,y:this.translation.y}},S.prototype._setScale=function(t){this.scale=t},S.prototype._getScale=function(){return this.scale},S.prototype._xToCanvas=function(t){return(t-this.translation.x)/this.scale},S.prototype._canvasToX=function(t){return t*this.scale+this.translation.x},S.prototype._yToCanvas=function(t){return(t-this.translation.y)/this.scale},S.prototype._canvasToY=function(t){return t*this.scale+this.translation.y},S.prototype._drawNodes=function(t){var e=this.nodes,i=[];for(var n in e)e.hasOwnProperty(n)&&(e[n].isSelected()?i.push(n):e[n].draw(t));for(var s=0,o=i.length;o>s;s++)e[i[s]].draw(t)},S.prototype._drawEdges=function(t){var e=this.edges;for(var i in e)if(e.hasOwnProperty(i)){var n=e[i];n.connected&&e[i].draw(t)}},S.prototype._doStabilize=function(){new Date;for(var t=0,e=this.constants.minVelocity,i=!1;!i&&this.constants.maxIterations>t;)this._calculateForces(),this._discreteStepNodes(),i=!this._isMoving(e),t++;new Date},S.prototype._calculateForces=function(){var t,e,i,n,s,o,r,a,h,d,l,u=this.nodes,c=this.edges,p=.01,f=this.frame.canvas.clientWidth/2,m=this.frame.canvas.clientHeight/2;for(t in u)if(u.hasOwnProperty(t)){var g=u[t];e=f-g.x,i=m-g.y,n=Math.atan2(i,e),o=Math.cos(n)*p,r=Math.sin(n)*p,g._setForce(o,r)}var v=this.constants.nodes.distance,y=10;for(var b in u)if(u.hasOwnProperty(b)){var w=u[b];for(var _ in u)if(u.hasOwnProperty(_)){var E=u[_];e=E.x-w.x,i=E.y-w.y,s=Math.sqrt(e*e+i*i),n=Math.atan2(i,e),a=1/(1+Math.exp((s/v-1)*y)),o=Math.cos(n)*a,r=Math.sin(n)*a,w._addForce(-o,-r),E._addForce(o,r)}}for(t in c)if(c.hasOwnProperty(t)){var T=c[t];T.connected&&(e=T.to.x-T.from.x,i=T.to.y-T.from.y,l=T.length,d=Math.sqrt(e*e+i*i),n=Math.atan2(i,e),h=T.stiffness*(l-d),o=Math.cos(n)*h,r=Math.sin(n)*h,T.from._addForce(-o,-r),T.to._addForce(o,r))}},S.prototype._isMoving=function(t){var e=this.nodes;for(var i in e)if(e.hasOwnProperty(i)&&e[i].isMoving(t))return!0;return!1},S.prototype._discreteStepNodes=function(){var t=this.refreshRate/1e3,e=this.nodes;for(var i in e)e.hasOwnProperty(i)&&e[i].discreteStep(t)},S.prototype.start=function(){if(this.moving){this._calculateForces(),this._discreteStepNodes();var t=this.constants.minVelocity;this.moving=this._isMoving(t)}if(this.moving){if(!this.timer){var e=this;this.timer=window.setTimeout(function(){e.timer=void 0,e.start(),e._redraw()},this.refreshRate)}}else this._redraw()},S.prototype.stop=function(){this.timer&&(window.clearInterval(this.timer),this.timer=void 0)};var k={util:C,events:L,Controller:d,DataSet:o,DataView:r,Range:h,Stack:a,TimeStep:TimeStep,EventBus:s,components:{items:{Item:m,ItemBox:g,ItemPoint:v,ItemRange:y},Component:l,Panel:u,RootPanel:c,ItemSet:f,TimeAxis:p},graph:{Node:E,Edge:T,Popup:x,Groups:Groups,Images:Images},Timeline:_,Graph:S};n!==void 0&&(n=k),i!==void 0&&i.exports!==void 0&&(i.exports=k),"function"==typeof t&&t(function(){return k}),"undefined"!=typeof window&&(window.vis=k),C.loadCss("/* vis.js stylesheet */\n.vis.timeline {\n}\n\n\n.vis.timeline.rootpanel {\n position: relative;\n overflow: hidden;\n\n border: 1px solid #bfbfbf;\n -moz-box-sizing: border-box;\n box-sizing: border-box;\n}\n\n.vis.timeline .panel {\n position: absolute;\n overflow: hidden;\n}\n\n\n.vis.timeline .groupset {\n position: absolute;\n padding: 0;\n margin: 0;\n}\n\n.vis.timeline .labels {\n position: absolute;\n top: 0;\n left: 0;\n width: 100%;\n height: 100%;\n\n padding: 0;\n margin: 0;\n\n border-right: 1px solid #bfbfbf;\n box-sizing: border-box;\n -moz-box-sizing: border-box;\n}\n\n.vis.timeline .labels .label {\n position: absolute;\n left: 0;\n top: 0;\n width: 100%;\n border-bottom: 1px solid #bfbfbf;\n color: #4d4d4d;\n}\n\n.vis.timeline .labels .label .inner {\n display: inline-block;\n padding: 5px;\n}\n\n\n.vis.timeline .itemset {\n position: absolute;\n padding: 0;\n margin: 0;\n overflow: hidden;\n}\n\n.vis.timeline .background {\n}\n\n.vis.timeline .foreground {\n}\n\n.vis.timeline .itemset-axis {\n position: absolute;\n}\n\n.vis.timeline .groupset .itemset-axis {\n border-top: 1px solid #bfbfbf;\n}\n\n/* TODO: with orientation=='bottom', this will more or less overlap with timeline axis\n.vis.timeline .groupset .itemset-axis:last-child {\n border-top: none;\n}\n*/\n\n\n.vis.timeline .item {\n position: absolute;\n color: #1A1A1A;\n border-color: #97B0F8;\n background-color: #D5DDF6;\n display: inline-block;\n}\n\n.vis.timeline .item.selected {\n border-color: #FFC200;\n background-color: #FFF785;\n z-index: 999;\n}\n\n.vis.timeline .item.cluster {\n /* TODO: use another color or pattern? */\n background: #97B0F8 url('img/cluster_bg.png');\n color: white;\n}\n.vis.timeline .item.cluster.point {\n border-color: #D5DDF6;\n}\n\n.vis.timeline .item.box {\n text-align: center;\n border-style: solid;\n border-width: 1px;\n border-radius: 5px;\n -moz-border-radius: 5px; /* For Firefox 3.6 and older */\n}\n\n.vis.timeline .item.point {\n background: none;\n}\n\n.vis.timeline .dot {\n border: 5px solid #97B0F8;\n position: absolute;\n border-radius: 5px;\n -moz-border-radius: 5px; /* For Firefox 3.6 and older */\n}\n\n.vis.timeline .item.range {\n overflow: hidden;\n border-style: solid;\n border-width: 1px;\n border-radius: 2px;\n -moz-border-radius: 2px; /* For Firefox 3.6 and older */\n}\n\n.vis.timeline .item.range .drag-left {\n cursor: w-resize;\n z-index: 1000;\n}\n\n.vis.timeline .item.range .drag-right {\n cursor: e-resize;\n z-index: 1000;\n}\n\n.vis.timeline .item.range .content {\n position: relative;\n display: inline-block;\n}\n\n.vis.timeline .item.line {\n position: absolute;\n width: 0;\n border-left-width: 1px;\n border-left-style: solid;\n}\n\n.vis.timeline .item .content {\n margin: 5px;\n white-space: nowrap;\n overflow: hidden;\n}\n\n.vis.timeline .axis {\n position: relative;\n}\n\n.vis.timeline .axis .text {\n position: absolute;\n color: #4d4d4d;\n padding: 3px;\n white-space: nowrap;\n}\n\n.vis.timeline .axis .text.measure {\n position: absolute;\n padding-left: 0;\n padding-right: 0;\n margin-left: 0;\n margin-right: 0;\n visibility: hidden;\n}\n\n.vis.timeline .axis .grid.vertical {\n position: absolute;\n width: 0;\n border-right: 1px solid;\n}\n\n.vis.timeline .axis .grid.horizontal {\n position: absolute;\n left: 0;\n width: 100%;\n height: 0;\n border-bottom: 1px solid;\n}\n\n.vis.timeline .axis .grid.minor {\n border-color: #e5e5e5;\n}\n\n.vis.timeline .axis .grid.major {\n border-color: #bfbfbf;\n}\n\n")},{hammerjs:1,moment:2}]},{},[3])(3)}); \ No newline at end of file +(function(t){if("function"==typeof bootstrap)bootstrap("vis",t);else if("object"==typeof exports)module.exports=t();else if("function"==typeof define&&define.amd)define(t);else if("undefined"!=typeof ses){if(!ses.ok())return;ses.makeVis=t}else"undefined"!=typeof window?window.vis=t():global.vis=t()})(function(){var t;return function e(t,i,n){function s(r,a){if(!i[r]){if(!t[r]){var h="function"==typeof require&&require;if(!a&&h)return h(r,!0);if(o)return o(r,!0);throw Error("Cannot find module '"+r+"'")}var d=i[r]={exports:{}};t[r][0].call(d.exports,function(e){var i=t[r][1][e];return s(i?i:e)},d,d.exports,e,t,i,n)}return i[r].exports}for(var o="function"==typeof require&&require,r=0;n.length>r;r++)s(n[r]);return s}({1:[function(t,e){(function(t,i){"use strict";function n(){if(!s.READY){s.event.determineEventTypes();for(var t in s.gestures)s.gestures.hasOwnProperty(t)&&s.detection.register(s.gestures[t]);s.event.onTouch(s.DOCUMENT,s.EVENT_MOVE,s.detection.detect),s.event.onTouch(s.DOCUMENT,s.EVENT_END,s.detection.detect),s.READY=!0}}var s=function(t,e){return new s.Instance(t,e||{})};s.defaults={stop_browser_behavior:{userSelect:"none",touchAction:"none",touchCallout:"none",contentZooming:"none",userDrag:"none",tapHighlightColor:"rgba(0,0,0,0)"}},s.HAS_POINTEREVENTS=navigator.pointerEnabled||navigator.msPointerEnabled,s.HAS_TOUCHEVENTS="ontouchstart"in t,s.MOBILE_REGEX=/mobile|tablet|ip(ad|hone|od)|android/i,s.NO_MOUSEEVENTS=s.HAS_TOUCHEVENTS&&navigator.userAgent.match(s.MOBILE_REGEX),s.EVENT_TYPES={},s.DIRECTION_DOWN="down",s.DIRECTION_LEFT="left",s.DIRECTION_UP="up",s.DIRECTION_RIGHT="right",s.POINTER_MOUSE="mouse",s.POINTER_TOUCH="touch",s.POINTER_PEN="pen",s.EVENT_START="start",s.EVENT_MOVE="move",s.EVENT_END="end",s.DOCUMENT=document,s.plugins={},s.READY=!1,s.Instance=function(t,e){var i=this;return n(),this.element=t,this.enabled=!0,this.options=s.utils.extend(s.utils.extend({},s.defaults),e||{}),this.options.stop_browser_behavior&&s.utils.stopDefaultBrowserBehavior(this.element,this.options.stop_browser_behavior),s.event.onTouch(t,s.EVENT_START,function(t){i.enabled&&s.detection.startDetect(i,t)}),this},s.Instance.prototype={on:function(t,e){for(var i=t.split(" "),n=0;i.length>n;n++)this.element.addEventListener(i[n],e,!1);return this},off:function(t,e){for(var i=t.split(" "),n=0;i.length>n;n++)this.element.removeEventListener(i[n],e,!1);return this},trigger:function(t,e){var i=s.DOCUMENT.createEvent("Event");i.initEvent(t,!0,!0),i.gesture=e;var n=this.element;return s.utils.hasParent(e.target,n)&&(n=e.target),n.dispatchEvent(i),this},enable:function(t){return this.enabled=t,this}};var o=null,r=!1,a=!1;s.event={bindDom:function(t,e,i){for(var n=e.split(" "),s=0;n.length>s;s++)t.addEventListener(n[s],i,!1)},onTouch:function(t,e,i){var n=this;this.bindDom(t,s.EVENT_TYPES[e],function(h){var d=h.type.toLowerCase();if(!d.match(/mouse/)||!a){(d.match(/touch/)||d.match(/pointerdown/)||d.match(/mouse/)&&1===h.which)&&(r=!0),d.match(/touch|pointer/)&&(a=!0);var l=0;r&&(s.HAS_POINTEREVENTS&&e!=s.EVENT_END?l=s.PointerEvent.updatePointer(e,h):d.match(/touch/)?l=h.touches.length:a||(l=d.match(/up/)?0:1),l>0&&e==s.EVENT_END?e=s.EVENT_MOVE:l||(e=s.EVENT_END),l||null===o?o=h:h=o,i.call(s.detection,n.collectEventData(t,e,h)),s.HAS_POINTEREVENTS&&e==s.EVENT_END&&(l=s.PointerEvent.updatePointer(e,h))),l||(o=null,r=!1,a=!1,s.PointerEvent.reset())}})},determineEventTypes:function(){var t;t=s.HAS_POINTEREVENTS?s.PointerEvent.getEvents():s.NO_MOUSEEVENTS?["touchstart","touchmove","touchend touchcancel"]:["touchstart mousedown","touchmove mousemove","touchend touchcancel mouseup"],s.EVENT_TYPES[s.EVENT_START]=t[0],s.EVENT_TYPES[s.EVENT_MOVE]=t[1],s.EVENT_TYPES[s.EVENT_END]=t[2]},getTouchList:function(t){return s.HAS_POINTEREVENTS?s.PointerEvent.getTouchList():t.touches?t.touches:[{identifier:1,pageX:t.pageX,pageY:t.pageY,target:t.target}]},collectEventData:function(t,e,i){var n=this.getTouchList(i,e),o=s.POINTER_TOUCH;return(i.type.match(/mouse/)||s.PointerEvent.matchType(s.POINTER_MOUSE,i))&&(o=s.POINTER_MOUSE),{center:s.utils.getCenter(n),timeStamp:(new Date).getTime(),target:i.target,touches:n,eventType:e,pointerType:o,srcEvent:i,preventDefault:function(){this.srcEvent.preventManipulation&&this.srcEvent.preventManipulation(),this.srcEvent.preventDefault&&this.srcEvent.preventDefault()},stopPropagation:function(){this.srcEvent.stopPropagation()},stopDetect:function(){return s.detection.stopDetect()}}}},s.PointerEvent={pointers:{},getTouchList:function(){var t=this,e=[];return Object.keys(t.pointers).sort().forEach(function(i){e.push(t.pointers[i])}),e},updatePointer:function(t,e){return t==s.EVENT_END?this.pointers={}:(e.identifier=e.pointerId,this.pointers[e.pointerId]=e),Object.keys(this.pointers).length},matchType:function(t,e){if(!e.pointerType)return!1;var i={};return i[s.POINTER_MOUSE]=e.pointerType==e.MSPOINTER_TYPE_MOUSE||e.pointerType==s.POINTER_MOUSE,i[s.POINTER_TOUCH]=e.pointerType==e.MSPOINTER_TYPE_TOUCH||e.pointerType==s.POINTER_TOUCH,i[s.POINTER_PEN]=e.pointerType==e.MSPOINTER_TYPE_PEN||e.pointerType==s.POINTER_PEN,i[t]},getEvents:function(){return["pointerdown MSPointerDown","pointermove MSPointerMove","pointerup pointercancel MSPointerUp MSPointerCancel"]},reset:function(){this.pointers={}}},s.utils={extend:function(t,e,n){for(var s in e)t[s]!==i&&n||(t[s]=e[s]);return t},hasParent:function(t,e){for(;t;){if(t==e)return!0;t=t.parentNode}return!1},getCenter:function(t){for(var e=[],i=[],n=0,s=t.length;s>n;n++)e.push(t[n].pageX),i.push(t[n].pageY);return{pageX:(Math.min.apply(Math,e)+Math.max.apply(Math,e))/2,pageY:(Math.min.apply(Math,i)+Math.max.apply(Math,i))/2}},getVelocity:function(t,e,i){return{x:Math.abs(e/t)||0,y:Math.abs(i/t)||0}},getAngle:function(t,e){var i=e.pageY-t.pageY,n=e.pageX-t.pageX;return 180*Math.atan2(i,n)/Math.PI},getDirection:function(t,e){var i=Math.abs(t.pageX-e.pageX),n=Math.abs(t.pageY-e.pageY);return i>=n?t.pageX-e.pageX>0?s.DIRECTION_LEFT:s.DIRECTION_RIGHT:t.pageY-e.pageY>0?s.DIRECTION_UP:s.DIRECTION_DOWN},getDistance:function(t,e){var i=e.pageX-t.pageX,n=e.pageY-t.pageY;return Math.sqrt(i*i+n*n)},getScale:function(t,e){return t.length>=2&&e.length>=2?this.getDistance(e[0],e[1])/this.getDistance(t[0],t[1]):1},getRotation:function(t,e){return t.length>=2&&e.length>=2?this.getAngle(e[1],e[0])-this.getAngle(t[1],t[0]):0},isVertical:function(t){return t==s.DIRECTION_UP||t==s.DIRECTION_DOWN},stopDefaultBrowserBehavior:function(t,e){var i,n=["webkit","khtml","moz","ms","o",""];if(e&&t.style){for(var s=0;n.length>s;s++)for(var o in e)e.hasOwnProperty(o)&&(i=o,n[s]&&(i=n[s]+i.substring(0,1).toUpperCase()+i.substring(1)),t.style[i]=e[o]);"none"==e.userSelect&&(t.onselectstart=function(){return!1})}}},s.detection={gestures:[],current:null,previous:null,stopped:!1,startDetect:function(t,e){this.current||(this.stopped=!1,this.current={inst:t,startEvent:s.utils.extend({},e),lastEvent:!1,name:""},this.detect(e))},detect:function(t){if(this.current&&!this.stopped){t=this.extendEventData(t);for(var e=this.current.inst.options,i=0,n=this.gestures.length;n>i;i++){var o=this.gestures[i];if(!this.stopped&&e[o.name]!==!1&&o.handler.call(o,t,this.current.inst)===!1){this.stopDetect();break}}return this.current&&(this.current.lastEvent=t),t.eventType==s.EVENT_END&&!t.touches.length-1&&this.stopDetect(),t}},stopDetect:function(){this.previous=s.utils.extend({},this.current),this.current=null,this.stopped=!0},extendEventData:function(t){var e=this.current.startEvent;if(e&&(t.touches.length!=e.touches.length||t.touches===e.touches)){e.touches=[];for(var i=0,n=t.touches.length;n>i;i++)e.touches.push(s.utils.extend({},t.touches[i]))}var o=t.timeStamp-e.timeStamp,r=t.center.pageX-e.center.pageX,a=t.center.pageY-e.center.pageY,h=s.utils.getVelocity(o,r,a);return s.utils.extend(t,{deltaTime:o,deltaX:r,deltaY:a,velocityX:h.x,velocityY:h.y,distance:s.utils.getDistance(e.center,t.center),angle:s.utils.getAngle(e.center,t.center),direction:s.utils.getDirection(e.center,t.center),scale:s.utils.getScale(e.touches,t.touches),rotation:s.utils.getRotation(e.touches,t.touches),startEvent:e}),t},register:function(t){var e=t.defaults||{};return e[t.name]===i&&(e[t.name]=!0),s.utils.extend(s.defaults,e,!0),t.index=t.index||1e3,this.gestures.push(t),this.gestures.sort(function(t,e){return t.indexe.index?1:0}),this.gestures}},s.gestures=s.gestures||{},s.gestures.Hold={name:"hold",index:10,defaults:{hold_timeout:500,hold_threshold:1},timer:null,handler:function(t,e){switch(t.eventType){case s.EVENT_START:clearTimeout(this.timer),s.detection.current.name=this.name,this.timer=setTimeout(function(){"hold"==s.detection.current.name&&e.trigger("hold",t)},e.options.hold_timeout);break;case s.EVENT_MOVE:t.distance>e.options.hold_threshold&&clearTimeout(this.timer);break;case s.EVENT_END:clearTimeout(this.timer)}}},s.gestures.Tap={name:"tap",index:100,defaults:{tap_max_touchtime:250,tap_max_distance:10,tap_always:!0,doubletap_distance:20,doubletap_interval:300},handler:function(t,e){if(t.eventType==s.EVENT_END){var i=s.detection.previous,n=!1;if(t.deltaTime>e.options.tap_max_touchtime||t.distance>e.options.tap_max_distance)return;i&&"tap"==i.name&&t.timeStamp-i.lastEvent.timeStamp0&&t.touches.length>e.options.swipe_max_touches)return;(t.velocityX>e.options.swipe_velocity||t.velocityY>e.options.swipe_velocity)&&(e.trigger(this.name,t),e.trigger(this.name+t.direction,t))}}},s.gestures.Drag={name:"drag",index:50,defaults:{drag_min_distance:10,drag_max_touches:1,drag_block_horizontal:!1,drag_block_vertical:!1,drag_lock_to_axis:!1,drag_lock_min_distance:25},triggered:!1,handler:function(t,e){if(s.detection.current.name!=this.name&&this.triggered)return e.trigger(this.name+"end",t),this.triggered=!1,i;if(!(e.options.drag_max_touches>0&&t.touches.length>e.options.drag_max_touches))switch(t.eventType){case s.EVENT_START:this.triggered=!1;break;case s.EVENT_MOVE:if(t.distancet.deltaY?s.DIRECTION_UP:s.DIRECTION_DOWN:0>t.deltaX?s.DIRECTION_LEFT:s.DIRECTION_RIGHT),this.triggered||(e.trigger(this.name+"start",t),this.triggered=!0),e.trigger(this.name,t),e.trigger(this.name+t.direction,t),(e.options.drag_block_vertical&&s.utils.isVertical(t.direction)||e.options.drag_block_horizontal&&!s.utils.isVertical(t.direction))&&t.preventDefault();break;case s.EVENT_END:this.triggered&&e.trigger(this.name+"end",t),this.triggered=!1}}},s.gestures.Transform={name:"transform",index:45,defaults:{transform_min_scale:.01,transform_min_rotation:1,transform_always_block:!1},triggered:!1,handler:function(t,e){if(s.detection.current.name!=this.name&&this.triggered)return e.trigger(this.name+"end",t),this.triggered=!1,i;if(!(2>t.touches.length))switch(e.options.transform_always_block&&t.preventDefault(),t.eventType){case s.EVENT_START:this.triggered=!1;break;case s.EVENT_MOVE:var n=Math.abs(1-t.scale),o=Math.abs(t.rotation);if(e.options.transform_min_scale>n&&e.options.transform_min_rotation>o)return;s.detection.current.name=this.name,this.triggered||(e.trigger(this.name+"start",t),this.triggered=!0),e.trigger(this.name,t),o>e.options.transform_min_rotation&&e.trigger("rotate",t),n>e.options.transform_min_scale&&(e.trigger("pinch",t),e.trigger("pinch"+(1>t.scale?"in":"out"),t));break;case s.EVENT_END:this.triggered&&e.trigger(this.name+"end",t),this.triggered=!1}}},s.gestures.Touch={name:"touch",index:-1/0,defaults:{prevent_default:!1,prevent_mouseevents:!1},handler:function(t,e){return e.options.prevent_mouseevents&&t.pointerType==s.POINTER_MOUSE?(t.stopDetect(),i):(e.options.prevent_default&&t.preventDefault(),t.eventType==s.EVENT_START&&e.trigger(this.name,t),i)}},s.gestures.Release={name:"release",index:1/0,handler:function(t,e){t.eventType==s.EVENT_END&&e.trigger(this.name,t)}},"object"==typeof e&&"object"==typeof e.exports?e.exports=s:(t.Hammer=s,"function"==typeof t.define&&t.define.amd&&t.define("hammer",[],function(){return s}))})(this)},{}],2:[function(e,i){(function(n){function s(t,e){return function(i){return p(t.call(this,i),e)}}function o(t,e){return function(i){return this.lang().ordinal(t.call(this,i),e)}}function r(){}function a(t){d(this,t)}function h(t){var e=t.years||t.year||t.y||0,i=t.months||t.month||t.M||0,n=t.weeks||t.week||t.w||0,s=t.days||t.day||t.d||0,o=t.hours||t.hour||t.h||0,r=t.minutes||t.minute||t.m||0,a=t.seconds||t.second||t.s||0,h=t.milliseconds||t.millisecond||t.ms||0;this._input=t,this._milliseconds=+h+1e3*a+6e4*r+36e5*o,this._days=+s+7*n,this._months=+i+12*e,this._data={},this._bubble()}function d(t,e){for(var i in e)e.hasOwnProperty(i)&&(t[i]=e[i]);return t}function l(t){return 0>t?Math.ceil(t):Math.floor(t)}function p(t,e){for(var i=t+"";e>i.length;)i="0"+i;return i}function c(t,e,i,n){var s,o,r=e._milliseconds,a=e._days,h=e._months;r&&t._d.setTime(+t._d+r*i),(a||h)&&(s=t.minute(),o=t.hour()),a&&t.date(t.date()+a*i),h&&t.month(t.month()+h*i),r&&!n&&H.updateOffset(t),(a||h)&&(t.minute(s),t.hour(o))}function u(t){return"[object Array]"===Object.prototype.toString.call(t)}function f(t,e){var i,n=Math.min(t.length,e.length),s=Math.abs(t.length-e.length),o=0;for(i=0;n>i;i++)~~t[i]!==~~e[i]&&o++;return o+s}function m(t){return t?pe[t]||t.toLowerCase().replace(/(.)s$/,"$1"):t}function g(t,e){return e.abbr=t,V[t]||(V[t]=new r),V[t].set(e),V[t]}function v(t){delete V[t]}function y(t){if(!t)return H.fn._lang;if(!V[t]&&B)try{e("./lang/"+t)}catch(i){return H.fn._lang}return V[t]||H.fn._lang}function b(t){return t.match(/\[.*\]/)?t.replace(/^\[|\]$/g,""):t.replace(/\\/g,"")}function w(t){var e,i,n=t.match(X);for(e=0,i=n.length;i>e;e++)n[e]=me[n[e]]?me[n[e]]:b(n[e]);return function(s){var o="";for(e=0;i>e;e++)o+=n[e]instanceof Function?n[e].call(s,t):n[e];return o}}function _(t,e){return e=E(e,t.lang()),ce[e]||(ce[e]=w(e)),ce[e](t)}function E(t,e){function i(t){return e.longDateFormat(t)||t}for(var n=5;n--&&(Z.lastIndex=0,Z.test(t));)t=t.replace(Z,i);return t}function T(t,e){switch(t){case"DDDD":return Q;case"YYYY":return $;case"YYYYY":return te;case"S":case"SS":case"SSS":case"DDD":return J;case"MMM":case"MMMM":case"dd":case"ddd":case"dddd":return ee;case"a":case"A":return y(e._l)._meridiemParse;case"X":return se;case"Z":case"ZZ":return ie;case"T":return ne;case"MM":case"DD":case"YY":case"HH":case"hh":case"mm":case"ss":case"M":case"D":case"d":case"H":case"h":case"m":case"s":return K;default:return RegExp(t.replace("\\",""))}}function x(t){var e=(ie.exec(t)||[])[0],i=(e+"").match(he)||["-",0,0],n=+(60*i[1])+~~i[2];return"+"===i[0]?-n:n}function S(t,e,i){var n,s=i._a;switch(t){case"M":case"MM":null!=e&&(s[1]=~~e-1);break;case"MMM":case"MMMM":n=y(i._l).monthsParse(e),null!=n?s[1]=n:i._isValid=!1;break;case"D":case"DD":null!=e&&(s[2]=~~e);break;case"DDD":case"DDDD":null!=e&&(s[1]=0,s[2]=~~e);break;case"YY":s[0]=~~e+(~~e>68?1900:2e3);break;case"YYYY":case"YYYYY":s[0]=~~e;break;case"a":case"A":i._isPm=y(i._l).isPM(e);break;case"H":case"HH":case"h":case"hh":s[3]=~~e;break;case"m":case"mm":s[4]=~~e;break;case"s":case"ss":s[5]=~~e;break;case"S":case"SS":case"SSS":s[6]=~~(1e3*("0."+e));break;case"X":i._d=new Date(1e3*parseFloat(e));break;case"Z":case"ZZ":i._useUTC=!0,i._tzm=x(e)}null==e&&(i._isValid=!1)}function M(t){var e,i,n,s=[];if(!t._d){for(n=C(t),e=0;3>e&&null==t._a[e];++e)t._a[e]=s[e]=n[e];for(;7>e;e++)t._a[e]=s[e]=null==t._a[e]?2===e?1:0:t._a[e];s[3]+=~~((t._tzm||0)/60),s[4]+=~~((t._tzm||0)%60),i=new Date(0),t._useUTC?(i.setUTCFullYear(s[0],s[1],s[2]),i.setUTCHours(s[3],s[4],s[5],s[6])):(i.setFullYear(s[0],s[1],s[2]),i.setHours(s[3],s[4],s[5],s[6])),t._d=i}}function D(t){var e=t._i;t._d||(t._a=[e.years||e.year||e.y,e.months||e.month||e.M,e.days||e.day||e.d,e.hours||e.hour||e.h,e.minutes||e.minute||e.m,e.seconds||e.second||e.s,e.milliseconds||e.millisecond||e.ms],M(t))}function C(t){var e=new Date;return t._useUTC?[e.getUTCFullYear(),e.getUTCMonth(),e.getUTCDate()]:[e.getFullYear(),e.getMonth(),e.getDate()]}function O(t){var e,i,n,s=y(t._l),o=""+t._i;for(n=E(t._f,s).match(X),t._a=[],e=0;n.length>e;e++)i=(T(n[e],t).exec(o)||[])[0],i&&(o=o.slice(o.indexOf(i)+i.length)),me[n[e]]&&S(n[e],i,t);o&&(t._il=o),t._isPm&&12>t._a[3]&&(t._a[3]+=12),t._isPm===!1&&12===t._a[3]&&(t._a[3]=0),M(t)}function N(t){var e,i,n,s,o,r=99;for(s=0;t._f.length>s;s++)e=d({},t),e._f=t._f[s],O(e),i=new a(e),o=f(e._a,i.toArray()),i._il&&(o+=i._il.length),r>o&&(r=o,n=i);d(t,n)}function L(t){var e,i=t._i,n=oe.exec(i);if(n){for(t._f="YYYY-MM-DD"+(n[2]||" "),e=0;4>e;e++)if(ae[e][1].exec(i)){t._f+=ae[e][0];break}ie.exec(i)&&(t._f+=" Z"),O(t)}else t._d=new Date(i)}function k(t){var e=t._i,i=q.exec(e);e===n?t._d=new Date:i?t._d=new Date(+i[1]):"string"==typeof e?L(t):u(e)?(t._a=e.slice(0),M(t)):e instanceof Date?t._d=new Date(+e):"object"==typeof e?D(t):t._d=new Date(e)}function I(t,e,i,n,s){return s.relativeTime(e||1,!!i,t,n)}function A(t,e,i){var n=W(Math.abs(t)/1e3),s=W(n/60),o=W(s/60),r=W(o/24),a=W(r/365),h=45>n&&["s",n]||1===s&&["m"]||45>s&&["mm",s]||1===o&&["h"]||22>o&&["hh",o]||1===r&&["d"]||25>=r&&["dd",r]||45>=r&&["M"]||345>r&&["MM",W(r/30)]||1===a&&["y"]||["yy",a];return h[2]=e,h[3]=t>0,h[4]=i,I.apply({},h)}function P(t,e,i){var n,s=i-e,o=i-t.day();return o>s&&(o-=7),s-7>o&&(o+=7),n=H(t).add("d",o),{week:Math.ceil(n.dayOfYear()/7),year:n.year()}}function F(t){var e=t._i,i=t._f;return null===e||""===e?null:("string"==typeof e&&(t._i=e=y().preparse(e)),H.isMoment(e)?(t=d({},e),t._d=new Date(+e._d)):i?u(i)?N(t):O(t):k(t),new a(t))}function Y(t,e){H.fn[t]=H.fn[t+"s"]=function(t){var i=this._isUTC?"UTC":"";return null!=t?(this._d["set"+i+e](t),H.updateOffset(this),this):this._d["get"+i+e]()}}function R(t){H.duration.fn[t]=function(){return this._data[t]}}function z(t,e){H.duration.fn["as"+t]=function(){return+this/e}}for(var H,U,j="2.2.1",W=Math.round,V={},B=i!==n&&i.exports,q=/^\/?Date\((\-?\d+)/i,G=/(\-)?(?:(\d*)\.)?(\d+)\:(\d+)\:(\d+)\.?(\d{3})?/,X=/(\[[^\[]*\])|(\\)?(Mo|MM?M?M?|Do|DDDo|DD?D?D?|ddd?d?|do?|w[o|w]?|W[o|W]?|YYYYY|YYYY|YY|gg(ggg?)?|GG(GGG?)?|e|E|a|A|hh?|HH?|mm?|ss?|SS?S?|X|zz?|ZZ?|.)/g,Z=/(\[[^\[]*\])|(\\)?(LT|LL?L?L?|l{1,4})/g,K=/\d\d?/,J=/\d{1,3}/,Q=/\d{3}/,$=/\d{1,4}/,te=/[+\-]?\d{1,6}/,ee=/[0-9]*['a-z\u00A0-\u05FF\u0700-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF]+|[\u0600-\u06FF\/]+(\s*?[\u0600-\u06FF]+){1,2}/i,ie=/Z|[\+\-]\d\d:?\d\d/i,ne=/T/i,se=/[\+\-]?\d+(\.\d{1,3})?/,oe=/^\s*\d{4}-\d\d-\d\d((T| )(\d\d(:\d\d(:\d\d(\.\d\d?\d?)?)?)?)?([\+\-]\d\d:?\d\d)?)?/,re="YYYY-MM-DDTHH:mm:ssZ",ae=[["HH:mm:ss.S",/(T| )\d\d:\d\d:\d\d\.\d{1,3}/],["HH:mm:ss",/(T| )\d\d:\d\d:\d\d/],["HH:mm",/(T| )\d\d:\d\d/],["HH",/(T| )\d\d/]],he=/([\+\-]|\d\d)/gi,de="Date|Hours|Minutes|Seconds|Milliseconds".split("|"),le={Milliseconds:1,Seconds:1e3,Minutes:6e4,Hours:36e5,Days:864e5,Months:2592e6,Years:31536e6},pe={ms:"millisecond",s:"second",m:"minute",h:"hour",d:"day",w:"week",W:"isoweek",M:"month",y:"year"},ce={},ue="DDD w W M D d".split(" "),fe="M D H h m s w W".split(" "),me={M:function(){return this.month()+1},MMM:function(t){return this.lang().monthsShort(this,t)},MMMM:function(t){return this.lang().months(this,t)},D:function(){return this.date()},DDD:function(){return this.dayOfYear()},d:function(){return this.day()},dd:function(t){return this.lang().weekdaysMin(this,t)},ddd:function(t){return this.lang().weekdaysShort(this,t)},dddd:function(t){return this.lang().weekdays(this,t)},w:function(){return this.week()},W:function(){return this.isoWeek()},YY:function(){return p(this.year()%100,2)},YYYY:function(){return p(this.year(),4)},YYYYY:function(){return p(this.year(),5)},gg:function(){return p(this.weekYear()%100,2)},gggg:function(){return this.weekYear()},ggggg:function(){return p(this.weekYear(),5)},GG:function(){return p(this.isoWeekYear()%100,2)},GGGG:function(){return this.isoWeekYear()},GGGGG:function(){return p(this.isoWeekYear(),5)},e:function(){return this.weekday()},E:function(){return this.isoWeekday()},a:function(){return this.lang().meridiem(this.hours(),this.minutes(),!0)},A:function(){return this.lang().meridiem(this.hours(),this.minutes(),!1)},H:function(){return this.hours()},h:function(){return this.hours()%12||12},m:function(){return this.minutes()},s:function(){return this.seconds()},S:function(){return~~(this.milliseconds()/100)},SS:function(){return p(~~(this.milliseconds()/10),2)},SSS:function(){return p(this.milliseconds(),3)},Z:function(){var t=-this.zone(),e="+";return 0>t&&(t=-t,e="-"),e+p(~~(t/60),2)+":"+p(~~t%60,2)},ZZ:function(){var t=-this.zone(),e="+";return 0>t&&(t=-t,e="-"),e+p(~~(10*t/6),4)},z:function(){return this.zoneAbbr()},zz:function(){return this.zoneName()},X:function(){return this.unix()}};ue.length;)U=ue.pop(),me[U+"o"]=o(me[U],U);for(;fe.length;)U=fe.pop(),me[U+U]=s(me[U],2);for(me.DDDD=s(me.DDD,3),d(r.prototype,{set:function(t){var e,i;for(i in t)e=t[i],"function"==typeof e?this[i]=e:this["_"+i]=e},_months:"January_February_March_April_May_June_July_August_September_October_November_December".split("_"),months:function(t){return this._months[t.month()]},_monthsShort:"Jan_Feb_Mar_Apr_May_Jun_Jul_Aug_Sep_Oct_Nov_Dec".split("_"),monthsShort:function(t){return this._monthsShort[t.month()]},monthsParse:function(t){var e,i,n;for(this._monthsParse||(this._monthsParse=[]),e=0;12>e;e++)if(this._monthsParse[e]||(i=H.utc([2e3,e]),n="^"+this.months(i,"")+"|^"+this.monthsShort(i,""),this._monthsParse[e]=RegExp(n.replace(".",""),"i")),this._monthsParse[e].test(t))return e},_weekdays:"Sunday_Monday_Tuesday_Wednesday_Thursday_Friday_Saturday".split("_"),weekdays:function(t){return this._weekdays[t.day()]},_weekdaysShort:"Sun_Mon_Tue_Wed_Thu_Fri_Sat".split("_"),weekdaysShort:function(t){return this._weekdaysShort[t.day()]},_weekdaysMin:"Su_Mo_Tu_We_Th_Fr_Sa".split("_"),weekdaysMin:function(t){return this._weekdaysMin[t.day()]},weekdaysParse:function(t){var e,i,n;for(this._weekdaysParse||(this._weekdaysParse=[]),e=0;7>e;e++)if(this._weekdaysParse[e]||(i=H([2e3,1]).day(e),n="^"+this.weekdays(i,"")+"|^"+this.weekdaysShort(i,"")+"|^"+this.weekdaysMin(i,""),this._weekdaysParse[e]=RegExp(n.replace(".",""),"i")),this._weekdaysParse[e].test(t))return e},_longDateFormat:{LT:"h:mm A",L:"MM/DD/YYYY",LL:"MMMM D YYYY",LLL:"MMMM D YYYY LT",LLLL:"dddd, MMMM D YYYY LT"},longDateFormat:function(t){var e=this._longDateFormat[t];return!e&&this._longDateFormat[t.toUpperCase()]&&(e=this._longDateFormat[t.toUpperCase()].replace(/MMMM|MM|DD|dddd/g,function(t){return t.slice(1)}),this._longDateFormat[t]=e),e},isPM:function(t){return"p"===(t+"").toLowerCase().charAt(0)},_meridiemParse:/[ap]\.?m?\.?/i,meridiem:function(t,e,i){return t>11?i?"pm":"PM":i?"am":"AM"},_calendar:{sameDay:"[Today at] LT",nextDay:"[Tomorrow at] LT",nextWeek:"dddd [at] LT",lastDay:"[Yesterday at] LT",lastWeek:"[Last] dddd [at] LT",sameElse:"L"},calendar:function(t,e){var i=this._calendar[t];return"function"==typeof i?i.apply(e):i},_relativeTime:{future:"in %s",past:"%s ago",s:"a few seconds",m:"a minute",mm:"%d minutes",h:"an hour",hh:"%d hours",d:"a day",dd:"%d days",M:"a month",MM:"%d months",y:"a year",yy:"%d years"},relativeTime:function(t,e,i,n){var s=this._relativeTime[i];return"function"==typeof s?s(t,e,i,n):s.replace(/%d/i,t)},pastFuture:function(t,e){var i=this._relativeTime[t>0?"future":"past"];return"function"==typeof i?i(e):i.replace(/%s/i,e)},ordinal:function(t){return this._ordinal.replace("%d",t)},_ordinal:"%d",preparse:function(t){return t},postformat:function(t){return t},week:function(t){return P(t,this._week.dow,this._week.doy).week},_week:{dow:0,doy:6}}),H=function(t,e,i){return F({_i:t,_f:e,_l:i,_isUTC:!1})},H.utc=function(t,e,i){return F({_useUTC:!0,_isUTC:!0,_l:i,_i:t,_f:e}).utc()},H.unix=function(t){return H(1e3*t)},H.duration=function(t,e){var i,n,s=H.isDuration(t),o="number"==typeof t,r=s?t._input:o?{}:t,a=G.exec(t);return o?e?r[e]=t:r.milliseconds=t:a&&(i="-"===a[1]?-1:1,r={y:0,d:~~a[2]*i,h:~~a[3]*i,m:~~a[4]*i,s:~~a[5]*i,ms:~~a[6]*i}),n=new h(r),s&&t.hasOwnProperty("_lang")&&(n._lang=t._lang),n},H.version=j,H.defaultFormat=re,H.updateOffset=function(){},H.lang=function(t,e){return t?(t=t.toLowerCase(),t=t.replace("_","-"),e?g(t,e):null===e?(v(t),t="en"):V[t]||y(t),H.duration.fn._lang=H.fn._lang=y(t),n):H.fn._lang._abbr},H.langData=function(t){return t&&t._lang&&t._lang._abbr&&(t=t._lang._abbr),y(t)},H.isMoment=function(t){return t instanceof a},H.isDuration=function(t){return t instanceof h},d(H.fn=a.prototype,{clone:function(){return H(this)},valueOf:function(){return+this._d+6e4*(this._offset||0)},unix:function(){return Math.floor(+this/1e3)},toString:function(){return this.format("ddd MMM DD YYYY HH:mm:ss [GMT]ZZ")},toDate:function(){return this._offset?new Date(+this):this._d},toISOString:function(){return _(H(this).utc(),"YYYY-MM-DD[T]HH:mm:ss.SSS[Z]")},toArray:function(){var t=this;return[t.year(),t.month(),t.date(),t.hours(),t.minutes(),t.seconds(),t.milliseconds()]},isValid:function(){return null==this._isValid&&(this._isValid=this._a?!f(this._a,(this._isUTC?H.utc(this._a):H(this._a)).toArray()):!isNaN(this._d.getTime())),!!this._isValid},invalidAt:function(){var t,e=this._a,i=(this._isUTC?H.utc(this._a):H(this._a)).toArray();for(t=6;t>=0&&e[t]===i[t];--t);return t},utc:function(){return this.zone(0)},local:function(){return this.zone(0),this._isUTC=!1,this},format:function(t){var e=_(this,t||H.defaultFormat);return this.lang().postformat(e)},add:function(t,e){var i;return i="string"==typeof t?H.duration(+e,t):H.duration(t,e),c(this,i,1),this},subtract:function(t,e){var i;return i="string"==typeof t?H.duration(+e,t):H.duration(t,e),c(this,i,-1),this},diff:function(t,e,i){var n,s,o=this._isUTC?H(t).zone(this._offset||0):H(t).local(),r=6e4*(this.zone()-o.zone());return e=m(e),"year"===e||"month"===e?(n=432e5*(this.daysInMonth()+o.daysInMonth()),s=12*(this.year()-o.year())+(this.month()-o.month()),s+=(this-H(this).startOf("month")-(o-H(o).startOf("month")))/n,s-=6e4*(this.zone()-H(this).startOf("month").zone()-(o.zone()-H(o).startOf("month").zone()))/n,"year"===e&&(s/=12)):(n=this-o,s="second"===e?n/1e3:"minute"===e?n/6e4:"hour"===e?n/36e5:"day"===e?(n-r)/864e5:"week"===e?(n-r)/6048e5:n),i?s:l(s)},from:function(t,e){return H.duration(this.diff(t)).lang(this.lang()._abbr).humanize(!e)},fromNow:function(t){return this.from(H(),t)},calendar:function(){var t=this.diff(H().zone(this.zone()).startOf("day"),"days",!0),e=-6>t?"sameElse":-1>t?"lastWeek":0>t?"lastDay":1>t?"sameDay":2>t?"nextDay":7>t?"nextWeek":"sameElse";return this.format(this.lang().calendar(e,this))},isLeapYear:function(){var t=this.year();return 0===t%4&&0!==t%100||0===t%400},isDST:function(){return this.zone()+H(t).startOf(e)},isBefore:function(t,e){return e=e!==n?e:"millisecond",+this.clone().startOf(e)<+H(t).startOf(e)},isSame:function(t,e){return e=e!==n?e:"millisecond",+this.clone().startOf(e)===+H(t).startOf(e)},min:function(t){return t=H.apply(null,arguments),this>t?this:t},max:function(t){return t=H.apply(null,arguments),t>this?this:t},zone:function(t){var e=this._offset||0;return null==t?this._isUTC?e:this._d.getTimezoneOffset():("string"==typeof t&&(t=x(t)),16>Math.abs(t)&&(t=60*t),this._offset=t,this._isUTC=!0,e!==t&&c(this,H.duration(e-t,"m"),1,!0),this)},zoneAbbr:function(){return this._isUTC?"UTC":""},zoneName:function(){return this._isUTC?"Coordinated Universal Time":""},hasAlignedHourOffset:function(t){return t=t?H(t).zone():0,0===(this.zone()-t)%60},daysInMonth:function(){return H.utc([this.year(),this.month()+1,0]).date()},dayOfYear:function(t){var e=W((H(this).startOf("day")-H(this).startOf("year"))/864e5)+1;return null==t?e:this.add("d",t-e)},weekYear:function(t){var e=P(this,this.lang()._week.dow,this.lang()._week.doy).year;return null==t?e:this.add("y",t-e)},isoWeekYear:function(t){var e=P(this,1,4).year;return null==t?e:this.add("y",t-e)},week:function(t){var e=this.lang().week(this);return null==t?e:this.add("d",7*(t-e))},isoWeek:function(t){var e=P(this,1,4).week;return null==t?e:this.add("d",7*(t-e))},weekday:function(t){var e=(this._d.getDay()+7-this.lang()._week.dow)%7;return null==t?e:this.add("d",t-e)},isoWeekday:function(t){return null==t?this.day()||7:this.day(this.day()%7?t:t-7)},get:function(t){return t=m(t),this[t.toLowerCase()]()},set:function(t,e){t=m(t),this[t.toLowerCase()](e)},lang:function(t){return t===n?this._lang:(this._lang=y(t),this)}}),U=0;de.length>U;U++)Y(de[U].toLowerCase().replace(/s$/,""),de[U]);Y("year","FullYear"),H.fn.days=H.fn.day,H.fn.months=H.fn.month,H.fn.weeks=H.fn.week,H.fn.isoWeeks=H.fn.isoWeek,H.fn.toJSON=H.fn.toISOString,d(H.duration.fn=h.prototype,{_bubble:function(){var t,e,i,n,s=this._milliseconds,o=this._days,r=this._months,a=this._data;a.milliseconds=s%1e3,t=l(s/1e3),a.seconds=t%60,e=l(t/60),a.minutes=e%60,i=l(e/60),a.hours=i%24,o+=l(i/24),a.days=o%30,r+=l(o/30),a.months=r%12,n=l(r/12),a.years=n},weeks:function(){return l(this.days()/7)},valueOf:function(){return this._milliseconds+864e5*this._days+2592e6*(this._months%12)+31536e6*~~(this._months/12)},humanize:function(t){var e=+this,i=A(e,!t,this.lang());return t&&(i=this.lang().pastFuture(e,i)),this.lang().postformat(i)},add:function(t,e){var i=H.duration(t,e);return this._milliseconds+=i._milliseconds,this._days+=i._days,this._months+=i._months,this._bubble(),this},subtract:function(t,e){var i=H.duration(t,e);return this._milliseconds-=i._milliseconds,this._days-=i._days,this._months-=i._months,this._bubble(),this},get:function(t){return t=m(t),this[t.toLowerCase()+"s"]()},as:function(t){return t=m(t),this["as"+t.charAt(0).toUpperCase()+t.slice(1)+"s"]()},lang:H.fn.lang});for(U in le)le.hasOwnProperty(U)&&(z(U,le[U]),R(U.toLowerCase()));z("Weeks",6048e5),H.duration.fn.asMonths=function(){return(+this-31536e6*this.years())/2592e6+12*this.years()},H.lang("en",{ordinal:function(t){var e=t%10,i=1===~~(t%100/10)?"th":1===e?"st":2===e?"nd":3===e?"rd":"th";return t+i}}),B&&(i.exports=H),"undefined"==typeof ender&&(this.moment=H),"function"==typeof t&&t.amd&&t("moment",[],function(){return H})}).call(this)},{}],3:[function(e,i,n){function s(){this.subscriptions=[]}function o(t){if(this.id=O.randomUUID(),this.options=t||{},this.data={},this.fieldId=this.options.fieldId||"id",this.convert={},this.options.convert)for(var e in this.options.convert)if(this.options.convert.hasOwnProperty(e)){var i=this.options.convert[e];this.convert[e]="Date"==i||"ISODate"==i||"ASPDate"==i?"Date":i +}this.subscribers={},this.internalIds={}}function r(t,e){this.id=O.randomUUID(),this.data=null,this.ids={},this.options=e||{},this.fieldId="id",this.subscribers={};var i=this;this.listener=function(){i._onEvent.apply(i,arguments)},this.setData(t)}function a(t,e){this.parent=t,this.options=e||{},this.defaultOptions={order:function(t,e){if(t instanceof y){if(e instanceof y){var i=t.data.end-t.data.start,n=e.data.end-e.data.start;return i-n||t.data.start-e.data.start}return-1}return e instanceof y?1:t.data.start-e.data.start},margin:{item:10}},this.ordered=[]}function h(t){this.id=O.randomUUID(),this.start=0,this.end=0,this.options={min:null,max:null,zoomMin:null,zoomMax:null},this.listeners=[],this.setOptions(t)}function d(){this.id=O.randomUUID(),this.components={},this.repaintTimer=void 0,this.reflowTimer=void 0}function l(){this.id=null,this.parent=null,this.depends=null,this.controller=null,this.options=null,this.frame=null,this.top=0,this.left=0,this.width=0,this.height=0}function p(t,e,i){this.id=O.randomUUID(),this.parent=t,this.depends=e,this.options=i||{}}function c(t,e){this.id=O.randomUUID(),this.container=t,this.options=e||{},this.defaultOptions={autoResize:!0},this.listeners={}}function u(t,e,i){this.id=O.randomUUID(),this.parent=t,this.depends=e,this.dom={majorLines:[],majorTexts:[],minorLines:[],minorTexts:[],redundant:{majorLines:[],majorTexts:[],minorLines:[],minorTexts:[]}},this.props={range:{start:0,end:0,minimumStep:0},lineTop:0},this.options=i||{},this.defaultOptions={orientation:"bottom",showMinorLabels:!0,showMajorLabels:!0},this.conversion=null,this.range=null}function f(t,e,i){this.id=O.randomUUID(),this.parent=t,this.depends=e,this.options=i||{},this.defaultOptions={type:"box",align:"center",orientation:"bottom",margin:{axis:20,item:10},padding:5},this.dom={};var n=this;this.itemsData=null,this.range=null,this.listeners={add:function(t,e,i){i!=n.id&&n._onAdd(e.items)},update:function(t,e,i){i!=n.id&&n._onUpdate(e.items)},remove:function(t,e,i){i!=n.id&&n._onRemove(e.items)}},this.items={},this.queue={},this.stack=new a(this,Object.create(this.options)),this.conversion=null}function m(t,e,i,n){this.parent=t,this.data=e,this.dom=null,this.options=i||{},this.defaultOptions=n||{},this.selected=!1,this.visible=!1,this.top=0,this.left=0,this.width=0,this.height=0}function g(t,e,i,n){this.props={dot:{left:0,top:0,width:0,height:0},line:{top:0,left:0,width:0,height:0}},m.call(this,t,e,i,n)}function v(t,e,i,n){this.props={dot:{top:0,width:0,height:0},content:{height:0,marginLeft:0}},m.call(this,t,e,i,n)}function y(t,e,i,n){this.props={content:{left:0,width:0}},m.call(this,t,e,i,n)}function b(t,e,i){this.id=O.randomUUID(),this.parent=t,this.groupId=e,this.itemset=null,this.options=i||{},this.options.top=0,this.props={label:{width:0,height:0}},this.top=0,this.left=0,this.width=0,this.height=0}function w(t,e,i){this.id=O.randomUUID(),this.parent=t,this.depends=e,this.options=i||{},this.range=null,this.itemsData=null,this.groupsData=null,this.groups={},this.dom={},this.props={labels:{width:0}},this.queue={};var n=this;this.listeners={add:function(t,e){n._onAdd(e.items)},update:function(t,e){n._onUpdate(e.items)},remove:function(t,e){n._onRemove(e.items)}}}function _(t,e,i){var n=this;if(this.options=O.extend({orientation:"bottom",min:null,max:null,zoomMin:10,zoomMax:31536e10,showMinorLabels:!0,showMajorLabels:!0,autoResize:!1},i),this.controller=new d,!t)throw Error("No container element provided");var s=Object.create(this.options);s.height=function(){return n.options.height?n.options.height:n.timeaxis.height+n.content.height},this.rootPanel=new c(t,s),this.controller.add(this.rootPanel);var o=Object.create(this.options);o.left=function(){return n.labelPanel.width},o.width=function(){return n.rootPanel.width-n.labelPanel.width},o.top=null,o.height=null,this.itemPanel=new p(this.rootPanel,[],o),this.controller.add(this.itemPanel);var r=Object.create(this.options);r.top=null,r.left=null,r.height=null,r.width=function(){return n.content&&"function"==typeof n.content.getLabelsWidth?n.content.getLabelsWidth():0},this.labelPanel=new p(this.rootPanel,[],r),this.controller.add(this.labelPanel);var a=M().hours(0).minutes(0).seconds(0).milliseconds(0);this.range=new h({start:a.clone().add("days",-3).valueOf(),end:a.clone().add("days",4).valueOf()}),this.range.subscribe(this.rootPanel,"move","horizontal"),this.range.subscribe(this.rootPanel,"zoom","horizontal"),this.range.on("rangechange",function(){var t=!0;n.controller.requestReflow(t)}),this.range.on("rangechanged",function(){var t=!0;n.controller.requestReflow(t)});var l=Object.create(s);l.range=this.range,l.left=null,l.top=null,l.width="100%",l.height=null,this.timeaxis=new u(this.itemPanel,[],l),this.timeaxis.setRange(this.range),this.controller.add(this.timeaxis),this.setGroups(null),this.itemsData=null,this.groupsData=null,e&&this.setItems(e)}function E(t,e,i,n){this.selected=!1,this.edges=[],this.group=n.nodes.group,this.fontSize=n.nodes.fontSize,this.fontFace=n.nodes.fontFace,this.fontColor=n.nodes.fontColor,this.color=n.nodes.color,this.id=void 0,this.shape=n.nodes.shape,this.image=n.nodes.image,this.x=0,this.y=0,this.xFixed=!1,this.yFixed=!1,this.radius=n.nodes.radius,this.radiusFixed=!1,this.radiusMin=n.nodes.radiusMin,this.radiusMax=n.nodes.radiusMax,this.imagelist=e,this.grouplist=i,this.setProperties(t,n),this.mass=50,this.fx=0,this.fy=0,this.vx=0,this.vy=0,this.minForce=n.minForce,this.damping=.9}function T(t,e,i){if(!e)throw"No graph provided";this.graph=e,this.widthMin=i.edges.widthMin,this.widthMax=i.edges.widthMax,this.id=void 0,this.fromId=void 0,this.toId=void 0,this.style=i.edges.style,this.title=void 0,this.width=i.edges.width,this.value=void 0,this.length=i.edges.length,this.from=null,this.to=null,this.connected=!1,this.dash=O.extend({},i.edges.dash),this.stiffness=void 0,this.color=i.edges.color,this.widthFixed=!1,this.lengthFixed=!1,this.setProperties(t,i)}function x(t,e,i,n){this.container=t?t:document.body,this.x=0,this.y=0,this.padding=5,void 0!==e&&void 0!==i&&this.setPosition(e,i),void 0!==n&&this.setText(n),this.frame=document.createElement("div");var s=this.frame.style;s.position="absolute",s.visibility="hidden",s.border="1px solid #666",s.color="black",s.padding=this.padding+"px",s.backgroundColor="#FFFFC6",s.borderRadius="3px",s.MozBorderRadius="3px",s.WebkitBorderRadius="3px",s.boxShadow="3px 3px 10px rgba(128, 128, 128, 0.5)",s.whiteSpace="nowrap",this.container.appendChild(this.frame)}function S(t,e,i){this.containerElement=t,this.width="100%",this.height="100%",this.refreshRate=50,this.stabilize=!0,this.selectable=!0,this.constants={nodes:{radiusMin:5,radiusMax:20,radius:5,distance:100,shape:"ellipse",image:void 0,widthMin:16,widthMax:64,fontColor:"black",fontSize:14,fontFace:"arial",color:{border:"#2B7CE9",background:"#97C2FC",highlight:{border:"#2B7CE9",background:"#D2E5FF"}},borderColor:"#2B7CE9",backgroundColor:"#97C2FC",highlightColor:"#D2E5FF",group:void 0},edges:{widthMin:1,widthMax:15,width:1,style:"line",color:"#343434",fontColor:"#343434",fontSize:14,fontFace:"arial",length:100,dash:{length:10,gap:5,altLength:void 0}},minForce:.05,minVelocity:.02,maxIterations:1e3};var n=this;this.nodes={},this.edges={},this.nodesData=null,this.edgesData=null;var s=this;this.nodesListeners={add:function(t,e){s._addNodes(e.items),s.start()},update:function(t,e){s._updateNodes(e.items),s.start()},remove:function(t,e){s._removeNodes(e.items),s.start()}},this.edgesListeners={add:function(t,e){s._addEdges(e.items),s.start()},update:function(t,e){s._updateEdges(e.items),s.start()},remove:function(t,e){s._removeEdges(e.items),s.start()}},this.groups=new Groups,this.images=new Images,this.images.setOnloadCallback(function(){n._redraw()}),this.moving=!1,this.selection=[],this.timer=void 0,this._create(),this.setOptions(i),this.setData(e)}var M="undefined"!=typeof window&&window.moment||e("moment"),D="undefined"!=typeof window&&window.Hammer||e("hammerjs");if(!Array.prototype.indexOf){Array.prototype.indexOf=function(t){for(var e=0;this.length>e;e++)if(this[e]==t)return e;return-1};try{console.log("Warning: Ancient browser detected. Please update your browser")}catch(C){}}Array.prototype.forEach||(Array.prototype.forEach=function(t,e){for(var i=0,n=this.length;n>i;++i)t.call(e||this,this[i],i,this)}),Array.prototype.map||(Array.prototype.map=function(t,e){var i,n,s;if(null==this)throw new TypeError(" this is null or not defined");var o=Object(this),r=o.length>>>0;if("function"!=typeof t)throw new TypeError(t+" is not a function");for(e&&(i=e),n=Array(r),s=0;r>s;){var a,h;s in o&&(a=o[s],h=t.call(i,a,s,o),n[s]=h),s++}return n}),Array.prototype.filter||(Array.prototype.filter=function(t){"use strict";if(null==this)throw new TypeError;var e=Object(this),i=e.length>>>0;if("function"!=typeof t)throw new TypeError;for(var n=[],s=arguments[1],o=0;i>o;o++)if(o in e){var r=e[o];t.call(s,r,o,e)&&n.push(r)}return n}),Object.keys||(Object.keys=function(){var t=Object.prototype.hasOwnProperty,e=!{toString:null}.propertyIsEnumerable("toString"),i=["toString","toLocaleString","valueOf","hasOwnProperty","isPrototypeOf","propertyIsEnumerable","constructor"],n=i.length;return function(s){if("object"!=typeof s&&"function"!=typeof s||null===s)throw new TypeError("Object.keys called on non-object");var o=[];for(var r in s)t.call(s,r)&&o.push(r);if(e)for(var a=0;n>a;a++)t.call(s,i[a])&&o.push(i[a]);return o}}()),Array.isArray||(Array.isArray=function(t){return"[object Array]"===Object.prototype.toString.call(t)}),Function.prototype.bind||(Function.prototype.bind=function(t){if("function"!=typeof this)throw new TypeError("Function.prototype.bind - what is trying to be bound is not callable");var e=Array.prototype.slice.call(arguments,1),i=this,n=function(){},s=function(){return i.apply(this instanceof n&&t?this:t,e.concat(Array.prototype.slice.call(arguments)))};return n.prototype=this.prototype,s.prototype=new n,s}),Object.create||(Object.create=function(t){function e(){}if(arguments.length>1)throw Error("Object.create implementation only accepts the first parameter.");return e.prototype=t,new e}),Function.prototype.bind||(Function.prototype.bind=function(t){if("function"!=typeof this)throw new TypeError("Function.prototype.bind - what is trying to be bound is not callable");var e=Array.prototype.slice.call(arguments,1),i=this,n=function(){},s=function(){return i.apply(this instanceof n&&t?this:t,e.concat(Array.prototype.slice.call(arguments)))};return n.prototype=this.prototype,s.prototype=new n,s});var O={};O.isNumber=function(t){return t instanceof Number||"number"==typeof t},O.isString=function(t){return t instanceof String||"string"==typeof t},O.isDate=function(t){if(t instanceof Date)return!0;if(O.isString(t)){var e=N.exec(t);if(e)return!0;if(!isNaN(Date.parse(t)))return!0}return!1},O.isDataTable=function(t){return"undefined"!=typeof google&&google.visualization&&google.visualization.DataTable&&t instanceof google.visualization.DataTable},O.randomUUID=function(){var t=function(){return Math.floor(65536*Math.random()).toString(16)};return t()+t()+"-"+t()+"-"+t()+"-"+t()+"-"+t()+t()+t()},O.extend=function(t){for(var e=1,i=arguments.length;i>e;e++){var n=arguments[e];for(var s in n)n.hasOwnProperty(s)&&void 0!==n[s]&&(t[s]=n[s])}return t},O.convert=function(t,e){var i;if(void 0===t)return void 0;if(null===t)return null;if(!e)return t;if("string"!=typeof e&&!(e instanceof String))throw Error("Type must be a string");switch(e){case"boolean":case"Boolean":return Boolean(t);case"number":case"Number":return Number(t.valueOf());case"string":case"String":return t+"";case"Date":if(O.isNumber(t))return new Date(t);if(t instanceof Date)return new Date(t.valueOf());if(M.isMoment(t))return new Date(t.valueOf());if(O.isString(t))return i=N.exec(t),i?new Date(Number(i[1])):M(t).toDate();throw Error("Cannot convert object of type "+O.getType(t)+" to type Date");case"Moment":if(O.isNumber(t))return M(t);if(t instanceof Date)return M(t.valueOf());if(M.isMoment(t))return M.clone();if(O.isString(t))return i=N.exec(t),i?M(Number(i[1])):M(t);throw Error("Cannot convert object of type "+O.getType(t)+" to type Date");case"ISODate":if(O.isNumber(t))return new Date(t);if(t instanceof Date)return t.toISOString();if(M.isMoment(t))return t.toDate().toISOString();if(O.isString(t))return i=N.exec(t),i?new Date(Number(i[1])).toISOString():new Date(t).toISOString();throw Error("Cannot convert object of type "+O.getType(t)+" to type ISODate");case"ASPDate":if(O.isNumber(t))return"/Date("+t+")/";if(t instanceof Date)return"/Date("+t.valueOf()+")/";if(O.isString(t)){i=N.exec(t);var n;return n=i?new Date(Number(i[1])).valueOf():new Date(t).valueOf(),"/Date("+n+")/"}throw Error("Cannot convert object of type "+O.getType(t)+" to type ASPDate");default:throw Error("Cannot convert object of type "+O.getType(t)+' to type "'+e+'"')}};var N=/^\/?Date\((\-?\d+)/i;O.getType=function(t){var e=typeof t;return"object"==e?null==t?"null":t instanceof Boolean?"Boolean":t instanceof Number?"Number":t instanceof String?"String":t instanceof Array?"Array":t instanceof Date?"Date":"Object":"number"==e?"Number":"boolean"==e?"Boolean":"string"==e?"String":e},O.getAbsoluteLeft=function(t){for(var e=document.documentElement,i=document.body,n=t.offsetLeft,s=t.offsetParent;null!=s&&s!=i&&s!=e;)n+=s.offsetLeft,n-=s.scrollLeft,s=s.offsetParent;return n},O.getAbsoluteTop=function(t){for(var e=document.documentElement,i=document.body,n=t.offsetTop,s=t.offsetParent;null!=s&&s!=i&&s!=e;)n+=s.offsetTop,n-=s.scrollTop,s=s.offsetParent;return n},O.getPageY=function(t){if("pageY"in t)return t.pageY;var e;e="targetTouches"in t&&t.targetTouches.length?t.targetTouches[0].clientY:t.clientY;var i=document.documentElement,n=document.body;return e+(i&&i.scrollTop||n&&n.scrollTop||0)-(i&&i.clientTop||n&&n.clientTop||0)},O.getPageX=function(t){if("pageY"in t)return t.pageX;var e;e="targetTouches"in t&&t.targetTouches.length?t.targetTouches[0].clientX:t.clientX;var i=document.documentElement,n=document.body;return e+(i&&i.scrollLeft||n&&n.scrollLeft||0)-(i&&i.clientLeft||n&&n.clientLeft||0)},O.addClassName=function(t,e){var i=t.className.split(" ");-1==i.indexOf(e)&&(i.push(e),t.className=i.join(" "))},O.removeClassName=function(t,e){var i=t.className.split(" "),n=i.indexOf(e);-1!=n&&(i.splice(n,1),t.className=i.join(" "))},O.forEach=function(t,e){var i,n;if(t instanceof Array)for(i=0,n=t.length;n>i;i++)e(t[i],i,t);else for(i in t)t.hasOwnProperty(i)&&e(t[i],i,t)},O.updateProperty=function(t,e,i){return t[e]!==i?(t[e]=i,!0):!1},O.addEventListener=function(t,e,i,n){t.addEventListener?(void 0===n&&(n=!1),"mousewheel"===e&&navigator.userAgent.indexOf("Firefox")>=0&&(e="DOMMouseScroll"),t.addEventListener(e,i,n)):t.attachEvent("on"+e,i)},O.removeEventListener=function(t,e,i,n){t.removeEventListener?(void 0===n&&(n=!1),"mousewheel"===e&&navigator.userAgent.indexOf("Firefox")>=0&&(e="DOMMouseScroll"),t.removeEventListener(e,i,n)):t.detachEvent("on"+e,i)},O.getTarget=function(t){t||(t=window.event);var e;return t.target?e=t.target:t.srcElement&&(e=t.srcElement),void 0!=e.nodeType&&3==e.nodeType&&(e=e.parentNode),e},O.stopPropagation=function(t){t||(t=window.event),t.stopPropagation?t.stopPropagation():t.cancelBubble=!0},O.preventDefault=function(t){t||(t=window.event),t.preventDefault?t.preventDefault():t.returnValue=!1},O.option={},O.option.asBoolean=function(t,e){return"function"==typeof t&&(t=t()),null!=t?0!=t:e||null},O.option.asNumber=function(t,e){return"function"==typeof t&&(t=t()),null!=t?Number(t)||e||null:e||null},O.option.asString=function(t,e){return"function"==typeof t&&(t=t()),null!=t?t+"":e||null},O.option.asSize=function(t,e){return"function"==typeof t&&(t=t()),O.isString(t)?t:O.isNumber(t)?t+"px":e||null},O.option.asElement=function(t,e){return"function"==typeof t&&(t=t()),t||e||null},O.loadCss=function(t){if("undefined"!=typeof document){var e=document.createElement("style");e.type="text/css",e.styleSheet?e.styleSheet.cssText=t:e.appendChild(document.createTextNode(t)),document.getElementsByTagName("head")[0].appendChild(e)}};var L={listeners:[],indexOf:function(t){for(var e=this.listeners,i=0,n=this.listeners.length;n>i;i++){var s=e[i];if(s&&s.object==t)return i}return-1},addListener:function(t,e,i){var n=this.indexOf(t),s=this.listeners[n];s||(s={object:t,events:{}},this.listeners.push(s));var o=s.events[e];o||(o=[],s.events[e]=o),-1==o.indexOf(i)&&o.push(i)},removeListener:function(t,e,i){var n=this.indexOf(t),s=this.listeners[n];if(s){var o=s.events[e];o&&(n=o.indexOf(i),-1!=n&&o.splice(n,1),0==o.length&&delete s.events[e]);var r=0,a=s.events;for(var h in a)a.hasOwnProperty(h)&&r++;0==r&&delete this.listeners[n]}},removeAllListeners:function(){this.listeners=[]},trigger:function(t,e,i){var n=this.indexOf(t),s=this.listeners[n];if(s){var o=s.events[e];if(o)for(var r=0,a=o.length;a>r;r++)o[r](i)}}};s.prototype.on=function(t,e,i){var n=t instanceof RegExp?t:RegExp(t.replace("*","\\w+")),s={id:O.randomUUID(),event:t,regexp:n,callback:"function"==typeof e?e:null,target:i};return this.subscriptions.push(s),s.id},s.prototype.off=function(t){for(var e=0;this.subscriptions.length>e;){var i=this.subscriptions[e],n=!0;if(t instanceof Object)for(var s in t)t.hasOwnProperty(s)&&t[s]!==i[s]&&(n=!1);else n=i.id==t;n?this.subscriptions.splice(e,1):e++}},s.prototype.emit=function(t,e,i){for(var n=0;this.subscriptions.length>n;n++){var s=this.subscriptions[n];s.regexp.test(t)&&s.callback&&s.callback(t,e,i)}},o.prototype.subscribe=function(t,e){var i=this.subscribers[t];i||(i=[],this.subscribers[t]=i),i.push({callback:e})},o.prototype.unsubscribe=function(t,e){var i=this.subscribers[t];i&&(this.subscribers[t]=i.filter(function(t){return t.callback!=e}))},o.prototype._trigger=function(t,e,i){if("*"==t)throw Error("Cannot trigger event *");var n=[];t in this.subscribers&&(n=n.concat(this.subscribers[t])),"*"in this.subscribers&&(n=n.concat(this.subscribers["*"]));for(var s=0;n.length>s;s++){var o=n[s];o.callback&&o.callback(t,e,i||null)}},o.prototype.add=function(t,e){var i,n=[],s=this;if(t instanceof Array)for(var o=0,r=t.length;r>o;o++)i=s._addItem(t[o]),n.push(i);else if(O.isDataTable(t))for(var a=this._getColumnNames(t),h=0,d=t.getNumberOfRows();d>h;h++){for(var l={},p=0,c=a.length;c>p;p++){var u=a[p];l[u]=t.getValue(h,p)}i=s._addItem(l),n.push(i)}else{if(!(t instanceof Object))throw Error("Unknown dataType");i=s._addItem(t),n.push(i)}return n.length&&this._trigger("add",{items:n},e),n},o.prototype.update=function(t,e){var i=[],n=[],s=this,o=s.fieldId,r=function(t){var e=t[o];s.data[e]?(e=s._updateItem(t),n.push(e)):(e=s._addItem(t),i.push(e))};if(t instanceof Array)for(var a=0,h=t.length;h>a;a++)r(t[a]);else if(O.isDataTable(t))for(var d=this._getColumnNames(t),l=0,p=t.getNumberOfRows();p>l;l++){for(var c={},u=0,f=d.length;f>u;u++){var m=d[u];c[m]=t.getValue(l,u)}r(c)}else{if(!(t instanceof Object))throw Error("Unknown dataType");r(t)}return i.length&&this._trigger("add",{items:i},e),n.length&&this._trigger("update",{items:n},e),i.concat(n)},o.prototype.get=function(){var t,e,i,n,s=this,o=O.getType(arguments[0]);"String"==o||"Number"==o?(t=arguments[0],i=arguments[1],n=arguments[2]):"Array"==o?(e=arguments[0],i=arguments[1],n=arguments[2]):(i=arguments[0],n=arguments[1]);var r;if(i&&i.type){if(r="DataTable"==i.type?"DataTable":"Array",n&&r!=O.getType(n))throw Error('Type of parameter "data" ('+O.getType(n)+") "+"does not correspond with specified options.type ("+i.type+")");if("DataTable"==r&&!O.isDataTable(n))throw Error('Parameter "data" must be a DataTable when options.type is "DataTable"')}else r=n?"DataTable"==O.getType(n)?"DataTable":"Array":"Array";var a,h,d,l,p=i&&i.convert||this.options.convert,c=i&&i.filter,u=[];if(void 0!=t)a=s._getItem(t,p),c&&!c(a)&&(a=null);else if(void 0!=e)for(d=0,l=e.length;l>d;d++)a=s._getItem(e[d],p),(!c||c(a))&&u.push(a);else for(h in this.data)this.data.hasOwnProperty(h)&&(a=s._getItem(h,p),(!c||c(a))&&u.push(a));if(i&&i.order&&void 0==t&&this._sort(u,i.order),i&&i.fields){var f=i.fields;if(void 0!=t)a=this._filterFields(a,f);else for(d=0,l=u.length;l>d;d++)u[d]=this._filterFields(u[d],f)}if("DataTable"==r){var m=this._getColumnNames(n);if(void 0!=t)s._appendRow(n,m,a);else for(d=0,l=u.length;l>d;d++)s._appendRow(n,m,u[d]);return n}if(void 0!=t)return a;if(n){for(d=0,l=u.length;l>d;d++)n.push(u[d]);return n}return u},o.prototype.getIds=function(t){var e,i,n,s,o,r=this.data,a=t&&t.filter,h=t&&t.order,d=t&&t.convert||this.options.convert,l=[];if(a)if(h){o=[];for(n in r)r.hasOwnProperty(n)&&(s=this._getItem(n,d),a(s)&&o.push(s));for(this._sort(o,h),e=0,i=o.length;i>e;e++)l[e]=o[e][this.fieldId]}else for(n in r)r.hasOwnProperty(n)&&(s=this._getItem(n,d),a(s)&&l.push(s[this.fieldId]));else if(h){o=[];for(n in r)r.hasOwnProperty(n)&&o.push(r[n]);for(this._sort(o,h),e=0,i=o.length;i>e;e++)l[e]=o[e][this.fieldId]}else for(n in r)r.hasOwnProperty(n)&&(s=r[n],l.push(s[this.fieldId]));return l},o.prototype.forEach=function(t,e){var i,n,s=e&&e.filter,o=e&&e.convert||this.options.convert,r=this.data;if(e&&e.order)for(var a=this.get(e),h=0,d=a.length;d>h;h++)i=a[h],n=i[this.fieldId],t(i,n);else for(n in r)r.hasOwnProperty(n)&&(i=this._getItem(n,o),(!s||s(i))&&t(i,n))},o.prototype.map=function(t,e){var i,n=e&&e.filter,s=e&&e.convert||this.options.convert,o=[],r=this.data;for(var a in r)r.hasOwnProperty(a)&&(i=this._getItem(a,s),(!n||n(i))&&o.push(t(i,a)));return e&&e.order&&this._sort(o,e.order),o},o.prototype._filterFields=function(t,e){var i={};for(var n in t)t.hasOwnProperty(n)&&-1!=e.indexOf(n)&&(i[n]=t[n]);return i},o.prototype._sort=function(t,e){if(O.isString(e)){var i=e;t.sort(function(t,e){var n=t[i],s=e[i];return n>s?1:s>n?-1:0})}else{if("function"!=typeof e)throw new TypeError("Order must be a function or a string");t.sort(e)}},o.prototype.remove=function(t,e){var i,n,s,o=[];if(t instanceof Array)for(i=0,n=t.length;n>i;i++)s=this._remove(t[i]),null!=s&&o.push(s);else s=this._remove(t),null!=s&&o.push(s);return o.length&&this._trigger("remove",{items:o},e),o},o.prototype._remove=function(t){if(O.isNumber(t)||O.isString(t)){if(this.data[t])return delete this.data[t],delete this.internalIds[t],t}else if(t instanceof Object){var e=t[this.fieldId];if(e&&this.data[e])return delete this.data[e],delete this.internalIds[e],e}return null},o.prototype.clear=function(t){var e=Object.keys(this.data);return this.data={},this.internalIds={},this._trigger("remove",{items:e},t),e},o.prototype.max=function(t){var e=this.data,i=null,n=null;for(var s in e)if(e.hasOwnProperty(s)){var o=e[s],r=o[t];null!=r&&(!i||r>n)&&(i=o,n=r)}return i},o.prototype.min=function(t){var e=this.data,i=null,n=null;for(var s in e)if(e.hasOwnProperty(s)){var o=e[s],r=o[t];null!=r&&(!i||n>r)&&(i=o,n=r)}return i},o.prototype.distinct=function(t){var e=this.data,i=[],n=this.options.convert[t],s=0;for(var o in e)if(e.hasOwnProperty(o)){for(var r=e[o],a=O.convert(r[t],n),h=!1,d=0;s>d;d++)if(i[d]==a){h=!0;break}h||(i[s]=a,s++)}return i},o.prototype._addItem=function(t){var e=t[this.fieldId];if(void 0!=e){if(this.data[e])throw Error("Cannot add item: item with id "+e+" already exists")}else e=O.randomUUID(),t[this.fieldId]=e,this.internalIds[e]=t;var i={};for(var n in t)if(t.hasOwnProperty(n)){var s=this.convert[n];i[n]=O.convert(t[n],s)}return this.data[e]=i,e},o.prototype._getItem=function(t,e){var i,n,s=this.data[t];if(!s)return null;var o={},r=this.fieldId,a=this.internalIds;if(e)for(i in s)s.hasOwnProperty(i)&&(n=s[i],i==r&&n in a||(o[i]=O.convert(n,e[i])));else for(i in s)s.hasOwnProperty(i)&&(n=s[i],i==r&&n in a||(o[i]=n));return o},o.prototype._updateItem=function(t){var e=t[this.fieldId];if(void 0==e)throw Error("Cannot update item: item has no id (item: "+JSON.stringify(t)+")");var i=this.data[e];if(!i)throw Error("Cannot update item: no item with id "+e+" found");for(var n in t)if(t.hasOwnProperty(n)){var s=this.convert[n];i[n]=O.convert(t[n],s)}return e},o.prototype._getColumnNames=function(t){for(var e=[],i=0,n=t.getNumberOfColumns();n>i;i++)e[i]=t.getColumnId(i)||t.getColumnLabel(i);return e},o.prototype._appendRow=function(t,e,i){for(var n=t.addRow(),s=0,o=e.length;o>s;s++){var r=e[s];t.setValue(n,s,i[r])}},r.prototype.setData=function(t){var e,i,n;if(this.data){this.data.unsubscribe&&this.data.unsubscribe("*",this.listener),e=[];for(var s in this.ids)this.ids.hasOwnProperty(s)&&e.push(s);this.ids={},this._trigger("remove",{items:e})}if(this.data=t,this.data){for(this.fieldId=this.options.fieldId||this.data&&this.data.options&&this.data.options.fieldId||"id",e=this.data.getIds({filter:this.options&&this.options.filter}),i=0,n=e.length;n>i;i++)s=e[i],this.ids[s]=!0;this._trigger("add",{items:e}),this.data.subscribe&&this.data.subscribe("*",this.listener)}},r.prototype.get=function(){var t,e,i,n=this,s=O.getType(arguments[0]);"String"==s||"Number"==s||"Array"==s?(t=arguments[0],e=arguments[1],i=arguments[2]):(e=arguments[0],i=arguments[1]);var o=O.extend({},this.options,e);this.options.filter&&e&&e.filter&&(o.filter=function(t){return n.options.filter(t)&&e.filter(t)});var r=[];return void 0!=t&&r.push(t),r.push(o),r.push(i),this.data&&this.data.get.apply(this.data,r)},r.prototype.getIds=function(t){var e;if(this.data){var i,n=this.options.filter;i=t&&t.filter?n?function(e){return n(e)&&t.filter(e)}:t.filter:n,e=this.data.getIds({filter:i,order:t&&t.order})}else e=[];return e},r.prototype._onEvent=function(t,e,i){var n,s,o,r,a=e&&e.items,h=this.data,d=[],l=[],p=[];if(a&&h){switch(t){case"add":for(n=0,s=a.length;s>n;n++)o=a[n],r=this.get(o),r&&(this.ids[o]=!0,d.push(o));break;case"update":for(n=0,s=a.length;s>n;n++)o=a[n],r=this.get(o),r?this.ids[o]?l.push(o):(this.ids[o]=!0,d.push(o)):this.ids[o]&&(delete this.ids[o],p.push(o));break;case"remove":for(n=0,s=a.length;s>n;n++)o=a[n],this.ids[o]&&(delete this.ids[o],p.push(o))}d.length&&this._trigger("add",{items:d},i),l.length&&this._trigger("update",{items:l},i),p.length&&this._trigger("remove",{items:p},i)}},r.prototype.subscribe=o.prototype.subscribe,r.prototype.unsubscribe=o.prototype.unsubscribe,r.prototype._trigger=o.prototype._trigger,TimeStep=function(t,e,i){this.current=new Date,this._start=new Date,this._end=new Date,this.autoScale=!0,this.scale=TimeStep.SCALE.DAY,this.step=1,this.setRange(t,e,i)},TimeStep.SCALE={MILLISECOND:1,SECOND:2,MINUTE:3,HOUR:4,DAY:5,WEEKDAY:6,MONTH:7,YEAR:8},TimeStep.prototype.setRange=function(t,e,i){t instanceof Date&&e instanceof Date&&(this._start=void 0!=t?new Date(t.valueOf()):new Date,this._end=void 0!=e?new Date(e.valueOf()):new Date,this.autoScale&&this.setMinimumStep(i))},TimeStep.prototype.first=function(){this.current=new Date(this._start.valueOf()),this.roundToMinor()},TimeStep.prototype.roundToMinor=function(){switch(this.scale){case TimeStep.SCALE.YEAR:this.current.setFullYear(this.step*Math.floor(this.current.getFullYear()/this.step)),this.current.setMonth(0);case TimeStep.SCALE.MONTH:this.current.setDate(1);case TimeStep.SCALE.DAY:case TimeStep.SCALE.WEEKDAY:this.current.setHours(0);case TimeStep.SCALE.HOUR:this.current.setMinutes(0);case TimeStep.SCALE.MINUTE:this.current.setSeconds(0);case TimeStep.SCALE.SECOND:this.current.setMilliseconds(0)}if(1!=this.step)switch(this.scale){case TimeStep.SCALE.MILLISECOND:this.current.setMilliseconds(this.current.getMilliseconds()-this.current.getMilliseconds()%this.step);break;case TimeStep.SCALE.SECOND:this.current.setSeconds(this.current.getSeconds()-this.current.getSeconds()%this.step);break;case TimeStep.SCALE.MINUTE:this.current.setMinutes(this.current.getMinutes()-this.current.getMinutes()%this.step);break;case TimeStep.SCALE.HOUR:this.current.setHours(this.current.getHours()-this.current.getHours()%this.step);break;case TimeStep.SCALE.WEEKDAY:case TimeStep.SCALE.DAY:this.current.setDate(this.current.getDate()-1-(this.current.getDate()-1)%this.step+1);break;case TimeStep.SCALE.MONTH:this.current.setMonth(this.current.getMonth()-this.current.getMonth()%this.step);break;case TimeStep.SCALE.YEAR:this.current.setFullYear(this.current.getFullYear()-this.current.getFullYear()%this.step);break;default:}},TimeStep.prototype.hasNext=function(){return this.current.valueOf()<=this._end.valueOf()},TimeStep.prototype.next=function(){var t=this.current.valueOf();if(6>this.current.getMonth())switch(this.scale){case TimeStep.SCALE.MILLISECOND:this.current=new Date(this.current.valueOf()+this.step);break;case TimeStep.SCALE.SECOND:this.current=new Date(this.current.valueOf()+1e3*this.step);break;case TimeStep.SCALE.MINUTE:this.current=new Date(this.current.valueOf()+60*1e3*this.step);break;case TimeStep.SCALE.HOUR:this.current=new Date(this.current.valueOf()+60*60*1e3*this.step);var e=this.current.getHours();this.current.setHours(e-e%this.step);break;case TimeStep.SCALE.WEEKDAY:case TimeStep.SCALE.DAY:this.current.setDate(this.current.getDate()+this.step);break;case TimeStep.SCALE.MONTH:this.current.setMonth(this.current.getMonth()+this.step);break;case TimeStep.SCALE.YEAR:this.current.setFullYear(this.current.getFullYear()+this.step);break;default:}else switch(this.scale){case TimeStep.SCALE.MILLISECOND:this.current=new Date(this.current.valueOf()+this.step);break;case TimeStep.SCALE.SECOND:this.current.setSeconds(this.current.getSeconds()+this.step);break;case TimeStep.SCALE.MINUTE:this.current.setMinutes(this.current.getMinutes()+this.step);break;case TimeStep.SCALE.HOUR:this.current.setHours(this.current.getHours()+this.step);break;case TimeStep.SCALE.WEEKDAY:case TimeStep.SCALE.DAY:this.current.setDate(this.current.getDate()+this.step);break;case TimeStep.SCALE.MONTH:this.current.setMonth(this.current.getMonth()+this.step);break;case TimeStep.SCALE.YEAR:this.current.setFullYear(this.current.getFullYear()+this.step);break;default:}if(1!=this.step)switch(this.scale){case TimeStep.SCALE.MILLISECOND:this.current.getMilliseconds()0&&(this.step=e),this.autoScale=!1},TimeStep.prototype.setAutoScale=function(t){this.autoScale=t},TimeStep.prototype.setMinimumStep=function(t){if(void 0!=t){var e=31104e6,i=2592e6,n=864e5,s=36e5,o=6e4,r=1e3,a=1;1e3*e>t&&(this.scale=TimeStep.SCALE.YEAR,this.step=1e3),500*e>t&&(this.scale=TimeStep.SCALE.YEAR,this.step=500),100*e>t&&(this.scale=TimeStep.SCALE.YEAR,this.step=100),50*e>t&&(this.scale=TimeStep.SCALE.YEAR,this.step=50),10*e>t&&(this.scale=TimeStep.SCALE.YEAR,this.step=10),5*e>t&&(this.scale=TimeStep.SCALE.YEAR,this.step=5),e>t&&(this.scale=TimeStep.SCALE.YEAR,this.step=1),3*i>t&&(this.scale=TimeStep.SCALE.MONTH,this.step=3),i>t&&(this.scale=TimeStep.SCALE.MONTH,this.step=1),5*n>t&&(this.scale=TimeStep.SCALE.DAY,this.step=5),2*n>t&&(this.scale=TimeStep.SCALE.DAY,this.step=2),n>t&&(this.scale=TimeStep.SCALE.DAY,this.step=1),n/2>t&&(this.scale=TimeStep.SCALE.WEEKDAY,this.step=1),4*s>t&&(this.scale=TimeStep.SCALE.HOUR,this.step=4),s>t&&(this.scale=TimeStep.SCALE.HOUR,this.step=1),15*o>t&&(this.scale=TimeStep.SCALE.MINUTE,this.step=15),10*o>t&&(this.scale=TimeStep.SCALE.MINUTE,this.step=10),5*o>t&&(this.scale=TimeStep.SCALE.MINUTE,this.step=5),o>t&&(this.scale=TimeStep.SCALE.MINUTE,this.step=1),15*r>t&&(this.scale=TimeStep.SCALE.SECOND,this.step=15),10*r>t&&(this.scale=TimeStep.SCALE.SECOND,this.step=10),5*r>t&&(this.scale=TimeStep.SCALE.SECOND,this.step=5),r>t&&(this.scale=TimeStep.SCALE.SECOND,this.step=1),200*a>t&&(this.scale=TimeStep.SCALE.MILLISECOND,this.step=200),100*a>t&&(this.scale=TimeStep.SCALE.MILLISECOND,this.step=100),50*a>t&&(this.scale=TimeStep.SCALE.MILLISECOND,this.step=50),10*a>t&&(this.scale=TimeStep.SCALE.MILLISECOND,this.step=10),5*a>t&&(this.scale=TimeStep.SCALE.MILLISECOND,this.step=5),a>t&&(this.scale=TimeStep.SCALE.MILLISECOND,this.step=1) +}},TimeStep.prototype.snap=function(t){if(this.scale==TimeStep.SCALE.YEAR){var e=t.getFullYear()+Math.round(t.getMonth()/12);t.setFullYear(Math.round(e/this.step)*this.step),t.setMonth(0),t.setDate(0),t.setHours(0),t.setMinutes(0),t.setSeconds(0),t.setMilliseconds(0)}else if(this.scale==TimeStep.SCALE.MONTH)t.getDate()>15?(t.setDate(1),t.setMonth(t.getMonth()+1)):t.setDate(1),t.setHours(0),t.setMinutes(0),t.setSeconds(0),t.setMilliseconds(0);else if(this.scale==TimeStep.SCALE.DAY||this.scale==TimeStep.SCALE.WEEKDAY){switch(this.step){case 5:case 2:t.setHours(24*Math.round(t.getHours()/24));break;default:t.setHours(12*Math.round(t.getHours()/12))}t.setMinutes(0),t.setSeconds(0),t.setMilliseconds(0)}else if(this.scale==TimeStep.SCALE.HOUR){switch(this.step){case 4:t.setMinutes(60*Math.round(t.getMinutes()/60));break;default:t.setMinutes(30*Math.round(t.getMinutes()/30))}t.setSeconds(0),t.setMilliseconds(0)}else if(this.scale==TimeStep.SCALE.MINUTE){switch(this.step){case 15:case 10:t.setMinutes(5*Math.round(t.getMinutes()/5)),t.setSeconds(0);break;case 5:t.setSeconds(60*Math.round(t.getSeconds()/60));break;default:t.setSeconds(30*Math.round(t.getSeconds()/30))}t.setMilliseconds(0)}else if(this.scale==TimeStep.SCALE.SECOND)switch(this.step){case 15:case 10:t.setSeconds(5*Math.round(t.getSeconds()/5)),t.setMilliseconds(0);break;case 5:t.setMilliseconds(1e3*Math.round(t.getMilliseconds()/1e3));break;default:t.setMilliseconds(500*Math.round(t.getMilliseconds()/500))}else if(this.scale==TimeStep.SCALE.MILLISECOND){var i=this.step>5?this.step/2:1;t.setMilliseconds(Math.round(t.getMilliseconds()/i)*i)}},TimeStep.prototype.isMajor=function(){switch(this.scale){case TimeStep.SCALE.MILLISECOND:return 0==this.current.getMilliseconds();case TimeStep.SCALE.SECOND:return 0==this.current.getSeconds();case TimeStep.SCALE.MINUTE:return 0==this.current.getHours()&&0==this.current.getMinutes();case TimeStep.SCALE.HOUR:return 0==this.current.getHours();case TimeStep.SCALE.WEEKDAY:case TimeStep.SCALE.DAY:return 1==this.current.getDate();case TimeStep.SCALE.MONTH:return 0==this.current.getMonth();case TimeStep.SCALE.YEAR:return!1;default:return!1}},TimeStep.prototype.getLabelMinor=function(t){switch(void 0==t&&(t=this.current),this.scale){case TimeStep.SCALE.MILLISECOND:return M(t).format("SSS");case TimeStep.SCALE.SECOND:return M(t).format("s");case TimeStep.SCALE.MINUTE:return M(t).format("HH:mm");case TimeStep.SCALE.HOUR:return M(t).format("HH:mm");case TimeStep.SCALE.WEEKDAY:return M(t).format("ddd D");case TimeStep.SCALE.DAY:return M(t).format("D");case TimeStep.SCALE.MONTH:return M(t).format("MMM");case TimeStep.SCALE.YEAR:return M(t).format("YYYY");default:return""}},TimeStep.prototype.getLabelMajor=function(t){switch(void 0==t&&(t=this.current),this.scale){case TimeStep.SCALE.MILLISECOND:return M(t).format("HH:mm:ss");case TimeStep.SCALE.SECOND:return M(t).format("D MMMM HH:mm");case TimeStep.SCALE.MINUTE:case TimeStep.SCALE.HOUR:return M(t).format("ddd D MMMM");case TimeStep.SCALE.WEEKDAY:case TimeStep.SCALE.DAY:return M(t).format("MMMM YYYY");case TimeStep.SCALE.MONTH:return M(t).format("YYYY");case TimeStep.SCALE.YEAR:return"";default:return""}},a.prototype.setOptions=function(t){O.extend(this.options,t)},a.prototype.update=function(){this._order(),this._stack()},a.prototype._order=function(){var t=this.parent.items;if(!t)throw Error("Cannot stack items: parent does not contain items");var e=[],i=0;O.forEach(t,function(t){t.visible&&(e[i]=t,i++)});var n=this.options.order||this.defaultOptions.order;if("function"!=typeof n)throw Error("Option order must be a function");e.sort(n),this.ordered=e},a.prototype._stack=function(){var t,e,i,n=this.ordered,s=this.options,o=s.orientation||this.defaultOptions.orientation,r="top"==o;for(i=s.margin&&void 0!==s.margin.item?s.margin.item:this.defaultOptions.margin.item,t=0,e=n.length;e>t;t++){var a=n[t],h=null;do h=this.checkOverlap(n,t,0,t-1,i),null!=h&&(a.top=r?h.top+h.height+i:h.top-a.height-i);while(h)}},a.prototype.checkOverlap=function(t,e,i,n,s){for(var o=this.collision,r=t[e],a=n;a>=i;a--){var h=t[a];if(o(r,h,s)&&a!=e)return h}return null},a.prototype.collision=function(t,e,i){return t.left-ie.left&&t.top-ie.top},h.prototype.setOptions=function(t){O.extend(this.options,t),(null!=t.start||null!=t.end)&&this.setRange(t.start,t.end)},h.prototype.subscribe=function(t,e,i){var n,s=this;if("horizontal"!=i&&"vertical"!=i)throw new TypeError('Unknown direction "'+i+'". '+'Choose "horizontal" or "vertical".');if("move"==e)n={component:t,event:e,direction:i,callback:function(t){s._onMouseDown(t,n)},params:{}},t.on("mousedown",n.callback),s.listeners.push(n);else{if("zoom"!=e)throw new TypeError('Unknown event "'+e+'". '+'Choose "move" or "zoom".');n={component:t,event:e,direction:i,callback:function(t){s._onMouseWheel(t,n)},params:{}},t.on("mousewheel",n.callback),s.listeners.push(n)}},h.prototype.on=function(t,e){L.addListener(this,t,e)},h.prototype._trigger=function(t){L.trigger(this,t,{start:this.start,end:this.end})},h.prototype.setRange=function(t,e){var i=this._applyRange(t,e);i&&(this._trigger("rangechange"),this._trigger("rangechanged"))},h.prototype._applyRange=function(t,e){var i,n=null!=t?O.convert(t,"Number"):this.start,s=null!=e?O.convert(e,"Number"):this.end;if(isNaN(n))throw Error('Invalid start "'+t+'"');if(isNaN(s))throw Error('Invalid end "'+e+'"');if(n>s&&(s=n),null!=this.options.min){var o=this.options.min.valueOf();o>n&&(i=o-n,n+=i,s+=i)}if(null!=this.options.max){var r=this.options.max.valueOf();s>r&&(i=s-r,n-=i,s-=i)}if(null!=this.options.zoomMin){var a=this.options.zoomMin.valueOf();0>a&&(a=0),a>s-n&&(this.end-this.start>a?(i=a-(s-n),n-=i/2,s+=i/2):(n=this.start,s=this.end))}if(null!=this.options.zoomMax){var h=this.options.zoomMax.valueOf();0>h&&(h=0),s-n>h&&(h>this.end-this.start?(i=s-n-h,n+=i/2,s-=i/2):(n=this.start,s=this.end))}var d=this.start!=n||this.end!=s;return this.start=n,this.end=s,d},h.prototype.getRange=function(){return{start:this.start,end:this.end}},h.prototype.conversion=function(t){return this.start,this.end,h.conversion(this.start,this.end,t)},h.conversion=function(t,e,i){return 0!=i&&0!=e-t?{offset:t,factor:i/(e-t)}:{offset:0,factor:1}},h.prototype._onMouseDown=function(t,e){t=t||window.event;var i=e.params,n=t.which?1==t.which:1==t.button;if(n){i.mouseX=O.getPageX(t),i.mouseY=O.getPageY(t),i.previousLeft=0,i.previousOffset=0,i.moved=!1,i.start=this.start,i.end=this.end;var s=e.component.frame;s&&(s.style.cursor="move");var o=this;i.onMouseMove||(i.onMouseMove=function(t){o._onMouseMove(t,e)},O.addEventListener(document,"mousemove",i.onMouseMove)),i.onMouseUp||(i.onMouseUp=function(t){o._onMouseUp(t,e)},O.addEventListener(document,"mouseup",i.onMouseUp)),O.preventDefault(t)}},h.prototype._onMouseMove=function(t,e){t=t||window.event;var i=e.params,n=O.getPageX(t),s=O.getPageY(t);void 0==i.mouseX&&(i.mouseX=n),void 0==i.mouseY&&(i.mouseY=s);var o=n-i.mouseX,r=s-i.mouseY,a="horizontal"==e.direction?o:r;Math.abs(a)>=1&&(i.moved=!0);var h=i.end-i.start,d="horizontal"==e.direction?e.component.width:e.component.height,l=-a/d*h;this._applyRange(i.start+l,i.end+l),this._trigger("rangechange"),O.preventDefault(t)},h.prototype._onMouseUp=function(t,e){t=t||window.event;var i=e.params;e.component.frame&&(e.component.frame.style.cursor="auto"),i.onMouseMove&&(O.removeEventListener(document,"mousemove",i.onMouseMove),i.onMouseMove=null),i.onMouseUp&&(O.removeEventListener(document,"mouseup",i.onMouseUp),i.onMouseUp=null),i.moved&&this._trigger("rangechanged")},h.prototype._onMouseWheel=function(t,e){t=t||window.event;var i=0;if(t.wheelDelta?i=t.wheelDelta/120:t.detail&&(i=-t.detail/3),i){var n=this,s=function(){var s=i/5,o=null,r=e.component.frame;if(r){var a,h;if("horizontal"==e.direction){a=e.component.width,h=n.conversion(a);var d=O.getAbsoluteLeft(r),l=O.getPageX(t);o=(l-d)/h.factor+h.offset}else{a=e.component.height,h=n.conversion(a);var p=O.getAbsoluteTop(r),c=O.getPageY(t);o=(p+a-c-p)/h.factor+h.offset}}n.zoom(s,o)};s()}O.preventDefault(t)},h.prototype.zoom=function(t,e){null==e&&(e=(this.start+this.end)/2),t>=1&&(t=.9),-1>=t&&(t=-.9),0>t&&(t/=1+t);var i=this.start-e,n=this.end-e,s=this.start-i*t,o=this.end-n*t;this.setRange(s,o)},h.prototype.move=function(t){var e=this.end-this.start,i=this.start+e*t,n=this.end+e*t;this.start=i,this.end=n},h.prototype.moveTo=function(t){var e=(this.start+this.end)/2,i=e-t,n=this.start-i,s=this.end-i;this.setRange(n,s)},d.prototype.add=function(t){if(void 0==t.id)throw Error("Component has no field id");if(!(t instanceof l||t instanceof d))throw new TypeError("Component must be an instance of prototype Component or Controller");t.controller=this,this.components[t.id]=t},d.prototype.remove=function(t){var e;for(e in this.components)if(this.components.hasOwnProperty(e)&&(e==t||this.components[e]==t))break;e&&delete this.components[e]},d.prototype.requestReflow=function(t){if(t)this.reflow();else if(!this.reflowTimer){var e=this;this.reflowTimer=setTimeout(function(){e.reflowTimer=void 0,e.reflow()},0)}},d.prototype.requestRepaint=function(t){if(t)this.repaint();else if(!this.repaintTimer){var e=this;this.repaintTimer=setTimeout(function(){e.repaintTimer=void 0,e.repaint()},0)}},d.prototype.repaint=function(){function t(n,s){s in i||(n.depends&&n.depends.forEach(function(e){t(e,e.id)}),n.parent&&t(n.parent,n.parent.id),e=n.repaint()||e,i[s]=!0)}var e=!1;this.repaintTimer&&(clearTimeout(this.repaintTimer),this.repaintTimer=void 0);var i={};O.forEach(this.components,t),e&&this.reflow()},d.prototype.reflow=function(){function t(n,s){s in i||(n.depends&&n.depends.forEach(function(e){t(e,e.id)}),n.parent&&t(n.parent,n.parent.id),e=n.reflow()||e,i[s]=!0)}var e=!1;this.reflowTimer&&(clearTimeout(this.reflowTimer),this.reflowTimer=void 0);var i={};O.forEach(this.components,t),e&&this.repaint()},l.prototype.setOptions=function(t){t&&(O.extend(this.options,t),this.controller&&(this.requestRepaint(),this.requestReflow()))},l.prototype.getOption=function(t){var e;return this.options&&(e=this.options[t]),void 0===e&&this.defaultOptions&&(e=this.defaultOptions[t]),e},l.prototype.getContainer=function(){return null},l.prototype.getFrame=function(){return this.frame},l.prototype.repaint=function(){return!1},l.prototype.reflow=function(){return!1},l.prototype.hide=function(){return this.frame&&this.frame.parentNode?(this.frame.parentNode.removeChild(this.frame),!0):!1},l.prototype.show=function(){return this.frame&&this.frame.parentNode?!1:this.repaint()},l.prototype.requestRepaint=function(){if(!this.controller)throw Error("Cannot request a repaint: no controller configured");this.controller.requestRepaint()},l.prototype.requestReflow=function(){if(!this.controller)throw Error("Cannot request a reflow: no controller configured");this.controller.requestReflow()},p.prototype=new l,p.prototype.setOptions=l.prototype.setOptions,p.prototype.getContainer=function(){return this.frame},p.prototype.repaint=function(){var t=0,e=O.updateProperty,i=O.option.asSize,n=this.options,s=this.frame;if(!s){s=document.createElement("div"),s.className="panel";var o=n.className;o&&("function"==typeof o?O.addClassName(s,o()+""):O.addClassName(s,o+"")),this.frame=s,t+=1}if(!s.parentNode){if(!this.parent)throw Error("Cannot repaint panel: no parent attached");var r=this.parent.getContainer();if(!r)throw Error("Cannot repaint panel: parent has no container element");r.appendChild(s),t+=1}return t+=e(s.style,"top",i(n.top,"0px")),t+=e(s.style,"left",i(n.left,"0px")),t+=e(s.style,"width",i(n.width,"100%")),t+=e(s.style,"height",i(n.height,"100%")),t>0},p.prototype.reflow=function(){var t=0,e=O.updateProperty,i=this.frame;return i?(t+=e(this,"top",i.offsetTop),t+=e(this,"left",i.offsetLeft),t+=e(this,"width",i.offsetWidth),t+=e(this,"height",i.offsetHeight)):t+=1,t>0},c.prototype=new p,c.prototype.setOptions=l.prototype.setOptions,c.prototype.repaint=function(){var t=0,e=O.updateProperty,i=O.option.asSize,n=this.options,s=this.frame;if(!s){s=document.createElement("div"),s.className="vis timeline rootpanel";var o=n.className;o&&O.addClassName(s,O.option.asString(o)),this.frame=s,t+=1}if(!s.parentNode){if(!this.container)throw Error("Cannot repaint root panel: no container attached");this.container.appendChild(s),t+=1}return t+=e(s.style,"top",i(n.top,"0px")),t+=e(s.style,"left",i(n.left,"0px")),t+=e(s.style,"width",i(n.width,"100%")),t+=e(s.style,"height",i(n.height,"100%")),this._updateEventEmitters(),this._updateWatch(),t>0},c.prototype.reflow=function(){var t=0,e=O.updateProperty,i=this.frame;return i?(t+=e(this,"top",i.offsetTop),t+=e(this,"left",i.offsetLeft),t+=e(this,"width",i.offsetWidth),t+=e(this,"height",i.offsetHeight)):t+=1,t>0},c.prototype._updateWatch=function(){var t=this.getOption("autoResize");t?this._watch():this._unwatch()},c.prototype._watch=function(){var t=this;this._unwatch();var e=function(){var e=t.getOption("autoResize");return e?(t.frame&&(t.frame.clientWidth!=t.width||t.frame.clientHeight!=t.height)&&t.requestReflow(),void 0):(t._unwatch(),void 0)};O.addEventListener(window,"resize",e),this.watchTimer=setInterval(e,1e3)},c.prototype._unwatch=function(){this.watchTimer&&(clearInterval(this.watchTimer),this.watchTimer=void 0)},c.prototype.on=function(t,e){var i=this.listeners[t];i||(i=[],this.listeners[t]=i),i.push(e),this._updateEventEmitters()},c.prototype._updateEventEmitters=function(){if(this.listeners){var t=this;O.forEach(this.listeners,function(e,i){if(t.emitters||(t.emitters={}),!(i in t.emitters)){var n=t.frame;if(n){var s=function(t){e.forEach(function(e){e(t)})};t.emitters[i]=s,O.addEventListener(n,i,s)}}})}},u.prototype=new l,u.prototype.setOptions=l.prototype.setOptions,u.prototype.setRange=function(t){if(!(t instanceof h||t&&t.start&&t.end))throw new TypeError("Range must be an instance of Range, or an object containing start and end.");this.range=t},u.prototype.toTime=function(t){var e=this.conversion;return new Date(t/e.factor+e.offset)},u.prototype.toScreen=function(t){var e=this.conversion;return(t.valueOf()-e.offset)*e.factor},u.prototype.repaint=function(){var t=0,e=O.updateProperty,i=O.option.asSize,n=this.options,s=this.getOption("orientation"),o=this.props,r=this.step,a=this.frame;if(a||(a=document.createElement("div"),this.frame=a,t+=1),a.className="axis "+s,!a.parentNode){if(!this.parent)throw Error("Cannot repaint time axis: no parent attached");var h=this.parent.getContainer();if(!h)throw Error("Cannot repaint time axis: parent has no container element");h.appendChild(a),t+=1}var d=a.parentNode;if(d){var l=a.nextSibling;d.removeChild(a);var p="bottom"==s&&this.props.parentHeight&&this.height?this.props.parentHeight-this.height+"px":"0px";if(t+=e(a.style,"top",i(n.top,p)),t+=e(a.style,"left",i(n.left,"0px")),t+=e(a.style,"width",i(n.width,"100%")),t+=e(a.style,"height",i(n.height,this.height+"px")),this._repaintMeasureChars(),this.step){this._repaintStart(),r.first();for(var c=void 0,u=0;r.hasNext()&&1e3>u;){u++;var f=r.getCurrent(),m=this.toScreen(f),g=r.isMajor();this.getOption("showMinorLabels")&&this._repaintMinorText(m,r.getLabelMinor()),g&&this.getOption("showMajorLabels")?(m>0&&(void 0==c&&(c=m),this._repaintMajorText(m,r.getLabelMajor())),this._repaintMajorLine(m)):this._repaintMinorLine(m),r.next()}if(this.getOption("showMajorLabels")){var v=this.toTime(0),y=r.getLabelMajor(v),b=y.length*(o.majorCharWidth||10)+10;(void 0==c||c>b)&&this._repaintMajorText(0,y)}this._repaintEnd()}this._repaintLine(),l?d.insertBefore(a,l):d.appendChild(a)}return t>0},u.prototype._repaintStart=function(){var t=this.dom,e=t.redundant;e.majorLines=t.majorLines,e.majorTexts=t.majorTexts,e.minorLines=t.minorLines,e.minorTexts=t.minorTexts,t.majorLines=[],t.majorTexts=[],t.minorLines=[],t.minorTexts=[]},u.prototype._repaintEnd=function(){O.forEach(this.dom.redundant,function(t){for(;t.length;){var e=t.pop();e&&e.parentNode&&e.parentNode.removeChild(e)}})},u.prototype._repaintMinorText=function(t,e){var i=this.dom.redundant.minorTexts.shift();if(!i){var n=document.createTextNode("");i=document.createElement("div"),i.appendChild(n),i.className="text minor",this.frame.appendChild(i)}this.dom.minorTexts.push(i),i.childNodes[0].nodeValue=e,i.style.left=t+"px",i.style.top=this.props.minorLabelTop+"px"},u.prototype._repaintMajorText=function(t,e){var i=this.dom.redundant.majorTexts.shift();if(!i){var n=document.createTextNode(e);i=document.createElement("div"),i.className="text major",i.appendChild(n),this.frame.appendChild(i)}this.dom.majorTexts.push(i),i.childNodes[0].nodeValue=e,i.style.top=this.props.majorLabelTop+"px",i.style.left=t+"px"},u.prototype._repaintMinorLine=function(t){var e=this.dom.redundant.minorLines.shift();e||(e=document.createElement("div"),e.className="grid vertical minor",this.frame.appendChild(e)),this.dom.minorLines.push(e);var i=this.props;e.style.top=i.minorLineTop+"px",e.style.height=i.minorLineHeight+"px",e.style.left=t-i.minorLineWidth/2+"px"},u.prototype._repaintMajorLine=function(t){var e=this.dom.redundant.majorLines.shift();e||(e=document.createElement("DIV"),e.className="grid vertical major",this.frame.appendChild(e)),this.dom.majorLines.push(e);var i=this.props;e.style.top=i.majorLineTop+"px",e.style.left=t-i.majorLineWidth/2+"px",e.style.height=i.majorLineHeight+"px"},u.prototype._repaintLine=function(){var t=this.dom.line,e=this.frame;this.options,this.getOption("showMinorLabels")||this.getOption("showMajorLabels")?(t?(e.removeChild(t),e.appendChild(t)):(t=document.createElement("div"),t.className="grid horizontal major",e.appendChild(t),this.dom.line=t),t.style.top=this.props.lineTop+"px"):t&&axis.parentElement&&(e.removeChild(axis.line),delete this.dom.line)},u.prototype._repaintMeasureChars=function(){var t,e=this.dom;if(!e.measureCharMinor){t=document.createTextNode("0");var i=document.createElement("DIV");i.className="text minor measure",i.appendChild(t),this.frame.appendChild(i),e.measureCharMinor=i}if(!e.measureCharMajor){t=document.createTextNode("0");var n=document.createElement("DIV");n.className="text major measure",n.appendChild(t),this.frame.appendChild(n),e.measureCharMajor=n}},u.prototype.reflow=function(){var t=0,e=O.updateProperty,i=this.frame,n=this.range;if(!n)throw Error("Cannot repaint time axis: no range configured");if(i){t+=e(this,"top",i.offsetTop),t+=e(this,"left",i.offsetLeft);var s=this.props,o=this.getOption("showMinorLabels"),r=this.getOption("showMajorLabels"),a=this.dom.measureCharMinor,h=this.dom.measureCharMajor;a&&(s.minorCharHeight=a.clientHeight,s.minorCharWidth=a.clientWidth),h&&(s.majorCharHeight=h.clientHeight,s.majorCharWidth=h.clientWidth);var d=i.parentNode?i.parentNode.offsetHeight:0;switch(d!=s.parentHeight&&(s.parentHeight=d,t+=1),this.getOption("orientation")){case"bottom":s.minorLabelHeight=o?s.minorCharHeight:0,s.majorLabelHeight=r?s.majorCharHeight:0,s.minorLabelTop=0,s.majorLabelTop=s.minorLabelTop+s.minorLabelHeight,s.minorLineTop=-this.top,s.minorLineHeight=Math.max(this.top+s.majorLabelHeight,0),s.minorLineWidth=1,s.majorLineTop=-this.top,s.majorLineHeight=Math.max(this.top+s.minorLabelHeight+s.majorLabelHeight,0),s.majorLineWidth=1,s.lineTop=0;break;case"top":s.minorLabelHeight=o?s.minorCharHeight:0,s.majorLabelHeight=r?s.majorCharHeight:0,s.majorLabelTop=0,s.minorLabelTop=s.majorLabelTop+s.majorLabelHeight,s.minorLineTop=s.minorLabelTop,s.minorLineHeight=Math.max(d-s.majorLabelHeight-this.top),s.minorLineWidth=1,s.majorLineTop=0,s.majorLineHeight=Math.max(d-this.top),s.majorLineWidth=1,s.lineTop=s.majorLabelHeight+s.minorLabelHeight;break;default:throw Error('Unkown orientation "'+this.getOption("orientation")+'"')}var l=s.minorLabelHeight+s.majorLabelHeight;t+=e(this,"width",i.offsetWidth),t+=e(this,"height",l),this._updateConversion();var p=O.convert(n.start,"Date"),c=O.convert(n.end,"Date"),u=this.toTime(5*(s.minorCharWidth||10))-this.toTime(0);this.step=new TimeStep(p,c,u),t+=e(s.range,"start",p.valueOf()),t+=e(s.range,"end",c.valueOf()),t+=e(s.range,"minimumStep",u.valueOf())}return t>0},u.prototype._updateConversion=function(){var t=this.range;if(!t)throw Error("No range configured");this.conversion=t.conversion?t.conversion(this.width):h.conversion(t.start,t.end,this.width)},f.prototype=new p,f.types={box:g,range:y,point:v},f.prototype.setOptions=l.prototype.setOptions,f.prototype.setRange=function(t){if(!(t instanceof h||t&&t.start&&t.end))throw new TypeError("Range must be an instance of Range, or an object containing start and end.");this.range=t},f.prototype.repaint=function(){var t=0,e=O.updateProperty,i=O.option.asSize,n=this.options,s=this.getOption("orientation"),o=this.defaultOptions,r=this.frame;if(!r){r=document.createElement("div"),r.className="itemset";var a=n.className;a&&O.addClassName(r,O.option.asString(a));var h=document.createElement("div");h.className="background",r.appendChild(h),this.dom.background=h;var d=document.createElement("div");d.className="foreground",r.appendChild(d),this.dom.foreground=d;var l=document.createElement("div");l.className="itemset-axis",this.dom.axis=l,this.frame=r,t+=1}if(!this.parent)throw Error("Cannot repaint itemset: no parent attached");var p=this.parent.getContainer();if(!p)throw Error("Cannot repaint itemset: parent has no container element");r.parentNode||(p.appendChild(r),t+=1),this.dom.axis.parentNode||(p.appendChild(this.dom.axis),t+=1),t+=e(r.style,"left",i(n.left,"0px")),t+=e(r.style,"top",i(n.top,"0px")),t+=e(r.style,"width",i(n.width,"100%")),t+=e(r.style,"height",i(n.height,this.height+"px")),t+=e(this.dom.axis.style,"left",i(n.left,"0px")),t+=e(this.dom.axis.style,"width",i(n.width,"100%")),t+="bottom"==s?e(this.dom.axis.style,"top",this.height+this.top+"px"):e(this.dom.axis.style,"top",this.top+"px"),this._updateConversion();var c=this,u=this.queue,m=this.itemsData,g=this.items,v={};return Object.keys(u).forEach(function(e){var i=u[e],s=g[e];switch(i){case"add":case"update":var r=m&&m.get(e,v);if(r){var a=r.type||r.start&&r.end&&"range"||n.type||"box",h=f.types[a];if(s&&(h&&s instanceof h?(s.data=r,t++):(t+=s.hide(),s=null)),!s){if(!h)throw new TypeError('Unknown item type "'+a+'"');s=new h(c,r,n,o),t++}s.repaint(),g[e]=s}delete u[e];break;case"remove":s&&(t+=s.hide()),delete g[e],delete u[e];break;default:console.log('Error: unknown action "'+i+'"')}}),O.forEach(this.items,function(e){e.visible?(t+=e.show(),e.reposition()):t+=e.hide()}),t>0},f.prototype.getForeground=function(){return this.dom.foreground},f.prototype.getBackground=function(){return this.dom.background},f.prototype.getAxis=function(){return this.dom.axis},f.prototype.reflow=function(){var t=0,e=this.options,i=e.margin&&e.margin.axis||this.defaultOptions.margin.axis,n=e.margin&&e.margin.item||this.defaultOptions.margin.item,s=O.updateProperty,o=O.option.asNumber,r=O.option.asSize,a=this.frame;if(a){this._updateConversion(),O.forEach(this.items,function(e){t+=e.reflow()}),this.stack.update();var h,d=o(e.maxHeight),l=null!=r(e.height);if(l)h=a.offsetHeight;else{var p=this.stack.ordered;if(p.length){var c=p[0].top,u=p[0].top+p[0].height;O.forEach(p,function(t){c=Math.min(c,t.top),u=Math.max(u,t.top+t.height)}),h=u-c+i+n}else h=i+n}null!=d&&(h=Math.min(h,d)),t+=s(this,"height",h),t+=s(this,"top",a.offsetTop),t+=s(this,"left",a.offsetLeft),t+=s(this,"width",a.offsetWidth)}else t+=1;return t>0},f.prototype.hide=function(){var t=!1;return this.frame&&this.frame.parentNode&&(this.frame.parentNode.removeChild(this.frame),t=!0),this.dom.axis&&this.dom.axis.parentNode&&(this.dom.axis.parentNode.removeChild(this.dom.axis),t=!0),t},f.prototype.setItems=function(t){var e,i=this,n=this.itemsData;if(t){if(!(t instanceof o||t instanceof r))throw new TypeError("Data must be an instance of DataSet");this.itemsData=t}else this.itemsData=null;if(n&&(O.forEach(this.listeners,function(t,e){n.unsubscribe(e,t)}),e=n.getIds(),this._onRemove(e)),this.itemsData){var s=this.id;O.forEach(this.listeners,function(t,e){i.itemsData.subscribe(e,t,s)}),e=this.itemsData.getIds(),this._onAdd(e)}},f.prototype.getItems=function(){return this.itemsData},f.prototype._onUpdate=function(t){this._toQueue("update",t)},f.prototype._onAdd=function(t){this._toQueue("add",t)},f.prototype._onRemove=function(t){this._toQueue("remove",t)},f.prototype._toQueue=function(t,e){var i=this.queue;e.forEach(function(e){i[e]=t}),this.controller&&this.requestRepaint()},f.prototype._updateConversion=function(){var t=this.range;if(!t)throw Error("No range configured");this.conversion=t.conversion?t.conversion(this.width):h.conversion(t.start,t.end,this.width)},f.prototype.toTime=function(t){var e=this.conversion;return new Date(t/e.factor+e.offset)},f.prototype.toScreen=function(t){var e=this.conversion;return(t.valueOf()-e.offset)*e.factor},m.prototype.select=function(){this.selected=!0},m.prototype.unselect=function(){this.selected=!1},m.prototype.show=function(){return!1},m.prototype.hide=function(){return!1},m.prototype.repaint=function(){return!1},m.prototype.reflow=function(){return!1},g.prototype=new m(null,null),g.prototype.select=function(){this.selected=!0},g.prototype.unselect=function(){this.selected=!1},g.prototype.repaint=function(){var t=!1,e=this.dom;if(e||(this._create(),e=this.dom,t=!0),e){if(!this.parent)throw Error("Cannot repaint item: no parent attached");var i=this.parent.getForeground();if(!i)throw Error("Cannot repaint time axis: parent has no foreground container element");var n=this.parent.getBackground();if(!n)throw Error("Cannot repaint time axis: parent has no background container element");var s=this.parent.getAxis();if(!n)throw Error("Cannot repaint time axis: parent has no axis container element");if(e.box.parentNode||(i.appendChild(e.box),t=!0),e.line.parentNode||(n.appendChild(e.line),t=!0),e.dot.parentNode||(s.appendChild(e.dot),t=!0),this.data.content!=this.content){if(this.content=this.data.content,this.content instanceof Element)e.content.innerHTML="",e.content.appendChild(this.content);else{if(void 0==this.data.content)throw Error('Property "content" missing in item '+this.data.id);e.content.innerHTML=this.content}t=!0}var o=(this.data.className?" "+this.data.className:"")+(this.selected?" selected":"");this.className!=o&&(this.className=o,e.box.className="item box"+o,e.line.className="item line"+o,e.dot.className="item dot"+o,t=!0)}return t},g.prototype.show=function(){return this.dom&&this.dom.box.parentNode?!1:this.repaint()},g.prototype.hide=function(){var t=!1,e=this.dom;return e&&(e.box.parentNode&&(e.box.parentNode.removeChild(e.box),t=!0),e.line.parentNode&&e.line.parentNode.removeChild(e.line),e.dot.parentNode&&e.dot.parentNode.removeChild(e.dot)),t},g.prototype.reflow=function(){var t,e,i,n,s,o,r,a,h,d,l,p,c=0;if(void 0==this.data.start)throw Error('Property "start" missing in item '+this.data.id);if(l=this.data,p=this.parent&&this.parent.range,l&&p){var u=p.end-p.start;this.visible=l.start>p.start-u&&l.start0},g.prototype._create=function(){var t=this.dom;t||(this.dom=t={},t.box=document.createElement("DIV"),t.content=document.createElement("DIV"),t.content.className="content",t.box.appendChild(t.content),t.line=document.createElement("DIV"),t.line.className="line",t.dot=document.createElement("DIV"),t.dot.className="dot")},g.prototype.reposition=function(){var t=this.dom,e=this.props,i=this.options.orientation||this.defaultOptions.orientation;if(t){var n=t.box,s=t.line,o=t.dot;n.style.left=this.left+"px",n.style.top=this.top+"px",s.style.left=e.line.left+"px","top"==i?(s.style.top="0px",s.style.height=this.top+"px"):(s.style.top=this.top+this.height+"px",s.style.height=Math.max(this.parent.height-this.top-this.height+this.props.dot.height/2,0)+"px"),o.style.left=e.dot.left+"px",o.style.top=e.dot.top+"px"}},v.prototype=new m(null,null),v.prototype.select=function(){this.selected=!0},v.prototype.unselect=function(){this.selected=!1},v.prototype.repaint=function(){var t=!1,e=this.dom;if(e||(this._create(),e=this.dom,t=!0),e){if(!this.parent)throw Error("Cannot repaint item: no parent attached");var i=this.parent.getForeground();if(!i)throw Error("Cannot repaint time axis: parent has no foreground container element");if(e.point.parentNode||(i.appendChild(e.point),i.appendChild(e.point),t=!0),this.data.content!=this.content){if(this.content=this.data.content,this.content instanceof Element)e.content.innerHTML="",e.content.appendChild(this.content);else{if(void 0==this.data.content)throw Error('Property "content" missing in item '+this.data.id);e.content.innerHTML=this.content}t=!0}var n=(this.data.className?" "+this.data.className:"")+(this.selected?" selected":"");this.className!=n&&(this.className=n,e.point.className="item point"+n,t=!0)}return t},v.prototype.show=function(){return this.dom&&this.dom.point.parentNode?!1:this.repaint()},v.prototype.hide=function(){var t=!1,e=this.dom;return e&&e.point.parentNode&&(e.point.parentNode.removeChild(e.point),t=!0),t},v.prototype.reflow=function(){var t,e,i,n,s,o,r,a,h,d,l=0;if(void 0==this.data.start)throw Error('Property "start" missing in item '+this.data.id);if(h=this.data,d=this.parent&&this.parent.range,h&&d){var p=d.end-d.start;this.visible=h.start>d.start-p&&h.start0},v.prototype._create=function(){var t=this.dom;t||(this.dom=t={},t.point=document.createElement("div"),t.content=document.createElement("div"),t.content.className="content",t.point.appendChild(t.content),t.dot=document.createElement("div"),t.dot.className="dot",t.point.appendChild(t.dot))},v.prototype.reposition=function(){var t=this.dom,e=this.props;t&&(t.point.style.top=this.top+"px",t.point.style.left=this.left+"px",t.content.style.marginLeft=e.content.marginLeft+"px",t.dot.style.top=e.dot.top+"px")},y.prototype=new m(null,null),y.prototype.select=function(){this.selected=!0},y.prototype.unselect=function(){this.selected=!1},y.prototype.repaint=function(){var t=!1,e=this.dom;if(e||(this._create(),e=this.dom,t=!0),e){if(!this.parent)throw Error("Cannot repaint item: no parent attached");var i=this.parent.getForeground();if(!i)throw Error("Cannot repaint time axis: parent has no foreground container element");if(e.box.parentNode||(i.appendChild(e.box),t=!0),this.data.content!=this.content){if(this.content=this.data.content,this.content instanceof Element)e.content.innerHTML="",e.content.appendChild(this.content);else{if(void 0==this.data.content)throw Error('Property "content" missing in item '+this.data.id); +e.content.innerHTML=this.content}t=!0}var n=this.data.className?" "+this.data.className:"";this.className!=n&&(this.className=n,e.box.className="item range"+n,t=!0)}return t},y.prototype.show=function(){return this.dom&&this.dom.box.parentNode?!1:this.repaint()},y.prototype.hide=function(){var t=!1,e=this.dom;return e&&e.box.parentNode&&(e.box.parentNode.removeChild(e.box),t=!0),t},y.prototype.reflow=function(){var t,e,i,n,s,o,r,a,h,d,l,p,c,u,f,m,g=0;if(void 0==this.data.start)throw Error('Property "start" missing in item '+this.data.id);if(void 0==this.data.end)throw Error('Property "end" missing in item '+this.data.id);return h=this.data,d=this.parent&&this.parent.range,this.visible=h&&d?h.startd.start:!1,this.visible&&(t=this.dom,t?(e=this.props,i=this.options,o=this.parent,r=o.toScreen(this.data.start),a=o.toScreen(this.data.end),l=O.updateProperty,p=t.box,c=o.width,f=i.orientation||this.defaultOptions.orientation,n=i.margin&&i.margin.axis||this.defaultOptions.margin.axis,s=i.padding||this.defaultOptions.padding,g+=l(e.content,"width",t.content.offsetWidth),g+=l(this,"height",p.offsetHeight),-c>r&&(r=-c),a>2*c&&(a=2*c),u=0>r?Math.min(-r,a-r-e.content.width-2*s):0,g+=l(e.content,"left",u),"top"==f?(m=n,g+=l(this,"top",m)):(m=o.height-this.height-n,g+=l(this,"top",m)),g+=l(this,"left",r),g+=l(this,"width",Math.max(a-r,1))):g+=1),g>0},y.prototype._create=function(){var t=this.dom;t||(this.dom=t={},t.box=document.createElement("div"),t.content=document.createElement("div"),t.content.className="content",t.box.appendChild(t.content))},y.prototype.reposition=function(){var t=this.dom,e=this.props;t&&(t.box.style.top=this.top+"px",t.box.style.left=this.left+"px",t.box.style.width=this.width+"px",t.content.style.left=e.content.left+"px")},b.prototype=new l,b.prototype.setOptions=l.prototype.setOptions,b.prototype.getContainer=function(){return this.parent.getContainer()},b.prototype.setItems=function(t){if(this.itemset&&(this.itemset.hide(),this.itemset.setItems(),this.parent.controller.remove(this.itemset),this.itemset=null),t){var e=this.groupId,i=Object.create(this.options);this.itemset=new f(this,null,i),this.itemset.setRange(this.parent.range),this.view=new r(t,{filter:function(t){return t.group==e}}),this.itemset.setItems(this.view),this.parent.controller.add(this.itemset)}},b.prototype.repaint=function(){return!1},b.prototype.reflow=function(){var t=0,e=O.updateProperty;if(t+=e(this,"top",this.itemset?this.itemset.top:0),t+=e(this,"height",this.itemset?this.itemset.height:0),this.label){var i=this.label.firstChild;t+=e(this.props.label,"width",i.clientWidth),t+=e(this.props.label,"height",i.clientHeight)}else t+=e(this.props.label,"width",0),t+=e(this.props.label,"height",0);return t>0},w.prototype=new p,w.prototype.setOptions=l.prototype.setOptions,w.prototype.setRange=function(){},w.prototype.setItems=function(t){this.itemsData=t;for(var e in this.groups)if(this.groups.hasOwnProperty(e)){var i=this.groups[e];i.setItems(t)}},w.prototype.getItems=function(){return this.itemsData},w.prototype.setRange=function(t){this.range=t},w.prototype.setGroups=function(t){var e,i=this;if(this.groupsData&&(O.forEach(this.listeners,function(t,e){i.groupsData.unsubscribe(e,t)}),e=this.groupsData.getIds(),this._onRemove(e)),t?t instanceof o?this.groupsData=t:(this.groupsData=new o({convert:{start:"Date",end:"Date"}}),this.groupsData.add(t)):this.groupsData=null,this.groupsData){var n=this.id;O.forEach(this.listeners,function(t,e){i.groupsData.subscribe(e,t,n)}),e=this.groupsData.getIds(),this._onAdd(e)}},w.prototype.getGroups=function(){return this.groupsData},w.prototype.repaint=function(){var t,e,i,n,s=0,o=O.updateProperty,r=O.option.asSize,a=O.option.asElement,h=this.options,d=this.dom.frame,l=this.dom.labels;if(!this.parent)throw Error("Cannot repaint groupset: no parent attached");var p=this.parent.getContainer();if(!p)throw Error("Cannot repaint groupset: parent has no container element");if(!d){d=document.createElement("div"),d.className="groupset",this.dom.frame=d;var c=h.className;c&&O.addClassName(d,O.option.asString(c)),s+=1}d.parentNode||(p.appendChild(d),s+=1);var u=a(h.labelContainer);if(!u)throw Error('Cannot repaint groupset: option "labelContainer" not defined');l||(l=document.createElement("div"),l.className="labels",this.dom.labels=l),l.parentNode&&l.parentNode==u||(l.parentNode&&l.parentNode.removeChild(l.parentNode),u.appendChild(l)),s+=o(d.style,"height",r(h.height,this.height+"px")),s+=o(d.style,"top",r(h.top,"0px")),s+=o(d.style,"left",r(h.left,"0px")),s+=o(d.style,"width",r(h.width,"100%")),s+=o(l.style,"top",r(h.top,"0px"));var f=this,m=this.queue,g=this.groups,v=this.groupsData,y=Object.keys(m);if(y.length){y.forEach(function(t){var e=m[t],i=g[t];switch(e){case"add":case"update":if(!i){var n=Object.create(f.options);i=new b(f,t,n),i.setItems(f.itemsData),g[t]=i,f.controller.add(i)}i.data=v.get(t),delete m[t];break;case"remove":i&&(i.setItems(),delete g[t],f.controller.remove(i)),delete m[t];break;default:console.log('Error: unknown action "'+e+'"')}});var w=this.groupsData.getIds({order:this.options.groupsOrder});for(t=0;w.length>t;t++)(function(t,e){var i=0;e&&(i=function(){return e.top+e.height}),t.setOptions({top:i})})(g[w[t]],g[w[t-1]]);for(;l.firstChild;)l.removeChild(l.firstChild);for(t=0;w.length>t;t++)e=w[t],n=this._createLabel(e),l.appendChild(n);s++}for(e in g)g.hasOwnProperty(e)&&(i=g[e],n=i.label,n&&(n.style.top=i.top+"px",n.style.height=i.height+"px"));return s>0},w.prototype._createLabel=function(t){var e=this.groups[t],i=document.createElement("div");i.className="label";var n=document.createElement("div");n.className="inner",i.appendChild(n);var s=e.data&&e.data.content;s instanceof Element?n.appendChild(s):void 0!=s&&(n.innerHTML=s);var o=e.data&&e.data.className;return o&&O.addClassName(i,o),e.label=i,i},w.prototype.getContainer=function(){return this.dom.frame},w.prototype.getLabelsWidth=function(){return this.props.labels.width},w.prototype.reflow=function(){var t,e,i=0,n=this.options,s=O.updateProperty,o=O.option.asNumber,r=O.option.asSize,a=this.dom.frame;if(a){var h,d=o(n.maxHeight),l=null!=r(n.height);if(l)h=a.offsetHeight;else{h=0;for(t in this.groups)this.groups.hasOwnProperty(t)&&(e=this.groups[t],h+=e.height)}null!=d&&(h=Math.min(h,d)),i+=s(this,"height",h),i+=s(this,"top",a.offsetTop),i+=s(this,"left",a.offsetLeft),i+=s(this,"width",a.offsetWidth)}var p=0;for(t in this.groups)if(this.groups.hasOwnProperty(t)){e=this.groups[t];var c=e.props&&e.props.label&&e.props.label.width||0;p=Math.max(p,c)}return i+=s(this.props.labels,"width",p),i>0},w.prototype.hide=function(){return this.dom.frame&&this.dom.frame.parentNode?(this.dom.frame.parentNode.removeChild(this.dom.frame),!0):!1},w.prototype.show=function(){return this.dom.frame&&this.dom.frame.parentNode?!1:this.repaint()},w.prototype._onUpdate=function(t){this._toQueue(t,"update")},w.prototype._onAdd=function(t){this._toQueue(t,"add")},w.prototype._onRemove=function(t){this._toQueue(t,"remove")},w.prototype._toQueue=function(t,e){var i=this.queue;t.forEach(function(t){i[t]=e}),this.controller&&this.requestRepaint()},_.prototype.setOptions=function(t){t&&O.extend(this.options,t),this.controller.reflow(),this.controller.repaint()},_.prototype.setItems=function(t){var e,i=null==this.itemsData;if(t?t instanceof o&&(e=t):e=null,t instanceof o||(e=new o({convert:{start:"Date",end:"Date"}}),e.add(t)),this.itemsData=e,this.content.setItems(e),i&&(void 0==this.options.start||void 0==this.options.end)){var n=this.getItemRange(),s=n.min,r=n.max;if(null!=s&&null!=r){var a=r.valueOf()-s.valueOf();0>=a&&(a=864e5),s=new Date(s.valueOf()-.05*a),r=new Date(r.valueOf()+.05*a)}void 0!=this.options.start&&(s=new Date(this.options.start.valueOf())),void 0!=this.options.end&&(r=new Date(this.options.end.valueOf())),(null!=s||null!=r)&&this.range.setRange(s,r)}},_.prototype.setGroups=function(t){var e=this;this.groupsData=t;var i=this.groupsData?w:f;if(!(this.content instanceof i)){this.content&&(this.content.hide(),this.content.setItems&&this.content.setItems(),this.content.setGroups&&this.content.setGroups(),this.controller.remove(this.content));var n=Object.create(this.options);O.extend(n,{top:function(){return"top"==e.options.orientation?e.timeaxis.height:e.itemPanel.height-e.timeaxis.height-e.content.height},left:null,width:"100%",height:function(){return e.options.height?e.itemPanel.height-e.timeaxis.height:null},maxHeight:function(){if(e.options.maxHeight){if(!O.isNumber(e.options.maxHeight))throw new TypeError("Number expected for property maxHeight");return e.options.maxHeight-e.timeaxis.height}return null},labelContainer:function(){return e.labelPanel.getContainer()}}),this.content=new i(this.itemPanel,[this.timeaxis],n),this.content.setRange&&this.content.setRange(this.range),this.content.setItems&&this.content.setItems(this.itemsData),this.content.setGroups&&this.content.setGroups(this.groupsData),this.controller.add(this.content)}},_.prototype.getItemRange=function(){var t=this.itemsData,e=null,i=null;if(t){var n=t.min("start");e=n?n.start.valueOf():null;var s=t.max("start");s&&(i=s.start.valueOf());var o=t.max("end");o&&(i=null==i?o.end.valueOf():Math.max(i,o.end.valueOf()))}return{min:null!=e?new Date(e):null,max:null!=i?new Date(i):null}},function(t){function e(t){return M=t,c()}function i(){D=0,C=M.charAt(0)}function n(){D++,C=M.charAt(D)}function s(){return M.charAt(D+1)}function o(t){return L.test(t)}function r(t,e){if(t||(t={}),e)for(var i in e)e.hasOwnProperty(i)&&(t[i]=e[i]);return t}function a(t,e,i){for(var n=e.split("."),s=t;n.length;){var o=n.shift();n.length?(s[o]||(s[o]={}),s=s[o]):s[o]=i}}function h(t,e){for(var i,n,s=null,o=[t],a=t;a.parent;)o.push(a.parent),a=a.parent;if(a.nodes)for(i=0,n=a.nodes.length;n>i;i++)if(e.id===a.nodes[i].id){s=a.nodes[i];break}for(s||(s={id:e.id},t.node&&(s.attr=r(s.attr,t.node))),i=o.length-1;i>=0;i--){var h=o[i];h.nodes||(h.nodes=[]),-1==h.nodes.indexOf(s)&&h.nodes.push(s)}e.attr&&(s.attr=r(s.attr,e.attr))}function d(t,e){if(t.edges||(t.edges=[]),t.edges.push(e),t.edge){var i=r({},t.edge);e.attr=r(i,e.attr)}}function l(t,e,i,n,s){var o={from:e,to:i,type:n};return t.edge&&(o.attr=r({},t.edge)),o.attr=r(o.attr||{},s),o}function p(){for(N=x.NULL,O="";" "==C||" "==C||"\n"==C||"\r"==C;)n();do{var t=!1;if("#"==C){for(var e=D-1;" "==M.charAt(e)||" "==M.charAt(e);)e--;if("\n"==M.charAt(e)||""==M.charAt(e)){for(;""!=C&&"\n"!=C;)n();t=!0}}if("/"==C&&"/"==s()){for(;""!=C&&"\n"!=C;)n();t=!0}if("/"==C&&"*"==s()){for(;""!=C;){if("*"==C&&"/"==s()){n(),n();break}n()}t=!0}for(;" "==C||" "==C||"\n"==C||"\r"==C;)n()}while(t);if(""==C)return N=x.DELIMITER,void 0;var i=C+s();if(S[i])return N=x.DELIMITER,O=i,n(),n(),void 0;if(S[C])return N=x.DELIMITER,O=C,n(),void 0;if(o(C)||"-"==C){for(O+=C,n();o(C);)O+=C,n();return"false"==O?O=!1:"true"==O?O=!0:isNaN(Number(O))||(O=Number(O)),N=x.IDENTIFIER,void 0}if('"'==C){for(n();""!=C&&('"'!=C||'"'==C&&'"'==s());)O+=C,'"'==C&&n(),n();if('"'!=C)throw w('End of string " expected');return n(),N=x.IDENTIFIER,void 0}for(N=x.UNKNOWN;""!=C;)O+=C,n();throw new SyntaxError('Syntax error in part "'+_(O,30)+'"')}function c(){var t={};if(i(),p(),"strict"==O&&(t.strict=!0,p()),("graph"==O||"digraph"==O)&&(t.type=O,p()),N==x.IDENTIFIER&&(t.id=O,p()),"{"!=O)throw w("Angle bracket { expected");if(p(),u(t),"}"!=O)throw w("Angle bracket } expected");if(p(),""!==O)throw w("End of file expected");return p(),delete t.node,delete t.edge,delete t.graph,t}function u(t){for(;""!==O&&"}"!=O;)f(t),";"==O&&p()}function f(t){var e=m(t);if(e)return y(t,e),void 0;var i=g(t);if(!i){if(N!=x.IDENTIFIER)throw w("Identifier expected");var n=O;if(p(),"="==O){if(p(),N!=x.IDENTIFIER)throw w("Identifier expected");t[n]=O,p()}else v(t,n)}}function m(t){var e=null;if("subgraph"==O&&(e={},e.type="subgraph",p(),N==x.IDENTIFIER&&(e.id=O,p())),"{"==O){if(p(),e||(e={}),e.parent=t,e.node=t.node,e.edge=t.edge,e.graph=t.graph,u(e),"}"!=O)throw w("Angle bracket } expected");p(),delete e.node,delete e.edge,delete e.graph,delete e.parent,t.subgraphs||(t.subgraphs=[]),t.subgraphs.push(e)}return e}function g(t){return"node"==O?(p(),t.node=b(),"node"):"edge"==O?(p(),t.edge=b(),"edge"):"graph"==O?(p(),t.graph=b(),"graph"):null}function v(t,e){var i={id:e},n=b();n&&(i.attr=n),h(t,i),y(t,e)}function y(t,e){for(;"->"==O||"--"==O;){var i,n=O;p();var s=m(t);if(s)i=s;else{if(N!=x.IDENTIFIER)throw w("Identifier or subgraph expected");i=O,h(t,{id:i}),p()}var o=b(),r=l(t,e,i,n,o);d(t,r),e=i}}function b(){for(var t=null;"["==O;){for(p(),t={};""!==O&&"]"!=O;){if(N!=x.IDENTIFIER)throw w("Attribute name expected");var e=O;if(p(),"="!=O)throw w("Equal sign = expected");if(p(),N!=x.IDENTIFIER)throw w("Attribute value expected");var i=O;a(t,e,i),p(),","==O&&p()}if("]"!=O)throw w("Bracket ] expected");p()}return t}function w(t){return new SyntaxError(t+', got "'+_(O,30)+'" (char '+D+")")}function _(t,e){return e>=t.length?t:t.substr(0,27)+"..."}function E(t,e,i){t instanceof Array?t.forEach(function(t){e instanceof Array?e.forEach(function(e){i(t,e)}):i(t,e)}):e instanceof Array?e.forEach(function(e){i(t,e)}):i(t,e)}function T(t){function i(t){var e={from:t.from,to:t.to};return r(e,t.attr),e.style="->"==t.type?"arrow":"line",e}var n=e(t),s={nodes:[],edges:[],options:{}};return n.nodes&&n.nodes.forEach(function(t){var e={id:t.id,label:(t.label||t.id)+""};r(e,t.attr),e.image&&(e.shape="image"),s.nodes.push(e)}),n.edges&&n.edges.forEach(function(t){var e,n;e=t.from instanceof Object?t.from.nodes:{id:t.from},n=t.to instanceof Object?t.to.nodes:{id:t.to},t.from instanceof Object&&t.from.edges&&t.from.edges.forEach(function(t){var e=i(t);s.edges.push(e)}),E(e,n,function(e,n){var o=l(s,e.id,n.id,t.type,t.attr),r=i(o);s.edges.push(r)}),t.to instanceof Object&&t.to.edges&&t.to.edges.forEach(function(t){var e=i(t);s.edges.push(e)})}),n.attr&&(s.options=n.attr),s}var x={NULL:0,DELIMITER:1,IDENTIFIER:2,UNKNOWN:3},S={"{":!0,"}":!0,"[":!0,"]":!0,";":!0,"=":!0,",":!0,"->":!0,"--":!0},M="",D=0,C="",O="",N=x.NULL,L=/[a-zA-Z_0-9.:#]/;t.parseDOT=e,t.DOTToGraph=T}(O!==void 0?O:n),"undefined"!=typeof CanvasRenderingContext2D&&(CanvasRenderingContext2D.prototype.circle=function(t,e,i){this.beginPath(),this.arc(t,e,i,0,2*Math.PI,!1)},CanvasRenderingContext2D.prototype.square=function(t,e,i){this.beginPath(),this.rect(t-i,e-i,2*i,2*i)},CanvasRenderingContext2D.prototype.triangle=function(t,e,i){this.beginPath();var n=2*i,s=n/2,o=Math.sqrt(3)/6*n,r=Math.sqrt(n*n-s*s);this.moveTo(t,e-(r-o)),this.lineTo(t+s,e+o),this.lineTo(t-s,e+o),this.lineTo(t,e-(r-o)),this.closePath()},CanvasRenderingContext2D.prototype.triangleDown=function(t,e,i){this.beginPath();var n=2*i,s=n/2,o=Math.sqrt(3)/6*n,r=Math.sqrt(n*n-s*s);this.moveTo(t,e+(r-o)),this.lineTo(t+s,e-o),this.lineTo(t-s,e-o),this.lineTo(t,e+(r-o)),this.closePath()},CanvasRenderingContext2D.prototype.star=function(t,e,i){this.beginPath();for(var n=0;10>n;n++){var s=0===n%2?1.3*i:.5*i;this.lineTo(t+s*Math.sin(2*n*Math.PI/10),e-s*Math.cos(2*n*Math.PI/10))}this.closePath()},CanvasRenderingContext2D.prototype.roundRect=function(t,e,i,n,s){var o=Math.PI/180;0>i-2*s&&(s=i/2),0>n-2*s&&(s=n/2),this.beginPath(),this.moveTo(t+s,e),this.lineTo(t+i-s,e),this.arc(t+i-s,e+s,s,270*o,360*o,!1),this.lineTo(t+i,e+n-s),this.arc(t+i-s,e+n-s,s,0,90*o,!1),this.lineTo(t+s,e+n),this.arc(t+s,e+n-s,s,90*o,180*o,!1),this.lineTo(t,e+s),this.arc(t+s,e+s,s,180*o,270*o,!1)},CanvasRenderingContext2D.prototype.ellipse=function(t,e,i,n){var s=.5522848,o=i/2*s,r=n/2*s,a=t+i,h=e+n,d=t+i/2,l=e+n/2;this.beginPath(),this.moveTo(t,l),this.bezierCurveTo(t,l-r,d-o,e,d,e),this.bezierCurveTo(d+o,e,a,l-r,a,l),this.bezierCurveTo(a,l+r,d+o,h,d,h),this.bezierCurveTo(d-o,h,t,l+r,t,l)},CanvasRenderingContext2D.prototype.database=function(t,e,i,n){var s=1/3,o=i,r=n*s,a=.5522848,h=o/2*a,d=r/2*a,l=t+o,p=e+r,c=t+o/2,u=e+r/2,f=e+(n-r/2),m=e+n;this.beginPath(),this.moveTo(l,u),this.bezierCurveTo(l,u+d,c+h,p,c,p),this.bezierCurveTo(c-h,p,t,u+d,t,u),this.bezierCurveTo(t,u-d,c-h,e,c,e),this.bezierCurveTo(c+h,e,l,u-d,l,u),this.lineTo(l,f),this.bezierCurveTo(l,f+d,c+h,m,c,m),this.bezierCurveTo(c-h,m,t,f+d,t,f),this.lineTo(t,u)},CanvasRenderingContext2D.prototype.arrow=function(t,e,i,n){var s=t-n*Math.cos(i),o=e-n*Math.sin(i),r=t-.9*n*Math.cos(i),a=e-.9*n*Math.sin(i),h=s+n/3*Math.cos(i+.5*Math.PI),d=o+n/3*Math.sin(i+.5*Math.PI),l=s+n/3*Math.cos(i-.5*Math.PI),p=o+n/3*Math.sin(i-.5*Math.PI);this.beginPath(),this.moveTo(t,e),this.lineTo(h,d),this.lineTo(r,a),this.lineTo(l,p),this.closePath()},CanvasRenderingContext2D.prototype.dashedLine=function(t,e,i,n,s){s||(s=[10,5]),0==c&&(c=.001);var o=s.length;this.moveTo(t,e);for(var r=i-t,a=n-e,h=a/r,d=Math.sqrt(r*r+a*a),l=0,p=!0;d>=.1;){var c=s[l++%o];c>d&&(c=d);var u=Math.sqrt(c*c/(1+h*h));0>r&&(u=-u),t+=u,e+=h*u,this[p?"lineTo":"moveTo"](t,e),d-=c,p=!p}}),E.prototype.attachEdge=function(t){-1==this.edges.indexOf(t)&&this.edges.push(t),this._updateMass()},E.prototype.detachEdge=function(t){var e=this.edges.indexOf(t);-1!=e&&this.edges.splice(e,1),this._updateMass()},E.prototype._updateMass=function(){this.mass=50+20*this.edges.length},E.prototype.setProperties=function(t,e){if(t){if(void 0!=t.id&&(this.id=t.id),void 0!=t.label&&(this.label=t.label),void 0!=t.title&&(this.title=t.title),void 0!=t.group&&(this.group=t.group),void 0!=t.x&&(this.x=t.x),void 0!=t.y&&(this.y=t.y),void 0!=t.value&&(this.value=t.value),void 0===this.id)throw"Node must have an id";if(this.group){var i=this.grouplist.get(this.group);for(var n in i)i.hasOwnProperty(n)&&(this[n]=i[n])}if(void 0!=t.shape&&(this.shape=t.shape),void 0!=t.image&&(this.image=t.image),void 0!=t.radius&&(this.radius=t.radius),void 0!=t.color&&(this.color=E.parseColor(t.color)),void 0!=t.fontColor&&(this.fontColor=t.fontColor),void 0!=t.fontSize&&(this.fontSize=t.fontSize),void 0!=t.fontFace&&(this.fontFace=t.fontFace),void 0!=this.image){if(!this.imagelist)throw"No imagelist provided";this.imageObj=this.imagelist.load(this.image)}switch(this.xFixed=this.xFixed||void 0!=t.x,this.yFixed=this.yFixed||void 0!=t.y,this.radiusFixed=this.radiusFixed||void 0!=t.radius,"image"==this.shape&&(this.radiusMin=e.nodes.widthMin,this.radiusMax=e.nodes.widthMax),this.shape){case"database":this.draw=this._drawDatabase,this.resize=this._resizeDatabase;break;case"box":this.draw=this._drawBox,this.resize=this._resizeBox;break;case"circle":this.draw=this._drawCircle,this.resize=this._resizeCircle;break;case"ellipse":this.draw=this._drawEllipse,this.resize=this._resizeEllipse;break;case"image":this.draw=this._drawImage,this.resize=this._resizeImage;break;case"text":this.draw=this._drawText,this.resize=this._resizeText;break;case"dot":this.draw=this._drawDot,this.resize=this._resizeShape;break;case"square":this.draw=this._drawSquare,this.resize=this._resizeShape;break;case"triangle":this.draw=this._drawTriangle,this.resize=this._resizeShape;break;case"triangleDown":this.draw=this._drawTriangleDown,this.resize=this._resizeShape;break;case"star":this.draw=this._drawStar,this.resize=this._resizeShape;break;default:this.draw=this._drawEllipse,this.resize=this._resizeEllipse}this._reset()}},E.parseColor=function(t){var e;return O.isString(t)?e={border:t,background:t,highlight:{border:t,background:t}}:(e={},e.background=t.background||"white",e.border=t.border||e.background,O.isString(t.highlight)?e.highlight={border:t.highlight,background:t.highlight}:(e.highlight={},e.highlight.background=t.highlight&&t.highlight.background||e.background,e.highlight.border=t.highlight&&t.highlight.border||e.border)),e},E.prototype.select=function(){this.selected=!0,this._reset()},E.prototype.unselect=function(){this.selected=!1,this._reset()},E.prototype._reset=function(){this.width=void 0,this.height=void 0},E.prototype.getTitle=function(){return this.title},E.prototype.distanceToBorder=function(t,e){var i=1;switch(this.width||this.resize(t),this.shape){case"circle":case"dot":return this.radius+i;case"ellipse":var n=this.width/2,s=this.height/2,o=Math.sin(e)*n,r=Math.cos(e)*s;return n*s/Math.sqrt(o*o+r*r);case"box":case"image":case"text":default:return this.width?Math.min(Math.abs(this.width/2/Math.cos(e)),Math.abs(this.height/2/Math.sin(e)))+i:0}},E.prototype._setForce=function(t,e){this.fx=t,this.fy=e},E.prototype._addForce=function(t,e){this.fx+=t,this.fy+=e},E.prototype.discreteStep=function(t){if(!this.xFixed){var e=-this.damping*this.vx,i=(this.fx+e)/this.mass;this.vx+=i/t,this.x+=this.vx/t}if(!this.yFixed){var n=-this.damping*this.vy,s=(this.fy+n)/this.mass;this.vy+=s/t,this.y+=this.vy/t}},E.prototype.isFixed=function(){return this.xFixed&&this.yFixed},E.prototype.isMoving=function(t){return Math.abs(this.vx)>t||Math.abs(this.vy)>t||!this.xFixed&&Math.abs(this.fx)>this.minForce||!this.yFixed&&Math.abs(this.fy)>this.minForce},E.prototype.isSelected=function(){return this.selected},E.prototype.getValue=function(){return this.value},E.prototype.getDistance=function(t,e){var i=this.x-t,n=this.y-e;return Math.sqrt(i*i+n*n)},E.prototype.setValueRange=function(t,e){if(!this.radiusFixed&&void 0!==this.value){var i=(this.radiusMax-this.radiusMin)/(e-t);this.radius=(this.value-t)*i+this.radiusMin}},E.prototype.draw=function(){throw"Draw method not initialized for node"},E.prototype.resize=function(){throw"Resize method not initialized for node"},E.prototype.isOverlappingWith=function(t){return this.leftt.left&&this.topt.top},E.prototype._resizeImage=function(){if(!this.width){var t,e;if(this.value){var i=this.imageObj.height/this.imageObj.width;t=this.radius||this.imageObj.width,e=this.radius*i||this.imageObj.height}else t=this.imageObj.width,e=this.imageObj.height;this.width=t,this.height=e}},E.prototype._drawImage=function(t){this._resizeImage(t),this.left=this.x-this.width/2,this.top=this.y-this.height/2;var e;this.imageObj?(t.drawImage(this.imageObj,this.left,this.top,this.width,this.height),e=this.y+this.height/2):e=this.y,this._label(t,this.label,this.x,e,void 0,"top")},E.prototype._resizeBox=function(t){if(!this.width){var e=5,i=this.getTextSize(t);this.width=i.width+2*e,this.height=i.height+2*e}},E.prototype._drawBox=function(t){this._resizeBox(t),this.left=this.x-this.width/2,this.top=this.y-this.height/2,t.strokeStyle=this.selected?this.color.highlight.border:this.color.border,t.fillStyle=this.selected?this.color.highlight.background:this.color.background,t.lineWidth=this.selected?2:1,t.roundRect(this.left,this.top,this.width,this.height,this.radius),t.fill(),t.stroke(),this._label(t,this.label,this.x,this.y)},E.prototype._resizeDatabase=function(t){if(!this.width){var e=5,i=this.getTextSize(t),n=i.width+2*e;this.width=n,this.height=n}},E.prototype._drawDatabase=function(t){this._resizeDatabase(t),this.left=this.x-this.width/2,this.top=this.y-this.height/2,t.strokeStyle=this.selected?this.color.highlight.border:this.color.border,t.fillStyle=this.selected?this.color.highlight.background:this.color.background,t.lineWidth=this.selected?2:1,t.database(this.x-this.width/2,this.y-.5*this.height,this.width,this.height),t.fill(),t.stroke(),this._label(t,this.label,this.x,this.y)},E.prototype._resizeCircle=function(t){if(!this.width){var e=5,i=this.getTextSize(t),n=Math.max(i.width,i.height)+2*e;this.radius=n/2,this.width=n,this.height=n}},E.prototype._drawCircle=function(t){this._resizeCircle(t),this.left=this.x-this.width/2,this.top=this.y-this.height/2,t.strokeStyle=this.selected?this.color.highlight.border:this.color.border,t.fillStyle=this.selected?this.color.highlight.background:this.color.background,t.lineWidth=this.selected?2:1,t.circle(this.x,this.y,this.radius),t.fill(),t.stroke(),this._label(t,this.label,this.x,this.y)},E.prototype._resizeEllipse=function(t){if(!this.width){var e=this.getTextSize(t);this.width=1.5*e.width,this.height=2*e.height,this.widthl;l++)t.fillText(r[l],i,d),d+=h}},E.prototype.getTextSize=function(t){if(void 0!=this.label){t.font=(this.selected?"bold ":"")+this.fontSize+"px "+this.fontFace;for(var e=this.label.split("\n"),i=(this.fontSize+4)*e.length,n=0,s=0,o=e.length;o>s;s++)n=Math.max(n,t.measureText(e[s]).width);return{width:n,height:i}}return{width:0,height:0}},T.prototype.setProperties=function(t,e){if(t)switch(void 0!=t.from&&(this.fromId=t.from),void 0!=t.to&&(this.toId=t.to),void 0!=t.id&&(this.id=t.id),void 0!=t.style&&(this.style=t.style),void 0!=t.label&&(this.label=t.label),this.label&&(this.fontSize=e.edges.fontSize,this.fontFace=e.edges.fontFace,this.fontColor=e.edges.fontColor,void 0!=t.fontColor&&(this.fontColor=t.fontColor),void 0!=t.fontSize&&(this.fontSize=t.fontSize),void 0!=t.fontFace&&(this.fontFace=t.fontFace)),void 0!=t.title&&(this.title=t.title),void 0!=t.width&&(this.width=t.width),void 0!=t.value&&(this.value=t.value),void 0!=t.length&&(this.length=t.length),t.dash&&(void 0!=t.dash.length&&(this.dash.length=t.dash.length),void 0!=t.dash.gap&&(this.dash.gap=t.dash.gap),void 0!=t.dash.altLength&&(this.dash.altLength=t.dash.altLength)),void 0!=t.color&&(this.color=t.color),this.connect(),this.widthFixed=this.widthFixed||void 0!=t.width,this.lengthFixed=this.lengthFixed||void 0!=t.length,this.stiffness=1/this.length,this.style){case"line":this.draw=this._drawLine;break;case"arrow":this.draw=this._drawArrow;break;case"arrow-center":this.draw=this._drawArrowCenter;break;case"dash-line":this.draw=this._drawDashLine;break;default:this.draw=this._drawLine}},T.prototype.connect=function(){this.disconnect(),this.from=this.graph.nodes[this.fromId]||null,this.to=this.graph.nodes[this.toId]||null,this.connected=this.from&&this.to,this.connected?(this.from.attachEdge(this),this.to.attachEdge(this)):(this.from&&this.from.detachEdge(this),this.to&&this.to.detachEdge(this))},T.prototype.disconnect=function(){this.from&&(this.from.detachEdge(this),this.from=null),this.to&&(this.to.detachEdge(this),this.to=null),this.connected=!1},T.prototype.getTitle=function(){return this.title},T.prototype.getValue=function(){return this.value},T.prototype.setValueRange=function(t,e){if(!this.widthFixed&&void 0!==this.value){var i=(this.widthMax-this.widthMin)/(e-t);this.width=(this.value-t)*i+this.widthMin}},T.prototype.draw=function(){throw"Method draw not initialized in edge"},T.prototype.isOverlappingWith=function(t){var e=10,i=this.from.x,n=this.from.y,s=this.to.x,o=this.to.y,r=t.left,a=t.top,h=T._dist(i,n,s,o,r,a);return e>h},T.prototype._drawLine=function(t){t.strokeStyle=this.color,t.lineWidth=this._getLineWidth();var e;if(this.from!=this.to)this._line(t),this.label&&(e=this._pointOnLine(.5),this._label(t,this.label,e.x,e.y));else{var i,n,s=this.length/4,o=this.from;o.width||o.resize(t),o.width>o.height?(i=o.x+o.width/2,n=o.y-s):(i=o.x+s,n=o.y-o.height/2),this._circle(t,i,n,s),e=this._pointOnCircle(i,n,s,.5),this._label(t,this.label,e.x,e.y)}},T.prototype._getLineWidth=function(){return this.from.selected||this.to.selected?Math.min(2*this.width,this.widthMax):this.width},T.prototype._line=function(t){t.beginPath(),t.moveTo(this.from.x,this.from.y),t.lineTo(this.to.x,this.to.y),t.stroke()},T.prototype._circle=function(t,e,i,n){t.beginPath(),t.arc(e,i,n,0,2*Math.PI,!1),t.stroke()},T.prototype._label=function(t,e,i,n){if(e){t.font=(this.from.selected||this.to.selected?"bold ":"")+this.fontSize+"px "+this.fontFace,t.fillStyle="white";var s=t.measureText(e).width,o=this.fontSize,r=i-s/2,a=n-o/2;t.fillRect(r,a,s,o),t.fillStyle=this.fontColor||"black",t.textAlign="left",t.textBaseline="top",t.fillText(e,r,a)}},T.prototype._drawDashLine=function(t){if(t.strokeStyle=this.color,t.lineWidth=this._getLineWidth(),t.beginPath(),t.lineCap="round",void 0!=this.dash.altLength?t.dashedLine(this.from.x,this.from.y,this.to.x,this.to.y,[this.dash.length,this.dash.gap,this.dash.altLength,this.dash.gap]):void 0!=this.dash.length&&void 0!=this.dash.gap?t.dashedLine(this.from.x,this.from.y,this.to.x,this.to.y,[this.dash.length,this.dash.gap]):(t.moveTo(this.from.x,this.from.y),t.lineTo(this.to.x,this.to.y)),t.stroke(),this.label){var e=this._pointOnLine(.5);this._label(t,this.label,e.x,e.y)}},T.prototype._pointOnLine=function(t){return{x:(1-t)*this.from.x+t*this.to.x,y:(1-t)*this.from.y+t*this.to.y}},T.prototype._pointOnCircle=function(t,e,i,n){var s=2*(n-3/8)*Math.PI;return{x:t+i*Math.cos(s),y:e-i*Math.sin(s)}},T.prototype._drawArrowCenter=function(t){var e;if(t.strokeStyle=this.color,t.fillStyle=this.color,t.lineWidth=this._getLineWidth(),this.from!=this.to){this._line(t);var i=Math.atan2(this.to.y-this.from.y,this.to.x-this.from.x),n=10+5*this.width;e=this._pointOnLine(.5),t.arrow(e.x,e.y,i,n),t.fill(),t.stroke(),this.label&&(e=this._pointOnLine(.5),this._label(t,this.label,e.x,e.y))}else{var s,o,r=this.length/4,a=this.from;a.width||a.resize(t),a.width>a.height?(s=a.x+a.width/2,o=a.y-r):(s=a.x+r,o=a.y-a.height/2),this._circle(t,s,o,r);var i=.2*Math.PI,n=10+5*this.width;e=this._pointOnCircle(s,o,r,.5),t.arrow(e.x,e.y,i,n),t.fill(),t.stroke(),this.label&&(e=this._pointOnCircle(s,o,r,.5),this._label(t,this.label,e.x,e.y))}},T.prototype._drawArrow=function(t){t.strokeStyle=this.color,t.fillStyle=this.color,t.lineWidth=this._getLineWidth();var e,i;if(this.from!=this.to){e=Math.atan2(this.to.y-this.from.y,this.to.x-this.from.x);var n=this.to.x-this.from.x,s=this.to.y-this.from.y,o=Math.sqrt(n*n+s*s),r=this.from.distanceToBorder(t,e+Math.PI),a=(o-r)/o,h=a*this.from.x+(1-a)*this.to.x,d=a*this.from.y+(1-a)*this.to.y,l=this.to.distanceToBorder(t,e),p=(o-l)/o,c=(1-p)*this.from.x+p*this.to.x,u=(1-p)*this.from.y+p*this.to.y;if(t.beginPath(),t.moveTo(h,d),t.lineTo(c,u),t.stroke(),i=10+5*this.width,t.arrow(c,u,e,i),t.fill(),t.stroke(),this.label){var f=this._pointOnLine(.5);this._label(t,this.label,f.x,f.y)}}else{var m,g,v,y=this.from,b=this.length/4;y.width||y.resize(t),y.width>y.height?(m=y.x+y.width/2,g=y.y-b,v={x:m,y:y.y,angle:.9*Math.PI}):(m=y.x+b,g=y.y-y.height/2,v={x:y.x,y:g,angle:.6*Math.PI}),t.beginPath(),t.arc(m,g,b,0,2*Math.PI,!1),t.stroke(),i=10+5*this.width,t.arrow(v.x,v.y,v.angle,i),t.fill(),t.stroke(),this.label&&(f=this._pointOnCircle(m,g,b,.5),this._label(t,this.label,f.x,f.y)) +}},T._dist=function(t,e,i,n,s,o){var r=i-t,a=n-e,h=r*r+a*a,d=((s-t)*r+(o-e)*a)/h;d>1?d=1:0>d&&(d=0);var l=t+d*r,p=e+d*a,c=l-s,u=p-o;return Math.sqrt(c*c+u*u)},x.prototype.setPosition=function(t,e){this.x=parseInt(t),this.y=parseInt(e)},x.prototype.setText=function(t){this.frame.innerHTML=t},x.prototype.show=function(t){if(void 0===t&&(t=!0),t){var e=this.frame.clientHeight,i=this.frame.clientWidth,n=this.frame.parentNode.clientHeight,s=this.frame.parentNode.clientWidth,o=this.y-e;o+e+this.padding>n&&(o=n-e-this.padding),this.padding>o&&(o=this.padding);var r=this.x;r+i+this.padding>s&&(r=s-i-this.padding),this.padding>r&&(r=this.padding),this.frame.style.left=r+"px",this.frame.style.top=o+"px",this.frame.style.visibility="visible"}else this.hide()},x.prototype.hide=function(){this.frame.style.visibility="hidden"},Groups=function(){this.clear(),this.defaultIndex=0},Groups.DEFAULT=[{border:"#2B7CE9",background:"#97C2FC",highlight:{border:"#2B7CE9",background:"#D2E5FF"}},{border:"#FFA500",background:"#FFFF00",highlight:{border:"#FFA500",background:"#FFFFA3"}},{border:"#FA0A10",background:"#FB7E81",highlight:{border:"#FA0A10",background:"#FFAFB1"}},{border:"#41A906",background:"#7BE141",highlight:{border:"#41A906",background:"#A1EC76"}},{border:"#E129F0",background:"#EB7DF4",highlight:{border:"#E129F0",background:"#F0B3F5"}},{border:"#7C29F0",background:"#AD85E4",highlight:{border:"#7C29F0",background:"#D3BDF0"}},{border:"#C37F00",background:"#FFA807",highlight:{border:"#C37F00",background:"#FFCA66"}},{border:"#4220FB",background:"#6E6EFD",highlight:{border:"#4220FB",background:"#9B9BFD"}},{border:"#FD5A77",background:"#FFC0CB",highlight:{border:"#FD5A77",background:"#FFD1D9"}},{border:"#4AD63A",background:"#C2FABC",highlight:{border:"#4AD63A",background:"#E6FFE3"}}],Groups.prototype.clear=function(){this.groups={},this.groups.length=function(){var t=0;for(var e in this)this.hasOwnProperty(e)&&t++;return t}},Groups.prototype.get=function(t){var e=this.groups[t];if(void 0==e){var i=this.defaultIndex%Groups.DEFAULT.length;this.defaultIndex++,e={},e.color=Groups.DEFAULT[i],this.groups[t]=e}return e},Groups.prototype.add=function(t,e){return this.groups[t]=e,e.color&&(e.color=E.parseColor(e.color)),e},Images=function(){this.images={},this.callback=void 0},Images.prototype.setOnloadCallback=function(t){this.callback=t},Images.prototype.load=function(t){var e=this.images[t];if(void 0==e){var i=this;e=new Image,this.images[t]=e,e.onload=function(){i.callback&&i.callback(this)},e.src=t}return e},S.prototype.setData=function(t){if(t&&t.dot&&(t.nodes||t.edges))throw new SyntaxError('Data must contain either parameter "dot" or parameter pair "nodes" and "edges", but not both.');if(this.setOptions(t&&t.options),t&&t.dot){if(t&&t.dot){var e=k.util.DOTToGraph(t.dot);return this.setData(e),void 0}}else this._setNodes(t&&t.nodes),this._setEdges(t&&t.edges);this.stabilize&&this._doStabilize(),this.start()},S.prototype.setOptions=function(t){if(t){if(void 0!=t.width&&(this.width=t.width),void 0!=t.height&&(this.height=t.height),void 0!=t.stabilize&&(this.stabilize=t.stabilize),void 0!=t.selectable&&(this.selectable=t.selectable),t.edges){for(var e in t.edges)t.edges.hasOwnProperty(e)&&(this.constants.edges[e]=t.edges[e]);void 0!=t.edges.length&&t.nodes&&void 0==t.nodes.distance&&(this.constants.edges.length=t.edges.length,this.constants.nodes.distance=1.25*t.edges.length),t.edges.fontColor||(this.constants.edges.fontColor=t.edges.color),t.edges.dash&&(void 0!=t.edges.dash.length&&(this.constants.edges.dash.length=t.edges.dash.length),void 0!=t.edges.dash.gap&&(this.constants.edges.dash.gap=t.edges.dash.gap),void 0!=t.edges.dash.altLength&&(this.constants.edges.dash.altLength=t.edges.dash.altLength))}if(t.nodes){for(e in t.nodes)t.nodes.hasOwnProperty(e)&&(this.constants.nodes[e]=t.nodes[e]);t.nodes.color&&(this.constants.nodes.color=E.parseColor(t.nodes.color))}if(t.groups)for(var i in t.groups)if(t.groups.hasOwnProperty(i)){var n=t.groups[i];this.groups.add(i,n)}}this.setSize(this.width,this.height),this._setTranslation(this.frame.clientWidth/2,this.frame.clientHeight/2),this._setScale(1)},S.prototype._trigger=function(t,e){L.trigger(this,t,e)},S.prototype._create=function(){for(;this.containerElement.hasChildNodes();)this.containerElement.removeChild(this.containerElement.firstChild);if(this.frame=document.createElement("div"),this.frame.className="graph-frame",this.frame.style.position="relative",this.frame.style.overflow="hidden",this.frame.canvas=document.createElement("canvas"),this.frame.canvas.style.position="relative",this.frame.appendChild(this.frame.canvas),!this.frame.canvas.getContext){var t=document.createElement("DIV");t.style.color="red",t.style.fontWeight="bold",t.style.padding="10px",t.innerHTML="Error: your browser does not support HTML canvas",this.frame.canvas.appendChild(t)}var e=this;this.drag={},this.pinch={},this.hammer=D(this.frame.canvas,{prevent_default:!0}),this.hammer.on("tap",e._onTap.bind(e)),this.hammer.on("hold",e._onHold.bind(e)),this.hammer.on("pinch",e._onPinch.bind(e)),this.hammer.on("touch",e._onTouch.bind(e)),this.hammer.on("dragstart",e._onDragStart.bind(e)),this.hammer.on("drag",e._onDrag.bind(e)),this.hammer.on("dragend",e._onDragEnd.bind(e)),this.hammer.on("mousewheel",e._onMouseWheel.bind(e)),this.hammer.on("mousemove",e._onMouseMoveTitle.bind(e)),this.containerElement.appendChild(this.frame)},S.prototype._getNodeAt=function(t){var e=this._xToCanvas(t.x),i=this._yToCanvas(t.y),n={left:e,top:i,right:e,bottom:i},s=this._getNodesOverlappingWith(n);return s.length>0?s[s.length-1]:null},S.prototype._getPointer=function(t){return{x:t.pageX-k.util.getAbsoluteLeft(this.frame.canvas),y:t.pageY-k.util.getAbsoluteTop(this.frame.canvas)}},S.prototype._onTouch=function(t){this.drag.pointer=this._getPointer(t.gesture.touches[0]),this.drag.pinched=!1,this.pinch.scale=this._getScale()},S.prototype._onDragStart=function(){var t=this.drag;t.translation=this._getTranslation(),t.nodeId=this._getNodeAt(t.pointer);var e=this.nodes[t.nodeId];e&&!e.isSelected()&&this._selectNodes([t.nodeId]);var i=this;t.selection=[],this.selection.forEach(function(e){var n=i.nodes[e];if(n){var s={id:e,node:n,x:n.x,y:n.y,xFixed:n.xFixed,yFixed:n.yFixed};n.xFixed=!0,n.yFixed=!0,t.selection.push(s)}})},S.prototype._onDrag=function(t){if(!this.drag.pinched){var e=this._getPointer(t.gesture.touches[0]),i=this,n=this.drag,s=n.selection;if(s&&s.length){var o=e.x-n.pointer.x,r=e.y-n.pointer.y;s.forEach(function(t){var e=t.node;t.xFixed||(e.x=i._xToCanvas(i._canvasToX(t.x)+o)),t.yFixed||(e.y=i._yToCanvas(i._canvasToX(t.y)+r))}),this.moving||(this.moving=!0,this.start())}else{var a=e.x-this.drag.pointer.x,h=e.y-this.drag.pointer.y;this._setTranslation(this.drag.translation.x+a,this.drag.translation.y+h),this._redraw(),this.moved=!0}}},S.prototype._onDragEnd=function(){var t=this.drag.selection;t&&t.forEach(function(t){t.node.xFixed=t.xFixed,t.node.yFixed=t.yFixed})},S.prototype._onTap=function(t){var e=this._getPointer(t.gesture.touches[0]),i=this._getNodeAt(e),n=this.nodes[i];n?(this._selectNodes([i]),this.moving||this._redraw()):(this._unselectNodes(),this._redraw())},S.prototype._onHold=function(t){var e=this._getPointer(t.gesture.touches[0]),i=this._getNodeAt(e),n=this.nodes[i];if(n){if(n.isSelected())this._unselectNodes([i]);else{var s=!0;this._selectNodes([i],s)}this.moving||this._redraw()}},S.prototype._onPinch=function(t){var e=this._getPointer(t.gesture.center);this.drag.pinched=!0,"scale"in this.pinch||(this.pinch.scale=1);var i=this.pinch.scale*t.gesture.scale;this._zoom(i,e)},S.prototype._zoom=function(t,e){var i=this._getScale();.01>t&&(t=.01),t>10&&(t=10);var n=this._getTranslation(),s=t/i,o=(1-s)*e.x+n.x*s,r=(1-s)*e.y+n.y*s;return this._setScale(t),this._setTranslation(o,r),this._redraw(),t},S.prototype._onMouseWheel=function(t){var e=0;if(t.wheelDelta?e=t.wheelDelta/120:t.detail&&(e=-t.detail/3),e){"mouswheelScale"in this.pinch||(this.pinch.mouswheelScale=1);var i=this.pinch.mouswheelScale,n=e/10;0>e&&(n/=1-n),i*=1+n;var s=D.event.collectEventData(this,"scroll",t),o=this._getPointer(s.center);i=this._zoom(i,o),this.pinch.mouswheelScale=i}t.preventDefault()},S.prototype._onMouseMoveTitle=function(t){var e=D.event.collectEventData(this,"mousemove",t),i=this._getPointer(e.center);this.popupNode&&this._checkHidePopup(i);var n=this,s=function(){n._checkShowPopup(i)};this.popupTimer&&clearInterval(this.popupTimer),this.leftButtonDown||(this.popupTimer=setTimeout(s,300))},S.prototype._checkShowPopup=function(t){var e,i={left:this._xToCanvas(t.x),top:this._yToCanvas(t.y),right:this._xToCanvas(t.x),bottom:this._yToCanvas(t.y)},n=this.popupNode;if(void 0==this.popupNode){var s=this.nodes;for(e in s)if(s.hasOwnProperty(e)){var o=s[e];if(void 0!=o.getTitle()&&o.isOverlappingWith(i)){this.popupNode=o;break}}}if(void 0==this.popupNode){var r=this.edges;for(e in r)if(r.hasOwnProperty(e)){var a=r[e];if(a.connected&&void 0!=a.getTitle()&&a.isOverlappingWith(i)){this.popupNode=a;break}}}if(this.popupNode){if(this.popupNode!=n){var h=this;h.popup||(h.popup=new x(h.frame)),h.popup.setPosition(t.x-3,t.y-3),h.popup.setText(h.popupNode.getTitle()),h.popup.show()}}else this.popup&&this.popup.hide()},S.prototype._checkHidePopup=function(t){this.popupNode&&this._getNodeAt(t)||(this.popupNode=void 0,this.popup&&this.popup.hide())},S.prototype._unselectNodes=function(t,e){var i,n,s,o=!1;if(t)for(i=0,n=t.length;n>i;i++){s=t[i],this.nodes[s].unselect();for(var r=0;this.selection.length>r;)this.selection[r]==s?(this.selection.splice(r,1),o=!0):r++}else if(this.selection&&this.selection.length){for(i=0,n=this.selection.length;n>i;i++)s=this.selection[i],this.nodes[s].unselect(),o=!0;this.selection=[]}return!o||1!=e&&void 0!=e||this._trigger("select"),o},S.prototype._selectNodes=function(t,e){var i,n,s=!1,o=!0;if(t.length!=this.selection.length)o=!1;else for(i=0,n=Math.min(t.length,this.selection.length);n>i;i++)if(t[i]!=this.selection[i]){o=!1;break}if(o)return s;if(void 0==e||0==e){var r=!1;s=this._unselectNodes(void 0,r)}for(i=0,n=t.length;n>i;i++){var a=t[i],h=-1!=this.selection.indexOf(a);h||(this.nodes[a].select(),this.selection.push(a),s=!0)}return s&&this._trigger("select"),s},S.prototype._getNodesOverlappingWith=function(t){var e=this.nodes,i=[];for(var n in e)e.hasOwnProperty(n)&&e[n].isOverlappingWith(t)&&i.push(n);return i},S.prototype.getSelection=function(){return this.selection.concat([])},S.prototype.setSelection=function(t){var e,i,n;if(!t||void 0==t.length)throw"Selection must be an array with ids";for(e=0,i=this.selection.length;i>e;e++)n=this.selection[e],this.nodes[n].unselect();for(this.selection=[],e=0,i=t.length;i>e;e++){n=t[e];var s=this.nodes[n];if(!s)throw new RangeError('Node with id "'+n+'" not found');s.select(),this.selection.push(n)}this.redraw()},S.prototype._updateSelection=function(){for(var t=0;this.selection.length>t;){var e=this.selection[t];this.nodes[e]?t++:this.selection.splice(t,1)}},S.prototype._getConnectionCount=function(t){function e(t){for(var e=[],i=0,n=t.length;n>i;i++)for(var s=t[i],o=s.edges,r=0,a=o.length;a>r;r++){var h=o[r],d=null;h.from==s?d=h.to:h.to==s&&(d=h.from);var l,p;if(d)for(l=0,p=t.length;p>l;l++)if(t[l]==d){d=null;break}if(d)for(l=0,p=e.length;p>l;l++)if(e[l]==d){d=null;break}d&&e.push(d)}return e}void 0==t&&(t=1);var i=[],n=this.nodes;for(var s in n)if(n.hasOwnProperty(s)){for(var o=[n[s]],r=0;t>r;r++)o=o.concat(e(o));i.push(o)}for(var a=[],h=0,d=i.length;d>h;h++)a.push(i[h].length);return a},S.prototype.setSize=function(t,e){this.frame.style.width=t,this.frame.style.height=e,this.frame.canvas.style.width="100%",this.frame.canvas.style.height="100%",this.frame.canvas.width=this.frame.canvas.clientWidth,this.frame.canvas.height=this.frame.canvas.clientHeight},S.prototype._setNodes=function(t){var e=this.nodesData;if(t instanceof o||t instanceof r)this.nodesData=t;else if(t instanceof Array)this.nodesData=new o,this.nodesData.add(t);else{if(t)throw new TypeError("Array or DataSet expected");this.nodesData=new o}if(e&&O.forEach(this.nodesListeners,function(t,i){e.unsubscribe(i,t)}),this.nodes={},this.nodesData){var i=this;O.forEach(this.nodesListeners,function(t,e){i.nodesData.subscribe(e,t)});var n=this.nodesData.getIds();this._addNodes(n)}this._updateSelection()},S.prototype._addNodes=function(t){for(var e,i=0,n=t.length;n>i;i++){e=t[i];var s=this.nodesData.get(e),o=new E(s,this.images,this.groups,this.constants);if(this.nodes[e]=o,!o.isFixed()){var r=2*this.constants.edges.length,a=t.length,h=2*Math.PI*(i/a);o.x=r*Math.cos(h),o.y=r*Math.sin(h),this.moving=!0}}this._reconnectEdges(),this._updateValueRange(this.nodes)},S.prototype._updateNodes=function(t){for(var e=this.nodes,i=this.nodesData,n=0,s=t.length;s>n;n++){var o=t[n],r=e[o],a=i.get(o);r?r.setProperties(a,this.constants):(r=new E(properties,this.images,this.groups,this.constants),e[o]=r,r.isFixed()||(this.moving=!0))}this._reconnectEdges(),this._updateValueRange(e)},S.prototype._removeNodes=function(t){for(var e=this.nodes,i=0,n=t.length;n>i;i++){var s=t[i];delete e[s]}this._reconnectEdges(),this._updateSelection(),this._updateValueRange(e)},S.prototype._setEdges=function(t){var e=this.edgesData;if(t instanceof o||t instanceof r)this.edgesData=t;else if(t instanceof Array)this.edgesData=new o,this.edgesData.add(t);else{if(t)throw new TypeError("Array or DataSet expected");this.edgesData=new o}if(e&&O.forEach(this.edgesListeners,function(t,i){e.unsubscribe(i,t)}),this.edges={},this.edgesData){var i=this;O.forEach(this.edgesListeners,function(t,e){i.edgesData.subscribe(e,t)});var n=this.edgesData.getIds();this._addEdges(n)}this._reconnectEdges()},S.prototype._addEdges=function(t){for(var e=this.edges,i=this.edgesData,n=0,s=t.length;s>n;n++){var o=t[n],r=e[o];r&&r.disconnect();var a=i.get(o);e[o]=new T(a,this,this.constants)}this.moving=!0,this._updateValueRange(e)},S.prototype._updateEdges=function(t){for(var e=this.edges,i=this.edgesData,n=0,s=t.length;s>n;n++){var o=t[n],r=i.get(o),a=e[o];a?(a.disconnect(),a.setProperties(r,this.constants),a.connect()):(a=new T(r,this,this.constants),this.edges[o]=a)}this.moving=!0,this._updateValueRange(e)},S.prototype._removeEdges=function(t){for(var e=this.edges,i=0,n=t.length;n>i;i++){var s=t[i],o=e[s];o&&(o.disconnect(),delete e[s])}this.moving=!0,this._updateValueRange(e)},S.prototype._reconnectEdges=function(){var t,e=this.nodes,i=this.edges;for(t in e)e.hasOwnProperty(t)&&(e[t].edges=[]);for(t in i)if(i.hasOwnProperty(t)){var n=i[t];n.from=null,n.to=null,n.connect()}},S.prototype._updateValueRange=function(t){var e,i=void 0,n=void 0;for(e in t)if(t.hasOwnProperty(e)){var s=t[e].getValue();void 0!==s&&(i=void 0===i?s:Math.min(s,i),n=void 0===n?s:Math.max(s,n))}if(void 0!==i&&void 0!==n)for(e in t)t.hasOwnProperty(e)&&t[e].setValueRange(i,n)},S.prototype.redraw=function(){this.setSize(this.width,this.height),this._redraw()},S.prototype._redraw=function(){var t=this.frame.canvas.getContext("2d"),e=this.frame.canvas.width,i=this.frame.canvas.height;t.clearRect(0,0,e,i),t.save(),t.translate(this.translation.x,this.translation.y),t.scale(this.scale,this.scale),this._drawEdges(t),this._drawNodes(t),t.restore()},S.prototype._setTranslation=function(t,e){void 0===this.translation&&(this.translation={x:0,y:0}),void 0!==t&&(this.translation.x=t),void 0!==e&&(this.translation.y=e)},S.prototype._getTranslation=function(){return{x:this.translation.x,y:this.translation.y}},S.prototype._setScale=function(t){this.scale=t},S.prototype._getScale=function(){return this.scale},S.prototype._xToCanvas=function(t){return(t-this.translation.x)/this.scale},S.prototype._canvasToX=function(t){return t*this.scale+this.translation.x},S.prototype._yToCanvas=function(t){return(t-this.translation.y)/this.scale},S.prototype._canvasToY=function(t){return t*this.scale+this.translation.y},S.prototype._drawNodes=function(t){var e=this.nodes,i=[];for(var n in e)e.hasOwnProperty(n)&&(e[n].isSelected()?i.push(n):e[n].draw(t));for(var s=0,o=i.length;o>s;s++)e[i[s]].draw(t)},S.prototype._drawEdges=function(t){var e=this.edges;for(var i in e)if(e.hasOwnProperty(i)){var n=e[i];n.connected&&e[i].draw(t)}},S.prototype._doStabilize=function(){new Date;for(var t=0,e=this.constants.minVelocity,i=!1;!i&&this.constants.maxIterations>t;)this._calculateForces(),this._discreteStepNodes(),i=!this._isMoving(e),t++;new Date},S.prototype._calculateForces=function(){var t,e,i,n,s,o,r,a,h,d,l,p=this.nodes,c=this.edges,u=.01,f=this.frame.canvas.clientWidth/2,m=this.frame.canvas.clientHeight/2;for(t in p)if(p.hasOwnProperty(t)){var g=p[t];e=f-g.x,i=m-g.y,n=Math.atan2(i,e),o=Math.cos(n)*u,r=Math.sin(n)*u,g._setForce(o,r)}var v=this.constants.nodes.distance,y=10;for(var b in p)if(p.hasOwnProperty(b)){var w=p[b];for(var _ in p)if(p.hasOwnProperty(_)){var E=p[_];e=E.x-w.x,i=E.y-w.y,s=Math.sqrt(e*e+i*i),n=Math.atan2(i,e),a=1/(1+Math.exp((s/v-1)*y)),o=Math.cos(n)*a,r=Math.sin(n)*a,w._addForce(-o,-r),E._addForce(o,r)}}for(t in c)if(c.hasOwnProperty(t)){var T=c[t];T.connected&&(e=T.to.x-T.from.x,i=T.to.y-T.from.y,l=T.length,d=Math.sqrt(e*e+i*i),n=Math.atan2(i,e),h=T.stiffness*(l-d),o=Math.cos(n)*h,r=Math.sin(n)*h,T.from._addForce(-o,-r),T.to._addForce(o,r))}},S.prototype._isMoving=function(t){var e=this.nodes;for(var i in e)if(e.hasOwnProperty(i)&&e[i].isMoving(t))return!0;return!1},S.prototype._discreteStepNodes=function(){var t=this.refreshRate/1e3,e=this.nodes;for(var i in e)e.hasOwnProperty(i)&&e[i].discreteStep(t)},S.prototype.start=function(){if(this.moving){this._calculateForces(),this._discreteStepNodes();var t=this.constants.minVelocity;this.moving=this._isMoving(t)}if(this.moving){if(!this.timer){var e=this;this.timer=window.setTimeout(function(){e.timer=void 0,e.start(),e._redraw()},this.refreshRate)}}else this._redraw()},S.prototype.stop=function(){this.timer&&(window.clearInterval(this.timer),this.timer=void 0)};var k={util:O,events:L,Controller:d,DataSet:o,DataView:r,Range:h,Stack:a,TimeStep:TimeStep,EventBus:s,components:{items:{Item:m,ItemBox:g,ItemPoint:v,ItemRange:y},Component:l,Panel:p,RootPanel:c,ItemSet:f,TimeAxis:u},graph:{Node:E,Edge:T,Popup:x,Groups:Groups,Images:Images},Timeline:_,Graph:S};n!==void 0&&(n=k),i!==void 0&&i.exports!==void 0&&(i.exports=k),"function"==typeof t&&t(function(){return k}),"undefined"!=typeof window&&(window.vis=k),O.loadCss("/* vis.js stylesheet */\n.vis.timeline {\n}\n\n\n.vis.timeline.rootpanel {\n position: relative;\n overflow: hidden;\n\n border: 1px solid #bfbfbf;\n -moz-box-sizing: border-box;\n box-sizing: border-box;\n}\n\n.vis.timeline .panel {\n position: absolute;\n overflow: hidden;\n}\n\n\n.vis.timeline .groupset {\n position: absolute;\n padding: 0;\n margin: 0;\n}\n\n.vis.timeline .labels {\n position: absolute;\n top: 0;\n left: 0;\n width: 100%;\n height: 100%;\n\n padding: 0;\n margin: 0;\n\n border-right: 1px solid #bfbfbf;\n box-sizing: border-box;\n -moz-box-sizing: border-box;\n}\n\n.vis.timeline .labels .label {\n position: absolute;\n left: 0;\n top: 0;\n width: 100%;\n border-bottom: 1px solid #bfbfbf;\n color: #4d4d4d;\n}\n\n.vis.timeline .labels .label .inner {\n display: inline-block;\n padding: 5px;\n}\n\n\n.vis.timeline .itemset {\n position: absolute;\n padding: 0;\n margin: 0;\n overflow: hidden;\n}\n\n.vis.timeline .background {\n}\n\n.vis.timeline .foreground {\n}\n\n.vis.timeline .itemset-axis {\n position: absolute;\n}\n\n.vis.timeline .groupset .itemset-axis {\n border-top: 1px solid #bfbfbf;\n}\n\n/* TODO: with orientation=='bottom', this will more or less overlap with timeline axis\n.vis.timeline .groupset .itemset-axis:last-child {\n border-top: none;\n}\n*/\n\n\n.vis.timeline .item {\n position: absolute;\n color: #1A1A1A;\n border-color: #97B0F8;\n background-color: #D5DDF6;\n display: inline-block;\n}\n\n.vis.timeline .item.selected {\n border-color: #FFC200;\n background-color: #FFF785;\n z-index: 999;\n}\n\n.vis.timeline .item.cluster {\n /* TODO: use another color or pattern? */\n background: #97B0F8 url('img/cluster_bg.png');\n color: white;\n}\n.vis.timeline .item.cluster.point {\n border-color: #D5DDF6;\n}\n\n.vis.timeline .item.box {\n text-align: center;\n border-style: solid;\n border-width: 1px;\n border-radius: 5px;\n -moz-border-radius: 5px; /* For Firefox 3.6 and older */\n}\n\n.vis.timeline .item.point {\n background: none;\n}\n\n.vis.timeline .dot {\n border: 5px solid #97B0F8;\n position: absolute;\n border-radius: 5px;\n -moz-border-radius: 5px; /* For Firefox 3.6 and older */\n}\n\n.vis.timeline .item.range {\n overflow: hidden;\n border-style: solid;\n border-width: 1px;\n border-radius: 2px;\n -moz-border-radius: 2px; /* For Firefox 3.6 and older */\n}\n\n.vis.timeline .item.range .drag-left {\n cursor: w-resize;\n z-index: 1000;\n}\n\n.vis.timeline .item.range .drag-right {\n cursor: e-resize;\n z-index: 1000;\n}\n\n.vis.timeline .item.range .content {\n position: relative;\n display: inline-block;\n}\n\n.vis.timeline .item.line {\n position: absolute;\n width: 0;\n border-left-width: 1px;\n border-left-style: solid;\n}\n\n.vis.timeline .item .content {\n margin: 5px;\n white-space: nowrap;\n overflow: hidden;\n}\n\n.vis.timeline .axis {\n position: relative;\n}\n\n.vis.timeline .axis .text {\n position: absolute;\n color: #4d4d4d;\n padding: 3px;\n white-space: nowrap;\n}\n\n.vis.timeline .axis .text.measure {\n position: absolute;\n padding-left: 0;\n padding-right: 0;\n margin-left: 0;\n margin-right: 0;\n visibility: hidden;\n}\n\n.vis.timeline .axis .grid.vertical {\n position: absolute;\n width: 0;\n border-right: 1px solid;\n}\n\n.vis.timeline .axis .grid.horizontal {\n position: absolute;\n left: 0;\n width: 100%;\n height: 0;\n border-bottom: 1px solid;\n}\n\n.vis.timeline .axis .grid.minor {\n border-color: #e5e5e5;\n}\n\n.vis.timeline .axis .grid.major {\n border-color: #bfbfbf;\n}\n\n")},{hammerjs:1,moment:2}]},{},[3])(3)}); \ No newline at end of file From 6ff96bb8a9f108b01da131b1b8c782bc7140735f Mon Sep 17 00:00:00 2001 From: josdejong Date: Tue, 17 Sep 2013 12:37:58 +0200 Subject: [PATCH 05/18] A fix in dragging nodes in the graph around --- HISTORY.md | 3 +- src/graph/Graph.js | 70 ++++++++++++++++++++-------------------------- vis.js | 68 +++++++++++++++++++------------------------- vis.min.js | 2 +- 4 files changed, 62 insertions(+), 81 deletions(-) diff --git a/HISTORY.md b/HISTORY.md index f060ba8c..7f56b3f0 100644 --- a/HISTORY.md +++ b/HISTORY.md @@ -2,8 +2,9 @@ vis.js history http://visjs.org -## (not yet released), version 0.1.1 +## (not yet released), version 0.2.0 +- Implemented full touch support for Graph. - Fixed initial empty range in the Timeline in case of a single item. - Fixed field `className` not working for items. diff --git a/src/graph/Graph.js b/src/graph/Graph.js index 751a8d80..6e24f1b6 100644 --- a/src/graph/Graph.js +++ b/src/graph/Graph.js @@ -366,52 +366,42 @@ Graph.prototype._onTouch = function (event) { Graph.prototype._onDragStart = function () { var drag = this.drag; + drag.selection = []; drag.translation = this._getTranslation(); - - // note: drag.pointer is set in _onTouch to get the initial touch location drag.nodeId = this._getNodeAt(drag.pointer); + // note: drag.pointer is set in _onTouch to get the initial touch location - // select the clicked node if not yet selected var node = this.nodes[drag.nodeId]; - if (node && !node.isSelected()) { - this._selectNodes([drag.nodeId]); - } - - // creat an array with the selected nodes and their original location and status - var me = this; - drag.selection = []; - this.selection.forEach(function (id) { - var node = me.nodes[id]; - if (node) { - var s = { - id: id, - node: node, - - // store original x, y, xFixed and yFixed, make the node temporarily Fixed - x: node.x, - y: node.y, - xFixed: node.xFixed, - yFixed: node.yFixed - }; - - node.xFixed = true; - node.yFixed = true; - - drag.selection.push(s); + if (node) { + // select the clicked node if not yet selected + if (!node.isSelected()) { + this._selectNodes([drag.nodeId]); } - }); - /* TODO: cleanup - if (drag.node) { - this._selectNodes([drag.nodeId]); + // create an array with the selected nodes and their original location and status + var me = this; + this.selection.forEach(function (id) { + var node = me.nodes[id]; + if (node) { + var s = { + id: id, + node: node, + + // store original x, y, xFixed and yFixed, make the node temporarily Fixed + x: node.x, + y: node.y, + xFixed: node.xFixed, + yFixed: node.yFixed + }; + + node.xFixed = true; + node.yFixed = true; + + drag.selection.push(s); + } + }); - // store original xFixed and yFixed, make the node temporarily Fixed - drag.xFixed = drag.node.xFixed; - drag.yFixed = drag.node.yFixed; - drag.node.xFixed = true; - drag.node.yFixed = true; } - */ }; /** @@ -438,11 +428,11 @@ Graph.prototype._onDrag = function (event) { var node = s.node; if (!s.xFixed) { - node.x = me._xToCanvas(me._canvasToX(s.x) + deltaX); + node.x = me._canvasToX(me._xToCanvas(s.x) + deltaX); } if (!s.yFixed) { - node.y = me._yToCanvas(me._canvasToX(s.y) + deltaY); + node.y = me._canvasToY(me._yToCanvas(s.y) + deltaY); } }); diff --git a/vis.js b/vis.js index 48e0fa3a..0983765b 100644 --- a/vis.js +++ b/vis.js @@ -13219,52 +13219,42 @@ Graph.prototype._onTouch = function (event) { Graph.prototype._onDragStart = function () { var drag = this.drag; + drag.selection = []; drag.translation = this._getTranslation(); - - // note: drag.pointer is set in _onTouch to get the initial touch location drag.nodeId = this._getNodeAt(drag.pointer); + // note: drag.pointer is set in _onTouch to get the initial touch location - // select the clicked node if not yet selected var node = this.nodes[drag.nodeId]; - if (node && !node.isSelected()) { - this._selectNodes([drag.nodeId]); - } - - // creat an array with the selected nodes and their original location and status - var me = this; - drag.selection = []; - this.selection.forEach(function (id) { - var node = me.nodes[id]; - if (node) { - var s = { - id: id, - node: node, - - // store original x, y, xFixed and yFixed, make the node temporarily Fixed - x: node.x, - y: node.y, - xFixed: node.xFixed, - yFixed: node.yFixed - }; + if (node) { + // select the clicked node if not yet selected + if (!node.isSelected()) { + this._selectNodes([drag.nodeId]); + } - node.xFixed = true; - node.yFixed = true; + // create an array with the selected nodes and their original location and status + var me = this; + this.selection.forEach(function (id) { + var node = me.nodes[id]; + if (node) { + var s = { + id: id, + node: node, + + // store original x, y, xFixed and yFixed, make the node temporarily Fixed + x: node.x, + y: node.y, + xFixed: node.xFixed, + yFixed: node.yFixed + }; - drag.selection.push(s); - } - }); + node.xFixed = true; + node.yFixed = true; - /* TODO: cleanup - if (drag.node) { - this._selectNodes([drag.nodeId]); + drag.selection.push(s); + } + }); - // store original xFixed and yFixed, make the node temporarily Fixed - drag.xFixed = drag.node.xFixed; - drag.yFixed = drag.node.yFixed; - drag.node.xFixed = true; - drag.node.yFixed = true; } - */ }; /** @@ -13291,11 +13281,11 @@ Graph.prototype._onDrag = function (event) { var node = s.node; if (!s.xFixed) { - node.x = me._xToCanvas(me._canvasToX(s.x) + deltaX); + node.x = me._canvasToX(me._xToCanvas(s.x) + deltaX); } if (!s.yFixed) { - node.y = me._yToCanvas(me._canvasToX(s.y) + deltaY); + node.y = me._canvasToY(me._yToCanvas(s.y) + deltaY); } }); diff --git a/vis.min.js b/vis.min.js index 3f532e20..c0f6489b 100644 --- a/vis.min.js +++ b/vis.min.js @@ -26,4 +26,4 @@ }this.subscribers={},this.internalIds={}}function r(t,e){this.id=O.randomUUID(),this.data=null,this.ids={},this.options=e||{},this.fieldId="id",this.subscribers={};var i=this;this.listener=function(){i._onEvent.apply(i,arguments)},this.setData(t)}function a(t,e){this.parent=t,this.options=e||{},this.defaultOptions={order:function(t,e){if(t instanceof y){if(e instanceof y){var i=t.data.end-t.data.start,n=e.data.end-e.data.start;return i-n||t.data.start-e.data.start}return-1}return e instanceof y?1:t.data.start-e.data.start},margin:{item:10}},this.ordered=[]}function h(t){this.id=O.randomUUID(),this.start=0,this.end=0,this.options={min:null,max:null,zoomMin:null,zoomMax:null},this.listeners=[],this.setOptions(t)}function d(){this.id=O.randomUUID(),this.components={},this.repaintTimer=void 0,this.reflowTimer=void 0}function l(){this.id=null,this.parent=null,this.depends=null,this.controller=null,this.options=null,this.frame=null,this.top=0,this.left=0,this.width=0,this.height=0}function p(t,e,i){this.id=O.randomUUID(),this.parent=t,this.depends=e,this.options=i||{}}function c(t,e){this.id=O.randomUUID(),this.container=t,this.options=e||{},this.defaultOptions={autoResize:!0},this.listeners={}}function u(t,e,i){this.id=O.randomUUID(),this.parent=t,this.depends=e,this.dom={majorLines:[],majorTexts:[],minorLines:[],minorTexts:[],redundant:{majorLines:[],majorTexts:[],minorLines:[],minorTexts:[]}},this.props={range:{start:0,end:0,minimumStep:0},lineTop:0},this.options=i||{},this.defaultOptions={orientation:"bottom",showMinorLabels:!0,showMajorLabels:!0},this.conversion=null,this.range=null}function f(t,e,i){this.id=O.randomUUID(),this.parent=t,this.depends=e,this.options=i||{},this.defaultOptions={type:"box",align:"center",orientation:"bottom",margin:{axis:20,item:10},padding:5},this.dom={};var n=this;this.itemsData=null,this.range=null,this.listeners={add:function(t,e,i){i!=n.id&&n._onAdd(e.items)},update:function(t,e,i){i!=n.id&&n._onUpdate(e.items)},remove:function(t,e,i){i!=n.id&&n._onRemove(e.items)}},this.items={},this.queue={},this.stack=new a(this,Object.create(this.options)),this.conversion=null}function m(t,e,i,n){this.parent=t,this.data=e,this.dom=null,this.options=i||{},this.defaultOptions=n||{},this.selected=!1,this.visible=!1,this.top=0,this.left=0,this.width=0,this.height=0}function g(t,e,i,n){this.props={dot:{left:0,top:0,width:0,height:0},line:{top:0,left:0,width:0,height:0}},m.call(this,t,e,i,n)}function v(t,e,i,n){this.props={dot:{top:0,width:0,height:0},content:{height:0,marginLeft:0}},m.call(this,t,e,i,n)}function y(t,e,i,n){this.props={content:{left:0,width:0}},m.call(this,t,e,i,n)}function b(t,e,i){this.id=O.randomUUID(),this.parent=t,this.groupId=e,this.itemset=null,this.options=i||{},this.options.top=0,this.props={label:{width:0,height:0}},this.top=0,this.left=0,this.width=0,this.height=0}function w(t,e,i){this.id=O.randomUUID(),this.parent=t,this.depends=e,this.options=i||{},this.range=null,this.itemsData=null,this.groupsData=null,this.groups={},this.dom={},this.props={labels:{width:0}},this.queue={};var n=this;this.listeners={add:function(t,e){n._onAdd(e.items)},update:function(t,e){n._onUpdate(e.items)},remove:function(t,e){n._onRemove(e.items)}}}function _(t,e,i){var n=this;if(this.options=O.extend({orientation:"bottom",min:null,max:null,zoomMin:10,zoomMax:31536e10,showMinorLabels:!0,showMajorLabels:!0,autoResize:!1},i),this.controller=new d,!t)throw Error("No container element provided");var s=Object.create(this.options);s.height=function(){return n.options.height?n.options.height:n.timeaxis.height+n.content.height},this.rootPanel=new c(t,s),this.controller.add(this.rootPanel);var o=Object.create(this.options);o.left=function(){return n.labelPanel.width},o.width=function(){return n.rootPanel.width-n.labelPanel.width},o.top=null,o.height=null,this.itemPanel=new p(this.rootPanel,[],o),this.controller.add(this.itemPanel);var r=Object.create(this.options);r.top=null,r.left=null,r.height=null,r.width=function(){return n.content&&"function"==typeof n.content.getLabelsWidth?n.content.getLabelsWidth():0},this.labelPanel=new p(this.rootPanel,[],r),this.controller.add(this.labelPanel);var a=M().hours(0).minutes(0).seconds(0).milliseconds(0);this.range=new h({start:a.clone().add("days",-3).valueOf(),end:a.clone().add("days",4).valueOf()}),this.range.subscribe(this.rootPanel,"move","horizontal"),this.range.subscribe(this.rootPanel,"zoom","horizontal"),this.range.on("rangechange",function(){var t=!0;n.controller.requestReflow(t)}),this.range.on("rangechanged",function(){var t=!0;n.controller.requestReflow(t)});var l=Object.create(s);l.range=this.range,l.left=null,l.top=null,l.width="100%",l.height=null,this.timeaxis=new u(this.itemPanel,[],l),this.timeaxis.setRange(this.range),this.controller.add(this.timeaxis),this.setGroups(null),this.itemsData=null,this.groupsData=null,e&&this.setItems(e)}function E(t,e,i,n){this.selected=!1,this.edges=[],this.group=n.nodes.group,this.fontSize=n.nodes.fontSize,this.fontFace=n.nodes.fontFace,this.fontColor=n.nodes.fontColor,this.color=n.nodes.color,this.id=void 0,this.shape=n.nodes.shape,this.image=n.nodes.image,this.x=0,this.y=0,this.xFixed=!1,this.yFixed=!1,this.radius=n.nodes.radius,this.radiusFixed=!1,this.radiusMin=n.nodes.radiusMin,this.radiusMax=n.nodes.radiusMax,this.imagelist=e,this.grouplist=i,this.setProperties(t,n),this.mass=50,this.fx=0,this.fy=0,this.vx=0,this.vy=0,this.minForce=n.minForce,this.damping=.9}function T(t,e,i){if(!e)throw"No graph provided";this.graph=e,this.widthMin=i.edges.widthMin,this.widthMax=i.edges.widthMax,this.id=void 0,this.fromId=void 0,this.toId=void 0,this.style=i.edges.style,this.title=void 0,this.width=i.edges.width,this.value=void 0,this.length=i.edges.length,this.from=null,this.to=null,this.connected=!1,this.dash=O.extend({},i.edges.dash),this.stiffness=void 0,this.color=i.edges.color,this.widthFixed=!1,this.lengthFixed=!1,this.setProperties(t,i)}function x(t,e,i,n){this.container=t?t:document.body,this.x=0,this.y=0,this.padding=5,void 0!==e&&void 0!==i&&this.setPosition(e,i),void 0!==n&&this.setText(n),this.frame=document.createElement("div");var s=this.frame.style;s.position="absolute",s.visibility="hidden",s.border="1px solid #666",s.color="black",s.padding=this.padding+"px",s.backgroundColor="#FFFFC6",s.borderRadius="3px",s.MozBorderRadius="3px",s.WebkitBorderRadius="3px",s.boxShadow="3px 3px 10px rgba(128, 128, 128, 0.5)",s.whiteSpace="nowrap",this.container.appendChild(this.frame)}function S(t,e,i){this.containerElement=t,this.width="100%",this.height="100%",this.refreshRate=50,this.stabilize=!0,this.selectable=!0,this.constants={nodes:{radiusMin:5,radiusMax:20,radius:5,distance:100,shape:"ellipse",image:void 0,widthMin:16,widthMax:64,fontColor:"black",fontSize:14,fontFace:"arial",color:{border:"#2B7CE9",background:"#97C2FC",highlight:{border:"#2B7CE9",background:"#D2E5FF"}},borderColor:"#2B7CE9",backgroundColor:"#97C2FC",highlightColor:"#D2E5FF",group:void 0},edges:{widthMin:1,widthMax:15,width:1,style:"line",color:"#343434",fontColor:"#343434",fontSize:14,fontFace:"arial",length:100,dash:{length:10,gap:5,altLength:void 0}},minForce:.05,minVelocity:.02,maxIterations:1e3};var n=this;this.nodes={},this.edges={},this.nodesData=null,this.edgesData=null;var s=this;this.nodesListeners={add:function(t,e){s._addNodes(e.items),s.start()},update:function(t,e){s._updateNodes(e.items),s.start()},remove:function(t,e){s._removeNodes(e.items),s.start()}},this.edgesListeners={add:function(t,e){s._addEdges(e.items),s.start()},update:function(t,e){s._updateEdges(e.items),s.start()},remove:function(t,e){s._removeEdges(e.items),s.start()}},this.groups=new Groups,this.images=new Images,this.images.setOnloadCallback(function(){n._redraw()}),this.moving=!1,this.selection=[],this.timer=void 0,this._create(),this.setOptions(i),this.setData(e)}var M="undefined"!=typeof window&&window.moment||e("moment"),D="undefined"!=typeof window&&window.Hammer||e("hammerjs");if(!Array.prototype.indexOf){Array.prototype.indexOf=function(t){for(var e=0;this.length>e;e++)if(this[e]==t)return e;return-1};try{console.log("Warning: Ancient browser detected. Please update your browser")}catch(C){}}Array.prototype.forEach||(Array.prototype.forEach=function(t,e){for(var i=0,n=this.length;n>i;++i)t.call(e||this,this[i],i,this)}),Array.prototype.map||(Array.prototype.map=function(t,e){var i,n,s;if(null==this)throw new TypeError(" this is null or not defined");var o=Object(this),r=o.length>>>0;if("function"!=typeof t)throw new TypeError(t+" is not a function");for(e&&(i=e),n=Array(r),s=0;r>s;){var a,h;s in o&&(a=o[s],h=t.call(i,a,s,o),n[s]=h),s++}return n}),Array.prototype.filter||(Array.prototype.filter=function(t){"use strict";if(null==this)throw new TypeError;var e=Object(this),i=e.length>>>0;if("function"!=typeof t)throw new TypeError;for(var n=[],s=arguments[1],o=0;i>o;o++)if(o in e){var r=e[o];t.call(s,r,o,e)&&n.push(r)}return n}),Object.keys||(Object.keys=function(){var t=Object.prototype.hasOwnProperty,e=!{toString:null}.propertyIsEnumerable("toString"),i=["toString","toLocaleString","valueOf","hasOwnProperty","isPrototypeOf","propertyIsEnumerable","constructor"],n=i.length;return function(s){if("object"!=typeof s&&"function"!=typeof s||null===s)throw new TypeError("Object.keys called on non-object");var o=[];for(var r in s)t.call(s,r)&&o.push(r);if(e)for(var a=0;n>a;a++)t.call(s,i[a])&&o.push(i[a]);return o}}()),Array.isArray||(Array.isArray=function(t){return"[object Array]"===Object.prototype.toString.call(t)}),Function.prototype.bind||(Function.prototype.bind=function(t){if("function"!=typeof this)throw new TypeError("Function.prototype.bind - what is trying to be bound is not callable");var e=Array.prototype.slice.call(arguments,1),i=this,n=function(){},s=function(){return i.apply(this instanceof n&&t?this:t,e.concat(Array.prototype.slice.call(arguments)))};return n.prototype=this.prototype,s.prototype=new n,s}),Object.create||(Object.create=function(t){function e(){}if(arguments.length>1)throw Error("Object.create implementation only accepts the first parameter.");return e.prototype=t,new e}),Function.prototype.bind||(Function.prototype.bind=function(t){if("function"!=typeof this)throw new TypeError("Function.prototype.bind - what is trying to be bound is not callable");var e=Array.prototype.slice.call(arguments,1),i=this,n=function(){},s=function(){return i.apply(this instanceof n&&t?this:t,e.concat(Array.prototype.slice.call(arguments)))};return n.prototype=this.prototype,s.prototype=new n,s});var O={};O.isNumber=function(t){return t instanceof Number||"number"==typeof t},O.isString=function(t){return t instanceof String||"string"==typeof t},O.isDate=function(t){if(t instanceof Date)return!0;if(O.isString(t)){var e=N.exec(t);if(e)return!0;if(!isNaN(Date.parse(t)))return!0}return!1},O.isDataTable=function(t){return"undefined"!=typeof google&&google.visualization&&google.visualization.DataTable&&t instanceof google.visualization.DataTable},O.randomUUID=function(){var t=function(){return Math.floor(65536*Math.random()).toString(16)};return t()+t()+"-"+t()+"-"+t()+"-"+t()+"-"+t()+t()+t()},O.extend=function(t){for(var e=1,i=arguments.length;i>e;e++){var n=arguments[e];for(var s in n)n.hasOwnProperty(s)&&void 0!==n[s]&&(t[s]=n[s])}return t},O.convert=function(t,e){var i;if(void 0===t)return void 0;if(null===t)return null;if(!e)return t;if("string"!=typeof e&&!(e instanceof String))throw Error("Type must be a string");switch(e){case"boolean":case"Boolean":return Boolean(t);case"number":case"Number":return Number(t.valueOf());case"string":case"String":return t+"";case"Date":if(O.isNumber(t))return new Date(t);if(t instanceof Date)return new Date(t.valueOf());if(M.isMoment(t))return new Date(t.valueOf());if(O.isString(t))return i=N.exec(t),i?new Date(Number(i[1])):M(t).toDate();throw Error("Cannot convert object of type "+O.getType(t)+" to type Date");case"Moment":if(O.isNumber(t))return M(t);if(t instanceof Date)return M(t.valueOf());if(M.isMoment(t))return M.clone();if(O.isString(t))return i=N.exec(t),i?M(Number(i[1])):M(t);throw Error("Cannot convert object of type "+O.getType(t)+" to type Date");case"ISODate":if(O.isNumber(t))return new Date(t);if(t instanceof Date)return t.toISOString();if(M.isMoment(t))return t.toDate().toISOString();if(O.isString(t))return i=N.exec(t),i?new Date(Number(i[1])).toISOString():new Date(t).toISOString();throw Error("Cannot convert object of type "+O.getType(t)+" to type ISODate");case"ASPDate":if(O.isNumber(t))return"/Date("+t+")/";if(t instanceof Date)return"/Date("+t.valueOf()+")/";if(O.isString(t)){i=N.exec(t);var n;return n=i?new Date(Number(i[1])).valueOf():new Date(t).valueOf(),"/Date("+n+")/"}throw Error("Cannot convert object of type "+O.getType(t)+" to type ASPDate");default:throw Error("Cannot convert object of type "+O.getType(t)+' to type "'+e+'"')}};var N=/^\/?Date\((\-?\d+)/i;O.getType=function(t){var e=typeof t;return"object"==e?null==t?"null":t instanceof Boolean?"Boolean":t instanceof Number?"Number":t instanceof String?"String":t instanceof Array?"Array":t instanceof Date?"Date":"Object":"number"==e?"Number":"boolean"==e?"Boolean":"string"==e?"String":e},O.getAbsoluteLeft=function(t){for(var e=document.documentElement,i=document.body,n=t.offsetLeft,s=t.offsetParent;null!=s&&s!=i&&s!=e;)n+=s.offsetLeft,n-=s.scrollLeft,s=s.offsetParent;return n},O.getAbsoluteTop=function(t){for(var e=document.documentElement,i=document.body,n=t.offsetTop,s=t.offsetParent;null!=s&&s!=i&&s!=e;)n+=s.offsetTop,n-=s.scrollTop,s=s.offsetParent;return n},O.getPageY=function(t){if("pageY"in t)return t.pageY;var e;e="targetTouches"in t&&t.targetTouches.length?t.targetTouches[0].clientY:t.clientY;var i=document.documentElement,n=document.body;return e+(i&&i.scrollTop||n&&n.scrollTop||0)-(i&&i.clientTop||n&&n.clientTop||0)},O.getPageX=function(t){if("pageY"in t)return t.pageX;var e;e="targetTouches"in t&&t.targetTouches.length?t.targetTouches[0].clientX:t.clientX;var i=document.documentElement,n=document.body;return e+(i&&i.scrollLeft||n&&n.scrollLeft||0)-(i&&i.clientLeft||n&&n.clientLeft||0)},O.addClassName=function(t,e){var i=t.className.split(" ");-1==i.indexOf(e)&&(i.push(e),t.className=i.join(" "))},O.removeClassName=function(t,e){var i=t.className.split(" "),n=i.indexOf(e);-1!=n&&(i.splice(n,1),t.className=i.join(" "))},O.forEach=function(t,e){var i,n;if(t instanceof Array)for(i=0,n=t.length;n>i;i++)e(t[i],i,t);else for(i in t)t.hasOwnProperty(i)&&e(t[i],i,t)},O.updateProperty=function(t,e,i){return t[e]!==i?(t[e]=i,!0):!1},O.addEventListener=function(t,e,i,n){t.addEventListener?(void 0===n&&(n=!1),"mousewheel"===e&&navigator.userAgent.indexOf("Firefox")>=0&&(e="DOMMouseScroll"),t.addEventListener(e,i,n)):t.attachEvent("on"+e,i)},O.removeEventListener=function(t,e,i,n){t.removeEventListener?(void 0===n&&(n=!1),"mousewheel"===e&&navigator.userAgent.indexOf("Firefox")>=0&&(e="DOMMouseScroll"),t.removeEventListener(e,i,n)):t.detachEvent("on"+e,i)},O.getTarget=function(t){t||(t=window.event);var e;return t.target?e=t.target:t.srcElement&&(e=t.srcElement),void 0!=e.nodeType&&3==e.nodeType&&(e=e.parentNode),e},O.stopPropagation=function(t){t||(t=window.event),t.stopPropagation?t.stopPropagation():t.cancelBubble=!0},O.preventDefault=function(t){t||(t=window.event),t.preventDefault?t.preventDefault():t.returnValue=!1},O.option={},O.option.asBoolean=function(t,e){return"function"==typeof t&&(t=t()),null!=t?0!=t:e||null},O.option.asNumber=function(t,e){return"function"==typeof t&&(t=t()),null!=t?Number(t)||e||null:e||null},O.option.asString=function(t,e){return"function"==typeof t&&(t=t()),null!=t?t+"":e||null},O.option.asSize=function(t,e){return"function"==typeof t&&(t=t()),O.isString(t)?t:O.isNumber(t)?t+"px":e||null},O.option.asElement=function(t,e){return"function"==typeof t&&(t=t()),t||e||null},O.loadCss=function(t){if("undefined"!=typeof document){var e=document.createElement("style");e.type="text/css",e.styleSheet?e.styleSheet.cssText=t:e.appendChild(document.createTextNode(t)),document.getElementsByTagName("head")[0].appendChild(e)}};var L={listeners:[],indexOf:function(t){for(var e=this.listeners,i=0,n=this.listeners.length;n>i;i++){var s=e[i];if(s&&s.object==t)return i}return-1},addListener:function(t,e,i){var n=this.indexOf(t),s=this.listeners[n];s||(s={object:t,events:{}},this.listeners.push(s));var o=s.events[e];o||(o=[],s.events[e]=o),-1==o.indexOf(i)&&o.push(i)},removeListener:function(t,e,i){var n=this.indexOf(t),s=this.listeners[n];if(s){var o=s.events[e];o&&(n=o.indexOf(i),-1!=n&&o.splice(n,1),0==o.length&&delete s.events[e]);var r=0,a=s.events;for(var h in a)a.hasOwnProperty(h)&&r++;0==r&&delete this.listeners[n]}},removeAllListeners:function(){this.listeners=[]},trigger:function(t,e,i){var n=this.indexOf(t),s=this.listeners[n];if(s){var o=s.events[e];if(o)for(var r=0,a=o.length;a>r;r++)o[r](i)}}};s.prototype.on=function(t,e,i){var n=t instanceof RegExp?t:RegExp(t.replace("*","\\w+")),s={id:O.randomUUID(),event:t,regexp:n,callback:"function"==typeof e?e:null,target:i};return this.subscriptions.push(s),s.id},s.prototype.off=function(t){for(var e=0;this.subscriptions.length>e;){var i=this.subscriptions[e],n=!0;if(t instanceof Object)for(var s in t)t.hasOwnProperty(s)&&t[s]!==i[s]&&(n=!1);else n=i.id==t;n?this.subscriptions.splice(e,1):e++}},s.prototype.emit=function(t,e,i){for(var n=0;this.subscriptions.length>n;n++){var s=this.subscriptions[n];s.regexp.test(t)&&s.callback&&s.callback(t,e,i)}},o.prototype.subscribe=function(t,e){var i=this.subscribers[t];i||(i=[],this.subscribers[t]=i),i.push({callback:e})},o.prototype.unsubscribe=function(t,e){var i=this.subscribers[t];i&&(this.subscribers[t]=i.filter(function(t){return t.callback!=e}))},o.prototype._trigger=function(t,e,i){if("*"==t)throw Error("Cannot trigger event *");var n=[];t in this.subscribers&&(n=n.concat(this.subscribers[t])),"*"in this.subscribers&&(n=n.concat(this.subscribers["*"]));for(var s=0;n.length>s;s++){var o=n[s];o.callback&&o.callback(t,e,i||null)}},o.prototype.add=function(t,e){var i,n=[],s=this;if(t instanceof Array)for(var o=0,r=t.length;r>o;o++)i=s._addItem(t[o]),n.push(i);else if(O.isDataTable(t))for(var a=this._getColumnNames(t),h=0,d=t.getNumberOfRows();d>h;h++){for(var l={},p=0,c=a.length;c>p;p++){var u=a[p];l[u]=t.getValue(h,p)}i=s._addItem(l),n.push(i)}else{if(!(t instanceof Object))throw Error("Unknown dataType");i=s._addItem(t),n.push(i)}return n.length&&this._trigger("add",{items:n},e),n},o.prototype.update=function(t,e){var i=[],n=[],s=this,o=s.fieldId,r=function(t){var e=t[o];s.data[e]?(e=s._updateItem(t),n.push(e)):(e=s._addItem(t),i.push(e))};if(t instanceof Array)for(var a=0,h=t.length;h>a;a++)r(t[a]);else if(O.isDataTable(t))for(var d=this._getColumnNames(t),l=0,p=t.getNumberOfRows();p>l;l++){for(var c={},u=0,f=d.length;f>u;u++){var m=d[u];c[m]=t.getValue(l,u)}r(c)}else{if(!(t instanceof Object))throw Error("Unknown dataType");r(t)}return i.length&&this._trigger("add",{items:i},e),n.length&&this._trigger("update",{items:n},e),i.concat(n)},o.prototype.get=function(){var t,e,i,n,s=this,o=O.getType(arguments[0]);"String"==o||"Number"==o?(t=arguments[0],i=arguments[1],n=arguments[2]):"Array"==o?(e=arguments[0],i=arguments[1],n=arguments[2]):(i=arguments[0],n=arguments[1]);var r;if(i&&i.type){if(r="DataTable"==i.type?"DataTable":"Array",n&&r!=O.getType(n))throw Error('Type of parameter "data" ('+O.getType(n)+") "+"does not correspond with specified options.type ("+i.type+")");if("DataTable"==r&&!O.isDataTable(n))throw Error('Parameter "data" must be a DataTable when options.type is "DataTable"')}else r=n?"DataTable"==O.getType(n)?"DataTable":"Array":"Array";var a,h,d,l,p=i&&i.convert||this.options.convert,c=i&&i.filter,u=[];if(void 0!=t)a=s._getItem(t,p),c&&!c(a)&&(a=null);else if(void 0!=e)for(d=0,l=e.length;l>d;d++)a=s._getItem(e[d],p),(!c||c(a))&&u.push(a);else for(h in this.data)this.data.hasOwnProperty(h)&&(a=s._getItem(h,p),(!c||c(a))&&u.push(a));if(i&&i.order&&void 0==t&&this._sort(u,i.order),i&&i.fields){var f=i.fields;if(void 0!=t)a=this._filterFields(a,f);else for(d=0,l=u.length;l>d;d++)u[d]=this._filterFields(u[d],f)}if("DataTable"==r){var m=this._getColumnNames(n);if(void 0!=t)s._appendRow(n,m,a);else for(d=0,l=u.length;l>d;d++)s._appendRow(n,m,u[d]);return n}if(void 0!=t)return a;if(n){for(d=0,l=u.length;l>d;d++)n.push(u[d]);return n}return u},o.prototype.getIds=function(t){var e,i,n,s,o,r=this.data,a=t&&t.filter,h=t&&t.order,d=t&&t.convert||this.options.convert,l=[];if(a)if(h){o=[];for(n in r)r.hasOwnProperty(n)&&(s=this._getItem(n,d),a(s)&&o.push(s));for(this._sort(o,h),e=0,i=o.length;i>e;e++)l[e]=o[e][this.fieldId]}else for(n in r)r.hasOwnProperty(n)&&(s=this._getItem(n,d),a(s)&&l.push(s[this.fieldId]));else if(h){o=[];for(n in r)r.hasOwnProperty(n)&&o.push(r[n]);for(this._sort(o,h),e=0,i=o.length;i>e;e++)l[e]=o[e][this.fieldId]}else for(n in r)r.hasOwnProperty(n)&&(s=r[n],l.push(s[this.fieldId]));return l},o.prototype.forEach=function(t,e){var i,n,s=e&&e.filter,o=e&&e.convert||this.options.convert,r=this.data;if(e&&e.order)for(var a=this.get(e),h=0,d=a.length;d>h;h++)i=a[h],n=i[this.fieldId],t(i,n);else for(n in r)r.hasOwnProperty(n)&&(i=this._getItem(n,o),(!s||s(i))&&t(i,n))},o.prototype.map=function(t,e){var i,n=e&&e.filter,s=e&&e.convert||this.options.convert,o=[],r=this.data;for(var a in r)r.hasOwnProperty(a)&&(i=this._getItem(a,s),(!n||n(i))&&o.push(t(i,a)));return e&&e.order&&this._sort(o,e.order),o},o.prototype._filterFields=function(t,e){var i={};for(var n in t)t.hasOwnProperty(n)&&-1!=e.indexOf(n)&&(i[n]=t[n]);return i},o.prototype._sort=function(t,e){if(O.isString(e)){var i=e;t.sort(function(t,e){var n=t[i],s=e[i];return n>s?1:s>n?-1:0})}else{if("function"!=typeof e)throw new TypeError("Order must be a function or a string");t.sort(e)}},o.prototype.remove=function(t,e){var i,n,s,o=[];if(t instanceof Array)for(i=0,n=t.length;n>i;i++)s=this._remove(t[i]),null!=s&&o.push(s);else s=this._remove(t),null!=s&&o.push(s);return o.length&&this._trigger("remove",{items:o},e),o},o.prototype._remove=function(t){if(O.isNumber(t)||O.isString(t)){if(this.data[t])return delete this.data[t],delete this.internalIds[t],t}else if(t instanceof Object){var e=t[this.fieldId];if(e&&this.data[e])return delete this.data[e],delete this.internalIds[e],e}return null},o.prototype.clear=function(t){var e=Object.keys(this.data);return this.data={},this.internalIds={},this._trigger("remove",{items:e},t),e},o.prototype.max=function(t){var e=this.data,i=null,n=null;for(var s in e)if(e.hasOwnProperty(s)){var o=e[s],r=o[t];null!=r&&(!i||r>n)&&(i=o,n=r)}return i},o.prototype.min=function(t){var e=this.data,i=null,n=null;for(var s in e)if(e.hasOwnProperty(s)){var o=e[s],r=o[t];null!=r&&(!i||n>r)&&(i=o,n=r)}return i},o.prototype.distinct=function(t){var e=this.data,i=[],n=this.options.convert[t],s=0;for(var o in e)if(e.hasOwnProperty(o)){for(var r=e[o],a=O.convert(r[t],n),h=!1,d=0;s>d;d++)if(i[d]==a){h=!0;break}h||(i[s]=a,s++)}return i},o.prototype._addItem=function(t){var e=t[this.fieldId];if(void 0!=e){if(this.data[e])throw Error("Cannot add item: item with id "+e+" already exists")}else e=O.randomUUID(),t[this.fieldId]=e,this.internalIds[e]=t;var i={};for(var n in t)if(t.hasOwnProperty(n)){var s=this.convert[n];i[n]=O.convert(t[n],s)}return this.data[e]=i,e},o.prototype._getItem=function(t,e){var i,n,s=this.data[t];if(!s)return null;var o={},r=this.fieldId,a=this.internalIds;if(e)for(i in s)s.hasOwnProperty(i)&&(n=s[i],i==r&&n in a||(o[i]=O.convert(n,e[i])));else for(i in s)s.hasOwnProperty(i)&&(n=s[i],i==r&&n in a||(o[i]=n));return o},o.prototype._updateItem=function(t){var e=t[this.fieldId];if(void 0==e)throw Error("Cannot update item: item has no id (item: "+JSON.stringify(t)+")");var i=this.data[e];if(!i)throw Error("Cannot update item: no item with id "+e+" found");for(var n in t)if(t.hasOwnProperty(n)){var s=this.convert[n];i[n]=O.convert(t[n],s)}return e},o.prototype._getColumnNames=function(t){for(var e=[],i=0,n=t.getNumberOfColumns();n>i;i++)e[i]=t.getColumnId(i)||t.getColumnLabel(i);return e},o.prototype._appendRow=function(t,e,i){for(var n=t.addRow(),s=0,o=e.length;o>s;s++){var r=e[s];t.setValue(n,s,i[r])}},r.prototype.setData=function(t){var e,i,n;if(this.data){this.data.unsubscribe&&this.data.unsubscribe("*",this.listener),e=[];for(var s in this.ids)this.ids.hasOwnProperty(s)&&e.push(s);this.ids={},this._trigger("remove",{items:e})}if(this.data=t,this.data){for(this.fieldId=this.options.fieldId||this.data&&this.data.options&&this.data.options.fieldId||"id",e=this.data.getIds({filter:this.options&&this.options.filter}),i=0,n=e.length;n>i;i++)s=e[i],this.ids[s]=!0;this._trigger("add",{items:e}),this.data.subscribe&&this.data.subscribe("*",this.listener)}},r.prototype.get=function(){var t,e,i,n=this,s=O.getType(arguments[0]);"String"==s||"Number"==s||"Array"==s?(t=arguments[0],e=arguments[1],i=arguments[2]):(e=arguments[0],i=arguments[1]);var o=O.extend({},this.options,e);this.options.filter&&e&&e.filter&&(o.filter=function(t){return n.options.filter(t)&&e.filter(t)});var r=[];return void 0!=t&&r.push(t),r.push(o),r.push(i),this.data&&this.data.get.apply(this.data,r)},r.prototype.getIds=function(t){var e;if(this.data){var i,n=this.options.filter;i=t&&t.filter?n?function(e){return n(e)&&t.filter(e)}:t.filter:n,e=this.data.getIds({filter:i,order:t&&t.order})}else e=[];return e},r.prototype._onEvent=function(t,e,i){var n,s,o,r,a=e&&e.items,h=this.data,d=[],l=[],p=[];if(a&&h){switch(t){case"add":for(n=0,s=a.length;s>n;n++)o=a[n],r=this.get(o),r&&(this.ids[o]=!0,d.push(o));break;case"update":for(n=0,s=a.length;s>n;n++)o=a[n],r=this.get(o),r?this.ids[o]?l.push(o):(this.ids[o]=!0,d.push(o)):this.ids[o]&&(delete this.ids[o],p.push(o));break;case"remove":for(n=0,s=a.length;s>n;n++)o=a[n],this.ids[o]&&(delete this.ids[o],p.push(o))}d.length&&this._trigger("add",{items:d},i),l.length&&this._trigger("update",{items:l},i),p.length&&this._trigger("remove",{items:p},i)}},r.prototype.subscribe=o.prototype.subscribe,r.prototype.unsubscribe=o.prototype.unsubscribe,r.prototype._trigger=o.prototype._trigger,TimeStep=function(t,e,i){this.current=new Date,this._start=new Date,this._end=new Date,this.autoScale=!0,this.scale=TimeStep.SCALE.DAY,this.step=1,this.setRange(t,e,i)},TimeStep.SCALE={MILLISECOND:1,SECOND:2,MINUTE:3,HOUR:4,DAY:5,WEEKDAY:6,MONTH:7,YEAR:8},TimeStep.prototype.setRange=function(t,e,i){t instanceof Date&&e instanceof Date&&(this._start=void 0!=t?new Date(t.valueOf()):new Date,this._end=void 0!=e?new Date(e.valueOf()):new Date,this.autoScale&&this.setMinimumStep(i))},TimeStep.prototype.first=function(){this.current=new Date(this._start.valueOf()),this.roundToMinor()},TimeStep.prototype.roundToMinor=function(){switch(this.scale){case TimeStep.SCALE.YEAR:this.current.setFullYear(this.step*Math.floor(this.current.getFullYear()/this.step)),this.current.setMonth(0);case TimeStep.SCALE.MONTH:this.current.setDate(1);case TimeStep.SCALE.DAY:case TimeStep.SCALE.WEEKDAY:this.current.setHours(0);case TimeStep.SCALE.HOUR:this.current.setMinutes(0);case TimeStep.SCALE.MINUTE:this.current.setSeconds(0);case TimeStep.SCALE.SECOND:this.current.setMilliseconds(0)}if(1!=this.step)switch(this.scale){case TimeStep.SCALE.MILLISECOND:this.current.setMilliseconds(this.current.getMilliseconds()-this.current.getMilliseconds()%this.step);break;case TimeStep.SCALE.SECOND:this.current.setSeconds(this.current.getSeconds()-this.current.getSeconds()%this.step);break;case TimeStep.SCALE.MINUTE:this.current.setMinutes(this.current.getMinutes()-this.current.getMinutes()%this.step);break;case TimeStep.SCALE.HOUR:this.current.setHours(this.current.getHours()-this.current.getHours()%this.step);break;case TimeStep.SCALE.WEEKDAY:case TimeStep.SCALE.DAY:this.current.setDate(this.current.getDate()-1-(this.current.getDate()-1)%this.step+1);break;case TimeStep.SCALE.MONTH:this.current.setMonth(this.current.getMonth()-this.current.getMonth()%this.step);break;case TimeStep.SCALE.YEAR:this.current.setFullYear(this.current.getFullYear()-this.current.getFullYear()%this.step);break;default:}},TimeStep.prototype.hasNext=function(){return this.current.valueOf()<=this._end.valueOf()},TimeStep.prototype.next=function(){var t=this.current.valueOf();if(6>this.current.getMonth())switch(this.scale){case TimeStep.SCALE.MILLISECOND:this.current=new Date(this.current.valueOf()+this.step);break;case TimeStep.SCALE.SECOND:this.current=new Date(this.current.valueOf()+1e3*this.step);break;case TimeStep.SCALE.MINUTE:this.current=new Date(this.current.valueOf()+60*1e3*this.step);break;case TimeStep.SCALE.HOUR:this.current=new Date(this.current.valueOf()+60*60*1e3*this.step);var e=this.current.getHours();this.current.setHours(e-e%this.step);break;case TimeStep.SCALE.WEEKDAY:case TimeStep.SCALE.DAY:this.current.setDate(this.current.getDate()+this.step);break;case TimeStep.SCALE.MONTH:this.current.setMonth(this.current.getMonth()+this.step);break;case TimeStep.SCALE.YEAR:this.current.setFullYear(this.current.getFullYear()+this.step);break;default:}else switch(this.scale){case TimeStep.SCALE.MILLISECOND:this.current=new Date(this.current.valueOf()+this.step);break;case TimeStep.SCALE.SECOND:this.current.setSeconds(this.current.getSeconds()+this.step);break;case TimeStep.SCALE.MINUTE:this.current.setMinutes(this.current.getMinutes()+this.step);break;case TimeStep.SCALE.HOUR:this.current.setHours(this.current.getHours()+this.step);break;case TimeStep.SCALE.WEEKDAY:case TimeStep.SCALE.DAY:this.current.setDate(this.current.getDate()+this.step);break;case TimeStep.SCALE.MONTH:this.current.setMonth(this.current.getMonth()+this.step);break;case TimeStep.SCALE.YEAR:this.current.setFullYear(this.current.getFullYear()+this.step);break;default:}if(1!=this.step)switch(this.scale){case TimeStep.SCALE.MILLISECOND:this.current.getMilliseconds()0&&(this.step=e),this.autoScale=!1},TimeStep.prototype.setAutoScale=function(t){this.autoScale=t},TimeStep.prototype.setMinimumStep=function(t){if(void 0!=t){var e=31104e6,i=2592e6,n=864e5,s=36e5,o=6e4,r=1e3,a=1;1e3*e>t&&(this.scale=TimeStep.SCALE.YEAR,this.step=1e3),500*e>t&&(this.scale=TimeStep.SCALE.YEAR,this.step=500),100*e>t&&(this.scale=TimeStep.SCALE.YEAR,this.step=100),50*e>t&&(this.scale=TimeStep.SCALE.YEAR,this.step=50),10*e>t&&(this.scale=TimeStep.SCALE.YEAR,this.step=10),5*e>t&&(this.scale=TimeStep.SCALE.YEAR,this.step=5),e>t&&(this.scale=TimeStep.SCALE.YEAR,this.step=1),3*i>t&&(this.scale=TimeStep.SCALE.MONTH,this.step=3),i>t&&(this.scale=TimeStep.SCALE.MONTH,this.step=1),5*n>t&&(this.scale=TimeStep.SCALE.DAY,this.step=5),2*n>t&&(this.scale=TimeStep.SCALE.DAY,this.step=2),n>t&&(this.scale=TimeStep.SCALE.DAY,this.step=1),n/2>t&&(this.scale=TimeStep.SCALE.WEEKDAY,this.step=1),4*s>t&&(this.scale=TimeStep.SCALE.HOUR,this.step=4),s>t&&(this.scale=TimeStep.SCALE.HOUR,this.step=1),15*o>t&&(this.scale=TimeStep.SCALE.MINUTE,this.step=15),10*o>t&&(this.scale=TimeStep.SCALE.MINUTE,this.step=10),5*o>t&&(this.scale=TimeStep.SCALE.MINUTE,this.step=5),o>t&&(this.scale=TimeStep.SCALE.MINUTE,this.step=1),15*r>t&&(this.scale=TimeStep.SCALE.SECOND,this.step=15),10*r>t&&(this.scale=TimeStep.SCALE.SECOND,this.step=10),5*r>t&&(this.scale=TimeStep.SCALE.SECOND,this.step=5),r>t&&(this.scale=TimeStep.SCALE.SECOND,this.step=1),200*a>t&&(this.scale=TimeStep.SCALE.MILLISECOND,this.step=200),100*a>t&&(this.scale=TimeStep.SCALE.MILLISECOND,this.step=100),50*a>t&&(this.scale=TimeStep.SCALE.MILLISECOND,this.step=50),10*a>t&&(this.scale=TimeStep.SCALE.MILLISECOND,this.step=10),5*a>t&&(this.scale=TimeStep.SCALE.MILLISECOND,this.step=5),a>t&&(this.scale=TimeStep.SCALE.MILLISECOND,this.step=1) }},TimeStep.prototype.snap=function(t){if(this.scale==TimeStep.SCALE.YEAR){var e=t.getFullYear()+Math.round(t.getMonth()/12);t.setFullYear(Math.round(e/this.step)*this.step),t.setMonth(0),t.setDate(0),t.setHours(0),t.setMinutes(0),t.setSeconds(0),t.setMilliseconds(0)}else if(this.scale==TimeStep.SCALE.MONTH)t.getDate()>15?(t.setDate(1),t.setMonth(t.getMonth()+1)):t.setDate(1),t.setHours(0),t.setMinutes(0),t.setSeconds(0),t.setMilliseconds(0);else if(this.scale==TimeStep.SCALE.DAY||this.scale==TimeStep.SCALE.WEEKDAY){switch(this.step){case 5:case 2:t.setHours(24*Math.round(t.getHours()/24));break;default:t.setHours(12*Math.round(t.getHours()/12))}t.setMinutes(0),t.setSeconds(0),t.setMilliseconds(0)}else if(this.scale==TimeStep.SCALE.HOUR){switch(this.step){case 4:t.setMinutes(60*Math.round(t.getMinutes()/60));break;default:t.setMinutes(30*Math.round(t.getMinutes()/30))}t.setSeconds(0),t.setMilliseconds(0)}else if(this.scale==TimeStep.SCALE.MINUTE){switch(this.step){case 15:case 10:t.setMinutes(5*Math.round(t.getMinutes()/5)),t.setSeconds(0);break;case 5:t.setSeconds(60*Math.round(t.getSeconds()/60));break;default:t.setSeconds(30*Math.round(t.getSeconds()/30))}t.setMilliseconds(0)}else if(this.scale==TimeStep.SCALE.SECOND)switch(this.step){case 15:case 10:t.setSeconds(5*Math.round(t.getSeconds()/5)),t.setMilliseconds(0);break;case 5:t.setMilliseconds(1e3*Math.round(t.getMilliseconds()/1e3));break;default:t.setMilliseconds(500*Math.round(t.getMilliseconds()/500))}else if(this.scale==TimeStep.SCALE.MILLISECOND){var i=this.step>5?this.step/2:1;t.setMilliseconds(Math.round(t.getMilliseconds()/i)*i)}},TimeStep.prototype.isMajor=function(){switch(this.scale){case TimeStep.SCALE.MILLISECOND:return 0==this.current.getMilliseconds();case TimeStep.SCALE.SECOND:return 0==this.current.getSeconds();case TimeStep.SCALE.MINUTE:return 0==this.current.getHours()&&0==this.current.getMinutes();case TimeStep.SCALE.HOUR:return 0==this.current.getHours();case TimeStep.SCALE.WEEKDAY:case TimeStep.SCALE.DAY:return 1==this.current.getDate();case TimeStep.SCALE.MONTH:return 0==this.current.getMonth();case TimeStep.SCALE.YEAR:return!1;default:return!1}},TimeStep.prototype.getLabelMinor=function(t){switch(void 0==t&&(t=this.current),this.scale){case TimeStep.SCALE.MILLISECOND:return M(t).format("SSS");case TimeStep.SCALE.SECOND:return M(t).format("s");case TimeStep.SCALE.MINUTE:return M(t).format("HH:mm");case TimeStep.SCALE.HOUR:return M(t).format("HH:mm");case TimeStep.SCALE.WEEKDAY:return M(t).format("ddd D");case TimeStep.SCALE.DAY:return M(t).format("D");case TimeStep.SCALE.MONTH:return M(t).format("MMM");case TimeStep.SCALE.YEAR:return M(t).format("YYYY");default:return""}},TimeStep.prototype.getLabelMajor=function(t){switch(void 0==t&&(t=this.current),this.scale){case TimeStep.SCALE.MILLISECOND:return M(t).format("HH:mm:ss");case TimeStep.SCALE.SECOND:return M(t).format("D MMMM HH:mm");case TimeStep.SCALE.MINUTE:case TimeStep.SCALE.HOUR:return M(t).format("ddd D MMMM");case TimeStep.SCALE.WEEKDAY:case TimeStep.SCALE.DAY:return M(t).format("MMMM YYYY");case TimeStep.SCALE.MONTH:return M(t).format("YYYY");case TimeStep.SCALE.YEAR:return"";default:return""}},a.prototype.setOptions=function(t){O.extend(this.options,t)},a.prototype.update=function(){this._order(),this._stack()},a.prototype._order=function(){var t=this.parent.items;if(!t)throw Error("Cannot stack items: parent does not contain items");var e=[],i=0;O.forEach(t,function(t){t.visible&&(e[i]=t,i++)});var n=this.options.order||this.defaultOptions.order;if("function"!=typeof n)throw Error("Option order must be a function");e.sort(n),this.ordered=e},a.prototype._stack=function(){var t,e,i,n=this.ordered,s=this.options,o=s.orientation||this.defaultOptions.orientation,r="top"==o;for(i=s.margin&&void 0!==s.margin.item?s.margin.item:this.defaultOptions.margin.item,t=0,e=n.length;e>t;t++){var a=n[t],h=null;do h=this.checkOverlap(n,t,0,t-1,i),null!=h&&(a.top=r?h.top+h.height+i:h.top-a.height-i);while(h)}},a.prototype.checkOverlap=function(t,e,i,n,s){for(var o=this.collision,r=t[e],a=n;a>=i;a--){var h=t[a];if(o(r,h,s)&&a!=e)return h}return null},a.prototype.collision=function(t,e,i){return t.left-ie.left&&t.top-ie.top},h.prototype.setOptions=function(t){O.extend(this.options,t),(null!=t.start||null!=t.end)&&this.setRange(t.start,t.end)},h.prototype.subscribe=function(t,e,i){var n,s=this;if("horizontal"!=i&&"vertical"!=i)throw new TypeError('Unknown direction "'+i+'". '+'Choose "horizontal" or "vertical".');if("move"==e)n={component:t,event:e,direction:i,callback:function(t){s._onMouseDown(t,n)},params:{}},t.on("mousedown",n.callback),s.listeners.push(n);else{if("zoom"!=e)throw new TypeError('Unknown event "'+e+'". '+'Choose "move" or "zoom".');n={component:t,event:e,direction:i,callback:function(t){s._onMouseWheel(t,n)},params:{}},t.on("mousewheel",n.callback),s.listeners.push(n)}},h.prototype.on=function(t,e){L.addListener(this,t,e)},h.prototype._trigger=function(t){L.trigger(this,t,{start:this.start,end:this.end})},h.prototype.setRange=function(t,e){var i=this._applyRange(t,e);i&&(this._trigger("rangechange"),this._trigger("rangechanged"))},h.prototype._applyRange=function(t,e){var i,n=null!=t?O.convert(t,"Number"):this.start,s=null!=e?O.convert(e,"Number"):this.end;if(isNaN(n))throw Error('Invalid start "'+t+'"');if(isNaN(s))throw Error('Invalid end "'+e+'"');if(n>s&&(s=n),null!=this.options.min){var o=this.options.min.valueOf();o>n&&(i=o-n,n+=i,s+=i)}if(null!=this.options.max){var r=this.options.max.valueOf();s>r&&(i=s-r,n-=i,s-=i)}if(null!=this.options.zoomMin){var a=this.options.zoomMin.valueOf();0>a&&(a=0),a>s-n&&(this.end-this.start>a?(i=a-(s-n),n-=i/2,s+=i/2):(n=this.start,s=this.end))}if(null!=this.options.zoomMax){var h=this.options.zoomMax.valueOf();0>h&&(h=0),s-n>h&&(h>this.end-this.start?(i=s-n-h,n+=i/2,s-=i/2):(n=this.start,s=this.end))}var d=this.start!=n||this.end!=s;return this.start=n,this.end=s,d},h.prototype.getRange=function(){return{start:this.start,end:this.end}},h.prototype.conversion=function(t){return this.start,this.end,h.conversion(this.start,this.end,t)},h.conversion=function(t,e,i){return 0!=i&&0!=e-t?{offset:t,factor:i/(e-t)}:{offset:0,factor:1}},h.prototype._onMouseDown=function(t,e){t=t||window.event;var i=e.params,n=t.which?1==t.which:1==t.button;if(n){i.mouseX=O.getPageX(t),i.mouseY=O.getPageY(t),i.previousLeft=0,i.previousOffset=0,i.moved=!1,i.start=this.start,i.end=this.end;var s=e.component.frame;s&&(s.style.cursor="move");var o=this;i.onMouseMove||(i.onMouseMove=function(t){o._onMouseMove(t,e)},O.addEventListener(document,"mousemove",i.onMouseMove)),i.onMouseUp||(i.onMouseUp=function(t){o._onMouseUp(t,e)},O.addEventListener(document,"mouseup",i.onMouseUp)),O.preventDefault(t)}},h.prototype._onMouseMove=function(t,e){t=t||window.event;var i=e.params,n=O.getPageX(t),s=O.getPageY(t);void 0==i.mouseX&&(i.mouseX=n),void 0==i.mouseY&&(i.mouseY=s);var o=n-i.mouseX,r=s-i.mouseY,a="horizontal"==e.direction?o:r;Math.abs(a)>=1&&(i.moved=!0);var h=i.end-i.start,d="horizontal"==e.direction?e.component.width:e.component.height,l=-a/d*h;this._applyRange(i.start+l,i.end+l),this._trigger("rangechange"),O.preventDefault(t)},h.prototype._onMouseUp=function(t,e){t=t||window.event;var i=e.params;e.component.frame&&(e.component.frame.style.cursor="auto"),i.onMouseMove&&(O.removeEventListener(document,"mousemove",i.onMouseMove),i.onMouseMove=null),i.onMouseUp&&(O.removeEventListener(document,"mouseup",i.onMouseUp),i.onMouseUp=null),i.moved&&this._trigger("rangechanged")},h.prototype._onMouseWheel=function(t,e){t=t||window.event;var i=0;if(t.wheelDelta?i=t.wheelDelta/120:t.detail&&(i=-t.detail/3),i){var n=this,s=function(){var s=i/5,o=null,r=e.component.frame;if(r){var a,h;if("horizontal"==e.direction){a=e.component.width,h=n.conversion(a);var d=O.getAbsoluteLeft(r),l=O.getPageX(t);o=(l-d)/h.factor+h.offset}else{a=e.component.height,h=n.conversion(a);var p=O.getAbsoluteTop(r),c=O.getPageY(t);o=(p+a-c-p)/h.factor+h.offset}}n.zoom(s,o)};s()}O.preventDefault(t)},h.prototype.zoom=function(t,e){null==e&&(e=(this.start+this.end)/2),t>=1&&(t=.9),-1>=t&&(t=-.9),0>t&&(t/=1+t);var i=this.start-e,n=this.end-e,s=this.start-i*t,o=this.end-n*t;this.setRange(s,o)},h.prototype.move=function(t){var e=this.end-this.start,i=this.start+e*t,n=this.end+e*t;this.start=i,this.end=n},h.prototype.moveTo=function(t){var e=(this.start+this.end)/2,i=e-t,n=this.start-i,s=this.end-i;this.setRange(n,s)},d.prototype.add=function(t){if(void 0==t.id)throw Error("Component has no field id");if(!(t instanceof l||t instanceof d))throw new TypeError("Component must be an instance of prototype Component or Controller");t.controller=this,this.components[t.id]=t},d.prototype.remove=function(t){var e;for(e in this.components)if(this.components.hasOwnProperty(e)&&(e==t||this.components[e]==t))break;e&&delete this.components[e]},d.prototype.requestReflow=function(t){if(t)this.reflow();else if(!this.reflowTimer){var e=this;this.reflowTimer=setTimeout(function(){e.reflowTimer=void 0,e.reflow()},0)}},d.prototype.requestRepaint=function(t){if(t)this.repaint();else if(!this.repaintTimer){var e=this;this.repaintTimer=setTimeout(function(){e.repaintTimer=void 0,e.repaint()},0)}},d.prototype.repaint=function(){function t(n,s){s in i||(n.depends&&n.depends.forEach(function(e){t(e,e.id)}),n.parent&&t(n.parent,n.parent.id),e=n.repaint()||e,i[s]=!0)}var e=!1;this.repaintTimer&&(clearTimeout(this.repaintTimer),this.repaintTimer=void 0);var i={};O.forEach(this.components,t),e&&this.reflow()},d.prototype.reflow=function(){function t(n,s){s in i||(n.depends&&n.depends.forEach(function(e){t(e,e.id)}),n.parent&&t(n.parent,n.parent.id),e=n.reflow()||e,i[s]=!0)}var e=!1;this.reflowTimer&&(clearTimeout(this.reflowTimer),this.reflowTimer=void 0);var i={};O.forEach(this.components,t),e&&this.repaint()},l.prototype.setOptions=function(t){t&&(O.extend(this.options,t),this.controller&&(this.requestRepaint(),this.requestReflow()))},l.prototype.getOption=function(t){var e;return this.options&&(e=this.options[t]),void 0===e&&this.defaultOptions&&(e=this.defaultOptions[t]),e},l.prototype.getContainer=function(){return null},l.prototype.getFrame=function(){return this.frame},l.prototype.repaint=function(){return!1},l.prototype.reflow=function(){return!1},l.prototype.hide=function(){return this.frame&&this.frame.parentNode?(this.frame.parentNode.removeChild(this.frame),!0):!1},l.prototype.show=function(){return this.frame&&this.frame.parentNode?!1:this.repaint()},l.prototype.requestRepaint=function(){if(!this.controller)throw Error("Cannot request a repaint: no controller configured");this.controller.requestRepaint()},l.prototype.requestReflow=function(){if(!this.controller)throw Error("Cannot request a reflow: no controller configured");this.controller.requestReflow()},p.prototype=new l,p.prototype.setOptions=l.prototype.setOptions,p.prototype.getContainer=function(){return this.frame},p.prototype.repaint=function(){var t=0,e=O.updateProperty,i=O.option.asSize,n=this.options,s=this.frame;if(!s){s=document.createElement("div"),s.className="panel";var o=n.className;o&&("function"==typeof o?O.addClassName(s,o()+""):O.addClassName(s,o+"")),this.frame=s,t+=1}if(!s.parentNode){if(!this.parent)throw Error("Cannot repaint panel: no parent attached");var r=this.parent.getContainer();if(!r)throw Error("Cannot repaint panel: parent has no container element");r.appendChild(s),t+=1}return t+=e(s.style,"top",i(n.top,"0px")),t+=e(s.style,"left",i(n.left,"0px")),t+=e(s.style,"width",i(n.width,"100%")),t+=e(s.style,"height",i(n.height,"100%")),t>0},p.prototype.reflow=function(){var t=0,e=O.updateProperty,i=this.frame;return i?(t+=e(this,"top",i.offsetTop),t+=e(this,"left",i.offsetLeft),t+=e(this,"width",i.offsetWidth),t+=e(this,"height",i.offsetHeight)):t+=1,t>0},c.prototype=new p,c.prototype.setOptions=l.prototype.setOptions,c.prototype.repaint=function(){var t=0,e=O.updateProperty,i=O.option.asSize,n=this.options,s=this.frame;if(!s){s=document.createElement("div"),s.className="vis timeline rootpanel";var o=n.className;o&&O.addClassName(s,O.option.asString(o)),this.frame=s,t+=1}if(!s.parentNode){if(!this.container)throw Error("Cannot repaint root panel: no container attached");this.container.appendChild(s),t+=1}return t+=e(s.style,"top",i(n.top,"0px")),t+=e(s.style,"left",i(n.left,"0px")),t+=e(s.style,"width",i(n.width,"100%")),t+=e(s.style,"height",i(n.height,"100%")),this._updateEventEmitters(),this._updateWatch(),t>0},c.prototype.reflow=function(){var t=0,e=O.updateProperty,i=this.frame;return i?(t+=e(this,"top",i.offsetTop),t+=e(this,"left",i.offsetLeft),t+=e(this,"width",i.offsetWidth),t+=e(this,"height",i.offsetHeight)):t+=1,t>0},c.prototype._updateWatch=function(){var t=this.getOption("autoResize");t?this._watch():this._unwatch()},c.prototype._watch=function(){var t=this;this._unwatch();var e=function(){var e=t.getOption("autoResize");return e?(t.frame&&(t.frame.clientWidth!=t.width||t.frame.clientHeight!=t.height)&&t.requestReflow(),void 0):(t._unwatch(),void 0)};O.addEventListener(window,"resize",e),this.watchTimer=setInterval(e,1e3)},c.prototype._unwatch=function(){this.watchTimer&&(clearInterval(this.watchTimer),this.watchTimer=void 0)},c.prototype.on=function(t,e){var i=this.listeners[t];i||(i=[],this.listeners[t]=i),i.push(e),this._updateEventEmitters()},c.prototype._updateEventEmitters=function(){if(this.listeners){var t=this;O.forEach(this.listeners,function(e,i){if(t.emitters||(t.emitters={}),!(i in t.emitters)){var n=t.frame;if(n){var s=function(t){e.forEach(function(e){e(t)})};t.emitters[i]=s,O.addEventListener(n,i,s)}}})}},u.prototype=new l,u.prototype.setOptions=l.prototype.setOptions,u.prototype.setRange=function(t){if(!(t instanceof h||t&&t.start&&t.end))throw new TypeError("Range must be an instance of Range, or an object containing start and end.");this.range=t},u.prototype.toTime=function(t){var e=this.conversion;return new Date(t/e.factor+e.offset)},u.prototype.toScreen=function(t){var e=this.conversion;return(t.valueOf()-e.offset)*e.factor},u.prototype.repaint=function(){var t=0,e=O.updateProperty,i=O.option.asSize,n=this.options,s=this.getOption("orientation"),o=this.props,r=this.step,a=this.frame;if(a||(a=document.createElement("div"),this.frame=a,t+=1),a.className="axis "+s,!a.parentNode){if(!this.parent)throw Error("Cannot repaint time axis: no parent attached");var h=this.parent.getContainer();if(!h)throw Error("Cannot repaint time axis: parent has no container element");h.appendChild(a),t+=1}var d=a.parentNode;if(d){var l=a.nextSibling;d.removeChild(a);var p="bottom"==s&&this.props.parentHeight&&this.height?this.props.parentHeight-this.height+"px":"0px";if(t+=e(a.style,"top",i(n.top,p)),t+=e(a.style,"left",i(n.left,"0px")),t+=e(a.style,"width",i(n.width,"100%")),t+=e(a.style,"height",i(n.height,this.height+"px")),this._repaintMeasureChars(),this.step){this._repaintStart(),r.first();for(var c=void 0,u=0;r.hasNext()&&1e3>u;){u++;var f=r.getCurrent(),m=this.toScreen(f),g=r.isMajor();this.getOption("showMinorLabels")&&this._repaintMinorText(m,r.getLabelMinor()),g&&this.getOption("showMajorLabels")?(m>0&&(void 0==c&&(c=m),this._repaintMajorText(m,r.getLabelMajor())),this._repaintMajorLine(m)):this._repaintMinorLine(m),r.next()}if(this.getOption("showMajorLabels")){var v=this.toTime(0),y=r.getLabelMajor(v),b=y.length*(o.majorCharWidth||10)+10;(void 0==c||c>b)&&this._repaintMajorText(0,y)}this._repaintEnd()}this._repaintLine(),l?d.insertBefore(a,l):d.appendChild(a)}return t>0},u.prototype._repaintStart=function(){var t=this.dom,e=t.redundant;e.majorLines=t.majorLines,e.majorTexts=t.majorTexts,e.minorLines=t.minorLines,e.minorTexts=t.minorTexts,t.majorLines=[],t.majorTexts=[],t.minorLines=[],t.minorTexts=[]},u.prototype._repaintEnd=function(){O.forEach(this.dom.redundant,function(t){for(;t.length;){var e=t.pop();e&&e.parentNode&&e.parentNode.removeChild(e)}})},u.prototype._repaintMinorText=function(t,e){var i=this.dom.redundant.minorTexts.shift();if(!i){var n=document.createTextNode("");i=document.createElement("div"),i.appendChild(n),i.className="text minor",this.frame.appendChild(i)}this.dom.minorTexts.push(i),i.childNodes[0].nodeValue=e,i.style.left=t+"px",i.style.top=this.props.minorLabelTop+"px"},u.prototype._repaintMajorText=function(t,e){var i=this.dom.redundant.majorTexts.shift();if(!i){var n=document.createTextNode(e);i=document.createElement("div"),i.className="text major",i.appendChild(n),this.frame.appendChild(i)}this.dom.majorTexts.push(i),i.childNodes[0].nodeValue=e,i.style.top=this.props.majorLabelTop+"px",i.style.left=t+"px"},u.prototype._repaintMinorLine=function(t){var e=this.dom.redundant.minorLines.shift();e||(e=document.createElement("div"),e.className="grid vertical minor",this.frame.appendChild(e)),this.dom.minorLines.push(e);var i=this.props;e.style.top=i.minorLineTop+"px",e.style.height=i.minorLineHeight+"px",e.style.left=t-i.minorLineWidth/2+"px"},u.prototype._repaintMajorLine=function(t){var e=this.dom.redundant.majorLines.shift();e||(e=document.createElement("DIV"),e.className="grid vertical major",this.frame.appendChild(e)),this.dom.majorLines.push(e);var i=this.props;e.style.top=i.majorLineTop+"px",e.style.left=t-i.majorLineWidth/2+"px",e.style.height=i.majorLineHeight+"px"},u.prototype._repaintLine=function(){var t=this.dom.line,e=this.frame;this.options,this.getOption("showMinorLabels")||this.getOption("showMajorLabels")?(t?(e.removeChild(t),e.appendChild(t)):(t=document.createElement("div"),t.className="grid horizontal major",e.appendChild(t),this.dom.line=t),t.style.top=this.props.lineTop+"px"):t&&axis.parentElement&&(e.removeChild(axis.line),delete this.dom.line)},u.prototype._repaintMeasureChars=function(){var t,e=this.dom;if(!e.measureCharMinor){t=document.createTextNode("0");var i=document.createElement("DIV");i.className="text minor measure",i.appendChild(t),this.frame.appendChild(i),e.measureCharMinor=i}if(!e.measureCharMajor){t=document.createTextNode("0");var n=document.createElement("DIV");n.className="text major measure",n.appendChild(t),this.frame.appendChild(n),e.measureCharMajor=n}},u.prototype.reflow=function(){var t=0,e=O.updateProperty,i=this.frame,n=this.range;if(!n)throw Error("Cannot repaint time axis: no range configured");if(i){t+=e(this,"top",i.offsetTop),t+=e(this,"left",i.offsetLeft);var s=this.props,o=this.getOption("showMinorLabels"),r=this.getOption("showMajorLabels"),a=this.dom.measureCharMinor,h=this.dom.measureCharMajor;a&&(s.minorCharHeight=a.clientHeight,s.minorCharWidth=a.clientWidth),h&&(s.majorCharHeight=h.clientHeight,s.majorCharWidth=h.clientWidth);var d=i.parentNode?i.parentNode.offsetHeight:0;switch(d!=s.parentHeight&&(s.parentHeight=d,t+=1),this.getOption("orientation")){case"bottom":s.minorLabelHeight=o?s.minorCharHeight:0,s.majorLabelHeight=r?s.majorCharHeight:0,s.minorLabelTop=0,s.majorLabelTop=s.minorLabelTop+s.minorLabelHeight,s.minorLineTop=-this.top,s.minorLineHeight=Math.max(this.top+s.majorLabelHeight,0),s.minorLineWidth=1,s.majorLineTop=-this.top,s.majorLineHeight=Math.max(this.top+s.minorLabelHeight+s.majorLabelHeight,0),s.majorLineWidth=1,s.lineTop=0;break;case"top":s.minorLabelHeight=o?s.minorCharHeight:0,s.majorLabelHeight=r?s.majorCharHeight:0,s.majorLabelTop=0,s.minorLabelTop=s.majorLabelTop+s.majorLabelHeight,s.minorLineTop=s.minorLabelTop,s.minorLineHeight=Math.max(d-s.majorLabelHeight-this.top),s.minorLineWidth=1,s.majorLineTop=0,s.majorLineHeight=Math.max(d-this.top),s.majorLineWidth=1,s.lineTop=s.majorLabelHeight+s.minorLabelHeight;break;default:throw Error('Unkown orientation "'+this.getOption("orientation")+'"')}var l=s.minorLabelHeight+s.majorLabelHeight;t+=e(this,"width",i.offsetWidth),t+=e(this,"height",l),this._updateConversion();var p=O.convert(n.start,"Date"),c=O.convert(n.end,"Date"),u=this.toTime(5*(s.minorCharWidth||10))-this.toTime(0);this.step=new TimeStep(p,c,u),t+=e(s.range,"start",p.valueOf()),t+=e(s.range,"end",c.valueOf()),t+=e(s.range,"minimumStep",u.valueOf())}return t>0},u.prototype._updateConversion=function(){var t=this.range;if(!t)throw Error("No range configured");this.conversion=t.conversion?t.conversion(this.width):h.conversion(t.start,t.end,this.width)},f.prototype=new p,f.types={box:g,range:y,point:v},f.prototype.setOptions=l.prototype.setOptions,f.prototype.setRange=function(t){if(!(t instanceof h||t&&t.start&&t.end))throw new TypeError("Range must be an instance of Range, or an object containing start and end.");this.range=t},f.prototype.repaint=function(){var t=0,e=O.updateProperty,i=O.option.asSize,n=this.options,s=this.getOption("orientation"),o=this.defaultOptions,r=this.frame;if(!r){r=document.createElement("div"),r.className="itemset";var a=n.className;a&&O.addClassName(r,O.option.asString(a));var h=document.createElement("div");h.className="background",r.appendChild(h),this.dom.background=h;var d=document.createElement("div");d.className="foreground",r.appendChild(d),this.dom.foreground=d;var l=document.createElement("div");l.className="itemset-axis",this.dom.axis=l,this.frame=r,t+=1}if(!this.parent)throw Error("Cannot repaint itemset: no parent attached");var p=this.parent.getContainer();if(!p)throw Error("Cannot repaint itemset: parent has no container element");r.parentNode||(p.appendChild(r),t+=1),this.dom.axis.parentNode||(p.appendChild(this.dom.axis),t+=1),t+=e(r.style,"left",i(n.left,"0px")),t+=e(r.style,"top",i(n.top,"0px")),t+=e(r.style,"width",i(n.width,"100%")),t+=e(r.style,"height",i(n.height,this.height+"px")),t+=e(this.dom.axis.style,"left",i(n.left,"0px")),t+=e(this.dom.axis.style,"width",i(n.width,"100%")),t+="bottom"==s?e(this.dom.axis.style,"top",this.height+this.top+"px"):e(this.dom.axis.style,"top",this.top+"px"),this._updateConversion();var c=this,u=this.queue,m=this.itemsData,g=this.items,v={};return Object.keys(u).forEach(function(e){var i=u[e],s=g[e];switch(i){case"add":case"update":var r=m&&m.get(e,v);if(r){var a=r.type||r.start&&r.end&&"range"||n.type||"box",h=f.types[a];if(s&&(h&&s instanceof h?(s.data=r,t++):(t+=s.hide(),s=null)),!s){if(!h)throw new TypeError('Unknown item type "'+a+'"');s=new h(c,r,n,o),t++}s.repaint(),g[e]=s}delete u[e];break;case"remove":s&&(t+=s.hide()),delete g[e],delete u[e];break;default:console.log('Error: unknown action "'+i+'"')}}),O.forEach(this.items,function(e){e.visible?(t+=e.show(),e.reposition()):t+=e.hide()}),t>0},f.prototype.getForeground=function(){return this.dom.foreground},f.prototype.getBackground=function(){return this.dom.background},f.prototype.getAxis=function(){return this.dom.axis},f.prototype.reflow=function(){var t=0,e=this.options,i=e.margin&&e.margin.axis||this.defaultOptions.margin.axis,n=e.margin&&e.margin.item||this.defaultOptions.margin.item,s=O.updateProperty,o=O.option.asNumber,r=O.option.asSize,a=this.frame;if(a){this._updateConversion(),O.forEach(this.items,function(e){t+=e.reflow()}),this.stack.update();var h,d=o(e.maxHeight),l=null!=r(e.height);if(l)h=a.offsetHeight;else{var p=this.stack.ordered;if(p.length){var c=p[0].top,u=p[0].top+p[0].height;O.forEach(p,function(t){c=Math.min(c,t.top),u=Math.max(u,t.top+t.height)}),h=u-c+i+n}else h=i+n}null!=d&&(h=Math.min(h,d)),t+=s(this,"height",h),t+=s(this,"top",a.offsetTop),t+=s(this,"left",a.offsetLeft),t+=s(this,"width",a.offsetWidth)}else t+=1;return t>0},f.prototype.hide=function(){var t=!1;return this.frame&&this.frame.parentNode&&(this.frame.parentNode.removeChild(this.frame),t=!0),this.dom.axis&&this.dom.axis.parentNode&&(this.dom.axis.parentNode.removeChild(this.dom.axis),t=!0),t},f.prototype.setItems=function(t){var e,i=this,n=this.itemsData;if(t){if(!(t instanceof o||t instanceof r))throw new TypeError("Data must be an instance of DataSet");this.itemsData=t}else this.itemsData=null;if(n&&(O.forEach(this.listeners,function(t,e){n.unsubscribe(e,t)}),e=n.getIds(),this._onRemove(e)),this.itemsData){var s=this.id;O.forEach(this.listeners,function(t,e){i.itemsData.subscribe(e,t,s)}),e=this.itemsData.getIds(),this._onAdd(e)}},f.prototype.getItems=function(){return this.itemsData},f.prototype._onUpdate=function(t){this._toQueue("update",t)},f.prototype._onAdd=function(t){this._toQueue("add",t)},f.prototype._onRemove=function(t){this._toQueue("remove",t)},f.prototype._toQueue=function(t,e){var i=this.queue;e.forEach(function(e){i[e]=t}),this.controller&&this.requestRepaint()},f.prototype._updateConversion=function(){var t=this.range;if(!t)throw Error("No range configured");this.conversion=t.conversion?t.conversion(this.width):h.conversion(t.start,t.end,this.width)},f.prototype.toTime=function(t){var e=this.conversion;return new Date(t/e.factor+e.offset)},f.prototype.toScreen=function(t){var e=this.conversion;return(t.valueOf()-e.offset)*e.factor},m.prototype.select=function(){this.selected=!0},m.prototype.unselect=function(){this.selected=!1},m.prototype.show=function(){return!1},m.prototype.hide=function(){return!1},m.prototype.repaint=function(){return!1},m.prototype.reflow=function(){return!1},g.prototype=new m(null,null),g.prototype.select=function(){this.selected=!0},g.prototype.unselect=function(){this.selected=!1},g.prototype.repaint=function(){var t=!1,e=this.dom;if(e||(this._create(),e=this.dom,t=!0),e){if(!this.parent)throw Error("Cannot repaint item: no parent attached");var i=this.parent.getForeground();if(!i)throw Error("Cannot repaint time axis: parent has no foreground container element");var n=this.parent.getBackground();if(!n)throw Error("Cannot repaint time axis: parent has no background container element");var s=this.parent.getAxis();if(!n)throw Error("Cannot repaint time axis: parent has no axis container element");if(e.box.parentNode||(i.appendChild(e.box),t=!0),e.line.parentNode||(n.appendChild(e.line),t=!0),e.dot.parentNode||(s.appendChild(e.dot),t=!0),this.data.content!=this.content){if(this.content=this.data.content,this.content instanceof Element)e.content.innerHTML="",e.content.appendChild(this.content);else{if(void 0==this.data.content)throw Error('Property "content" missing in item '+this.data.id);e.content.innerHTML=this.content}t=!0}var o=(this.data.className?" "+this.data.className:"")+(this.selected?" selected":"");this.className!=o&&(this.className=o,e.box.className="item box"+o,e.line.className="item line"+o,e.dot.className="item dot"+o,t=!0)}return t},g.prototype.show=function(){return this.dom&&this.dom.box.parentNode?!1:this.repaint()},g.prototype.hide=function(){var t=!1,e=this.dom;return e&&(e.box.parentNode&&(e.box.parentNode.removeChild(e.box),t=!0),e.line.parentNode&&e.line.parentNode.removeChild(e.line),e.dot.parentNode&&e.dot.parentNode.removeChild(e.dot)),t},g.prototype.reflow=function(){var t,e,i,n,s,o,r,a,h,d,l,p,c=0;if(void 0==this.data.start)throw Error('Property "start" missing in item '+this.data.id);if(l=this.data,p=this.parent&&this.parent.range,l&&p){var u=p.end-p.start;this.visible=l.start>p.start-u&&l.start0},g.prototype._create=function(){var t=this.dom;t||(this.dom=t={},t.box=document.createElement("DIV"),t.content=document.createElement("DIV"),t.content.className="content",t.box.appendChild(t.content),t.line=document.createElement("DIV"),t.line.className="line",t.dot=document.createElement("DIV"),t.dot.className="dot")},g.prototype.reposition=function(){var t=this.dom,e=this.props,i=this.options.orientation||this.defaultOptions.orientation;if(t){var n=t.box,s=t.line,o=t.dot;n.style.left=this.left+"px",n.style.top=this.top+"px",s.style.left=e.line.left+"px","top"==i?(s.style.top="0px",s.style.height=this.top+"px"):(s.style.top=this.top+this.height+"px",s.style.height=Math.max(this.parent.height-this.top-this.height+this.props.dot.height/2,0)+"px"),o.style.left=e.dot.left+"px",o.style.top=e.dot.top+"px"}},v.prototype=new m(null,null),v.prototype.select=function(){this.selected=!0},v.prototype.unselect=function(){this.selected=!1},v.prototype.repaint=function(){var t=!1,e=this.dom;if(e||(this._create(),e=this.dom,t=!0),e){if(!this.parent)throw Error("Cannot repaint item: no parent attached");var i=this.parent.getForeground();if(!i)throw Error("Cannot repaint time axis: parent has no foreground container element");if(e.point.parentNode||(i.appendChild(e.point),i.appendChild(e.point),t=!0),this.data.content!=this.content){if(this.content=this.data.content,this.content instanceof Element)e.content.innerHTML="",e.content.appendChild(this.content);else{if(void 0==this.data.content)throw Error('Property "content" missing in item '+this.data.id);e.content.innerHTML=this.content}t=!0}var n=(this.data.className?" "+this.data.className:"")+(this.selected?" selected":"");this.className!=n&&(this.className=n,e.point.className="item point"+n,t=!0)}return t},v.prototype.show=function(){return this.dom&&this.dom.point.parentNode?!1:this.repaint()},v.prototype.hide=function(){var t=!1,e=this.dom;return e&&e.point.parentNode&&(e.point.parentNode.removeChild(e.point),t=!0),t},v.prototype.reflow=function(){var t,e,i,n,s,o,r,a,h,d,l=0;if(void 0==this.data.start)throw Error('Property "start" missing in item '+this.data.id);if(h=this.data,d=this.parent&&this.parent.range,h&&d){var p=d.end-d.start;this.visible=h.start>d.start-p&&h.start0},v.prototype._create=function(){var t=this.dom;t||(this.dom=t={},t.point=document.createElement("div"),t.content=document.createElement("div"),t.content.className="content",t.point.appendChild(t.content),t.dot=document.createElement("div"),t.dot.className="dot",t.point.appendChild(t.dot))},v.prototype.reposition=function(){var t=this.dom,e=this.props;t&&(t.point.style.top=this.top+"px",t.point.style.left=this.left+"px",t.content.style.marginLeft=e.content.marginLeft+"px",t.dot.style.top=e.dot.top+"px")},y.prototype=new m(null,null),y.prototype.select=function(){this.selected=!0},y.prototype.unselect=function(){this.selected=!1},y.prototype.repaint=function(){var t=!1,e=this.dom;if(e||(this._create(),e=this.dom,t=!0),e){if(!this.parent)throw Error("Cannot repaint item: no parent attached");var i=this.parent.getForeground();if(!i)throw Error("Cannot repaint time axis: parent has no foreground container element");if(e.box.parentNode||(i.appendChild(e.box),t=!0),this.data.content!=this.content){if(this.content=this.data.content,this.content instanceof Element)e.content.innerHTML="",e.content.appendChild(this.content);else{if(void 0==this.data.content)throw Error('Property "content" missing in item '+this.data.id); e.content.innerHTML=this.content}t=!0}var n=this.data.className?" "+this.data.className:"";this.className!=n&&(this.className=n,e.box.className="item range"+n,t=!0)}return t},y.prototype.show=function(){return this.dom&&this.dom.box.parentNode?!1:this.repaint()},y.prototype.hide=function(){var t=!1,e=this.dom;return e&&e.box.parentNode&&(e.box.parentNode.removeChild(e.box),t=!0),t},y.prototype.reflow=function(){var t,e,i,n,s,o,r,a,h,d,l,p,c,u,f,m,g=0;if(void 0==this.data.start)throw Error('Property "start" missing in item '+this.data.id);if(void 0==this.data.end)throw Error('Property "end" missing in item '+this.data.id);return h=this.data,d=this.parent&&this.parent.range,this.visible=h&&d?h.startd.start:!1,this.visible&&(t=this.dom,t?(e=this.props,i=this.options,o=this.parent,r=o.toScreen(this.data.start),a=o.toScreen(this.data.end),l=O.updateProperty,p=t.box,c=o.width,f=i.orientation||this.defaultOptions.orientation,n=i.margin&&i.margin.axis||this.defaultOptions.margin.axis,s=i.padding||this.defaultOptions.padding,g+=l(e.content,"width",t.content.offsetWidth),g+=l(this,"height",p.offsetHeight),-c>r&&(r=-c),a>2*c&&(a=2*c),u=0>r?Math.min(-r,a-r-e.content.width-2*s):0,g+=l(e.content,"left",u),"top"==f?(m=n,g+=l(this,"top",m)):(m=o.height-this.height-n,g+=l(this,"top",m)),g+=l(this,"left",r),g+=l(this,"width",Math.max(a-r,1))):g+=1),g>0},y.prototype._create=function(){var t=this.dom;t||(this.dom=t={},t.box=document.createElement("div"),t.content=document.createElement("div"),t.content.className="content",t.box.appendChild(t.content))},y.prototype.reposition=function(){var t=this.dom,e=this.props;t&&(t.box.style.top=this.top+"px",t.box.style.left=this.left+"px",t.box.style.width=this.width+"px",t.content.style.left=e.content.left+"px")},b.prototype=new l,b.prototype.setOptions=l.prototype.setOptions,b.prototype.getContainer=function(){return this.parent.getContainer()},b.prototype.setItems=function(t){if(this.itemset&&(this.itemset.hide(),this.itemset.setItems(),this.parent.controller.remove(this.itemset),this.itemset=null),t){var e=this.groupId,i=Object.create(this.options);this.itemset=new f(this,null,i),this.itemset.setRange(this.parent.range),this.view=new r(t,{filter:function(t){return t.group==e}}),this.itemset.setItems(this.view),this.parent.controller.add(this.itemset)}},b.prototype.repaint=function(){return!1},b.prototype.reflow=function(){var t=0,e=O.updateProperty;if(t+=e(this,"top",this.itemset?this.itemset.top:0),t+=e(this,"height",this.itemset?this.itemset.height:0),this.label){var i=this.label.firstChild;t+=e(this.props.label,"width",i.clientWidth),t+=e(this.props.label,"height",i.clientHeight)}else t+=e(this.props.label,"width",0),t+=e(this.props.label,"height",0);return t>0},w.prototype=new p,w.prototype.setOptions=l.prototype.setOptions,w.prototype.setRange=function(){},w.prototype.setItems=function(t){this.itemsData=t;for(var e in this.groups)if(this.groups.hasOwnProperty(e)){var i=this.groups[e];i.setItems(t)}},w.prototype.getItems=function(){return this.itemsData},w.prototype.setRange=function(t){this.range=t},w.prototype.setGroups=function(t){var e,i=this;if(this.groupsData&&(O.forEach(this.listeners,function(t,e){i.groupsData.unsubscribe(e,t)}),e=this.groupsData.getIds(),this._onRemove(e)),t?t instanceof o?this.groupsData=t:(this.groupsData=new o({convert:{start:"Date",end:"Date"}}),this.groupsData.add(t)):this.groupsData=null,this.groupsData){var n=this.id;O.forEach(this.listeners,function(t,e){i.groupsData.subscribe(e,t,n)}),e=this.groupsData.getIds(),this._onAdd(e)}},w.prototype.getGroups=function(){return this.groupsData},w.prototype.repaint=function(){var t,e,i,n,s=0,o=O.updateProperty,r=O.option.asSize,a=O.option.asElement,h=this.options,d=this.dom.frame,l=this.dom.labels;if(!this.parent)throw Error("Cannot repaint groupset: no parent attached");var p=this.parent.getContainer();if(!p)throw Error("Cannot repaint groupset: parent has no container element");if(!d){d=document.createElement("div"),d.className="groupset",this.dom.frame=d;var c=h.className;c&&O.addClassName(d,O.option.asString(c)),s+=1}d.parentNode||(p.appendChild(d),s+=1);var u=a(h.labelContainer);if(!u)throw Error('Cannot repaint groupset: option "labelContainer" not defined');l||(l=document.createElement("div"),l.className="labels",this.dom.labels=l),l.parentNode&&l.parentNode==u||(l.parentNode&&l.parentNode.removeChild(l.parentNode),u.appendChild(l)),s+=o(d.style,"height",r(h.height,this.height+"px")),s+=o(d.style,"top",r(h.top,"0px")),s+=o(d.style,"left",r(h.left,"0px")),s+=o(d.style,"width",r(h.width,"100%")),s+=o(l.style,"top",r(h.top,"0px"));var f=this,m=this.queue,g=this.groups,v=this.groupsData,y=Object.keys(m);if(y.length){y.forEach(function(t){var e=m[t],i=g[t];switch(e){case"add":case"update":if(!i){var n=Object.create(f.options);i=new b(f,t,n),i.setItems(f.itemsData),g[t]=i,f.controller.add(i)}i.data=v.get(t),delete m[t];break;case"remove":i&&(i.setItems(),delete g[t],f.controller.remove(i)),delete m[t];break;default:console.log('Error: unknown action "'+e+'"')}});var w=this.groupsData.getIds({order:this.options.groupsOrder});for(t=0;w.length>t;t++)(function(t,e){var i=0;e&&(i=function(){return e.top+e.height}),t.setOptions({top:i})})(g[w[t]],g[w[t-1]]);for(;l.firstChild;)l.removeChild(l.firstChild);for(t=0;w.length>t;t++)e=w[t],n=this._createLabel(e),l.appendChild(n);s++}for(e in g)g.hasOwnProperty(e)&&(i=g[e],n=i.label,n&&(n.style.top=i.top+"px",n.style.height=i.height+"px"));return s>0},w.prototype._createLabel=function(t){var e=this.groups[t],i=document.createElement("div");i.className="label";var n=document.createElement("div");n.className="inner",i.appendChild(n);var s=e.data&&e.data.content;s instanceof Element?n.appendChild(s):void 0!=s&&(n.innerHTML=s);var o=e.data&&e.data.className;return o&&O.addClassName(i,o),e.label=i,i},w.prototype.getContainer=function(){return this.dom.frame},w.prototype.getLabelsWidth=function(){return this.props.labels.width},w.prototype.reflow=function(){var t,e,i=0,n=this.options,s=O.updateProperty,o=O.option.asNumber,r=O.option.asSize,a=this.dom.frame;if(a){var h,d=o(n.maxHeight),l=null!=r(n.height);if(l)h=a.offsetHeight;else{h=0;for(t in this.groups)this.groups.hasOwnProperty(t)&&(e=this.groups[t],h+=e.height)}null!=d&&(h=Math.min(h,d)),i+=s(this,"height",h),i+=s(this,"top",a.offsetTop),i+=s(this,"left",a.offsetLeft),i+=s(this,"width",a.offsetWidth)}var p=0;for(t in this.groups)if(this.groups.hasOwnProperty(t)){e=this.groups[t];var c=e.props&&e.props.label&&e.props.label.width||0;p=Math.max(p,c)}return i+=s(this.props.labels,"width",p),i>0},w.prototype.hide=function(){return this.dom.frame&&this.dom.frame.parentNode?(this.dom.frame.parentNode.removeChild(this.dom.frame),!0):!1},w.prototype.show=function(){return this.dom.frame&&this.dom.frame.parentNode?!1:this.repaint()},w.prototype._onUpdate=function(t){this._toQueue(t,"update")},w.prototype._onAdd=function(t){this._toQueue(t,"add")},w.prototype._onRemove=function(t){this._toQueue(t,"remove")},w.prototype._toQueue=function(t,e){var i=this.queue;t.forEach(function(t){i[t]=e}),this.controller&&this.requestRepaint()},_.prototype.setOptions=function(t){t&&O.extend(this.options,t),this.controller.reflow(),this.controller.repaint()},_.prototype.setItems=function(t){var e,i=null==this.itemsData;if(t?t instanceof o&&(e=t):e=null,t instanceof o||(e=new o({convert:{start:"Date",end:"Date"}}),e.add(t)),this.itemsData=e,this.content.setItems(e),i&&(void 0==this.options.start||void 0==this.options.end)){var n=this.getItemRange(),s=n.min,r=n.max;if(null!=s&&null!=r){var a=r.valueOf()-s.valueOf();0>=a&&(a=864e5),s=new Date(s.valueOf()-.05*a),r=new Date(r.valueOf()+.05*a)}void 0!=this.options.start&&(s=new Date(this.options.start.valueOf())),void 0!=this.options.end&&(r=new Date(this.options.end.valueOf())),(null!=s||null!=r)&&this.range.setRange(s,r)}},_.prototype.setGroups=function(t){var e=this;this.groupsData=t;var i=this.groupsData?w:f;if(!(this.content instanceof i)){this.content&&(this.content.hide(),this.content.setItems&&this.content.setItems(),this.content.setGroups&&this.content.setGroups(),this.controller.remove(this.content));var n=Object.create(this.options);O.extend(n,{top:function(){return"top"==e.options.orientation?e.timeaxis.height:e.itemPanel.height-e.timeaxis.height-e.content.height},left:null,width:"100%",height:function(){return e.options.height?e.itemPanel.height-e.timeaxis.height:null},maxHeight:function(){if(e.options.maxHeight){if(!O.isNumber(e.options.maxHeight))throw new TypeError("Number expected for property maxHeight");return e.options.maxHeight-e.timeaxis.height}return null},labelContainer:function(){return e.labelPanel.getContainer()}}),this.content=new i(this.itemPanel,[this.timeaxis],n),this.content.setRange&&this.content.setRange(this.range),this.content.setItems&&this.content.setItems(this.itemsData),this.content.setGroups&&this.content.setGroups(this.groupsData),this.controller.add(this.content)}},_.prototype.getItemRange=function(){var t=this.itemsData,e=null,i=null;if(t){var n=t.min("start");e=n?n.start.valueOf():null;var s=t.max("start");s&&(i=s.start.valueOf());var o=t.max("end");o&&(i=null==i?o.end.valueOf():Math.max(i,o.end.valueOf()))}return{min:null!=e?new Date(e):null,max:null!=i?new Date(i):null}},function(t){function e(t){return M=t,c()}function i(){D=0,C=M.charAt(0)}function n(){D++,C=M.charAt(D)}function s(){return M.charAt(D+1)}function o(t){return L.test(t)}function r(t,e){if(t||(t={}),e)for(var i in e)e.hasOwnProperty(i)&&(t[i]=e[i]);return t}function a(t,e,i){for(var n=e.split("."),s=t;n.length;){var o=n.shift();n.length?(s[o]||(s[o]={}),s=s[o]):s[o]=i}}function h(t,e){for(var i,n,s=null,o=[t],a=t;a.parent;)o.push(a.parent),a=a.parent;if(a.nodes)for(i=0,n=a.nodes.length;n>i;i++)if(e.id===a.nodes[i].id){s=a.nodes[i];break}for(s||(s={id:e.id},t.node&&(s.attr=r(s.attr,t.node))),i=o.length-1;i>=0;i--){var h=o[i];h.nodes||(h.nodes=[]),-1==h.nodes.indexOf(s)&&h.nodes.push(s)}e.attr&&(s.attr=r(s.attr,e.attr))}function d(t,e){if(t.edges||(t.edges=[]),t.edges.push(e),t.edge){var i=r({},t.edge);e.attr=r(i,e.attr)}}function l(t,e,i,n,s){var o={from:e,to:i,type:n};return t.edge&&(o.attr=r({},t.edge)),o.attr=r(o.attr||{},s),o}function p(){for(N=x.NULL,O="";" "==C||" "==C||"\n"==C||"\r"==C;)n();do{var t=!1;if("#"==C){for(var e=D-1;" "==M.charAt(e)||" "==M.charAt(e);)e--;if("\n"==M.charAt(e)||""==M.charAt(e)){for(;""!=C&&"\n"!=C;)n();t=!0}}if("/"==C&&"/"==s()){for(;""!=C&&"\n"!=C;)n();t=!0}if("/"==C&&"*"==s()){for(;""!=C;){if("*"==C&&"/"==s()){n(),n();break}n()}t=!0}for(;" "==C||" "==C||"\n"==C||"\r"==C;)n()}while(t);if(""==C)return N=x.DELIMITER,void 0;var i=C+s();if(S[i])return N=x.DELIMITER,O=i,n(),n(),void 0;if(S[C])return N=x.DELIMITER,O=C,n(),void 0;if(o(C)||"-"==C){for(O+=C,n();o(C);)O+=C,n();return"false"==O?O=!1:"true"==O?O=!0:isNaN(Number(O))||(O=Number(O)),N=x.IDENTIFIER,void 0}if('"'==C){for(n();""!=C&&('"'!=C||'"'==C&&'"'==s());)O+=C,'"'==C&&n(),n();if('"'!=C)throw w('End of string " expected');return n(),N=x.IDENTIFIER,void 0}for(N=x.UNKNOWN;""!=C;)O+=C,n();throw new SyntaxError('Syntax error in part "'+_(O,30)+'"')}function c(){var t={};if(i(),p(),"strict"==O&&(t.strict=!0,p()),("graph"==O||"digraph"==O)&&(t.type=O,p()),N==x.IDENTIFIER&&(t.id=O,p()),"{"!=O)throw w("Angle bracket { expected");if(p(),u(t),"}"!=O)throw w("Angle bracket } expected");if(p(),""!==O)throw w("End of file expected");return p(),delete t.node,delete t.edge,delete t.graph,t}function u(t){for(;""!==O&&"}"!=O;)f(t),";"==O&&p()}function f(t){var e=m(t);if(e)return y(t,e),void 0;var i=g(t);if(!i){if(N!=x.IDENTIFIER)throw w("Identifier expected");var n=O;if(p(),"="==O){if(p(),N!=x.IDENTIFIER)throw w("Identifier expected");t[n]=O,p()}else v(t,n)}}function m(t){var e=null;if("subgraph"==O&&(e={},e.type="subgraph",p(),N==x.IDENTIFIER&&(e.id=O,p())),"{"==O){if(p(),e||(e={}),e.parent=t,e.node=t.node,e.edge=t.edge,e.graph=t.graph,u(e),"}"!=O)throw w("Angle bracket } expected");p(),delete e.node,delete e.edge,delete e.graph,delete e.parent,t.subgraphs||(t.subgraphs=[]),t.subgraphs.push(e)}return e}function g(t){return"node"==O?(p(),t.node=b(),"node"):"edge"==O?(p(),t.edge=b(),"edge"):"graph"==O?(p(),t.graph=b(),"graph"):null}function v(t,e){var i={id:e},n=b();n&&(i.attr=n),h(t,i),y(t,e)}function y(t,e){for(;"->"==O||"--"==O;){var i,n=O;p();var s=m(t);if(s)i=s;else{if(N!=x.IDENTIFIER)throw w("Identifier or subgraph expected");i=O,h(t,{id:i}),p()}var o=b(),r=l(t,e,i,n,o);d(t,r),e=i}}function b(){for(var t=null;"["==O;){for(p(),t={};""!==O&&"]"!=O;){if(N!=x.IDENTIFIER)throw w("Attribute name expected");var e=O;if(p(),"="!=O)throw w("Equal sign = expected");if(p(),N!=x.IDENTIFIER)throw w("Attribute value expected");var i=O;a(t,e,i),p(),","==O&&p()}if("]"!=O)throw w("Bracket ] expected");p()}return t}function w(t){return new SyntaxError(t+', got "'+_(O,30)+'" (char '+D+")")}function _(t,e){return e>=t.length?t:t.substr(0,27)+"..."}function E(t,e,i){t instanceof Array?t.forEach(function(t){e instanceof Array?e.forEach(function(e){i(t,e)}):i(t,e)}):e instanceof Array?e.forEach(function(e){i(t,e)}):i(t,e)}function T(t){function i(t){var e={from:t.from,to:t.to};return r(e,t.attr),e.style="->"==t.type?"arrow":"line",e}var n=e(t),s={nodes:[],edges:[],options:{}};return n.nodes&&n.nodes.forEach(function(t){var e={id:t.id,label:(t.label||t.id)+""};r(e,t.attr),e.image&&(e.shape="image"),s.nodes.push(e)}),n.edges&&n.edges.forEach(function(t){var e,n;e=t.from instanceof Object?t.from.nodes:{id:t.from},n=t.to instanceof Object?t.to.nodes:{id:t.to},t.from instanceof Object&&t.from.edges&&t.from.edges.forEach(function(t){var e=i(t);s.edges.push(e)}),E(e,n,function(e,n){var o=l(s,e.id,n.id,t.type,t.attr),r=i(o);s.edges.push(r)}),t.to instanceof Object&&t.to.edges&&t.to.edges.forEach(function(t){var e=i(t);s.edges.push(e)})}),n.attr&&(s.options=n.attr),s}var x={NULL:0,DELIMITER:1,IDENTIFIER:2,UNKNOWN:3},S={"{":!0,"}":!0,"[":!0,"]":!0,";":!0,"=":!0,",":!0,"->":!0,"--":!0},M="",D=0,C="",O="",N=x.NULL,L=/[a-zA-Z_0-9.:#]/;t.parseDOT=e,t.DOTToGraph=T}(O!==void 0?O:n),"undefined"!=typeof CanvasRenderingContext2D&&(CanvasRenderingContext2D.prototype.circle=function(t,e,i){this.beginPath(),this.arc(t,e,i,0,2*Math.PI,!1)},CanvasRenderingContext2D.prototype.square=function(t,e,i){this.beginPath(),this.rect(t-i,e-i,2*i,2*i)},CanvasRenderingContext2D.prototype.triangle=function(t,e,i){this.beginPath();var n=2*i,s=n/2,o=Math.sqrt(3)/6*n,r=Math.sqrt(n*n-s*s);this.moveTo(t,e-(r-o)),this.lineTo(t+s,e+o),this.lineTo(t-s,e+o),this.lineTo(t,e-(r-o)),this.closePath()},CanvasRenderingContext2D.prototype.triangleDown=function(t,e,i){this.beginPath();var n=2*i,s=n/2,o=Math.sqrt(3)/6*n,r=Math.sqrt(n*n-s*s);this.moveTo(t,e+(r-o)),this.lineTo(t+s,e-o),this.lineTo(t-s,e-o),this.lineTo(t,e+(r-o)),this.closePath()},CanvasRenderingContext2D.prototype.star=function(t,e,i){this.beginPath();for(var n=0;10>n;n++){var s=0===n%2?1.3*i:.5*i;this.lineTo(t+s*Math.sin(2*n*Math.PI/10),e-s*Math.cos(2*n*Math.PI/10))}this.closePath()},CanvasRenderingContext2D.prototype.roundRect=function(t,e,i,n,s){var o=Math.PI/180;0>i-2*s&&(s=i/2),0>n-2*s&&(s=n/2),this.beginPath(),this.moveTo(t+s,e),this.lineTo(t+i-s,e),this.arc(t+i-s,e+s,s,270*o,360*o,!1),this.lineTo(t+i,e+n-s),this.arc(t+i-s,e+n-s,s,0,90*o,!1),this.lineTo(t+s,e+n),this.arc(t+s,e+n-s,s,90*o,180*o,!1),this.lineTo(t,e+s),this.arc(t+s,e+s,s,180*o,270*o,!1)},CanvasRenderingContext2D.prototype.ellipse=function(t,e,i,n){var s=.5522848,o=i/2*s,r=n/2*s,a=t+i,h=e+n,d=t+i/2,l=e+n/2;this.beginPath(),this.moveTo(t,l),this.bezierCurveTo(t,l-r,d-o,e,d,e),this.bezierCurveTo(d+o,e,a,l-r,a,l),this.bezierCurveTo(a,l+r,d+o,h,d,h),this.bezierCurveTo(d-o,h,t,l+r,t,l)},CanvasRenderingContext2D.prototype.database=function(t,e,i,n){var s=1/3,o=i,r=n*s,a=.5522848,h=o/2*a,d=r/2*a,l=t+o,p=e+r,c=t+o/2,u=e+r/2,f=e+(n-r/2),m=e+n;this.beginPath(),this.moveTo(l,u),this.bezierCurveTo(l,u+d,c+h,p,c,p),this.bezierCurveTo(c-h,p,t,u+d,t,u),this.bezierCurveTo(t,u-d,c-h,e,c,e),this.bezierCurveTo(c+h,e,l,u-d,l,u),this.lineTo(l,f),this.bezierCurveTo(l,f+d,c+h,m,c,m),this.bezierCurveTo(c-h,m,t,f+d,t,f),this.lineTo(t,u)},CanvasRenderingContext2D.prototype.arrow=function(t,e,i,n){var s=t-n*Math.cos(i),o=e-n*Math.sin(i),r=t-.9*n*Math.cos(i),a=e-.9*n*Math.sin(i),h=s+n/3*Math.cos(i+.5*Math.PI),d=o+n/3*Math.sin(i+.5*Math.PI),l=s+n/3*Math.cos(i-.5*Math.PI),p=o+n/3*Math.sin(i-.5*Math.PI);this.beginPath(),this.moveTo(t,e),this.lineTo(h,d),this.lineTo(r,a),this.lineTo(l,p),this.closePath()},CanvasRenderingContext2D.prototype.dashedLine=function(t,e,i,n,s){s||(s=[10,5]),0==c&&(c=.001);var o=s.length;this.moveTo(t,e);for(var r=i-t,a=n-e,h=a/r,d=Math.sqrt(r*r+a*a),l=0,p=!0;d>=.1;){var c=s[l++%o];c>d&&(c=d);var u=Math.sqrt(c*c/(1+h*h));0>r&&(u=-u),t+=u,e+=h*u,this[p?"lineTo":"moveTo"](t,e),d-=c,p=!p}}),E.prototype.attachEdge=function(t){-1==this.edges.indexOf(t)&&this.edges.push(t),this._updateMass()},E.prototype.detachEdge=function(t){var e=this.edges.indexOf(t);-1!=e&&this.edges.splice(e,1),this._updateMass()},E.prototype._updateMass=function(){this.mass=50+20*this.edges.length},E.prototype.setProperties=function(t,e){if(t){if(void 0!=t.id&&(this.id=t.id),void 0!=t.label&&(this.label=t.label),void 0!=t.title&&(this.title=t.title),void 0!=t.group&&(this.group=t.group),void 0!=t.x&&(this.x=t.x),void 0!=t.y&&(this.y=t.y),void 0!=t.value&&(this.value=t.value),void 0===this.id)throw"Node must have an id";if(this.group){var i=this.grouplist.get(this.group);for(var n in i)i.hasOwnProperty(n)&&(this[n]=i[n])}if(void 0!=t.shape&&(this.shape=t.shape),void 0!=t.image&&(this.image=t.image),void 0!=t.radius&&(this.radius=t.radius),void 0!=t.color&&(this.color=E.parseColor(t.color)),void 0!=t.fontColor&&(this.fontColor=t.fontColor),void 0!=t.fontSize&&(this.fontSize=t.fontSize),void 0!=t.fontFace&&(this.fontFace=t.fontFace),void 0!=this.image){if(!this.imagelist)throw"No imagelist provided";this.imageObj=this.imagelist.load(this.image)}switch(this.xFixed=this.xFixed||void 0!=t.x,this.yFixed=this.yFixed||void 0!=t.y,this.radiusFixed=this.radiusFixed||void 0!=t.radius,"image"==this.shape&&(this.radiusMin=e.nodes.widthMin,this.radiusMax=e.nodes.widthMax),this.shape){case"database":this.draw=this._drawDatabase,this.resize=this._resizeDatabase;break;case"box":this.draw=this._drawBox,this.resize=this._resizeBox;break;case"circle":this.draw=this._drawCircle,this.resize=this._resizeCircle;break;case"ellipse":this.draw=this._drawEllipse,this.resize=this._resizeEllipse;break;case"image":this.draw=this._drawImage,this.resize=this._resizeImage;break;case"text":this.draw=this._drawText,this.resize=this._resizeText;break;case"dot":this.draw=this._drawDot,this.resize=this._resizeShape;break;case"square":this.draw=this._drawSquare,this.resize=this._resizeShape;break;case"triangle":this.draw=this._drawTriangle,this.resize=this._resizeShape;break;case"triangleDown":this.draw=this._drawTriangleDown,this.resize=this._resizeShape;break;case"star":this.draw=this._drawStar,this.resize=this._resizeShape;break;default:this.draw=this._drawEllipse,this.resize=this._resizeEllipse}this._reset()}},E.parseColor=function(t){var e;return O.isString(t)?e={border:t,background:t,highlight:{border:t,background:t}}:(e={},e.background=t.background||"white",e.border=t.border||e.background,O.isString(t.highlight)?e.highlight={border:t.highlight,background:t.highlight}:(e.highlight={},e.highlight.background=t.highlight&&t.highlight.background||e.background,e.highlight.border=t.highlight&&t.highlight.border||e.border)),e},E.prototype.select=function(){this.selected=!0,this._reset()},E.prototype.unselect=function(){this.selected=!1,this._reset()},E.prototype._reset=function(){this.width=void 0,this.height=void 0},E.prototype.getTitle=function(){return this.title},E.prototype.distanceToBorder=function(t,e){var i=1;switch(this.width||this.resize(t),this.shape){case"circle":case"dot":return this.radius+i;case"ellipse":var n=this.width/2,s=this.height/2,o=Math.sin(e)*n,r=Math.cos(e)*s;return n*s/Math.sqrt(o*o+r*r);case"box":case"image":case"text":default:return this.width?Math.min(Math.abs(this.width/2/Math.cos(e)),Math.abs(this.height/2/Math.sin(e)))+i:0}},E.prototype._setForce=function(t,e){this.fx=t,this.fy=e},E.prototype._addForce=function(t,e){this.fx+=t,this.fy+=e},E.prototype.discreteStep=function(t){if(!this.xFixed){var e=-this.damping*this.vx,i=(this.fx+e)/this.mass;this.vx+=i/t,this.x+=this.vx/t}if(!this.yFixed){var n=-this.damping*this.vy,s=(this.fy+n)/this.mass;this.vy+=s/t,this.y+=this.vy/t}},E.prototype.isFixed=function(){return this.xFixed&&this.yFixed},E.prototype.isMoving=function(t){return Math.abs(this.vx)>t||Math.abs(this.vy)>t||!this.xFixed&&Math.abs(this.fx)>this.minForce||!this.yFixed&&Math.abs(this.fy)>this.minForce},E.prototype.isSelected=function(){return this.selected},E.prototype.getValue=function(){return this.value},E.prototype.getDistance=function(t,e){var i=this.x-t,n=this.y-e;return Math.sqrt(i*i+n*n)},E.prototype.setValueRange=function(t,e){if(!this.radiusFixed&&void 0!==this.value){var i=(this.radiusMax-this.radiusMin)/(e-t);this.radius=(this.value-t)*i+this.radiusMin}},E.prototype.draw=function(){throw"Draw method not initialized for node"},E.prototype.resize=function(){throw"Resize method not initialized for node"},E.prototype.isOverlappingWith=function(t){return this.leftt.left&&this.topt.top},E.prototype._resizeImage=function(){if(!this.width){var t,e;if(this.value){var i=this.imageObj.height/this.imageObj.width;t=this.radius||this.imageObj.width,e=this.radius*i||this.imageObj.height}else t=this.imageObj.width,e=this.imageObj.height;this.width=t,this.height=e}},E.prototype._drawImage=function(t){this._resizeImage(t),this.left=this.x-this.width/2,this.top=this.y-this.height/2;var e;this.imageObj?(t.drawImage(this.imageObj,this.left,this.top,this.width,this.height),e=this.y+this.height/2):e=this.y,this._label(t,this.label,this.x,e,void 0,"top")},E.prototype._resizeBox=function(t){if(!this.width){var e=5,i=this.getTextSize(t);this.width=i.width+2*e,this.height=i.height+2*e}},E.prototype._drawBox=function(t){this._resizeBox(t),this.left=this.x-this.width/2,this.top=this.y-this.height/2,t.strokeStyle=this.selected?this.color.highlight.border:this.color.border,t.fillStyle=this.selected?this.color.highlight.background:this.color.background,t.lineWidth=this.selected?2:1,t.roundRect(this.left,this.top,this.width,this.height,this.radius),t.fill(),t.stroke(),this._label(t,this.label,this.x,this.y)},E.prototype._resizeDatabase=function(t){if(!this.width){var e=5,i=this.getTextSize(t),n=i.width+2*e;this.width=n,this.height=n}},E.prototype._drawDatabase=function(t){this._resizeDatabase(t),this.left=this.x-this.width/2,this.top=this.y-this.height/2,t.strokeStyle=this.selected?this.color.highlight.border:this.color.border,t.fillStyle=this.selected?this.color.highlight.background:this.color.background,t.lineWidth=this.selected?2:1,t.database(this.x-this.width/2,this.y-.5*this.height,this.width,this.height),t.fill(),t.stroke(),this._label(t,this.label,this.x,this.y)},E.prototype._resizeCircle=function(t){if(!this.width){var e=5,i=this.getTextSize(t),n=Math.max(i.width,i.height)+2*e;this.radius=n/2,this.width=n,this.height=n}},E.prototype._drawCircle=function(t){this._resizeCircle(t),this.left=this.x-this.width/2,this.top=this.y-this.height/2,t.strokeStyle=this.selected?this.color.highlight.border:this.color.border,t.fillStyle=this.selected?this.color.highlight.background:this.color.background,t.lineWidth=this.selected?2:1,t.circle(this.x,this.y,this.radius),t.fill(),t.stroke(),this._label(t,this.label,this.x,this.y)},E.prototype._resizeEllipse=function(t){if(!this.width){var e=this.getTextSize(t);this.width=1.5*e.width,this.height=2*e.height,this.widthl;l++)t.fillText(r[l],i,d),d+=h}},E.prototype.getTextSize=function(t){if(void 0!=this.label){t.font=(this.selected?"bold ":"")+this.fontSize+"px "+this.fontFace;for(var e=this.label.split("\n"),i=(this.fontSize+4)*e.length,n=0,s=0,o=e.length;o>s;s++)n=Math.max(n,t.measureText(e[s]).width);return{width:n,height:i}}return{width:0,height:0}},T.prototype.setProperties=function(t,e){if(t)switch(void 0!=t.from&&(this.fromId=t.from),void 0!=t.to&&(this.toId=t.to),void 0!=t.id&&(this.id=t.id),void 0!=t.style&&(this.style=t.style),void 0!=t.label&&(this.label=t.label),this.label&&(this.fontSize=e.edges.fontSize,this.fontFace=e.edges.fontFace,this.fontColor=e.edges.fontColor,void 0!=t.fontColor&&(this.fontColor=t.fontColor),void 0!=t.fontSize&&(this.fontSize=t.fontSize),void 0!=t.fontFace&&(this.fontFace=t.fontFace)),void 0!=t.title&&(this.title=t.title),void 0!=t.width&&(this.width=t.width),void 0!=t.value&&(this.value=t.value),void 0!=t.length&&(this.length=t.length),t.dash&&(void 0!=t.dash.length&&(this.dash.length=t.dash.length),void 0!=t.dash.gap&&(this.dash.gap=t.dash.gap),void 0!=t.dash.altLength&&(this.dash.altLength=t.dash.altLength)),void 0!=t.color&&(this.color=t.color),this.connect(),this.widthFixed=this.widthFixed||void 0!=t.width,this.lengthFixed=this.lengthFixed||void 0!=t.length,this.stiffness=1/this.length,this.style){case"line":this.draw=this._drawLine;break;case"arrow":this.draw=this._drawArrow;break;case"arrow-center":this.draw=this._drawArrowCenter;break;case"dash-line":this.draw=this._drawDashLine;break;default:this.draw=this._drawLine}},T.prototype.connect=function(){this.disconnect(),this.from=this.graph.nodes[this.fromId]||null,this.to=this.graph.nodes[this.toId]||null,this.connected=this.from&&this.to,this.connected?(this.from.attachEdge(this),this.to.attachEdge(this)):(this.from&&this.from.detachEdge(this),this.to&&this.to.detachEdge(this))},T.prototype.disconnect=function(){this.from&&(this.from.detachEdge(this),this.from=null),this.to&&(this.to.detachEdge(this),this.to=null),this.connected=!1},T.prototype.getTitle=function(){return this.title},T.prototype.getValue=function(){return this.value},T.prototype.setValueRange=function(t,e){if(!this.widthFixed&&void 0!==this.value){var i=(this.widthMax-this.widthMin)/(e-t);this.width=(this.value-t)*i+this.widthMin}},T.prototype.draw=function(){throw"Method draw not initialized in edge"},T.prototype.isOverlappingWith=function(t){var e=10,i=this.from.x,n=this.from.y,s=this.to.x,o=this.to.y,r=t.left,a=t.top,h=T._dist(i,n,s,o,r,a);return e>h},T.prototype._drawLine=function(t){t.strokeStyle=this.color,t.lineWidth=this._getLineWidth();var e;if(this.from!=this.to)this._line(t),this.label&&(e=this._pointOnLine(.5),this._label(t,this.label,e.x,e.y));else{var i,n,s=this.length/4,o=this.from;o.width||o.resize(t),o.width>o.height?(i=o.x+o.width/2,n=o.y-s):(i=o.x+s,n=o.y-o.height/2),this._circle(t,i,n,s),e=this._pointOnCircle(i,n,s,.5),this._label(t,this.label,e.x,e.y)}},T.prototype._getLineWidth=function(){return this.from.selected||this.to.selected?Math.min(2*this.width,this.widthMax):this.width},T.prototype._line=function(t){t.beginPath(),t.moveTo(this.from.x,this.from.y),t.lineTo(this.to.x,this.to.y),t.stroke()},T.prototype._circle=function(t,e,i,n){t.beginPath(),t.arc(e,i,n,0,2*Math.PI,!1),t.stroke()},T.prototype._label=function(t,e,i,n){if(e){t.font=(this.from.selected||this.to.selected?"bold ":"")+this.fontSize+"px "+this.fontFace,t.fillStyle="white";var s=t.measureText(e).width,o=this.fontSize,r=i-s/2,a=n-o/2;t.fillRect(r,a,s,o),t.fillStyle=this.fontColor||"black",t.textAlign="left",t.textBaseline="top",t.fillText(e,r,a)}},T.prototype._drawDashLine=function(t){if(t.strokeStyle=this.color,t.lineWidth=this._getLineWidth(),t.beginPath(),t.lineCap="round",void 0!=this.dash.altLength?t.dashedLine(this.from.x,this.from.y,this.to.x,this.to.y,[this.dash.length,this.dash.gap,this.dash.altLength,this.dash.gap]):void 0!=this.dash.length&&void 0!=this.dash.gap?t.dashedLine(this.from.x,this.from.y,this.to.x,this.to.y,[this.dash.length,this.dash.gap]):(t.moveTo(this.from.x,this.from.y),t.lineTo(this.to.x,this.to.y)),t.stroke(),this.label){var e=this._pointOnLine(.5);this._label(t,this.label,e.x,e.y)}},T.prototype._pointOnLine=function(t){return{x:(1-t)*this.from.x+t*this.to.x,y:(1-t)*this.from.y+t*this.to.y}},T.prototype._pointOnCircle=function(t,e,i,n){var s=2*(n-3/8)*Math.PI;return{x:t+i*Math.cos(s),y:e-i*Math.sin(s)}},T.prototype._drawArrowCenter=function(t){var e;if(t.strokeStyle=this.color,t.fillStyle=this.color,t.lineWidth=this._getLineWidth(),this.from!=this.to){this._line(t);var i=Math.atan2(this.to.y-this.from.y,this.to.x-this.from.x),n=10+5*this.width;e=this._pointOnLine(.5),t.arrow(e.x,e.y,i,n),t.fill(),t.stroke(),this.label&&(e=this._pointOnLine(.5),this._label(t,this.label,e.x,e.y))}else{var s,o,r=this.length/4,a=this.from;a.width||a.resize(t),a.width>a.height?(s=a.x+a.width/2,o=a.y-r):(s=a.x+r,o=a.y-a.height/2),this._circle(t,s,o,r);var i=.2*Math.PI,n=10+5*this.width;e=this._pointOnCircle(s,o,r,.5),t.arrow(e.x,e.y,i,n),t.fill(),t.stroke(),this.label&&(e=this._pointOnCircle(s,o,r,.5),this._label(t,this.label,e.x,e.y))}},T.prototype._drawArrow=function(t){t.strokeStyle=this.color,t.fillStyle=this.color,t.lineWidth=this._getLineWidth();var e,i;if(this.from!=this.to){e=Math.atan2(this.to.y-this.from.y,this.to.x-this.from.x);var n=this.to.x-this.from.x,s=this.to.y-this.from.y,o=Math.sqrt(n*n+s*s),r=this.from.distanceToBorder(t,e+Math.PI),a=(o-r)/o,h=a*this.from.x+(1-a)*this.to.x,d=a*this.from.y+(1-a)*this.to.y,l=this.to.distanceToBorder(t,e),p=(o-l)/o,c=(1-p)*this.from.x+p*this.to.x,u=(1-p)*this.from.y+p*this.to.y;if(t.beginPath(),t.moveTo(h,d),t.lineTo(c,u),t.stroke(),i=10+5*this.width,t.arrow(c,u,e,i),t.fill(),t.stroke(),this.label){var f=this._pointOnLine(.5);this._label(t,this.label,f.x,f.y)}}else{var m,g,v,y=this.from,b=this.length/4;y.width||y.resize(t),y.width>y.height?(m=y.x+y.width/2,g=y.y-b,v={x:m,y:y.y,angle:.9*Math.PI}):(m=y.x+b,g=y.y-y.height/2,v={x:y.x,y:g,angle:.6*Math.PI}),t.beginPath(),t.arc(m,g,b,0,2*Math.PI,!1),t.stroke(),i=10+5*this.width,t.arrow(v.x,v.y,v.angle,i),t.fill(),t.stroke(),this.label&&(f=this._pointOnCircle(m,g,b,.5),this._label(t,this.label,f.x,f.y)) -}},T._dist=function(t,e,i,n,s,o){var r=i-t,a=n-e,h=r*r+a*a,d=((s-t)*r+(o-e)*a)/h;d>1?d=1:0>d&&(d=0);var l=t+d*r,p=e+d*a,c=l-s,u=p-o;return Math.sqrt(c*c+u*u)},x.prototype.setPosition=function(t,e){this.x=parseInt(t),this.y=parseInt(e)},x.prototype.setText=function(t){this.frame.innerHTML=t},x.prototype.show=function(t){if(void 0===t&&(t=!0),t){var e=this.frame.clientHeight,i=this.frame.clientWidth,n=this.frame.parentNode.clientHeight,s=this.frame.parentNode.clientWidth,o=this.y-e;o+e+this.padding>n&&(o=n-e-this.padding),this.padding>o&&(o=this.padding);var r=this.x;r+i+this.padding>s&&(r=s-i-this.padding),this.padding>r&&(r=this.padding),this.frame.style.left=r+"px",this.frame.style.top=o+"px",this.frame.style.visibility="visible"}else this.hide()},x.prototype.hide=function(){this.frame.style.visibility="hidden"},Groups=function(){this.clear(),this.defaultIndex=0},Groups.DEFAULT=[{border:"#2B7CE9",background:"#97C2FC",highlight:{border:"#2B7CE9",background:"#D2E5FF"}},{border:"#FFA500",background:"#FFFF00",highlight:{border:"#FFA500",background:"#FFFFA3"}},{border:"#FA0A10",background:"#FB7E81",highlight:{border:"#FA0A10",background:"#FFAFB1"}},{border:"#41A906",background:"#7BE141",highlight:{border:"#41A906",background:"#A1EC76"}},{border:"#E129F0",background:"#EB7DF4",highlight:{border:"#E129F0",background:"#F0B3F5"}},{border:"#7C29F0",background:"#AD85E4",highlight:{border:"#7C29F0",background:"#D3BDF0"}},{border:"#C37F00",background:"#FFA807",highlight:{border:"#C37F00",background:"#FFCA66"}},{border:"#4220FB",background:"#6E6EFD",highlight:{border:"#4220FB",background:"#9B9BFD"}},{border:"#FD5A77",background:"#FFC0CB",highlight:{border:"#FD5A77",background:"#FFD1D9"}},{border:"#4AD63A",background:"#C2FABC",highlight:{border:"#4AD63A",background:"#E6FFE3"}}],Groups.prototype.clear=function(){this.groups={},this.groups.length=function(){var t=0;for(var e in this)this.hasOwnProperty(e)&&t++;return t}},Groups.prototype.get=function(t){var e=this.groups[t];if(void 0==e){var i=this.defaultIndex%Groups.DEFAULT.length;this.defaultIndex++,e={},e.color=Groups.DEFAULT[i],this.groups[t]=e}return e},Groups.prototype.add=function(t,e){return this.groups[t]=e,e.color&&(e.color=E.parseColor(e.color)),e},Images=function(){this.images={},this.callback=void 0},Images.prototype.setOnloadCallback=function(t){this.callback=t},Images.prototype.load=function(t){var e=this.images[t];if(void 0==e){var i=this;e=new Image,this.images[t]=e,e.onload=function(){i.callback&&i.callback(this)},e.src=t}return e},S.prototype.setData=function(t){if(t&&t.dot&&(t.nodes||t.edges))throw new SyntaxError('Data must contain either parameter "dot" or parameter pair "nodes" and "edges", but not both.');if(this.setOptions(t&&t.options),t&&t.dot){if(t&&t.dot){var e=k.util.DOTToGraph(t.dot);return this.setData(e),void 0}}else this._setNodes(t&&t.nodes),this._setEdges(t&&t.edges);this.stabilize&&this._doStabilize(),this.start()},S.prototype.setOptions=function(t){if(t){if(void 0!=t.width&&(this.width=t.width),void 0!=t.height&&(this.height=t.height),void 0!=t.stabilize&&(this.stabilize=t.stabilize),void 0!=t.selectable&&(this.selectable=t.selectable),t.edges){for(var e in t.edges)t.edges.hasOwnProperty(e)&&(this.constants.edges[e]=t.edges[e]);void 0!=t.edges.length&&t.nodes&&void 0==t.nodes.distance&&(this.constants.edges.length=t.edges.length,this.constants.nodes.distance=1.25*t.edges.length),t.edges.fontColor||(this.constants.edges.fontColor=t.edges.color),t.edges.dash&&(void 0!=t.edges.dash.length&&(this.constants.edges.dash.length=t.edges.dash.length),void 0!=t.edges.dash.gap&&(this.constants.edges.dash.gap=t.edges.dash.gap),void 0!=t.edges.dash.altLength&&(this.constants.edges.dash.altLength=t.edges.dash.altLength))}if(t.nodes){for(e in t.nodes)t.nodes.hasOwnProperty(e)&&(this.constants.nodes[e]=t.nodes[e]);t.nodes.color&&(this.constants.nodes.color=E.parseColor(t.nodes.color))}if(t.groups)for(var i in t.groups)if(t.groups.hasOwnProperty(i)){var n=t.groups[i];this.groups.add(i,n)}}this.setSize(this.width,this.height),this._setTranslation(this.frame.clientWidth/2,this.frame.clientHeight/2),this._setScale(1)},S.prototype._trigger=function(t,e){L.trigger(this,t,e)},S.prototype._create=function(){for(;this.containerElement.hasChildNodes();)this.containerElement.removeChild(this.containerElement.firstChild);if(this.frame=document.createElement("div"),this.frame.className="graph-frame",this.frame.style.position="relative",this.frame.style.overflow="hidden",this.frame.canvas=document.createElement("canvas"),this.frame.canvas.style.position="relative",this.frame.appendChild(this.frame.canvas),!this.frame.canvas.getContext){var t=document.createElement("DIV");t.style.color="red",t.style.fontWeight="bold",t.style.padding="10px",t.innerHTML="Error: your browser does not support HTML canvas",this.frame.canvas.appendChild(t)}var e=this;this.drag={},this.pinch={},this.hammer=D(this.frame.canvas,{prevent_default:!0}),this.hammer.on("tap",e._onTap.bind(e)),this.hammer.on("hold",e._onHold.bind(e)),this.hammer.on("pinch",e._onPinch.bind(e)),this.hammer.on("touch",e._onTouch.bind(e)),this.hammer.on("dragstart",e._onDragStart.bind(e)),this.hammer.on("drag",e._onDrag.bind(e)),this.hammer.on("dragend",e._onDragEnd.bind(e)),this.hammer.on("mousewheel",e._onMouseWheel.bind(e)),this.hammer.on("mousemove",e._onMouseMoveTitle.bind(e)),this.containerElement.appendChild(this.frame)},S.prototype._getNodeAt=function(t){var e=this._xToCanvas(t.x),i=this._yToCanvas(t.y),n={left:e,top:i,right:e,bottom:i},s=this._getNodesOverlappingWith(n);return s.length>0?s[s.length-1]:null},S.prototype._getPointer=function(t){return{x:t.pageX-k.util.getAbsoluteLeft(this.frame.canvas),y:t.pageY-k.util.getAbsoluteTop(this.frame.canvas)}},S.prototype._onTouch=function(t){this.drag.pointer=this._getPointer(t.gesture.touches[0]),this.drag.pinched=!1,this.pinch.scale=this._getScale()},S.prototype._onDragStart=function(){var t=this.drag;t.translation=this._getTranslation(),t.nodeId=this._getNodeAt(t.pointer);var e=this.nodes[t.nodeId];e&&!e.isSelected()&&this._selectNodes([t.nodeId]);var i=this;t.selection=[],this.selection.forEach(function(e){var n=i.nodes[e];if(n){var s={id:e,node:n,x:n.x,y:n.y,xFixed:n.xFixed,yFixed:n.yFixed};n.xFixed=!0,n.yFixed=!0,t.selection.push(s)}})},S.prototype._onDrag=function(t){if(!this.drag.pinched){var e=this._getPointer(t.gesture.touches[0]),i=this,n=this.drag,s=n.selection;if(s&&s.length){var o=e.x-n.pointer.x,r=e.y-n.pointer.y;s.forEach(function(t){var e=t.node;t.xFixed||(e.x=i._xToCanvas(i._canvasToX(t.x)+o)),t.yFixed||(e.y=i._yToCanvas(i._canvasToX(t.y)+r))}),this.moving||(this.moving=!0,this.start())}else{var a=e.x-this.drag.pointer.x,h=e.y-this.drag.pointer.y;this._setTranslation(this.drag.translation.x+a,this.drag.translation.y+h),this._redraw(),this.moved=!0}}},S.prototype._onDragEnd=function(){var t=this.drag.selection;t&&t.forEach(function(t){t.node.xFixed=t.xFixed,t.node.yFixed=t.yFixed})},S.prototype._onTap=function(t){var e=this._getPointer(t.gesture.touches[0]),i=this._getNodeAt(e),n=this.nodes[i];n?(this._selectNodes([i]),this.moving||this._redraw()):(this._unselectNodes(),this._redraw())},S.prototype._onHold=function(t){var e=this._getPointer(t.gesture.touches[0]),i=this._getNodeAt(e),n=this.nodes[i];if(n){if(n.isSelected())this._unselectNodes([i]);else{var s=!0;this._selectNodes([i],s)}this.moving||this._redraw()}},S.prototype._onPinch=function(t){var e=this._getPointer(t.gesture.center);this.drag.pinched=!0,"scale"in this.pinch||(this.pinch.scale=1);var i=this.pinch.scale*t.gesture.scale;this._zoom(i,e)},S.prototype._zoom=function(t,e){var i=this._getScale();.01>t&&(t=.01),t>10&&(t=10);var n=this._getTranslation(),s=t/i,o=(1-s)*e.x+n.x*s,r=(1-s)*e.y+n.y*s;return this._setScale(t),this._setTranslation(o,r),this._redraw(),t},S.prototype._onMouseWheel=function(t){var e=0;if(t.wheelDelta?e=t.wheelDelta/120:t.detail&&(e=-t.detail/3),e){"mouswheelScale"in this.pinch||(this.pinch.mouswheelScale=1);var i=this.pinch.mouswheelScale,n=e/10;0>e&&(n/=1-n),i*=1+n;var s=D.event.collectEventData(this,"scroll",t),o=this._getPointer(s.center);i=this._zoom(i,o),this.pinch.mouswheelScale=i}t.preventDefault()},S.prototype._onMouseMoveTitle=function(t){var e=D.event.collectEventData(this,"mousemove",t),i=this._getPointer(e.center);this.popupNode&&this._checkHidePopup(i);var n=this,s=function(){n._checkShowPopup(i)};this.popupTimer&&clearInterval(this.popupTimer),this.leftButtonDown||(this.popupTimer=setTimeout(s,300))},S.prototype._checkShowPopup=function(t){var e,i={left:this._xToCanvas(t.x),top:this._yToCanvas(t.y),right:this._xToCanvas(t.x),bottom:this._yToCanvas(t.y)},n=this.popupNode;if(void 0==this.popupNode){var s=this.nodes;for(e in s)if(s.hasOwnProperty(e)){var o=s[e];if(void 0!=o.getTitle()&&o.isOverlappingWith(i)){this.popupNode=o;break}}}if(void 0==this.popupNode){var r=this.edges;for(e in r)if(r.hasOwnProperty(e)){var a=r[e];if(a.connected&&void 0!=a.getTitle()&&a.isOverlappingWith(i)){this.popupNode=a;break}}}if(this.popupNode){if(this.popupNode!=n){var h=this;h.popup||(h.popup=new x(h.frame)),h.popup.setPosition(t.x-3,t.y-3),h.popup.setText(h.popupNode.getTitle()),h.popup.show()}}else this.popup&&this.popup.hide()},S.prototype._checkHidePopup=function(t){this.popupNode&&this._getNodeAt(t)||(this.popupNode=void 0,this.popup&&this.popup.hide())},S.prototype._unselectNodes=function(t,e){var i,n,s,o=!1;if(t)for(i=0,n=t.length;n>i;i++){s=t[i],this.nodes[s].unselect();for(var r=0;this.selection.length>r;)this.selection[r]==s?(this.selection.splice(r,1),o=!0):r++}else if(this.selection&&this.selection.length){for(i=0,n=this.selection.length;n>i;i++)s=this.selection[i],this.nodes[s].unselect(),o=!0;this.selection=[]}return!o||1!=e&&void 0!=e||this._trigger("select"),o},S.prototype._selectNodes=function(t,e){var i,n,s=!1,o=!0;if(t.length!=this.selection.length)o=!1;else for(i=0,n=Math.min(t.length,this.selection.length);n>i;i++)if(t[i]!=this.selection[i]){o=!1;break}if(o)return s;if(void 0==e||0==e){var r=!1;s=this._unselectNodes(void 0,r)}for(i=0,n=t.length;n>i;i++){var a=t[i],h=-1!=this.selection.indexOf(a);h||(this.nodes[a].select(),this.selection.push(a),s=!0)}return s&&this._trigger("select"),s},S.prototype._getNodesOverlappingWith=function(t){var e=this.nodes,i=[];for(var n in e)e.hasOwnProperty(n)&&e[n].isOverlappingWith(t)&&i.push(n);return i},S.prototype.getSelection=function(){return this.selection.concat([])},S.prototype.setSelection=function(t){var e,i,n;if(!t||void 0==t.length)throw"Selection must be an array with ids";for(e=0,i=this.selection.length;i>e;e++)n=this.selection[e],this.nodes[n].unselect();for(this.selection=[],e=0,i=t.length;i>e;e++){n=t[e];var s=this.nodes[n];if(!s)throw new RangeError('Node with id "'+n+'" not found');s.select(),this.selection.push(n)}this.redraw()},S.prototype._updateSelection=function(){for(var t=0;this.selection.length>t;){var e=this.selection[t];this.nodes[e]?t++:this.selection.splice(t,1)}},S.prototype._getConnectionCount=function(t){function e(t){for(var e=[],i=0,n=t.length;n>i;i++)for(var s=t[i],o=s.edges,r=0,a=o.length;a>r;r++){var h=o[r],d=null;h.from==s?d=h.to:h.to==s&&(d=h.from);var l,p;if(d)for(l=0,p=t.length;p>l;l++)if(t[l]==d){d=null;break}if(d)for(l=0,p=e.length;p>l;l++)if(e[l]==d){d=null;break}d&&e.push(d)}return e}void 0==t&&(t=1);var i=[],n=this.nodes;for(var s in n)if(n.hasOwnProperty(s)){for(var o=[n[s]],r=0;t>r;r++)o=o.concat(e(o));i.push(o)}for(var a=[],h=0,d=i.length;d>h;h++)a.push(i[h].length);return a},S.prototype.setSize=function(t,e){this.frame.style.width=t,this.frame.style.height=e,this.frame.canvas.style.width="100%",this.frame.canvas.style.height="100%",this.frame.canvas.width=this.frame.canvas.clientWidth,this.frame.canvas.height=this.frame.canvas.clientHeight},S.prototype._setNodes=function(t){var e=this.nodesData;if(t instanceof o||t instanceof r)this.nodesData=t;else if(t instanceof Array)this.nodesData=new o,this.nodesData.add(t);else{if(t)throw new TypeError("Array or DataSet expected");this.nodesData=new o}if(e&&O.forEach(this.nodesListeners,function(t,i){e.unsubscribe(i,t)}),this.nodes={},this.nodesData){var i=this;O.forEach(this.nodesListeners,function(t,e){i.nodesData.subscribe(e,t)});var n=this.nodesData.getIds();this._addNodes(n)}this._updateSelection()},S.prototype._addNodes=function(t){for(var e,i=0,n=t.length;n>i;i++){e=t[i];var s=this.nodesData.get(e),o=new E(s,this.images,this.groups,this.constants);if(this.nodes[e]=o,!o.isFixed()){var r=2*this.constants.edges.length,a=t.length,h=2*Math.PI*(i/a);o.x=r*Math.cos(h),o.y=r*Math.sin(h),this.moving=!0}}this._reconnectEdges(),this._updateValueRange(this.nodes)},S.prototype._updateNodes=function(t){for(var e=this.nodes,i=this.nodesData,n=0,s=t.length;s>n;n++){var o=t[n],r=e[o],a=i.get(o);r?r.setProperties(a,this.constants):(r=new E(properties,this.images,this.groups,this.constants),e[o]=r,r.isFixed()||(this.moving=!0))}this._reconnectEdges(),this._updateValueRange(e)},S.prototype._removeNodes=function(t){for(var e=this.nodes,i=0,n=t.length;n>i;i++){var s=t[i];delete e[s]}this._reconnectEdges(),this._updateSelection(),this._updateValueRange(e)},S.prototype._setEdges=function(t){var e=this.edgesData;if(t instanceof o||t instanceof r)this.edgesData=t;else if(t instanceof Array)this.edgesData=new o,this.edgesData.add(t);else{if(t)throw new TypeError("Array or DataSet expected");this.edgesData=new o}if(e&&O.forEach(this.edgesListeners,function(t,i){e.unsubscribe(i,t)}),this.edges={},this.edgesData){var i=this;O.forEach(this.edgesListeners,function(t,e){i.edgesData.subscribe(e,t)});var n=this.edgesData.getIds();this._addEdges(n)}this._reconnectEdges()},S.prototype._addEdges=function(t){for(var e=this.edges,i=this.edgesData,n=0,s=t.length;s>n;n++){var o=t[n],r=e[o];r&&r.disconnect();var a=i.get(o);e[o]=new T(a,this,this.constants)}this.moving=!0,this._updateValueRange(e)},S.prototype._updateEdges=function(t){for(var e=this.edges,i=this.edgesData,n=0,s=t.length;s>n;n++){var o=t[n],r=i.get(o),a=e[o];a?(a.disconnect(),a.setProperties(r,this.constants),a.connect()):(a=new T(r,this,this.constants),this.edges[o]=a)}this.moving=!0,this._updateValueRange(e)},S.prototype._removeEdges=function(t){for(var e=this.edges,i=0,n=t.length;n>i;i++){var s=t[i],o=e[s];o&&(o.disconnect(),delete e[s])}this.moving=!0,this._updateValueRange(e)},S.prototype._reconnectEdges=function(){var t,e=this.nodes,i=this.edges;for(t in e)e.hasOwnProperty(t)&&(e[t].edges=[]);for(t in i)if(i.hasOwnProperty(t)){var n=i[t];n.from=null,n.to=null,n.connect()}},S.prototype._updateValueRange=function(t){var e,i=void 0,n=void 0;for(e in t)if(t.hasOwnProperty(e)){var s=t[e].getValue();void 0!==s&&(i=void 0===i?s:Math.min(s,i),n=void 0===n?s:Math.max(s,n))}if(void 0!==i&&void 0!==n)for(e in t)t.hasOwnProperty(e)&&t[e].setValueRange(i,n)},S.prototype.redraw=function(){this.setSize(this.width,this.height),this._redraw()},S.prototype._redraw=function(){var t=this.frame.canvas.getContext("2d"),e=this.frame.canvas.width,i=this.frame.canvas.height;t.clearRect(0,0,e,i),t.save(),t.translate(this.translation.x,this.translation.y),t.scale(this.scale,this.scale),this._drawEdges(t),this._drawNodes(t),t.restore()},S.prototype._setTranslation=function(t,e){void 0===this.translation&&(this.translation={x:0,y:0}),void 0!==t&&(this.translation.x=t),void 0!==e&&(this.translation.y=e)},S.prototype._getTranslation=function(){return{x:this.translation.x,y:this.translation.y}},S.prototype._setScale=function(t){this.scale=t},S.prototype._getScale=function(){return this.scale},S.prototype._xToCanvas=function(t){return(t-this.translation.x)/this.scale},S.prototype._canvasToX=function(t){return t*this.scale+this.translation.x},S.prototype._yToCanvas=function(t){return(t-this.translation.y)/this.scale},S.prototype._canvasToY=function(t){return t*this.scale+this.translation.y},S.prototype._drawNodes=function(t){var e=this.nodes,i=[];for(var n in e)e.hasOwnProperty(n)&&(e[n].isSelected()?i.push(n):e[n].draw(t));for(var s=0,o=i.length;o>s;s++)e[i[s]].draw(t)},S.prototype._drawEdges=function(t){var e=this.edges;for(var i in e)if(e.hasOwnProperty(i)){var n=e[i];n.connected&&e[i].draw(t)}},S.prototype._doStabilize=function(){new Date;for(var t=0,e=this.constants.minVelocity,i=!1;!i&&this.constants.maxIterations>t;)this._calculateForces(),this._discreteStepNodes(),i=!this._isMoving(e),t++;new Date},S.prototype._calculateForces=function(){var t,e,i,n,s,o,r,a,h,d,l,p=this.nodes,c=this.edges,u=.01,f=this.frame.canvas.clientWidth/2,m=this.frame.canvas.clientHeight/2;for(t in p)if(p.hasOwnProperty(t)){var g=p[t];e=f-g.x,i=m-g.y,n=Math.atan2(i,e),o=Math.cos(n)*u,r=Math.sin(n)*u,g._setForce(o,r)}var v=this.constants.nodes.distance,y=10;for(var b in p)if(p.hasOwnProperty(b)){var w=p[b];for(var _ in p)if(p.hasOwnProperty(_)){var E=p[_];e=E.x-w.x,i=E.y-w.y,s=Math.sqrt(e*e+i*i),n=Math.atan2(i,e),a=1/(1+Math.exp((s/v-1)*y)),o=Math.cos(n)*a,r=Math.sin(n)*a,w._addForce(-o,-r),E._addForce(o,r)}}for(t in c)if(c.hasOwnProperty(t)){var T=c[t];T.connected&&(e=T.to.x-T.from.x,i=T.to.y-T.from.y,l=T.length,d=Math.sqrt(e*e+i*i),n=Math.atan2(i,e),h=T.stiffness*(l-d),o=Math.cos(n)*h,r=Math.sin(n)*h,T.from._addForce(-o,-r),T.to._addForce(o,r))}},S.prototype._isMoving=function(t){var e=this.nodes;for(var i in e)if(e.hasOwnProperty(i)&&e[i].isMoving(t))return!0;return!1},S.prototype._discreteStepNodes=function(){var t=this.refreshRate/1e3,e=this.nodes;for(var i in e)e.hasOwnProperty(i)&&e[i].discreteStep(t)},S.prototype.start=function(){if(this.moving){this._calculateForces(),this._discreteStepNodes();var t=this.constants.minVelocity;this.moving=this._isMoving(t)}if(this.moving){if(!this.timer){var e=this;this.timer=window.setTimeout(function(){e.timer=void 0,e.start(),e._redraw()},this.refreshRate)}}else this._redraw()},S.prototype.stop=function(){this.timer&&(window.clearInterval(this.timer),this.timer=void 0)};var k={util:O,events:L,Controller:d,DataSet:o,DataView:r,Range:h,Stack:a,TimeStep:TimeStep,EventBus:s,components:{items:{Item:m,ItemBox:g,ItemPoint:v,ItemRange:y},Component:l,Panel:p,RootPanel:c,ItemSet:f,TimeAxis:u},graph:{Node:E,Edge:T,Popup:x,Groups:Groups,Images:Images},Timeline:_,Graph:S};n!==void 0&&(n=k),i!==void 0&&i.exports!==void 0&&(i.exports=k),"function"==typeof t&&t(function(){return k}),"undefined"!=typeof window&&(window.vis=k),O.loadCss("/* vis.js stylesheet */\n.vis.timeline {\n}\n\n\n.vis.timeline.rootpanel {\n position: relative;\n overflow: hidden;\n\n border: 1px solid #bfbfbf;\n -moz-box-sizing: border-box;\n box-sizing: border-box;\n}\n\n.vis.timeline .panel {\n position: absolute;\n overflow: hidden;\n}\n\n\n.vis.timeline .groupset {\n position: absolute;\n padding: 0;\n margin: 0;\n}\n\n.vis.timeline .labels {\n position: absolute;\n top: 0;\n left: 0;\n width: 100%;\n height: 100%;\n\n padding: 0;\n margin: 0;\n\n border-right: 1px solid #bfbfbf;\n box-sizing: border-box;\n -moz-box-sizing: border-box;\n}\n\n.vis.timeline .labels .label {\n position: absolute;\n left: 0;\n top: 0;\n width: 100%;\n border-bottom: 1px solid #bfbfbf;\n color: #4d4d4d;\n}\n\n.vis.timeline .labels .label .inner {\n display: inline-block;\n padding: 5px;\n}\n\n\n.vis.timeline .itemset {\n position: absolute;\n padding: 0;\n margin: 0;\n overflow: hidden;\n}\n\n.vis.timeline .background {\n}\n\n.vis.timeline .foreground {\n}\n\n.vis.timeline .itemset-axis {\n position: absolute;\n}\n\n.vis.timeline .groupset .itemset-axis {\n border-top: 1px solid #bfbfbf;\n}\n\n/* TODO: with orientation=='bottom', this will more or less overlap with timeline axis\n.vis.timeline .groupset .itemset-axis:last-child {\n border-top: none;\n}\n*/\n\n\n.vis.timeline .item {\n position: absolute;\n color: #1A1A1A;\n border-color: #97B0F8;\n background-color: #D5DDF6;\n display: inline-block;\n}\n\n.vis.timeline .item.selected {\n border-color: #FFC200;\n background-color: #FFF785;\n z-index: 999;\n}\n\n.vis.timeline .item.cluster {\n /* TODO: use another color or pattern? */\n background: #97B0F8 url('img/cluster_bg.png');\n color: white;\n}\n.vis.timeline .item.cluster.point {\n border-color: #D5DDF6;\n}\n\n.vis.timeline .item.box {\n text-align: center;\n border-style: solid;\n border-width: 1px;\n border-radius: 5px;\n -moz-border-radius: 5px; /* For Firefox 3.6 and older */\n}\n\n.vis.timeline .item.point {\n background: none;\n}\n\n.vis.timeline .dot {\n border: 5px solid #97B0F8;\n position: absolute;\n border-radius: 5px;\n -moz-border-radius: 5px; /* For Firefox 3.6 and older */\n}\n\n.vis.timeline .item.range {\n overflow: hidden;\n border-style: solid;\n border-width: 1px;\n border-radius: 2px;\n -moz-border-radius: 2px; /* For Firefox 3.6 and older */\n}\n\n.vis.timeline .item.range .drag-left {\n cursor: w-resize;\n z-index: 1000;\n}\n\n.vis.timeline .item.range .drag-right {\n cursor: e-resize;\n z-index: 1000;\n}\n\n.vis.timeline .item.range .content {\n position: relative;\n display: inline-block;\n}\n\n.vis.timeline .item.line {\n position: absolute;\n width: 0;\n border-left-width: 1px;\n border-left-style: solid;\n}\n\n.vis.timeline .item .content {\n margin: 5px;\n white-space: nowrap;\n overflow: hidden;\n}\n\n.vis.timeline .axis {\n position: relative;\n}\n\n.vis.timeline .axis .text {\n position: absolute;\n color: #4d4d4d;\n padding: 3px;\n white-space: nowrap;\n}\n\n.vis.timeline .axis .text.measure {\n position: absolute;\n padding-left: 0;\n padding-right: 0;\n margin-left: 0;\n margin-right: 0;\n visibility: hidden;\n}\n\n.vis.timeline .axis .grid.vertical {\n position: absolute;\n width: 0;\n border-right: 1px solid;\n}\n\n.vis.timeline .axis .grid.horizontal {\n position: absolute;\n left: 0;\n width: 100%;\n height: 0;\n border-bottom: 1px solid;\n}\n\n.vis.timeline .axis .grid.minor {\n border-color: #e5e5e5;\n}\n\n.vis.timeline .axis .grid.major {\n border-color: #bfbfbf;\n}\n\n")},{hammerjs:1,moment:2}]},{},[3])(3)}); \ No newline at end of file +}},T._dist=function(t,e,i,n,s,o){var r=i-t,a=n-e,h=r*r+a*a,d=((s-t)*r+(o-e)*a)/h;d>1?d=1:0>d&&(d=0);var l=t+d*r,p=e+d*a,c=l-s,u=p-o;return Math.sqrt(c*c+u*u)},x.prototype.setPosition=function(t,e){this.x=parseInt(t),this.y=parseInt(e)},x.prototype.setText=function(t){this.frame.innerHTML=t},x.prototype.show=function(t){if(void 0===t&&(t=!0),t){var e=this.frame.clientHeight,i=this.frame.clientWidth,n=this.frame.parentNode.clientHeight,s=this.frame.parentNode.clientWidth,o=this.y-e;o+e+this.padding>n&&(o=n-e-this.padding),this.padding>o&&(o=this.padding);var r=this.x;r+i+this.padding>s&&(r=s-i-this.padding),this.padding>r&&(r=this.padding),this.frame.style.left=r+"px",this.frame.style.top=o+"px",this.frame.style.visibility="visible"}else this.hide()},x.prototype.hide=function(){this.frame.style.visibility="hidden"},Groups=function(){this.clear(),this.defaultIndex=0},Groups.DEFAULT=[{border:"#2B7CE9",background:"#97C2FC",highlight:{border:"#2B7CE9",background:"#D2E5FF"}},{border:"#FFA500",background:"#FFFF00",highlight:{border:"#FFA500",background:"#FFFFA3"}},{border:"#FA0A10",background:"#FB7E81",highlight:{border:"#FA0A10",background:"#FFAFB1"}},{border:"#41A906",background:"#7BE141",highlight:{border:"#41A906",background:"#A1EC76"}},{border:"#E129F0",background:"#EB7DF4",highlight:{border:"#E129F0",background:"#F0B3F5"}},{border:"#7C29F0",background:"#AD85E4",highlight:{border:"#7C29F0",background:"#D3BDF0"}},{border:"#C37F00",background:"#FFA807",highlight:{border:"#C37F00",background:"#FFCA66"}},{border:"#4220FB",background:"#6E6EFD",highlight:{border:"#4220FB",background:"#9B9BFD"}},{border:"#FD5A77",background:"#FFC0CB",highlight:{border:"#FD5A77",background:"#FFD1D9"}},{border:"#4AD63A",background:"#C2FABC",highlight:{border:"#4AD63A",background:"#E6FFE3"}}],Groups.prototype.clear=function(){this.groups={},this.groups.length=function(){var t=0;for(var e in this)this.hasOwnProperty(e)&&t++;return t}},Groups.prototype.get=function(t){var e=this.groups[t];if(void 0==e){var i=this.defaultIndex%Groups.DEFAULT.length;this.defaultIndex++,e={},e.color=Groups.DEFAULT[i],this.groups[t]=e}return e},Groups.prototype.add=function(t,e){return this.groups[t]=e,e.color&&(e.color=E.parseColor(e.color)),e},Images=function(){this.images={},this.callback=void 0},Images.prototype.setOnloadCallback=function(t){this.callback=t},Images.prototype.load=function(t){var e=this.images[t];if(void 0==e){var i=this;e=new Image,this.images[t]=e,e.onload=function(){i.callback&&i.callback(this)},e.src=t}return e},S.prototype.setData=function(t){if(t&&t.dot&&(t.nodes||t.edges))throw new SyntaxError('Data must contain either parameter "dot" or parameter pair "nodes" and "edges", but not both.');if(this.setOptions(t&&t.options),t&&t.dot){if(t&&t.dot){var e=k.util.DOTToGraph(t.dot);return this.setData(e),void 0}}else this._setNodes(t&&t.nodes),this._setEdges(t&&t.edges);this.stabilize&&this._doStabilize(),this.start()},S.prototype.setOptions=function(t){if(t){if(void 0!=t.width&&(this.width=t.width),void 0!=t.height&&(this.height=t.height),void 0!=t.stabilize&&(this.stabilize=t.stabilize),void 0!=t.selectable&&(this.selectable=t.selectable),t.edges){for(var e in t.edges)t.edges.hasOwnProperty(e)&&(this.constants.edges[e]=t.edges[e]);void 0!=t.edges.length&&t.nodes&&void 0==t.nodes.distance&&(this.constants.edges.length=t.edges.length,this.constants.nodes.distance=1.25*t.edges.length),t.edges.fontColor||(this.constants.edges.fontColor=t.edges.color),t.edges.dash&&(void 0!=t.edges.dash.length&&(this.constants.edges.dash.length=t.edges.dash.length),void 0!=t.edges.dash.gap&&(this.constants.edges.dash.gap=t.edges.dash.gap),void 0!=t.edges.dash.altLength&&(this.constants.edges.dash.altLength=t.edges.dash.altLength))}if(t.nodes){for(e in t.nodes)t.nodes.hasOwnProperty(e)&&(this.constants.nodes[e]=t.nodes[e]);t.nodes.color&&(this.constants.nodes.color=E.parseColor(t.nodes.color))}if(t.groups)for(var i in t.groups)if(t.groups.hasOwnProperty(i)){var n=t.groups[i];this.groups.add(i,n)}}this.setSize(this.width,this.height),this._setTranslation(this.frame.clientWidth/2,this.frame.clientHeight/2),this._setScale(1)},S.prototype._trigger=function(t,e){L.trigger(this,t,e)},S.prototype._create=function(){for(;this.containerElement.hasChildNodes();)this.containerElement.removeChild(this.containerElement.firstChild);if(this.frame=document.createElement("div"),this.frame.className="graph-frame",this.frame.style.position="relative",this.frame.style.overflow="hidden",this.frame.canvas=document.createElement("canvas"),this.frame.canvas.style.position="relative",this.frame.appendChild(this.frame.canvas),!this.frame.canvas.getContext){var t=document.createElement("DIV");t.style.color="red",t.style.fontWeight="bold",t.style.padding="10px",t.innerHTML="Error: your browser does not support HTML canvas",this.frame.canvas.appendChild(t)}var e=this;this.drag={},this.pinch={},this.hammer=D(this.frame.canvas,{prevent_default:!0}),this.hammer.on("tap",e._onTap.bind(e)),this.hammer.on("hold",e._onHold.bind(e)),this.hammer.on("pinch",e._onPinch.bind(e)),this.hammer.on("touch",e._onTouch.bind(e)),this.hammer.on("dragstart",e._onDragStart.bind(e)),this.hammer.on("drag",e._onDrag.bind(e)),this.hammer.on("dragend",e._onDragEnd.bind(e)),this.hammer.on("mousewheel",e._onMouseWheel.bind(e)),this.hammer.on("mousemove",e._onMouseMoveTitle.bind(e)),this.containerElement.appendChild(this.frame)},S.prototype._getNodeAt=function(t){var e=this._xToCanvas(t.x),i=this._yToCanvas(t.y),n={left:e,top:i,right:e,bottom:i},s=this._getNodesOverlappingWith(n);return s.length>0?s[s.length-1]:null},S.prototype._getPointer=function(t){return{x:t.pageX-k.util.getAbsoluteLeft(this.frame.canvas),y:t.pageY-k.util.getAbsoluteTop(this.frame.canvas)}},S.prototype._onTouch=function(t){this.drag.pointer=this._getPointer(t.gesture.touches[0]),this.drag.pinched=!1,this.pinch.scale=this._getScale()},S.prototype._onDragStart=function(){var t=this.drag;t.selection=[],t.translation=this._getTranslation(),t.nodeId=this._getNodeAt(t.pointer);var e=this.nodes[t.nodeId];if(e){e.isSelected()||this._selectNodes([t.nodeId]);var i=this;this.selection.forEach(function(e){var n=i.nodes[e];if(n){var s={id:e,node:n,x:n.x,y:n.y,xFixed:n.xFixed,yFixed:n.yFixed};n.xFixed=!0,n.yFixed=!0,t.selection.push(s)}})}},S.prototype._onDrag=function(t){if(!this.drag.pinched){var e=this._getPointer(t.gesture.touches[0]),i=this,n=this.drag,s=n.selection;if(s&&s.length){var o=e.x-n.pointer.x,r=e.y-n.pointer.y;s.forEach(function(t){var e=t.node;t.xFixed||(e.x=i._canvasToX(i._xToCanvas(t.x)+o)),t.yFixed||(e.y=i._canvasToY(i._yToCanvas(t.y)+r))}),this.moving||(this.moving=!0,this.start())}else{var a=e.x-this.drag.pointer.x,h=e.y-this.drag.pointer.y;this._setTranslation(this.drag.translation.x+a,this.drag.translation.y+h),this._redraw(),this.moved=!0}}},S.prototype._onDragEnd=function(){var t=this.drag.selection;t&&t.forEach(function(t){t.node.xFixed=t.xFixed,t.node.yFixed=t.yFixed})},S.prototype._onTap=function(t){var e=this._getPointer(t.gesture.touches[0]),i=this._getNodeAt(e),n=this.nodes[i];n?(this._selectNodes([i]),this.moving||this._redraw()):(this._unselectNodes(),this._redraw())},S.prototype._onHold=function(t){var e=this._getPointer(t.gesture.touches[0]),i=this._getNodeAt(e),n=this.nodes[i];if(n){if(n.isSelected())this._unselectNodes([i]);else{var s=!0;this._selectNodes([i],s)}this.moving||this._redraw()}},S.prototype._onPinch=function(t){var e=this._getPointer(t.gesture.center);this.drag.pinched=!0,"scale"in this.pinch||(this.pinch.scale=1);var i=this.pinch.scale*t.gesture.scale;this._zoom(i,e)},S.prototype._zoom=function(t,e){var i=this._getScale();.01>t&&(t=.01),t>10&&(t=10);var n=this._getTranslation(),s=t/i,o=(1-s)*e.x+n.x*s,r=(1-s)*e.y+n.y*s;return this._setScale(t),this._setTranslation(o,r),this._redraw(),t},S.prototype._onMouseWheel=function(t){var e=0;if(t.wheelDelta?e=t.wheelDelta/120:t.detail&&(e=-t.detail/3),e){"mouswheelScale"in this.pinch||(this.pinch.mouswheelScale=1);var i=this.pinch.mouswheelScale,n=e/10;0>e&&(n/=1-n),i*=1+n;var s=D.event.collectEventData(this,"scroll",t),o=this._getPointer(s.center);i=this._zoom(i,o),this.pinch.mouswheelScale=i}t.preventDefault()},S.prototype._onMouseMoveTitle=function(t){var e=D.event.collectEventData(this,"mousemove",t),i=this._getPointer(e.center);this.popupNode&&this._checkHidePopup(i);var n=this,s=function(){n._checkShowPopup(i)};this.popupTimer&&clearInterval(this.popupTimer),this.leftButtonDown||(this.popupTimer=setTimeout(s,300))},S.prototype._checkShowPopup=function(t){var e,i={left:this._xToCanvas(t.x),top:this._yToCanvas(t.y),right:this._xToCanvas(t.x),bottom:this._yToCanvas(t.y)},n=this.popupNode;if(void 0==this.popupNode){var s=this.nodes;for(e in s)if(s.hasOwnProperty(e)){var o=s[e];if(void 0!=o.getTitle()&&o.isOverlappingWith(i)){this.popupNode=o;break}}}if(void 0==this.popupNode){var r=this.edges;for(e in r)if(r.hasOwnProperty(e)){var a=r[e];if(a.connected&&void 0!=a.getTitle()&&a.isOverlappingWith(i)){this.popupNode=a;break}}}if(this.popupNode){if(this.popupNode!=n){var h=this;h.popup||(h.popup=new x(h.frame)),h.popup.setPosition(t.x-3,t.y-3),h.popup.setText(h.popupNode.getTitle()),h.popup.show()}}else this.popup&&this.popup.hide()},S.prototype._checkHidePopup=function(t){this.popupNode&&this._getNodeAt(t)||(this.popupNode=void 0,this.popup&&this.popup.hide())},S.prototype._unselectNodes=function(t,e){var i,n,s,o=!1;if(t)for(i=0,n=t.length;n>i;i++){s=t[i],this.nodes[s].unselect();for(var r=0;this.selection.length>r;)this.selection[r]==s?(this.selection.splice(r,1),o=!0):r++}else if(this.selection&&this.selection.length){for(i=0,n=this.selection.length;n>i;i++)s=this.selection[i],this.nodes[s].unselect(),o=!0;this.selection=[]}return!o||1!=e&&void 0!=e||this._trigger("select"),o},S.prototype._selectNodes=function(t,e){var i,n,s=!1,o=!0;if(t.length!=this.selection.length)o=!1;else for(i=0,n=Math.min(t.length,this.selection.length);n>i;i++)if(t[i]!=this.selection[i]){o=!1;break}if(o)return s;if(void 0==e||0==e){var r=!1;s=this._unselectNodes(void 0,r)}for(i=0,n=t.length;n>i;i++){var a=t[i],h=-1!=this.selection.indexOf(a);h||(this.nodes[a].select(),this.selection.push(a),s=!0)}return s&&this._trigger("select"),s},S.prototype._getNodesOverlappingWith=function(t){var e=this.nodes,i=[];for(var n in e)e.hasOwnProperty(n)&&e[n].isOverlappingWith(t)&&i.push(n);return i},S.prototype.getSelection=function(){return this.selection.concat([])},S.prototype.setSelection=function(t){var e,i,n;if(!t||void 0==t.length)throw"Selection must be an array with ids";for(e=0,i=this.selection.length;i>e;e++)n=this.selection[e],this.nodes[n].unselect();for(this.selection=[],e=0,i=t.length;i>e;e++){n=t[e];var s=this.nodes[n];if(!s)throw new RangeError('Node with id "'+n+'" not found');s.select(),this.selection.push(n)}this.redraw()},S.prototype._updateSelection=function(){for(var t=0;this.selection.length>t;){var e=this.selection[t];this.nodes[e]?t++:this.selection.splice(t,1)}},S.prototype._getConnectionCount=function(t){function e(t){for(var e=[],i=0,n=t.length;n>i;i++)for(var s=t[i],o=s.edges,r=0,a=o.length;a>r;r++){var h=o[r],d=null;h.from==s?d=h.to:h.to==s&&(d=h.from);var l,p;if(d)for(l=0,p=t.length;p>l;l++)if(t[l]==d){d=null;break}if(d)for(l=0,p=e.length;p>l;l++)if(e[l]==d){d=null;break}d&&e.push(d)}return e}void 0==t&&(t=1);var i=[],n=this.nodes;for(var s in n)if(n.hasOwnProperty(s)){for(var o=[n[s]],r=0;t>r;r++)o=o.concat(e(o));i.push(o)}for(var a=[],h=0,d=i.length;d>h;h++)a.push(i[h].length);return a},S.prototype.setSize=function(t,e){this.frame.style.width=t,this.frame.style.height=e,this.frame.canvas.style.width="100%",this.frame.canvas.style.height="100%",this.frame.canvas.width=this.frame.canvas.clientWidth,this.frame.canvas.height=this.frame.canvas.clientHeight},S.prototype._setNodes=function(t){var e=this.nodesData;if(t instanceof o||t instanceof r)this.nodesData=t;else if(t instanceof Array)this.nodesData=new o,this.nodesData.add(t);else{if(t)throw new TypeError("Array or DataSet expected");this.nodesData=new o}if(e&&O.forEach(this.nodesListeners,function(t,i){e.unsubscribe(i,t)}),this.nodes={},this.nodesData){var i=this;O.forEach(this.nodesListeners,function(t,e){i.nodesData.subscribe(e,t)});var n=this.nodesData.getIds();this._addNodes(n)}this._updateSelection()},S.prototype._addNodes=function(t){for(var e,i=0,n=t.length;n>i;i++){e=t[i];var s=this.nodesData.get(e),o=new E(s,this.images,this.groups,this.constants);if(this.nodes[e]=o,!o.isFixed()){var r=2*this.constants.edges.length,a=t.length,h=2*Math.PI*(i/a);o.x=r*Math.cos(h),o.y=r*Math.sin(h),this.moving=!0}}this._reconnectEdges(),this._updateValueRange(this.nodes)},S.prototype._updateNodes=function(t){for(var e=this.nodes,i=this.nodesData,n=0,s=t.length;s>n;n++){var o=t[n],r=e[o],a=i.get(o);r?r.setProperties(a,this.constants):(r=new E(properties,this.images,this.groups,this.constants),e[o]=r,r.isFixed()||(this.moving=!0))}this._reconnectEdges(),this._updateValueRange(e)},S.prototype._removeNodes=function(t){for(var e=this.nodes,i=0,n=t.length;n>i;i++){var s=t[i];delete e[s]}this._reconnectEdges(),this._updateSelection(),this._updateValueRange(e)},S.prototype._setEdges=function(t){var e=this.edgesData;if(t instanceof o||t instanceof r)this.edgesData=t;else if(t instanceof Array)this.edgesData=new o,this.edgesData.add(t);else{if(t)throw new TypeError("Array or DataSet expected");this.edgesData=new o}if(e&&O.forEach(this.edgesListeners,function(t,i){e.unsubscribe(i,t)}),this.edges={},this.edgesData){var i=this;O.forEach(this.edgesListeners,function(t,e){i.edgesData.subscribe(e,t)});var n=this.edgesData.getIds();this._addEdges(n)}this._reconnectEdges()},S.prototype._addEdges=function(t){for(var e=this.edges,i=this.edgesData,n=0,s=t.length;s>n;n++){var o=t[n],r=e[o];r&&r.disconnect();var a=i.get(o);e[o]=new T(a,this,this.constants)}this.moving=!0,this._updateValueRange(e)},S.prototype._updateEdges=function(t){for(var e=this.edges,i=this.edgesData,n=0,s=t.length;s>n;n++){var o=t[n],r=i.get(o),a=e[o];a?(a.disconnect(),a.setProperties(r,this.constants),a.connect()):(a=new T(r,this,this.constants),this.edges[o]=a)}this.moving=!0,this._updateValueRange(e)},S.prototype._removeEdges=function(t){for(var e=this.edges,i=0,n=t.length;n>i;i++){var s=t[i],o=e[s];o&&(o.disconnect(),delete e[s])}this.moving=!0,this._updateValueRange(e)},S.prototype._reconnectEdges=function(){var t,e=this.nodes,i=this.edges;for(t in e)e.hasOwnProperty(t)&&(e[t].edges=[]);for(t in i)if(i.hasOwnProperty(t)){var n=i[t];n.from=null,n.to=null,n.connect()}},S.prototype._updateValueRange=function(t){var e,i=void 0,n=void 0;for(e in t)if(t.hasOwnProperty(e)){var s=t[e].getValue();void 0!==s&&(i=void 0===i?s:Math.min(s,i),n=void 0===n?s:Math.max(s,n))}if(void 0!==i&&void 0!==n)for(e in t)t.hasOwnProperty(e)&&t[e].setValueRange(i,n)},S.prototype.redraw=function(){this.setSize(this.width,this.height),this._redraw()},S.prototype._redraw=function(){var t=this.frame.canvas.getContext("2d"),e=this.frame.canvas.width,i=this.frame.canvas.height;t.clearRect(0,0,e,i),t.save(),t.translate(this.translation.x,this.translation.y),t.scale(this.scale,this.scale),this._drawEdges(t),this._drawNodes(t),t.restore()},S.prototype._setTranslation=function(t,e){void 0===this.translation&&(this.translation={x:0,y:0}),void 0!==t&&(this.translation.x=t),void 0!==e&&(this.translation.y=e)},S.prototype._getTranslation=function(){return{x:this.translation.x,y:this.translation.y}},S.prototype._setScale=function(t){this.scale=t},S.prototype._getScale=function(){return this.scale},S.prototype._xToCanvas=function(t){return(t-this.translation.x)/this.scale},S.prototype._canvasToX=function(t){return t*this.scale+this.translation.x},S.prototype._yToCanvas=function(t){return(t-this.translation.y)/this.scale},S.prototype._canvasToY=function(t){return t*this.scale+this.translation.y},S.prototype._drawNodes=function(t){var e=this.nodes,i=[];for(var n in e)e.hasOwnProperty(n)&&(e[n].isSelected()?i.push(n):e[n].draw(t));for(var s=0,o=i.length;o>s;s++)e[i[s]].draw(t)},S.prototype._drawEdges=function(t){var e=this.edges;for(var i in e)if(e.hasOwnProperty(i)){var n=e[i];n.connected&&e[i].draw(t)}},S.prototype._doStabilize=function(){new Date;for(var t=0,e=this.constants.minVelocity,i=!1;!i&&this.constants.maxIterations>t;)this._calculateForces(),this._discreteStepNodes(),i=!this._isMoving(e),t++;new Date},S.prototype._calculateForces=function(){var t,e,i,n,s,o,r,a,h,d,l,p=this.nodes,c=this.edges,u=.01,f=this.frame.canvas.clientWidth/2,m=this.frame.canvas.clientHeight/2;for(t in p)if(p.hasOwnProperty(t)){var g=p[t];e=f-g.x,i=m-g.y,n=Math.atan2(i,e),o=Math.cos(n)*u,r=Math.sin(n)*u,g._setForce(o,r)}var v=this.constants.nodes.distance,y=10;for(var b in p)if(p.hasOwnProperty(b)){var w=p[b];for(var _ in p)if(p.hasOwnProperty(_)){var E=p[_];e=E.x-w.x,i=E.y-w.y,s=Math.sqrt(e*e+i*i),n=Math.atan2(i,e),a=1/(1+Math.exp((s/v-1)*y)),o=Math.cos(n)*a,r=Math.sin(n)*a,w._addForce(-o,-r),E._addForce(o,r)}}for(t in c)if(c.hasOwnProperty(t)){var T=c[t];T.connected&&(e=T.to.x-T.from.x,i=T.to.y-T.from.y,l=T.length,d=Math.sqrt(e*e+i*i),n=Math.atan2(i,e),h=T.stiffness*(l-d),o=Math.cos(n)*h,r=Math.sin(n)*h,T.from._addForce(-o,-r),T.to._addForce(o,r))}},S.prototype._isMoving=function(t){var e=this.nodes;for(var i in e)if(e.hasOwnProperty(i)&&e[i].isMoving(t))return!0;return!1},S.prototype._discreteStepNodes=function(){var t=this.refreshRate/1e3,e=this.nodes;for(var i in e)e.hasOwnProperty(i)&&e[i].discreteStep(t)},S.prototype.start=function(){if(this.moving){this._calculateForces(),this._discreteStepNodes();var t=this.constants.minVelocity;this.moving=this._isMoving(t)}if(this.moving){if(!this.timer){var e=this;this.timer=window.setTimeout(function(){e.timer=void 0,e.start(),e._redraw()},this.refreshRate)}}else this._redraw()},S.prototype.stop=function(){this.timer&&(window.clearInterval(this.timer),this.timer=void 0)};var k={util:O,events:L,Controller:d,DataSet:o,DataView:r,Range:h,Stack:a,TimeStep:TimeStep,EventBus:s,components:{items:{Item:m,ItemBox:g,ItemPoint:v,ItemRange:y},Component:l,Panel:p,RootPanel:c,ItemSet:f,TimeAxis:u},graph:{Node:E,Edge:T,Popup:x,Groups:Groups,Images:Images},Timeline:_,Graph:S};n!==void 0&&(n=k),i!==void 0&&i.exports!==void 0&&(i.exports=k),"function"==typeof t&&t(function(){return k}),"undefined"!=typeof window&&(window.vis=k),O.loadCss("/* vis.js stylesheet */\n.vis.timeline {\n}\n\n\n.vis.timeline.rootpanel {\n position: relative;\n overflow: hidden;\n\n border: 1px solid #bfbfbf;\n -moz-box-sizing: border-box;\n box-sizing: border-box;\n}\n\n.vis.timeline .panel {\n position: absolute;\n overflow: hidden;\n}\n\n\n.vis.timeline .groupset {\n position: absolute;\n padding: 0;\n margin: 0;\n}\n\n.vis.timeline .labels {\n position: absolute;\n top: 0;\n left: 0;\n width: 100%;\n height: 100%;\n\n padding: 0;\n margin: 0;\n\n border-right: 1px solid #bfbfbf;\n box-sizing: border-box;\n -moz-box-sizing: border-box;\n}\n\n.vis.timeline .labels .label {\n position: absolute;\n left: 0;\n top: 0;\n width: 100%;\n border-bottom: 1px solid #bfbfbf;\n color: #4d4d4d;\n}\n\n.vis.timeline .labels .label .inner {\n display: inline-block;\n padding: 5px;\n}\n\n\n.vis.timeline .itemset {\n position: absolute;\n padding: 0;\n margin: 0;\n overflow: hidden;\n}\n\n.vis.timeline .background {\n}\n\n.vis.timeline .foreground {\n}\n\n.vis.timeline .itemset-axis {\n position: absolute;\n}\n\n.vis.timeline .groupset .itemset-axis {\n border-top: 1px solid #bfbfbf;\n}\n\n/* TODO: with orientation=='bottom', this will more or less overlap with timeline axis\n.vis.timeline .groupset .itemset-axis:last-child {\n border-top: none;\n}\n*/\n\n\n.vis.timeline .item {\n position: absolute;\n color: #1A1A1A;\n border-color: #97B0F8;\n background-color: #D5DDF6;\n display: inline-block;\n}\n\n.vis.timeline .item.selected {\n border-color: #FFC200;\n background-color: #FFF785;\n z-index: 999;\n}\n\n.vis.timeline .item.cluster {\n /* TODO: use another color or pattern? */\n background: #97B0F8 url('img/cluster_bg.png');\n color: white;\n}\n.vis.timeline .item.cluster.point {\n border-color: #D5DDF6;\n}\n\n.vis.timeline .item.box {\n text-align: center;\n border-style: solid;\n border-width: 1px;\n border-radius: 5px;\n -moz-border-radius: 5px; /* For Firefox 3.6 and older */\n}\n\n.vis.timeline .item.point {\n background: none;\n}\n\n.vis.timeline .dot {\n border: 5px solid #97B0F8;\n position: absolute;\n border-radius: 5px;\n -moz-border-radius: 5px; /* For Firefox 3.6 and older */\n}\n\n.vis.timeline .item.range {\n overflow: hidden;\n border-style: solid;\n border-width: 1px;\n border-radius: 2px;\n -moz-border-radius: 2px; /* For Firefox 3.6 and older */\n}\n\n.vis.timeline .item.range .drag-left {\n cursor: w-resize;\n z-index: 1000;\n}\n\n.vis.timeline .item.range .drag-right {\n cursor: e-resize;\n z-index: 1000;\n}\n\n.vis.timeline .item.range .content {\n position: relative;\n display: inline-block;\n}\n\n.vis.timeline .item.line {\n position: absolute;\n width: 0;\n border-left-width: 1px;\n border-left-style: solid;\n}\n\n.vis.timeline .item .content {\n margin: 5px;\n white-space: nowrap;\n overflow: hidden;\n}\n\n.vis.timeline .axis {\n position: relative;\n}\n\n.vis.timeline .axis .text {\n position: absolute;\n color: #4d4d4d;\n padding: 3px;\n white-space: nowrap;\n}\n\n.vis.timeline .axis .text.measure {\n position: absolute;\n padding-left: 0;\n padding-right: 0;\n margin-left: 0;\n margin-right: 0;\n visibility: hidden;\n}\n\n.vis.timeline .axis .grid.vertical {\n position: absolute;\n width: 0;\n border-right: 1px solid;\n}\n\n.vis.timeline .axis .grid.horizontal {\n position: absolute;\n left: 0;\n width: 100%;\n height: 0;\n border-bottom: 1px solid;\n}\n\n.vis.timeline .axis .grid.minor {\n border-color: #e5e5e5;\n}\n\n.vis.timeline .axis .grid.major {\n border-color: #bfbfbf;\n}\n\n")},{hammerjs:1,moment:2}]},{},[3])(3)}); \ No newline at end of file From 0f19f6499ff4f6429f6a17cddc672d49567cacf4 Mon Sep 17 00:00:00 2001 From: josdejong Date: Tue, 17 Sep 2013 13:31:10 +0200 Subject: [PATCH 06/18] A fix in dragging nodes in the graph around --- src/graph/Graph.js | 4 ++-- vis.js | 4 ++-- vis.min.js | 2 +- 3 files changed, 5 insertions(+), 5 deletions(-) diff --git a/src/graph/Graph.js b/src/graph/Graph.js index 6e24f1b6..9b62cabe 100644 --- a/src/graph/Graph.js +++ b/src/graph/Graph.js @@ -428,11 +428,11 @@ Graph.prototype._onDrag = function (event) { var node = s.node; if (!s.xFixed) { - node.x = me._canvasToX(me._xToCanvas(s.x) + deltaX); + node.x = me._xToCanvas(me._canvasToX(s.x) + deltaX); } if (!s.yFixed) { - node.y = me._canvasToY(me._yToCanvas(s.y) + deltaY); + node.y = me._yToCanvas(me._canvasToY(s.y) + deltaY); } }); diff --git a/vis.js b/vis.js index 0983765b..9304828a 100644 --- a/vis.js +++ b/vis.js @@ -13281,11 +13281,11 @@ Graph.prototype._onDrag = function (event) { var node = s.node; if (!s.xFixed) { - node.x = me._canvasToX(me._xToCanvas(s.x) + deltaX); + node.x = me._xToCanvas(me._canvasToX(s.x) + deltaX); } if (!s.yFixed) { - node.y = me._canvasToY(me._yToCanvas(s.y) + deltaY); + node.y = me._yToCanvas(me._canvasToY(s.y) + deltaY); } }); diff --git a/vis.min.js b/vis.min.js index c0f6489b..3cc9e542 100644 --- a/vis.min.js +++ b/vis.min.js @@ -26,4 +26,4 @@ }this.subscribers={},this.internalIds={}}function r(t,e){this.id=O.randomUUID(),this.data=null,this.ids={},this.options=e||{},this.fieldId="id",this.subscribers={};var i=this;this.listener=function(){i._onEvent.apply(i,arguments)},this.setData(t)}function a(t,e){this.parent=t,this.options=e||{},this.defaultOptions={order:function(t,e){if(t instanceof y){if(e instanceof y){var i=t.data.end-t.data.start,n=e.data.end-e.data.start;return i-n||t.data.start-e.data.start}return-1}return e instanceof y?1:t.data.start-e.data.start},margin:{item:10}},this.ordered=[]}function h(t){this.id=O.randomUUID(),this.start=0,this.end=0,this.options={min:null,max:null,zoomMin:null,zoomMax:null},this.listeners=[],this.setOptions(t)}function d(){this.id=O.randomUUID(),this.components={},this.repaintTimer=void 0,this.reflowTimer=void 0}function l(){this.id=null,this.parent=null,this.depends=null,this.controller=null,this.options=null,this.frame=null,this.top=0,this.left=0,this.width=0,this.height=0}function p(t,e,i){this.id=O.randomUUID(),this.parent=t,this.depends=e,this.options=i||{}}function c(t,e){this.id=O.randomUUID(),this.container=t,this.options=e||{},this.defaultOptions={autoResize:!0},this.listeners={}}function u(t,e,i){this.id=O.randomUUID(),this.parent=t,this.depends=e,this.dom={majorLines:[],majorTexts:[],minorLines:[],minorTexts:[],redundant:{majorLines:[],majorTexts:[],minorLines:[],minorTexts:[]}},this.props={range:{start:0,end:0,minimumStep:0},lineTop:0},this.options=i||{},this.defaultOptions={orientation:"bottom",showMinorLabels:!0,showMajorLabels:!0},this.conversion=null,this.range=null}function f(t,e,i){this.id=O.randomUUID(),this.parent=t,this.depends=e,this.options=i||{},this.defaultOptions={type:"box",align:"center",orientation:"bottom",margin:{axis:20,item:10},padding:5},this.dom={};var n=this;this.itemsData=null,this.range=null,this.listeners={add:function(t,e,i){i!=n.id&&n._onAdd(e.items)},update:function(t,e,i){i!=n.id&&n._onUpdate(e.items)},remove:function(t,e,i){i!=n.id&&n._onRemove(e.items)}},this.items={},this.queue={},this.stack=new a(this,Object.create(this.options)),this.conversion=null}function m(t,e,i,n){this.parent=t,this.data=e,this.dom=null,this.options=i||{},this.defaultOptions=n||{},this.selected=!1,this.visible=!1,this.top=0,this.left=0,this.width=0,this.height=0}function g(t,e,i,n){this.props={dot:{left:0,top:0,width:0,height:0},line:{top:0,left:0,width:0,height:0}},m.call(this,t,e,i,n)}function v(t,e,i,n){this.props={dot:{top:0,width:0,height:0},content:{height:0,marginLeft:0}},m.call(this,t,e,i,n)}function y(t,e,i,n){this.props={content:{left:0,width:0}},m.call(this,t,e,i,n)}function b(t,e,i){this.id=O.randomUUID(),this.parent=t,this.groupId=e,this.itemset=null,this.options=i||{},this.options.top=0,this.props={label:{width:0,height:0}},this.top=0,this.left=0,this.width=0,this.height=0}function w(t,e,i){this.id=O.randomUUID(),this.parent=t,this.depends=e,this.options=i||{},this.range=null,this.itemsData=null,this.groupsData=null,this.groups={},this.dom={},this.props={labels:{width:0}},this.queue={};var n=this;this.listeners={add:function(t,e){n._onAdd(e.items)},update:function(t,e){n._onUpdate(e.items)},remove:function(t,e){n._onRemove(e.items)}}}function _(t,e,i){var n=this;if(this.options=O.extend({orientation:"bottom",min:null,max:null,zoomMin:10,zoomMax:31536e10,showMinorLabels:!0,showMajorLabels:!0,autoResize:!1},i),this.controller=new d,!t)throw Error("No container element provided");var s=Object.create(this.options);s.height=function(){return n.options.height?n.options.height:n.timeaxis.height+n.content.height},this.rootPanel=new c(t,s),this.controller.add(this.rootPanel);var o=Object.create(this.options);o.left=function(){return n.labelPanel.width},o.width=function(){return n.rootPanel.width-n.labelPanel.width},o.top=null,o.height=null,this.itemPanel=new p(this.rootPanel,[],o),this.controller.add(this.itemPanel);var r=Object.create(this.options);r.top=null,r.left=null,r.height=null,r.width=function(){return n.content&&"function"==typeof n.content.getLabelsWidth?n.content.getLabelsWidth():0},this.labelPanel=new p(this.rootPanel,[],r),this.controller.add(this.labelPanel);var a=M().hours(0).minutes(0).seconds(0).milliseconds(0);this.range=new h({start:a.clone().add("days",-3).valueOf(),end:a.clone().add("days",4).valueOf()}),this.range.subscribe(this.rootPanel,"move","horizontal"),this.range.subscribe(this.rootPanel,"zoom","horizontal"),this.range.on("rangechange",function(){var t=!0;n.controller.requestReflow(t)}),this.range.on("rangechanged",function(){var t=!0;n.controller.requestReflow(t)});var l=Object.create(s);l.range=this.range,l.left=null,l.top=null,l.width="100%",l.height=null,this.timeaxis=new u(this.itemPanel,[],l),this.timeaxis.setRange(this.range),this.controller.add(this.timeaxis),this.setGroups(null),this.itemsData=null,this.groupsData=null,e&&this.setItems(e)}function E(t,e,i,n){this.selected=!1,this.edges=[],this.group=n.nodes.group,this.fontSize=n.nodes.fontSize,this.fontFace=n.nodes.fontFace,this.fontColor=n.nodes.fontColor,this.color=n.nodes.color,this.id=void 0,this.shape=n.nodes.shape,this.image=n.nodes.image,this.x=0,this.y=0,this.xFixed=!1,this.yFixed=!1,this.radius=n.nodes.radius,this.radiusFixed=!1,this.radiusMin=n.nodes.radiusMin,this.radiusMax=n.nodes.radiusMax,this.imagelist=e,this.grouplist=i,this.setProperties(t,n),this.mass=50,this.fx=0,this.fy=0,this.vx=0,this.vy=0,this.minForce=n.minForce,this.damping=.9}function T(t,e,i){if(!e)throw"No graph provided";this.graph=e,this.widthMin=i.edges.widthMin,this.widthMax=i.edges.widthMax,this.id=void 0,this.fromId=void 0,this.toId=void 0,this.style=i.edges.style,this.title=void 0,this.width=i.edges.width,this.value=void 0,this.length=i.edges.length,this.from=null,this.to=null,this.connected=!1,this.dash=O.extend({},i.edges.dash),this.stiffness=void 0,this.color=i.edges.color,this.widthFixed=!1,this.lengthFixed=!1,this.setProperties(t,i)}function x(t,e,i,n){this.container=t?t:document.body,this.x=0,this.y=0,this.padding=5,void 0!==e&&void 0!==i&&this.setPosition(e,i),void 0!==n&&this.setText(n),this.frame=document.createElement("div");var s=this.frame.style;s.position="absolute",s.visibility="hidden",s.border="1px solid #666",s.color="black",s.padding=this.padding+"px",s.backgroundColor="#FFFFC6",s.borderRadius="3px",s.MozBorderRadius="3px",s.WebkitBorderRadius="3px",s.boxShadow="3px 3px 10px rgba(128, 128, 128, 0.5)",s.whiteSpace="nowrap",this.container.appendChild(this.frame)}function S(t,e,i){this.containerElement=t,this.width="100%",this.height="100%",this.refreshRate=50,this.stabilize=!0,this.selectable=!0,this.constants={nodes:{radiusMin:5,radiusMax:20,radius:5,distance:100,shape:"ellipse",image:void 0,widthMin:16,widthMax:64,fontColor:"black",fontSize:14,fontFace:"arial",color:{border:"#2B7CE9",background:"#97C2FC",highlight:{border:"#2B7CE9",background:"#D2E5FF"}},borderColor:"#2B7CE9",backgroundColor:"#97C2FC",highlightColor:"#D2E5FF",group:void 0},edges:{widthMin:1,widthMax:15,width:1,style:"line",color:"#343434",fontColor:"#343434",fontSize:14,fontFace:"arial",length:100,dash:{length:10,gap:5,altLength:void 0}},minForce:.05,minVelocity:.02,maxIterations:1e3};var n=this;this.nodes={},this.edges={},this.nodesData=null,this.edgesData=null;var s=this;this.nodesListeners={add:function(t,e){s._addNodes(e.items),s.start()},update:function(t,e){s._updateNodes(e.items),s.start()},remove:function(t,e){s._removeNodes(e.items),s.start()}},this.edgesListeners={add:function(t,e){s._addEdges(e.items),s.start()},update:function(t,e){s._updateEdges(e.items),s.start()},remove:function(t,e){s._removeEdges(e.items),s.start()}},this.groups=new Groups,this.images=new Images,this.images.setOnloadCallback(function(){n._redraw()}),this.moving=!1,this.selection=[],this.timer=void 0,this._create(),this.setOptions(i),this.setData(e)}var M="undefined"!=typeof window&&window.moment||e("moment"),D="undefined"!=typeof window&&window.Hammer||e("hammerjs");if(!Array.prototype.indexOf){Array.prototype.indexOf=function(t){for(var e=0;this.length>e;e++)if(this[e]==t)return e;return-1};try{console.log("Warning: Ancient browser detected. Please update your browser")}catch(C){}}Array.prototype.forEach||(Array.prototype.forEach=function(t,e){for(var i=0,n=this.length;n>i;++i)t.call(e||this,this[i],i,this)}),Array.prototype.map||(Array.prototype.map=function(t,e){var i,n,s;if(null==this)throw new TypeError(" this is null or not defined");var o=Object(this),r=o.length>>>0;if("function"!=typeof t)throw new TypeError(t+" is not a function");for(e&&(i=e),n=Array(r),s=0;r>s;){var a,h;s in o&&(a=o[s],h=t.call(i,a,s,o),n[s]=h),s++}return n}),Array.prototype.filter||(Array.prototype.filter=function(t){"use strict";if(null==this)throw new TypeError;var e=Object(this),i=e.length>>>0;if("function"!=typeof t)throw new TypeError;for(var n=[],s=arguments[1],o=0;i>o;o++)if(o in e){var r=e[o];t.call(s,r,o,e)&&n.push(r)}return n}),Object.keys||(Object.keys=function(){var t=Object.prototype.hasOwnProperty,e=!{toString:null}.propertyIsEnumerable("toString"),i=["toString","toLocaleString","valueOf","hasOwnProperty","isPrototypeOf","propertyIsEnumerable","constructor"],n=i.length;return function(s){if("object"!=typeof s&&"function"!=typeof s||null===s)throw new TypeError("Object.keys called on non-object");var o=[];for(var r in s)t.call(s,r)&&o.push(r);if(e)for(var a=0;n>a;a++)t.call(s,i[a])&&o.push(i[a]);return o}}()),Array.isArray||(Array.isArray=function(t){return"[object Array]"===Object.prototype.toString.call(t)}),Function.prototype.bind||(Function.prototype.bind=function(t){if("function"!=typeof this)throw new TypeError("Function.prototype.bind - what is trying to be bound is not callable");var e=Array.prototype.slice.call(arguments,1),i=this,n=function(){},s=function(){return i.apply(this instanceof n&&t?this:t,e.concat(Array.prototype.slice.call(arguments)))};return n.prototype=this.prototype,s.prototype=new n,s}),Object.create||(Object.create=function(t){function e(){}if(arguments.length>1)throw Error("Object.create implementation only accepts the first parameter.");return e.prototype=t,new e}),Function.prototype.bind||(Function.prototype.bind=function(t){if("function"!=typeof this)throw new TypeError("Function.prototype.bind - what is trying to be bound is not callable");var e=Array.prototype.slice.call(arguments,1),i=this,n=function(){},s=function(){return i.apply(this instanceof n&&t?this:t,e.concat(Array.prototype.slice.call(arguments)))};return n.prototype=this.prototype,s.prototype=new n,s});var O={};O.isNumber=function(t){return t instanceof Number||"number"==typeof t},O.isString=function(t){return t instanceof String||"string"==typeof t},O.isDate=function(t){if(t instanceof Date)return!0;if(O.isString(t)){var e=N.exec(t);if(e)return!0;if(!isNaN(Date.parse(t)))return!0}return!1},O.isDataTable=function(t){return"undefined"!=typeof google&&google.visualization&&google.visualization.DataTable&&t instanceof google.visualization.DataTable},O.randomUUID=function(){var t=function(){return Math.floor(65536*Math.random()).toString(16)};return t()+t()+"-"+t()+"-"+t()+"-"+t()+"-"+t()+t()+t()},O.extend=function(t){for(var e=1,i=arguments.length;i>e;e++){var n=arguments[e];for(var s in n)n.hasOwnProperty(s)&&void 0!==n[s]&&(t[s]=n[s])}return t},O.convert=function(t,e){var i;if(void 0===t)return void 0;if(null===t)return null;if(!e)return t;if("string"!=typeof e&&!(e instanceof String))throw Error("Type must be a string");switch(e){case"boolean":case"Boolean":return Boolean(t);case"number":case"Number":return Number(t.valueOf());case"string":case"String":return t+"";case"Date":if(O.isNumber(t))return new Date(t);if(t instanceof Date)return new Date(t.valueOf());if(M.isMoment(t))return new Date(t.valueOf());if(O.isString(t))return i=N.exec(t),i?new Date(Number(i[1])):M(t).toDate();throw Error("Cannot convert object of type "+O.getType(t)+" to type Date");case"Moment":if(O.isNumber(t))return M(t);if(t instanceof Date)return M(t.valueOf());if(M.isMoment(t))return M.clone();if(O.isString(t))return i=N.exec(t),i?M(Number(i[1])):M(t);throw Error("Cannot convert object of type "+O.getType(t)+" to type Date");case"ISODate":if(O.isNumber(t))return new Date(t);if(t instanceof Date)return t.toISOString();if(M.isMoment(t))return t.toDate().toISOString();if(O.isString(t))return i=N.exec(t),i?new Date(Number(i[1])).toISOString():new Date(t).toISOString();throw Error("Cannot convert object of type "+O.getType(t)+" to type ISODate");case"ASPDate":if(O.isNumber(t))return"/Date("+t+")/";if(t instanceof Date)return"/Date("+t.valueOf()+")/";if(O.isString(t)){i=N.exec(t);var n;return n=i?new Date(Number(i[1])).valueOf():new Date(t).valueOf(),"/Date("+n+")/"}throw Error("Cannot convert object of type "+O.getType(t)+" to type ASPDate");default:throw Error("Cannot convert object of type "+O.getType(t)+' to type "'+e+'"')}};var N=/^\/?Date\((\-?\d+)/i;O.getType=function(t){var e=typeof t;return"object"==e?null==t?"null":t instanceof Boolean?"Boolean":t instanceof Number?"Number":t instanceof String?"String":t instanceof Array?"Array":t instanceof Date?"Date":"Object":"number"==e?"Number":"boolean"==e?"Boolean":"string"==e?"String":e},O.getAbsoluteLeft=function(t){for(var e=document.documentElement,i=document.body,n=t.offsetLeft,s=t.offsetParent;null!=s&&s!=i&&s!=e;)n+=s.offsetLeft,n-=s.scrollLeft,s=s.offsetParent;return n},O.getAbsoluteTop=function(t){for(var e=document.documentElement,i=document.body,n=t.offsetTop,s=t.offsetParent;null!=s&&s!=i&&s!=e;)n+=s.offsetTop,n-=s.scrollTop,s=s.offsetParent;return n},O.getPageY=function(t){if("pageY"in t)return t.pageY;var e;e="targetTouches"in t&&t.targetTouches.length?t.targetTouches[0].clientY:t.clientY;var i=document.documentElement,n=document.body;return e+(i&&i.scrollTop||n&&n.scrollTop||0)-(i&&i.clientTop||n&&n.clientTop||0)},O.getPageX=function(t){if("pageY"in t)return t.pageX;var e;e="targetTouches"in t&&t.targetTouches.length?t.targetTouches[0].clientX:t.clientX;var i=document.documentElement,n=document.body;return e+(i&&i.scrollLeft||n&&n.scrollLeft||0)-(i&&i.clientLeft||n&&n.clientLeft||0)},O.addClassName=function(t,e){var i=t.className.split(" ");-1==i.indexOf(e)&&(i.push(e),t.className=i.join(" "))},O.removeClassName=function(t,e){var i=t.className.split(" "),n=i.indexOf(e);-1!=n&&(i.splice(n,1),t.className=i.join(" "))},O.forEach=function(t,e){var i,n;if(t instanceof Array)for(i=0,n=t.length;n>i;i++)e(t[i],i,t);else for(i in t)t.hasOwnProperty(i)&&e(t[i],i,t)},O.updateProperty=function(t,e,i){return t[e]!==i?(t[e]=i,!0):!1},O.addEventListener=function(t,e,i,n){t.addEventListener?(void 0===n&&(n=!1),"mousewheel"===e&&navigator.userAgent.indexOf("Firefox")>=0&&(e="DOMMouseScroll"),t.addEventListener(e,i,n)):t.attachEvent("on"+e,i)},O.removeEventListener=function(t,e,i,n){t.removeEventListener?(void 0===n&&(n=!1),"mousewheel"===e&&navigator.userAgent.indexOf("Firefox")>=0&&(e="DOMMouseScroll"),t.removeEventListener(e,i,n)):t.detachEvent("on"+e,i)},O.getTarget=function(t){t||(t=window.event);var e;return t.target?e=t.target:t.srcElement&&(e=t.srcElement),void 0!=e.nodeType&&3==e.nodeType&&(e=e.parentNode),e},O.stopPropagation=function(t){t||(t=window.event),t.stopPropagation?t.stopPropagation():t.cancelBubble=!0},O.preventDefault=function(t){t||(t=window.event),t.preventDefault?t.preventDefault():t.returnValue=!1},O.option={},O.option.asBoolean=function(t,e){return"function"==typeof t&&(t=t()),null!=t?0!=t:e||null},O.option.asNumber=function(t,e){return"function"==typeof t&&(t=t()),null!=t?Number(t)||e||null:e||null},O.option.asString=function(t,e){return"function"==typeof t&&(t=t()),null!=t?t+"":e||null},O.option.asSize=function(t,e){return"function"==typeof t&&(t=t()),O.isString(t)?t:O.isNumber(t)?t+"px":e||null},O.option.asElement=function(t,e){return"function"==typeof t&&(t=t()),t||e||null},O.loadCss=function(t){if("undefined"!=typeof document){var e=document.createElement("style");e.type="text/css",e.styleSheet?e.styleSheet.cssText=t:e.appendChild(document.createTextNode(t)),document.getElementsByTagName("head")[0].appendChild(e)}};var L={listeners:[],indexOf:function(t){for(var e=this.listeners,i=0,n=this.listeners.length;n>i;i++){var s=e[i];if(s&&s.object==t)return i}return-1},addListener:function(t,e,i){var n=this.indexOf(t),s=this.listeners[n];s||(s={object:t,events:{}},this.listeners.push(s));var o=s.events[e];o||(o=[],s.events[e]=o),-1==o.indexOf(i)&&o.push(i)},removeListener:function(t,e,i){var n=this.indexOf(t),s=this.listeners[n];if(s){var o=s.events[e];o&&(n=o.indexOf(i),-1!=n&&o.splice(n,1),0==o.length&&delete s.events[e]);var r=0,a=s.events;for(var h in a)a.hasOwnProperty(h)&&r++;0==r&&delete this.listeners[n]}},removeAllListeners:function(){this.listeners=[]},trigger:function(t,e,i){var n=this.indexOf(t),s=this.listeners[n];if(s){var o=s.events[e];if(o)for(var r=0,a=o.length;a>r;r++)o[r](i)}}};s.prototype.on=function(t,e,i){var n=t instanceof RegExp?t:RegExp(t.replace("*","\\w+")),s={id:O.randomUUID(),event:t,regexp:n,callback:"function"==typeof e?e:null,target:i};return this.subscriptions.push(s),s.id},s.prototype.off=function(t){for(var e=0;this.subscriptions.length>e;){var i=this.subscriptions[e],n=!0;if(t instanceof Object)for(var s in t)t.hasOwnProperty(s)&&t[s]!==i[s]&&(n=!1);else n=i.id==t;n?this.subscriptions.splice(e,1):e++}},s.prototype.emit=function(t,e,i){for(var n=0;this.subscriptions.length>n;n++){var s=this.subscriptions[n];s.regexp.test(t)&&s.callback&&s.callback(t,e,i)}},o.prototype.subscribe=function(t,e){var i=this.subscribers[t];i||(i=[],this.subscribers[t]=i),i.push({callback:e})},o.prototype.unsubscribe=function(t,e){var i=this.subscribers[t];i&&(this.subscribers[t]=i.filter(function(t){return t.callback!=e}))},o.prototype._trigger=function(t,e,i){if("*"==t)throw Error("Cannot trigger event *");var n=[];t in this.subscribers&&(n=n.concat(this.subscribers[t])),"*"in this.subscribers&&(n=n.concat(this.subscribers["*"]));for(var s=0;n.length>s;s++){var o=n[s];o.callback&&o.callback(t,e,i||null)}},o.prototype.add=function(t,e){var i,n=[],s=this;if(t instanceof Array)for(var o=0,r=t.length;r>o;o++)i=s._addItem(t[o]),n.push(i);else if(O.isDataTable(t))for(var a=this._getColumnNames(t),h=0,d=t.getNumberOfRows();d>h;h++){for(var l={},p=0,c=a.length;c>p;p++){var u=a[p];l[u]=t.getValue(h,p)}i=s._addItem(l),n.push(i)}else{if(!(t instanceof Object))throw Error("Unknown dataType");i=s._addItem(t),n.push(i)}return n.length&&this._trigger("add",{items:n},e),n},o.prototype.update=function(t,e){var i=[],n=[],s=this,o=s.fieldId,r=function(t){var e=t[o];s.data[e]?(e=s._updateItem(t),n.push(e)):(e=s._addItem(t),i.push(e))};if(t instanceof Array)for(var a=0,h=t.length;h>a;a++)r(t[a]);else if(O.isDataTable(t))for(var d=this._getColumnNames(t),l=0,p=t.getNumberOfRows();p>l;l++){for(var c={},u=0,f=d.length;f>u;u++){var m=d[u];c[m]=t.getValue(l,u)}r(c)}else{if(!(t instanceof Object))throw Error("Unknown dataType");r(t)}return i.length&&this._trigger("add",{items:i},e),n.length&&this._trigger("update",{items:n},e),i.concat(n)},o.prototype.get=function(){var t,e,i,n,s=this,o=O.getType(arguments[0]);"String"==o||"Number"==o?(t=arguments[0],i=arguments[1],n=arguments[2]):"Array"==o?(e=arguments[0],i=arguments[1],n=arguments[2]):(i=arguments[0],n=arguments[1]);var r;if(i&&i.type){if(r="DataTable"==i.type?"DataTable":"Array",n&&r!=O.getType(n))throw Error('Type of parameter "data" ('+O.getType(n)+") "+"does not correspond with specified options.type ("+i.type+")");if("DataTable"==r&&!O.isDataTable(n))throw Error('Parameter "data" must be a DataTable when options.type is "DataTable"')}else r=n?"DataTable"==O.getType(n)?"DataTable":"Array":"Array";var a,h,d,l,p=i&&i.convert||this.options.convert,c=i&&i.filter,u=[];if(void 0!=t)a=s._getItem(t,p),c&&!c(a)&&(a=null);else if(void 0!=e)for(d=0,l=e.length;l>d;d++)a=s._getItem(e[d],p),(!c||c(a))&&u.push(a);else for(h in this.data)this.data.hasOwnProperty(h)&&(a=s._getItem(h,p),(!c||c(a))&&u.push(a));if(i&&i.order&&void 0==t&&this._sort(u,i.order),i&&i.fields){var f=i.fields;if(void 0!=t)a=this._filterFields(a,f);else for(d=0,l=u.length;l>d;d++)u[d]=this._filterFields(u[d],f)}if("DataTable"==r){var m=this._getColumnNames(n);if(void 0!=t)s._appendRow(n,m,a);else for(d=0,l=u.length;l>d;d++)s._appendRow(n,m,u[d]);return n}if(void 0!=t)return a;if(n){for(d=0,l=u.length;l>d;d++)n.push(u[d]);return n}return u},o.prototype.getIds=function(t){var e,i,n,s,o,r=this.data,a=t&&t.filter,h=t&&t.order,d=t&&t.convert||this.options.convert,l=[];if(a)if(h){o=[];for(n in r)r.hasOwnProperty(n)&&(s=this._getItem(n,d),a(s)&&o.push(s));for(this._sort(o,h),e=0,i=o.length;i>e;e++)l[e]=o[e][this.fieldId]}else for(n in r)r.hasOwnProperty(n)&&(s=this._getItem(n,d),a(s)&&l.push(s[this.fieldId]));else if(h){o=[];for(n in r)r.hasOwnProperty(n)&&o.push(r[n]);for(this._sort(o,h),e=0,i=o.length;i>e;e++)l[e]=o[e][this.fieldId]}else for(n in r)r.hasOwnProperty(n)&&(s=r[n],l.push(s[this.fieldId]));return l},o.prototype.forEach=function(t,e){var i,n,s=e&&e.filter,o=e&&e.convert||this.options.convert,r=this.data;if(e&&e.order)for(var a=this.get(e),h=0,d=a.length;d>h;h++)i=a[h],n=i[this.fieldId],t(i,n);else for(n in r)r.hasOwnProperty(n)&&(i=this._getItem(n,o),(!s||s(i))&&t(i,n))},o.prototype.map=function(t,e){var i,n=e&&e.filter,s=e&&e.convert||this.options.convert,o=[],r=this.data;for(var a in r)r.hasOwnProperty(a)&&(i=this._getItem(a,s),(!n||n(i))&&o.push(t(i,a)));return e&&e.order&&this._sort(o,e.order),o},o.prototype._filterFields=function(t,e){var i={};for(var n in t)t.hasOwnProperty(n)&&-1!=e.indexOf(n)&&(i[n]=t[n]);return i},o.prototype._sort=function(t,e){if(O.isString(e)){var i=e;t.sort(function(t,e){var n=t[i],s=e[i];return n>s?1:s>n?-1:0})}else{if("function"!=typeof e)throw new TypeError("Order must be a function or a string");t.sort(e)}},o.prototype.remove=function(t,e){var i,n,s,o=[];if(t instanceof Array)for(i=0,n=t.length;n>i;i++)s=this._remove(t[i]),null!=s&&o.push(s);else s=this._remove(t),null!=s&&o.push(s);return o.length&&this._trigger("remove",{items:o},e),o},o.prototype._remove=function(t){if(O.isNumber(t)||O.isString(t)){if(this.data[t])return delete this.data[t],delete this.internalIds[t],t}else if(t instanceof Object){var e=t[this.fieldId];if(e&&this.data[e])return delete this.data[e],delete this.internalIds[e],e}return null},o.prototype.clear=function(t){var e=Object.keys(this.data);return this.data={},this.internalIds={},this._trigger("remove",{items:e},t),e},o.prototype.max=function(t){var e=this.data,i=null,n=null;for(var s in e)if(e.hasOwnProperty(s)){var o=e[s],r=o[t];null!=r&&(!i||r>n)&&(i=o,n=r)}return i},o.prototype.min=function(t){var e=this.data,i=null,n=null;for(var s in e)if(e.hasOwnProperty(s)){var o=e[s],r=o[t];null!=r&&(!i||n>r)&&(i=o,n=r)}return i},o.prototype.distinct=function(t){var e=this.data,i=[],n=this.options.convert[t],s=0;for(var o in e)if(e.hasOwnProperty(o)){for(var r=e[o],a=O.convert(r[t],n),h=!1,d=0;s>d;d++)if(i[d]==a){h=!0;break}h||(i[s]=a,s++)}return i},o.prototype._addItem=function(t){var e=t[this.fieldId];if(void 0!=e){if(this.data[e])throw Error("Cannot add item: item with id "+e+" already exists")}else e=O.randomUUID(),t[this.fieldId]=e,this.internalIds[e]=t;var i={};for(var n in t)if(t.hasOwnProperty(n)){var s=this.convert[n];i[n]=O.convert(t[n],s)}return this.data[e]=i,e},o.prototype._getItem=function(t,e){var i,n,s=this.data[t];if(!s)return null;var o={},r=this.fieldId,a=this.internalIds;if(e)for(i in s)s.hasOwnProperty(i)&&(n=s[i],i==r&&n in a||(o[i]=O.convert(n,e[i])));else for(i in s)s.hasOwnProperty(i)&&(n=s[i],i==r&&n in a||(o[i]=n));return o},o.prototype._updateItem=function(t){var e=t[this.fieldId];if(void 0==e)throw Error("Cannot update item: item has no id (item: "+JSON.stringify(t)+")");var i=this.data[e];if(!i)throw Error("Cannot update item: no item with id "+e+" found");for(var n in t)if(t.hasOwnProperty(n)){var s=this.convert[n];i[n]=O.convert(t[n],s)}return e},o.prototype._getColumnNames=function(t){for(var e=[],i=0,n=t.getNumberOfColumns();n>i;i++)e[i]=t.getColumnId(i)||t.getColumnLabel(i);return e},o.prototype._appendRow=function(t,e,i){for(var n=t.addRow(),s=0,o=e.length;o>s;s++){var r=e[s];t.setValue(n,s,i[r])}},r.prototype.setData=function(t){var e,i,n;if(this.data){this.data.unsubscribe&&this.data.unsubscribe("*",this.listener),e=[];for(var s in this.ids)this.ids.hasOwnProperty(s)&&e.push(s);this.ids={},this._trigger("remove",{items:e})}if(this.data=t,this.data){for(this.fieldId=this.options.fieldId||this.data&&this.data.options&&this.data.options.fieldId||"id",e=this.data.getIds({filter:this.options&&this.options.filter}),i=0,n=e.length;n>i;i++)s=e[i],this.ids[s]=!0;this._trigger("add",{items:e}),this.data.subscribe&&this.data.subscribe("*",this.listener)}},r.prototype.get=function(){var t,e,i,n=this,s=O.getType(arguments[0]);"String"==s||"Number"==s||"Array"==s?(t=arguments[0],e=arguments[1],i=arguments[2]):(e=arguments[0],i=arguments[1]);var o=O.extend({},this.options,e);this.options.filter&&e&&e.filter&&(o.filter=function(t){return n.options.filter(t)&&e.filter(t)});var r=[];return void 0!=t&&r.push(t),r.push(o),r.push(i),this.data&&this.data.get.apply(this.data,r)},r.prototype.getIds=function(t){var e;if(this.data){var i,n=this.options.filter;i=t&&t.filter?n?function(e){return n(e)&&t.filter(e)}:t.filter:n,e=this.data.getIds({filter:i,order:t&&t.order})}else e=[];return e},r.prototype._onEvent=function(t,e,i){var n,s,o,r,a=e&&e.items,h=this.data,d=[],l=[],p=[];if(a&&h){switch(t){case"add":for(n=0,s=a.length;s>n;n++)o=a[n],r=this.get(o),r&&(this.ids[o]=!0,d.push(o));break;case"update":for(n=0,s=a.length;s>n;n++)o=a[n],r=this.get(o),r?this.ids[o]?l.push(o):(this.ids[o]=!0,d.push(o)):this.ids[o]&&(delete this.ids[o],p.push(o));break;case"remove":for(n=0,s=a.length;s>n;n++)o=a[n],this.ids[o]&&(delete this.ids[o],p.push(o))}d.length&&this._trigger("add",{items:d},i),l.length&&this._trigger("update",{items:l},i),p.length&&this._trigger("remove",{items:p},i)}},r.prototype.subscribe=o.prototype.subscribe,r.prototype.unsubscribe=o.prototype.unsubscribe,r.prototype._trigger=o.prototype._trigger,TimeStep=function(t,e,i){this.current=new Date,this._start=new Date,this._end=new Date,this.autoScale=!0,this.scale=TimeStep.SCALE.DAY,this.step=1,this.setRange(t,e,i)},TimeStep.SCALE={MILLISECOND:1,SECOND:2,MINUTE:3,HOUR:4,DAY:5,WEEKDAY:6,MONTH:7,YEAR:8},TimeStep.prototype.setRange=function(t,e,i){t instanceof Date&&e instanceof Date&&(this._start=void 0!=t?new Date(t.valueOf()):new Date,this._end=void 0!=e?new Date(e.valueOf()):new Date,this.autoScale&&this.setMinimumStep(i))},TimeStep.prototype.first=function(){this.current=new Date(this._start.valueOf()),this.roundToMinor()},TimeStep.prototype.roundToMinor=function(){switch(this.scale){case TimeStep.SCALE.YEAR:this.current.setFullYear(this.step*Math.floor(this.current.getFullYear()/this.step)),this.current.setMonth(0);case TimeStep.SCALE.MONTH:this.current.setDate(1);case TimeStep.SCALE.DAY:case TimeStep.SCALE.WEEKDAY:this.current.setHours(0);case TimeStep.SCALE.HOUR:this.current.setMinutes(0);case TimeStep.SCALE.MINUTE:this.current.setSeconds(0);case TimeStep.SCALE.SECOND:this.current.setMilliseconds(0)}if(1!=this.step)switch(this.scale){case TimeStep.SCALE.MILLISECOND:this.current.setMilliseconds(this.current.getMilliseconds()-this.current.getMilliseconds()%this.step);break;case TimeStep.SCALE.SECOND:this.current.setSeconds(this.current.getSeconds()-this.current.getSeconds()%this.step);break;case TimeStep.SCALE.MINUTE:this.current.setMinutes(this.current.getMinutes()-this.current.getMinutes()%this.step);break;case TimeStep.SCALE.HOUR:this.current.setHours(this.current.getHours()-this.current.getHours()%this.step);break;case TimeStep.SCALE.WEEKDAY:case TimeStep.SCALE.DAY:this.current.setDate(this.current.getDate()-1-(this.current.getDate()-1)%this.step+1);break;case TimeStep.SCALE.MONTH:this.current.setMonth(this.current.getMonth()-this.current.getMonth()%this.step);break;case TimeStep.SCALE.YEAR:this.current.setFullYear(this.current.getFullYear()-this.current.getFullYear()%this.step);break;default:}},TimeStep.prototype.hasNext=function(){return this.current.valueOf()<=this._end.valueOf()},TimeStep.prototype.next=function(){var t=this.current.valueOf();if(6>this.current.getMonth())switch(this.scale){case TimeStep.SCALE.MILLISECOND:this.current=new Date(this.current.valueOf()+this.step);break;case TimeStep.SCALE.SECOND:this.current=new Date(this.current.valueOf()+1e3*this.step);break;case TimeStep.SCALE.MINUTE:this.current=new Date(this.current.valueOf()+60*1e3*this.step);break;case TimeStep.SCALE.HOUR:this.current=new Date(this.current.valueOf()+60*60*1e3*this.step);var e=this.current.getHours();this.current.setHours(e-e%this.step);break;case TimeStep.SCALE.WEEKDAY:case TimeStep.SCALE.DAY:this.current.setDate(this.current.getDate()+this.step);break;case TimeStep.SCALE.MONTH:this.current.setMonth(this.current.getMonth()+this.step);break;case TimeStep.SCALE.YEAR:this.current.setFullYear(this.current.getFullYear()+this.step);break;default:}else switch(this.scale){case TimeStep.SCALE.MILLISECOND:this.current=new Date(this.current.valueOf()+this.step);break;case TimeStep.SCALE.SECOND:this.current.setSeconds(this.current.getSeconds()+this.step);break;case TimeStep.SCALE.MINUTE:this.current.setMinutes(this.current.getMinutes()+this.step);break;case TimeStep.SCALE.HOUR:this.current.setHours(this.current.getHours()+this.step);break;case TimeStep.SCALE.WEEKDAY:case TimeStep.SCALE.DAY:this.current.setDate(this.current.getDate()+this.step);break;case TimeStep.SCALE.MONTH:this.current.setMonth(this.current.getMonth()+this.step);break;case TimeStep.SCALE.YEAR:this.current.setFullYear(this.current.getFullYear()+this.step);break;default:}if(1!=this.step)switch(this.scale){case TimeStep.SCALE.MILLISECOND:this.current.getMilliseconds()0&&(this.step=e),this.autoScale=!1},TimeStep.prototype.setAutoScale=function(t){this.autoScale=t},TimeStep.prototype.setMinimumStep=function(t){if(void 0!=t){var e=31104e6,i=2592e6,n=864e5,s=36e5,o=6e4,r=1e3,a=1;1e3*e>t&&(this.scale=TimeStep.SCALE.YEAR,this.step=1e3),500*e>t&&(this.scale=TimeStep.SCALE.YEAR,this.step=500),100*e>t&&(this.scale=TimeStep.SCALE.YEAR,this.step=100),50*e>t&&(this.scale=TimeStep.SCALE.YEAR,this.step=50),10*e>t&&(this.scale=TimeStep.SCALE.YEAR,this.step=10),5*e>t&&(this.scale=TimeStep.SCALE.YEAR,this.step=5),e>t&&(this.scale=TimeStep.SCALE.YEAR,this.step=1),3*i>t&&(this.scale=TimeStep.SCALE.MONTH,this.step=3),i>t&&(this.scale=TimeStep.SCALE.MONTH,this.step=1),5*n>t&&(this.scale=TimeStep.SCALE.DAY,this.step=5),2*n>t&&(this.scale=TimeStep.SCALE.DAY,this.step=2),n>t&&(this.scale=TimeStep.SCALE.DAY,this.step=1),n/2>t&&(this.scale=TimeStep.SCALE.WEEKDAY,this.step=1),4*s>t&&(this.scale=TimeStep.SCALE.HOUR,this.step=4),s>t&&(this.scale=TimeStep.SCALE.HOUR,this.step=1),15*o>t&&(this.scale=TimeStep.SCALE.MINUTE,this.step=15),10*o>t&&(this.scale=TimeStep.SCALE.MINUTE,this.step=10),5*o>t&&(this.scale=TimeStep.SCALE.MINUTE,this.step=5),o>t&&(this.scale=TimeStep.SCALE.MINUTE,this.step=1),15*r>t&&(this.scale=TimeStep.SCALE.SECOND,this.step=15),10*r>t&&(this.scale=TimeStep.SCALE.SECOND,this.step=10),5*r>t&&(this.scale=TimeStep.SCALE.SECOND,this.step=5),r>t&&(this.scale=TimeStep.SCALE.SECOND,this.step=1),200*a>t&&(this.scale=TimeStep.SCALE.MILLISECOND,this.step=200),100*a>t&&(this.scale=TimeStep.SCALE.MILLISECOND,this.step=100),50*a>t&&(this.scale=TimeStep.SCALE.MILLISECOND,this.step=50),10*a>t&&(this.scale=TimeStep.SCALE.MILLISECOND,this.step=10),5*a>t&&(this.scale=TimeStep.SCALE.MILLISECOND,this.step=5),a>t&&(this.scale=TimeStep.SCALE.MILLISECOND,this.step=1) }},TimeStep.prototype.snap=function(t){if(this.scale==TimeStep.SCALE.YEAR){var e=t.getFullYear()+Math.round(t.getMonth()/12);t.setFullYear(Math.round(e/this.step)*this.step),t.setMonth(0),t.setDate(0),t.setHours(0),t.setMinutes(0),t.setSeconds(0),t.setMilliseconds(0)}else if(this.scale==TimeStep.SCALE.MONTH)t.getDate()>15?(t.setDate(1),t.setMonth(t.getMonth()+1)):t.setDate(1),t.setHours(0),t.setMinutes(0),t.setSeconds(0),t.setMilliseconds(0);else if(this.scale==TimeStep.SCALE.DAY||this.scale==TimeStep.SCALE.WEEKDAY){switch(this.step){case 5:case 2:t.setHours(24*Math.round(t.getHours()/24));break;default:t.setHours(12*Math.round(t.getHours()/12))}t.setMinutes(0),t.setSeconds(0),t.setMilliseconds(0)}else if(this.scale==TimeStep.SCALE.HOUR){switch(this.step){case 4:t.setMinutes(60*Math.round(t.getMinutes()/60));break;default:t.setMinutes(30*Math.round(t.getMinutes()/30))}t.setSeconds(0),t.setMilliseconds(0)}else if(this.scale==TimeStep.SCALE.MINUTE){switch(this.step){case 15:case 10:t.setMinutes(5*Math.round(t.getMinutes()/5)),t.setSeconds(0);break;case 5:t.setSeconds(60*Math.round(t.getSeconds()/60));break;default:t.setSeconds(30*Math.round(t.getSeconds()/30))}t.setMilliseconds(0)}else if(this.scale==TimeStep.SCALE.SECOND)switch(this.step){case 15:case 10:t.setSeconds(5*Math.round(t.getSeconds()/5)),t.setMilliseconds(0);break;case 5:t.setMilliseconds(1e3*Math.round(t.getMilliseconds()/1e3));break;default:t.setMilliseconds(500*Math.round(t.getMilliseconds()/500))}else if(this.scale==TimeStep.SCALE.MILLISECOND){var i=this.step>5?this.step/2:1;t.setMilliseconds(Math.round(t.getMilliseconds()/i)*i)}},TimeStep.prototype.isMajor=function(){switch(this.scale){case TimeStep.SCALE.MILLISECOND:return 0==this.current.getMilliseconds();case TimeStep.SCALE.SECOND:return 0==this.current.getSeconds();case TimeStep.SCALE.MINUTE:return 0==this.current.getHours()&&0==this.current.getMinutes();case TimeStep.SCALE.HOUR:return 0==this.current.getHours();case TimeStep.SCALE.WEEKDAY:case TimeStep.SCALE.DAY:return 1==this.current.getDate();case TimeStep.SCALE.MONTH:return 0==this.current.getMonth();case TimeStep.SCALE.YEAR:return!1;default:return!1}},TimeStep.prototype.getLabelMinor=function(t){switch(void 0==t&&(t=this.current),this.scale){case TimeStep.SCALE.MILLISECOND:return M(t).format("SSS");case TimeStep.SCALE.SECOND:return M(t).format("s");case TimeStep.SCALE.MINUTE:return M(t).format("HH:mm");case TimeStep.SCALE.HOUR:return M(t).format("HH:mm");case TimeStep.SCALE.WEEKDAY:return M(t).format("ddd D");case TimeStep.SCALE.DAY:return M(t).format("D");case TimeStep.SCALE.MONTH:return M(t).format("MMM");case TimeStep.SCALE.YEAR:return M(t).format("YYYY");default:return""}},TimeStep.prototype.getLabelMajor=function(t){switch(void 0==t&&(t=this.current),this.scale){case TimeStep.SCALE.MILLISECOND:return M(t).format("HH:mm:ss");case TimeStep.SCALE.SECOND:return M(t).format("D MMMM HH:mm");case TimeStep.SCALE.MINUTE:case TimeStep.SCALE.HOUR:return M(t).format("ddd D MMMM");case TimeStep.SCALE.WEEKDAY:case TimeStep.SCALE.DAY:return M(t).format("MMMM YYYY");case TimeStep.SCALE.MONTH:return M(t).format("YYYY");case TimeStep.SCALE.YEAR:return"";default:return""}},a.prototype.setOptions=function(t){O.extend(this.options,t)},a.prototype.update=function(){this._order(),this._stack()},a.prototype._order=function(){var t=this.parent.items;if(!t)throw Error("Cannot stack items: parent does not contain items");var e=[],i=0;O.forEach(t,function(t){t.visible&&(e[i]=t,i++)});var n=this.options.order||this.defaultOptions.order;if("function"!=typeof n)throw Error("Option order must be a function");e.sort(n),this.ordered=e},a.prototype._stack=function(){var t,e,i,n=this.ordered,s=this.options,o=s.orientation||this.defaultOptions.orientation,r="top"==o;for(i=s.margin&&void 0!==s.margin.item?s.margin.item:this.defaultOptions.margin.item,t=0,e=n.length;e>t;t++){var a=n[t],h=null;do h=this.checkOverlap(n,t,0,t-1,i),null!=h&&(a.top=r?h.top+h.height+i:h.top-a.height-i);while(h)}},a.prototype.checkOverlap=function(t,e,i,n,s){for(var o=this.collision,r=t[e],a=n;a>=i;a--){var h=t[a];if(o(r,h,s)&&a!=e)return h}return null},a.prototype.collision=function(t,e,i){return t.left-ie.left&&t.top-ie.top},h.prototype.setOptions=function(t){O.extend(this.options,t),(null!=t.start||null!=t.end)&&this.setRange(t.start,t.end)},h.prototype.subscribe=function(t,e,i){var n,s=this;if("horizontal"!=i&&"vertical"!=i)throw new TypeError('Unknown direction "'+i+'". '+'Choose "horizontal" or "vertical".');if("move"==e)n={component:t,event:e,direction:i,callback:function(t){s._onMouseDown(t,n)},params:{}},t.on("mousedown",n.callback),s.listeners.push(n);else{if("zoom"!=e)throw new TypeError('Unknown event "'+e+'". '+'Choose "move" or "zoom".');n={component:t,event:e,direction:i,callback:function(t){s._onMouseWheel(t,n)},params:{}},t.on("mousewheel",n.callback),s.listeners.push(n)}},h.prototype.on=function(t,e){L.addListener(this,t,e)},h.prototype._trigger=function(t){L.trigger(this,t,{start:this.start,end:this.end})},h.prototype.setRange=function(t,e){var i=this._applyRange(t,e);i&&(this._trigger("rangechange"),this._trigger("rangechanged"))},h.prototype._applyRange=function(t,e){var i,n=null!=t?O.convert(t,"Number"):this.start,s=null!=e?O.convert(e,"Number"):this.end;if(isNaN(n))throw Error('Invalid start "'+t+'"');if(isNaN(s))throw Error('Invalid end "'+e+'"');if(n>s&&(s=n),null!=this.options.min){var o=this.options.min.valueOf();o>n&&(i=o-n,n+=i,s+=i)}if(null!=this.options.max){var r=this.options.max.valueOf();s>r&&(i=s-r,n-=i,s-=i)}if(null!=this.options.zoomMin){var a=this.options.zoomMin.valueOf();0>a&&(a=0),a>s-n&&(this.end-this.start>a?(i=a-(s-n),n-=i/2,s+=i/2):(n=this.start,s=this.end))}if(null!=this.options.zoomMax){var h=this.options.zoomMax.valueOf();0>h&&(h=0),s-n>h&&(h>this.end-this.start?(i=s-n-h,n+=i/2,s-=i/2):(n=this.start,s=this.end))}var d=this.start!=n||this.end!=s;return this.start=n,this.end=s,d},h.prototype.getRange=function(){return{start:this.start,end:this.end}},h.prototype.conversion=function(t){return this.start,this.end,h.conversion(this.start,this.end,t)},h.conversion=function(t,e,i){return 0!=i&&0!=e-t?{offset:t,factor:i/(e-t)}:{offset:0,factor:1}},h.prototype._onMouseDown=function(t,e){t=t||window.event;var i=e.params,n=t.which?1==t.which:1==t.button;if(n){i.mouseX=O.getPageX(t),i.mouseY=O.getPageY(t),i.previousLeft=0,i.previousOffset=0,i.moved=!1,i.start=this.start,i.end=this.end;var s=e.component.frame;s&&(s.style.cursor="move");var o=this;i.onMouseMove||(i.onMouseMove=function(t){o._onMouseMove(t,e)},O.addEventListener(document,"mousemove",i.onMouseMove)),i.onMouseUp||(i.onMouseUp=function(t){o._onMouseUp(t,e)},O.addEventListener(document,"mouseup",i.onMouseUp)),O.preventDefault(t)}},h.prototype._onMouseMove=function(t,e){t=t||window.event;var i=e.params,n=O.getPageX(t),s=O.getPageY(t);void 0==i.mouseX&&(i.mouseX=n),void 0==i.mouseY&&(i.mouseY=s);var o=n-i.mouseX,r=s-i.mouseY,a="horizontal"==e.direction?o:r;Math.abs(a)>=1&&(i.moved=!0);var h=i.end-i.start,d="horizontal"==e.direction?e.component.width:e.component.height,l=-a/d*h;this._applyRange(i.start+l,i.end+l),this._trigger("rangechange"),O.preventDefault(t)},h.prototype._onMouseUp=function(t,e){t=t||window.event;var i=e.params;e.component.frame&&(e.component.frame.style.cursor="auto"),i.onMouseMove&&(O.removeEventListener(document,"mousemove",i.onMouseMove),i.onMouseMove=null),i.onMouseUp&&(O.removeEventListener(document,"mouseup",i.onMouseUp),i.onMouseUp=null),i.moved&&this._trigger("rangechanged")},h.prototype._onMouseWheel=function(t,e){t=t||window.event;var i=0;if(t.wheelDelta?i=t.wheelDelta/120:t.detail&&(i=-t.detail/3),i){var n=this,s=function(){var s=i/5,o=null,r=e.component.frame;if(r){var a,h;if("horizontal"==e.direction){a=e.component.width,h=n.conversion(a);var d=O.getAbsoluteLeft(r),l=O.getPageX(t);o=(l-d)/h.factor+h.offset}else{a=e.component.height,h=n.conversion(a);var p=O.getAbsoluteTop(r),c=O.getPageY(t);o=(p+a-c-p)/h.factor+h.offset}}n.zoom(s,o)};s()}O.preventDefault(t)},h.prototype.zoom=function(t,e){null==e&&(e=(this.start+this.end)/2),t>=1&&(t=.9),-1>=t&&(t=-.9),0>t&&(t/=1+t);var i=this.start-e,n=this.end-e,s=this.start-i*t,o=this.end-n*t;this.setRange(s,o)},h.prototype.move=function(t){var e=this.end-this.start,i=this.start+e*t,n=this.end+e*t;this.start=i,this.end=n},h.prototype.moveTo=function(t){var e=(this.start+this.end)/2,i=e-t,n=this.start-i,s=this.end-i;this.setRange(n,s)},d.prototype.add=function(t){if(void 0==t.id)throw Error("Component has no field id");if(!(t instanceof l||t instanceof d))throw new TypeError("Component must be an instance of prototype Component or Controller");t.controller=this,this.components[t.id]=t},d.prototype.remove=function(t){var e;for(e in this.components)if(this.components.hasOwnProperty(e)&&(e==t||this.components[e]==t))break;e&&delete this.components[e]},d.prototype.requestReflow=function(t){if(t)this.reflow();else if(!this.reflowTimer){var e=this;this.reflowTimer=setTimeout(function(){e.reflowTimer=void 0,e.reflow()},0)}},d.prototype.requestRepaint=function(t){if(t)this.repaint();else if(!this.repaintTimer){var e=this;this.repaintTimer=setTimeout(function(){e.repaintTimer=void 0,e.repaint()},0)}},d.prototype.repaint=function(){function t(n,s){s in i||(n.depends&&n.depends.forEach(function(e){t(e,e.id)}),n.parent&&t(n.parent,n.parent.id),e=n.repaint()||e,i[s]=!0)}var e=!1;this.repaintTimer&&(clearTimeout(this.repaintTimer),this.repaintTimer=void 0);var i={};O.forEach(this.components,t),e&&this.reflow()},d.prototype.reflow=function(){function t(n,s){s in i||(n.depends&&n.depends.forEach(function(e){t(e,e.id)}),n.parent&&t(n.parent,n.parent.id),e=n.reflow()||e,i[s]=!0)}var e=!1;this.reflowTimer&&(clearTimeout(this.reflowTimer),this.reflowTimer=void 0);var i={};O.forEach(this.components,t),e&&this.repaint()},l.prototype.setOptions=function(t){t&&(O.extend(this.options,t),this.controller&&(this.requestRepaint(),this.requestReflow()))},l.prototype.getOption=function(t){var e;return this.options&&(e=this.options[t]),void 0===e&&this.defaultOptions&&(e=this.defaultOptions[t]),e},l.prototype.getContainer=function(){return null},l.prototype.getFrame=function(){return this.frame},l.prototype.repaint=function(){return!1},l.prototype.reflow=function(){return!1},l.prototype.hide=function(){return this.frame&&this.frame.parentNode?(this.frame.parentNode.removeChild(this.frame),!0):!1},l.prototype.show=function(){return this.frame&&this.frame.parentNode?!1:this.repaint()},l.prototype.requestRepaint=function(){if(!this.controller)throw Error("Cannot request a repaint: no controller configured");this.controller.requestRepaint()},l.prototype.requestReflow=function(){if(!this.controller)throw Error("Cannot request a reflow: no controller configured");this.controller.requestReflow()},p.prototype=new l,p.prototype.setOptions=l.prototype.setOptions,p.prototype.getContainer=function(){return this.frame},p.prototype.repaint=function(){var t=0,e=O.updateProperty,i=O.option.asSize,n=this.options,s=this.frame;if(!s){s=document.createElement("div"),s.className="panel";var o=n.className;o&&("function"==typeof o?O.addClassName(s,o()+""):O.addClassName(s,o+"")),this.frame=s,t+=1}if(!s.parentNode){if(!this.parent)throw Error("Cannot repaint panel: no parent attached");var r=this.parent.getContainer();if(!r)throw Error("Cannot repaint panel: parent has no container element");r.appendChild(s),t+=1}return t+=e(s.style,"top",i(n.top,"0px")),t+=e(s.style,"left",i(n.left,"0px")),t+=e(s.style,"width",i(n.width,"100%")),t+=e(s.style,"height",i(n.height,"100%")),t>0},p.prototype.reflow=function(){var t=0,e=O.updateProperty,i=this.frame;return i?(t+=e(this,"top",i.offsetTop),t+=e(this,"left",i.offsetLeft),t+=e(this,"width",i.offsetWidth),t+=e(this,"height",i.offsetHeight)):t+=1,t>0},c.prototype=new p,c.prototype.setOptions=l.prototype.setOptions,c.prototype.repaint=function(){var t=0,e=O.updateProperty,i=O.option.asSize,n=this.options,s=this.frame;if(!s){s=document.createElement("div"),s.className="vis timeline rootpanel";var o=n.className;o&&O.addClassName(s,O.option.asString(o)),this.frame=s,t+=1}if(!s.parentNode){if(!this.container)throw Error("Cannot repaint root panel: no container attached");this.container.appendChild(s),t+=1}return t+=e(s.style,"top",i(n.top,"0px")),t+=e(s.style,"left",i(n.left,"0px")),t+=e(s.style,"width",i(n.width,"100%")),t+=e(s.style,"height",i(n.height,"100%")),this._updateEventEmitters(),this._updateWatch(),t>0},c.prototype.reflow=function(){var t=0,e=O.updateProperty,i=this.frame;return i?(t+=e(this,"top",i.offsetTop),t+=e(this,"left",i.offsetLeft),t+=e(this,"width",i.offsetWidth),t+=e(this,"height",i.offsetHeight)):t+=1,t>0},c.prototype._updateWatch=function(){var t=this.getOption("autoResize");t?this._watch():this._unwatch()},c.prototype._watch=function(){var t=this;this._unwatch();var e=function(){var e=t.getOption("autoResize");return e?(t.frame&&(t.frame.clientWidth!=t.width||t.frame.clientHeight!=t.height)&&t.requestReflow(),void 0):(t._unwatch(),void 0)};O.addEventListener(window,"resize",e),this.watchTimer=setInterval(e,1e3)},c.prototype._unwatch=function(){this.watchTimer&&(clearInterval(this.watchTimer),this.watchTimer=void 0)},c.prototype.on=function(t,e){var i=this.listeners[t];i||(i=[],this.listeners[t]=i),i.push(e),this._updateEventEmitters()},c.prototype._updateEventEmitters=function(){if(this.listeners){var t=this;O.forEach(this.listeners,function(e,i){if(t.emitters||(t.emitters={}),!(i in t.emitters)){var n=t.frame;if(n){var s=function(t){e.forEach(function(e){e(t)})};t.emitters[i]=s,O.addEventListener(n,i,s)}}})}},u.prototype=new l,u.prototype.setOptions=l.prototype.setOptions,u.prototype.setRange=function(t){if(!(t instanceof h||t&&t.start&&t.end))throw new TypeError("Range must be an instance of Range, or an object containing start and end.");this.range=t},u.prototype.toTime=function(t){var e=this.conversion;return new Date(t/e.factor+e.offset)},u.prototype.toScreen=function(t){var e=this.conversion;return(t.valueOf()-e.offset)*e.factor},u.prototype.repaint=function(){var t=0,e=O.updateProperty,i=O.option.asSize,n=this.options,s=this.getOption("orientation"),o=this.props,r=this.step,a=this.frame;if(a||(a=document.createElement("div"),this.frame=a,t+=1),a.className="axis "+s,!a.parentNode){if(!this.parent)throw Error("Cannot repaint time axis: no parent attached");var h=this.parent.getContainer();if(!h)throw Error("Cannot repaint time axis: parent has no container element");h.appendChild(a),t+=1}var d=a.parentNode;if(d){var l=a.nextSibling;d.removeChild(a);var p="bottom"==s&&this.props.parentHeight&&this.height?this.props.parentHeight-this.height+"px":"0px";if(t+=e(a.style,"top",i(n.top,p)),t+=e(a.style,"left",i(n.left,"0px")),t+=e(a.style,"width",i(n.width,"100%")),t+=e(a.style,"height",i(n.height,this.height+"px")),this._repaintMeasureChars(),this.step){this._repaintStart(),r.first();for(var c=void 0,u=0;r.hasNext()&&1e3>u;){u++;var f=r.getCurrent(),m=this.toScreen(f),g=r.isMajor();this.getOption("showMinorLabels")&&this._repaintMinorText(m,r.getLabelMinor()),g&&this.getOption("showMajorLabels")?(m>0&&(void 0==c&&(c=m),this._repaintMajorText(m,r.getLabelMajor())),this._repaintMajorLine(m)):this._repaintMinorLine(m),r.next()}if(this.getOption("showMajorLabels")){var v=this.toTime(0),y=r.getLabelMajor(v),b=y.length*(o.majorCharWidth||10)+10;(void 0==c||c>b)&&this._repaintMajorText(0,y)}this._repaintEnd()}this._repaintLine(),l?d.insertBefore(a,l):d.appendChild(a)}return t>0},u.prototype._repaintStart=function(){var t=this.dom,e=t.redundant;e.majorLines=t.majorLines,e.majorTexts=t.majorTexts,e.minorLines=t.minorLines,e.minorTexts=t.minorTexts,t.majorLines=[],t.majorTexts=[],t.minorLines=[],t.minorTexts=[]},u.prototype._repaintEnd=function(){O.forEach(this.dom.redundant,function(t){for(;t.length;){var e=t.pop();e&&e.parentNode&&e.parentNode.removeChild(e)}})},u.prototype._repaintMinorText=function(t,e){var i=this.dom.redundant.minorTexts.shift();if(!i){var n=document.createTextNode("");i=document.createElement("div"),i.appendChild(n),i.className="text minor",this.frame.appendChild(i)}this.dom.minorTexts.push(i),i.childNodes[0].nodeValue=e,i.style.left=t+"px",i.style.top=this.props.minorLabelTop+"px"},u.prototype._repaintMajorText=function(t,e){var i=this.dom.redundant.majorTexts.shift();if(!i){var n=document.createTextNode(e);i=document.createElement("div"),i.className="text major",i.appendChild(n),this.frame.appendChild(i)}this.dom.majorTexts.push(i),i.childNodes[0].nodeValue=e,i.style.top=this.props.majorLabelTop+"px",i.style.left=t+"px"},u.prototype._repaintMinorLine=function(t){var e=this.dom.redundant.minorLines.shift();e||(e=document.createElement("div"),e.className="grid vertical minor",this.frame.appendChild(e)),this.dom.minorLines.push(e);var i=this.props;e.style.top=i.minorLineTop+"px",e.style.height=i.minorLineHeight+"px",e.style.left=t-i.minorLineWidth/2+"px"},u.prototype._repaintMajorLine=function(t){var e=this.dom.redundant.majorLines.shift();e||(e=document.createElement("DIV"),e.className="grid vertical major",this.frame.appendChild(e)),this.dom.majorLines.push(e);var i=this.props;e.style.top=i.majorLineTop+"px",e.style.left=t-i.majorLineWidth/2+"px",e.style.height=i.majorLineHeight+"px"},u.prototype._repaintLine=function(){var t=this.dom.line,e=this.frame;this.options,this.getOption("showMinorLabels")||this.getOption("showMajorLabels")?(t?(e.removeChild(t),e.appendChild(t)):(t=document.createElement("div"),t.className="grid horizontal major",e.appendChild(t),this.dom.line=t),t.style.top=this.props.lineTop+"px"):t&&axis.parentElement&&(e.removeChild(axis.line),delete this.dom.line)},u.prototype._repaintMeasureChars=function(){var t,e=this.dom;if(!e.measureCharMinor){t=document.createTextNode("0");var i=document.createElement("DIV");i.className="text minor measure",i.appendChild(t),this.frame.appendChild(i),e.measureCharMinor=i}if(!e.measureCharMajor){t=document.createTextNode("0");var n=document.createElement("DIV");n.className="text major measure",n.appendChild(t),this.frame.appendChild(n),e.measureCharMajor=n}},u.prototype.reflow=function(){var t=0,e=O.updateProperty,i=this.frame,n=this.range;if(!n)throw Error("Cannot repaint time axis: no range configured");if(i){t+=e(this,"top",i.offsetTop),t+=e(this,"left",i.offsetLeft);var s=this.props,o=this.getOption("showMinorLabels"),r=this.getOption("showMajorLabels"),a=this.dom.measureCharMinor,h=this.dom.measureCharMajor;a&&(s.minorCharHeight=a.clientHeight,s.minorCharWidth=a.clientWidth),h&&(s.majorCharHeight=h.clientHeight,s.majorCharWidth=h.clientWidth);var d=i.parentNode?i.parentNode.offsetHeight:0;switch(d!=s.parentHeight&&(s.parentHeight=d,t+=1),this.getOption("orientation")){case"bottom":s.minorLabelHeight=o?s.minorCharHeight:0,s.majorLabelHeight=r?s.majorCharHeight:0,s.minorLabelTop=0,s.majorLabelTop=s.minorLabelTop+s.minorLabelHeight,s.minorLineTop=-this.top,s.minorLineHeight=Math.max(this.top+s.majorLabelHeight,0),s.minorLineWidth=1,s.majorLineTop=-this.top,s.majorLineHeight=Math.max(this.top+s.minorLabelHeight+s.majorLabelHeight,0),s.majorLineWidth=1,s.lineTop=0;break;case"top":s.minorLabelHeight=o?s.minorCharHeight:0,s.majorLabelHeight=r?s.majorCharHeight:0,s.majorLabelTop=0,s.minorLabelTop=s.majorLabelTop+s.majorLabelHeight,s.minorLineTop=s.minorLabelTop,s.minorLineHeight=Math.max(d-s.majorLabelHeight-this.top),s.minorLineWidth=1,s.majorLineTop=0,s.majorLineHeight=Math.max(d-this.top),s.majorLineWidth=1,s.lineTop=s.majorLabelHeight+s.minorLabelHeight;break;default:throw Error('Unkown orientation "'+this.getOption("orientation")+'"')}var l=s.minorLabelHeight+s.majorLabelHeight;t+=e(this,"width",i.offsetWidth),t+=e(this,"height",l),this._updateConversion();var p=O.convert(n.start,"Date"),c=O.convert(n.end,"Date"),u=this.toTime(5*(s.minorCharWidth||10))-this.toTime(0);this.step=new TimeStep(p,c,u),t+=e(s.range,"start",p.valueOf()),t+=e(s.range,"end",c.valueOf()),t+=e(s.range,"minimumStep",u.valueOf())}return t>0},u.prototype._updateConversion=function(){var t=this.range;if(!t)throw Error("No range configured");this.conversion=t.conversion?t.conversion(this.width):h.conversion(t.start,t.end,this.width)},f.prototype=new p,f.types={box:g,range:y,point:v},f.prototype.setOptions=l.prototype.setOptions,f.prototype.setRange=function(t){if(!(t instanceof h||t&&t.start&&t.end))throw new TypeError("Range must be an instance of Range, or an object containing start and end.");this.range=t},f.prototype.repaint=function(){var t=0,e=O.updateProperty,i=O.option.asSize,n=this.options,s=this.getOption("orientation"),o=this.defaultOptions,r=this.frame;if(!r){r=document.createElement("div"),r.className="itemset";var a=n.className;a&&O.addClassName(r,O.option.asString(a));var h=document.createElement("div");h.className="background",r.appendChild(h),this.dom.background=h;var d=document.createElement("div");d.className="foreground",r.appendChild(d),this.dom.foreground=d;var l=document.createElement("div");l.className="itemset-axis",this.dom.axis=l,this.frame=r,t+=1}if(!this.parent)throw Error("Cannot repaint itemset: no parent attached");var p=this.parent.getContainer();if(!p)throw Error("Cannot repaint itemset: parent has no container element");r.parentNode||(p.appendChild(r),t+=1),this.dom.axis.parentNode||(p.appendChild(this.dom.axis),t+=1),t+=e(r.style,"left",i(n.left,"0px")),t+=e(r.style,"top",i(n.top,"0px")),t+=e(r.style,"width",i(n.width,"100%")),t+=e(r.style,"height",i(n.height,this.height+"px")),t+=e(this.dom.axis.style,"left",i(n.left,"0px")),t+=e(this.dom.axis.style,"width",i(n.width,"100%")),t+="bottom"==s?e(this.dom.axis.style,"top",this.height+this.top+"px"):e(this.dom.axis.style,"top",this.top+"px"),this._updateConversion();var c=this,u=this.queue,m=this.itemsData,g=this.items,v={};return Object.keys(u).forEach(function(e){var i=u[e],s=g[e];switch(i){case"add":case"update":var r=m&&m.get(e,v);if(r){var a=r.type||r.start&&r.end&&"range"||n.type||"box",h=f.types[a];if(s&&(h&&s instanceof h?(s.data=r,t++):(t+=s.hide(),s=null)),!s){if(!h)throw new TypeError('Unknown item type "'+a+'"');s=new h(c,r,n,o),t++}s.repaint(),g[e]=s}delete u[e];break;case"remove":s&&(t+=s.hide()),delete g[e],delete u[e];break;default:console.log('Error: unknown action "'+i+'"')}}),O.forEach(this.items,function(e){e.visible?(t+=e.show(),e.reposition()):t+=e.hide()}),t>0},f.prototype.getForeground=function(){return this.dom.foreground},f.prototype.getBackground=function(){return this.dom.background},f.prototype.getAxis=function(){return this.dom.axis},f.prototype.reflow=function(){var t=0,e=this.options,i=e.margin&&e.margin.axis||this.defaultOptions.margin.axis,n=e.margin&&e.margin.item||this.defaultOptions.margin.item,s=O.updateProperty,o=O.option.asNumber,r=O.option.asSize,a=this.frame;if(a){this._updateConversion(),O.forEach(this.items,function(e){t+=e.reflow()}),this.stack.update();var h,d=o(e.maxHeight),l=null!=r(e.height);if(l)h=a.offsetHeight;else{var p=this.stack.ordered;if(p.length){var c=p[0].top,u=p[0].top+p[0].height;O.forEach(p,function(t){c=Math.min(c,t.top),u=Math.max(u,t.top+t.height)}),h=u-c+i+n}else h=i+n}null!=d&&(h=Math.min(h,d)),t+=s(this,"height",h),t+=s(this,"top",a.offsetTop),t+=s(this,"left",a.offsetLeft),t+=s(this,"width",a.offsetWidth)}else t+=1;return t>0},f.prototype.hide=function(){var t=!1;return this.frame&&this.frame.parentNode&&(this.frame.parentNode.removeChild(this.frame),t=!0),this.dom.axis&&this.dom.axis.parentNode&&(this.dom.axis.parentNode.removeChild(this.dom.axis),t=!0),t},f.prototype.setItems=function(t){var e,i=this,n=this.itemsData;if(t){if(!(t instanceof o||t instanceof r))throw new TypeError("Data must be an instance of DataSet");this.itemsData=t}else this.itemsData=null;if(n&&(O.forEach(this.listeners,function(t,e){n.unsubscribe(e,t)}),e=n.getIds(),this._onRemove(e)),this.itemsData){var s=this.id;O.forEach(this.listeners,function(t,e){i.itemsData.subscribe(e,t,s)}),e=this.itemsData.getIds(),this._onAdd(e)}},f.prototype.getItems=function(){return this.itemsData},f.prototype._onUpdate=function(t){this._toQueue("update",t)},f.prototype._onAdd=function(t){this._toQueue("add",t)},f.prototype._onRemove=function(t){this._toQueue("remove",t)},f.prototype._toQueue=function(t,e){var i=this.queue;e.forEach(function(e){i[e]=t}),this.controller&&this.requestRepaint()},f.prototype._updateConversion=function(){var t=this.range;if(!t)throw Error("No range configured");this.conversion=t.conversion?t.conversion(this.width):h.conversion(t.start,t.end,this.width)},f.prototype.toTime=function(t){var e=this.conversion;return new Date(t/e.factor+e.offset)},f.prototype.toScreen=function(t){var e=this.conversion;return(t.valueOf()-e.offset)*e.factor},m.prototype.select=function(){this.selected=!0},m.prototype.unselect=function(){this.selected=!1},m.prototype.show=function(){return!1},m.prototype.hide=function(){return!1},m.prototype.repaint=function(){return!1},m.prototype.reflow=function(){return!1},g.prototype=new m(null,null),g.prototype.select=function(){this.selected=!0},g.prototype.unselect=function(){this.selected=!1},g.prototype.repaint=function(){var t=!1,e=this.dom;if(e||(this._create(),e=this.dom,t=!0),e){if(!this.parent)throw Error("Cannot repaint item: no parent attached");var i=this.parent.getForeground();if(!i)throw Error("Cannot repaint time axis: parent has no foreground container element");var n=this.parent.getBackground();if(!n)throw Error("Cannot repaint time axis: parent has no background container element");var s=this.parent.getAxis();if(!n)throw Error("Cannot repaint time axis: parent has no axis container element");if(e.box.parentNode||(i.appendChild(e.box),t=!0),e.line.parentNode||(n.appendChild(e.line),t=!0),e.dot.parentNode||(s.appendChild(e.dot),t=!0),this.data.content!=this.content){if(this.content=this.data.content,this.content instanceof Element)e.content.innerHTML="",e.content.appendChild(this.content);else{if(void 0==this.data.content)throw Error('Property "content" missing in item '+this.data.id);e.content.innerHTML=this.content}t=!0}var o=(this.data.className?" "+this.data.className:"")+(this.selected?" selected":"");this.className!=o&&(this.className=o,e.box.className="item box"+o,e.line.className="item line"+o,e.dot.className="item dot"+o,t=!0)}return t},g.prototype.show=function(){return this.dom&&this.dom.box.parentNode?!1:this.repaint()},g.prototype.hide=function(){var t=!1,e=this.dom;return e&&(e.box.parentNode&&(e.box.parentNode.removeChild(e.box),t=!0),e.line.parentNode&&e.line.parentNode.removeChild(e.line),e.dot.parentNode&&e.dot.parentNode.removeChild(e.dot)),t},g.prototype.reflow=function(){var t,e,i,n,s,o,r,a,h,d,l,p,c=0;if(void 0==this.data.start)throw Error('Property "start" missing in item '+this.data.id);if(l=this.data,p=this.parent&&this.parent.range,l&&p){var u=p.end-p.start;this.visible=l.start>p.start-u&&l.start0},g.prototype._create=function(){var t=this.dom;t||(this.dom=t={},t.box=document.createElement("DIV"),t.content=document.createElement("DIV"),t.content.className="content",t.box.appendChild(t.content),t.line=document.createElement("DIV"),t.line.className="line",t.dot=document.createElement("DIV"),t.dot.className="dot")},g.prototype.reposition=function(){var t=this.dom,e=this.props,i=this.options.orientation||this.defaultOptions.orientation;if(t){var n=t.box,s=t.line,o=t.dot;n.style.left=this.left+"px",n.style.top=this.top+"px",s.style.left=e.line.left+"px","top"==i?(s.style.top="0px",s.style.height=this.top+"px"):(s.style.top=this.top+this.height+"px",s.style.height=Math.max(this.parent.height-this.top-this.height+this.props.dot.height/2,0)+"px"),o.style.left=e.dot.left+"px",o.style.top=e.dot.top+"px"}},v.prototype=new m(null,null),v.prototype.select=function(){this.selected=!0},v.prototype.unselect=function(){this.selected=!1},v.prototype.repaint=function(){var t=!1,e=this.dom;if(e||(this._create(),e=this.dom,t=!0),e){if(!this.parent)throw Error("Cannot repaint item: no parent attached");var i=this.parent.getForeground();if(!i)throw Error("Cannot repaint time axis: parent has no foreground container element");if(e.point.parentNode||(i.appendChild(e.point),i.appendChild(e.point),t=!0),this.data.content!=this.content){if(this.content=this.data.content,this.content instanceof Element)e.content.innerHTML="",e.content.appendChild(this.content);else{if(void 0==this.data.content)throw Error('Property "content" missing in item '+this.data.id);e.content.innerHTML=this.content}t=!0}var n=(this.data.className?" "+this.data.className:"")+(this.selected?" selected":"");this.className!=n&&(this.className=n,e.point.className="item point"+n,t=!0)}return t},v.prototype.show=function(){return this.dom&&this.dom.point.parentNode?!1:this.repaint()},v.prototype.hide=function(){var t=!1,e=this.dom;return e&&e.point.parentNode&&(e.point.parentNode.removeChild(e.point),t=!0),t},v.prototype.reflow=function(){var t,e,i,n,s,o,r,a,h,d,l=0;if(void 0==this.data.start)throw Error('Property "start" missing in item '+this.data.id);if(h=this.data,d=this.parent&&this.parent.range,h&&d){var p=d.end-d.start;this.visible=h.start>d.start-p&&h.start0},v.prototype._create=function(){var t=this.dom;t||(this.dom=t={},t.point=document.createElement("div"),t.content=document.createElement("div"),t.content.className="content",t.point.appendChild(t.content),t.dot=document.createElement("div"),t.dot.className="dot",t.point.appendChild(t.dot))},v.prototype.reposition=function(){var t=this.dom,e=this.props;t&&(t.point.style.top=this.top+"px",t.point.style.left=this.left+"px",t.content.style.marginLeft=e.content.marginLeft+"px",t.dot.style.top=e.dot.top+"px")},y.prototype=new m(null,null),y.prototype.select=function(){this.selected=!0},y.prototype.unselect=function(){this.selected=!1},y.prototype.repaint=function(){var t=!1,e=this.dom;if(e||(this._create(),e=this.dom,t=!0),e){if(!this.parent)throw Error("Cannot repaint item: no parent attached");var i=this.parent.getForeground();if(!i)throw Error("Cannot repaint time axis: parent has no foreground container element");if(e.box.parentNode||(i.appendChild(e.box),t=!0),this.data.content!=this.content){if(this.content=this.data.content,this.content instanceof Element)e.content.innerHTML="",e.content.appendChild(this.content);else{if(void 0==this.data.content)throw Error('Property "content" missing in item '+this.data.id); e.content.innerHTML=this.content}t=!0}var n=this.data.className?" "+this.data.className:"";this.className!=n&&(this.className=n,e.box.className="item range"+n,t=!0)}return t},y.prototype.show=function(){return this.dom&&this.dom.box.parentNode?!1:this.repaint()},y.prototype.hide=function(){var t=!1,e=this.dom;return e&&e.box.parentNode&&(e.box.parentNode.removeChild(e.box),t=!0),t},y.prototype.reflow=function(){var t,e,i,n,s,o,r,a,h,d,l,p,c,u,f,m,g=0;if(void 0==this.data.start)throw Error('Property "start" missing in item '+this.data.id);if(void 0==this.data.end)throw Error('Property "end" missing in item '+this.data.id);return h=this.data,d=this.parent&&this.parent.range,this.visible=h&&d?h.startd.start:!1,this.visible&&(t=this.dom,t?(e=this.props,i=this.options,o=this.parent,r=o.toScreen(this.data.start),a=o.toScreen(this.data.end),l=O.updateProperty,p=t.box,c=o.width,f=i.orientation||this.defaultOptions.orientation,n=i.margin&&i.margin.axis||this.defaultOptions.margin.axis,s=i.padding||this.defaultOptions.padding,g+=l(e.content,"width",t.content.offsetWidth),g+=l(this,"height",p.offsetHeight),-c>r&&(r=-c),a>2*c&&(a=2*c),u=0>r?Math.min(-r,a-r-e.content.width-2*s):0,g+=l(e.content,"left",u),"top"==f?(m=n,g+=l(this,"top",m)):(m=o.height-this.height-n,g+=l(this,"top",m)),g+=l(this,"left",r),g+=l(this,"width",Math.max(a-r,1))):g+=1),g>0},y.prototype._create=function(){var t=this.dom;t||(this.dom=t={},t.box=document.createElement("div"),t.content=document.createElement("div"),t.content.className="content",t.box.appendChild(t.content))},y.prototype.reposition=function(){var t=this.dom,e=this.props;t&&(t.box.style.top=this.top+"px",t.box.style.left=this.left+"px",t.box.style.width=this.width+"px",t.content.style.left=e.content.left+"px")},b.prototype=new l,b.prototype.setOptions=l.prototype.setOptions,b.prototype.getContainer=function(){return this.parent.getContainer()},b.prototype.setItems=function(t){if(this.itemset&&(this.itemset.hide(),this.itemset.setItems(),this.parent.controller.remove(this.itemset),this.itemset=null),t){var e=this.groupId,i=Object.create(this.options);this.itemset=new f(this,null,i),this.itemset.setRange(this.parent.range),this.view=new r(t,{filter:function(t){return t.group==e}}),this.itemset.setItems(this.view),this.parent.controller.add(this.itemset)}},b.prototype.repaint=function(){return!1},b.prototype.reflow=function(){var t=0,e=O.updateProperty;if(t+=e(this,"top",this.itemset?this.itemset.top:0),t+=e(this,"height",this.itemset?this.itemset.height:0),this.label){var i=this.label.firstChild;t+=e(this.props.label,"width",i.clientWidth),t+=e(this.props.label,"height",i.clientHeight)}else t+=e(this.props.label,"width",0),t+=e(this.props.label,"height",0);return t>0},w.prototype=new p,w.prototype.setOptions=l.prototype.setOptions,w.prototype.setRange=function(){},w.prototype.setItems=function(t){this.itemsData=t;for(var e in this.groups)if(this.groups.hasOwnProperty(e)){var i=this.groups[e];i.setItems(t)}},w.prototype.getItems=function(){return this.itemsData},w.prototype.setRange=function(t){this.range=t},w.prototype.setGroups=function(t){var e,i=this;if(this.groupsData&&(O.forEach(this.listeners,function(t,e){i.groupsData.unsubscribe(e,t)}),e=this.groupsData.getIds(),this._onRemove(e)),t?t instanceof o?this.groupsData=t:(this.groupsData=new o({convert:{start:"Date",end:"Date"}}),this.groupsData.add(t)):this.groupsData=null,this.groupsData){var n=this.id;O.forEach(this.listeners,function(t,e){i.groupsData.subscribe(e,t,n)}),e=this.groupsData.getIds(),this._onAdd(e)}},w.prototype.getGroups=function(){return this.groupsData},w.prototype.repaint=function(){var t,e,i,n,s=0,o=O.updateProperty,r=O.option.asSize,a=O.option.asElement,h=this.options,d=this.dom.frame,l=this.dom.labels;if(!this.parent)throw Error("Cannot repaint groupset: no parent attached");var p=this.parent.getContainer();if(!p)throw Error("Cannot repaint groupset: parent has no container element");if(!d){d=document.createElement("div"),d.className="groupset",this.dom.frame=d;var c=h.className;c&&O.addClassName(d,O.option.asString(c)),s+=1}d.parentNode||(p.appendChild(d),s+=1);var u=a(h.labelContainer);if(!u)throw Error('Cannot repaint groupset: option "labelContainer" not defined');l||(l=document.createElement("div"),l.className="labels",this.dom.labels=l),l.parentNode&&l.parentNode==u||(l.parentNode&&l.parentNode.removeChild(l.parentNode),u.appendChild(l)),s+=o(d.style,"height",r(h.height,this.height+"px")),s+=o(d.style,"top",r(h.top,"0px")),s+=o(d.style,"left",r(h.left,"0px")),s+=o(d.style,"width",r(h.width,"100%")),s+=o(l.style,"top",r(h.top,"0px"));var f=this,m=this.queue,g=this.groups,v=this.groupsData,y=Object.keys(m);if(y.length){y.forEach(function(t){var e=m[t],i=g[t];switch(e){case"add":case"update":if(!i){var n=Object.create(f.options);i=new b(f,t,n),i.setItems(f.itemsData),g[t]=i,f.controller.add(i)}i.data=v.get(t),delete m[t];break;case"remove":i&&(i.setItems(),delete g[t],f.controller.remove(i)),delete m[t];break;default:console.log('Error: unknown action "'+e+'"')}});var w=this.groupsData.getIds({order:this.options.groupsOrder});for(t=0;w.length>t;t++)(function(t,e){var i=0;e&&(i=function(){return e.top+e.height}),t.setOptions({top:i})})(g[w[t]],g[w[t-1]]);for(;l.firstChild;)l.removeChild(l.firstChild);for(t=0;w.length>t;t++)e=w[t],n=this._createLabel(e),l.appendChild(n);s++}for(e in g)g.hasOwnProperty(e)&&(i=g[e],n=i.label,n&&(n.style.top=i.top+"px",n.style.height=i.height+"px"));return s>0},w.prototype._createLabel=function(t){var e=this.groups[t],i=document.createElement("div");i.className="label";var n=document.createElement("div");n.className="inner",i.appendChild(n);var s=e.data&&e.data.content;s instanceof Element?n.appendChild(s):void 0!=s&&(n.innerHTML=s);var o=e.data&&e.data.className;return o&&O.addClassName(i,o),e.label=i,i},w.prototype.getContainer=function(){return this.dom.frame},w.prototype.getLabelsWidth=function(){return this.props.labels.width},w.prototype.reflow=function(){var t,e,i=0,n=this.options,s=O.updateProperty,o=O.option.asNumber,r=O.option.asSize,a=this.dom.frame;if(a){var h,d=o(n.maxHeight),l=null!=r(n.height);if(l)h=a.offsetHeight;else{h=0;for(t in this.groups)this.groups.hasOwnProperty(t)&&(e=this.groups[t],h+=e.height)}null!=d&&(h=Math.min(h,d)),i+=s(this,"height",h),i+=s(this,"top",a.offsetTop),i+=s(this,"left",a.offsetLeft),i+=s(this,"width",a.offsetWidth)}var p=0;for(t in this.groups)if(this.groups.hasOwnProperty(t)){e=this.groups[t];var c=e.props&&e.props.label&&e.props.label.width||0;p=Math.max(p,c)}return i+=s(this.props.labels,"width",p),i>0},w.prototype.hide=function(){return this.dom.frame&&this.dom.frame.parentNode?(this.dom.frame.parentNode.removeChild(this.dom.frame),!0):!1},w.prototype.show=function(){return this.dom.frame&&this.dom.frame.parentNode?!1:this.repaint()},w.prototype._onUpdate=function(t){this._toQueue(t,"update")},w.prototype._onAdd=function(t){this._toQueue(t,"add")},w.prototype._onRemove=function(t){this._toQueue(t,"remove")},w.prototype._toQueue=function(t,e){var i=this.queue;t.forEach(function(t){i[t]=e}),this.controller&&this.requestRepaint()},_.prototype.setOptions=function(t){t&&O.extend(this.options,t),this.controller.reflow(),this.controller.repaint()},_.prototype.setItems=function(t){var e,i=null==this.itemsData;if(t?t instanceof o&&(e=t):e=null,t instanceof o||(e=new o({convert:{start:"Date",end:"Date"}}),e.add(t)),this.itemsData=e,this.content.setItems(e),i&&(void 0==this.options.start||void 0==this.options.end)){var n=this.getItemRange(),s=n.min,r=n.max;if(null!=s&&null!=r){var a=r.valueOf()-s.valueOf();0>=a&&(a=864e5),s=new Date(s.valueOf()-.05*a),r=new Date(r.valueOf()+.05*a)}void 0!=this.options.start&&(s=new Date(this.options.start.valueOf())),void 0!=this.options.end&&(r=new Date(this.options.end.valueOf())),(null!=s||null!=r)&&this.range.setRange(s,r)}},_.prototype.setGroups=function(t){var e=this;this.groupsData=t;var i=this.groupsData?w:f;if(!(this.content instanceof i)){this.content&&(this.content.hide(),this.content.setItems&&this.content.setItems(),this.content.setGroups&&this.content.setGroups(),this.controller.remove(this.content));var n=Object.create(this.options);O.extend(n,{top:function(){return"top"==e.options.orientation?e.timeaxis.height:e.itemPanel.height-e.timeaxis.height-e.content.height},left:null,width:"100%",height:function(){return e.options.height?e.itemPanel.height-e.timeaxis.height:null},maxHeight:function(){if(e.options.maxHeight){if(!O.isNumber(e.options.maxHeight))throw new TypeError("Number expected for property maxHeight");return e.options.maxHeight-e.timeaxis.height}return null},labelContainer:function(){return e.labelPanel.getContainer()}}),this.content=new i(this.itemPanel,[this.timeaxis],n),this.content.setRange&&this.content.setRange(this.range),this.content.setItems&&this.content.setItems(this.itemsData),this.content.setGroups&&this.content.setGroups(this.groupsData),this.controller.add(this.content)}},_.prototype.getItemRange=function(){var t=this.itemsData,e=null,i=null;if(t){var n=t.min("start");e=n?n.start.valueOf():null;var s=t.max("start");s&&(i=s.start.valueOf());var o=t.max("end");o&&(i=null==i?o.end.valueOf():Math.max(i,o.end.valueOf()))}return{min:null!=e?new Date(e):null,max:null!=i?new Date(i):null}},function(t){function e(t){return M=t,c()}function i(){D=0,C=M.charAt(0)}function n(){D++,C=M.charAt(D)}function s(){return M.charAt(D+1)}function o(t){return L.test(t)}function r(t,e){if(t||(t={}),e)for(var i in e)e.hasOwnProperty(i)&&(t[i]=e[i]);return t}function a(t,e,i){for(var n=e.split("."),s=t;n.length;){var o=n.shift();n.length?(s[o]||(s[o]={}),s=s[o]):s[o]=i}}function h(t,e){for(var i,n,s=null,o=[t],a=t;a.parent;)o.push(a.parent),a=a.parent;if(a.nodes)for(i=0,n=a.nodes.length;n>i;i++)if(e.id===a.nodes[i].id){s=a.nodes[i];break}for(s||(s={id:e.id},t.node&&(s.attr=r(s.attr,t.node))),i=o.length-1;i>=0;i--){var h=o[i];h.nodes||(h.nodes=[]),-1==h.nodes.indexOf(s)&&h.nodes.push(s)}e.attr&&(s.attr=r(s.attr,e.attr))}function d(t,e){if(t.edges||(t.edges=[]),t.edges.push(e),t.edge){var i=r({},t.edge);e.attr=r(i,e.attr)}}function l(t,e,i,n,s){var o={from:e,to:i,type:n};return t.edge&&(o.attr=r({},t.edge)),o.attr=r(o.attr||{},s),o}function p(){for(N=x.NULL,O="";" "==C||" "==C||"\n"==C||"\r"==C;)n();do{var t=!1;if("#"==C){for(var e=D-1;" "==M.charAt(e)||" "==M.charAt(e);)e--;if("\n"==M.charAt(e)||""==M.charAt(e)){for(;""!=C&&"\n"!=C;)n();t=!0}}if("/"==C&&"/"==s()){for(;""!=C&&"\n"!=C;)n();t=!0}if("/"==C&&"*"==s()){for(;""!=C;){if("*"==C&&"/"==s()){n(),n();break}n()}t=!0}for(;" "==C||" "==C||"\n"==C||"\r"==C;)n()}while(t);if(""==C)return N=x.DELIMITER,void 0;var i=C+s();if(S[i])return N=x.DELIMITER,O=i,n(),n(),void 0;if(S[C])return N=x.DELIMITER,O=C,n(),void 0;if(o(C)||"-"==C){for(O+=C,n();o(C);)O+=C,n();return"false"==O?O=!1:"true"==O?O=!0:isNaN(Number(O))||(O=Number(O)),N=x.IDENTIFIER,void 0}if('"'==C){for(n();""!=C&&('"'!=C||'"'==C&&'"'==s());)O+=C,'"'==C&&n(),n();if('"'!=C)throw w('End of string " expected');return n(),N=x.IDENTIFIER,void 0}for(N=x.UNKNOWN;""!=C;)O+=C,n();throw new SyntaxError('Syntax error in part "'+_(O,30)+'"')}function c(){var t={};if(i(),p(),"strict"==O&&(t.strict=!0,p()),("graph"==O||"digraph"==O)&&(t.type=O,p()),N==x.IDENTIFIER&&(t.id=O,p()),"{"!=O)throw w("Angle bracket { expected");if(p(),u(t),"}"!=O)throw w("Angle bracket } expected");if(p(),""!==O)throw w("End of file expected");return p(),delete t.node,delete t.edge,delete t.graph,t}function u(t){for(;""!==O&&"}"!=O;)f(t),";"==O&&p()}function f(t){var e=m(t);if(e)return y(t,e),void 0;var i=g(t);if(!i){if(N!=x.IDENTIFIER)throw w("Identifier expected");var n=O;if(p(),"="==O){if(p(),N!=x.IDENTIFIER)throw w("Identifier expected");t[n]=O,p()}else v(t,n)}}function m(t){var e=null;if("subgraph"==O&&(e={},e.type="subgraph",p(),N==x.IDENTIFIER&&(e.id=O,p())),"{"==O){if(p(),e||(e={}),e.parent=t,e.node=t.node,e.edge=t.edge,e.graph=t.graph,u(e),"}"!=O)throw w("Angle bracket } expected");p(),delete e.node,delete e.edge,delete e.graph,delete e.parent,t.subgraphs||(t.subgraphs=[]),t.subgraphs.push(e)}return e}function g(t){return"node"==O?(p(),t.node=b(),"node"):"edge"==O?(p(),t.edge=b(),"edge"):"graph"==O?(p(),t.graph=b(),"graph"):null}function v(t,e){var i={id:e},n=b();n&&(i.attr=n),h(t,i),y(t,e)}function y(t,e){for(;"->"==O||"--"==O;){var i,n=O;p();var s=m(t);if(s)i=s;else{if(N!=x.IDENTIFIER)throw w("Identifier or subgraph expected");i=O,h(t,{id:i}),p()}var o=b(),r=l(t,e,i,n,o);d(t,r),e=i}}function b(){for(var t=null;"["==O;){for(p(),t={};""!==O&&"]"!=O;){if(N!=x.IDENTIFIER)throw w("Attribute name expected");var e=O;if(p(),"="!=O)throw w("Equal sign = expected");if(p(),N!=x.IDENTIFIER)throw w("Attribute value expected");var i=O;a(t,e,i),p(),","==O&&p()}if("]"!=O)throw w("Bracket ] expected");p()}return t}function w(t){return new SyntaxError(t+', got "'+_(O,30)+'" (char '+D+")")}function _(t,e){return e>=t.length?t:t.substr(0,27)+"..."}function E(t,e,i){t instanceof Array?t.forEach(function(t){e instanceof Array?e.forEach(function(e){i(t,e)}):i(t,e)}):e instanceof Array?e.forEach(function(e){i(t,e)}):i(t,e)}function T(t){function i(t){var e={from:t.from,to:t.to};return r(e,t.attr),e.style="->"==t.type?"arrow":"line",e}var n=e(t),s={nodes:[],edges:[],options:{}};return n.nodes&&n.nodes.forEach(function(t){var e={id:t.id,label:(t.label||t.id)+""};r(e,t.attr),e.image&&(e.shape="image"),s.nodes.push(e)}),n.edges&&n.edges.forEach(function(t){var e,n;e=t.from instanceof Object?t.from.nodes:{id:t.from},n=t.to instanceof Object?t.to.nodes:{id:t.to},t.from instanceof Object&&t.from.edges&&t.from.edges.forEach(function(t){var e=i(t);s.edges.push(e)}),E(e,n,function(e,n){var o=l(s,e.id,n.id,t.type,t.attr),r=i(o);s.edges.push(r)}),t.to instanceof Object&&t.to.edges&&t.to.edges.forEach(function(t){var e=i(t);s.edges.push(e)})}),n.attr&&(s.options=n.attr),s}var x={NULL:0,DELIMITER:1,IDENTIFIER:2,UNKNOWN:3},S={"{":!0,"}":!0,"[":!0,"]":!0,";":!0,"=":!0,",":!0,"->":!0,"--":!0},M="",D=0,C="",O="",N=x.NULL,L=/[a-zA-Z_0-9.:#]/;t.parseDOT=e,t.DOTToGraph=T}(O!==void 0?O:n),"undefined"!=typeof CanvasRenderingContext2D&&(CanvasRenderingContext2D.prototype.circle=function(t,e,i){this.beginPath(),this.arc(t,e,i,0,2*Math.PI,!1)},CanvasRenderingContext2D.prototype.square=function(t,e,i){this.beginPath(),this.rect(t-i,e-i,2*i,2*i)},CanvasRenderingContext2D.prototype.triangle=function(t,e,i){this.beginPath();var n=2*i,s=n/2,o=Math.sqrt(3)/6*n,r=Math.sqrt(n*n-s*s);this.moveTo(t,e-(r-o)),this.lineTo(t+s,e+o),this.lineTo(t-s,e+o),this.lineTo(t,e-(r-o)),this.closePath()},CanvasRenderingContext2D.prototype.triangleDown=function(t,e,i){this.beginPath();var n=2*i,s=n/2,o=Math.sqrt(3)/6*n,r=Math.sqrt(n*n-s*s);this.moveTo(t,e+(r-o)),this.lineTo(t+s,e-o),this.lineTo(t-s,e-o),this.lineTo(t,e+(r-o)),this.closePath()},CanvasRenderingContext2D.prototype.star=function(t,e,i){this.beginPath();for(var n=0;10>n;n++){var s=0===n%2?1.3*i:.5*i;this.lineTo(t+s*Math.sin(2*n*Math.PI/10),e-s*Math.cos(2*n*Math.PI/10))}this.closePath()},CanvasRenderingContext2D.prototype.roundRect=function(t,e,i,n,s){var o=Math.PI/180;0>i-2*s&&(s=i/2),0>n-2*s&&(s=n/2),this.beginPath(),this.moveTo(t+s,e),this.lineTo(t+i-s,e),this.arc(t+i-s,e+s,s,270*o,360*o,!1),this.lineTo(t+i,e+n-s),this.arc(t+i-s,e+n-s,s,0,90*o,!1),this.lineTo(t+s,e+n),this.arc(t+s,e+n-s,s,90*o,180*o,!1),this.lineTo(t,e+s),this.arc(t+s,e+s,s,180*o,270*o,!1)},CanvasRenderingContext2D.prototype.ellipse=function(t,e,i,n){var s=.5522848,o=i/2*s,r=n/2*s,a=t+i,h=e+n,d=t+i/2,l=e+n/2;this.beginPath(),this.moveTo(t,l),this.bezierCurveTo(t,l-r,d-o,e,d,e),this.bezierCurveTo(d+o,e,a,l-r,a,l),this.bezierCurveTo(a,l+r,d+o,h,d,h),this.bezierCurveTo(d-o,h,t,l+r,t,l)},CanvasRenderingContext2D.prototype.database=function(t,e,i,n){var s=1/3,o=i,r=n*s,a=.5522848,h=o/2*a,d=r/2*a,l=t+o,p=e+r,c=t+o/2,u=e+r/2,f=e+(n-r/2),m=e+n;this.beginPath(),this.moveTo(l,u),this.bezierCurveTo(l,u+d,c+h,p,c,p),this.bezierCurveTo(c-h,p,t,u+d,t,u),this.bezierCurveTo(t,u-d,c-h,e,c,e),this.bezierCurveTo(c+h,e,l,u-d,l,u),this.lineTo(l,f),this.bezierCurveTo(l,f+d,c+h,m,c,m),this.bezierCurveTo(c-h,m,t,f+d,t,f),this.lineTo(t,u)},CanvasRenderingContext2D.prototype.arrow=function(t,e,i,n){var s=t-n*Math.cos(i),o=e-n*Math.sin(i),r=t-.9*n*Math.cos(i),a=e-.9*n*Math.sin(i),h=s+n/3*Math.cos(i+.5*Math.PI),d=o+n/3*Math.sin(i+.5*Math.PI),l=s+n/3*Math.cos(i-.5*Math.PI),p=o+n/3*Math.sin(i-.5*Math.PI);this.beginPath(),this.moveTo(t,e),this.lineTo(h,d),this.lineTo(r,a),this.lineTo(l,p),this.closePath()},CanvasRenderingContext2D.prototype.dashedLine=function(t,e,i,n,s){s||(s=[10,5]),0==c&&(c=.001);var o=s.length;this.moveTo(t,e);for(var r=i-t,a=n-e,h=a/r,d=Math.sqrt(r*r+a*a),l=0,p=!0;d>=.1;){var c=s[l++%o];c>d&&(c=d);var u=Math.sqrt(c*c/(1+h*h));0>r&&(u=-u),t+=u,e+=h*u,this[p?"lineTo":"moveTo"](t,e),d-=c,p=!p}}),E.prototype.attachEdge=function(t){-1==this.edges.indexOf(t)&&this.edges.push(t),this._updateMass()},E.prototype.detachEdge=function(t){var e=this.edges.indexOf(t);-1!=e&&this.edges.splice(e,1),this._updateMass()},E.prototype._updateMass=function(){this.mass=50+20*this.edges.length},E.prototype.setProperties=function(t,e){if(t){if(void 0!=t.id&&(this.id=t.id),void 0!=t.label&&(this.label=t.label),void 0!=t.title&&(this.title=t.title),void 0!=t.group&&(this.group=t.group),void 0!=t.x&&(this.x=t.x),void 0!=t.y&&(this.y=t.y),void 0!=t.value&&(this.value=t.value),void 0===this.id)throw"Node must have an id";if(this.group){var i=this.grouplist.get(this.group);for(var n in i)i.hasOwnProperty(n)&&(this[n]=i[n])}if(void 0!=t.shape&&(this.shape=t.shape),void 0!=t.image&&(this.image=t.image),void 0!=t.radius&&(this.radius=t.radius),void 0!=t.color&&(this.color=E.parseColor(t.color)),void 0!=t.fontColor&&(this.fontColor=t.fontColor),void 0!=t.fontSize&&(this.fontSize=t.fontSize),void 0!=t.fontFace&&(this.fontFace=t.fontFace),void 0!=this.image){if(!this.imagelist)throw"No imagelist provided";this.imageObj=this.imagelist.load(this.image)}switch(this.xFixed=this.xFixed||void 0!=t.x,this.yFixed=this.yFixed||void 0!=t.y,this.radiusFixed=this.radiusFixed||void 0!=t.radius,"image"==this.shape&&(this.radiusMin=e.nodes.widthMin,this.radiusMax=e.nodes.widthMax),this.shape){case"database":this.draw=this._drawDatabase,this.resize=this._resizeDatabase;break;case"box":this.draw=this._drawBox,this.resize=this._resizeBox;break;case"circle":this.draw=this._drawCircle,this.resize=this._resizeCircle;break;case"ellipse":this.draw=this._drawEllipse,this.resize=this._resizeEllipse;break;case"image":this.draw=this._drawImage,this.resize=this._resizeImage;break;case"text":this.draw=this._drawText,this.resize=this._resizeText;break;case"dot":this.draw=this._drawDot,this.resize=this._resizeShape;break;case"square":this.draw=this._drawSquare,this.resize=this._resizeShape;break;case"triangle":this.draw=this._drawTriangle,this.resize=this._resizeShape;break;case"triangleDown":this.draw=this._drawTriangleDown,this.resize=this._resizeShape;break;case"star":this.draw=this._drawStar,this.resize=this._resizeShape;break;default:this.draw=this._drawEllipse,this.resize=this._resizeEllipse}this._reset()}},E.parseColor=function(t){var e;return O.isString(t)?e={border:t,background:t,highlight:{border:t,background:t}}:(e={},e.background=t.background||"white",e.border=t.border||e.background,O.isString(t.highlight)?e.highlight={border:t.highlight,background:t.highlight}:(e.highlight={},e.highlight.background=t.highlight&&t.highlight.background||e.background,e.highlight.border=t.highlight&&t.highlight.border||e.border)),e},E.prototype.select=function(){this.selected=!0,this._reset()},E.prototype.unselect=function(){this.selected=!1,this._reset()},E.prototype._reset=function(){this.width=void 0,this.height=void 0},E.prototype.getTitle=function(){return this.title},E.prototype.distanceToBorder=function(t,e){var i=1;switch(this.width||this.resize(t),this.shape){case"circle":case"dot":return this.radius+i;case"ellipse":var n=this.width/2,s=this.height/2,o=Math.sin(e)*n,r=Math.cos(e)*s;return n*s/Math.sqrt(o*o+r*r);case"box":case"image":case"text":default:return this.width?Math.min(Math.abs(this.width/2/Math.cos(e)),Math.abs(this.height/2/Math.sin(e)))+i:0}},E.prototype._setForce=function(t,e){this.fx=t,this.fy=e},E.prototype._addForce=function(t,e){this.fx+=t,this.fy+=e},E.prototype.discreteStep=function(t){if(!this.xFixed){var e=-this.damping*this.vx,i=(this.fx+e)/this.mass;this.vx+=i/t,this.x+=this.vx/t}if(!this.yFixed){var n=-this.damping*this.vy,s=(this.fy+n)/this.mass;this.vy+=s/t,this.y+=this.vy/t}},E.prototype.isFixed=function(){return this.xFixed&&this.yFixed},E.prototype.isMoving=function(t){return Math.abs(this.vx)>t||Math.abs(this.vy)>t||!this.xFixed&&Math.abs(this.fx)>this.minForce||!this.yFixed&&Math.abs(this.fy)>this.minForce},E.prototype.isSelected=function(){return this.selected},E.prototype.getValue=function(){return this.value},E.prototype.getDistance=function(t,e){var i=this.x-t,n=this.y-e;return Math.sqrt(i*i+n*n)},E.prototype.setValueRange=function(t,e){if(!this.radiusFixed&&void 0!==this.value){var i=(this.radiusMax-this.radiusMin)/(e-t);this.radius=(this.value-t)*i+this.radiusMin}},E.prototype.draw=function(){throw"Draw method not initialized for node"},E.prototype.resize=function(){throw"Resize method not initialized for node"},E.prototype.isOverlappingWith=function(t){return this.leftt.left&&this.topt.top},E.prototype._resizeImage=function(){if(!this.width){var t,e;if(this.value){var i=this.imageObj.height/this.imageObj.width;t=this.radius||this.imageObj.width,e=this.radius*i||this.imageObj.height}else t=this.imageObj.width,e=this.imageObj.height;this.width=t,this.height=e}},E.prototype._drawImage=function(t){this._resizeImage(t),this.left=this.x-this.width/2,this.top=this.y-this.height/2;var e;this.imageObj?(t.drawImage(this.imageObj,this.left,this.top,this.width,this.height),e=this.y+this.height/2):e=this.y,this._label(t,this.label,this.x,e,void 0,"top")},E.prototype._resizeBox=function(t){if(!this.width){var e=5,i=this.getTextSize(t);this.width=i.width+2*e,this.height=i.height+2*e}},E.prototype._drawBox=function(t){this._resizeBox(t),this.left=this.x-this.width/2,this.top=this.y-this.height/2,t.strokeStyle=this.selected?this.color.highlight.border:this.color.border,t.fillStyle=this.selected?this.color.highlight.background:this.color.background,t.lineWidth=this.selected?2:1,t.roundRect(this.left,this.top,this.width,this.height,this.radius),t.fill(),t.stroke(),this._label(t,this.label,this.x,this.y)},E.prototype._resizeDatabase=function(t){if(!this.width){var e=5,i=this.getTextSize(t),n=i.width+2*e;this.width=n,this.height=n}},E.prototype._drawDatabase=function(t){this._resizeDatabase(t),this.left=this.x-this.width/2,this.top=this.y-this.height/2,t.strokeStyle=this.selected?this.color.highlight.border:this.color.border,t.fillStyle=this.selected?this.color.highlight.background:this.color.background,t.lineWidth=this.selected?2:1,t.database(this.x-this.width/2,this.y-.5*this.height,this.width,this.height),t.fill(),t.stroke(),this._label(t,this.label,this.x,this.y)},E.prototype._resizeCircle=function(t){if(!this.width){var e=5,i=this.getTextSize(t),n=Math.max(i.width,i.height)+2*e;this.radius=n/2,this.width=n,this.height=n}},E.prototype._drawCircle=function(t){this._resizeCircle(t),this.left=this.x-this.width/2,this.top=this.y-this.height/2,t.strokeStyle=this.selected?this.color.highlight.border:this.color.border,t.fillStyle=this.selected?this.color.highlight.background:this.color.background,t.lineWidth=this.selected?2:1,t.circle(this.x,this.y,this.radius),t.fill(),t.stroke(),this._label(t,this.label,this.x,this.y)},E.prototype._resizeEllipse=function(t){if(!this.width){var e=this.getTextSize(t);this.width=1.5*e.width,this.height=2*e.height,this.widthl;l++)t.fillText(r[l],i,d),d+=h}},E.prototype.getTextSize=function(t){if(void 0!=this.label){t.font=(this.selected?"bold ":"")+this.fontSize+"px "+this.fontFace;for(var e=this.label.split("\n"),i=(this.fontSize+4)*e.length,n=0,s=0,o=e.length;o>s;s++)n=Math.max(n,t.measureText(e[s]).width);return{width:n,height:i}}return{width:0,height:0}},T.prototype.setProperties=function(t,e){if(t)switch(void 0!=t.from&&(this.fromId=t.from),void 0!=t.to&&(this.toId=t.to),void 0!=t.id&&(this.id=t.id),void 0!=t.style&&(this.style=t.style),void 0!=t.label&&(this.label=t.label),this.label&&(this.fontSize=e.edges.fontSize,this.fontFace=e.edges.fontFace,this.fontColor=e.edges.fontColor,void 0!=t.fontColor&&(this.fontColor=t.fontColor),void 0!=t.fontSize&&(this.fontSize=t.fontSize),void 0!=t.fontFace&&(this.fontFace=t.fontFace)),void 0!=t.title&&(this.title=t.title),void 0!=t.width&&(this.width=t.width),void 0!=t.value&&(this.value=t.value),void 0!=t.length&&(this.length=t.length),t.dash&&(void 0!=t.dash.length&&(this.dash.length=t.dash.length),void 0!=t.dash.gap&&(this.dash.gap=t.dash.gap),void 0!=t.dash.altLength&&(this.dash.altLength=t.dash.altLength)),void 0!=t.color&&(this.color=t.color),this.connect(),this.widthFixed=this.widthFixed||void 0!=t.width,this.lengthFixed=this.lengthFixed||void 0!=t.length,this.stiffness=1/this.length,this.style){case"line":this.draw=this._drawLine;break;case"arrow":this.draw=this._drawArrow;break;case"arrow-center":this.draw=this._drawArrowCenter;break;case"dash-line":this.draw=this._drawDashLine;break;default:this.draw=this._drawLine}},T.prototype.connect=function(){this.disconnect(),this.from=this.graph.nodes[this.fromId]||null,this.to=this.graph.nodes[this.toId]||null,this.connected=this.from&&this.to,this.connected?(this.from.attachEdge(this),this.to.attachEdge(this)):(this.from&&this.from.detachEdge(this),this.to&&this.to.detachEdge(this))},T.prototype.disconnect=function(){this.from&&(this.from.detachEdge(this),this.from=null),this.to&&(this.to.detachEdge(this),this.to=null),this.connected=!1},T.prototype.getTitle=function(){return this.title},T.prototype.getValue=function(){return this.value},T.prototype.setValueRange=function(t,e){if(!this.widthFixed&&void 0!==this.value){var i=(this.widthMax-this.widthMin)/(e-t);this.width=(this.value-t)*i+this.widthMin}},T.prototype.draw=function(){throw"Method draw not initialized in edge"},T.prototype.isOverlappingWith=function(t){var e=10,i=this.from.x,n=this.from.y,s=this.to.x,o=this.to.y,r=t.left,a=t.top,h=T._dist(i,n,s,o,r,a);return e>h},T.prototype._drawLine=function(t){t.strokeStyle=this.color,t.lineWidth=this._getLineWidth();var e;if(this.from!=this.to)this._line(t),this.label&&(e=this._pointOnLine(.5),this._label(t,this.label,e.x,e.y));else{var i,n,s=this.length/4,o=this.from;o.width||o.resize(t),o.width>o.height?(i=o.x+o.width/2,n=o.y-s):(i=o.x+s,n=o.y-o.height/2),this._circle(t,i,n,s),e=this._pointOnCircle(i,n,s,.5),this._label(t,this.label,e.x,e.y)}},T.prototype._getLineWidth=function(){return this.from.selected||this.to.selected?Math.min(2*this.width,this.widthMax):this.width},T.prototype._line=function(t){t.beginPath(),t.moveTo(this.from.x,this.from.y),t.lineTo(this.to.x,this.to.y),t.stroke()},T.prototype._circle=function(t,e,i,n){t.beginPath(),t.arc(e,i,n,0,2*Math.PI,!1),t.stroke()},T.prototype._label=function(t,e,i,n){if(e){t.font=(this.from.selected||this.to.selected?"bold ":"")+this.fontSize+"px "+this.fontFace,t.fillStyle="white";var s=t.measureText(e).width,o=this.fontSize,r=i-s/2,a=n-o/2;t.fillRect(r,a,s,o),t.fillStyle=this.fontColor||"black",t.textAlign="left",t.textBaseline="top",t.fillText(e,r,a)}},T.prototype._drawDashLine=function(t){if(t.strokeStyle=this.color,t.lineWidth=this._getLineWidth(),t.beginPath(),t.lineCap="round",void 0!=this.dash.altLength?t.dashedLine(this.from.x,this.from.y,this.to.x,this.to.y,[this.dash.length,this.dash.gap,this.dash.altLength,this.dash.gap]):void 0!=this.dash.length&&void 0!=this.dash.gap?t.dashedLine(this.from.x,this.from.y,this.to.x,this.to.y,[this.dash.length,this.dash.gap]):(t.moveTo(this.from.x,this.from.y),t.lineTo(this.to.x,this.to.y)),t.stroke(),this.label){var e=this._pointOnLine(.5);this._label(t,this.label,e.x,e.y)}},T.prototype._pointOnLine=function(t){return{x:(1-t)*this.from.x+t*this.to.x,y:(1-t)*this.from.y+t*this.to.y}},T.prototype._pointOnCircle=function(t,e,i,n){var s=2*(n-3/8)*Math.PI;return{x:t+i*Math.cos(s),y:e-i*Math.sin(s)}},T.prototype._drawArrowCenter=function(t){var e;if(t.strokeStyle=this.color,t.fillStyle=this.color,t.lineWidth=this._getLineWidth(),this.from!=this.to){this._line(t);var i=Math.atan2(this.to.y-this.from.y,this.to.x-this.from.x),n=10+5*this.width;e=this._pointOnLine(.5),t.arrow(e.x,e.y,i,n),t.fill(),t.stroke(),this.label&&(e=this._pointOnLine(.5),this._label(t,this.label,e.x,e.y))}else{var s,o,r=this.length/4,a=this.from;a.width||a.resize(t),a.width>a.height?(s=a.x+a.width/2,o=a.y-r):(s=a.x+r,o=a.y-a.height/2),this._circle(t,s,o,r);var i=.2*Math.PI,n=10+5*this.width;e=this._pointOnCircle(s,o,r,.5),t.arrow(e.x,e.y,i,n),t.fill(),t.stroke(),this.label&&(e=this._pointOnCircle(s,o,r,.5),this._label(t,this.label,e.x,e.y))}},T.prototype._drawArrow=function(t){t.strokeStyle=this.color,t.fillStyle=this.color,t.lineWidth=this._getLineWidth();var e,i;if(this.from!=this.to){e=Math.atan2(this.to.y-this.from.y,this.to.x-this.from.x);var n=this.to.x-this.from.x,s=this.to.y-this.from.y,o=Math.sqrt(n*n+s*s),r=this.from.distanceToBorder(t,e+Math.PI),a=(o-r)/o,h=a*this.from.x+(1-a)*this.to.x,d=a*this.from.y+(1-a)*this.to.y,l=this.to.distanceToBorder(t,e),p=(o-l)/o,c=(1-p)*this.from.x+p*this.to.x,u=(1-p)*this.from.y+p*this.to.y;if(t.beginPath(),t.moveTo(h,d),t.lineTo(c,u),t.stroke(),i=10+5*this.width,t.arrow(c,u,e,i),t.fill(),t.stroke(),this.label){var f=this._pointOnLine(.5);this._label(t,this.label,f.x,f.y)}}else{var m,g,v,y=this.from,b=this.length/4;y.width||y.resize(t),y.width>y.height?(m=y.x+y.width/2,g=y.y-b,v={x:m,y:y.y,angle:.9*Math.PI}):(m=y.x+b,g=y.y-y.height/2,v={x:y.x,y:g,angle:.6*Math.PI}),t.beginPath(),t.arc(m,g,b,0,2*Math.PI,!1),t.stroke(),i=10+5*this.width,t.arrow(v.x,v.y,v.angle,i),t.fill(),t.stroke(),this.label&&(f=this._pointOnCircle(m,g,b,.5),this._label(t,this.label,f.x,f.y)) -}},T._dist=function(t,e,i,n,s,o){var r=i-t,a=n-e,h=r*r+a*a,d=((s-t)*r+(o-e)*a)/h;d>1?d=1:0>d&&(d=0);var l=t+d*r,p=e+d*a,c=l-s,u=p-o;return Math.sqrt(c*c+u*u)},x.prototype.setPosition=function(t,e){this.x=parseInt(t),this.y=parseInt(e)},x.prototype.setText=function(t){this.frame.innerHTML=t},x.prototype.show=function(t){if(void 0===t&&(t=!0),t){var e=this.frame.clientHeight,i=this.frame.clientWidth,n=this.frame.parentNode.clientHeight,s=this.frame.parentNode.clientWidth,o=this.y-e;o+e+this.padding>n&&(o=n-e-this.padding),this.padding>o&&(o=this.padding);var r=this.x;r+i+this.padding>s&&(r=s-i-this.padding),this.padding>r&&(r=this.padding),this.frame.style.left=r+"px",this.frame.style.top=o+"px",this.frame.style.visibility="visible"}else this.hide()},x.prototype.hide=function(){this.frame.style.visibility="hidden"},Groups=function(){this.clear(),this.defaultIndex=0},Groups.DEFAULT=[{border:"#2B7CE9",background:"#97C2FC",highlight:{border:"#2B7CE9",background:"#D2E5FF"}},{border:"#FFA500",background:"#FFFF00",highlight:{border:"#FFA500",background:"#FFFFA3"}},{border:"#FA0A10",background:"#FB7E81",highlight:{border:"#FA0A10",background:"#FFAFB1"}},{border:"#41A906",background:"#7BE141",highlight:{border:"#41A906",background:"#A1EC76"}},{border:"#E129F0",background:"#EB7DF4",highlight:{border:"#E129F0",background:"#F0B3F5"}},{border:"#7C29F0",background:"#AD85E4",highlight:{border:"#7C29F0",background:"#D3BDF0"}},{border:"#C37F00",background:"#FFA807",highlight:{border:"#C37F00",background:"#FFCA66"}},{border:"#4220FB",background:"#6E6EFD",highlight:{border:"#4220FB",background:"#9B9BFD"}},{border:"#FD5A77",background:"#FFC0CB",highlight:{border:"#FD5A77",background:"#FFD1D9"}},{border:"#4AD63A",background:"#C2FABC",highlight:{border:"#4AD63A",background:"#E6FFE3"}}],Groups.prototype.clear=function(){this.groups={},this.groups.length=function(){var t=0;for(var e in this)this.hasOwnProperty(e)&&t++;return t}},Groups.prototype.get=function(t){var e=this.groups[t];if(void 0==e){var i=this.defaultIndex%Groups.DEFAULT.length;this.defaultIndex++,e={},e.color=Groups.DEFAULT[i],this.groups[t]=e}return e},Groups.prototype.add=function(t,e){return this.groups[t]=e,e.color&&(e.color=E.parseColor(e.color)),e},Images=function(){this.images={},this.callback=void 0},Images.prototype.setOnloadCallback=function(t){this.callback=t},Images.prototype.load=function(t){var e=this.images[t];if(void 0==e){var i=this;e=new Image,this.images[t]=e,e.onload=function(){i.callback&&i.callback(this)},e.src=t}return e},S.prototype.setData=function(t){if(t&&t.dot&&(t.nodes||t.edges))throw new SyntaxError('Data must contain either parameter "dot" or parameter pair "nodes" and "edges", but not both.');if(this.setOptions(t&&t.options),t&&t.dot){if(t&&t.dot){var e=k.util.DOTToGraph(t.dot);return this.setData(e),void 0}}else this._setNodes(t&&t.nodes),this._setEdges(t&&t.edges);this.stabilize&&this._doStabilize(),this.start()},S.prototype.setOptions=function(t){if(t){if(void 0!=t.width&&(this.width=t.width),void 0!=t.height&&(this.height=t.height),void 0!=t.stabilize&&(this.stabilize=t.stabilize),void 0!=t.selectable&&(this.selectable=t.selectable),t.edges){for(var e in t.edges)t.edges.hasOwnProperty(e)&&(this.constants.edges[e]=t.edges[e]);void 0!=t.edges.length&&t.nodes&&void 0==t.nodes.distance&&(this.constants.edges.length=t.edges.length,this.constants.nodes.distance=1.25*t.edges.length),t.edges.fontColor||(this.constants.edges.fontColor=t.edges.color),t.edges.dash&&(void 0!=t.edges.dash.length&&(this.constants.edges.dash.length=t.edges.dash.length),void 0!=t.edges.dash.gap&&(this.constants.edges.dash.gap=t.edges.dash.gap),void 0!=t.edges.dash.altLength&&(this.constants.edges.dash.altLength=t.edges.dash.altLength))}if(t.nodes){for(e in t.nodes)t.nodes.hasOwnProperty(e)&&(this.constants.nodes[e]=t.nodes[e]);t.nodes.color&&(this.constants.nodes.color=E.parseColor(t.nodes.color))}if(t.groups)for(var i in t.groups)if(t.groups.hasOwnProperty(i)){var n=t.groups[i];this.groups.add(i,n)}}this.setSize(this.width,this.height),this._setTranslation(this.frame.clientWidth/2,this.frame.clientHeight/2),this._setScale(1)},S.prototype._trigger=function(t,e){L.trigger(this,t,e)},S.prototype._create=function(){for(;this.containerElement.hasChildNodes();)this.containerElement.removeChild(this.containerElement.firstChild);if(this.frame=document.createElement("div"),this.frame.className="graph-frame",this.frame.style.position="relative",this.frame.style.overflow="hidden",this.frame.canvas=document.createElement("canvas"),this.frame.canvas.style.position="relative",this.frame.appendChild(this.frame.canvas),!this.frame.canvas.getContext){var t=document.createElement("DIV");t.style.color="red",t.style.fontWeight="bold",t.style.padding="10px",t.innerHTML="Error: your browser does not support HTML canvas",this.frame.canvas.appendChild(t)}var e=this;this.drag={},this.pinch={},this.hammer=D(this.frame.canvas,{prevent_default:!0}),this.hammer.on("tap",e._onTap.bind(e)),this.hammer.on("hold",e._onHold.bind(e)),this.hammer.on("pinch",e._onPinch.bind(e)),this.hammer.on("touch",e._onTouch.bind(e)),this.hammer.on("dragstart",e._onDragStart.bind(e)),this.hammer.on("drag",e._onDrag.bind(e)),this.hammer.on("dragend",e._onDragEnd.bind(e)),this.hammer.on("mousewheel",e._onMouseWheel.bind(e)),this.hammer.on("mousemove",e._onMouseMoveTitle.bind(e)),this.containerElement.appendChild(this.frame)},S.prototype._getNodeAt=function(t){var e=this._xToCanvas(t.x),i=this._yToCanvas(t.y),n={left:e,top:i,right:e,bottom:i},s=this._getNodesOverlappingWith(n);return s.length>0?s[s.length-1]:null},S.prototype._getPointer=function(t){return{x:t.pageX-k.util.getAbsoluteLeft(this.frame.canvas),y:t.pageY-k.util.getAbsoluteTop(this.frame.canvas)}},S.prototype._onTouch=function(t){this.drag.pointer=this._getPointer(t.gesture.touches[0]),this.drag.pinched=!1,this.pinch.scale=this._getScale()},S.prototype._onDragStart=function(){var t=this.drag;t.selection=[],t.translation=this._getTranslation(),t.nodeId=this._getNodeAt(t.pointer);var e=this.nodes[t.nodeId];if(e){e.isSelected()||this._selectNodes([t.nodeId]);var i=this;this.selection.forEach(function(e){var n=i.nodes[e];if(n){var s={id:e,node:n,x:n.x,y:n.y,xFixed:n.xFixed,yFixed:n.yFixed};n.xFixed=!0,n.yFixed=!0,t.selection.push(s)}})}},S.prototype._onDrag=function(t){if(!this.drag.pinched){var e=this._getPointer(t.gesture.touches[0]),i=this,n=this.drag,s=n.selection;if(s&&s.length){var o=e.x-n.pointer.x,r=e.y-n.pointer.y;s.forEach(function(t){var e=t.node;t.xFixed||(e.x=i._canvasToX(i._xToCanvas(t.x)+o)),t.yFixed||(e.y=i._canvasToY(i._yToCanvas(t.y)+r))}),this.moving||(this.moving=!0,this.start())}else{var a=e.x-this.drag.pointer.x,h=e.y-this.drag.pointer.y;this._setTranslation(this.drag.translation.x+a,this.drag.translation.y+h),this._redraw(),this.moved=!0}}},S.prototype._onDragEnd=function(){var t=this.drag.selection;t&&t.forEach(function(t){t.node.xFixed=t.xFixed,t.node.yFixed=t.yFixed})},S.prototype._onTap=function(t){var e=this._getPointer(t.gesture.touches[0]),i=this._getNodeAt(e),n=this.nodes[i];n?(this._selectNodes([i]),this.moving||this._redraw()):(this._unselectNodes(),this._redraw())},S.prototype._onHold=function(t){var e=this._getPointer(t.gesture.touches[0]),i=this._getNodeAt(e),n=this.nodes[i];if(n){if(n.isSelected())this._unselectNodes([i]);else{var s=!0;this._selectNodes([i],s)}this.moving||this._redraw()}},S.prototype._onPinch=function(t){var e=this._getPointer(t.gesture.center);this.drag.pinched=!0,"scale"in this.pinch||(this.pinch.scale=1);var i=this.pinch.scale*t.gesture.scale;this._zoom(i,e)},S.prototype._zoom=function(t,e){var i=this._getScale();.01>t&&(t=.01),t>10&&(t=10);var n=this._getTranslation(),s=t/i,o=(1-s)*e.x+n.x*s,r=(1-s)*e.y+n.y*s;return this._setScale(t),this._setTranslation(o,r),this._redraw(),t},S.prototype._onMouseWheel=function(t){var e=0;if(t.wheelDelta?e=t.wheelDelta/120:t.detail&&(e=-t.detail/3),e){"mouswheelScale"in this.pinch||(this.pinch.mouswheelScale=1);var i=this.pinch.mouswheelScale,n=e/10;0>e&&(n/=1-n),i*=1+n;var s=D.event.collectEventData(this,"scroll",t),o=this._getPointer(s.center);i=this._zoom(i,o),this.pinch.mouswheelScale=i}t.preventDefault()},S.prototype._onMouseMoveTitle=function(t){var e=D.event.collectEventData(this,"mousemove",t),i=this._getPointer(e.center);this.popupNode&&this._checkHidePopup(i);var n=this,s=function(){n._checkShowPopup(i)};this.popupTimer&&clearInterval(this.popupTimer),this.leftButtonDown||(this.popupTimer=setTimeout(s,300))},S.prototype._checkShowPopup=function(t){var e,i={left:this._xToCanvas(t.x),top:this._yToCanvas(t.y),right:this._xToCanvas(t.x),bottom:this._yToCanvas(t.y)},n=this.popupNode;if(void 0==this.popupNode){var s=this.nodes;for(e in s)if(s.hasOwnProperty(e)){var o=s[e];if(void 0!=o.getTitle()&&o.isOverlappingWith(i)){this.popupNode=o;break}}}if(void 0==this.popupNode){var r=this.edges;for(e in r)if(r.hasOwnProperty(e)){var a=r[e];if(a.connected&&void 0!=a.getTitle()&&a.isOverlappingWith(i)){this.popupNode=a;break}}}if(this.popupNode){if(this.popupNode!=n){var h=this;h.popup||(h.popup=new x(h.frame)),h.popup.setPosition(t.x-3,t.y-3),h.popup.setText(h.popupNode.getTitle()),h.popup.show()}}else this.popup&&this.popup.hide()},S.prototype._checkHidePopup=function(t){this.popupNode&&this._getNodeAt(t)||(this.popupNode=void 0,this.popup&&this.popup.hide())},S.prototype._unselectNodes=function(t,e){var i,n,s,o=!1;if(t)for(i=0,n=t.length;n>i;i++){s=t[i],this.nodes[s].unselect();for(var r=0;this.selection.length>r;)this.selection[r]==s?(this.selection.splice(r,1),o=!0):r++}else if(this.selection&&this.selection.length){for(i=0,n=this.selection.length;n>i;i++)s=this.selection[i],this.nodes[s].unselect(),o=!0;this.selection=[]}return!o||1!=e&&void 0!=e||this._trigger("select"),o},S.prototype._selectNodes=function(t,e){var i,n,s=!1,o=!0;if(t.length!=this.selection.length)o=!1;else for(i=0,n=Math.min(t.length,this.selection.length);n>i;i++)if(t[i]!=this.selection[i]){o=!1;break}if(o)return s;if(void 0==e||0==e){var r=!1;s=this._unselectNodes(void 0,r)}for(i=0,n=t.length;n>i;i++){var a=t[i],h=-1!=this.selection.indexOf(a);h||(this.nodes[a].select(),this.selection.push(a),s=!0)}return s&&this._trigger("select"),s},S.prototype._getNodesOverlappingWith=function(t){var e=this.nodes,i=[];for(var n in e)e.hasOwnProperty(n)&&e[n].isOverlappingWith(t)&&i.push(n);return i},S.prototype.getSelection=function(){return this.selection.concat([])},S.prototype.setSelection=function(t){var e,i,n;if(!t||void 0==t.length)throw"Selection must be an array with ids";for(e=0,i=this.selection.length;i>e;e++)n=this.selection[e],this.nodes[n].unselect();for(this.selection=[],e=0,i=t.length;i>e;e++){n=t[e];var s=this.nodes[n];if(!s)throw new RangeError('Node with id "'+n+'" not found');s.select(),this.selection.push(n)}this.redraw()},S.prototype._updateSelection=function(){for(var t=0;this.selection.length>t;){var e=this.selection[t];this.nodes[e]?t++:this.selection.splice(t,1)}},S.prototype._getConnectionCount=function(t){function e(t){for(var e=[],i=0,n=t.length;n>i;i++)for(var s=t[i],o=s.edges,r=0,a=o.length;a>r;r++){var h=o[r],d=null;h.from==s?d=h.to:h.to==s&&(d=h.from);var l,p;if(d)for(l=0,p=t.length;p>l;l++)if(t[l]==d){d=null;break}if(d)for(l=0,p=e.length;p>l;l++)if(e[l]==d){d=null;break}d&&e.push(d)}return e}void 0==t&&(t=1);var i=[],n=this.nodes;for(var s in n)if(n.hasOwnProperty(s)){for(var o=[n[s]],r=0;t>r;r++)o=o.concat(e(o));i.push(o)}for(var a=[],h=0,d=i.length;d>h;h++)a.push(i[h].length);return a},S.prototype.setSize=function(t,e){this.frame.style.width=t,this.frame.style.height=e,this.frame.canvas.style.width="100%",this.frame.canvas.style.height="100%",this.frame.canvas.width=this.frame.canvas.clientWidth,this.frame.canvas.height=this.frame.canvas.clientHeight},S.prototype._setNodes=function(t){var e=this.nodesData;if(t instanceof o||t instanceof r)this.nodesData=t;else if(t instanceof Array)this.nodesData=new o,this.nodesData.add(t);else{if(t)throw new TypeError("Array or DataSet expected");this.nodesData=new o}if(e&&O.forEach(this.nodesListeners,function(t,i){e.unsubscribe(i,t)}),this.nodes={},this.nodesData){var i=this;O.forEach(this.nodesListeners,function(t,e){i.nodesData.subscribe(e,t)});var n=this.nodesData.getIds();this._addNodes(n)}this._updateSelection()},S.prototype._addNodes=function(t){for(var e,i=0,n=t.length;n>i;i++){e=t[i];var s=this.nodesData.get(e),o=new E(s,this.images,this.groups,this.constants);if(this.nodes[e]=o,!o.isFixed()){var r=2*this.constants.edges.length,a=t.length,h=2*Math.PI*(i/a);o.x=r*Math.cos(h),o.y=r*Math.sin(h),this.moving=!0}}this._reconnectEdges(),this._updateValueRange(this.nodes)},S.prototype._updateNodes=function(t){for(var e=this.nodes,i=this.nodesData,n=0,s=t.length;s>n;n++){var o=t[n],r=e[o],a=i.get(o);r?r.setProperties(a,this.constants):(r=new E(properties,this.images,this.groups,this.constants),e[o]=r,r.isFixed()||(this.moving=!0))}this._reconnectEdges(),this._updateValueRange(e)},S.prototype._removeNodes=function(t){for(var e=this.nodes,i=0,n=t.length;n>i;i++){var s=t[i];delete e[s]}this._reconnectEdges(),this._updateSelection(),this._updateValueRange(e)},S.prototype._setEdges=function(t){var e=this.edgesData;if(t instanceof o||t instanceof r)this.edgesData=t;else if(t instanceof Array)this.edgesData=new o,this.edgesData.add(t);else{if(t)throw new TypeError("Array or DataSet expected");this.edgesData=new o}if(e&&O.forEach(this.edgesListeners,function(t,i){e.unsubscribe(i,t)}),this.edges={},this.edgesData){var i=this;O.forEach(this.edgesListeners,function(t,e){i.edgesData.subscribe(e,t)});var n=this.edgesData.getIds();this._addEdges(n)}this._reconnectEdges()},S.prototype._addEdges=function(t){for(var e=this.edges,i=this.edgesData,n=0,s=t.length;s>n;n++){var o=t[n],r=e[o];r&&r.disconnect();var a=i.get(o);e[o]=new T(a,this,this.constants)}this.moving=!0,this._updateValueRange(e)},S.prototype._updateEdges=function(t){for(var e=this.edges,i=this.edgesData,n=0,s=t.length;s>n;n++){var o=t[n],r=i.get(o),a=e[o];a?(a.disconnect(),a.setProperties(r,this.constants),a.connect()):(a=new T(r,this,this.constants),this.edges[o]=a)}this.moving=!0,this._updateValueRange(e)},S.prototype._removeEdges=function(t){for(var e=this.edges,i=0,n=t.length;n>i;i++){var s=t[i],o=e[s];o&&(o.disconnect(),delete e[s])}this.moving=!0,this._updateValueRange(e)},S.prototype._reconnectEdges=function(){var t,e=this.nodes,i=this.edges;for(t in e)e.hasOwnProperty(t)&&(e[t].edges=[]);for(t in i)if(i.hasOwnProperty(t)){var n=i[t];n.from=null,n.to=null,n.connect()}},S.prototype._updateValueRange=function(t){var e,i=void 0,n=void 0;for(e in t)if(t.hasOwnProperty(e)){var s=t[e].getValue();void 0!==s&&(i=void 0===i?s:Math.min(s,i),n=void 0===n?s:Math.max(s,n))}if(void 0!==i&&void 0!==n)for(e in t)t.hasOwnProperty(e)&&t[e].setValueRange(i,n)},S.prototype.redraw=function(){this.setSize(this.width,this.height),this._redraw()},S.prototype._redraw=function(){var t=this.frame.canvas.getContext("2d"),e=this.frame.canvas.width,i=this.frame.canvas.height;t.clearRect(0,0,e,i),t.save(),t.translate(this.translation.x,this.translation.y),t.scale(this.scale,this.scale),this._drawEdges(t),this._drawNodes(t),t.restore()},S.prototype._setTranslation=function(t,e){void 0===this.translation&&(this.translation={x:0,y:0}),void 0!==t&&(this.translation.x=t),void 0!==e&&(this.translation.y=e)},S.prototype._getTranslation=function(){return{x:this.translation.x,y:this.translation.y}},S.prototype._setScale=function(t){this.scale=t},S.prototype._getScale=function(){return this.scale},S.prototype._xToCanvas=function(t){return(t-this.translation.x)/this.scale},S.prototype._canvasToX=function(t){return t*this.scale+this.translation.x},S.prototype._yToCanvas=function(t){return(t-this.translation.y)/this.scale},S.prototype._canvasToY=function(t){return t*this.scale+this.translation.y},S.prototype._drawNodes=function(t){var e=this.nodes,i=[];for(var n in e)e.hasOwnProperty(n)&&(e[n].isSelected()?i.push(n):e[n].draw(t));for(var s=0,o=i.length;o>s;s++)e[i[s]].draw(t)},S.prototype._drawEdges=function(t){var e=this.edges;for(var i in e)if(e.hasOwnProperty(i)){var n=e[i];n.connected&&e[i].draw(t)}},S.prototype._doStabilize=function(){new Date;for(var t=0,e=this.constants.minVelocity,i=!1;!i&&this.constants.maxIterations>t;)this._calculateForces(),this._discreteStepNodes(),i=!this._isMoving(e),t++;new Date},S.prototype._calculateForces=function(){var t,e,i,n,s,o,r,a,h,d,l,p=this.nodes,c=this.edges,u=.01,f=this.frame.canvas.clientWidth/2,m=this.frame.canvas.clientHeight/2;for(t in p)if(p.hasOwnProperty(t)){var g=p[t];e=f-g.x,i=m-g.y,n=Math.atan2(i,e),o=Math.cos(n)*u,r=Math.sin(n)*u,g._setForce(o,r)}var v=this.constants.nodes.distance,y=10;for(var b in p)if(p.hasOwnProperty(b)){var w=p[b];for(var _ in p)if(p.hasOwnProperty(_)){var E=p[_];e=E.x-w.x,i=E.y-w.y,s=Math.sqrt(e*e+i*i),n=Math.atan2(i,e),a=1/(1+Math.exp((s/v-1)*y)),o=Math.cos(n)*a,r=Math.sin(n)*a,w._addForce(-o,-r),E._addForce(o,r)}}for(t in c)if(c.hasOwnProperty(t)){var T=c[t];T.connected&&(e=T.to.x-T.from.x,i=T.to.y-T.from.y,l=T.length,d=Math.sqrt(e*e+i*i),n=Math.atan2(i,e),h=T.stiffness*(l-d),o=Math.cos(n)*h,r=Math.sin(n)*h,T.from._addForce(-o,-r),T.to._addForce(o,r))}},S.prototype._isMoving=function(t){var e=this.nodes;for(var i in e)if(e.hasOwnProperty(i)&&e[i].isMoving(t))return!0;return!1},S.prototype._discreteStepNodes=function(){var t=this.refreshRate/1e3,e=this.nodes;for(var i in e)e.hasOwnProperty(i)&&e[i].discreteStep(t)},S.prototype.start=function(){if(this.moving){this._calculateForces(),this._discreteStepNodes();var t=this.constants.minVelocity;this.moving=this._isMoving(t)}if(this.moving){if(!this.timer){var e=this;this.timer=window.setTimeout(function(){e.timer=void 0,e.start(),e._redraw()},this.refreshRate)}}else this._redraw()},S.prototype.stop=function(){this.timer&&(window.clearInterval(this.timer),this.timer=void 0)};var k={util:O,events:L,Controller:d,DataSet:o,DataView:r,Range:h,Stack:a,TimeStep:TimeStep,EventBus:s,components:{items:{Item:m,ItemBox:g,ItemPoint:v,ItemRange:y},Component:l,Panel:p,RootPanel:c,ItemSet:f,TimeAxis:u},graph:{Node:E,Edge:T,Popup:x,Groups:Groups,Images:Images},Timeline:_,Graph:S};n!==void 0&&(n=k),i!==void 0&&i.exports!==void 0&&(i.exports=k),"function"==typeof t&&t(function(){return k}),"undefined"!=typeof window&&(window.vis=k),O.loadCss("/* vis.js stylesheet */\n.vis.timeline {\n}\n\n\n.vis.timeline.rootpanel {\n position: relative;\n overflow: hidden;\n\n border: 1px solid #bfbfbf;\n -moz-box-sizing: border-box;\n box-sizing: border-box;\n}\n\n.vis.timeline .panel {\n position: absolute;\n overflow: hidden;\n}\n\n\n.vis.timeline .groupset {\n position: absolute;\n padding: 0;\n margin: 0;\n}\n\n.vis.timeline .labels {\n position: absolute;\n top: 0;\n left: 0;\n width: 100%;\n height: 100%;\n\n padding: 0;\n margin: 0;\n\n border-right: 1px solid #bfbfbf;\n box-sizing: border-box;\n -moz-box-sizing: border-box;\n}\n\n.vis.timeline .labels .label {\n position: absolute;\n left: 0;\n top: 0;\n width: 100%;\n border-bottom: 1px solid #bfbfbf;\n color: #4d4d4d;\n}\n\n.vis.timeline .labels .label .inner {\n display: inline-block;\n padding: 5px;\n}\n\n\n.vis.timeline .itemset {\n position: absolute;\n padding: 0;\n margin: 0;\n overflow: hidden;\n}\n\n.vis.timeline .background {\n}\n\n.vis.timeline .foreground {\n}\n\n.vis.timeline .itemset-axis {\n position: absolute;\n}\n\n.vis.timeline .groupset .itemset-axis {\n border-top: 1px solid #bfbfbf;\n}\n\n/* TODO: with orientation=='bottom', this will more or less overlap with timeline axis\n.vis.timeline .groupset .itemset-axis:last-child {\n border-top: none;\n}\n*/\n\n\n.vis.timeline .item {\n position: absolute;\n color: #1A1A1A;\n border-color: #97B0F8;\n background-color: #D5DDF6;\n display: inline-block;\n}\n\n.vis.timeline .item.selected {\n border-color: #FFC200;\n background-color: #FFF785;\n z-index: 999;\n}\n\n.vis.timeline .item.cluster {\n /* TODO: use another color or pattern? */\n background: #97B0F8 url('img/cluster_bg.png');\n color: white;\n}\n.vis.timeline .item.cluster.point {\n border-color: #D5DDF6;\n}\n\n.vis.timeline .item.box {\n text-align: center;\n border-style: solid;\n border-width: 1px;\n border-radius: 5px;\n -moz-border-radius: 5px; /* For Firefox 3.6 and older */\n}\n\n.vis.timeline .item.point {\n background: none;\n}\n\n.vis.timeline .dot {\n border: 5px solid #97B0F8;\n position: absolute;\n border-radius: 5px;\n -moz-border-radius: 5px; /* For Firefox 3.6 and older */\n}\n\n.vis.timeline .item.range {\n overflow: hidden;\n border-style: solid;\n border-width: 1px;\n border-radius: 2px;\n -moz-border-radius: 2px; /* For Firefox 3.6 and older */\n}\n\n.vis.timeline .item.range .drag-left {\n cursor: w-resize;\n z-index: 1000;\n}\n\n.vis.timeline .item.range .drag-right {\n cursor: e-resize;\n z-index: 1000;\n}\n\n.vis.timeline .item.range .content {\n position: relative;\n display: inline-block;\n}\n\n.vis.timeline .item.line {\n position: absolute;\n width: 0;\n border-left-width: 1px;\n border-left-style: solid;\n}\n\n.vis.timeline .item .content {\n margin: 5px;\n white-space: nowrap;\n overflow: hidden;\n}\n\n.vis.timeline .axis {\n position: relative;\n}\n\n.vis.timeline .axis .text {\n position: absolute;\n color: #4d4d4d;\n padding: 3px;\n white-space: nowrap;\n}\n\n.vis.timeline .axis .text.measure {\n position: absolute;\n padding-left: 0;\n padding-right: 0;\n margin-left: 0;\n margin-right: 0;\n visibility: hidden;\n}\n\n.vis.timeline .axis .grid.vertical {\n position: absolute;\n width: 0;\n border-right: 1px solid;\n}\n\n.vis.timeline .axis .grid.horizontal {\n position: absolute;\n left: 0;\n width: 100%;\n height: 0;\n border-bottom: 1px solid;\n}\n\n.vis.timeline .axis .grid.minor {\n border-color: #e5e5e5;\n}\n\n.vis.timeline .axis .grid.major {\n border-color: #bfbfbf;\n}\n\n")},{hammerjs:1,moment:2}]},{},[3])(3)}); \ No newline at end of file +}},T._dist=function(t,e,i,n,s,o){var r=i-t,a=n-e,h=r*r+a*a,d=((s-t)*r+(o-e)*a)/h;d>1?d=1:0>d&&(d=0);var l=t+d*r,p=e+d*a,c=l-s,u=p-o;return Math.sqrt(c*c+u*u)},x.prototype.setPosition=function(t,e){this.x=parseInt(t),this.y=parseInt(e)},x.prototype.setText=function(t){this.frame.innerHTML=t},x.prototype.show=function(t){if(void 0===t&&(t=!0),t){var e=this.frame.clientHeight,i=this.frame.clientWidth,n=this.frame.parentNode.clientHeight,s=this.frame.parentNode.clientWidth,o=this.y-e;o+e+this.padding>n&&(o=n-e-this.padding),this.padding>o&&(o=this.padding);var r=this.x;r+i+this.padding>s&&(r=s-i-this.padding),this.padding>r&&(r=this.padding),this.frame.style.left=r+"px",this.frame.style.top=o+"px",this.frame.style.visibility="visible"}else this.hide()},x.prototype.hide=function(){this.frame.style.visibility="hidden"},Groups=function(){this.clear(),this.defaultIndex=0},Groups.DEFAULT=[{border:"#2B7CE9",background:"#97C2FC",highlight:{border:"#2B7CE9",background:"#D2E5FF"}},{border:"#FFA500",background:"#FFFF00",highlight:{border:"#FFA500",background:"#FFFFA3"}},{border:"#FA0A10",background:"#FB7E81",highlight:{border:"#FA0A10",background:"#FFAFB1"}},{border:"#41A906",background:"#7BE141",highlight:{border:"#41A906",background:"#A1EC76"}},{border:"#E129F0",background:"#EB7DF4",highlight:{border:"#E129F0",background:"#F0B3F5"}},{border:"#7C29F0",background:"#AD85E4",highlight:{border:"#7C29F0",background:"#D3BDF0"}},{border:"#C37F00",background:"#FFA807",highlight:{border:"#C37F00",background:"#FFCA66"}},{border:"#4220FB",background:"#6E6EFD",highlight:{border:"#4220FB",background:"#9B9BFD"}},{border:"#FD5A77",background:"#FFC0CB",highlight:{border:"#FD5A77",background:"#FFD1D9"}},{border:"#4AD63A",background:"#C2FABC",highlight:{border:"#4AD63A",background:"#E6FFE3"}}],Groups.prototype.clear=function(){this.groups={},this.groups.length=function(){var t=0;for(var e in this)this.hasOwnProperty(e)&&t++;return t}},Groups.prototype.get=function(t){var e=this.groups[t];if(void 0==e){var i=this.defaultIndex%Groups.DEFAULT.length;this.defaultIndex++,e={},e.color=Groups.DEFAULT[i],this.groups[t]=e}return e},Groups.prototype.add=function(t,e){return this.groups[t]=e,e.color&&(e.color=E.parseColor(e.color)),e},Images=function(){this.images={},this.callback=void 0},Images.prototype.setOnloadCallback=function(t){this.callback=t},Images.prototype.load=function(t){var e=this.images[t];if(void 0==e){var i=this;e=new Image,this.images[t]=e,e.onload=function(){i.callback&&i.callback(this)},e.src=t}return e},S.prototype.setData=function(t){if(t&&t.dot&&(t.nodes||t.edges))throw new SyntaxError('Data must contain either parameter "dot" or parameter pair "nodes" and "edges", but not both.');if(this.setOptions(t&&t.options),t&&t.dot){if(t&&t.dot){var e=k.util.DOTToGraph(t.dot);return this.setData(e),void 0}}else this._setNodes(t&&t.nodes),this._setEdges(t&&t.edges);this.stabilize&&this._doStabilize(),this.start()},S.prototype.setOptions=function(t){if(t){if(void 0!=t.width&&(this.width=t.width),void 0!=t.height&&(this.height=t.height),void 0!=t.stabilize&&(this.stabilize=t.stabilize),void 0!=t.selectable&&(this.selectable=t.selectable),t.edges){for(var e in t.edges)t.edges.hasOwnProperty(e)&&(this.constants.edges[e]=t.edges[e]);void 0!=t.edges.length&&t.nodes&&void 0==t.nodes.distance&&(this.constants.edges.length=t.edges.length,this.constants.nodes.distance=1.25*t.edges.length),t.edges.fontColor||(this.constants.edges.fontColor=t.edges.color),t.edges.dash&&(void 0!=t.edges.dash.length&&(this.constants.edges.dash.length=t.edges.dash.length),void 0!=t.edges.dash.gap&&(this.constants.edges.dash.gap=t.edges.dash.gap),void 0!=t.edges.dash.altLength&&(this.constants.edges.dash.altLength=t.edges.dash.altLength))}if(t.nodes){for(e in t.nodes)t.nodes.hasOwnProperty(e)&&(this.constants.nodes[e]=t.nodes[e]);t.nodes.color&&(this.constants.nodes.color=E.parseColor(t.nodes.color))}if(t.groups)for(var i in t.groups)if(t.groups.hasOwnProperty(i)){var n=t.groups[i];this.groups.add(i,n)}}this.setSize(this.width,this.height),this._setTranslation(this.frame.clientWidth/2,this.frame.clientHeight/2),this._setScale(1)},S.prototype._trigger=function(t,e){L.trigger(this,t,e)},S.prototype._create=function(){for(;this.containerElement.hasChildNodes();)this.containerElement.removeChild(this.containerElement.firstChild);if(this.frame=document.createElement("div"),this.frame.className="graph-frame",this.frame.style.position="relative",this.frame.style.overflow="hidden",this.frame.canvas=document.createElement("canvas"),this.frame.canvas.style.position="relative",this.frame.appendChild(this.frame.canvas),!this.frame.canvas.getContext){var t=document.createElement("DIV");t.style.color="red",t.style.fontWeight="bold",t.style.padding="10px",t.innerHTML="Error: your browser does not support HTML canvas",this.frame.canvas.appendChild(t)}var e=this;this.drag={},this.pinch={},this.hammer=D(this.frame.canvas,{prevent_default:!0}),this.hammer.on("tap",e._onTap.bind(e)),this.hammer.on("hold",e._onHold.bind(e)),this.hammer.on("pinch",e._onPinch.bind(e)),this.hammer.on("touch",e._onTouch.bind(e)),this.hammer.on("dragstart",e._onDragStart.bind(e)),this.hammer.on("drag",e._onDrag.bind(e)),this.hammer.on("dragend",e._onDragEnd.bind(e)),this.hammer.on("mousewheel",e._onMouseWheel.bind(e)),this.hammer.on("mousemove",e._onMouseMoveTitle.bind(e)),this.containerElement.appendChild(this.frame)},S.prototype._getNodeAt=function(t){var e=this._xToCanvas(t.x),i=this._yToCanvas(t.y),n={left:e,top:i,right:e,bottom:i},s=this._getNodesOverlappingWith(n);return s.length>0?s[s.length-1]:null},S.prototype._getPointer=function(t){return{x:t.pageX-k.util.getAbsoluteLeft(this.frame.canvas),y:t.pageY-k.util.getAbsoluteTop(this.frame.canvas)}},S.prototype._onTouch=function(t){this.drag.pointer=this._getPointer(t.gesture.touches[0]),this.drag.pinched=!1,this.pinch.scale=this._getScale()},S.prototype._onDragStart=function(){var t=this.drag;t.selection=[],t.translation=this._getTranslation(),t.nodeId=this._getNodeAt(t.pointer);var e=this.nodes[t.nodeId];if(e){e.isSelected()||this._selectNodes([t.nodeId]);var i=this;this.selection.forEach(function(e){var n=i.nodes[e];if(n){var s={id:e,node:n,x:n.x,y:n.y,xFixed:n.xFixed,yFixed:n.yFixed};n.xFixed=!0,n.yFixed=!0,t.selection.push(s)}})}},S.prototype._onDrag=function(t){if(!this.drag.pinched){var e=this._getPointer(t.gesture.touches[0]),i=this,n=this.drag,s=n.selection;if(s&&s.length){var o=e.x-n.pointer.x,r=e.y-n.pointer.y;s.forEach(function(t){var e=t.node;t.xFixed||(e.x=i._xToCanvas(i._canvasToX(t.x)+o)),t.yFixed||(e.y=i._yToCanvas(i._canvasToY(t.y)+r))}),this.moving||(this.moving=!0,this.start())}else{var a=e.x-this.drag.pointer.x,h=e.y-this.drag.pointer.y;this._setTranslation(this.drag.translation.x+a,this.drag.translation.y+h),this._redraw(),this.moved=!0}}},S.prototype._onDragEnd=function(){var t=this.drag.selection;t&&t.forEach(function(t){t.node.xFixed=t.xFixed,t.node.yFixed=t.yFixed})},S.prototype._onTap=function(t){var e=this._getPointer(t.gesture.touches[0]),i=this._getNodeAt(e),n=this.nodes[i];n?(this._selectNodes([i]),this.moving||this._redraw()):(this._unselectNodes(),this._redraw())},S.prototype._onHold=function(t){var e=this._getPointer(t.gesture.touches[0]),i=this._getNodeAt(e),n=this.nodes[i];if(n){if(n.isSelected())this._unselectNodes([i]);else{var s=!0;this._selectNodes([i],s)}this.moving||this._redraw()}},S.prototype._onPinch=function(t){var e=this._getPointer(t.gesture.center);this.drag.pinched=!0,"scale"in this.pinch||(this.pinch.scale=1);var i=this.pinch.scale*t.gesture.scale;this._zoom(i,e)},S.prototype._zoom=function(t,e){var i=this._getScale();.01>t&&(t=.01),t>10&&(t=10);var n=this._getTranslation(),s=t/i,o=(1-s)*e.x+n.x*s,r=(1-s)*e.y+n.y*s;return this._setScale(t),this._setTranslation(o,r),this._redraw(),t},S.prototype._onMouseWheel=function(t){var e=0;if(t.wheelDelta?e=t.wheelDelta/120:t.detail&&(e=-t.detail/3),e){"mouswheelScale"in this.pinch||(this.pinch.mouswheelScale=1);var i=this.pinch.mouswheelScale,n=e/10;0>e&&(n/=1-n),i*=1+n;var s=D.event.collectEventData(this,"scroll",t),o=this._getPointer(s.center);i=this._zoom(i,o),this.pinch.mouswheelScale=i}t.preventDefault()},S.prototype._onMouseMoveTitle=function(t){var e=D.event.collectEventData(this,"mousemove",t),i=this._getPointer(e.center);this.popupNode&&this._checkHidePopup(i);var n=this,s=function(){n._checkShowPopup(i)};this.popupTimer&&clearInterval(this.popupTimer),this.leftButtonDown||(this.popupTimer=setTimeout(s,300))},S.prototype._checkShowPopup=function(t){var e,i={left:this._xToCanvas(t.x),top:this._yToCanvas(t.y),right:this._xToCanvas(t.x),bottom:this._yToCanvas(t.y)},n=this.popupNode;if(void 0==this.popupNode){var s=this.nodes;for(e in s)if(s.hasOwnProperty(e)){var o=s[e];if(void 0!=o.getTitle()&&o.isOverlappingWith(i)){this.popupNode=o;break}}}if(void 0==this.popupNode){var r=this.edges;for(e in r)if(r.hasOwnProperty(e)){var a=r[e];if(a.connected&&void 0!=a.getTitle()&&a.isOverlappingWith(i)){this.popupNode=a;break}}}if(this.popupNode){if(this.popupNode!=n){var h=this;h.popup||(h.popup=new x(h.frame)),h.popup.setPosition(t.x-3,t.y-3),h.popup.setText(h.popupNode.getTitle()),h.popup.show()}}else this.popup&&this.popup.hide()},S.prototype._checkHidePopup=function(t){this.popupNode&&this._getNodeAt(t)||(this.popupNode=void 0,this.popup&&this.popup.hide())},S.prototype._unselectNodes=function(t,e){var i,n,s,o=!1;if(t)for(i=0,n=t.length;n>i;i++){s=t[i],this.nodes[s].unselect();for(var r=0;this.selection.length>r;)this.selection[r]==s?(this.selection.splice(r,1),o=!0):r++}else if(this.selection&&this.selection.length){for(i=0,n=this.selection.length;n>i;i++)s=this.selection[i],this.nodes[s].unselect(),o=!0;this.selection=[]}return!o||1!=e&&void 0!=e||this._trigger("select"),o},S.prototype._selectNodes=function(t,e){var i,n,s=!1,o=!0;if(t.length!=this.selection.length)o=!1;else for(i=0,n=Math.min(t.length,this.selection.length);n>i;i++)if(t[i]!=this.selection[i]){o=!1;break}if(o)return s;if(void 0==e||0==e){var r=!1;s=this._unselectNodes(void 0,r)}for(i=0,n=t.length;n>i;i++){var a=t[i],h=-1!=this.selection.indexOf(a);h||(this.nodes[a].select(),this.selection.push(a),s=!0)}return s&&this._trigger("select"),s},S.prototype._getNodesOverlappingWith=function(t){var e=this.nodes,i=[];for(var n in e)e.hasOwnProperty(n)&&e[n].isOverlappingWith(t)&&i.push(n);return i},S.prototype.getSelection=function(){return this.selection.concat([])},S.prototype.setSelection=function(t){var e,i,n;if(!t||void 0==t.length)throw"Selection must be an array with ids";for(e=0,i=this.selection.length;i>e;e++)n=this.selection[e],this.nodes[n].unselect();for(this.selection=[],e=0,i=t.length;i>e;e++){n=t[e];var s=this.nodes[n];if(!s)throw new RangeError('Node with id "'+n+'" not found');s.select(),this.selection.push(n)}this.redraw()},S.prototype._updateSelection=function(){for(var t=0;this.selection.length>t;){var e=this.selection[t];this.nodes[e]?t++:this.selection.splice(t,1)}},S.prototype._getConnectionCount=function(t){function e(t){for(var e=[],i=0,n=t.length;n>i;i++)for(var s=t[i],o=s.edges,r=0,a=o.length;a>r;r++){var h=o[r],d=null;h.from==s?d=h.to:h.to==s&&(d=h.from);var l,p;if(d)for(l=0,p=t.length;p>l;l++)if(t[l]==d){d=null;break}if(d)for(l=0,p=e.length;p>l;l++)if(e[l]==d){d=null;break}d&&e.push(d)}return e}void 0==t&&(t=1);var i=[],n=this.nodes;for(var s in n)if(n.hasOwnProperty(s)){for(var o=[n[s]],r=0;t>r;r++)o=o.concat(e(o));i.push(o)}for(var a=[],h=0,d=i.length;d>h;h++)a.push(i[h].length);return a},S.prototype.setSize=function(t,e){this.frame.style.width=t,this.frame.style.height=e,this.frame.canvas.style.width="100%",this.frame.canvas.style.height="100%",this.frame.canvas.width=this.frame.canvas.clientWidth,this.frame.canvas.height=this.frame.canvas.clientHeight},S.prototype._setNodes=function(t){var e=this.nodesData;if(t instanceof o||t instanceof r)this.nodesData=t;else if(t instanceof Array)this.nodesData=new o,this.nodesData.add(t);else{if(t)throw new TypeError("Array or DataSet expected");this.nodesData=new o}if(e&&O.forEach(this.nodesListeners,function(t,i){e.unsubscribe(i,t)}),this.nodes={},this.nodesData){var i=this;O.forEach(this.nodesListeners,function(t,e){i.nodesData.subscribe(e,t)});var n=this.nodesData.getIds();this._addNodes(n)}this._updateSelection()},S.prototype._addNodes=function(t){for(var e,i=0,n=t.length;n>i;i++){e=t[i];var s=this.nodesData.get(e),o=new E(s,this.images,this.groups,this.constants);if(this.nodes[e]=o,!o.isFixed()){var r=2*this.constants.edges.length,a=t.length,h=2*Math.PI*(i/a);o.x=r*Math.cos(h),o.y=r*Math.sin(h),this.moving=!0}}this._reconnectEdges(),this._updateValueRange(this.nodes)},S.prototype._updateNodes=function(t){for(var e=this.nodes,i=this.nodesData,n=0,s=t.length;s>n;n++){var o=t[n],r=e[o],a=i.get(o);r?r.setProperties(a,this.constants):(r=new E(properties,this.images,this.groups,this.constants),e[o]=r,r.isFixed()||(this.moving=!0))}this._reconnectEdges(),this._updateValueRange(e)},S.prototype._removeNodes=function(t){for(var e=this.nodes,i=0,n=t.length;n>i;i++){var s=t[i];delete e[s]}this._reconnectEdges(),this._updateSelection(),this._updateValueRange(e)},S.prototype._setEdges=function(t){var e=this.edgesData;if(t instanceof o||t instanceof r)this.edgesData=t;else if(t instanceof Array)this.edgesData=new o,this.edgesData.add(t);else{if(t)throw new TypeError("Array or DataSet expected");this.edgesData=new o}if(e&&O.forEach(this.edgesListeners,function(t,i){e.unsubscribe(i,t)}),this.edges={},this.edgesData){var i=this;O.forEach(this.edgesListeners,function(t,e){i.edgesData.subscribe(e,t)});var n=this.edgesData.getIds();this._addEdges(n)}this._reconnectEdges()},S.prototype._addEdges=function(t){for(var e=this.edges,i=this.edgesData,n=0,s=t.length;s>n;n++){var o=t[n],r=e[o];r&&r.disconnect();var a=i.get(o);e[o]=new T(a,this,this.constants)}this.moving=!0,this._updateValueRange(e)},S.prototype._updateEdges=function(t){for(var e=this.edges,i=this.edgesData,n=0,s=t.length;s>n;n++){var o=t[n],r=i.get(o),a=e[o];a?(a.disconnect(),a.setProperties(r,this.constants),a.connect()):(a=new T(r,this,this.constants),this.edges[o]=a)}this.moving=!0,this._updateValueRange(e)},S.prototype._removeEdges=function(t){for(var e=this.edges,i=0,n=t.length;n>i;i++){var s=t[i],o=e[s];o&&(o.disconnect(),delete e[s])}this.moving=!0,this._updateValueRange(e)},S.prototype._reconnectEdges=function(){var t,e=this.nodes,i=this.edges;for(t in e)e.hasOwnProperty(t)&&(e[t].edges=[]);for(t in i)if(i.hasOwnProperty(t)){var n=i[t];n.from=null,n.to=null,n.connect()}},S.prototype._updateValueRange=function(t){var e,i=void 0,n=void 0;for(e in t)if(t.hasOwnProperty(e)){var s=t[e].getValue();void 0!==s&&(i=void 0===i?s:Math.min(s,i),n=void 0===n?s:Math.max(s,n))}if(void 0!==i&&void 0!==n)for(e in t)t.hasOwnProperty(e)&&t[e].setValueRange(i,n)},S.prototype.redraw=function(){this.setSize(this.width,this.height),this._redraw()},S.prototype._redraw=function(){var t=this.frame.canvas.getContext("2d"),e=this.frame.canvas.width,i=this.frame.canvas.height;t.clearRect(0,0,e,i),t.save(),t.translate(this.translation.x,this.translation.y),t.scale(this.scale,this.scale),this._drawEdges(t),this._drawNodes(t),t.restore()},S.prototype._setTranslation=function(t,e){void 0===this.translation&&(this.translation={x:0,y:0}),void 0!==t&&(this.translation.x=t),void 0!==e&&(this.translation.y=e)},S.prototype._getTranslation=function(){return{x:this.translation.x,y:this.translation.y}},S.prototype._setScale=function(t){this.scale=t},S.prototype._getScale=function(){return this.scale},S.prototype._xToCanvas=function(t){return(t-this.translation.x)/this.scale},S.prototype._canvasToX=function(t){return t*this.scale+this.translation.x},S.prototype._yToCanvas=function(t){return(t-this.translation.y)/this.scale},S.prototype._canvasToY=function(t){return t*this.scale+this.translation.y},S.prototype._drawNodes=function(t){var e=this.nodes,i=[];for(var n in e)e.hasOwnProperty(n)&&(e[n].isSelected()?i.push(n):e[n].draw(t));for(var s=0,o=i.length;o>s;s++)e[i[s]].draw(t)},S.prototype._drawEdges=function(t){var e=this.edges;for(var i in e)if(e.hasOwnProperty(i)){var n=e[i];n.connected&&e[i].draw(t)}},S.prototype._doStabilize=function(){new Date;for(var t=0,e=this.constants.minVelocity,i=!1;!i&&this.constants.maxIterations>t;)this._calculateForces(),this._discreteStepNodes(),i=!this._isMoving(e),t++;new Date},S.prototype._calculateForces=function(){var t,e,i,n,s,o,r,a,h,d,l,p=this.nodes,c=this.edges,u=.01,f=this.frame.canvas.clientWidth/2,m=this.frame.canvas.clientHeight/2;for(t in p)if(p.hasOwnProperty(t)){var g=p[t];e=f-g.x,i=m-g.y,n=Math.atan2(i,e),o=Math.cos(n)*u,r=Math.sin(n)*u,g._setForce(o,r)}var v=this.constants.nodes.distance,y=10;for(var b in p)if(p.hasOwnProperty(b)){var w=p[b];for(var _ in p)if(p.hasOwnProperty(_)){var E=p[_];e=E.x-w.x,i=E.y-w.y,s=Math.sqrt(e*e+i*i),n=Math.atan2(i,e),a=1/(1+Math.exp((s/v-1)*y)),o=Math.cos(n)*a,r=Math.sin(n)*a,w._addForce(-o,-r),E._addForce(o,r)}}for(t in c)if(c.hasOwnProperty(t)){var T=c[t];T.connected&&(e=T.to.x-T.from.x,i=T.to.y-T.from.y,l=T.length,d=Math.sqrt(e*e+i*i),n=Math.atan2(i,e),h=T.stiffness*(l-d),o=Math.cos(n)*h,r=Math.sin(n)*h,T.from._addForce(-o,-r),T.to._addForce(o,r))}},S.prototype._isMoving=function(t){var e=this.nodes;for(var i in e)if(e.hasOwnProperty(i)&&e[i].isMoving(t))return!0;return!1},S.prototype._discreteStepNodes=function(){var t=this.refreshRate/1e3,e=this.nodes;for(var i in e)e.hasOwnProperty(i)&&e[i].discreteStep(t)},S.prototype.start=function(){if(this.moving){this._calculateForces(),this._discreteStepNodes();var t=this.constants.minVelocity;this.moving=this._isMoving(t)}if(this.moving){if(!this.timer){var e=this;this.timer=window.setTimeout(function(){e.timer=void 0,e.start(),e._redraw()},this.refreshRate)}}else this._redraw()},S.prototype.stop=function(){this.timer&&(window.clearInterval(this.timer),this.timer=void 0)};var k={util:O,events:L,Controller:d,DataSet:o,DataView:r,Range:h,Stack:a,TimeStep:TimeStep,EventBus:s,components:{items:{Item:m,ItemBox:g,ItemPoint:v,ItemRange:y},Component:l,Panel:p,RootPanel:c,ItemSet:f,TimeAxis:u},graph:{Node:E,Edge:T,Popup:x,Groups:Groups,Images:Images},Timeline:_,Graph:S};n!==void 0&&(n=k),i!==void 0&&i.exports!==void 0&&(i.exports=k),"function"==typeof t&&t(function(){return k}),"undefined"!=typeof window&&(window.vis=k),O.loadCss("/* vis.js stylesheet */\n.vis.timeline {\n}\n\n\n.vis.timeline.rootpanel {\n position: relative;\n overflow: hidden;\n\n border: 1px solid #bfbfbf;\n -moz-box-sizing: border-box;\n box-sizing: border-box;\n}\n\n.vis.timeline .panel {\n position: absolute;\n overflow: hidden;\n}\n\n\n.vis.timeline .groupset {\n position: absolute;\n padding: 0;\n margin: 0;\n}\n\n.vis.timeline .labels {\n position: absolute;\n top: 0;\n left: 0;\n width: 100%;\n height: 100%;\n\n padding: 0;\n margin: 0;\n\n border-right: 1px solid #bfbfbf;\n box-sizing: border-box;\n -moz-box-sizing: border-box;\n}\n\n.vis.timeline .labels .label {\n position: absolute;\n left: 0;\n top: 0;\n width: 100%;\n border-bottom: 1px solid #bfbfbf;\n color: #4d4d4d;\n}\n\n.vis.timeline .labels .label .inner {\n display: inline-block;\n padding: 5px;\n}\n\n\n.vis.timeline .itemset {\n position: absolute;\n padding: 0;\n margin: 0;\n overflow: hidden;\n}\n\n.vis.timeline .background {\n}\n\n.vis.timeline .foreground {\n}\n\n.vis.timeline .itemset-axis {\n position: absolute;\n}\n\n.vis.timeline .groupset .itemset-axis {\n border-top: 1px solid #bfbfbf;\n}\n\n/* TODO: with orientation=='bottom', this will more or less overlap with timeline axis\n.vis.timeline .groupset .itemset-axis:last-child {\n border-top: none;\n}\n*/\n\n\n.vis.timeline .item {\n position: absolute;\n color: #1A1A1A;\n border-color: #97B0F8;\n background-color: #D5DDF6;\n display: inline-block;\n}\n\n.vis.timeline .item.selected {\n border-color: #FFC200;\n background-color: #FFF785;\n z-index: 999;\n}\n\n.vis.timeline .item.cluster {\n /* TODO: use another color or pattern? */\n background: #97B0F8 url('img/cluster_bg.png');\n color: white;\n}\n.vis.timeline .item.cluster.point {\n border-color: #D5DDF6;\n}\n\n.vis.timeline .item.box {\n text-align: center;\n border-style: solid;\n border-width: 1px;\n border-radius: 5px;\n -moz-border-radius: 5px; /* For Firefox 3.6 and older */\n}\n\n.vis.timeline .item.point {\n background: none;\n}\n\n.vis.timeline .dot {\n border: 5px solid #97B0F8;\n position: absolute;\n border-radius: 5px;\n -moz-border-radius: 5px; /* For Firefox 3.6 and older */\n}\n\n.vis.timeline .item.range {\n overflow: hidden;\n border-style: solid;\n border-width: 1px;\n border-radius: 2px;\n -moz-border-radius: 2px; /* For Firefox 3.6 and older */\n}\n\n.vis.timeline .item.range .drag-left {\n cursor: w-resize;\n z-index: 1000;\n}\n\n.vis.timeline .item.range .drag-right {\n cursor: e-resize;\n z-index: 1000;\n}\n\n.vis.timeline .item.range .content {\n position: relative;\n display: inline-block;\n}\n\n.vis.timeline .item.line {\n position: absolute;\n width: 0;\n border-left-width: 1px;\n border-left-style: solid;\n}\n\n.vis.timeline .item .content {\n margin: 5px;\n white-space: nowrap;\n overflow: hidden;\n}\n\n.vis.timeline .axis {\n position: relative;\n}\n\n.vis.timeline .axis .text {\n position: absolute;\n color: #4d4d4d;\n padding: 3px;\n white-space: nowrap;\n}\n\n.vis.timeline .axis .text.measure {\n position: absolute;\n padding-left: 0;\n padding-right: 0;\n margin-left: 0;\n margin-right: 0;\n visibility: hidden;\n}\n\n.vis.timeline .axis .grid.vertical {\n position: absolute;\n width: 0;\n border-right: 1px solid;\n}\n\n.vis.timeline .axis .grid.horizontal {\n position: absolute;\n left: 0;\n width: 100%;\n height: 0;\n border-bottom: 1px solid;\n}\n\n.vis.timeline .axis .grid.minor {\n border-color: #e5e5e5;\n}\n\n.vis.timeline .axis .grid.major {\n border-color: #bfbfbf;\n}\n\n")},{hammerjs:1,moment:2}]},{},[3])(3)}); \ No newline at end of file From 85c77a61571bc0936911b8bcdaeb22d3db9ff15f Mon Sep 17 00:00:00 2001 From: josdejong Date: Tue, 17 Sep 2013 13:42:19 +0200 Subject: [PATCH 07/18] Fixed naming of translation functions --- src/graph/Graph.js | 48 ++++++++++++++++++++++++++++++++++------------ 1 file changed, 36 insertions(+), 12 deletions(-) diff --git a/src/graph/Graph.js b/src/graph/Graph.js index 9b62cabe..b5f3b92b 100644 --- a/src/graph/Graph.js +++ b/src/graph/Graph.js @@ -318,8 +318,8 @@ Graph.prototype._create = function () { * @private */ Graph.prototype._getNodeAt = function (pointer) { - var x = this._xToCanvas(pointer.x); - var y = this._yToCanvas(pointer.y); + var x = this._canvasToX(pointer.x); + var y = this._canvasToY(pointer.y); var obj = { left: x, @@ -428,11 +428,11 @@ Graph.prototype._onDrag = function (event) { var node = s.node; if (!s.xFixed) { - node.x = me._xToCanvas(me._canvasToX(s.x) + deltaX); + node.x = me._canvasToX(me._xToCanvas(s.x) + deltaX); } if (!s.yFixed) { - node.y = me._yToCanvas(me._canvasToY(s.y) + deltaY); + node.y = me._canvasToY(me._yToCanvas(s.y) + deltaY); } }); @@ -656,10 +656,10 @@ Graph.prototype._onMouseMoveTitle = function (event) { */ Graph.prototype._checkShowPopup = function (pointer) { var obj = { - left: this._xToCanvas(pointer.x), - top: this._yToCanvas(pointer.y), - right: this._xToCanvas(pointer.x), - bottom: this._yToCanvas(pointer.y) + left: this._canvasToX(pointer.x), + top: this._canvasToY(pointer.y), + right: this._canvasToX(pointer.x), + bottom: this._canvasToY(pointer.y) }; var id; @@ -1407,19 +1407,43 @@ Graph.prototype._getScale = function() { return this.scale; }; -Graph.prototype._xToCanvas = function(x) { +/** + * Convert a horizontal point on the HTML canvas to the x-value of the model + * @param {number} x + * @returns {number} + * @private + */ +Graph.prototype._canvasToX = function(x) { return (x - this.translation.x) / this.scale; }; -Graph.prototype._canvasToX = function(x) { +/** + * Convert an x-value in the model to a horizontal point on the HTML canvas + * @param {number} x + * @returns {number} + * @private + */ +Graph.prototype._xToCanvas = function(x) { return x * this.scale + this.translation.x; }; -Graph.prototype._yToCanvas = function(y) { +/** + * Convert a vertical point on the HTML canvas to the y-value of the model + * @param {number} y + * @returns {number} + * @private + */ +Graph.prototype._canvasToY = function(y) { return (y - this.translation.y) / this.scale; }; -Graph.prototype._canvasToY = function(y) { +/** + * Convert an y-value in the model to a vertical point on the HTML canvas + * @param {number} y + * @returns {number} + * @private + */ +Graph.prototype._yToCanvas = function(y) { return y * this.scale + this.translation.y ; }; From 51ba1498034dbd98062a4576a5bcfa82334a9672 Mon Sep 17 00:00:00 2001 From: josdejong Date: Tue, 17 Sep 2013 14:09:49 +0200 Subject: [PATCH 08/18] Updated vis overview image --- docs/css/style.css | 6 +++ docs/img/vis_overview.odg | Bin 30379 -> 29653 bytes docs/img/vis_overview.png | Bin 65183 -> 49562 bytes docs/index.html | 7 +++ src/graph/Graph.js | 57 ++++++++++----------- vis.js | 105 +++++++++++++++++++++++--------------- vis.min.js | 2 +- 7 files changed, 106 insertions(+), 71 deletions(-) diff --git a/docs/css/style.css b/docs/css/style.css index 5addab9c..14ba2183 100644 --- a/docs/css/style.css +++ b/docs/css/style.css @@ -39,13 +39,19 @@ h3 { font-size: 140%; } +a > img { + border: none; +} + a { color: #2B7CE9; text-decoration: none; } + a:visited { color: #2E60A4; } + a:hover { color: red; text-decoration: underline; diff --git a/docs/img/vis_overview.odg b/docs/img/vis_overview.odg index 27ef9772606aa8d9e7d6f5638d7d09d2395b720d..0038f586beae1786d7b9fb6b05cbcaa46f91203e 100644 GIT binary patch delta 11792 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�fVD#u=}Z;ZBrb!eYEry}1sy-z zuYrJhhwna?GCsUv0uQ+{Wxw$Q+7{L8$Mxs3v-9WQbJKl6cxL(Qk?kSd|C}3G+EE$d z@AtQ0Oh@K_7AU}#Zb&Hqe4+cR1qC?T0qajxi`{|iPo~|T0^IF@^LK&cPv+X5_wO1C z@SO|FU!48}N3tB9q5gcvaenhZp8bL~oO%9&D!-#_DKH?=@87TS|0A9LdLL|O?rQQI zwW!ELLF0gMK!5Z8CkR6M2Mq{RK?(x7n7g`K*;~5&UzBzvO6`j5AP^P@2#oB44lPOz zCUN1{{f(Obc|LxlrvFZR+W*2(|8q3|T>M|>>mTWbDY(i7=hvwJAT%(lI}voA4fvHi z+kfxEM>itqpEh7}M-uR}8{EI^S!}_XZnS?E@pn6OTX3}l9+<`rgW`YUJd%HO3j(Fv zf<+xD(EhC2e|CSwg$R1)Hw&`=>kF#gFB)v{sy#AT$rb5Orv|P>(2{mwPgkZt<=-3v o?7+J&)YN}ZDp{RbnhomLvHP`yxc?eNiyheCoeqxK;dkx-0|11@!vFvP delta 12456 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 V>_4#~vI3+(k&#doFBdiX@*f7Yf4cwx literal 65183 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 YVJ3Yjw2b?wtEx%9LMS65+Lo$8% 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 + +

Install

diff --git a/src/graph/Graph.js b/src/graph/Graph.js index b5f3b92b..11cf53bb 100644 --- a/src/graph/Graph.js +++ b/src/graph/Graph.js @@ -163,7 +163,6 @@ Graph.prototype.setData = function(data) { this._setEdges(data && data.edges); } - // find a stable position or start animating to a stable position if (this.stabilize) { this._doStabilize(); @@ -251,7 +250,7 @@ Graph.prototype.setOptions = function (options) { /** * fire an event - * @param {String} event The name of an event, for example "select" + * @param {String} event The name of an event, for example 'select' * @param {Object} params Optional object with event parameters * @private */ @@ -273,21 +272,21 @@ Graph.prototype._create = function () { this.containerElement.removeChild(this.containerElement.firstChild); } - this.frame = document.createElement("div"); - this.frame.className = "graph-frame"; - this.frame.style.position = "relative"; - this.frame.style.overflow = "hidden"; + this.frame = document.createElement('div'); + this.frame.className = 'graph-frame'; + this.frame.style.position = 'relative'; + this.frame.style.overflow = 'hidden'; // create the graph canvas (HTML canvas element) - this.frame.canvas = document.createElement( "canvas" ); - this.frame.canvas.style.position = "relative"; + this.frame.canvas = document.createElement( 'canvas' ); + this.frame.canvas.style.position = 'relative'; this.frame.appendChild(this.frame.canvas); if (!this.frame.canvas.getContext) { - var noCanvas = document.createElement( "DIV" ); - noCanvas.style.color = "red"; - noCanvas.style.fontWeight = "bold" ; - noCanvas.style.padding = "10px"; - noCanvas.innerHTML = "Error: your browser does not support HTML canvas"; + var noCanvas = document.createElement( 'DIV' ); + noCanvas.style.color = 'red'; + noCanvas.style.fontWeight = 'bold' ; + noCanvas.style.padding = '10px'; + noCanvas.innerHTML = 'Error: your browser does not support HTML canvas'; this.frame.canvas.appendChild(noCanvas); } @@ -877,7 +876,7 @@ Graph.prototype.setSelection = function(selection) { var i, iMax, id; if (!selection || (selection.length == undefined)) - throw "Selection must be an array with ids"; + throw 'Selection must be an array with ids'; // first unselect any selected node for (i = 0, iMax = this.selection.length; i < iMax; i++) { @@ -1000,17 +999,17 @@ Graph.prototype._getConnectionCount = function(level) { /** * Set a new size for the graph - * @param {string} width Width in pixels or percentage (for example "800px" - * or "50%") - * @param {string} height Height in pixels or percentage (for example "400px" - * or "30%") + * @param {string} width Width in pixels or percentage (for example '800px' + * or '50%') + * @param {string} height Height in pixels or percentage (for example '400px' + * or '30%') */ Graph.prototype.setSize = function(width, height) { this.frame.style.width = width; this.frame.style.height = height; - this.frame.canvas.style.width = "100%"; - this.frame.canvas.style.height = "100%"; + this.frame.canvas.style.width = '100%'; + this.frame.canvas.style.height = '100%'; this.frame.canvas.width = this.frame.canvas.clientWidth; this.frame.canvas.height = this.frame.canvas.clientHeight; @@ -1337,7 +1336,7 @@ Graph.prototype.redraw = function() { * @private */ Graph.prototype._redraw = function() { - var ctx = this.frame.canvas.getContext("2d"); + var ctx = this.frame.canvas.getContext('2d'); // clear the canvas var w = this.frame.canvas.width; @@ -1365,8 +1364,8 @@ Graph.prototype._redraw = function() { Graph.prototype._setTranslation = function(offsetX, offsetY) { if (this.translation === undefined) { this.translation = { - "x": 0, - "y": 0 + x: 0, + y: 0 }; } @@ -1385,8 +1384,8 @@ Graph.prototype._setTranslation = function(offsetX, offsetY) { */ Graph.prototype._getTranslation = function() { return { - "x": this.translation.x, - "y": this.translation.y + x: this.translation.x, + y: this.translation.y }; }; @@ -1449,7 +1448,7 @@ Graph.prototype._yToCanvas = function(y) { /** * Redraw all nodes - * The 2d context of a HTML canvas can be retrieved by canvas.getContext("2d"); + * The 2d context of a HTML canvas can be retrieved by canvas.getContext('2d'); * @param {CanvasRenderingContext2D} ctx * @private */ @@ -1476,7 +1475,7 @@ Graph.prototype._drawNodes = function(ctx) { /** * Redraw all edges - * The 2d context of a HTML canvas can be retrieved by canvas.getContext("2d"); + * The 2d context of a HTML canvas can be retrieved by canvas.getContext('2d'); * @param {CanvasRenderingContext2D} ctx * @private */ @@ -1512,7 +1511,7 @@ Graph.prototype._doStabilize = function() { var end = new Date(); - // console.log("Stabilized in " + (end-start) + " ms, " + count + " iterations" ); // TODO: cleanup + // console.log('Stabilized in ' + (end-start) + ' ms, ' + count + ' iterations' ); // TODO: cleanup }; /** @@ -1669,7 +1668,7 @@ Graph.prototype._calculateForces = function() { /** * Check if any of the nodes is still moving - * @param {number} vmin the minimum velocity considered as "moving" + * @param {number} vmin the minimum velocity considered as 'moving' * @return {boolean} true if moving, false if non of the nodes is moving * @private */ diff --git a/vis.js b/vis.js index 9304828a..0bfa98bb 100644 --- a/vis.js +++ b/vis.js @@ -13016,7 +13016,6 @@ Graph.prototype.setData = function(data) { this._setEdges(data && data.edges); } - // find a stable position or start animating to a stable position if (this.stabilize) { this._doStabilize(); @@ -13104,7 +13103,7 @@ Graph.prototype.setOptions = function (options) { /** * fire an event - * @param {String} event The name of an event, for example "select" + * @param {String} event The name of an event, for example 'select' * @param {Object} params Optional object with event parameters * @private */ @@ -13126,21 +13125,21 @@ Graph.prototype._create = function () { this.containerElement.removeChild(this.containerElement.firstChild); } - this.frame = document.createElement("div"); - this.frame.className = "graph-frame"; - this.frame.style.position = "relative"; - this.frame.style.overflow = "hidden"; + this.frame = document.createElement('div'); + this.frame.className = 'graph-frame'; + this.frame.style.position = 'relative'; + this.frame.style.overflow = 'hidden'; // create the graph canvas (HTML canvas element) - this.frame.canvas = document.createElement( "canvas" ); - this.frame.canvas.style.position = "relative"; + this.frame.canvas = document.createElement( 'canvas' ); + this.frame.canvas.style.position = 'relative'; this.frame.appendChild(this.frame.canvas); if (!this.frame.canvas.getContext) { - var noCanvas = document.createElement( "DIV" ); - noCanvas.style.color = "red"; - noCanvas.style.fontWeight = "bold" ; - noCanvas.style.padding = "10px"; - noCanvas.innerHTML = "Error: your browser does not support HTML canvas"; + var noCanvas = document.createElement( 'DIV' ); + noCanvas.style.color = 'red'; + noCanvas.style.fontWeight = 'bold' ; + noCanvas.style.padding = '10px'; + noCanvas.innerHTML = 'Error: your browser does not support HTML canvas'; this.frame.canvas.appendChild(noCanvas); } @@ -13171,8 +13170,8 @@ Graph.prototype._create = function () { * @private */ Graph.prototype._getNodeAt = function (pointer) { - var x = this._xToCanvas(pointer.x); - var y = this._yToCanvas(pointer.y); + var x = this._canvasToX(pointer.x); + var y = this._canvasToY(pointer.y); var obj = { left: x, @@ -13281,11 +13280,11 @@ Graph.prototype._onDrag = function (event) { var node = s.node; if (!s.xFixed) { - node.x = me._xToCanvas(me._canvasToX(s.x) + deltaX); + node.x = me._canvasToX(me._xToCanvas(s.x) + deltaX); } if (!s.yFixed) { - node.y = me._yToCanvas(me._canvasToY(s.y) + deltaY); + node.y = me._canvasToY(me._yToCanvas(s.y) + deltaY); } }); @@ -13509,10 +13508,10 @@ Graph.prototype._onMouseMoveTitle = function (event) { */ Graph.prototype._checkShowPopup = function (pointer) { var obj = { - left: this._xToCanvas(pointer.x), - top: this._yToCanvas(pointer.y), - right: this._xToCanvas(pointer.x), - bottom: this._yToCanvas(pointer.y) + left: this._canvasToX(pointer.x), + top: this._canvasToY(pointer.y), + right: this._canvasToX(pointer.x), + bottom: this._canvasToY(pointer.y) }; var id; @@ -13730,7 +13729,7 @@ Graph.prototype.setSelection = function(selection) { var i, iMax, id; if (!selection || (selection.length == undefined)) - throw "Selection must be an array with ids"; + throw 'Selection must be an array with ids'; // first unselect any selected node for (i = 0, iMax = this.selection.length; i < iMax; i++) { @@ -13853,17 +13852,17 @@ Graph.prototype._getConnectionCount = function(level) { /** * Set a new size for the graph - * @param {string} width Width in pixels or percentage (for example "800px" - * or "50%") - * @param {string} height Height in pixels or percentage (for example "400px" - * or "30%") + * @param {string} width Width in pixels or percentage (for example '800px' + * or '50%') + * @param {string} height Height in pixels or percentage (for example '400px' + * or '30%') */ Graph.prototype.setSize = function(width, height) { this.frame.style.width = width; this.frame.style.height = height; - this.frame.canvas.style.width = "100%"; - this.frame.canvas.style.height = "100%"; + this.frame.canvas.style.width = '100%'; + this.frame.canvas.style.height = '100%'; this.frame.canvas.width = this.frame.canvas.clientWidth; this.frame.canvas.height = this.frame.canvas.clientHeight; @@ -14190,7 +14189,7 @@ Graph.prototype.redraw = function() { * @private */ Graph.prototype._redraw = function() { - var ctx = this.frame.canvas.getContext("2d"); + var ctx = this.frame.canvas.getContext('2d'); // clear the canvas var w = this.frame.canvas.width; @@ -14218,8 +14217,8 @@ Graph.prototype._redraw = function() { Graph.prototype._setTranslation = function(offsetX, offsetY) { if (this.translation === undefined) { this.translation = { - "x": 0, - "y": 0 + x: 0, + y: 0 }; } @@ -14238,8 +14237,8 @@ Graph.prototype._setTranslation = function(offsetX, offsetY) { */ Graph.prototype._getTranslation = function() { return { - "x": this.translation.x, - "y": this.translation.y + x: this.translation.x, + y: this.translation.y }; }; @@ -14260,25 +14259,49 @@ Graph.prototype._getScale = function() { return this.scale; }; -Graph.prototype._xToCanvas = function(x) { +/** + * Convert a horizontal point on the HTML canvas to the x-value of the model + * @param {number} x + * @returns {number} + * @private + */ +Graph.prototype._canvasToX = function(x) { return (x - this.translation.x) / this.scale; }; -Graph.prototype._canvasToX = function(x) { +/** + * Convert an x-value in the model to a horizontal point on the HTML canvas + * @param {number} x + * @returns {number} + * @private + */ +Graph.prototype._xToCanvas = function(x) { return x * this.scale + this.translation.x; }; -Graph.prototype._yToCanvas = function(y) { +/** + * Convert a vertical point on the HTML canvas to the y-value of the model + * @param {number} y + * @returns {number} + * @private + */ +Graph.prototype._canvasToY = function(y) { return (y - this.translation.y) / this.scale; }; -Graph.prototype._canvasToY = function(y) { +/** + * Convert an y-value in the model to a vertical point on the HTML canvas + * @param {number} y + * @returns {number} + * @private + */ +Graph.prototype._yToCanvas = function(y) { return y * this.scale + this.translation.y ; }; /** * Redraw all nodes - * The 2d context of a HTML canvas can be retrieved by canvas.getContext("2d"); + * The 2d context of a HTML canvas can be retrieved by canvas.getContext('2d'); * @param {CanvasRenderingContext2D} ctx * @private */ @@ -14305,7 +14328,7 @@ Graph.prototype._drawNodes = function(ctx) { /** * Redraw all edges - * The 2d context of a HTML canvas can be retrieved by canvas.getContext("2d"); + * The 2d context of a HTML canvas can be retrieved by canvas.getContext('2d'); * @param {CanvasRenderingContext2D} ctx * @private */ @@ -14341,7 +14364,7 @@ Graph.prototype._doStabilize = function() { var end = new Date(); - // console.log("Stabilized in " + (end-start) + " ms, " + count + " iterations" ); // TODO: cleanup + // console.log('Stabilized in ' + (end-start) + ' ms, ' + count + ' iterations' ); // TODO: cleanup }; /** @@ -14498,7 +14521,7 @@ Graph.prototype._calculateForces = function() { /** * Check if any of the nodes is still moving - * @param {number} vmin the minimum velocity considered as "moving" + * @param {number} vmin the minimum velocity considered as 'moving' * @return {boolean} true if moving, false if non of the nodes is moving * @private */ diff --git a/vis.min.js b/vis.min.js index 3cc9e542..2b24b43d 100644 --- a/vis.min.js +++ b/vis.min.js @@ -26,4 +26,4 @@ }this.subscribers={},this.internalIds={}}function r(t,e){this.id=O.randomUUID(),this.data=null,this.ids={},this.options=e||{},this.fieldId="id",this.subscribers={};var i=this;this.listener=function(){i._onEvent.apply(i,arguments)},this.setData(t)}function a(t,e){this.parent=t,this.options=e||{},this.defaultOptions={order:function(t,e){if(t instanceof y){if(e instanceof y){var i=t.data.end-t.data.start,n=e.data.end-e.data.start;return i-n||t.data.start-e.data.start}return-1}return e instanceof y?1:t.data.start-e.data.start},margin:{item:10}},this.ordered=[]}function h(t){this.id=O.randomUUID(),this.start=0,this.end=0,this.options={min:null,max:null,zoomMin:null,zoomMax:null},this.listeners=[],this.setOptions(t)}function d(){this.id=O.randomUUID(),this.components={},this.repaintTimer=void 0,this.reflowTimer=void 0}function l(){this.id=null,this.parent=null,this.depends=null,this.controller=null,this.options=null,this.frame=null,this.top=0,this.left=0,this.width=0,this.height=0}function p(t,e,i){this.id=O.randomUUID(),this.parent=t,this.depends=e,this.options=i||{}}function c(t,e){this.id=O.randomUUID(),this.container=t,this.options=e||{},this.defaultOptions={autoResize:!0},this.listeners={}}function u(t,e,i){this.id=O.randomUUID(),this.parent=t,this.depends=e,this.dom={majorLines:[],majorTexts:[],minorLines:[],minorTexts:[],redundant:{majorLines:[],majorTexts:[],minorLines:[],minorTexts:[]}},this.props={range:{start:0,end:0,minimumStep:0},lineTop:0},this.options=i||{},this.defaultOptions={orientation:"bottom",showMinorLabels:!0,showMajorLabels:!0},this.conversion=null,this.range=null}function f(t,e,i){this.id=O.randomUUID(),this.parent=t,this.depends=e,this.options=i||{},this.defaultOptions={type:"box",align:"center",orientation:"bottom",margin:{axis:20,item:10},padding:5},this.dom={};var n=this;this.itemsData=null,this.range=null,this.listeners={add:function(t,e,i){i!=n.id&&n._onAdd(e.items)},update:function(t,e,i){i!=n.id&&n._onUpdate(e.items)},remove:function(t,e,i){i!=n.id&&n._onRemove(e.items)}},this.items={},this.queue={},this.stack=new a(this,Object.create(this.options)),this.conversion=null}function m(t,e,i,n){this.parent=t,this.data=e,this.dom=null,this.options=i||{},this.defaultOptions=n||{},this.selected=!1,this.visible=!1,this.top=0,this.left=0,this.width=0,this.height=0}function g(t,e,i,n){this.props={dot:{left:0,top:0,width:0,height:0},line:{top:0,left:0,width:0,height:0}},m.call(this,t,e,i,n)}function v(t,e,i,n){this.props={dot:{top:0,width:0,height:0},content:{height:0,marginLeft:0}},m.call(this,t,e,i,n)}function y(t,e,i,n){this.props={content:{left:0,width:0}},m.call(this,t,e,i,n)}function b(t,e,i){this.id=O.randomUUID(),this.parent=t,this.groupId=e,this.itemset=null,this.options=i||{},this.options.top=0,this.props={label:{width:0,height:0}},this.top=0,this.left=0,this.width=0,this.height=0}function w(t,e,i){this.id=O.randomUUID(),this.parent=t,this.depends=e,this.options=i||{},this.range=null,this.itemsData=null,this.groupsData=null,this.groups={},this.dom={},this.props={labels:{width:0}},this.queue={};var n=this;this.listeners={add:function(t,e){n._onAdd(e.items)},update:function(t,e){n._onUpdate(e.items)},remove:function(t,e){n._onRemove(e.items)}}}function _(t,e,i){var n=this;if(this.options=O.extend({orientation:"bottom",min:null,max:null,zoomMin:10,zoomMax:31536e10,showMinorLabels:!0,showMajorLabels:!0,autoResize:!1},i),this.controller=new d,!t)throw Error("No container element provided");var s=Object.create(this.options);s.height=function(){return n.options.height?n.options.height:n.timeaxis.height+n.content.height},this.rootPanel=new c(t,s),this.controller.add(this.rootPanel);var o=Object.create(this.options);o.left=function(){return n.labelPanel.width},o.width=function(){return n.rootPanel.width-n.labelPanel.width},o.top=null,o.height=null,this.itemPanel=new p(this.rootPanel,[],o),this.controller.add(this.itemPanel);var r=Object.create(this.options);r.top=null,r.left=null,r.height=null,r.width=function(){return n.content&&"function"==typeof n.content.getLabelsWidth?n.content.getLabelsWidth():0},this.labelPanel=new p(this.rootPanel,[],r),this.controller.add(this.labelPanel);var a=M().hours(0).minutes(0).seconds(0).milliseconds(0);this.range=new h({start:a.clone().add("days",-3).valueOf(),end:a.clone().add("days",4).valueOf()}),this.range.subscribe(this.rootPanel,"move","horizontal"),this.range.subscribe(this.rootPanel,"zoom","horizontal"),this.range.on("rangechange",function(){var t=!0;n.controller.requestReflow(t)}),this.range.on("rangechanged",function(){var t=!0;n.controller.requestReflow(t)});var l=Object.create(s);l.range=this.range,l.left=null,l.top=null,l.width="100%",l.height=null,this.timeaxis=new u(this.itemPanel,[],l),this.timeaxis.setRange(this.range),this.controller.add(this.timeaxis),this.setGroups(null),this.itemsData=null,this.groupsData=null,e&&this.setItems(e)}function E(t,e,i,n){this.selected=!1,this.edges=[],this.group=n.nodes.group,this.fontSize=n.nodes.fontSize,this.fontFace=n.nodes.fontFace,this.fontColor=n.nodes.fontColor,this.color=n.nodes.color,this.id=void 0,this.shape=n.nodes.shape,this.image=n.nodes.image,this.x=0,this.y=0,this.xFixed=!1,this.yFixed=!1,this.radius=n.nodes.radius,this.radiusFixed=!1,this.radiusMin=n.nodes.radiusMin,this.radiusMax=n.nodes.radiusMax,this.imagelist=e,this.grouplist=i,this.setProperties(t,n),this.mass=50,this.fx=0,this.fy=0,this.vx=0,this.vy=0,this.minForce=n.minForce,this.damping=.9}function T(t,e,i){if(!e)throw"No graph provided";this.graph=e,this.widthMin=i.edges.widthMin,this.widthMax=i.edges.widthMax,this.id=void 0,this.fromId=void 0,this.toId=void 0,this.style=i.edges.style,this.title=void 0,this.width=i.edges.width,this.value=void 0,this.length=i.edges.length,this.from=null,this.to=null,this.connected=!1,this.dash=O.extend({},i.edges.dash),this.stiffness=void 0,this.color=i.edges.color,this.widthFixed=!1,this.lengthFixed=!1,this.setProperties(t,i)}function x(t,e,i,n){this.container=t?t:document.body,this.x=0,this.y=0,this.padding=5,void 0!==e&&void 0!==i&&this.setPosition(e,i),void 0!==n&&this.setText(n),this.frame=document.createElement("div");var s=this.frame.style;s.position="absolute",s.visibility="hidden",s.border="1px solid #666",s.color="black",s.padding=this.padding+"px",s.backgroundColor="#FFFFC6",s.borderRadius="3px",s.MozBorderRadius="3px",s.WebkitBorderRadius="3px",s.boxShadow="3px 3px 10px rgba(128, 128, 128, 0.5)",s.whiteSpace="nowrap",this.container.appendChild(this.frame)}function S(t,e,i){this.containerElement=t,this.width="100%",this.height="100%",this.refreshRate=50,this.stabilize=!0,this.selectable=!0,this.constants={nodes:{radiusMin:5,radiusMax:20,radius:5,distance:100,shape:"ellipse",image:void 0,widthMin:16,widthMax:64,fontColor:"black",fontSize:14,fontFace:"arial",color:{border:"#2B7CE9",background:"#97C2FC",highlight:{border:"#2B7CE9",background:"#D2E5FF"}},borderColor:"#2B7CE9",backgroundColor:"#97C2FC",highlightColor:"#D2E5FF",group:void 0},edges:{widthMin:1,widthMax:15,width:1,style:"line",color:"#343434",fontColor:"#343434",fontSize:14,fontFace:"arial",length:100,dash:{length:10,gap:5,altLength:void 0}},minForce:.05,minVelocity:.02,maxIterations:1e3};var n=this;this.nodes={},this.edges={},this.nodesData=null,this.edgesData=null;var s=this;this.nodesListeners={add:function(t,e){s._addNodes(e.items),s.start()},update:function(t,e){s._updateNodes(e.items),s.start()},remove:function(t,e){s._removeNodes(e.items),s.start()}},this.edgesListeners={add:function(t,e){s._addEdges(e.items),s.start()},update:function(t,e){s._updateEdges(e.items),s.start()},remove:function(t,e){s._removeEdges(e.items),s.start()}},this.groups=new Groups,this.images=new Images,this.images.setOnloadCallback(function(){n._redraw()}),this.moving=!1,this.selection=[],this.timer=void 0,this._create(),this.setOptions(i),this.setData(e)}var M="undefined"!=typeof window&&window.moment||e("moment"),D="undefined"!=typeof window&&window.Hammer||e("hammerjs");if(!Array.prototype.indexOf){Array.prototype.indexOf=function(t){for(var e=0;this.length>e;e++)if(this[e]==t)return e;return-1};try{console.log("Warning: Ancient browser detected. Please update your browser")}catch(C){}}Array.prototype.forEach||(Array.prototype.forEach=function(t,e){for(var i=0,n=this.length;n>i;++i)t.call(e||this,this[i],i,this)}),Array.prototype.map||(Array.prototype.map=function(t,e){var i,n,s;if(null==this)throw new TypeError(" this is null or not defined");var o=Object(this),r=o.length>>>0;if("function"!=typeof t)throw new TypeError(t+" is not a function");for(e&&(i=e),n=Array(r),s=0;r>s;){var a,h;s in o&&(a=o[s],h=t.call(i,a,s,o),n[s]=h),s++}return n}),Array.prototype.filter||(Array.prototype.filter=function(t){"use strict";if(null==this)throw new TypeError;var e=Object(this),i=e.length>>>0;if("function"!=typeof t)throw new TypeError;for(var n=[],s=arguments[1],o=0;i>o;o++)if(o in e){var r=e[o];t.call(s,r,o,e)&&n.push(r)}return n}),Object.keys||(Object.keys=function(){var t=Object.prototype.hasOwnProperty,e=!{toString:null}.propertyIsEnumerable("toString"),i=["toString","toLocaleString","valueOf","hasOwnProperty","isPrototypeOf","propertyIsEnumerable","constructor"],n=i.length;return function(s){if("object"!=typeof s&&"function"!=typeof s||null===s)throw new TypeError("Object.keys called on non-object");var o=[];for(var r in s)t.call(s,r)&&o.push(r);if(e)for(var a=0;n>a;a++)t.call(s,i[a])&&o.push(i[a]);return o}}()),Array.isArray||(Array.isArray=function(t){return"[object Array]"===Object.prototype.toString.call(t)}),Function.prototype.bind||(Function.prototype.bind=function(t){if("function"!=typeof this)throw new TypeError("Function.prototype.bind - what is trying to be bound is not callable");var e=Array.prototype.slice.call(arguments,1),i=this,n=function(){},s=function(){return i.apply(this instanceof n&&t?this:t,e.concat(Array.prototype.slice.call(arguments)))};return n.prototype=this.prototype,s.prototype=new n,s}),Object.create||(Object.create=function(t){function e(){}if(arguments.length>1)throw Error("Object.create implementation only accepts the first parameter.");return e.prototype=t,new e}),Function.prototype.bind||(Function.prototype.bind=function(t){if("function"!=typeof this)throw new TypeError("Function.prototype.bind - what is trying to be bound is not callable");var e=Array.prototype.slice.call(arguments,1),i=this,n=function(){},s=function(){return i.apply(this instanceof n&&t?this:t,e.concat(Array.prototype.slice.call(arguments)))};return n.prototype=this.prototype,s.prototype=new n,s});var O={};O.isNumber=function(t){return t instanceof Number||"number"==typeof t},O.isString=function(t){return t instanceof String||"string"==typeof t},O.isDate=function(t){if(t instanceof Date)return!0;if(O.isString(t)){var e=N.exec(t);if(e)return!0;if(!isNaN(Date.parse(t)))return!0}return!1},O.isDataTable=function(t){return"undefined"!=typeof google&&google.visualization&&google.visualization.DataTable&&t instanceof google.visualization.DataTable},O.randomUUID=function(){var t=function(){return Math.floor(65536*Math.random()).toString(16)};return t()+t()+"-"+t()+"-"+t()+"-"+t()+"-"+t()+t()+t()},O.extend=function(t){for(var e=1,i=arguments.length;i>e;e++){var n=arguments[e];for(var s in n)n.hasOwnProperty(s)&&void 0!==n[s]&&(t[s]=n[s])}return t},O.convert=function(t,e){var i;if(void 0===t)return void 0;if(null===t)return null;if(!e)return t;if("string"!=typeof e&&!(e instanceof String))throw Error("Type must be a string");switch(e){case"boolean":case"Boolean":return Boolean(t);case"number":case"Number":return Number(t.valueOf());case"string":case"String":return t+"";case"Date":if(O.isNumber(t))return new Date(t);if(t instanceof Date)return new Date(t.valueOf());if(M.isMoment(t))return new Date(t.valueOf());if(O.isString(t))return i=N.exec(t),i?new Date(Number(i[1])):M(t).toDate();throw Error("Cannot convert object of type "+O.getType(t)+" to type Date");case"Moment":if(O.isNumber(t))return M(t);if(t instanceof Date)return M(t.valueOf());if(M.isMoment(t))return M.clone();if(O.isString(t))return i=N.exec(t),i?M(Number(i[1])):M(t);throw Error("Cannot convert object of type "+O.getType(t)+" to type Date");case"ISODate":if(O.isNumber(t))return new Date(t);if(t instanceof Date)return t.toISOString();if(M.isMoment(t))return t.toDate().toISOString();if(O.isString(t))return i=N.exec(t),i?new Date(Number(i[1])).toISOString():new Date(t).toISOString();throw Error("Cannot convert object of type "+O.getType(t)+" to type ISODate");case"ASPDate":if(O.isNumber(t))return"/Date("+t+")/";if(t instanceof Date)return"/Date("+t.valueOf()+")/";if(O.isString(t)){i=N.exec(t);var n;return n=i?new Date(Number(i[1])).valueOf():new Date(t).valueOf(),"/Date("+n+")/"}throw Error("Cannot convert object of type "+O.getType(t)+" to type ASPDate");default:throw Error("Cannot convert object of type "+O.getType(t)+' to type "'+e+'"')}};var N=/^\/?Date\((\-?\d+)/i;O.getType=function(t){var e=typeof t;return"object"==e?null==t?"null":t instanceof Boolean?"Boolean":t instanceof Number?"Number":t instanceof String?"String":t instanceof Array?"Array":t instanceof Date?"Date":"Object":"number"==e?"Number":"boolean"==e?"Boolean":"string"==e?"String":e},O.getAbsoluteLeft=function(t){for(var e=document.documentElement,i=document.body,n=t.offsetLeft,s=t.offsetParent;null!=s&&s!=i&&s!=e;)n+=s.offsetLeft,n-=s.scrollLeft,s=s.offsetParent;return n},O.getAbsoluteTop=function(t){for(var e=document.documentElement,i=document.body,n=t.offsetTop,s=t.offsetParent;null!=s&&s!=i&&s!=e;)n+=s.offsetTop,n-=s.scrollTop,s=s.offsetParent;return n},O.getPageY=function(t){if("pageY"in t)return t.pageY;var e;e="targetTouches"in t&&t.targetTouches.length?t.targetTouches[0].clientY:t.clientY;var i=document.documentElement,n=document.body;return e+(i&&i.scrollTop||n&&n.scrollTop||0)-(i&&i.clientTop||n&&n.clientTop||0)},O.getPageX=function(t){if("pageY"in t)return t.pageX;var e;e="targetTouches"in t&&t.targetTouches.length?t.targetTouches[0].clientX:t.clientX;var i=document.documentElement,n=document.body;return e+(i&&i.scrollLeft||n&&n.scrollLeft||0)-(i&&i.clientLeft||n&&n.clientLeft||0)},O.addClassName=function(t,e){var i=t.className.split(" ");-1==i.indexOf(e)&&(i.push(e),t.className=i.join(" "))},O.removeClassName=function(t,e){var i=t.className.split(" "),n=i.indexOf(e);-1!=n&&(i.splice(n,1),t.className=i.join(" "))},O.forEach=function(t,e){var i,n;if(t instanceof Array)for(i=0,n=t.length;n>i;i++)e(t[i],i,t);else for(i in t)t.hasOwnProperty(i)&&e(t[i],i,t)},O.updateProperty=function(t,e,i){return t[e]!==i?(t[e]=i,!0):!1},O.addEventListener=function(t,e,i,n){t.addEventListener?(void 0===n&&(n=!1),"mousewheel"===e&&navigator.userAgent.indexOf("Firefox")>=0&&(e="DOMMouseScroll"),t.addEventListener(e,i,n)):t.attachEvent("on"+e,i)},O.removeEventListener=function(t,e,i,n){t.removeEventListener?(void 0===n&&(n=!1),"mousewheel"===e&&navigator.userAgent.indexOf("Firefox")>=0&&(e="DOMMouseScroll"),t.removeEventListener(e,i,n)):t.detachEvent("on"+e,i)},O.getTarget=function(t){t||(t=window.event);var e;return t.target?e=t.target:t.srcElement&&(e=t.srcElement),void 0!=e.nodeType&&3==e.nodeType&&(e=e.parentNode),e},O.stopPropagation=function(t){t||(t=window.event),t.stopPropagation?t.stopPropagation():t.cancelBubble=!0},O.preventDefault=function(t){t||(t=window.event),t.preventDefault?t.preventDefault():t.returnValue=!1},O.option={},O.option.asBoolean=function(t,e){return"function"==typeof t&&(t=t()),null!=t?0!=t:e||null},O.option.asNumber=function(t,e){return"function"==typeof t&&(t=t()),null!=t?Number(t)||e||null:e||null},O.option.asString=function(t,e){return"function"==typeof t&&(t=t()),null!=t?t+"":e||null},O.option.asSize=function(t,e){return"function"==typeof t&&(t=t()),O.isString(t)?t:O.isNumber(t)?t+"px":e||null},O.option.asElement=function(t,e){return"function"==typeof t&&(t=t()),t||e||null},O.loadCss=function(t){if("undefined"!=typeof document){var e=document.createElement("style");e.type="text/css",e.styleSheet?e.styleSheet.cssText=t:e.appendChild(document.createTextNode(t)),document.getElementsByTagName("head")[0].appendChild(e)}};var L={listeners:[],indexOf:function(t){for(var e=this.listeners,i=0,n=this.listeners.length;n>i;i++){var s=e[i];if(s&&s.object==t)return i}return-1},addListener:function(t,e,i){var n=this.indexOf(t),s=this.listeners[n];s||(s={object:t,events:{}},this.listeners.push(s));var o=s.events[e];o||(o=[],s.events[e]=o),-1==o.indexOf(i)&&o.push(i)},removeListener:function(t,e,i){var n=this.indexOf(t),s=this.listeners[n];if(s){var o=s.events[e];o&&(n=o.indexOf(i),-1!=n&&o.splice(n,1),0==o.length&&delete s.events[e]);var r=0,a=s.events;for(var h in a)a.hasOwnProperty(h)&&r++;0==r&&delete this.listeners[n]}},removeAllListeners:function(){this.listeners=[]},trigger:function(t,e,i){var n=this.indexOf(t),s=this.listeners[n];if(s){var o=s.events[e];if(o)for(var r=0,a=o.length;a>r;r++)o[r](i)}}};s.prototype.on=function(t,e,i){var n=t instanceof RegExp?t:RegExp(t.replace("*","\\w+")),s={id:O.randomUUID(),event:t,regexp:n,callback:"function"==typeof e?e:null,target:i};return this.subscriptions.push(s),s.id},s.prototype.off=function(t){for(var e=0;this.subscriptions.length>e;){var i=this.subscriptions[e],n=!0;if(t instanceof Object)for(var s in t)t.hasOwnProperty(s)&&t[s]!==i[s]&&(n=!1);else n=i.id==t;n?this.subscriptions.splice(e,1):e++}},s.prototype.emit=function(t,e,i){for(var n=0;this.subscriptions.length>n;n++){var s=this.subscriptions[n];s.regexp.test(t)&&s.callback&&s.callback(t,e,i)}},o.prototype.subscribe=function(t,e){var i=this.subscribers[t];i||(i=[],this.subscribers[t]=i),i.push({callback:e})},o.prototype.unsubscribe=function(t,e){var i=this.subscribers[t];i&&(this.subscribers[t]=i.filter(function(t){return t.callback!=e}))},o.prototype._trigger=function(t,e,i){if("*"==t)throw Error("Cannot trigger event *");var n=[];t in this.subscribers&&(n=n.concat(this.subscribers[t])),"*"in this.subscribers&&(n=n.concat(this.subscribers["*"]));for(var s=0;n.length>s;s++){var o=n[s];o.callback&&o.callback(t,e,i||null)}},o.prototype.add=function(t,e){var i,n=[],s=this;if(t instanceof Array)for(var o=0,r=t.length;r>o;o++)i=s._addItem(t[o]),n.push(i);else if(O.isDataTable(t))for(var a=this._getColumnNames(t),h=0,d=t.getNumberOfRows();d>h;h++){for(var l={},p=0,c=a.length;c>p;p++){var u=a[p];l[u]=t.getValue(h,p)}i=s._addItem(l),n.push(i)}else{if(!(t instanceof Object))throw Error("Unknown dataType");i=s._addItem(t),n.push(i)}return n.length&&this._trigger("add",{items:n},e),n},o.prototype.update=function(t,e){var i=[],n=[],s=this,o=s.fieldId,r=function(t){var e=t[o];s.data[e]?(e=s._updateItem(t),n.push(e)):(e=s._addItem(t),i.push(e))};if(t instanceof Array)for(var a=0,h=t.length;h>a;a++)r(t[a]);else if(O.isDataTable(t))for(var d=this._getColumnNames(t),l=0,p=t.getNumberOfRows();p>l;l++){for(var c={},u=0,f=d.length;f>u;u++){var m=d[u];c[m]=t.getValue(l,u)}r(c)}else{if(!(t instanceof Object))throw Error("Unknown dataType");r(t)}return i.length&&this._trigger("add",{items:i},e),n.length&&this._trigger("update",{items:n},e),i.concat(n)},o.prototype.get=function(){var t,e,i,n,s=this,o=O.getType(arguments[0]);"String"==o||"Number"==o?(t=arguments[0],i=arguments[1],n=arguments[2]):"Array"==o?(e=arguments[0],i=arguments[1],n=arguments[2]):(i=arguments[0],n=arguments[1]);var r;if(i&&i.type){if(r="DataTable"==i.type?"DataTable":"Array",n&&r!=O.getType(n))throw Error('Type of parameter "data" ('+O.getType(n)+") "+"does not correspond with specified options.type ("+i.type+")");if("DataTable"==r&&!O.isDataTable(n))throw Error('Parameter "data" must be a DataTable when options.type is "DataTable"')}else r=n?"DataTable"==O.getType(n)?"DataTable":"Array":"Array";var a,h,d,l,p=i&&i.convert||this.options.convert,c=i&&i.filter,u=[];if(void 0!=t)a=s._getItem(t,p),c&&!c(a)&&(a=null);else if(void 0!=e)for(d=0,l=e.length;l>d;d++)a=s._getItem(e[d],p),(!c||c(a))&&u.push(a);else for(h in this.data)this.data.hasOwnProperty(h)&&(a=s._getItem(h,p),(!c||c(a))&&u.push(a));if(i&&i.order&&void 0==t&&this._sort(u,i.order),i&&i.fields){var f=i.fields;if(void 0!=t)a=this._filterFields(a,f);else for(d=0,l=u.length;l>d;d++)u[d]=this._filterFields(u[d],f)}if("DataTable"==r){var m=this._getColumnNames(n);if(void 0!=t)s._appendRow(n,m,a);else for(d=0,l=u.length;l>d;d++)s._appendRow(n,m,u[d]);return n}if(void 0!=t)return a;if(n){for(d=0,l=u.length;l>d;d++)n.push(u[d]);return n}return u},o.prototype.getIds=function(t){var e,i,n,s,o,r=this.data,a=t&&t.filter,h=t&&t.order,d=t&&t.convert||this.options.convert,l=[];if(a)if(h){o=[];for(n in r)r.hasOwnProperty(n)&&(s=this._getItem(n,d),a(s)&&o.push(s));for(this._sort(o,h),e=0,i=o.length;i>e;e++)l[e]=o[e][this.fieldId]}else for(n in r)r.hasOwnProperty(n)&&(s=this._getItem(n,d),a(s)&&l.push(s[this.fieldId]));else if(h){o=[];for(n in r)r.hasOwnProperty(n)&&o.push(r[n]);for(this._sort(o,h),e=0,i=o.length;i>e;e++)l[e]=o[e][this.fieldId]}else for(n in r)r.hasOwnProperty(n)&&(s=r[n],l.push(s[this.fieldId]));return l},o.prototype.forEach=function(t,e){var i,n,s=e&&e.filter,o=e&&e.convert||this.options.convert,r=this.data;if(e&&e.order)for(var a=this.get(e),h=0,d=a.length;d>h;h++)i=a[h],n=i[this.fieldId],t(i,n);else for(n in r)r.hasOwnProperty(n)&&(i=this._getItem(n,o),(!s||s(i))&&t(i,n))},o.prototype.map=function(t,e){var i,n=e&&e.filter,s=e&&e.convert||this.options.convert,o=[],r=this.data;for(var a in r)r.hasOwnProperty(a)&&(i=this._getItem(a,s),(!n||n(i))&&o.push(t(i,a)));return e&&e.order&&this._sort(o,e.order),o},o.prototype._filterFields=function(t,e){var i={};for(var n in t)t.hasOwnProperty(n)&&-1!=e.indexOf(n)&&(i[n]=t[n]);return i},o.prototype._sort=function(t,e){if(O.isString(e)){var i=e;t.sort(function(t,e){var n=t[i],s=e[i];return n>s?1:s>n?-1:0})}else{if("function"!=typeof e)throw new TypeError("Order must be a function or a string");t.sort(e)}},o.prototype.remove=function(t,e){var i,n,s,o=[];if(t instanceof Array)for(i=0,n=t.length;n>i;i++)s=this._remove(t[i]),null!=s&&o.push(s);else s=this._remove(t),null!=s&&o.push(s);return o.length&&this._trigger("remove",{items:o},e),o},o.prototype._remove=function(t){if(O.isNumber(t)||O.isString(t)){if(this.data[t])return delete this.data[t],delete this.internalIds[t],t}else if(t instanceof Object){var e=t[this.fieldId];if(e&&this.data[e])return delete this.data[e],delete this.internalIds[e],e}return null},o.prototype.clear=function(t){var e=Object.keys(this.data);return this.data={},this.internalIds={},this._trigger("remove",{items:e},t),e},o.prototype.max=function(t){var e=this.data,i=null,n=null;for(var s in e)if(e.hasOwnProperty(s)){var o=e[s],r=o[t];null!=r&&(!i||r>n)&&(i=o,n=r)}return i},o.prototype.min=function(t){var e=this.data,i=null,n=null;for(var s in e)if(e.hasOwnProperty(s)){var o=e[s],r=o[t];null!=r&&(!i||n>r)&&(i=o,n=r)}return i},o.prototype.distinct=function(t){var e=this.data,i=[],n=this.options.convert[t],s=0;for(var o in e)if(e.hasOwnProperty(o)){for(var r=e[o],a=O.convert(r[t],n),h=!1,d=0;s>d;d++)if(i[d]==a){h=!0;break}h||(i[s]=a,s++)}return i},o.prototype._addItem=function(t){var e=t[this.fieldId];if(void 0!=e){if(this.data[e])throw Error("Cannot add item: item with id "+e+" already exists")}else e=O.randomUUID(),t[this.fieldId]=e,this.internalIds[e]=t;var i={};for(var n in t)if(t.hasOwnProperty(n)){var s=this.convert[n];i[n]=O.convert(t[n],s)}return this.data[e]=i,e},o.prototype._getItem=function(t,e){var i,n,s=this.data[t];if(!s)return null;var o={},r=this.fieldId,a=this.internalIds;if(e)for(i in s)s.hasOwnProperty(i)&&(n=s[i],i==r&&n in a||(o[i]=O.convert(n,e[i])));else for(i in s)s.hasOwnProperty(i)&&(n=s[i],i==r&&n in a||(o[i]=n));return o},o.prototype._updateItem=function(t){var e=t[this.fieldId];if(void 0==e)throw Error("Cannot update item: item has no id (item: "+JSON.stringify(t)+")");var i=this.data[e];if(!i)throw Error("Cannot update item: no item with id "+e+" found");for(var n in t)if(t.hasOwnProperty(n)){var s=this.convert[n];i[n]=O.convert(t[n],s)}return e},o.prototype._getColumnNames=function(t){for(var e=[],i=0,n=t.getNumberOfColumns();n>i;i++)e[i]=t.getColumnId(i)||t.getColumnLabel(i);return e},o.prototype._appendRow=function(t,e,i){for(var n=t.addRow(),s=0,o=e.length;o>s;s++){var r=e[s];t.setValue(n,s,i[r])}},r.prototype.setData=function(t){var e,i,n;if(this.data){this.data.unsubscribe&&this.data.unsubscribe("*",this.listener),e=[];for(var s in this.ids)this.ids.hasOwnProperty(s)&&e.push(s);this.ids={},this._trigger("remove",{items:e})}if(this.data=t,this.data){for(this.fieldId=this.options.fieldId||this.data&&this.data.options&&this.data.options.fieldId||"id",e=this.data.getIds({filter:this.options&&this.options.filter}),i=0,n=e.length;n>i;i++)s=e[i],this.ids[s]=!0;this._trigger("add",{items:e}),this.data.subscribe&&this.data.subscribe("*",this.listener)}},r.prototype.get=function(){var t,e,i,n=this,s=O.getType(arguments[0]);"String"==s||"Number"==s||"Array"==s?(t=arguments[0],e=arguments[1],i=arguments[2]):(e=arguments[0],i=arguments[1]);var o=O.extend({},this.options,e);this.options.filter&&e&&e.filter&&(o.filter=function(t){return n.options.filter(t)&&e.filter(t)});var r=[];return void 0!=t&&r.push(t),r.push(o),r.push(i),this.data&&this.data.get.apply(this.data,r)},r.prototype.getIds=function(t){var e;if(this.data){var i,n=this.options.filter;i=t&&t.filter?n?function(e){return n(e)&&t.filter(e)}:t.filter:n,e=this.data.getIds({filter:i,order:t&&t.order})}else e=[];return e},r.prototype._onEvent=function(t,e,i){var n,s,o,r,a=e&&e.items,h=this.data,d=[],l=[],p=[];if(a&&h){switch(t){case"add":for(n=0,s=a.length;s>n;n++)o=a[n],r=this.get(o),r&&(this.ids[o]=!0,d.push(o));break;case"update":for(n=0,s=a.length;s>n;n++)o=a[n],r=this.get(o),r?this.ids[o]?l.push(o):(this.ids[o]=!0,d.push(o)):this.ids[o]&&(delete this.ids[o],p.push(o));break;case"remove":for(n=0,s=a.length;s>n;n++)o=a[n],this.ids[o]&&(delete this.ids[o],p.push(o))}d.length&&this._trigger("add",{items:d},i),l.length&&this._trigger("update",{items:l},i),p.length&&this._trigger("remove",{items:p},i)}},r.prototype.subscribe=o.prototype.subscribe,r.prototype.unsubscribe=o.prototype.unsubscribe,r.prototype._trigger=o.prototype._trigger,TimeStep=function(t,e,i){this.current=new Date,this._start=new Date,this._end=new Date,this.autoScale=!0,this.scale=TimeStep.SCALE.DAY,this.step=1,this.setRange(t,e,i)},TimeStep.SCALE={MILLISECOND:1,SECOND:2,MINUTE:3,HOUR:4,DAY:5,WEEKDAY:6,MONTH:7,YEAR:8},TimeStep.prototype.setRange=function(t,e,i){t instanceof Date&&e instanceof Date&&(this._start=void 0!=t?new Date(t.valueOf()):new Date,this._end=void 0!=e?new Date(e.valueOf()):new Date,this.autoScale&&this.setMinimumStep(i))},TimeStep.prototype.first=function(){this.current=new Date(this._start.valueOf()),this.roundToMinor()},TimeStep.prototype.roundToMinor=function(){switch(this.scale){case TimeStep.SCALE.YEAR:this.current.setFullYear(this.step*Math.floor(this.current.getFullYear()/this.step)),this.current.setMonth(0);case TimeStep.SCALE.MONTH:this.current.setDate(1);case TimeStep.SCALE.DAY:case TimeStep.SCALE.WEEKDAY:this.current.setHours(0);case TimeStep.SCALE.HOUR:this.current.setMinutes(0);case TimeStep.SCALE.MINUTE:this.current.setSeconds(0);case TimeStep.SCALE.SECOND:this.current.setMilliseconds(0)}if(1!=this.step)switch(this.scale){case TimeStep.SCALE.MILLISECOND:this.current.setMilliseconds(this.current.getMilliseconds()-this.current.getMilliseconds()%this.step);break;case TimeStep.SCALE.SECOND:this.current.setSeconds(this.current.getSeconds()-this.current.getSeconds()%this.step);break;case TimeStep.SCALE.MINUTE:this.current.setMinutes(this.current.getMinutes()-this.current.getMinutes()%this.step);break;case TimeStep.SCALE.HOUR:this.current.setHours(this.current.getHours()-this.current.getHours()%this.step);break;case TimeStep.SCALE.WEEKDAY:case TimeStep.SCALE.DAY:this.current.setDate(this.current.getDate()-1-(this.current.getDate()-1)%this.step+1);break;case TimeStep.SCALE.MONTH:this.current.setMonth(this.current.getMonth()-this.current.getMonth()%this.step);break;case TimeStep.SCALE.YEAR:this.current.setFullYear(this.current.getFullYear()-this.current.getFullYear()%this.step);break;default:}},TimeStep.prototype.hasNext=function(){return this.current.valueOf()<=this._end.valueOf()},TimeStep.prototype.next=function(){var t=this.current.valueOf();if(6>this.current.getMonth())switch(this.scale){case TimeStep.SCALE.MILLISECOND:this.current=new Date(this.current.valueOf()+this.step);break;case TimeStep.SCALE.SECOND:this.current=new Date(this.current.valueOf()+1e3*this.step);break;case TimeStep.SCALE.MINUTE:this.current=new Date(this.current.valueOf()+60*1e3*this.step);break;case TimeStep.SCALE.HOUR:this.current=new Date(this.current.valueOf()+60*60*1e3*this.step);var e=this.current.getHours();this.current.setHours(e-e%this.step);break;case TimeStep.SCALE.WEEKDAY:case TimeStep.SCALE.DAY:this.current.setDate(this.current.getDate()+this.step);break;case TimeStep.SCALE.MONTH:this.current.setMonth(this.current.getMonth()+this.step);break;case TimeStep.SCALE.YEAR:this.current.setFullYear(this.current.getFullYear()+this.step);break;default:}else switch(this.scale){case TimeStep.SCALE.MILLISECOND:this.current=new Date(this.current.valueOf()+this.step);break;case TimeStep.SCALE.SECOND:this.current.setSeconds(this.current.getSeconds()+this.step);break;case TimeStep.SCALE.MINUTE:this.current.setMinutes(this.current.getMinutes()+this.step);break;case TimeStep.SCALE.HOUR:this.current.setHours(this.current.getHours()+this.step);break;case TimeStep.SCALE.WEEKDAY:case TimeStep.SCALE.DAY:this.current.setDate(this.current.getDate()+this.step);break;case TimeStep.SCALE.MONTH:this.current.setMonth(this.current.getMonth()+this.step);break;case TimeStep.SCALE.YEAR:this.current.setFullYear(this.current.getFullYear()+this.step);break;default:}if(1!=this.step)switch(this.scale){case TimeStep.SCALE.MILLISECOND:this.current.getMilliseconds()0&&(this.step=e),this.autoScale=!1},TimeStep.prototype.setAutoScale=function(t){this.autoScale=t},TimeStep.prototype.setMinimumStep=function(t){if(void 0!=t){var e=31104e6,i=2592e6,n=864e5,s=36e5,o=6e4,r=1e3,a=1;1e3*e>t&&(this.scale=TimeStep.SCALE.YEAR,this.step=1e3),500*e>t&&(this.scale=TimeStep.SCALE.YEAR,this.step=500),100*e>t&&(this.scale=TimeStep.SCALE.YEAR,this.step=100),50*e>t&&(this.scale=TimeStep.SCALE.YEAR,this.step=50),10*e>t&&(this.scale=TimeStep.SCALE.YEAR,this.step=10),5*e>t&&(this.scale=TimeStep.SCALE.YEAR,this.step=5),e>t&&(this.scale=TimeStep.SCALE.YEAR,this.step=1),3*i>t&&(this.scale=TimeStep.SCALE.MONTH,this.step=3),i>t&&(this.scale=TimeStep.SCALE.MONTH,this.step=1),5*n>t&&(this.scale=TimeStep.SCALE.DAY,this.step=5),2*n>t&&(this.scale=TimeStep.SCALE.DAY,this.step=2),n>t&&(this.scale=TimeStep.SCALE.DAY,this.step=1),n/2>t&&(this.scale=TimeStep.SCALE.WEEKDAY,this.step=1),4*s>t&&(this.scale=TimeStep.SCALE.HOUR,this.step=4),s>t&&(this.scale=TimeStep.SCALE.HOUR,this.step=1),15*o>t&&(this.scale=TimeStep.SCALE.MINUTE,this.step=15),10*o>t&&(this.scale=TimeStep.SCALE.MINUTE,this.step=10),5*o>t&&(this.scale=TimeStep.SCALE.MINUTE,this.step=5),o>t&&(this.scale=TimeStep.SCALE.MINUTE,this.step=1),15*r>t&&(this.scale=TimeStep.SCALE.SECOND,this.step=15),10*r>t&&(this.scale=TimeStep.SCALE.SECOND,this.step=10),5*r>t&&(this.scale=TimeStep.SCALE.SECOND,this.step=5),r>t&&(this.scale=TimeStep.SCALE.SECOND,this.step=1),200*a>t&&(this.scale=TimeStep.SCALE.MILLISECOND,this.step=200),100*a>t&&(this.scale=TimeStep.SCALE.MILLISECOND,this.step=100),50*a>t&&(this.scale=TimeStep.SCALE.MILLISECOND,this.step=50),10*a>t&&(this.scale=TimeStep.SCALE.MILLISECOND,this.step=10),5*a>t&&(this.scale=TimeStep.SCALE.MILLISECOND,this.step=5),a>t&&(this.scale=TimeStep.SCALE.MILLISECOND,this.step=1) }},TimeStep.prototype.snap=function(t){if(this.scale==TimeStep.SCALE.YEAR){var e=t.getFullYear()+Math.round(t.getMonth()/12);t.setFullYear(Math.round(e/this.step)*this.step),t.setMonth(0),t.setDate(0),t.setHours(0),t.setMinutes(0),t.setSeconds(0),t.setMilliseconds(0)}else if(this.scale==TimeStep.SCALE.MONTH)t.getDate()>15?(t.setDate(1),t.setMonth(t.getMonth()+1)):t.setDate(1),t.setHours(0),t.setMinutes(0),t.setSeconds(0),t.setMilliseconds(0);else if(this.scale==TimeStep.SCALE.DAY||this.scale==TimeStep.SCALE.WEEKDAY){switch(this.step){case 5:case 2:t.setHours(24*Math.round(t.getHours()/24));break;default:t.setHours(12*Math.round(t.getHours()/12))}t.setMinutes(0),t.setSeconds(0),t.setMilliseconds(0)}else if(this.scale==TimeStep.SCALE.HOUR){switch(this.step){case 4:t.setMinutes(60*Math.round(t.getMinutes()/60));break;default:t.setMinutes(30*Math.round(t.getMinutes()/30))}t.setSeconds(0),t.setMilliseconds(0)}else if(this.scale==TimeStep.SCALE.MINUTE){switch(this.step){case 15:case 10:t.setMinutes(5*Math.round(t.getMinutes()/5)),t.setSeconds(0);break;case 5:t.setSeconds(60*Math.round(t.getSeconds()/60));break;default:t.setSeconds(30*Math.round(t.getSeconds()/30))}t.setMilliseconds(0)}else if(this.scale==TimeStep.SCALE.SECOND)switch(this.step){case 15:case 10:t.setSeconds(5*Math.round(t.getSeconds()/5)),t.setMilliseconds(0);break;case 5:t.setMilliseconds(1e3*Math.round(t.getMilliseconds()/1e3));break;default:t.setMilliseconds(500*Math.round(t.getMilliseconds()/500))}else if(this.scale==TimeStep.SCALE.MILLISECOND){var i=this.step>5?this.step/2:1;t.setMilliseconds(Math.round(t.getMilliseconds()/i)*i)}},TimeStep.prototype.isMajor=function(){switch(this.scale){case TimeStep.SCALE.MILLISECOND:return 0==this.current.getMilliseconds();case TimeStep.SCALE.SECOND:return 0==this.current.getSeconds();case TimeStep.SCALE.MINUTE:return 0==this.current.getHours()&&0==this.current.getMinutes();case TimeStep.SCALE.HOUR:return 0==this.current.getHours();case TimeStep.SCALE.WEEKDAY:case TimeStep.SCALE.DAY:return 1==this.current.getDate();case TimeStep.SCALE.MONTH:return 0==this.current.getMonth();case TimeStep.SCALE.YEAR:return!1;default:return!1}},TimeStep.prototype.getLabelMinor=function(t){switch(void 0==t&&(t=this.current),this.scale){case TimeStep.SCALE.MILLISECOND:return M(t).format("SSS");case TimeStep.SCALE.SECOND:return M(t).format("s");case TimeStep.SCALE.MINUTE:return M(t).format("HH:mm");case TimeStep.SCALE.HOUR:return M(t).format("HH:mm");case TimeStep.SCALE.WEEKDAY:return M(t).format("ddd D");case TimeStep.SCALE.DAY:return M(t).format("D");case TimeStep.SCALE.MONTH:return M(t).format("MMM");case TimeStep.SCALE.YEAR:return M(t).format("YYYY");default:return""}},TimeStep.prototype.getLabelMajor=function(t){switch(void 0==t&&(t=this.current),this.scale){case TimeStep.SCALE.MILLISECOND:return M(t).format("HH:mm:ss");case TimeStep.SCALE.SECOND:return M(t).format("D MMMM HH:mm");case TimeStep.SCALE.MINUTE:case TimeStep.SCALE.HOUR:return M(t).format("ddd D MMMM");case TimeStep.SCALE.WEEKDAY:case TimeStep.SCALE.DAY:return M(t).format("MMMM YYYY");case TimeStep.SCALE.MONTH:return M(t).format("YYYY");case TimeStep.SCALE.YEAR:return"";default:return""}},a.prototype.setOptions=function(t){O.extend(this.options,t)},a.prototype.update=function(){this._order(),this._stack()},a.prototype._order=function(){var t=this.parent.items;if(!t)throw Error("Cannot stack items: parent does not contain items");var e=[],i=0;O.forEach(t,function(t){t.visible&&(e[i]=t,i++)});var n=this.options.order||this.defaultOptions.order;if("function"!=typeof n)throw Error("Option order must be a function");e.sort(n),this.ordered=e},a.prototype._stack=function(){var t,e,i,n=this.ordered,s=this.options,o=s.orientation||this.defaultOptions.orientation,r="top"==o;for(i=s.margin&&void 0!==s.margin.item?s.margin.item:this.defaultOptions.margin.item,t=0,e=n.length;e>t;t++){var a=n[t],h=null;do h=this.checkOverlap(n,t,0,t-1,i),null!=h&&(a.top=r?h.top+h.height+i:h.top-a.height-i);while(h)}},a.prototype.checkOverlap=function(t,e,i,n,s){for(var o=this.collision,r=t[e],a=n;a>=i;a--){var h=t[a];if(o(r,h,s)&&a!=e)return h}return null},a.prototype.collision=function(t,e,i){return t.left-ie.left&&t.top-ie.top},h.prototype.setOptions=function(t){O.extend(this.options,t),(null!=t.start||null!=t.end)&&this.setRange(t.start,t.end)},h.prototype.subscribe=function(t,e,i){var n,s=this;if("horizontal"!=i&&"vertical"!=i)throw new TypeError('Unknown direction "'+i+'". '+'Choose "horizontal" or "vertical".');if("move"==e)n={component:t,event:e,direction:i,callback:function(t){s._onMouseDown(t,n)},params:{}},t.on("mousedown",n.callback),s.listeners.push(n);else{if("zoom"!=e)throw new TypeError('Unknown event "'+e+'". '+'Choose "move" or "zoom".');n={component:t,event:e,direction:i,callback:function(t){s._onMouseWheel(t,n)},params:{}},t.on("mousewheel",n.callback),s.listeners.push(n)}},h.prototype.on=function(t,e){L.addListener(this,t,e)},h.prototype._trigger=function(t){L.trigger(this,t,{start:this.start,end:this.end})},h.prototype.setRange=function(t,e){var i=this._applyRange(t,e);i&&(this._trigger("rangechange"),this._trigger("rangechanged"))},h.prototype._applyRange=function(t,e){var i,n=null!=t?O.convert(t,"Number"):this.start,s=null!=e?O.convert(e,"Number"):this.end;if(isNaN(n))throw Error('Invalid start "'+t+'"');if(isNaN(s))throw Error('Invalid end "'+e+'"');if(n>s&&(s=n),null!=this.options.min){var o=this.options.min.valueOf();o>n&&(i=o-n,n+=i,s+=i)}if(null!=this.options.max){var r=this.options.max.valueOf();s>r&&(i=s-r,n-=i,s-=i)}if(null!=this.options.zoomMin){var a=this.options.zoomMin.valueOf();0>a&&(a=0),a>s-n&&(this.end-this.start>a?(i=a-(s-n),n-=i/2,s+=i/2):(n=this.start,s=this.end))}if(null!=this.options.zoomMax){var h=this.options.zoomMax.valueOf();0>h&&(h=0),s-n>h&&(h>this.end-this.start?(i=s-n-h,n+=i/2,s-=i/2):(n=this.start,s=this.end))}var d=this.start!=n||this.end!=s;return this.start=n,this.end=s,d},h.prototype.getRange=function(){return{start:this.start,end:this.end}},h.prototype.conversion=function(t){return this.start,this.end,h.conversion(this.start,this.end,t)},h.conversion=function(t,e,i){return 0!=i&&0!=e-t?{offset:t,factor:i/(e-t)}:{offset:0,factor:1}},h.prototype._onMouseDown=function(t,e){t=t||window.event;var i=e.params,n=t.which?1==t.which:1==t.button;if(n){i.mouseX=O.getPageX(t),i.mouseY=O.getPageY(t),i.previousLeft=0,i.previousOffset=0,i.moved=!1,i.start=this.start,i.end=this.end;var s=e.component.frame;s&&(s.style.cursor="move");var o=this;i.onMouseMove||(i.onMouseMove=function(t){o._onMouseMove(t,e)},O.addEventListener(document,"mousemove",i.onMouseMove)),i.onMouseUp||(i.onMouseUp=function(t){o._onMouseUp(t,e)},O.addEventListener(document,"mouseup",i.onMouseUp)),O.preventDefault(t)}},h.prototype._onMouseMove=function(t,e){t=t||window.event;var i=e.params,n=O.getPageX(t),s=O.getPageY(t);void 0==i.mouseX&&(i.mouseX=n),void 0==i.mouseY&&(i.mouseY=s);var o=n-i.mouseX,r=s-i.mouseY,a="horizontal"==e.direction?o:r;Math.abs(a)>=1&&(i.moved=!0);var h=i.end-i.start,d="horizontal"==e.direction?e.component.width:e.component.height,l=-a/d*h;this._applyRange(i.start+l,i.end+l),this._trigger("rangechange"),O.preventDefault(t)},h.prototype._onMouseUp=function(t,e){t=t||window.event;var i=e.params;e.component.frame&&(e.component.frame.style.cursor="auto"),i.onMouseMove&&(O.removeEventListener(document,"mousemove",i.onMouseMove),i.onMouseMove=null),i.onMouseUp&&(O.removeEventListener(document,"mouseup",i.onMouseUp),i.onMouseUp=null),i.moved&&this._trigger("rangechanged")},h.prototype._onMouseWheel=function(t,e){t=t||window.event;var i=0;if(t.wheelDelta?i=t.wheelDelta/120:t.detail&&(i=-t.detail/3),i){var n=this,s=function(){var s=i/5,o=null,r=e.component.frame;if(r){var a,h;if("horizontal"==e.direction){a=e.component.width,h=n.conversion(a);var d=O.getAbsoluteLeft(r),l=O.getPageX(t);o=(l-d)/h.factor+h.offset}else{a=e.component.height,h=n.conversion(a);var p=O.getAbsoluteTop(r),c=O.getPageY(t);o=(p+a-c-p)/h.factor+h.offset}}n.zoom(s,o)};s()}O.preventDefault(t)},h.prototype.zoom=function(t,e){null==e&&(e=(this.start+this.end)/2),t>=1&&(t=.9),-1>=t&&(t=-.9),0>t&&(t/=1+t);var i=this.start-e,n=this.end-e,s=this.start-i*t,o=this.end-n*t;this.setRange(s,o)},h.prototype.move=function(t){var e=this.end-this.start,i=this.start+e*t,n=this.end+e*t;this.start=i,this.end=n},h.prototype.moveTo=function(t){var e=(this.start+this.end)/2,i=e-t,n=this.start-i,s=this.end-i;this.setRange(n,s)},d.prototype.add=function(t){if(void 0==t.id)throw Error("Component has no field id");if(!(t instanceof l||t instanceof d))throw new TypeError("Component must be an instance of prototype Component or Controller");t.controller=this,this.components[t.id]=t},d.prototype.remove=function(t){var e;for(e in this.components)if(this.components.hasOwnProperty(e)&&(e==t||this.components[e]==t))break;e&&delete this.components[e]},d.prototype.requestReflow=function(t){if(t)this.reflow();else if(!this.reflowTimer){var e=this;this.reflowTimer=setTimeout(function(){e.reflowTimer=void 0,e.reflow()},0)}},d.prototype.requestRepaint=function(t){if(t)this.repaint();else if(!this.repaintTimer){var e=this;this.repaintTimer=setTimeout(function(){e.repaintTimer=void 0,e.repaint()},0)}},d.prototype.repaint=function(){function t(n,s){s in i||(n.depends&&n.depends.forEach(function(e){t(e,e.id)}),n.parent&&t(n.parent,n.parent.id),e=n.repaint()||e,i[s]=!0)}var e=!1;this.repaintTimer&&(clearTimeout(this.repaintTimer),this.repaintTimer=void 0);var i={};O.forEach(this.components,t),e&&this.reflow()},d.prototype.reflow=function(){function t(n,s){s in i||(n.depends&&n.depends.forEach(function(e){t(e,e.id)}),n.parent&&t(n.parent,n.parent.id),e=n.reflow()||e,i[s]=!0)}var e=!1;this.reflowTimer&&(clearTimeout(this.reflowTimer),this.reflowTimer=void 0);var i={};O.forEach(this.components,t),e&&this.repaint()},l.prototype.setOptions=function(t){t&&(O.extend(this.options,t),this.controller&&(this.requestRepaint(),this.requestReflow()))},l.prototype.getOption=function(t){var e;return this.options&&(e=this.options[t]),void 0===e&&this.defaultOptions&&(e=this.defaultOptions[t]),e},l.prototype.getContainer=function(){return null},l.prototype.getFrame=function(){return this.frame},l.prototype.repaint=function(){return!1},l.prototype.reflow=function(){return!1},l.prototype.hide=function(){return this.frame&&this.frame.parentNode?(this.frame.parentNode.removeChild(this.frame),!0):!1},l.prototype.show=function(){return this.frame&&this.frame.parentNode?!1:this.repaint()},l.prototype.requestRepaint=function(){if(!this.controller)throw Error("Cannot request a repaint: no controller configured");this.controller.requestRepaint()},l.prototype.requestReflow=function(){if(!this.controller)throw Error("Cannot request a reflow: no controller configured");this.controller.requestReflow()},p.prototype=new l,p.prototype.setOptions=l.prototype.setOptions,p.prototype.getContainer=function(){return this.frame},p.prototype.repaint=function(){var t=0,e=O.updateProperty,i=O.option.asSize,n=this.options,s=this.frame;if(!s){s=document.createElement("div"),s.className="panel";var o=n.className;o&&("function"==typeof o?O.addClassName(s,o()+""):O.addClassName(s,o+"")),this.frame=s,t+=1}if(!s.parentNode){if(!this.parent)throw Error("Cannot repaint panel: no parent attached");var r=this.parent.getContainer();if(!r)throw Error("Cannot repaint panel: parent has no container element");r.appendChild(s),t+=1}return t+=e(s.style,"top",i(n.top,"0px")),t+=e(s.style,"left",i(n.left,"0px")),t+=e(s.style,"width",i(n.width,"100%")),t+=e(s.style,"height",i(n.height,"100%")),t>0},p.prototype.reflow=function(){var t=0,e=O.updateProperty,i=this.frame;return i?(t+=e(this,"top",i.offsetTop),t+=e(this,"left",i.offsetLeft),t+=e(this,"width",i.offsetWidth),t+=e(this,"height",i.offsetHeight)):t+=1,t>0},c.prototype=new p,c.prototype.setOptions=l.prototype.setOptions,c.prototype.repaint=function(){var t=0,e=O.updateProperty,i=O.option.asSize,n=this.options,s=this.frame;if(!s){s=document.createElement("div"),s.className="vis timeline rootpanel";var o=n.className;o&&O.addClassName(s,O.option.asString(o)),this.frame=s,t+=1}if(!s.parentNode){if(!this.container)throw Error("Cannot repaint root panel: no container attached");this.container.appendChild(s),t+=1}return t+=e(s.style,"top",i(n.top,"0px")),t+=e(s.style,"left",i(n.left,"0px")),t+=e(s.style,"width",i(n.width,"100%")),t+=e(s.style,"height",i(n.height,"100%")),this._updateEventEmitters(),this._updateWatch(),t>0},c.prototype.reflow=function(){var t=0,e=O.updateProperty,i=this.frame;return i?(t+=e(this,"top",i.offsetTop),t+=e(this,"left",i.offsetLeft),t+=e(this,"width",i.offsetWidth),t+=e(this,"height",i.offsetHeight)):t+=1,t>0},c.prototype._updateWatch=function(){var t=this.getOption("autoResize");t?this._watch():this._unwatch()},c.prototype._watch=function(){var t=this;this._unwatch();var e=function(){var e=t.getOption("autoResize");return e?(t.frame&&(t.frame.clientWidth!=t.width||t.frame.clientHeight!=t.height)&&t.requestReflow(),void 0):(t._unwatch(),void 0)};O.addEventListener(window,"resize",e),this.watchTimer=setInterval(e,1e3)},c.prototype._unwatch=function(){this.watchTimer&&(clearInterval(this.watchTimer),this.watchTimer=void 0)},c.prototype.on=function(t,e){var i=this.listeners[t];i||(i=[],this.listeners[t]=i),i.push(e),this._updateEventEmitters()},c.prototype._updateEventEmitters=function(){if(this.listeners){var t=this;O.forEach(this.listeners,function(e,i){if(t.emitters||(t.emitters={}),!(i in t.emitters)){var n=t.frame;if(n){var s=function(t){e.forEach(function(e){e(t)})};t.emitters[i]=s,O.addEventListener(n,i,s)}}})}},u.prototype=new l,u.prototype.setOptions=l.prototype.setOptions,u.prototype.setRange=function(t){if(!(t instanceof h||t&&t.start&&t.end))throw new TypeError("Range must be an instance of Range, or an object containing start and end.");this.range=t},u.prototype.toTime=function(t){var e=this.conversion;return new Date(t/e.factor+e.offset)},u.prototype.toScreen=function(t){var e=this.conversion;return(t.valueOf()-e.offset)*e.factor},u.prototype.repaint=function(){var t=0,e=O.updateProperty,i=O.option.asSize,n=this.options,s=this.getOption("orientation"),o=this.props,r=this.step,a=this.frame;if(a||(a=document.createElement("div"),this.frame=a,t+=1),a.className="axis "+s,!a.parentNode){if(!this.parent)throw Error("Cannot repaint time axis: no parent attached");var h=this.parent.getContainer();if(!h)throw Error("Cannot repaint time axis: parent has no container element");h.appendChild(a),t+=1}var d=a.parentNode;if(d){var l=a.nextSibling;d.removeChild(a);var p="bottom"==s&&this.props.parentHeight&&this.height?this.props.parentHeight-this.height+"px":"0px";if(t+=e(a.style,"top",i(n.top,p)),t+=e(a.style,"left",i(n.left,"0px")),t+=e(a.style,"width",i(n.width,"100%")),t+=e(a.style,"height",i(n.height,this.height+"px")),this._repaintMeasureChars(),this.step){this._repaintStart(),r.first();for(var c=void 0,u=0;r.hasNext()&&1e3>u;){u++;var f=r.getCurrent(),m=this.toScreen(f),g=r.isMajor();this.getOption("showMinorLabels")&&this._repaintMinorText(m,r.getLabelMinor()),g&&this.getOption("showMajorLabels")?(m>0&&(void 0==c&&(c=m),this._repaintMajorText(m,r.getLabelMajor())),this._repaintMajorLine(m)):this._repaintMinorLine(m),r.next()}if(this.getOption("showMajorLabels")){var v=this.toTime(0),y=r.getLabelMajor(v),b=y.length*(o.majorCharWidth||10)+10;(void 0==c||c>b)&&this._repaintMajorText(0,y)}this._repaintEnd()}this._repaintLine(),l?d.insertBefore(a,l):d.appendChild(a)}return t>0},u.prototype._repaintStart=function(){var t=this.dom,e=t.redundant;e.majorLines=t.majorLines,e.majorTexts=t.majorTexts,e.minorLines=t.minorLines,e.minorTexts=t.minorTexts,t.majorLines=[],t.majorTexts=[],t.minorLines=[],t.minorTexts=[]},u.prototype._repaintEnd=function(){O.forEach(this.dom.redundant,function(t){for(;t.length;){var e=t.pop();e&&e.parentNode&&e.parentNode.removeChild(e)}})},u.prototype._repaintMinorText=function(t,e){var i=this.dom.redundant.minorTexts.shift();if(!i){var n=document.createTextNode("");i=document.createElement("div"),i.appendChild(n),i.className="text minor",this.frame.appendChild(i)}this.dom.minorTexts.push(i),i.childNodes[0].nodeValue=e,i.style.left=t+"px",i.style.top=this.props.minorLabelTop+"px"},u.prototype._repaintMajorText=function(t,e){var i=this.dom.redundant.majorTexts.shift();if(!i){var n=document.createTextNode(e);i=document.createElement("div"),i.className="text major",i.appendChild(n),this.frame.appendChild(i)}this.dom.majorTexts.push(i),i.childNodes[0].nodeValue=e,i.style.top=this.props.majorLabelTop+"px",i.style.left=t+"px"},u.prototype._repaintMinorLine=function(t){var e=this.dom.redundant.minorLines.shift();e||(e=document.createElement("div"),e.className="grid vertical minor",this.frame.appendChild(e)),this.dom.minorLines.push(e);var i=this.props;e.style.top=i.minorLineTop+"px",e.style.height=i.minorLineHeight+"px",e.style.left=t-i.minorLineWidth/2+"px"},u.prototype._repaintMajorLine=function(t){var e=this.dom.redundant.majorLines.shift();e||(e=document.createElement("DIV"),e.className="grid vertical major",this.frame.appendChild(e)),this.dom.majorLines.push(e);var i=this.props;e.style.top=i.majorLineTop+"px",e.style.left=t-i.majorLineWidth/2+"px",e.style.height=i.majorLineHeight+"px"},u.prototype._repaintLine=function(){var t=this.dom.line,e=this.frame;this.options,this.getOption("showMinorLabels")||this.getOption("showMajorLabels")?(t?(e.removeChild(t),e.appendChild(t)):(t=document.createElement("div"),t.className="grid horizontal major",e.appendChild(t),this.dom.line=t),t.style.top=this.props.lineTop+"px"):t&&axis.parentElement&&(e.removeChild(axis.line),delete this.dom.line)},u.prototype._repaintMeasureChars=function(){var t,e=this.dom;if(!e.measureCharMinor){t=document.createTextNode("0");var i=document.createElement("DIV");i.className="text minor measure",i.appendChild(t),this.frame.appendChild(i),e.measureCharMinor=i}if(!e.measureCharMajor){t=document.createTextNode("0");var n=document.createElement("DIV");n.className="text major measure",n.appendChild(t),this.frame.appendChild(n),e.measureCharMajor=n}},u.prototype.reflow=function(){var t=0,e=O.updateProperty,i=this.frame,n=this.range;if(!n)throw Error("Cannot repaint time axis: no range configured");if(i){t+=e(this,"top",i.offsetTop),t+=e(this,"left",i.offsetLeft);var s=this.props,o=this.getOption("showMinorLabels"),r=this.getOption("showMajorLabels"),a=this.dom.measureCharMinor,h=this.dom.measureCharMajor;a&&(s.minorCharHeight=a.clientHeight,s.minorCharWidth=a.clientWidth),h&&(s.majorCharHeight=h.clientHeight,s.majorCharWidth=h.clientWidth);var d=i.parentNode?i.parentNode.offsetHeight:0;switch(d!=s.parentHeight&&(s.parentHeight=d,t+=1),this.getOption("orientation")){case"bottom":s.minorLabelHeight=o?s.minorCharHeight:0,s.majorLabelHeight=r?s.majorCharHeight:0,s.minorLabelTop=0,s.majorLabelTop=s.minorLabelTop+s.minorLabelHeight,s.minorLineTop=-this.top,s.minorLineHeight=Math.max(this.top+s.majorLabelHeight,0),s.minorLineWidth=1,s.majorLineTop=-this.top,s.majorLineHeight=Math.max(this.top+s.minorLabelHeight+s.majorLabelHeight,0),s.majorLineWidth=1,s.lineTop=0;break;case"top":s.minorLabelHeight=o?s.minorCharHeight:0,s.majorLabelHeight=r?s.majorCharHeight:0,s.majorLabelTop=0,s.minorLabelTop=s.majorLabelTop+s.majorLabelHeight,s.minorLineTop=s.minorLabelTop,s.minorLineHeight=Math.max(d-s.majorLabelHeight-this.top),s.minorLineWidth=1,s.majorLineTop=0,s.majorLineHeight=Math.max(d-this.top),s.majorLineWidth=1,s.lineTop=s.majorLabelHeight+s.minorLabelHeight;break;default:throw Error('Unkown orientation "'+this.getOption("orientation")+'"')}var l=s.minorLabelHeight+s.majorLabelHeight;t+=e(this,"width",i.offsetWidth),t+=e(this,"height",l),this._updateConversion();var p=O.convert(n.start,"Date"),c=O.convert(n.end,"Date"),u=this.toTime(5*(s.minorCharWidth||10))-this.toTime(0);this.step=new TimeStep(p,c,u),t+=e(s.range,"start",p.valueOf()),t+=e(s.range,"end",c.valueOf()),t+=e(s.range,"minimumStep",u.valueOf())}return t>0},u.prototype._updateConversion=function(){var t=this.range;if(!t)throw Error("No range configured");this.conversion=t.conversion?t.conversion(this.width):h.conversion(t.start,t.end,this.width)},f.prototype=new p,f.types={box:g,range:y,point:v},f.prototype.setOptions=l.prototype.setOptions,f.prototype.setRange=function(t){if(!(t instanceof h||t&&t.start&&t.end))throw new TypeError("Range must be an instance of Range, or an object containing start and end.");this.range=t},f.prototype.repaint=function(){var t=0,e=O.updateProperty,i=O.option.asSize,n=this.options,s=this.getOption("orientation"),o=this.defaultOptions,r=this.frame;if(!r){r=document.createElement("div"),r.className="itemset";var a=n.className;a&&O.addClassName(r,O.option.asString(a));var h=document.createElement("div");h.className="background",r.appendChild(h),this.dom.background=h;var d=document.createElement("div");d.className="foreground",r.appendChild(d),this.dom.foreground=d;var l=document.createElement("div");l.className="itemset-axis",this.dom.axis=l,this.frame=r,t+=1}if(!this.parent)throw Error("Cannot repaint itemset: no parent attached");var p=this.parent.getContainer();if(!p)throw Error("Cannot repaint itemset: parent has no container element");r.parentNode||(p.appendChild(r),t+=1),this.dom.axis.parentNode||(p.appendChild(this.dom.axis),t+=1),t+=e(r.style,"left",i(n.left,"0px")),t+=e(r.style,"top",i(n.top,"0px")),t+=e(r.style,"width",i(n.width,"100%")),t+=e(r.style,"height",i(n.height,this.height+"px")),t+=e(this.dom.axis.style,"left",i(n.left,"0px")),t+=e(this.dom.axis.style,"width",i(n.width,"100%")),t+="bottom"==s?e(this.dom.axis.style,"top",this.height+this.top+"px"):e(this.dom.axis.style,"top",this.top+"px"),this._updateConversion();var c=this,u=this.queue,m=this.itemsData,g=this.items,v={};return Object.keys(u).forEach(function(e){var i=u[e],s=g[e];switch(i){case"add":case"update":var r=m&&m.get(e,v);if(r){var a=r.type||r.start&&r.end&&"range"||n.type||"box",h=f.types[a];if(s&&(h&&s instanceof h?(s.data=r,t++):(t+=s.hide(),s=null)),!s){if(!h)throw new TypeError('Unknown item type "'+a+'"');s=new h(c,r,n,o),t++}s.repaint(),g[e]=s}delete u[e];break;case"remove":s&&(t+=s.hide()),delete g[e],delete u[e];break;default:console.log('Error: unknown action "'+i+'"')}}),O.forEach(this.items,function(e){e.visible?(t+=e.show(),e.reposition()):t+=e.hide()}),t>0},f.prototype.getForeground=function(){return this.dom.foreground},f.prototype.getBackground=function(){return this.dom.background},f.prototype.getAxis=function(){return this.dom.axis},f.prototype.reflow=function(){var t=0,e=this.options,i=e.margin&&e.margin.axis||this.defaultOptions.margin.axis,n=e.margin&&e.margin.item||this.defaultOptions.margin.item,s=O.updateProperty,o=O.option.asNumber,r=O.option.asSize,a=this.frame;if(a){this._updateConversion(),O.forEach(this.items,function(e){t+=e.reflow()}),this.stack.update();var h,d=o(e.maxHeight),l=null!=r(e.height);if(l)h=a.offsetHeight;else{var p=this.stack.ordered;if(p.length){var c=p[0].top,u=p[0].top+p[0].height;O.forEach(p,function(t){c=Math.min(c,t.top),u=Math.max(u,t.top+t.height)}),h=u-c+i+n}else h=i+n}null!=d&&(h=Math.min(h,d)),t+=s(this,"height",h),t+=s(this,"top",a.offsetTop),t+=s(this,"left",a.offsetLeft),t+=s(this,"width",a.offsetWidth)}else t+=1;return t>0},f.prototype.hide=function(){var t=!1;return this.frame&&this.frame.parentNode&&(this.frame.parentNode.removeChild(this.frame),t=!0),this.dom.axis&&this.dom.axis.parentNode&&(this.dom.axis.parentNode.removeChild(this.dom.axis),t=!0),t},f.prototype.setItems=function(t){var e,i=this,n=this.itemsData;if(t){if(!(t instanceof o||t instanceof r))throw new TypeError("Data must be an instance of DataSet");this.itemsData=t}else this.itemsData=null;if(n&&(O.forEach(this.listeners,function(t,e){n.unsubscribe(e,t)}),e=n.getIds(),this._onRemove(e)),this.itemsData){var s=this.id;O.forEach(this.listeners,function(t,e){i.itemsData.subscribe(e,t,s)}),e=this.itemsData.getIds(),this._onAdd(e)}},f.prototype.getItems=function(){return this.itemsData},f.prototype._onUpdate=function(t){this._toQueue("update",t)},f.prototype._onAdd=function(t){this._toQueue("add",t)},f.prototype._onRemove=function(t){this._toQueue("remove",t)},f.prototype._toQueue=function(t,e){var i=this.queue;e.forEach(function(e){i[e]=t}),this.controller&&this.requestRepaint()},f.prototype._updateConversion=function(){var t=this.range;if(!t)throw Error("No range configured");this.conversion=t.conversion?t.conversion(this.width):h.conversion(t.start,t.end,this.width)},f.prototype.toTime=function(t){var e=this.conversion;return new Date(t/e.factor+e.offset)},f.prototype.toScreen=function(t){var e=this.conversion;return(t.valueOf()-e.offset)*e.factor},m.prototype.select=function(){this.selected=!0},m.prototype.unselect=function(){this.selected=!1},m.prototype.show=function(){return!1},m.prototype.hide=function(){return!1},m.prototype.repaint=function(){return!1},m.prototype.reflow=function(){return!1},g.prototype=new m(null,null),g.prototype.select=function(){this.selected=!0},g.prototype.unselect=function(){this.selected=!1},g.prototype.repaint=function(){var t=!1,e=this.dom;if(e||(this._create(),e=this.dom,t=!0),e){if(!this.parent)throw Error("Cannot repaint item: no parent attached");var i=this.parent.getForeground();if(!i)throw Error("Cannot repaint time axis: parent has no foreground container element");var n=this.parent.getBackground();if(!n)throw Error("Cannot repaint time axis: parent has no background container element");var s=this.parent.getAxis();if(!n)throw Error("Cannot repaint time axis: parent has no axis container element");if(e.box.parentNode||(i.appendChild(e.box),t=!0),e.line.parentNode||(n.appendChild(e.line),t=!0),e.dot.parentNode||(s.appendChild(e.dot),t=!0),this.data.content!=this.content){if(this.content=this.data.content,this.content instanceof Element)e.content.innerHTML="",e.content.appendChild(this.content);else{if(void 0==this.data.content)throw Error('Property "content" missing in item '+this.data.id);e.content.innerHTML=this.content}t=!0}var o=(this.data.className?" "+this.data.className:"")+(this.selected?" selected":"");this.className!=o&&(this.className=o,e.box.className="item box"+o,e.line.className="item line"+o,e.dot.className="item dot"+o,t=!0)}return t},g.prototype.show=function(){return this.dom&&this.dom.box.parentNode?!1:this.repaint()},g.prototype.hide=function(){var t=!1,e=this.dom;return e&&(e.box.parentNode&&(e.box.parentNode.removeChild(e.box),t=!0),e.line.parentNode&&e.line.parentNode.removeChild(e.line),e.dot.parentNode&&e.dot.parentNode.removeChild(e.dot)),t},g.prototype.reflow=function(){var t,e,i,n,s,o,r,a,h,d,l,p,c=0;if(void 0==this.data.start)throw Error('Property "start" missing in item '+this.data.id);if(l=this.data,p=this.parent&&this.parent.range,l&&p){var u=p.end-p.start;this.visible=l.start>p.start-u&&l.start0},g.prototype._create=function(){var t=this.dom;t||(this.dom=t={},t.box=document.createElement("DIV"),t.content=document.createElement("DIV"),t.content.className="content",t.box.appendChild(t.content),t.line=document.createElement("DIV"),t.line.className="line",t.dot=document.createElement("DIV"),t.dot.className="dot")},g.prototype.reposition=function(){var t=this.dom,e=this.props,i=this.options.orientation||this.defaultOptions.orientation;if(t){var n=t.box,s=t.line,o=t.dot;n.style.left=this.left+"px",n.style.top=this.top+"px",s.style.left=e.line.left+"px","top"==i?(s.style.top="0px",s.style.height=this.top+"px"):(s.style.top=this.top+this.height+"px",s.style.height=Math.max(this.parent.height-this.top-this.height+this.props.dot.height/2,0)+"px"),o.style.left=e.dot.left+"px",o.style.top=e.dot.top+"px"}},v.prototype=new m(null,null),v.prototype.select=function(){this.selected=!0},v.prototype.unselect=function(){this.selected=!1},v.prototype.repaint=function(){var t=!1,e=this.dom;if(e||(this._create(),e=this.dom,t=!0),e){if(!this.parent)throw Error("Cannot repaint item: no parent attached");var i=this.parent.getForeground();if(!i)throw Error("Cannot repaint time axis: parent has no foreground container element");if(e.point.parentNode||(i.appendChild(e.point),i.appendChild(e.point),t=!0),this.data.content!=this.content){if(this.content=this.data.content,this.content instanceof Element)e.content.innerHTML="",e.content.appendChild(this.content);else{if(void 0==this.data.content)throw Error('Property "content" missing in item '+this.data.id);e.content.innerHTML=this.content}t=!0}var n=(this.data.className?" "+this.data.className:"")+(this.selected?" selected":"");this.className!=n&&(this.className=n,e.point.className="item point"+n,t=!0)}return t},v.prototype.show=function(){return this.dom&&this.dom.point.parentNode?!1:this.repaint()},v.prototype.hide=function(){var t=!1,e=this.dom;return e&&e.point.parentNode&&(e.point.parentNode.removeChild(e.point),t=!0),t},v.prototype.reflow=function(){var t,e,i,n,s,o,r,a,h,d,l=0;if(void 0==this.data.start)throw Error('Property "start" missing in item '+this.data.id);if(h=this.data,d=this.parent&&this.parent.range,h&&d){var p=d.end-d.start;this.visible=h.start>d.start-p&&h.start0},v.prototype._create=function(){var t=this.dom;t||(this.dom=t={},t.point=document.createElement("div"),t.content=document.createElement("div"),t.content.className="content",t.point.appendChild(t.content),t.dot=document.createElement("div"),t.dot.className="dot",t.point.appendChild(t.dot))},v.prototype.reposition=function(){var t=this.dom,e=this.props;t&&(t.point.style.top=this.top+"px",t.point.style.left=this.left+"px",t.content.style.marginLeft=e.content.marginLeft+"px",t.dot.style.top=e.dot.top+"px")},y.prototype=new m(null,null),y.prototype.select=function(){this.selected=!0},y.prototype.unselect=function(){this.selected=!1},y.prototype.repaint=function(){var t=!1,e=this.dom;if(e||(this._create(),e=this.dom,t=!0),e){if(!this.parent)throw Error("Cannot repaint item: no parent attached");var i=this.parent.getForeground();if(!i)throw Error("Cannot repaint time axis: parent has no foreground container element");if(e.box.parentNode||(i.appendChild(e.box),t=!0),this.data.content!=this.content){if(this.content=this.data.content,this.content instanceof Element)e.content.innerHTML="",e.content.appendChild(this.content);else{if(void 0==this.data.content)throw Error('Property "content" missing in item '+this.data.id); e.content.innerHTML=this.content}t=!0}var n=this.data.className?" "+this.data.className:"";this.className!=n&&(this.className=n,e.box.className="item range"+n,t=!0)}return t},y.prototype.show=function(){return this.dom&&this.dom.box.parentNode?!1:this.repaint()},y.prototype.hide=function(){var t=!1,e=this.dom;return e&&e.box.parentNode&&(e.box.parentNode.removeChild(e.box),t=!0),t},y.prototype.reflow=function(){var t,e,i,n,s,o,r,a,h,d,l,p,c,u,f,m,g=0;if(void 0==this.data.start)throw Error('Property "start" missing in item '+this.data.id);if(void 0==this.data.end)throw Error('Property "end" missing in item '+this.data.id);return h=this.data,d=this.parent&&this.parent.range,this.visible=h&&d?h.startd.start:!1,this.visible&&(t=this.dom,t?(e=this.props,i=this.options,o=this.parent,r=o.toScreen(this.data.start),a=o.toScreen(this.data.end),l=O.updateProperty,p=t.box,c=o.width,f=i.orientation||this.defaultOptions.orientation,n=i.margin&&i.margin.axis||this.defaultOptions.margin.axis,s=i.padding||this.defaultOptions.padding,g+=l(e.content,"width",t.content.offsetWidth),g+=l(this,"height",p.offsetHeight),-c>r&&(r=-c),a>2*c&&(a=2*c),u=0>r?Math.min(-r,a-r-e.content.width-2*s):0,g+=l(e.content,"left",u),"top"==f?(m=n,g+=l(this,"top",m)):(m=o.height-this.height-n,g+=l(this,"top",m)),g+=l(this,"left",r),g+=l(this,"width",Math.max(a-r,1))):g+=1),g>0},y.prototype._create=function(){var t=this.dom;t||(this.dom=t={},t.box=document.createElement("div"),t.content=document.createElement("div"),t.content.className="content",t.box.appendChild(t.content))},y.prototype.reposition=function(){var t=this.dom,e=this.props;t&&(t.box.style.top=this.top+"px",t.box.style.left=this.left+"px",t.box.style.width=this.width+"px",t.content.style.left=e.content.left+"px")},b.prototype=new l,b.prototype.setOptions=l.prototype.setOptions,b.prototype.getContainer=function(){return this.parent.getContainer()},b.prototype.setItems=function(t){if(this.itemset&&(this.itemset.hide(),this.itemset.setItems(),this.parent.controller.remove(this.itemset),this.itemset=null),t){var e=this.groupId,i=Object.create(this.options);this.itemset=new f(this,null,i),this.itemset.setRange(this.parent.range),this.view=new r(t,{filter:function(t){return t.group==e}}),this.itemset.setItems(this.view),this.parent.controller.add(this.itemset)}},b.prototype.repaint=function(){return!1},b.prototype.reflow=function(){var t=0,e=O.updateProperty;if(t+=e(this,"top",this.itemset?this.itemset.top:0),t+=e(this,"height",this.itemset?this.itemset.height:0),this.label){var i=this.label.firstChild;t+=e(this.props.label,"width",i.clientWidth),t+=e(this.props.label,"height",i.clientHeight)}else t+=e(this.props.label,"width",0),t+=e(this.props.label,"height",0);return t>0},w.prototype=new p,w.prototype.setOptions=l.prototype.setOptions,w.prototype.setRange=function(){},w.prototype.setItems=function(t){this.itemsData=t;for(var e in this.groups)if(this.groups.hasOwnProperty(e)){var i=this.groups[e];i.setItems(t)}},w.prototype.getItems=function(){return this.itemsData},w.prototype.setRange=function(t){this.range=t},w.prototype.setGroups=function(t){var e,i=this;if(this.groupsData&&(O.forEach(this.listeners,function(t,e){i.groupsData.unsubscribe(e,t)}),e=this.groupsData.getIds(),this._onRemove(e)),t?t instanceof o?this.groupsData=t:(this.groupsData=new o({convert:{start:"Date",end:"Date"}}),this.groupsData.add(t)):this.groupsData=null,this.groupsData){var n=this.id;O.forEach(this.listeners,function(t,e){i.groupsData.subscribe(e,t,n)}),e=this.groupsData.getIds(),this._onAdd(e)}},w.prototype.getGroups=function(){return this.groupsData},w.prototype.repaint=function(){var t,e,i,n,s=0,o=O.updateProperty,r=O.option.asSize,a=O.option.asElement,h=this.options,d=this.dom.frame,l=this.dom.labels;if(!this.parent)throw Error("Cannot repaint groupset: no parent attached");var p=this.parent.getContainer();if(!p)throw Error("Cannot repaint groupset: parent has no container element");if(!d){d=document.createElement("div"),d.className="groupset",this.dom.frame=d;var c=h.className;c&&O.addClassName(d,O.option.asString(c)),s+=1}d.parentNode||(p.appendChild(d),s+=1);var u=a(h.labelContainer);if(!u)throw Error('Cannot repaint groupset: option "labelContainer" not defined');l||(l=document.createElement("div"),l.className="labels",this.dom.labels=l),l.parentNode&&l.parentNode==u||(l.parentNode&&l.parentNode.removeChild(l.parentNode),u.appendChild(l)),s+=o(d.style,"height",r(h.height,this.height+"px")),s+=o(d.style,"top",r(h.top,"0px")),s+=o(d.style,"left",r(h.left,"0px")),s+=o(d.style,"width",r(h.width,"100%")),s+=o(l.style,"top",r(h.top,"0px"));var f=this,m=this.queue,g=this.groups,v=this.groupsData,y=Object.keys(m);if(y.length){y.forEach(function(t){var e=m[t],i=g[t];switch(e){case"add":case"update":if(!i){var n=Object.create(f.options);i=new b(f,t,n),i.setItems(f.itemsData),g[t]=i,f.controller.add(i)}i.data=v.get(t),delete m[t];break;case"remove":i&&(i.setItems(),delete g[t],f.controller.remove(i)),delete m[t];break;default:console.log('Error: unknown action "'+e+'"')}});var w=this.groupsData.getIds({order:this.options.groupsOrder});for(t=0;w.length>t;t++)(function(t,e){var i=0;e&&(i=function(){return e.top+e.height}),t.setOptions({top:i})})(g[w[t]],g[w[t-1]]);for(;l.firstChild;)l.removeChild(l.firstChild);for(t=0;w.length>t;t++)e=w[t],n=this._createLabel(e),l.appendChild(n);s++}for(e in g)g.hasOwnProperty(e)&&(i=g[e],n=i.label,n&&(n.style.top=i.top+"px",n.style.height=i.height+"px"));return s>0},w.prototype._createLabel=function(t){var e=this.groups[t],i=document.createElement("div");i.className="label";var n=document.createElement("div");n.className="inner",i.appendChild(n);var s=e.data&&e.data.content;s instanceof Element?n.appendChild(s):void 0!=s&&(n.innerHTML=s);var o=e.data&&e.data.className;return o&&O.addClassName(i,o),e.label=i,i},w.prototype.getContainer=function(){return this.dom.frame},w.prototype.getLabelsWidth=function(){return this.props.labels.width},w.prototype.reflow=function(){var t,e,i=0,n=this.options,s=O.updateProperty,o=O.option.asNumber,r=O.option.asSize,a=this.dom.frame;if(a){var h,d=o(n.maxHeight),l=null!=r(n.height);if(l)h=a.offsetHeight;else{h=0;for(t in this.groups)this.groups.hasOwnProperty(t)&&(e=this.groups[t],h+=e.height)}null!=d&&(h=Math.min(h,d)),i+=s(this,"height",h),i+=s(this,"top",a.offsetTop),i+=s(this,"left",a.offsetLeft),i+=s(this,"width",a.offsetWidth)}var p=0;for(t in this.groups)if(this.groups.hasOwnProperty(t)){e=this.groups[t];var c=e.props&&e.props.label&&e.props.label.width||0;p=Math.max(p,c)}return i+=s(this.props.labels,"width",p),i>0},w.prototype.hide=function(){return this.dom.frame&&this.dom.frame.parentNode?(this.dom.frame.parentNode.removeChild(this.dom.frame),!0):!1},w.prototype.show=function(){return this.dom.frame&&this.dom.frame.parentNode?!1:this.repaint()},w.prototype._onUpdate=function(t){this._toQueue(t,"update")},w.prototype._onAdd=function(t){this._toQueue(t,"add")},w.prototype._onRemove=function(t){this._toQueue(t,"remove")},w.prototype._toQueue=function(t,e){var i=this.queue;t.forEach(function(t){i[t]=e}),this.controller&&this.requestRepaint()},_.prototype.setOptions=function(t){t&&O.extend(this.options,t),this.controller.reflow(),this.controller.repaint()},_.prototype.setItems=function(t){var e,i=null==this.itemsData;if(t?t instanceof o&&(e=t):e=null,t instanceof o||(e=new o({convert:{start:"Date",end:"Date"}}),e.add(t)),this.itemsData=e,this.content.setItems(e),i&&(void 0==this.options.start||void 0==this.options.end)){var n=this.getItemRange(),s=n.min,r=n.max;if(null!=s&&null!=r){var a=r.valueOf()-s.valueOf();0>=a&&(a=864e5),s=new Date(s.valueOf()-.05*a),r=new Date(r.valueOf()+.05*a)}void 0!=this.options.start&&(s=new Date(this.options.start.valueOf())),void 0!=this.options.end&&(r=new Date(this.options.end.valueOf())),(null!=s||null!=r)&&this.range.setRange(s,r)}},_.prototype.setGroups=function(t){var e=this;this.groupsData=t;var i=this.groupsData?w:f;if(!(this.content instanceof i)){this.content&&(this.content.hide(),this.content.setItems&&this.content.setItems(),this.content.setGroups&&this.content.setGroups(),this.controller.remove(this.content));var n=Object.create(this.options);O.extend(n,{top:function(){return"top"==e.options.orientation?e.timeaxis.height:e.itemPanel.height-e.timeaxis.height-e.content.height},left:null,width:"100%",height:function(){return e.options.height?e.itemPanel.height-e.timeaxis.height:null},maxHeight:function(){if(e.options.maxHeight){if(!O.isNumber(e.options.maxHeight))throw new TypeError("Number expected for property maxHeight");return e.options.maxHeight-e.timeaxis.height}return null},labelContainer:function(){return e.labelPanel.getContainer()}}),this.content=new i(this.itemPanel,[this.timeaxis],n),this.content.setRange&&this.content.setRange(this.range),this.content.setItems&&this.content.setItems(this.itemsData),this.content.setGroups&&this.content.setGroups(this.groupsData),this.controller.add(this.content)}},_.prototype.getItemRange=function(){var t=this.itemsData,e=null,i=null;if(t){var n=t.min("start");e=n?n.start.valueOf():null;var s=t.max("start");s&&(i=s.start.valueOf());var o=t.max("end");o&&(i=null==i?o.end.valueOf():Math.max(i,o.end.valueOf()))}return{min:null!=e?new Date(e):null,max:null!=i?new Date(i):null}},function(t){function e(t){return M=t,c()}function i(){D=0,C=M.charAt(0)}function n(){D++,C=M.charAt(D)}function s(){return M.charAt(D+1)}function o(t){return L.test(t)}function r(t,e){if(t||(t={}),e)for(var i in e)e.hasOwnProperty(i)&&(t[i]=e[i]);return t}function a(t,e,i){for(var n=e.split("."),s=t;n.length;){var o=n.shift();n.length?(s[o]||(s[o]={}),s=s[o]):s[o]=i}}function h(t,e){for(var i,n,s=null,o=[t],a=t;a.parent;)o.push(a.parent),a=a.parent;if(a.nodes)for(i=0,n=a.nodes.length;n>i;i++)if(e.id===a.nodes[i].id){s=a.nodes[i];break}for(s||(s={id:e.id},t.node&&(s.attr=r(s.attr,t.node))),i=o.length-1;i>=0;i--){var h=o[i];h.nodes||(h.nodes=[]),-1==h.nodes.indexOf(s)&&h.nodes.push(s)}e.attr&&(s.attr=r(s.attr,e.attr))}function d(t,e){if(t.edges||(t.edges=[]),t.edges.push(e),t.edge){var i=r({},t.edge);e.attr=r(i,e.attr)}}function l(t,e,i,n,s){var o={from:e,to:i,type:n};return t.edge&&(o.attr=r({},t.edge)),o.attr=r(o.attr||{},s),o}function p(){for(N=x.NULL,O="";" "==C||" "==C||"\n"==C||"\r"==C;)n();do{var t=!1;if("#"==C){for(var e=D-1;" "==M.charAt(e)||" "==M.charAt(e);)e--;if("\n"==M.charAt(e)||""==M.charAt(e)){for(;""!=C&&"\n"!=C;)n();t=!0}}if("/"==C&&"/"==s()){for(;""!=C&&"\n"!=C;)n();t=!0}if("/"==C&&"*"==s()){for(;""!=C;){if("*"==C&&"/"==s()){n(),n();break}n()}t=!0}for(;" "==C||" "==C||"\n"==C||"\r"==C;)n()}while(t);if(""==C)return N=x.DELIMITER,void 0;var i=C+s();if(S[i])return N=x.DELIMITER,O=i,n(),n(),void 0;if(S[C])return N=x.DELIMITER,O=C,n(),void 0;if(o(C)||"-"==C){for(O+=C,n();o(C);)O+=C,n();return"false"==O?O=!1:"true"==O?O=!0:isNaN(Number(O))||(O=Number(O)),N=x.IDENTIFIER,void 0}if('"'==C){for(n();""!=C&&('"'!=C||'"'==C&&'"'==s());)O+=C,'"'==C&&n(),n();if('"'!=C)throw w('End of string " expected');return n(),N=x.IDENTIFIER,void 0}for(N=x.UNKNOWN;""!=C;)O+=C,n();throw new SyntaxError('Syntax error in part "'+_(O,30)+'"')}function c(){var t={};if(i(),p(),"strict"==O&&(t.strict=!0,p()),("graph"==O||"digraph"==O)&&(t.type=O,p()),N==x.IDENTIFIER&&(t.id=O,p()),"{"!=O)throw w("Angle bracket { expected");if(p(),u(t),"}"!=O)throw w("Angle bracket } expected");if(p(),""!==O)throw w("End of file expected");return p(),delete t.node,delete t.edge,delete t.graph,t}function u(t){for(;""!==O&&"}"!=O;)f(t),";"==O&&p()}function f(t){var e=m(t);if(e)return y(t,e),void 0;var i=g(t);if(!i){if(N!=x.IDENTIFIER)throw w("Identifier expected");var n=O;if(p(),"="==O){if(p(),N!=x.IDENTIFIER)throw w("Identifier expected");t[n]=O,p()}else v(t,n)}}function m(t){var e=null;if("subgraph"==O&&(e={},e.type="subgraph",p(),N==x.IDENTIFIER&&(e.id=O,p())),"{"==O){if(p(),e||(e={}),e.parent=t,e.node=t.node,e.edge=t.edge,e.graph=t.graph,u(e),"}"!=O)throw w("Angle bracket } expected");p(),delete e.node,delete e.edge,delete e.graph,delete e.parent,t.subgraphs||(t.subgraphs=[]),t.subgraphs.push(e)}return e}function g(t){return"node"==O?(p(),t.node=b(),"node"):"edge"==O?(p(),t.edge=b(),"edge"):"graph"==O?(p(),t.graph=b(),"graph"):null}function v(t,e){var i={id:e},n=b();n&&(i.attr=n),h(t,i),y(t,e)}function y(t,e){for(;"->"==O||"--"==O;){var i,n=O;p();var s=m(t);if(s)i=s;else{if(N!=x.IDENTIFIER)throw w("Identifier or subgraph expected");i=O,h(t,{id:i}),p()}var o=b(),r=l(t,e,i,n,o);d(t,r),e=i}}function b(){for(var t=null;"["==O;){for(p(),t={};""!==O&&"]"!=O;){if(N!=x.IDENTIFIER)throw w("Attribute name expected");var e=O;if(p(),"="!=O)throw w("Equal sign = expected");if(p(),N!=x.IDENTIFIER)throw w("Attribute value expected");var i=O;a(t,e,i),p(),","==O&&p()}if("]"!=O)throw w("Bracket ] expected");p()}return t}function w(t){return new SyntaxError(t+', got "'+_(O,30)+'" (char '+D+")")}function _(t,e){return e>=t.length?t:t.substr(0,27)+"..."}function E(t,e,i){t instanceof Array?t.forEach(function(t){e instanceof Array?e.forEach(function(e){i(t,e)}):i(t,e)}):e instanceof Array?e.forEach(function(e){i(t,e)}):i(t,e)}function T(t){function i(t){var e={from:t.from,to:t.to};return r(e,t.attr),e.style="->"==t.type?"arrow":"line",e}var n=e(t),s={nodes:[],edges:[],options:{}};return n.nodes&&n.nodes.forEach(function(t){var e={id:t.id,label:(t.label||t.id)+""};r(e,t.attr),e.image&&(e.shape="image"),s.nodes.push(e)}),n.edges&&n.edges.forEach(function(t){var e,n;e=t.from instanceof Object?t.from.nodes:{id:t.from},n=t.to instanceof Object?t.to.nodes:{id:t.to},t.from instanceof Object&&t.from.edges&&t.from.edges.forEach(function(t){var e=i(t);s.edges.push(e)}),E(e,n,function(e,n){var o=l(s,e.id,n.id,t.type,t.attr),r=i(o);s.edges.push(r)}),t.to instanceof Object&&t.to.edges&&t.to.edges.forEach(function(t){var e=i(t);s.edges.push(e)})}),n.attr&&(s.options=n.attr),s}var x={NULL:0,DELIMITER:1,IDENTIFIER:2,UNKNOWN:3},S={"{":!0,"}":!0,"[":!0,"]":!0,";":!0,"=":!0,",":!0,"->":!0,"--":!0},M="",D=0,C="",O="",N=x.NULL,L=/[a-zA-Z_0-9.:#]/;t.parseDOT=e,t.DOTToGraph=T}(O!==void 0?O:n),"undefined"!=typeof CanvasRenderingContext2D&&(CanvasRenderingContext2D.prototype.circle=function(t,e,i){this.beginPath(),this.arc(t,e,i,0,2*Math.PI,!1)},CanvasRenderingContext2D.prototype.square=function(t,e,i){this.beginPath(),this.rect(t-i,e-i,2*i,2*i)},CanvasRenderingContext2D.prototype.triangle=function(t,e,i){this.beginPath();var n=2*i,s=n/2,o=Math.sqrt(3)/6*n,r=Math.sqrt(n*n-s*s);this.moveTo(t,e-(r-o)),this.lineTo(t+s,e+o),this.lineTo(t-s,e+o),this.lineTo(t,e-(r-o)),this.closePath()},CanvasRenderingContext2D.prototype.triangleDown=function(t,e,i){this.beginPath();var n=2*i,s=n/2,o=Math.sqrt(3)/6*n,r=Math.sqrt(n*n-s*s);this.moveTo(t,e+(r-o)),this.lineTo(t+s,e-o),this.lineTo(t-s,e-o),this.lineTo(t,e+(r-o)),this.closePath()},CanvasRenderingContext2D.prototype.star=function(t,e,i){this.beginPath();for(var n=0;10>n;n++){var s=0===n%2?1.3*i:.5*i;this.lineTo(t+s*Math.sin(2*n*Math.PI/10),e-s*Math.cos(2*n*Math.PI/10))}this.closePath()},CanvasRenderingContext2D.prototype.roundRect=function(t,e,i,n,s){var o=Math.PI/180;0>i-2*s&&(s=i/2),0>n-2*s&&(s=n/2),this.beginPath(),this.moveTo(t+s,e),this.lineTo(t+i-s,e),this.arc(t+i-s,e+s,s,270*o,360*o,!1),this.lineTo(t+i,e+n-s),this.arc(t+i-s,e+n-s,s,0,90*o,!1),this.lineTo(t+s,e+n),this.arc(t+s,e+n-s,s,90*o,180*o,!1),this.lineTo(t,e+s),this.arc(t+s,e+s,s,180*o,270*o,!1)},CanvasRenderingContext2D.prototype.ellipse=function(t,e,i,n){var s=.5522848,o=i/2*s,r=n/2*s,a=t+i,h=e+n,d=t+i/2,l=e+n/2;this.beginPath(),this.moveTo(t,l),this.bezierCurveTo(t,l-r,d-o,e,d,e),this.bezierCurveTo(d+o,e,a,l-r,a,l),this.bezierCurveTo(a,l+r,d+o,h,d,h),this.bezierCurveTo(d-o,h,t,l+r,t,l)},CanvasRenderingContext2D.prototype.database=function(t,e,i,n){var s=1/3,o=i,r=n*s,a=.5522848,h=o/2*a,d=r/2*a,l=t+o,p=e+r,c=t+o/2,u=e+r/2,f=e+(n-r/2),m=e+n;this.beginPath(),this.moveTo(l,u),this.bezierCurveTo(l,u+d,c+h,p,c,p),this.bezierCurveTo(c-h,p,t,u+d,t,u),this.bezierCurveTo(t,u-d,c-h,e,c,e),this.bezierCurveTo(c+h,e,l,u-d,l,u),this.lineTo(l,f),this.bezierCurveTo(l,f+d,c+h,m,c,m),this.bezierCurveTo(c-h,m,t,f+d,t,f),this.lineTo(t,u)},CanvasRenderingContext2D.prototype.arrow=function(t,e,i,n){var s=t-n*Math.cos(i),o=e-n*Math.sin(i),r=t-.9*n*Math.cos(i),a=e-.9*n*Math.sin(i),h=s+n/3*Math.cos(i+.5*Math.PI),d=o+n/3*Math.sin(i+.5*Math.PI),l=s+n/3*Math.cos(i-.5*Math.PI),p=o+n/3*Math.sin(i-.5*Math.PI);this.beginPath(),this.moveTo(t,e),this.lineTo(h,d),this.lineTo(r,a),this.lineTo(l,p),this.closePath()},CanvasRenderingContext2D.prototype.dashedLine=function(t,e,i,n,s){s||(s=[10,5]),0==c&&(c=.001);var o=s.length;this.moveTo(t,e);for(var r=i-t,a=n-e,h=a/r,d=Math.sqrt(r*r+a*a),l=0,p=!0;d>=.1;){var c=s[l++%o];c>d&&(c=d);var u=Math.sqrt(c*c/(1+h*h));0>r&&(u=-u),t+=u,e+=h*u,this[p?"lineTo":"moveTo"](t,e),d-=c,p=!p}}),E.prototype.attachEdge=function(t){-1==this.edges.indexOf(t)&&this.edges.push(t),this._updateMass()},E.prototype.detachEdge=function(t){var e=this.edges.indexOf(t);-1!=e&&this.edges.splice(e,1),this._updateMass()},E.prototype._updateMass=function(){this.mass=50+20*this.edges.length},E.prototype.setProperties=function(t,e){if(t){if(void 0!=t.id&&(this.id=t.id),void 0!=t.label&&(this.label=t.label),void 0!=t.title&&(this.title=t.title),void 0!=t.group&&(this.group=t.group),void 0!=t.x&&(this.x=t.x),void 0!=t.y&&(this.y=t.y),void 0!=t.value&&(this.value=t.value),void 0===this.id)throw"Node must have an id";if(this.group){var i=this.grouplist.get(this.group);for(var n in i)i.hasOwnProperty(n)&&(this[n]=i[n])}if(void 0!=t.shape&&(this.shape=t.shape),void 0!=t.image&&(this.image=t.image),void 0!=t.radius&&(this.radius=t.radius),void 0!=t.color&&(this.color=E.parseColor(t.color)),void 0!=t.fontColor&&(this.fontColor=t.fontColor),void 0!=t.fontSize&&(this.fontSize=t.fontSize),void 0!=t.fontFace&&(this.fontFace=t.fontFace),void 0!=this.image){if(!this.imagelist)throw"No imagelist provided";this.imageObj=this.imagelist.load(this.image)}switch(this.xFixed=this.xFixed||void 0!=t.x,this.yFixed=this.yFixed||void 0!=t.y,this.radiusFixed=this.radiusFixed||void 0!=t.radius,"image"==this.shape&&(this.radiusMin=e.nodes.widthMin,this.radiusMax=e.nodes.widthMax),this.shape){case"database":this.draw=this._drawDatabase,this.resize=this._resizeDatabase;break;case"box":this.draw=this._drawBox,this.resize=this._resizeBox;break;case"circle":this.draw=this._drawCircle,this.resize=this._resizeCircle;break;case"ellipse":this.draw=this._drawEllipse,this.resize=this._resizeEllipse;break;case"image":this.draw=this._drawImage,this.resize=this._resizeImage;break;case"text":this.draw=this._drawText,this.resize=this._resizeText;break;case"dot":this.draw=this._drawDot,this.resize=this._resizeShape;break;case"square":this.draw=this._drawSquare,this.resize=this._resizeShape;break;case"triangle":this.draw=this._drawTriangle,this.resize=this._resizeShape;break;case"triangleDown":this.draw=this._drawTriangleDown,this.resize=this._resizeShape;break;case"star":this.draw=this._drawStar,this.resize=this._resizeShape;break;default:this.draw=this._drawEllipse,this.resize=this._resizeEllipse}this._reset()}},E.parseColor=function(t){var e;return O.isString(t)?e={border:t,background:t,highlight:{border:t,background:t}}:(e={},e.background=t.background||"white",e.border=t.border||e.background,O.isString(t.highlight)?e.highlight={border:t.highlight,background:t.highlight}:(e.highlight={},e.highlight.background=t.highlight&&t.highlight.background||e.background,e.highlight.border=t.highlight&&t.highlight.border||e.border)),e},E.prototype.select=function(){this.selected=!0,this._reset()},E.prototype.unselect=function(){this.selected=!1,this._reset()},E.prototype._reset=function(){this.width=void 0,this.height=void 0},E.prototype.getTitle=function(){return this.title},E.prototype.distanceToBorder=function(t,e){var i=1;switch(this.width||this.resize(t),this.shape){case"circle":case"dot":return this.radius+i;case"ellipse":var n=this.width/2,s=this.height/2,o=Math.sin(e)*n,r=Math.cos(e)*s;return n*s/Math.sqrt(o*o+r*r);case"box":case"image":case"text":default:return this.width?Math.min(Math.abs(this.width/2/Math.cos(e)),Math.abs(this.height/2/Math.sin(e)))+i:0}},E.prototype._setForce=function(t,e){this.fx=t,this.fy=e},E.prototype._addForce=function(t,e){this.fx+=t,this.fy+=e},E.prototype.discreteStep=function(t){if(!this.xFixed){var e=-this.damping*this.vx,i=(this.fx+e)/this.mass;this.vx+=i/t,this.x+=this.vx/t}if(!this.yFixed){var n=-this.damping*this.vy,s=(this.fy+n)/this.mass;this.vy+=s/t,this.y+=this.vy/t}},E.prototype.isFixed=function(){return this.xFixed&&this.yFixed},E.prototype.isMoving=function(t){return Math.abs(this.vx)>t||Math.abs(this.vy)>t||!this.xFixed&&Math.abs(this.fx)>this.minForce||!this.yFixed&&Math.abs(this.fy)>this.minForce},E.prototype.isSelected=function(){return this.selected},E.prototype.getValue=function(){return this.value},E.prototype.getDistance=function(t,e){var i=this.x-t,n=this.y-e;return Math.sqrt(i*i+n*n)},E.prototype.setValueRange=function(t,e){if(!this.radiusFixed&&void 0!==this.value){var i=(this.radiusMax-this.radiusMin)/(e-t);this.radius=(this.value-t)*i+this.radiusMin}},E.prototype.draw=function(){throw"Draw method not initialized for node"},E.prototype.resize=function(){throw"Resize method not initialized for node"},E.prototype.isOverlappingWith=function(t){return this.leftt.left&&this.topt.top},E.prototype._resizeImage=function(){if(!this.width){var t,e;if(this.value){var i=this.imageObj.height/this.imageObj.width;t=this.radius||this.imageObj.width,e=this.radius*i||this.imageObj.height}else t=this.imageObj.width,e=this.imageObj.height;this.width=t,this.height=e}},E.prototype._drawImage=function(t){this._resizeImage(t),this.left=this.x-this.width/2,this.top=this.y-this.height/2;var e;this.imageObj?(t.drawImage(this.imageObj,this.left,this.top,this.width,this.height),e=this.y+this.height/2):e=this.y,this._label(t,this.label,this.x,e,void 0,"top")},E.prototype._resizeBox=function(t){if(!this.width){var e=5,i=this.getTextSize(t);this.width=i.width+2*e,this.height=i.height+2*e}},E.prototype._drawBox=function(t){this._resizeBox(t),this.left=this.x-this.width/2,this.top=this.y-this.height/2,t.strokeStyle=this.selected?this.color.highlight.border:this.color.border,t.fillStyle=this.selected?this.color.highlight.background:this.color.background,t.lineWidth=this.selected?2:1,t.roundRect(this.left,this.top,this.width,this.height,this.radius),t.fill(),t.stroke(),this._label(t,this.label,this.x,this.y)},E.prototype._resizeDatabase=function(t){if(!this.width){var e=5,i=this.getTextSize(t),n=i.width+2*e;this.width=n,this.height=n}},E.prototype._drawDatabase=function(t){this._resizeDatabase(t),this.left=this.x-this.width/2,this.top=this.y-this.height/2,t.strokeStyle=this.selected?this.color.highlight.border:this.color.border,t.fillStyle=this.selected?this.color.highlight.background:this.color.background,t.lineWidth=this.selected?2:1,t.database(this.x-this.width/2,this.y-.5*this.height,this.width,this.height),t.fill(),t.stroke(),this._label(t,this.label,this.x,this.y)},E.prototype._resizeCircle=function(t){if(!this.width){var e=5,i=this.getTextSize(t),n=Math.max(i.width,i.height)+2*e;this.radius=n/2,this.width=n,this.height=n}},E.prototype._drawCircle=function(t){this._resizeCircle(t),this.left=this.x-this.width/2,this.top=this.y-this.height/2,t.strokeStyle=this.selected?this.color.highlight.border:this.color.border,t.fillStyle=this.selected?this.color.highlight.background:this.color.background,t.lineWidth=this.selected?2:1,t.circle(this.x,this.y,this.radius),t.fill(),t.stroke(),this._label(t,this.label,this.x,this.y)},E.prototype._resizeEllipse=function(t){if(!this.width){var e=this.getTextSize(t);this.width=1.5*e.width,this.height=2*e.height,this.widthl;l++)t.fillText(r[l],i,d),d+=h}},E.prototype.getTextSize=function(t){if(void 0!=this.label){t.font=(this.selected?"bold ":"")+this.fontSize+"px "+this.fontFace;for(var e=this.label.split("\n"),i=(this.fontSize+4)*e.length,n=0,s=0,o=e.length;o>s;s++)n=Math.max(n,t.measureText(e[s]).width);return{width:n,height:i}}return{width:0,height:0}},T.prototype.setProperties=function(t,e){if(t)switch(void 0!=t.from&&(this.fromId=t.from),void 0!=t.to&&(this.toId=t.to),void 0!=t.id&&(this.id=t.id),void 0!=t.style&&(this.style=t.style),void 0!=t.label&&(this.label=t.label),this.label&&(this.fontSize=e.edges.fontSize,this.fontFace=e.edges.fontFace,this.fontColor=e.edges.fontColor,void 0!=t.fontColor&&(this.fontColor=t.fontColor),void 0!=t.fontSize&&(this.fontSize=t.fontSize),void 0!=t.fontFace&&(this.fontFace=t.fontFace)),void 0!=t.title&&(this.title=t.title),void 0!=t.width&&(this.width=t.width),void 0!=t.value&&(this.value=t.value),void 0!=t.length&&(this.length=t.length),t.dash&&(void 0!=t.dash.length&&(this.dash.length=t.dash.length),void 0!=t.dash.gap&&(this.dash.gap=t.dash.gap),void 0!=t.dash.altLength&&(this.dash.altLength=t.dash.altLength)),void 0!=t.color&&(this.color=t.color),this.connect(),this.widthFixed=this.widthFixed||void 0!=t.width,this.lengthFixed=this.lengthFixed||void 0!=t.length,this.stiffness=1/this.length,this.style){case"line":this.draw=this._drawLine;break;case"arrow":this.draw=this._drawArrow;break;case"arrow-center":this.draw=this._drawArrowCenter;break;case"dash-line":this.draw=this._drawDashLine;break;default:this.draw=this._drawLine}},T.prototype.connect=function(){this.disconnect(),this.from=this.graph.nodes[this.fromId]||null,this.to=this.graph.nodes[this.toId]||null,this.connected=this.from&&this.to,this.connected?(this.from.attachEdge(this),this.to.attachEdge(this)):(this.from&&this.from.detachEdge(this),this.to&&this.to.detachEdge(this))},T.prototype.disconnect=function(){this.from&&(this.from.detachEdge(this),this.from=null),this.to&&(this.to.detachEdge(this),this.to=null),this.connected=!1},T.prototype.getTitle=function(){return this.title},T.prototype.getValue=function(){return this.value},T.prototype.setValueRange=function(t,e){if(!this.widthFixed&&void 0!==this.value){var i=(this.widthMax-this.widthMin)/(e-t);this.width=(this.value-t)*i+this.widthMin}},T.prototype.draw=function(){throw"Method draw not initialized in edge"},T.prototype.isOverlappingWith=function(t){var e=10,i=this.from.x,n=this.from.y,s=this.to.x,o=this.to.y,r=t.left,a=t.top,h=T._dist(i,n,s,o,r,a);return e>h},T.prototype._drawLine=function(t){t.strokeStyle=this.color,t.lineWidth=this._getLineWidth();var e;if(this.from!=this.to)this._line(t),this.label&&(e=this._pointOnLine(.5),this._label(t,this.label,e.x,e.y));else{var i,n,s=this.length/4,o=this.from;o.width||o.resize(t),o.width>o.height?(i=o.x+o.width/2,n=o.y-s):(i=o.x+s,n=o.y-o.height/2),this._circle(t,i,n,s),e=this._pointOnCircle(i,n,s,.5),this._label(t,this.label,e.x,e.y)}},T.prototype._getLineWidth=function(){return this.from.selected||this.to.selected?Math.min(2*this.width,this.widthMax):this.width},T.prototype._line=function(t){t.beginPath(),t.moveTo(this.from.x,this.from.y),t.lineTo(this.to.x,this.to.y),t.stroke()},T.prototype._circle=function(t,e,i,n){t.beginPath(),t.arc(e,i,n,0,2*Math.PI,!1),t.stroke()},T.prototype._label=function(t,e,i,n){if(e){t.font=(this.from.selected||this.to.selected?"bold ":"")+this.fontSize+"px "+this.fontFace,t.fillStyle="white";var s=t.measureText(e).width,o=this.fontSize,r=i-s/2,a=n-o/2;t.fillRect(r,a,s,o),t.fillStyle=this.fontColor||"black",t.textAlign="left",t.textBaseline="top",t.fillText(e,r,a)}},T.prototype._drawDashLine=function(t){if(t.strokeStyle=this.color,t.lineWidth=this._getLineWidth(),t.beginPath(),t.lineCap="round",void 0!=this.dash.altLength?t.dashedLine(this.from.x,this.from.y,this.to.x,this.to.y,[this.dash.length,this.dash.gap,this.dash.altLength,this.dash.gap]):void 0!=this.dash.length&&void 0!=this.dash.gap?t.dashedLine(this.from.x,this.from.y,this.to.x,this.to.y,[this.dash.length,this.dash.gap]):(t.moveTo(this.from.x,this.from.y),t.lineTo(this.to.x,this.to.y)),t.stroke(),this.label){var e=this._pointOnLine(.5);this._label(t,this.label,e.x,e.y)}},T.prototype._pointOnLine=function(t){return{x:(1-t)*this.from.x+t*this.to.x,y:(1-t)*this.from.y+t*this.to.y}},T.prototype._pointOnCircle=function(t,e,i,n){var s=2*(n-3/8)*Math.PI;return{x:t+i*Math.cos(s),y:e-i*Math.sin(s)}},T.prototype._drawArrowCenter=function(t){var e;if(t.strokeStyle=this.color,t.fillStyle=this.color,t.lineWidth=this._getLineWidth(),this.from!=this.to){this._line(t);var i=Math.atan2(this.to.y-this.from.y,this.to.x-this.from.x),n=10+5*this.width;e=this._pointOnLine(.5),t.arrow(e.x,e.y,i,n),t.fill(),t.stroke(),this.label&&(e=this._pointOnLine(.5),this._label(t,this.label,e.x,e.y))}else{var s,o,r=this.length/4,a=this.from;a.width||a.resize(t),a.width>a.height?(s=a.x+a.width/2,o=a.y-r):(s=a.x+r,o=a.y-a.height/2),this._circle(t,s,o,r);var i=.2*Math.PI,n=10+5*this.width;e=this._pointOnCircle(s,o,r,.5),t.arrow(e.x,e.y,i,n),t.fill(),t.stroke(),this.label&&(e=this._pointOnCircle(s,o,r,.5),this._label(t,this.label,e.x,e.y))}},T.prototype._drawArrow=function(t){t.strokeStyle=this.color,t.fillStyle=this.color,t.lineWidth=this._getLineWidth();var e,i;if(this.from!=this.to){e=Math.atan2(this.to.y-this.from.y,this.to.x-this.from.x);var n=this.to.x-this.from.x,s=this.to.y-this.from.y,o=Math.sqrt(n*n+s*s),r=this.from.distanceToBorder(t,e+Math.PI),a=(o-r)/o,h=a*this.from.x+(1-a)*this.to.x,d=a*this.from.y+(1-a)*this.to.y,l=this.to.distanceToBorder(t,e),p=(o-l)/o,c=(1-p)*this.from.x+p*this.to.x,u=(1-p)*this.from.y+p*this.to.y;if(t.beginPath(),t.moveTo(h,d),t.lineTo(c,u),t.stroke(),i=10+5*this.width,t.arrow(c,u,e,i),t.fill(),t.stroke(),this.label){var f=this._pointOnLine(.5);this._label(t,this.label,f.x,f.y)}}else{var m,g,v,y=this.from,b=this.length/4;y.width||y.resize(t),y.width>y.height?(m=y.x+y.width/2,g=y.y-b,v={x:m,y:y.y,angle:.9*Math.PI}):(m=y.x+b,g=y.y-y.height/2,v={x:y.x,y:g,angle:.6*Math.PI}),t.beginPath(),t.arc(m,g,b,0,2*Math.PI,!1),t.stroke(),i=10+5*this.width,t.arrow(v.x,v.y,v.angle,i),t.fill(),t.stroke(),this.label&&(f=this._pointOnCircle(m,g,b,.5),this._label(t,this.label,f.x,f.y)) -}},T._dist=function(t,e,i,n,s,o){var r=i-t,a=n-e,h=r*r+a*a,d=((s-t)*r+(o-e)*a)/h;d>1?d=1:0>d&&(d=0);var l=t+d*r,p=e+d*a,c=l-s,u=p-o;return Math.sqrt(c*c+u*u)},x.prototype.setPosition=function(t,e){this.x=parseInt(t),this.y=parseInt(e)},x.prototype.setText=function(t){this.frame.innerHTML=t},x.prototype.show=function(t){if(void 0===t&&(t=!0),t){var e=this.frame.clientHeight,i=this.frame.clientWidth,n=this.frame.parentNode.clientHeight,s=this.frame.parentNode.clientWidth,o=this.y-e;o+e+this.padding>n&&(o=n-e-this.padding),this.padding>o&&(o=this.padding);var r=this.x;r+i+this.padding>s&&(r=s-i-this.padding),this.padding>r&&(r=this.padding),this.frame.style.left=r+"px",this.frame.style.top=o+"px",this.frame.style.visibility="visible"}else this.hide()},x.prototype.hide=function(){this.frame.style.visibility="hidden"},Groups=function(){this.clear(),this.defaultIndex=0},Groups.DEFAULT=[{border:"#2B7CE9",background:"#97C2FC",highlight:{border:"#2B7CE9",background:"#D2E5FF"}},{border:"#FFA500",background:"#FFFF00",highlight:{border:"#FFA500",background:"#FFFFA3"}},{border:"#FA0A10",background:"#FB7E81",highlight:{border:"#FA0A10",background:"#FFAFB1"}},{border:"#41A906",background:"#7BE141",highlight:{border:"#41A906",background:"#A1EC76"}},{border:"#E129F0",background:"#EB7DF4",highlight:{border:"#E129F0",background:"#F0B3F5"}},{border:"#7C29F0",background:"#AD85E4",highlight:{border:"#7C29F0",background:"#D3BDF0"}},{border:"#C37F00",background:"#FFA807",highlight:{border:"#C37F00",background:"#FFCA66"}},{border:"#4220FB",background:"#6E6EFD",highlight:{border:"#4220FB",background:"#9B9BFD"}},{border:"#FD5A77",background:"#FFC0CB",highlight:{border:"#FD5A77",background:"#FFD1D9"}},{border:"#4AD63A",background:"#C2FABC",highlight:{border:"#4AD63A",background:"#E6FFE3"}}],Groups.prototype.clear=function(){this.groups={},this.groups.length=function(){var t=0;for(var e in this)this.hasOwnProperty(e)&&t++;return t}},Groups.prototype.get=function(t){var e=this.groups[t];if(void 0==e){var i=this.defaultIndex%Groups.DEFAULT.length;this.defaultIndex++,e={},e.color=Groups.DEFAULT[i],this.groups[t]=e}return e},Groups.prototype.add=function(t,e){return this.groups[t]=e,e.color&&(e.color=E.parseColor(e.color)),e},Images=function(){this.images={},this.callback=void 0},Images.prototype.setOnloadCallback=function(t){this.callback=t},Images.prototype.load=function(t){var e=this.images[t];if(void 0==e){var i=this;e=new Image,this.images[t]=e,e.onload=function(){i.callback&&i.callback(this)},e.src=t}return e},S.prototype.setData=function(t){if(t&&t.dot&&(t.nodes||t.edges))throw new SyntaxError('Data must contain either parameter "dot" or parameter pair "nodes" and "edges", but not both.');if(this.setOptions(t&&t.options),t&&t.dot){if(t&&t.dot){var e=k.util.DOTToGraph(t.dot);return this.setData(e),void 0}}else this._setNodes(t&&t.nodes),this._setEdges(t&&t.edges);this.stabilize&&this._doStabilize(),this.start()},S.prototype.setOptions=function(t){if(t){if(void 0!=t.width&&(this.width=t.width),void 0!=t.height&&(this.height=t.height),void 0!=t.stabilize&&(this.stabilize=t.stabilize),void 0!=t.selectable&&(this.selectable=t.selectable),t.edges){for(var e in t.edges)t.edges.hasOwnProperty(e)&&(this.constants.edges[e]=t.edges[e]);void 0!=t.edges.length&&t.nodes&&void 0==t.nodes.distance&&(this.constants.edges.length=t.edges.length,this.constants.nodes.distance=1.25*t.edges.length),t.edges.fontColor||(this.constants.edges.fontColor=t.edges.color),t.edges.dash&&(void 0!=t.edges.dash.length&&(this.constants.edges.dash.length=t.edges.dash.length),void 0!=t.edges.dash.gap&&(this.constants.edges.dash.gap=t.edges.dash.gap),void 0!=t.edges.dash.altLength&&(this.constants.edges.dash.altLength=t.edges.dash.altLength))}if(t.nodes){for(e in t.nodes)t.nodes.hasOwnProperty(e)&&(this.constants.nodes[e]=t.nodes[e]);t.nodes.color&&(this.constants.nodes.color=E.parseColor(t.nodes.color))}if(t.groups)for(var i in t.groups)if(t.groups.hasOwnProperty(i)){var n=t.groups[i];this.groups.add(i,n)}}this.setSize(this.width,this.height),this._setTranslation(this.frame.clientWidth/2,this.frame.clientHeight/2),this._setScale(1)},S.prototype._trigger=function(t,e){L.trigger(this,t,e)},S.prototype._create=function(){for(;this.containerElement.hasChildNodes();)this.containerElement.removeChild(this.containerElement.firstChild);if(this.frame=document.createElement("div"),this.frame.className="graph-frame",this.frame.style.position="relative",this.frame.style.overflow="hidden",this.frame.canvas=document.createElement("canvas"),this.frame.canvas.style.position="relative",this.frame.appendChild(this.frame.canvas),!this.frame.canvas.getContext){var t=document.createElement("DIV");t.style.color="red",t.style.fontWeight="bold",t.style.padding="10px",t.innerHTML="Error: your browser does not support HTML canvas",this.frame.canvas.appendChild(t)}var e=this;this.drag={},this.pinch={},this.hammer=D(this.frame.canvas,{prevent_default:!0}),this.hammer.on("tap",e._onTap.bind(e)),this.hammer.on("hold",e._onHold.bind(e)),this.hammer.on("pinch",e._onPinch.bind(e)),this.hammer.on("touch",e._onTouch.bind(e)),this.hammer.on("dragstart",e._onDragStart.bind(e)),this.hammer.on("drag",e._onDrag.bind(e)),this.hammer.on("dragend",e._onDragEnd.bind(e)),this.hammer.on("mousewheel",e._onMouseWheel.bind(e)),this.hammer.on("mousemove",e._onMouseMoveTitle.bind(e)),this.containerElement.appendChild(this.frame)},S.prototype._getNodeAt=function(t){var e=this._xToCanvas(t.x),i=this._yToCanvas(t.y),n={left:e,top:i,right:e,bottom:i},s=this._getNodesOverlappingWith(n);return s.length>0?s[s.length-1]:null},S.prototype._getPointer=function(t){return{x:t.pageX-k.util.getAbsoluteLeft(this.frame.canvas),y:t.pageY-k.util.getAbsoluteTop(this.frame.canvas)}},S.prototype._onTouch=function(t){this.drag.pointer=this._getPointer(t.gesture.touches[0]),this.drag.pinched=!1,this.pinch.scale=this._getScale()},S.prototype._onDragStart=function(){var t=this.drag;t.selection=[],t.translation=this._getTranslation(),t.nodeId=this._getNodeAt(t.pointer);var e=this.nodes[t.nodeId];if(e){e.isSelected()||this._selectNodes([t.nodeId]);var i=this;this.selection.forEach(function(e){var n=i.nodes[e];if(n){var s={id:e,node:n,x:n.x,y:n.y,xFixed:n.xFixed,yFixed:n.yFixed};n.xFixed=!0,n.yFixed=!0,t.selection.push(s)}})}},S.prototype._onDrag=function(t){if(!this.drag.pinched){var e=this._getPointer(t.gesture.touches[0]),i=this,n=this.drag,s=n.selection;if(s&&s.length){var o=e.x-n.pointer.x,r=e.y-n.pointer.y;s.forEach(function(t){var e=t.node;t.xFixed||(e.x=i._xToCanvas(i._canvasToX(t.x)+o)),t.yFixed||(e.y=i._yToCanvas(i._canvasToY(t.y)+r))}),this.moving||(this.moving=!0,this.start())}else{var a=e.x-this.drag.pointer.x,h=e.y-this.drag.pointer.y;this._setTranslation(this.drag.translation.x+a,this.drag.translation.y+h),this._redraw(),this.moved=!0}}},S.prototype._onDragEnd=function(){var t=this.drag.selection;t&&t.forEach(function(t){t.node.xFixed=t.xFixed,t.node.yFixed=t.yFixed})},S.prototype._onTap=function(t){var e=this._getPointer(t.gesture.touches[0]),i=this._getNodeAt(e),n=this.nodes[i];n?(this._selectNodes([i]),this.moving||this._redraw()):(this._unselectNodes(),this._redraw())},S.prototype._onHold=function(t){var e=this._getPointer(t.gesture.touches[0]),i=this._getNodeAt(e),n=this.nodes[i];if(n){if(n.isSelected())this._unselectNodes([i]);else{var s=!0;this._selectNodes([i],s)}this.moving||this._redraw()}},S.prototype._onPinch=function(t){var e=this._getPointer(t.gesture.center);this.drag.pinched=!0,"scale"in this.pinch||(this.pinch.scale=1);var i=this.pinch.scale*t.gesture.scale;this._zoom(i,e)},S.prototype._zoom=function(t,e){var i=this._getScale();.01>t&&(t=.01),t>10&&(t=10);var n=this._getTranslation(),s=t/i,o=(1-s)*e.x+n.x*s,r=(1-s)*e.y+n.y*s;return this._setScale(t),this._setTranslation(o,r),this._redraw(),t},S.prototype._onMouseWheel=function(t){var e=0;if(t.wheelDelta?e=t.wheelDelta/120:t.detail&&(e=-t.detail/3),e){"mouswheelScale"in this.pinch||(this.pinch.mouswheelScale=1);var i=this.pinch.mouswheelScale,n=e/10;0>e&&(n/=1-n),i*=1+n;var s=D.event.collectEventData(this,"scroll",t),o=this._getPointer(s.center);i=this._zoom(i,o),this.pinch.mouswheelScale=i}t.preventDefault()},S.prototype._onMouseMoveTitle=function(t){var e=D.event.collectEventData(this,"mousemove",t),i=this._getPointer(e.center);this.popupNode&&this._checkHidePopup(i);var n=this,s=function(){n._checkShowPopup(i)};this.popupTimer&&clearInterval(this.popupTimer),this.leftButtonDown||(this.popupTimer=setTimeout(s,300))},S.prototype._checkShowPopup=function(t){var e,i={left:this._xToCanvas(t.x),top:this._yToCanvas(t.y),right:this._xToCanvas(t.x),bottom:this._yToCanvas(t.y)},n=this.popupNode;if(void 0==this.popupNode){var s=this.nodes;for(e in s)if(s.hasOwnProperty(e)){var o=s[e];if(void 0!=o.getTitle()&&o.isOverlappingWith(i)){this.popupNode=o;break}}}if(void 0==this.popupNode){var r=this.edges;for(e in r)if(r.hasOwnProperty(e)){var a=r[e];if(a.connected&&void 0!=a.getTitle()&&a.isOverlappingWith(i)){this.popupNode=a;break}}}if(this.popupNode){if(this.popupNode!=n){var h=this;h.popup||(h.popup=new x(h.frame)),h.popup.setPosition(t.x-3,t.y-3),h.popup.setText(h.popupNode.getTitle()),h.popup.show()}}else this.popup&&this.popup.hide()},S.prototype._checkHidePopup=function(t){this.popupNode&&this._getNodeAt(t)||(this.popupNode=void 0,this.popup&&this.popup.hide())},S.prototype._unselectNodes=function(t,e){var i,n,s,o=!1;if(t)for(i=0,n=t.length;n>i;i++){s=t[i],this.nodes[s].unselect();for(var r=0;this.selection.length>r;)this.selection[r]==s?(this.selection.splice(r,1),o=!0):r++}else if(this.selection&&this.selection.length){for(i=0,n=this.selection.length;n>i;i++)s=this.selection[i],this.nodes[s].unselect(),o=!0;this.selection=[]}return!o||1!=e&&void 0!=e||this._trigger("select"),o},S.prototype._selectNodes=function(t,e){var i,n,s=!1,o=!0;if(t.length!=this.selection.length)o=!1;else for(i=0,n=Math.min(t.length,this.selection.length);n>i;i++)if(t[i]!=this.selection[i]){o=!1;break}if(o)return s;if(void 0==e||0==e){var r=!1;s=this._unselectNodes(void 0,r)}for(i=0,n=t.length;n>i;i++){var a=t[i],h=-1!=this.selection.indexOf(a);h||(this.nodes[a].select(),this.selection.push(a),s=!0)}return s&&this._trigger("select"),s},S.prototype._getNodesOverlappingWith=function(t){var e=this.nodes,i=[];for(var n in e)e.hasOwnProperty(n)&&e[n].isOverlappingWith(t)&&i.push(n);return i},S.prototype.getSelection=function(){return this.selection.concat([])},S.prototype.setSelection=function(t){var e,i,n;if(!t||void 0==t.length)throw"Selection must be an array with ids";for(e=0,i=this.selection.length;i>e;e++)n=this.selection[e],this.nodes[n].unselect();for(this.selection=[],e=0,i=t.length;i>e;e++){n=t[e];var s=this.nodes[n];if(!s)throw new RangeError('Node with id "'+n+'" not found');s.select(),this.selection.push(n)}this.redraw()},S.prototype._updateSelection=function(){for(var t=0;this.selection.length>t;){var e=this.selection[t];this.nodes[e]?t++:this.selection.splice(t,1)}},S.prototype._getConnectionCount=function(t){function e(t){for(var e=[],i=0,n=t.length;n>i;i++)for(var s=t[i],o=s.edges,r=0,a=o.length;a>r;r++){var h=o[r],d=null;h.from==s?d=h.to:h.to==s&&(d=h.from);var l,p;if(d)for(l=0,p=t.length;p>l;l++)if(t[l]==d){d=null;break}if(d)for(l=0,p=e.length;p>l;l++)if(e[l]==d){d=null;break}d&&e.push(d)}return e}void 0==t&&(t=1);var i=[],n=this.nodes;for(var s in n)if(n.hasOwnProperty(s)){for(var o=[n[s]],r=0;t>r;r++)o=o.concat(e(o));i.push(o)}for(var a=[],h=0,d=i.length;d>h;h++)a.push(i[h].length);return a},S.prototype.setSize=function(t,e){this.frame.style.width=t,this.frame.style.height=e,this.frame.canvas.style.width="100%",this.frame.canvas.style.height="100%",this.frame.canvas.width=this.frame.canvas.clientWidth,this.frame.canvas.height=this.frame.canvas.clientHeight},S.prototype._setNodes=function(t){var e=this.nodesData;if(t instanceof o||t instanceof r)this.nodesData=t;else if(t instanceof Array)this.nodesData=new o,this.nodesData.add(t);else{if(t)throw new TypeError("Array or DataSet expected");this.nodesData=new o}if(e&&O.forEach(this.nodesListeners,function(t,i){e.unsubscribe(i,t)}),this.nodes={},this.nodesData){var i=this;O.forEach(this.nodesListeners,function(t,e){i.nodesData.subscribe(e,t)});var n=this.nodesData.getIds();this._addNodes(n)}this._updateSelection()},S.prototype._addNodes=function(t){for(var e,i=0,n=t.length;n>i;i++){e=t[i];var s=this.nodesData.get(e),o=new E(s,this.images,this.groups,this.constants);if(this.nodes[e]=o,!o.isFixed()){var r=2*this.constants.edges.length,a=t.length,h=2*Math.PI*(i/a);o.x=r*Math.cos(h),o.y=r*Math.sin(h),this.moving=!0}}this._reconnectEdges(),this._updateValueRange(this.nodes)},S.prototype._updateNodes=function(t){for(var e=this.nodes,i=this.nodesData,n=0,s=t.length;s>n;n++){var o=t[n],r=e[o],a=i.get(o);r?r.setProperties(a,this.constants):(r=new E(properties,this.images,this.groups,this.constants),e[o]=r,r.isFixed()||(this.moving=!0))}this._reconnectEdges(),this._updateValueRange(e)},S.prototype._removeNodes=function(t){for(var e=this.nodes,i=0,n=t.length;n>i;i++){var s=t[i];delete e[s]}this._reconnectEdges(),this._updateSelection(),this._updateValueRange(e)},S.prototype._setEdges=function(t){var e=this.edgesData;if(t instanceof o||t instanceof r)this.edgesData=t;else if(t instanceof Array)this.edgesData=new o,this.edgesData.add(t);else{if(t)throw new TypeError("Array or DataSet expected");this.edgesData=new o}if(e&&O.forEach(this.edgesListeners,function(t,i){e.unsubscribe(i,t)}),this.edges={},this.edgesData){var i=this;O.forEach(this.edgesListeners,function(t,e){i.edgesData.subscribe(e,t)});var n=this.edgesData.getIds();this._addEdges(n)}this._reconnectEdges()},S.prototype._addEdges=function(t){for(var e=this.edges,i=this.edgesData,n=0,s=t.length;s>n;n++){var o=t[n],r=e[o];r&&r.disconnect();var a=i.get(o);e[o]=new T(a,this,this.constants)}this.moving=!0,this._updateValueRange(e)},S.prototype._updateEdges=function(t){for(var e=this.edges,i=this.edgesData,n=0,s=t.length;s>n;n++){var o=t[n],r=i.get(o),a=e[o];a?(a.disconnect(),a.setProperties(r,this.constants),a.connect()):(a=new T(r,this,this.constants),this.edges[o]=a)}this.moving=!0,this._updateValueRange(e)},S.prototype._removeEdges=function(t){for(var e=this.edges,i=0,n=t.length;n>i;i++){var s=t[i],o=e[s];o&&(o.disconnect(),delete e[s])}this.moving=!0,this._updateValueRange(e)},S.prototype._reconnectEdges=function(){var t,e=this.nodes,i=this.edges;for(t in e)e.hasOwnProperty(t)&&(e[t].edges=[]);for(t in i)if(i.hasOwnProperty(t)){var n=i[t];n.from=null,n.to=null,n.connect()}},S.prototype._updateValueRange=function(t){var e,i=void 0,n=void 0;for(e in t)if(t.hasOwnProperty(e)){var s=t[e].getValue();void 0!==s&&(i=void 0===i?s:Math.min(s,i),n=void 0===n?s:Math.max(s,n))}if(void 0!==i&&void 0!==n)for(e in t)t.hasOwnProperty(e)&&t[e].setValueRange(i,n)},S.prototype.redraw=function(){this.setSize(this.width,this.height),this._redraw()},S.prototype._redraw=function(){var t=this.frame.canvas.getContext("2d"),e=this.frame.canvas.width,i=this.frame.canvas.height;t.clearRect(0,0,e,i),t.save(),t.translate(this.translation.x,this.translation.y),t.scale(this.scale,this.scale),this._drawEdges(t),this._drawNodes(t),t.restore()},S.prototype._setTranslation=function(t,e){void 0===this.translation&&(this.translation={x:0,y:0}),void 0!==t&&(this.translation.x=t),void 0!==e&&(this.translation.y=e)},S.prototype._getTranslation=function(){return{x:this.translation.x,y:this.translation.y}},S.prototype._setScale=function(t){this.scale=t},S.prototype._getScale=function(){return this.scale},S.prototype._xToCanvas=function(t){return(t-this.translation.x)/this.scale},S.prototype._canvasToX=function(t){return t*this.scale+this.translation.x},S.prototype._yToCanvas=function(t){return(t-this.translation.y)/this.scale},S.prototype._canvasToY=function(t){return t*this.scale+this.translation.y},S.prototype._drawNodes=function(t){var e=this.nodes,i=[];for(var n in e)e.hasOwnProperty(n)&&(e[n].isSelected()?i.push(n):e[n].draw(t));for(var s=0,o=i.length;o>s;s++)e[i[s]].draw(t)},S.prototype._drawEdges=function(t){var e=this.edges;for(var i in e)if(e.hasOwnProperty(i)){var n=e[i];n.connected&&e[i].draw(t)}},S.prototype._doStabilize=function(){new Date;for(var t=0,e=this.constants.minVelocity,i=!1;!i&&this.constants.maxIterations>t;)this._calculateForces(),this._discreteStepNodes(),i=!this._isMoving(e),t++;new Date},S.prototype._calculateForces=function(){var t,e,i,n,s,o,r,a,h,d,l,p=this.nodes,c=this.edges,u=.01,f=this.frame.canvas.clientWidth/2,m=this.frame.canvas.clientHeight/2;for(t in p)if(p.hasOwnProperty(t)){var g=p[t];e=f-g.x,i=m-g.y,n=Math.atan2(i,e),o=Math.cos(n)*u,r=Math.sin(n)*u,g._setForce(o,r)}var v=this.constants.nodes.distance,y=10;for(var b in p)if(p.hasOwnProperty(b)){var w=p[b];for(var _ in p)if(p.hasOwnProperty(_)){var E=p[_];e=E.x-w.x,i=E.y-w.y,s=Math.sqrt(e*e+i*i),n=Math.atan2(i,e),a=1/(1+Math.exp((s/v-1)*y)),o=Math.cos(n)*a,r=Math.sin(n)*a,w._addForce(-o,-r),E._addForce(o,r)}}for(t in c)if(c.hasOwnProperty(t)){var T=c[t];T.connected&&(e=T.to.x-T.from.x,i=T.to.y-T.from.y,l=T.length,d=Math.sqrt(e*e+i*i),n=Math.atan2(i,e),h=T.stiffness*(l-d),o=Math.cos(n)*h,r=Math.sin(n)*h,T.from._addForce(-o,-r),T.to._addForce(o,r))}},S.prototype._isMoving=function(t){var e=this.nodes;for(var i in e)if(e.hasOwnProperty(i)&&e[i].isMoving(t))return!0;return!1},S.prototype._discreteStepNodes=function(){var t=this.refreshRate/1e3,e=this.nodes;for(var i in e)e.hasOwnProperty(i)&&e[i].discreteStep(t)},S.prototype.start=function(){if(this.moving){this._calculateForces(),this._discreteStepNodes();var t=this.constants.minVelocity;this.moving=this._isMoving(t)}if(this.moving){if(!this.timer){var e=this;this.timer=window.setTimeout(function(){e.timer=void 0,e.start(),e._redraw()},this.refreshRate)}}else this._redraw()},S.prototype.stop=function(){this.timer&&(window.clearInterval(this.timer),this.timer=void 0)};var k={util:O,events:L,Controller:d,DataSet:o,DataView:r,Range:h,Stack:a,TimeStep:TimeStep,EventBus:s,components:{items:{Item:m,ItemBox:g,ItemPoint:v,ItemRange:y},Component:l,Panel:p,RootPanel:c,ItemSet:f,TimeAxis:u},graph:{Node:E,Edge:T,Popup:x,Groups:Groups,Images:Images},Timeline:_,Graph:S};n!==void 0&&(n=k),i!==void 0&&i.exports!==void 0&&(i.exports=k),"function"==typeof t&&t(function(){return k}),"undefined"!=typeof window&&(window.vis=k),O.loadCss("/* vis.js stylesheet */\n.vis.timeline {\n}\n\n\n.vis.timeline.rootpanel {\n position: relative;\n overflow: hidden;\n\n border: 1px solid #bfbfbf;\n -moz-box-sizing: border-box;\n box-sizing: border-box;\n}\n\n.vis.timeline .panel {\n position: absolute;\n overflow: hidden;\n}\n\n\n.vis.timeline .groupset {\n position: absolute;\n padding: 0;\n margin: 0;\n}\n\n.vis.timeline .labels {\n position: absolute;\n top: 0;\n left: 0;\n width: 100%;\n height: 100%;\n\n padding: 0;\n margin: 0;\n\n border-right: 1px solid #bfbfbf;\n box-sizing: border-box;\n -moz-box-sizing: border-box;\n}\n\n.vis.timeline .labels .label {\n position: absolute;\n left: 0;\n top: 0;\n width: 100%;\n border-bottom: 1px solid #bfbfbf;\n color: #4d4d4d;\n}\n\n.vis.timeline .labels .label .inner {\n display: inline-block;\n padding: 5px;\n}\n\n\n.vis.timeline .itemset {\n position: absolute;\n padding: 0;\n margin: 0;\n overflow: hidden;\n}\n\n.vis.timeline .background {\n}\n\n.vis.timeline .foreground {\n}\n\n.vis.timeline .itemset-axis {\n position: absolute;\n}\n\n.vis.timeline .groupset .itemset-axis {\n border-top: 1px solid #bfbfbf;\n}\n\n/* TODO: with orientation=='bottom', this will more or less overlap with timeline axis\n.vis.timeline .groupset .itemset-axis:last-child {\n border-top: none;\n}\n*/\n\n\n.vis.timeline .item {\n position: absolute;\n color: #1A1A1A;\n border-color: #97B0F8;\n background-color: #D5DDF6;\n display: inline-block;\n}\n\n.vis.timeline .item.selected {\n border-color: #FFC200;\n background-color: #FFF785;\n z-index: 999;\n}\n\n.vis.timeline .item.cluster {\n /* TODO: use another color or pattern? */\n background: #97B0F8 url('img/cluster_bg.png');\n color: white;\n}\n.vis.timeline .item.cluster.point {\n border-color: #D5DDF6;\n}\n\n.vis.timeline .item.box {\n text-align: center;\n border-style: solid;\n border-width: 1px;\n border-radius: 5px;\n -moz-border-radius: 5px; /* For Firefox 3.6 and older */\n}\n\n.vis.timeline .item.point {\n background: none;\n}\n\n.vis.timeline .dot {\n border: 5px solid #97B0F8;\n position: absolute;\n border-radius: 5px;\n -moz-border-radius: 5px; /* For Firefox 3.6 and older */\n}\n\n.vis.timeline .item.range {\n overflow: hidden;\n border-style: solid;\n border-width: 1px;\n border-radius: 2px;\n -moz-border-radius: 2px; /* For Firefox 3.6 and older */\n}\n\n.vis.timeline .item.range .drag-left {\n cursor: w-resize;\n z-index: 1000;\n}\n\n.vis.timeline .item.range .drag-right {\n cursor: e-resize;\n z-index: 1000;\n}\n\n.vis.timeline .item.range .content {\n position: relative;\n display: inline-block;\n}\n\n.vis.timeline .item.line {\n position: absolute;\n width: 0;\n border-left-width: 1px;\n border-left-style: solid;\n}\n\n.vis.timeline .item .content {\n margin: 5px;\n white-space: nowrap;\n overflow: hidden;\n}\n\n.vis.timeline .axis {\n position: relative;\n}\n\n.vis.timeline .axis .text {\n position: absolute;\n color: #4d4d4d;\n padding: 3px;\n white-space: nowrap;\n}\n\n.vis.timeline .axis .text.measure {\n position: absolute;\n padding-left: 0;\n padding-right: 0;\n margin-left: 0;\n margin-right: 0;\n visibility: hidden;\n}\n\n.vis.timeline .axis .grid.vertical {\n position: absolute;\n width: 0;\n border-right: 1px solid;\n}\n\n.vis.timeline .axis .grid.horizontal {\n position: absolute;\n left: 0;\n width: 100%;\n height: 0;\n border-bottom: 1px solid;\n}\n\n.vis.timeline .axis .grid.minor {\n border-color: #e5e5e5;\n}\n\n.vis.timeline .axis .grid.major {\n border-color: #bfbfbf;\n}\n\n")},{hammerjs:1,moment:2}]},{},[3])(3)}); \ No newline at end of file +}},T._dist=function(t,e,i,n,s,o){var r=i-t,a=n-e,h=r*r+a*a,d=((s-t)*r+(o-e)*a)/h;d>1?d=1:0>d&&(d=0);var l=t+d*r,p=e+d*a,c=l-s,u=p-o;return Math.sqrt(c*c+u*u)},x.prototype.setPosition=function(t,e){this.x=parseInt(t),this.y=parseInt(e)},x.prototype.setText=function(t){this.frame.innerHTML=t},x.prototype.show=function(t){if(void 0===t&&(t=!0),t){var e=this.frame.clientHeight,i=this.frame.clientWidth,n=this.frame.parentNode.clientHeight,s=this.frame.parentNode.clientWidth,o=this.y-e;o+e+this.padding>n&&(o=n-e-this.padding),this.padding>o&&(o=this.padding);var r=this.x;r+i+this.padding>s&&(r=s-i-this.padding),this.padding>r&&(r=this.padding),this.frame.style.left=r+"px",this.frame.style.top=o+"px",this.frame.style.visibility="visible"}else this.hide()},x.prototype.hide=function(){this.frame.style.visibility="hidden"},Groups=function(){this.clear(),this.defaultIndex=0},Groups.DEFAULT=[{border:"#2B7CE9",background:"#97C2FC",highlight:{border:"#2B7CE9",background:"#D2E5FF"}},{border:"#FFA500",background:"#FFFF00",highlight:{border:"#FFA500",background:"#FFFFA3"}},{border:"#FA0A10",background:"#FB7E81",highlight:{border:"#FA0A10",background:"#FFAFB1"}},{border:"#41A906",background:"#7BE141",highlight:{border:"#41A906",background:"#A1EC76"}},{border:"#E129F0",background:"#EB7DF4",highlight:{border:"#E129F0",background:"#F0B3F5"}},{border:"#7C29F0",background:"#AD85E4",highlight:{border:"#7C29F0",background:"#D3BDF0"}},{border:"#C37F00",background:"#FFA807",highlight:{border:"#C37F00",background:"#FFCA66"}},{border:"#4220FB",background:"#6E6EFD",highlight:{border:"#4220FB",background:"#9B9BFD"}},{border:"#FD5A77",background:"#FFC0CB",highlight:{border:"#FD5A77",background:"#FFD1D9"}},{border:"#4AD63A",background:"#C2FABC",highlight:{border:"#4AD63A",background:"#E6FFE3"}}],Groups.prototype.clear=function(){this.groups={},this.groups.length=function(){var t=0;for(var e in this)this.hasOwnProperty(e)&&t++;return t}},Groups.prototype.get=function(t){var e=this.groups[t];if(void 0==e){var i=this.defaultIndex%Groups.DEFAULT.length;this.defaultIndex++,e={},e.color=Groups.DEFAULT[i],this.groups[t]=e}return e},Groups.prototype.add=function(t,e){return this.groups[t]=e,e.color&&(e.color=E.parseColor(e.color)),e},Images=function(){this.images={},this.callback=void 0},Images.prototype.setOnloadCallback=function(t){this.callback=t},Images.prototype.load=function(t){var e=this.images[t];if(void 0==e){var i=this;e=new Image,this.images[t]=e,e.onload=function(){i.callback&&i.callback(this)},e.src=t}return e},S.prototype.setData=function(t){if(t&&t.dot&&(t.nodes||t.edges))throw new SyntaxError('Data must contain either parameter "dot" or parameter pair "nodes" and "edges", but not both.');if(this.setOptions(t&&t.options),t&&t.dot){if(t&&t.dot){var e=k.util.DOTToGraph(t.dot);return this.setData(e),void 0}}else this._setNodes(t&&t.nodes),this._setEdges(t&&t.edges);this.stabilize&&this._doStabilize(),this.start()},S.prototype.setOptions=function(t){if(t){if(void 0!=t.width&&(this.width=t.width),void 0!=t.height&&(this.height=t.height),void 0!=t.stabilize&&(this.stabilize=t.stabilize),void 0!=t.selectable&&(this.selectable=t.selectable),t.edges){for(var e in t.edges)t.edges.hasOwnProperty(e)&&(this.constants.edges[e]=t.edges[e]);void 0!=t.edges.length&&t.nodes&&void 0==t.nodes.distance&&(this.constants.edges.length=t.edges.length,this.constants.nodes.distance=1.25*t.edges.length),t.edges.fontColor||(this.constants.edges.fontColor=t.edges.color),t.edges.dash&&(void 0!=t.edges.dash.length&&(this.constants.edges.dash.length=t.edges.dash.length),void 0!=t.edges.dash.gap&&(this.constants.edges.dash.gap=t.edges.dash.gap),void 0!=t.edges.dash.altLength&&(this.constants.edges.dash.altLength=t.edges.dash.altLength))}if(t.nodes){for(e in t.nodes)t.nodes.hasOwnProperty(e)&&(this.constants.nodes[e]=t.nodes[e]);t.nodes.color&&(this.constants.nodes.color=E.parseColor(t.nodes.color))}if(t.groups)for(var i in t.groups)if(t.groups.hasOwnProperty(i)){var n=t.groups[i];this.groups.add(i,n)}}this.setSize(this.width,this.height),this._setTranslation(this.frame.clientWidth/2,this.frame.clientHeight/2),this._setScale(1)},S.prototype._trigger=function(t,e){L.trigger(this,t,e)},S.prototype._create=function(){for(;this.containerElement.hasChildNodes();)this.containerElement.removeChild(this.containerElement.firstChild);if(this.frame=document.createElement("div"),this.frame.className="graph-frame",this.frame.style.position="relative",this.frame.style.overflow="hidden",this.frame.canvas=document.createElement("canvas"),this.frame.canvas.style.position="relative",this.frame.appendChild(this.frame.canvas),!this.frame.canvas.getContext){var t=document.createElement("DIV");t.style.color="red",t.style.fontWeight="bold",t.style.padding="10px",t.innerHTML="Error: your browser does not support HTML canvas",this.frame.canvas.appendChild(t)}var e=this;this.drag={},this.pinch={},this.hammer=D(this.frame.canvas,{prevent_default:!0}),this.hammer.on("tap",e._onTap.bind(e)),this.hammer.on("hold",e._onHold.bind(e)),this.hammer.on("pinch",e._onPinch.bind(e)),this.hammer.on("touch",e._onTouch.bind(e)),this.hammer.on("dragstart",e._onDragStart.bind(e)),this.hammer.on("drag",e._onDrag.bind(e)),this.hammer.on("dragend",e._onDragEnd.bind(e)),this.hammer.on("mousewheel",e._onMouseWheel.bind(e)),this.hammer.on("mousemove",e._onMouseMoveTitle.bind(e)),this.containerElement.appendChild(this.frame)},S.prototype._getNodeAt=function(t){var e=this._canvasToX(t.x),i=this._canvasToY(t.y),n={left:e,top:i,right:e,bottom:i},s=this._getNodesOverlappingWith(n);return s.length>0?s[s.length-1]:null},S.prototype._getPointer=function(t){return{x:t.pageX-k.util.getAbsoluteLeft(this.frame.canvas),y:t.pageY-k.util.getAbsoluteTop(this.frame.canvas)}},S.prototype._onTouch=function(t){this.drag.pointer=this._getPointer(t.gesture.touches[0]),this.drag.pinched=!1,this.pinch.scale=this._getScale()},S.prototype._onDragStart=function(){var t=this.drag;t.selection=[],t.translation=this._getTranslation(),t.nodeId=this._getNodeAt(t.pointer);var e=this.nodes[t.nodeId];if(e){e.isSelected()||this._selectNodes([t.nodeId]);var i=this;this.selection.forEach(function(e){var n=i.nodes[e];if(n){var s={id:e,node:n,x:n.x,y:n.y,xFixed:n.xFixed,yFixed:n.yFixed};n.xFixed=!0,n.yFixed=!0,t.selection.push(s)}})}},S.prototype._onDrag=function(t){if(!this.drag.pinched){var e=this._getPointer(t.gesture.touches[0]),i=this,n=this.drag,s=n.selection;if(s&&s.length){var o=e.x-n.pointer.x,r=e.y-n.pointer.y;s.forEach(function(t){var e=t.node;t.xFixed||(e.x=i._canvasToX(i._xToCanvas(t.x)+o)),t.yFixed||(e.y=i._canvasToY(i._yToCanvas(t.y)+r))}),this.moving||(this.moving=!0,this.start())}else{var a=e.x-this.drag.pointer.x,h=e.y-this.drag.pointer.y;this._setTranslation(this.drag.translation.x+a,this.drag.translation.y+h),this._redraw(),this.moved=!0}}},S.prototype._onDragEnd=function(){var t=this.drag.selection;t&&t.forEach(function(t){t.node.xFixed=t.xFixed,t.node.yFixed=t.yFixed})},S.prototype._onTap=function(t){var e=this._getPointer(t.gesture.touches[0]),i=this._getNodeAt(e),n=this.nodes[i];n?(this._selectNodes([i]),this.moving||this._redraw()):(this._unselectNodes(),this._redraw())},S.prototype._onHold=function(t){var e=this._getPointer(t.gesture.touches[0]),i=this._getNodeAt(e),n=this.nodes[i];if(n){if(n.isSelected())this._unselectNodes([i]);else{var s=!0;this._selectNodes([i],s)}this.moving||this._redraw()}},S.prototype._onPinch=function(t){var e=this._getPointer(t.gesture.center);this.drag.pinched=!0,"scale"in this.pinch||(this.pinch.scale=1);var i=this.pinch.scale*t.gesture.scale;this._zoom(i,e)},S.prototype._zoom=function(t,e){var i=this._getScale();.01>t&&(t=.01),t>10&&(t=10);var n=this._getTranslation(),s=t/i,o=(1-s)*e.x+n.x*s,r=(1-s)*e.y+n.y*s;return this._setScale(t),this._setTranslation(o,r),this._redraw(),t},S.prototype._onMouseWheel=function(t){var e=0;if(t.wheelDelta?e=t.wheelDelta/120:t.detail&&(e=-t.detail/3),e){"mouswheelScale"in this.pinch||(this.pinch.mouswheelScale=1);var i=this.pinch.mouswheelScale,n=e/10;0>e&&(n/=1-n),i*=1+n;var s=D.event.collectEventData(this,"scroll",t),o=this._getPointer(s.center);i=this._zoom(i,o),this.pinch.mouswheelScale=i}t.preventDefault()},S.prototype._onMouseMoveTitle=function(t){var e=D.event.collectEventData(this,"mousemove",t),i=this._getPointer(e.center);this.popupNode&&this._checkHidePopup(i);var n=this,s=function(){n._checkShowPopup(i)};this.popupTimer&&clearInterval(this.popupTimer),this.leftButtonDown||(this.popupTimer=setTimeout(s,300))},S.prototype._checkShowPopup=function(t){var e,i={left:this._canvasToX(t.x),top:this._canvasToY(t.y),right:this._canvasToX(t.x),bottom:this._canvasToY(t.y)},n=this.popupNode;if(void 0==this.popupNode){var s=this.nodes;for(e in s)if(s.hasOwnProperty(e)){var o=s[e];if(void 0!=o.getTitle()&&o.isOverlappingWith(i)){this.popupNode=o;break}}}if(void 0==this.popupNode){var r=this.edges;for(e in r)if(r.hasOwnProperty(e)){var a=r[e];if(a.connected&&void 0!=a.getTitle()&&a.isOverlappingWith(i)){this.popupNode=a;break}}}if(this.popupNode){if(this.popupNode!=n){var h=this;h.popup||(h.popup=new x(h.frame)),h.popup.setPosition(t.x-3,t.y-3),h.popup.setText(h.popupNode.getTitle()),h.popup.show()}}else this.popup&&this.popup.hide()},S.prototype._checkHidePopup=function(t){this.popupNode&&this._getNodeAt(t)||(this.popupNode=void 0,this.popup&&this.popup.hide())},S.prototype._unselectNodes=function(t,e){var i,n,s,o=!1;if(t)for(i=0,n=t.length;n>i;i++){s=t[i],this.nodes[s].unselect();for(var r=0;this.selection.length>r;)this.selection[r]==s?(this.selection.splice(r,1),o=!0):r++}else if(this.selection&&this.selection.length){for(i=0,n=this.selection.length;n>i;i++)s=this.selection[i],this.nodes[s].unselect(),o=!0;this.selection=[]}return!o||1!=e&&void 0!=e||this._trigger("select"),o},S.prototype._selectNodes=function(t,e){var i,n,s=!1,o=!0;if(t.length!=this.selection.length)o=!1;else for(i=0,n=Math.min(t.length,this.selection.length);n>i;i++)if(t[i]!=this.selection[i]){o=!1;break}if(o)return s;if(void 0==e||0==e){var r=!1;s=this._unselectNodes(void 0,r)}for(i=0,n=t.length;n>i;i++){var a=t[i],h=-1!=this.selection.indexOf(a);h||(this.nodes[a].select(),this.selection.push(a),s=!0)}return s&&this._trigger("select"),s},S.prototype._getNodesOverlappingWith=function(t){var e=this.nodes,i=[];for(var n in e)e.hasOwnProperty(n)&&e[n].isOverlappingWith(t)&&i.push(n);return i},S.prototype.getSelection=function(){return this.selection.concat([])},S.prototype.setSelection=function(t){var e,i,n;if(!t||void 0==t.length)throw"Selection must be an array with ids";for(e=0,i=this.selection.length;i>e;e++)n=this.selection[e],this.nodes[n].unselect();for(this.selection=[],e=0,i=t.length;i>e;e++){n=t[e];var s=this.nodes[n];if(!s)throw new RangeError('Node with id "'+n+'" not found');s.select(),this.selection.push(n)}this.redraw()},S.prototype._updateSelection=function(){for(var t=0;this.selection.length>t;){var e=this.selection[t];this.nodes[e]?t++:this.selection.splice(t,1)}},S.prototype._getConnectionCount=function(t){function e(t){for(var e=[],i=0,n=t.length;n>i;i++)for(var s=t[i],o=s.edges,r=0,a=o.length;a>r;r++){var h=o[r],d=null;h.from==s?d=h.to:h.to==s&&(d=h.from);var l,p;if(d)for(l=0,p=t.length;p>l;l++)if(t[l]==d){d=null;break}if(d)for(l=0,p=e.length;p>l;l++)if(e[l]==d){d=null;break}d&&e.push(d)}return e}void 0==t&&(t=1);var i=[],n=this.nodes;for(var s in n)if(n.hasOwnProperty(s)){for(var o=[n[s]],r=0;t>r;r++)o=o.concat(e(o));i.push(o)}for(var a=[],h=0,d=i.length;d>h;h++)a.push(i[h].length);return a},S.prototype.setSize=function(t,e){this.frame.style.width=t,this.frame.style.height=e,this.frame.canvas.style.width="100%",this.frame.canvas.style.height="100%",this.frame.canvas.width=this.frame.canvas.clientWidth,this.frame.canvas.height=this.frame.canvas.clientHeight},S.prototype._setNodes=function(t){var e=this.nodesData;if(t instanceof o||t instanceof r)this.nodesData=t;else if(t instanceof Array)this.nodesData=new o,this.nodesData.add(t);else{if(t)throw new TypeError("Array or DataSet expected");this.nodesData=new o}if(e&&O.forEach(this.nodesListeners,function(t,i){e.unsubscribe(i,t)}),this.nodes={},this.nodesData){var i=this;O.forEach(this.nodesListeners,function(t,e){i.nodesData.subscribe(e,t)});var n=this.nodesData.getIds();this._addNodes(n)}this._updateSelection()},S.prototype._addNodes=function(t){for(var e,i=0,n=t.length;n>i;i++){e=t[i];var s=this.nodesData.get(e),o=new E(s,this.images,this.groups,this.constants);if(this.nodes[e]=o,!o.isFixed()){var r=2*this.constants.edges.length,a=t.length,h=2*Math.PI*(i/a);o.x=r*Math.cos(h),o.y=r*Math.sin(h),this.moving=!0}}this._reconnectEdges(),this._updateValueRange(this.nodes)},S.prototype._updateNodes=function(t){for(var e=this.nodes,i=this.nodesData,n=0,s=t.length;s>n;n++){var o=t[n],r=e[o],a=i.get(o);r?r.setProperties(a,this.constants):(r=new E(properties,this.images,this.groups,this.constants),e[o]=r,r.isFixed()||(this.moving=!0))}this._reconnectEdges(),this._updateValueRange(e)},S.prototype._removeNodes=function(t){for(var e=this.nodes,i=0,n=t.length;n>i;i++){var s=t[i];delete e[s]}this._reconnectEdges(),this._updateSelection(),this._updateValueRange(e)},S.prototype._setEdges=function(t){var e=this.edgesData;if(t instanceof o||t instanceof r)this.edgesData=t;else if(t instanceof Array)this.edgesData=new o,this.edgesData.add(t);else{if(t)throw new TypeError("Array or DataSet expected");this.edgesData=new o}if(e&&O.forEach(this.edgesListeners,function(t,i){e.unsubscribe(i,t)}),this.edges={},this.edgesData){var i=this;O.forEach(this.edgesListeners,function(t,e){i.edgesData.subscribe(e,t)});var n=this.edgesData.getIds();this._addEdges(n)}this._reconnectEdges()},S.prototype._addEdges=function(t){for(var e=this.edges,i=this.edgesData,n=0,s=t.length;s>n;n++){var o=t[n],r=e[o];r&&r.disconnect();var a=i.get(o);e[o]=new T(a,this,this.constants)}this.moving=!0,this._updateValueRange(e)},S.prototype._updateEdges=function(t){for(var e=this.edges,i=this.edgesData,n=0,s=t.length;s>n;n++){var o=t[n],r=i.get(o),a=e[o];a?(a.disconnect(),a.setProperties(r,this.constants),a.connect()):(a=new T(r,this,this.constants),this.edges[o]=a)}this.moving=!0,this._updateValueRange(e)},S.prototype._removeEdges=function(t){for(var e=this.edges,i=0,n=t.length;n>i;i++){var s=t[i],o=e[s];o&&(o.disconnect(),delete e[s])}this.moving=!0,this._updateValueRange(e)},S.prototype._reconnectEdges=function(){var t,e=this.nodes,i=this.edges;for(t in e)e.hasOwnProperty(t)&&(e[t].edges=[]);for(t in i)if(i.hasOwnProperty(t)){var n=i[t];n.from=null,n.to=null,n.connect()}},S.prototype._updateValueRange=function(t){var e,i=void 0,n=void 0;for(e in t)if(t.hasOwnProperty(e)){var s=t[e].getValue();void 0!==s&&(i=void 0===i?s:Math.min(s,i),n=void 0===n?s:Math.max(s,n))}if(void 0!==i&&void 0!==n)for(e in t)t.hasOwnProperty(e)&&t[e].setValueRange(i,n)},S.prototype.redraw=function(){this.setSize(this.width,this.height),this._redraw()},S.prototype._redraw=function(){var t=this.frame.canvas.getContext("2d"),e=this.frame.canvas.width,i=this.frame.canvas.height;t.clearRect(0,0,e,i),t.save(),t.translate(this.translation.x,this.translation.y),t.scale(this.scale,this.scale),this._drawEdges(t),this._drawNodes(t),t.restore()},S.prototype._setTranslation=function(t,e){void 0===this.translation&&(this.translation={x:0,y:0}),void 0!==t&&(this.translation.x=t),void 0!==e&&(this.translation.y=e)},S.prototype._getTranslation=function(){return{x:this.translation.x,y:this.translation.y}},S.prototype._setScale=function(t){this.scale=t},S.prototype._getScale=function(){return this.scale},S.prototype._canvasToX=function(t){return(t-this.translation.x)/this.scale},S.prototype._xToCanvas=function(t){return t*this.scale+this.translation.x},S.prototype._canvasToY=function(t){return(t-this.translation.y)/this.scale},S.prototype._yToCanvas=function(t){return t*this.scale+this.translation.y},S.prototype._drawNodes=function(t){var e=this.nodes,i=[];for(var n in e)e.hasOwnProperty(n)&&(e[n].isSelected()?i.push(n):e[n].draw(t));for(var s=0,o=i.length;o>s;s++)e[i[s]].draw(t)},S.prototype._drawEdges=function(t){var e=this.edges;for(var i in e)if(e.hasOwnProperty(i)){var n=e[i];n.connected&&e[i].draw(t)}},S.prototype._doStabilize=function(){new Date;for(var t=0,e=this.constants.minVelocity,i=!1;!i&&this.constants.maxIterations>t;)this._calculateForces(),this._discreteStepNodes(),i=!this._isMoving(e),t++;new Date},S.prototype._calculateForces=function(){var t,e,i,n,s,o,r,a,h,d,l,p=this.nodes,c=this.edges,u=.01,f=this.frame.canvas.clientWidth/2,m=this.frame.canvas.clientHeight/2;for(t in p)if(p.hasOwnProperty(t)){var g=p[t];e=f-g.x,i=m-g.y,n=Math.atan2(i,e),o=Math.cos(n)*u,r=Math.sin(n)*u,g._setForce(o,r)}var v=this.constants.nodes.distance,y=10;for(var b in p)if(p.hasOwnProperty(b)){var w=p[b];for(var _ in p)if(p.hasOwnProperty(_)){var E=p[_];e=E.x-w.x,i=E.y-w.y,s=Math.sqrt(e*e+i*i),n=Math.atan2(i,e),a=1/(1+Math.exp((s/v-1)*y)),o=Math.cos(n)*a,r=Math.sin(n)*a,w._addForce(-o,-r),E._addForce(o,r)}}for(t in c)if(c.hasOwnProperty(t)){var T=c[t];T.connected&&(e=T.to.x-T.from.x,i=T.to.y-T.from.y,l=T.length,d=Math.sqrt(e*e+i*i),n=Math.atan2(i,e),h=T.stiffness*(l-d),o=Math.cos(n)*h,r=Math.sin(n)*h,T.from._addForce(-o,-r),T.to._addForce(o,r))}},S.prototype._isMoving=function(t){var e=this.nodes;for(var i in e)if(e.hasOwnProperty(i)&&e[i].isMoving(t))return!0;return!1},S.prototype._discreteStepNodes=function(){var t=this.refreshRate/1e3,e=this.nodes;for(var i in e)e.hasOwnProperty(i)&&e[i].discreteStep(t)},S.prototype.start=function(){if(this.moving){this._calculateForces(),this._discreteStepNodes();var t=this.constants.minVelocity;this.moving=this._isMoving(t)}if(this.moving){if(!this.timer){var e=this;this.timer=window.setTimeout(function(){e.timer=void 0,e.start(),e._redraw()},this.refreshRate)}}else this._redraw()},S.prototype.stop=function(){this.timer&&(window.clearInterval(this.timer),this.timer=void 0)};var k={util:O,events:L,Controller:d,DataSet:o,DataView:r,Range:h,Stack:a,TimeStep:TimeStep,EventBus:s,components:{items:{Item:m,ItemBox:g,ItemPoint:v,ItemRange:y},Component:l,Panel:p,RootPanel:c,ItemSet:f,TimeAxis:u},graph:{Node:E,Edge:T,Popup:x,Groups:Groups,Images:Images},Timeline:_,Graph:S};n!==void 0&&(n=k),i!==void 0&&i.exports!==void 0&&(i.exports=k),"function"==typeof t&&t(function(){return k}),"undefined"!=typeof window&&(window.vis=k),O.loadCss("/* vis.js stylesheet */\n.vis.timeline {\n}\n\n\n.vis.timeline.rootpanel {\n position: relative;\n overflow: hidden;\n\n border: 1px solid #bfbfbf;\n -moz-box-sizing: border-box;\n box-sizing: border-box;\n}\n\n.vis.timeline .panel {\n position: absolute;\n overflow: hidden;\n}\n\n\n.vis.timeline .groupset {\n position: absolute;\n padding: 0;\n margin: 0;\n}\n\n.vis.timeline .labels {\n position: absolute;\n top: 0;\n left: 0;\n width: 100%;\n height: 100%;\n\n padding: 0;\n margin: 0;\n\n border-right: 1px solid #bfbfbf;\n box-sizing: border-box;\n -moz-box-sizing: border-box;\n}\n\n.vis.timeline .labels .label {\n position: absolute;\n left: 0;\n top: 0;\n width: 100%;\n border-bottom: 1px solid #bfbfbf;\n color: #4d4d4d;\n}\n\n.vis.timeline .labels .label .inner {\n display: inline-block;\n padding: 5px;\n}\n\n\n.vis.timeline .itemset {\n position: absolute;\n padding: 0;\n margin: 0;\n overflow: hidden;\n}\n\n.vis.timeline .background {\n}\n\n.vis.timeline .foreground {\n}\n\n.vis.timeline .itemset-axis {\n position: absolute;\n}\n\n.vis.timeline .groupset .itemset-axis {\n border-top: 1px solid #bfbfbf;\n}\n\n/* TODO: with orientation=='bottom', this will more or less overlap with timeline axis\n.vis.timeline .groupset .itemset-axis:last-child {\n border-top: none;\n}\n*/\n\n\n.vis.timeline .item {\n position: absolute;\n color: #1A1A1A;\n border-color: #97B0F8;\n background-color: #D5DDF6;\n display: inline-block;\n}\n\n.vis.timeline .item.selected {\n border-color: #FFC200;\n background-color: #FFF785;\n z-index: 999;\n}\n\n.vis.timeline .item.cluster {\n /* TODO: use another color or pattern? */\n background: #97B0F8 url('img/cluster_bg.png');\n color: white;\n}\n.vis.timeline .item.cluster.point {\n border-color: #D5DDF6;\n}\n\n.vis.timeline .item.box {\n text-align: center;\n border-style: solid;\n border-width: 1px;\n border-radius: 5px;\n -moz-border-radius: 5px; /* For Firefox 3.6 and older */\n}\n\n.vis.timeline .item.point {\n background: none;\n}\n\n.vis.timeline .dot {\n border: 5px solid #97B0F8;\n position: absolute;\n border-radius: 5px;\n -moz-border-radius: 5px; /* For Firefox 3.6 and older */\n}\n\n.vis.timeline .item.range {\n overflow: hidden;\n border-style: solid;\n border-width: 1px;\n border-radius: 2px;\n -moz-border-radius: 2px; /* For Firefox 3.6 and older */\n}\n\n.vis.timeline .item.range .drag-left {\n cursor: w-resize;\n z-index: 1000;\n}\n\n.vis.timeline .item.range .drag-right {\n cursor: e-resize;\n z-index: 1000;\n}\n\n.vis.timeline .item.range .content {\n position: relative;\n display: inline-block;\n}\n\n.vis.timeline .item.line {\n position: absolute;\n width: 0;\n border-left-width: 1px;\n border-left-style: solid;\n}\n\n.vis.timeline .item .content {\n margin: 5px;\n white-space: nowrap;\n overflow: hidden;\n}\n\n.vis.timeline .axis {\n position: relative;\n}\n\n.vis.timeline .axis .text {\n position: absolute;\n color: #4d4d4d;\n padding: 3px;\n white-space: nowrap;\n}\n\n.vis.timeline .axis .text.measure {\n position: absolute;\n padding-left: 0;\n padding-right: 0;\n margin-left: 0;\n margin-right: 0;\n visibility: hidden;\n}\n\n.vis.timeline .axis .grid.vertical {\n position: absolute;\n width: 0;\n border-right: 1px solid;\n}\n\n.vis.timeline .axis .grid.horizontal {\n position: absolute;\n left: 0;\n width: 100%;\n height: 0;\n border-bottom: 1px solid;\n}\n\n.vis.timeline .axis .grid.minor {\n border-color: #e5e5e5;\n}\n\n.vis.timeline .axis .grid.major {\n border-color: #bfbfbf;\n}\n\n")},{hammerjs:1,moment:2}]},{},[3])(3)}); \ No newline at end of file From d9d4c3d18eb1a9343c652e0983eaaed0ac6cb0ba Mon Sep 17 00:00:00 2001 From: josdejong Date: Fri, 20 Sep 2013 12:12:19 +0200 Subject: [PATCH 09/18] Updated network example and overview image --- docs/img/vis_overview.odg | Bin 29653 -> 32645 bytes examples/graph/17_network_info.html | 51 +++++++++++++++------------- 2 files changed, 27 insertions(+), 24 deletions(-) diff --git a/docs/img/vis_overview.odg b/docs/img/vis_overview.odg index 0038f586beae1786d7b9fb6b05cbcaa46f91203e..7659955f2fb858c383c3b5b082a352ee45b32523 100644 GIT binary patch delta 16760 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 delta 13757 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 Date: Fri, 20 Sep 2013 12:15:26 +0200 Subject: [PATCH 10/18] Released version 0.2.0 --- HISTORY.md | 2 +- bower.json | 2 +- package.json | 2 +- vis.js | 4 ++-- vis.min.js | 4 ++-- 5 files changed, 7 insertions(+), 7 deletions(-) diff --git a/HISTORY.md b/HISTORY.md index 7f56b3f0..7d1ecb63 100644 --- a/HISTORY.md +++ b/HISTORY.md @@ -2,7 +2,7 @@ vis.js history http://visjs.org -## (not yet released), version 0.2.0 +## 2013-09-20, version 0.2.0 - Implemented full touch support for Graph. - Fixed initial empty range in the Timeline in case of a single item. diff --git a/bower.json b/bower.json index 113d2cce..cf70ad90 100644 --- a/bower.json +++ b/bower.json @@ -1,6 +1,6 @@ { "name": "vis", - "version": "0.2.0-SNAPSHOT", + "version": "0.2.0", "description": "A dynamic, browser-based visualization library.", "homepage": "http://visjs.org/", "repository": { diff --git a/package.json b/package.json index a9333fee..236c7073 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "vis", - "version": "0.2.0-SNAPSHOT", + "version": "0.2.0", "description": "A dynamic, browser-based visualization library.", "homepage": "http://visjs.org/", "repository": { diff --git a/vis.js b/vis.js index 0bfa98bb..eeb9980b 100644 --- a/vis.js +++ b/vis.js @@ -4,8 +4,8 @@ * * A dynamic, browser-based visualization library. * - * @version 0.2.0-SNAPSHOT - * @date 2013-09-17 + * @version 0.2.0 + * @date 2013-09-20 * * @license * Copyright (C) 2011-2013 Almende B.V, http://almende.com diff --git a/vis.min.js b/vis.min.js index 2b24b43d..3f3d76a8 100644 --- a/vis.min.js +++ b/vis.min.js @@ -4,8 +4,8 @@ * * A dynamic, browser-based visualization library. * - * @version 0.2.0-SNAPSHOT - * @date 2013-09-17 + * @version 0.2.0 + * @date 2013-09-20 * * @license * Copyright (C) 2011-2013 Almende B.V, http://almende.com From 5bafcadbf082c1d0fad8881179afdab5505f11f3 Mon Sep 17 00:00:00 2001 From: josdejong Date: Fri, 20 Sep 2013 12:24:56 +0200 Subject: [PATCH 11/18] Updated to version 0.3.0-SNAPSHOT --- bower.json | 2 +- package.json | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/bower.json b/bower.json index cf70ad90..29dec11a 100644 --- a/bower.json +++ b/bower.json @@ -1,6 +1,6 @@ { "name": "vis", - "version": "0.2.0", + "version": "0.3.0-SNAPSHOT", "description": "A dynamic, browser-based visualization library.", "homepage": "http://visjs.org/", "repository": { diff --git a/package.json b/package.json index 236c7073..61bfcefb 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "vis", - "version": "0.2.0", + "version": "0.3.0-SNAPSHOT", "description": "A dynamic, browser-based visualization library.", "homepage": "http://visjs.org/", "repository": { From 3be9da2a4b3e1ddcf2cc956c52b68b821490d300 Mon Sep 17 00:00:00 2001 From: josdejong Date: Fri, 20 Sep 2013 17:58:14 +0200 Subject: [PATCH 12/18] Fixed non-working scroll on FF --- src/graph/Graph.js | 1 + 1 file changed, 1 insertion(+) diff --git a/src/graph/Graph.js b/src/graph/Graph.js index 11cf53bb..7e26fc5c 100644 --- a/src/graph/Graph.js +++ b/src/graph/Graph.js @@ -304,6 +304,7 @@ Graph.prototype._create = function () { this.hammer.on('drag', me._onDrag.bind(me) ); this.hammer.on('dragend', me._onDragEnd.bind(me) ); this.hammer.on('mousewheel',me._onMouseWheel.bind(me) ); + this.hammer.on('DOMMouseScroll',me._onMouseWheel.bind(me) ); // for FF this.hammer.on('mousemove', me._onMouseMoveTitle.bind(me) ); // add the frame to the container element From 1b2292c1da9b640d64bc8b0e1d19d50509d290f9 Mon Sep 17 00:00:00 2001 From: josdejong Date: Fri, 20 Sep 2013 18:09:28 +0200 Subject: [PATCH 13/18] A fix calculating the size of a node when the range is empty --- src/graph/Node.js | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/src/graph/Node.js b/src/graph/Node.js index 36fb87bb..edb10a6c 100644 --- a/src/graph/Node.js +++ b/src/graph/Node.js @@ -397,8 +397,13 @@ Node.prototype.getDistance = function(x, y) { */ Node.prototype.setValueRange = function(min, max) { if (!this.radiusFixed && this.value !== undefined) { + if (max == min) { + this.radius = (this.radiusMin + this.radiusMax) / 2; + } + else { var scale = (this.radiusMax - this.radiusMin) / (max - min); this.radius = (this.value - min) * scale + this.radiusMin; + } } }; From 42cb37580496418117b747ab95e02764530916f9 Mon Sep 17 00:00:00 2001 From: Nelson Reis Date: Fri, 11 Oct 2013 18:13:22 +0100 Subject: [PATCH 14/18] Update references to moment.js in the examples --- examples/timeline/02_dataset.html | 2 +- examples/timeline/03_much_data.html | 2 +- examples/timeline/05_groups.html | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/examples/timeline/02_dataset.html b/examples/timeline/02_dataset.html index ad74d2d5..7871480d 100644 --- a/examples/timeline/02_dataset.html +++ b/examples/timeline/02_dataset.html @@ -20,7 +20,7 @@ - + diff --git a/examples/timeline/03_much_data.html b/examples/timeline/03_much_data.html index db94f807..c55ecfca 100644 --- a/examples/timeline/03_much_data.html +++ b/examples/timeline/03_much_data.html @@ -11,7 +11,7 @@ - + diff --git a/examples/timeline/05_groups.html b/examples/timeline/05_groups.html index 17b85200..81909619 100644 --- a/examples/timeline/05_groups.html +++ b/examples/timeline/05_groups.html @@ -17,7 +17,7 @@ - + From 2728e4ae3044036f3cd78a6dd17677d9b108e50c Mon Sep 17 00:00:00 2001 From: Eric Gillingham Date: Wed, 16 Oct 2013 14:44:14 -0700 Subject: [PATCH 15/18] Fix dataSet parsing of Moment objects Calling just moment.clone() won't do anything but error. Since moment.isMoment(object) guarantees object is already a moment instance, just calling moment(object) will clone it per the moment docs http://momentjs.com/docs/#/parsing/moment-clone/ --- src/util.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/util.js b/src/util.js index 70c907a4..95dcafbc 100644 --- a/src/util.js +++ b/src/util.js @@ -171,7 +171,7 @@ util.convert = function convert(object, type) { return moment(object.valueOf()); } else if (moment.isMoment(object)) { - return moment.clone(); + return moment(object); } if (util.isString(object)) { match = ASPDateRegex.exec(object); From 38653ed5eb3265bee54319fa6c9679ef686e00c6 Mon Sep 17 00:00:00 2001 From: josdejong Date: Mon, 21 Oct 2013 14:58:17 +0200 Subject: [PATCH 16/18] Fixed links in examples to moment.js (see #13) --- examples/timeline/02_dataset.html | 2 +- examples/timeline/03_much_data.html | 2 +- examples/timeline/05_groups.html | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/examples/timeline/02_dataset.html b/examples/timeline/02_dataset.html index 7871480d..36575945 100644 --- a/examples/timeline/02_dataset.html +++ b/examples/timeline/02_dataset.html @@ -20,7 +20,7 @@ - + diff --git a/examples/timeline/03_much_data.html b/examples/timeline/03_much_data.html index c55ecfca..45c4f40e 100644 --- a/examples/timeline/03_much_data.html +++ b/examples/timeline/03_much_data.html @@ -11,7 +11,7 @@ - + diff --git a/examples/timeline/05_groups.html b/examples/timeline/05_groups.html index 81909619..d6c9ced4 100644 --- a/examples/timeline/05_groups.html +++ b/examples/timeline/05_groups.html @@ -17,7 +17,7 @@ - + From a2498f0f6ccadf4d327859fa3726d87ed010002d Mon Sep 17 00:00:00 2001 From: Fedor Tirsel Date: Thu, 24 Oct 2013 16:22:49 +0200 Subject: [PATCH 17/18] Current time bar as a component --- Jakefile.js | 4 +- src/timeline/Timeline.js | 5 + src/timeline/component/CurrentTime.js | 101 +++++++++++++++++++++ src/timeline/component/css/currenttime.css | 5 + 4 files changed, 114 insertions(+), 1 deletion(-) create mode 100644 src/timeline/component/CurrentTime.js create mode 100644 src/timeline/component/css/currenttime.css diff --git a/Jakefile.js b/Jakefile.js index b54781e3..42857a70 100644 --- a/Jakefile.js +++ b/Jakefile.js @@ -34,7 +34,8 @@ task('build', {async: true}, function () { './src/timeline/component/css/groupset.css', './src/timeline/component/css/itemset.css', './src/timeline/component/css/item.css', - './src/timeline/component/css/timeaxis.css' + './src/timeline/component/css/timeaxis.css', + './src/timeline/component/css/currenttime.css' ], header: '/* vis.js stylesheet */', separator: '\n' @@ -62,6 +63,7 @@ task('build', {async: true}, function () { './src/timeline/component/Panel.js', './src/timeline/component/RootPanel.js', './src/timeline/component/TimeAxis.js', + './src/timeline/component/CurrentTime.js', './src/timeline/component/ItemSet.js', './src/timeline/component/item/*.js', './src/timeline/component/Group.js', diff --git a/src/timeline/Timeline.js b/src/timeline/Timeline.js index 10ea6add..27c62282 100644 --- a/src/timeline/Timeline.js +++ b/src/timeline/Timeline.js @@ -17,6 +17,7 @@ function Timeline (container, items, options) { // zoomable: true, // TODO: option zoomable showMinorLabels: true, showMajorLabels: true, + showCurrentTime: false, autoResize: false }, options); @@ -109,6 +110,10 @@ function Timeline (container, items, options) { this.timeaxis.setRange(this.range); this.controller.add(this.timeaxis); + // current time bar + this.currenttime = new CurrentTime(this.timeaxis, [], rootOptions); + this.controller.add(this.currenttime); + // create itemset or groupset this.setGroups(null); diff --git a/src/timeline/component/CurrentTime.js b/src/timeline/component/CurrentTime.js new file mode 100644 index 00000000..d4a792fb --- /dev/null +++ b/src/timeline/component/CurrentTime.js @@ -0,0 +1,101 @@ +/** + * A current time bar + * @param {Component} parent + * @param {Component[]} [depends] Components on which this components depends + * (except for the parent) + * @param {Object} [options] Available parameters: + * {Boolean} [showCurrentTime] + * @constructor CurrentTime + * @extends Component + */ + +function CurrentTime (parent, depends, options) { + this.id = util.randomUUID(); + this.parent = parent; + this.depends = depends; + + this.options = options || {}; + this.defaultOptions = { + showCurrentTime: false + }; +} + +CurrentTime.prototype = new Component(); + +CurrentTime.prototype.setOptions = Component.prototype.setOptions; + +/** + * Get the container element of the bar, which can be used by a child to + * add its own widgets. + * @returns {HTMLElement} container + */ +CurrentTime.prototype.getContainer = function () { + return this.frame; +}; + +/** + * Repaint the component + * @return {Boolean} changed + */ +CurrentTime.prototype.repaint = function () { + var bar = this.frame, + parent = this.parent, + parentContainer = parent.parent.getContainer(); + + if (!parent) { + throw new Error('Cannot repaint bar: no parent attached'); + } + + if (!parentContainer) { + throw new Error('Cannot repaint bar: parent has no container element'); + } + + if (!this.getOption('showCurrentTime')) { + if (bar) { + parentContainer.removeChild(bar); + delete this.frame; + } + + return; + } + + if (!bar) { + bar = document.createElement('div'); + bar.className = 'currenttime'; + bar.style.position = 'absolute'; + bar.style.top = '0px'; + bar.style.height = '100%'; + + parentContainer.appendChild(bar); + this.frame = bar; + } + + if (!parent.conversion) { + parent._updateConversion(); + } + + var now = new Date(); + var x = parent.toScreen(now); + + bar.style.left = x + 'px'; + bar.title = 'Current time: ' + now; + + // start a timer to adjust for the new time + if (this.currentTimeTimer !== undefined) { + clearTimeout(this.currentTimeTimer); + delete this.currentTimeTimer; + } + + var timeline = this; + var interval = 1 / parent.conversion.factor / 2; + + if (interval < 30) { + interval = 30; + } + + this.currentTimeTimer = setTimeout(function() { + timeline.repaint(); + }, interval); + + return false; +}; diff --git a/src/timeline/component/css/currenttime.css b/src/timeline/component/css/currenttime.css new file mode 100644 index 00000000..5ea0380b --- /dev/null +++ b/src/timeline/component/css/currenttime.css @@ -0,0 +1,5 @@ +.vis.timeline .currenttime { + background-color: #FF7F6E; + width: 2px; + z-index: 9; +} \ No newline at end of file From f73d8628115477434caae5747b01807f3fc9e9c6 Mon Sep 17 00:00:00 2001 From: josdejong Date: Fri, 25 Oct 2013 13:12:19 +0200 Subject: [PATCH 18/18] Added docs for option `showCurrentTime` --- HISTORY.md | 5 +++++ docs/timeline.html | 7 +++++++ examples/timeline/02_dataset.html | 3 ++- 3 files changed, 14 insertions(+), 1 deletion(-) diff --git a/HISTORY.md b/HISTORY.md index 7d1ecb63..0d6a30a2 100644 --- a/HISTORY.md +++ b/HISTORY.md @@ -1,6 +1,11 @@ vis.js history http://visjs.org +## , version 0.3.0 + +- Implemented option `showCurrentTime`, displaying a red, vertical bar at + current time. Thanks fi0dor. + ## 2013-09-20, version 0.2.0 diff --git a/docs/timeline.html b/docs/timeline.html index 4bdd9ee7..525a4baf 100644 --- a/docs/timeline.html +++ b/docs/timeline.html @@ -425,6 +425,13 @@ var options = { of item ranges. Must correspond with the css of item ranges. + + showCurrentTime + boolean + false + Show a vertical bar at the current time. + + showMajorLabels boolean diff --git a/examples/timeline/02_dataset.html b/examples/timeline/02_dataset.html index 36575945..5ce3ab8f 100644 --- a/examples/timeline/02_dataset.html +++ b/examples/timeline/02_dataset.html @@ -51,7 +51,8 @@ start: now.clone().add('days', -3), end: now.clone().add('days', 7), orientation: 'top', - height: '100%' + height: '100%', + showCurrentTime: true }; var timeline = new vis.Timeline(container, items, options);