mirror of
https://github.com/ionic-team/ionic-framework.git
synced 2025-08-18 03:00:58 +08:00
@ -14,17 +14,15 @@ import { createColorClasses } from '../../utils/theme';
|
||||
scoped: true
|
||||
})
|
||||
export class Searchbar {
|
||||
|
||||
private nativeInput!: HTMLInputElement;
|
||||
private isCancelVisible = false;
|
||||
private shouldBlur = true;
|
||||
private shouldAlignLeft = true;
|
||||
|
||||
@Element() el!: HTMLElement;
|
||||
|
||||
@Prop({ context: 'document' }) doc!: Document;
|
||||
|
||||
@State() activated = false;
|
||||
|
||||
@State() focused = false;
|
||||
|
||||
/**
|
||||
@ -158,9 +156,14 @@ export class Searchbar {
|
||||
/**
|
||||
* Clears the input field and triggers the control change.
|
||||
*/
|
||||
private clearInput() {
|
||||
private clearInput(ev?: Event) {
|
||||
this.ionClear.emit();
|
||||
|
||||
if (ev) {
|
||||
ev.preventDefault();
|
||||
ev.stopPropagation();
|
||||
}
|
||||
|
||||
// setTimeout() fixes https://github.com/ionic-team/ionic/issues/7527
|
||||
// wait for 4 frames
|
||||
setTimeout(() => {
|
||||
@ -170,7 +173,6 @@ export class Searchbar {
|
||||
this.ionInput.emit();
|
||||
}
|
||||
}, 16 * 4);
|
||||
this.shouldBlur = false;
|
||||
}
|
||||
|
||||
/**
|
||||
@ -180,10 +182,7 @@ export class Searchbar {
|
||||
*/
|
||||
private cancelSearchbar() {
|
||||
this.ionCancel.emit();
|
||||
|
||||
this.clearInput();
|
||||
this.shouldBlur = true;
|
||||
this.activated = false;
|
||||
}
|
||||
|
||||
/**
|
||||
@ -197,36 +196,13 @@ export class Searchbar {
|
||||
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
|
||||
* based on whether there is a value in the searchbar or not.
|
||||
*/
|
||||
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.ionBlur.emit();
|
||||
this.positionElements();
|
||||
}
|
||||
|
||||
@ -234,12 +210,8 @@ export class Searchbar {
|
||||
* Sets the Searchbar to focused and active on input focus.
|
||||
*/
|
||||
private onFocus() {
|
||||
this.activated = true;
|
||||
|
||||
this.focused = true;
|
||||
this.ionFocus.emit();
|
||||
this.inputUpdated();
|
||||
|
||||
this.positionElements();
|
||||
}
|
||||
|
||||
@ -270,7 +242,7 @@ export class Searchbar {
|
||||
*/
|
||||
private positionPlaceholder() {
|
||||
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;
|
||||
|
||||
if (this.shouldAlignLeft) {
|
||||
@ -339,7 +311,6 @@ export class Searchbar {
|
||||
return {
|
||||
class: {
|
||||
...createColorClasses(this.color),
|
||||
'searchbar-active': this.activated,
|
||||
'searchbar-animated': this.animated,
|
||||
'searchbar-has-value': (this.value !== ''),
|
||||
'searchbar-show-cancel': this.showCancelButton,
|
||||
@ -356,9 +327,8 @@ export class Searchbar {
|
||||
const cancelButton = (this.showCancelButton)
|
||||
? <button
|
||||
type="button"
|
||||
tabIndex={this.mode === 'ios' && !this.activated ? -1 : undefined}
|
||||
tabIndex={this.mode === 'ios' && !this.focused ? -1 : undefined}
|
||||
onClick={this.cancelSearchbar.bind(this)}
|
||||
onMouseDown={this.cancelSearchbar.bind(this)}
|
||||
class="searchbar-cancel-button">
|
||||
{ this.mode === 'md'
|
||||
? <ion-icon mode={this.mode} icon={this.cancelButtonIcon}></ion-icon>
|
||||
@ -385,9 +355,11 @@ export class Searchbar {
|
||||
|
||||
<button
|
||||
type="button"
|
||||
no-blur={true}
|
||||
class="searchbar-clear-button"
|
||||
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>
|
||||
</button>
|
||||
</div>,
|
||||
|
@ -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) {
|
||||
console.debug('Input: enableInputBlurring');
|
||||
@ -25,17 +25,18 @@ export function enableInputBlurring(doc: Document) {
|
||||
if (!active) {
|
||||
return;
|
||||
}
|
||||
|
||||
// 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;
|
||||
}
|
||||
|
||||
// if the selected target is the active element, do not blur
|
||||
const tapped = ev.target;
|
||||
const tapped = ev.target as HTMLElement;
|
||||
if (tapped === active) {
|
||||
return;
|
||||
}
|
||||
if (SKIP_BLURRING.indexOf(tapped.tagName) >= 0) {
|
||||
if (tapped.matches(SKIP_SELECTOR) || tapped.closest(SKIP_SELECTOR)) {
|
||||
return;
|
||||
}
|
||||
|
||||
|
Reference in New Issue
Block a user