2011-10-21 3 views
4

Так что я уже давно это делаю. Я пытаюсь создать таблицу перетаскивания, которая имеет отношения родитель-потомок, но где дети не могут быть перемещены из родительской группы, и все родители сортируются между собой. Я смоделировал свою форму и тему вне кода меню администратора, и у меня есть это дублирование этой функциональности. Проблема в том, что я могу переместить детей другому родителю или позволить ему стать родителем. В качестве иллюстрации:Drupal: Перетаскиваемый стол родительского ребенка

Category 1 
| 
|--Item 1 
|--Item 2 
Category 2 
| 
|--Item 3 
|--Item 4 
|--Item 5 

Я хотел бы иметь возможность сортировать пункт 1 и пункт 2 друг с другом, а также пункт 3, пункт 4, и пункт 5 друг с другом, но не перемещать их между категории 1 и Категория 2. Мне также нужно иметь возможность сортировать категории 1 и категорию 2 друг с другом, беря с собой детей. Я прошел через множество комбинаций $action, $group, $subgroup настроек, смешанных с $class настройками для категорий и элементов, которые я потерял. Ничто из того, что я пробовал до сих пор, не вызвало желаемого результата. Вот соответствующие биты моего кода, как это в настоящее время:

В моей форме:

$form['#tree'] = true; 
foreach($categories as $cat) { 
    if(!isset($form['categories'][$cat->cid])){ 
     $form['categories'][$cat->cid] = array(
      'weight' => array(
       '#type'   => 'weight', 
       '#delta'  => 25, 
       '#attributes' => array('class' => array('item-weight', 'item-weight-' . $cat->cid)), 
      ), 
      'cid' => array(
       '#type'   => 'hidden', 
       '#value'  => $cat->cid, 
       '#attributes' => array('class' => array('cid')), 
      ), 
     ); 
     foreach($cats[$cat->cid] as $item) { 
      $form['categories'][$cat->cid]['items'][$item->id] = array(
       'weight' => array(
        '#type'   => 'weight', 
        '#delta'  => 25, 
        '#default_value'=> $item->weight, 
        '#attributes' => array('class' => array('item-weight', 'item-weight-' . $cat->cid)), 
       ), 
       'cid' => array(
        '#type'   => 'hidden', 
        '#value'  => $cat->cid, 
        '#attributes' => array('class' => array('cid')), 
       ), 
      ); 
     } 
    } 
} 

В моей теме:

$children = element_children($form['categories']); 
$rows = array(); 
if(count($children) > 0) { 
    foreach($children as $cid) { 
     $row = array(
      drupal_render($form['categories'][$cid]['weight']) . 
       drupal_render($form['categories'][$cid]['cid']), 
     ); 

     $rows[] = array(
      'data' => $row, 
      'class' => array('draggable', 'tabledrag-root'), 
     ); 
     foreach(element_children($form['categories'][$cid]['items']) as $id) { 
      $row = array(
       theme('indentation', array('size' => 1)) . drupal_render($form['categories'][$cid]['items'][$id]['name']), 
       drupal_render($form['categories'][$cid]['items'][$id]['weight']) . 
        drupal_render($form['categories'][$cid]['items'][$id]['cid']), 
      ); 

      $rows[] = array(
       'data' => $row, 
       'class' => array('draggable', 'tabledrag-leaf'), 
      ); 
     } 
     drupal_add_tabledrag('cat-table', 'order', 'sibling', 'item-weight', 'item-weight-' . $cid); 
    } 
} 


drupal_add_tabledrag('cat-table', 'match', 'parent', 'cid', 'cid', 'cid', true, 1); 
$output = theme('table', array('header' => $headers, 'rows' => $rows, 'attributes' => array('id' => 'cat-table'))); 
$output .= drupal_render_children($form); 
return $output; 

Я перечитал документацию для drupal_add_tabledrag(), смотрели на код, посмотрел пример кода и обыскал вокруг drupal.org и Google, но ничего не придумал.

