aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/components/TimeLine.vue11
-rw-r--r--src/lib.ts30
-rw-r--r--tests/lib.test.ts18
3 files changed, 50 insertions, 9 deletions
diff --git a/src/components/TimeLine.vue b/src/components/TimeLine.vue
index 373439a..18ae107 100644
--- a/src/components/TimeLine.vue
+++ b/src/components/TimeLine.vue
@@ -88,7 +88,8 @@ import {moduloPositive, animateWithClass, getTextWidth} from '../util';
import {
getDaysInMonth, MIN_CAL_DATE, MONTH_NAMES, HistDate, HistEvent, getImagePath, dateToYearStr, dateToTickStr,
MIN_DATE, MAX_DATE, MONTH_SCALE, DAY_SCALE, SCALES,
- stepDate, getScaleRatio, getNumSubUnits, getUnitDiff, getEventPrecision, dateToUnit, dateToScaleDate,
+ stepDate, getScaleRatio, getNumSubUnits, getUnitDiff, getEventPrecision, getScaleForJump,
+ dateToUnit, dateToScaleDate,
TimelineState,
} from '../lib';
import {useStore} from '../store';
@@ -1332,12 +1333,8 @@ watch(() => props.searchTarget, () => {
if (!idToPos.value.has(event.id)){ // If not already visible
// Determine new time range
- let tempScale = scale.value;
- let targetDate = event.start;
- if (targetDate.isEarlier(MIN_CAL_DATE) && tempScale < 1){ // Account for jumping out of calendar limits
- tempScale = getEventPrecision(event);
- }
- targetDate = dateToScaleDate(targetDate, tempScale);
+ let tempScale = getScaleForJump(event);
+ let targetDate = dateToScaleDate(event.start, tempScale);
const startEndDiff = getUnitDiff(startDate.value, endDate.value, scale.value);
let targetStart = stepDate(targetDate, tempScale, {forward: false, count: Math.floor(startEndDiff / 2)});
if (targetStart.isEarlier(MIN_DATE)){
diff --git a/src/lib.ts b/src/lib.ts
index 051a449..1067119 100644
--- a/src/lib.ts
+++ b/src/lib.ts
@@ -628,7 +628,7 @@ export function getUnitDiff(date: HistDate, date2: HistDate, scale: number): num
}
}
-// Returns smallest scale at which 'event's start-startUpper range is within one unit, or infinity
+// Returns smallest scale at which 'event's start-startUpper range is within one unit, or infinity if there is none
export function getEventPrecision(event: HistEvent): number {
// Note: Intentionally not adding an exception for century and millenia ranges like
// 101 to 200 (as opposed to 100 to 199) being interpreted as 'within' one 100/1000-year scale unit
@@ -649,6 +649,34 @@ export function getEventPrecision(event: HistEvent): number {
return Number.POSITIVE_INFINITY;
}
+// Returns an 'appropriate' scale to use when jumping to a target date
+export function getScaleForJump(event: HistEvent): number {
+ const start = event.start;
+ const startUpper = event.startUpper;
+ if (start.gcal != null){
+ if (start.day > 1){
+ return MONTH_SCALE; // Intentionally not using DAY_SCALE
+ } else if (start.month > 1
+ || startUpper != null // Account for month-precision events
+ && gregorianToJdn(start.year, start.month+1, 0)
+ == gregorianToJdn(startUpper.year, startUpper.month, startUpper.day)){
+ return MONTH_SCALE;
+ }
+ }
+ for (let scaleIdx = 0; scaleIdx < SCALES.length - 2; scaleIdx++){
+ const scale = SCALES[scaleIdx];
+ if ((scale == 100 || scale == 1e3) // Account for century/millenium-precision events
+ && moduloPositive(start.year - 1, scale) == 0 && startUpper != null
+ && startUpper.year == start.year + scale - 1 || start.year + scale - 1 == 0){ // Account for no 0 BC
+ return scale;
+ }
+ if (moduloPositive(start.year, scale) == 0){
+ return scale;
+ }
+ }
+ throw new Error('Invalid state');
+}
+
export function dateToUnit(date: HistDate, scale: number): number {
// For a YearDate and sub-yearly scale, uses the first day of the YearDate's year
if (scale >= 1){
diff --git a/tests/lib.test.ts b/tests/lib.test.ts
index 4810c55..5f602d3 100644
--- a/tests/lib.test.ts
+++ b/tests/lib.test.ts
@@ -6,7 +6,7 @@ import {
dateToDisplayStr, boundedDateToStr,
queryServer, jsonToHistDate, jsonToHistEvent,
DAY_SCALE, MONTH_SCALE, stepDate, inDateScale, getScaleRatio, getUnitDiff,
- getEventPrecision, dateToUnit, dateToScaleDate,
+ getEventPrecision, getScaleForJump, dateToUnit, dateToScaleDate,
DateRangeTree,
} from '/src/lib.ts';
@@ -233,6 +233,22 @@ test('getEventPrecision', () => {
expect(getEventPrecision(new HistEvent(1, 'one', new CalDate(1, 2, 3), new CalDate(1, 2, 3)))).toBe(DAY_SCALE)
})
+test('getScaleForJump', () => {
+ expect(getScaleForJump(new HistEvent(1, '1', new CalDate(1970, 2, 3), null))).toBe(DAY_SCALE)
+ expect(getScaleForJump(new HistEvent(1, '1', new CalDate(1970, 2, 1), null))).toBe(MONTH_SCALE)
+ expect(getScaleForJump(new HistEvent(1, '1', new CalDate(100, 1, 1), new CalDate(100, 1, 31)))).toBe(MONTH_SCALE)
+ expect(getScaleForJump(new HistEvent(1, '1', new CalDate(12, 1, 1), null))).toBe(1)
+ expect(getScaleForJump(new HistEvent(1, '1', new YearDate(-20), null))).toBe(10)
+ expect(getScaleForJump(new HistEvent(1, '1', new YearDate(-100), null))).toBe(100)
+ expect(getScaleForJump(new HistEvent(1, '1', new YearDate(-99), new CalDate(-1, 1, 1)))).toBe(100)
+ expect(getScaleForJump(new HistEvent(1, '1', new YearDate(1501), new CalDate(1600, 1, 1)))).toBe(100)
+ expect(getScaleForJump(new HistEvent(1, '1', new YearDate(1500), new CalDate(1599, 1, 1)))).toBe(100)
+ expect(getScaleForJump(new HistEvent(1, '1', new YearDate(1001), null))).toBe(1)
+ expect(getScaleForJump(new HistEvent(1, '1', new YearDate(1001), new YearDate(2000)))).toBe(1000)
+ expect(getScaleForJump(new HistEvent(1, '1', new CalDate(1e5, 1, 1), null))).toBe(1e5)
+ expect(getScaleForJump(new HistEvent(1, '1', new CalDate(1e5+1, 1, 1), null))).toBe(1)
+})
+
test('dateToUnit', () => {
expect(dateToUnit(new CalDate(2013), 1e3)).toBe(2)
expect(dateToUnit(new CalDate(2013), 100)).toBe(20)