21.09.2022, 19:20
|
Новичок на форуме
|
|
Регистрация: 21.09.2022
Сообщений: 9
|
|
Множественное выделение текста Range
Всем привет! Помогите, пожалуйста, гуру JS, бьюсь не первый день, в сети нет информации по этому вопросу...
В общем есть редактируемый DIV, в нем можно набрать текст, в firefox'е при зажатии Ctrl можно выделить несколько областей одновременно и с ними работать... Но вот незадача, когда корректирую один из фрагментов выделенных, остальные выделения отпускаются и мой цикл завершается...
Прошу прощения, что привожу код не в песочнице, а тут, так как песком вообще не пользуюсь...
for(let n = 0; n < select.rangeCount; n++){
let range = select.getRangeAt(n);
let newNode = document.createElement(pressButton);
newNode.appendChild(range.cloneContents());
range.insertNode(newNode);
range.setStartAfter(newNode);
range.deleteContents();
}
Заранее всех благодарю...
|
|
21.09.2022, 19:43
|
|
Тлен
|
|
Регистрация: 02.01.2010
Сообщений: 6,587
|
|
Всё работает (выдели три раза):
<body>
Всем привет! Помогите, пожалуйста, гуру JS, бьюсь не первый день, в сети нет информации по этому вопросу...
В общем есть редактируемый DIV, в нем можно набрать текст, в firefox'е при зажатии Ctrl можно выделить несколько областей одновременно и с ними работать... Но вот незадача, когда корректирую один из фрагментов выделенных, остальные выделения отпускаются и мой цикл завершается...
Прошу прощения, что привожу код не в песочнице, а тут, так как песком вообще не пользуюсь...
<script>
document.documentElement.onmouseup = () => {
const pressButton = 'u';
const select = getSelection();
if(select.rangeCount < 3) return;
for(let n = 0; n < select.rangeCount; n++){
let range = select.getRangeAt(n);
let newNode = document.createElement(pressButton);
newNode.appendChild(range.cloneContents());
range.insertNode(newNode);
range.setStartAfter(newNode);
range.deleteContents();
}
}
</script>
Заранее всех благодарю...
</body>
Нужно больше деталей где именно проблемы.
Могу предложить сначала положить Range'и в массив, а потом с ним работать, но без конкретики - это гадание.
P.S. Ну и я бы на тему этой фичи не заморачивался, хром так не умеет и не собирается вроде.
__________________
29375, 35
|
|
23.09.2022, 17:55
|
Новичок на форуме
|
|
Регистрация: 21.09.2022
Сообщений: 9
|
|
Спасибо большое за ответ! Сейчас проверил и правда все работает, тогда значит у меня в коде где-то выделение снимается... А разве range не является живой коллекцией? Вернее если поместить его в массив и менять, разве остальные ключи не изменятся?
|
|
23.09.2022, 19:12
|
Новичок на форуме
|
|
Регистрация: 21.09.2022
Сообщений: 9
|
|
В общем немного разобрался, ваш код с событием на мышку работает, а в моем коде событие на нажатие кнопки в интерфейсе, но у меня фокус не теряется, с этим у меня уже была проблема я с ней разобрался ранее...
Я выделяю текст, нажимаю на кнопку, все меняется и выделение остается, но, когда создаю несколько выделений и так же нажимаю на кнопку, первое исправляется, а последующие нет и выделение с них снимается...
Понимаю, что возможно задаю глупый вопрос, потому что кода привожу мало, но может у кого-то был с этим опыт?
|
|
23.09.2022, 19:46
|
|
Тлен
|
|
Регистрация: 02.01.2010
Сообщений: 6,587
|
|
nail2010, без кода - можно только гадать. Нужен хотя бы твой магческий способ не терять фокус. Скорее всего он работает просто восстанавливая выделение после того как оное пропало и не учитывает вариант множественности.
__________________
29375, 35
|
|
29.09.2022, 19:48
|
Новичок на форуме
|
|
Регистрация: 21.09.2022
Сообщений: 9
|
|
Прошу прощения за такую большую задержку, но проект большой и частей много... Я вывел аспекты, которые касаются этого функционала и привел вот в этом, отдельно взятом html-файле...
<html>
<head>
<title></title>
<script>
document.addEventListener("DOMContentLoaded", function(){
// Перебираем кнопки
for(let n = 1; n <= 3; n++){
document.getElementById("BUTTON_"+n).onclick = function(){
let select = window.getSelection();
if(select.isCollapsed){
// Ни одного выделенияя нет
}
else {
let pressButton = this.getAttribute("data-tagName");
let countSelected = 0;
// Перебераем выделения
for(let n = 0; n < select.rangeCount; n++){
let range = select.getRangeAt(n);
let parentElem = range.commonAncestorContainer.parentNode;
let parentElemСhangeable = range.commonAncestorContainer;
// Выделение в нашем блоке
for(let q = 0; q <= q+1; q++){
if(parentElemСhangeable.id == "CONTENT"){
let newNode = document.createElement(pressButton);
newNode.appendChild(range.cloneContents());
range.insertNode(newNode);
range.setStartAfter(newNode);
range.deleteContents();
break;
}
else {
parentElemСhangeable = parentElemСhangeable.parentNode;
}
if(parentElemСhangeable.tagName == "BODY"){
break;
}
}
}
}
}
}
});
</script>
</head>
<body>
<div id="CONTENT" contenteditable="true" style="display:inline-block; border:1px dashed #999; color:#666; background:#EEE; padding:2px 5px; margin:10px 0; min-height: 10em;">
Какое-то длинное высказывание, как вводная часть текста... Выдели меня... Выдели меня... Выдели меня... Выдели меня...
</div>
<div>
<button id="BUTTON_1" data-tagName="H1" style="margin-right: 0.5em;">Заголовок 1</button>
<button id="BUTTON_2" data-tagName="H2" style="margin-right: 0.5em;">Заголовок 2</button>
<button id="BUTTON_3" data-tagName="H3">Заголовок 3</button>
</div>
</body>
</html>
|
|
29.09.2022, 19:54
|
Новичок на форуме
|
|
Регистрация: 21.09.2022
Сообщений: 9
|
|
Код с виду работает, но, к сожалению, не работает для множественных выделений... Я даже не знаю, что делать... Первое выделение заменяется, а последующие нет... Мне кажется, когда выполняется setStartAfter и deleteContents остальные выделения просто перестают быть выделенными... Может есть рецепт, без этих инструкций?
|
|
29.09.2022, 20:07
|
Новичок на форуме
|
|
Регистрация: 21.09.2022
Сообщений: 9
|
|
И вот еще один момент... Использую просто
range.surroundContents(newNode);
Без каких либо удалений... Но, этот метод он обрамляет все содержимое вместе с тегами и вкладывает их всех друг в друга, получается вроде этого:
<h2><h3>Выдели меня...</h3></h2>
но мне так не нужно...
Я, конечно, могу потом почистить код, перед отправкой или уже на сервере, но как быть с тем, что этот метод можно использовать только в полных боках...
Цитата:
|
Чтобы этот метод сработал, диапазон должен содержать как открывающие, так и закрывающие теги для всех элементов внутри себя: не допускаются частичные диапазоны по типу <i>abc
|
|
|
|
|