'select', // Type
* 'name' => 'Search By', // Displayed title for item
* 'id' => 'searchby', // Item id and name
* 'width' => '120px', // (Optional) Item width
* 'size' => '15', // (Optional) Maximum number of items to show in the menu (default 15)
* 'value' => $vars['searchby'], // (Optional) Current value(-s) for item
* 'values' => array('mac' => 'MAC Address',
* 'ip' => 'IP Address')); // Array with option items
* - array for 'multiselect' item type (array keys same as above)
* $search[] = array('type' => 'multiselect',
* 'name' => 'Priorities',
* 'id' => 'priority',
* 'width' => '150px',
* 'subtext' => TRUE, // (Optional) Display items value right of the item name
* 'encode' => FALSE, // (Optional) Use var_encode for values, use when values contains commas or empty string
* 'value' => $vars['priority'],
* 'values' => $priorities);
* - array for 'text' or 'input' item type
* $search[] = array('type' => 'text',
* 'name' => 'Address',
* 'id' => 'address',
* 'width' => '120px',
* 'placeholder' => FALSE, // (Optional) Display item name as pleseholder or left relatively input
* 'value' => $vars['address']);
* - array for 'datetime' item type
* $search[] = array('type' => 'datetime',
* 'id' => 'timestamp',
* 'presets' => TRUE, // (optional) Show select field with timerange presets
* 'min' => dbFetchCell('SELECT MIN(`timestamp`) FROM `syslog`'), // (optional) Minimum allowed date/time
* 'max' => dbFetchCell('SELECT MAX(`timestamp`) FROM `syslog`'), // (optional) Maximum allowed date/time
* 'from' => $vars['timestamp_from'], // (optional) Current 'from' value
* 'to' => $vars['timestamp_to']); // (optional) Current 'to' value
* - array for 'sort' item pseudo type
* $search[] = array('type' => 'sort',
* 'value' => $vars['sort'],
* 'values' => $sorts);
* - array for 'newline' item pseudo type
* $search[] = array('type' => 'newline',
* 'hr' => FALSE); // (optional) show or not horizontal line
* print_search($search, 'Title here', 'search', url);
*
* @param array $data
* @param string|null $title
* @param string $button
* @param string|null $url
*
* @return void
*/
function print_search($data, $title = NULL, $button = 'search', $url = NULL)
{
// Cache permissions to session var
permissions_cache_session();
//r($_SESSION['cache']);
$submit_by_key = FALSE;
$string_items = '';
foreach ($data as $item)
{
if ($url && isset($item['id']))
{
// Remove old vars from url
$url = preg_replace('/'.$item['id'].'=[^\/]+\/?/', '', $url);
}
if ($item['type'] == 'sort')
{
$sort = $item;
continue;
}
else if (isset($item['submit_by_key']) && $item['submit_by_key'])
{
$submit_by_key = TRUE;
}
$string_items .= generate_form_element($item);
}
$form_id = 'search-'.strgen('4');
if ($submit_by_key)
{
$action = '';
if ($url)
{
$action .= 'this.form.prop(\'action\', form_to_path(\'' . $form_id . '\'));';
}
register_html_resource('script', '$(function(){$(\'form#' . $form_id . '\').each(function(){$(this).find(\'input\').keypress(function(e){if(e.which==10||e.which==13){'.$action.'this.form.submit();}});});});');
}
// Form header
$string = PHP_EOL . '' . PHP_EOL;
$string .= '
' . PHP_EOL;
$string .= '' . PHP_EOL . PHP_EOL;
// Print search form
echo($string);
}
// Just callback functions to print_form with $return flag
function generate_form($data)
{
return print_form($data, TRUE);
}
function generate_form_box($data)
{
return print_form_box($data, TRUE);
}
/**
* Pretty form generator
*
* Form options:
* id - form id, default is auto generated
* type - rows (multiple elements with small amount of rows), horizontal (mostly single element per row), simple (raw form without any grid/divs)
* brand - only for rows, adds "other" form title (I think not work and obsolete)
* title - displayed form title (only for rows and horizontal)
* icon - adds icon to title
* class - adds div with class (default box box-solid) in horizontal
* space - adds style for base div in rows type and horizontal with box box-solid class (padding: xx) and horizontal type with box class (padding-top: xx)
* style - adds style for base form element, default (margin-bottom:0;)
* url - form action url, if url set and submit element with id "search" used (or submit_by_key), than form send params as GET query
* submit_by_key - send form query by press enter key in text/input forms
* fieldset - horizontal specific, array with fieldset names and descriptions, in form element should be add fieldset option with same key name
*
* Elements options see in generate_form_element() description
*
* @param array $data Form options and form elements
* @param bool $return If used and set to TRUE, print_form() will return form html instead of outputting it.
*
* @return NULL
*/
function print_form($data, $return = FALSE)
{
// Just return if safety requirements are not fulfilled
if (isset($data['userlevel']) && $data['userlevel'] > $_SESSION['userlevel']) { return; }
// Return if the user doesn't have write permissions to the relevant entity
if (isset($data['entity_write_permit']) &&
!is_entity_write_permitted($data['entity_write_permit']['entity_id'], $data['entity_write_permit']['entity_type']))
{
return;
}
/*
// Use modal with form
if (isset($data['modal_args']) && !empty($data['modal_args']))
{
// Print modal form
echo(generate_form_modal($data));
}
*/
// Time our form filling.
$form_start = microtime(TRUE);
$form_id = (isset($data['id']) ? $data['id'] : 'form-'.strgen());
$form_class = 'form form-inline'; // default for rows and simple
if (isset($data['style']))
{
$form_style = ' style="'.$data['style'].'"';
} else {
$form_style = ' style="margin-bottom: 0px;"';
}
$base_class = (array_key_exists('class', $data) ? $data['class'] : OBS_CLASS_BOX);
$base_space = ($data['space'] ? $data['space'] : '5px');
$used_vars = array();
// Cache permissions to session var
permissions_cache_session();
//r($_SESSION['cache']);
if ($data['submit_by_key'])
{
$action = '';
if ($data['url'])
{
$action .= 'this.form.prop(\'action\', form_to_path(\'' . $form_id . '\'));';
}
register_html_resource('script', '$(function(){$(\'form#' . $form_id . '\').each(function(){$(this).find(\'input\').keypress(function(e){if(e.which==10||e.which==13){'.$action.'this.form.submit();}});});});');
}
// Form elements
if ($data['type'] === 'rows') {
// Rows form, see example in html/pages/devices.inc.php
//$div_padding = 'padding: 0px '.$base_space.' '.$base_space.' '.$base_space.' !important;'; // Top padding set as 0px, all other to base
$div_padding = 'padding: '.$base_space.' !important;';
if (str_contains_array($base_class, 'box')) {
$base_space = ($data['space'] ? $data['space'] : '10px');
// Box horizontal style
$box_args = [
'id' => 'box-' . $form_id,
'header-border' => TRUE,
'body-style' => $div_padding // Override top padding
];
if (isset($data['title'])) { $box_args['title'] = $data['title']; }
$div_begin = generate_box_open($box_args);
$div_end = generate_box_close();
unset($box_args);
} else {
$div_begin = '
' . PHP_EOL;
$div_end = '
' . PHP_EOL;
}
$row_style = '';
$string_elements = '';
// Calculate grid sizes for rows
foreach ($data['row'] as $k => $row)
{
$row_count = safe_count($row);
// Default (auto) grid size for elements
$row_grid = (int)(12 / $row_count);
$grid_count = 0; // Count for custom passed grid sizes
foreach ($row as $id => $element)
{
if (isset($element['div_class']) && preg_match('/col-(?:lg|md|sm)-(\d+)/', $element['div_class'], $matches))
{
// Class with col size passed
$grid_count += (int)$matches[1];
}
else if (isset($element['grid']))
{
// Grid size passed
if ($element['grid'] > 0 && $element['grid'] <= 12)
{
$grid_count += (int)$element['grid'];
} else {
// Incorrect size
unset($row[$k]['grid']);
}
}
}
$row_grid = 12 - $grid_count; // Free grid size after custom grid
$row_grid = (int)($row_grid / $row_count); // Default (auto) grid size for elements
if ($grid_count > 2 && $row_grid < 1) { $row_grid = 1; } // minimum 1 for auto if custom grid passed
else if ($row_grid < 2) { $row_grid = 2; } // minimum 2 for auto
$data['grid'][$k] = $row_grid; // Store default grid size for row
}
//r($data['grid']);
foreach ($data['row'] as $k => $row)
{
$row_class = 'row';
if (isset($data['row_options'][$k])) // If row options exist for current row
{
if ($data['row_options'][$k]['class'])
{
$row_class .= ' ' . $data['row_options'][$k]['class'];
}
}
$string_elements .= '
' . PHP_EOL;
foreach ($row as $id => $element)
{
$used_vars[] = $id;
$element['id'] = $id;
// Default class with default row grid size or passed from options
$grid = (isset($element['grid']) ? $element['grid'] : $data['grid'][$k]);
$div_class = 'col-lg-' . $grid . ' col-md-' . $grid . ' col-sm-' . $grid;
// By default xs grid always 12
if (isset($element['grid_xs']) && $element['grid_xs'] > 0 && $element['grid_xs'] <= 12)
{
$div_class .= ' col-xs-' . $element['grid_xs'];
}
if (empty($element['div_class']))
{
$element['div_class'] = $div_class;
}
else if (isset($element['grid']) && !preg_match('/col-(?:lg|md|sm|xs)-(\d+)/', $element['div_class']))
{
// Combine if passed both: grid size and div_class (and class not has col-* grid elements)
$element['div_class'] = $div_class . ' ' . $element['div_class'];
}
if ($element['right'])
{
$element['div_class'] .= ' col-lg-push-0 col-md-push-0 col-sm-push-0';
}
if ($id === 'search') {
// Add form_id here, for generate onclick action in submit button
if ($data['url']) {
$element['form_id'] = $form_id;
}
} else {
// all other cases add form_id
$element['form_id'] = $form_id;
}
// Here added padding-block-start for space between rows (also if row elements moved to newline)
//$string_elements .= '
' . PHP_EOL;
$string_elements .= '
' . PHP_EOL;
// Add space between rows
$row_style = 'style="margin-top: '.$base_space.';"';
}
// end rows type
} elseif ($data['type'] === 'horizontal') {
// Horizontal form, see example in html/pages/user_edit.inc.php
if (str_contains_array($base_class, [ 'widget', 'box' ])) {
$base_space = ($data['space'] ? $data['space'] : '10px');
// Box horizontal style
$box_args = [
'id' => 'box-' . $form_id,
'header-border' => TRUE,
'body-style' => 'padding-top: '.$base_space.' !important;' // Override top padding
];
if (isset($data['title'])) { $box_args['title'] = $data['title']; }
$div_begin = generate_box_open($box_args);
$div_end = generate_box_close();
unset($box_args);
} elseif (empty($base_class)) {
// Clean class
// Example in html/pages.logon.inc.php
$div_begin = PHP_EOL;
$div_end = PHP_EOL;
} else {
// Old box box-solid style (or any custom style)
$div_begin = '
' . PHP_EOL;
if (isset($data['title']))
{
$div_begin .= '
' . PHP_EOL;
} else {
// Do not add control group for submit/hidden
$fieldset[$row_group] .= $row_elements;
}
//$row_style = 'style="margin-top: '.$base_space.';"'; // Add space between rows
}
foreach ($data['fieldset'] as $row_group => $entry)
{
if (isset($fieldset[$row_group]))
{
if (!is_array($entry))
{
$entry = array('title' => $entry);
}
$fieldset_begin = '';
$fieldset_end = '';
// Additional div class if set
if (isset($entry['class']))
{
$fieldset_begin = '
' . PHP_EOL . $fieldset_begin;
$fieldset_end .= '
' . PHP_EOL;
}
$row_elements = $fieldset_begin . '
' . PHP_EOL;
$fieldset[$row_group] = $row_elements . $fieldset_end;
}
}
// Final combining elements
$string_elements = implode('', $fieldset);
} else {
// Simple form, without any divs, see example in html/pages/user_edit.inc.php
$div_begin = '';
$div_end = '';
$string_elements = '';
foreach ($data['row'] as $k => $row)
{
foreach ($row as $id => $element)
{
$used_vars[] = $id;
$element['id'] = $id;
if ($id === 'search') {
// Add form_id here, for generate onclick action in submit button
if ($data['url']) {
$element['form_id'] = $form_id;
}
} else {
// all other cases add form_id
$element['form_id'] = $form_id;
}
$string_elements .= generate_form_element($element);
}
$string_elements .= PHP_EOL;
}
}
// Add CSRF Token
if (!in_array('requesttoken', $used_vars) && isset($_SESSION['requesttoken']))
{
$string_elements .= generate_form_element(array('type' => 'hidden',
'id' => 'requesttoken',
'value' => $_SESSION['requesttoken'])) . PHP_EOL;
$used_vars[] = 'requesttoken';
}
// Always clean pagination from form action url
$used_vars[] = 'pageno';
$used_vars[] = 'pagination';
$used_vars[] = 'pagesize';
// Remove old vars from url
if ($data['url'])
{
foreach ($used_vars as $var)
{
$data['url'] = preg_replace('/'.$var.'=[^\/]+\/?/', '', $data['url']);
}
}
// Form header
if (isset($data['right']) && $data['right'])
{
$form_class .= ' pull-right';
}
$string = PHP_EOL . "" . PHP_EOL;
$string .= $div_begin;
$string .= '' . PHP_EOL;
$string .= $div_end;
$string .= "" . PHP_EOL;
if ($return)
{
// Save generation time for profiling
$GLOBALS['form_time'] += utime() - $form_start;
// Return form as string
return $string;
}
// Print form
echo($string);
// Save generation time for profiling (after echo)
$GLOBALS['form_time'] += utime() - $form_start;
}
// Box specific form (mostly same as in print_form, but support only box style and fieldset options)
// FIXME should likely not be in this file? As it's used throughout the software now...
function print_form_box($data, $return = FALSE)
{
// Just return if safety requirements are not fulfilled
if (isset($data['userlevel']) && $data['userlevel'] > $_SESSION['userlevel']) { return; }
// Return if the user doesn't have write permissions to the relevant entity
if (isset($data['entity_write_permit']) &&
!is_entity_write_permitted($data['entity_write_permit']['entity_id'], $data['entity_write_permit']['entity_type']))
{
return;
}
// Time our form filling.
$form_start = microtime(TRUE);
$form_id = (isset($data['id']) ? $data['id'] : 'form-'.strgen());
$form_class = 'form form-horizontal';
if (isset($data['style']))
{
$form_style = ' style="'.$data['style'].'"';
} else {
$form_style = ' style="margin-bottom:0px;"';
}
$base_class = (array_key_exists('class', $data) ? $data['class'] : OBS_CLASS_BOX);
$base_space = ($data['space'] ? $data['space'] : '15px');
$used_vars = array();
// Cache permissions to session var
permissions_cache_session();
//r($_SESSION['cache']);
if ($data['submit_by_key'])
{
$action = '';
if ($data['url'])
{
$action .= 'this.form.prop(\'action\', form_to_path(\'' . $form_id . '\'));';
}
register_html_resource('script', '$(function(){$(\'form#' . $form_id . '\').each(function(){$(this).find(\'input\').keypress(function(e){if(e.which==10||e.which==13){'.$action.'this.form.submit();}});});});');
}
$header = '';
if (isset($data['title']))
{
$header .= '
' . $data['title'] . '
' . PHP_EOL;
}
// Form elements
$div_begin = '
' . PHP_EOL;
$div_end = '
' . PHP_EOL;
if ($data['type'] === 'horizontal')
{
$row_style = '';
$fieldset = array();
foreach ($data['row'] as $k => $row)
{
$first_key = key($row);
$row_group = $k;
$row_elements = '';
$row_label = '';
$row_control_group = FALSE;
$i = 0;
foreach ($row as $id => $element)
{
$used_vars[] = $id;
$element['id'] = $id;
if ($element['fieldset'])
{
$row_group = $element['fieldset']; // Add this element to group
}
// Additional element options for horizontal specific form
$div_style = '';
switch ($element['type'])
{
case 'hidden':
break;
case 'submit':
$div_class = 'form-actions';
break;
case 'text':
case 'input':
case 'password':
case 'textarea':
default:
$row_control_group = TRUE;
// In horizontal, first element name always placed at left
if (!isset($element['placeholder'])) { $element['placeholder'] = TRUE; }
// offset == FALSE disable label width and align class control-label
if (!isset($element['offset']))
{
if (isset($data['fieldset'][$element['fieldset']]['offset']))
{
// Copy from fieldset
$element['offset'] = $data['fieldset'][$element['fieldset']]['offset'];
}
elseif (($element['type'] === 'raw' || $element['type'] === 'html') && $first_key === $id)
{
// When raw/html element first, disable offset
$element['offset'] = FALSE;
} else {
// Default
$element['offset'] = TRUE;
}
}
if ($i < 1)
{
// Add label for first element in row
if ($element['name'])
{
$row_label = ' ' . PHP_EOL;
}
$row_control_id = $element['id'] . '_div';
if ($element['type'] === 'datetime')
{
$element['name'] = '';
}
}
// nextrow class element to new line (after label)
$div_class = ($element['offset']) ? 'controls' : 'nextrow';
break;
}
if (!isset($element['div_class']))
{
$element['div_class'] = $div_class;
}
if ($element['div_class'] === 'form-actions')
{
// Remove margins only for form-actions elements
$div_style = 'margin: 0px;';
}
//if ($element['right'])
//{
// $element['div_class'] .= ' pull-right';
//}
if (isset($element['div_style']))
{
$div_style .= ' ' . $element['div_style'];
}
if ($id === 'search') {
// Add form_id here, for generate onclick action in submit button
if ($data['url']) {
$element['form_id'] = $form_id;
}
} else {
// all other cases add form_id
$element['form_id'] = $form_id;
}
$row_elements .= generate_form_element($element);
$i++;
}
if ($element['div_class'])
{
// no additional divs if empty div class (hidden element for example)
$row_begin = $row_label . PHP_EOL . '
' . PHP_EOL;
}
if (isset($entry['tooltip'])) { $box_args['style'] = $entry['style']; }
$fieldset_begin = generate_box_open($box_args);
$fieldset_end = generate_box_close();
// Additional div class if set
if (isset($entry['class']))
{
$fieldset_begin = '
' . PHP_EOL . $fieldset_begin;
$fieldset_end .= '
' . PHP_EOL;
}
$row_elements = $fieldset_begin . '
' . PHP_EOL;
$fieldset[$group] = $row_elements . $fieldset_end;
}
}
// Combine fieldsets into common rows
foreach ($divs as $entry)
{
$row_elements = $div_begin;
foreach ($entry as $i => $group)
{
$row_elements .= $fieldset[$group];
if ($i > 0)
{
// unset all fieldsets except first one for replace later
unset($fieldset[$group]);
}
}
$row_elements .= $div_end;
// now replace first fieldset in group
$fieldset[array_shift($entry)] = $row_elements;
}
// Final combining elements
$string_elements = implode('', $fieldset);
}
// Add CSRF Token
if (!in_array('requesttoken', $used_vars) && isset($_SESSION['requesttoken']))
{
$string_elements .= generate_form_element(array('type' => 'hidden',
'id' => 'requesttoken',
'value' => $_SESSION['requesttoken'])) . PHP_EOL;
$used_vars[] = 'requesttoken';
}
// Remove old vars from url
if ($data['url'])
{
foreach ($used_vars as $var)
{
$data['url'] = preg_replace('/'.$var.'=[^\/]+\/?/', '', $data['url']);
}
}
// Form header
$string = PHP_EOL . "" . PHP_EOL;
$string .= $header;
$string .= '' . PHP_EOL;
$string .= $fieldset_tooltip;
$string .= "" . PHP_EOL;
if ($return)
{
// Save generation time for profiling
$GLOBALS['form_time'] += utime() - $form_start;
// Return form as string
return $string;
}
// Print form
echo($string);
// Save generation time for profiling (after echo)
$GLOBALS['form_time'] += utime() - $form_start;
}
/**
* Generates form elements. The main use for print_search() and print_form(), see examples of this functions.
*
* Common options (can be in any(mostly) element type):
* (string) id - element identificator
* (array) attribs - any custom element attrib (where key is attrib name, value - attrib value)
* (bool) offset - for horizontal forms enable (default) or disable element offset (shift to the right on 180px)
* Options tree:
* textarea -\
* (string)id, (string)name, (bool)readonly, (bool)disabled, (string)width, (string)class,
* (int)rows, (int)cols,
* (string)value, (bool,string)placeholder, (bool)ajax, (array)ajax_vars
* text, input, password -\
* (string)id, (string)name, (bool)readonly, (bool)disabled, (string)width, (string)class,
* (string)value, (bool,string)placeholder, (bool)ajax, (array)ajax_vars,
* (bool)show_password
* hidden -\
* (string)id, (string)value
* select, multiselect -\
* (string)id, (string)name, (bool)readonly, (bool)disabled, (string)onchange, (string)width,
* (string)title, (int)size, (bool)right, (bool)live-search, (bool)encode, (bool)subtext
* (string)value, (array)values, (string)icon,
* values items can be arrays, ie:
* value => array('name' => string, 'group' => string, 'icon' => string, 'class' => string, 'style' => string)
* datetime -\
* (string)id, (string)name, (bool)readonly, (bool)disabled,
* (string|FALSE)from, (string|FALSE)to, (bool)presets, (string)min, (string)max
* (string)value (use it for single input)
* checkbox, switch, toggle -\
* (string)id, (string)name, (bool)readonly, (bool)disabled, (string)onchange,
* [switch only]: (bool)revert, (int)width, (string)size, (string)off-color, (string)on-color, (string)off-text, (string)on-text
* [toggle only]: (string)view, (string)size, (string)palette, (string)group, (string)label,
* (string)icon-check, (string)label-check, (string)icon-uncheck, (string)label-uncheck
* (string)value, (string)placeholder, (string)title
* submit -\
* (string)id, (string)name, (bool)readonly, (bool)disabled,
* (string)class, (bool)right, (string)tooltip,
* (string)value, (string)form_id, (string)icon
* html, raw -\
* (string)id, (bool)offset,
* (string)html, (string)value
* newline -\
* (string)id,
* (bool)hr
*
* @param array $item Options for current form element
* @param string $type Type of form element, also can passed as $item['type']
* @return string Generated form element
*/
function generate_form_element($item, $type = '')
{
// Check community edition
if (isset($item['community']) && !$item['community'] && OBSERVIUM_EDITION === 'community') {
return '';
}
$value_isset = isset($item['value']);
if (!$value_isset) { $item['value'] = ''; }
if (is_array($item['value']))
{
// Passed from URI comma values always converted to array, re-implode it
$item['value_escaped'] = escape_html(implode(',', $item['value']));
} else {
$item['value_escaped'] = escape_html($item['value']);
}
if (!isset($item['type'])) { $item['type'] = $type; }
$string = '';
$element_tooltip = '';
$element_data = '';
// auto add some common html attribs
foreach ([ 'onchange', 'oninput', 'onclick', 'ondblclick', 'onfocus', 'onsubmit' ] as $attrib) {
if (isset($item[$attrib])) {
$item['attribs'][$attrib] = $item[$attrib];
}
}
if (isset($item['attribs']) && is_array($item['attribs']))
{
// Custom html attributes
if (isset($item['attribs']['data-toggle']))
{
// Enable item specific JS/CSS/Script
switch ($item['attribs']['data-toggle'])
{
case 'confirm':
case 'confirmation':
if ($item['attribs']['data-toggle'] === 'confirmation') {
$item['attribs']['data-toggle'] = 'confirm';
}
// popConfirm
//register_html_resource('js', 'jquery.popconfirm.js');
//register_html_resource('script', '$("[data-toggle=\'' . $item['attribs']['data-toggle'] . '\']").popConfirm();');
// Bootstrap-Confirmation
register_html_resource('js', 'bootstrap-confirmation.js');
//register_html_resource('script', '$("[data-toggle=\'' . $item['attribs']['data-toggle'] .
// '\']").confirmation({rootSelector: \'[data-toggle=' . $item['attribs']['data-toggle'] . ']\',});');
//$script_options = [ 'rootSelector: \'[data-toggle=' . $item['attribs']['data-toggle'] . ']\'' ];
if (!isset($item['attribs']['data-btn-ok-label'])) {
// default "Yes"
//$item['attribs']['data-btn-ok-label'] = 'Yes';
}
if (!isset($item['attribs']['data-btn-ok-class'])) {
// default "btn btn-xs btn-primary"
}
if (!isset($item['attribs']['data-btn-ok-icon'])) {
// default "glyphicon glyphicon-ok"
//$item['attribs']['data-btn-ok-icon'] = 'Yes';
}
if (!isset($item['attribs']['data-btn-cancel-label'])) {
// default "No"
//$item['attribs']['data-btn-cancel-label'] = 'Cheese';
}
if (!isset($item['attribs']['data-btn-cancel-class'])) {
// default "btn btn-xs btn-default"
//$item['attribs']['data-btn-cancel-class'] = 'btn-small btn-warning';
}
if (!isset($item['attribs']['data-btn-cancel-icon'])) {
// default "glyphicon glyphicon-remove"
//$item['attribs']['data-btn-cancel-icon'] = 'icon-sort';
}
// migrate from popConfirm
if (!isset($item['attribs']['data-title'])) {
$item['attribs']['data-title'] = 'Confirmation';
}
if (!isset($item['attribs']['data-singleton'])) {
$item['attribs']['data-singleton'] = 'true';
}
if (!isset($item['attribs']['data-popout'])) {
$item['attribs']['data-popout'] = 'true';
}
if (isset($item['attribs']['data-confirm-placement'])) {
$item['attribs']['data-placement'] = $item['attribs']['data-confirm-placement'];
unset($item['attribs']['data-confirm-placement']);
}
if (isset($item['attribs']['data-confirm-content'])) {
$item['attribs']['data-content'] = $item['attribs']['data-confirm-content'];
unset($item['attribs']['data-confirm-content']);
}
//register_html_resource('script', '$("[data-toggle=\'' . $item['attribs']['data-toggle'] . '\']").confirmation({' . implode(', ', $script_options) . '});');
break;
case 'switch':
// Bootstrap Toggle
//$element_data .= ' data-selector="bootstrap-toggle"';
$item['attribs']['data-selector'] = "bootstrap-toggle";
register_html_resource('js', 'bootstrap-toggle.min.js');
//register_html_resource('js', 'bootstrap-toggle.js'); /// DEVEL
register_html_resource('css', 'bootstrap-toggle.min.css');
register_html_resource('script', '$("input[data-selector=\'bootstrap-toggle\']").bootstrapToggle();');
/* bootstrapSwitch (deprecated)
register_html_resource('js', 'bootstrap-switch.min.js');
//register_html_resource('css', 'bootstrap-switch.css');
register_html_resource('script', '$("[data-toggle=\'' . $item['attribs']['data-toggle'] . '\']").bootstrapSwitch();');
*/
break;
case 'toggle':
if (str_contains($item['class'], 'tiny-toggle')) {
// TinyToggle
$script = '';
if ($item['onchange']) {
// Here toggle specific onchange behavior
$script .= 'onChange: function(obj, value) { ' . $item['onchange'] . ' },';
// Set custom element selector
$selector = 'tiny-toggle-' . md5($item['onchange']);
//$element_data .= ' data-selector="'.$selector.'"';
$item['attribs']['data-selector'] = $selector;
register_html_resource('script', '$("input[data-selector=\''.$selector.'\'].tiny-toggle").tinyToggle({' . $script . '});');
unset($item['onchange']);
} else {
//$element_data .= ' data-selector="tiny-toggle"';
$item['attribs']['data-selector'] = "tiny-toggle";
//register_html_resource('script', '$("[data-toggle=\'' . $item['attribs']['data-toggle'] . '\']").tinyToggle({'.$script.'});'); // this selector intersects with bootstrap toggle
register_html_resource('script', '$("input[data-selector=\'tiny-toggle\'].tiny-toggle").tinyToggle();');
}
register_html_resource('js', 'tiny-toggle.min.js');
register_html_resource('css', 'tiny-toggle.min.css');
} else {
// Bootstrap Toggle
//$element_data .= ' data-selector="bootstrap-toggle"';
$item['attribs']['data-selector'] = "bootstrap-toggle";
register_html_resource('js', 'bootstrap-toggle.min.js');
//register_html_resource('js', 'bootstrap-toggle.js'); /// DEVEL
register_html_resource('css', 'bootstrap-toggle.min.css');
register_html_resource('script', '$("input[data-selector=\'bootstrap-toggle\']").bootstrapToggle();');
}
//r($item);
break;
}
}
$element_data .= ' ' . generate_html_attribs($item['attribs']);
}
switch ($item['type'])
{
case 'hidden':
if (!$item['readonly'] && !$item['disabled']) // If item readonly or disabled, just skip item
{
$string .= ' ' . PHP_EOL;
}
break;
case 'password':
case 'textarea':
case 'text':
case 'input':
$item_class = '';
$value_hidden = FALSE;
if ($item['type'] !== 'textarea')
{
$item_begin = ' 7)) {
$item['value_escaped'] = '••••••••';
$value_hidden = TRUE;
}
// add icon for show/hide password
if ($item['show_password']) {
$item_begin .= ' data-toggle="password" ';
register_html_resource('js', 'bootstrap-show-password.min.js');
$GLOBALS['cache_html']['javascript'][] = "$('[data-toggle=\"password\"]').password();";
}
//elseif (!$value_hidden && $autocomplete_off) {}
}
// Disable Autocomplete if required
if ($autocomplete_off) {
$browser = detect_browser();
//r($browser);
// Autofill off is not simple!
//https://developer.mozilla.org/en-US/docs/Web/Security/Securing_your_site/Turning_off_form_autocompletion#The_autocomplete_attribute_and_login_fields
//https://www.chromium.org/developers/design-documents/form-styles-that-chromium-understands
//https://stackoverflow.com/questions/41945535/html-disable-password-manager
if ($item['type'] === 'password' && !$value_hidden)
{
$autocomplete_value = 'new-password';
$item_begin = '' .
'' .
'' .
$item_begin;
} else {
$autocomplete_value = 'off';
}
$item_begin .= ' autocomplete="'.$autocomplete_value.'" ';
if ($browser['browser'] === 'Safari') {
// Safari issue: https://stackoverflow.com/questions/22661977/disabling-safari-autofill-on-usernames-and-passwords
//$item_begin .= ' autocomplete="off" readonly onfocus="if (this.hasAttribute(\'readonly\')) {this.removeAttribute(\'readonly\'); this.blur(); this.focus();}" ';
//$item_begin .= ' autocomplete="false" ';
// This disable safari autocomplete button
register_html_resource('style', <<';
$item_class .= 'input';
} else {
$item_begin = ' ';
$item_class .= 'form-control';
}
$item_begin .= $element_data; // Add custom data- attribs
if ($item['disabled'])
{
$item_end = ' disabled="1"' . $item_end;
}
else if ($item['readonly'])
{
$item_end = ' readonly="1"' . $item_end;
}
if (isset($item['placeholder']) && $item['placeholder'] !== FALSE)
{
if ($item['placeholder'] === TRUE)
{
$item['placeholder'] = $item['name'];
}
$string .= PHP_EOL;
$string .= $item_begin . 'placeholder="'.$item['placeholder'].'" ';
$item['placeholder'] = TRUE; // Set to true for check at end
} elseif ($item['type'] === 'text') {
$string .= $item_begin;
} else {
$string .= '