| [ Index ] |
PHP Cross Reference of Drupal 6 (gatewave) |
[Summary view] [Print] [Text view]
1 <?php 2 // $Id: multicolumncheckboxesradios.module,v 1.39 2010/09/08 23:04:57 mattyoung Exp $ 3 /** 4 * @file multicolumncheckboxesradios.module 5 * Extends checkboxes/radios form element to have multi-column display option 6 * See README.txt for details 7 */ 8 9 10 11 12 function multicolumncheckboxesradios_widget_settings_alter(&$v, $op, $widget) { 13 $widget_types = array_merge(array( 14 'optionwidgets_buttons', 15 'content_taxonomy_options', 16 'nodereference_buttons', 17 'userreference_buttons', 18 'select_or_other_buttons', 19 ), variable_get('multicolumncheckboxesradios_extra_widget_types', array())); 20 21 if (in_array($widget['type'], $widget_types) || in_array($widget['widget_type'], $widget_types)) { 22 switch ($op) { 23 case 'form': 24 $v['multicolumncheckboxesradios'] = array( 25 '#type' => 'fieldset', 26 '#title' => t('Multicolumn checkbox/radio buttons widget display settings'), 27 '#description' => t('Adjust settings to display checkbox/radio buttons widget in columns.'), 28 '#collapsible' => TRUE, 29 '#collapsed' => FALSE, 30 '#weight' => 2, 31 ); 32 $v['multicolumncheckboxesradios']['mccr_width'] = array( 33 '#type' => 'select', 34 '#title' => t('Columns'), 35 '#options' => array(0 => t('Multi-column off'), 1 => '1', 2 => '2', 3 => '3', 4 => '4', 5 => '5', 6 => '6', 7 => '7', 8 => '8', 9 => '9'), 36 '#default_value' => isset($widget['mccr_width']) ? $widget['mccr_width'] : 1, 37 '#description' => t('The number of columns desired.'), 38 ); 39 $v['multicolumncheckboxesradios']['mccr_row-major'] = array( 40 '#type' => 'checkbox', 41 '#title' => t('Row-major'), 42 '#default_value' => isset($widget['mccr_row-major']) ? $widget['mccr_row-major'] : 0, 43 '#description' => t('Select this to display check boxes/radios button across the screen first, then down.'), 44 ); 45 $v['multicolumncheckboxesradios']['mccr_indent'] = array( 46 '#type' => 'select', 47 '#title' => t('Indent'), 48 '#options' => array(0 => '0', 1 => '1', 2 => '2', 3 => '3', 4 => '4', 5 => '5', 6 => '6', 7 => '7', 8 => '8'), 49 '#default_value' => isset($widget['mccr_indent']) ? $widget['mccr_indent'] : 0, 50 '#description' => t('The number of indentation desired.'), 51 ); 52 $v['multicolumncheckboxesradios']['mccr_caption'] = array( 53 '#type' => 'textfield', 54 '#title' => t('Caption'), 55 '#default_value' => isset($widget['mccr_caption']) ? $widget['mccr_caption'] : '', 56 '#description' => t('Table caption for the multicolumn checkboxes/radios.'), 57 ); 58 $v['multicolumncheckboxesradios']['mccr_column-heading'] = array( 59 '#type' => 'textarea', 60 '#title' => t('Column heading'), 61 '#default_value' => isset($widget['mccr_column-heading']) ? $widget['mccr_column-heading'] : '', 62 '#description' => t('The column heading each on a separate line.'), 63 ); 64 $v['multicolumncheckboxesradios']['mccr_row-heading'] = array( 65 '#type' => 'textarea', 66 '#title' => t('Row heading'), 67 '#default_value' => isset($widget['mccr_row-heading']) ? $widget['mccr_row-heading'] : '', 68 '#description' => t('The row heading each on a separate line.'), 69 ); 70 break; 71 case 'save': 72 $v = array_merge($v, array('mccr_width', 'mccr_row-major', 'mccr_indent', 'mccr_caption', 'mccr_column-heading', 'mccr_row-heading')); 73 break; 74 } 75 } 76 } 77 78 79 80 function multicolumncheckboxesradios_elements() { 81 return array( 82 'checkboxes' => array( 83 '#multicolumn' => FALSE, 84 '#process' => array('multicolumncheckboxesradios_element_process'), 85 ), 86 'radios' => array( 87 '#multicolumn' => FALSE, 88 '#process' => array('multicolumncheckboxesradios_element_process'), 89 ), 90 ); 91 } 92 93 94 95 /** 96 * Form element process function to add multi-column markup to checkboxes/radios 97 * 98 * @param $element 99 * @return the processed element 100 */ 101 function multicolumncheckboxesradios_element_process($element, $edit, &$form_state, $form) { 102 // only do this if it's coming from CCK, otherwise, let the normal form element through 103 if (empty($element['#multicolumn']) && isset($form['#field_info'])) { 104 $widget = &$form['#field_info'][$element['#parents'][0]]['widget']; 105 $temp = $widget['mccr_column-heading']; 106 if (!empty($temp)) { 107 $column_heading = explode("\r", trim($temp)); 108 } 109 $temp = $widget['mccr_row-heading']; 110 if (!empty($temp)) { 111 $row_heading = explode("\r", trim($temp)); 112 } 113 $element['#multicolumn'] = array( 114 'width' => $widget['mccr_width'], 115 'row-major' => $widget['mccr_row-major'], 116 'indent' => $widget['mccr_indent'], 117 'caption' => $widget['mccr_caption'], 118 'column-heading' => $column_heading, 119 'row-heading' => $row_heading, 120 ); 121 } 122 123 // if multicolumn option is not set or width parameter is not set, do nothing 124 if (empty($element['#multicolumn']) || empty($element['#multicolumn']['width'])) { 125 return $element; 126 } 127 128 129 $item_total = count($element['#options']) + (!empty($element['#multicolumn']['indent']) ? $element['#multicolumn']['indent'] : 0); 130 131 // in case there are fewer items than the width, then the width is just the 132 // item_total in one row 133 $width = min($item_total, $element['#multicolumn']['width']); 134 // if we end up with no elements, do nothing 135 if ($width < 1) { 136 return $element; 137 } 138 139 140 // copy and unset the checkboxe/radios child elements, we will rearrange them 141 $keys = array_keys($element['#options']); 142 $element_total = count($keys); 143 $copy = array(); 144 for ($i = 0 ; $i < $element_total ; ++$i) { 145 $copy[$keys[$i]] = $element[$keys[$i]]; 146 unset($element[$keys[$i]]); 147 } 148 149 $space = array( 150 '#type' => 'markup', 151 '#value' => ' ', 152 ); 153 154 if (!empty($element['#multicolumn']['indent'])) { 155 $indent = $element['#multicolumn']['indent']; 156 $spaces = array(); 157 for ($i = 0 ; $i < $indent ; ++$i) { 158 $spaces["multicolumncheckboxesradios-space-$i"] = $space; 159 } 160 $copy = $spaces + $copy; 161 } 162 163 164 if (empty($element['#multicolumn']['row-major'])) { 165 $rows = _multicolumncheckboxesradios_chunk_transpose($copy, $width); 166 } 167 else { 168 $rows = array_chunk($copy, $width, TRUE); 169 } 170 171 // fill the last row tail end with space if it's shorter than $width 172 $last_row = &$rows[count($rows) - 1]; 173 while (($last_row_size = count($last_row)) < $width) { 174 $last_row["multicolumncheckboxesradios-tail-space-$last_row_size"] = $space; 175 } 176 177 // prepend the row heading in each row 178 $has_row_heading = !empty($element['#multicolumn']['row-heading']); 179 if ($has_row_heading) { 180 $i = 0; 181 $row_count = count($rows); 182 foreach ($element['#multicolumn']['row-heading'] as $h) { 183 if ($i < $row_count) { 184 $rows[$i] = array("multicolumncheckboxesradios-row-heading-$i" => array('#type' => 'markup', '#value' => $h)) + $rows[$i]; 185 } 186 else { 187 $rows[$i] = array("multicolumncheckboxesradios-row-heading-$i" => array('#type' => 'markup', '#value' => $h)); 188 } 189 ++$i; 190 } 191 for ( ; $i < $row_count ; ++$i) { 192 $rows[$i] = array("multicolumncheckboxesradios-row-heading-$i" => $space) + $rows[$i]; 193 } 194 } 195 196 197 $markup = ''; 198 $table_class = 'class="multicolumncheckboxesradios-table"'; 199 $has_column_heading = !empty($element['#multicolumn']['column-heading']); 200 if ($has_column_heading) { 201 $table_class = 'class="multicolumncheckboxesradios-table sticky-enabled"'; 202 drupal_add_js('misc/tableheader.js'); 203 204 $markup = _multicolumncheckboxesradios_make_heading_markup($element['#multicolumn']['column-heading'], 205 'multicolumncheckboxesradios-column-heading', 206 'multicolumncheckboxesradios-column-heading-first', 207 'multicolumncheckboxesradios-column-heading-last'); 208 if ($has_row_heading) { 209 $markup = '<th class="multicolumncheckboxesradios-heading-corner"> </th>' . $markup; 210 } 211 212 $markup = '<thead><tr>' . $markup . '</tr></thead>'; 213 } 214 215 $caption = trim($element['#multicolumn']['caption']); 216 if (!empty($caption)) { 217 $markup = '<caption>' . $caption . '</caption>' . $markup; 218 } 219 220 $element['multicolumncheckboxesradios-table-open'] = array( 221 '#type' => 'markup', 222 '#value' => '<table ' . $table_class . '>' . $markup . '<tbody>', 223 ); 224 225 226 $flip = array('even' => 'odd', 'odd' => 'even'); 227 $class = 'even'; 228 foreach ($rows as &$row) { 229 $class = $flip[$class]; 230 $keys = array_keys($row); 231 $row_size = count($keys); 232 switch ($row_size) { 233 case 1: 234 if ($has_row_heading) { 235 $row[$keys[0]]['#prefix'] = "<tr class=\"$class\"><td class=\"multicolumncheckboxesradios-row-heading\">"; 236 $row[$keys[0]]['#suffix'] = '</td></tr>'; 237 } 238 else { 239 $row[$keys[0]]['#prefix'] = "<tr class=\"$class\"><td class=\"multicolumncheckboxesradios-column-first multicolumncheckboxesradios-column multicolumncheckboxesradios-column-last\">"; 240 $row[$keys[0]]['#suffix'] = '</td></tr>'; 241 } 242 break; 243 case 2: 244 if ($has_row_heading) { 245 $row[$keys[0]]['#prefix'] = "<tr class=\"$class\"><td class=\"multicolumncheckboxesradios-row-heading\">"; 246 $row[$keys[0]]['#suffix'] = '</td>'; 247 $row[$keys[1]]['#prefix'] = "<td class=\"multicolumncheckboxesradios-column-first multicolumncheckboxesradios-column multicolumncheckboxesradios-column-last\">"; 248 $row[$keys[1]]['#suffix'] = '</td></tr>'; 249 } 250 else { 251 $row[$keys[0]]['#prefix'] = "<tr class=\"$class\"><td class=\"multicolumncheckboxesradios-column-first multicolumncheckboxesradios-column\">"; 252 $row[$keys[0]]['#suffix'] = '</td>'; 253 $row[$keys[1]]['#prefix'] = '<td class="multicolumncheckboxesradios-column multicolumncheckboxesradios-column-last">'; 254 $row[$keys[1]]['#suffix'] = '</td></tr>'; 255 } 256 break; 257 default: 258 if ($has_row_heading) { 259 $row[$keys[0]]['#prefix'] = "<tr class=\"$class\"><td class=\"multicolumncheckboxesradios-row-heading\">"; 260 $row[$keys[0]]['#suffix'] = '</td>'; 261 $row[$keys[1]]['#prefix'] = '<td class="multicolumncheckboxesradios-column-first multicolumncheckboxesradios-column">'; 262 $row[$keys[1]]['#suffix'] = '</td>'; 263 264 $end_index = $row_size - 1; 265 for ($i = 2 ; $i < $end_index ; ++$i) { 266 $row[$keys[$i]]['#prefix'] = '<td class="multicolumncheckboxesradios-column">'; 267 $row[$keys[$i]]['#suffix'] = '</td>'; 268 } 269 270 $row[$keys[$end_index]]['#prefix'] = '<td class="multicolumncheckboxesradios-column multicolumncheckboxesradios-column-last">'; 271 $row[$keys[$end_index]]['#suffix'] = '</td></tr>'; 272 } 273 else { 274 $row[$keys[0]]['#prefix'] = "<tr class=\"$class\"><td class=\"multicolumncheckboxesradios-column-first multicolumncheckboxesradios-column\">"; 275 $row[$keys[0]]['#suffix'] = '</td>'; 276 277 $end_index = $row_size - 1; 278 for ($i = 1 ; $i < $end_index ; ++$i) { 279 $row[$keys[$i]]['#prefix'] = '<td class="multicolumncheckboxesradios-column">'; 280 $row[$keys[$i]]['#suffix'] = '</td>'; 281 } 282 $row[$keys[$end_index]]['#prefix'] = '<td class="multicolumncheckboxesradios-column multicolumncheckboxesradios-column-last">'; 283 $row[$keys[$end_index]]['#suffix'] = '</td></tr>'; 284 } 285 break; 286 } 287 } 288 289 foreach ($rows as &$row) { 290 foreach ($row as $k => &$v) { 291 $element[$k] = $v; 292 } 293 } 294 295 $element['multicolumncheckboxesradios-table-close'] = array( 296 '#type' => 'markup', 297 '#value' => '</tbody></table>', 298 ); 299 300 // default stylesheet 301 drupal_add_css(drupal_get_path('module', 'multicolumncheckboxesradios') .'/multicolumncheckboxesradios.css'); 302 303 return $element; 304 } 305 306 307 /** 308 * Break the 1D array into 2D chunk array, always satify the $width value by 309 * varying the height of each chunk, then transpose it. 310 * 311 * @param array $items element to break up 312 * @param int $width the width 313 * @return array the result in 2D array 314 */ 315 function _multicolumncheckboxesradios_chunk_transpose($items, $width) { 316 $result = array(); 317 318 if ($width == 1) { 319 foreach ($items as $k => &$v) { 320 $result[] = array($k => $v); 321 } 322 } 323 else { 324 $keys = array_keys($items); 325 326 $total = count($items); 327 $counter = 0; 328 $a = array(); 329 for ($i = 0 ; $i < $width ; ++$i) { 330 $height = ceil(($total - $counter) / ($width - $i)); 331 $a[$i] = array_slice($keys, $counter, $height); 332 $counter += $height; 333 } 334 335 // transpose 336 array_unshift($a, NULL); 337 $b = call_user_func_array('array_map', $a); 338 // transpose can result in NULL value at the end, clear them 339 $last_row = &$b[count($b) - 1]; 340 341 while (end($last_row) == NULL) { 342 array_pop($last_row); 343 } 344 345 foreach ($b as $i => &$key_row) { 346 $key_row = (array) $key_row; 347 foreach ($key_row as $key) { 348 $result[$i][$key] = $items[$key]; 349 } 350 } 351 } 352 return $result; 353 } 354 355 356 /** 357 * Take an array of string, produce a string of HTML markup of each string as 358 * <div class="regular first">item-first</div><div class="regular">item-n</div>... 359 * <div class="regular last">item-last</div> 360 * 361 * @param array $items string items 362 * @param string $class_regular class name normally 363 * @param string $class_first class name in the first position 364 * @param string $class_last class name in the last position 365 * @return string the HTML markup 366 */ 367 function _multicolumncheckboxesradios_make_heading_markup($items, $class_regular, $class_first, $class_last) { 368 $i = 1; 369 $total = count($items); 370 $result = ''; 371 foreach ($items as $item) { 372 $class_string = $class_regular; 373 if ($i == 1) { 374 $class_string .= ' ' . $class_first; 375 } 376 if ($i == $total) { 377 $class_string .= ' ' . $class_last; 378 } 379 $result .= "<th class=\"$class_string\">$item</th>"; 380 ++$i; 381 } 382 return $result; 383 }
title
Description
Body
title
Description
Body
title
Description
Body
title
Body
| Generated: Thu Mar 24 11:18:33 2011 | Cross-referenced by PHPXref 0.7 |