Solving the html word wrapping problem in DayPilot Lite

A while ago I ported the DayPilot Lite calendar/schedule control into a Monorail view component and everything went smooth except for the word wrapping.

Whenever an event in the calendar/schedule contained a word that did not fit the placeholder the entire description was hidden from the end user.

It looked like this:

When it should look something like this:

This problem was inherited from the original implementation so I didn’t care about solving it while porting the code. But recently it started to become a real pain and I had to try and solve it without messing anything up.

I did a quick search on SO and found two interesting threads, word wrap in css/js and
Who has solved the long-word-breaks-my-div problem?.

CSS to the rescue?

My first attempt to solve the issue was by fixing it with css (as it always should be when it comes to display issues).
I began by digging into the rendered HTML in search for a suitable css select to modify.

omfg…

Well that reminded me why I didn’t want to do any bigger modifications to the control in the first place.

Anyway, I ended up adding a class called dpevent to the div containing the event description, inserted the css definition below and crossed my fingers while firing it up in Chrome…

.dpevent{
    white-space: pre-wrap; /* css-3 */
    white-space: -moz-pre-wrap; /* Mozilla, since 1999 */
    white-space: -pre-wrap; /* Opera 4-6 */
    white-space: -o-pre-wrap; /* Opera 7 */
    word-wrap: break-word; /* Internet Explorer 5.5+ */ 
}

…and got back an event worse looking page then before!

Epic css fail!

I even tried IE8 to see if that would render the page but no, still the same result.
Obviously having white spaces set to “pre”-mode in the css is a very bad thing when the target tag contains a lot of extra white-spaces.
(Is it possible to disable indention on a HtmlTextWriter?)

Css and JavaScript/jQuery to the rescue?

Since the simple css tricks did not work this time I decided to try and fix it with some classic Internet duct tape (JavaScript and jQuery).
I wrote a very simple script to remove (trim) all the whitespace around the description.

        $(document).ready(function() { 	
		$(".dpevent").each(function (){
			$(this).html($(this).html().trim())
		});
	});

But did it work?

No, it only took me exactly back to where I started.

JavaScript/jQuery to the rescue?

After giving up on css I started looking at the alternatives for manually inserting word breaks into the text. A couple of promising JavaScript projects (e.g. hyphenator) turned up but they all seemed to be overkill for this simple case.

The suggestions on SO got me curious on to the wbr tag that seemed to be just what I needed. As a couple of other’s already demonstrated on SO, inserting ​ in between every four letter or so should do the trick. But since even a four letter word would be too wide in my case I decided to insert word breaking symbols all over the place.

	function wrappableString(string) {
	  var output = '';
	  for (var i=0; i<string.length; i++) {
		output += string.charAt(i);
		output += '&#8203;';
	  }
 
	  return output;
	}
 
	$(document).ready(function() { 	
		$(".dpevent").each(function (index, element){
			$(this).html(wrappableString($(this).html().trim()))
		});
	});


YES! Finally I got some results although it looked like s**t when the time was wrapped as well.

Server side to the rescue!

I could have continued on my JavaScript path to salvation here and include some logic in the script for only including word breaks around letters and hence leave numbers and punctuation marks etc.

But instead of going down that road I came to my senses and realized that this would probably be much easier to solve on the server side before the event had been reduced to a simple string. So just before the string concatenation was done I added my little “WrappableString” (terrible name! suggestions?) method for constructing a strings that wraps nicely even in small places.

        private void renderEvent(HtmlTextWriter output, Event e, Day d)
        {
            string displayText = WrappableString(e.Name) + " (" + e.Start.ToShortTimeString() + " - " + e.End.ToShortTimeString() + ")";
            // Black hole...
        }
 
        private static string WrappableString(string inputString) {
            if (string.IsNullOrEmpty(inputString)) return String.Empty;
            var sb = new StringBuilder();
            foreach (var c in inputString.Trim()) {
                sb.Append(c);
                sb.Append("&#8203;"); // http://www.quirksmode.org/oddsandends/wbr.html
            }
            return sb.ToString();
        }


Bingo!

No comments yet.

Leave a Reply