This repository has been archived by the owner on May 29, 2019. It is now read-only.
-
Notifications
You must be signed in to change notification settings - Fork 6.7k
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
feat(collapse): make collapse work with bootstrap3
Closes #1240 If starting out collapsed, the expand animation would jump since the `initialAnimSkip` was still `true`.
- Loading branch information
1 parent
3db699d
commit 517dff6
Showing
1 changed file
with
67 additions
and
69 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,83 +1,81 @@ | ||
angular.module('ui.bootstrap.collapse',['ui.bootstrap.transition']) | ||
angular.module('ui.bootstrap.collapse', ['ui.bootstrap.transition']) | ||
|
||
// The collapsible directive indicates a block of html that will expand and collapse | ||
.directive('collapse', ['$transition', function($transition) { | ||
// CSS transitions don't work with height: auto, so we have to manually change the height to a | ||
// specific value and then once the animation completes, we can reset the height to auto. | ||
// Unfortunately if you do this while the CSS transitions are specified (i.e. in the CSS class | ||
// "collapse") then you trigger a change to height 0 in between. | ||
// The fix is to remove the "collapse" CSS class while changing the height back to auto - phew! | ||
var fixUpHeight = function(scope, element, height) { | ||
// We remove the collapse CSS class to prevent a transition when we change to height: auto | ||
element.removeClass('collapse'); | ||
element.css({ height: height }); | ||
// It appears that reading offsetWidth makes the browser realise that we have changed the | ||
// height already :-/ | ||
var x = element[0].offsetWidth; | ||
element.addClass('collapse'); | ||
}; | ||
.directive('collapse', ['$transition', function ($transition, $timeout) { | ||
|
||
return { | ||
link: function(scope, element, attrs) { | ||
return { | ||
link: function (scope, element, attrs) { | ||
|
||
var isCollapsed; | ||
var initialAnimSkip = true; | ||
var initialAnimSkip = true; | ||
var currentTransition; | ||
|
||
scope.$watch(attrs.collapse, function(value) { | ||
if (value) { | ||
collapse(); | ||
} else { | ||
expand(); | ||
function doTransition(change) { | ||
var newTransition = $transition(element, change); | ||
if (currentTransition) { | ||
currentTransition.cancel(); | ||
} | ||
currentTransition = newTransition; | ||
newTransition.then(newTransitionDone, newTransitionDone); | ||
return newTransition; | ||
|
||
function newTransitionDone() { | ||
// Make sure it's this transition, otherwise, leave it alone. | ||
if (currentTransition === newTransition) { | ||
currentTransition = undefined; | ||
} | ||
} | ||
} | ||
|
||
function expand() { | ||
if (initialAnimSkip) { | ||
initialAnimSkip = false; | ||
expandDone(); | ||
} else { | ||
var targetElHeight = element[0].scrollHeight; | ||
if (targetElHeight) { | ||
element.removeClass('collapse').addClass('collapsing'); | ||
doTransition({ height: element[0].scrollHeight + 'px' }).then(expandDone); | ||
} else { | ||
expandDone(); | ||
} | ||
} | ||
} | ||
}); | ||
|
||
|
||
var currentTransition; | ||
var doTransition = function(change) { | ||
if ( currentTransition ) { | ||
currentTransition.cancel(); | ||
function expandDone() { | ||
element.removeClass('collapsing'); | ||
element.addClass('collapse in'); | ||
element.css({height: 'auto'}); | ||
} | ||
currentTransition = $transition(element,change); | ||
currentTransition.then( | ||
function() { currentTransition = undefined; }, | ||
function() { currentTransition = undefined; } | ||
); | ||
return currentTransition; | ||
}; | ||
|
||
var expand = function () { | ||
isCollapsed = false; | ||
if (initialAnimSkip) { | ||
initialAnimSkip = false; | ||
expandDone(); | ||
} else { | ||
var targetElHeight = element[0].scrollHeight; | ||
if (targetElHeight) { | ||
doTransition({ height: targetElHeight + 'px' }).then(expandDone); | ||
function collapse() { | ||
if (initialAnimSkip) { | ||
initialAnimSkip = false; | ||
collapseDone(); | ||
element.css({height: 0}); | ||
} else { | ||
expandDone(); | ||
// CSS transitions don't work with height: auto, so we have to manually change the height to a specific value | ||
element.css({ height: element[0].scrollHeight + 'px' }); | ||
//trigger reflow so a browser relaizes that height was updated from auto to a specific value | ||
var x = element[0].offsetWidth; | ||
|
||
element.removeClass('collapse in').addClass('collapsing'); | ||
|
||
doTransition({ height: 0 }).then(collapseDone); | ||
} | ||
} | ||
}; | ||
|
||
function expandDone() { | ||
if ( !isCollapsed ) { | ||
fixUpHeight(scope, element, 'auto'); | ||
element.addClass('in'); | ||
function collapseDone() { | ||
element.removeClass('collapsing'); | ||
element.addClass('collapse'); | ||
} | ||
|
||
scope.$watch(attrs.collapse, function (shouldCollapse) { | ||
if (shouldCollapse) { | ||
collapse(); | ||
} else { | ||
expand(); | ||
} | ||
}); | ||
|
||
} | ||
|
||
var collapse = function() { | ||
isCollapsed = true; | ||
element.removeClass('in'); | ||
if (initialAnimSkip) { | ||
initialAnimSkip = false; | ||
fixUpHeight(scope, element, 0); | ||
} else { | ||
fixUpHeight(scope, element, element[0].scrollHeight + 'px'); | ||
doTransition({'height':'0'}); | ||
} | ||
}; | ||
} | ||
}; | ||
}]); | ||
}; | ||
}]); |