diff --git a/js/angular/directive/slides.js b/js/angular/directive/slides.js index 5fecb952695..5dc712fa3f7 100644 --- a/js/angular/directive/slides.js +++ b/js/angular/directive/slides.js @@ -15,29 +15,82 @@ * * @usage * ```html - * - * - *

BLUE

- *
- * - *

YELLOW

- *
- * - *

PINK

- *
- *
+ * + * + * + *

BLUE

+ *
+ * + *

YELLOW

+ *
+ * + *

PINK

+ *
+ *
+ *
* ``` * * ```js * $scope.options = { * loop: false, - * effect: fade, + * effect: 'fade', * speed: 500, * } - * $scope.data = {}; - * $scope.$watch('data.slider', function(nv, ov) { - * $scope.slider = $scope.data.slider; - * }) + * + * $scope.$on("$ionicSlides.sliderInitialized", function(event, data){ + * // data.slider is the instance of Swiper + * $scope.slider = data.slider; + * }); + * + * $scope.$on("$ionicSlides.slideChangeStart", function(event, data){ + * console.log('Slide change is beginning'); + * }); + * + * $scope.$on("$ionicSlides.slideChangeEnd", function(event, data){ + * // note: the indexes are 0-based + * $scope.activeIndex = data.activeIndex; + * $scope.previousIndex = data.previousIndex; + * }); + * + * ``` + * + * ## Slide Events + * + * The slides component dispatches events when the active slide changes + * + * + * + * + * + * + * + * + * + * + * + * + * + * + *
$ionicSlides.slideChangeStartThis event is emitted when a slide change begins
$ionicSlides.slideChangeEndThis event is emitted when a slide change completes
$ionicSlides.sliderInitializedThis event is emitted when the slider is initialized. It provides access to an instance of the slider.
+ * + * + * ## Updating Slides Dynamically + * When applying data to the slider at runtime, typically everything will work as expected. + * + * In the event that the slides are looped, use the `updateLoop` method on the slider to ensure the slides update correctly. + * + * ``` + * $scope.$on("$ionicSlides.sliderInitialized", function(event, data){ + * // grab an instance of the slider + * $scope.slider = data.slider; + * }); + * + * function dataChangeHandler(){ + * // call this function when data changes, such as an HTTP request, etc + * if ( $scope.slider ){ + * $scope.slider.updateLoop(); + * } + * } * ``` * */ @@ -61,11 +114,6 @@ function($animate, $timeout, $compile) { '', controller: ['$scope', '$element', function($scope, $element) { var _this = this; - var _watchHandler = null; - var _enterHandler = null; - var _afterLeaveHandler = null; - var _modalRemovedHandler = null; - var _modalPresentedHandler = null; this.update = function() { $timeout(function() { @@ -96,52 +144,6 @@ function($animate, $timeout, $compile) { _this.update(); }, 50); - this.updateLoop = ionic.debounce(function() { - if ( _this._options.loop ) { - _this.__slider.updateLoop(); - } - }, 50); - - this.watchForChanges = function() { - if ( !_watchHandler ) { - // if we're not already watching, start watching - _watchHandler = $scope.$watch(function() { - console.log("Watch triggered"); - _this.updateLoop(); - }); - } - }; - - this.stopWatching = function() { - if ( _watchHandler ) { - console.log("Stopping watching..."); - _watchHandler(); - _watchHandler = null; - } - }; - - this.cleanUpEventHandlers = function() { - if ( _enterHandler ) { - _enterHandler(); - _enterHandler = null; - } - - if ( _afterLeaveHandler ) { - _afterLeaveHandler(); - _afterLeaveHandler = null; - } - - if ( _modalRemovedHandler ) { - _modalRemovedHandler(); - _modalRemovedHandler = null; - } - - if ( _modalPresentedHandler ) { - _modalPresentedHandler(); - _modalPresentedHandler = null; - } - }; - this.getSlider = function() { return _this.__slider; }; @@ -160,37 +162,22 @@ function($animate, $timeout, $compile) { $timeout(function() { var slider = new ionic.views.Swiper($element.children()[0], newOptions, $scope, $compile); + $scope.$emit("$ionicSlides.sliderInitialized", { slider: slider }); + _this.__slider = slider; $scope.slider = _this.__slider; $scope.$on('$destroy', function() { slider.destroy(); _this.__slider = null; - _this.stopWatching(); - _this.cleanUpEventHandlers(); - - }); - - _this.watchForChanges(); - - _enterHandler = $scope.$on("$ionicView.enter", function() { - _this.watchForChanges(); }); - - _afterLeaveHandler = $scope.$on("$ionicView.afterLeave", function() { - _this.stopWatching(); - }); - - _modalRemovedHandler = $scope.$on("$ionic.modalRemoved", function() { - _this.stopWatching(); - }); - - _modalPresentedHandler = $scope.$on("$ionic.modalPresented", function() { - _this.watchForChanges(); - }); - }); + $timeout(function() { + // if it's a loop, render the slides again just incase + _this.rapidUpdate(); + }, 200); + }], link: function($scope) { diff --git a/js/views/slidesView.js b/js/views/slidesView.js index 9555948de3f..a896482dfae 100644 --- a/js/views/slidesView.js +++ b/js/views/slidesView.js @@ -1811,6 +1811,11 @@ s.emit('onTransitionStart', s); if (s.activeIndex !== s.previousIndex) { s.emit('onSlideChangeStart', s); + _scope.$emit("$ionicSlides.slideChangeStart", { + slider: s, + activeIndex: s.getSlideDataIndex(s.activeIndex), + previousIndex: s.getSlideDataIndex(s.previousIndex) + }); if (s.activeIndex > s.previousIndex) { s.emit('onSlideNextStart', s); } @@ -1830,6 +1835,11 @@ s.emit('onTransitionEnd', s); if (s.activeIndex !== s.previousIndex) { s.emit('onSlideChangeEnd', s); + _scope.$emit("$ionicSlides.slideChangeEnd", { + slider: s, + activeIndex: s.getSlideDataIndex(s.activeIndex), + previousIndex: s.getSlideDataIndex(s.previousIndex) + }); if (s.activeIndex > s.previousIndex) { s.emit('onSlideNextEnd', s); } @@ -2046,24 +2056,38 @@ }; s.updateLoop = function(){ - // this is an Ionic custom function - var duplicates = s.wrapper.children('.' + s.params.slideClass + '.' + s.params.slideDuplicateClass); - var slides = s.wrapper.children('.' + s.params.slideClass); - for ( var i = 0; i < duplicates.length; i++ ){ - var duplicate = duplicates[i]; - var swiperSlideIndex = angular.element(duplicate).attr("data-swiper-slide-index"); - // loop through each slide - for ( var j = 0; i < slides.length; j++ ){ - // if it's not a duplicate, and the data swiper slide index matches the duplicate value - var slide = slides[j] - if ( !angular.element(slide).hasClass(s.params.slideDuplicateClass) && angular.element(slide).attr("data-swiper-slide-index") === swiperSlideIndex ){ - // sweet, it's a match - duplicate.innerHTML = slide.innerHTML; + var currentSlide = s.slides.eq(s.activeIndex); + if ( angular.element(currentSlide).hasClass(s.params.slideDuplicateClass) ){ + // we're on a duplicate, so slide to the non-duplicate + var swiperSlideIndex = angular.element(currentSlide).attr("data-swiper-slide-index"); + var slides = s.wrapper.children('.' + s.params.slideClass); + for ( var i = 0; i < slides.length; i++ ){ + if ( !angular.element(slides[i]).hasClass(s.params.slideDuplicateClass) && angular.element(slides[i]).attr("data-swiper-slide-index") === swiperSlideIndex ){ + s.slideTo(i, 0, false, true); break; } } + // if we needed to switch slides, we did that. So, now call the createLoop function internally + setTimeout(function(){ + s.createLoop(); + }, 50); } } + + s.getSlideDataIndex = function(slideIndex){ + // this is an Ionic custom function + // Swiper loops utilize duplicate DOM elements for slides when in a loop + // which means that we cannot rely on the actual slide index for our events + // because index 0 does not necessarily point to index 0 + // and index n+1 does not necessarily point to the expected piece of data + // therefore, rather than using the actual slide index we should + // use the data index that swiper includes as an attribute on the dom elements + // because this is what will be meaningful to the consumer of our events + var slide = s.slides.eq(slideIndex); + var attributeIndex = angular.element(slide).attr("data-swiper-slide-index"); + return parseInt(attributeIndex); + } + /*========================= Loop ===========================*/ @@ -2092,26 +2116,25 @@ slide.attr('data-swiper-slide-index', index); }); for (i = 0; i < appendSlides.length; i++) { - /*newNode = angular.element(appendSlides[i]).clone().addClass(s.params.slideDuplicateClass); + + newNode = angular.element(appendSlides[i]).clone().addClass(s.params.slideDuplicateClass); newNode.removeAttr('ng-transclude'); newNode.removeAttr('ng-repeat'); scope = angular.element(appendSlides[i]).scope(); newNode = $compile(newNode)(scope); angular.element(s.wrapper).append(newNode); - */ - s.wrapper.append($(appendSlides[i].cloneNode(true)).addClass(s.params.slideDuplicateClass)); + //s.wrapper.append($(appendSlides[i].cloneNode(true)).addClass(s.params.slideDuplicateClass)); } for (i = prependSlides.length - 1; i >= 0; i--) { - s.wrapper.prepend($(prependSlides[i].cloneNode(true)).addClass(s.params.slideDuplicateClass)); + //s.wrapper.prepend($(prependSlides[i].cloneNode(true)).addClass(s.params.slideDuplicateClass)); - /*newNode = angular.element(prependSlides[i]).clone().addClass(s.params.slideDuplicateClass); + newNode = angular.element(prependSlides[i]).clone().addClass(s.params.slideDuplicateClass); newNode.removeAttr('ng-transclude'); newNode.removeAttr('ng-repeat'); scope = angular.element(prependSlides[i]).scope(); newNode = $compile(newNode)(scope); angular.element(s.wrapper).prepend(newNode); - */ } }; s.destroyLoop = function () { diff --git a/test/html/slides.html b/test/html/slides.html index d9a06e31cba..df92b5d1479 100644 --- a/test/html/slides.html +++ b/test/html/slides.html @@ -42,11 +42,17 @@

