网络编程
位置:首页>> 网络编程>> JavaScript>> 原生js实现autocomplete插件

原生js实现autocomplete插件

作者:香草柠檬  发布时间:2024-04-17 09:44:55 

标签:js,autocomplete,插件

在实际的项目中,能用别人写好的插件实现相关功能是最好不过,为了节约时间成本,因为有的项目比较紧急,没充分时间让你自己来写,即便写了,你还要花大量时间调试兼容性。但是出于学习的目的,你可以利用闲暇时间,自己动手写写,看一些原生js的东西,根据自己的思路做插件,这样能提高水平。
说到autotemplete,好多人都用过,引用autotemplete.js,然后就可以实现在输入框输入值的时候提示下拉选项,类似于百度搜索框那种提示功能,下面就来说说自己的思路。
为输入框添加input事件
1.input事件兼容性代码如下:


AddEvt:function(ele, evt, fn) {
     if (document.addEventListener) {
       ele.addEventListener(evt, fn, false);
     } else if (document.attachEvent) {
       ele.attachEvent('on' + (evt == "input" ? "propertychange" : evt), fn);
     } else {
       ele['on' + (evt == "input" ? "propertychange" : evt)] = fn;
     }
   }

input事件和其他的事件不一样,低版本的ie不支持input事件,只能用propertychange事件,高版本的ie和w3c标准浏览器支持input事件
2.输入事件触发的时候获取数据
这里数据有两种形式,一种是直接设置的对象数组,一种是ajax请求返回数据
这时候我们需要一个ajax请求函数,这里写了一个get请求


get: function(url, paraobj, fn, timeout) {
       var xhr = null;
       try {

////兼容firefox,chrom
         if (window.XMLHttpRequest) {
           xhr = new XMLHttpRequest();
         }

//////兼容IE

else if (Window.ActiveXObject) {

xhr = new ActiveXObject("Msxml2.Xmlhttp");
         }
       } catch (e) {
         //TODO handle the exception
         xhr = new ActiveXObject('Microsoft.Xmlhttp');
       }
       xhr.onreadystatechange = function() {
         if (this.readyState == 4 && this.status == 200) {
           fn.call(this, this.responseText);

} else {
           setTimeout(function() {

xhr.abort();
           }, timeout);
         }
       };
       var parastr = '';
       parastr += "?";
       for (var prop in paraobj) {
         parastr += prop + "=" + paraobj[prop] + "&";
       }
        xhr.open('get', parastr != "?" ? (url + parastr) : url, true);
        xhr.send();

}

3. ajax请求成功,且有数据的时候创建下拉框并在下拉框中追加选项       ////创建下拉Div
创建下拉框代码:


createShowDiv: function() {

///如果下拉div已存在,删除掉
     var parentNode = this.autoElement.parentNode || this.autoElement.parentElement;
     var childNodes = parentNode.childNodes;
     var showDiv = document.getElementById(this.config.showdivId);
     if (showDiv) {
       parentNode.removeChild(showDiv);
     }
     //创建下拉Div
     var div = document.createElement('div');
     div.id = this.config.showdivId;
     //设置下拉div样式
     var style = this.config.style || {
       width: '200px',
       height: 'auto',
       backgroundColor: '#1c5683',
       cursor: 'pointer',
       display: 'block'
     };<br>    
     for (var prop in style) {
       div.style[prop] = style[prop];
     }
     this.showdiv = div;
   }

追加选项代码:


appendChild: function(data) {
     var self = this;
     var data = data;
     var fragment = document.createDocumentFragment();
     for (var i = 0; i < data.length; i++) {
       var obj = data[i];
       var child = document.createElement('div');
       child.style.width = self.showdiv.style.width;
       child.style.border = '1px';
       child.style.borderStyle = 'solid';
       child.style.borderTopColor = 'white';
       child.setAttribute('key', obj[self.config.valueFiled]);
       child.innerHTML = obj[self.config.textFiled];
       fragment.appendChild(child);
     }
     self.showdiv.appendChild(fragment);
     self.util.insertAfter(self.showdiv, self.autoElement);

//为下拉框添加点击事件
     self.util.AddEvt(self.showdiv, 'click', function(e) {
       var evt = e || window.event;
       var target = evt.srcElement || evt.target;
       var key = target.getAttribute("key");
       var val = target.innerHTML;
       self.autoElement.value = val;
       self.closeDiv();
       self.config.select.call(self, key, val);
     });
   }

