mirror of
https://github.com/ionic-team/ionic-framework.git
synced 2025-11-08 15:51:16 +08:00
Fixed up some nav stuff
This commit is contained in:
2
js/ext/angular/src/directive/ionicContent.js
vendored
2
js/ext/angular/src/directive/ionicContent.js
vendored
@ -10,7 +10,7 @@ angular.module('ionic.ui.content', [])
|
||||
.directive('pane', function() {
|
||||
return {
|
||||
restrict: 'E',
|
||||
compile: function(element, attr) {
|
||||
link: function(scope, element, attr) {
|
||||
element.addClass('pane');
|
||||
}
|
||||
}
|
||||
|
||||
337
js/ext/angular/src/directive/ionicNav.js
vendored
337
js/ext/angular/src/directive/ionicNav.js
vendored
@ -1,28 +1,78 @@
|
||||
(function() {
|
||||
'use strict';
|
||||
|
||||
/**
|
||||
* @description
|
||||
* The NavController is a navigation stack View Controller modelled off of
|
||||
* UINavigationController from Cocoa Touch. With the Nav Controller, you can
|
||||
* "push" new "pages" on to the navigation stack, and then pop them off to go
|
||||
* back. The NavController controls a navigation bar with a back button and title
|
||||
* which updates as the pages switch.
|
||||
*
|
||||
* The NavController makes sure to not recycle scopes of old pages
|
||||
* so that a pop will still show the same state that the user left.
|
||||
*
|
||||
* However, once a page is popped, its scope is destroyed and will have to be
|
||||
* recreated then next time it is pushed.
|
||||
*
|
||||
*/
|
||||
angular.module('ionic.ui.nav', ['ionic.service.templateLoad', 'ionic.service.gesture', 'ionic.service.platform', 'ngAnimate'])
|
||||
|
||||
.controller('NavCtrl', ['$scope', '$element', '$animate', '$compile', 'TemplateLoader', 'Platform', function($scope, $element, $animate, $compile, TemplateLoader, Platform) {
|
||||
.controller('NavCtrl', ['$scope', '$element', '$animate', '$compile', '$timeout', 'TemplateLoader', 'Platform', function($scope, $element, $animate, $compile, $timeout, TemplateLoader, Platform) {
|
||||
var _this = this;
|
||||
|
||||
angular.extend(this, ionic.controllers.NavController.prototype);
|
||||
|
||||
var pushInAnimation = $scope.pushInAnimation || 'slide-in-left';
|
||||
var pushOutAnimation = $scope.pushOutAnimation || 'slide-out-left';
|
||||
var popInAnimation = $scope.popInAnimation || 'slide-in-right';
|
||||
var popOutAnimation = $scope.popOutAnimation || 'slide-out-right';
|
||||
|
||||
// Remove some push classnames
|
||||
var cleanElementAnimations = function(el) {
|
||||
el.removeClass(pushInAnimation);
|
||||
el.removeClass(pushOutAnimation);
|
||||
el.removeClass(popInAnimation);
|
||||
el.removeClass(popOutAnimation);
|
||||
}
|
||||
|
||||
/**
|
||||
* Push a template onto the navigation stack.
|
||||
* @param {string} templateUrl the URL of the template to load.
|
||||
*/
|
||||
this.pushFromTemplate = ionic.throttle(function(templateUrl) {
|
||||
var childScope = $scope.$new();
|
||||
childScope.isVisible = true;
|
||||
var last = _this.getTopController();
|
||||
|
||||
// Load the given template
|
||||
TemplateLoader.load(templateUrl).then(function(templateString) {
|
||||
|
||||
// Compile the template with the new scrope, and append it to the navigation's content area
|
||||
// Compile the template with the new scope, and append
|
||||
// it to the navigation's content area
|
||||
var el = $compile(templateString)(childScope, function(cloned, scope) {
|
||||
var content = angular.element($element[0].querySelector('.content, .scroll'));
|
||||
$animate.enter(cloned, angular.element(content));
|
||||
|
||||
// If there was a last controller, remove it and mark the new
|
||||
// one to animate
|
||||
if(last) {
|
||||
// Push animate
|
||||
cleanElementAnimations(last.element);
|
||||
$animate.addClass(last.element, pushOutAnimation, function() {
|
||||
last.element[0].style.display = 'none';
|
||||
last.element.removeClass(pushOutAnimation);
|
||||
});
|
||||
|
||||
}
|
||||
|
||||
|
||||
if(last) {
|
||||
// We will need to animate in the new page since we have an old page
|
||||
cloned.addClass(pushInAnimation);
|
||||
$animate.addClass(cloned, pushInAnimation);
|
||||
}
|
||||
|
||||
$animate.enter(cloned, $element, null, function() {
|
||||
});
|
||||
|
||||
});
|
||||
});
|
||||
}, 300, {
|
||||
@ -31,13 +81,34 @@ angular.module('ionic.ui.nav', ['ionic.service.templateLoad', 'ionic.service.ges
|
||||
|
||||
// Pop function, throttled
|
||||
this.popController = ionic.throttle(function() {
|
||||
_this.pop();
|
||||
$scope.$broadcast('navs.pop');
|
||||
var last = _this.pop();
|
||||
|
||||
var next = _this.getTopController();
|
||||
|
||||
if(last) {
|
||||
|
||||
cleanElementAnimations(last.element);
|
||||
$animate.addClass(last.element, popOutAnimation, function() {
|
||||
last.scope.$destroy();
|
||||
last.element.remove();
|
||||
});
|
||||
}
|
||||
|
||||
// Animate the next one in
|
||||
if(next) {
|
||||
cleanElementAnimations(next.element);
|
||||
$animate.addClass(next.element, popInAnimation)
|
||||
next.element[0].style.display = 'block';
|
||||
}
|
||||
|
||||
$scope.$parent.$broadcast('navigation.pop');
|
||||
}, 300, {
|
||||
trailing: false
|
||||
});
|
||||
|
||||
|
||||
// Extend the low-level navigation controller
|
||||
// for this angular controller
|
||||
ionic.controllers.NavController.call(this, {
|
||||
content: {
|
||||
},
|
||||
@ -79,8 +150,19 @@ angular.module('ionic.ui.nav', ['ionic.service.templateLoad', 'ionic.service.ges
|
||||
* nav-content directive when it is linked to a scope on the page.
|
||||
*/
|
||||
$scope.pushController = function(scope, element) {
|
||||
_this.push(scope);
|
||||
$scope.$broadcast('navs.push', scope);
|
||||
_this.push({
|
||||
scope: scope,
|
||||
element: element
|
||||
});
|
||||
$scope.$parent.$broadcast('navigation.push', scope);
|
||||
};
|
||||
|
||||
this.pushController = function(scope, element) {
|
||||
_this.push({
|
||||
scope: scope,
|
||||
element: element
|
||||
});
|
||||
$scope.$parent.$broadcast('navigation.push', scope);
|
||||
};
|
||||
|
||||
$scope.navController = this;
|
||||
@ -91,7 +173,10 @@ angular.module('ionic.ui.nav', ['ionic.service.templateLoad', 'ionic.service.ges
|
||||
});
|
||||
}])
|
||||
|
||||
.directive('navs', function() {
|
||||
/**
|
||||
* The main directive for the controller.
|
||||
*/
|
||||
.directive('navigation', function() {
|
||||
return {
|
||||
restrict: 'E',
|
||||
replace: true,
|
||||
@ -99,26 +184,54 @@ angular.module('ionic.ui.nav', ['ionic.service.templateLoad', 'ionic.service.ges
|
||||
controller: 'NavCtrl',
|
||||
//templateUrl: 'ext/angular/tmpl/ionicTabBar.tmpl.html',
|
||||
template: '<div class="view" ng-transclude></div>',
|
||||
scope: {
|
||||
first: '@',
|
||||
pushAnimation: '@',
|
||||
popAnimation: '@'
|
||||
},
|
||||
link: function($scope, $element, $attr, navCtrl) {
|
||||
$scope.pushAnimation = $scope.pushAnimation || 'slide-in-left';
|
||||
$scope.popAnimation = $scope.popAnimation || 'slide-out-left';
|
||||
|
||||
if($scope.first) {
|
||||
navCtrl.pushFromTemplate($scope.first);
|
||||
}
|
||||
}
|
||||
};
|
||||
})
|
||||
|
||||
/**
|
||||
* Our Nav Bar directive which updates as the controller state changes.
|
||||
*/
|
||||
.directive('navBar', function() {
|
||||
return {
|
||||
restrict: 'E',
|
||||
require: '^navs',
|
||||
require: '^navigation',
|
||||
replace: true,
|
||||
scope: {
|
||||
type: '@',
|
||||
backButtonType: '@',
|
||||
backButtonLabel: '@',
|
||||
backButtonIcon: '@',
|
||||
alignTitle: '@'
|
||||
},
|
||||
template: '<header class="bar bar-header nav-bar" ng-class="{hidden: !navController.navBar.isVisible}">' +
|
||||
'<button ng-click="goBack()" class="button" ng-if="navController.controllers.length > 1" ng-class="backButtonType">Back</button>' +
|
||||
'<h1 class="title">{{navController.getTopController().title}}</h1>' +
|
||||
'<button ng-click="goBack()" class="button" ng-if="navController.controllers.length > 1" ng-class="backButtonType" ng-bind-html="backButtonContent"></button>' +
|
||||
'<h1 class="title">{{navController.getTopController().scope.title}}</h1>' +
|
||||
'</header>',
|
||||
link: function($scope, $element, $attr, navCtrl) {
|
||||
var backButton;
|
||||
|
||||
$scope.backButtonContent = '';
|
||||
|
||||
if($scope.backButtonIcon) {
|
||||
$scope.backButtonContent += '<i class="icon ' + $scope.backButtonIcon + '"></i>';
|
||||
}
|
||||
if($scope.backButtonLabel) {
|
||||
$scope.backButtonContent += ' ' + $scope.backButtonLabel
|
||||
}
|
||||
|
||||
|
||||
$scope.navController = navCtrl;
|
||||
|
||||
$scope.goBack = function() {
|
||||
@ -135,12 +248,12 @@ angular.module('ionic.ui.nav', ['ionic.service.templateLoad', 'ionic.service.ges
|
||||
|
||||
$scope.headerBarView = hb;
|
||||
|
||||
$scope.$parent.$on('navs.push', function() {
|
||||
$scope.$parent.$on('navigation.push', function() {
|
||||
backButton = angular.element($element[0].querySelector('.button'));
|
||||
backButton.addClass($scope.backButtonType);
|
||||
hb.align();
|
||||
});
|
||||
$scope.$parent.$on('navs.pop', function() {
|
||||
$scope.$parent.$on('navigation.pop', function() {
|
||||
hb.align();
|
||||
});
|
||||
|
||||
@ -151,140 +264,78 @@ angular.module('ionic.ui.nav', ['ionic.service.templateLoad', 'ionic.service.ges
|
||||
};
|
||||
})
|
||||
|
||||
.directive('navContent', ['Gesture', '$animate', '$compile', function(Gesture, $animate, $compile) {
|
||||
|
||||
// We need to animate the new controller into view.
|
||||
var animatePushedController = function(childScope, clone, $element, isForward) {
|
||||
var parent = angular.element($element.parent().parent().parent());
|
||||
|
||||
var title = angular.element(parent[0].querySelector('.title'));
|
||||
|
||||
// Clone the old title and insert it so we can animate it back into place for the new controller
|
||||
var newTitle = angular.element(title.clone());
|
||||
$compile(newTitle)(childScope);
|
||||
title.after(newTitle);
|
||||
// Grab the button so we can slide it in
|
||||
var button = angular.element(parent[0].querySelector('.button'));
|
||||
|
||||
if(isForward) {
|
||||
|
||||
// Slide the button in
|
||||
$animate.addClass(button, childScope.slideButtonInAnimation, function() {
|
||||
$animate.removeClass(button, childScope.slideButtonInAnimation, function() {});
|
||||
})
|
||||
|
||||
// Slide the new title in
|
||||
$animate.addClass(newTitle, childScope.slideTitleInAnimation, function() {
|
||||
$animate.removeClass(newTitle, childScope.slideTitleInAnimation, function() {
|
||||
newTitle.scope().$destroy();
|
||||
newTitle.remove();
|
||||
});
|
||||
});
|
||||
|
||||
// Grab the old title and slide it out
|
||||
var title = $element.parent().parent().parent()[0].querySelector('.title');
|
||||
$animate.addClass(angular.element(title), childScope.slideTitleOutAnimation, function() {
|
||||
$animate.removeClass(angular.element(title), childScope.slideTitleOutAnimation, function() {
|
||||
});
|
||||
});
|
||||
} else {
|
||||
clone.addClass(childScope.slideBackInAnimation);
|
||||
}
|
||||
};
|
||||
.directive('navPage', ['Gesture', '$animate', '$compile', function(Gesture, $animate, $compile) {
|
||||
|
||||
return {
|
||||
restrict: 'ECA',
|
||||
require: '^navs',
|
||||
transclude: 'element',
|
||||
compile: function(element, attr, transclude) {
|
||||
return function($scope, $element, $attr, navCtrl) {
|
||||
var lastParent, lastIndex, childScope, childElement;
|
||||
restrict: 'AC',
|
||||
require: '^navigation',
|
||||
link: function($scope, $element, $attr, navCtrl) {
|
||||
var lastParent, lastIndex, childScope, childElement;
|
||||
|
||||
// Store that we should go forwards on the animation. This toggles
|
||||
// based on the visibility sequence (to support reverse transitions)
|
||||
var lastDirection = null;
|
||||
// Store that we should go forwards on the animation. This toggles
|
||||
// based on the visibility sequence (to support reverse transitions)
|
||||
var lastDirection = null;
|
||||
|
||||
$scope.title = $attr.title;
|
||||
$scope.pushAnimation = $attr.pushAnimation || 'slide-in-left';
|
||||
$scope.popAnimation = $attr.popAnimation || 'slide-in-right';
|
||||
$scope.slideTitleInAnimation = $attr.slideTitleInAnimation || 'bar-title-in';
|
||||
$scope.slideTitleOutAnimation = $attr.slideTitleOutAnimation || 'bar-title-out';
|
||||
$scope.slideButtonInAnimation = $attr.slideButtonInAnimation || 'bar-button-in';
|
||||
$scope.slideButtonOutAnimation = $attr.slideButtonOutAnimation || 'bar-button-out';
|
||||
$scope.title = $attr.title;
|
||||
|
||||
if($attr.navBar === "false") {
|
||||
navCtrl.hideNavBar();
|
||||
} else {
|
||||
navCtrl.showNavBar();
|
||||
}
|
||||
|
||||
$scope.visibilityChanged = function(direction) {
|
||||
lastDirection = direction;
|
||||
|
||||
if($scope.isVisible) {
|
||||
$scope.$broadcast('navContent.shown');
|
||||
} else {
|
||||
$scope.$broadcast('navContent.hidden');
|
||||
}
|
||||
|
||||
if(!childElement) {
|
||||
return;
|
||||
}
|
||||
|
||||
var clone = childElement;
|
||||
|
||||
if(direction == 'push') {
|
||||
clone.addClass(childScope.pushAnimation);
|
||||
clone.removeClass(childScope.popAnimation);
|
||||
} else if(direction == 'pop') {
|
||||
clone.addClass(childScope.popAnimation);
|
||||
clone.removeClass(childScope.pushAnimation);
|
||||
}
|
||||
};
|
||||
|
||||
// Push this controller onto the stack
|
||||
$scope.pushController($scope, $element);
|
||||
|
||||
$scope.$watch('isVisible', function(value) {
|
||||
|
||||
if(value) {
|
||||
childScope = $scope.$new();
|
||||
|
||||
transclude(childScope, function(clone) {
|
||||
childElement = clone;
|
||||
|
||||
if(lastDirection == 'push') {
|
||||
clone.addClass(childScope.pushAnimation);
|
||||
} else if(lastDirection == 'pop') {
|
||||
clone.addClass(childScope.popAnimation);
|
||||
}
|
||||
|
||||
$animate.enter(clone, $element.parent(), $element, function() {
|
||||
clone.removeClass(childScope.pushAnimation);
|
||||
clone.removeClass(childScope.popAnimation);
|
||||
});
|
||||
});
|
||||
} else {
|
||||
// Taken from ngIf
|
||||
if(childElement) {
|
||||
// Check if this is visible, and if so, create it and show it
|
||||
$animate.leave(childElement, function() {
|
||||
if(childScope) {
|
||||
childElement.removeClass(childScope.pushAnimation);
|
||||
childElement.removeClass(childScope.popAnimation);
|
||||
}
|
||||
});
|
||||
childElement = undefined;
|
||||
}
|
||||
if(childScope) {
|
||||
childScope.$destroy();
|
||||
childScope = undefined;
|
||||
}
|
||||
}
|
||||
});
|
||||
if($attr.navBar === "false") {
|
||||
navCtrl.hideNavBar();
|
||||
} else {
|
||||
navCtrl.showNavBar();
|
||||
}
|
||||
|
||||
$scope.$on('$destroy', function() {
|
||||
if(childElement) {
|
||||
childElement.remove();
|
||||
}
|
||||
});
|
||||
|
||||
// Push this controller onto the stack
|
||||
navCtrl.pushController($scope, $element);
|
||||
}
|
||||
};
|
||||
}]);
|
||||
}
|
||||
}])
|
||||
|
||||
.directive('navPush', function() {
|
||||
return {
|
||||
restrict: 'A',
|
||||
link: function($scope, $element, $attr) {
|
||||
var templateUrl = $attr.navPush;
|
||||
|
||||
var pushTemplate = function(e) {
|
||||
$scope.$apply(function() {
|
||||
$scope.navController && $scope.navController.pushFromTemplate(templateUrl);
|
||||
});
|
||||
return false;
|
||||
};
|
||||
|
||||
$element.bind('tap', pushTemplate);
|
||||
|
||||
$scope.$on('$destroy', function() {
|
||||
$element.unbind('tap', pushTemplate);
|
||||
});
|
||||
}
|
||||
}
|
||||
})
|
||||
|
||||
.directive('navPop', function() {
|
||||
return {
|
||||
restrict: 'A',
|
||||
link: function($scope, $element, $attr, navCtrl) {
|
||||
var popTemplate = function(e) {
|
||||
$scope.$apply(function() {
|
||||
$scope.navController && navController.pop();
|
||||
});
|
||||
return false;
|
||||
};
|
||||
|
||||
$element.bind('tap', popTemplate);
|
||||
|
||||
$scope.$on('$destroy', function() {
|
||||
$element.unbind('tap', popTemplate);
|
||||
});
|
||||
}
|
||||
}
|
||||
})
|
||||
|
||||
})();
|
||||
|
||||
Reference in New Issue
Block a user