营业开辟情境之:完成一个@功用

近来接到了一个营业需求,让用户能够经由过程网页谈天框的体式格局在线完成生意业务,一个用户能够有多个营业群,个中一个功用就是要@人,@这个功用在实际的运用中经常能够碰到,比方微博、QQ都有@功用,本日我们就以前端的体式格局谈谈怎样一步步完成一个@功用。

@功用涉及到的原生API

  • obj.selectionStart猎取光标位置

  • obj.setSelectionRange(n, n)设置光标位置

  • keyup事宜和keydown事宜

1.搭建我们的html文件

几个处所迥殊申明下:实际操纵中,我们涌现了@选框要及时更新列表数据,在这个dome中我们先用静态列表替代,结果是一样的。然后这个pre是用来定位@选框用的,注重pre大小,字体要和输入框一样,并将pre相对定位到页面的左上角,并设置不可见。

<!-- 文本输入框 -->
<textarea id="app" class="con" contenteditable="true"></textarea>
<!-- 提交按钮 -->
<input type="button" class="submit" id="submit" value="提交">
<!-- @选框 -->
<div id="selectuser" class="selectbox" style="display:none;">
    <h2>@用户</h2>
    <ul id="selectlist">
        <li uid="1">陆小凤</li>
        <li uid="2">西门吹雪</li>
        <li uid="3">百晓生</li>
        <li uid="4">张无忌</li>
        <li uid="5">赵敏</li>
        <li uid="6">段誉</li>
        <li uid="7">虚竹</li>
        <li uid="8">段德</li>
        <li uid="9">周杰伦</li>
        <li uid="10">张学友</li>
    </ul>
</div>
<!-- 暂存输入框数据 -->
<pre id="pre_text"></pre>

2、完成@选框涌现,并将@选框定位到当前光标右下角

详细完成思绪:检测键盘的左侧是不是是@字符,假如有的话,将输入框光标前面的内容复制一份到pre,并在pre背面增添一个span,这个sapn用来辅佐定位@选框的。我们算出这个span相对于页面左上角的left和top,就是等下@选框相对于文本框的left和top的间隔,由于我们@选框是相对定位相对于body,所以在加上文本框相对于body的offsetLeft和offsetTop就是我们@选框所要定位的left和top了。

//全局定义一个变量为光标位置
var cursor;
//文本框绑定keyup事宜,检测输入
textapp.addEventListener('keyup', function(e){
    //猎取光标
    cursor = textapp.selectionStart;
    // 当前光标所在位置的前一名为@字符,涌现@选框
    if(textapp.value.substring(0,cursor).charAt(cursor-1) === '@'){
        // 推断末了一个字符是不是为@
        pre_text.innerHTML = textapp.value.substring(0,cursor);
        pre_text.innerHTML += '<span id="proxy" style="display:inline-block; width: 100px;"></span>';
        var span = document.getElementById('proxy');
        var conX = textapp.offsetLeft;
        var conY = textapp.offsetTop;
        var spanX = span.offsetLeft + conX;
        var spanY = span.offsetTop + conY;
        selectuser.style.left = spanX + 'px';
        selectuser.style.top = spanY + 'px';
        selectuser.style.display = 'block';
        //设置@选框的默许款式
        listSet();
    }else{
        selectuser.style.display = 'none';
    }    
})
// @框默许设置
function listSet() {
    var list = $('#selectlist');
    list.focus();
    $('#selectlist').find('li').eq(0).addClass('hover').siblings('li').removeClass('hover');
    $('#selectuser').scrollTop(0);
}

3.键盘直接操纵@选框

当我们的@选框涌现了,而且定位好了,涌现在我们想要的位置了,我们直接用键盘上下去挑选所要@的人了(鼠标点击选中状况等下引见)。这里我们要斟酌的点有两个:1.当我们光标在输入框末了,我们按上下摆布光标就会变化位置。2.挑选以后光标位置的变化。

1的解决办法是:我们光标位置的变化是在keydown的时刻实行的,keydown是先于我们的keyup之前实行的,所以我们就要在keydown的时刻就阻挠默许,防备光标挪动

textapp.addEventListener('keydown', function(e){
    //建立在@选框涌现的状况下
    if(selectuser.style.display == 'block'){
        var code = e.keyCode;
        //摆布回车时阻挠默许,防备光标挪动
        if(code == 38 || code == 40 || code == 13){
            e.preventDefault();
        }
    }
})

