M
M
MarvinJan2019-10-07 22:03:38
JavaScript
MarvinJan, 2019-10-07 22:03:38

How to optimize the dynamic truncate of the middle of a list?

Good evening, colleagues!
In general, there is one interesting problem - it has been solved, but the optimization leaves much to be desired, which I wanted to consult with you about.
The essence of the problem: there is an array of strings in the angular

["Java",  "projects",  "dev",  "test",  "controller",  "src",  "main",  "resources",  "application"]

Each line is output to li > a via *ngFor . All li - horizontally, in a line. So, when the elements start to climb onto the next line, you need to truncate the entire list in the center and add "..." there, that is, it was:
Java projects dev test controller src main resources application

And on the smaller screen it became:
Java projects ... main resources application
Currently implemented as follows:
public truncateRow() {
    if (this.isExcessiveWidth() && this.truncatedItems.length > 3) {
      const centralItemIndex = Math.floor((this.truncatedItems.length - 1) / 2);
      this.truncatedItems.splice(centralItemIndex, 2, "...");
      return setTimeout(() => {
        this.truncateRow();
      });
    }
  }

1. The need for truncation is checked by the isExcessiveWidth method (compares the height of the parent ul with the first li , if more = needs to be truncated) and the presence of at least 3 lines in the array, so that, taking into account the addition of "...", there will always be at least 3 lines.
2. Next, take the central element of the array, cut it out and the next one, add an ellipsis in their place.
3. Repeat until the conditions are no longer met.
setTimeout is needed to allow new ul dimensions to render.
And so actually a question:
All it works, but: process of "truncation" is noticeable for a human eye - user experience suffers.
Perhaps there is some other approach, without recursion, or with it, but more optimized?

Answer the question

In order to leave comments, you need to log in

2 answer(s)
A
Anton Shvets, 2019-10-08
@Xuxicheta

Instead of an explicit child li, you create an invisible one with opacity: 0; position: absolute to take it out of the flow and hide it visually. Unlike display: none , the element will be rendered and its geometric dimensions will be available.
Get its length, get the length of the parent, truncate the array until li is shorter than the parent.
And only then do you show the main li with a truncated array.
You can use the same li, just change the class for it.

F
forspamonly2, 2019-10-11
@forspamonly2

if you don’t have complex texts there (with all sorts of rtl fragments and other perversions affecting the layout), then you can try to calculate the sizes by hand using measureText from canvas

Didn't find what you were looking for?

Ask your question

Ask a Question

731 491 924 answers to any question