Skip to content

Commit 0bbfd4f

Browse files
committedAug 19, 2019
Merge branch 'master' of github.com:matt-d-rat/react-middle-truncate
2 parents c192168 + 2f1dc21 commit 0bbfd4f

File tree

1 file changed

+48
-71
lines changed

1 file changed

+48
-71
lines changed
 

‎src/react-middle-truncate/middle-truncate.jsx

+48-71
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,32 @@ import PropTypes from 'prop-types';
55
import measureText from 'measure-text';
66
import units from 'units-css';
77

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+
834
// A React component for truncating text in the middle of the string.
935
//
1036
// This component automatically calculates the required width and height of the text
@@ -21,24 +47,13 @@ class MiddleTruncate extends PureComponent {
2147
static propTypes = {
2248
className: PropTypes.string,
2349
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]),
2951
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]),
3954
style: PropTypes.object,
4055
text: PropTypes.string
41-
};
56+
}
4257

4358
static defaultProps = {
4459
className: '',
@@ -49,26 +64,12 @@ class MiddleTruncate extends PureComponent {
4964
start: 0,
5065
style: {},
5166
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 );
6667
}
6768

6869
state = {
6970
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)
7273
}
7374

7475
componentDidMount() {
@@ -82,19 +83,19 @@ class MiddleTruncate extends PureComponent {
8283
}
8384

8485
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) });
8687
}
8788

8889
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) });
9091
}
9192
}
9293

9394
componentWillUnmount() {
9495
window.removeEventListener('resize', this.onResize);
9596
}
9697

97-
onCopy(event) {
98+
onCopy = event => {
9899
const { smartCopy } = this.props;
99100

100101
// 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 {
106107

107108
// If smartCopy is set to partial or if smartCopy is set to all and the entire string was selected
108109
// 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)) {
110111
event.preventDefault();
111112
const clipboardData = event.clipboardData || window.clipboardData || event.originalEvent.clipboardData;
112113

113114
clipboardData.setData('text/plain', this.props.text);
114115
}
115116
}
116117

117-
onResize() {
118+
onResize = debounce(() => {
118119
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)
133121

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 => {
148123
const node = findDOMNode(ref);
149124
const text = node.textContent;
150125

@@ -185,7 +160,7 @@ class MiddleTruncate extends PureComponent {
185160
};
186161
}
187162

188-
truncateText(measurements) {
163+
truncateText = measurements => {
189164
const { text, ellipsis } = this.props;
190165
const { start, end } = this.state;
191166

@@ -194,7 +169,7 @@ class MiddleTruncate extends PureComponent {
194169
}
195170

196171
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);
198173
const middleIndex = Math.round(text.length / 2);
199174

200175
const preserveLeftSide = text.slice(0, start);
@@ -205,15 +180,17 @@ class MiddleTruncate extends PureComponent {
205180
return `${preserveLeftSide}${leftSide}${ellipsis}${rightSide}${preserveRightSide}`;
206181
}
207182

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 => {
209185
const measurements = this.calculateMeasurements();
210186

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;
214191

215192
this.setState(() => ({ truncatedText }));
216-
}
193+
}, 0)
217194

218195
render() {
219196
// eslint-disable-next-line no-unused-vars

0 commit comments

Comments
 (0)
Please sign in to comment.