Browse Source

Fixed #6: options `min` and `max` are broken.

css_transitions
josdejong 11 years ago
parent
commit
15a4ac5265
6 changed files with 88 additions and 75 deletions
  1. +2
    -0
      HISTORY.md
  2. +52
    -45
      src/timeline/Range.js
  3. +1
    -2
      src/timeline/TimeStep.js
  4. +19
    -18
      src/timeline/Timeline.js
  5. +7
    -6
      src/timeline/component/TimeAxis.js
  6. +7
    -4
      test/timeline.html

+ 2
- 0
HISTORY.md View File

@ -5,6 +5,8 @@ http://visjs.org
- Implemented option `showCurrentTime`, displaying a red, vertical bar at - Implemented option `showCurrentTime`, displaying a red, vertical bar at
current time. Thanks fi0dor. current time. Thanks fi0dor.
- Fixed broken Timeline options `min` and `max`.
- Fixed not being able to load vis.js in node.js.
## 2013-09-20, version 0.2.0 ## 2013-09-20, version 0.2.0

+ 52
- 45
src/timeline/Range.js View File

@ -8,16 +8,10 @@
*/ */
function Range(options) { function Range(options) {
this.id = util.randomUUID(); this.id = util.randomUUID();
this.start = 0; // Number
this.end = 0; // Number
// this.options = options || {}; // TODO: fix range options
this.options = {
min: null,
max: null,
zoomMin: null,
zoomMax: null
};
this.start = null; // Number
this.end = null; // Number
this.options = options || {};
this.listeners = []; this.listeners = [];
@ -27,8 +21,6 @@ function Range(options) {
/** /**
* Set options for the range controller * Set options for the range controller
* @param {Object} options Available options: * @param {Object} options Available options:
* {Number} start Set start value of the range
* {Number} end Set end value of the range
* {Number} min Minimum value for start * {Number} min Minimum value for start
* {Number} max Maximum value for end * {Number} max Maximum value for end
* {Number} zoomMin Set a minimum value for * {Number} zoomMin Set a minimum value for
@ -39,8 +31,9 @@ function Range(options) {
Range.prototype.setOptions = function (options) { Range.prototype.setOptions = function (options) {
util.extend(this.options, options); util.extend(this.options, options);
if (options.start != null || options.end != null) {
this.setRange(options.start, options.end);
// re-apply range with new limitations
if (this.start !== null && this.end !== null) {
this.setRange(this.start, this.end);
} }
}; };
@ -119,8 +112,8 @@ Range.prototype._trigger = function (event) {
/** /**
* Set a new start and end range * Set a new start and end range
* @param {Number} start
* @param {Number} end
* @param {Number} [start]
* @param {Number} [end]
*/ */
Range.prototype.setRange = function(start, end) { Range.prototype.setRange = function(start, end) {
var changed = this._applyRange(start, end); var changed = this._applyRange(start, end);
@ -134,21 +127,23 @@ Range.prototype.setRange = function(start, end) {
* Set a new start and end range. This method is the same as setRange, but * Set a new start and end range. This method is the same as setRange, but
* does not trigger a range change and range changed event, and it returns * does not trigger a range change and range changed event, and it returns
* true when the range is changed * true when the range is changed
* @param {Number} start
* @param {Number} end
* @param {Number} [start]
* @param {Number} [end]
* @return {Boolean} changed * @return {Boolean} changed
* @private * @private
*/ */
Range.prototype._applyRange = function(start, end) { Range.prototype._applyRange = function(start, end) {
var newStart = (start != null) ? util.convert(start, 'Number') : this.start;
var newEnd = (end != null) ? util.convert(end, 'Number') : this.end;
var diff;
var newStart = (start != null) ? util.convert(start, 'Number') : this.start,
newEnd = (end != null) ? util.convert(end, 'Number') : this.end,
max = (this.options.max != null) ? util.convert(this.options.max, 'Date').valueOf() : null,
min = (this.options.min != null) ? util.convert(this.options.min, 'Date').valueOf() : null,
diff;
// check for valid number // check for valid number
if (isNaN(newStart)) {
if (isNaN(newStart) || newStart === null) {
throw new Error('Invalid start "' + start + '"'); throw new Error('Invalid start "' + start + '"');
} }
if (isNaN(newEnd)) {
if (isNaN(newEnd) || newEnd === null) {
throw new Error('Invalid end "' + end + '"'); throw new Error('Invalid end "' + end + '"');
} }
@ -158,64 +153,76 @@ Range.prototype._applyRange = function(start, end) {
} }
// prevent start < min // prevent start < min
if (this.options.min != null) {
var min = this.options.min.valueOf();
if (min !== null) {
if (newStart < min) { if (newStart < min) {
diff = (min - newStart); diff = (min - newStart);
newStart += diff; newStart += diff;
newEnd += diff; newEnd += diff;
// prevent end > max
if (max != null) {
if (newEnd > max) {
newEnd = max;
}
}
} }
} }
// prevent end > max // prevent end > max
if (this.options.max != null) {
var max = this.options.max.valueOf();
if (max !== null) {
if (newEnd > max) { if (newEnd > max) {
diff = (newEnd - max); diff = (newEnd - max);
newStart -= diff; newStart -= diff;
newEnd -= diff; newEnd -= diff;
// prevent start < min
if (min != null) {
if (newStart < min) {
newStart = min;
}
}
} }
} }
// prevent (end-start) > zoomMin
if (this.options.zoomMin != null) {
var zoomMin = this.options.zoomMin.valueOf();
// prevent (end-start) < zoomMin
if (this.options.zoomMin !== null) {
var zoomMin = parseFloat(this.options.zoomMin);
if (zoomMin < 0) { if (zoomMin < 0) {
zoomMin = 0; zoomMin = 0;
} }
if ((newEnd - newStart) < zoomMin) { if ((newEnd - newStart) < zoomMin) {
if ((this.end - this.start) > zoomMin) {
if ((this.end - this.start) === zoomMin) {
// ignore this action, we are already zoomed to the minimum
newStart = this.start;
newEnd = this.end;
}
else {
// zoom to the minimum // zoom to the minimum
diff = (zoomMin - (newEnd - newStart)); diff = (zoomMin - (newEnd - newStart));
newStart -= diff / 2; newStart -= diff / 2;
newEnd += diff / 2; newEnd += diff / 2;
} }
else {
// ingore this action, we are already zoomed to the minimum
newStart = this.start;
newEnd = this.end;
}
} }
} }
// prevent (end-start) > zoomMin
if (this.options.zoomMax != null) {
var zoomMax = this.options.zoomMax.valueOf();
// prevent (end-start) > zoomMax
if (this.options.zoomMax !== null) {
var zoomMax = parseFloat(this.options.zoomMax);
if (zoomMax < 0) { if (zoomMax < 0) {
zoomMax = 0; zoomMax = 0;
} }
if ((newEnd - newStart) > zoomMax) { if ((newEnd - newStart) > zoomMax) {
if ((this.end - this.start) < zoomMax) {
if ((this.end - this.start) === zoomMax) {
// ignore this action, we are already zoomed to the maximum
newStart = this.start;
newEnd = this.end;
}
else {
// zoom to the maximum // zoom to the maximum
diff = ((newEnd - newStart) - zoomMax); diff = ((newEnd - newStart) - zoomMax);
newStart += diff / 2; newStart += diff / 2;
newEnd -= diff / 2; newEnd -= diff / 2;
} }
else {
// ingore this action, we are already zoomed to the maximum
newStart = this.start;
newEnd = this.end;
}
} }
} }

+ 1
- 2
src/timeline/TimeStep.js View File

@ -63,8 +63,7 @@ TimeStep.SCALE = {
*/ */
TimeStep.prototype.setRange = function(start, end, minimumStep) { TimeStep.prototype.setRange = function(start, end, minimumStep) {
if (!(start instanceof Date) || !(end instanceof Date)) { if (!(start instanceof Date) || !(end instanceof Date)) {
//throw "No legal start or end date in method setRange";
return;
throw "No legal start or end date in method setRange";
} }
this._start = (start != undefined) ? new Date(start.valueOf()) : new Date(); this._start = (start != undefined) ? new Date(start.valueOf()) : new Date();

+ 19
- 18
src/timeline/Timeline.js View File

@ -7,11 +7,12 @@
*/ */
function Timeline (container, items, options) { function Timeline (container, items, options) {
var me = this; var me = this;
this.options = util.extend({
var now = moment().hours(0).minutes(0).seconds(0).milliseconds(0);
this.options = {
orientation: 'bottom', orientation: 'bottom',
min: null, min: null,
max: null, max: null,
zoomMin: 10, // milliseconds
zoomMin: 10, // milliseconds
zoomMax: 1000 * 60 * 60 * 24 * 365 * 10000, // milliseconds zoomMax: 1000 * 60 * 60 * 24 * 365 * 10000, // milliseconds
// moveable: true, // TODO: option moveable // moveable: true, // TODO: option moveable
// zoomable: true, // TODO: option zoomable // zoomable: true, // TODO: option zoomable
@ -19,7 +20,7 @@ function Timeline (container, items, options) {
showMajorLabels: true, showMajorLabels: true,
showCurrentTime: false, showCurrentTime: false,
autoResize: false autoResize: false
}, options);
};
// controller // controller
this.controller = new Controller(); this.controller = new Controller();
@ -72,19 +73,13 @@ function Timeline (container, items, options) {
this.controller.add(this.labelPanel); this.controller.add(this.labelPanel);
// range // range
var now = moment().hours(0).minutes(0).seconds(0).milliseconds(0);
this.range = new Range({
start: now.clone().add('days', -3).valueOf(),
end: now.clone().add('days', 4).valueOf()
});
/* TODO: fix range options
var rangeOptions = Object.create(this.options); var rangeOptions = Object.create(this.options);
this.range = new Range(rangeOptions); this.range = new Range(rangeOptions);
this.range.setRange( this.range.setRange(
now.clone().add('days', -3).valueOf(), now.clone().add('days', -3).valueOf(),
now.clone().add('days', 4).valueOf() now.clone().add('days', 4).valueOf()
); );
*/
// TODO: reckon with options moveable and zoomable // TODO: reckon with options moveable and zoomable
this.range.subscribe(this.rootPanel, 'move', 'horizontal'); this.range.subscribe(this.rootPanel, 'move', 'horizontal');
this.range.subscribe(this.rootPanel, 'zoom', 'horizontal'); this.range.subscribe(this.rootPanel, 'zoom', 'horizontal');
@ -120,7 +115,12 @@ function Timeline (container, items, options) {
this.itemsData = null; // DataSet this.itemsData = null; // DataSet
this.groupsData = null; // DataSet this.groupsData = null; // DataSet
// set data
// apply options
if (options) {
this.setOptions(options);
}
// set data (must be after options are applied)
if (items) { if (items) {
this.setItems(items); this.setItems(items);
} }
@ -131,11 +131,12 @@ function Timeline (container, items, options) {
* @param {Object} options TODO: describe the available options * @param {Object} options TODO: describe the available options
*/ */
Timeline.prototype.setOptions = function (options) { Timeline.prototype.setOptions = function (options) {
if (options) {
util.extend(this.options, options);
}
util.extend(this.options, options);
// TODO: apply range min,max
// force update of range
// options.start and options.end can be undefined
//this.range.setRange(options.start, options.end);
this.range.setRange();
this.controller.reflow(); this.controller.reflow();
this.controller.repaint(); this.controller.repaint();
@ -174,7 +175,7 @@ Timeline.prototype.setItems = function(items) {
// apply the data range as range // apply the data range as range
var dataRange = this.getItemRange(); var dataRange = this.getItemRange();
// add 5% on both sides
// add 5% space on both sides
var min = dataRange.min; var min = dataRange.min;
var max = dataRange.max; var max = dataRange.max;
if (min != null && max != null) { if (min != null && max != null) {
@ -189,10 +190,10 @@ Timeline.prototype.setItems = function(items) {
// override specified start and/or end date // override specified start and/or end date
if (this.options.start != undefined) { if (this.options.start != undefined) {
min = new Date(this.options.start.valueOf());
min = util.convert(this.options.start, 'Date');
} }
if (this.options.end != undefined) { if (this.options.end != undefined) {
max = new Date(this.options.end.valueOf());
max = util.convert(this.options.end, 'Date');
} }
// apply range if there is a min or max available // apply range if there is a min or max available

+ 7
- 6
src/timeline/component/TimeAxis.js View File

@ -487,12 +487,13 @@ TimeAxis.prototype.reflow = function () {
// calculate range and step // calculate range and step
this._updateConversion(); this._updateConversion();
var start = util.convert(range.start, 'Date'),
end = util.convert(range.end, 'Date'),
minimumStep = this.toTime((props.minorCharWidth || 10) * 5) - this.toTime(0);
this.step = new TimeStep(start, end, minimumStep);
changed += update(props.range, 'start', start.valueOf());
changed += update(props.range, 'end', end.valueOf());
var start = util.convert(range.start, 'Number'),
end = util.convert(range.end, 'Number'),
minimumStep = this.toTime((props.minorCharWidth || 10) * 5).valueOf()
-this.toTime(0).valueOf();
this.step = new TimeStep(new Date(start), new Date(end), minimumStep);
changed += update(props.range, 'start', start);
changed += update(props.range, 'end', end);
changed += update(props.range, 'minimumStep', minimumStep.valueOf()); changed += update(props.range, 'minimumStep', minimumStep.valueOf());
} }

+ 7
- 4
test/timeline.html View File

@ -2,6 +2,7 @@
<html> <html>
<head> <head>
<title></title> <title></title>
<script src="../node_modules/moment/moment.js"></script>
<script src="../vis.js"></script> <script src="../vis.js"></script>
<style type="text/css"> <style type="text/css">
@ -62,11 +63,13 @@
var container = document.getElementById('visualization'); var container = document.getElementById('visualization');
var options = { var options = {
//orientation: 'top', //orientation: 'top',
//start: now.clone().add('days', -7).valueOf(),
//end: now.clone().add('days', 7).valueOf(),
start: now.clone().add('days', -7),
end: now.clone().add('days', 7),
//maxHeight: 200, //maxHeight: 200,
min: moment('2013-01-01').valueOf(),
max: moment('2013-12-31').valueOf(),
//start: moment('2013-01-01'),
//end: moment('2013-12-31'),
min: moment('2013-01-01'),
max: moment('2013-12-31'),
zoomMin: 1000 * 60 * 60 * 24, // 1 day zoomMin: 1000 * 60 * 60 * 24, // 1 day
zoomMax: 1000 * 60 * 60 * 24 * 30 * 6 // 6 months zoomMax: 1000 * 60 * 60 * 24 * 30 * 6 // 6 months
}; };

Loading…
Cancel
Save