Skip to content
This repository was archived by the owner on May 10, 2018. It is now read-only.

Commit 6ff425d

Browse files
committed
feat(carousel): add rn-carousel-deep-watch
1 parent 0578ae4 commit 6ff425d

File tree

3 files changed

+77
-9
lines changed

3 files changed

+77
-9
lines changed

README.md

+1
Original file line numberDiff line numberDiff line change
@@ -49,6 +49,7 @@ angular.module('MyApp', ['angular-carousel']);
4949
- `rn-carousel-auto-slide` add this attribute to make the carousel slide automatically after given seconds (default=3)
5050
- `rn-carousel-transition` : transition type, can be one of `slide, zoom, hexagon, fadeAndSlide, none`. (default=slide)
5151
- `rn-carousel-locked`: two way binding boolean that lock/unlock the carousel
52+
- `rn-carousel-deep-watch`: Deep watch the collection which enable to dynamically add slides at beginning without corrupting position
5253

5354
## Indicators
5455

index.html

+47-5
Original file line numberDiff line numberDiff line change
@@ -109,6 +109,7 @@ <h3>Custom templates without ng-repeat and auto-slide</h3>
109109
<div>
110110
<h3>Lockable carousel</h3>
111111
<div class="details">
112+
use rn-carousel-locked binding to dynamically lock/unlock the carousel
112113
</div>
113114
<div class="carousel-demo">
114115
<label><input type="checkbox" ng-model="isLocked"/>Lock the carousel</label>
@@ -121,9 +122,32 @@ <h3>Lockable carousel</h3>
121122
</ul>
122123
</div>
123124
</div>
125+
<br>
126+
<div>
127+
<h3>Add/Remove items in the collection</h3>
128+
<div class="details">
129+
The carousel is bound to your ngRepeat collection.<br>
130+
If you add items at the start of the collection, then by default, the slide position will change.<br>
131+
If you want to preserve position even when adding items at the head of the collection, you need to add the `rn-carousel-deep-watch` attribute. This has a performance impact so use carefully.<br>
132+
Works great with buffering too so you can have almost infinite slides while keeping only 5 items in the DOM<br>
133+
</div>
134+
<div class="carousel-demo" >
135+
<button ng-click="addSlide('head')">Add at beginning</button>
136+
<button ng-click="addSlide('tail')">Add at end</button>
137+
<ul rn-carousel rn-carousel-index="carouselIndex6" rn-carousel-deep-watch rn-carousel-buffered class="carousel5">
138+
<li ng-repeat="slide in slides6 track by slide.id">
139+
<div ng-style="{'background-image': 'url(' + slide.img + ')'}" class="bgimage">
140+
#{{ slide.id }}
141+
</div>
142+
</li>
143+
</ul>
144+
<div rn-carousel-indicators ng-if="slides6.length > 1" slides="slides6" rn-carousel-index="carouselIndex6"></div>
145+
</div>
146+
</div>
124147

125148
</div>
126-
149+
<p>&nbsp;</p>
150+
<p>&nbsp;</p>
127151
</body>
128152
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.9/angular.min.js"></script>
129153
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.9/angular-touch.min.js"></script>
@@ -144,15 +168,19 @@ <h3>Lockable carousel</h3>
144168

145169
$scope.colors = ["#fc0003", "#f70008", "#f2000d", "#ed0012", "#e80017", "#e3001c", "#de0021", "#d90026", "#d4002b", "#cf0030", "#c90036", "#c4003b", "#bf0040", "#ba0045", "#b5004a", "#b0004f", "#ab0054", "#a60059", "#a1005e", "#9c0063", "#960069", "#91006e", "#8c0073", "#870078", "#82007d", "#7d0082", "#780087", "#73008c", "#6e0091", "#690096", "#63009c", "#5e00a1", "#5900a6", "#5400ab", "#4f00b0", "#4a00b5", "#4500ba", "#4000bf", "#3b00c4", "#3600c9", "#3000cf", "#2b00d4", "#2600d9", "#2100de", "#1c00e3", "#1700e8", "#1200ed", "#0d00f2", "#0800f7", "#0300fc"];
146170

