diff --git a/docs/timeline/index.html b/docs/timeline/index.html index 81e40f97..374b9f97 100644 --- a/docs/timeline/index.html +++ b/docs/timeline/index.html @@ -612,6 +612,7 @@ function (option, path) { hour: 'HH:mm', weekday: 'ddd D', day: 'D', + week: 'w', month: 'MMM', year: 'YYYY' }, @@ -622,6 +623,7 @@ function (option, path) { hour: 'ddd D MMMM', weekday: 'MMMM YYYY', day: 'MMMM YYYY', + week: 'MMMM YYYY', month: 'YYYY', year: '' } @@ -1044,7 +1046,7 @@ function (option, path) {
snap
function can be replaced with a custom function, or can be set to null
to disable snapping. The signature of the snap function is:
function snap(date: Date, scale: string, step: number) : Date or number- The parameter
scale
can be can be 'millisecond', 'second', 'minute', 'hour', 'weekday, 'day, 'month, or 'year'. The parameter step
is a number like 1, 2, 4, 5.
+ The parameter scale
can be can be 'millisecond', 'second', 'minute', 'hour', 'weekday, 'week', 'day, 'month, or 'year'. The parameter step
is a number like 1, 2, 4, 5.
'millisecond'
, 'second'
, 'minute'
, 'hour'
, 'weekday'
, 'day'
, 'month'
, 'year'
. Example usage:
+ 'millisecond'
, 'second'
, 'minute'
, 'hour'
, 'weekday'
, 'week'
, 'day'
, 'month'
, 'year'
. Example usage:
var options = { timeAxis: {scale: 'minute', step: 5} }+
Note: The 'week' scale only works properly when locales are enabled.
vis-day1
, vis-day2
, ..., vis-day31
vis-week1
, vis-week2
, ..., vis-week53
vis-january
, vis-february
, vis-march
, vis-april
, vis-may
, vis-june
, vis-july
, vis-august
, vis-september
, vis-october
, vis-november
, vis-december
vis-year2014
, vis-year2015
, ...+ Note: the 'week' scale is not included in the automatic zoom levels as its scale is not a direct logical successor of 'days' nor a logical predecessor of 'months' +
Examples:
diff --git a/examples/timeline/styling/weekStyling.html b/examples/timeline/styling/weekStyling.html new file mode 100644 index 00000000..9a3a919e --- /dev/null +++ b/examples/timeline/styling/weekStyling.html @@ -0,0 +1,111 @@ + + + ++ Week numbers are calculated based on locales. For this to properly work, the timeline must be loaded with a version + of moment.js including locales.
+To set a locale for the timeline, specify the option
+ {locale: STRING}
.
To set the scale to use week numbers, use for example {scale: 'week', step: 1}
.
The following timeline is initialized with the 'de' locale and items are added with locally localized moment.js + objects. The timeline locale can be switched to another locale at runtime. If you choose the 'en' locale, the week + numbers will be calculated according to the US week calendar numbering scheme.
+ ++ + +
+ + + + + + \ No newline at end of file diff --git a/lib/timeline/TimeStep.js b/lib/timeline/TimeStep.js index e3f6ff7b..530e1726 100644 --- a/lib/timeline/TimeStep.js +++ b/lib/timeline/TimeStep.js @@ -69,6 +69,7 @@ TimeStep.FORMAT = { hour: 'HH:mm', weekday: 'ddd D', day: 'D', + week: 'w', month: 'MMM', year: 'YYYY' }, @@ -79,6 +80,7 @@ TimeStep.FORMAT = { hour: 'ddd D MMMM', weekday: 'MMMM YYYY', day: 'MMMM YYYY', + week: 'MMMM YYYY', month: 'YYYY', year: '' } @@ -101,7 +103,7 @@ TimeStep.prototype.setMoment = function (moment) { /** * Set custom formatting for the minor an major labels of the TimeStep. * Both `minorLabels` and `majorLabels` are an Object with properties: - * 'millisecond', 'second', 'minute', 'hour', 'weekday', 'day', 'month', 'year'. + * 'millisecond', 'second', 'minute', 'hour', 'weekday', 'day', 'week', 'month', 'year'. * @param {{minorLabels: Object, majorLabels: Object}} format */ TimeStep.prototype.setFormat = function (format) { @@ -153,6 +155,7 @@ TimeStep.prototype.roundToMinor = function() { this.current.year(this.step * Math.floor(this.current.year() / this.step)); this.current.month(0); case 'month': this.current.date(1); + case 'week': this.current.weekday(0); case 'day': // intentional fall through case 'weekday': this.current.hours(0); case 'hour': this.current.minutes(0); @@ -170,6 +173,7 @@ TimeStep.prototype.roundToMinor = function() { case 'hour': this.current.subtract(this.current.hours() % this.step, 'hours'); break; case 'weekday': // intentional fall through case 'day': this.current.subtract((this.current.date() - 1) % this.step, 'day'); break; + case 'week': this.current.subtract(this.current.week() % this.step, 'week'); break; case 'month': this.current.subtract(this.current.month() % this.step, 'month'); break; case 'year': this.current.subtract(this.current.year() % this.step, 'year'); break; default: break; @@ -210,6 +214,21 @@ TimeStep.prototype.next = function() { break; case 'weekday': // intentional fall through case 'day': this.current.add(this.step, 'day'); break; + case 'week': + if (this.current.weekday() !== 0){ // we had a month break not correlating with a week's start before + this.current.weekday(0); // switch back to week cycles + this.current.add(this.step, 'week'); + } else { // first day of the week + var nextWeek = this.current.clone(); + nextWeek.add(1, 'week'); + if(nextWeek.isSame(this.current, 'month')){ // is the first day of the next week in the same month? + this.current.add(this.step, 'week'); // the default case + } else { // inject a step at each first day of the month + this.current.add(this.step, 'week'); + this.current.date(1); + } + } + break; case 'month': this.current.add(this.step, 'month'); break; case 'year': this.current.add(this.step, 'year'); break; default: break; @@ -224,6 +243,7 @@ TimeStep.prototype.next = function() { case 'hour': if(this.current.hours() > 0 && this.current.hours() < this.step) this.current.hours(0); break; case 'weekday': // intentional fall through case 'day': if(this.current.date() < this.step+1) this.current.date(1); break; + case 'week': if(this.current.week() < this.step) this.current.week(1); break; // week numbering starts at 1, not 0 case 'month': if(this.current.month() < this.step) this.current.month(0); break; case 'year': break; // nothing to do for year default: break; @@ -260,7 +280,7 @@ TimeStep.prototype.getCurrent = function() { * @param {{scale: string, step: number}} params * An object containing two properties: * - A string 'scale'. Choose from 'millisecond', 'second', - * 'minute', 'hour', 'weekday', 'day', 'month', 'year'. + * 'minute', 'hour', 'weekday', 'day', 'week', 'month', 'year'. * - A number 'step'. A step size, by default 1. * Choose for example 1, 2, 5, or 10. */ @@ -338,7 +358,7 @@ TimeStep.prototype.setMinimumStep = function(minimumStep) { * Static function * @param {Date} date the date to be snapped. * @param {string} scale Current scale, can be 'millisecond', 'second', - * 'minute', 'hour', 'weekday, 'day', 'month', 'year'. + * 'minute', 'hour', 'weekday, 'day', 'week', 'month', 'year'. * @param {number} step Current step (1, 2, 4, 5, ... * @return {Date} snappedDate */ @@ -370,6 +390,20 @@ TimeStep.snap = function(date, scale, step) { clone.seconds(0); clone.milliseconds(0); } + else if (scale == 'week') { + if (clone.weekday() > 2) { // doing it the momentjs locale aware way + clone.weekday(0); + clone.add(1, 'week'); + } + else { + clone.weekday(0); + } + + clone.hours(0); + clone.minutes(0); + clone.seconds(0); + clone.milliseconds(0); + } else if (scale == 'day') { //noinspection FallthroughInSwitchStatementJS switch (step) { @@ -452,6 +486,7 @@ TimeStep.prototype.isMajor = function() { switch (this.scale) { case 'year': case 'month': + case 'week': case 'weekday': case 'day': case 'hour': @@ -465,6 +500,7 @@ TimeStep.prototype.isMajor = function() { } else if (this.switchedMonth == true) { switch (this.scale) { + case 'week': case 'weekday': case 'day': case 'hour': @@ -501,6 +537,8 @@ TimeStep.prototype.isMajor = function() { case 'weekday': // intentional fall through case 'day': return (date.date() == 1); + case 'week': + return (date.date() == 1); case 'month': return (date.month() == 0); case 'year': @@ -530,7 +568,15 @@ TimeStep.prototype.getLabelMinor = function(date) { } var format = this.format.minorLabels[this.scale]; - return (format && format.length > 0) ? this.moment(date).format(format) : ''; + // noinspection FallThroughInSwitchStatementJS + switch (this.scale) { + case 'week': + if(this.isMajor() && date.weekday() !== 0){ + return ""; + } + default: + return (format && format.length > 0) ? this.moment(date).format(format) : ''; + } }; /** @@ -624,6 +670,11 @@ TimeStep.prototype.getClassName = function() { classNames.push(this.step <= 2 ? 'vis-' + current.format('dddd').toLowerCase() : ''); classNames.push(even(current.date() - 1)); break; + case 'week': + classNames.push('vis-week' + current.format('w')); + classNames.push(currentWeek(current)); + classNames.push(even(current.week())); + break; case 'month': classNames.push('vis-' + current.format('MMMM').toLowerCase()); classNames.push(currentMonth(current)); diff --git a/lib/timeline/component/TimeAxis.js b/lib/timeline/component/TimeAxis.js index f575af4b..2d1b1d18 100644 --- a/lib/timeline/component/TimeAxis.js +++ b/lib/timeline/component/TimeAxis.js @@ -227,6 +227,7 @@ TimeAxis.prototype._repaintLabels = function () { var x; var xNext; var isMajor, nextIsMajor; + var showMinorGrid; var width = 0, prevWidth; var line; var labelMinor; @@ -255,7 +256,10 @@ TimeAxis.prototype._repaintLabels = function () { prevWidth = width; width = xNext - x; - var showMinorGrid = (width >= prevWidth * 0.4); // prevent displaying of the 31th of the month on a scale of 5 days + switch (step.scale) { + case 'week': showMinorGrid = true; break; + default: showMinorGrid = (width >= prevWidth * 0.4); break; // prevent displaying of the 31th of the month on a scale of 5 days + } if (this.options.showMinorLabels && showMinorGrid) { var label = this._repaintMinorText(x, labelMinor, orientation, className); diff --git a/lib/timeline/optionsTimeline.js b/lib/timeline/optionsTimeline.js index 41ac8d0b..fb6f3c3d 100644 --- a/lib/timeline/optionsTimeline.js +++ b/lib/timeline/optionsTimeline.js @@ -54,6 +54,7 @@ let allOptions = { hour: {string,'undefined': 'undefined'}, weekday: {string,'undefined': 'undefined'}, day: {string,'undefined': 'undefined'}, + week: {string,'undefined': 'undefined'}, month: {string,'undefined': 'undefined'}, year: {string,'undefined': 'undefined'}, __type__: {object, 'function': 'function'} @@ -65,6 +66,7 @@ let allOptions = { hour: {string,'undefined': 'undefined'}, weekday: {string,'undefined': 'undefined'}, day: {string,'undefined': 'undefined'}, + week: {string,'undefined': 'undefined'}, month: {string,'undefined': 'undefined'}, year: {string,'undefined': 'undefined'}, __type__: {object, 'function': 'function'} @@ -181,6 +183,7 @@ let configureOptions = { hour: 'HH:mm', weekday: 'ddd D', day: 'D', + week: 'w', month: 'MMM', year: 'YYYY' }, @@ -191,6 +194,7 @@ let configureOptions = { hour: 'ddd D MMMM', weekday: 'MMMM YYYY', day: 'MMMM YYYY', + week: 'MMMM YYYY', month: 'YYYY', year: '' } @@ -236,7 +240,7 @@ let configureOptions = { start: '', //template: {'function': 'function'}, //timeAxis: { - // scale: ['millisecond', 'second', 'minute', 'hour', 'weekday', 'day', 'month', 'year'], + // scale: ['millisecond', 'second', 'minute', 'hour', 'weekday', 'day', 'week', 'month', 'year'], // step: [1, 1, 10, 1] //}, tooltip: {