DIV可编辑模式在光标位置插入内容

当我们做一个聊天对话框时,可能想要支持图片发送或表情,而且我们希望表情和图片都以图片方式呈现在输入框内,这时,textarea就不管用了,因为它只支持纯文本。

我们可以利用div的contentEditable="true"属性设置,使DIV可编辑,这样,div中就可以追加图片。

我们插入表情时,需要先点击输入框上方或下方给的一个表情按钮,从而弹出一个浮动层,里面是各种表情,点击表情,即可将表情放到DIV中光标所在位置。

但有一个问题是:如果发送表情,是可能需要将表情插入到文本中间,而非文本末尾。而当我们点击表情按钮时,会导致DIV失去焦点,从而导致表情只能追加到文本末尾。

别担心,这个问题也可以解决,我们给表情按钮以及弹出的表情列表层最外层元素都增加两个HTML属性即可。

属性是:unselectable="on" onmousedown="return false;"

 然后再来的问题就是,如何能将选择到的元素插入到可编辑div中的光标位置呢?我在百度上搜索,找到了解决办法:

function insertAtCursor(dom, html) {
	if (dom != document.activeElement) { // 如果dom没有获取到焦点,追加
		dom.innerHTML = dom.innerHTML + html;
		return;
	}
	var sel, range;
	if (window.getSelection) {
		// IE9 或 非IE浏览器
		sel = window.getSelection();
		if (sel.getRangeAt && sel.rangeCount) {
			range = sel.getRangeAt(0);
			range.deleteContents();
			// Range.createContextualFragment() would be useful here but is
			// non-standard and not supported in all browsers (IE9, for one)
			var el = document.createElement("div");
			el.innerHTML = html;
			var frag = document.createDocumentFragment(),
				node, lastNode;
			while ((node = el.firstChild)) {
				lastNode = frag.appendChild(node);
			}
			range.insertNode(frag);
			// Preserve the selection
			if (lastNode) {
				range = range.cloneRange();
				range.setStartAfter(lastNode);
				range.collapse(true);
				sel.removeAllRanges();
				sel.addRange(range);
			}
		}
	} else if (document.selection && document.selection.type != "Control") {
		// IE < 9
		document.selection.createRange().pasteHTML(html);
	}
}

另外再给一份针对texterea中在光标位置插入Text内容的代码:

function insertValueAtCursor(myField, insertContent) 
{
    if (myField != document.activeElement) {
        myField.value = myField.value + insertContent;
        return;
    }
    //IE support
    if (document.selection) 
    {
        myField.focus();
        var sel     = document.selection.createRange();
        sel.text    = insertContent;
        sel.select();
    }
    //MOZILLA/NETSCAPE support
    else if (typeof myField.selectionStart === 'number' || typeof myField.selectionEnd == 'number') 
    {
        var startPos    = myField.selectionStart;
        var endPos      = myField.selectionEnd;
        console.log("startPos:" + startPos)
        // save scrollTop before insert
        var restoreTop    = myField.scrollTop;
        myField.value    = myField.value.substring(0, startPos) + insertContent + myField.value.substring(endPos, myField.value.length);
        if (restoreTop > 0)
        {
            // restore previous scrollTop
            myField.scrollTop = restoreTop;
        }
        myField.focus();
        myField.selectionStart  = startPos + insertContent.length;
        myField.selectionEnd    = startPos + insertContent.length;
    } else {
    	console.log('OK')
        myField.value += insertContent;
        myField.focus();
    }
}

最后我有一个例子,在附件中,下载下来,打开index.html或editor.html都能看到效果。

值得注意的是,上述代码只针对IE9以上版本以及chrome,firefox等支持HTML5的浏览器有效,IE8中做不到在光标位置插入图片。

如果要兼容IE8.0我找到了解决办法,就是不止是在父元素有这个属性就行,还需要在鼠标点击的那个元素加上这两个属性就OK。我把附件替换了,大家可以参考。

猜你喜欢

转载自canlynet.iteye.com/blog/2340751