From 1e9c17d09e2852d2e1c25268fd05541e4eec843f Mon Sep 17 00:00:00 2001 From: Severiano Badajoz Date: Thu, 28 May 2020 10:43:36 -0700 Subject: [PATCH] accurately compute largest possible string --- client/src/components/util/truncate.js | 94 ++++++++++++++++++++++---- 1 file changed, 82 insertions(+), 12 deletions(-) diff --git a/client/src/components/util/truncate.js b/client/src/components/util/truncate.js index c61e0ee8..5824dba5 100644 --- a/client/src/components/util/truncate.js +++ b/client/src/components/util/truncate.js @@ -31,26 +31,94 @@ export default class Truncate extends Component { return this.fontIsLoaded ? "Roboto Condensed" : "Helvetica Neue"; } + computeLargestTruncatedString = ( + str, + maxSize, + params, + length = str.length - 1, + lastLength = 0, + close = -1 + ) => { + // Generate the truncated string with ellipses(not if full string) + const shortenedString = + length === str.length - 1 + ? str + : `${str.slice(0, length)}…${str.slice(-length / 2)}`; + // Measure the size of that string + const renderedSize = pixelWidth(shortenedString, params); + + // If that full length string is smaller than the maxSize don't return a truncated string + if (renderedSize < maxSize && length === str.length - 1) { + return null; + } + // Base case: If we've narrowed down to a length, return the closest string + if (length === lastLength) { + console.log("RETURNING", { length, lastLength, renderedSize }); + return `${str.slice(0, close)}…${str.slice(-close / 2)}`; + } + // If the current size is longer than max + if (renderedSize > maxSize) { + console.log({ + length, + lastLength, + renderedSize, + close, + size: "big", + }); + // If we're only one off from the closest string so far, just return the closest string + if (length - close === 1) { + console.log("RETURNING", { length, lastLength, renderedSize }); + + return `${str.slice(0, close)}…${str.slice(-close / 2)}`; + } + // Otherwise recursively call with half the current length + return this.computeLargestTruncatedString( + str, + maxSize, + params, + length < lastLength + ? length / 2 + : Math.floor(Math.floor((length - lastLength) / 2) + lastLength), + length, + close + ); + } + // If the current size is smaller than the max + if (renderedSize < maxSize) { + console.log({ + length, + lastLength, + renderedSize, + close, + size: "small", + }); + // Save this length as the closest so far + close = length; + // Recursively call with a larger string + return this.computeLargestTruncatedString( + str, + maxSize, + params, + Math.floor((lastLength - length) / 2) + length, + length, + close + ); + } + console.log("RETURNING", { length, lastLength, renderedSize }); + + return shortenedString; + }; + maybeTruncateString = (str, maxSize, fontSize, bold, italic) => { const activeFont = Truncate.getLoadedFont(); - - const renderedSize = pixelWidth(str, { + console.log({ activeFont }); + return this.computeLargestTruncatedString(str, maxSize, { font: activeFont, size: fontSize, map: widthsMap, bold, italic, }); - let truncatedString = null; - if (renderedSize > maxSize) { - const percentage = renderedSize / maxSize; - const newLength = str.length / percentage; - truncatedString = `${str.slice(0, newLength / 2)}…${str.slice( - -newLength / 2 - )}`; - } - - return truncatedString; }; render() { @@ -69,6 +137,8 @@ export default class Truncate extends Component { bold, italic ); + console.log({ truncatedString }); + // Only make tooltip if string has to be truncated if (truncatedString) { // clone children, changing the children(text) to the truncated string