Cette solution fonctionne dans tous les principaux navigateurs:
saveSelection()
est attaché aux événements onmouseup
et onkeyup
du div et enregistre la sélection dans la variable savedRange
.
restoreSelection()
est attaché à l' onfocus
événement du div et resélectionne la sélection enregistrée dans savedRange
.
Cela fonctionne parfaitement à moins que vous ne souhaitiez que la sélection soit restaurée lorsque l'utilisateur clique sur le div également (ce qui est un peu peu intuitif car normalement vous vous attendez à ce que le curseur aille là où vous cliquez mais le code inclus pour l'exhaustivité)
Pour ce faire, les événements onclick
et onmousedown
sont annulés par la fonction cancelEvent()
qui est une fonction de navigateur croisé pour annuler l'événement. La cancelEvent()
fonction exécute également la restoreSelection()
fonction car lorsque l'événement de clic est annulé, le div ne reçoit pas le focus et par conséquent rien n'est sélectionné du tout à moins que cette fonction ne soit exécutée.
La variable isInFocus
stocke si elle est dans le focus et est remplacée par "false" onblur
et "true" onfocus
. Cela permet d'annuler les événements de clic uniquement si le div n'est pas sélectionné (sinon vous ne pourrez pas du tout modifier la sélection).
Si vous souhaitez que la sélection soit modifiée lorsque le div est focalisé par un clic, et ne pas restaurer la sélection onclick
(et uniquement lorsque le focus est donné à l'élément par programme en utilisant document.getElementById("area").focus();
ou similaire, supprimez simplement les événements onclick
et onmousedown
. L' onblur
événement et les fonctions onDivBlur()
et cancelEvent()
peut également être retiré en toute sécurité dans ces circonstances.
Ce code devrait fonctionner s'il est déposé directement dans le corps d'une page html si vous souhaitez le tester rapidement:
<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
travaillais dans des navigateurs non IE o_o