What is problem here?
if ( window.getSelection() )
EditField = window.getSelection().getRangeAt(0);
throws error:
<
The problem seems to be WebKit-specific; I could not reproduce it in IE or Firefox. As OP already mentioned, the error on Google Chrome is:
Uncaught IndexSizeError: Failed to execute 'getRangeAt' on 'Selection': 0 is not a valid index
Safari has the same issue, but the message is different:
INDEX_SIZE_ERR: DOM Exception 1: Index or size was negative, or greater than the allowed value.
Typically happens in simple WYSIWYG editors. Example:
Once the page has loaded, click the button; you will see the error message in the JavaScript console (Chrome) or error console (Safari). But if you click anywhere inside the editor section before clicking the button, the error will not occur.
This problem is easy to prevent; always check rangeCount before calling getRangeAt:
function doInsert(text) {
var sel = window.getSelection && window.getSelection();
if (sel && sel.rangeCount > 0) {
var range = sel.getRangeAt(0);
...
Of course, you can avoid the situation by giving the editor focus (with method focus) upon page load.
However, there are rare events that cause your editor to lose its selection range later on. So far, I have only been able to reproduce this with a multi-select list control:
Again, I can prevent the error by checking rangeCount. But the problem remains that my button does not insert the selected list item at the last known caret position, as it was supposed to do. Method focus does not help; it will reset the caret position to the top left position in the editor.
A solution is to continuously save the current selection range (for this purpose, trap event SelectionChange):
var savedRange = null;
document.addEventListener("selectionchange", HandleSelectionChange, false);
function HandleSelectionChange() {
var sel = window.getSelection && window.getSelection();
if (sel && sel.rangeCount > 0) {
savedRange = sel.getRangeAt(0);
}
}
And restore it when the button is clicked:
function doInsert(text) {
var sel = window.getSelection && window.getSelection();
if (sel && sel.rangeCount == 0 && savedRange != null) {
sel.addRange(savedRange);
}
if (sel && sel.rangeCount > 0) {
var range = sel.getRangeAt(0);
var node = document.createTextNode(text);
range.deleteContents();
range.insertNode(node);
}
}
Fiddle: http://jsfiddle.net/stXDu/