Вывод виджетов с помощью свайп

+2
204
Вывод виджетов с помощью свайп

Я как всегда с фишкой для моб телефонов. Свайп окно всеми известно кто пользуется мобильными приложениями. 

1) берем любой виджет заходив во вкладку шаблона и выбираем это ( см. скрин)

Изображение 

2 берем и вставляем этот код :

  1. <style>
  2. /* Общие стили для затемняющего фона */
  3. .adaptive-modal {
  4. display: none;
  5. position: fixed;
  6. z-index: 2000;
  7. left: 0;
  8. bottom: 0;
  9. width: 100%;
  10. height: 100%;
  11. background-color: rgba(0, 0, 0, 0.4);
  12. }
  13.  
  14. /* Стили для мобильных устройств (по умолчанию) */
  15. .adaptive-modal-container {
  16. position: fixed;
  17. left: 0;
  18. bottom: -100%;
  19. width: 100%;
  20. max-height: 95vh; /* Максимальная высота 90% экрана */
  21. background-color: #fff;
  22. display: flex;
  23. flex-direction: column;
  24. box-shadow: 0 -2px 10px rgba(0, 0, 0, 0.3);
  25. border-top-left-radius: 10px;
  26. border-top-right-radius: 10px;
  27. transition: bottom 0.2s ease, transform 0.05s ease;
  28. will-change: transform;
  29. }
  30. /* При открытии на мобильных: окно поднимается вверх */
  31. .adaptive-modal.show .adaptive-modal-container {
  32. bottom: 0;
  33. }
  34.  
  35. /* Шапка окна: фиксированная, без прокрутки */
  36. .adaptive-modal-titlebar {
  37. position: relative;
  38. padding: 20px;
  39. padding-top: 40px; /* Отступ для полоски */
  40. flex-shrink: 0;
  41. cursor: grab;
  42. }
  43.  
  44. /* Прокручиваемая область с содержимым */
  45. .adaptive-modal-body {
  46. padding: 0 20px 20px;
  47. overflow-y: auto;
  48. -webkit-overflow-scrolling: touch;
  49. flex: 1;
  50. }
  51.  
  52. /* Кнопка закрытия (отображается в шапке) */
  53. .adaptive-modal-close {
  54. position: absolute;
  55. top: 20px;
  56. right: 20px;
  57. cursor: pointer;
  58. font-size: 24px;
  59. }
  60.  
  61. /* Полоска для приглашения к свайпу (видна только на мобильных) */
  62. .adaptive-swipe-indicator {
  63. position: absolute;
  64. top: 10px;
  65. left: 50%;
  66. transform: translateX(-50%);
  67. width: 50px;
  68. height: 5px;
  69. background-color: #ccc;
  70. border-radius: 3px;
  71. }
  72.  
  73. /* Стили для десктопных устройств */
  74. @media (min-width: 768px) {
  75. .adaptive-modal {
  76. justify-content: center;
  77. align-items: center;
  78. }
  79. .adaptive-modal-container {
  80. position: relative;
  81. max-height: none;
  82. max-width: 500px;
  83. width: 100%;
  84. border-radius: 10px;
  85. box-shadow: 0 2px 10px rgba(0, 0, 0, 0.3);
  86. bottom: auto;
  87. transform: none;
  88. transition: opacity 0.2s ease;
  89. opacity: 0;
  90. flex-direction: column;
  91. }
  92. .adaptive-modal.show .adaptive-modal-container {
  93. opacity: 1;
  94. }
  95. .adaptive-swipe-indicator {
  96. display: none;
  97. }
  98. .adaptive-modal-titlebar {
  99. padding-top: 20px;
  100. cursor: default;
  101. }
  102. }
  103. </style>
  104.  
  105. <!-- Пример кнопки для открытия окна (если требуется) -->
  106. <!--<button id="openAdaptiveModal">Открыть окно</button>-->
  107.  
  108. <div id="adaptiveModal" class="adaptive-modal">
  109. <div class="adaptive-modal-container" id="adaptiveModalContainer">
  110. <div class="adaptive-modal-titlebar" id="adaptiveModalTitlebar">
  111. <div class="adaptive-swipe-indicator"></div>
  112. <span class="adaptive-modal-close"></span>
  113. </div>
  114. <div class="adaptive-modal-body" id="adaptiveModalBody">
  115. {body}
  116. </div>
  117. </div>
  118. </div>
  119.  
  120. <script>
  121. document.addEventListener("DOMContentLoaded", function() {
  122. const openModalButton = document.getElementById("openAdaptiveModal");
  123. const modal = document.getElementById("adaptiveModal");
  124. const modalContainer = document.getElementById("adaptiveModalContainer");
  125. const modalBody = document.getElementById("adaptiveModalBody");
  126. const titlebar = document.getElementById("adaptiveModalTitlebar");
  127. const closeButton = document.querySelector(".adaptive-modal .adaptive-modal-close");
  128.  
  129. let startY = 0,
  130. translateY = 0,
  131. threshold = 200; // Порог для закрытия окна при свайпе по контейнеру
  132.  
  133. // Переменные для свайпа по шапке
  134. let headerStartY = 0,
  135. headerTranslateY = 0,
  136. headerThreshold = 150; // Порог для свайпа по шапке (более чувствительный)
  137.  
  138. /* Функция открытия модального окна */
  139. function openModal() {
  140. if (window.innerWidth >= 768) {
  141. modal.style.display = "flex";
  142. } else {
  143. modal.style.display = "block";
  144. }
  145. document.body.style.overflow = "hidden";
  146. setTimeout(() => {
  147. modal.classList.add("show");
  148. }, 10);
  149. }
  150.  
  151. /* Функция закрытия модального окна */
  152. function closeModal() {
  153. modal.classList.remove("show");
  154. document.body.style.overflow = "";
  155. modalContainer.style.transform = "";
  156. setTimeout(() => {
  157. modal.style.display = "none";
  158. }, 200);
  159. }
  160.  
  161. /* Сброс положения контейнера при свайпе по контейнеру */
  162. function resetModalContent() {
  163. modalContainer.style.transition = "transform 0.05s ease";
  164. modalContainer.style.transform = "translateY(0)";
  165. setTimeout(() => {
  166. modalContainer.style.transition = "transform 0.05s ease";
  167. }, 50);
  168. }
  169.  
  170. /* Сброс положения контейнера при свайпе за шапку - минимальные задержки */
  171. function resetHeaderSwipe() {
  172. modalContainer.style.transition = "transform 0.05s ease";
  173. modalContainer.style.transform = "translateY(0)";
  174. setTimeout(() => {
  175. modalContainer.style.transition = "transform 0.05s ease";
  176. }, 50);
  177. }
  178.  
  179. /* Обработчики для шапки (titlebar) для свайпа независимо от содержимого */
  180. titlebar.addEventListener("touchstart", function(e) {
  181. titlebar.style.transition = "none";
  182. headerStartY = e.touches[0].clientY;
  183. e.stopPropagation();
  184. });
  185.  
  186. titlebar.addEventListener("touchmove", function(e) {
  187. const currentY = e.touches[0].clientY;
  188. headerTranslateY = currentY - headerStartY;
  189. if (headerTranslateY > 0) {
  190. modalContainer.style.transform = "translateY(" + headerTranslateY + "px)";
  191. }
  192. e.stopPropagation();
  193. });
  194.  
  195. titlebar.addEventListener("touchend", function(e) {
  196. if (headerTranslateY > headerThreshold) {
  197. closeModal();
  198. } else {
  199. resetHeaderSwipe();
  200. }
  201. headerStartY = 0;
  202. headerTranslateY = 0;
  203. e.stopPropagation();
  204. });
  205.  
  206. /* Обработчики для области контейнера, если касание происходит вне шапки */
  207. modalContainer.addEventListener("touchstart", function(e) {
  208. if (e.target.closest('.adaptive-modal-titlebar')) return;
  209. if (modalBody.scrollTop > 0) {
  210. startY = null;
  211. return;
  212. }
  213. modalContainer.style.transition = "none";
  214. startY = e.touches[0].clientY;
  215. });
  216.  
  217. modalContainer.addEventListener("touchmove", function(e) {
  218. if (startY === null) return;
  219. const currentY = e.touches[0].clientY;
  220. translateY = currentY - startY;
  221. if (translateY > 0) {
  222. modalContainer.style.transform = "translateY(" + translateY + "px)";
  223. }
  224. });
  225.  
  226. modalContainer.addEventListener("touchend", function() {
  227. if (startY === null) return;
  228. if (translateY > threshold) {
  229. closeModal();
  230. } else {
  231. resetModalContent();
  232. }
  233. startY = 0;
  234. translateY = 0;
  235. });
  236.  
  237. if (openModalButton) {
  238. openModalButton.addEventListener("click", openModal);
  239. }
  240.  
  241. closeButton.addEventListener("click", closeModal);
  242.  
  243. window.addEventListener("click", function(event) {
  244. if (event.target === modal) {
  245. closeModal();
  246. }
  247. });
  248.  
  249. // Если окно должно открываться автоматически, можно вызвать openModal() здесь
  250. // openModal();
  251. });
  252. </script>

