Javascript-форум (https://javascript.ru/forum/)
-   Общие вопросы Javascript (https://javascript.ru/forum/misc/)
-   -   Обрамление тегами выделенного текста (https://javascript.ru/forum/misc/84594-obramlenie-tegami-vydelennogo-teksta.html)

javascript_pupil 23.10.2022 14:26

Обрамление тегами выделенного текста
 
Не хочется изобретать велосипед: эта функция работает во многих движках форумов, включая и этот. Нажимаешь на кнопку "Вставить ссылку" и выходит всплывающее окно, которое, после ввода необходимой информации вставляет её в выделенный текст.

Вот, пример: форум <- сделанный скриптом данного движка.

Вопрос: где найти читабельный пример подобного кода? Понимаю, что это где-то в файле типа ckeditor.js, но JS код там сжат и достать его быстро не получается. Есть примеры на Stack Overflow, но там без всплывающего окна для ввода URL.

Alikberov 24.10.2022 07:00

<script>
function addLink() {
	const textarea = document.querySelector("TextArea");
	const text = textarea.value.substring(textarea.selectionStart, textarea.selectionEnd);
	const href = prompt("Адрес ссылки", "https://javascript.ru/forum/misc/");
	textarea.value = `${textarea.value.substr(0, textarea.selectionStart)}<a href='${href}'>${text}</a>${textarea.value.substr(textarea.selectionEnd)}`;
	document.body.appendChild(code);
}
</script>
<body>
<button onclick='addLink()'>Добавить ссылку</button>
<textarea>Ссылка#1 Ссылка№2</textarea>
</body>

рони 24.10.2022 07:04

Alikberov,
а выделенный текст где? :no: автор просит это

Alikberov 24.10.2022 07:19

Цитата:

Сообщение от рони (Сообщение 548550)
Alikberov,
а выделенный текст где? :no: автор просит это

Упс. Поправил.:D

рони 24.10.2022 07:26

Alikberov,
после строки 5
if(!href) return;
и
if(!text) text = href;
или так
<a href='${href}'>${text||href}

Alikberov 24.10.2022 08:01

Цитата:

Сообщение от рони (Сообщение 548552)
Alikberov

A не слишком ли упрощаем задачу?:lol:
Лет 20 тому назад на уроках Лого не все понимали, почему вторичный запуск кода выдавал ошибку, так как не догадывались поставить черепашку в исходную точку.

javascript_pupil 25.10.2022 21:28

Всем спасибо, но "не работает". :(

Точнее: сам пример решения конечно рабочий, но как только начинаешь его встраивать в свою систему - отказ. Пробовал 2 варианта:

1. Целиком указанный код на страницу перлового скрипта. Получаю серверную ошибку: Not enough arguments for substr at ... near "selectionEnd)"
Ругается вот на эту строку:
textarea.value = `${textarea.value.substr(0, textarea.selectionStart)}<a href='${href}'>${text}</a>${textarea.value.substr(textarea.selectionEnd)}`;

Почему Perl падает из-за JS сказать затрудняюсь.

2. Вынос скрипта во внешний файл выдает следующую ошибку: "addLink" не определено.

Вроде бы всё правильно, но не работает - ничего не происходит. Да, "button" заменил на
<a href="#" onclick="addLink()">Add Link</a>


Буду признателен за подсказку: что я сделал не так?

Alikberov 26.10.2022 06:00

<script>
function addLink(button) {
	const textarea = button.parentNode.TextAreaTag;
	const href = prompt("Адрес ссылки", "https://javascript.ru/forum/misc/");
	const text = textarea.value.substring(textarea.selectionStart, textarea.selectionEnd) || href;
	if(!href)
		return;
*!*
	// Определите один из этих двух рабочих вариантов
	if("ticks" in button.dataset)
		textarea.value = `${textarea.value.substr(0, textarea.selectionStart)}<a href='${href}'>${text}</a>${textarea.value.substr(textarea.selectionEnd)}`;
	else
		textarea.value = textarea.value.substr(0, textarea.selectionStart) + "<a href='" + href + "'>" + text + "</a>" + textarea.value.substr(textarea.selectionEnd);
*/!*
	document.body.appendChild(code);
}
</script>
<body>
<form>
<a href='#' onclick='addLink(this)' data-ticks><img src='https://javascript.ru/forum/images/editor/createlink.gif'></a>
<a href='#' onclick='addLink(this)'><img src='https://javascript.ru/forum/images/editor/createlink.gif'></a><br>
<textarea name=TextAreaTag rows=3 cols=80>
Ссылка#1
Ссылка№2
</textarea>
</form>
</body>

javascript_pupil 26.10.2022 08:47

Вот этот вариант со строкой
textarea.value = textarea.value.substr(0, textarea.selectionStart) + "<a href='" + href + "'>" + text + "</a>" + textarea.value.substr(textarea.selectionEnd);

мне более понятен и он работает в моем случае. Спасибо!

Но есть еще 1 нюанс. В моем случае в форме используются 2 textarea, но мне бы хотелось обойтись одной кнопкой для них. В любом случае выделить текст можно только в одной textarea, соответственно в нее и надо вставлять модифицированную строку. Вопрос: чем заменить "textarea.value"? Ведь у нас две одинаковых textarea, естественно с разными именами и идентификаторами.

Alikberov 26.10.2022 09:30

<script>
function addLink(button) {
	if(button.parentNode.dataset.focused) {
		const textarea = button.parentNode[button.parentNode.dataset.focused];
		const href = prompt("Адрес ссылки", "https://javascript.ru/forum/misc/");
		const text = textarea.value.substring(textarea.selectionStart, textarea.selectionEnd) || href;
		const pos = textarea.selectionStart;
		if(href)
			textarea.value = textarea.value.substr(0, textarea.selectionStart) + "<a href='" + href + "'>" + text + "</a>" + textarea.value.substr(textarea.selectionEnd);
		textarea.focus();
		textarea.selectionStart = textarea.selectionEnd = pos;
	}
}
</script>

<body>
<form data-focused>
<a href='#' onclick='addLink(this)'><img src='https://javascript.ru/forum/images/editor/createlink.gif'></a><br>
<textarea name=TextAreaTag rows=3 cols=80 onfocus='this.parentNode.dataset["focused"] = this.name'>
Ссылка#1
Ссылка№2
</textarea><br>
<textarea name=TextAreaTaq rows=3 cols=80 onfocus='this.parentNode.dataset["focused"] = this.name'>
Ссылка#3
Ссылка№4
</textarea>
</form>
</body>

javascript_pupil 26.10.2022 10:19

Этот вариант не подходит. Надо переписывать программный код которым создаются формы, textarea и т.п. Проще вторую кнопку воткнуть для 2-й textarea.

И у меня еще один вопрос: как проверить href регуляркой?

На Perl это выглядело бы так:

if ($url =~ m/^http/) {
...
} else {
...
}

javascript_pupil 26.10.2022 10:29

Разобрался со вторым вопросом:
if (href.match(/^(http)/)) {

Alikberov 27.10.2022 07:00

Цитата:

Сообщение от javascript_pupil (Сообщение 548590)
Этот вариант не подходит. Надо переписывать программный код которым создаются формы, textarea и т.п. Проще вторую кнопку воткнуть для 2-й textarea.

<script>
var lastTextArea; // Сохраняет ссылку на TextArea под фокусом при нажатии на кнопку вставки ссылки
var lastUserLink = "https://javascript.ru/forum/misc/"; // Сохраняет адрес последней введенной ссылки

function addLink(button) {
	if(button.parentNode.contains(lastTextArea)) {
		const href = prompt("Адрес ссылки", lastUserLink);
		const text = lastTextArea.value.substring(lastTextArea.selectionStart, lastTextArea.selectionEnd) || href;
		const injected = "<a href='" + href + "'>" + text + "</a>";
		const from = lastTextArea.selectionStart;
		let last = lastTextArea.selectionEnd;
		if(href) {
			lastUserLink = href; // Запоминаем адрес введённой ссылки
			lastTextArea.value = lastTextArea.value.substr(0, from) + injected + lastTextArea.value.substr(last);
			last = from + injected.length; // Корректируем выделение, чтобы охватить вставляемый тег ссылки
		}
		lastTextArea.focus(); // Возвращаем фокус и восстанавливаем выделение
		lastTextArea.selectionStart = from;
		lastTextArea.selectionEnd = last;
	}
}
</script>

<body>
<form>
<a href='#' onfocus='lastTextArea = event.relatedTarget' onclick='addLink(this)'><img src='https://javascript.ru/forum/images/editor/createlink.gif'></a><br>
<textarea rows=3 cols=80>
Ссылка#1
Ссылка№2
</textarea><br>
<textarea rows=3 cols=80>
Ссылка#3
Ссылка№4
</textarea>
</form>
</body>

javascript_pupil 28.10.2022 10:03

Теперь другая проблема: это не работает в IE 11. :(

javascript_pupil 28.10.2022 10:20

Еще вопрос: а может быть решать эту задачу другим способом? Не привязываться к каким либо тегам, а работать с выделенным текстом. Т.е. сохранять его где-то, затем обрабатывать добавляя введенную из всплывающего окна информацию (URL в данном случае) и возвращать модифицированный текст обратно, заменяя выделенный и снимая выделение.

Что-то типа этого возможно?

function getSelectionText() {
var txt = '';
  
txt = window.getSelection().toString();

const href = prompt("Link URL", "");

txt.value = txt + href;

}


Вариант не работает, но смысл думаю понятен.


Часовой пояс GMT +3, время: 21:21.