当我们做一个聊天对话框时,可能想要支持图片发送或表情,而且我们希望表情和图片都以图片方式呈现在输入框内,这时,textarea就不管用了,因为它只支持纯文本。
我们可以利用div的contentEditable="true"属性设置,使DIV可编辑,这样,div中就可以追加图片。
我们插入表情时,需要先点击输入框上方或下方给的一个表情按钮,从而弹出一个浮动层,里面是各种表情,点击表情,即可将表情放到DIV中光标所在位置。
但有一个问题是:如果发送表情,是可能需要将表情插入到文本中间,而非文本末尾。而当我们点击表情按钮时,会导致DIV失去焦点,从而导致表情只能追加到文本末尾。
别担心,这个问题也可以解决,我们给表情按钮以及弹出的表情列表层最外层元素都增加两个HTML属性即可。
属性是:unselectable="on" οnmοusedοwn="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。我把附件替换了,大家可以参考。