Конструктор карт 2GIS - как встроить в Drupal 7

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

Аватар пользователя chelwolf chelwolf 8 февраля 2023 в 11:10

У 2ГИС есть виджет карт для сайта (https://widgets.2gis.com/firmsconstructor/project/32), а есть конструктор карт, где можно создавать маркеры и делать много чего ещё (https://makemap.2gis.ru/). Речь пойдёт именно о конструкторе, я сделал в нём карту и получил следующий код для встраивания:

<iframe id="map_324866338" frameborder="0" width="100%" height="600px" sandbox="allow-modals allow-forms allow-scripts allow-same-origin allow-popups allow-top-navigation-by-user-activation"></iframe><script type="text/javascript">(function(e,t){var r=document.getElementById(e);r.contentWindow.document.open(),r.contentWindow.document.write(atob(t)),r.contentWindow.document.close()})("map_324866338", "PGJvZHk+PHN0eWxlPgogICAgICAgIGh0bWwsIGJvZHkgewogICAgICAgICAgICBtYXJnaW46IDA7CiAgICAgICAgICAgIHBhZGRpbmc6IDA7CiAgICAgICAgfQogICAgICAgIGh0bWwsIGJvZHksICNtYXAgewogICAgICAgICAgICB3aWR0aDogMTAwJTsKICAgICAgICAgICAgaGVpZ2h0OiAxMDAlOwogICAgICAgIH0KICAgICAgICAuYnVsbGV0LW1hcmtlciB7CiAgICAgICAgICAgIHdpZHRoOiAyMHB4OwogICAgICAgICAgICBoZWlnaHQ6IDIwcHg7CiAgICAgICAgICAgIGJveC1zaXppbmc6IGJvcmRlci1ib3g7CiAgICAgICAgICAgIGJhY2tncm91bmQtY29sb3I6ICNmZmY7CiAgICAgICAgICAgIGJveC1zaGFkb3c6IDAgMXB4IDNweCAwIHJnYmEoMCwgMCwgMCwgMC4yKTsKICAgICAgICAgICAgYm9yZGVyOiA0cHggc29saWQgIzAyODFmMjsKICAgICAgICAgICAgYm9yZGVyLXJhZGl1czogNTAlOwogICAgICAgIH0KICAgICAgICAucGVybWFuZW50LXRvb2x0aXAgewogICAgICAgICAgICBiYWNrZ3JvdW5kOiBub25lOwogICAgICAgICAgICBib3gtc2hhZG93OiBub25lOwogICAgICAgICAgICBib3JkZXI6IG5vbmU7CiAgICAgICAgICAgIHBhZGRpbmc6IDZweCAxMnB4OwogICAgICAgICAgICBjb2xvcjogIzI2MjYyNjsKICAgICAgICB9CiAgICAgICAgLnBlcm1hbmVudC10b29sdGlwOmJlZm9yZSB7CiAgICAgICAgICAgIGRpc3BsYXk6IG5vbmU7CiAgICAgICAgfQogICAgICAgIC5kZy1wb3B1cF9oaWRkZW5fdHJ1ZSB7CiAgICAgICAgICAgIGRpc3BsYXk6IGJsb2NrOwogICAgICAgIH0KICAgICAgICAubGVhZmxldC1jb250YWluZXIgLmxlYWZsZXQtcG9wdXAgLmxlYWZsZXQtcG9wdXAtY2xvc2UtYnV0dG9uIHsKICAgICAgICAgICAgdG9wOiAwOwogICAgICAgICAgICByaWdodDogMDsKICAgICAgICAgICAgd2lkdGg6IDIwcHg7CiAgICAgICAgICAgIGhlaWdodDogMjBweDsKICAgICAgICAgICAgZm9udC1zaXplOiAyMHB4OwogICAgICAgICAgICBsaW5lLWhlaWdodDogMTsKICAgICAgICB9CiAgICA8L3N0eWxlPjxkaXYgaWQ9Im1hcCI+PC9kaXY+PHNjcmlwdCB0eXBlPSJ0ZXh0L2phdmFzY3JpcHQiIHNyYz0iaHR0cHM6Ly9tYXBzLmFwaS4yZ2lzLnJ1LzIuMC9sb2FkZXIuanM/cGtnPWZ1bGwmYW1wO3NraW49bGlnaHQiPjwvc2NyaXB0PjxzY3JpcHQ+KGZ1bmN0aW9uKGUpe3ZhciB0PUpTT04ucGFyc2UoZSkscj10Lm9yZGVyZWRHZW9tZXRyaWVzLG49dC5tYXBQb3NpdGlvbixhPXQuaXNXaGVlbFpvb21FbmFibGVkO2Z1bmN0aW9uIG8oZSl7cmV0dXJuIGRlY29kZVVSSUNvbXBvbmVudChhdG9iKGUpLnNwbGl0KCIiKS5tYXAoZnVuY3Rpb24oZSl7cmV0dXJuIiUiKygiMDAiK2UuY2hhckNvZGVBdCgwKS50b1N0cmluZygxNikpLnNsaWNlKC0yKX0pLmpvaW4oIiIpKX1ERy50aGVuKGZ1bmN0aW9uKCl7dmFyIGU9REcubWFwKCJtYXAiLHtjZW50ZXI6W24ubGF0LG4ubG9uXSx6b29tOm4uem9vbSxzY3JvbGxXaGVlbFpvb206YSx6b29tQ29udHJvbDohYX0pO0RHLmdlb0pTT04ocix7c3R5bGU6ZnVuY3Rpb24oZSl7dmFyIHQscixuLGEsbztyZXR1cm57ZmlsbENvbG9yOm51bGw9PT0odD1lKXx8dm9pZCAwPT09dD92b2lkIDA6dC5wcm9wZXJ0aWVzLmZpbGxDb2xvcixmaWxsT3BhY2l0eTpudWxsPT09KHI9ZSl8fHZvaWQgMD09PXI/dm9pZCAwOnIucHJvcGVydGllcy5maWxsT3BhY2l0eSxjb2xvcjpudWxsPT09KG49ZSl8fHZvaWQgMD09PW4/dm9pZCAwOm4ucHJvcGVydGllcy5zdHJva2VDb2xvcix3ZWlnaHQ6bnVsbD09PShhPWUpfHx2b2lkIDA9PT1hP3ZvaWQgMDphLnByb3BlcnRpZXMuc3Ryb2tlV2lkdGgsb3BhY2l0eTpudWxsPT09KG89ZSl8fHZvaWQgMD09PW8/dm9pZCAwOm8ucHJvcGVydGllcy5zdHJva2VPcGFjaXR5fX0scG9pbnRUb0xheWVyOmZ1bmN0aW9uKGUsdCl7cmV0dXJuInJhZGl1cyJpbiBlLnByb3BlcnRpZXM/REcuY2lyY2xlKHQsZS5wcm9wZXJ0aWVzLnJhZGl1cyk6REcubWFya2VyKHQse2ljb246ZnVuY3Rpb24oZSl7cmV0dXJuIERHLmRpdkljb24oe2h0bWw6IjxkaXYgY2xhc3M9J2J1bGxldC1tYXJrZXInIHN0eWxlPSdib3JkZXItY29sb3I6ICIrZSsiOyc+PC9kaXY+IixjbGFzc05hbWU6Im92ZXJyaWRlLWRlZmF1bHQiLGljb25TaXplOlsyMCwyMF0saWNvbkFuY2hvcjpbMTAsMTBdfSl9KGUucHJvcGVydGllcy5jb2xvcil9KX0sb25FYWNoRmVhdHVyZTpmdW5jdGlvbihlLHQpe2UucHJvcGVydGllcy5kZXNjcmlwdGlvbiYmdC5iaW5kUG9wdXAobyhlLnByb3BlcnRpZXMuZGVzY3JpcHRpb24pLHtjbG9zZUJ1dHRvbjohMCxjbG9zZU9uRXNjYXBlS2V5OiEwfSksZS5wcm9wZXJ0aWVzLnRpdGxlJiZ0LmJpbmRUb29sdGlwKG8oZS5wcm9wZXJ0aWVzLnRpdGxlKSx7cGVybWFuZW50OiEwLG9wYWNpdHk6MSxjbGFzc05hbWU6InBlcm1hbmVudC10b29sdGlwIn0pfX0pLmFkZFRvKGUpfSl9KSgneyJvcmRlcmVkR2VvbWV0cmllcyI6W3sidHlwZSI6IkZlYXR1cmUiLCJwcm9wZXJ0aWVzIjp7ImNvbG9yIjoiIzAyODFmMiIsInRpdGxlIjoiMEpyUXNOR0MwTDdRdWc9PSIsImRlc2NyaXB0aW9uIjoiIiwiekluZGV4IjoxMDAwMDAwMDAwfSwiZ2VvbWV0cnkiOnsidHlwZSI6IlBvaW50IiwiY29vcmRpbmF0ZXMiOls1OS45Nzg5MTQsNTUuMDQ3OTkxXX0sImlkIjo4NzB9XSwibWFwUG9zaXRpb24iOnsibGF0Ijo1NS4wNDc5MjMxMjg5NzQ0OSwibG9uIjo1OS45NzkzNzU2MDA4MTQ4MjYsInpvb20iOjE4fSwiaXNXaGVlbFpvb21FbmFibGVkIjp0cnVlfScpPC9zY3JpcHQ+PHNjcmlwdCBhc3luYz0iIiB0eXBlPSJ0ZXh0L2phdmFzY3JpcHQiIHNyYz0iaHR0cHM6Ly93d3cuZ29vZ2xldGFnbWFuYWdlci5jb20vZ3RhZy9qcz9pZD1VQS0xNTg4NjYxNjgtMSI+PC9zY3JpcHQ+PHNjcmlwdCB0eXBlPSJ0ZXh0L2phdmFzY3JpcHQiPihmdW5jdGlvbihlKXtmdW5jdGlvbiB0KCl7ZGF0YUxheWVyLnB1c2goYXJndW1lbnRzKX13aW5kb3cuZGF0YUxheWVyPXdpbmRvdy5kYXRhTGF5ZXJ8fFtdLHQoImpzIixuZXcgRGF0ZSksdCgiY29uZmlnIixlKSx3aW5kb3cuZ3RhZz10fSkoJ1VBLTE1ODg2NjE2OC0xJyk8L3NjcmlwdD48L2JvZHk+")</script>

Вставляю этот код через текстовое поле формата FullHtml при создании материала - в итоге карта не работает. В консоли только предупреждение: An iframe which has both allow-scripts and allow-same-origin for its sandbox attribute can remove its sandboxing.

Пробовал следующее:
1) Вставлял напрямую в шаблон tpl.php - результат тот же.
2) Ставил модуль Security Kit и давал разрешение на фреймы - не помогает.
3) Подключал JS 2GIS api (хотя в документации об этом не сказано) - не помогает.
4) Попробовал вставить код виджета на сторонний проект, где используется чистый html шаблон без движка - карта работает.