147-
function addSlide(target, style) {
171+
function getSlide(target, style) {
148172
var i = target.length;
149-
target.push({
173+
return {
150174
id: (i + 1),
151175
label: 'slide #' + (i + 1),
152176
img: 'http://lorempixel.com/450/300/' + style + '/' + ((i + 1) % 10) ,
153177
color: $scope.colors[ (i*10) % $scope.colors.length],
154178
odd: (i % 2 === 0)
155-
});
179+
};
180+
}
181+
182+
function addSlide(target, style) {
183+
target.push(getSlide(target, style));
156184
};
157185

158186
$scope.carouselIndex = 3;
@@ -183,7 +211,21 @@ <h3>Lockable carousel</h3>
183211
$scope.slides4 = [];
184212
addSlides($scope.slides4, 'city', 50);
185213

186-
});
214+
215+
// 5th ngRepeat demo
216+
$scope.slides6 = [];
217+
$scope.carouselIndex6 = 0;
218+
addSlides($scope.slides6, 'sports', 10);
219+
$scope.addSlide = function(at) {
220+
if(at==='head') {
221+
$scope.slides6.unshift(getSlide($scope.slides6, 'people'));
222+
} else {
223+
$scope.slides6.push(getSlide($scope.slides6, 'people'));
224+
}
225+
}
226+
227+
})
228+
187229

188230
</script>
189231
</html>

src/directives/rn-carousel.js

+29-4
Original file line numberDiff line numberDiff line change
@@ -128,6 +128,18 @@
128128

129129
var requestAnimationFrame = $window.requestAnimationFrame || $window.webkitRequestAnimationFrame || $window.mozRequestAnimationFrame;
130130

131+
function getItemIndex(collection, target, defaultIndex) {
132+
var result = defaultIndex;
133+
collection.every(function(item, index) {
134+
if (angular.equals(item, target)) {
135+
result = index;
136+
return false;
137+
}
138+
return true;
139+
});
140+
return result;
141+
};
142+
131143
return {
132144
restrict: 'A',
133145
scope: true,
@@ -261,6 +273,7 @@
261273
};
262274

263275
function goToSlide(index, slideOptions) {
276+
//console.log('goToSlide', arguments);
264277
// move a to the given slide index
265278
if (index === undefined) {
266279
index = scope.carouselIndex;
@@ -415,11 +428,23 @@
415428
}
416429

417430
if (isRepeatBased) {
418-
scope.$watchCollection(repeatCollection, function(newValue, oldValue) {
419-
//console.log('repeatCollection', arguments);
431+
// use rn-carousel-deep-watch to fight the Angular $watchCollection weakness : https://github.com/angular/angular.js/issues/2621
432+
// optional because it have some performance impacts (deep watch)
433+
var deepWatch = (iAttributes.rnCarouselDeepWatch!==undefined);
434+
435+
scope[deepWatch?'$watch':'$watchCollection'](repeatCollection, function(newValue, oldValue) {
436+
//console.log('repeatCollection', currentSlides);
437+
var oldSlides = (currentSlides || newValue).slice();
420438
currentSlides = newValue;
421-
goToSlide(scope.carouselIndex);
422-
});
439+
// if deepWatch ON ,manually compare objects to guess the new position
440+
if (deepWatch && angular.isArray(newValue)) {
441+
var activeElement = oldValue[scope.carouselIndex];
442+
var newIndex = getItemIndex(newValue, activeElement, scope.carouselIndex);
443+
goToSlide(newIndex, {animate: false});
444+
} else {
445+
goToSlide(scope.carouselIndex, {animate: false});
446+
}
447+
}, true);
423448
}
424449

425450
function swipeEnd(coords, event, forceAnimation) {

0 commit comments

Comments
 (0)