diff options
author | Shin'ya Ueoka <ueokande@i-beam.org> | 2017-10-08 15:04:55 +0900 |
---|---|---|
committer | Shin'ya Ueoka <ueokande@i-beam.org> | 2017-10-08 15:04:55 +0900 |
commit | 39fb5400370b818760dc7bcfe42e74b2512a840d (patch) | |
tree | 5191fc93c4cf1489c9ddd9d0003e30137a967018 /src/components | |
parent | d886d7de290b6fee00c55c5487416048f3de4bf2 (diff) |
separate content
Diffstat (limited to 'src/components')
-rw-r--r-- | src/components/content-input.js | 67 | ||||
-rw-r--r-- | src/components/follow.js | 168 | ||||
-rw-r--r-- | src/components/keymapper.js | 43 |
3 files changed, 0 insertions, 278 deletions
diff --git a/src/components/content-input.js b/src/components/content-input.js deleted file mode 100644 index 9568caf..0000000 --- a/src/components/content-input.js +++ /dev/null @@ -1,67 +0,0 @@ -export default class ContentInputComponent { - constructor(target) { - this.pressed = {}; - this.onKeyListeners = []; - - target.addEventListener('keypress', this.onKeyPress.bind(this)); - target.addEventListener('keydown', this.onKeyDown.bind(this)); - target.addEventListener('keyup', this.onKeyUp.bind(this)); - } - - update() { - } - - onKey(cb) { - this.onKeyListeners.push(cb); - } - - onKeyPress(e) { - if (this.pressed[e.key] && this.pressed[e.key] !== 'keypress') { - return; - } - this.pressed[e.key] = 'keypress'; - this.capture(e); - } - - onKeyDown(e) { - if (this.pressed[e.key] && this.pressed[e.key] !== 'keydown') { - return; - } - this.pressed[e.key] = 'keydown'; - this.capture(e); - } - - onKeyUp(e) { - delete this.pressed[e.key]; - } - - capture(e) { - if (this.fromInput(e)) { - if (e.key === 'Escape' && e.target.blur) { - e.target.blur(); - } - return; - } - if (e.key === 'OS') { - return; - } - - let stop = false; - for (let listener of this.onKeyListeners) { - stop = stop || listener(e.key, e.ctrlKey); - if (stop) { - break; - } - } - if (stop) { - e.preventDefault(); - e.stopPropagation(); - } - } - - fromInput(e) { - return e.target instanceof HTMLInputElement || - e.target instanceof HTMLTextAreaElement || - e.target instanceof HTMLSelectElement; - } -} diff --git a/src/components/follow.js b/src/components/follow.js deleted file mode 100644 index 0ec1e87..0000000 --- a/src/components/follow.js +++ /dev/null @@ -1,168 +0,0 @@ -import * as followActions from 'actions/follow'; -import messages from 'shared/messages'; -import Hint from 'content/hint'; -import HintKeyProducer from 'content/hint-key-producer'; - -const DEFAULT_HINT_CHARSET = 'abcdefghijklmnopqrstuvwxyz'; - -const inWindow = (window, element) => { - let { - top, left, bottom, right - } = element.getBoundingClientRect(); - return ( - top >= 0 && left >= 0 && - bottom <= (window.innerHeight || document.documentElement.clientHeight) && - right <= (window.innerWidth || document.documentElement.clientWidth) - ); -}; - -export default class FollowComponent { - constructor(wrapper, store) { - this.wrapper = wrapper; - this.store = store; - this.hintElements = {}; - this.state = {}; - } - - update() { - let prevState = this.state; - this.state = this.store.getState().follow; - if (!prevState.enabled && this.state.enabled) { - this.create(); - } else if (prevState.enabled && !this.state.enabled) { - this.remove(); - } else if (prevState.keys !== this.state.keys) { - this.updateHints(); - } - } - - key(key) { - if (!this.state.enabled) { - return false; - } - - switch (key) { - case 'Enter': - this.activate(this.hintElements[this.state.keys].target); - return; - case 'Escape': - this.store.dispatch(followActions.disable()); - return; - case 'Backspace': - case 'Delete': - this.store.dispatch(followActions.backspace()); - break; - default: - if (DEFAULT_HINT_CHARSET.includes(key)) { - this.store.dispatch(followActions.keyPress(key)); - } - break; - } - return true; - } - - updateHints() { - let keys = this.state.keys; - let shown = Object.keys(this.hintElements).filter((key) => { - return key.startsWith(keys); - }); - let hidden = Object.keys(this.hintElements).filter((key) => { - return !key.startsWith(keys); - }); - if (shown.length === 0) { - this.remove(); - return; - } else if (shown.length === 1) { - this.activate(this.hintElements[keys].target); - this.store.dispatch(followActions.disable()); - } - - shown.forEach((key) => { - this.hintElements[key].show(); - }); - hidden.forEach((key) => { - this.hintElements[key].hide(); - }); - } - - activate(element) { - switch (element.tagName.toLowerCase()) { - case 'a': - if (this.state.newTab) { - // getAttribute() to avoid to resolve absolute path - let href = element.getAttribute('href'); - - // eslint-disable-next-line no-script-url - if (!href || href === '#' || href.startsWith('javascript:')) { - return; - } - return browser.runtime.sendMessage({ - type: messages.OPEN_URL, - url: element.href, - newTab: this.state.newTab, - }); - } - if (element.href.startsWith('http://') || - element.href.startsWith('https://') || - element.href.startsWith('ftp://')) { - return browser.runtime.sendMessage({ - type: messages.OPEN_URL, - url: element.href, - newTab: this.state.newTab, - }); - } - return element.click(); - case 'input': - switch (element.type) { - case 'file': - case 'checkbox': - case 'radio': - case 'submit': - case 'reset': - case 'button': - case 'image': - case 'color': - return element.click(); - default: - return element.focus(); - } - case 'textarea': - return element.focus(); - case 'button': - return element.click(); - } - } - - create() { - let doc = this.wrapper.ownerDocument; - let elements = FollowComponent.getTargetElements(doc); - let producer = new HintKeyProducer(DEFAULT_HINT_CHARSET); - let hintElements = {}; - Array.prototype.forEach.call(elements, (ele) => { - let keys = producer.produce(); - let hint = new Hint(ele, keys); - hintElements[keys] = hint; - }); - this.hintElements = hintElements; - } - - remove() { - let hintElements = this.hintElements; - Object.keys(this.hintElements).forEach((key) => { - hintElements[key].remove(); - }); - } - - static getTargetElements(doc) { - let all = doc.querySelectorAll('a,button,input,textarea'); - let filtered = Array.prototype.filter.call(all, (element) => { - let style = window.getComputedStyle(element); - return style.display !== 'none' && - style.visibility !== 'hidden' && - element.type !== 'hidden' && - element.offsetHeight > 0 && - inWindow(window, element); - }); - return filtered; - } -} diff --git a/src/components/keymapper.js b/src/components/keymapper.js deleted file mode 100644 index 3685a4f..0000000 --- a/src/components/keymapper.js +++ /dev/null @@ -1,43 +0,0 @@ -import * as inputActions from 'actions/input'; -import * as operationActions from 'actions/operation'; - -export default class KeymapperComponent { - constructor(store) { - this.store = store; - } - - update() { - } - - key(key, ctrl) { - let keymaps = this.keymaps(); - if (!keymaps) { - return; - } - this.store.dispatch(inputActions.keyPress(key, ctrl)); - - let input = this.store.getState().input; - let matched = Object.keys(keymaps).filter((keyStr) => { - return keyStr.startsWith(input.keys); - }); - if (matched.length === 0) { - this.store.dispatch(inputActions.clearKeys()); - return false; - } else if (matched.length > 1 || - matched.length === 1 && input.keys !== matched[0]) { - return true; - } - let operation = keymaps[matched]; - this.store.dispatch(operationActions.exec(operation)); - this.store.dispatch(inputActions.clearKeys()); - return true; - } - - keymaps() { - let settings = this.store.getState().setting.settings; - if (!settings || !settings.json) { - return null; - } - return JSON.parse(settings.json).keymaps; - } -} |