webew
Войти » Регистрация
 
JavaScript

WYSIWYG: вставляем произвольный HTML-код

5 ноября 2008, 19:31

Задача: при редактировании данных в визуальном редакторе иметь возможность вставлять произвольные элементы форматирования, например, заголовки.

Метод execCommand позволяет вставлять как простейшие элементы форматирования (жирность, курсив, подчеркивание), так и более сложные. Начнем с них.

Диалог с пользователем — создаем ссылки

Усложним код нашего простейшего висивига, добавив туда кнопку для добавления ссылок. Прежде чем добавить ссылку, необходимо спросить у пользователя её URL. Сделаем это с помощью метода prompt. Всего несколько строк кода необходимо добавить к текущему коду висивига, чтобы заработало добавление ссылок:

// Выведем HTML-код этих элементов
document.write("<input type='button' value='Link' onclick='setLink()' class='under' />");
// Запишем код функции для выставления форматирования
// Используется метод execCommand объекта document
function setLink() {
    var url = prompt("Введите URL:", "http://");
    if (!url) return;
    iWin.focus();
    iWin.document.execCommand("CreateLink", null, url);
}

Пример простейшего ВИСИВИГа с функцией добавления ссылок

Как видно из примера, метод execCommand принимает в качестве третьего аргумента параметр команды CreateLink — URL ссылки. Не только создание ссылки требует диалога с пользователем. Чтобы задать цвет текста или цвет фона (команды ForeColor и BackColor соот-но), необходимо попросить юзера выбрать этот цвет (обычно из какого-то списка), а затем передать его методу в формате #RRGGBB.

Вставляем произвольный HTML-контент

Вам необходимо вставить в визуальный редактор вполне конкретный HTML-код, например такой:

<h1 class="oranzh"></h1>

Метод execCommand бессилен для решении такой задачи. Необходимо собственное решение, например, такой обходной путь:

  • Чтобы поставить произвольное форматирование на выделенный фрагмент, воспользуемся командой forecolor, которая выставит цвет текста. Цвет специально подберем такой, которым пользуются нечасто.
  • В зависимости от браузера цвет выставляется либо с помощью <font color="#RRGGBB"></font> (IE, Opera), либо с помощью <span style="color:rgb(RR,GG,BB)"></span> (Gecko). Чтобы привести цвет к единому формату #RRGGBB воспользуемся функцией rgbNormal().
  • Пройдемся по всем узлам DOM-дерева документа, найдем фонты и спаны с нужным цветом и добавим в них необходимый HTML-код, не забывая почистить за собой. Обход по узлам — дело не простое. Т.к. мы удаляем узлы с нужным цветом, необходимо идти от самых вложенных элементов вверх по иерархии узлов, чтобы не получилось сбоя. Для этого восопользуемся функцией nodeList, которая отдаст массив узлов с указанием степени их вложенности, который можно отсортировать.

Новый код:

