diff --git a/src/components/searchbar/searchbar.ios.scss b/src/components/searchbar/searchbar.ios.scss
index 74a6c719ba..c8f1f4ba7a 100644
--- a/src/components/searchbar/searchbar.ios.scss
+++ b/src/components/searchbar/searchbar.ios.scss
@@ -15,12 +15,11 @@ $searchbar-ios-input-search-icon-svg: "" !default;
@@ -86,7 +85,6 @@ ion-searchbar {
border-radius: 5px;
font-size: 1.4rem;
font-weight: 400;
- line-height: $searchbar-ios-input-line-height;
color: $searchbar-ios-input-text-color;
background-color: $searchbar-ios-input-background-color;
@@ -118,19 +116,30 @@ ion-searchbar {
// -----------------------------------------
.searchbar-ios-cancel {
- flex: 0 0 0%;
+ display: none;
- margin-right: 0;
+ flex-shrink: 0;
+
+ margin-right: -100%;
margin-left: 0;
padding: 0;
+ padding-left: 8px;
height: 30px;
- visibility: hidden;
- transform: translateX(calc(100% + #{$searchbar-ios-padding-left-right}));
+ cursor: pointer;
+
+ opacity: 0;
+
+ transform: translate3d(0, 0, 0);
transition: $searchbar-ios-cancel-transition;
+
+ pointer-events: none;
}
+.searchbar-show-cancel .searchbar-ios-cancel {
+ display: block;
+}
// Searchbar Left Aligned (iOS only)
// -----------------------------------------
@@ -145,20 +154,19 @@ ion-searchbar {
}
}
-// Searchbar Focused
+
+// Searchbar Has Focus
// -----------------------------------------
.searchbar-has-focus {
.searchbar-ios-cancel {
- flex: 0 0 auto;
+ opacity: 1;
- padding-left: 8px;
-
- visibility: visible;
- transform: translateX(0);
+ pointer-events: auto;
}
}
+
// Searchbar in Toolbar
// -----------------------------------------
diff --git a/src/components/searchbar/searchbar.md.scss b/src/components/searchbar/searchbar.md.scss
index b66d1f48e5..4f5692643a 100644
--- a/src/components/searchbar/searchbar.md.scss
+++ b/src/components/searchbar/searchbar.md.scss
@@ -130,7 +130,7 @@ ion-searchbar {
// Searchbar Focused
// -----------------------------------------
-.searchbar-has-focus:not(.searchbar-hide-cancel) {
+.searchbar-has-focus.searchbar-show-cancel {
.searchbar-search-icon {
display: none;
}
diff --git a/src/components/searchbar/searchbar.ts b/src/components/searchbar/searchbar.ts
index ba16d14768..bef595cacd 100644
--- a/src/components/searchbar/searchbar.ts
+++ b/src/components/searchbar/searchbar.ts
@@ -5,17 +5,6 @@ import {Config} from '../../config/config';
import {isPresent} from '../../util/util';
-/**
-* @private
-*/
-@Directive({
- selector: '.searchbar-input',
-})
-export class SearchbarInput {
- constructor(public elementRef: ElementRef) {}
-}
-
-
/**
* @name Searchbar
* @module ionic
@@ -26,7 +15,7 @@ export class SearchbarInput {
* ```html
*
*
@@ -39,29 +28,28 @@ export class SearchbarInput {
selector: 'ion-searchbar',
host: {
'[class.searchbar-has-value]': '_value',
- '[class.searchbar-hide-cancel]': 'hideCancelButton'
+ '[class.searchbar-active]': '_isActive',
+ '[class.searchbar-show-cancel]': 'showCancelButton',
+ '[class.searchbar-left-aligned]': 'shouldAlignLeft()'
},
template:
'
' +
- '',
- directives: [SearchbarInput],
+ '',
encapsulation: ViewEncapsulation.None
})
export class Searchbar {
private _value: string|number = '';
private _tmr: any;
private _shouldBlur: boolean = true;
-
- private inputEle: any;
- private iconEle: any;
- private mode: string;
+ private _isActive: boolean = false;
+ private _searchbarInput: ElementRef;
/**
* @input {string} Set the the cancel button text. Default: `"Cancel"`.
@@ -71,7 +59,7 @@ export class Searchbar {
/**
* @input {boolean} Whether to hide the cancel button or not. Default: `"false"`.
*/
- @Input() hideCancelButton: any = false;
+ @Input() showCancelButton: any = false;
/**
* @input {number} How long, in milliseconds, to wait to trigger the `input` event after each keystroke. Default `250`.
@@ -131,12 +119,7 @@ export class Searchbar {
/**
* @private
*/
- @HostBinding('class.searchbar-has-focus') isFocused: boolean;
-
- /**
- * @private
- */
- @HostBinding('class.searchbar-left-aligned') shouldLeftAlign: boolean;
+ @HostBinding('class.searchbar-has-focus') _sbHasFocus: boolean;
constructor(
private _elementRef: ElementRef,
@@ -152,28 +135,32 @@ export class Searchbar {
/**
* @private
*/
- @ViewChild(SearchbarInput)
- private set _searchbarInput(searchbarInput: SearchbarInput) {
- this.inputEle = searchbarInput.elementRef.nativeElement;
+ @ViewChild('searchbarInput')
+ private set searchbarInput(searchbarInput: ElementRef) {
+ this._searchbarInput = searchbarInput;
+
+ let inputEle = searchbarInput.nativeElement;
// By defalt set autocomplete="off" unless specified by the input
let autoComplete = (this.autocomplete === '' || this.autocomplete === 'on') ? 'on' : this._config.get('autocomplete', 'off');
- this.inputEle.setAttribute('autocomplete', autoComplete);
+ inputEle.setAttribute('autocomplete', autoComplete);
// by default set autocorrect="off" unless specified by the input
let autoCorrect = (this.autocorrect === '' || this.autocorrect === 'on') ? 'on' : this._config.get('autocorrect', 'off');
- this.inputEle.setAttribute('autocorrect', autoCorrect);
+ inputEle.setAttribute('autocorrect', autoCorrect);
// by default set spellcheck="false" unless specified by the input
let spellCheck = (this.spellcheck === '' || this.spellcheck === 'true' || this.spellcheck === true) ? true : this._config.getBoolean('spellcheck', false);
- this.inputEle.setAttribute('spellcheck', spellCheck);
+ inputEle.setAttribute('spellcheck', spellCheck);
// by default set type="search" unless specified by the input
- this.inputEle.setAttribute('type', this.type);
+ inputEle.setAttribute('type', this.type);
}
@ViewChild('searchbarIcon') _searchbarIcon: ElementRef;
+ @ViewChild('cancelButton', {read: ElementRef}) _cancelButton: ElementRef;
+
/**
* @input {string} Set the input value.
*/
@@ -191,38 +178,44 @@ export class Searchbar {
* On Initialization check for attributes
*/
ngOnInit() {
- this.mode = this._config.get('mode');
-
- let hideCancelButton = this.hideCancelButton;
- if (typeof hideCancelButton === 'string') {
- this.hideCancelButton = (hideCancelButton === '' || hideCancelButton === 'true');
+ let showCancelButton = this.showCancelButton;
+ if (typeof showCancelButton === 'string') {
+ this.showCancelButton = (showCancelButton === '' || showCancelButton === 'true');
}
-
- this.shouldLeftAlign = this._value && this._value.toString().trim() !== '';
}
/**
* @private
- * After View Initialization check the value
+ * After View Initialization position the elements
*/
ngAfterViewInit() {
- this.iconEle = this._searchbarIcon.nativeElement;
- this.setElementLeft();
+ this.positionElements();
}
/**
* @private
- * Determines whether or not to add style to the element
- * to center it properly (ios only)
+ * After Content is checked position the elements
*/
- setElementLeft() {
- if (this.mode !== 'ios') return;
+ ngAfterContentChecked() {
+ this.positionElements();
+ }
- if (this.shouldLeftAlign) {
- this.inputEle.removeAttribute('style');
- this.iconEle.removeAttribute('style');
- } else {
- this.addElementLeft();
+ /**
+ * @private
+ * Positions the input search icon, placeholder, and the cancel button
+ * based on the input value and if it is focused. (ios only)
+ */
+ positionElements() {
+ if (this._config.get('mode') !== 'ios') return;
+
+ // Position the input placeholder & search icon
+ if (this._searchbarInput && this._searchbarIcon) {
+ this.positionInputPlaceholder(this._searchbarInput.nativeElement, this._searchbarIcon.nativeElement);
+ }
+
+ // Position the cancel button
+ if (this._cancelButton && this._cancelButton.nativeElement) {
+ this.positionCancelButton(this._cancelButton.nativeElement);
}
}
@@ -231,23 +224,50 @@ export class Searchbar {
* Calculates the amount of padding/margin left for the elements
* in order to center them based on the placeholder width
*/
- addElementLeft() {
- // Create a dummy span to get the placeholder width
- let tempSpan = document.createElement('span');
- tempSpan.innerHTML = this.placeholder;
- document.body.appendChild(tempSpan);
+ positionInputPlaceholder(inputEle: HTMLElement, iconEle: HTMLElement) {
+ if (this.shouldAlignLeft()) {
+ inputEle.removeAttribute('style');
+ iconEle.removeAttribute('style');
+ } else {
+ // Create a dummy span to get the placeholder width
+ let tempSpan = document.createElement('span');
+ tempSpan.innerHTML = this.placeholder;
+ document.body.appendChild(tempSpan);
- // Get the width of the span then remove it
- let textWidth = tempSpan.offsetWidth;
- tempSpan.remove();
+ // Get the width of the span then remove it
+ let textWidth = tempSpan.offsetWidth;
+ tempSpan.remove();
- // Set the input padding left
- let inputLeft = 'calc(50% - ' + (textWidth / 2) + 'px)';
- this.inputEle.style.paddingLeft = inputLeft;
+ // Set the input padding left
+ let inputLeft = 'calc(50% - ' + (textWidth / 2) + 'px)';
+ inputEle.style.paddingLeft = inputLeft;
- // Set the icon margin left
- let iconLeft = 'calc(50% - ' + ((textWidth / 2) + 30) + 'px)';
- this.iconEle.style.marginLeft = iconLeft;
+ // Set the icon margin left
+ let iconLeft = 'calc(50% - ' + ((textWidth / 2) + 30) + 'px)';
+ iconEle.style.marginLeft = iconLeft;
+ }
+ }
+
+ /**
+ * @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';
+ } else {
+ cancelButtonEle.style.marginRight = -cancelButtonEle.offsetWidth + '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 );
}
/**
@@ -267,14 +287,14 @@ export class Searchbar {
/**
* @private
- * Sets the Searchbar to focused and aligned left on input focus.
+ * Sets the Searchbar to focused and active on input focus.
*/
inputFocused(ev: UIEvent) {
this.ionFocus.emit(ev);
- this.isFocused = true;
- this.shouldLeftAlign = true;
- this.setElementLeft();
+ this._sbHasFocus = true;
+ this._isActive = true;
+ this.positionElements();
}
/**
@@ -286,15 +306,14 @@ export class Searchbar {
// _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) {
- this.inputEle.focus();
+ this._searchbarInput.nativeElement.focus();
this._shouldBlur = true;
return;
}
this.ionBlur.emit(ev);
- this.isFocused = false;
- this.shouldLeftAlign = this._value && this._value.toString().trim() !== '';
- this.setElementLeft();
+ this._sbHasFocus = false;
+ this.positionElements();
}
/**
@@ -324,6 +343,7 @@ export class Searchbar {
this.clearInput(ev);
this._shouldBlur = true;
+ this._isActive = false;
}
/**
diff --git a/src/components/searchbar/test/floating/index.ts b/src/components/searchbar/test/floating/index.ts
index c65a75c8d7..c5823d343e 100644
--- a/src/components/searchbar/test/floating/index.ts
+++ b/src/components/searchbar/test/floating/index.ts
@@ -41,6 +41,7 @@ class E2EApp {
ngAfterViewInit() {
this.customPlaceholder = 33;
+ this.defaultCancel = "after view";
this.changeDetectorRef.detectChanges();
}
diff --git a/src/components/searchbar/test/floating/main.html b/src/components/searchbar/test/floating/main.html
index 5737183093..bd598fc112 100644
--- a/src/components/searchbar/test/floating/main.html
+++ b/src/components/searchbar/test/floating/main.html
@@ -1,27 +1,30 @@
Search - Default
-
+
defaultSearch: {{ defaultSearch }}
Search - Custom Placeholder
-
+
customPlaceholder: {{ customPlaceholder }}
- Search - Hide Cancel Button
-
+ Search - No Cancel Button
+
defaultCancel: {{ defaultCancel }}
Search - Custom Cancel Button Danger
-
+
+
+ Search - Value passed
+
diff --git a/src/components/searchbar/test/toolbar/main.html b/src/components/searchbar/test/toolbar/main.html
index d036151f66..7a40104212 100644
--- a/src/components/searchbar/test/toolbar/main.html
+++ b/src/components/searchbar/test/toolbar/main.html
@@ -10,7 +10,7 @@
Search - Primary Toolbar
-
+
Search - Dark Toolbar
@@ -20,7 +20,7 @@
Search - Light Toolbar
-
+
diff --git a/src/config/directives.ts b/src/config/directives.ts
index da423c9168..b00a191f20 100644
--- a/src/config/directives.ts
+++ b/src/config/directives.ts
@@ -36,7 +36,7 @@ import {Segment, SegmentButton} from '../components/segment/segment';
import {RadioButton} from '../components/radio/radio-button';
import {RadioGroup} from '../components/radio/radio-group';
import {Range} from '../components/range/range';
-import {Searchbar, SearchbarInput} from '../components/searchbar/searchbar';
+import {Searchbar} from '../components/searchbar/searchbar';
import {Nav} from '../components/nav/nav';
import {NavPush, NavPop} from '../components/nav/nav-push';
import {NavRouter} from '../components/nav/nav-router';
@@ -89,7 +89,6 @@ import {ShowWhen, HideWhen} from '../components/show-hide-when/show-hide-when';
* - Icon
* - Spinner
* - Searchbar
- * - SearchbarInput
* - Segment
* - SegmentButton
* - Checkbox
@@ -164,7 +163,6 @@ export const IONIC_DIRECTIVES: any[] = [
// Forms
Searchbar,
- SearchbarInput,
Segment,
SegmentButton,
Checkbox,