NoctisHsu
10/20/2015 - 6:01 AM

carouselDirective.ts

/// <reference path="../../Scripts/typings/angularjs/angular.d.ts"/>
/// <reference path="../../TypeScripts/Services/layoutTemplateDataService.ts"/>
module NineYi.Mall.Directives {
    interface ICarouselDirectiveScope extends ng.IScope {
        slides:NineYi.WebStore.Frontend.BE.LayoutTemplateData.AdDisplayEntity[];
        // 使用循環輪播
        useCycle:boolean;
        // 是否使用自動播放
        autoPlay:boolean;
        // 自動播放下一張的間隔
        autoPlayInterval:number;
        // 輪播元件高度
        slideHeight:number;
        // 輪播項目數量
        slidesNum:number;
        // 當前輪播項目
        currentSlide:number;
        // 觸發輪播
        changeSlide:(targetSilde:number)=>void;
        // 下一張輪播
        goNext:()=>void;
        // 上一張輪播
        goPrev:()=>void;
        // 初始化元件內容
        initSlide:()=>void;
        // callback function
        callBack:()=>void;
        // 自動輪播
        autoChangeSlide:()=>void;
        // 開始自動輪播
        autoPlayStart:()=>void;
        // 停止自動輪播
        autoPlayStop:()=>void;
        // 重置輪播間隔
        resetInterval:()=>void;
        // 是否正在執行自動輪播
        isAutoPlaying:boolean;

        firstSlide:NineYi.WebStore.Frontend.BE.LayoutTemplateData.AdDisplayEntity;

        lastSlide:NineYi.WebStore.Frontend.BE.LayoutTemplateData.AdDisplayEntity;
    }

    /**
     * @ngdoc Directive
     * @name CarouselDirective
     * @description 輪播元件
     */
    export class CarouselDirective implements ng.IDirective {

        static factory() {
            var directive = ($interval:ng.IIntervalService, $windows:ng.IWindowService, $swipe) =>
                new CarouselDirective($interval, $windows, $swipe);
            directive.$inject = ['$interval', '$window', '$swipe'];
            return directive;
        }

        public restrict = 'AE';
        public scope = {
            slides: '=',
            slideHeight: '=',
            callBack: '&',
            autoPlay: '@',
            autoPlayInterval: '@',
            targetSlide: '='
        };
        public transclude = true;
        public templateUrl = '/V2/TypeScripts/Components/carousel.html';
        public link:(scope:ICarouselDirectiveScope, element:ng.IAugmentedJQuery, attrs:ng.IAttributes) => void;

