Я не совсем уверен, в чем причина проблемы, поскольку в некоторых случаях Chrome будет правильно фокусировать элемент, хотя в большинстве случаев это не так. Вам вообще не нужно запрашивать фокусировку, так как при нажатии клавиши фокус не теряется. Если вы пропустите вызов setEditFocus()
, вы должны заметить, что он по-прежнему работает правильно во всем, кроме Chrome, который, очевидно, обижается, что вы удалили весь контент в теле.
Когда вы устанавливаете contenteditable
, каждый браузер устанавливает innerHTML
элемента body
документа iframe на что-то другое:
Browser | innerHTML
-----------------------------
Internet Explorer | ''
Opera | '<br>\n'
Firefox | '<br>'
Chrome/Safari | '\n'
Если вы не ожидаете увидеть этот дополнительный материал при последующем анализе содержимого, вы можете удалить его заранее в addFrame()
.
Мне удалось «исправить» проблему, выполнив следующие действия:
Сначала обновите обработчик событий, чтобы мы могли вернуть в него false
и запретили Opera генерировать HTML для удовольствия, когда мы вызываем getSelection()
позже ...
function addFrame() {
...
window.iframeloaded = function() {
...
if (typeof iframeDoc.addEventListener != UNDEF) {
iframeDoc.addEventListener('keypress', keyHandler, false);
} else if (typeof iframeDoc.attachEvent != UNDEF) {
iframeDoc.attachEvent('onkeypress', keyHandler);
}
}
}
Редактировать: Удалена оригинальная функция в пользу новой, включенной ниже
Наконец, верните false
из обработчика нажатия клавиш, чтобы исправить проблему Opera, упомянутую выше.
function keyHandler (evt) {
var myKey=(evt.which || evt.charCode || evt.keyCode)
if (myKey==13) {
...
return false;
}
}
Изначально я делал то, что предлагал syockit , но обнаружил, что он делает странные вещи с размером каретки в Chrome, чего этот метод, похоже, избегает (хотя Firefox все еще немного отключен ...) , Если вам это безразлично, установка непустого значения innerHTML
, вероятно, является более простым решением.
Также обратите внимание, что вы должны использовать className
вместо class
в объекте, который вы передаете new Element()
, так как IE, кажется, считает его зарезервированным словом и говорит, что это синтаксическая ошибка.
Редактировать : Поэкспериментировав, кажется, следующая функция надежно работает в IE8 / Firefox / Chrome / Safari / Opera для более продвинутого теста. К сожалению, мне пришлось включить обнаружение браузера Prototype в учетную запись Opera, поскольку, хотя в отношении JavaScript все выглядит одинаково, для реального поведения требуется другой код, конфликтующий с другими браузерами, и я не смог найти лучший способ различать их.
Вот новая функция, которая фокусируется на редактируемом контенте iframe и гарантирует, что, если там уже есть контент, каретка перемещается в конец этого контента:
function focusEditableFrame(frame) {
if (!frame)
return;
if (frame.contentWindow)
frame = frame.contentWindow;
if (!Prototype.Browser.Opera) {
frame.focus();
if (frame.getSelection) {
if (frame.document.body.innerHTML == '')
frame.getSelection().extend(frame.document.body, 0);
else
frame.getSelection().collapseToEnd();
} else if (frame.document.body.createTextRange) {
var range = frame.document.body.createTextRange();
range.moveEnd('character', frame.document.body.innerHTML.length);
range.collapse(false);
range.select();
}
} else {
frame.document.body.blur();
frame.document.body.focus();
}
}
Обновлено setEditFocus()
(сейчас не обязательно, но так как оно у вас уже есть):
function setEditFocus()
{
focusEditableFrame($(editorFrame));
}