Choices/src/scripts/components/list.ts
Josh Johnson 68313da412
Convert to typescript (#795)
* Typescript config setup

* Add type annotations to components

* Further type additions

* And more...

* Add types to actions

* Add types to templates

* Further type checks

* Further type additons

* Install fuse latest

* Housekeeping

* Remove old type definitions

* Fix remaning type issues

* Fix some failing tests

* Remove types workflow

* Fix failing unit tests

* Resolve back space event regression

* Convert cypress files to .ts

* Fix eslint issues

* Remove cachebusting urls

* Resolve delete button bug

* Resolve regression bugs

* Fix lint script

* Fix lint workflow

* Pass args instead of object to keyboard handlers

* Flatten misc reducer

* Resolve keyboad action test failures

* Use Pick instead of Partial

* Use interfaces in action tests

* Update firefox image

* Incorporate #791

* Incorporate #788
2019-12-23 18:22:54 +00:00

98 lines
2.5 KiB
TypeScript

import { SCROLLING_SPEED } from '../constants';
export default class List {
element: HTMLElement;
scrollPos: number;
height: number;
constructor({ element }: { element: HTMLElement }) {
this.element = element;
this.scrollPos = this.element.scrollTop;
this.height = this.element.offsetHeight;
}
clear(): void {
this.element.innerHTML = '';
}
append(node: Element | DocumentFragment): void {
this.element.appendChild(node);
}
getChild(selector: string): HTMLElement | null {
return this.element.querySelector(selector);
}
hasChildren(): boolean {
return this.element.hasChildNodes();
}
scrollToTop(): void {
this.element.scrollTop = 0;
}
scrollToChildElement(element: HTMLElement, direction: 1 | -1): void {
if (!element) {
return;
}
const listHeight = this.element.offsetHeight;
// Scroll position of dropdown
const listScrollPosition = this.element.scrollTop + listHeight;
const elementHeight = element.offsetHeight;
// Distance from bottom of element to top of parent
const elementPos = element.offsetTop + elementHeight;
// Difference between the element and scroll position
const destination =
direction > 0
? this.element.scrollTop + elementPos - listScrollPosition
: element.offsetTop;
requestAnimationFrame(() => {
this._animateScroll(destination, direction);
});
}
_scrollDown(scrollPos: number, strength: number, destination: number): void {
const easing = (destination - scrollPos) / strength;
const distance = easing > 1 ? easing : 1;
this.element.scrollTop = scrollPos + distance;
}
_scrollUp(scrollPos: number, strength: number, destination: number): void {
const easing = (scrollPos - destination) / strength;
const distance = easing > 1 ? easing : 1;
this.element.scrollTop = scrollPos - distance;
}
_animateScroll(destination: number, direction: number): void {
const strength = SCROLLING_SPEED;
const choiceListScrollTop = this.element.scrollTop;
let continueAnimation = false;
if (direction > 0) {
this._scrollDown(choiceListScrollTop, strength, destination);
if (choiceListScrollTop < destination) {
continueAnimation = true;
}
} else {
this._scrollUp(choiceListScrollTop, strength, destination);
if (choiceListScrollTop > destination) {
continueAnimation = true;
}
}
if (continueAnimation) {
requestAnimationFrame(() => {
this._animateScroll(destination, direction);
});
}
}
}