Разное

Шаблоны html: Распродажа HTML шаблоны

06.08.2023

Олдскульные HTML-шаблоны снова в моде! htmx и другие средства борьбы с javascript fatigue / Хабр

Рендеринг веб-страниц на стороне сервера, как знают многие читатели, вышел из употребления уже лет 10 как. «Перезагрузка страниц занимает ощутимое время, при этом пользователю не показывается даже спиннер! Что об этом говорят наши UX гайдлайны?» — таким вопросом задавались IT компании, принимая решение немедленно переезжать на single-page application.

Долгие годы никто не решался идти против веяний эпохи, пока лет 5 назад затишье не нарушил популярный веб-фреймворк Phoenix для языка Elixir (курица в капле на моей картинке). Его авторы считали, что обладающая сверхспособностями Erlang VM сумеет развеять предрассудки о якобы тормознутом серверном рендеринге.

Что ж — они не ошиблись: Phoenix Live View получила популярность, и теперь является для поклонников языка Elixir свидетельством преимуществ их рантайма. Сервер с клиентом общаются исключительно по вебсокету, html генерируется на сервере, коэффициент полезной информации в передаваемом трафике близок к 100%.

Видимо, у авторов Phoenix — не только вера в возможности рантайма, но ещё и прямые руки.

Возвращение к серверным шаблонам в Python сообществе стало для некоторых неожиданностью — я, конечно, про фреймворк htmx. Я смотрел их демо на DjangoCon — у них обычный сайт на django, они даже вебсокеты используют только в крайнем случае. Сайт, при этом, отзывчивый — перезагрузок страницы не происходит. (Как это работает? А что, так можно было?)

htmx — это вообще говоря, клиентский код — npm пакет. Он расширяет набор атрибутов в html тэгах для добавления логики (так же делают многие js-фреймворки). Каждый компонент — это такая псевдо-форма (иногда — настоящая форма). При определённых событиях, она шлёт на сервер запросы и — частый случай — перезаписывает своё содержимое на то, что пришло в ответе с сервера.

Вот пример простого компонента:

<div hx-target="this" hx-swap="outerHTML">
    <div><label>First Name</label>: Joe</div>
    <div><label>Last Name</label>: Blow</div>
    <div><label>Email</label>: joe@blow. com</div>
    <button hx-get="/contact/1/edit">
    Click To Edit
    </button>
</div>

Клик на кнопку заменяет поля на редактируемые, причём запрос на сервер, скорее всего, опять вернёт перезаписываемый компонент.

Почему эта магия работает? Потому что обычный reactive фреймворк делает, по сути, то же самое: при определённых событиях он вызывает логику, которая решает, изменится ли его состояние. Эта логика чаще всего предполагает запрос на сервер. А в htmx запрос на сервер делается всегда (и урл этого запроса явно прописан в соответствующем атрибуте).

<button hx-delete="/account">Соцсети не для меня</button>

В клиент-ориентированном фреймворке onclick был бы функцией, но без запроса на сервер всё равно бы не обошлось. А если нет разницы, зачем платить больше?

Ещё один пример: пусть у нас есть большая страничка, которую мы рендерим по серверному шаблону. Пусть она состоит из 5 визуальных компонентов. В результате действий пользователя, 2 компонента «сообразили», что информация в них больше не актуальна, и им нужен апдейт. Что они сделают? Конечно, гет-запрос на свой урл — и обновятся. Как компонент может сообразить, что ему нужен апдейт? По наступлению какого-то события. В htmx есть события на все случаи жизни — в том числе, можно заводить кастомные. Флаг наступления события может установить как предыдущий ответ с сервера — с помощью хедеров, так и нотификация по вебсокету, например.

Несмотря на простоту концепта, кроме htmx — такое впечатление, что никто до этого не додумался. (UPDATE: есть ещё Hotwire, который построен на похожих принципах)

В общем, если Вы сомневаетесь, использовать ли для django-админки SPA или серверные шаблоны — то не сомневайтесь и берите htmx. Если Вы адепт full-stack разработки на Python — тоже. Разделение труда — единственный весомый контраргумент для меня: серверные разработчики обычно не очень разбираются в вёрстке, вне зависимости от используемого языка.

