Установить фокус на элемент div contenteditable

У меня есть <div contenteditable=true>, где я определяю WYSIWYG некоторые элементы. Например, <p>,<h1> и т. д. Я хотел бы сосредоточить внимание непосредственно на одном из этих элементов.

Например на <p id="p_test">. Но кажется, что функция focus() не работает с элементами <div>, элементами <p>...

Есть ли другой способ определить фокус в моем случае?


person sanceray3    schedule 05.03.2010    source источник
comment
Вы не можете сфокусировать div или p, так как для него нет действий, на что вы пытаетесь сфокусироваться?   -  person Nick Craver    schedule 05.03.2010
comment
@NickCraver в вопросе упоминается, что его содержимое можно редактировать, что означает, что вы можете печатать и редактировать его и т. Д. Совершенно правильный вопрос, имхо.   -  person Blowsie    schedule 10.12.2012
comment
@Blowsie Я полагаю, что в исходном вопросе не упоминалась функция редактирования контента. Ник Крейвер отредактировал его и придал ему смысл. фокус.   -  person Matej Svajger    schedule 20.01.2015


Ответы (9)


Старый пост, но ни одно из решений не сработало для меня. Я понял это в конце концов, хотя:

var div = document.getElementById('contenteditablediv');
setTimeout(function() {
    div.focus();
}, 0);
person chris97ong    schedule 11.05.2016
comment
не уверен, почему, это полностью работает!!! обертывание логики .focus() в setTimeout помогло!! Спасибо! - person sga4; 07.11.2016
comment
Хороший! Некоторые вещи должны вернуться к планировщику, прежде чем ими можно будет правильно управлять. Браузеры странные. Спасибо! - person B T; 12.12.2016
comment
Я столкнулся с этим только при размещении кода в обработчике onClick другого элемента. Я предполагаю, что есть состояние гонки: кнопка нажата -> обработчик onClick фокусирует какой-то элемент -> кнопка получает фокус. Размещение setTimeout отложит код, который заставит его сохранять фокус. - person Vilius Paulauskas; 02.01.2018
comment
Я из будущего, и это тоже работа над будущим - person Bariq Dharmawan; 07.11.2020

В современных браузерах вы можете использовать:

var p = document.getElementById('contentEditableElementId'),
    s = window.getSelection(),
    r = document.createRange();
r.setStart(p, 0);
r.setEnd(p, 0);
s.removeAllRanges();
s.addRange(r);

Но если ваш элемент пуст, у меня возникли некоторые странные проблемы, поэтому для пустых элементов вы можете сделать это:

var p = document.getElementById('contentEditableElementId'),
    s = window.getSelection(),
    r = document.createRange();
p.innerHTML = '\u00a0';
r.selectNodeContents(p);
s.removeAllRanges();
s.addRange(r);
document.execCommand('delete', false, null);

После удаления nbsp курсор остается внутри элемента p

P.S. просто обычное пространство мне не подходит

person Dima Vidmich    schedule 31.05.2013
comment
что такое переменная p в ваших примерах? - person B T; 17.06.2014
comment
@BT Я предполагаю, что это корневой элемент P, хотя он должен был уточнить это, не оставляя места для сомнений. - person Savas Vedova; 22.06.2015
comment
Из множества предложенных решений это единственное, которое сработало для меня, позволяя мне сосредоточиться на редактируемом контенте div в диалоговом окне jquery. - person Steve Roberts; 18.07.2016
comment
Отличное решение .. Спасибо :) - person Sunil Kumar; 27.06.2017
comment
Я заменил нули на единицы в r.setStart(p, 1) и r.setEnd(p, 1), чтобы поместить курсор в конец contenteditable div. Не знаю, почему это сработало, но сработало. Спасибо! - person Dave Land; 30.08.2018

Я заметил, что jQuery focus() не работает для моего contenteditable DIV с шириной и высотой 0. Я заменил его на .get(0).focus() - собственный метод фокуса javascript - и он работает.

