This commit is contained in:
Max Lynch
2013-11-11 21:18:48 -06:00
parent 58dc717ab9
commit 56a64b8bc6
7 changed files with 172 additions and 76 deletions

6
dist/css/ionic.css vendored
View File

@ -4602,7 +4602,7 @@ a.button {
@-webkit-keyframes slideOutRight { @-webkit-keyframes slideOutRight {
0% { 0% {
-webkit-transform: translate3d(0%, 0, 0); } -webkit-transform: translate3d(0, 0, 0); }
100% { 100% {
-webkit-transform: translate3d(100%, 0, 0); } } -webkit-transform: translate3d(100%, 0, 0); } }
@ -4641,12 +4641,12 @@ a.button {
-webkit-animation-name: slideOutRight; } -webkit-animation-name: slideOutRight; }
.slide-out-right.ng-enter, .slide-out-right > .ng-enter { .slide-out-right.ng-enter, .slide-out-right > .ng-enter {
-webkit-animation-duration: 2250ms; -webkit-animation-duration: 250ms;
-webkit-animation-fill-mode: both; -webkit-animation-fill-mode: both;
-webkit-animation-timing-function: ease-in-out; -webkit-animation-timing-function: ease-in-out;
-webkit-animation-name: slideOutRight; } -webkit-animation-name: slideOutRight; }
.slide-out-right.ng-leave, .slide-out-right > .ng-leave { .slide-out-right.ng-leave, .slide-out-right > .ng-leave {
-webkit-animation-duration: 2250ms; -webkit-animation-duration: 250ms;
-webkit-animation-fill-mode: both; -webkit-animation-fill-mode: both;
-webkit-animation-timing-function: ease-in-out; -webkit-animation-timing-function: ease-in-out;
-webkit-animation-name: slideInRight; } -webkit-animation-name: slideInRight; }

View File

@ -788,7 +788,7 @@ angular.module('ionic.ui.nav', ['ionic.service.templateLoad', 'ionic.service.ges
* Push a template onto the navigation stack. * Push a template onto the navigation stack.
* @param {string} templateUrl the URL of the template to load. * @param {string} templateUrl the URL of the template to load.
*/ */
this.pushFromTemplate = function(templateUrl) { this.pushFromTemplate = ionic.debounce(function(templateUrl) {
var childScope = $scope.$new(); var childScope = $scope.$new();
childScope.isVisible = true; childScope.isVisible = true;
@ -798,13 +798,10 @@ angular.module('ionic.ui.nav', ['ionic.service.templateLoad', 'ionic.service.ges
// Compile the template with the new scrope, and append it to the navigation's content area // Compile the template with the new scrope, and append it to the navigation's content area
var el = $compile(templateString)(childScope, function(cloned, scope) { var el = $compile(templateString)(childScope, function(cloned, scope) {
var content = angular.element($element[0].querySelector('.content, .scroll')); var content = angular.element($element[0].querySelector('.content, .scroll'));
//content.append(cloned);
//angular.element(content).append(cloned);
$animate.enter(cloned, angular.element(content)); $animate.enter(cloned, angular.element(content));
}); });
}); });
}; }, 100, true);
/** /**
* Push a controller to the stack. This is called by the child * Push a controller to the stack. This is called by the child
@ -909,7 +906,7 @@ angular.module('ionic.ui.nav', ['ionic.service.templateLoad', 'ionic.service.ges
// Store that we should go forwards on the animation. This toggles // Store that we should go forwards on the animation. This toggles
// based on the visibility sequence (to support reverse transitions) // based on the visibility sequence (to support reverse transitions)
var wasVisible = null; var lastDirection = null;
$scope.title = $attr.title; $scope.title = $attr.title;
$scope.pushAnimation = $attr.pushAnimation || 'slide-in-left'; $scope.pushAnimation = $attr.pushAnimation || 'slide-in-left';
@ -925,6 +922,24 @@ angular.module('ionic.ui.nav', ['ionic.service.templateLoad', 'ionic.service.ges
navCtrl.showNavBar(); navCtrl.showNavBar();
} }
$scope.visibilityChanged = function(direction) {
lastDirection = direction;
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 // Push this controller onto the stack
$scope.pushController($scope, $element); $scope.pushController($scope, $element);
@ -936,39 +951,33 @@ angular.module('ionic.ui.nav', ['ionic.service.templateLoad', 'ionic.service.ges
transclude(childScope, function(clone) { transclude(childScope, function(clone) {
childElement = clone; childElement = clone;
// Check if this is visible, and if so, create it and show it if(lastDirection == 'push') {
if(wasVisible === false) {
clone.removeClass(childScope.pushAnimation);
clone.addClass(childScope.popAnimation);
} else {
clone.addClass(childScope.pushAnimation); clone.addClass(childScope.pushAnimation);
clone.removeClass(childScope.popAnimation); } else if(lastDirection == 'pop') {
clone.addClass(childScope.popAnimation);
} }
$animate.enter(clone, $element.parent(), $element); $animate.enter(clone, $element.parent(), $element, function() {
wasVisible = true; clone.removeClass(childScope.pushAnimation);
clone.removeClass(childScope.popAnimation);
});
}); });
} else { } else {
// Taken from ngIf // Taken from ngIf
if(childElement) { if(childElement) {
var clone = childElement;
// Check if this is visible, and if so, create it and show it // Check if this is visible, and if so, create it and show it
if(wasVisible === false) { $animate.leave(childElement, function() {
clone.removeClass(childScope.pushAnimation); if(childScope) {
clone.addClass(childScope.popAnimation); childElement.removeClass(childScope.pushAnimation);
} else { childElement.removeClass(childScope.popAnimation);
clone.addClass(childScope.pushAnimation); }
clone.removeClass(childScope.popAnimation); });
}
$animate.leave(childElement);
childElement = undefined; childElement = undefined;
wasVisible = false;
} }
if(childScope) { if(childScope) {
childScope.$destroy(); childScope.$destroy();
childScope = undefined; childScope = undefined;
} }
} }
}); });
} }

59
dist/js/ionic.js vendored
View File

@ -1837,9 +1837,16 @@ window.ionic = {
; ;
(function(ionic) { (function(ionic) {
/**
* Various utilities used throughout Ionic
*
* Some of these are adopted from underscore.js and backbone.js, both also MIT licensed.
*/
ionic.Utils = { ionic.Utils = {
// Return a function that will be called with the given context /**
* Return a function that will be called with the given context
*/
proxy: function(func, context) { proxy: function(func, context) {
var args = Array.prototype.slice.call(arguments, 2); var args = Array.prototype.slice.call(arguments, 2);
return function() { return function() {
@ -1847,6 +1854,41 @@ window.ionic = {
}; };
}, },
/**
* Only call a function once in the given interval.
*
* @param func {Function} the function to call
* @param wait {int} how long to wait before/after to allow function calls
* @param immediate {boolean} whether to call immediately or after the wait interval
*/
debounce: function(func, wait, immediate) {
var timeout, args, context, timestamp, result;
return function() {
context = this;
args = arguments;
timestamp = new Date();
var later = function() {
var last = (new Date()) - timestamp;
if (last < wait) {
timeout = setTimeout(later, wait - last);
} else {
timeout = null;
if (!immediate) result = func.apply(context, args);
}
};
var callNow = immediate && !timeout;
if (!timeout) {
timeout = setTimeout(later, wait);
}
if (callNow) result = func.apply(context, args);
return result;
};
},
/**
* Throttle the given fun, only allowing it to be
* called at most every `wait` ms.
*/
throttle: function(func, wait, options) { throttle: function(func, wait, options) {
var context, args, result; var context, args, result;
var timeout = null; var timeout = null;
@ -1931,6 +1973,7 @@ window.ionic = {
ionic.extend = ionic.Utils.extend; ionic.extend = ionic.Utils.extend;
ionic.throttle = ionic.Utils.throttle; ionic.throttle = ionic.Utils.throttle;
ionic.proxy = ionic.Utils.proxy; ionic.proxy = ionic.Utils.proxy;
ionic.debounce = ionic.Utils.debounce;
})(window.ionic); })(window.ionic);
; ;
@ -4188,21 +4231,17 @@ ionic.controllers.NavController = ionic.controllers.ViewController.inherit({
return; return;
// Actually switch the active controllers // Actually switch the active controllers
// Remove the old one
//last && last.detach();
if(last) { if(last) {
last.isVisible = false; last.isVisible = false;
last.visibilityChanged && last.visibilityChanged(); last.visibilityChanged && last.visibilityChanged('push');
} }
// Grab the top controller on the stack // Grab the top controller on the stack
var next = this.controllers[this.controllers.length - 1]; var next = this.controllers[this.controllers.length - 1];
// TODO: No DOM stuff here
//this.content.el.appendChild(next.el);
next.isVisible = true; next.isVisible = true;
next.visibilityChanged && next.visibilityChanged(); // Trigger visibility change, but send 'first' if this is the first page
next.visibilityChanged && next.visibilityChanged(last ? 'push' : 'first');
this._updateNavBar(); this._updateNavBar();
@ -4227,7 +4266,7 @@ ionic.controllers.NavController = ionic.controllers.ViewController.inherit({
last = this.controllers.pop(); last = this.controllers.pop();
if(last) { if(last) {
last.isVisible = false; last.isVisible = false;
last.visibilityChanged && last.visibilityChanged(); last.visibilityChanged && last.visibilityChanged('pop');
} }
// Remove the old one // Remove the old one
@ -4238,7 +4277,7 @@ ionic.controllers.NavController = ionic.controllers.ViewController.inherit({
// TODO: No DOM stuff here // TODO: No DOM stuff here
//this.content.el.appendChild(next.el); //this.content.el.appendChild(next.el);
next.isVisible = true; next.isVisible = true;
next.visibilityChanged && next.visibilityChanged(); next.visibilityChanged && next.visibilityChanged('pop');
// Switch to it (TODO: Animate or such things here) // Switch to it (TODO: Animate or such things here)

View File

@ -60,21 +60,17 @@ ionic.controllers.NavController = ionic.controllers.ViewController.inherit({
return; return;
// Actually switch the active controllers // Actually switch the active controllers
// Remove the old one
//last && last.detach();
if(last) { if(last) {
last.isVisible = false; last.isVisible = false;
last.visibilityChanged && last.visibilityChanged(); last.visibilityChanged && last.visibilityChanged('push');
} }
// Grab the top controller on the stack // Grab the top controller on the stack
var next = this.controllers[this.controllers.length - 1]; var next = this.controllers[this.controllers.length - 1];
// TODO: No DOM stuff here
//this.content.el.appendChild(next.el);
next.isVisible = true; next.isVisible = true;
next.visibilityChanged && next.visibilityChanged(); // Trigger visibility change, but send 'first' if this is the first page
next.visibilityChanged && next.visibilityChanged(last ? 'push' : 'first');
this._updateNavBar(); this._updateNavBar();
@ -99,7 +95,7 @@ ionic.controllers.NavController = ionic.controllers.ViewController.inherit({
last = this.controllers.pop(); last = this.controllers.pop();
if(last) { if(last) {
last.isVisible = false; last.isVisible = false;
last.visibilityChanged && last.visibilityChanged(); last.visibilityChanged && last.visibilityChanged('pop');
} }
// Remove the old one // Remove the old one
@ -110,7 +106,7 @@ ionic.controllers.NavController = ionic.controllers.ViewController.inherit({
// TODO: No DOM stuff here // TODO: No DOM stuff here
//this.content.el.appendChild(next.el); //this.content.el.appendChild(next.el);
next.isVisible = true; next.isVisible = true;
next.visibilityChanged && next.visibilityChanged(); next.visibilityChanged && next.visibilityChanged('pop');
// Switch to it (TODO: Animate or such things here) // Switch to it (TODO: Animate or such things here)

View File

@ -48,7 +48,7 @@ angular.module('ionic.ui.nav', ['ionic.service.templateLoad', 'ionic.service.ges
* Push a template onto the navigation stack. * Push a template onto the navigation stack.
* @param {string} templateUrl the URL of the template to load. * @param {string} templateUrl the URL of the template to load.
*/ */
this.pushFromTemplate = function(templateUrl) { this.pushFromTemplate = ionic.debounce(function(templateUrl) {
var childScope = $scope.$new(); var childScope = $scope.$new();
childScope.isVisible = true; childScope.isVisible = true;
@ -58,13 +58,10 @@ angular.module('ionic.ui.nav', ['ionic.service.templateLoad', 'ionic.service.ges
// Compile the template with the new scrope, and append it to the navigation's content area // Compile the template with the new scrope, and append it to the navigation's content area
var el = $compile(templateString)(childScope, function(cloned, scope) { var el = $compile(templateString)(childScope, function(cloned, scope) {
var content = angular.element($element[0].querySelector('.content, .scroll')); var content = angular.element($element[0].querySelector('.content, .scroll'));
//content.append(cloned);
//angular.element(content).append(cloned);
$animate.enter(cloned, angular.element(content)); $animate.enter(cloned, angular.element(content));
}); });
}); });
}; }, 100, true);
/** /**
* Push a controller to the stack. This is called by the child * Push a controller to the stack. This is called by the child
@ -169,7 +166,7 @@ angular.module('ionic.ui.nav', ['ionic.service.templateLoad', 'ionic.service.ges
// Store that we should go forwards on the animation. This toggles // Store that we should go forwards on the animation. This toggles
// based on the visibility sequence (to support reverse transitions) // based on the visibility sequence (to support reverse transitions)
var wasVisible = null; var lastDirection = null;
$scope.title = $attr.title; $scope.title = $attr.title;
$scope.pushAnimation = $attr.pushAnimation || 'slide-in-left'; $scope.pushAnimation = $attr.pushAnimation || 'slide-in-left';
@ -185,6 +182,24 @@ angular.module('ionic.ui.nav', ['ionic.service.templateLoad', 'ionic.service.ges
navCtrl.showNavBar(); navCtrl.showNavBar();
} }
$scope.visibilityChanged = function(direction) {
lastDirection = direction;
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 // Push this controller onto the stack
$scope.pushController($scope, $element); $scope.pushController($scope, $element);
@ -196,39 +211,33 @@ angular.module('ionic.ui.nav', ['ionic.service.templateLoad', 'ionic.service.ges
transclude(childScope, function(clone) { transclude(childScope, function(clone) {
childElement = clone; childElement = clone;
// Check if this is visible, and if so, create it and show it if(lastDirection == 'push') {
if(wasVisible === false) {
clone.removeClass(childScope.pushAnimation);
clone.addClass(childScope.popAnimation);
} else {
clone.addClass(childScope.pushAnimation); clone.addClass(childScope.pushAnimation);
clone.removeClass(childScope.popAnimation); } else if(lastDirection == 'pop') {
clone.addClass(childScope.popAnimation);
} }
$animate.enter(clone, $element.parent(), $element); $animate.enter(clone, $element.parent(), $element, function() {
wasVisible = true; clone.removeClass(childScope.pushAnimation);
clone.removeClass(childScope.popAnimation);
});
}); });
} else { } else {
// Taken from ngIf // Taken from ngIf
if(childElement) { if(childElement) {
var clone = childElement;
// Check if this is visible, and if so, create it and show it // Check if this is visible, and if so, create it and show it
if(wasVisible === false) { $animate.leave(childElement, function() {
clone.removeClass(childScope.pushAnimation); if(childScope) {
clone.addClass(childScope.popAnimation); childElement.removeClass(childScope.pushAnimation);
} else { childElement.removeClass(childScope.popAnimation);
clone.addClass(childScope.pushAnimation); }
clone.removeClass(childScope.popAnimation); });
}
$animate.leave(childElement);
childElement = undefined; childElement = undefined;
wasVisible = false;
} }
if(childScope) { if(childScope) {
childScope.$destroy(); childScope.$destroy();
childScope = undefined; childScope = undefined;
} }
} }
}); });
} }

View File

@ -1,8 +1,15 @@
(function(ionic) { (function(ionic) {
/**
* Various utilities used throughout Ionic
*
* Some of these are adopted from underscore.js and backbone.js, both also MIT licensed.
*/
ionic.Utils = { ionic.Utils = {
// Return a function that will be called with the given context /**
* Return a function that will be called with the given context
*/
proxy: function(func, context) { proxy: function(func, context) {
var args = Array.prototype.slice.call(arguments, 2); var args = Array.prototype.slice.call(arguments, 2);
return function() { return function() {
@ -10,6 +17,41 @@
}; };
}, },
/**
* Only call a function once in the given interval.
*
* @param func {Function} the function to call
* @param wait {int} how long to wait before/after to allow function calls
* @param immediate {boolean} whether to call immediately or after the wait interval
*/
debounce: function(func, wait, immediate) {
var timeout, args, context, timestamp, result;
return function() {
context = this;
args = arguments;
timestamp = new Date();
var later = function() {
var last = (new Date()) - timestamp;
if (last < wait) {
timeout = setTimeout(later, wait - last);
} else {
timeout = null;
if (!immediate) result = func.apply(context, args);
}
};
var callNow = immediate && !timeout;
if (!timeout) {
timeout = setTimeout(later, wait);
}
if (callNow) result = func.apply(context, args);
return result;
};
},
/**
* Throttle the given fun, only allowing it to be
* called at most every `wait` ms.
*/
throttle: function(func, wait, options) { throttle: function(func, wait, options) {
var context, args, result; var context, args, result;
var timeout = null; var timeout = null;
@ -94,5 +136,6 @@
ionic.extend = ionic.Utils.extend; ionic.extend = ionic.Utils.extend;
ionic.throttle = ionic.Utils.throttle; ionic.throttle = ionic.Utils.throttle;
ionic.proxy = ionic.Utils.proxy; ionic.proxy = ionic.Utils.proxy;
ionic.debounce = ionic.Utils.debounce;
})(window.ionic); })(window.ionic);

View File

@ -33,7 +33,7 @@
} }
@-webkit-keyframes slideOutRight { @-webkit-keyframes slideOutRight {
0% { 0% {
-webkit-transform: translate3d(0%,0,0); -webkit-transform: translate3d(0,0,0);
} }
100% { 100% {
-webkit-transform: translate3d(100%,0,0); -webkit-transform: translate3d(100%,0,0);
@ -87,13 +87,13 @@
.slide-out-right { .slide-out-right {
&.ng-enter, > .ng-enter { &.ng-enter, > .ng-enter {
-webkit-animation-duration: 2250ms; -webkit-animation-duration: 250ms;
-webkit-animation-fill-mode: both; -webkit-animation-fill-mode: both;
-webkit-animation-timing-function: ease-in-out; -webkit-animation-timing-function: ease-in-out;
-webkit-animation-name: slideOutRight; -webkit-animation-name: slideOutRight;
} }
&.ng-leave, > .ng-leave { &.ng-leave, > .ng-leave {
-webkit-animation-duration: 2250ms; -webkit-animation-duration: 250ms;
-webkit-animation-fill-mode: both; -webkit-animation-fill-mode: both;
-webkit-animation-timing-function: ease-in-out; -webkit-animation-timing-function: ease-in-out;
-webkit-animation-name: slideInRight; -webkit-animation-name: slideInRight;