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

This file contains ambiguous Unicode characters!

This file contains ambiguous Unicode characters that may be confused with others in your current locale. If your use case is intentional and legitimate, you can safely ignore this warning. Use the Escape button to highlight these characters.

/*
* @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));