Мое единственное решение до сих пор заключается в том, чтобы скопировать и изменить файл tabledrag.js, чтобы просто устранить эти возможности, но при остановке проблемы с отступом с элементами (что означает, не позволяя им быть одинаковыми с категориями), сохраняя их в той же категории было не забава.

Я полагаю, что самый важный вопрос: использование стандартного Drupal - это возможно?

+0

как abt использовать fieldset для его форматирования? http://api.drupal.org/api/drupal/developer!topics!forms_api_reference.html/7#fieldset –

ответ

0

Я знаю, что вы уже сделали много кодирования, поэтому вы не можете отказаться от этого на данный момент, но DraggableViews отлично подходит для этого. Вы можете настроить нормальный вид и добавить этот фильтр draggableviews, он добавит вес и, возможно, родительскую ссылку. В самом представлении используется одна и та же система drag-n-drop, как и остальные бэкэнд-таблицы Drupal.

В качестве альтернативы вы можете использовать термины и термины таксономии связи для узлов, и просто используйте это drag-n-drop.

Если мне что-то недостает в ваших потребностях, извини, просто подумал, что я предлагаю это более простое решение, поскольку оно определенно послужило мне в прошлом. Удачи в любом случае.

+0

Как вы это сделаете без модуля? Это должно быть возможно с помощью drupal_add_tabledrag, но я тоже не могу найти способ предотвратить перетаскивание перекрестного родителя. Таблица, которую я сортирую, - это форма, а не относящиеся к обоим. – Kevin

0

Только что закончил добавить эту функциональность в мой модуль

https://github.com/player259/ajax_table

Там нет никакой помощи, демо устарел, но я работаю над этим время от времени

поддержка

Секции была достигнута главенствующий tabledrag.js функция

Используйте этот фрагмент кода для вставки таблицы

$form['map'] = array(
    '#type' => 'ajax_table', 
    '#header' => array(t('Element'), t('Settings'), t('Weight')), 
    'rows' => array(), 
    '#draggable' => array(
    // drupal_add_tabledrag will be called in theme layer 
    // NULL first arg to apply to this table 
    array(NULL, 'match', 'parent', 'perfect-form-parent', 'perfect-form-parent', 'perfect-form-index'), 
    array(NULL, 'depth', 'group', 'perfect-form-depth', NULL, NULL, FALSE), 
    array(NULL, 'order', 'sibling', 'perfect-form-weight'), 
), 
    '#draggable_groups' => array(), 
); 

foreach ($map as $i => $element) { 

    // ... some logic 

    $form['map']['rows'][$i] = array(
    'data' => array(
     'element' => array(), 
     'settings' => array(), 
     'tabledrag' => array(
     'index' => array(
      '#type' => 'hidden', 
      '#value' => $element['data']['tabledrag']['index'], 
      '#attributes' => array('class' => array('perfect-form-index')), 
     ), 
     'parent' => array(
      '#type' => 'hidden', 
      '#default_value' => $element['data']['tabledrag']['parent'], 
      '#attributes' => array('class' => array('perfect-form-parent')), 
     ), 
     'depth' => array(
      '#type' => 'hidden', 
      '#default_value' => $element['data']['tabledrag']['depth'], 
      '#attributes' => array('class' => array('perfect-form-depth')), 
     ),   
     'weight' => array(
      '#type' => 'weight', 
      '#delta' => $max_weight, 
      '#default_value' => $weight, 
      '#attributes' => array('class' => array('perfect-form-weight')), 
     ), 
    ), 
    ), 
    '#attributes' => array('class' => array($row_class_current, $row_class_child)), 
); 

    // This means that row with $row_class_child class could have as parent 
    // only row with $row_class_parent class 
    // NULL means root - there are no parents 

    $form['map']['#draggable_groups'][$row_class_child] = 
    $depth ? $row_class_parent : NULL; 
} 
0

