Collected

Home

Create collection

Browse collections

Join Collected


Username


Password


Forgot your password?


myfirst

A collection of:

nothing really   

Visits:

2,304   

View:

 
Add to favorites |

Limiting The Visibility Of WordPress Posts Via Usernames


Smashing Magazine Feed 27 Jan 2012, 2:51 pm CET

  

Controlling who is able to view a post is a simple task once the system is established. Limiting access to certain users has several applications, such as enabling a design studio to distribute artwork to its various clients, or enabling a small school to arrange for homework to be posted online using a cheap and easy solution.

lpvuau-splash1

The easiest method to get this system working is to make the recipients of the information “subscribers” (since they need not be able to post) and the distributors of information “authors” (since they should only be able to edit their own posts). This system eliminates several headaches for the webmaster by managing who has access to particular posts. The username would be used to identify who is allowed to view certain posts, since it is unique and, for the most part, constant.

The Basics

What Will You Need?

  • WordPress 3.1 or later
  • Members of various roles
  • The ability to modify your theme’s files
  • Basic knowledge of PHP and MySQL

What Is a Username?

In general, a username is a means by which to identify and verify a user. It is not the only way to identify a user, but remembering a username is easier for the person logging in than having to remember a random user ID. A username can be made unique to an individual, unlike a person’s name or email address (family members may share the same name, or even the same email address). This ease of use and uniqueness is why usernames are used on most websites that require people to sign up in order to access the website or certain of its features.

To WordPress, a username is means of identifying a user. Paired with a password, a username enables someone to access their profile and, depending on their permissions within WordPress, to access to the administrative pages of the website. A username can be used for many functions in the operation and management of a website, such as karma, prestige, user roles and expulsion.

A WordPress username is unique and impossible for the average user to change. Thus, the system is a potentially reliable means of identifying individuals. This reliability is important for a system in which a post must be visible to only a few people. The permissions of a post should not alter merely because someone has changed their name or email address.

Screenshot of a WordPress single user page The user page in a WordPress installation. Note that “Usernames cannot be changed.”

Setting Up The Back End

In order for an author to be able to set permissions for visibility, a method of selecting users must be set up on the post editing page. We could accomplish this by one of several methods, one of the easiest and most efficient of which is to create a meta box (or widget) in the post editing page that allows the author to add custom information, as required by a theme or plugin. This information enables us to tell the theme which members should have viewing rights to particular posts.

A Basic Custom Meta Box

Justin Tadlock’s article “How to Create Custom Post Meta Boxes in WordPress” explains how to create meta boxes, and we’ll reuse that code here.

Let’s assume we’re dealing with a website for a music school named “Smashing Magazine’s Fancy Flautists.” We will use the name smashing_flautist_access in the code for the back end to distinguish it from other custom functions. Justin’s code is a great starting point for this project, but it needs a little customization for our purpose. Place the following code in your theme’s functions.php, and modify the various labels according to your project.

/* Fire our meta box setup function on the post editor screen. */
add_action( 'load-post.php', 'smashing_post_meta_boxes_setup' );
add_action( 'load-post-new.php', 'smashing_post_meta_boxes_setup' );

/* Meta box setup function. */
function smashing_post_meta_boxes_setup() {

        /* Add meta boxes on the 'add_meta_boxes' hook. */
        add_action( 'add_meta_boxes', 'smashing_add_post_meta_boxes' );

        /* Save post meta on the 'save_post' hook. */
        add_action( 'save_post', 'smashing_flautist_access_save_meta', 10, 2 );
}

/* Create one or more meta boxes to be displayed on the post editor screen. */
function smashing_add_post_meta_boxes() {

        add_meta_box(
                'smashing-flautist-access',                     // Unique ID
                esc_html__( 'Post Viewing Permission', 'smashing_flautist' ),           // Title
                'smashing_flautist_access_meta_box',            // Callback function
                'post',                                 // Admin page (or post type)
                'normal',                                       // Context
                'default'                                       // Priority
        );
}

/* Display the post meta box. */
function smashing_flautist_access_meta_box( $object, $box ) { ?>

        <?php wp_nonce_field( basename( __FILE__ ), 'smashing_flautist_access_nonce' ); ?>

        <p>
                <label for="smashing-flautist-access"><?php _e( "Enter the username of the subscriber that you want to view this content.", 'smashing_flautist' ); ?></label>
                <br />
                <input class="widefat" type="text" name="smashing-flautist-access" id="smashing-flautist-access" value="<?php echo esc_attr( get_post_meta( $object->ID, 'smashing_flautist_access', true ) ); ?>" size="30" />
        </p>
<?php }

With Justin’s code, modified for this project, we should have a custom meta box that looks like this:

Screenshot of a basic meta box A basic meta box positioned below the post editing box.

Adding Ease to the Selection

This box can be used as is, and the author would simply input the members who they want to allow to view a post. This would work well if each author had very few usernames to remember; but if the author has long list of usernames to choose from, then a list of members would have to be displayed, and there would have to be a system that allows the authors to choose members from the list. Add the following code to the area just below the original box, just after the closing paragraph tag, to display a list of users with their names, along with radio buttons to grant one of the users access to the current post.

<table class="smashing-flautist-access">
<tr align="left">
<th>Username</th>
<th>    </th>
<th>Visiblity</th>
<th>    </th>
<th>Name</th>
</tr>
<?php
global $post;
        $users = get_users('role=subscriber');
        foreach ($users as $user) {
                        $user_info = get_userdata( $user->ID );
                        if(get_post_meta( $object->ID, 'smashing_flautist_access', true ) == $user->user_login) $ifchecked = 'checked="checked" ';
                        echo "<tr>";
                        echo "<td>$user->user_login</td><td>    </td>";
                        echo "<td align="center"><input type="radio" name="smashing-flautist-access" id="smashing-flautist-access" value="$user->user_login" " . $ifchecked ."/></td><td>    </td>";
                        echo "<td>$user_info->last_name, $user_info->first_name</td><td>    </td>";
                        echo "</tr>";
                        unset($ifchecked);

        } ?></table>

If everything goes well, you should end up with a box underneath the post editor that looks similar to the image below. The form containing the radio buttons gets a list of users that are listed as subscribers and makes the selection of the student with viewing permissions easy, all without the post’s author having to remember any usernames.

Screenshot of a meta box with user information A meta box that contains a method to select the particular name and information of each user.

Saving the List

Now that we have generated a list that makes it easy for the authors to pick which members they want to be able to view particular posts, we have to create a system to add the list to WordPress’ MySQL database so that we can retrieve it later. We also need a way to tell WordPress to update this list of usernames in case the author decides later to add or remove someone from a particular post’s list of authorized viewers. The code provided by Justin does excellent work; place his code below in your theme’s functions.php, just after the function that sets up the custom meta box.

/* Save post meta on the 'save_post' hook. */
add_action( 'save_post', 'smashing_flautist_access_save_meta', 10, 2 );

/* Save the meta box's post metadata. */
function smashing_flautist_access_save_meta( $post_id, $post ) {

        /* Make all $wpdb references within this function refer to this variable */
        global $wpdb;

        /* Verify the nonce before proceeding. */
        if ( !isset( $_POST['smashing_flautist_access_nonce'] ) || !wp_verify_nonce( $_POST['smashing_flautist_access_nonce'], basename( __FILE__ ) ) )
                return $post_id;

        /* Get the post type object. */
        $post_type = get_post_type_object( $post->post_type );

        /* Check if the current user has permission to edit the post. */
        if ( !current_user_can( $post_type->cap->edit_post, $post_id ) )
                return $post_id;

        /* Get the posted data and sanitize it for use as an HTML class. */
        $new_meta_value = ( isset( $_POST['smashing-flautist-access'] ) ? sanitize_html_class( $_POST['smashing-flautist-access'] ) : '' );

        /* Get the meta key. */
        $meta_key = 'smashing_flautist_access';

        /* Get the meta value of the custom field key. */
        $meta_value = get_post_meta( $post_id, $meta_key, true );

        /* If a new meta value was added and there was no previous value, add it. */
        if ( $new_meta_value && '' == $meta_value )
                {
                add_post_meta( $post_id, $meta_key, $new_meta_value, true );
                $wpdb->query($wpdb->prepare("UPDATE $wpdb->posts SET post_status = 'private' WHERE ID = ".$post_id." AND post_type ='post'"));
                }
        /* If the new meta value does not match the old value, update it. */
        elseif ( $new_meta_value && $new_meta_value != $meta_value )
                {
                update_post_meta( $post_id, $meta_key, $new_meta_value );
                $wpdb->query($wpdb->prepare("UPDATE $wpdb->posts SET post_status = 'private' WHERE ID = ".$post_id." AND post_type ='post'"));
                }
        /* If there is no new meta value but an old value exists, delete it. */
        elseif ( '' == $new_meta_value && $meta_value )
                {
                delete_post_meta( $post_id, $meta_key, $meta_value );
                $wpdb->query($wpdb->prepare("UPDATE $wpdb->posts SET post_status = 'public' WHERE ID = ".$post_id." AND post_type ='post'"));
                }
}

The three MySQL queries are in place to prevent unauthorized users from viewing protected posts and to hide the posts from the RSS feeds. The first query runs only when new data populates the previously empty custom field, while the second query runs only when the data in the custom field has changed. The third query runs only if the custom field is emptied, and it sets the post’s visibility back to “Public.” All three are protected from SQL injection attacks by using $wpdb->prepare() to validate the data entered into the username form field.

If you don’t like that WordPress precedes the post’s title with the word “Private,” then add the following code to your theme’s functions.php file. This custom function is called when your theme would display a post’s title; it finds any instance of the words “Protected” or “Private” at the beginning of the title and removes them. In the core of WordPress’ programming, the function get_the_title() adds those words if a post’s visibility is restricted and the person viewing is not an administrator. What the following code does is send a message to the action that get_the_title() hooks into, telling it to remove the terms “Protected: ” and “Private: ” from the title. So, you can set a post’s title to begin with either term, and the title will not be altered; this code only affects WordPress’ ability to add to your title.

function smashing_title_trim($title) {
        $title = attribute_escape($title);
        $needles = array(__('Protected: '),__('Private: '));
        $title = str_replace($needles,'',$title);
        return $title;
}
add_filter('protected_title_format','smashing_title_trim');
add_filter('private_title_format','smashing_title_trim');

To allow users at the subscriber level to see private posts, you have to give them that capability. As it happens, some of the code we’ll be using later frees us from having to worry about users at the subscriber level seeing the posts of others.

$subRole = get_role( 'subscriber' );
$subRole->add_cap( 'read_private_posts' );

You can also grant users at the subscriber level permission to view private pages, in case you want a dedicated page of information that subscribers should know.

$subRole->add_cap( 'read_private_pages' );

Setting Up The Front End

Now that we have a way to add members to the list of people who can view a particular post, we have to modify our theme to use this data, and to actually control the visibility of each post based on this list. First, we need a way to get the username of the person who can view a post. Secondly, we would compare the username of the member with viewing permissions to the user who is currently logged in. Finally, we would make the theme display either the post in the loop or an error message (or perhaps nothing at all).

Place this code just after The Loop starts. It goes in single.php, category.php and index.php if you will be displaying posts on the home page.

<?php
/* Get the post's acceptable viewer. */
                $flautist_access = get_post_meta($post->ID, 'smashing_flautist_access', true );
/* Get the post's current viewer, if he or she is logged in. */
                if(is_user_logged_in()) {$current_flautist = $current_user->user_login;}
/* See if the acceptable viewer and the current viewer are the same */
                if($flautist_access == $current_flautist || current_user_can('author') || current_user_can('editor') || current_user_can('administrator'))
                        {echo ''; ?>

Place this code just before the loop ends. Here is where you can show an error message telling the user that they may not view this post. Or you could leave this code as is to make it appear as though the current visitor is not missing anything.

<?php } else { echo ''; } ?>

This is what a hidden post looks like to the public or to a user who is not logged in. They would see what appears to be an error message and are redirected away from the post.

What the public sees when trying to view a protected post If a person is not logged in and tries to view a restricted post, they would get an error message.

What an unauthorized user sees when trying to view a protected post If a user is logged in but not allowed to view a restricted post, they would see either nothing or an error message specific to members.

What an authorized user sees when trying to view a protected post If a member is logged in and authorized to view a protected post, then they would see the post itself.

Conclusion

Being able to control who can view individual posts is a useful feature with a wide variety of applications. Third-party software can natively do this, but WordPress is widely supported and documented, which means that any security holes that might allow unauthorized users to view restricted posts would be shut in a future update. Plus, it allows you to run an actual blog next to posts with limited visibility. This system could be used by administrators to distribute personalized content, by professionals to send files to clients, or by bloggers to restrict the visibility of certain posts to certain members.

Enabling an author to control who can view their posts can help them tailor the blog’s content to the needs or tastes of certain users. Ultimately, you will have to factor in the purpose and content of your website when deciding whether to use this method. It’s not for everyone, but it suit the needs of owners of small websites who want to deliver certain content to certain people.

Resources

(al)


© Chris Ellison for Smashing Magazine, 2012.

ShopTalk Episode 3


CSS-Tricks 27 Jan 2012, 5:27 am CET

Where Dave and I are joined by Chris Eppstein. Sponsored by LessAccounting and United Pixelworkers (who are offering a 10% discount on shirts with coupon code "shoptalk").

Direct Link to ArticlePermalink

ShopTalk Episode 3 is a post from CSS-Tricks

24 Extremely Useful Ruby Gems for Web Development


Nettuts+ 26 Jan 2012, 10:38 pm CET

One of the nicer things about developing on the Ruby platform is the sheer amount of meticulously categorized, highly reusable code wrapped up as aptly named ‘gems’.

I’m sure you’ve heard of popular frameworks like Sinatra or the super popular Rails but you’re missing an entire spectrum of gems that handle issues at a much lower level. Start using these and watch your productivity shoot through the roof!


A Quick Note

I’m well aware that some of the gems listed here have Rails, or parts of Rails, as a dependency. That doesn’t mean that they are any less useful or need to be sneered at.


CarrierWave

Upload files in your Ruby applications, map them to a range of ORMs, store them on different backends. It works well with Rack based web applications, such as Ruby on Rails.

Related reading


Kaminari

Kaminari is a Scope & Engine based, clean, powerful, customizable and sophisticated paginator. Kaminari supports multiple ORMs (ActiveRecord, Mongoid, MongoMapper) multiple web frameworks (Rails, Sinatra), and multiple template engines (ERB, Haml).

Related reading


HAML

Haml (HTML Abstraction Markup Language) is a layer on top of XHTML or XML that’s designed to express the structure of XHTML or XML documents in a non-repetitive, elegant, easy way, using indentation rather than closing tags and allowing Ruby to be embedded with ease. It was originally envisioned as a plugin for Ruby on Rails, but it can function as a stand-alone templating engine.

Related reading


Authlogic

A simple, unobtrusive model based Ruby authentication solution. Authlogic is very flexible, it has a strong public API and a plethora of hooks to allow you to modify behavior and extend it.

Related reading


Shoulda

Shoulda is a gem that allows you to create more understandable tests for your Ruby application. Shoulda allows you to provide context to your tests enabling you to categorize tests according to a specific feature or scenario you’re testing.

Related reading


factory_girl

factory_girl provides a framework and DSL for defining and using factories – less error-prone, more explicit, and all-around easier to work with than fixtures. It has straightforward definition syntax, support for multiple build strategies (saved instances, unsaved instances, attribute hashes, and stubbed objects), and support for multiple factories for the same class (user, admin_user, and so on), including factory inheritance.

Related reading


RMagick

RMagick is an interface between the Ruby programming language and the ImageMagick and GraphicsMagick image processing libraries.

Related reading


Cancan

CanCan is an authorization library for Ruby on Rails which restricts what resources a given user is allowed to access and is decoupled from user roles. All permissions are stored in a single location and not duplicated across controllers, views, and database queries.

Related reading


Nokogiri

Nokogiri is an HTML, XML, SAX, and Reader parser. Among Nokogiri’s many features is the ability to search documents via XPath or CSS3 selectors. Nokogiri parses and searches XML/HTML very quickly, and also has correctly implemented CSS3 selector support as well as XPath support.

Related reading


SASS

Sass makes CSS fun again. Sass is an extension of CSS3, adding nested rules, variables, mixins, selector inheritance, and more. It’s translated to well-formatted, standard CSS using the command line tool or a web-framework plugin.

Related reading


Formtastic

Formtastic is a Rails FormBuilder DSL (with some other goodies) to make it far easier to create beautiful, semantically rich, syntactically awesome, readily stylable and wonderfully accessible HTML forms in your Rails applications.

Related reading


Capistrano

Capistrano is a utility and framework for executing commands in parallel on multiple remote machines, via SSH. It uses a simple DSL (borrowed in part from Rake) that allows you to define tasks, which may be applied to machines in certain roles. It also supports tunneling connections via some gateway machine to allow operations to be performed behind VPN’s and firewalls.

Related reading


Omniauth

OmniAuth is a Ruby authentication framework that provides a standardized interface to many different authentication providers such as Facebook, OpenID, and even traditional username and password.

Related reading


Bundler

Bundler is a tool that manages gem dependencies for your ruby application. It takes a gem manifest file and is able to fetch, download, and install the gems and all child dependencies specified in this manifest. It can manage any update to the gem manifest file and update the bundle’s gems accordingly. It also lets you run any ruby code in context of the bundle’s gem environment.

Related reading


resque

Resque (pronounced like “rescue”) is a Redis-backed library for creating background jobs, placing those jobs on multiple queues, and processing them later. Resque is heavily inspired by DelayedJob.

Related reading


Jammit

Jammit is an industrial strength asset packaging library for Rails, providing both the CSS and JavaScript concatenation and compression that you’d expect, as well as YUI Compressor and Closure Compiler compatibility, ahead-of-time gzipping, built-in JavaScript template support, and optional Data-URI / MHTML image embedding.

Related reading


capybara

Capybara helps you test Rails and Rack applications by simulating how a real user would interact with your app. It is agnostic about the driver running your tests and comes with Rack::Test and Selenium support built in.

Related reading


Active Merchant

Active Merchant is an extraction from the e-commerce system Shopify. Shopify’s requirements for a simple and unified API to access dozens of different payment gateways with very different internal APIs was the chief principle in designing the library. It was developed for usage in Ruby on Rails web applications and integrates seamlessly as a plugin but it also works excellently as a stand alone library.

Related reading


eventmachine

EventMachine implements a fast, single-threaded engine for arbitrary networkcommunications. It’s extremely easy to use in Ruby. EventMachine wraps all interactions with IP sockets, allowing programs to concentrate on the implementation of network protocols. It can be used to create both network servers and clients.

Related reading


mustache

Inspired by ctemplate, Mustache is a framework-agnostic way to renderlogic-free views.As ctemplates says, “It emphasizes separating logic from presentation:it is impossible to embed application logic in this templatelanguage.

Related reading


Passenger

Phusion Passenger™ — a.k.a. mod_rails or mod_rack — makes deployment of Ruby web applications, such as those built on the revolutionary Ruby on Rails web framework, a breeze.

Related reading


Chef

Chef is a system integration framework designed to bring the benefits of configuration management to your entire infrastructure. With Chef, you can manage your servers by writing code, not by running commands.

Related reading


Thinking Sphinx

A concise and easy-to-use Ruby library that connects ActiveRecord to the Sphinx search daemon, managing configuration, indexing and searching.

Related reading


Wrapping Up

