aboutsummaryrefslogtreecommitdiff
path: root/src/content/presenters/FollowPresenter.ts
diff options
context:
space:
mode:
Diffstat (limited to 'src/content/presenters/FollowPresenter.ts')
-rw-r--r--src/content/presenters/FollowPresenter.ts83
1 files changed, 49 insertions, 34 deletions
diff --git a/src/content/presenters/FollowPresenter.ts b/src/content/presenters/FollowPresenter.ts
index fef8140..8aef819 100644
--- a/src/content/presenters/FollowPresenter.ts
+++ b/src/content/presenters/FollowPresenter.ts
@@ -1,11 +1,18 @@
-import Hint, { InputHint, LinkHint } from './Hint';
-import * as doms from '../../shared/utils/dom';
+import Hint, { InputHint, LinkHint } from "./Hint";
+import * as doms from "../../shared/utils/dom";
const TARGET_SELECTOR = [
- 'a', 'button', 'input', 'textarea', 'area',
- '[contenteditable=true]', '[contenteditable=""]', '[tabindex]',
- '[role="button"]', 'summary'
-].join(',');
+ "a",
+ "button",
+ "input",
+ "textarea",
+ "area",
+ "[contenteditable=true]",
+ '[contenteditable=""]',
+ "[tabindex]",
+ '[role="button"]',
+ "summary",
+].join(",");
interface Size {
width: number;
@@ -21,11 +28,9 @@ const inViewport = (
win: Window,
element: Element,
viewSize: Size,
- framePosition: Point,
+ framePosition: Point
): boolean => {
- const {
- top, left, bottom, right
- } = doms.viewportRect(element);
+ const { top, left, bottom, right } = doms.viewportRect(element);
const doc = win.document;
const frameWidth = doc.documentElement.clientWidth;
const frameHeight = doc.documentElement.clientHeight;
@@ -34,9 +39,12 @@ const inViewport = (
// out of frame
return false;
}
- if (right + framePosition.x < 0 || bottom + framePosition.y < 0 ||
- left + framePosition.x > viewSize.width ||
- top + framePosition.y > viewSize.height) {
+ if (
+ right + framePosition.x < 0 ||
+ bottom + framePosition.y < 0 ||
+ left + framePosition.x > viewSize.width ||
+ top + framePosition.y > viewSize.height
+ ) {
// out of viewport
return false;
}
@@ -47,11 +55,11 @@ const isAriaHiddenOrAriaDisabled = (win: Window, element: Element): boolean => {
if (!element || win.document.documentElement === element) {
return false;
}
- for (const attr of ['aria-hidden', 'aria-disabled']) {
+ for (const attr of ["aria-hidden", "aria-disabled"]) {
const value = element.getAttribute(attr);
if (value !== null) {
const hidden = value.toLowerCase();
- if (hidden === '' || hidden === 'true') {
+ if (hidden === "" || hidden === "true") {
return true;
}
}
@@ -88,8 +96,10 @@ export class FollowPresenterImpl implements FollowPresenter {
const min = Math.min(targets.length, tags.length);
for (let i = 0; i < min; ++i) {
const target = targets[i];
- if (target instanceof HTMLAnchorElement ||
- target instanceof HTMLAreaElement) {
+ if (
+ target instanceof HTMLAnchorElement ||
+ target instanceof HTMLAreaElement
+ ) {
this.hints.push(new LinkHint(target, tags[i]));
} else {
this.hints.push(new InputHint(target, tags[i]));
@@ -98,35 +108,40 @@ export class FollowPresenterImpl implements FollowPresenter {
}
filterHints(prefix: string): void {
- const shown = this.hints.filter(h => h.getTag().startsWith(prefix));
- const hidden = this.hints.filter(h => !h.getTag().startsWith(prefix));
+ const shown = this.hints.filter((h) => h.getTag().startsWith(prefix));
+ const hidden = this.hints.filter((h) => !h.getTag().startsWith(prefix));
- shown.forEach(h => h.show());
- hidden.forEach(h => h.hide());
+ shown.forEach((h) => h.show());
+ hidden.forEach((h) => h.hide());
}
clearHints(): void {
- this.hints.forEach(h => h.remove());
+ this.hints.forEach((h) => h.remove());
this.hints = [];
}
getHint(tag: string): Hint | undefined {
- return this.hints.find(h => h.getTag() === tag);
+ return this.hints.find((h) => h.getTag() === tag);
}
private getTargets(viewSize: Size, framePosition: Point): HTMLElement[] {
const all = window.document.querySelectorAll(TARGET_SELECTOR);
- const filtered = Array.prototype.filter.call(all, (element: HTMLElement) => {
- const style = window.getComputedStyle(element);
-
- // AREA's 'display' in Browser style is 'none'
- return (element.tagName === 'AREA' || style.display !== 'none') &&
- style.visibility !== 'hidden' &&
- (element as HTMLInputElement).type !== 'hidden' &&
- element.offsetHeight > 0 &&
- !isAriaHiddenOrAriaDisabled(window, element) &&
- inViewport(window, element, viewSize, framePosition);
- });
+ const filtered = Array.prototype.filter.call(
+ all,
+ (element: HTMLElement) => {
+ const style = window.getComputedStyle(element);
+
+ // AREA's 'display' in Browser style is 'none'
+ return (
+ (element.tagName === "AREA" || style.display !== "none") &&
+ style.visibility !== "hidden" &&
+ (element as HTMLInputElement).type !== "hidden" &&
+ element.offsetHeight > 0 &&
+ !isAriaHiddenOrAriaDisabled(window, element) &&
+ inViewport(window, element, viewSize, framePosition)
+ );
+ }
+ );
return filtered;
}
}