Отключение выбора доставило мне неприятности - PullRequest
0 голосов
/ 08 ноября 2018

Я хочу удалить слово перед символом carret и заменить его другим словом. Мне удалось достичь своей цели, только если я повернул выбор с помощью css, используя

*{
-moz-user- select:-moz-none;
-khtml-user- select:none;
-webkit-user- select:none;
-ms-user- select:none;
user- select:none;
}

Отмена выбора позже доставила мне неприятности, потому что в какой-то момент я хотел бы, чтобы пользователь выделил некоторый текст в документе. В Firefox, после отключения выделения, каретка не будет перемещаться внутри элемента, такого как span внутри 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>
...