Directions for creating draggable-interface


While developing a website it very often happens that sorting should be done by a specific criterion in which case ViewsNodequeueFlag and other similar modules are used. Sometimes, however, those modules' functional does not suffice to meet the client's tough demands. Of course, one can create multiple nodequeues which means that your client will later need educating in the responsibilities each of the nodequeues has been assigned with. This approach seems to be doubtful, though, from the point of view of the site's usability. Another option might suggest adding of the "weight" cck-field along with manual identifying of its weight, so as to eventually sort by it. And again, having thousands of nodes at hand makes this method irrelevant.

 In view of the above, "drag-and-drop" interface is likely to be the most valid of the sort options in question. Realization of this method will be outlined in this post.

 First of all we do add cck-field "weight" to the necessary type of content. Then in hook_menu we declare the page to host both draggable-interface and form itself:

function my_module_drag_form($form_state, $node) { 
  $form['my_items']['#tree'] = TRUE; 
  $vids = my_module_select_vids_function(); // выбираем нужные ноды
  //правильный способ выполнения запроса к ссk-полям 
  $type_name  = 'product'; 
  $field_name = 'field_product_weight'; 
  $type = content_types($type_name); 
  $field = $type['fields'][$field_name]; 
  $data = content_database_info($field); 
  $join  = $data['table']; 
  $field = $data['columns'][end(array_keys($data['columns']))]['column']; 
  //выбираем тайтлы нод и значение поля "weight" 
  $q = db_query("SELECT f.%s, n.title, n.nid, n.vid 
                 FROM {node} n 
                 INNER JOIN {%s} f ON f.vid = n.vid 
                 WHERE n.vid IN (" . db_placeholders($vids, 'int') . ") ORDER BY f.%s ASC", array_merge(array($field), array($join), $vids, array($field)));
  //собственно сама форма 
  while ($d = db_fetch_array($q)) { 
    $form['my_items'][$d['vid']] = array( 
      'name' => array( 
              '#type' => 'markup', 
              '#value' => l($d['title'], 'node/' . $d['nid']),
      'weight' => array( 
              '#type' => 'weight', 
              '#delta' => 10, 
              '#default_value' => $d[$field], 
              '#attributes' => array('class' => 'weight'),
  $form['submit'] = array( 
      '#type' => 'submit', 
      '#value' => t('Save Changes'), 
  return $form; 

To log on the changes in the database, we add submit function to the form: 

function my_module_drag_form_submit($form, &$form_state) {
  $type_name  = 'product'; 
  $field_name = 'field_product_weight'; 
  $type = content_types($type_name); 
  $field = $type['fields'][$field_name]; 
  $data = content_database_info($field); 
  $join  = $data['table']; 
  $field = $data['columns'][end(array_keys($data['columns']))]['column']; 
  //обновляем значение поля "weight" в базе данных 
  foreach ($form_state['values']['my_items'] as $k => $item) { 
    $q = db_query("UPDATE {%s} SET %s=%d WHERE %s.vid=%d", $join, $field, $item['weight'], $join, $k);

We declare the theming function for our form:

function my_module_theme() { 
  return array( 
    'my_module_drag_form' => array( 
        'arguments' => array('form' => NULL), 

Theming function will look as follows:

function theme_my_module_drag_form($form) { 
  // переменная, которая будет содержать возвращаемое значение
  $output = ''; 
  // проходимся по каждому элементу массива таблицы 
  foreach($form['my_items'] as $id => $row) { 
    // если $id не число - пропускаем эту строчку 
    if (!intval($id)) 
    // этот массив будет содержать ячейки строки 
    $this_row = array(); 
    // генерируем markup name 
    $this_row[] = drupal_render($row['name']); 
    // добавляем поле с весом 
    $this_row[] = drupal_render($row['weight']); 
    // добавляем строку в массив строк 
    $table_rows[] = array('data' => $this_row, 'class'=>'draggable');
  // убеждаемся, что количесво заголовков совпадает с количеством столбцов
  $header = array( 
  $table_id = 'my_items'; 
  // добавляем draggable 
  drupal_add_tabledrag($table_id, 'order', 'sibling', 'weight');   
  // переопределяем элемент формы 'my_items' маркапом, сгенерированным нашей таблицей
  $form['my_items'] = array( 
      '#type' => 'markup', 
      '#value' => theme('table', $header, $table_rows, array('id' => $table_id)),
      '#weight' => '1', 
  // генерируем форму 
  $output = drupal_render($form); 

  return $output; 

As a result, we will have a happy client and the picture as described at the top of this page.

5 votes, Rating: 5

Read also


Pressflow is Drupal’s distributive that provides advanced efficiency and scaling. It’s developed by the guys from Four Kitchens Company.


I was asked many times how to translate element <Any> in drop-down list in filter of views module.


What’s CDN? Content Delivery Network or Content Distribution Network, CDN – geographically distributed network infrastructure which allows optimizing delivery and distribution of content to the...


The founders and developers of MySQL resigned from their native company which belongs to Oracle (once Sun consumed MySQL and later Oracle consumed Sun).


Profiling – is a process of work analysis of application for data acquisition about efficiency (acquisition of set of characteristics – CPU times, memory usage and resources processing, number of...

Need a quote? Let's discuss the project

Are you looking for someone to help you with your Drupal Web Development needs? Let’s get in touch and discuss the requirements of your project. We would love to hear from you.

Join the people who have already subscribed!

Want to be aware of important and interesting things happening? We will inform you about new blog posts on Drupal development, design, QA testing and more, as well news about Drupal events.

No charge. Unsubscribe anytime