drupal表单元素

 

在本节中,我们将通过例子来展示内置的Drupal表单元素。
 
Textfield(文本字段)
       元素textfield的示例如下:
$form['pet_name'] = array(
    '#title' => t('Name'),
    '#type' => 'textfield',
    '#description' => t('Enter the name of your pet.'),
    '#default_value' => $user->pet_name,
    '#maxlength' => 32,
    '#required' => TRUE,
    '#size' => 15,
    '#weight' => 5,
    '#autocomplete_path' => 'pet/common_pet_names',
);
 
$form['pet_weight'] = array(
    '#title' => t('Weight'),
    '#type' => 'textfield',
    '#description' => t('Enter the weight of your pet in kilograms.'),
    '#field_suffix' => t('kilograms'),
    '#default_value' => $user->pet_weight,
    '#size' => 4,
    '#weight' => 10,
);
 
    表单元素的显示结果如图10-11所示
10-11元素textfield
 
    #field_prefix 和 #field_suffix属性是特定于文本字段的,它们在文本字段输入框的前面或者后面紧接着放置一个字符串。
    #autocomplete属性定义了一个路径,Drupal自动包含进来的JavaScript将使用jQuery向该路径发送HTTP请求。在前面的例子中,它将请求http://example.com/pet/common_pet_names。实际例子可以参看modules/user/user.pages.inc中的user_autocomplete()函数。
    文本字段元素的常用属性如下:#attributes, #autocomplete_path (默认为 FALSE), #default_value, #description, #field_prefix, #field_suffix,#maxlength (默认为128), #prefix, #required, #size (默认为60), #suffix, #title,#process(默认为form_expand_ahah),和 #weight。

老葛的Drupal培训班 Think in Drupal

Drupal版本:

drupal表单元素: Password(密码)

老葛的Drupal培训班 Think in Drupal

该元素创建一个HTML密码字段,在这里用户的输入不直接显示(一般在屏幕上使用符号“·”代替)。user_login_block()中的示例如下:
$form['pass'] = array(
    '#type' => 'password',
    '#title' => t('Password'),
    '#maxlength' => 60,
    '#size' => 15,
    '#required' => TRUE,
);
 
    密码元素的常用属性如下:#attributes, #description, #maxlength, #prefix, #required, #size (默认为 60), #suffix, #title, #process(默认为form_expand_ahah),和#weight。出于安全原因,在密码元素中不使用#default_value属性。

 

Drupal版本:

drupal表单元素: Password with Confirmation(带确认的密码)

老葛的Drupal培训班 Think in Drupal

该元素创建两个HTML密码字段,并附加一个验证器来检查两个密码是否匹配。例如,在用户模块中,当用户修改他/她的密码时,用到了该元素:
$form['account']['pass'] = array(
    '#type' => 'password_confirm',
    '#description' => t('To change the current user password, enter the new
        password in both fields.'),
    '#size' => 25,
);
 

Drupal版本:

drupal表单元素: Textarea(文本域)

 

文本域元素的示例如下:
$form['pet_habits'] = array(
       '#title' => t('Habits'),
       '#type' => 'textarea',
       '#description' => t('Describe the habits of your pet.'),
       '#default_value' => $user->pet_habits,
       '#cols' => 40,
       '#rows' => 3,
       '#resizable' => FALSE,
       '#weight' => 15,
);
       文本域元素的常用属性如下:#attributes, #cols (默认为60) , #default_value, #description, #prefix, #required,#resizable, #suffix, #title, #rows (默认为5) , #process(默认为form_expand_ahah), 和 #weight。
    如果通过设置#resizable为TRUE,启用动态的文本域调整器,那么属性#cols的设置将不起作用。
 

老葛的Drupal培训班 Think in Drupal

Drupal版本:

drupal表单元素: Select(下拉选择框)

老葛的Drupal培训班 Think in Drupal

一个来自于modules/statistics/statistics.admin.inc的下拉选择框元素的示例:
 
$period = drupal_map_assoc(array(3600, 10800, 21600, 32400, 43200, 86400, 172800,
    259200, 604800, 1209600, 2419200, 4838400, 9676800), 'format_interval');
 
/* Period now looks like this:
    Array (
        [3600] => 1 hour
        [10800] => 3 hours
        [21600] => 6 hours
        [32400] => 9 hours
        [43200] => 12 hours
        [86400] => 1 day
        [172800] => 2 days
        [259200] => 3 days
        [604800] => 1 week
        [1209600] => 2 weeks
        [2419200] => 4 weeks
        [4838400] => 8 weeks
        [9676800] => 16 weeks )
*/
 
$form['access']['statistics_flush_accesslog_timer'] = array(
    '#type' => 'select',
    '#title' => t('Discard access logs older than'),
    '#default_value' => variable_get('statistics_flush_accesslog_timer',            259200),
    '#options' => $period,
    '#description' => t('Older access log entries (including referrer statistics)
        will be automatically discarded. (Requires a correctly configured
        <a href="@cron">cron maintenance task</a>.)', array('@cron' =>
        url('admin/reports/status'))),
);
 
    通过将属性#options定义为一个包含子菜单选项的关联数组,Drupal支持对下拉选项的分组,如图10-12所示。
 
