Browse Source

Implemented item selection and a function select to get/set the selected items

css_transitions
josdejong 11 years ago
parent
commit
ebf756c88f
7 changed files with 128 additions and 33 deletions
  1. +3
    -0
      HISTORY.md
  2. +8
    -1
      docs/timeline.html
  3. +31
    -30
      examples/timeline/06_event_listeners.html
  4. +77
    -2
      src/timeline/Timeline.js
  5. +3
    -0
      src/timeline/component/item/ItemBox.js
  6. +3
    -0
      src/timeline/component/item/ItemPoint.js
  7. +3
    -0
      src/timeline/component/item/ItemRange.js

+ 3
- 0
HISTORY.md View File

@ -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

+ 8
- 1
docs/timeline.html View File

@ -555,7 +555,7 @@ var options = {
<tr>
<td>on(event, callback)</td>
<td>none</td>
<td>Create an event listener. The callback function is invoked every time the event is triggered. Avialable events: <code>rangechange</code>, <code>rangechanged</code>. The callback function is invoked as <code>callback(properties)</code>, where <code>properties</code> is an object containing event specific properties.</td>
<td>Create an event listener. The callback function is invoked every time the event is triggered. Avialable events: <code>rangechange</code>, <code>rangechanged</code>, <code>select</code>. The callback function is invoked as <code>callback(properties)</code>, where <code>properties</code> is an object containing event specific properties.</td>
</tr>
<tr>
@ -564,6 +564,13 @@ var options = {
<td>Remove an event listener created before via function <code>on(event, callback)</code>.</td>
</tr>
<tr>
<td>select([ids])</td>
<td>ids</td>
<td>Select or deselect items, or get current selection. Returns an array with the ids of the currently selected items.
</td>
</tr>
<tr>
<td>setGroups(groups)</td>
<td>none</td>

+ 31
- 30
examples/timeline/06_event_listeners.html View File

@ -13,39 +13,40 @@
<link href="../../dist/vis.css" rel="stylesheet" type="text/css" />
</head>
<body>
<div id="visualization"></div>
<div id="log"></div>
<div id="visualization"></div>
<p></p>
<div id="log"></div>
<script type="text/javascript">
var container = document.getElementById('visualization');
var items = [
{id: 1, content: 'item 1', start: '2013-04-20'},
{id: 2, content: 'item 2', start: '2013-04-14'},
{id: 3, content: 'item 3', start: '2013-04-18'},
{id: 4, content: 'item 4', start: '2013-04-16', end: '2013-04-19'},
{id: 5, content: 'item 5', start: '2013-04-25'},
{id: 6, content: 'item 6', start: '2013-04-27'}
];
var options = {};
var timeline = new vis.Timeline(container, items, options);
<script type="text/javascript">
var container = document.getElementById('visualization');
var items = [
{id: 1, content: 'item 1', start: '2013-04-20'},
{id: 2, content: 'item 2', start: '2013-04-14'},
{id: 3, content: 'item 3', start: '2013-04-18'},
{id: 4, content: 'item 4', start: '2013-04-16', end: '2013-04-19'},
{id: 5, content: 'item 5', start: '2013-04-25'},
{id: 6, content: 'item 6', start: '2013-04-27'}
];
var options = {};
var timeline = new vis.Timeline(container, items, options);
function logEvent(event, properties) {
var log = document.getElementById('log');
var msg = document.createElement('div');
msg.innerHTML = 'event=' + event + ', properties=' + JSON.stringify(properties);
log.firstChild ? log.insertBefore(msg, log.firstChild) : log.appendChild(msg);
}
timeline.on('rangechange', function (properties) {
logEvent('rangechange', properties);
});
timeline.on('rangechanged', function (properties) {
logEvent('rangechanged', properties);
});
timeline.on('select', function (properties) {
logEvent('select', properties);
});
timeline.on('rangechange', function (properties) {
logEvent('rangechange', properties);
});
timeline.on('rangechanged', function (properties) {
logEvent('rangechanged', properties);
});
timeline.on('select', function (properties) {
logEvent('select', properties);
});
function logEvent(event, properties) {
var log = document.getElementById('log');
var msg = document.createElement('div');
msg.innerHTML = 'event=' + event + ', properties=' + JSON.stringify(properties);
log.firstChild ? log.insertBefore(msg, log.firstChild) : log.appendChild(msg);
}
</script>
</script>
</body>
</html>

+ 77
- 2
src/timeline/Timeline.js View File

@ -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;
};

+ 3
- 0
src/timeline/component/item/ItemBox.js View File

@ -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;
}
};

+ 3
- 0
src/timeline/component/item/ItemPoint.js View File

@ -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;
}
};

+ 3
- 0
src/timeline/component/item/ItemRange.js View File

@ -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;
}
};

Loading…
Cancel
Save