Advomatic

Submission of a form on this page has been disabled as you do not have JavaScript enabled in your browser.
Syndicate content
Updated: 1 hour 29 min ago

A lesson in the usefulness of CSS sprite generators

Wed, 02/03/2010 - 16:40

The basic premise of a sprite image is to consolidate your site's graphics into one (or more) master image file. Then, with the magic of CSS's background-position property, you can shift the master sprite image around and only reveal the parts you want. Like a window. Some might even say like a Sliding Door.

What are the benefits of sprites? There are a few very good reasons to use this method.

Manageability

If you use a ton of images, keeping them in a few master sprite images keeps them manageable. Adding new images to your sprite is just a matter of finding space on the sprite image and putting it there, then taking the x/y coordinates and using them as the background-position to get your new image to show up where you need it to. Rather than create one huge sprite for this site, breaking them up into a few different ones is a good idea. First, you do not want to end up with a 500kb+ final image that will make your users sit and wait while it loads up every image for your site at once. Second, you can categorize your images. For example, on a recent project, I had four main sprites: one for background images, one for icons, one for buttons (including hover/active states) and one for text images that were being used for block titles and whatnot.

Reducing your HTTP request overhead

Anyone who has done work on a high-traffic, high-profile site knows that you want to reduce the amount of HTTP requests that are made as the page loads. One frequent offender here is CSS background images that are requested from the server. If you tend to do a lot of CSS background-image work, each one of those images is requested from the server on page load. These requests will make your fellow developers sad as they attempt to tweak the site for maximum efficiency and performance. Instead of having a bajillion little CSS background images loaded, why not throw them all into sprites and keep your fellow developers happy?

A great way to figure out how severe this problem may be is to get the YSlow for Firebug extension for Firefox: http://developer.yahoo.com/yslow/

This awesome little tool will show you exactly how many CSS images are being loaded and specifically which images are the problem. The goal is to reduce that number and in turn, give your site a higher Yslow grade.

Commonly-used generators

We want to use sprites to help speed the site up, but there are times building the sprite manually by arranging each image on a sprite (in addition to collecting x/y coordinates for each) looks like it will be a very tedious task. In come several popular CSS generators to the rescue. Here are a few that seem like good candidates:

  • http://spritegen.website-performance.org
    Lots of tweakable options, an easy to use interface and open source. You can also install locally and run it from your server to bypass their .5MB upload limit on images.
  • http://www.csssprites.com
    This one is fairly bare bones. It looks like it would be useful if you don't need anything fancy.
  • http://csssprites.org
    SmartSprites uses a different approach to spriting, in which you annotate your CSS files to specify which images should be included in the final sprite, and the code is generated within your own CSS files. The main benefit to this method is that there is no copy/pasting CSS for each generated sprite image into your CSS file, it all runs on the fly, and automatically handles things when images are added, removed or changed. The downside is that there appears to be a learning curve to usage beyond traditional spriting, as well as the fact that it must be installed and run locally, command line style.