        constructor(private $interval:ng.IIntervalService,
                    private $window:ng.IWindowService,
                    private $swipe) {

            this.link = ($scope:ICarouselDirectiveScope, element:ng.IAugmentedJQuery) => {

                var el = element[0];
                var containerEl = el.getElementsByTagName("ul")[0];

                var slidesWatcherDisposer = $scope.$watch('slides', function (newVal, oldVal) {
                    if (newVal && newVal !== oldVal) {
                        $scope.firstSlide = $scope.slides[0];
                        $scope.lastSlide = $scope.slides[$scope.slides.length - 1];
                        $scope.initSlide();
                        // 自動輪播開啟且輪播項目大於1張
                        if ($scope.autoPlay && $scope.slidesNum > 1) {
                            $scope.isAutoPlaying = false;
                            $scope.autoPlayStart();
                            var stopOffsetHeight = el.getBoundingClientRect().top + $scope.slideHeight;//取得輪播的offset高度
                            angular.element($window).bind("scroll", function () {
                                if (pageYOffset > stopOffsetHeight) { // 當scroll over 輪播元件,則停止自動輪播
                                    $scope.autoPlayStop();
                                }
                                else {
                                    $scope.autoPlayStart();
                                }
                            });
                        }
                        slidesWatcherDisposer()
                    }
                });

                var slideHeightWatcherDisposer = $scope.$watch('slideHeight', function (newVal, oldVal) {
                    if (newVal && newVal !== oldVal) {
                        $scope.slideHeight = newVal;
                        slideHeightWatcherDisposer();
                    }
                });

                $scope.autoChangeSlide = function () {
                    $scope.changeSlide($scope.currentSlide + 1);
                };

                $scope.changeSlide = function (targetSilde:number) {

                    $scope.currentSlide = targetSilde;

                    if (targetSilde > $scope.slidesNum) { //大於總張數,設為第一張執行循環
                        $scope.currentSlide = 1;
                    }
                    else if (targetSilde < 1) { //小於1張,設為最後一張執行循環
                        $scope.currentSlide = $scope.slidesNum;
                    }
                    else {
                        $scope.currentSlide = targetSilde;
                    }

                    if ($scope.currentSlide <= $scope.slidesNum && $scope.currentSlide > 0) {
                        if ($scope.currentSlide === $scope.slidesNum) {
                            containerEl.classList.remove('show-transition');
                            containerEl.classList.add('hide-transition');
                            
                            var translateSetting = 'translate3d(0px, 0px, 0px)';
                            containerEl.style.transform = translateSetting;
                            containerEl.style["-webkit-transform"] = translateSetting;
                            containerEl.style["-moz-transform"] = translateSetting;
                            containerEl.style["-o-transform"] = translateSetting;
                            containerEl.style["-ms-transform"] = translateSetting;

                            containerEl.classList.remove('hide-transition');
                            containerEl.classList.add('show-transition');

                            var diff = (-1 * 100 * (2)) / $scope.slidesNum + '%';
                            var translateSetting2 = 'translate3d(' + diff + ', 0px, 0px)';
                            containerEl.style.transform = translateSetting2;
                            containerEl.style["-webkit-transform"] = translateSetting2;
                            containerEl.style["-moz-transform"] = translateSetting2;
                            containerEl.style["-o-transform"] = translateSetting2;
                            containerEl.style["-ms-transform"] = translateSetting2;

                        }
                        else {

                            if ($scope.currentSlide === 1) {
                                // 當前為假的第一張輪播

                            }

                            containerEl.classList.remove('hide-transition');
                            containerEl.classList.add('show-transition');

                            var diff = (-1 * 100 * ($scope.currentSlide - 1)) / $scope.slidesNum + '%';
                            var translateSetting = 'translate3d(' + diff + ', 0px, 0px)';
                            containerEl.style.transform = translateSetting;
                            containerEl.style["-webkit-transform"] = translateSetting;
                            containerEl.style["-moz-transform"] = translateSetting;
                            containerEl.style["-o-transform"] = translateSetting;
                            containerEl.style["-ms-transform"] = translateSetting;
                        }

                    }

                };

                $scope.goNext = function () {
                    $scope.resetInterval();
                    $scope.changeSlide($scope.currentSlide + 1);
                };

                $scope.goPrev = function () {
                    $scope.resetInterval();
                    $scope.changeSlide($scope.currentSlide - 1);
                };

                $scope.initSlide = function () {
                    var slidesEl = containerEl.getElementsByTagName("li");

                    $scope.slidesNum = slidesEl.length;

                    el.style.position = 'relative';
                    el.style.overflow = 'hidden';

                    containerEl.style.position = 'relative';

                    containerEl.style.width = ($scope.slidesNum * 100) + '%';
                    containerEl.style.listStyleType = 'none';
                    containerEl.style.margin = '0';
                    containerEl.style.padding = '0';
                    containerEl.style.transitionDuration = '0.6s';

                    for (var i = 0; i < $scope.slidesNum; i++) {
                        var slideEl = slidesEl[i];
                        slideEl.style.display = 'inline-block';
                        slideEl.style.width = (100 / $scope.slidesNum) + '%';

                    }
                    $scope.changeSlide(2);
                };

                var autoPlayPromise:ng.IPromise<any>;

                $scope.autoPlayStop = function () {
                    if ($scope.isAutoPlaying) {
                        $interval.cancel(autoPlayPromise);
                        $scope.isAutoPlaying = false;
                    }
                };

                var autoPlayInterval = $scope.autoPlayInterval ? $scope.autoPlayInterval : 5000; //設定輪播間隔時間

                $scope.autoPlayStart = function () {
                    if (!$scope.isAutoPlaying) {
                        $scope.isAutoPlaying = true;
                    }
                    else {
                        // 先停止在開始輪播,避免同時執行多個interval
                        $scope.autoPlayStop();
                    }
                    autoPlayPromise = $interval($scope.autoChangeSlide, autoPlayInterval);

                };

                $scope.resetInterval = function () {
                    // scope.autoPlayStop();
                    //scope.autoPlayStart();
                };

                element.on('$destroy', function () {
                    $interval.cancel(autoPlayPromise);
                });

                element.bind('touchstart', function () {
                    $scope.resetInterval();
                });
            }
        }
    }


    angular.module('NineYi.Mall.Directives').directive('nsCarousel', CarouselDirective.factory());
}