Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Sequential selection feat #73

Merged
merged 3 commits into from
Sep 7, 2019
Merged
Show file tree
Hide file tree
Changes from 2 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 7 additions & 0 deletions docs/timeline/index.html
Original file line number Diff line number Diff line change
Expand Up @@ -1038,6 +1038,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 />

<h3>editing</h3>
<a href="./editing/customSnappingOfItems.html">custom snapping of items</a><br />
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