Nielesen: Designing Effective Carousels

I wrote a roundoup of articles explaining why carousels are bad and kill clickthrus earlier. Jakob Nielsen provides some advice on how to design one properly if you really must have one.

Summary: Carousels allow multiple pieces of content to occupy a single, coveted space. This may placate corporate infighting, but on large- or small-view ports, people often scroll past carousels. A static hero or integrating content in the UI may be better solutions. But if a carousel is your hero, good navigation and content can help make it effective.

From: Designing Effective Carousels

Why global variables are bad

This question came up yesterday when Sandy and I presented at DC Web Women, an Introduction to  PHP [slides]. I couldn’t come up with a coherent set of arguments at the time, in a way that I could explain easily. These posts do a better job, first a general programming article on the subject:

Implicit coupling — A program with many global variables often has tight couplings between some of those variables, and couplings between variables and functions. Grouping coupled items into cohesive units usually leads to better programs.

From: Global Variables Are Bad

And a PHP specific article full of excellent examples

You may have heard that globals are bad. This is often thrown around as programming gospel by people who don’t completely understand what they’re saying. These people aren’t wrong, they just don’t often program what they preach. I’ve lost track of the number of times I’ve had the “globals are bad” conversation with someone (and been in agreement) only to find their code is littered with statics and singletons. These people are confusing globals (as in the $GLOBALS array) and global state.

From: Why global state is the devil, and how to avoid using it – TomNomNom.com

Remove unapproved comments from WordPress exports

Recently, I needed to migrate some WordPress blogs to another system. WordPress provides a handy way to export content in its WXR format. However, it’ll export all comments, whether approved or not. This is good from a data backup standpoint, but I didn’t need to import these. They were also bloating the XML file and affecting how long it took my import to process.  I needed a way to remove unapproved comments, the following code will do that using PHP’s DOMDocument extension to walk an input file. The cleaned up content is sent to STDOUT so you can pipe it to another file to save.

<?php
if (!isset($_SERVER['argv'][1])) {
    echo "\nSpecify input file \n";
    exit;
}

$infile = $_SERVER['argv'][1];

$doc = new DOMDocument();
$doc->recover = TRUE;
$doc->load($infile);

$comments = $doc->getElementsByTagName('comment');
$to_remove = array();

foreach ($comments as $comment) {
    if ($approved = $comment->getElementsByTagName('comment_approved')) {
        if ($approved->length > 0) {
            $app = $approved->item(0);

            // can't remove nodes while looping
            if (0 == $app->nodeValue) {
                $to_remove[] = $comment;
            }
        }
    }
}

if (count($to_remove)) {
    foreach ($to_remove as $elt) {
        $elt->parentNode->removeChild($elt);
    }
}

$doc->formatOutput = true;
$doc->preserveWhiteSpace = false;
echo $doc->saveXML();

Carousels are bad for Accessibility

I’ve never been a fan of carousels. They’ve become a crutch for designers and clients who want to spice up a homepage presentation with something that moves. ShoulIUseACarousel was shared by a lot of folks I follow, NetMagazine did an interview with the accessibility expert who created the site.

JS: Carousels are seemingly an easy fix to two universal design problems: how do I fit so much content into so little space, and how do I decide what content is the most important? It’s easy to justify away the usability issues of a carousel when you consider the benefits of presenting multiple content pieces in such little real estate

From: Accessibility expert warns: stop using carousels | News | .net magazine

From an information architecture perspective, Travis Lafleur provides a better alternative. In spirit, it’s very similar to the approach we used on DCUnited.com back when I was there.

Consider this simple, straightforward alternative. First, determine essential content to be featured on the page. Keep in mind the desired outcomes of the project as a whole, the mindset and goals of your users, and what actions you want them to take on the particular page. Next, prioritize. This can be as simple as assigning numbers to each item. If users notice only one thing on the page, what should that be? If they notice two, what should the second be? – and so on. If you’re having trouble prioritizing – or have too many items to promote – consider breaking the content into logical groups and spreading it over multiple pages.

From: Biggs|Gilmore – A Critique of Carousels

It turns out they also don’t lead users to take meaningful actions.

I’m sure you’ve come across dozens, if not hundreds of image sliders or carousels (also called ‘rotating offers’). You might even like them. But the truth is that they’re conversion killers.

From: Don’t Use Automatic Image Sliders or Carousels, Ignore the Fad

Eric Runyon has the stats to back this up, click through to see how many people click beyond the first slide.

Carousels. That gem of a web feature that clients love, and many developers hate. One thing is certain, they are the darling of HigherEd. In fact, they’re loved so much, I’ve been assigned many times to retroactively add them to sites that have already been live for years. This led me ask how much are users really interacting with the carousels.

From: Carousel Interaction Stats | WeedyGarden

Finally, Jack Shepard lists better alternatives to using a carousel slide.

Let me preface this by saying this discovery is not anything new, however unless you’re really geeking out you won’t be in the know on this stuff.

From: The cure for the common image slider carousel

Highest attended soccer matches in the USA

This started as a reply to a reddit poster claiming a USA-Turkey match in 2010 was “the highest attended soccer match ever”

According to this the attendance was 55,407. Nice, but not the highest ever for soccer.
http://www.ussoccer.com/news/mens-national-team/2010/05/turkey-game-report.aspx

But not the larget for soccer that I can find. Portugal played the USA at RFK during the 1996 olympics, attendance was 58,012. 
http://www.dcconvention.com/Venues/RFKStadium/UniqueSpaces.aspx

