/*-
* ============LICENSE_START=======================================================
* SDC
* ================================================================================
* Copyright (C) 2017 AT&T Intellectual Property. All rights reserved.
* ================================================================================
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
* ============LICENSE_END=========================================================
*/
///
module Sdc.Directives {
'use strict';
export interface SlideData {
url: string;
id: string;
index: number;
callback: Function;
}
export interface ISdcPageScrollDirectiveScope extends ng.IScope {
slidesData:Array;
showNav: boolean;
showPreviousNext: boolean;
currentSlide:SlideData;
showCloseButton:boolean;
closeButtonCallback:Function;
startSlideIndex:number;
onNavButtonClick(slideName):void;
onCloseButtonClick():void;
goToPrevSlide():void;
goToNextSlide():void;
goToSlide(slide:SlideData):void;
onSlideChangeEnd():void;
onMouseWheel(event):void;
onKeyDown(event):void;
onResize(event):void;
gotoSlideIndex(index):void;
}
export class SdcPageScrollDirective implements ng.IDirective {
constructor(private $templateCache:ng.ITemplateCacheService) {
}
scope = {
slidesData: '=',
showNav: '=',
showPreviousNext: '=',
showCloseButton: '=',
closeButtonCallback: '=',
startSlideIndex: '=?'
};
public replace = true;
public restrict = 'E';
private delayExec:any;
template = ():string => {
return this.$templateCache.get('/app/scripts/directives/page-scroller/page-scroller.html');
};
link = ($scope:ISdcPageScrollDirectiveScope, $elem:JQuery, attr:any) => {
let isAnimating = false; //Animating flag - is our app animating
let pageHeight = $(window).innerHeight(); //The height of the window
let slidesContainer;
let navButtons;
let slides:any; //Only graph-links that starts with
//Key codes for up and down arrows on keyboard. We'll be using this to navigate change slides using the keyboard
let keyCodes = {
UP : 38,
DOWN: 40
};
$scope.onCloseButtonClick = ():void => {
if ($scope.closeButtonCallback){
$scope.closeButtonCallback();
};
};
// Wait for the dom to load (after ngRepeat).
$scope.$on('onRepeatLast', (scope, element, attrs) => {
slides = $(".slide", slidesContainer);
slidesContainer = $(".slides-container");
navButtons = $("nav a").filter("[href^='#']");
// Adding event listeners
$(window).on("resize", (e) => {$scope.onResize(e);}).resize();
$(window).on("mousewheel DOMMouseScroll", (e) => {$scope.onMouseWheel(e);});
$(document).on("keydown", (e) => {$scope.onKeyDown(e);});
//Going to the first slide
if ($scope.startSlideIndex){
$scope.gotoSlideIndex($scope.startSlideIndex);
} else {
$scope.gotoSlideIndex(0);
}
});
$scope.gotoSlideIndex = (index) => {
$scope.goToSlide($scope.slidesData[index]);
};
// When a button is clicked - first get the button href, and then slide to the container, if there's such a container
$scope.onNavButtonClick = (slide:SlideData):void => {
$scope.goToSlide(slide);
};
// If there's a previous slide, slide to it
$scope.goToPrevSlide = ():void => {
let previousSlide = $scope.slidesData[$scope.currentSlide.index-1];
if (previousSlide) {
$scope.goToSlide(previousSlide);
}
};
// If there's a next slide, slide to it
$scope.goToNextSlide = ():void => {
let nextSlide = $scope.slidesData[$scope.currentSlide.index+1];
if (nextSlide) {
$scope.goToSlide(nextSlide);
}
};
// Actual transition between slides
$scope.goToSlide = (slide:SlideData):void => {
//console.log("start goToSlide");
//If the slides are not changing and there's such a slide
if(!isAnimating && slide) {
//setting animating flag to true
isAnimating = true;
$scope.currentSlide = slide;
$scope.currentSlide.callback();
//Sliding to current slide
let calculatedY = pageHeight * ($scope.currentSlide.index);
//console.log("$scope.currentSlide.index: " + $scope.currentSlide.index + " | calculatedY: " + calculatedY);
$('.slides-container').animate(
{
scrollTop: calculatedY + 'px'
},
{
duration: 1000,
specialEasing: {
width: "linear",
height: "easeInOutQuart"
},
complete: function() {
$scope.onSlideChangeEnd();
}
}
);
//Animating menu items
$(".sdc-page-scroller nav a.active").removeClass("active");
$(".sdc-page-scroller nav [href='#" + $scope.currentSlide.id + "']").addClass("active");
}
};
// Once the sliding is finished, we need to restore "isAnimating" flag.
// You can also do other things in this function, such as changing page title
$scope.onSlideChangeEnd = ():void => {
isAnimating = false;
};
// When user scrolls with the mouse, we have to change slides
$scope.onMouseWheel = (event):void => {
//Normalize event wheel delta
let delta = event.originalEvent.wheelDelta / 30 || -event.originalEvent.detail;
//If the user scrolled up, it goes to previous slide, otherwise - to next slide
if(delta < -1) {
this.delayAction($scope.goToNextSlide);
} else if(delta > 1) {
this.delayAction($scope.goToPrevSlide);
}
event.preventDefault();
};
// Getting the pressed key. Only if it's up or down arrow, we go to prev or next slide and prevent default behaviour
// This way, if there's text input, the user is still able to fill it
$scope.onKeyDown = (event):void => {
let PRESSED_KEY = event.keyCode;
if(PRESSED_KEY == keyCodes.UP){
$scope.goToPrevSlide();
event.preventDefault();
} else if(PRESSED_KEY == keyCodes.DOWN){
$scope.goToNextSlide();
event.preventDefault();
}
};
// When user resize it's browser we need to know the new height, so we can properly align the current slide
$scope.onResize = (event):void => {
//This will give us the new height of the window
let newPageHeight = $(window).innerHeight();
// If the new height is different from the old height ( the browser is resized vertically ), the slides are resized
if(pageHeight !== newPageHeight) {
pageHeight = newPageHeight;
}
};
};
private initSlides = ():void => {
//pageHeight
};
private delayAction = (action:Function):void => {
clearTimeout(this.delayExec);
this.delayExec = setTimeout(function () {
action();
}, 100);
};
public static factory = ($templateCache:ng.ITemplateCacheService)=> {
return new SdcPageScrollDirective($templateCache);
};
}
SdcPageScrollDirective.factory.$inject = ['$templateCache'];
}