А теперь — о самом интересном аспекте (на мой взгляд). Интересующиеся мобильной разработкой или читающие блог Яндекса, наверно, видели анонс о выходе в опен-сорс фреймворка divkit.

Кроме хабра и ютуба , о нём не очень много можно найти за пределами Яндекса (сам я не из Яндекса). В демо на ютубе девушка несколько раз упоминает фреймворк как «дивный кит». Лично мне название нравится — осталось только кита на логотипе фреймворка изобразить.

divkit — это что-то вроде такого универсального html (точнее, json), который он (divkit) умеет отображать на Android, iOS и на вебе. Таким образом, клиентский код сводится к минимуму, а задача сервера — как раз, формировать этот самый json. Получается, в Яндексе тоже используют рендеринг на сервере — для мобилок! (замахнулись на их нативную природу, не иначе)

Так вот, лично я считаю, что для мобилок серверный рендеринг ещё нужнее . Потому что у нас есть две разные платформы, как минимум — сами знаете, какие. Языки для разработки приложений у них — разные, графические библиотеки — тоже, причём, в случае Apple — закрытые. Какое в Яндексе нашли этому решение — писать максимум логики на стороне сервера, логично же?

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

Шаблоны. Руководство по языку YMapsML

Шаблоны позволяют сформировать произвольное HTML-представление геообъектов, балунов и хинтов. Например, если для отображения метки требуется использовать не только изображение с тенью, но и текст, необходимо сконструировать соответствующий его шаблон и задействовать его в стиле, использующемся для отображения метки.

Для определения шаблона используется элемент repr:Template, внутри которого в контейнере repr:text размещается HTML-код (тело шаблона).

<repr:Template gml:id="hintTemplate">
  <repr:text><div>Подсказка</div></repr:text>
</repr:Template>

В ряде случаев стиль не позволяет изменить отображения внешнего вида объекта никаким другим образом, кроме использования шаблона (см. например, repr:balloonContentStyle).

Шаблон является составной частью стиля, на который ссылается географический объект или коллекция.

При использовании шаблона доступ к значению любого XML-элемента, находящегося внутри элемента ymaps:GeoObject или ymaps:GeoObjectCollection осуществляется с помощью обращения к соответствующей переменной.

Для определения переменных используются строки вида $[имя_переменной|значение_по_умолчанию].

Имя переменной представляет собой местоположение этого XML-элемента внутри элемента, к которому применяется стиль. Местоположение задаётся последовательным перечислением названий всех родительских элементов и названия самого элемента, в качестве разделителя используется точка.

Допустим, описание географического объекта выглядит следующим образом:

<GeoObject>
  <gml:name>Офис Яндекса на улице Льва Толстого</gml:name>
  <gml:metaDataProperty>
     <AnyMetaData>
       <address>119021, Москва, ул. Льва Толстого, 16</address>
       <phone>+7 495 739-70-00</phone>
       <fax>+7 495 739-70-70</fax>
      </AnyMetaData>
  </gml:metaDataProperty>
  <gml:Point>
    <gml:pos>37.58828 55.733913</gml:pos>
  </gml:Point>
</GeoObject>

Тогда шаблон балуна, отображающего название объекта, адрес и телефон офиса, может выглядеть следующим образом.

<Template gml:id="balloonTemplate">
  <text>
    <div>
      <div>$[name]</div>
      <div>Адрес: $[metaDataProperty.AnyMetaData.address]</div>
      <div>Телефон: $[metaDataProperty.AnyMetaData.phone|не указан]</div>
  <text>
</Template>

Если не задать телефон офиса (т. е. удалить из приведённого примера элемент phone), то вместо номера телефона будет отображена строка «не указан».

Существует несколько правил, ограничивающих использование в тексте шаблона некоторых HTML-элементов и атрибутов. Список ограничений приведён в следующей таблице.

