var app = angular.module('plunker', ['ngAnimate']);
app.controller('MainCtrl', function($scope) {
$scope.a = [1, 2, 3];
$scope.b = [4, 5, 6];
$scope.start = function() {
$scope.b.push($scope.a.shift());
$scope.a.push($scope.b.shift());
}
});
<!DOCTYPE html>
<html ng-app="plunker">
<head>
<meta charset="utf-8" />
<title>AngularJS Plunker</title>
<link rel="stylesheet" href="style.css" />
<script src="https://code.angularjs.org/1.5.5/angular.min.js"></script>
<script src="https://code.angularjs.org/1.5.5/angular-animate.min.js"></script>
<script src="app.js"></script>
</head>
<body ng-controller="MainCtrl">
<div class="animated row" ng-repeat="i in a track by i" ng-animate-ref="item-{{i}}">{{i}}</div>
<br>
<div class="animated row" ng-repeat="i in b track by i" ng-animate-ref="item-{{i}}">{{i}}</div>
<a href="javascript:;" ng-click="start()">Start</a>
</body>
</html>
/* Put your css in here */
.row.ng-leave {
transition: 0.2s linear all;
}
.row.ng-anchor-in-add {
transition: 0.5s linear all;
}
/*
* angular-ui-bootstrap
* http://angular-ui.github.io/bootstrap/
* Version: 1.0.0-SNAPSHOT - 2015-10-26
* License: MIT
*/
angular.module("ui.bootstrap", ["ui.bootstrap.tpls","ui.bootstrap.carousel"]);
angular.module("ui.bootstrap.tpls", ["template/carousel/carousel.html","template/carousel/slide.html"]);
angular.module('ui.bootstrap.carousel', [])
.controller('UibCarouselController', ['$scope', '$element', '$interval', '$animate', function($scope, $element, $interval, $animate) {
var self = this,
slides = self.slides = $scope.slides = [],
NEW_ANIMATE = angular.version.minor >= 4,
SLIDE_DIRECTION = 'uib-slideDirection',
currentIndex = -1,
currentInterval, isPlaying;
self.currentSlide = null;
var destroyed = false;
/* direction: "prev" or "next" */
self.select = $scope.select = function(nextSlide, direction) {
var nextIndex = $scope.indexOfSlide(nextSlide);
//Decide direction if it's not given
if (direction === undefined) {
direction = nextIndex > self.getCurrentIndex() ? 'next' : 'prev';
}
//Prevent this user-triggered transition from occurring if there is already one in progress
if (nextSlide && nextSlide !== self.currentSlide && !$scope.$currentTransition) {
goNext(nextSlide, nextIndex, direction);
}
};
function goNext(slide, index, direction) {
// Scope has been destroyed, stop here.
if (destroyed) { return; }
angular.extend(slide, {direction: direction, active: true});
angular.extend(self.currentSlide || {}, {direction: direction, active: false});
if ($animate.enabled() && !$scope.noTransition && !$scope.$currentTransition &&
slide.$element && self.slides.length > 1) {
slide.$element.data(SLIDE_DIRECTION, slide.direction);
if (self.currentSlide && self.currentSlide.$element) {
self.currentSlide.$element.data(SLIDE_DIRECTION, slide.direction);
}
$scope.$currentTransition = true;
if (NEW_ANIMATE) {
$animate.on('addClass', slide.$element, function(element, phase) {
if (phase === 'close') {
$scope.$currentTransition = null;
$animate.off('addClass', element);
}
});
} else {
slide.$element.one('$animate:close', function closeFn() {
$scope.$currentTransition = null;
});
}
}
self.currentSlide = slide;
currentIndex = index;
//every time you change slides, reset the timer
restartTimer();
}
$scope.$on('$destroy', function() {
destroyed = true;
});
function getSlideByIndex(index) {
if (angular.isUndefined(slides[index].index)) {
return slides[index];
}
var i, len = slides.length;
for (i = 0; i < slides.length; ++i) {
if (slides[i].index == index) {
return slides[i];
}
}
}
self.getCurrentIndex = function() {
if (self.currentSlide && angular.isDefined(self.currentSlide.index)) {
return +self.currentSlide.index;
}
return currentIndex;
};
/* Allow outside people to call indexOf on slides array */
$scope.indexOfSlide = function(slide) {
return angular.isDefined(slide.index) ? +slide.index : slides.indexOf(slide);
};
$scope.next = function() {
var newIndex = (self.getCurrentIndex() + 1) % slides.length;
if (newIndex === 0 && $scope.noWrap()) {
$scope.pause();
return;
}
return self.select(getSlideByIndex(newIndex), 'next');
};
$scope.prev = function() {
var newIndex = self.getCurrentIndex() - 1 < 0 ? slides.length - 1 : self.getCurrentIndex() - 1;
if ($scope.noWrap() && newIndex === slides.length - 1) {
$scope.pause();
return;
}
return self.select(getSlideByIndex(newIndex), 'prev');
};
$scope.isActive = function(slide) {
return self.currentSlide === slide;
};
$scope.$watch('interval', restartTimer);
$scope.$watchCollection('slides', resetTransition);
$scope.$on('$destroy', resetTimer);
function restartTimer() {
resetTimer();
var interval = +$scope.interval;
if (!isNaN(interval) && interval > 0) {
currentInterval = $interval(timerFn, interval);
}
}
function resetTimer() {
if (currentInterval) {
$interval.cancel(currentInterval);
currentInterval = null;
}
}
function timerFn() {
var interval = +$scope.interval;
if (isPlaying && !isNaN(interval) && interval > 0 && slides.length) {
$scope.next();
} else {
$scope.pause();
}
}
function resetTransition(slides) {
if (!slides.length) {
$scope.$currentTransition = null;
}
}
$scope.play = function() {
if (!isPlaying) {
isPlaying = true;
restartTimer();
}
};
$scope.pause = function() {
if (!$scope.noPause) {
isPlaying = false;
resetTimer();
}
};
self.addSlide = function(slide, element) {
slide.$element = element;
slides.push(slide);
//if this is the first slide or the slide is set to active, select it
if (slides.length === 1 || slide.active) {
self.select(slides[slides.length - 1]);
if (slides.length === 1) {
$scope.play();
}
} else {
slide.active = false;
}
};
self.removeSlide = function(slide) {
if (angular.isDefined(slide.index)) {
slides.sort(function(a, b) {
return +a.index > +b.index;
});
}
//get the index of the slide inside the carousel
var index = slides.indexOf(slide);
slides.splice(index, 1);
if (slides.length > 0 && slide.active) {
if (index >= slides.length) {
self.select(slides[index - 1]);
} else {
self.select(slides[index]);
}
} else if (currentIndex > index) {
currentIndex--;
}
//clean the currentSlide when no more slide
if (slides.length === 0) {
self.currentSlide = null;
}
};
$scope.$watch('noTransition', function(noTransition) {
$animate.enabled($element, noTransition);
});
}])
.directive('uibCarousel', [function() {
return {
transclude: true,
replace: true,
controller: 'UibCarouselController',
controllerAs: 'carousel',
require: 'carousel',
templateUrl: function(element, attrs) {
return attrs.templateUrl || 'template/carousel/carousel.html';
},
scope: {
interval: '=',
noTransition: '=',
noPause: '=',
noWrap: '&'
}
};
}])
.directive('uibSlide', function() {
return {
require: '^uibCarousel',
restrict: 'EA',
transclude: true,
replace: true,
templateUrl: function(element, attrs) {
return attrs.templateUrl || 'template/carousel/slide.html';
},
scope: {
active: '=?',
actual: '=?',
index: '=?'
},
link: function (scope, element, attrs, carouselCtrl) {
carouselCtrl.addSlide(scope, element);
//when the scope is destroyed then remove the slide from the current slides array
scope.$on('$destroy', function() {
carouselCtrl.removeSlide(scope);
});
scope.$watch('active', function(active) {
if (active) {
carouselCtrl.select(scope);
}
});
}
};
})
.animation('.item', [
'$injector', '$animate',
function ($injector, $animate) {
var SLIDE_DIRECTION = 'uib-slideDirection',
$animateCss = null;
if ($injector.has('$animateCss')) {
$animateCss = $injector.get('$animateCss');
}
function removeClass(element, className, callback) {
element.removeClass(className);
if (callback) {
callback();
}
}
return {
beforeAddClass: function(element, className, done) {
// Due to transclusion, noTransition property is on parent's scope
if (className == 'active' && !$animate.enabled(element)) {
var stopped = false;
var direction = element.data(SLIDE_DIRECTION);
var directionClass = direction == 'next' ? 'left' : 'right';
var removeClassFn = removeClass.bind(this, element,
directionClass + ' ' + direction, done);
element.addClass(direction);
if ($animateCss) {
$animateCss(element, {addClass: directionClass})
.start()
.done(removeClassFn);
} else {
$animate.addClass(element, directionClass).then(function () {
if (!stopped) {
removeClassFn();
}
done();
});
}
return function () {
stopped = true;
};
}
done();
},
beforeRemoveClass: function (element, className, done) {
// Due to transclusion, noTransition property is on parent's scope
if (className === 'active' && !$animate.enabled(element)) {
var stopped = false;
var direction = element.data(SLIDE_DIRECTION);
var directionClass = direction == 'next' ? 'left' : 'right';
var removeClassFn = removeClass.bind(this, element, directionClass, done);
if ($animateCss) {
$animateCss(element, {addClass: directionClass})
.start()
.done(removeClassFn);
} else {
$animate.addClass(element, directionClass).then(function() {
if (!stopped) {
removeClassFn();
}
done();
});
}
return function() {
stopped = true;
};
}
done();
}
};
}]);
angular.module("template/carousel/carousel.html", []).run(["$templateCache", function($templateCache) {
$templateCache.put("template/carousel/carousel.html",
"<div ng-mouseenter=\"pause()\" ng-mouseleave=\"play()\" class=\"carousel\" ng-swipe-right=\"prev()\" ng-swipe-left=\"next()\">\n" +
" <div class=\"carousel-inner\" ng-transclude></div>\n" +
" <a role=\"button\" href class=\"left carousel-control\" ng-click=\"prev()\" ng-show=\"slides.length > 1\">\n" +
" <span aria-hidden=\"true\" class=\"glyphicon glyphicon-chevron-left\"></span>\n" +
" <span class=\"sr-only\">previous</span>\n" +
" </a>\n" +
" <a role=\"button\" href class=\"right carousel-control\" ng-click=\"next()\" ng-show=\"slides.length > 1\">\n" +
" <span aria-hidden=\"true\" class=\"glyphicon glyphicon-chevron-right\"></span>\n" +
" <span class=\"sr-only\">next</span>\n" +
" </a>\n" +
" <ol class=\"carousel-indicators\" ng-show=\"slides.length > 1\">\n" +
" <li ng-repeat=\"slide in slides | orderBy:indexOfSlide track by $index\" ng-class=\"{ active: isActive(slide) }\" ng-click=\"select(slide)\">\n" +
" <span class=\"sr-only\">slide {{ $index + 1 }} of {{ slides.length }}<span ng-if=\"isActive(slide)\">, currently active</span></span>\n" +
" </li>\n" +
" </ol>\n" +
"</div>");
}]);
angular.module("template/carousel/slide.html", []).run(["$templateCache", function($templateCache) {
$templateCache.put("template/carousel/slide.html",
"<div ng-class=\"{\n" +
" 'active': active\n" +
" }\" class=\"item text-center\" ng-transclude></div>\n" +
"");
}]);
!angular.$$csp() && angular.element(document).find('head').prepend('<style type="text/css">.ng-animate.item:not(.left):not(.right){-webkit-transition:0s ease-in-out left;transition:0s ease-in-out left}</style>');