Skip to content
Open
Show file tree
Hide file tree
Changes from all 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
41 changes: 40 additions & 1 deletion docs/timeline/index.html
Original file line number Diff line number Diff line change
Expand Up @@ -1071,6 +1071,15 @@ <h2 id="Configuration_Options">Configuration Options</h2>
</td>
</tr>

<tr parent="rollingMode" class="hidden">
<td class="indent">rollingMode.showButton</td>
<td>boolean</td>
<td><code>true</code></td>
<td>
Set whether to show the built-in button to resume rollingMode. Set to false if you want to implement your own controls.
</td>
</tr>

<tr>
<td>rtl</td>
<td>boolean</td>
Expand Down Expand Up @@ -1546,7 +1555,7 @@ <h2 id="Methods">Methods</h2>
<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. Available events: <code>rangechange</code>, <code>rangechanged</code>, <code>select</code>, <code>itemover</code>, <code>itemout</code>. The callback function is invoked as <code>callback(properties)</code>, where <code>properties</code> is an object containing event specific properties. See section <a href="#Events">Events for more information</a>.</td>
<td>Create an event listener. The callback function is invoked every time the event is triggered. Available events: <code>rangechange</code>, <code>rangechanged</code>, <code>rollingModeChanged</code>, <code>select</code>, <code>itemover</code>, <code>itemout</code>. The callback function is invoked as <code>callback(properties)</code>, where <code>properties</code> is an object containing event specific properties. See section <a href="#Events">Events for more information</a>.</td>
</tr>

<tr>
Expand Down Expand Up @@ -1676,6 +1685,27 @@ <h2 id="Methods">Methods</h2>
</td>
</tr>

<tr>
<td>enableRollingMode()</td>
<td>none</td>
<td>Enable rollingMode. If already rolling, does nothing.
</td>
</tr>

<tr>
<td>disableRollingMode()</td>
<td>none</td>
<td>Disable rollingMode. If not rolling, does nothing.
</td>
</tr>

<tr>
<td>isRolling()</td>
<td>Boolean</td>
<td>Return whether rollingMode is enabled.
</td>
</tr>

<tr>
<td>zoomIn(percentage [, options, callback])</td>
<td>none</td>
Expand Down Expand Up @@ -1881,6 +1911,15 @@ <h2 id="Events">Events</h2>
</td>
</tr>

<tr>
<td>rollingModeChanged</td>
<td>
<li><code>enabled</code> (Boolean): Whether rollingMode is enabled.</li>
</td>
<td>Fired once after rolling mode has been enabled or disabled
</td>
</tr>

