Предпросмотр для InstantCMS 2 2.X

3932

Всем привет!

В ходе работы над одним дополнением, которым поделюсь позже, вспомнилась идея: "а не плохо было бы перед публикацией записи посмотреть что получится". Многие ресурсы имеют такой функционал в своем комплекте, а чем инстант хуже?))
Сначала двигался по пути реализации дополнительного функционала указанного выше дополнения, затем посмотрел в сторону отдельного компонента и, наконец, остановился на хаке системного компонента content. При удачном стечении обстоятельств, надеюсь опубликовать pull request. Ну а что это за обстоятельства - читаем ниже...

Предпросмотр для InstantCMS 2


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

Ближе к телу:
1. Создаем файл ..\system\controllers\content\actions\item_preview.php и кидаем в него следующий код
Спойлер
2. Далее модифицируем файлы ..\system\controllers\content\actions\item_add.php и ..\system\controllers\content\actions\item_edit.php
для первого добавляем перед $item = $this->model->addContentItem($ctype, $item, $fields); (205 строка), для второго $item = $this->model->updateContentItem($ctype, $id, $item, $fields); (182 строка)
Код PHP:
  1. // Блок предпросмотра
  2. if ($this->request->has('is_preview')){
  3.  
  4. $this->runAction('item_preview', array(array($ctype, $item)));
  5.  
  6. }
и также добавляем для item_add.php (238 строка), для item_edit.php (213 строка) перед if ($errors){ cmsUser::addSessionMessage(LANG_FORM_ERRORS, 'error'); }:
Код PHP:
  1. // Запрос предпросмотра с ошибками заполнения полей
  2. if ($errors && $this->request->has('is_preview')){
  3.  
  4. $this->cms_template->renderJSON(array(
  5. 'errors' => $errors,
  6. 'message' => LANG_FORM_ERRORS
  7. ));
  8.  
  9. }
3. Теперь добавим кнопку взаимодействия с новым функционалом и стилизуем её. Дописываем в файле ..\templates\default\controllers\content\item_form.tpl.php строку в рендере формы (она помечена комментарием):
Код PHP:
  1. $this->renderForm($form, $item, array(
  2. 'action' => '',
  3. 'method' => 'post',
  4. 'toolbar' => false,
  5. 'hook' => array(
  6. 'event' => "content_{$ctype['name']}_form_html",
  7. 'param' => array(
  8. 'do' => $do,
  9. 'id' => $do=='edit' ? $item['id'] : null
  10. )
  11. ),
  12. 'append_html' => html_button('Предпросмотр', 'preview', "icms.content.getPreview();", array('class'=>'button-preview', 'data-description' => 'Предварительный просмотр')), // <- Вот эта строка !!!
  13. ), $errors);
Здесь заголовок кнопки и описание поля вывода предпросмотра прописаны хардкорно, но в готовом решении конечно же будут языковые константы.
data-description - необходим чтобы передать текст в js-скрипт на фронтенде. Есть и другие способы, но я выбрал этот.
Добавляем немного стилей в конец файла ..\templates\default\css\theme-content.css
Код CSS:
  1. #preview {
  2. border: 5px solid #d6d6d6;
  3. padding: 10px;
  4. margin: 7px 0 20px;
  5. }
  6. .preview-title {
  7. margin-bottom: 10px;
  8. font-size: 12px;
  9. color: #aaa;
  10. }
  11. input.button-preview {
  12. float: right;
  13. background: #dedede;
  14. color: #333;
  15. }
  16.  
  17. input.button-preview:hover {
  18. background: #e7e7e7;
  19. }
4. И небольшой скрипт. Добавляем в ..\templates\default\js\content.js функцию
Спойлер
Чистим кэш браузера и проверяем работу.

Вопросы и предложения

Как я написал в начале поста есть ряд моментов которые требуют обсуждения:

1. Сторонние разработчики могут делать и делают специфические поля, которые рендеряться по своему внутреннему механизму вывода контента (например в моем компоненте Опросы). Для этих целей предлагаю ввести флаг is_preview в функцию ..\system\core\formfield.php parse($value) -> parse($value, $is_preview=false). Соответственно по этому флагу можно особым образом выводить html-содержимое "нестандартных" полей.

2. Для аналогичных целей с п.1. можно добавить обработчик получения данных поля из атрибута data-preview. В js-скрипте выше этот участок кода закомментирован. Вопрос для разработчиков - нужно ли оно? Или достаточно флага is_preview, или всё же добавить еще возможность формирования данных на фронтэнеде.

3. В представленном решении есть одна большая проблема - подключение стилей CSS! Если поле выводит данные, которые в своем составе содержат стили подключаемые, например, через addCSS(...), то они в текущем виде никак не подгружаются, и соответственно такие данные криво отображаются в области предпросмотра. Тоже самое происходит и с подключаемыми скриптами, функции которых могут запрашиваться при рендере контента, поэтому внутренние скрипты я вычищаю из результатов предпросмотра.

