前段时间发了一个编辑器的插件,忙完后自己再次进行了详细的测试,然后心里冒出一句:“这谁写的这么奇葩的插件?完全没什么luan用啊!”
自己做了让自己不满意的事,咋整?男人不怕累,花了时间重写(为世界上所有像我一样勤劳的男人点赞)~
思维导图
在小生看来,在开发每一个新功能的时候都应该做到心中有一张思维导图:功能实现逻辑和实现功能大致的方法。当然我们不可能在还没动手
前就考虑得面面俱到,但在正式开发之前心里对整个流程有个清晰的印象肯定会让我们在动手时愈加流畅(喝口娃哈哈美滋滋,看图~):
流程效果图
触发检索事件字符可自定义,默认为 $,输入 $ 触发检索显示,此时检索值为空,所以显示所有选项,继续输入 a ,检索值为 a,显示匹配选项,当再输入 . 时, 检索值获取条件发生改变(具体我们等下看代码),
图四中为整个流程在控制台中的记录。
js代码 -- 监听输入框
全局变量
考虑到里面小方法比较多,为了简化代码,这里我选择模块化一下,需要用到以下全局变量。这里特别提一下:持续事件和点事件的区别,持续顾名思义,持续事件就是一直触发的事件,这里 $ 触发检索事件后,检索值 selectVal
是变化的,但是我们又不需要它一直处于触发状态,怎么办呢?对,开关,我们可以给这个事件设置一个开关,条件满足时打开开关,事件持续触发,结束后关闭开关,结束检索事件,这里设置的开关是:searchStart;而点事件
这里就是输入 . 时触发的事件,它只需要在输入 . 时获取相关的值就行了,不需要连续触发,这里我们设置参数 enterCharacter : 当前输入的字符
var _this = $(this); var e = event || window.event; // 键值兼容 var searchStart = false; // 设置检索事件开关 var checkCharacter = false; // 输入字符检索开关 var oldCurrentPos = ''; // 检索值开始的位置 var currentPos = ''; // 检索值结束的位置 var selectVal = ''; // 检索值 var pos = ''; // 设置光标位置 var enterCharacter = ''; // 当前输入的字符 var dotVal; // 输入 . 时从0到当前光标位置文本 var dotDollerPos; // 获取往后查找离 . 最近的 $ 的下标,引文输入 . 时的检索值即dotSelectVal不包含 $ 本身,所以需要加1 var dotSelectVal; // 输入 . 时的检索值
插入输入框
首先插入下拉框,当然留到后面插入也可以(你开心你说什么都是对的),但是这里有个点需要注意一下:为什么选择插入在body下?因为我们获取到的下拉框的位置是绝对定位坐标。
// 插入下拉框 _this.dropdown = $('<ul></ul>'); // 获取到的弹出的下拉框的位置是绝对定位的坐标,所以得把弹出的层放到$("body").after(_this.dropdown); _this.dropdown.css({ 'width':opts.dropdownWidth, 'position':'absolute', }); _this.css({ 'position': 'relative', });
注意:这里我们提一下,要获取检索值,即 selectVal,我们需要知道事件触发时光标所在的位置,即 oldCurrentPos,以及光标当前位置 currentPos,有了这两个 下标,我们才能动态获取 selectVal
获取光标当前位置
关于获取输入框光标以及获取值等方法,不了解的朋友可以去看一下 range 方法,当然无数前辈已经做过无数归纳总结讲解(向前辈们敬礼~):
// 获取当前光标位置 currentPos var getStart =function() { var all_range = ''; if (navigator.userAgent.indexOf("MSIE") > -1) { //IE if( _this.get(0).tagName == "TEXTAREA" ){ // 根据body创建textRange all_range = document.body.createTextRange(); // 让textRange范围包含元素里所有内容 all_range.moveToElementText(_this.get(0)); } else { // 根据当前输入元素类型创建textRange all_range = _this.get(0).createTextRange(); } // 输入元素获取焦点 _this.focus(); // 获取当前的textRange,如果当前的textRange是一个具体位置而不是范围,textRange的范围从currentPos到end.此时currentPos等于end var cur_range = document.selection.createRange(); // 将当前的textRange的end向前移"选中的文本.length"个单位.保证currentPos=end cur_range.moveEnd('character',-cur_range.text.length) // 将当前textRange的currentPos移动到之前创建的textRange的currentPos处, 此时当前textRange范围变为整个内容的currentPos处到当前范围end处 cur_range.setEndPoint("StartToStart",all_range); // 此时当前textRange的Start到End的长度,就是光标的位置 currentPos = cur_range.text.length; } else { // 文本框获取焦点 _this.focus(); // 获取当前元素光标位置 currentPos = _this.get(0).selectionStart; //console.log("光标当前位置:"+currentPos); } // 返回光标位置 return currentPos; };
获取检索值开始位置