Search code examples
javascriptsplitline-breaks

Split text [without \n or <br>] on visible line breaks with JS


I have a span with max-width and a long text without \n or < br>. Is it possible to get the positions of the automaticly generated line breaks via JS?

"Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam voluptua" within a small span breaks for example like this:

"Lorem ipsum dolor sit amet,[break]
consetetur sadipscing elitr,[break]
sed diam voluptua"

I need to split the lines on breaks or get the index of the "hidden line break"-characters.

https://jsfiddle.net/DerLangeVonTetris/x63Ldcez/

HTML:

<h1 class="multiline-headline">
    <span class="decoration-text">Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam voluptua</span>
</h1>
<div class="preview"></div>

JS:

(function () {
    var span = document.getElementsByTagName('span')[0],
        spanLines = [];

    // do magic start

    spanLines.push(span.innerText.slice(0,27));
    spanLines.push(span.innerText.slice(28,56));
    spanLines.push(span.innerText.slice(57));

    // do magic end

    document.getElementsByClassName('preview')[0].innerText = JSON.stringify(spanLines);    

}(window));

RESULT:

["Lorem ipsum dolor sit amet,","consetetur sadipscing elitr,","sed diam voluptua"]

Why I need this:

https://jsfiddle.net/DerLangeVonTetris/xgbsvpdy/

The decoration-break Polyfill "decofill" works on Edge when I add < br>s. But on responsive views I get problems when I add the HTML line breaks hardcoded. Therefore I need to add them on clientside.


Solution

  • I like your question! it has a big challenge, and i like challenges!!

    I'm going to use my own trick for answering this question (via pure js and for the first time - without the same):

    function MyOwnSplit(myTextDiv){
      var res = myTextDiv.innerHTML.trim().split(/ +/).map(function(t){
        return "<span>"+t+" </span>";
      });
      var mainText = myTextDiv.innerHTML;
      var fakeDiv=document.createElement("div");
      fakeDiv.innerHTML=res.join("");
      fakeDiv.setAttribute("style", myTextDiv.getAttribute("style"));
      fakeDiv.style.visibility='hidden';
      myTextDiv.insertAdjacentElement("afterend", fakeDiv);
      var finalRes={}, l=0, prvCTop=-Infinity;
      fakeDiv.childNodes.forEach(function(c){
        var top = c.offsetTop, A;
        if(top!=prvCTop) {
          l+=1;
          finalRes[l]=(A=[]);
          prvCTop=top;
        } else A=finalRes[l];
        A.push(c.innerHTML.trim());
      });
      fakeDiv.parentElement.removeChild(fakeDiv);
      return finalRes;
    }
    var res=MyOwnSplit(document.querySelector(".my-text"));
    console.log(JSON.stringify(res));
    //or getting all lines:
    var r={};
    for(var lN in res) {r["Line"+lN]=res[lN].join(" ");};
    console.log(JSON.stringify(r));
    <div style='width: 110px; border: solid 1px #f0f0f0' class='my-text'>
        Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam voluptua
    </div>
    <b>You can change the "width" and see the result.</b>

    • The result1 is a object which per key is number of related line & value is words of that line.

    • The result2 is a object which per key is line number & value is the line itself.