Расширение функциональности элемента input type=”text” до уровня «ComboBox»

в 5:53, , рубрики: asp.net mvc, jquery, jquery plugins, метки: ,

Введение

В сети существует огромное количество плагинов для реализации какого рода расширений. К сожалению (к счастью ?) все они (возможно я плохо искал ?), предлагают некое законченное решение в разметкой и стилями. Если Вам нужен только функционал, то этот плагин для Вас.

Идея

Расширить функциональность элемента до уровня combobox. Только функционал без разметки и стилей. Организовать взаимодействие стандартными способом.
Для запросов к серверу использовать get ajax запрос, передавая на вход значение элемента.
Настраивать элемент через атрибуты:

<input id="comboBox" data-options='{"url":"Home/Load","lengthText": 4,"timeWait":300 }' type="text" />
или
<input id="comboBox1" data-url="Home/Load" type="text" />

Где:
url – адрес сервиса
lengthText –минимальное количество символов после которого производится запрос (умолчание 3)
timeWait – время в мсек по истечении которого производится запрос (умолчание 300)

Оповещения разработчика о состоянии запроса организовать через систему событий.

query_start – старт запроса
query_end – окончание запроса
query_data – получение результата запроса
query_reset – сброс результатов
query_error – ошибка запроса

Обернуть все в плагин jQuery (v 1.7) — query()

$().ready(function () {
    $("#comboBox")
    .query()
    .bind("query_data", function (e, data) {
	// вывести куда то результат – например в <div id=”panel”/>
    })
    .bind("query_error", function (e, data) {
	// сообщить об ошибке
    })
    .bind("query_reset", function () {
	// очистить <div id=”panel”/>
    })
    .bind('query_start query_end', function (e) {
        //  как то показать что идет запрос – здесь меняем фон элемента
        $(this).css({ backgroundColor: e.type == "query_start" ? "#fdf5e6" : "#FFF" });
    });
});

Реализация

(function ($) {
    function query(target) { 
        this.$target = $(target);
        // получаем конфигурацию
        this.options = this.$target.data('options') || { url: this.$target.data("url") }; 
        if (!this.options.url)  // нет url - продолжение  не возможно
            throw Error("Ошибка конфигурации..."); 
        // значения по умолчанию
        this.options = $.extend({ lengthText: 3, timeWait: 300 }, this.options); 
    };

    query.prototype = {
        handler: function (val) {
             // игнорировать результаты предыдущего запроса если до его завершения была нажата клавиша
             if(this.def )  
                this.def.abort() ;

            if (val.length < this.options.lengthText) {  // проверка количества введенных символов
                this.$target.trigger('query_reset');     
                return;
            };

            var self = this;
            // прервать запрос если есть новый до истечения времени timeWait
            clearTimeout(this.timer); 
            // запуск запроса после иcтечения времени timeWait
            this.timer = setTimeout(function () { self._ajax(val); }, this.options.timeWait); 
        },
        _ajax: function (val) {
            var self = this;
            this.$target.trigger('query_start');// старт запроса
            this.def = $.get(this.options.url, { val: val })
                // получены результаты запроса
                .done(function (data) { self.$target.trigger('query_data', [data]); })  
                .error(function (data) { self.$target.trigger('query_error', [data]); }) // ошибка
                .always(function () { self.$target.trigger('query_end'); }); // запрос завершен
        }
    };
    $.fn.query = function () {
        this.each(function () {
            $(this)
            .data("query", new query(this)) // создаем обьект и сохраняем его в элементе
            .bind('keyup', function (e) { 
                // по отпусканию клавиши вызываем обработчик из сохраненного объекта
               $(this).data("query").handler($(this).val()); 
            });
        });
        return this;
    };
}
(jQuery));

В заключение приведу код для действия контроллера ASP.NET MVC.
Здесь возвращается json хотя никто не накладывает никаких ограничений на тип возвращаемых значений. Например, это может быть html в частичном представлении.

        public ActionResult Load(string val)
        {
            var data = new  { id=1, name="..."};  // какие то данные. Можно отфильтровать по параметру val 
            //throw new  Exception("Error", null);
            //System.Threading.Thread.Sleep(1000);
            return Json(data, JsonRequestBehavior.AllowGet);
        }

Автор: Che603000

* - обязательные к заполнению поля


https://ajax.googleapis.com/ajax/libs/jquery/3.4.1/jquery.min.js