Before launch

Before entering the space capsule, please prepare accordingly:

+

+ +

+
+ +

During launch

@@ -56,6 +62,9 @@

During launch

launch and minutes after reacing the proper altitude needed to utilize the ion propulsion engines that will carry you to HD 219134 b.

+

+ +

After launch and years ahead

@@ -64,6 +73,9 @@

After launch and years ahead

Thus begins the long journey to HD 219134 b. To pass the time, we've supplied you with a variety of pharmaceuticals along with a pamphlet to understand the benefits and drawbacks of each.

+

+ +

Whether you choose to utilize your full Vitality Buffer of four earth-years by experiencing the mystery and excitement of traveling through the vast universe, you must transition to the Cryo Pad for preservation for the rest of the voyage. @@ -72,10 +84,16 @@

After launch and years ahead

During your long nap, the experimental Worm Slip engines will fire to reduce the journey by several hundreds of thousands of earth-years. The status of the experiment will not be known until your planned Cryo Wake in 4000 earth-years.

+
+ +

Approaching HD 219134 b

some property: {{viewModel.someProperty}}
+

+ +

If you are lucky enough to be able to see HD 219134 b with your own eyes, congratulations! No space pioneer has ever made it this far. Take a minute and celebrate this monumental achievement by @@ -89,9 +107,15 @@