上面说的是主要的几步思路,现在看一下怎么将这些代码封装到一个对象中,让它成为插件。这时候我们用到匿名闭包:


(function(win) {
 var autocomplete= function() {
   this.Init.apply(this, arguments);

}

autocomplete.prototype = {

////添加相关操作代码

Init: {}, ///初始化参数

Render: {},

createShowDiv: {}, ///创建下拉div

appendChild: {}, ///在下拉div里面追加显示项

closeDiv: {}, ////关闭下拉框

//////工具对象,事件,请求,还有dom节点操作的函数

util: {

AddEvt: {}, ///添加事件

insertAfter: {}, ///在某元素后面追加元素

get: {} //// Ajax get请求

}

}

win.Autocomplete= function(paraobj) {
   new autocomplete(paraobj).Render();
 }
})(window)


主体的代码添加好了,我们把具体的实现代码展示出来:


(function(win) {
 var autocomplete = function () {
   this.Init.apply(this, arguments);
 }
 autocomplete.prototype = {
   Init: function() {
     var args = Array.prototype.slice.call(arguments);
     if (args && args.length > 0) {
       var config = args[0];
       var getType = Object.prototype.toString;
       if (config && getType.call(config) == "[object Object]") {
         //       this.config = config;
         this.config = config || {
           id: '', //控件id
           data: [], //数据
           textFiled: '', //显示的文字的属性名
           valueFiled: '', //获取value的属性名
           style: {}, //显示的下拉div的样式设置
           url: '', //ajax请求的url
           paraName:'name',//ajax请求的参数
           select: function() {}, //选择选项时触发的事件,
           showdivId: '' //下拉选择区域的id
         };
       }
     }
   },
   Render: function() {
     var self = this;
     if (self.config) {
       var autoElement = document.getElementById(self.config.id);
       this.autoElement = autoElement;
       if (autoElement) {
         self.util.AddEvt(this.autoElement, 'input', function() {
           try {
             if (autoElement.value) {
               ////ajax请求获取数据的方式
               if (self.config.url && !self.config.data) {
                 var paraobj = {};
                 paraobj[self.config.paraName] = autoElement.value;
                 self.util.get(self.config.url, paraobj, function (data) {
                   self.createShowDiv();
                   self.appendChild(eval('(' + data + ')'));
                 }, 10000);
               }
               ////直接设置对象数组的形式
               else if
                 (!self.config.url && self.config.data) {
                 self.createShowDiv();
                 self.appendChild(self.config.data);
               }

} else {
               self.closeDiv();
             }

} catch (e) {
             //TODO handle the exception
             alert(e);
           }
         });
       }

}
   },
   ////创建下拉Div
   createShowDiv: function() {

///如果下拉div已存在,删除掉
     var parentNode = this.autoElement.parentNode || this.autoElement.parentElement;
     var childNodes = parentNode.childNodes;
     var showDiv = document.getElementById(this.config.showdivId);
     if (showDiv) {
       parentNode.removeChild(showDiv);
     }
     //创建下拉Div
     var div = document.createElement('div');
     div.id = this.config.showdivId;
     //设置下拉div样式
     var style = this.config.style || {
       width: '200px',
       height: 'auto',
       backgroundColor: '#1c5683',
       cursor: 'pointer',
       display: 'block'
     };
     for (var prop in style) {
       div.style[prop] = style[prop];
     }
     this.showdiv = div;
   },
   ///在下拉div里面追加显示项
   appendChild: function(data) {
     var self = this;
     var data = data;
     var fragment = document.createDocumentFragment();
     for (var i = 0; i < data.length; i++) {
       var obj = data[i];
       var child = document.createElement('div');
       child.style.width = self.showdiv.style.width;
       child.style.border = '1px';
       child.style.borderStyle = 'solid';
       child.style.borderTopColor = 'white';
       child.setAttribute('key', obj[self.config.valueFiled]);
       child.innerHTML = obj[self.config.textFiled];
       fragment.appendChild(child);
     }
     self.showdiv.appendChild(fragment);
     self.util.insertAfter(self.showdiv, self.autoElement);

//为下拉框添加点击事件
     self.util.AddEvt(self.showdiv, 'click', function(e) {
       var evt = e || window.event;
       var target = evt.srcElement || evt.target;
       var key = target.getAttribute("key");
       var val = target.innerHTML;
       self.autoElement.value = val;
       self.closeDiv();
       self.config.select.call(self, key, val);
     });
   },
   ////关闭下拉框
   closeDiv: function () {
     if (this.showdiv) {
       this.showdiv.style.display = 'none';
     }

}
   ,
   util: {
     ///添加事件
     AddEvt: function(ele, evt, fn) {
       if (document.addEventListener) {
         ele.addEventListener(evt, fn, false);
       } else if (document.attachEvent) {
         ele.attachEvent('on' + (evt == "input" ? "propertychange" : evt), fn);
       } else {
         ele['on' + (evt == "input" ? "propertychange" : evt)] = fn;
       }
     },
     ///在某元素后面追加元素
     insertAfter: function(ele, targetELe) {
       var parentnode = targetELe.parentNode || targetELe.parentElement;
       if (parentnode.lastChild == targetELe) {
         parentnode.appendChild(ele);
       } else {
         parentnode.insertBefore(ele, targetELe.nextSibling);
       }
     },
     ///Get请求
     get: function(url, paraobj, fn, timeout) {
       var xhr = null;
       try {
         if (window.XMLHttpRequest) {
           xhr = new XMLHttpRequest();
         } else if (Window.ActiveXObject) {

xhr = new ActiveXObject("Msxml2.Xmlhttp");
         }
       } catch (e) {
         //TODO handle the exception
         xhr = new ActiveXObject('Microsoft.Xmlhttp');
       }
       xhr.onreadystatechange = function() {
         if (this.readyState == 4 && this.status == 200) {
           fn.call(this, this.responseText);

} else {
           setTimeout(function() {

xhr.abort();
           }, timeout);
         }
       };
       var parastr = '';
       parastr += "?";
       for (var prop in paraobj) {
         parastr += prop + "=" + paraobj[prop] + "&";
       }
        xhr.open('get', parastr != "?" ? (url + parastr) : url, true);
        xhr.send();

}
   }
 }

win.AutoComplete = function (paraobj) {
   new autocomplete(paraobj).Render();

}

})(window)

