Что такое WYSIWYG-редактор? Это редактор, позволяющий пользователю видеть (в форме редактора) то, что он получит, нажав «Сохранить». Одним из популярных редакторов этого толка безусловно является CKEditor (далее, CKE). Принцип его работы, если очень грубо, в том, что пользователю в форму выводится, так сказать, отрендеренный HTML, а подспудно хранится исходный HTML-код, который отправится в значение textarea при сохранении. То есть пользователь видит жирный текст, а редактор хранит <strong>жирный текст</strong>
.
Безусловно, принцип WYSIWYG в CKE нельзя назвать абсолютным: в зависимости от стилей, применяемых на сайте, пользователь может получить не совсем то, что он видит в редакторе. Например, стили заголовков могут быть иными, отступы могут отличаться, картинки могут обрамляться рамками и т.д. Но в общих чертах принцип соблюден: жирное будет выведено жирным, курсив — курсивом, ссылка останется ссылкой, а изображение — изображением.
Но что делать, если нам нужно ввести в редактор что-то за рамками HTML. Что-то, что при выводе на страницу потребует исполнения какой-либо логики, отсутствующей в редакторе CKE и неприменимой к тексту в процессе редактирования? Вот например в Друпале есть токены, т.е. надписи в квадратных скобочках (например, [node:title]
), которые при выводе на страницу будут заменены значениями (например, заголовком материала). Очевидно, CKE лишен возможности преобразовать токены в значения при редактировании, но это и не требуется. Сама суть токенов в том, что их значения будут доступны позже, при выводе.
А что если нам нужно выводить на страницу своеобразный токен, а в самом редакторе CKE при редактировании заменять его картинкой? Зачем? Ну, например, пишет пользователь сайта статью, и хочет вставить в нее картинку. Но не простую картинку, которую можно просто загрузить при редактировании и вставить insert-ом или one click upload-ом. А такую картинку, чтобы она была материалом в пользовательском фотоальбоме и вставлялась прямо оттуда. И при просмотре отображалась так, чтоб по клику на нее в окне colorbox появлялась не только увеличенная картинка, но и ее заголовок, комментарии, линк на автора, счетчик лайков и т.п. Ну, в общем, отрендеренный материал.
При этом разумеется пользователь должен просто выбрать картинку из списка-фотоальбома, а не вручную составлять HTML нужной ссылки. То есть мы хотим чтобы пользователь щелкнул на фотку, а в сохраняемом HTML редактора появился какой-нибудь токен или специальный (лучше даже придуманный) HTML-тег. Можно так сделать в CKE? Вставить тег — да, можно, но в отрендеренном представлении редактора ничего не появится, т.к. CKE по умолчанию не умеет отображать придуманные нами теги. Вот и давайте его научим.
Пускай наш придуманный тег называется <image_insert id="123" src="/sites/default/files/image/myimage.jpg" />
, где в id
мы запишем nid вставляемого изображения, в src — путь к картинке (пригодится). А в поле редактора CKE мы хотим, чтобы вместо тега image_insert появлялось само изображение — просто чтобы не смущать пользователя какими-то тегами. Для этого в CKE есть плагин Fake Objects.
Создадим небольшой плагин для CKE:
CKEDITOR.plugins.add( 'image_insert',
{
requires : [ 'fakeobjects' ],
init: function( editor ) {
//добавляем тег image_insert в наборы элементов
var tagName = 'image_insert';
CKEDITOR.dtd.image_insert = {'#' : 1}; //в разрешенные
CKEDITOR.dtd.$empty[tagName] = 1; //в самозакрывающиеся
CKEDITOR.dtd.$block[tagName] = 1; //в блочные
CKEDITOR.dtd.$body[tagName] = 1; //в дочерние для <body>
CKEDITOR.dtd.p[tagName] = 1; //в дочерние для <p>
},
afterInit : function( editor ) {
var dataProcessor = editor.dataProcessor,
dataFilter = dataProcessor && dataProcessor.dataFilter;
if ( dataFilter ) {
//создаем правило замены тега на fake element
dataFilter.addRules(
{
elements :
{
'image_insert' : function( element )
{
//создаем fake element
var fakeElement = editor.createFakeParserElement(element, 'image_insert', 'image_insert', false);
//копируем атрибут src из оригинала (адрес картинки)
fakeElement.attributes.src = element.attributes.src;
return fakeElement;
}
}
});
}
}
});
Теперь правила созданы и осталось только правильно добавить тег. Например вот так:
function imageInsertDialogOk() {
editor = this.getParentEditor();
//вставляем в текст тег <image_insert id="nid-123" src="/sites/default/files/image/myimage.jpg" />
var element = CKEDITOR.dom.element.createFromHtml( '<image_insert id="nid-123" src="/sites/default/files/image/myimage.jpg" />' );
//создаем соответствующий fake element
var fakeElement = editor.createFakeElement(element, 'image_insert', 'img', false);
fakeElement.setAttribute('src', "/sites/default/files/image/myimage.jpg");
editor.insertElement(fakeElement);
}
Вставленный таким образом тег в редакторе автоматически преобразуется в картинку, а в HTML останется придуманным тегом, который мы сможем обработать при выводе, например, своим input filter.
Код из данной статьи проверялся в CKE версии 3.6. Для CKE 4 принцип примерно похожий.