Approaching HD 219134 b

If the Worm Slip experiment failed and you have only partially progressed on your journey to HD 219134 b, please review the Contingency Plan for ideas on how to make the most of the rest of your life in space.

+
+ +

Life on HD 219134 b

+

+ +

Scientists aren't quite sure what life on HD 219134 b will be like! In order to help you adapt to a set of predicted atmospheric, pressure, and temperature environments, @@ -104,6 +128,9 @@

Life on HD 219134 b

at Ion Space Pursuits, we thank you for your participation in this important research study.

some property: {{viewModel.someProperty}}
+
+ +
@@ -117,30 +144,31 @@

Life on HD 219134 b

} $scope.viewModel = {}; $scope.viewModel.someProperty = "Waiting..."; - //$scope.someProperty = "Waiting..."; - $scope.data = {}; - $scope.$watch('data.slider', function(nv, ov) { - $scope.slider = $scope.data.slider; - }) + + $scope.$on("$ionicSlides.sliderInitialized", function(event, data){ + console.log("Slider initialized: ", data); + $scope.slider = data.slider; + }); + $interval(function() { //$scope.someProperty = Math.random(); $scope.viewModel.someProperty = Math.random(); - }, 200) - $scope.doClick = function() { - console.log('CLICK'); - } - /* - $scope.extraSlides = []; - var i = 0; - var c = $interval(function() { - $scope.extraSlides.push({ - id: ++i - }) - if(i > 2) { - $interval.cancel(c); + if ( $scope.slider ){ + $scope.slider.updateLoop(); } - }, 2000) - */ + }, 1000); + + $scope.$on("$ionicSlides.slideChangeEnd", function(event, data){ + console.log("slideChangeEnd event: ", data); + }); + + $scope.$on("$ionicSlides.slideChangeStart", function(event, data){ + console.log("slideChangeStart event: ", data); + }); + + $scope.doClick = function(){ + alert("clicked!"); + } }]);