Есть ли CSS-селектор, когда каретка находится в элементе?
У меня есть contenteditable
Элемент, я хочу, чтобы элементы внутри применяли стиль, когда каретка находится внутри них.
В этом примере стиль меняется на :hover
:
div{
caret-color: red;
}
span:hover {
font-weight:bold;
}
<div contenteditable="true">
<span>Sub element one</span>
text node
<span>sub element two</span>
</div>
Здесь вы можете увидеть каретку, так как я нарисовал ее красным, но над другой span
:
Есть ли способ применить такой стиль, но когда каретка находится внутри элемента? Так что текст в span
вокруг красная линия жирная?
Решение будет выглядеть так:
Решение CSS было бы идеальным, но я бы рассмотрел решения JS, если это невозможно.
3 ответа
С CSS?
Нет, нет css
селектор для этого.
С JavaScript?
Да, вы можете сделать это с JavaScript
с использованием .getSelection()
функция.
С .getSelection()
Вы можете получить текущую позицию каретки и element
каретка включена.
window.getSelection().focusNode.parentElement // Returns DOM node
window.getSelection ()
Возвращает объект Selection, представляющий диапазон текста, выбранного пользователем, или текущую позицию каретки.
https://developer.mozilla.org/en-US/docs/Web/API/Window/getSelection
Таким образом, используя эту информацию, вы можете создать функцию, которая стилизует элемент, на котором находится каретка
var ctl = document.getElementById('contenteditable');
var selection;
function styleNode() {
// Get selection / caret position
selection = window.getSelection();
// Check if type is Caret and not Range (selection)
if(selection.type === 'Caret')
{
// Remove styles
Array.prototype.forEach.call(selection.focusNode.parentElement.parentElement.getElementsByTagName( "span" ), child => {
child.style.fontWeight = "normal";
});
// Only style <span> elements
if(selection.focusNode.parentElement.tagName === 'SPAN')
{
// Set style on element where caret is
selection.focusNode.parentElement.style.fontWeight = "bold";
}
}
}
// Removes styles on focusout
function reset() {
Array.prototype.forEach.call(ctl.getElementsByTagName( "span" ), child => {
child.style.fontWeight = "normal";
});
}
ctl.addEventListener("keyup", styleNode);
ctl.addEventListener("click", styleNode);
ctl.addEventListener("focusout", reset);
<div contenteditable id="contenteditable">
<span>This is</span> some editable <span>content</span>
</div>
Я думаю, что нужен другой подход. Поскольку редактирование требует нажатия на элемент, я бы просто настроить click
обработчик событий на подэлементах для их стилизации.
// Get reference to the contenteditable element
var container = document.querySelector("[contenteditable='true']");
// Set up a click event handler for the container
container.addEventListener("click", function(evt){
// Loop over child elements and remove the active class
Array.prototype.slice.call(container.querySelectorAll("*")).forEach(function(el){
el.classList.remove("active");
});
// Apply the active class to the clicked element
evt.target.classList.add("active");
});
.active {
font-weight:bold;
}
<div contenteditable="true">
<span>Sub element one</span>
text node
<span>sub element two</span>
</div>
Слушатель событийselectionchange
весьма полезно для обнаружения изменения положения каретки (из-за мыши или клавиатуры). Он обнаруживает, что он также должен работать на мобильных устройствах при пролистывании пробела для перемещения каретки.