3

I have a module that produces a lot of pages. A set of these are handled by a particular part of my application, and I would like all these to have a class added to either html or body. I'd settle for #block-system-main.

The existing answers point to a template preprocess hooks e.g. hook_preprocess_html() but this feels wrong.

I'd have to create that hook and then tell it to go somewhere else to determine which page call back was used and which class to apply - it's all backwards. Drupal's already selected the right callback, so a 2nd lookup is another thing to maintain and an inefficiency.

I could of course do something like set a global $extra_page_classes variable and then implement the hook to add these classes to the page, which is more efficient but it's still messy. Or I could add (yet another) wrapping <div> to my callback output, but that's not going to give a themer chance to adapt the rest of the page elements outside of the main content.

Seems odd that a page callback, responsible for the substantial content of the page, can't set page-level attributes. A page callback can, for example, choose to call drupal_add_css(), but it (apparently) can't do something as simple as add a class to the page.

As it seems odd and Drupal usually has some (often hidden) elegance, I thought I'd ask specifically if there was a better way.

0

Well, I think your confusion comes from the D7/D6 fact that a "page" has little clue whats going on around it. As you've said the page callback function tells drupal "what goes in the $content" but not what adornments happen on the page HTML DOM around $content.

To my knowledge unless your using Panels, Context or something else to share "page state" through components of your site -- this is simply how D7 simply works.

Without using context, panels, etc. I usually end up looking for url paths or NIDs or custom content array attributes #project-add-body-classes in hook functions to fire off my logic.

For what you describe I would use hook_html_alter() and look for a page path to alter the body_classes array as needed.

  • Thanks for your answer. Are you meaning to add to 'classes_array' from within hook_page_alter()? Can't get that working - tried on $page, $page[content] $page[content][system_main], but nothing. – artfulrobot Feb 22 '13 at 20:21
  • I have edited my answer. hook_page_alter only lets you muck with the $content type stuff in a page. I guess hook_html_alter is the only think that lets you change body_classes easily in a hook. – tenken Feb 22 '13 at 21:00
  • 1
    Have edited your Q as I presume you meant template_preprocess_html(). I've done this but searching the array for the '#myappclass' key requires recursive loop (page.content.content.content...system_main.#myappclass) which is inefficient. I might change code to just use a global instead; at least that's easily identifiable. Thanks for your time, anyway. – artfulrobot Feb 23 '13 at 14:02
0

You could simply do it from within a page callback with inline JS.

drupal_add_js('jQuery(document).ready(function () {
  jQuery("body").addClass("foobar");  
});', 'inline');

Alternatively use template_preprocess_html to add a body classes depending on the current path.

/**
 * Implements hook_menu().
 */
function MYMOUDLE_menu() {

  $items = [];

  $items['foo/bar'] = [
    'title'            => 'Foobar',
    'description'      => 'Lorem ipsum.',
    'access arguments' => ['access content'],
    'page callback'    => '_MYMODULE_mycallback',
    'type'             => MENU_CALLBACK,
  ];

  return $items;
}

Now add the body class dynamically by comparing the URL arguments from above.

/**
 * Implements template_preprocess_html().
 */
function MYMODULE_preprocess_html(&$variables) {

  // Add HTML <body> class.
  if (arg(0) === 'foo' && arg(1) === 'bar') {
    $variables['classes_array'][] = 'foobar';
  }
}

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.