Autocomplete.hash = {};
Autocomplete.generator = 0;
function Autocomplete(source,type,callback) {
this.id = Autocomplete.generator++;
this.source = source;
this.type = type;
this.index = -1;
this.guesses = [];
this.visible = false;
this.callback = callback;
var scopedThis = this;
this.display = document.createElement('div');
this.display.style.position = 'absolute';
this.display.style.display = 'none';
this.display.className = 'autocompleter';
this.display.style.backgroundColor = 'white';
this.display.style.border = '1px solid #42619C';
this.display.style.zIndex = 10;
this.display.style.overflow = 'hidden';
this.display.onmouseout = function(event) {
scopedThis.clearIndex();
}
this.source.onkeydown = function(event) {
event = event || window.event;
switch(event.keyCode) {
case 38: //up
scopedThis.setIndex(scopedThis.index-1);
return false;
case 40: //down
scopedThis.setIndex(scopedThis.index+1);
return false;
case 13: //enter
case 9: //tab
if(scopedThis.visible) {
if(scopedThis.index == -1) {
scopedThis.setIndex(0);
}
if(scopedThis.index != -1) {
scopedThis.accept();
if(event.keyCode != 9) {
return false;
}
}
}
break;
}
}
this.source.onkeyup = function(event) {
if(scopedThis.source.value != scopedThis.previous) {
scopedThis.setGuesses(scopedThis.guesses);
}
scopedThis.request();
}
this.source.onblur = function(event) {
scopedThis.cancel(true);
}
Autocomplete.hash[this.id] = this;
}
Autocomplete.prototype = {
accept: function() {
if(this.index != -1) {
var app = this.guesses[this.index];
this.source.value = app.display;
//this.source.appId = app.value;
this.previous = this.source.value;
this.cancel(true);
if(this.callback) {
this.callback(app);
}
}
},
cancel: function(clear) {
if(this.ajax) {
this.ajax.cancel();
this.ajax = null;
}
if(clear) {
this.setGuesses([]);
}
},
request: function() {
if(this.source.value == '') {
this.previous = '';
this.setGuesses([]);
}
else if(this.source.value != this.previous) {
this.previous = this.source.value;
var scopedThis = this;
this.cancel();
var ajax = new Ajax("/ajax/autocomplete.php",{
method:'get',
data:'type='+encodeURIComponent(this.type)+'&text='+encodeURIComponent(this.source.value),
onComplete:function(response){
scopedThis.ajax = null;
try {
eval("var guesses = "+response);
scopedThis.setGuesses(guesses);
}
catch(E){alert(E.name + ": "+E.message)}
}
});
ajax.request();
this.ajax = ajax;
}
},
setGuesses: function(guesses) {
if(guesses.length > 0) {
this.guesses = guesses;
}
this.index = -1;
var scopedThis = this;
var coords = $(this.source).getCoordinates();
this.display.style.left = coords.left + 'px';
this.display.style.top = coords.bottom + 'px';
this.display.style.width = Math.round(coords.width * 1.5) + 'px';
this.display.innerHTML = '';
var displayed = 0;
for(var i = 0 ; i < guesses.length ; i++) {
var app = guesses[i];
var div = document.createElement('div');
div.style.position = 'relative';
div.style.overflow = 'hidden';
div.style.cursor = 'pointer';
div.style.whiteSpace = 'nowrap';
div.style.width = '100%';
div.innerHTML = '';
if(app.icon){
div.innerHTML += "
";
}
else {
div.innerHTML += "
";
}
div.innerHTML += ""+app.display+"";
eval("div.onmouseover = function(event) {scopedThis.setIndex("+displayed+");};");
eval("div.onmousedown = function(event) {scopedThis.setIndex("+displayed+");scopedThis.accept();};");
div.title = app.display;
app.dom = div;
this.display.appendChild(div);
displayed++;
}
this.visible = displayed>0;
this.display.style.display = this.visible?'':'none';
if(this.display.parentNode != document.body) {
document.body.appendChild(this.display);
}
},
clearIndex: function() {
if(this.index != -1) {
this.guesses[this.index].dom.style.backgroundColor = '';
}
this.index = -1;
},
setIndex: function(index) {
if(index < 0) {
index = 0;
}
if(index >= this.guesses.length) {
index = this.guesses.length - 1;
}
if(this.index != index) {
if(this.index != -1) {
this.guesses[this.index].dom.style.backgroundColor = '';
}
this.index = index;
this.guesses[index].dom.style.backgroundColor = '#DEDFEF';
}
}
};