(Note: there is also the CSS Sprite Generator module, which I did not try out because it's only available for Drupal 5.)

Best time for a sprite generator?

The best time to use a sprite generator is when you are handed HTML/CSS from a different vendor, or any other situation where you haven't been around since Day One on the project. When you have tons of images in your image directory, and most of them are being used as background-images in the CSS, this is a good time to optimize your theme with the help of a generator. In the project I mentioned earlier, this was the case. I ended up using the generator from http://spritegen.website-performance.org due to the fact that there was no real learning curve and we needed to get our site optimized for load times quickly.

There are several situations where a generator can choke and you have to step in and fix things manually, such as when you want to repeat an image horizontally. I've found that the best approach is to create special sprites for images that will be repeated in the background. These images will usually not repeat correctly if the generator places them within a sprite with other non-repeating images.

The verdict

If this is not the case and you are doing the markup/CSS production work, I recommend learning how to build sprite images on your own, from the start of the project. Not only does it give you fine control over where you want to place your images within the sprite, it also will save you a good chunk of time trying to untangle someone else's CSS (as well as rigorous testing to make sure the generator correctly placed images and created CSS). Turn on the grid in your graphic program and make use of "Snap to Grid", this will give you consistent X and Y coordinates for your CSS. For example, set the grid to every 10 pixels, and you'll be able to easily drag in your images onto the sprite and place it where you want. Coming up with the X/Y coordinates is a lot easier since you won't have to zoom in at 10000x magnification to verify the exact location where your image is located.

Homebrewing your sprites is not only a great skill to learn, it should be standard procedure for any site you want optimized for performance, small or large.

Categories: Drupal

Theming the User Login Block

Thu, 01/21/2010 - 18:12

Don't want people to look at your site and immediately know it is Drupal? Theme your user login block!

While it isn't always your top priority, customizing the look and feel of the login form helps maintain the integrity of a custom design. In this post, I'll get you started using both CSS and PHP to manipulate the form's elements in Drupal 6 - on the login block.
<!--break-->
Using CSS to style the Login Block

The easiest way to make changes to your login form is with CSS. If you have Firebug installed in your Firefox browser, you can pop it open to look at the HTML of the form itself. Let's look at the HTML of the login block (simplified a little):

<div class="block block-user" id="block-user-0">
  <h2>User login</h2>
  <div class="content">
    <form id="user-login-form" method="post">
      <div>
        <div id="edit-name-wrapper" class="form-item">
          <label>Username: <span class="form-required">*</span></label>
          <input type="text" class="form-text required" value="" size="15" id="edit-name" name="name" maxlength="60">
        </div>
        <div id="edit-pass-wrapper" class="form-item">
          <label>Password: <span class="form-required">*</span></label>
          <input type="password" class="form-text required" size="15" maxlength="60" id="edit-pass" name="pass">
        </div>
        <input type="submit" class="form-submit" value="Log in" id="edit-submit" name="op">
        <div class="item-list">
          <ul>
            <li class="first">
              <a title="Create a new user account." href="/user/register">Create new account</a>
            </li>
            <li class="last">
              <a title="Request new password via e-mail." href="/user/password">Request new password</a>
            </li>
          </ul>
        </div>
        <input type="hidden" value="form-9e4b8b6b59b15e9ce5b527ab94185021" id="form-9e4b8b6b59b15e9ce5b527ab94185021" name="form_build_id">
        <input type="hidden" value="user_login_block" id="edit-user-login-block" name="form_id">
      </div>
    </form>
  </div>
</div>

With CSS, you can do the bulk of changing the way the form looks: color, font, size, using a custom image for your button, or changing the border of the input fields. Open the custom CSS file of your theme and create a new section for your login form:

/*
* User login form.
*/

Here's CSS for changing the Log in button, for example:

#user-login-form .form-submit {
  background: transparent url(images/my_button.png) no-repeat scroll left top;
  border: 0 none;
  cursor: pointer; /* cursor turns to a hand upon hover */
  display: block;
}

Or add a hover style to your button:

#user-login-form .form-submit:hover {
  background-image: url(images/my_button_hover.png);
}

Or give your inputs custom background and hide the generic input fields:

#user-login-form .form-item {
  background: transparent url(images/my_input.png) no-repeat scroll left top;
}

#user-login-form .form-item input {
  background-color: transparent;
  border: 0;
}

If you want to add to or change the HTML that wraps around the <form></form> tags, you can make a custom template called block-user-0.tpl.php in your theme. This, however, will not allow you to manipulate any of the form elements.

Hint: block template names are suggested by their ID tags -- so you can see the ID of this block from the above HTML is block-user-0, hence the block-user-0.tpl.php file name.

Altering the Form's HTML

CSS will take you pretty far, but say you want to change the structure of that HTML inside the <form></form> tags. You'll need to override the form in your template.php file.

