[Drupal教程] 如何添加CSS和Javascript定制Drupal7表单

时间:2022-08-14 22:12:04
Drupal7表单定制和Drupal6大致相同,但是也有一些区别。这次我就来说说Drupal7是如何定制表单的。新建一个“form_theme”模块,然后创建一个表单,显示如下:
My name is [FORM INPUT] [FORM INPUT] and I am [FORM INPUT] years old.
这三个表单元素的默认值依次显示“First name”,“Last name”和“Age”,当用户点击某个INPUT时,该表单元素的值为空,然后你就能随意书写了。
这个简易的功能涉及到:
  • 主题化表单
  • 给表单添加JQuery(JavaScript)
  • 给表单添加CSS  {3 u& v2 ~# Z
这个教程的主要目的是学习如何主题化表单,我不会对一些与主题化不相关的代码做过多地介绍。同样地,如果你想看懂这篇教程,你必须先知道:
  • 怎样在Drupal7中创建一个模块
  • 怎样在Drupal中使用drupal_get_form()创建一个表单. L, k% L+ ]6 @
我也不会对教程中的CSS和JQuery代码做过多的讲解,你可以直接复制并粘贴到本地去试验。呵呵,我的目的是如何将CSS和JQuery添加进Drupal中。; V8 L' p, l' R; V, r& h
开始吧!
第一步:使用hook_menu()为表单注册一个路径
我需要先注册一个页面路径好展现表单,下面是hook_menu()的实现:; L! ]& j! G: ~9 i, Q: @

