Drupal 6 Development Can Be A Caching Pain

druplicon_small.pngDrupal provides some great caching tools to improve page loading performance. Production sites see huge speed increases because of caching. But, when a site is being developed caching can quickly turn into a nightmare. For example, when you add a new theme override function your to template.php file it isn't picked up right away and you may end up banging your head wondering what's going on. Or, when your developing filter code your filtered content may be cached. Going to the performance setting page and clearing the cache is annoying and a work flow problem. So, let's look at a couple simple solutions that can make development a little easier and less painful.

Cache Disable Module

Drupal wiz kid Dmitri Gaskin created the Cache Disable module which does just as it's name suggests. While some solutions clear the cache on every page load this module disables it. During development this is a great tool to use.

Clearing The Cache In Your Code

If you just want to clear part of the cache during development you can use some code snippets to do just that. For example, if you are developing a theme and just don't want the theme information to stay in the cache you could call drupal_rebuild_theme_registry() in your theme to rebuild the theme cache on every page load. A simple way to do this would be to add the following code snippet to the bottom of your page.tpl.php file.

<?php
  drupal_rebuild_theme_registry
();
?>

Other cache clearing functions you can use are cache_clear_all(), menu_rebuild(), and drupal_flush_all_caches(), which clears all possible caches including those that contributed modules use with the caching system.

Once the sites are ready for production these functions or modules we added should be removed so we can get all the caching benefits.

Follow Project Issues with Yahoo Pipes

Drupal provides project owners with the ability to follow issues on their projects. Simply go to your My Projects page and you can see an overview of your projects and even grab a RSS feed of the latest issues. But, if you are just a project co-maintainer or a contributor who doesn't actually have access to a project there is no nice and easy place to follow the issues on that project. I used Yahoo Pipes to solve this problem because it outputs RSS, has quick add buttons for sites like My Yahoo and Netvibes, can be added to a page as a badge, and it provides JSON and PHP access.

drupal-pipes.png

The image above shows the simple pipe I created. I went to each of the issues pages, grabbed the RSS feed for that issue list, and inserted it to Feed Fetch. I followed that up by using sort to bring the newest issues to the top (you can sort this is any way you like). And, then I output that. I can now view this in a number of different ways and places.

If you want to get fancy you only need to pull in one RSS feed. The variable called projects in the feed URL can be a comma separated list of project nodes.

Evaluating Content Management Systems

joomla-logo.jpgContent Management Systems are always being evaluated. Sometimes it's an organization looking for the next system to host their website. Sometimes it's someone writing a review about a system. And, still other times it's the competition taking a peak at the products they are up against. Let's take a look at some common areas we need to evaluate whether the system is open source or proprietary.

The Developers

One of the first areas to look at is the developers behind a product. Are they engineering a system or throwing something together ad hoc? Are they knowledgeable about content management and social publishing? Are they good developers who attempt to use good design patterns and practices?

In not talking about the developers who use a CMS to create a website. That's something separate unless you have the same people doing both which happens with some proprietary systems.

Support

No quality support options can be a deal breaker for many. Many companies in the enterprise world have policies that stop software purchase where no support contracts are available unless someone with leverage gets this overridden. This same thing happens within many churches, ministries, and other non-profits.

What are the support options available for a product? Sometimes this will be a regular monthly fee for ongoing support and other times you can get it on a case by case basis.

Do the support options fit your needs and environment?

Usability

The more web based tools I try the more I find usability is not an up front factor where it should be. When we think about the people using a CMS we need to think about the lower common denominators. That is, the people who aren't super tech savvy. Think of a church secretary or someone in the age bracket over 55 (where they spent most of their life without a computer). Think of people who aren't using technology everyday and aren't going to learn loads of new terms and concepts. How intuitive is a CMS for them to use?

Innovation

