select2_box
Github

    public function select2_box()
    {
        return _class('html')->select2_box('input_name', ['k1' => 'key1', 'k2' => 'key2']);
    }
    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);
    }