Drupal7创建支持拖拽的表格

标签:

Drupal 7 已经内置了对可拖拽表格的支持,可以让用户通过上下拖动十字图标对表格的行进行排序。你能在输入格式管理后台看到一个使用这一技术的例子(/admin/config/content/formats)

pic1

drupal_add_tabledrag()函数是构建可拖拽表格的关键,下文将告诉你具体如何来做。

这个例子创建了一个后台设置页面,用于让管理员设置一系列内容用于首页的幻灯片。关于幻灯片的实现不会在本文展示,我们将创建一个自定义模块,叫slideshow。下面展示的代码会被放在slideshow.module文件里。

这个表格由5列组成:

  • 第一列是一个十字图标,这个十字图标用于拖拽,可以有自己的列,也可以嵌入到其他列里。
  • 第二列是一个输入框,使用了autocomplete特性,在你输入的时候自动显示提示。
  • 第三列是一个正常的slideshow标题
  • 第四列是隐藏的weights列,这个列将在用户点击"Show row weights"时显示。
  • 最后一列是操作列,放的是删除链接。

pic2

定义菜单项,注册theme

<?php
// Implements hook_menu().
function slideshow_menu() {
 
$items = array();
 
 
// Slideshow manage page.
 
$items['admin/config/user-interface/slideshow'] = array(
   
'title' => 'Slideshow',
   
'description' => 'Manage slideshow list.',
   
'page callback' => 'drupal_get_form',
   
'page arguments' => array('slideshow_manage'),
   
'access arguments' => array('administer content'),
  );
 
 
// Autocomplete callback.
 
$items['slideshow/autocomplete'] = array(
   
'page callback' => 'slideshow_autocomplete',
   
'access arguments' => array('administer content'),
   
'type' => MENU_CALLBACK,
  );
 
  return
$items;
}
// Implements hook_theme().
function slideshow_theme($existing, $type, $theme, $path) {
  return array(
   
'slideshow_manage' => array(
     
'render element' => 'form',
    ),
  );
}
?>

实现slideshow回调函数

<?php
function slideshow_manage() {
 
$slides = variable_get('slideshow_slides', array());
 
 
// Empty row for new slide input.
 
$slides[] = array('nid' => 0, 'caption' => '', 'weight' => 0);
 
 
$form['#tree'] = TRUE;
  foreach (
$slides as $id => $slide) {
    if (!empty(
$slide['nid'])) {
     
$node = node_load($slide['nid']);
    }
    else {
     
$node = (object)array('title' => '');
    }
   
   
// Textfield to hold content id.
   
$form['slides'][$slide['nid']]['node'] = array(
     
'#type' => 'textfield',
     
'#autocomplete_path' => 'ui-slideshow/autocomplete',
     
'#default_value' => check_plain($node->title) . (!empty($node->nid) ? " [$node->nid]" : ''),
    );
   
// Caption for the slideshow.
   
$form['slides'][$slide['nid']]['caption'] = array(
     
'#type' => 'textfield',
     
'#default_value' => $slide['caption'],
    );
   
// This field is invisible, but contains sort info (weights).
   
$form['slides'][$slide['nid']]['weight'] = array(
     
'#type' => 'weight',
     
'#title' => t('Weight'),
     
'#title_display' => 'invisible',
     
'#default_value' => $slide['weight'],
    );
   
// Operation links (to remove rows).
   
$form['slides'][$slide['nid']]['op'] = array(
     
'#markup' => '<a href="http://www.drupalproject.org/" class="remove-row">' . t('Remove') . '</a>',
    );
  }
 
 
// jQuery to implement remove feature. Setting the text field to empty
  // and submitting the form will remove the rows.
 
$js = <<<EOD
(function ($) {
  $(function() {
    $('a.remove-row').click(function() {
      $(this).closest('tr').fadeOut(function() {
        $(this).find('input.form-autocomplete').val('')
          .closest('form').submit();
      });
    });;
  });
})(jQuery);
EOD;
 
 
drupal_add_js($js, array('type' => 'inline'));
 
 
$form['submit'] = array('#type' => 'submit', '#value' => t('Save changes'));
 
  return
$form;
}
?>

实现表单提交处理函数

<?php
// This looks for the node id in the submitted value, "Test title string [123]"
function slideshow_manage_submit($form, &$form_state) {
 
$slides = array();
  foreach (
$form_state['values']['slides'] as $slide) {
   
preg_match('/\[(\d+)\]$/', $slide['node'], $matches);
    if (
$nid = !empty($matches[1]) ? (int)$matches[1] : 0) {
     
$slides[] = array(
       
'nid' => $nid,
       
'caption' => $slide['caption'],
       
'weight' => $slide['weight'],
      );
    }
  }
 
  if (!empty(
$slides)) {
   
usort($slides, '_slideshow_arraysort');
  }
 
 
variable_set('slideshow_slides', $slides);
 
drupal_set_message(t('Slides have been saved.'));
}
// Custom array sort function by weight.
function _slideshow_arraysort($a, $b) {
  if (isset(
$a['weight']) && isset($b['weight'])) {
    return
$a['weight'] < $b['weight'] ? -1 : 1;
  }
  return
0;
}
?>

为自动完成实现回调函数

<?php
// Search titles of article and page contents.
function slideshow_autocomplete($string) {
 
$query = db_select('node', 'n');
 
$query->fields('n', array('nid', 'title'));
 
 
$types = array('article', 'page'); // Add additional content types as you like.
 
if (!empty($types)) {
   
$db_or = db_or();
    foreach (
$types as $type) {
      if (!empty(
$type)) {
       
$db_or->condition('n.type', $type, '=');
      }
    }
   
$query->condition($db_or);
  }
 
 
$result = $query
   
->condition('n.title', '%' . db_like($string) . '%', 'LIKE')
    ->
range(0, 10)
    ->
execute();
 
 
$matches = array();
  foreach (
$result as $row) {
   
$matches[$row->title . " [$row->nid]"] = check_plain($row->title) . " [$row->nid]";
  }
 
 
drupal_json_output($matches);
}
?>

实现theme函数

<?php
// Theme function for slideshow_manage().
function theme_slideshow_manage($variables) {
 
$form = $variables['form'];
 
 
$rows = array();
  foreach (
element_children($form['slides']) as $nid) {
   
$form['slides'][$nid]['weight']['#attributes']['class'] = array('slides-order-weight');
   
$rows[] = array(
     
'data' => array(
        array(
'class' => array('slide-cross')),
       
drupal_render($form['slides'][$nid]['node']),
       
drupal_render($form['slides'][$nid]['caption']),
       
drupal_render($form['slides'][$nid]['weight']),
       
drupal_render($form['slides'][$nid]['op']),
      ),
     
'class' => array('draggable'),
    );
  }
 
 
$header = array('', t('Content'), t('Caption (If empty, title is used)'), t('Weight'), t('Operations'));
 
$output = drupal_render($form['note']);
 
$output .= theme('table', array('header' => $header, 'rows' => $rows, 'attributes' => array('id' => 'slides-order')));
 
$output .= drupal_render_children($form);
 
 
drupal_add_tabledrag('slides-order', 'order', 'sibling', 'slides-order-weight');
 
  return
$output;
}
?>

函数slideshow_manage和theme_slideshow_manage是实现拖拽效果的核心。