可編輯的DIV(相容IE8)以及插入內容到游標位置
阿新 • • 發佈:2019-01-10
在做web版聊天程式時,往往需要將一個DIV設定為可編輯狀態,並且可以插入表情。
插入表情時,不僅僅是在輸入的文字最後追加表情,還可能在輸入文字的中間,即游標位置插入表情(游標後還有文字)。
另外,還需要保證貼上進來的文字必須是純文字,不然百度搜索一篇文章貼上進來,就太亂了。我們希望輸入的文字都是純文字,只有最基本的p標籤或div標籤。
通過各種百度搜索,我在專案中成功實施。
現將專案中的技術提取出來,形成一個小樣例,大家可以參照使用。算是對網上提供這些素材的開發人員的回饋了。
html程式碼:
<!DOCTYPE html>
<html lang="en" >
<head>
<meta charset="UTF-8">
<title>可編輯的DIV(相容IE8)</title>
<style type="text/css">
#content {
width: 500px;
height: 200px;
border: 1px solid #CCC;
}
</style>
<script src="../jquery.js"></script>
<script src="./contenteditable.js"></script>
</head>
<body>
<button id="insert" unselectable="on" onmousedown="return false">笑臉</button>
<div id="content" contenteditable="true"></div>
<script type="text/javascript">
// 在游標位置插入html程式碼,如果dom沒有獲取到焦點則追加到最後
function insertAtCursor(jsDom, html) {
if (jsDom != document.activeElement) { // 如果dom沒有獲取到焦點,追加
jsDom.innerHTML = jsDom.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);
}
}
$('#insert').click(function() {
var html = ':)';
insertAtCursor(document.getElementById('content'), html);
});
</script>
</body>
</html>
contenteditable.js程式碼:
/**
* contenteditable="plaintext-only"在Firefox,ie瀏覽器中無效,這會導致DIV不可編輯。
* 通過監聽貼上動作,過濾純文字放入可編輯DIV的游標位置
*/
$(function() {
$('[contenteditable]').each(function() {
// 幹掉IE http之類地址自動加連結
try {
document.execCommand("AutoUrlDetect", false, false);
} catch (e) {}
$(this).on('paste', function(e) {
e.preventDefault();
var text = null;
if (window.clipboardData && clipboardData.setData) {
// IE
text = window.clipboardData.getData('text');
} else {
text = (e.originalEvent || e).clipboardData.getData('text/plain');
}
if (!text) {
return false; // 貼上圖片時
}
if (document.body.createTextRange) {
console.log('insert Text');
if (document.selection) {
textRange = document.selection.createRange();
} else if (window.getSelection) {
sel = window.getSelection();
var range = sel.getRangeAt(0);
// 建立臨時元素,使得TextRange可以移動到正確的位置
var tempEl = document.createElement("span");
tempEl.innerHTML = "&#FEFF;";
range.deleteContents();
range.insertNode(tempEl);
textRange = document.body.createTextRange();
textRange.moveToElementText(tempEl);
tempEl.parentNode.removeChild(tempEl);
}
textRange.text = text;
textRange.collapse(false);
textRange.select();
} else {
// Chrome之類瀏覽器
document.execCommand("insertText", false, text);
}
});
// 去除Crtl+b/Ctrl+i/Ctrl+u等快捷鍵
$(this).on('keydown', function(e) {
// e.metaKey for mac
if (e.ctrlKey || e.metaKey) {
switch (e.keyCode) {
case 66: //ctrl+B or ctrl+b
case 98:
case 73: //ctrl+I or ctrl+i
case 105:
case 85: //ctrl+U or ctrl+u
case 117:
e.preventDefault();
break;
}
}
});
});
});