Керівництво по створенню draggable-інтерфейсу

13.03.2011
Directions for creating draggable-interface
Автор:

При розробці сайтів досить часто потрібно виконати сортування нод за якимось окремим критерієм. Для цього здебільшого використовують ViewsNodequeueFlag та інші схожі модулі. Але нерідко трапляється так, що функціоналу цих модулів виявляється замало, аби задовольнити хитрі вимоги замовника. Звісно ж, можна вдатись до створення безлічі nodequeue із подальшим розтлумачуванням замовнику, яка з них і за що відповідає. Така система, проте, виглядає як мінімум сумнівно з точки зору юзабіліті. Ще одним варіантом рішення може бути додавання cck-поля "weight" вручну для кожної ноди із зазначенням її ваги і подальшим по ній сортуванням. Та, знову ж таки, за наявності тисяч нод даний спосіб не є вирішенням проблеми.

Адекватним рішенням у цьому випадку буде застосування "drag-and-drop" інтерфейса - його реалізацію ми й розглянемо в даній статті. Насамперед, ми, все-таки, додамо cck-поле "weight" до потрібного типу контенту. Тоді в hook_menu оголошуємо сторінку, на якій буде draggable-інтерфейс і, зокремо, й сама форма:

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; 
}

Для запису змін в базу даних додаємо submit до форми: 

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);
  } 
}

Оголошуємо функцію темізації для нашої форми:

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

Функція темізації:

function theme_my_module_drag_form($form) { 
  // переменная, которая будет содержать возвращаемое значение
  $output = ''; 
  // проходимся по каждому элементу массива таблицы 
  foreach($form['my_items'] as $id => $row) { 
    // если $id не число - пропускаем эту строчку 
    if (!intval($id)) 
        continue; 
    // этот массив будет содержать ячейки строки 
    $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( 
    'Name', 
    'Weight', 
  ); 
  $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; 
}

На виході ми отримуємо задоволеного замовника і ту картину, яка зображена на початку статті.

Голосів: 1 Рейтинг: 5

Також по темі

1
Pressflow - дистрибутив Drupal, який забезпечує покращену продуктивність і маштабування. Він розроблений хлопцями з Four Kitchens
2

Напевно всі стикались з готовими збірками сайтів на Drupal, коли після встановлення отримуєш готовий сайт з набором необхідних модулів, своєю темою і т.д. Існує велика кількість таких збірок,...

3

Профілювання - це процес аналізу роботи додатку для збору інформації про продуктивність (збір набору характеристик - час, використання оперативної пам'яті і ресурсів процесора, кількість викликів...

4

Дуже багато раз мене питали як у випадаючому списку фільтра модуля views перекласти елемент "Any".

Так! Стандартно, перекладом інтерфейсу, це не зробити.

5

Що таке CDN? Кому і нащо потрібно використовувати CDN? Все це описується в нашому блог-пості....

Subscribe to our blog updates