From 7723f551c80ae18b240a8f258fe6cce0571978a8 Mon Sep 17 00:00:00 2001 From: Varun Patil Date: Sat, 15 Oct 2022 11:00:24 -0700 Subject: [PATCH] scroller: use binary search for moveHoverCursor --- src/components/ScrollerManager.vue | 12 +++++----- src/mixins/GlobalMixin.ts | 1 + src/services/Utils.ts | 35 +++++++++++++++++++++++++++++- 3 files changed, 40 insertions(+), 8 deletions(-) diff --git a/src/components/ScrollerManager.vue b/src/components/ScrollerManager.vue index c4cf9385..a1cf194a 100644 --- a/src/components/ScrollerManager.vue +++ b/src/components/ScrollerManager.vue @@ -206,7 +206,7 @@ export default class ScrollerManager extends Mixins(GlobalMixin) { // Itearte over rows for (const row of this.rows) { if (row.type === IRowType.HEAD) { - if (Object.values(this.TagDayID).includes(row.dayId)) { + if (this.TagDayIDValueSet.has(row.dayId)) { // Blank tick this.ticks.push(getTick(row.dayId)); } else { @@ -234,22 +234,20 @@ export default class ScrollerManager extends Mixins(GlobalMixin) { this.hoverCursorY = y; // Get index of previous tick - let idx = this.ticks.findIndex(t => t.top >= y); + let idx = utils.binarySearch(this.ticks, y, 'top'); if (idx === 0) { // use this tick - } else if (idx >= 1) { + } else if (idx >= 1 && idx <= this.ticks.length) { idx = idx - 1; - } else if (idx === -1 && this.ticks.length > 0) { - idx = this.ticks.length - 1; } else { return; } // DayId of current hover - const dayId = this.ticks[idx].dayId + const dayId = this.ticks[idx]?.dayId // Special days - if (Object.values(this.TagDayID).includes(dayId)) { + if (dayId === undefined || this.TagDayIDValueSet.has(dayId)) { this.hoverCursorText = ""; return; } diff --git a/src/mixins/GlobalMixin.ts b/src/mixins/GlobalMixin.ts index 492108a4..4ce25188 100644 --- a/src/mixins/GlobalMixin.ts +++ b/src/mixins/GlobalMixin.ts @@ -9,4 +9,5 @@ export default class GlobalMixin extends Vue { public readonly c = constants.c; public readonly TagDayID = constants.TagDayID; + public readonly TagDayIDValueSet = new Set(Object.values(this.TagDayID)); } \ No newline at end of file diff --git a/src/services/Utils.ts b/src/services/Utils.ts index c27d8833..adb3702e 100644 --- a/src/services/Utils.ts +++ b/src/services/Utils.ts @@ -33,7 +33,7 @@ export function getLongDateStr(date: Date, skipYear=false, time=false) { * @return {Number} A 32bit integer * @see http://werxltd.com/wp/2010/05/13/javascript-implementation-of-javas-string-hashcode-method/ */ - export function hashCode(str: string): number { +export function hashCode(str: string): number { let hash = 0; for (let i = 0, len = str.length; i < len; i++) { let chr = str.charCodeAt(i); @@ -43,6 +43,39 @@ export function getLongDateStr(date: Date, skipYear=false, time=false) { return hash; } +/** + * Search for elem in a sorted array of objects + * If the object is not found, return the index where it should be inserted + * + * @param arr Array of objects to search + * @param elem Element to search for + * @param key Key to use for comparison + */ +export function binarySearch(arr: any, elem: any, key?: string) { + let minIndex = 0; + let maxIndex = arr.length - 1; + let currentIndex: number; + let currentElement: any; + + while (minIndex <= maxIndex) { + currentIndex = (minIndex + maxIndex) / 2 | 0; + currentElement = key ? arr[currentIndex][key] : arr[currentIndex]; + + if (currentElement < elem) { + minIndex = currentIndex + 1; + } + else if (currentElement > elem) { + maxIndex = currentIndex - 1; + } + else { + return currentIndex; + } + } + + return minIndex; +} + +/** Global constants */ export const constants = { c: { FLAG_PLACEHOLDER: 1 << 0,