Я пытаюсь построить вокруг contenteditable, сначала отключив поведение стиля текста с помощью сочетаний клавиш, таких как ctrl+b
или ctrl+i
.
Я использую event.preventDefault()
, когда эти сочетания клавиш обнаруживаются в событиях keyup
и keydown
, однако иногда редко, я замечаю, что contenteditable по-прежнему игнорирует event.preventDefault()
, а сочетание клавиш соблюдается.
Есть ли способ полностью отключить эти сочетания клавиш, кроме отмены keyup
и keydown
?
Мой детектор ярлыков был неисправен, и в некоторых случаях он пропускал событие. Кажется, что отмена события на keydown
фактически отменяет и ярлык.
Я создал jsfiddle для всех, кто хочет попробовать: https://jsfiddle.net/mohj19bs/28/
Я закрою эту тему завтра, на случай, если кто-то еще может поделиться чем-то интересным, так как contenteditable
не перестает меня удивлять.
@code Я отменил мероприятие keyup
, потому что только отмена keydown
не всегда помогала, так что я подумал. Но вы правы, вы можете нажать Ctrl
+B
, и пока обе клавиши полностью нажаты, по умолчанию эффект сработает — это означает, что отмена keydown
должна помочь, но иногда Contenteditable стилизует текст редко! Позже я создам хороший jsfiddle.
Также следите за событием keypress
. Он по-прежнему выскакивает на определенные браузеры, и некоторый код все еще действует на него.
@terrymorse да, я тоже об этом думал, но особо не задумывался об этом, потому что сочетания клавиш обычно прослушиваются с помощью keydown
, но это может сработать в более интересных сценариях, подобных этому...
Не могли бы вы показать какой-нибудь код, чтобы мы могли выяснить, когда возникает проблема, и отладить ее оттуда?
хорошо, я сейчас создаю небольшой редактор в jsfiddle. @код
Я только что понял, что моя функция обнаружения ярлыков была неисправна :( Когда вы нажимаете эти клавиши и держите их нажатыми в том же порядке Ctrl
+Any
+I
, моя функция не может идентифицировать это как сочетание клавиш для курсива и, таким образом, пропускает событие Мне очень жаль всех - отмена ярлыков на «keydown», кажется, на самом деле очень хорошо справляется со своей задачей.
Это была ошибка оператора (меня), и код был в порядке.
Вот еще одна стратегия, которая может сработать для вас. Вместо того, чтобы пытаться предотвратить вставку элементов b
и i
, просто сразу удалите их на keyup
или на paste
.
К рассмотренным случаям относятся:
И он работает рекурсивно, чтобы заботиться о вложенных элементах.
let forbiddenTags = ["B", "I", "STRONG"]
let clean = function(e){
// Loop through all child nodes
e.target.childNodes.forEach(function(item){
// recursion if there are childnodes
if (item.childNodes){
clean({target:item})
}
// Remove forbidden tags
if (item.tagName && forbiddenTags.indexOf(item.tagName) > -1){
item.insertAdjacentHTML("afterEnd", item.innerHTML)
item.remove()
return
}
// Reset inline style
if (item.style){
item.style.fontWeight = "normal"
item.style.fontStyle = "normal"
}
})
}
document.querySelector("#test").addEventListener("keyup", clean)
document.querySelector("#test").addEventListener("paste", clean)
div{
border: 1px solid grey;
padding: 0.5em;
}
table{
border-collapse: collapse;
}
td{
border: 1px solid grey;
}
<div id = "test" contentEditable=true>Enter text here</div>
<br>
Paste me in!:
<div id = "pasteit">
<b>bold</b> <i>italic</i> <strong>strong</strong> <span style = "font-weight:bold;">inline</span>
<table>
<tr>
<td style = "font-style:italic;">Italic</td>
<td style = "font-weight:bold;">Bold</td>
</tr>
</table>
</div>
Это работает, но, по-моему, это ужасный UX. Я думаю, что пользователь попытается выделить его жирным шрифтом, это работает, говорит «ура», идет «куда в мире делся мой жирный текст»? Попробовав 3 или 4 раза, пользователь сообщает об ошибке, в которой говорится, что «всякий раз, когда я выделяю что-то жирным шрифтом, оно выделяется». Счастливый разработчик, безумный потребитель.
@code: можно легко показать alert
или красивое модальное окно, чтобы сообщить пользователю, что жирный шрифт и курсив не разрешены.
это правда, но до того, как я научился программировать, на некоторых веб-сайтах, которые я использовал, были редактируемые элементы div, где, когда я вставлял HTML вместо предотвращения вставки, он сразу же удалял его. Там все еще есть доли секунды показа HTML. Хотя я не был разработчиком, я был очень раздражен и подумал, что тот, кто создал веб-сайт, сделал плохую работу; также было ясно, что мне не разрешалось вставлять HTML, но я все еще ненавидел то, как это работает. Я не скажу, что этот ответ сам по себе плохой, но UX действительно действует мне на нервы. Было бы намного лучше сделать так, чтобы жирный текст никогда не появлялся.
@code: С самого начала ... Почему не разрешить выделение жирным шрифтом и курсивом - это настоящий вопрос. ;)
Это несколько работает, но с этим решением вы все еще подвергаетесь черной магии contenteditable - это означает, что полужирный шрифт обрабатывается по-разному (т.е. путем его переноса в b или strong или с использованием встроенного) в зависимости от разных браузеров/кейсов.
Я отредактировал, чтобы заботиться об этих случаях.
Снова отредактировано, чтобы позаботиться о вложенных элементах.
Лойс, ваше решение работает, но оно просто слепо убивает указанные стили текста. Сценарии использования такого решения чрезвычайно малы, поскольку каждый контент, доступный для редактирования, должен обрабатываться и храниться в каком-либо формате данных. Правильное решение состоит в том, чтобы запретить contenteditable когда-либо применять стиль текста, чтобы нам не приходилось иметь дело с непоследовательным адом разметки при обработке его содержимого. Это также решило бы проблемы UX, упомянутые @code. Я обновил свой вопрос, чтобы отразить мои новые выводы.
Не уверен, с какой проблемой вы имеете дело, но это работает хорошо...
document.getElementById("test").addEventListener("keydown", e => {
if (!e.ctrlKey) return;
if (e.keyCode === 66 || e.keyCode === 73) {
e.preventDefault();
}
});
<div id = "test" contenteditable>This div is editable</div>
И однострочник для вашего удовольствия:
document.getElementById("test").onkeydown = e => !(e.ctrlKey && (e.keyCode === 66 || e.keyCode === 73));
<div id = "test" contenteditable>This div is editable</div>
Почему вы используете и
keyup
, иkeydown
? Кстати,keyup
не сработает, потому что, подумайте об этом. Когда вы нажимаетеCtrl
+T
илиCtrl
+S
, прежде чем вы уберете палец с клавиатуры, желаемое действие уже выполняется. Я бы, наверное, просто использовалkeyup
. Не могли бы вы включить код?