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

Commit 517dff6

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 3db699d commit 517dff6

File tree

1 file changed

+67
-69
lines changed

1 file changed

+67
-69
lines changed

src/collapse/collapse.js

+67-69
Original file line numberDiff line numberDiff line change
@@ -1,83 +1,81 @@
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 doTransition(change) {
12+
var newTransition = $transition(element, change);
13+
if (currentTransition) {
14+
currentTransition.cancel();
15+
}
16+
currentTransition = newTransition;
17+
newTransition.then(newTransitionDone, newTransitionDone);
18+
return newTransition;
19+
20+
function newTransitionDone() {
21+
// Make sure it's this transition, otherwise, leave it alone.
22+
if (currentTransition === newTransition) {
23+
currentTransition = undefined;
24+
}
25+
}
26+
}
27+
28+
function expand() {
29+
if (initialAnimSkip) {
30+
initialAnimSkip = false;
31+
expandDone();
32+
} else {
33+
var targetElHeight = element[0].scrollHeight;
34+
if (targetElHeight) {
35+
element.removeClass('collapse').addClass('collapsing');
36+
doTransition({ height: element[0].scrollHeight + 'px' }).then(expandDone);
37+
} else {
38+
expandDone();
39+
}
40+
}
3141
}
32-
});
33-
3442

35-
var currentTransition;
36-
var doTransition = function(change) {
37-
if ( currentTransition ) {
38-
currentTransition.cancel();
43+
function expandDone() {
44+
element.removeClass('collapsing');
45+
element.addClass('collapse in');
46+
element.css({height: 'auto'});
3947
}
40-
currentTransition = $transition(element,change);
41-
currentTransition.then(
42-
function() { currentTransition = undefined; },
43-
function() { currentTransition = undefined; }
44-
);
45-
return currentTransition;
46-
};
4748

48-
var expand = function () {
49-
isCollapsed = false;
50-
if (initialAnimSkip) {
51-
initialAnimSkip = false;
52-
expandDone();
53-
} else {
54-
var targetElHeight = element[0].scrollHeight;
55-
if (targetElHeight) {
56-
doTransition({ height: targetElHeight + 'px' }).then(expandDone);
49+
function collapse() {
50+
if (initialAnimSkip) {
51+
initialAnimSkip = false;
52+
collapseDone();
53+
element.css({height: 0});
5754
} else {
58-
expandDone();
55+
// CSS transitions don't work with height: auto, so we have to manually change the height to a specific value
56+
element.css({ height: element[0].scrollHeight + 'px' });
57+
//trigger reflow so a browser relaizes that height was updated from auto to a specific value
58+
var x = element[0].offsetWidth;
59+
60+
element.removeClass('collapse in').addClass('collapsing');
61+
62+
doTransition({ height: 0 }).then(collapseDone);
5963
}
6064
}
61-
};
6265

63-
function expandDone() {
64-
if ( !isCollapsed ) {
65-
fixUpHeight(scope, element, 'auto');
66-
element.addClass('in');
66+
function collapseDone() {
67+
element.removeClass('collapsing');
68+
element.addClass('collapse');
6769
}
70+
71+
scope.$watch(attrs.collapse, function (shouldCollapse) {
72+
if (shouldCollapse) {
73+
collapse();
74+
} else {
75+
expand();
76+
}
77+
});
78+
6879
}
69-
70-
var collapse = function() {
71-
isCollapsed = true;
72-
element.removeClass('in');
73-
if (initialAnimSkip) {
74-
initialAnimSkip = false;
75-
fixUpHeight(scope, element, 0);
76-
} else {
77-
fixUpHeight(scope, element, element[0].scrollHeight + 'px');
78-
doTransition({'height':'0'});
79-
}
80-
};
81-
}
82-
};
83-
}]);
80+
};
81+
}]);

0 commit comments

Comments
 (0)