The Internet, the way we use it, and the way we connect with others is changing at a fairly high rate. Technology is giving us the ability to redefine our processes as things become simpler and more widely distributed. At the same time, web based technologies are becoming more integrated with each other and our lives. How is a CMS moving with this trend? How is a CMS at adopting new processes and technologies to help your organization do what it does better?

Features

This one seems simple and it usually is. Does the CMS have the features to implement the things you need it to do? This means that you need to know what to look for before you dive into picking a CMS. It's the requirements of a product before you pick a solution mentality rather than picking a solution and using what it has mentality.

Over the next few weeks I'll be blogging about each of these areas and what they mean in more detail.

How To Measure Church Effectiveness

flot-small.pngWhen I first started looking into church statistics and measurements I found measurements like the the number of members at a church, the number of weekend attenders, and income for a church on any given week. These numbers give a little detail about the church but they don't provide much insight into how church is doing towards meeting it's goals. They provide some numbers that allow a church to be compared to other churches but they don't provide much detail about an individual church. Let's look at some measurements that can be taken in a church providing insight into how a church is doing at its, God given, mission.

Growth

The bible tells us to go and make disciples of all nations in Matthew 28. This is a mission of growth and something measurements can tell us how we're doing. The mission is to make disciples, that is people going from not having faith and belief to disciples. This measurement doesn't directly relate to the number of new people who come to a church. It's independent of total church growth.

Recent statistics released by a number of church bodies have said this number is about 3% of their growth. Measuring this has caused them to change their outreach model.

Teaching

Another part of the mission supplied to us in Matthew 28 is that we are to make disciples by teaching. This doesn't mean it has to be formal classroom teaching but there is some form of mentoring or teaching going on. This is something we can measure. If you have a class for people who don't know about church you can measure the attendance of the people who are genuinely new to the idea of church. Do you have a bible study? What is the attendance at that?

Another part of this is people being prepared to teach others. It could be parents teaching their children, people leading a book club for Christian books, someone mentoring a friend in their spiritual journey, or someone teaching a formal class. Something to measure is how many people in your congregation have the resources to do that? How many people have the experience to be in one or more of these roles?

Money

Money seems to be a big deal in the church for a lot of people. Money is a personal issue for a lot of people. It's something people tend to want to keep for themselves and keep God out. Measurements here can be very effective. But, all measurements here need to be put in context. What is the income from a group compared to their demographics? Are they giving a tithe or not? This can provide some insight into the members of a church. Not from a money angle but a heart angle. It can show us if people are joyfully giving or not.

Bringing These Things Together

When we start to bring these different measurements together we can get a more well rounded picture of the spiritual model of a local church.

For example, you may have a church full of people who give a tithe but they don't know much about the bible and they don't outreach. Or, you may have a church that is growing at a great rate but there are few, if any, new people becoming disciples.

When we start mashing together these measurements in calculated ways we can start to get a model for our local church. We can start to see what's going on. This is an important step. As we drill down in identifying what's going wrong we can see where we need to work, as a church, to communally grow in our faiths.

Rotating Banner Images with Views and jQuery

Rotating banner images is a simple way to spice up most sites. It adds something shiny that can hook people in. If you use jQuery, like I often do, then a simple way to do the rotating banner images is using the jQuery cycle plugin. This plugin can even be used along with drupals views module to create dynamic lists of rotating images.

But, there are some downfalls with this approach. For example, if you create a list of images for the jQuery cycle plugin to rotate through you need to set all but one of them not to display with css. Even though most of the images are not initially displaying they are still downloaded in many browsers. If you have a bunch of images loading that have any size this has a potential to waste a lot of bandwidth if those images aren't viewed.

This was a problem that I ran into working on a few sites. Here's a solution I use that solves this problem while working well with Views, jQuery, and any content Views can create.

Note: This explanation applies to drupal 5.

The Views

The first thing I do is create 2 views. One that contains only one image, to be used for the initial display, and a second that loads all of the images to rotate through. The view that loads only one image gets embedded into a template file, like my page-front.tpl.php file.

