Commit 3d3df156 authored by Robert Knight's avatar Robert Knight

Fix excerpt content height when switching from edit back to view mode

The 'max-height' style property was not updated when the <excerpt>'s
enabled state changed from false to true which happened when switching
from annotation edit mode back to view mode.

Use ngStyle to ensure the inline styles applied to the <excerpt>'s
content element are updated as necessary in this case.
parent 15406d38
......@@ -13,17 +13,12 @@ function ExcerptController() {
return true;
};
// Test seam. Overwritten in the link function
this.overflowing = function () {
return false;
};
this.isExpandable = function () {
return this.collapse && this.overflowing();
return this.overflowing() && this.collapse;
};
this.isCollapsible = function () {
return !this.collapse;
return this.overflowing() && !this.collapse;
};
this.toggle = function () {
......@@ -31,7 +26,7 @@ function ExcerptController() {
};
this.showInlineControls = function () {
return this.inlineControls && (this.isExpandable() || this.isCollapsible())
return this.overflowing() && this.inlineControls;
}
}
......@@ -56,18 +51,26 @@ function excerpt() {
link: function (scope, elem, attrs, ctrl) {
var contentElem;
function checkForOverflowChange() {
scope.$digest();
updateContentMaxHeight();
}
ctrl.contentStyle = function contentStyle() {
if (!contentElem) {
return {};
}
function updateContentMaxHeight() {
var maxHeight;
if (ctrl.collapse) {
contentElem.style.maxHeight = toPx(ctrl.collapsedHeight);
maxHeight = toPx(ctrl.collapsedHeight);
} else if (ctrl.animate) {
// animating the height change requires that the final
// height be specified exactly, rather than relying on
// auto height
maxHeight = toPx(contentElem.scrollHeight);
} else {
contentElem.style.maxHeight =
ctrl.animate ? toPx(contentElem.scrollHeight) : '';
maxHeight = '';
}
return {
'max-height': maxHeight,
};
}
ctrl.overflowing = function overflowing() {
......@@ -77,46 +80,26 @@ function excerpt() {
return contentElem.scrollHeight > ctrl.collapsedHeight;
};
// init function which sets up watches that perform the initial
// call to updateContentMaxHeight() to collapse the <excerpt> and
// alter the state if the <excerpt> is expanded/collapsed in future
function init() {
scope.$watch('vm.enabled()', function (isEnabled) {
if (isEnabled) {
contentElem = elem[0].querySelector('.excerpt');
// trigger a recalculation of ctrl.overflowing() and properties
// which depend upon it when embedded media loads.
//
// In future we might wish to trigger checking for other events
// outside of Angular's knowledge as well, eg. loading of embedded
// media
contentElem.addEventListener('load', checkForOverflowChange,
true /* capture. 'load' events do not bubble */);
} else {
contentElem = undefined;
}
});
scope.$watch('vm.collapse', function (isCollapsed) {
if (!contentElem) {
return;
}
updateContentMaxHeight();
});
scope.$watch('vm.overflowing()', function () {
if (ctrl.onCollapsibleChanged) {
ctrl.onCollapsibleChanged({collapsible: ctrl.overflowing()});
}
});
}
scope.$watch('vm.enabled()', function (isEnabled) {
if (isEnabled) {
contentElem = elem[0].querySelector('.excerpt');
// run the init() function asynchronously so that any
// directives in the transcluded content of the DOM have been
// processed by the time the first call to updateContentMaxHeight()
// happens.
scope.$evalAsync(init);
// trigger an update of the excerpt when events happen
// outside of Angular's knowledge that might affect the content
// size. For now, the only event we handle is loading of
// embedded media or frames
contentElem.addEventListener('load', scope.$digest.bind(scope),
true /* capture. 'load' events do not bubble */);
} else {
contentElem = undefined;
}
});
scope.$watch('vm.overflowing()', function () {
if (ctrl.onCollapsibleChanged) {
ctrl.onCollapsibleChanged({collapsible: ctrl.overflowing()});
}
});
},
scope: {
/** Whether or not expansion should be animated. Defaults to true. */
......
......@@ -21,6 +21,10 @@ describe('excerpt directive', function () {
return util.createDirective(document, 'excerpt', attrs, {}, content);
}
function height(el) {
return el.querySelector('.excerpt').offsetHeight;
}
before(function () {
angular.module('app', [])
.directive('excerpt', excerpt.directive);
......@@ -50,6 +54,13 @@ describe('excerpt directive', function () {
assert.equal(element.find('.excerpt #foo').length, 0);
assert.equal(element.find('#foo').length, 1);
});
it('truncates long contents when enabled', function () {
var element = excerptDirective({enabled: false}, TALL_DIV);
element.scope.enabled = true;
element.scope.$digest();
assert.isBelow(height(element[0]), 100);
});
});
function isHidden(el) {
......@@ -100,10 +111,6 @@ describe('excerpt directive', function () {
});
describe('.collapse', function () {
function height(el) {
return el.querySelector('.excerpt').offsetHeight;
}
it('collapses the body if collapse is true', function () {
var element = excerptDirective({collapse: true}, TALL_DIV);
assert.isBelow(height(element[0]), 100);
......
<div ng-transclude ng-if="!vm.enabled()"></div>
<div class="excerpt__container" ng-if="vm.enabled()">
<div class="excerpt">
<div class="excerpt" ng-style="vm.contentStyle()">
<div ng-transclude></div>
<div class="excerpt__inline-controls"
ng-show="vm.showInlineControls()">
......
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