diff --git a/src/ng/animator.js b/src/ng/animator.js index 662ed6834ea0..667962dbbb25 100644 --- a/src/ng/animator.js +++ b/src/ng/animator.js @@ -194,6 +194,7 @@ var $AnimatorProvider = function() { * Reveals the element by setting the CSS property `display` to `block` and then starts the show animation directly after. * * @param {jQuery/jqLite element} element the element that will be rendered visible or hidden + * @param {boolean} instant Should the actual animation be shown or skip it? (useful for setting initial state) */ animator.show = animateActionFactory('show', show, noop); @@ -206,6 +207,7 @@ var $AnimatorProvider = function() { * Starts the hide animation first and sets the CSS `display` property to `none` upon completion. * * @param {jQuery/jqLite element} element the element that will be rendered visible or hidden + * @param {boolean} instant Should the actual animation be shown or skip it? (useful for setting initial state) */ animator.hide = animateActionFactory('hide', noop, hide); return animator; @@ -235,10 +237,11 @@ var $AnimatorProvider = function() { afterFn(element, parent, after); return; } + var instant = (typeof(parent) === 'boolean') && parent === true; - element.addClass(setupClass); + if (!instant) element.addClass(setupClass); beforeFn(element, parent, after); - if (element.length == 0) return done(); + if (element.length == 0 || instant) return done(); var memento = (polyfillSetup || noop)(element); diff --git a/src/ng/directive/ngShowHide.js b/src/ng/directive/ngShowHide.js index 7ccc0aa06b71..7ea3bc7f35f3 100644 --- a/src/ng/directive/ngShowHide.js +++ b/src/ng/directive/ngShowHide.js @@ -102,8 +102,8 @@ var ngShowDirective = ['$animator', function($animator) { return function(scope, element, attr) { var animate = $animator(scope, attr); - scope.$watch(attr.ngShow, function ngShowWatchAction(value){ - animate[toBoolean(value) ? 'show' : 'hide'](element); + scope.$watch(attr.ngShow, function ngShowWatchAction(value, oldValue){ + animate[toBoolean(value) ? 'show' : 'hide'](element, value === oldValue); }); }; }]; @@ -211,8 +211,8 @@ var ngShowDirective = ['$animator', function($animator) { var ngHideDirective = ['$animator', function($animator) { return function(scope, element, attr) { var animate = $animator(scope, attr); - scope.$watch(attr.ngHide, function ngHideWatchAction(value){ - animate[toBoolean(value) ? 'hide' : 'show'](element); + scope.$watch(attr.ngHide, function ngHideWatchAction(value, oldValue){ + animate[toBoolean(value) ? 'hide' : 'show'](element, value === oldValue); }); }; }]; diff --git a/test/ng/directive/ngShowHideSpec.js b/test/ng/directive/ngShowHideSpec.js index d1d314e72912..afea0b513e66 100644 --- a/test/ng/directive/ngShowHideSpec.js +++ b/test/ng/directive/ngShowHideSpec.js @@ -69,33 +69,42 @@ describe('ngShow / ngHide - ngAnimate', function() { '' )($scope); $scope.$digest(); + // initially no animation should be fired, lets check + expect(element.attr('class')).not.toContain('custom-show-start'); + expect(element.attr('class')).not.toContain('custom-show-setup'); + // lets fire hide animation + $scope.on = false; + $scope.$digest(); if ($sniffer.supportsTransitions) { - expect(element.attr('class')).toContain('custom-show-setup'); + expect(element.attr('class')).toContain('custom-hide-setup'); window.setTimeout.expect(1).process(); - - expect(element.attr('class')).toContain('custom-show-start'); + expect(element.attr('class')).toContain('custom-hide-start'); window.setTimeout.expect(1000).process(); } else { expect(window.setTimeout.queue).toEqual([]); } - expect(element.attr('class')).not.toContain('custom-show-start'); - expect(element.attr('class')).not.toContain('custom-show-setup'); + expect(element.attr('class')).not.toContain('custom-hide-start'); + expect(element.attr('class')).not.toContain('custom-hide-setup'); - $scope.on = false; + // and show animation: + $scope.on = true; $scope.$digest(); + if ($sniffer.supportsTransitions) { - expect(element.attr('class')).toContain('custom-hide-setup'); + expect(element.attr('class')).toContain('custom-show-setup'); window.setTimeout.expect(1).process(); - expect(element.attr('class')).toContain('custom-hide-start'); + + expect(element.attr('class')).toContain('custom-show-start'); window.setTimeout.expect(1000).process(); } else { expect(window.setTimeout.queue).toEqual([]); } - expect(element.attr('class')).not.toContain('custom-hide-start'); - expect(element.attr('class')).not.toContain('custom-hide-setup'); + expect(element.attr('class')).not.toContain('custom-show-start'); + expect(element.attr('class')).not.toContain('custom-show-setup'); + })); }); @@ -111,34 +120,43 @@ describe('ngShow / ngHide - ngAnimate', function() { '' )($scope); $scope.$digest(); + // initially no animation should be fired, lets check + expect(element.attr('class')).not.toContain('custom-hide-start'); + expect(element.attr('class')).not.toContain('custom-hide-setup'); + + // lets fire show animation + $scope.off = false; + $scope.$digest(); if ($sniffer.supportsTransitions) { - expect(element.attr('class')).toContain('custom-hide-setup'); + expect(element.attr('class')).toContain('custom-show-setup'); window.setTimeout.expect(1).process(); - - expect(element.attr('class')).toContain('custom-hide-start'); + expect(element.attr('class')).toContain('custom-show-start'); window.setTimeout.expect(1000).process(); } else { expect(window.setTimeout.queue).toEqual([]); } - expect(element.attr('class')).not.toContain('custom-hide-start'); - expect(element.attr('class')).not.toContain('custom-hide-setup'); + expect(element.attr('class')).not.toContain('custom-show-start'); + expect(element.attr('class')).not.toContain('custom-show-setup'); - $scope.off = false; + // lets fire hide animation + $scope.off = true; $scope.$digest(); if ($sniffer.supportsTransitions) { - expect(element.attr('class')).toContain('custom-show-setup'); + expect(element.attr('class')).toContain('custom-hide-setup'); window.setTimeout.expect(1).process(); - expect(element.attr('class')).toContain('custom-show-start'); + + expect(element.attr('class')).toContain('custom-hide-start'); window.setTimeout.expect(1000).process(); } else { expect(window.setTimeout.queue).toEqual([]); } - expect(element.attr('class')).not.toContain('custom-show-start'); - expect(element.attr('class')).not.toContain('custom-show-setup'); + expect(element.attr('class')).not.toContain('custom-hide-start'); + expect(element.attr('class')).not.toContain('custom-hide-setup'); + })); }); });