最近写了个基于Prototype的AutoComplete的小程序,没有太多的技术含量,但是也贴出来吧。
var
AutoComplete
=
Class.create(
...
{
initialize: function(ele,func,options)...{
this.oInput = $(ele);
this.getContent = func;
this.oDiv = $(document.createElement('div'));
this.visible = false;
this.index = -1;
this.count = 0;
this.oInputFocus = true;
this.setDivStyle();
this.options = this.setOptions(options);
this.appendDiv();
Event.observe(this.oInput, 'blur', this.onBlur.bindAsEventListener(this));
Event.observe(this.oInput, 'keydown', this.onKeyDown.bindAsEventListener(this));
Event.observe(this.oInput, 'dblclick', this.onDblClick.bindAsEventListener(this));
Event.observe(this.oInput, 'keyup', this.onKeyUp.bindAsEventListener(this));
},
setDivStyle:function()...{
var position = this.oInput.cumulativeOffset();
this.oDiv.style.display = 'none';
this.oDiv.style.position = 'absolute';
this.oDiv.id = 'autoComplete';
this.oDiv.style.left = position.left + "px";
this.oDiv.style.top = position.top + this.oInput.getHeight() + "px";
this.oDiv.style.border = "1px solid #cfcfcf";
this.oDiv.style.zIndex = "100";
this.oDiv.style.backgroundColor = "white";
},
setOptions:function(opt)...{
var options = ...{
hoverColor:'aqua',
containerId:'',
postAutoComplete:function()...{}
};
Object.extend(options, opt || ...{ });
return options;
},
setItemStyle:function(ele)...{
ele.style.padding = "2px";
ele.style.cursor = "default";
ele.style.fontSize = "1.6em";
},
appendDiv:function()...{
if(this.options.containerId == '')
document.body.appendChild(this.oDiv);
else
$(this.options.containerId).appendChild(this.oDiv);
},
finalize:function()...{
alert('not implement yet');
},
show:function()...{
this.fillItems();
if(this.count > 0)...{
Element.show(this.oDiv.id);
this.visible = true;
}
},
fillItems:function()...{
this.clearItems();
var content = this.getContent(this.oInput.value);
if(content == '' || content == 'Failure') ...{
return;
}
var arr = content.split(',');
this.count = arr.length;
for(var i=0;i<this.count;++i)...{
var e = $(document.createElement('div'));
this.setItemStyle(e);
this.addObserver(e);
e.innerText = arr[i];
e.index = i;
this.oDiv.appendChild(e);
}
},
hide:function()...{
Element.hide(this.oDiv.id);
this.clearItems();
this.index = -1;
this.visible = false;
this.count = 0;
},
onBlur:function()...{
if(this.index == -1)...{
this.hide();
}
else...{
}
},
onDblClick:function()...{
this.show();
},
onKeyDown:function()...{
if(this.visible)...{
switch(event.keyCode)...{
case Event.KEY_DOWN:
this.getNextItem();
Event.stop(event);
break;
case Event.KEY_UP:
this.getPrevItem();
Event.stop(event);
break;
case Event.KEY_RETURN:
this.selectItem();
Event.stop(event);
break;
}
}
},
onKeyUp:function()...{
if( (event.keyCode >=65 && event.keyCode <= 90) ||
(event.keyCode >=48 && event.keyCode <= 57))
...{
this.show();
}
if(!this.visible)...{
if(event.keyCode == Event.KEY_DOWN && this.oInput.value != '')...{
this.show();
}
}
if(event.keyCode == Event.KEY_BACKSPACE)...{
if(this.oInput.value.blank())...{
this.hide();
}
else...{
this.show();
}
}
},
getNextItem:function()...{
var idx = (this.index == this.count - 1) ? (this.index = 0) : ++this.index;
var ele = this.getCurrentItem(idx);
this.render(ele);
},
getPrevItem:function()...{
var idx = (this.index == 0) ? (this.index = this.count - 1) : --this.index;
var ele = this.getCurrentItem(idx);
this.render(ele);
},
getCurrentItem:function(idx)...{
var ele;
$(this.oDiv.id).childElements().each(
function(item)...{
if(item.index == idx)...{
ele = item;
throw $break;
}
}
);
return ele;
},
render:function(ele)...{
$(this.oDiv.id).childElements().each(
function(item)...{
item.style.backgroundColor = 'white';
}
);
ele.style.backgroundColor = this.options.hoverColor;
this.oInput.value = ele.innerText;
},
addObserver: function(element)...{
Event.observe(element, "mouseover", this.onItemMouseOver.bindAsEventListener(this));
Event.observe(element,"mouseout",this.onItemMouseOut.bindAsEventListener(this));
Event.observe(element, "click", this.onItemClick.bindAsEventListener(this));
},
onItemMouseOver:function()...{
var ele = Event.findElement(event,'div');
this.index = ele.index;
this.render(ele);
Event.stop(event);
},
onItemMouseOut:function()...{
var ele = Event.findElement(event,'div');
this.index = -1;
ele.style.backgroundColor = 'white';
Event.stop(event);
},
onItemClick:function()...{
var ele = Event.findElement(event,'div');
this.oInput.value = ele.innerText;
this.hide();
this.options.postAutoComplete();
},
selectItem:function()...{
var ele;
var children = $(this.oDiv.id).childElements();
for(var i=0,len=children.length;i<len;++i)...{
if(children[i].index == this.index)...{
ele = children[i];
break;
}
}
this.oInput.value = ele.innerText;
this.hide();
this.options.postAutoComplete();
},
clearItems:function()...{
while (this.oDiv.childNodes[0])...{
this.oDiv.removeChild(this.oDiv.childNodes[0]);
}
}
}
);
initialize: function(ele,func,options)...{
this.oInput = $(ele);
this.getContent = func;
this.oDiv = $(document.createElement('div'));
this.visible = false;
this.index = -1;
this.count = 0;
this.oInputFocus = true;
this.setDivStyle();
this.options = this.setOptions(options);
this.appendDiv();
Event.observe(this.oInput, 'blur', this.onBlur.bindAsEventListener(this));
Event.observe(this.oInput, 'keydown', this.onKeyDown.bindAsEventListener(this));
Event.observe(this.oInput, 'dblclick', this.onDblClick.bindAsEventListener(this));
Event.observe(this.oInput, 'keyup', this.onKeyUp.bindAsEventListener(this));
},
setDivStyle:function()...{
var position = this.oInput.cumulativeOffset();
this.oDiv.style.display = 'none';
this.oDiv.style.position = 'absolute';
this.oDiv.id = 'autoComplete';
this.oDiv.style.left = position.left + "px";
this.oDiv.style.top = position.top + this.oInput.getHeight() + "px";
this.oDiv.style.border = "1px solid #cfcfcf";
this.oDiv.style.zIndex = "100";
this.oDiv.style.backgroundColor = "white";
},
setOptions:function(opt)...{
var options = ...{
hoverColor:'aqua',
containerId:'',
postAutoComplete:function()...{}
};
Object.extend(options, opt || ...{ });
return options;
},
setItemStyle:function(ele)...{
ele.style.padding = "2px";
ele.style.cursor = "default";
ele.style.fontSize = "1.6em";
},
appendDiv:function()...{
if(this.options.containerId == '')
document.body.appendChild(this.oDiv);
else
$(this.options.containerId).appendChild(this.oDiv);
},
finalize:function()...{
alert('not implement yet');
},
show:function()...{
this.fillItems();
if(this.count > 0)...{
Element.show(this.oDiv.id);
this.visible = true;
}
},
fillItems:function()...{
this.clearItems();
var content = this.getContent(this.oInput.value);
if(content == '' || content == 'Failure') ...{
return;
}
var arr = content.split(',');
this.count = arr.length;
for(var i=0;i<this.count;++i)...{
var e = $(document.createElement('div'));
this.setItemStyle(e);
this.addObserver(e);
e.innerText = arr[i];
e.index = i;
this.oDiv.appendChild(e);
}
},
hide:function()...{
Element.hide(this.oDiv.id);
this.clearItems();
this.index = -1;
this.visible = false;
this.count = 0;
},
onBlur:function()...{
if(this.index == -1)...{
this.hide();
}
else...{
}
},
onDblClick:function()...{
this.show();
},
onKeyDown:function()...{
if(this.visible)...{
switch(event.keyCode)...{
case Event.KEY_DOWN:
this.getNextItem();
Event.stop(event);
break;
case Event.KEY_UP:
this.getPrevItem();
Event.stop(event);
break;
case Event.KEY_RETURN:
this.selectItem();
Event.stop(event);
break;
}
}
},
onKeyUp:function()...{
if( (event.keyCode >=65 && event.keyCode <= 90) ||
(event.keyCode >=48 && event.keyCode <= 57))
...{
this.show();
}
if(!this.visible)...{
if(event.keyCode == Event.KEY_DOWN && this.oInput.value != '')...{
this.show();
}
}
if(event.keyCode == Event.KEY_BACKSPACE)...{
if(this.oInput.value.blank())...{
this.hide();
}
else...{
this.show();
}
}
},
getNextItem:function()...{
var idx = (this.index == this.count - 1) ? (this.index = 0) : ++this.index;
var ele = this.getCurrentItem(idx);
this.render(ele);
},
getPrevItem:function()...{
var idx = (this.index == 0) ? (this.index = this.count - 1) : --this.index;
var ele = this.getCurrentItem(idx);
this.render(ele);
},
getCurrentItem:function(idx)...{
var ele;
$(this.oDiv.id).childElements().each(
function(item)...{
if(item.index == idx)...{
ele = item;
throw $break;
}
}
);
return ele;
},
render:function(ele)...{
$(this.oDiv.id).childElements().each(
function(item)...{
item.style.backgroundColor = 'white';
}
);
ele.style.backgroundColor = this.options.hoverColor;
this.oInput.value = ele.innerText;
},
addObserver: function(element)...{
Event.observe(element, "mouseover", this.onItemMouseOver.bindAsEventListener(this));
Event.observe(element,"mouseout",this.onItemMouseOut.bindAsEventListener(this));
Event.observe(element, "click", this.onItemClick.bindAsEventListener(this));
},
onItemMouseOver:function()...{
var ele = Event.findElement(event,'div');
this.index = ele.index;
this.render(ele);
Event.stop(event);
},
onItemMouseOut:function()...{
var ele = Event.findElement(event,'div');
this.index = -1;
ele.style.backgroundColor = 'white';
Event.stop(event);
},
onItemClick:function()...{
var ele = Event.findElement(event,'div');
this.oInput.value = ele.innerText;
this.hide();
this.options.postAutoComplete();
},
selectItem:function()...{
var ele;
var children = $(this.oDiv.id).childElements();
for(var i=0,len=children.length;i<len;++i)...{
if(children[i].index == this.index)...{
ele = children[i];
break;
}
}
this.oInput.value = ele.innerText;
this.hide();
this.options.postAutoComplete();
},
clearItems:function()...{
while (this.oDiv.childNodes[0])...{
this.oDiv.removeChild(this.oDiv.childNodes[0]);
}
}
}
);
使用方法如下:
new
AutoComplete(updatingTagId,
function (val) ... {
new Ajax.Request(url,
...{
method: 'get',
onSuccess: function(transport) ...{
return transport.responseText;
},
onFailure: function()...{alert('Failure'); return 'Failure';}
}
);
} ,
... { hoverColor = 'blue',
containerId = 'pageContainer',
postAutoComplete:function()...{alert('execute after autoComplete');}
);
function (val) ... {
new Ajax.Request(url,
...{
method: 'get',
onSuccess: function(transport) ...{
return transport.responseText;
},
onFailure: function()...{alert('Failure'); return 'Failure';}
}
);
} ,
... { hoverColor = 'blue',
containerId = 'pageContainer',
postAutoComplete:function()...{alert('execute after autoComplete');}
);