BUEditor
С недавних пор я задумался о смене на сайте редактора текста. До этого у меня был установлен CKEditor. Службу он нёс свою исправно, но появились новые задачи. Возникла необходимость редактора с гибкой системой настройки. Такой возможности CKEditor не предоставляет. К тому же в последнее время был замечен небольшой баг связанный со вставкой пустой строки в начало текста. А также Мелочь, но не приятно. Поэтому я выбрал для своих целей модуль BUEditor.
Чем же он лучше?
- Он предоставляет редактор с гибкой системой настройки. Можно изменять как угодно кнопки. Добавлять форматирование для любых фильтров (HTML, BBCode, Wiki, и пр.)
- Лёгкая возможность встраивания сторонних возможностей. Это будет показано далее.
- Хорошая интеграция с IMCE и многое другое.
Установка
- Копируем файлы модуля в директорию где располагаются все модули, например, sites/all/modules
- Подключаем модуль на странице admin/modules
- Добавляем или редактируем фильтры на странице admin/config/content/bueditor
- Там же устанавливаем фильтры для определенных ролей
- Можно установить модуль IMCE для загрузки файлов/изображений на сервер
- Настроить форматы ввода для работы с редактором на странице admin/config/content/formats
Настройка

По-умолчанию доступны следующие кнопки:
| Insert/edit image |
|
| Insert/edit link |
|
| tpl:dot | |
| Bold | <strong>%TEXT%</strong> |
| Italic | <em>%TEXT%</em> |
| Underline | <ins>%TEXT%</ins> |
| Strikethrough | <del>%TEXT%</del> |
| tpl:dot | |
| Ordered list. Converts selected lines to a numbered list. | js: E.wrapLines('<ol>\n', ' <li>', ' </li>', '\n</ol>'); |
| Unordered list. Converts selected lines to a bulleted list. | js: E.wrapLines('<ul>\n', ' <li>', ' </li>', '\n</ul>'); |
| tpl:dot | |
| Headings |
|
| Quote | <blockquote>%TEXT%</blockquote> |
| Code | <code>%TEXT%</code> |
| tpl:dot | |
| Teaser break | <!--break--> |
| Preview | js: E.prv(); |
| Help | js: E.help('fadeIn'); |
Форматирование текста
Стандартный вариант, предложенный разработчиками модуля, меня не устроил по двум причинам. Во-первых, теги добавляются только для выделенного текста, игнорируя переносы строк. Во-вторых, при повторном нажатии кнопки не происходит снятие форматирование, а добавляется новое. Предложенный мной вариант исправляет данные ошибки.
| Старый вариант | Новый вариант | |
|---|---|---|
| Код |
|
|
| Без форматирования |
|
|
| Наложение форматирования | ||
| Снятие форматирования |
|
Вставить таблицу
Для добавления таблицы в редактор нужно использовать следующий код:
// Сообщаем об использовании javascript-кода js: // Открываем всплывающее окно с содержанием в виде таблицы E.quickPop.open('<table id="bue-table" style="width:auto;height:auto;"><tr><td></td><td></td><td></td></tr><tr><td></td><td></td><td></td></tr><tr><td></td><td></td><td></td></tr></table>'); // Устанавливаем начальные координаты для визуального эффекта TX=-1; TY=-1; // Задаем функцию TD для управления ячейкой таблицы во всплывающем окне TD=function(){ // Устанавливаем CSS-свойства для ячейки (css), её содержание (html), а также события при наведении курсора (mouseover) и щелчке мыши (click); $(this).css({width:'16px',height:'16px',border:'1px solid #ddd',padding:'5px',backgroundColor:'white',cursor:'pointer'}).html(' ').mouseover(TDOver).click(TDClick); }; // Функция TDOver для обработки события при наведении курсора на ячейку TDOver=function(){ // Получаем доступ к текущей строке var row=this.parentNode; // Получем доступ к таблице var table=row.parentNode; // Определяем положение курсора над таблицей var X=this.cellIndex; var Y=row.rowIndex; // Если курсор достиг правого края таблицы, то в каждую строку добавляем по ячейке if(X==row.cells.length-1){ for(var i=table.rows.length;i;i--) TD.apply(table.rows[i-1].insertCell(X+1)); } // Если курсор достиг нижнего края таблицы, то в добавляем строку с необходимым количеством ячеек if(Y==table.rows.length-1){ var _row=table.insertRow(Y+1); for(var i=0,t=row.cells.length;i<t;i++) TD.apply(_row.insertCell(i)); } // Устанавливаем свойства для ячейки var aX=X<TX ? [TX,X,TY,'white'] : [X,TX,Y,'blue']; var aY=Y<TY ? [TY,Y,TX,'white'] : [Y,TY,X,'blue']; // Всё что левее и выше курсора закрашиваем синим, остальное белым for(var i=aX[0];i>aX[1];i--) for(var j=aX[2];j>-1;j--){ table.rows[j].cells[i].style.backgroundColor=aX[3]; } for(var i=aY[0];i>aY[1];i--) for(var j=aY[2];j>-1;j--){ table.rows[i].cells[j].style.backgroundColor=aY[3]; } // Устанавливаем новые координаты для визуального эффекта TX=X; TY=Y; }; // Функция TDClick для обработки события при щелчке мыши на ячейку TDClick=function(){ // Устанавливаем начальные значения var cells=''; var rows=''; // В зависимости от количества выделенных столбцов, устанаваливаем количество HTML тегов TD for(var i=TX;i>-1;i--){ cells+='<td></td>'; } // В зависимости от количества выделенных строк, устанаваливаем количество HTML тегов TR for(var i=TY;i>-1;i--){ rows+='<tr>'+cells+'</tr>\n'; } // Добавляем теги для таблицы в редактор E.replaceSelection('<table>\n'+rows+'</table>\n','end'); }; // Перебираем все ячейки таблицы во всплывающем окне $('#bue-table td').each(TD);
Добавить/редактировать изображение
Для добавления (редактирования) изображения в редактор нужно использовать следующий код:
js: // Задаем начальные размеры изображения W = 0; H = 0; // Задаем функцию bopen открытия диалога выбора изображения с помощью модуля imce bopen = function(obj) { // Если диалог возможен E.imce && E.imce.url && E.imce.open({ // Задаем текущий объект. Передаем его через параметр функции. target: obj, // Режим диалога стандартный ready: E.imce.readyDefault, // Обработчик выбора изображения меняем на наш sendto: function(file, win, pop) { // Получаем объект input кнопки и все другие поля var target = E.imce.target, el = target.form.elements // Устанавливаем значение в поле URL target.value = file.url; // Устанавливаем значение в поле Ширина el['attr_width'].value = file.width; // Устанавливаем значение в поле Высота el['attr_height'].value = file.height; // Устанавливаем значение в поле Описание el['attr_alt'].value = file.name; // Задаем обработчик смены значения в поле Ширина el['attr_width'].onchange = function(){ // Если было выбрано изображение if (H > 0) { // Сохраняем новое значение var _W = parseInt(this.value); // Изменяем высоту H = parseInt(H * (_W / W)); // Устанавливаем значение в поле Высота el['attr_height'].value = H.toString(); // Заменяем старое значение новым W = _W; } }; // Задаем обработчик смены значения в поле Высота el['attr_height'].onchange = function(){ // Если было выбрано изображение if (W > 0) { // Сохраняем новое значение var _H = parseInt(this.value); // Изменяем ширину W = parseInt(W * (_H / H)); // Устанавливаем значение в поле Ширина el['attr_width'].value = W.toString(); // Заменяем старое значение новым H = _H; } }; // Сохраняем ширину изображения W = file.width; // Сохраняем высоту изображения H = file.height; // Закрываем диалоговое окно pop.close(); // Устанавливаем фокус ввода для поля URL target.focus(); } }); } // Задаем функцию b для отображения кнопки открытия диалога выбора изображения с помощью модуля imce b = function() { // Если модуль imce установлен, то отображаем кнопку return E.imce.url ? '<input type="button" id="bue-imce-button" name="bue_imce_button" class="form-submit" value="'+ Drupal.t('Browse') +'" onclick="bopen(this.form.elements[\'attr_src\'])">' : ''; }; // Задаем поля формы для добавления/редактирования изображения var form = [ {name: 'src', title: 'URL', required: true, suffix: b()}, {name: 'width', title: 'Ширина x Высота', suffix: ' x ', getnext: true, attributes: {size: 3}}, {name: 'height', attributes: {size: 3}}, // Добавляем поле Выравнивание {name: 'align', title: 'Выравнивание', type: 'select', options: {'': '', left: 'По левому краю', right: 'По правому краю', center: 'По центру'}}, {name: 'alt', title: 'Описание', required: true} ]; // Вызываем диалоговое окно формы для добавления/редактирования изображения E.tagDialog('img', form, {title: 'Добавить/редактировать изображение'});
Добавить формулу
Для использования данного функционала нам потребуется библиотека MathJax. Её можно скачать, а лучше просто добавить следующий javascript код:
var script = document.createElement("script"); script.type = "text/javascript"; script.src = "https://d3eoax9i5htok0.cloudfront.net/mathjax/1.1-latest/MathJax.js?config=TeX-AMS-MML_HTMLorMML-full"; var config = 'MathJax.Hub.Startup.onload();'; if (window.opera) {script.innerHTML = config} else {script.text = config} document.getElementsByTagName("head")[0].appendChild(script);
Сделать это можно с помощью drupal_add_js в файле template.php:
<?php /** * template_preprocess_page */ function MYTHEME_preprocess_page(&$variables) { drupal_add_js('jQuery(document).ready(function () {'+ 'var script = document.createElement("script");script.type = "text/javascript";'+ 'script.src = "https://d3eoax9i5htok0.cloudfront.net/mathjax/1.1-latest/MathJax.js?config=TeX-AMS-MML_HTMLorMML-full";'+ 'var config = "MathJax.Hub.Startup.onload();";'+ 'if (window.opera) {script.innerHTML = config} else {script.text = config}'+ 'document.getElementsByTagName("head")[0].appendChild(script); });', 'inline'); } ?>
Пример работы библиотеки:
\[J_\alpha(x) = \sum_{m=0}^\infty \frac{(-1)^m}{m! \, \Gamma(m + \alpha + 1)}{\left({\frac{x}{2}}\right)}^{2 m + \alpha}\]
Добавляем кнопку \[%TEXT%\].
Предварительный просмотр
В завершении изменим предварительный просмотр. Сделаем его с помощью модуля Ajax markup. Для этого нам нужно установить данный модуль и изменить обработчик кнопки на js: E.prvAjax();
Автоматическое форматирование новой строки
Для удобства набора и форматирования текста, в редакторе Lab есть экспериментальная функция Auto LI. Я её немного усовершенствовал и теперь она может при переносе строки добавлять не только теги LI, но и другие, например, тег P. Теги для добавления задаются в коде.
Работает это следующим образом. Допустим, у нас имеется список и теперь при переносе строки на новой добавляются теги <li></li> и устанавливается курсор между ними. Тоже самое относится и к тегу P. Система автоматически определяет каким тегом заканчивалась предыдущая строка и в зависимости от полученной информации добавляет форматирование новой строки.
А теперь по-порядку...
Создаем новый файл bue.wrap.js следующего содержания:
BUE.preprocess.wrap = function(E, $) { E.wrap=['li','p']; $(E.textArea).bind('keyup.bue', function(e) { if (!e.ctrlKey && !e.shiftKey && !e.originalEvent.altKey && e.keyCode == 13) { var prefix = E.getContent().substr(0, E.posSelection().start); for(var i in E.wrap){ var re=new RegExp('<\\/'+E.wrap[i]+'>\\s*$','i'); if(re.test(prefix)) E.tagSelection('<'+E.wrap[i]+'>', '</'+E.wrap[i]+'>'); } } }); };
и помещаем его в папку library модуля bueditor.
В завершении добавляем нашу библиотеку в настройках редактора, во вкладке Editor Paths:
Сноски
Для добавления на сайт сносок воспользуемся модулем footnotes. Нужно его загрузить, установить и включить в форматах ввода.
Чтобы добавить сноску, нужно добавить тег fn. С помощью атрибута value можно указать символ отображения сноски. Значением тега должен текст сноски. Например, <fn value="1">Сноска</fn>
В завершении добавим кнопку для нашего редактора <fn>%TEXT%</fn>
Пример: 1
Данный материал находится в процессе разработки...
- 1. Сноска
Комментировать