Ничего в нем не меняем {body} уже внутри

3 Сохраняем и размещаем свой виджет в любое место кроме хеда и футера ( просто в любое, все равно он скрыт)

С виджетом все!

Далее с помощью виджета или в тело шаблона вставляете код кнопки для вызова этого меню (Виджет с кнопкой можете размещать в любое месте, даже футер или хедер

  1. <button id="openAdaptiveModal" class="btn btn-primary" style="margin-right: 5px"><svg class="icms-svg-icon w-16" fill="currentColor"><use href="/templates/modern/images/icons/solid.svg#ellipsis-h"></use></svg>Открыть окно</button>

Все! Кнопку размещай где угодно она вызовет виджет с этой страницы!

Что получаем ?

ИзображениеИзображениеИзображениеИзображение

свайп адаптирован под любую длину информации, свайпается ( скрывается) пальцем вниз.

ВАЖНО!
Если вы хотите много виджетов запаковать таким образом то нужно прописывать уникальные классы в коде выше ( что бы не было конфликтов) к каждому виджету.

Так же можно кто разберется упаковать любой контент. Короче сделал все по госту приложений.

На настройки самого виджета это не влияет, как настроете так он и будет в свайп окне

Кому что надо доработать упаковать, пишите. За донатик помогу ) 

