デモ
var Suggest = function(input, suggest, dic) {
this.idInput = document.getElementById(input);
this.idSuggest = document.getElementById(suggest);
this.dic = dic
this.idx = -1;
this.serchWord = "";
this.init();
};
Suggest.Key = {
UP: 38,
DOWN: 40,
RETURN: 13,
TAB: 9,
ESC: 27
};
Suggest.forEach = function(array, func, obj) {
for (var i = 0; i < array.length; i++)
func.call(obj, array[i], i, array);
};
Suggest.addEvent = function(obj, type, func) {
obj.addEventListener ?
obj.addEventListener(type, func, false) :
obj.attachEvent("on" + type, func);
};
Suggest.escapeHTML = function(value) {
return v.replace(/&/g, "&").replace(/</g,"<").replace(/>/g, ">");
};
Suggest.prototype.select = function() {
var i = this.idx;
if (i != -1) {
var area = this.idSuggest.firstChild;
this.idInput.value = area.childNodes[i].innerHTML;
}
this.removeView();
};
Suggest.prototype.keyEvent = function(e) {
var idx = this.idx;
switch (e.keyCode) {
case Suggest.Key.TAB: case Suggest.Key.ESC:
this.removeView();
break;
case Suggest.Key.RETURN:
this.select();
break;
case Suggest.Key.UP:
if (this.idSuggest.firstChild == null) return;
var list = this.idSuggest.firstChild.childNodes;
if (idx == -1) {
list[list.length - 1].className = "select";
this.idInput.value = list[list.length -1].innerHTML;
this.idx = list.length - 1;
} else if (idx - 1 >= 0) {
if (idx >= 0) list[idx].className = "over";
list[idx - 1].className = "select";
this.idInput.value = list[idx -1].innerHTML;
this.idx -= 1;
} else {
list[idx].className = "over";
this.idx = -1;
this.idInput.value = this.serchWord;
}
break;
case Suggest.Key.DOWN:
if (this.idSuggest.firstChild == null) return;
var list = this.idSuggest.firstChild.childNodes;
if (idx + 1 < list.length) {
if (idx != -1) list[idx].className = "over";
list[idx + 1].className = "select";
this.idInput.value = list[idx + 1].innerHTML;
this.idx += 1;
} else {
list[idx].className = "over";
this.idInput.value = this.serchWord;
this.idx = -1;
}
break;
default:
setTimeout(this.bind(this.serch), 500);
break;
}
};
Suggest.prototype.init = function() {
Suggest.addEvent(this.idInput, "blur", this.bind(this.select));
Suggest.addEvent(this.idInput, "keydown", this.bindEvent(this.keyEvent));
};
Suggest.prototype.serch = function() {
var result = [];
var value = this.idInput.value;
this.removeView();
if (value == "") return;
this.serchWord = value;
value = Suggest.escapeHTML(value);
Suggest.forEach(this.dic, function (word) {
if (word.match(value)) result.push(word);
}, this);
if (result.length == 0) return;
this.createView(result);
};
Suggest.prototype.removeView = function() {
if (this.idSuggest.firstChild != null) {
this.idSuggest.removeChild(this.idSuggest.firstChild);
this.idx = -1;
}
};
Suggest.prototype.changeSelect = function(i) {
var list = this.idSuggest.firstChild.childNodes;
if (this.idx != -1) list[this.idx].className = "over";
list[i].className = "select";
this.idx = i;
};
Suggest.prototype.createView = function(result) {
var area = document.createElement("div");
area.id = "suggest_area";
Suggest.forEach(result, function(r, i) {
var div = document.createElement("div");
Suggest.addEvent(div, "mouseover", this.bind(this.changeSelect, i));
div.innerHTML = r;
div.className = "over";
area.appendChild(div);
}, this);
this.idSuggest.appendChild(area);
};
Suggest.prototype.bind = function(func) {
var self = this;
var args = Array.prototype.slice.call(arguments, 1);
return function() {
func.apply(self, args);
};
};
Suggest.prototype.bindEvent = function(func) {
var self = this;
var args = Array.prototype.slice.call(arguments, 1);
return function(e) {
func.apply(self, [e].concat(args));
};
};