-
Notifications
You must be signed in to change notification settings - Fork 6
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Ivo Sonderegger
committed
Oct 21, 2019
1 parent
d9776d1
commit 05583df
Showing
2 changed files
with
242 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,146 @@ | ||
/** | ||
* @module meteoJS/timeline/navigationButtons | ||
*/ | ||
import addEventFunctions from '../Events.js'; | ||
import Timeline from '../Timeline.js'; | ||
|
||
/** | ||
* Determines how the time is chosen, when a button for time navigation is | ||
* clicked. On "exact" the time in the timeline is only changed if the time | ||
* exists. In all other cases the time will be changed and a suitable timestamp | ||
* is chosen. | ||
* | ||
* @typedef {string="exact","nearest","before","later"} | ||
* module:meteoJS/timeline/navigationButtons~findTimeBy | ||
*/ | ||
|
||
/** | ||
* Options for NavigationButtons. | ||
* | ||
* @typedef {Object} module:meteoJS/timeline/navigationButtons~options | ||
* @param {module:meteoJS/timeline~Timeline} timeline - Timeline object. | ||
* @param {module:meteoJS/timeline/navigationButtons~findTimeBy} findTimeBy | ||
* Determines how the time is chosen, when a button is clicked. | ||
* @param {string|undefined} buttonClass - Default button class. | ||
*/ | ||
|
||
/** | ||
* @classdesc Class to create buttons and insert them into the DOM to navigate | ||
* through the times of the passed timeline. | ||
* Events, wenn gedrückt (und vorallem wenn Time nicht vorhanden) | ||
* Wenn Zeit nicht vorhanden, wähle nächster Zeitpunkt/früherer/späterere/kein Zeitpunkt | ||
* In Verbindung mit keyboardNavigation -> Tooltip dazu | ||
* | ||
* @fires module:meteoJS/timeline/navigationButtons#click:button | ||
*/ | ||
export class NavigationButtons { | ||
|
||
/** | ||
* @param {module:meteoJS/timeline/navigationButtons~options} [options] | ||
* Options. | ||
*/ | ||
constructor({ timeline, | ||
findTimeBy = "exact", | ||
buttonClass, | ||
} = {}) { | ||
/** | ||
* @type module:meteoJS/timeline~Timeline | ||
*/ | ||
this.timeline = timeline; | ||
|
||
/** | ||
* @type module:meteoJS/timeline/navigationButtons~findTimeBy | ||
*/ | ||
this.findTimeBy = findTimeBy; | ||
|
||
/** | ||
* @type string|undefined | ||
*/ | ||
this.buttonClass = buttonClass; | ||
} | ||
|
||
/** | ||
* @typedef {Object} module:meteoJS/timeline/navigationButtons~buttonDefinition | ||
* @param {string|undefined} [buttonClass} - Class. | ||
* @param {string="first","last","prev","next","nextAllEnabled","prevAllEnabled","add","sub"} | ||
* methodName - Method to execute on timeline, when button is clicked. | ||
* @param {integer} [timeAmount] - Required when methodName is "add" or "sub." | ||
* @param {string} [timeKey] - Required when methodName is "add" or "sub." | ||
* @param {string} [text] - Text for button. | ||
* @param {string} [title] - Title for button. | ||
*/ | ||
|
||
/** | ||
* Creates button HTMLElements and append them to the passed node. | ||
* | ||
* @param {HTMLElement} node - Node to insert the buttons into it. | ||
* @param {...module:meteoJS/timeline/navigationButtons~buttonDefinition} | ||
* buttons - Button defintions to insert. | ||
*/ | ||
insertButtonInto(node, ...buttons) { | ||
buttons.forEach(({ buttonClass, | ||
methodName, | ||
timeAmount, | ||
timeKey, | ||
text, | ||
title } = {}) => { | ||
if (!/^(first|last|prev|next|nextAllEnabled|prevAllEnabled|add|sub)$/ | ||
.test(methodName)) | ||
return; | ||
if (text === undefined) | ||
switch (methodName) { | ||
case 'first': | ||
text = '|«'; | ||
break; | ||
case 'last': | ||
text = '»|'; | ||
break; | ||
case 'prev': | ||
text = '«'; | ||
break; | ||
case 'next': | ||
text = '»'; | ||
break; | ||
case 'nextAllEnabled': | ||
text = '»'; | ||
break; | ||
case 'prevAllEnabled': | ||
text = '«'; | ||
break; | ||
case 'add': | ||
text = `+${timeAmount}${timeKey}`; | ||
break; | ||
case 'sub': | ||
text = `-${timeAmount}${timeKey}`; | ||
break; | ||
} | ||
let button = document.createElement('button'); | ||
button.appendChild(document.createTextNode(text)); | ||
button.setAttribute('type', 'button'); | ||
if (typeof buttonClass == 'string') | ||
button.classList.add(buttonClass.split(' ')); | ||
else if (typeof this.buttonClass == 'string') | ||
button.classList.add(this.buttonClass.split(' ')); | ||
if (title !== undefined) | ||
button.setAttribute('title', title); | ||
button.addEventListener('onclick', () => { | ||
switch (methodName) { | ||
case 'add': | ||
this.timeline.add(timeAmount, timeKey); | ||
break; | ||
case 'sub': | ||
this.timeline.sub(timeAmount, timeKey); | ||
break; | ||
default: | ||
this.timeline[methodName](); | ||
} | ||
this.trigger('click:button'); | ||
}); | ||
node.appendChild(button); | ||
}); | ||
} | ||
|
||
} | ||
addEventFunctions(NavigationButtons.prototype); | ||
export default NavigationButtons; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,96 @@ | ||
import assert from 'assert'; | ||
import 'jsdom-global/register'; | ||
import Timeline from '../../../src/meteoJS/Timeline.js'; | ||
import NavigationButtons | ||
from '../../../src/meteoJS/timeline/NavigationButtons.js'; | ||
import { NavigationButtons as NavigationButtonsClass } | ||
from '../../../src/meteoJS/timeline/NavigationButtons.js'; | ||
|
||
describe('NavigationButtons', () => { | ||
let timeline = new Timeline(); | ||
timeline.setTimesBySetID('', | ||
[...Array(17).keys()] | ||
.map(i => i*3) | ||
.map(i => new Date(Date.UTC(2019, 10, 21 + Math.trunc(i/24), i % 24)))); | ||
it('Defaults', () => { | ||
let clickCounter = 0; | ||
let nB = new NavigationButtons({ timeline }); | ||
nB.on('click:button', () => clickCounter++); | ||
let node = document.createElement('div'); | ||
nB.insertButtonInto(node, | ||
{ methodName: 'first' }, | ||
{ methodName: 'prevAllEnabled' }, | ||
{ methodName: 'prev', | ||
title: 'Previous' }, | ||
{ methodName: 'sub', | ||
timeAmount: 12, | ||
timeKey: 'h' }, | ||
{ methodName: 'sub', | ||
timeAmount: 6, | ||
timeKey: 'h', | ||
text: 'ABC' }, | ||
{ methodName: 'sub', | ||
timeAmount: 3, | ||
timeKey: 'h' }, | ||
{ methodName: 'add', | ||
timeAmount: 3, | ||
timeKey: 'h' }, | ||
{ methodName: 'add', | ||
timeAmount: 12, | ||
timeKey: 'h' }, | ||
{ methodName: 'next', | ||
buttonClass: 'btn' }, | ||
{ methodName: 'nextAllEnabled' }, | ||
{ methodName: 'last' }); | ||
assert.equal(node.childElementCount, 11, 'children count'); | ||
[['', undefined, '|«'], | ||
['', undefined, '«'], | ||
['', 'Previous', '«'], | ||
['', undefined, '-12h'], | ||
['', undefined, 'ABC'], | ||
['', undefined, '-3h'], | ||
['', undefined, '+3h'], | ||
['', undefined, '+12h'], | ||
['btn', undefined, '»'], | ||
['', undefined, '»'], | ||
['', undefined, '»|']].forEach((result, i) => { | ||
assert.equal(node.children[i].className, result[0], `${i}: class`); | ||
assert.equal(node.children[i].getAttribute('title'), result[1], `${i}: title`); | ||
assert.equal(node.children[i].textContent, result[2], `${i}: textContent`); | ||
}); | ||
node.children[10].dispatchEvent(new CustomEvent('onclick')); // last | ||
assert.equal(timeline.getSelectedTime(), timeline.getTimes()[16], 'selected time 16'); | ||
node.children[6].dispatchEvent(new CustomEvent('onclick')); // +3h | ||
assert.equal(timeline.getSelectedTime(), timeline.getTimes()[16], 'selected time 16'); | ||
node.children[2].dispatchEvent(new CustomEvent('onclick')); // Prev | ||
assert.equal(timeline.getSelectedTime(), timeline.getTimes()[15], 'selected time 15'); | ||
node.children[3].dispatchEvent(new CustomEvent('onclick')); // -12h | ||
assert.equal(timeline.getSelectedTime().valueOf(), timeline.getTimes()[11].valueOf(), 'selected time 11'); | ||
assert.equal(clickCounter, 4, 'click counter'); | ||
}); | ||
it('Constructor options: buttonClass', () => { | ||
let nB = new NavigationButtons({ | ||
timeline, | ||
buttonClass: 'btn btn-secondary' | ||
}); | ||
let node = document.createElement('div'); | ||
nB.insertButtonInto(node, | ||
{ methodName: 'first' }, | ||
{ methodName: 'last' }); | ||
assert.equal(node.childElementCount, 2, 'children count'); | ||
assert.equal(node.children[0].className, 'btn,btn-secondary', '0: class'); | ||
assert.equal(node.children[0].getAttribute('title'), undefined, '0: title'); | ||
assert.equal(node.children[0].textContent, '|«', '0: textContent'); | ||
assert.equal(node.children[1].className, 'btn,btn-secondary', '0: class'); | ||
assert.equal(node.children[1].getAttribute('title'), undefined, '0: title'); | ||
assert.equal(node.children[1].textContent, '»|', '0: textContent'); | ||
}); | ||
it('named import', () => { | ||
let nB = new NavigationButtons({ | ||
timeline | ||
}); | ||
let node = document.createElement('div'); | ||
nB.insertButtonInto(node, { methodName: 'first' }); | ||
assert.equal(node.childElementCount, 1, 'children count'); | ||
}); | ||
}); |