fix(searchbar): fix input bluring

fixes #14916
This commit is contained in:
Manu Mtz.-Almeida
2018-07-29 14:19:51 +02:00
parent a62759c3cc
commit d65174bcf3
2 changed files with 18 additions and 45 deletions

View File

@ -14,17 +14,15 @@ import { createColorClasses } from '../../utils/theme';
scoped: true scoped: true
}) })
export class Searchbar { export class Searchbar {
private nativeInput!: HTMLInputElement; private nativeInput!: HTMLInputElement;
private isCancelVisible = false; private isCancelVisible = false;
private shouldBlur = true;
private shouldAlignLeft = true; private shouldAlignLeft = true;
@Element() el!: HTMLElement; @Element() el!: HTMLElement;
@Prop({ context: 'document' }) doc!: Document; @Prop({ context: 'document' }) doc!: Document;
@State() activated = false;
@State() focused = false; @State() focused = false;
/** /**
@ -158,9 +156,14 @@ export class Searchbar {
/** /**
* Clears the input field and triggers the control change. * Clears the input field and triggers the control change.
*/ */
private clearInput() { private clearInput(ev?: Event) {
this.ionClear.emit(); this.ionClear.emit();
if (ev) {
ev.preventDefault();
ev.stopPropagation();
}
// setTimeout() fixes https://github.com/ionic-team/ionic/issues/7527 // setTimeout() fixes https://github.com/ionic-team/ionic/issues/7527
// wait for 4 frames // wait for 4 frames
setTimeout(() => { setTimeout(() => {
@ -170,7 +173,6 @@ export class Searchbar {
this.ionInput.emit(); this.ionInput.emit();
} }
}, 16 * 4); }, 16 * 4);
this.shouldBlur = false;
} }
/** /**
@ -180,10 +182,7 @@ export class Searchbar {
*/ */
private cancelSearchbar() { private cancelSearchbar() {
this.ionCancel.emit(); this.ionCancel.emit();
this.clearInput(); this.clearInput();
this.shouldBlur = true;
this.activated = false;
} }
/** /**
@ -197,36 +196,13 @@ export class Searchbar {
this.ionInput.emit(ev); this.ionInput.emit(ev);
} }
private inputUpdated() {
// const inputEl = (this.el.shadowRoot || this.el).querySelector('.searchbar-input') as HTMLInputElment;
// It is important not to re-assign the value if it is the same, because,
// otherwise, the caret is moved to the end of the input
// if (inputEl && inputEl.value !== this.value) {
// // inputEl.value = this.value;
// this.value = inputEl.value;
// }
this.positionElements();
}
/** /**
* Sets the Searchbar to not focused and checks if it should align left * Sets the Searchbar to not focused and checks if it should align left
* based on whether there is a value in the searchbar or not. * based on whether there is a value in the searchbar or not.
*/ */
private onBlur() { private onBlur() {
const inputEl = (this.el.shadowRoot || this.el).querySelector('.searchbar-input') as HTMLInputElement;
// shouldBlur determines if it should blur
// if we are clearing the input we still want to stay focused in the input
if (this.shouldBlur === false) {
inputEl.focus();
this.shouldBlur = true;
this.ionBlur.emit();
this.inputUpdated();
return;
}
this.focused = false; this.focused = false;
this.ionBlur.emit();
this.positionElements(); this.positionElements();
} }
@ -234,12 +210,8 @@ export class Searchbar {
* Sets the Searchbar to focused and active on input focus. * Sets the Searchbar to focused and active on input focus.
*/ */
private onFocus() { private onFocus() {
this.activated = true;
this.focused = true; this.focused = true;
this.ionFocus.emit(); this.ionFocus.emit();
this.inputUpdated();
this.positionElements(); this.positionElements();
} }
@ -270,7 +242,7 @@ export class Searchbar {
*/ */
private positionPlaceholder() { private positionPlaceholder() {
const isRTL = this.doc.dir === 'rtl'; const isRTL = this.doc.dir === 'rtl';
const inputEl = (this.el.shadowRoot || this.el).querySelector('.searchbar-input') as HTMLInputElement; const inputEl = this.nativeInput;
const iconEl = (this.el.shadowRoot || this.el).querySelector('.searchbar-search-icon') as HTMLElement; const iconEl = (this.el.shadowRoot || this.el).querySelector('.searchbar-search-icon') as HTMLElement;
if (this.shouldAlignLeft) { if (this.shouldAlignLeft) {
@ -339,7 +311,6 @@ export class Searchbar {
return { return {
class: { class: {
...createColorClasses(this.color), ...createColorClasses(this.color),
'searchbar-active': this.activated,
'searchbar-animated': this.animated, 'searchbar-animated': this.animated,
'searchbar-has-value': (this.value !== ''), 'searchbar-has-value': (this.value !== ''),
'searchbar-show-cancel': this.showCancelButton, 'searchbar-show-cancel': this.showCancelButton,
@ -356,9 +327,8 @@ export class Searchbar {
const cancelButton = (this.showCancelButton) const cancelButton = (this.showCancelButton)
? <button ? <button
type="button" type="button"
tabIndex={this.mode === 'ios' && !this.activated ? -1 : undefined} tabIndex={this.mode === 'ios' && !this.focused ? -1 : undefined}
onClick={this.cancelSearchbar.bind(this)} onClick={this.cancelSearchbar.bind(this)}
onMouseDown={this.cancelSearchbar.bind(this)}
class="searchbar-cancel-button"> class="searchbar-cancel-button">
{ this.mode === 'md' { this.mode === 'md'
? <ion-icon mode={this.mode} icon={this.cancelButtonIcon}></ion-icon> ? <ion-icon mode={this.mode} icon={this.cancelButtonIcon}></ion-icon>
@ -385,9 +355,11 @@ export class Searchbar {
<button <button
type="button" type="button"
no-blur={true}
class="searchbar-clear-button" class="searchbar-clear-button"
onClick={this.clearInput.bind(this)} onClick={this.clearInput.bind(this)}
onMouseDown={this.clearInput.bind(this)}> onMouseDown={this.clearInput.bind(this)}
onTouchStart={this.clearInput.bind(this)}>
<ion-icon mode={this.mode} icon={clearIcon} class="searchbar-clear-icon"></ion-icon> <ion-icon mode={this.mode} icon={clearIcon} class="searchbar-clear-icon"></ion-icon>
</button> </button>
</div>, </div>,

View File

@ -1,5 +1,5 @@
const SKIP_BLURRING = ['INPUT', 'TEXTAREA', 'ION-INPUT', 'ION-TEXTAREA']; const SKIP_SELECTOR = 'input, textarea, [no-blur]';
export function enableInputBlurring(doc: Document) { export function enableInputBlurring(doc: Document) {
console.debug('Input: enableInputBlurring'); console.debug('Input: enableInputBlurring');
@ -25,17 +25,18 @@ export function enableInputBlurring(doc: Document) {
if (!active) { if (!active) {
return; return;
} }
// only blur if the active element is a text-input or a textarea // only blur if the active element is a text-input or a textarea
if (SKIP_BLURRING.indexOf(active.tagName) === -1) { if (active.matches(SKIP_SELECTOR)) {
return; return;
} }
// if the selected target is the active element, do not blur // if the selected target is the active element, do not blur
const tapped = ev.target; const tapped = ev.target as HTMLElement;
if (tapped === active) { if (tapped === active) {
return; return;
} }
if (SKIP_BLURRING.indexOf(tapped.tagName) >= 0) { if (tapped.matches(SKIP_SELECTOR) || tapped.closest(SKIP_SELECTOR)) {
return; return;
} }