To rozwiązanie działa we wszystkich głównych przeglądarkach:
saveSelection()
jest dołączony do zdarzeń onmouseup
i onkeyup
elementu div i zapisuje wybór w zmiennej savedRange
.
restoreSelection()
jest dołączony do onfocus
zdarzenia div i ponownie wybiera zaznaczenie zapisane w savedRange
.
Działa to doskonale, chyba że chcesz, aby zaznaczenie zostało przywrócone, gdy użytkownik kliknie również element div (co jest trochę nieintuicyjne, ponieważ zwykle oczekujesz, że kursor znajdzie się w miejscu kliknięcia, ale kod zawiera kompletność)
Aby to osiągnąć, zdarzenia onclick
i onmousedown
są anulowane przez funkcję, cancelEvent()
która jest funkcją cross browser do anulowania zdarzenia. cancelEvent()
Funkcja działa również restoreSelection()
funkcję ponieważ jako zdarzenie click jest anulowane div nie odbiera ostrość i dlatego nic nie jest zaznaczone w ogóle, chyba że jest to uruchomić funkcje.
Zmienna isInFocus
przechowuje, czy jest fokus, i jest zmieniana na „false” onblur
i „true”onfocus
. Dzięki temu zdarzenia kliknięcia mogą być anulowane tylko wtedy, gdy element div nie jest aktywny (w przeciwnym razie nie można by w ogóle zmienić zaznaczenia).
Jeśli chcesz, aby zaznaczenie onclick
uległo zmianie, gdy element div jest skupiony przez kliknięcie, i nie chcesz go przywracać (i tylko wtedy, gdy fokus zostanie nadany elementowi programowo za pomocą document.getElementById("area").focus();
lub podobnie, po prostu usuń zdarzenia onclick
i onmousedown
. onblur
Zdarzenie onDivBlur()
i cancelEvent()
funkcje i w takich okolicznościach można również bezpiecznie usunąć.
Ten kod powinien działać, jeśli zostanie umieszczony bezpośrednio w treści strony html, jeśli chcesz go szybko przetestować:
<div id="area" style="width:300px;height:300px;" onblur="onDivBlur();" onmousedown="return cancelEvent(event);" onclick="return cancelEvent(event);" contentEditable="true" onmouseup="saveSelection();" onkeyup="saveSelection();" onfocus="restoreSelection();"></div>
<script type="text/javascript">
var savedRange,isInFocus;
function saveSelection()
{
if(window.getSelection)//non IE Browsers
{
savedRange = window.getSelection().getRangeAt(0);
}
else if(document.selection)//IE
{
savedRange = document.selection.createRange();
}
}
function restoreSelection()
{
isInFocus = true;
document.getElementById("area").focus();
if (savedRange != null) {
if (window.getSelection)//non IE and there is already a selection
{
var s = window.getSelection();
if (s.rangeCount > 0)
s.removeAllRanges();
s.addRange(savedRange);
}
else if (document.createRange)//non IE and no selection
{
window.getSelection().addRange(savedRange);
}
else if (document.selection)//IE
{
savedRange.select();
}
}
}
//this part onwards is only needed if you want to restore selection onclick
var isInFocus = false;
function onDivBlur()
{
isInFocus = false;
}
function cancelEvent(e)
{
if (isInFocus == false && savedRange != null) {
if (e && e.preventDefault) {
//alert("FF");
e.stopPropagation(); // DOM style (return false doesn't always work in FF)
e.preventDefault();
}
else {
window.event.cancelBubble = true;//IE stopPropagation
}
restoreSelection();
return false; // false = IE style
}
}
</script>
contentEditable
pracował w przeglądarkach innych niż IE-O_o