diff --git a/src/components/searchbar/searchbar.ios.scss b/src/components/searchbar/searchbar.ios.scss index b1cea8f18fb..697e5431f87 100644 --- a/src/components/searchbar/searchbar.ios.scss +++ b/src/components/searchbar/searchbar.ios.scss @@ -66,8 +66,6 @@ $searchbar-ios-toolbar-input-background: rgba(0, 0, 0, .08) !default; background-repeat: no-repeat; background-size: $searchbar-ios-input-search-icon-size; - - transition: $searchbar-ios-input-transition; } @@ -87,8 +85,6 @@ $searchbar-ios-toolbar-input-background: rgba(0, 0, 0, .08) !default; color: $searchbar-ios-input-text-color; background-color: $searchbar-ios-input-background-color; - - transition: $searchbar-ios-input-transition; } @@ -119,7 +115,6 @@ $searchbar-ios-toolbar-input-background: rgba(0, 0, 0, .08) !default; flex-shrink: 0; - margin-right: -100%; margin-left: 0; padding: 0; padding-left: 8px; @@ -127,20 +122,8 @@ $searchbar-ios-toolbar-input-background: rgba(0, 0, 0, .08) !default; height: 30px; cursor: pointer; - - opacity: 0; - - transform: translate3d(0, 0, 0); - transition: $searchbar-ios-cancel-transition; - - pointer-events: none; } -.searchbar-ios.searchbar-show-cancel .searchbar-ios-cancel { - display: block; -} - - // Searchbar Left Aligned (iOS only) // ----------------------------------------- @@ -156,10 +139,8 @@ $searchbar-ios-toolbar-input-background: rgba(0, 0, 0, .08) !default; // Searchbar Has Focus // ----------------------------------------- -.searchbar-ios.searchbar-has-focus .searchbar-ios-cancel { - opacity: 1; - - pointer-events: auto; +.searchbar-ios.searchbar-show-cancel.searchbar-has-focus .searchbar-ios-cancel { + display: block; } @@ -225,3 +206,29 @@ $searchbar-ios-toolbar-input-background: rgba(0, 0, 0, .08) !default; } } + +// Searchbar animation +// ----------------------------------------- + +.searchbar-ios.searchbar-animated .searchbar-search-icon, +.searchbar-ios.searchbar-animated .searchbar-input { + transition: $searchbar-ios-input-transition; +} + +.searchbar-animated.searchbar-has-focus .searchbar-ios-cancel { + opacity: 1; + + pointer-events: auto; +} + +.searchbar-animated .searchbar-ios-cancel { + display: block; + + margin-right: -100%; + + opacity: 0; + transform: translate3d(0, 0, 0); + transition: $searchbar-ios-cancel-transition; + + pointer-events: none; +} diff --git a/src/components/searchbar/searchbar.scss b/src/components/searchbar/searchbar.scss index 9d68e30b5cc..0a67f402dde 100644 --- a/src/components/searchbar/searchbar.scss +++ b/src/components/searchbar/searchbar.scss @@ -48,3 +48,4 @@ ion-searchbar { .searchbar-has-value.searchbar-has-focus .searchbar-clear-icon { display: block; } + diff --git a/src/components/searchbar/searchbar.ts b/src/components/searchbar/searchbar.ts index 3c77aa472d6..03377ba02b2 100644 --- a/src/components/searchbar/searchbar.ts +++ b/src/components/searchbar/searchbar.ts @@ -3,7 +3,7 @@ import { NgControl } from '@angular/forms'; import { Config } from '../../config/config'; import { Ion } from '../ion'; -import { isPresent } from '../../util/util'; +import { isPresent, isTrueProperty } from '../../util/util'; import { Debouncer } from '../../util/debouncer'; @@ -39,16 +39,19 @@ import { Debouncer } from '../../util/debouncer'; '' + '', host: { + '[class.searchbar-animated]': 'animated', '[class.searchbar-has-value]': '_value', '[class.searchbar-active]': '_isActive', '[class.searchbar-show-cancel]': 'showCancelButton', - '[class.searchbar-left-aligned]': 'shouldAlignLeft()' + '[class.searchbar-left-aligned]': '_shouldAlignLeft' }, encapsulation: ViewEncapsulation.None }) export class Searchbar extends Ion { _value: string|number = ''; _shouldBlur: boolean = true; + _shouldAlignLeft: boolean = true; + _isCancelVisible: boolean = false; _isActive: boolean = false; _searchbarInput: ElementRef; _debouncer: Debouncer = new Debouncer(250); @@ -115,6 +118,11 @@ export class Searchbar extends Ion { */ @Input() type: string = 'search'; + /** + * @input {string|boolean} Set the input's spellcheck property. Values: `true`, `false`. Default `false`. + */ + @Input() animated: string | boolean = false; + /** * @output {event} When the Searchbar input has changed including cleared. */ @@ -217,7 +225,7 @@ export class Searchbar extends Ion { * @private * After View Checked position the elements */ - ngAfterViewChecked() { + ngAfterContentInit() { this.positionElements(); } @@ -227,26 +235,31 @@ export class Searchbar extends Ion { * based on the input value and if it is focused. (ios only) */ positionElements() { - if (this._config.get('mode') !== 'ios') return; + let isAnimated = isTrueProperty(this.animated); + let prevAlignLeft = this._shouldAlignLeft; + let shouldAlignLeft = (!isAnimated || (this._value && this._value.toString().trim() !== '') || this._sbHasFocus === true); + this._shouldAlignLeft = shouldAlignLeft; - // Position the input placeholder & search icon - if (this._searchbarInput && this._searchbarIcon) { - this.positionInputPlaceholder(this._searchbarInput.nativeElement, this._searchbarIcon.nativeElement); + if (this._config.get('mode') !== 'ios') { + return; } - // Position the cancel button - if (this._cancelButton && this._cancelButton.nativeElement) { - this.positionCancelButton(this._cancelButton.nativeElement); + if (prevAlignLeft !== shouldAlignLeft) { + this.positionPlaceholder(); + } + if (isAnimated) { + this.positionCancelButton(); } } - /** - * @private - * Calculates the amount of padding/margin left for the elements - * in order to center them based on the placeholder width - */ - positionInputPlaceholder(inputEle: HTMLElement, iconEle: HTMLElement) { - if (this.shouldAlignLeft()) { + positionPlaceholder() { + if (!this._searchbarInput || !this._searchbarIcon) { + return; + } + let inputEle = this._searchbarInput.nativeElement; + let iconEle = this._searchbarIcon.nativeElement; + + if (this._shouldAlignLeft) { inputEle.removeAttribute('style'); iconEle.removeAttribute('style'); } else { @@ -273,23 +286,26 @@ export class Searchbar extends Ion { * @private * Show the iOS Cancel button on focus, hide it offscreen otherwise */ - positionCancelButton(cancelButtonEle: HTMLElement) { - if (cancelButtonEle.offsetWidth > 0) { - if (this._sbHasFocus) { - cancelButtonEle.style.marginRight = '0'; + positionCancelButton() { + if (!this._cancelButton || !this._cancelButton.nativeElement) { + return; + } + let showShowCancel = this._sbHasFocus; + if (showShowCancel !== this._isCancelVisible) { + let cancelStyleEle = this._cancelButton.nativeElement; + let cancelStyle = cancelStyleEle.style; + this._isCancelVisible = showShowCancel; + if (showShowCancel) { + cancelStyle.marginRight = '0'; } else { - cancelButtonEle.style.marginRight = -cancelButtonEle.offsetWidth + 'px'; + let offset = cancelStyleEle.offsetWidth; + if (offset > 0) { + cancelStyle.marginRight = -offset + 'px'; + } } } } - /** - * @private - * Align the input placeholder left on focus or if a value exists - */ - shouldAlignLeft() { - return ( (this._value && this._value.toString().trim() !== '') || this._sbHasFocus === true ); - } /** * @private @@ -399,4 +415,8 @@ export class Searchbar extends Ion { registerOnTouched(fn: () => {}): void { this.onTouched = fn; } + + focus() { + this.getNativeElement().focus(); + } } diff --git a/src/components/searchbar/test/basic/main.html b/src/components/searchbar/test/basic/main.html index 02309d58241..682b34e8aed 100644 --- a/src/components/searchbar/test/basic/main.html +++ b/src/components/searchbar/test/basic/main.html @@ -2,6 +2,9 @@
defaultSearch: {{ defaultSearch }}
diff --git a/src/components/searchbar/test/nav/search.html b/src/components/searchbar/test/nav/search.html index 8aa8be3a5bd..6daff2c3716 100644 --- a/src/components/searchbar/test/nav/search.html +++ b/src/components/searchbar/test/nav/search.html @@ -14,8 +14,9 @@