4. Очень проблематично получить ID формы добавления/редактирования контента! Эту проблему я обошел указанием вместо id непосредственно тега form, но механизм получения id был бы не лишним))

5. И в заключении интересует вопрос куда лучше выводить области предпросмотра?
Предпросмотр для InstantCMS 2
Сейчас, по примеру хабра, я показываю превьюшку вверху формы (позиция 1). Может стоит задействовать позицию 2 или 3? Или выводить в модальном окне, или еще какие варианты?

Демо здесь
[email protected] / 123456


UPD 3 вопрос можно решить заменой подключения стилей с addCSS(...) на addCSSFromContext(...). Также и для js - addJSFromContext($file, $comment='')
Just4Fun - Аватарки! | СтопХам - userscript для instantcms.ru
Комментарии (35)
Алексей Тимофеев 15 апреля 2016 в 02:23 +1
Отличное дополнение!
Я думаю позиция 2 будет самое то - посмотрел - сохранил.
Jestik 15 апреля 2016 в 09:05 +1
Поддерживаю
Val 16 апреля 2016 в 12:51 +1
Cтудия Sitestroi:
Отличное дополнение!
Дополнение это слишком громко - очередной хак, с претензией на pull request laugh

Поменял вывод предпросмотра на демо во вторую позицию.
Согласен, здесь более логично увидеть превьюшку.
WebMan 16 апреля 2016 в 14:10 +1
Позиция 3 точно не логична и неудобна - можно исключить.

При размещении и в позиции 1, и в 2, всё равно приходится прокручивать и область предпросмотра, и форму до кнопки "Сохранить". Также нужно учитывать, что обычно предпросмотр используется там, где текст по высоте больше, чем форма. Поэтому на мой взгляд, правильнее оставить предпросмотр в позиции 1. Посмотрел весь текст сверху вниз, что-то решил изменить и форма уже сразу перед глазами - удобно и без лишних движений. Если всё подходит, то кнопка "Сохранить" тут же под формой - прокручивать если и нужно, то невысокую форму и вниз, а не большой текст и в обратном направлении. А если делать в п.2, то для изменения нужно прокручивать весь текст обратно до верха, потом прокрутить форму и там менять в форме - это нелогично, это лишние манипуляции и неудобно.

Да и привычнее видеть кнопку "Сохранить" под формой ввода, а не под текстом. Ведь сохраняем мы не просмотренный текст, а то, что набрано в форме. Если предпросмотр будет в п.2, то при изменении текста в форме и неизменности текста предпросмотра могут быть непонятки: что мы сохраняем, просмотренный текст, раз кнопка "Сохранить" под ним, или набранное в форме? Так что и с этой точки зрения удобнее делать предпросмотр сверху в позиции 1, как Val сразу интуитивно и сделал.
Val 16 апреля 2016 в 22:40 +1
WebMan:
Посмотрел весь текст сверху вниз, что-то решил изменить и форма уже сразу перед глазами - удобно и без лишних движений. Если всё подходит, то кнопка "Сохранить" тут же под формой - прокручивать если и нужно, то невысокую форму и вниз, а не большой текст и в обратном направлении.
Действительно, если вдуматься, UX лежит именно в описанной вами плоскости))

WebMan:
Да и привычнее видеть кнопку "Сохранить" под формой ввода, а не под текстом. Ведь сохраняем мы не просмотренный текст, а то, что набрано в форме.
Тоже согласен с этим

WebMan, а как вы смотрите на модальное окно предпросмотра?
Zau4man 15 апреля 2016 в 10:07 +1
Имхо, надо пилить предпросмотр полей fieldText и все. Остальные не трогать.
Какая разница пользователю как будут выглядеть теги, или заголовок. Или прикрепленный к материалу файл. Или карта из поля карты.

Избавьте разработчиков и себя от ненужной возни. Сделайте предпросмотр для поля html.
Val 15 апреля 2016 в 10:34 +2
Если мы юзаем WYSIWYG редакторы для html-полей, зачем тогда вообще предпросмотр? IMHO просматривая конечный результат мы хотим увидеть до публикации как все должно смотреться, возможно пробежаться взглядом по тексту чтобы найти различные неточности и т.д. Да, все это можно сделать и без функционала предпросмотра))

Zau4man:
Избавьте разработчиков и себя от ненужной возни.
О кокой возне вы говорите? Если поле рендерится (а это большинство случаев) то ничего не надо специально делать, если нет, то решение остается на выбор разработчика. Хочет он показать результат в предпросмотре - внесет пару строк кода, считает что это лишнее - ничего писать не надо.