Also MLS Cup 1997 at RFK featuring home side D.C. United was attended by 57,431 people.
http://en.wikipedia.org/wiki/MLS_Cup_’97

Also, the LA Coliseum would sell out for soccer matches, albeit ones not featuring the USA. Capacity is 92k
http://articles.latimes.com/1999/apr/29/news/mn-32450

Turns out the USSF has a page with attendance records, and the USA-Turkey game, or the others mentioned by me above, would not make it, as the minimum cutoff is around 78,000. Maybe the US turkey game was the best attended USMNT during the previous world cup cycle?
http://www.ussoccer.com/teams/us-men/records/attendance-records/largest-crowds-in-us.aspx

Quick mysqldump snapshot script

I find myself needing this often on different servers, you may find it useful too. This script creates a timestamped dump of a mysql database to the current directory. Assumes it runs as a user who can connect to the database. You can set those credentials using the -u and -p command line switches for mysqldump

#!/bin/bash
# retrieve a database and gzip it

if [ $# -ne 1]
then
  echo "Usage: `basename $0` {database_name}"
  exit $E_BADARGS
fi

DB="$1"

DATEZ=`date +%Y-%m-%d-%H%M`
OUTFILE="$DB.$DATEZ.sql.gz";

echo "mysqldump for $DB to $OUTFILE"
sudo mysqldump --opt -e -C -Q $1 | gzip -c > $OUTFILE

Extract images from an HTML snippet

The function here will take an HTML fragment and return an array of useful images it finds.

<?php
/**
 * extractImages
 *
 * @param $text
 * @return array|bool
 */
function extractImages($text)
{
    $header = '<meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />';
    $text = $header . $text;
    $dom = new DOMDocument();
    if (@$dom-&gt;loadHTML($text)) {
        $xpath = new DOMXpath($dom);
        if ($images = $xpath-&gt;evaluate("//img")) {
            $result = array();
            foreach ($images as $i =&gt; $img) {
                $ht = $img-&gt;getAttribute('height');
                $wd = $img-&gt;getAttribute('width');
                // if height &amp; width are 1 its a bug, ignore
                if (1 === (int)$ht &amp;&amp; 1 === (int)$wd) {
                    continue;
                }
                // if it doesn't end in an image file extension
                // then ignore
                $src = $img-&gt;getAttribute('src');
                if (!preg_match('/.(png|jpg|gif)$/i', $src)) {
                    continue;
                }
                // do we need to figure out the full url to the image?
                if (!preg_match('/^https?:///', $src)) {
                    continue;
                }
                $alt = $img-&gt;getAttribute('alt');
                $result[$i] = array('src' =&gt; $src, 'alt' =&gt; $alt, 'height' =&gt; $ht, 'width' =&gt; $wd);
            }
            if (!empty($result)) {
                return $result;
            }
        }
    }
    return false;
}

Measuring Site Speed localy

This is a cool utility that uses YSlow! and PhantomJS to measure your site’s speed across many pages. Should be good for identifying slow individual pages as well as practices that impact multiple pages.

This is how it works: You feed it with a start URL and how deep you want it to crawl. The pages are fetched and all links within the same domain from that page are analyzed, and a couple of HTML pages are created with the result. Sounds simple?

From: Performance Calendar » Do you sitespeed?

Smelly PHP code

Adam Culp posted the 3rd article in his Clean Development Series this week, Dirty Code (how to spot/smell it). When you read it, you should keep in mind that he is pointing out practices which correlate with poorly written code not prescribing a list of things to avoid. It’s a good list of things to look for and engendered quite a discussion in our internal Musketeers IRC.

Comments are valuable

Using good names for variables, functions, and methods does make your code self commenting, but often times that is not sufficient. Writing good comments is an art, too many comments get in the way, but a lack of comments is just as bad. Code can be dense to parse where a comment will help you out. They also let you quickly scan through a longer code block, just skimming the comments, to find EXACTLY the bit you need to change/desbug/fix/etc. Of course, the latter you can also get by breaking up large blocks of code into functions.

Comments should not explain what the code does, but should capture the “why” of how you are solving a problem. For example, if you’re looping over something a bad comment is “// loop through results”, a good comment is “// loop through results and extract any image tags”

Using Switch Statements

You definitely should not take this item in his list to mean that “Switch statements are evil.” You could have equally bad code if you use a long block of if/then/elseif statements. If you’re using them within a class, you’re better off using polymorphism, as he suggests, or maybe look at coding to an Interface instead of coding around multiple implementations.

Other code smells

In reviewing the article, I thought of other smells that indicate bad code. Some are minor, but if frequent, you know you’re dealing with someone who knows little more than to copy-and-paste code from the Interwebs. These include:

  • Error suppression with @. There are very, very, very few cases where its ok to suppress an error instead of handling the error or preventing it in the first place.
  • Using globals directly. Anything in $_GET, $_POST, $_REQUEST, $_COOKIE should be filtered and validated before you use it. ‘Nuff said
  • Deep class hierarchy. A deep class hierarchy likely means you should be using composition instead of inheritance to change class behaviors.
  • Lack of Prepared DB Statements. Building SQL queries as strings instead of using PDO or the mysqli extensions’ prepared statements can open up sql injection vulnerabilities.
  • Antiquated PHP Practices. A catch all for things we all did nearly a decade ago, includes depending on register globals being on, using “or die()” to catch errors, using the mysql_* functions. PHP has evolved, there’s no reason for you not to evolve with it.

That’s generally what I look for when evaluating code quality. What are some things I missed?