Pages插件
该插件允许最终用户使用简单的WYSIWYG用户界面来创建和编辑静态页面和菜单。
管理静态页面
Static pages are managed on the Pages tab of the Static Pages plugin. Static pages have three required parameters - Title, URL and Layout. The URL is generated automatically when the Title is entered, but it could be changed manually. URLs must start with the forward slash character. The Layout drop-down allows to select a layout created with the CMS. Only layouts that include the staticPage
component are displayed in the drop-down.
Pages are hierarchical. The page hierarchy is used when a new page URL is generated, but as URLs can be changed manually, the hierarchy doesn’t really affect the routing process. The only place where the page hierarchy matters is the generated Menus. The generated menus reflect the page hierarchy. You can manage the page hierarchy by dragging pages in the page tree. The page drag handle appears when you move the mouse cursor over page item in the tree.
Optional properties of static pages are Hidden and Hide in navigation. The Hidden checkbox allows to hide a page from the front-end. Hidden pages are still visible for administrators who are logged into the back-end. The Hide in navigation checkbox allows to hide a page from generated menus and breadcrumbs.
占位符
If a static layout contains placeholders, the static page editor will show tabs for editing the placeholder contents. The plugin automatically detects text and HTML placeholders and displays a corresponding editor for them - the WYSIWYG editor for HTML placeholders and a text editor for text placeholders.
Snippets片段
Snippets are elements that can be added by a Static Page, in the rich text editor. They allow to inject complex (and interactive) areas to pages. There are many possible applications and examples of using Snippets:
- Google Maps snippet - outputs a map centered on specific coordinates with predefined zoom factor. That snippet would be great for static pages that explain directions.
- Universal commenting system - allows visitors to post comments to any static page.
- Third-party integrations - for example with Yelp or TripAdvisor for displaying extra information on a static page.
Snippets are displayed in the sidebar list on the Static Pages and can be added into a rich editor with a mouse click. Snippets are configurable and have properties that users can manage with the Inspector.
管理菜单
您可以在“静态页面”插件的“Menus”选项卡上管理菜单
一个网站可以包含多个菜单,例如主菜单,页脚菜单,侧边栏菜单等。
菜单包含在 staticMenu
组件中,主题开发人员可以在页面布局中带入该组件
菜单具有两个必需的属性
菜单 Name 和菜单 Code
菜单名称显示在后端的菜单列表中。
菜单代码是引用布局代码中的菜单所必需的,它是API参数。
菜单可以包含多个menu items,和菜单项可以嵌套。每个菜单项都有许多属性。
所有菜单项类型都有一些通用属性,某些属性取决于item type
常用菜单项属性是“ Title 和 Type
Title定义菜单项文本。
Type是一个下拉列表,显示了OctoberCMS副本中可用的所有菜单项类型。
标准菜单项类型
The available menu item types depend on the installed plugins, but there are three basic item types that are supported out of the box.
Header {.subheader}
Items of this type are used for displaying text and don’t link to anything. The text could be used as a category heading for other menu items. This type will only show a title property.
URL {.subheader}
Items of this type are links to a specific fixed URL. That could be an URL of an or internal page. Items of this type don’t have any other properties - just the title and URL.
Static Page {.subheader}
Items of this type refer to static pages. The static page should be selected in the Reference drop-down list described below.
All Static Pages {.subheader}
Items of this type expand to create links to all static pages defined in the theme. Nested pages are represented with nested menu items.
自定义菜单项类型
Other plugins can supply new menu item types. For example, the Blog plugin by RainLab supplies two more types:
Blog Category {.subheader}
An item of this type represents a link to a specific blog category. The category should be selected in the Reference drop-down. This menu type also requires selecting a CMS page that outputs a blog category.
All Blog Categories {.subheader}
An item of this time expands into multiple items representing all blog existing categories. This menu type also requires selecting a CMS page.
菜单项属性
Depending on the selected menu item time you might need to provide other properties of the menu item. The available properties are described below.
Reference {.subheader}
A drop-down list of objects the menu item should refer to. The list content depends on the menu item type. For the Static page item type the list displays all static pages defined in the system. For the Blog category item type the list displays a list of blog categories.
Allow nested items {.subheader}
This checkbox is available only for menu item types that suppose nested objects. For example, static pages are hierarchical, and this property is available for the Static page item type. On the other hand, blog categories are not hierarchical, and the checkbox is hidden.
Replace this item with its generated children {.subheader}
A checkbox determining whether the menu item should be replaced with generated menu items. This property is available only for menu item types that suppose automatic item generating, for example for the Static page menu item type. The Blog category menu item type doesn’t have this property because blog categories cannot be nested and menu items of this type always point to a specific blog category. This property is very handy when you want to include generated menu items to the root of the menu. For example, you can create the All blog categories menu item and enable the replacing. As a result you will get a menu that lists all blog categories on the first level of the menu. If you didn’t enable the replacing, there would be a root menu item, with blog categories listed under it.
CMS Page {.subheader}
This drop-down is available for menu item types that require a special CMS page to refer to. For example, the Blog category menu item type requires a CMS page that hosts the blogPosts
component. The CMS Page drop-down for this item type will only display pages that include this component.
Code {.subheader}
The Code field allows to assign the API code that you can use to set the active menu item explicitly in the page’s onInit()
handler described in the documentation.
参考
请阅读 Getting started with Static Pages
该插件当前包含三个组件:静态页面,静态菜单和静态面包屑。
集成“静态页面”插件
In the simplest case you could create a layout in the CMS area and include the plugin’s components in its body. The next example layout outputs a menu, breadcrumbs and a static page:
<html><head><title>{
{ this.page.title }}</title></head><body>{% component 'staticMenu' %}{% component 'staticBreadcrumbs' %}{% page %}</body>
</html>
链接到静态页面
When a static page is first created it will be assigned a file name based on the URL. For example, a page with the URL /chairs will create a content file called static-pages/chairs.htm in the theme. This file will not change even if the URL is changed at a later time.
To create a link to a static page, use the |staticPage
filter:
<a href="{
{ 'chairs'|staticPage }}">Go to Chairs</a>
This filter translates to PHP code as:
echo RainLab\Pages\Classes\Page::url('chairs');
If you want to link to the static page by its URL, simply use the |app
filter:
<a href="{
{ '/chairs'|app }}">Go to Chairs</a>
后端表单
If you need to select from a list of static pages in your own backend forms, you can use the staticpagepicker
widget:
fields:field_name:label: Static Pagetype: staticpagepicker
The field’s assigned value will be the static page’s file name, which can be used to link to the page as described above.
占位符
Placeholders defined in the layout are automatically detected by the Static Pages plugin. The Edit Static Page form displays a tab for each placeholder defined in the layout used by the page. Placeholders are defined in the layout in the usual way:
{% placeholder ordering %}
The placeholder
tag accepts some optional attributes:
title
: manages the tab title in the Static Page editor.type
: manages the placeholder type. There are two types supported at the moment - text and html.ignore
: if set to true, will be ignored by the Static Page editor.
The content of text placeholders is escaped before it’s displayed. Text placeholders are edited with a regular (non-WYSIWYG) text editor. The title and type attributes should be defined after the placeholder code:
{% placeholder ordering title="Ordering information" type="text" %}
They should also appear after the default
attribute, if it’s presented.
{% placeholder ordering default title="Ordering information" type="text" %}There is no ordering information for this product.
{% endplaceholder %}
To prevent a placeholder from appearing in the editor set the ignore
attribute.
{% placeholder systemInfo ignore=true %}
创建新的菜单项类型
插件可以使用新的菜单项类型扩展“静态页面”插件。
请参阅[Blog插件](https://octobercms.com/plugin/rainlab-blog)以获取集成示例。
新菜单类型将通过“静态页面”插件触发的API事件进行注册。
事件处理程序应在[插件注册文件](https://octobercms.com/docs/plugin/registration#registration-file)的boot()
方法中定义。
插件中应处理三个事件
pages.menuitem.listType
该事件方法应返回插件支持的新菜单项类型的列表。pages.menuitem.getTypeInfo
该事件方法应返回一个菜单项类型的细节信息pages.menuitem.resolveItem
事件处理程序“解析”菜单项信息并返回实际的项URL, title, 该项目当前是否处于活动状态的指示器,以及子项目(如果有)。
下一个示例显示了Blog插件的事件处理程序注册代码。
Blog插件注册两种item类型。
如您所见,Blog插件使用Category类来处理事件。这是推荐的方法。
public function boot()
{Event::listen('pages.menuitem.listTypes', function() {return ['blog-category'=>'Blog category','all-blog-categories'=>'All blog categories',];});Event::listen('pages.menuitem.getTypeInfo', function($type) {if ($type == 'blog-category' || $type == 'all-blog-categories') {return Category::getMenuTypeInfo($type);}});Event::listen('pages.menuitem.resolveItem', function($type, $item, $url, $theme) {if ($type == 'blog-category' || $type == 'all-blog-categories') {return Category::resolveMenuItem($item, $url, $theme);}});
}
注册新菜单项类型
新的菜单项类型已在pages.menuitem.listTypes
事件中注册。
处理程序应返回一个关联数组,其中,键为类型代码,值为类型名称。
强烈建议在类型代码中使用插件名称
以避免与其他菜单项类型提供程序发生冲突。例:
[`my-plugin-item-type` => 'My plugin menu item type'
]
返回有关item类型的信息
插件应该给pages.menuitem.getTypeInfo
事件方法提供有关‘被支持的菜单项类型’的详细信息。
处理程序获得一个参数–菜单项类型代码(menu item type code)
这是你用pages.menuitem.listTypes
注册的众多code中的一个
处理程序代码必须检查所请求的item类型code是否属于插件。
处理程序应以以下格式返回关联数组:
Array ([dynamicItems] => 0,[nesting] => 0,[references] => Array ([11] => News,[12] => Tutorials,[33] => Philosophy)[cmsPages] => Array ([0] => Cms\Classes\Page object,[1] => Cms\Classes\Page object)
)
数组的所有元素都是可选的,并取决于菜单项的类型。
dynamicItems
and nesting
的默认值为false
,这些键可以省略。
dynamicItems 元素
dynamicItems元素是一个布尔值,指示该项类型是否可以生成新的菜单项。
可选,如果省略,则为false
生成新菜单项的菜单项类型的示例:All blog categories, Static page.。
不会生成新菜单项的item类型示例:URL, Blog category。
nesting element 嵌套元素
nesting
元素是一个布尔值,指示item类型是否支持嵌套
可选,如果省略,则为false。
支持嵌套的项目类型的示例:Static page, All static pages
不支持嵌套的商品类型示例:Blog category, URL.
references element
The references
element is a list objects the menu item could refer to. For example, the Blog category menu item type returns a list of the blog categories. Some object supports nesting, for example static pages. Other objects don’t support nesting, for example the blog categories. The format of the references
value depends on whether the references have subitems or not. The format for references that don’t support subitems is
['item-key' => 'Item title']
The format for references with subitems is
['item-key' => ['title'=>'Item title', 'items'=>[...]]]
The reference keys should reflect the object identifier they represent. For blog categories keys match the category identifiers. A plugin should be able to load an object by its key in the pages.menuitem.resolveItem
event handler. The references element is optional, it is required only if a menu item type supports the Reference drop-down, or, in other words, if the user should be able to select an object the menu item refers to.
cmsPages element
The cmsPages
is a list of CMS pages that can display objects supported by the menu item type. For example, for the Blog category item type the page list contains pages that host the blogPosts
component. That component can display a blog category contents. The cmsPages
element should be an array of the Cms\Classes\Page
objects. The next code snippet shows how to return a list of pages hosting a specific component.
use Cms\Classes\Page as CmsPage;
use Cms\Classes\Theme;...$result = [];
...
$theme = Theme::getActiveTheme();
$pages = CmsPage::listInTheme($theme, true);$cmsPages = [];
foreach ($pages as $page) {if (!$page->hasComponent('blogPosts')) {continue;}$cmsPages[] = $page;
}$result['cmsPages'] = $cmsPages;
...
return $result;
Resolving menu items
When the Static Pages plugin generates a menu on the front-end, every menu item should resolved by the plugin that supplies the menu item type. The process of resolving involves generating the real item URL, determining whether the menu item is active, and generating the subitems (if required). Plugins should register the pages.menuitem.resolveItem
event handler in order to resolve menu items. The event handler takes four arguments:
$type
- the item type name. Plugins must only handle item types they provide and ignore other types.$item
- the menu item object (RainLab\Pages\Classes\MenuItem). The menu item object represents the menu item configuration provided by the user. The object has the following properties:title
,type
,reference
,cmsPage
,nesting
.$url
- specifies the current absolute URL, in lower case. Always use theUrl::to()
helper to generate menu item links and compare them with the current URL.$theme
- the current theme object (Cms\Classes\Theme
).
The event handler should return an array. The array keys depend on whether the menu item contains subitems or not. Expected result format:
Array ([url] => https://example.com/blog/category/another-category[isActive] => 1,[items] => Array ([0] => Array ([title] => Another category[url] => https://example.com/blog/category/another-category[isActive] => 1)[1] => Array ([title] => News[url] => https://example.com/blog/category/news[isActive] => 0))
)
The url
and isActive
elements are required for menu items that point to a specific page, but it’s not always the case. For example, the All blog categories menu item type doesn’t have a specific page to point to. It generates multiple menu items. In this case the items should be listed in the items
element. The items
element should only be provided if the menu item’s nesting
property is true
.
As the resolving process occurs every time when the front-end page is rendered, it’s a good idea to cache all the information required for resolving menu items, if that’s possible.
If your item type requires a CMS page to resolve item URLs, you might need to return the selected page’s URL, and sometimes pass parameters to the page through the URL. The next code example shows how to load a blog category CMS page referred by a menu item and how to generate an URL to this page. The blog category page has the blogPosts
component that can load the requested category slug from the URL. We assume that the URL parameter is called ‘slug’, although it can be edited manually. We skip the part that loads the real parameter name for the simplicity. Please refer to the Blog plugin for the reference.
use Cms\Classes\Page as CmsPage;
use October\Rain\Router\Helper as RouterHelper;
use Str;
use Url;...$page = CmsPage::loadCached($theme, $item->cmsPage);// Always check if the page can be resolved
if (!$page) {return;
}// Generate the URL
$url = CmsPage::url($page->getBaseFileName(), ['slug' => $category->slug]);$url = Url::to(Str::lower(RouterHelper::normalizeUrl($url)));
To determine whether an item is active just compare it with the $url
argument of the event handler.
Overriding generated references
In order to override generated references you can listen to pages.menu.referencesGenerated
event that fires right before injecting to page object. For example you can filter the unwanted menu entries.
Snippets
Snippets are elements that can be added by non-technical user to a Static Page, in the rich text editor. They allow to inject complex (and interactive) areas to pages. There are many possible applications and examples of using Snippets:
- Google Maps snippet - outputs a map centered on specific coordinates with predefined zoom factor. That snippet would be great for static pages that explain directions.
- Universal commenting system - allows visitors to post comments to any static page.
- Third-party integrations - for example with Yelp or TripAdvisor for displaying extra information on a static page.
Snippets are displayed in the sidebar list on the Static Pages and can be added into a rich editor with a mouse click. Snippets are configurable and have properties that users can manage with the Inspector.
Snippets can be created from partials or programmatically in plugins. Conceptually snippets are similar to CMS components (and technically, components can act as snippets).
Snippets created from partials
Partial-based snippets provide simpler functionality and usually are just containers for HTML markup (or markup generated with Twig in a snippet).
To create snippet from a partial just enter the snippet code and snippet name in the partial form.
The snippet properties are optional and can be defined with the grid control on the partial settings form. The table has the following columns:
- Property title - specifies the property title. The property title will be visible to the end user in the snippet inspector popup window.
- Property code - specifies the property code. The property code is used for accessing the property values in the partial markup. See the example below. The property code should start with a Latin letter and can contain Latin letters and digits.
- Type - the property type. Available types are String, Dropdown and Checkbox.
- Default - the default property value. For Checkbox properties use 0 and 1 values.
- Options - the option list for the drop-down properties. The option list should have the following format:
key:Value | key2:Value
. The keys represent the internal option value, and values represent the string that users see in the drop-down list. The pipe character separates individual options. Example:us:US | ca:Canada
. The key is optional, if it’s omitted (US | Canada
), the internal option value will be zero-based integer (0, 1, …). It’s recommended to always use explicit option keys. The keys can contain only Latin letters, digits and characters - and _.
Any property defined in the property list can be accessed within the partial markdown as a usual variable, for example:
The country name is {
{ country }}
In addition, properties can be passed to the partial components using an external property value.
Snippets created from components
Any component can be registered as a snippet and be used in Static Pages. To register a snippet, add the registerPageSnippets()
method to your plugin class in the registration file. The API for registering a snippet is similar to the one for registering components - the method should return an array with class names in keys and aliases in values:
public function registerPageSnippets()
{return ['\RainLab\Weather\Components\Weather' => 'weather'];
}
A same component can be registered with registerPageSnippets() and registerComponents() and used in CMS pages and Static Pages.
Custom page fields
There is a special syntax you can use inside your layout to add custom fields to the page editor form, called Syntax Fields. For example, if you add the following markup to a Layout that uses Static Pages:
{variable name="tagline" label="Tagline" tab="Header" type="text"}{/variable}
{variable name="banner" label="Banner" tab="Header" type="mediafinder" mode="image"}{/variable}
{variable name="color" label="Color" tab="Header" type="dropdown"options="blue:Blue | orange:Orange | red:Red"
}{/variable}
These act just like regular form field definitions. Accessing the variables inside the markup is just as easy:
<h1>{
{ tagline }}</h1>
<img src="{
{ banner|media }}" alt="" />
All custom fields are placed in the Secondary tabs container (next to Content field). If you need to place them in the Primary tabs container, use placement=“primary” attribute.
{variable name="tagline" label="Tagline" tab="Header" type="text" placement="primary"}{/variable}
Alternatively you may use the field type as the tag name, here we use the {text}
tag to directly render the tagline
variable:
<h1>{text name="tagline" label="Tagline"}Our wonderful website{/text}</h1>
You may also use the {repeater}
tag for repeating content:
{repeater name="content_sections" prompt="Add another content section"}<h3>{text name="content_header" label="Content section" placeholder="Type in a heading and enter some content for it below"}{/text}</h3><div>{richeditor name="content_body" size="large"}{/richeditor}</div>
{/repeater}
For more details on syntax fields, see the Parser section of the October documentation.
Custom menu item form fields
Just like CMS objects have the view bag component to store arbitrary values, you may use the viewBag
property of the MenuItem
class to store custom data values and add corresponding form fields.
Event::listen('backend.form.extendFields', function ($widget) {if (!$widget->getController() instanceof \RainLab\Pages\Controllers\Index ||!$widget->model instanceof \RainLab\Pages\Classes\MenuItem) {return;}$widget->addTabFields(['viewBag[featured]' => ['tab' => 'Display','label' => 'Featured','comment' => 'Mark this menu item as featured','type' => 'checkbox']]);
});
This value can then be accessed in Twig using the {
{ item.viewBag }}
property on the menu item. For example:
{% for item in items %}<li class="{
{ item.viewBag.featured ? 'featured' }}"><a href="{
{ item.url }}">{
{ item.title }}</a></li>
{% endfor %}