Редактор HTML-тегов на JS


Пусть это и не ново, но в данной статья я расскажу, каким образом реализована вставка BB-кодов в <textarea> на различных форумах и гостевых книгах. Также этот подход можно приспособить для того, чтобы написать редактор HTML-тегов, например для CMS при создании новой записи, чтобы можно было быстро, если понадобиться, обрамить текст в нужные теги. Понятное дело, это не визуальный редактор (WYSIWYG) и надо знать хоть чуть-чуть HTML. Я не особо люблю визуальные редакторы, т.к всё равно они оставляют много ненужного мусора в коде и тормознуто работают.

Для написания такого редактора, нам традиционно понадобиться помощь Javascript, в частности метод «document.getSelection» (для нормальных браузеров, читай не IE) и свойство «document.selection.createRange().text». Вызывая метод document.getSelection(), мы можем получить информацию о позиции курсора вначале выделения текста и его конце, что позволяет всегда точно выделить нужный кусок кода и вернуть его на место, предварительно обрамив HTML-тегом.
При помощи document.selection.createRange().text мы можем как читать (get), так и устанавливать (set) значение выделенного текста на странице.

Для того чтобы управлять логикой и содержимым для вставки нужного текста воспользуемся также стандартными функциями объекта window — prompt (позволяет ввести текст в спец. окно) и confirm (окно подтверждения, т.е «Ок» или «Отмена»). Перед началом работы, также, необходимо перевести фокус на поле ввода при помощи метода focus() у этого элемента формы. Для нашего будущего HTML-редактора мы также реализуем следующие функции:

  • вставка введенного имени тега в виде открывающего и закрывающего элемента (<TAG></TAG>)

  • вставка гиперссылки с дополнительными аттрибутами (<A>)

  • обработка нескольких строк для вставки списка (<OL> или <UL>)


Все остальные, необходимые вам, функции можете дописать сами по аналогии. Готовый код редактора вместе с комментариями приведен ниже:

<script type="text/javascript">

function HTML_edit( action )
{
area = document.getElementById('textfield'); // получаем объект поля ввода
area.focus(); // перед началом работы переводим фокус на текстарею (иначе в IE не будет работать)

// получаем выделенный текст и подготавливаем его к обработке
if( document.getSelection )
{
document.getSelection();

avalue = area.value;
sel_length = avalue.length;
sel_start = area.selectionStart;
sel_end = area.selectionEnd;

left_side_text = avalue.substring(0, sel_start);
selected_text = avalue.substring(sel_start, sel_end);
right_side_text = avalue.substring(sel_end, sel_length);
}
// для остальных браузеров (IE), не понимающих работу с «выделениями», приведенную выше
else if( document.selection ) selected_text = document.selection.createRange().text;

// обрабатываем выделенный текст на основе переданного аргумента action
switch( action )
{
// простая вставка любого тега
case 'custom_tag':
tagname = prompt('Введите название HTML-тега', '');
if( tagname )
{
prefix = '<'+ tagname +'>';
suffix = '</'+ tagname +'>';
}
break;
// вставка ссылки
case 'hyperlink':
if( !selected_text ) selected_text = prompt('Введите текст ссылки', '');
if( selected_text )
{
if( selected_text.match(/^http:\/\/|www/) ) {
url = selected_text;
selected_text = prompt('Введите текст ссылки', url) || '';
}
else url = prompt('Введите адрес ссылки', '') || '';

url = 'http://' + url.replace(/^\w+:\/\//, '');
title = prompt('Введите описание ссылки (title)', '') || '';
indexing = confirm('Добавить элементы для запрета индексации ссылки в поисковых системах?') || '';
prefix = (indexing ? '<noindex>' : '') + '<a href="'+ url +'" title="'+ title +'" '+ (indexing ? 'rel="nofollow"' : '') +'>';
suffix = '</a>' + (indexing ? '</noindex>' : '');
}
break;
// обработка нескольких строк текста для вставки списка
case 'list':
tagname = prompt('Укажите тип списка (UL - маркерованый, OL - нумерованый)', 'ul') || '';
selected_text = selected_text.replace(/\r?\n/g, '</li>\n\t<li>');
prefix = '<'+ tagname +'>\n\t<li>';
suffix = '</li>\n</'+ tagname +'>';
break;
}

// возвращаем результаты работы функции обратно в поле ввода текста
if( prefix != null && suffix != null )
{
if( document.getSelection ) area.value = left_side_text + prefix + selected_text + suffix + right_side_text;
else if( document.selection ) document.selection.createRange().text = prefix + selected_text + suffix;
}
}

</script>

<input type="button" value="&lt;CUSTOM TAG>" title="Вставка парного открывающего и закрывающего тега" onclick="HTML_edit('custom_tag')" />
<input type="button" value="&lt;A HREF=..>" title="Вставка ссылки" onclick="HTML_edit('hyperlink')" />
<input type="button" value="&lt;OL|UL> &rarr; &lt;LI>" title="Создание списка из выделенных строк" onclick="HTML_edit('list')" />
<br />
<textarea cols="115" rows="15" wrap="off" id="textfield"></textarea>


Результаты работы редактора

13.09.2009 / javascript, кодинг
Понравилась статья?
Подпишись на рассылку через RSS или следуй за нами в Twitter!
Похожие статьи:
Оценка статьи: проголосовало - 5, средняя оценка - 4,4
Комментарии к статье (3):
[ 31.08.2010 - 19:28 ] - Alexandr
Супер отличная статья! Сейчас добавляю новые функции этого редактора. :)
[ 31.08.2010 - 19:50 ] - Alexandr
Ой, забыл! У меня вопрос! Я добавил кнопку "равнение по центру" и сделал так на js:

case 'center':
tagname = prompt('Валяйте текст ;)', '');
if( tagname )
{
prefix = '<center>'+ tagname +'';
suffix = '</center>';
}
break;
}

Правильно ли? Или есть другой вариант?
Ваш вариант будет работать, но в этом случае, если выделить текст и нажать на кнопку, всё равно появиться окно «PROMPT», а нужно, по-хорошему, чтобы еще выделенный текст обрамлялся в нужный нам тег.

Вот мой вариант:
case 'center':
if( selected_text = selected_text || prompt('Валяйте текст', '') )
{
prefix = '<div align="center">',
suffix = '</div>';
}
break;

[ 01.09.2010 - 15:55 ] - Alexandr
Спасибо! Отличный сайт! Буду изучать, а то собрался написать свою CMS, а сам знаю только HTML и CSS.
Добавить комментарий
АНТИСПАМ: Выберите улыбающийся смайл: yep! nope! nope!
Оформление заявки
Файл>>