willoller.com

Avatar

Learning to match the beat of the Old World man.

Ordinal Suffixes in PHP


function ordinalize($int) {

   //sanity
   $int = (int)$int;
   if(!is_numeric($int)) return false;

   // You could internationalize here
   $suffixes = array('th', 'st', 'nd', 'rd');

   // Get the number in the tens place
   $tens = substr($int,-2,1);

   // All of the numbers 10-19 return 'th'
   if($tens == 1) return $int.$suffixes[0];

   // Get the number in the ones place
   $cardinal = substr($int,-1);

   // All numbers ending in 1, 2, 3 have special suffixes
   if($suffixes[$cardinal]) return $int.$suffixes[$cardinal];

   // All remaining numbers end in 'th'
   return $int.$suffixes[0];

}

 

Textile ol li count bug

Just hit a bug with the Textile 2.0 library:


# Portland, OR
# Sanford, FL
# Albuquerque, NM
# San Diego, CA
# Bellingham, WA
 

Was producing:


<ol>
   <li>Portland, OR</li>
   <li>Sanford, FL</li>
   <li>Albuquerque, NM</li>
   <li>San Diego, CA   </li>
</ol>
<ol>
   <li>Bellingham, WA</li>
</ol>
 

Found the solution here:

You can work around the problem, by replacing these two lines (in the fList function in /textpattern/lib/classTextile.php):

foreach($text as $line) {
  $nextline = next($text);

 
with:

foreach($text as $nr => $line) {
  $nextline = isset($text[$nr+1]) ? $text[$nr+1] : false;

 

Counting Characters php vs javascript

On a recent project, an issue cropped up where we were exporting xml reports to a third party, who had rules about line lengths in Description fields.

So, I wrote up a quick-and-dirty character counter for the description field so the client can keep their descriptions under the 1500-word limit.

Here’s how it was done:


if (!$fdata['description']) {
   $errors[] = "You must enter a Description";
} elseif(strlen($fdata['description']) > 1500) {
   $len = strlen($fdata['description']);
   $errors[] = "Descriptions are limited to 1500 characters ($len)";
}

 

Now the html and javascript:


<li class="description">
   <label for="htmlarea" class="required">Description *</label>
   <textarea name="description" id="htmlarea" cols="80" rows="20" class="textarea">< ?= $ff['description'] ?></textarea>
   <p class="hint" id="desc_char_count">1500 character limit</p>
</li>
 

$(function(){
   $('#htmlarea').keyup(function(){
      var charLength = $(this).val().length;
      $('#desc_char_count').html(charLength + ' of 1500 characters used');
      if($(this).val().length > 1500) {
         $('#desc_char_count').removeClass('positive').addClass('negative').html('<strong>You have ' + $(this).val().length + ' characters. You may only have up to 1500 characters.</strong>');
      } else {
         $('#desc_char_count').addClass('positive').removeClass('negative');
      }
   });
   $('#htmlarea').keyup();
});

 

All was working well, except I underestimated the descriptions. The next morning, the thing was broken. The php side was kicking validation errors (“over 1500 characters”), while the javascript was counting a mere 1480. Why?

Turns out the data was full of bullets and other multibyte characters. To make the counts match, I needed multibyte-safe php:


if (!$fdata['description']) {
   $errors[] = "You must enter a Description";
} elseif(mb_strlen($fdata['description'],'UTF-8') > 1500) {
   $len = mb_strlen($fdata['description'],'UTF-8');
   $errors[] = "Descriptions are limited to 1500 characters ($len)";
}

 

Hooray! Now the counts match!

Continue

Before you go