You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

316 lines
11 KiB

/*
* @name jQuery.auto-suggest
* @projectDescription AJAX auto-suggest for Bootstrap 3
* @author | https://github.com/androiddevelop/auto-suggest
* @version 1.0
* @license Apache License
*
*/
(function ($) {
$.fn.autosuggest = function (options) {
var defaults = {
url: "/search",
method: 'get',
wrapperClass: "as-wrapper",
menuClass: "as-menu",
minLength: 1,
maxNum: 5,
align: "left",
queryParamName: 'query',
split: null,
highlight: true,
extra: {},
nextStep: null,
open: null,
close: null,
immediate: false,
data: null,
firstSelected: false, //第一个被选中
dataCallback: null, //接口数据转换方法
dataType: 'json',
onSelect: null, //选中项方法返回选中项jQuery对象
dataFun: null
};
var settings = $.extend({}, defaults, options);
$(this).attr('autocomplete', 'off');
$(this).wrap('<div class="' + settings.wrapperClass + '"></div>');
$('<div class="' + settings.menuClass + ' list-group"></div>').insertAfter($(this));
var xhr;
var that = $(this);
var alignClass = ' as-align-left';
if (settings.align == 'center') {
alignClass = ' as-align-center';
} else if (settings.align == 'right') {
alignClass = ' as-align-right';
}
$(".as-menu").css("top", $(that).outerHeight());
var lastText = "";
var lock = false;
setInterval(checkInput, 200);
//检测输入
function checkInput() {
var query = $(that).val();
if (lock || query == lastText) {
return;
}
lastText = query;
if (query == null) {
closeComponent($(that).next('.' + settings.menuClass));
return;
}
if (query.length < settings.minLength) {
closeComponent($(that).next('.' + settings.menuClass));
return;
}
//处理分隔符,分隔符为最后一个字符时,隐藏建议框
if (settings.split != null && query.charAt(query.length - 1) == settings.split) {
$(that).next('.' + settings.menuClass).html('');
closeComponent($(that).next('.' + settings.menuClass));
}
searchQuery();
}
//hide auto-suggest component when lose focus
$(this).blur(function () {
setTimeout(function () {
closeComponent($(that).next('.' + settings.menuClass));
}, 200);
});
//查询
function searchQuery() {
var query = $(that).val();
var queryName = settings.queryParamName;
if (!query) {
$(that).next('.' + settings.menuClass).html('');
closeComponent($(that).next('.' + settings.menuClass));
}
var json = settings.dataFun(query);
if (settings.dataCallback) {
json = settings.data = settings.dataCallback(json);
}
var results = '';
var selectIndex = -1;
var suggestionsNum = 0;
$.each(json, function (i, j) {
if (settings.maxNum > i) {
if (settings.highlight) {
// 结果展示
results += '<span href="javascript:void(0)" class="list-group-item ' + alignClass + '" data-id="' + j.id + '" data-value="' + j.value + '" data-label="'
+ j.label + '">' + getStrongText(j.value, query) + ' <span class="sub-value">' + getStrongText(j.subvalue, query) + '</span></span>';
} else {
results += '<span href="javascript:void(0)" class="list-group-item ' + alignClass + '" data-id="' + j.id + '" data-value="' + j.value + '" data-label="'
+ j.label + '">' + j.value + ' <span class="sub-value">' + j.subvalue + '</span></span>';
}
suggestionsNum++;
}
});
$(that).next('.' + settings.menuClass).html(results);
$(that).next('.' + settings.menuClass).children().on("click", selectResult);
//do not show when lose focus
if ($(that).is(":focus")) {
openComponent($(that).next('.' + settings.menuClass));
}
//close component when there is no data.
if (suggestionsNum == 0 && $(that).next('.' + settings.menuClass).is(':visible') && settings.close != null) {
closeComponent($(that).next('.' + settings.menuClass));
}
$(that).unbind("keydown");
$(".as-selected").removeClass("as-selected");
var upDownOperate = false; //has up or down operate
if (settings.firstSelected) {
selectIndex = (selectIndex + 1) % suggestionsNum;
$(that).next('.' + settings.menuClass).children().eq(selectIndex).addClass("as-selected");
upDownOperate = true;
}
$(that).keydown(function (event) {
var keyCode = event.keyCode;
if ($(that).next('.' + settings.menuClass).css("display") == 'none' && keyCode != 13) {
return;
}
//up arrow
if (keyCode == 38) {
$(".as-selected").removeClass("as-selected");
selectIndex = (selectIndex + suggestionsNum - 1) % suggestionsNum;
$(that).next('.' + settings.menuClass).children().eq(selectIndex).addClass("as-selected");
upDownOperate = true;
//阻止光标移至输入框最前面
event.preventDefault();
return;
}
//down arrow
if (keyCode == 40) {
$(".as-selected").removeClass("as-selected");
selectIndex = (selectIndex + 1) % suggestionsNum;
$(that).next('.' + settings.menuClass).children().eq(selectIndex).addClass("as-selected");
upDownOperate = true;
return;
}
//enter
if (keyCode == 13) {
//suggestion component is visible after the operation up and down arrows
if (upDownOperate) {
lock = true;
lastText = getRealText($(".as-selected").data('value'));
$(that).val(lastText);
lock = false;
closeComponent($(that).next('.' + settings.menuClass));
if (settings.immediate && settings.nextStep != null) {
settings.nextStep($(".as-selected"));
} else {
upDownOperate = false;
}
settings.onSelect && settings.onSelect($(".as-selected"));
} else {
if (settings.nextStep != null && $(that).val().length > 0) {
closeComponent($(that).next('.' + settings.menuClass));
settings.nextStep($(".as-selected"));
//防止多余请求
xhr.abort();
}
}
}
});
//鼠标悬浮事件
$(that).next('.' + settings.menuClass).children().each(function (index) {
$(this).on("mouseenter", function () {
$(".as-selected").removeClass("as-selected");
$(this).addClass("as-selected");
selectIndex = index;
});
});
}
//建议框关闭
function closeComponent(ele) {
if (ele.is(':visible')) {
ele.hide();
if (settings.close != null) {
settings.close();
}
}
}
//建议框打开
function openComponent(ele) {
if (!ele.is(':visible')) {
ele.show();
if (settings.open != null) {
settings.open();
}
}
}
//do something after select menu
function selectResult() {
lock = true;
lastText = getRealText($(this).data('value'));
$(that).val(lastText);
lock = false;
closeComponent($(that).next('.' + settings.menuClass));
$(that).focus();
if (settings.immediate && settings.nextStep != null) {
settings.nextStep($(".as-selected"));
}
settings.onSelect && settings.onSelect($(this));
return false;
}
//返回组合后的文本
function getRealText(selectedValue) {
//没有分割府的话直接返回
if (settings.split == null) {
return selectedValue;
}
var query = $(that).val();
var result = selectedValue;
var index = query.lastIndexOf(settings.split);
if (index != -1) {
result = query.substring(0, index) + settings.split + selectedValue;
}
return result;
}
//获取真实查询内容
function getRealQuery(query) {
if (settings.split != null) {
var index = query.lastIndexOf(settings.split);
if (index != -1) {
query = query.substring(index + settings.split.length);
}
}
return query;
}
//对文本加入高亮操作
function getStrongText(text, matchText) {
if (text == undefined) {
return "";
}
if (matchText == undefined) {
return text;
}
var searchStartPosition = 0;
var textTmp = text;
var result = "";
var length = matchText.length;
text = text.toLowerCase();
matchText = matchText.toLowerCase();
var index = text.indexOf(matchText, searchStartPosition);
while (index != -1) {
result = result + textTmp.substring(searchStartPosition, index) + "<strong>" + textTmp.substr(index, length) + "</strong>";
searchStartPosition = index + length;
index = textTmp.indexOf(matchText, searchStartPosition);
}
result = result + textTmp.substring(searchStartPosition);
return result;
}
return this;
};
}(jQuery));