原生js编写autoComplete插件


Posted in Javascript onApril 13, 2016

最近有提关于下拉选项过多的时候,希望输入关键词,可以搜索内容的需求,但是之前项目太赶,所以也就没有来得及做,因为希望用原生js写一些内容,所以插件是采用了原生js写的思路如下
第一步:fnInit实现初始化一些字段
第二步:加载搜索框的div
第三步:实现search功能,删除原节点并加载新节点
第四步:点击或者回车的时候设置value
代码:
autoComplete.js

/** 
 * @summary   AutoComplete 
 * @description 输入框自动检索下拉选项 
 * @version   0.0.1 
 * @file     autoComplete.js 
 * @author   cangowu 
 * @contact   1138806090@qq.com 
 * @copyright  Copyright 2016 cangoWu. 
 * 
 * 这是一个基于原生js的自动完成搜索的下拉输入框, 
 * 可以通过移动鼠标上下键回车以及直接用鼠标点击 
 * 选中搜索的选项,在一些关键的地方都有注释 
 * 
 * 实例参见: 
 * CSDN博客:http://blog.csdn.net/wzgdjm/article/details/51122615 
 * Github:https://github.com/cangowu/autoComplete 
 * 
 */ 
(function () { 
 
  function AutoComplete() { 
    if (!(this instanceof AutoComplete)) { 
      return new AutoComplete(); 
    } 
    this.sSearchValue = ''; 
    this.index = -1; 
  } 
 
  AutoComplete.prototype = { 
    fnInit: function (option) {//初始化基本信息 
      var oDefault = { 
        id: '', //控件id 
        data: [], //数据 
        paraName: '', 
        textFiled: '', //显示的文字的属性名 
        valueFiled: '', //获取value的属性名 
        style: {}, //显示的下拉div的样式设置 
        url: '', //ajax请求的url 
        select: function () { 
        }, //选择选项时触发的事件 
      }; 
      var _option = option; 
 
      this.sId = _option.id || oDefault.id; 
      this.aData = _option.data || oDefault.data; 
      this.paraName = _option.paraName || oDefault.paraName; 
      this.sTextFiled = _option.textFiled || oDefault.textFiled; 
      this.sValueFiled = _option.valueFiled || oDefault.valueFiled; 
      this.style = _option.style || oDefault.style; 
      this.sUrl = _option.url || oDefault.url; 
      this.fnSelect = _option.select || oDefault.select; 
      this.sDivId = this.sId + new Date().getTime();//加载选项额divid 
 
      //判断如果传入了url,没有传入data数据,就ajax获取数据,否则使用data取数据 
      if (this.sUrl !== '' && this.aData.length === 0) { 
        var that = this; 
        this.util.fnGet(this.sUrl, function (data) { 
          console.log(eval(data)); 
          that.aData = eval(data); 
        }, 10); 
      } 
 
      //给aData排序 
      var sTextField = this.sTextFiled; 
      this.aData.sort(function (a, b) { 
        return a[sTextField] > b[sTextField]; 
      }); 
      //获取控件 
      this.domInput = document.getElementById(this.sId); 
      //this.domDiv = document.getElementById(this.sDivId); 
    }, 
    fnRender: function () {//渲染一些必须的节点 
      var that = this; 
      //生成一个对应的div,承载后面的一些选项的 
      if (that.sDivId) { 
        var domDiv = document.createElement('div'); 
        domDiv.id = that.sDivId; 
        domDiv.style.background = '#fff'; 
        domDiv.style.width = that.domInput.offsetWidth - 2 + 'px'; 
        domDiv.style.position = 'absolute'; 
        domDiv.style.border = '1px solid #a9a9a9'; 
        domDiv.style.display = 'none'; 
        that.util.fnInsertAfter(domDiv, that.domInput); 
 
        //加载之后才能将domDiv赋值为 
        this.domDiv = document.getElementById(this.sDivId); 
      } 
      //给input添加keyup事件 
      that.util.fnAddEvent(that.domInput, 'keyup', function (event) { 
        that.fnSearch(event); 
      }); 
    }, 
    fnSearch: function (event) { 
      //判断如果不是回车键,上键下键的时候执行搜索 
      if (event.keyCode != 13 && event.keyCode != 38 && event.keyCode != 40) { 
        this.fnLoadSearchContent(); 
        this.fnShowDiv(); 
      } else {//搜索之后监测键盘事件 
        var length = this.domDiv.children.length; 
        if (event.keyCode == 40) { 
          ++this.index; 
          if (this.index >= length) { 
            this.index = 0; 
          } else if (this.index == length) { 
            this.domInput.value = this.sSearchValue; 
          } 
          this.domInput.value = this.domDiv.childNodes[this.index].text; 
          this.fnChangeClass(); 
        } 
        else if (event.keyCode == 38) { 
          this.index--; 
          if (this.index <= -1) { 
            this.index = length - 1; 
          } else if (this.index == -1) { 
            this.obj.value = this.sSearchValue; 
          } 
          this.domInput.value = this.domDiv.childNodes[this.index].text; 
          this.fnChangeClass(); 
        } 
        else if (event.keyCode == 13) { 
          this.fnLoadSearchContent(); 
          this.fnShowDiv(); 
          //this.domDiv.style.display = this.domDiv.style.display === 'none' ? 'block' : 'none'; 
          this.index = -1; 
        } else { 
          this.index = -1; 
        } 
      } 
    }, 
    fnLoadSearchContent: function () { 
      //删除所有的子节点 
      while (this.domDiv.hasChildNodes()) { 
        this.domDiv.removeChild(this.domDiv.firstChild); 
      } 
      //设置search的值 
      this.sSearchValue = this.domInput.value; 
      //如果值为空的时候选择退出 
      var sTrimSearchValue = this.sSearchValue.replace(/(^\s*)|(\s*$)/g, ''); 
      if (sTrimSearchValue == "") { 
        this.domDiv.style.display = 'none'; 
        return; 
      } 
      try { 
        var reg = new RegExp("(" + sTrimSearchValue + ")", "i"); 
      } 
      catch (e) { 
        return; 
      } 
      //搜索并增加新节点 
      var nDivIndex = 0; 
      for (var i = 0; i < this.aData.length; i++) { 
        if (reg.test(this.aData[i][this.sTextFiled])) { 
          var domDiv = document.createElement("div"); 
          //div.className="auto_onmouseout"; 
          domDiv.text = this.aData[i][this.sTextFiled]; 
          domDiv.onclick = this.fnSetValue(this); 
          domDiv.onmouseover = this.fnAutoOnMouseOver(this, nDivIndex); 
          domDiv.innerHTML = this.aData[i][this.sTextFiled].replace(reg, "<strong>$1</strong>");//搜索到的字符粗体显示 
          this.domDiv.appendChild(domDiv); 
          nDivIndex++; 
        } 
      } 
    }, 
    fnSetValue: function (that) { 
      return function () { 
        that.domInput.value = this.text; 
        that.domDiv.style.display = 'none'; 
      } 
    }, 
    fnAutoOnMouseOver: function (that, idx) { 
      return function () { 
        that.index = idx; 
        that.fnChangeClass(); 
      } 
    }, 
    fnChangeClass: function () { 
      var that = this; 
      var length = that.domDiv.children.length; 
      for (var j = 0; j < length; j++) { 
        if (j != that.index) { 
          that.domDiv.childNodes[j].style.backgroundColor = ''; 
          that.domDiv.childNodes[j].style.color = '#000'; 
        } else { 
          that.domDiv.childNodes[j].style.backgroundColor = 'blue'; 
          that.domDiv.childNodes[j].style.color = '#fff'; 
        } 
      } 
    }, 
    fnShowDiv: function () { 
      if (this.domDiv.children.length !== 0) { 
        this.domDiv.style.display = this.domDiv.style.display === 'none' ? 'block' : 'none'; 
      } 
    }, 
    util: {//公共接口方法 
      fnInsertAfter: function (ele, targetEle) { 
        var parentnode = targetEle.parentNode || targetEle.parentElement; 
        if (parentnode.lastChild == targetEle) { 
          parentnode.appendChild(ele); 
        } else { 
          parentnode.insertBefore(ele, targetEle.nextSibling); 
        } 
      }, 
      fnAddEvent: 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; 
        } 
      }, 
      fnGet: function (url, 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); 
          } 
        }; 
        xhr.open('get', url, true); 
        xhr.send(); 
      } 
    } 
  } 
 
  window.AutoComplete = function (option) { 
    var aOption = Array.prototype.slice.call(arguments); 
    for(var i=0;i<aOption.length;i++){ 
      var autoComplete = new AutoComplete(); 
      autoComplete.fnInit(aOption[i]); 
      autoComplete.fnRender(); 
    } 
  } 
 
})(window);

index.html

<!DOCTYPE html> 
<html lang="en"> 
<head> 
  <meta charset="UTF-8"> 
  <title>Title</title> 
</head> 
<body> 
 
<div> 
<input type="text" id="txtTest"> 
</div> 
<br> 
<div> 
<input type="text" id="txtTest1"> 
</div> 
 
<script src="autoComplete.js"></script> 
<script> 
 
  window.onload = function () { 
    var option = { 
      id: 'txtTest', //控件id 
      data: [{ 
        "id": "1", 
        "name": "aaaaa" 
      }, { 
        "id": "2", 
        "name": "bbbbb" 
      }, { 
        "id": "2", 
        "name": "bbb吴bb" 
      }, { 
        "id": "2", 
        "name": "bbbzbb" 
      }], 
      paraName: 'name', 
      textFiled: 'name', //显示的文字的属性名 
      valueFiled: 'id', //获取value的属性名 
      select: function (val, text) { 
        alert(val + '' + text); 
      } //选择选项时触发的事件 
    }; 
    var option1 = { 
      id: 'txtTest1', //控件id 
      url: 'data.json', //数据 
      paraName: 'name', 
      textFiled: 'name', //显示的文字的属性名 
      valueFiled: 'id', //获取value的属性名 
      select: function (val, text) { 
        alert(val + '' + text); 
      } //选择选项时触发的事件 
    }; 
    AutoComplete(option,option1); 
 
  } 
 