Примеры таких нестандартных полей, как уже упоминал в посте, мои опросы - в форме редактирования пользователь видит менеджер опросов, т.е. список их заголовков, а в записи - уже выводятся полноценные вопросы с вариантами ответов. Или недавно опубликованное поле Loadыря "Список количества", и множество других подобных полей. Это примеры полей которые интересно посмотреть в "препродакшене", т.е. перед публикацией записи.
kirkr 15 апреля 2016 в 12:33 +1
Val, к сожалению редакторы не дают возможность видить все, так как не всегда корректно форматируют. Поэтому данное дополнение очень хорошее решение, если оно будет доступно людям, то ничего плохого не произойдет.

Можно сделать предпросмотр и сейчас, не ставя публиковать в статьях (типа черновик). Но если решение будет универсальным, то бует удобно. даже пускай если будет открываться в отдельном окне.
Val 15 апреля 2016 в 13:08 +1
Без публикации получается, как вы правильно заметили, что то вроде черновика)) И основной момент здесь в том что запись сохраняется в БД.
kirkr:
Но если решение будет универсальным, то бует удобно. даже пускай если будет открываться в отдельном окне.
Именно универсальности я и хочу добиться - поэтому и опубликовал текущий пост с вопросами.
Вы за вариант модального окна?
Val 15 апреля 2016 в 13:22 +1
Нашел косячек в положении кнопки "Предпросмотр". Если включить опцию модерации контента перед публикацией, то при добавлении записи показывается надпись "Материал будет опубликован после проверки модератором", которая налазит на кнопку "Предпросмотр".
Отсюда вопрос: куда девать эту пимпу?
Также есть предложение при включенной опции премодерации, переименовывать кнопку "Сохранить" в "Отправить на модерацию", тогда и надпись о публикации после проверки можно убрать совсем, или выводить ее в виде хинта под кнопкой. Получается более наглядный UX))
""
Изображение уменьшено. Щелкните, чтобы увидеть оригинал.
GluK 15 апреля 2016 в 13:45 0
сделай слева от "сохранить"
Val 15 апреля 2016 в 14:12 +1
Слева от "Сохранить" рассматривал такой вариант в самом начале. Меня он смущает последовательностью кнопок с точки зрения UX и UI. Кнопка "Сохранить" здесь главная - это основное действие на странице, поэтому она и выделена цветом и должна стоять по ходу движения глаз и мыши на первом месте.
Вот такой вариант мне кажется неуместным:
""
Изображение уменьшено. Щелкните, чтобы увидеть оригинал.

А как поместить "Предпросмотр" справа от "Сохранить" (не выравнивание по правому краю, а следом за сохранить) без костылей я пока не знаю.
Val 15 апреля 2016 в 14:33 +6
В идеале считаю такой вариант лучшим:
""
Изображение уменьшено. Щелкните, чтобы увидеть оригинал.

