Как подружить Tickets и TinyMCE
        Разрабатывая свой очередной (аж второй :) ) проект на Modx Revolution столкнулся со странностью поведения сниппета Tickets (tickets-1.6.16-pl ): при создании тикета не появлялась стандартная панелька Modx с кнопками сохранения, отмены и помощи в правом верхнем углу админки. Вот так выглядит админка при создании нового тикета: кнопок нет, полос прокрутки нет.
 
Погуглив я обнаружил, что неодинок в своих проблемах: этот вопрос неоднократно поднимался даже на этом ресурсе. Вариантов решения аж 2 (из комментариев к тем записям):
Но неужели ничего нельзя сделать? Давайте попробуем разобраться под катом.
Если посмотреть в консоль браузера мы увидим ошибку JS
 
 
Можно предположить, что в данном месте происходит создание какого-то html элемента и заполнение его содержимым, которое должно до этого храниться в объекте Tiny.lang. Если мы попробуем посмотреть на его содержимое, то увидим, что оно undefined, т.е. этот объект не заполнен, более того — даже не создан. Попробуем найти откуда он заполняется, поставив брейкпоинт на эту строку и загрузив любую другую страницу, с которой не возникает проблем. И оказалось, что действительно этот объект в других страницах заполнен и содержит в себе данные локализации нашего любимого редактора tinymce.
 
И проблему вызывает отсутствие подписи вот этой маленькой галочки:
 
В поисках места создания этого объекта я набрел на элемент script в head, в котором происходит заполнение данного объекта:
 
Значит этот вывод генерируется на сервере и нужно искать в Modx'е. После определенного поиска место генерации данного конфига было обнаружено метод initialize редактора (\core\components\tinymce\tinymce.class.php:169).
 
Путем использования дебагера было определено, что инициализация редактора происходит при подгрузке ресурса — неважно, создание это или обновление. А также оказалось замечено, что при создании тикета (который тоже является ресурсом) происходит инициализация редактора. Я предположил, что в процессе создания тикета происходит потеря ранее инициализированных данных, что и является причиной проблемы. За создание тикета отвечает класс TicketCreateManagerController (core\components\tickets\controllers\ticket\create.class.php), который наследуется от стандартного класса ResourceCreateManagerController и в котором происходит переопределение метода loadCustomCssJs (:40), где происходит следующее
 
 
Однако позже меня посетила мысль, что не всегда этот элемент может занимать именно этот индекс, поэтому гораздо лучше будет его гарантированно находить и заменять на нужный. Для этого был написан приватный метод класса создания тикета
З.Ы. Также на данный момент замечен баг: при входе в созданный тикет для редактирования его html текст отображается в поле «Аннотация»
 
В комментариях хочется увидеть мнение сообщества по поводу данного способа решения проблемы и стоит ли делать пулл-реквест с данным решением для включения его в исходный сниппет?
З.З.Ы. Поставил Tickets-1.8.0 pl. Теперь при переходе на страницу — раздел с тикетами — она не отображается вообще. Все свои изменения естественно откатил до исходного состояния. Может это у меня одного такая проблема? Поделитесь пожалуйста.
     
    
    
                                                                                
            Погуглив я обнаружил, что неодинок в своих проблемах: этот вопрос неоднократно поднимался даже на этом ресурсе. Вариантов решения аж 2 (из комментариев к тем записям):
