因为我们这里存在两种选择方式,鼠标点击和按 enter 键,两者的区别只在于执行事件的方式,将同样的代码写两遍未免有点不美,这里我们将它摘出来
注意:此处需要区分触发检索事件的符号是 $ 还是 . ,因为符号不同,我们获取的值是不同的,光标定位也是不同
// 选中li当前项 改变输入框value值 定位光标 var changeValue = function(){ var val = _this.val(); var liTxt = _this.dropdown.find(".active").text(); var liTxtLength = liTxt.length; var valLength = val.length; // 此处需要区分触发检索事件的符号是 if( enterCharacter == opts.levelCharacter ){ // 如果是 . var beforeSelectVal = val.substring(0,dotDollerPos); } else{ // 如果是 & var beforeSelectVal = val.substring(0,oldCurrentPos); } var beforeSelectValLength = beforeSelectVal.length; var afterSelectVal = val.substring(currentPos,valLength); var pos = liTxtLength + beforeSelectValLength; val = beforeSelectVal+liTxt+afterSelectVal; _this.val(val); setCarePosition(pos,pos); // 将光标定位在插入值后面 endSearch(); console.log("文本长度:"+beforeSelectVal.length); console.log("li文本为:"+liTxt); console.log("前部为:"+beforeSelectVal); console.log("后部分为:"+afterSelectVal); return false; // 此处必须加上return false 不然会调用callbacktips 初始化 dropdown }
定义回调函数
获取检索值之后就需要发送请求了,我们拿到返回的数组 arr_json 后,将其遍历生成 li 添加到下拉框中
// 定义回调函数 callbacktips var callbacktips = function(arr_json){ // 初始化 UL _this.dropdown.find("li").remove(); if( arr_json ){ for( i=0;i<arr_json.length;i++ ){ var n = arr_json[i].indexOf(selectVal); if( n != -1 ){ _this.dropdown.append('<li>'+arr_json[i]+'</li>'); }else{ return; } }; } _this.dropdown.show(); _this.dropdown.find("li:first-child").addClass("active"); // 自定义样式 _this.dropdown.find("li").css({ 'width':'100%', }); };
获得焦点时获取光标位置
这里我们直接调用上面的方法就行了
// 获得焦点的时候获取光标位置 _this.click(function(){ getOldCurrentPos() });
阻止键盘默认事件
这里我们需要判断下拉框的状态:显示还是隐藏
//下拉框显示时 阻止键盘方向键默认事件 _this.keydown(function(e){ var dropdownIsshow = _this.dropdown.css("display"); if( dropdownIsshow == "block" ){ if( e.keyCode == 38 || e.keyCode == 40 || e.keyCode == 13 ){ e.preventDefault(); } } })
keyup 事件
通过keyuo事件:”我们能实时监听输入框;也能通过按键切换当前项以及改变光标位置;也能限制输入字符范围,比如这里:当输入某些字符时,将会被认为输入了不合法字符而终止检索事件;
我们的事件开关也是通过该事件能改变其状态的以及 enter 键选取当前项
// 监听输入框value值变化 _this.keyup(function(e){ var val = _this.val(); // 当前项索引 var n = _this.dropdown.find(".active").index(); // li 个数 var n_max = _this.dropdown.find("li").length; getStart(); // 获得最新光标位置 // 方向键控制 li 选项 if( e.keyCode == 38 ){ if(n-1>=0){ _this.dropdown.find('li').eq(n-1).addClass("active").siblings().removeClass("active"); } if( n == 0){ _this.dropdown.find('li').eq(n_max-1).addClass("active").siblings().removeClass("active"); } return false; // 此处必须加上return false 不然会重复初始化 } if( e.keyCode == 40 ){ if(n<n_max-1){ _this.dropdown.find('li').eq(n+1).addClass("active").siblings().removeClass("active"); } if( n+1 == n_max ){ _this.dropdown.find('li').eq(0).addClass("active").siblings().removeClass("active"); } return false; // 此处必须加上return false 不然会重复初始化 } if( e.keyCode != 37 && e.keyCode != 38 && e.keyCode != 39 && e.keyCode != 40 ){ var reg = new RegExp("[`~!@#^&*()=|{}':;',\\[\\]<>/?~!@#¥……&*()——|{}【】‘;:”“'。,、?]"); enterCharacter = val.substring(currentPos-1,currentPos); // 当前输入的字符 //console.log(enterCharacter); if( reg.test(enterCharacter) == false && enterCharacter != " "){ // 输入的字符合法 可以执行检索事件 //console.log("输入字符合法"); checkCharacter = true; }else{ checkCharacter = false; endSearch() console.log("输入了不合法字符"); //console.log(selectVal); } } console.log("当前输入的字符是:"+enterCharacter); if( enterCharacter == opts.triggerCharacter || enterCharacter == opts.levelCharacter){ console.log("输入了$或者."); // 输入了 $,打开开关,允许检索事件执行 searchStart = true; getOldCurrentPos(); // 输入 $ 的时候重置 oldCurrentPos } getSelectVal(); // 外度调用获取检索值方法 保证实时更新 selectVal 及 searchStart if( searchStart == true && checkCharacter == true && e.keyCode != 13 ){ console.log("获取的值:"+selectVal); if( $.isFunction(opts.keyPressAction) ){ opts.keyPressAction(selectVal, function(arr_json){ // 调用回调函数 callbacktips(arr_json); }); } } if( e.keyCode == 13 ){ // 按enter键选取当前li文本值 重组输入框 value值 var dropdownIsshow = _this.dropdown.css("display"); if( dropdownIsshow == "block" ){ // 为了在下拉框隐藏时按 enter键 能换行,需要加上这个判断 changeValue(); console.log("这是点击enter后searchStart:"+searchStart); } } console.log("这是整个事件执行完成以后:"+searchStart); });
鼠标滑入切换当前项
// 切换当前项 _this.dropdown.on('mouseenter','li',function(){ $(this).addClass("active").siblings().removeClass("active"); });
点击选取当前项 失去焦点事件
这里采用了 event.target 方法来获得事件源,如果是 下拉框中的 li ,则执行 changeValue() 方法,否则结束检索事件 endSearch()