因为项目需要,写了一个简单的AJAX自动完成的小例子,这里给出代码。
代码没有优化,优化方向是:1.进一步解耦 2.增加本地数据缓存的筛选,减少交互次数 3.优化筛选算法
有兴趣的朋友可以去尝试一下。
使用方法是:
var autoCompleteController = new AutoComplete(document.getElementById('keyword'),{
startPoint:3,
JSONService:'autocomplete.php'
});
后台页面(比如:autocomplete.php)接受一个GET方式提交的keyword参数,返回类似
[{"name":"Test1","value":"1"},{"name":"Test2","value":"2"}]
的JSON字符串即可
代码没有优化,优化方向是:1.进一步解耦 2.增加本地数据缓存的筛选,减少交互次数 3.优化筛选算法
有兴趣的朋友可以去尝试一下。
/*
* AutoComplete Class
* Author: Robin Chen(robchen@126.com)
*/
// AutoComplete Class
var AutoComplete = function (dom,options) {
this.dom = dom;
this.startPoint = options.startPoint || 3;
this.JSONService = options.JSONService;
this.selector = new AutoCompleteSelector(this);
var __this = this;
this.selectMode = true;
this.dom.onfocus = this.dom.onchange = this.dom.onkeyup = function(){
setTimeout(function(){
if(__this.dom.cacheValue != __this.dom.value){
__this.dom.cacheValue = __this.dom.value;
__this.search();
}else{
if(__this.dom.value.length >= __this.startPoint)__this.selector.show();
}
},10);
}
var onMouseClick = function(evt){
var evt = evt || event;
var target = evt.target || evt.srcElement;
if(target != __this.dom && target != __this.selector.dom){
__this.selector.hide();
}
}
try{
document.body.attachEvent('onclick',onMouseClick);
}catch(e){
document.body.addEventListener('click',onMouseClick,false);
}
}
AutoComplete.prototype = {
request:null,
dataCache:null,
createXMLHttpRequest:function(){
try{
return new XMLHttpRequest();
}catch(e){
return new ActiveXObject('Microsoft.XMLHTTP');
}
},
search:function(){
var keyword = this.dom.value;
if(keyword.length < this.startPoint)return;
if(this.request)this.request.abort();
var request = this.request = this.createXMLHttpRequest();
request.open('GET',this.JSONService + '?keyword=' + escape(keyword),true);
var __this = this;
request.onreadystatechange = function(){
if(request.readyState == 4 && request.status == 200){
var data = eval('(' + request.responseText + ')');
__this.parseData.call(__this,data);
}
}
request.send();
},
parseData:function(data){
this.dataCache = data;
this.selector.load(data);
if(this.selector.dom.getElementsByTagName('div').length > 0){
this.selector.show();
}else{
this.selector.hide();
}
}
}
// AutoCompleteSelector Class
var AutoCompleteSelector = function (autoCompleteObject) {
this.autoCompleteObject = autoCompleteObject;
if(arguments[1]){
this.dom = arguments[1];
}else{
this.dom = this.createDefaultSelectorElement();
}
}
AutoCompleteSelector.prototype = {
createDefaultSelectorElement:function(){
var target = this.autoCompleteObject.dom;
var obj = target;
var width = target.offsetWidth;
var left = target.offsetLeft;
var top = target.offsetHeight + target.offsetTop;
if(window.ActiveXObject){
try{
obj = obj.parentNode;
while(obj && obj.style){
obj = obj.parentNode;
left += parseInt(obj.offsetLeft) || 0;
top += parseInt(obj.offsetTop) || 0;
}
}catch(e){}
}
var div = document.createElement('div');
div.className = 'autoCompleteSelector';
div.style.position = 'absolute';
div.style.left = left - 1 + 'px';
div.style.top = top + 'px';
div.style.width = width + 'px';
div.style.height = '200px';
div.style.overflow = 'auto';
div.style.display = 'none';
div.style.zIndex = '1000';
div.style.border = '1px solid #000';
div.style.backgroundColor = '#fff';
document.body.appendChild(div);
div.autoCompleteSelectorObject = this;
return div;
},
dataCache:[],
show:function(){
this.dom.style.display = 'block';
},
hide:function(){
this.dom.style.display = 'none';
},
load:function(data){
this.clear();
for(var i = 0; i < data.length; i ++){
this.add(new AutoCompleteSelectItem(data[i],this));
}
},
clear:function(){
this.dom.innerHTML = '';
},
add:function(item){
this.dom.appendChild(item.dom);
},
remove:function(item){
this.dom.removeChild(item.dom);
}
}
// AutoCompleteSelectItem Class
var AutoCompleteSelectItem = function (data,autoCompleteSelectorObject) {
this.name = data.name;
this.value = data.value;
this.dataCache = data;
this.autoCompleteSelectorObject = autoCompleteSelectorObject;
this.dom = this.create();
var __this = this;
this.dom.onclick = function(){
__this.autoCompleteSelectorObject.autoCompleteObject.dom.cacheValue = __this.name;
__this.autoCompleteSelectorObject.autoCompleteObject.dom.value = __this.name;
__this.autoCompleteSelectorObject.hide();
}
}
AutoCompleteSelectItem.prototype = {
create:function(){
var div = document.createElement('div');
div.className = 'autoCompleteSelectItem';
div.style.width = 'auto';
div.style.height = '14px';
div.style.fontSize = '11px';
div.style.lineHeight = '14px';
div.style.textAlign = 'left';
div.style.padding = '2px';
div.style.borderBottom = '1px solid #ccc';
div.style.color = '#000';
div.style.backgroundColor = '#fff';
div.style.overflow = 'hidden';
div.onmouseover = function(){
this.style.backgroundColor = '#999';
this.style.color = '#fff';
this.style.cursor = 'pointer';
}
div.onmouseout = function(){
this.style.backgroundColor = '#fff';
this.style.color = '#000';
}
div.innerHTML = this.name;
div.autoCompleteSelectItem = this;
return div;
}
}
* AutoComplete Class
* Author: Robin Chen(robchen@126.com)
*/
// AutoComplete Class
var AutoComplete = function (dom,options) {
this.dom = dom;
this.startPoint = options.startPoint || 3;
this.JSONService = options.JSONService;
this.selector = new AutoCompleteSelector(this);
var __this = this;
this.selectMode = true;
this.dom.onfocus = this.dom.onchange = this.dom.onkeyup = function(){
setTimeout(function(){
if(__this.dom.cacheValue != __this.dom.value){
__this.dom.cacheValue = __this.dom.value;
__this.search();
}else{
if(__this.dom.value.length >= __this.startPoint)__this.selector.show();
}
},10);
}
var onMouseClick = function(evt){
var evt = evt || event;
var target = evt.target || evt.srcElement;
if(target != __this.dom && target != __this.selector.dom){
__this.selector.hide();
}
}
try{
document.body.attachEvent('onclick',onMouseClick);
}catch(e){
document.body.addEventListener('click',onMouseClick,false);
}
}
AutoComplete.prototype = {
request:null,
dataCache:null,
createXMLHttpRequest:function(){
try{
return new XMLHttpRequest();
}catch(e){
return new ActiveXObject('Microsoft.XMLHTTP');
}
},
search:function(){
var keyword = this.dom.value;
if(keyword.length < this.startPoint)return;
if(this.request)this.request.abort();
var request = this.request = this.createXMLHttpRequest();
request.open('GET',this.JSONService + '?keyword=' + escape(keyword),true);
var __this = this;
request.onreadystatechange = function(){
if(request.readyState == 4 && request.status == 200){
var data = eval('(' + request.responseText + ')');
__this.parseData.call(__this,data);
}
}
request.send();
},
parseData:function(data){
this.dataCache = data;
this.selector.load(data);
if(this.selector.dom.getElementsByTagName('div').length > 0){
this.selector.show();
}else{
this.selector.hide();
}
}
}
// AutoCompleteSelector Class
var AutoCompleteSelector = function (autoCompleteObject) {
this.autoCompleteObject = autoCompleteObject;
if(arguments[1]){
this.dom = arguments[1];
}else{
this.dom = this.createDefaultSelectorElement();
}
}
AutoCompleteSelector.prototype = {
createDefaultSelectorElement:function(){
var target = this.autoCompleteObject.dom;
var obj = target;
var width = target.offsetWidth;
var left = target.offsetLeft;
var top = target.offsetHeight + target.offsetTop;
if(window.ActiveXObject){
try{
obj = obj.parentNode;
while(obj && obj.style){
obj = obj.parentNode;
left += parseInt(obj.offsetLeft) || 0;
top += parseInt(obj.offsetTop) || 0;
}
}catch(e){}
}
var div = document.createElement('div');
div.className = 'autoCompleteSelector';
div.style.position = 'absolute';
div.style.left = left - 1 + 'px';
div.style.top = top + 'px';
div.style.width = width + 'px';
div.style.height = '200px';
div.style.overflow = 'auto';
div.style.display = 'none';
div.style.zIndex = '1000';
div.style.border = '1px solid #000';
div.style.backgroundColor = '#fff';
document.body.appendChild(div);
div.autoCompleteSelectorObject = this;
return div;
},
dataCache:[],
show:function(){
this.dom.style.display = 'block';
},
hide:function(){
this.dom.style.display = 'none';
},
load:function(data){
this.clear();
for(var i = 0; i < data.length; i ++){
this.add(new AutoCompleteSelectItem(data[i],this));
}
},
clear:function(){
this.dom.innerHTML = '';
},
add:function(item){
this.dom.appendChild(item.dom);
},
remove:function(item){
this.dom.removeChild(item.dom);
}
}
// AutoCompleteSelectItem Class
var AutoCompleteSelectItem = function (data,autoCompleteSelectorObject) {
this.name = data.name;
this.value = data.value;
this.dataCache = data;
this.autoCompleteSelectorObject = autoCompleteSelectorObject;
this.dom = this.create();
var __this = this;
this.dom.onclick = function(){
__this.autoCompleteSelectorObject.autoCompleteObject.dom.cacheValue = __this.name;
__this.autoCompleteSelectorObject.autoCompleteObject.dom.value = __this.name;
__this.autoCompleteSelectorObject.hide();
}
}
AutoCompleteSelectItem.prototype = {
create:function(){
var div = document.createElement('div');
div.className = 'autoCompleteSelectItem';
div.style.width = 'auto';
div.style.height = '14px';
div.style.fontSize = '11px';
div.style.lineHeight = '14px';
div.style.textAlign = 'left';
div.style.padding = '2px';
div.style.borderBottom = '1px solid #ccc';
div.style.color = '#000';
div.style.backgroundColor = '#fff';
div.style.overflow = 'hidden';
div.onmouseover = function(){
this.style.backgroundColor = '#999';
this.style.color = '#fff';
this.style.cursor = 'pointer';
}
div.onmouseout = function(){
this.style.backgroundColor = '#fff';
this.style.color = '#000';
}
div.innerHTML = this.name;
div.autoCompleteSelectItem = this;
return div;
}
}
使用方法是:
var autoCompleteController = new AutoComplete(document.getElementById('keyword'),{
startPoint:3,
JSONService:'autocomplete.php'
});
后台页面(比如:autocomplete.php)接受一个GET方式提交的keyword参数,返回类似
[{"name":"Test1","value":"1"},{"name":"Test2","value":"2"}]
的JSON字符串即可