$options = array(
    array(
        t('Healthy') => array(
            1 => t('wagging'),
            2 => t('upright'),
            3 => t('no tail')
        ),
    ),
    array(
        t('Unhealthy') => array(
            4 => t('bleeding'),
            5 => t('oozing'),
        ),
    ),
);
$form['pet_tail'] = array(
    '#title' => t('Tail demeanor'),
    '#type' => 'select',
    '#description' => t('Pick the closest match that describes the tail
        of your pet.'),
    '#options' => $options,
    '#multiple' => FALSE,
    '#weight' => 20,
);
 
    图10-12 使用分组的下拉选择框
 
    通过将#multiple属性设置为TRUE,可以启用多选。这也将改变$form_state['values']中的值,从一个字符串(例如,'pet_tail' = '2',假定在前面的例子中选择了upright)变为了一个数组(例如,pet_tail = array( 1 => '1', 2 => '2'),假定在前面的例子中同时选择了wagging 和upright)。
    下拉选择框元素的常用属性如下:#attributes, #default_value,#description, #multiple, #options, #prefix, #required, #suffix, #title, #process(默认为form_expand_ahah),和#weight.

Drupal版本:

drupal表单元素: Radio Buttons(单选按钮)

老葛的Drupal培训班 Think in Drupal

来自于modules/block/block.admin.inc的单选按钮元素的示例:
 
$form['user_vis_settings']['custom'] = array(
    '#type' => 'radios',
    '#title' => t('Custom visibility settings'),
    '#options' => array(
        t('Users cannot control whether or not they see this block.'),
        t('Show this block by default, but let individual users hide it.'),
        t('Hide this block by default but let individual users show it.')
    ),
    '#description' => t('Allow individual users to customize the visibility of
        this block in their account settings.'),
    '#default_value' => $edit['custom'],
);
       单选按钮元素的常用属性如下:#attributes, #default_value, #description,#options, #prefix, #required, #suffix, #title, 和 #weight.注意#process属性默认设为expand_radios() (参看 includes/form.inc)。
 

Drupal版本:

drupal表单元素: Check Boxes(复选框)

 

复选框元素的示例如下。该元素的呈现版本如图10-13所示。
$options = array(
    'poison' => t('Sprays deadly poison'),
    'metal' => t('Can bite/claw through metal'),
    'deadly' => t('Killed previous owner') );
$form['danger'] = array(
    '#title' => t('Special conditions'),
    '#type' => 'checkboxes',
    '#description' => (t('Please note if any of these conditions apply to your
        pet.')),
    '#options' => $options,
    '#weight' => 25,
);
10-13 复选框元素示例图
 
    在验证和提交函数中,通常使用array_filter()函数来获取复选框的键。例如,假如在图10-13中前两个复选框被选中了,那么$form_state['values']['danger']将包含以下内容:
array(
    'poison' => 'poison',
    'metal' => 'metal',
    deadly' => 0,
)
    运行array_filter($form_state['values']['danger'])将生成只包含复选框的键的数组:array('poison', 'metal')。
       复选框元素的常用属性如下:#attributes, #default_value, #description, #options, #prefix, #required, #suffix, #title, #tree (默认为TRUE), 和#weight.注意#process属性默认设为expand_checkboxes() (参看 includes/form.inc)。
 

老葛的Drupal培训班 Think in Drupal

Drupal版本:

drupal表单元素: Value(值)

老葛的Drupal培训班 Think in Drupal

值元素是用来在drupal内部将数值从$form传递到$form_state['values']的,而不需要将其发送到浏览器端,例如:
$form['pid'] = array(
    '#type' => 'value',
    '#value' => 123,
);
    当表单提交后$form_state['values']['pid']将为123。
    不要混淆了type = '#value' 和 #value = 123。前者声明了正被描述的元素的类型,而后者声明了该元素的值。值元素只有属性#type和#value可用。

Drupal版本:

drupal表单元素: Hidden(隐藏域)

老葛的Drupal培训班 Think in Drupal

该元素使用一个类型为hidden的HTML输入字段将一个隐藏值传递到一个表单中,示例如下:
 
$form['my_hidden_field'] = array(
    '#type' => 'hidden',
    '#value' => t('I am a hidden field value'),
);
 
    如果你想在表单中传递一个隐藏值,通常使用值元素会更好一些,只有当值元素不能满足需求时才使用隐藏域元素。用户可以通过web表单的HTML源代码来查看隐藏域元素,但是却查看不了值元素,这是因为后者只存在于Drupal内部。
    隐藏域元素只有属性#type、#value、#prefix, #process(默认为form_expand_ahah), 和#suffix可用。
 

Drupal版本:

drupal表单元素: Date(日期)

老葛的Drupal培训班 Think in Drupal

日期元素,如图10-14所示,它是一个由3个下拉选择框联合而成的元素:
 
$form['deadline'] = array(
    '#title' => t('Deadline'),
    '#type' => 'date',
    '#description' => t('Set the deadline.'),
    '#default_value' => array(
        'month' => format_date(time(), 'custom', 'n'),
        'day' => format_date(time(), 'custom', 'j'),
        'year' => format_date(time(), 'custom', 'Y'),
    ),
);
 
10-14 日期字段
 
    日期元素的常用属性如下:#attributes, #default_value, #description, #prefix, #required, #suffix, #title, 和#weight. 属性#process默认设为expand_date(),在该方法中年选择器被硬编码为从1900到2050。属性#element_validate默认设为date_validate()(两个函数都位于includes/form.inc中)。当你在表单中定义日期元素时,通过定义这些属性,就使用你自己的代码来替代默认的了。

Drupal版本:

drupal表单元素: Weight(重量)

老葛的Drupal培训班 Think in Drupal

重量元素(不要与属性#weight混淆了)是一个用来声明重量的下拉选择框:
 
$form['weight'] = array(
    '#type' => 'weight',
    '#title' => t('Weight'),
    '#default_value' => $edit['weight'],
    '#delta' => 10,
    '#description' => t('In listings, the heavier vocabularies will sink and the
        lighter vocabularies will be positioned nearer the top.'),
);
 
前面代码的显示结果如图10-15所示。
 
10-15 重量元素
 
    属性#delta决定了重量的可供选择范围,默认为10.例如,如果你将#delta设为50,那么重量的范围就应该为从-50到50. 重量元素的常用属性如下:#attributes, #delta (默认为 10), #default_value, #description, #prefix, #required, #suffix, #title, 和#weight。#process属性默认为array('process_weight', 'form_expand_ahah')。
 

Drupal版本:

drupal表单元素: File Upload(文件上传)

老葛的Drupal培训班 Think in Drupal

文件元素创建了一个文件上传接口。下面是一个来自于modules/user/user.module的示例:
 
$form['picture']['picture_upload'] = array(
    '#type' => 'file',
    '#title' => t('Upload picture'),
    '#size' => 48,
    '#description' => t('Your virtual face or picture.')
);
 
    本元素的显示方式如图10-16所示。
 
10-16 文件上传元素
 
注意,如果你使用了文件元素,那么你需要在你表单的根部设置属性enctype:$form['#attributes']['enctype'] = 'multipart/form-data';
文件元素的常用属性如下:#attributes, #default_value, #description, #prefix, #required, #size (默认为 60), #suffix, #title, 和 #weight.
 

Drupal版本:

drupal表单元素: Fieldset(字段集)

老葛的Drupal培训班 Think in Drupal

字段集元素是用来对其它表单元素进行归类分组的。可将其声明为可伸缩的,这样当用户查看表单并点击字段集标题时,由Drupal自动提供的JavaScript能够动态的打开和关闭字段集。注意,在这个例子中,属性#access用来允许或拒绝访问字段集中的所有字段:
 
// Node author information for administrators.
$form['author'] = array(
    '#type' => 'fieldset',
    '#access' => user_access('administer nodes'),
    '#title' => t('Authoring information'),
    '#collapsible' => TRUE,
    '#collapsed' => TRUE,
    '#weight' => 20,
);
 
字段集元素的常用属性如下:#attributes, #collapsed (默认为 FALSE), #collapsible (默认为 FALSE), #description, #prefix, #suffix, #title, #process(默认为form_expand_ahah),和 #weight。
 

Drupal版本:

drupal表单元素: Submit(提交按钮)

老葛的Drupal培训班 Think in Drupal

提交按钮元素是用来提交表单的。按钮内部显示的单词默认为“提交”,但是可以使用属性#value来修改它:
 
$form['submit'] = array(
    '#type' => 'submit',
    '#value' => t('Continue'),
);
 
    提交按钮元素的常用属性如下:#attributes, #button_type (默认为 'submit'), #executes_submit_callback (默认为 TRUE), #name (默认为 'op'),#prefix, #suffix, #value, #process(默认为form_expand_ahah),和#weight。
    另外,可以将#validate和#submit属性直接分配给提交按钮元素。例如,如果#submit设置为了array('my_special_form_submit'),那么就会使用函数my_special_form_submit()来替代表单的定义了的提交处理器。

Drupal版本:

drupal表单元素: Button(按钮)

 

按钮元素除了属性#executes_submit_callback默认为FALSE以外,其它属性与提交按钮元素完全相同。属性#executes_submit_callback告诉Drupal是否需要处理表单,为TRUE时处理表单,为FALSE时则简单的重新呈现表单。和提交按钮元素一样,可以将特定的验证和提交函数直接分配给这个按钮元素。

老葛的Drupal培训班 Think in Drupal

Drupal版本:

drupal表单元素: Image Button(图片按钮)

老葛的Drupal培训班 Think in Drupal

图片按钮元素与提交按钮元素基本相同,但有两点例外。首先,它有一个#src属性,使用一个图片的URL作为它的值。其次,它把内部表单属性#has_garbage_value设置为了TRUE,这样就会阻止使用#default_value属性,从而避免在微软IE浏览器中的臭虫。不要在图片按钮中使用#default_value属性。下面是一个图片按钮,它使用内置的“Powered by Drupal”图片作为按钮:
 
$form['my_image_button'] = array(
    '#type' => 'image_button',
    '#src' => 'misc/powered-blue-80x15.png',
    '#value' => 'foo',
);
 
    通过查看$form_state['clicked_button']['#value'],就可以安全的取回图片按钮的值了。
 

Drupal版本:

drupal表单元素: Markup(标识文本)

老葛的Drupal培训班 Think in Drupal

如果没有设置属性#type的话,标识文本元素就是默认的元素类型了。它用来在表单中引入一段文本或者HTML。
 
$form['disclaimer'] = array(
    '#prefix' => '<div>',
    '#value' => t('The information below is entirely optional.'),
    '#suffix' => '</div>',
);
 
    标识文本元素的常用属性如下:#attributes, #prefix (默认为空字符串 ''), #suffix (默认为空字符串''), #value, and #weight.
 
警告 如果你把文本输出在一个可伸缩的字段集的内部,那么要使用<div>标签对其进行包装,如同例子中所展示的那样,这样当字段集被折叠起来时,你的文本也被折叠在了里面。
 

Drupal版本:

drupal表单元素: Item(项目)

 

项目元素的格式与其它输入表单元素的相同,比如文本字段或下拉选择框字段,但是它缺少输入框。
 
$form['removed'] = array(
    '#title' => t('Shoe size'),
    '#type' => 'item',
    '#description' => t('This question has been removed because the law prohibits       us from asking your shoe size.'),
);
 
前面元素的呈现结果如图10-17所示。
 
10-17 项目元素
 
       项目元素的常用属性如下:#attributes, #description, #prefix(默认为空字符串''), #required, #suffix (默认为空字符串''),#title, #value,和 #weight.

老葛的Drupal培训班 Think in Drupal

Drupal版本:

#ahah属性(1)

老葛的Drupal培训班 Think in Drupal

#ahah元素属性是向Drupal提供AHAH实现信息的,AHAH允许使用JavaScript来修改表单元素。
 
提示 你可能已经注意到了,在我们描述过的许多表单元素中,#process的默认值都为form_expand_ahah。在元素中添加#ahah属性,就是向Drupal指示为这个元素使用AHAH。函数form_expand_ahah()用来确保#ahah的值拥有合理的默认值。
 
    在上传模块的用于文件上传的附件按钮中,就用到了这一个属性,如下所示:
 
$form['new']['attach'] = array(
    '#type' => 'submit',
    '#value' => t('Attach'),
    '#name' => 'attach',
    '#ahah' => array(
    'path' => 'upload/js',
    'wrapper' => 'attach-wrapper',
    'progress' => array(
        'type' => 'bar',
        'message' => t('Please wait...'),
    ),
),
'#submit' => array('node_form_submit_build_node'),
);
 
    #ahah属性的值是一个键值数组。下面的键是必须的:
 
• path: JavaScript所要请求的菜单项的Drupal路径。菜单项的回调和菜单项的路径以js结尾,这表示该项目是通过JavaScript调用的。在前面的例子中,Drupal路径就是upload/js,而相应的回调就是upload_js()(不信的话,你可以查看modules/upload/upload.module中的函数upload_menu())。
 
• wrapper: 对应于一个HTML元素的id属性(通常为<div>)。在前面的例子中,上传模块涉及到下面的这个元素:<div id="attach-wrapper">。
 

Drupal版本:

drupal #ahah属性(2)

老葛的Drupal培训班 Think in Drupal

下面的键是可选的:
• effect: 在替换元素时使用的视觉效果。可能的值有none,fade,和slide。默认值为none。
 
• event: 事件,用来触发浏览器执行JavaScript HTTP请求。Drupal基于元素类型设置了一些默认值。这些值显示在表10-1中。
 
10-1.在表单元素中,触发AHAH的事件的默认名字
元素          默认事件
submit          mousedown*
button          mousedown*
image_button    mousedown*
password        blur
textfield       blur
textarea        blur
radio           change
checkbox        change
select          change
*还包括keypress事件。
 
• method: 当JavaScript HTTP请求的响应返回时,用来修改已有HTML的JQuery方法。可能的值有after,append, before, prepend, 和replace。默认的方法是replace。这个值用在下面的JavaScript(参看misc/ahah.js)中:
 
if (this.method == 'replace') {
    wrapper.empty().append(new_content);
}
else {
    wrapper[this.method](new_content);
}
 
• progress: 通知的方式-----一个JavaScript事件发生后,Drupal向用户发送通知的方式。该属性的值是一个数组,包含以下键:type和message,例如:
 
$form['submit'] = array(
    '#type' => 'submit',
    '#value' => t('Click Me'),
    '#ahah' => array(
        'event' => 'click',
        'path' => 'poof/message_js',
        'wrapper' => 'target',
        'effect' => 'fade',
        'progress' => array(
            'type' => 'throbber',
            'message' => t('One moment...'),
        ),
    )
);
 
    type的默认值为throbber,它是一个圆形的转动的图标,在JavaScript HTTP请求正在运行时,它还会显示一个可选的消息。另外的一个选择就是bar,它是一个进度条(如果声明为bar的话,那么将会添加一个单独的JavaScript文件misc/progress.js)。如果类型被设置为了bar,那么有以下可选键可用:url和interval。url键用来为进度条声明一个URL,通过调用这个URL,就可以判定它的百分比,一个从0到100的整数;而interval键则是用来声明检查进度的频率(以秒为单位)。
 
• selector: 通过声明一个选择器,就可以将JavaScript HTTP 请求的结果附加在页面中的多个元素上(而不仅仅是表单元素)。

Drupal版本:

drupal #ahah属性(3)

老葛的Drupal培训班 Think in Drupal

下面是一个表单的简单示例,它允许使用AHAH来动态替换一些文本。按钮使用throbber来指示用户应该继续等待,如图10-18所示。这里是sites/all/modules/custom/poof/poof.info:
 
; $Id$
name = Poof
description = Demonstrates AHAH forms.
package = Pro Drupal Development
core = 6.x
 
    而下面则是sites/all/modules/custom/poof/poof.module:
 
<?php
 
/**
 * Implementation of hook_menu().
 */
function poof_menu() {
    $items['poof'] = array(
        'title' => 'Ahah!',
        'page callback' => 'drupal_get_form',
        'page arguments' => array('poof_form'),
        'access arguments' => array('access content'),
    );
    $items['poof/message_js'] = array(
        'page callback' => 'poof_message_js',
        'type' => MENU_CALLBACK,
        'access arguments' => array('access content'),
    );
    return $items;
}
 
/**
 * Form definition.
 */
function poof_form() {
    $form['target'] = array(
        '#type' => 'markup',
        '#prefix' => '<div id="target">',
        '#value' => t('Click the button below. I dare you.'),
        '#suffix' => '</div>',
    );
    $form['submit'] = array(
        '#type' => 'submit',
        '#value' => t('Click Me'),
        '#ahah' => array(
            'event' => 'click',
            'path' => 'poof/message_js',
            'wrapper' => 'target',
            'effect' => 'fade',
        )
    );
 
    return $form;
}
 
/**
 * Menu callback for AHAH additions.
 */
function poof_message_js() {
    $output = t('POOF!');
    drupal_json(array('status' => TRUE, 'data' => $output));
}
 
10-18.点击按钮后,将会显示一个圆形的转动的throbber图标,之后将会进行基于AHAH的文本替换。
 

Drupal版本:

drupal #ahah属性(4)

 

在下面,还是这个模块,不过这次实现了进度条功能,而更新的频率为两秒一次(参看图10-19)。
 
警告 这个模块只是简单的说明了如何与进度条进行交互;在实际中,你应该报告的是实际任务完成的百分比。特别强调的一点是,你不要像示例中所给的那样,使用Drupal的持久化变量系统来存储和读取进度,这是因为多个用户同时运行表单时,这种方式就会出错。替代的方式是,你需要对数据库进行查询来获取已插入记录的百分比。
 
<?php
 
/**
 * Implementation of hook_menu().
 */
function poof_menu() {
    $items['poof'] = array(
        'title' => 'Ahah!',
        'page callback' => 'drupal_get_form',
        'page arguments' => array('poof_form'),
        'access arguments' => array('access content'),
    );
    $items['poof/message_js'] = array(
        'page callback' => 'poof_message_js',
        'type' => MENU_CALLBACK,
        'access arguments' => array('access content'),
    );
    $items['poof/interval_js'] = array(
       'page callback' => 'poof_interval_js',
       'type' => MENU_CALLBACK,
       'access arguments' => array('access content'),
    );
    return $items;
}
 
/**
 * Form definition.
 */
function poof_form() {
    $form['target'] = array(
        '#type' => 'markup',
        '#prefix' => '<div id="target">',
        '#value' => t('Click the button below. I dare you.'),
        '#suffix' => '</div>',
    );
    $form['submit'] = array(
        '#type' => 'submit',
        '#value' => t('Click Me'),
        '#ahah' => array(
            'event' => 'click',
            'path' => 'poof/message_js',
            'wrapper' => 'target',
            'effect' => 'fade',
           'progress' => array(
              'type' => 'bar',
              'message' => t('One moment...'),
              'interval' => 2,
              'url' => 'poof/interval_js',
           ),
        )
    );
 
    return $form;
}
 
/**
 * Menu callback for AHAH additions.
 */
function poof_message_js() {
    $output = t('POOF!');
    for ($i = 0; $i < 100; $i = $i + 20) {
       // Record how far we are.
       variable_set('poof_percentage', $i);
       // Simulate performing a task by waiting 2 seconds.
       sleep(2);
    }
    drupal_json(array('status' => TRUE, 'data' => $output));
}
 
/**
 * Menu callback for AHAH progress bar intervals.
 */
function poof_interval_js() {
    // Read how far we are.
    $percentage = variable_get('poof_percentage', 0);
    // Return the value to the JavaScript progress bar.
    drupal_json(array('percentage' => $percentage));
}
 
10-19.进度条显示了完成的百分比。

老葛的Drupal培训班 Think in Drupal

Drupal版本: