这篇文章主要介绍了在 IE8 上 JS 实现 combobox 支持拼音检索功能的相关资料,本文介绍的非常详细,具有参考借鉴价值, 需要的朋友可以参考下
Javascript 是一种由 Netscape 的 LiveScript 发展而来的原型化继承的基于对象的动态类型的区分大小写的客户端脚本语言,主要目的是为了解决服务器端语言,比如 Perl,遗留的速度问题,为客户提供更流畅的浏览效果。
最近在 ie8 碰到一个 js 问题,需要实现 (ie8) 使用拼音或者拼音首字母来检索 select 中的内容,原来的 combobox 只能支持汉字输入检索,现在需要进行改进,现在我将一步一步的实现方法记录下来,功能简单,也可能有 bug 和不足,供学习参考。(本文只是提供思路学习和备份,实际情况需要在 ie8 或者 ie 兼容模式上使用,所以没有考虑到别的浏览器)
目录结构:
test
|--js
|--index.html
在 index 页面中添加
index.html
- <!DOCTYPE html>
- <html>
- <head>
- <meta charset="utf-8" />
- <title>
- </title>
- <script type="text/javascript" src="js/autoComplete.js">
- </script>
- <script type="text/javascript">
- </script>
- </head>
- <body>
- <input type="text" id="txtDisplay" />
- <select id="city">
- <option value="1">
- 北京
- </option>
- <option value="2">
- 上海
- </option>
- <option value="3">
- 广州
- </option>
- <option value="4">
- 深圳
- </option>
- <option value="5">
- 重庆
- </option>
- <option value="6">
- 天津
- </option>
- <option value="7">
- 沈阳
- </option>
- <option value="8">
- 南京
- </option>
- <option value="9">
- 武汉
- </option>
- <option value="10">
- 长春
- </option>
- <option value="11">
- 成都
- </option>
- <option value="12">
- 大连
- </option>
- <option value="13">
- 杭州
- </option>
- <option value="14">
- 青岛
- </option>
- <option value="15">
- a济南
- </option>
- <option value="16">
- 厦门
- </option>
- <option value="17">
- 福州
- </option>
- <option value="18">
- 西安
- </option>
- <option value="19">
- 长沙
- </option>
- <option value="20">
- 哈尔滨
- </option>
- </select>
- </body>
- </html>
效果:开始将 select 的下拉列表框隐藏,当点击 input 文本框的时候显示到 input 框的下面,选择完成后再将 select 隐藏。
js 实现:
如果一个页面有多个地方需要实现这样的功能,这个时候就要使用面向对象的思维,尽可能代码重用,我们需要自定义一个 ap 这样的集合。
autoComplete.js
- function Map() {
- /** 存放键的数组(遍历用到) */
- this.keys = new Array();
- /** 存放数据 */
- this.data = new Object();
- /**
- * 放入一个键值对
- * @param {String} key
- * @param {Object} value
- */
- this.put = function(key, value) {
- if(this.data[key] == null){
- this.keys.push(key);
- }
- this.data[key] = value;
- };
- /**
- * 获取某键对应的值
- * @param {String} key
- * @return {Object} value
- */
- this.get = function(key) {
- return this.data[key];
- };
- /**
- * 删除一个键值对
- * @param {String} key
- */
- this.remove = function(key) {
- this.keys.remove(key);
- this.data[key] = null;
- };
- /**
- * 遍历Map,执行处理函数
- *
- * @param {Function} 回调函数 function(key,value,index){..}
- */
- this.each = function(fn){
- if(typeof fn != 'function'){
- return;
- }
- var len = this.keys.length;
- for(var i=0;i<len;i++){
- var k = this.keys[i];
- fn(k,this.data[k],i);
- }
- };
- /**
- * 获取键值数组(类似Java的entrySet())
- * @return 键值对象{key,value}的数组
- */
- this.entrys = function() {
- var len = this.keys.length;
- var entrys = new Array(len);
- for (var i = 0; i < len; i++) {
- entrys[i] = {
- key : this.keys[i],
- value : this.data[i]
- };
- }
- return entrys;
- };
- /**
- * 判断Map是否为空
- */
- this.isEmpty = function() {
- return this.keys.length == 0;
- };
- /**
- * 获取键值对数量
- */
- this.size = function(){
- return this.keys.length;
- };
- /**
- * 重写toString
- */
- this.toString = function(){
- var s = "{";
- for(var i=0;i<this.keys.length;i++,s+=','){
- var k = this.keys[i];
- s += k+"="+this.data[k];
- }
- s+="}";
- return s;
- };
- }
- Array.prototype.remove = function(s) {
- for (var i = 0; i < this.length; i++) {
- if (s == this[i])
- this.splice(i, 1);
- }
- }
现在我们要写一个程序加载入口文件,用来将 input 和 select 的对象传入,然后进行事件绑定等等一系列的操作。
- var autoCompleteMap = new Map(); //组件容器,便于组件事件驱动时调用,同时支持多组件管理
- var splitFleg = "_"; //分隔符
- /**
- * 文本框,下拉框组合成自动补全组件
- * @param {Object} txtObj 文本框对象
- * @param {Object} selectObj 下拉框对象
- * @param {int} selectSize 显示下拉框的数量
- * @param {int} selectLength 下拉框的长度
- */
- function AutoComplete(txtObj, selectObj, selectSize, selectLength) {
- this.cacheContainer = new Array(); //缓存容器,用来在页面刚刚加载的时候将option中的内容缓存到cacheContainer中
- this.init = function() {
- this.initCache(); //缓存数据,将option的数据缓存到cacheContainer
- this.initCSS(); //初始化css 将select隐藏
- this.registerEvent(); //注册事件
- this.setSelectIdPosition(); //设置select的位置
- // 缓存当前组件,便于组件事件驱动时调用,同时支持多组件管理
- autoCompleteMap.put(txtObj.id + selectObj.id, this);
- // 界面刷新后,将直属机构下拉框text值,写入文本框
- var selectIndex = selectObj.selectedIndex;
- if (selectIndex > 0) //第一个内容一般是 【请选择】,如果没有则将>0改为>=0
- txtObj.value = selectObj.options[selectIndex].text;
- }
- //缓存数据,将option的数据缓存到cacheContainer
- this.initCache = function() {
- var select_options = selectObj.options;
- if (select_options == null || select_options.length == 0) {
- return;
- }
- this.cacheContainer = [];
- for (var i = 0; i < select_options.length; i++) {
- this.cacheContainer[i] = select_options[i].text + splitFleg + select_options[i].value;
- }
- }
- this.initCSS = function() {
- selectObj.style.display = "none";
- selectObj.style.position = "absolute";
- selectObj.style.zIndex = 2;
- selectObj.style.width = selectLength + "px";
- selectObj.multiple = "multiple";
- txtObj.style.width = selectLength - 5 + "px";
- }
- this.registerEvent = function() {
- // 下拉框事件
- selectObj.ondblclick = this.doubleClickEvent;
- selectObj.onkeyup = this.keyupEvent;
- selectObj.onblur = this.OnblurEvent;
- selectObj.onfocus = this.OnfocusEvent;
- // 文本框事件
- txtObj.onfocus = this.OnfocusEvent;
- txtObj.onblur = this.OnblurEvent;
- txtObj.onkeyup = this.txtObjKeyupEvent;
- }
- this.setSelectIdPosition = function() {
- var position = this.findPosition(txtObj);
- selectObj.style.left = position[0] + "px";
- selectObj.style.top = position[3] + 3 + "px";
- }
- this.findPosition = function(oElement) {
- var x2 = 0;
- var y2 = 0;
- var width = oElement.offsetWidth;
- var height = oElement.offsetHeight;
- if (typeof(oElement.offsetParent) != 'undefined') {
- for (var posX = 0, posY = 0; oElement; oElement = oElement.offsetParent) {
- posX += oElement.offsetLeft;
- posY += oElement.offsetTop;
- }
- x2 = posX + width;
- y2 = posY + height;
- return [posX, posY, x2, y2];
- } else {
- x2 = oElement.x + width;
- y2 = oElement.y + height;
- return [oElement.x, oElement.y, x2, y2];
- }
- }
- //-----------------绑定的事件------------------------
- /**
- * select下拉列表框双击事件
- */
- this.doubleClickEvent = function() {
- selectObj.style.display = "none";
- var selectIndex = selectObj.selectedIndex;
- txtObj.value = selectObj.options[selectIndex].text;
- }
- /**
- * 鼠标点击松开事件
- */
- this.keyupEvent = function() {
- var autocomplete = autoCompleteMap.get(txtObj.id + selectObj.id);
- if (event.keyCode == 13) {
- event.returnValue = false;
- var srcElem = document.activeElement; //获取当前聚焦的对象
- var testval = srcElem.id;
- if (testval == selectObj.id) {
- autocomplete.doubleClickEvent();
- }
- }
- }
- /**
- * 聚焦事件
- */
- this.OnblurEvent = function() {
- var srcElem = document.activeElement;
- var testval = srcElem.id;
- if (testval != selectObj.id && testval != txtObj.id) { //如果没有聚焦到当前input框或者select列表
- selectObj.style.display = "none"; //将select列表隐藏
- }
- }
- /**
- * 聚焦事件
- */
- this.OnfocusEvent = function() {
- var autocomplete = autoCompleteMap.get(txtObj.id + selectObj.id);
- autocomplete.setSelectIdPosition();
- var srcElem = document.activeElement;
- var testval = srcElem.id;
- if (testval == selectObj.id || testval == txtObj.id) { //聚焦在当前对象
- if (txtObj.value.length != 0) { //当input框中存在字符,则不进行任何操作
- return;
- }
- var selectIdLength = selectObj.options.length;
- if (selectIdLength > selectSize) {
- selectObj.size = selectSize;
- } else {
- selectObj.size = selectIdLength;
- }
- selectObj.style.display = "block";
- }
- }
- var myTimeout = null;
- /**
- * 文本框鼠标聚焦松开事件 ,设置一个定时器,每个特定的时间执行函数,查询和input框中匹配到的select列表数据并显示
- */
- this.txtObjKeyupEvent = function() {
- var autocomplete = autoCompleteMap.get(txtObj.id + selectObj.id);
- if (event.keyCode == 40) { //input框中点击键盘方向键下,这个时候不需要进行检索,只有在输入的时候触发检索事件
- var srcElem = document.activeElement;
- var testval = srcElem.id;
- if (testval == txtObj.id) {
- selectObj.focus();
- if (selectObj.options.length >= 1)
- selectObj.options[0].selected = true;
- }
- return;
- }
- if (autocomplete.myTimeout != null) { //清空设置的定时执行事件
- clearTimeout(autocomplete.myTimeout);
- }
- autocomplete.myTimeout = setTimeout(autocomplete.doAJAX, 200);
- }
- //----------------------------检索显示匹配数据-----------------------------
- /**
- * 做主要的查询匹配操作
- */
- this.doAJAX = function() {
- var autocomplete = autoCompleteMap.get(txtObj.id + selectObj.id);
- //清空原来的OPTIONS
- autocomplete.clearAllOptions();
- autocomplete.setSelectIdPosition();
- var inputStr = txtObj.value;
- var arrays = autocomplete.compareInput(inputStr); //匹配符合查询条件的数据
- if (arrays == null || arrays.length == 0) {
- selectObj.style.display = "none";
- return;
- }
- selectObj.style.display = "block";
- for (var i = 0; i < arrays.length; i++) {
- var optionParams = arrays[i].split(splitFleg);
- var opt = new Option();
- opt.text = optionParams[0];
- opt.value = optionParams[1];
- selectObj.add(opt);
- }
- if (arrays.length > selectSize) {
- selectObj.size = selectSize;
- } else {
- selectObj.size = arrays.length;
- }
- }
- /**
- * 清空原来的OPTIONS
- */
- this.clearAllOptions = function() {
- //清空原来的OPTIONS
- var nL = selectObj.options.length;
- while (nL > 0) {
- selectObj.remove(selectObj.options.length - 1);
- nL = selectObj.options.length;
- }
- }
- //--------------------------数据检索规则---------------------
- /**
- * 数据检索规则
- * @param {String} inputStr input框中需要进行匹配的条件
- */
- this.compareInput = function(inputStr) {
- if (this.cacheContainer.length == 0) {
- return;
- }
- inputStr = inputStr.replace(/(^[\s]*)/g, ""); //去前边空白字符串
- inputStr = this.deleteSpecialSpace(inputStr); //去除特殊空白字符串
- if (inputStr == null || inputStr.length == 0) {
- return this.cacheContainer;
- }
- inputStr = disableSpecialCharacter(inputStr); //特殊字符处理
- var resultArray = new Array();
- var k = 0;
- var selectText = "";
- for (var i = 0; i < this.cacheContainer.length; i++) {
- selectText = (this.cacheContainer[i].split(splitFleg)[0]).replace(/(^[\s]*)/g, "");
- selectText = this.deleteSpecialSpace(selectText);
- if (compareRules(inputStr, selectText)) { //匹配规则
- resultArray[k] = this.cacheContainer[i];
- k++;
- }
- }
- return uniqueArray(resultArray);
- }
- /**
- * 去除特殊空白字符串
- */
- this.deleteSpecialSpace = function(srcStr) {
- var temp = "";
- for (var i = 0; i < srcStr.length; i++) {
- var charStr = srcStr.charAt(i);
- // 界面特殊空格Unicode=160,此空格既不是全角,也非半角
- if (charStr.charCodeAt(0) == 160) {
- continue;
- }
- temp += charStr;
- }
- return temp;
- }
- }
- /**
- * @param {String} inputStr 需要进行过滤的字符
- * 特殊字符处理
- */
- function disableSpecialCharacter(inputStr) {
- inputStr = inputStr.replace(new RegExp("\\\\", 'g'), "\\\\");
- inputStr = inputStr.replace(new RegExp("\\.", 'g'), "\\.");
- inputStr = inputStr.replace(new RegExp("\\^", 'g'), "\\^");
- inputStr = inputStr.replace(new RegExp("\\{", 'g'), "\\{");
- inputStr = inputStr.replace(new RegExp("\\[", 'g'), "\\[");
- inputStr = inputStr.replace(new RegExp("\\(", 'g'), "\\(");
- inputStr = inputStr.replace(new RegExp("\\|", 'g'), "\\|");
- inputStr = inputStr.replace(new RegExp("\\]", 'g'), "\\]");
- inputStr = inputStr.replace(new RegExp("\\)", 'g'), "\\)");
- inputStr = inputStr.replace(new RegExp("\\*", 'g'), "\\*");
- inputStr = inputStr.replace(new RegExp("\\+", 'g'), "\\+");
- inputStr = inputStr.replace(new RegExp("\\?", 'g'), "\\?");
- return inputStr;
- }
- /**
- * 匹配规则
- * @param {String} inputStr input框字符,匹配条件
- * @param {String} selectText 被匹配文字
- */
- function compareRules(inputStr, selectText) {
- //匹配汉字
- return selectText.indexOf(inputStr) != -1 ;
- }
- /**
- * 过滤重复数据
- * @param {Object} arr 结果数组
- */
- function uniqueArray(arr) {
- if(arr == null || arr.length == 0){
- return arr;
- }
- return arr.reverse().join(",").match( /([^,]+)(?!.*\1)/ig).reverse();
- }
- /**
- * 在原来onload的基础上加上自定义要执行的函数
- * @param {Object} func 加载函数
- */
- function addLoadEvent(func) {
- var oldonload = window.onload;
- if (typeof window.onload != 'function') {
- window.onload = func;
- } else {
- window.onload = function() {
- oldonload();
- func();
- }
- }
- }
引入将汉字转换成拼音的工具 js
pinYinHanZi.js
注意:该版本有一些 bug 和对其他(除 ie)浏览器不兼容性。
以上所述是小编给大家介绍的在 IE8 上 JS 实现 combobox 支持拼音检索功能的相关知识,希望对大家有所帮助,如果大家有任何疑问请给我留言,小编会及时回复大家的。在此也非常感谢大家对 phperz 网站的支持!
来源: http://www.phperz.com/article/17/0330/265547.html