<?php
function form_theme_menu()
{% A' A/ V) E6 Y/ D
    $menu['form_theme'] = array- L( C9 Q8 b, B& O# y
    (5 L: V; A: z9 Y5 V& F; s) z
        'title' => 'Theming Forms',# ^, @* y" ~# E$ s
        'description' => 'Practicing theming forms in Drupal 7',6 j* _8 q. V* y% {: E* S2 Y- W) ]
        'page callback' => 'drupal_get_form',
        'page arguments' => array('form_theme_form'),
        'access callback' => TRUE,
    );
    return $menu;9 R2 l- k+ U8 `$ Z. q, j  S* ~# Q
}- b1 U( ?) f8 D! W4 h# K3 b
?>
$ w" u1 g) p5 |8 f0 a
; i% L* q7 z* ]' ?$ ^
第二步:定义表单! _' D0 {/ R  F$ U; _( |, X0 A/ f9 t2 ^
在我的表单里,我需要三个textfield,表单定义如下:

<?php/ A; i: w- h& w) T0 O0 L
$form['first_name'] = array
(# `% w. I7 N( [! c! i5 V6 G
    '#type' => 'textfield',3 {3 e) ~  h* }- @5 s
);
$form['last_name'] = array4 B1 w' a( U3 l9 m) j2 Y
(+ c, U$ e/ c( T+ S
    '#type' => 'textfield',
);; o% T. G- h. V
$form['age'] = array
(
    '#type' => 'textfield',
    '#maxlength' => 3,
);
?>
9 s: g7 |6 p" g" k# v

嘿嘿,代码十分简洁吧。我已经创建了这些表单元素,它们没什么修饰或其它配置。
然后,我需要添加CSS和Javascript到该表单。Drupal7有个新属性,#attached,我能通过它添加,代码如下:
$ Z; ]- H6 M- B6 v0 s- h0 p: c* [
<?php4 z$ w4 p8 V4 J& e3 [% D* m
// Get the path to the module
$path = drupal_get_path('module', 'form_theme');3 v  A& `7 M, d
// Attach the CSS and JS to the form
$form['#attached'] = array7 P* _0 l2 @% |' @
(
    'css' => array8 E2 S8 q. q! p! r
    (
        'type' => 'file',$ e/ J4 u, Z* x" i6 O3 W
        'data' => $path . '/form_theme.css',
    ),
    'js' => array
    (
        'type' => 'file',; u% U. h2 q) Q+ G$ p9 ~# o
        'data' => $path . '/form_theme.js',5 W1 X* H* I" T2 n' u* k1 d
    ),
);; x/ j' W4 Z: D+ T8 N
?>
5 J' P3 o; _8 Q, w: k0 N& K; P
! s: M0 C  v( w0 ?0 E
这种方法相比drupal_add_js()和drupal_add_css()有个很大的好处,就是其它模块可以在该模块的样式和脚本的基础上做修改。/ \( o/ V2 {6 O& h! N$ u
最后,返回我的$form表单,代码如下:

<?php5 r. v% I4 E; z, c! W
function form_theme_form($form, &$form_state)
{7 M/ x! [- e: b0 G$ |# Q* {: j
    $form['first_name'] = array
    (
        '#type' => 'textfield',
    );
    $form['last_name'] = array
    (1 H* u; X4 K& V
        '#type' => 'textfield',# u! q% v3 p' @" V+ Q4 e- w4 }
    );
    $form['age'] = array
    () m1 K: a5 }5 I7 v( x0 g
        '#type' => 'textfield',
        '#maxlength' => 3,
    );  q; a" u* D8 v1 U% ]0 a3 M2 t
    // Get the path to the module
    $path = drupal_get_path('module', 'form_theme');+ I9 e) M# G+ Q8 l. ]; S
    // Attach the CSS and JS to the form
    $form['#attached'] = array
    (7 o, N- U# ]& R$ H" l9 b
        'css' => array
        (- b6 U7 M& H6 l4 o9 R; i" J
            'type' => 'file',7 f+ U0 q* i. K! g/ M5 a
            'data' => $path . '/form_theme.css',
        ),/ y- g0 B: @* _+ B7 V) c3 ^4 ^
        'js' => array
        (
            'type' => 'file',- ?2 p6 a' }! n; k3 I
            'data' => $path . '/form_theme.js',
        ),6 P6 }' l; \' s; q# l+ w7 e5 \
    );9 \& ?' w4 f! t7 a
    return $form;9 Y: l- Z! g( }# G$ N4 [
}
?>
. D" J8 ?! g5 x8 U7 J6 p' E: Q2 _) u: a
8 Z: E) N' |+ K. G1 v
第三步:用hook_theme()注册一个主题函数
从Drupal6开始,主题函数就需要通过hook_theme()注册,但是在Drupal6和Drupal7中还是有些细微的区别。在Drupal7中,表单的主题函数不是使用“arguments”,而是使用仅仅只有“form”一个值的“render element”。在注册主题函数时,你必须让索引和你已经定义的表单函数保持一致。代码如下:) c! v- b! p" m9 n) X3 M! G/ ~$ M7 ^

<?php7 Z* P% D$ l# Y
function form_theme_theme()
{" |1 C, f4 Q. S
    return array: x; k; @( }/ l) J' W% ?
    (
        'form_theme_form' => array
        (
            'render element' => 'form', Y" j3 @3 n" g  X1 a
        ),
    );; z: e( J7 m6 j: d* t" z7 `
}
?>


正如你所见,我已经注册了一个主题函数。主题函数的命名十分重要,因为这个主题函数跟表单有相同的名称,Drupal在实现这个表单时会自动调用该主题函数。我也不需要添加#theme到我定义的表单$form中,这是多余的。3 b: \# q; j0 M+ R- H8 O/ |
第四步:写主题函数& c3 O0 d9 L7 s& K- H  ^
在Drupal7中,写主题函数,有几个注意点。它们是:
  • 函数只有一个参数,命名为$variables的数组。$variables有一个form索引,该索引的值就包括所有你已定义的表单元素。
  • 所有的表单元素必须要作为参数传给drupal_render()函数。这个函数能将一个PHP数组转换成HTML,并且将Javascript和css添加进去。这些Drupal会自动帮你完成,你仅仅需要传递这些参数就行了。
  • 在写主题函数的最后,你必须将剩余的表单元素传给drupal_render_children()函数,这样才能将剩下的或隐藏的表单元素转换成HTML。这是跟Drupal6一个很大的不同。在Drupal6中,我们直接传递$form给drupal_render(),但是在Drupal7中,这样做就会导致死循环,而且不会出现任何错误提示。2 i6 I6 ?* L1 x4 V9 Z: U
主题函数是以“theme_”加上我们上面注册过“form_theme_form”命名的。代码如下:

<?php+ z/ M- h) A0 A, `, p0 q  D
function theme_form_theme_form($variables)2 W8 q7 I% N0 n" f: g
{( a# u1 L, l4 X1 s3 J
    // Isolate the form definition form the $variables array
    $form = $variables['form'];' t8 B$ u6 y4 S: W: j
    $output = '<h2>' . t('Please enter your information below') . '</h2>';
    // Put the entire structure into a div that can be used for
    // CSS purposes. B; @- R3 s+ `" U
    $output .= '<div id="personal_details">';
    // Each of the pieces of text is wrapped in a <span>
    // tag to allow it to be floated left( g: _' \8 O- R' B. }) ~# }% G
    $output .= '<span>' . t('My name is') . '</span>';
    // Form elements are rendered with drupal_render()/ ?# M# J3 v" k* p  }5 O1 v
    $output .= drupal_render($form['first_name']);" N7 N$ w7 F! [
    $output .= drupal_render($form['last_name']);
    $output .= '<span>' . t('and I am') . '</span>';" g  c6 e4 v, C# y/ t# c% K
    $output .= drupal_render($form['age']);8 ]  Q* s, M' k
    $output .= '<span>' . t('years old.') . '</span>';
    $output .= '</div>';: k& V$ k( R( ~  l
    // Pass the remaining form elements through drupal_render_children()
    $output .= drupal_render_children($form);! X% r2 L9 c* }
    // return the output
    return $output;
}8 L" N. n4 x8 J$ L7 l% H
?>
1 T5 ^$ J5 t3 u, z

