0

Change the weight of your items by drag and drop

Posted July 2nd, 2010 in by thomas

Hello,

Ever wanted how to re-order your items (nodes, custom,…) easily with drag and drop just like drupal do with menus ?

It can be done with the function

the process can be divided in 3 steps

- build a form (to change weight of your items)
- theme it as a table (to add the js stuff)
- update weight items in db (..to save it)

Let’s take the example of Benecol. They want to display / send 21 tips, 1 a day. A solution can be to store the day of the tip in the edit / add form and update it if necessary. but if we want to change day 20 to day 2 we have to update every tips from 2 to 20… not very handy and can be source if errors.

this update can be done easily with drag and drop, without errors !
in this example we will create a table containing the 21steps and displayed with step number, title, body and an edit link

1. build a form

function benecol_eplan_display_content_form() {
 $r = db_query("select title, nid, field_estdnumb_value as step, body 
 from node inner join node_revisions using(nid)
 inner join content_type_estep using(nid) 
 order by field_estdnumb_value");
 while ($row = db_fetch_object($r)){
 //create a partial table row containing the data from the table
 $data = array(
 "(".$row->step.")",
 $row->title,
 truncate_utf8(strip_tags($row->body),100,TRUE,TRUE),
 l(t('edit'), "node/".$row->nid."/edit", array('query'=>drupal_get_destination()))
 );
 //add our static "row" data into a form value
 $form['rows'][$row->nid]['data']=array('#type' => 'value','#value' => $data);
 //now create the weight form element. (if js is enabled, it will be hidden by core tabledrag.js) 
 $form['rows'][$row->nid]['weight-'.$row->nid]=array(
 '#type'=>'textfield',
 '#size'=>5,
 '#default_value'=>$row->step,
 '#attributes' => array('class'=>'weight'),
 );
 }    
 //add submit
 $form['submit']=array(
 '#type'=>'submit',
 '#value'=>t('Save changes'),
 );
 return $form;
}

2. theme the form as a table

function theme_benecol_eplan_display_content_form($form){
//loop through each "row" in the table array
 foreach($form['rows'] as $id => $row){
 //we are only interested in numeric keys
 if (intval($id)){  
 $this_row = $row['data']['#value'];
 //Add the weight field to the row
 $this_row[] = drupal_render($form['rows'][$id]['weight-'.$id]);
 //Add the row to the array of rows and css class for js
 $table_rows[] = array('data'=>$this_row, 'class'=>'draggable');
 }
 }
 //Make sure the header count matches the column count
 $header=array(
 t("Day"),t("Title"), t("Body"),t("Edit"),t("Order")
 );
 $output = theme('table',$header,$table_rows,array('id'=>'esptep-table'));
 $output .= drupal_render($form);
//will add tabledrag.js
 drupal_add_tabledrag('esptep-table', 'order', 'sibling', 'weight');      
 return $output;
}

3. update weight in db on submit

function benecol_eplan_display_content_form_submit($form, &$form_state) {
 foreach($form_state['values'] as $key=>$data){
 //we are only interested in weight elements
 if (substr($key,0,6)=='weight' && is_numeric($data)) {
 //we have the DB id of the row in the element name
 $id = str_replace('weight-','',$key);
//and the order in $data
 db_query("UPDATE {content_type_estep} SET field_estdnumb_value=%d WHERE nid=%d",$data,$id);
 }
 }
}

Leave a Reply