Skip to content

Commit

Permalink
Truncate long bodies and quotes
Browse files Browse the repository at this point in the history
Introduces auto-truncation of long bodies and quotes which expand when
you click on a "More" link.

Feature flagged as 'truncate_annotations'.
  • Loading branch information
JakeHartnell authored and nickstenning committed Oct 8, 2015
1 parent 81ca666 commit f4414f7
Show file tree
Hide file tree
Showing 10 changed files with 152 additions and 11 deletions.
1 change: 1 addition & 0 deletions h/features.py
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@
'streamer': "Enable 'live streaming' for annotations via the websocket?",
'search_normalized': "Assume all data has normalized URI fields?",
'show_unanchored_annotations': "Show annotations that fail to anchor?",
'truncate_annotations': "Truncate long quotes and bodies in annotations?",
}


Expand Down
1 change: 1 addition & 0 deletions h/static/scripts/app.coffee
Original file line number Diff line number Diff line change
Expand Up @@ -105,6 +105,7 @@ module.exports = angular.module('h', [

.directive('annotation', require('./directive/annotation'))
.directive('deepCount', require('./directive/deep-count'))
.directive('excerpt', require('./directive/excerpt'))
.directive('formInput', require('./directive/form-input'))
.directive('formValidate', require('./directive/form-validate'))
.directive('groupList', require('./directive/group-list').directive)
Expand Down
7 changes: 5 additions & 2 deletions h/static/scripts/directive/annotation.coffee
Original file line number Diff line number Diff line change
Expand Up @@ -405,8 +405,8 @@ AnnotationController = [
#
###
module.exports = [
'$document',
($document) ->
'$document', 'features'
($document, features) ->
linkFn = (scope, elem, attrs, [ctrl, thread, threadFilter, counter]) ->
# Observe the isSidebar attribute
attrs.$observe 'isSidebar', (value) ->
Expand All @@ -419,6 +419,9 @@ module.exports = [
scope.$evalAsync ->
ctrl.save()

# Give template access to feature flags
scope.feature = features.flagEnabled

scope.share = (event) ->
$container = angular.element(event.currentTarget).parent()
$container.addClass('open').find('input').focus().select()
Expand Down
60 changes: 60 additions & 0 deletions h/static/scripts/directive/excerpt.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,60 @@
'use strict';

/**
* @ngdoc directive
* @name excerpt
* @restrict E
* @description This directive truncates its contents to a height specified in
* CSS, and provides controls for expanding and collapsing the
* resulting truncated element. For example, with the following
* template HTML:
*
* <article class="post">
* <excerpt>
* <div class="body" ng-model="post.body"></div>
* </excerpt>
* </article>
*
* You would need to define the allowable height of the excerpt in
* CSS:
*
* article.post .excerpt {
* max-height: 10em;
* }
*
* And the excerpt directive will take care of the rest.
*
* You can selectively disable truncation by providing a boolean
* expression to the `enabled` parameter, e.g.:
*
* <excerpt enabled="!post.inFull">...</excerpt>
*/
module.exports = function () {
return {
link: function (scope, elem, attr, ctrl) {
scope.collapsed = true;

if (typeof scope.enabled === 'undefined') {
scope.enabled = function () { return true; };
}

scope.isOverflowing = function () {
var excerpt = elem[0].querySelector('.excerpt');
if (!excerpt) {
return false;
}
return (excerpt.scrollHeight > excerpt.clientHeight);
};

scope.toggle = function () {
scope.collapsed = !scope.collapsed;
};
},
scope: {
enabled: '&?',
},
restrict: 'E',
transclude: true,
templateUrl: 'excerpt.html',
};
};
20 changes: 20 additions & 0 deletions h/static/styles/annotations.scss
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,26 @@
.annotation-header { margin-top: 0 }
.annotation-footer { margin-bottom: 0 }

.annotation-section {
.excerpt { max-height: 4.8em; }
.excerpt-control a {
font-style: italic;
font-family: $serif-font-family;
font-weight: normal;
}
.excerpt--collapsed:after {
height: $base-line-height;
@include background(linear-gradient(to right,
rgba(255,255,255,0) 20%,
rgba(255,255,255,1) 100%
));
}
}

.annotation-body {
.excerpt { max-height: 16.2em; }
}

.annotation-user {
color: $text-color;
font-weight: bold;
Expand Down
1 change: 1 addition & 0 deletions h/static/styles/common.scss
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
@import 'mixins/responsive';
@import 'grid';
@import 'annotations';
@import 'excerpt';
@import 'forms';
@import 'markdown-editor';
@import 'spinner';
Expand Down
31 changes: 31 additions & 0 deletions h/static/styles/excerpt.scss
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
@import "compass/css3/images";
@import "variables";

.excerpt {
position: relative;
overflow: hidden;
}

.excerpt--collapsed:after {
position: absolute;
bottom: 0;
height: $base-line-height * 3; // This controls the apparent height of the gradient.
width: 100%;
content: "";
pointer-events: none;
@include background(linear-gradient(to bottom,
rgba(255,255,255,0) 20%,
rgba(255,255,255,1) 100%
));
}

.excerpt--uncollapsed {
max-height: 100% !important;
}

.excerpt-control a {
display: block;
text-align: right;
font-weight: bold;
width: 100%;
}
3 changes: 3 additions & 0 deletions h/templates/app.html.jinja2
Original file line number Diff line number Diff line change
Expand Up @@ -93,6 +93,9 @@
<script type="text/ng-template" id="annotation.html">
{{ include_raw("h:templates/client/annotation.html") }}
</script>
<script type="text/ng-template" id="excerpt.html">
{{ include_raw("h:templates/client/excerpt.html") }}
</script>
<script type="text/ng-template" id="group_list.html">
{{ include_raw("h:templates/client/group_list.html") }}
</script>
Expand Down
21 changes: 12 additions & 9 deletions h/templates/client/annotation.html
Original file line number Diff line number Diff line change
Expand Up @@ -56,12 +56,14 @@
<!-- Excerpts -->
<section class="annotation-section"
ng-repeat="target in vm.annotation.target track by $index">
<blockquote class="annotation-quote"
ng-hide="target.diffHTML && vm.showDiff"
ng-bind-html="selector.exact"
ng-repeat="selector in target.selector
| filter : {'type': 'TextQuoteSelector'}
track by $index"></blockquote>
<excerpt enabled="feature('truncate_annotations')">
<blockquote class="annotation-quote"
ng-hide="target.diffHTML && vm.showDiff"
ng-bind-html="selector.exact"
ng-repeat="selector in target.selector
| filter : {'type': 'TextQuoteSelector'}
track by $index"></blockquote>
</excerpt>
<blockquote class="annotation-quote"
ng-bind-html="target.diffHTML"
ng-show="target.diffHTML && vm.showDiff"></blockquote>
Expand All @@ -76,11 +78,12 @@
<!-- / Excerpts -- >
<!-- Body -->
<section name="text"
class="annotation-body"
ng-model="vm.annotation.text"
<section name="text" class="annotation-body">
<excerpt enabled="feature('truncate_annotations') && !vm.editing">
<div ng-model="vm.annotation.text"
ng-readonly="!vm.editing"
markdown>
</excerpt>
</section>
<!-- / Body -->

Expand Down
18 changes: 18 additions & 0 deletions h/templates/client/excerpt.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
<div ng-transclude ng-if="!enabled()"></div>
<div ng-if="enabled()">
<div class="excerpt"
ng-class="{'excerpt--uncollapsed': !collapsed,
'excerpt--collapsed': isOverflowing() && collapsed}"
ng-transclude></div>

<div class="excerpt-control">
<a ng-if="isOverflowing() && collapsed"
ng-click="toggle()"
class="more"
href="">More</a>
<a ng-if="!collapsed"
class="less"
ng-click="toggle()"
href="">Less</a>
</div>
</div>

0 comments on commit f4414f7

Please sign in to comment.