import { Component , ElementRef , EventEmitter , Input , Optional , Output , Renderer , ViewChild , ViewEncapsulation } from '@angular/core' ; import { NgControl } from '@angular/forms' ; import { Config } from '../../config/config' ; import { BaseInput } from '../../util/base-input' ; import { isPresent , isTrueProperty } from '../../util/util' ; import { TimeoutDebouncer } from '../../util/debouncer' ; import { Platform } from '../../platform/platform' ; name module description usage demo see {@link /docs/components#searchbar Searchbar Component Docs} @ Component ( { selector : 'ion-searchbar' , template : '<div class="searchbar-input-container">' + '<button ion-button mode="md" (click)="cancelSearchbar($event)" (mousedown)="cancelSearchbar($event)" clear color="dark" class="searchbar-md-cancel" type="button">' + '<ion-icon name="md-arrow-back"></ion-icon>' + '</button>' + '<div #searchbarIcon class="searchbar-search-icon"></div>' + '<input #searchbarInput class="searchbar-input" (input)="inputChanged($event)" (blur)="inputBlurred()" (focus)="inputFocused()" ' + 'dir="auto" ' + '[attr.placeholder]="placeholder" ' + '[attr.type]="type" ' + '[attr.autocomplete]="_autocomplete" ' + '[attr.autocorrect]="_autocorrect" ' + '[attr.spellcheck]="_spellcheck">' + '<button ion-button clear class="searchbar-clear-icon" [mode]="_mode" (click)="clearInput($event)" (mousedown)="clearInput($event)" type="button" aria-label="clear"></button>' + '</div>' + '<button ion-button #cancelButton mode="ios" [tabindex]="_isActive ? 1 : -1" clear (click)="cancelSearchbar($event)" (mousedown)="cancelSearchbar($event)" class="searchbar-ios-cancel" type="button">{{cancelButtonText}}</button>' , 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-has-focus]' : '_isFocus' } , encapsulation : ViewEncapsulation . None } ) export class Searchbar extends BaseInput < string > { _shouldBlur : boolean = true ; _shouldAlignLeft : boolean = true ; _isCancelVisible : boolean = false ; _spellcheck : boolean = false ; _autocomplete : string = 'off' ; _autocorrect : string = 'off' ; _isActive : boolean = false ; _showCancelButton : boolean = false ; _animated : boolean = false ; _inputDebouncer : TimeoutDebouncer = new TimeoutDebouncer ( 0 ) ; input @ Input ( ) cancelButtonText : string = 'Cancel' ; input @ Input ( ) get showCancelButton ( ) : boolean { return this . _showCancelButton ; } set showCancelButton ( val ) { this . _showCancelButton = isTrueProperty ( val ) ; } input @ Input ( ) get debounce ( ) : number { return this . _debouncer . wait ; } set debounce ( val ) { this . _debouncer . wait = val ; this . _inputDebouncer . wait = val ; } input @ Input ( ) placeholder : string = 'Search' ; input @ Input ( ) set autocomplete ( val ) { this . _autocomplete = ( val === '' || val === 'on' ) ? 'on' : this . _config . get ( 'autocomplete' , 'off' ) ; } input @ Input ( ) set autocorrect ( val ) { this . _autocorrect = ( val === '' || val === 'on' ) ? 'on' : this . _config . get ( 'autocorrect' , 'off' ) ; } input @ Input ( ) set spellcheck ( val ) { this . _spellcheck = ( val === '' || val === 'true' || val === true ) ? true : this . _config . getBoolean ( 'spellcheck' , false ) ; } input @ Input ( ) type : string = 'search' ; input @ Input ( ) get animated ( ) : boolean { return this . _animated ; } set animated ( val ) { this . _animated = isTrueProperty ( val ) ; } output @ Output ( ) ionInput : EventEmitter < UIEvent > = new EventEmitter < UIEvent > ( ) ; output @ Output ( ) ionCancel : EventEmitter < UIEvent > = new EventEmitter < UIEvent > ( ) ; output @ Output ( ) ionClear : EventEmitter < UIEvent > = new EventEmitter < UIEvent > ( ) ; constructor ( config , private _plt , elementRef , renderer , @ Optional ( ) ngControl ) { super ( config , elementRef , renderer , 'searchbar' , '' , null , null , ngControl ) ; this . debounce = 250 ; } @ ViewChild ( 'searchbarInput' ) _searchbarInput : ElementRef ; @ ViewChild ( 'searchbarIcon' ) _searchbarIcon : ElementRef ; @ ViewChild ( 'cancelButton' , { read : ElementRef } ) _cancelButton : ElementRef ; hidden ngOnInit ( ) { const showCancelButton = this . showCancelButton ; if ( typeof showCancelButton === 'string' ) { this . showCancelButton = ( showCancelButton === '' || showCancelButton === 'true' ) ; } } hidden _inputUpdated ( ) { const ele = this . _searchbarInput . nativeElement ; const value = this . _value ; if ( ele . value !== value ) { ele . value = value ; } this . positionElements ( ) ; } hidden positionElements ( ) { const isAnimated = this . _animated ; const prevAlignLeft = this . _shouldAlignLeft ; const shouldAlignLeft = ( ! isAnimated || ( this . _value && this . _value . toString ( ) . trim ( ) !== '' ) || this . _isFocus === true ) ; this . _shouldAlignLeft = shouldAlignLeft ; if ( this . _mode !== 'ios' ) { return ; } if ( prevAlignLeft !== shouldAlignLeft ) { this . positionPlaceholder ( ) ; } if ( isAnimated ) { this . positionCancelButton ( ) ; } } positionPlaceholder ( ) { const inputEle = this . _searchbarInput . nativeElement ; const iconEle = this . _searchbarIcon . nativeElement ; if ( this . _shouldAlignLeft ) { inputEle . removeAttribute ( 'style' ) ; iconEle . removeAttribute ( 'style' ) ; } else { var doc = this . _plt . doc ( ) ; var tempSpan = doc . createElement ( 'span' ) ; tempSpan . innerHTML = this . placeholder ; doc . body . appendChild ( tempSpan ) ; var textWidth = tempSpan . offsetWidth ; doc . body . removeChild ( tempSpan ) ; var inputLeft = 'calc(50% - ' + ( textWidth / 2 ) + 'px)' ; if ( this . _plt . isRTL ) { inputEle . style . paddingRight = inputLeft ; } else { inputEle . style . paddingLeft = inputLeft ; } var iconLeft = 'calc(50% - ' + ( ( textWidth / 2 ) + 30 ) + 'px)' ; if ( this . _plt . isRTL ) { iconEle . style . marginRight = iconLeft ; } else { iconEle . style . marginLeft = iconLeft ; } } } hidden positionCancelButton ( ) { const showShowCancel = this . _isFocus ; if ( showShowCancel !== this . _isCancelVisible ) { var cancelStyleEle = this . _cancelButton . nativeElement ; var cancelStyle = cancelStyleEle . style ; this . _isCancelVisible = showShowCancel ; if ( showShowCancel ) { if ( this . _plt . isRTL ) { cancelStyle . marginLeft = '0' ; } else { cancelStyle . marginRight = '0' ; } } else { var offset = cancelStyleEle . offsetWidth ; if ( offset > 0 ) { if ( this . _plt . isRTL ) { cancelStyle . marginLeft = - offset + 'px' ; } else { cancelStyle . marginRight = - offset + 'px' ; } } } } } hidden inputChanged ( ev ) { this . value = ev . target . value ; this . _inputDebouncer . debounce ( ( ) => { this . ionInput . emit ( ev ) ; } ) ; } hidden inputFocused ( ) { this . _isActive = true ; this . _fireFocus ( ) ; this . positionElements ( ) ; } hidden inputBlurred ( ) { if ( this . _shouldBlur === false ) { this . _searchbarInput . nativeElement . focus ( ) ; this . _shouldBlur = true ; return ; } this . _fireBlur ( ) ; this . positionElements ( ) ; } hidden clearInput ( ev ) { this . ionClear . emit ( ev ) ; setTimeout ( ( ) => { let value = this . _value ; if ( isPresent ( value ) && value !== '' ) { this . value = '' ; this . ionInput . emit ( ev ) ; } } , 16 * 4 ) ; this . _shouldBlur = false ; } hidden cancelSearchbar ( ev ) { this . ionCancel . emit ( ev ) ; this . clearInput ( ev ) ; this . _shouldBlur = true ; this . _isActive = false ; } setFocus ( ) { this . _renderer . invokeElementMethod ( this . _searchbarInput . nativeElement , 'focus' ) ; } }