The second view I'll setup to return as an array in JavaScript. The return method to use in this example is "return drupal_to_js($items);", but that's not the only way that will work.

In both cases I'll use template files that are called from custom theme functions that are called by template.php. The Views Theme Wizard modules, that comes with views, can help you create those functions. In the theme file for the single image I'll put in something like:

<div id="some-unique-id">
<!-- Insert my content here -->
</div>

While the template file for the view containing the content to rotate through would look like:

<!-- Insert my content here -->

In both cases the "Insert my content here" should be the same.

Note: If you are a theming ninja you can accomplish this with just one view and one template file.

The JavaScript

Here is a bit of JavaScript containing an example of an external file that does the heavy lifting. You'll notice that it contains a jQuery preloader function that I've previously written about. The different parts of the javascript file are explained with comments.

// Create the namespace for the functions to work out of.
Drupal.themename = {};

// The function that gets called to do the replacement
Drupal.themename.replaceimage = function () {
 
  // Replace the content inside #some-unique-id
  $('#some-unique-id').html(themename_rotating_images[themename_rotating_pointer]);;
 
  // Increase the pointer
  themename_rotating_pointer++;

  // Reset the pointer and turn off image preloading.
  // Note the number 10. This needs to be set the total number of items
  // in your view minus 1. This can be stored in a setting and passed in.
  if (themename_rotating_pointer == 10) {
    themename_rotating_pointer = 0;
    themename_rotating_switch = 0;
  }
 
  // Preload the content item after the next one. I load 2 ahead to
  // give the preloading more time for bigger files
  if (themename_rotating_switch == 1) {
    $.preloaddivs(themename_rotating_images[themename_rotating_pointer + 1]);
  }
}

// This is a content preloader function.
jQuery.preloaddivs = function(){
  for(var i = 0; i<arguments.length; i++)
  {
    jQuery("<div>").html(arguments[i]);
  }
}

$(document).ready(function() {
  // Preload the first 2 pieces of content.
  jQuery.preloaddivs(themename_rotating_images[themename_rotating_pointer], themename_rotating_images[themename_rotating_pointer + 1]);
 
  // Setup the content replacer to run every 7 seconds. This number can
  // be changed and even setup via a setting.
  setInterval("Drupal.themename.replaceimage()", 7000);
});

This is just a basic example of how to do this. On sites I build, like MuddyRivermedia.org, I've put in fade in and fade out effects. All of the hard set variables in this example can be passed in with settings and variables so they can be made entirely dynamic and this can be made to be more flexible. I've hard coded them for simplicity.

The Theme

The final step is to include all of this stuff into the theme so that it all comes together. The views theming functions should already be included in the template.php file so I won't include them here. Here are the other things to put in the template.php file:

<?php
function _phptemplate_variables($hook, $variables = array()) {
 
 
// Add out stuff to the page
 
if ($hook == 'page') {
   
   
// This logic will do our work on just the site homepage.
    // This logic can be changed to occur on other pages
   
if (request_uri() == '/' || request_uri() == '/'. variable_get('site_frontpage', NULL)) {
     
// Load the scripts.js file described above.
     
drupal_add_js(path_to_theme() .'/scripts.js', 'theme');

     
// Load the variable with the rotating images. Notice the
      // str_replace and substr functions used to remove the wrapper
      // divs placed in by views. Change the class names to the ones
      // from your view.
     
drupal_add_js('var themename_rotating_images = '. substr(str_replace("<div class='view view-my-example'><div class='view-content view-content-my-example'>", '', theme('view', 'home_image_random', 10, FALSE, 'block')), 0, -13) .';', 'inline');
     
drupal_add_js("var themename_rotating_pointer = 0;", 'inline');
     
drupal_add_js("var themename_rotating_switch = 1;", 'inline');
    }
   
   
// Rebuild the phptemplate page variable $scripts with new content
   
$variables['scripts'] = drupal_get_js();
  }
}
?>

