9

Aug

Deko Boko 1.1 - Compatible with IE 7 and the New WP-reCAPTCHA

Topic: WordPress and Web Programming
Tags: , , ,

A report of CSS trouble with IE7 in Deko Boko 1.0 has led me to release a fairly major upgrade - Deko Boko 1.1 is available for download at wordpress.org:

  • I’ve completely rewritten the XHTML and the CSS for the contact form. If you’re upgrading, and you’ve customized your contact form, you’ll need to migrate your changes. The reason is that the widely used CSS “clearfix” code that I had in Deko Boko breaks in IE7 (I know, I’m late in catching this - I’ve switched to Ubuntu on my laptop and I wasn’t keeping up with the latest Microsoft nonsense). For reasons explained in my rant below, this pushed me to do a full rewrite, which simplifies both the markup and the CSS.
  • One of the features of Deko Boko is that is it plays nicely with WP-reCAPTCHA (the official reCAPTCHA plugin for handling spam in comments). The latest version of WP-reCAPTCHA changed the name of the WordPress option variable where it stores its API key, so Deko Boko now looks for it under the new name and the old name.
  • I added a language selector to the Deko Boko settings menu, so you can choose a language other than English for the reCAPTCHA widget.

<rant>The challenge with writing a plugin like this is keeping both the XHTML and the CSS at a level where you don’t need to be a coding guru to make changes yourself. I want the Deko Boko contact form to be customizable by people with beginner-to-intermediate level coding skills. But there are a multitude of variations in how CSS is implemented in different browsers, not to mention the things that are just plain broken. Nowhere is this problem worse than forms. So developers are often forced to choose between doing semantically “incorrect” things in their markup (like using br tags to force certain layout effects), or writing hundreds of lines of complicated CSS, often with filters to deal with incompatibilities between browsers.

Unfortunately the solution for the IE7 “clearfix” problem I mentioned above breaks clearfix for IE6 (requiring an IE6 filter to then fix that). IMHO clearfix is a hack to begin with, needed to deal with an oversight in the CSS model. And in any event, the code needed to fix the problem for definition lists was way too fragile for a plugin like this, which is meant to be flexible and extensible. So I dropped the definition list in favor of an ordered list, following the techniques described in Cameron Adam’s excellent article on form layout. His approach to form layout is the best I’ve seen, with some clever yet simple approaches to the markup (the right word is “elegant” - as it’s semantically correct too) to get around some of the most common problems with form layout. It’s also such a well written and highly detailed article, that I can simply refer you to it if you want to extend the layout of the Deko Boko contact form to suit your own needs ;-) .</rant>

4

Jun

Making an HTML Table Using Arrays of Column Data

Topic: WordPress and Web Programming
Tags: ,

Most of the time, if you need to create an HTML table to display data pulled from a database, it’s a fairly straightforward task: the data is organized in rows, and since HTML tables are generated in rows, it’s easy to loop through the rows of data and display them in succession. But sometimes you can have a situation where you want to display the data as columns, which is not something you can easily do in HTML. Here’s an example of how to approach this challenge.

Displayed below is an array of data from a project I’ve been working on. I’ll explain the color coding in a minute. The first element is a sub array of laboratory sample IDs, and the subsequent elements are subarrays indicating which laboratory tests should be run on which samples. (I’ll spare you an explanation of the database structure behind all this, but suffice it to say that pulling out the data with this organization was the most efficient solution).


Array[4] (
    0 => Array[6] (
        0 => 'Sample ID',
        1 => 193,
        2 => 194,
        3 => 195,
        4 => 196,
        5 => 197,
    ),
    1 => Array[4] (
        0 => 'Phospholipids',
        1 => 'Y',
        3 => 'Y',
        5 => 'Y',
    ),
    2 => Array[6] (
        0 => 'Apolipoprotein A-I',
        1 => 'Y',
        2 => 'Y',
        3 => 'Y',
        4 => 'Y',
        5 => 'Y',
    ),
    3 => Array[4] (
        0 => 'Gastrin',
        2 => 'Y',
        3 => 'Y',
        4 => 'Y',
    ),
)

How I ultimately what to display the data is like this:

Sample ID Phospholipids Apolipoprotein A-I Gastrin
193 Y Y  
194   Y Y
195 Y Y Y
196   Y Y
197 Y Y  

To get from here to there, you need to visualize how you want to arrange the data elements. If you use the color coding I assigned to the array indexes above, you can picture the data in rows, like this:

0,0    1,0    2,0    3,0

0,1    1,1    2,1    3,1

etc.

To generate a display of the data in this manner, you need to loop through the arrays in an inside-out manner. You loop through the subarrays to set the rows, and then have a nested loop through the parent array to set the cells. Here’s the PHP code for it:


$content = "<table>\n";

// This loop controls the table rows
// $cols is the name of the parent array
for ($inner=0; $inner < count($cols[0]); $inner++) {
    $content .= "<tr>";

    // This loop generates the table cells
    for ($outer=0; $outer < count($cols); $outer++) {
        // this assumes you want the first row to be a header row
        $tag = ($inner == 0) ? "th" : "td";
        $content .= "<$tag>{$cols[$outer][$inner]}</$tag>";
    }

    $content .= "</tr>\n";
}

