禁用选择使我陷入困境

时间:2018-11-07 23:10:29

标签: javascript css selection contenteditable

我要删除的单词在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>

0 个答案:

没有答案