I have been searching to implement a solution to calculate the lines of an element in React (writing in Typescript) using React Hooks and Redux.
A jquery implementation I found and liked here from member e-info128 that has 9 votes for the only reason that
"Works in all browsers without rare functions out of standards."
In the current project that I work on, we implement jquery as well (don't ask why we mixed the two, it was not our decision)... So initially I tried to make it work in jquery. And it works!! The code below does the job.
const calculate = (obj: JQuery<HTMLElement>) => {
let cloned = obj.clone(true, true);
cloned.html('a<br>b').hide().appendTo(parentClass);
let size = cloned?.height()! / 2;
cloned.remove();
let noOfLines = obj?.height()! / size;
return Math.trunc(noOfLines);
}
window.addEventListener("resize", () => {
let element = $('#calculateLines');
if (element) {
let lines = calculate(element);
console.log(lines);
}
});
However I really wanted to try and "translate" this and not use jquery...
So I have the following snippet:
const calculateNotInJQuery = (obj: HTMLElement) => {
let cloned = obj.cloneNode(true) as HTMLElement;
let tempElement = document.createElement('p');
tempElement.innerHTML = "a<br></br>b";
tempElement.setAttribute("type", "hidden");
let parentElement = document.getElementById('someParentClass');
cloned.appendChild(tempElement)
parentElement?.appendChild(cloned);
let size = cloned.clientHeight / 2;
cloned.remove();
let noOfLines = ((obj.clientHeight / size);
return Math.trunc(noOfLines);
}
window.addEventListener("resize", () => {
let element = $('#calculateLines');
if (element) {
let lines = calculate(element);
console.log(lines);
}
});
The last line returns always 1. If I remove Math.trunc, it takes values from 0 to 1. I understand that I have trouble "translating" this line:
cloned.html('a<br>b').hide().appendTo(parentClass);
to make it work. What I think it says, is: we create some html for the cloned Node, we hide it and we append it to the parent element.
so I tried to do something similar but I do not know where my logic is wrong here:
let cloned = obj.cloneNode(true) as HTMLElement;
let tempElement = document.createElement('p');
tempElement.innerHTML = "a<br></br>b";
tempElement.setAttribute("type", "hidden");
let parentElement = document.getElementById('someParentClass');
cloned.appendChild(tempElement)
parentElement?.appendChild(cloned);
Any suggestions will be appreciated as always. Thank you in advance!
[EDIT]
After ori-drori's suggestion, I created the solution and I also created a sandbox because there seems to be sth wrong with it.
The sandbox is here.
What happens is,
- when the button is as "Read More", then the lines are calculated correctly -when I resize the window-.The button is hidden or displayed as it should.
- Now I click on the Read More, all the text is displayed, and the correct calculated lines are visible. We have the "Read Less" label now.
- When I resize the window, with the "Read Less" description and all the text displayed, the calculation is not correct. For instance, I can have 5 lines visually but the calculation gives me 7 lines.
What am I doing wrong now? What is happening between expanding and collapsing the text that gives me a faulty number of lines?