У меня была аналогичная проблема при работе, поэтому я разместил здесь свое решение, так как ни один из них не работал правильно во всех ситуациях.Это делается на 100% в javascript, на стороне php вам просто нужно установить tabledrag в соответствии с родителем на pid и отсортировать с родными братьями по весу.

Текущий код работает над модулем примера (tabledrag parent/child), чтобы адаптировать его к вашим потребностям, изменив параметр .example-item-pid вашим классом для поля ввода PID. Вам просто нужно добавить его в примерный код, чтобы он работал, и посмотреть, соответствует ли он вашей потребностям.

Первая функция аннулирует любую попытку удаления элементов, которые не имеют одного и того же родителя (PID), чем целевой элемент.

Вторая функция обходит функцию dragRow, чтобы удалить элемент в нужном месте (= последние дети целевой строки) и на нужной глубине (= такая же глубина, что и целевая строка).

/** 
* Invalidate swap check if the row target is not of the same parent 
* So we can only sort elements under the same parent and not move them to another parent 
* 
* @override Drupal.tableDrag.row.isValidSwap 
*/ 
// Keep the original implementation - we still need it. 
Drupal.tableDrag.prototype.row.prototype._isValidSwap = Drupal.tableDrag.prototype.row.prototype.isValidSwap; 
Drupal.tableDrag.prototype.row.prototype.isValidSwap = function(row) { 
    if (this.indentEnabled) { 
    if (row && $('.example-item-pid', this.element).val() !== $('.example-item-pid', row).val()) { 
     return false; 
    } 
    } 

    // Return the original result. 
    return this._isValidSwap(row); 
} 

/** 
* Position the dragged element under the last children of the element target for swapping when moving down our dragged element. 
* Removed the indentation, since we can not change parent. 
* @override Drupal.tableDrag.row.dragRow 
*/ 
Drupal.tableDrag.prototype.dragRow = function (event, self) { 
    if (self.dragObject) { 
    self.currentMouseCoords = self.mouseCoords(event); 

    var y = self.currentMouseCoords.y - self.dragObject.initMouseOffset.y; 
    var x = self.currentMouseCoords.x - self.dragObject.initMouseOffset.x; 

    // Check for row swapping and vertical scrolling. 
    if (y != self.oldY) { 
     self.rowObject.direction = y > self.oldY ? 'down' : 'up'; 
     self.oldY = y; // Update the old value. 

     // Check if the window should be scrolled (and how fast). 
     var scrollAmount = self.checkScroll(self.currentMouseCoords.y); 
     // Stop any current scrolling. 
     clearInterval(self.scrollInterval); 
     // Continue scrolling if the mouse has moved in the scroll direction. 
     if (scrollAmount > 0 && self.rowObject.direction == 'down' || scrollAmount < 0 && self.rowObject.direction == 'up') { 
     self.setScroll(scrollAmount); 
     } 

     // If we have a valid target, perform the swap and restripe the table. 
     var currentRow = self.findDropTargetRow(x, y); 
     if (currentRow) { 
     if (self.rowObject.direction == 'down') { 

      /** 
      * When going down we want to position the element after the last children and not right under the currentRow 
      */ 
      // create a new row prototype with currentRow 
      var rowObject = new self.row(currentRow, 'mouse', self.indentEnabled, self.maxDepth, false); 
      // extract all children 
      var childrenRows = rowObject.findChildren(); 
      // if we have children 
      if (childrenRows.length > 0) { 
      // we change the row to swap with the last children 
      currentRow = childrenRows[childrenRows.length - 1]; 
      } 

      self.rowObject.swap('after', currentRow, self); 
     } 
     else { 
      self.rowObject.swap('before', currentRow, self); 
     } 
     self.restripeTable(); 
     } 
    } 
    /** 
    * We have disabled the indentation changes since it is not possible to change parent. 
    */ 

    return false; 
    } 
}; 
Смежные вопросы