So those were some of the awesome gems I’ve found extremely useful when I’m whipping up a web app in Ruby. I’m a 100% sure I’m missing a metric butt load of others though. Let me know about your favorite gems in the comments below and thank you so much for reading!

Animate to an Inline Style


CSS-Tricks 26 Jan 2012, 9:18 pm CET

You already know that inline styles are "bad practice." Inline styles aren't reusable like CSS in separate files is, and thus, inefficient bloat. Unless of course, when it isn't. There are some instances where inline styles make perfect sense. Perhaps you have an application where user's pick their favorite color, and then you set the background of the body to that. Using an inline style in that case is actually more efficient than external CSS, since it's specific to one user and one element.

Now let's say you want to animate to a value set in an inline style. Say you want to animate a progress bar. You start at zero, and need to go up to any arbitrary value. Perhaps a call to the server tells you how complete an upload is and you set the value from that.

In a post I did nearly a year ago, I lamented that you can't animate to an inline style. You can't declare a keyframe in inline styles and you don't know what final value to animate to in the external CSS. Alas I was wrong, as I didn't know about this bonafide little CSS trick.

<div class="progress-bar">
  <div style="width: 75%">Upload is 75% complete.</div>
</div>

Here's the trick: just omit the to or 100% declaration from the @keyframe:

@-webkit-keyframes progress-bar {
   0% { width: 0; }
}
@-moz-keyframes progress-bar {
   0% { width: 0; }
}

Then you call the animation on the progress bar:

.progress-bar > div {
  -webkit-animation: progress-bar 2s;
  -moz-animation: progress-bar 2s;
}

And just like that, the progress bar will animate itself up to the value set by the inline style.

View Demo

Here's a Dabblet if you wanna mess with it.

Special thanks to Michael Paryna who emailed me about this and got me to give it a try.

Animate to an Inline Style is a post from CSS-Tricks

The UX Research Plan That Stakeholders Love


Smashing Magazine Feed 26 Jan 2012, 4:35 pm CET

  

UX practitioners, both consultants and in house, sometimes conduct research. Be it usability testing or user research with a generative goal, research requires planning. To make sure product managers, developers, marketers and executives (let’s call them stakeholders) act on UX research results, planning must be crystal clear, collaborative, fast and digestible. Long plans or no plans don’t work for people. You must be able to boil a UX research plan down to one page. If you can’t or won’t, then you won’t get buy-in for the research and its results.

This article addresses one key aspect of planning UX research: the one-page plan document. Before we get to that, we’ll briefly discuss the benefits of research planning and identify the audience of a research planning document.

Blueprint Heart (Image: Patrick Hoesly)

A word about stakeholders. A stakeholder in the UX world is a code name for the people who UX practitioners work with. These are our clients, whether internal or external to our organization. These are people who need to believe in what we do, act on research results, and fund and sponsor future research. We all have a stake in product development. They have a stake in UX research.

The Benefits Of Research Planning

Very generally speaking, UX research can answer two types of questions:

  1. What’s useful? What do people need? Who is the target audience?
  2. What’s usable? Does the design work for people, and how it can be improved?

Dozens of research methodologies could be implemented to answer these and more specific questions, and it is up to designers, researchers and their teams to decide what works best for them and when is the right time to answer their questions.

Here are the benefits of planning UX research:

  • Get a better feel of stakeholders. A written plan helps you identify what works and doesn’t work for people, and what questions they are trying to answer.
  • Engage stakeholders. A study plan ensures they are properly involved with the study and its results. If there’s no written plan, then there’s a greater chance that stakeholders won’t feel engaged.
  • Writing things down helps you. When you put things in writing, they look very different than how you imagined them when they were just thoughts in your head. Always have a written study plan, even if you don’t share it with anyone else.

Now, let’s quickly identify the target audience for the research planning document.

Who Are You Planning For? Who Are The Stakeholders?

As with every product or service, the best offering comes from carefully identifying the target audience, their needs and their wants. Different UX research stakeholders are interested in different aspects of a research plan:

  • Product managers and software engineers are mostly interested in the study’s goal, research questions and schedule. In some cases, they are also interested in the criteria for participants. These stakeholders are usually interested in goals and questions because these determine the content of the study and its focus. They are interested in the schedule to make sure it enables them to make timely design, business and development decisions. Criteria for participants interest them when the product targets a very specific demographic and they want to make sure participants are representative of that demographic.
  • Managers and executives are probably interested in the study’s goal and the overall cost of the study, because they are likely sponsoring the study. Usually, their bandwidth does not allow them more than that.
  • You! The plan is mostly for you. As soon as you put your thoughts in writing, something happens, and you find holes in them. These holes help you improve the plan. A written plan also helps you focus and better prepare for the study. The fact of the matter is that if you can’t boil your plan down to a page, you probably don’t really understand it.

Now that we’ve discussed why a planning document is important and who it is for, let’s get to the nitty gritty of the document.

The Plan That Stakeholders Love: The One-Pager

The users of a research plan love brevity and appreciate succinct definitions of what will happen, why, when and with whom. Here are the sections that go in a one-page research plan:

  • Title The title should combine the thing you’re studying and the methodology; for example, “Monster.com field study” or “XYZ Phone data-entry usability test.” Sometimes mentioning the target audience of the study is also appropriate; for example, “Whitehouse.com news page interviews with senior citizens.”
  • Author and stakeholders State your full name, title and email address on one line. After you get the stakeholders’ buy-in for the plan, add their details as well — the research belongs to everyone now.
  • Date Update it whenever the plan is updated.
  • Background Describe what led to this study. Discuss the recent history of the project. Be brief, no more than five lines.
  • Goals Briefly state the high-level reason (or reasons) for conducting this study. Try to phrase it in one sentence. If that wouldn’t make sense, create a numbered list of very short goal statements. If you have more than three to four goals, you are either aiming too high (meaning you have too many goals) or repeating yourself.
  • Research questions These are the specifics, the core of your plan. Provide a numbered list of questions that you plan to answer during the study. It is extremely important that your stakeholders understand that you will not necessarily be asking the study participants these questions. As a rule of thumb, have no more than seven to ten questions, preferably around five. Later on, you will construct your study script to answer these questions. An effective way to think about research questions is to imagine that they are the headings in the study’s summary.
  • Methodology In an academic environment, this section has one primary goal: to provide as many details as other researchers need in order to repeat the exact same study. In practice, the goal of the methodology section is to briefly inform the stakeholders of what will happen, for how long and where.
  • Participants Provide a list of the primary characteristics of the people you will be recruiting to participate in the study. Have a good reason for each and every characteristic. If you have two participant groups, describe both groups’ characteristics in lists or in a table. Append a draft form that you’ll use to screen participants.
  • Schedule Inform stakeholders of at least three important dates: when recruiting starts, when the study will take place, and when they can expect results. Large research projects require more scheduling details. For example, if the study involves travel to another city or country, more dates might be required for on-site preparation and meetings or for analysis workshops.
  • Script placeholder When a full study script is ready, it will appear under this title. Until then, all you need is a heading with a “TBD” indication.

A Sample UX Research Plan

XYZ Phone Data-Entry Usability Test

By John Smith-Kline, Usability Researcher, jskline@example.com

Stakeholders: Wanda Verdi (PM), Sam Crouch (Lead Engineer)

Last updated: 13 January 2012

Background Since January 2009, when the XYZ Phone was introduced to the world, particularly after its market release, journalists, bloggers, industry experts, other stakeholders and customers have privately and publicly expressed negative opinions about the XYZ Phone’s keyboard. These views suggest that the keyboard is hard to use and that it imposes a poor experience on customers. Some have claimed this as the main reason why the XYZ Phone will not succeed among business users. Over the years, several improvements have been made to data entry (such as using horizontal keyboards for most features), to no avail.

Goals Identify the strengths and weaknesses of data entry on the XYZ Phone, and provide opportunities for improvement.

Research questions

  1. How do people enter data on the XYZ Phone?
  2. What is the learning curve of new XYZ Phone users when they enter data?
  3. What are the most common errors users make when entering data?

Methodology A usability study will be held in our lab with 20 participants. Each participant session will last 60 minutes and will include a short briefing, an interview, a task performance with an XYZ Phone and a debriefing. Among the tasks: enter an email subject heading, compose a long email, check news updates on CNN’s website, create a calendar event and more.

Participants These are the primary characteristics of the study’s participants:

  • Business user,
  • Age 22 to 55,
  • Never used an XYZ Phone,
  • Expressed interest in learning more about or purchasing an XYZ Phone,
  • Uses the Web at least 10 hours a week.

[Link to a draft screener]

Schedule

  • Recruiting: begins on November 12
  • Study day: November 22
  • Results delivery: December 2

Script TBD

Recap

A short plan that you and your stakeholders prepare together is key to a successful start of a UX research project.

  • Boil down your collective knowledge, agreements and understanding of what will happen, why, with whom and when.
  • Set the right expectations among stakeholders.
  • Try to keep the plan to one page.
  • Secure buy-in for the UX research by making it a team effort.
  • The core of the plan is the list of questions you are trying to answer. Choose the right ones.

Happy planning!

(al) (fi) (il)


© Tomer Sharon for Smashing Magazine, 2012.

Custom Fonts in Emails


CSS-Tricks 25 Jan 2012, 6:45 pm CET

A reader writes in:

Would it be possible to draw an entire typeface in CSS to be sent in emails? Our company needs to send out emails to about 20k people to introduce a new brand that we are launching. The emails will be in HTML/CSS. My CEO is very specific about the type of aesthetic he wants to achieve, and this includes using a typeface that is not native to either Mac or Windows computers. We do not want to use images in our email.

First off, it's pretty cool your CEO cares about type and aesthetics at all. It's usually a good thing to have the person steering the ship care about beauty and details down to that level. Let's consider the options.

The first thing that comes to mind in custom fonts these days is @font-face. The browser support for it is pretty darn good. Unfortunately, browser support isn't what we need here, it's email client support. According to some research by Campaign Monitor, @font-face is only working Apple's Mail.app and the Mail app on iOS. You could try to make the progressive enhancement case to your CEO, but at that low level of support might be a tough sell.

Another thing you mentioned was trying to recreate the font through CSS somehow. Maybe something like this. I've even played around with this concept a little bit specifically with the idea of image-free emails in mind. This is the realm of big-pixel-art though. Recreating a font pixel by pixel with no anti-aliasing, as you are surely aware, is a fool's errand.

In reality I think there are two solutions.

The first is to reconsider this sentence: "We do not want to use images in our email." Why not? It seems like you are OK with sending HTML emails since you're specifically looking for clever solutions and text emails are capable of very little cleverness short of ASCII art. People use images in emails all the time. Admittedly, the fact users often have to specifically choose to view them is a bit of a turn off, but using proper ALT text on the images makes the email still work even if they never do that.

The second is to give up on this custom font in email thing. Not to sound defeatist here, but your branding will not be ruined by the lack of a specific typeface in an email. Anywhere where you all agree it is critical (e.g. a slogan?), use an image, otherwise, use a nice readable font that works OK in pairing with your brand typeface and move on with more important tasks.

Personally, I think I'd go with @font-face despite the current low support. Actively developing what you want to work helps build the desire momentum needed to get product vendors (in this case email clients) to improve their products and give us better CSS support.

Custom Fonts in Emails is a post from CSS-Tricks

Why you Should be using PHP’s PDO for Database Access


Nettuts+ 25 Jan 2012, 5:04 pm CET

Many PHP programmers learned how to access databases by using either the MySQL or MySQLi extensions. As of PHP 5.1, there’s a better way. PHP Data Objects (PDO) provide methods for prepared statements and working with objects that will make you far more productive!

May of 2010

PDO Introduction

“PDO – PHP Data Objects – is a database access layer providing a uniform method of access to multiple databases.”

It doesn’t account for database-specific syntax, but can allow for the process of switching databases and platforms to be fairly painless, simply by switching the connection string in many instances.

PDO - db abstraction layer

This tutorial isn’t meant to be a complete how-to on SQL. It’s written primarily for people currently using the mysql or mysqli extension to help them make the jump to the more portable and powerful PDO.

Database Support

The extension can support any database that a PDO driver has been written for. At the time of this writing, the following database drivers are available:

  • PDO_DBLIB ( FreeTDS / Microsoft SQL Server / Sybase )
  • PDO_FIREBIRD ( Firebird/Interbase 6 )
  • PDO_IBM ( IBM DB2 )
  • PDO_INFORMIX ( IBM Informix Dynamic Server )
  • PDO_MYSQL ( MySQL 3.x/4.x/5.x )
  • PDO_OCI ( Oracle Call Interface )
  • PDO_ODBC ( ODBC v3 (IBM DB2, unixODBC and win32 ODBC) )
  • PDO_PGSQL ( PostgreSQL )
  • PDO_SQLITE ( SQLite 3 and SQLite 2 )
  • PDO_4D ( 4D )

All of these drivers are not necessarily available on your system; here’s a quick way to find out which drivers you have:

print_r(PDO::getAvailableDrivers());

Connecting

Different databases may have slightly different connection methods. Below, the method to connect to some of the most popular databases are shown. You’ll notice that the first three are identical, other then the database type – and then SQLite has its own syntax.

Connection String
try {
  # MS SQL Server and Sybase with PDO_DBLIB
  $DBH = new PDO("mssql:host=$host;dbname=$dbname, $user, $pass");
  $DBH = new PDO("sybase:host=$host;dbname=$dbname, $user, $pass");

  # MySQL with PDO_MYSQL
  $DBH = new PDO("mysql:host=$host;dbname=$dbname", $user, $pass);

  # SQLite Database
  $DBH = new PDO("sqlite:my/database/path/database.db");
}
catch(PDOException $e) {
    echo $e->getMessage();
}

Please take note of the try/catch block – you should always wrap your PDO operations in a try/catch, and use the exception mechanism – more on this shortly. Typically you’re only going to make a single connection – there are several listed to show you the syntax. $DBH stands for ‘database handle’ and will be used throughout this tutorial.

You can close any connection by setting the handle to null.

# close the connection
$DBH = null;

You can get more information on database specific options and/or connection strings for other databases from PHP.net.


Exceptions and PDO

PDO can use exceptions to handle errors, which means anything you do with PDO should be wrapped in a try/catch block. You can force PDO into one of three error modes by setting the error mode attribute on your newly created database handle. Here’s the syntax:

$DBH->setAttribute( PDO::ATTR_ERRMODE, PDO::ERRMODE_SILENT );
$DBH->setAttribute( PDO::ATTR_ERRMODE, PDO::ERRMODE_WARNING );
$DBH->setAttribute( PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION );

No matter what error mode you set, an error connecting will always produce an exception, and creating a connection should always be contained in a try/catch block.

PDO::ERRMODE_SILENT

This is the default error mode. If you leave it in this mode, you’ll have to check for errors in the way you’re probably used to if you used the mysql or mysqli extensions. The other two methods are more ideal for DRY programming.

PDO::ERRMODE_WARNING

This mode will issue a standard PHP warning, and allow the program to continue execution. It’s useful for debugging.

PDO::ERRMODE_EXCEPTION

This is the mode you should want in most situations. It fires an exception, allowing you to handle errors gracefully and hide data that might help someone exploit your system. Here’s an example of taking advantage of exceptions:

# connect to the database
try {
  $DBH = new PDO("mysql:host=$host;dbname=$dbname", $user, $pass);
  $DBH->setAttribute( PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION );

  # UH-OH! Typed DELECT instead of SELECT!
  $DBH->prepare('DELECT name FROM people');
}
catch(PDOException $e) {
    echo "I'm sorry, Dave. I'm afraid I can't do that.";
    file_put_contents('PDOErrors.txt', $e->getMessage(), FILE_APPEND);
}

There’s an intentional error in the select statement; this will cause an exception. The exception sends the details of the error to a log file, and displays a friendly (or not so friendly) message to the user.


Insert and Update

Inserting new data, or updating existing data is one of the more common database operations. Using PDO, this is normally a two-step process. Everything covered in this section applies equally to both UPDATE and INSERT operations.

2 to 3 step insert and update

Here’s an example of the most basic type of insert:

# STH means "Statement Handle"
$STH = $DBH->prepare("INSERT INTO folks ( first_name ) values ( 'Cathy' )");
$STH->execute();

You could also accomplish the same operation by using the exec() method, with one less call. In most situations, you’re going to use the longer method so you can take advantage of prepared statements. Even if you’re only going to use it once, using prepared statements will help protect you from SQL injection attacks.

Prepared Statements

Using prepared statements will help protect you from SQL injection.

A prepared statement is a precompiled SQL statement that can be executed multiple times by sending just the data to the server. It has the added advantage of automatically making the data used in the placeholders safe from SQL injection attacks.

You use a prepared statement by including placeholders in your SQL. Here’s three examples: one without placeholders, one with unnamed placeholders, and one with named placeholders.

# no placeholders - ripe for SQL Injection!
$STH = $DBH->("INSERT INTO folks (name, addr, city) values ($name, $addr, $city)");