Подозреваю, что скрипт, который генерирует виджет, нужно как-то оборачивать в Drupal.behaviors (часть с (function(e,t)), вероятнее всего дело в этом. Я пробовал разные вариант, но у меня не заработало.

Подскажите как правильно сделать? У кого есть опыт интеграции таких карт в материал?

Лучший ответ

Аватар пользователя chelwolf chelwolf 10 февраля 2023 в 14:16

В ходе детального тестирования выяснилось, что скрипт не успевает сработать из-за библиотеки Simplebar (https://grsmto.github.io/simplebar/), которую мы используем для настройки нестандартного скроллинга на всем сайте. Для этого сразу после body мы оборачиваем контент в div с классом "scrollWrapper", который и инициализирует скрипт.

Почему так происходит - вопрос к 2GIS. Яндекс и Гугл исправно работают.

Решили котсылём:
1) Делаем два поля в админ панели: код iframe (activity_map_iframe) и код js (activity_map_js) для карты
2) Создаём материал и вставляем код из конструктора 2GIS в соответствующие поля, убираем обёртку скроптов (тег scripts)
3) В коде выводим эти поля и делаем небольшую задержку в срабатывании JS:

<?php
$activity_map_js 
field_view_field('node'$node"field_activity_map_js", array('label' => 'hidden'));
$activity_map_iframe field_view_field('node'$node"field_activity_map_iframe", array('label' => 'hidden'));
<?
php if (!empty($activity_map_iframe)): ?>
                    <?php echo render($activity_map_iframe); ?>
                <?php endif ?>
                <?php if (!empty($activity_map_js)): ?>
                    <script type="text/javascript">
                        (function ($) {
                          Drupal.behaviors.GisMapInit = {
                            attach : function(context, settings) {
                                setTimeout(() => {
                                    <?php echo render($activity_map_js); ?>
                                }, 5000)
                              }
                            };
                        })(jQuery);
                    </script>
                <?php endif ?>

