From 1c848f1f2d6a8fe39246380175b03356bb909edd Mon Sep 17 00:00:00 2001 From: Oleg Yapparov Date: Sat, 21 Feb 2015 15:04:05 +0100 Subject: [PATCH 1/3] Multiple customTime vertical bars --- docs/timeline.html | 9 +++ examples/timeline/34_add_custom_timebar.html | 68 ++++++++++++++++++++ examples/timeline/index.html | 2 +- lib/timeline/Core.js | 60 +++++++++++++++++ lib/timeline/component/CustomTime.js | 19 +++++- 5 files changed, 154 insertions(+), 4 deletions(-) create mode 100644 examples/timeline/34_add_custom_timebar.html diff --git a/docs/timeline.html b/docs/timeline.html index 59eec23e..391ff5cc 100644 --- a/docs/timeline.html +++ b/docs/timeline.html @@ -854,6 +854,13 @@ var options = { Description + + addCustomTime(time) + Number + + Add new vertical bar representing custom time. Each new line is assigned a unique ID and can be dragged by the user. Parameter time can be a Date, Number, or String. Returns ID of the newly created bar. Only applicable when the option showCustomTime is true. + + clear([what]) none @@ -1130,6 +1137,7 @@ timeline.off('select', onSelect); @@ -1142,6 +1150,7 @@ timeline.off('select', onSelect); diff --git a/examples/timeline/34_add_custom_timebar.html b/examples/timeline/34_add_custom_timebar.html new file mode 100644 index 00000000..426cb93a --- /dev/null +++ b/examples/timeline/34_add_custom_timebar.html @@ -0,0 +1,68 @@ + + + + Timeline | Show current and custom time bars + + + + + + + + +

+ + +

+

+ + +

+

+ timechange bar index: event: +

+

+ timechanged bar index: event: +


+ +
+ + + + \ No newline at end of file diff --git a/examples/timeline/index.html b/examples/timeline/index.html index c21533dc..82526bd7 100644 --- a/examples/timeline/index.html +++ b/examples/timeline/index.html @@ -44,7 +44,7 @@

31_background_areas_with_groups.html

32_grid_styling.html

33_custom_snapping.html

- +

34_add_custom_timebar.html

requirejs_example.html

diff --git a/lib/timeline/Core.js b/lib/timeline/Core.js index 0ad99d98..b018fac1 100644 --- a/lib/timeline/Core.js +++ b/lib/timeline/Core.js @@ -7,6 +7,7 @@ var Range = require('./Range'); var ItemSet = require('./component/ItemSet'); var Activator = require('../shared/Activator'); var DateUtil = require('./DateUtil'); +var CustomTime = require('./component/CustomTime'); /** * Create a timeline visualization @@ -302,6 +303,65 @@ Core.prototype.getCustomTime = function() { return this.customTime.getCustomTime(); }; +/** + * Add custom vertical bar + * param {Date | String | Number} time A Date, unix timestamp, or + * ISO date string. Time point where the new bar should be placed + * @return {int} ID of the new bar + */ +Core.prototype.addCustomTime = function (time) { + if (!this.currentTime) { + throw new Error('Option showCurrentTime must be true'); + } + + if (time === undefined) { + throw new Error('Time parameter for the custom bar must be provided'); + } + + var ts = util.convert(time, 'Date').valueOf(), + customTime, id; + + if ('customLastId' in this) { + id = ++this.customLastId; + } else { + id = this.customLastId = 1; + } + + customTime = new CustomTime(this.body, { + showCustomTime : true, + time : ts, + id : id + }); + + this.components.push(customTime); + this.redraw(); + + return id; +}; + +/** + * Remove previously added custom bar + * @param {int} id ID of the custom bar to be removed + * @return {boolean} True if the bar exists and is removed, false otherwise + */ +Core.prototype.removeCustomTime = function (id) { + var me = this; + + var reduceLastId = function() { + if ('customLastId' in me && me.customLastId > 0) { + me.customLastId--; + } + }; + + this.components.forEach(function (bar, index, components) { + if (bar instanceof CustomTime && bar.options.id === id) { + reduceLastId(); + components.splice(index, 1); + bar.destroy(); + } + }); +}; + /** * Get the id's of the currently visible items. diff --git a/lib/timeline/component/CustomTime.js b/lib/timeline/component/CustomTime.js index 44c2a4da..eea21450 100644 --- a/lib/timeline/component/CustomTime.js +++ b/lib/timeline/component/CustomTime.js @@ -20,11 +20,17 @@ function CustomTime (body, options) { this.defaultOptions = { showCustomTime: false, locales: locales, - locale: 'en' + locale: 'en', + id: 0 }; this.options = util.extend({}, this.defaultOptions); - this.customTime = new Date(); + if (options && options.time) { + this.customTime = options.time; + } else { + this.customTime = new Date(); + } + this.eventParams = {}; // stores state parameters while dragging the bar // create the DOM @@ -43,7 +49,12 @@ CustomTime.prototype = new Component(); CustomTime.prototype.setOptions = function(options) { if (options) { // copy all options that we know - util.selectiveExtend(['showCustomTime', 'locale', 'locales'], this.options, options); + util.selectiveExtend(['showCustomTime', 'locale', 'locales', 'id'], this.options, options); + + // Triggered by addCustomTimeBar, redraw to add new bar + if (this.options.id) { + this.redraw(); + } } }; @@ -169,6 +180,7 @@ CustomTime.prototype._onDrag = function (event) { // fire a timechange event this.body.emitter.emit('timechange', { + id: this.options.id, time: new Date(this.customTime.valueOf()) }); @@ -186,6 +198,7 @@ CustomTime.prototype._onDragEnd = function (event) { // fire a timechanged event this.body.emitter.emit('timechanged', { + id: this.options.id, time: new Date(this.customTime.valueOf()) }); From 01207417f3175dca90e6a23bc6237407602d13e5 Mon Sep 17 00:00:00 2001 From: Oleg Yapparov Date: Sun, 22 Feb 2015 13:51:21 +0100 Subject: [PATCH 2/3] Added id parameter to set/getCustomTime methods, docs update --- docs/timeline.html | 16 ++++++--- examples/timeline/34_add_custom_timebar.html | 6 +++- lib/timeline/Core.js | 35 ++++++++++++++++---- 3 files changed, 45 insertions(+), 12 deletions(-) diff --git a/docs/timeline.html b/docs/timeline.html index 391ff5cc..aebcac8d 100644 --- a/docs/timeline.html +++ b/docs/timeline.html @@ -910,9 +910,9 @@ timeline.clear({options: true}); // clear options only - getCustomTime() + getCustomTime([id]) Date - Retrieve the custom time. Only applicable when the option showCustomTime is true. + Retrieve the custom time. Only applicable when the option showCustomTime is true. If parameter id is provided, time of the custom time bar under that ID is returned. @@ -965,6 +965,14 @@ timeline.clear({options: true}); // clear options only + + removeCustomTime(id) + none + + Remove vertical bars previously added to the timeline via addCustomTime method. Parameter id is the ID of the custom vertical bar returned by addCustomTime method. + + + setCurrentTime(time) none @@ -974,9 +982,9 @@ timeline.clear({options: true}); // clear options only - setCustomTime(time) + setCustomTime(time [, id]) none - Adjust the custom time bar. Only applicable when the option showCustomTime is true. time can be a Date object, numeric timestamp, or ISO date string. + Adjust the custom time bar. Only applicable when the option showCustomTime is true. time can be a Date object, numeric timestamp, or ISO date string. Parameter id represents ID of the custom time bar, provided by addCustomTime method. diff --git a/examples/timeline/34_add_custom_timebar.html b/examples/timeline/34_add_custom_timebar.html index 426cb93a..9afab8b8 100644 --- a/examples/timeline/34_add_custom_timebar.html +++ b/examples/timeline/34_add_custom_timebar.html @@ -21,7 +21,7 @@

- +

timechange bar index: event: @@ -44,6 +44,10 @@ }; var timeline = new vis.Timeline(container, items, options); + // Set first time bar + customDate = new Date(customDate.getFullYear(), customDate.getMonth(), customDate.getDate() + 1); + timeline.addCustomTime(customDate); + document.getElementById('add').onclick = function () { customDate = new Date(customDate.getFullYear(), customDate.getMonth(), customDate.getDate() + 1); timeline.addCustomTime(customDate); diff --git a/lib/timeline/Core.js b/lib/timeline/Core.js index b018fac1..432089b5 100644 --- a/lib/timeline/Core.js +++ b/lib/timeline/Core.js @@ -282,25 +282,42 @@ Core.prototype.destroy = function () { /** * Set a custom time bar * @param {Date} time + * @param {int} id */ -Core.prototype.setCustomTime = function (time) { +Core.prototype.setCustomTime = function (time, id) { if (!this.customTime) { throw new Error('Cannot get custom time: Custom time bar is not enabled'); } - this.customTime.setCustomTime(time); + var barId = util.option.asNumber(id) || 0; + + this.components.forEach(function (element, index, components) { + if (element instanceof CustomTime && element.options.id === barId) { + element.setCustomTime(time); + } + }); }; /** * Retrieve the current custom time. * @return {Date} customTime + * @param {int} id */ -Core.prototype.getCustomTime = function() { +Core.prototype.getCustomTime = function(id) { if (!this.customTime) { throw new Error('Cannot get custom time: Custom time bar is not enabled'); } - return this.customTime.getCustomTime(); + var barId = util.option.asNumber(id) || 0, + customTime = this.customTime.getCustomTime();; + + this.components.forEach(function (element, index, components) { + if (element instanceof CustomTime && element.options.id === barId) { + customTime = element.getCustomTime(); + } + }); + + return customTime; }; /** @@ -355,9 +372,13 @@ Core.prototype.removeCustomTime = function (id) { this.components.forEach(function (bar, index, components) { if (bar instanceof CustomTime && bar.options.id === id) { - reduceLastId(); - components.splice(index, 1); - bar.destroy(); + + // Only the lines added by the user will be removed + if (bar.options.id > 0) { + reduceLastId(); + components.splice(index, 1); + bar.destroy(); + } } }); }; From 9c469d02ba650e0303670e301c845ecea54307aa Mon Sep 17 00:00:00 2001 From: Oleg Yapparov Date: Sun, 22 Feb 2015 21:35:51 +0100 Subject: [PATCH 3/3] Added option to supply ID for the new custom time bar --- docs/timeline.html | 14 +++-- examples/timeline/34_add_custom_timebar.html | 22 +++---- lib/timeline/Core.js | 60 +++++++++++++------- 3 files changed, 59 insertions(+), 37 deletions(-) diff --git a/docs/timeline.html b/docs/timeline.html index aebcac8d..cc07b99a 100644 --- a/docs/timeline.html +++ b/docs/timeline.html @@ -855,10 +855,12 @@ var options = { - addCustomTime(time) - Number + addCustomTime(time[, id]) + Number | String - Add new vertical bar representing custom time. Each new line is assigned a unique ID and can be dragged by the user. Parameter time can be a Date, Number, or String. Returns ID of the newly created bar. Only applicable when the option showCustomTime is true. + Only applicable when the option showCustomTime is true.
+ Add new vertical bar representing custom time that can be dragged by the user. Parameter time can be a Date, Number, or String. Parameter id can be Number or String. If id is provided, it will be used as ID for the new vertical bar, otherwise the ID will be auto generated.
+ Returns ID of the newly created bar. @@ -984,7 +986,7 @@ timeline.clear({options: true}); // clear options only setCustomTime(time [, id]) none - Adjust the custom time bar. Only applicable when the option showCustomTime is true. time can be a Date object, numeric timestamp, or ISO date string. Parameter id represents ID of the custom time bar, provided by addCustomTime method. + Adjust the custom time bar. Only applicable when the option showCustomTime is true. Parameter time can be a Date object, numeric timestamp, or ISO date string. Parameter id represents ID of the custom time bar, provided by addCustomTime method and can be a Number or String. @@ -1145,7 +1147,7 @@ timeline.off('select', onSelect);

@@ -1158,7 +1160,7 @@ timeline.off('select', onSelect); diff --git a/examples/timeline/34_add_custom_timebar.html b/examples/timeline/34_add_custom_timebar.html index 9afab8b8..894d2881 100644 --- a/examples/timeline/34_add_custom_timebar.html +++ b/examples/timeline/34_add_custom_timebar.html @@ -16,18 +16,18 @@

- - + +

- - + +

- timechange bar index: event: + timechange bar index: . Time:

- timechanged bar index: event: + timechanged bar index: . Time:


@@ -46,16 +46,18 @@ // Set first time bar customDate = new Date(customDate.getFullYear(), customDate.getMonth(), customDate.getDate() + 1); - timeline.addCustomTime(customDate); + timeline.addCustomTime(customDate, 1); document.getElementById('add').onclick = function () { customDate = new Date(customDate.getFullYear(), customDate.getMonth(), customDate.getDate() + 1); - timeline.addCustomTime(customDate); + var barId = document.getElementById('barId').value || undefined; + timeline.addCustomTime(customDate, barId); + document.getElementById('barId').value = ''; }; document.getElementById('remove').onclick = function () { - var index = document.getElementById('barIndex'); - timeline.removeCustomTime(parseInt(index.value)); + timeline.removeCustomTime(document.getElementById('barIndex').value); + document.getElementById('barIndex').value = ''; }; timeline.on('timechange', function (properties) { diff --git a/lib/timeline/Core.js b/lib/timeline/Core.js index 432089b5..5b3b16e6 100644 --- a/lib/timeline/Core.js +++ b/lib/timeline/Core.js @@ -289,7 +289,7 @@ Core.prototype.setCustomTime = function (time, id) { throw new Error('Cannot get custom time: Custom time bar is not enabled'); } - var barId = util.option.asNumber(id) || 0; + var barId = id || 0; this.components.forEach(function (element, index, components) { if (element instanceof CustomTime && element.options.id === barId) { @@ -308,8 +308,8 @@ Core.prototype.getCustomTime = function(id) { throw new Error('Cannot get custom time: Custom time bar is not enabled'); } - var barId = util.option.asNumber(id) || 0, - customTime = this.customTime.getCustomTime();; + var barId = id || 0, + customTime = this.customTime.getCustomTime(); this.components.forEach(function (element, index, components) { if (element instanceof CustomTime && element.options.id === barId) { @@ -322,11 +322,12 @@ Core.prototype.getCustomTime = function(id) { /** * Add custom vertical bar - * param {Date | String | Number} time A Date, unix timestamp, or + * @param {Date | String | Number} time A Date, unix timestamp, or * ISO date string. Time point where the new bar should be placed - * @return {int} ID of the new bar + * @param {Number | String} ID of the new bar + * @return {Number | String} ID of the new bar */ -Core.prototype.addCustomTime = function (time) { +Core.prototype.addCustomTime = function (time, id) { if (!this.currentTime) { throw new Error('Option showCurrentTime must be true'); } @@ -336,24 +337,47 @@ Core.prototype.addCustomTime = function (time) { } var ts = util.convert(time, 'Date').valueOf(), - customTime, id; + numIds, customTime, customBarId; + + // All bar IDs are kept in 1 array, mixed types + // Bar with ID 0 is the default bar. + if (!this.customBarIds || this.customBarIds.constructor !== Array) { + this.customBarIds = [0]; + } + + // If the ID is not provided, generate one, otherwise just use it + if (id === undefined) { + + numIds = this.customBarIds.filter(function (element) { + return util.isNumber(element); + }); + + customBarId = numIds.length > 0 ? Math.max.apply(null, numIds) + 1 : 1; - if ('customLastId' in this) { - id = ++this.customLastId; } else { - id = this.customLastId = 1; + + // Check for duplicates + this.customBarIds.forEach(function (element) { + if (element === id) { + throw new Error('Custom time ID already exists'); + } + }); + + customBarId = id; } + this.customBarIds.push(customBarId); + customTime = new CustomTime(this.body, { showCustomTime : true, time : ts, - id : id + id : customBarId }); this.components.push(customTime); this.redraw(); - return id; + return customBarId; }; /** @@ -362,20 +386,14 @@ Core.prototype.addCustomTime = function (time) { * @return {boolean} True if the bar exists and is removed, false otherwise */ Core.prototype.removeCustomTime = function (id) { - var me = this; - var reduceLastId = function() { - if ('customLastId' in me && me.customLastId > 0) { - me.customLastId--; - } - }; + var me = this; this.components.forEach(function (bar, index, components) { if (bar instanceof CustomTime && bar.options.id === id) { - // Only the lines added by the user will be removed - if (bar.options.id > 0) { - reduceLastId(); + if (bar.options.id !== 0) { + me.customBarIds.splice(me.customBarIds.indexOf(id), 1); components.splice(index, 1); bar.destroy(); }