• 原生js实现autocomplete插件


            在实际的项目中,能用别人写好的插件实现相关功能是最好不过,为了节约时间成本,因为有的项目比较紧急,没充分时间让你自己来写,即便写了,你还要花大量时间调试兼容性。但是出于学习的目的,你可以利用闲暇时间,自己动手写写,看一些原生js的东西,根据自己的思路做插件,这样能提高水平。

              说到autotemplete,好多人都用过,引用autotemplete.js,然后就可以实现在输入框输入值的时候提示下拉选项,类似于百度搜索框那种提示功能,下面就来说说自己的思路。

    1.  为输入框添加input事件

          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 || {
                     '200px',
                    height: 'auto',
                    backgroundColor: '#1c5683',
                    cursor: 'pointer',
                    display: 'block'
                };
    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 || {
    				 '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);
            }
    

      现在基本的功能实现和调用讲完了,从开始到最后的过程是比较麻烦的,每个方法都是一步步实现,没有引用其他的库,要考虑到各个浏览器的兼容性。如果你有什么疑问,请留言,我会回复。

          

        

  • 相关阅读:
    mysql备份
    Linux 配置参考
    oracle补丁安装
    多智能体城市交通计算综合应用
    基于纳什均衡的多智能体强化学习交通信号控制
    多智能体强化学习在城市交通信号控制中的研究与应用- 笔记
    Sarsa与Q-learning
    Pandas笔记
    Python学习笔记
    Game Theory and Multi-agent Reinforcement Learning笔记 下
  • 原文地址:https://www.cnblogs.com/a546558309/p/4754767.html
Copyright © 2020-2023  润新知