Pretty Word Wrapper with MooTools or PHP
Details, details, details. Details are what take a good site to the next level. Small details like link nudging (jQuery, MooTools), simple but stylish CSS enhancements, and opacity effects are the cheeky effects that give your website the edge over similar websites. The detail we'll be addressing today is "widowed" text. A "widow" occurs when only one word of a long string wraps to the next line. An example would be:
No offense to raging cougars out there but widows look wonky. The best way to prevent widows is to add a " " between the last and second-to-last words in a string. Doing this, the example above would split to the next like at "or" so that two words would be on the second line. Today I'll show you how to accomplish this using a tiny MooTools class or PHP.
The MooTools JavaScript
//class var WordWrapper = new Class({ Implements: [Options], options: { elements: 'h1', minWords: 3 }, initialize: function(options) { this.elements = $$(options.elements); this.elements.each(function(el) { this.apply(el); },this); }, apply: function(element) { var original = element.get('html'), arr = original.split(' '); if(arr.length >= this.options.minWords) { //join the last and second to last arr[arr.length - 2] += ' ' + arr[arr.length - 1]; arr.pop(); element.set('html',arr.join(' ')); } } });
The MooTools plugin offers just a few options: the elements to apply this too and the minimum number of words the element must have before the substitution takes place. The usage is just as easy as you'd expect:
//usage window.addEvent('domready',function() { var ww = new WordWrapper({ elements: 'h2' }); }); //sample results //"This Is The First Attempt" becomes: This Is The First Attempt //"Leave Me" is not long enough to modify //"Que?" is not long enough to modify //"I Am, I Am SuperMan, And I Can Do Anything" becomes: I Am, I Am SuperMan, And I Can Do Anything
Awesome....but what about a PHP version? Sure, why not?
The PHP
function word_wrapper($text,$minWords = 3) { $return = $text; $arr = explode(' ',$text); if(count($arr) >= $minWords) { $arr[count($arr) - 2].= ' '.$arr[count($arr) - 1]; array_pop($arr); $return = implode(' ',$arr); } return $return; }
And Voila! Now you can update any text before it hits the DOM!
The jQuery
Wanna see how you'd accomplish this feat with jQuery? Hop over to Chris Coyier's CSS-Tricks blog post to find out!
Wouldn’t it be more safe-mode friendly if you used document.getElements() instead of $$?
@Chris the Developer: How so?
Took me a while to understand what this was doing until I noticed that the   is replaced by a blank space ‘ ‘ in the code!
Should read: $arr[count($arr) – 2].= ‘ ’.$arr[count($arr) – 1];
Thanks Francis! Stupid WordPress…
Ineresting approach, I use a little function that cuts the text off after a certain amount of characters and then adds … to it. Of course I’m checking correctly for things like, cutting at the first space before the max amount of chars, taking care of commas and hyphens, etc
Hmm.. I like this idea, but still the www is not a thing like print is in combination with InDesign (I reffuse to mention Quark, lol), which have advanced widow cut rules etc. build in. I mean, it’s not always appropriate to move the two last words to the next line as a default in various languages/situations.. then I rather blame the browser’s neanderthaler rudeness :)
But again, it’s an original idea which probably makes the headlines in most cases a bit nicer, and the JS is small (and php is fast).
You can stream line you code a little by changing the
with
You can do the same with the PHP too.
since the array Pop method both removes the last item in the array AND returns its value. Though this will not make a huge impact on the performance of the code it is code practice.
I can’t get this to work. Am I doing something wrong?
I add the php code into the head but it doesn’t add a non-break-space
Can anyone point me to a working example?
Works fine for us with PHP, example in the h1 headline at http://charleston.thedigitel.com/politics/folly-beach-bans-discrimination-based-sexual-orien-38425-0315
I also modified it a bit to allow for us to concat the last three words if there are six or more words (good for our headline setup), code below.
Fiddlesticks, it garbled my code paste (I even used the
tags!) See it here http://pastebin.com/DhVKZu1T
Okay, I give up. Here is a Gist on how to do it in Ruby: https://gist.github.com/stephenhowells/6245701“>https://gist.github.com/stephenhowells/6245701” rel=”nofollow”>https://gist.github.com/stephenhowells/6245701
I believe this should be done on the front-end, however here’s an alternate PHP implementation (no support for min words):
I believe this should be done on the front-end, however here’s an alternate PHP implementation (no support for min words): http://pastebin.com/0h6ZqZUE