aboutsummaryrefslogtreecommitdiff
path: root/src/content/components
diff options
context:
space:
mode:
authorShin'ya Ueoka <ueokande@i-beam.org>2019-05-16 21:35:58 +0900
committerShin'ya Ueoka <ueokande@i-beam.org>2019-05-17 23:06:27 +0900
commitfb8b4d28ce47171a83a7bf5148293fd2318cc02f (patch)
tree02e23efe01d38adeb6dafb6794bc1d3e4866a055 /src/content/components
parent8cef5981b808bc1713170627c88dc26ca81063c1 (diff)
Hints as a classes
Diffstat (limited to 'src/content/components')
-rw-r--r--src/content/components/common/follow.ts79
-rw-r--r--src/content/components/common/hint.ts62
2 files changed, 25 insertions, 116 deletions
diff --git a/src/content/components/common/follow.ts b/src/content/components/common/follow.ts
index 67f2dd9..a30a3d5 100644
--- a/src/content/components/common/follow.ts
+++ b/src/content/components/common/follow.ts
@@ -1,8 +1,11 @@
import MessageListener from '../../MessageListener';
-import Hint from './hint';
+import Hint, { LinkHint, InputHint } from '../../presenters/Hint';
import * as dom from '../../../shared/utils/dom';
import * as messages from '../../../shared/messages';
import * as keyUtils from '../../../shared/utils/keys';
+import TabsClient, { TabsClientImpl } from '../../client/TabsClient';
+
+let tabsClient: TabsClient = new TabsClientImpl();
const TARGET_SELECTOR = [
'a', 'button', 'input', 'textarea', 'area',
@@ -95,27 +98,6 @@ export default class Follow {
return true;
}
- openLink(element: HTMLAreaElement|HTMLAnchorElement) {
- // Browser prevent new tab by link with target='_blank'
- if (!this.newTab && element.getAttribute('target') !== '_blank') {
- element.click();
- return;
- }
-
- let href = element.getAttribute('href');
-
- // eslint-disable-next-line no-script-url
- if (!href || href === '#' || href.toLowerCase().startsWith('javascript:')) {
- return;
- }
- return browser.runtime.sendMessage({
- type: messages.OPEN_URL,
- url: element.href,
- newTab: true,
- background: this.background,
- });
- }
-
countHints(sender: any, viewSize: Size, framePosition: Point) {
this.targets = Follow.getTargetElements(this.win, viewSize, framePosition);
sender.postMessage(JSON.stringify({
@@ -134,8 +116,13 @@ export default class Follow {
this.hints = {};
for (let i = 0; i < keysArray.length; ++i) {
let keys = keysArray[i];
- let hint = new Hint(this.targets[i], keys);
- this.hints[keys] = hint;
+ let target = this.targets[i];
+ if (target instanceof HTMLAnchorElement ||
+ target instanceof HTMLAreaElement) {
+ this.hints[keys] = new LinkHint(target, keys);
+ } else {
+ this.hints[keys] = new InputHint(target, keys);
+ }
}
}
@@ -154,42 +141,26 @@ export default class Follow {
this.targets = [];
}
- activateHints(keys: string) {
+ async activateHints(keys: string): Promise<void> {
let hint = this.hints[keys];
if (!hint) {
return;
}
- let element = hint.getTarget();
- switch (element.tagName.toLowerCase()) {
- case 'a':
- return this.openLink(element as HTMLAnchorElement);
- case 'area':
- return this.openLink(element as HTMLAreaElement);
- case 'input':
- switch ((element as HTMLInputElement).type) {
- case 'file':
- case 'checkbox':
- case 'radio':
- case 'submit':
- case 'reset':
- case 'button':
- case 'image':
- case 'color':
- return element.click();
- default:
- return element.focus();
+
+ if (hint instanceof LinkHint) {
+ let url = hint.getLink();
+ // ignore taget='_blank'
+ if (!this.newTab && hint.getLinkTarget() !== '_blank') {
+ hint.click();
+ return;
}
- case 'textarea':
- return element.focus();
- case 'button':
- case 'summary':
- return element.click();
- default:
- if (dom.isContentEditable(element)) {
- return element.focus();
- } else if (element.hasAttribute('tabindex')) {
- return element.click();
+ // eslint-disable-next-line no-script-url
+ if (!url || url === '#' || url.toLowerCase().startsWith('javascript:')) {
+ return;
}
+ await tabsClient.openUrl(url, this.newTab, this.background);
+ } else if (hint instanceof InputHint) {
+ hint.activate();
}
}
diff --git a/src/content/components/common/hint.ts b/src/content/components/common/hint.ts
deleted file mode 100644
index 2fcbb0f..0000000
--- a/src/content/components/common/hint.ts
+++ /dev/null
@@ -1,62 +0,0 @@
-import * as dom from '../../../shared/utils/dom';
-
-interface Point {
- x: number;
- y: number;
-}
-
-const hintPosition = (element: Element): Point => {
- let { left, top, right, bottom } = dom.viewportRect(element);
-
- if (element.tagName !== 'AREA') {
- return { x: left, y: top };
- }
-
- return {
- x: (left + right) / 2,
- y: (top + bottom) / 2,
- };
-};
-
-export default class Hint {
- private target: HTMLElement;
-
- private element: HTMLElement;
-
- constructor(target: HTMLElement, tag: string) {
- let doc = target.ownerDocument;
- if (doc === null) {
- throw new TypeError('ownerDocument is null');
- }
-
- let { x, y } = hintPosition(target);
- let { scrollX, scrollY } = window;
-
- this.target = target;
-
- this.element = doc.createElement('span');
- this.element.className = 'vimvixen-hint';
- this.element.textContent = tag;
- this.element.style.left = x + scrollX + 'px';
- this.element.style.top = y + scrollY + 'px';
-
- this.show();
- doc.body.append(this.element);
- }
-
- show(): void {
- this.element.style.display = 'inline';
- }
-
- hide(): void {
- this.element.style.display = 'none';
- }
-
- remove(): void {
- this.element.remove();
- }
-
- getTarget(): HTMLElement {
- return this.target;
- }
-}