diff --git a/HISTORY.md b/HISTORY.md index 238152d2..bfb1741c 100644 --- a/HISTORY.md +++ b/HISTORY.md @@ -9,6 +9,11 @@ http://visjs.org - Added German (de) locale. Thanks @Tooa. - Fixed critical camera zoom bug #1273. +### Timeline + +- Fixed #1215: inconsistent types of properties `start` and `end` in callback + functions `onMove`, `onMoving`, `onAdd`. + ## 2015-08-28, version 4.8.0 diff --git a/docs/network/index.html b/docs/network/index.html index dc0eaf40..a930d4b5 100644 --- a/docs/network/index.html +++ b/docs/network/index.html @@ -333,11 +333,7 @@ network.setOptions(options); clickToUse Boolean false - Locales object. By default only 'en', 'de', 'es' and 'nl' are supported. Take a look - at - the locales - section below for more explaination on how to customize this. + When a Network is configured to be clickToUse, it will react to mouse and touch events only when active. When active, a blue shadow border is displayed around the Network. The network is set active by clicking on it, and is changed to inactive again by clicking outside the Network or by pressing the ESC key. configure diff --git a/lib/timeline/component/ItemSet.js b/lib/timeline/component/ItemSet.js index be30cf67..c4c11511 100644 --- a/lib/timeline/component/ItemSet.js +++ b/lib/timeline/component/ItemSet.js @@ -1160,7 +1160,7 @@ ItemSet.prototype._getGroupIndex = function(groupId) { if (groupId == this.groupIds[i]) return i; } -} +}; /** * Start dragging the selected events @@ -1174,8 +1174,8 @@ ItemSet.prototype._onDragStart = function (event) { if (item && item.selected) { - if (!this.options.editable.updateTime && - !this.options.editable.updateGroup && + if (!this.options.editable.updateTime && + !this.options.editable.updateGroup && !item.editable) { return; } @@ -1193,7 +1193,7 @@ ItemSet.prototype._onDragStart = function (event) { item: dragLeftItem, initialX: event.center.x, dragLeft: true, - data: util.extend({}, item.data) // clone the items data + data: this._cloneItemData(item.data) }; this.touchParams.itemProps = [props]; @@ -1203,7 +1203,7 @@ ItemSet.prototype._onDragStart = function (event) { item: dragRightItem, initialX: event.center.x, dragRight: true, - data: util.extend({}, item.data) // clone the items data + data: this._cloneItemData(item.data) }; this.touchParams.itemProps = [props]; @@ -1216,15 +1216,13 @@ ItemSet.prototype._onDragStart = function (event) { this.touchParams.itemProps = this.getSelection().map(function (id) { var item = me.items[id]; var groupIndex = me._getGroupIndex(item.data.group); - var props = { + return { item: item, initialX: event.center.x, groupOffset: baseGroupIndex-groupIndex, - data: util.extend({}, item.data) // clone the items data + data: this._cloneItemData(item.data) }; - - return props; - }); + }.bind(this)); } event.stopPropagation(); @@ -1267,14 +1265,14 @@ ItemSet.prototype._onDragStartAddItem = function (event) { var newItem = new RangeItem(itemData, this.conversion, this.options); newItem.id = id; // TODO: not so nice setting id afterwards - newItem.data = itemData; + newItem.data = this._cloneItemData(itemData); this._addItem(newItem); var props = { item: newItem, dragRight: true, initialX: event.center.x, - data: util.extend({}, itemData) + data: newItem.data }; this.touchParams.itemProps = [props]; @@ -1301,32 +1299,30 @@ ItemSet.prototype._onDrag = function (event) { var updateGroupAllowed = me.options.editable.updateGroup; var newGroupBase = null; if (updateGroupAllowed && selectedItem) { - if (selectedItem.data.group != undefined) { - // drag from one group to another - var group = me.groupFromTarget(event); - if (group) { - //we know the offset for all items, so the new group for all items - //will be relative to this one. - newGroupBase = this._getGroupIndex(group.groupId); - } + if (selectedItem.data.group != undefined) { + // drag from one group to another + var group = me.groupFromTarget(event); + if (group) { + //we know the offset for all items, so the new group for all items + //will be relative to this one. + newGroupBase = this._getGroupIndex(group.groupId); } + } } // move this.touchParams.itemProps.forEach(function (props) { - var newProps = {}; var current = me.body.util.toTime(event.center.x - xOffset); var initial = me.body.util.toTime(props.initialX - xOffset); - var offset = current - initial; - - var itemData = util.extend({}, props.item.data); // clone the data + var offset = current - initial; // ms + var itemData = this._cloneItemData(props.item.data); // clone the data if (props.item.editable === false) { return; } - var updateTimeAllowed = me.options.editable.updateTime || - props.item.editable === true; + var updateTimeAllowed = me.options.editable.updateTime || + props.item.editable === true; if (updateTimeAllowed) { if (props.dragLeft) { @@ -1334,6 +1330,7 @@ ItemSet.prototype._onDrag = function (event) { if (itemData.start != undefined) { var initialStart = util.convert(props.data.start, 'Date'); var start = new Date(initialStart.valueOf() + offset); + // TODO: pass a Moment instead of a Date to snap(). (Breaking change) itemData.start = snap ? snap(start, scale, step) : start; } } @@ -1342,6 +1339,7 @@ ItemSet.prototype._onDrag = function (event) { if (itemData.end != undefined) { var initialEnd = util.convert(props.data.end, 'Date'); var end = new Date(initialEnd.valueOf() + offset); + // TODO: pass a Moment instead of a Date to snap(). (Breaking change) itemData.end = snap ? snap(end, scale, step) : end; } } @@ -1355,18 +1353,20 @@ ItemSet.prototype._onDrag = function (event) { var initialEnd = util.convert(props.data.end, 'Date'); var duration = initialEnd.valueOf() - initialStart.valueOf(); + // TODO: pass a Moment instead of a Date to snap(). (Breaking change) itemData.start = snap ? snap(start, scale, step) : start; itemData.end = new Date(itemData.start.valueOf() + duration); } else { + // TODO: pass a Moment instead of a Date to snap(). (Breaking change) itemData.start = snap ? snap(start, scale, step) : start; } } } } - var updateGroupAllowed = me.options.editable.updateGroup || - props.item.editable === true; + var updateGroupAllowed = me.options.editable.updateGroup || + props.item.editable === true; if (updateGroupAllowed && (!props.dragLeft && !props.dragRight) && newGroupBase!=null) { if (itemData.group != undefined) { @@ -1381,12 +1381,13 @@ ItemSet.prototype._onDrag = function (event) { } // confirm moving the item + itemData = this._cloneItemData(itemData); // convert start and end to the correct type me.options.onMoving(itemData, function (itemData) { if (itemData) { props.item.setData(itemData); } }); - }); + }.bind(this)); this.stackDirty = true; // force re-stacking of all items next redraw this.body.emitter.emit('change'); @@ -1445,7 +1446,7 @@ ItemSet.prototype._onDragEnd = function (event) { } else { // update existing item - var itemData = util.extend({}, props.item.data); // clone the data + var itemData = this._cloneItemData(props.item.data); // convert start and end to the correct type me.options.onMove(itemData, function (itemData) { if (itemData) { // apply changes @@ -1461,7 +1462,7 @@ ItemSet.prototype._onDragEnd = function (event) { } }); } - }); + }.bind(this)); } }; @@ -1708,7 +1709,7 @@ ItemSet.prototype._onAddItem = function (event) { var scale = this.body.util.getScale(); var step = this.body.util.getStep(); - var newItem = { + var newItemData = { start: snap ? snap(start, scale, step) : start, content: 'new item' }; @@ -1716,18 +1717,19 @@ ItemSet.prototype._onAddItem = function (event) { // when default type is a range, add a default end date to the new item if (this.options.type === 'range') { var end = this.body.util.toTime(x + this.props.width / 5); - newItem.end = snap ? snap(end, scale, step) : end; + newItemData.end = snap ? snap(end, scale, step) : end; } - newItem[this.itemsData._fieldId] = util.randomUUID(); + newItemData[this.itemsData._fieldId] = util.randomUUID(); var group = this.groupFromTarget(event); if (group) { - newItem.group = group.groupId; + newItemData.group = group.groupId; } // execute async handler to customize (or cancel) adding an item - this.options.onAdd(newItem, function (item) { + newItemData = this._cloneItemData(newItemData); // convert start and end to the correct type + this.options.onAdd(newItemData, function (item) { if (item) { me.itemsData.getDataSet().add(item); // TODO: need to trigger a redraw? @@ -1901,4 +1903,27 @@ ItemSet.itemSetFromTarget = function(event) { return null; }; +/** + * Clone the data of an item, and "normalize" it: convert the start and end date + * to the type (Date, Moment, ...) configured in the DataSet. If not configured, + * start and end are converted to Date. + * @param {Object} itemData, typically `item.data` + * @return {Object} The cloned object + * @private + */ +ItemSet.prototype._cloneItemData = function (itemData) { + var clone = util.extend({}, itemData); + + // convert start and end date to the type (Date, Moment, ...) configured in the DataSet + var type = this.itemsData.getDataSet()._options.type; + if (clone.start != undefined) { + clone.start = util.convert(clone.start, type && type.start || 'Date'); + } + if (clone.end != undefined) { + clone.end = util.convert(clone.end , type && type.end || 'Date'); + } + + return clone; +}; + module.exports = ItemSet; diff --git a/test/timeline_groups.html b/test/timeline_groups.html index aac1c2ca..4df1b433 100644 --- a/test/timeline_groups.html +++ b/test/timeline_groups.html @@ -71,7 +71,9 @@ } // create a dataset with items - var items = new vis.DataSet(); + var items = new vis.DataSet({ + type: {start: 'Moment', end: 'Moment'} + }); for (var i = 0; i < itemCount; i++) { var start = now.clone().add(Math.random() * 200, 'hours'); var end = Math.random() > 0.5 ? start.clone().add(24, 'hours') : undefined; @@ -117,6 +119,7 @@ }, onMove: function (item, callback) { + console.log('onMove', item) if (confirm('Do you really want to move the item to\n' + 'start: ' + item.start + '\n' + 'end: ' + item.end + '?')) {