<tr>
<td>select</td>
<td>
Expand Down
46 changes: 40 additions & 6 deletions lib/timeline/Range.js
Original file line number Diff line number Diff line change
Expand Up @@ -53,7 +53,8 @@ export default class Range extends Component {
zoomMax: 1000 * 60 * 60 * 24 * 365 * 10000, // milliseconds
rollingMode: {
follow: false,
offset: 0.5
offset: 0.5,
showButton: true
}
};
this.options = util.extend({}, this.defaultOptions);
Expand Down Expand Up @@ -99,14 +100,25 @@ export default class Range extends Component {
setOptions(options) {
if (options) {
// copy the options that we know
const rollingModeFields = ['follow', 'offset', 'showButton'];
util.selectiveExtend(rollingModeFields, this.options.rollingMode, options.rollingMode);

const fields = [
'animation', 'direction', 'min', 'max', 'zoomMin', 'zoomMax', 'moveable', 'zoomable',
'moment', 'activate', 'hiddenDates', 'zoomKey', 'zoomFriction', 'rtl', 'showCurrentTime', 'rollingMode', 'horizontalScroll'
'moment', 'activate', 'hiddenDates', 'zoomKey', 'zoomFriction', 'rtl', 'showCurrentTime', 'horizontalScroll'
];
util.selectiveExtend(fields, this.options, options);

if (options.rollingMode && options.rollingMode.follow) {
this.startRolling();
if (options.rollingMode) {
if (options.rollingMode.follow) {
this.startRolling();
} else if (options.rollingMode.follow === false) {
this.stopRolling();
}

if (options.rollingMode.showButton && !this.rolling) {
this.body.dom.rollingModeBtn.style.visibility = "visible";
}
}
if ('start' in options || 'end' in options) {
// apply a new range. both start and end are optional
Expand All @@ -120,12 +132,17 @@ export default class Range extends Component {
*/
startRolling() {
const me = this;
me.options.rollingMode.follow = true;

if (!me.rolling) {
this.body.emitter.emit('rollingModeChanged', {enabled: true});
}

/**
* Updates the current time.
*/
function update () {
me.stopRolling();
me._stopRolling(false);
me.rolling = true;


Expand Down Expand Up @@ -159,10 +176,27 @@ export default class Range extends Component {
* Stop auto refreshing the current time bar
*/
stopRolling() {
this._stopRolling(true);
}

/**
* Stop auto refreshing the current time bar
* @param {Boolean} fireEvent whether to fire the 'rollingModeChanged' event
* @private
* @return {void}
*/
_stopRolling(fireEvent) {
if (this.currentTimeTimer !== undefined) {
if (fireEvent) {
this.body.emitter.emit('rollingModeChanged', {enabled: false});
}
this.options.rollingMode.follow = false;

clearTimeout(this.currentTimeTimer);
this.rolling = false;
this.body.dom.rollingModeBtn.style.visibility = "visible";
if (this.options.rollingMode.showButton) {
this.body.dom.rollingModeBtn.style.visibility = "visible";
}
}
}

Expand Down
31 changes: 31 additions & 0 deletions lib/timeline/Timeline.js
Original file line number Diff line number Diff line change
Expand Up @@ -742,6 +742,37 @@ export default class Timeline extends Core {
}
}

/**
* Enable rollingMode. If already rolling, does nothing.
* @returns {void}
*/
enableRollingMode() {
if (!this.range.rolling) {
if (this.options.rollingMode == undefined) {
this.setOptions(this.options)
}
this.range.startRolling();
}
}

/**
* Disable rollingMode. If not rolling, does nothing.
* @returns {void}
*/
disableRollingMode() {
if (this.range.rolling) {
this.range.stopRolling();
}
}

/**
* Return whether rollingMode is enabled.
* @returns {Boolean}
*/
isRolling() {
return this.range.rolling;
}

/**
* redraw
* @private
Expand Down
1 change: 1 addition & 0 deletions lib/timeline/optionsTimeline.js
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@ let allOptions = {
rollingMode: {
follow: { 'boolean': bool },
offset: {number,'undefined': 'undefined'},
showButton: { 'boolean': bool },
__type__: {object}
},
onTimeout: {
Expand Down
101 changes: 101 additions & 0 deletions test/Timeline.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -64,4 +64,105 @@ describe('Timeline', () => {
assert( selectedIds.length === 1 )
assert( dataSet.get(selectedIds[0]).fooid === 2 )
});

it("enabling and disabling rollingMode should work as expected and fire applicable events", function () {
const timeline = new Timeline(document.createElement("div"), []);
assert(timeline.isRolling() === false);

let enabledEvents = 0;
let disabledEvents = 0;
timeline.on("rollingModeChanged", ({ enabled }) => {
if (enabled) {
enabledEvents += 1;
} else {
disabledEvents += 1;
}
});

// should be a no-op
timeline.disableRollingMode();
assert(timeline.isRolling() === false);

timeline.enableRollingMode();
assert(timeline.isRolling() === true);

// should be a no-op
timeline.enableRollingMode();
assert(timeline.isRolling() === true);

timeline.disableRollingMode();
assert(timeline.isRolling() === false);

assert(enabledEvents === 1);
assert(disabledEvents === 1);
});
it("enabling and disabling rollingMode via options should work as expected and fire applicable events", function () {
const timeline = new Timeline(document.createElement("div"), []);
assert(timeline.isRolling() === false);

let enabledEvents = 0;
let disabledEvents = 0;
timeline.on("rollingModeChanged", ({ enabled }) => {
if (enabled) {
enabledEvents += 1;
} else {
disabledEvents += 1;
}
});

// No-op
timeline.setOptions({rollingMode:{}});
assert(timeline.isRolling() === false);

// No-op
timeline.setOptions({rollingMode:{follow: false}});
assert(timeline.isRolling() === false);

// Now enable it
timeline.setOptions({rollingMode:{follow: true}});
assert(timeline.isRolling() === true);

// Setting some other option, without follow, should not disable it
timeline.setOptions({rollingMode:{offset: 0.5}});
assert(timeline.isRolling() === true);

timeline.setOptions({rollingMode:{follow: false}});
assert(timeline.isRolling() === false);


assert(enabledEvents === 1);
assert(disabledEvents === 1);
});
it("mixing enabling and disabling rollingMode via options and methods should work as expected and fire applicable events", function () {
const timeline = new Timeline(document.createElement("div"), []);
assert(timeline.isRolling() === false);

let enabledEvents = 0;
let disabledEvents = 0;
timeline.on("rollingModeChanged", ({ enabled }) => {
if (enabled) {
enabledEvents += 1;
} else {
disabledEvents += 1;
}
});

timeline.enableRollingMode();
assert(timeline.isRolling() === true);

// No-op
timeline.setOptions({rollingMode:{}});
assert(timeline.isRolling() === true);

// Setting some other option, without follow, should not disable it
timeline.setOptions({rollingMode:{offset: 0.5}});
assert(timeline.isRolling() === true);

// No-op
timeline.setOptions({rollingMode:{follow: false}});
assert(timeline.isRolling() === false);

assert(enabledEvents === 1);
assert(disabledEvents === 1);
});
});
1 change: 1 addition & 0 deletions types/index.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -205,6 +205,7 @@ export interface TimelineTimeAxisOption {
export interface TimelineRollingModeOption {
follow?: boolean;
offset?: number;
showButton?: boolean;
}

export interface TimelineTooltipOption {
Expand Down