Drupal: parent-child drag table

So, I'm already going for it. I am trying to create a drag and drop table that has a parent-child relationship, but where the children cannot be moved from the parent group, and all parents are sorted among themselves. I modeled my form and theme outside the admin menu code, and I have this duplication of this functionality. The problem is that I can move children to another parent or allow him to become a parent. By way of illustration:

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

I would like to be able to sort positions 1 and paragraph 2 with each other, as well as paragraphs 3, paragraph 4 and paragraph 5 with each other, but not move them between categories 1 and 2. I also need able to sort categories 1 and category 2 each with a friend, forcing the children with them. I made many combinations of the $action , $group , $subgroup settings mixed with the $class settings for the categories and elements that I lost. None of what I have tried so far has produced the desired result. Here are the relevant bits of my code, as of now:

In my form:

 $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')), ), ); } } } 

In my topic:

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

I read the documentation for drupal_add_tabledrag() , looked at the code, looked at the code example and searched around drupal.org and Google, but came up with nothing.

My only solution so far is to copy and modify the tabledrag.js file to simply eliminate these features, but when stopping the indentation problem with the elements (which means not allowing them to be the same with the categories), keeping them in that the same category was Not Fun.

I believe the most important question is: is it possible to use standard Drupal?

+4
source share
3 answers

I know that you have already done a lot of coding, so you cannot refuse this, but DraggableViews does a great job of this. You can adjust the normal view and add this draggableviews filter, it will add weight and possibly a parent link. The view itself uses the same drag-n-drop system as the rest of the Drupal base tables.

Alternatively, you can use the link to the terms and bind taxonomy terms to nodes and just use this drag-n-drop function.

If something is missing in your needs, my apologies, I just thought that I was proposing this simpler solution, since it definitely served me in the past. Good luck anyway.

0
source

Just finished adding this feature to my module

https://github.com/player259/ajax_table

There is no help, the demonstration is out of date, but I work on it from time to time.

Partition support was achieved by overriding tabledrag.js functions

Use this snippet to insert a table.

 $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
source

I had a similar problem, so I posted my solution here, since none of them found workable in any situation. This is 100% done in javascript, on the php side you just need to set tabledrag according to the parent to pid and sort by siblings by weight.

Current code is working on an example module (tabledrag parent / child) to adapt it to your needs by changing the .example-item-pid parameter with your class for the PID input field. You just need to add it to the sample code for it to work, and see if it fits your needs.

The first function cancels any attempt to delete elements that do not have the same parent (PID) than the target element.

The second function bypasses the dragRow function to remove the element in the right place (= the last children of the target row) and at the desired depth (= the same depth as the target row).

 /** * 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; } }; 
0
source

All Articles