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时,该表单元素的值为空,然后你就能随意书写了。 这个简易的功能涉及到:
开始吧! 第一步:使用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中,写主题函数,有几个注意点。它们是:
<?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)); 好了,你可以试试看。 原文出自:http://junepeng.info/zh/node/28 |