Также не забываем создать шаблон для полей с названием:
field--field_activity_map_iframe.tpl.php
field--field_activity_map_js.tpl.php

Внутри которых оставляем только:

<?php foreach ($items as $delta => $item): ?>
    <?php print render($item); ?>
<?php 
endforeach; ?>

Это избавит от лишней обёртки, которая поломает код.

Комментарии

Аватар пользователя Selpi Selpi 8 февраля 2023 в 11:18

FullHTML у вас скорее всего все-равно имеет фильтрацию/редактор. Создайте отдельный формат текста вообще без фильтров, только дайте к нему доступ исключительно админам, так как иначе все желающие смогут встраивать произвольный код в страницы. (Ради эксперимента вставил вашу карту и она без проблем работает)

По поводу CORS, есть одноименный модуль, либо оно настраивается на уровне веб сервера.

Аватар пользователя chelwolf chelwolf 8 февраля 2023 в 11:26

Чтобы исключить фильтрацию через формат текста - вставлял напрямую в шаблон

Поставил модуль CORS с доступом "*|*" - не сработало

Аватар пользователя Selpi Selpi 8 февраля 2023 в 11:30

Проверьте, что скрипт вставляется целиком и не портится форматированием. Если бы у вас была проблема с CORS, в консоли была бы ошибка и блокировка скрипта, а не предупреждение.