Ограничения на использование HTML в шаблонах
Игнорируются элементы script и iframe

Элементы script и iframe удаляются вместе с их содержимым.

Пример:

<div><script>alert(\"XSS\")"</script></div>

заменяется на

<div />
Игнорируются атрибуты, отвечающие за вызов обработчиков событий

Атрибуты, отвечающие за вызов обработчиков событий (onclick, onchange, onkeypress и т.

д.), удаляются из элементов вместе со своим содержимым.

Пример:

<divXSS\")">$[name]</div>

заменяется на

<div>$[name]</div>
Игнорируется атрибут class

Атрибут class удаляется из элементов вместе со своим содержимым.

Пример:

<div>$[name]</div>

заменяется на

<div>$[name]</div>
В URL ссылки атрибута href должна быть указана схема; схема javascript игнорируется

Атрибут href удаляется вместе со своим содержимым, если в URL ссылки не указана схема (протокол) или используется схема javascript.

Пример:

<a href="$[metaDataProperty.AnyMetaData.test.a]">link</a>

заменяется на

<a>link</a>
Игнорируется свойство position:absolute атрибута style

Если атрибут style содержит свойство position:absoute, данное свойство удаляется.

Пример:

<div>$[name]</div>

заменяется на

<div>$[name]</div>
Игнорируются CSS expressions

Если атрибут style содержит CSS expressions (поддерживаются только браузерами Internet Explorer до версии 8), он удаляется вместе со своим содержимым

Была ли статья полезна?

Блестящие — HTML-шаблоны

В большинстве случаев лучший способ создать пользовательский интерфейс приложения Shiny — создать его с помощью кода R, используя такие функции, как fluidPage() , div() и т. д. Однако иногда вам может понадобиться интегрировать Shiny с существующим HTML, и, начиная с Shiny 0.13 (и htmltools 0.3), это можно сделать с помощью HTML-шаблонов. Шаблоны можно использовать для создания полных веб-страниц, а также для создания HTML для компонентов, включенных в приложение Shiny.

Полные веб-страницы

Чтобы использовать шаблон HTML для пользовательского интерфейса, сначала создайте файл HTML в каталоге приложения на том же уровне, что и файлы ui. R , server.R или app.R (не в каталоге ). www/ подкаталог). Вот пример шаблона для полной веб-страницы, template.html :

.
 {% исходный %}



  <голова>
    {{ headContent() }}
  
  <тело>
    <дел>
      {{ кнопка }}
      {{ слайдер }}
    
{% выводить %}

А вот соответствующий ui.R , использующий шаблон:

 ## ui.R ##
htmlШаблон("template.html",
  кнопка = actionButton("действие", "Действие"),
  слайдер = слайдерВвод("х", "Х", 1, 100, 50)
) 

На что обратить внимание:

Шаблон представляет собой обычный HTML, за исключением частей {{ "{{ и " }}}} . Части в этих фигурных скобках — это код R, который оценивается при обработке шаблона.

headContent() должен быть помещен в раздел HTML-кода, если это полная HTML-страница (в отличие от компонента страницы, о котором мы поговорим позже). Это говорит Shiny, что сюда следует включить код различных заголовков Shiny.

В ui.R , htmlTemplate() вызывается с именованными аргументами кнопкой и ползунком . Значения используются при оценке кода R в шаблоне.

После обработки созданный HTML будет выглядеть примерно так. Вы можете видеть, где было вставлено содержимое блестящей головы, а также actionButton и sliderВведите HTML-код.

 

  <голова>
         css" rel="stylesheet"/>  
       
  <тело>
    <дел>
      <тип кнопки="кнопка"
             >Действие
      <дел>
        
        <ввод
               
               данных мин = "1"
               данные макс = "100"
               данные из = "50" данные-шаг = "1" данные-сетка = "истина"
               номер сетки данных = "9.9" data-grid-snap="false"
               разделитель данных-prettify=","
               клавиатура данных = "истина"
               шаг клавиатуры данных = "1.01010101010101"
               интервал перетаскивания данных = "истина"
               тип данных-данных="число"/>