Skip to content

Commit

Permalink
Sequential selection feat (#73)
Browse files Browse the repository at this point in the history
* Sequential Selectability

* docs
  • Loading branch information
jczacharia authored and yotamberk committed Sep 7, 2019
1 parent 45182af commit d35e6ce
Show file tree
Hide file tree
Showing 5 changed files with 278 additions and 2 deletions.
7 changes: 7 additions & 0 deletions docs/timeline/index.html
Original file line number Diff line number Diff line change
Expand Up @@ -1076,6 +1076,13 @@ <h2 id="Configuration_Options">Configuration Options</h2>
<td>If true, the items on the timeline can be selected. Multiple items can be selected by long pressing them, or by using ctrl+click or shift+click. The event <code>select</code> is fired each time the selection has changed (see section <a href="#Events">Events</a>).</td>
</tr>

<tr>
<td>sequentialSelection</td>
<td>boolean</td>
<td><code>false</code></td>
<td>If true, then only sequential items are allowed to be selected (no gaps) when <code>multiselect</code> is true</td>
</tr>

<tr>
<td>showCurrentTime</td>
<td>boolean</td>
Expand Down
1 change: 1 addition & 0 deletions examples/timeline/index.html
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ <h3>interaction</h3>
<a href="./interaction/navigationMenu.html">navigation menu</a><br />
<a href="./interaction/rollingMode.html">rolling mode</a><br />
<a href="./interaction/setSelection.html">set selection</a><br />
<a href="./interaction/sequentialSelection.html">Sequential Selection</a><br />
<a href="./interaction/specificItemSelectable.html">specific selectable items</a><br />

<h3>editing</h3>
Expand Down
259 changes: 259 additions & 0 deletions examples/timeline/interaction/sequentialSelection.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,259 @@
<!DOCTYPE html>
<html>
<head>
<title>Timeline | Sequential Selection</title>

<script src="../../../dist/vis-timeline-graph2d.min.js"></script>
<link href="../../../dist/vis-timeline-graph2d.min.css" rel="stylesheet" type="text/css" />

<style>
body,
html {
font-family: arial, sans-serif;
font-size: 11pt;
}

.vis-item.vis-background.negative {
background-color: rgba(255, 0, 0, 0.2);
}
.vis-item.vis-background.positive {
background-color: rgba(105, 255, 98, 0.2);
}
.vis-item.vis-background.marker {
border-left: 2px solid green;
}

table {
border: 1px solid gray;
}

td {
text-align: center;
}

code {
padding: 2px 4px;
font-size: 90%;
color: #c7254e;
background-color: #f9f2f4;
border-radius: 4px;
}
</style>
</head>
<body>
<p>This example shows the sequential selection option.</p>
<p>
When <code>sequentialSelection</code> is true, then only sequential items are allowed to be selected (no
gaps).
</p>
<table>
<thead>
<tr>
<th>Option</th>
<th>Status</th>
<th>Toggle</th>
</tr>
</thead>
<tbody>
<tr>
<td><code>sequentialSelection</code></td>
<td id="seq">true</td>
<td><button onclick="toggleSequentialSelection()">Toggle</button></td>
</tr>
</tbody>
</table>
<br />

<div id="visualization"></div>

<script>
// create a dataset with items
// we specify the type of the fields `start` and `end` here to be strings
// containing an ISO date. The fields will be outputted as ISO dates
// automatically getting data from the DataSet via items.get().
var items = new vis.DataSet({
type: { start: 'ISODate', end: 'ISODate' }
});
var groups = new vis.DataSet([
{
id: 'bar',
content: 'bar',
subgroupStack: { sg_1: true, sg_2: true, sg_3: true },
subgroupVisibility: { sg_1: true, sg_2: true, sg_3: true }
},
{
id: 'foo',
content: 'foo',
subgroupOrder: 'subgroupOrder' // this group has no subgroups but this would be the other method to do the sorting.
}
]);
// add items to the DataSet
items.add([
{ id: 'A', start: '2014-01-20', end: '2014-01-22', type: 'background', group: 'foo' },
{
id: 'B',
start: '2014-01-22',
end: '2014-01-23',
type: 'background',
group: 'foo',
className: 'negative'
},
{ id: 0, content: 'no subgroup', start: '2014-01-20', end: '2014-01-22', group: 'foo' },

{
id: 'SG_1_1',
start: '2014-01-25',
end: '2014-01-27',
type: 'background',
group: 'bar',
subgroup: 'sg_1',
subgroupOrder: 0
},
{
id: 'SG_1_2',
start: '2014-01-26',
end: '2014-01-27',
type: 'background',
className: 'positive',
group: 'bar',
subgroup: 'sg_1',
subgroupOrder: 0
},
{
id: 1,
content: 'subgroup0_1',
start: '2014-01-23T12:00:00',
end: '2014-01-26T12:00:00',
group: 'bar',
subgroup: 'sg_1',
subgroupOrder: 0
},
{
id: 2,
content: 'subgroup0_2',
start: '2014-01-22T12:00:01',
end: '2014-01-25T12:00:00',
group: 'bar',
subgroup: 'sg_1',
subgroupOrder: 0
},

{
id: 'SG_2_1',
start: '2014-02-01',
end: '2014-02-02',
type: 'background',
group: 'bar',
subgroup: 'sg_2',
subgroupOrder: 1
},
{
id: 'SG_2_2',
start: '2014-02-2',
end: '2014-02-03',
type: 'background',
className: 'negative',
group: 'bar',
subgroup: 'sg_2',
subgroupOrder: 1
},
{
id: 3,
content: 'subgroup1_1',
start: '2014-01-27T02:00:00',
end: '2014-01-29',
group: 'bar',
subgroup: 'sg_2',
subgroupOrder: 1
},
{
id: 4,
content: 'subgroup1_2',
start: '2014-01-28',
end: '2014-02-02',
group: 'bar',
subgroup: 'sg_2',
subgroupOrder: 1
},

{
id: 'SG_3_1',
start: '2014-01-23',
end: '2014-01-25',
type: 'background',
group: 'bar',
subgroup: 'sg_3',
subgroupOrder: 2,
content: 'a'
},
{
id: 'SG_3_2',
start: '2014-01-26',
end: '2014-01-28',
type: 'background',
className: 'positive',
group: 'bar',
subgroup: 'sg_3',
subgroupOrder: 2,
content: 'b'
},
{
id: 5,
content: 'subgroup2_1',
start: '2014-01-23T12:00:00',
end: '2014-01-26T12:00:00',
group: 'bar',
subgroup: 'sg_3',
subgroupOrder: 2
},
{
id: 6,
content: 'subgroup2_2',
start: '2014-01-26T12:00:01',
end: '2014-01-29T12:00:00',
group: 'bar',
subgroup: 'sg_3',
subgroupOrder: 2
},

{
id: 'background',
start: '2014-01-29',
end: '2014-01-30',
type: 'background',
className: 'negative',
group: 'bar'
},
{
id: 'background_all',
start: '2014-01-31',
end: '2014-02-02',
type: 'background',
className: 'positive'
}
]);

var container = document.getElementById('visualization');
var stackingStatus = document.getElementById('stackingStatus');
var stackSubgroupsStatus = document.getElementById('stackSubgroupsStatus');
var options = {
// orientation:'top'
start: '2014-01-10',
end: '2014-02-10',
editable: true,
stack: true,
stackSubgroups: true,
multiselect: true,
sequentialSelection: true
};

var timeline = new vis.Timeline(container, items, groups, options);

function toggleSequentialSelection() {
options.sequentialSelection = !options.sequentialSelection;
document.getElementById('seq').innerHTML = options.sequentialSelection;
timeline.setOptions(options);
}
</script>
</body>
</html>
12 changes: 10 additions & 2 deletions lib/timeline/component/ItemSet.js
Original file line number Diff line number Diff line change
Expand Up @@ -149,6 +149,8 @@ class ItemSet extends Component {
this.itemsSettingTime = null;
this.initialItemSetDrawn = false;
this.userContinueNotBail = null;

this.sequentialSelection = false;

// listeners for the DataSet of the items
this.itemListeners = {
Expand Down Expand Up @@ -389,7 +391,7 @@ class ItemSet extends Component {
if (options) {
// copy all options that we know
const fields = [
'type', 'rtl', 'align', 'order', 'stack', 'stackSubgroups', 'selectable', 'multiselect',
'type', 'rtl', 'align', 'order', 'stack', 'stackSubgroups', 'selectable', 'multiselect', 'sequentialSelection',
'multiselectPerGroup', 'groupOrder', 'dataAttributes', 'template', 'groupTemplate', 'visibleFrameTemplate',
'hide', 'snap', 'groupOrderSwap', 'showTooltips', 'tooltip', 'tooltipOnItemUpdateTime', 'groupHeightMode', 'onTimeout'
];
Expand All @@ -409,6 +411,12 @@ class ItemSet extends Component {
}
}

if ('sequentialSelection' in options) {
if (typeof options.sequentialSelection === 'boolean') {
this.options.sequentialSelection = options.sequentialSelection;
}
}

if ('orientation' in options) {
if (typeof options.orientation === 'string') {
this.options.orientation.item = options.orientation === 'top' ? 'top' : 'bottom';
Expand Down Expand Up @@ -2358,7 +2366,7 @@ class ItemSet extends Component {

const shiftKey = event.srcEvent && event.srcEvent.shiftKey || false;

if (shiftKey && this.options.multiselect) {
if ((shiftKey || this.options.sequentialSelection) && this.options.multiselect) {
// select all items between the old selection and the tapped item
const itemGroup = this.itemsData.get(item.id).group;

Expand Down
1 change: 1 addition & 0 deletions lib/timeline/optionsTimeline.js
Original file line number Diff line number Diff line change
Expand Up @@ -141,6 +141,7 @@ let allOptions = {
__type__: {string, object}
},
selectable: { 'boolean': bool},
sequentialSelection: { 'boolean': bool },
showCurrentTime: { 'boolean': bool},
showMajorLabels: { 'boolean': bool},
showMinorLabels: { 'boolean': bool},
Expand Down

0 comments on commit d35e6ce

Please sign in to comment.