TinyMCE + Tickets + выбор главной картинки в TV

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

Вот что получилось:


Инструкция под катом

Да простите меня за велосипеды

1. Установка TinyMCE
Почему этот редактор? Перепробовал много разных, но только TinyMCE не создает лишних тегов и Tickets нормально обрабатывает контент + удобно кастомизируется и быстро работает

1.1 Непосредственно в чанке создания тикета добавляем такой код:
<script src="//cdn.tinymce.com/4/tinymce.min.js"></script>
<script>
tinyMCE.PluginManager.add('stylebuttons', function(editor, url) {
['pre', 'p', 'code', 'h1', 'h2', 'h3', 'h4', 'h5', 'h6'].forEach(function(name){
editor.addButton("style-" + name, {
tooltip: "Header " + name.toUpperCase(),
text: name.toUpperCase(),
onClick: function() { editor.execCommand('mceToggleFormat', false, name); },
onPostRender: function() {
var self = this, setup = function() {
editor.formatter.formatChanged(name, function(state) {
self.active(state);
});
};
editor.formatter ? setup() : editor.on('init', setup);
}
})
});
});

tinymce.init({
selector: ".cont-edit",
setup: function (editor) {editor.on('change', function () {editor.save();});},
plugins: ['advlist autolink lists link image charmap print preview anchor','searchreplace visualblocks code fullscreen','insertdatetime media table contextmenu paste code stylebuttons ticketsfiles'],
advlist_bullet_styles:'',
advlist_number_styles:'',
menu:{},
toolbar:'undo redo | style-h2 style-h3 bold italic underline strikethrough alignleft aligncenter | bullist numlist | link image code'
});
</script>

в tinymce.init обязательно должен присутствовать код
setup: function (editor) {editor.on('change', function () {editor.save();});}
иначе в textarea ничего не будет попадать и Tickets будет ругаться.
В списке плагинов должен быть также перечислен ticketsfiles

1.2 Мне для сайта нужны были Header 2 и Header 3, поэтому в скрипте есть плагин, добавляющий несколько тегов. Но в toolbar у меня только style-h2 style-h3, куда можно также приписать style-h1, к примеру.

NB! TinyMCE у меня инициализируется в текстовую область с классом ".cont-edit"

Добавьте следующие стили в свой файл .css, так как редактор может отображаться кривовато из-за убранных элементов:
.mce-container, .mce-container-body {overflow:hidden;}
.mce-splitbtn .mce-open {display:none;}
.mce-btn .mce-txt {font-size:18px!important;font-weight:bold;opacity:.9;}

2. Вставка в редактор TinyMCE картинки из добавленных файлов Tickets

2.1 Заходим в assets/components/tickets/js/web и открываем скрипт files.js
В самом низу будет функция на клик по ticket-file-insert и добавление файла в markItUp.
Закомментируйте или удалите этот код и вставьте этот:

tinymce.PluginManager.add('ticketsfiles', function(editor, url) {
$(document).on('click', '.ticket-file-insert', function(e) {
	var $this = $(this);
	var $parent = $this.parents('.ticket-file');
	var $text = $('.mce-content-body');
	var template = $parent.find('.ticket-file-template').html();
	template = template.replace(/^\n/g, '').replace(/\t{2}/g, '').replace(/\t$/g, '');
	$text.focus();
	editor.insertContent(template);
	return false;
});
});
Сохраняем скрипт и радуемся, так как редактор уже работает нормально

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

3.1 Нам понадобится чанк tpl.Tickets.form.image или тот, который вы вызываете в сниппете TicketForm
И добавляем под
<a href="#" class="ticket-file-insert">[[%ticket_file_insert]]</a>
строку
<a href="#" class="ticket-file-promo" style="color:grey">Сделать главной</a>

и под
<div class="ticket-file-template">
<a href="[[+url]]" title="[[+name]]" class="swipebox" rel="[[+id]]"><img src="[[+url]]" /></a>
</div>
строку
<div class="ticket-file-template-promo" style="display:none">[[+url]]</div>

