PageBlocks. Интеграция шаблона Snow на MODX
Всем привет.
Данным уроком хочу показать как можно легко и быстро интегрировать шаблон на MODX, надеюсь будет полезно. Забегая наперед, у меня получилось интегрировать сайт за 50 минут.
Для урока выбрал бесплатный шаблон Snow, он включает в себя главную страницу, 2 страницы портфолио и 2 страницы блога. А основным компонентом для интеграции будет PageBlocks.
1. Устанавливаем MODx
2. Переименовываем файл ht.access на .htaccess
3. Устанавливаем компоненты:
Страницы About и Contact — это ссылки на соответствующие блоки на главной странице.
Заменяем код главного шаблона на
Создаем чанки:
head:
header:
footer:
Структура блока:
Добавляем блок на страницу:
Поздравляю! Мы только что создали первый блок, надеюсь все было понятно. Идем дальше.
Здесь, все очень просто создаем блок с 2 полями: заголовок и контент, поэтому детально разбирать его не будем.
Структура:
Структура:
Коллекция — это создание однотипных блоков. Если блок имеет поля pagetitle, template и alias, то он будет привязан к ресурсу, который будет создан после создания блока. И все совпадающие поля синхронизируются в обоих направлениях. То есть, изменили поле в блоке и в ресурсе соответствующее поле тоже будет изменено и наоборот.
Шаг 1. Создаем блок для коллекции:
Поля:
Чанк work:
Шаг 2. Создаем коллекцию для наших работ.
Показывать коллекцию будем только в ресурсе c id 4 (Portfolio).
Шаг 3. Заполняем коллекцию.
Шаг 4. Создаем блок, в котором будем выводить нашу коллекцию.
Если вернуться в самое начало к блоку Portfolio, то нам нужны 2 поля — заголовок и описание.
Чанк projects
Здесь делаем по аналогии с блоком Features
Шаг 1. Создаем таблицу с полями: content и author
Шаг 2. Создаем блок в полями bg и reviews (ранее созданная таблица)
Чанк reviews:
Блок состоит только из логотипов, поэтому создаем блок с одним полем — галерея.
Чанк partners:
Добавляем логотипы:
Данный блог аналогичен блоку Portfolio. В итоге должно получиться так:
Чанк latest-blog
Чанк blog:
Структура:
Чанк contacts:
Чанк form.contact
Чанк email.contact:
Чанк portfolio-single
Чанк blog-single
Вот и все, сайт готов! Кому понравилось ставьте лайк.
Ссылка на сайт
Данным уроком хочу показать как можно легко и быстро интегрировать шаблон на MODX, надеюсь будет полезно. Забегая наперед, у меня получилось интегрировать сайт за 50 минут.
Для урока выбрал бесплатный шаблон Snow, он включает в себя главную страницу, 2 страницы портфолио и 2 страницы блога. А основным компонентом для интеграции будет PageBlocks.
Шаг 1. Подготовка
1. Устанавливаем MODx
2. Переименовываем файл ht.access на .htaccess
3. Устанавливаем компоненты:
- PageBlocks (конструктор блоков)
- Ace (редактор кода)
- TinyMCE Rich Text Editor (визуальный редактор)
- pdoTools (набор удобных сниппетов)
- SocialNetworks (для соц. сетей)
- FormIt (обработчик форм для MODX)
- AjaxForm (отправка форм через Ajax)
- Включаем дружеские url (friendly_urls)
- Включаем псевдоним родителя в построении uri (use_alias_path)
- Включаем Fenom на страницах (pdotools_fenom_parser)
- Включаем Fenom в чанках (pdotools_fenom_default)
- Разрешаем доступ к объектам MODX и PdoTools (pdotools_fenom_modx)
- Отключение доступа к странице по id (request_method_strict = Да)
Шаг 2. Создаем страницы
Страницы About и Contact — это ссылки на соответствующие блоки на главной странице.
Шаг 3. Настройка шаблона
Заменяем код главного шаблона на
<!DOCTYPE html>
<html lang="en">
<head>
{block 'head'}
{insert 'head'}
{/block}
</head>
<body>
{insert 'header'}
{insert 'navbar-mobile'}
<div class="nk-main">
{block 'blocks'}
{'!PageBlocks' | snippet}
{/block}
{block 'content'}
{$_modx->resource.content}
{/block}
{insert 'footer'}
</div>
<script src="/assets/js/combined.js"></script>
</body>
</html>
Создаем чанки:
head:
<meta charset="utf-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<title>{$_modx->resource.pagetitle} | {'site_name' | config}</title>
<meta name="description" content="{$_modx->resource.description}">
<link rel="icon" type="image/png" href="/assets/images/favicon.png">
<meta name="viewport" content="width=device-width, initial-scale=1">
<!-- Google Fonts -->
<link href="https://fonts.googleapis.com/css?family=Playfair+Display:400,400i,700,700i%7cWork+Sans:400,500,700" rel="stylesheet" type="text/css">
<link rel="stylesheet" href="/assets/css/combined.css">
header:
<header class="nk-header{if $_modx->resource.id != 1} nk-header-opaque{/if}">
<nav class="nk-navbar nk-navbar-top{if $_modx->resource.id == 1} nk-navbar-sticky nk-navbar-transparent nk-navbar-white-text-on-top{/if}">
<div class="container">
<div class="nk-nav-table">
<a href="/" class="nk-nav-logo">
<img src="/assets/images/logo-light.svg" alt="" width="85" class="nk-nav-logo-onscroll">
<img src="/assets/images/logo.svg" alt="" width="85">
</a>
{'!pdoMenu' | snippet: [
'parents' => 0,
'tplOuter' => '@INLINE <ul {$classes} data-nav-mobile="#nk-nav-mobile">{$wrapper}</ul>',
'outerClass' => 'nk-nav nk-nav-right hidden-md-down',
'scheme' => 'full',
]}
<ul class="nk-nav nk-nav-right nk-nav-icons">
<li class="single-icon hidden-lg-up">
<a href="#" class="nk-navbar-full-toggle">
<span class="nk-icon-burger">
<span class="nk-t-1"></span>
<span class="nk-t-2"></span>
<span class="nk-t-3"></span>
</span>
</a>
</li>
</ul>
</div>
</div>
</nav>
</header>
footer:
<footer class="nk-footer">
<div class="nk-footer-cont">
<div class="container text-xs-center">
<div class="nk-footer-social">
{'!SocialNetworks' | snippet: [
'fontawesome' => 'none',
'outerClass' => '',
'tpl' => '@INLINE <li><a href="{$link}" target="_blank" title="{$name}"><i class="fa fa-{$icon}"></i></a></li>',
]}
</div>
<div class="nk-footer-text">
<p>{'' | date: 'Y'} © {'site_name' | config}</p>
</div>
</div>
</div>
</footer>
Шаг 4. Создаем блоки
1. Блок Hero
Структура блока:
- фон блока (bg)
- подзаголовок (subtitle)
- заголовок (title)
- заголовок с курсивным начертанием (title_em)
Добавляем блок на страницу:
Поздравляю! Мы только что создали первый блок, надеюсь все было понятно. Идем дальше.
2. Блок About
Здесь, все очень просто создаем блок с 2 полями: заголовок и контент, поэтому детально разбирать его не будем.
3. Блок Features
Структура:
- фон (bg)
- таблица преимущества (features)
- Иконка (icon)
- Число (num)
- Заголовок (title)
4. Блок Portfolio
Структура:
- Заголовок (title)
- Описание (description)
- Работы (будет выводиться коллекция)
Коллекция — это создание однотипных блоков. Если блок имеет поля pagetitle, template и alias, то он будет привязан к ресурсу, который будет создан после создания блока. И все совпадающие поля синхронизируются в обоих направлениях. То есть, изменили поле в блоке и в ресурсе соответствующее поле тоже будет изменено и наоборот.
Шаг 1. Создаем блок для коллекции:
Поля:
- Превью (img)
- Заголовок (pagetitle)
- Тег (tag)
- Шаблон (template)
- Псевдоним (alias)
Чанк work:
<div class="nk-isotope-item" data-filter="{$tag}">
<div class="nk-portfolio-item nk-portfolio-item-square nk-portfolio-item-info-style-1">
<a href="{$uri}" class="nk-portfolio-item-link"></a>
<div class="nk-portfolio-item-image">
<div style="background-image: url(/{$img});"></div>
</div>
<div class="nk-portfolio-item-info nk-portfolio-item-info-center text-xs-center">
<div>
<h2 class="portfolio-item-title h3">{$pagetitle}</h2>
<div class="portfolio-item-category">{$tag}</div>
</div>
</div>
</div>
</div>
Шаг 2. Создаем коллекцию для наших работ.
Показывать коллекцию будем только в ресурсе c id 4 (Portfolio).
Шаг 3. Заполняем коллекцию.
Шаг 4. Создаем блок, в котором будем выводить нашу коллекцию.
Если вернуться в самое начало к блоку Portfolio, то нам нужны 2 поля — заголовок и описание.
Чанк projects
<div class="nk-box bg-white" id="projects">
<div class="nk-gap-4 mt-5"></div>
<h2 class="text-xs-center display-4">{$title}</h2>
<div class="nk-gap mnt-6"></div>
{if $content}
<div class="container">
<div class="row">
<div class="col-lg-8 offset-lg-2">
<div class="text-xs-center">{$content}
</div>
</div>
</div>
</div>
{/if}
<div class="nk-gap-2 mt-12"></div>
<div class="container">
<div class="nk-portfolio-list nk-isotope nk-isotope-3-cols">
{'!PageBlocks' | snippet: [
'rid' => 4,
'collection' => 2,
'limit' => 9
]}
</div>
</div>
<div class="nk-gap-4 mt-15"></div>
</div>
5. Блок Reviews
Здесь делаем по аналогии с блоком Features
Шаг 1. Создаем таблицу с полями: content и author
Шаг 2. Создаем блок в полями bg и reviews (ранее созданная таблица)
Чанк reviews:
<div class="nk-box bg-dark-1">
<div class="bg-image bg-image-parallax" style="background-image: url({$bg});"></div>
<div class="nk-gap-5 mnt-6"></div>
<div class="nk-gap-3"></div>
<div class="container-fluid">
<!-- START: Carousel -->
<div class="nk-carousel nk-carousel-all-visible text-white" data-autoplay="18000" data-dots="true">
<div class="nk-carousel-inner">
{foreach $reviews as $review}
<div>
<div>
<blockquote class="nk-blockquote-style-1 text-white">
{$review.content}
<cite>{$review.author}</cite>
</blockquote>
<div class="nk-gap-3 mt-10"></div>
</div>
</div>
{/foreach}
</div>
</div>
<!-- END: Carousel -->
</div>
<div class="nk-gap-4 mt-3"></div>
</div>
6. Блок Partners
Блок состоит только из логотипов, поэтому создаем блок с одним полем — галерея.
Чанк partners:
<div class="bg-white">
<div class="container">
<div class="nk-carousel-2 nk-carousel-x4 nk-carousel-no-margin nk-carousel-all-visible">
<div class="nk-carousel-inner">
{foreach $logos as $logo}
<div>
<div>
<div class="nk-box-1">
<img src="{$logo.url}" alt="{$logo.title}" class="nk-img-fit">
</div>
</div>
</div>
{/foreach}
</div>
</div>
</div>
</div>
Добавляем логотипы:
7. Блок Latest blog
Данный блог аналогичен блоку Portfolio. В итоге должно получиться так:
Чанк latest-blog
<div class="nk-box bg-gray-1" id="blog">
<div class="nk-gap-4 mt-5"></div>
<h2 class="text-xs-center display-4">{$title}</h2>
<div class="nk-gap mnt-6"></div>
{if $content}
<div class="container">
<div class="row">
<div class="col-lg-8 offset-lg-2">
<div class="text-xs-center">{$content}
</div>
</div>
</div>
</div>
{/if}
<div class="nk-gap-2 mt-12"></div>
<div class="container">
<!-- START: Carousel -->
<div class="nk-carousel-2 nk-carousel-x2 nk-carousel-no-margin nk-carousel-all-visible nk-blog-isotope" data-dots="true">
<div class="nk-carousel-inner">
{set $blogs = '!PageBlocks' | snippet: [
'rid' => 5,
'collection' => 3,
'limit' => 9,
'return' => 'json'
] | fromJSON}
{foreach $blogs as $blog}
<div>
<div>
<div class="pl-15 pr-15">
{$_modx->getChunk('blog', $blog)}
</div>
<div class="nk-gap-1"></div>
</div>
</div>
{/foreach}
</div>
</div>
<!-- END: Carousel -->
</div>
<div class="nk-gap-5 mt-20"></div>
</div>
Чанк blog:
<div class="nk-blog-post">
<div class="nk-post-thumb">
<a href="/{$uri}">
<img src="/{$img}" alt="{$pagetitle|notags}" class="nk-img-stretch">
</a>
<div class="nk-post-category"><a href="/{$uri}">{$tag}</a></div>
</div>
<h2 class="nk-post-title h4"><a href="blog-single.html">{$pagetitle}</a></h2>
<div class="nk-post-date">
{$publishedon | date_format: '%d.%m.%Y'}
</div>
<div class="nk-post-text">
<p>{$description}</p>
</div>
</div>
8. Блок Contacts
Структура:
- Заголовок (title)
- Описание (content)
- Адрес (address)
- Телефон (phone)
- Почта (email)
- Факс (fax)
Чанк contacts:
<div class="container" id="contact">
<div class="nk-gap-5"></div>
<div class="row vertical-gap">
<div class="col-lg-5">
<h2 class="display-4">{$title}</h2>
<div class="nk-gap mnt-3"></div>
{$content}
<ul class="nk-contact-info">
{if $address}
<li><strong>Address:</strong> {$address}</li>
{/if}
{if $phone}
<li><strong>Phone:</strong> {$phone}</li>
{/if}
{if $email}
<li><strong>Email:</strong> {$email}</li>
{/if}
{if $fax}
<li><strong>Fax:</strong> {$fax}</li>
{/if}
</ul>
</div>
<div class="col-lg-7">
{'!AjaxForm' | snippet: [
'form' => 'form.contact',
'hooks' => 'email',
'emailTpl' => 'email.contact',
'emailSubject' => 'Contacts',
'emailTo' => 'Superboshnik@gmail.com',
'emailFrom' => $_modx->config.emailsender,
'emailFromName' => $_modx->config.site_name,
'validate' => 'name:required,email:required,title:required,message:required',
'validationErrorMessage' => 'В форме содержатся ошибки!',
'successMessage' => 'Сообщение успешно отправлено',
]}
</div>
</div>
<div class="nk-gap-5"></div>
</div>
Чанк form.contact
<form action="{$_modx->resource.uri}" method="post" class="nk-form nk-form-ajax">
<div class="row vertical-gap">
<div class="col-md-6">
<input type="text" class="form-control" name="name" placeholder="Your Name">
</div>
<div class="col-md-6">
<input type="email" class="form-control" name="email" placeholder="Your Email">
</div>
</div>
<div class="nk-gap-1"></div>
<input type="text" class="form-control" name="title" placeholder="Your Title">
<div class="nk-gap-1"></div>
<textarea class="form-control" name="message" rows="8" placeholder="Your Comment" aria-required="true"></textarea>
<div class="nk-gap-1"></div>
<button class="nk-btn" type="submit">Send Message</button>
</form>
Чанк email.contact:
<ul>
<li><b>Name:</b> {$name}</li>
<li><b>Email:</b> {$email}</li>
<li><b>Title:</b> {$title}</li>
<li><b>Message:</b> {$message}</li>
</ul>
Шаг 5. Создаем другие страницы
Страница Portfolio
На этой странице нам нужно вывести 9 последних работ из коллекции. Для вывода будем использовать сниппет pdoPage. В настройках ресурса отключаем html-редактор и вставляем код в поле content:<div id="pdopage">
<div class="container">
<!-- START: Filter -->
<div class="nk-pagination nk-pagination-nobg nk-pagination-center">
<a href="#nk-toggle-filter">
<span class="nk-icon-squares"></span>
</a>
</div>
<ul class="nk-isotope-filter">
<li class="active" data-filter="*">All</li>
<li data-filter="Branding">Branding</li>
<li data-filter="Print">Print</li>
<li data-filter="Photography">Photography</li>
<li data-filter="Design">Design</li>
<li data-filter="Mockup">Mockup</li>
</ul>
<!-- END: Filter -->
<div class="nk-portfolio-list nk-isotope nk-isotope-3-cols rows">
{'!pdoPage' | snippet: [
'element' => 'PageBlocks',
'sortby' => 'rank',
'sortdir' => 'desc',
'limit' => 9,
'ajaxMode' => 'button',
'ajaxTplMore' => '@INLINE <div class="nk-gap-4"></div><div class="nk-pagination nk-pagination-center btn-more"><a href="#">Load More Works</a></div>',
'where' => [
'resource_id' => $_modx->resource.id,
'collection_id' => 2,
'active' => 1,
]
]}
</div>
<div class="nk-gap-4"></div>
</div>
{'page.nav' | placeholder}
</div>
Внутренняя страница работы
Добавляем блок:Чанк portfolio-single
<div class="container">
<div class="nk-portfolio-single">
<div class="nk-gap-4 mb-14"></div>
<h1 class="nk-portfolio-title display-4">{$title ?: $_modx->resource.pagetitle}</h1>
<div class="row vertical-gap">
<div class="col-lg-8">
<div class="nk-portfolio-info">
<div class="nk-portfolio-text">
{$content}
</div>
</div>
</div>
<div class="col-lg-4">
<table class="nk-portfolio-details">
{if $client}
<tr>
<td>
<strong>Client:</strong>
</td>
<td>{$client}</td>
</tr>
{/if}
{if $date}
<tr>
<td>
<strong>Date:</strong>
</td>
<td>{$date | date_format: '%d.%m.%Y'}</td>
</tr>
{/if}
</table>
</div>
</div>
<div class="nk-gap-4 mt-14"></div>
</div>
</div>
{if $img}
<img class="nk-img-fit" src="/{$img}">
{/if}
<div class="nk-pagination nk-pagination-center">
<div class="container">
{'!pdoNeighbors' | snippet: [
'tplWrapper' => '@INLINE {$prev}<a class="nk-pagination-center" href="#"><span class="nk-icon-squares"></span></a>{$next}',
'tplPrev' => '@INLINE <a class="nk-pagination-prev" href="/{$uri}"><span class="pe-7s-angle-left"></span> Previous Work</a>',
'tplNext' => '@INLINE <a class="nk-pagination-next" href="/{$uri}">Next Work <span class="pe-7s-angle-right"></span></a>',
]}
</div>
</div>
Страница Blog и внутренняя страница
Делаем по аналогии с портфолио.Чанк blog-single
{if $img}
<div class="nk-header-title nk-header-title-lg">
<div class="bg-image">
<div style="background-image: url(/{$img});"></div>
</div>
<div class="nk-header-table">
<div class="nk-header-table-cell">
<div class="container">
</div>
</div>
</div>
</div>
{/if}
// Здесь стоит остановится на одном моменте.
// На внутренней страницы блога мы должны вывести тег статьи, но мы не расширяли модель ресурса,
// поэтому это поле находиться только в блоке и чтобы получить все поля используем такую конструкцию:
{set $block = '!PageBlocks' | snippet: [
'object_id' => $_modx->resource.id,
'return' => 'json',
] | fromJSON}
<div class="container">
<div class="row">
<div class="col-lg-8 offset-lg-2">
<div class="nk-gap-4"></div>
<!-- START: Post -->
<div class="nk-blog-post nk-blog-post-single">
<h1 class="display-4">{$title ?: $_modx->resource.pagetitle}</h1>
<div class="nk-post-meta">
<div class="nk-post-date">{$_modx->resource.publishedon}</div>
// И теперь у нас есть доступ к полям блока и выводим тег:
<div class="nk-post-category"><a href="#"{$block.tag}</a></div>
</div>
<!-- START: Post Text -->
<div class="nk-post-text">
{$content}
</div>
<!-- END: Post Text -->
</div>
<!-- END: Post -->
<div class="nk-gap-3"></div>
</div>
</div>
</div>
<div class="nk-pagination nk-pagination-center">
<div class="container">
{'!pdoNeighbors' | snippet: [
'tplWrapper' => '@INLINE {$prev}<a class="nk-pagination-center" href="#"><span class="nk-icon-squares"></span></a>{$next}',
'tplPrev' => '@INLINE <a class="nk-pagination-prev" href="/{$uri}"><span class="pe-7s-angle-left"></span> Previous Work</a>',
'tplNext' => '@INLINE <a class="nk-pagination-next" href="/{$uri}">Next Work <span class="pe-7s-angle-right"></span></a>',
]}
</div>
</div>
Вот и все, сайт готов! Кому понравилось ставьте лайк.
Ссылка на сайт
Поблагодарить автора
Отправить деньги
Комментарии: 11
Вот и первый урок в новом разделе «Уроки». Александр Красавчик!
Кстати если кто-то не заметил — у нас созданы два новых раздела.
Уроки и обзоры. Сделано это в рамках задачи по популяризации MODX.
В рамках раздела обзоры — хотим дать больше контента и свежего взгляда на популярные и не очень компоненты, информации о которых не хватает!
В рамках раздела уроки — планируем рассказывать о «современных» технологиях разработки, объясняя почему сниппет IF — который до сих пор встречается, это плохо!
Кстати если кто-то не заметил — у нас созданы два новых раздела.
Уроки и обзоры. Сделано это в рамках задачи по популяризации MODX.
В рамках раздела обзоры — хотим дать больше контента и свежего взгляда на популярные и не очень компоненты, информации о которых не хватает!
В рамках раздела уроки — планируем рассказывать о «современных» технологиях разработки, объясняя почему сниппет IF — который до сих пор встречается, это плохо!
За такие уроки плюсики должны умножаться на 5
Согласен, материал отличный! Не исключено, что так и сделаем. Но раздел скорее всего будет закрытым и писать в него можно будет только при определенном рейтинге или каком то другом ограничении. Планов много — добраться бы.
Кстати кому интересно узнать о планах развития MODX.pro?
Кстати кому интересно узнать о планах развития MODX.pro?
Кстати кому интересно узнать о планах развития MODX.pro?Интересно! Ждем анонс.
Компонент реально крутой получился, уже перерос компонент от Марка из modmore. Единственное чего не хватает, возможности указывать файловые чанки, снова нужно писать код в админке.
а что нельзя в чанке написать
{include "file:chunks/chunk.tpl"}
??
Можно, а смысл? В чанке вызывать файловый чанк. Скоро будет поддержка файловых чанков.
Т.е. код оставищь в чанке и можно будет указать путь, как у MODX?
Ага, будет создаваться файловых чанк
Кто-то пробовал делать поиск по сайту на этом компоненте?
Ну сам себе и отвечу, компонент AdvSearch прекрасно ищет по json PageBlocks и MigX
Авторизуйтесь или зарегистрируйтесь, чтобы оставлять комментарии.