Как сделать опредленный режим отображения ноды в модальном окне.

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

Аватар пользователя VasyOK VasyOK 23 ноября 2020 в 18:28

Вывожу ноду в модальном окне через ссылку:
<a class="use-ajax"  data-dialog-type="modal" href="/mynode">Ссылка </a>

Можно ли, чтобы в модульном окне открывался определенный дисплей (тизер) ноды, а переходя на ноду (открытие ссылки в новой вкладке или новом окне) уже был другой дисплей ?

В D7 через colorbox_node это было возможно.

Комментарии

Аватар пользователя OldWarrior OldWarrior 23 ноября 2020 в 19:22

Судя по всему - невозможно и нода будет отображаться в default view mode. Однако, навскидку есть некоторые программные варианты.

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

Аватар пользователя vlucas vlucas 23 ноября 2020 в 20:01
1

Вполне логично, что так работает в контексте Modal API, т.к. вы в ссылке указываете открыть ноду - путь к ноде. Этот роут ведет на ноду в default (full).

Т.е. чтобы открыть что-то, надо чтобы у него был роут. Нету - можно создать.

Есть даже контриб для этого
https://www.drupal.org/project/view_mode_page

Аватар пользователя VasyOK VasyOK 24 ноября 2020 в 0:33

С этим модуль можно вывести по одной ссылке разные дисплеи в модале и без модала?
Пока что я вижу, что модуль задает страницу типа /%/teaser т.е. это уже другая ссылка. Или я не дочитал инструкцию?

Аватар пользователя vlucas vlucas 24 ноября 2020 в 0:35

модуль не пробовал, но по описанию он добавляет роуты нужные тебе.
А дальше, хочешь в модал, хочешь не в модал

Аватар пользователя OldWarrior OldWarrior 24 ноября 2020 в 3:38
1

vlucas wrote: С этим модуль можно вывести по одной ссылке разные дисплеи в модале и без модала?

Нет, ссылки будут отличаться для каждого дополнительного дисплея.
Пример:
mysite.com/mynode - дисплей 'default '
mysite.com/mynode/summary - дисплей 'summary'

Если прям очень необходимо, чтобы оба дисплея отображались по одной ссылке, то без программных костылей не обойтись - чтобы отделить AJAX-запрос (который суть модал и должен иметь отдельный view mode) от обычного запроса. Например, читать состояние серверной переменной $_SERVER['HTTP_X_REQUESTED_WITH'] и, если она установлена, то менять view mode.

Например, можно сбацать имплементацию хука hook_entity_view_mode_alter и устанавливать view mode 'по желанию', как-то так:

<?php
function YOUR_MODULE_entity_view_mode_alter(&$view_modeDrupal\Core\Entity\EntityInterface $entity$context) {
  if (
$entity->getEntityTypeId() == 'node' && $entity->bundle() == 'my_node_type' && isset($_SERVER['HTTP_X_REQUESTED_WITH']) && $_SERVER['HTTP_X_REQUESTED_WITH'] == 'XMLHttpRequest') {
    
$view_mode 'MY_CUSTOM VIEW MODE';
  }
}
?>
Аватар пользователя vlucas vlucas 24 ноября 2020 в 12:18

ну я про это ещё с первого комментария пишу ))
Modal API никак не связан с дисплеями того что он открывает. Ему вообще по барабану что открывать, что дадите )

Аватар пользователя OldWarrior OldWarrior 24 ноября 2020 в 16:43

vlucas wrote: ну я про это ещё с первого комментария пишу ))

Про что именно?

Васька, видимо, интересует (полагаю, по шаманским соображениям SEO или по каким-то другим сакральным причинам) есть ли возможность использовать один и тот же URL для разных режимов отображения ноды.
И (имхо) без программных решений в этом случае точно не обойтись.

Аватар пользователя gun_dose gun_dose 24 ноября 2020 в 17:05
1

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

Аватар пользователя VasyOK VasyOK 24 ноября 2020 в 17:13

