/// <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());
}