3.2 Далее, если закрыли, снова открываем files.js в assets/components/tickets/js/web
и после функции, которую мы добавили в пункте 2 ставим следующий код:

$(document).on('click', '.ticket-file-promo', function(e) {
	var $this = $(this);
	var $parent = $this.parents('.ticket-file');
	var $text = $('#mainimage');
	var $bg = $('#bgpromoimg');
	var template = $parent.find('.ticket-file-template-promo').html();
	template = template.replace(/^\n/g, '').replace(/\t{2}/g, '').replace(/\t$/g, '');

	$('.ticket-file-promo').css({"color":"grey"});
	$this.css({"color":"green"});
	$text.attr('value',template);
	$bg.css('background-image', 'url(' + template + ')').css({"background-size":"cover"});
	return false;
});
Тут по идее нужно убрать лишнее и добавить нормальные addClass, а не inline стили, но у меня сайт сейчас в разработке, поэтому дизайн только предполагается.

3.3 В форме тикета должен быть скрытый input
<input type="hidden" name="item-image" id="mainimage" value="" />
а также div#bgpromoimg, в котором показывается главная картинка

NB! Не забудьте добавить в allowedFields TicketForm значение TV item-image

3.4 Так как при сохранении тикета в TV записывается неправильное значение
/assets/images/tickets/0/08adfeeb6a7870c6350e031e758551682541d375.jpg
то нам нужно вырезать assets/images/tickets/0/ и заменить 0 на ID тикета

Пример: в чанке вывода изображения тикета добавляем
[[+item-image:!empty=`<a href="[[~[[+id]]]]" class="image transition-03 smooth"><img alt="[[+pagetitle]]" src="[[pthumb? &input=`/assets/images/tickets/[[+id]][[+item-image:stripString=`/assets/images/tickets/0`]]` &options=`h=300&w=670&zc=1`]]" /></a>`]]
NB! Должен быть установлен компонент pThumb (очень быстро работает, кстати)

Вот и всё, надеюсь, кому-нибудь этот гайд поможет

p.s. не забудьте выключить редактор markItUp в конфигах tickets
p.s.s для сайтов, где нужна вставка кода, нужно добавить codesample в вызов tinymce (plugins,toolbar)
Andrei D.
24 апреля 2016, 12:32
modx.pro
46
5 800
+15

Комментарии: 27

