(mixed) custom id attribute value
* if numeric value is passed it'll be just appended to the name e.g. {filed-name}-{value}
* if false is passed id will be not created
* if empty string is passed (or no 'id' option is found)
* in all other cases the value will be used as field id
* default: empty string
*
* - class => (string) field class(es)
* Example: 'tbox select class1 class2 class3'
* NOTE: this will override core classes, so you have to explicit include them!
* default: empty string
*
* - size => (int) size attribute value (used when needed)
* default: 40
*
* - title (string) title attribute
* default: empty string (omitted)
*
* - readonly => (bool) readonly attribute
* default: false
*
* - selected => (bool) selected attribute (used when needed)
* default: false
*
* checked => (bool) checked attribute (used when needed)
* default: false
* - disabled => (bool) disabled attribute
* default: false
*
* - tabindex => (int) tabindex attribute value
* default: inner tabindex counter
*
* - other => (string) additional data
* Example: 'attribute1="value1" attribute2="value2"'
* default: empty string
*/
class e_form
{
protected $_tabindex_counter = 0;
protected $_tabindex_enabled = true;
protected $_cached_attributes = array();
/**
* @var user_class
*/
protected $_uc;
protected $_required_string;
function __construct($enable_tabindex = false)
{
$this->_tabindex_enabled = $enable_tabindex;
$this->_uc = e107::getUserClass();
$this->setRequiredString('* ');
}
/**
* Open a new form
* @param string name
* @param $method - post|get default is post
* @param @target - e_REQUEST_URI by default
* @param $other - unused at the moment.
* @return string
*/
public function open($name, $method=null, $target=null, $options=null)
{
if($target == null)
{
$target = e_REQUEST_URI;
}
if($method == null)
{
$method = "post";
}
$class = "";
$autoComplete = "";
parse_str($options,$options);
if(vartrue($options['class']))
{
$class = "class='".$options['class']."'";
}
else // default
{
$class= "class='form-horizontal'";
}
if(isset($options['autocomplete'])) // leave as isset()
{
$autoComplete = " autocomplete='".($options['autocomplete'] ? 'on' : 'off')."'";
}
if($method == 'get' && strpos($target,'='))
{
list($url,$qry) = explode("?",$target);
$text = "\n
";
$thpath = isset($sc_parameters['nothumb']) || vartrue($hide) ? $default : $default_thumb;
$label = "
";
$label .= $tp->toIcon($default_url);
$label .= "
";
// $label = "
";
}
else // Images
{
$title = (vartrue($sc_parameters['help'])) ? "title='".$sc_parameters['help']."'" : "";
$width = vartrue($sc_parameters['w'], 120);
$height = vartrue($sc_parameters['h'], 100);
$ret = "
";
$att = 'aw='.$width."'&ah=".$height."'";
$thpath = isset($sc_parameters['nothumb']) || vartrue($hide) ? $default : $tp->thumbUrl($default_thumb, $att, true);
$label = "
";
if($cat != 'news' && $cat !='page' && $cat !='')
{
$cat = $cat . "_image";
}
}
$ret .= $this->mediaUrl($cat, $label,$name_id,$sc_parameters);
$ret .= "
\n";
$ret .= "
";
$ret .= "
";
// $ret .= $this->text($name,$default); // to be hidden eventually.
return $ret;
// ----------------
}
/**
* File Picker
* @param string name eg. 'myfield' or 'myfield[]'
* @param mixed default
* @param string label
* @param mixed sc_parameters
*/
function filepicker($name, $default, $label = '', $sc_parameters = '')
{
$tp = e107::getParser();
$name_id = $this->name2id($name);
if(is_string($sc_parameters))
{
if(strpos($sc_parameters, '=') === false) $sc_parameters = 'media='.$sc_parameters;
parse_str($sc_parameters, $sc_parameters);
}
$cat = vartrue($sc_parameters['media']) ? $tp->toDB($sc_parameters['media']) : "_common_file";
$ret = '';
if($sc_parameters['data'] === 'array')
{
// Do not use $this->hidden() method - as it will break 'id' value.
$ret .= "
";
$ret .= "
";
$ret .= "
";
$default = $default['path'];
}
else
{
$ret .= "
";
}
$default_label = ($default) ? $default : "Choose a file";
$label = "
".basename($default_label)." ";
$sc_parameters['mode'] = 'main';
$sc_parameters['action'] = 'dialog';
// $ret .= $this->mediaUrl($cat, $label,$name_id,"mode=dialog&action=list");
$ret .= $this->mediaUrl($cat, $label,$name_id,$sc_parameters);
return $ret;
}
/**
* Date field with popup calendar // NEW in 0.8/2.0
*
* @param string $name the name of the field
* @param integer $datestamp UNIX timestamp - default value of the field
* @param array or str
* @example $frm->datepicker('my_field',time(),'type=date');
* @example $frm->datepicker('my_field',time(),'type=datetime&inline=1');
* @example $frm->datepicker('my_field',time(),'type=date&format=yyyy-mm-dd');
* @example $frm->datepicker('my_field',time(),'type=datetime&format=MM, dd, yyyy hh:ii');
*
* @url http://trentrichardson.com/examples/timepicker/
*/
function datepicker($name, $datestamp = false, $options = null)
{
if(vartrue($options) && is_string($options))
{
parse_str($options,$options);
}
$type = varset($options['type']) ? trim($options['type']) : "date"; // OR 'datetime'
$dateFormat = varset($options['format']) ? trim($options['format']) :e107::getPref('inputdate', '%Y-%m-%d');
$ampm = (preg_match("/%l|%I|%p|%P/",$dateFormat)) ? 'true' : 'false';
$value = null;
if($type == 'datetime' && !varset($options['format']))
{
$dateFormat .= " ".e107::getPref('inputtime', '%H:%M:%S');
}
$dformat = e107::getDate()->toMask($dateFormat);
$id = $this->name2id($name);
$classes = array('date' => 'e-date', 'datetime' => 'e-datetime');
if ($datestamp)
{
$value = is_numeric($datestamp) ? e107::getDate()->convert_date($datestamp, $dateFormat) : $datestamp; //date("d/m/Y H:i:s", $datestamp);
}
$text = "";
// $text .= 'dformat='.$dformat.' defdisp='.$dateFormat;
$class = (isset($classes[$type])) ? $classes[$type] : "tbox e-date";
$size = vartrue($options['size']) ? intval($options['size']) : 40;
$required = vartrue($options['required']) ? "required" : "";
$firstDay = vartrue($options['firstDay']) ? $options['firstDay'] : 0;
$xsize = (vartrue($options['size']) && !is_numeric($options['size'])) ? $options['size'] : 'xlarge';
if(vartrue($options['inline']))
{
$text .= "
";
}
else
{
$text .= "
";
}
// $text .= "ValueFormat: ".$dateFormat." Value: ".$value;
// $text .= " ({$dformat}) type:".$dateFormat." ".$value;
// Load it in the footer.
e107::css('core', 'bootstrap-datetimepicker/css/bootstrap-datetimepicker.min.css', 'jquery');
e107::js('core', 'bootstrap-datetimepicker/js/bootstrap-datetimepicker.min.js', 'jquery', 2);
if(e_LANGUAGE !== 'English')
{
e107::js('footer-inline', e107::getDate()->buildDateLocale());
}
e107::js('footer-inline', '
$("input.e-date").each(function() {
$(this).datetimepicker({
minView: "month",
maxView: "decade",
autoclose: true,
format: $(this).attr("data-date-format"),
weekStart: $(this).attr("data-date-firstday"),
language: $(this).attr("data-date-language")
});
});
$("input.e-datetime").each(function() {
$(this).datetimepicker({
autoclose: true,
format: $(this).attr("data-date-format"),
weekStart: $(this).attr("data-date-firstday"),
showMeridian: $(this).attr("data-date-ampm"),
language: $(this).attr("data-date-language")
});
});
');
return $text;
}
/**
* User auto-complete search
*
* @param string $name_fld field name for user name
* @param string $id_fld field name for user id
* @param string $default_name default user name value
* @param integer $default_id default user id
* @param array|string $options [optional] 'readonly' (make field read only), 'name' (db field name, default user_name)
* @return string HTML text for display
*/
function userpicker($name_fld, $id_fld, $default_name, $default_id, $options = array())
{
if(!is_array($options))
{
parse_str($options, $options);
}
$default_name = vartrue($default_name, '');
$default_id = vartrue($default_id, '');
$default_options = array();
if (!empty($default_name))
{
$default_options = array(
array(
'value' => $default_id,
'label' => $default_name,
),
);
}
$defaults['selectize'] = array(
'loadPath' => e_BASE . 'user.php',
'create' => false,
'maxItems' => 1,
'mode' => 'multi',
'options' => $default_options,
);
$options = array_replace_recursive($defaults, $options);
$ret = $this->text($name_fld, $default_id, 20, $options);
return $ret;
}
/**
* A Rating element
* @var $text
*/
function rate($table,$id,$options=null)
{
$table = preg_replace('/\W/', '', $table);
$id = intval($id);
return e107::getRate()->render($table, $id, $options);
}
function like($table,$id,$options=null)
{
$table = preg_replace('/\W/', '', $table);
$id = intval($id);
return e107::getRate()->renderLike($table,$id,$options);
}
function file($name, $options = array())
{
$options = $this->format_options('file', $name, $options);
//never allow id in format name-value for text fields
return "
get_attributes($options, $name)." />";
}
function upload($name, $options = array())
{
return 'Ready to use upload form fields, optional - file list view';
}
function password($name, $value = '', $maxlength = 50, $options = array())
{
if(is_string($options)) parse_str($options, $options);
$addon = "";
$gen = "";
if(vartrue($options['generate']))
{
$gen = '
Generate ';
if(empty($options['nomask']))
{
$gen .= '
Show ';
}
}
if(vartrue($options['strength']))
{
$addon .= "
";
}
$options['pattern'] = vartrue($options['pattern'],'[\S]{4,}');
$options['required'] = varset($options['required'], 1);
$options['class'] = vartrue($options['class'],'e-password');
e107::js('core', 'password/jquery.pwdMeter.js', 'jquery', 2);
e107::js('footer-inline', '
$(".e-password").pwdMeter({
minLength: 6,
displayGeneratePassword: true,
generatePassText: "Generate",
randomPassLength: 12
});
');
if(deftrue('BOOTSTRAP') == 3)
{
$options['class'] .= ' form-control';
}
if(vartrue($options['size']) && !is_numeric($options['size']))
{
$options['class'] .= " input-".$options['size'];
unset($options['size']); // don't include in html 'size='.
}
$type = empty($options['nomask']) ? 'password' : 'text';
$options = $this->format_options('text', $name, $options);
//never allow id in format name-value for text fields
$text = "
get_attributes($options, $name)." />";
if(empty($gen) && empty($addon))
{
return $text;
}
else
{
return "
".$text.$gen." ".vartrue($addon);
}
}
/**
* Render Pagination using 'nextprev' shortcode.
* @param string $url eg. e_REQUEST_SELF.'?from=[FROM]'
* @param int $total total records
* @param int $from value to replace [FROM] with in the URL
* @param int $perPage number of items per page
* @param array $options template, type, glyphs
* @return string
*/
public function pagination($url='', $total=0, $from=0, $perPage=10, $options=array())
{
if(!is_numeric($total))
{
return '';
}
require_once(e_CORE."shortcodes/single/nextprev.php");
$nextprev = array(
'tmpl_prefix' => varset($options['template'],'default'),
'total' => intval($total),
'amount' => intval($perPage),
'current' => intval($from),
'url' => urldecode($url),
'type' => varset($options['type'],'record'), // page|record
'glyphs' => vartrue($options['glyphs'],false) // 1|0
);
return nextprev_shortcode($nextprev);
}
/**
* Render a bootStrap ProgressBar.
* @param string $name
* @param number $value
* @param array $options
* @example Use
*/
public function progressBar($name,$value,$options=array())
{
if(!deftrue('BOOTSTRAP')) // Legacy ProgressBar.
{
$barl = (file_exists(THEME.'images/barl.png') ? THEME_ABS.'images/barl.png' : e_PLUGIN_ABS.'poll/images/barl.png');
$barr = (file_exists(THEME.'images/barr.png') ? THEME_ABS.'images/barr.png' : e_PLUGIN_ABS.'poll/images/barr.png');
$bar = (file_exists(THEME.'images/bar.png') ? THEME_ABS.'images/bar.png' : e_PLUGIN_ABS.'poll/images/bar.png');
return "
";
}
$class = vartrue($options['class'],'');
$target = $this->name2id($name);
$striped = (vartrue($options['btn-label'])) ? ' progress-striped active' : '';
$text = "
";
$loading = vartrue($options['loading'],'Please wait...');
$buttonId = $target.'-start';
if(vartrue($options['btn-label']))
{
$interval = vartrue($options['interval'],1000);
$text .= '
'.$options['btn-label'].' ';
$text .= '
'.LAN_CANCEL.' ';
}
return $text;
}
/**
* Textarea Element
* @param $name
* @param $value
* @param $rows
* @param $cols
* @param $options
* @param $count
* @return string
*/
function textarea($name, $value, $rows = 10, $cols = 80, $options = array(), $counter = false)
{
if(is_string($options)) parse_str($options, $options);
// auto-height support
if(vartrue($options['size']) && !is_numeric($options['size']))
{
$options['class'] .= " form-control input-".$options['size'];
unset($options['size']); // don't include in html 'size='.
}
elseif(!vartrue($options['noresize']))
{
$options['class'] = (isset($options['class']) && $options['class']) ? $options['class'].' e-autoheight' : 'tbox col-md-7 span7 e-autoheight';
}
$options = $this->format_options('textarea', $name, $options);
// print_a($options);
//never allow id in format name-value for text fields
return "
".(false !== $counter ? $this->hidden('__'.$name.'autoheight_opt', $counter) : '');
}
/**
* Bbcode Area. Name, value, template, media-Cat, size, options array eg. counter
* IMPORTANT: $$mediaCat is also used is the media-manager category identifier
* @param $name
* @param $value
* @param $template
* @param $mediaCat _common
* @param $size : small | medium | large
* @param $options array();
*/
function bbarea($name, $value, $template = '', $mediaCat='_common', $size = 'large', $options = array())
{
if(is_string($options)) parse_str($options, $options);
//size - large|medium|small
//width should be explicit set by current admin theme
// $size = 'input-large';
switch($size)
{
case 'tiny':
$rows = '3';
// $height = "style='height:250px'"; // inline required for wysiwyg
break;
case 'small':
$rows = '7';
$height = "style='height:230px'"; // inline required for wysiwyg
$size = "input-block-level";
break;
case 'medium':
$rows = '10';
$height = "style='height:375px'"; // inline required for wysiwyg
$size = "input-block-level";
break;
case 'large':
default:
$rows = '15';
$size = 'large input-block-level';
// $height = "style='height:500px;width:1025px'"; // inline required for wysiwyg
break;
}
// auto-height support
$options['class'] = 'tbox bbarea '.($size ? ' '.$size : '').' e-wysiwyg e-autoheight form-control';
$bbbar = '';
$help_tagid = $this->name2id($name)."--preview";
if(e107::wysiwyg(true) === false) // bbarea loaded, so activate wysiwyg (if enabled in preferences)
{
$options['other'] = "onselect='storeCaret(this);' onclick='storeCaret(this);' onkeyup='storeCaret(this);' {$height}";
}
else
{
$options['other'] = " ".$height;
}
$counter = vartrue($options['counter'],false);
$ret = "
\n";
$ret .= e107::getBB()->renderButtons($template,$help_tagid);
$ret .= $this->textarea($name, $value, $rows, 70, $options, $counter); // higher thank 70 will break some layouts.
$ret .= "
\n";
$_SESSION['media_category'] = $mediaCat; // used by TinyMce.
return $ret;
// Quick fix - hide TinyMCE links if not installed, dups are handled by JS handler
/*
e107::getJs()->footerInline("
if(typeof tinyMCE === 'undefined')
{
\$$('a.e-wysiwyg-switch').invoke('hide');
}
");
*/
}
/**
* Render a checkbox
* @param string $name
* @param mixed $value
* @param boolean $checked
* @param mixed $options query-string or array or string for a label. eg. label=Hello&foo=bar or array('label'=>Hello') or 'Hello'
* @return string
*/
function checkbox($name, $value, $checked = false, $options = array())
{
if(!is_array($options))
{
if(strpos($options,"=")!==false)
{
parse_str($options, $options);
}
elseif(is_array($options))
{
// do nothing.
}
else // Assume it's a label.
{
$options = array('label'=>$options);
}
}
$labelClass = (!empty($options['inline'])) ? 'checkbox-inline' : 'checkbox';
$labelTitle = '';
$options = $this->format_options('checkbox', $name, $options);
$options['checked'] = $checked; //comes as separate argument just for convenience
$text = "";
$active = ($checked === true) ? " active" : ""; // allow for styling if needed.
if(!empty($options['label'])) // add attributes to
{
if(!empty($options['title']))
{
$labelTitle = " title=\"".$options['title']."\"";
unset($options['title']);
}
if(!empty($options['class']))
{
$labelClass .= " ".$options['class'];
unset($options['class']);
}
}
$pre = (vartrue($options['label'])) ? "" : ""; // Bootstrap compatible markup
$post = (vartrue($options['label'])) ? $options['label']." " : "";
unset($options['label']); // not to be used as attribute;
$text .= " get_attributes($options, $name, $value)." />";
return $pre.$text.$post;
}
/**
* Render an array of checkboxes.
* @param string $name
* @param array $option_array
* @param mixed $checked
* @param array $options [optional useKeyValues]
*/
function checkboxes($name, $option_array, $checked, $options=array())
{
$name = (strpos($name, '[') === false) ? $name.'[]' : $name;
if(!is_array($checked)) $checked = explode(",",$checked);
$text = "";
$cname = $name;
foreach($option_array as $k=>$label)
{
if(!empty($options['useKeyValues'])) // ie. auto-generated
{
$key = $k;
$c = in_array($k, $checked) ? true : false;
}
else
{
$key = 1;
$cname = str_replace('[]','['.$k.']',$name);
$c = vartrue($checked[$k]);
}
$text .= $this->checkbox($cname, $key, $c, $label);
}
if(!empty($text))
{
return "".$text."
";
}
return $text;
}
function checkbox_label($label_title, $name, $value, $checked = false, $options = array())
{
return $this->checkbox($name, $value, $checked, $options).$this->label($label_title, $name, $value);
}
function checkbox_switch($name, $value, $checked = false, $label = '')
{
return $this->checkbox($name, $value, $checked).$this->label($label ? $label : LAN_ENABLED, $name, $value);
}
function checkbox_toggle($name, $selector = 'multitoggle', $id = false, $label='') //TODO Fixme - labels will break this. Don't use checkbox, use html.
{
$selector = 'jstarget:'.$selector;
if($id) $id = $this->name2id($id);
return $this->checkbox($name, $selector, false, array('id' => $id,'class' => 'checkbox checkbox-inline toggle-all','label'=>$label));
}
function uc_checkbox($name, $current_value, $uc_options, $field_options = array())
{
if(!is_array($field_options)) parse_str($field_options, $field_options);
return '
'.$this->_uc->vetted_tree($name, array($this, '_uc_checkbox_cb'), $current_value, $uc_options, $field_options).'
';
}
/**
* Callback function used with $this->uc_checkbox
*
* @see user_class->select() for parameters
*/
function _uc_checkbox_cb($treename, $classnum, $current_value, $nest_level, $field_options)
{
if($classnum == e_UC_BLANK)
return '';
if (!is_array($current_value))
{
$tmp = explode(',', $current_value);
}
$classIndex = abs($classnum); // Handle negative class values
$classSign = (substr($classnum, 0, 1) == '-') ? '-' : '';
$class = $style = '';
if($nest_level == 0)
{
$class = " strong";
}
else
{
$style = " style='text-indent:" . (1.2 * $nest_level) . "em'";
}
$descr = varset($field_options['description']) ? ' ('.$this->_uc->uc_get_classdescription($classnum).') ' : '';
return "".$this->checkbox($treename.'[]', $classnum, in_array($classnum, $tmp), $field_options).$this->label($this->_uc->uc_get_classname($classIndex).$descr, $treename.'[]', $classnum)."
\n";
}
function uc_label($classnum)
{
return $this->_uc->uc_get_classname($classnum);
}
/**
* A Radio Button Form Element
* @param $name
* @param @value array pair-values|string - auto-detected.
* @param $checked boolean
* @param $options
*/
function radio($name, $value, $checked = false, $options = null)
{
if(!is_array($options)) parse_str($options, $options);
if(is_array($value))
{
return $this->radio_multi($name, $value, $checked, $options);
}
$labelFound = vartrue($options['label']);
unset($options['label']); // label attribute not valid in html5
$options = $this->format_options('radio', $name, $options);
$options['checked'] = $checked; //comes as separate argument just for convenience
// $options['class'] = 'inline';
$text = "";
// return print_a($options,true);
if($labelFound) // Bootstrap compatible markup
{
$defaultClass = (deftrue('BOOTSTRAP') === 3) ? 'radio-inline' : 'radio inline';
$dis = (!empty($options['disabled'])) ? " disabled" : "";
$text .= "";
}
$text .= " get_attributes($options, $name, $value)." />";
if(vartrue($options['help']))
{
$text .= "".$options['help']."
";
}
if($labelFound)
{
$text .= "".$labelFound." ";
}
return $text;
}
/**
* Boolean Radio Buttons.
* @param name string
* @param check_enabled boolean
* @param label_enabled default is LAN_ENABLED
* @param label_disabled default is LAN_DISABLED
* @param options array - inverse=1 (invert values) or reverse=1 (switch display order)
*/
function radio_switch($name, $checked_enabled = false, $label_enabled = '', $label_disabled = '',$options=array())
{
if(!is_array($options)) parse_str($options, $options);
$options_on = varset($options['enabled'],array());
$options_off = varset($options['disabled'],array());
if(vartrue($options['class']) == 'e-expandit' || vartrue($options['expandit'])) // See admin->prefs 'Single Login' for an example.
{
$options_on = array_merge($options, array('class' => 'e-expandit-on'));
$options_off = array_merge($options, array('class' => 'e-expandit-off'));
}
$options_on['label'] = $label_enabled ? defset($label_enabled,$label_enabled) : LAN_ENABLED;
$options_off['label'] = $label_disabled ? defset($label_disabled,$label_disabled) : LAN_DISABLED;
if(!empty($options['inverse'])) // Same as 'writeParms'=>'reverse=1&enabled=LAN_DISABLED&disabled=LAN_ENABLED'
{
$text = $this->radio($name, 0, !$checked_enabled, $options_on)." ".$this->radio($name, 1, $checked_enabled, $options_off);
}
elseif(!empty($options['reverse'])) // reverse display order.
{
$text = $this->radio($name, 0, !$checked_enabled, $options_off)." ".$this->radio($name, 1, $checked_enabled, $options_on);
}
else
{
$text = $this->radio($name, 1, $checked_enabled, $options_on)." ".$this->radio($name, 0, !$checked_enabled, $options_off);
}
return $text;
}
/**
* XXX INTERNAL ONLY - Use radio() instead. array will automatically trigger this internal method.
* @param string $name
* @param array $elements = arrays value => label
* @param string/integer $checked = current value
* @param boolean $multi_line
* @param mixed $help array of field help items or string of field-help (to show on all)
*/
private function radio_multi($name, $elements, $checked, $options=array(), $help = null)
{
/* // Bootstrap Test.
return'
Option one is this and that—be sure to include why its great
Option one is this and that—be sure to include why its great
Option two can be something else and selecting it will deselect option one
';
*/
$text = array();
if(is_string($elements)) parse_str($elements, $elements);
if(!is_array($options)) parse_str($options, $options);
$help = '';
if(vartrue($options['help']))
{
$help = "".$options['help']."
";
unset($options['help']);
}
foreach ($elements as $value => $label)
{
$label = defset($label, $label);
$helpLabel = (is_array($help)) ? vartrue($help[$value]) : $help;
// Bootstrap Style Code - for use later.
$options['label'] = $label;
$options['help'] = $helpLabel;
$text[] = $this->radio($name, $value, (string) $checked === (string) $value, $options);
// $text[] = $this->radio($name, $value, (string) $checked === (string) $value)."".$this->label($label, $name, $value).(isset($helpLabel) ? "".$helpLabel."
" : '');
}
if($multi_line === false)
{
// return implode(" ", $text);
}
// support of UI owned 'newline' parameter
if(!varset($options['sep']) && vartrue($options['newline'])) $options['sep'] = ' '; // TODO div class=separator?
$separator = varset($options['sep']," ");
// return print_a($text,true);
return implode($separator, $text).$help;
// return implode("\n", $text);
//XXX Limiting markup.
// return "".implode("
", $text)."
";
}
/**
* Just for BC - use the $options['label'] instead.
*/
function label($text, $name = '', $value = '')
{
// $backtrack = debug_backtrace(DEBUG_BACKTRACE_IGNORE_ARGS,2);
// e107::getMessage()->addDebug("Deprecated \$frm->label() used in: ".print_a($backtrack,true));
$for_id = $this->_format_id('', $name, $value, 'for');
return "{$text} ";
}
function help($text)
{
return !empty($text) ? ''.$text.'
' : '';
}
function select_open($name, $options = array())
{
if(!is_array($options)) parse_str($options, $options);
if(vartrue($options['size']) && !is_numeric($options['size']))
{
$options['class'] .= " input-".$options['size'];
unset($options['size']); // don't include in html 'size='.
}
$options = $this->format_options('select', $name, $options);
return "get_attributes($options, $name).">";
}
/**
* @DEPRECATED - use select() instead.
*/
function selectbox($name, $option_array, $selected = false, $options = array(), $defaultBlank= false)
{
return $this->select($name, $option_array, $selected, $options, $defaultBlank);
}
/**
*
* @param string $name
* @param array $option_array
* @param boolean $selected [optional]
* @param string|array $options [optional]
* @param boolean|string $defaultBlank [optional] set to TRUE if the first entry should be blank, or to a string to use it for the blank description.
* @return string HTML text for display
*/
function select($name, $option_array, $selected = false, $options = array(), $defaultBlank= false)
{
if(!is_array($options)) parse_str($options, $options);
if($option_array === 'yesno')
{
$option_array = array(1 => LAN_YES, 0 => LAN_NO);
}
if(vartrue($options['multiple']))
{
$name = (strpos($name, '[') === false) ? $name.'[]' : $name;
if(!is_array($selected)) $selected = explode(",",$selected);
}
$text = $this->select_open($name, $options)."\n";
if(isset($options['default']))
{
if($options['default'] === 'blank')
{
$options['default'] = ' ';
}
$text .= $this->option($options['default'], varset($options['defaultValue'],''));
}
elseif($defaultBlank)
{
$diz = is_string($defaultBlank) ? $defaultBlank : ' ';
$text .= $this->option($diz, '');
}
if(varset($options['useValues'])) // use values as keys.
{
$new = array();
foreach($option_array as $v)
{
$new[$v] = $v;
}
$option_array = $new;
}
$text .= $this->option_multi($option_array, $selected)."\n".$this->select_close();
return $text;
}
/**
* Universal Userclass selector - checkboxes, dropdown, everything.
* @param $name - form element name
* @param $curval - current userclass value(s) as array or comma separated.
* @param $type - 'checkbox', 'dropdown',
* @param options - query string or array. 'options=admin,mainadmin,classes&vetted=1&exclusions=0' etc.
* @return the userclass form element
*/
function userclass($name, $curval=255, $type=null, $options=null)
{
if(!empty($options))
{
if(is_array($options))
{
$opt = $options;
}
else
{
parse_str($options,$opt);
}
}
else
{
$opt = array();
}
$optlist = vartrue($opt['options'],null);
switch ($type)
{
case 'checkbox':
return e107::getUserClass()->uc_checkboxes($name, $curval, $optlist, null,false);
break;
case 'dropdown':
default:
return e107::getUserClass()->uc_dropdown($name, $curval, $optlist, $opt);
break;
}
}
/**
* Renders a generic search box. If $filter has values, a filter box will be included with the options provided.
*
*/
function search($name, $searchVal, $submitName, $filterName='', $filterArray=false, $filterVal=false)
{
$tp = e107::getParser();
$text = '
'.$this->text($name, $searchVal,20,'class=search-query&placeholder=Search…').'
'.$tp->toGlyph('fa-search',' ').'
';
if(is_array($filter))
{
$text .= $this->selectbox($$filterName, $filterArray, $filterVal);
}
// $text .= $this->admin_button($submitName,LAN_SEARCH,'search');
return $text;
/*
$text .=
Display All
Clear Filter
General
Misc
Test 3
Display All
Filter
*/
}
function uc_select($name, $current_value, $uc_options, $select_options = array(), $opt_options = array())
{
if(!empty($select_options['multiple']) && substr($name,-1) != ']')
{
$name .= '[]';
}
if(empty($current_value) && !empty($uc_options)) // make the first in the opt list the default value.
{
$tmp = explode(",", $uc_options);
$current_value = e107::getUserClass()->getClassFromKey($tmp[0]);
}
if(!empty($current_value) && !is_numeric($current_value)) // convert name to id.
{
$current_value = $this->_uc->getID($current_value);
}
return $this->select_open($name, $select_options)."\n".$this->_uc->vetted_tree($name, array($this, '_uc_select_cb'), $current_value, $uc_options, $opt_options)."\n".$this->select_close();
}
// Callback for vetted_tree - Creates the option list for a selection box
function _uc_select_cb($treename, $classnum, $current_value, $nest_level)
{
$classIndex = abs($classnum); // Handle negative class values
$classSign = (substr($classnum, 0, 1) == '-') ? '-' : '';
if($classnum == e_UC_BLANK)
return $this->option(' ', '');
$tmp = explode(',', $current_value);
if($nest_level == 0)
{
$prefix = '';
$style = "font-weight:bold; font-style: italic;";
}
elseif($nest_level == 1)
{
$prefix = ' ';
$style = "font-weight:bold";
}
else
{
$prefix = ' '.str_repeat('--', $nest_level - 1).'>';
$style = '';
}
return $this->option($prefix.$this->_uc->uc_get_classname($classnum), $classSign.$classIndex, ($current_value !== '' && in_array($classnum, $tmp)), array("style"=>"{$style}"))."\n";
}
function optgroup_open($label, $disabled = false, $options = null)
{
return "";
}
/**
* tag generation.
* @param $option_title
* @param $value
* @param $selected
* @param $options (eg. disabled=1)
*/
function option($option_title, $value, $selected = false, $options = '')
{
if(is_string($options)) parse_str($options, $options);
if(false === $value) $value = '';
$options = $this->format_options('option', '', $options);
$options['selected'] = $selected; //comes as separate argument just for convenience
return " get_attributes($options).">".defset($option_title, $option_title)." ";
}
/**
* Use selectbox() instead.
*/
function option_multi($option_array, $selected = false, $options = array())
{
if(is_string($option_array)) parse_str($option_array, $option_array);
$text = '';
foreach ($option_array as $value => $label)
{
if(is_array($label))
{
$text .= $this->optgroup_open($value);
foreach($label as $val => $lab)
{
if(is_array($lab))
{
$text .= $this->optgroup_open($val,null,array('class'=>'level-2')); // Not valid HTML5 - but appears to work in modern browsers.
foreach($lab as $k=>$v)
{
$text .= $this->option($v, $k, (is_array($selected) ? in_array($k, $selected) : $selected == $k), $options)."\n";
}
$text .= $this->optgroup_close($val);
}
else
{
$text .= $this->option($lab, $val, (is_array($selected) ? in_array($val, $selected) : $selected == $val), $options)."\n";
}
}
$text .= $this->optgroup_close();
}
else
{
$text .= $this->option($label, $value, (is_array($selected) ? in_array($value, $selected) : $selected == $value), $options)."\n";
}
}
return $text;
}
function optgroup_close()
{
return " ";
}
function select_close()
{
return " ";
}
function hidden($name, $value, $options = array())
{
$options = $this->format_options('hidden', $name, $options);
return " get_attributes($options, $name, $value)." />";
}
/**
* Generate hidden security field
* @return string
*/
function token()
{
return " ";
}
function submit($name, $value, $options = array())
{
$options = $this->format_options('submit', $name, $options);
return " get_attributes($options, $name, $value)." />";
}
function submit_image($name, $value, $image, $title='', $options = array())
{
$tp = e107::getParser();
$options = $this->format_options('submit_image', $name, $options);
switch ($image)
{
case 'edit':
$icon = "e-edit-32";
$options['class'] = $options['class'] == 'action' ? 'btn btn-default action edit' : $options['class'];
break;
case 'delete':
$icon = "e-delete-32";
$options['class'] = $options['class'] == 'action' ? 'btn btn-default action delete' : $options['class'];
$options['other'] = 'data-confirm="'.LAN_JSCONFIRM.'"';
break;
case 'execute':
$icon = "e-execute-32";
$options['class'] = $options['class'] == 'action' ? 'btn btn-default action execute' : $options['class'];
break;
case 'view':
$icon = "e-view-32";
$options['class'] = $options['class'] == 'action' ? 'btn btn-default action view' : $options['class'];
break;
}
$options['title'] = $title;//shorthand
return "get_attributes($options, $name, $value)." >".$tp->toIcon($icon)." ";
}
/**
* Alias of admin_button, adds the etrigger_ prefix required for UI triggers
* @see e_form::admin_button()
*/
function admin_trigger($name, $value, $action = 'submit', $label = '', $options = array())
{
return $this->admin_button('etrigger_'.$name, $value, $action, $label, $options);
}
/**
* Generic Button Element.
* @param string $name
* @param string $value
* @param string $action [optional] default is submit - use 'dropdown' for a bootstrap dropdown button.
* @param string $label [optional]
* @param string|array $options [optional]
* @return string
*/
public function button($name, $value, $action = 'submit', $label = '', $options = array())
{
if(deftrue('BOOTSTRAP') && $action == 'dropdown' && is_array($value))
{
// $options = $this->format_options('admin_button', $name, $options);
$options['class'] = vartrue($options['class']);
$align = vartrue($options['align'],'left');
$text = '';
return $text;
}
return $this->admin_button($name, $value, $action, $label, $options);
}
/**
* Render a Breadcrumb in Bootstrap format.
* @param $array
*/
function breadcrumb($array)
{
if(!is_array($array)){ return; }
$opt = array();
$homeIcon = e107::getParser()->toGlyph('icon-home.glyph',false);
$opt[] = "".$homeIcon." "; // Add Site-Pref to disable?
$text = '";
// return print_a($opt,true);
return $text;
}
/**
* Admin Button - for front-end, use button();
* @param string $name
* @param string $value
* @param string $action [optional] default is submit
* @param string $label [optional]
* @param string|array $options [optional]
* @return string
*/
function admin_button($name, $value, $action = 'submit', $label = '', $options = array())
{
$btype = 'submit';
if(strpos($action, 'action') === 0) $btype = 'button';
$options = $this->format_options('admin_button', $name, $options);
$options['class'] = vartrue($options['class']);
$options['class'] .= ' btn '.$action.' ';//shorthand
if(empty($label)) $label = $value;
switch ($action)
{
case 'update':
case 'create':
case 'import':
case 'submit':
case 'success':
$options['class'] .= 'btn-success';
break;
case 'checkall':
$options['class'] .= 'btn-default btn-mini btn-xs';
break;
case 'cancel':
$options['class'] .= 'btn-default';
// use this for neutral colors.
break;
case 'delete':
case 'danger':
$options['class'] .= 'btn-danger';
$options['other'] = 'data-confirm="'.LAN_JSCONFIRM.'"';
break;
case 'execute':
$options['class'] .= 'btn-success';
break;
case 'other':
case 'login':
case 'primary':
$options['class'] .= 'btn-primary';
break;
case 'warning':
case 'confirm':
$options['class'] .= 'btn-warning';
break;
case 'batch':
case 'batch e-hide-if-js': // FIXME hide-js shouldn't be here.
$options['class'] .= 'btn-primary';
break;
case 'filter':
case 'filter e-hide-if-js': // FIXME hide-js shouldn't be here.
$options['class'] .= 'btn-primary';
break;
case 'default':
default:
$options['class'] .= 'btn-default';
break;
}
return "
get_attributes($options, $name).">{$label}
";
}
function getNext()
{
if(!$this->_tabindex_enabled) return 0;
$this->_tabindex_counter += 1;
return $this->_tabindex_counter;
}
function getCurrent()
{
if(!$this->_tabindex_enabled) return 0;
return $this->_tabindex_counter;
}
function resetTabindex($reset = 0)
{
$this->_tabindex_counter = $reset;
}
function get_attributes($options, $name = '', $value = '')
{
$ret = '';
//
foreach ($options as $option => $optval)
{
$optval = trim($optval);
switch ($option)
{
case 'id':
$ret .= $this->_format_id($optval, $name, $value);
break;
case 'class':
if(!empty($optval)) $ret .= " class='{$optval}'";
break;
case 'size':
if($optval) $ret .= " size='{$optval}'";
break;
case 'title':
if($optval) $ret .= " title='{$optval}'";
break;
case 'label':
if($optval) $ret .= " label='{$optval}'";
break;
case 'tabindex':
if($optval) $ret .= " tabindex='{$optval}'";
elseif(false === $optval || !$this->_tabindex_enabled) break;
else
{
$this->_tabindex_counter += 1;
$ret .= " tabindex='".$this->_tabindex_counter."'";
}
break;
case 'readonly':
if($optval) $ret .= " readonly='readonly'";
break;
case 'multiple':
if($optval) $ret .= " multiple='multiple'";
break;
case 'selected':
if($optval) $ret .= " selected='selected'";
break;
case 'maxlength':
if($optval) $ret .= " maxlength='{$optval}'";
break;
case 'checked':
if($optval) $ret .= " checked='checked'";
break;
case 'disabled':
if($optval) $ret .= " disabled='disabled'";
break;
case 'required':
if($optval) $ret .= " required='required'";
break;
case 'autofocus':
if($optval) $ret .= " autofocus='autofocus'";
break;
case 'placeholder':
if($optval) $ret .= " placeholder='{$optval}'";
break;
case 'wrap':
if($optval) $ret .= " wrap='{$optval}'";
break;
case 'autocomplete':
if($optval) $ret .= " autocomplete='{$optval}'";
break;
case 'pattern':
if($optval) $ret .= " pattern='{$optval}'";
break;
case 'other':
if($optval) $ret .= " $optval";
break;
}
if(substr($option,0,5) =='data-')
{
$ret .= " ".$option."='{$optval}'";
}
}
return $ret;
}
/**
* Auto-build field attribute id
*
* @param string $id_value value for attribute id passed with the option array
* @param string $name the name attribute passed to that field
* @param unknown_type $value the value attribute passed to that field
* @return string formatted id attribute
*/
function _format_id($id_value, $name, $value = '', $return_attribute = 'id')
{
if($id_value === false) return '';
//format data first
$name = trim($this->name2id($name), '-');
$value = trim(preg_replace('#[^a-zA-Z0-9\-]#','-', $value), '-');
//$value = trim(preg_replace('#[^a-z0-9\-]#/i','-', $value), '-'); // This should work - but didn't for me!
$value = trim(str_replace("/","-",$value), '-'); // Why?
if(!$id_value && is_numeric($value)) $id_value = $value;
// clean - do it better, this could lead to dups
$id_value = trim($id_value, '-');
if(empty($id_value) ) return " {$return_attribute}='{$name}".($value ? "-{$value}" : '')."'";// also useful when name is e.g. name='my_name[some_id]'
elseif(is_numeric($id_value) && $name) return " {$return_attribute}='{$name}-{$id_value}'";// also useful when name is e.g. name='my_name[]'
else return " {$return_attribute}='{$id_value}'";
}
function name2id($name)
{
$name = strtolower($name);
return rtrim(str_replace(array('[]', '[', ']', '_', '/', ' ','.', '(', ')'), array('-', '-', '', '-', '-', '-', '-','',''), $name), '-');
}
/**
* Format options based on the field type,
* merge with default
*
* @param string $type
* @param string $name form name attribute value
* @param array|string $user_options
* @return array merged options
*/
function format_options($type, $name, $user_options=null)
{
if(is_string($user_options))
{
parse_str($user_options, $user_options);
}
$def_options = $this->_default_options($type);
if(is_array($user_options))
{
$user_options['name'] = $name; //required for some of the automated tasks
foreach (array_keys($user_options) as $key)
{
if(!isset($def_options[$key]) && substr($key,0,5)!='data-') unset($user_options[$key]); // data-xxxx exempt //remove it?
}
}
else
{
$user_options = array('name' => $name); //required for some of the automated tasks
}
return array_merge($def_options, $user_options);
}
/**
* Get default options array based on the field type
*
* @param string $type
* @return array default options
*/
function _default_options($type)
{
if(isset($this->_cached_attributes[$type])) return $this->_cached_attributes[$type];
$def_options = array(
'id' => '',
'class' => '',
'title' => '',
'size' => '',
'readonly' => false,
'selected' => false,
'checked' => false,
'disabled' => false,
'required' => false,
'autofocus' => false,
'tabindex' => 0,
'label' => '',
'placeholder' => '',
'pattern' => '',
'other' => '',
'autocomplete' => '',
'maxlength' => '',
'wrap' => '',
'maxlength' => ''
// 'multiple' => false, - see case 'select'
);
$form_control = (deftrue('BOOTSTRAP') === 3) ? ' form-control' : '';
switch ($type) {
case 'hidden':
$def_options = array('id' => false, 'disabled' => false, 'other' => '');
break;
case 'text':
$def_options['class'] = 'tbox input-text'.$form_control;
unset($def_options['selected'], $def_options['checked']);
break;
case 'file':
$def_options['class'] = 'tbox file';
unset($def_options['selected'], $def_options['checked']);
break;
case 'textarea':
$def_options['class'] = 'tbox textarea'.$form_control;
unset($def_options['selected'], $def_options['checked'], $def_options['size']);
break;
case 'select':
$def_options['class'] = 'tbox select'.$form_control;
$def_options['multiple'] = false;
unset($def_options['checked']);
break;
case 'option':
$def_options = array('class' => '', 'selected' => false, 'other' => '', 'disabled' => false, 'label' => '');
break;
case 'radio':
//$def_options['class'] = ' ';
unset($def_options['size'], $def_options['selected']);
break;
case 'checkbox':
unset($def_options['size'], $def_options['selected']);
break;
case 'submit':
$def_options['class'] = 'button btn btn-primary';
unset($def_options['checked'], $def_options['selected'], $def_options['readonly']);
break;
case 'submit_image':
$def_options['class'] = 'action';
unset($def_options['checked'], $def_options['selected'], $def_options['readonly']);
break;
case 'admin_button':
unset($def_options['checked'], $def_options['selected'], $def_options['readonly']);
break;
}
$this->_cached_attributes[$type] = $def_options;
return $def_options;
}
function columnSelector($columnsArray, $columnsDefault = '', $id = 'column_options')
{
$columnsArray = array_filter($columnsArray);
// navbar-header nav-header
// navbar-header nav-header
$text = '";
// $text .= " ";
$text .= "";
/*
$text = '