# unnamed placeholders
$STH = $DBH->("INSERT INTO folks (name, addr, city) values (?, ?, ?);

# named placeholders
$STH = $DBH->("INSERT INTO folks (name, addr, city) value (:name, :addr, :city)");

You want to avoid the first method; it’s here for comparison. The choice of using named or unnamed placeholders will affect how you set data for those statements.

Unnamed Placeholders

# assign variables to each place holder, indexed 1-3
$STH->bindParam(1, $name);
$STH->bindParam(2, $addr);
$STH->bindParam(3, $city);

# insert one row
$name = "Daniel"
$addr = "1 Wicked Way";
$city = "Arlington Heights";
$STH->execute();

# insert another row with different values
$name = "Steve"
$addr = "5 Circle Drive";
$city = "Schaumburg";
$STH->execute();

There are two steps here. First, we assign variables to the various placeholders (lines 2-4). Then, we assign values to those placeholders and execute the statement. To send another set of data, just change the values of those variables and execute the statement again.

Does this seem a bit unwieldy for statements with a lot of parameters? It is. However, if your data is stored in an array, there’s an easy shortcut:

# the data we want to insert
$data = array('Cathy', '9 Dark and Twisty Road', 'Cardiff');

$STH = $DBH->("INSERT INTO folks (name, addr, city) values (?, ?, ?);
$STH->execute($data);

That’s easy!

The data in the array applies to the placeholders in order. $data[0] goes into the first placeholder, $data[1] the second, etc. However, if your array indexes are not in order, this won’t work properly, and you’ll need to re-index the array.

Named Placeholders

You could probably guess the syntax, but here’s an example:

# the first argument is the named placeholder name - notice named
# placeholders always start with a colon.
$STH->bindParam(':name', $name);

You can use a shortcut here as well, but it works with associative arrays. Here’s an example:

# the data we want to insert
$data = array( 'name' => 'Cathy', 'addr' => '9 Dark and Twisty', 'city' => 'Cardiff' );

# the shortcut!
$STH = $DBH->("INSERT INTO folks (name, addr, city) value (:name, :addr, :city)");
$STH->execute($data);

The keys of your array do not need to start with a colon, but otherwise need to match the named placeholders. If you have an array of arrays you can iterate over them, and simply call the execute with each array of data.

Another nice feature of named placeholders is the ability to insert objects directly into your database, assuming the properties match the named fields. Here’s an example object, and how you’d perform your insert:

# a simple object
class person {
    public $name;
    public $addr;
    public $city;

    function __construct($n,$a,$c) {
        $this->name = $n;
        $this->addr = $a;
        $this->city = $c;
    }
    # etc ...
}

$cathy = new person('Cathy','9 Dark and Twisty','Cardiff');

# here's the fun part:
$STH = $DBH->("INSERT INTO folks (name, addr, city) value (:name, :addr, :city)");
$STH->execute((array)$cathy);

By casting the object to an array in the execute, the properties are treated as array keys.


Selecting Data

Fetch data into arrays or objects

Data is obtained via the ->fetch(), a method of your statement handle. Before calling fetch, it’s best to tell PDO how you’d like the data to be fetched. You have the following options:

  • PDO::FETCH_ASSOC: returns an array indexed by column name
  • PDO::FETCH_BOTH (default): returns an array indexed by both column name and number
  • PDO::FETCH_BOUND: Assigns the values of your columns to the variables set with the ->bindColumn() method
  • PDO::FETCH_CLASS: Assigns the values of your columns to properties of the named class. It will create the properties if matching properties do not exist
  • PDO::FETCH_INTO: Updates an existing instance of the named class
  • PDO::FETCH_LAZY: Combines PDO::FETCH_BOTH/PDO::FETCH_OBJ, creating the object variable names as they are used
  • PDO::FETCH_NUM: returns an array indexed by column number
  • PDO::FETCH_OBJ: returns an anonymous object with property names that correspond to the column names

In reality, there are three which will cover most situations: FETCH_ASSOC, FETCH_CLASS, and FETCH_OBJ. In order to set the fetch method, the following syntax is used:

$STH->setFetchMode(PDO::FETCH_ASSOC);

You can also set the fetch type directly within the ->fetch() method call.

FETCH_ASSOC

This fetch type creates an associative array, indexed by column name. This should be quite familiar to anyone who has used the mysql/mysqli extensions. Here’s an example of selecting data with this method:

# using the shortcut ->query() method here since there are no variable
# values in the select statement.
$STH = $DBH->query('SELECT name, addr, city from folks');

# setting the fetch mode
$STH->setFetchMode(PDO::FETCH_ASSOC);

while($row = $STH->fetch()) {
    echo $row['name'] . "n";
    echo $row['addr'] . "n";
    echo $row['city'] . "n";
}

The while loop will continue to go through the result set one row at a time until complete.

FETCH_OBJ

This fetch type creates an object of std class for each row of fetched data. Here’s an example:

# creating the statement
$STH = $DBH->query('SELECT name, addr, city from folks');

# setting the fetch mode
$STH->setFetchMode(PDO::FETCH_OBJ);

# showing the results
while($row = $STH->fetch()) {
    echo $row->name . "n";
    echo $row->addr . "n";
    echo $row->city . "n";
}

FETCH_CLASS

The properties of your object are set BEFORE the constructor is called. This is important.

This fetch method allows you to fetch data directly into a class of your choosing. When you use FETCH_CLASS, the properties of your object are set BEFORE the constructor is called. Read that again, it’s important. If properties matching the column names don’t exist, those properties will be created (as public) for you.

This means if your data needs any transformation after it comes out of the database, it can be done automatically by your object as each object is created.

As an example, imagine a situation where the address needs to be partially obscured for each record. We could do this by operating on that property in the constructor. Here’s an example:

class secret_person {
    public $name;
    public $addr;
    public $city;
    public $other_data;

    function __construct($other = '') {
        $this->address = preg_replace('/[a-z]/', 'x', $this->address);
        $this->other_data = $other;
    }
}

As data is fetched into this class, the address has all its lowercase a-z letters replaced by the letter x. Now, using the class and having that data transform occur is completely transparent:

$STH = $DBH->query('SELECT name, addr, city from folks');
$STH->setFetchMode(PDO::FETCH_CLASS, 'secret_person');

while($obj = $STH->fetch()) {
    echo $obj->addr;
}

If the address was ’5 Rosebud,’ you’d see ’5 Rxxxxxx’ as your output. Of course, there may be situations where you want the constructor called before the data is assigned. PDO has you covered for this, too.

$STH->setFetchMode(PDO::FETCH_CLASS | PDO::FETCH_PROPS_LATE, 'secret_person');

Now, when you repeat the previous example with this fetch mode (PDO::FETCH_PROPS_LATE) the address will NOT be obscured, since the constructor was called and the properties were assigned.

Finally, if you really need to, you can pass arguments to the constructor when fetching data into objects with PDO:

$STH->setFetchMode(PDO::FETCH_CLASS, 'secret_person', array('stuff'));

If you need to pass different data to the constructor for each object, you can set the fetch mode inside the fetch method:

$i = 0;
while($rowObj =  $STH->fetch(PDO::FETCH_CLASS, 'secret_person', array($i))) {
    // do stuff
    $i++
}

Some Other Helpful Methods

While this isn’t meant to cover everything in PDO (it’s a huge extension!) there are a few more methods you’ll want to know in order to do basic things with PDO.

$DBH->lastInsertId();

The ->lastInsertId() method is always called on the database handle, not statement handle, and will return the auto incremented id of the last inserted row by that connection.

$DBH->exec('DELETE FROM folks WHERE 1');
$DBH->exec("SET time_zone = '-8:00'");

The ->exec() method is used for operations that can not return data other then the affected rows. The above are two examples of using the exec method.

$safe = $DBH->quote($unsafe);

The ->quote() method quotes strings so they are safe to use in queries. This is your fallback if you’re not using prepared statements.

$rows_affected = $STH->rowCount();

The ->rowCount() method returns an integer indicating the number of rows affected by an operation. In at least one known version of PDO, according to [this bug report](http://bugs.php.net/40822) the method does not work with select statements. If you’re having this problem, and can’t upgrade PHP, you could get the number of rows with the following:

$sql = "SELECT COUNT(*) FROM folks";
if ($STH = $DBH->query($sql)) {
    # check the row count
    if ($STH->fetchColumn() > 0) {

    # issue a real select here, because there's data!
    }
    else {
        echo "No rows matched the query.";
    }
}

Conclusion

I hope this helps some of you migrate away from the mysql and mysqli extensions. What do you think? Are there any of you out there who might make the switch?

How To Deliver Exceptional Client Service


Smashing Magazine Feed 25 Jan 2012, 3:02 pm CET

  

We often hear companies, including Web agencies, boast about how they provide exceptional client service. But how do they define exceptional?

Consider this scenario. You are hired to design and develop a new website for a retail client. The client loves the design, and the pages you develop use the latest in HTML5, CSS3 and responsive design, resulting in a website that works wonderfully across browsers and devices. The e-commerce features of the new website help the client significantly increase their online sales, and the entire project is delivered on time and on budget. Now, is this “exceptional” client service? I don’t think it is.

When the client hired you, they expected that you would design and develop a great website. They also expected it would be done according to the timeline and budget set during the planning stages of the project. As successful as this project may have been for both you and the client, in the end, you did exactly what you were hired to do. You did your job.

Just Doing Your Job Vs. Delivering Exceptional Service

Nothing is wrong with “just doing your job.” In many cases, that alone is a tall order. So, while doing what you were hired to do is nothing to be ashamed of, it is also not exceptional — nor will it set you apart. There will always be other agencies or designers that will be able to do the work as well as you can — and there will certainly be someone willing to do it cheaper! The service you provide is how you can truly differentiate yourself.

Exceptional client service is about going beyond what is realistically expected of you. It is about surprising, and often delighting, customers, turning them into enthusiastic referral sources and lifelong clients who stick with you not only because you do great work at a fair price, but because the value you bring to them goes far beyond just your products.

In this article, I’ll detail a few of the ways that I have tried to take my own client service to the next level and deliver a better experience, starting with the most important aspect: the relationships that you establish with the clients who hire you.

Superhero racing to help There is a difference between doing what you were hired to do and delivering a superheroic level of service. (Image: JD Hancock)

Creating Real Relationships

Here’s a quick exercise. Write down your five most important clients (how you define “important” is up to you). Then, write down as many things you know about those clients that have nothing to do with their business or the work you have done for them. What are their hobbies or passions? How many kids do they have? How old are those kids, and what are their names? Where do they like to vacation? Things like that.

So, how long is your list? If you’re like most people I speak with, probably not very long at all. We learn everything we can about a client’s business, but we often fail to discover anything substantial about our clients as people. If we do not engage with our clients in a real, personal way, then we are just another vendor — and vendors are easily replaceable with better cheaper options. However, clients are much less likely to consider replacing people with whom they have real relationships.

So, how do you start learning more about your clients? Simple: ask them questions about themselves and their lives, not just about their business.

Asking Real Questions

When I give this advice to others, it is often met with some apprehension. Asking someone about their business goals is easy. Asking them about their life outside of the office is harder. We often avoid getting personal for fear of offending the person or saying the wrong thing; but by being overly cautious, we miss the chance to create a real relationship.

Whenever I get nervous about getting too personal with a client, I remind myself of a story. A few years ago, I had the privilege to work on the website for the Tori Lynn Andreozzi Foundation. This non-profit foundation was named after a young girl who, walking home from school one afternoon, was struck by a drunk driver. Tori survived but was forever changed. Today, she is in a minimally conscious state, unable to walk, speak or eat.

In one of my first meetings with this client, I sat down with the head of the foundation, Tori’s mother, Cathy. I began the conversation simply by asking her, “How is Tori doing today?”

Cathy smiled and answered that Tori was doing well. We had our meeting and discussed the website and the project. As we were wrapping up, Cathy thanked me for asking her about Tori. She explained that so many people avoid asking about her daughter, fearing the news would be bad or that Cathy would be upset by the question. The truth is that, even though Tori has bad days, Cathy always enjoys talking about her daughter and was very happy to be asked about her. By asking Cathy how her daughter was doing, I showed her that I cared about more than just the project.

Website for the Tori Lynn Andreozzi Foundation The website for the Tori Lynn Andreozzi Foundation

Today, Cathy is one of my favorite people to speak with, and we begin every conversation by asking how each other’s children are doing. We have much more than a great client-vendor relationship, all because I asked a real question, honestly cared about the answer, and created a real, human connection in the process. Had I been too afraid to ask that question, I might never have been able to build the relationship that I have now.

Don’t be afraid to ask your clients real questions. If they don’t want to answer you, they won’t. But for those who do (and you will find that most, if not all, of your clients will be happy to have a real conversation that has nothing to do with business), you will be well on your way to building real relationships.

Participate In More Than Just Projects

Another way to build a relationship with a client that goes beyond the project is to participate in their events. If the client runs a non-profit organization, they might have fundraisers or similar events that offer you an opportunity to support their cause and nurture the relationship. Go to these events and participate. As a bonus, you will also be helping a worthwhile cause.

Not all of your clients will have fundraising events, but they might invite you to holiday parties and other gatherings. Take advantage of these opportunities to interact with your clients outside of a normal business setting. It will go a long way to reinforcing those real relationships that you are trying to create and show that you are more than just another vendor.

Similarly, consider inviting clients to some of your events to show that you view them as more than just a source of business. When they arrive, greet them warmly and enjoy their company, leaving business talk for another day.

Help Them With Services That You Do Not Provide

Clients may hire you to design and develop a Web presence for them, but in the course of the project you will often discover that they need other services that you do not provide. By listening to their needs, you might learn that they have issues with their payroll company or their accountants or some other aspect of their business.

Look to your own business and the vendors you use. There may be a service or company that you have had success with that you could recommend. Also look to your other clients to see whether they offer services that fit. If appropriate, set up a lunch meeting between you, the client with the need and the client that might be able to fill that need. Not only will you be taking two clients out for lunch, you will hopefully be helping them both by making a valuable connection between the two companies.

When a client can say, “I hired this company to design our website and they ended up helping us revamp our entire payroll system!” you position yourself as much more than just their “Web team” — you show that you are a valued business resource and a trusted advisor.

Pick Up The Phone

Good communication is key to any relationship. Still, judging from the number of clients I speak with who are unhappy with their current Web team — not because they do a poor job, but because they are unresponsive — quality communication is not always a given.

Regularly updating your clients by email is important, but also pick up the phone every now and then, so that you become more than just that distant person behind those electronic updates. By hearing your voice, clients will feel more connected to you and the project. It also shows them that you value them enough to take the time to make a personal call, and it gives you a chance to talk about something other than business.

Conversations bubbles in an office Regular phone calls allow you to have real conversations with clients, communicating at a personal level that email and other electronic updates do not allow for. (Image: opensourceway)

Face The Bad Times Head On

Have you ever had to share bad news with a client, but rather than pick up the phone to discuss the issue, you waited and sent an email at 5:15 pm on a Friday? By doing this, you may have bought yourself a few more days before having to face the client’s worried questions, but you also damage the relationship by hiding behind an email. It also means that the client will read the bad news first thing on Monday morning; definitely not a good start to their week, and definitely not the way to treat a valued relationship.

Here’s a secret: clients do not expect you to be perfect. They do, however, expect you to be honest. When something goes wrong, let them know quickly so that they are not blindsided by the issue later on. And never deliver bad news by email. Picking up the phone to discuss the news lets you reassure the client and answer any questions they may have. An after-hours email certainly won’t do that for them.

If the matter is handled correctly, the client will not remember that something went wrong. They will remember that you were honest and kept them apprised of the state of the project, even when it did not go according to plan.

Be Thankful And Show Appreciation

When was the last time you thanked a client for working with you? How did you do it? Did you send a basket of cookies or chocolate with a generic “thank you” message, or did you do something more personal?

Too often, we fail to even thank our clients for their business. We are so keen to finish a project and move on to the next one that we forget to properly show our appreciation.

While a basket of sweets and a generic message is better than nothing, consider sending a personal, handwritten thank-you note.

Handwritten letters have become all but extinct these days. With the rise of electronic communication such as email, social networks and text messaging, so few people take the time and effort to actually write a letter. The gesture of a personal letter will delight and surprise your client, not only because you have thanked them, but because the way you did so was personal, memorable and the perfect cap to a successful project.

Handwritten thank you message A thankful, personal handwritten card is a great way to cap off a successful project. (Image: irrezolut)

How About You? Do You Deliver Exceptional Client Service?

I hope this article starts a conversation. How do you deliver exceptional client service? What tips can you share so that others can delight their own clients and offer them value beyond just products?

In this industry, we are always eager to share the latest tips and tricks on CSS, HTML, JavaScript, PHP or some other Web technology. Let’s also start to share tips on how to deliver exceptional client service, because success in this industry is about much more than developing great websites — it’s about developing great relationships.

(al)


© Jeremy Girard for Smashing Magazine, 2012.

Meet Crockford’s JSDev


Nettuts+ 25 Jan 2012, 6:29 am CET

Recently, Douglas Crockford released a neat tool that makes the process of developing and testing your JavaScript a bit easier. Interested in learning more? Watch today’s quick tip to find out!


Watch the Screencast


Show Link


Will you use JSDev?

I’m curious; is this something that you’ll use in your daily coding? I’m still not sure, myself. Let us hear your thoughts in the comments!

What Successful Products Teach Us About Web Design


Smashing Magazine Feed 24 Jan 2012, 4:01 pm CET

  

Web design is a craft that is constantly evolving and yet also sometimes sabotaged. The moment a design is released, a new version is born. In the beginning, like a baby, it seems vulnerable and weak, but in time it grows up and becomes self-sufficient. Redesigning a website for its own sake doesn’t prove anything; quite the contrary, it reveals a lack of effectiveness on the part of the designer.

Product design is a craft in which new versions come to life with increasing difficulty. We can learn a thing or two from it when designing for the Web. First, let’s look at some examples.

  • How many designs for the iPhone has Apple released since 2007? The answer is one, with only two tweaks. How many Motorola phones for Android can you find on the market right now? Thirteen, not counting the old models.
  • How many designs of the Mini Cooper do you know of? Just that one brave design that has continually evolved since 1959! How many Toyota Corolla models can you count since 1967? Nineteen.
  • Zippo lighters have retained their appeal since 1933!

Forget marketing, technical specs and hardware. Products such as the iPhone, the Mini Cooper and the Zippo lighter have become wildly successful because of their outstanding design. Such massive success springs from three sources: the designer, sticking to the scope and iteration. These aspects can help us in Web design, too. In this article, we’ll look at what we can learn from successful product design.

The Ability Of The Designer

Zippo Zippo lighters have remained elegant and reliable through time. (Image: cell105)

Do you trust your instincts? You should! Because when you see a design, you judge its attractiveness in less than a second. We all know what we like, even if we can’t always explain it. It’s about aesthetics. Aesthetics is a child of harmony, and harmony is not magic. It can be achieved when the designer embraces certain principles, such as balance, contrast and dominance. Becoming a fantastic designer, though, requires more than pure technique. It requires that you see the context and make decisions accordingly.

A couple of comments by Karim Rashid, featured in the documentary Objectified are fascinating and revealing. First, Rashid talks about a stereo that he loved as a teenager:

It was a white kind of bubble stereo with these two bubble white speakers. And it was probably very inexpensive — it was a real democratic product, and it had a turntable and the whole thing built in. It was a beautiful thing. Looking back and thinking why it was a beautiful thing, it was very self-contained, and the message was very strong and very simple, and at the same time it was very human. There was a quality about it.

See? A democratic, self-contained, human, simple thing with a strong message.

Here is Rashid again on thinking outside the box:

Why do we feel like we need to keep revisiting the archetype over and over and over again? Digital cameras, for example, [whose] format, proportion, the fact that they’re a horizontal rectangle, are a model of the original silver film camera. So, in turn it’s the film that defined the shape of the camera. All of a sudden, our digital cameras have no film. So, why on earth do we have the same shape we have?

How is it that Karim Rashid extracts such clear conclusions? What hinders us from doing the same? And not just in theory. Let’s do it for real. The next time you are about to make an important design decision, stop and ask yourself, What would I do if I were Dieter Rams or Jonathan Ive or — since you’re a Web designer — Douglas Bowman?

Asking this kind of question briefly expands our skills of judgment and makes us ultra-alert. Doing it regularly can drastically heighten our perception, values and actions as designers. Is this enough? No, but it is the beginning of a beautiful relationship with design.

And the Zippo lighter? It looks both friendly and solid, a comrade that needs your attention in order to keep working. Ιt has its own scent; it’s windproof; and above all, the sound when you flip open the lid is distinctive. And if you’ve owned a Zippo for a while, you must have noticed that it learns how you touch it when you light it.

All together, a Zippo is a product of craft — just as our designs for the Web should be. This is as simple and as hard as it sounds.

Focusing On The Scope

Mini Cooper Once a Mini, always a Mini. (Image: Shelley Gibb)

Let’s go back to cars for a moment.

As noted earlier, the Corolla models of Toyota are nothing spectacular in their design. But what is a Toyota car known for? It’s a reliable, relatively cheap family car. Is Toyota successful? You bet!

What’s a Mini Cooper? It’s a beautiful small car that appeals mostly to young people. Is it successful? Of course, it is.

Cars are complicated machines. They do more than transport people. If a Toyota were as fancy as the Mini, then it wouldn’t be affordable. If a Mini were reimagined as a family car, then it would lose some of its charm. Oversimplification? Perhaps. But you get the point.

There’s a scope behind each product. As long as the scope is met, the product will be effective and remain on the market. The same happens in Web design.

Consider a metaphor. The closest physical product to a website is a periodical. Take Wired magazine (the physical magazine, that is, not the website or iPad app, which have slightly different characteristics). I’ve been reading it for more than 10 years, and if I had to describe it succinctly I would say “forward-thinking and cool.” Wired reinvents itself every once in a while and persistently fine-tunes the design, but the scope remains the same. Excellent design and illustration, superbly written long articles and a ton of clever short ones serve the main purpose: to introduce its audience to a new era. Audiences change over time, and new eras dawn, but Wired remains. Why? Because it has always respected a higher purpose. Sure, many magazines are well designed, and enough of them have great content. But you rarely find one with a unique identity, an identity that can’t be easily copied.

Your probably less complicated Web project needs to perform similarly. You must define the objectives. The design must promote them. Good content should prevail. You know the rules; make sure to follow them. Moreover, know where to stop. If it’s a new idea with vague potential or yet another feature or a last-minute change, just say no.

Websites are like breathing organisms. They evolve; new features are added and others are dropped, but they never stay still. Or at least they shouldn’t. Thus, while a promising fresh idea shouldn’t be discarded, it should be held until the next major update.

Big, ambitious, well-funded websites often seem to lose focus. Their owners try to satisfy all requests. This is a recipe for disaster, because it creates unnecessary friction between everyone working on the project. It dulls the impact of the best features and, above all, the scope. Tension fills the air. The worst days are ahead.

Such practices have led to the infamous concept of design by committee. Simply put, if everything is important, then nothing is important.

Iterations

Apple Store, London Is what Apple does magic? I think not. (Image: Jon Rawlinson)

Let’s talk Apple. Apple’s iconic design and its founder’s exceptional way of thinking have been overanalyzed lately.

No matter how many words we write about Steve Jobs, we still seem to explain away his success as being a kind of magic. But that’s plainly wrong. People are inclined towards the least complicated, least demanding explanation to a conundrum. It is written in our genes. We think more deeply only when there’s a serious reason to do so. (But I digress.)

So, let’s do away with what Adrian Slywotzky refers to as the “Eureka” myth:

Apple would love us to believe it’s all “Eureka.” But Apple produces 10 pixel-perfect prototypes for each feature. They compete — and are winnowed down to three, then one, resulting in a highly evolved winner. Because Apple knows the more you compete inside, the less you’ll have to compete outside.

If Apple iterates so painstakingly, why shouldn’t we?

Inspiration for a great design roars when it comes. And implementing the idea brings a rush of enthusiasm. And our eyes sparkle when we anticipate outstanding success. And yet it rarely works that way.

Why? Because ideas and their execution are seldom free from flaws. You know the old cliché, “There is always room for improvement.” It still stands. There is always room for improvement, and accepting that your idea is the one that needs improvement takes courage. Demolishing your next great product in order to make it better takes nerve and self-discipline. But it also makes you wiser, and can dramatically improve the product.

Iterating extensively and in detail doesn’t depend on a certain type of project or a certain budget. It’s a tricky thing, because it forces us to confront our imperfect nature as human beings. To embrace our inner flaws is to walk the road of truth and maturity, silently, without making a show that we’re doing it.

This weight might feel a little heavy on our shoulders. If it does or if you dismiss Apple’s success, consider what Oliver Reichenstein, head of Information Architects, says about the iterations that his team makes in each development phase (this quote appears in the comments section):

It’s often almost impossible to explain easily why things look like they do, because we went through so many iterations, that it feels like explaining a chess game with all the ifs and whats.

The same goes when designing for the Web: there’s no excuse to avoid making as many iterations as we can.

Final Thoughts

When successful designers are asked where they seek inspiration, they often say something like, “Everywhere — I go for a walk and observe the world around me.” And it’s true. But what they don’t often say is that they also know what to observe and how to ignore the noise of the world.

There are many beautiful well-functioning products around us. Each has a story to tell, a story that is strongly attached to its design, its scope and the iterations that the designer took before releasing it to the world.

Take the Dyson vacuum cleaner. Its design is at least impressive, and its scope is clear (to suck dirt better than other cleaners and, thus, to make your environment healthier), and it took hundreds of prototypes for the designers to figure out how to make it work without a bag. The first Dyson vacuum cleaner was sold in 1970! To explore further and find similar products, just search for our three key words: “design scope iteration.”

Creating a lasting website is no easier than creating a lasting vacuum cleaner. But neither is it impossible. It requires a holistic approach, focus and maturity, just like the products we’ve looked at here. Not to mention, it requires a paradigm shift.

(al)


© Yiannis Konstantakopoulos for Smashing Magazine, 2012.

.htaccess Files for the Rest of Us


Nettuts+ 24 Jan 2012, 1:37 am CET

.htaccess files are used to configure Apache, as well a range of other web servers. Despite the .htaccess file type extension, they are simply text files that can be edited using any text-editor. In this article, we’ll review what they are, and how you can use them in your projects.

Please note that .htaccess files don't work on Windows-based systems, although they can be edited and uploaded to a compatible web server, and on Linux-based systems they are hidden by default.

In order to work with htaccess files locally, to see how they work and generally play around with them, we can use XAMPP (or MAMP) on the Mac – a package that installs and configures Apache, PHP and MySQL. To edit these .htaccess files on Mac, we should use a text editor that allows for the opening of hidden files, such as TextWrangler.

A .htaccess file follows the same format as Apache’s main configuration file: httpd.conf. Many of the settings that can be configured using the main configuration file can also be configured with them, and vice versa.

A setting configured in an .htaccess file will override the same setting in the main configuration file for the directory which contains the file, as well as all of its subdirectories.

They are sometimes referred to as dynamic configuration files because they are read by the server on every request to the directory they are contained within. This means that any changes to an .htaccess file will take effect immediately, without requiring a reboot of the server, unlike changes made to the global configuration file. It also means that you pay a slight performance hit for using them, but they can be useful when you don't have access to the server's main configuration file.

So now we all know what .htaccess files are, how they are edited and worked with, and some of their pros and cons, let's look at how they can be used and some of the cool stuff they can do.


Redirects and URL Rewriting

A popular use of .htaccess files is to perform redirects or rewrite URLs. This can help with SEO following a domain name change, or file-structure reorganisation, or can make long unsightly URL more friendly and memorable.

Redirections

A redirection can be as simple as the following:

Redirect 301 ^old.html$ <a href="http://localhost/new.html" target="_blank">http://localhost/new.html</a> 

This sets the HTTP status code to 301 (moved permanently) and redirects all requests to old.html transparently to new.html. We use a regular expression to match the URL to redirect, which gives us a fine degree of control to ensure only the correct URL is matched for redirection, but adds complexity to the configuration and administration of it. The full URL of the resource being redirected to is required.

Rewrites

A rewrite rule can be as simple as this:

RewriteEngine on
RewriteRule ^old.html$ new.html

In this example, we just provide a simple file redirect from one file to another, which will also be performed transparently, without changing what is displayed in the address bar. The first directive, RewriteEngine on, simply ensures that the rewrite engine is enabled.

In order to update what is displayed in the address bar of the visitor's browser, we can use the R flag at the end of the RewriteRule e.g.

RewriteRule ^old.html$ <a href="http://hostname/new.html" target="_blank">http://hostname/new.html</a> [r=301]

The r flag causes an external redirection which is why the full URL (an example URL here) to the new page is given. We can also specify the status code when using the flag. This causes the address bar to be updated in the visitor's browser.

One of the possible uses for URL rewriting I gave at the start of this section was to make unsightly URLs (containing query-string data) friendlier to visitors and search engines. Let's see this in action now:

RewriteRule ^products/([^/]+)/([^/]+)/([^/<WBR>]+) product.php?cat=$1&brand=$2&<WBR>prod=$3

This rule will allow visitors to use a URL like products/turntables/technics/sl1210, and have it transformed into product.php?cat=turntables&<WBR>brand=technics&prod=sl1210. The parentheses in between the forward slashes in the above regular expression are capturing groups – we can use each of these as $1, $2 and $3 respectively. The [^/]+ character class within the parentheses means match any character except a forward-slash 1 or more times.

In practice, URL rewriting can be (and usually is) much more complex and achieve far greater things than this. URL rewriting is better explained using entire tutorials so we won't look at them in any further detail here.


Serving Custom Error Pages

It's just not cool to show the default 404 page anymore. Many sites take the opportunity offered by a file not found error to inject a little humour into their site, but at the very least, people expect the 404 page of a site to at least match the style and theme of any other page of the site.

Very closely related to URL rewriting, serving a custom error page instead of the standard 404 page is easy with an .htaccess file:

ErrorDocument 404 ";/404.html";

That's all we need; whenever a 404 error occurs, the specified page is displayed. We can configure pages to be displayed for many other server errors too.


Restricting Access to Specific Resources

Using .htaccess files, we can enable password protection of any file or directory, to all users, or based on things like domain or IP address. This is after all one of their core uses. To prevent access to an entire directory, we would simple create a new .htaccess file, containing the following code:

AuthName ";Username and password required";
AuthUserFile /path/to/.htpasswd
Require valid-user
AuthType Basic

This file should then be saved into the directory we wish to protect. The AuthName directive specifies the message to display in the username/password dialog box, the AuthUserFile should be the path to the .htpasswd file. The Require directive specifies that only authenticated users may access the protected file while the AuthType is set to Basic.

To protect a specific file, we can wrap the above code in a <files> directive, which specifies the protected file:

Files ";protectedfile.html";>
AuthName ";Username and password required";
AuthUserFile /path/to/.htpasswd
Require valid-user
AuthType Basic
</Files>

We also require an .htpasswd file for these types of authentication, which contains a colon-separated list of usernames and encrypted passwords required to access the protected resource(s). This file should be saved in a directory that is not accessible to the web. There are a range of services that can be used to generate these files automatically as the password should be stored in encrypted form.


Block Access to Certain Entities

Another use of .htaccess files is to quickly and easily block all requests from an IP address or user-agent. To block a specific IP address, simply add the following directives to your .htaccess file:

order allow,deny
deny from 192.168.0.1
allow from all

The order directive tells Apache in which order to evaluate the allow/deny directives. In this case, allow is evaluated first, then deny. The allow from all directive is evaluated first (even though it appears after the deny directive) and all IPs are allowed, then if the client's IP matches the one specified in the deny directive, access is forbidden. This lets everyone in except the specified IP. Note that we can also deny access to entire IP blocks by supplying a shorter IP, e.g. 192.168.

To deny requests based on user-agent, we could do this:

RewriteCond %{HTTP_USER_AGENT} ^OrangeSpider
RewriteRule ^(.*)$ http://%{REMOTE_ADDR}/$ [r=301,l]

In this example, any client with a HTTP_USER_AGENT string starting with OrangeSpider (a bad bot) is redirected back to the address that it originated from. The regular expression matches any single character (.) zero or more times (*) and redirects to the %{REMOTE_ADDR} environment variable. The l flag we used here instructs Apache to treat this match as the last rule so will not process any others before performing the rewrite.


Force an IE Rendering Mode

Alongside controlling how the server responds to certain requests, we can also do things to the visitor's browser, such as forcing IE to render pages using a specific rendering engine. For example, we can use the mod_headers module, if it is present, to set the X-UA-Compatible header:

Header set X-UA-Compatible ";IE=Edge";

Adding this line to an .htaccess file will instruct IE to use the highest rendering mode available. As demonstrated by HTML5 Boilerplate, we can also avoid setting this header on files that don't require it by using a <FilesMatch directive like so:

<FilesMatch ";.(js|css|gif|png|jpe?g|pdf|<WBR>xml|oga|ogg|m4a|ogv|mp4|m4v|<WBR>webm|svg|svgz|eot|ttf|otf|<WBR>woff|ico|webp|appcache|<WBR>manifest|htc|crx|xpi|<WBR>safariextz|vcf)$";>;
  Header unset X-UA-Compatible
</FilesMatch>

Implement Caching

Caching is easy to set up and can make your site load faster.

Caching is easy to set up and can make your site load faster. 'Nuff said! By setting a far-future expires date on elements of sites that don't change very often, we can prevent the browser from requesting unchanged resources on every request.

If you're running your site through Google PageSpeed or Yahoo's YSlow and you get the message about setting far-future expiry headers, this is how you fix it:

ExpiresActive on
ExpiresByType image/gif                 ";access plus 1 month";
ExpiresByType image/png                 ";access plus 1 month";
ExpiresByType image/jpg                 ";access plus 1 month";
ExpiresByType image/jpeg                ";access plus 1 month";
ExpiresByType video/ogg                 ";access plus 1 month";
ExpiresByType audio/ogg                 ";access plus 1 month";
ExpiresByType video/mp4                 ";access plus 1 month";
ExpiresByType video/webm                ";access plus 1 month";

You can add different ExpiresByType directives for any content that is listed in the performance tool you're using, or anything else that you want to control caching on. The first directive, ExpiresActive on, simply ensures the generation of Expires headers is switched on. These directives depend on Apache having the mod_expires module loaded.


Enabling Compression

Another warning we may get in a performance checker refers to enabling compression, and this is also something we can fix simply by updating our .htaccess file:

FilterDeclare   COMPRESS
FilterProvider  COMPRESS  DEFLATE resp=Content-Type $text/html
FilterProvider  COMPRESS  DEFLATE resp=Content-Type $text/css
FilterProvider  COMPRESS  DEFLATE resp=Content-Type $text/javascript
FilterChain     COMPRESS
FilterProtocol  COMPRESS  DEFLATE change=yes;byteranges=no

This compression scheme works on newer versions of Apache (2.1+) using the mod_filter module. It uses the DEFLATE compression algorithm to compress content based on its response content-type, in this case we specify text/html, text/css and text/javascript (which will likely be the types of files flagged in PageSpeed/Yslow anyhow).

In the above example we start out by declaring the filter we wish to use, in this case COMPRESS, using the FilterDeclare directive. We then list the content types we wish to use this filter. The FilterChain directive then instructs the server to build a filter chain based on the FilterProvider directives we have listed. The FilterProtocol directive allows us to specify options that are applied to the filter chain whenever it is run, the options we need to use are change=yes (the content may be changed by the filter (in this case, compressed)) and byteranges=no (the filter must only be applied to complete files).

On older versions of Apache, the mod_deflate module is used to configure DEFLATE compression. We have less control of how the content is filtered in this case, but the directives are simpler:

SetOutputFilter DEFLATE
AddOutputFilterByType DEFLATE text/html text/css text/javascript

In this case we just set the compression algorithm using the SetOutputFilter directive, and then specify the content-types we'd like to compress using the AddOutputFilterByType directive.

Usually your web server will use one of these modules depending on which version of Apache is in use. Generally, you will know this beforehand, but if you are creating a generic .htaccess file that you can use on a variety of sites, or which you may share with other people and therefore you don't know which modules may be in use, you may wish to use both of the above blocks of code wrapped in <IfModule module_name> directives so that the correct module is used and the server doesn't throw a 500 error if we try to configure a module that isn't included. You should be aware that it's also relatively common for hosts that run a large number of sites from a single box to disable compression as there is a small CPU performance hit for compressing on the server.


Summary

We looked at some of the most common uses for .htaccess files, and reviewed how we can achieve certain tasks that, as website builders/maintainers, are of particular interest to us. As is the case with any introductory tutorial of this nature, the subjects we've covered are presented as introductions to a particular topic. There are many other options and configurations than we have been able to look at, so I'd strongly recommend further reading on any subject that is of particular interest.

Introduction To Linux Commands


Smashing Magazine Feed 23 Jan 2012, 1:02 pm CET

  

At the heart of every modern Mac and Linux computer is the “terminal.” The terminal evolved from the text-based computer terminals of the 1960s and ’70s, which themselves replaced punch cards as the main way to interact with a computer. It’s also known as the command shell, or simply “shell.” Windows has one, too, but it’s called the “command prompt” and is descended from the MS-DOS of the 1980s.

Mac, Linux and Windows computers today are mainly controlled through user-friendly feature-rich graphical user interfaces (GUIs), with menus, scroll bars and drag-and-drop interfaces. But all of the basic stuff can still be accomplished by typing text commands into the terminal or command prompt.

Using Finder or Explorer to open a folder is akin to the cd command (for “change directory”). Viewing the contents of a folder is like ls (short for “list,” or dir in Microsoft’s command prompt). And there are hundreds more for moving files, editing files, launching applications, manipulating images, backing up and restoring stuff, and much more.

So, why would anyone want to bother with these text commands when you can use the mouse instead? The main reason is that they are very useful for controlling remote computers on which a GUI is not available, particularly Web servers, and especially Linux Web servers that have been stripped of all unnecessary graphical software.

Sometimes these lean Linux servers are managed through a Web browser interface, such as cPanel or Plesk, letting you create databases, email addresses and websites; but sometimes that is not enough. This article provides a broad introduction to text commands and the situations in which they are useful. We’ll cover the following:

  • Why knowing a few commands is useful;
  • Issuing commands on your own computer;
  • Using SSH to log into your Web server;
  • Getting your bearings: pwd, cs ls;
  • Viewing and moving files: cat, more, head, tail, mv, cp, rm;
  • Searching for files: find;
  • Looking through and editing files: grep, vi;
  • Backing up and restoring files and databases: tar, zip, unzip, mysqldump, mysql;
  • File permissions: chmod.

Why Knowing A Few Linux Commands Is Useful

As a website developer or server administrator, you would gain a big asset in becoming comfortable with these commands: for website emergencies, to configure a server and for your CV. It can also save you money. Many hosting companies offer fully managed servers but at a high monthly premium. Or else they charge by the hour for technical support.

Perhaps you need to archive some big files or make a change to the httpd.conf file or figure out why your website’s images have suddenly stopped loading. You might not want to pay $50 to your server’s administrator for a five-minute job. This article gives you the tools to make such changes yourself.

And why “Linux” commands? Two main types of servers are available today: Windows and UNIX. UNIX-based servers include Linux (which split off in 1991), Mac OS X (2002) and several more traditional UNIX systems, such as BSD, Solaris and HP-UX. Linux commands are basically UNIX commands and so will run on all of them. In fact, I use the term “Linux” here only because it is more common and less frightening than “UNIX.” Windows servers, on the other hand, have a much smaller market share and are more often controlled through GUIs, such as Remote Desktop and VNC, rather than the command line.

In fact, a November 2011 survey showed that Apache accounted for about 65% of all Web servers. Apache usually runs in the popular LAMP configuration: Linux, Apache, MySQL and PHP. Microsoft was a distant second, with 15%. Third place nginx runs on Linux, UNIX, Mac and Windows. So, the commands in this article will work on at least two thirds of all servers.

Issuing Commands To Your Own Computer

You can quickly experiment with text commands on your own computer. On Mac with OS X, go to Applications → Utilities, and run Terminal. On a PC with Windows, go to Start → All Programs → Accessories, and choose “Command Prompt.” On Ubuntu Linux, go to Applications → Accessories, and choose Terminal.

On Windows you should see this:

The Windows command prompt

This is the command line (i.e. shell, prompt or terminal) on your own computer. You can type dir on Windows or ls on Linux or Mac followed by “Enter” to see a list of the files in the current “directory” (i.e. folder, location or path).

All we will be doing for the rest of this article is opening up one of these terminals on a remote computer: your Web server.

You may have used VNC or Remote Desktop, which allow you to actually view the desktop on someone else’s computer: your screen shows their screen, your mouse controls their mouse, your keyboard mimics their keyboard.

The terminal is similar to this but without the fancy menus or scroll bars. If you were to plug a keyboard and screen into your Web server, sitting in a fireproof basement somewhere, you would probably see one of these terminals, waiting patiently for your user name and password.

Using SSH To Log Into Your Web Server

The application SSH, or Secure Shell, is used to log into Web servers. It often takes the same user name and password as FTP, but it has to be allowed by your host. If you have a dedicated Web server, it is probably already allowed. If you use cloud hosting, then you might need to request it first. If you are on shared hosting, you’ll definitely need to request it, and the administrator may refuse.

On Linux or Mac, open up Terminal as described above and type the following:

ssh -l username www.myserver.com

The -l stands for “log in as,” and your user name goes after it. If SSH is allowed, then it will ask for a password. If not, you’ll get an error message, like this one:

SSH Command and Connection Error

Running the ssh command and being denied access

On Windows, you will need to download some SSH software. Putty is a popular and easy choice. It downloads as a single EXE file, which you can save to your desktop and run right away. Type your website as the host name, check the SSH box under “Connection Type,” and click “Open.” It will ask for your user name and then your password.

Running Putty on Windows

Running Putty on Windows in order to SSH to your Web server

Once successfully logged in, you will usually see a welcome message. After that, you will be presented with a few letters and a $ sign (or a # sign if you have logged in as root). The letters often represent your user name and where you’ve come from, or the name of the server. A ~ indicates that you are in your home directory. The $ is the prompt; it indicates that you can start typing commands now, something like:

Successful SSH to a server

A successful SSH log-in to a Web server. The $ means we can start typing commands.

The next section introduces a few basic commands.

Getting Your Bearings

On Windows, when you go to “My Documents” from the Start menu, it opens your “My Documents” directory in Windows Explorer and shows the contents. If some nosy colleague walked by and asked “What directory are you in?” you could say “I’m in my documents.”

If you SSH’ed to a server as the user “admin,” you would land in admin’s home directory, probably /home/admin. You can verify this by typing the command pwd, which shows your current location (i.e. folder, directory or path).

The pwd and ls commands

The pwd command tells you where you are, cd changes the directory and ls shows the contents of a directory.

To change to another directory, use the cd command with the destination, like so:

cd /

This will change the directory to /, the top of the whole UNIX directory structure. The command ls lists the contents of the current directory, in this case /.

In the screenshot above, the terminal is color-coded. Dark-blue entries are subdirectories, and black entries are files. A lot of the interesting stuff on Web servers happens in the /etc, /home and /var directories. Using just cd and ls, you can explore your server and find out where stuff is.

When using cd, you can specify the new directory absolutely (beginning with a slash, like /var/www) or relative to your current location (without the initial slash). You can also go up a directory with two dots. Practice with the sequence below, pressing “Enter” after each command. Can you guess what the last command will tell you?

cd /var
ls
cd www
ls
cd ..
pwd

Viewing And Moving Files

On many Linux servers, websites are located in /var/www/vhosts. You can check on your server by doing the following:

cd /var/www/vhosts
ls

If you see a list of websites, you can move into one of them. Within the website’s main directory, you will probably see the same files that you see when you FTP to the website, things such as httpdocs (where your website’s files are), httpsdocs (if you have a separate secure website), conf (configuration files), statistics (logs and compiled statistics), error_docs, private and more.

You can then change into your website’s public-facing directory, which is myserver.com/httpdocs in this example:

cd myserver.com
ls
cd httpdocs
ls

Now you have arrived, and you can run a new command, cat, which displays the contents of a file. For instance, if you have an index.html file, run:

cat index.html

If your index.html file is more than a few lines long, it will rush past in a blur. You can use the more command to show it slowly, one page at time. After you type the command below, it will show you the first page. You can press the space bar to show the next page, “Enter” to show the next line, and Q to quit.

more index.html

You can also show just the first few or last few lines of a file with the head and tail commands. It shows 10 lines by default, but you can pass in any number:

head index.html
tail -20 index.html

If you would like to rename this file, use the mv command, short for “move”:

mv index.html indexold.html

Similarly, the cp is the copy command, and rm removes files.

cp index.html indexold.html
rm indexold.html

Below is a string of commands in action. In order, it confirms the current directory with pwd, looks at the contents with ls, views index.html with cat, then renames it with mv, and finally removes it with rm, with a lot of ls in between to show the changes.

The cat and mv commands

The cat, mv and rm commands in action, for displaying, moving and then removing a file.

More Advanced Tip: Changing the Prompt

Note that in our initial examples, the full prompt included the current directory. For instance, in [admin@myserver /]$, the / indicated that the user was in the / directory. In the example directly above, it was removed, or else it would have crowded the screenshot by constantly saying [admin@myserver /var/www/vhosts/myserver.com/httpdocs]$.

You can change the prompt to whatever you want by setting the PS1 environment variable. Here are a couple of examples, the latter including the user, host and current directory:

PS1="[woohoooo ]$ "
PS1='[${USER}@${HOSTNAME} ${PWD}]$ '

Searching For Files

On big websites, files can get lost. Perhaps you vaguely remember uploading a new version of your client’s logo about four months ago, but it has since fallen out of favor and been replaced. Now, out of the blue, the client wants it back. You could download everything from the server using FTP and search the files using Finder or Explorer. Or you could log in and search using the command line.

The find command can search through files by name, size and modified time. If you just give it a directory, it will list everything that the directory contains. Try this:

find /var/www

You will probably see lots and lots of file names whizzing past. If you have many websites, it could continue for a couple of minutes. You can stop it by hitting Control + C (i.e. holding down the Control key on your keyboard and pressing the letter C). That’s the way to interrupt a Linux command. A more useful command would be:

find /var/www | more

The pipe symbol (|) takes the output of one command (in this case, the long list of files produced by find) and passes it to another command (in this case, more, which shows you one page of files at a time). As above, press the space bar to show the next page, and Q to quit.

To search for a specific file name, add -name and the file name. You can use * as a wild card (the backslash is not always necessary but is good practice with the find command). You can combine searches using -o (for “or”). If you leave out the -o, it becomes an “and.”

find /var/www -name logo.gif
find /var/www -name *.gif
find /var/www -name *.gif -o -name *.jpg

You can also search by size by adding -size. So, you could look for all GIFs between 5 and 10 KB:

find /var/www -name *.gif -size +5k -size -10k

Similarly, to find a file that was last changed between 90 and 180 days ago, you can use -ctime:

find /var/www -name *.gif -ctime +90 -ctime -180

In both of these cases, you will probably also want to know the actual file size and date last changed. For this, you can add -printf, which is similar to the C function printf in that you use the % sign to output various information. This command outputs the file size (up to 15 characters wide), the date and time changed (down to the nanosecond) and the file name:

find /var/www -name *.gif -size +5k -size -10k -ctime +90 -ctime -180 -printf "%10s  %c  %pn"

With that whopper, you have hopefully found the missing file. Here is an example:

Variations on the find command

Searching for all GIFs within a single website, and displaying the file sizes, changed times and file names.

Another useful parameter is -cmin, which lets you see files that have changed in the last few minutes. So, if something goes wrong on a website, you can run this to see everything that has changed in the last 10 minutes:

find /var/www -cmin -10 -printf "%c %pn"

This will show files and directories that have changed. Thus, it won’t show files that have been removed (because they are no longer there), but it will show the directories that they were removed from. To show only files, add -type f:

find /var/www -cmin -10 -type f -printf "%c %pn"

More Advanced Tip: Reading the Manual

I didn’t have to remember all of the variations above. I consulted the manual several times, like so:

man find

While reading a manual page, the controls are the same as more: space bar for paging, “Enter” to go forward one line and Q to quit. The up and down arrows also work. You can search within a page of the manual by typing / and a keyword, such as /printf. This will jump you to the next occurrence of that term. You can search backwards with ?printf, and you can repeat the search by pressing N.

Looking Through And Editing Files

Most visual code editors allow you to search through many files when you’re looking for a particular variable or bit of HTML. You can also do this directly on the server using the command grep. This is useful when something goes wrong on a complex website with hundreds of files and you have to find the error and fix it fast.

Let’s say you view the HTML source and see that the error happens right after <div id="left">. You can let grep do the searching for you. Give it the thing to be searched for and the files to search in. These commands change to the website directory and grep through all files ending in php. You need to put quotes around the HTML because it contains spaces, and the inner quotes have to be escaped with backslashes:

cd /var/www/vhosts/myserver.com/httpdocs/
grep "<div id="left">" *.php

This will tell you which files in the current directory contain that bit of HTML. If you want to search in subdirectories, you can use the -r option with a directory at the end, instead of a list of files. The single dot tells it to start in the current directory.

grep -r "<div id="left">" .

Alternatively, you could use the find command from above to tell it which files to look in. To put a command within a command, enclose it in back apostrophes. The following searches only for the HTML in PHP files modified in the last 14 days:

grep "<div id="left">" `find . -name *.php -ctime -14`

You can also add -n to show the line numbers, as in this example:

Using grep to look for things inside files

Searching for a bit of HTML within the PHP files in the current directory

And how do you quickly fix an error when you find it? To do that, you will need to start up a Linux text editor. Different editors are available, such as pico and emacs, but the one that is guaranteed to be there is vi. To edit a file, type vi and the file name:

vi index.php

vi is a complex editor. It can do most of the amazing things that a fully featured visual editor can do, but without the mouse. In brief, you can use the arrow keys to get around the file (or H, J, K and L on very basic terminals where even the arrow keys don’t work). To delete a character, press X. To delete a whole line, press DD. To insert a new character, press I. This takes you into “insert mode,” and you can start typing. Press the Escape key when finished to go back to “command mode.” Within command mode, type :w to save (i.e. write) the file and :q to quit, or :wq to do both at the same time.

The vi editor also supports copying and pasting, undoing and redoing, searching and replacing, opening multiple files and copying between them, etc. To find out how, look for a good vi tutorial (such as “Mastering the VI Editor”). Note also that on many computers, vi is just a shortcut to vim, which stands for “vi improved,” so you can follow vim tutorials, too.

The Linux editor vi

Editing files with the vi text editor

More Advanced Tip: Tab Completion

When changing directories and editing files, you might get tired of having to type the file names in full over and over again. The Terminal loses some of its shine this way. This can be avoided with command-line completion, performed using tabs.

It works like this: start typing the name of a file or a command, and then press Tab. If there is only one possibility, Linux will fill in as much as it can. If nothing happens, it means there is more than one possibility. Press Tab again to show all of the possibilities.

For example, if above I had typed…

vi i

… And then pressed Tab, it would have filled in the rest for me…

vi index.php

… Unless several files started with I. In that case, I would have had to press Tab again to see the options.

Backing Up And Restoring Files And Databases

Some Linux servers do support the zip command, but all of them support tar, whose original purpose was to archive data to magnetic tapes. To back up a directory, specify the backup file name and the directory to back up, such as:

cd /var/www/vhosts/myserver.com/httpdocs/
tar czf /tmp/backup.tgz .

The czf means “create zipped file.” The single dot stands for the current directory. You can also back up individual files. To back up just things changed in the last day, add the find command:

tar cfz /tmp/backup.tgz `find . -type f -ctime -1`

Both of these commands put the actual backup file in the temporary /tmp directory — if the backup file is in the same directory that you are backing up, it will cause an error. You can move the file to where you need it afterwards. To see what is in an archive, use the tzf options instead:

tar tfz /tmp/backup.tgz

Linux tar command

Creating and showing the contents of a backup file using tar

To restore things, use xzf, for “extract from zipped file.” First, run a listing as above to check what’s in there, and then restore one or more of the files. The second command restores all of the files from the archive into the current directory:

tar xfz /tmp/backup.tgz ./index.php ./test.php
tar xfz /tmp/backup.tgz

If your server has the zip command, then run these commands to do the same thing:

cd /var/www/vhosts/myserver.com/httpdocs/
zip -r /tmp/backup.zip .
zip -r /tmp/backup.zip `find . -type f -ctime -1`
unzip -l /tmp/backup.zip
unzip /tmp/backup.zip test.php
unzip /tmp/backup.zip

If your Web server uses MySQL, then you might want to regularly back up your data. For this, there is the mysqldump command. The format of the command is:

mysqldump --user="username" --password="password" --add-drop-table database

Replace the user name, password and database with your values. Instead of specifying a database, you can use -A to dump all databases. If you get errors about table locking, you can add --single-transaction. Once you submit the user name and password, this will output a load of SQL in a long blur. To save the output to a file, you will need to use the > symbol. This sends the output of a command to a file.

mysqldump --user="username" --password="password" --add-drop-table database > /tmp/db.sql

To restore a database backup, you can use the mysql command. This command lets you run SQL statements from the command line. For example, the following command gets you into the database:

mysql --user="username" --password="password" dbname

At the mysql> prompt, you can type an SQL statement such as:

mysql> SHOW TABLES;
mysql> SELECT * FROM customers;

For restoring, you’ll need to use the pipe (|), which will send the output from one command into another. In this case, cat will output the database backup file and send it into the mysql command:

cat /tmp/db.sql | mysql --user="username" --password="password" dbname

If people are looking over your shoulder while you’re doing this, you might not want to type the password directly into the command. In this case, just leave it out, and mysql or mysqldump will ask for it instead.

cat /tmp/db.sql | mysql --user="username" --password dbname

Once you’ve created the database backup file, you can include it in the backups we did above:

tar czf /tmp/backup.tgz . /tmp/db.sql

More Advanced Tip: Hidden Files and Wildcards

Many websites use a file called .htaccess to implement URL rewriting and password protection. In UNIX, all files starting with a single dot are hidden. They won’t show up when you do ls, and they won’t get backed up if you do this:

tar czf /tmp/backup.tgz *

The * is a wildcard. Before the command executes, the * is replaced with all non-hidden files in the current directory. To include hidden files as well, it’s better to back up the whole directory as above using a single dot:

tar czf /tmp/backup.tgz .

To show hidden files when doing a directory listing, add -a to the command:

ls -a
ls -la

File Permissions

If you use FTP regularly to upload files to websites, then you might be familiar with permissions. All files and directories on Linux (and Mac, Windows and other UNIX systems) have an owner, a group and a set of flags specifying who can read, write and execute them.

The list of user names (and, thus, potential file owners) on a UNIX system is stored in the file /etc/passwd. You can try:

more /etc/passwd

The Apache Web server is started by a command when the Web server boots up. But the user who starts Apache is often a restricted and unprivileged user, such as nobody or apache or www-data. This is for security reasons, to prevent someone from hacking into the website and then gaining control of the whole server. You can find out who that user is by running the command below and looking in the first column. The ps aux command shows all of the processes running on the server, and grep shows only processes that contain the word “apache.”

ps aux | grep apache

This can cause conflicts, though. If you upload a file to a website via FTP and log in as admin, then the file will be owned by admin. If Apache was started by the user named nobody, then Apache might not be able to read that file and won’t be able to send it to any users who request it when viewing the website. Instead, users will see a broken image or a message such as “403 Forbidden. You don’t have permission to access that file.”

A subtler and more common problem is when an image can be viewed but not overwritten or removed via the website’s content management system (CMS). In this case, the user nobody can read the file but can’t write to it.

You can view permissions using the ls command with an extra -l, like so:

ls -l

ls command with long list format

The command ls -l shows information about permissions, owners, size and date.

This directory contains three files, with three subdirectories shown in green. The first letter on each line indicates the type: d for directory and - for normal file. The next nine letters are the permissions; they indicate the read, write and execute permissions for the owner, group and everyone else. After the number (which represents the size) is the owner and group for the file. These files are all owned by admin. This is followed by the file size (less useful for directories) and the date and time of the last modification.

Below is another example of three files in an images subdirectory. Two of the files were uploaded by admin via FTP, and Apache was started by the user www-data. One of the files will be unviewable through a Web browser. Which do you think it is?

Bad permissions

The answer is bg.jpg. Both bg.jpg and logo2.gif have the same permissions: only the owner can read and write them. The logo2.gif file is OK because the owner is www-data, so that file can be accessed, read and returned by Apache. The logo.gif file is also OK because it has r in all three permissions (i.e. owner, group and everyone else). But bg.jpg will fail because only the user admin can read it, not the user who started Apache. If you were to access that file in a Web browser, you would see something like this:

What happens when you try to access a file without the correct permissions in a browser.

These sorts of errors can be resolved with the chmod command, which changes file permissions. The three sets of permissions are represented in commands with u (“user” or owner), g (“group”), o (“other” or everyone else) or a (“all”). So, to enable all users to read bg.jpg, either of these would work:

chmod go+r images/bg.jpg
chmod a+r images/bg.jpg

If this file were also part of a CMS, then you’d have to also add write permissions before the CMS could overwrite it:

chmod a+rw images/bg.jpg

You can also make these changes to all files in all of the subdirectories by adding -R. This recursive operation is not supported by some FTP programs and so is a useful command-line tool:

chmod -R a+rw images/

Directories also need the x (“execute” permission), but files generally don’t (unless they are in a cgi-bin). So, you can give everything rwx (read, write and execute) permissions and then take away the x from the files:

chmod -R a+rwx images/
chmod -R a-x `find images/ -type f`

However, this does leave everything rather open, making it easier for hackers to gain a foothold. Ideally, your set of permissions should be as restrictive as possible. Files should be writable by the Apache user only when needed by the CMS.

More Advanced Tip: Chown and the Superuser

Another useful permissions command is chown. It changes the owner of a file. However, you have to be logged in as a user with sufficient privileges (such as root) in order to run it. To make www-data the owner of bg.jpg, run this:

chown www-data images/bg.jpg

This will probably return “Permission denied.” You have to run the command as the superuser. For this, you will need to find the root password for your server, and then run the following:

sudo chown www-data images/bg.jpg

You will definitely need to be the superuser if you want to edit configuration files, such as Apache’s:

sudo vi /etc/httpd/conf/httpd.conf

If you want to become the superuser for every command, run this:

su

This is dangerous, though, because you could easily accidentally remove things — especially if you are using the rm command, and particularly if you’re using it in recursive mode (rm -r), and most especially if you also force the changes and ignore any warnings (rm -r -f).

Conclusion

This article has introduced some very useful Linux commands, a potential asset for any aspiring Web worker and a surefire way to impress a dinner date.

For a few more commands related specifically to website crashes, check out the Smashing Magazine article “What to Do When Your Website Goes Down.” For a broader view, try this list of Linux commands. And the “Mastering the VI Editor” tutorial mentioned above explains vi well.

Hopefully, you now have the tools and confidence to pitch in the next time one of your websites has a problem.

(al)


© Paul Tero for Smashing Magazine, 2012.

Open Call For International Communities


Smashing Magazine Feed 21 Jan 2012, 10:31 pm CET

  

At Smashing Magazine, we are big proponents of diversity and sharing. We encourage designers and developers worldwide to step up and use Smashing Magazine as a platform to share their opinions, ideas or techniques. Our editorial process is quite evolved, yet we are very open to users’ suggestions. In fact, if an author has something to say, we try to help them collect their thoughts, strengthen their points and sharpen their language.

As it is, Smashing Magazine is in English; we communicate in English in our articles, through our comments, in social channels — everywhere. We have a quite good overview of what’s happening in the Web design scene among creative professionals where English is prevalent. When it comes to non-English Web design communities, we have almost no idea what’s going on there… it’s as if they never existed.

Last year, I was lucky to have attended quite a few conferences across Europe. I wanted to get a better understanding of what’s going on in those countries, how evolved their industry is and, more importantly, what techniques and tools they have developed and use in their work. Among all the small talks and casual discussions I had, I was impressed by the creative energy of designs in Czech Republic, by the pursuit of optimization of Russian projects, by the attention to professionalism in Norway and by the abundant democratic design culture of Swedes. Before I spoke to all those people and had a look at their projects, I had no idea about all the fantastic small projects and techniques they developed.

Future of Web Design Conference in London, 2010 Web design conferences offer fantastic opportunities for building connections in our community. Also, they are great for exploring innovative techniques and recent developments of our craft. Image credit

In fact, it appeared to me that there is so much going on in these non-English speaking communities, yet many of them are closed and separate, almost inaccessible to the rest of the world. For instance, in Russia there are fantastic design blogs like Habrahabr.ru where creative professionals share their thoughts, techniques and tools, yet because the blog is in Russian, it’s invisible for most creative professionals worldwide. Fortunately, Russian is my native language so I can read and write in Russian, but not everybody is as lucky as I am.

In my discussions with Christian Heilmann who has been traveling around the world much more than I have, the same holds true for many countries in Eastern Europe, Asia and South America, partly because of the language barrier.

We can change that. We invite all professionals from all parts of the world to get in touch with us. If you have been writing in Russian, Czech or any other language, but have a good command of English, we’d be more than happy to learn from your insights and share your expertise, techniques or tools with our worldwide audience. Our proofreaders will be more than happy to brush up your English writing, so it surely isn’t a reason not to write.

We’d Love To Learn From You!

We are always happy to support designers and developers who contribute to our fantastic Web design community and present tools, goodies, templates, articles or anything else for everybody to use and learn from. You could write about:

  • case-studies from your work, the decisions made and decisions rejected,
  • front-end / back-end techniques you’ve developed or implemented in your projects,
  • expert advice for beginners or professionals that you’ve gathered over years of professional work,
  • the cultural differences that designers worldwide should be aware of when working on projects targeted at your country,
  • open source projects, tools and other resources you’ve released or contributed to.

Of course, we will publish quality material and you will get paid, too. Even if you don’t want to write an article, we will do our best to support you on Twitter, Facebook, or in our email newsletter. And if you don’t feel that Smashing Magazine fits you for one reason or another, feel free to go ahead and contact other publications, we’re perfectly fine with that.

Spread the word!

If you don’t have time to write in English, here is what you can do to help:

  • If writing isn’t for you, draw the attention of your colleagues to this post and encourage them to share their insights,
  • Translate this article into your native language and publish it in popular design blogs or magazines in your country,
  • Bring up the topic during your next meetup, bar-camp or mini-conference.

Let’s Get In Touch!

Please drop us an email at ideas@smashingmagazine.com and tell us a bit about yourself, your expertise and the projects you’ve contributed to. Share your techniques and your thoughts! And if you’re organizing a social event, please invite foreign speakers and attendees to join and encourage them to share their expertise as well.

I sincerely believe that we can all benefit from diversity, and we can enrich our toolboxes, workflows and perhaps even our mindset with new viewpoints and insights. We are looking forward to your emails!

(jvb)


© Vitaly Friedman for Smashing Magazine, 2012.

Testing your PHP Codebase with EnhancePHP


Nettuts+ 21 Jan 2012, 5:51 am CET

You know it; I know it. We should be testing our code more than we do. Part of the reason we don’t, I think, is that we don’t know exactly how. Well, I’m getting rid of that excuse today: I’m teaching you to test your PHP with the EnhancePHP framework.


Meet EnhancePHP

I’m not going to try to convince you to test your code; and we’re not going to discuss Test Driven Development, either. That’s been done before on Nettuts+. In that article, Nikko Bautista explains exactly why testing is a good thing and outlines a TDD workflow. Read that sometime, if you aren’t familiar with TDD. He also uses the SimpleTest library for his examples, so if you don’t like the look of EnhancePHP, you might try SimpleTest as an alternative.

As I said, we’ll be using the EnhancePHP. It’s a great little PHP library—a single file—that offers a lot of testing functionality.

Start by heading over to their download page and grabbing the latest version of the framework.

We’re going to be building a really simple Validation class to test. It won’t do too much: just return true if the item passes validation, or false if it doesn’t. So, set up a really simple little project:

We’ll do this is a semi-TDD fashion, so let’s start by writing a few tests.


Writing Tests

Out little class is going to validate three things: email addresses, usernames, and phone numbers.

But before we get to writing actual tests, we’ll need to set up our class:

<?php

class Validation_test extends EnhanceTestFixture {
        public function setUp () {
                $this-> val = new Validation();
        }

}

This is our start; notice that we’re extending the class EnhanceTestFixture. By doing so, we let EnhancePHP know that any public methods of this class are tests, with the exception of methods setUp and tearDown. As you might guess, these methods run before and after all your tests (not before and after each one). In this case, our setUp method will create a new Validation instance and assign it to a property on our instance.

By the way, if you’re relatively new to PHP, you might not be familiar with that EnhanceTestFixture syntax: what’s with the slashes? That’s PHP namespacing for you; check out the docs if you aren’t familiar with it.

So, the tests!

Email Addresses

Let’s start by validating email addresses. As you’ll see, just doing a basic test is pretty simple:

public function validates_a_good_email_address () {
        $result = $this->val->validate_email("john@doe.com");
        EnhanceAssert::isTrue($result);
}

We simply call the method we want to test, passing it a valid email address, and storing the $result. Then, we hand $result to the isTrue method. That method belongs to the EnhanceAssert class.

We want to make sure our class will reject non-email addresses. So, let’s test for that:

public function reject_bad_email_addresses () {
        $val_wrapper = EnhanceCore::getCodeCoverageWrapper('Validation');
        $val_email = $this->get_scenario('validate_email');
        $addresses = array("john", "jo!hn@doe.com", "john@doe.", "jo*hn@doe.com");

        foreach ($addresses as $addr) {
                $val_email->with($addr)->expect(false);
        }
        $val_email->verifyExpectations();
}

This introduces a pretty cool feature of EnhancePHP: scenarios. We want to test a bunch of non-email addresses to make sure our method will return false. By creating a scenario, we essentially wrap an instance of our class in some EnhancePHP goodness, are write much less code to test all our non-addresses. That’s what $val_wrapper is: a modified instance of our Validation class. Then, $val_email is the scenario object, somewhat like a shortcut to the validate_email method.

Then, we’ve got an array of strings that should not validate as email addresses. We’ll loop over that array with a foreach loop. Notice how we run the test: we call the with method on our scenario object, passing it the parameters for the method we’re testing. Then, we call the expect method on that, and pass it whatever we expect to get back.

Finally, we call the scenario’s verifyExpectations method.

So, the first tests are written; how do we run them?


Running Tests

Before we actually run the tests, we’ll need to create our Validation class. Inside lib.validation.php, start with this:

<?php

class Validation {
        public function validate_email ($address) {

        }
}

Now, in test.php, we’ll pull it all together:

<?php

require "vendor/EnhanceTestFramework.php";
require "lib/validation.php";
require "test/validation_test.php";

EnhanceCore::runTests();

First, we’ll require all the necessary files. Then, we call the runTests method, which finds our tests.

Next comes the neat part. Fire up a server, and you’ll get some nice HTML output:

Very nice, right? Now, if you’ve got PHP in your terminal, run this is in the terminal:

EnhancePHP notices that you’re in a different environment, and adjusts its output appropriately. A side benefit of this is that if you’re using an IDE, like PhpStorm, that can run unit tests, you can view this terminal output right inside the IDE.

You can also get XML and TAP output, if that’s what you prefer, just pass EnhanceTemplateType::Xml or EnhanceTemplateType::Tap to the runTests method to get the appropriate output. Note that running it in the terminal will also produce command-line results, no matter what you pass to runTests.

Getting the Tests to Pass

Let’s write the method that causes our tests to pass. As you know, that’s the validate_email. At the top of the Validation class, let’s define a public property:

public $email_regex = '/^[w+-_.]+@[w.]+.w+$/';

I’m putting this in a public property so that if the user wants to replace it with their own regex, they could. I’m using this simple version of an email regex, but you can replace it with your favourite regex if you want.

Then, there’s the method:

public function validate_email ($address) {
        return preg_match($this->email_regex, $address) == 1
}

Now, we run the tests again, and:


Writing More Tests

Time for more tests:

Usernames

Let’s create some tests for usernames now. Our requirements are simply that it must be a 4 to 20 character string consisting only of word characters or periods. So:

public function validates_a_good_username () {
        $result = $this->val->validate_username("some_user_name.12");
        EnhanceAssert::isTrue($result);
}

Now, how about a few usernames that shouldn’t validate:

public function rejects_bad_usernames () {
        $val_username = $this->get_scenario('validate_username');
        $usernames = array(
                "name with space",
                "no!exclaimation!mark",
                "ts",
                "thisUsernameIsTooLongItShouldBeBetweenFourAndTwentyCharacters");

        foreach ($usernames as $name) {
                $val_username->with($name)->expect(false);
        }
        $val_username->verifyExpectations();
}

This is very similar to our reject_bad_email_addresses function. Notice, however, that we’re calling this get_scenario method: where’s that come from? I’m abstracting the scenario creation functionality into private method, at the bottom of our class:

private function get_scenario ($method) {
        $val_wrapper = EnhanceCore::getCodeCoverageWrapper('Validation');
    return EnhanceCore::getScenario($val_wrapper, $method);
}

We can use this in our reject_bad_usernames and replace the scenario creation in reject_bad_email_addresses as well. Because this is a private method, EnhancePHP won’t try to run it as a normal test, the way it will with public methods.

We’ll make these tests pass similarly to how we made the first set pass:

# At the top . . .
public  $username_regex = '/^[w.]{4,20}$/';

# and the method . . .
public function validate_username ($username) {
        return preg_match($this->username_regex, $username) == 1;
}

This is pretty basic, of course, but that’s all that’s needed to meet our goal. If we wanted to return an explanation in the case of failure, you might do something like this:

public function validate_username ($username) {
        $len = strlen($username);
        if ($len < 4 || $len > 20) {
                return "Username must be between 4 and 20 characters";
        } elseif (preg_match($this->username_regex, $username) == 1) {
                return true;
        } else {
                return "Username must only include letters, numbers, underscores, or periods.";
        }
}

Of course, you might also want to check if the username already exists.

Now, run the tests and you should see them all passing.

Phone Numbers

I think you’re getting the hang of this by now, so let’s finish of our validation example by checking phone numbers:

public function validates_good_phonenumbers () {
        $val_phonenumber = $this->get_scenario("validate_phonenumber");
        $numbers = array("1234567890", "(890) 123-4567",
                "123-456-7890", "123 456 7890", "(123) 456 7890");

        foreach($numbers as $num) {
                $val_phonenumber->with($num)->expect(true);
        }
        $val_phonenumber->verifyExpectations();
}

public function rejects_bad_phonenumnbers () {
        $result = $this->val->validate_phonenumber("123456789012");
        EnhanceAssert::isFalse($result);
}

You can probably figure out the Validation method:

public $phonenumber_regex = '/^d{10}$|^((?d{3})?[ |-]d{3}[ |-]d{4})$/';

public function validate_phonenumber ($number) {
        return preg_match($this->phonenumber_regex, $number) == 1;
}

Now, we can run all the tests together. Here’s what that looks like from the command line (my preferred testing environment):


Other Test Functionality

Of course, EnhancePHP can do a lot more than what we’ve looked at in this little example. Let’s look at some of that now.

We very briefly met the EnhanceAssert class in our first test. We didn’t really use it otherwise, because it’s not useful when using scenarios. However, it’s where all the assertion methods are. The beauty of them is that their names make their functionality incredibly obvious. The following test examples would pass:

  • EnhanceAssert::areIdentical("Nettuts+", "Nettuts+")
  • EnhanceAssert::areNotIdentical("Nettuts+", "Psdtuts+")
  • EnhanceAssert::isTrue(true)
  • EnhanceAssert::isFalse(false)
  • EnhanceAssert::contains("Net", "Nettuts+")
  • EnhanceAssert::isNull(null)
  • EnhanceAssert::isNotNull('Nettust+')
  • EnhanceAssert::isInstanceOfType('Exception', new Exception(""))
  • EnhanceAssert::isNotInstanceOfType('String', new Exception(""))

There are a few other assertion methods, too; you can check the docs for a complete list and examples.

Mocks

EnhancePHP can also do mocks and stubs. Haven’t heard of mocks and stubs? Well, they aren’t too complicated. A mock is a wrapper for object, that can keep track of what methods are called, with what properties they are called, and what values are returned. A mock will have some test to verify, as we’ll see.

Here’s a small example of a mock. Let’s start with a very simple class that counts:

<?php

require "vendor/EnhanceTestFramework.php";

class Counter {
  public $num = 0;
  public function increment ($num = 1) {
    $this->num = $this->num + $num;
    return $this->num;
  }
}

We have one function: increment, that accepts a parameter (but defaults to 1), and increments the $num property by that number.

We might use this class if we were building a scoreboard:

class Scoreboard {
  public $home = 0;
  public $away = 0;

  public function __construct ($home, $away) {
    $this->home_counter = $home;
    $this->away_counter = $away;
  } 

  public function score_home () {
    $this->home = $this->home_counter->increment();
    return $this->home;
  }
  public function score_away () {
    $this->away = $this->away_counter->increment();
    return $this->home;
  }
}

Now, we want to test to make sure that the Counter instance method increment is working properly when the Scoreboard instance methods call it. So we creat this test:

class ScoreboardTest extends EnhanceTestFixture {
  public function score_home_calls_increment () {
    $home_counter_mock = EnhanceMockFactory::createMock("Counter");
    $away_counter = new Counter();

    $home_counter_mock->addExpectation( EnhanceExpect::method('increment') );

    $scoreboard = new Scoreboard($home_counter_mock, $away_counter);
    $scoreboard->score_home();

    $home_counter_mock->verifyExpectations();
  }
}

EnhanceCore::runTests();

Notice that we start by creating $home_counter_mock: we use the EnhancePHP mock factory, passing it the name of the class we’re mocking. This returns a “wrapped” instance of Counter. Then, we add an expectation, with this line

$home_counter_mock->addExpectation( EnhanceExpect::method('increment') );

Our expectation just says that we expect the increment method to be called.

After that, we go on to create the Scoreboard instance, and call score_home. Then, we verifyExpectations. If you run this, you’ll see that our test passes.

We could also state what parameters we want a method on the mock object to be called with, what value is returned, or how many times the method should be called, with something like this:

$home_counter_mock->addExpectation( EnhanceExpect::method('increment')->with(10) );
$home_counter_mock->addExpectation( EnhanceExpect::method('increment')->times(2) );
$home_counter_mock->addExpectation( EnhanceExpect::method('increment')->returns(1) );
$home_counter_mock->addExpectation( EnhanceExpect::method('increment')->with(3)->times(1) );
$home_counter_mock->addExpectation( EnhanceExpect::method('increment')->with(2)->returns(2) );

I should mention that, while with and times will show failed tests if the expectations aren’t meant, returns doesn’t. You’ll have to store the return value and use an assertion to very that. I’m not sure why that’s the case, but every library has its quirks :). (You can see an example of this in the library examples in Github.)

Stubs

Then, there are stubs. A stub fills in for a real object and method, returning exactly what you tell it to. So, let’s say we want to make sure that our Scoreboard instance is correctly using the value it receives from increment, we can stub a Counter instance so we can control what increment will return:

class ScoreboardTest extends EnhanceTestFixture {
  public function score_home_calls_increment () {
    $home_counter_stub = EnhanceStubFactory::createStub("Counter");
    $away_counter = new Counter();

    $home_counter_stub->addExpectation( EnhanceExpect::method('increment')->returns(10) );

    $scoreboard = new Scoreboard($home_counter_stub, $away_counter);
    $result = $scoreboard->score_home();

    EnhanceAssert::areIdentical($result, 10);

  }
}

EnhanceCore::runTests();

Here, we’re using EnhanceStubFactory::createStub to create our stub counter. Then, we add an expectation that the method increment will return 10. We can see that the result it what we’d expect, given our code.

For more examples of mocks and stub with the EnhancePHP library, check out the Github Repo.


Conclusion

Well, that’s a look at testing in PHP, using the EnhancePHP framework. It’s an incredibly simple framework, but it provides everything you need to do some simple unit testing on your PHP code. Even if you choose a different method/framework for testing your PHP (or perhaps roll your own!), I hope this tutorial has sparked an interest in testing your code, and how simple it can be.

But maybe you already test your PHP. Let us all know what you use in the comments; after all, we’re all here to learn from each other! Thank you so much for stopping by!

Extracting Logos Using Levels In Adobe Fireworks


Smashing Magazine Feed 20 Jan 2012, 5:47 pm CET

  

In all the years that I’ve been using Adobe Fireworks, I have always had to perform one task in every project: remove the background from a logo. Most of the time, it’s because the client doesn’t have the original raw file that their previous designer used to create their company’s logo, or because I need to work with a bunch of affiliate logos that I downloaded from the Web and not all of them have transparency information.

With a rectangular or elliptical logo, I just trace over it with a shape and turn it into a mask. But when tracing a mask is impractical (as with complex shapes or text-based logos), I used to follow a method that I devised for extracting logos in Adobe Fireworks that doesn’t rely on the dreaded Magic Wand tool. This method took advantage of a few Live Effects to remove the background and retain the logo form. It was simple, but also primitive: it worked perfectly only when the contrast between the logo and background was already ideal and the logo form had only one color. Otherwise, I ended up with jagged edges.

I have since much improved the process of handling multi-colored logos and non-white backgrounds; it works best on solid-colored text and shapes with clear outlines. Because it involves Fireworks’ awesome features and tools, this method is a quick and easy solution that you can incorporate in your Web and interface design workflows.

And yes, still no Magic Wand tool.

Let’s Begin!

To start off, fire up Adobe Fireworks and load your logo image on the canvas. In the example below, I created a three-color logo text, surrounded by a blu-ish hue, on a canvas with a transparent background.

Create a back-up of the image by selecting it using the Pointer tool (V on the keyboard), cloning it (Shift + D, or in the menu Edit → Clone) and hiding it (L, or View → Hide Selection). You will need this back-up near the end of the process, but for now, keep it hidden.

Logo image on canvas Place the logo image on the Fireworks canvas.

Tip: You can also use Duplicate (Ctrl/Cmd + Alt/Opt + D, or Edit → Duplicate) instead of Clone to copy the image. The difference is that Duplicate offsets the position of the copied object by 10 pixels down and 10 pixels to the right, whereas Clone creates the copy in the same exact position as the original object.

Original image and hidden backup in the Layers panel The original image and hidden back-up in the Layers panel.

Step 1: Breakdown

To be able to deal with the different colors of the logo separately, we first need to break the logo down into “pieces,” one foreground color per piece. Use the Pointer tool to select the logo image, and use one or more bitmap selection tools (Marquee or Oval Marquee (M), Lasso or Polygon Lasso (L) — set the Edge to “Hard” in the Properties panel) to select a piece of the logo. Make sure the piece you select has only one color (not counting the image’s background). Cut and paste the selected piece (Ctrl/Cmd + X, and then Ctrl/Cmd + V) to separate it from the rest. Do this for each piece; cancel the Marquee selection (Ctrl/Cmd + D or Esc, or in the menu Select → Deselect) and switch back to the Pointer tool (V) if you need to select the logo image again.

Tip: Double-click on an image object to quickly switch from Pointer tool to Marquee tool.

Select a piece of the logo.

In our example, I’ve used a (rectangular) Marquee, but you can use the Oval Marquee for circular or elliptical selections, and the Lasso or Polygon Lasso for irregular shapes.

Cut up the logo into pieces Cut up the logo into pieces.

If your logo has only one color, skip this step and treat the whole image as your only piece.

Step 2: Desaturate

Select all of the pieces of the logo image using the Pointer tool, and apply a Hue/Saturation filter (in the Properties panel, go to Filters: [+] → Adjust Color → Hue/Saturation…). Drag the Saturation slider all the way to the left (-100) to reduce the logo to grayscale. Make sure that Lightness is set to 0 and that Colorize is unchecked before clicking “OK.”

Desaturate all pieces Desaturate all pieces.

A Note on Filters

Adobe Fireworks features two almost identical sets of filters: one in the application menu and another in the Properties panel (the Live Filters).

Filters menu vs. Live Filters Filters menu vs. Live Filters in the Properties panel

Filters applied using the application menu are “destructive,” in that they can’t be undone by any other means except Undo (Ctrl/Cmd + Z, or in the menu Edit → Undo). Furthermore, target vector objects (shapes and text) need to be converted into bitmap objects before they can work their magic, which makes editing the original object harder. To adjust the effect of the filter that you just applied, you will need to undo that step and reapply the filter.

To maintain the ability to easily edit an object and its filters’ properties, always use the Live Filters in the Properties panel. This way, you can make changes to the original object, and the filters will adjust automatically. You will also be able to change a filter’s settings at any time, or disable or remove the filter, without adversely affecting the other filters.

Step 3: Levels

What makes this newer method different is the use of the Levels filter (as opposed to the Brightness/Contrast filter of the older method) to push the dark grays into pure black and the light grays into white, while maintaining the smooth edges of the logo’s curves.

Select one piece of the logo image using the Pointer tool, and apply a Levels filter (in the Properties panel, go to Filters: [+] → Adjust Color → Levels…). In the Levels dialog, set the Channel drop-down to “RGB” (which is the default). Below the histogram under Input Levels, move the left and right arrow sliders to change the intensity of the dark and light areas of the image piece, respectively. Make sure that the Preview checkbox is checked, so that you can see your changes in real time. Move the left arrow slider just enough to the left to get the logo part to show up completely black, but not so far left that the edges of the logo become jagged. The same goes for the right arrow slider: move it right to get a pure white background. You can leave the center slider untouched. Click “OK” to apply the filter.

Levels filter applied to first piece Apply the Levels filter to each piece.

You can check the accuracy of your filter values by bringing up the Info panel (Shift + Alt/Opt + F12, or in the menu Window → Info) and hovering over the black area to obtain its RGB color value. The RGB values should all be set to 00; otherwise, go back to the Levels dialog and readjust the slider.

Use the Info panel’s RGBA reading to check the color values.

Do the same for the white area, this time setting all three RGB values to FF in the color reading.

You can further fine-tune the levels by changing the number values in the left and right text boxes in the Input Levels dialog, which correspond to the left and right sliders in the visual graph. Increase the value of the left text box to darken the dark-gray areas until all three RGB values are set to 00 in the Info panel; decrease the values if the edges of the logo become too jagged. The inverse is true for the right text box. This allows you to get pure black and white colors, while keeping the edges of the logo as smooth as possible.

Repeat the whole process in step 3 for all other image pieces.

Pieces with different Levels settings Pieces with different settings in the Levels filter. Notice the same rightmost value across all instances, corresponding to the same background color.

Bonus side effect: If your original logo image has compression artifacts, this step could greatly reduce them.

Step 4: Alpha Transparency

Once all of your image’s pieces have been “leveled” into black and white, use the Pointer tool to select an image piece and apply a “Convert to Alpha” filter (in the Properties panel, go to Filters: [+] → Other → Convert to Alpha). Doing this step separately per piece is important because each piece has a different setting in the Levels filter. If you were to apply a new filter to all pieces at once, Fireworks would equalize the settings for all of the other filters present.

Convert to Alpha filter Apply a “Convert to Alpha” filter to each piece.

In this step, you will again be able to check for the accuracy of your settings for the Levels filter; if the black area of an image piece is not completely black, it will show up as slightly transparent once the Alpha filter is applied. (This is where the checkerboard background of the canvas comes in handy.) Also, if the background is not completely white, you’ll see it faintly after converting the image piece to alpha.

Applying the “Convert to Alpha” filter to all pieces.

Step 5: Recolor

At this point, you have successfully extracted the logo form from its background. The next step is to bring back the original colors. To do this, open the Layers panel (F2, or in the menu Window → Layers), and look for the object that you hid at the beginning of this tutorial. Click on the visibility box at the left end of that object to make it visible again. Nudge it down so that it’s below the processed logo pieces and in clear view. Use the Pointer tool to select an image piece and apply a Color Fill filter (in the Properties panel, go to Filters: [+] → Adjust Color → Color Fill). In the Color Fill settings, click on the color swatch, and sample the corresponding color from the original logo image. Do the same for all other image pieces.

Color Fill filter applied to first piece Apply a Color Fill filter to the first piece, picking the color from the original logo image.

To sample a color for the Color Fill filter: 1. Click on the color swatch in the filter dialog, 2. Click on the part of the image whose color you want to sample, 3. The color swatch will update with the new color.

Step 6: Convert To Symbol

Once you have recolored all of the pieces, select the original logo image with the Pointer tool and hide it (Ctrl/Cmd + L, or in the menu View → Hide Selection). You can also click on the eye icon of that object in the Layers panel to hide it. Select all of the image pieces using the Pointer tool, and convert them into a symbol (F8, or Modify → Symbol → Convert to Symbol…) before using it in your layout, so that new filter changes affect the new logo as a whole.

The Convert to Symbol dialog.

If you wish to make changes to the objects inside the symbol, you can do one of the following:

  • With the instance of the symbol selected, go to Modify → Symbol → Edit Symbol;
  • Right-click on the instance of the symbol, and select Symbol → Edit Symbol;
  • Double-click on the instance of the symbol.

All logo pieces recolored and converted into a Symbol.

Taking It Further

You now have a version of the logo that you can set against any type of background: solid, gradient, textured or tiled. You can even use it as a bitmap mask over a photo, pattern or gradient if you want a different look. To do this, you’ll need to flatten the logo symbol first (Ctrl/Cmd + Alt/Opt + Shift + Z, or in the menu Modify → Flatten Selection), but you can always bring back your final logo by dragging an instance of the symbol from the Document Library panel (F11, or Window → Document Library) onto the canvas.

Extracting Logos Using Levels in Adobe Fireworks: the final result The final result.

If you are feeling adventurous, you could try turning it into a vector object using the Magic Wand tool first (W) and then running the “Convert Marquee to Path” command (Select → Convert Marquee to Path). Your mileage may vary, though: “Convert Marquee to Path” doesn’t always play well with complex shapes, but you can always tweak the vector paths that are created by that command until they match the logo.

(al) (mb) (vf)

Downloads

Need a sample to study? Download the sample archive for this tutorial (ZIP file, 57.6 KB), containing the Fireworks PNG (created in Adobe Fw CS5).

Further Reading


Smashing Is Looking For Experts On Fireworks, Photoshop & Illustrator

As our crafts mature, so do our tools. Fireworks, Photoshop and Illustrator are powerful tools that we, as designers, use on a regular basis. Fireworks is surely more flexible for Web at times (and UI/screen design in general), since it is dedicated specifically to the Web designer’s needs. And yet, it is underrated by many. We should all indeed be more open to try out new and different tools and share the techniques and our experiences with the community.

We look forward to hearing from you!

We’d love to cover more articles on Fireworks, Photoshop and Illustrator explaining useful techniques, tips and “lessons learned” from professional designers. So, if you:

  • Have a solid knowledge of at least one of these tools,
  • Have a solid experience in design (especially Web/screen/mobile),
  • Have a couple of articles published on any of the tools mentioned,
  • Or perhaps have even released some extensions or tools for Fireworks, Photoshop or Illustrator…

Then please drop us an email at ideas@smashingmagazine.com. Please include details about your experience, examples of your work, links to your articles and your article ideas (at least two). Of course, all authors get paid :-)

We look forward to hearing from you!

— Smashing Editorial Team


© Jose Olarte for Smashing Magazine, 2012.

Burst Title


CSS-Tricks 20 Jan 2012, 4:51 am CET

During the previews for a movie I saw recently, there was an advertisement for an Oprah-related something or another. I wasn't paying attention because I was trying to get out my phone so I could snap a picture of it. Which I failed to do. There was these neat title screens that I thought would be fun to recreate with CSS. They looked like... well they looked like this:

View Demo   Download Files

Turns out you can do it rather semantically. Just a header tag with an anchor link inside. Admittedly, it would be cool to do it with just the header tag but I wasn't able to figure out a way to get the layers all right with the text on top without the extra element.

<h1><a href="#">CSS-Tricks</a></h1>
h1 {
  text-align: center;
  color: white;
  text-transform: uppercase;
  padding: 1px;
  font-family: 'Raleway', cursive;
  font-weight: 100;
  position: relative;
  background: -webkit-linear-gradient(left, black, #eee, black);
  background: -moz-linear-gradient(left, black, #eee, black);
  background: -ms-linear-gradient(left, black, #eee, black);
  background: -o-linear-gradient(left, black, #eee, black);
}
h1:before {
  content: "";
  position: absolute;
  left: 50%;
  top: -50px;
  width: 600px;
  margin-left: -300px;
  margin-top: -220px;
  height: 600px;
  background: -webkit-radial-gradient(50% 50%, ellipse closest-side, #444, black);
  background: -moz-radial-gradient(50% 50%, ellipse closest-side, #444, black);
  background: -ms-radial-gradient(50% 50%, ellipse closest-side, #444, black);
  background: -o-radial-gradient(50% 50%, ellipse closest-side, #444, black);
  z-index: -1;
}
h1 a {
  background: black;
  display: block;
  padding: 20px;
  text-decoration: none;
  letter-spacing: 30px;
  color: white;
}

I listed out all the vendor prefixes here because using them is required in "real" usage and I worry about people copying and pasting pseudo code. But if you want to play around with this and don't want to deal with all that, the Dabblet demo doesn't need them as it uses Prefix Free.

I also added some animations to the demo just for fun.

View Demo   Download Files

Burst Title is a post from CSS-Tricks

Burst Title


CSS-Tricks 20 Jan 2012, 4:51 am CET

During the previews for a movie I saw recently, there was an advertisement for an Oprah-related something or another. I wasn't paying attention because I was trying to get out my phone so I could snap a picture of it. Which I failed to do. There was these neat title screens that I thought would be fun to recreate with CSS. They looked like... well they looked like this:

View Demo   Download Files

Turns out you can do it rather semantically. Just a header tag with an anchor link inside. Admittedly, it would be cool to do it with just the header tag but I wasn't able to figure out a way to get the layers all right with the text on top without the extra element.

<h1><a href="#">CSS-Tricks</a></h1>
h1 {
  text-align: center;
  color: white;
  text-transform: uppercase;
  padding: 1px;
  font-family: 'Raleway', cursive;
  font-weight: 100;
  position: relative;
  background: -webkit-linear-gradient(left, black, #eee, black);
  background: -moz-linear-gradient(left, black, #eee, black);
  background: -ms-linear-gradient(left, black, #eee, black);
  background: -o-linear-gradient(left, black, #eee, black);
}
h1:before {
  content: "";
  position: absolute;
  left: 50%;
  top: -50px;
  width: 600px;
  margin-left: -300px;
  margin-top: -220px;
  height: 600px;
  background: -webkit-radial-gradient(50% 50%, ellipse closest-side, #444, black);
  background: -moz-radial-gradient(50% 50%, ellipse closest-side, #444, black);
  background: -ms-radial-gradient(50% 50%, ellipse closest-side, #444, black);
  background: -o-radial-gradient(50% 50%, ellipse closest-side, #444, black);
  z-index: -1;
}
h1 a {
  background: black;
  display: block;
  padding: 20px;
  text-decoration: none;
  letter-spacing: 30px;
  color: white;
}

I listed out all the vendor prefixes here because using them is required in "real" usage and I worry about people copying and pasting pseudo code. But if you want to play around with this and don't want to deal with all that, the Dabblet demo doesn't need them as it uses Prefix Free.

I also added some animations to the demo just for fun.

View Demo   Download Files

Burst Title is a post from CSS-Tricks

New Course: Introduction to Web Typography


Nettuts+ 20 Jan 2012, 12:24 am CET

Web typography is accessible to everyone. If you’ve ever built or designed a web page, you’ve almost definitely turned your hand to web typography of some sort. As a discipline, typography has been practiced for hundreds of years, and as a result there are many lessons and conventions we can learn from.

Saying that, web typography is a bit like skiing. It’s unwise to just grab a couple of wooden planks and throw yourself down a black piste; you’ll develop bad habits and perhaps even break a bone. Before diving into your next web project, make sure you’ve at least considered the fundamentals.

I can’t help you with skiing, but I can help you with web typography. If you’ve never looked properly into the subject, or even if you need a refresher, Introduction to Web Typography is for you!


Free Preview Lessons


Overview

As with all Tuts+ Premium courses, we’ll start at the beginning, working through the basics and some terminology, before moving on to the practicalities. During the process we’ll build ourselves a demo web page which will highlight the theory we cover. Even if you’re not yet confident with HTML and CSS, each video comes with source files stepping off from where the previous video ended.

Take a look at the episodes listed below and be sure to check out the preview videos even if you don’t yet have a Premium subscription.

Lesson Overview This course comprises 11 helpful videos.

As with all Tuts+ Premium courses, each lesson has an accompanying forum where you can discuss ideas and questions which arise as you watch the videos.

Course Forum Get involved with the forum, where you can discuss each lesson.

Tuts+ Premium

The recently re-launched Tuts+ Premium is a service that provides top-tier training in a variety of creative fields. Whether you prefer books, visual training, or in depth tutorials, we have you covered. While we unfortunately can’t afford to provide the service for free, it’s only $19 a month – less than you’d spend on dinner.

I hope you’ll consider checking it out! In addition to learning a huge variety of new skills, it’s also a fantastic way to say thank you to Nettuts+.

From jQuery to JavaScript: A Reference


Nettuts+ 19 Jan 2012, 9:58 pm CET

Whether we like it or not, more and more developers are being introduced to the world of JavaScript through jQuery first. In many ways, these newcomers are the lucky ones. They have access to a plethora of new JavaScript APIs, which make the process of DOM traversal (something that many folks depend on jQuery for) considerably easier. Unfortunately, they don’t know about these APIs!

In this article, we’ll take a variety of common jQuery tasks, and convert them to both modern and legacy JavaScript.

Modern vs. Legacy – For each item in the list below, you’ll find the modern, “cool kids” way to accomplish the task, and the legacy, “make old browsers happy” version. The choice you choose for your own projects will largely depend on your visitors.


Before We Begin

Please note that some of the legacy examples in this article will make use of a simple, cross-browser, addEvent function. This function will simply ensure that both the W3C-recommended event model, addEventListener, and Internet Explorer’s legacy attachEvent are normalized.

So, when I refer to addEvent(els, event, handler) in the legacy code snippets below, the following function is being referenced.

var addEvent = (function () {
        var filter = function(el, type, fn) {
                for ( var i = 0, len = el.length; i < len; i++ ) {
                        addEvent(el[i], type, fn);
                }
        };
        if ( document.addEventListener ) {
                return function (el, type, fn) {
                        if ( el && el.nodeName || el === window ) {
                                el.addEventListener(type, fn, false);
                        } else if (el && el.length) {
                                filter(el, type, fn);
                        }
                };
        }

        return function (el, type, fn) {
                if ( el && el.nodeName || el === window ) {
                        el.attachEvent('on' + type, function () { return fn.call(el, window.event); });
                } else if ( el && el.length ) {
                        filter(el, type, fn);
                }
        };
})();

// usage
addEvent( document.getElementsByTagName('a'), 'click', fn);

1 – $('#container');

This function call will query the DOM for the element with an id of container, and create a new jQuery object.

Modern JavaScript

var container = document.querySelector('#container');

querySelector is part of the Selectors API, which provides us with the ability to query the DOM using the CSS selectors that we’re already familiar with.

This particular method will return the first element that matches the passed selector.

Legacy

var container = document.getElementById('container');

Pay special attention to how you reference the element. When using getElementById, you pass the value alone, while, with querySelector, a CSS selector is expected.


2 – $('#container').find('li');

This time, we’re not hunting for a single element; instead, we’re capturing any number of list items that are descendants of #container.

Modern JavaScript

var lis = document.querySelectorAll('#container li');

querySelectorAll will return all elements that match the specified CSS selector.

Selector Limitations

While nearly all relevant browsers support the Selectors API, the specific CSS selectors you pass are still limited to the capability of the browser. Translation: Internet Explorer 8 will only support CSS 2.1 selectors.

Legacy

var lis = document.getElementById('container').getElementsByTagName('li');

3 – $('a').on('click', fn);

In this example, we’re attaching a click event listener to all anchor tags on the page.

Modern JavaScript

[].forEach.call( document.querySelectorAll('a'), function(el) {
   // anchor was clicked
});

The above snippet looks scary, but it’s not too bad. Because querySelectorAll returns a NodeList rather than an Array, we can’t directly access methods, like forEach. This is remedied by calling forEach on the Array object, and passing the the results of querySelectorAll as this.

Legacy

var anchors = document.getElementsbyTagName('a');
addEvent(anchors[i], 'click', fn);

4 – $('ul').on('click', 'a', fn);

Ahh – this example is slightly different. This time, the jQuery snippet is using event delegation. The click listener is being applied to all unordered lists, however, the callback function will only fire if the target (what the user specifically clicked on) is an anchor tag.

Modern JavaScript

document.addEventListener('click', function(e) {
   if ( e.target.matchesSelector('ul a') ) {
      // proceed
   }
}, false);

Technically, this vanilla JavaScript method isn’t the same as the jQuery example. Instead, it’s attaching the event listener directly to the document. It then uses the new matchesSelector method to determine if the target – the node that was clicked – matches the provided selector. This way, we’re attaching a single event listener, rather than many.

Please note that, at the time of this writing, all browsers implement matchesSelector via their own respective prefixes: mozMatchesSelector, webkitMatchesSelector, etc. To normalize the method, one might write:

var matches;

(function(doc) {
   matches =
      doc.matchesSelector ||
      doc.webkitMatchesSelector ||
      doc.mozMatchesSelector ||
      doc.oMatchesSelector ||
      doc.msMatchesSelector;
})(document.documentElement);

document.addEventListener('click', function(e) {
   if ( matches.call( e.target, 'ul a') ) {
      // proceed
   }
}, false);

With this technique, in Webkit, matches will refer to webkitMatchesSelector, and, in Mozilla, mozMatchesSelector.

Legacy

var uls = document.getElementsByTagName('ul');

addEvent(uls, 'click', function() {
   var target = e.target || e.srcElement;
   if ( target && target.nodeName === 'A' ) {
      // proceed
   }
});

As a fallback, we determine if the nodeName property (the name of the target element) is equal to our desired query. Pay special attention to the fact that older versions of Internet Explorer sometimes plays by their own rules – sort of like the kid who eats play-doh during lunch time. You won’t be able to access target directly from the event object. Instead, you’ll want to look for event.srcElement.


5 - $('#box').addClass('wrap');

jQuery provides a helpful API for modifying class names on a set of elements.

Modern JavaScript

document.querySelector('#box').classList.add('wrap');

This new technique uses the new classList API to add, remove, and toggle class names.

var container = document.querySelector('#box');

container.classList.add('wrap');
container.classList.remove('wrap');
container.classList.toggle('wrap');

Legacy

var box = document.getElementById('box'),

    hasClass = function (el, cl) {
        var regex = new RegExp('(?:\s|^)' + cl + '(?:\s|$)');
        return !!el.className.match(regex);
    },

    addClass = function (el, cl) {
        el.className += ' ' + cl;
    },

    removeClass = function (el, cl) {
        var regex = new RegExp('(?:\s|^)' + cl + '(?:\s|$)');
        el.className = el.className.replace(regex, ' ');
    },

    toggleClass = function (el, cl) {
        hasClass(el, cl) ? removeClass(el, cl) : addClass(el, cl);

    };

addClass(box, 'drago');
removeClass(box, 'drago');
toggleClass(box, 'drago'); // if the element does not have a class of 'drago', add one.

The fallback technique requires just a tad more work, ay?


6 - $('#list').next();

jQuery’s next method will return the element that immediately follows the current element in the wrapped set.

Modern JavaScript

var next = document.querySelector('#list').nextElementSibling; // IE9

nextElementSibling will refer specifically to the next element node, rather than any node (text, comment, element). Unfortunately, Internet Explorer 8 and below do not support it.

Legacy

var list = document.getElementById('list'),
        next = list.nextSibling;

// we want the next element node...not text.
while ( next.nodeType > 1 ) next = next.nextSibling;

There’s a couple ways to write this. In this example, we’re detecting the nodeType of the node that follows the specified element. It could be text, element, or even a comment. As we specifically need the next element, we desire a nodeType of 1. If next.nodeType returns a number greater than 1, we should skip it and keep going, as it’s probably a text node.


7 - $('<div id=box></div>').appendTo('body');

In addition to querying the DOM, jQuery also offers the ability to create and inject elements.

Modern JavaScript

var div = document.createElement('div');
div.id = 'box';
document.body.appendChild(div);

There’s nothing modern about this example; it’s how we’ve accomplished the process of creating and injecting elements into the DOM for a long, long time.

You’ll likely need to add content to the element, in which case you can either use innerHTML, or createTextNode.

div.appendChild( document.createTextNode('wacka wacka') );

// or

div.innerHTML = 'wacka wacka';

8 – $(document).ready(fn)

jQuery’s document.ready method is incredibly convenient. It allows us to begin executing code as soon as possible after the DOM has been loaded.

Modern JavaScript

document.addEventListener('DOMContentLoaded', function() {
   // have fun
});

Standardized as part of HTML5, the DOMContentLoaded event will fire as soon as the document has been completed parsed.

Legacy

// http://dustindiaz.com/smallest-domready-ever
function ready(cb) {
        /in/.test(document.readyState) // in = loadINg
                ? setTimeout('ready('+cb+')', 9)
                : cb();
}

ready(function() {
   // grab something from the DOM
});

The fallback solution, every nine milliseconds, will detect the value of document.readyState. If “loading” is returned, the document hasn’t yet been fully parsed (/in/.test(). Once it has, though, document.readyState will equal “complete,” at which point the user’s callback function is executed.


9 – $(‘.box’).css(‘color’, ‘red’);

If possible, always add a class to an element, when you need to provide special styling. However, sometimes, the styling will be determined dynamically, in which case it needs to be inserted as an attribute.

Modern JavaScript

[].forEach.call( document.querySelectorAll('.box'), function(el) {
  el.style.color = 'red'; // or add a class
});

Once again, we’re using the [].forEach.call() technique to filter through all of the elements with a class of box, and make them red, via the style object.

Legacy

var box = document.getElementsByClassName('box'), // refer to example #10 below for a cross-browser solution
   i = box.length;
 
while ( i-- > 0 && (box[i].style.color = 'red') );

This time, we’re getting a bit tricky with the while loop. Yes, it’s a bit snarky, isn’t it? Essentially, we’re mimicking:

var i = 0, len;

for ( len = box.length; i < len; i++ ) {
   box[i].style.color = 'red';
}

However, as we only need to perform a single action, we can save a couple lines. Note that readability is far more important than saving two lines – hence my “snarky” reference. Nonetheless, it’s always fun to see how condensed you can make your loops. We’re developers; we do this sort of stuff for fun! Anyhow, feel free to stick with the for statement version.


10 – $()

Clearly, our intention is not to replicate the entire jQuery API. Typically, for non-jQuery projects, the $ or $$ function is used as shorthand for retrieving one or more elements from the DOM.

Modern JavaScript

var $ = function(el) {
        return document.querySelectorAll(el);
};
// Usage = $('.box');

Notice that $ is simply a one-character pointer to document.querySelector. It saves time!

Legacy

if ( !document.getElementsByClassName ) {
        document.getElementsByClassName = function(cl, tag) {
           var els, matches = [],
              i = 0, len,
              regex = new RegExp('(?:\s|^)' + cl + '(?:\s|$)');
         
           // If no tag name is specified,
           // we have to grab EVERY element from the DOM         
           els = document.getElementsByTagName(tag || "*");
           if ( !els[0] ) return false;

           for ( len = els.length; i < len; i++ ) {
              if ( els[i].className.match(regex) ) {
                 matches.push( els[i]);
              }
           }
           return matches; // an array of elements that have the desired classname
        };
}
 
// Very simple implementation. We're only checking for an id, class, or tag name.
// Does not accept CSS selectors in pre-querySelector browsers.
var $ = function(el, tag) {
   var firstChar = el.charAt(0);
 
   if ( document.querySelectorAll ) return document.querySelectorAll(el);
 
   switch ( firstChar ) {
      case "#":
         return document.getElementById( el.slice(1) );
      case ".":
         return document.getElementsByClassName( el.slice(1), tag );
      default:
         return document.getElementsByTagName(el);
   }
};

// Usage
$('#container');
$('.box'); // any element with a class of box
$('.box', 'div'); // look for divs with a class of box
$('p'); // get all p elements

Unfortunately, the legacy method isn’t quite so minimal. Honestly, at this point, you should use a library. jQuery is highly optimized for working with the DOM, which is why it’s so popular! The example above will certainly work, however, it doesn’t support complex CSS selectors in older browsers; that task is just a wee-bit more complicated!


Summary

It’s important for me to note that that I’m not encouraging you to abandon jQuery. I use it in nearly all of my projects. That said, don’t always be willing to embrace abstractions without taking a bit of time to research the underlying code.

I’d like this posting to serve as a living document, of sorts. If you have any of your own (or improvements/clarifications for my examples), leave a comment below, and I’ll sporadically update this posting with new items. Bookmark this page now! Lastly, I’d like to send a hat-tip to this set of examples, which served as the impetus for this post.

How To Integrate Facebook, Twitter And Google+ In WordPress


Smashing Magazine Feed 19 Jan 2012, 5:32 pm CET

  

Integrating social media services in your website design is vital if you want to make it easy for readers to share your content. While some users are happy with the social media buttons that come built into their design template, the majority of WordPress users install a plugin to automatically embed sharing links on their pages. Many of you will find that a plugin does exactly what you need; others not so much. Some are poorly coded, and most include services that you just don’t need. And while some great social media plugins are out there, they don’t integrate with every WordPress design.

The Big Three: Twitter, Facebook, and Google+

If you aren’t comfortable editing your WordPress templates, a plugin is probably the best solution. If you are comfortable making a few edits to your theme, then consider manually integrating social media so that you have more control over what services appear on your website.

Today, we’ll show you how to manually integrate the three most popular social media services on your website: Twitter, Facebook and Google+. First, you’ll learn how to integrate Facebook comments on your WordPress website, to make it easier for readers to discuss your posts. Then, we’ll show you the most common ways to display your latest tweets in the sidebar, which should encourage more people to follow you on Twitter. Finally, we’ll show you how to add sharing buttons for all three social media services to your home page, posts and pages.

Please make sure to back up all of your template files before making any changes, so that you can revert back if something goes wrong. Testing your changes in a non-production area first would also be prudent.

Integrate Facebook Comments On Your Website

Because most people are signed into Facebook when they browse the Web, enabling Facebook comments on your website is a great way to encourage people to leave comments. It also curbs spam. While many solutions purport to reduce spam comments on WordPress, most are either ineffective or frustrate visitors by blocking legitimate comments.

Feature-rich commenting solutions such as IntenseDebate and Disqus have benefits, of course, because they allow users to comment using Facebook and a number of other services; but before visitors can comment, they have to grant access to the application, an additional step that discourages some from commenting. By comparison, integrating Facebook comments directly enables visitors to comment with no fuss. Also, this commenting system allows users to comment by signing into Facebook, Yahoo, AOL or Hotmail.

Before integrating Facebook on WordPress Mods at the end of September, I looked at a few solutions. I followed a great tutorial by Joseph Badow and tried a few plugins, such as Facebook Comments For WordPress. The reality, though, is that the official Facebook comment plugin is the quickest and easiest way to add Facebook comments to your website.

Simply follow the steps below to get up and running.

1. Create a Facebook Application

To use Facebook comments on your website, create a new comment application for your website on the Facebook Application page. This step is required, whether you add Facebook comments manually using a third-party plugin or with the official Facebook plugin.

Simply click on the “+ Create New App” button on the Facebook Application page, and enter a unique name for your application in the “App Display Name” field. The “App Namespace” field doesn’t have to be filled in for Facebook comments (it’s used with the Facebook Open Graph Protocol).

Create Facebook App

You will then be provided with an “App ID/API key” and an “App secret key.” You don’t need to remember these numbers because the official Facebook comments plugin automatically inserts them into the code that you need to add to your website.

Create Facebook Application

2. Add the Code to Your Website

Next, go back to the Facebook Comments plugin page and get the code for your website. The box allows you to change the URL on which comments will be placed, the number of comments to be shown, the width of the box and the color scheme (light or dark).

Customise Facebook

You don’t have to worry about what you enter in the box because all of the attributes can be modified manually. And it doesn’t matter what URL you enter because we will be replacing it later with the WordPress permalink:

  • href The URL for this Comments plugin. News feed stories on Facebook will link to this URL.
  • width The width of the plugin in pixels. The minimum recommended width is 400 pixels.
  • colorscheme The color scheme for the plugin (either light or dark).
  • num_posts The number of comments to show by default. The default is 10, and the minimum is 1.
  • mobile (beta) Whether to show the mobile version. The default is false.

When you click on the “Get Code” button, a box will appear with your plugin code (choose the HTML5 option, because FBML is being deprecated). Make sure to select the application that you set up earlier for your comments so that the correct application ID is added to the code.

Get Facebook Application Code

Insert the first piece of code directly after the <body> tag in your header.php template:

<div id="fb-root"></div>
<script>(function(d, s, id) {
var js, fjs = d.getElementsByTagName(s)[0];
if (d.getElementById(id)) return;
js = d.createElement(s); js.id = id;
js.src = "//connect.facebook.net/en_GB/all.js#xfbml=1&appId=YOURAPPLICATIONID";
fjs.parentNode.insertBefore(js, fjs);
}(document, 'script', 'facebook-jssdk'));</script>

Put the second line of code where you want to show the comments. Make sure the static URL is replaced with the WordPress permalink (<?php the_permalink() ?>) so that comments show correctly on every page of your website.

<div class="fb-comments" data-href="<?php the_permalink() ?>" data-num-posts="15" data-width="500"></div>

To put Facebook comments above WordPress comments, add the above code just below the line that reads <!-- You can start editing here. --> in the comments.php template. To put Facebook comments below WordPress comments, add the above code below the </form> tag (again in the comments.php template).

If you plan to completely replace your WordPress comments with Facebook comments, simply replace the call to your comments.php template with the call to your Facebook comments. For example, to replace comments in posts, simply add the code to the single.php template. Similarly, edit the page.php template to show Facebook comments on pages.

Facebook Comments

Your should now see the Facebook comments box displayed on your website. To get an update whenever someone leaves a comment using Facebook, add yourself as a moderator to your application on the Comment Moderation tool page.

Show Your Latest Tweets In The Sidebar

Displaying your latest tweets is a good way to encourage people to follow you on Twitter. The most common place to display tweets is in the sidebar, although you can add them to any area of the website.

Display Your Latest Tweets Manually

I have tried a few manual solutions for showing tweets on my websites, and my favorite comes from Chris Coyier of CSS-Tricks. His RSS fetching snippet is a quick and effective way to show the latest tweets from your account. The RSS address of your Twitter account is http://api.twitter.com/1/statuses/user_timeline.rss?screen_name=xxxxx (where xxxxx is your Twitter user name). For the tweets that you favorite, use http://twitter.com/favorites/xxxxx.rss. For example, the RSS for the latest tweets from Smashing Magazine is http://api.twitter.com/1/statuses/user_timeline.rss?screen_name=smashingmag; and to display only the favorites, https://twitter.com/favorites/smashingmag.rss. Once you’ve got your Twitter RSS address, simply add it to Chris’ PHP snippet.

<?php
include_once(ABSPATH . WPINC . '/feed.php');
$rss = fetch_feed('https://api.twitter.com/1/statuses/user_timeline.rss?screen_name=smashingmag');
$maxitems = $rss->get_item_quantity(3);
$rss_items = $rss->get_items(0, $maxitems);
?>

<ul>
<?php if ($maxitems == 0) echo '<li>No items.</li>';
else
// Loop through each feed item and display each item as a hyperlink.
foreach ( $rss_items as $item ) : ?>
<li>
<a href='<?php echo $item->get_permalink(); ?>'>
<?php echo $item->get_title(); ?>
</a>
</li>
<?php endforeach; ?>
</ul>

For a more stylish way to display tweets manually, check out Martin Angelov’s tutorial “Display Your Favorite Tweets Using PHP and jQuery,” or Sea of Cloud’s “Javascript Plugin Solution.”

Display Your Latest Tweets Using the Official Twitter Widget

The official Twitter profile widget looks great and is easy to customize. You can define the number of tweets to display and whether the box should expand to show all tweets or provide a scroll bar.

The dimensions can be adjusted manually, or you can use an auto-width option. The color scheme can easily be changed in the settings area, too. Once the widget is the way you want it, simply grab the code and add it to the appropriate WordPress template.

Official Twitter Profile Widget

Display Your Latest Tweets Using a WordPress Plugin

If you don’t want to code things manually or use the official Twitter profile widget, you could try one of the many plugins available:

Add Social-Media Sharing Buttons To Your WordPress Website

Adding social-media sharing and voting buttons is very straightforward and enables readers to share your content on the Web. Simply get the code directly from the following pages:

The buttons you get from the above links work well when added directly to posts (single.php) and pages (page.php). But they don’t work correctly on the home page (index.php) or the archive (archive.php) by default, because we want to show the number of likes, pluses and retweets for each individual article, rather than the page that lists the article. That is, if you simply add the default code to index.php, every button will show the number of shares for your home page, not for each article.

To resolve this, simply make sure that each button uses the article permalink, rather than the URL of the page it is on. To add sharing buttons only to posts, simply choose the button you want from the links above and copy the code to single.php; to add the buttons only to pages, just add the code to page.php.

To show the number of likes, pluses and retweets that an article has on the home page and in the archives, follow the steps noted below for Facebook, Google+ and Twitter below (the code for showing a sharing button on the index page will work for posts and pages, too). You can see an example of sharing buttons integrated in post excerpts on my own website WordPress Mods and on popular blogs such as Mashable.

Social Media Sharing Buttons Example

Facebook

Facebook’s Like button comes with a lot of options. Choose from three layouts: standard, button count and box count. An email button (labelled “Send”) can be added, and you can set the width of the box, too. You can also show profile pictures below the button, choose between the labels “Like” and “Recommend,” choose between a light and dark color scheme, and set the font.

Customise Facebook

You need to add two pieces of code to your website. First, add the JavaScript SDK code directly after the <body> tag (in the header.php template). This code has to be added only once (i.e. if you’ve already added the code to show Facebook comments on your website, you don’t need to add it again).

Put the second piece of code where you want to show the Like button. To ensure that the correct page is referenced, add href="<?php echo get_permalink($post->ID); ?>" to the second piece of code. It should look something like this:

<div class="fb-like" data-href="http://www.facebook.com/smashmag" href="<?php echo get_permalink($post->ID); ?>" data-send="false" data-layout="box_count" data-width="450" data-show-faces="true" data-font="arial"></div>

More information on how to customize the Like button can be found on the Facebook Like Button page.

Google+

Google+ offers four sizes of sharing buttons: small, medium, standard and tall. The number of votes that a page has received can be shown inline, shown in a bubble or removed altogether.

Customise Google+

Linking to your article’s permalink is very easy. Just append href="<?php the_permalink(); ?>" to the g:plusone tag. For example, to show a tall inline Google+ button, you would use the following code:

<!-- Place this tag where you want the +1 button to render -->
<g:plusone size="tall" annotation="inline" href="<?php the_permalink(); ?>"></g:plusone>

<!-- Place this render call where appropriate -->
<script type="text/javascript">
(function() {
var po = document.createElement('script'); po.type = 'text/javascript'; po.async = true;
po.src = 'https://apis.google.com/js/plusone.js';
var s = document.getElementsByTagName('script')[0]; s.parentNode.insertBefore(po, s);
})();
</script>

For more tips on customizing the Google+ button, please view the official Google+ button documentation page.

Twitter

Twitter offers four types of buttons: one for sharing links, one for inviting people to follow you, a hash tag button for tweeting stories, and another for mentions (used for contacting others via Twitter). The button you need to show the number of shares that an article has gotten is called “Share a link.”

On the button customization page, you can choose whether to show the number of retweets and can append “Via,” “Recommend” and “Hashtag” mentions to the shared link.

Customise Twitter

To make sure Twitter uses the title of your article and the correct URL, simply add ata-text="<?php the_title(); ?>" and data-url="<?php the_permalink(); ?>" to your link. For example, if you were using the small button, you would use:

<a href="https://twitter.com/share" class="twitter-share-button" data-via="smashingmag" ata-text="<?php the_title(); ?>" data-url="<?php the_permalink(); ?>">Tweet</a>
<script>!function(d,s,id){var js,fjs=d.getElementsByTagName(s)[0];if(!d.getElementById(id)){js=d.createElement(s);js.id=id;js.src="//platform.twitter.com/widgets.js";fjs.parentNode.insertBefore(js,fjs);}}(document,"script","twitter-wjs");</script>

To show the larger button instead, simply append data-size="large" to the link. To show the popular vertical button (shown below) instead of the default horizontal button, append data-count="vertical" to the link.

Twitter Vertical Button

For more tips on customizing the Twitter button, please view the official Twitter button documentation page.

Summary

Many WordPress users continue to use plugins to integrate social-media sharing buttons and activity on their websites. As we’ve seen, though, integrating social-media services manually is straightforward and, for many users, a better solution than simply installing a plugin and making do with whatever features it offers.

Integrating Facebook comments on your website takes only a few minutes and is much less complicated than any of the available plugins. While good tutorials are available that show you how to manually add Twitter to your website, the official widget from Twitter is the best all-around solution for most websites.

Some fantastic plugins exist for WordPress to automatically insert social-media voting buttons in your design. Installing and setting them up takes only a few minutes, although manually adding the buttons enables you to give them maximum visibility.

Remember, play it safe and make any changes in a test area first before applying the changes to the live website. I also recommend backing up all of your template files before changing anything (and your database if required). A few minutes of preparation could save you hours of troubleshooting, so try not to skip this step.

Hopefully, you’ve found this useful. If you are unsure of any aspect of this tutorial, please let us know and we’ll do our best to clarify the step or help you with it. Also, subscribe to Smashing Magazine via RSS, Twitter, Facebook or Google+ to get the latest articles delivered directly to you.

(al)


© Kevin Muldoon for Smashing Magazine, 2012.

More