diff --git a/Jakefile.js b/Jakefile.js
index 4a75e4e9..296c2d5f 100644
--- a/Jakefile.js
+++ b/Jakefile.js
@@ -2,16 +2,20 @@
* Jake build script
*/
var jake = require('jake'),
- fs = require('fs'),
+ browserify = require('browserify'),
path = require('path');
require('jake-utils');
+// constants
+var VIS = './vis.js';
+var VIS_MIN = './vis.min.js';
+
/**
* default task
*/
desc('Execute all tasks: build all libraries');
-task('default', ['vis'], function () {
+task('default', ['build', 'minify'], function () {
console.log('done');
});
@@ -19,10 +23,7 @@ task('default', ['vis'], function () {
* build the visualization library vis.js
*/
desc('Build the visualization library vis.js');
-task('vis', function () {
- var VIS = './vis.js';
- var VIS_MIN = './vis.min.js';
-
+task('build', {async: true}, function () {
// concatenate and stringify css files
var result = concat({
src: [
@@ -35,44 +36,36 @@ task('vis', function () {
});
var cssText = JSON.stringify(result.code);
- // concatenate the script files
- concat({
- dest: VIS,
- src: [
- './src/module.js',
-
- './src/util.js',
- './src/events.js',
- './src/timestep.js',
- './src/dataset.js',
- './src/stack.js',
- './src/range.js',
- './src/controller.js',
-
- './src/component/component.js',
- './src/component/panel.js',
- './src/component/rootpanel.js',
- './src/component/timeaxis.js',
- './src/component/itemset.js',
- './src/component/item/*.js',
-
- './src/visualization/timeline.js',
-
- // TODO: do not package moment.js with vis.js.
- './lib/moment.js'
- ],
-
- header: read('./src/header.js') + '\n' +
- '(function () { ', // start of closure
-
- separator: '\n',
-
- // Note: we insert the css as a string in the javascript code here
- // the css will be injected on load of the javascript library
- footer: 'loadCss(' + cssText + ');\n' +
- '})();' // end of closure
+ // bundle the script files
+ // TODO: do not package moment.js with vis.js.
+ var b = browserify();
+ b.add('./src/vis.js');
+ b.bundle({
+ standalone: 'vis'
+ }, function (err, code) {
+ // add header and footer
+ var lib =
+ read('./src/header.js') +
+ code +
+ read('./src/module.js') +
+ '\nloadCss(' + cssText + ');\n'; // inline css
+
+ // write bundled file
+ write(VIS, lib);
+ console.log('created ' + VIS);
+
+ // update version number and stuff in the javascript files
+ replacePlaceholders(VIS);
+
+ complete();
});
+});
+/**
+ * minify the visualization library vis.js
+ */
+desc('Minify the visualization library vis.js');
+task('minify', function () {
// minify javascript
minify({
src: VIS,
@@ -81,40 +74,22 @@ task('vis', function () {
});
// update version number and stuff in the javascript files
- [VIS, VIS_MIN].forEach(function (file) {
- replace({
- replacements: [
- {pattern: '@@name', replacement: 'vis.js'},
- {pattern: '@@date', replacement: today()},
- {pattern: '@@version', replacement: version()}
- ],
- src: file
- });
- });
+ replacePlaceholders(VIS_MIN);
- console.log('created vis.js library');
+ console.log('created ' + VIS_MIN);
});
/**
- * Recursively remove a directory and its files
- * https://gist.github.com/tkihira/2367067
- * @param {String} dir
+ * replace version, date, and name placeholders in the provided file
+ * @param {String} filename
*/
-var rmdir = function(dir) {
- var list = fs.readdirSync(dir);
- for(var i = 0; i < list.length; i++) {
- var filename = path.join(dir, list[i]);
- var stat = fs.statSync(filename);
-
- if(filename == "." || filename == "..") {
- // pass these files
- } else if(stat.isDirectory()) {
- // rmdir recursively
- rmdir(filename);
- } else {
- // rm fiilename
- fs.unlinkSync(filename);
- }
- }
- fs.rmdirSync(dir);
+var replacePlaceholders = function (filename) {
+ replace({
+ replacements: [
+ {pattern: '@@name', replacement: 'vis.js'},
+ {pattern: '@@date', replacement: today()},
+ {pattern: '@@version', replacement: version()}
+ ],
+ src: filename
+ });
};
diff --git a/README.md b/README.md
index 5c7e64d6..a8f20be4 100644
--- a/README.md
+++ b/README.md
@@ -111,18 +111,26 @@ To build the library from source, clone the project from github
git clone git://github.com/almende/vis.git
The project uses [jake](https://github.com/mde/jake) as build tool.
+The build script uses [Browserify](http://browserify.org/) to
+bundle the source code into a library,
+and uses [UglifyJS](http://lisperator.net/uglifyjs/) to minify the code.
+The source code uses the module style of node (require and module.exports) to
+organize dependencies.
+
+To install all dependencies and build the library, run `npm install` in the
+root of the project.
+
+ cd vis
+ npm install
+
To be able to run jake from the command line, jake must be installed globally:
sudo npm install -g jake
Then, the project can be build by executing jake in the root of the project:
- cd vis
jake
-This will build the library for each of the components. The built libraries can
-be found in the directory `bin`, and includes examples.
-
## License
diff --git a/package.json b/package.json
index 2b2d484a..68ffdf51 100644
--- a/package.json
+++ b/package.json
@@ -1,6 +1,6 @@
{
"name": "vis",
- "version": "0.0.5",
+ "version": "0.0.6",
"description": "A dynamic, browser-based visualization library.",
"homepage": "http://visjs.org/",
"repository": {
@@ -20,7 +20,12 @@
"network",
"browser"
],
- "dependencies": {},
+ "scripts": {
+ "prepublish": "jake"
+ },
+ "dependencies": {
+ "moment": "latest"
+ },
"devDependencies": {
"jake": ">= 0.5.9",
"jake-utils": ">= 0.0.18",
diff --git a/src/component/component.js b/src/component/component.js
index 97c351e7..85fd8412 100644
--- a/src/component/component.js
+++ b/src/component/component.js
@@ -1,3 +1,5 @@
+var util = require('./../util');
+
/**
* Prototype for visual components
*/
@@ -116,4 +118,4 @@ Component.prototype.on = function (event, callback) {
};
// exports
-vis.component.Component = Component;
+module.exports = exports = Component;
diff --git a/src/component/item/item.js b/src/component/item/item.js
index 52d4b5e3..c2697e54 100644
--- a/src/component/item/item.js
+++ b/src/component/item/item.js
@@ -1,3 +1,4 @@
+var Component = require('../component');
/**
* @constructor Item
@@ -33,4 +34,4 @@ Item.prototype.unselect = function () {
};
// exports
-vis.component.item.Item = Item;
+module.exports = exports = Item;
diff --git a/src/component/item/itembox.js b/src/component/item/itembox.js
index bc864cf7..960d9f91 100644
--- a/src/component/item/itembox.js
+++ b/src/component/item/itembox.js
@@ -1,3 +1,6 @@
+var util = require('../../util'),
+ Item = require('./item');
+
/**
* @constructor ItemBox
* @extends Item
@@ -272,4 +275,4 @@ ItemBox.prototype.reposition = function () {
};
// exports
-vis.component.item.box = ItemBox;
+module.exports = exports = ItemBox;
diff --git a/src/component/item/itempoint.js b/src/component/item/itempoint.js
index 01949263..1efccb93 100644
--- a/src/component/item/itempoint.js
+++ b/src/component/item/itempoint.js
@@ -1,3 +1,6 @@
+var util = require('../../util'),
+ Item = require('./item');
+
/**
* @constructor ItemPoint
* @extends Item
@@ -208,4 +211,4 @@ ItemPoint.prototype.reposition = function () {
};
// exports
-vis.component.item.point = ItemPoint;
+module.exports = exports = ItemPoint;
diff --git a/src/component/item/itemrange.js b/src/component/item/itemrange.js
index 250c88d8..56b1b4a6 100644
--- a/src/component/item/itemrange.js
+++ b/src/component/item/itemrange.js
@@ -1,3 +1,6 @@
+var util = require('../../util'),
+ Item = require('./item');
+
/**
* @constructor ItemRange
* @extends Item
@@ -217,4 +220,4 @@ ItemRange.prototype.reposition = function () {
};
// exports
-vis.component.item.range = ItemRange;
+module.exports = exports = ItemRange;
diff --git a/src/component/itemset.js b/src/component/itemset.js
index 0af784b0..5646b473 100644
--- a/src/component/itemset.js
+++ b/src/component/itemset.js
@@ -1,3 +1,11 @@
+var util = require('../util'),
+ DataSet = require('../dataset'),
+ Panel = require('./panel'),
+ Stack = require('../stack'),
+ ItemBox = require('./item/itembox'),
+ ItemRange = require('./item/itemrange'),
+ ItemPoint = require('./item/itempoint');
+
/**
* 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
@@ -54,6 +62,13 @@ function ItemSet(parent, depends, options) {
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:
@@ -189,7 +204,7 @@ ItemSet.prototype.repaint = function () {
var type = itemData.type ||
(itemData.start && itemData.end && 'range') ||
'box';
- var constructor = vis.component.item[type];
+ var constructor = ItemSet.types[type];
// TODO: how to handle items with invalid data? hide them and give a warning? or throw an error?
if (item) {
@@ -499,4 +514,4 @@ ItemSet.prototype.toScreen = function(time) {
};
// exports
-vis.component.ItemSet = ItemSet;
+module.exports = exports = ItemSet;
diff --git a/src/component/panel.js b/src/component/panel.js
index 838c3725..20ccda82 100644
--- a/src/component/panel.js
+++ b/src/component/panel.js
@@ -1,3 +1,6 @@
+var util = require('../util'),
+ Component = require('./component');
+
/**
* A panel can contain components
* @param {Component} [parent]
@@ -101,4 +104,4 @@ Panel.prototype.reflow = function () {
};
// exports
-vis.component.Panel = Panel;
+module.exports = exports = Panel;
diff --git a/src/component/rootpanel.js b/src/component/rootpanel.js
index 4b8239c1..7b107ea0 100644
--- a/src/component/rootpanel.js
+++ b/src/component/rootpanel.js
@@ -1,3 +1,6 @@
+var util = require('../util'),
+ Panel = require('./panel');
+
/**
* A root panel can hold components. The root panel must be initialized with
* a DOM element as container.
@@ -200,4 +203,4 @@ RootPanel.prototype._updateEventEmitters = function () {
};
// exports
-vis.component.RootPanel = RootPanel;
+module.exports = exports = RootPanel;
diff --git a/src/component/timeaxis.js b/src/component/timeaxis.js
index 94248f34..07c79466 100644
--- a/src/component/timeaxis.js
+++ b/src/component/timeaxis.js
@@ -1,3 +1,7 @@
+var util = require('../util'),
+ TimeStep = require('../timestep'),
+ Component = require('./component');
+
/**
* A horizontal time axis
* @param {Component} parent
@@ -524,4 +528,4 @@ TimeAxis.prototype._updateConversion = function() {
};
// exports
-vis.component.TimeAxis = TimeAxis;
+module.exports = exports = TimeAxis;
diff --git a/src/controller.js b/src/controller.js
index 24c3da9d..0735f36e 100644
--- a/src/controller.js
+++ b/src/controller.js
@@ -1,3 +1,6 @@
+var util = require('./util'),
+ Component = require('./component/component');
+
/**
* @constructor Controller
*
@@ -139,4 +142,5 @@ Controller.prototype.reflow = function () {
};
// exports
-vis.Controller = Controller;
+module.exports = exports = Controller;
+
diff --git a/src/dataset.js b/src/dataset.js
index 7298cc6b..083872a1 100644
--- a/src/dataset.js
+++ b/src/dataset.js
@@ -1,3 +1,5 @@
+var util = require('./util');
+
/**
* DataSet
*
@@ -547,4 +549,4 @@ DataSet.prototype._appendRow = function (dataTable, columns, item) {
};
// exports
-vis.DataSet = DataSet;
+module.exports = exports = DataSet;
diff --git a/src/events.js b/src/events.js
index bb091970..b2309a6b 100644
--- a/src/events.js
+++ b/src/events.js
@@ -1,4 +1,3 @@
-
/**
* Event listener (singleton)
*/
@@ -116,4 +115,4 @@ var events = {
};
// exports
-vis.events = events;
+module.exports = exports = events;
diff --git a/src/module.js b/src/module.js
index 7b2519bf..0ef13dac 100644
--- a/src/module.js
+++ b/src/module.js
@@ -1,19 +1,3 @@
-// Define namespace vis
-var vis = {
- component: {
- item: {}
- }
-};
-
-/**
- * CommonJS module exports
- */
-if (typeof exports !== 'undefined') {
- exports = vis;
-}
-if (typeof module !== 'undefined') {
- module.exports = vis;
-}
/**
* AMD module exports
@@ -24,14 +8,6 @@ if (typeof(define) === 'function') {
});
}
-/**
- * Window exports
- */
-if (typeof window !== 'undefined') {
- // attach the module to the window, load as a regular javascript file
- window['vis'] = vis;
-}
-
/**
* load css from text
* @param {String} css Text containing css
diff --git a/src/range.js b/src/range.js
index a94b3ff6..3dd8187d 100644
--- a/src/range.js
+++ b/src/range.js
@@ -1,3 +1,6 @@
+var util = require('./util'),
+ events = require('./events');
+
/**
* @constructor Range
* A Range controls a numeric range with a start and end value.
@@ -524,4 +527,4 @@ Range.prototype.move = function(moveFactor) {
};
// exports
-vis.Range = Range;
+module.exports = exports = Range;
diff --git a/src/stack.js b/src/stack.js
index e1420c6e..5cfa2363 100644
--- a/src/stack.js
+++ b/src/stack.js
@@ -1,3 +1,5 @@
+var util = require('./util');
+
/**
* @constructor Stack
* Stacks items on top of each other.
@@ -157,4 +159,4 @@ Stack.prototype.collision = function(a, b, margin) {
};
// exports
-vis.Stack = Stack;
+module.exports = exports = Stack;
diff --git a/src/timestep.js b/src/timestep.js
index 1b636021..0c9e7d34 100644
--- a/src/timestep.js
+++ b/src/timestep.js
@@ -1,4 +1,7 @@
-/**
+var util = require('./util'),
+ moment = require('moment');
+
+ /**
* @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
@@ -449,5 +452,5 @@ TimeStep.prototype.getLabelMajor = function(date) {
}
};
-// export
-vis.TimeStep = TimeStep;
+// exports
+module.exports = exports = TimeStep;
diff --git a/src/util.js b/src/util.js
index fe0d7809..e34b8be4 100644
--- a/src/util.js
+++ b/src/util.js
@@ -780,6 +780,5 @@ if(!Array.isArray) {
};
}
-
-// export
-vis.util = util;
+// exports
+module.exports = exports = util;
diff --git a/src/vis.js b/src/vis.js
new file mode 100644
index 00000000..581c1cf9
--- /dev/null
+++ b/src/vis.js
@@ -0,0 +1,31 @@
+/**
+ * vis.js library exports
+ */
+var vis = {
+ Controller: require('./controller'),
+ DataSet: require('./dataset'),
+ events: require('./events'),
+ Range: require('./range'),
+ Stack: require('./stack'),
+ TimeStep: require('./timestep'),
+ util: require('./util'),
+
+ component: {
+ item: {
+ Item: '../../Item',
+ ItemBox: '../../ItemBox',
+ ItemPoint: '../../ItemPoint',
+ ItemRange: '../../ItemRange'
+ },
+
+ Component: require('./component/component'),
+ Panel: require('./component/panel'),
+ RootPanel: require('./component/rootpanel'),
+ ItemSet: require('./component/itemset'),
+ TimeAxis: require('./component/timeaxis')
+ },
+
+ Timeline: require('./visualization/timeline')
+};
+
+module.exports = exports = vis;
diff --git a/src/visualization/timeline.js b/src/visualization/timeline.js
index 3ba18ade..8d70740e 100644
--- a/src/visualization/timeline.js
+++ b/src/visualization/timeline.js
@@ -1,3 +1,12 @@
+var util = require('./../util'),
+ moment = require('moment'),
+ Range = require('../range'),
+ Controller = require('../controller'),
+ Component = require('../component/component'),
+ RootPanel = require('../component/rootpanel'),
+ TimeAxis = require('../component/timeaxis'),
+ ItemSet = require('../component/itemset');
+
/**
* Create a timeline visualization
* @param {HTMLElement} container
@@ -140,4 +149,4 @@ Timeline.prototype.setData = function(data) {
};
// exports
-vis.Timeline = Timeline;
+module.exports = exports = Timeline;
diff --git a/test/timeline.html b/test/timeline.html
index 51eedc17..0b3af27c 100644
--- a/test/timeline.html
+++ b/test/timeline.html
@@ -2,6 +2,13 @@
+
diff --git a/vis.js b/vis.js
index 12d59aaa..0619f7cd 100644
--- a/vis.js
+++ b/vis.js
@@ -4,8 +4,8 @@
*
* A dynamic, browser-based visualization library.
*
- * @version 0.0.5
- * @date 2013-04-24
+ * @version 0.0.6
+ * @date 2013-04-25
*
* @license
* Copyright (C) 2011-2013 Almende B.V, http://almende.com
@@ -22,66 +22,161 @@
* License for the specific language governing permissions and limitations under
* the License.
*/
-
-(function () {
-// Define namespace vis
+(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 0) {
- this.step = newStep;
+ if (data instanceof Array) {
+ // Array
+ data.forEach(function (item) {
+ var id = me._updateItem(item);
+ items.push(id);
+ });
+ }
+ else if (util.isDataTable(data)) {
+ // Google DataTable
+ var columns = this._getColumnNames(data);
+ for (var row = 0, rows = data.getNumberOfRows(); row < rows; row++) {
+ var item = {};
+ columns.forEach(function (field, col) {
+ item[field] = data.getValue(row, col);
+ });
+ id = me._updateItem(item);
+ items.push(id);
+ }
+ }
+ else if (data instanceof Object) {
+ // Single item
+ id = me._updateItem(data);
+ items.push(id);
+ }
+ else {
+ throw new Error('Unknown dataType');
}
- this.autoScale = false;
+ this._trigger('update', {items: items}, senderId);
};
/**
- * Enable or disable autoscaling
- * @param {boolean} enable If true, autoascaling is set true
+ * Get a data item or multiple items
+ * @param {String | Number | Array | Object} [ids] Id of a single item, or an
+ * array with multiple id's, or
+ * undefined or an Object with options
+ * to retrieve all data.
+ * @param {Object} [options] Available options:
+ * {String} [type]
+ * 'DataTable' or 'Array' (default)
+ * {Object.} [fieldTypes]
+ * {String[]} [fields] filter fields
+ * @param {Array | DataTable} [data] If provided, items will be appended
+ * to this array or table. Required
+ * in case of Google DataTable
+ * @return {Array | Object | DataTable | null} data
+ * @throws Error
*/
-TimeStep.prototype.setAutoScale = function (enable) {
- this.autoScale = enable;
-};
+DataSet.prototype.get = function (ids, options, data) {
+ var me = this;
+ // shift arguments when first argument contains the options
+ if (util.getType(ids) == 'Object') {
+ data = options;
+ options = ids;
+ ids = undefined;
+ }
-/**
- * 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;
- }
-
- 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;}
-};
-
-/**
- * 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);
- }
-
- 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);
- }
-};
-
-/**
- * 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;
- }
-};
-
-
-/**
- * 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;
- }
-
- 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 '';
- }
-};
-
-
-/**
- * Returns formatted text for the major axislabel, 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;
- }
-
- //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 '';
- }
-};
-
-// export
-vis.TimeStep = TimeStep;
-
-/**
- * DataSet
- *
- * Usage:
- * var dataSet = new DataSet({
- * fieldId: '_id',
- * fieldTypes: {
- * // ...
- * }
- * });
- *
- * 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.} [fieldTypes]
- * {String[]} [fields] filter fields
- * @param {Array | DataTable} [data] If provided, items will be appended
- * to this array or table. Required
- * in case of Google DataTable
- * @return {Array | Object | DataTable | null} data
- * @throws Error
- */
-DataSet.prototype.get = function (ids, options, data) {
- var me = this;
-
- // shift arguments when first argument contains the options
- if (util.getType(ids) == 'Object') {
- data = options;
- options = ids;
- ids = undefined;
- }
-
- // merge field types
- var fieldTypes = {};
- if (this.options && this.options.fieldTypes) {
- util.forEach(this.options.fieldTypes, function (value, field) {
- fieldTypes[field] = value;
- });
- }
- if (options && options.fieldTypes) {
- util.forEach(options.fieldTypes, function (value, field) {
- fieldTypes[field] = value;
- });
+ // merge field types
+ var fieldTypes = {};
+ if (this.options && this.options.fieldTypes) {
+ util.forEach(this.options.fieldTypes, function (value, field) {
+ fieldTypes[field] = value;
+ });
+ }
+ if (options && options.fieldTypes) {
+ util.forEach(options.fieldTypes, function (value, field) {
+ fieldTypes[field] = value;
+ });
}
var fields = options ? options.fields : undefined;
@@ -1991,7 +1662,10 @@ DataSet.prototype._appendRow = function (dataTable, columns, item) {
};
// exports
-vis.DataSet = DataSet;
+module.exports = exports = DataSet;
+
+},{"./util":8}],6:[function(require,module,exports){
+var util = require('./util');
/**
* @constructor Stack
@@ -2152,7 +1826,11 @@ Stack.prototype.collision = function(a, b, margin) {
};
// exports
-vis.Stack = Stack;
+module.exports = exports = Stack;
+
+},{"./util":8}],5:[function(require,module,exports){
+var util = require('./util'),
+ events = require('./events');
/**
* @constructor Range
@@ -2643,187 +2321,47 @@ Range.prototype.zoom = function(zoomFactor, zoomAround) {
}
// 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);
- }
-
- // 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);
-};
-
-/**
- * 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
- */
-Range.prototype.move = function(moveFactor) {
- // zoom start Date and end Date relative to the zoomAroundDate
- var diff = (this.end - this.start);
-
- // apply new values
- var newStart = this.start + diff * moveFactor;
- var newEnd = this.end + diff * moveFactor;
-
- // TODO: reckon with min and max range
-
- this.start = newStart;
- this.end = newEnd;
-};
-
-// exports
-vis.Range = Range;
-
-/**
- * @constructor Controller
- *
- * A Controller controls the reflows and repaints of all visual components
- */
-function Controller () {
- this.id = util.randomUUID();
- this.components = {};
-
- this.repaintTimer = undefined;
- this.reflowTimer = undefined;
-}
-
-/**
- * Add a component to the controller
- * @param {Component | Controller} component
- */
-Controller.prototype.add = function (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');
- }
-
- // add the component
- component.controller = this;
- this.components[component.id] = component;
-};
-
-/**
- * Request a reflow. The controller will schedule a reflow
- */
-Controller.prototype.requestReflow = function () {
- if (!this.reflowTimer) {
- var me = this;
- this.reflowTimer = setTimeout(function () {
- me.reflowTimer = undefined;
- me.reflow();
- }, 0);
- }
-};
-
-/**
- * Request a repaint. The controller will schedule a repaint
- */
-Controller.prototype.requestRepaint = function () {
- if (!this.repaintTimer) {
- var me = this;
- this.repaintTimer = setTimeout(function () {
- me.repaintTimer = undefined;
- me.repaint();
- }, 0);
- }
-};
-
-/**
- * Repaint all components
- */
-Controller.prototype.repaint = function () {
- var changed = false;
-
- // cancel any running repaint request
- if (this.repaintTimer) {
- clearTimeout(this.repaintTimer);
- this.repaintTimer = undefined;
- }
-
- 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;
- }
+ // out with a factor -0.1
+ if (zoomFactor < 0) {
+ zoomFactor = zoomFactor / (1 + zoomFactor);
}
- util.forEach(this.components, repaint);
+ // zoom start and end relative to the zoomAround value
+ var startDiff = (this.start - zoomAround);
+ var endDiff = (this.end - zoomAround);
- // immediately reflow when needed
- if (changed) {
- this.reflow();
- }
- // TODO: limit the number of nested reflows/repaints, prevent loop
+ // calculate new start and end
+ var newStart = this.start - startDiff * zoomFactor;
+ var newEnd = this.end - endDiff * zoomFactor;
+
+ this.setRange(newStart, newEnd);
};
/**
- * Reflow all components
+ * 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
*/
-Controller.prototype.reflow = function () {
- var resized = false;
-
- // cancel any running repaint request
- if (this.reflowTimer) {
- clearTimeout(this.reflowTimer);
- this.reflowTimer = undefined;
- }
-
- 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);
- }
+Range.prototype.move = function(moveFactor) {
+ // zoom start Date and end Date relative to the zoomAroundDate
+ var diff = (this.end - this.start);
- // reflow the component itself and mark as done
- resized = component.reflow() || resized;
- done[id] = true;
- }
- }
+ // apply new values
+ var newStart = this.start + diff * moveFactor;
+ var newEnd = this.end + diff * moveFactor;
- util.forEach(this.components, reflow);
+ // TODO: reckon with min and max range
- // immediately repaint when needed
- if (resized) {
- this.repaint();
- }
- // TODO: limit the number of nested reflows/repaints, prevent loop
+ this.start = newStart;
+ this.end = newEnd;
};
// exports
-vis.Controller = Controller;
+module.exports = exports = Range;
+
+},{"./util":8,"./events":4}],9:[function(require,module,exports){
+var util = require('./../util');
/**
* Prototype for visual components
@@ -2943,7 +2481,11 @@ Component.prototype.on = function (event, callback) {
};
// exports
-vis.component.Component = Component;
+module.exports = exports = Component;
+
+},{"./../util":8}],10:[function(require,module,exports){
+var util = require('../util'),
+ Component = require('./component');
/**
* A panel can contain components
@@ -3034,119 +2576,570 @@ Panel.prototype.reflow = function () {
update = util.updateProperty,
frame = this.frame;
- 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;
+ 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);
+};
+
+// exports
+module.exports = exports = Panel;
+
+},{"../util":8,"./component":9}],11:[function(require,module,exports){
+var util = require('../util'),
+ Panel = require('./panel');
+
+/**
+ * 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
+ */
+function RootPanel(container, options) {
+ this.id = util.randomUUID();
+ this.container = container;
+ this.options = {
+ autoResize: true
+ };
+
+ this.listeners = {}; // event listeners
+
+ this.setOptions(options);
+}
+
+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]
+ * {String | Number | function} [height]
+ * {Boolean | function} [autoResize]
+ */
+RootPanel.prototype.setOptions = function (options) {
+ util.extend(this.options, options);
+
+ if (this.options.autoResize) {
+ this._watch();
+ }
+ else {
+ this._unwatch();
+ }
+};
+
+/**
+ * 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;
+ if (!frame) {
+ frame = document.createElement('div');
+ frame.className = 'graph panel';
+
+ if (options.className) {
+ util.addClassName(frame, util.option.asString(options.className));
+ }
+
+ this.frame = frame;
+ changed += 1;
+ }
+ if (!frame.parentNode) {
+ if (!this.container) {
+ throw new Error('Cannot repaint root panel: no container attached');
+ }
+ 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%'));
+
+ this._updateEventEmitters();
+
+ return (changed > 0);
+};
+
+/**
+ * Reflow the component
+ * @return {Boolean} resized
+ */
+RootPanel.prototype.reflow = function () {
+ var changed = 0,
+ update = util.updateProperty,
+ frame = this.frame;
+
+ 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);
+};
+
+/**
+ * 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;
+
+ this._unwatch();
+
+ var checkSize = function () {
+ if (!me.options.autoResize) {
+ // stop watching when the option autoResize is changed to false
+ me._unwatch();
+ return;
+ }
+
+ if (me.frame) {
+ // check whether the frame is resized
+ if ((me.frame.clientWidth != me.width) ||
+ (me.frame.clientHeight != me.height)) {
+ me.requestReflow();
+ }
+ }
+ };
+
+ // TODO: automatically cleanup the event listener when the frame is deleted
+ util.addEventListener(window, 'resize', checkSize);
+
+ 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;
+ }
+
+ // 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);
+
+ this._updateEventEmitters();
+};
+
+/**
+ * Update the event listeners for all event emitters
+ * @private
+ */
+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);
+ }
+ }
+ });
+
+ // TODO: be able to delete event listeners
+ // TODO: be able to move event listeners to a parent when available
}
-
- return (changed > 0);
};
// exports
-vis.component.Panel = Panel;
+module.exports = exports = RootPanel;
+
+},{"../util":8,"./panel":10}],12:[function(require,module,exports){
+var util = require('../util'),
+ DataSet = require('../dataset'),
+ Panel = require('./panel'),
+ Stack = require('../stack'),
+ ItemBox = require('./item/itembox'),
+ ItemRange = require('./item/itemrange'),
+ ItemPoint = require('./item/itempoint');
/**
- * 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
+ * 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
*/
-function RootPanel(container, options) {
+function ItemSet(parent, depends, options) {
this.id = util.randomUUID();
- this.container = container;
+ this.parent = parent;
+ this.depends = depends;
+
+ // one options object is shared by this itemset and all its items
this.options = {
- autoResize: true
+ style: 'box',
+ align: 'center',
+ orientation: 'bottom',
+ margin: {
+ axis: 20,
+ item: 10
+ },
+ padding: 5
};
- this.listeners = {}; // event listeners
+ this.dom = {};
+
+ var me = this;
+ this.data = null; // DataSet
+ this.range = null; // Range or Object {start: number, end: number}
+ 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);
+ }
+ };
+
+ this.items = {};
+ this.queue = {}; // queue with items to be added/updated/removed
+ this.stack = new Stack(this);
+ this.conversion = null;
this.setOptions(options);
}
-RootPanel.prototype = new Panel();
+ItemSet.prototype = new Panel();
+
+// available item types will be registered here
+ItemSet.types = {
+ box: ItemBox,
+ range: ItemRange,
+ point: ItemPoint
+};
/**
- * 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]
- * {String | Number | function} [height]
- * {Boolean | function} [autoResize]
+ * 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} [style]
+ * Default style 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.
*/
-RootPanel.prototype.setOptions = function (options) {
+ItemSet.prototype.setOptions = function (options) {
util.extend(this.options, options);
- if (this.options.autoResize) {
- this._watch();
- }
- else {
- this._unwatch();
+ // TODO: ItemSet should also attach event listeners for rangechange and rangechanged, like timeaxis
+
+ this.stack.setOptions(this.options);
+};
+
+/**
+ * Set range (start and end).
+ * @param {Range | Object} range A Range or an object containing start and end.
+ */
+ItemSet.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;
};
/**
* Repaint the component
* @return {Boolean} changed
*/
-RootPanel.prototype.repaint = function () {
+ItemSet.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 = 'graph panel';
+ frame.className = 'itemset';
if (options.className) {
util.addClassName(frame, util.option.asString(options.className));
}
+ // 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;
+
+ // create axis panel
+ var axis = document.createElement('div');
+ axis.className = 'itemset-axis';
+ //frame.appendChild(axis);
+ this.dom.axis = axis;
+
this.frame = frame;
changed += 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) {
- if (!this.container) {
- throw new Error('Cannot repaint root panel: no container attached');
- }
- this.container.appendChild(frame);
+ parentContainer.appendChild(frame);
+ changed += 1;
+ }
+ if (!this.dom.axis.parentNode) {
+ parentContainer.appendChild(this.dom.axis);
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%'));
- this._updateEventEmitters();
+ // reposition axis
+ changed += update(this.dom.axis.style, 'top', asSize(options.top, '0px'));
+
+ this._updateConversion();
+
+ var me = this,
+ queue = this.queue,
+ data = this.data,
+ items = this.items,
+ dataOptions = {
+ fields: ['id', 'start', 'end', 'content', 'type']
+ };
+ // TODO: copy options from the itemset itself?
+ // TODO: make orientation dynamically changable for the items
+
+ // show/hide added/changed/removed items
+ Object.keys(queue).forEach(function (id) {
+ var entry = queue[id];
+ var item = entry.item;
+ //noinspection FallthroughInSwitchStatementJS
+ switch (entry.action) {
+ case 'add':
+ case 'update':
+ var itemData = data.get(id, dataOptions);
+ var type = itemData.type ||
+ (itemData.start && itemData.end && 'range') ||
+ 'box';
+ var constructor = ItemSet.types[type];
+
+ // 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, delete the item
+ item.visible = false;
+ changed += item.repaint();
+ item = null;
+ }
+ else {
+ item.data = itemData; // TODO: create a method item.setData ?
+ changed += item.repaint();
+ }
+ }
+
+ if (!item) {
+ // create item
+ if (constructor) {
+ item = new constructor(me, itemData, options);
+ changed += item.repaint();
+ }
+ else {
+ throw new TypeError('Unknown item type "' + type + '"');
+ }
+ }
+
+ // update lists
+ items[id] = item;
+ delete queue[id];
+ break;
+
+ case 'remove':
+ if (item) {
+ // TODO: remove dom of the item
+ item.visible = false;
+ changed += item.repaint();
+ }
+
+ // update lists
+ delete items[id];
+ delete queue[id];
+ break;
+
+ default:
+ console.log('Error: unknown action "' + entry.action + '"');
+ }
+ });
+
+ // reposition all items
+ util.forEach(this.items, function (item) {
+ item.reposition();
+ });
return (changed > 0);
};
+/**
+ * Get the foreground container element
+ * @return {HTMLElement} foreground
+ */
+ItemSet.prototype.getForeground = function () {
+ return this.dom.foreground;
+};
+
+/**
+ * Get the background container element
+ * @return {HTMLElement} background
+ */
+ItemSet.prototype.getBackground = function () {
+ return this.dom.background;
+};
+
/**
* Reflow the component
* @return {Boolean} resized
*/
-RootPanel.prototype.reflow = function () {
+ItemSet.prototype.reflow = function () {
var changed = 0,
+ options = this.options,
update = util.updateProperty,
+ asNumber = util.option.asNumber,
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();
+
+ var maxHeight = asNumber(options.maxHeight);
+ var height;
+ if (options.height != null) {
+ height = frame.offsetHeight;
+ if (maxHeight != null) {
+ height = Math.min(height, maxHeight);
+ }
+ changed += update(this, 'height', height);
+ }
+ else {
+ // height is not specified, determine the height from the height and positioned items
+ var frameHeight = this.height;
+ height = 0;
+ if (options.orientation == 'top') {
+ util.forEach(this.items, function (item) {
+ height = Math.max(height, item.top + item.height);
+ });
+ }
+ else {
+ // orientation == 'bottom'
+ util.forEach(this.items, function (item) {
+ height = Math.max(height, frameHeight - item.top);
+ });
+ }
+ height += options.margin.axis;
+
+ if (maxHeight != null) {
+ height = Math.min(height, maxHeight);
+ }
+
+ 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);
- changed += update(this, 'height', frame.offsetHeight);
}
else {
changed += 1;
@@ -3156,103 +3149,180 @@ RootPanel.prototype.reflow = function () {
};
/**
- * Watch for changes in the size of the frame. On resize, the Panel will
- * automatically redraw itself.
- * @private
+ * Set data
+ * @param {DataSet | Array | DataTable} data
*/
-RootPanel.prototype._watch = function () {
+ItemSet.prototype.setData = function(data) {
+ // unsubscribe from current dataset
+ var current = this.data;
+ if (current) {
+ util.forEach(this.listeners, function (callback, event) {
+ current.unsubscribe(event, callback);
+ });
+ }
+
+ if (data instanceof DataSet) {
+ this.data = data;
+ }
+ else {
+ this.data = new DataSet({
+ fieldTypes: {
+ start: 'Date',
+ end: 'Date'
+ }
+ });
+ this.data.add(data);
+ }
+
+ var id = this.id;
var me = this;
+ util.forEach(this.listeners, function (callback, event) {
+ me.data.subscribe(event, callback, id);
+ });
- this._unwatch();
+ var dataItems = this.data.get({filter: ['id']});
+ var ids = [];
+ util.forEach(dataItems, function (dataItem, index) {
+ ids[index] = dataItem.id;
+ });
+ this._onAdd(ids);
+};
- var checkSize = function () {
- if (!me.options.autoResize) {
- // stop watching when the option autoResize is changed to false
- me._unwatch();
- return;
- }
- if (me.frame) {
- // check whether the frame is resized
- if ((me.frame.clientWidth != me.width) ||
- (me.frame.clientHeight != me.height)) {
- me.requestReflow();
- }
- }
- };
+/**
+ * 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
+ */
+ItemSet.prototype.getDataRange = function () {
+ // calculate min from start filed
+ var data = this.data;
+ var min = data.min('start');
+ min = min ? min.start.valueOf() : null;
- // TODO: automatically cleanup the event listener when the frame is deleted
- util.addEventListener(window, 'resize', checkSize);
+ // calculate max of both start and end fields
+ var maxStart = data.max('start');
+ var maxEnd = data.max('end');
+ maxStart = maxStart ? maxStart.start.valueOf() : null;
+ maxEnd = maxEnd ? maxEnd.end.valueOf() : null;
+ var max = Math.max(maxStart, maxEnd);
- this.watchTimer = setInterval(checkSize, 1000);
+ return {
+ min: new Date(min),
+ max: new Date(max)
+ };
};
/**
- * Stop watching for a resize of the frame.
+ * Handle updated items
+ * @param {Number[]} ids
* @private
*/
-RootPanel.prototype._unwatch = function () {
- if (this.watchTimer) {
- clearInterval(this.watchTimer);
- this.watchTimer = undefined;
- }
+ItemSet.prototype._onUpdate = function(ids) {
+ this._toQueue(ids, 'update');
+};
- // TODO: remove event listener on window.resize
+/**
+ * Handle changed items
+ * @param {Number[]} ids
+ * @private
+ */
+ItemSet.prototype._onAdd = function(ids) {
+ this._toQueue(ids, 'add');
};
/**
- * 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.
+ * Handle removed items
+ * @param {Number[]} ids
+ * @private
*/
-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);
+ItemSet.prototype._onRemove = function(ids) {
+ this._toQueue(ids, 'remove');
+};
- this._updateEventEmitters();
+/**
+ * Put items in the queue to be added/updated/remove
+ * @param {Number[]} ids
+ * @param {String} action can be 'add', 'update', 'remove'
+ */
+ItemSet.prototype._toQueue = function (ids, action) {
+ var items = this.items;
+ var queue = this.queue;
+ ids.forEach(function (id) {
+ var entry = queue[id];
+ if (entry) {
+ // already queued, update the action of the entry
+ entry.action = action;
+ }
+ else {
+ // not yet queued, add an entry to the queue
+ queue[id] = {
+ item: items[id] || null,
+ action: action
+ };
+ }
+ });
+
+ if (this.controller) {
+ //this.requestReflow();
+ this.requestRepaint();
+ }
};
/**
- * Update the event listeners for all event emitters
+ * 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
*/
-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);
- }
- }
- });
-
- // TODO: be able to delete event listeners
- // TODO: be able to move event listeners to a parent when available
+ItemSet.prototype._updateConversion = function() {
+ var range = this.range;
+ if (!range) {
+ throw new Error('No range configured');
+ }
+
+ if (range.conversion) {
+ this.conversion = range.conversion(this.width);
+ }
+ else {
+ this.conversion = Range.conversion(range.start, range.end, this.width);
}
};
+/**
+ * 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(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(time) {
+ var conversion = this.conversion;
+ return (time.valueOf() - conversion.offset) * conversion.factor;
+};
+
// exports
-vis.component.RootPanel = RootPanel;
+module.exports = exports = ItemSet;
+
+},{"../util":8,"../dataset":3,"./panel":10,"../stack":6,"./item/itembox":15,"./item/itempoint":16,"./item/itemrange":17}],14:[function(require,module,exports){
+var util = require('../util'),
+ TimeStep = require('../timestep'),
+ Component = require('./component');
/**
* A horizontal time axis
@@ -3659,671 +3729,593 @@ TimeAxis.prototype._repaintMeasureChars = function () {
};
/**
- * Reflow the component
- * @return {Boolean} resized
- */
-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');
- }
-
- 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.options.showMinorLabels,
- showMajorLabels = this.options.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.options.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.options.orientation + '"');
- }
-
- 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.cast(range.start, 'Date'),
- end = util.cast(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);
-};
-
-/**
- * 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
- */
-TimeAxis.prototype._updateConversion = function() {
- var range = this.range;
- if (!range) {
- throw new Error('No range configured');
- }
-
- if (range.conversion) {
- this.conversion = range.conversion(this.width);
- }
- else {
- this.conversion = Range.conversion(range.start, range.end, this.width);
- }
-};
-
-// exports
-vis.component.TimeAxis = TimeAxis;
-
-/**
- * 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
- */
-function ItemSet(parent, depends, options) {
- this.id = util.randomUUID();
- this.parent = parent;
- this.depends = depends;
-
- // one options object is shared by this itemset and all its items
- this.options = {
- style: 'box',
- align: 'center',
- orientation: 'bottom',
- margin: {
- axis: 20,
- item: 10
- },
- padding: 5
- };
-
- this.dom = {};
-
- var me = this;
- this.data = null; // DataSet
- this.range = null; // Range or Object {start: number, end: number}
- 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);
- }
- };
-
- this.items = {};
- this.queue = {}; // queue with items to be added/updated/removed
- this.stack = new Stack(this);
- this.conversion = null;
-
- this.setOptions(options);
-}
-
-ItemSet.prototype = new Panel();
-
-/**
- * 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} [style]
- * Default style 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 = function (options) {
- util.extend(this.options, options);
-
- // TODO: ItemSet should also attach event listeners for rangechange and rangechanged, like timeaxis
-
- this.stack.setOptions(this.options);
-};
-
-/**
- * Set range (start and end).
- * @param {Range | Object} range A Range or an object containing start and end.
- */
-ItemSet.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;
-};
-
-/**
- * Repaint the component
- * @return {Boolean} changed
+ * Reflow the component
+ * @return {Boolean} resized
*/
-ItemSet.prototype.repaint = function () {
+TimeAxis.prototype.reflow = function () {
var changed = 0,
update = util.updateProperty,
- asSize = util.option.asSize,
- options = this.options,
- frame = this.frame;
+ frame = this.frame,
+ range = this.range;
- if (!frame) {
- frame = document.createElement('div');
- frame.className = 'itemset';
+ if (!range) {
+ throw new Error('Cannot repaint time axis: no range configured');
+ }
- if (options.className) {
- util.addClassName(frame, util.option.asString(options.className));
+ 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.options.showMinorLabels,
+ showMajorLabels = this.options.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;
}
- // create background panel
- var background = document.createElement('div');
- background.className = 'background';
- frame.appendChild(background);
- this.dom.background = background;
+ var parentHeight = frame.parentNode ? frame.parentNode.offsetHeight : 0;
+ if (parentHeight != props.parentHeight) {
+ props.parentHeight = parentHeight;
+ changed += 1;
+ }
+ switch (this.options.orientation) {
+ case 'bottom':
+ props.minorLabelHeight = showMinorLabels ? props.minorCharHeight : 0;
+ props.majorLabelHeight = showMajorLabels ? props.majorCharHeight : 0;
- // create foreground panel
- var foreground = document.createElement('div');
- foreground.className = 'foreground';
- frame.appendChild(foreground);
- this.dom.foreground = foreground;
+ props.minorLabelTop = 0;
+ props.majorLabelTop = props.minorLabelTop + props.minorLabelHeight;
- // create axis panel
- var axis = document.createElement('div');
- axis.className = 'itemset-axis';
- //frame.appendChild(axis);
- this.dom.axis = axis;
+ props.minorLineTop = -this.top;
+ props.minorLineHeight = Math.max(this.top + props.majorLabelHeight, 0);
+ props.minorLineWidth = 1; // TODO: really calculate width
- this.frame = frame;
- changed += 1;
- }
+ props.majorLineTop = -this.top;
+ props.majorLineHeight = Math.max(this.top + props.minorLabelHeight + props.majorLabelHeight, 0);
+ props.majorLineWidth = 1; // TODO: really calculate width
- 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;
+ 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.options.orientation + '"');
+ }
+
+ 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.cast(range.start, 'Date'),
+ end = util.cast(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());
}
- // 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%'));
+ return (changed > 0);
+};
- // reposition axis
- changed += update(this.dom.axis.style, 'top', asSize(options.top, '0px'));
+/**
+ * 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
+ */
+TimeAxis.prototype._updateConversion = function() {
+ var range = this.range;
+ if (!range) {
+ throw new Error('No range configured');
+ }
- this._updateConversion();
+ if (range.conversion) {
+ this.conversion = range.conversion(this.width);
+ }
+ else {
+ this.conversion = Range.conversion(range.start, range.end, this.width);
+ }
+};
- var me = this,
- queue = this.queue,
- data = this.data,
- items = this.items,
- dataOptions = {
- fields: ['id', 'start', 'end', 'content', 'type']
- };
- // TODO: copy options from the itemset itself?
- // TODO: make orientation dynamically changable for the items
+// exports
+module.exports = exports = TimeAxis;
- // show/hide added/changed/removed items
- Object.keys(queue).forEach(function (id) {
- var entry = queue[id];
- var item = entry.item;
- //noinspection FallthroughInSwitchStatementJS
- switch (entry.action) {
- case 'add':
- case 'update':
- var itemData = data.get(id, dataOptions);
- var type = itemData.type ||
- (itemData.start && itemData.end && 'range') ||
- 'box';
- var constructor = vis.component.item[type];
+},{"../util":8,"../timestep":7,"./component":9}],7:[function(require,module,exports){
+var util = require('./util'),
+ moment = require('moment');
- // 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, delete the item
- item.visible = false;
- changed += item.repaint();
- item = null;
- }
- else {
- item.data = itemData; // TODO: create a method item.setData ?
- changed += item.repaint();
- }
- }
+ /**
+ * @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();
- if (!item) {
- // create item
- if (constructor) {
- item = new constructor(me, itemData, options);
- changed += item.repaint();
- }
- else {
- throw new TypeError('Unknown item type "' + type + '"');
- }
- }
+ this.autoScale = true;
+ this.scale = TimeStep.SCALE.DAY;
+ this.step = 1;
- // update lists
- items[id] = item;
- delete queue[id];
- break;
+ // initialize the range
+ this.setRange(start, end, minimumStep);
+};
- case 'remove':
- if (item) {
- // TODO: remove dom of the item
- item.visible = false;
- changed += item.repaint();
- }
+/// enum scale
+TimeStep.SCALE = {
+ MILLISECOND: 1,
+ SECOND: 2,
+ MINUTE: 3,
+ HOUR: 4,
+ DAY: 5,
+ WEEKDAY: 6,
+ MONTH: 7,
+ YEAR: 8
+};
- // update lists
- delete items[id];
- delete queue[id];
- break;
- default:
- console.log('Error: unknown action "' + entry.action + '"');
- }
- });
+/**
+ * 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;
+ }
- // reposition all items
- util.forEach(this.items, function (item) {
- item.reposition();
- });
+ this._start = (start != undefined) ? new Date(start.valueOf()) : new Date();
+ this._end = (end != undefined) ? new Date(end.valueOf()) : new Date();
- return (changed > 0);
+ if (this.autoScale) {
+ this.setMinimumStep(minimumStep);
+ }
};
/**
- * Get the foreground container element
- * @return {HTMLElement} foreground
+ * Set the range iterator to the start date.
*/
-ItemSet.prototype.getForeground = function () {
- return this.dom.foreground;
+TimeStep.prototype.first = function() {
+ this.current = new Date(this._start.valueOf());
+ this.roundToMinor();
};
/**
- * Get the background container element
- * @return {HTMLElement} background
+ * 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.getBackground = function () {
- return this.dom.background;
+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
+ }
+
+ 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;
+ }
+ }
};
/**
- * Reflow the component
- * @return {Boolean} resized
+ * Check if the there is a next step
+ * @return {boolean} true if the current date has not passed the end date
*/
-ItemSet.prototype.reflow = function () {
- var changed = 0,
- options = this.options,
- update = util.updateProperty,
- asNumber = util.option.asNumber,
- 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.hasNext = function () {
+ return (this.current.valueOf() <= this._end.valueOf());
+};
- var maxHeight = asNumber(options.maxHeight);
- var height;
- if (options.height != null) {
- height = frame.offsetHeight;
- if (maxHeight != null) {
- height = Math.min(height, maxHeight);
- }
- changed += update(this, 'height', height);
- }
- else {
- // height is not specified, determine the height from the height and positioned items
- var frameHeight = this.height;
- height = 0;
- if (options.orientation == 'top') {
- util.forEach(this.items, function (item) {
- height = Math.max(height, item.top + item.height);
- });
- }
- else {
- // orientation == 'bottom'
- util.forEach(this.items, function (item) {
- height = Math.max(height, frameHeight - item.top);
- });
- }
- height += options.margin.axis;
+/**
+ * Do the next step
+ */
+TimeStep.prototype.next = function() {
+ var prev = this.current.valueOf();
- if (maxHeight != null) {
- height = Math.min(height, maxHeight);
- }
+ // 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:
- changed += update(this, 'height', height);
+ 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;
}
-
- // 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;
+ 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;
+ }
}
- return (changed > 0);
-};
-
-/**
- * Set data
- * @param {DataSet | Array | DataTable} data
- */
-ItemSet.prototype.setData = function(data) {
- // unsubscribe from current dataset
- var current = this.data;
- if (current) {
- util.forEach(this.listeners, function (callback, event) {
- current.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;
+ }
}
- if (data instanceof DataSet) {
- this.data = data;
- }
- else {
- this.data = new DataSet({
- fieldTypes: {
- start: 'Date',
- end: 'Date'
- }
- });
- this.data.add(data);
+ // safety mechanism: if current time is still unchanged, move to the end
+ if (this.current.valueOf() == prev) {
+ this.current = new Date(this._end.valueOf());
}
+};
- var id = this.id;
- var me = this;
- util.forEach(this.listeners, function (callback, event) {
- me.data.subscribe(event, callback, id);
- });
- var dataItems = this.data.get({filter: ['id']});
- var ids = [];
- util.forEach(dataItems, function (dataItem, index) {
- ids[index] = dataItem.id;
- });
- this._onAdd(ids);
+/**
+ * Get the current datetime
+ * @return {Date} current The current date
+ */
+TimeStep.prototype.getCurrent = function() {
+ return this.current;
};
-
/**
- * 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
+ * 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.
*/
-ItemSet.prototype.getDataRange = function () {
- // calculate min from start filed
- var data = this.data;
- var min = data.min('start');
- min = min ? min.start.valueOf() : null;
+TimeStep.prototype.setScale = function(newScale, newStep) {
+ this.scale = newScale;
- // calculate max of both start and end fields
- var maxStart = data.max('start');
- var maxEnd = data.max('end');
- maxStart = maxStart ? maxStart.start.valueOf() : null;
- maxEnd = maxEnd ? maxEnd.end.valueOf() : null;
- var max = Math.max(maxStart, maxEnd);
+ if (newStep > 0) {
+ this.step = newStep;
+ }
- return {
- min: new Date(min),
- max: new Date(max)
- };
+ 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(ids) {
- this._toQueue(ids, 'update');
+TimeStep.prototype.setAutoScale = function (enable) {
+ this.autoScale = enable;
};
-/**
- * Handle changed items
- * @param {Number[]} ids
- * @private
- */
-ItemSet.prototype._onAdd = function(ids) {
- this._toQueue(ids, 'add');
-};
/**
- * Handle removed 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._onRemove = function(ids) {
- this._toQueue(ids, 'remove');
+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;}
};
/**
- * Put items in the queue to be added/updated/remove
- * @param {Number[]} ids
- * @param {String} action can be 'add', 'update', 'remove'
+ * 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._toQueue = function (ids, action) {
- var items = this.items;
- var queue = this.queue;
- ids.forEach(function (id) {
- var entry = queue[id];
- if (entry) {
- // already queued, update the action of the entry
- entry.action = action;
+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 {
- // not yet queued, add an entry to the queue
- queue[id] = {
- item: items[id] || null,
- action: action
- };
+ date.setDate(1);
}
- });
- if (this.controller) {
- //this.requestReflow();
- this.requestRepaint();
+ date.setHours(0);
+ date.setMinutes(0);
+ date.setSeconds(0);
+ date.setMilliseconds(0);
}
-};
-
-/**
- * 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() {
- var range = this.range;
- if (!range) {
- throw new Error('No range configured');
+ 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);
}
-
- if (range.conversion) {
- this.conversion = range.conversion(this.width);
+ 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 {
- this.conversion = Range.conversion(range.start, range.end, this.width);
+ 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);
}
};
/**
- * 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(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(time) {
- var conversion = this.conversion;
- return (time.valueOf() - conversion.offset) * conversion.factor;
-};
-
-// exports
-vis.component.ItemSet = ItemSet;
-
-
-/**
- * @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
- * // TODO: describe available options
+ * 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.
*/
-function Item (parent, data, options) {
- this.parent = parent;
- this.data = data;
- this.selected = false;
- this.visible = true;
- this.dom = null;
- this.options = options;
-}
+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;
+ }
+};
-Item.prototype = new Component();
/**
- * Select current item
+ * 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
*/
-Item.prototype.select = function () {
- this.selected = true;
+TimeStep.prototype.getLabelMinor = function(date) {
+ if (date == undefined) {
+ date = this.current;
+ }
+
+ 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 '';
+ }
};
+
/**
- * Unselect current item
+ * Returns formatted text for the major axislabel, 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
*/
-Item.prototype.unselect = function () {
- this.selected = false;
+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 '';
+ }
};
// exports
-vis.component.item.Item = Item;
+module.exports = exports = TimeStep;
+
+},{"./util":8,"moment":18}],16:[function(require,module,exports){
+var util = require('../../util'),
+ Item = require('./item');
/**
- * @constructor ItemBox
+ * @constructor ItemPoint
* @extends Item
* @param {ItemSet} parent
* @param {Object} data Object containing parameters start
@@ -4331,32 +4323,29 @@ vis.component.item.Item = Item;
* @param {Object} [options] Options to set initial property values
* // TODO: describe available options
*/
-function ItemBox (parent, data, options) {
+function ItemPoint (parent, data, options) {
this.props = {
dot: {
- left: 0,
top: 0,
width: 0,
height: 0
},
- line: {
- top: 0,
- left: 0,
- width: 0,
- height: 0
+ content: {
+ height: 0,
+ marginLeft: 0
}
};
Item.call(this, parent, data, options);
}
-ItemBox.prototype = new Item (null, null);
+ItemPoint.prototype = new Item (null, null);
/**
* Select the item
* @override
*/
-ItemBox.prototype.select = function () {
+ItemPoint.prototype.select = function () {
this.selected = true;
// TODO: select and unselect
};
@@ -4365,7 +4354,7 @@ ItemBox.prototype.select = function () {
* Unselect the item
* @override
*/
-ItemBox.prototype.unselect = function () {
+ItemPoint.prototype.unselect = function () {
this.selected = false;
// TODO: select and unselect
};
@@ -4374,7 +4363,7 @@ ItemBox.prototype.unselect = function () {
* Repaint the item
* @return {Boolean} changed
*/
-ItemBox.prototype.repaint = function () {
+ItemPoint.prototype.repaint = function () {
// TODO: make an efficient repaint
var changed = false;
var dom = this.dom;
@@ -4387,7 +4376,7 @@ ItemBox.prototype.repaint = function () {
dom = this.dom;
if (dom) {
- if (!this.options && !this.parent) {
+ if (!this.options && !this.options.parent) {
throw new Error('Cannot repaint item: no parent attached');
}
var foreground = this.parent.getForeground();
@@ -4395,22 +4384,10 @@ ItemBox.prototype.repaint = function () {
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');
- }
- if (!dom.box.parentNode) {
- foreground.appendChild(dom.box);
- changed = true;
- }
- if (!dom.line.parentNode) {
- background.appendChild(dom.line);
- changed = true;
- }
- if (!dom.dot.parentNode) {
- this.parent.dom.axis.appendChild(dom.dot);
+ if (!dom.point.parentNode) {
+ foreground.appendChild(dom.point);
+ foreground.appendChild(dom.point);
changed = true;
}
@@ -4435,9 +4412,7 @@ ItemBox.prototype.repaint = function () {
(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;
+ dom.point.className = 'item point' + className;
changed = true;
}
}
@@ -4445,16 +4420,8 @@ ItemBox.prototype.repaint = function () {
else {
// hide when visible
if (dom) {
- if (dom.box.parentNode) {
- dom.box.parentNode.removeChild(dom.box);
- changed = true;
- }
- if (dom.line.parentNode) {
- dom.line.parentNode.removeChild(dom.line);
- changed = true;
- }
- if (dom.dot.parentNode) {
- dom.dot.parentNode.removeChild(dom.dot);
+ if (dom.point.parentNode) {
+ dom.point.parentNode.removeChild(dom.point);
changed = true;
}
}
@@ -4464,11 +4431,11 @@ ItemBox.prototype.repaint = function () {
};
/**
- * Reflow the item: calculate its actual size and position from the DOM
+ * Reflow the item: calculate its actual size from the DOM
* @return {boolean} resized returns true if the axis is resized
* @override
*/
-ItemBox.prototype.reflow = function () {
+ItemPoint.prototype.reflow = function () {
if (this.data.start == undefined) {
throw new Error('Property "start" missing in item ' + this.data.id);
}
@@ -4477,52 +4444,32 @@ ItemBox.prototype.reflow = function () {
dom = this.dom,
props = this.props,
options = this.options,
- start = this.parent.toScreen(this.data.start),
- align = options && options.align,
orientation = options.orientation,
+ start = this.parent.toScreen(this.data.start),
changed = 0,
- top,
- left;
+ top;
if (dom) {
- changed += update(props.dot, 'height', dom.dot.offsetHeight);
+ 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.line, 'width', dom.line.offsetWidth);
- changed += update(props.line, 'width', dom.line.offsetWidth);
- 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);
+ changed += update(props.dot, 'height', dom.dot.offsetHeight);
+ changed += update(props.content, 'height', dom.content.offsetHeight);
- changed += update(props.line, 'left', start - props.line.width / 2);
- changed += update(props.dot, 'left', start - props.dot.width / 2);
if (orientation == 'top') {
top = options.margin.axis;
-
- changed += update(this, 'top', top);
- changed += update(props.line, 'top', 0);
- changed += update(props.line, 'height', top);
- changed += update(props.dot, 'top', -props.dot.height / 2);
}
else {
// default or 'bottom'
var parentHeight = this.parent.height;
- top = parentHeight - this.height - options.margin.axis;
-
- changed += update(this, 'top', top);
- changed += update(props.line, 'top', top + this.height);
- changed += update(props.line, 'height', Math.max(options.margin.axis, 0));
- changed += update(props.dot, 'top', parentHeight - props.dot.height / 2);
+ top = Math.max(parentHeight - this.height - options.margin.axis, 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;
@@ -4535,27 +4482,24 @@ ItemBox.prototype.reflow = function () {
* Create an items DOM
* @private
*/
-ItemBox.prototype._create = function () {
+ItemPoint.prototype._create = function () {
var dom = this.dom;
if (!dom) {
this.dom = dom = {};
- // create the box
- dom.box = document.createElement('DIV');
+ // background box
+ dom.point = document.createElement('div');
// className is updated in repaint()
- // contents box (inside the background box). used for making margins
- dom.content = document.createElement('DIV');
+ // contents box, right from the dot
+ 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';
+ dom.point.appendChild(dom.content);
- // dot on axis
- dom.dot = document.createElement('DIV');
- dom.dot.className = 'dot';
+ // dot at start
+ dom.dot = document.createElement('div');
+ dom.dot.className = 'dot';
+ dom.point.appendChild(dom.dot);
}
};
@@ -4564,42 +4508,30 @@ ItemBox.prototype._create = function () {
* range and size of the items itemset
* @override
*/
-ItemBox.prototype.reposition = function () {
+ItemPoint.prototype.reposition = function () {
var dom = this.dom,
- props = this.props,
- orientation = this.options.orientation;
+ props = this.props;
if (dom) {
- var box = dom.box,
- line = dom.line,
- dot = dom.dot;
-
- box.style.left = this.left + 'px';
- box.style.top = this.top + 'px';
-
- 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 = props.line.top + 'px';
- line.style.top = (this.top + this.height) + 'px';
- line.style.height = Math.max(props.dot.top - this.top - this.height, 0) + 'px';
+ dom.point.style.top = this.top + 'px';
+ dom.point.style.left = this.left + 'px';
- }
+ dom.content.style.marginLeft = props.content.marginLeft + 'px';
+ //dom.content.style.marginRight = props.content.marginRight + 'px'; // TODO
- dot.style.left = props.dot.left + 'px';
- dot.style.top = props.dot.top + 'px';
+ dom.dot.style.top = props.dot.top + 'px';
}
};
// exports
-vis.component.item.box = ItemBox;
+module.exports = exports = ItemPoint;
+
+},{"../../util":8,"./item":19}],15:[function(require,module,exports){
+var util = require('../../util'),
+ Item = require('./item');
/**
- * @constructor ItemPoint
+ * @constructor ItemBox
* @extends Item
* @param {ItemSet} parent
* @param {Object} data Object containing parameters start
@@ -4607,29 +4539,32 @@ vis.component.item.box = ItemBox;
* @param {Object} [options] Options to set initial property values
* // TODO: describe available options
*/
-function ItemPoint (parent, data, options) {
+function ItemBox (parent, data, options) {
this.props = {
dot: {
+ left: 0,
top: 0,
width: 0,
height: 0
},
- content: {
- height: 0,
- marginLeft: 0
+ line: {
+ top: 0,
+ left: 0,
+ width: 0,
+ height: 0
}
};
Item.call(this, parent, data, options);
}
-ItemPoint.prototype = new Item (null, null);
+ItemBox.prototype = new Item (null, null);
/**
* Select the item
* @override
*/
-ItemPoint.prototype.select = function () {
+ItemBox.prototype.select = function () {
this.selected = true;
// TODO: select and unselect
};
@@ -4638,7 +4573,7 @@ ItemPoint.prototype.select = function () {
* Unselect the item
* @override
*/
-ItemPoint.prototype.unselect = function () {
+ItemBox.prototype.unselect = function () {
this.selected = false;
// TODO: select and unselect
};
@@ -4647,7 +4582,7 @@ ItemPoint.prototype.unselect = function () {
* Repaint the item
* @return {Boolean} changed
*/
-ItemPoint.prototype.repaint = function () {
+ItemBox.prototype.repaint = function () {
// TODO: make an efficient repaint
var changed = false;
var dom = this.dom;
@@ -4660,7 +4595,7 @@ ItemPoint.prototype.repaint = function () {
dom = this.dom;
if (dom) {
- if (!this.options && !this.options.parent) {
+ if (!this.options && !this.parent) {
throw new Error('Cannot repaint item: no parent attached');
}
var foreground = this.parent.getForeground();
@@ -4668,10 +4603,22 @@ ItemPoint.prototype.repaint = function () {
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');
+ }
- if (!dom.point.parentNode) {
- foreground.appendChild(dom.point);
- foreground.appendChild(dom.point);
+ if (!dom.box.parentNode) {
+ foreground.appendChild(dom.box);
+ changed = true;
+ }
+ if (!dom.line.parentNode) {
+ background.appendChild(dom.line);
+ changed = true;
+ }
+ if (!dom.dot.parentNode) {
+ this.parent.dom.axis.appendChild(dom.dot);
changed = true;
}
@@ -4696,7 +4643,9 @@ ItemPoint.prototype.repaint = function () {
(this.selected ? ' selected' : '');
if (this.className != className) {
this.className = className;
- dom.point.className = 'item point' + className;
+ dom.box.className = 'item box' + className;
+ dom.line.className = 'item line' + className;
+ dom.dot.className = 'item dot' + className;
changed = true;
}
}
@@ -4704,8 +4653,16 @@ ItemPoint.prototype.repaint = function () {
else {
// hide when visible
if (dom) {
- if (dom.point.parentNode) {
- dom.point.parentNode.removeChild(dom.point);
+ if (dom.box.parentNode) {
+ dom.box.parentNode.removeChild(dom.box);
+ changed = true;
+ }
+ if (dom.line.parentNode) {
+ dom.line.parentNode.removeChild(dom.line);
+ changed = true;
+ }
+ if (dom.dot.parentNode) {
+ dom.dot.parentNode.removeChild(dom.dot);
changed = true;
}
}
@@ -4715,11 +4672,11 @@ ItemPoint.prototype.repaint = function () {
};
/**
- * Reflow the item: calculate its actual size from the DOM
+ * Reflow the item: calculate its actual size and position from the DOM
* @return {boolean} resized returns true if the axis is resized
* @override
*/
-ItemPoint.prototype.reflow = function () {
+ItemBox.prototype.reflow = function () {
if (this.data.start == undefined) {
throw new Error('Property "start" missing in item ' + this.data.id);
}
@@ -4728,32 +4685,52 @@ ItemPoint.prototype.reflow = function () {
dom = this.dom,
props = this.props,
options = this.options,
- orientation = options.orientation,
start = this.parent.toScreen(this.data.start),
+ align = options && options.align,
+ orientation = options.orientation,
changed = 0,
- top;
+ top,
+ left;
if (dom) {
- 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);
+ changed += update(props.dot, 'width', dom.dot.offsetWidth);
+ changed += update(props.line, 'width', dom.line.offsetWidth);
+ changed += update(props.line, 'width', dom.line.offsetWidth);
+ 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);
+ changed += update(props.line, 'left', start - props.line.width / 2);
+ changed += update(props.dot, 'left', start - props.dot.width / 2);
if (orientation == 'top') {
top = options.margin.axis;
+
+ changed += update(this, 'top', top);
+ changed += update(props.line, 'top', 0);
+ changed += update(props.line, 'height', top);
+ changed += update(props.dot, 'top', -props.dot.height / 2);
}
else {
// default or 'bottom'
var parentHeight = this.parent.height;
- top = Math.max(parentHeight - this.height - options.margin.axis, 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
+ top = parentHeight - this.height - options.margin.axis;
- changed += update(props.dot, 'top', (this.height - props.dot.height) / 2);
+ changed += update(this, 'top', top);
+ changed += update(props.line, 'top', top + this.height);
+ changed += update(props.line, 'height', Math.max(options.margin.axis, 0));
+ changed += update(props.dot, 'top', parentHeight - props.dot.height / 2);
+ }
}
else {
changed += 1;
@@ -4766,24 +4743,27 @@ ItemPoint.prototype.reflow = function () {
* Create an items DOM
* @private
*/
-ItemPoint.prototype._create = function () {
+ItemBox.prototype._create = function () {
var dom = this.dom;
if (!dom) {
this.dom = dom = {};
- // background box
- dom.point = document.createElement('div');
+ // create the box
+ dom.box = document.createElement('DIV');
// className is updated in repaint()
- // contents box, right from the dot
- dom.content = document.createElement('div');
+ // contents box (inside the background box). used for making margins
+ dom.content = document.createElement('DIV');
dom.content.className = 'content';
- dom.point.appendChild(dom.content);
+ dom.box.appendChild(dom.content);
- // dot at start
- dom.dot = document.createElement('div');
- dom.dot.className = 'dot';
- dom.point.appendChild(dom.dot);
+ // line to axis
+ dom.line = document.createElement('DIV');
+ dom.line.className = 'line';
+
+ // dot on axis
+ dom.dot = document.createElement('DIV');
+ dom.dot.className = 'dot';
}
};
@@ -4792,23 +4772,43 @@ ItemPoint.prototype._create = function () {
* range and size of the items itemset
* @override
*/
-ItemPoint.prototype.reposition = function () {
+ItemBox.prototype.reposition = function () {
var dom = this.dom,
- props = this.props;
+ props = this.props,
+ orientation = this.options.orientation;
if (dom) {
- dom.point.style.top = this.top + 'px';
- dom.point.style.left = this.left + 'px';
+ var box = dom.box,
+ line = dom.line,
+ dot = dom.dot;
- dom.content.style.marginLeft = props.content.marginLeft + 'px';
- //dom.content.style.marginRight = props.content.marginRight + 'px'; // TODO
+ box.style.left = this.left + 'px';
+ box.style.top = this.top + 'px';
- dom.dot.style.top = props.dot.top + 'px';
+ 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 = props.line.top + 'px';
+ line.style.top = (this.top + this.height) + 'px';
+ line.style.height = Math.max(props.dot.top - this.top - this.height, 0) + 'px';
+
+ }
+
+ dot.style.left = props.dot.left + 'px';
+ dot.style.top = props.dot.top + 'px';
}
};
// exports
-vis.component.item.point = ItemPoint;
+module.exports = exports = ItemBox;
+
+},{"../../util":8,"./item":19}],17:[function(require,module,exports){
+var util = require('../../util'),
+ Item = require('./item');
/**
* @constructor ItemRange
@@ -5003,179 +5003,36 @@ ItemRange.prototype._create = function () {
dom.box = document.createElement('div');
// className is updated in repaint()
- // contents box
- dom.content = document.createElement('div');
- dom.content.className = 'content';
- dom.box.appendChild(dom.content);
- }
-};
-
-/**
- * Reposition the item, recalculate its left, top, and width, using the current
- * range and size of the items itemset
- * @override
- */
-ItemRange.prototype.reposition = function () {
- 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';
- }
-};
-
-// exports
-vis.component.item.range = ItemRange;
-
-/**
- * Create a timeline visualization
- * @param {HTMLElement} container
- * @param {DataSet | Array | DataTable} [data]
- * @param {Object} [options] See Timeline.setOptions for the available options.
- * @constructor
- */
-function Timeline (container, data, options) {
- var me = this;
- this.options = {
- orientation: 'bottom',
- zoomMin: 10, // milliseconds
- zoomMax: 1000 * 60 * 60 * 24 * 365 * 10000, // milliseconds
- moveable: true,
- zoomable: true
- };
-
- // controller
- this.controller = new Controller();
-
- // main panel
- if (!container) {
- throw new Error('No container element provided');
- }
- this.main = new RootPanel(container, {
- autoResize: false,
- height: function () {
- return me.timeaxis.height + me.itemset.height;
- }
- });
- this.controller.add(this.main);
-
- // 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: reckon with options moveable and zoomable
- this.range.subscribe(this.main, 'move', 'horizontal');
- this.range.subscribe(this.main, 'zoom', 'horizontal');
- this.range.on('rangechange', function () {
- // TODO: fix the delay in reflow/repaint, does not feel snappy
- me.controller.requestReflow();
- });
- this.range.on('rangechanged', function () {
- me.controller.requestReflow();
- });
-
- // TODO: put the listeners in setOptions, be able to dynamically change with options moveable and zoomable
-
- // time axis
- this.timeaxis = new TimeAxis(this.main, [], {
- orientation: this.options.orientation,
- range: this.range
- });
- this.timeaxis.setRange(this.range);
- this.controller.add(this.timeaxis);
-
- // items panel
- this.itemset = new ItemSet(this.main, [this.timeaxis], {
- orientation: this.options.orientation
- });
- this.itemset.setRange(this.range);
- this.controller.add(this.itemset);
-
- // set data
- if (data) {
- this.setData(data);
- }
-
- this.setOptions(options);
-}
-
-/**
- * Set options
- * @param {Object} options TODO: describe the available options
- */
-Timeline.prototype.setOptions = function (options) {
- util.extend(this.options, options);
-
- // update options the timeaxis
- this.timeaxis.setOptions(this.options);
-
- // update options for the range
- this.range.setOptions(this.options);
-
- // update options the itemset
- var top,
- me = this;
- if (this.options.orientation == 'top') {
- top = function () {
- return me.timeaxis.height;
- }
- }
- else {
- top = function () {
- return me.main.height - me.timeaxis.height - me.itemset.height;
- }
- }
- this.itemset.setOptions({
- orientation: this.options.orientation,
- top: top
- });
-
- this.controller.repaint();
+ // contents box
+ dom.content = document.createElement('div');
+ dom.content.className = 'content';
+ dom.box.appendChild(dom.content);
+ }
};
/**
- * Set data
- * @param {DataSet | Array | DataTable} data
+ * Reposition the item, recalculate its left, top, and width, using the current
+ * range and size of the items itemset
+ * @override
*/
-Timeline.prototype.setData = function(data) {
- var dataset = this.itemset.data;
- if (!dataset) {
- // first load of data
- this.itemset.setData(data);
-
- // apply the data range as range
- var dataRange = this.itemset.getDataRange();
+ItemRange.prototype.reposition = function () {
+ var dom = this.dom,
+ props = this.props;
- // add 5% on both sides
- var min = dataRange.min;
- var max = dataRange.max;
- if (min != null && max != null) {
- var interval = (max.valueOf() - min.valueOf());
- min = new Date(min.valueOf() - interval * 0.05);
- max = new Date(max.valueOf() + interval * 0.05);
- }
+ if (dom) {
+ dom.box.style.top = this.top + 'px';
+ dom.box.style.left = this.left + 'px';
+ dom.box.style.width = this.width + 'px';
- // apply range if there is a min or max available
- if (min != null || max != null) {
- this.range.setRange(min, max);
- }
- }
- else {
- // updated data
- this.itemset.setData(data);
+ dom.content.style.left = props.content.left + 'px';
}
};
// exports
-vis.Timeline = Timeline;
+module.exports = exports = ItemRange;
-// moment.js
+},{"../../util":8,"./item":19}],18:[function(require,module,exports){
+(function(){// moment.js
// version : 2.0.0
// author : Tim Wood
// license : MIT
@@ -6576,5 +6433,234 @@ vis.Timeline = Timeline;
}
}).call(this);
+})()
+},{}],13:[function(require,module,exports){
+var util = require('./../util'),
+ moment = require('moment'),
+ Range = require('../range'),
+ Controller = require('../controller'),
+ Component = require('../component/component'),
+ RootPanel = require('../component/rootpanel'),
+ TimeAxis = require('../component/timeaxis'),
+ ItemSet = require('../component/itemset');
+
+/**
+ * Create a timeline visualization
+ * @param {HTMLElement} container
+ * @param {DataSet | Array | DataTable} [data]
+ * @param {Object} [options] See Timeline.setOptions for the available options.
+ * @constructor
+ */
+function Timeline (container, data, options) {
+ var me = this;
+ this.options = {
+ orientation: 'bottom',
+ zoomMin: 10, // milliseconds
+ zoomMax: 1000 * 60 * 60 * 24 * 365 * 10000, // milliseconds
+ moveable: true,
+ zoomable: true
+ };
+
+ // controller
+ this.controller = new Controller();
+
+ // main panel
+ if (!container) {
+ throw new Error('No container element provided');
+ }
+ this.main = new RootPanel(container, {
+ autoResize: false,
+ height: function () {
+ return me.timeaxis.height + me.itemset.height;
+ }
+ });
+ this.controller.add(this.main);
+
+ // 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: reckon with options moveable and zoomable
+ this.range.subscribe(this.main, 'move', 'horizontal');
+ this.range.subscribe(this.main, 'zoom', 'horizontal');
+ this.range.on('rangechange', function () {
+ // TODO: fix the delay in reflow/repaint, does not feel snappy
+ me.controller.requestReflow();
+ });
+ this.range.on('rangechanged', function () {
+ me.controller.requestReflow();
+ });
+
+ // TODO: put the listeners in setOptions, be able to dynamically change with options moveable and zoomable
+
+ // time axis
+ this.timeaxis = new TimeAxis(this.main, [], {
+ orientation: this.options.orientation,
+ range: this.range
+ });
+ this.timeaxis.setRange(this.range);
+ this.controller.add(this.timeaxis);
+
+ // items panel
+ this.itemset = new ItemSet(this.main, [this.timeaxis], {
+ orientation: this.options.orientation
+ });
+ this.itemset.setRange(this.range);
+ this.controller.add(this.itemset);
+
+ // set data
+ if (data) {
+ this.setData(data);
+ }
+
+ this.setOptions(options);
+}
+
+/**
+ * Set options
+ * @param {Object} options TODO: describe the available options
+ */
+Timeline.prototype.setOptions = function (options) {
+ util.extend(this.options, options);
+
+ // update options the timeaxis
+ this.timeaxis.setOptions(this.options);
+
+ // update options for the range
+ this.range.setOptions(this.options);
+
+ // update options the itemset
+ var top,
+ me = this;
+ if (this.options.orientation == 'top') {
+ top = function () {
+ return me.timeaxis.height;
+ }
+ }
+ else {
+ top = function () {
+ return me.main.height - me.timeaxis.height - me.itemset.height;
+ }
+ }
+ this.itemset.setOptions({
+ orientation: this.options.orientation,
+ top: top
+ });
+
+ this.controller.repaint();
+};
+
+/**
+ * Set data
+ * @param {DataSet | Array | DataTable} data
+ */
+Timeline.prototype.setData = function(data) {
+ var dataset = this.itemset.data;
+ if (!dataset) {
+ // first load of data
+ this.itemset.setData(data);
+
+ // apply the data range as range
+ var dataRange = this.itemset.getDataRange();
+
+ // add 5% on both sides
+ var min = dataRange.min;
+ var max = dataRange.max;
+ if (min != null && max != null) {
+ var interval = (max.valueOf() - min.valueOf());
+ min = new Date(min.valueOf() - interval * 0.05);
+ max = new Date(max.valueOf() + interval * 0.05);
+ }
+
+ // apply range if there is a min or max available
+ if (min != null || max != null) {
+ this.range.setRange(min, max);
+ }
+ }
+ else {
+ // updated data
+ this.itemset.setData(data);
+ }
+};
+
+// exports
+module.exports = exports = Timeline;
+
+},{"./../util":8,"../range":5,"../controller":2,"../component/component":9,"../component/rootpanel":11,"../component/timeaxis":14,"../component/itemset":12,"moment":18}],19:[function(require,module,exports){
+var Component = require('../component');
+
+/**
+ * @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
+ * // TODO: describe available options
+ */
+function Item (parent, data, options) {
+ this.parent = parent;
+ this.data = data;
+ this.selected = false;
+ this.visible = true;
+ this.dom = null;
+ this.options = options;
+}
+
+Item.prototype = new Component();
+
+/**
+ * Select current item
+ */
+Item.prototype.select = function () {
+ this.selected = true;
+};
+
+/**
+ * Unselect current item
+ */
+Item.prototype.unselect = function () {
+ this.selected = false;
+};
+
+// exports
+module.exports = exports = Item;
+
+},{"../component":9}]},{},[1])(1)
+});
+;
+/**
+ * AMD module exports
+ */
+if (typeof(define) === 'function') {
+ define(function () {
+ return vis;
+ });
+}
+
+/**
+ * load css from text
+ * @param {String} css Text containing css
+ */
+var loadCss = function (css) {
+ // 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';
+
+ // 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);
+};
+
loadCss("/* vis.js stylesheet */\n\n.graph {\n position: relative;\n border: 1px solid #bfbfbf;\n}\n\n.graph .panel {\n position: absolute;\n}\n\n.graph .itemset {\n position: absolute;\n padding: 0;\n margin: 0;\n overflow: hidden;\n}\n\n.graph .background {\n}\n\n.graph .foreground {\n}\n\n.graph .itemset-axis {\n position: absolute;\n}\n\n.graph .item {\n position: absolute;\n color: #1A1A1A;\n border-color: #97B0F8;\n background-color: #D5DDF6;\n display: inline-block;\n}\n\n.graph .item.selected {\n border-color: #FFC200;\n background-color: #FFF785;\n z-index: 999;\n}\n\n.graph .item.cluster {\n /* TODO: use another color or pattern? */\n background: #97B0F8 url('img/cluster_bg.png');\n color: white;\n}\n.graph .item.cluster.point {\n border-color: #D5DDF6;\n}\n\n.graph .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.graph .item.point {\n background: none;\n}\n\n.graph .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.graph .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.graph .item.range .drag-left {\n cursor: w-resize;\n z-index: 1000;\n}\n\n.graph .item.range .drag-right {\n cursor: e-resize;\n z-index: 1000;\n}\n\n.graph .item.range .content {\n position: relative;\n display: inline-block;\n}\n\n.graph .item.line {\n position: absolute;\n width: 0;\n border-left-width: 1px;\n border-left-style: solid;\n}\n\n.graph .item .content {\n margin: 5px;\n white-space: nowrap;\n overflow: hidden;\n}\n\n/* TODO: better css name, 'graph' is way to generic */\n\n.graph {\n overflow: hidden;\n}\n\n.graph .axis {\n position: relative;\n}\n\n.graph .axis .text {\n position: absolute;\n color: #4d4d4d;\n padding: 3px;\n white-space: nowrap;\n}\n\n.graph .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.graph .axis .grid.vertical {\n position: absolute;\n width: 0;\n border-right: 1px solid;\n}\n\n.graph .axis .grid.horizontal {\n position: absolute;\n left: 0;\n width: 100%;\n height: 0;\n border-bottom: 1px solid;\n}\n\n.graph .axis .grid.minor {\n border-color: #e5e5e5;\n}\n\n.graph .axis .grid.major {\n border-color: #bfbfbf;\n}\n\n");
-})();
\ No newline at end of file
diff --git a/vis.min.js b/vis.min.js
index 0522c60d..3f1f6c2d 100644
--- a/vis.min.js
+++ b/vis.min.js
@@ -4,8 +4,8 @@
*
* A dynamic, browser-based visualization library.
*
- * @version 0.0.5
- * @date 2013-04-24
+ * @version 0.0.6
+ * @date 2013-04-25
*
* @license
* Copyright (C) 2011-2013 Almende B.V, http://almende.com
@@ -22,6 +22,6 @@
* License for the specific language governing permissions and limitations under
* the License.
*/
-(function(){function t(t){var e=this;this.options=t||{},this.data={},this.fieldId=this.options.fieldId||"id",this.fieldTypes={},this.options.fieldTypes&&g.forEach(this.options.fieldTypes,function(t,n){e.fieldTypes[n]="Date"==t||"ISODate"==t||"ASPDate"==t?"Date":t}),this.subscribers={},this.internalIds={}}function e(t,e){this.parent=t,this.options={order:function(t,e){return e.width-t.width||t.left-e.left}},this.ordered=[],this.setOptions(e)}function n(t){this.id=g.randomUUID(),this.start=0,this.end=0,this.options={min:null,max:null,zoomMin:null,zoomMax:null},this.setOptions(t),this.listeners=[]}function i(){this.id=g.randomUUID(),this.components={},this.repaintTimer=void 0,this.reflowTimer=void 0}function o(){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 r(t,e,n){this.id=g.randomUUID(),this.parent=t,this.depends=e,this.options={},this.setOptions(n)}function s(t,e){this.id=g.randomUUID(),this.container=t,this.options={autoResize:!0},this.listeners={},this.setOptions(e)}function a(t,e,n){this.id=g.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={orientation:"bottom",showMinorLabels:!0,showMajorLabels:!0},this.conversion=null,this.range=null,this.setOptions(n)}function h(t,n,i){this.id=g.randomUUID(),this.parent=t,this.depends=n,this.options={style:"box",align:"center",orientation:"bottom",margin:{axis:20,item:10},padding:5},this.dom={};var o=this;this.data=null,this.range=null,this.listeners={add:function(t,e){o._onAdd(e.items)},update:function(t,e){o._onUpdate(e.items)},remove:function(t,e){o._onRemove(e.items)}},this.items={},this.queue={},this.stack=new e(this),this.conversion=null,this.setOptions(i)}function c(t,e,n){this.parent=t,this.data=e,this.selected=!1,this.visible=!0,this.dom=null,this.options=n}function p(t,e,n){this.props={dot:{left:0,top:0,width:0,height:0},line:{top:0,left:0,width:0,height:0}},c.call(this,t,e,n)}function u(t,e,n){this.props={dot:{top:0,width:0,height:0},content:{height:0,marginLeft:0}},c.call(this,t,e,n)}function d(t,e,n){this.props={content:{left:0,width:0}},c.call(this,t,e,n)}function l(t,e,o){var r=this;if(this.options={orientation:"bottom",zoomMin:10,zoomMax:31536e10,moveable:!0,zoomable:!0},this.controller=new i,!t)throw Error("No container element provided");this.main=new s(t,{autoResize:!1,height:function(){return r.timeaxis.height+r.itemset.height}}),this.controller.add(this.main);var c=moment().hours(0).minutes(0).seconds(0).milliseconds(0);this.range=new n({start:c.clone().add("days",-3).valueOf(),end:c.clone().add("days",4).valueOf()}),this.range.subscribe(this.main,"move","horizontal"),this.range.subscribe(this.main,"zoom","horizontal"),this.range.on("rangechange",function(){r.controller.requestReflow()}),this.range.on("rangechanged",function(){r.controller.requestReflow()}),this.timeaxis=new a(this.main,[],{orientation:this.options.orientation,range:this.range}),this.timeaxis.setRange(this.range),this.controller.add(this.timeaxis),this.itemset=new h(this.main,[this.timeaxis],{orientation:this.options.orientation}),this.itemset.setRange(this.range),this.controller.add(this.itemset),e&&this.setData(e),this.setOptions(o)}var f={component:{item:{}}};"undefined"!=typeof exports&&(exports=f),"undefined"!=typeof module&&(module.exports=f),"function"==typeof define&&define(function(){return f}),"undefined"!=typeof window&&(window.vis=f);var m=function(t){document.getElementsByTagName("script");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)},g={};g.isNumber=function(t){return t instanceof Number||"number"==typeof t},g.isString=function(t){return t instanceof String||"string"==typeof t},g.isDate=function(t){if(t instanceof Date)return!0;if(g.isString(t)){var e=v.exec(t);if(e)return!0;if(!isNaN(Date.parse(t)))return!0}return!1},g.isDataTable=function(t){return"undefined"!=typeof google&&google.visualization&&google.visualization.DataTable&&t instanceof google.visualization.DataTable},g.randomUUID=function(){var t=function(){return Math.floor(65536*Math.random()).toString(16)};return t()+t()+"-"+t()+"-"+t()+"-"+t()+"-"+t()+t()+t()},g.extend=function(t,e){for(var n in e)e.hasOwnProperty(n)&&(t[n]=e[n]);return t},g.cast=function(t,e){if(void 0===t)return void 0;if(null===t)return null;if(!e)return t;if("function"==typeof e)return e(t);switch(e){case"boolean":case"Boolean":return Boolean(t);case"number":case"Number":return Number(t);case"string":case"String":return t+"";case"Date":if(g.isNumber(t))return new Date(t);if(t instanceof Date)return new Date(t.valueOf());if(g.isString(t)){var n=v.exec(t);return n?new Date(Number(n[1])):moment(t).toDate()}throw Error("Cannot cast object of type "+g.getType(t)+" to type Date");case"ISODate":if(t instanceof Date)return t.toISOString();if(g.isNumber(t)||g.isString(t))return moment(t).toDate().toISOString();throw Error("Cannot cast object of type "+g.getType(t)+" to type ISODate");case"ASPDate":if(t instanceof Date)return"/Date("+t.valueOf()+")/";if(g.isNumber(t)||g.isString(t))return"/Date("+moment(t).valueOf()+")/";throw Error("Cannot cast object of type "+g.getType(t)+" to type ASPDate");default:throw Error("Cannot cast object of type "+g.getType(t)+' to type "'+e+'"')}};var v=/^\/?Date\((\-?\d+)/i;if(g.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},g.getAbsoluteLeft=function(t){for(var e=document.documentElement,n=document.body,i=t.offsetLeft,o=t.offsetParent;null!=o&&o!=n&&o!=e;)i+=o.offsetLeft,i-=o.scrollLeft,o=o.offsetParent;return i},g.getAbsoluteTop=function(t){for(var e=document.documentElement,n=document.body,i=t.offsetTop,o=t.offsetParent;null!=o&&o!=n&&o!=e;)i+=o.offsetTop,i-=o.scrollTop,o=o.offsetParent;return i},g.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 n=document.documentElement,i=document.body;return e+(n&&n.scrollTop||i&&i.scrollTop||0)-(n&&n.clientTop||i&&i.clientTop||0)},g.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 n=document.documentElement,i=document.body;return e+(n&&n.scrollLeft||i&&i.scrollLeft||0)-(n&&n.clientLeft||i&&i.clientLeft||0)},g.addClassName=function(t,e){var n=t.className.split(" ");-1==n.indexOf(e)&&(n.push(e),t.className=n.join(" "))},g.removeClassName=function(t,e){var n=t.className.split(" "),i=n.indexOf(e);-1!=i&&(n.splice(i,1),t.className=n.join(" "))},g.forEach=function(t,e){if(t instanceof Array)t.forEach(e);else for(var n in t)t.hasOwnProperty(n)&&e(t[n],n,t)},g.updateProperty=function(t,e,n){return t[e]!==n?(t[e]=n,!0):!1},g.addEventListener=function(t,e,n,i){t.addEventListener?(void 0===i&&(i=!1),"mousewheel"===e&&navigator.userAgent.indexOf("Firefox")>=0&&(e="DOMMouseScroll"),t.addEventListener(e,n,i)):t.attachEvent("on"+e,n)},g.removeEventListener=function(t,e,n,i){t.removeEventListener?(void 0===i&&(i=!1),"mousewheel"===e&&navigator.userAgent.indexOf("Firefox")>=0&&(e="DOMMouseScroll"),t.removeEventListener(e,n,i)):t.detachEvent("on"+e,n)},g.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},g.stopPropagation=function(t){t||(t=window.event),t.stopPropagation?t.stopPropagation():t.cancelBubble=!0},g.preventDefault=function(t){t||(t=window.event),t.preventDefault?t.preventDefault():t.returnValue=!1},g.option={},g.option.asBoolean=function(t,e){return"function"==typeof t&&(t=t()),null!=t?0!=t:e||null},g.option.asNumber=function(t,e){return"function"==typeof t&&(t=t()),null!=t?Number(t):e||null},g.option.asString=function(t,e){return"function"==typeof t&&(t=t()),null!=t?t+"":e||null},g.option.asSize=function(t,e){return"function"==typeof t&&(t=t()),g.isString(t)?t:g.isNumber(t)?t+"px":e||null},g.option.asElement=function(t,e){return"function"==typeof t&&(t=t()),t||e||null},!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(y){}}Array.prototype.forEach||(Array.prototype.forEach=function(t,e){for(var n=0,i=this.length;i>n;++n)t.call(e||this,this[n],n,this)}),Array.prototype.map||(Array.prototype.map=function(t,e){var n,i,o;if(null==this)throw new TypeError(" this is null or not defined");var r=Object(this),s=r.length>>>0;if("function"!=typeof t)throw new TypeError(t+" is not a function");for(e&&(n=e),i=Array(s),o=0;s>o;){var a,h;o in r&&(a=r[o],h=t.call(n,a,o,r),i[o]=h),o++}return i}),Array.prototype.filter||(Array.prototype.filter=function(t){"use strict";if(null==this)throw new TypeError;var e=Object(this),n=e.length>>>0;if("function"!=typeof t)throw new TypeError;for(var i=[],o=arguments[1],r=0;n>r;r++)if(r in e){var s=e[r];t.call(o,s,r,e)&&i.push(s)}return i}),Object.keys||(Object.keys=function(){var t=Object.prototype.hasOwnProperty,e=!{toString:null}.propertyIsEnumerable("toString"),n=["toString","toLocaleString","valueOf","hasOwnProperty","isPrototypeOf","propertyIsEnumerable","constructor"],i=n.length;return function(o){if("object"!=typeof o&&"function"!=typeof o||null===o)throw new TypeError("Object.keys called on non-object");var r=[];for(var s in o)t.call(o,s)&&r.push(s);if(e)for(var a=0;i>a;a++)t.call(o,n[a])&&r.push(n[a]);return r}}()),Array.isArray||(Array.isArray=function(t){return"[object Array]"===Object.prototype.toString.call(t)}),f.util=g;var S={listeners:[],indexOf:function(t){for(var e=this.listeners,n=0,i=this.listeners.length;i>n;n++){var o=e[n];if(o&&o.object==t)return n}return-1},addListener:function(t,e,n){var i=this.indexOf(t),o=this.listeners[i];o||(o={object:t,events:{}},this.listeners.push(o));var r=o.events[e];r||(r=[],o.events[e]=r),-1==r.indexOf(n)&&r.push(n)},removeListener:function(t,e,n){var i=this.indexOf(t),o=this.listeners[i];if(o){var r=o.events[e];r&&(i=r.indexOf(n),-1!=i&&r.splice(i,1),0==r.length&&delete o.events[e]);var s=0,a=o.events;for(var h in a)a.hasOwnProperty(h)&&s++;0==s&&delete this.listeners[i]}},removeAllListeners:function(){this.listeners=[]},trigger:function(t,e,n){var i=this.indexOf(t),o=this.listeners[i];if(o){var r=o.events[e];if(r)for(var s=0,a=r.length;a>s;s++)r[s](n)}}};f.events=S,TimeStep=function(t,e,n){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,n)},TimeStep.SCALE={MILLISECOND:1,SECOND:2,MINUTE:3,HOUR:4,DAY:5,WEEKDAY:6,MONTH:7,YEAR:8},TimeStep.prototype.setRange=function(t,e,n){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(n))},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,n=2592e6,i=864e5,o=36e5,r=6e4,s=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*n>t&&(this.scale=TimeStep.SCALE.MONTH,this.step=3),n>t&&(this.scale=TimeStep.SCALE.MONTH,this.step=1),5*i>t&&(this.scale=TimeStep.SCALE.DAY,this.step=5),2*i>t&&(this.scale=TimeStep.SCALE.DAY,this.step=2),i>t&&(this.scale=TimeStep.SCALE.DAY,this.step=1),i/2>t&&(this.scale=TimeStep.SCALE.WEEKDAY,this.step=1),4*o>t&&(this.scale=TimeStep.SCALE.HOUR,this.step=4),o>t&&(this.scale=TimeStep.SCALE.HOUR,this.step=1),15*r>t&&(this.scale=TimeStep.SCALE.MINUTE,this.step=15),10*r>t&&(this.scale=TimeStep.SCALE.MINUTE,this.step=10),5*r>t&&(this.scale=TimeStep.SCALE.MINUTE,this.step=5),r>t&&(this.scale=TimeStep.SCALE.MINUTE,this.step=1),15*s>t&&(this.scale=TimeStep.SCALE.SECOND,this.step=15),10*s>t&&(this.scale=TimeStep.SCALE.SECOND,this.step=10),5*s>t&&(this.scale=TimeStep.SCALE.SECOND,this.step=5),s>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 n=this.step>5?this.step/2:1;t.setMilliseconds(Math.round(t.getMilliseconds()/n)*n)}},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 moment(t).format("SSS");case TimeStep.SCALE.SECOND:return moment(t).format("s");case TimeStep.SCALE.MINUTE:return moment(t).format("HH:mm");case TimeStep.SCALE.HOUR:return moment(t).format("HH:mm");case TimeStep.SCALE.WEEKDAY:return moment(t).format("ddd D");case TimeStep.SCALE.DAY:return moment(t).format("D");case TimeStep.SCALE.MONTH:return moment(t).format("MMM");case TimeStep.SCALE.YEAR:return moment(t).format("YYYY");default:return""}},TimeStep.prototype.getLabelMajor=function(t){switch(void 0==t&&(t=this.current),this.scale){case TimeStep.SCALE.MILLISECOND:return moment(t).format("HH:mm:ss");case TimeStep.SCALE.SECOND:return moment(t).format("D MMMM HH:mm");case TimeStep.SCALE.MINUTE:case TimeStep.SCALE.HOUR:return moment(t).format("ddd D MMMM");case TimeStep.SCALE.WEEKDAY:case TimeStep.SCALE.DAY:return moment(t).format("MMMM YYYY");case TimeStep.SCALE.MONTH:return moment(t).format("YYYY");case TimeStep.SCALE.YEAR:return"";default:return""}},f.TimeStep=TimeStep,t.prototype.subscribe=function(t,e,n){var i=this.subscribers[t];i||(i=[],this.subscribers[t]=i),i.push({id:n?n+"":null,callback:e})},t.prototype.unsubscribe=function(t,e){var n=this.subscribers[t];n&&(this.subscribers[t]=n.filter(function(t){return t.callback!=e}))},t.prototype._trigger=function(t,e,n){if("*"==t)throw Error("Cannot trigger event *");var i=[];t in this.subscribers&&(i=i.concat(this.subscribers[t])),"*"in this.subscribers&&(i=i.concat(this.subscribers["*"])),i.forEach(function(i){i.id!=n&&i.callback&&i.callback(t,e,n||null)})},t.prototype.add=function(t,e){var n,i=[],o=this;if(t instanceof Array)t.forEach(function(t){var e=o._addItem(t);i.push(e)});else if(g.isDataTable(t))for(var r=this._getColumnNames(t),s=0,a=t.getNumberOfRows();a>s;s++){var h={};r.forEach(function(e,n){h[e]=t.getValue(s,n)}),n=o._addItem(h),i.push(n)}else{if(!(t instanceof Object))throw Error("Unknown dataType");n=o._addItem(t),i.push(n)}this._trigger("add",{items:i},e)},t.prototype.update=function(t,e){var n,i=[],o=this;if(t instanceof Array)t.forEach(function(t){var e=o._updateItem(t);i.push(e)});else if(g.isDataTable(t))for(var r=this._getColumnNames(t),s=0,a=t.getNumberOfRows();a>s;s++){var h={};r.forEach(function(e,n){h[e]=t.getValue(s,n)}),n=o._updateItem(h),i.push(n)}else{if(!(t instanceof Object))throw Error("Unknown dataType");n=o._updateItem(t),i.push(n)}this._trigger("update",{items:i},e)},t.prototype.get=function(t,e,n){var i=this;"Object"==g.getType(t)&&(n=e,e=t,t=void 0);var o={};this.options&&this.options.fieldTypes&&g.forEach(this.options.fieldTypes,function(t,e){o[e]=t}),e&&e.fieldTypes&&g.forEach(e.fieldTypes,function(t,e){o[e]=t});var r,s=e?e.fields:void 0;if(e&&e.type){if(r="DataTable"==e.type?"DataTable":"Array",n&&r!=g.getType(n))throw Error('Type of parameter "data" ('+g.getType(n)+") "+"does not correspond with specified options.type ("+e.type+")");if("DataTable"==r&&!g.isDataTable(n))throw Error('Parameter "data" must be a DataTable when options.type is "DataTable"')}else r=n?"DataTable"==g.getType(n)?"DataTable":"Array":"Array";if("DataTable"==r){var a=this._getColumnNames(n);if(void 0==t)g.forEach(this.data,function(t){i._appendRow(n,a,i._castItem(t))});else if(g.isNumber(t)||g.isString(t)){var h=i._castItem(i.data[t],o,s);this._appendRow(n,a,h)}else{if(!(t instanceof Array))throw new TypeError('Parameter "ids" must be undefined, a String, Number, or Array');t.forEach(function(t){var e=i._castItem(i.data[t],o,s);i._appendRow(n,a,e)})}}else if(n=n||[],void 0==t)g.forEach(this.data,function(t){n.push(i._castItem(t,o,s))});else{if(g.isNumber(t)||g.isString(t))return this._castItem(i.data[t],o,s);if(!(t instanceof Array))throw new TypeError('Parameter "ids" must be undefined, a String, Number, or Array');t.forEach(function(t){n.push(i._castItem(i.data[t],o,s))})}return n},t.prototype.remove=function(t,e){var n=[],i=this;if(g.isNumber(t)||g.isString(t))delete this.data[t],delete this.internalIds[t],n.push(t);else if(t instanceof Array)t.forEach(function(t){i.remove(t)}),n=n.concat(t);else if(t instanceof Object)for(var o in this.data)this.data.hasOwnProperty(o)&&this.data[o]==t&&(delete this.data[o],delete this.internalIds[o],n.push(o));this._trigger("remove",{items:n},e)},t.prototype.clear=function(t){var e=Object.keys(this.data);this.data={},this.internalIds={},this._trigger("remove",{items:e},t)},t.prototype.max=function(t){var e=this.data,n=Object.keys(e),i=null,o=null;return n.forEach(function(n){var r=e[n],s=r[t];null!=s&&(!i||s>o)&&(i=r,o=s)}),i},t.prototype.min=function(t){var e=this.data,n=Object.keys(e),i=null,o=null;return n.forEach(function(n){var r=e[n],s=r[t];null!=s&&(!i||o>s)&&(i=r,o=s)}),i},t.prototype._addItem=function(t){var e=t[this.fieldId];void 0==e&&(e=g.randomUUID(),t[this.fieldId]=e,this.internalIds[e]=t);var n={};for(var i in t)if(t.hasOwnProperty(i)){var o=this.fieldTypes[i];n[i]=g.cast(t[i],o)}return this.data[e]=n,e},t.prototype._castItem=function(t,e,n){var i,o=this.fieldId,r=this.internalIds;return t?(i={},e=e||{},n?g.forEach(t,function(t,o){-1!=n.indexOf(o)&&(i[o]=g.cast(t,e[o]))}):g.forEach(t,function(t,n){n==o&&t in r||(i[n]=g.cast(t,e[n]))})):i=null,i},t.prototype._updateItem=function(t){var e=t[this.fieldId];if(void 0==e)throw Error("Item has no id (item: "+JSON.stringify(t)+")");var n=this.data[e];if(n){for(var i in t)if(t.hasOwnProperty(i)){var o=this.fieldTypes[i];n[i]=g.cast(t[i],o)}}else this._addItem(t);return e},t.prototype._getColumnNames=function(t){for(var e=[],n=0,i=t.getNumberOfColumns();i>n;n++)e[n]=t.getColumnId(n)||t.getColumnLabel(n);return e},t.prototype._appendRow=function(t,e,n){var i=t.addRow();e.forEach(function(e,o){t.setValue(i,o,n[e])})},f.DataSet=t,e.prototype.setOptions=function(t){g.extend(this.options,t)},e.prototype.update=function(){this._order(),this._stack()},e.prototype._order=function(){var t=this.parent.items;if(!t)throw Error("Cannot stack items: parent does not contain items");var e=[],n=0;g.forEach(t,function(t){e[n]=t,n++});var i=this.options.order;if("function"!=typeof this.options.order)throw Error("Option order must be a function");e.sort(i),this.ordered=e},e.prototype._stack=function(){var t,e,n=this.ordered,i=this.options,o="top"==i.orientation,r=i.margin&&i.margin.item||0;for(t=0,e=n.length;e>t;t++){var s=n[t],a=null;do a=this.checkOverlap(n,t,0,t-1,r),null!=a&&(s.top=o?a.top+a.height+r:a.top-s.height-r);while(a)}},e.prototype.checkOverlap=function(t,e,n,i,o){for(var r=this.collision,s=t[e],a=i;a>=n;a--){var h=t[a];if(r(s,h,o)&&a!=e)return h}return null},e.prototype.collision=function(t,e,n){return t.left-ne.left&&t.top-ne.top},f.Stack=e,n.prototype.setOptions=function(t){g.extend(this.options,t),(null!=t.start||null!=t.end)&&this.setRange(t.start,t.end)},n.prototype.subscribe=function(t,e,n){var i,o=this;if("horizontal"!=n&&"vertical"!=n)throw new TypeError('Unknown direction "'+n+'". '+'Choose "horizontal" or "vertical".');if("move"==e)i={component:t,event:e,direction:n,callback:function(t){o._onMouseDown(t,i)},params:{}},t.on("mousedown",i.callback),o.listeners.push(i);else{if("zoom"!=e)throw new TypeError('Unknown event "'+e+'". '+'Choose "move" or "zoom".');i={component:t,event:e,direction:n,callback:function(t){o._onMouseWheel(t,i)},params:{}},t.on("mousewheel",i.callback),o.listeners.push(i)}},n.prototype.on=function(t,e){S.addListener(this,t,e)},n.prototype._trigger=function(t){S.trigger(this,t,{start:this.start,end:this.end})},n.prototype.setRange=function(t,e){var n=this._applyRange(t,e);n&&(this._trigger("rangechange"),this._trigger("rangechanged"))},n.prototype._applyRange=function(t,e){var n,i=null!=t?g.cast(t,"Number"):this.start,o=null!=e?g.cast(e,"Number"):this.end;if(isNaN(i))throw Error('Invalid start "'+t+'"');if(isNaN(o))throw Error('Invalid end "'+e+'"');if(i>o&&(o=i),null!=this.options.min){var r=this.options.min.valueOf();r>i&&(n=r-i,i+=n,o+=n)}if(null!=this.options.max){var s=this.options.max.valueOf();o>s&&(n=o-s,i-=n,o-=n)}if(null!=this.options.zoomMin){var a=this.options.zoomMin.valueOf();0>a&&(a=0),a>o-i&&(this.end-this.start>a?(n=a-(o-i),i-=n/2,o+=n/2):(i=this.start,o=this.end))}if(null!=this.options.zoomMax){var h=this.options.zoomMax.valueOf();0>h&&(h=0),o-i>h&&(h>this.end-this.start?(n=o-i-h,i+=n/2,o-=n/2):(i=this.start,o=this.end))}var c=this.start!=i||this.end!=o;return this.start=i,this.end=o,c},n.prototype.getRange=function(){return{start:this.start,end:this.end}},n.prototype.conversion=function(t){return this.start,this.end,n.conversion(this.start,this.end,t)},n.conversion=function(t,e,n){return 0!=n&&0!=e-t?{offset:t,factor:n/(e-t)}:{offset:0,factor:1}},n.prototype._onMouseDown=function(t,e){t=t||window.event;var n=e.params,i=t.which?1==t.which:1==t.button;if(i){n.mouseX=g.getPageX(t),n.mouseY=g.getPageY(t),n.previousLeft=0,n.previousOffset=0,n.moved=!1,n.start=this.start,n.end=this.end;var o=e.component.frame;o&&(o.style.cursor="move");var r=this;n.onMouseMove||(n.onMouseMove=function(t){r._onMouseMove(t,e)},g.addEventListener(document,"mousemove",n.onMouseMove)),n.onMouseUp||(n.onMouseUp=function(t){r._onMouseUp(t,e)},g.addEventListener(document,"mouseup",n.onMouseUp)),g.preventDefault(t)}},n.prototype._onMouseMove=function(t,e){t=t||window.event;var n=e.params,i=g.getPageX(t),o=g.getPageY(t);void 0==n.mouseX&&(n.mouseX=i),void 0==n.mouseY&&(n.mouseY=o);var r=i-n.mouseX,s=o-n.mouseY,a="horizontal"==e.direction?r:s;Math.abs(a)>=1&&(n.moved=!0);var h=n.end-n.start,c="horizontal"==e.direction?e.component.width:e.component.height,p=-a/c*h;this._applyRange(n.start+p,n.end+p),this._trigger("rangechange"),g.preventDefault(t)},n.prototype._onMouseUp=function(t,e){t=t||window.event;var n=e.params;e.component.frame&&(e.component.frame.style.cursor="auto"),n.onMouseMove&&(g.removeEventListener(document,"mousemove",n.onMouseMove),n.onMouseMove=null),n.onMouseUp&&(g.removeEventListener(document,"mouseup",n.onMouseUp),n.onMouseUp=null),n.moved&&this._trigger("rangechanged")},n.prototype._onMouseWheel=function(t,e){t=t||window.event;var n=0;if(t.wheelDelta?n=t.wheelDelta/120:t.detail&&(n=-t.detail/3),n){var i=this,o=function(){var o=n/5,r=null,s=e.component.frame;if(s){var a,h;if("horizontal"==e.direction){a=e.component.width,h=i.conversion(a);var c=g.getAbsoluteLeft(s),p=g.getPageX(t);r=(p-c)/h.factor+h.offset}else{a=e.component.height,h=i.conversion(a);var u=g.getAbsoluteTop(s),d=g.getPageY(t);r=(u+a-d-u)/h.factor+h.offset}}i.zoom(o,r)};o()}g.preventDefault(t)},n.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 n=this.start-e,i=this.end-e,o=this.start-n*t,r=this.end-i*t;this.setRange(o,r)},n.prototype.move=function(t){var e=this.end-this.start,n=this.start+e*t,i=this.end+e*t;this.start=n,this.end=i},f.Range=n,i.prototype.add=function(t){if(void 0==t.id)throw Error("Component has no field id");if(!(t instanceof o||t instanceof i))throw new TypeError("Component must be an instance of prototype Component or Controller");t.controller=this,this.components[t.id]=t},i.prototype.requestReflow=function(){if(!this.reflowTimer){var t=this;this.reflowTimer=setTimeout(function(){t.reflowTimer=void 0,t.reflow()},0)}},i.prototype.requestRepaint=function(){if(!this.repaintTimer){var t=this;this.repaintTimer=setTimeout(function(){t.repaintTimer=void 0,t.repaint()},0)}},i.prototype.repaint=function(){function t(i,o){o in n||(i.depends&&i.depends.forEach(function(e){t(e,e.id)}),i.parent&&t(i.parent,i.parent.id),e=i.repaint()||e,n[o]=!0)}var e=!1;this.repaintTimer&&(clearTimeout(this.repaintTimer),this.repaintTimer=void 0);var n={};g.forEach(this.components,t),e&&this.reflow()},i.prototype.reflow=function(){function t(i,o){o in n||(i.depends&&i.depends.forEach(function(e){t(e,e.id)}),i.parent&&t(i.parent,i.parent.id),e=i.reflow()||e,n[o]=!0)}var e=!1;this.reflowTimer&&(clearTimeout(this.reflowTimer),this.reflowTimer=void 0);var n={};g.forEach(this.components,t),e&&this.repaint()},f.Controller=i,o.prototype.setOptions=function(t){t&&g.extend(this.options,t),this.controller&&(this.requestRepaint(),this.requestReflow())},o.prototype.getContainer=function(){return null},o.prototype.getFrame=function(){return this.frame},o.prototype.repaint=function(){return!1},o.prototype.reflow=function(){return!1},o.prototype.requestRepaint=function(){if(!this.controller)throw Error("Cannot request a repaint: no controller configured");this.controller.requestRepaint()
-},o.prototype.requestReflow=function(){if(!this.controller)throw Error("Cannot request a reflow: no controller configured");this.controller.requestReflow()},o.prototype.on=function(t,e){if(!this.parent)throw Error("Cannot attach event: no root panel found");this.parent.on(t,e)},f.component.Component=o,r.prototype=new o,r.prototype.getContainer=function(){return this.frame},r.prototype.repaint=function(){var t=0,e=g.updateProperty,n=g.option.asSize,i=this.options,o=this.frame;if(o||(o=document.createElement("div"),o.className="panel",i.className&&("function"==typeof i.className?g.addClassName(o,i.className()+""):g.addClassName(o,i.className+"")),this.frame=o,t+=1),!o.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(o),t+=1}return t+=e(o.style,"top",n(i.top,"0px")),t+=e(o.style,"left",n(i.left,"0px")),t+=e(o.style,"width",n(i.width,"100%")),t+=e(o.style,"height",n(i.height,"100%")),t>0},r.prototype.reflow=function(){var t=0,e=g.updateProperty,n=this.frame;return n?(t+=e(this,"top",n.offsetTop),t+=e(this,"left",n.offsetLeft),t+=e(this,"width",n.offsetWidth),t+=e(this,"height",n.offsetHeight)):t+=1,t>0},f.component.Panel=r,s.prototype=new r,s.prototype.setOptions=function(t){g.extend(this.options,t),this.options.autoResize?this._watch():this._unwatch()},s.prototype.repaint=function(){var t=0,e=g.updateProperty,n=g.option.asSize,i=this.options,o=this.frame;if(o||(o=document.createElement("div"),o.className="graph panel",i.className&&g.addClassName(o,g.option.asString(i.className)),this.frame=o,t+=1),!o.parentNode){if(!this.container)throw Error("Cannot repaint root panel: no container attached");this.container.appendChild(o),t+=1}return t+=e(o.style,"top",n(i.top,"0px")),t+=e(o.style,"left",n(i.left,"0px")),t+=e(o.style,"width",n(i.width,"100%")),t+=e(o.style,"height",n(i.height,"100%")),this._updateEventEmitters(),t>0},s.prototype.reflow=function(){var t=0,e=g.updateProperty,n=this.frame;return n?(t+=e(this,"top",n.offsetTop),t+=e(this,"left",n.offsetLeft),t+=e(this,"width",n.offsetWidth),t+=e(this,"height",n.offsetHeight)):t+=1,t>0},s.prototype._watch=function(){var t=this;this._unwatch();var e=function(){return t.options.autoResize?(t.frame&&(t.frame.clientWidth!=t.width||t.frame.clientHeight!=t.height)&&t.requestReflow(),void 0):(t._unwatch(),void 0)};g.addEventListener(window,"resize",e),this.watchTimer=setInterval(e,1e3)},s.prototype._unwatch=function(){this.watchTimer&&(clearInterval(this.watchTimer),this.watchTimer=void 0)},s.prototype.on=function(t,e){var n=this.listeners[t];n||(n=[],this.listeners[t]=n),n.push(e),this._updateEventEmitters()},s.prototype._updateEventEmitters=function(){if(this.listeners){var t=this;g.forEach(this.listeners,function(e,n){if(t.emitters||(t.emitters={}),!(n in t.emitters)){var i=t.frame;if(i){var o=function(t){e.forEach(function(e){e(t)})};t.emitters[n]=o,g.addEventListener(i,n,o)}}})}},f.component.RootPanel=s,a.prototype=new o,a.prototype.setOptions=function(t){g.extend(this.options,t)},a.prototype.setRange=function(t){if(!(t instanceof n||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},a.prototype.toTime=function(t){var e=this.conversion;return new Date(t/e.factor+e.offset)},a.prototype.toScreen=function(t){var e=this.conversion;return(t.valueOf()-e.offset)*e.factor},a.prototype.repaint=function(){var t=0,e=g.updateProperty,n=g.option.asSize,i=this.options,o=this.props,r=this.step,s=this.frame;if(s||(s=document.createElement("div"),this.frame=s,t+=1),s.className="axis "+i.orientation,!s.parentNode){if(!this.parent)throw Error("Cannot repaint time axis: no parent attached");var a=this.parent.getContainer();if(!a)throw Error("Cannot repaint time axis: parent has no container element");a.appendChild(s),t+=1}var h=s.parentNode;if(h){var c=s.nextSibling;h.removeChild(s);var p=i.orientation,u="bottom"==p&&this.props.parentHeight&&this.height?this.props.parentHeight-this.height+"px":"0px";if(t+=e(s.style,"top",n(i.top,u)),t+=e(s.style,"left",n(i.left,"0px")),t+=e(s.style,"width",n(i.width,"100%")),t+=e(s.style,"height",n(i.height,this.height+"px")),this._repaintMeasureChars(),this.step){this._repaintStart(),r.first();for(var d=void 0,l=0;r.hasNext()&&1e3>l;){l++;var f=r.getCurrent(),m=this.toScreen(f),v=r.isMajor();i.showMinorLabels&&this._repaintMinorText(m,r.getLabelMinor()),v&&i.showMajorLabels?(m>0&&(void 0==d&&(d=m),this._repaintMajorText(m,r.getLabelMajor())),this._repaintMajorLine(m)):this._repaintMinorLine(m),r.next()}if(i.showMajorLabels){var y=this.toTime(0),S=r.getLabelMajor(y),T=S.length*(o.majorCharWidth||10)+10;(void 0==d||d>T)&&this._repaintMajorText(0,S)}this._repaintEnd()}this._repaintLine(),c?h.insertBefore(s,c):h.appendChild(s)}return t>0},a.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=[]},a.prototype._repaintEnd=function(){g.forEach(this.dom.redundant,function(t){for(;t.length;){var e=t.pop();e&&e.parentNode&&e.parentNode.removeChild(e)}})},a.prototype._repaintMinorText=function(t,e){var n=this.dom.redundant.minorTexts.shift();if(!n){var i=document.createTextNode("");n=document.createElement("div"),n.appendChild(i),n.className="text minor",this.frame.appendChild(n)}this.dom.minorTexts.push(n),n.childNodes[0].nodeValue=e,n.style.left=t+"px",n.style.top=this.props.minorLabelTop+"px"},a.prototype._repaintMajorText=function(t,e){var n=this.dom.redundant.majorTexts.shift();if(!n){var i=document.createTextNode(e);n=document.createElement("div"),n.className="text major",n.appendChild(i),this.frame.appendChild(n)}this.dom.majorTexts.push(n),n.childNodes[0].nodeValue=e,n.style.top=this.props.majorLabelTop+"px",n.style.left=t+"px"},a.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 n=this.props;e.style.top=n.minorLineTop+"px",e.style.height=n.minorLineHeight+"px",e.style.left=t-n.minorLineWidth/2+"px"},a.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 n=this.props;e.style.top=n.majorLineTop+"px",e.style.left=t-n.majorLineWidth/2+"px",e.style.height=n.majorLineHeight+"px"},a.prototype._repaintLine=function(){var t=this.dom.line,e=this.frame,n=this.options;n.showMinorLabels||n.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)},a.prototype._repaintMeasureChars=function(){var t,e=this.dom;if(!e.characterMinor){t=document.createTextNode("0");var n=document.createElement("DIV");n.className="text minor measure",n.appendChild(t),this.frame.appendChild(n),e.measureCharMinor=n}if(!e.characterMajor){t=document.createTextNode("0");var i=document.createElement("DIV");i.className="text major measure",i.appendChild(t),this.frame.appendChild(i),e.measureCharMajor=i}},a.prototype.reflow=function(){var t=0,e=g.updateProperty,n=this.frame,i=this.range;if(!i)throw Error("Cannot repaint time axis: no range configured");if(n){t+=e(this,"top",n.offsetTop),t+=e(this,"left",n.offsetLeft);var o=this.props,r=this.options.showMinorLabels,s=this.options.showMajorLabels,a=this.dom.measureCharMinor,h=this.dom.measureCharMajor;a&&(o.minorCharHeight=a.clientHeight,o.minorCharWidth=a.clientWidth),h&&(o.majorCharHeight=h.clientHeight,o.majorCharWidth=h.clientWidth);var c=n.parentNode?n.parentNode.offsetHeight:0;switch(c!=o.parentHeight&&(o.parentHeight=c,t+=1),this.options.orientation){case"bottom":o.minorLabelHeight=r?o.minorCharHeight:0,o.majorLabelHeight=s?o.majorCharHeight:0,o.minorLabelTop=0,o.majorLabelTop=o.minorLabelTop+o.minorLabelHeight,o.minorLineTop=-this.top,o.minorLineHeight=Math.max(this.top+o.majorLabelHeight,0),o.minorLineWidth=1,o.majorLineTop=-this.top,o.majorLineHeight=Math.max(this.top+o.minorLabelHeight+o.majorLabelHeight,0),o.majorLineWidth=1,o.lineTop=0;break;case"top":o.minorLabelHeight=r?o.minorCharHeight:0,o.majorLabelHeight=s?o.majorCharHeight:0,o.majorLabelTop=0,o.minorLabelTop=o.majorLabelTop+o.majorLabelHeight,o.minorLineTop=o.minorLabelTop,o.minorLineHeight=Math.max(c-o.majorLabelHeight-this.top),o.minorLineWidth=1,o.majorLineTop=0,o.majorLineHeight=Math.max(c-this.top),o.majorLineWidth=1,o.lineTop=o.majorLabelHeight+o.minorLabelHeight;break;default:throw Error('Unkown orientation "'+this.options.orientation+'"')}var p=o.minorLabelHeight+o.majorLabelHeight;t+=e(this,"width",n.offsetWidth),t+=e(this,"height",p),this._updateConversion();var u=g.cast(i.start,"Date"),d=g.cast(i.end,"Date"),l=this.toTime(5*(o.minorCharWidth||10))-this.toTime(0);this.step=new TimeStep(u,d,l),t+=e(o.range,"start",u.valueOf()),t+=e(o.range,"end",d.valueOf()),t+=e(o.range,"minimumStep",l.valueOf())}return t>0},a.prototype._updateConversion=function(){var t=this.range;if(!t)throw Error("No range configured");this.conversion=t.conversion?t.conversion(this.width):n.conversion(t.start,t.end,this.width)},f.component.TimeAxis=a,h.prototype=new r,h.prototype.setOptions=function(t){g.extend(this.options,t),this.stack.setOptions(this.options)},h.prototype.setRange=function(t){if(!(t instanceof n||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},h.prototype.repaint=function(){var t=0,e=g.updateProperty,n=g.option.asSize,i=this.options,o=this.frame;if(!o){o=document.createElement("div"),o.className="itemset",i.className&&g.addClassName(o,g.option.asString(i.className));var r=document.createElement("div");r.className="background",o.appendChild(r),this.dom.background=r;var s=document.createElement("div");s.className="foreground",o.appendChild(s),this.dom.foreground=s;var a=document.createElement("div");a.className="itemset-axis",this.dom.axis=a,this.frame=o,t+=1}if(!this.parent)throw Error("Cannot repaint itemset: no parent attached");var h=this.parent.getContainer();if(!h)throw Error("Cannot repaint itemset: parent has no container element");o.parentNode||(h.appendChild(o),t+=1),this.dom.axis.parentNode||(h.appendChild(this.dom.axis),t+=1),t+=e(o.style,"height",n(i.height,this.height+"px")),t+=e(o.style,"top",n(i.top,"0px")),t+=e(o.style,"left",n(i.left,"0px")),t+=e(o.style,"width",n(i.width,"100%")),t+=e(this.dom.axis.style,"top",n(i.top,"0px")),this._updateConversion();var c=this,p=this.queue,u=this.data,d=this.items,l={fields:["id","start","end","content","type"]};return Object.keys(p).forEach(function(e){var n=p[e],o=n.item;switch(n.action){case"add":case"update":var r=u.get(e,l),s=r.type||r.start&&r.end&&"range"||"box",a=f.component.item[s];if(o&&(a&&o instanceof a?(o.data=r,t+=o.repaint()):(o.visible=!1,t+=o.repaint(),o=null)),!o){if(!a)throw new TypeError('Unknown item type "'+s+'"');o=new a(c,r,i),t+=o.repaint()}d[e]=o,delete p[e];break;case"remove":o&&(o.visible=!1,t+=o.repaint()),delete d[e],delete p[e];break;default:console.log('Error: unknown action "'+n.action+'"')}}),g.forEach(this.items,function(t){t.reposition()}),t>0},h.prototype.getForeground=function(){return this.dom.foreground},h.prototype.getBackground=function(){return this.dom.background},h.prototype.reflow=function(){var t=0,e=this.options,n=g.updateProperty,i=g.option.asNumber,o=this.frame;if(o){this._updateConversion(),g.forEach(this.items,function(e){t+=e.reflow()}),this.stack.update();var r,s=i(e.maxHeight);if(null!=e.height)r=o.offsetHeight,null!=s&&(r=Math.min(r,s)),t+=n(this,"height",r);else{var a=this.height;r=0,"top"==e.orientation?g.forEach(this.items,function(t){r=Math.max(r,t.top+t.height)}):g.forEach(this.items,function(t){r=Math.max(r,a-t.top)}),r+=e.margin.axis,null!=s&&(r=Math.min(r,s)),t+=n(this,"height",r)}t+=n(this,"top",o.offsetTop),t+=n(this,"left",o.offsetLeft),t+=n(this,"width",o.offsetWidth)}else t+=1;return t>0},h.prototype.setData=function(e){var n=this.data;n&&g.forEach(this.listeners,function(t,e){n.unsubscribe(e,t)}),e instanceof t?this.data=e:(this.data=new t({fieldTypes:{start:"Date",end:"Date"}}),this.data.add(e));var i=this.id,o=this;g.forEach(this.listeners,function(t,e){o.data.subscribe(e,t,i)});var r=this.data.get({filter:["id"]}),s=[];g.forEach(r,function(t,e){s[e]=t.id}),this._onAdd(s)},h.prototype.getDataRange=function(){var t=this.data,e=t.min("start");e=e?e.start.valueOf():null;var n=t.max("start"),i=t.max("end");n=n?n.start.valueOf():null,i=i?i.end.valueOf():null;var o=Math.max(n,i);return{min:new Date(e),max:new Date(o)}},h.prototype._onUpdate=function(t){this._toQueue(t,"update")},h.prototype._onAdd=function(t){this._toQueue(t,"add")},h.prototype._onRemove=function(t){this._toQueue(t,"remove")},h.prototype._toQueue=function(t,e){var n=this.items,i=this.queue;t.forEach(function(t){var o=i[t];o?o.action=e:i[t]={item:n[t]||null,action:e}}),this.controller&&this.requestRepaint()},h.prototype._updateConversion=function(){var t=this.range;if(!t)throw Error("No range configured");this.conversion=t.conversion?t.conversion(this.width):n.conversion(t.start,t.end,this.width)},h.prototype.toTime=function(t){var e=this.conversion;return new Date(t/e.factor+e.offset)},h.prototype.toScreen=function(t){var e=this.conversion;return(t.valueOf()-e.offset)*e.factor},f.component.ItemSet=h,c.prototype=new o,c.prototype.select=function(){this.selected=!0},c.prototype.unselect=function(){this.selected=!1},f.component.item.Item=c,p.prototype=new c(null,null),p.prototype.select=function(){this.selected=!0},p.prototype.unselect=function(){this.selected=!1},p.prototype.repaint=function(){var t=!1,e=this.dom;if(this.visible){if(e||(this._create(),t=!0),e=this.dom){if(!this.options&&!this.parent)throw Error("Cannot repaint item: no parent attached");var n=this.parent.getForeground();if(!n)throw Error("Cannot repaint time axis: parent has no foreground container element");var i=this.parent.getBackground();if(!i)throw Error("Cannot repaint time axis: parent has no background container element");if(e.box.parentNode||(n.appendChild(e.box),t=!0),e.line.parentNode||(i.appendChild(e.line),t=!0),e.dot.parentNode||(this.parent.dom.axis.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)}}else e&&(e.box.parentNode&&(e.box.parentNode.removeChild(e.box),t=!0),e.line.parentNode&&(e.line.parentNode.removeChild(e.line),t=!0),e.dot.parentNode&&(e.dot.parentNode.removeChild(e.dot),t=!0));return t},p.prototype.reflow=function(){if(void 0==this.data.start)throw Error('Property "start" missing in item '+this.data.id);var t,e,n=g.updateProperty,i=this.dom,o=this.props,r=this.options,s=this.parent.toScreen(this.data.start),a=r&&r.align,h=r.orientation,c=0;if(i)if(c+=n(o.dot,"height",i.dot.offsetHeight),c+=n(o.dot,"width",i.dot.offsetWidth),c+=n(o.line,"width",i.line.offsetWidth),c+=n(o.line,"width",i.line.offsetWidth),c+=n(this,"width",i.box.offsetWidth),c+=n(this,"height",i.box.offsetHeight),e="right"==a?s-this.width:"left"==a?s:s-this.width/2,c+=n(this,"left",e),c+=n(o.line,"left",s-o.line.width/2),c+=n(o.dot,"left",s-o.dot.width/2),"top"==h)t=r.margin.axis,c+=n(this,"top",t),c+=n(o.line,"top",0),c+=n(o.line,"height",t),c+=n(o.dot,"top",-o.dot.height/2);else{var p=this.parent.height;t=p-this.height-r.margin.axis,c+=n(this,"top",t),c+=n(o.line,"top",t+this.height),c+=n(o.line,"height",Math.max(r.margin.axis,0)),c+=n(o.dot,"top",p-o.dot.height/2)}else c+=1;return c>0},p.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")},p.prototype.reposition=function(){var t=this.dom,e=this.props,n=this.options.orientation;if(t){var i=t.box,o=t.line,r=t.dot;i.style.left=this.left+"px",i.style.top=this.top+"px",o.style.left=e.line.left+"px","top"==n?(o.style.top="0px",o.style.height=this.top+"px"):(o.style.top=e.line.top+"px",o.style.top=this.top+this.height+"px",o.style.height=Math.max(e.dot.top-this.top-this.height,0)+"px"),r.style.left=e.dot.left+"px",r.style.top=e.dot.top+"px"}},f.component.item.box=p,u.prototype=new c(null,null),u.prototype.select=function(){this.selected=!0},u.prototype.unselect=function(){this.selected=!1},u.prototype.repaint=function(){var t=!1,e=this.dom;if(this.visible){if(e||(this._create(),t=!0),e=this.dom){if(!this.options&&!this.options.parent)throw Error("Cannot repaint item: no parent attached");var n=this.parent.getForeground();if(!n)throw Error("Cannot repaint time axis: parent has no foreground container element");if(e.point.parentNode||(n.appendChild(e.point),n.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 i=(this.data.className?" "+this.data.className:"")+(this.selected?" selected":"");this.className!=i&&(this.className=i,e.point.className="item point"+i,t=!0)}}else e&&e.point.parentNode&&(e.point.parentNode.removeChild(e.point),t=!0);return t},u.prototype.reflow=function(){if(void 0==this.data.start)throw Error('Property "start" missing in item '+this.data.id);var t,e=g.updateProperty,n=this.dom,i=this.props,o=this.options,r=o.orientation,s=this.parent.toScreen(this.data.start),a=0;if(n){if(a+=e(this,"width",n.point.offsetWidth),a+=e(this,"height",n.point.offsetHeight),a+=e(i.dot,"width",n.dot.offsetWidth),a+=e(i.dot,"height",n.dot.offsetHeight),a+=e(i.content,"height",n.content.offsetHeight),"top"==r)t=o.margin.axis;else{var h=this.parent.height;t=Math.max(h-this.height-o.margin.axis,0)}a+=e(this,"top",t),a+=e(this,"left",s-i.dot.width/2),a+=e(i.content,"marginLeft",1.5*i.dot.width),a+=e(i.dot,"top",(this.height-i.dot.height)/2)}else a+=1;return a>0},u.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))},u.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")},f.component.item.point=u,d.prototype=new c(null,null),d.prototype.select=function(){this.selected=!0},d.prototype.unselect=function(){this.selected=!1},d.prototype.repaint=function(){var t=!1,e=this.dom;if(this.visible){if(e||(this._create(),t=!0),e=this.dom){if(!this.options&&!this.options.parent)throw Error("Cannot repaint item: no parent attached");var n=this.parent.getForeground();if(!n)throw Error("Cannot repaint time axis: parent has no foreground container element");if(e.box.parentNode||(n.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 i=this.data.className?""+this.data.className:"";this.className!=i&&(this.className=i,e.box.className="item range"+i,t=!0)}}else e&&e.box.parentNode&&(e.box.parentNode.removeChild(e.box),t=!0);return t},d.prototype.reflow=function(){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);var t=this.dom,e=this.props,n=this.options,i=this.parent,o=i.toScreen(this.data.start),r=i.toScreen(this.data.end),s=0;if(t){var a,h,c=g.updateProperty,p=t.box,u=i.width,d=n.orientation;s+=c(e.content,"width",t.content.offsetWidth),s+=c(this,"height",p.offsetHeight),-u>o&&(o=-u),r>2*u&&(r=2*u),a=0>o?Math.min(-o,r-o-e.content.width-2*n.padding):0,s+=c(e.content,"left",a),"top"==d?(h=n.margin.axis,s+=c(this,"top",h)):(h=i.height-this.height-n.margin.axis,s+=c(this,"top",h)),s+=c(this,"left",o),s+=c(this,"width",Math.max(r-o,1))}else s+=1;return s>0},d.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))},d.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")},f.component.item.range=d,l.prototype.setOptions=function(t){g.extend(this.options,t),this.timeaxis.setOptions(this.options),this.range.setOptions(this.options);var e,n=this;e="top"==this.options.orientation?function(){return n.timeaxis.height}:function(){return n.main.height-n.timeaxis.height-n.itemset.height},this.itemset.setOptions({orientation:this.options.orientation,top:e}),this.controller.repaint()},l.prototype.setData=function(t){var e=this.itemset.data;if(e)this.itemset.setData(t);else{this.itemset.setData(t);var n=this.itemset.getDataRange(),i=n.min,o=n.max;if(null!=i&&null!=o){var r=o.valueOf()-i.valueOf();i=new Date(i.valueOf()-.05*r),o=new Date(o.valueOf()+.05*r)}(null!=i||null!=o)&&this.range.setRange(i,o)}},f.Timeline=l,function(t){function e(t,e){return function(n){return h(t.call(this,n),e)}}function n(t){return function(e){return this.lang().ordinal(t.call(this,e))}}function i(){}function o(t){s(this,t)}function r(t){var e=this._data={},n=t.years||t.year||t.y||0,i=t.months||t.month||t.M||0,o=t.weeks||t.week||t.w||0,r=t.days||t.day||t.d||0,s=t.hours||t.hour||t.h||0,h=t.minutes||t.minute||t.m||0,c=t.seconds||t.second||t.s||0,p=t.milliseconds||t.millisecond||t.ms||0;this._milliseconds=p+1e3*c+6e4*h+36e5*s,this._days=r+7*o,this._months=i+12*n,e.milliseconds=p%1e3,c+=a(p/1e3),e.seconds=c%60,h+=a(c/60),e.minutes=h%60,s+=a(h/60),e.hours=s%24,r+=a(s/24),r+=7*o,e.days=r%30,i+=a(r/30),e.months=i%12,n+=a(i/12),e.years=n}function s(t,e){for(var n in e)e.hasOwnProperty(n)&&(t[n]=e[n]);return t}function a(t){return 0>t?Math.ceil(t):Math.floor(t)}function h(t,e){for(var n=t+"";e>n.length;)n="0"+n;return n}function c(t,e,n){var i,o=e._milliseconds,r=e._days,s=e._months;o&&t._d.setTime(+t+o*n),r&&t.date(t.date()+r*n),s&&(i=t.date(),t.date(1).month(t.month()+s*n).date(Math.min(i,t.daysInMonth())))}function p(t){return"[object Array]"===Object.prototype.toString.call(t)}function u(t,e){var n,i=Math.min(t.length,e.length),o=Math.abs(t.length-e.length),r=0;for(n=0;i>n;n++)~~t[n]!==~~e[n]&&r++;return r+o}function d(t,e){return e.abbr=t,H[t]||(H[t]=new i),H[t].set(e),H[t]}function l(t){return t?(!H[t]&&I&&require("./lang/"+t),H[t]):N.fn._lang}function f(t){return t.match(/\[.*\]/)?t.replace(/^\[|\]$/g,""):t.replace(/\\/g,"")}function m(t){var e,n,i=t.match(R);for(e=0,n=i.length;n>e;e++)i[e]=oe[i[e]]?oe[i[e]]:f(i[e]);return function(o){var r="";for(e=0;n>e;e++)r+="function"==typeof i[e].call?i[e].call(o,t):i[e];return r}}function g(t,e){function n(e){return t.lang().longDateFormat(e)||e}for(var i=5;i--&&U.test(e);)e=e.replace(U,n);return ee[e]||(ee[e]=m(e)),ee[e](t)}function v(t){switch(t){case"DDDD":return P;case"YYYY":return W;case"YYYYY":return V;case"S":case"SS":case"SSS":case"DDD":return z;case"MMM":case"MMMM":case"dd":case"ddd":case"dddd":case"a":case"A":return q;case"X":return X;case"Z":case"ZZ":return Z;case"T":return B;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 F;default:return RegExp(t.replace("\\",""))}}function y(t,e,n){var i,o=n._a;switch(t){case"M":case"MM":o[1]=null==e?0:~~e-1;break;case"MMM":case"MMMM":i=l(n._l).monthsParse(e),null!=i?o[1]=i:n._isValid=!1;break;case"D":case"DD":case"DDD":case"DDDD":null!=e&&(o[2]=~~e);break;case"YY":o[0]=~~e+(~~e>68?1900:2e3);break;case"YYYY":case"YYYYY":o[0]=~~e;break;case"a":case"A":n._isPm="pm"===(e+"").toLowerCase();break;case"H":case"HH":case"h":case"hh":o[3]=~~e;break;case"m":case"mm":o[4]=~~e;break;case"s":case"ss":o[5]=~~e;break;case"S":case"SS":case"SSS":o[6]=~~(1e3*("0."+e));break;case"X":n._d=new Date(1e3*parseFloat(e));break;case"Z":case"ZZ":n._useUTC=!0,i=(e+"").match(Q),i&&i[1]&&(n._tzh=~~i[1]),i&&i[2]&&(n._tzm=~~i[2]),i&&"+"===i[0]&&(n._tzh=-n._tzh,n._tzm=-n._tzm)}null==e&&(n._isValid=!1)}function S(t){var e,n,i=[];if(!t._d){for(e=0;7>e;e++)t._a[e]=i[e]=null==t._a[e]?2===e?1:0:t._a[e];i[3]+=t._tzh||0,i[4]+=t._tzm||0,n=new Date(0),t._useUTC?(n.setUTCFullYear(i[0],i[1],i[2]),n.setUTCHours(i[3],i[4],i[5],i[6])):(n.setFullYear(i[0],i[1],i[2]),n.setHours(i[3],i[4],i[5],i[6])),t._d=n}}function T(t){var e,n,i=t._f.match(R),o=t._i;for(t._a=[],e=0;i.length>e;e++)n=(v(i[e]).exec(o)||[])[0],n&&(o=o.slice(o.indexOf(n)+n.length)),oe[i[e]]&&y(i[e],n,t);t._isPm&&12>t._a[3]&&(t._a[3]+=12),t._isPm===!1&&12===t._a[3]&&(t._a[3]=0),S(t)}function w(t){for(var e,n,i,r,a=99;t._f.length;){if(e=s({},t),e._f=t._f.pop(),T(e),n=new o(e),n.isValid()){i=n;break}r=u(e._a,n.toArray()),a>r&&(a=r,i=n)}s(t,i)}function E(t){var e,n=t._i;if(K.exec(n)){for(t._f="YYYY-MM-DDT",e=0;4>e;e++)if($[e][1].exec(n)){t._f+=$[e][0];break}Z.exec(n)&&(t._f+=" Z"),T(t)}else t._d=new Date(n)}function b(e){var n=e._i,i=j.exec(n);n===t?e._d=new Date:i?e._d=new Date(+i[1]):"string"==typeof n?E(e):p(n)?(e._a=n.slice(0),S(e)):e._d=n instanceof Date?new Date(+n):new Date(n)}function M(t,e,n,i,o){return o.relativeTime(e||1,!!n,t,i)}function _(t,e,n){var i=k(Math.abs(t)/1e3),o=k(i/60),r=k(o/60),s=k(r/24),a=k(s/365),h=45>i&&["s",i]||1===o&&["m"]||45>o&&["mm",o]||1===r&&["h"]||22>r&&["hh",r]||1===s&&["d"]||25>=s&&["dd",s]||45>=s&&["M"]||345>s&&["MM",k(s/30)]||1===a&&["y"]||["yy",a];return h[2]=e,h[3]=t>0,h[4]=n,M.apply({},h)}function D(t,e,n){var i=n-e,o=n-t.day();return o>i&&(o-=7),i-7>o&&(o+=7),Math.ceil(N(t).add("d",o).dayOfYear()/7)}function L(t){var e=t._i,n=t._f;return null===e||""===e?null:("string"==typeof e&&(t._i=e=l().preparse(e)),N.isMoment(e)?(t=s({},e),t._d=new Date(+e._d)):n?p(n)?w(t):T(t):b(t),new o(t))}function C(t,e){N.fn[t]=N.fn[t+"s"]=function(t){var n=this._isUTC?"UTC":"";return null!=t?(this._d["set"+n+e](t),this):this._d["get"+n+e]()}}function x(t){N.duration.fn[t]=function(){return this._data[t]}}function A(t,e){N.duration.fn["as"+t]=function(){return+this/e}}for(var N,O,Y="2.0.0",k=Math.round,H={},I="undefined"!=typeof module&&module.exports,j=/^\/?Date\((\-?\d+)/i,R=/(\[[^\[]*\])|(\\)?(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,F=/\d\d?/,z=/\d{1,3}/,P=/\d{3}/,W=/\d{1,4}/,V=/[+\-]?\d{1,6}/,q=/[0-9]*[a-z\u00A0-\u05FF\u0700-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF]+|[\u0600-\u06FF]+\s*?[\u0600-\u06FF]+/i,Z=/Z|[\+\-]\d\d:?\d\d/i,B=/T/i,X=/[\+\-]?\d+(\.\d{1,3})?/,K=/^\s*\d{4}-\d\d-\d\d((T| )(\d\d(:\d\d(:\d\d(\.\d\d?\d?)?)?)?)?([\+\-]\d\d:?\d\d)?)?/,J="YYYY-MM-DDTHH:mm:ssZ",$=[["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/]],Q=/([\+\-]|\d\d)/gi,G="Month|Date|Hours|Minutes|Seconds|Milliseconds".split("|"),te={Milliseconds:1,Seconds:1e3,Minutes:6e4,Hours:36e5,Days:864e5,Months:2592e6,Years:31536e6},ee={},ne="DDD w W M D d".split(" "),ie="M D H h m s w W".split(" "),oe={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 h(this.year()%100,2)},YYYY:function(){return h(this.year(),4)},YYYYY:function(){return h(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 h(~~(this.milliseconds()/10),2)},SSS:function(){return h(this.milliseconds(),3)},Z:function(){var t=-this.zone(),e="+";return 0>t&&(t=-t,e="-"),e+h(~~(t/60),2)+":"+h(~~t%60,2)},ZZ:function(){var t=-this.zone(),e="+";return 0>t&&(t=-t,e="-"),e+h(~~(10*t/6),4)},X:function(){return this.unix()}};ne.length;)O=ne.pop(),oe[O+"o"]=n(oe[O]);for(;ie.length;)O=ie.pop(),oe[O+O]=e(oe[O],2);for(oe.DDDD=e(oe.DDD,3),i.prototype={set:function(t){var e,n;for(n in t)e=t[n],"function"==typeof e?this[n]=e:this["_"+n]=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,n,i;for(this._monthsParse||(this._monthsParse=[]),e=0;12>e;e++)if(this._monthsParse[e]||(n=N([2e3,e]),i="^"+this.months(n,"")+"|^"+this.monthsShort(n,""),this._monthsParse[e]=RegExp(i.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,n){return t>11?n?"pm":"PM":n?"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 n=this._calendar[t];return"function"==typeof n?n.apply(e):n},_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,n,i){var o=this._relativeTime[n];return"function"==typeof o?o(t,e,n,i):o.replace(/%d/i,t)},pastFuture:function(t,e){var n=this._relativeTime[t>0?"future":"past"];return"function"==typeof n?n(e):n.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 D(t,this._week.dow,this._week.doy)},_week:{dow:0,doy:6}},N=function(t,e,n){return L({_i:t,_f:e,_l:n,_isUTC:!1})},N.utc=function(t,e,n){return L({_useUTC:!0,_isUTC:!0,_l:n,_i:t,_f:e})},N.unix=function(t){return N(1e3*t)},N.duration=function(t,e){var n,i=N.isDuration(t),o="number"==typeof t,s=i?t._data:o?{}:t;return o&&(e?s[e]=t:s.milliseconds=t),n=new r(s),i&&t.hasOwnProperty("_lang")&&(n._lang=t._lang),n},N.version=Y,N.defaultFormat=J,N.lang=function(e,n){return e?(n?d(e,n):H[e]||l(e),N.duration.fn._lang=N.fn._lang=l(e),t):N.fn._lang._abbr},N.langData=function(t){return t&&t._lang&&t._lang._abbr&&(t=t._lang._abbr),l(t)},N.isMoment=function(t){return t instanceof o},N.isDuration=function(t){return t instanceof r},N.fn=o.prototype={clone:function(){return N(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 N.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?!u(this._a,(this._isUTC?N.utc(this._a):N(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=g(this,t||N.defaultFormat);return this.lang().postformat(e)},add:function(t,e){var n;return n="string"==typeof t?N.duration(+e,t):N.duration(t,e),c(this,n,1),this},subtract:function(t,e){var n;return n="string"==typeof t?N.duration(+e,t):N.duration(t,e),c(this,n,-1),this},diff:function(t,e,n){var i,o,r=this._isUTC?N(t).utc():N(t).local(),s=6e4*(this.zone()-r.zone());return e&&(e=e.replace(/s$/,"")),"year"===e||"month"===e?(i=432e5*(this.daysInMonth()+r.daysInMonth()),o=12*(this.year()-r.year())+(this.month()-r.month()),o+=(this-N(this).startOf("month")-(r-N(r).startOf("month")))/i,"year"===e&&(o/=12)):(i=this-r-s,o="second"===e?i/1e3:"minute"===e?i/6e4:"hour"===e?i/36e5:"day"===e?i/864e5:"week"===e?i/6048e5:i),n?o:a(o)},from:function(t,e){return N.duration(this.diff(t)).lang(this.lang()._abbr).humanize(!e)},fromNow:function(t){return this.from(N(),t)},calendar:function(){var t=this.diff(N().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()+N(e).startOf(n)},isBefore:function(e,n){return n=n!==t?n:"millisecond",+this.clone().startOf(n)<+N(e).startOf(n)},isSame:function(e,n){return n=n!==t?n:"millisecond",+this.clone().startOf(n)===+N(e).startOf(n)},zone:function(){return this._isUTC?0:this._d.getTimezoneOffset()},daysInMonth:function(){return N.utc([this.year(),this.month()+1,0]).date()},dayOfYear:function(t){var e=k((N(this).startOf("day")-N(this).startOf("year"))/864e5)+1;return null==t?e:this.add("d",t-e)},isoWeek:function(t){var e=D(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(e){return e===t?this._lang:(this._lang=l(e),this)}},O=0;G.length>O;O++)C(G[O].toLowerCase().replace(/s$/,""),G[O]);C("year","FullYear"),N.fn.days=N.fn.day,N.fn.weeks=N.fn.week,N.fn.isoWeeks=N.fn.isoWeek,N.duration.fn=r.prototype={weeks:function(){return a(this.days()/7)},valueOf:function(){return this._milliseconds+864e5*this._days+2592e6*this._months},humanize:function(t){var e=+this,n=_(e,!t,this.lang());return t&&(n=this.lang().pastFuture(e,n)),this.lang().postformat(n)},lang:N.fn.lang};for(O in te)te.hasOwnProperty(O)&&(A(O,te[O]),x(O.toLowerCase()));A("Weeks",6048e5),N.lang("en",{ordinal:function(t){var e=t%10,n=1===~~(t%100/10)?"th":1===e?"st":2===e?"nd":3===e?"rd":"th";return t+n}}),I&&(module.exports=N),"undefined"==typeof ender&&(this.moment=N),"function"==typeof define&&define.amd&&define("moment",[],function(){return N})}.call(this),m("/* vis.js stylesheet */\n\n.graph {\n position: relative;\n border: 1px solid #bfbfbf;\n}\n\n.graph .panel {\n position: absolute;\n}\n\n.graph .itemset {\n position: absolute;\n padding: 0;\n margin: 0;\n overflow: hidden;\n}\n\n.graph .background {\n}\n\n.graph .foreground {\n}\n\n.graph .itemset-axis {\n position: absolute;\n}\n\n.graph .item {\n position: absolute;\n color: #1A1A1A;\n border-color: #97B0F8;\n background-color: #D5DDF6;\n display: inline-block;\n}\n\n.graph .item.selected {\n border-color: #FFC200;\n background-color: #FFF785;\n z-index: 999;\n}\n\n.graph .item.cluster {\n /* TODO: use another color or pattern? */\n background: #97B0F8 url('img/cluster_bg.png');\n color: white;\n}\n.graph .item.cluster.point {\n border-color: #D5DDF6;\n}\n\n.graph .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.graph .item.point {\n background: none;\n}\n\n.graph .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.graph .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.graph .item.range .drag-left {\n cursor: w-resize;\n z-index: 1000;\n}\n\n.graph .item.range .drag-right {\n cursor: e-resize;\n z-index: 1000;\n}\n\n.graph .item.range .content {\n position: relative;\n display: inline-block;\n}\n\n.graph .item.line {\n position: absolute;\n width: 0;\n border-left-width: 1px;\n border-left-style: solid;\n}\n\n.graph .item .content {\n margin: 5px;\n white-space: nowrap;\n overflow: hidden;\n}\n\n/* TODO: better css name, 'graph' is way to generic */\n\n.graph {\n overflow: hidden;\n}\n\n.graph .axis {\n position: relative;\n}\n\n.graph .axis .text {\n position: absolute;\n color: #4d4d4d;\n padding: 3px;\n white-space: nowrap;\n}\n\n.graph .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.graph .axis .grid.vertical {\n position: absolute;\n width: 0;\n border-right: 1px solid;\n}\n\n.graph .axis .grid.horizontal {\n position: absolute;\n left: 0;\n width: 100%;\n height: 0;\n border-bottom: 1px solid;\n}\n\n.graph .axis .grid.minor {\n border-color: #e5e5e5;\n}\n\n.graph .axis .grid.major {\n border-color: #bfbfbf;\n}\n\n")})();
\ 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(t,e,n){function i(n,r){if(!e[n]){if(!t[n]){var s="function"==typeof require&&require;if(!r&&s)return s(n,!0);if(o)return o(n,!0);throw Error("Cannot find module '"+n+"'")}var a=e[n]={exports:{}};t[n][0].call(a.exports,function(e){var o=t[n][1][e];return i(o?o:e)},a,a.exports)}return e[n].exports}for(var o="function"==typeof require&&require,r=0;n.length>r;r++)i(n[r]);return i}({1:[function(t,e,n){var i={Controller:t("./controller"),DataSet:t("./dataset"),events:t("./events"),Range:t("./range"),Stack:t("./stack"),TimeStep:t("./timestep"),util:t("./util"),component:{item:{Item:"../../Item",ItemBox:"../../ItemBox",ItemPoint:"../../ItemPoint",ItemRange:"../../ItemRange"},Component:t("./component/component"),Panel:t("./component/panel"),RootPanel:t("./component/rootpanel"),ItemSet:t("./component/itemset"),TimeAxis:t("./component/timeaxis")},Timeline:t("./visualization/timeline")};e.exports=n=i},{"./controller":2,"./dataset":3,"./events":4,"./range":5,"./stack":6,"./timestep":7,"./util":8,"./component/component":9,"./component/panel":10,"./component/rootpanel":11,"./component/itemset":12,"./visualization/timeline":13,"./component/timeaxis":14}],4:[function(t,e,n){var i={listeners:[],indexOf:function(t){for(var e=this.listeners,n=0,i=this.listeners.length;i>n;n++){var o=e[n];if(o&&o.object==t)return n}return-1},addListener:function(t,e,n){var i=this.indexOf(t),o=this.listeners[i];o||(o={object:t,events:{}},this.listeners.push(o));var r=o.events[e];r||(r=[],o.events[e]=r),-1==r.indexOf(n)&&r.push(n)},removeListener:function(t,e,n){var i=this.indexOf(t),o=this.listeners[i];if(o){var r=o.events[e];r&&(i=r.indexOf(n),-1!=i&&r.splice(i,1),0==r.length&&delete o.events[e]);var s=0,a=o.events;for(var h in a)a.hasOwnProperty(h)&&s++;0==s&&delete this.listeners[i]}},removeAllListeners:function(){this.listeners=[]},trigger:function(t,e,n){var i=this.indexOf(t),o=this.listeners[i];if(o){var r=o.events[e];if(r)for(var s=0,a=r.length;a>s;s++)r[s](n)}}};e.exports=n=i},{}],8:[function(t,e,n){var i={};i.isNumber=function(t){return t instanceof Number||"number"==typeof t},i.isString=function(t){return t instanceof String||"string"==typeof t},i.isDate=function(t){if(t instanceof Date)return!0;if(i.isString(t)){var e=o.exec(t);if(e)return!0;if(!isNaN(Date.parse(t)))return!0}return!1},i.isDataTable=function(t){return"undefined"!=typeof google&&google.visualization&&google.visualization.DataTable&&t instanceof google.visualization.DataTable},i.randomUUID=function(){var t=function(){return Math.floor(65536*Math.random()).toString(16)};return t()+t()+"-"+t()+"-"+t()+"-"+t()+"-"+t()+t()+t()},i.extend=function(t,e){for(var n in e)e.hasOwnProperty(n)&&(t[n]=e[n]);return t},i.cast=function(t,e){if(void 0===t)return void 0;if(null===t)return null;if(!e)return t;if("function"==typeof e)return e(t);switch(e){case"boolean":case"Boolean":return Boolean(t);case"number":case"Number":return Number(t);case"string":case"String":return t+"";case"Date":if(i.isNumber(t))return new Date(t);if(t instanceof Date)return new Date(t.valueOf());if(i.isString(t)){var n=o.exec(t);return n?new Date(Number(n[1])):moment(t).toDate()}throw Error("Cannot cast object of type "+i.getType(t)+" to type Date");case"ISODate":if(t instanceof Date)return t.toISOString();if(i.isNumber(t)||i.isString(t))return moment(t).toDate().toISOString();throw Error("Cannot cast object of type "+i.getType(t)+" to type ISODate");case"ASPDate":if(t instanceof Date)return"/Date("+t.valueOf()+")/";if(i.isNumber(t)||i.isString(t))return"/Date("+moment(t).valueOf()+")/";throw Error("Cannot cast object of type "+i.getType(t)+" to type ASPDate");default:throw Error("Cannot cast object of type "+i.getType(t)+' to type "'+e+'"')}};var o=/^\/?Date\((\-?\d+)/i;if(i.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},i.getAbsoluteLeft=function(t){for(var e=document.documentElement,n=document.body,i=t.offsetLeft,o=t.offsetParent;null!=o&&o!=n&&o!=e;)i+=o.offsetLeft,i-=o.scrollLeft,o=o.offsetParent;return i},i.getAbsoluteTop=function(t){for(var e=document.documentElement,n=document.body,i=t.offsetTop,o=t.offsetParent;null!=o&&o!=n&&o!=e;)i+=o.offsetTop,i-=o.scrollTop,o=o.offsetParent;return i},i.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 n=document.documentElement,i=document.body;return e+(n&&n.scrollTop||i&&i.scrollTop||0)-(n&&n.clientTop||i&&i.clientTop||0)},i.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 n=document.documentElement,i=document.body;return e+(n&&n.scrollLeft||i&&i.scrollLeft||0)-(n&&n.clientLeft||i&&i.clientLeft||0)},i.addClassName=function(t,e){var n=t.className.split(" ");-1==n.indexOf(e)&&(n.push(e),t.className=n.join(" "))},i.removeClassName=function(t,e){var n=t.className.split(" "),i=n.indexOf(e);-1!=i&&(n.splice(i,1),t.className=n.join(" "))},i.forEach=function(t,e){if(t instanceof Array)t.forEach(e);else for(var n in t)t.hasOwnProperty(n)&&e(t[n],n,t)},i.updateProperty=function(t,e,n){return t[e]!==n?(t[e]=n,!0):!1},i.addEventListener=function(t,e,n,i){t.addEventListener?(void 0===i&&(i=!1),"mousewheel"===e&&navigator.userAgent.indexOf("Firefox")>=0&&(e="DOMMouseScroll"),t.addEventListener(e,n,i)):t.attachEvent("on"+e,n)},i.removeEventListener=function(t,e,n,i){t.removeEventListener?(void 0===i&&(i=!1),"mousewheel"===e&&navigator.userAgent.indexOf("Firefox")>=0&&(e="DOMMouseScroll"),t.removeEventListener(e,n,i)):t.detachEvent("on"+e,n)},i.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},i.stopPropagation=function(t){t||(t=window.event),t.stopPropagation?t.stopPropagation():t.cancelBubble=!0},i.preventDefault=function(t){t||(t=window.event),t.preventDefault?t.preventDefault():t.returnValue=!1},i.option={},i.option.asBoolean=function(t,e){return"function"==typeof t&&(t=t()),null!=t?0!=t:e||null},i.option.asNumber=function(t,e){return"function"==typeof t&&(t=t()),null!=t?Number(t):e||null},i.option.asString=function(t,e){return"function"==typeof t&&(t=t()),null!=t?t+"":e||null},i.option.asSize=function(t,e){return"function"==typeof t&&(t=t()),i.isString(t)?t:i.isNumber(t)?t+"px":e||null},i.option.asElement=function(t,e){return"function"==typeof t&&(t=t()),t||e||null},!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(r){}}Array.prototype.forEach||(Array.prototype.forEach=function(t,e){for(var n=0,i=this.length;i>n;++n)t.call(e||this,this[n],n,this)}),Array.prototype.map||(Array.prototype.map=function(t,e){var n,i,o;if(null==this)throw new TypeError(" this is null or not defined");var r=Object(this),s=r.length>>>0;if("function"!=typeof t)throw new TypeError(t+" is not a function");for(e&&(n=e),i=Array(s),o=0;s>o;){var a,h;o in r&&(a=r[o],h=t.call(n,a,o,r),i[o]=h),o++}return i}),Array.prototype.filter||(Array.prototype.filter=function(t){"use strict";if(null==this)throw new TypeError;var e=Object(this),n=e.length>>>0;if("function"!=typeof t)throw new TypeError;for(var i=[],o=arguments[1],r=0;n>r;r++)if(r in e){var s=e[r];t.call(o,s,r,e)&&i.push(s)}return i}),Object.keys||(Object.keys=function(){var t=Object.prototype.hasOwnProperty,e=!{toString:null}.propertyIsEnumerable("toString"),n=["toString","toLocaleString","valueOf","hasOwnProperty","isPrototypeOf","propertyIsEnumerable","constructor"],i=n.length;return function(o){if("object"!=typeof o&&"function"!=typeof o||null===o)throw new TypeError("Object.keys called on non-object");var r=[];for(var s in o)t.call(o,s)&&r.push(s);if(e)for(var a=0;i>a;a++)t.call(o,n[a])&&r.push(n[a]);return r}}()),Array.isArray||(Array.isArray=function(t){return"[object Array]"===Object.prototype.toString.call(t)}),e.exports=n=i},{}],2:[function(t,e,n){function i(){this.id=o.randomUUID(),this.components={},this.repaintTimer=void 0,this.reflowTimer=void 0}var o=t("./util"),r=t("./component/component");i.prototype.add=function(t){if(void 0==t.id)throw Error("Component has no field id");if(!(t instanceof r||t instanceof i))throw new TypeError("Component must be an instance of prototype Component or Controller");t.controller=this,this.components[t.id]=t},i.prototype.requestReflow=function(){if(!this.reflowTimer){var t=this;this.reflowTimer=setTimeout(function(){t.reflowTimer=void 0,t.reflow()},0)}},i.prototype.requestRepaint=function(){if(!this.repaintTimer){var t=this;this.repaintTimer=setTimeout(function(){t.repaintTimer=void 0,t.repaint()},0)}},i.prototype.repaint=function(){function t(i,o){o in n||(i.depends&&i.depends.forEach(function(e){t(e,e.id)}),i.parent&&t(i.parent,i.parent.id),e=i.repaint()||e,n[o]=!0)}var e=!1;this.repaintTimer&&(clearTimeout(this.repaintTimer),this.repaintTimer=void 0);var n={};o.forEach(this.components,t),e&&this.reflow()},i.prototype.reflow=function(){function t(i,o){o in n||(i.depends&&i.depends.forEach(function(e){t(e,e.id)}),i.parent&&t(i.parent,i.parent.id),e=i.reflow()||e,n[o]=!0)}var e=!1;this.reflowTimer&&(clearTimeout(this.reflowTimer),this.reflowTimer=void 0);var n={};o.forEach(this.components,t),e&&this.repaint()},e.exports=n=i},{"./util":8,"./component/component":9}],3:[function(t,e,n){function i(t){var e=this;this.options=t||{},this.data={},this.fieldId=this.options.fieldId||"id",this.fieldTypes={},this.options.fieldTypes&&o.forEach(this.options.fieldTypes,function(t,n){e.fieldTypes[n]="Date"==t||"ISODate"==t||"ASPDate"==t?"Date":t}),this.subscribers={},this.internalIds={}}var o=t("./util");i.prototype.subscribe=function(t,e,n){var i=this.subscribers[t];i||(i=[],this.subscribers[t]=i),i.push({id:n?n+"":null,callback:e})},i.prototype.unsubscribe=function(t,e){var n=this.subscribers[t];n&&(this.subscribers[t]=n.filter(function(t){return t.callback!=e}))},i.prototype._trigger=function(t,e,n){if("*"==t)throw Error("Cannot trigger event *");var i=[];t in this.subscribers&&(i=i.concat(this.subscribers[t])),"*"in this.subscribers&&(i=i.concat(this.subscribers["*"])),i.forEach(function(i){i.id!=n&&i.callback&&i.callback(t,e,n||null)})},i.prototype.add=function(t,e){var n,i=[],r=this;if(t instanceof Array)t.forEach(function(t){var e=r._addItem(t);i.push(e)});else if(o.isDataTable(t))for(var s=this._getColumnNames(t),a=0,h=t.getNumberOfRows();h>a;a++){var c={};s.forEach(function(e,n){c[e]=t.getValue(a,n)}),n=r._addItem(c),i.push(n)}else{if(!(t instanceof Object))throw Error("Unknown dataType");n=r._addItem(t),i.push(n)}this._trigger("add",{items:i},e)},i.prototype.update=function(t,e){var n,i=[],r=this;if(t instanceof Array)t.forEach(function(t){var e=r._updateItem(t);i.push(e)});else if(o.isDataTable(t))for(var s=this._getColumnNames(t),a=0,h=t.getNumberOfRows();h>a;a++){var c={};s.forEach(function(e,n){c[e]=t.getValue(a,n)}),n=r._updateItem(c),i.push(n)}else{if(!(t instanceof Object))throw Error("Unknown dataType");n=r._updateItem(t),i.push(n)}this._trigger("update",{items:i},e)},i.prototype.get=function(t,e,n){var i=this;"Object"==o.getType(t)&&(n=e,e=t,t=void 0);var r={};this.options&&this.options.fieldTypes&&o.forEach(this.options.fieldTypes,function(t,e){r[e]=t}),e&&e.fieldTypes&&o.forEach(e.fieldTypes,function(t,e){r[e]=t});var s,a=e?e.fields:void 0;if(e&&e.type){if(s="DataTable"==e.type?"DataTable":"Array",n&&s!=o.getType(n))throw Error('Type of parameter "data" ('+o.getType(n)+") "+"does not correspond with specified options.type ("+e.type+")");if("DataTable"==s&&!o.isDataTable(n))throw Error('Parameter "data" must be a DataTable when options.type is "DataTable"')}else s=n?"DataTable"==o.getType(n)?"DataTable":"Array":"Array";if("DataTable"==s){var h=this._getColumnNames(n);if(void 0==t)o.forEach(this.data,function(t){i._appendRow(n,h,i._castItem(t))});else if(o.isNumber(t)||o.isString(t)){var c=i._castItem(i.data[t],r,a);this._appendRow(n,h,c)}else{if(!(t instanceof Array))throw new TypeError('Parameter "ids" must be undefined, a String, Number, or Array');t.forEach(function(t){var e=i._castItem(i.data[t],r,a);i._appendRow(n,h,e)})}}else if(n=n||[],void 0==t)o.forEach(this.data,function(t){n.push(i._castItem(t,r,a))});else{if(o.isNumber(t)||o.isString(t))return this._castItem(i.data[t],r,a);if(!(t instanceof Array))throw new TypeError('Parameter "ids" must be undefined, a String, Number, or Array');t.forEach(function(t){n.push(i._castItem(i.data[t],r,a))})}return n},i.prototype.remove=function(t,e){var n=[],i=this;if(o.isNumber(t)||o.isString(t))delete this.data[t],delete this.internalIds[t],n.push(t);else if(t instanceof Array)t.forEach(function(t){i.remove(t)}),n=n.concat(t);else if(t instanceof Object)for(var r in this.data)this.data.hasOwnProperty(r)&&this.data[r]==t&&(delete this.data[r],delete this.internalIds[r],n.push(r));this._trigger("remove",{items:n},e)},i.prototype.clear=function(t){var e=Object.keys(this.data);this.data={},this.internalIds={},this._trigger("remove",{items:e},t)},i.prototype.max=function(t){var e=this.data,n=Object.keys(e),i=null,o=null;return n.forEach(function(n){var r=e[n],s=r[t];null!=s&&(!i||s>o)&&(i=r,o=s)}),i},i.prototype.min=function(t){var e=this.data,n=Object.keys(e),i=null,o=null;return n.forEach(function(n){var r=e[n],s=r[t];null!=s&&(!i||o>s)&&(i=r,o=s)}),i},i.prototype._addItem=function(t){var e=t[this.fieldId];void 0==e&&(e=o.randomUUID(),t[this.fieldId]=e,this.internalIds[e]=t);var n={};for(var i in t)if(t.hasOwnProperty(i)){var r=this.fieldTypes[i];n[i]=o.cast(t[i],r)}return this.data[e]=n,e},i.prototype._castItem=function(t,e,n){var i,r=this.fieldId,s=this.internalIds;return t?(i={},e=e||{},n?o.forEach(t,function(t,r){-1!=n.indexOf(r)&&(i[r]=o.cast(t,e[r]))}):o.forEach(t,function(t,n){n==r&&t in s||(i[n]=o.cast(t,e[n]))})):i=null,i},i.prototype._updateItem=function(t){var e=t[this.fieldId];if(void 0==e)throw Error("Item has no id (item: "+JSON.stringify(t)+")");var n=this.data[e];if(n){for(var i in t)if(t.hasOwnProperty(i)){var r=this.fieldTypes[i];n[i]=o.cast(t[i],r)}}else this._addItem(t);return e},i.prototype._getColumnNames=function(t){for(var e=[],n=0,i=t.getNumberOfColumns();i>n;n++)e[n]=t.getColumnId(n)||t.getColumnLabel(n);return e},i.prototype._appendRow=function(t,e,n){var i=t.addRow();e.forEach(function(e,o){t.setValue(i,o,n[e])})},e.exports=n=i},{"./util":8}],6:[function(t,e,n){function i(t,e){this.parent=t,this.options={order:function(t,e){return e.width-t.width||t.left-e.left}},this.ordered=[],this.setOptions(e)}var o=t("./util");i.prototype.setOptions=function(t){o.extend(this.options,t)},i.prototype.update=function(){this._order(),this._stack()},i.prototype._order=function(){var t=this.parent.items;if(!t)throw Error("Cannot stack items: parent does not contain items");var e=[],n=0;o.forEach(t,function(t){e[n]=t,n++});var i=this.options.order;if("function"!=typeof this.options.order)throw Error("Option order must be a function");e.sort(i),this.ordered=e},i.prototype._stack=function(){var t,e,n=this.ordered,i=this.options,o="top"==i.orientation,r=i.margin&&i.margin.item||0;for(t=0,e=n.length;e>t;t++){var s=n[t],a=null;do a=this.checkOverlap(n,t,0,t-1,r),null!=a&&(s.top=o?a.top+a.height+r:a.top-s.height-r);while(a)}},i.prototype.checkOverlap=function(t,e,n,i,o){for(var r=this.collision,s=t[e],a=i;a>=n;a--){var h=t[a];if(r(s,h,o)&&a!=e)return h}return null},i.prototype.collision=function(t,e,n){return t.left-ne.left&&t.top-ne.top},e.exports=n=i},{"./util":8}],5:[function(t,e,n){function i(t){this.id=o.randomUUID(),this.start=0,this.end=0,this.options={min:null,max:null,zoomMin:null,zoomMax:null},this.setOptions(t),this.listeners=[]}var o=t("./util"),r=t("./events");i.prototype.setOptions=function(t){o.extend(this.options,t),(null!=t.start||null!=t.end)&&this.setRange(t.start,t.end)},i.prototype.subscribe=function(t,e,n){var i,o=this;if("horizontal"!=n&&"vertical"!=n)throw new TypeError('Unknown direction "'+n+'". '+'Choose "horizontal" or "vertical".');if("move"==e)i={component:t,event:e,direction:n,callback:function(t){o._onMouseDown(t,i)},params:{}},t.on("mousedown",i.callback),o.listeners.push(i);else{if("zoom"!=e)throw new TypeError('Unknown event "'+e+'". '+'Choose "move" or "zoom".');i={component:t,event:e,direction:n,callback:function(t){o._onMouseWheel(t,i)},params:{}},t.on("mousewheel",i.callback),o.listeners.push(i)}},i.prototype.on=function(t,e){r.addListener(this,t,e)},i.prototype._trigger=function(t){r.trigger(this,t,{start:this.start,end:this.end})},i.prototype.setRange=function(t,e){var n=this._applyRange(t,e);n&&(this._trigger("rangechange"),this._trigger("rangechanged"))},i.prototype._applyRange=function(t,e){var n,i=null!=t?o.cast(t,"Number"):this.start,r=null!=e?o.cast(e,"Number"):this.end;if(isNaN(i))throw Error('Invalid start "'+t+'"');if(isNaN(r))throw Error('Invalid end "'+e+'"');if(i>r&&(r=i),null!=this.options.min){var s=this.options.min.valueOf();s>i&&(n=s-i,i+=n,r+=n)}if(null!=this.options.max){var a=this.options.max.valueOf();r>a&&(n=r-a,i-=n,r-=n)}if(null!=this.options.zoomMin){var h=this.options.zoomMin.valueOf();0>h&&(h=0),h>r-i&&(this.end-this.start>h?(n=h-(r-i),i-=n/2,r+=n/2):(i=this.start,r=this.end))}if(null!=this.options.zoomMax){var c=this.options.zoomMax.valueOf();0>c&&(c=0),r-i>c&&(c>this.end-this.start?(n=r-i-c,i+=n/2,r-=n/2):(i=this.start,r=this.end))}var p=this.start!=i||this.end!=r;return this.start=i,this.end=r,p},i.prototype.getRange=function(){return{start:this.start,end:this.end}},i.prototype.conversion=function(t){return this.start,this.end,i.conversion(this.start,this.end,t)},i.conversion=function(t,e,n){return 0!=n&&0!=e-t?{offset:t,factor:n/(e-t)}:{offset:0,factor:1}},i.prototype._onMouseDown=function(t,e){t=t||window.event;var n=e.params,i=t.which?1==t.which:1==t.button;if(i){n.mouseX=o.getPageX(t),n.mouseY=o.getPageY(t),n.previousLeft=0,n.previousOffset=0,n.moved=!1,n.start=this.start,n.end=this.end;var r=e.component.frame;r&&(r.style.cursor="move");var s=this;n.onMouseMove||(n.onMouseMove=function(t){s._onMouseMove(t,e)},o.addEventListener(document,"mousemove",n.onMouseMove)),n.onMouseUp||(n.onMouseUp=function(t){s._onMouseUp(t,e)},o.addEventListener(document,"mouseup",n.onMouseUp)),o.preventDefault(t)}},i.prototype._onMouseMove=function(t,e){t=t||window.event;var n=e.params,i=o.getPageX(t),r=o.getPageY(t);void 0==n.mouseX&&(n.mouseX=i),void 0==n.mouseY&&(n.mouseY=r);var s=i-n.mouseX,a=r-n.mouseY,h="horizontal"==e.direction?s:a;Math.abs(h)>=1&&(n.moved=!0);var c=n.end-n.start,p="horizontal"==e.direction?e.component.width:e.component.height,u=-h/p*c;this._applyRange(n.start+u,n.end+u),this._trigger("rangechange"),o.preventDefault(t)},i.prototype._onMouseUp=function(t,e){t=t||window.event;var n=e.params;e.component.frame&&(e.component.frame.style.cursor="auto"),n.onMouseMove&&(o.removeEventListener(document,"mousemove",n.onMouseMove),n.onMouseMove=null),n.onMouseUp&&(o.removeEventListener(document,"mouseup",n.onMouseUp),n.onMouseUp=null),n.moved&&this._trigger("rangechanged")},i.prototype._onMouseWheel=function(t,e){t=t||window.event;var n=0;if(t.wheelDelta?n=t.wheelDelta/120:t.detail&&(n=-t.detail/3),n){var i=this,r=function(){var r=n/5,s=null,a=e.component.frame;if(a){var h,c;if("horizontal"==e.direction){h=e.component.width,c=i.conversion(h);var p=o.getAbsoluteLeft(a),u=o.getPageX(t);s=(u-p)/c.factor+c.offset}else{h=e.component.height,c=i.conversion(h);var l=o.getAbsoluteTop(a),d=o.getPageY(t);s=(l+h-d-l)/c.factor+c.offset}}i.zoom(r,s)};r()}o.preventDefault(t)},i.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 n=this.start-e,i=this.end-e,o=this.start-n*t,r=this.end-i*t;this.setRange(o,r)},i.prototype.move=function(t){var e=this.end-this.start,n=this.start+e*t,i=this.end+e*t;this.start=n,this.end=i},e.exports=n=i},{"./util":8,"./events":4}],9:[function(t,e,n){function i(){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}var o=t("./../util");i.prototype.setOptions=function(t){t&&o.extend(this.options,t),this.controller&&(this.requestRepaint(),this.requestReflow())},i.prototype.getContainer=function(){return null},i.prototype.getFrame=function(){return this.frame},i.prototype.repaint=function(){return!1},i.prototype.reflow=function(){return!1},i.prototype.requestRepaint=function(){if(!this.controller)throw Error("Cannot request a repaint: no controller configured");this.controller.requestRepaint()},i.prototype.requestReflow=function(){if(!this.controller)throw Error("Cannot request a reflow: no controller configured");this.controller.requestReflow()},i.prototype.on=function(t,e){if(!this.parent)throw Error("Cannot attach event: no root panel found");this.parent.on(t,e)},e.exports=n=i},{"./../util":8}],10:[function(t,e,n){function i(t,e,n){this.id=o.randomUUID(),this.parent=t,this.depends=e,this.options={},this.setOptions(n)}var o=t("../util"),r=t("./component");i.prototype=new r,i.prototype.getContainer=function(){return this.frame},i.prototype.repaint=function(){var t=0,e=o.updateProperty,n=o.option.asSize,i=this.options,r=this.frame;if(r||(r=document.createElement("div"),r.className="panel",i.className&&("function"==typeof i.className?o.addClassName(r,i.className()+""):o.addClassName(r,i.className+"")),this.frame=r,t+=1),!r.parentNode){if(!this.parent)throw Error("Cannot repaint panel: no parent attached");var s=this.parent.getContainer();if(!s)throw Error("Cannot repaint panel: parent has no container element");s.appendChild(r),t+=1}return t+=e(r.style,"top",n(i.top,"0px")),t+=e(r.style,"left",n(i.left,"0px")),t+=e(r.style,"width",n(i.width,"100%")),t+=e(r.style,"height",n(i.height,"100%")),t>0},i.prototype.reflow=function(){var t=0,e=o.updateProperty,n=this.frame;return n?(t+=e(this,"top",n.offsetTop),t+=e(this,"left",n.offsetLeft),t+=e(this,"width",n.offsetWidth),t+=e(this,"height",n.offsetHeight)):t+=1,t>0},e.exports=n=i},{"../util":8,"./component":9}],11:[function(t,e,n){function i(t,e){this.id=o.randomUUID(),this.container=t,this.options={autoResize:!0},this.listeners={},this.setOptions(e)}var o=t("../util"),r=t("./panel");i.prototype=new r,i.prototype.setOptions=function(t){o.extend(this.options,t),this.options.autoResize?this._watch():this._unwatch()},i.prototype.repaint=function(){var t=0,e=o.updateProperty,n=o.option.asSize,i=this.options,r=this.frame;if(r||(r=document.createElement("div"),r.className="graph panel",i.className&&o.addClassName(r,o.option.asString(i.className)),this.frame=r,t+=1),!r.parentNode){if(!this.container)throw Error("Cannot repaint root panel: no container attached");this.container.appendChild(r),t+=1}return t+=e(r.style,"top",n(i.top,"0px")),t+=e(r.style,"left",n(i.left,"0px")),t+=e(r.style,"width",n(i.width,"100%")),t+=e(r.style,"height",n(i.height,"100%")),this._updateEventEmitters(),t>0},i.prototype.reflow=function(){var t=0,e=o.updateProperty,n=this.frame;return n?(t+=e(this,"top",n.offsetTop),t+=e(this,"left",n.offsetLeft),t+=e(this,"width",n.offsetWidth),t+=e(this,"height",n.offsetHeight)):t+=1,t>0},i.prototype._watch=function(){var t=this;this._unwatch();var e=function(){return t.options.autoResize?(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)},i.prototype._unwatch=function(){this.watchTimer&&(clearInterval(this.watchTimer),this.watchTimer=void 0)},i.prototype.on=function(t,e){var n=this.listeners[t];n||(n=[],this.listeners[t]=n),n.push(e),this._updateEventEmitters()},i.prototype._updateEventEmitters=function(){if(this.listeners){var t=this;o.forEach(this.listeners,function(e,n){if(t.emitters||(t.emitters={}),!(n in t.emitters)){var i=t.frame;if(i){var r=function(t){e.forEach(function(e){e(t)})};t.emitters[n]=r,o.addEventListener(i,n,r)}}})}},e.exports=n=i},{"../util":8,"./panel":10}],12:[function(t,e,n){function i(t,e,n){this.id=o.randomUUID(),this.parent=t,this.depends=e,this.options={style:"box",align:"center",orientation:"bottom",margin:{axis:20,item:10},padding:5},this.dom={};var i=this;this.data=null,this.range=null,this.listeners={add:function(t,e){i._onAdd(e.items)},update:function(t,e){i._onUpdate(e.items)},remove:function(t,e){i._onRemove(e.items)}},this.items={},this.queue={},this.stack=new a(this),this.conversion=null,this.setOptions(n)}var o=t("../util"),r=t("../dataset"),s=t("./panel"),a=t("../stack"),h=t("./item/itembox"),c=t("./item/itemrange"),p=t("./item/itempoint");i.prototype=new s,i.types={box:h,range:c,point:p},i.prototype.setOptions=function(t){o.extend(this.options,t),this.stack.setOptions(this.options)},i.prototype.setRange=function(t){if(!(t instanceof Range||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},i.prototype.repaint=function(){var t=0,e=o.updateProperty,n=o.option.asSize,r=this.options,s=this.frame;if(!s){s=document.createElement("div"),s.className="itemset",r.className&&o.addClassName(s,o.option.asString(r.className));var a=document.createElement("div");a.className="background",s.appendChild(a),this.dom.background=a;var h=document.createElement("div");h.className="foreground",s.appendChild(h),this.dom.foreground=h;var c=document.createElement("div");c.className="itemset-axis",this.dom.axis=c,this.frame=s,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");s.parentNode||(p.appendChild(s),t+=1),this.dom.axis.parentNode||(p.appendChild(this.dom.axis),t+=1),t+=e(s.style,"height",n(r.height,this.height+"px")),t+=e(s.style,"top",n(r.top,"0px")),t+=e(s.style,"left",n(r.left,"0px")),t+=e(s.style,"width",n(r.width,"100%")),t+=e(this.dom.axis.style,"top",n(r.top,"0px")),this._updateConversion();var u=this,l=this.queue,d=this.data,f=this.items,m={fields:["id","start","end","content","type"]};return Object.keys(l).forEach(function(e){var n=l[e],o=n.item;switch(n.action){case"add":case"update":var s=d.get(e,m),a=s.type||s.start&&s.end&&"range"||"box",h=i.types[a];if(o&&(h&&o instanceof h?(o.data=s,t+=o.repaint()):(o.visible=!1,t+=o.repaint(),o=null)),!o){if(!h)throw new TypeError('Unknown item type "'+a+'"');o=new h(u,s,r),t+=o.repaint()}f[e]=o,delete l[e];break;case"remove":o&&(o.visible=!1,t+=o.repaint()),delete f[e],delete l[e];break;default:console.log('Error: unknown action "'+n.action+'"')}}),o.forEach(this.items,function(t){t.reposition()}),t>0},i.prototype.getForeground=function(){return this.dom.foreground},i.prototype.getBackground=function(){return this.dom.background},i.prototype.reflow=function(){var t=0,e=this.options,n=o.updateProperty,i=o.option.asNumber,r=this.frame;if(r){this._updateConversion(),o.forEach(this.items,function(e){t+=e.reflow()}),this.stack.update();var s,a=i(e.maxHeight);if(null!=e.height)s=r.offsetHeight,null!=a&&(s=Math.min(s,a)),t+=n(this,"height",s);else{var h=this.height;s=0,"top"==e.orientation?o.forEach(this.items,function(t){s=Math.max(s,t.top+t.height)}):o.forEach(this.items,function(t){s=Math.max(s,h-t.top)}),s+=e.margin.axis,null!=a&&(s=Math.min(s,a)),t+=n(this,"height",s)}t+=n(this,"top",r.offsetTop),t+=n(this,"left",r.offsetLeft),t+=n(this,"width",r.offsetWidth)}else t+=1;return t>0},i.prototype.setData=function(t){var e=this.data;e&&o.forEach(this.listeners,function(t,n){e.unsubscribe(n,t)}),t instanceof r?this.data=t:(this.data=new r({fieldTypes:{start:"Date",end:"Date"}}),this.data.add(t));var n=this.id,i=this;o.forEach(this.listeners,function(t,e){i.data.subscribe(e,t,n)});var s=this.data.get({filter:["id"]}),a=[];o.forEach(s,function(t,e){a[e]=t.id}),this._onAdd(a)},i.prototype.getDataRange=function(){var t=this.data,e=t.min("start");e=e?e.start.valueOf():null;var n=t.max("start"),i=t.max("end");n=n?n.start.valueOf():null,i=i?i.end.valueOf():null;var o=Math.max(n,i);return{min:new Date(e),max:new Date(o)}},i.prototype._onUpdate=function(t){this._toQueue(t,"update")},i.prototype._onAdd=function(t){this._toQueue(t,"add")},i.prototype._onRemove=function(t){this._toQueue(t,"remove")},i.prototype._toQueue=function(t,e){var n=this.items,i=this.queue;t.forEach(function(t){var o=i[t];o?o.action=e:i[t]={item:n[t]||null,action:e}}),this.controller&&this.requestRepaint()},i.prototype._updateConversion=function(){var t=this.range;if(!t)throw Error("No range configured");this.conversion=t.conversion?t.conversion(this.width):Range.conversion(t.start,t.end,this.width)},i.prototype.toTime=function(t){var e=this.conversion;return new Date(t/e.factor+e.offset)},i.prototype.toScreen=function(t){var e=this.conversion;return(t.valueOf()-e.offset)*e.factor},e.exports=n=i},{"../util":8,"../dataset":3,"./panel":10,"../stack":6,"./item/itembox":15,"./item/itempoint":16,"./item/itemrange":17}],14:[function(t,e,n){function i(t,e,n){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={orientation:"bottom",showMinorLabels:!0,showMajorLabels:!0},this.conversion=null,this.range=null,this.setOptions(n)}var o=t("../util"),r=t("../timestep"),s=t("./component");i.prototype=new s,i.prototype.setOptions=function(t){o.extend(this.options,t)},i.prototype.setRange=function(t){if(!(t instanceof Range||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},i.prototype.toTime=function(t){var e=this.conversion;return new Date(t/e.factor+e.offset)},i.prototype.toScreen=function(t){var e=this.conversion;return(t.valueOf()-e.offset)*e.factor},i.prototype.repaint=function(){var t=0,e=o.updateProperty,n=o.option.asSize,i=this.options,r=this.props,s=this.step,a=this.frame;if(a||(a=document.createElement("div"),this.frame=a,t+=1),a.className="axis "+i.orientation,!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 c=a.parentNode;if(c){var p=a.nextSibling;c.removeChild(a);var u=i.orientation,l="bottom"==u&&this.props.parentHeight&&this.height?this.props.parentHeight-this.height+"px":"0px";if(t+=e(a.style,"top",n(i.top,l)),t+=e(a.style,"left",n(i.left,"0px")),t+=e(a.style,"width",n(i.width,"100%")),t+=e(a.style,"height",n(i.height,this.height+"px")),this._repaintMeasureChars(),this.step){this._repaintStart(),s.first();for(var d=void 0,f=0;s.hasNext()&&1e3>f;){f++;var m=s.getCurrent(),g=this.toScreen(m),v=s.isMajor();i.showMinorLabels&&this._repaintMinorText(g,s.getLabelMinor()),v&&i.showMajorLabels?(g>0&&(void 0==d&&(d=g),this._repaintMajorText(g,s.getLabelMajor())),this._repaintMajorLine(g)):this._repaintMinorLine(g),s.next()}if(i.showMajorLabels){var y=this.toTime(0),S=s.getLabelMajor(y),T=S.length*(r.majorCharWidth||10)+10;(void 0==d||d>T)&&this._repaintMajorText(0,S)}this._repaintEnd()}this._repaintLine(),p?c.insertBefore(a,p):c.appendChild(a)}return t>0
+},i.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=[]},i.prototype._repaintEnd=function(){o.forEach(this.dom.redundant,function(t){for(;t.length;){var e=t.pop();e&&e.parentNode&&e.parentNode.removeChild(e)}})},i.prototype._repaintMinorText=function(t,e){var n=this.dom.redundant.minorTexts.shift();if(!n){var i=document.createTextNode("");n=document.createElement("div"),n.appendChild(i),n.className="text minor",this.frame.appendChild(n)}this.dom.minorTexts.push(n),n.childNodes[0].nodeValue=e,n.style.left=t+"px",n.style.top=this.props.minorLabelTop+"px"},i.prototype._repaintMajorText=function(t,e){var n=this.dom.redundant.majorTexts.shift();if(!n){var i=document.createTextNode(e);n=document.createElement("div"),n.className="text major",n.appendChild(i),this.frame.appendChild(n)}this.dom.majorTexts.push(n),n.childNodes[0].nodeValue=e,n.style.top=this.props.majorLabelTop+"px",n.style.left=t+"px"},i.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 n=this.props;e.style.top=n.minorLineTop+"px",e.style.height=n.minorLineHeight+"px",e.style.left=t-n.minorLineWidth/2+"px"},i.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 n=this.props;e.style.top=n.majorLineTop+"px",e.style.left=t-n.majorLineWidth/2+"px",e.style.height=n.majorLineHeight+"px"},i.prototype._repaintLine=function(){var t=this.dom.line,e=this.frame,n=this.options;n.showMinorLabels||n.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)},i.prototype._repaintMeasureChars=function(){var t,e=this.dom;if(!e.characterMinor){t=document.createTextNode("0");var n=document.createElement("DIV");n.className="text minor measure",n.appendChild(t),this.frame.appendChild(n),e.measureCharMinor=n}if(!e.characterMajor){t=document.createTextNode("0");var i=document.createElement("DIV");i.className="text major measure",i.appendChild(t),this.frame.appendChild(i),e.measureCharMajor=i}},i.prototype.reflow=function(){var t=0,e=o.updateProperty,n=this.frame,i=this.range;if(!i)throw Error("Cannot repaint time axis: no range configured");if(n){t+=e(this,"top",n.offsetTop),t+=e(this,"left",n.offsetLeft);var s=this.props,a=this.options.showMinorLabels,h=this.options.showMajorLabels,c=this.dom.measureCharMinor,p=this.dom.measureCharMajor;c&&(s.minorCharHeight=c.clientHeight,s.minorCharWidth=c.clientWidth),p&&(s.majorCharHeight=p.clientHeight,s.majorCharWidth=p.clientWidth);var u=n.parentNode?n.parentNode.offsetHeight:0;switch(u!=s.parentHeight&&(s.parentHeight=u,t+=1),this.options.orientation){case"bottom":s.minorLabelHeight=a?s.minorCharHeight:0,s.majorLabelHeight=h?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=a?s.minorCharHeight:0,s.majorLabelHeight=h?s.majorCharHeight:0,s.majorLabelTop=0,s.minorLabelTop=s.majorLabelTop+s.majorLabelHeight,s.minorLineTop=s.minorLabelTop,s.minorLineHeight=Math.max(u-s.majorLabelHeight-this.top),s.minorLineWidth=1,s.majorLineTop=0,s.majorLineHeight=Math.max(u-this.top),s.majorLineWidth=1,s.lineTop=s.majorLabelHeight+s.minorLabelHeight;break;default:throw Error('Unkown orientation "'+this.options.orientation+'"')}var l=s.minorLabelHeight+s.majorLabelHeight;t+=e(this,"width",n.offsetWidth),t+=e(this,"height",l),this._updateConversion();var d=o.cast(i.start,"Date"),f=o.cast(i.end,"Date"),m=this.toTime(5*(s.minorCharWidth||10))-this.toTime(0);this.step=new r(d,f,m),t+=e(s.range,"start",d.valueOf()),t+=e(s.range,"end",f.valueOf()),t+=e(s.range,"minimumStep",m.valueOf())}return t>0},i.prototype._updateConversion=function(){var t=this.range;if(!t)throw Error("No range configured");this.conversion=t.conversion?t.conversion(this.width):Range.conversion(t.start,t.end,this.width)},e.exports=n=i},{"../util":8,"../timestep":7,"./component":9}],7:[function(t,e,n){var i=(t("./util"),t("moment"));TimeStep=function(t,e,n){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,n)},TimeStep.SCALE={MILLISECOND:1,SECOND:2,MINUTE:3,HOUR:4,DAY:5,WEEKDAY:6,MONTH:7,YEAR:8},TimeStep.prototype.setRange=function(t,e,n){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(n))},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,n=2592e6,i=864e5,o=36e5,r=6e4,s=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*n>t&&(this.scale=TimeStep.SCALE.MONTH,this.step=3),n>t&&(this.scale=TimeStep.SCALE.MONTH,this.step=1),5*i>t&&(this.scale=TimeStep.SCALE.DAY,this.step=5),2*i>t&&(this.scale=TimeStep.SCALE.DAY,this.step=2),i>t&&(this.scale=TimeStep.SCALE.DAY,this.step=1),i/2>t&&(this.scale=TimeStep.SCALE.WEEKDAY,this.step=1),4*o>t&&(this.scale=TimeStep.SCALE.HOUR,this.step=4),o>t&&(this.scale=TimeStep.SCALE.HOUR,this.step=1),15*r>t&&(this.scale=TimeStep.SCALE.MINUTE,this.step=15),10*r>t&&(this.scale=TimeStep.SCALE.MINUTE,this.step=10),5*r>t&&(this.scale=TimeStep.SCALE.MINUTE,this.step=5),r>t&&(this.scale=TimeStep.SCALE.MINUTE,this.step=1),15*s>t&&(this.scale=TimeStep.SCALE.SECOND,this.step=15),10*s>t&&(this.scale=TimeStep.SCALE.SECOND,this.step=10),5*s>t&&(this.scale=TimeStep.SCALE.SECOND,this.step=5),s>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 n=this.step>5?this.step/2:1;t.setMilliseconds(Math.round(t.getMilliseconds()/n)*n)}},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 i(t).format("SSS");case TimeStep.SCALE.SECOND:return i(t).format("s");case TimeStep.SCALE.MINUTE:return i(t).format("HH:mm");case TimeStep.SCALE.HOUR:return i(t).format("HH:mm");case TimeStep.SCALE.WEEKDAY:return i(t).format("ddd D");case TimeStep.SCALE.DAY:return i(t).format("D");case TimeStep.SCALE.MONTH:return i(t).format("MMM");case TimeStep.SCALE.YEAR:return i(t).format("YYYY");default:return""}},TimeStep.prototype.getLabelMajor=function(t){switch(void 0==t&&(t=this.current),this.scale){case TimeStep.SCALE.MILLISECOND:return i(t).format("HH:mm:ss");case TimeStep.SCALE.SECOND:return i(t).format("D MMMM HH:mm");case TimeStep.SCALE.MINUTE:case TimeStep.SCALE.HOUR:return i(t).format("ddd D MMMM");case TimeStep.SCALE.WEEKDAY:case TimeStep.SCALE.DAY:return i(t).format("MMMM YYYY");case TimeStep.SCALE.MONTH:return i(t).format("YYYY");case TimeStep.SCALE.YEAR:return"";default:return""}},e.exports=n=TimeStep},{"./util":8,moment:18}],16:[function(t,e,n){function i(t,e,n){this.props={dot:{top:0,width:0,height:0},content:{height:0,marginLeft:0}},r.call(this,t,e,n)}var o=t("../../util"),r=t("./item");i.prototype=new r(null,null),i.prototype.select=function(){this.selected=!0},i.prototype.unselect=function(){this.selected=!1},i.prototype.repaint=function(){var t=!1,e=this.dom;if(this.visible){if(e||(this._create(),t=!0),e=this.dom){if(!this.options&&!this.options.parent)throw Error("Cannot repaint item: no parent attached");var n=this.parent.getForeground();if(!n)throw Error("Cannot repaint time axis: parent has no foreground container element");if(e.point.parentNode||(n.appendChild(e.point),n.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 i=(this.data.className?" "+this.data.className:"")+(this.selected?" selected":"");this.className!=i&&(this.className=i,e.point.className="item point"+i,t=!0)}}else e&&e.point.parentNode&&(e.point.parentNode.removeChild(e.point),t=!0);return t},i.prototype.reflow=function(){if(void 0==this.data.start)throw Error('Property "start" missing in item '+this.data.id);var t,e=o.updateProperty,n=this.dom,i=this.props,r=this.options,s=r.orientation,a=this.parent.toScreen(this.data.start),h=0;if(n){if(h+=e(this,"width",n.point.offsetWidth),h+=e(this,"height",n.point.offsetHeight),h+=e(i.dot,"width",n.dot.offsetWidth),h+=e(i.dot,"height",n.dot.offsetHeight),h+=e(i.content,"height",n.content.offsetHeight),"top"==s)t=r.margin.axis;else{var c=this.parent.height;t=Math.max(c-this.height-r.margin.axis,0)}h+=e(this,"top",t),h+=e(this,"left",a-i.dot.width/2),h+=e(i.content,"marginLeft",1.5*i.dot.width),h+=e(i.dot,"top",(this.height-i.dot.height)/2)}else h+=1;return h>0},i.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))},i.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")},e.exports=n=i},{"../../util":8,"./item":19}],15:[function(t,e,n){function i(t,e,n){this.props={dot:{left:0,top:0,width:0,height:0},line:{top:0,left:0,width:0,height:0}},r.call(this,t,e,n)}var o=t("../../util"),r=t("./item");i.prototype=new r(null,null),i.prototype.select=function(){this.selected=!0},i.prototype.unselect=function(){this.selected=!1},i.prototype.repaint=function(){var t=!1,e=this.dom;if(this.visible){if(e||(this._create(),t=!0),e=this.dom){if(!this.options&&!this.parent)throw Error("Cannot repaint item: no parent attached");var n=this.parent.getForeground();if(!n)throw Error("Cannot repaint time axis: parent has no foreground container element");var i=this.parent.getBackground();if(!i)throw Error("Cannot repaint time axis: parent has no background container element");if(e.box.parentNode||(n.appendChild(e.box),t=!0),e.line.parentNode||(i.appendChild(e.line),t=!0),e.dot.parentNode||(this.parent.dom.axis.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)}}else e&&(e.box.parentNode&&(e.box.parentNode.removeChild(e.box),t=!0),e.line.parentNode&&(e.line.parentNode.removeChild(e.line),t=!0),e.dot.parentNode&&(e.dot.parentNode.removeChild(e.dot),t=!0));return t},i.prototype.reflow=function(){if(void 0==this.data.start)throw Error('Property "start" missing in item '+this.data.id);var t,e,n=o.updateProperty,i=this.dom,r=this.props,s=this.options,a=this.parent.toScreen(this.data.start),h=s&&s.align,c=s.orientation,p=0;if(i)if(p+=n(r.dot,"height",i.dot.offsetHeight),p+=n(r.dot,"width",i.dot.offsetWidth),p+=n(r.line,"width",i.line.offsetWidth),p+=n(r.line,"width",i.line.offsetWidth),p+=n(this,"width",i.box.offsetWidth),p+=n(this,"height",i.box.offsetHeight),e="right"==h?a-this.width:"left"==h?a:a-this.width/2,p+=n(this,"left",e),p+=n(r.line,"left",a-r.line.width/2),p+=n(r.dot,"left",a-r.dot.width/2),"top"==c)t=s.margin.axis,p+=n(this,"top",t),p+=n(r.line,"top",0),p+=n(r.line,"height",t),p+=n(r.dot,"top",-r.dot.height/2);else{var u=this.parent.height;t=u-this.height-s.margin.axis,p+=n(this,"top",t),p+=n(r.line,"top",t+this.height),p+=n(r.line,"height",Math.max(s.margin.axis,0)),p+=n(r.dot,"top",u-r.dot.height/2)}else p+=1;return p>0},i.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")},i.prototype.reposition=function(){var t=this.dom,e=this.props,n=this.options.orientation;if(t){var i=t.box,o=t.line,r=t.dot;i.style.left=this.left+"px",i.style.top=this.top+"px",o.style.left=e.line.left+"px","top"==n?(o.style.top="0px",o.style.height=this.top+"px"):(o.style.top=e.line.top+"px",o.style.top=this.top+this.height+"px",o.style.height=Math.max(e.dot.top-this.top-this.height,0)+"px"),r.style.left=e.dot.left+"px",r.style.top=e.dot.top+"px"}},e.exports=n=i},{"../../util":8,"./item":19}],17:[function(t,e,n){function i(t,e,n){this.props={content:{left:0,width:0}},r.call(this,t,e,n)}var o=t("../../util"),r=t("./item");i.prototype=new r(null,null),i.prototype.select=function(){this.selected=!0},i.prototype.unselect=function(){this.selected=!1},i.prototype.repaint=function(){var t=!1,e=this.dom;if(this.visible){if(e||(this._create(),t=!0),e=this.dom){if(!this.options&&!this.options.parent)throw Error("Cannot repaint item: no parent attached");var n=this.parent.getForeground();if(!n)throw Error("Cannot repaint time axis: parent has no foreground container element");if(e.box.parentNode||(n.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 i=this.data.className?""+this.data.className:"";this.className!=i&&(this.className=i,e.box.className="item range"+i,t=!0)}}else e&&e.box.parentNode&&(e.box.parentNode.removeChild(e.box),t=!0);return t},i.prototype.reflow=function(){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);var t=this.dom,e=this.props,n=this.options,i=this.parent,r=i.toScreen(this.data.start),s=i.toScreen(this.data.end),a=0;if(t){var h,c,p=o.updateProperty,u=t.box,l=i.width,d=n.orientation;a+=p(e.content,"width",t.content.offsetWidth),a+=p(this,"height",u.offsetHeight),-l>r&&(r=-l),s>2*l&&(s=2*l),h=0>r?Math.min(-r,s-r-e.content.width-2*n.padding):0,a+=p(e.content,"left",h),"top"==d?(c=n.margin.axis,a+=p(this,"top",c)):(c=i.height-this.height-n.margin.axis,a+=p(this,"top",c)),a+=p(this,"left",r),a+=p(this,"width",Math.max(s-r,1))}else a+=1;return a>0},i.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))},i.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")},e.exports=n=i},{"../../util":8,"./item":19}],18:[function(e,n){(function(){(function(i){function o(t,e){return function(n){return u(t.call(this,n),e)}}function r(t){return function(e){return this.lang().ordinal(t.call(this,e))}}function s(){}function a(t){c(this,t)}function h(t){var e=this._data={},n=t.years||t.year||t.y||0,i=t.months||t.month||t.M||0,o=t.weeks||t.week||t.w||0,r=t.days||t.day||t.d||0,s=t.hours||t.hour||t.h||0,a=t.minutes||t.minute||t.m||0,h=t.seconds||t.second||t.s||0,c=t.milliseconds||t.millisecond||t.ms||0;this._milliseconds=c+1e3*h+6e4*a+36e5*s,this._days=r+7*o,this._months=i+12*n,e.milliseconds=c%1e3,h+=p(c/1e3),e.seconds=h%60,a+=p(h/60),e.minutes=a%60,s+=p(a/60),e.hours=s%24,r+=p(s/24),r+=7*o,e.days=r%30,i+=p(r/30),e.months=i%12,n+=p(i/12),e.years=n}function c(t,e){for(var n in e)e.hasOwnProperty(n)&&(t[n]=e[n]);return t}function p(t){return 0>t?Math.ceil(t):Math.floor(t)}function u(t,e){for(var n=t+"";e>n.length;)n="0"+n;return n}function l(t,e,n){var i,o=e._milliseconds,r=e._days,s=e._months;o&&t._d.setTime(+t+o*n),r&&t.date(t.date()+r*n),s&&(i=t.date(),t.date(1).month(t.month()+s*n).date(Math.min(i,t.daysInMonth())))}function d(t){return"[object Array]"===Object.prototype.toString.call(t)}function f(t,e){var n,i=Math.min(t.length,e.length),o=Math.abs(t.length-e.length),r=0;for(n=0;i>n;n++)~~t[n]!==~~e[n]&&r++;return r+o}function m(t,e){return e.abbr=t,R[t]||(R[t]=new s),R[t].set(e),R[t]}function g(t){return t?(!R[t]&&U&&e("./lang/"+t),R[t]):k.fn._lang}function v(t){return t.match(/\[.*\]/)?t.replace(/^\[|\]$/g,""):t.replace(/\\/g,"")}function y(t){var e,n,i=t.match(z);for(e=0,n=i.length;n>e;e++)i[e]=ae[i[e]]?ae[i[e]]:v(i[e]);return function(o){var r="";for(e=0;n>e;e++)r+="function"==typeof i[e].call?i[e].call(o,t):i[e];return r}}function S(t,e){function n(e){return t.lang().longDateFormat(e)||e}for(var i=5;i--&&P.test(e);)e=e.replace(P,n);return oe[e]||(oe[e]=y(e)),oe[e](t)}function T(t){switch(t){case"DDDD":return V;case"YYYY":return B;case"YYYYY":return Z;case"S":case"SS":case"SSS":case"DDD":return q;case"MMM":case"MMMM":case"dd":case"ddd":case"dddd":case"a":case"A":return X;case"X":return $;case"Z":case"ZZ":return K;case"T":return J;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 w(t,e,n){var i,o=n._a;switch(t){case"M":case"MM":o[1]=null==e?0:~~e-1;break;case"MMM":case"MMMM":i=g(n._l).monthsParse(e),null!=i?o[1]=i:n._isValid=!1;break;case"D":case"DD":case"DDD":case"DDDD":null!=e&&(o[2]=~~e);break;case"YY":o[0]=~~e+(~~e>68?1900:2e3);break;case"YYYY":case"YYYYY":o[0]=~~e;break;case"a":case"A":n._isPm="pm"===(e+"").toLowerCase();break;case"H":case"HH":case"h":case"hh":o[3]=~~e;break;case"m":case"mm":o[4]=~~e;break;case"s":case"ss":o[5]=~~e;break;case"S":case"SS":case"SSS":o[6]=~~(1e3*("0."+e));break;case"X":n._d=new Date(1e3*parseFloat(e));break;case"Z":case"ZZ":n._useUTC=!0,i=(e+"").match(ee),i&&i[1]&&(n._tzh=~~i[1]),i&&i[2]&&(n._tzm=~~i[2]),i&&"+"===i[0]&&(n._tzh=-n._tzh,n._tzm=-n._tzm)}null==e&&(n._isValid=!1)}function E(t){var e,n,i=[];if(!t._d){for(e=0;7>e;e++)t._a[e]=i[e]=null==t._a[e]?2===e?1:0:t._a[e];i[3]+=t._tzh||0,i[4]+=t._tzm||0,n=new Date(0),t._useUTC?(n.setUTCFullYear(i[0],i[1],i[2]),n.setUTCHours(i[3],i[4],i[5],i[6])):(n.setFullYear(i[0],i[1],i[2]),n.setHours(i[3],i[4],i[5],i[6])),t._d=n}}function b(t){var e,n,i=t._f.match(z),o=t._i;for(t._a=[],e=0;i.length>e;e++)n=(T(i[e]).exec(o)||[])[0],n&&(o=o.slice(o.indexOf(n)+n.length)),ae[i[e]]&&w(i[e],n,t);t._isPm&&12>t._a[3]&&(t._a[3]+=12),t._isPm===!1&&12===t._a[3]&&(t._a[3]=0),E(t)}function M(t){for(var e,n,i,o,r=99;t._f.length;){if(e=c({},t),e._f=t._f.pop(),b(e),n=new a(e),n.isValid()){i=n;break}o=f(e._a,n.toArray()),r>o&&(r=o,i=n)}c(t,i)}function _(t){var e,n=t._i;if(Q.exec(n)){for(t._f="YYYY-MM-DDT",e=0;4>e;e++)if(te[e][1].exec(n)){t._f+=te[e][0];break}K.exec(n)&&(t._f+=" Z"),b(t)}else t._d=new Date(n)}function D(t){var e=t._i,n=F.exec(e);e===i?t._d=new Date:n?t._d=new Date(+n[1]):"string"==typeof e?_(t):d(e)?(t._a=e.slice(0),E(t)):t._d=e instanceof Date?new Date(+e):new Date(e)}function L(t,e,n,i,o){return o.relativeTime(e||1,!!n,t,i)}function C(t,e,n){var i=j(Math.abs(t)/1e3),o=j(i/60),r=j(o/60),s=j(r/24),a=j(s/365),h=45>i&&["s",i]||1===o&&["m"]||45>o&&["mm",o]||1===r&&["h"]||22>r&&["hh",r]||1===s&&["d"]||25>=s&&["dd",s]||45>=s&&["M"]||345>s&&["MM",j(s/30)]||1===a&&["y"]||["yy",a];return h[2]=e,h[3]=t>0,h[4]=n,L.apply({},h)}function x(t,e,n){var i=n-e,o=n-t.day();return o>i&&(o-=7),i-7>o&&(o+=7),Math.ceil(k(t).add("d",o).dayOfYear()/7)}function A(t){var e=t._i,n=t._f;return null===e||""===e?null:("string"==typeof e&&(t._i=e=g().preparse(e)),k.isMoment(e)?(t=c({},e),t._d=new Date(+e._d)):n?d(n)?M(t):b(t):D(t),new a(t))}function N(t,e){k.fn[t]=k.fn[t+"s"]=function(t){var n=this._isUTC?"UTC":"";return null!=t?(this._d["set"+n+e](t),this):this._d["get"+n+e]()}}function O(t){k.duration.fn[t]=function(){return this._data[t]}}function Y(t,e){k.duration.fn["as"+t]=function(){return+this/e}}for(var k,H,I="2.0.0",j=Math.round,R={},U=n!==i&&n.exports,F=/^\/?Date\((\-?\d+)/i,z=/(\[[^\[]*\])|(\\)?(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,P=/(\[[^\[]*\])|(\\)?(LT|LL?L?L?|l{1,4})/g,W=/\d\d?/,q=/\d{1,3}/,V=/\d{3}/,B=/\d{1,4}/,Z=/[+\-]?\d{1,6}/,X=/[0-9]*[a-z\u00A0-\u05FF\u0700-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF]+|[\u0600-\u06FF]+\s*?[\u0600-\u06FF]+/i,K=/Z|[\+\-]\d\d:?\d\d/i,J=/T/i,$=/[\+\-]?\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)?)?/,G="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,ne="Month|Date|Hours|Minutes|Seconds|Milliseconds".split("|"),ie={Milliseconds:1,Seconds:1e3,Minutes:6e4,Hours:36e5,Days:864e5,Months:2592e6,Years:31536e6},oe={},re="DDD w W M D d".split(" "),se="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 u(this.year()%100,2)},YYYY:function(){return u(this.year(),4)},YYYYY:function(){return u(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 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)},X:function(){return this.unix()}};re.length;)H=re.pop(),ae[H+"o"]=r(ae[H]);for(;se.length;)H=se.pop(),ae[H+H]=o(ae[H],2);for(ae.DDDD=o(ae.DDD,3),s.prototype={set:function(t){var e,n;for(n in t)e=t[n],"function"==typeof e?this[n]=e:this["_"+n]=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,n,i;for(this._monthsParse||(this._monthsParse=[]),e=0;12>e;e++)if(this._monthsParse[e]||(n=k([2e3,e]),i="^"+this.months(n,"")+"|^"+this.monthsShort(n,""),this._monthsParse[e]=RegExp(i.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,n){return t>11?n?"pm":"PM":n?"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 n=this._calendar[t];return"function"==typeof n?n.apply(e):n},_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,n,i){var o=this._relativeTime[n];return"function"==typeof o?o(t,e,n,i):o.replace(/%d/i,t)},pastFuture:function(t,e){var n=this._relativeTime[t>0?"future":"past"];
+return"function"==typeof n?n(e):n.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 x(t,this._week.dow,this._week.doy)},_week:{dow:0,doy:6}},k=function(t,e,n){return A({_i:t,_f:e,_l:n,_isUTC:!1})},k.utc=function(t,e,n){return A({_useUTC:!0,_isUTC:!0,_l:n,_i:t,_f:e})},k.unix=function(t){return k(1e3*t)},k.duration=function(t,e){var n,i=k.isDuration(t),o="number"==typeof t,r=i?t._data:o?{}:t;return o&&(e?r[e]=t:r.milliseconds=t),n=new h(r),i&&t.hasOwnProperty("_lang")&&(n._lang=t._lang),n},k.version=I,k.defaultFormat=G,k.lang=function(t,e){return t?(e?m(t,e):R[t]||g(t),k.duration.fn._lang=k.fn._lang=g(t),i):k.fn._lang._abbr},k.langData=function(t){return t&&t._lang&&t._lang._abbr&&(t=t._lang._abbr),g(t)},k.isMoment=function(t){return t instanceof a},k.isDuration=function(t){return t instanceof h},k.fn=a.prototype={clone:function(){return k(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 k.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?k.utc(this._a):k(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=S(this,t||k.defaultFormat);return this.lang().postformat(e)},add:function(t,e){var n;return n="string"==typeof t?k.duration(+e,t):k.duration(t,e),l(this,n,1),this},subtract:function(t,e){var n;return n="string"==typeof t?k.duration(+e,t):k.duration(t,e),l(this,n,-1),this},diff:function(t,e,n){var i,o,r=this._isUTC?k(t).utc():k(t).local(),s=6e4*(this.zone()-r.zone());return e&&(e=e.replace(/s$/,"")),"year"===e||"month"===e?(i=432e5*(this.daysInMonth()+r.daysInMonth()),o=12*(this.year()-r.year())+(this.month()-r.month()),o+=(this-k(this).startOf("month")-(r-k(r).startOf("month")))/i,"year"===e&&(o/=12)):(i=this-r-s,o="second"===e?i/1e3:"minute"===e?i/6e4:"hour"===e?i/36e5:"day"===e?i/864e5:"week"===e?i/6048e5:i),n?o:p(o)},from:function(t,e){return k.duration(this.diff(t)).lang(this.lang()._abbr).humanize(!e)},fromNow:function(t){return this.from(k(),t)},calendar:function(){var t=this.diff(k().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()+k(t).startOf(e)},isBefore:function(t,e){return e=e!==i?e:"millisecond",+this.clone().startOf(e)<+k(t).startOf(e)},isSame:function(t,e){return e=e!==i?e:"millisecond",+this.clone().startOf(e)===+k(t).startOf(e)},zone:function(){return this._isUTC?0:this._d.getTimezoneOffset()},daysInMonth:function(){return k.utc([this.year(),this.month()+1,0]).date()},dayOfYear:function(t){var e=j((k(this).startOf("day")-k(this).startOf("year"))/864e5)+1;return null==t?e:this.add("d",t-e)},isoWeek:function(t){var e=x(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===i?this._lang:(this._lang=g(t),this)}},H=0;ne.length>H;H++)N(ne[H].toLowerCase().replace(/s$/,""),ne[H]);N("year","FullYear"),k.fn.days=k.fn.day,k.fn.weeks=k.fn.week,k.fn.isoWeeks=k.fn.isoWeek,k.duration.fn=h.prototype={weeks:function(){return p(this.days()/7)},valueOf:function(){return this._milliseconds+864e5*this._days+2592e6*this._months},humanize:function(t){var e=+this,n=C(e,!t,this.lang());return t&&(n=this.lang().pastFuture(e,n)),this.lang().postformat(n)},lang:k.fn.lang};for(H in ie)ie.hasOwnProperty(H)&&(Y(H,ie[H]),O(H.toLowerCase()));Y("Weeks",6048e5),k.lang("en",{ordinal:function(t){var e=t%10,n=1===~~(t%100/10)?"th":1===e?"st":2===e?"nd":3===e?"rd":"th";return t+n}}),U&&(n.exports=k),"undefined"==typeof ender&&(this.moment=k),"function"==typeof t&&t.amd&&t("moment",[],function(){return k})}).call(this)})()},{}],13:[function(t,e,n){function i(t,e,n){var i=this;if(this.options={orientation:"bottom",zoomMin:10,zoomMax:31536e10,moveable:!0,zoomable:!0},this.controller=new a,!t)throw Error("No container element provided");this.main=new h(t,{autoResize:!1,height:function(){return i.timeaxis.height+i.itemset.height}}),this.controller.add(this.main);var o=r().hours(0).minutes(0).seconds(0).milliseconds(0);this.range=new s({start:o.clone().add("days",-3).valueOf(),end:o.clone().add("days",4).valueOf()}),this.range.subscribe(this.main,"move","horizontal"),this.range.subscribe(this.main,"zoom","horizontal"),this.range.on("rangechange",function(){i.controller.requestReflow()}),this.range.on("rangechanged",function(){i.controller.requestReflow()}),this.timeaxis=new c(this.main,[],{orientation:this.options.orientation,range:this.range}),this.timeaxis.setRange(this.range),this.controller.add(this.timeaxis),this.itemset=new p(this.main,[this.timeaxis],{orientation:this.options.orientation}),this.itemset.setRange(this.range),this.controller.add(this.itemset),e&&this.setData(e),this.setOptions(n)}var o=t("./../util"),r=t("moment"),s=t("../range"),a=t("../controller"),h=(t("../component/component"),t("../component/rootpanel")),c=t("../component/timeaxis"),p=t("../component/itemset");i.prototype.setOptions=function(t){o.extend(this.options,t),this.timeaxis.setOptions(this.options),this.range.setOptions(this.options);var e,n=this;e="top"==this.options.orientation?function(){return n.timeaxis.height}:function(){return n.main.height-n.timeaxis.height-n.itemset.height},this.itemset.setOptions({orientation:this.options.orientation,top:e}),this.controller.repaint()},i.prototype.setData=function(t){var e=this.itemset.data;if(e)this.itemset.setData(t);else{this.itemset.setData(t);var n=this.itemset.getDataRange(),i=n.min,o=n.max;if(null!=i&&null!=o){var r=o.valueOf()-i.valueOf();i=new Date(i.valueOf()-.05*r),o=new Date(o.valueOf()+.05*r)}(null!=i||null!=o)&&this.range.setRange(i,o)}},e.exports=n=i},{"./../util":8,"../range":5,"../controller":2,"../component/component":9,"../component/rootpanel":11,"../component/timeaxis":14,"../component/itemset":12,moment:18}],19:[function(t,e,n){function i(t,e,n){this.parent=t,this.data=e,this.selected=!1,this.visible=!0,this.dom=null,this.options=n}var o=t("../component");i.prototype=new o,i.prototype.select=function(){this.selected=!0},i.prototype.unselect=function(){this.selected=!1},e.exports=n=i},{"../component":9}]},{},[1])(1)}),"function"==typeof define&&define(function(){return vis});var loadCss=function(t){document.getElementsByTagName("script");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)};loadCss("/* vis.js stylesheet */\n\n.graph {\n position: relative;\n border: 1px solid #bfbfbf;\n}\n\n.graph .panel {\n position: absolute;\n}\n\n.graph .itemset {\n position: absolute;\n padding: 0;\n margin: 0;\n overflow: hidden;\n}\n\n.graph .background {\n}\n\n.graph .foreground {\n}\n\n.graph .itemset-axis {\n position: absolute;\n}\n\n.graph .item {\n position: absolute;\n color: #1A1A1A;\n border-color: #97B0F8;\n background-color: #D5DDF6;\n display: inline-block;\n}\n\n.graph .item.selected {\n border-color: #FFC200;\n background-color: #FFF785;\n z-index: 999;\n}\n\n.graph .item.cluster {\n /* TODO: use another color or pattern? */\n background: #97B0F8 url('img/cluster_bg.png');\n color: white;\n}\n.graph .item.cluster.point {\n border-color: #D5DDF6;\n}\n\n.graph .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.graph .item.point {\n background: none;\n}\n\n.graph .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.graph .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.graph .item.range .drag-left {\n cursor: w-resize;\n z-index: 1000;\n}\n\n.graph .item.range .drag-right {\n cursor: e-resize;\n z-index: 1000;\n}\n\n.graph .item.range .content {\n position: relative;\n display: inline-block;\n}\n\n.graph .item.line {\n position: absolute;\n width: 0;\n border-left-width: 1px;\n border-left-style: solid;\n}\n\n.graph .item .content {\n margin: 5px;\n white-space: nowrap;\n overflow: hidden;\n}\n\n/* TODO: better css name, 'graph' is way to generic */\n\n.graph {\n overflow: hidden;\n}\n\n.graph .axis {\n position: relative;\n}\n\n.graph .axis .text {\n position: absolute;\n color: #4d4d4d;\n padding: 3px;\n white-space: nowrap;\n}\n\n.graph .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.graph .axis .grid.vertical {\n position: absolute;\n width: 0;\n border-right: 1px solid;\n}\n\n.graph .axis .grid.horizontal {\n position: absolute;\n left: 0;\n width: 100%;\n height: 0;\n border-bottom: 1px solid;\n}\n\n.graph .axis .grid.minor {\n border-color: #e5e5e5;\n}\n\n.graph .axis .grid.major {\n border-color: #bfbfbf;\n}\n\n");
\ No newline at end of file