12
12
* *
13
13
*********************************************************/
14
14
15
- export interface IOptions {
15
+ export interface IClampOptions {
16
16
clamp ?: number | string | 'auto' ;
17
17
useNativeClamp ?: boolean ;
18
18
splitOnChars ?: Array < string > ;
@@ -21,11 +21,22 @@ export interface IOptions {
21
21
truncationHTML ?: string ;
22
22
}
23
23
24
- export interface IResponse {
24
+ export interface IClampResponse {
25
25
original : string ;
26
26
clamped : string ;
27
27
}
28
28
29
+ /**
30
+ * @description Returns the height of an element as an integer (max of scroll/offset/client).
31
+ * Note: inline elements return 0 for scrollHeight and clientHeight.
32
+ * @param elem
33
+ * @returns height in number'
34
+ * @author github.com/danmana - copied from https://github.com/josephschmitt/Clamp.js/pull/18
35
+ */
36
+ const getElemHeight = ( elem : HTMLElement | Element ) : number => {
37
+ return Math . max ( elem . scrollHeight , ( < HTMLElement > elem ) . offsetHeight , elem . clientHeight ) ;
38
+ }
39
+
29
40
/********************************************************
30
41
* *
31
42
* UTILITY FUNCTIONS *
@@ -74,7 +85,7 @@ const computeStyle = (elem: HTMLElement | Element, prop: string): string => {
74
85
* @returns max lines
75
86
*/
76
87
const getMaxLines = ( element : HTMLElement | Element , height ?: number ) : number => {
77
- const availHeight = height || element . clientHeight ,
88
+ const availHeight = height || getElemHeight ( element ) ,
78
89
lineHeight = getLineHeight ( element ) ;
79
90
return Math . max ( Math . floor ( availHeight / lineHeight ) , 0 ) ;
80
91
} ;
@@ -99,12 +110,12 @@ const getMaxHeight = (element: HTMLElement | Element, clmp: number): number => {
99
110
*/
100
111
const getLineHeight = ( elem : HTMLElement | Element ) : number => {
101
112
const lh = computeStyle ( elem , 'line-height' ) ;
102
- if ( lh == 'normal' ) {
113
+ if ( lh === 'normal' ) {
103
114
// Normal line heights vary from browser to browser. The spec recommends
104
115
// a value between 1.0 and 1.2 of the font size. Using 1.1 to split the diff.
105
- return parseInt ( computeStyle ( elem , 'font-size' ) ) * 1.2 ;
116
+ return parseFloat ( computeStyle ( elem , 'font-size' ) ) * 1.2 ;
106
117
}
107
- return parseInt ( lh ) ;
118
+ return parseFloat ( lh ) ;
108
119
} ;
109
120
110
121
/**
@@ -113,11 +124,11 @@ const getLineHeight = (elem: HTMLElement | Element): number => {
113
124
* @param options config option
114
125
* @returns Element's last child.
115
126
*/
116
- const getLastChild = ( elem : HTMLElement | Element , options : IOptions ) : HTMLElement => {
127
+ const getLastChild = ( elem : HTMLElement | Element , options : IClampOptions ) : HTMLElement => {
117
128
//Current element has children, need to go deeper and get last child as a text node
118
129
if (
119
- ( elem . lastChild as any ) . children &&
120
- ( elem . lastChild as any ) . children . length > 0
130
+ ( < HTMLElement > elem . lastChild ) . children &&
131
+ ( < HTMLElement > elem . lastChild ) . children . length > 0
121
132
) {
122
133
return getLastChild (
123
134
Array . prototype . slice . call ( elem . children ) . pop ( ) ,
@@ -129,7 +140,7 @@ const getLastChild = (elem: HTMLElement | Element, options: IOptions): HTMLEleme
129
140
! elem . lastChild ||
130
141
! elem . lastChild . nodeValue ||
131
142
elem . lastChild . nodeValue === '' ||
132
- elem . lastChild . nodeValue == options . truncationChar
143
+ elem . lastChild . nodeValue === options . truncationChar
133
144
) {
134
145
elem . lastChild . parentNode . removeChild ( elem . lastChild ) ;
135
146
return getLastChild ( elem , options ) ;
@@ -149,7 +160,7 @@ const getLastChild = (elem: HTMLElement | Element, options: IOptions): HTMLEleme
149
160
const applyEllipsis = (
150
161
elem : HTMLElement | Element ,
151
162
str : string ,
152
- options : IOptions
163
+ options : IClampOptions
153
164
) : void => {
154
165
elem . nodeValue = str + options . truncationChar ;
155
166
} ;
@@ -170,15 +181,15 @@ const truncate = (
170
181
element : HTMLElement | Element ,
171
182
truncationHTMLContainer : HTMLElement ,
172
183
maxHeight : number ,
173
- options : IOptions ,
184
+ options : IClampOptions ,
174
185
config : any = {
175
186
splitOnChars : options . splitOnChars . slice ( 0 ) ,
176
187
splitChar : options . splitOnChars . slice ( 0 ) [ 0 ] ,
177
188
chunks : null ,
178
189
lastChunk : null ,
179
190
}
180
191
) : string => {
181
- if ( ! maxHeight ) {
192
+ if ( ! target || ! maxHeight ) {
182
193
return element . innerHTML ;
183
194
}
184
195
@@ -220,7 +231,7 @@ const truncate = (
220
231
// Search produced valid chunks
221
232
if ( chunks ) {
222
233
// It fits
223
- if ( element . clientHeight <= maxHeight ) {
234
+ if ( getElemHeight ( element ) <= maxHeight ) {
224
235
// There's still more characters to try splitting on, not quite done yet
225
236
if ( splitOnChars . length >= 0 && splitChar !== '' ) {
226
237
applyEllipsis (
@@ -291,7 +302,7 @@ const truncate = (
291
302
* @param element. Element containing the text node to clamp.
292
303
* @param options. Options to pass to the clamper.
293
304
*/
294
- export function clamp ( element : Element | HTMLElement , options ?: IOptions ) : IResponse {
305
+ export function clamp ( element : Element | HTMLElement , options ?: IClampOptions ) : IClampResponse {
295
306
/**
296
307
* merge default options with provided options (if any).
297
308
*/
@@ -307,20 +318,20 @@ export function clamp(element: Element | HTMLElement, options?: IOptions): IResp
307
318
const sty = ( < HTMLElement > element ) . style ;
308
319
const original = element . innerHTML ;
309
320
const supportsNativeClamp =
310
- typeof ( < HTMLElement > element ) . style . webkitLineClamp != 'undefined' ;
321
+ typeof ( < HTMLElement > element ) . style . webkitLineClamp !== 'undefined' ;
311
322
let clampValue = options . clamp ;
312
323
const isCSSValue =
313
- ( clampValue as string ) . indexOf &&
314
- ( ( clampValue as string ) . indexOf ( 'px' ) > - 1 ||
315
- ( clampValue as string ) . indexOf ( 'em' ) > - 1 ) ;
324
+ ( < string > clampValue ) . indexOf &&
325
+ ( ( < string > clampValue ) . indexOf ( 'px' ) > - 1 ||
326
+ ( < string > clampValue ) . indexOf ( 'em' ) > - 1 ) ;
316
327
let truncationHTMLContainer ;
317
328
if ( options . truncationHTML ) {
318
329
truncationHTMLContainer = document . createElement ( 'span' ) ;
319
330
truncationHTMLContainer . innerHTML = options . truncationHTML ;
320
331
}
321
332
322
333
// CONSTRUCTOR ________________________________________________________________
323
- if ( clampValue == 'auto' ) {
334
+ if ( clampValue === 'auto' ) {
324
335
clampValue = getMaxLines ( element ) ;
325
336
} else if ( isCSSValue ) {
326
337
clampValue = getMaxLines ( element , parseInt ( clampValue as string ) ) ;
@@ -333,11 +344,11 @@ export function clamp(element: Element | HTMLElement, options?: IOptions): IResp
333
344
sty . display = '-webkit-box' ;
334
345
sty . webkitLineClamp = clampValue as string ;
335
346
if ( isCSSValue ) {
336
- sty . height = options . clamp + 'px' ;
347
+ sty . height = < string > options . clamp ;
337
348
}
338
349
} else {
339
350
const height = getMaxHeight ( element , clampValue as number ) ;
340
- if ( height <= element . clientHeight ) {
351
+ if ( height < getElemHeight ( element ) ) {
341
352
clamped = truncate (
342
353
getLastChild ( element , options ) ,
343
354
element ,
0 commit comments