00001 <?php
00010 class tpForm extends Plugin
00011 {
00012 var $guid = 0;
00013 var $data_id = 0;
00014
00015 var $errors;
00016 var $form_name;
00017 var $element_layouts;
00018
00022 function tpForm() {
00023 $this->Plugin();
00024 $this->depend('html');
00025
00026 $this->errors = array();
00027 $this->form_name = '';
00028
00029 $this->element_layouts = array(
00030 'leftlabel' => '<div class="form_element_container clearfix">'.
00031 '<div class="form_help form_leftlabel">{{HELP}}</div>'.
00032 '<div class="form_label form_leftlabel" style="width:{{LBLWIDTH}}; min-width:{{LBLWIDTH}};">{{LABEL}}</div>'.
00033 '<div class="form_element form_leftlabel">{{ELEMENT}}{{ERROR}}</div><!--[if IE]><br /><![endif]-->'.
00034 '</div>',
00035 'toplabel' => '<div class="form_element_container clearfix">'.
00036 '<div class="form_element form_toplabel">{{HELP}}{{LABEL}}<br />{{ELEMENT}}{{ERROR}}</div>'.
00037 '</div>',
00038 'labelonly' => '<div class="form_element_container clearfix">'.
00039 '<div class="form_label form_leftlabel" style="max-width:100%; width:100%">{{LABEL}}</div>'.
00040 '</div>',
00041 'elemonly' => '<div class="form_element_container clearfix">'.
00042 '<div class="form_element form_leftlabel" style="max-width:100%; width:100%">{{ELEMENT}}{{ERROR}}</div>'.
00043 '</div>'
00044 );
00045 }
00046
00054 function propagate($data='', $prefix='', $suffix='')
00055 {
00056 $out = '';
00057 if(!is_array($data)) {
00058 switch(strtolower($data)) {
00059 case 'post': $data = $_POST; break;
00060 case 'get': $data = $_GET; break;
00061 default: $data = array_merge($_GET, $_POST);
00062 }
00063 }
00064 foreach($data as $k=>$v) {
00065 if(is_array($v)) {
00066 if($prefix) {
00067 $out .= $this->propagate($v, $prefix.$k.'][', ']');
00068 } else {
00069 $out .= $this->propagate($v, $prefix.$k.'[', ']');
00070 }
00071 continue;
00072 }
00073 $out .= $this->hidden($prefix.$k.$suffix, $v)."\n";
00074 }
00075 return $out;
00076 }
00077
00084 function error_box($errors)
00085 {
00086 $out = '<div class="error"><ul>';
00087 foreach($errors as $k=>$v) {
00088 $out .= "<li>$v</li>";
00089 }
00090 $out .= '</ul></div>';
00091 return $out;
00092 }
00093
00103 function tooltip($text, $icon='')
00104 {
00105 if(!$icon) $icon = 'icons/info.gif';
00106 $this->depends->html->js_load('jq_tooltip', 'jq/jquery.tooltip');
00107 $this->depends->html->js_run('jq_tooltip', '$(\'img.helpicon\').Tooltip({showURL:false,delay:0});');
00108 $this->depends->html->css_load('tooltip');
00109
00110
00111 $text = preg_replace('|"|', '\\"', $text);
00112 return $this->depends->html->image($icon, array('class'=>'helpicon','title'=>$text));
00113 }
00114
00121 function tooltip_bind($elements)
00122 {
00123 $this->depends->html->js_load('jq_tooltip', 'jq/jquery.tooltip');
00124 $this->depends->html->js_run('', '$(\''.$elements.'\').Tooltip({showURL:false,delay:0});');
00125 $this->depends->html->css_load('tooltip', 'tooltip');
00126 }
00127
00139 function open_form($name, $action, $method='post', $errors=array(), $attribs=array())
00140 {
00141 $this->form_name = '';
00142 list($name) = $this->_escape($name);
00143 $id = $this->dom_id(isset($attribs['id']) ? $attribs['id'] : $name);
00144 unset($attribs['id']);
00145 $out = '<form name="'.$name.'" id="'.$id.'" method="'.$method.'" action="'.$action.'"';
00146 $out .= $this->depends->html->_attribs($attribs) . '>';;
00147 $this->errors = $errors;
00148 $this->form_name = $name;
00149 return $out;
00150 }
00151
00159 function close_form()
00160 {
00161 $this->errors = array();
00162 return '</form>';
00163 }
00164
00173 function imagebutton($name, $src, $attribs=array())
00174 {
00175 list($name,$src) = $this->_escape($name,$src);
00176 $id = $this->dom_id($name);
00177 $out = '<input type="image" name="'.$name.'" src="'.$src.'" align="absmiddle"';
00178 $attribs['class'] .= (empty($attribs['class']) ? 'image' : ' image');
00179 $out .= $this->depends->html->_attribs(array_merge(array('id'=>$id), $attribs));
00180 $out .= ' />';
00181 return $out;
00182 }
00183
00192 function submit($name, $value='Submit', $attribs=array())
00193 {
00194 list($name,$value) = $this->_escape($name,$value);
00195 $id = $this->dom_id($name);
00196 $out = '<input type="submit" name="'.$name.'" value="'.$value.'" class="submit" align="absmiddle"';
00197 $out .= $this->depends->html->_attribs(array_merge(array('id'=>$id), $attribs));
00198 $out .= ' />';
00199 return $out;
00200 }
00201
00210 function hidden($name, $value, $attribs=array())
00211 {
00212 list($name,$value) = $this->_escape($name,$value);
00213 $id = $this->dom_id($name);
00214 $out = '<input type="hidden" name="'.$name.'" value="'.$value.'"';
00215 $out .= $this->depends->html->_attribs(array_merge(array('id'=>$id), $attribs));
00216 $out .= ' />';
00217 return $out;
00218 }
00219
00230 function text($name, $value='', $size='', $maxlength='', $attribs=array())
00231 {
00232 list($name,$value) = $this->_escape($name,$value);
00233 $id = $this->dom_id($name);
00234 $err = $this->_error($name, $attribs);
00235 $out = '<input type="text" name="'.$name.'" value="'.$value.'"';
00236 if($size) $out .= ' size="'.$size.'"';
00237 if($maxlength) $out .= ' maxlength="'.$maxlength.'"';
00238 $out .= $this->depends->html->_attribs(array_merge(array('id'=>$id), $attribs));
00239 $out .= ' />';
00240 return $out.$err;
00241 }
00242
00253 function password($name, $value='', $size='', $maxlength='', $attribs=array())
00254 {
00255 list($name,$value) = $this->_escape($name,$value);
00256 $id = $this->dom_id($name);
00257 $err = $this->_error($name, $attribs);
00258 $out = '<input type="password" name="'.$name.'" value="'.$value.'"';
00259 if($size) $out .= ' size="'.$size.'"';
00260 if($maxlength) $out .= ' maxlength="'.$maxlength.'"';
00261 $out .= $this->depends->html->_attribs(array_merge(array('id'=>$id), $attribs));
00262 $out .= ' />';
00263 return $out.$err;
00264 }
00265
00280 function file($name, $value='', $size='', $preview_url='', $remove_url='', $attribs=array())
00281 {
00282 list($name,$value) = $this->_escape($name,$value);
00283 $id = $this->dom_id($name);
00284 $err = $this->_error($name, $attribs);
00285
00286 $out = '<input type="file" name="'.$name.'" value="'.$value.'"';
00287 if($size) $out .= ' size="'.$size.'"';
00288 $out .= $this->depends->html->_attribs(array_merge(array('id'=>$id), $attribs));
00289 $out .= ' />';
00290
00291 $preview_url = str_replace(array('_ID_','<id>'), $this->data_id, $preview_url);
00292 $remove_url = str_replace(array('_ID_','<id>'), $this->data_id, $remove_url);
00293
00294 if($preview_url) {
00295 $out .= ' '.$this->depends->html->link(__('Preview'), url($preview_url), '', false, array('target'=>'_blank'));
00296 } else if($value && $preview_url !== false) {
00297 // Use a sensible default URL (direct link to the file).
00298 // Don't url()-ize it, it's already absolute
00299 $out .= ' '.$this->depends->html->link(__('Preview'), $value, '', false, array('target'=>'_blank'));
00300 }
00301 if($remove_url) {
00302 $sep = $preview_url !== false ? ' | ' : ' ';
00303 $out .= $sep.$this->depends->html->link(__('Remove'), url($remove_url), __('Are you sure you want to remove this file?'));
00304 }
00305 return $out.$err;
00306 }
00307
00322 function image($name, $value='', $size='', $preview_url='', $remove_url='', $attribs=array())
00323 {
00324 list($name,$value) = $this->_escape($name,$value);
00325 $id = $this->dom_id($name);
00326 $err = $this->_error($name, $attribs);
00327 $out = '';
00328 $display = 'block';
00329 $preview_url = str_replace(array('_ID_','<id>'), $this->data_id, $preview_url);
00330 $remove_url = str_replace(array('_ID_','<id>'), $this->data_id, $remove_url);
00331 if($value) {
00332 $display = 'none';
00333 $out .= '<div id="'.$name.'_img">';
00334 if($preview_url) {
00335 $out .= $this->depends->html->link('<img src="'.$value.'" border="0" />', url($preview_url), '', true);
00336 } else {
00337 $out .= '<img src="'.$value.'" border="0" />';
00338 }
00339 $out .= '<br /><a href="#" onClick="$(\'#'.$name.'_img\').hide(\'normal\',function(){ $(\'#'.$name.'_file\').show(\'normal\'); });return false;">'.__('Change').'</a>';
00340 if($remove_url) {
00341 $out .= ' | '.$this->depends->html->link('Delete', url($remove_url), __('Are you sure?'));
00342 }
00343 $out .= '<br /></div>';
00344 }
00345 $out .= '<div id="'.$name.'_file" style="display:'.$display.'">';
00346 $out .= '<input type="file" name="'.$name.'" value="'.$value.'"';
00347 if($size) $out .= ' size="'.$size.'"';
00348 $out .= $this->depends->html->_attribs(array_merge(array('id'=>$id), $attribs));
00349 $out .= ' /></div>';
00350 return $out.$err;
00351 }
00352
00362 function date($name, $value='', $format='%Y-%m-%d', $attribs=array())
00363 {
00364 $err = $this->_error($name, $attribs);
00365 $id = $this->dom_id($name);
00366 $this->depends->html->css_load('calendar', 'calendar');
00367 $this->depends->html->js_load('calendar', 'calendar/calendar');
00368 $this->depends->html->js_load('calendar_lang', 'calendar/calendar-en');
00369 $this->depends->html->js_load('calendar_setup', 'calendar/calendar-setup');
00370 $js = <<<EOT
00371 Calendar.setup({
00372 inputField: "$id",
00373 ifFormat: "$format",
00374 showsTime: false,
00375 button: "btn_$name",
00376 singleClick: true,
00377 showOthers: true
00378 });
00379 EOT;
00380 $this->depends->html->js_run('calendar_setup', $js, false);
00381 $out = $this->text($name, $value, 10, 22, array_merge($attribs,array('no_error'=>true)));
00382 $out .= $this->depends->html->image('icons/calendar.gif', array('id'=>"btn_$name",'align'=>'top'));
00383 return $out.$err;
00384 }
00385
00395 function datetime($name, $value='', $format='%Y-%m-%d %k:%M', $attribs=array())
00396 {
00397 $err = $this->_error($name, $attribs);
00398 $id = $this->dom_id($name);
00399 $this->depends->html->css_load('calendar', 'calendar');
00400 $this->depends->html->js_load('calendar', 'calendar/calendar');
00401 $this->depends->html->js_load('calendar_lang', 'calendar/calendar-en');
00402 $this->depends->html->js_load('calendar_setup', 'calendar/calendar-setup');
00403 $js = <<<EOT
00404 // fix the width if in a table cell
00405 var inp = $('#$id');
00406 var dad = inp.parent()[0].nodeName.toLowerCase();
00407 if(dad == 'th' || dad == 'td') {
00408 inp.css('width', inp.width()+'px');
00409 inp.parent().css('width', (inp.width()+20+'px'));
00410 }
00411 inp.parent().find('img').css('cursor','pointer');
00412
00413 Calendar.setup({
00414 inputField: "$id",
00415 ifFormat: "$format",
00416 showsTime: true,
00417 button: "btn_$name",
00418 singleClick: true,
00419 showOthers: true
00420 });
00421 EOT;
00422 $this->depends->html->js_run('calendar_setup', $js, false);
00423 $out = $this->text($name, $value, 16, 34, array_merge($attribs,array('no_error'=>true)));
00424 $out .= $this->depends->html->image('icons/calendar.gif', array('id'=>"btn_$name",'align'=>'top'));
00425 return $out.$err;
00426 }
00427
00436 function color($name, $value, $attribs=array())
00437 {
00438 $err = $this->_error($name, $attribs);
00439 $div = '<div id="color_picker"></div>';
00440 $js = <<<EOT
00441 var farb = $.farbtastic('#color_picker');
00442 $('.colorwell').each(function(){
00443 farb.linkTo(this);
00444 });
00445 EOT;
00446 $value = $value ? $value : '#ffffff';
00447 $this->depends->html->css_load('colorsel', 'colorsel');
00448 $this->depends->html->js_load('jq_colorsel', 'jq/jquery.colorsel');
00449 $this->depends->html->js_run('jq_colorsel', $js);
00450 $out = $div;
00451 $out .= $this->text($name, $value, 8, 7, array_merge($attribs,array('class'=>'colorwell')));
00452 $out .= $this->imagebutton("btn_$name", $this->depends->html->url('/img/icons/color_wheel.gif',true),array('onClick'=>'colorsel(this,\''.$name.'\');return false;'));
00453 return $out.$err;
00454 }
00455
00466 function textarea($name, $value='', $rows=10, $cols=50, $attribs=array())
00467 {
00468 list($name,$value) = $this->_escape($name,$value);
00469 $err = $this->_error($name, $attribs);
00470 $id = $this->dom_id($name);
00471 $out = '<textarea name="'.$name.'" rows="'.$rows.'" cols="'.$cols.'"';
00472 $out .= $this->depends->html->_attribs(array_merge(array('id'=>$id), $attribs));
00473 $out .= '>';
00474 $out .= $value . '</textarea>';
00475 return $out.$err;
00476 }
00477
00494 function htmlarea($name, $value='', $rows=15, $cols=100, $mceinit='', $attribs=array())
00495 {
00496 $js_gz = <<<EOT
00497 tinyMCE_GZ.init({
00498 plugins : "safari,pagebreak,style,layer,table,save,advhr,advimage,advlink,emotions,iespell,inlinepopups,insertdatetime,preview,media,searchreplace,print,contextmenu,paste,directionality,fullscreen,noneditable,visualchars,nonbreaking,xhtmlxtras,template",
00499 themes : "simple,advanced",
00500 languages : "en",
00501 disk_cache : true,
00502 debug : false
00503 });
00504 EOT;
00505
00506 $default_cfg = array(
00507 'mode' => "textareas",
00508 'theme' => "advanced",
00509 'editor_selector' => "mceEditor",
00510 'plugins' => "safari,pagebreak,style,layer,table,save,advhr,advimage,advlink,emotions,iespell,inlinepopups,insertdatetime,preview,media,searchreplace,print,contextmenu,paste,directionality,fullscreen,noneditable,visualchars,nonbreaking,xhtmlxtras,template",
00511
00512 // Theme options
00513 'theme_advanced_buttons1' => "save,newdocument,|,bold,italic,underline,strikethrough,|,justifyleft,justifycenter,justifyright,justifyfull,|,styleselect,formatselect,fontselect,fontsizeselect",
00514 'theme_advanced_buttons2' => "cut,copy,paste,pastetext,pasteword,|,search,replace,|,bullist,numlist,|,outdent,indent,blockquote,|,undo,redo,|,link,unlink,anchor,image,cleanup,help,code,|,insertdate,inserttime,preview,|,forecolor,backcolor",
00515 'theme_advanced_buttons3' => "tablecontrols,|,hr,removeformat,visualaid,|,sub,sup,|,charmap,emotions,iespell,media,advhr,|,print,|,ltr,rtl,|,fullscreen",
00516 //'theme_advanced_buttons4' => "insertlayer,moveforward,movebackward,absolute,|,styleprops,|,cite,abbr,acronym,del,ins,attribs,|,visualchars,nonbreaking,template,pagebreak",
00517 'theme_advanced_toolbar_location' => "top",
00518 'theme_advanced_toolbar_align' => "left",
00519 'theme_advanced_statusbar_location' => "bottom",
00520 'theme_advanced_resizing' => true,
00521
00522 // Options
00523 'file_browser_callback' => "tinyBrowser",
00524 'convert_urls' => false,
00525 'relative_urls' => false,
00526 'paste_use_dialog' => false,
00527 'theme_advanced_resizing' => true,
00528 'theme_advanced_resize_horizontal' => true,
00529 'apply_source_formatting' => true,
00530 'force_br_newlines' => true,
00531 'force_p_newlines' => false,
00532
00533 'content_css' => url('/css.php?c=htmlarea')
00534 );
00535
00536 // if no $mceinit specified, fall back to a default one set by htmlarea_preload()
00537 if($mceinit === '' && isset($this->_mce_init)) $mceinit = $this->_mce_init;
00538
00539 // if $mceinit['content_css'] is an array of files, then convert the
00540 // local ones to go through css.php
00541 if(is_array($mceinit) && is_array($mceinit['content_css'])) {
00542 $css_arr = array();
00543 foreach($mceinit['content_css'] as $c) {
00544 $css_arr[] = (!preg_match('|^http[s]?:
00545 }
00546 $mceinit['content_css'] = implode(',', $css_arr);
00547 }
00548
00549 if(is_array($mceinit)) {
00550
00551 $init_cfg = json_encode(array_merge($default_cfg, $mceinit));
00552 } else if(!empty($mceinit)) {
00553
00554 $init_cfg = $mceinit;
00555 } else {
00556
00557 $init_cfg = json_encode($default_cfg);
00558 }
00559
00560 $mceinit = <<<EOT
00561 tinyMCE.init($init_cfg);
00562
00563 function mce_toggle(id) {
00564 if(!tinyMCE.get(id)) {
00565 tinyMCE.execCommand('mceAddControl', false, id);
00566 } else {
00567 tinyMCE.execCommand('mceRemoveControl', false, id);
00568 }
00569 }
00570 EOT;
00571
00572 if($this->web->ajax) {
00573 $js_ajax = "tinyMCE.execCommand(\"mceAddControl\", false, \"$name\");";
00574 $this->depends->html->js_run('+tinymce_'.$name, $js_ajax);
00575 } else {
00576 $this->depends->html->head('tinymce_gz_js', $this->depends->html->js('tinymce/tiny_mce_gzip'));
00577 $this->depends->html->head('tinymce_browser_js', '<script type="text/javascript" src="'.url('/js/tinymce/plugins/tinybrowser/tb_tinymce.js.php').'"></script>');
00578 $this->depends->html->head('tinymce_gzinit_js', '<script type="text/javascript">'.$js_gz.'</script>');
00579
00580 $this->depends->html->js_run('+tinymce', $mceinit);
00581 }
00582
00583
00584
00585 $_SESSION['TINYMCE'] = true;
00586
00587 if($name == '_htmlarea_preload') return '';
00588 return $this->textarea($name, $value, 15, 100, array('class'=>'mceEditor')+$attribs);
00589 }
00590
00607 function htmlarea_preload($mceinit='')
00608 {
00609 $this->_mce_init = $mceinit;
00610 return $this->htmlarea('_htmlarea_preload', '', 15, 100, $mceinit, array('style'=>'display:none'));
00611 }
00612
00623 function checkbox($name, $value='', $label='', $checked=false, $attribs=array())
00624 {
00625 list($name,$value) = $this->_escape($name,$value);
00626 $err = $this->_error($name, $attribs);
00627 $id = $this->dom_id($name);
00628 $out = '<input type="checkbox" name="'.$name.'" value="'.$value.'"';
00629 if($checked) $out .= ' checked="checked"';
00630 $out .= $this->depends->html->_attribs(array_merge(array('id'=>$id, 'style'=>'border:none'),$attribs));
00631 $out .= ' /> '.$label;
00632 return $out.$err;
00633 }
00634
00645 function radio($name, $value='', $options=array(), $sep='<br />', $attribs=array())
00646 {
00647
00648 if(is_array($sep)) {
00649 $attribs = $sep;
00650 $sep = '<br />';
00651 }
00652
00653 list($name) = $this->_escape($name);
00654 $err = $this->_error($name, $attribs);
00655 $id = $this->dom_id($name);
00656 $out = '';
00657 foreach($options as $val=>$label) {
00658 $out .= '<input type="radio" name="'.$name.'" value="'.$val.'"';
00659 if($val == $value) $out .= ' checked="checked"';
00660 $out .= $this->depends->html->_attribs(array_merge(array('id'=>$id, 'style'=>'border:none'),$attribs));
00661 $out .= ' /> '.$label.$sep;
00662 }
00663 return $out.$err;
00664 }
00665
00677 function select($name, $value='', $options=array(), $size='', $multiple=false, $attribs=array())
00678 {
00679 list($name) = $this->_escape($name);
00680 $err = $this->_error($name, $attribs);
00681 $id = $this->dom_id($name);
00682 $fname = $name;
00683 if($multiple && substr($fname, -2) != '[]') $fname .= '[]';
00684 $out = '<select name="'.$fname.'"';
00685 if($size) $out .= ' size="'.$size.'"';
00686 if($multiple) $out .= ' multiple="multiple"';
00687 $out .= $this->depends->html->_attribs(array_merge(array('id'=>$id), $attribs));
00688 $out .= '>';
00689
00690 if(!$multiple && is_array($value)) $value = array_shift($value);
00691
00692 $selected = false;
00693 foreach($options as $val=>$label) {
00694 if(is_array($label)) {
00695 $out .= '<optgroup label="'.$val.'">';
00696 foreach($label as $subval=>$sublbl) {
00697 $out .= $this->_select_option($subval, $sublbl, $value, $multiple, $selected);
00698 }
00699 $out .= '</optgroup>';
00700 } else {
00701 $out .= $this->_select_option($val, $label, $value, $multiple, $selected);
00702 }
00703 }
00704 $out .= '</select>';
00705 return $out.$err;
00706 }
00707 function _select_option($optval, $optlbl, $value, $mult, &$sel) {
00708 $ret = '<option value="'.$optval.'"';
00709 if(is_array($value) && $mult) {
00710
00711 if(in_array($optval, $value)) $ret .= ' selected';
00712 } else {
00713
00714 if($optval == $value && !$mult && !$sel) {
00715 $ret .= ' selected';
00716 $sel = true;
00717 }
00718 }
00719 $ret .= '>'.$optlbl.'</option>';
00720 return $ret;
00721 }
00722
00736 function multiselect($name, $value, $options, $show_selects=false, $multiple=true, $attribs=array())
00737 {
00738 $err = $this->_error($name, $attribs);
00739 $id = $this->dom_id($name);
00740 if(!is_array($value)) $value = array($value=>$value);
00741 list($name) = $this->_escape($name);
00742 if(substr($name, -2) != '[]') $name .= '[]';
00743
00744 $js = <<<EOT
00745 $('div.multiselect p.option').click(function(){
00746 var chk = $(this).find('input[type=checkbox]:first');
00747 if(chk.attr('checked')) {
00748 chk.attr('checked',false);
00749 $(this).removeClass("selected");
00750 } else {
00751 var div = chk.parent().parent();
00752 if(div.attr('rel') != 'multiple') {
00753 div.find('input[type=checkbox]').attr('checked',false).parent().removeClass("selected");
00754 }
00755 chk.attr('checked',true);
00756 $(this).addClass("selected");
00757 }
00758 });
00759 $('div.multiselect p.option input[type=checkbox]').click(function() {
00760 $(this).attr('checked', !$(this).attr('checked'));
00761 });
00762 EOT;
00763 $out = '<div class="multiselect_container"';
00764 $out .= $this->depends->html->_attribs($attribs);
00765 $out .= '>';
00766 $out .= '<div class="multiselect" id="'.$id.'"';
00767 if($multiple) $out .= ' rel="multiple"';
00768 $out .= '>';
00769 foreach($options as $val=>$label) {
00770 if(in_array($val, $value)) {
00771 $out .= '<p class="option selected"><input type="checkbox" name="'.$name.'" value="'.$val.'" checked="checked" /> '.$label.'</p>';
00772 } else {
00773 $out .= '<p class="option"><input type="checkbox" class="checkbox" name="'.$name.'" value="'.$val.'" /> '.$label.'</p>';
00774 }
00775 }
00776 $out .= '</div>';
00777 if($show_selects) {
00778 $out .= '<div class="multiselect_control" id="'.$id.'_control">';
00779 $out .= $this->depends->html->image('icons/tick.gif', 'selall', array('title'=>__('Select All')));
00780 $out .= $this->depends->html->image('icons/cross.gif', 'selnone', array('title'=>__('Select None')));
00781 $out .= '</div>';
00782 $this->depends->html->css_load('', 'tooltip');
00783 $this->depends->html->js_load('jq_tooltip', 'jq/jquery.tooltip');
00784 $this->depends->html->js_run('jq_tooltip_multiselect', '$(\'div.multiselect_control img\').Tooltip({showURL:false,extraClass:\'action\'});');
00785 $js .= <<<EOT
00786 $('div.multiselect_control img[alt=selall]').click(function() {
00787 $(this).parent().prev('div').find('input[type=checkbox]').each(function(){
00788 $(this).attr('checked',true);
00789 $(this).parent().addClass("selected");
00790 });
00791 });
00792 $('div.multiselect_control img[alt=selnone]').click(function() {
00793 $(this).parent().prev('div').find('input[type=checkbox]').each(function(){
00794 $(this).attr('checked',false);
00795 $(this).parent().removeClass("selected");
00796 });
00797 });
00798 EOT;
00799 }
00800 $out .= '</div>';
00801 $this->depends->html->js_run('multiselect', $js);
00802 return $out.$err;
00803 }
00804
00846 function build_form($params, $data=array(), $errors=array())
00847 {
00848 $guid = ++$this->guid;
00849
00850 $class = $this->_getparam($params, 'class', 'form');
00851 $method = $this->_getparam($params, 'method', 'post');
00852 $submit = $this->_getparam($params, 'submit', __('Save Changes'));
00853 $options = $this->_getparam($params, 'options', array());
00854 $data_id = $this->_getparam($params, 'data_id', 0);
00855 $layout = $this->_getparam($params, 'layout', array());
00856 $elements = $this->_getparam($params, 'elements', array());
00857 $form_id = $this->_getparam($params, 'form_id', 'form'.$guid);
00858 $form_name = $this->_getparam($params, 'form_name', 'form'.$guid);
00859 $action = $this->_getparam($params, 'action', '');
00860
00861
00862
00863
00864 $this->data_id = $data_id;
00865
00866 if(!$options['noopen']) {
00867
00868 $form_attribs = array('id'=>$form_id);
00869 if(isset($params['enctype'])) $form_attribs['enctype'] = $params['enctype'];
00870 $out .= $this->open_form($form_name, $action, $method, $errors, $form_attribs);
00871
00872
00873 $out .= '<div';
00874 if($class) $out .= ' class="'.$class.'"';
00875 $out .= ">\n";
00876 }
00877
00878 $numcols = $this->_getparam($options, 'numcols', 1);
00879
00880
00881 $first_key = key($elements);
00882 $first_val = current($elements);
00883 if(isset($first_val['type']) && !is_array($first_val['type'])) {
00884 $elements = array('0' => $elements);
00885 }
00886
00887
00888 if($data_id && !$options['nopk']) {
00889 $elements[$first_key]['id'] = array('type'=>'hidden','value'=>$data_id);
00890 }
00891
00892 assert_type($layout, 'array');
00893 foreach($elements as $col=>$subform) {
00894 assert_type($layout[$col], 'array');
00895 if(!isset($layout[$col]['colspan'])) $layout[$col]['colspan'] = 1;
00896 if(!isset($layout[$col]['label_width'])) $layout[$col]['label_width'] = 'auto';
00897 }
00898
00899 $elem_layout = $options['toplabel'] ? 'toplabel' : 'leftlabel';
00900
00901
00902 foreach($elements as $column=>$elems) {
00903 foreach($elems as $name=>$elem) {
00904 if(isset($elem['value']) && $elem['type'] == 'checkbox') {
00905 if($data[$name] == $elem['value']) {
00906 $elements[$column][$name]['checked'] = true;
00907 }
00908 } else if(!isset($elem['value']) && isset($data[$name])) {
00909
00910 if(!($elements[$column][$name]['type'] == 'date' && $data[$name] == '0000-00-00')) {
00911 $elements[$column][$name]['value'] = $data[$name];
00912 }
00913 }
00914 unset($errors[$name]);
00915 }
00916 }
00917
00918
00919
00920 if(count($errors) && !$options['hide_misc_errors']) {
00921 $out .= $this->error_box($errors);
00922 }
00923
00924
00925 foreach($elements as $column=>$subform) {
00926 foreach($subform as $name=>$elem) {
00927 if($elem['type'] != 'hidden') continue;
00928 $out .= $this->hidden($name, $elem['value']);
00929 }
00930 }
00931
00932 $c_loc = 0;
00933 $clearnext = true;
00934 foreach($elements as $col_id=>$subform) {
00935
00936 if($clearnext && $c_loc > 0) $out .= '<br class="clearfix" />';
00937 $c_loc += $layout[$col_id]['colspan'];
00938 if(isset($layout[$col_id]['width'])) {
00939 $width = $layout[$col_id]['width'];
00940 if(is_numeric($width)) $width .= 'px';
00941 } else {
00942 $width = floor(($layout[$col_id]['colspan'] / $numcols) * 100).'%';
00943 }
00944 $cls = $c_loc % $numcols == 0 ? ' dynsize' : '';
00945 if($layout[$col_id]['colspan']) {
00946 $cls .= " {$layout[$col_id]['class']}";
00947 }
00948 $out .= '<div class="subform'.$cls.'" style="width:'.$width.';';
00949 if($clearnext) {
00950 $out .= 'clear:left;';
00951 $clearnext = false;
00952 } else if($c_loc % $numcols == 0) {
00953
00954 $out .= $numcols == 1 ? 'clear:both' : 'clear:right;';
00955 $clearnext = true;
00956 }
00957 $out .= '">';
00958
00959
00960 if(!isset($layout[$col_id]['label_width'])) $layout[$col_id]['label_width'] = 'auto';
00961 $lblwidth = $layout[$col_id]['label_width'];
00962 if($elem_layout == 'leftlabel' && $lblwidth == 'auto') {
00963 if($layout[$col_id]['label_width'] == 'auto') {
00964
00965 $llength = 0;
00966 foreach($subform as $name=>$elem) {
00967 if($elem['type'] == 'label') continue;
00968 if(!isset($elem['prompt'])) continue;
00969 $s = mb_strlen(strip_tags($elem['prompt']));
00970 if($s > $llength) $llength = $s;
00971 }
00972 $lblwidth = $llength.'em';
00973 }
00974 }
00975 if(is_numeric(substr($lblwidth, -1, 1))) $lblwidth .= 'px';
00976
00977 foreach($subform as $name=>$elem) {
00978 if($elem['type'] == 'hidden') continue;
00979
00980 $subvars = array('help'=>'', 'label'=>'', 'element'=>'', 'error'=>'', 'lblwidth'=>$lblwidth);
00981 $attribs = $this->_getparam($elem, 'attribs', array());
00982
00983 if(isset($elem['error'])) $attribs['class'] = 'error';
00984
00985 $attribs['tabindex'] = $c_loc;
00986
00987
00988 if(isset($elem['help'])) {
00989 $subvars['help'] = $this->tooltip($elem['help']);
00990 if($elem_layout == 'toplabel') $subvars['help'] .= ' ';
00991 } else if($elem_layout == 'leftlabel') {
00992 $subvars['help'] = ' ';
00993 }
00994
00995
00996 if(empty($elem['prompt'])) $elem['prompt'] = ' ';
00997 $subvars['label'] = '<label for="'.$name.'">'.$elem['prompt'].'</label>';
00998 $subvars['element'] = $this->_show_element($name, $elem, $attribs);
00999 if(isset($elem['error'])) {
01000 $subvars['error'] = '<br /><p class="error">'.$elem['error'].'</p>';
01001 }
01002
01003 if($elem['type'] == 'label') {
01004 $el = $this->element_layouts['labelonly'];
01005 } else if($elem['nolabel'] == true) {
01006 $el = $this->element_layouts['elemonly'];
01007 } else {
01008 $el = $this->element_layouts[$elem_layout];
01009 }
01010
01011
01012 $out .= str_replace(
01013 array('{{HELP}}','{{LABEL}}','{{ELEMENT}}','{{ERROR}}','{{LBLWIDTH}}'),
01014 $subvars, $el);
01015 }
01016 $out .= "</div>\n";
01017 }
01018
01019 if(!$options['noclose'] && !$options['nosubmit']) {
01020 $c = array_shift(explode(' ', $class));
01021
01022 if(empty($params['submit_pos']) || $params['submit_pos'] == 'right') {
01023
01024 $js = <<<EOT
01025 var elem_width = 0;
01026 try { var parent = $('#$form_id div.$c').position(); } catch(err) { return; }
01027 $('#{$form_id} div.dynsize').find('div.form_element').each(function(){
01028 var pos = $(this).position().left + $(this).width() - parent.left;
01029 if(pos > elem_width) elem_width = pos;
01030 });
01031 $('#{$form_id} div.form_submit').css('width', elem_width+'px');
01032 EOT;
01033 $this->depends->html->js_run('', $js);
01034 }
01035
01036 $out .= '<div class="form_submit">';
01037
01038
01039
01040 if(isset($params['submit_html'])) {
01041 $out .= $params['submit_html'];
01042 } else {
01043 $opts = array();
01044 if(isset($options['spinner'])) {
01045 $opts['onClick'] .= "$(this).prev('img.spinner').css('display','inline');";
01046 $out .= $this->depends->html->image($options['spinner'], array('class'=>'spinner','align'=>'top','style'=>'display:none'));
01047 }
01048 if(isset($params['submit_msg'])) {
01049 $opts['onClick'] .= "this.value='{$params['submit_msg']}';this.disabled=true;this.form.submit();return false;";
01050 }
01051 if(is_array($submit)) {
01052 if($data_id) {
01053 $out .= $this->submit('submit_btn'.$guid, $submit[1], $opts);
01054 } else {
01055 $out .= $this->submit('submit_btn'.$guid, $submit[0], $opts);
01056 }
01057 } else {
01058 $out .= $this->submit('submit_btn'.$guid, $submit, $opts);
01059 }
01060 }
01061
01062 $out .= "</div>\n";
01063 }
01064
01065 if(!$options['noclose']) {
01066 $out .= "</div>\n";
01067 $out .= $this->close_form();
01068 }
01069
01070 $this->data_id = 0;
01071 return $out;
01072 }
01073
01108 function build_tabbed_form($params, $tabs, $data=array(), $errors=array())
01109 {
01110 $guid = ++$this->guid;
01111
01112 $class = $this->_getparam($params, 'class', 'form');
01113 $method = $this->_getparam($params, 'method', 'post');
01114 $submit = $this->_getparam($params, 'submit', __('Save Changes'));
01115 $submit_msg = $this->_getparam($params, 'submit_msg', '');
01116 $form_id = $this->_getparam($params, 'form_id', 'form'.$guid);
01117 $form_name = $this->_getparam($params, 'form_name', 'form'.$guid);
01118 $action = $this->_getparam($params, 'action', '');
01119 $data_id = $this->_getparam($params, 'data_id', 0);
01120 $spinner = $this->_getparam($params, 'spinner', '');
01121
01122 $this->depends->html->css_load('tabs');
01123 $this->depends->html->js_load('jq/jquery.tabs');
01124
01125 $out = '';
01126
01127
01128 $form_attribs = array('id'=>$form_id);
01129 if(isset($params['enctype'])) $form_attribs['enctype'] = $params['enctype'];
01130 $out .= $this->open_form($form_name, $action, $method, $errors, $form_attribs);
01131 if($data_id) {
01132 $out .= $this->hidden('id', $data_id);
01133 }
01134
01135 $out .= '<div id="form_container'.$guid.'">';
01136 $out .= '<ul>';
01137 foreach($tabs as $tabid=>$tab) {
01138 $active = $tab['active'] ? ' class="tabs-selected"' : '';
01139 $out .= '<li'.$active.'><a href="#'.$tabid.'">'.$tab['label'].'</a></li>';
01140 }
01141 $out .= '</ul>';
01142 foreach($tabs as $tabid=>$tab) {
01143 $content = '';
01144 if(isset($tab['content'])) {
01145 $content = $tab['content'];
01146 } else if(isset($tab['form'])) {
01147 $f = $tab['form'];
01148 if(!is_array($f['options'])) $f['options'] = array();
01149 $f['options']['noopen'] = true;
01150 $f['options']['noclose'] = true;
01151 $f['options']['nopk'] = true;
01152 $f['data_id'] = $data_id;
01153 $content = $this->build_form($f, $data, $errors);
01154 }
01155
01156 $out .= '<div id="'.$tabid.'" style="background:#fff;">';
01157 $out .= '<div class="'.$class.' clearfix">';
01158 $out .= $content;
01159 $out .= '</div></div>';
01160 }
01161 $out .= '</div>';
01162
01163
01164 $opts = array('style'=>'float:right');
01165 if($spinner) $opts['onClick'] .= "$(this).next('img.spinner').css('display','inline');";
01166 if($submit_msg) $opts['onClick'] .= "this.value='$submit_msg';this.disabled=true;this.form.submit();return false;";
01167 if(is_array($submit)) {
01168 if($data_id) {
01169 $out .= $this->submit('submit_btn'.$guid, $submit[1], $opts);
01170 } else {
01171 $out .= $this->submit('submit_btn'.$guid, $submit[0], $opts);
01172 }
01173 } else {
01174 $out .= $this->submit('submit_btn'.$guid, $submit, $opts);
01175 }
01176 if($spinner) $out .= $this->depends->html->image($spinner, array('class'=>'spinner','align'=>'top','style'=>'float:right;display:none'));
01177 $out .= $this->close_form();
01178
01179 $this->depends->html->js_run('', "$('#form_container{$guid}').tabs();");
01180
01181 return $out;
01182 }
01183
01184 function _show_element($name, $elem, $attribs)
01185 {
01186 $out = '';
01187 switch($elem['type']) {
01188
01189
01190
01191
01192
01193
01194
01195
01196
01197 case 'separator':
01198 case 'label':
01199 $out .= '<br />';
01200 break;
01201 case 'custom':
01202 $out .= $this->_getparam($elem, 'data', '');
01203 break;
01204 case 'value':
01205 $v = $this->_getparam($elem, 'value', '');
01206 if(empty($v)) $v = ' ';
01207 $out .= "<strong>$v</strong>";
01208 break;
01209
01210 case 'text':
01211 $out .= $this->text($name,
01212 $this->_getparam($elem, 'value', ''),
01213 $this->_getparam($elem, 'size', 30),
01214 $this->_getparam($elem, 'maxlength', 255),
01215 $attribs);
01216 break;
01217 case 'password':
01218 $out .= $this->password($name,
01219 $this->_getparam($elem, 'value', ''),
01220 $this->_getparam($elem, 'size', 30),
01221 $this->_getparam($elem, 'maxlength', 255),
01222 $attribs);
01223 break;
01224 case 'file':
01225 $out .= $this->file($name,
01226 $this->_getparam($elem, 'value', ''),
01227 $this->_getparam($elem, 'size', '30'),
01228 $this->_getparam($elem, 'preview_url', ''),
01229 $this->_getparam($elem, 'remove_url', ''),
01230 $attribs);
01231 break;
01232 case 'image':
01233 $out .= $this->image($name,
01234 $this->_getparam($elem, 'value', ''),
01235 $this->_getparam($elem, 'size', '30'),
01236 $this->_getparam($elem, 'preview_url', ''),
01237 $this->_getparam($elem, 'remove_url', ''),
01238 $attribs);
01239 break;
01240 case 'date':
01241 $out .= $this->date($name,
01242 $this->_getparam($elem, 'value', ''),
01243 $this->_getparam($elem, 'format', '%Y-%m-%d'),
01244 $attribs);
01245 break;
01246 case 'datetime':
01247 $out .= $this->datetime($name,
01248 $this->_getparam($elem, 'value', ''),
01249 $this->_getparam($elem, 'format', '%Y-%m-%d %k:%M'),
01250 $attribs);
01251 break;
01252 case 'color':
01253 $out .= $this->color($name,
01254 $this->_getparam($elem, 'value', ''),
01255 $attribs);
01256 break;
01257 case 'textarea':
01258 $out .= $this->textarea($name,
01259 $this->_getparam($elem, 'value', ''),
01260 $this->_getparam($elem, 'rows', 10),
01261 $this->_getparam($elem, 'cols', 50),
01262 $attribs);
01263 break;
01264 case 'richtextarea':
01265 $out .= $this->richtextarea($name,
01266 $this->_getparam($elem, 'value', ''),
01267 $this->_getparam($elem, 'height', 500),
01268 $this->_getparam($elem, 'width', 600),
01269 $this->_getparam($elem, 'toolbar', ''),
01270 $attribs);
01271 break;
01272 case 'htmlarea':
01273 $out .= $this->htmlarea($name,
01274 $this->_getparam($elem, 'value', ''),
01275 $this->_getparam($elem, 'rows', 15),
01276 $this->_getparam($elem, 'cols', 100),
01277 $this->_getparam($elem, 'mceinit', ''),
01278 $attribs);
01279 break;
01280 case 'checkbox':
01281 $out .= $this->checkbox($name,
01282 $this->_getparam($elem, 'value', ''),
01283 $this->_getparam($elem, 'label', ''),
01284 $this->_getparam($elem, 'checked', false),
01285 $attribs);
01286 break;
01287 case 'radio':
01288 $out .= $this->radio($name,
01289 $this->_getparam($elem, 'value', ''),
01290 $this->_getparam($elem, 'options', array()),
01291 $attribs);
01292 break;
01293 case 'select':
01294 $out .= $this->select($name,
01295 $this->_getparam($elem, 'value', ''),
01296 $this->_getparam($elem, 'options', array()),
01297 $this->_getparam($elem, 'size', ''),
01298 $this->_getparam($elem, 'multiple', false),
01299 $attribs);
01300 break;
01301 case 'multiselect':
01302 $out .= $this->multiselect($name,
01303 $this->_getparam($elem, 'value', ''),
01304 $this->_getparam($elem, 'options', array()),
01305 $this->_getparam($elem, 'show_selects', false),
01306 $this->_getparam($elem, 'multiple', true),
01307 $attribs);
01308 break;
01309 }
01310 if($elem['extra']) {
01311 $out .= " {$elem['extra']}";
01312 }
01313 return $out;
01314 }
01315
01323 function dom_id($name)
01324 {
01325
01326
01327 $id = str_replace(array('[',']',' '), array('','','-'), $name);
01328 if($this->form_name) $id = $this->form_name."_$id";
01329 return $id;
01330
01331 $id = str_replace(array('_','[',']',' '), array('-','','','-'), $name);
01332 if($this->form_name) $id = $this->form_name."-$id";
01333 return $id;
01334 }
01335
01336 function _getparam($params, $name, $default)
01337 {
01338 if(isset($params[$name])) {
01339 return $params[$name];
01340 }
01341 return $default;
01342 }
01343
01344 function _escape($var)
01345 {
01346 $ret = array();
01347 foreach(func_get_args() as $var) {
01348 $ret[] = htmlspecialchars($var);
01349 }
01350 return $ret;
01351 }
01352
01353 function _error($name, &$attribs)
01354 {
01355 $err = '';
01356 if($attribs['no_error']) {
01357 unset($attribs['no_error']);
01358 return $err;
01359 }
01360 if(isset($this->errors[$name])) {
01361 $err = '<br /><p class="error">'.$this->errors[$name].'</p>';
01362 $attribs['class'] .= (empty($attribs['class']) ? 'error' : ' error');
01363 }
01364 return $err;
01365 }
01366 }
01367
01368 ?>