到这里,我已经完成大部分的内容,定义表单,注册主题函数,实现主题函数。但是我还没添加CSS和Javascript。
第五步:创建CSS和Javascript文件
在第二步中我添加了CSS和JS路径,这两个文件都在form_theme模块的根目录。CSS代码如下:1 G) S2 r2 q2 V  X" c2 @2 J5 A- @0 o

#personal_details span, #personal_details div+ t5 m% a, _/ I2 Q% v/ `% O' O
{
float:left;0 X5 D6 C3 n# [( L0 W. `
}
) _/ S! i' C# l' h
#personal_details .form-item-first-name, #personal_details .form-item-last-name) k7 X$ v- Z7 M# S: d; K
{! B" k# P& [8 C# j7 b1 |" M
width:115px;
}% u7 @& z6 i* @. i8 T  X

#edit-first-name, #edit-last-name% ]0 m' \) {  @8 K# V# Y9 o% J5 N
{# |6 |+ ~( c9 r2 X* F8 ~( M
width:100px;
}
- J& R& e) J1 V# G* u- [. H6 |
#personal_details .form-item-age; s- p' g1 \9 A2 g3 L6 `  J7 t
{
width:50px;' w2 M, ~2 \* p2 P) D" P
}1 j4 N- F1 i; J6 H# z+ V5 ?

#edit-age
{
width:35px;
}

