0

I have given text strings which are displayed in containers of varying width. I want to allow linebreaks only after the character "·", which occurs two or three times in each of those text strings.

What I came up with (see below): With jQuery, I wrapped a span around the whole string with a css class that applies white-space: nowrap; to the string, and additionally I added a <br> tag after each "·", both using a replaceAll function: Now line breaks can only happen at the position of the inserted <br> tags.

My problem: This forces line breaks at all <br> tags. But if part one and two of the text string (i.e. the text up to the second "·" character) would fit into the parent container next to each other, I would like the line break only to happen after the second "·"!

var mytext = $('#wrapper2 .string1').text();
var search = " ·";

$('#wrapper2 .string1').each( function(index, element) {
  $(element).html( $(element).html().replaceAll(mytext, '<span class="inner_wrapper">' + mytext + '</span>') );
  $(element).html( $(element).html().replaceAll(search, search + '<br>') );
})
.wrapper1 {
  width: 400px;
  border: 1px solid #aaa;
  padding: 0.5em;
  font-size: 18px;
  text-align: center;
}

#wrapper2 .inner_wrapper {
  white-space: nowrap;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<h3>The original text</h3>
<div id="wrapper1" class="wrapper1">
  <p class="string1">The title of the event · day, month and year · at the end the location</p>
</div>
<p>The width of the above box can change. What I want: Linebreaks should only occur <b>after the "·" characters</b>.</p>
<h3>The text processed by jQuery</h3>
<div id="wrapper2" class="wrapper1">
  <p class="string1">The title of the event · day, month and year · at the end the location</p>
</div>
<p>This comes close, but if there is enough space (as in the boxes above), the first linebreak should occur after the <b>second</b> "·" character, not after <em>all</em> of them.</p>
Johannes
  • 64,305
  • 18
  • 73
  • 130
  • 1
    Use [``](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/wbr#:~:text=The%20HTML%20element%20represents,a%20break%20at%20that%20location.) instead of `
    `. As an alternative the HTML Unicode entity `­` is feasible.
    – zer00ne Dec 13 '22 at 23:10
  • @zer00ne Well, at least in combination with `white-space: nowrap;` this doesn't work as desired. I'd have to find a way to wrap the *parts* of the text (i.e. the parts between the `·` characters), apply `white-space: nowrap;` to those spans and then add `` between those parts. But I don't know how to split the text that way – although if I can split it that way, I wouldn't need the `` anymore and could just have regular spaces between the spans... – Johannes Dec 13 '22 at 23:19
  • 1
    You could .split() the original string into an array using "·" as the delimiter, then calculate the width of each segment (see https://stackoverflow.com/questions/118241/calculate-text-width-with-javascript). Then iterate over the array, reconstructing the string and adding
    based on the widths and the box width.
    – Nikkorian Dec 13 '22 at 23:52

2 Answers2

1

You could use the <wbr /> tag to add a word break only when needed, but unfortunately this does not work with a white-space: nowrap; style. The trick is to remove that style, replace all spaces with &nbsp; (non-braking space) entity, and restore spaces (or <wbr /> tags) where needed:

var $el = $('#wrapper2 .string1');
var html = $el.text()
  .replace(/ /g, '&nbsp;')
  .replace(/(&nbsp;·)/g, '$1 '); // or replace with '$1<wbr />'
$el.html(html);
.wrapper1 {
  width: 400px;
  border: 1px solid #aaa;
  margin: 3px 0;
  padding: 0 0.5em;
  font-size: 18px;
  text-align: center;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<b>The original text</b>
<div id="wrapper1" class="wrapper1">
  <p class="string1">The title of the event · day, month and year · at the end the location</p>
</div>
<b>The text processed by jQuery</b>
<div id="wrapper2" class="wrapper1">
  <p class="string1">The title of the event · day, month and year · at the end the location</p>
</div>
Peter Thoeny
  • 7,379
  • 1
  • 10
  • 20
  • Thank you, that's a good solution, it uses less code than my own solution which I came up with inspired by @Nikkorians comment about `split()` (I might post that later to provide an alternative). But actually the `` tag isn't needed at all for this: In the second step, `· ` can simply be replaced by `· `, i.e. using a regular space at which the string will also only break if necessary. I guess the `` tag is rather intended for situations where one wants to allow a *word* (or any part of the string not containing spaces) to be broken without hyphen. – Johannes Dec 14 '22 at 13:40
  • FYI, there is also a `­` that hyphenates as needed. – Peter Thoeny Dec 14 '22 at 18:42
  • 1
    I updated the answer to restore spaces instead of `` where needed – Peter Thoeny Dec 14 '22 at 18:52
0

To complete this question/answer set for anyone who's interested, here's the solution I came up with myself after reading @Nikkorian's comment concerning split() and wrapping the split substrings in <span> tags, to which I apply white-space: nowrap via CSS to avoid linebreaks inside them:

I split the text string using split('·') (var "parts", which is an array), looped through that array until the next-to-last part adding span tags around it and a · before span's end tag, then added the last part, also with a span tag around it, but without the · at the end.

$('#wrapper2 .string1').each( function(index, element) {
  var parts = $(element).text().split(' · ');
    var editedContent = '';
    for(var i=0; i < parts.length - 1; i++) {
            editedContent += '<span>' + parts[i] + ' ·</span> '; 
    }
    editedContent += '<span>' + parts[i] + '</span>';
    $(element).html(editedContent); 
});
.wrapper1 {
  width: 400px;
  border: 1px solid #aaa;
  padding: 0.5em;
  font-size: 18px;
  text-align: center;
}
#wrapper2 > .string1 > span {
 white-space: nowrap;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<h3>The original text</h3>
<div id="wrapper1" class="wrapper1">
  <p class="string1">The title of the event · day, month and year · at the end the location</p>
</div>
<p>The width of the above box can change. What I want: Linebreaks should only occur <b>after the "·" characters</b>.</p>
<h3>The text processed with javascript/jQuery</h3>
<div id="wrapper2" class="wrapper1">
  <p class="string1">The title of the event · day, month and year · at the end the location</p>
</div>
<p>This is the desired result: linebreaks can only occur after the "·" characters which appear between the substrings, but if the container is wide enough, two or more substrings can appear in the first line.</p>
Johannes
  • 64,305
  • 18
  • 73
  • 130