I need a solution to dynamically trim multi-line text in a container and have it end with ellipses instead.
CSS non-solution
Ideally CSS (line clamp) would handle this, but the Browser Support is just not there (85.65%). - Also it's currently an "extremely fragile [...] half-baked non-standardized propert[y]" (source).
JS: Pop until it fits (current solution)
I currently have a working JavaScript solution (measure & pop, until it fits), but it scales poorly. It's affected by the difference between text length and clamped length as well as the number of clamped text elements.
var trimTextAddEllipses = function (targetElementClassName) {
var elArray = document.getElementsByClassName(targetElementClassName);
Array.from(elArray).forEach(function (el) {
// create a cache of full text in data-attribute to be non-destructive
if (!el.hasAttribute('data-text-cache')) {
el.setAttribute('data-text-cache',el.textContent);
}
// reset
var words = el.textContent = el.getAttribute('data-text-cache');
// turn into array to pop off items until it fits.
var wordArray = words.split(' ');
while (el.scrollHeight > el.offsetHeight) {
wordArray.pop();
el.innerHTML = wordArray.join(' ') + ' …';
}
});
};
For resizes I call it as callback to a requestAnimationFrame call to limit the number of times the clamping is done.
JS: Binary search (goal)
The words are in order (i.e. sorted), so a binary search approach would work to make the code more effective.
I found this this binarySearch function but can't come up with a comparison function to make this work properly.
I'd like help coming up with either a comparison function to use with the linked binary search function - or a different binary search solution that works for this problem.
Note
From the comments I'm aware that there's room for further optimization past binary search, but that it would require a lot of JS work (i.e. estimating rather than measuring, thus avoiding rendering this over and over) - but that seems too difficult.