diff --git a/js/ext/angular/src/directive/ionicViewState.js b/js/ext/angular/src/directive/ionicViewState.js index 10c36a28278..ec571f0822f 100644 --- a/js/ext/angular/src/directive/ionicViewState.js +++ b/js/ext/angular/src/directive/ionicViewState.js @@ -23,7 +23,7 @@ angular.module('ionic.ui.viewState', ['ionic.service.view', 'ionic.service.gestu * Our Nav Bar directive which updates as the controller state changes. */ .directive('ionNavBar', ['$ionicViewService', '$rootScope', '$animate', '$compile', - function( $ionicViewService, $rootScope, $animate, $compile) { + function( $ionicViewService, $rootScope, $animate, $compile) { return { restrict: 'E', @@ -40,8 +40,10 @@ angular.module('ionic.ui.viewState', ['ionic.service.view', 'ionic.service.gestu template: '', compile: function(tElement, tAttrs) { return function link($scope, $element, $attr) { - $scope.titles = []; //defaults - $scope.backButtonEnabled = true; + $scope.backButtonEnabled = false; $scope.animateEnabled = true; $scope.isReverse = false; $scope.isInvisible = true; @@ -100,7 +100,7 @@ angular.module('ionic.ui.viewState', ['ionic.service.view', 'ionic.service.gestu $scope.backButtonEnabled = !!data; }), $scope.$parent.$on('viewState.titleUpdated', function(e, data) { - $scope.titles[$scope.titles.length - 1] = data && data.title || ''; + $scope.title = data && data.title || ''; }) ]; $scope.$on('$destroy', function() { @@ -109,19 +109,66 @@ angular.module('ionic.ui.viewState', ['ionic.service.view', 'ionic.service.gestu }); function updateHeaderData(data) { - var newTitle = data && data.title || ''; - - $scope.isReverse = data.navDirection == 'back'; - if (data.hideBackButton) { - $scope.backButtonEnabled = false; + if (angular.isDefined(data.hideBackButton)) { + $scope.backButtonEnabled = !!data.hideBackButton; } - + $scope.isReverse = data.navDirection == 'back'; $scope.animateEnabled = !!(data.navDirection && data.animate !== false); - $scope.titles.length = 0; - $scope.titles.push(newTitle); + $scope.leftButtons = data.leftButtons; $scope.rightButtons = data.rightButtons; + $scope.oldTitle = $scope.title; + $scope.title = data && data.title || ''; + + //If no animation, we're done! + if (!$scope.animateEnabled) { + hb.align(); + return; + } else { + animateTitles(); + } + } + + function animateTitles() { + var oldTitleEl, newTitleEl, currentTitles; + + //If we have any title right now (or more than one, they could be transitioning on switch), + //replace the first one with an oldTitle element + currentTitles = $element[0].querySelectorAll('.title'); + if (currentTitles.length) { + oldTitleEl = $compile('

')($scope); + angular.element(currentTitles[0]).replaceWith(oldTitleEl); + } + //Compile new title + newTitleEl = $compile('

')($scope); + + //Animate in one frame + ionic.requestAnimationFrame(function() { + + oldTitleEl && $animate.leave(angular.element(oldTitleEl)); + + var insert = oldTitleEl && angular.element(oldTitleEl) || null; + $animate.enter(newTitleEl, $element, insert, function() { + hb.align(); + }); + + //Cleanup any old titles leftover (besides the one we already did replaceWith on) + angular.forEach(currentTitles, function(el) { + if (el && el.parentNode) { + //Use .remove() to cleanup things like .data() + angular.element(el).remove(); + } + }); + + //$apply so bindings fire + $scope.$digest(); + + //Stop flicker of new title on ios7 + ionic.requestAnimationFrame(function() { + newTitleEl[0].classList.remove('invisible'); + }); + }); } }; } diff --git a/js/ext/angular/test/directive/ionicView.unit.js b/js/ext/angular/test/directive/ionicView.unit.js index fa56ab2fd82..3f6f40a6f2c 100644 --- a/js/ext/angular/test/directive/ionicView.unit.js +++ b/js/ext/angular/test/directive/ionicView.unit.js @@ -51,23 +51,23 @@ describe('Ionic View', function() { function backButton() { return angular.element(element[0].querySelector('.back-button')); }; - expect(backButton().length).toEqual(1); + expect(backButton().hasClass('hide')).toEqual(true); scope.$broadcast('viewState.showBackButton', false); scope.$apply(); - expect(backButton().length).toEqual(0); + expect(backButton().hasClass('hide')).toEqual(true); scope.$broadcast('viewState.showBackButton', true); scope.$apply(); - expect(backButton().length).toEqual(1); + expect(backButton().hasClass('hide')).toEqual(false); scope.$broadcast('$viewHistory.historyChange', { showBack: false }); scope.$apply(); - expect(backButton().length).toEqual(0); + expect(backButton().hasClass('hide')).toEqual(true); scope.$broadcast('$viewHistory.historyChange', { showBack: true }); scope.$apply(); - expect(backButton().length).toEqual(1); + expect(backButton().hasClass('hide')).toEqual(false); }); it('should show/hide navBar', function() { @@ -113,7 +113,7 @@ describe('Ionic View', function() { scope.$digest(); var navBar = element.find('header'); var title = navBar.find('h1'); - expect(title.text().trim()).toEqual('Title'); + expect(element.find('header').find('h1').text().trim()).toEqual('Title'); scope.viewTitle = 'New Title'; scope.$digest();