joke
Def 29 мая 2016 в 23:20 0
а передаются только поля или свойства тоже передаются? и можно ли в определенных типах контента убирать кнопку предпросмотра?)
Val 30 мая 2016 в 10:49 +1
Схема работы предпросмотра полностью совпадает с сохранением записи типа контента, но непосредственно перед записью данных в БД они (данные) отправляются через рендер обратно клиенту и выводятся в требуемое место. Таким образом, передается ровно так как в движке изначально реализовано.
Зайдите на демо-сайт и потестируйте =)
vikont 4 июня 2016 в 00:13 +1
А куда само дополнение делось?
Есть только пункт 1 описания со Спойлером и все!
Val 4 июня 2016 в 16:07 +1
Проблему поправили smile
vikont 4 июня 2016 в 20:36 +1
Спасибо!
В отдельный компонент когда завернете?
Хорошее дело. А вот Хаки только головняк добавляют.
vikont 5 июня 2016 в 03:40 0
У меня не заработал. Все прописал как в описании - кнопки нет
Перенес настройки из Дефолтного шаблона в свой кнопка появилась, но не работает!
Возможно неправильно прописал код js/ Куда лучше всего вносить код из 4-го пункта и в какой шаблон?
Val 5 июня 2016 в 21:44 +1
В данном случае кнопку гораздо правильнее выводить не через "append_html", а напрямую в шаблоне формы рядом с кнопкой сабмита.
vikont:
Куда лучше всего вносить код из 4-го пункта и в какой шаблон?
Нужно вносить в тот файл который у вас грузится клиенту (вероятнее всего это файл с вашего шаблона).
Зайдите на демосайт и посмотрите как там реализовано.
vikont 5 июня 2016 в 22:22 0
Мне конечно приятно, что считают знатоком РНР, но увы, это совсем не так!
Поэтому будет проще, если как выше напишите что и куда вставить.
Надеюсь когда все получится, сделать патч к Компоненту Мои патчи, чтобы другие могли воспользоваться Хаком без головной боли.
Думаю именно по этой причине не появилось много заинтересованных. Сразу не пошло...
Val 6 июня 2016 в 21:56 +1
vikont, готов вам помочь, но напишите мне подробнее что у вас не получается. Просто переписывать пост сюда не вижу смысла. Вроде старался максимально подробно описать с указанием где какую строчку заменить и на что и как))
Попробуйте еще раз на дефолтном шаблоне чистого движка. Если получится, то нужно искать проблему в стороннем шаблоне (возможно что-то не вписали или не туда вписали и, например, просто не выводится кнопка, а функционал присутствует) ?
Про демосайт, я имел ввиду, посмотреть через devtools что и как, например, в скриптах и html-коде страниц. Но там все ровно так как и описано в тексте поста.
Обращайтесь в личку по возникшим трудностям, победим их вместе smile
Val 5 июня 2016 в 21:39 +1
Делать в виде компонента данный функционал не планируется, в первую очередь по причине невозможности обойтись без хаков. Идея предпросмотра была опубликована для получения фибдека от сообщества и формирования своеобразного видения. Судя по всему функционал не вызвал особого интереса у большинства, поэтому заинтересоанные могут пользоваться хаком.
vikont 5 июня 2016 в 22:16 +2
Тогда ему самое место в коробочке! Лишним предосмотр бывает только у тех кто мало постит руками!
vikont 5 июня 2016 в 22:28 +1
Уважаемый Val, ну не каждый же такой въедливый как я и будет настойчиво допытываться как реализовать ваше предложение! smile
Сам предосмотр нужен! Конечно можно без него обойтись, да и без вилок обходятся..., но макароны удобнее вилкой...
Вот этот предосмотр, когда он есть, будет использоваться некоторыми на постоянной основе! Остальные ихредка по ходу жизни!
Так что в коробочку его и никаких хаков! Будет приятное расширение функционала с нуля.
Val 6 июня 2016 в 22:08 +1
Я тоже за предпросмотр)) Обязательно вернусь к нему в недалеком будущем.
p.s. а на счёт "коробки"... в последнее время какая-то тенденция нехорошая любое дополнение тянуть в коробку. Вот мне оно нужно, и вам и еще 5-10 пользователям, но абсолютному большинству нет! Так что до коробки надо еще дорасти =)
Но почва подготовлена, и семена посажены...
Михаил 30 августа 2016 в 21:34 0
Уважаемый Val, сделал по вашей инструкции - все работает, но есть два вопроса)
1 Использую редактор markitup, и в предпросмотре нет абзацев http://joxi.ru/p27R9Dgig6pDm7 Как это можно исправить?
2 Возможно ли, чтобыпосле того, как первый раз нажата кнопка Предпросмотр, вместе с формой (и после нее) добавилась еще одна кнопка Сохранить?
Val 30 августа 2016 в 22:41 +1
1. Тут скорее вопрос к самому редактору. Он также выводит текст без абзацев если просто нажать на кнопку "сохранить". Глубоко не разбирался но предполагаю что абзацы нужно заполнять в ручную - <br> или <p>...</p>

2. Если я правильно вас понял, можно добавить в конец функции getPreview() следующий код:
Код JAVASCRIPT:
  1. $form.find('.button-submit').clone().appendTo('#preview').click(function(){
  2. $form.submit();
  3. });
Михаил 30 августа 2016 в 23:15 0
Наверное, я не туда добавил (после 51 строки) т.к. по клику на Предпросмотр - кнопка Сохранить появляется в теле формы предпросомтра и сразу же исчезает.

Код PHP:
  1.  
  2. $form.after('<div id="preview"><div class="preview-title">'+preview_title+'</div>'+html.html()+'</div>');
  3. }, 'json');
  4.  
  5. $form.find('.button-submit').clone().appendTo('#preview').click(function(){
  6. $form.submit();
  7. });
  8.  
  9.  
Val 31 августа 2016 в 00:23 +2
попробуйте так:
Спойлер
Михаил 31 августа 2016 в 08:42 +1
Работает, спс.
Владимир 30 августа 2016 в 23:07 +2
Предпросмотр нужен! И желательно коробочный.
Bonefacei 31 августа 2016 в 01:32 +2
Этот бы функционал в коробку!
Саня 12 декабря 2017 в 10:38 0
А где его взять или скачать? Убрали из дополнений что ли?
ParadoX 11 июня 2018 в 18:37 0
К огромному сожалению в 2.9 не работает. Пользователи в один голос ругаются, что нет предпросмотра - очень неудобно постить, приходится каждый раз редактировать((