Руководство по tinymce

TinyMCE AdvancedПредыдущая статья была посвящена расширению и настройке визуального редактора в WordPress. Сегодня я расскажу, как работать в визуальном редакторе TinyMCE. Данная статья будет полезна не только обладателям WordPress блогов, но и всем, у кого есть сайты.

Мы подробно рассмотрим все функции, которыми обладает визуальный редактор и научимся пользоваться ими. Однако, я не буду подробно останавливаться на кнопках, назначение которых очевидно. Наиболее не понятные, на мой взгляд, инструменты, рассмотрим более детально.

Общий вид визуального редактора TinyMCE

Для удобства я приведу скриншот панели инструментов из настройки плагина TinyMCE Advanced в параметрах WordPress. На скриншоте пронумерована каждая кнопка. Вы можете найти интересующий вас инструмент по его номеру в списке ниже.

WYSIWYG общий вид

Описание функций визуального редактора TinyMCE

Блок «Шрифт»

1. Полужирный (Bold)
2. Наклонный (Italic)
3. Зачёркнутый (Strikethrough)
4. Подчёркнутый (Underline)

Блок «Списки»

5. Маркированный список (Unordered list)
6. Нумерованный список (Ordered list)

Блок «Отступ»

7. Сдвинуть влево (Outdent)
Позволяет сдвинуть часть текста влево на 30 пикселей по отношению к остальному тексту.

8. Сдвинуть вправо (Indent)

Блок «Выравнивание текста»

9. По левому краю (Align left)
10. По центру (Align center)
11. По правому краю (Align right)
12. По ширине (Align full)

Блок «Управление объектами и кодом»

