diff --git a/src/collapse/collapse.js b/src/collapse/collapse.js index 5c59f09a2d..9fa692f912 100644 --- a/src/collapse/collapse.js +++ b/src/collapse/collapse.js @@ -1,6 +1,6 @@ angular.module('ui.bootstrap.collapse', []) - .directive('collapse', ['$animate', '$injector', function($animate, $injector) { + .directive('uibCollapse', ['$animate', '$injector', function($animate, $injector) { var $animateCss = $injector.has('$animateCss') ? $injector.get('$animateCss') : null; return { link: function(scope, element, attrs) { @@ -64,7 +64,7 @@ angular.module('ui.bootstrap.collapse', []) .addClass('collapse'); } - scope.$watch(attrs.collapse, function(shouldCollapse) { + scope.$watch(attrs.uibCollapse, function(shouldCollapse) { if (shouldCollapse) { collapse(); } else { diff --git a/src/collapse/collapse.old.js b/src/collapse/collapse.old.js new file mode 100644 index 0000000000..3201a74656 --- /dev/null +++ b/src/collapse/collapse.old.js @@ -0,0 +1,82 @@ +angular.module('ui.bootstrap.collapse') + + .value('$collapseSuppressWarning', false) + + .directive('collapse', ['$animate', '$injector', '$log', '$collapseSuppressWarning', function($animate, $injector, $log, $collapseSuppressWarning) { + var $animateCss = $injector.has('$animateCss') ? $injector.get('$animateCss') : null; + return { + link: function(scope, element, attrs) { + if (!$collapseSuppressWarning) { + $log.warn('collapse is now deprecated. Use uib-collapse instead.'); + } + + function expand() { + element.removeClass('collapse') + .addClass('collapsing') + .attr('aria-expanded', true) + .attr('aria-hidden', false); + + if ($animateCss) { + $animateCss(element, { + addClass: 'in', + easing: 'ease', + to: { height: element[0].scrollHeight + 'px' } + }).start().done(expandDone); + } else { + $animate.addClass(element, 'in', { + to: { height: element[0].scrollHeight + 'px' } + }).then(expandDone); + } + } + + function expandDone() { + element.removeClass('collapsing') + .addClass('collapse') + .css({height: 'auto'}); + } + + function collapse() { + if (!element.hasClass('collapse') && !element.hasClass('in')) { + return collapseDone(); + } + + element + // IMPORTANT: The height must be set before adding "collapsing" class. + // Otherwise, the browser attempts to animate from height 0 (in + // collapsing class) to the given height here. + .css({height: element[0].scrollHeight + 'px'}) + // initially all panel collapse have the collapse class, this removal + // prevents the animation from jumping to collapsed state + .removeClass('collapse') + .addClass('collapsing') + .attr('aria-expanded', false) + .attr('aria-hidden', true); + + if ($animateCss) { + $animateCss(element, { + removeClass: 'in', + to: {height: '0'} + }).start().done(collapseDone); + } else { + $animate.removeClass(element, 'in', { + to: {height: '0'} + }).then(collapseDone); + } + } + + function collapseDone() { + element.css({height: '0'}); // Required so that collapse works when animation is disabled + element.removeClass('collapsing') + .addClass('collapse'); + } + + scope.$watch(attrs.collapse, function(shouldCollapse) { + if (shouldCollapse) { + collapse(); + } else { + expand(); + } + }); + } + }; + }]); diff --git a/src/collapse/docs/demo.html b/src/collapse/docs/demo.html index b05869e0d7..462bda3ba0 100644 --- a/src/collapse/docs/demo.html +++ b/src/collapse/docs/demo.html @@ -1,7 +1,7 @@

-
-
Some content
+
+
Some content
-
\ No newline at end of file +
diff --git a/src/collapse/test/collapse.old.spec.js b/src/collapse/test/collapse.old.spec.js new file mode 100644 index 0000000000..85029b7f1c --- /dev/null +++ b/src/collapse/test/collapse.old.spec.js @@ -0,0 +1,163 @@ +describe('collapse deprecation', function() { + beforeEach(module('ui.bootstrap.collapse')); + beforeEach(module('ngAnimateMock')); + + it('should suppress warning', function() { + module(function($provide) { + $provide.value('$collapseSuppressWarning', true); + }); + + inject(function($compile, $log, $rootScope) { + spyOn($log, 'warn'); + + var element = $compile('
Some Content
')($rootScope); + $rootScope.$digest(); + + expect($log.warn.calls.count()).toBe(0); + }); + }); + + it('should give warning by default', inject(function($compile, $log, $rootScope) { + spyOn($log, 'warn'); + + var element = $compile('
Some Content
')($rootScope); + $rootScope.$digest(); + + expect($log.warn.calls.count()).toBe(1); + expect($log.warn.calls.argsFor(0)).toEqual(['collapse is now deprecated. Use uib-collapse instead.']); + + })); +}); + +describe('collapse directive', function() { + var element, scope, $compile, $animate; + + beforeEach(module('ui.bootstrap.collapse')); + beforeEach(module('ngAnimateMock')); + + beforeEach(inject(function(_$rootScope_, _$compile_, _$animate_) { + scope = _$rootScope_; + $compile = _$compile_; + $animate = _$animate_; + })); + + beforeEach(function() { + element = $compile('
Some Content
')(scope); + angular.element(document.body).append(element); + }); + + afterEach(function() { + element.remove(); + }); + + it('should be hidden on initialization if isCollapsed = true', function() { + scope.isCollapsed = true; + scope.$digest(); + expect(element.height()).toBe(0); + }); + + it('should collapse if isCollapsed = true on subsequent use', function() { + scope.isCollapsed = false; + scope.$digest(); + $animate.flush(); + scope.isCollapsed = true; + scope.$digest(); + $animate.flush(); + expect(element.height()).toBe(0); + }); + + it('should be shown on initialization if isCollapsed = false', function() { + scope.isCollapsed = false; + scope.$digest(); + $animate.flush(); + expect(element.height()).not.toBe(0); + }); + + it('should expand if isCollapsed = false on subsequent use', function() { + scope.isCollapsed = false; + scope.$digest(); + $animate.flush(); + scope.isCollapsed = true; + scope.$digest(); + $animate.flush(); + scope.isCollapsed = false; + scope.$digest(); + $animate.flush(); + expect(element.height()).not.toBe(0); + }); + + it('should expand if isCollapsed = true on subsequent uses', function() { + scope.isCollapsed = false; + scope.$digest(); + $animate.flush(); + scope.isCollapsed = true; + scope.$digest(); + $animate.flush(); + scope.isCollapsed = false; + scope.$digest(); + $animate.flush(); + scope.isCollapsed = true; + scope.$digest(); + $animate.flush(); + expect(element.height()).toBe(0); + }); + + it('should change aria-expanded attribute', function() { + scope.isCollapsed = false; + scope.$digest(); + $animate.flush(); + expect(element.attr('aria-expanded')).toBe('true'); + + scope.isCollapsed = true; + scope.$digest(); + $animate.flush(); + expect(element.attr('aria-expanded')).toBe('false'); + }); + + it('should change aria-hidden attribute', function() { + scope.isCollapsed = false; + scope.$digest(); + $animate.flush(); + expect(element.attr('aria-hidden')).toBe('false'); + + scope.isCollapsed = true; + scope.$digest(); + $animate.flush(); + expect(element.attr('aria-hidden')).toBe('true'); + }); + + describe('dynamic content', function() { + var element; + + beforeEach(function() { + element = angular.element('

Initial content

Additional content
'); + $compile(element)(scope); + angular.element(document.body).append(element); + }); + + afterEach(function() { + element.remove(); + }); + + it('should grow accordingly when content size inside collapse increases', function() { + scope.exp = false; + scope.isCollapsed = false; + scope.$digest(); + var collapseHeight = element.height(); + scope.exp = true; + $animate.flush(); + scope.$digest(); + expect(element.height()).toBeGreaterThan(collapseHeight); + }); + + it('should shrink accordingly when content size inside collapse decreases', function() { + scope.exp = true; + scope.isCollapsed = false; + scope.$digest(); + var collapseHeight = element.height(); + scope.exp = false; + scope.$digest(); + expect(element.height()).toBeLessThan(collapseHeight); + }); + }); +}); diff --git a/src/collapse/test/collapse.spec.js b/src/collapse/test/collapse.spec.js index 5ffdd83bf7..a9aedfc907 100644 --- a/src/collapse/test/collapse.spec.js +++ b/src/collapse/test/collapse.spec.js @@ -10,7 +10,7 @@ describe('collapse directive', function() { })); beforeEach(function() { - element = $compile('
Some Content
')(scope); + element = $compile('
Some Content
')(scope); angular.element(document.body).append(element); }); @@ -98,7 +98,7 @@ describe('collapse directive', function() { var element; beforeEach(function() { - element = angular.element('

Initial content

Additional content
'); + element = angular.element('

Initial content

Additional content
'); $compile(element)(scope); angular.element(document.body).append(element); });