Задача: написать простейший визуальный редактор и немного разобраться как он работает.
- Простейший WYSIWYG (визуальный редактор)
- WYSIWYG: вставляем произвольный HTML-код
Что такое WYSIWYG?
WYSIWYG — аббревиатура What You See Is What You Get. В переводе: "что вижу, то и получаю". В висивиге можно просматривать и редактировать HTML-содержимое не редактируя HTML-код. Наиболее близкая аналогия ВИСИВИГу - это текстовый процессор от Microsoft Word, с которым многие знакомы. В нем, чтобы поставить жирность или курсив, не нужно писать теги или другие элементы форматирования, достаточно просто нажать соотствующую функциональную кнопку.
Как это работает?
Для написания простого ВИСИВИГа не нужно изобретать велосипед, все средства уже встроены и успешно работают. Механизм работы большинства визуальных редакторов основан на свойстве designMode объекта document. Это встроенное свойство (к сожалению, далеко не для всех браузеров, но для большинства современных) как раз и позволяет редактировать HTML-контент. После его активанции (designMode='On') на web-страницу можно ставить привычный нам курсор и набивать/удалять текст или изменять форматирование контента.
Бывает удобно не редактировать всю страницу, а иметь какую-то фиксированную область, для чего используется iframe. Именно его объект document используется для активации свойства designMode.
Форматирование содержимого в пределах ВИСИВИГа осуществляется с помощью непростого метода execCommand, реализация которого сильно различается от браузера к браузеру.
Смотрим JavaScript-код для простейшего ВИСИВИГа:
// ШАГ 1: Выводим iframe и получаем доступ к нему
// ***********************
// Выводим в HTML-поток iframe
document.write("<iframe scrolling='no' frameborder='no' src='#' id='frameId' name='frameId'></iframe><br/>");
// Определим Gecko-браузеры, т.к. они отличаются в своей работе от Оперы и IE
var isGecko = navigator.userAgent.toLowerCase().indexOf("gecko") != -1;
// Получаем доступ к объектам window & document для ифрейма
var iframe = (isGecko) ? document.getElementById("frameId") : frames["frameId"];
var iWin = (isGecko) ? iframe.contentWindow : iframe.window;
var iDoc = (isGecko) ? iframe.contentDocument : iframe.document;
// ***********************
// ШАГ 2: Добавим на пустую страницу ифрейма произвольный HTML-код
// ***********************
// Формируем HTML-код
iHTML = "<html><head>\n";
iHTML += "<style>\n";
iHTML += "body, div, p, td {font-size:12px; font-family:tahoma; margin:0px; padding:0px;}";
iHTML += "body {margin:5px;}";
iHTML += "</style>\n";
iHTML += "<body><u>Содержимое</u> с <b>HTML</b>-<i>разметкой</i></body>";
iHTML += "</html>";
// Добавляем его с помощью методов объекта document
iDoc.open();
iDoc.write(iHTML);
iDoc.close();
// ***********************
// ШАГ 3: Инициализация свойства designMode объекта document
// ***********************
if (!iDoc.designMode) alert("Визуальный режим редактирования не поддерживается Вашим браузером");
else iDoc.designMode = (isGecko) ? "on" : "On";
// ***********************
// ШАГ 4: Простейшие элементы редактирования: жирность, курсив, подчеркивание
// ***********************
// Выведем HTML-код этих элементов
document.write("<input type='button' value='Ж' onclick='setBold()' class='bold' />");
document.write("<input type='button' value='К' onclick='setItal()' class='ital' />");
document.write("<input type='button' value='Ч' onclick='setUnder()' class='under' />");
// Запишем код функции, для выставления форматирования
// Используется метод execCommand объекта document
function setBold() {
iWin.focus();
iWin.document.execCommand("bold", null, "");
}
function setItal() {
iWin.focus();
iWin.document.execCommand("italic", null, "");
}
function setUnder() {
iWin.focus();
iWin.document.execCommand("underline", null, "");
}
Пример работы простейшего ВИСИВИГа
Замечение:
Данная версия визуального редактора не может работать в Опере ниже версии 9.01 и покажет предупреждение "Визуальный режим редактирования не поддерживается Вашим браузером".
Работоспособность проверена в:
- IE 6,
- FF 1.5,
- Opera 9.01 +,
- Mozilla 1.7.2,
- NN 7.1 +.

