import { ChangeDetectionStrategy , Component , ElementRef , Input , OnDestroy , Optional , Renderer , ViewEncapsulation } from '@angular/core' ; import { Img as IImg } from './img-interface' ; import { Content } from '../content/content' ; import { DomController } from '../../platform/dom-controller' ; import { isPresent , isTrueProperty } from '../../util/util' ; import { Platform } from '../../platform/platform' ; name description @ Component ( { selector : 'ion-img' , template : '<img>' , changeDetection : ChangeDetectionStrategy . OnPush , encapsulation : ViewEncapsulation . None , } ) export class Img implements OnDestroy , IImg { internal _src : string ; internal _requestingSrc : string ; internal _renderedSrc : string ; internal _hasLoaded : boolean ; internal _cache : boolean = true ; internal _bounds : any ; internal _rect : any ; internal _w : string = '' ; internal _h : string = '' ; internal _wQ : string = '' ; internal _hQ : string = '' ; internal _img : HTMLImageElement ; internal _unreg : Function ; hidden canRequest : boolean ; hidden canRender : boolean ; constructor ( private _elementRef , private _renderer , private _plt , @ Optional ( ) private _content , private _dom ) { if ( ! this . _content ) { console . warn ( `ion-img can only be used within an ion-content` ) ; } else { this . _content . addImg ( this ) ; } this . _isLoaded ( false ) ; } input @ Input ( ) get src ( ) : string { return this . _src ; } set src ( newSrc ) { if ( newSrc !== this . _src ) { this . reset ( ) ; this . _src = newSrc ; this . _hasLoaded = newSrc . indexOf ( 'data:' ) === 0 ; this . update ( ) ; } } hidden reset ( ) { if ( this . _requestingSrc ) { console . debug ( `abortRequest ${ this . _requestingSrc } ${ Date . now ( ) }` ) ; this . _srcAttr ( '' ) ; this . _requestingSrc = null ; } if ( this . _renderedSrc ) { console . debug ( `clearRender ${ this . _renderedSrc } ${ Date . now ( ) }` ) ; this . _renderedSrc = null ; this . _isLoaded ( false ) ; } } hidden update ( ) { if ( this . _src && this . _content . isImgsUpdatable ( ) ) { if ( this . canRequest && ( this . _src !== this . _renderedSrc && this . _src !== this . _requestingSrc ) && ! this . _hasLoaded ) { console . debug ( `request ${ this . _src } ${ Date . now ( ) }` ) ; this . _requestingSrc = this . _src ; this . _isLoaded ( false ) ; this . _srcAttr ( this . _src ) ; this . _setDims ( ) ; } if ( this . canRender && this . _hasLoaded && this . _src !== this . _renderedSrc ) { this . _renderedSrc = this . _src ; this . _setDims ( ) ; this . _dom . write ( ( ) => { if ( this . _hasLoaded ) { console . debug ( `render ${ this . _src } ${ Date . now ( ) }` ) ; this . _isLoaded ( true ) ; this . _srcAttr ( this . _src ) ; } } ) ; } } } internal _isLoaded ( isLoaded ) { const renderer = this . _renderer ; const ele = this . _elementRef . nativeElement ; renderer . setElementClass ( ele , 'img-loaded' , isLoaded ) ; renderer . setElementClass ( ele , 'img-unloaded' , ! isLoaded ) ; } internal _srcAttr ( srcAttr ) { const imgEle = this . _img ; const renderer = this . _renderer ; if ( imgEle && imgEle . src !== srcAttr ) { renderer . setElementAttribute ( this . _img , 'src' , srcAttr ) ; renderer . setElementAttribute ( this . _img , 'alt' , this . alt ) ; } } hidden get top ( ) : number { const bounds = this . _getBounds ( ) ; return bounds && bounds . top || 0 ; } hidden get bottom ( ) : number { const bounds = this . _getBounds ( ) ; return bounds && bounds . bottom || 0 ; } private _getBounds ( ) { if ( this . _bounds ) { return this . _bounds ; } if ( ! this . _rect ) { this . _rect = ( < HTMLElement > this . _elementRef . nativeElement ) . getBoundingClientRect ( ) ; console . debug ( `img, ${ this . _src }, read, ${ this . _rect . top } - ${ this . _rect . bottom }` ) ; } return this . _rect ; } input @ Input ( ) set bounds ( b ) { if ( isPresent ( b ) ) { this . _bounds = b ; } } input @ Input ( ) get cache ( ) : boolean { return this . _cache ; } set cache ( val ) { this . _cache = isTrueProperty ( val ) ; } input @ Input ( ) set width ( val ) { this . _wQ = getUnitValue ( val ) ; this . _setDims ( ) ; } input @ Input ( ) set height ( val ) { this . _hQ = getUnitValue ( val ) ; this . _setDims ( ) ; } private _setDims ( ) { if ( this . canRender && ( this . _w !== this . _wQ || this . _h !== this . _hQ ) ) { var wrapperEle = this . _elementRef . nativeElement ; var renderer = this . _renderer ; this . _dom . write ( ( ) => { if ( this . _w !== this . _wQ ) { this . _w = this . _wQ ; renderer . setElementStyle ( wrapperEle , 'width' , this . _w ) ; } if ( this . _h !== this . _hQ ) { this . _h = this . _hQ ; renderer . setElementStyle ( wrapperEle , 'height' , this . _h ) ; } } ) ; } } input @ Input ( ) alt : string = '' ; hidden ngAfterContentInit ( ) { this . _img = this . _elementRef . nativeElement . firstChild ; this . _unreg = this . _plt . registerListener ( this . _img , 'load' , ( ) => { this . _hasLoaded = true ; this . update ( ) ; } , { passive : true } ) ; } hidden ngOnDestroy ( ) { this . _unreg && this . _unreg ( ) ; this . _content && this . _content . removeImg ( this ) ; } } function getUnitValue ( val ) { if ( isPresent ( val ) ) { if ( typeof val === 'string' ) { if ( val . indexOf ( '%' ) > - 1 || val . indexOf ( 'px' ) > - 1 ) { return val ; } if ( val . length ) { return val + 'px' ; } } else if ( typeof val === 'number' ) { return val + 'px' ; } } return '' ; }