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) { function When moving items on the Timeline, they will be snapped to nice dates like full hours or days, depending on the current scale. The 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. @@ -1088,10 +1090,11 @@ function (option, path) { timeAxis.scale String none - Set a fixed scale for the time axis of the Timeline. Choose from 'millisecond', 'second', 'minute', 'hour', 'weekday', 'day', 'month', 'year'. Example usage: + Set a fixed scale for the time axis of the Timeline. Choose from '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.

@@ -2023,6 +2026,9 @@ var options = { Daysvis-day1, vis-day2, ..., vis-day31 + + Weekvis-week1, vis-week2, ..., vis-week53 + Monthsvis-january, vis-february, vis-march, vis-april, vis-may, vis-june, vis-july, vis-august, vis-september, vis-october, vis-november, vis-december @@ -2030,6 +2036,9 @@ var options = { Yearsvis-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 @@ + + + + Timeline | Grid styling + + + + + + + + + + +

+ 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: {