This example shows the basic idea for using Views, image preloading, and jQuery to create a dynamic content rotation on a site with drupal.

There is a bit of room for optimization and quite a bit of flexibility and eye candy (like fading and other animations) that can be built in and on top of what is included here.

How To: Views to Javascript

The views module for drupal provides a powerful way to create queries of content and then present it in a number of different ways. One of the ways I've seen seldom used is views generating lists and variables for javascript and jQuery. Let's take a look at how we can accomplish this fairly easily.

At the heart of making this happens is theme override functions and drupal_to_js, a function that converts php variables into javascript variables.

To find your views theme override function you can install the Views Theme Wizard module that comes with views. Using the views theme wizard you should be able to get a function like:

<?php
function phptemplate_views_view_list_My_Example($view, $nodes, $type) {
 
$fields = _views_get_fields();

 
$taken = array();

 
// Set up the fields in nicely named chunks.
 
foreach ($view->field as $id => $field) {
   
$field_name = $field['field'];
    if (isset(
$taken[$field_name])) {
     
$field_name = $field['queryname'];
    }
   
$taken[$field_name] = true;
   
$field_names[$id] = $field_name;
  }

 
// Set up some variables that won't change.
 
$base_vars = array(
   
'view' => $view,
   
'view_type' => $type,
  );

  foreach (
$nodes as $i => $node) {
   
$vars = $base_vars;
   
$vars['node'] = $node;
   
$vars['count'] = $i;
   
$vars['stripe'] = $i % 2 ? 'even' : 'odd';
    foreach (
$view->field as $id => $field) {
     
$name = $field_names[$id];
     
$vars[$name] = views_theme_field('views_handle_field', $field['queryname'], $fields, $field, $node, $view);
      if (isset(
$field['label'])) {
       
$vars[$name . '_label'] = $field['label'];
      }
    }
   
$items[] = _phptemplate_callback('views-list-My_Example', $vars);
  }
  if (
$items) {
    return
theme('item_list', $items);
  }
}
?>

This function goes in your template.php file, as the wizard will tell you, and is the place where we start.

There are a few things we can change here to manipulate our information for javascript. The first is the line:

<?php
  $items
[] = _phptemplate_callback('views-list-My_Example', $vars);
?>

This line is taking each node found by views with the accompanying fields, as selected in the view, and passing it to a template file to style the content. In this case the fields on the view are passed to the file views-list-My_Example.tpl.php in your themes folder where you can style it.

You can keep this line the way it is and style the content to pass to your javascript, as I did for the image rotator on MuddyRiverMedia.org, or you can turn the fields into variables in an array to pass to javascript. To turn them into variables to pass to the javascript as an array change the line to read:

<?php
  $items
[] = $vars;
?>

The next part of the equation is to supply the view to javascript in a way the javascript can use it. To do this we alter the line:

<?php
 
return theme('item_list', $items);
?>

There are 2 ways to do this. The first is to create a javascript variable in our theme and the second is to pass it in as a drupal setting for javascript. To create a javascript variable change the line above to:

<?php
 
return drupal_to_js($items);
?>

Then, in the javascript part of your theme you can do something like this:

var myvarname = <?php print theme('views', 'My_Example', NULL, NULL, 'embed'); ?>

Note: This has to be a file generated by PHP and can't be an external javascript file

Another way to add this views generated information is to pass it in as a drupal setting for your javascript. To do this change:

<?php
 
return theme('item_list', $items);
?>

To:

<?php
 
return $items;
?>

Then, in your theme or a module use something like:

<?php
  drupal_add_js
(array('myvarname' = > theme('views', 'My_Example', NULL, NULL, 'embed')), 'setting');
?>

In your javascript this variable would then be accessible at Drupal.settings.myvarname. You'll notice that we didn't use drupal_to_js in this case. That's because drupal does this for us when we use a setting in drupal_add_js.