Но неужели ничего нельзя сделать? Давайте попробуем разобраться под катом.
Можно предположить, что в данном месте происходит создание какого-то html элемента и заполнение его содержимым, которое должно до этого храниться в объекте Tiny.lang. Если мы попробуем посмотреть на его содержимое, то увидим, что оно undefined, т.е. этот объект не заполнен, более того — даже не создан. Попробуем найти откуда он заполняется, поставив брейкпоинт на эту строку и загрузив любую другую страницу, с которой не возникает проблем. И оказалось, что действительно этот объект в других страницах заполнен и содержит в себе данные локализации нашего любимого редактора tinymce.
И проблему вызывает отсутствие подписи вот этой маленькой галочки:
В поисках места создания этого объекта я набрел на элемент script в head, в котором происходит заполнение данного объекта:
Значит этот вывод генерируется на сервере и нужно искать в Modx'е. После определенного поиска место генерации данного конфига было обнаружено метод initialize редактора (\core\components\tinymce\tinymce.class.php:169).
Путем использования дебагера было определено, что инициализация редактора происходит при подгрузке ресурса — неважно, создание это или обновление. А также оказалось замечено, что при создании тикета (который тоже является ресурсом) происходит инициализация редактора. Я предположил, что в процессе создания тикета происходит потеря ранее инициализированных данных, что и является причиной проблемы. За создание тикета отвечает класс TicketCreateManagerController (core\components\tickets\controllers\ticket\create.class.php), который наследуется от стандартного класса ResourceCreateManagerController и в котором происходит переопределение метода loadCustomCssJs (:40), где происходит следующее
$html = $this->head['html'];
parent::loadCustomCssJs();
$this->head['html'] = $html;Именно вызов родительского метода loadCustomCssJs и обеспечивает корректную подгрузку всех данных, в том числе так необходимого нам объекта Tiny.lang из конфига TinyMCE, и помещает их в виде массива в $this->head['html'] (далее head['html']). Но вся проблема заключается в том, что этот массив после заполнения перезаписывается более ранним вариантом, в котором нет того, что нам нужно. Далее в процессе выполнения метода создания тикета происходит добавление новых элементов в этот массив, хранящих настройки и свойства для клиентской части, однако конфиг редактора оказывается безвозвратно потерян и в конечном рендере страницы не участвует. Путем экспериментов было определено, что корректная работа будет восстановлена при замене всего лишь одного элемента массива head['html'], содержащего данные о документе. В данном массиве он устанавливает с индексом 1, поэтому изначальный вариант лечения выглядел такОднако позже меня посетила мысль, что не всегда этот элемент может занимать именно этот индекс, поэтому гораздо лучше будет его гарантированно находить и заменять на нужный. Для этого был написан приватный метод класса создания тикета
/**
   * To replace the the required array element
   *
   * @param $needle string
   * @param $html string
   * @param $srcHead array as reference
   *
   * @return void
   */
  private function replaceHeadHTML($needle, $html, &$srcHead)
  {
    foreach ($srcHead as &$haystack) {
      if (strpos($haystack, $needle)) {
        $haystack = $html;
        break;
      }
    }
  }который находит именно тот элемент в исходном массиве head['html'], который нужно заменить (там строки одинаково начинаются) и заменяет его на переданную строку, содержащую те данные, что мы хотим передать в клиентскую часть. Тогда в методе loadCustomCssJs использую данный метод следующим образом//данные, которые должен подгрузить сниппет помещаем в переменную
	$newLoadProperties = '
	<script type="text/javascript">
	// <![CDATA[
	MODx.config.publish_document = ' . (int)$this->canPublish . ';
	MODx.config.default_template = ' . $this->modx->getOption('tickets.default_template', 