下面是使用的代码

页面调用


window.onload = function () {
 AutoComplete({
   id: 'txtTest', //控件id
   url: '/Home/Test4', //数据
   paraName:'name',
   textFiled: 'name', //显示的文字的属性名
   valueFiled: 'id', //获取value的属性名
   //         style: {}, //显示的下拉div的样式设置
   //           url: '', //ajax请求的url
   select: function (val, text) {
     alert(val + '---' + text);
   }, //选择选项时触发的事件,
   showdivId: 'showDIv' //下拉选择区域的id});
 });

}

后台代码如下,这里我用的是mvc


public JsonResult Test4(string  name)
{
 var list=new List<Student>();
 list.Add(new Student { id="1",name="aaaaa"});
 list.Add(new Student { id = "2", name = "aacc" });

list.Add(new Student { id = "3", name = "aabb" });
 list.Add(new Student { id = "4", name = "bbcc" });

if (!string.IsNullOrEmpty(name))
 {
   list = list.Where(p => p.name.Contains(name)).ToList();
 }
 return Json(list,JsonRequestBehavior.AllowGet);
}

  现在基本的功能实现和调用讲完了,从开始到最后的过程是比较麻烦的,每个方法都是一步步实现,没有引用其他的库,要考虑到各个浏览器的兼容性。

0
投稿

猜你喜欢

手机版 网络编程 asp之家 www.aspxhome.com