В этой части серии мы создадим остальные наши узлы контента (страницы) и начнем добавлять макросы XSLT для обработки таких вещей, как создание навигации по сайту и <umbraco:Macro>
элементов <umbraco:Macro>
.
Также доступно в этой серии:
- Начало работы с Umbraco: Часть 1
- Начало работы с Umbraco: Часть 2
- Начало работы с Umbraco: Часть 3
- Начало работы с Umbraco: часть 4
- Начало работы с Umbraco: часть 5
Создание остальных узлов содержимого
Сначала мы добавим остальные наши узлы контента. Помните, типы документов + шаблоны + узлы содержимого = страницы. Для просмотра бэк-энда сайт должен быть открыт в Visual Web Developer Express (VWD). Щелкните правой кнопкой мыши страницу default.aspx
на правой панели Solution Explorer
и выберите View in Browser
. Домашняя страница сайта должна загрузиться. Чтобы получить доступ к бэкенду, замените default.aspx
в адресной строке на umbraco, после чего вы должны перейти на экран входа в систему, а затем в бэкэнд после того, как ваши учетные данные были введены.
Все страницы на сайте должны быть созданы как дочерние узлы домашней страницы, чтобы XSLT работал правильно. Щелкните правой кнопкой мыши узел « Home
в верхней левой части панели и выберите « Create
в раскрывающемся меню. Это даст нам диалог Create
; в поле Name
введите About Us
. Поле Choose Document Type
уже должно быть заполнено первым доступным типом документа — Content
— это нормально, просто нажмите кнопку « Create
внизу, и новый узел будет создан как дочерний узел узла « Home
:
Введите текст в текстовой области, затем Properties
вкладку « Properties
» и введите « All About Us
в поле « Page Title
, затем сохраните новый узел, используя значок диска на панели инструментов. Далее мы создадим страницу News List
; щелкните правой кнопкой мыши узел Home
и снова выберите Create
. Введите News
в качестве имени и выберите Тип документа News List
в поле выбора. Эта страница не имеет пользовательских свойств (она будет построена с использованием макроса), поэтому узел откроется на вкладке Properties
. Введите Company News
в поле Page Title
и щелкните значок «Сохранить и опубликовать».
Далее мы можем создать несколько новостей; на этот раз щелкните правой кнопкой мыши узел News
и выберите Create
. Добавьте News Item 1
в поле « Name
и нажмите « Create
(правильный тип документа уже будет выбран). У нас есть еще несколько полей для заполнения на этот раз; идти вперед и выбрать дату, добавить Headline
и Story Text
. Мы также можем добавить другое изображение в библиотеку мультимедиа и выбрать его с помощью средства выбора медиафайлов (хотя это изображение не обязательно для News Items
). Также добавьте Page Title
на вкладке Properties
. Как только это будет сделано, создайте еще одну News Item
и снова заполните поля. Убедитесь, что в текстовой области имеется достаточное количество текста для каждой новости, поскольку мы будем извлекать часть из каждого News Item
чтобы создать страницу News List
.
Итак, теперь мы создали Content page
News List
и пару News Items
. Осталось только создать несколько панелей героев для отображения на главной странице. Снова щелкните правой кнопкой мыши узел Home
, затем добавьте Panel 1
в качестве имени нового узла и выберите тип документа Hero Panel
. Используйте текстовую область на только что созданном узле, чтобы добавить текст на панель. Кроме того, мы должны убедиться, что мы переключаемся на вкладку Properties
и Umbraco Hide In Navigation
флажок Umbraco Hide In Navigation
. Создайте несколько панелей таким образом, возможно, используя другой текст или что-то, чтобы различать разные панели. На этом этапе наш сервер должен выглядеть следующим образом:
Создание макроса
Теперь, когда наши страницы созданы, мы можем начать писать макросы XSLT, которые будут создавать более сложные аспекты сайта, такие как навигация, список новостей и т. Д. Если мы откроем файл BasePage.master
в VWD, первый <umbraco:Macro>
мы находим, является макросом pageTitle
. Сначала мы создадим его, так как он довольно прост и должен дать базовое введение в XSLT.
В серверной части Umbraco перейдите в раздел « Developer
», щелкните правой кнопкой мыши папку XSLT и выберите « Create
. В появившемся диалоговом окне добавьте pageTitle
качестве имени Filename
и оставьте для поля выбора значение Clean
. Обратите внимание, что флажок « Create Macro
уже отмечен. Нажмите кнопку Create
. Новый файл XSLT и соответствующий ему макрос будут созданы. Выберите макрос (он будет найден в папке « Macros
» в дереве узлов) и измените Alias
макроса с PageTitle
на pageTitle
(для согласованности).
Теперь переключитесь обратно на VWD и откройте файл XSLT в Solution Explorer
справа. Новый файл XSLT, который мы создали в Umbraco, должен быть в списке. Конечно, мы можем добавить код XSLT напрямую через Umbraco, однако по соображениям Intellisense полезно написать его на VWD. Откройте файл XSLT, примерно в середине файла появится комментарий, который гласит <!—start writing XSLT -->
, удалите этот комментарий и замените его следующим кодом:
1
2
3
4
5
6
|
<xsl:if test=»$currentPage/pageTitle != »»>
<xsl:value-of select=»$currentPage/pageTitle»/>
<xsl:text> — </xsl:text>
</xsl:if>
<xsl:value-of select=»$currentPage/ancestor-or-self::* /domainName»/>
|
Сохраните файл XSLT. По сути, XSLT используется для преобразования XML в другие типы XML или другие форматы XML, такие как XHTML. Данные, которые мы вводим в поля в серверной части Umbraco, хранятся в базе данных в виде XML, поэтому мы можем использовать XSLT для обработки этого XML и преобразования его в (X) HTML для отображения на наших страницах. Прежде чем углубляться в детали того, что делает приведенный выше код, нам просто нужно взглянуть на пару основных концепций для работы с XSLT.
Прежде всего, сразу после элемента <xsl:output>
есть элемент параметра XSL ( <xsl:param>
), называемый currentPage
. Это будет установлено на любую страницу, которая «вызывает» XSLT-файл, поэтому, если посетитель просматривает домашнюю страницу сайта, параметр currentPage
будет установлен на Home
узел в серверной части. Если страница содержимого, такая как страница « About us
, просматривается, параметр currentPage
будет установлен на эту страницу.
На следующей строке у нас есть элемент шаблона XSL ( <xsl:template>
), для которого установлено соответствие /
что означает, что он должен соответствовать всем элементам и атрибутам XML в документе (сохраненное представление XML узла в back- конец).
Теперь давайте посмотрим на код, который мы добавили к элементу <xsl:template>
. Сначала мы используем элемент <xsl:if>
чтобы проверить, содержит ли значение currentPage
(в параметрах XSLT должно начинаться с символа $
) значение элемента pageTitle
. Это элемент pageTitle
в нашем узле страницы, а не макрос pageTitle
. Если оно содержит значение, следующая строка <xsl:value-of>
позволяет нам выбрать содержимое свойства pageTitle
. Затем мы используем элемент <xsl:text>
чтобы указать дефис для использования в качестве разделителя.
Наконец, мы снова используем элемент <xsl:value-of>
чтобы выбрать свойство domainName
. В этом элементе мы используем шаг XPath, который состоит из оси ancestor-or-self
чтобы выбрать все узлы-предки currentPage
а также currentPage
, и узел ::*
проверки всех атрибутов выбранных предков. Мы ограничимся этим до свойства domainName
мы установили на Home
узле с /domainName
предиката /domainName
.
Теперь просмотрите домашнюю страницу сайта, и заголовок страницы должен автоматически установить значение, которое мы ввели в свойстве domainName
. Если мы просматриваем страницу о нас (просто добавляем /about-us.aspx
в конец URL-адреса localhost в адресной строке), мы обнаруживаем, что заголовок установлен на All About Us – The Company
. Название страницы — Название сайта является предпочтительным форматом заголовка по причинам SEO.
В этом примере страницы, у которых не установлено свойство pageTitle
, просто возвращаются к свойству domainName
. Некоторые авторы макросов добавляют дополнительный уровень защиты, и если pageTitle
не установлен, вместо этого nodeName
к nodeName
. Это полезно, если клиент может забыть установить pageTitle
при добавлении новых страниц на сайт, но это означает, что заголовок страницы может заканчиваться именами файлов в верблюжьей оболочке. Есть аргументы за и против этого метода. Я оставлю вам решать, нужен ли этот дополнительный запасной вариант.
Добавление большего количества макросов
Давайте добавим еще несколько макросов; Затем мы должны построить навигацию для сайта, чтобы было легче перемещаться между страницами. Этот макрос будет намного сложнее, чем макет PageTitle, который мы только что рассмотрели. Мы оставили некоторую разметку в файле BasePage.master
, это структура, с которой мы закончим, как только закончим. Удалите это с главной страницы и добавьте <umbraco:Macro>
элемент <umbraco:Macro>
:
1
|
<umbraco:Macro Alias=»topNav» runat=»server»></umbraco:Macro>
|
Теперь создайте новый файл XSLT (и, следовательно, макрос) с именем topNav
. В VWD откройте новый файл XSLT и добавьте следующий код непосредственно после параметра currentPage
:
1
|
<xsl:variable name=»rootNode» select=»$currentPage/ancestor-or-self::* [@isDoc and @level=1]» /></div>
|
Затем добавьте следующий код в элемент <xsl: template>:
01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
|
<nav>
<ul class=»clear-float»>
<li>
<a href=»{umbraco.library:NiceUrl($rootNode/@id)}»>
<xsl:if test=»$rootNode/@id = $currentPage/@id»>
<xsl:attribute name=»class»>on</xsl:attribute>
</xsl:if>
<xsl:value-of select=»$rootNode/@nodeName» />
</a>
</li>
<xsl:for-each select=»$currentPage/rootNode/* [@isDoc and string(umbracoNavHide) != ‘1’]»>
<li>
<xsl:if test=»position() = last()»>
<xsl:attribute name=»class»>
<xsl:text>last</xsl:text>
</xsl:attribute>
</xsl:if>
<a href=»{umbraco.library:NiceUrl(@id)}»>
<xsl:if test=»$currentPage/@id = @id»>
<xsl:attribute name=»class»>on</xsl:attribute>
</xsl:if>
<xsl:attribute name=»title»>
<xsl:value-of select=»@nodeName»/>
</xsl:attribute>
<xsl:value-of select=»@nodeName»/>
</a>
<xsl:if test=»child::* [@isDoc]»>
<ul>
<xsl:for-each select=»child::* [@isDoc and string(umbracoNavHide) != ‘1’]»>
<xsl:choose>
<xsl:when test=»position() < 6 and string(child::NewsItem = ‘1’)»>
<li>
<a href=»{umbraco.library:NiceUrl(@id)}»>
<xsl:attribute name=»title»>
<xsl:value-of select=»@nodeName»/>
</xsl:attribute>
<xsl:value-of select=»@nodeName»/>
</a>
</li>
</xsl:when>
<xsl:otherwise>
<li>
<a href=»{umbraco.library:NiceUrl(@id)}»>
<xsl:attribute name=»title»>
<xsl:value-of select=»@nodeName»/>
</xsl:attribute>
<xsl:value-of select=»@nodeName»/>
</a>
</li>
</xsl:otherwise>
</xsl:choose>
</xsl:for-each>
</ul>
</xsl:if>
</li>
</xsl:for-each>
</ul>
</nav>
|
Сохраните файл. Прежде всего, мы устанавливаем переменную, которая соответствует корневому узлу сайта, то есть домашней странице. Чтобы выбрать только домашнюю страницу, мы перемещаемся от currentPage
(используя параметр $currentPage
) через всех предков, используя ось ancestor-or-self
а также ::*
testtest и предикат ::*
, проверяя, что узел имеет атрибут @isDoc
(это добавлен на все узлы страницы Umbraco) и находится на уровне 1 (еще один атрибут, добавленный Umbraco). Это даст нам корневой узел сайта, который является домашней страницей.
Затем в <xsl:template>
мы сначала создаем внешние контейнеры для нашего меню навигации, в частности элементы <nav>
и <ul>
. Затем мы добавляем первый элемент <li>
и первый элемент привязки. Мы устанавливаем href
привязки, используя библиотечную функцию Umbraco NiceUrl
, которая принимает id
документа в качестве аргумента. Мы предоставляем id
корневого узла, используя нашу переменную $rootNode
(как и параметры, переменные начинаются с символа $
. Атрибуты начинаются с @
в XSLT). Функция NiceUrl
будет возвращать сохраненный URL-адрес для узла.
Затем мы проверяем, совпадает ли id
$rootNode
с id
$currentPage
используя инструкцию <xsl:if>
; если это так, мы знаем, что домашняя страница в данный момент просматривается, и добавляем класс on
для привязки. Затем мы выбираем имя узла ( Name
присвоенное узлу в серверной части Umbraco, которое отображается на вкладке Properties
для узла), чтобы использовать его в качестве атрибута title
элемента привязки, и его текст, используя элемент <xsl:value-of>
для выбора значений.
Затем нам нужно перебрать каждый узел страницы под домашней страницей, то есть мы используем цикл <xsl:for-each>
чтобы выбрать и обработать все узлы, которые являются $rootNode
и также являются документами, но которые дополнительно не umbracoNavHide
флажок umbracoNavHide
. Это препятствует тому, чтобы наши панели Героя были перечислены в меню навигации по всему сайту, что явно нам не нужно!
Для каждого дочернего элемента $rootNode
мы создаем новый элемент <li>
. Мы делаем быструю проверку, чтобы увидеть, обрабатываем ли мы последний узел в наборе, что достигается путем проверки, равна ли position
узла в наборе узлов last
. Если это так, мы добавляем имя класса last
в <li>
.
Хотя это и не является строго необходимым в этом примере, это все же невероятно полезный метод, позволяющий использовать видение, поскольку ни IE6, ни IE7 (на которые по-прежнему приходится большой процент аудитории несчастного числа сайтов) не могут использовать
last-child
CSS селектор.
Затем мы создаем новый <a>
внутри <li>
и устанавливаем его href
используя функцию NiceUrl
еще раз, на этот раз передавая атрибут id
текущего узла. Мы устанавливаем заголовок и текст якоря так же, как и раньше. Мы также добавляем класс on
если просматриваемая страница совпадает со страницей, обрабатываемой в данный момент. Поскольку мы уже находимся в контексте узла, нам в основном не нужно использовать параметр $currentPage
, используя его только тогда, когда мы @id
текущего узла с @id
текущей страницы.
После того как ссылка для элемента nav
создана, мы проводим еще один тест (снова используя условное <xsl:if>
), чтобы определить, есть ли у текущего узла дочерние узлы, являющиеся документами. Если это так, мы создаем суб-навигацию с использованием вложенного <ul>
, а затем выбираем каждый дочерний узел, который является документом и не имеет флажка umbracoNvHide
.
Затем мы используем условное выражение <xsl:choose>
, которое похоже на XSLT, эквивалентный if...else
, чтобы ограничить число NewsItem
дочернего меню NewsItem
пятью, проверяя, имеет ли дочерний элемент position
менее 6 когда мы обрабатываем NewsItems
. Мы можем проверить, обрабатываем ли мы в настоящее время узлы NewsItem
, проверив, NewsItem
ли тест для этого элемента ( child::NewsItem
) child::NewsItem
true
.
Мы должны ограничить субнав для новостных элементов, потому что после того, как сайт какое-то время работал, потенциально могут быть сотни новостных статей, и было бы смешно перечислять их все в навигационном меню. Затем мы создаем новые <li>
и <a>
для каждого дочернего элемента, максимум до 5. Это в элементе <xsl:when>
, который эквивалентен части if
в if...else
. Когда мы не обрабатываем NewsItems
, мы просто создаем subnav для всех элементов (в элементе <xsl:otherwise>
else
<xsl:otherwise>
, который эквивалентен части else
if...else
.)
Это по сути это; если мы сохраним это сейчас и вернемся на домашнюю страницу сайта (фактическую домашнюю страницу, которая просматривается в браузере, а не на узел «Домой» в бэкэнде) и обновим ее, мы обнаружим, что наша nav
верхнего уровня создана для нас автоматически:
Далее мы можем создать навигацию для нижнего колонтитула сайта; это почти идентично верхней навигационной панели, за исключением того, что у него нет поднабра. Создайте новый XSLT-файл таким же образом, как и раньше, и назовите его footerNav
. Добавьте следующий код в файл:
01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
|
<nav>
<ul>
<li>
<a href=»{umbraco.library:NiceUrl($rootNode/@id)}»>
<xsl:if test=»$rootNode/@id = $currentPage/@id»>
<xsl:attribute name=»class»>on</xsl:attribute>
</xsl:if>
<xsl:attribute name=»title»>
<xsl:value-of select=»$rootNode/@nodeName»/>
</xsl:attribute>
<xsl:value-of select=»$rootNode/@nodeName» />
</a>
</li>
<xsl:for-each select=»$rootNode/* [@isDoc and string(umbracoNavHide) != ‘1’]»>
<li>
<xsl:if test=»position() = last()»>
<xsl:attribute name=»class»>
<xsl:text>last</xsl:text>
</xsl:attribute>
</xsl:if>
<a href=»{umbraco.library:NiceUrl(@id)}»>
<xsl:if test=»$currentPage/@id = @id»>
<xsl:attribute name=»class»>on</xsl:attribute>
</xsl:if>
<xsl:attribute name=»title»>
<xsl:value-of select=»@nodeName»/>
</xsl:attribute>
<xsl:value-of select=»@nodeName»/>
</a>
</li>
</xsl:for-each>
</ul>
</nav>
|
Этот XSLT-файл также должен определить переменную rootNode
в верхней части, как и в случае с topNav
, и не забудьте добавить <umbraco:Macro>
в файл BasePage.master
:
1
|
<umbraco:Macro Alias=»footerNav» runat=»server»></umbraco:Macro>
|
Это все макросы, которые нам нужны в файле BasePage.master
. В файле Home.master
есть только макрос панели Hero, который мы добавим в другой части серии, а в файле Content.master
вообще нет макросов. Следующий файл, к которому нам нужно добавить макрос, это страница NewsList.master
; мы добавим это в следующей части серии.
Резюме
В этой части руководства мы начали писать XSLT-файлы, которые создают различные части сайта на основе созданных узлов контента. Именно здесь сайт действительно начинает собираться и ощущать себя полностью работающим веб-сайтом.
XSLT и XPath являются мощными языками для работы с документами XML и элементами, содержащимися в этих документах. Если это был ваш первый опыт работы с XSLT, некоторые из них могут все еще казаться немного чуждыми, особенно если вы привыкли работать с более интуитивными языками, такими как HTML и CSS. Но не волнуйтесь, XSLT и XPath легко подобрать, если немного потренироваться, и они заслуживают изучения языков, например, jQuery использует XPath для выбора элементов из (X) HTML-страниц.
В следующей части серии мы добавим XSLT-файлы, которые будут создавать страницу списка новостей и меню навигации по новостям, а затем перейдем к рассмотрению того, как мы можем добавить .Net User Controls в Umbraco для еще большей пользовательской функциональности.