I have a div tag with dynamic text value and I want to find how to calculate the number of rows that the string spreads out to according to the font size and the div width
For example:
div {
width: 15px
fontSize: 12px
overflow: hidden
display: block
overflow-wrap: break-word
}
and the string is: "abcdefghijk"
the result in the UI will be:
first row- "abc" second row- "defg" third row- "hijk"
So expected calculation value should be 3 (3 rows).
Is it possible to calculate that?
http://jsfiddle.net/b6upgdqz/15/
CodePudding user response:
I guess you would have to explicit also the line-height and then divide the total height of the containing div by the line-height you set...
const input = document.getElementById("text");
const container = document.getElementById("container");
const rows = document.getElementById("rows");
input.addEventListener("input", function handleInputChange(event) {
updateRowsCount(event.currentTarget.value);
});
function updateRowsCount(text) {
writeText(text);
computeRows(container);
}
function writeText(text) {
container.innerHTML = text;
}
function computeRows(container) {
const style = window.getComputedStyle(container);
const containerHeight = parseFloat(style.height);
const lineHeight = parseFloat(style.lineHeight);
const rowsCount = Math.ceil(containerHeight / lineHeight);
rows.innerHTML = rowsCount;
}
updateRowsCount(input.value);
#sample {
display: flex;
align-items: flex-start;
}
#sample > * {
margin-right: 2rem;
}
#container {
width: 15px;
font-size: 12px;
line-height: 1.2;
overflow: hidden;
display: block;
overflow-wrap: break-word;
background: pink;
}
<div id="sample">
<input id="text" value="abcdefghijkl" />
<div id="container"></div>
<div id="rows"></div>
</div>
CodePudding user response:
Working Demo: https://dojo.telerik.com/EzEjucOF/5
var calculateLineCount = function (element) {
var lineHeightBefore = element.css("line-height"),
boxSizing = element.css("box-sizing"),
height,
lineCount;
// Force the line height to a known value
element.css("line-height", "1px");
// Take a snapshot of the height
height = parseFloat(element.css("height"));
// Reset the line height
element.css("line-height", lineHeightBefore);
if (boxSizing == "border-box") {
// With "border-box", padding cuts into the content, so we have to subtract
// it out
var paddingTop = parseFloat(element.css("padding-top")),
paddingBottom = parseFloat(element.css("padding-bottom"));
height -= (paddingTop paddingBottom);
}
// The height is the line count
lineCount = height;
return lineCount;
}
$("#lineCount").html("Total number(s) of line : " calculateLineCount($(".divwrap")));
div {
width: 22px;
font-size: 12px;
overflow: hidden;
display: block;
overflow-wrap: break-word;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<div >
abcdefghijk
</div>
<h2 id="lineCount"></h2>
CodePudding user response:
You can get the bounding boxes for each line through Range#getClientRects().
If your #container
contains further markup like <div>
s etc. The bounding boxes for these are also added to the list and need to be filtered out.
const input = document.getElementById("text");
const container = document.getElementById("container");
const rows = document.getElementById("rows");
input.addEventListener("input", function handleInputChange(event) {
updateRowsCount(event.currentTarget.value);
});
function updateRowsCount(text) {
container.innerHTML = text;
const range = document.createRange();
range.selectNodeContents(container);
let rects = range.getClientRects();
// deal with markup;
rects = [...rects]
// sort them by vertical position, leafnodes before their parents.
.sort((a, b) => a.bottom - b.bottom || b.top - a.top)
// remove the bounding boxes for nested markup; in this case, the <p>
.filter((v, i, a) => !i || v.top >= a[i - 1].bottom);
const rowsCount = rects.length;
rows.innerHTML = rowsCount;
}
updateRowsCount(input.value);
#sample {
display: flex;
align-items: flex-start;
}
#sample > * {
margin-right: 2rem;
}
#container {
width: 15px;
font-size: 12px;
line-height: 1.2;
overflow: hidden;
display: block;
overflow-wrap: break-word;
background: pink;
}
<div id="sample">
<input id="text" value="ab<p>cdefghij</p>kl" />
<div id="container"></div>
<div id="rows"></div>
</div>