plugins/html/classes/yf_html.class.php
<?php
/**
* HTML high-level controls collection.
*
* @author YFix Team <yfix.dev@gmail.com>
* @version 1.0
*/
class yf_html
{
public $AUTO_ASSIGN_IDS = true;
public $BOXES_USE_STPL = false;
public $SELECT_BOX_DEF_OPT_TPL = '- %select% %name% -';
public $CLASS_LABEL_RADIO = 'radio';
public $CLASS_LABEL_RADIO_INLINE = 'radio-inline';
public $CLASS_LABEL_RADIO_SELECTED = 'active';
public $CLASS_LABEL_CHECKBOX = 'checkbox';
public $CLASS_LABEL_CHECKBOX_INLINE = 'checkbox-inline';
public $CLASS_LABEL_CHECKBOX_SELECTED = 'active';
public $CLASS_LABEL_BTN_RADIO = 'btn btn-xs btn-primary';
public $CLASS_LABEL_BTN_CHECKBOX = 'btn btn-xs btn-primary';
public $CLASS_SELECT_BOX = 'form-control';
public $CLASS_SELECT_OPTION_DEFAULT = 'opt-default';
public $CLASS_INPUT = 'form-control';
/**
* Catch missing method call.
* @param mixed $name
* @param mixed $args
*/
public function __call($name, $args)
{
return main()->extend_call($this, $name, $args);
}
/**
* We cleanup object properties when cloning.
*/
public function __clone()
{
$keep_prefix = 'CLASS_';
$keep_len = strlen($keep_prefix);
$keep_prefix2 = 'CONF_';
$keep_len2 = strlen($keep_prefix2);
foreach ((array) get_object_vars($this) as $k => $v) {
if (substr($k, 0, $keep_len) === $keep_prefix) {
continue;
}
if (substr($k, 0, $keep_len2) === $keep_prefix2) {
continue;
}
if ($k[0] == '_') {
$this->$k = null;
}
}
}
/**
* Need to avoid calling render() without params.
*/
public function __toString()
{
try {
return (string) $this->render();
} catch (Exception $e) {
return '';
}
}
public function _init()
{
$this->_is_bs3 = (conf('css_framework') == 'bs3');
}
/**
* Get and sort items ordered array (recursively).
* @param mixed $items
* @param mixed $skip_item_id
* @param mixed $parent_id
*/
public function _recursive_sort_items($items = [], $skip_item_id = 0, $parent_id = 0)
{
$children = [];
foreach ((array) $items as $id => $info) {
$parent_id = (int) $info['parent_id'];
if ($skip_item_id == $id) {
continue;
}
$children[$parent_id][$id] = $id;
}
$ids = $this->_count_levels(0, $children);
$new_items = [];
foreach ((array) $ids as $id => $level) {
$new_items[$id] = $items[$id] + ['level' => $level];
}
return $new_items;
}
/**
* @param mixed $start_id
* @param mixed $level
*/
public function _count_levels($start_id = 0, &$children, $level = 0)
{
$ids = [];
foreach ((array) $children[$start_id] as $id => $_tmp) {
$ids[$id] = $level;
if (isset($children[$id])) {
foreach ((array) $this->_count_levels($id, $children, $level + 1) as $_id => $_level) {
$ids[$_id] = $_level;
}
}
}
return $ids;
}
/**
* Wrapper for template engine
* Example:
* return html()->dd_table(db()->get_2d('SELECT * FROM '.db('countries')));.
* @param mixed $params
*/
public function chained_wrapper($params = [])
{
$this->_chained_mode = true;
$this->_params = $params;
return $this;
}
/**
* @param mixed $replace
* @param mixed $extra
*/
public function simple_table($replace = [], $extra = [])
{
if ( ! $replace) {
return false;
}
$key_name = isset($extra['key']['name']) ? $extra['key']['name'] : 'key';
$val_name = isset($extra['val']['name']) ? $extra['val']['name'] : 'val';
$key_extra = isset($extra['key']['extra']) ? $extra['key']['extra'] : [];
$val_extra = isset($extra['val']['extra']) ? $extra['val']['extra'] : [];
$key_func = isset($extra['key']['func']) ? $extra['key']['func'] : 'text';
if ( ! is_string($key_func) && is_callable($key_func)) {
$key_callable = $key_func;
$key_func = 'func';
}
$val_func = isset($extra['val']['func']) ? $extra['val']['func'] : 'text';
if ( ! is_string($val_func) && is_callable($val_func)) {
$val_callable = $val_func;
$val_func = 'func';
}
$data = [];
foreach ((array) $replace as $k => $v) {
$data[] = [
$key_name => $k,
$val_name => $v,
];
}
$extra['id'] = $extra['id'] ?: __FUNCTION__ . '_' . ++$this->_ids[__FUNCTION__];
$extra['no_header'] = isset($extra['no_header']) ? $extra['no_header'] : 1;
$extra['pager_records_on_page'] = isset($extra['pager_records_on_page']) ? $extra['pager_records_on_page'] : 10000;
$extra['no_total'] = isset($extra['no_total']) ? $extra['no_total'] : true;
$extra['no_pages'] = isset($extra['no_pages']) ? $extra['no_pages'] : true;
$extra['hide_empty'] = isset($extra['hide_empty']) ? $extra['hide_empty'] : true;
return table($data, $extra)
->$key_func($key_name, $key_callable, $key_extra)
->$val_func($val_name, $val_callable, $val_extra);
}
/**
* @param mixed $replace
* @param mixed $field_types
* @param mixed $extra
*/
public function dd_table($replace = [], $field_types = [], $extra = [])
{
$extra['id'] = $extra['id'] ?: __FUNCTION__ . '_' . ++$this->_ids[__FUNCTION__];
if (DEBUG_MODE) {
$ts = microtime(true);
}
$form = form($replace, [
'legend' => $replace['title'],
'no_form' => 1,
'dd_mode' => 1,
'dd_class' => 'span6 col-md-6',
]);
foreach ((array) $replace as $name => $val) {
$func = 'container';
$_extra = [
'desc' => $name,
'value' => $val,
];
$ft = $field_types[$name];
if (isset($ft)) {
if (is_array($ft)) {
if (isset($ft['func'])) {
$func = $ft['func'];
}
$_extra = (array) $ft + $_extra;
} else {
$func = $ft;
}
}
$_extra += (array) $extra;
// Callback to decide if we need to show this field or not
if (isset($_extra['display_func']) && is_callable($_extra['display_func'])) {
$_display_allowed = $_extra['display_func']($val, $_extra);
if ( ! $_display_allowed) {
continue;
}
}
if ($func) {
$form->$func($val, $_extra);
}
}
$legend = $extra['legend'] ? '<legend>' . _prepare_html(t($extra['legend'])) . '</legend>' : '';
$div_class = $extra['div_class'] ? $extra['div_class'] : 'span6 col-md-6';
if (DEBUG_MODE) {
debug('dd_table[]', [
'fields' => $replace,
'field_types' => $field_types,
'extra' => $extra,
'time' => round(microtime(true) - $ts, 5),
'trace' => main()->trace_string(),
]);
}
return '<div class="row-fluid" id="' . $extra['id'] . '">' . $legend . '<div class="' . $div_class . '">' . $form . '</div></div>';
}
/**
* @param mixed $extra
*/
public function modal($extra = [])
{
$extra['id'] = $extra['id'] ?: __FUNCTION__ . '_' . ++$this->_ids[__FUNCTION__];
$def_style = $extra['inline'] ? 'position: relative; top: auto; left: auto; right: auto; bottom: auto; margin: 0 auto 20px; z-index: 1; max-width: 100%; display: block; overflow-y: auto;' : '';
$extra['style'] = $extra['style'] ?: $def_style;
return '
<div class="modal" style="' . $extra['style'] . '" id="' . $extra['id'] . '">
<div class="modal-dialog">
<div class="modal-content">
<div class="modal-header">'
. ($extra['show_close'] ? '<button type="button" class="close" data-dismiss="modal" aria-hidden="true">×</button>' : '')
. ($extra['header'] ? '<h3>' . $extra['header'] . '</h3>' : '')
. '</div>
<div class="modal-body">' . $extra['body'] . '</div>'
. ($extra['footer'] ? '<div class="modal-footer">' . $extra['footer'] . '</div>' : '') . '
</div>
</div>
</div>';
}
/**
* @param mixed $tabs
* @param mixed $extra
*/
public function tabs($tabs = [], $extra = [])
{
$extra['id'] = $extra['id'] ?: __FUNCTION__ . '_' . ++$this->_ids[__FUNCTION__];
$extra_by_id = [];
if (isset($extra['by_id'])) {
$extra_by_id = (array) $extra['by_id'];
unset($extra['by_id']);
}
$links_prefix = $extra['links_prefix'] ?: 'tab_';
$headers = [];
$items = [];
foreach ((array) $tabs as $k => $v) {
$desc_raw = null;
$disabled = null;
if ( ! is_array($v)) {
$content = $v;
$v = [];
} else {
$content = $v['content'];
$desc_raw = $v['desc_raw'];
$disabled = $v['disabled'];
}
$content = trim($content);
$_extra = (array) $extra_by_id[$k] + (array) $extra;
if ($_extra['hide_empty'] && ! strlen($content)) {
continue;
}
$name = $v['name'] ?: $k;
$desc = $v['desc'] ?: ( ! $_extra['no_auto_desc'] ? ucfirst(str_replace('_', ' ', $name)) : $name);
$id = preg_replace('~[^a-z0-9_-]+~i', '', $v['id'] ?: $links_prefix . $k);
if (isset($_extra['selected'])) {
$is_active = ($_extra['selected'] == $k);
} else {
$is_active = (++$i == 1);
}
if (isset($_extra['totals'][$name])) {
$v['badge'] = (int) (isset($_extra['totals'][$name]['total']) ? $_extra['totals'][$name]['total'] : $_extra['totals'][$name]);
}
$badge = isset($v['badge']) ? ' <sup class="badge badge-' . ($v['class_badge'] ?: 'info') . '">' . $v['badge'] . '</sup>' : '';
if ( ! $_extra['no_headers']) {
$class_head = $v['class_head'] ?: $_extra['class_head'];
$class_head .= $_extra['class_add_head'] ? ' ' . $_extra['class_add_head'] : '';
if ($is_active) {
$class_head = trim('active ' . $class_head);
}
$_extra_head = (array) $_extra['tab_head'];
$_extra_head['class'] = $_extra_head['class'] ?: $class_head;
$headers[] =
'<li' . _attrs($_extra_head, ['id', 'class', 'style']) . '>
<a ' . ( ! $disabled ? 'href="#' . fix_html_attr_id($id) . '" ' : '') . 'data-toggle="tab">' . ($desc_raw ?: t($desc)) . $badge . '</a>
</li>';
}
$class_body = ($_extra['class'] ?: $v['class_body']) ?: $_extra['class_body'];
$class_body = $class_body ?: 'tab-pane';
$class_body .= $_extra['class_add_body'] ? ' ' . $_extra['class_add_body'] : '';
if ($is_active || $_extra['show_all']) {
$class_body = trim('active ' . $class_body);
} else {
$class_body = trim('fade ' . $class_body);
}
$_extra_body = (array) $_extra['tab_body'];
$_extra_body['id'] = $_extra_body['id'] ?: $id;
$_extra_body['class'] = $_extra_body['class'] ?: $class_body;
$items[] = '<div' . _attrs($_extra_body, ['id', 'class', 'style']) . '>' . $content . '</div>';
}
$body .= $headers ? '<ul id="' . $extra['id'] . '" class="nav nav-tabs">' . implode(PHP_EOL, (array) $headers) . '</ul>' . PHP_EOL : '';
$body .= '<div id="' . $extra['id'] . '_content" class="tab-content">' . implode(PHP_EOL, (array) $items) . '</div>';
return $body;
}
/**
* @param mixed $data
* @param mixed $extra
*/
public function accordion($data = [], $extra = [])
{
$extra['id'] = $extra['id'] ?: __FUNCTION__ . '_' . ++$this->_ids[__FUNCTION__];
$items = [];
foreach ((array) $data as $k => $v) {
if ( ! is_array($v)) {
$content = $v;
$v = [];
} else {
$content = $v['body'];
}
$name = $v['name'] ?: $k;
$desc = $v['desc'] ?: ucfirst(str_replace('_', ' ', $name));
$id = $v['id'] ?: 'accordion_item_' . $k;
if (isset($extra['selected'])) {
$is_selected = ($extra['selected'] == $k);
} else {
$is_selected = (++$i == 1);
}
$class_group = $v['class_group'] ?: $extra['class_group'];
$class_head = $v['class_head'] ?: $extra['class_head'];
$class_body = $v['class_body'] ?: $extra['class_body'];
$badge = $v['badge'] ? ' <sup class="badge badge-' . ($v['class_badge'] ?: 'info') . '">' . $v['badge'] . '</sup>' : '';
$items[] =
'<div class="accordion-group panel panel-default' . ($class_group ? ' ' . $class_group : '') . '">
<div class="accordion-heading panel-heading' . ($class_head ? ' ' . $class_head : '') . '">
' . ($this->_is_bs3 ? '<h4 class="panel-title">' : '') . '
<a class="accordion-toggle" data-toggle="collapse" data-parent="#' . $extra['id'] . '" href="#' . $id . '">' . $desc . $badge . '</a>
' . ($this->_is_bs3 ? '</h4>' : '') . '
</div>
<div id="' . $id . '" class="accordion-body panel-collapse collapse' . ($is_selected ? ' in' : '') . ($class_body ? ' ' . $class_body : '') . '">
<div class="accordion-inner panel-body">' . $content . '</div>
</div>
</div>';
}
return '<div class="panel-group accordion' . ($extra['class'] ? ' ' . $extra['class'] : '') . '" id="' . $extra['id'] . '">' . implode(PHP_EOL, (array) $items) . '</div>';
}
/**
* @param mixed $data
* @param mixed $extra
*/
public function carousel($data = [], $extra = [])
{
$extra['id'] = $extra['id'] ?: __FUNCTION__ . '_' . ++$this->_ids[__FUNCTION__];
$items = [];
$headers = [];
foreach ((array) $data as $k => $v) {
if ( ! is_array($v)) {
$img_src = $v;
$v = [];
} else {
$img_src = $v['img'];
}
$desc = $v['desc'];
$alt = $v['alt'] ?: strip_tags($desc);
$id = $v['id'] ?: 'carousel_item_' . $k;
if (isset($extra['selected'])) {
$is_active = ($extra['selected'] == $k);
} else {
$is_active = (++$i == 1);
}
$class_head = $v['class_head'] ?: $extra['class_head'];
$class_body = $v['class_body'] ?: $extra['class_body'];
$headers[] = '<li data-target="#' . $extra['id'] . '" data-slide-to="' . ($i - 1) . '" class="' . ($is_active ? 'active' : '') . ($class_head ? ' ' . $class_head : '') . '"></li>';
$items[] =
'<div class="item' . ($is_active ? ' active' : '') . ($class_body ? ' ' . $class_body : '') . '">
<img src="' . $img_src . '" alt="' . $alt . '">
' . ($desc ? '<div class="carousel-caption">' . $desc . '</div>' : '') . '
</div>';
}
$controls = '
<a class="left carousel-control" href="#' . $extra['id'] . '" data-slide="prev"><span class="icon icon-chevron-left fa fa-chevron-left"></span></a>
<a class="right carousel-control" href="#' . $extra['id'] . '" data-slide="next"><span class="icon icon-chevron-right fa fa-chevron-right"></span></a>
';
return '<div id="' . $extra['id'] . '" class="carousel slide' . ($extra['class'] ? ' ' . $extra['class'] : '') . '" data-ride="carousel">
<ol class="carousel-indicators">' . implode(PHP_EOL, $headers) . '</ol>
<div class="carousel-inner">' . implode(PHP_EOL, $items) . '</div>
' . ( ! $extra['no_controls'] ? $controls : '') . '
</div>';
}
/**
* @param mixed $data
* @param mixed $extra
*/
public function alert($data = [], $extra = [])
{
$extra['id'] = $extra['id'] ?: __FUNCTION__ . '_' . ++$this->_ids[__FUNCTION__];
$close_btn = ( ! $extra['no_close'] && ! $data['no_close']) ? '<button type="button" class="close" data-dismiss="alert">×</button>' : '';
$head = is_array($data) ? $data['head'] : '';
$body = is_array($data) ? $data['body'] : $data;
$alert_type = $extra['alert'] ?: (is_array($data) ? $data['alert'] : '');
if ( ! $alert_type) {
$alert_type = 'error';
}
return '
<div class="alert alert-block alert-' . $alert_type . ' fade in' . ($extra['class'] ? ' ' . $extra['class'] : '') . '" id="' . $extra['id'] . '">
' . $close_btn . '
' . ($head ? '<h4 class="alert-heading">' . $head . '</h4>' : '') . '
' . $body . '
</div>';
}
/**
* @param mixed $data
* @param mixed $extra
*/
public function navbar($data = [], $extra = [])
{
$extra['id'] = $extra['id'] ?: __FUNCTION__ . '_' . ++$this->_ids[__FUNCTION__];
$items = [];
$brand = '';
if (isset($data['brand'])) {
$b = $data['brand'];
unset($data['brand']);
$brand = '<a class="brand navbar-brand' . ($b['class'] ? ' ' . $b['class'] : '') . '" href="' . $b['link'] . '" title="' . $b['name'] . '">' . $b['name'] . '</a>';
}
$data = _prepare_html($data);
foreach ((array) $data as $k => $v) {
if (isset($extra['selected'])) {
$is_selected = ($extra['selected'] == $k);
} else {
$is_selected = (++$i == 1);
}
$class_item = $v['class_item'] ?: $extra['class_item'];
$badge = $v['badge'] ? ' <sup class="badge badge-' . ($v['class_badge'] ?: 'info') . '">' . $v['badge'] . '</sup>' : '';
$items[] = '<li class="' . ($is_selected ? ' active' : '') . ($class_item ? ' ' . $class_item : '') . '"><a href="' . $v['link'] . '" title="' . $v['name'] . '">' . $v['name'] . $badge . '</a></li>';
}
return
'<div class="navbar navbar-default' . ($extra['class'] ? ' ' . $extra['class'] : '') . '" id="' . $extra['id'] . '">
<div class="navbar-inner navbar-header">'
. $brand
. '<ul class="nav navbar-nav">' . implode(PHP_EOL, (array) $items) . '</a>
</div>
</div>';
}
/**
* @param mixed $data
* @param mixed $extra
*/
public function breadcrumbs($data = [], $extra = [])
{
$extra['id'] = $extra['id'] ?: __FUNCTION__ . '_' . ++$this->_ids[__FUNCTION__];
$items = [];
$divider = $extra['divider'] ?: ''; // '/'
$show_divider = ! $this->_is_bs3 && strlen($divider);
$len = count((array) $data);
$data = _prepare_html($data);
foreach ((array) $data as $k => $v) {
$is_last = (++$i == $len);
$class_item = $v['class_item'] ?: $extra['class_item'];
$badge = $v['badge'] ? ' <sup class="badge badge-' . ($v['class_badge'] ?: 'info') . '">' . $v['badge'] . '</sup>' : '';
$items[] = '<li class="' . ($is_last ? ' active' : '') . ($class_item ? ' ' . $class_item : '') . '">
' . (
($is_last || ! $v['link']) ? $v['name']
: '<a href="' . $v['link'] . '" title="' . $v['name'] . '">' . $v['name'] . $badge . '</a>' . ($show_divider ? ' <span class="divider">' . $divider . '</span>' : '')
) . '
</li>';
}
$tag = $this->_is_bs3 ? 'ol' : 'ul';
return '<' . $tag . ' class="breadcrumb' . ($extra['class'] ? ' ' . $extra['class'] : '') . '" id="' . $extra['id'] . '"">' . implode(PHP_EOL, (array) $items) . '</' . $tag . '>';
}
/**
* @param mixed $data
* @param mixed $extra
*/
public function thumbnails($data = [], $extra = [])
{
$items = [];
$columns = (int) $extra['columns'] ?: 3;
$row_class = 'span' . round(12 / $columns) . ' col-md-' . round(12 / $columns);
foreach ((array) $data as $k => $v) {
if ( ! is_array($v)) {
$img_src = $v;
$v = [];
} else {
$img_src = $v['img'];
}
$class_item = $v['class_item'] ?: $extra['class_item'];
$tag = $this->_is_bs3 ? 'div' : 'li';
$items[] =
'<' . $tag . ' class="' . $row_class . ($class_item ? ' ' . $class_item : '') . ($v['style'] ? ' style="' . $v['style'] . '"' : '') . '">
<div class="thumbnail">
<img alt="' . _prepare_html($v['alt'] ?: $v['head']) . '" src="' . _prepare_html($img_src) . '" />
' . (($v['head'] || $v['body']) ? '<div class="caption">' . ($v['head'] ? '<h3>' . _prepare_html($v['head']) . '</h3>' : '') . ' ' . $v['body'] . '</div>' : '') . '
</div>
</' . $tag . '>';
}
$body = [];
$tag = $this->_is_bs3 ? 'div' : 'ul';
foreach (array_chunk($items, $columns) as $_items) {
$id = __FUNCTION__ . '_' . ++$this->_ids[__FUNCTION__];
$body[] = '<' . $tag . ' class="thumbnails' . ($extra['class'] ? ' ' . $extra['class'] : '') . '" id="' . $id . '">' . implode(PHP_EOL, (array) $_items) . '</' . $tag . '>';
}
return implode(PHP_EOL, $body);
}
/**
* @param mixed $data
* @param mixed $extra
*/
public function progress_bar($data = [], $extra = [])
{
$extra['id'] = $extra['id'] ?: __FUNCTION__ . '_' . ++$this->_ids[__FUNCTION__];
$items = [];
foreach ((array) $data as $v) {
if ( ! is_array($v)) {
$val = $v;
$v = [];
} else {
$val = $v['val'];
}
$type = $v['type'] ?: $extra['type'];
$class_item = $v['class_item'] ?: $extra['class_item'];
$items[] = '<div class="progress-bar bar bar-' . $type . ' progress-bar-' . $type . ($class_item ? ' ' . $class_item : '')
. '" style="width: ' . $val . '%;' . ($v['style'] ? ' ' . $v['style'] : '') . '" role="progressbar"></div>';
}
return '<div class="progress' . ($extra['class'] ? ' ' . $extra['class'] : '') . '" id="' . $extra['id'] . '">' . implode(PHP_EOL, (array) $items) . '</div>';
}
/**
* @param mixed $data
* @param mixed $extra
*/
public function pagination($data = [], $extra = [])
{
$extra['id'] = $extra['id'] ?: __FUNCTION__ . '_' . ++$this->_ids[__FUNCTION__];
if (isset($data['prev'])) {
$prev = $data['prev'];
unset($data['prev']);
}
if (isset($data['next'])) {
$next = $data['next'];
unset($data['next']);
}
$items = [];
// TODO: auto-detect current page and need of first. last
if ($prev) {
$items[] = '<li><a href="' . $prev . '">' . t('Prev') . '</a></li>';
}
foreach ((array) $data as $page => $link) {
$items[] = '<li><a href="' . $link . '">' . $page . '</a></li>';
}
if ($next) {
$items[] = '<li><a href="' . $next . '">' . t('Next') . '</a></li>';
}
if ($this->_is_bs3) {
return '<div><ul class="pagination' . ($extra['class'] ? ' ' . $extra['class'] : '') . '" id="' . $extra['id'] . '">' . implode(PHP_EOL, $items) . '</ul></div>';
}
return '<div class="pagination' . ($extra['class'] ? ' ' . $extra['class'] : '') . '" id="' . $extra['id'] . '"><ul>' . implode(PHP_EOL, $items) . '</ul></div>';
}
/**
* @param mixed $extra
*/
public function panel($extra = [])
{
$extra['id'] = $extra['id'] ?: __FUNCTION__ . '_' . ++$this->_ids[__FUNCTION__];
$extra['class'] = $extra['class'] ?: 'panel panel-default';
return
'<div class="' . implode(' ', array_filter([$extra['class'], $extra['class_add']])) . '" id="' . $extra['id'] . '">
<div class="panel-heading">
<h3 class="panel-title">' . $extra['title'] . '</h3>
</div>
<div class="panel-body">' . $extra['body'] . '</div>
</div>';
}
/**
* @param mixed $data
* @param mixed $extra
*/
public function jumbotron($data = [], $extra = [])
{
$extra['id'] = $extra['id'] ?: __FUNCTION__ . '_' . ++$this->_ids[__FUNCTION__];
return '<div class="jumbotron' . ($extra['class'] ? ' ' . $extra['class'] : '') . '" id="' . $extra['id'] . '"><h1>' . $data['head'] . '</h1>' . $data['body'] . '</div>';
}
/**
* @param mixed $body
* @param mixed $extra
*/
public function well($body = '', $extra = [])
{
$extra['id'] = $extra['id'] ?: __FUNCTION__ . '_' . ++$this->_ids[__FUNCTION__];
if ( ! $extra['class']) {
$extra['class'] = 'well-lg';
}
return '<div class="well well-lg' . ($extra['class'] ? ' ' . $extra['class'] : '') . '" id="' . $extra['id'] . '">' . $body . '</div>';
}
/**
* @param mixed $data
* @param mixed $extra
*/
public function list_group($data = [], $extra = [])
{
$extra['id'] = $extra['id'] ?: __FUNCTION__ . '_' . ++$this->_ids[__FUNCTION__];
$items = [];
foreach ((array) $data as $v) {
if ( ! is_array($v)) {
$body = $v;
$v = [];
} else {
$body = $v['body'];
}
$type = $v['type'] ?: $extra['type'];
$class_item = $v['class_item'] ?: $extra['class_item'];
$items[] = '<li class="list-group-item' . ($class_item ? ' ' . $class_item : '') . '"><span class="badge">' . $v['badge'] . '</span> ' . $body . '</li>';
}
return '<ul class="list-group' . ($extra['class'] ? ' ' . $extra['class'] : '') . '" id="' . $extra['id'] . '">' . implode(PHP_EOL, (array) $items) . '</ul>';
}
/**
* @param mixed $data
* @param mixed $extra
*/
public function media_objects($data = [], $extra = [])
{
$extra['id'] = $extra['id'] ?: __FUNCTION__ . '_' . ++$this->_ids[__FUNCTION__];
if ($data) {
$data = $this->_recursive_sort_items($data);
}
$img_class = ($extra['img_class'] ?: 'media-object') . ($extra['img_class_add'] ? ' ' . $extra['img_class_add'] : '');
$keys = array_keys($data);
$keys_counter = array_flip($keys);
$items = [];
foreach ((array) $data as $id => $item) {
$next_id = $keys[$keys_counter[$id] + 1];
$next_item = $next_id ? $data[$next_id] : [];
$close_num_levels = 1;
if ($next_item) {
$close_num_levels = $item['level'] - $next_item['level'] + 1;
if ($close_num_levels < 0) {
$close_num_levels = 0;
}
} elseif ($item['level'] > 0) {
$close_num_levels = $item['level'] + 1;
}
$items[] = '
<div class="media">
<a class="pull-left"' . ($item['link'] ? ' href="' . $item['link'] . '"' : '') . '>'
. '<img class="' . $img_class . '" alt="' . $item['alt'] . '" src="' . $item['img'] . '"' . ($item['img_width'] ? ' width="' . $item['img_width'] . '"' : '') . ($item['img_height'] ? ' height="' . $item['img_height'] . '"' : '') . '></a>
<div class="media-body">
<h4 class="media-heading">'
. ($item['link'] ? '<a href="' . $item['link'] . '">' : '') . $item['head'] . ($item['link'] ? '</a>' : '')
. ($item['date'] ? ' <small class="pull-right">' . _format_date($item['date'], $extra['date_format'] ?: 'full') . '</small>' : '')
. '</h4>'
. $item['body'] . '
';
if ($close_num_levels) {
$items[] = str_repeat(PHP_EOL . '</div></div>' . PHP_EOL, $close_num_levels);
}
}
return '<div class="media-objects' . ($extra['class'] ? ' ' . $extra['class'] : '') . '" id="' . $extra['id'] . '">' . implode(PHP_EOL, (array) $items) . '</div>';
}
/**
* @param mixed $data
* @param mixed $extra
*/
public function menu($data = [], $extra = [])
{
$extra['id'] = $extra['id'] ?: __FUNCTION__ . '_' . ++$this->_ids[__FUNCTION__];
if ($data) {
$data = $this->_recursive_sort_items($data);
}
$keys = array_keys($data);
$keys_counter = array_flip($keys);
$items = [];
$ul_opened = false;
foreach ((array) $data as $id => $item) {
$next_item = $data[$keys[$keys_counter[$id] + 1]];
$has_children = false;
$close_li = 1;
$close_ul = 0;
if ($next_item) {
if ($next_item['level'] > $item['level']) {
$has_children = true;
}
$close_li = $item['level'] - $next_item['level'] + 1;
if ($close_li < 0) {
$close_li = 0;
}
}
$badge = $item['badge'] ? ' <sup class="badge badge-' . ($item['class_badge'] ?: 'info') . '">' . $item['badge'] . '</sup>' : '';
$items[] = '
<li class="dropdown">
<a href="' . $item['link'] . '" class="dropdown-toggle">' . $item['name'] . $badge . ($has_children ? ' <b class="caret"></b>' : '') . '</a>';
if ($has_children) {
$ul_opened = true;
$items[] = PHP_EOL . '<ul class="dropdown-menu sub-menu">' . PHP_EOL;
} elseif ($close_li) {
if ($ul_opened && ! $has_children && $item['level'] != $next_item['level']) {
$ul_opened = false;
$close_ul = 1;
}
$tmp = str_repeat(PHP_EOL . ($close_ul ? '</li></ul>' : '</li>') . PHP_EOL, $close_li);
if ($close_li > 1 && $close_ul) {
$tmp = substr($tmp, 0, -strlen('</ul>' . PHP_EOL)) . PHP_EOL;
}
$items[] = $tmp;
}
}
return '<div class="navbar navbar-default' . ($extra['class'] ? ' ' . $extra['class'] : '') . '" id="' . $extra['id'] . '">
<div class="navbar-inner navbar-header">
<ul class="nav navbar-nav">' . implode(PHP_EOL, (array) $items) . '</ul>
</div>
</div>';
}
/**
* @param mixed $data
* @param mixed $extra
*/
public function grid($data = [], $extra = [])
{
$extra['id'] = $extra['id'] ?: __FUNCTION__ . '_' . ++$this->_ids[__FUNCTION__];
$rows = [];
$ul_opened = false;
foreach ((array) $data as $id => $row) {
$items = [];
$row_col = count((array) $row) ? floor(12 / count((array) $row)) : 1;
if ($row_col < 1) {
$row_col = 1;
}
foreach ((array) $row as $rid => $item) {
$body = $item[0] ?: $item['body'];
$col = $item[1] ?: $item['col'];
$class = $item['class'];
if ( ! $col) {
$col = $row_col;
}
$items[] = '<div class="span' . $col . ' col-md-' . $col . ($class ? ' ' . $class : '') . '">' . $body . '</div>';
}
$rows[] = '<div class="row-fluid show-grid">' . implode(PHP_EOL, $items) . '</div>';
}
return '<div class="grid' . ($extra['class'] ? ' ' . $extra['class'] : '') . '" id="' . $extra['id'] . '">' . implode(PHP_EOL, (array) $rows) . '</div>';
}
/**
* @param mixed $data
* @param mixed $extra
*/
public function navlist($data = [], $extra = [])
{
$extra['id'] = $extra['id'] ?: __FUNCTION__ . '_' . ++$this->_ids[__FUNCTION__];
$items = [];
foreach ((array) $data as $k => $v) {
if ( ! is_array($v)) {
$name = $v;
$link = $k;
$v = [];
} else {
$name = $v['name'];
$link = $v['link'];
}
$class_item = $v['class_item'] ?: $extra['class_item'];
$badge = $v['badge'] ? ' <sup class="badge badge-' . ($v['class_badge'] ?: 'info') . '">' . $v['badge'] . '</sup>' : '';
$items[] = '<li class="' . ($class_item ? ' ' . $class_item : '') . '"><a href="' . $link . '"><i class="icon-chevron-right fa fa-chevron-right"></i> ' . t($name) . $badge . '</a></li>';
}
return '<div class="bs-docs-sidebar"><ul class="nav nav-list bs-docs-sidenav' . ($extra['class'] ? ' ' . $extra['class'] : '') . '" id="' . $extra['id'] . '">' . implode(PHP_EOL, (array) $items) . '</ul></div>';
}
/**
* @param mixed $data
* @param mixed $extra
*/
public function li($data = [], $extra = [])
{
$extra['id'] = $extra['id'] ?: __FUNCTION__ . '_' . ++$this->_ids[__FUNCTION__];
$items = [];
foreach ((array) $data as $v) {
if ( ! is_array($v)) {
$body = $v;
$v = [];
} else {
$body = $v['body'] ?: $v['name'];
}
if ( ! strlen($body)) {
continue;
}
$class_item = $v['class'] ?: $extra['class_item'];
$badge = $v['badge'] ? ' <sup class="badge badge-' . ($v['class_badge'] ?: 'info') . '">' . $v['badge'] . '</sup>' : '';
$items[] = '<li class="' . ($class_item ? ' ' . $class_item : '') . '"' . ($v['id'] ? ' id="' . $v['id'] . '"' : '') . '>' . $badge . ($v['link'] ? '<a href="' . $v['link'] . '">' . $body . '</a>' : $body) . '</li>';
if (is_array($v['sub'])) {
$items[] = $this->li($v['sub'], $extra);
continue;
}
}
return '<ul' . _attrs(['id', 'class', 'style'], $extra) . '>' . implode(PHP_EOL, (array) $items) . '</ul>';
}
/**
* @param mixed $data
* @param mixed $extra
*/
public function tree($data = [], $extra = [])
{
return _class('html_tree', 'classes/html/')->tree($data, $extra);
}
/**
* @param mixed $data
* @param mixed $extra
*/
public function li_tree($data = [], $extra = [])
{
return _class('html_tree', 'classes/html/')->li_tree($data, $extra);
}
/**
* @param mixed $name
* @param mixed $values
* @param mixed $selected
* @param mixed $show_text
* @param mixed $type
* @param mixed $add_str
* @param mixed $translate
* @param mixed $level
*/
public function select_box($name, $values = [], $selected = '', $show_text = false, $type = 2, $add_str = '', $translate = 0, $level = 0)
{
// Passing params as array
if (is_array($name)) {
$extra = (array) $extra + $name;
$name = $extra['name'];
}
$values = isset($extra['values']) ? $extra['values'] : (array) $values; // Required
$translate = isset($extra['translate']) ? $extra['translate'] : $translate;
if ($extra['no_translate']) {
$translate = 0;
}
$selected = isset($extra['selected']) ? $extra['selected'] : $selected;
$show_text = isset($extra['show_text']) ? $extra['show_text'] : ($show_text !== null ? $show_text : false);
$type = isset($extra['type']) ? $extra['type'] : ($type !== null ? $type : 2);
$level = isset($extra['level']) ? $extra['level'] : $level;
// (example: $add_str = 'size=6')
$add_str = isset($extra['add_str']) ? $extra['add_str'] : $add_str;
$extra['class'] = isset($extra['class']) ? $extra['class'] : $this->CLASS_SELECT_BOX;
$extra['class_add'] && $extra['class'] = trim($extra['class'] . ' ' . $extra['class_add']);
if ( ! $values && @ ! $extra['ajax']) {
return false;
}
if ($extra['disabled']) {
$extra['disabled'] = 'disabled';
}
$body = [];
if ($level == 0) {
$extra['force_id'] && $id = $extra['force_id'];
$id = $id ?: __FUNCTION__ . '_' . ++$this->_ids[__FUNCTION__];
if ($this->AUTO_ASSIGN_IDS) {
$extra['id'] = $id;
}
if ($extra['outer_label']) {
$body[] = '<label class="outer-label">' . $extra['outer_label'] . '</label>';
}
$extra['name'] = $name;
$body[] = '<select' . _attrs($extra, ['name', 'id', 'class', 'style', 'disabled', 'required']) . ($add_str ? ' ' . $add_str : '') . '>';
}
$selected = (string) $selected;
if ($show_text && $level == 0) {
$def_opt_text = $show_text;
if ($show_text == 1) {
$def_opt_text = str_replace(['%name%', '%select%'], [t($name), t('Select')], $this->SELECT_BOX_DEF_OPT_TPL);
}
$body[] = '<option value="" class="' . $this->CLASS_SELECT_OPTION_DEFAULT . '">' . $def_opt_text . '</option>';
}
$self_func = __FUNCTION__;
$option_callback = $extra['option_callback'];
$use_option_callback = is_callable($option_callback);
foreach ((array) $values as $key => $cur_value) {
if (is_array($cur_value)) {
$body[] = '<optgroup label="' . $key . '" title="' . ($translate ? t($key) : $key) . '">';
$body[] = $this->$self_func($name, $cur_value, $selected, $show_text, $type, $add_str, $translate, $level + 1);
$body[] = '</optgroup>';
} else {
$_what_compare = (string) ($type == 1 ? $cur_value : $key);
$is_selected = ($_what_compare == $selected);
$text = $translate ? t($cur_value) : $cur_value;
if ($use_option_callback) {
$body[] = $option_callback($key, $cur_value, $is_selected, $text, $extra);
} else {
$body[] = '<option value="' . $key . '"' . ($is_selected ? ' selected="selected"' : '') . '>' . $text . '</option>';
}
}
}
$body[] = $level == 0 ? '</select>' : '';
return implode(PHP_EOL, $body);
}
/**
* @param mixed $name
* @param mixed $values
* @param mixed $selected
* @param mixed $show_text
* @param mixed $type
* @param mixed $add_str
* @param mixed $translate
* @param mixed $level
* @param mixed $disabled
*/
public function multi_select($name, $values = [], $selected = '', $show_text = false, $type = 2, $add_str = '', $translate = 0, $level = 0, $disabled = false)
{
// Passing params as array
if (is_array($name)) {
$extra = (array) $extra + $name;
$name = $extra['name'];
}
$values = isset($extra['values']) ? $extra['values'] : (array) $values; // Required
$translate = isset($extra['translate']) ? $extra['translate'] : $translate;
if ($extra['no_translate']) {
$translate = 0;
}
$selected = isset($extra['selected']) ? $extra['selected'] : $selected;
$show_text = isset($extra['show_text']) ? $extra['show_text'] : ($show_text !== null ? $show_text : false);
$type = isset($extra['type']) ? $extra['type'] : ($type !== null ? $type : 2);
$level = isset($extra['level']) ? $extra['level'] : $level;
// (example: $add_str = 'size=6') disabled
$add_str = isset($extra['add_str']) ? $extra['add_str'] : $add_str;
$extra['class'] = isset($extra['class']) ? $extra['class'] : $this->CLASS_SELECT_BOX;
$extra['class_add'] && $extra['class'] = trim($extra['class'] . ' ' . $extra['class_add']);
if ( ! $values) {
return false;
}
if ($extra['disabled'] || $disabled) {
$extra['disabled'] = 'disabled';
}
if ( ! is_array($selected)) {
$selected = (string) $selected;
}
$body = [];
if ($level == 0) {
$extra['force_id'] && $id = $extra['force_id'];
$id = $id ?: __FUNCTION__ . '_' . ++$this->_ids[__FUNCTION__];
if ($this->AUTO_ASSIGN_IDS) {
$extra['id'] = $id;
}
if ($extra['outer_label']) {
$body[] = '<label class="outer-label">' . $extra['outer_label'] . '</label>';
}
$extra['multiple'] = 'multiple';
$extra['name'] = $name ? $name . '[]' : '';
$body[] = '<select' . _attrs($extra, ['name', 'id', 'class', 'style', 'multiple', 'disabled', 'required']) . ($add_str ? ' ' . trim($add_str) : '') . '>';
}
if ($show_text && $level == 0) {
$def_opt_text = $show_text;
if ($show_text == 1) {
$def_opt_text = str_replace(['%name%', '%select%'], [t($name), t('Select')], $this->SELECT_BOX_DEF_OPT_TPL);
}
$body[] = '<option value="" class="' . $this->CLASS_SELECT_OPTION_DEFAULT . '">' . $def_opt_text . '</option>';
}
$self_func = __FUNCTION__;
foreach ((array) $values as $key => $value) {
if (is_array($value)) {
$body[] = '<optgroup label="' . $key . '" title="' . ($translate ? t($key) : $key) . '">';
$body[] = $this->$self_func($name, $value, $selected, $show_text, $type, $add_str, $translate, $level + 1);
$body[] = '</optgroup>';
} else {
// Selected value could be an array
if (is_array($selected)) {
if ($type == 1) {
$sel_text = in_array($key, $selected) ? 'selected="selected"' : '';
} else {
$sel_text = isset($selected[$key]) ? 'selected="selected"' : '';
}
} elseif (strlen($selected)) {
$_what_compare = (string) ($type == 1 ? $value : $key);
$sel_text = $_what_compare == $selected ? 'selected="selected"' : '';
} else {
$sel_text = '';
}
$body[] = '<option value="' . $key . '"' . ($sel_text ? ' ' . $sel_text : '') . '>' . ($translate ? t($value) : $value) . '</option>';
}
}
$body[] = $level == 0 ? '</select>' : '';
return implode(PHP_EOL, $body);
}
/**
* Alias.
* @param mixed $name
* @param mixed $values
* @param mixed $selected
* @param mixed $show_text
* @param mixed $type
* @param mixed $add_str
* @param mixed $translate
* @param mixed $level
* @param mixed $disabled
*/
public function multi_select_box($name, $values = [], $selected = '', $show_text = false, $type = 2, $add_str = '', $translate = 0, $level = 0, $disabled = false)
{
return $this->multi_select($name, $values, $selected, $show_text, $type, $add_str, $translate, $level, $disabled);
}
/**
* @param mixed $name
* @param mixed $values
* @param null|mixed $selected
*/
public function button_yes_no_box($name, $values = [], $selected = null)
{
$def_cls = $this->CLASS_LABEL_BTN_RADIO;
$values = [
['class' => $def_cls . ' btn-warning', 'html' => '<i class="fa fa-ban"></i> ' . t('No') . '</span>'],
['class' => $def_cls . ' btn-success', 'html' => '<i class="fa fa-check"></i> ' . t('Yes') . '</span>'],
];
return $this->button_radio_box($name, $values, $selected);
}
/**
* @param mixed $name
* @param mixed $values
* @param null|mixed $selected
*/
public function button_allow_deny_box($name, $values = [], $selected = null)
{
$def_cls = $this->CLASS_LABEL_BTN_RADIO;
$values = [
['class' => $def_cls . ' btn-warning', 'html' => '<i class="fa fa-ban"></i> ' . t('Deny') . '</span>'],
['class' => $def_cls . ' btn-success', 'html' => '<i class="fa fa-check"></i> ' . t('Allow') . '</span>'],
];
return $this->button_radio_box($name, $values, $selected);
}
/**
* @param mixed $name
* @param mixed $values
* @param null|mixed $selected
* @param mixed $extra
*/
public function button_radio_box($name, $values = [], $selected = null, $extra = [])
{
if (is_array($name)) {
$extra = (array) $extra + $name;
$name = $extra['name'];
}
! is_array($extra) && $extra = [];
$label_extra = $extra['label_extra'];
$extra = [
'name' => $name ?: $extra['name'],
'values' => isset($values) ? $values : $extra['values'],
'selected' => isset($selected) ? $selected : $extra['selected'],
'use_stpl' => false,
'label_extra' => [
'class' => ($label_extra['class'] ?: $this->CLASS_LABEL_BTN_RADIO) . ($extra['horizontal'] ? ' ' . $this->CLASS_LABEL_RADIO_INLINE : ''),
],
] + $extra;
$label_right = $extra['label_right'] ? '<label class="text"> <small>' . $extra['desc'] . '</small></label>' : '';
return '<div class="btn-group" data-toggle="buttons">' . $this->radio_box($extra) . $label_right . '</div>';
}
/**
* @param mixed $name
* @param mixed $values
* @param mixed $selected
*/
public function button_check_box($name, $values = [], $selected = '')
{
if (is_array($name)) {
$extra = (array) $extra + $name;
$name = $extra['name'];
}
! is_array($extra) && $extra = [];
$label_extra = $extra['label_extra'];
$extra = [
'name' => $name,
'values' => $values,
'selected' => $selected,
'use_stpl' => false,
'label_extra' => [
'class' => ($label_extra['class'] ?: $this->CLASS_LABEL_BTN_CHECKBOX),
],
] + $extra;
$label_right = $extra['label_right'] ? '<label class="text"> <small>' . $extra['desc'] . '</small></label>' : '';
return '<div class="btn-group" data-toggle="buttons">' . $this->check_box($extra) . $label_right . '</div>';
}
/**
* @param mixed $name
* @param mixed $values
* @param mixed $selected
* @param mixed $horizontal
* @param mixed $type
* @param mixed $add_str
* @param mixed $translate
*/
public function radio_box($name, $values = [], $selected = '', $horizontal = true, $type = 2, $add_str = '', $translate = 0)
{
if (is_array($name)) {
$extra = (array) $extra + $name;
$name = $extra['name'];
}
$values = isset($extra['values']) ? $extra['values'] : (array) $values; // Required
$translate = isset($extra['translate']) ? $extra['translate'] : $translate;
if ($extra['no_translate']) {
$translate = 0;
}
$selected = isset($extra['selected']) ? $extra['selected'] : $selected;
$type = isset($extra['type']) ? $extra['type'] : ($type !== null ? $type : 2);
$horizontal = isset($extra['horizontal']) ? $extra['horizontal'] : $horizontal;
$add_str = isset($extra['add_str']) ? $extra['add_str'] : $add_str;
if ($extra['class_add']) {
$add_str .= ' class="' . trim($extra['class'] . ' ' . $extra['class_add']) . '" ';
}
if ($extra['style']) {
$add_str .= ' style="' . $extra['style'] . '" ';
}
if ( ! $values) {
return false;
}
$selected = (string) $selected;
$id_prefix = __FUNCTION__ . '_' . ++$this->_ids[__FUNCTION__];
$extra['force_id'] && $id_prefix = $extra['force_id'];
$counter = 0;
$body = [];
if ($extra['outer_label']) {
$body[] = '<label class="outer-label">' . $extra['outer_label'] . '</label>';
}
$orig_extra = $extra;
$use_stpl = isset($extra['use_stpl']) ? $extra['use_stpl'] : $this->BOXES_USE_STPL;
foreach ((array) $values as $value => $val_name) {
$label_extra_class = '';
if (is_array($val_name)) {
$extra = (array) $orig_extra + (array) $val_name['extra'];
$label_extra_class = $val_name['class'];
$val_name = $val_name['html'];
}
$is_selected = ((string) ($type == 1 ? $val_name : $value) == $selected);
$id = $id_prefix . '_' . ++$counter;
if ($use_stpl) {
$body[] = tpl()->parse('system/common/radio_box_item', [
'name' => $name,
'value' => $value,
'selected' => $is_selected ? 'checked="checked"' : '',
'add_str' => $add_str,
'label' => $translate ? t($val_name) : $val_name,
'horizontal' => (int) ((bool) $horizontal),
'id' => $id,
'extra' => $extra,
]);
} else {
$label_extra = $extra['label_extra'];
$label_extra['class'] = ($label_extra_class ?: $label_extra['class'] ?: $this->CLASS_LABEL_RADIO) . ($horizontal ? ' ' . $this->CLASS_LABEL_RADIO_INLINE : '');
if ($extra['class_add_label_radio']) {
$label_extra['class'] .= ' ' . $extra['class_add_label_radio'];
}
if ($is_selected) {
$label_extra['class'] .= ' ' . $this->CLASS_LABEL_RADIO_SELECTED;
}
$body[] =
'<label' . _attrs($label_extra, ['id', 'class', 'style']) . '>'
. '<input type="radio" name="' . $name . '" id="' . $id . '" value="' . $value . '"' . ($add_str ? ' ' . trim($add_str) : '') . ($is_selected ? ' checked="checked"' : '') . '>'
. '<span>' . t($val_name) . '</span>'
. '</label>' . PHP_EOL;
}
}
return implode(PHP_EOL, $body);
}
/**
* Simple check box.
* @param mixed $name
* @param mixed $value
* @param mixed $selected
* @param mixed $add_str
* @param mixed $extra
*/
public function check_box($name = '', $value = '', $selected = '', $add_str = '', $extra = [])
{
if (is_array($name)) {
$extra = (array) $extra + $name;
$name = $extra['name'];
}
if ( ! is_array($extra)) {
$extra = [];
}
$extra['name'] = strlen($name) ? $name : (strlen($extra['name']) ? $extra['name'] : 'checkbox');
$extra['value'] = strlen($value) ? $value : (strlen($extra['value']) ? $extra['value'] : '1');
$selected = isset($extra['selected']) ? $extra['selected'] : $selected;
if (isset($extra['checked'])) {
$selected = $extra['checked'];
}
$extra['checked'] = $selected ? 'checked' : null;
$extra['id'] = ($extra['force_id'] ?: $extra['id']) ?: ($this->AUTO_ASSIGN_IDS ? __FUNCTION__ . '_' . ++$this->_ids[__FUNCTION__] : null);
$extra['desc'] = isset($extra['desc']) ? $extra['desc'] : ucfirst(str_replace('_', '', $extra['name']));
if ($extra['no_desc']) {
$extra['desc'] = '';
}
$extra['class'] = trim($extra['class'] . ' ' . $extra['class_add']);
$add_str = $extra['add_str'] ? $extra['add_str'] : $add_str;
$translate = $extra['translate'] ? $extra['translate'] : $translate;
$label_extra = $extra['label_extra'];
$def_label_class = $this->CLASS_LABEL_CHECKBOX . ' ' . $this->CLASS_LABEL_CHECKBOX_INLINE;
$label_extra['class'] = isset($label_extra['class']) ? $label_extra['class'] : (isset($extra['class_label_checkbox']) ? $extra['class_label_checkbox'] : $def_label_class);
if ($extra['class_add_label_checkbox']) {
$label_extra['class'] .= ' ' . $extra['class_add_label_checkbox'];
}
if ($selected) {
$label_extra['class'] .= ' ' . $this->CLASS_LABEL_CHECKBOX_SELECTED;
}
$body = [];
if ($extra['outer_label']) {
$body[] = '<label class="outer-label">' . $extra['outer_label'] . '</label>';
}
$extra['type'] = 'checkbox';
$body[] = '<label' . _attrs($label_extra, ['id', 'class', 'style']) . '>'
. '<input' . _attrs($extra, ['type', 'name', 'id', 'value', 'checked', 'class', 'style', 'disabled', 'required']) . ($add_str ? ' ' . $add_str : '')
. '> <span>' . ($translate ? t($extra['desc']) : $extra['desc']) . '</span>' // Please do not remove whitespace before :)
. '</label>';
return implode(PHP_EOL, $body);
}
/**
* Processing many checkboxes at one time.
* @param mixed $name
* @param mixed $values
* @param mixed $selected
* @param mixed $horizontal
* @param mixed $type
* @param mixed $add_str
* @param mixed $translate
* @param mixed $name_as_array
*/
public function multi_check_box($name, $values = [], $selected = [], $horizontal = true, $type = 2, $add_str = '', $translate = 0, $name_as_array = false)
{
if (is_array($name)) {
$extra = (array) $extra + $name;
$name = $extra['name'];
}
$values = isset($extra['values']) ? $extra['values'] : (array) $values; // Required
$translate = isset($extra['translate']) ? $extra['translate'] : 0;
if ($extra['no_translate']) {
$translate = 0;
}
$selected = $extra['selected'];
$type = isset($extra['type']) ? $extra['type'] : ($type !== null ? $type : 2);
$horizontal = isset($extra['horizontal']) ? $extra['horizontal'] : $horizontal;
$name_as_array = isset($extra['name_as_array']) ? $extra['name_as_array'] : false;
$add_str = isset($extra['add_str']) ? $extra['add_str'] : '';
if ($extra['class']) {
$add_str .= ' class="' . trim($extra['class'] . ' ' . $extra['class_add']) . '" ';
}
if ($extra['style']) {
$add_str .= ' style="' . $extra['style'] . '" ';
}
if ( ! $values) {
return false;
}
if ( ! is_array($selected)) {
$selected = (string) $selected;
}
$body = [];
if ($extra['outer_label']) {
$body[] = '<label class="outer-label">' . $extra['outer_label'] . '</label>';
}
foreach ((array) $values as $key => $value) {
$sel_text = '';
// Selected value could be an array
if (is_array($selected)) {
if ($type == 1) {
$sel_text = in_array($value, $selected) ? 'checked="checked"' : '';
} else {
$sel_text = isset($selected[$key]) ? 'checked="checked"' : '';
}
} elseif (strlen($selected)) {
$_what_compare = (string) ($type == 1 ? $value : $key);
$sel_text = $_what_compare == $selected ? 'checked="checked"' : '';
} else {
$sel_text = '';
}
$is_selected = strlen($sel_text) ? 1 : 0;
if ($name_as_array) {
$val_name = $name . '[' . $key . ']';
} else {
$val_name = $name . '_' . $key;
}
$label_extra = $extra['label_extra'];
$label_extra['class'] = isset($label_extra['class']) ? $label_extra['class'] : (isset($extra['class_label_checkbox']) ? $extra['class_label_checkbox'] : $this->CLASS_LABEL_CHECKBOX);
if ($horizontal) {
$label_extra['class'] .= ' ' . $this->CLASS_LABEL_CHECKBOX_INLINE;
}
if ($extra['class_add_label_checkbox']) {
$label_extra['class'] .= ' ' . $extra['class_add_label_checkbox'];
}
if ($is_selected) {
$label_extra['class'] .= ' ' . $this->CLASS_LABEL_CHECKBOX_SELECTED;
}
$id = __FUNCTION__ . '_' . ++$this->_ids[__FUNCTION__];
if ($extra['no_desc']) {
$desc = '';
} else {
$desc = ($translate ? t($value) : $value);
}
if ($this->BOXES_USE_STPL) {
$body[] = tpl()->parse('system/common/check_box_item', [
'name' => $val_name,
'value' => $key,
'desc' => $desc,
'selected' => $sel_text,
'add_str' => $add_str,
'label' => $translate ? t($value) : $value,
'id' => $id,
'extra' => $extra,
]);
} else {
$body[] = '<label' . _attrs($label_extra, ['id', 'class', 'style']) . '>'
. '<input type="checkbox" name="' . $val_name . '" id="' . $id . '" value="' . $key . '"'
. ($is_selected ? ' ' . $sel_text : '') . ($add_str ? ' ' . trim($add_str) : '')
. '> ' . '<span>' . $desc . '</span>' // Please do not remove whitespace :)
. '</label>';
}
}
return implode(PHP_EOL, $body);
}
/**
* Simple input form control.
* @param mixed $name
* @param mixed $value
* @param mixed $extra
*/
public function input($name = '', $value = '', $extra = [])
{
if (is_array($name)) {
$extra = (array) $extra + $name;
$name = $extra['name'];
}
if ( ! is_array($extra)) {
$extra = [];
}
$extra['name'] = $extra['name'] ?: ($name ?: 'text');
$extra['value'] = $extra['value'] ?: $value;
$extra['id'] = $extra['id'] ?: __FUNCTION__ . '_' . ++$this->_ids[__FUNCTION__];
$extra['desc'] = $extra['desc'] ?: ucfirst(str_replace('_', '', $extra['name']));
$extra['type'] = $extra['type'] ?: 'text';
$extra['placeholder'] = $extra['placeholder'] ? t($extra['placeholder']) : $extra['desc'];
$extra['class'] = isset($extra['class']) ? $extra['class'] : $this->CLASS_INPUT;
if ($extra['class_add']) {
$extra['class'] = trim($extra['class'] . ' ' . $extra['class_add']);
}
$attrs_names = ['name', 'type', 'id', 'class', 'style', 'placeholder', 'value', 'data', 'size', 'maxlength', 'pattern', 'disabled', 'required', 'autocomplete', 'accept', 'target', 'autofocus', 'title', 'min', 'max', 'step', 'readonly'];
return '<input' . _attrs($extra, $attrs_names) . '>';
}
/**
* Simple textarea form control.
* @param mixed $name
* @param mixed $value
* @param mixed $extra
*/
public function textarea($name = '', $value = '', $extra = [])
{
if (is_array($name)) {
$extra = (array) $extra + $name;
$name = $extra['name'];
}
if ( ! is_array($extra)) {
$extra = [];
}
$extra['name'] = $extra['name'] ?: ($name ?: 'text');
$extra['value'] = $extra['value'] ?: $value;
$extra['id'] = $extra['id'] ?: __FUNCTION__ . '_' . ++$this->_ids[__FUNCTION__];
$extra['desc'] = $extra['desc'] ?: ucfirst(str_replace('_', '', $extra['name']));
$extra['type'] = $extra['type'] ?: 'text';
$extra['placeholder'] = $extra['placeholder'] ? t($extra['placeholder']) : $extra['desc'];
$extra['contenteditable'] = ( ! isset($extra['contenteditable']) || $extra['contenteditable']) ? 'true' : false;
$attrs_names = ['id', 'name', 'placeholder', 'contenteditable', 'class', 'style', 'cols', 'rows', 'title', 'required', 'size', 'disabled', 'readonly', 'autocomplete', 'autofocus'];
return '<textarea' . _attrs($extra, $attrs_names) . '>' . ( ! isset($extra['no_escape']) ? _htmlchars($extra['value']) : $extra['value']) . '</textarea>';
}
/**
* @param mixed $name
* @param mixed $values
* @param mixed $selected
* @param mixed $extra
*/
public function div_box($name, $values = [], $selected = '', $extra = [])
{
if (is_array($name)) {
$extra = (array) $extra + $name;
$name = $extra['name'];
}
$desc = $extra['desc'] ? $extra['desc'] : ucfirst(str_replace('_', '', $name));
$values = isset($extra['values']) ? $extra['values'] : (array) $values; // Required
$translate = isset($extra['translate']) ? $extra['translate'] : 0;
if ($extra['no_translate']) {
$translate = 0;
}
$selected = $extra['selected'] ?: $selected;
$extra['id'] = $extra['id'] ?: __FUNCTION__ . '_' . ++$this->_ids[__FUNCTION__];
if ( ! $values) {
return false;
}
$selected = (string) $selected;
$items = [];
$selected_val = '';
foreach ((array) $values as $key => $cur_value) {
$_what_compare = (string) ($type == 1 ? $cur_value : $key);
$is_selected = $_what_compare == $selected;
$val = ($translate ? t($cur_value) : $cur_value);
$items[] = '<li class="dropdown' . ($is_selected ? ' active' : '') . '"><a data-value="' . $key . '"' . ($is_selected ? ' data-selected="selected"' : '') . '>' . $val . '</a></li>';
if ($is_selected) {
$selected_val = $val;
}
}
$body = [];
$body[] = '<li class="dropdown" style="list-style-type:none;" id="' . $extra['id'] . '">';
$body[] = '<a class="dropdown-toggle" data-toggle="dropdown">' . ($selected_val ?: $desc) . ' <span class="caret"></span></a>';
$body[] = '<ul class="dropdown-menu">';
foreach ($items as $v) {
$body[] = $v;
}
$body[] = '</ul>';
$body[] = '</li>';
return implode(PHP_EOL, $body);
}
/**
* @param mixed $name
* @param mixed $values
* @param mixed $selected
* @param mixed $extra
*/
public function button_box($name, $values = [], $selected = '', $extra = [])
{
if (is_array($name)) {
$extra = (array) $extra + $name;
$name = $extra['name'];
}
$desc = isset($extra['desc']) ? $extra['desc'] : ucfirst(str_replace('_', '', $name));
$values = isset($extra['values']) ? $extra['values'] : (array) $values; // Required
$translate = isset($extra['translate']) ? $extra['translate'] : 0;
if ($extra['no_translate']) {
$translate = 0;
}
$selected = isset($extra['selected']) ? $extra['selected'] : $selected;
$extra['id'] = $extra['id'] ?: __FUNCTION__ . '_' . ++$this->_ids[__FUNCTION__];
if ( ! $values) {
return false;
}
$selected = (string) $selected;
$items = [];
$selected_val = '';
foreach ((array) $values as $key => $cur_value) {
$_what_compare = (string) ($type == 1 ? $cur_value : $key);
$is_selected = $_what_compare == $selected;
$val = $translate ? t($cur_value) : $cur_value;
$items[] = '<li class="dropdown' . ($is_selected ? ' active' : '') . '"><a data-value="' . $key . '"' . ($is_selected ? ' data-selected="selected"' : '') . '>' . $val . '</a></li>';
if ($is_selected) {
$selected_val = $val;
}
}
$class = $extra['class'] ?: 'btn dropdown-toggle';
$extra['class_add'] && $class .= ' ' . $extra['class_add'];
$text = $selected_val ?: $desc;
$body = [];
$body[] = '<div class="btn-group" id="' . $extra['id'] . '">';
if ($extra['button_split']) {
$body[] = '<button class="btn">' . $text . '</button>';
$body[] = '<button class="' . $class . '" data-toggle="dropdown"><span class="caret"></span></button>';
} else {
$body[] = '<button class="' . $class . '" data-toggle="dropdown">' . $text . ' <span class="caret"></span></button>';
}
$body[] = '<ul class="dropdown-menu">';
foreach ($items as $v) {
$body[] = $v;
}
$body[] = '</ul>';
$body[] = '</div>';
return implode(PHP_EOL, $body);
}
/**
* @param mixed $name
* @param mixed $values
* @param mixed $selected
* @param mixed $extra
*/
public function button_split_box($name, $values = [], $selected = '', $extra = [])
{
$extra['button_split'] = true;
return $this->button_box($name, $values, $selected, $extra);
}
/**
* @param mixed $name
* @param mixed $values
* @param mixed $selected
* @param mixed $extra
*/
public function list_box($name, $values = [], $selected = '', $extra = [])
{
if (is_array($name)) {
$extra = (array) $extra + $name;
$name = $extra['name'];
}
$desc = isset($extra['desc']) ? $extra['desc'] : ucfirst(str_replace('_', '', $name));
$values = isset($extra['values']) ? $extra['values'] : (array) $values; // Required
$translate = isset($extra['translate']) ? $extra['translate'] : 0;
if ($extra['no_translate']) {
$translate = 0;
}
$selected = isset($extra['selected']) ? $extra['selected'] : $selected;
$extra['id'] = $extra['id'] ?: __FUNCTION__ . '_' . ++$this->_ids[__FUNCTION__];
if ( ! $values) {
return false;
}
asset('bfh-select');
$extra['class'] = 'bfh-selectbox ' . $extra['class_add'];
$extra['data-name'] = $name;
$extra['data-value'] = (string) $selected;
$extra['data-filter'] = isset($extra['data-filter']) ? $extra['data-filter'] : (count((array) $values) > 10 ? 'true' : '');
$body .= '<div' . _attrs($extra, ['id', 'class', 'style']) . '>';
foreach ((array) $values as $key => $cur_value) {
$body .= '<div data-value="' . $key . '">' . ($translate ? t($cur_value) : $cur_value) . '</div>' . PHP_EOL;
}
$body .= '</div>';
return $body;
}
/**
* @param mixed $name
* @param mixed $values
* @param mixed $selected
* @param mixed $extra
*/
public function select2_box($name, $values = [], $selected = '', $extra = [])
{
$css = [];
$style = [];
if (is_array($name)) {
$extra = (array) $extra + $name;
} else {
$extra['name'] = $name;
}
$extra['force_id'] = $extra['force_id'] ?: __FUNCTION__ . '_' . ++$this->_ids[__FUNCTION__];
// put default js options here
$js_options = (array) $extra['js_options'] + [
'width' => 'element',
'placeholder' => @$extra['placeholder'] ?: @$extra['desc'],
];
// ajax
$js_functions = [];
if (@$extra['ajax_func']) {
foreach ((array) $extra['ajax_func'] as $key => $value) {
$js_options['ajax'][$key] = '%__' . $key . '__%';
$js_functions['"%__' . $key . '__%"'] = $value;
}
}
if (@$extra['ajax']) {
$js_options += [
'maximumSelectionSize' => 10,
'minimumInputLength' => 1,
'minimumInputLength' => 1,
'initSelection' => '%__initSelection__%',
];
$js_options['ajax'] = $extra['ajax'];
$js_options['ajax'] += [
// 'dataType' => 'json',
// 'quietMillis' => 500,
// 'cache' => true,
'data' => '%__data__%',
'results' => '%__results__%',
];
$js_functions += [
'"%__data__%"' => 'function( term, page, context ) { return { q: term, page: page }; }',
'"%__results__%"' => 'function( data, page, query ) { return { results: data.items, more: data.more || false }; }',
'"%__initSelection__%"' => 'function( element, callback ) {
var $this = $(element);
var id = $this.val();
if( id !== "" ) {
$.ajax("' . $js_options['ajax']['url'] . '" + "&q=" + id, {
dataType: "json"
}).done(function(data) { callback(data.items[0] || null); });
}
}',
];
}
asset('jq-select2');
// prepare js options
$_js_options = json_encode($js_options, JSON_PRETTY_PRINT);
$js_functions && $_js_options = str_replace(array_keys($js_functions), array_values($js_functions), $_js_options);
jquery('$("#' . addslashes($extra['force_id']) . '").select2(' . $_js_options . ');');
$func = $extra['multiple'] ? 'multi_select' : 'select_box';
if ($extra['ajax']) {
$func = 'input';
$extra['id'] = $extra['force_id'];
$extra['value'] = @$extra['selected'] ?: @$extra['value'] ?: '';
$css[] = $this->CLASS_INPUT;
}
$css[] = 'no-chosen';
$extra['class'] && $css[] = $extra['class'];
// $style[] = 'padding:0.3em';
$extra['style'] && $style[] = $extra['style'];
$extra['class'] = implode(' ', $css);
$extra['style'] = implode(';', $style);
return $this->$func($extra, $values, $selected);
}
/**
* @param mixed $name
* @param mixed $values
* @param mixed $selected
* @param mixed $extra
*/
public function chosen_box($name, $values = [], $selected = '', $extra = [])
{
if (is_array($name)) {
$extra = (array) $extra + $name;
} else {
$extra['name'] = $name;
}
$extra['force_id'] = $extra['force_id'] ?: __FUNCTION__ . '_' . ++$this->_ids[__FUNCTION__];
asset('chosen');
$js_options = (array) $extra['js_options'] + [
'disable_search_threshold' => 10,
'no_results_text' => t('No results match'),
'placeholder_text_multiple' => t('Select Some Options'),
'placeholder_text_single' => t('Select an Option'),
'search_contains' => true,
// put default js options here
];
jquery('$("#' . addslashes($extra['force_id']) . '").chosen(' . json_encode($js_options, JSON_PRETTY_PRINT) . ');');
$func = $extra['multiple'] ? 'multi_select' : 'select_box';
return $this->$func($extra, $values, $selected);
}
/**
* @param mixed $name
* @param mixed $values
* @param mixed $selected
* @param mixed $extra
*/
public function phone_box($name = 'phone', $values = [], $selected = '', $extra = [])
{
if (is_array($name)) {
$extra = (array) $extra + $name;
} else {
$extra['name'] = $name;
}
if ( ! $extra['name']) {
$name = $extra['name'] = 'phone';
}
$extra['force_id'] = $extra['force_id'] ?: __FUNCTION__ . '_' . ++$this->_ids[__FUNCTION__];
if ( ! $extra['id']) {
$extra['id'] = $extra['force_id'] . '_input';
}
asset('jquery-intl-tel-input');
$countries = [];
foreach ((array) main()->get_data('geo_countries') as $k => $data) {
$countries[] = strtolower($data['code']);
}
$preferred_countries = [
'ua', 'by', 'ru',
];
$js_options = (array) $extra['js_options'] + [
'autoPlaceholder' => true,
'onlyCountries' => $countries,
'preferredCountries' => $preferred_countries,
// 'excludeCountries' => ["us"],
// 'separateDialCode' => true,
// 'allowDropdown' => false,
// 'autoHideDialCode' => false,
// 'dropdownContainer' => "body",
// 'initialCountry' => "auto",
// 'nationalMode' => false,
// 'numberType' => "MOBILE",
// 'utilsScript' => '//cdnjs.cloudflare.com/ajax/libs/intl-tel-input/8.5.2/js/utils.js',
];
jquery('
var input_selector = "#' . addslashes($extra['id']) . '";
var phone = $(input_selector);
var reset = function() {
phone.removeClass("phone-error");
phone.removeClass("phone-success");
};
phone.intlTelInput($.merge(
' . json_encode($js_options, JSON_PRETTY_PRINT) . '
, {
geoIpLookup : function(callback) {
$.get("//ipinfo.io", function() {}, "jsonp").always(function(resp) {
var countryCode = (resp && resp.country) ? resp.country : "";
callback(countryCode);
});
}
}
));
phone.blur(function() {
reset();
if ($.trim(phone.val())) {
if (phone.intlTelInput("isValidNumber")) {
phone.addClass("phone-success");
} else {
phone.addClass("phone-error");
}
}
});
// on keyup / change flag: reset
phone.on("keyup change", reset);
$(phone).closest("form").submit(function() {
phone.val(phone.intlTelInput("getNumber"));
});
');
return $this->input($extra + [
'maxlength' => 20,
'type' => 'tel',
// 'pattern' => '^[0-9\s\(\)-]{7,20}$',
]);
}
/**
* @param mixed $name
* @param mixed $values
* @param mixed $selected
* @param mixed $extra
*/
public function image_select_box($name, $values = [], $selected = '', $extra = [])
{
if (is_array($name)) {
$extra = (array) $extra + $name;
} else {
$extra['name'] = $name;
}
$extra['force_id'] = $extra['force_id'] ?: __FUNCTION__ . '_' . ++$this->_ids[__FUNCTION__];
asset('jquery-image-picker');
asset('jquery-imagesloaded');
asset('masonry');
$extra['class_add'] = trim($extra['class_add'] . ' image-picker masonry');
$js_options = (array) $extra['js_options'] + [
// put default js options here
];
jquery('
var select_box = $("#' . addslashes($extra['force_id']) . '")
select_box.imagepicker(' . json_encode($js_options, JSON_PRETTY_PRINT) . ');
var container = select_box.next("ul.thumbnails");
container.imagesLoaded(function(){
container.masonry({
itemSelector: "li",
});
});
');
$extra['option_callback'] = function ($key, $cur_value, $is_selected, $text, $extra) {
return '<option value="' . $key . '"' . ($is_selected ? ' selected="selected"' : '') . ' data-img-src="' . $cur_value . '">' . $text . '</option>';
};
$func = $extra['multiple'] ? 'multi_select' : 'select_box';
return $this->$func($extra, $values, $selected);
}
/**
* @param mixed $name
* @param mixed $cur_date
*/
public function date_picker($name, $cur_date = '')
{
js('jquery-ui');
css('jquery-ui');
jquery('$(".datepicker").datepicker({ dateFormat: "yy-mm-dd" });');
css('//cdnjs.cloudflare.com/ajax/libs/jqueryui/1.10.4/css/jquery.ui.datepicker.min.css');
$extra['id'] = $extra['id'] ?: __FUNCTION__ . '_' . ++$this->_ids[__FUNCTION__];
// TODO: use input() unified control
return '<input type="text" name="' . $name . '" class="datepicker" value="' . $cur_date . '" style="width:80px" readonly="true" id="' . $extra['id'] . '" />';
}
/**
* @param mixed $selected
* @param mixed $years
* @param mixed $name_postfix
* @param mixed $add_str
* @param mixed $show_what
* @param mixed $show_text
* @param mixed $translate
*/
public function date_box($selected = '', $years = '', $name_postfix = '', $add_str = '', $show_what = 'ymd', $show_text = 1, $translate = 1)
{
return _class('html_datetime', 'classes/html/')->date_box($selected, $years, $name_postfix, $add_str, $show_what, $show_text, $translate);
}
/**
* @param mixed $selected
* @param mixed $name_postfix
* @param mixed $add_str
* @param mixed $show_text
* @param mixed $translate
*/
public function time_box($selected = '', $name_postfix = '', $add_str = '', $show_text = 1, $translate = 1)
{
return _class('html_datetime', 'classes/html/')->time_box($selected, $name_postfix, $add_str, $show_text, $translate);
}
/**
* @param mixed $name
* @param mixed $selected
* @param mixed $years
* @param mixed $add_str
* @param mixed $show_what
* @param mixed $show_text
* @param mixed $translate
*/
public function date_box2($name, $selected = '', $years = '', $add_str = '', $show_what = 'ymd', $show_text = 1, $translate = 1)
{
return _class('html_datetime', 'classes/html/')->date_box2($name, $selected, $years, $add_str, $show_what, $show_text, $translate);
}
/**
* @param mixed $name
* @param mixed $selected
* @param mixed $add_str
* @param mixed $show_text
* @param mixed $translate
*/
public function time_box2($name, $selected = '', $add_str = '', $show_text = 1, $translate = 1)
{
return _class('html_datetime', 'classes/html/')->time_box2($name, $selected, $add_str, $show_text, $translate);
}
/**
* @param mixed $name
* @param mixed $selected
* @param mixed $years
* @param mixed $add_str
* @param mixed $show_what
* @param mixed $show_text
* @param mixed $translate
*/
public function datetime_box2($name, $selected = '', $years = '', $add_str = '', $show_what = 'ymd', $show_text = 1, $translate = 1)
{
return _class('html_datetime', 'classes/html/')->datetime_box2($name, $selected, $years, $add_str, $show_what, $show_text, $translate);
}
/**
* @param mixed $text
* @param mixed $extra
*/
public function tooltip($text = '', $extra = [])
{
if (is_array($text)) {
$extra = (array) $extra + $text;
$text = '';
}
if ( ! is_array($extra)) {
$extra = [];
}
// css('.popover { width:auto; min-width: 100px;}');
$extra['text'] = $extra['text'] ?: $text;
$extra['icon'] = $extra['icon'] ?: 'icon icon-info-sign fa fa-question-circle';
$extra['href'] = $extra['href'] ?: '#';
$extra['class'] = ($extra['class'] ?: 'yf_tip') . ($extra['class_add'] ? ' ' . $extra['class_add'] : '');
$extra['data-content'] = $extra['data-content'] ?: _prepare_html($extra['text']);
$extra['data-toggle'] = $extra['data-toggle'] ?: 'popover';
$extra['data-container'] = $extra['data-container'] ?: 'body';
$extra['data-html'] = $extra['data-html'] ?: 'true';
return ( ! $extra['no_nbsp'] ? ' ' : '') . '<span' . _attrs($extra, ['id', 'class', 'style']) . '><i class="' . $extra['icon'] . '"></i></span>';
}
/**
* Hyperlink container.
*/
public function a()
{
$args = func_get_args();
$a = [];
// numerics params
if (isset($args[0]) && is_array($args[0])) {
$a = $args[0];
} elseif (isset($args[0])) {
$a['href'] = $args[0];
$a['title'] = $args[1];
$a['icon'] = $args[2];
$a['text'] = $args[3];
$a['class_add'] = $args[4];
$a['target'] = $args[5];
$a['no_text'] = $args[6];
// named params
} elseif (isset($args['link'])) {
$a = $args;
}
if (isset($args['extra']) && is_array($args['extra'])) {
foreach ($args['extra'] as $k => $v) {
$a[$k] = $v;
}
}
if ( ! isset($a['text'])) {
$a['text'] = $a['title'] ?: $a['href'];
}
if ($a['href'] && substr($a['href'], 0, strlen('http')) !== 'http' && substr($a['href'], 0, strlen('//')) !== '//') {
$a['href'] = url($a['href']);
}
if ( ! isset($a['class'])) {
$a['class'] = 'btn btn-default btn-mini btn-xs';
}
if ($a['class_add']) {
$a['class'] .= ' ' . $a['class_add'];
}
if ( ! isset($a['target'])) {
$a['target'] = '_blank';
}
$icon = '';
if (isset($a['icon'])) {
$icon = [];
if ( ! is_array($a['icon'])) {
$a['icon'] = [$a['icon']];
}
foreach ((array) $a['icon'] as $i) {
$icon[] = '<i class="' . $i . '"></i>';
}
$icon = implode(' ', $icon);
}
return '<a' . _attrs($a, ['href', 'title', 'class', 'style', 'id', 'rel', 'target', 'disabled']) . '>' . $icon . ($a['no_text'] ? '' : (strlen($a['text']) ? ($icon ? ' ' : '') . _prepare_html($a['text']) : '')) . '</a>';
}
/**
* Active toggler.
* @param mixed $url
* @param mixed $active
* @param mixed $extra
*/
public function btn_active($url = '', $active = 0, $extra = [])
{
! $url && $url = url('/@object/active/@id');
$pairs = [
'class' => ['btn-warning', 'btn-success'],
'icon' => ['fa fa-ban', 'fa fa-check'],
'title' => [t('Disabled'), t('Active')],
];
$class = ($extra['class'] ?: 'change_active') . ($extra['class_add'] ? ' ' . $extra['class_add'] : '');
return $extra['disabled'] ? $pairs['class'][$active] : $this->a(
$url,
$pairs['title'][$active],
$pairs['icon'][$active],
'',
$class . ' active_short ' . $pairs['class'][$active]
);
}
/**
* Icon container.
*/
public function icon()
{
$args = func_get_args();
$a = [];
// numerics params
if (isset($args[0]) && is_array($args[0])) {
$a = $a[0];
} elseif (isset($args[0])) {
$a['icon'] = $args[0];
$a['title'] = $args[1];
$a['text'] = $args[2];
$a['class'] = $args[3];
// named params
} elseif (isset($args['icon'])) {
$a = $args;
}
if (isset($args['extra']) && is_array($args['extra'])) {
foreach ($args['extra'] as $k => $v) {
$a[$k] = $v;
}
}
if ( ! isset($a['text'])) {
$a['text'] = $a['title'];
}
if ( ! isset($a['style'])) {
$a['style'] = 'padding-right:5px';
}
return '<span style="' . $a['style'] . '" title="' . _prepare_html($a['title']) . '"><i class="' . $a['icon'] . '"></i>' . (strlen($a['text']) ? ' ' . _prepare_html($a['text']) : '') . '</span>';
}
/**
* Country container.
*/
public function country()
{
asset('bfh-select');
$args = func_get_args();
$a = [];
// numerics params
if (isset($args[0]) && is_array($args[0])) {
$a = $args[0];
} elseif (isset($args[0])) {
$a['code'] = $args[0];
$a['link'] = $args[1];
$a['class'] = $args[2];
}
if (isset($args['extra']) && is_array($args['extra'])) {
foreach ($args['extra'] as $k => $v) {
$a[$k] = $v;
}
}
$code = strtoupper($a['code']);
if ( ! $code) {
return false;
}
$name = _prepare_html($this->_get_country_name($code));
if ($a['link']) {
return a(str_replace('%code', $code, $a['link']), $code . ' | ' . $name, 'bfh-flag-' . $code, '', $a['class']);
}
return $this->icon('bfh-flag-' . $code);
}
/**
* IP container.
*/
public function ip()
{
asset('bfh-select');
$args = func_get_args();
$a = [];
// numerics params
if (isset($args[0]) && is_array($args[0])) {
$a = $args[0];
} elseif (isset($args[0])) {
$a['ip'] = $args[0];
}
if (isset($args['extra']) && is_array($args['extra'])) {
foreach ($args['extra'] as $k => $v) {
$a[$k] = $v;
}
}
$ip = $a['ip'];
$code = strtoupper($this->_get_ip_country($ip));
$name = _prepare_html($this->_get_country_name($code));
return a('http://www.infobyip.com/ip-' . urlencode($ip) . '.html', $ip . ' | ' . $code . ' | ' . $name, ($code ? 'bfh-flag-' . $code : ''), $ip, $a['class']);
}
/**
* @param mixed $ip
*/
public function _get_ip_country($ip)
{
if ( ! isset($this->_ip_to_country[$ip])) {
$func = 'geoip_country_code_by_name';
$this->_ip_to_country[$ip] = is_callable($func) ? $func($ip) : '';
}
return $this->_ip_to_country[$ip];
}
/**
* @param mixed $code
*/
public function _get_country_name($code)
{
if ( ! isset($this->_country_names)) {
$this->_country_names = db()->select('code', 'name')->from('geo_countries')->get_2d();
}
return $this->_country_names[$code];
}
/**
* @param mixed $obj
* @param mixed $items
* @param mixed $extra
*/
public function module_menu($obj, $items = [], $extra = [])
{
// TODO: check $obj for methods existance and hide not existing
// TODO: build auto-menu if items empty
$out = [];
$selected = '/' . $_GET['object'] . '/' . $_GET['action'];
$selected2 = '/@object/' . $_GET['action'];
foreach ((array) $items as $i) {
$is_selected = (strpos($i[0], $selected) === 0) || (strpos($i[0], $selected2) === 0);
$out[] = a($i[0], $i[1], $i[2], $i[3], $is_selected ? 'disabled btn-primary' : '', $i[5] ?: '', $i[6]);
}
return implode($out) . PHP_EOL;
}
}