2.选中@人后,我们用setSelectionRange来设置光标的位置,将下面这段代码输入框keyup绑定事宜内里,放在最前面

    // 当@选框存在时,推断键盘上移,下移,以及回车选中事宜
    if(selectuser.style.display == 'block'){
        var code = e.keyCode;
        if(code == 38){
            // 上移
            preCode();
            return;
        }else if (code == 40){
            // 下移
            nextCode();
            return;
        }else if(code == 13){
            //回车选中@人
            var textname = '';
            $('#selectlist').find('li').each(function(){
                if($(this).hasClass('hover')){
                    textname = $(this).html();
                }
            });
            //@完后文本框显现内容
            $('#app').val(getText($('#app').val(), cursor, textname));
            //增加后光标的位置
            var n = textname.length + 1 + cursor;
            //设置光标的位置
            textapp.setSelectionRange(n, n);
            //选中后隐蔽@选框
            $('#selectuser').hide();
            return;
        }
    }

上面这段代码我们用到了三个函数

    // 键盘上移
    function preCode() {
        var index = $('#selectlist').find('.hover').index();
        if(index == 0){
            return;
        }else{
            index--;
            $('#selectuser').scrollTop(index * 26);
            $('#selectlist').find('li').eq(index).addClass('hover').siblings('li').removeClass('hover');
        }
    }
    // 键盘下移
    function nextCode() {
        var len = $('#selectlist').find('li').length;
        var index = $('#selectlist').find('.hover').index();
        if(index == len-1){
            return;
        }else{
            index++;
            $('#selectuser').scrollTop(index * 26);
            $('#selectlist').find('li').eq(index).addClass('hover').siblings('li').removeClass('hover');
        }
    }
    //@人的文本格式,为背面加一个空格,背面用到 
    function getText(app, cursor, textname) {
        var text1 = app.substring(0, cursor);
        var text2 = app.substring(cursor);
        return text1 + textname + ' ' + text2;
    }

4.提交操纵时,掏出有用的@人

当我们音讯输入完成后,点击发送(我们这里用个提交按钮)。我们要检测这个音讯中是不是有@人,并把当前这条音讯有用的@人掏出来,这里注重并不是说我们之前选中了@某个人后就有用了,能够在这个人的名字中我又输入了其他的字符。所以我们要在发送音讯的时刻做一次搜检,把有用的@人提掏出来,而且以背景划定的数据格式。(我们临时划定为数组吧)。

    // 提交
    $('#submit').on('click', function() {
        var msg = $('#app').val();
        //检测输入框是不是为空
        if(msg === ''){
            alert('内容不能为空!');
            return;
        }
        //返回有用@人列表
        var arr = handleMsg(msg);
    });
    //操纵信息提取有用@人
    function handleMsg(msg) {
        //寄存有用@人id的数组
        var At = [];
        //正则考证吧以@开首空格完毕的选出来已数组的情势
        var arrAt = msg.match(/@{1}([\u4e00-\u9fa5]|\w)+\s{1}/g);
        //申明没有@人,直接韩慧
        if(arrAt === null){
            console.log('没有选中@的人!');
            return At;
        }
        // 对arrAt数组即当前信息@人的列表举行遍历
        for (var i = 0; i < arrAt.length; i++) {
            var username = arrAt[i].replace('@', '').trim();
            // 对照当前群组人选
            var grounpuser = $('#selectlist').find('li');
            for (var j = 0; j < grounpuser.length; j++) {
                //假如名字雷同,则把id放进数组内容
                if(username == grounpuser.eq(j).html()){
                    var uid = grounpuser.eq(j).attr('uid');
                    At.push(uid);
                    break;
                }
            };
        };
        return At;
    }

结束

好了,一个@的功用已基础完成了,剩下的就是经由过程ajax与背景的交互了。假如你以为本篇文章对你有收成请赞下,也能够关注下我,分享事情,进修的前端个人感悟分享。github

    原文作者:cwsjoker
    原文地址: https://segmentfault.com/a/1190000005797788
    本文转自网络文章,转载此文章仅为分享知识,如有侵权,请联系博主进行删除。
点赞