Skip to content

Commit a172458

Browse files
committed
fix(searchBox): handling pasting event with contextual menu.
fixes #467
1 parent e5a414a commit a172458

File tree

2 files changed

+93
-35
lines changed

2 files changed

+93
-35
lines changed

widgets/search-box/__tests__/search-box-test.js

Lines changed: 70 additions & 34 deletions
Original file line numberDiff line numberDiff line change
@@ -168,6 +168,55 @@ describe('search-box()', () => {
168168
});
169169
});
170170

171+
context('input event listenner', () => {
172+
let input;
173+
beforeEach(() => {
174+
container = document.createElement('div');
175+
input = createHTMLNodeFromString('<input />');
176+
input.addEventListener = sinon.spy();
177+
});
178+
179+
function simulateInputEvent() {
180+
// Given
181+
helper.state.query = 'foo';
182+
// When
183+
widget.init(initialState, helper);
184+
// Then
185+
expect(input.addEventListener.called).toEqual(true);
186+
expect(input.addEventListener.args[1].length).toEqual(3);
187+
expect(input.addEventListener.args[1][0]).toEqual('input');
188+
let fn = input.addEventListener.args[1][1];
189+
190+
return fn({currentTarget: {value: 'test'}});
191+
}
192+
193+
context('instant search', () => {
194+
beforeEach(() => {
195+
widget = searchBox({container, autofocus: 'auto'});
196+
widget.getInput = sinon.stub().returns(input);
197+
});
198+
199+
it('performs a search on any change', () => {
200+
simulateInputEvent();
201+
expect(helper.setQuery.calledOnce).toBe(true);
202+
expect(helper.search.called).toBe(true);
203+
});
204+
});
205+
206+
context('non-instant search', () => {
207+
beforeEach(() => {
208+
widget = searchBox({container, autofocus: 'auto', searchOnEnterKeyPressOnly: true});
209+
widget.getInput = sinon.stub().returns(input);
210+
});
211+
212+
it('does not performs (will be handle by keyup event)', () => {
213+
simulateInputEvent();
214+
expect(helper.setQuery.calledOnce).toBe(true);
215+
expect(helper.search.called).toBe(false);
216+
});
217+
});
218+
});
219+
171220
context('keyup', () => {
172221
let input;
173222
beforeEach(() => {
@@ -176,25 +225,30 @@ describe('search-box()', () => {
176225
input.addEventListener = sinon.spy();
177226
});
178227

228+
function simulateKeyUpEvent(args) {
229+
// Given
230+
helper.state.query = 'foo';
231+
// When
232+
widget.init(initialState, helper);
233+
// Then
234+
expect(input.addEventListener.called).toEqual(true);
235+
expect(input.addEventListener.args[0].length).toEqual(2);
236+
expect(input.addEventListener.args[0][0]).toEqual('keyup');
237+
let fn = input.addEventListener.args[0][1];
238+
239+
return fn(args);
240+
}
241+
179242
context('instant search', () => {
180243
beforeEach(() => {
181244
widget = searchBox({container, autofocus: 'auto'});
182245
widget.getInput = sinon.stub().returns(input);
183246
});
184247

185-
it('performs the search on keyup', () => {
186-
// Given
187-
helper.state.query = 'foo';
188-
// When
189-
widget.init(initialState, helper);
190-
// Then
191-
expect(input.addEventListener.called).toEqual(true);
192-
expect(input.addEventListener.args[0].length).toEqual(2);
193-
expect(input.addEventListener.args[0][0]).toEqual('keyup');
194-
let fn = input.addEventListener.args[0][1];
195-
fn({});
248+
it('do not perform the search on keyup event (should be done by input event)', () => {
249+
simulateKeyUpEvent({});
196250
expect(helper.setQuery.calledOnce).toBe(true);
197-
expect(helper.search.calledOnce).toBe(true);
251+
expect(helper.search.called).toBe(false);
198252
});
199253
});
200254

@@ -204,32 +258,14 @@ describe('search-box()', () => {
204258
widget.getInput = sinon.stub().returns(input);
205259
});
206260

207-
it('performs the search on <ENTER>', () => {
208-
// Given
209-
helper.state.query = 'foo';
210-
// When
211-
widget.init(initialState, helper);
212-
// Then
213-
expect(input.addEventListener.called).toEqual(true);
214-
expect(input.addEventListener.args[0].length).toEqual(2);
215-
expect(input.addEventListener.args[0][0]).toEqual('keyup');
216-
let fn = input.addEventListener.args[0][1];
217-
fn({keyCode: 13});
261+
it('performs the search on keyup if <ENTER>', () => {
262+
simulateKeyUpEvent({keyCode: 13});
218263
expect(helper.setQuery.calledOnce).toBe(true);
219264
expect(helper.search.calledOnce).toBe(true);
220265
});
221266

222-
it('doesn\'t perform the search on keyup', () => {
223-
// Given
224-
helper.state.query = 'foo';
225-
// When
226-
widget.init(initialState, helper);
227-
// Then
228-
expect(input.addEventListener.called).toEqual(true);
229-
expect(input.addEventListener.args[0].length).toEqual(2);
230-
expect(input.addEventListener.args[0][0]).toEqual('keyup');
231-
let fn = input.addEventListener.args[0][1];
232-
fn({});
267+
it('doesn\'t perform the search on keyup if not <ENTER>', () => {
268+
simulateKeyUpEvent({});
233269
expect(helper.setQuery.calledOnce).toBe(true);
234270
expect(helper.search.calledOnce).toBe(false);
235271
});

widgets/search-box/search-box.js

Lines changed: 23 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@ let bem = require('../../lib/utils').bemHelper('ais-search-box');
66
let cx = require('classnames');
77

88
const KEY_ENTER = 13;
9+
const KEY_SUPPRESS = 8;
910

1011
/**
1112
* Instantiate a searchbox
@@ -100,13 +101,34 @@ function searchBox({
100101

101102
// Add all the needed attributes and listeners to the input
102103
this.addDefaultAttributesToInput(input, initialState.query);
104+
105+
// Keep keyup to handle searchOnEnterKeyPressOnly
103106
input.addEventListener('keyup', (e) => {
104107
helper.setQuery(input.value);
105-
if (!searchOnEnterKeyPressOnly || e.keyCode === KEY_ENTER) {
108+
if (searchOnEnterKeyPressOnly && e.keyCode === KEY_ENTER) {
109+
helper.search();
110+
}
111+
112+
// IE8/9 compatibility
113+
if (window.attachEvent && e.keyCode === KEY_SUPPRESS) {
106114
helper.search();
107115
}
108116
});
109117

118+
function inputCallback(e) {
119+
let target = (e.currentTarget) ? e.currentTarget : e.srcElement;
120+
helper.setQuery(target.value);
121+
if (!searchOnEnterKeyPressOnly) {
122+
helper.search();
123+
}
124+
}
125+
126+
if (window.attachEvent) { // IE8/9 compatibility
127+
input.attachEvent('onpropertychange', inputCallback);
128+
} else {
129+
input.addEventListener('input', inputCallback, false);
130+
}
131+
110132
if (isInputTargeted) {
111133
// To replace the node, we need to create an intermediate node
112134
let placeholderNode = document.createElement('div');

0 commit comments

Comments
 (0)