Div+contenteditable 模拟 textarea 及存在的问题

2016-10-13 07:45:15

在网页端实现聊天功能时,大多会采用textarea来实现,但是当需要在textarea中显示表情/图片时,就不好实现了。这时候普遍的方法是给div添加contenteditable属性,来模拟textarea,而在div中显示图片及表情就可以轻松实现了。

The contenteditable global attribute is an enumerated attribute indicating if the element should be editable by the user. If so, the browser modifies its widget to allow editing. The attribute must take one of the following values:

  • true or the empty string, which indicates that the element must be editable;
  • false, which indicates that the element must not be editable. If this attribute is not set, its default value is inherited from its parent element.

focus定位问题

使用div模拟textarea后会发现一个问题,就是每次点击输入框或者使用$('#tag').focus()让输入框聚焦时,光标都会定位在最开始的位置。 解决办法:

function placeCaretAtEnd(el) {  
    el.focus();
    if (typeof window.getSelection != "undefined"
            && typeof document.createRange != "undefined") {
        var range = document.createRange();
        range.selectNodeContents(el);
        range.collapse(false);
        var sel = window.getSelection();
        sel.removeAllRanges();
        sel.addRange(range);
    } else if (typeof document.body.createTextRange != "undefined") {
        var textRange = document.body.createTextRange();
        textRange.moveToElementText(el);
        textRange.collapse(false);
        textRange.select();
    }
}

placeCaretAtEnd( document.getElementById("content") );  

粘贴复制问题

当使用div作为输入框时,你会发现,粘贴复制到的全是HTML结构,而我们想要的是粘贴复制纯文本,就像textarea那样。解决方法就是监听div的粘贴事件,然后在粘贴事件中匹配替换HTML元素,返回纯文本:

var $plainText = $("#plainText");

$plainText.on('paste', function (e) {
    window.setTimeout(function () {
        $plainText.html(removeAllTags(replaceStyleAttr($plainText.html())));
    }, 0);
});

function replaceStyleAttr (str) {  
    return str.replace(/(<[\w\W]*?)(style)([\w\W]*?>)/g, function (a, b, c, d) {
        return b + 'style_replace' + d;
    });
}

function removeTagsExcludeA (str) {  
    return str.replace(/<\/?((?!a)(\w+))\s*[\w\W]*?>/g, '');
}

function removeAllTags (str) {  
    return str.replace(/<\/?(\w+)\s*[\w\W]*?>/g, '');
}
jQuery 监听隐藏表单

设置了一个隐藏表单,其值由Ajax异步修改。前端需要实时监听该值,并由此进行相关操作。 <input type="hidden" value="" id="datas" name="datas"> 正常的表单可以使用 .change() 事件监听其 value 的改变,而隐藏表单其 value 改变时不会触发 change() 事件! 解决方法: 当为隐藏表单赋值后,使用 trigger() 手动触发 change() 事件: function setValue(ajaxData){ $('#datas').val(ajaxData).trigger('change'); } $('#datas').change(){ console.log('changed'); }

background滤镜效果及高斯模糊

background滤镜效果 场景及实现:父级div嵌套子div,父div有背景图片,子div中有文字,需要实现背景图加黑色半透明遮罩,不影响子div中文字的显示效果。 CSS的filter滤镜效果的Brightness属性可以实现遮罩效果,但是类似于opacity属性,这种效果会影响子div的显示效果: 解决方法: <div id="section1"> <div id="content"> </div> </div> #section1 { background: url('../images/bg-img.jpg') center center no-repeat; background-size: cover; position: relative; } #content { position: absolute; } #section1::before { content: ''; display: block;