Commit 46f3e7c3 authored by Robert Knight's avatar Robert Knight

Update <excerpt> overflow state when excerpt is shown or hidden via ng-show

In addition to the content changing, the window resizing and media loading,
another way that the excerpt's overflow state can change is if it or a parent
element's visibility changes.

Since there isn't a generic, performant way to watch the visibility of DOM
elements, the change here adds a scope watch which tests for the presence of
the 'ng-hide' class used by the ng-show and ng-hide directives on parent
elements, since that is the only method of changing visibility that we actually
need to support at the moment.
parent ce306e60
...@@ -64,6 +64,19 @@ function excerpt(ExcerptOverflowMonitor) { ...@@ -64,6 +64,19 @@ function excerpt(ExcerptOverflowMonitor) {
controller: ExcerptController, controller: ExcerptController,
controllerAs: 'vm', controllerAs: 'vm',
link: function (scope, elem, attrs, ctrl) { link: function (scope, elem, attrs, ctrl) {
// Test if the element or any of its parents have been hidden by
// an 'ng-show' directive
function isElementHidden() {
var el = elem[0];
while (el) {
if (el.classList.contains('ng-hide')) {
return true;
}
el = el.parentElement;
}
return false;
}
var overflowMonitor = new ExcerptOverflowMonitor({ var overflowMonitor = new ExcerptOverflowMonitor({
getState: function () { getState: function () {
return { return {
...@@ -105,6 +118,15 @@ function excerpt(ExcerptOverflowMonitor) { ...@@ -105,6 +118,15 @@ function excerpt(ExcerptOverflowMonitor) {
window.removeEventListener('resize', overflowMonitor.check); window.removeEventListener('resize', overflowMonitor.check);
}); });
// Watch for changes to the visibility of the excerpt.
// Unfortunately there is no DOM API for this, so we rely on a digest
// being triggered after the visibility changes.
scope.$watch(isElementHidden, function (hidden) {
if (!hidden) {
overflowMonitor.check();
}
});
// Watch input properties which may affect the overflow state // Watch input properties which may affect the overflow state
scope.$watch('vm.contentData', overflowMonitor.check); scope.$watch('vm.contentData', overflowMonitor.check);
scope.$watch('vm.enabled', overflowMonitor.check); scope.$watch('vm.enabled', overflowMonitor.check);
......
...@@ -106,6 +106,24 @@ describe('excerpt directive', function () { ...@@ -106,6 +106,24 @@ describe('excerpt directive', function () {
}); });
}); });
context('visibility changes', function () {
it('schedules an overflow check when shown', function () {
var element = excerptDirective({}, '<span></span>');
fakeOverflowMonitor.check.reset();
// ng-hide is the class used by the ngShow and ngHide directives
// to show or hide elements. For now, this is the only way of hiding
// or showing excerpts that we need to support.
element[0].classList.add('ng-hide');
element.scope.$digest();
assert.notCalled(fakeOverflowMonitor.check);
element[0].classList.remove('ng-hide');
element.scope.$digest();
assert.called(fakeOverflowMonitor.check);
});
});
context('excerpt content style', function () { context('excerpt content style', function () {
it('sets the content style using ExcerptOverflowMonitor#contentStyle()', function () { it('sets the content style using ExcerptOverflowMonitor#contentStyle()', function () {
var element = excerptDirective({}, '<span></span>'); var element = excerptDirective({}, '<span></span>');
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment