From ebf756c88f70cec73425d1ed27b0c654316bf696 Mon Sep 17 00:00:00 2001 From: josdejong Date: Wed, 29 Jan 2014 17:47:58 +0100 Subject: [PATCH] Implemented item selection and a function select to get/set the selected items --- HISTORY.md | 3 + docs/timeline.html | 9 ++- examples/timeline/06_event_listeners.html | 61 ++++++++--------- src/timeline/Timeline.js | 79 ++++++++++++++++++++++- src/timeline/component/item/ItemBox.js | 3 + src/timeline/component/item/ItemPoint.js | 3 + src/timeline/component/item/ItemRange.js | 3 + 7 files changed, 128 insertions(+), 33 deletions(-) diff --git a/HISTORY.md b/HISTORY.md index a0b11008..732ec19e 100644 --- a/HISTORY.md +++ b/HISTORY.md @@ -8,6 +8,9 @@ http://visjs.org - Implemented functions `on` and `off` to create event listeners for events `rangechange` and `rangechanged`. +- Impelmented function `select` to get and set the selected items. +- Items can be selected by clicking them, muti-select by holding them. + ### Graph diff --git a/docs/timeline.html b/docs/timeline.html index 91e5dadc..ccf9ce15 100644 --- a/docs/timeline.html +++ b/docs/timeline.html @@ -555,7 +555,7 @@ var options = { on(event, callback) none - Create an event listener. The callback function is invoked every time the event is triggered. Avialable events: rangechange, rangechanged. The callback function is invoked as callback(properties), where properties is an object containing event specific properties. + Create an event listener. The callback function is invoked every time the event is triggered. Avialable events: rangechange, rangechanged, select. The callback function is invoked as callback(properties), where properties is an object containing event specific properties. @@ -564,6 +564,13 @@ var options = { Remove an event listener created before via function on(event, callback). + + select([ids]) + ids + Select or deselect items, or get current selection. Returns an array with the ids of the currently selected items. + + + setGroups(groups) none diff --git a/examples/timeline/06_event_listeners.html b/examples/timeline/06_event_listeners.html index 78587db0..9257157d 100644 --- a/examples/timeline/06_event_listeners.html +++ b/examples/timeline/06_event_listeners.html @@ -13,39 +13,40 @@ -
-
+
+

+
- + \ No newline at end of file diff --git a/src/timeline/Timeline.js b/src/timeline/Timeline.js index c77678cf..3cc01b87 100644 --- a/src/timeline/Timeline.js +++ b/src/timeline/Timeline.js @@ -83,6 +83,7 @@ function Timeline (container, items, options) { ); // TODO: reckon with options moveable and zoomable + // TODO: put the listeners in setOptions, be able to dynamically change with options moveable and zoomable this.range.subscribe(this.rootPanel, 'move', 'horizontal'); this.range.subscribe(this.rootPanel, 'zoom', 'horizontal'); this.range.on('rangechange', function (properties) { @@ -96,7 +97,12 @@ function Timeline (container, items, options) { me._trigger('rangechanged', properties); }); - // TODO: put the listeners in setOptions, be able to dynamically change with options moveable and zoomable + // single select (or unselect) when tapping an item + // TODO: implement ctrl+click + this.rootPanel.on('tap', this._onSelectItem.bind(this)); + + // multi select when holding mouse/touch, or on ctrl+click + this.rootPanel.on('hold', this._onMultiSelectItem.bind(this)); // time axis var timeaxisOptions = Object.create(rootOptions); @@ -344,7 +350,8 @@ Timeline.prototype.getItemRange = function getItemRange() { }; /** - * Change the item selection, and/or get currently selected items + * Select or deselect items, or get current selection. + * Returns the currently selected items * @param {Array} [ids] An array with zero or more ids of the items to be selected. * @return {Array} ids The ids of the selected items */ @@ -389,3 +396,71 @@ Timeline.prototype.off = function off (event, callback) { Timeline.prototype._trigger = function _trigger(event, properties) { events.trigger(this, event, properties || {}); }; + +/** + * Handle selecting/deselecting an item when tapping it + * @param {Event} event + * @private + */ +Timeline.prototype._onSelectItem = function (event) { + var item = this._itemFromTarget(event); + + var selection = item ? [item.id] : []; + selection = this.select(selection); + this._trigger('select', { + items: selection + }); + + event.stopPropagation(); +}; + +/** + * Handle selecting/deselecting multiple items when holding an item + * @param {Event} event + * @private + */ +Timeline.prototype._onMultiSelectItem = function (event) { + var selection, + item = this._itemFromTarget(event); + + if (!item) { + // do nothing... + return; + } + selection = this.select(); // current selection + var index = selection.indexOf(item.id); + if (index == -1) { + // item is not yet selected -> select it + selection.push(item.id); + } + else { + // item is already selected -> deselect it + selection.splice(index, 1); + } + + selection = this.select(selection); + this._trigger('select', { + items: selection + }); + + event.stopPropagation(); +}; + +/** + * Find an item from an event target: + * searches for the attribute 'timeline-item' in the event target's element tree + * @param {Event} event + * @return {Item | null| item + * @private + */ +Timeline.prototype._itemFromTarget = function _itemFromTarget (event) { + var target = event.target; + while (target) { + if (target.hasOwnProperty('timeline-item')) { + return target['timeline-item']; + } + target = target.parentNode; + } + + return null; +}; \ No newline at end of file diff --git a/src/timeline/component/item/ItemBox.js b/src/timeline/component/item/ItemBox.js index 15f9c6ed..cde86f5a 100644 --- a/src/timeline/component/item/ItemBox.js +++ b/src/timeline/component/item/ItemBox.js @@ -260,6 +260,9 @@ ItemBox.prototype._create = function _create() { // dot on axis dom.dot = document.createElement('DIV'); dom.dot.className = 'dot'; + + // attach this item as attribute + dom.box['timeline-item'] = this; } }; diff --git a/src/timeline/component/item/ItemPoint.js b/src/timeline/component/item/ItemPoint.js index f42d6322..1a78a92b 100644 --- a/src/timeline/component/item/ItemPoint.js +++ b/src/timeline/component/item/ItemPoint.js @@ -210,6 +210,9 @@ ItemPoint.prototype._create = function _create() { dom.dot = document.createElement('div'); dom.dot.className = 'dot'; dom.point.appendChild(dom.dot); + + // attach this item as attribute + dom.point['timeline-item'] = this; } }; diff --git a/src/timeline/component/item/ItemRange.js b/src/timeline/component/item/ItemRange.js index 92774683..a2feec99 100644 --- a/src/timeline/component/item/ItemRange.js +++ b/src/timeline/component/item/ItemRange.js @@ -226,6 +226,9 @@ ItemRange.prototype._create = function _create() { dom.content = document.createElement('div'); dom.content.className = 'content'; dom.box.appendChild(dom.content); + + // attach this item as attribute + dom.box['timeline-item'] = this; } };