<About />

My name is Kevin. I am a web professional living in Massachusetts. I build websites mostly using Drupal and jQuery. I use Vim even when I don't need to. When I'm not on the computer, I'm usually hanging with my wife, Melissa.

<Search />

Kevin Hankens's blog

Keeping an eye on memory usage

So, while working on a project recently we were faced with the reality that Drupal was using too much memory for our server to handle. The culprit was an AJAX refresh script that helped us to keep the page content up-to-date without refreshing. We had spent a good amount of time tuning the amount of processing and bandwidth used by the module, but the Drupal full bootstrap was just killing us with a 10 second refresh rate.

The solution we settled on was to not bootstrap Drupal if it wasn't necessary. We implemented a preliminary PHP script that the AJAX request was first passed to. This script opened a MySQL connection and ran a single query to check for updated content. If there was none, the script returned empty JSON. If content was found, then Drupal was fully bootstrapped to load the content and return a full JSON structure with the new content.

The results shouldn't be surprising, but still blew me away. Using the PHP function memory_get_peak_usage() we were able to see just how much memory the scripts were using at the point where the JSON was returned. When new content was found and Drupal bootstrapped PHP used 16961212 bytes (16.18 MB) of memory, but when there was no new content, the intermediate script only used 86968 bytes (84.9 KB) of memory.

Read more for the code...

Drupal, jQuery and $.ajax() easyness.

So, I've been remiss in my blogging as of late. It's not for a lack of ideas though, so I'm going to jump right back in with something cool that I've been using a lot lately. Once again, I'm just astounded at how insanely easy jQuery makes my life. I've been reading Resig's book on the train this week and the main thing I'm learning is just how important it is to have Javascript frameworks like jQuery. There are so many nuances between major browsers - even the "modern" ones - that it would be ridiculous to try and account for them yourself when these frameworks already do such a great job.

I've written before about doing modals using the popups api and it sounds like there is some goodies in ctools. Though, sometimes you just need laser precision to accomplish one specific task to meet a clients requirement. In these cases, I'm not at all opposed to writing a quick module.

Let's say you need a really simple module that provides a link to trigger something on the back end of your site and returns a response without a page refresh. This type of thing is super common these days and jQuery makes it oh-so-simple to implement.

Read on for the code...

Welch-Dickey Loop

Here's a quickie panorama from last weekend's hike around the Welch-Dickey loop on the southern side of the White Mountain National Forest. What a beautiful day to be out in the woods!

Rapid voicemail prompt

How many of you are sick of having to wait through five minutes of voicemail instructions when you call someone? I know I am. Do the world a favor and check out the following link with instructions on how to remove the instructions from your voicemail greeting (make sure to read the comments for other carriers):

Engadget.com

-- Edit --

Whoa, apparently this is a pretty big movement!

NYTimes.com

Adding help text to your Drupal forms using the Popups API

It seems fairly often that I put links into Drupal help text. It's a great way to show some extended descriptions or direct people to administrative options. The only annoying thing is that it really disrupts the UX. If you are entering a new node, you risk leaving an unsaved form. If you use target="_blank" then you risk confusion by having multiple windows open. So, after reading Gábor's post on D7UX overlays I decided to try out the Popups API module to solve this annoying problem.

So, now I am absolutely in love with the Popups API. It provides a great way to show contextual help and even let users execute administrative forms without losing their place. For example, I've run into a few situations where I'm using a CCK nodereference field and thought it would be awesome to create the referenced node without leaving the /node/add form. Now it becomes simple - the Popups API allows you to create an elegant javascript popup that doesn't have a negative effect on the UX. The popup can contain any page content on your site - a new node/add form, a custom page, etc. If you want to get crazy, you can even set up the popups to refresh or effect the parent page.

For example click here to leave a comment. [Planet Drupal readers will have to click through to my site to see this example]

The installation isn't too bad, but make sure that you check out the README.txt file that comes with the module. Once you enable the module, you will have to make sure that you have a container <div> around your $content variable in page.tpl.php - this will filter out the extraneous parts of your theme and only show the important parts in the popups. Next you have to specify the selector of that container <div> in your global theme settings. Finally, you need to do one of three things to make it work: 1) enable popup scanning on all pages (located in the admin settings), 2) call popups_add_popups() somewhere in a module callback, 3) add one of the popups classes to your anchor tag. The available popup classes will determine how the popup interacts with the parent page. Again, check out the README.txt for all of the details.

Also, be sure to watch the screencast on the Popups API project page to really see how cool this module is. You can use these popups to show any number of things. For example, you could create a wiki page that your administrators can edit, then link to that node from help text so that editors can maintain their own help text with notes. You could even build administrative views with bulk operations, or link to a user creation form. If you have ever had someone ask: "can I do this without leaving the page?" then this is a great module for you.

The coolest part is that this doesn't even scratch the surface of what you can do with these popups. It's a very exciting time for Drupal UX and I'm totally excited to see these things find their way into core.

Drupal/Vim users, highlight your .module files

I live in Vim, but finally got tired of editing my .module files without syntax highlighting - ugh. Turns out all you have to do is tell vim what the file is so that it knows what to shade.

Make sure that the following is in your vimrc file - notice the filetype on line:

" Switch syntax highlighting on, when the terminal has colors
" Also switch on highlighting the last used search pattern.
filetype on
if &t_Co > 2 || has("gui_running")
  syntax on
  set hlsearch
endif

Then place the following in ~/.vim/filetype.vim, restart Vim and you are all set!

"  ~/.vim/filetype.vim
" tell Vim what a .module file is
if exists("did_load_filetypes")
  finish