// ***********************
// ШАГ 5: Форматирование произвольным HTML-контентом
// ***********************
// nodeList - формирует массив всех узлов с указанием степени их вложенности
function nodeList(parentNode, list, level) {
    var i, node, count;
    if (!list) list = new Array();
    level++;
    for (i = 0; i < parentNode.childNodes.length; i++) {
        node = parentNode.childNodes[i];
        if (node.nodeType != 1) continue;
        count = list.length;
        list[count] = new Array();
        list[count][0] = node;
        list[count][1] = level;
        nodeList(node, list, level);
    }
    return list;
}
// rgbNormal - приводит цвет к стандарту #RRGGBB
function rgbNormal(color) {
    color = color.toString();
    var re = /rgb\((.*?)\)/i;
    if(re.test(color)) {
        compose = RegExp.$1.split(",");
        var hex = ['0','1','2','3','4','5','6','7','8','9','A','B','C','D','E','F'];
        var result = "#";
        for (var i = 0; i < compose.length; i++) {
            rgb = parseInt(compose[i]);
            result += hex[parseInt(rgb / 16)] + hex[rgb % 16];
        }
        return result;
    } else return color;
}
function execCommandImitation(start, end) {
    // Cтавим ForeColor-форматирование с помощью специального цвета
    iDoc.execCommand("ForeColor", false, "#f5F856");
    // Получаем все элементы форматируемого документа
    var allNodes = nodeList(iDoc.body, false, 0);
    // Сортируем их по уровню вложенности
    var maxLevel = 0;
    for (i = 0; i < allNodes.length; i++) {
        maxLevel = allNodes[i][1] > maxLevel ? allNodes[i][1] : maxLevel;
    }
    // 4. Для всех элементов заменяем FONT и SPAN со специальным цветом на переданный код
    var node, newnode, color, parent;
    for (j = maxLevel; j >= 1; j--) {
        for (i = 0; i < allNodes.length; i++) {
            if (allNodes[i][1] != j) continue;
            node = allNodes[i][0];
            sname = node.nodeName.toLowerCase();
            color = node.color ? rgbNormal(node.color) : rgbNormal(node.style.color);
            if (color) color = color.toLowerCase();
            if (sname == "font" || sname == "span" && color == "#f5f856") {
                try {
                    node.innerHTML = start + node.innerHTML + end;
                } catch(e) {}
                parent = node.parentNode;
                while (node.childNodes.length > 0) parent.insertBefore(node.firstChild, node);
                parent.removeChild(node);
            }
        }
    }
    iWin.focus();
}

Пример ВИСИВИГа c произвольным HTML-форматированием

Чтобы заголовок был оранжевым, при формировании стилей документа был добавлен класс:

iHTML += ".oranzh {color:#FF6300;}";

Поверено в WIN: IE6, IE7, FF2, Opera 9.5, Safari 3.

Задача решена!


// Все права на статью JavaScript::WYSIWYG - вставляем произвольный HTML-код принадлежат сайту 2007.fastcoder.ru
Статьи, часто просматриваемые вместе с этой:
Определение версии flash-плеера
Об осле и ресайзе
Пользуемся AJAX-объектом
Добавить комментарий
Отображение комментариев: Древовидное | Плоское

Zodios

Спасибо за обзор только вот не понял зачем это нужно? Чем не подходят уже написанные редакторы? Или это ознакомительная статья?
zodios.net
06.11.2008, 08:38
Ответить

bur

Уже написанные редакторы - это сильно сказано. Чаще всего берут tinyMCE, больше хорошо написанных и распространенных продуктов не припомню.

Так вот, если вам нужно от висивига жирность, курсив и ссылка, то можно:
а) Воспользоваться услугами tinyMCE, там неплохое API и немного повозившись с настройками можно получить необходимый результат.
б) Написать свой простейший редактор c JavaScript-кодом на 1 экран. Такой подход мне лично больше по душе, т.к. понимаешь суть происходящих процессов и можешь внести любые корректировки.

А теперь внимание! Вам необходима своя личная кнопка, которой нет в арсенале tinyMCE, например, кнопка "Цитата", вставляющая в простешем случае такой код:

<p class="quote">тут выделенный фрагмент, если он есть</p>