Views can be a very useful way to pass information to javascript to make our sites even more useful and fun.

How To: Clear Floats in CSS

Have you ever had the situation where you tried to clear a floating element in your web design only to have something not line up right? Maybe the box model in your design didn't line up right. Maybe a column was too long and ran over something it shouldn't. You look at your CSS and see clear: both; in the right place and can't find the problem. There are better ways to clear floats. They deal with cross browser issues and do so without adding extra elements to a page.

A common way to fix the float problem is to stick <br style="clear:both"/> after your floated items to clear the float. This works and it keeps columns aligned. But, it adds extra elements to the page and you may have spacing issues from this tag.

Instead of doing this I'd suggest two different methods.

Position Everything Method

Over at position everything there is an article on how to clear floats without adding any structured markup to a page. To do this you first add the following to your css:

.clear-block:after {
  content: ".";
  display: block;
  height: 0;
  clear: both;
  visibility: hidden;
}

.clear-block {
  display: inline-block;
}

/* Hides from IE-mac \*/
* html .clear-block {
  height: 1%;
}
.clear-block {
  display: block;
}
/* End hide from IE-mac */

Then, in your page have something like the following:

<div id="wrapper" class="clear-block">
  <div style="float:right">
    // Your content here
  </div>
  <div style="float:left">
    // More content here
  </div>
</div>

This is the method built into drupal and one that works well. It takes advantage of the rarely used :after method in css. It, also, works in all the major browsers including the now dead IE for Mac.

Paul O’Brien Method

Paul O'Brien suggested adding overflow:auto to the outer div.

An example of this would look like:

<div id="outer" style="overflow: auto;">
  <div style="float:right">
    // Your content here
  </div>
  <div style="float:left">
    // More content here
  </div>
</div>
<div id="footer" style="clear:both;">
  // Some footer content
</div>

Adding overflow:auto seems to be a gentle enough reminder to browsers that the content in them is in them and to enclose the whole thing in them.

While, I used the CSS in style tags here I'd suggest putting all the CSS in style sheets in a production site. Happy Positioning.

Rename Tabs In Drupal 5

Renaming tabs in drupal 6 is easy thanks to hook_menu_alter. In drupal 5 it's not so easy and there is no place to rename them outside of the theme system. So, let's take a look at how to rename tabs in the theme system. This method is similar to the method I outlined for removing tabs via the theme system.

First, put the following function in your template.php file.

<?php
/**
* Function renames tabs in drupal
*
* @param  $label_old
* Name of old label to replace
*
* @param  $label_new
* Name of new label to replace with
*
* @param  $vars
* $vars from _phptemplate_variables
*
*/
function phptemplate_change_tab_label($label_old, $label_new, &$vars) {
 
$tabs = explode("\n", $vars['tabs']);
 
$vars['tabs'] = '';

  foreach(
$tabs as $tab) {
    if(
strpos($tab, '>'. $label_old .'<') === FALSE) {
     
$vars['tabs'] .= $tab . "\n";
    }
    else {
     
$vars['tabs'] .= str_replace('>'. $label_old .'<', '>'. $label_new .'<', $tab) .
"\n";
    }
  }
}
?>

Then, in the function _phptemplate_variables in your template.php put something like:

<?php
function _phptemplate_variables($hook, $vars = array()) {
  if (
$hook == 'page') {
    if (
arg(0) == 'user' && is_numeric(arg(1))) {
     
phptemplate_change_tab_label('Edit', 'Edit account settings', &$vars);
    }
  }
}
?>

In this example we change the 'Edit' tab to read 'Edit account settings' and we do this only on user pages. This allows us to customize the interface and make our drupal site more usable.

Removing and Altering Tab Names In Drupal 5

Altering menu items in drupal 6 is fairly easy thanks to hook_menu_alter. But, in drupal 5 it's not so easy. While we can't achieve all the power of hook_menu_alter we can remove tabs, among other things. Let's take a look at how to do this.

