<!DOCTYPE html>
<html ng-app="myApp">
<head>
<script data-require="angular.js@*" data-semver="1.5.0" src="https://ajax.googleapis.com/ajax/libs/angularjs/1.5.0/angular.js"></script>
<script src="https://code.angularjs.org/1.5.0/angular-animate.min.js"></script>
<script src="https://code.angularjs.org/1.5.0/angular-aria.min.js"></script>
<script src="https://ajax.googleapis.com/ajax/libs/angular_material/1.0.5/angular-material.min.js"></script>
<link rel="stylesheet" href="https://ajax.googleapis.com/ajax/libs/angular_material/1.0.5/angular-material.min.css" />
<link href="https://fonts.googleapis.com/icon?family=Material+Icons" rel="stylesheet">
<link rel="stylesheet" href="jk-carousel.min.css" />
<link rel="stylesheet" href="style.css" />
<script src="jk-carousel.min.js"></script>
<script src="app.js"></script>
</head>
<body ng-controller="MyCtrl">
<md-card layout="column" layout-align="center center" style="padding-bottom: 10px">
<h3>Basic Carousel setup</h3>
<jk-carousel data="dataArray" item-template-url="'item-template.html'" max-width="800" max-height="500">
</jk-carousel>
</md-card>
<md-card layout="column" layout-align="center center" style="padding-bottom: 10px">
<h3>AutoSlide Carousel</h3>
<jk-carousel data="dataArray" item-template-url="'item-template.html'" max-width="800" max-height="500" auto-slide="true" auto-slide-time="2000">
</jk-carousel>
</md-card>
</body>
</html>
# Angular Material Carousel
[jQuery2DotNet](http://www.jquery2dotnet.com/)
// Code goes here
angular.module('myApp', ['ngMaterial', 'jkAngularCarousel'])
.controller('MyCtrl', function($scope) {
$scope.dataArray = [
{
src: 'http://lorempixel.com/960/720/city/'
},
{
src: 'http://lorempixel.com/960/720/animals/'
},
{
src: 'http://lorempixel.com/960/720/transport/'
},
{
src: 'http://lorempixel.com/960/720/nightlife/'
},
{
src: 'http://lorempixel.com/960/720/nature/'
},
{
src: 'http://lorempixel.com/960/720/fashion/'
},
{
src: 'http://lorempixel.com/960/720/food/'
},
{
src: 'http://lorempixel.com/960/720/technics/'
}
];
});
body {
padding: 20px;
}
md-card {
margin: auto;
left: 0;
right: 0;
margin-bottom: 20px;
}
<div>
<img ng-src="{{slideItem.src}}" >
</div>
.jk-carousel {
height: 100%;
overflow: hidden;
position: relative; }
.jk-carousel .slides-container {
height: 100%;
position: relative; }
.jk-carousel .slides-container .slide .ng-scope img:first-child {
max-width: 100%;
max-height: 100%; }
.jk-carousel .left-arrow-button,
.jk-carousel .right-arrow-button {
position: absolute;
margin: auto !important;
top: 0;
bottom: 0; }
.jk-carousel .right-arrow-button {
right: 0; }
.jk-carousel .md-icon-button {
width: 48px;
height: 48px;
margin: 0;
padding: 0; }
.jk-carousel .md-icon-button md-icon {
color: #ffffff;
width: 48px;
height: 48px;
font-size: 48px;
cursor: pointer;
outline: none !important; }
.jk-carousel .radio-buttons-container {
position: absolute;
bottom: 0;
margin-bottom: 20px;
width: 100%; }
.jk-carousel .radio-buttons-container md-radio-button {
margin-right: 5px;
outline: none; }
.jk-carousel .radio-buttons-container md-radio-button .md-off {
border-color: #ffffff; }
(function() {
'use strict';
angular.module('jkAngularCarousel', [
'jkAngularCarousel.templates'
]);
}());
(function() {
'use strict';
function CarouselController($timeout, $attrs, $interval, $window) {
var that = this;
that.currentIndex = 0;
that.currentMarginLeftValue = 0;
that.radioButtonIndex = 0;
that.transitionsTime = 500;
that.transitionsEnabled = true;
$attrs.$observe('data', function() {
that.onDataChange();
});
that.registerElement = function(element) {
that.element = element;
that.elementParent = that.element.parent();
that.slidesContainer = angular.element(that.element.find('div')[0]);
$window.addEventListener('resize', function() {
that.updateSlidesContainerWidth();
});
};
that.onDataChange = function() {
if (that.isDataInvalidOrTooSmall()) {
return;
}
that.executeCloneData();
$timeout(function() {
that.updateSlidesContainerWidth();
that.restartFromFirstItem();
});
};
that.updateSlidesContainerWidth = function() {
that.scaleContent();
that.currentWidth = that.element.prop('offsetWidth');
that.currentHeight = that.element.prop('offsetHeight');
that.resizeSlides();
var newSlidesContainerWidth = that.currentWidth * that.cloneData.length;
that.slidesContainer.css('width', newSlidesContainerWidth + 'px');
that.scaleMarginLeft(newSlidesContainerWidth);
that.currentSlidesContainerWidth = newSlidesContainerWidth;
};
that.scaleContent = function() {
that.maxWidth = that.maxWidth ? parseInt(that.maxWidth): 0;
if( that.maxWidth === 0 ){
that.maxWidth = that.element.prop('offsetWidth');
}
that.maxHeight = that.maxHeight ? parseInt(that.maxHeight): 0;
if( that.maxHeight === 0 ){
that.maxHeight = that.element.prop('offsetHeight');
}
var currentElementParentWidth = that.elementParent.prop('offsetWidth');
if( currentElementParentWidth < that.maxWidth ){
console.log(currentElementParentWidth, that.maxWidth);
var newHeight = (that.maxHeight * currentElementParentWidth) / that.maxWidth;
that.element.css('width', currentElementParentWidth + 'px');
that.element.css('height', newHeight + 'px');
}else if( currentElementParentWidth >= that.maxWidth ){
that.element.css('width', that.maxWidth + 'px');
that.element.css('height', that.maxHeight + 'px');
}
};
that.resizeSlides = function(){
var slides = $window.document.getElementsByClassName('slide');
for( var index=0; index < slides.length; index++ ){
var slide = angular.element(slides[index]);
slide.css('width', that.currentWidth + 'px');
slide.css('height', that.currentHeight + 'px');
}
};
that.scaleMarginLeft = function(newSlidesContainerWidth){
if(
that.currentSlidesContainerWidth &&
that.currentSlidesContainerWidth !== newSlidesContainerWidth
){
that.currentMarginLeftValue = that.currentMarginLeftValue * newSlidesContainerWidth;
that.currentMarginLeftValue = that.currentMarginLeftValue / that.currentSlidesContainerWidth;
that.disableTransitions();
that.applyMarginLeft();
that.enableTransitions();
}
};
that.restartFromFirstItem = function() {
if (!that.currentWidth) {
return;
}
that.disableTransitions();
that.currentMarginLeftValue = that.currentWidth * -1;
that.applyMarginLeft();
that.currentIndex = 0;
that.radioButtonIndex = that.currentIndex;
that.enableTransitions();
};
that.executeCloneData = function() {
var cloneArray = [];
for (var index = 0; index < that.data.length; index++) {
var item = that.data[index];
cloneArray.push(item);
}
that.cloneFirstItem(cloneArray);
that.cloneLastItem(cloneArray);
that.cloneData = cloneArray;
};
that.cloneFirstItem = function(cloneArray) {
var firstItem = cloneArray[0];
var firstItemClone = angular.copy(firstItem);
cloneArray.push(firstItemClone);
};
that.cloneLastItem = function(cloneArray) {
var lastItem = cloneArray[that.data.length - 1];
var lastItemClone = angular.copy(lastItem);
cloneArray.unshift(lastItemClone);
};
that.validateAutoSlide = function() {
if (!that.autoSlide) {
that.stopAutoSlide();
} else {
that.startAutoSlide();
}
};
that.restartAutoSlide = function() {
if (!that.autoSlide) {
return;
}
if (that.transitionsEnabled) {
$timeout(function() {
that.stopAutoSlide();
that.startAutoSlide();
}, that.transitionsTime);
} else {
that.stopAutoSlide();
that.startAutoSlide();
}
};
that.startAutoSlide = function() {
if (!angular.isDefined(that.autoSlideInterval)) {
that.autoSlideInterval = $interval(function() {
that.navigateRight();
}, that.autoSlideTime);
}
};
that.stopAutoSlide = function() {
if (angular.isDefined(that.autoSlideInterval)) {
$interval.cancel(that.autoSlideInterval);
that.autoSlideInterval = undefined;
}
};
that.onNavigateLeft = function() {
that.navigateLeft();
that.restartAutoSlide();
};
that.navigateLeft = function() {
if (that.isDataInvalidOrTooSmall()) {
return;
}
that.currentIndex--;
that.radioButtonIndex = that.currentIndex;
that.currentMarginLeftValue += that.currentWidth;
that.applyMarginLeft();
that.restartAutoSlide();
if (that.currentIndex === -1) {
that.restartFromLastItem();
}
};
that.restartFromLastItem = function() {
$timeout(function() {
that.disableTransitions();
that.currentMarginLeftValue = (that.currentWidth * that.data.length) * -1;
that.applyMarginLeft();
that.currentIndex = that.data.length - 1;
that.radioButtonIndex = that.currentIndex;
that.enableTransitions();
}, that.transitionsTime);
};
that.onNavigateRight = function() {
that.navigateRight();
that.restartAutoSlide();
};
that.navigateRight = function() {
if (that.isDataInvalidOrTooSmall()) {
return;
}
that.currentIndex++;
that.radioButtonIndex = that.currentIndex;
that.currentMarginLeftValue -= that.currentWidth;
that.applyMarginLeft();
that.restartAutoSlide();
if (that.currentIndex === that.data.length) {
$timeout(function() {
that.restartFromFirstItem();
}, that.transitionsTime);
}
};
that.applyMarginLeft = function() {
that.slidesContainer.css('margin-left', that.currentMarginLeftValue + 'px');
};
that.disableTransitions = function() {
that.slidesContainer.css('transition', 'none');
that.transitionsEnabled = false;
};
that.enableTransitions = function() {
$timeout(function() {
that.slidesContainer.css('transition', 'margin 0.5s ease-in-out');
that.transitionsEnabled = true;
}, 200);
};
that.onRadioButtonClick = function() {
var multiplier;
if (that.radioButtonIndex > that.currentIndex) {
multiplier = that.radioButtonIndex - that.currentIndex;
that.currentMarginLeftValue -= (that.currentWidth * multiplier);
} else {
multiplier = that.currentIndex - that.radioButtonIndex;
that.currentMarginLeftValue += (that.currentWidth * multiplier);
}
that.currentIndex = that.radioButtonIndex;
that.applyMarginLeft();
that.restartAutoSlide();
};
that.isDataInvalidOrTooSmall = function() {
if (!that.data || that.data.length === 0) {
return true;
}
return false;
};
}
angular
.module('jkAngularCarousel')
.controller('JKCarouselController', [
'$timeout', '$attrs', '$interval', '$window',
CarouselController
]);
}());
(function() {
'use strict';
function CarouselDirective() {
function link(scope, element, attrs, ctrl) {
if (attrs.autoSlide === undefined) {
ctrl.autoSlide = false;
}
if (attrs.autoSlideTime === undefined) {
ctrl.autoSlideTime = 5000;
}
ctrl.registerElement(element);
scope.$on('$destroy', function() {
ctrl.stopAutoSlide();
});
scope.$watch('ctrl.autoSlide', function() {
ctrl.validateAutoSlide();
});
scope.$watch('ctrl.autoSlideTime', function() {
ctrl.restartAutoSlide();
});
}
return {
restrict: 'E',
replace: true,
templateUrl: 'carousel-directive.html',
scope: {},
controller: 'JKCarouselController',
controllerAs: 'ctrl',
bindToController: {
data: '=',
itemTemplateUrl: '=',
maxWidth: '@?',
maxHeight: '@?',
autoSlide: '@?',
autoSlideTime: '@?'
},
link: link
};
}
angular
.module('jkAngularCarousel')
.directive('jkCarousel', [
CarouselDirective
]);
}());
(function(){angular.module("jkAngularCarousel.templates", []).run(["$templateCache", function($templateCache) {$templateCache.put("carousel-directive.html","<div class=\"jk-carousel\" >\n\n <div class=\"slides-container\" layout=\"row\" >\n <div\n ng-repeat=\"slideItem in ctrl.cloneData\"\n class=\"slide\"\n >\n <div ng-include=\"ctrl.itemTemplateUrl\" ></div>\n </div>\n </div>\n\n <md-button class=\"md-icon-button left-arrow-button\" >\n <md-icon ng-click=\"ctrl.navigateLeft()\" >chevron_left</md-icon>\n </md-button>\n\n <md-button class=\"md-icon-button right-arrow-button\" >\n <md-icon ng-click=\"ctrl.navigateRight()\" >chevron_right</md-icon>\n </md-button>\n\n <md-radio-group\n class=\"radio-buttons-container\"\n layout=\"row\"\n ng-model=\"ctrl.radioButtonIndex\"\n layout-align=\"center center\"\n ng-change=\"ctrl.onRadioButtonClick()\" >\n <md-radio-button\n ng-repeat=\"item in ctrl.data\"\n ng-value=\"$index\"\n aria-label=\"$index\" >\n </md-radio-button>\n </md-radio-group>\n\n</div>\n");}]);})();