私が参加していたプロジェクトの 1 つで、そのようなものを作ったことを思い出しました。私はあなたの検査のためにコードを掘り起こしました (DSL は Dynamic Search List の略です):
var dslTimer = [];
var dslData = [];
var dslControls = [];
var dslSelected = [];
var dslSelectedIndex = 0;
var callBackFunction;
function addDsl(inputField, dslPlaceHolder, dslUrl, maxDepth, callback, countryLimitation) {
var dslIndex = dslControls.length + 1;
dslControls[dslIndex] = [inputField, dslPlaceHolder, dslUrl, maxDepth, countryLimitation];
callBackFunction = callback;
$('#' + inputField).keyup(function(e) {
var key = e.keyCode;
if (key == '13') {
if ($('#' + dslControls[dslIndex][1]).hasClass('hidden') && $('#' + inputField).val().length > 0) {
if (callback == null) {
$('#' + dslControls[dslIndex][1]).closest('form').submit();
}
else {
callback();
}
}
else {
$('#' + dslControls[dslIndex][1]).addClass('hidden');
}
} else if (key == '38') {
//Up key
$('#' + dslControls[dslIndex][1] + ' ul li:nth-child(' + dslSelectedIndex + ') a').removeClass('highlight');
dslSelectedIndex -= 1;
if (dslSelectedIndex < 0) {
dslSelectedIndex = $('#' + dslControls[dslIndex][1] + ' ul li').length;
}
$('#' + dslControls[dslIndex][1] + ' ul li:nth-child(' + dslSelectedIndex + ') a').addClass('highlight');
var str = $('#' + dslControls[dslIndex][1] + ' ul li:nth-child(' + dslSelectedIndex + ') a').text();
if (str != null && str != "") {
$('#' + dslControls[dslIndex][0]).val(str);
}
} else if (key == '40') {
//Down key
$('#' + dslControls[dslIndex][1] + ' ul li:nth-child(' + dslSelectedIndex + ') a').removeClass('highlight');
dslSelectedIndex += 1
if (dslSelectedIndex > $('#' + dslControls[dslIndex][1] + ' ul li').length) {
dslSelectedIndex = 0;
}
$('#' + dslControls[dslIndex][1] + ' ul li:nth-child(' + dslSelectedIndex + ') a').addClass('highlight');
var str = $('#' + dslControls[dslIndex][1] + ' ul li:nth-child(' + dslSelectedIndex + ') a').text();
if (str != null && str != "") {
$('#' + dslControls[dslIndex][0]).val(str);
}
} else {
var input = $('#' + dslControls[dslIndex][0]).val();
if (input.length >= 2) {
window.clearTimeout(dslTimer[dslIndex]);
dslTimer[dslIndex] = window.setTimeout('doDsl(' + dslIndex + ')', 100);
}
else {
$('#' + dslControls[dslIndex][1]).addClass('hidden');
}
}
});
$('#' + inputField).blur(function(e) {
window.setTimeout('blurDsl(' + dslIndex + ')', 500);
});
return dslIndex;
}
function doDsl(dslIndex) {
getDsl(dslIndex, $('#' + dslControls[dslIndex][0]).val());
}
function getDsl(dslIndex, searchstring) {
if (searchstring.length < 2) {
return;
}
var postData = { 'input': searchstring, 'maxDepth': dslControls[dslIndex][3] };
if (typeof (dslControls[dslIndex][4]) != 'undefined' || dslControls[dslIndex][4] != null) {
postData.countryId = dslControls[dslIndex][4].val();
}
$.ajax({
type: 'POST',
url: dslControls[dslIndex][2],
data: postData,
dataType: "json",
contentType: "application/x-www-form-urlencoded",
timeout: 60000,
global : false,
success: function (data) {
(data.length > 0)
? showDsl(dslIndex, data)
: blurDsl(dslIndex);
}
});
}
function showDsl(dslIndex, data) {
dslData[dslIndex] = data;
dslSelected[dslIndex] = null;
var htmlString = '<ul>';
var searchText = $('#' + dslControls[dslIndex][0]).val().ignoreAccent();
$.each(data, function(i, item) {
var text = item.Text;
var accentlessText = item.AccentlessText.Value;
var boldStart = accentlessText.toLowerCase().indexOf(searchText.toLowerCase());
while (boldStart > -1 && searchText.length > 0) {
text = text.substring(0, boldStart) + '<strong>' + text.substring(boldStart, (boldStart + searchText.length)) + '</strong>' + text.substring((boldStart + searchText.length), text.length);
boldStart = accentlessText.toLowerCase().indexOf(searchText.toLowerCase(), (boldStart + 17 + searchText.length));
}
htmlString += '<li><a href="javascript:void(0)" onmousedown="selectDsl(' + dslIndex + ', \'' + item.Id + '\')" tabindex="' + (1000 + i) + '">' + text + '</a></li>';
});
htmlString += '</ul>';
$('#' + dslControls[dslIndex][1] + ' ul').replaceWith(htmlString);
dslSelectedIndex = 0;
if (data.length > 0) {
$('#' + dslControls[dslIndex][1]).removeClass('hidden');
}
}
function selectDsl(dslIndex, id) {
$('#' + dslControls[dslIndex][1]).addClass('hidden');
$.each(dslData[dslIndex], function(i, item) {
if (item.Id == id) {
$('#' + dslControls[dslIndex][0]).val(item.Text);
dslSelected[dslIndex] = item;
if (callBackFunction != null) {
callBackFunction();
}
}
});
}
function blurDsl(dslIndex) {
$('#' + dslControls[dslIndex][1]).addClass('hidden');
}
// Source: https://github.com/zimny/accentless
(function () {
if (String.prototype.ignoreAccent) return;
var AccentCharCodesTable = {
"a": [224, 229],
"A": [192, 198],
"c": [231, 231],
"C": [199, 199],
"e": [231, 235],
"E": [200, 203],
"i": [236, 239],
"I": [204, 208],
"n": [241, 241],
"N": [209, 209],
"o": [242, 246],
"O": [209, 214],
"s": [353, 353],
"S": [352, 352],
"u": [248, 252],
"U": [216, 220],
"y": [253, 253],
"Y": [221, 221],
"z": [382, 382],
"Z": [381, 381]
};
String.prototype.ignoreAccent = function() {
var i, currentCharCode, char, str = this.split("");
for (i = 0; i < str.length; i++) {
currentCharCode = str[i].charCodeAt(0);
if (currentCharCode < 192) continue;
for (char in AccentCharCodesTable) {
if (AccentCharCodesTable.hasOwnProperty(char)) {
if (currentCharCode >= AccentCharCodesTable[char][0] && currentCharCode <= AccentCharCodesTable[char][1]) {
str[i] = char;
break;
}
}
}
}
return str.join("");
};
})();