Skip to content

Commit

Permalink
fix(carousel): angular-ui#488 Carousel fails to update model changes.
Browse files Browse the repository at this point in the history
 - Uses dom element index.
 - Adds order to indicators to match slide order.
  • Loading branch information
kkruit committed Nov 11, 2014
1 parent 35d0cc1 commit bfa58c0
Show file tree
Hide file tree
Showing 3 changed files with 80 additions and 12 deletions.
67 changes: 57 additions & 10 deletions src/carousel/carousel.js
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ angular.module('ui.bootstrap.carousel', ['ui.bootstrap.transition'])
var destroyed = false;
/* direction: "prev" or "next" */
self.select = $scope.select = function(nextSlide, direction) {
var nextIndex = slides.indexOf(nextSlide);
var nextIndex = self.indexOfSlide(nextSlide);
//Decide direction if it's not given
if (direction === undefined) {
direction = nextIndex > currentIndex ? 'next' : 'prev';
Expand Down Expand Up @@ -59,7 +59,7 @@ angular.module('ui.bootstrap.carousel', ['ui.bootstrap.transition'])
transitionDone(nextSlide, self.currentSlide);
}
self.currentSlide = nextSlide;
currentIndex = nextIndex;
currentIndex = self.indexOfSlide(nextSlide);
//every time you change slides, reset the timer
restartTimer();
}
Expand All @@ -72,27 +72,55 @@ angular.module('ui.bootstrap.carousel', ['ui.bootstrap.transition'])
$scope.$on('$destroy', function () {
destroyed = true;
});

/* Allow outside people to call indexOf on slides array */
self.indexOfSlide = function(slide) {
return slides.indexOf(slide);
if(angular.isUndefined(slide.$element)) {
return slides.indexOf(slide);
}
var slideElements = slide.$element.parent().children();
for(var i = 0; i < slideElements.length; i++){
if(slideElements[i] === slide.$element[0]){
return i;
}
}
return false;
};

$scope.next = function() {
var newIndex = (currentIndex + 1) % slides.length;
$scope.indexOfSlide = function (slide) {
return self.indexOfSlide(slide);
};

$scope.next = function() {
//Prevent this user-triggered transition from occurring if there is already one in progress
if (!$scope.$currentTransition) {
return self.select(slides[newIndex], 'next');
var nextSlide = null;
if(angular.isUndefined(self.currentSlide.$element)) {
return false;
}
var nextElement = self.currentSlide.$element.next();
if(nextElement.length === 1){
nextSlide = getSlideFromElement(nextElement);
} else {
nextSlide = getFirstSlide();
}
return self.select(nextSlide, 'next');
}
};

$scope.prev = function() {
var newIndex = currentIndex - 1 < 0 ? slides.length - 1 : currentIndex - 1;

//Prevent this user-triggered transition from occurring if there is already one in progress
if (!$scope.$currentTransition) {
return self.select(slides[newIndex], 'prev');
var prevSlide = null;
if(angular.isUndefined(self.currentSlide.$element)) {
return false;
}
var prevElement = self.currentSlide.$element[0].previousElementSibling;
if(prevElement !== null){
prevSlide = getSlideFromElement(prevElement);
} else {
prevSlide = getLastSlide();
}
return self.select(prevSlide, 'next');
}
};

Expand Down Expand Up @@ -140,6 +168,25 @@ angular.module('ui.bootstrap.carousel', ['ui.bootstrap.transition'])
}
};

function getSlideFromElement(element) {
return angular.element(element).scope().$$childHead;
}

function getSlideElements() {
return self.currentSlide.$element.parent().children();
}

function getLastSlide() {
var slideElements = getSlideElements();
var lastSlideElement = slideElements[slideElements.length-1];
return getSlideFromElement(lastSlideElement);
}

function getFirstSlide(){
var firstSlideElement = getSlideElements()[0];
return getSlideFromElement(firstSlideElement);
}

self.addSlide = function(slide, element) {
slide.$element = element;
slides.push(slide);
Expand Down
23 changes: 22 additions & 1 deletion src/carousel/test/carousel.spec.js
Original file line number Diff line number Diff line change
Expand Up @@ -266,7 +266,28 @@ describe('carousel', function() {
scope.$destroy();
expect($interval.cancel).toHaveBeenCalled();
});

it('should respect changes in order', function() {
scope.slides[0].order = 1;
scope.slides[1].order = 2;
scope.slides[2].order = 3;
var elm = $compile(
'<carousel interval="interval">' +
'<slide ng-repeat="slide in slides | orderBy:\'order\'" active="slide.active">' +
'{{slide.content}}' +
'</slide>' +
'</carousel>'
)(scope);
$rootScope.$digest();
scope.slides[0].order = 3;
scope.slides[1].order = 2;
scope.slides[2].order = 1;
scope.slides[0].active = true;
$rootScope.$digest();
var navNext = elm.find('a.right');
testSlideActive(0);
navNext.click();
testSlideActive(2);
});
});

describe('controller', function() {
Expand Down
2 changes: 1 addition & 1 deletion template/carousel/carousel.html
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
<div ng-mouseenter="pause()" ng-mouseleave="play()" class="carousel" ng-swipe-right="prev()" ng-swipe-left="next()">
<ol class="carousel-indicators" ng-show="slides.length > 1">
<li ng-repeat="slide in slides track by $index" ng-class="{active: isActive(slide)}" ng-click="select(slide)"></li>
<li ng-repeat="slide in slides | orderBy:indexOfSlide track by $index" ng-class="{active: isActive(slide)}" ng-click="select(slide)"></li>
</ol>
<div class="carousel-inner" ng-transclude></div>
<a class="left carousel-control" ng-click="prev()" ng-show="slides.length > 1"><span class="glyphicon glyphicon-chevron-left"></span></a>
Expand Down

0 comments on commit bfa58c0

Please sign in to comment.