js完美实现@提到好友特效(兼容各大浏览器)


Posted in Javascript onMarch 16, 2015

要求

1.输入@时,弹出匹配的好友菜单

2.光标进入包含有"@好友"的标签时,弹出菜单

3.按backspace删除时,如果光标前面是包含有"@好友"的标签,弹出菜单

4.兼容ie,firefox.

具体做法

针对要求一,很自然的会想到对输入框绑定事件。这里要绑定mousedown,而不是mouseup.因为如果是mouseup的话,用event.preventDefault()是无法阻止键盘输入@的。另外,这里在事件回调中用return false也是起不了作用的。

绑定mousedown事件后,就要插入自定义的包含有"@好友"的标签了。新浪微博的输入框是用textarea做的,无法知道其内部是怎样处理的,只好看百度贴吧了。

js完美实现@提到好友特效(兼容各大浏览器)

可以看到,贴吧是插入了<span class='at'></span>标签。这应该是方便后台用正则表达式匹配。

具体的

        vm.check_key=function(e){

            var editor=$('editor'),range;

            if(e.shiftKey&&e.keyCode==50){

                if (document.selection && document.selection.createRange) {

                    range = document.selection.createRange();

                    range.pasteHTML(" <span id='at"+at_index+"' class='at_span'>@</span> ");

                }else{

                    document.execCommand("insertHtml", false," <span id='at"+at_index+"' class='at_span'>@</span> ");

                }

                e.preventDefault();

            }

        };

这里需要在光标处插入,所以用到了range.

然后就是菜单显示了,关键在于怎么定位。我的做法很垃圾,就是为插入的span添加id,然后根据span id的位置为菜单定位。如果有更好的做法,请告诉我一声。

具体的

    function at_box_show(at){

        var at_pos=avalon($(at)).position();

        $('at_box').style.left=at_pos.left+'px';

        $('at_box').style.top=at_pos.top+16+'px';

        $('at_box').style.display='block';

    }

    var at_index=0,cur_index=0;

    avalon.define('editor', function(vm) {

        vm.item_click=function(){

            $('at'+cur_index).innerHTML="@"+this.innerHTML;

            $('at_box').style.display='none';

            at_index++;

        };

        vm.check_key=function(e){

            var editor=$('editor'),a=getCharacterPrecedingCaret(editor),range;

            if(e.shiftKey&&e.keyCode==50){

                if (document.selection && document.selection.createRange) {

                    range = document.selection.createRange();

                    range.pasteHTML(" <span id='at"+at_index+"' class='at_span'>@</span> ");

                }else{

                    document.execCommand("insertHtml", false," <span id='at"+at_index+"' class='at_span'>@</span> ");

                }

                at_box_show('at'+at_index);

                cur_index=at_index;

                e.preventDefault();

            }

        };

    });

at_show_box根据新插入的span id,为at_box定位,然后显示菜单。cur_index表示光标当前所在的span id.设置这个变量因为用户可能倒回去改已经插入的span,而at_index是一直递增的,所以这里就还需要一个变量。

用户点击菜单中好友项,触发item_click回调。回调里就是将好友名字用innserHTML添加到当前span里面.然后隐藏菜单,at_index++。

上面是监听shift+@,接着是监听backspace删除。

    function getTextBeforeCursor(containerEl) {

        var precedingChar = "", sel, range, precedingRange;

        if (window.getSelection) {

            sel = window.getSelection();

            if (sel.rangeCount > 0) {

                range = sel.getRangeAt(0).cloneRange();

                range.collapse(true);

                range.setStart(containerEl, 0);

                precedingChar = range.cloneContents();

            }

        } else if ( (sel = document.selection)) {

            range = sel.createRange();

            precedingRange = range.duplicate();

            precedingRange.moveToElementText(containerEl);

            precedingRange.setEndPoint("EndToStart", range);

            precedingChar = precedingRange.htmlText;

        }

        return precedingChar;

    }

getTextBeforeCursor的作用是获取光标前的内容.由于兼容性,这个函数在标准浏览器中可以得到是光标前所有内容的DocumentFragment,而在ie中就只能得到文本(不是node)了,不过这个html字符串可以转换成DocumentFragment.在avalon中用parseHTML就可以将html字符串变成node了。jquery中用$(html)[0]也能得到node.

有了这个函数,再用lastChild就可以判断光标是不是在光标前html的lastChild里,并且这个lastChild是span。

具体的

               var a=getTextBeforeCursor($('editor'));

                       if(e.keyCode==8){

                if(!-[1,]){

                    var b=avalon.parseHTML(a).lastChild;

                }else{

                    var b=a.lastChild;

                }

                if(b.nodeType==1&&b.nodeName=='SPAN'){

                    var id=b.id;

                    cur_index=b.id.substring(2);

                    at_box_show(b.id);

                }else

                    $('at_box').style.display='none';

            }

