Skip to content

Commit 44d5a0f

Browse files
committedMay 5, 2016
fix(slides): changed the way looped/duplicates slides work, added documentation
changed the way looped/duplicates slides work, added documentation closes ionic-team#6305
2 parents f19b2fe + 302d566 commit 44d5a0f

File tree

3 files changed

+166
-128
lines changed

3 files changed

+166
-128
lines changed
 

‎js/angular/directive/slides.js

+76-89
Original file line numberDiff line numberDiff line change
@@ -15,29 +15,82 @@
1515
*
1616
* @usage
1717
* ```html
18-
* <ion-slides options="options" slider="data.slider">
19-
* <ion-slide-page>
20-
* <div class="box blue"><h1>BLUE</h1></div>
21-
* </ion-slide-page>
22-
* <ion-slide-page>
23-
* <div class="box yellow"><h1>YELLOW</h1></div>
24-
* </ion-slide-page>
25-
* <ion-slide-page>
26-
* <div class="box pink"><h1>PINK</h1></div>
27-
* </ion-slide-page>
28-
* </ion-slides>
18+
* <ion-content scroll="false">
19+
* <ion-slides options="options" slider="data.slider">
20+
* <ion-slide-page>
21+
* <div class="box blue"><h1>BLUE</h1></div>
22+
* </ion-slide-page>
23+
* <ion-slide-page>
24+
* <div class="box yellow"><h1>YELLOW</h1></div>
25+
* </ion-slide-page>
26+
* <ion-slide-page>
27+
* <div class="box pink"><h1>PINK</h1></div>
28+
* </ion-slide-page>
29+
* </ion-slides>
30+
* </ion-content>
2931
* ```
3032
*
3133
* ```js
3234
* $scope.options = {
3335
* loop: false,
34-
* effect: fade,
36+
* effect: 'fade',
3537
* speed: 500,
3638
* }
37-
* $scope.data = {};
38-
* $scope.$watch('data.slider', function(nv, ov) {
39-
* $scope.slider = $scope.data.slider;
40-
* })
39+
*
40+
* $scope.$on("$ionicSlides.sliderInitialized", function(event, data){
41+
* // data.slider is the instance of Swiper
42+
* $scope.slider = data.slider;
43+
* });
44+
*
45+
* $scope.$on("$ionicSlides.slideChangeStart", function(event, data){
46+
* console.log('Slide change is beginning');
47+
* });
48+
*
49+
* $scope.$on("$ionicSlides.slideChangeEnd", function(event, data){
50+
* // note: the indexes are 0-based
51+
* $scope.activeIndex = data.activeIndex;
52+
* $scope.previousIndex = data.previousIndex;
53+
* });
54+
*
55+
* ```
56+
*
57+
* ## Slide Events
58+
*
59+
* The slides component dispatches events when the active slide changes
60+
*
61+
* <table class="table">
62+
* <tr>
63+
* <td><code>$ionicSlides.slideChangeStart</code></td>
64+
* <td>This event is emitted when a slide change begins</td>
65+
* </tr>
66+
* <tr>
67+
* <td><code>$ionicSlides.slideChangeEnd</code></td>
68+
* <td>This event is emitted when a slide change completes</td>
69+
* </tr>
70+
* <tr>
71+
* <td><code>$ionicSlides.sliderInitialized</code></td>
72+
* <td>This event is emitted when the slider is initialized. It provides access to an instance of the slider.</td>
73+
* </tr>
74+
* </table>
75+
*
76+
*
77+
* ## Updating Slides Dynamically
78+
* When applying data to the slider at runtime, typically everything will work as expected.
79+
*
80+
* In the event that the slides are looped, use the `updateLoop` method on the slider to ensure the slides update correctly.
81+
*
82+
* ```
83+
* $scope.$on("$ionicSlides.sliderInitialized", function(event, data){
84+
* // grab an instance of the slider
85+
* $scope.slider = data.slider;
86+
* });
87+
*
88+
* function dataChangeHandler(){
89+
* // call this function when data changes, such as an HTTP request, etc
90+
* if ( $scope.slider ){
91+
* $scope.slider.updateLoop();
92+
* }
93+
* }
4194
* ```
4295
*
4396
*/
@@ -61,11 +114,6 @@ function($animate, $timeout, $compile) {
61114
'</div>',
62115
controller: ['$scope', '$element', function($scope, $element) {
63116
var _this = this;
64-
var _watchHandler = null;
65-
var _enterHandler = null;
66-
var _afterLeaveHandler = null;
67-
var _modalRemovedHandler = null;
68-
var _modalPresentedHandler = null;
69117

70118
this.update = function() {
71119
$timeout(function() {
@@ -96,52 +144,6 @@ function($animate, $timeout, $compile) {
96144
_this.update();
97145
}, 50);
98146

99-
this.updateLoop = ionic.debounce(function() {
100-
if ( _this._options.loop ) {
101-
_this.__slider.updateLoop();
102-
}
103-
}, 50);
104-
105-
this.watchForChanges = function() {
106-
if ( !_watchHandler ) {
107-
// if we're not already watching, start watching
108-
_watchHandler = $scope.$watch(function() {
109-
console.log("Watch triggered");
110-
_this.updateLoop();
111-
});
112-
}
113-
};
114-
115-
this.stopWatching = function() {
116-
if ( _watchHandler ) {
117-
console.log("Stopping watching...");
118-
_watchHandler();
119-
_watchHandler = null;
120-
}
121-
};
122-
123-
this.cleanUpEventHandlers = function() {
124-
if ( _enterHandler ) {
125-
_enterHandler();
126-
_enterHandler = null;
127-
}
128-
129-
if ( _afterLeaveHandler ) {
130-
_afterLeaveHandler();
131-
_afterLeaveHandler = null;
132-
}
133-
134-
if ( _modalRemovedHandler ) {
135-
_modalRemovedHandler();
136-
_modalRemovedHandler = null;
137-
}
138-
139-
if ( _modalPresentedHandler ) {
140-
_modalPresentedHandler();
141-
_modalPresentedHandler = null;
142-
}
143-
};
144-
145147
this.getSlider = function() {
146148
return _this.__slider;
147149
};
@@ -160,37 +162,22 @@ function($animate, $timeout, $compile) {
160162
$timeout(function() {
161163
var slider = new ionic.views.Swiper($element.children()[0], newOptions, $scope, $compile);
162164

165+
$scope.$emit("$ionicSlides.sliderInitialized", { slider: slider });
166+
163167
_this.__slider = slider;
164168
$scope.slider = _this.__slider;
165169

166170
$scope.$on('$destroy', function() {
167171
slider.destroy();
168172
_this.__slider = null;
169-
_this.stopWatching();
170-
_this.cleanUpEventHandlers();
171-
172-
});
173-
174-
_this.watchForChanges();
175-
176-
_enterHandler = $scope.$on("$ionicView.enter", function() {
177-
_this.watchForChanges();
178173
});
179-
180-
_afterLeaveHandler = $scope.$on("$ionicView.afterLeave", function() {
181-
_this.stopWatching();
182-
});
183-
184-
_modalRemovedHandler = $scope.$on("$ionic.modalRemoved", function() {
185-
_this.stopWatching();
186-
});
187-
188-
_modalPresentedHandler = $scope.$on("$ionic.modalPresented", function() {
189-
_this.watchForChanges();
190-
});
191-
192174
});
193175

176+
$timeout(function() {
177+
// if it's a loop, render the slides again just incase
178+
_this.rapidUpdate();
179+
}, 200);
180+
194181
}],
195182

196183
link: function($scope) {

‎js/views/slidesView.js

+42-19
Original file line numberDiff line numberDiff line change
@@ -1811,6 +1811,11 @@
18111811
s.emit('onTransitionStart', s);
18121812
if (s.activeIndex !== s.previousIndex) {
18131813
s.emit('onSlideChangeStart', s);
1814+
_scope.$emit("$ionicSlides.slideChangeStart", {
1815+
slider: s,
1816+
activeIndex: s.getSlideDataIndex(s.activeIndex),
1817+
previousIndex: s.getSlideDataIndex(s.previousIndex)
1818+
});
18141819
if (s.activeIndex > s.previousIndex) {
18151820
s.emit('onSlideNextStart', s);
18161821
}
@@ -1830,6 +1835,11 @@
18301835
s.emit('onTransitionEnd', s);
18311836
if (s.activeIndex !== s.previousIndex) {
18321837
s.emit('onSlideChangeEnd', s);
1838+
_scope.$emit("$ionicSlides.slideChangeEnd", {
1839+
slider: s,
1840+
activeIndex: s.getSlideDataIndex(s.activeIndex),
1841+
previousIndex: s.getSlideDataIndex(s.previousIndex)
1842+
});
18331843
if (s.activeIndex > s.previousIndex) {
18341844
s.emit('onSlideNextEnd', s);
18351845
}
@@ -2046,24 +2056,38 @@
20462056
};
20472057

20482058
s.updateLoop = function(){
2049-
// this is an Ionic custom function
2050-
var duplicates = s.wrapper.children('.' + s.params.slideClass + '.' + s.params.slideDuplicateClass);
2051-
var slides = s.wrapper.children('.' + s.params.slideClass);
2052-
for ( var i = 0; i < duplicates.length; i++ ){
2053-
var duplicate = duplicates[i];
2054-
var swiperSlideIndex = angular.element(duplicate).attr("data-swiper-slide-index");
2055-
// loop through each slide
2056-
for ( var j = 0; i < slides.length; j++ ){
2057-
// if it's not a duplicate, and the data swiper slide index matches the duplicate value
2058-
var slide = slides[j]
2059-
if ( !angular.element(slide).hasClass(s.params.slideDuplicateClass) && angular.element(slide).attr("data-swiper-slide-index") === swiperSlideIndex ){
2060-
// sweet, it's a match
2061-
duplicate.innerHTML = slide.innerHTML;
2059+
var currentSlide = s.slides.eq(s.activeIndex);
2060+
if ( angular.element(currentSlide).hasClass(s.params.slideDuplicateClass) ){
2061+
// we're on a duplicate, so slide to the non-duplicate
2062+
var swiperSlideIndex = angular.element(currentSlide).attr("data-swiper-slide-index");
2063+
var slides = s.wrapper.children('.' + s.params.slideClass);
2064+
for ( var i = 0; i < slides.length; i++ ){
2065+
if ( !angular.element(slides[i]).hasClass(s.params.slideDuplicateClass) && angular.element(slides[i]).attr("data-swiper-slide-index") === swiperSlideIndex ){
2066+
s.slideTo(i, 0, false, true);
20622067
break;
20632068
}
20642069
}
2070+
// if we needed to switch slides, we did that. So, now call the createLoop function internally
2071+
setTimeout(function(){
2072+
s.createLoop();
2073+
}, 50);
20652074
}
20662075
}
2076+
2077+
s.getSlideDataIndex = function(slideIndex){
2078+
// this is an Ionic custom function
2079+
// Swiper loops utilize duplicate DOM elements for slides when in a loop
2080+
// which means that we cannot rely on the actual slide index for our events
2081+
// because index 0 does not necessarily point to index 0
2082+
// and index n+1 does not necessarily point to the expected piece of data
2083+
// therefore, rather than using the actual slide index we should
2084+
// use the data index that swiper includes as an attribute on the dom elements
2085+
// because this is what will be meaningful to the consumer of our events
2086+
var slide = s.slides.eq(slideIndex);
2087+
var attributeIndex = angular.element(slide).attr("data-swiper-slide-index");
2088+
return parseInt(attributeIndex);
2089+
}
2090+
20672091
/*=========================
20682092
Loop
20692093
===========================*/
@@ -2092,26 +2116,25 @@
20922116
slide.attr('data-swiper-slide-index', index);
20932117
});
20942118
for (i = 0; i < appendSlides.length; i++) {
2095-
/*newNode = angular.element(appendSlides[i]).clone().addClass(s.params.slideDuplicateClass);
2119+
2120+
newNode = angular.element(appendSlides[i]).clone().addClass(s.params.slideDuplicateClass);
20962121
newNode.removeAttr('ng-transclude');
20972122
newNode.removeAttr('ng-repeat');
20982123
scope = angular.element(appendSlides[i]).scope();
20992124
newNode = $compile(newNode)(scope);
21002125
angular.element(s.wrapper).append(newNode);
2101-
*/
2102-
s.wrapper.append($(appendSlides[i].cloneNode(true)).addClass(s.params.slideDuplicateClass));
2126+
//s.wrapper.append($(appendSlides[i].cloneNode(true)).addClass(s.params.slideDuplicateClass));
21032127
}
21042128
for (i = prependSlides.length - 1; i >= 0; i--) {
2105-
s.wrapper.prepend($(prependSlides[i].cloneNode(true)).addClass(s.params.slideDuplicateClass));
2129+
//s.wrapper.prepend($(prependSlides[i].cloneNode(true)).addClass(s.params.slideDuplicateClass));
21062130

2107-
/*newNode = angular.element(prependSlides[i]).clone().addClass(s.params.slideDuplicateClass);
2131+
newNode = angular.element(prependSlides[i]).clone().addClass(s.params.slideDuplicateClass);
21082132
newNode.removeAttr('ng-transclude');
21092133
newNode.removeAttr('ng-repeat');
21102134

21112135
scope = angular.element(prependSlides[i]).scope();
21122136
newNode = $compile(newNode)(scope);
21132137
angular.element(s.wrapper).prepend(newNode);
2114-
*/
21152138
}
21162139
};
21172140
s.destroyLoop = function () {

0 commit comments

Comments
 (0)