Ну и в стили висивига нужно будет дописать:
p.quote {font:italic 100% arial; color:#666; padding-left:5px; border-left:2px solid #666;}


Это для примера. Может пригодится кнопка "Юзер" (как в ЖЖ или Хабре) или кнопка "Полночный бред" для висивига какой-нибудь социальной сети. С очень сложным фрагментом HTML-кода. Куда бежать? Что делать?

Так вот, бежать никуда не надо, берем готовую функцию и вставляем HTML-код любой сложности по фокусу в визуальные редактор.

Кстати, это вторая статья в цикле статей про висивиги. Целью цикла является подробное объяснение механизмов работы визуального редактора и написание небольшого готового решения, которое можно будет доточить до любого удобного состояния.
06.11.2008, 08:55
Ответить
NO USERPIC

ayavryk

>Чаще всего берут tinyMCE, больше хорошо написанных и распространенных продуктов не припомню.
Наверное вы плохо смотрели. У него достаточно глюков по сравнению с FCKEditor или JCE Editor. Ну и по производительность на больших текстах он проигрывает FCK. Кстати такая же беда будет у вашего самопального редактора. Врожденный дефект.

>А теперь внимание! Вам необходима своя личная кнопка, которой нет в арсенале tinyMCE, например, кнопка >"Цитата", вставляющая в простешем случае такой код:
Воспользуйтесь FCK там есть возможность вставки готовых шаблонов. Странно, что такой возможности нет в Tiny. Хотя идея вставки через визивиг элементов форм (кнопки) попахивает бредом.

Свой редактор конечно здорово. В учебных целях. Для работы - занятие непродуктивное. Однако переписывать заново необходимый функционал - занятие неблагодарное. Ни один Визивиг нельзя допускать до пользователя без кнопки "Paste from MS Word". Написать ее может быть просто, но глюк с разрушением таблиц год назад присутствовал практически во всех халявных визивигах исключая м.б. FCKEditor и JCE Editor

07.11.2008, 10:04
Ответить
NO USERPIC

plagm

>А теперь внимание! Вам необходима своя личная кнопка, которой нет в арсенале tinyMCE, например, кнопка "Цитата", вставляющая в простешем случае такой код:

<p class="quote">тут выделенный фрагмент, если он есть</p>


Если нет нужной кнопки, то можно написать плагин для tinyMCE. У них хорошее API для этого. Сам писал неоднократно.
05.12.2008, 14:16
Ответить

Zodios

Мне кажется для облегченной версии которая здесь приводится хорошое применение в форме написание комментария на блоге?
zodios.net
06.11.2008, 13:06
Ответить
NO USERPIC

ApplE

Кроме tinyMCE есть ещё FCKEditor. Но это я не к тому что лучше ими пользоваться. Придерживаюсь того же мнения - если есть возможность, время, деньги (нужное подчеркнуть) лучше всё написать самому. При условии что понимаешь что пишешь. Тогда действительно больше контроля над своим кодом. Как следствие его легче модернизировать.

Огромное спасибо за статью. Пролили свет на то как это работает. А то порой настроить мощный редактор, перенасыщенный ненужными, в конкретном проекте, функциями очень тяжело.

И если честно появляется некоторое недоверие. Не столько к самому редактору (tineMCE, FCKEditor) сколько к своим настройкам в нём. Всё ли учёл? Как это это повлияло на безопастность и работоспособность? Уменшился или увеличился трафик и нагрузка на браузер. Для меня это важно. В этом случает 100%-эффективнее написать свой, с четким набором функций редактор где всё просто и понятно.

Ещё раз спасибо.
06.11.2008, 13:48
Ответить
NO USERPIC

satel

Добрый день. Есть задача: в FCKeditor добавить свою кнопку, при нажатии на которую после курсора вставляется следующий текст: <center><a class="highslide" onclick="return hs.expand(this, {captionId: 'caption1'})" href="http://drupal.site/sites/default/files/node_images/1.gif"><img height="80" alt="" width="100" border="1" wigth="200" style="border-right: medium none; border-top: medium none; border-left: medium none; border-bottom: medium none" src="http://drupal.site/sites/default/files/node_images/1_thumb.gif" /></a>&nbsp; <center></center></center>
Кнопку нарисовал, назвал VAW.gif, теперь я так понимаю надо создать файл fckplugin.js и в него прописать скрипт для этой кнопки. Подскажите, что прописывать???
03.07.2009, 07:07
Ответить
Добавить комментарий
Отображение комментариев: Древовидное | Плоское
© 2008—2017 webew.ru, связаться: x собака webew.ru
Сайт использует Flede и соответствует стандартам WAI-WCAG 1.0 на уровне A.
Rambler's Top100

Реклама: