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 URL传中文参数引发的乱码问题
Sep 02 Javascript
从零开始学习jQuery (二) 万能的选择器
Oct 01 Javascript
js实现兼容IE和FF的上下层的移动
May 04 Javascript
解决jquery实现的radio重新选中的问题
Jul 03 Javascript
前端实现文件的断点续传(前端文件提交+后端PHP文件接收)
Nov 04 Javascript
jQuery Validate验证表单时多个name相同的元素只验证第一个的解决方法
Dec 24 Javascript
如何给ss bash 写一个 WEB 端查看流量的页面
Mar 23 Javascript
JavaScript实现选中文字提示新浪微博分享效果
Jun 15 Javascript
详解react-redux插件入门
Apr 19 Javascript
JS引用传递与值传递的区别与用法分析
Jun 01 Javascript
JS实现简易留言板特效
Dec 23 Javascript
基于JavaScript实现年月日三级联动
Jun 22 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动态生成JavaScript代码
2009/03/09 PHP
完美实现GIF动画缩略图的php代码
2011/01/02 PHP
php实现在站点里面添加邮件发送的功能
2020/04/28 PHP
基于php(Thinkphp)+jquery 实现ajax多选反选不选删除数据功能
2017/02/24 PHP
php解压缩zip和rar压缩包文件的方法
2019/07/10 PHP
Ext.get() 和 Ext.query()组合使用实现最灵活的取元素方式
2011/09/26 Javascript
jQuery 关于伪类选择符的使用说明
2013/04/24 Javascript
jQuery插件EasyUI校验规则 validatebox验证框
2015/11/29 Javascript
javascript特殊日历控件分享
2016/03/07 Javascript
js实现table添加行tr、删除行tr、清空行tr的简单实例
2016/10/15 Javascript
原生js实现无限循环轮播图效果
2017/01/20 Javascript
js正则表达式校验指定字符串的方法
2018/07/23 Javascript
vue-better-scroll 的使用实例代码详解
2018/12/03 Javascript
node Buffer缓存区常见操作示例
2019/05/04 Javascript
浅谈JavaScript中等号、双等号、 三等号的区别
2020/08/06 Javascript
vant-ui组件调用Dialog弹窗异步关闭操作
2020/11/04 Javascript
vue 获取到数据但却渲染不到页面上的解决方法
2020/11/19 Vue.js
原生js 实现表单验证功能
2021/02/08 Javascript
[44:15]DOTA2上海特级锦标赛主赛事日 - 5 败者组决赛Liquid VS EG第二局
2016/03/06 DOTA
python 限制函数调用次数的实例讲解
2018/04/21 Python
python复制文件到指定目录的实例
2018/04/27 Python
Pycharm设置utf-8自动显示方法
2019/01/17 Python
解决django-xadmin列表页filter关联对象搜索问题
2019/11/15 Python
Python类中self参数用法详解
2020/02/13 Python
CSS3教程(9):设置RGB颜色
2009/04/02 HTML / CSS
css3中background新增的4个新的相关属性用法介绍
2013/09/26 HTML / CSS
在IE6系列等老式浏览器中使用HTML5的新标签实现方案
2012/12/25 HTML / CSS
Kate Spade美国官网:纽约新兴时尚品牌,以包包闻名于世
2017/11/09 全球购物
父亲追悼会答谢词
2014/01/17 职场文书
资助贫困学生倡议书
2014/05/16 职场文书
员工生日活动方案
2014/08/24 职场文书
学生意外伤害赔偿协议书
2014/09/17 职场文书
逃课检讨书怎么写
2015/01/01 职场文书
几款流行的HTML5 UI框架比较(小结)
2021/04/08 HTML / CSS
2021年最新用于图像处理的Python库总结
2021/06/15 Python
mysql聚集索引、辅助索引、覆盖索引、联合索引的使用
2022/02/12 MySQL