I have an array with a number of paragraphs which are to be placed inside a container until that container is »full«. Whatever does not fit into this container is to be placed into a separate container.
My solution mostly works fine, with a slight »cosmetic« error which I would like to fix.
My approach is to declare a maximum height for the container in which the text will be placed (0px
at the beginning, due to it being empty). This max-height is equal to the height of the element wrapping the container, which has its height set via CSS.
I then place the content into a text node
inside the first container by updating the nodeValue
. Before each iteration, the height of the container is checked and as long as it is not taller than the parent which is wrapping it, the content is placed. As soon as the first container is »full« (= its height is equal to its parent's height), the remaining content is placed into the separate container.
I cannot simply place each whole paragraph, because if the last paragraph that is placed inside the first container is long enough to fill multiple lines (of course depending on the container's/parent's width), these lines will still end up in the first container and be cut off. Therefore, I'm iterating over each word of each paragraph, checking the height every time the nodeValue
is updated.
This all works as expected, please see the attached snippet.
The only remaining issue is the last line of text inside the first container being only one word long. I know this happens of course because as soon as the nodeValue
is being updated with this word, the container's height is recognised as too tall to fit more content and the script moves on to the next container.
Is there a way to »catch« that last word and make sure it also gets placed into the second container? Or alternatively fill the last line of the first container properly, but I assume that is more complicated. Appreciate any advice.
// Utilities
function update_NodeContent(newContent, container) {
var nodeContent_old = container.childNodes[0].nodeValue;
var nodeContent_add = newContent + " ";
var nodeContent_new = nodeContent_old + nodeContent_add;
container.childNodes[0].nodeValue = nodeContent_new;
}
// Variables
var cellHeight = $("#cell1").height();
// Content
var content = [
"The quick, brown fox jumps over a lazy dog. DJs flock by when MTV ax quiz prog. Junk MTV quiz graced by fox whelps. Bawds jog, flick quartz, vex nymphs. Waltz, bad nymph, for quick jigs vex!",
"Fox nymphs grab quick-jived waltz. Brick quiz whangs jumpy veldt fox. Bright vixens jump; dozy fowl quack. Quick wafting zephyrs vex bold Jim. Quick zephyrs blow, vexing daft Jim. Sex-charged fop blew my junk TV quiz.",
"How quickly daft jumping zebras vex. Two driven jocks help fax my big quiz. Quick, Baz, get my woven flax jodhpurs! »Now fax quiz Jack!« my brave ghost pled. Five quacking zephyrs jolt my wax bed.",
"Flummoxed by job, kvetching W. zaps Iraq. Cozy sphinx waves quart jug of bad milk. A very bad quack might jinx zippy fowls. Few quips galvanized the mock jury box. Quick brown dogs jump over the lazy fox."
]
function placeText() {
while (content.length) {
var node = document.createTextNode("");
$("#cell1 .container").append(node);
//
var content_words = content[0].split(" ");
for (var i = 0; i < content_words.length; i++) {
//
var textBlockHeight = $("#cell1 .container").height();
if (textBlockHeight < cellHeight) {
update_NodeContent(content_words[i], $('#cell1 .container')[0]);
} else {
update_NodeContent(content_words[i], $('#cell2 .container')[0]);
}
}
//
var itemtoRemove = content[0];
content.shift();
}
}
// Execution
placeText();
:root {
--height_line_single: 19px;
--height_textBlock: calc(var(--height_line_single) * 14);
}
body {
font-size: 16px;
line-height: 1.2;
}
p {
margin: 0 0 1rem 0;
}
p.noMargin {
margin: 0;
}
.article {
width: 90vw;
}
.text-block {
height: var(--height_textBlock);
overflow: hidden;
background: lightgreen;
margin-bottom: 1rem;
}
#cell1 {
width: calc(100%/3);
}
#cell2 {
column-count: 3;
column-fill: auto;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<div class="article">
<div id="cell1" class="text-block">
<div class="container">
</div>
</div>
<div id="cell2" class="text-block">
<div class="container">
</div>
</div>
</div>
Here's a working example. The selectors and heights could be changed to use the jQuery versions if you desire. You didn't not finalize looping through the content in your example above, so I'll leave that for you to add.
This example can also be viewed on CodePen: https://codepen.io/edlucas/pen/MWYrybK
// Utilities
function update_NodeContent(newContent, container) {
// Ensure that we start with an empty string
var nodeContent_old = container.innerHTML ? container.innerHTML : '';
container.innerHTML = nodeContent_old + newContent + " ";
}
// Content
var content = [
"The quick, brown fox jumps over a lazy dog. DJs flock by when MTV ax quiz prog. Junk MTV quiz graced by fox whelps. Bawds jog, flick quartz, vex nymphs. Waltz, bad nymph, for quick jigs vex!",
"Fox nymphs grab quick-jived waltz. Brick quiz whangs jumpy veldt fox. Bright vixens jump; dozy fowl quack. Quick wafting zephyrs vex bold Jim. Quick zephyrs blow, vexing daft Jim. Sex-charged fop blew my junk TV quiz.",
"How quickly daft jumping zebras vex. Two driven jocks help fax my big quiz. Quick, Baz, get my woven flax jodhpurs! »Now fax quiz Jack!« my brave ghost pled. Five quacking zephyrs jolt my wax bed.",
"Flummoxed by job, kvetching W. zaps Iraq. Cozy sphinx waves quart jug of bad milk. A very bad quack might jinx zippy fowls. Few quips galvanized the mock jury box. Quick brown dogs jump over the lazy fox."
]
var containerHeight = document.querySelector('#cell1').clientHeight;
function placeText() {
if (content.length) {
var content_words = content[0].split(" ");
var holdContent = "";
var useSecondContainer = false;
var $textBlock1 = document.querySelector('#cell1 .container');
var $textBlock2 = document.querySelector('#cell2 .container');
var textBlockHeight = 0;
var word = '';
for (var i = 0; i < content_words.length; i++) {
word = content_words[i];
// Ensure that we have a word to display
if (word && word.trim()) {
textBlockHeight = $textBlock1.clientHeight;
// If we have not already exceeded the first container
if (textBlockHeight <= containerHeight && !useSecondContainer) {
// Add to first container
holdContent = $textBlock1.innerHTML;
update_NodeContent(word, $textBlock1);
// If we exceed the height with this addition, restore the contents to the
// last state and add this word to the second container
if ($textBlock1.clientHeight > containerHeight) {
// Restore last good content
$textBlock1.innerHTML = holdContent;
// Add to the second container
useSecondContainer = true;
update_NodeContent(word, $textBlock2);
}
} else {
// Add to the second container
update_NodeContent(word, $textBlock2);
}
}
}
}
}
// Execution
placeText();
:root {
--height_line_single: 19px;
--height_textBlock: calc(var(--height_line_single) * 2);
}
body {
font-size: 16px;
line-height: 1.2;
}
p {
margin: 0 0 1rem 0;
}
p.noMargin {
margin: 0;
}
.article {
width: 90vw;
}
.text-block {
height: var(--height_textBlock);
overflow: hidden;
background: lightgreen;
margin-bottom: 1rem;
}
#cell1 {
width: calc(100%/3);
}
#cell2 {
column-count: 3;
column-fill: auto;
}
<div class="article">
<div id="cell1" class="text-block">
<div class="container">
</div>
</div>
<div id="cell2" class="text-block">
<div class="container">
</div>
</div>
</div>