endif
augroup filetypedetect
  au! BufRead,BufNewFile *.module               setfiletype php
augroup END

Proud of my Dad

I got a nice surprise today. My Dad, who just received his first personal computer as a gift from Jeff, called me on Skype. It was his second unaided video chat ever (Jeff appropriately got the first ;) I have to say that I was a little amazed, but there is a popular theory that he just plays dumb with computers. Anyway, I think that he's got a bright future as a geek!

Just got back in town from our wedding back in Iowa. Thus the ungeeklike lapse in blogs and tweets this past week. I promise a whole spread of photos as soon as they arrive!

Creating a colorable theme

I've always been fascinated by the color module. If you've ever selected a color palette for the Garland theme, you know how cool this module is. So a couple of weekends ago I decided to buckle down and figure it all out. It wasn't the easiest module to learn, but I have to say it felt really, really good when I finally got it to work. It's not overly complicated, but there are a lot of configurations to keep track of.

I kind of liked my experimental theme, so I started using it for myself and contributed it on drupal.org as Aquanaut.

If you want to get started with the color module, I highly recommend reading this doc page. It covers all of the basics. A couple of things that I learned:

  • Format your CSS file so that multiple CSS selectors/pseudo classes are on the same line:
      /** Don't use this format **/
      a:link,
      a:visited {
        color: #336699;
      }
     

      /** Use this format instead **/
      a:link, a:visited {
        color: #336699
      }
     
  • The first color palette in the schemes array in color.inc simply defines the color picker values. If you select the default (first) color pallette, color module ignores it and loads the style.css and images from your theme directory.
  • A really easy way to create default theme images is to set up the base.png and color.inc, pick a color palette using the color module, save the changes, then copy the images from your files/color directory into your theme directory.
  • Each fill color can only be used once, so organize your base.png wisely if you need to use a color for two different image slices.

Happy theming!

What's with the new design?

Yes, the colors are a bit much, but it's a very exciting design for me. This is my first theme using Drupal's color module. I've been meaning to learn how to use it for quite some time. So, last weekend I sat down and decided to not get up until I had it down. This was no small task as this was one of the more complicated Drupal APIs that I have yet to learn. It's not that difficult to understand, there are just a lot of moving parts. I'll do a more extensive blog post about the inner workings of the theme, but in short, you can pick the background color, link and text color, and pick a gradient for the top-right block using a simple color picker. I'm hoping to polish this one up and submit it to drupal.org as my first contrib theme!

DrupliconOne of the most fun parts of the project was to create a colorable Druplicon. I traced some of the highlights and shadows from the Druplicon in Illustrator, then added these to my base.png for the color module. Now, when you color your theme, the Druplicon becomes the same color as your site links!

I'm super excited about having this in my arsenal because it provides some elegant, helpful features when handing off a site to a non-technical administrator. You really don't even need the complicated background images. You can use the color module for something as basic as just letting them select the link and text colors. Very cool stuff!!

Using Drupal's Batch API

I don't know how I went so long without implementing Drupal's Batch API, but finally had a chance to play with it yesterday and had a Drupal Aha! moment. This particular API is very handy and surprisingly easy to implement.

We've been working on a way to synchronize a bunch of development environments using SVN and make it quick to deploy a new install of the site we're working on. The first step was to use the Import/Export module to dump content types, views and taxonomy definitions to text files. This way we could commit them to the repository and quickly build the framework for a fresh install of the site. Just install Drupal, then run the import function for the content types, views and taxonomies.

This was all great until we started exporting complex content types. It turned out that the system would fail if we tried to do more than one at a time, which meant going through the tedious effort of exporting... one... at... a... time.

Batch API to the rescue!

The Batch API module lets you easily set a batch of callbacks that Drupal will run one at a time, thus avoiding script timeouts for laborious tasks. The batch can be naturally set up in your form submit handler, or can be called in any other function by adding one extra line of code.

<?php
// Set up the Batch API
$batch = array('operations' => array(),
 
'finished' => '',
 
'title' => t('Exporting to files'),
 
'init_message' => t('Starting the export'),
 
'progress_message' => t('Exported @current out of @total'),
 
'error_message' => t('An error occurred and some or all of the exports have failed.'),
);
?>

Add as many functions to the batch queue as you need:

<?php
// Add an array declaring the callback function for your
// batch process and an array of callback arguments
$batch['operations'][] = array('your_batch_function', array($arg1, $arg2));
// add whatever logic you need
$batch['operations'][] = array('another_batch_function', array($arg1, $arg2));
?>

Tell the Batch API that you are finished:

<?php
if (!empty($batch['operations'])) {
 
batch_set($batch);
 
// batch_process() only needed if not inside a form _submit handler :
 
batch_process();
}
?>

drupal_execute() is not happy

One problem that I ran into along the way was the discovery that drupal_execute() has some compatibility issues with the Batch API. If I tried to use drupal_execute() in my batch callbacks, it would fail. Luckily there was a link to this tip to pause the batch that allowed the batch functions to use drupal_execute() with no complaints.

<?php
function your_batch_function($arg1, $arg2) {
 
// Pause the batch
 
$batch =& batch_get();
 
$ref = $batch;
 
$batch = null;

 
// run your code with drupal_execute()

  // Unpause the batch
 
$batch = $ref;
}
?>

Batching makes me happy

So, I just got done batch exporting 88 items including 19 super complex content types, 64 views and 4 vocabularies (one containing over 100 terms) and all it only took a few clicks. The Batch API is an amazing time saver. Combining it with some other awesome community tools like Import/Export gives me time to go take a much needed coffee break :)