This is more so a Feature Suggestion. I've already created this feature and am using it in production environments. I'm just curious what the community thinks of it.

Any Drupal themer is very aware of the problem with block theming where, the only way to select a block module block is to use the id (ie: #block-block-12). Yes other modules (like block_class) attempt to fix this but I really don't like their module-level approaches when this is really just a theming issue. Mostly, i don't like how block_class adds a new table just to store a class name inside of. It just seems wrong.
So i was racking my brain trying to think of a simpler way to handle this. I started liking the idea of basing the class name off of the block description. After all, block descriptions are required, so it is something that already exists, that you can always count on being there.

I was quite excited that I'd be able to solve the age-old block selector problem with little or no overhead. But then I quickly discovered that the block description is not available in the $block object. I found that block module block descriptions are stored in the {boxes} table. So in the end, the {boxes} query and the string manipulation in zen_clean_css_identifier() is really the only overhead to this solution. (devel reported the {boxes} query to take ~.12 ms)

Here are the details.

In Zen's template.php, function zen_preprocess_block(), I've added the following:

  // Add special class for block blocks based off description.
  if (theme_get_setting('wbr_block_classes')) {
    if ($desc = zen_block_description_get(array('module' => $block->module, 'delta' => $block->delta))) {
      $classes[] = 'block-'. zen_clean_css_identifier($desc);
    }
  }

This function is new:

function zen_block_description_get($params) {
  $module = $params['module'];
  $delta = $params['delta'];
  if ($module != 'block') {
    // Only block blocks have their info stored in {boxes}.
    return;
  }
  $desc = db_fetch_object(db_query("SELECT b.info FROM {boxes} b WHERE b.bid = %d", $delta));
  return $desc->info;
}

This function is new and is borrowed from http://drupal.org/node/464862 :

/**
 *  Prepare a string for use as css class.
 *  Borrowed from: http://drupal.org/node/464862
 */
function zen_clean_css_identifier($identifier, $coding_standards = TRUE, $safe_prefix = 'class-') {
  // Valid characters are:
  // - the hyphen (U+002D)
  // - a-z (U+0030 - U+0039)
  // - A-Z (U+0041 - U+005A)
  // - the underscore (U+005F)
  // - 0-9 (U+0061 - U+007A)
  // - ISO 10646 characters U+00A1 and higher
  // We strip out any character not in the above list.
  $identifier = strtolower(preg_replace('/[\x{0000}-\x{002C}\x{002E}-\x{002F}\x{003A}-\x{0040}\x{005B}-\x{005E}\x{0060}\x{007B}-\x{00A0}]/u', '-', $identifier));

  // Drupal's coding standards use lowercase characters and dashes instead of
  // underscores.
  if ($coding_standards) {
    $identifier = str_replace('_', '-', drupal_strtolower($identifier));
  }

  // CSS identifiers can't start with a number or a dash and a number, so we
  // prepend a safe string to prevent an invalid identifier.
  $start = substr($identifier, 0, 1);
  if ($start == '-') {
    $start = substr($identifier, 1, 1);
  }
  if (is_numeric($start)) {
    $identifier = $safe_prefix . $identifier;
  }

  return $identifier;
}

I then added this to theme-settings.php so that the class feature can be easily enabled/disabled:

  // Add special block class based off block description.
  $form['themedev']['wbr_block_classes'] = array(
    '#type'          => 'checkbox',
    '#title'         => t('Add extra classes to blocks.'),
    '#default_value' => $settings['wbr_block_classes'],
    '#description'   => t('Add a class to block module blocks based off its description.'),
    '#prefix'        => '<div id="div-wbr-block-classes"><strong>' . t('Block classes:') . '</strong>',
    '#suffix'        => '</div>',
  );

And finally, I added this to zen.info and STARTERKIT.info so that the block class feature would be enabled by default:

settings[zen_block_classes]        = 1

Comments

Nick Robillard’s picture

Oops

settings[zen_block_classes]        = 1

should have been

settings[wbr_block_classes]        = 1

Edit: I've since updated this feature to not use the new function zen_clean_css_identifier(), but to piggyback off of zen_clean_id(). I did this once i saw that preprocesser functions use zen_clean_id() to clean css classes (and not just ids - fyi, ids and classes do have slightly different rules for validation).

akalata’s picture

Status: Active » Closed (won't fix)

Closing old/inactive requests.