use key instead of keyCode in follow

jh-changes
Shin'ya Ueoka 7 years ago
parent ea455059bd
commit 944683a2d8
  1. 64
      src/components/follow.js
  2. 4
      src/reducers/follow.js
  3. 10
      test/components/follow.test.js
  4. 20
      test/reducers/follow.test.js

@ -5,21 +5,6 @@ import HintKeyProducer from 'content/hint-key-producer';
const DEFAULT_HINT_CHARSET = 'abcdefghijklmnopqrstuvwxyz';
const availableKey = (keyCode) => {
return (
KeyboardEvent.DOM_VK_0 <= keyCode && keyCode <= KeyboardEvent.DOM_VK_9 ||
KeyboardEvent.DOM_VK_A <= keyCode && keyCode <= KeyboardEvent.DOM_VK_Z
);
};
const isNumericKey = (code) => {
return KeyboardEvent.DOM_VK_0 <= code && code <= KeyboardEvent.DOM_VK_9;
};
const isAlphabeticKey = (code) => {
return KeyboardEvent.DOM_VK_A <= code && code <= KeyboardEvent.DOM_VK_Z;
};
const inWindow = (window, element) => {
let {
top, left, bottom, right
@ -49,8 +34,7 @@ export default class FollowComponent {
this.create();
} else if (prevState.enabled && !this.state.enabled) {
this.remove();
} else if (JSON.stringify(prevState.keys) !==
JSON.stringify(this.state.keys)) {
} else if (prevState.keys !== this.state.keys) {
this.updateHints();
}
}
@ -60,23 +44,21 @@ export default class FollowComponent {
return;
}
let { keyCode } = e;
switch (keyCode) {
case KeyboardEvent.DOM_VK_ENTER:
case KeyboardEvent.DOM_VK_RETURN:
this.activate(this.hintElements[
FollowComponent.codeChars(this.state.keys)].target);
let { key } = e;
switch (key) {
case 'Enter':
this.activate(this.hintElements[this.state.keys].target);
return;
case KeyboardEvent.DOM_VK_ESCAPE:
case 'Escape':
this.store.dispatch(followActions.disable());
return;
case KeyboardEvent.DOM_VK_BACK_SPACE:
case KeyboardEvent.DOM_VK_DELETE:
case 'Backspace':
case 'Delete':
this.store.dispatch(followActions.backspace());
break;
default:
if (availableKey(keyCode)) {
this.store.dispatch(followActions.keyPress(keyCode));
if (DEFAULT_HINT_CHARSET.includes(key)) {
this.store.dispatch(followActions.keyPress(key));
}
break;
}
@ -86,18 +68,18 @@ export default class FollowComponent {
}
updateHints() {
let chars = FollowComponent.codeChars(this.state.keys);
let keys = this.state.keys;
let shown = Object.keys(this.hintElements).filter((key) => {
return key.startsWith(chars);
return key.startsWith(keys);
});
let hidden = Object.keys(this.hintElements).filter((key) => {
return !key.startsWith(chars);
return !key.startsWith(keys);
});
if (shown.length === 0) {
this.remove();
return;
} else if (shown.length === 1) {
this.activate(this.hintElements[chars].target);
this.activate(this.hintElements[keys].target);
this.remove();
}
@ -177,24 +159,6 @@ export default class FollowComponent {
});
}
static codeChars(codes) {
const CHARCODE_ZERO = '0'.charCodeAt(0);
const CHARCODE_A = 'a'.charCodeAt(0);
let chars = '';
for (let code of codes) {
if (isNumericKey(code)) {
chars += String.fromCharCode(
code - KeyboardEvent.DOM_VK_0 + CHARCODE_ZERO);
} else if (isAlphabeticKey(code)) {
chars += String.fromCharCode(
code - KeyboardEvent.DOM_VK_A + CHARCODE_A);
}
}
return chars;
}
static getTargetElements(doc) {
let all = doc.querySelectorAll('a,button,input,textarea');
let filtered = Array.prototype.filter.call(all, (element) => {

@ -3,7 +3,7 @@ import actions from 'actions';
const defaultState = {
enabled: false,
newTab: false,
keys: [],
keys: '',
};
export default function reducer(state = defaultState, action = {}) {
@ -19,7 +19,7 @@ export default function reducer(state = defaultState, action = {}) {
});
case actions.FOLLOW_KEY_PRESS:
return Object.assign({}, state, {
keys: state.keys.concat([action.key]),
keys: state.keys + action.key,
});
case actions.FOLLOW_BACKSPACE:
return Object.assign({}, state, {

@ -2,16 +2,6 @@ import { expect } from "chai";
import FollowComponent from 'components/follow';
describe('FollowComponent', () => {
describe('#codeChars', () => {
it('returns a string for key codes', () => {
let chars = [
KeyboardEvent.DOM_VK_0, KeyboardEvent.DOM_VK_1,
KeyboardEvent.DOM_VK_A, KeyboardEvent.DOM_VK_B];
expect(FollowComponent.codeChars(chars)).to.equal('01ab');
expect(FollowComponent.codeChars([])).to.be.equal('');
});
});
describe('#getTargetElements', () => {
beforeEach(() => {
document.body.innerHTML = __html__['test/components/follow.html'];

@ -7,7 +7,7 @@ describe('follow reducer', () => {
let state = followReducer(undefined, {});
expect(state).to.have.property('enabled', false);
expect(state).to.have.property('newTab');
expect(state).to.have.deep.property('keys', []);
expect(state).to.have.deep.property('keys', '');
});
it ('returns next state for FOLLOW_ENABLE', () => {
@ -24,24 +24,24 @@ describe('follow reducer', () => {
});
it ('returns next state for FOLLOW_KEY_PRESS', () => {
let action = { type: actions.FOLLOW_KEY_PRESS, key: 100};
let state = followReducer({ keys: [] }, action);
expect(state).to.have.deep.property('keys', [100]);
let action = { type: actions.FOLLOW_KEY_PRESS, key: 'a'};
let state = followReducer({ keys: '' }, action);
expect(state).to.have.deep.property('keys', 'a');
action = { type: actions.FOLLOW_KEY_PRESS, key: 200};
action = { type: actions.FOLLOW_KEY_PRESS, key: 'b'};
state = followReducer(state, action);
expect(state).to.have.deep.property('keys', [100, 200]);
expect(state).to.have.deep.property('keys', 'ab');
});
it ('returns next state for FOLLOW_BACKSPACE', () => {
let action = { type: actions.FOLLOW_BACKSPACE };
let state = followReducer({ keys: [100, 200] }, action);
expect(state).to.have.deep.property('keys', [100]);
let state = followReducer({ keys: 'ab' }, action);
expect(state).to.have.deep.property('keys', 'a');
state = followReducer(state, action);
expect(state).to.have.deep.property('keys', []);
expect(state).to.have.deep.property('keys', '');
state = followReducer(state, action);
expect(state).to.have.deep.property('keys', []);
expect(state).to.have.deep.property('keys', '');
});
});