Темплейты: Команды рендеринга (v 1.x)
Переменная
Простейшая команда темплейта - отобразить переменную. Синтаксис тривиален:
VARIABLE
Например, если необходимо отобразить содержимое значения message
, достаточно написать:
<% message %>
Это, в действительности, транслируется в следующий код C++:
out()<<cppcms::filters::escape(content.message);
, где функция escape
записывает в поток переменную-член содержимого message
и экранирует специальные HTML-символы <
, >
, &
, "
в их HTML представление - такое как <
Если необходимо получить значение какого-либо свойства, достаточно написать:
<% some_property() %>
, которое транслируется в:
out()<<cppcms::filters::escape(content.some_property());
Переменная с фильтрами
Вы можете добавить произвольные фильтры отображаемой переменной. Синтаксис следующий:
VARIABLE [ '|' filter [ '|' filter ] ... ]
, где filter
:
[ 'ext' ] NAME [ '(' ( VARIABLE | STRING | NUMBER ) [ ',' ( VARIABLE | STRING | NUMBER ) ] ... ]
Описание
Если фильтры не указаны - переменная экранируется автоматичски, но если указаны - они будут использованы вместо экранирования.
Каждая переменная - в действительности создание или вызов специального объекта фильтра с указанными параметрами, где первый параметр - "фильтруемая" переменная, а другие - параметры фильтра. Например:
<% birthday | strftime("%d/%m/%Y") %>
Транслируется в:
out()<<cppcms::filters::strftime(content.birthday,"%d/%m/%Y");
Вы также можете конкатенировать фильтры, используя символ |
:
<% birthday | strftime("%d %m %Y") | urlencode %>
Будет рендериться как: out()<<cppcms::filters::urlencode(cppcms::filters::strftime(content.birthday,"%d/%m/%Y"));
Доступно множество предопределенных фильтров, см. ссылку на namespace cppcms::filters.
Один из фильтров, о котором стоит упомянуть - фильтр raw
, позволяющий записать выходную переменную в чистом виде без HTML-экранирования.
<% ready_html | raw %>
Переменная ready_html
будет записана в выходной поток в чистом виде без экранирования HTML-символов, таких как <
.
Вы можете указать произвольные внешние фильтры, определенные в классе content
. Например:
namespace data { struct page { ... virtual string bbcode(string const &); ... }; }
Затем, в темплейте можно указать:
<% class page uses data::page %> <% template render() %> <% message | ext bbcode %> <% end %> <% end %>
Примечание: В платформе Windows динамически подгружаемые библиотеки (dll) не допускают неизвестные символы.
Поэтому, если необходима поддержка Windows, необходимо создать Ваши фильтры как виртуальные функции или обратные вызовы - типа booster::function<>
чтобы предотвратить ссылочность на внешние символы.
Интернационализация
Синтаксис
'gt' STRING [ 'using' using-options ] 'ngt' STRING ',' STRING ',' VARIABLE [ 'using' using-options
, где using-options
:
display-variable-block [ ',' display-variable-block [ ',' ... ] ]
Где display-variable-block
- любая переменная из опциональных фильтров, описанных выше. Например:
<% gt "Press the button" %> <% gt "Hello Dear {1}, we are glad to see you!" using name %> <% gt "Hello <a href=\"{1}\">{2}</a> you have {3}" using link | urlencode , name , something %> <% ngt "You have one apple","You have {2} apples",n using n %>
Описание
gt
-- gettext
переводит данную строку в соответствии с локалью, определенной в выводимом потоке. Например:
<% gt "Press the button" %>
Будет переведено как "Press the button" в English-локали и "Нажмите кнопку" - в Russian-локали.
Можно указать дополнительные параметры, используя опцию using
. Можно передать список, разделенный запятой, в том виде, в котором собирались отображаться переменные. Как обычно, можно использовать любые другие фильтры. "{1}", "{2}" и т.д., определяя очередность входных переменных. Для таких замен используется booster::locale::format
или cppcms::locale::format
(в соответствии с backend'ом локализации, с которым компилировался CppCMS).
ngt
-- ngettext
переводит множественную форму данного целого, где первый параметр - единственное число, второй - множественное и третий должен быть используемой переменной.
Примечание:
- При использовании
ngt
предполагается использование синтаксисаusing
, потому что необходимо обеспечить отображение действительного числа. Для проверки направления текста можно использовать
<% if rtl %>
или<% if not rtl %>
. В действительности, это эквивалент:<% if (cppcms::locale::gettext("LTR",out().getloc())=="RTL") %>
Описание оператора
if
см. в дальнейшем тексте.
Подключение других темплейтов
Синтаксис
'include' IDENTIFIER '(' [ parameter [ ',' parameter ...] ] ')'
, где parameter
- одно из VARIABLE, STRING или NUMBER. Например:
<% include title() %> <% include parent::foo() %> <% include bar(x,"test",-1.0) %>
Описание
Эта команда позволяет включить в это место другие темплейты (в действительности вызывая другие функции-члены). Вы можете включить существующие реализации в родительские view для их расширения. Например:
<% view master uses data::master %> <% template menu() %> <li><a href="#1">Main</a></li> <li><a href="#2">Products</a></li> <% end template %> <% template render() %> <ul><% include menu() %></ul> <% end template %> <% end view %> <% view sales uses data::sales extends master %> <% template menu() %> <% include master::menu() %> <li><a href="#3">Orders</a></li> <% end %> <% end %>
Этот код расширяет menu, добавляя в него view sales
с дополнительными опциями.
Рендеринг форм
Синтаксис
'form' ('as_p' | 'as_table' | 'as_ul' | 'as_dl' | 'as_space' | 'input' | 'begin' | 'end' ) VARIABLE
флаги as_*
позволяют рендерить cppcms::form
со специфичными разделителями, в то время как флаги input
, begin
и end
- позволяют рендерить отдельную часть widget'а.
Описание
Формы организованы как объект формы или набор widget'ов. Каждый набор может рендериться с использованием различных разделителей:
as_p
-- используя HTML-параграфы.as_table
-- используя таблицы. Примечание: теги<table>...</table>
не добавляются, пользователь должен указать их.as_ul
-- как список (используя<li>..</li>
).<ul>..</ul>
- не определяются.as_dl
-- как определяемый список.<dl>
-тэги не определяются, используются<dt>..</dt>
и<dd>..</dd>
.as_space
-- вставляет пробелы между элементами.
Например:
<table> <% form as_table form.fields %> </table> <p><% form as_space form.submit_buttons %></p>
Может отрендериться как:
<table> <tr><th>User Name:</th><td><input ... /></td></tr> <tr><th>Password: </th><td><input ... /></td></tr> </table> <p><input ... value="Login" /> <input ... value="Forgot Password" /></p>
Иногда, необходимо выполнить произвольный рендеринг widget'ов, не предопределенный из этого списка.
В этом случае можно рендерить только поле <input ...>
вызывая
<% form input some_button %>
, который отрендериться в виде:
<input type="submit" name="_3" value="Press" />
Заметьте, input
- не означает строгое ограничение для widget'ов, использующих HTML-тег input
, он работает в любых других widget'ах, ограниченных только фактическим рендерингом содержимого без "help"-сообщений. Например, для widget'а
cppcms::widgets::textarea
это будет <textarea ...>some text</textarea>
Иногда, необходим более точный доступ к визуализируемым частям widget'а, например, необходимо добавить некоторые атрибуты для widget'а в view.
Вы можете рендерить begin
или end
часть widget'а так, что можно будет вставить между ними HTML-атрибуты или даже JavaScript:
<% form begin some_button %> onclick="return foo()" <% form end some_button %>
Который рендериться как
<input type="submit" name="_3" onclick="return foo()" value="Press" />
Для генерации произвольного HTML для widget'ов, всегда можно использовать свойства widget'а напрямую:
<input type="submit" name="<% button.name() %>" value="Press" /> ( <% button.help() %> )
См.: cppcms::widgets
namespace для описания специфичных свойств widget'а.
Выбор генерации HTML/XHTML
Вы можете запросить генерацию HTML- или XHTML-кода в формах, используя следующую команду:
( 'xhtml' | 'html' )
Заметьте, эта команда распространяется глобально на весь темплейт не соединяясь с определенным классом. Вы должны включить ее в самый верхний класс Вашего view.
<% c++ #include "all_data.h" %> <% xhtml %> <% skin %> <% view master uses data::master %> <% template render() %> <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
На данный момент, эта опция влияет только на генерацию кода форм.
Встраивание кода C++
Вы всегда можете встроить любой C++-код, используя:
"c++" any-c++-statement
Например:
<% c++ #include "all_content.h" %>
Примечания:
Если хотите ссылаться в коде на переменные содержимого темплейта, не забудьте использовать
content
член класса. Например:<% a %> + <% b %> = <% c++ out()<<content.a+content.b; %>
- Вообще, использовать С++-код в темплейте нежелательно. Используйте его только в крайней необходимости.
- Если необходимо использовать специальные условия, предпочтительнее использовать специальный оператор if, чем
<% c++ if() { %>...<% c++ } %>