Аватар пользователя chelwolf chelwolf 8 февраля 2023 в 13:25

Проверил, не портится форматированием. В итоге получаю пустую обёртку. Написал в техподдержку 2gis, возможно они помогут.

У вас в каком виде получилось вывести эту карту в Drupal 7? Используйте последнюю версию ядра?

Аватар пользователя Selpi Selpi 8 февраля 2023 в 13:28

Я проверял на друпале 6, 7 и 9, все последних версий. Код вставлялся в материал типа Страница текстовым фильтром "Без форматирования". Карта ваша подгружалась с катком каким-то в центре.

Аватар пользователя chelwolf chelwolf 10 февраля 2023 в 14:16

В ходе детального тестирования выяснилось, что скрипт не успевает сработать из-за библиотеки Simplebar (https://grsmto.github.io/simplebar/), которую мы используем для настройки нестандартного скроллинга на всем сайте. Для этого сразу после body мы оборачиваем контент в div с классом "scrollWrapper", который и инициализирует скрипт.

Почему так происходит - вопрос к 2GIS. Яндекс и Гугл исправно работают.

Решили котсылём:
1) Делаем два поля в админ панели: код iframe (activity_map_iframe) и код js (activity_map_js) для карты
2) Создаём материал и вставляем код из конструктора 2GIS в соответствующие поля, убираем обёртку скроптов (тег scripts)
3) В коде выводим эти поля и делаем небольшую задержку в срабатывании JS:

<?php
$activity_map_js 
field_view_field('node'$node"field_activity_map_js", array('label' => 'hidden'));
$activity_map_iframe field_view_field('node'$node"field_activity_map_iframe", array('label' => 'hidden'));
<?
php if (!empty($activity_map_iframe)): ?>
                    <?php echo render($activity_map_iframe); ?>
                <?php endif ?>
                <?php if (!empty($activity_map_js)): ?>
                    <script type="text/javascript">
                        (function ($) {
                          Drupal.behaviors.GisMapInit = {
                            attach : function(context, settings) {
                                setTimeout(() => {
                                    <?php echo render($activity_map_js); ?>
                                }, 5000)
                              }
                            };
                        })(jQuery);
                    </script>
                <?php endif ?>

Также не забываем создать шаблон для полей с названием:
field--field_activity_map_iframe.tpl.php
field--field_activity_map_js.tpl.php

Внутри которых оставляем только:

<?php foreach ($items as $delta => $item): ?>
    <?php print render($item); ?>
<?php 
endforeach; ?>

Это избавит от лишней обёртки, которая поломает код.

Аватар пользователя chelwolf chelwolf 22 марта 2023 в 11:45

Дополню ветку по этой проблеме:

Проблему работы 2GIS с библиотекой Simplebar удалось повторить без использования Drupal. Если карту вставлять внутри DIV, который использует библиотеку, она не отображается: https://codepen.io/denton444/pen/rNZZmoY

Обратная связь от разработчиков: «Разработчики проверили Ваш код. К сожалению, мы не можем гарантировать совместимость нашего кода карты со сторонними библиотеками. Применяемое Вами в текущий момент времени решение - единственный вариант устранить данную проблему.» (тикет JIRA SUPPORT-831645)

Поэтому используйте Google или Яндекс. Если принципиально необходим 2GIS - используйте код выше, в качестве времени задержки можно ставить "0" - тогда карта все ровно сработает, даже на медленном интернете 3G.