To remove tabs put the following function in your template.php file.

<?php
/**
* Remove a tab
*
* @param  $label
* The label to remove
*
* @param  $vars
* $vars from _phptemplate_variables
*/
function phptemplate_remove_tab($label, &$vars) {
 
$tabs = explode("\n", $vars['tabs']);
 
$vars['tabs'] = '';

  foreach(
$tabs as $tab) {
    if(
strpos($tab, '>'. $label .'<') === FALSE) {
     
$vars['tabs'] .= $tab . "\n";
    }
  }
}
?>

Then, in the function _phptemplate_variables use this new function like the following example.

<?php
function _phptemplate_variables($hook, $vars = array()) {
  if (
$hook == 'page') {
   
phptemplate_remove_tab('View', &$vars);
  }
}
?>

This would remove all tabs with the name View. If we wanted to get more complicated we can use some arguments. This example only removes the View tab on user pages.
<?php
function _phptemplate_variables($hook, $vars = array()) {
  if (
$hook == 'page') {
    if (
arg(0) == 'user' && is_numeric(arg(1)) && arg(2) == '') {
       
phptemplate_remove_tab('View', &$vars);
      }
  }
}
?>

This is just one of the menu related alterations we can do from the template.php file. But, it is one I put to good use regularly.

5 Tips To Become A Better Podcaster

podcast iconEvery podcaster has room for improvement. Whether that podcaster is someone who has just started their first podcast or someone who is a seasoned veteran, there is always room to improve. When Bob and I first started podcasting with the Geeks and God podcast we were not nearly as good as we are today (though there is still much room to improve). We've worked to improve, not only the technology behind the show, but how we present ourselves as podcasters. Here are a few of the methods I've learned to help me improve at being a podcaster.

Pay Attention To Other Podcasters

Find a few podcasters you like to listen to and start paying attention to them. By paying attention I mean, listen to how they talk, their attitude, what they talk about, their intensity, and see if you can figure out their facial expression by the tone in their voice. Can you tell when they are smiling?

Then, try to add some of those qualities you like in when you speak. Start slow with just one. Add it in to an everyday conversation first to take it for a test drive. This will make it more natural when you try to have that characteristic on the podcast.

Think of this like an actor might. Actors work on their performances. They learn how to speak for the part and how to carry themselves for the part. And, they practice this first. Podcasters are trying to deliver a message and, while they are not playing a role, presentation matters.

Listen To Your Own Podcast

For me, this is one of the most difficult tasks to do. I can understand why some actors won't watch something they were in. But, to improve at podcasting you need to listen to yourself. Ask yourself if there is something you don't like about your delivery. Are you someone you would want to listen to? If not, why not.

Get Some Feedback

Find someone who can be truly honest with you and get feedback from them. Ask for specifics. If you can find someone who is a good speaker this would be better because they should know what works.

I think of this like a golf coach. Someone who can look at your game and see what's stopping you from having that sweet swing.

Don't Talk About Yourself

Unless the podcast is about your life, don't talk about yourself very much on the podcast. People want to hear about the topic, not your life.

I bring this up because I think it's a trap a lot of podcasters fall into. Talking about your life is an easy fall back when you aren't sure what to say or when you get nervous. It something you know. Fight the urge.

Learn To Be Comfortable

This tip is more for someone who has just started podcasting. When I first got behind a microphone I was nervous. Putting something out on the Internet that had my thoughts and voice on it made me nervous. I expect this out of new podcasters. Learning to be comfortable is one of the best things you can learn to do. People can hear discomfort. Discomfort makes you more critical in a bad way. Discomfort distracts from your train of thought and ability to do a good show.

Work to get comfortable.

These are just a handful of things that can bring about a dramatic difference in a podcast. The technology only gets a podcast so far. It's the podcaster that makes or breaks a podcast.