Благодарность можно 89819178831 сбер.

0
Реклама Реклама #
+1
Fuze Fuze 2 дня назад #

Эммм. И ведь пойдут делать это. Ну ёмоё, ну почитайте вы матчасть, что такое HTML страница, её структура и т.п. Куда вы вставляете в шаблон контейнера теги html, body, head. Они у вас есть на странице.

Короче сделал все по госту приложений.

Ну да. Сочувствую кому вы будете помогать за донатик.

0
Happy Happy 2 дня назад #

Ок больше не буду делиться ничем ) 

Все кто прочитал этот пост, не делайте, сломаете сайт.

Делайте только то что заложено движком. 

Вместо критики лучше исправили и дали людям 

Если вы про лишние теги типа HTML и body, то это не стоило такого комментария. Их просто можно удалить 

С компа уберу эти теги. Тоже мне проблема 

+3
Fuze Fuze 2 дня назад #

Триггернуло что вы на серьёзном пишите про благодарность и помощь за донат.

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

Вы когда в чатгпт промпты пишите, уточняйте ему где вы хотите размещать код. Вот и эра ИИ получила человеческий фактор :)

Вместо критики лучше исправили и дали людям 

Я достаточно даю людям на безвозмездной основе. А в вашем посте вы не просили помощи.