person Vlad    schedule 05.02.2013
comment
Какой браузер? Кажется, это не работает в Safari, но Firefox и Chrome справляются с этим нормально. - person Brian McCutchon; 18.07.2013
comment
Какая часть? Выберите элемент и focus(), например, document.getElementById(#mydiv).focus() - person Vlad; 13.10.2015

В большинстве случаев, если вы не можете вызвать .focus() для элемента, это происходит потому, что tabIndex равен -1, что означает, что клавиша табуляции не может сфокусироваться на нем, когда вы нажимаете табуляцию для навигации.

Изменение tabIndex на >= 0 позволит вам сосредоточиться на элементах. Если вам нужно сделать это динамически, вы можете просто добавить tabindex >= 0 к вашему элементу в прослушивателе событий.

person wafs    schedule 02.07.2018
comment
это должен быть одобренный ответ. вы не можете вызвать метод .focus() для элемента, если он не имеет атрибута tabindex - person Ivan Hanák; 05.07.2020

Вы можете попробовать этот код, он может автоматически фокусироваться на последнем месте вставки.

let p = document.getElementById('contenteditablediv')
let s = window.getSelection()
let r = document.createRange()
r.setStart(p, p.childElementCount)
r.setEnd(p, p.childElementCount)
s.removeAllRanges()
s.addRange(r)
person Surmon    schedule 04.03.2017
comment
Спасибо, частично такой же ответ выше у меня не сработал, мне нужно было добавить p.childElementCount вместо 1, как вы написали. - person NoxFly; 20.12.2020

Чтобы продолжить ответ @Surmon. Если вы хотите автоматически сфокусироваться сразу после последней буквы/цифры в тексте вместо последнего места вставки (последнее место вставки переместит курсор на новую строку, если дочерние узлы заключены в теги типа блока, а не в обычный текст) затем примените эту небольшую модификацию:

r.setStart(p.lastChild, 1);
r.setEnd(p.lastChild, 1);

Это расширенная функция, которая проверяет, есть ли у редактора/элемента какие-либо дочерние узлы, и в зависимости от ситуации соответствующим образом устанавливает курсор в конце:

let p = document.getElementById('contenteditablediv');
p.focus();  // alternatively use setTimeout(() => { p.focus(); }, 0);
// this is enough to focus an empty element (at least in Chrome)

if (p.hasChildNodes()) {  // if the element is not empty
  let s = window.getSelection();
  let r = document.createRange();
  let e = p.childElementCount > 0 ? p.lastChild : p;  
  r.setStart(e, 1); 
  r.setEnd(e, 1);    
  s.removeAllRanges();
  s.addRange(r);
} 
person M.Calugaru    schedule 21.12.2019

Если кто-то, кто использует MediumEditor, который управляет элементом contenteditable, наткнется на эту проблему, следующее сработало для меня:

editor.selectElement(editorDOMNode);
  1. editor является экземпляром MediumEditor.
  2. editorDOMNode — это ссылка на фактический узел contenteditable DOM.
  3. Также можно сфокусироваться на конкретном дочернем узле в редакторе следующим образом:

    editor.selectElement(editorDOMNode.childNodes[0]);
    
person Eye    schedule 02.03.2016

Еще одна вещь, которую нужно проверить: если у вас открыто окно консоли браузера, убедитесь, что консоль не имеет фокуса при загрузке страницы, иначе элемент на странице не получит фокус, как ожидалось.

Это также означает, что вы не можете запустить document.querySelector('#your-elem').focus() в консоли (пробовали с Chrome, Safari и Firefox на Mac, август 2020 г.).

person Jouni Kananen    schedule 08.08.2020
comment
Спасатель жизни! В консоли ничего не делал, но при попытке сделать это в реальном коде: document.querySelector('.pell-content').focus(); работало отлично, для Pell RTE. Сумасшедший, спасибо! - person Vael Victus; 22.01.2021

Привяжите обработчик события "щелчок" ко всем элементам внутри div, доступного для редактирования, и измените класс/стиль при щелчке (т.е. добавьте класс "сфокусированный" к элементу);

Вы можете определить для пользователя, какой элемент находится в фокусе, добавив стиль, такой как цветная рамка или внутренняя тень блока. Затем, когда вы хотите получить доступ к сфокусированному элементу в вашем скрипте jQuery, просто сделайте что-то вроде этого:

var focused = $('.focused');

person Brian P Johnson    schedule 20.04.2012
comment
Он спрашивает о фактическом перемещении курсора пользователя на элемент, а не только о стиле выбранных элементов. - person Brian McCutchon; 18.07.2013
comment
Это не поможет. - person ; 07.11.2014