最后是光标进入span标签,显示菜单。这个很显然需要绑定鼠标事件。这里绑定mouseup,因为如果绑定mousedown的话,需要鼠标在span标签再点一次才能显示菜单。至于原理,和上面差不多。

        vm.check_mouse=function(e){

            var editor=$('editor'),a=getTextBeforeCursor(editor);

            if(!-[1,]){

                var b=avalon.parseHTML(getTextBeforeCursor(editor)).lastChild;

            }else{

                var b=a.lastChild;

            }

            if(b!=null&&b.nodeType==1&&b.nodeName=='SPAN'){

                var id=b.id;

                cur_index=b.id.substring(2);

                at_box_show(b.id);

            }else

                $('at_box').style.display='none';

        };

注意,如果光标在span里面,就要取出它的id,at_box根据这个id定位,另外还要重置cur_index.

至于ajax更新菜单,字符匹配我就不做了

效果

firefox

js完美实现@提到好友特效(兼容各大浏览器)

ie8

js完美实现@提到好友特效(兼容各大浏览器)

ie7

js完美实现@提到好友特效(兼容各大浏览器)

ie6

js完美实现@提到好友特效(兼容各大浏览器)

下载

以上就是本文所述的全部内容了,希望对大家了解javascript能够有所帮助。

Javascript 相关文章推荐
js常用函数 不错
Sep 08 Javascript
枚举JavaScript对象的函数
Dec 22 Javascript
jQuery实现长文字部分显示代码
May 13 Javascript
JS分页控件 可用于无刷新分页
Jul 23 Javascript
js 验证身份证信息有效性
Mar 28 Javascript
JS数组的遍历方式for循环与for...in
Jul 31 Javascript
JS实现超过长度限制后自动跳转下一款文本框的方法
Feb 23 Javascript
js面向对象之常见创建对象的几种方式(工厂模式、构造函数模式、原型模式)
Nov 09 Javascript
JS判断字符串字节数并截取长度的方法
Mar 05 Javascript
jQuery实现鼠标经过像翻页和描点链接效果
Aug 08 Javascript
Javascript中常用类型的格式化方法小结
Dec 26 Javascript
js实现简单点赞操作
Mar 17 Javascript
JavaScript DSL 流畅接口(使用链式调用)实例
Mar 15 #Javascript
JavaScript中的DSL元编程介绍
Mar 15 #Javascript
JavaScript中的立即执行函数表达式介绍
Mar 15 #Javascript
Javascript中的arguments与重载介绍
Mar 15 #Javascript
JavaScript中的闭包介绍
Mar 15 #Javascript
Javascript中的匿名函数与封装介绍
Mar 15 #Javascript
Javascript中的方法链(Method Chaining)介绍
Mar 15 #Javascript
You might like
php 图片上添加透明度渐变的效果
2009/06/29 PHP
让的PHP代码飞起来的40条小技巧(提升php效率)
2010/04/12 PHP
PHP 抽象方法与抽象类abstract关键字介绍及应用
2014/10/16 PHP
PHP中把对象数组转换成普通数组的方法
2015/07/10 PHP
PHP/HTML混写的四种方式总结
2017/02/27 PHP
了解一点js的Eval函数
2012/07/26 Javascript
JavaScript高级程序设计(第3版)学习笔记11 内建js对象
2012/10/11 Javascript
javascript在IE下trim函数无法使用的解决方法
2014/09/12 Javascript
JavaScript中判断变量是数组、函数或是对象类型的方法
2015/02/25 Javascript
基于jquery实现复选框全选,反选,全不选等功能
2015/10/16 Javascript
jQuery实现ctrl+enter(回车)提交表单
2015/10/19 Javascript
Vue resource中的GET与POST请求的实例代码
2017/07/21 Javascript
Node.js实现连接mysql数据库功能示例
2017/09/15 Javascript
详解 vue better-scroll滚动插件排坑
2018/02/08 Javascript
jQuery插件实现弹性运动完整示例
2018/07/07 jQuery
更优雅的微信小程序骨架屏实现详解
2019/08/07 Javascript
零基础写python爬虫之urllib2中的两个重要概念:Openers和Handlers
2014/11/05 Python
Python文档生成工具pydoc使用介绍
2015/06/02 Python
Python赋值语句后逗号的作用分析
2015/06/08 Python
wxPython的安装图文教程(Windows)
2017/12/28 Python
Python处理中文标点符号大集合
2018/05/14 Python
Python图像处理之简单画板实现方法示例
2018/08/30 Python
python学生信息管理系统实现代码
2019/12/17 Python
详解canvas在圆弧周围绘制文本的两种写法
2018/05/22 HTML / CSS
英国最大的香水商店:The Fragrance Shop
2018/07/06 全球购物
业务副厂长岗位职责
2014/01/03 职场文书
保护环境倡议书
2014/04/14 职场文书
房产转让协议书(2014版)
2014/09/30 职场文书
2014年银行柜员工作总结
2014/11/12 职场文书
大学生创业事迹材料
2014/12/30 职场文书
员工手册编写范本
2015/05/14 职场文书
教师继续教育反思周记
2015/06/25 职场文书
2019脱贫攻坚工作总结报告范本!
2019/08/06 职场文书
Ajax是什么?Ajax高级用法之Axios技术
2021/04/21 Javascript
浅谈Python响应式类库RxPy
2021/06/14 Python
Android开发EditText禁止输入监听及InputFilter字符过滤
2022/06/10 Java/Android