import { Component , View , Directive , ElementRef , Query , QueryList , NgFor , NgIf , EventEmitter } from 'angular2/angular2' ; @ Directive ( { selector : 'carousel-slide' , host : { '[class.item]' : '_itemClass' , '[class.active]' : '_activeClass' , '[class.left]' : '_leftClass' , '[class.right]' : '_rightClass' , '[class.prev]' : '_prevClass' , '[class.next]' : '_nextClass' , 'role' : 'listbox' } } ) export class CarouselSlide { private _el : HTMLElement ; private _itemClass : boolean = true ; private _activeClass : boolean ; private _leftClass : boolean ; private _rightClass : boolean ; private _prevClass : boolean ; private _nextClass : boolean ; constructor ( el ) { this . _el = el . nativeElement ; } getElement ( ) { return this . _el ; } activate ( ) { this . _activeClass = true ; } deactivate ( ) { this . _activeClass = false ; } prepareAnimation ( isToRight ) { isToRight ? this . _nextClass = true : this . _prevClass = true ; } animate ( isToRight ) { isToRight ? this . _leftClass = true : this . _rightClass = true ; } cleanAfterAnimation ( ) { this . _leftClass = this . _rightClass = this . _nextClass = this . _prevClass = false ; } } @ Directive ( { selector : 'carousel-caption' , host : { '[class.carousel-caption]' : 'carouselCaptionClass' } } ) export class CarouselCaption { private carouselCaptionClass : boolean = true ; } @ Component ( { selector : 'carousel' , properties : [ 'index' , 'wrap' , 'interval' , 'pause' , 'noTransition: no-transition' ] , host : { '(mouseenter)' : 'toggleAutomaticSliding()' , '(mouseleave)' : 'toggleAutomaticSliding()' } , events : [ 'indexchange' , 'slidestart' , 'slideend' ] , templateUrl : './carousel/carousel.html' , directives : [ NgFor , NgIf ] } ) export class Carousel { pause : string = "hover" ; private indexchange : EventEmitter = new EventEmitter ( ) ; private slidestart : EventEmitter = new EventEmitter ( ) ; private slideend : EventEmitter = new EventEmitter ( ) ; private _el : ElementRef ; private _activeIndex : number = - 1 ; private _interval : number = 5000 ; private _isChangingSlide : boolean = false ; private _isToRight : boolean = true ; private _noTransition : boolean = false ; private _query : QueryList < CarouselSlide > ; private _slides : Array < CarouselSlide > = [ ] ; private _timerId : number = null ; private _transitionEnd : string = getTransitionEnd ( ) ; private _wrap : boolean = true ; constructor ( @ Query ( CarouselSlide ) query , el ) { this . _el = el ; this . _startCycling ( ) ; ( < any > query . changes ) . toRx ( ) . subscribe ( _ => this . _registerSlides ( query ) ) ; } private _registerSlides ( query ) { var activeSlide = this . _slides [ this . _activeIndex ] ; this . _slides = [ ] ; var activationDone = false ; query . map ( ( slide ) => { slide . deactivate ( ) ; slide . cleanAfterAnimation ( ) ; if ( slide === activeSlide || ( typeof activeSlide === "undefined" && this . _activeIndex == this . _slides . length ) ) { slide . activate ( ) ; if ( this . _activeIndex !== this . _slides . length ) { if ( typeof this . _activeIndex != "string" ) { this . indexchange . next ( this . _slides . length ) ; } this . _activeIndex = this . _slides . length ; } activationDone = true ; } this . _slides . push ( slide ) ; } ) ; if ( ! activationDone && this . _slides [ 0 ] ) { this . _slides [ 0 ] . activate ( ) ; this . _activeIndex = 0 ; this . indexchange . next ( this . _activeIndex ) ; } this . _isChangingSlide = false ; this . _isToRight = null ; } set wrap ( newValue ) { this . _wrap = typeof newValue === "string" ? newValue != "false" : newValue ; } set noTransition ( newValue ) { this . _noTransition = typeof newValue === "string" ? newValue != "false" : newValue ; } set interval ( newValue ) { this . _interval = typeof newValue === "string" ? parseInt ( newValue ) : newValue ; this . _stopCycling ( ) ; this . _startCycling ( ) ; } set index ( newValue ) { if ( ! this . _isChangingSlide && newValue != this . _activeIndex && newValue >= 0 && newValue <= this . _slides . length - 1 ) { this . _isChangingSlide = true ; if ( this . _isToRight == null ) { this . _isToRight = newValue > this . _activeIndex ; } this . slidestart . next ( null ) ; var currentSlide = this . _slides [ this . _activeIndex ] ; var nextSlide = this . _slides [ newValue ] ; if ( ! this . _noTransition && this . _transitionEnd && currentSlide ) { nextSlide . prepareAnimation ( this . _isToRight ) ; setTimeout ( ( ) => { currentSlide . animate ( this . _isToRight ) ; nextSlide . animate ( this . _isToRight ) ; var endAnimationCallback = ( event ) => { currentSlide . getElement ( ) . removeEventListener ( this . _transitionEnd , endAnimationCallback , false ) ; this . _finalizeTransition ( currentSlide , nextSlide , newValue ) ; } ; currentSlide . getElement ( ) . addEventListener ( this . _transitionEnd , endAnimationCallback , false ) ; } , 30 ) ; } else { this . _finalizeTransition ( currentSlide , nextSlide , newValue ) ; } } else if ( this . _activeIndex == - 1 ) { this . _finalizeTransition ( null , null , newValue ) ; ( < any > this . _el ) . parentView . _view . changeDetector . detectChanges ( ) ; } } private _finalizeTransition ( currentSlide , nextSlide , newValue ) { if ( currentSlide ) { currentSlide . deactivate ( ) ; currentSlide . cleanAfterAnimation ( ) ; } if ( nextSlide ) { nextSlide . activate ( ) ; nextSlide . cleanAfterAnimation ( ) ; } this . _activeIndex = newValue ; this . _isChangingSlide = false ; this . _isToRight = null ; if ( currentSlide || nextSlide ) { this . slideend . next ( null ) ; this . indexchange . next ( this . _activeIndex ) ; } } navigateTo ( newIndex ) { this . index = newIndex ; } prev ( ) { if ( this . hasPrev ( ) ) { var prevIndex = this . _activeIndex - 1 < 0 ? this . _slides . length - 1 : this . _activeIndex - 1 ; this . _isToRight = false ; this . index = prevIndex ; } } next ( ) { if ( this . hasNext ( ) ) { var nextIndex = ( this . _activeIndex + 1 ) % this . _slides . length ; this . _isToRight = true ; this . index = nextIndex ; } } hasPrev ( ) { return this . _slides . length > 1 && ! ( ! this . _wrap && this . _activeIndex === 0 ) ; } hasNext ( ) { return this . _slides . length > 1 && ! ( ! this . _wrap && this . _activeIndex === ( this . _slides . length - 1 ) ) ; } toggleAutomaticSliding ( ) { if ( this . pause === "hover" ) { if ( this . _timerId ) { this . _stopCycling ( ) ; } else { this . _startCycling ( ) ; } } } private _startCycling ( ) { if ( this . _interval >= 0 ) { this . _timerId = setInterval ( ( ) => { this . next ( ) ; } , this . _interval > 600 ? this . _interval : 600 ) ; } } private _stopCycling ( ) { if ( this . _timerId ) { clearInterval ( this . _timerId ) ; } this . _timerId = null ; } } function getTransitionEnd ( ) { var el = document . createElement ( 'angular2-bootstrap' ) ; var transEndEventNames = { WebkitTransition : 'webkitTransitionEnd' , MozTransition : 'transitionend' , OTransition : 'oTransitionEnd otransitionend' , transition : 'transitionend' } ; for ( var name in transEndEventNames ) { if ( el . style [ name ] !== undefined ) { return transEndEventNames [ name ] ; } } return null ; }