Skip to content
This repository was archived by the owner on May 29, 2019. It is now read-only.

Commit cadc0f9

Browse files
feat(collapse): make collapse work with bootstrap3
Closes #1240 If starting out collapsed, the expand animation would jump since the `initialAnimSkip` was still `true`.
1 parent d04a063 commit cadc0f9

File tree

1 file changed

+64
-71
lines changed

1 file changed

+64
-71
lines changed

Diff for: src/collapse/collapse.js

+64-71
Original file line numberDiff line numberDiff line change
@@ -1,82 +1,75 @@
1-
angular.module('ui.bootstrap.collapse',['ui.bootstrap.transition'])
1+
angular.module('ui.bootstrap.collapse', ['ui.bootstrap.transition'])
22

3-
// The collapsible directive indicates a block of html that will expand and collapse
4-
.directive('collapse', ['$transition', function($transition) {
5-
// CSS transitions don't work with height: auto, so we have to manually change the height to a
6-
// specific value and then once the animation completes, we can reset the height to auto.
7-
// Unfortunately if you do this while the CSS transitions are specified (i.e. in the CSS class
8-
// "collapse") then you trigger a change to height 0 in between.
9-
// The fix is to remove the "collapse" CSS class while changing the height back to auto - phew!
10-
var fixUpHeight = function(scope, element, height) {
11-
// We remove the collapse CSS class to prevent a transition when we change to height: auto
12-
element.removeClass('collapse');
13-
element.css({ height: height });
14-
// It appears that reading offsetWidth makes the browser realise that we have changed the
15-
// height already :-/
16-
var x = element[0].offsetWidth;
17-
element.addClass('collapse');
18-
};
3+
.directive('collapse', ['$transition', function ($transition, $timeout) {
194

20-
return {
21-
link: function(scope, element, attrs) {
5+
return {
6+
link: function (scope, element, attrs) {
227

23-
var isCollapsed;
24-
var initialAnimSkip = true;
8+
var initialAnimSkip = true;
9+
var currentTransition;
2510

26-
scope.$watch(attrs.collapse, function(value) {
27-
if (value) {
28-
collapse();
29-
} else {
30-
expand();
11+
function resetCurrentTransition() {
12+
currentTransition = undefined;
3113
}
32-
});
33-
3414

35-
var currentTransition;
36-
var doTransition = function(change) {
37-
if ( currentTransition ) {
38-
currentTransition.cancel();
15+
function doTransition(change) {
16+
if (currentTransition) {
17+
currentTransition.cancel();
18+
}
19+
(currentTransition = $transition(element, change)).then(resetCurrentTransition, resetCurrentTransition);
20+
return currentTransition;
3921
}
40-
currentTransition = $transition(element,change);
41-
currentTransition.then(
42-
function() { currentTransition = undefined; },
43-
function() { currentTransition = undefined; }
44-
);
45-
return currentTransition;
46-
};
4722

48-
var expand = function() {
49-
if (initialAnimSkip) {
50-
initialAnimSkip = false;
51-
if ( !isCollapsed ) {
52-
fixUpHeight(scope, element, 'auto');
53-
element.addClass('in');
23+
function expand() {
24+
if (initialAnimSkip) {
25+
initialAnimSkip = false;
26+
element.removeClass('collapsing');
27+
element.addClass('collapse in');
28+
element.css({height: 'auto'});
29+
} else {
30+
element.removeClass('collapse').addClass('collapsing');
31+
doTransition({ height: element[0].scrollHeight + 'px' }).then(function () {
32+
element.removeClass('collapsing');
33+
element.addClass('collapse in');
34+
element.css({height: 'auto'});
35+
});
5436
}
55-
} else {
56-
doTransition({ height : element[0].scrollHeight + 'px' })
57-
.then(function() {
58-
// This check ensures that we don't accidentally update the height if the user has closed
59-
// the group while the animation was still running
60-
if ( !isCollapsed ) {
61-
fixUpHeight(scope, element, 'auto');
62-
element.addClass('in');
63-
}
64-
});
6537
}
66-
isCollapsed = false;
67-
};
68-
69-
var collapse = function() {
70-
isCollapsed = true;
71-
element.removeClass('in');
72-
if (initialAnimSkip) {
73-
initialAnimSkip = false;
74-
fixUpHeight(scope, element, 0);
75-
} else {
76-
fixUpHeight(scope, element, element[0].scrollHeight + 'px');
77-
doTransition({'height':'0'});
38+
39+
function collapse() {
40+
if (initialAnimSkip) {
41+
initialAnimSkip = false;
42+
element.removeClass('collapsing');
43+
element.addClass('collapse');
44+
element.css({height: 0});
45+
} else {
46+
// CSS transitions don't work with height: auto, so we have to manually change the height to a specific value
47+
element.css({ height: element[0].scrollHeight + 'px' });
48+
//trigger reflow so a browser relaizes that height was updated from auto to a specific value
49+
var x = element[0].offsetWidth;
50+
51+
element.removeClass('collapse in').addClass('collapsing');
52+
53+
doTransition({ height: 0 }).then(function () {
54+
element.removeClass('collapsing');
55+
element.addClass('collapse');
56+
});
57+
}
7858
}
79-
};
80-
}
81-
};
82-
}]);
59+
60+
scope.$watch(attrs.collapse, function (shouldCollapse) {
61+
if (shouldCollapse) {
62+
collapse();
63+
} else {
64+
expand();
65+
}
66+
});
67+
68+
}
69+
};
70+
}]);
71+
72+
//TODO:
73+
//- refactor to remove code duplication
74+
//- corner cases - what happens in animation is in progress?
75+
//- tests based on the DOM state / classes

0 commit comments

Comments
 (0)