Жду часть два - форматирование с помощью <h1></h1> и создание списков.
К примеру, нумерованный список по аналогии вставляется так:
iWin.focus();
iWin.document.execCommand("InsertOrderedList", null, "");
}
С заголовками, как и со вставкой любого произвольного HTML-контента сложнее. Постараюсь описать это в отдельной статье.
Добавьте на страницу скрытую текстарию (которая, кстати, может быть видна при отключенном яваскрипте) и кнопку "Отправить".
При клике на кнопку в текстарию записывайте содержимое висивига, примерно так:
<textarea id="dataId" name="data" />
<input type="submit" value="Отправить" />
</form>
<script type="text/javascript">
document.getElementById('dataId').style.display = 'none';
</script>
Совместите это с кодом висивига - должно помочь.
<textarea name="data" style="display:none;"></textarea>
Смотрите сами, всё зависит от решаемой задачи.
остальные нормально выводят только неформатированный код...
onsubmit="alert(iDoc.body.innerHTML);"
да, и еще вопрос сразу - много мусора в получаемом коде - можно как-нибудь малой кровью избавиться от него? или только через регулярные выражения?
Спасибо, заранее =)
Для отладки использую такой код.
<form method="post" action="result.php" onsubmit="this.data.value=iDoc.body.innerHTML">
<textarea id="dataId" name="data"></textarea>
<input type="submit" value="Отправить" />
</form>
Т.е. при нажатии на слово "Обновить" можно просмотреть html-код который генерирует редактор. Может кому пригодиться.
К сожалению, строка iDoc.designMode = (isGecko) ? "on" : "On";
не срабатывает. До присовения "On" iDoc.designMode = inherit, а после присвоения "On" становится равным "Off". Есть подозрение, что родительская страница блокирует изменения iDoc.designMode.
Буду благодарен за помощь. Уж очень не хочется использовать contentEditable
iDoc.open();
iDoc.write(iHTML);
iDoc.close();
Если сервер возвращает просто текст, без тегов, то он спокойно попадает для редактирования. А вот если сервер возвращает HTML, что и требуется, то редактор просто не хочет работать.
Пробовал также записывать код вот сюда
Результат тот же. Что посоветуете?
Second\
Third";
Возможно из-за этого у вас не работает скрипт?
Убрал средствами ПХП все символы перевода строки.
Потом еще косяк нашёл. Редактор при вставке ссылки использует вот такие кавычки
Заменил кавычки на одинарные ' теперь всё ништяк....
Примного благодарен!!!!!!
window.frames["frameId"].document.body.innerHTML =document.getElementById('someid').value
Таким образом не нужно изменять оригинальное форматирование текста и т.п.
Это более удобно, чем экранировать переносы и следить за кавычками на стороне сервера...
Но есть один важный вопрос. Как быть, если я хочу поместить редактор в конкретном месте на странице. Пробовала вывсети iframe не через document.write, а сразу в htm'ой странице там, где нужно. Но тогда он почему перестаёт быть виден через document.getElementById("frameId").
Подскажите, пожалуйста, как быть.
function setImage(url) {
iWin.focus();
iWin.document.execCommand("InsertImage", null, url);
}
но, если выделить добавленный смайл, то вокруг него появляется рамка и его можно растянуть. Более того, новый текст и смайлы можно после этого вводить только если щелкнуть вне ранее введенного смайла. Запрет на ресайз можно (правдо дост. криво) реализовать через css: img {width: auto !important; height: auto !important;}. А вот как победить остальные глюки?