Kevin
Kevin

Reputation: 13226

Splitting strings, preserve HTML tags and words

I need to take an input from a WYSIWYG and break it down to having 33 (or approximate) characters per line. If it hits the limit, I need to insert a new line. Here is what I came up with:

for($i=0; $i < strlen($string); $i++) {
  if ($i % 33 == 0 && $i != 0) {
    $characters[] = '\r';
  }
  $characters[] = $string[$i];
}

$result = implode($characters);

This breaks HTML tags and words. I need to ignore HTML tags, and allow words to finish before breaking a line. What is a better way to achieve this?

Upvotes: 0

Views: 831

Answers (2)

Jemaclus
Jemaclus

Reputation: 2376

What I would do is explode by space, then figure out the number of "words" that can fit on a line without going over 33 characters.

 $words = explode(' ', $string); // Get all the "words" into one string
 $lines = array(); // Array of the lines
 $line = array(); // One line
 for ($i = 0; $i < count($words); $i++) {
     $new_line = array_merge($line, $words[$i]); // Previous line plus this word
     $new_line_length = strlen(strip_tags(implode(' ', $new_line))); // Length of line
     if ($new_line_length <= 33) { // Is this line under 33 characters?
         $line[] = $words[$i];  // Yes, let's add this word to the line
     } else { // No, too long.
         $line[] = "\r";  // Add newline
         $lines[] = $line; // Add $line to the $lines array
         $line = array(); // Reset the line
     }
 }
 $final_string = implode('', $lines); // Put the whole thing back into one string

I just did this in here and haven't tested it, but it's the basic general idea. Hope it helps. Good luck. :)

Edit: added strip_tags() to the length check so tags won't affect the length of the line (since they're invisible anyway)

Upvotes: 1

Halcyon
Halcyon

Reputation: 57719

I've found that JavaScript is actually very good at this because you have the power of the DOM available. You can just ask "how wide is this piece of tekst", which takes individual character widths into account.

The overall idea is:

  1. Traverse your DOM fragment from root to leafs.
  2. For each node determine if it is a block level element (like div) or an inline element (like span or a). For block level elements: assume they will begin on a new line and end with a new line, so reset your counters accordingly.
  3. Keep adding characters (or words) to some invisible div which has the same font properties as the wysiwyg and query the width. If the width exceeds your set amount, insert a line break.

Upvotes: 0

Related Questions