Василий Столейков
24 апреля 2016, 16:03
0
Спасибо! Как раз такая же задача висит недоделанная у меня…
    brioni
    24 апреля 2016, 18:50
    0
    Вот спасибо-хорошо!

    Правильно понял, что тегов в тексте теперь нет и можно видеть написаное без «предпросмотра»?
      Andrei D.
      24 апреля 2016, 19:08
      +2
      да, но в списке плагинов tinymce можете дописать еще preview, тогда появится иконка-глаз с удобным popup превью
      Василий Столейков
      24 апреля 2016, 18:59
      0
      Вопрос: как себя ведёт этот редактор в связке с последующим Jevix-выводом контента? Ckeditor например расставляет везде теги абзацев, а Jevix-у это не нравится — у него br-ки.
        Andrei D.
        24 апреля 2016, 19:06
        1
        0
        все работает хорошо с теми тегами, которые в этом гайде, другие не смотрел.
        также я написал, что протестил с десяток других подобных редакторов, причем в списке tinymce был последним из-за моего давнего плохого отношения от редактора в бэкенде
          Ivan Shvindin
          24 апреля 2016, 19:07
          +1
          в настройках jevix можно отключить бр и будут абзацы
          Andrei D.
          24 апреля 2016, 19:33
          0
          Картинка может ввести в заблуждение, что последняя иконка в тулбаре является вставкой кода, как на modx.pro. Но это просто просмотр содержания в html виде.
          Для сайтов, где нужна вставка кода, нужно добавить codesample в вызов tinymce (plugins,toolbar)

          добавил в описание
            Konstantin
            01 мая 2016, 14:19
            1
            +1
            А после обновления Тикетса это все прекратит работать?
              Andrei D.
              01 мая 2016, 19:39
              0
              разумеется, если формы создания и изменения тикета будут с дефолтными именами
              Николай Загумённов
              25 мая 2016, 11:12
              3
              0
              Путь до картинки можно менять не модификаторами во время, а при сохранении тикета, плагином на событие OnDocFormSave.
              Заодно проверяет поле content на наличие картинок с таким путём и меняет 0 на id.
              Может кому пригодится.
              Мне пригодился этот пост. Спасибо за него.

              <?php
              switch ($modx->event->name) {
              
                  case 'OnDocFormSave':
                      if (is_object($resource) && is_array($resource->_fields)) {
                          $data = $resource->_fields;
                          $resource_id = $data['id'];
                          // $modx->log(1, print_r($data, 1));
              
                          $flds = $tv_values = array();
                          foreach ($data as $key => $value) {
                              if ($key == 'item_image')  {
                                  $tv_id = 2; // id твшки с картинкой
              
                                  $value = trim($value);
                                  $tv_value = str_replace('assets/images/tickets/0', 'assets/images/tickets/' . $resource_id, $value);
                              }
                              if ($key == 'content') {
                              	$content = str_replace('assets/images/tickets/0', 'assets/images/tickets/' . $resource_id, $value);
                              }
                          }
                          if (!empty($content)) {
                          	$res_obj = $modx->getObject('modResource',$resource_id);
                          	$res_obj->set('content', $content);
                          	$res_obj->save();
                          	unset($res_obj);
                          }
                          // пишем в таблицу modTemplateVarResource
                          if (!empty($tv_value)) {
                              //$modx->log(1, print_r($tv_values, 1));
              
                              	if (!$tv_obj = $modx->getObject('modTemplateVarResource', array(
                                      'tmplvarid' => $tv_id,
                                      'contentid' => $resource_id,
                                  ))) {
                                      $tv_obj = $modx->newObject('modTemplateVarResource');
                                  }
              
                                  $tv_obj->fromArray(array(
                                      'tmplvarid' => $tv_id,
                                      'contentid' => $resource_id,
                                      'value' => $tv_value,
                                  ));
                                  $tv_obj->save();
                                  // $modx->log(1, print_r($tv_obj->toArray(), 1));
              
                                  unset($tv_obj);
                          }
                      }
                  break;
              }
                Борис И
                11 февраля 2020, 15:48
                0
                Спасибо большое. Два дня пытался починить, ничего не помогало, с помощью данного плагина все заработало. Вопрос, вот это для чего
                $tv_id = 2; // id твшки с картинкой
                Влад
                24 октября 2016, 01:03
                0
                ВОт понадобился для сайта функционал ведения пользователями блогов. начал прикручивать tinymce по данной инструкции во фронт. В итоге потратил целый день но так и не смог один момент настоить. Конкретно при добавлении картинки с ссылкой на оригинальное изображение с атрибутом data-uk-lightbox и последующей публикации тикета, не сохраняется путь к thumb в пути остается /0/ вместо айди ресурса, хотя в ссылке на оригинальное изображение все четко вставляется айди и при клике на сломанное превью открывается изображение в полном разрешении. Голову сломал не знаю куда копать а для этого сайта очень нужен wyziwyg редактор!!! Прошу помощи у автора данного решения модет есть какой нить велосипед))
                  Николай Загумённов
                  24 октября 2016, 09:19
                  0
                  Разве плагин в комментарии выше не решает эту проблему?
                    Влад
                    24 октября 2016, 09:52
                    0
                    Нет не решает. Я не супер спец по модиксу но я понял что данный плагин срабатывает только при сохранении из админки а я с фронтенда создаю и тут скорее всего требуется другое событие, вчера методом научного тыка перебрал с пару десятков)))) других событий, ничего не получилось. Может направите на путь истинный куда копать? Заранее благодарю!
                      Николай Загумённов
                      24 октября 2016, 10:02
                      0
                      C фронтенда он тоже должен работать.
                        Влад
                        24 октября 2016, 10:08
                        0
                        Я уже все перепроверил все сделал как описано в данном примере, кроме сохранения главной картинки.
                        И вот щас опять проверил все три пункта все ровно, а с фронта не работает плагин. Путь к оригинальной картинки норм прописывает а к thumb с 0
                        <a href="assets/images/tickets/396/2f02f4711ceda7759c1da1cff2124a682c30cbbb.jpg" data-uk-lightbox="{group:'group1'}"><img src="assets/images/tickets/0/2f02f4711ceda7759c1da1cff2124a682c30cbbb.jpg"></a>
                          Влад
                          24 октября 2016, 10:09
                          0
                          я на самом деле уже где то часов 5-6 потратил на решение проблемы, тиктетс переустанавливал,
                          гугл перелопатил, готов даже денег заплатить!!! вообще не понимаю в чем проблема!
                    Andrei D.
                    24 октября 2016, 11:19
                    0
                    велосипед для данного конкретного случая приведен в пункте 3.4
                      Влад
                      24 октября 2016, 11:22
                      0
                      ТАк я тв ничего не сохраняю, проблема конкретно в поле content
                        Влад
                        24 октября 2016, 13:53
                        0
                        В итоге включили Jevix и все корректно заработало
                      Sergey
                      11 января 2017, 00:05
                      0
                      Добрый день. Подключаю TinyMCE по данному решению. Во фронте выскакивает ошибка в консоле — SyntaxError: unterminated regular expression literal. Отладчик показывает следующую ситуацию —
                      tinyMCE.PluginManager.add('stylebuttons'  </p>
                      Подскажите в чем может быть проблема?
                        Борис И
                        03 февраля 2019, 16:03
                        0
                        Спасибо, отличное решение. Периодически, в процессе пересохранения тикета с фронта у url картинок (/assets/images/tickets/14/kartinka.jpg) удалялся слеш перед ссылкой (assets/images/tickets/14/kartinka.jpg),
                        после чего отображение ломалось т.к. вместо site.ru/assets/images/tickets/14/kartinka.jpg
                        было site.ru/razdel/assets/images/tickets/14/kartinka.jpg
                        Решилось:
                        1. добавил в
                        tinymce.init({
                        selector: "#ticket-editor",
                        relative_urls: false,
                        2. в параметрах плагина Path Options установил fullpathurl вместо docrelative
                        Пока все нормально.
                          Борис И
                          28 апреля 2019, 11:40
                          0
                          Опять нашел косяк. После пересохраниения тикета, к картинкам добавляет второй слеш.
                          Исправил, так
                          вместо
                          tinymce.init({
                          selector: "#ticket-editor",
                          relative_urls: false,
                          стало
                          tinymce.init({
                          selector: "#ticket-editor",
                          relative_urls: false,
                          remove_script_host: false,
                          весь код такой
                          <script src="//cdn.tinymce.com/4/tinymce.min.js"></script>
                          <script>
                          tinyMCE.PluginManager.add('stylebuttons', function(editor, url) {
                          ['pre', 'p', 'code', 'h1', 'h2', 'h3', 'h4', 'h5', 'h6'].forEach(function(name){
                          editor.addButton("style-" + name, {
                          tooltip: "Header " + name.toUpperCase(),
                          text: name.toUpperCase(),
                          onClick: function() { editor.execCommand('mceToggleFormat', false, name); },
                          onPostRender: function() {
                          var self = this, setup = function() {
                          editor.formatter.formatChanged(name, function(state) {
                          self.active(state);
                          });
                          };
                          editor.formatter ? setup() : editor.on('init', setup);
                          }
                          })
                          });
                          });
                          
                          tinymce.init({
                          selector: "#ticket-editor",
                          relative_urls: false,
                           remove_script_host: false,
                          setup: function (editor) {editor.on('change', function () {editor.save();});},
                          plugins: ['advlist autolink lists link image charmap print preview anchor','searchreplace visualblocks code fullscreen','insertdatetime media table contextmenu paste code  stylebuttons ticketsfiles'],
                          advlist_bullet_styles:'',
                          advlist_number_styles:'',
                          menu:{},
                          toolbar:'undo redo | style-h2 style-h3 bold blockquote italic underline strikethrough alignleft aligncenter | bullist numlist | link image media code '
                          });
                          </script>
                          Борис И
                          03 августа 2019, 12:21
                          0
                          Здравствуйте.
                          Подскажите пожалуйста. Нужно добавить кнопку с добавлением своих стилей к тексту (блоку).
                          В вызове
                          toolbar:'undo redo | style-h2 style-h3 style-h4 bold blockquote italic underline strikethrough alignleft aligncenter | bullist numlist | link image media code visualblocks   styleselect'
                          добавил styleselect. Кнопка Formats в редакторе появилась, там стандартные стили (теги — обертки).
                          В настройках tiny.css_selectors прописал свои стили.
                          Не работает, выводит стили (теги — обертки) уже вшитые в редактор. Что я делаю не так
                            Борис И
                            03 августа 2019, 13:18
                            0
                            Проверил в админке все ок. Вопрос. Как подключить свои стили с фронта
                              Борис И
                              03 августа 2019, 13:51
                              0
                              Все как положено, сам спросил, сам ответил)
                              Вдруг кому пригодится, для примера:
                              Для своих стилей, код
                              style_formats: [
                                     {title: 'Выделение синим', block: 'div', classes: 'blb'},
                                     {title: 'Выделение зеленым', block: 'div', classes: 'blg'},
                                     {title: 'Выделение красным', block: 'div', classes: 'blr'},
                                     {title: 'Выделение', block: 'div', classes: 'bl'},
                                  ],
                              Весь код ниже
                              <script src="//cdn.tinymce.com/4/tinymce.min.js"></script>
                              <script>
                              tinyMCE.PluginManager.add('stylebuttons', function(editor, url) {
                              ['pre', 'p', 'code', 'h1', 'h2', 'h3', 'h4', 'h5', 'h6'].forEach(function(name){
                              editor.addButton("style-" + name, {
                              tooltip: "Header " + name.toUpperCase(),
                              text: name.toUpperCase(),
                              onClick: function() { editor.execCommand('mceToggleFormat', false, name); },
                              onPostRender: function() {
                              var self = this, setup = function() {
                              editor.formatter.formatChanged(name, function(state) {
                              self.active(state);
                              });
                              };
                              editor.formatter ? setup() : editor.on('init', setup);
                              }
                              })
                              });
                              });
                              
                              tinymce.init({
                              selector: "#ticket-editor",
                              relative_urls: false,
                              remove_script_host: false,
                              style_formats: [
                                     {title: 'Выделение синим', block: 'div', classes: 'blb'},
                                     {title: 'Выделение зеленым', block: 'div', classes: 'blg'},
                                     {title: 'Выделение красным', block: 'div', classes: 'blr'},
                                     {title: 'Выделение', block: 'div', classes: 'bl'},
                                  ],
                              setup: function (editor) {editor.on('change', function () {editor.save();});},
                              plugins: ['advlist autolink lists link image charmap print preview anchor','searchreplace visualblocks code fullscreen','insertdatetime media table contextmenu paste code  stylebuttons ticketsfiles'],
                              advlist_bullet_styles:'',
                              advlist_number_styles:'',
                              menu:{},
                              toolbar:'undo redo | style-h2 style-h3 style-h4 bold blockquote italic underline strikethrough alignleft aligncenter | bullist numlist | link image media code visualblocks   styleselect'
                              });
                              </script>
                            Авторизуйтесь или зарегистрируйтесь, чтобы оставлять комментарии.
                            27