Подскажите пожалуйста, можно как-нибудь сделать так, чтобы часть текста в textarea
поле было заданного цвета, отличного от основного цвета текста?
Знаю, что есть отдельные библиотеки, но для моих целей это избыточно. Вот и думаю, можно ли обойтись малой кровью.
Стандартные элементы textarea
и input
не предоставляют возможностей форматирования отдельных подстрок их текстового содержимого, и не могут содержать вложенные строчные элементы (которым можно было бы задать CSS-стили).
Поэтому, данная задача обычно решается созданием имитации поля ввода:
Элементу, предназначенному для вывода (обычно берется div
или span
), добавляют атрибут contenteditable
- он включает возможность прямого редактирования текста содержимого;
CSS-стилями достигают внешнего сходства элемента со стандартным полем ввода - фон, бордер, прокрутка при переполнении, и т.д.. В контексте задачи, это самая легкая часть;
Пишут скрипт, который оборачивает части текстового содержимого в подэлементы (которые, в свою очередь, и оформляются средствами CSS). А также, реализуется поведение элемента, подобное поведению RichText-редактора. И вот это, уже весьма непросто.
Основная сложность - в получении и установке позиции каретки (текстового курсора)... актуальные веб-стандарты не предоставляют удобных средств для этого. Необходимо создавать велосипед, и довольно непростой (с нуля, подобный скрипт за 10 минут не написать).
Следовательно, если цель не в том чтобы создать свое - рациональнее будет использовать одну из множества готовых реализаций такого элемента ввода.
Простой пример подсветки (не "на лету"):
const HL_RULES = [
{ cl: 'str', re: /("[^"]+")/ },
{ cl: 'optr', re: /^(var|let|for|in|of|function|function*|const|do|while|break|continue|if|else|switch|case|default|try|catch|throw|delete|void|yield|yield*|return)$/ },
{ cl: 'cnst', re: /(\d+)/ },
{ cl: 'brcs', re: /({|})/ }
];
let txt = document.querySelector('.custom-textarea'),
btn = document.getElementById('hl');
txt.addEventListener('focus', () => txt.innerHTML = txt.textContent);
btn.addEventListener('click', () => simpleHighlighter(txt));
btn.click();
function simpleHighlighter(el) {
if (el instanceof Event)
el = this;
// если эту функцию назначать обработчиком input, то тут должен быть код сохранения позиции каретки...
let words = textToArray(el),
html = '',
rule;
words.forEach(word => {
if (rule = getHlRuleFor(word))
html += `<span class="${rule.cl}">${rule.m}</span>`;
else
html += word;
});
el.innerHTML = html;
// ..., а тут - код установки каретки обратно на сохраненную позицию
}
function textToArray(el) {
const RE = /(^|\(+?|[^\w]+?)((?:"[^"]*")|(?:[{}\w]+))(\)+?[\S]+?)?/gmi; // эта регулярка весьма далека от совершенства :)
let result = [],
match, i;
while (match = RE.exec(el.textContent)) {
for (i = 1; i < match.length; i++) {
if (match[i])
result.push(match[i]);
}
}
return result;
}
function getHlRuleFor(word) {
let rule, mr;
if (rule = HL_RULES.find(r => mr = word.match(r.re)))
rule.m = mr[1];
return rule;
}
* { font: 14px sans-serif; }
html, body { margin: 0; padding: 0; }
.custom-textarea {
min-width: 40ch;
min-height: 7em; height: 50%;
padding: 0.1em 0.3ch; margin: 0.5em 0;
overflow: auto; resize: both;
border: 1px solid #ccc;
}
.custom-textarea,
.custom-textarea span {
font-family: monospace;
}
.str { color: #e94; }
.optr { color: #47d; font-weight: 500; }
.cnst { color: #4a4; }
.brcs { color: #d44; }
<pre class="custom-textarea" contenteditable="">function foo() {
let a = "Последовательность чисел:";
for (var i = 0; i < 42; i++) {
if (a === 13)
alert("Попалось 'счастливое' число :)");
a += " " + i;
}
return a;
}
</pre>
<button id="hl">Подсветить синтаксис</button>
<textarea rows="7" contenteditable="true">
<h1>qwa</h1>
<p>qwa-qwa</p>
</textarea>
введи @qwa
// -----
var textarea = textarea || document.getElementById('textarea')
let timer = null // id таймера
let t = 1e3 // задержка в миллисекундах
textarea.addEventListener('keyup', foo)
// --
function highlightWords() {
var original = textarea.textContent
var replaced = original.replace(/@[a-zA-Z0-9]+/g,
(username) => "<span class='exists'>" + username + "</span>")
textarea.innerHTML = replaced
}
function foo(e) {
clearTimeout(timer)
if (e.srcElement.textContent) {
timer = setTimeout(highlightWords, t);
}
}
div[contenteditable=true] {
width: 300px;
height: 200px;
border: 1px solid #ccc;
padding: 5px;
}
.exists {
color: blue;
}
<div contenteditable="true" id="textarea">
<h1>qwa</h1>
<p>qwa-<b>qwa</b></p>
<center>center</center>
</div>
данный пример взят и отредактирован отсюда https://stackoverflow.com/a/21420554/4794368
Айфон мало держит заряд, разбираемся с проблемой вместе с AppLab
Перевод документов на английский язык: Важность и ключевые аспекты
Доброго времени суток, стоит задача передать N таблиц html в excel в формате xlsx + передавать туда же картинку в виде base64, может кто сталкивался подскажите...
Проблема с работой cssПочему тег p с классом cite не работает? Написал всё правильно, проверил через ideone, работает нормально
Есть OwlCarousel с фотографиями, при нажатии на которые по двойному клику должна открываться галерея fancyboxДело в том, что галерея открывается по умолчанию...