跳转到主要内容
结一 提交于 10 July 2014

作者:结一

众所周知,drupal的html结构是比较冗重的,而为了很好的标记这些结构就必然要给它们赋予相应的class,这样才能通过不同的或相同的class来赋予样式,完成这界面美观设计的飞跃。总的说来drupal的class只有比标签结构更多,很显然一个标签上可以挂好几个class呢,这么多的class必然有其生成的一些规律,所以本篇文章打算从这个角度来简单分析下drupal主题。

body的class

对于下面这段代码,相信大家都不会陌生

<body class="html front not-logged-in one-sidebar sidebar-second page-node">
    ...
</body>

为了了解它,我们找到modules/system目录下的html.tpl.php文件,打开找到第55行,发现如下代码,原来是由$classes变量输出的

<body class="<?php print $classes; ?>" <?php print $attributes;?>>

接下里我们在上面的注释部分的第36,37行找到如下说明

 * - $classes String of classes that can be used to style contextually through
 *   CSS.

这里只说明了原来是个数组而已,那到底怎么定义的呢,继续找到第39-41行,如下代码:

 * @see template_preprocess()
 * @see template_preprocess_html()
 * @see template_process()

这就相当于如果要查看更多的话,就找到这三个函数。于是我们找到万能的drupal api 查询,一查原来在theme.inc文件的第2343行,找到这个之后,直接就可以在这个文件再搜其他两个函数了。

template-process.jpg

下面我们挑重要的分析下:

template_preprocess()函数中定义了变量classes_array为数组(第2357行)

  // Initialize html class attribute for the current hook.
  $variables['classes_array'] = array(drupal_html_class($hook));

template_preprocess_html()函数中往数组classes_array中添加了一些元素(第2453-2489行),代码太多就不贴出来了,主要就是是否登录,是否首页,布局,page node,node type几个class

template_process()函数中把数组classes_array转成了以空格隔开的字符串,并赋值给变量$classes

// Flatten out classes.
$variables['classes'] = implode(' ', $variables['classes_array']);

这就是body class的整个一个流程。

如果要添删改呢,那么就得用到hook_preprocess_html(&$variables, $hook)这个函数了,以dgd7主题的template一个修改为例(第93行):

  // In template_preprocess_html() we have easy access to the "class" attribute
  // for the <body> element. Here we add a helper class that indicates that
  // there is no title for the page to help styling the content region easily.
  if (!drupal_get_title()) {
    $vars['classes_array'][] = 'no-title';
  }

region的class

因为page.tpl.php没有,所以我们直接跳过,然后同样该在modules/system目录找到region.tpl.php文件,注释的第9-14行说明了这个$class变量,而第32行调用了该变量,默认该变量有两个class,一个为region,一个为region-[name],至于怎么定义的可以在template_preprocess_region()函数中找到

 * - $classes: String of classes that can be used to style contextually through
 *   CSS. It can be manipulated through the variable $classes_array from
 *   preprocess functions. The default values can be one or more of the following:
 *   - region: The current template type, i.e., "theming hook".
 *   - region-[name]: The name of the region with underscores replaced with
 *     dashes. For example, the page_top region would have a region-page-top class.

<div class="<?php print $classes; ?>">

如需增删改,使用hook_preprocess_region(),同样以dgd7主题的template为例,第98-113行:

/**
* Implements template_preprocess_region().
*
* The changes made in this function affect the variables for the region.tpl.php
* template file. In this theme we have not overridden this template, so the
* core default, located in modules/system/region.tpl.php isbeing used. This
* code is covered on pages 318-319.
*/
function dgd7_preprocess_region(&$vars) {
  $region = $vars['region'];

  // Add an "outer" class to the darker regions.
  if (in_array($region, array('header', 'footer', 'sidebar_first', 'sidebar_second'))) {
    $vars['classes_array'][] = 'outer';
  }
}

node的class

在modules/node目录找到node.tpl.php,第21-35行解释了$class变量,而第83行调用该变量,如何定义可以查阅template_preprocess_node()函数,至于增删改,使用hook_preprocess_node()即可,是不是感觉突然一下简单了。

field的class

modules/field/theme目录找到field.tpl.php,第21-35行解释了$class变量,而第53行调用该变量,如何定义可以查阅template_preprocess_field()函数,至于怎么...(省略,大家都懂的),这里提醒下,因为可能一个字段有多个值,所以这里使用了一层嵌套,先是field-items然后才是循环field-item,所以如果你想省标签的话,可以先判断$items数组的长度,如果只是一个,那么就直接干掉外层的field-items

<div class="field-items"<?php print $content_attributes; ?>>
    <?php foreach ($items as $delta => $item): ?>
      <div class="field-item <?php print $delta % 2 ? 'odd' : 'even'; ?>"<?php print $item_attributes[$delta]; ?>><?php print render($item); ?></div>
    <?php endforeach; ?>
</div>

views的class

下载views模块,解压后在其theme目录中找到views-view.tpl.php,第8-15行解释再加第17行自定义的class,第30行调用,在目录的theme.inc中第44行template_preprocess_views_view()函数中定义如下(第55-68行):

// Basic classes
$vars['css_class'] = '';

$vars['classes_array'] = array();
$vars['classes_array'][] = 'view';
$vars['classes_array'][] = 'view-' . drupal_clean_css_identifier($vars['name']);
$vars['classes_array'][] = 'view-id-' . $vars['name'];
$vars['classes_array'][] = 'view-display-id-' . $vars['display_id'];

$css_class = $view->display_handler->get_option('css_class');
if (!empty($css_class)) {
    $vars['css_class'] = preg_replace('/[^a-zA-Z0-9- ]/', '-', $css_class);
    $vars['classes_array'][] = $vars['css_class'];
}

关于drupal的class机制就分析道这里,了解了这些class之后,对于美化主题选用class还是很有帮助的,不然那么多个class,依靠直觉去选一个那中奖的几率估计是比较高的。当然还有一个panels的,因为对这个没有什么研究,所以就不献丑了,喜欢的同学可以研究下,反正都是一个路子。

Drupal 版本