13. Вставить ссылку (Insert/edit link)
Необходимо выделить фрагмент текста или изображение, с которого будет вести ссылка. Во всплывающем окне можно задать некоторые настройки:

  • URL (Адрес ссылки) — введите полный адрес ссылки (<a href=»адрес ссылки»>текст ссылки</a>). Если ссылка внутренняя, начине со слэша: /first_page/
  • Для использования якорей, введите в URL решетку+название якоря (#bottom). Подробнее про якоря описано в статье про создание оглавления.
  • Открывать ссылку в новом окне (Target)

14. Удалить ссылку (Remove link)

15. Вставить изображение (Insert/edit image)
Для вставки изображения в WordPress нужно использовать кнопку «Добавить медиафайл», расположенную над визуальным редактором слева. Однако кнопку №15 удобно использовать для настройки изображения. На вкладке «Положение» можно задать отступы, выравнивание и размеры картинки.
редактирование изображения wordpress

16. Вычистить грязный код (Cleanup messy code)
Код автоматически корректируется, удаляются ошибочные и ненужные теги.

17. Редактировать код HTML (Edit HTML Source)
Редактировать код приходится довольно часто, т.к. визуальный редактор не всегда выполняет команды так, как вы хотите.

18. Редактор css стиля (Style)
Дает возможность редактировать стиль шрифта путем изменения различных его параметров.
стиль css

19. Вставить тег «далее» (More tag)
Очень нужный инструмент, позволяет выделить аннотацию статьи (краткое описание, которое отображается на странице списка постов).
Нажатием данной кнопки вставляется тег <!—more—> и все, что расположено до этого тега, попадет в аннотацию.
После слова more в теге можно дописать фразу, которая будет являться ссылкой на полный текст статьи: <!—more Читать  далее…—>
Следите, чтобы все теги, расположенные до тега More были закрыты.

20. Вставить разрыв страницы (Split page)
Позволяет разделить очень длинную статью на несколько страниц. В код вставится тег <!—nextpage—> и после него на сайте появится пагинация и кнопка «следующая страница».

21. Проверка правописания (Check Spelling)

22. Найти (Search)
Стандартные поиск и замена в вордпресс зачастую работают криво. Поэтому лучше не использовать эту кнопку, а вызывать поиск браузера нажатием клавиш ctrl+F (перед уберите указатель мыши с редактируемого текста, щелкнув на серую по бокам)

23. Заменить (Replace)
Используется, чтобы находить и заменять нужные фразы в тексте.

24. Полноэкранный режим (Full Screen)
Редактирование статьи разворачивается на весь экран, при этом панель визуального редактора практически исчезает, поэтому данный режим не удобен.

25. Вставить горизонтальный разделитель (Horizontal rule)
Добавляет в текст горизонтальную линию (тег <hr />)

Блок «Стиль абзаца»

26. Стиль оформления текста
Из CSS-файла tinymce подгружается список стилей, которые можно использовать для оформления статьи.

27. Стиль оформления абзаца
Дает возможность выбрать формат абзаца из следующих:

Параметр (англ) Параметр (рус) HTML тег
Paragraph Абзац <p></p>
Address Стиль адреса <address></address>
Preformatted Преформатированный <pre></pre>
Header 1 Заголовок 1го уровня <h1></h1>
Header 2 Заголовок 2го уровня <h2></h2>
Header 3 Заголовок 3го уровня <h3></h3>
Header 4 Заголовок 4го уровня <h4></h4>
Header 5 Заголовок 5го уровня <h5></h5>
Header 6 Заголовок 6го уровня <h6></h6>

Все эти форматы важны не только для визуального оформления, но и для SEO-продвижения.

28. Тип шрифта (семейство или название шрифта)

29. Размер шрифта

30. Убрать форматирование (Remove Format)
Очищает текст от тегов форматирования

31. Вставить произвольный символ(Chapter Map)
Вставляет в текст код выбранного символа.

32. Печать (Print)
Выводит статью на печать.

33. Выбрать цвет текста (Text color)
Предлагается выбрать цвета из предложенных. При нажатии «другие цвета» открывается палитра. Не забудьте предварительно выделить текст, которому задаете цвет.

34. Цвет фона (Back color)

35. Эмоции (Smiles)
Используется для вставки в статью смайликов.

36. Верхний индекс (Sup)
Заключает выделенное слово в тег <sup>.

37. Нижний индекс (Sub)
Заключает выделенное слово в тег <sub>.

38. Вставить/редактировать медиафайл (Insert Movie)
Позволяет вставить в статью видео в один клик. Нужно вставить ссылку на видео (например, из ютуба) и указать размер окна, которое появится в статье.

39. Отменить (Undo)
40. Повторить (Redo)
41. Помощь (Help)

42. Цитата (Quote)
Заключает абзац в тег <blockquote>. Если в стилевом файле вашей темы прописаны правила для данного тега, то текст получит соответствующее оформление. Подробнее про оформление цитат смотрите по ссылке.

43. Цитата (Citation)
Обрамляет выделенный текст тегом <cite>. Обычно используется для оформления сноски на другой материал. Текст внутри тега отображается курсивом или подчеркивается пунктиром.

Блок  «Таблицы»

44. Вставить новую таблицу (Insert a new table)
Кнопка дает возможность добавить новую таблицу или отредактировать имеющуюся. Здесь можно задать отступы, размеры, выравнивание и т.д.
параметры таблицы

45. Свойства строки (Table row properties)
Если выделить нужную стоку таблицы, станет активной данная кнопка, которая позволяет настроить отображение строк таблицы.
параметры строки

46. Свойства ячейки (Table cell properties)
Аналогично свойствам строки.

47. Вставить строку перед текущей (Insert row before)
48. Вставить строку после текущей (Insert row after)
49. Удалить текущую строку (Delete row)
50. Вставить столбец перед текущим (Insert column before)
51. Вставить столбец после текущего (Insert column after)
52. Удалить столбец (Delete column)
53. Разделить ячейки (Split table cells)
54. Объединить ячейки (Merge table cells)

55. Показать/скрыть дополнительную панель (Hide next row)
Дополнительной панелью считается последняя четвертая строка.

56. Вставить/редактировать аттрибуты (XHTML Attribs)
С помощью данной функции можно добавлять следующие атрибуты к html-тегам(сверху вниз): title, id, class, style, dir, lang, tabindex, accesskey. Атрибут добавится к ближайшему тегу той части текст, на которой стоит курсор.

Блок «Управление фрагментами»

57. Вырезать (Cut)
58. Копировать (Copy)
59. Вставить (Paste)

60. Вставить как текст (Paste as Plain Text)
Текст, находящийся в буфере обмена, сначала полностью очищается от форматирования, затем вставляется в редактор. Это удобно, если вы копируете из ворда, но не хотите сохранять форматирование. Можно отметить галочку «Сохранять разрывы строк», тогда переносы будут оформлены в виде абзацев.

61. Вставить из Word (Paste from Word)
При копировании материалов из ворда удобно использовать этот режим. Он очищает данные от лишнего форматирования, т.е. код получается чистым.

62. Вставка (Inserted Text)
Помещает текст в тег <ins>, который отображается подчеркнутым и показывает, что данный текст был добавлен в новую версию статьи.

63. Удаление (Deleted Text)
Обрамляет текст тегом <del>, который отображается в браузере зачеркнутым. Помогает отслеживать, какие изменения сделаны в новой версии статьи.

64. Аббревиатура (Abbreviation)
Обрамляет выделенный текст тегом <abbr>, который показывает, что текст является аббревиатурой. В поле «Заголовок» указывается расшифровка аббревиатуры, этот заголовок будет всплывающей подсказкой, при наведении на текст аббревиатуры.

65. Вставить дату (Insert Date)
Позволяет вставить текущую дату.

66. Вставить время (Insert Time)

67. Ориентиры/невидимые символы (Visual Aids)

68. Вставить/редактировать якорь (Anchor)
Вставляет на страницу якорь (тег <a name=»имя_якоря»></a>), в открывшемся окне необходимо указать название якоря (параметр name). Для того, чтобы создать ссылку на данный якорь, необходимо при редактировании ссылки (ссылка) в поле url указать #имя_якоря.

69. (IE Spell)

70. Горизонтальный разделитель (Advanced HR)
Вставляет в текст горизонтальную линию (тег <hr />). В отличие от номера 25 позволяет настроить ширину, высоту линии и наличие тени.

71. Сокращение (Ancronym)

Обрамляет выделенный текст тегом <acronym>, который показывает, что текст является акронимом. Отличие от аббревиатуры в том, что акроним – это устоявшееся сокращение (например, США, СПИД). Аналогично, в поле «заголовок» указывается расшифровка – всплывающая подсказка.

Блок «Слои»

72. Вставить новый слой
Вставляет в код тег <div> с абсолютным позиционированием, внутри которого находится текст.

73. Переместить вперед
Задает тегу <div> параметр z-index, который позволяет размещать слой поверх или за текстом.

74. Переместить назад

75. Включить выключить абсолютное позиционирование

76. Включить/выключить символы визуального контроля (Hidden Chars)
Включает/выключает отображение невидимых символов. Данная функция довольно убога по сравнению с вордом, поэтому используется редко.

77. Вставить символ неразрывного пробела (NB Space)
Эта кнопка вставляет символ пробела (&nbsp;). В принципе в визуальном редакторе такую же роль выполняет кнопка пробела на клавиатуре.

Получилось что-то вроде справочника по TinyMCE с описанием назначения каждой кнопки. Возвращайтесь к этой статье всегда, когда хотите посмотреть, что делает та или иная кнопка. А так же, если хотите добиться какого-то эффекта в оформлении статьи, но не знаете как.

Не забывайте подписываться на RSS, чтобы не пропустить новую важную информацию!

Как вы уже поняли, редактор является платформенным Javascript редактором HTML кода, т.е. WYSIWYG редактором для сайтов и веб приложений. Разработчиком этого полезного продукта является компания Moxiecode Systems AB.

Знакомство с великим и могучим текстовым редактором на JS

Как вы уже поняли, редактор является платформенным Javascript редактором HTML кода, т.е. WYSIWYG редактором для сайтов и веб приложений. Разработчиком этого полезного продукта является компания Moxiecode Systems AB. К ключевым особенностям программы относятся: поддержка тем\шаблонов, языковая поддержка и возможность подключения плагинов. HTML редактор TinyMCE используется во многих системах управления и движках сайтов, в том числе и в системе управления BIT company CMS v 1.01. Мы можем отметить программу как отличный и широкофункциональный инструмент для редактирования HTML кода, вставки видео, текстово-графической информации, таблиц и графиков. Правда так же отметим и скудность русскоязычной информации о методах и свойствах JS редактора TinyMCE( но вам повезло! Здесь вы найдете ответы на базовые вопросы и научитесь работать с редактором TinyMCE).

Как видно из титульного изображения выше, JS редактор очень похож на текстовый редактор в офисных приложения — принцип работы у редактора TinyMCE аналогичный. Для пользователей не знакомых с возможностями html и css есть графический интерфейс редактора. Для пользователей которые владеют языком программирования html и css есть так же расширенный редактор HTML. Данный редактор позволяет решить практически любые задачи, связанные с оформление страниц.

Инструкция полностью применима для редактора версии 3.5.11. Для более поздних версий методология работы с редактором так же должна быть аналогичной.

Установка и настройка TinyMCE

1. Скачиваем свежую версию редактора здесь и распаковываем.

2. Копируем содержимое архива в нужную вам директорию сайта.

3. Подключаем редактор к нашему сайту путем вставки кода на нужную страницу:

<script type="text/javascript" src="/path/to/tiny_mce.js"></script>

4. Инициализируем редактор при помощи JavaScript кода:

<!-- TinyMCE -->
<script type="text/javascript">
tinyMCE.init({
    mode : "textareas",
    theme : "simple"
 });
</script>
<!-- /TinyMCE -->
<textarea></textarea>

5. Готово! Теперь вы вставили и инициализировали простейший TinyMCE редактор.

Как вы заметили подключение и инициализация JS редактора проходит в 3 логических шага:

  • подключение библиотеки к странице сайта
  • инициализация объекта
  • вставка тега textarea, который и становится графическим html редактором.

Инициализация редактора и его параметры

Редактор TinyMCE возможно инициализировать с различными параметрами, темами, плагинами. В данном разделе мы рассмотрим некоторые параметры и их значения. Вот пример инициализации редактора в системе управления BIT company CMS V 1.01:

<!-- TinyMCE -->
<script type="text/javascript">
    tinyMCE.init({
        // General options
        mode : "exact",
        elements: "content_editor",
        theme : "advanced",
        language:"ru",
        plugins : "autolink,lists,spellchecker,pagebreak,style,layer,table,save,advhr,advimage,advlink,emotions,iespell,inlinepopups,insertdatetime,preview,media,searchreplace,print,contextmenu,paste,directionality,fullscreen,noneditable,visualchars,nonbreaking,xhtmlxtras,template,precode,uploads_image",
    
        // Theme options
        theme_advanced_buttons1 : "save,newdocument,|,bold,italic,underline,strikethrough,|,justifyleft,justifycenter,justifyright,justifyfull,|,styleselect,formatselect,fontselect,fontsizeselect",
        theme_advanced_buttons2 : "cut,copy,paste,pastetext,pasteword,|,search,replace,|,bullist,numlist,|,outdent,indent,blockquote,|,undo,redo,|,link,unlink,preCode,anchor,image,uploads_image,cleanup,help,code,|,insertdate,inserttime,preview,|,forecolor,backcolor",
        theme_advanced_buttons3 : "tablecontrols,|,hr,removeformat,visualaid,|,sub,sup,|,charmap,emotions,iespell,media,advhr,|,print,|,ltr,rtl,|,fullscreen",
        theme_advanced_buttons4 : "insertlayer,moveforward,movebackward,absolute,|,styleprops,spellchecker,|,cite,abbr,acronym,del,ins,attribs,|,visualchars,nonbreaking,template,blockquote,pagebreak,|,insertfile,insertimage",
        theme_advanced_toolbar_location : "top",
        theme_advanced_toolbar_align : "left",
        theme_advanced_statusbar_location : "bottom",
        theme_advanced_resizing : true,

        // Skin options
        skin : "o2k7",
        skin_variant : "silver",

        // Drop lists for link/image/media/template dialogs
        template_external_list_url : "js/template_list.js",
        external_link_list_url : "js/link_list.js",
        external_image_list_url : "js/image_list.js",
        media_external_list_url : "js/media_list.js",

        // Replace values for the template plugin
        template_replace_values : {  username : "Some User",  staffid : "991234"  }
    });
    </script>
<!-- /TinyMCE -->

mode [textareas|exact|specific_textareas|none] — определяет какие html экхемляры будут преобразованы в графические редакторы TinyMCE.

  • textareas — преобразовывает все теги <textarea> к виду редактора
  • specific_textareas — преобразуются только элементы имеющие, указанный в параметре editor_selector селектор или не имеющие селектор, указанный в editor_deselector
<script type="text/javascript">
        tinyMCE.init ({
            mode : "specific_textareas",
            editor_selector : "editme",
            language:"ru",
            theme : "simple"
        });
    </script>
<textarea id="content" class="editme" name="content"></textarea>
  • exact — преобразуются только элементы, идентификаторы которых перечислены в параметре elements(пример из BIT company CMS).
  • none — элементы не преобразуются

theme [simple|advanced] — определяет режим инициализации редактора.

  • simple — режим, включающий базовые функции и запрещающий гибкую настройку
  • advanced — режим, позволяющий гибкую настройку плагинов, кнопок редактора, темы редактора и т.д.

language — указывает код языкового пакета графического редактора TinyMCE.

plugins — список плагинов, инициализируемых вместе с редактором, разделенные запятыми.

theme_advanced_buttons<1-n> — содержит список элементов управления для вставки в панели инструментов, где <1-n> строка в панели инструментов.

theme_advanced_toolbar_location — указывает, где должны располагаться панели инструментов: top — сверху, bottom — снизу.

theme_advanced_toolbar_align — позволяет задать выравнивание панели инструментов: по левому краю, по правому и по центру.

theme_advanced_statusbar_location — задает положение статусбара (top — вверху, bottom — внизу), либо указывает на его отсуствие — none.

theme_advanced_resizing — включает — true или выключает — false возможность изменять размеры окна редактора. Не работает, если значение theme_advanced_statusbar_location установлено в none.

skin — указывает какой скин данной темы необходимо использовать.

skin_variant — указывает какой вариант скина необходимо использовать.

content_css — подключает пользовательский css-файл(либо набор файлов, перечисленных через запятую), который будет использоваться в редакторе.

relative_urls — устанавливает, будут ли ссылки в редакторе относительные (true) или абсолютные (false).

template_replace_values — преобразование элемента страницы в графический редактор html кода с параметрами.

template_replace_values : { username : "Some User", staffid : "991234" }

Вот мы и подытожим с вопросом подключения и инициализации графического редактора html кода TinyMCE для сайта. Всем спасибо!

TinyMCE Documentation

This project maintains the documentation for TinyMCE at
https://www.tiny.cloud/docs-4x/. If you have any
modifications you wish to contribute, fork this project, make the changes
and submit a pull request. You will need to sign the contributors license
agreement, which will be emailed to you upon creating the pull request.

This project is built using Jekyll.

Contributing to the TinyMCE Documentation

If you would like to contribute to the TinyMCE project please read the TinyMCE Documentation Contributor’s Guide at either:

  • TinyMCE Documentation — Contributor’s Guide.
  • GitHub — Contributing to the TinyMCE developer documentation.

Working on TinyMCE documentation

Compiling or building the documentation

The following procedure assists with building (or compiling) the documentation locally. Tiny recommends testing and reviewing changes locally prior to submitting a pull request.

Installing Prerequisites

Linux users

You need the following programs installed on your computer:

  • Ruby version 2 or later. To verify the installed version, run:
  1. Install git, g++, make, and the zlib development files. For example:

    • On Fedora, run:

      sudo dnf install git-all gcc-c++ make zlib-devel
      
    • On Ubuntu, Debian or their derivatives, run:

      sudo apt install git gcc cpp make zlib1g-dev
      
  2. Install Ruby Nokogiri: https://nokogiri.org/

    sudo gem install nokogiri
    
  3. Install Ruby Bundler. Install using:

  4. (optional) Docker

Windows users

If you are a Windows user, follow these steps to work on TinyMCE documentation:

  1. Install git for Windows.

  2. Install Ruby+Devkit.

  3. Run the following command on a command prompt to install Ruby Bundler:

Mac OS users
  1. Ruby version 2 or later is required. Verify the pre-installed version, using:

  2. Install Ruby Bundler, using:

First time set up

Once you have installed any missing prerequisites, in a terminal or on a command prompt:

  1. Clone the git repository:

    git clone git@github.com:tinymce/tinymce-docs.git
    
  2. Change directory into the cloned git repository:

  3. Run the initialization script to install dependencies and create the required local files in the git repository:

Run the development version of the documentation

To create a development version of the documentation, run:

Allow the serve.sh script to run in the background while you are working on the TinyMCE documentation.

To view the documentation; in a web browser, navigate to http://localhost:4000/.

Note: The development version of the documentation will update automatically when you save changes locally.

TinyMCE API documentation

The TinyMCE API documentation is maintained within the TinyMCE project repository and compiled for the documentation site using MoxieDoc.

Prerequisites
  • NodeJS.
  • The TinyMCE documentation repository set up for development as described in Installing Prerequisites and First time set up.
Installing MoxieDoc

To install MoxieDoc, run:

npm install -g git://github.com/tinymce/moxiedoc.git
Run the development version of the documentation for the current TinyMCE version
  1. Download the TinyMCE version in the .api-version file in this project’s root directory and extract the API documentation using:
    ./_scripts/api-reference.sh
  1. Start the development server using:
Run the development version of the documentation for a local TinyMCE repository
  1. Extract the API documentation from a local copy of the TinyMCE repository using:
    ./_scripts/api-reference-local.sh <path/to/the/tinymce/repo>
  1. Start the development server using:
  1. To include updates made to the TinyMCE API documentation in the TinyMCE repository, run the api-reference-local script:
    ./_scripts/api-reference-local.sh <path/to/the/tinymce/repo>

Note: The development server does not need to be stopped prior to running the api-reference-local script.

  1. Главная
  2. Блоги
  3. Блог Макс К.

Главные вкладки

  • Просмотр(активная вкладка)
  • Реакции

Аватар пользователя Макс К.


26 октября 2007 в 13:00


Кнопки редактора TinyMCE

Часто на Drupal сайты ставят визуальный html-редактор TinyMCE.

Этот редактор поддерживает до 80 Word-подобных кнопок и у него гораздо более широкие возможности для html-редактирования, чем у Word.

Я написал инструкцию для пользователей по использованию кнопочек редактора и работе с иллюстрациями.

Оглавление инструкции по TinyMCE

  • Типовые кнопки (Жирный текст, Сдвиг абзаца влево, Сдвиг абзаца вправо, Маркированный список, Нумерованный список, Отмена предыдущего действия, Возврат отмененного действия).
  • Простановка и изменение ссылки
  • Удаление ссылки
  • Вставка картинки с другого сайта
  • Подготовка и поиск картинок
  • Надежное размещение картинок
  • Копирайты картинок
  • Спецсимволы
  • Вставка текста из редактора Word
  • Линия раздела
  • Проверка орфографии на лету
  • Типографика

Ссылки:

  • Прочитать полный текст инструкции
  • Перепробовать все кнопочки
  • Установить модуль TinyMCE

Время на прочтение
11 мин

Количество просмотров 57K

Здравствуйте, меня зовут Константин, я работаю front-end-разработчиком на информационно-развлекательном портале, основную долю контента которого составляют новости и статьи. И, конечно же, нам было крайне важно организовать удобную работу с порталом для наших редакторов. О том, каких успехов мы добились на данном поприще, и будет эта статья.

У себя на портале для редактирования новостей и статей мы используем WYSIWYG-редактор TinyMCE версии 4.2.4. Он показал себя с наилучшей стороны среди всех WYSIWYG-редакторов как по стабильности работы, так и по качеству формируемой HTML-разметки. К тому же он оказался наиболее простым в освоении для людей, привыкших работать с офисными приложениями.

Но одних его базовых возможностей не хватает для того, чтобы реализовать все потребности редакции. Я не стану описывать процесс конфигурирования TinyMCE: во-первых, нужды у всех разные, а во-вторых, этот момент очень хорошо освещен в документации. Зато я расскажу о решениях, которые для многих могут оказаться полезными и которые не так просто найти в интернете.

А пойдет сегодня речь о:

  • работе с изображениями;
  • форматировании HTML-разметки при вставке текста из внешних источников;
  • типографике.

Работа с изображениями

В последнее время количество иллюстраций в наших статьях заметно возросло. И потому одной из важнейших задач для нас стала реализация простого и удобного механизма работы с изображениями.

Вот важнейшие моменты, которые мы для себя определили:

  • простая загрузка изображений;
  • простая вставка изображений в текст;
  • ресайз изображений до размеров, заданных в тексте;
  • простое создание ссылки на увеличенное изображение.

В интернете есть немало плагинов к TinyMCE для работы с графикой (в том числе и его родной, платный плагин MoxieManager), которые имитируют файловые менеджеры. Однако, как показала практика, все эти богатые возможности «а-ля» проводник Windows редакторам совсем не нужны. И потому мы решили отказаться от данной концепции и максимально упростить загрузку иллюстраций и добавление их в статью.

Для этого мы расположили под окном TinyMCE дополнительную панель конкретно для работы с изображениями. Мы решили, что когда кто-либо правит определенный текст, он должен видеть лишь те изображения, которые непосредственно относятся к этой статье. Их будет не так много, и каталогизировать изображения не придется. Также, на всякий случай, мы добавили в панель и вторую вкладку — для работы с глобальными иллюстрациями, которые могут быть доступны во всех статьях (но ей до сих пор не воспользовались).

Для загрузки изображений мы использовали плагин Dropzone.js. Он обладает следующими особенностями:

  • поддержка Drag’n’Drop;
  • мультизагрузка через Ajax;
  • простая кастомизация;
  • и никаких зависимостей — только ванильный JS.

Его конфигурация, также как и конфигурация TinyMCE, хорошо описана в документации. Я уверен — вы с легкостью сможете заточить его работу под себя, и поэтому не буду заострять на нем внимание. Вы так же можете использовать любой другой подобный плагин, благо их сейчас достаточно много.

Благодаря такому подходу мы получили возможность хранить изображения на сервере так, как нам вздумается, и упростили процесс их загрузки. Но нашей конечной целью является все-таки добавление изображений в текст статьи.

Итак, мы имеем некую панель, на которой отображается список всех доступных для статьи изображений, и нам необходимо, чтобы при клике по этим изображениям они вставлялись в текст. Этого нам поможет добиться функция редактора TinyMCE execCommand:

tinymce.activeEditor.execCommand('mceInsertContent', false, img);

Но это далеко не все — тут как раз начинается самая интересная часть. Действуя подобным образом, мы получаем богатые возможности по контролю над добавляемыми элементами.

К примеру, у нас на портале строго ограничена ширина контентной области, отведенной под статью. И если загруженное изображение намного шире — оно будет уменьшено до необходимых размеров и вставлено вместе с ссылкой на оригинал. При этом достаточно большие изображения у нас вставляются в обертке, которая растягивается на всю ширину статьи и заливается по краям средним цветом с помощью jQuery-плагина.

Определение соответствующего поведения происходит на стадии добавления иллюстрации в текст. Но как же быть, если пользователи будут редактировать изображения стандартными средствами управления TinyMCE? Чтобы не потерять контроль над элементами, добавим обработчик события NodeChange для редактора (мы делаем это в момент конфигурирования TinyMCE):

tinymce.init({ 
    /* Конфигурация редактора */

    setup: function (editor) {
        editor.on('NodeChange', function (e) { 
            if (e.element.nodeName === 'IMG' && e.element.classList.contains('mce-object') === false) {
                /* Ваш код */ 
            }
        }); 
    } 
}); 

Так как различные встраиваемые элементы (iframe, embedded) в TinyMCE заменяются изображением-заглушкой, проводим дополнительную проверку на отсутствие класса mce-object, чтобы отличить их от обычных иллюстраций.

Отловив событие изменения элемента и определив, что этот элемент является изображением, мы возвращаем себе контроль над ним. Мы можем проверить, не вышли ли его размеры (установленные размеры будут переданы в объекте события: e.width, e.height) за допустимые пределы, не нарушены ли пропорции (и такое бывало) и т.д… Рекомендую сохранять оригинальные размеры изображений в data-* атрибутах элементов.

Вы можете возразить, сказав, что для отлова ресайза изображений в редакторе достаточно использовать события ObjectResizeStart и ObjectResized. Однако данные события не сработают, если размеры иллюстрации будут изменены с помощью инструмента вставки/редактирования изображения.

Еще одна хитрость — чтобы не дать изображению растягиваться больше заданных пределов (это могут быть как ограничения контентной области, так и максимальные размеры самого изображения), задайте для него свойства max-width и max-height в атрибуте style при вставке.

Таким образом мы решили несколько пунктов нашей первоначальной задачи, но нас все еще волнует ресайз изображений до размеров, заданных в статье на стороне сервера, чтобы посетителям портала не пришлось загружать большие (тяжелые) иллюстрации, которые бы лишь визуально уменьшались.

Данная проблема решается довольно просто, если для редактирования текста вы используете bb-коды — вы просто выполняете ресайз изображений в момент обработки команды вставки их в текст. В случае с WYSIWYG-редакторами у вас есть два варианта: парсить сформированный HTML или же использовать специальные ссылки. Мы выбрали второй.

Независимо от того, на чем написан ваш бэкенд, вы сможете сделать так, чтобы по определенным параметрам в ссылке формировалось подходящее изображение и помещалось в кэш. При вставке элемента в редактор сгенерировать соответствующую ссылку достаточно просто, а в момент редактирования изображения нам на помощь вновь придёт обработчик события NodeChange. Главное помнить, что при изменении атрибута src элемента необходимо будет поменять еще и атрибут data-mce-src.

Вот такой обработчик используется у нас (для работы с DOM здесь применяется jQuery):

resizeImage = function ($image, width, height) {
    var originalWidth = parseInt($image.data('originalWidth'), 10),
        originalHeight = parseInt($image.data('originalHeight'), 10),
        ratio,
        defaultWidth,
        defaultHeight,
        link = $image.attr('src'),
        linkParams;

    if (typeof width === 'undefined' || width === null) {
        width = parseInt($image.attr('width'), 10);
    }

    if (typeof height === 'undefined' || height === null) {
        height = parseInt($image.attr('height'), 10);
    }

    defaultWidth = width;
    defaultHeight = height;

    /* Для старых изображений, без сохраненных оригинальных размеров */
    if (isNaN(originalWidth) || originalWidth === 0 || isNaN(originalHeight) || originalHeight === 0) {
        $image
            .attr({
                width: '',
                height: ''
            })
            .css({
                maxWidth: 'none',
                maxHeight: 'none'
            });

        originalWidth = $image.width();
        originalHeight = $image.height();

        ratio = originalWidth / originalHeight;

        var maxWidth = Math.min(originalWidth, pageWidth),
            maxHeight = (maxWidth === originalWidth ? originalHeight : Math.round(maxWidth / ratio));

        $image
            .attr({
                width: width,
                height: height,
                'data-original-width': originalWidth,
                'data-original-height': originalHeight
            })
            .css({
                maxWidth: maxWidth,
                maxHeight: maxHeight
            });
    } else {
        ratio = originalWidth / originalHeight;
    }

    width = Math.min(originalWidth, pageWidth, width);
    height = (width === originalWidth ? originalHeight : Math.round(width / ratio));

    if (link.substr(0, 7) === 'http://') {
        linkParams = link.substr(7).split('/');
    } else {
        linkParams = link.split('/');
    }

    /* Проверка соответсвия ссылки определенной структуре, и обновление ее */
    if (linkParams.length === 6 && linkParams[0] === window.location.host && (linkParams[1] === 'r' || linkParams[1] === 'c') &&
        isDecimal(linkParams[2]) && isDecimal(linkParams[3])) {
        link = 'http://' + linkParams[0] + '/' + linkParams[1] + '/' + width + '/' + height + '/' + linkParams[4] + '/' + linkParams[5];
        $image.attr({
            src: link,
            'data-mce-src': link
        });
    }

    if (width !== defaultWidth || height !== defaultHeight) {
        $image.attr({
            width: width,
            height: height
        });
    }
}

tinymce.init({ 
    /* Конфигурация редактора */

    setup: function (editor) {
        editor.on('NodeChange', function (e) { 
            if (e.element.nodeName === 'IMG' && e.element.classList.contains('mce-object') === false) {
                resizeImage($(e.element), e.width, e.height);
            }
        }); 
    } 
}); 

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

Форматирование HTML-разметки

Именно эта задача вызвала у нас больше всего трудностей.

После тщательного изучения документации по TinyMCE было обнаружено, что нет никакой возможности сконфигурировать редактор так, чтобы он очищал HTML-разметку от различного мусора при вставке текста из Word’а или же с других сайтов, и при этом бы не урезал функциональные возможности пользователей. Готовых решений, удовлетворяющих нашим потребностям, в интернете мы также не нашли.

Пришлось справляться собственными силами, и вот что у нас получилось github.com/WEACOMRU/html-formatting.

Представленная в репозитории функция проверяет соответствие содержимого переданного ей контейнера определенным правилам и избавляется от всего лишнего. Она написана на чистом JS и не требует никаких зависимостей и распространяется по лицензии MIT.

Для форматирования разметки в момент вставки текста в TinyMCE необходимо задать обработчик события paste_postprocess:

tinymce.init({ 
    /* Конфигурация редактора */ 
    paste_postprocess: function (plugin, args) { 
        var 
            valid_elements = { 
                /* Конфигурация правил форматирования */  
            }; 
        htmlFormatting(args.node, valid_elements); 
    }
}); 

С принципами конфигурирования правил вы можете ознакомиться на гитхабе, я же расскажу о том, как эта функция работает.

Если смотреть на уже готовое решение, все оказывается достаточно элементарно: в цикле перебираем все дочерние элементы HTML-контейнера и для каждого запускаем отдельную обработку. Функцию выполняем рекурсивно до тех пор, пока не достигнем самого глубокого уровня вложенности.

process = function (node, valid_elements) {
    var taskSet = [],
        i;

    for (i = 0; i < node.childNodes.length; i++) {
        processNode(node.childNodes[i], valid_elements, taskSet);
    }

    doTasks(taskSet);
}

В процессе обработки отдельного элемента прежде всего проверяем, с чем мы имеем дело: с HTML-элементом или же с текстом.

processNode = function (node, valid_elements, taskSet) {
    var rule;

    if (node.nodeType === 1) {
        /* HTML-элемент */
    } else if (node.nodeType === 3) {
        /* Текстовый элемент */
    }
}

Текстовые элементы обрабатываются по-своему — из них удаляются все неразрывные пробелы.

processText = function (node) {
    node.nodeValue = node.nodeValue.replace(/\xa0/g, ' ');
}

Это вызвано тем, что наши редакторы испытывали трудности из-за сохраняющихся неразрывных пробелов в скопированном тексте, которые ломали переносы в статье. Данная процедура решает эту проблему, однако она может оказаться нежелательной для вас, если это так — подправьте исходный код функции под свои нужды.

Обработка HTML-элементов выполняется в соответствии с заданными правилами.

getRule = function (node, valid_elements) {
    var re = new RegExp('(?:^|,)' + node.tagName.toLowerCase() + '(?:,|$)'),
        rules = Object.keys(valid_elements),
        rule = false,
        i;

    for (i = 0; i < rules.length && !rule; i++) {
        if (re.test(rules[i])) {
            rule = valid_elements[rules[i]];
        }
    }

    return rule;
}
...
processNode = function (node, valid_elements, taskSet) {
    var rule;

    if (node.nodeType === 1) {
        rule = getRule(node, valid_elements);
        ...
    } else if (node.nodeType === 3) {
        processText(node);
    }
}

Если правило для данного элемента не найдено — он распаковывается, т.е. все его дочерние элементы выносятся на уровень выше и заменяют данный элемент.

unpack = function (node) {
    var parent = node.parentNode;

    while (node.childNodes.length > 0) {
        parent.insertBefore(node.childNodes[0], node);
    }
}
...
if (rule) {
    if (typeof rule.valid_elements === 'undefined') {
        process(node, valid_elements);
    } else {
        process(node, rule.valid_elements)
    }
    ...
} else {
    process(node, valid_elements);
    
    if (node.hasChildNodes()) {
        taskSet.push({
            task: 'unpack',
            node: node
        });
    }
    
    taskSet.push({
        task: 'remove',
        node: node
    })
}

При наличии соответствующего правила элемент сохраняется, если он не пуст (непустым считается контейнер, содержащий хоть один текстовый элемент на любом уровне вложенности, состоящий не только из пробелов) или же в правиле нет установки удалять пустые элементы (no_empty).

isEmpty = function (node) {
    var result = true,
        re = /^\s*$/,
        i, child;

    if (node.hasChildNodes()) {
        for (i = 0; i < node.childNodes.length && result; i++) {
            child = node.childNodes[i];

            if (child.nodeType === 1) {
                result = isEmpty(child);
            } else if (child.nodeType === 3 && !re.test(child.nodeValue)) {
                result = false;
            }
        }
    }

    return result;
}
...
if (rule.no_empty && isEmpty(node)) {
    taskSet.push({
        task: 'remove',
        node: node
    });
} else {
    ...
}

В зависимости от конфигурации правила проверяются стили и классы элемента.

checkStyles = function (node, valid_styles) {
    var i, re;

    if (typeof valid_styles === 'string' && node.style.length) {
        for (i = node.style.length - 1; i >= 0; i--) {
            re = new RegExp('(?:^|,)' + node.style[i] + '(?:,|$)');

            if (!re.test(valid_styles)) {
                node.style[node.style[i]] = '';
            }
        }
        
        if (!node.style.cssText) {
            node.removeAttribute('style');
        }
    }
}

checkClasses = function (node, valid_classes) {
    var i, re;

    if (typeof valid_classes === 'string' && node.classList.length) {
        for (i = node.classList.length - 1; i >= 0; i--) {
            re = new RegExp('(?:^|\\s)' + node.classList[i] + '(?:\\s|$)');

            if (!re.test(valid_classes)) {
                node.classList.remove(node.classList[i]);
            }
        }

        if (!node.className) {
            node.removeAttribute('class');
        }
    }
}
...
checkStyles(node, rule.valid_styles);
checkClasses(node, rule.valid_classes);

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

if (rule.convert_to) {
    taskSet.push({
        task: 'convert',
        node: node,
        convert_to: rule.convert_to
    });
} else if (node.id) {
    node.removeAttribute('id');
}

if (typeof rule.process === 'function') {
    taskSet.push({
        task: 'process',
        node: node,
        process: rule.process
    });
}

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

convert = function (node, convert_to) {
    var parent = node.parentNode,
        converted = document.createElement(convert_to);

    if (node.style.cssText) {
        converted.style.cssText = node.style.cssText;
    }
    if (node.className) {
        converted.className = node.className;
    }

    while (node.childNodes.length > 0) {
        converted.appendChild(node.childNodes[0]);
    }

    parent.replaceChild(converted, node);
}

Как вы уже, наверное, заметили, все манипуляции с DOM ставятся в очередь и выполняются по завершении текущего цикла по элементам, дабы не нарушать его.

doTasks = function (taskSet) {
    var i;

    for (i = 0; i < taskSet.length; i++) {
        switch (taskSet[i].task) {
            case 'remove':
                taskSet[i].node.parentNode.removeChild(taskSet[i].node);
                break;

            case 'convert':
                convert(taskSet[i].node, taskSet[i].convert_to);
                break;

            case 'process':
                taskSet[i].process(taskSet[i].node);
                break;

            case 'unpack':
                unpack(taskSet[i].node);
                break;
        }
    }
}

Демо работы функции вы найдете в репозитории. Я надеюсь, что данное описание поможет вам видоизменять функцию под ваши конкретные нужды, если в чистом виде она вас не удовлетворит, или хотя бы послужит идейным вдохновением.

Типографика

Ну и напоследок остается самое простое — внедрение типографа. Мы использовали замечательный скрипт Дениса Селезнева hcodes github.com/typograf/typograf.

Все, что нужно — это написать маленький плагин к TinyMCE:

tinymce.PluginManager.add('typograf', function (editor, url) {
    'use strict';

    var scriptLoader = new tinymce.dom.ScriptLoader(),
        tp,
        typo = function () {
            if (tp) {
                editor.setContent(tp.execute(editor.getContent()));
                editor.undoManager.add();
            }
        };

    scriptLoader.add(url + '/typograf.min.js');

    scriptLoader.loadQueue(function () {
        tp = new Typograf({
            lang: 'ru',
            mode: 'name'
        });
    });

    editor.addButton('typograf', {
        text: 'Типографика',
        icon: 'blockquote',
        onclick: typo
    });

    editor.addMenuItem('typograf', {
        context: 'format',
        text: 'Типографика',
        icon: 'blockquote',
        onclick: typo
    });
});

Как видите, скрипт типографа размещен в папке с плагином и подгружается асинхронно средствами редактора https://www.tinymce.com/docs/api/class/tinymce.dom.scriptloader/. Вы же можете загружать скрипт отдельно от TinyMCE, если планируете использовать типограф и в других функциях.

Когда скрипт загружен, происходит инициализация переменной tp. Доступ к контенту редактора осуществляется с помощью методов getContent() и setContent(). Ну и, конечно, после применения типографики нужно добавить еще один уровень отката изменений, используя undoManager.

В качестве иконки для кнопки и пункта меню мы использовали шрифтовую иконку редактора для цитат. С перечнем доступных иконок в TinyMCE вы можете ознакомиться в файле skin.css — (классы .mce-i-*).

На этом все, надеемся наш опыт поможет вам в реализации собственных идей и сократит время поиска решений.

Понравилась статья? Поделить с друзьями:

А вот и еще интересные новости по теме:

  • Амбене био показания к применению инструкция
  • Lg direct drive 5 kg инструкция программ
  • Элюфор суспензия инструкция по применению для детей при ротовирусе
  • Витамины будь здоров витамины группы в инструкция
  • Zirkulin инструкция по применению на русском языке

  • 0 0 голоса
    Рейтинг статьи
    Подписаться
    Уведомить о
    guest

    0 комментариев
    Старые
    Новые Популярные
    Межтекстовые Отзывы
    Посмотреть все комментарии