Browse Source

Integrated an option configurator

flowchartTest
jos 9 years ago
parent
commit
f30a3a4556
14 changed files with 273 additions and 29 deletions
  1. +1
    -1
      HISTORY.md
  2. +7
    -0
      docs/timeline/index.html
  3. +13
    -3
      lib/timeline/Core.js
  4. +3
    -3
      lib/timeline/TimeStep.js
  5. +22
    -0
      lib/timeline/Timeline.js
  6. +9
    -7
      lib/timeline/component/ItemSet.js
  7. +11
    -9
      lib/timeline/component/TimeAxis.js
  8. +1
    -1
      lib/timeline/component/item/BackgroundItem.js
  9. +1
    -1
      lib/timeline/component/item/BoxItem.js
  10. +2
    -2
      lib/timeline/component/item/PointItem.js
  11. +2
    -2
      lib/timeline/component/item/RangeItem.js
  12. +198
    -0
      lib/timeline/options.js
  13. +2
    -0
      test/timeline.html
  14. +1
    -0
      test/timeline_groups.html

+ 1
- 1
HISTORY.md View File

@ -11,7 +11,6 @@ http://visjs.org
When creating a custom bundle using browserify, one now needs to add a
transform step using `6to5ify`, this is described in README.md.
### Timeline
- Implemented option `multiselect`, which is false by default.
@ -93,6 +92,7 @@ http://visjs.org
### Timeline
- Integrated an option configurator.
- Implemented orientation option `'both'`, displaying a time axis both on top
and bottom (#665).
- Implemented creating new range items by dragging in an empty space with the

+ 7
- 0
docs/timeline/index.html View File

@ -477,6 +477,13 @@ var options = {
When active, a blue shadow border is displayed around the Timeline. The Timeline is set active by clicking on it, and is changed to inactive again by clicking outside the Timeline or by pressing the ESC key.</td>
</tr>
<tr>
<td>configure</td>
<td class="mid">boolean</td>
<td class="mid"><code>false</code></td>
<td>When true, a configurator is loaded where all configuration options of the Timeline can be changed live.</td>
</tr>
<tr>
<td>dataAttributes</td>
<td class="mid">string[] or 'all'</string></td>

+ 13
- 3
lib/timeline/Core.js View File

@ -13,9 +13,6 @@ var CustomTime = require('./component/CustomTime');
/**
* Create a timeline visualization
* @param {HTMLElement} container
* @param {vis.DataSet | Array} [items]
* @param {Object} [options] See Core.setOptions for the available options.
* @constructor
*/
function Core () {}
@ -284,6 +281,19 @@ Core.prototype.setOptions = function (options) {
// propagate options to all components
this.components.forEach(component => component.setOptions(options));
// enable/disable configure
if (this.configurationSystem) {
this.configurationSystem.setOptions(options.configure);
// collect the settings of all components, and pass them to the configuration system
var appliedOptions = util.deepExtend({}, this.options);
this.components.forEach(function (component) {
util.deepExtend(appliedOptions, component.options);
});
console.log('options', appliedOptions)
this.configurationSystem.setModuleOptions({global: appliedOptions});
}
// redraw everything
this._redraw();
};

+ 3
- 3
lib/timeline/TimeStep.js View File

@ -80,7 +80,7 @@ TimeStep.FORMAT = {
/**
* Set custom formatting for the minor an major labels of the TimeStep.
* Both `minorLabels` and `majorLabels` are an Object with properties:
* 'millisecond, 'second, 'minute', 'hour', 'weekday, 'day, 'month, 'year'.
* 'millisecond', 'second', 'minute', 'hour', 'weekday', 'day', 'month', 'year'.
* @param {{minorLabels: Object, majorLabels: Object}} format
*/
TimeStep.prototype.setFormat = function (format) {
@ -246,7 +246,7 @@ TimeStep.prototype.getCurrent = function() {
* @param {{scale: string, step: number}} params
* An object containing two properties:
* - A string 'scale'. Choose from 'millisecond', 'second',
* 'minute', 'hour', 'weekday, 'day, 'month, 'year'.
* 'minute', 'hour', 'weekday', 'day', 'month', 'year'.
* - A number 'step'. A step size, by default 1.
* Choose for example 1, 2, 5, or 10.
*/
@ -324,7 +324,7 @@ TimeStep.prototype.setMinimumStep = function(minimumStep) {
* Static function
* @param {Date} date the date to be snapped.
* @param {string} scale Current scale, can be 'millisecond', 'second',
* 'minute', 'hour', 'weekday, 'day, 'month, 'year'.
* 'minute', 'hour', 'weekday, 'day', 'month', 'year'.
* @param {number} step Current step (1, 2, 4, 5, ...
* @return {Date} snappedDate
*/

+ 22
- 0
lib/timeline/Timeline.js View File

@ -9,6 +9,10 @@ var TimeAxis = require('./component/TimeAxis');
var CurrentTime = require('./component/CurrentTime');
var CustomTime = require('./component/CustomTime');
var ItemSet = require('./component/ItemSet');
var ConfigurationSystem = require('../network/modules/ConfigurationSystem');
var allOptions = require('./options').allOptions;
var configureOptions = require('./options').configureOptions;
/**
* Create a timeline visualization
@ -111,6 +115,9 @@ function Timeline (container, items, groups, options) {
me.emit('contextmenu', me.getEventProperties(event))
};
// setup configuration system
this.configurationSystem = new ConfigurationSystem(this, container, configureOptions);
// apply options
if (options) {
this.setOptions(options);
@ -143,6 +150,21 @@ Timeline.prototype.redraw = function() {
this._redraw();
};
Timeline.prototype.setOptions = function (options) {
Core.prototype.setOptions.call(this, options);
if ('type' in options) {
if (options.type !== this.options.type) {
this.options.type = options.type;
// force recreation of all items
var itemsData = this.itemsData;
this.setItems(null); // remove all
this.setItems(itemsData); // add all
}
}
};
/**
* Set items
* @param {vis.DataSet | Array | null} items

+ 9
- 7
lib/timeline/component/ItemSet.js View File

@ -29,7 +29,9 @@ function ItemSet(body, options) {
this.defaultOptions = {
type: null, // 'box', 'point', 'range', 'background'
orientation: 'bottom', // item orientation: 'top' or 'bottom'
orientation: {
item: 'bottom' // item orientation: 'top' or 'bottom'
},
align: 'auto', // alignment of box items
stack: true,
groupOrder: null,
@ -222,7 +224,7 @@ ItemSet.prototype._create = function(){
* Alignment for the items, only applicable for
* BoxItem. Choose 'center' (default), 'left', or
* 'right'.
* {String} orientation
* {String} orientation.item
* Orientation of the item set. Choose 'top' or
* 'bottom' (default).
* {Function} groupOrder
@ -282,10 +284,10 @@ ItemSet.prototype.setOptions = function(options) {
if ('orientation' in options) {
if (typeof options.orientation === 'string') {
this.options.orientation = options.orientation;
this.options.orientation.item = options.orientation === 'top' ? 'top' : 'bottom';
}
else if (typeof options.orientation === 'object' && 'item' in options.orientation) {
this.options.orientation = options.orientation.item;
this.options.orientation.item = options.orientation.item;
}
}
@ -504,7 +506,7 @@ ItemSet.prototype.redraw = function() {
range = this.body.range,
asSize = util.option.asSize,
options = this.options,
orientation = options.orientation,
orientation = options.orientation.item,
resized = false,
frame = this.dom.frame,
editable = options.editable.updateTime || options.editable.updateGroup;
@ -578,7 +580,7 @@ ItemSet.prototype.redraw = function() {
* @private
*/
ItemSet.prototype._firstGroup = function() {
var firstGroupIndex = (this.options.orientation == 'top') ? 0 : (this.groupIds.length - 1);
var firstGroupIndex = (this.options.orientation.item == 'top') ? 0 : (this.groupIds.length - 1);
var firstGroupId = this.groupIds[firstGroupIndex];
var firstGroup = this.groups[firstGroupId] || this.groups[UNGROUPED];
@ -1593,7 +1595,7 @@ ItemSet.prototype.groupFromTarget = function(event) {
return group;
}
if (this.options.orientation === 'top') {
if (this.options.orientation.item === 'top') {
if (i === this.groupIds.length - 1 && pageY > top) {
return group;
}

+ 11
- 9
lib/timeline/component/TimeAxis.js View File

@ -34,10 +34,12 @@ function TimeAxis (body, options) {
};
this.defaultOptions = {
orientation: 'bottom', // axis orientation: 'top' or 'bottom'
orientation: {
axis: 'bottom'
}, // axis orientation: 'top' or 'bottom'
showMinorLabels: true,
showMajorLabels: true,
format: null,
format: TimeStep.FORMAT,
timeAxis: null
};
this.options = util.extend({}, this.defaultOptions);
@ -56,14 +58,14 @@ TimeAxis.prototype = new Component();
* Set options for the TimeAxis.
* Parameters will be merged in current options.
* @param {Object} options Available options:
* {string} [orientation]
* {string} [orientation.axis]
* {boolean} [showMinorLabels]
* {boolean} [showMajorLabels]
*/
TimeAxis.prototype.setOptions = function(options) {
if (options) {
// copy all options that we know
util.selectiveExtend([
util.selectiveDeepExtend([
'showMinorLabels',
'showMajorLabels',
'hiddenDates',
@ -73,10 +75,10 @@ TimeAxis.prototype.setOptions = function(options) {
if ('orientation' in options) {
if (typeof options.orientation === 'string') {
this.options.orientation = options.orientation;
this.options.orientation.axis = options.orientation;
}
else if (typeof options.orientation === 'object' && 'axis' in options.orientation) {
this.options.orientation = options.orientation.axis;
this.options.orientation.axis = options.orientation.axis;
}
}
@ -131,7 +133,7 @@ TimeAxis.prototype.redraw = function () {
var background = this.dom.background;
// determine the correct parent DOM element (depending on option orientation)
var parent = (options.orientation == 'top') ? this.body.dom.top : this.body.dom.bottom;
var parent = (options.orientation.axis == 'top') ? this.body.dom.top : this.body.dom.bottom;
var parentChanged = (foreground.parentNode !== parent);
// calculate character width and height
@ -148,7 +150,7 @@ TimeAxis.prototype.redraw = function () {
props.width = foreground.offsetWidth;
props.minorLineHeight = this.body.domProps.root.height - props.majorLabelHeight -
(options.orientation == 'top' ? this.body.domProps.bottom.height : this.body.domProps.top.height);
(options.orientation.axis == 'top' ? this.body.domProps.bottom.height : this.body.domProps.top.height);
props.minorLineWidth = 1; // TODO: really calculate width
props.majorLineHeight = props.minorLineHeight + props.majorLabelHeight;
props.majorLineWidth = 1; // TODO: really calculate width
@ -185,7 +187,7 @@ TimeAxis.prototype.redraw = function () {
* @private
*/
TimeAxis.prototype._repaintLabels = function () {
var orientation = this.options.orientation;
var orientation = this.options.orientation.axis;
// calculate range and step (step such that we have space for 7 characters per label)
var start = util.convert(this.body.range.start, 'Number');

+ 1
- 1
lib/timeline/component/item/BackgroundItem.js View File

@ -143,7 +143,7 @@ BackgroundItem.prototype.repositionX = RangeItem.prototype.repositionX;
* @Override
*/
BackgroundItem.prototype.repositionY = function(margin) {
var onTop = this.options.orientation === 'top';
var onTop = this.options.orientation.item === 'top';
this.dom.content.style.top = onTop ? '' : '0';
this.dom.content.style.bottom = onTop ? '0' : '';
var height;

+ 1
- 1
lib/timeline/component/item/BoxItem.js View File

@ -191,7 +191,7 @@ BoxItem.prototype.repositionX = function() {
* @Override
*/
BoxItem.prototype.repositionY = function() {
var orientation = this.options.orientation;
var orientation = this.options.orientation.item;
var box = this.dom.box;
var line = this.dom.line;
var dot = this.dom.dot;

+ 2
- 2
lib/timeline/component/item/PointItem.js View File

@ -166,8 +166,8 @@ PointItem.prototype.repositionX = function() {
* @Override
*/
PointItem.prototype.repositionY = function() {
var orientation = this.options.orientation,
point = this.dom.point;
var orientation = this.options.orientation.item;
var point = this.dom.point;
if (orientation == 'top') {
point.style.top = this.top + 'px';

+ 2
- 2
lib/timeline/component/item/RangeItem.js View File

@ -234,8 +234,8 @@ RangeItem.prototype.repositionX = function(limitSize) {
* @Override
*/
RangeItem.prototype.repositionY = function() {
var orientation = this.options.orientation,
box = this.dom.box;
var orientation = this.options.orientation.item;
var box = this.dom.box;
if (orientation == 'top') {
box.style.top = this.top + 'px';

+ 198
- 0
lib/timeline/options.js View File

@ -0,0 +1,198 @@
/**
* This object contains all possible options. It will check if the types are correct, if required if the option is one
* of the allowed values.
*
* __any__ means that the name of the property does not matter.
* __type__ is a required field for all objects and contains the allowed types of all objects
*/
let string = 'string';
let boolean = 'boolean';
let number = 'number';
let array = 'array';
let date = 'date';
let object = 'object'; // should only be in a __type__ property
let dom = 'dom';
let moment = 'moment';
let fn = 'function';
let nada = 'null';
let undef = 'undefined';
let any = 'any';
let allOptions = {
configure: {
enabled: {boolean},
filter: {boolean,string,array},
container: {dom},
__type__: {object,boolean,string,array}
},
//globals :
align: {string},
autoResize: {boolean},
clickToUse: {boolean},
dataAttributes: {string, Array},
editable: {boolean, object},
end: {number, Date, string, moment},
format: {
minorLabels: {
millisecond: {string},
second: {string},
minute: {string},
hour: {string},
weekday: {string},
day: {string},
month: {string},
year: {string}
},
majorLabels: {
millisecond: {string},
second: {string},
minute: {string},
hour: {string},
weekday: {string},
day: {string},
month: {string},
year: {string}
}
},
groupOrder: {string, fn},
height: {string, number},
hiddenDates: {object, array},
locale:{string},
locales:{
__any__: {object},
__type__: {object}
},
margin: {
axis: {number},
item: {
horizontal: {number},
vertical: {number},
__type__: {object,number}
},
__type__: {object,number}
},
max: {date, number, string, moment},
maxHeight: {number, string},
min: {date, number, string, moment},
minHeight: {number, string},
moveable: {boolean},
multiselect: {boolean},
onAdd: {fn},
onUpdate: {fn},
onMove: {fn},
onMoving: {fn},
onRename: {fn},
order: {fn},
orientation: {
axis: {string},
item: {string},
__type__: {string, object}
},
selectable: {boolean},
showCurrentTime: {boolean},
showMajorLabels: {boolean},
showMinorLabels: {boolean},
stack: {boolean},
snap: {fn, nada},
start: {date, number, string, moment},
template: {fn},
timeAxis: {
scale: {string},
step: {number},
__type__: {object}
},
type: {string},
width: {string, number},
zoomable: {boolean},
zoomMax: {number},
zoomMin: {number},
__type__: {object}
};
let configureOptions = {
global: {
align: ['center', 'left', 'right'],
autoResize: true,
clickToUse: false,
// dataAttributes: ['all'], // FIXME: can be 'all' or string[]
editable: {
add: false,
remove: false,
updateGroup: false,
updateTime: false
},
end: '',
format: {
minorLabels: {
millisecond:'SSS',
second: 's',
minute: 'HH:mm',
hour: 'HH:mm',
weekday: 'ddd D',
day: 'D',
month: 'MMM',
year: 'YYYY'
},
majorLabels: {
millisecond:'HH:mm:ss',
second: 'D MMMM HH:mm',
minute: 'ddd D MMMM',
hour: 'ddd D MMMM',
weekday: 'MMMM YYYY',
day: 'MMMM YYYY',
month: 'YYYY',
year: ''
}
},
//groupOrder: {string, fn},
height: '',
//hiddenDates: {object, array},
locale: '',
margin: {
axis: [20, 0, 100, 1],
item: {
horizontal: [10, 0, 100, 1],
vertical: [10, 0, 100, 1]
}
},
max: '',
maxHeight: '',
min: '',
minHeight: '',
moveable: false,
multiselect: false,
//onAdd: {fn},
//onUpdate: {fn},
//onMove: {fn},
//onMoving: {fn},
//onRename: {fn},
//order: {fn},
orientation: {
axis: ['both', 'bottom', 'top'],
item: ['bottom', 'top']
},
selectable: true,
showCurrentTime: false,
showMajorLabels: true,
showMinorLabels: true,
stack: true,
//snap: {fn, nada},
start: '',
//template: {fn},
//timeAxis: {
// scale: ['millisecond', 'second', 'minute', 'hour', 'weekday', 'day', 'month', 'year'],
// step: [1, 1, 10, 1]
//},
type: ['box', 'point', 'range', 'background'],
width: '100%',
zoomable: true,
zoomMax: [315360000000000, 10, 315360000000000, 1],
zoomMin: [10, 10, 315360000000000, 1]
}
};
export {allOptions, configureOptions};

+ 2
- 0
test/timeline.html View File

@ -142,6 +142,8 @@
var container = document.getElementById('visualization');
var options = {
configure: true,
multiselect: true,
editable: true,
//orientation: 'top',
orientation: 'both',

+ 1
- 0
test/timeline_groups.html View File

@ -90,6 +90,7 @@
var container = document.getElementById('visualization');
var options = {
//orientation: 'top',
multiselect: true,
editable: {
add: true,
remove: true,

Loading…
Cancel
Save