Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Submit feedback
Contribute to GitLab
Sign in
Toggle navigation
C
coopwire-hypothesis
Project
Project
Details
Activity
Releases
Cycle Analytics
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Issues
0
Issues
0
List
Board
Labels
Milestones
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Charts
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Charts
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
孙灵跃 Leon Sun
coopwire-hypothesis
Commits
c285a898
Commit
c285a898
authored
Jan 07, 2016
by
Nick Stenning
Browse files
Options
Browse Files
Download
Plain Diff
Merge pull request #2802 from hypothesis/t158-truncated_annot_design
T158 - Update truncated annotation card design
parents
9574d01e
e04aba4e
Changes
9
Hide whitespace changes
Inline
Side-by-side
Showing
9 changed files
with
362 additions
and
179 deletions
+362
-179
annotation.js
h/static/scripts/directive/annotation.js
+21
-0
excerpt.js
h/static/scripts/directive/excerpt.js
+101
-52
excerpt-test.js
h/static/scripts/directive/test/excerpt-test.js
+115
-53
util.js
h/static/scripts/directive/test/util.js
+13
-1
annotations.scss
h/static/styles/annotations.scss
+5
-31
excerpt.scss
h/static/styles/excerpt.scss
+63
-26
util.scss
h/static/styles/util.scss
+9
-0
annotation.html
h/templates/client/annotation.html
+18
-7
excerpt.html
h/templates/client/excerpt.html
+17
-9
No files found.
h/static/scripts/directive/annotation.js
View file @
c285a898
...
...
@@ -310,6 +310,14 @@ function AnnotationController(
*/
vm
.
cancelTimestampRefresh
=
undefined
;
/** Determines whether controls to expand/collapse the annotation body
* are displayed adjacent to the tags field.
*/
vm
.
canCollapseBody
=
false
;
/** Determines whether the annotation body should be collapsed. */
vm
.
collapseBody
=
true
;
/** The domain model, contains the currently saved version of the
* annotation from the server (or in the case of new annotations that
* haven't been saved yet - the data that will be saved to the server when
...
...
@@ -588,6 +596,11 @@ function AnnotationController(
}
};
vm
.
toggleCollapseBody
=
function
(
event
)
{
event
.
stopPropagation
();
vm
.
collapseBody
=
!
vm
.
collapseBody
;
};
/**
* @ngdoc method
* @name annotation.AnnotationController#reply
...
...
@@ -750,6 +763,14 @@ function AnnotationController(
vm
.
user
=
function
()
{
return
domainModel
.
user
;
}
/** Sets whether or not the controls for
* expanding/collapsing the body of lengthy annotations
* should be shown.
*/
vm
.
setBodyCollapsible
=
function
(
canCollapse
)
{
vm
.
canCollapseBody
=
canCollapse
;
};
init
();
...
...
h/static/scripts/directive/excerpt.js
View file @
c285a898
'use strict'
;
function
ExcerptController
()
{
var
collapsed
=
true
;
if
(
this
.
collapse
===
undefined
)
{
this
.
collapse
=
true
;
}
// Enabled is a test seam: overwritten in link function.
this
.
enabled
=
function
()
{
return
true
;
};
if
(
this
.
animate
===
undefined
)
{
this
.
animate
=
true
;
}
// Overflowing is a test seam: overwritten in link function.
this
.
overflowing
=
function
()
{
return
false
;
};
this
.
enabled
=
this
.
enabled
||
function
()
{
return
true
;
};
// Is the excerpt collapsed? True if no-one has toggled the excerpt open
// and the element is overflowing.
this
.
collapsed
=
function
()
{
if
(
!
collapsed
)
{
return
false
;
}
return
this
.
overflowing
();
this
.
isExpandable
=
function
()
{
return
this
.
overflowing
()
&&
this
.
collapse
;
};
this
.
uncollapsed
=
function
()
{
return
!
collapsed
;
this
.
isCollapsible
=
function
()
{
return
this
.
overflowing
()
&&
!
this
.
collapse
;
};
this
.
toggle
=
function
()
{
collapsed
=
!
collapsed
;
this
.
toggle
=
function
(
event
)
{
event
.
stopPropagation
();
this
.
collapse
=
!
this
.
collapse
;
};
return
this
;
this
.
showInlineControls
=
function
()
{
return
this
.
overflowing
()
&&
this
.
inlineControls
;
}
this
.
bottomShadowStyles
=
function
()
{
return
{
'excerpt__shadow'
:
true
,
'excerpt__shadow--transparent'
:
this
.
inlineControls
,
'is-hidden'
:
!
this
.
isExpandable
(),
};
}
}
function
toPx
(
val
)
{
return
val
.
toString
()
+
'px'
;
}
/**
* @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>
* @description This directive truncates the height of its contents to a
* specified number of lines and provides controls for expanding
* and collapsing the resulting truncated element.
*/
// @ngInject
function
excerpt
()
{
return
{
bindToController
:
true
,
controller
:
ExcerptController
,
controllerAs
:
'vm'
,
link
:
function
(
scope
,
elem
,
attrs
,
ctrl
)
{
// Test if the transcluded element is overflowing its container. We use
// clientHeight rather than offsetHeight because we assume you'll be using
// this with "overflow: hidden;" (i.e. no scrollbars) and it's usually
// much faster to calculate than offsetHeight (which includes scrollbars).
var
contentElem
;
ctrl
.
contentStyle
=
function
contentStyle
()
{
if
(
!
contentElem
)
{
return
{};
}
var
maxHeight
;
if
(
ctrl
.
collapse
)
{
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
{
maxHeight
=
''
;
}
return
{
'max-height'
:
maxHeight
,
};
}
ctrl
.
overflowing
=
function
overflowing
()
{
var
excerpt
=
elem
[
0
].
querySelector
(
'.excerpt'
);
if
(
!
excerpt
)
{
if
(
!
contentElem
)
{
return
false
;
}
return
(
excerpt
.
scrollHeight
>
excerpt
.
clientHeight
)
;
return
contentElem
.
scrollHeight
>
ctrl
.
collapsedHeight
;
};
// If the `enabled` attr was provided, we override the enabled function.
if
(
attrs
.
enabled
)
{
ctrl
.
enabled
=
scope
.
enabled
;
}
scope
.
$watch
(
'vm.enabled()'
,
function
(
isEnabled
)
{
if
(
isEnabled
)
{
contentElem
=
elem
[
0
].
querySelector
(
'.excerpt'
);
// 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. */
animate
:
'='
,
/** Whether or not truncation should be enabled */
enabled
:
'&?'
,
/**
* Specifies whether controls to expand and collapse
* the excerpt should be shown inside the <excerpt> component.
* If false, external controls can expand/collapse the excerpt by
* setting the 'collapse' property.
*/
inlineControls
:
'='
,
/** Sets whether or not the excerpt is collapsed. */
collapse
:
'='
,
/** Called when the collapsibility of the excerpt (that is, whether or
* not the content height exceeds the collapsed height), changes.
*/
onCollapsibleChanged
:
'&?'
,
/** The height of this container in pixels when collapsed.
*/
collapsedHeight
:
'='
,
},
restrict
:
'E'
,
transclude
:
true
,
...
...
h/static/scripts/directive/test/excerpt-test.js
View file @
c285a898
'use strict'
;
var
assign
=
require
(
'core-js/modules/$.object-assign'
);
var
util
=
require
(
'./util'
);
var
excerpt
=
require
(
'../excerpt'
);
describe
(
'excerpt directive'
,
function
()
{
var
SHORT_DIV
=
'<div id="foo" style="height:5px;"></div>'
;
var
TALL_DIV
=
'<div id="foo" style="height:200px;">foo bar</div>'
;
describe
(
'excerpt.Controller'
,
function
()
{
var
ctrl
;
beforeEach
(
function
()
{
ctrl
=
new
excerpt
.
Controller
();
ctrl
.
overflowing
=
function
()
{
return
false
;
};
});
function
excerptDirective
(
attrs
,
content
)
{
var
defaultAttrs
=
{
// disable animation so that expansion/collapse happens immediately
// when the controls are toggled in tests
animate
:
false
,
enabled
:
true
,
collapsedHeight
:
40
,
inlineControls
:
false
,
};
attrs
=
assign
(
defaultAttrs
,
attrs
);
return
util
.
createDirective
(
document
,
'excerpt'
,
attrs
,
{},
content
);
}
it
(
'starts collapsed if the element is overflowing'
,
function
()
{
ctrl
.
overflowing
=
function
()
{
return
true
;
};
function
height
(
el
)
{
return
el
.
querySelector
(
'.excerpt'
).
offsetHeight
;
}
assert
.
isTrue
(
ctrl
.
collapsed
());
before
(
function
()
{
angular
.
module
(
'app'
,
[])
.
directive
(
'excerpt'
,
excerpt
.
directive
);
});
it
(
'does not start collapsed if the element is not overflowing'
,
function
()
{
assert
.
isFalse
(
ctrl
.
collapsed
());
beforeEach
(
function
()
{
angular
.
mock
.
module
(
'app'
);
angular
.
mock
.
module
(
'h.templates'
);
});
it
(
'is not initially uncollapsed if the element is overflowing
'
,
function
()
{
assert
.
isFalse
(
ctrl
.
uncollapsed
());
}
);
describe
(
'enabled state
'
,
function
()
{
it
(
'renders its contents in a .excerpt element by default'
,
function
()
{
var
element
=
excerptDirective
({},
'<span id="foo"></span>'
);
it
(
'is not initially uncollapsed if the element is not overflowing'
,
function
()
{
assert
.
isFalse
(
ctrl
.
uncollapsed
());
});
assert
.
equal
(
element
.
find
(
'.excerpt #foo'
).
length
,
1
);
});
describe
(
'.toggle()'
,
function
()
{
beforeEach
(
function
()
{
ctrl
.
overflowing
=
function
()
{
return
true
;
};
it
(
'when enabled, renders its contents in a .excerpt element'
,
function
()
{
var
element
=
excerptDirective
({
enabled
:
true
},
'<span id="foo"></span>'
);
assert
.
equal
(
element
.
find
(
'.excerpt #foo'
).
length
,
1
);
});
it
(
'toggles the collapsed state'
,
function
()
{
var
a
=
ctrl
.
collapsed
();
ctrl
.
toggle
();
var
b
=
ctrl
.
collapsed
();
ctrl
.
toggle
();
var
c
=
ctrl
.
collapsed
();
it
(
'when disabled, renders its contents but not in a .excerpt element'
,
function
()
{
var
element
=
excerptDirective
({
enabled
:
false
},
'<span id="foo"></span>'
);
assert
.
notEqual
(
a
,
b
);
assert
.
notEqual
(
b
,
c
);
assert
.
equal
(
a
,
c
);
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
);
});
});
describe
(
'excerpt.excerpt'
,
function
()
{
function
excerptDirective
(
attrs
,
content
)
{
return
util
.
createDirective
(
document
,
'excerpt'
,
attrs
,
{},
content
);
function
isHidden
(
el
)
{
return
!
el
.
offsetParent
||
el
.
classList
.
contains
(
'ng-hide'
);
}
before
(
function
()
{
angular
.
module
(
'app'
,
[])
.
directive
(
'excerpt'
,
excerpt
.
directive
);
});
function
findVisible
(
el
,
selector
)
{
var
elements
=
el
.
querySelectorAll
(
selector
);
for
(
var
i
=
0
;
i
<
elements
.
length
;
i
++
)
{
if
(
!
isHidden
(
elements
[
i
]))
{
return
elements
[
i
];
}
}
return
undefined
;
}
beforeEach
(
function
()
{
angular
.
mock
.
module
(
'app'
);
angular
.
mock
.
module
(
'h.templates'
);
});
describe
(
'inline controls'
,
function
()
{
function
findInlineControl
(
el
)
{
return
findVisible
(
el
,
'.excerpt__toggle-link'
);
}
it
(
'displays inline controls if collapsed'
,
function
()
{
var
element
=
excerptDirective
({
inlineControls
:
true
},
TALL_DIV
);
element
.
scope
.
$digest
();
var
expandLink
=
findInlineControl
(
element
[
0
]);
assert
.
ok
(
expandLink
);
assert
.
equal
(
expandLink
.
querySelector
(
'a'
).
textContent
,
'More'
);
});
it
(
'renders its contents in a .excerpt element by default'
,
function
()
{
var
element
=
excerptDirective
({},
'<span id="foo"></span>'
);
it
(
'does not display inline controls if not collapsed'
,
function
()
{
var
element
=
excerptDirective
({
inlineControls
:
true
},
SHORT_DIV
);
var
expandLink
=
findInlineControl
(
element
[
0
]);
assert
.
notOk
(
expandLink
);
});
assert
.
equal
(
element
.
find
(
'.excerpt #foo'
).
length
,
1
);
it
(
'toggles the expanded state when clicked'
,
function
()
{
var
element
=
excerptDirective
({
inlineControls
:
true
},
TALL_DIV
);
element
.
scope
.
$digest
();
var
expandLink
=
findInlineControl
(
element
[
0
]);
angular
.
element
(
expandLink
.
querySelector
(
'a'
)).
click
();
element
.
scope
.
$digest
();
var
collapseLink
=
findInlineControl
(
element
[
0
]);
assert
.
equal
(
collapseLink
.
querySelector
(
'a'
).
textContent
,
'Less'
);
});
});
it
(
'when enabled, renders its contents in a .excerpt element'
,
function
()
{
var
element
=
excerptDirective
({
enabled
:
true
},
'<span id="foo"></span>'
);
describe
(
'.collapse'
,
function
()
{
it
(
'collapses the body if collapse is true'
,
function
()
{
var
element
=
excerptDirective
({
collapse
:
true
},
TALL_DIV
);
assert
.
isBelow
(
height
(
element
[
0
]),
100
);
});
assert
.
equal
(
element
.
find
(
'.excerpt #foo'
).
length
,
1
);
it
(
'does not collapse the body if collapse is false'
,
function
()
{
var
element
=
excerptDirective
({
collapse
:
false
},
TALL_DIV
);
assert
.
isAbove
(
height
(
element
[
0
]),
100
);
});
});
it
(
'when disabled, renders its contents but not in a .excerpt element'
,
function
()
{
var
element
=
excerptDirective
({
enabled
:
false
},
'<span id="foo"></span>'
);
describe
(
'.onCollapsibleChanged'
,
function
()
{
it
(
'reports true if excerpt is tall'
,
function
()
{
var
callback
=
sinon
.
stub
();
var
element
=
excerptDirective
({
onCollapsibleChanged
:
{
args
:
[
'collapsible'
],
callback
:
callback
,
}
},
TALL_DIV
);
assert
.
calledWith
(
callback
,
true
);
});
assert
.
equal
(
element
.
find
(
'.excerpt #foo'
).
length
,
0
);
assert
.
equal
(
element
.
find
(
'#foo'
).
length
,
1
);
it
(
'reports false if excerpt is short'
,
function
()
{
var
callback
=
sinon
.
stub
();
var
element
=
excerptDirective
({
onCollapsibleChanged
:
{
args
:
[
'collapsible'
],
callback
:
callback
,
}
},
SHORT_DIV
);
assert
.
calledWith
(
callback
,
false
);
});
});
});
h/static/scripts/directive/test/util.js
View file @
c285a898
...
...
@@ -51,15 +51,21 @@ function hyphenate(name) {
* scope when the element is linked
* @param {string} [initialHtml] - Initial inner HTML content for the directive
* element.
* @param {Object} [opts] - Object specifying options for creating the
* directive:
* 'parentElement' - The parent element for the new
* directive. Defaults to document.body
*
* @return {DOMElement} The Angular jqLite-wrapped DOM element for the component.
* The returned object has a link(scope) method which will
* re-link the component with new properties.
*/
function
createDirective
(
document
,
name
,
attrs
,
initialScope
,
initialHtml
)
{
function
createDirective
(
document
,
name
,
attrs
,
initialScope
,
initialHtml
,
opts
)
{
attrs
=
attrs
||
{};
initialScope
=
initialScope
||
{};
initialHtml
=
initialHtml
||
''
;
opts
=
opts
||
{};
opts
.
parentElement
=
opts
.
parentElement
||
document
.
body
;
// create a template consisting of a single element, the directive
// we want to create and compile it
...
...
@@ -82,6 +88,11 @@ function createDirective(document, name, attrs, initialScope, initialHtml) {
});
templateElement
.
innerHTML
=
initialHtml
;
// add the element to the document's body so that
// it responds to events, becomes visible, reports correct
// values for its dimensions etc.
opts
.
parentElement
.
appendChild
(
templateElement
);
// setup initial scope
Object
.
keys
(
attrs
).
forEach
(
function
(
key
)
{
if
(
attrs
[
key
].
callback
)
{
...
...
@@ -105,6 +116,7 @@ function createDirective(document, name, attrs, initialScope, initialHtml) {
element
.
link
=
linkDirective
;
element
.
scope
=
childScope
;
childScope
.
$digest
();
element
.
ctrl
=
element
.
controller
(
name
);
return
element
;
}
...
...
h/static/styles/annotations.scss
View file @
c285a898
...
...
@@ -20,22 +20,16 @@ $annotation-card-left-padding: 10px;
font-family
:
$sans-font-family
;
font-weight
:
300
;
position
:
relative
;
.reply-count
{
color
:
$gray-light
;
&
:focus
{
outline
:
0
;
}
}
&
:hover
.annotation-timestamp
,
&
:hover
.reply-count
{
color
:
$link-color
;
}
}
.annotation-
timestamp
{
.annotation-
link
{
font-size
:
$body1-font-size
;
color
:
$color-gray
;
&
:hover
{
color
:
$link-color-hover
;
}
&
:focus
{
outline
:
0
;
}
.annotation
:hover
&
{
color
:
$link-color
;
}
}
.annotation-quote-list
,
...
...
@@ -78,25 +72,6 @@ $annotation-card-left-padding: 10px;
.annotation-quote-list
{
margin-top
:
14px
;
margin-bottom
:
14px
;
.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
,
$mask-start-color
,
$mask-end-color
));
}
}
.annotation-body
{
.excerpt
{
max-height
:
16
.2em
;
}
}
.annotation-media-embed
{
...
...
@@ -168,7 +143,6 @@ $annotation-card-left-padding: 10px;
}
}
//PRIVACY CONTROL////////////////////////////
privacy
{
position
:
relative
;
...
...
h/static/styles/excerpt.scss
View file @
c285a898
@import
"compass/css3/images"
;
@at-root
{
$expand-duration
:
.15s
;
.excerpt
{
position
:
relative
;
overflow
:
hidden
;
}
// the truncated body of the <excerpt>
.excerpt
{
transition
:
max-height
$expand-duration
ease-in
;
overflow
:
hidden
;
}
.excerpt--collapsed
:after
{
position
:
absolute
;
bottom
:
0
;
height
:
$base-line-height
*
2
;
// This controls the apparent height of the gradient.
width
:
100%
;
content
:
""
;
pointer-events
:
none
;
@include
background
(
linear-gradient
(
to
bottom
,
$mask-start-color
,
$mask-end-color
));
}
// a container which wraps the <excerpt> and contains the excerpt
// itself plus the shadow at the bottom that can be clicked to expand or
// collapse it
.excerpt__container
{
position
:
relative
;
}
.excerpt--uncollapsed
{
max-height
:
100%
!
important
;
}
// inline controls for expanding and collapsing
// the <excerpt>
// -------------
.excerpt__inline-controls
{
display
:
block
;
position
:
absolute
;
right
:
0
;
bottom
:
0
;
}
.excerpt__toggle-link
{
padding-left
:
15px
;
background-image
:
linear-gradient
(
to
right
,
transparent
0px
,
white
12px
);
}
.excerpt__toggle-link
>
a
{
color
:
$text-color
;
font-style
:
italic
;
font-weight
:
normal
;
}
// a shadow displayed at the bottom of an <excerpt>s with inline controls
// disabled, which provides a hint that the excerpt is collapsed
// -------------
// the distance by which the shadow indicating a collapsed
// annotation expands beyond the left/right edges of the card.
// This value is chosen such that the shadow expands to the full width of
// the card
$shadow-h-offset
:
-12px
;
.excerpt__shadow
{
position
:
absolute
;
left
:
$shadow-h-offset
;
right
:
$shadow-h-offset
;
bottom
:
0
;
height
:
40px
;
background-image
:
linear-gradient
(
to
bottom
,
transparent
50%
,
rgba
(
0
,
0
,
0
,
0
.08
)
95%
,
rgba
(
0
,
0
,
0
,
0
.13
)
100%
);
transition
:
opacity
$expand-duration
linear
;
}
.excerpt__shadow--transparent
{
background-image
:
none
;
}
.excerpt-control
a
{
display
:
block
;
text-align
:
right
;
font-weight
:
bold
;
width
:
100%
;
.excerpt__shadow.is-hidden
{
opacity
:
0
;
pointer-events
:
none
;
}
}
h/static/styles/util.scss
View file @
c285a898
...
...
@@ -3,6 +3,11 @@
flex-grow
:
1
;
}
.u-layout-row
{
display
:
flex
;
flex-direction
:
row
;
}
.u-center
{
margin-left
:
auto
;
margin-right
:
auto
;
...
...
@@ -13,3 +18,7 @@
flex-direction
:
row
;
justify-content
:
flex-end
;
}
.u-strong
{
font-weight
:
bold
;
}
h/templates/client/annotation.html
View file @
c285a898
...
...
@@ -14,7 +14,7 @@
</span>
<span
class=
"annotation-collapsed-replies"
>
<a
class=
"
reply-count small
"
href=
""
<a
class=
"
annotation-link
"
href=
""
ng-click=
"replyCountClick()"
ng-pluralize
count=
"replyCount"
when=
"{'0': '', 'one': '1 reply', 'other': '{} replies'}"
></a>
...
...
@@ -45,7 +45,7 @@
<span
class=
"u-flex-spacer"
></span>
<!-- Timestamp -->
<a
class=
"annotation-
timestamp
"
<a
class=
"annotation-
link
"
target=
"_blank"
title=
"{{vm.absoluteTimestamp}}"
ng-if=
"!vm.editing() && vm.updated()"
...
...
@@ -57,7 +57,9 @@
<section
class=
"annotation-quote-list"
ng-repeat=
"target in vm.target() track by $index"
ng-if=
"vm.hasQuotes()"
>
<excerpt
enabled=
"vm.feature('truncate_annotations')"
>
<excerpt
enabled=
"vm.feature('truncate_annotations')"
collapsed-height=
"40"
inline-controls=
"true"
>
<blockquote
class=
"annotation-quote"
ng-bind-html=
"selector.exact"
ng-repeat=
"selector in target.selector
...
...
@@ -70,7 +72,11 @@
<!-- Body -->
<section
name=
"text"
class=
"annotation-body"
>
<excerpt
enabled=
"vm.feature('truncate_annotations') && !vm.editing()"
>
<excerpt
enabled=
"vm.feature('truncate_annotations') && !vm.editing()"
inline-controls=
"false"
on-collapsible-changed=
"vm.setBodyCollapsible(collapsible)"
collapse=
"vm.collapseBody"
collapsed-height=
"200"
>
<markdown
ng-model=
"vm.form.text"
read-only=
"!vm.editing()"
embeds-enabled=
"vm.feature('embed_media')"
>
...
...
@@ -94,13 +100,18 @@
</tags-input>
</div>
<div
class=
"annotation-body tags tags-read-only"
ng-if=
"
vm.form.tags.length
&& !vm.editing()"
>
<div
class=
"annotation-body
u-layout-row
tags tags-read-only"
ng-if=
"
(vm.canCollapseBody || vm.form.tags.length)
&& !vm.editing()"
>
<ul
class=
"tag-list"
>
<li
class=
"tag-item"
ng-repeat=
"tag in vm.form.tags"
>
<a
href=
"/stream?q=tag:'{{tag.text|urlencode}}'"
target=
"_blank"
>
{{tag.text}}
</a>
</li>
</ul>
<div
class=
"u-stretch"
></div>
<a
class=
"annotation-link u-strong"
ng-show=
"vm.canCollapseBody"
ng-click=
"vm.toggleCollapseBody($event)"
ng-title=
"vm.collapseBody ? 'Show the full annotation text' : 'Show the first few lines only'"
ng-bind=
"vm.collapseBody ? 'More' : 'Less'"
></a>
</div>
<!-- / Tags -->
...
...
@@ -130,7 +141,7 @@
</div>
<div
class=
"annotation-replies"
ng-if=
"replyCount > 0"
>
<a
class=
"
reply-count small
"
href=
""
<a
class=
"
annotation-link
"
href=
""
ng-click=
"replyCountClick()"
ng-pluralize
count=
"replyCount"
when=
"{'0': '', 'one': '1 reply', 'other': '{} replies'}"
></a>
...
...
h/templates/client/excerpt.html
View file @
c285a898
<div
ng-transclude
ng-if=
"!vm.enabled()"
></div>
<div
ng-if=
"vm.enabled()"
>
<div
class=
"excerpt"
ng-class=
"{'excerpt--uncollapsed': vm.uncollapsed(),
'excerpt--collapsed': vm.collapsed()}"
ng-transclude
></div>
<div
class=
"excerpt-control"
>
<a
ng-if=
"vm.collapsed()"
ng-click=
"vm.toggle()"
>
More
</a>
<a
ng-if=
"vm.uncollapsed()"
ng-click=
"vm.toggle()"
>
Less
</a>
<div
class=
"excerpt__container"
ng-if=
"vm.enabled()"
>
<div
class=
"excerpt"
ng-style=
"vm.contentStyle()"
>
<div
ng-transclude
></div>
<div
class=
"excerpt__inline-controls"
ng-show=
"vm.showInlineControls()"
>
<span
class=
"excerpt__toggle-link"
ng-show=
"vm.isExpandable()"
>
…
<a
ng-click=
"vm.toggle($event)"
title=
"Show the full excerpt"
>
More
</a>
</span>
<span
class=
"excerpt__toggle-link"
ng-show=
"vm.isCollapsible()"
>
<a
ng-click=
"vm.toggle($event)"
title=
"Show the first few lines only"
>
Less
</a>
</span>
</div>
</div>
<div
ng-click=
"vm.toggle($event)"
ng-class=
"vm.bottomShadowStyles()"
title=
"Show the full excerpt"
></div>
</div>
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment