private static function _get_field_html($name, $field_type = self::FORM_FIELD_INPUT, $properties = array(), $field_html_only = false)
 {
     $field_class_map = array(self::FORM_FIELD_INPUT => 'input', self::FORM_FIELD_FILEINPUT => 'input input-file', self::FORM_FIELD_SELECT => 'select', self::FORM_FIELD_SELECT2 => 'select', self::FORM_FIELD_MULTISELECT => 'select select-multiple', self::FORM_FIELD_TEXTAREA => 'textarea', self::FORM_FIELD_CHECKBOX => 'checkbox', self::FORM_FIELD_RADIO => 'radio', self::FORM_FIELD_RATING => 'rating', self::FORM_FIELD_RATINGS => 'rating', self::FORM_FIELD_HIDDEN => '', self::FORM_FIELD_BLANK => '');
     $result = '';
     $field_html = '';
     $result_html = '';
     $notes = '';
     $label = '';
     $attrs = array();
     switch ($field_type) {
         case self::FORM_FIELD_LABEL:
             $default_prop = array('label' => '');
             $new_prop = parent::get_clean_structure($default_prop, $properties, array(), 'label');
             $result_html = $new_prop['label'];
             break;
         case self::FORM_FIELD_BLANK:
             $default_prop = array('content' => '');
             $new_prop = parent::get_clean_structure($default_prop, $properties, array(), 'content');
             $result_html = $new_prop['content'];
             break;
         case self::FORM_FIELD_RATINGS:
             $default_prop = array('items' => array(), 'icon' => SmartUI::$icon_source . '-star');
             $new_prop = parent::get_clean_structure($default_prop, $properties, array(), 'max');
             if (!is_array($new_prop['items'])) {
                 $new_prop['items'] = array($new_prop['items']);
             }
             $items = $new_prop['items'];
             $rating_html_list = array();
             foreach ($items as $item) {
                 $item_prop = array('max' => 5, 'icon' => $new_prop['icon'], 'name' => $name . '-' . SmartUtil::create_id(), 'label' => '');
                 $new_item_prop = parent::set_array_prop_def($item_prop, $item, 'max');
                 $field_html = self::_get_field_html($new_item_prop['name'], self::FORM_FIELD_RATING, $new_item_prop, true);
                 $field_html .= $new_item_prop['label'] ? $new_item_prop['label'] : ' ';
                 $result_html = '	<div class="' . $field_class_map[$field_type] . '">';
                 $result_html .= $field_html;
                 $result_html .= '	</div>';
                 $rating_html_list[] = $result_html;
             }
             $result_html = implode('', $rating_html_list);
             break;
         case self::FORM_FIELD_RATING:
             $default_prop = array('max' => 5, 'icon' => SmartUI::$icon_source . '-star');
             $new_prop = parent::get_clean_structure($default_prop, $properties, array(), 'max');
             $rating_html_list = array();
             for ($i = $new_prop['max']; $i >= 1; $i--) {
                 $rate_id = $name . '-' . $i;
                 $rating_html = self::_get_field_html($name, self::FORM_FIELD_INPUT, array('type' => 'radio', 'id' => $rate_id), true);
                 $rating_html .= '<label for="' . $rate_id . '"><i class="' . SmartUI::$icon_source . ' ' . $new_prop['icon'] . '"></i></label>';
                 $rating_html_list[] = $rating_html;
             }
             $field_html .= implode('', $rating_html_list);
             if ($field_html_only) {
                 return $field_html;
             }
             $result_html .= '	<label class="' . $field_class_map[$field_type] . '">';
             $result_html .= $field_html;
             $result_html .= '	</label>';
             break;
         case self::FORM_FIELD_TEXTAREA:
             $default_prop = array('rows' => 3, 'attr' => array(), 'class' => array(), 'icon' => '', 'icon_append' => true, 'value' => '', 'id' => '', 'type' => '', 'placeholder' => '', 'disabled' => false, 'wrapper' => 'label');
             $new_prop = parent::get_clean_structure($default_prop, $properties, array(), 'placeholder');
             $classes = array();
             $classes[] = 'custom-scroll';
             if ($new_prop['class']) {
                 array_push($classes, $new_prop['class']);
             }
             $attrs = array();
             $attrs[] = 'class="' . implode(' ', $classes) . '"';
             $attrs[] = 'rows="' . $new_prop['rows'] . '"';
             $attrs[] = 'name="' . $name . '"';
             if ($new_prop['disabled']) {
                 $attrs[] = 'disabled="disabled"';
             }
             if ($new_prop['id']) {
                 $attrs[] = 'id="' . $new_prop['id'] . '"';
             }
             if ($new_prop['placeholder']) {
                 $attrs[] = 'placeholder="' . $new_prop['placeholder'] . '"';
             }
             if ($new_prop['attr']) {
                 $attrs[] = implode(' ', $new_prop['attr']);
             }
             if ($new_prop['icon']) {
                 $field_html .= '<i class="icon-' . ($new_prop['icon_append'] ? 'append' : 'prepend') . ' ' . SmartUI::$icon_source . ' ' . $new_prop['icon'] . '"></i>';
             }
             $field_html .= '<textarea ' . implode(' ', $attrs) . '>';
             $field_html .= $new_prop['value'];
             $field_html .= '</textarea>';
             $field_class_map[self::FORM_FIELD_TEXTAREA] = 'textarea' . ($new_prop['type'] ? ' textarea-' . $new_prop['type'] : '');
             if ($field_html_only) {
                 return $field_html;
             }
             $result_html .= '	<' . $new_prop['wrapper'] . ' class="' . $field_class_map[$field_type] . '">';
             $result_html .= $field_html;
             $result_html .= '	</' . $new_prop['wrapper'] . '>';
             break;
         case self::FORM_FIELD_MULTISELECT:
             if (isset($properties['attr'])) {
                 array_push($properties['attr'], array('multiple="multiple"', 'class="custom-scroll"'));
             } else {
                 $properties['attr'] = array('multiple="multiple"');
             }
             if (isset($properties['class'])) {
                 array_push($properties['class'], array('custom-scroll'));
             } else {
                 $properties['class'] = array('custom-scroll');
             }
             $properties['icon'] = '';
             $field_html = self::_get_field_html($name, self::FORM_FIELD_SELECT, $properties, true);
             if ($field_html_only) {
                 return $field_html;
             }
             $result_html .= '	<label class="' . $field_class_map[$field_type] . '">';
             $result_html .= $field_html;
             $result_html .= '	</label>';
             break;
         case self::FORM_FIELD_SELECT2:
             if (!is_array($properties['class'])) {
                 $properties['class'] = array($properties['class']);
             }
             array_push($properties['class'], 'select2');
             $properties['icon'] = '';
             $field_html = self::_get_field_html($name, self::FORM_FIELD_SELECT, $properties, true);
             if ($field_html_only) {
                 return $field_html;
             }
             $result_html .= '	<label class="' . $field_class_map[$field_type] . '">';
             $result_html .= $field_html;
             $result_html .= '	</label>';
             break;
         case self::FORM_FIELD_SELECT:
             $default_prop = array('data' => array(), 'display' => '', 'value' => '', 'container' => 'select', 'selected' => false, 'id' => '', 'attr' => array(), 'class' => array(), 'icon' => '<i></i>', 'item_attr' => null, 'disabled' => false);
             $get_property_value = parent::_get_property_value_func();
             $new_prop = parent::get_clean_structure($default_prop, $properties, array(), 'data');
             $data = $new_prop['data'];
             if (!is_array($data)) {
                 parent::err('SmartUI::Form "data" is required for "select" field.');
                 return '';
             }
             if (!$data) {
                 $data = array(array('No Data'));
             }
             $data = SmartUtil::object_to_array($data);
             if (!$new_prop['display']) {
                 $display_key = array_keys($data[0]);
                 $new_prop['display'] = is_array($data[0]) && $display_key ? $display_key[0] : 0;
             }
             if (!$new_prop['value']) {
                 $value_key = array_keys($data[0]);
                 $new_prop['value'] = is_array($data[0]) && $value_key ? $value_key[0] : 0;
             }
             $option_list = array();
             foreach ($data as $row) {
                 $item_attr = '';
                 if (!is_array($row)) {
                     $row = array($row);
                 }
                 $selected = $row[$new_prop['value']] == $new_prop['selected'];
                 if (isset($new_prop['item_attr'])) {
                     $item_attr = $get_property_value($new_prop['item_attr'], array('if_closure' => function ($item_attr) use($row) {
                         return SmartUtil::run_callback($row);
                     }, 'if_array' => function ($item_attr) use($row) {
                         $attrs = array();
                         foreach ($item_attr as $attr) {
                             $attrs[] = SmartUtil::replace_col_codes($attr, $row);
                         }
                         return implode(' ', $attrs);
                     }, 'if_other' => function ($item_attr) use($row) {
                         return SmartUtil::replace_col_codes($item_attr, $row);
                     }));
                 }
                 $option_list[] = '<option value="' . $row[$new_prop['value']] . '"' . ($selected ? ' selected' : '') . ($item_attr ? ' ' . $item_attr : '') . '>' . $row[$new_prop['display']] . '</option>';
             }
             $attrs = array();
             $attrs[] = 'name="' . $name . '"';
             if ($new_prop['disabled']) {
                 $attrs[] = 'disabled="disabled"';
             }
             if ($new_prop['id']) {
                 $attrs[] = 'id="' . $new_prop['id'] . '"';
             }
             if ($new_prop['attr']) {
                 $attrs[] = implode(' ', $new_prop['attr']);
             }
             if ($new_prop['class']) {
                 $attrs[] = 'class="' . implode(' ', $new_prop['class']) . '"';
             }
             $field_html = '<' . $new_prop['container'] . ' ' . implode(' ', $attrs) . '>';
             $field_html .= implode('', $option_list);
             $field_html .= '</' . $new_prop['container'] . '>' . $new_prop['icon'];
             if ($field_html_only) {
                 return $field_html;
             }
             $result_html .= '	<label class="' . $field_class_map[$field_type] . '">';
             $result_html .= $field_html;
             $result_html .= '	</label>';
             break;
         case self::FORM_FIELD_FILEINPUT:
             $file_button = self::_get_field_html($name, self::FORM_FIELD_INPUT, array('type' => 'file', 'attr' => array_merge(array('onchange="this.parentNode.nextSibling.value = this.value"'), isset($properties['attr']) ? $properties['attr'] : array())), true);
             $field_html = '<span class="button">';
             $field_html .= $file_button;
             $field_html .= 'Browse</span>';
             $default_prop = array('icon' => false, 'tooltip' => false, 'attr' => array('readonly'), 'type' => 'text');
             if ($properties) {
                 foreach ($properties as $key => $value) {
                     if (!isset($default_prop[$key])) {
                         $default_prop[$key] = $value;
                     }
                 }
             }
             $field_html .= self::_get_field_html($name . '-display', self::FORM_FIELD_INPUT, $default_prop, true);
             if ($field_html_only) {
                 return $field_html;
             }
             $result_html .= '	<label class="' . $field_class_map[$field_type] . '">';
             $result_html .= $field_html;
             $result_html .= '	</label>';
             break;
         case self::FORM_FIELD_HIDDEN:
             $default_prop = array('icon' => false, 'tooltip' => false, 'type' => 'hidden', 'value' => '');
             $new_prop = parent::get_clean_structure($default_prop, $properties, array(), 'value');
             $field_html .= self::_get_field_html($name, self::FORM_FIELD_INPUT, $new_prop, true);
             return $field_html;
             break;
         case self::FORM_FIELD_INPUT:
             $default_prop = array('type' => 'text', 'attr' => array(), 'id' => '', 'icon' => '', 'icon_append' => true, 'placeholder' => '', 'value' => '', 'tooltip' => array(), 'disabled' => false, 'autocomplete' => false, 'size' => '', 'class' => array());
             $new_prop = parent::get_clean_structure($default_prop, $properties, array(), 'placeholder');
             $classes = array();
             if ($new_prop['class']) {
                 array_push($classes, $new_prop['class']);
             }
             if ($new_prop['size']) {
                 $classes[] = 'input-' . $new_prop['size'];
             }
             $attrs = array();
             $attrs[] = $classes ? 'class="' . implode(' ', $classes) . '"' : '';
             $attrs[] = 'type="' . $new_prop['type'] . '"';
             $attrs[] = 'name="' . $name . '"';
             if ($new_prop['attr']) {
                 $attrs[] = implode(' ', $new_prop['attr']);
             }
             if ($new_prop['id']) {
                 $attrs[] = 'id="' . $new_prop['id'] . '"';
             }
             $attrs[] = 'value="' . $new_prop['value'] . '"';
             if ($new_prop['placeholder']) {
                 $attrs[] = 'placeholder="' . $new_prop['placeholder'] . '"';
             }
             if ($new_prop['disabled']) {
                 $attrs[] = 'disabled="disabled"';
             }
             $ac_html = '';
             if ($new_prop['autocomplete']) {
                 $ac_prop = array('data' => array(), 'display' => '', 'value' => '');
                 if (!isset($new_prop['autocomplete']['data'])) {
                     $ac_prop['data'] = $new_prop['autocomplete'];
                 } else {
                     $ac_prop['data'] = $new_prop['autocomplete']['data'];
                     $ac_prop['display'] = isset($new_prop['autocomplete']['display']) ? $new_prop['autocomplete']['display'] : '';
                     $ac_prop['value'] = isset($new_prop['autocomplete']['value']) ? $new_prop['autocomplete']['value'] : '';
                 }
                 $list_name = 'list-' . $name . '-' . SmartUtil::create_id();
                 $ac_html = self::_get_field_html('', self::FORM_FIELD_SELECT, array('container' => 'datalist', 'data' => $ac_prop['data'], 'display' => $ac_prop['display'], 'value' => $ac_prop['value'], 'id' => $list_name), true);
                 $attrs[] = 'list="' . $list_name . '"';
             }
             if ($new_prop['icon']) {
                 $field_html .= '<i class="icon-' . ($new_prop['icon_append'] ? 'append' : 'prepend') . ' ' . SmartUI::$icon_source . ' ' . $new_prop['icon'] . '"></i>';
             }
             $field_html .= '<input ' . implode(' ', $attrs) . ' />';
             $field_html .= $ac_html;
             if ($new_prop['tooltip']) {
                 $tooltip_prop = array('content' => '', 'position' => 'top-right');
                 $new_tooltip_prop = parent::set_array_prop_def($tooltip_prop, $new_prop['tooltip'], 'content');
                 $field_html .= '<b class="tooltip tooltip-' . $new_tooltip_prop['position'] . '">' . $new_tooltip_prop['content'] . '</b>';
             }
             if ($field_html_only) {
                 return $field_html;
             }
             $result_html .= '	<label class="' . $field_class_map[$field_type] . '">';
             $result_html .= $field_html;
             $result_html .= '	</label>';
             break;
         case self::FORM_FIELD_RADIO:
             $default_prop = array('items' => array(), 'cols' => 0, 'inline' => false, 'toggle' => false);
             $new_prop = parent::get_clean_structure($default_prop, $properties, array(), 'items');
             if (!is_array($new_prop['items'])) {
                 $new_prop['items'] = array($new_prop['items']);
             }
             $items = $new_prop['items'];
             $item_list_html = array();
             foreach ($items as $item) {
                 $items_prop = array('name' => $name, 'checked' => false, 'value' => '', 'label' => '', 'id' => '', 'disabled' => false);
                 $new_item_prop = parent::set_array_prop_def($items_prop, $item, 'label');
                 $item_html = self::_get_field_html($new_item_prop['name'], self::FORM_FIELD_INPUT, array('type' => 'radio', 'attr' => $new_item_prop['checked'] ? array('checked') : null, 'value' => $new_item_prop['value'], 'id' => $new_item_prop['id']), true);
                 if ($new_prop['toggle']) {
                     $text_off = is_array($new_prop['toggle']) && isset($new_prop['toggle']['text-off']) ? $new_prop['toggle']['text-off'] : 'OFF';
                     $text_on = is_array($new_prop['toggle']) && isset($new_prop['toggle']['text-on']) ? $new_prop['toggle']['text-on'] : 'ON';
                     $item_html .= '<i data-swchon-text="' . $text_on . '" data-swchoff-text="' . $text_off . '"></i>';
                 } else {
                     $item_html .= '<i></i>';
                 }
                 $item_html .= $new_item_prop['label'];
                 $field_html = '	<label class="' . ($new_prop['toggle'] ? 'toggle' : $field_class_map[$field_type]) . ' ' . ($new_item_prop['disabled'] ? 'state-disabled' : '') . '">';
                 $field_html .= $item_html;
                 $field_html .= '	</label>';
                 $item_list_html[] = $field_html;
             }
             if ($new_prop['cols']) {
                 $result_html .= '<div class="row">';
                 $result_html .= self::print_col_items($item_list_html, function ($item) {
                     return $item;
                 }, $new_prop['cols'], true);
                 $result_html .= '</div>';
             } else {
                 $list_html = implode('', $item_list_html);
                 if ($new_prop['inline']) {
                     $result_html .= '<div class="inline-group">';
                     $result_html .= $list_html;
                     $result_html .= '</div>';
                 } else {
                     $result_html .= $list_html;
                 }
             }
             if ($field_html_only) {
                 return $result_html;
             }
             break;
         case self::FORM_FIELD_CHECKBOX:
             $default_prop = array('items' => array(), 'cols' => 0, 'inline' => false, 'toggle' => false);
             $new_prop = parent::get_clean_structure($default_prop, $properties, array(), 'items');
             if (!is_array($new_prop['items'])) {
                 $new_prop['items'] = array($new_prop['items']);
             }
             $items = $new_prop['items'];
             $item_list_html = array();
             foreach ($items as $item) {
                 $items_prop = array('name' => $name, 'checked' => false, 'value' => '', 'label' => '', 'id' => '', 'disabled' => false);
                 $new_item_prop = parent::set_array_prop_def($items_prop, $item, 'label');
                 $item_html = self::_get_field_html($new_item_prop['name'], self::FORM_FIELD_INPUT, array('type' => 'checkbox', 'attr' => $new_item_prop['checked'] ? array('checked') : null, 'value' => $new_item_prop['value'], 'id' => $new_item_prop['id']), true);
                 if ($new_prop['toggle']) {
                     $text_off = is_array($new_prop['toggle']) && isset($new_prop['toggle']['text-off']) ? $new_prop['toggle']['text-off'] : 'OFF';
                     $text_on = is_array($new_prop['toggle']) && isset($new_prop['toggle']['text-on']) ? $new_prop['toggle']['text-on'] : 'ON';
                     $item_html .= '<i data-swchon-text="' . $text_on . '" data-swchoff-text="' . $text_off . '"></i>';
                 } else {
                     $item_html .= '<i></i>';
                 }
                 $item_html .= $new_item_prop['label'];
                 $field_html = '	<label class="' . ($new_prop['toggle'] ? 'toggle' : $field_class_map[$field_type]) . ' ' . ($new_item_prop['disabled'] ? 'state-disabled' : '') . '">';
                 $field_html .= $item_html;
                 $field_html .= '	</label>';
                 $item_list_html[] = $field_html;
             }
             if ($new_prop['cols']) {
                 $result_html .= '<div class="row">';
                 $result_html .= self::print_col_items($item_list_html, function ($item) {
                     return $item;
                 }, $new_prop['cols'], true);
                 $result_html .= '</div>';
             } else {
                 $list_html = implode('', $item_list_html);
                 if ($new_prop['inline']) {
                     $result_html .= '<div class="inline-group">';
                     $result_html .= $list_html;
                     $result_html .= '</div>';
                 } else {
                     $result_html .= $list_html;
                 }
             }
             if ($field_html_only) {
                 return $result_html;
             }
             break;
     }
     if (is_array($properties)) {
         $notes = isset($properties['note']) ? '<div class="note">' . $properties['note'] . '</div>' : '';
         $label = isset($properties['label']) && $properties['label'] ? '<label class="label">' . $properties['label'] . '</label>' : '';
     }
     $result .= $label;
     $result .= $result_html;
     $result .= $notes;
     return $result;
 }