| [ Index ] |
|
Code source de b2evolution 2.1.0-beta |
1 <?php 2 /** 3 * This file implements the Fast Form handling class. 4 * 5 * This file is part of the evoCore framework - {@link http://evocore.net/} 6 * See also {@link http://sourceforge.net/projects/evocms/}. 7 * 8 * @copyright (c)2003-2007 by Francois PLANQUE - {@link http://fplanque.net/} 9 * Parts of this file are copyright (c)2004 by PROGIDISTRI - {@link http://progidistri.com/}. 10 * Parts of this file are copyright (c)2004-2005 by Daniel HAHLER - {@link http://thequod.de/contact}. 11 * 12 * {@internal License choice 13 * - If you have received this file as part of a package, please find the license.txt file in 14 * the same folder or the closest folder above for complete license terms. 15 * - If you have received this file individually (e-g: from http://evocms.cvs.sourceforge.net/) 16 * then you must choose one of the following licenses before using the file: 17 * - GNU General Public License 2 (GPL) - http://www.opensource.org/licenses/gpl-license.php 18 * - Mozilla Public License 1.1 (MPL) - http://www.opensource.org/licenses/mozilla1.1.php 19 * }} 20 * 21 * {@internal Open Source relicensing agreement: 22 * Daniel HAHLER grants Francois PLANQUE the right to license 23 * Daniel HAHLER's contributions to this file and the b2evolution project 24 * under any OSI approved OSS license (http://www.opensource.org/licenses/). 25 * 26 * PROGIDISTRI grants Francois PLANQUE the right to license 27 * PROGIDISTRI's contributions to this file and the b2evolution project 28 * under any OSI approved OSS license (http://www.opensource.org/licenses/). 29 * }} 30 * 31 * @package evocore 32 * 33 * {@internal Below is a list of authors who have contributed to design/coding of this file: }} 34 * @author blueyed: Daniel HAHLER 35 * @author fplanque: Francois PLANQUE. 36 * @author fsaya: Fabrice SAYA-GASNIER / PROGIDISTRI 37 * @author mbruneau: Marc BRUNEAU / PROGIDISTRI 38 * 39 * @todo Provide buffering of whole Form to be able to add onsubmit-JS to enable/disabled 40 * (group) checkboxes again and other useful stuff. 41 * 42 * NOTE: we use an member array ($_common_params) for exchanging params between functions. 43 * This will most probably cause problems, when nesting inputs. This should be refactored 44 * to use a field_name-based member array. (blueyed) 45 * 46 * @version $Id: _form.class.php,v 1.16 2007/11/02 02:39:57 fplanque Exp $ 47 */ 48 if( !defined('EVO_MAIN_INIT') ) die( 'Please, do not access this page directly.' ); 49 50 load_funcs( '_core/ui/_uiwidget.class.php' ); 51 52 /** 53 * Form class 54 * 55 * @package evocore 56 */ 57 class Form extends Widget 58 { 59 /** 60 * Output HTML or just return it? 61 * @var boolean 62 */ 63 var $output = true; 64 65 /** 66 * Remember number of open tags that need to be handled in {@link end_form()}. 67 * 68 * @var array 69 */ 70 var $_opentags = array( 'fieldset' => 0 ); 71 72 /** 73 * Suffix for LABELs. 74 * @var string 75 */ 76 var $label_suffix = ':'; 77 78 79 /** 80 * Common params shared between methods. 81 * 82 * These can all be used with the $field_params argument of the functions. 83 * 84 * - 'note': The note associated with the field. 85 * - 'note_format': The format of the note. %s gets replaced by the note. 86 * - 'label': The label for the field. 87 * - 'required': is the element required to be filled/checked? This will add a visual hint (boolean; default: false) 88 * 89 * @see handle_common_params() 90 * @var array 91 */ 92 var $_common_params = array(); 93 94 /** 95 * This is the default note format, where {@link handle_common_params()} falls 96 * back to, when not given with $field_params. 97 * @todo This might be used in switch_layout(). 98 * @var string 99 */ 100 var $note_format = ' <span class="notes">%s</span>'; 101 102 /** 103 * This is a buffer for hidden fields. We'll display all of them just before the end of form </form>. This avoids having them caught in between table rows. 104 * 105 * @var string 106 */ 107 var $hiddens = array(); 108 109 /** 110 * Do we need to add javascript for check/uncheck all functionality 111 */ 112 var $check_all = false; 113 114 /** 115 * Additional Javascript to append to the form, in {@link Form::end_form()}. 116 * 117 * @access protected 118 * @var array 119 */ 120 var $append_javascript = array(); 121 122 /** 123 * Display param errors with fields, appended to the note? 124 * @var boolean 125 */ 126 var $disp_param_err_messages_with_fields = true; 127 128 /** 129 * Stack of previous used layouts 130 * @see Form::switch_layout() 131 * @var array 132 */ 133 var $saved_layouts; 134 var $saved_templates; 135 136 137 /** 138 * Constructor 139 * 140 * @param string the action destination of the form (NULL for pagenow) 141 * @param string the name of the form (will be used as an ID) 142 * @param string the action to execute when the form is submitted 143 * @param string the method used to send data 144 * @param string the form layout : 'fieldset', 'table' or '' (NULL means: if there is an {@link $AdminUI} object get it from there, otherwise use 'fieldset') 145 */ 146 function Form( $form_action = NULL, $form_name = '', $form_method = 'post', $layout = NULL, $enctype = '' ) 147 { 148 global $AdminUI, $pagenow; 149 150 $this->form_name = $form_name; 151 $this->form_action = (is_null($form_action) ? $pagenow : $form_action ); 152 $this->form_method = $form_method; 153 $this->enctype = $enctype; 154 155 if( is_null( $layout ) || $layout == 'split' || $layout == 'none' ) 156 { 157 if( is_object($AdminUI) ) 158 { // Get default skin setting: 159 $template = $AdminUI->get_template( 'Form' ); 160 $layout = $template['layout']; 161 } 162 else 163 { // This happens for comment forms for example... 164 $layout = 'fieldset'; 165 } 166 } 167 elseif( $layout == 'compact' ) 168 { 169 $template = $AdminUI->get_template( 'compact_form' ); 170 $layout = $template['layout']; 171 } 172 173 if( !isset($template) && $layout == 'fieldset' ) 174 { // happens on login screen and after $layout setting above 175 $template = array( 176 'layout' => 'fieldset', 177 'formstart' => '<div>',// required before (no_)title_fmt for validation 178 'title_fmt' => '<span style="float:right">$global_icons$</span><h2>$title$</h2>'."\n", 179 'no_title_fmt' => '<span style="float:right">$global_icons$</span>'."\n", 180 'fieldset_begin' => '<fieldset $fieldset_attribs$>'."\n" 181 .'<legend $title_attribs$>$fieldset_title$</legend>'."\n", 182 'fieldset_end' => '</fieldset>'."\n", 183 'fieldstart' => '<fieldset $ID$>'."\n", 184 'labelstart' => '<div class="label">', 185 'labelend' => "</div>\n", 186 'labelempty' => '<div class="label"></div>', // so that IE6 aligns DIV.input correcctly 187 'inputstart' => '<div class="input">', 188 'infostart' => '<div class="info">', 189 'inputend' => "</div>\n", 190 'fieldend' => "</fieldset>\n\n", 191 'buttonsstart' => '<fieldset><div class="input">', 192 'buttonsend' => "</div></fieldset>\n\n", 193 'formend' => '</div>', 194 ); 195 } 196 197 $this->saved_layouts = array($layout); 198 $this->saved_templates = array($template); 199 $this->switch_layout( NULL ); // "restore" saved layout. 200 201 } 202 203 204 /** 205 * @param string|NULL the form layout : 'fieldset', 'table' or ''; NULL to restore previsouly saved layout 206 */ 207 function switch_layout( $layout ) 208 { 209 if( $layout == NULL ) 210 { // we want to restore previous layout: 211 if( count($this->saved_layouts) ) 212 { 213 $this->layout = array_shift($this->saved_layouts); 214 // Temporary hack: 215 $template = array_shift($this->saved_templates); 216 if( !empty($template ) ) 217 { 218 //pre_dump($template); 219 $this->template = $template; 220 $this->formstart = $template['formstart']; 221 $this->title_fmt = $template['title_fmt']; 222 $this->no_title_fmt = $template['no_title_fmt']; 223 $this->fieldstart = $template['fieldstart']; 224 $this->labelstart = $template['labelstart']; 225 $this->labelend = $template['labelend']; 226 $this->labelempty = $template['labelempty']; 227 $this->inputstart = $template['inputstart']; 228 $this->infostart = $template['infostart']; 229 $this->inputend = $template['inputend']; 230 $this->fieldend = $template['fieldend']; 231 $this->buttonsstart = $template['buttonsstart']; 232 $this->buttonsend = $template['buttonsend']; 233 $this->formend = $template['formend']; 234 } 235 } 236 } 237 else 238 { // We want to switch to a new layout 239 array_unshift( $this->saved_layouts, $this->layout ); 240 $this->layout = $layout; 241 242 switch( $this->layout ) 243 { 244 case 'table': 245 $this->formstart = '<table cellspacing="0" class="fform">'."\n"; 246 // Note: no thead in here until you can safely add a tbody to the rest of the content... 247 $this->title_fmt = '<tr class="formtitle"><th colspan="2"><div class="results_title">' 248 .'<span class="right_icons">$global_icons$</span>' 249 .'$title$</div></th></tr>'."\n"; 250 $this->no_title_fmt = '<tr><th colspan="2"><span class="right_icons">$global_icons$</span></th></tr>'."\n"; 251 $this->fieldstart = '<tr $ID$>'."\n"; 252 $this->labelstart = '<td class="label">'; 253 $this->labelend = "</td>\n"; 254 $this->labelempty = '<td class="label"> </td>'."\n"; 255 $this->inputstart = '<td class="input">'; 256 $this->infostart = '<td class="info">'; 257 $this->inputend = "</td>\n"; 258 $this->fieldend = "</tr>\n\n"; 259 $this->buttonsstart = '<tr class="buttons"><td colspan="2">'; 260 $this->buttonsend = "</td></tr>\n"; 261 $this->formend = "</table>\n"; 262 break; 263 264 case 'fieldset': 265 $this->formstart = '<div>';// required before (no_)title_fmt for validation 266 $this->title_fmt = '<span style="float:right">$global_icons$</span><h2>$title$</h2>'."\n"; 267 $this->no_title_fmt = '<span style="float:right">$global_icons$</span>'."\n"; 268 $this->fieldstart = '<fieldset $ID$>'."\n"; 269 $this->labelstart = '<div class="label">'; 270 $this->labelend = "</div>\n"; 271 $this->labelempty = '<div class="label"></div>'; // so that IE6 aligns DIV.input correcctly 272 $this->inputstart = '<div class="input">'; 273 $this->infostart = '<div class="info">'; 274 $this->inputend = "</div>\n"; 275 $this->fieldend = "</fieldset>\n\n"; 276 $this->buttonsstart = '<fieldset><div class="input">'; 277 $this->buttonsend = "</div></fieldset>\n\n"; 278 $this->formend = '</div>'; 279 break; 280 281 case 'chicago': // Temporary dirty hack 282 $this->formstart = '<div>';// required before (no_)title_fmt for validation 283 $this->title_fmt = '<span style="float:right">$global_icons$</span><h2>$title$</h2>'."\n"; 284 $this->no_title_fmt = '<span style="float:right">$global_icons$</span>'."\n"; 285 $this->fieldstart = '<fieldset $ID$>'."\n"; 286 $this->labelstart = '<div class="label">'; 287 $this->labelend = "</div>\n"; 288 $this->labelempty = '<div class="label"></div>'; // so that IE6 aligns DIV.input correcctly 289 $this->inputstart = '<div class="input">'; 290 $this->infostart = '<div class="info">'; 291 $this->inputend = "</div>\n"; 292 $this->fieldend = "</fieldset>\n\n"; 293 $this->buttonsstart = '<fieldset><div class="input">'; 294 $this->buttonsend = "</div></fieldset>\n\n"; 295 $this->formend = '</div>'; 296 break; 297 298 case 'linespan': 299 $this->formstart = ''; 300 $this->title_fmt = '<span style="float:right">$global_icons$</span><h2>$title$</h2>'."\n"; 301 $this->no_title_fmt = '<span style="float:right">$global_icons$</span> '."\n"; 302 $this->fieldstart = '<div class="tile" $ID$>'; 303 $this->labelstart = '<strong>'; 304 $this->labelend = "</strong>\n"; 305 $this->labelempty = ''; 306 $this->inputstart = ''; 307 $this->infostart = ''; 308 $this->inputend = "\n"; 309 $this->fieldend = "</div>\n"; 310 $this->buttonsstart = ''; 311 $this->buttonsend = "\n"; 312 $this->formend = ''; 313 break; 314 315 case 'blockspan': 316 $this->formstart = ''; 317 $this->title_fmt = '$title$'."\n"; // TODO: icons 318 $this->no_title_fmt = ''; // " 319 $this->fieldstart = '<span class="block" $ID$>'; 320 $this->labelstart = ''; 321 $this->labelend = "\n"; 322 $this->labelempty = ''; 323 $this->inputstart = ''; 324 $this->infostart = ''; 325 $this->inputend = "\n"; 326 $this->fieldend = '</span>'.get_icon( 'pixel' )."\n"; 327 $this->buttonsstart = ''; 328 $this->buttonsend = "\n"; 329 $this->formend = ''; 330 break; 331 332 default: 333 // "none" (no layout) 334 $this->formstart = ''; 335 $this->title_fmt = '$title$'."\n"; // TODO: icons 336 $this->no_title_fmt = ''; // " 337 $this->fieldstart = ''; // fp> shall we still use $ID$ here ? 338 $this->labelstart = ''; 339 $this->labelend = "\n"; 340 $this->labelempty = ''; 341 $this->inputstart = ''; 342 $this->infostart = ''; 343 $this->inputend = "\n"; 344 $this->fieldend = "\n"; 345 $this->buttonsstart = ''; 346 $this->buttonsend = "\n"; 347 $this->formend = ''; 348 } 349 350 } 351 } 352 353 354 /** 355 * Start an input field. 356 * 357 * A field is a fielset containing a label div and an input div. 358 * 359 * @uses $_common_params 360 * @param string The name of the field 361 * @param string The field label 362 * @param boolean Reset {@link $_common_params}? This should be used if you build a field by yourself. 363 * @return The generated HTML 364 */ 365 function begin_field( $field_name = NULL, $field_label = NULL, $reset_common_params = false ) 366 { 367 if( $reset_common_params ) 368 { 369 $this->_common_params = array(); 370 } 371 // Remember these, to make them available to get_label() 372 if( isset($field_name) ) 373 { 374 $this->_common_params['name'] = $field_name; 375 } 376 if( isset($field_label) ) 377 { 378 $this->_common_params['label'] = $field_label; 379 } 380 381 // Start the new form field and inject an automatic DOM id 382 // This is useful to show/hide the whole field by JS. 383 if( !empty( $this->_common_params['id'] ) ) 384 { 385 $ffield_id = 'id="ffield_'.$this->_common_params['id'].'" '; 386 } 387 else 388 { // No ID in case there's no id/name given for a field. 389 $ffield_id = ''; 390 } 391 $r = str_replace( '$ID$', $ffield_id, $this->fieldstart ); 392 393 if( isset($this->_common_params['field_prefix']) ) 394 { 395 $r .= $this->_common_params['field_prefix']; 396 } 397 398 $r .= $this->get_label(); 399 400 $r .= $this->inputstart; 401 402 return $r; 403 } 404 405 406 /** 407 * End an input field. 408 * 409 * A field is a fielset containing a label div and an input div. 410 * 411 * @param string Field's note to display. (deprecated) 412 * @param string Format of the field's note (%s gets replaced with the note). (deprecated) 413 * @return The generated HTML 414 */ 415 function end_field( $field_note = NULL, $field_note_format = NULL ) 416 { 417 if( isset($field_note) ) // Note: allow "0" as a note 418 { // deprecated - should get set by calling handle_common_params() 419 $this->_common_params['note'] = $field_note; 420 } 421 if( isset($field_note_format) ) 422 { // deprecated - should get set by calling handle_common_params() 423 $this->_common_params['note_format'] = $field_note_format; 424 } 425 426 $r = ''; 427 428 if( !empty($this->_common_params['note']) ) 429 { // We have a note 430 $r .= sprintf( $this->_common_params['note_format'], $this->_common_params['note'] ); 431 } 432 433 if( isset($this->_common_params['field_suffix']) ) 434 { 435 $r .= $this->_common_params['field_suffix']; 436 } 437 438 $r .= $this->inputend.$this->fieldend; 439 440 return $r; 441 } 442 443 444 /** 445 * Builds a fieldset tag. This is a fieldset element by default, but a th element 446 * for table layout. 447 * 448 * @param string the title of the fieldset 449 * @param string the field params to the fieldset 450 * additionally 'legend_params' can be used to give an array of field params 451 * @return true|string true (if output) or the generated HTML if not outputting 452 */ 453 function begin_fieldset( $title = '', $field_params = array() ) 454 { 455 if( !isset($field_params['class']) ) 456 { 457 $field_params['class'] = 'fieldset'; 458 } 459 460 switch( $this->layout ) 461 { 462 case 'table': 463 $r = '<tr'.get_field_attribs_as_string($field_params).'><th colspan="2">'."\n"; 464 // NOTE: empty THs can be rendered and/or are DHTML scriptable 465 466 if( $title != '' ) 467 { // there is a title to display 468 $r .= $title; 469 } 470 471 $r .= "</th></tr>\n"; 472 break; 473 474 default: 475 if( ! empty($field_params['legend_params']) ) 476 { // We have params specifically passed for the title 477 $legend_params = $field_params['legend_params']; 478 unset( $field_params['legend_params'] ); 479 } 480 481 $r = str_replace( '$fieldset_attribs$', get_field_attribs_as_string($field_params), $this->template['fieldset_begin'] ); 482 // $r = '<fieldset'.get_field_attribs_as_string($field_params).'>'."\n"; 483 484 $r = str_replace( '$fieldset_title$', $title, $r ); 485 486 if( empty($legend_params) ) 487 { // there are no legend_params, remove the placeholder 488 $r = str_replace( '$title_attribs$', '', $r ); 489 } 490 else 491 { 492 $r = str_replace( '$title_attribs$', get_field_attribs_as_string($legend_params), $r ); 493 } 494 495 $this->_opentags['fieldset']++; 496 } 497 498 return $this->display_or_return( $r ); 499 } 500 501 502 /** 503 * Ends a fieldset. 504 * 505 * @return true|string true (if output) or the generated HTML if not outputting 506 */ 507 function end_fieldset() 508 { 509 switch( $this->layout ) 510 { 511 case 'table': 512 $r = ''; 513 break; 514 515 default: 516 $r = $this->template['fieldset_end']; 517 $this->_opentags['fieldset']--; 518 } 519 520 return $this->display_or_return( $r ); 521 } 522 523 524 /** 525 * Builds a text (or password) input field. 526 * 527 * Note: please use {@link Form::password_input()} for password fields. 528 * 529 * @param string The name of the input field. This gets used for id also, if no id given in $field_params. 530 * @param string Initial value 531 * @param integer Size of the input field 532 * @param string Label displayed with the field 533 * @param string "help" note (Should provide something useful, otherwise leave it empty) 534 * @param array Extended attributes/params. 535 * - 'maxlength': if not set, $field_size gets used (use '' to disable it) 536 * - 'class': the CSS class to use for the <input> element 537 * - 'type': 'text', 'password' (defaults to 'text') 538 * - 'force_to': 'UpperCase' (JS onchange handler) 539 * - NOTE: any other attributes will be used as is (onchange, onkeyup, id, ..). 540 * @return true|string true (if output) or the generated HTML if not outputting 541 */ 542 function text_input( $field_name, $field_value, $field_size, $field_label, $field_note = '', $field_params = array() ) 543 { 544 $field_params['value'] = $field_value; 545 546 if( !empty($field_note) ) 547 { 548 $field_params['note'] = $field_note; 549 } 550 551 if( !empty($field_size) ) 552 { 553 if( !isset($field_params['maxlength']) ) 554 { // maxlength defaults to size 555 $field_params['maxlength'] = $field_size; 556 } 557 558 $field_params['size'] = $field_size; 559 } 560 561 if( !isset($field_params['type']) ) 562 { // type defaults to "text" 563 $field_params['type'] = 'text'; 564 } 565 566 if( isset($field_params['force_to']) ) 567 { 568 if( $field_params['force_to'] == 'UpperCase' ) 569 { // Force input to uppercase (at front of onchange event) 570 $field_params['onchange'] = 'this.value = this.value.toUpperCase();' 571 .( empty($field_params['onchange']) ? '' : ' '.$field_params['onchange'] ); 572 } 573 unset($field_params['force_to']); // not a html attrib 574 } 575 576 // Give it a class, so it can be selected for CSS in IE6 577 if( empty($field_params['class']) ) $field_params['class'] = 'form_text_input'; 578 else $field_params['class'] .= ' form_text_input'; 579 580 $field_params['name'] = $field_name; 581 $field_params['label'] = $field_label; 582 return $this->input_field( $field_params ); 583 } 584 585 586 /** 587 * Builds a text (or password) input field. 588 * 589 * Note: please use {@link Form::password()} for password fields 590 * 591 * @param string the name of the input field 592 * @param string initial value 593 * @param integer size of the input field 594 * @param string label displayed in front of the field 595 * @param string note displayed with field 596 * @param integer max length of the value (if 0 field_size will be used!) 597 * @param string the CSS class to use 598 * @param string input type (only 'text' or 'password' makes sense) 599 * @return mixed true (if output) or the generated HTML if not outputting 600 */ 601 function text( $field_name, $field_value, $field_size, $field_label, $field_note = '', 602 $field_maxlength = 0, $field_class = '', $inputtype = 'text', $force_to = '' ) 603 { 604 $field_params = array(); 605 606 if( $field_maxlength !== 0 ) 607 { 608 $field_params['maxlength'] = $field_maxlength; 609 } 610 if( $field_class !== '' ) 611 { 612 $field_params['class'] = $field_class; 613 } 614 if( $inputtype !== 'text' ) 615 { 616 $field_params['type'] = $inputtype; 617 } 618 if( $force_to !== '' ) 619 { 620 $field_params['force_to'] = $force_to; 621 } 622 623 return $this->text_input( $field_name, $field_value, $field_size, $field_label, $field_note, $field_params ); 624 } 625 626 627 /** 628 * Builds a password input field. 629 * 630 * Calls the text_input() method with type == 'password'. 631 * 632 * @param string The name of the input field. This gets used for id also, if no id given in $field_params. 633 * @param string Initial value 634 * @param integer Size of the input field 635 * @param string Label displayed in front of the field 636 * @param string Note displayed with field 637 * @param integer Max length of the value (if 0 field_size will be used!) 638 * @param string Extended attributes, see {@link text_input()}. 639 * @return mixed true (if output) or the generated HTML if not outputting 640 */ 641 function password_input( $field_name, $field_value, $field_size, $field_label, $field_params = array() ) 642 { 643 $field_params['type'] = 'password'; 644 645 return $this->text_input( $field_name, $field_value, $field_size, $field_label, '', $field_params ); // TEMP: Note already in params 646 } 647 648 649 /** 650 * Builds a password input field. 651 * 652 * Calls the text() method with a 'password' parameter. 653 * 654 * @param string the name of the input field 655 * @param string initial value 656 * @param integer size of the input field 657 * @param string label displayed in front of the field 658 * @param string note displayed with field 659 * @param integer max length of the value (if 0 field_size will be used!) 660 * @param string the CSS class to use 661 * @return mixed true (if output) or the generated HTML if not outputting 662 */ 663 function password( $field_name, $field_value, $field_size, $field_label, $field_note = '', 664 $field_maxlength = 0 , $field_class = '' ) 665 { 666 $field_params = array( 'type' => 'password' ); 667 668 if( $field_maxlength !== 0 ) 669 { 670 $field_params['maxlength'] = $field_maxlength; 671 } 672 if( !empty($field_class) ) 673 { 674 $field_params['class'] = $field_class; 675 } 676 677 return $this->text_input( $field_name, $field_value, $field_size, $field_label, $field_note, $field_params ); 678 } 679 680 681 /** 682 * Builds a date input field. 683 * 684 * @param string the name of the input field 685 * @param string initial value (ISO datetime (YYYY-MM-DD HH:MM:SS) 686 * or erroneous if the field is in error state) 687 * @param string label displayed in front of the field 688 * @param array Optional params. Additionally to {@link $_common_params} you can use: 689 * - date_format: Format of the date (string, PHP format, default taken from {@link locale_datefmt()}) 690 * - add_date_format_note: If true, date format note gets prepended to the field's note 691 * @return mixed true (if output) or the generated HTML if not outputting 692 */ 693 function date_input( $field_name, $field_value, $field_label, $field_params = array() ) 694 { 695 global $month, $weekday_letter; 696 697 if( empty($field_params['date_format']) ) 698 { // Use locale date format: 699 $date_format = locale_datefmt(); 700 } 701 else 702 { 703 $date_format = $field_params['date_format']; 704 } 705 // Don't keep that attrib in the list: 706 unset( $field_params['date_format'] ); 707 708 // Convert PHP date format to JS library date format (date.js): 709 // NOTE: when editing/extending this here, you probably also have to adjust param_check_date()! 710 $js_date_format = preg_replace_callback( '~(\\\)?(\w)~', create_function( '$m', ' 711 if( $m[1] == "\\\" ) return "\\\".$m[0]; // leave escaped 712 switch( $m[2] ) 713 { 714 case "d": return "dd"; // day, 01-31 715 case "j": return "d"; // day, 1-31 716 case "l": return "EE"; // weekday (name) 717 case "D": return "E"; // weekday (abbr) 718 case "e": return ""; // weekday letter, not supported 719 720 case "m": return "MM"; // month, 01-12 721 case "n": return "M"; // month, 1-12 722 case "F": return "MMM"; // full month name; "name or abbr" in date.js 723 case "M": return "NNN"; // month name abbr 724 725 case "y": return "yy"; // year, 00-99 726 case "Y": return "yyyy"; // year, XXXX 727 default: 728 return $m[0]; 729 }' ), $date_format ); 730 #pre_dump( $js_date_format ); 731 732 if( param_has_error( $field_name ) ) 733 { // There is an error message for this field: 734 735 // We do not try to format the date, we keep the erroneous date. 736 //echo 'error on '.$field_name.' keep erroneous entry intact '; 737 738 $field_params['value'] = trim(substr( $field_value, 0, 10 )); 739 } 740 else 741 { // Make the date value clean for display: 742 743 // The date value may be compact, in this case we have to decompact it 744 if( preg_match( '/^[0-9]+$/', $field_value ) ) 745 { // The date is compact, so we decompact it 746 $field_value = decompact_date( $field_value ); 747 } 748 749 // Get DATE part of datetime and format it to locale format: 750 $field_params['value'] = mysql2date( $date_format, $field_value ); 751 } 752 753 754 if( !empty($field_params['add_date_format_note']) ) 755 { // Prepend $date_format to note 756 $field_params['note'] = empty($field_params['note']) 757 ? '('.$date_format.')' 758 : '('.$date_format.') '.$field_params['note']; 759 } 760 unset( $field_params['add_date_format_note'] ); 761 762 763 if( !isset($field_params['size']) ) 764 { // Get size out of $date_format if not explicitly set 765 $field_params['size'] = strlen( $js_date_format ); 766 } 767 768 /* 769 dh> do not use maxlength by default. Makes no sense IMHO and fails with dateformats like "j \d\e F, Y" 770 if( !isset($field_params['maxlength']) ) 771 { 772 $field_params['maxlength'] = $field_params['size']; 773 } 774 */ 775 776 // Give it a class, so it can be selected for CSS in IE6 777 if( empty($field_params['class']) ) $field_params['class'] = 'form_date_input'; 778 else $field_params['class'] .= ' form_date_input'; 779 780 781 $this->handle_common_params( $field_params, $field_name, $field_label ); 782 783 $r = $this->begin_field() 784 .'<script type="text/javascript"> 785 //<![CDATA[ 786 var cal_'.$field_name.' = new CalendarPopup(); 787 cal_'.$field_name.'.showYearNavigation(); 788 cal_'.$field_name.'.showNavigationDropdowns(); 789 // cal_'.$field_name.'.showYearNavigationInput(); 790 // MonthNames get set through MONTH_NAMES 791 cal_'.$field_name.'.setDayHeaders( ' 792 ."'".T_($weekday_letter[0])."'," 793 ."'".T_($weekday_letter[1])."'," 794 ."'".T_($weekday_letter[2])."'," 795 ."'".T_($weekday_letter[3])."'," 796 ."'".T_($weekday_letter[4])."'," 797 ."'".T_($weekday_letter[5])."'," 798 ."'".T_($weekday_letter[6])."' );\n" 799 .' cal_'.$field_name.'.setWeekStartDay('.locale_startofweek().'); 800 cal_'.$field_name.".setTodayText('".TS_('Today')."'); 801 //]]> 802 </script>\n" 803 .$this->get_input_element($field_params, false) 804 .'<a href="#" onclick="cal_'.$field_name.".select(document.getElementById('".$field_name."'), 'anchor_".$field_name."', '".$js_date_format."');" 805 .' return false;" name="anchor_'.$field_name.'" id="anchor_'.$this->get_valid_id($field_name).'" title="'.T_('Select date').'">' 806 .get_icon( 'calendar', 'imgtag', array( 'title'=>T_('Select date') ) ).'</a>'; 807 808 $r .= $this->end_field(); 809 810 return $this->display_or_return( $r ); 811 } 812 813 814 /** 815 * Builds a date input field. 816 * 817 * @param string the name of the input field 818 * @param string initial value (ISO datetime) 819 * @param string label displayed in front of the field 820 * @param string date format (php format) 821 * @return mixed true (if output) or the generated HTML if not outputting 822 */ 823 function date( $field_name, $field_value, $field_label, $date_format = NULL ) 824 { 825 $field_params = array( 'date_format' => $date_format, 'type' => 'text' ); 826 827 return $this->date_input( $field_name, $field_value, $field_label, $field_params ); 828 } 829 830 831 /** 832 * Builds a time input field. 833 * 834 * @param string The name of the input field 835 * @param string Initial value (ISO datetime) 836 * @param string Label displayed in front of the field 837 * @param array Optional params. Additionally to {@link $_common_params} you can use: 838 * - 'time_format': Format of the time (string, default 'hh:mm:ss') 839 * @return mixed true (if output) or the generated HTML if not outputting 840 */ 841 function time_input( $field_name, $field_value, $field_label, $field_params = array() ) 842 { 843 if( isset($field_params['time_format']) ) 844 { 845 $field_format = '('.$field_params['time_format'].')'; 846 unset( $field_params['time_format'] ); // not an attribute 847 } 848 else 849 { 850 $field_format = '(hh:mm:ss)'; 851 } 852 853 // Prepend format to note 854 if( isset($field_params['note']) ) 855 { 856 $field_params['note'] = $field_format.' '.$field_params['note']; 857 } 858 else 859 { 860 $field_params['note'] = $field_format; 861 } 862 863 $field_size = strlen($field_format); 864 865 // Get time part of datetime: 866 $field_value = substr( $field_value, 11, 8 ); 867 868 return $this->text_input( $field_name, $field_value, $field_size, $field_label, '', $field_params ); // TEMP: Note already in params 869 } 870 871 872 /** 873 * Builds a time input field. 874 * 875 * @param string the name of the input field 876 * @param string initial value (ISO datetime) 877 * @param string label displayed in front of the field 878 * @return mixed true (if output) or the generated HTML if not outputting 879 */ 880 function time( $field_name, $field_value, $field_label, $field_format = 'hh:mm:ss' ) 881 { 882 $field_params = array( 'time_format' => $field_format ); 883 884 return $this->time_input( $field_name, $field_value, $field_label, $field_params ); 885 } 886 887 888 /** 889 * Builds a time select input field 890 * 891 * @param string field name 892 * @param string initial value (ISO datetime or time only) 893 * @param string precison xmn or xsec (x:integer) for the options minutes or secondes 894 * @param string field label to be display before the field 895 * @param string note to be displayed after the field 896 * @param string CSS class for select 897 * @param string Javascript to add for onchange event (trailing ";"). 898 */ 899 function time_select( $field_name, $field_value = NULL, $precision = '5mn', $field_label, $field_note = NULL, $field_class = NULL, $field_onchange = NULL ) 900 { 901 preg_match( '#([0-9]+)(mn|s)#', $precision, $matches ); 902 903 if( !isset( $matches[1] ) && !isset( $matches[2] ) ) 904 { // precison has a bad format 905 return; 906 } 907 908 $field_params = array( 909 'note' => $field_note, 910 'class' => $field_class, 911 'onchange' => $field_onchange ); 912 913 /*** instantiate the precison for the minutes and secondes select options ****/ 914 915 if( $matches[2] == 'mn' ) 916 { 917 $precision_mn = $matches[1]; 918 $precision_s = 0; 919 // convert the precision in sec 920 $precision *= 60; 921 } 922 else 923 { 924 $precision_mn = 1; 925 $precision_s = $matches[1]; 926 } 927 928 // Check if field value is only a time 929 if( strlen( $field_value ) <= 8 ) 930 { // Add date part: 931 $field_value = '2000-01-01 '.$field_value; 932 } 933 934 /*** set round time with the precision ***/ 935 // Get nb sec since unix... 936 $nbsec = mysql2timestamp( $field_value ); 937 $modulo = $nbsec % $precision; 938 939 if( $modulo < ( $precision / 2 ) ) 940 { // The round time is before 941 $nbsec -= $modulo; 942 } 943 else 944 { // The round time is after 945 $nbsec += $precision - $modulo; 946 } 947 948 /******************************************************/ 949 950 $this->handle_common_params( $field_params, $field_name, $field_label ); 951 952 $r = $this->begin_field(); 953 954 /********** select options for the hours *************/ 955 956 $field_params['name'] = $field_name . '_h'; 957 $field_params['id'] = $field_params['name']; 958 // Get Hour part of datetime: 959 $hour = date( 'H', $nbsec ); 960 961 $r .= $this->_number_select( $hour, 23 , 1, $field_params); 962 963 /********* select options for the minutes *************/ 964 965 $field_params['name'] = $field_name . '_mn'; 966 $field_params['id'] = $field_params['name']; 967 // Get Minute part of datetime: 968 $minute = date('i',$nbsec); 969 970 $r .= ':'.$this->_number_select( $minute, 59, $precision_mn, $field_params); 971 972 if( $precision_s ) 973 {/********* select options for the minutes ***********/ 974 975 $field_params['name'] = $field_name . '_s'; 976 $field_params['id'] = $field_params['name']; 977 // Get Secondes part of datetime: 978 $seconde = substr( $field_value, 17, 2 ); 979 980 $r .=':'.$this->_number_select( $seconde, 59, $precision_s, $field_params); 981 } 982 983 $r .= $this->end_field(); 984 985 return $this->display_or_return( $r ); 986 } 987 988 989 /** 990 * Buil a select input field number 991 * @access private 992 * 993 * @param string field value of selected 994 * @param integer maximum value for the input select 995 * @param integer increment for the loop (precision) 996 * @param array params 997 */ 998 function _number_select( $field_value, $max, $precision = 1, $field_params ) 999 { 1000 $r = '<select'.get_field_attribs_as_string( $field_params ).'>'; 1001 1002 for( $i=0; $i <= $max ; $i += $precision) 1003 { 1004 $val = sprintf( '%02d', $i ); 1005 $r .= '<option value="'.$val.'"'. 1006 ($field_value == $val ? ' selected="selected"' : '') . 1007 '>' .$val.'</option>'; 1008 } 1009 1010 $r .= '</select>'; 1011 1012 return $r; 1013 } 1014 1015 1016 /** 1017 * Builds a duration input field. 1018 * 1019 * @todo @Francois: please check API and change as appropriate. 1020 * 1021 * @param string the name of the input field 1022 * @param string initial value (seconds) 1023 * @param string label displayed in front of the field 1024 * @param array Optional params. Additionally to {@link $_common_params} you can use: 1025 * - minutes_step ( default = 15 ); 1026 * @return mixed true (if output) or the generated HTML if not outputting 1027 */ 1028 function duration_input( $field_prefix, $duration, $field_label, $field_params = array() ) 1029 { 1030 $this->handle_common_params( $field_params, $field_prefix, $field_label ); 1031 1032 $r = $this->begin_field(); 1033 1034 $days = floor( $duration / 86400 ); // 24 hours 1035 $r .= "\n".'<select name="'.$field_prefix.'_days" id="'.$this->get_valid_id($field_prefix).'_days">'; 1036 $r .= '<option value="0"'.( 0 == $days ? ' selected="selected"' : '' ).">---</option>\n"; 1037 for( $i = 1; $i <= 30; $i++ ) 1038 { 1039 $r .= '<option value="'.$i.'"'.( $i == $days ? ' selected="selected"' : '' ).'>'.$i."</option>\n"; 1040 } 1041 $r .= '</select>'.T_('days')."\n"; 1042 1043 $hours = floor( $duration / 3600 ) % 24; 1044 $r .= "\n".'<select name="'.$field_prefix.'_hours" id="'.$this->get_valid_id($field_prefix).'_hours">'; 1045 $r .= '<option value="0"'.( 0 == $hours ? ' selected="selected"' : '' ).">---</option>\n"; 1046 for( $i = 1; $i <= 23; $i++ ) 1047 { 1048 $r .= '<option value="'.$i.'"'.( $i == $hours ? ' selected="selected"' : '' ).'>'.$i."</option>\n"; 1049 } 1050 $r .= '</select>'.T_('hours')."\n"; 1051 1052 $minutes = floor( $duration / 60 ) % 60; 1053 $minutes_step = ( empty($field_params['minutes_step']) ? 15 : $field_params['minutes_step'] ); 1054 $r .= "\n".'<select name="'.$field_prefix.'_minutes" id="'.$this->get_valid_id($field_prefix).'_minutes">'; 1055 for( $i = 0; $i <= 59 ; $i += $minutes_step ) 1056 { 1057 $r .= '<option value="'.$i.'"'.( ($minutes>=$i && $minutes<($i+$minutes_step)) ? ' selected="selected"' : '' ).'>' 1058 .($i == 0 ? '---' : substr('0'.$i,-2))."</option>\n"; 1059 } 1060 $r .= '</select>'.T_('minutes')."\n"; 1061 1062 $r .= $this->end_field(); 1063 1064 return $this->display_or_return( $r ); 1065 } 1066 1067 1068 /** 1069 * Builds a duration input field. 1070 * 1071 * @param string the name of the input field 1072 * @param string initial value (seconds) 1073 * @param string label displayed in front of the field 1074 * @return mixed true (if output) or the generated HTML if not outputting 1075 */ 1076 function duration( $field_prefix, $duration, $field_label ) 1077 { 1078 return $this->duration_input( $field_prefix, $duration, $field_label ); 1079 } 1080 1081 1082 /** 1083 * Build a select to choose a weekday. 1084 * 1085 * @uses select_input_options() 1086 * 1087 * @return true|string 1088 */ 1089 function dayOfWeek_input( $field_name, $field_value, $field_label, $field_params = array() ) 1090 { 1091 global $weekday_abbrev; 1092 1093 $field_options = ''; 1094 1095 foreach( $weekday_abbrev as $lNumber => $lWeekday ) 1096 { 1097 $field_options .= '<option'; 1098 1099 if( $field_value == $lNumber ) 1100 { 1101 $field_options .= ' selected="selected"'; 1102 } 1103 $field_options .= ' value="'.$lNumber.'">'.T_($lWeekday).'</option>'; 1104 } 1105 1106 return $this->select_input_options( $field_name, $field_options, $field_label, '', $field_params ); 1107 } 1108 1109 1110 /** 1111 * Build a select to choose a weekday. 1112 * 1113 * @return true|string 1114 */ 1115 function dayOfWeek( $field_name, $field_value, $field_label, $field_note = NULL, $field_class = NULL ) 1116 { 1117 $field_params = array(); 1118 if( isset($field_note) ) 1119 { 1120 $field_params['note'] = $field_note; 1121 } 1122 1123 if( isset($field_class) ) 1124 { 1125 $field_params['class'] = $field_class; 1126 } 1127 1128 return $this->dayOfWeek_input( $field_name, $field_value, $field_label, $field_params ); 1129 } 1130 1131 1132 /** 1133 * Builds a checkbox field 1134 * 1135 * @param string the name of the checkbox 1136 * @param boolean indicating if the checkbox must be checked by default 1137 * @param string label 1138 * @param array Optional params. Additionally to {@link $_common_params} you can use: 1139 * 'value': the value attribute of the checkbox (default 1) 1140 * @return mixed true (if output) or the generated HTML if not outputting 1141 */ 1142 function checkbox_input( $field_name, $field_checked, $field_label, $field_params = array() ) 1143 { 1144 $field_params['name'] = $field_name; 1145 $field_params['label'] = $field_label; 1146 $field_params['type'] = 'checkbox'; 1147 1148 if( !isset($field_params['value']) ) 1149 { 1150 $field_params['value'] = 1; 1151 } 1152 1153 if( $field_checked ) 1154 { 1155 $field_params['checked'] = 'checked'; 1156 } 1157 1158 if( !isset($field_params['class']) ) 1159 { 1160 $field_params['class'] = 'checkbox'; 1161 } 1162 1163 return $this->input_field( $field_params ); 1164 } 1165 1166 1167 /* 1168 * EXPERIMENTAL: simpler method of obtaining basic checkboxes 1169 */ 1170 function checkbox_basic_input( $field_name, $field_checked, $field_label, $field_params = array() ) 1171 { 1172 $field_params['name'] = $field_name; 1173 $field_params['type'] = 'checkbox'; 1174 1175 if( !isset($field_params['value']) ) 1176 { 1177 $field_params['value'] = 1; 1178 } 1179 1180 if( $field_checked ) 1181 { 1182 $field_params['checked'] = 'checked'; 1183 } 1184 1185 if( !isset($field_params['class']) ) 1186 { 1187 $field_params['class'] = 'checkbox'; 1188 } 1189 1190 echo '<label>'; 1191 echo $this->get_input_element($field_params); 1192 echo $field_label; 1193 echo '</label>'; 1194 } 1195 1196 1197 /** 1198 * Builds a checkbox field 1199 * 1200 * @param string the name of the checkbox 1201 * @param boolean indicating if the checkbox must be checked 1202 * @param string label 1203 * @param string note 1204 * @param string CSS class 1205 * @param string value to use 1206 * @param boolean an optional indicating whether the box is disabled or not 1207 * @return mixed true (if output) or the generated HTML if not outputting 1208 */ 1209 function checkbox( $field_name, $field_checked, $field_label, $field_note = '', 1210 $field_class = '', $field_value = 1, $field_disabled = false ) 1211 { 1212 $field_params = array(); 1213 1214 if( $field_note !== '' ) 1215 { 1216 $field_params['note'] = $field_note; 1217 } 1218 if( $field_class !== '' ) 1219 { 1220 $field_params['class'] = $field_class; 1221 } 1222 if( $field_value !== 1 ) 1223 { 1224 $field_params['value'] = $field_value; 1225 } 1226 if( $field_disabled != false ) 1227 { 1228 $field_params['disabled'] = 'disabled'; 1229 } 1230 1231 return $this->checkbox_input( $field_name, $field_checked, $field_label, $field_params ); 1232 } 1233 1234 1235 /** 1236 * Return links to check and uncheck all check boxes of the form 1237 */ 1238 function check_all() 1239 { 1240 // Need to add event click on links at the form end. 1241 $this->check_all = true; 1242 1243 // fp> This is "name=" and I mean it!!! The JS is looking for all elements with this name! 1244 return '<a name="check_all_nocheckchanges" href="'.regenerate_url().'">' 1245 //.T_('Check all').' ' 1246 .get_icon( 'check_all', 'imgtag', NULL, true ) 1247 .'</a> | <a name="uncheck_all_nocheckchanges" href="'.regenerate_url().'">' 1248 //.T_('Uncheck all').' ' 1249 .get_icon( 'uncheck_all', 'imgtag', NULL, true ).'</a> '.' '; 1250 } 1251 1252 1253 /** 1254 * Builds the form field 1255 * 1256 * @param string the class to use for the form tag 1257 * @param string title to display on top of the form 1258 * @param array Additional params to the form element. See {@link $_common_params}. 1259 * These may override class members. 1260 * @return mixed true (if output) or the generated HTML if not outputting 1261 */ 1262 function begin_form( $form_class = NULL, $form_title = '', $form_params = array() ) 1263 { 1264 $this->handle_common_params( $form_params, NULL /* "name" attribute is deprecated in xhtml */ ); 1265 1266 if( ! empty($this->form_name) ) 1267 { 1268 $form_params['id'] = $this->form_name; 1269 } 1270 1271 // Set non-mandatory attributes if given in $form_params 1272 if( !isset($form_params['enctype']) && !empty( $this->enctype ) ) 1273 { 1274 $form_params['enctype'] = $this->enctype; 1275 } 1276 1277 if( !isset($form_params['class']) && !empty( $form_class ) ) 1278 { 1279 $form_params['class'] = $form_class; 1280 } 1281 1282 if( !isset($form_params['method']) ) 1283 { 1284 $form_params['method'] = $this->form_method; 1285 } 1286 1287 if( !isset($form_params['action']) ) 1288 { 1289 $form_params['action'] = $this->form_action; 1290 } 1291 1292 if( !empty($form_params['bozo_start_modified']) ) 1293 { 1294 $bozo_start_modified = true; 1295 unset( $form_params['bozo_start_modified'] ); 1296 } 1297 1298 $r = "\n\n<form".get_field_attribs_as_string($form_params).">\n"; 1299 1300 // $r .= '<div>'; // for XHTML (dh> removed 'style="display:inline"' because it's buggy with FireFox 1.0.x, at least at the "Write" admin page; see http://forums.b2evolution.net/viewtopic.php?t=10130) 1301 // fp> inline was needed for inline forms like the DELETE confirmation. 1302 // fp> why does XHTML require all forms to have an embedded DIV? 1303 1304 $r .= $this->formstart; 1305 1306 if( empty($form_title) ) 1307 { 1308 $r .= $this->replace_vars( $this->no_title_fmt ); 1309 } 1310 else 1311 { 1312 $this->title = $form_title; 1313 1314 $r .= $this->replace_vars( $this->title_fmt ); 1315 } 1316 1317 // Initialization of javascript vars used to create parent_child select lists 1318 // TODO: does this make sense to add it to every form?? 1319 $r .= '<script type="text/javascript"> 1320 var nb_dynamicSelects = 0; 1321 var tab_dynamicSelects = Array(); 1322 </script>'; 1323 1324 global $UserSettings; 1325 if( isset($UserSettings) && $UserSettings->get( 'control_form_abortions' ) 1326 && preg_match( '#^(.*)_checkchanges#', $this->form_name ) ) 1327 { // This form will trigger the bozo validator, preset a localized bozo confirm message: 1328 1329 $r .= '<script type="text/javascript"> 1330 if( typeof bozo == "object" ) 1331 { // If Bozo validator is active: 1332 bozo.confirm_mess = \''; 1333 if( empty( $this->title ) ) 1334 { // No form title: 1335 $r .= TS_( 'You have modified this form but you haven\'t submitted it yet.\nYou are about to lose your edits.\nAre you sure?' ); 1336 } 1337 else 1338 { // with form title: 1339 $r .= sprintf( TS_( 'You have modified the form \"%s\"\nbut you haven\'t submitted it yet.\nYou are about to lose your edits.\nAre you sure?' ), $this->title ); 1340 } 1341 1342 $r .= '\';'; 1343 1344 if( !empty($bozo_start_modified) ) 1345 { 1346 $r .= ' 1347 // Update number of changes for this form: 1348 bozo.tab_changes["'.$this->form_name.'"] = 1; 1349 // Update Total # of changes: 1350 bozo.nb_changes++; 1351 '; 1352 } 1353 1354 1355 $r .=' } 1356 </script>'; 1357 } 1358 1359 return $this->display_or_return( $r ); 1360 } 1361 1362 1363 /** 1364 * Ends the form, optionally displays buttons and closes all open fieldsets. 1365 * 1366 * @param array Optional array to display the buttons before the end of the form, see {@link buttons_input()} 1367 * @return true|string true (if output) or the generated HTML if not outputting. 1368 */ 1369 function end_form( $buttons = array() ) 1370 { 1371 $r = ''; 1372 if( !empty( $buttons ) ) 1373 { 1374 $save_output = $this->output; 1375 $this->output = 0; 1376 1377 $r .= $this->buttons( $buttons ); // converts old-style to new style, through convert_button_to_field_params() 1378 1379 $this->output = $save_output; 1380 } 1381 1382 while( $this->_opentags['fieldset']-- > 0 ) 1383 { 1384 $r .= "\n</fieldset>\n"; 1385 } 1386 1387 $r .= $this->formend; 1388 1389 1390 // Display all buffered hidden fields in a 0 height DIV (for XHTML): 1391 $r .= '<div style="height:0">'.implode( '', $this->hiddens ).'</div>'; 1392 1393 // $r .= '</div>'; 1394 $r .= "\n</form>\n\n"; 1395 1396 // When the page loads, Initialize all the parent child select lists + other javascripts 1397 $r .= ' 1398 <script type="text/javascript"> 1399 //<![CDATA[ 1400 if( typeof addEvent == "function" && typeof init_dynamicSelect == "function" ) 1401 { 1402 addEvent( window, "load", init_dynamicSelect, false ); 1403 '; 1404 if( $this->check_all ) 1405 { // Init check_all event on check_all links 1406 $r .= 'addEvent( window, "load", init_check_all, false );'; 1407 } 1408 $r .= ' 1409 } 1410 '; 1411 1412 if( $this->append_javascript ) 1413 { // Append Javascript that we have added 1414 $r .= implode( "\n", $this->append_javascript ); 1415 } 1416 $r .= ' 1417 //]]> 1418 </script>'; 1419 1420 // Reset (in case we re-use begin_form! NOTE: DO NOT REUSE begin_form, it's against the spec.) 1421 $this->hiddens = array(); 1422 1423 return $this->display_or_return( $r ); 1424 } 1425 1426 1427 /** 1428 * Builds a checkbox list 1429 * 1430 * the two-dimension array must indicate, for each checkbox: 1431 * - the name, 1432 * - the value, 1433 * - the comment to put between <input> and <br /> 1434 * - a boolean indicating whether the box must be checked or not 1435 * - an optional boolean indicating whether the box is disabled or not 1436 * - an optional note 1437 * - 'required': is the box required to be checked (boolean; default: false) 1438 * 1439 * @todo Transform to $field_params schema. 1440 * @param array a two-dimensional array containing the parameters of the input tag 1441 * @param string name 1442 * @param string label 1443 * @param boolean true to surround checkboxes if they are required 1444 * @param boolean true add a surround_check span, used by check_all mouseover 1445 * @return mixed true (if output) or the generated HTML if not outputting 1446 */ 1447 function checklist( $options, $field_name, $field_label, $required = false, $add_highlight_spans = false ) 1448 { 1449 $field_params = array(); 1450 $field_params['type'] = 'checkbox'; 1451 $this->handle_common_params( $field_params, $field_name, $field_label ); 1452 1453 $r = $this->begin_field( $field_name, $field_label ); 1454 1455 foreach( $options as $option ) 1456 { //loop to construct the list of 'input' tags 1457 1458 $loop_field_name = $option[0]; 1459 1460 $loop_field_note = isset($option[5]) ? $option[5] : ''; 1461 1462 $r .= '<label class="">'; 1463 1464 if( $add_highlight_spans ) 1465 { // Need it to highlight checkbox for check_all and uncheck_all mouseover 1466 $r .= '<span name="surround_check" class="checkbox_surround_init">'; 1467 $after_field_highlight = '</span>'; 1468 } 1469 else 1470 { 1471 $after_field_highlight = ''; 1472 } 1473 1474 $after_field = ''; 1475 if( param_has_error( $field_name ) ) 1476 { // There is an error message for this field, we want to mark the checkboxes with a red border: 1477 $r .= '<span class="checkbox_error">'; 1478 $after_field .= '</span>'; 1479 } 1480 if( $required ) 1481 { //this field is required 1482 $r .= '<span class="checkbox_required">'; 1483 $after_field .= '</span>'; 1484 } 1485 1486 $r .= "\t".'<input type="checkbox" name="'.$loop_field_name.'" value="'.$option[1].'" '; 1487 if( $option[3] ) 1488 { //the checkbox has to be checked by default 1489 $r .= ' checked="checked" '; 1490 } 1491 if( isset( $option[4] ) && $option[4] ) 1492 { // the checkbox has to be disabled 1493 $r .= ' disabled="disabled" '; 1494 } 1495 $r .= ' class="checkbox" />'; 1496 1497 $r .= $after_field; 1498 1499 $r .= $after_field_highlight; 1500 1501 $r .= ' '.$option[2]; 1502 1503 $r .='</label>'; 1504 1505 if( !empty($loop_field_note) ) 1506 { // We want to display a note: 1507 $r .= ' <span class="notes">'.$loop_field_note.'</span>'; 1508 } 1509 $r .= "<br />\n"; 1510 } 1511 1512 $r .= $this->end_field(); 1513 1514 return $this->display_or_return( $r ); 1515 } 1516 1517 1518 /** 1519 * Display a select field and populate it with a callback function. 1520 * 1521 * @param string field name 1522 * @param string default field value 1523 * @param callback callback function 1524 * @param string field label to be display before the field 1525 * @param array Optional params. Additionally to {@link $_common_params} you can use: 1526 * Nothing yet. 1527 * @return mixed true (if output) or the generated HTML if not outputting 1528 */ 1529 function select_input( $field_name, $field_value, $field_list_callback, $field_label, $field_params = array() ) 1530 { 1531 $field_options = call_user_func( $field_list_callback, $field_value ); 1532 1533 return $this->select_input_options( $field_name, $field_options, $field_label, '', $field_params ); 1534 } 1535 1536 1537 /** 1538 * Display a select field and populate it with a callback function. 1539 * 1540 * @param string field name 1541 * @param string default field value 1542 * @param callback callback function 1543 * @param string field label to be display before the field 1544 * @param string note to be displayed after the field 1545 * @param string CSS class for select 1546 * @param string Javascript to add for onchange event (trailing ";"). 1547 * @return mixed true (if output) or the generated HTML if not outputting 1548 */ 1549 function select( 1550 $field_name, 1551 $field_value, 1552 $field_list_callback, 1553 $field_label, 1554 $field_note = '', 1555 $field_class = '', 1556 $field_onchange = NULL ) 1557 { 1558 $field_params = array(); 1559 if( $field_note !== '' ) 1560 { 1561 $field_params['note'] = $field_note; 1562 } 1563 if( $field_class !== '' ) 1564 { 1565 $field_params['class'] = $field_class; 1566 } 1567 if( isset($field_onchange) ) 1568 { 1569 $field_params['onchange'] = $field_onchange; 1570 } 1571 1572 return $this->select_input( $field_name, $field_value, $field_list_callback, $field_label, $field_params ); 1573 } 1574 1575 1576 /** 1577 * Display a select field and populate it with a cache object by using a callback 1578 * method. 1579 * 1580 * @uses select_input_options() 1581 * @param string Field name 1582 * @param string Default field value 1583 * @param DataObjectCache Cache containing values for list 1584 * @param string Field label to be display with the field 1585 * @param array Optional params. Additionally to {@link $_common_params} you can use: 1586 * - 'allow_none': allow to select [none] in list (boolean, default false) 1587 * - 'object_callback': Object's callback method name (string, default 'get_option_list') 1588 * - 'loop_object_method': The method on the objects inside the callback (string, default NULL) 1589 * @return mixed true (if output) or the generated HTML if not outputting 1590 */ 1591 function select_input_object( $field_name, $field_value, & $field_object, $field_label, $field_params = array() ) 1592 { 1593 if( isset($field_params['allow_none']) ) 1594 { 1595 $allow_none = $field_params['allow_none']; 1596 unset( $field_params['allow_none'] ); 1597 } 1598 else 1599 { 1600 $allow_none = false; 1601 } 1602 1603 if( isset($field_params['object_callback']) ) 1604 { 1605 $field_object_callback = $field_params['object_callback']; 1606 unset( $field_params['object_callback'] ); 1607 } 1608 else 1609 { 1610 $field_object_callback = 'get_option_list'; 1611 } 1612 1613 if( isset($field_params['loop_object_method']) ) 1614 { 1615 $field_options = $field_object->$field_object_callback( $field_value, $allow_none, $field_params['loop_object_method'] ); 1616 } 1617 else 1618 { 1619 $field_options = $field_object->$field_object_callback( $field_value, $allow_none ); 1620 } 1621 1622 if( isset($field_params['note']) ) 1623 { 1624 $field_note = $field_params['note']; 1625 unset( $field_params['note'] ); 1626 } 1627 else 1628 { 1629 $field_note = ''; 1630 } 1631 1632 return $this->select_input_options( $field_name, $field_options, $field_label, $field_note, $field_params ); 1633 } 1634 1635 1636 /** 1637 * Display a select field and populate it with a cache object. 1638 * 1639 * @uses select_input_object() 1640 * @param string field name 1641 * @param string default field value 1642 * @param DataObjectCache Cache containing values for list 1643 * @param string field label to be display before the field 1644 * @param string note to be displayed after the field 1645 * @param boolean allow to select [none] in list 1646 * @param string CSS class for select 1647 * @param string Object's callback method name. 1648 * @param string Javascript to add for onchange event (trailing ";"). 1649 * @return mixed true (if output) or the generated HTML if not outputting 1650 */ 1651 function select_object( 1652 $field_name, 1653 $field_value, 1654 & $field_object, 1655 $field_label, 1656 $field_note = '', 1657 $allow_none = false, 1658 $field_class = '', 1659 $field_object_callback = 'get_option_list', 1660 $field_onchange = NULL ) 1661 { 1662 $field_params = array( 1663 'note' => $field_note, 1664 'allow_none' => $allow_none, 1665 'class' => $field_class, 1666 'object_callback' => $field_object_callback, 1667 'onchange' => $field_onchange ); 1668 1669 return $this->select_input_object( $field_name, $field_value, $field_object, $field_label, $field_params ); 1670 } 1671 1672 1673 /** 1674 * Display a select field and populate it with a cache object. 1675 * 1676 * @param string field name 1677 * @param string string containing options '<option>...</option>' 1678 * @param string field label to be display before the field 1679 * @param string "help" note (Should provide something useful, otherwise leave it empty) 1680 * @param array Optional params. Additionally to {@link $_common_params} you can use: 1681 * - 'label': Field label to be display before the field 1682 * - 'class': CSS class for select 1683 * @return mixed true (if output) or the generated HTML if not outputting 1684 */ 1685 function select_input_options( $field_name, $field_options, $field_label, $field_note = '', $field_params = array() ) 1686 { 1687 $this->handle_common_params( $field_params, $field_name, $field_label ); 1688 1689 $r = $this->begin_field(); 1690 if( !empty( $field_params['parent'] ) ) 1691 {// need to display an arrow to show that this select list options has a preselection from a parent 1692 $r .= get_icon( 'parent_childto_arrow' ); 1693 } 1694 1695 $r .="\n<select".get_field_attribs_as_string($field_params).'>' 1696 .$field_options 1697 ."</select>\n"; 1698 1699 $r .= $this->end_field( $field_note ); 1700 1701 if( !empty( $field_params['parent'] ) ) 1702 { // Set up the dynamic preselection array from the parent to this select list options 1703 $r .= "<script type='text/javascript'> 1704 tab_dynamicSelects[nb_dynamicSelects] = Array(); 1705 tab_dynamicSelects[nb_dynamicSelects]['parent'] = '".$field_params['parent']."'; 1706 tab_dynamicSelects[nb_dynamicSelects]['child'] = '$field_name'; 1707 nb_dynamicSelects++; 1708 </script>"; 1709 } 1710 1711 return $this->display_or_return( $r ); 1712 } 1713 1714 1715 /** 1716 * Display a select field and populate it with a cache object. 1717 * 1718 * @uses select_input_options() 1719 * @param string field name 1720 * @param string string containing options 1721 * @param string field label to be display before the field 1722 * @param string note to be displayed after the field 1723 * @param string CSS class for select 1724 * @param string Javascript to add for onchange event (trailing ";"). 1725 * @return mixed true (if output) or the generated HTML if not outputting 1726 */ 1727 function select_options( 1728 $field_name, 1729 $field_options, 1730 $field_label, 1731 $field_note = NULL, 1732 $field_class = NULL, 1733 $field_onchange = NULL ) 1734 { 1735 $field_params = array( 1736 'note' => $field_note, 1737 'class' => $field_class, 1738 'onchange' => $field_onchange, 1739 ); 1740 1741 return $this->select_input_options( $field_name, $field_options, $field_label, '', $field_params ); 1742 } 1743 1744 1745 /** 1746 * This is a stub for {@link select_input_options()} which builds the required list 1747 * of <option> elements from a given list of options ($field_options) and 1748 * the selected value ($field_value). 1749 * 1750 * @uses select_input_options() 1751 * @param string field name 1752 * @param mixed Initial value 1753 * @param array Options. If an associative key (string) is used, this gets the value attribute. 1754 * NOTE: numeric strings get converted to integers by PHP! 1755 * @param string Field label to be display before the field 1756 * @param string Note 1757 * @param array Optional params. Additionally to {@link $_common_params} you can use: 1758 * - 'value': The selected value 1759 * - 'force_keys_as_values': Use the key of $field_options for "value" attrib always. 1760 * - Plus all of {@link select_input_options()}. 1761 * @return mixed true (if output) or the generated HTML if not outputting 1762 */ 1763 function select_input_array( $field_name, $field_value, $field_options, $field_label, $field_note = NULL, $field_params = array() ) 1764 { 1765 if( isset($field_params['force_keys_as_values']) ) 1766 { 1767 $force_keys_as_values = $field_params['force_keys_as_values']; 1768 unset($field_params['force_keys_as_values']); // not an attribute to <select> 1769 } 1770 else 1771 { 1772 $force_keys_as_values = false; 1773 } 1774 1775 // Build $options_list 1776 $options_list = ''; 1777 1778 foreach( $field_options as $l_key => $l_option ) 1779 { 1780 // Get the value attribute from key if is_string(): 1781 $l_value = ($force_keys_as_values || is_string($l_key)) ? $l_key : $l_option; 1782 1783 $options_list .= '<option value="'.format_to_output($l_value, 'formvalue').'"'; 1784 1785 if( (string)$l_value == (string)$field_value ) // cast to string so "1,2" is != 1 1786 { 1787 $options_list .= ' selected="selected"'; 1788 } 1789 1790 $options_list .= '>'.format_to_output($l_option).'</option>'; 1791 } 1792 1793 return $this->select_input_options( $field_name, $options_list, $field_label, $field_note, $field_params ); 1794 } 1795 1796 1797 /** 1798 * Combo box 1799 * Display a select options list with an option 'new', 1800 * and when this one is seleted, display a combo input text to add a new value 1801 * 1802 * @param string field name 1803 * @param string field value 1804 * @param string containing options 1805 * @param string field label 1806 * @param array Optional params 1807 * 1808 * @return mixed true (if output) or the generated HTML if not outputting 1809 */ 1810 function combo_box( $field_name, $field_value, $field_options, $field_label, $field_params = array() ) 1811 { 1812 if( param_has_error( $field_name) ) 1813 { // There is an error on the combo, so we need to set the combo input text class to 'field_error' 1814 $input_class = 'field_error'; 1815 } 1816 else 1817 { 1818 if( isset( $field_params['required'] ) && $field_params['required'] ) 1819 { // The field is required, so update its class: 1820 $input_class = ' field_required'; 1821 } 1822 else 1823 { 1824 $input_class = ''; 1825 } 1826 } 1827 unset($field_params['required']); // already handled above, do not pass to handle_common_params() 1828 1829 // Set onchange event on the select, when the select changes, we check the value to display or hide an input text after it 1830 $field_params['onchange']= 'check_combo( this.id, this.options[this.selectedIndex].value, "'.$input_class.'")'; 1831 1832 $this->handle_common_params( $field_params, $field_name, $field_label ); 1833 1834 $r = $this->begin_field(); 1835 1836 // Select option to add after the select list a combo input text: 1837 $option_new = '<option value="new">'.T_('New').': </option>'."\n"; 1838 1839 // Add the new option to the select list: 1840 $field_options = $option_new . $field_options; 1841 1842 // Select list 1843 $r .="\n<select".get_field_attribs_as_string($field_params).'>' 1844 .$field_options 1845 ."</select>\n"; 1846 1847 if( $field_options == $option_new || $input_class == 'field_error' || !$field_value ) 1848 { // The list is empty or there is an error on the combo or no field value, so we have to display the input text: 1849 $visible = 'inline'; 1850 } 1851 else 1852 { // Hide the input text: 1853 $visible = 'none' ; 1854 } 1855 1856 $r .= '<input type="text" id="'.$field_name.'_combo" name="'.$field_name.'_combo" size="30" class="'.$input_class.'" style="display:'.$visible.'">'; 1857 1858 if( $visible == 'none' ) 1859 { // The input text is hidden, so if no javascript activated, we always display input text: 1860 $r .= '<script type="text/javascript"></script>'; // We need <script> tag here to use a <noscript> tag when javascript is deactivated: 1861 $r .= '<noscript> 1862 <input type="text" id="'.$field_name.'_combo" name="'.$field_name.'_combo" size="30" class="'.$input_class.'"> 1863 </noscript>'; 1864 } 1865 1866 $r .= $this->end_field(); 1867 1868 return $this->display_or_return( $r ); 1869 } 1870 1871 1872 /** 1873 * Build a text area. 1874 * 1875 * @param string Name of the field 1876 * @param string Value of the field 1877 * @param integer Number of rows 1878 * @param string Label for the field 1879 * @param array Optional params. Additionally to {@link $_common_params} you can use: 1880 * - 'cols': Number of columns (integer, default 50) 1881 */ 1882 function textarea_input( $field_name, $field_value, $field_rows, $field_label, $field_params = array() ) 1883 { 1884 global $rsc_url; 1885 1886 if( !isset($field_params['cols']) ) 1887 { 1888 $field_params['cols'] = 50; 1889 } 1890 1891 if( !isset($field_params['note_format']) ) 1892 { // Default note_format for <textarea>: 1893 $field_params['note_format'] = '<br/><span class="notes">%s</span>'; 1894 } 1895 1896 $this->handle_common_params( $field_params, $field_name, $field_label ); 1897 1898 // Give it a class, so it can be selected for CSS in IE6 1899 if( empty($field_params['class']) ) $field_params['class'] = 'form_textarea_input'; 1900 else $field_params['class'] .= ' form_textarea_input'; 1901 1902 if( isset($field_params['maxlength']) ) 1903 { // attach event to the textarea to accomplish max length: 1904 $this->append_javascript['textarea_maxlength'.$field_name] = ' 1905 if( typeof jQuery == "function" ) 1906 { 1907 $("#'.$field_params['id'].'").bind( "keyup", function(event) 1908 { 1909 if( this.value.length > '.$field_params['maxlength'].' ) 1910 { 1911 this.value = this.value.substr(0,'.$field_params['maxlength'].'); 1912 event.preventDefault(); 1913 } 1914 } ); 1915 }'; 1916 unset($field_params['maxlength']); // not a HTML attribute for textarea 1917 } 1918 1919 $r = $this->begin_field() 1920 // NOTE: The following pixel is needed to avoid the dity IE textarea expansion bug 1921 // see http://fplanque.net/2003/Articles/iecsstextarea/index.html 1922 .'<img src="'.$rsc_url.'img/blank.gif" width="1" height="1" alt="" />' 1923 .'<textarea' 1924 .get_field_attribs_as_string( $field_params ) 1925 .' rows="'.$field_rows.'">' 1926 .format_to_output( $field_value, 'formvalue' ) 1927 .'</textarea>' 1928 // NOTE: this one is for compensating the previous pixel in case of center aligns. 1929 .'<img src="'.$rsc_url.'img/blank.gif" width="1" height="1" alt="" />' 1930 .$this->end_field(); 1931 1932 return $this->display_or_return( $r ); 1933 } 1934 1935 1936 /** 1937 * Build a text area. 1938 * 1939 * @uses textarea_input() 1940 * 1941 * @param string 1942 * @param string 1943 * @param integer 1944 * @param string 1945 * @param string 1946 * @param integer 1947 * @param string 1948 */ 1949 function textarea( $field_name, $field_value, $field_rows, $field_label, 1950 $field_note = '', $field_cols = 50 , $field_class = '' ) 1951 { 1952 $field_params = array( 1953 'note' => $field_note, 1954 'cols' => $field_cols, 1955 'class' => $field_class ); 1956 1957 return $this->textarea_input( $field_name, $field_value, $field_rows, $field_label, $field_params ); 1958 } 1959 1960 1961 /** 1962 * Builds an info field. 1963 * An info field is a fieldset containing a label div and an info div. 1964 * 1965 * {@internal 1966 * NOTE: we don't use {@link begin_field()} here, because the label is meant 1967 * to be always on the left and this avoids fiddling with the <label> tag. 1968 * }} 1969 * 1970 * @param string the field label 1971 * @param string the field info 1972 * @param array Optional params. Additionally to {@link $_common_params} you can use: 1973 * - 'format_info': Format of info content, see {@link format_to_output()} (string, default 'htmlbody') 1974 * @return mixed true (if output) or the generated HTML if not outputting 1975 */ 1976 function info_field( $field_label, $field_info, $field_params = array() ) 1977 { 1978 if( isset($field_params['format_info']) ) 1979 { 1980 $format_info = $field_params['format_info']; 1981 unset($field_params['format_info']); // not an HTML element 1982 } 1983 else 1984 { 1985 $format_info = 'htmlbody'; 1986 } 1987 1988 if( !isset($field_params['note_format']) ) 1989 { // Default field_note for info: 1990 $field_params['note_format'] = ' <small class="notes">%s</small>'; 1991 } 1992 1993 $this->handle_common_params( $field_params, NULL, $field_label ); 1994 1995 $r = $this->fieldstart; 1996 1997 if( strlen($field_label) ) 1998 { 1999 $r .= $this->labelstart.$field_label; 2000 $r .= $this->label_suffix; 2001 $r .= $this->labelend; 2002 } 2003 else 2004 { // Empty label: 2005 $r .= $this->labelempty; 2006 } 2007 2008 $r .= $this->infostart; 2009 2010 // PAYLOAD: 2011 $r .= format_to_output( $field_info, $format_info ); 2012 2013 2014 // Taken from end_field() - but we use $infoend: 2015 if( !empty($this->_common_params['note']) ) 2016 { // We have a note 2017 $r .= sprintf( $this->_common_params['note_format'], $this->_common_params['note'] ); 2018 } 2019 2020 if( isset($this->_common_params['field_suffix']) ) 2021 { 2022 $r .= $this->_common_params['field_suffix']; 2023 } 2024 2025 $r .= ( isset($this->infoend) ? $this->infoend : $this->inputend ).$this->fieldend; 2026 2027 return $this->display_or_return( $r ); 2028 } 2029 2030 2031 /** 2032 * Builds an info field. 2033 * An info field is a fieldset containing a label div and an info div. 2034 * 2035 * @param string the field label 2036 * @param string the field info 2037 * @param string see {@link format_to_output()} 2038 * @return mixed true (if output) or the generated HTML if not outputting 2039 */ 2040 function info( $field_label, $field_info, $field_note = NULL, $format = 'htmlbody' ) 2041 { 2042 $field_params = array( 2043 'note' => $field_note, 2044 'format_info' => $format ); 2045 2046 return $this->info_field( $field_label, $field_info, $field_params ); 2047 } 2048 2049 2050 /** 2051 * Builds a button list. 2052 * 2053 * The array contains an associative array for each button (params to {@link button_input()}. 2054 * 2055 * @param array a two-dimension array containing the elements of the input tags 2056 * @return mixed true (if output) or the generated HTML if not outputting 2057 */ 2058 function buttons_input( $buttons = array() ) 2059 { 2060 $r = ''; 2061 $hidden = true; // boolean that tests if the buttons are all hidden 2062 2063 $save_output = $this->output; 2064 $this->output = false; 2065 2066 foreach( $buttons as $l_button ) 2067 { 2068 if( !isset($l_button['type']) || $l_button['type'] != 'hidden' ) 2069 { // not a hidden button 2070 $hidden = false; 2071 } 2072 2073 $r .= $this->button_input( $l_button ); 2074 } 2075 /* 2076 else 2077 { // Default: Save and Reset 2078 $r .= $this->get_input_element( array( 2079 'type' => 'submit', 2080 'value' => T_('Save !'), 2081 'class' => 'SaveButton', 2082 'input_prefix => "\t\t\t" ); 2083 $r .= $this->get_input_element( array( 2084 'type' => 'reset', 2085 'value' => T_('Reset'), 2086 'class' => 'ResetButton', 2087 'input_prefix => "\t\t\t" ); 2088 }*/ 2089 2090 $this->output = $save_output; 2091 2092 if( ! $hidden ) 2093 { // there are not only hidden buttons : additional tags 2094 $r = $this->buttonsstart.$r.$this->buttonsend; 2095 } 2096 2097 return $this->display_or_return( $r ); 2098 } 2099 2100 2101 /** 2102 * Builds a button list. 2103 * 2104 * Array entries with numeric (deprecated) keys are converted to their equivalent string indexes. 2105 * 2106 * the two-dimension array must contain : 2107 * - the button type 2108 * - the name (optional) 2109 * - the value (optional) 2110 * - the class (optional) 2111 * - the onclick attribute (optional) 2112 * - the style (optional) 2113 * 2114 * @param array a two-dimension array containing the elements of the input tags 2115 * @param boolean to select or not the default display 2116 * @return mixed true (if output) or the generated HTML if not outputting 2117 */ 2118 function buttons( $buttons = array() ) 2119 { 2120 $buttons_list = array(); 2121 2122 foreach( $buttons as $l_button ) 2123 { 2124 $buttons_list[] = $this->convert_button_to_field_params( $l_button ); 2125 } 2126 2127 return $this->buttons_input( $buttons_list ); 2128 } 2129 2130 2131 /** 2132 * Builds a button. 2133 * 2134 * Array entries with numeric (deprecated) keys are converted to their equivalent string indexes. 2135 * 2136 * @param array Optional params. Additionally to {@link $_common_params} you can use: 2137 * - type: The type attribute (string, default 'submit') 2138 * @return mixed true (if output) or the generated HTML if not outputting 2139 */ 2140 function button_input( $field_params = array() ) 2141 { 2142 if( empty($field_params['type']) ) 2143 { // default type 2144 $field_params['type'] = 'submit'; 2145 } 2146 2147 if( !isset($field_params['input_prefix']) ) 2148 { // default prefix 2149 $field_params['input_prefix'] = "\t\t\t"; 2150 } 2151 2152 return $this->display_or_return( $this->get_input_element( $field_params ) ); 2153 } 2154 2155 2156 /** 2157 * Builds a button 2158 * 2159 * the array must contain : 2160 * - the button type 2161 * - the name (optional) 2162 * - the value (optional) 2163 * - the class (optional) 2164 * - the onclick attribute (optional) 2165 * - the style (optional) 2166 * 2167 * @param array a two-dimension array containing the elements of the input tags 2168 * @return mixed true (if output) or the generated HTML if not outputting 2169 */ 2170 function button( $options ) 2171 { 2172 $field_params = $this->convert_button_to_field_params( $options ); 2173 2174 if( empty($field_params['type']) ) 2175 { 2176 $field_params['type'] = 'submit'; // default type 2177 } 2178 2179 return $this->button_input( $field_params ); 2180 } 2181 2182 2183 /** 2184 * Convert a deprecated, numeric button array to a field_params array. 2185 * 2186 * @deprecated 2187 * @param array A button array like button() and buttons() are getting. 2188 * @return array The button array converted to a string indexed button array (field_params). 2189 */ 2190 function convert_button_to_field_params( $options ) 2191 { 2192 $field_params = array(); 2193 2194 foreach( array_keys($options) as $l_key ) 2195 { 2196 if( is_int($l_key) ) 2197 { 2198 switch( $l_key ) 2199 { 2200 case 0: $field_params['type'] = $options[0]; break; 2201 case 1: $field_params['name'] = $options[1]; break; 2202 case 2: $field_params['value'] = $options[2]; break; 2203 case 3: $field_params['class'] = $options[3]; break; 2204 case 4: $field_params['onclick'] = $options[4]; break; 2205 case 5: $field_params['style'] = $options[5]; break; 2206 } 2207 } 2208 else 2209 { 2210 $field_params[$l_key] = $options[$l_key]; 2211 } 2212 } 2213 2214 return $field_params; 2215 } 2216 2217 2218 /** 2219 * Builds an hidden input tag, overwriting any previous hidden values (except for "foo[]"). 2220 * 2221 * @param string Field name 2222 * @param string Field value 2223 * @param array Optional params. This is e.g. useful for "id". 2224 * See {@link $_common_params}. 2225 */ 2226 function hidden( $field_name, $field_value, $field_params = array() ) 2227 { 2228 if( is_array( $field_value ) ) 2229 { // this happens for example when we've POSTed an array (for PHP it's an array then) 2230 foreach( $field_value as $l_key => $l_value ) 2231 { 2232 // Recursion: 2233 $this->hidden( $field_name.'['.$l_key.']', $l_value, $field_params ); 2234 } 2235 } 2236 else 2237 { 2238 $field_params['name'] = $field_name; 2239 $field_params['type'] = 'hidden'; 2240 $field_params['value'] = $field_value; 2241 2242 if( strpos($field_name, '[]') ) 2243 { // array-style name or we don't want to overwrite, just add it: 2244 $this->hiddens[] = $this->get_input_element( $field_params ); 2245 } 2246 else 2247 { 2248 if( isset($this->existing_hiddens[$field_name]) ) 2249 { 2250 unset($this->hiddens[$this->existing_hiddens[$field_name]]); 2251 } 2252 2253 // add the field and remember that it already exists: 2254 end($this->hiddens); 2255 $key = key($this->hiddens)+1; 2256 $this->hiddens[$key] = $this->get_input_element( $field_params ); 2257 $this->existing_hiddens[$field_name] = $key; 2258 } 2259 } 2260 } 2261 2262 2263 /** 2264 * Add the "ctrl" param, used in the backoffice, as a hidden field. 2265 */ 2266 function hidden_ctrl() 2267 { 2268 global $ctrl; 2269 if( !empty( $ctrl) ) 2270 { 2271 $this->hidden( 'ctrl', $ctrl ); 2272 } 2273 } 2274 2275 2276 /** 2277 * Builds a list of hidden inputs. 2278 * 2279 * @param array Array of parameters to {@link hidden()}: 2280 * - 0: field_name 2281 * - 1: field_value 2282 * - 2: field_params 2283 * @return mixed true (if output) or the generated HTML if not outputting 2284 */ 2285 function hiddens( $hiddens ) 2286 { 2287 $save_output = $this->output; 2288 $this->output = false; 2289 foreach( $hiddens as $hidden ) 2290 { 2291 $this->hidden( $hidden[0], $hidden[1], isset($hidden[2]) ? $hidden[2] : array() ); 2292 } 2293 $this->output = $save_output; 2294 } 2295 2296 2297 /** 2298 * Builds a list of hidden inputs from an array where the keys are the field names. 2299 * 2300 * It supports array values (one-dimensional) and generates appropriate key-value pairs. 2301 * 2302 * @uses Form::hidden() 2303 * @param array associative array ( name => value ) of hidden fields. 2304 * @param array|NULL A list of keys to ignore. 2305 */ 2306 function hiddens_by_key( $hiddens, $exclude = NULL ) 2307 { 2308 if( $this->output ) 2309 { // only save output once, if necessary (recursion!) 2310 $save_output = $this->output; 2311 $this->output = false; 2312 } 2313 foreach( $hiddens as $l_name => $l_value ) 2314 { 2315 if( isset($exclude) && in_array( $l_name, $exclude ) ) 2316 { 2317 continue; 2318 } 2319 if( is_array( $l_value ) ) 2320 { // this happens for example when we've POSTed an array (for PHP it's an array then) 2321 foreach( $l_value as $ll_key => $ll_value ) 2322 { 2323 // Recursion: 2324 $this->hiddens_by_key( array( $l_name.'['.$ll_key.']' => $ll_value ), $exclude ); 2325 } 2326 } 2327 else 2328 { 2329 $this->hidden( $l_name, $l_value ); 2330 } 2331 } 2332 2333 if( isset($save_output) ) 2334 { 2335 $this->output = $save_output; 2336 } 2337 } 2338 2339 2340 /** 2341 * Builds a submit input tag 2342 * 2343 * the array must contain : 2344 * - the name (optional) 2345 * - the value (optional) 2346 * - the class (optional) 2347 * - the onclick attribute (optional) 2348 * - the style (optional) 2349 * 2350 * @todo Use <div class="input"> for layout == 'fieldset' (property). 2351 * @param array Optional params. Additionally to {@link $_common_params} you can use: 2352 * Nothing yet. 2353 * @return mixed true (if output) or the generated HTML if not outputting 2354 */ 2355 function submit_input( $field_params = array() ) 2356 { 2357 $field_params['type'] = 'submit'; 2358 2359 return $this->button_input( $field_params ); 2360 } 2361 2362 2363 /** 2364 * Builds a submit input tag 2365 * 2366 * the array must contain : 2367 * - the name (optional) 2368 * - the value (optional) 2369 * - the class (optional) 2370 * - the onclick attribute (optional) 2371 * - the style (optional) 2372 * 2373 * @param array an array containing the elements of the input tags 2374 * @return mixed true (if output) or the generated HTML if not outputting 2375 */ 2376 function submit( $options ) 2377 { 2378 array_unshift( $options, 'submit' ); 2379 2380 return $this->button( $options ); 2381 } 2382 2383 2384 /** 2385 * Generate set of radio options. 2386 * 2387 * @param string The name of the radio options 2388 * @param string The checked option's value 2389 * @param array of arrays The radio options 2390 * Keys: 2391 * - 'value' (required) 2392 * - 'label' (required) 2393 * - 'note' 2394 * - 'type' (default: "radio") 2395 * - 'class' (default: "radio") 2396 * - 'checked' (default: 'value' gets compared to $field_value) 2397 * - 'name' (default: $field_name) 2398 * - 'suffix' (gets used after the radio's label) 2399 * - Plus everything for {@link get_input_element()} ) 2400 * @param string Label 2401 * @param array Optional params. Additionally to {@link $_common_params} you can use: 2402 * - lines: Options on seperate lines (DIVs) (boolean, default false) 2403 * NOTE: these params/attribs get used as default for every INPUT field, 2404 * overridden by $field_options 2405 * @return mixed true (if output) or the generated HTML if not outputting 2406 */ 2407 function radio_input( $field_name, $field_value, $field_options, $field_label, $field_params = array() ) 2408 { 2409 if( isset($field_params['lines']) ) 2410 { 2411 $field_lines = $field_params['lines']; 2412 unset($field_params['lines']); // no HTML attribute 2413 } 2414 else 2415 { 2416 $field_lines = false; 2417 } 2418 2419 if( !isset($field_params['note_format']) ) 2420 { // Default field_note for radios: 2421 $field_params['note_format'] = '<span class="notes">%s</span>'; 2422 if( $field_lines ) 2423 { 2424 $field_params['note_format'] = '<div>'.$field_params['note_format'].'</div>'; 2425 } 2426 } 2427 2428 $field_params['id'] = false; // No ID attribute for the label 2429 $this->handle_common_params( $field_params, $field_name, $field_label ); 2430 unset($field_params['id']); // unset, so it gets handled correctly as default below 2431 2432 $r = $this->begin_field(); 2433 2434 /* 2435 * Build options list: 2436 */ 2437 $count_options = 0; // used for unique IDs (label/radio) 2438 foreach( $field_options as $loop_radio ) 2439 { 2440 // Merge defaults from $field_params: 2441 $loop_radio = array_merge( $field_params, $loop_radio ); 2442 2443 if( $field_lines ) $r .= "<div>\n"; 2444 2445 // Defaults: 2446 if( ! isset($loop_radio['type']) ) $loop_radio['type'] = 'radio'; 2447 if( ! isset($loop_radio['class']) ) $loop_radio['class'] = 'radio'; 2448 if( ! isset($loop_radio['name']) ) $loop_radio['name'] = $field_name; 2449 if( ! isset($loop_radio['id']) ) 2450 { // build unique id: 2451 $loop_radio['id'] = $this->get_valid_id($field_params['name'].'_radio_'.(++$count_options)); 2452 } 2453 2454 if( isset($loop_radio['checked']) ) 2455 { // convert boolean: 2456 if( $loop_radio['checked'] ) $loop_radio['checked'] = 'checked'; 2457 } 2458 elseif( $field_value == $loop_radio['value'] ) 2459 { // Current selection: 2460 $loop_radio['checked'] = 'checked'; 2461 } 2462 2463 // Unset non-HTML attribs: 2464 $label = $loop_radio['label']; 2465 $note = isset($loop_radio['note']) ? $loop_radio['note'] : null; 2466 $suffix = isset($loop_radio['suffix']) ? $loop_radio['suffix'] : ''; 2467 unset($loop_radio['label'], $loop_radio['note'], $loop_radio['suffix']); 2468 2469 // the radio element: 2470 $r .= $this->get_input_element( $loop_radio, false ); 2471 2472 // the label: 2473 $r .= '<label class="radiooption" for="'.$loop_radio['id'].'">'.$label.'</label>'; 2474 2475 if( ! empty($note) ) 2476 { // Add a note for the current radio option: 2477 $r .= '<span class="notes">'.$note.'</span>'; 2478 } 2479 2480 // optional text for radio option (like additional fieldsets or input boxes) 2481 $r .= $suffix; 2482 2483 // Split radio options by whitespace: 2484 $r .= "\n"; 2485 2486 if( $field_lines ) $r .= "</div>\n"; 2487 } 2488 2489 $r .= $this->end_field(); 2490 2491 return $this->display_or_return( $r ); 2492 } 2493 2494 2495 /** 2496 * Generate set of radio options. 2497 * 2498 * @param string the name of the radio options 2499 * @param string the checked option 2500 * @param array of arrays the radio options (0: value, 1: label, 2: notes, 3: additional HTML [input field, ..], 4: attribs for <input tag> ) 2501 * @param string label 2502 * @param boolean options on seperate lines (DIVs) 2503 * @param string notes 2504 * @return mixed true (if output) or the generated HTML if not outputting 2505 */ 2506 function radio( $field_name, $field_value, $field_options, $field_label, $field_lines = false, $field_note = '' ) 2507 { 2508 $new_field_options = array(); 2509 2510 foreach( $field_options as $l_key => $l_options ) 2511 { 2512 $new_field_options[$l_key] = array( 2513 'value' => $l_options[0], 2514 'label' => $l_options[1] ); 2515 2516 if( isset($l_options[2]) ) 2517 { 2518 $new_field_options[$l_key]['note'] = $l_options[2]; 2519 } 2520 if( isset($l_options[4]) ) 2521 { // Convert "inline attribs" to "params" array 2522 preg_match_all( '#(\w+)=[\'"](.*)[\'"]#', $l_options[4], $matches, PREG_SET_ORDER ); 2523 2524 foreach( $matches as $l_set_nr => $l_match ) 2525 { 2526 $new_field_options[$l_key][$l_match[1]] = $l_match[2]; 2527 } 2528 } 2529 2530 if( isset($l_options[3]) ) 2531 { 2532 $new_field_options[$l_key]['suffix'] = $l_options[3]; 2533 } 2534 } 2535 2536 $field_params = array( 'lines' => $field_lines, 'note' => $field_note ); 2537 2538 return $this->radio_input( $field_name, $field_value, $new_field_options, $field_label, $field_params ); 2539 } 2540 2541 2542 /** 2543 * Generate a general input field. 2544 * 2545 * This is the base function for text_input(), checkbox_input(), .. 2546 * 2547 * @uses get_input_element() to generate the <input> element 2548 * 2549 * @param array Optional params. Additionally to {@link $_common_params} you can use: 2550 * - see {@link get_input_element()} 2551 * @return true|string true (if output) or the generated HTML if not outputting 2552 */ 2553 function input_field( $field_params = array() ) 2554 { 2555 $element = $this->get_input_element($field_params); 2556 2557 $r = $this->begin_field() 2558 .$element 2559 .$this->end_field(); 2560 2561 return $this->display_or_return( $r ); 2562 } 2563 2564 2565 /** 2566 * Generate a general input element. 2567 * 2568 * @param array Optional params. 2569 * Additionally to {@link $_common_params} you can use: 2570 * - input_prefix: Text before <input /> (string, default '') 2571 * - input_suffix: Text after <input /> (string, default "\n") 2572 * - input_help: Gets used as default value on empty input (type=text) 2573 * elements. It gets attached through JavaScript (onfocus, onblur and form.onsubmit). 2574 * 2575 * @return string The <input /> element. 2576 */ 2577 function get_input_element( $field_params = array(), $parse_common = true ) 2578 { 2579 if( $parse_common ) 2580 { 2581 $this->handle_common_params( $field_params ); 2582 } 2583 2584 if( isset($field_params['input_prefix']) ) 2585 { 2586 $input_prefix = $field_params['input_prefix']; 2587 unset($field_params['input_prefix']); // no HTML attribute 2588 } 2589 else 2590 { 2591 $input_prefix = ''; 2592 } 2593 2594 if( isset($field_params['input_suffix']) ) 2595 { 2596 $input_suffix = $field_params['input_suffix']; 2597 unset($field_params['input_suffix']); // no HTML attribute 2598 } 2599 else 2600 { 2601 $input_suffix = "\n"; 2602 } 2603 2604 if( isset($field_params['input_help']) && ( empty($field_params['type']) || $field_params['type'] == 'text' ) ) 2605 { 2606 $this->append_javascript[] = 'input_decorated_help( "'.$field_params['id'].'", "'.format_to_output($field_params['input_help'], 'formvalue').'" );'; 2607 2608 unset($field_params['input_help']); // no HTML attribute 2609 } 2610 2611 $r = $input_prefix 2612 .'<input'.get_field_attribs_as_string( $field_params ).' />' 2613 .$input_suffix; 2614 2615 return $r; 2616 } 2617 2618 2619 /** 2620 * Convert a given string (e.g. fieldname) to a valid HTML id. 2621 * 2622 * @static 2623 * @return string 2624 */ 2625 function get_valid_id( $id ) 2626 { 2627 static $id_count = 0; 2628 if( substr( $id, -2 ) == '[]' ) 2629 { 2630 $id = substr( $id, 0, -2 ).'_A'.(++$id_count); 2631 } 2632 return str_replace( array( '[', ']' ), '_', $id ); 2633 } 2634 2635 2636 /** 2637 * Get the label of a field. This is used by {@link begin_field()} or {@link end_field()}, 2638 * 2639 * @access protected 2640 * @return string 2641 */ 2642 function get_label() 2643 { 2644 $r = ''; 2645 2646 $label = $this->_common_params['label']; 2647 2648 if( strlen($label) ) 2649 { 2650 $r .= $this->labelstart 2651 .'<label' 2652 .( !empty($this->_common_params['id']) 2653 ? ' for="'.format_to_output( $this->_common_params['id'], 'htmlattr' ).'"' 2654 : '' ) 2655 .'>' 2656 .format_to_output($label, 'htmlbody'); 2657 2658 $r .= $this->label_suffix; 2659 2660 $r .= '</label>' 2661 .$this->labelend; 2662 } 2663 else 2664 { // Empty label: 2665 $r .= $this->labelempty; 2666 } 2667 2668 return $r; 2669 } 2670 2671 2672 /** 2673 * Extract common params out of $field_params into {@link $_common_params} and unsets them in $field_params. 2674 * 2675 * Also handles adding errors to the note. 2676 * 2677 * @access protected 2678 * @param array An array passed to a field generating function like {@link text_input()}. By reference! 2679 * @param string|NULL The name of the field. If not empty it gets used to build the id attribute. 2680 */ 2681 function handle_common_params( & $field_params, $field_name = NULL, $field_label = NULL ) 2682 { 2683 #pre_dump( 'handle_common_params (before)', $field_params ); 2684 2685 $this->_common_params = array(); // Reset 2686 2687 // Copy optional variables, if given: 2688 if( isset($field_name) ) 2689 { 2690 $field_params['name'] = $field_name; 2691 } 2692 if( isset($field_label) ) 2693 { 2694 $field_params['label'] = $field_label; 2695 } 2696 2697 if( isset($field_params['note']) ) 2698 { 2699 $this->_common_params['note'] = $field_params['note']; 2700 unset($field_params['note']); // no HTML attribute 2701 } 2702 else 2703 { 2704 $this->_common_params['note'] = NULL; 2705 } 2706 2707 if( isset($field_params['note_format']) ) 2708 { 2709 $this->_common_params['note_format'] = $field_params['note_format']; 2710 unset($field_params['note_format']); // no HTML attribute 2711 } 2712 else 2713 { 2714 $this->_common_params['note_format'] = $this->note_format; 2715 } 2716 2717 if( isset($field_params['label']) ) 2718 { 2719 $this->_common_params['label'] = $field_params['label']; 2720 unset($field_params['label']); // no HTML attribute 2721 } 2722 else 2723 { 2724 $this->_common_params['label'] = ''; 2725 } 2726 2727 if( isset($field_params['field_prefix']) ) 2728 { 2729 $this->_common_params['field_prefix'] = $field_params['field_prefix']; 2730 unset( $field_params['field_prefix'] ); 2731 } 2732 2733 if( isset($field_params['field_suffix']) ) 2734 { 2735 $this->_common_params['field_suffix'] = $field_params['field_suffix']; 2736 unset( $field_params['field_suffix'] ); 2737 } 2738 2739 if( isset($field_params['required']) ) 2740 { 2741 $this->_common_params['required'] = $field_params['required']; 2742 unset($field_params['required']); 2743 } 2744 2745 2746 if( !empty($field_params['name']) ) 2747 { 2748 if( !isset($field_params['id']) ) 2749 { // Autogenerate id attrib (not for hidden, radio and submit types) 2750 if( empty($field_params['type']) 2751 || ( $field_params['type'] != 'hidden' 2752 && $field_params['type'] != 'radio' 2753 && $field_params['type'] != 'submit' 2754 ) ) 2755 { // Save ID with field_params and _common_params (for get_label()) 2756 $field_params['id'] = $this->_common_params['id'] = $this->get_valid_id($field_params['name']); 2757 } 2758 } 2759 else 2760 { 2761 $this->_common_params['id'] = $field_params['id']; 2762 } 2763 } 2764 2765 // Mark required fields: 2766 if( isset($this->_common_params['required']) && $this->_common_params['required'] ) 2767 { // add "field_required" class: 2768 if( isset($field_params['type']) && $field_params['type'] == 'checkbox' ) 2769 { // checkboxes need a span 2770 $field_params['input_prefix'] = ( isset($field_params['input_prefix']) ? $field_params['input_prefix'] : '' ).'<span class="checkbox_required">'; 2771 $field_params['input_suffix'] = '</span>'.( isset($field_params['input_suffix']) ? $field_params['input_suffix'] : '' ); 2772 } 2773 else 2774 { 2775 $field_params['class'] = isset( $field_params['class'] ) ? $field_params['class'].' field_required' : 'field_required'; 2776 } 2777 } 2778 2779 // Error handling: 2780 if( isset($field_params['name']) && param_has_error( $field_params['name'] ) ) 2781 { // There is an error message for this field: 2782 if( isset($field_params['type']) && $field_params['type'] == 'checkbox' ) 2783 { // checkboxes need a span 2784 $field_params['input_prefix'] = ( isset($field_params['input_prefix']) ? $field_params['input_prefix'] : '' ).'<span class="checkbox_error">'; 2785 $field_params['input_suffix'] = '</span>'.( isset($field_params['input_suffix']) ? $field_params['input_suffix'] : '' ); 2786 } 2787 else 2788 { 2789 $field_params['class'] = isset( $field_params['class'] ) ? $field_params['class'].' field_error' : 'field_error'; 2790 } 2791 2792 if( $this->disp_param_err_messages_with_fields ) 2793 { 2794 $this->_common_params['note'] .= ' <span class="field_error">'.param_get_error_msg( $field_params['name'] ).'</span>'; 2795 } 2796 } 2797 2798 #pre_dump( 'handle_common_params (after)', $field_params ); 2799 } 2800 2801 2802 /** 2803 * Display or return, according to {@link $output}. 2804 * 2805 * @return true|string True, if we want to display, the string if not. 2806 */ 2807 function display_or_return( $r ) 2808 { 2809 if( $this->output ) 2810 { 2811 echo $r; 2812 return true; 2813 } 2814 else 2815 { 2816 return $r; 2817 } 2818 } 2819 2820 } 2821 2822 /* 2823 * $Log: _form.class.php,v $ 2824 * Revision 1.16 2007/11/02 02:39:57 fplanque 2825 * refactored blog settings / UI 2826 * 2827 * Revision 1.15 2007/11/01 19:52:46 fplanque 2828 * better comment forms 2829 * 2830 * Revision 1.14 2007/10/29 01:24:49 fplanque 2831 * no message 2832 * 2833 * Revision 1.13 2007/10/10 10:52:26 yabs 2834 * validation - linsepan/blockspan/default are probably still invalid 2835 * 2836 * Revision 1.12 2007/10/08 08:31:59 fplanque 2837 * nicer forms 2838 * 2839 * Revision 1.11 2007/10/06 21:04:15 fplanque 2840 * temporary fix 2841 * 2842 * Revision 1.10 2007/09/30 05:00:45 fplanque 2843 * fixes 2844 * 2845 * Revision 1.9 2007/09/29 11:18:35 yabs 2846 * minor bug fix 2847 * 2848 * There's still a problem with the login form that needs fixing 2849 * 2850 * Revision 1.8 2007/09/29 09:48:55 yabs 2851 * minor bug fixes 2852 * 2853 * Revision 1.7 2007/09/29 03:08:24 fplanque 2854 * a little cleanup of the form class, hopefully fixing the plugin screen 2855 * 2856 * Revision 1.6 2007/09/12 21:00:30 fplanque 2857 * UI improvements 2858 * 2859 * Revision 1.5 2007/09/11 08:23:44 yabs 2860 * minor bug fix 2861 * 2862 * Revision 1.4 2007/09/07 20:11:18 fplanque 2863 * Better category selector 2864 * 2865 * Revision 1.3 2007/09/03 16:44:28 fplanque 2866 * chicago admin skin 2867 * 2868 * Revision 1.2 2007/09/02 19:23:42 blueyed 2869 * doc 2870 * 2871 * Revision 1.1 2007/06/25 10:59:01 fplanque 2872 * MODULES (refactored MVC) 2873 * 2874 * Revision 1.82 2007/05/23 09:17:04 blueyed 2875 * Support for stacking in Form::switch_layout() 2876 * 2877 * Revision 1.81 2007/05/15 14:57:24 blueyed 2878 * Fix for Form::select_input_array() "selected"-Handling (cast values to string when comparing) 2879 * 2880 * Revision 1.80 2007/04/26 00:11:07 fplanque 2881 * (c) 2007 2882 * 2883 * Revision 1.79 2007/04/23 15:06:28 blueyed 2884 * radio_input(): Respect "lines" param for "note_format" default value 2885 * 2886 * Revision 1.78 2007/04/20 03:01:12 fplanque 2887 * doc 2888 * 2889 * Revision 1.77 2007/04/16 15:49:59 blueyed 2890 * Minor fixes: 2891 * - allow "0" as label 2892 fp> once again this should not be documented in the changelog but at the right place in the code 2893 fp> someday it will just get "cleaned up" -> broken again for lack of a comment. Don't complain then... 2894 * - format-to-output label 2895 * 2896 * Revision 1.76 2007/04/16 15:46:10 blueyed 2897 * Fixed $labelempty for IE6 and "fieldset" layout 2898 * 2899 * Revision 1.75 2007/03/23 14:47:48 blueyed 2900 * - Display both "required" and "error" states in checklist() and through handle_common_params() 2901 * - "force_keys_as_values" param for select_input_array() (Props A. Becker) 2902 * - cleanup, minor fixes 2903 * 2904 * Revision 1.74 2007/03/23 14:33:23 blueyed 2905 * Re-added $field_params for hidden(), which is needed, e.g. when adding an id to a hidden form element. 2906 * 2907 * Revision 1.73 2007/03/21 01:44:51 fplanque 2908 * item controller: better return to current filterset - step 1 2909 * 2910 * Revision 1.72 2007/03/11 21:29:09 fplanque 2911 * cleanup 2912 * 2913 * Revision 1.71 2007/03/09 15:39:56 blueyed 2914 * radio_input(): Use "checked" param for $field_options if given 2915 * 2916 * Revision 1.70 2007/03/09 15:18:52 blueyed 2917 * Removed bloated "params" usage in Form::radio_input() for $field_options. Now the attribs/params for each radio input are directly in the $field_options entry instead. 2918 * 2919 * Revision 1.69 2007/02/11 15:00:15 fplanque 2920 * keeping JS abstraction. 2921 * 2922 * Revision 1.67 2007/01/24 06:43:25 fplanque 2923 * fix 2924 * 2925 * Revision 1.66 2007/01/23 08:57:36 fplanque 2926 * decrap! 2927 * 2928 * Revision 1.65 2007/01/07 05:25:09 fplanque 2929 * "fixed" regression :/ 2930 * 2931 * Revision 1.64 2006/12/22 22:22:20 blueyed 2932 * Unset "maxlength" field_param in textarea_input(): not a html attrib 2933 * 2934 * Revision 1.63 2006/12/13 19:34:25 fplanque 2935 * doc 2936 * 2937 * Revision 1.62 2006/12/13 18:00:35 blueyed 2938 * Allow "0" as note (again) + avoid unnecessary negation 2939 * 2940 * Revision 1.61 2006/12/10 23:17:10 fplanque 2941 * oops 2942 * 2943 * Revision 1.60 2006/12/10 22:17:04 fplanque 2944 * added note support to select_input 2945 * 2946 * Revision 1.59 2006/12/10 12:42:40 blueyed 2947 * "maxlength" handling for textarea fields through javascript 2948 * 2949 * Revision 1.58 2006/12/09 01:55:36 fplanque 2950 * feel free to fill in some missing notes 2951 * hint: "login" does not need a note! :P 2952 * 2953 * Revision 1.57 2006/12/08 02:08:01 uid156866 2954 * MFH: Fixed "Write" page/tab for Firefox 1.0.x 2955 * 2956 * Revision 1.56 2006/12/07 23:13:13 fplanque 2957 * @var needs to have only one argument: the variable type 2958 * Otherwise, I can't code! 2959 * 2960 * Revision 1.55 2006/12/06 19:12:11 fplanque 2961 * not all comments are something "TO DO". Some really just are "comments" 2962 * 2963 * Revision 1.54 2006/12/06 18:48:20 blueyed 2964 * doc 2965 * 2966 * Revision 1.53 2006/12/06 18:06:18 fplanque 2967 * an experiment with JS hiding/showing form parts 2968 * 2969 * Revision 1.52 2006/11/24 18:27:27 blueyed 2970 * Fixed link to b2evo CVS browsing interface in file docblocks 2971 * 2972 * Revision 1.51 2006/11/19 22:17:42 fplanque 2973 * minor / doc 2974 * 2975 * Revision 1.50 2006/11/19 15:52:27 blueyed 2976 * Fixed E_NOTICE with Form::hidden 2977 * 2978 * Revision 1.49 2006/11/18 17:58:57 blueyed 2979 * added DIV.inline and use it additionally for span.line replacement 2980 * 2981 * Revision 1.48 2006/11/16 23:48:56 blueyed 2982 * Use div.line instead of span.line as element wrapper for XHTML validity 2983 * 2984 * Revision 1.47 2006/11/16 20:03:25 blueyed 2985 * Cleanup; added $infoend support 2986 * 2987 * Revision 1.46 2006/11/16 01:49:40 fplanque 2988 * doc 2989 * 2990 * Revision 1.45 2006/11/08 17:47:55 blueyed 2991 * Extra classes 'form_text_input' and 'form_textarea_input' to enable IE6 CSS selection 2992 * 2993 * Revision 1.44 2006/11/05 20:13:57 fplanque 2994 * minor 2995 * 2996 * Revision 1.43 2006/11/03 14:25:24 blueyed 2997 * Made Form::get_valid_id() static 2998 * 2999 * Revision 1.42 2006/10/14 16:07:54 blueyed 3000 * Overwrite previous added hidden fields (by default), when adding hidden inputs. 3001 */ 3002 ?>
titre
Description
Corps
titre
Description
Corps
titre
Description
Corps
titre
Corps
| Généré le : Thu Nov 29 23:58:50 2007 | par Balluche grâce à PHPXref 0.7 |
|