@@ -5,6 +5,32 @@ import PropTypes from 'prop-types';
5
5
import measureText from 'measure-text' ;
6
6
import units from 'units-css' ;
7
7
8
+ const getStartOffset = ( start , text ) => {
9
+ if ( start === '' || start === null ) {
10
+ return 0 ;
11
+ }
12
+
13
+ if ( ! isNaN ( parseInt ( start , 10 ) ) ) {
14
+ return Math . round ( toFinite ( start ) ) ;
15
+ }
16
+
17
+ const result = new RegExp ( start ) . exec ( text ) ;
18
+ return result ? result . index + result [ 0 ] . length : 0 ;
19
+ } ;
20
+
21
+ const getEndOffset = ( end , text ) => {
22
+ if ( end === '' || end === null ) {
23
+ return 0 ;
24
+ }
25
+
26
+ if ( ! isNaN ( parseInt ( end , 10 ) ) ) {
27
+ return Math . round ( toFinite ( end ) ) ;
28
+ }
29
+
30
+ const result = new RegExp ( end ) . exec ( text ) ;
31
+ return result ? result [ 0 ] . length : 0 ;
32
+ } ;
33
+
8
34
// A React component for truncating text in the middle of the string.
9
35
//
10
36
// This component automatically calculates the required width and height of the text
@@ -21,24 +47,13 @@ class MiddleTruncate extends PureComponent {
21
47
static propTypes = {
22
48
className : PropTypes . string ,
23
49
ellipsis : PropTypes . string ,
24
- end : PropTypes . oneOfType ( [
25
- PropTypes . number ,
26
- PropTypes . instanceOf ( RegExp ) ,
27
- PropTypes . string
28
- ] ) ,
50
+ end : PropTypes . oneOfType ( [ PropTypes . number , PropTypes . instanceOf ( RegExp ) , PropTypes . string ] ) ,
29
51
onResizeDebounceMs : PropTypes . number ,
30
- smartCopy : PropTypes . oneOfType ( [
31
- PropTypes . oneOf ( [ 'partial' , 'all' ] ) ,
32
- PropTypes . bool
33
- ] ) ,
34
- start : PropTypes . oneOfType ( [
35
- PropTypes . number ,
36
- PropTypes . instanceOf ( RegExp ) ,
37
- PropTypes . string
38
- ] ) ,
52
+ smartCopy : PropTypes . oneOfType ( [ PropTypes . oneOf ( [ 'partial' , 'all' ] ) , PropTypes . bool ] ) ,
53
+ start : PropTypes . oneOfType ( [ PropTypes . number , PropTypes . instanceOf ( RegExp ) , PropTypes . string ] ) ,
39
54
style : PropTypes . object ,
40
55
text : PropTypes . string
41
- } ;
56
+ }
42
57
43
58
static defaultProps = {
44
59
className : '' ,
@@ -49,26 +64,12 @@ class MiddleTruncate extends PureComponent {
49
64
start : 0 ,
50
65
style : { } ,
51
66
text : ''
52
- } ;
53
-
54
- constructor ( props ) {
55
- super ( props ) ;
56
-
57
- this . getStartOffset = this . getStartOffset . bind ( this ) ;
58
- this . getEndOffset = this . getEndOffset . bind ( this ) ;
59
- this . onCopy = this . onCopy . bind ( this ) ;
60
- this . calculateMeasurements = this . calculateMeasurements . bind ( this ) ;
61
- this . truncateText = this . truncateText . bind ( this ) ;
62
-
63
- // Debounce the parsing of the text so that the component has had time to render its DOM for measurement calculations
64
- this . parseTextForTruncation = debounce ( this . parseTextForTruncation . bind ( this ) , 0 ) ;
65
- this . onResize = debounce ( this . onResize . bind ( this ) , this . props . onResizeDebounceMs ) ;
66
67
}
67
68
68
69
state = {
69
70
truncatedText : this . props . text ,
70
- start : this . getStartOffset ( this . props . start , this . props . text ) ,
71
- end : this . getEndOffset ( this . props . end , this . props . text )
71
+ start : getStartOffset ( this . props . start , this . props . text ) ,
72
+ end : getEndOffset ( this . props . end , this . props . text )
72
73
}
73
74
74
75
componentDidMount ( ) {
@@ -82,19 +83,19 @@ class MiddleTruncate extends PureComponent {
82
83
}
83
84
84
85
if ( nextProps . start !== this . props . start ) {
85
- this . setState ( { start : this . getStartOffset ( nextProps . start , nextProps . text ) } ) ;
86
+ this . setState ( { start : getStartOffset ( nextProps . start , nextProps . text ) } ) ;
86
87
}
87
88
88
89
if ( nextProps . end !== this . props . end ) {
89
- this . setState ( { end : this . getEndOffset ( nextProps . end , nextProps . text ) } ) ;
90
+ this . setState ( { end : getEndOffset ( nextProps . end , nextProps . text ) } ) ;
90
91
}
91
92
}
92
93
93
94
componentWillUnmount ( ) {
94
95
window . removeEventListener ( 'resize' , this . onResize ) ;
95
96
}
96
97
97
- onCopy ( event ) {
98
+ onCopy = event => {
98
99
const { smartCopy } = this . props ;
99
100
100
101
// If smart copy is not enabled, simply return and use the default behaviour of the copy event
@@ -106,45 +107,19 @@ class MiddleTruncate extends PureComponent {
106
107
107
108
// If smartCopy is set to partial or if smartCopy is set to all and the entire string was selected
108
109
// copy the original full text to the user's clipboard
109
- if ( smartCopy === 'partial' || ( smartCopy === 'all' && selectedText === this . state . truncatedText ) ) {
110
+ if ( smartCopy === 'partial' || ( smartCopy === 'all' && selectedText === this . state . truncatedText ) ) {
110
111
event . preventDefault ( ) ;
111
112
const clipboardData = event . clipboardData || window . clipboardData || event . originalEvent . clipboardData ;
112
113
113
114
clipboardData . setData ( 'text/plain' , this . props . text ) ;
114
115
}
115
116
}
116
117
117
- onResize ( ) {
118
+ onResize = debounce ( ( ) => {
118
119
this . parseTextForTruncation ( this . props . text ) ;
119
- }
120
-
121
- getStartOffset ( start , text ) {
122
- if ( start === '' || start === null ) {
123
- return 0 ;
124
- }
125
-
126
- if ( ! isNaN ( parseInt ( start , 10 ) ) ) {
127
- return Math . round ( toFinite ( start ) ) ;
128
- }
129
-
130
- const result = new RegExp ( start ) . exec ( text ) ;
131
- return result ? result . index + result [ 0 ] . length : 0 ;
132
- }
120
+ } , this . props . onResizeDebounceMs )
133
121
134
- getEndOffset ( end , text ) {
135
- if ( end === '' || end === null ) {
136
- return 0 ;
137
- }
138
-
139
- if ( ! isNaN ( parseInt ( end , 10 ) ) ) {
140
- return Math . round ( toFinite ( end ) ) ;
141
- }
142
-
143
- const result = new RegExp ( end ) . exec ( text ) ;
144
- return result ? result [ 0 ] . length : 0 ;
145
- }
146
-
147
- getTextMeasurement = ( ref ) => {
122
+ getTextMeasurement = ref => {
148
123
const node = findDOMNode ( ref ) ;
149
124
const text = node . textContent ;
150
125
@@ -185,7 +160,7 @@ class MiddleTruncate extends PureComponent {
185
160
} ;
186
161
}
187
162
188
- truncateText ( measurements ) {
163
+ truncateText = measurements => {
189
164
const { text, ellipsis } = this . props ;
190
165
const { start, end } = this . state ;
191
166
@@ -194,7 +169,7 @@ class MiddleTruncate extends PureComponent {
194
169
}
195
170
196
171
const delta = Math . ceil ( measurements . text . width . value - measurements . component . width . value ) ;
197
- const totalLettersToRemove = Math . ceil ( ( ( delta / measurements . ellipsis . width . value ) ) ) ;
172
+ const totalLettersToRemove = Math . ceil ( delta / measurements . ellipsis . width . value ) ;
198
173
const middleIndex = Math . round ( text . length / 2 ) ;
199
174
200
175
const preserveLeftSide = text . slice ( 0 , start ) ;
@@ -205,15 +180,17 @@ class MiddleTruncate extends PureComponent {
205
180
return `${ preserveLeftSide } ${ leftSide } ${ ellipsis } ${ rightSide } ${ preserveRightSide } ` ;
206
181
}
207
182
208
- parseTextForTruncation ( text ) {
183
+ // Debounce the parsing of the text so that the component has had time to render its DOM for measurement calculations
184
+ parseTextForTruncation = debounce ( text => {
209
185
const measurements = this . calculateMeasurements ( ) ;
210
186
211
- const truncatedText = ( Math . round ( measurements . text . width . value ) > Math . round ( measurements . component . width . value ) )
212
- ? this . truncateText ( measurements )
213
- : text ;
187
+ const truncatedText =
188
+ Math . round ( measurements . text . width . value ) > Math . round ( measurements . component . width . value )
189
+ ? this . truncateText ( measurements )
190
+ : text ;
214
191
215
192
this . setState ( ( ) => ( { truncatedText } ) ) ;
216
- }
193
+ } , 0 )
217
194
218
195
render ( ) {
219
196
// eslint-disable-next-line no-unused-vars
0 commit comments