0
Happy Happy 2 дня назад #

Теги убрал лишние. Причем тут gpt. Там больше моего чего его. Все лазят в интернете за поиском подсказок.

Я так и думал что вас зацепила именно помощь и фин поддержка ) меня тоже тригернуло. Это сплошь и рядом. Но, местные разработчики меня научили ценить свой труд и навык. ) 

Все не расстраивайтесь. Лояльней надо к тем кто учится программированию . 

В не в агрессивной форме выражать свою не приязнь. 

То что я предложил людям, работает? Работает! Это главное . 

0
Fuze Fuze 2 дня назад #

Я и не расстраиваюсь, не мой же пост :) Агрессию я точно в комментарий не закладывал.

Лояльней надо к тем кто учится программированию . 

Куда уж ещё лояльней. Пост на месте, на форуме вам отвечают, за постоянные орфографические ошибки молчат ;-) Вы правда не очень слушаете, а очень сложно помогать тому, кто помощь не принимает.

0
Happy Happy 2 дня назад #

Понял принял, да, писать я не очень умею грамотно. Иногда и т9 помогает их допускать 

+3
Pro AV Pro AV 2 дня назад #

Happy не обижайтесь, но критика про теги html, body правильная. Вам же не запрещают делиться полезными наработками. Просто примите положительную критику, поправьте код и будет всем хорошо от этого.

0
Happy Happy 2 дня назад #

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

+4
Pechora Pechora 2 дня назад #

Можно проще. Создать новую обертку для виджета — благо в системе есть такая возможность и использовать ее в любом виджете. Ну а кнопка — сделать для нее отдельный виджет, дел на 20 минут. Ну а в целом — хорошее практичное решение, просто немного не так поданное. 

0
Happy Happy 2 дня назад #

Подскажите пожалуйста на будущее или изменю пост как и где создаётся доп обёртка виджета ?

0
Fuze Fuze 2 дня назад #

docs.instantcms.ru/dev/widgets#обертка-виджета

При выводе на страницу шаблон виджета оборачивается (помещается внутрь) еще одним шаблоном – оберткой (wrapper). Оберток может быть несколько, они хранятся в папке /templates/{тема}/widgets. Например, тема default имеет три доступные обертки:

  • wrapper.tpl.php – используется по-умолчанию для всех виджетов. Содержит вывод заголовка и тела виджета, в которое помещается результат его работы;
  • wrapper_plain.tpl.php – «пустая» обертка, просто выводит тело виджета, не добавляя никаких дополнительных тегов вокруг;
  • wrapper_tabbed.tpl.php – обертка, поддерживающая вывод сразу нескольких виджетов (каждый в отдельной вкладке).

Видео-туториал: Создание виджета

0
Happy Happy 2 дня назад #

А вы об этом. Ну как я в посте об этом бы донес здесь? Если у каждого виджета своя структура, проще боди затолкать чем содержимое. А так я скинул универсальную верстку. 

0
Fuze Fuze 2 дня назад #

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

Вы не поняли, речь про обёртку. Это грубо говоря то, что вы прописали в «свой шаблон контейнера», только в файле, где можно подключить css/js файлы и доступен PHP.

Откройте указанные файлы и посмотрите что в них.

Еще от автора

Модальное окно свайп для вывода виджетов ч.2
Альтернативное решение для вывода виджетов на сайте
Виджет шаблон вывода категорий как на авито
Виджет шаблон вывода категорий как на авито
"Поделиться" на мобильном устройстве
Альтернативный способ поделиться страницей
Используя этот сайт, вы соглашаетесь с тем, что мы используем файлы cookie.