null, $this->modx->getOption('default_template'), true) . ';
	MODx.onDocFormRender = "' . $this->onDocFormRender . '";
	MODx.ctx = "' . $this->ctx . '";
	Ext.onReady(function() {
		MODx.load(' . $this->modx->toJSON($ready) . ');
	});
	// ]]>
	</script>';
    
	// заменяем в массиве строку, начинающуюся таким же образом, как и та, которую нужно перезаписать
	$this->replaceHeadHTML('
		<script type="text/javascript">
	    // <![CDATA[
	    MODx.config.publish_document = ', $newLoadProperties, $this->head['html']);При этом, естественно, вышеуказанный кусочек с заполнением head['html'] должен выглядеть как вызов функции класса-родителя без дополнительных переопределенийparent::loadCustomCssJs();Недостаток данного метода в том, что такие же манипуляции нужно произвести в классе TicketUpdateManagerController (core\components\tickets\controllers\ticket\update.class.php). З.Ы. Также на данный момент замечен баг: при входе в созданный тикет для редактирования его html текст отображается в поле «Аннотация»
В комментариях хочется увидеть мнение сообщества по поводу данного способа решения проблемы и стоит ли делать пулл-реквест с данным решением для включения его в исходный сниппет?
З.З.Ы. Поставил Tickets-1.8.0 pl. Теперь при переходе на страницу — раздел с тикетами — она не отображается вообще. Все свои изменения естественно откатил до исходного состояния. Может это у меня одного такая проблема? Поделитесь пожалуйста.
Комментарии: 22
                Нифига не понял по методу, но плюсую за желание решить проблему, сам сейчас мучаюсь с TinyMCE RTE 1.1.x, он менее удобен, чем обычный TinyMCE.
                    З.Ы. Также на данный момент замечен баг: при входе в созданный тикет для редактирования его html текст отображается в поле «Аннотация»По-моему это не баг, туда автоматически помещается текст, который потом выводится в качестве интро у тикета (до кнопки «Читать далее»). По дефолту, насколько я понял, просто пропускается всё содержимое content через Jevix.
                У меня ест решения будет время вложу!            
                    
                1. Ребят, насколько я понимаю, в miniShop2 такой проблемы нет. 
2. Tickets и miniShop2 очень похожи — ибо автор у них один.
3. Неужели никто не может сравнить работу с TinyMCE у этих двух дополнений и прислать PR с исправлением?
Я сам не пользуюсь TinyMCE, так что решение проблемы исключительно в ваших руках.
                    2. Tickets и miniShop2 очень похожи — ибо автор у них один.
3. Неужели никто не может сравнить работу с TinyMCE у этих двух дополнений и прислать PR с исправлением?
Я сам не пользуюсь TinyMCE, так что решение проблемы исключительно в ваших руках.
                Василий а ты каким редактором пользуешься? Почему именно им?            
                    
                Ace, потому что он хороший.
Мне не нравится, когда редактор от меня что-то скрывает. Или меняет то, что я написал modx.pro/security/8811-about-the-benefits-of-rte/
                    Мне не нравится, когда редактор от меня что-то скрывает. Или меняет то, что я написал modx.pro/security/8811-about-the-benefits-of-rte/
                А для контент-менеджеров удобно? Или всяким там менеджерам отдельную фронтенд часть делать нужно?            
                    
                Не знаю. У меня нет контент менеджеров и последний сайт на заказ, который я делал на MODX, был Vrmedia, с отдельной админкой на фронте.            
                    
                Василий, сколько денег будет стоить внесение таких изменений (не дожидаясь PR) + замена MarcitUp на TinyMCE хотя бы для TicketCreate во фрондэнде? (для краудфандинга)            
                    
                PR для исправления работы с редактором уже прислали, как будет время — обработаю. А менять на фронтенде я ничего не планирую.
MarkItUp отключается в настройках, дальше можно подключать любой удобный редактор самостоятельно.
                    MarkItUp отключается в настройках, дальше можно подключать любой удобный редактор самостоятельно.
                Ок. Спасибо.
С отключение MarkItUp все просто, а вот подключить любой удобный редактор самостоятельно у меня не получается. Пробовал.
                    С отключение MarkItUp все просто, а вот подключить любой удобный редактор самостоятельно у меня не получается. Пробовал.
                На свой страх и риск modx.pro/solutions/8592-tinymce-tickets-choice-of-main-images-in-tv/            
                    
                Спасибо. Буду пробовать.            
                    
                Вчера только столкнулся с такой проблемой, потом увидел, что на сайте стоит TinyMCE, удалил поставил другой, полет нормальный.
Самый оптимальный редактор для менеджеров который я ставлю — это CKEditor.
Выбрал CKEditor из-за того, что он хотя бы не плодит дохерища тегов.
                    Самый оптимальный редактор для менеджеров который я ставлю — это CKEditor.
Выбрал CKEditor из-за того, что он хотя бы не плодит дохерища тегов.
                Выпустил новую версию, должно работать — проверяйте.            
                    
                Возможно и я что-то напортачил, поставил предыдущую версию, все нормально работает. Это окно заметил когда в редакторе TinyMCE попытался переключить в режим HTML. Что-то не давало нажать кнопку, по F12 увидел, что есть поверх всего дополнительный div у которого opacity было 0. Сам сайт еще пустой, только начал его настраивать.
Вот я повторно установил и опять появилось, может есть предположение, что это такое? Не понятно почему он берет данные именно 404 страницы.
            
                    Вот я повторно установил и опять появилось, может есть предположение, что это такое? Не понятно почему он берет данные именно 404 страницы.
            
                Без понятия.
Еще раз — я не пользуюсь такими редакторами и разбираться с их особенностями мне не досуг. Кнопка HTML у меня на тесте работала без проблем.
                    Еще раз — я не пользуюсь такими редакторами и разбираться с их особенностями мне не досуг. Кнопка HTML у меня на тесте работала без проблем.
                Хорошо, спасибо.            
                    
                Была аналогичная проблема вплоть до некой php ошибки при попытке создать/редактировать документ.
Я решил это так: использовать CKEditor.
                    Я решил это так: использовать CKEditor.
                CKEditor на фронтенде тоже неплохо подключается. Деактивируем в настройках MarkItUp, текстовое поле в чанке 
            
                    <textarea class="form-control" placeholder="[[%ticket_content]]" name="content" id="content"   
 rows="40"></textarea> подключаем скрипт на странице <script src="/assets/components/ckeditor/ckeditor.js"></script><script>CKEDITOR.replace('content');</script>Загруженные картинки просто перетаскиваются в текст. Заказчики с MarkItUp никак не дружат.
            
                Подскажите, а вопрос как-то решился или нет?            
                    
                            Авторизуйтесь или зарегистрируйтесь, чтобы оставлять комментарии.
                    
            
                    
                    
                