$content .= "</table>\n";

// then display or return $content...

The first subarray contains the Sample IDs, so I used it to set the maximum count for the outer loop that controls the HTML table rows (because I can be confident there will never be data beyond the last sample). If you don’t have an analogous subarray, you’ll need to check to see which subarray is longest, and use that to control the count.

4

Mar

Generating HTML Tables with a Variable Number of Columns and Rows

Topic: WordPress and Web Programming
Tags: ,

Often when you’re generating an HTML table on the fly, you need to be able to display an arbitrary number of columns and rows. This typically comes up when displaying data from a database, where you can get any number of records (rows) back. Fortunately handling a variable number of rows is easy in HTML, since all you have to do is keep adding table row tags until you run out of records. The harder, and less common, case is handling a variable number of columns. An example of where this situation comes up is my Shashin plugin, as Shashin users can decide how many columns they want in the display of their photos. Another example is a form where you need multiple rows and columns for neatly laying out a variable number of checkboxes.

I’ve seen a number of strange and tortured solutions to this problem over the years, so I thought I’d share my solution, which is really simple (I’m sure many others have figured this out as well, but I haven’t seen it posted anywhere). What’s often missing in other solutions I’ve seen is properly closing the final table row when the number of cells in it is less than the preceding rows. Here’s some generic PHP code for it:

// desired number of columns - this can be any number
$cols = 3;

$output = "<table>\n";

$cell_count = 1;

for ($i = 0; $i < count($your_array); $i++) {
    if ($cell_count == 1) {
        $output .= "<tr>\n";
    }

    $output .= "<td>your cell content</td>\n";
    $cell_count++;

    // end the row if we've generated the expected number of columns
    // or if we're at the end of the array
    if ($cell_count > $cols || $i == (count($your_array) - 1)) {
        $output .= "</tr>\n";
        $cell_count = 1;
    }
}

$output .= "</table>\n";

And just for fun here’s the same thing in Smarty:

<table>
<{assign var="cell_count" value=1}>
<{foreach key=key item=item from=$your_array name=yourloop}>
    <{if $cell_count == 1}>
        <tr>
    <{/if}>
    <td>your cell content</td>
    <{math assign="cell_count" equation="$cell_count + 1"}>

    <{if $cell_count > 3 || $smarty.foreach.yourloop.last}>
        </tr>
        <{assign var="cell_count" value=1}>
    <{/if}>
<{/foreach}>
</table>

23

Feb

CSS and the Limits of Definition Lists

Topic: WordPress and Web Programming
Tags: ,

I’ve become a fan of definition lists as a layout tool. Here’s a snippet of HTML, using them to markup a form. You can make the input element label the definition term (dt) and the input element itself the definition data (dd), like so:

<dl>
<dt><label for="first_name">First Name<label></dt>
<dd><input type="text" name="first_name" id="first_name" size="20" /></dd>
<dt><label for="last_name">Last Name<label></dt>
<dd><input type="text" name="last_name" id="last_name" size="20" /></dd>
etc...
</dl>

What makes this better than using an HTML table is that with CSS you can specify whatever layout you want: you can style it so the dt is above, below, to the right, or to the left of its dd partner. This is particularly helpful when you’re writing re-usable code that might be needed in situations where you can’t predict the layout needs.

But tonight I discovered the limit of this approach, which is when you can’t predict whether the vertical height of the dt’s content will exceed the height of the dd’s. I’ve been working on the next version of Shashin, and what’s been driving the effort is the Boxing Dragons art gallery site, which I just finished working on. I’m using Shashin to display a list of albums (in this case artists) with the description of the album alongside the cover image of the album. For the next release of Shashin, I was originally planning to do this markup with definition lists (with the album cover as the dt and the description as the dd), giving users the flexibility to layout their album and description pairs any way they want, via CSS.

This approach to styling definition lists is fairly tidy, and works fine when the height of the dd is the same or greater than the dt. And in Firefox it also works when the height of the dt is greater, but not so in IE6 (I’ve been resisting upgrading so I haven’t tested with IE7). In IE6 the content of a dd will “flow up” into any available space above it, pushing a dd’s content higher than the position of its dt partner.

The clearfix solution for positioning floating divs doesn’t help here (believe me, I tried). I found several threads of people discussing this problem (or something quite similar to it) but no reliable solutions. The best I found was this admirable effort, but it entails about 70 lines of CSS code as well as some goofy markup. It’s also quite fragile - as soon as I started tweaking things like margins even slightly, it would start to fall apart. Although I probably could have gotten the layout I wanted if I kept at it, the CSS would have been so complex it would have defeated the purpose: to make it fairly easy for Shashin users to alter the stylesheet to get the layout they want.

So, at least for now, I’ve given up on using a definition list and have retreated to using a table. The upside is the markup and the CSS are straightforward and cross-browser compatible. The downside for Shashin is that there’s no flexibility: the album covers have to stay on the left, and the descriptions on the right.