Совершенно верно. Меня это интересует именно из здравого смысла. Сеошники меня не поймут, если будут адреса типа /*/teaser да и не нужны мне такие адреса.

Аватар пользователя OldWarrior OldWarrior 24 ноября 2020 в 18:34

Не думал в этом аспекте. Или Васёк не очень понятно изложил суть задачи.
Действительно, тогда даже странно, почему не предусмотрено штатных механизмов выбора view mode на этот случай.

Аватар пользователя vlucas vlucas 24 ноября 2020 в 19:06

Да не имеет это отношение к Modal API!
Цель - вывести что-то (абстрагируемся от конкретно чего - что правильно) в модальном окне. Это вовсе не сущность может быть

Аватар пользователя OldWarrior OldWarrior 24 ноября 2020 в 20:15

Ну это как бы всё понятно.
Но какой-то признак AJAX-запроса (входящий на целевой контроллер) можно было обеспечить. Соответственно, чтобы и canonical-роут нод мог бы его читать и предлагать выбор из режимов отображения. Задачка-то вроде получается из востребованных.

Аватар пользователя Andruxa Andruxa 24 ноября 2020 в 22:22
1

OldWarrior wrote: Но какой-то признак AJAX-запроса (входящий на целевой контроллер) можно было обеспечить

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

Поэтому, в таком случае, проще всего было бы сделать ссылку вида
<a href="/some/alias" data-modal-href="/modal/node/{nid}"> и по click'у делать запрос по урлу в data-modal-href
соотвественно, по роуту /modal/node/{nid} - отдавать рендер ноды без регионов.

Аватар пользователя OldWarrior OldWarrior 25 ноября 2020 в 3:58
1

Andruxa wrote: Можно добавить какой-нибудь кастомный заголовок в запрос... и т.д.

Да зачем так усложнять, Андрюха?
"Всё уже украдено до нас" ©, т.е.:
Symfony\Component\HttpFoundation\Request::isXmlHttpRequest() либо просто
<?php if ($_SERVER['HTTP_X_REQUESTED_WITH'] == 'XMLHttpRequest'){...} ?>

Остаётся "научить" контроллер canonical-роута читать этот флаг и понимать, когда нужно отдавать сущность в другом view mode (или просто юзать вышеприведённый hook_entity_view_mode_alter), а также программно добавить новый специальный режим отображения а-ля "ajax_modal" для связывания с AJAX-запросами. Или вообще добавить галку "Use on AJAX request only" в настройки каждого дисплея (что будет указывать на то, что данный дисплей обрабатывает исключительно AJAX-запросы).

И то и другое - в общем-то несколько строк PHP-кода. Это если говорить о патче ядра или новом контрибе.

Andruxa wrote: Поэтому, в таком случае, проще всего было бы сделать ссылку вида
<a href="/some/alias" data-modal-href="/modal/node/{nid}">...

Преимущество этой идеи в том, что можно указывать разные целевые AJAX-роуты даже для одного и того же типа материала (допустим, когда несколько типов модальных окон для нод и вызываются они каждый своей ссылкой). Но тогда и эти роуты нужно, разумеется, писать программно для каждого индивидуального случая. Либо (как предлагал vlucas выше) юзать https://www.drupal.org/project/view_mode_page.

Аватар пользователя Andruxa Andruxa 25 ноября 2020 в 9:36

OldWarrior wrote: HTTP_X_REQUESTED_WITH

Меня терзают смутные сомнения.
Далеко не всегда вебсервер предоставляет это значение, особенно в случае проксирования запросов nginx -> apache. Там в конфигах вирт.хостов порою такое написано - обнять и плакать.
Да и идея отдачи разного контента по одному урлу - попахивает клоакингом.

Аватар пользователя OldWarrior OldWarrior 25 ноября 2020 в 18:03

Andruxa wrote: Далеко не всегда вебсервер предоставляет это значение, особенно в случае проксирования запросов nginx -> apache.

Возможно это и так, но под апачем у меня пока не было проблем (я использую это решение на одной из своих самописных систем). Хотя в целом - да, всё же следует учитывать и то, что переменная может быть не выставлена сервером. Ниже gun_dose предлагает иной способ идентификации AJAX-запросов.

Andruxa wrote: Да и идея отдачи разного контента по одному урлу - попахивает клоакингом.

Это не то, чтобы совсем разный контент - скорее разные версии одного материала. Но если вспомнить страницы терминов (или даже просто /node) - там динамический контент на одном урле может меняться ежеминутно. Ну это так, мысли.

Аватар пользователя adano adano 24 ноября 2020 в 7:36

В D7 через colorbox_node это было возможно.

Уточни, каким образом...

Так можно же через шаблонный if (!$page) подсунуть разницу для модалки и full-mode...
Пихай туда что хочешь, хоть любимую вьюху.

P.S. Хотя, для ссылки use-ajax-modal это может и не прокатит.

Аватар пользователя VasyOK VasyOK 24 ноября 2020 в 12:14

Нет, если модал выводится по определенной ссылке, я могу и без всяких модулей это накликать.
Совершенно верно: "необходимо, чтобы оба дисплея отображались по одной ссылке"

adano, уточняю. В настройках отображения материала есть дисплей Colorbox - в нем и настривается.

Аватар пользователя gun_dose gun_dose 25 ноября 2020 в 10:26
1

Короче, я тут вспомнил одну вещь, которая ещё со времён семёрки не менялась. Для ссылок с классом use-ajax можно в качестве последнего компонента пути указывать "nojs", типа /node/1/nojs. Друпаловский аякс обрабатывает эти ссылки таким образом, что запрос отправляется на урл /node/1/ajax. И издревле (как минимум со времён семёрки) пути таких контроллеров принято объявлять как /node/{id}/{ajax}. И по второму параметру можно определять, аяксовый запрос или простой, и отдавать соответственно аякс-респонс либо редирект на ноду. Редирект конечно может быть не очень красиво, но можно на ссылки повесить nofollow.

Вторая вещь, которая касается ссылок с классом use-ajax: к урлу аяксового запроса добавляется параметр _wrapper_format=drupal_ajax. То есть если даже запрашивать ноду по её обычному урлу, то всё равно есть простой и понятный признак, чтобы идентифицировать запрос, как аяксовый. То есть, можно воспользоваться hook_entity_view_mode_alter, как предлагали выше, а в хуке уже смотреть гет-параметры запроса и подменять вью-мод.

Аватар пользователя OldWarrior OldWarrior 25 ноября 2020 в 17:55

gun_dose wrote: Вторая вещь, которая касается ссылок с классом use-ajax: к урлу аяксового запроса добавляется параметр _wrapper_format=drupal_ajax. То есть если даже запрашивать ноду по её обычному урлу, то всё равно есть простой и понятный признак, чтобы идентифицировать запрос, как аяксовый. То есть, можно воспользоваться hook_entity_view_mode_alter, как предлагали выше, а в хуке уже смотреть гет-параметры запр

По-моему, тоже вполне себе рабочее решение.
Тем более, что выше уже указывают на то, что отдача разного контента по одному урлу может быть аморальна. А тут вроде как урлы разные.

Аватар пользователя Skerth Skerth 25 ноября 2020 в 14:43

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

Ссылка в HTML:

<a href="/form/callback" class="btn use-ajax" data-dialog-type="modal" rel="nofollow">Обратный звонок</a>

THEME.theme

<?php
function HOOK_theme_suggestions_alter(array &$suggestions, array $vars$hook) {
  if (
in_array($hook, array('webform'))) {

    

$wrapper_format = \Drupal::request()->query->get('_wrapper_format');
    
$is_modal = \Drupal::request()->query->get('is_modal');

    if (

$wrapper_format == 'drupal_modal' || $is_modal) {
      
$suggestions[] = $hook '__' 'modal';

      return;
    }

    

$params = \Drupal::routeMatch()->getParameters();
    if (
$params->get('webform')) {
      
$suggestions[] = $hook '__' 'full';
    }
  }
}
?>

При ajax загрузки модального окна передавал Get параметр

template.js:

  // Update Drupal.Ajax.prototype.beforeSend only once.
  if (typeof Drupal.Ajax !== 'undefined' && typeof Drupal.Ajax.prototype.beforeSubmitOriginal === 'undefined') {
    Drupal.Ajax.prototype.beforeSubmitOriginal = Drupal.Ajax.prototype.beforeSubmit;
    Drupal.Ajax.prototype.beforeSubmit = function (form_values, element_settings, options) {
      if (this.$form.hasClass('webform-modal')) {
        options.url += '&is_modal=1';
      }
      return this.beforeSubmitOriginal();
    };
  }

После чего смог нормально использовать разные Twig шаблоны для модалки и странички:

  • webform--modal.html.twig
  • webform--full.html.twig

Не претендую на правильность, но работает как часы)

P.s. в 7-ке было проще с колорбоксом. Можно было условия на view_mode прописать в самом файле темизации.

Аватар пользователя VasyOK VasyOK 23 декабря 2020 в 15:09

Видимо пришлось вернуться к теме вопроса.
Много сверху всего написано, я так сходу в это не въеду, извините за повторы.

Итак я могу сформитровать ссылку вида <a href="/some/alias" data-modal-href="/modal/node/{nid}">, где /modal/node/{nid} - путь сформированный вьюхой (для этого же не принципиален модуль view_mode_page?)

И как выводить в модале именно то что, что в data-modal-href ?

Аватар пользователя Andruxa Andruxa 23 декабря 2020 в 22:11

Как-то так:

$("a[data-modal-href]").click(function(){
  $.colorbox({href: $(this).data("modal-href")});
});

мог ошибиться, давно не брал в руки джаваскрпт.

Аватар пользователя Andruxa Andruxa 24 декабря 2020 в 12:02

А чем попап сделан?

в общем случае как-то так:

$.get($(this).data("modal-href"), function(data){
  $("popup-content-selector").html(data);
  $("popup").trigger("popup");
});
Аватар пользователя VasyOK VasyOK 24 декабря 2020 в 12:04

Попап сделан через ui-dialog, который встроен в Drupal. Эта конструкция работает по умолчанию (в темах ядра):
<a class="use-ajax"  data-dialog-type="modal" href="/mynode">Ссылка </a>

Аватар пользователя VasyOK VasyOK 25 декабря 2020 в 18:15

что-то не получается через "html(data).dialog()"

Спсциалисты по JS и ui-dialog, посдскажите.

Ссылка
<a class="use-ajax"  data-dialog-type="modal" href="/mynode" data-modal-href="/modal/node/1">Ссылка </a>

Как сделать, чтобы по клику открывалось то, что в data-modal-href?

$("a[data-modal-href]").click(function() {
                var url = $(this).attr("data-modal-href");                
                /*тут вроде строчку дописать. как открыть ссылку с полученным url?*/
});
Аватар пользователя VasyOK VasyOK 26 декабря 2020 в 3:14

Еще так пробовал

 $("a[data-modal-href]").click(function() {
                url = $(this).attr("data-modal-href");
                $('<div class="ui-dialog"></div>').load(url).dialog();
});

Оно, то работает, но выводит вместе с контентом еще и регионы темы. + не может нормально завершить операцию.