diff options
| author | Pete Bacon Darwin | 2013-11-02 09:22:26 +0000 | 
|---|---|---|
| committer | Jeff Cross | 2013-11-06 00:14:11 -0800 | 
| commit | d378f5500ab2eef0779338336c6a95656505ebb8 (patch) | |
| tree | b824ce7a50df0427cc86fb2d50813e47e76f73ac | |
| parent | 9470080762aecca5285d0f5cac4ae01540bbad4c (diff) | |
| download | angular.js-d378f5500ab2eef0779338336c6a95656505ebb8.tar.bz2 | |
fix(ngInclude): only run anchorScroll after animation is done
We need to wait until animations have added the content to the document before
trying to `autoscroll` to anchors that may have been inserted.
Fixes #4723
| -rw-r--r-- | src/ng/directive/ngInclude.js | 12 | ||||
| -rw-r--r-- | test/ng/directive/ngIncludeSpec.js | 110 | 
2 files changed, 92 insertions, 30 deletions
| diff --git a/src/ng/directive/ngInclude.js b/src/ng/directive/ngInclude.js index f4b84fcf..7ca9a48b 100644 --- a/src/ng/directive/ngInclude.js +++ b/src/ng/directive/ngInclude.js @@ -176,6 +176,11 @@ var ngIncludeDirective = ['$http', '$templateCache', '$anchorScroll', '$compile'          };          scope.$watch($sce.parseAsResourceUrl(srcExp), function ngIncludeWatchAction(src) { +          var afterAnimation = function() { +            if (isDefined(autoScrollExp) && (!autoScrollExp || scope.$eval(autoScrollExp))) { +              $anchorScroll(); +            } +          };            var thisChangeId = ++changeCounter;            if (src) { @@ -190,13 +195,8 @@ var ngIncludeDirective = ['$http', '$templateCache', '$anchorScroll', '$compile'                  currentElement = clone;                  currentElement.html(response); -                $animate.enter(currentElement, null, $element); +                $animate.enter(currentElement, null, $element, afterAnimation);                  $compile(currentElement.contents())(currentScope); - -                if (isDefined(autoScrollExp) && (!autoScrollExp || scope.$eval(autoScrollExp))) { -                  $anchorScroll(); -                } -                  currentScope.$emit('$includeContentLoaded');                  scope.$eval(onloadExp);                }); diff --git a/test/ng/directive/ngIncludeSpec.js b/test/ng/directive/ngIncludeSpec.js index b8b0c16b..beb29da7 100644 --- a/test/ng/directive/ngIncludeSpec.js +++ b/test/ng/directive/ngIncludeSpec.js @@ -312,7 +312,7 @@ describe('ngInclude', function() {    })); -  describe('autoscoll', function() { +  describe('autoscroll', function() {      var autoScrollSpy;      function spyOnAnchorScroll() { @@ -328,33 +328,58 @@ describe('ngInclude', function() {        };      } -    function changeTplAndValueTo(template, value) { -      return function($rootScope, $browser) { -        $rootScope.$apply(function() { -          $rootScope.tpl = template; -          $rootScope.value = value; -        }); -      }; -    } - -    beforeEach(module(spyOnAnchorScroll())); +    beforeEach(module(spyOnAnchorScroll(), 'mock.animate'));      beforeEach(inject(          putIntoCache('template.html', 'CONTENT'),          putIntoCache('another.html', 'CONTENT'))); -      it('should call $anchorScroll if autoscroll attribute is present', inject(          compileAndLink('<div><ng:include src="tpl" autoscroll></ng:include></div>'), -        changeTplAndValueTo('template.html'), function() { +        function($rootScope, $animate, $timeout) { + +      $rootScope.$apply(function () { +        $rootScope.tpl = 'template.html'; +      }); + +      expect(autoScrollSpy).not.toHaveBeenCalled(); +      $animate.flushNext('enter'); +      $timeout.flush(); +        expect(autoScrollSpy).toHaveBeenCalledOnce();      })); -    it('should call $anchorScroll if autoscroll evaluates to true', inject( -        compileAndLink('<div><ng:include src="tpl" autoscroll="value"></ng:include></div>'), -        changeTplAndValueTo('template.html', true), -        changeTplAndValueTo('another.html', 'some-string'), -        changeTplAndValueTo('template.html', 100), function() { +    it('should call $anchorScroll if autoscroll evaluates to true', +      inject(function($rootScope, $compile, $animate, $timeout) { + +      element = $compile('<div><ng:include src="tpl" autoscroll="value"></ng:include></div>')($rootScope); + +      $rootScope.$apply(function () { +        $rootScope.tpl = 'template.html'; +        $rootScope.value = true; +      }); + +      $animate.flushNext('enter'); +      $timeout.flush(); + +      $rootScope.$apply(function () { +        $rootScope.tpl = 'another.html'; +        $rootScope.value = 'some-string'; +      }); + +      $animate.flushNext('leave'); +      $animate.flushNext('enter'); +      $timeout.flush(); + +      $rootScope.$apply(function() { +        $rootScope.tpl = 'template.html'; +        $rootScope.value = 100; +      }); + +      $animate.flushNext('leave'); +      $animate.flushNext('enter'); +      $timeout.flush(); +        expect(autoScrollSpy).toHaveBeenCalled();        expect(autoScrollSpy.callCount).toBe(3);      })); @@ -362,18 +387,55 @@ describe('ngInclude', function() {      it('should not call $anchorScroll if autoscroll attribute is not present', inject(          compileAndLink('<div><ng:include src="tpl"></ng:include></div>'), -        changeTplAndValueTo('template.html'), function() { +        function($rootScope, $animate, $timeout) { + +      $rootScope.$apply(function () { +        $rootScope.tpl = 'template.html'; +      }); + +      $animate.flushNext('enter'); +      $timeout.flush();        expect(autoScrollSpy).not.toHaveBeenCalled();      })); -    it('should not call $anchorScroll if autoscroll evaluates to false', inject( -        compileAndLink('<div><ng:include src="tpl" autoscroll="value"></ng:include></div>'), -        changeTplAndValueTo('template.html', false), -        changeTplAndValueTo('template.html', undefined), -        changeTplAndValueTo('template.html', null), function() { +    it('should not call $anchorScroll if autoscroll evaluates to false', +      inject(function($rootScope, $compile, $animate, $timeout) { + +      element = $compile('<div><ng:include src="tpl" autoscroll="value"></ng:include></div>')($rootScope); + +      $rootScope.$apply(function () { +        $rootScope.tpl = 'template.html'; +        $rootScope.value = false; +      }); + +      $animate.flushNext('enter'); +      $timeout.flush(); + +      $rootScope.$apply(function () { +        $rootScope.tpl = 'template.html'; +        $rootScope.value = undefined; +      }); + +      $rootScope.$apply(function () { +        $rootScope.tpl = 'template.html'; +        $rootScope.value = null; +      }); +        expect(autoScrollSpy).not.toHaveBeenCalled();      })); + +    it('should only call $anchorScroll after the "enter" animation completes', inject( +        compileAndLink('<div><ng:include src="tpl" autoscroll></ng:include></div>'), +        function($rootScope, $animate, $timeout) { +          expect(autoScrollSpy).not.toHaveBeenCalled(); + +          $rootScope.$apply("tpl = 'template.html'"); +          $animate.flushNext('enter'); +          $timeout.flush(); + +          expect(autoScrollSpy).toHaveBeenCalledOnce(); +    }));    });  }); | 
