JS for-loop + if-statement: перехват последнего вхождения при условном обновлении текстового узла

У меня есть массив с несколькими абзацами, которые должны быть помещены в контейнер, пока этот контейнер не будет «заполнен». Все, что не помещается в этот контейнер, должно быть помещено в отдельный контейнер.

Мое решение в основном работает нормально, с небольшой «косметической» ошибкой, которую я хотел бы исправить. Мой подход состоит в том, чтобы объявить максимальную высоту контейнера, в который будет помещен текст (0px в начале, так как он пуст). Эта максимальная высота равна высоте элемента, обертывающего контейнер, высота которого задается с помощью CSS.

Затем я помещаю содержимое в text node внутри первого контейнера, обновляя файл nodeValue. Перед каждой итерацией проверяется высота контейнера, и пока он не выше родителя, который его обертывает, содержимое размещается. Как только первый контейнер «полный» (= его высота равна высоте его родителя), оставшееся содержимое помещается в отдельный контейнер.

Я не могу просто поместить каждый абзац целиком, потому что если последний абзац, помещенный в первый контейнер, достаточно длинный, чтобы заполнить несколько строк (конечно, в зависимости от ширины контейнера/родителя), эти строки все равно окажутся в первом контейнере и быть отрезанным. Поэтому я перебираю каждое слово каждого абзаца, проверяя высоту каждый раз, когда обновляется nodeValue.

Все это работает, как и ожидалось, см. прикрепленный фрагмент.

Единственная оставшаяся проблема заключается в том, что последняя строка текста внутри первого контейнера имеет длину всего одно слово. Я знаю, что это происходит, конечно, потому что, как только nodeValue обновляется этим словом, высота контейнера распознается как слишком высокая, чтобы вместить больше содержимого, и скрипт переходит к следующему контейнеру.

Есть ли способ «поймать» это последнее слово и убедиться, что оно также помещено во второй контейнер? Или, альтернативно, правильно заполнить последнюю строку первого контейнера, но я предполагаю, что это сложнее. Ценю любые советы.

// 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>


person JoSch    schedule 04.01.2020    source источник


Ответы (1)


Вот рабочий пример. Селекторы и высоты можно изменить, чтобы использовать версии jQuery, если хотите. Вы не завершили цикл по содержимому в приведенном выше примере, поэтому я оставлю это на ваше усмотрение.

Этот пример также можно посмотреть на 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>
person Ed Lucas    schedule 05.01.2020