#personal_details span
{7 O+ ~" f. e3 q
margin-right:5px;
padding-top:5px;( X5 g# S9 I0 _- ~  K8 X
}3 G# M) J- N2 O0 ?/ ?  b

Javascript代码如下:

// We wrap the entire code in an anonymous function6 N" R, V' C1 s/ B3 Y1 D
// in order to prevent namespace collisions, and to
// allow for jQuery to be set in a safe mode where
// it will not collide with other javascript libraries.
// While this is the proper way to do it in Drupal 7,; N" a' ~5 P0 \( b
// this method is actually good to use in Drupal 6 as- L& u. e, C4 X# ]7 n/ j. c
// well, for the same reasons.( p; R4 A# A1 v$ D: X
(function($)# \+ h  ?; l2 P* I
{
// In Drupal 6, each element of Drupal.behaviors/ y7 \( d8 I% l/ E4 `- {2 F
// was a function that was executed when the
// document was ready. In Drupal 7, each element9 g2 x, i$ @; F+ O$ G/ W
// of Drupal.behaviors is an object with an) Z" k4 T# z* d( ?& }4 T; r
// element 'attach' (and optionally an element
// 'detach'), which is executed when the document0 b$ a  v6 a% I/ e
// is ready$ y2 G9 U! H2 x2 n
Drupal.behaviors.formTheme = {
attach:function() {6 a/ ~1 ~& L  l" i. [7 J2 i* K
// First, define an empty array
var defaults = [];1 S# X8 k8 i3 |) q) J: ?+ d' z
// Next, add three elements to the array,
// one for each of the form elements. The value$ f$ A- w$ A- A; f: n
// is of the array element is set as the default
// text. This text is run through Drupal.t(),/ ~% B9 ^- P$ [
// which is the Drupal JavaScript equivalent+ l+ L6 v, V: C+ |$ g2 A( r
// of the Drupal PHP t() function, and allows
// for translating of text in a JavaScript document, z# q0 v$ e1 r9 ?" L' p* @' x
defaults["#edit-first-name"] = Drupal.t("First Name");
defaults["#edit-last-name"] = Drupal.t("Last Name");- \7 h, {. k) w0 r) q
defaults["#edit-age"] = Drupal.t("Age");
// Next we loop through each of the elements of the array( o. L* l0 F  O! Q* s% L! `# s8 \
var element;. A; L. K; ?- b
for(element in defaults)4 h2 f/ G, W9 D
{
// We wrap the body in the following if() statement
// as each element in an array will also have a- l. ]$ U) F6 \2 ^& Q- ?5 X& M
// prototype element. If you don't understand this,% Q/ t. A" m7 R) E6 i. a
// don't worry. Just copy it. It will make your
// for(A in B) loops run better.
if(defaults.hasOwnProperty(element)) {
// 1) Set a placeholder in the form element
// 2) Set the CSS text color to grey for the placeholder% I9 R" x$ K$ D, W' X
// 3) Attach an onfocus and onblur listener to each element
$(element).val(defaults[element]).css("color", "grey").focus(function()5 I5 a4 m; e% B
{5 R1 X1 y5 [) m5 V9 P& i
// This is entered on focus. It checks: C1 q: t6 p& E1 e  S  ~' C1 s( P' B
// if the value of the form element is, l( d. i2 C4 G& G! Z0 N& W3 m" E9 H) a
// the default value of the placeholder,9 L6 {: S8 t4 q+ Q
// and if it is, it clears the value and8 h0 k, j/ ^* |$ \$ B
// sets the text color to black,as the' N2 i, j9 n2 T3 \' b
// entered text will be the actual text
// and not the greyed out placeholder text.
var key = "#" + $(this).attr("id");
if($(this).val() === defaults[key]) {
$(this).css("color", "black").val("");7 \; [- h# n1 h
}" t! K2 ?2 d7 k1 k  X( _( T
}).blur(function()
{
// This is entered on blur, when the element
// is exited out of. It checks if the element4 r. n- U1 z( x! n0 f% |( h; `
// is empty, and if it is, it sets the default
// placeholder text back into the element, and
// changes the text color to the grey placeholder% n1 _! V: e, _$ @' q& h/ X8 R
// text color.
if($(this).val() == "") {" D& {& J8 \' E  K1 ]( c/ c, i5 Z; D9 i
var key = "#" + $(this).attr("id");
$(this).css("color", "grey").val(defaults[key]);$ I7 ^+ H  Y9 Z! Q0 g7 _4 R$ k6 F0 w
}. f' {5 j" H/ d& y; C
});; w* Q4 a1 p& ~
}  y: w# ]# ~. U( u% ^) m+ r. ]0 a
}6 ]3 k, X. `: V7 r+ b- u( [# s
}
};
}(jQuery));

好了,你可以试试看。
原文出自:[Drupal教程] 如何添加CSS和Javascript定制Drupal7表单http://junepeng.info/zh/node/28