JavaScript实现自定义短信模板

2017-01-09  本文已影响637人  Stevenzwzhai

自定义短信模板,要求:可以插入关键字,当然是可以在点击到文本域中的任意位置,关键字以中括号包裹的形式出现【关键字】,删除关键字要整个关键都删掉,而不是自己全删除。

效果图

a.png

这里说下我的思路,要完成这样一个功能,分为以下几点:
1.在指定位置插入关键字
2.删除关键字要整个删除掉,并且关键字是不可编辑的,用户也是不可以输入中文中括号的

首先我们列一下难点

1.在任意位置插入,那肯定要拿到位置坐标,如果获取这个位置?
2.关键字是用中文中括号包裹的,那么用户就不可以去使用中文中括号,怎么阻止用户输入呢?
3.既然是关键字自然是不可以编辑的,怎么让它不可编辑?
4.中文中括号可英文中括号keyCode是一样的,怎么处理?
5.当编辑区域失去焦点的时候,我们立即点关键字肯定就是要插入,但是点击其他地方怎么处理?
6.删除关键字的时候,如何一次按键就整个都删掉?

现在我们来把上面的难点一一解答

1.关于光标位置,我上一篇文章中有写到,这里就不多说了,http://www.jianshu.com/p/19a507cd5fd7.
2.关于第2,3,4一起来说。首先为了防止我们识别关键字出问题,那么就要阻止用户自己输入中括号,说道阻止输入某个字符,大家很容想到,那就是在输入的瞬间就把它删除掉,这个没错。我们在判断按键为左中括号时候去删除的时候,会发现并不能完成整个中括号的删除,因为落下一个右中括号。没错,第一个坑出现了,这是为什么,大家有没有注意到,每次你输入中文中括号的时候,其实只需要按左边中括号就会左右都出现,大括号小括号都是这样。

【】按下左,左右一起出现

好,我们知道了问题所在,那就在右括号按下的时候删掉两个字符,可是,你会发现,如果只按右中括号的时候,他就真的只出现右中括号,所以呢,分开处理。
这次没问题了吧,可是你会发现依然是剩下右边的括号没删除,而且还把前面的括号前的一个字符删掉了,坑吧?这就是第二个坑,你在判断keyCode的时候其实会有三次,第一次是左中括号keyCode,第二次是右中括号,第三次是左箭头。而第二次第三次并不是你按下的,是第一按下之后自动带出的。所以当你按下左中括号之后,其实最后光标是跑到了括号中。

【|】

 obj.addEventListener('keyup', function(e) {
//每次在文本域中输入的时候都要获取其光标位置,以便于其他操作
cursorIndex = getFocus(obj);

//由于我们是禁止输入中文中括号的,而中文中括号输入左右情况不同,需要分别处理
if (e.keyCode == 219) {
    e.preventDefault();
    //这里获取到光标左侧的内容
    var leftChar = obj.value.slice(cursorIndex - 1, cursorIndex);

    //只有输入结束的是右中括号,而且它的前一个字符是左中括号才把它删除,防止把关键字删除掉
    if (/\】/g.test(leftChar) && obj.value.charAt(cursorIndex - 2) === '【') {
        obj.value = obj.value.slice(0, cursorIndex - 2) + obj.value.slice(cursorIndex, obj.value.length);
    }

} else if (e.keyCode == 221) {
    e.preventDefault();
    //右中括号就好办多了,因为它不会自动带出左中括号
    var leftChar = obj.value.slice(cursorIndex - 1, cursorIndex);
    if (/\】/g.test(leftChar)) {
        obj.value = obj.value.slice(0, cursorIndex - 1) + obj.value.slice(cursorIndex, obj.value.length);
    }
}
//防止上下左右键移动光标进入关键字中
if ((e.keyCode == 37 || e.keyCode == 39 || e.keyCode == 38 || e.keyCode == 40) && lastKeyCode !== 219) {
    dealFocusMove(obj, cursorIndex);
} else if (e.keyCode == 8) {
    //backspace删除的时候删除整个关键字
    dealFocusL(obj, cursorIndex, allKeyWords);
} else if (e.keyCode == 46) {
    //delete删除的时候也是删除整个关键字
    dealFocusR(obj, cursorIndex, allKeyWords)
}
if (e.keyCode !== 37 && e.keyCode !== 39) {
    //这里防止手动按得左右键影响左中括号判断
    lastKeyCode = e.keyCode;
}
}, false);

那这咋搞,还要分别删除么?不用的,我们只要不让他跑到中间就可以了,对就是preventDefault()。有疑问了吧?没错,这个无法阻止中文按键。
关键字不可编辑,但是文本怎么能不编辑啊?编辑的关键是什么,就是有光标啊,那我们不让光标进入关键字不就行了,这里还顺带解决了的防止鼠标点击关键字中间。我想的思路是,关键字的中括号是成对出现的,那么光标进入了,光标前面的内容中中括号自然不是成对的,这就是判断条件,把它挪出来就可以了。当然从按左右键要分别处理,因为是向不同方向越过整个关键字,上下键就简单了,都放把光标设置在关键字左边就可以了。

if ((e.keyCode == 37 || e.keyCode == 39) && lastKeyCode === 219) {
    //这里是防止按下中文中括号左键的时候带动左右键的按下,这样保证光标一直在最后
    e.preventDefault();
}
b.jpg

3.怎么处理点击文本域,立即点击关键字是插入,点击其他地方之后再点击关键字不可插入?这里我定义了一个参数存储光标位置,当点击其他位置的时候就让光标置空,而点击关键字的时候判断一下光标位置是否存在就可以了

if (cursorIndex !== null) {
    //这里判断是否是我们要点击的是不是关键字
    if (e.target.tagName !== "TEXTAREA" && e.target.getAttribute('isFocus')) {
        //插入关键字

    } else if (e.target.tagName == "TEXTAREA" && e.target.getAttribute('isFocus')) {
        //点击文本区域操作
    } else {
        //点击其他地方要将光标位置置空,防止点击关键字添加
        cursorIndex = null;
    }
}

4.删除整个关键字,这里还是用关于如何防止光标进入关键字的方式。只要发现不成对,就把最近的另一半到光标之间的删除

【关键字| 或者 |关键字】

就是backspace和delete两种,当然在处理的时候用了一些小技巧,就是正则表达式的RegExp.lastIndex,最后一次匹配到的位置,还有其他,看代码吧。

代码地址地址https://github.com/Stevenzwzhai/plugs/tree/master/%E8%87%AA%E5%AE%9A%E4%B9%89%E6%A8%A1%E6%9D%BF-template

上一篇下一篇

猜你喜欢

热点阅读