Altering the form is a two-part process.

First, you will need to find your form's ID. For any Drupal form, you will find it inside a hidden input that includes the attribute name="form_id". The VALUE of that input is your form ID. If you look in the HTML above, you will see the value of that the input is "user_login_block".

Now we need to register the override function with the theme system in your template.php file.

<?php
/**
* Implementation of hook_theme.
*
* Register custom theme functions.
*/
function themename_theme() {
  return array(
    // The form ID.
    'user_login_block' => array(
      // Forms always take the form argument.
      'arguments' => array('form' => NULL),
    ),
  );
}
?>

Make sure to clear your theme registry by visiting /admin/settings/performance.

Hint: You will notice that it's annoying to theme a login form (which you only see when you are logged out) when you need to keep clearing the registry (which you can only do when logged in). Instead of logging in & out repeatedly or having two browsers open, try using Firefox's Stealther extension. It lets you easily toggle between being logged in and logged out.

At the bottom of template.php, add your form overrides.

/*
FORM OVERRIDES
*/

/**
* Theme override for user login block.
*
* The function is named themename_formid.
*/
function themename_user_login_block($form) {
  // Add your overrides here.
}

You can take a look at what you can manipulate by adding print_r($form); or, if you have the Devel module enabled, dpm($form);. Place it after any overrides if you want to see any changes you have made in the printout.

Hint: To use dpm on a form that you only see when you are logged out, you'll need to change permissions on the devel module at /admin/user/permissions. Allow anonymous users to use the devel module -- but make SURE to change this when you are done testing!

Let's try changing a few items and see how it looks now:

/**
* Theme override for user login block.
*
* The function is named themename_formid.
*/
function themename_user_login_block($form) {
  $form['name']['#title'] = t('your username'); //wrap any text in a t function
  $form['pass']['#title'] = t('your password');
  $form['pass']['#suffix'] = t('<em>Enter your password above.</em>');
  unset($form['links']['#value']); //remove links under fields
  return (drupal_render($form));
}

If you only have a few overrides, this is the way to go. However, if you have a form that you need to completely rewrite (probably not the case for the login form, but perhaps a content form), you can consider making a template for it. However, templated form overrides do render five times slower than overrides done in template.php.

I'll address that option in my next blog entry!

Categories: Drupal

Quick and easy Congressional District lookups for your CiviCRM contacts

Tue, 01/19/2010 - 18:39

By definition CiviCRM is used by many organizations in the political sphere. For those organizations working in the US one useful metric to have on your contacts is their congressional district. Up until now this has usually been accomplished with either custom code, or exporting your contacts, sending them through a bulk lookup tool, and re-importing them. There is now an easier way to get this with the CiviCRM Sunlight Congressional District module. Yes the name is long but verbosity is perhaps better than obscurity when naming your open source project* (Login Toboggan and Deadwood I'm looking at you).

As the name implies this module integrates with the excellent Sunlight API. The Sunlight API is a way for developers to easily fetch information about congressional districts and the members of congress that represent them. With this module you can now integrate this into CiviCRM with ease:

  1. Enable the module
  2. Create some custom fields in CiviCRM to store the congressional district
  3. Tell the module about your fields
  4. Watch as the module fetches information from Sunlight

The module also exposes its own API so that you can go even further to fit your site's needs (list all users in a district, show the members of congress for a district, etc. ). As an example of how to utilize this API it includes an additional module called "Congress" that provides a user tab showing the user's congress members, and a directory of all your user's districts.

The module is currently in Beta. There's some polishing that needs to be done to make the module useful in a wide variety of use cases. But don't let that hold you back. The module is used in production on at least one major site and has already done several hundred thousand lookups.

* The downside to such a long name is that through the rest of this blog post I need to refer to it as "the module" :P

This has been cross-posted to civicrm.org

Categories: Drupal