我要删除的单词在carret之前用另一个单词替换。只有在我使用css进行选择时,我才设法实现我的目标
*{
-moz-user- select:-moz-none;
-khtml-user- select:none;
-webkit-user- select:none;
-ms-user- select:none;
user- select:none;
}
选择的变化后来给我带来麻烦,因为在某种程度上,我希望用户突出显示文档中的某些文本。在Firefox中,关闭选择后,插入符号将不会在contenteditable div中的跨度之类的元素内移动。 仅当您关闭选择后,下面的代码片段才能按预期工作。 有人可以在不关闭选择的情况下解决问题吗?
//this function gets the word before carret position
function getWordPrecedingCaret (containerEl) {
var preceding = "",
sel,
range,
precedingRange;
if (window.getSelection) {
sel = window.getSelection();
if (sel.rangeCount > 0) {
range = sel.getRangeAt(0).cloneRange();
range.collapse(true);
range.setStart(containerEl, 0);
preceding = range.toString();
}
} else if ((sel = document.selection) && sel.type != "Control") {
range = sel.createRange();
precedingRange = range.duplicate();
precedingRange.moveToElementText(containerEl);
precedingRange.setEndPoint("EndToStart", range);
preceding = precedingRange.text;
}
var lastWord = preceding.match(/(?:\s|^)([\S]+)$/i);
if (lastWord) {
return lastWord;
} else {
return false;
}
}
//this code only shows and hides auto suggest div on keyup, keydown and click events
$(document).on('keydown keyup click','#editable_div',function(e){
var el=document.getElementById('editable_div');
var lastWord = getWordPrecedingCaret(el);
if (lastWord){
var last_word_string=lastWord[1];
var atSignFound=last_word_string.search(/@/);
var last_word_string_length=last_word_string.length;
if(((atSignFound !== -1) && (last_word_string_length > 2) && ((e.type=='keydown')) || (atSignFound !== -1) && (last_word_string_length > 1) && (e.type=='keyup'))){
$('.auto_suggest_div').fadeIn(1);
}
}
else{
$('.auto_suggest_div').fadeOut(1);
}
});
//this is where i actually need some help
function replace_word_before_or_around_caret(){
var sel;
if(window.getSelection && (sel=window.getSelection()).modify){
sel.collapseToStart();
sel.modify("move","backward","word");
sel.modify("extend","forward","word");
sel.deleteFromDocument();
var new_el=document.createElement('span');
new_el.innerHTML='School';
var range=sel.getRangeAt( 0);
range.insertNode(new_el);
sel.removeAllRanges();
}
}
//if we click the yellow apple button...replace club with school in contenteditable div
$(document).on('click','.auto_suggest_div',function(){
replace_word_before_or_around_caret();
});
.parent_div{
position:relative;
}
.editable_div{
width:300px;
height:100px;
border:1px #DCDCDC solid;
padding:5px 10px;
}
.auto_suggest_div{
width:100px;
padding:5px 10px;
background:#ffff00;
text-align:center;
cursor:pointer;
border:1px #DCDCDC solid;
position:absolute;
left:100px;
bottom:-30px;
display:none;
}
.explanation{
margin-top:50px;
}
/*
if you remove comments here, the result will be okay but i dont want to disable selection
*{
-webkit-user-select: none;
-moz-user-select: -moz-none;
-ms-user-select: none;
user-select: none;
}
*/
<script src="https://code.jquery.com/jquery-1.9.1.min.js"></script>
<div class="parent_div">
<div class="editable_div"id="editable_div"contenteditable="true"></div>
<div class="auto_suggest_div">Apple</div>
</div>
<div class="explanation">
If you type am @club, a yellow button named apple will appear. If you click on apple button, the word club should be replaced by the word school.
<p>Unfortunately, the word school replaces apple instead of club</p>
<p>Note if you disable document selection using css, this will work</p>
<p>I have a hint that clicking an element might change previous selection but am not good at selection stuffs.</p>
</div>