diff --git a/src/timeline/Timeline.js b/src/timeline/Timeline.js index 946a1fc8..0c4b7b76 100644 --- a/src/timeline/Timeline.js +++ b/src/timeline/Timeline.js @@ -407,7 +407,7 @@ Timeline.prototype.setGroups = function(groupSet) { // create new GroupSet when needed if (!this.groupSet) { this.groupSet = new GroupSet(this.contentPanel, this.sideContentPanel, options); - this.groupSet.on('change', this.rootPanel.repaint.bind(this.rootPanel, 'changes')); + this.groupSet.on('change', this.rootPanel.repaint.bind(this.rootPanel)); this.groupSet.setRange(this.range); this.groupSet.setItems(this.itemsData); this.groupSet.setGroups(this.groupsData); diff --git a/src/timeline/component/GroupSet.js b/src/timeline/component/GroupSet.js index d52c166a..053e1c10 100644 --- a/src/timeline/component/GroupSet.js +++ b/src/timeline/component/GroupSet.js @@ -446,16 +446,59 @@ GroupSet.prototype._toQueue = function _toQueue(ids, action) { }; /** - * Find the Group from an event target: + * Find the GroupSet from an event target: * searches for the attribute 'timeline-groupset' in the event target's element * tree, then finds the right group in this groupset * @param {Event} event * @return {Group | null} group */ +GroupSet.groupSetFromTarget = function groupSetFromTarget (event) { + var target = event.target; + while (target) { + if (target.hasOwnProperty('timeline-groupset')) { + return target['timeline-groupset']; + } + target = target.parentNode; + } + + return null; +}; + +/** + * Find the Group from an event target: + * searches for the two elements having attributes 'timeline-groupset' and + * 'timeline-itemset' in the event target's element, then finds the right group. + * @param {Event} event + * @return {Group | null} group + */ GroupSet.groupFromTarget = function groupFromTarget (event) { - var groupset, - target = event.target; + // find the groupSet + var groupSet = null; + var target = event.target; + while (target && !groupSet) { + if (target.hasOwnProperty('timeline-groupset')) { + groupSet = target['timeline-groupset']; + } + target = target.parentNode; + } + + // find the itemset + var itemSet = ItemSet.itemSetFromTarget(event); + + // find the right group + if (groupSet && itemSet) { + for (var groupId in groupSet.groups) { + if (groupSet.groups.hasOwnProperty(groupId)) { + var group = groupSet.groups[groupId]; + if (group.itemSet == itemSet) { + return group; + } + } + } + } + + /* TODO: cleanup while (target) { if (target.hasOwnProperty('timeline-groupset')) { groupset = target['timeline-groupset']; @@ -474,6 +517,7 @@ GroupSet.groupFromTarget = function groupFromTarget (event) { } } } + */ return null; }; diff --git a/src/timeline/component/ItemSet.js b/src/timeline/component/ItemSet.js index ddf117ca..d44a2527 100644 --- a/src/timeline/component/ItemSet.js +++ b/src/timeline/component/ItemSet.js @@ -436,7 +436,9 @@ ItemSet.prototype.removeItem = function removeItem (id) { // confirm deletion this.options.onRemove(item, function (item) { if (item) { - dataset.remove(item); + // remove by id here, it is possible that an item has no id defined + // itself, so better not delete by the item itself + dataset.remove(id); } }); } @@ -514,13 +516,18 @@ ItemSet.prototype._onRemove = function _onRemove(ids) { var item = me.items[id]; if (item) { count++; - item.hide(); // TODO: only hide when displayed + item.hide(); delete me.items[id]; delete me.visibleItems[id]; + + // remove from selection + var index = me.selection.indexOf(id); + if (index != -1) me.selection.splice(index, 1); } }); if (count) { + // update order this._order(); this.stackDirty = true; // force re-stacking of all items next repaint this.emit('change'); @@ -662,6 +669,7 @@ ItemSet.prototype._onDragEnd = function (event) { me.options.onMove(item, function (item) { if (item) { // apply changes + item[dataset.fieldId] = id; // ensure the item contains its id (can be undefined) changes.push(item); } else { diff --git a/test/timeline.html b/test/timeline.html index 170c2297..81fae4e2 100644 --- a/test/timeline.html +++ b/test/timeline.html @@ -87,6 +87,29 @@ var timeline = new vis.Timeline(container, items, options); console.timeEnd('create timeline'); + timeline.on('select', function (selection) { + console.log('select', selection); + }); + + /* + timeline.on('rangechange', function (range) { + console.log('rangechange', range); + }); + timeline.on('rangechanged', function (range) { + console.log('rangechanged', range); + }); + */ + + items.on('add', function (nodes) { + console.log('add', nodes); + }); + items.on('update', function (nodes) { + console.log('update', nodes); + }); + items.on('remove', function (nodes) { + console.log('remove', nodes); + }); + \ No newline at end of file diff --git a/test/timeline_groups.html b/test/timeline_groups.html index 63b12c83..d2c3c49c 100644 --- a/test/timeline_groups.html +++ b/test/timeline_groups.html @@ -94,6 +94,39 @@ timeline.setItems(items); console.timeEnd('set items'); + timeline.on('select', function (selection) { + console.log('select', selection); + }); + + /* + timeline.on('rangechange', function (range) { + console.log('rangechange', range); + }); + timeline.on('rangechanged', function (range) { + console.log('rangechanged', range); + }); + */ + + items.on('add', function (nodes) { + console.log('items add', nodes); + }); + items.on('update', function (nodes) { + console.log('items update', nodes); + }); + items.on('remove', function (nodes) { + console.log('items remove', nodes); + }); + + groups.on('add', function (nodes) { + console.log('groups add', nodes); + }); + groups.on('update', function (nodes) { + console.log('groups update', nodes); + }); + groups.on('remove', function (nodes) { + console.log('groups remove', nodes); + }); + \ No newline at end of file