</script> 
</body> 
</html>

data.json

[ 
 { 
  "id": "1", 
  "name": "aaaaa" 
 }, 
 { 
  "id": "2", 
  "name": "bbbbb" 
 }, 
 { 
  "id": "3", 
  "name": "ccccc" 
 } 
]

以上就是本文的全部内容,希望对大家学习javascript程序设计有所帮助。

Javascript 相关文章推荐
javascript HTMLEncode HTMLDecode的完整实例(兼容ie和火狐)
Jun 02 Javascript
JavaScript 判断指定字符串是否为有效数字
May 11 Javascript
jQuery EasyUI API 中文文档 - MenuButton菜单按钮使用介绍
Oct 06 Javascript
DWR实现模拟Google搜索效果实现原理及代码
Jan 30 Javascript
有关jquery与DOM节点操作方法和属性记录
Apr 15 Javascript
jQuery向父辈遍历的简单方法
Sep 18 Javascript
js判断手机系统是android还是ios
Mar 07 Javascript
AngularJS之页面跳转Route实例代码
Mar 10 Javascript
让微信小程序支持ES6中Promise特性的方法详解
Jun 13 Javascript
JS一个简单的注册页面实例
Sep 05 Javascript
uni-app自定义导航栏按钮|uniapp仿微信顶部导航条功能
Nov 12 Javascript
Vue的props父传子的示例代码
May 20 Javascript
JS中的eval 为什么加括号
Apr 13 #Javascript
jQuery操作属性和样式详解
Apr 13 #Javascript
jquery跟随屏幕滚动效果的实现代码
Apr 13 #Javascript
两种方法解决javascript url post 特殊字符转义 + &amp; #
Apr 13 #Javascript
Angular.js与Bootstrap相结合实现手风琴菜单代码
Apr 13 #Javascript
JQuery 两种方法解决刚创建的元素遍历不到的问题
Apr 13 #Javascript
更高效的使用JQuery 这里总结了8个小技巧
Apr 13 #Javascript
You might like
使用字符串函数输出整数化的PHP版本号
2006/10/09 PHP
PHP和Mysqlweb应用开发核心技术-第1部分 Php基础-2 php语言介绍
2011/07/03 PHP
PHP递归调用的小技巧讲解
2013/02/19 PHP
PHP中如何实现常用邮箱的基本判断
2014/01/07 PHP
PHP中类的自动加载的方法
2017/03/17 PHP
PHP的cookie与session原理及用法详解
2019/09/27 PHP
拖动Html元素集合 Drag and Drop any item
2006/12/22 Javascript
JavaScript Event学习第五章 高级事件注册模型
2010/02/07 Javascript
jQuery在vs2008及js文件中的无智能提示的解决方法
2010/12/30 Javascript
使用CSS3的scale实现网页整体缩放
2014/03/18 Javascript
基于JS实现PHP的sprintf函数实例
2015/11/14 Javascript
理解 JavaScript Scoping &amp; Hoisting(二)
2015/11/18 Javascript
浅谈Sticky组件的改进实现
2016/03/22 Javascript
Vue项目中使用Vux的安装过程
2018/05/01 Javascript
vue中动态select的使用方法示例
2019/10/28 Javascript
javascript实现弹出层效果
2019/12/10 Javascript
vue 通过绑定事件获取当前行的id操作
2020/07/27 Javascript
[43:53]OG vs EG 2019国际邀请赛淘汰赛 胜者组 BO3 第三场 8.22
2019/09/05 DOTA
python操作MongoDB基础知识
2013/11/01 Python
Python复制文件操作实例详解
2015/11/10 Python
python计算两个地址之间的距离方法
2018/06/09 Python
基于Python List的赋值方法
2018/06/23 Python
Python Pandas批量读取csv文件到dataframe的方法
2018/10/08 Python
Python XlsxWriter模块Chart类用法实例分析
2019/03/11 Python
利用Python制作动态排名图的实现代码
2020/04/09 Python
python实现图像随机裁剪的示例代码
2020/12/10 Python
法国房车租赁网站:Yescapa
2019/08/26 全球购物
简单说说tomcat的配置
2013/05/28 面试题
毕业证丢失证明
2014/01/15 职场文书
家庭教育先进个人事迹材料
2014/01/24 职场文书
军训 自我鉴定
2014/02/03 职场文书
安全生产会议制度
2015/08/06 职场文书
2016党员干部反腐倡廉心得体会
2016/01/13 职场文书
教师师德承诺书2016
2016/03/25 职场文书
VUE之图片Base64编码使用ElementUI组件上传
2022/04/09 Vue.js
MySQL选择合适的备份策略和备份工具
2022/06/01 MySQL