Введение
В сети существует огромное количество плагинов для реализации какого рода расширений. К сожалению (к счастью ?) все они (возможно я плохо искал ?), предлагают некое законченное решение в разметкой и стилями. Если Вам нужен только функционал, то этот плагин для Вас.
Идея
Расширить функциональность элемента до автокомплит. Только функционал без разметки и стилей. Организовать взаимодействие стандартными способом.
Для запросов к серверу использовать 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