. */ /** * Collection of HTML form widgets. * * @package Form */ /** * Generates a radio button toggle. * * @param array $values The values as an array * @param string $field The field name * @param string $checked The checked button, takes a value from $vals * @param int $tabindex The HTML tabindex * @param string $id The HTML id * @return string A HTML radio button set * @example * echo radioSet(array( * 'value1' => 'Label1', * 'value2' => 'Label2', * ), 'myInput', 'value1'); */ function radioSet($values, $field, $checked = '', $tabindex = 0, $id = '') { if ($id) { $id = $id.'-'.$field; } else { $id = $field; } $out = array(); foreach ((array) $values as $value => $label) { $out[] = radio($field, $value, (string) $value === (string) $checked, $id.'-'.$value, $tabindex); $out[] = n.tag($label, 'label', array('for' => $id.'-'.$value)); } return join('', $out); } /** * Generates a Yes/No radio button toggle. * * These buttons are booleans. 'Yes' will have a value of 1 and 'No' is 0. * * @param string $field The field name * @param string $checked The checked button, either '1', '0' * @param int $tabindex The HTML tabindex * @param string $id The HTML id * @return string HTML * @see radioSet() * @example * echo form( * 'Is this an example?'. * yesnoRadio('is_example', 1) * ); */ function yesnoRadio($field, $checked = '', $tabindex = 0, $id = '') { $vals = array( '0' => gTxt('no'), '1' => gTxt('yes'), ); return radioSet($vals, $field, $checked, $tabindex, $id); } /** * Generates an On/Off radio button toggle. * * @param string $field The field name * @param string $checked The checked button, either '1', '0' * @param int $tabindex The HTML tabindex * @param string $id The HTML id * @return string HTML * @see radioSet() */ function onoffRadio($field, $checked = '', $tabindex = 0, $id = '') { $vals = array( '0' => gTxt('off'), '1' => gTxt('on'), ); return radioSet($vals, $field, $checked, $tabindex, $id); } /** * Generates a select field. * * @param string $name The field * @param array $array The values as an array array( 'value' => 'label' ) * @param mixed $value The selected option(s). If an array, renders the select multiple * @param bool $blank_first If TRUE, prepends an empty option to the list * @param mixed $onchange If TRUE submits the form when an option is changed. If a string, inserts it to the select tag * @param string $select_id The HTML id * @param bool $check_type Type-agnostic comparison * @param bool $disabled If TRUE renders the select disabled * @return string HTML * @example * echo selectInput('myInput', array( * 'value1' => 'Label1', * 'value2' => 'Label2', * )); */ function selectInput($name = '', $array = array(), $value = '', $blank_first = false, $onchange = '', $select_id = '', $check_type = false, $disabled = false) { $out = array(); $selected = false; $multiple = is_array($value) ? ' multiple="multiple"' : ''; if ($multiple) { $name .= '[]'; } else { $value = (string) $value; } foreach ($array as $avalue => $alabel) { if (!$multiple && $value === (string) $avalue || $multiple && in_array($avalue, $value)) { $sel = ' selected="selected"'; $selected = true; } else { $sel = ''; } $out[] = ''; } if ($blank_first) { array_unshift($out, ''); } $atts = join_atts(array( 'id' => $select_id, 'name' => $name, 'disabled' => (bool) $disabled, ), TEXTPATTERN_STRIP_EMPTY); if ((string) $onchange === '1') { $atts .= ' data-submit-on="change"'; } elseif ($onchange) { $atts .= ' '.trim($onchange); } return n.''.n.join(n, $out).n.''.n .($multiple ? hInput($name, '').n : ''); // TODO: use jQuery UI selectmenu? } /** * Generates a tree structured select field. * * This field takes a NSTREE structure as an associative array. This is mainly * used for categories. * * @param string $select_name The field * @param array $array The values as an array * @param string $value The selected option. Takes a value from $value * @param string $select_id The HTML id * @param int $truncate Truncate labels to certain length. Disabled if set <4. * @return string HTML * @see getTree() */ function treeSelectInput($select_name = '', $array = array(), $value = '', $select_id = '', $truncate = 0) { $out = array(); $doctype = get_pref('doctype'); $selected = false; foreach ($array as $a) { if ($a['name'] == 'root') { continue; } if ((string) $a['name'] === (string) $value) { $sel = ' selected="selected"'; $selected = true; } else { $sel = ''; } $sp = str_repeat(sp.sp, $a['level']); if (($truncate > 3) && (strlen(utf8_decode($a['title'])) > $truncate)) { $htmltitle = ' title="'.txpspecialchars($a['title']).'"'; $a['title'] = preg_replace('/^(.{0,'.($truncate - 3).'}).*$/su', '$1', $a['title']); $hellip = '…'; } else { $htmltitle = $hellip = ''; } $data_level = ''; if ($doctype !== 'xhtml') { $data_level = ' data-level="'.$a['level'].'"'; } $out[] = ''; } array_unshift($out, ''); return n.tag(n.join(n, $out).n, 'select', array( 'id' => $select_id, 'name' => $select_name, )); } /** * Generic form input. * * @param string $type The input type * @param string $name The input name * @param string $value The value * @param string $class The HTML class * @param string $title The tooltip * @param string $onClick Inline JavaScript attached to the click event * @param int $size The input size * @param int $tab The HTML tabindex * @param string $id The HTML id * @param bool $disabled If TRUE renders the input disabled * @param bool $required If TRUE the field is marked as required * @param string $placeholder The placeholder value displayed when the field is empty * @return string HTML input * @example * echo fInput('text', 'myInput', 'My example value'); */ function fInput($type, $name, $value, $class = '', $title = '', $onClick = '', $size = 0, $tab = 0, $id = '', $disabled = false, $required = false, $placeholder = '') { $atts = join_atts(array( 'class' => $class, 'id' => $id, 'name' => $name, 'type' => $type, 'size' => (int) $size, 'title' => $title, 'onclick' => $onClick, 'tabindex' => (int) $tab, 'disabled' => (bool) $disabled, 'required' => (bool) $required, 'placeholder' => $placeholder, ), TEXTPATTERN_STRIP_EMPTY); if ($type != 'file' && $type != 'image') { $atts .= join_atts(array('value' => (string) $value), TEXTPATTERN_STRIP_NONE); } return n.tag_void('input', $atts); } /** * Sanitises a page title. * * @param string $text The input string * @return string * @deprecated in 4.2.0 * @see escape_title() */ function cleanfInput($text) { trigger_error(gTxt('deprecated_function_with', array('{name}' => __FUNCTION__, '{with}' => 'escape_title')), E_USER_NOTICE); return escape_title($text); } /** * Hidden form input. * * @param string $name The name * @param string $value The value * @return string HTML input * @example * echo hInput('myInput', 'hidden value'); */ function hInput($name, $value) { return fInput('hidden', $name, $value); } /** * Hidden step input. * * @param string $step The step * @return string HTML input * @see form() * @see eInput() * @example * echo form( * eInput('event'). * sInput('step') * ); */ function sInput($step) { return hInput('step', $step); } /** * Hidden event input. * * @param string $event The event * @return string HTML input * @see form() * @see sInput() * @example * echo form( * eInput('event'). * sInput('step') * ); */ function eInput($event) { return hInput('event', $event); } /** * Hidden form token input. * * @return string A hidden HTML input containing a CSRF token * @see bouncer() * @see form_token() */ function tInput() { return hInput('_txp_token', form_token()); } /** * A checkbox. * * @param string $name The field * @param string $value The value * @param bool $checked If TRUE the box is checked * @param int $tabindex The HTML tabindex * @param string $id The HTML id * @return string HTML input * @example * echo checkbox('name', 'value', true); */ function checkbox($name, $value, $checked = true, $tabindex = 0, $id = '') { $class = 'checkbox'; if ($checked) { $class .= ' active'; } $atts = join_atts(array( 'class' => $class, 'id' => $id, 'name' => $name, 'type' => 'checkbox', 'checked' => (bool) $checked, 'tabindex' => (int) $tabindex, ), TEXTPATTERN_STRIP_EMPTY); $atts .= join_atts(array('value' => (string) $value), TEXTPATTERN_STRIP_NONE); return n.tag_void('input', $atts); } /** * A checkbox without an option to set the value. * * @param string $name The field * @param bool $value If TRUE the box is checked * @param int $tabindex The HTML tabindex * @param string $id The HTML id * @return string HTML input * @access private * @see checkbox() */ function checkbox2($name, $value, $tabindex = 0, $id = '') { return checkbox($name, 1, $value, $tabindex, $id); } /** * A single radio button. * * @param string $name The field * @param string $value The value * @param bool $checked If TRUE, the button is selected * @param string $id The HTML id * @param int $tabindex The HTML tabindex * @return string HTML input */ function radio($name, $value, $checked = true, $id = '', $tabindex = 0) { $class = 'radio'; if ($checked) { $class .= ' active'; } $atts = join_atts(array( 'class' => $class, 'id' => $id, 'name' => $name, 'type' => 'radio', 'checked' => (bool) $checked, 'tabindex' => (int) $tabindex, ), TEXTPATTERN_STRIP_EMPTY); $atts .= join_atts(array('value' => (string) $value), TEXTPATTERN_STRIP_NONE); return n.tag_void('input', $atts); } /** * Generates a form element. * * This form will contain a CSRF token if called on an authenticated page. * * @param string $contents The form contents * @param string $style Inline styles added to the form * @param string $onsubmit JavaScript run when the form is sent * @param string $method The form method, e.g. "post", "get" * @param string $class The HTML class * @param string $fragment A URL fragment added to the form target * @param string $id The HTML id * @param string $role ARIA role name * @return string HTML form element */ function form($contents, $style = '', $onsubmit = '', $method = 'post', $class = '', $fragment = '', $id = '', $role = '') { $action = 'index.php'; if ($onsubmit) { $onsubmit = 'return '.$onsubmit; } if ($fragment) { $action .= '#'.$fragment; } return n.tag($contents.tInput().n, 'form', array( 'class' => $class, 'id' => $id, 'method' => $method, 'action' => $action, 'onsubmit' => $onsubmit, 'role' => $role, 'style' => $style, )); } /** * Gets and sanitises a field from a prefixed core database table. * * @param string $name The field * @param string $event The table * @param string $identifier The field used for selecting * @param string $id The value used for selecting * @return string HTML * @access private * @see fetch() * @see txpspecialchars() */ function fetch_editable($name, $event, $identifier, $id) { $q = fetch($name, 'txp_'.$event, $identifier, $id); return txpspecialchars($q); } /** * A textarea. * * @param string $name The field * @param int $h The field height in pixels * @param int $w The field width in pixels * @param string $thing The value * @param string $id The HTML id * @param int $rows Rows * @param int $cols Columns * @param string $placeholder The placeholder value displayed when the field is empty * @return string HTML */ function text_area($name, $h = 0, $w = 0, $thing = '', $id = '', $rows = 5, $cols = 40, $placeholder = '') { $style = ''; if ($w) { $style .= 'width:'.intval($w).'px;'; } if ($h) { $style .= 'height:'.intval($h).'px;'; } if ((string) $thing === '') { $thing = null; } else { $thing = txpspecialchars($thing); } if (!intval($rows)) { $rows = 5; } if (!intval($cols)) { $cols = 40; } return n.tag($thing, 'textarea', array( 'id' => $id, 'name' => $name, 'rows' => (int) $rows, 'cols' => (int) $cols, 'style' => $style, 'placeholder' => $placeholder, )); } /** * Generates a select field with a name "type". * * @param array $options * @return string * @access private * @see selectInput() */ function type_select($options) { return n.''; } /** * Generates a list of options for use in a select field. * * @param array $array * @return string * @access private * @see selectInput() */ function type_options($array) { foreach ($array as $a => $b) { $out[] = n.''; } return join('', $out); } /** * Generates a list of radio buttons wrapped in a unordered list. * * @param string $name The field * @param array $values The values as an array array( $value => $label ) * @param string $current_val The selected option. Takes a value from $value * @param string $hilight_val The highlighted list item * @param string|array $atts HTML attributes * @return string HTML */ function radio_list($name, $values, $current_val = '', $hilight_val = '', $atts = array('class' => 'plain-list')) { foreach ($values as $value => $label) { $id = $name.'-'.$value; $class = 'status-'.$value; if ((string) $value === (string) $hilight_val) { $label = strong($label); $class .= ' active'; } $out[] = tag( radio($name, $value, ((string) $current_val === (string) $value), $id). n.tag($label, 'label', array('for' => $id)), 'li', array('class' => $class) ); } return tag(n.join(n, $out).n, 'ul', $atts); } /** * Generates a field used to store and set a date. * * @param string $name The field * @param string $datevar The strftime format the date is displayed * @param int $time The displayed date as a UNIX timestamp * @param int $tab The HTML tabindex * @param string $id The HTML id * @return string HTML * @access private * @example * echo tsi('year', '%Y', 1200000000); */ function tsi($name, $datevar, $time, $tab = 0, $id = '') { static $placeholders = array( '%Y' => 'yyyy', '%m' => 'mm', '%d' => 'dd', '%H' => 'hh', '%M' => 'mn', '%S' => 'ss', ); $value = $placeholder = ''; $size = INPUT_TINY; $pattern = '([0-5][0-9])'; if ((int) $time) { $value = safe_strftime($datevar, (int) $time); } if (isset($placeholders[$datevar])) { $placeholder = gTxt($placeholders[$datevar]); } if ($datevar == '%Y' || $name == 'year' || $name == 'exp_year') { $class = 'input-year'; $size = INPUT_XSMALL; $pattern = '[0-9]{4}'; } if ($datevar == '%m' || $name == 'month' || $name == 'exp_month') { $class = 'input-month'; $pattern = '(0[1-9]|1[012])'; } if ($datevar == '%d' || $name == 'day' || $name == 'exp_day') { $class = 'input-day'; $pattern = '(0[1-9]|1[0-9]|2[0-9]|3[01])'; } if ($datevar == '%H' || $name == 'hour' || $name == 'exp_hour') { $class = 'input-hour'; $pattern = '(0[0-9]|1[0-9]|2[0-3])'; } if ($datevar == '%M' || $name == 'minute' || $name == 'exp_minute') { $class = 'input-minute'; } if ($datevar == '%S' || $name == 'second' || $name == 'exp_second') { $class = 'input-second'; } return n.tag_void('input', array( 'class' => $class, 'id' => $id, 'name' => $name, 'type' => 'text', 'inputmode' => 'numeric', 'pattern' => $pattern, 'size' => (int) $size, 'maxlength' => $size, 'title' => gTxt('article_'.$name), 'aria-label' => gTxt('article_'.$name), 'placeholder' => $placeholder, 'tabindex' => (int) $tab, 'value' => $value, )); }