From 8527eb20b35da1f9fc165cb2413b188662314750 Mon Sep 17 00:00:00 2001 From: Pavel Savchuk Date: Mon, 21 Feb 2022 09:34:56 +0300 Subject: [PATCH] Issue #69 | Don't truncate if text fits into an element This happens if the truncate-component if wrapped by a flex element, and that flex element only takes minimal required space to fix its content. The issue here is that `measureText` methods uses rounding, while width of the truncate component's ref is calculated without rounding. Removing rounding and applying good-enough floats comparison fixes the issue. --- server.js | 5 +++-- src/App.js | 15 +++++++++++++++ src/TextTruncate.js | 20 ++++++++++++-------- 3 files changed, 30 insertions(+), 10 deletions(-) diff --git a/server.js b/server.js index 4e8f2b4..05abfc3 100644 --- a/server.js +++ b/server.js @@ -5,6 +5,7 @@ var config = require('./webpack.config.dev'); var app = express(); var compiler = webpack(config); +var PORT = 3000 app.use(require('webpack-dev-middleware')(compiler, { noInfo: true, @@ -17,11 +18,11 @@ app.get('*', function(req, res) { res.sendFile(path.join(__dirname, 'index.html')); }); -app.listen(3000, 'localhost', function(err) { +app.listen(PORT, 'localhost', function(err) { if (err) { console.log(err); return; } - console.log('Listening at http://localhost:3000'); + console.log(`Listening at http://localhost:${PORT}`); }); diff --git a/src/App.js b/src/App.js index fdc0f90..e7a5e4e 100644 --- a/src/App.js +++ b/src/App.js @@ -214,6 +214,21 @@ export class App extends Component { /> +
+
+ 13. Issue{" "} + + #69 + +
+
+ +
+
); diff --git a/src/TextTruncate.js b/src/TextTruncate.js index 6f3c4dc..cb059b3 100644 --- a/src/TextTruncate.js +++ b/src/TextTruncate.js @@ -1,6 +1,9 @@ import React, {Component, createElement} from 'react'; import PropTypes from 'prop-types'; +const PRECISION = 0.0001; +const isEqual = (n1, n2) => Math.abs(n1 - n2) < PRECISION; + export default class TextTruncate extends Component { static propTypes = { containerClassName: PropTypes.string, @@ -54,7 +57,7 @@ export default class TextTruncate extends Component { if (this.rafId) { window.cancelAnimationFrame(this.rafId); } - this.rafId = window.requestAnimationFrame(this.update.bind(this)) + this.rafId = window.requestAnimationFrame(this.update.bind(this)); }; onToggled = (truncated) => { @@ -83,7 +86,7 @@ export default class TextTruncate extends Component { }; measureWidth(text) { - return Math.ceil(this.canvas.measureText(text).width); + return this.canvas.measureText(text).width; } getRenderText() { @@ -109,8 +112,9 @@ export default class TextTruncate extends Component { return null; } + const fullTextWidth = this.measureWidth(text); // return if all of text can be displayed - if (scopeWidth >= this.measureWidth(text)) { + if (scopeWidth > fullTextWidth || isEqual(scopeWidth, fullTextWidth)) { this.onToggled(false); return createElement(textElement, props, text); } @@ -136,7 +140,7 @@ export default class TextTruncate extends Component { let lastSpaceIndex = -1; let ext = ''; let loopCnt = 0; - + while (displayLine-- > 0) { ext = displayLine ? '' : truncateText + (childText ? (' ' + childText) : ''); while (currentPos <= maxTextLength) { @@ -172,7 +176,7 @@ export default class TextTruncate extends Component { } truncatedText = text.substr(startPos, currentPos); } else { - currentPos--; + currentPos--; truncatedText = text.substr(startPos, currentPos); } } else { @@ -180,7 +184,7 @@ export default class TextTruncate extends Component { truncatedText = text.substr(startPos, currentPos); } width = this.measureWidth(truncatedText + ext); - } while (width >= scopeWidth && truncatedText.length > 0); + } while ((width > scopeWidth || isEqual(width, scopeWidth)) && truncatedText.length > 0); startPos += currentPos; break; } @@ -202,7 +206,7 @@ export default class TextTruncate extends Component { this.onToggled(false); return createElement(textElement, props, text); } - + this.onTruncated(); this.onToggled(true); return ( @@ -232,7 +236,7 @@ export default class TextTruncate extends Component { const { fontWeight, fontStyle, fontSize, fontFamily } = style; - const renderText = this.scope && line ? this.getRenderText() : createElement(textElement, props, text);; + const renderText = this.scope && line ? this.getRenderText() : createElement(textElement, props, text); const rootProps = { ref: (el) => {this.scope = el}, className: containerClassName,