diff --git a/examples/timeline/other/customTimeBarsSnap.html b/examples/timeline/other/customTimeBarsSnap.html new file mode 100644 index 0000000000..ac0acde1cb --- /dev/null +++ b/examples/timeline/other/customTimeBarsSnap.html @@ -0,0 +1,93 @@ +<!DOCTYPE HTML> +<html> +<head> + <title>Timeline | other | Show current and custom time bars with snapping</title> + + <style type="text/css"> + body, html { + font-family: sans-serif; + font-size: 11pt; + } + </style> + + <script src="../../../standalone/umd/vis-timeline-graph2d.min.js"></script> + <link href="../../../styles/vis-timeline-graph2d.min.css" rel="stylesheet" type="text/css" /> + +</head> +<body> + +<p> + The Timeline has functions to add multiple custom time bars which can be dragged by the user. +</p> +<p> + <input type="button" id="add" value="Add custom vertical bar"> + <input type="text" id="barId" placeholder="custom bar ID"> +</p> +<p> + <input type="button" id="remove" value="Remove custom vertical bar"> + <input type="text" id="barIndex" value="t1" placeholder="custom bar ID"> +</p> +<p> + <code><strong>timechange</strong></code> event, index: <span id="timechangeBar"></span>, time: <span id="timechangeEvent"></span> +</p> +<p> + <code><strong>timechanged</strong></code> event, index: <span id="timechangedBar"></span>, time: <span id="timechangedEvent"></span> +</p><br> + +<div id="visualization"></div> + +<script type="text/javascript"> + var container = document.getElementById('visualization'); + var items = new vis.DataSet(); + var customDate = new Date(); + var options = { + showCurrentTime: true, + start: new Date(Date.now() - 1000 * 60 * 60 * 24), + end: new Date(Date.now() + 1000 * 60 * 60 * 24 * 6), + snap: function (date, scale, step) { + const hour = 60 * 1000; + return Math.round(date / hour) * hour; + } + }; + 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, 't1'); + + document.getElementById('add').onclick = function () { + try { + customDate = new Date(customDate.getFullYear(), customDate.getMonth(), customDate.getDate() + 1); + var barId = document.getElementById('barId').value || undefined; + timeline.addCustomTime(customDate, barId); + document.getElementById('barId').value = ''; + } + catch (err) { + console.log(err); + alert(err); + } + }; + + document.getElementById('remove').onclick = function () { + try { + timeline.removeCustomTime(document.getElementById('barIndex').value); + document.getElementById('barIndex').value = ''; + } + catch (err) { + console.log(err); + alert(err); + } + }; + + timeline.on('timechange', function (properties) { + document.getElementById('timechangeBar').innerHTML = properties.id; + document.getElementById('timechangeEvent').innerHTML = properties.time; + }); + timeline.on('timechanged', function (properties) { + document.getElementById('timechangedBar').innerHTML = properties.id; + document.getElementById('timechangedEvent').innerHTML = properties.time; + }); + +</script> +</body> +</html> diff --git a/lib/timeline/Core.js b/lib/timeline/Core.js index 9772a0bf7c..347af0d2dd 100644 --- a/lib/timeline/Core.js +++ b/lib/timeline/Core.js @@ -669,7 +669,8 @@ class Core { const customTime = new CustomTime(this.body, util.extend({}, this.options, { time : timestamp, - id + id, + snap: this.itemSet.options.snap })); this.customTimes.push(customTime); diff --git a/lib/timeline/component/CustomTime.js b/lib/timeline/component/CustomTime.js index 5ba5cdc287..7759ed9a46 100644 --- a/lib/timeline/component/CustomTime.js +++ b/lib/timeline/component/CustomTime.js @@ -63,7 +63,7 @@ class CustomTime extends Component { setOptions(options) { if (options) { // copy all options that we know - util.selectiveExtend(['moment', 'locale', 'locales', 'id', 'title', 'rtl'], this.options, options); + util.selectiveExtend(['moment', 'locale', 'locales', 'id', 'title', 'rtl', 'snap'], this.options, options); } } @@ -260,7 +260,13 @@ class CustomTime extends Component { const x = this.body.util.toScreen(this.eventParams.customTime) + deltaX; const time = this.body.util.toTime(x); - this.setCustomTime(time); + const scale = this.body.util.getScale(); + const step = this.body.util.getStep(); + const snap = this.options.snap; + + const snappedTime = snap ? snap(time, scale, step) : time; + + this.setCustomTime(snappedTime); // fire a timechange event this.body.emitter.emit('timechange', {