X-Git-Url: https://adrianiainlam.tk/git/?a=blobdiff_plain;f=dygraph-tickers.js;h=35cd75af7f905ca25abc146d1701fc7284a33705;hb=refs%2Fheads%2Fmore-spacing;hp=7b3dae1458d4df1d9ae2b7bdbac41c1747d7c111;hpb=f921ded5f9b65e5283218f7b5f9baf8f8c07178c;p=dygraphs.git diff --git a/dygraph-tickers.js b/dygraph-tickers.js index 7b3dae1..35cd75a 100644 --- a/dygraph-tickers.js +++ b/dygraph-tickers.js @@ -58,8 +58,9 @@ * middle of the years. */ -/*jshint globalstrict:true, sub:true */ +/*jshint sub:true */ /*global Dygraph:false */ +(function() { "use strict"; /** @typedef {Array.<{v:number, label:string, label_v:(string|undefined)}>} */ @@ -232,14 +233,15 @@ Dygraph.HOURLY = 10; Dygraph.TWO_HOURLY = 11; Dygraph.SIX_HOURLY = 12; Dygraph.DAILY = 13; -Dygraph.WEEKLY = 14; -Dygraph.MONTHLY = 15; -Dygraph.QUARTERLY = 16; -Dygraph.BIANNUAL = 17; -Dygraph.ANNUAL = 18; -Dygraph.DECADAL = 19; -Dygraph.CENTENNIAL = 20; -Dygraph.NUM_GRANULARITIES = 21; +Dygraph.TWO_DAILY = 14; +Dygraph.WEEKLY = 15; +Dygraph.MONTHLY = 16; +Dygraph.QUARTERLY = 17; +Dygraph.BIANNUAL = 18; +Dygraph.ANNUAL = 19; +Dygraph.DECADAL = 20; +Dygraph.CENTENNIAL = 21; +Dygraph.NUM_GRANULARITIES = 22; // Date components enumeration (in the order of the arguments in Date) // TODO: make this an @enum @@ -253,7 +255,19 @@ Dygraph.DATEFIELD_MS = 6; Dygraph.NUM_DATEFIELDS = 7; -/** @type {Array.<{datefield:number, step:number, spacing:number}>} */ +/** + * The value of datefield will start at an even multiple of "step", i.e. + * if datefield=SS and step=5 then the first tick will be on a multiple of 5s. + * + * For granularities <= HOURLY, ticks are generated every `spacing` ms. + * + * At coarser granularities, ticks are generated by incrementing `datefield` by + * `step`. In this case, the `spacing` value is only used to estimate the + * number of ticks. It should roughly correspond to the spacing between + * adjacent ticks. + * + * @type {Array.<{datefield:number, step:number, spacing:number}>} + */ Dygraph.TICK_PLACEMENT = []; Dygraph.TICK_PLACEMENT[Dygraph.SECONDLY] = {datefield: Dygraph.DATEFIELD_SS, step: 1, spacing: 1000 * 1}; Dygraph.TICK_PLACEMENT[Dygraph.TWO_SECONDLY] = {datefield: Dygraph.DATEFIELD_SS, step: 2, spacing: 1000 * 2}; @@ -269,6 +283,7 @@ Dygraph.TICK_PLACEMENT[Dygraph.HOURLY] = {datefield: Dygraph.DATEFIELD_ Dygraph.TICK_PLACEMENT[Dygraph.TWO_HOURLY] = {datefield: Dygraph.DATEFIELD_HH, step: 2, spacing: 1000 * 3600 * 2}; Dygraph.TICK_PLACEMENT[Dygraph.SIX_HOURLY] = {datefield: Dygraph.DATEFIELD_HH, step: 6, spacing: 1000 * 3600 * 6}; Dygraph.TICK_PLACEMENT[Dygraph.DAILY] = {datefield: Dygraph.DATEFIELD_D, step: 1, spacing: 1000 * 86400}; +Dygraph.TICK_PLACEMENT[Dygraph.TWO_DAILY] = {datefield: Dygraph.DATEFIELD_D, step: 2, spacing: 1000 * 86400 * 2}; Dygraph.TICK_PLACEMENT[Dygraph.WEEKLY] = {datefield: Dygraph.DATEFIELD_D, step: 7, spacing: 1000 * 604800}; Dygraph.TICK_PLACEMENT[Dygraph.MONTHLY] = {datefield: Dygraph.DATEFIELD_M, step: 1, spacing: 1000 * 7200 * 365.2524}; // 1e3 * 60 * 60 * 24 * 365.2524 / 12 Dygraph.TICK_PLACEMENT[Dygraph.QUARTERLY] = {datefield: Dygraph.DATEFIELD_M, step: 3, spacing: 1000 * 21600 * 365.2524}; // 1e3 * 60 * 60 * 24 * 365.2524 / 4 @@ -285,7 +300,7 @@ Dygraph.TICK_PLACEMENT[Dygraph.CENTENNIAL] = {datefield: Dygraph.DATEFIELD_ * NOTE: this assumes that Dygraph.LOG_SCALE = 10. * @type {Array.} */ -Dygraph.PREFERRED_LOG_TICK_VALUES = function() { +Dygraph.PREFERRED_LOG_TICK_VALUES = (function() { var vals = []; for (var power = -39; power <= 39; power++) { var range = Math.pow(10, power); @@ -295,7 +310,7 @@ Dygraph.PREFERRED_LOG_TICK_VALUES = function() { } } return vals; -}(); +})(); /** * Determine the correct granularity of ticks on a date axis. @@ -342,81 +357,34 @@ Dygraph.numDateTicks = function(start_time, end_time, granularity) { Dygraph.getDateAxis = function(start_time, end_time, granularity, opts, dg) { var formatter = /** @type{AxisLabelFormatter} */( opts("axisLabelFormatter")); - var utc = opts("labelsDateUTC"); - + var utc = opts("labelsUTC"); + var accessors = utc ? Dygraph.DateAccessorsUTC : Dygraph.DateAccessorsLocal; + var datefield = Dygraph.TICK_PLACEMENT[granularity].datefield; var step = Dygraph.TICK_PLACEMENT[granularity].step; var spacing = Dygraph.TICK_PLACEMENT[granularity].spacing; - - // Choose appropiate date methods according to UTC or local time option. - // weekday: return the day of week from a Date object. - // decompose_date: decompose a Date object into an array of datefields. - // compose_date: compose a Date object from an array of date fields. - var compose_date, decompose_date, weekday; - if (utc) { - weekday = function (d) { - return d.getUTCDay(); - }; - decompose_date = function (d) { - var a = []; - a[Dygraph.DATEFIELD_Y] = d.getUTCFullYear(); - a[Dygraph.DATEFIELD_M] = d.getUTCMonth(); - a[Dygraph.DATEFIELD_D] = d.getUTCDate(); - a[Dygraph.DATEFIELD_HH] = d.getUTCHours(); - a[Dygraph.DATEFIELD_MM] = d.getUTCMinutes(); - a[Dygraph.DATEFIELD_SS] = d.getUTCSeconds(); - a[Dygraph.DATEFIELD_MS] = d.getUTCMilliseconds(); - return a; - }; - compose_date = function (a) { - var d = new Date(Date.UTC(a[Dygraph.DATEFIELD_Y], - a[Dygraph.DATEFIELD_M], - a[Dygraph.DATEFIELD_D], - a[Dygraph.DATEFIELD_HH], - a[Dygraph.DATEFIELD_MM], - a[Dygraph.DATEFIELD_SS], - a[Dygraph.DATEFIELD_MS])); - return d; - }; - } else { - weekday = function(d) { - return d.getDay(); - }; - decompose_date = function (d) { - var a = []; - a[Dygraph.DATEFIELD_Y] = d.getFullYear(); - a[Dygraph.DATEFIELD_M] = d.getMonth(); - a[Dygraph.DATEFIELD_D] = d.getDate(); - a[Dygraph.DATEFIELD_HH] = d.getHours(); - a[Dygraph.DATEFIELD_MM] = d.getMinutes(); - a[Dygraph.DATEFIELD_SS] = d.getSeconds(); - a[Dygraph.DATEFIELD_MS] = d.getMilliseconds(); - return a; - }; - compose_date = function (a) { - var d = new Date(a[Dygraph.DATEFIELD_Y], - a[Dygraph.DATEFIELD_M], - a[Dygraph.DATEFIELD_D], - a[Dygraph.DATEFIELD_HH], - a[Dygraph.DATEFIELD_MM], - a[Dygraph.DATEFIELD_SS], - a[Dygraph.DATEFIELD_MS]); - return d; - }; - } - + // Choose a nice tick position before the initial instant. // Currently, this code deals properly with the existent daily granularities: // DAILY (with step of 1) and WEEKLY (with step of 7 but specially handled). // Other daily granularities (say TWO_DAILY) should also be handled specially // by setting the start_date_offset to 0. var start_date = new Date(start_time); - var date_array = decompose_date(start_date); + var date_array = []; + date_array[Dygraph.DATEFIELD_Y] = accessors.getFullYear(start_date); + date_array[Dygraph.DATEFIELD_M] = accessors.getMonth(start_date); + date_array[Dygraph.DATEFIELD_D] = accessors.getDate(start_date); + date_array[Dygraph.DATEFIELD_HH] = accessors.getHours(start_date); + date_array[Dygraph.DATEFIELD_MM] = accessors.getMinutes(start_date); + date_array[Dygraph.DATEFIELD_SS] = accessors.getSeconds(start_date); + date_array[Dygraph.DATEFIELD_MS] = accessors.getMilliseconds(start_date); + var start_date_offset = date_array[datefield] % step; if (granularity == Dygraph.WEEKLY) { // This will put the ticks on Sundays. - start_date_offset = weekday(start_date); + start_date_offset = accessors.getDay(start_date); } + date_array[datefield] -= start_date_offset; for (var df = datefield + 1; df < Dygraph.NUM_DATEFIELDS; df++) { // The minimum value is 1 for the day of month, and 0 for all other fields. @@ -434,56 +402,39 @@ Dygraph.getDateAxis = function(start_time, end_time, granularity, opts, dg) { // there are dates that do not represent any time value at all // (those in the hour skipped at the 'spring forward'), // and the JavaScript engines usually return an equivalent value. - // Hence we have to check that the date is effectively increased at each step, - // and that a tick should be place at the returned date. - // Since start_date is no later than start_time (but possibly equal), - // assuming a previous tick just before start_time removes an spurious - // tick outside the given time range. + // Hence we have to check that the date is properly increased at each step, + // returning a date at a nice tick position. var ticks = []; - var next_tick_date = compose_date(date_array); - var next_tick_time = next_tick_date.getTime(); - var prev_tick_time = start_time - 1; + var tick_date = accessors.makeDate.apply(null, date_array); + var tick_time = tick_date.getTime(); if (granularity <= Dygraph.HOURLY) { - while (next_tick_time <= end_time) { - if (next_tick_time > prev_tick_time) { - ticks.push({ v: next_tick_time, - label: formatter(next_tick_date, granularity, opts, dg) - }); - prev_tick_time = next_tick_time; - } - next_tick_time += spacing; - next_tick_date = new Date(next_tick_time); + if (tick_time < start_time) { + tick_time += spacing; + tick_date = new Date(tick_time); } - } else if (granularity < Dygraph.DAILY) { - var get_hours; - if (utc) { - get_hours = function (d) { return d.getUTCHours(); }; - } else { - get_hours = function (d) { return d.getHours(); }; + while (tick_time <= end_time) { + ticks.push({ v: tick_time, + label: formatter(tick_date, granularity, opts, dg) + }); + tick_time += spacing; + tick_date = new Date(tick_time); } - while (next_tick_time <= end_time) { - if (next_tick_time > prev_tick_time && - get_hours(next_tick_date) % step == 0) { - ticks.push({ v: next_tick_time, - label: formatter(next_tick_date, granularity, opts, dg) - }); - prev_tick_time = next_tick_time; - } + } else { + if (tick_time < start_time) { date_array[datefield] += step; - next_tick_date = compose_date(date_array); - next_tick_time = next_tick_date.getTime(); + tick_date = accessors.makeDate.apply(null, date_array); + tick_time = tick_date.getTime(); } - } else { - while (next_tick_time <= end_time) { - if (next_tick_time > prev_tick_time) { - ticks.push({ v: next_tick_time, - label: formatter(next_tick_date, granularity, opts, dg) + while (tick_time <= end_time) { + if (granularity >= Dygraph.DAILY || + accessors.getHours(tick_date) % step === 0) { + ticks.push({ v: tick_time, + label: formatter(tick_date, granularity, opts, dg) }); - prev_tick_time = next_tick_time; } date_array[datefield] += step; - next_tick_date = compose_date(date_array); - next_tick_time = next_tick_date.getTime(); + tick_date = accessors.makeDate.apply(null, date_array); + tick_time = tick_date.getTime(); } } return ticks; @@ -501,3 +452,5 @@ if (Dygraph && Dygraph.DEFAULT_ATTRS['axes']['y']['ticker'] = Dygraph.numericTicks; Dygraph.DEFAULT_ATTRS['axes']['y2']['ticker'] = Dygraph.numericTicks; } + +})();