Merge branch '7023-tutorials'
@ -14,9 +14,6 @@ We are going to create a site in which all the content can be edited in the Silv
|
|||||||
navigation system, which will be generated on the fly to include all pages you add in the CMS. We will use two different
|
navigation system, which will be generated on the fly to include all pages you add in the CMS. We will use two different
|
||||||
templates - one for the home page, and one for the rest of the site.
|
templates - one for the home page, and one for the rest of the site.
|
||||||
|
|
||||||
![](_images/home-small.jpg)![](_images/menu-two-level-small.jpg)
|
|
||||||
|
|
||||||
|
|
||||||
## Installation
|
## Installation
|
||||||
|
|
||||||
You need to [download the SilverStripe software](http://www.silverstripe.org/stable-download) and install it to your local
|
You need to [download the SilverStripe software](http://www.silverstripe.org/stable-download) and install it to your local
|
||||||
@ -24,13 +21,13 @@ machine or to a webserver.
|
|||||||
|
|
||||||
For more infomation about installing and configuring a webserver read the [Installation instructions and videos](../installation).
|
For more infomation about installing and configuring a webserver read the [Installation instructions and videos](../installation).
|
||||||
|
|
||||||
If you want to follow this tutorial please choose "empty template" when installing SilverStripe. If you want a fully
|
This tutorial uses the SilverStripe CMS default theme 'Simple' which you will find in the themes folder. We will investigate the existing template files that make up the theme as well as create some new files to build upon the theme.
|
||||||
featured theme then select the 'BlackCandy' option.
|
|
||||||
|
|
||||||
## Exploring the installation
|
## Exploring the installation
|
||||||
|
|
||||||
After installation, open up the folder where you installed SilverStripe. If you installed on windows with WAMP, it will
|
After installation, open up the folder where you installed SilverStripe.
|
||||||
likely be at *c:\wamp\wwww*.
|
|
||||||
|
If you installed on windows with WAMP, it will likely be at *c:\wamp\wwww*. On Mac OS X with MAMP, it will likely be at */Applications/MAMP/htdocs/*
|
||||||
|
|
||||||
Let's have a look at the folder structure.
|
Let's have a look at the folder structure.
|
||||||
|
|
||||||
@ -46,40 +43,59 @@ When designing your site you should only need to modify the *mysite*, *themes* a
|
|||||||
|
|
||||||
## Using the CMS
|
## Using the CMS
|
||||||
|
|
||||||
The CMS is the area in which you can manage your site content. You can access the cms at http://localhost/admin. You
|
### User Interface Basics
|
||||||
|
|
||||||
|
![](_images/tutorial1_cms-basic.jpg)
|
||||||
|
|
||||||
|
The CMS is the area in which you can manage your site content. You can access the cms at http://localhost/admin (or http://yourdomain.com/admin if you are using you own domain name). You
|
||||||
will be presented with a login screen. You can login with the details you provided at installation. After logging in you
|
will be presented with a login screen. You can login with the details you provided at installation. After logging in you
|
||||||
should be greeted with the CMS, pictured below (we've entered some test content).
|
should be greeted with the CMS and a list of the pages currently in the CMS. Here you can add, delete and reorganize the pages using the buttons at the top. Clicking on a page will open it in the page editing interface pictured below (we've entered some test content).
|
||||||
|
|
||||||
![](_images/cms-numbered.jpg)
|
![](_images/tutorial1_cms-numbered.jpg)
|
||||||
|
|
||||||
|
1. These buttons allow you to move between the different sections in the CMS. There are four core sections in the CMS - "Pages", "Files", "Users" and "Settings". Modules may have their own sections here as well, if any are installed. In this tutorial we will be focusing on the "Pages" section.
|
||||||
|
2. While in "Pages" you can quickly move between the pages in the CMS by clicking the vertical bar between the CMS menu and the editor. This will slide out a sidebar. To hide this, click the arrow at the bottom of the sidebar.
|
||||||
|
|
||||||
|
![](_images/tutorial1_cms-numbered-2b.jpg)
|
||||||
|
|
||||||
1. These buttons allow you to move between the different sections in the CMS. There are three core sections in the CMS - Site Content, Files & Images and Security. Modules may have their own sections here as well, if any are installed. In this tutorial we will be focusing on the Site Content section.
|
|
||||||
2. All the pages in the site are laid out in the site tree. You can add, delete and reorganize the pages using the buttons at the top. Clicking on a page will open it in the editor on the right.
|
|
||||||
3. This section allows you to edit the content for the currently selected page, as well as changing other properties of the page such as the page name and URL. The content editor has full [WYSIWYG](http://en.wikipedia.org/wiki/WYSIWYG) abilities, allow you to change formatting and insert links, images and tables.
|
3. This section allows you to edit the content for the currently selected page, as well as changing other properties of the page such as the page name and URL. The content editor has full [WYSIWYG](http://en.wikipedia.org/wiki/WYSIWYG) abilities, allow you to change formatting and insert links, images and tables.
|
||||||
4. There are two copies of each page: draft & published. These buttons allow you to save your changes to the draft copy, publish your draft copy, or revert your draft copy to the published copy. By having separate draft & published copies, we can preview draft changes in the site before publishing them to the live site.
|
4. These buttons allow you to save your changes to the draft copy, publish your draft copy, unpublish from the live website or remove a page from the draft website.
|
||||||
5. The navigator will open the current page in the CMS, the draft site, or the published site.
|
The SilverStripe CMS workflow stores two copies of a page, a draft and a published one. By having separate draft & published copies, we can preview draft changes in the site before publishing them to the live website. You can quickly preview your draft pages without leaving the CMS by clicking the "Preview" button.
|
||||||
|
|
||||||
|
### Page Editor
|
||||||
|
|
||||||
|
Once you have selected a page to modify from the Pages section your page will open in the Page Editior.
|
||||||
|
|
||||||
|
The Edit Page section has 3 main areas in which you can edit the content of the page, change the settings and track your revision history (These will be covered in more detail further on in the tutorials).
|
||||||
|
|
||||||
|
![](_images/tutorial1_editpage-numbered.jpg)
|
||||||
|
|
||||||
|
1. *Content* - Allows you to set the title, wysiwyg content, URL and Meta data for your page.
|
||||||
|
2. *Settings* - Here you set the type of page behavior, parent page, show in search, show in menu, and who can view or edit the page.
|
||||||
|
3. *History* - This allow you to view previous version of your page, compare change and revert to previous version if need be.
|
||||||
|
|
||||||
|
|
||||||
### Try it
|
### Try it
|
||||||
|
|
||||||
There are three pages already created for you - "Home", "About Us" and "Contact Us", as well as a 404 page. Experiment
|
There are three pages already created for you - "Home", "About Us" and "Contact Us", as well as a 404 page. Experiment
|
||||||
with the editor - try different formatting, tables and images. When you are done, click "Save" to save the page or "Save
|
with the editor - try different formatting, tables and images. When you are done, click "Save" to save the page or "Save
|
||||||
& Publish" to post the content to the live site. In our screenshot we've entered some test content.
|
& Publish" to post the content to the live site.
|
||||||
|
|
||||||
> Don't worry that we currently have no way of navigating from page to page without using the CMS - we will build a navigation system soon.
|
When you create a new page, you are given a drop down that allows you to set the structure of the page (Top level or Under another page) and the page type.
|
||||||
|
The page type specifies the templates used to render the page, the fields that are able to be edited in the CMS, and page specific
|
||||||
When you create a new page, you are given a drop down that allows you to select the page type of the page. The page type
|
|
||||||
specifies the templates used to render the page, the fields that are able to be edited in the CMS, and page specific
|
|
||||||
behavior. We will explain page types in more depth as we progress; for now, make all pages of the type "Page".
|
behavior. We will explain page types in more depth as we progress; for now, make all pages of the type "Page".
|
||||||
|
|
||||||
|
![](_images/tutorial1_addpage.jpg)
|
||||||
|
|
||||||
![](_images/home-first.jpg)
|
**SilverStripe's friendly URLs**
|
||||||
|
|
||||||
**SilverStripe's virtual URLs**
|
|
||||||
|
|
||||||
While you are on the draft or live SilverStripe site, you may notice the URLs point to files that don't exist, e.g.
|
While you are on the draft or live SilverStripe site, you may notice the URLs point to files that don't exist, e.g.
|
||||||
http://localhost/contact. SilverStripe uses the URL field on the Meta-Data tab of the editor to look up the appropriate
|
http://localhost/contact or http://yourdomainname.com/about-us etc. SilverStripe uses the URL field on the Meta-Data tab of the Edit Page -> Content section to look up the appropriate
|
||||||
page in the database.
|
page in the database.
|
||||||
|
|
||||||
![](_images/url.jpg)
|
Note that if you have sub-pages, changing the Top level URL field for a page will affect the URL for all sub-pages. For example, if we changed the URL field "/about-us/" to "/about-silverstripe/" then the sub-pages URLs would now be "/about-silverstripe/URL-of-subpage/" rather than "/about-us/URL-of-subpage/".
|
||||||
|
|
||||||
|
![](_images/tutorial1_url.jpg)
|
||||||
|
|
||||||
When you create a new page, SilverStripe automatically creates an appropriate URL for it. For example, *About Us* will
|
When you create a new page, SilverStripe automatically creates an appropriate URL for it. For example, *About Us* will
|
||||||
become *about-us*. You are able to change it yourself so that you can make long titles more usable or descriptive. For
|
become *about-us*. You are able to change it yourself so that you can make long titles more usable or descriptive. For
|
||||||
@ -96,22 +112,30 @@ control codes. Because of this, you can have as much control of your site’s HT
|
|||||||
|
|
||||||
Every page in your site has a **page type**. We will briefly talk about page types later, and go into much more detail
|
Every page in your site has a **page type**. We will briefly talk about page types later, and go into much more detail
|
||||||
in tutorial two; right now all our pages will be of the page type *Page*. When rendering a page, SilverStripe will look
|
in tutorial two; right now all our pages will be of the page type *Page*. When rendering a page, SilverStripe will look
|
||||||
for a template file in the *tutorial/templates* folder, with the name `<PageType>`.ss - in our case *Page.ss*.
|
for a template file in the *simple/templates* folder, with the name `<PageType>`.ss - in our case *Page.ss*.
|
||||||
|
|
||||||
Open *themes/tutorial/templates/Page.ss*. It uses standard HTML with three exceptions: `<% base_tag %>`, *$Content* and
|
Open *themes/simple/templates/Page.ss*. It uses standard HTML apart from these exceptions:
|
||||||
*$SilverStripeNavigator*. These template markers are processed by SilverStripe into HTML before being sent to your
|
|
||||||
browser.
|
|
||||||
|
|
||||||
`<% base_tag %>` is replaced with the HTML [base element](http://www.w3.org/TR/html401/struct/links.html#h-12.4). This
|
`<% base_tag %>` is replaced with the HTML [base element](http://www.w3.org/TR/html401/struct/links.html#h-12.4). This
|
||||||
ensures the browser knows where to locate your site's images and css files.
|
ensures the browser knows where to locate your site's images and css files.
|
||||||
|
|
||||||
|
*$MetaTitle, $Title, and $SiteConfig.Title* in the html <title> tag are replaced by the title set in the Meta tags, Page Name, or Settings -> Site Title.
|
||||||
|
|
||||||
|
*$Title* is simply replaced with the name of the page ('Page name' on the 'Main' tab in the editor).
|
||||||
|
|
||||||
|
*$MetaTags* adds meta tags for search engines, as well as the page title ('Title' on the 'Meta-data' tab in the
|
||||||
|
editor). You can define your metatags in the meta-data tab off the content editor in the CMS.
|
||||||
|
|
||||||
|
*$Layout* is replaced with the contents of a template file with the same name as the page type we are using.
|
||||||
|
|
||||||
|
Open *themes/simple/templates/Layout/Page.ss*. You will see more HTML and more SilverStripe template replacement tags and variables.
|
||||||
|
|
||||||
*$Content* is replaced with the content of the page currently being viewed. This allows you to make all changes to
|
*$Content* is replaced with the content of the page currently being viewed. This allows you to make all changes to
|
||||||
your site's content in the CMS.
|
your site's content in the CMS.
|
||||||
|
|
||||||
*$SilverStripeNavigator* inserts the HTML for the navigator at the bottom of the page, which allows you to move
|
These template markers are processed by SilverStripe into HTML before being sent to your
|
||||||
quickly between the CMS and the draft and published version of your page.
|
browser and are formatted either with a *$* at the beginning or are between the SilverStripe template tags *`<% %>`*.
|
||||||
|
|
||||||
![The SilverStripe Navigator](_images/navigator.jpg)
|
|
||||||
|
|
||||||
**Flushing the cache**
|
**Flushing the cache**
|
||||||
|
|
||||||
@ -119,85 +143,38 @@ Whenever we edit a template file, we need to append *?flush=1* onto the end of t
|
|||||||
http://localhost/home/?flush=1. SilverStripe stores template files in a cache for quicker load times. Whenever there are
|
http://localhost/home/?flush=1. SilverStripe stores template files in a cache for quicker load times. Whenever there are
|
||||||
changes to the template, we must flush the cache in order for the changes to take effect.
|
changes to the template, we must flush the cache in order for the changes to take effect.
|
||||||
|
|
||||||
## Inserting the page title
|
## The Navigation System
|
||||||
|
|
||||||
Let's introduce two new template variables - *$Title* and *$MetaTags*.
|
We are now going to look at how the navigation system is implemented in the template.
|
||||||
|
|
||||||
*$Title* is simply replaced with the name of the page ('Page name' on the 'Main' tab in the editor).
|
Open up *themes/simple/templates/Includes/Navigation.ss*
|
||||||
|
|
||||||
Open *themes/tutorial/templates/Page.ss* and find the following code:
|
Menu for our site are created using a **loop**. Loops allow us to iterate over a data set, and render each item using a sub-template. The
|
||||||
|
**loop** *Menu(1)* returns the set of the first level menu items. We can then use the template variable
|
||||||
:::ss
|
*$MenuTitle* to show the title of the page we are linking to, $Link for the URL of the page and $LinkingMode to help style our menu with CSS (explained in more detail shortly).
|
||||||
<div id="Header">
|
|
||||||
<h1> </h1>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
and replace it with
|
|
||||||
|
|
||||||
:::ss
|
|
||||||
<div id="Header">
|
|
||||||
<h1>$Title</h1>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
|
|
||||||
*$MetaTags* adds meta tags for search engines, as well as the page title ('Title' on the 'Meta-data' tab in the
|
|
||||||
editor). You can define your metatags in the meta-data tab off the content editor in the CMS.
|
|
||||||
|
|
||||||
Add *$MetaTags* to the head so that it looks like this:
|
|
||||||
|
|
||||||
:::ss
|
|
||||||
<head>
|
|
||||||
<% base_tag %>
|
|
||||||
$MetaTags
|
|
||||||
<% require themedCSS(layout) %>
|
|
||||||
<% require themedCSS(typography) %>
|
|
||||||
<% require themedCSS(form) %>
|
|
||||||
</head>
|
|
||||||
|
|
||||||
|
|
||||||
> Don't forget to flush the cache each time you change a template by adding *?flush=1* onto the end of the URL.
|
|
||||||
|
|
||||||
Your page should now look something like this (with your own content of course):
|
|
||||||
|
|
||||||
![](_images/title.jpg)
|
|
||||||
|
|
||||||
## Making a Navigation System
|
|
||||||
|
|
||||||
So far we have made several pages, but we have no way to navigate between them. We can create a menu for our site using
|
|
||||||
a **control block**. Control blocks allow us to iterate over a data set, and render each item using a sub-template. The
|
|
||||||
**page control** *Menu(1)* returns the set of the first level menu items. We can then use the template variable
|
|
||||||
*$MenuTitle* to show the title of the page we are linking to.
|
|
||||||
|
|
||||||
Open up *themes/tutorial/templates/Page.ss*, and insert the following code inside `<div id="Main">`:
|
|
||||||
|
|
||||||
:::ss
|
|
||||||
<ul id="Menu1">
|
|
||||||
<% control Menu(1) %>
|
|
||||||
<li><a href="#">$MenuTitle</a></li>
|
|
||||||
<% end_control %>
|
|
||||||
</ul>
|
|
||||||
|
|
||||||
Here we've created an unordered list called *Menu1*, which *themes/tutorial/css/layout.css* will style into the menu.
|
|
||||||
Then, using a control block over the page control *Menu(1)*, we add a link to the list for each menu item.
|
|
||||||
|
|
||||||
All going to plan, your page should look like this:
|
|
||||||
|
|
||||||
![](_images/menu.jpg)
|
|
||||||
|
|
||||||
The menu isn't really very useful until each button links to the relevant page. We can get the link for the menu item in
|
|
||||||
question by using the *$Link* template variable.
|
|
||||||
|
|
||||||
Replace the list item line with this one:
|
|
||||||
|
|
||||||
:::ss
|
|
||||||
<li><a href="$Link" title="Go to the "{$Title}" page">$MenuTitle</a></li>
|
|
||||||
|
|
||||||
> $Title refers to *Page Name* in the CMS, whereas $MenuTitle refers to (the often shorter) *Navigation label*
|
> $Title refers to *Page Name* in the CMS, whereas $MenuTitle refers to (the often shorter) *Navigation label*
|
||||||
|
|
||||||
|
:::ss
|
||||||
|
<ul>
|
||||||
|
<% loop Menu(1) %>
|
||||||
|
<li class="$LinkingMode"><a href="$Link" title="$Title.XML">$MenuTitle.XML</a></li>
|
||||||
|
<% end_loop %>
|
||||||
|
</ul>
|
||||||
|
|
||||||
|
Here we've created an unordered list called *Menu1*, which *themes/simple/css/layout.css* will style into the menu.
|
||||||
|
Then, using a loop over the page control *Menu(1)*, we add a link to the list for each menu item.
|
||||||
|
|
||||||
|
This creates the navigation at the top of the page:
|
||||||
|
|
||||||
|
![](_images/tutorial1_menu.jpg)
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
## Highlighting the current page
|
## Highlighting the current page
|
||||||
|
|
||||||
A useful feature is highlighting the current page the user is looking at. We can do this with the template variable
|
A useful feature is highlighting the current page the user is looking at. We can do this with the template variable
|
||||||
*$LinkingMode*. *$LinkingMode* returns one of three values:
|
*$LinkingMode* which we mentioned before. *$LinkingMode* returns one of three values:
|
||||||
|
|
||||||
* *current* - This page is being visited, and should be highlighted
|
* *current* - This page is being visited, and should be highlighted
|
||||||
* *link* - The page is not currently being visited, so shouldn't be highlighted
|
* *link* - The page is not currently being visited, so shouldn't be highlighted
|
||||||
@ -205,58 +182,56 @@ A useful feature is highlighting the current page the user is looking at. We can
|
|||||||
|
|
||||||
> For example: if you were visiting a staff member such as "Home > Company > Staff > Bob Smith", you would want to highlight 'Company' to say you are in that section.
|
> For example: if you were visiting a staff member such as "Home > Company > Staff > Bob Smith", you would want to highlight 'Company' to say you are in that section.
|
||||||
|
|
||||||
Highlighting the current page is easy, simply assign a css class based on the value of *$LinkingMode*. Then provide a different style for current/section in css, as has been provided for you in *tutorial/css/layout.css*.
|
Highlighting the current page is easy, simply assign a css class based on the value of *$LinkingMode*. Then provide a different style for current/section in css, as has been provided for you in *simple/css/layout.css*.
|
||||||
|
|
||||||
Change the list item line in *Page.ss* so it looks like this:
|
![](_images/tutorial1_menu-highlighted.jpg)
|
||||||
|
|
||||||
:::ss
|
## A second level of navigation
|
||||||
<li class="$LinkingMode">
|
|
||||||
<a href="$Link" title="Go to the "{$Title}" page">$MenuTitle</a>
|
|
||||||
</li>
|
|
||||||
|
|
||||||
You should now have a fully functional top menu
|
The top navigation system is currently quite restrictive. There is no way to
|
||||||
|
nest pages, we have a completely flat site. Adding a second level in SilverStripe is easy. First (if you haven't already done so), let's add some pages.
|
||||||
|
|
||||||
![](_images/menu-highlighted.jpg)
|
The "About Us" section could use some expansion.
|
||||||
|
|
||||||
## Adding a second level
|
Select "Add New" in the Pages section, and create two new pages nested under the page "About Us" called "What we do" and "Our History" with the type "Page".
|
||||||
|
|
||||||
Although we have a fully functional navigation system, it is currently quite restrictive. Currently there is no way to
|
You can also create the pages elsewhere on the site tree, and drag and drop the pages into place.
|
||||||
nest pages, we have a completely flat site. Adding a second level in SilverStripe is easy. First, let's add some pages. The "About Us" section could use some expansion.
|
|
||||||
|
|
||||||
Select "About Us", and create two new pages "What we do" and "Our History" of the type "Page" inside. You can also create the pages elsewhere on the site tree, and use the reorganize button to drag and drop the pages into place.
|
|
||||||
|
|
||||||
Either way, your site tree should now look something like this:
|
Either way, your site tree should now look something like this:
|
||||||
|
|
||||||
![](_images/2nd_level-cut.jpg)
|
![](_images/tutorial1_2nd_level-cut.jpg)
|
||||||
|
|
||||||
|
Great, we now have a hierarchical site structure, let's now look at how this is created and displayed in our template.
|
||||||
|
|
||||||
Great, we now have a hierarchical site structure, but we still have no way of getting to these second level pages.
|
|
||||||
Adding a second level menu is very similar to adding the first level menu.
|
Adding a second level menu is very similar to adding the first level menu.
|
||||||
|
|
||||||
Open up our *Page.ss* template, and find the `<div id="ContentContainer">` tag. Underneath it, add the following code:
|
Open up */themes/simple/templates/Includes/Sidebar.ss* template and look at the following code:
|
||||||
|
|
||||||
:::ss
|
:::ss
|
||||||
<ul id="Menu2">
|
<ul>
|
||||||
<% control Menu(2) %>
|
<% loop Menu(2) %>
|
||||||
<li class="$LinkingMode"><a href="$Link" title="Go to the "{$Title}" page">$MenuTitle</a></li>
|
<li class="$LinkingMode"><a href="$Link" title="Go to the $Title.XML page"><span class="arrow">→</span><span class="text">$MenuTitle.XML</span></a></li>
|
||||||
<% end_control %>
|
<% end_loop %>
|
||||||
</ul>
|
</ul>
|
||||||
|
|
||||||
This should look very familiar. It is exactly the same as our first menu, except we have named our linked list *Menu2*
|
This should look very familiar. It is the same idea as our first menu, except the loop block now uses *Menu(2)* instead of *Menu(1)*.
|
||||||
and we are using the control *Menu(2)* instead of *Menu(1)*. As we can see here, the *Menu* control takes a single
|
As we can see here, the *Menu* control takes a single
|
||||||
argument - the level of the menu we want to get. Our css file will style this linked list into the second level menu,
|
argument - the level of the menu we want to get. Our css file will style this linked list into the second level menu,
|
||||||
using our usual *$LinkingMode* technique to highlight the current page.
|
using our usual *$LinkingMode* technique to highlight the current page.
|
||||||
|
|
||||||
We now have our second level menu, but we also have a problem. The menu is displayed on every page, even those that
|
To make sure the menu is not displayed on every page, even those that *don't* have any nested pages. We use an **if block**.
|
||||||
don't have any nested pages. We can solve this problem with an **if block**. Simply surround the menu with an if block
|
Look again in the *Sidebar.ss* file and you will see that the menu is surrounded with an **if block**
|
||||||
like this:
|
like this:
|
||||||
|
|
||||||
:::ss
|
:::ss
|
||||||
<% if Menu(2) %>
|
<% if Menu(2) %>
|
||||||
<ul id="Menu2">
|
...
|
||||||
<% control Menu(2) %>
|
<ul>
|
||||||
<li class="$LinkingMode"><a href="$Link" title="Go to the "{$Title}" page">$MenuTitle</a></li>
|
<% loop Menu(2) %>
|
||||||
<% end_control %>
|
<li class="$LinkingMode"><a href="$Link" title="Go to the $Title.XML page"><span class="arrow">→</span><span class="text">$MenuTitle.XML</span></a></li>
|
||||||
</ul>
|
<% end_loop %>
|
||||||
|
</ul>
|
||||||
|
...
|
||||||
<% end_if %>
|
<% end_if %>
|
||||||
|
|
||||||
The if block only includes the code inside it if the condition is true. In this case, it checks for the existence of
|
The if block only includes the code inside it if the condition is true. In this case, it checks for the existence of
|
||||||
@ -265,38 +240,52 @@ be processed and the menu will not be shown.
|
|||||||
|
|
||||||
Now that we have two levels of navigation, it would also be useful to include some "breadcrumbs".
|
Now that we have two levels of navigation, it would also be useful to include some "breadcrumbs".
|
||||||
|
|
||||||
Find *`<div id="Content" class="typography">`* and underneath it add:
|
Open up */themes/simple/templates/Includes/BreadCrumbs.ss* template and look at the following code:
|
||||||
|
|
||||||
:::ss
|
:::ss
|
||||||
<div class="breadcrumbs">
|
<% if Level(2) %>
|
||||||
$Breadcrumbs
|
<div id="Breadcrumbs">
|
||||||
|
$Breadcrumbs
|
||||||
</div>
|
</div>
|
||||||
|
<% end_if %>
|
||||||
|
|
||||||
Breadcrumbs are only useful on pages that aren't in the top level. We can ensure that we only show them if we aren't in
|
Breadcrumbs are only useful on pages that aren't in the top level. We can ensure that we only show them if we aren't in
|
||||||
the top level with another if statement.
|
the top level with another if statement.
|
||||||
|
|
||||||
:::ss
|
The *Level* page control allows you to get data from the page's parents, e.g. if you used *Level(1)*, you could use
|
||||||
<% if Level(2) %>
|
|
||||||
<div class="breadcrumbs">
|
|
||||||
$Breadcrumbs
|
|
||||||
</div>
|
|
||||||
<% end_if %>
|
|
||||||
|
|
||||||
The *Level* page control allows you to get data from the page's parents, eg if you used *Level(1)*, you could use
|
|
||||||
*$Level(1).Title* to get the top level page title. In this case, we merely use it to check the existence of a second
|
*$Level(1).Title* to get the top level page title. In this case, we merely use it to check the existence of a second
|
||||||
level page; if one exists then we include the breadcrumbs.
|
level page; if one exists then we include the breadcrumbs.
|
||||||
|
|
||||||
We now have a fully functioning two level navigation system. Both menus should be updating and highlighting as you move
|
This shows how the two level navigation system functions. Both menus should be updating and highlighting as you move
|
||||||
from page to page. They will also mirror changes done in the SilverStripe CMS, such as renaming pages or moving them
|
from page to page. They will also mirror changes done in the SilverStripe CMS, such as renaming pages or moving them
|
||||||
around.
|
around.
|
||||||
|
|
||||||
![](_images/menu-two-level.jpg)
|
![](_images/tutorial1_menu-two-level.jpg)
|
||||||
|
|
||||||
|
Feel free to experiment with the if and loop blocks, for example you could create a drop down style menu from the top navigation using a combination of the if blocks, loop blocks and some CSS to style it. This uses a *Children* if and loop block which checks to see if there is any sub-pages available within each top level navigation item, you will need to come up with your own CSS to correctly style this approach.
|
||||||
|
|
||||||
|
::ss
|
||||||
|
<ul>
|
||||||
|
<% loop Menu(1) %>
|
||||||
|
<li class="$LinkingMode">
|
||||||
|
<a href="$Link" title="$Title.XML">$MenuTitle.XML</a>
|
||||||
|
<% if Children %>
|
||||||
|
<ul>
|
||||||
|
<% loop Children %>
|
||||||
|
<li class="$LinkingMode"><a href="$Link" title="Go to the $Title.XML page"><span class="arrow">→</span><span class="text">$MenuTitle.XML</span></a></li>
|
||||||
|
<% end_loop %>
|
||||||
|
<ul>
|
||||||
|
<% end_if %>
|
||||||
|
</li>
|
||||||
|
<% end_loop %>
|
||||||
|
</ul>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
## Using a different template for the home page
|
## Using a different template for the home page
|
||||||
|
|
||||||
So far, a single template *Page.ss* is being used for the entire site. This is useful for the purpose of this
|
So far, a single template layout *Layouts/Page.ss* is being used for the entire site. This is useful for the purpose of this
|
||||||
tutorial, but in a finished website we can expect there to be several page layouts.
|
tutorial, but in a finished website we can expect there to be several page layouts.
|
||||||
|
|
||||||
To illustrate how we do this, we will create a new template for the homepage. This template will have a large graphical
|
To illustrate how we do this, we will create a new template for the homepage. This template will have a large graphical
|
||||||
@ -305,7 +294,7 @@ banner to welcome visitors.
|
|||||||
### Creating a new page type
|
### Creating a new page type
|
||||||
|
|
||||||
Earlier we stated that every page in a SilverStripe site has a **page type**, and that SilverStripe will look for a
|
Earlier we stated that every page in a SilverStripe site has a **page type**, and that SilverStripe will look for a
|
||||||
template corresponding to the page type. Therefore, the first step to get the homepage using a different template is to
|
template or template layout corresponding to the page type. Therefore, the first step to get the homepage using a different template is to
|
||||||
create a new page type.
|
create a new page type.
|
||||||
|
|
||||||
Each page type is represented by two php classes: a *data object* and a *controller*. Don't worry about the details of page
|
Each page type is represented by two php classes: a *data object* and a *controller*. Don't worry about the details of page
|
||||||
@ -332,8 +321,9 @@ Create a new file *HomePage.php* in *mysite/code*. Copy the following code into
|
|||||||
|
|
||||||
|
|
||||||
Every page type also has a database table corresponding to it. Every time we modify the database, we need to rebuild it.
|
Every page type also has a database table corresponding to it. Every time we modify the database, we need to rebuild it.
|
||||||
We can do this by going to [http://localhost/dev/build?flush=1](http://localhost/dev/build?flush=1). It may take a
|
We can do this by going to [http://localhost/dev/build?flush=1](http://localhost/dev/build?flush=1) or replace *localhost* with your own domain name.
|
||||||
moment, so be patient. This add tables and fields needed by your site, and modifies any structures that have changed. It
|
|
||||||
|
It may take a moment, so be patient. This add tables and fields needed by your site, and modifies any structures that have changed. It
|
||||||
does this non-destructively - it will never delete your data.
|
does this non-destructively - it will never delete your data.
|
||||||
|
|
||||||
As we have just created a new page type, SilverStripe will add this to the list of page types in the database.
|
As we have just created a new page type, SilverStripe will add this to the list of page types in the database.
|
||||||
@ -342,9 +332,9 @@ As we have just created a new page type, SilverStripe will add this to the list
|
|||||||
|
|
||||||
After building the database, we can change the page type of the homepage in the CMS.
|
After building the database, we can change the page type of the homepage in the CMS.
|
||||||
|
|
||||||
Under the "Behaviour" tab. Change it to *HomePage*, and click "Save Draft" and "Publish".
|
Navigate in the CMS to the "Home" page and under the "Behaviour" tab in the "Edit Page > Settings" section. Change it to *Home Page*, and click "Save & Publish".
|
||||||
|
|
||||||
![](_images/homepage-type.jpg)
|
![](_images/tutorial1_homepage-type.jpg)
|
||||||
|
|
||||||
Our homepage is now of the page type *HomePage*. However, even though it is of the *HomePage* page type, it is still
|
Our homepage is now of the page type *HomePage*. However, even though it is of the *HomePage* page type, it is still
|
||||||
rendered with the *Page* template. SilverStripe still renders the homepage using the *Page* template because when we
|
rendered with the *Page* template. SilverStripe still renders the homepage using the *Page* template because when we
|
||||||
@ -352,118 +342,39 @@ created the *HomePage* page type, we inherited from *Page*. So when SilverStripe
|
|||||||
will use the *Page* template. SilverStripe always attempts to use the most specific template first, and then falls back
|
will use the *Page* template. SilverStripe always attempts to use the most specific template first, and then falls back
|
||||||
to the template of the page type's parents.
|
to the template of the page type's parents.
|
||||||
|
|
||||||
|
|
||||||
### Creating a new template
|
### Creating a new template
|
||||||
|
|
||||||
To create a new template, create a copy of *Page.ss* (found in *themes/tutorial/templates*) and call it *HomePage.ss*. If we flush the cache (*?flush=1*), SilverStripe should now be using *HomePage.ss* for the homepage, and *Page.ss* for the rest of the site. Now let's customize the *HomePage* template.
|
To create a new template layout, create a copy of *Page.ss* (found in *themes/simple/templates/Layouts*) and call it *HomePage.ss*. If we flush the cache (*?flush=1*), SilverStripe should now be using *HomePage.ss* for the homepage, and *Page.ss* for the rest of the site. Now let's customize the *HomePage* template.
|
||||||
|
|
||||||
First, remove the breadcrumbs and the secondary menu; we don't need them for the homepage. Let's replace the title with our image. Add this line above the *Content* div:
|
First, remove the breadcrumbs and the secondary menu by removing the `<% include SideBar %>` line of code; we don't need them for the homepage. Let's replace the title with an image. Add this line above the *$Content* variable.
|
||||||
|
|
||||||
|
Now add the following to replace the `<h1>$Title</h1>` code in your template:
|
||||||
|
|
||||||
:::ss
|
:::ss
|
||||||
<div id="Banner">
|
<div id="Banner">
|
||||||
<img src="themes/tutorial/images/welcome.png" alt="Homepage image" />
|
<img src="http://www.silverstripe.org/themes/silverstripe/images/sslogo.png" alt="Homepage image" />
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
|
||||||
![](_images/home-template.jpg)
|
Your Home page should now look like this:
|
||||||
|
|
||||||
### Using a subtemplate
|
|
||||||
|
|
||||||
Having two templates is good, but we have a lot of identical code in the two templates. Rather than having two
|
|
||||||
completely separate templates, we can use subtemplates to specify only the part of the template that has changed.
|
|
||||||
If we compare *Page.ss* and *HomePage.ss*, we can see the only differences are within the *ContentContainer* div.
|
|
||||||
|
|
||||||
Copy the contents of the *ContentContainer* div from *themes/tutorial/templates/Page.ss* to a new file
|
|
||||||
*themes/tutorial/templates/Layout/Page.ss*, and do the same from *themes/tutorial/templates/HomePage.ss* to
|
|
||||||
*themes/tutorial/templates/Layout/HomePage.ss*.
|
|
||||||
|
|
||||||
The files should look like this:
|
|
||||||
|
|
||||||
**themes/tutorial/templates/Layout/Page.ss**
|
|
||||||
|
|
||||||
:::ss
|
|
||||||
<% if Menu(2) %>
|
|
||||||
<ul id="Menu2">
|
|
||||||
<% control Menu(2) %>
|
|
||||||
<li class="$LinkingMode"><a href="$Link" title="Go to the "{$Title}" page">$MenuTitle</a></li>
|
|
||||||
<% end_control %>
|
|
||||||
</ul>
|
|
||||||
<% end_if %>
|
|
||||||
|
|
||||||
<div id="Content" class="typography">
|
|
||||||
<% if Level(2) %>
|
|
||||||
<div class="breadcrumbs">
|
|
||||||
$Breadcrumbs
|
|
||||||
</div>
|
|
||||||
<% end_if %>
|
|
||||||
$Content
|
|
||||||
$Form
|
|
||||||
</div>
|
|
||||||
|
|
||||||
|
|
||||||
**themes/tutorial/templates/Layout/HomePage.ss**
|
![](_images/tutorial1_home-template.jpg)
|
||||||
|
|
||||||
:::ss
|
SilverStripe first searches for a template in the *themes/simple/templates* folder. Since there is no *HomePage.ss*,
|
||||||
<div id="Banner">
|
|
||||||
<img src="themes/tutorial/images/welcome.png" alt="Homepage image" />
|
|
||||||
</div>
|
|
||||||
<div id="Content" class="typography">
|
|
||||||
$Content
|
|
||||||
</div>
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
We can then delete *themes/tutorial/templates/HomePage.ss*, as it is no longer needed.
|
|
||||||
|
|
||||||
Replace the code we just copied out of *themes/tutorial/templates/Page.ss* with *$Layout*, so it looks like this:
|
|
||||||
|
|
||||||
**themes/tutorial/templates/Page.ss**
|
|
||||||
|
|
||||||
:::ss
|
|
||||||
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.1//EN" "http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd">
|
|
||||||
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" >
|
|
||||||
<head>
|
|
||||||
<% base_tag %>
|
|
||||||
$MetaTags
|
|
||||||
<% require themedCSS(layout) %>
|
|
||||||
<% require themedCSS(typography) %>
|
|
||||||
<% require themedCSS(form) %>
|
|
||||||
</head>
|
|
||||||
<body>
|
|
||||||
<div id="Main">
|
|
||||||
<ul id="Menu1">
|
|
||||||
<% control Menu(1) %>
|
|
||||||
<li class="$LinkingMode"><a href="$Link" title="Go to the "{$Title}" page">$MenuTitle</a></li>
|
|
||||||
<% end_control %>
|
|
||||||
</ul>
|
|
||||||
<div id="Header">
|
|
||||||
<h1>$Title</h1>
|
|
||||||
</div>
|
|
||||||
<div id="ContentContainer">
|
|
||||||
$Layout
|
|
||||||
</div>
|
|
||||||
<div id="Footer">
|
|
||||||
<span>Visit <a href="http://www.silverstripe.com" title="Visit www.silverstripe.com">www.silverstripe.com</a> to download the CMS</span>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
$SilverStripeNavigator
|
|
||||||
</body>
|
|
||||||
</html>
|
|
||||||
|
|
||||||
> As you have just done a few template changes, remember to add *?flush=1* in your URL to flush the cache so see your changes in the browser
|
|
||||||
|
|
||||||
SilverStripe first searches for a template in the *themes/tutorial/templates* folder. Since there is no *HomePage.ss*,
|
|
||||||
it will use the *Page.ss* for both *Page* and *HomePage* page types. When it comes across the *$Layout* tag, it will
|
it will use the *Page.ss* for both *Page* and *HomePage* page types. When it comes across the *$Layout* tag, it will
|
||||||
then descend into the *themes/tutorial/templates/Layout* folder, and will use *Page.ss* for the *Page* page type, and
|
then descend into the *themes/simple/templates/Layout* folder, and will use *Page.ss* for the *Page* page type, and
|
||||||
*HomePage.ss* for the *HomePage* page type.
|
*HomePage.ss* for the *HomePage* page type. So while you could create a HomePage.ss in the *themes/simple/templates/* it is better to reuse the navigation and footer common to both our Home page and the rest of the pages on our website and lets you write less code to achieve the end result.
|
||||||
|
|
||||||
|
![](_images/tutorial1_subtemplates-diagram.jpg)
|
||||||
|
|
||||||
![](_images/subtemplates-diagram.jpg)
|
|
||||||
|
|
||||||
## Summary
|
## Summary
|
||||||
|
|
||||||
Starting from a basic template, we have introduced template variables, controls and if blocks, and we have used these
|
We have introduced template variables, controls and if blocks, and we have used these
|
||||||
to build a basic but fully functional site. You have also been briefly introduced to page types, and seen how they
|
to build a basic but fully functional site. You have also been briefly introduced to page types, and seen how they
|
||||||
correspond to templates and subtemplates. By using these templates, you have seen how to customize the site content
|
correspond to templates and sub-templates. By using these templates, you have seen how to customize the site content
|
||||||
according to the page type of the page you are displaying.
|
according to the page type of the page you are displaying.
|
||||||
|
|
||||||
In the next tutorial, [Extending a Basic Site](2-extending-a-basic-site), we will explore page types on a
|
In the next tutorial, [Extending a Basic Site](2-extending-a-basic-site), we will explore page types on a
|
||||||
|
@ -16,7 +16,9 @@ Throughout this tutorial we are going to work on adding two new sections to the
|
|||||||
first is a news section, with a recent news listing on the homepage and an RSS feed. The second is a staff section,
|
first is a news section, with a recent news listing on the homepage and an RSS feed. The second is a staff section,
|
||||||
which demonstrates more complex database structures by associating an image with each staff member.
|
which demonstrates more complex database structures by associating an image with each staff member.
|
||||||
|
|
||||||
![](_images/news-with-rss-small.jpg)![](_images/einstein-small.jpg)
|
![](_images/tutorial2_newslist.jpg)
|
||||||
|
|
||||||
|
![](_images/tutorial2_einstein.jpg)
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
@ -57,7 +59,7 @@ the database, which fields can be edited in the CMS, and can use code to make ou
|
|||||||
A more in-depth introduction of Model-View-Controller can be found
|
A more in-depth introduction of Model-View-Controller can be found
|
||||||
[here](http://www.slash7.com/articles/2005/02/22/mvc-the-most-vexing-conundrum).
|
[here](http://www.slash7.com/articles/2005/02/22/mvc-the-most-vexing-conundrum).
|
||||||
|
|
||||||
![](_images/pagetype-inheritance.jpg)
|
![](_images/tutorial2_pagetype-inheritance.jpg)
|
||||||
|
|
||||||
## Creating the news section page types
|
## Creating the news section page types
|
||||||
|
|
||||||
@ -171,8 +173,10 @@ method to the *ArticlePage* class.
|
|||||||
public function getCMSFields() {
|
public function getCMSFields() {
|
||||||
$fields = parent::getCMSFields();
|
$fields = parent::getCMSFields();
|
||||||
|
|
||||||
$fields->addFieldToTab('Root.Content', new DateField('Date'), 'Content');
|
$datefield = new DateField('Date');
|
||||||
$fields->addFieldToTab('Root.Content', new TextField('Author'), 'Content');
|
$datefield->setConfig('showcalendar', true);
|
||||||
|
$fields->addFieldToTab('Root.Main', $datefield, 'Content');
|
||||||
|
$fields->addFieldToTab('Root.Main', new TextField('Author'), 'Content');
|
||||||
|
|
||||||
return $fields;
|
return $fields;
|
||||||
}
|
}
|
||||||
@ -192,13 +196,14 @@ Firstly, we get the fields from the parent class; we want to add fields, not rep
|
|||||||
returned is a `[api:FieldList]` object.
|
returned is a `[api:FieldList]` object.
|
||||||
|
|
||||||
:::php
|
:::php
|
||||||
$fields->addFieldToTab('Root.Content', new DateField('Date'), 'Content');
|
$fields->addFieldToTab('Root.Main', new TextField('Author'), 'Content');
|
||||||
$fields->addFieldToTab('Root.Content', new TextField('Author'), 'Content');
|
$fields->addFieldToTab('Root.Main', new DateField('Date'), 'Content');
|
||||||
|
|
||||||
|
|
||||||
We can then add our new fields with *addFieldToTab*. The first argument is the tab on which we want to add the field to:
|
We can then add our new fields with *addFieldToTab*. The first argument is the tab on which we want to add the field to:
|
||||||
"Root.Content" is the tab which the content editor is on. The second argument is the field to add; this is not a
|
"Root.Main" is the tab which the content editor is on (another is "Root.Metadata". The second argument is the field to add; this is not a database field, but a `[api:FormField]` - see the documentation for more details.
|
||||||
database field, but a `[api:FormField]` documentation for more details.
|
|
||||||
|
We add two fields: A simple `[api:TextField}` and a `[api:DateField]`. There are many more FormFields available in the default installation, please refer to [Form Field Types](form-field-types) for the list.
|
||||||
|
|
||||||
:::php
|
:::php
|
||||||
return $fields;
|
return $fields;
|
||||||
@ -210,14 +215,15 @@ to edit the fields in the CMS.
|
|||||||
Now that we have created our page types, let's add some content. Go into the CMS and create an *ArticleHolder* page
|
Now that we have created our page types, let's add some content. Go into the CMS and create an *ArticleHolder* page
|
||||||
named "News", and create some *ArticlePage*s inside it.
|
named "News", and create some *ArticlePage*s inside it.
|
||||||
|
|
||||||
![](_images/news-cms.jpg)
|
![](_images/tutorial2_news-cms.jpg)
|
||||||
|
|
||||||
## Modifing the date field
|
## Modifing the date field
|
||||||
|
|
||||||
**Please note:** As of version 2.4, the DateField type no longer automatically adds a javascript datepicker. Your date field will look just like a text field.
|
At the moment, your date field will look just like a text field.
|
||||||
This makes it confusing and doesn't give the user much help when adding a date.
|
This makes it confusing and doesn't give the user much help when adding a date.
|
||||||
|
|
||||||
To make the date field a bit more user friendly, you can add a dropdown calendar, set the date format and add better title.
|
To make the date field a bit more user friendly, you can add a dropdown calendar, set the date format and add better title. By default,
|
||||||
|
the date field will have the date format defined by your locale.
|
||||||
|
|
||||||
:::php
|
:::php
|
||||||
<?php
|
<?php
|
||||||
@ -229,11 +235,11 @@ To make the date field a bit more user friendly, you can add a dropdown calendar
|
|||||||
public function getCMSFields() {
|
public function getCMSFields() {
|
||||||
$fields = parent::getCMSFields();
|
$fields = parent::getCMSFields();
|
||||||
|
|
||||||
$fields->addFieldToTab('Root.Content', $dateField = new DateField('Date','Article Date (for example: 20/12/2010)'), 'Content');
|
$fields->addFieldToTab('Root.Main', $dateField = new DateField('Date','Article Date (for example: 20/12/2010)'), 'Content');
|
||||||
$dateField->setConfig('showcalendar', true);
|
$dateField->setConfig('showcalendar', true);
|
||||||
$dateField->setConfig('dateformat', 'dd/MM/YYYY');
|
$dateField->setConfig('dateformat', 'dd/MM/YYYY');
|
||||||
|
|
||||||
$fields->addFieldToTab('Root.Content', new TextField('Author','Author Name'), 'Content');
|
$fields->addFieldToTab('Root.Main', new TextField('Author','Author Name'), 'Content');
|
||||||
|
|
||||||
return $fields;
|
return $fields;
|
||||||
}
|
}
|
||||||
@ -243,7 +249,7 @@ Let's walk through these changes.
|
|||||||
:::php
|
:::php
|
||||||
$fields->addFieldToTab('Root.Content', $dateField = new DateField('Date','Article Date (for example: 20/12/2010)'), 'Content');
|
$fields->addFieldToTab('Root.Content', $dateField = new DateField('Date','Article Date (for example: 20/12/2010)'), 'Content');
|
||||||
|
|
||||||
*$dateField* is added only to the DateField in order to change the configuration.
|
*$dateField* is declared only to in order to change the configuration of the DateField.
|
||||||
|
|
||||||
:::php
|
:::php
|
||||||
$dateField->setConfig('showcalendar', true);
|
$dateField->setConfig('showcalendar', true);
|
||||||
@ -258,8 +264,8 @@ Set *showCalendar* to true to have a calendar appear underneath the Date field w
|
|||||||
:::php
|
:::php
|
||||||
$fields->addFieldToTab('Root.Content', new TextField('Author','Author Name'), 'Content');
|
$fields->addFieldToTab('Root.Content', new TextField('Author','Author Name'), 'Content');
|
||||||
|
|
||||||
By default the first argument *'Date'* or *'Author'* is shown as the title, however this might not be that helpful so to change the title,
|
By default the field name *'Date'* or *'Author'* is shown as the title, however this might not be that helpful so to change the title,
|
||||||
add the new title as the second argument. See the `[api:DateField]` documentation for more details.
|
add the new title as the second argument. See the `[api:DateField]` documentation for more details of the DateField configuration.
|
||||||
|
|
||||||
|
|
||||||
## Creating the templates
|
## Creating the templates
|
||||||
@ -273,131 +279,102 @@ page layout.
|
|||||||
|
|
||||||
First, the template for displaying a single article:
|
First, the template for displaying a single article:
|
||||||
|
|
||||||
**themes/tutorial/templates/Layout/ArticlePage.ss**
|
**themes/simple/templates/Layout/ArticlePage.ss**
|
||||||
|
|
||||||
|
|
||||||
:::ss
|
:::ss
|
||||||
<% if Menu(2) %>
|
<div class="content-container">
|
||||||
<ul id="Menu2">
|
<article>
|
||||||
<% control Menu(2) %>
|
<h1>$Title</h1>
|
||||||
<li class="$LinkingMode"><a href="$Link" title="Go to the $Title page">$MenuTitle</a></li>
|
<div class="news-details">
|
||||||
<% end_control %>
|
<p>Posted on $Date.Nice by $Author</p>
|
||||||
</ul>
|
|
||||||
<% end_if %>
|
|
||||||
|
|
||||||
<div id="Content" class="typography">
|
|
||||||
<% if Level(2) %>
|
|
||||||
<div class="breadcrumbs">
|
|
||||||
$Breadcrumbs
|
|
||||||
</div>
|
</div>
|
||||||
<% end_if %>
|
<div class="content">$Content</div>
|
||||||
|
</article>
|
||||||
<h1>$Title</h1>
|
$Form
|
||||||
$Content
|
$PageComments
|
||||||
<div class="newsDetails">
|
|
||||||
Posted on $Date.Nice by $Author
|
|
||||||
</div>
|
|
||||||
</div>
|
</div>
|
||||||
|
<% include SideBar %>
|
||||||
|
|
||||||
|
|
||||||
The first block of code is our regular second level menu; we also have our regular breadcrumbs code here. We will see
|
Most of the code is just like the regular Page.ss, we include an informational div with the date and the author of the Article.
|
||||||
how to remove these blocks of repetitive code in a bit.
|
|
||||||
|
|
||||||
We use *$Date* and *$Author* to access the new fields. In fact, all template variables and page controls come from
|
We use *$Date* and *$Author* to access the new fields. In fact, all template variables and page controls come from
|
||||||
either the data object or the controller for the page being displayed. The *$Breadcrumbs* variable comes from the
|
either the data object or the controller for the page being displayed. The *$Title* variable comes from the
|
||||||
*Breadcrumbs()* method of the `[api:SiteTree]` class. *$Date* and *$Author* come from the *Article* table through
|
*Title* field of the `[api:SiteTree]` class. *$Date* and *$Author* come from the *ArticlePage* table through
|
||||||
your data object. *$Content* comes from the *SiteTree* table through the same data object. The data for your page is
|
your custom Page. *$Content* comes from the *SiteTree* table through the same data object. The data for your page is
|
||||||
spread across several tables in the database matched by id - e.g. *Content* is in the *SiteTree* table, and *Date* and
|
spread across several tables in the database matched by id - e.g. *Content* is in the *SiteTree* table, and *Date* and
|
||||||
*Author* are in the *Article* table. SilverStripe matches these records by their ids and collates them into the single
|
*Author* are in the *ArticlePage* table. SilverStripe matches these records by their ids and collates them into the single
|
||||||
data object.
|
data object.
|
||||||
|
|
||||||
![](_images/data-collation.jpg)
|
![](_images/tutorial2_data-collation.jpg)
|
||||||
|
|
||||||
Rather than using *$Date* directly, we use *$Date.Nice*. If we look in the `[api:Date]` documentation, we can see
|
Rather than using *$Date* directly, we use *$Date.Nice*. If we look in the `[api:Date]` documentation, we can see
|
||||||
that the *Nice* function returns the date in *dd/mm/yyyy* format, rather than the *yyyy-mm-dd* format stored in the
|
that the *Nice* function returns the date in *dd/mm/yyyy* format, rather than the *yyyy-mm-dd* format stored in the
|
||||||
database.
|
database.
|
||||||
|
|
||||||
![](_images/news.jpg)
|
![](_images/tutorial2_news.jpg)
|
||||||
|
|
||||||
Now we'll create a template for the article holder: we want our news section to show a list of news items, each with a
|
Now we'll create a template for the article holder: we want our news section to show a list of news items, each with a
|
||||||
summary.
|
summary.
|
||||||
|
|
||||||
**themes/tutorial/templates/Layout/ArticleHolder.ss**
|
**themes/simple/templates/Layout/ArticleHolder.ss**
|
||||||
|
|
||||||
:::ss
|
:::ss
|
||||||
<div id="Content" class="typography">
|
<div class="content-container">
|
||||||
$Content
|
<article>
|
||||||
<ul id="NewsList">
|
<h1>$Title</h1>
|
||||||
<% control Children %>
|
$Content
|
||||||
<li class="newsDateTitle"><a href="$Link" title="Read more on "{$Title}"">$Title</a></li>
|
<div class="content">$Content</div>
|
||||||
<li class="newsDateTitle">$Date.Nice</li>
|
</article>
|
||||||
<li class="newsSummary">$Content.FirstParagraph <a href="$Link" title="Read more on "{$Title}"">Read more >></a></li>
|
<% loop Children %>
|
||||||
<% end_control %>
|
<article>
|
||||||
</ul>
|
<h2><a href="$Link" title="Read more on "{$Title}"">$Title</a></h2>
|
||||||
|
<p>$Content.FirstParagraph</p>
|
||||||
|
<a href="$Link" title="Read more on "{$Title}"">Read more >></a>
|
||||||
|
</article>
|
||||||
|
<% end_loop %>
|
||||||
|
$Form
|
||||||
</div>
|
</div>
|
||||||
|
<% include SideBar %>
|
||||||
|
|
||||||
|
|
||||||
Here we use the page control *Children*. As the name suggests, this control allows you to iterate over the children of a
|
Here we use the page control *Children*. As the name suggests, this control allows you to iterate over the children of a
|
||||||
page, which in this case is our news articles. The *$Link* variable will give the address of the article which we can
|
page, which in this case is our news articles. The *$Link* variable will give the address of the article which we can
|
||||||
use to create a link, and the *FirstParagraph* function of the `[api:HTMLText]` field gives us a nice summary of the
|
use to create a link, and the *FirstParagraph* function of the `[api:HTMLText]` field gives us a nice summary of the
|
||||||
article.
|
article. The function strips all tags from the paragraph extracted.
|
||||||
|
|
||||||
![](_images/articleholder.jpg)
|
![](_images/tutorial2_articleholder.jpg)
|
||||||
|
|
||||||
Remember that the visual styles are not part of the CMS, they are defined in the tutorial CSS file.
|
|
||||||
|
|
||||||
|
|
||||||
### Using include files in templates
|
### Using include files in templates
|
||||||
|
|
||||||
The second level menu is something we want in most, but not all, pages so we can't put it in the base template. By
|
|
||||||
putting it in a separate file in the *tutorial/templates/Includes* folder, we can use `<% include templatename %>` to
|
|
||||||
include it in our other templates. Separate the second level menu into a new file *themes/tutorial/templates/Includes/Menu2.ss*.
|
|
||||||
|
|
||||||
**themes/tutorial/templates/Includes/Menu2.ss**
|
|
||||||
|
|
||||||
:::ss
|
|
||||||
<% if Menu(2) %>
|
|
||||||
<ul id="Menu2">
|
|
||||||
<% control Menu(2) %>
|
|
||||||
<li class="$LinkingMode"><a href="$Link" title="Go to the $Title page">$MenuTitle</a></li>
|
|
||||||
<% end_control %>
|
|
||||||
</ul>
|
|
||||||
<% end_if %>
|
|
||||||
|
|
||||||
|
|
||||||
And then replace the second level menu with `<% include Menu2 %>` in *Page.ss* and *ArticlePage.ss* like so:
|
|
||||||
|
|
||||||
**themes/tutorial/templates/Layout/Page.ss**, **themes/tutorial/templates/Layout/ArticlePage.ss**
|
|
||||||
|
|
||||||
:::ss
|
|
||||||
<% include Menu2 %>
|
|
||||||
|
|
||||||
<div id="Content" class="typography">
|
|
||||||
...
|
|
||||||
|
|
||||||
|
|
||||||
Do the same with the breadcrumbs:
|
|
||||||
|
|
||||||
**themes/tutorial/templates/Includes/Breadcrumbs.ss**
|
|
||||||
|
|
||||||
:::ss
|
|
||||||
<% if Level(2) %>
|
|
||||||
<div class="breadcrumbs">
|
|
||||||
$Breadcrumbs
|
|
||||||
</div>
|
|
||||||
<% end_if %>
|
|
||||||
|
|
||||||
|
|
||||||
**themes/tutorial/templates/Layout/Page.ss**, **themes/tutorial/templates/Layout/ArticlePage.ss**
|
|
||||||
|
|
||||||
:::ss
|
|
||||||
...
|
|
||||||
<div id="Content" class="typography">
|
|
||||||
<% include Breadcrumbs %>
|
|
||||||
...
|
|
||||||
|
|
||||||
|
|
||||||
You can make your templates more modular and easier to maintain by separating commonly-used pieces into include files.
|
You can make your templates more modular and easier to maintain by separating commonly-used pieces into include files.
|
||||||
|
You are already familiar with the `<% include Sidebar %>`-Line for the menu.
|
||||||
|
|
||||||
|
We'll separate the display of linked articles as we want to reuse this code later on.
|
||||||
|
|
||||||
|
Replace the code in *ArticleHolder.ss** with an include statement:
|
||||||
|
|
||||||
|
**themes/simple/templates/Layout/ArticleHolder.ss**
|
||||||
|
|
||||||
|
:::ss
|
||||||
|
...
|
||||||
|
<% loop Children %>
|
||||||
|
<% include ArticleTeaser %>
|
||||||
|
<% end_loop %>
|
||||||
|
...
|
||||||
|
|
||||||
|
and paste the code in a new include snippet:
|
||||||
|
|
||||||
|
**themes/simple/templates/Includes/ArticleTeaser.ss**
|
||||||
|
|
||||||
|
:::ss
|
||||||
|
<article>
|
||||||
|
<h2><a href="$Link" title="Read more on "{$Title}"">$Title</a></h2>
|
||||||
|
<p>$Content.FirstParagraph</p>
|
||||||
|
<a href="$Link" title="Read more on "{$Title}"">Read more >></a>
|
||||||
|
</article>
|
||||||
|
|
||||||
### Changing the icons of pages in the CMS
|
### Changing the icons of pages in the CMS
|
||||||
|
|
||||||
@ -405,21 +382,18 @@ Let's now make a purely cosmetic change that nevertheless helps to make the info
|
|||||||
Add the following field to the *ArticleHolder* and *ArticlePage* classes:
|
Add the following field to the *ArticleHolder* and *ArticlePage* classes:
|
||||||
|
|
||||||
:::php
|
:::php
|
||||||
static $icon = "themes/tutorial/images/treeicons/news";
|
static $icon = "framework/docs/en/tutorials/_images/treeicons/news-file.gif";
|
||||||
|
|
||||||
|
|
||||||
And this one to the *HomePage* class:
|
And this one to the *HomePage* class:
|
||||||
|
|
||||||
:::php
|
:::php
|
||||||
static $icon = "themes/tutorial/images/treeicons/home";
|
static $icon = "framework/docs/en/tutorials/_images/treeicons/home-file.gif";
|
||||||
|
|
||||||
|
|
||||||
This will change the icons for the pages in the CMS.
|
This will change the icons for the pages in the CMS.
|
||||||
|
|
||||||
> Note: that the corresponding filename to the path given for $icon will end with **-file.gif**,
|
![](_images/tutorial2_icons2.jpg)
|
||||||
> e.g. when you specify **news** above, the filename will be **news-file.gif**.
|
|
||||||
|
|
||||||
![](_images/icons2.jpg)
|
|
||||||
|
|
||||||
## Showing the latest news on the homepage
|
## Showing the latest news on the homepage
|
||||||
|
|
||||||
@ -432,28 +406,25 @@ control. We can get the data for the news articles by implementing our own funct
|
|||||||
:::php
|
:::php
|
||||||
...
|
...
|
||||||
public function LatestNews($num=5) {
|
public function LatestNews($num=5) {
|
||||||
$news = DataObject::get_one("ArticleHolder");
|
$holder = DataObject::get_one("ArticleHolder");
|
||||||
return ($news) ? DataObject::get("ArticlePage", "ParentID = $news->ID", "Date DESC", "", $num) : false;
|
return ($holder) ? DataList::create('ArticlePage')->where('"ParentID" = '.$holder->ID)->sort('Date DESC')->limit($num) : false;
|
||||||
}
|
}
|
||||||
...
|
...
|
||||||
|
|
||||||
|
|
||||||
This function simply runs a database query that gets the latest news articles from the database. By default, this is
|
This function simply runs a database query that gets the latest news articles from the database. By default, this is
|
||||||
five, but you can change it by passing a number to the function. See the `[api:DataObject]` documentation for
|
five, but you can change it by passing a number to the function. See the [Data Model](../topics/datamodel) documentation for
|
||||||
details. We can reference this function as a page control in our *HomePage* template:
|
details. We can reference this function as a page control in our *HomePage* template:
|
||||||
|
|
||||||
**themes/tutorial/templates/Layout/Homepage.ss**
|
**themes/tutorial/templates/Layout/Homepage.ss**
|
||||||
|
|
||||||
:::ss
|
:::ss
|
||||||
...
|
...
|
||||||
$Content
|
<div class="content">$Content</div>
|
||||||
<ul id="NewsList">
|
</article>
|
||||||
<% control LatestNews %>
|
<% loop LatestNews %>
|
||||||
<li class="newsDateTitle"><a href="$Link" title="Read more on "{$Title}"">$Title</a></li>
|
<% include ArticleTeaser %>
|
||||||
<li class="newsDateTitle">$Date.Nice</li>
|
<% end_loop %>
|
||||||
<li class="newsSummary">$Content.FirstParagraph<a href="$Link" title="Read more on "{$Title}"">Read more >></a></li>
|
|
||||||
<% end_control %>
|
|
||||||
</ul>
|
|
||||||
...
|
...
|
||||||
|
|
||||||
|
|
||||||
@ -466,7 +437,7 @@ page is referenced in other pages, e.g. by page controls. A good rule of thumb i
|
|||||||
page currently being viewed in the controller; only if a function needs to be used in another page should you put it in
|
page currently being viewed in the controller; only if a function needs to be used in another page should you put it in
|
||||||
the data object.
|
the data object.
|
||||||
|
|
||||||
![](_images/homepage-news.jpg)
|
![](_images/tutorial2_homepage-news.jpg)
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
@ -491,7 +462,7 @@ that name on the controller if it exists.
|
|||||||
Depending on your browser, you should see something like the picture below. If your browser doesn't support RSS, you
|
Depending on your browser, you should see something like the picture below. If your browser doesn't support RSS, you
|
||||||
will most likely see the XML output instead.
|
will most likely see the XML output instead.
|
||||||
|
|
||||||
![](_images/rss-feed.jpg)
|
![](_images/tutorial2_rss-feed.jpg)
|
||||||
|
|
||||||
Now all we need is to let the user know that our RSS feed exists. The `[api:RSSFeed]` in your controller, it will be
|
Now all we need is to let the user know that our RSS feed exists. The `[api:RSSFeed]` in your controller, it will be
|
||||||
called when the page is requested. Add this function to *ArticleHolder_Controller*:
|
called when the page is requested. Add this function to *ArticleHolder_Controller*:
|
||||||
@ -505,9 +476,9 @@ called when the page is requested. Add this function to *ArticleHolder_Controlle
|
|||||||
|
|
||||||
This automatically generates a link-tag in the header of our template. The *init* function is then called on the parent
|
This automatically generates a link-tag in the header of our template. The *init* function is then called on the parent
|
||||||
class to ensure any initialization the parent would have done if we hadn't overridden the *init* function is still
|
class to ensure any initialization the parent would have done if we hadn't overridden the *init* function is still
|
||||||
called. In Firefox you can see the RSS feed link in the address bar:
|
called. Depending on your browser, you can see the RSS feed link in the address bar:
|
||||||
|
|
||||||
![](_images/rss.jpg)
|
![](_images/tutorial2_rss.jpg)
|
||||||
|
|
||||||
## Adding a staff section
|
## Adding a staff section
|
||||||
|
|
||||||
@ -553,7 +524,7 @@ insert an image in the *$Content* field).
|
|||||||
public function getCMSFields() {
|
public function getCMSFields() {
|
||||||
$fields = parent::getCMSFields();
|
$fields = parent::getCMSFields();
|
||||||
|
|
||||||
$fields->addFieldToTab("Root.Content.Images", new UploadField('Photo'));
|
$fields->addFieldToTab("Root.Images", new UploadField('Photo'));
|
||||||
|
|
||||||
return $fields;
|
return $fields;
|
||||||
}
|
}
|
||||||
@ -569,74 +540,71 @@ a simple database field like all the fields we have seen so far, but has its own
|
|||||||
array, we create a relationship between the *StaffPage* table and the *Image* table by storing the id of the respective
|
array, we create a relationship between the *StaffPage* table and the *Image* table by storing the id of the respective
|
||||||
*Image* in the *StaffPage* table.
|
*Image* in the *StaffPage* table.
|
||||||
|
|
||||||
We then add an `[api:UploadField]` in the *getCMSFields* function to the tab "Root.Content.Images". Since this tab doesn't exist,
|
We then add an `[api:UploadField]` in the *getCMSFields* function to the tab "Root.Images". Since this tab doesn't exist,
|
||||||
the *addFieldToTab* function will create it for us. The *ImageField* allows us to select an image or upload a new one in
|
the *addFieldToTab* function will create it for us. The *UploadField* allows us to select an image or upload a new one in
|
||||||
the CMS.
|
the CMS.
|
||||||
|
|
||||||
![](_images/photo.jpg)
|
![](_images/tutorial2_photo.jpg)
|
||||||
|
|
||||||
Rebuild the database ([http://localhost/dev/build?flush=1](http://localhost/dev/build?flush=1)) and open the CMS. Create
|
Rebuild the database ([http://localhost/dev/build?flush=1](http://localhost/dev/build?flush=1)) and open the CMS. Create
|
||||||
a new *StaffHolder* called "Staff" in the "About Us" section, and create some *StaffPage*s in it.
|
a new *StaffHolder* called "Staff", and create some *StaffPage*s in it.
|
||||||
|
|
||||||
![](_images/create-staff.jpg)
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
![](_images/tutorial2_create-staff.jpg)
|
||||||
|
|
||||||
|
|
||||||
### Creating the staff section templates
|
### Creating the staff section templates
|
||||||
|
|
||||||
The staff section templates aren't too difficult to create, thanks to the utility methods provided by the `[api:Image]` class.
|
The staff section templates aren't too difficult to create, thanks to the utility methods provided by the `[api:Image]` class.
|
||||||
|
|
||||||
**themes/tutorial/templates/Layout/StaffHolder.ss**
|
**themes/simple/templates/Layout/StaffHolder.ss**
|
||||||
|
|
||||||
:::ss
|
:::ss
|
||||||
<% include Menu2 %>
|
<div class="content-container">
|
||||||
|
<article>
|
||||||
<div id="Content" class="typography">
|
<h1>$Title</h1>
|
||||||
<% include Breadcrumbs %>
|
$Content
|
||||||
$Content
|
<div class="content">$Content</div>
|
||||||
|
</article>
|
||||||
<ul id="StaffList">
|
<% loop Children %>
|
||||||
<% control Children %>
|
<article>
|
||||||
<li>
|
<h2><a href="$Link" title="Read more on "{$Title}"">$Title</a></h2>
|
||||||
<div class="staffname"><a href="$Link">$Title</a></div>
|
$Photo.SetWidth(150)
|
||||||
<div class="staffphoto">$Photo.SetWidth(50)</div>
|
<p>$Content.FirstParagraph</p>
|
||||||
<div class="staffdescription"><p>$Content.FirstSentence</p></div>
|
<a href="$Link" title="Read more on "{$Title}"">Read more >></a>
|
||||||
</li>
|
</article>
|
||||||
<% end_control %>
|
<% end_loop %>
|
||||||
</ul>
|
$Form
|
||||||
</div>
|
</div>
|
||||||
|
<% include SideBar %>
|
||||||
|
|
||||||
|
|
||||||
This template is very similar to the *ArticleHolder* template. The *SetWidth* method of the `[api:Image]` class
|
This template is very similar to the *ArticleHolder* template. The *SetWidth* method of the `[api:Image]` class
|
||||||
will resize the image before sending it to the browser. The resized image is cached, so the server doesn't have to
|
will resize the image before sending it to the browser. The resized image is cached, so the server doesn't have to
|
||||||
resize the image every time the page is viewed.
|
resize the image every time the page is viewed.
|
||||||
|
|
||||||
![](_images/staff-section.jpg)
|
![](_images/tutorial2_staff-section.jpg)
|
||||||
|
|
||||||
The *StaffPage* template is also very straight forward.
|
The *StaffPage* template is also very straight forward.
|
||||||
|
|
||||||
**themes/tutorial/templates/Layout/StaffPage.ss**
|
**themes/tutorial/templates/Layout/StaffPage.ss**
|
||||||
|
|
||||||
:::ss
|
:::ss
|
||||||
<% include Menu2 %>
|
<div class="content-container">
|
||||||
|
<article>
|
||||||
<div id="Content" class="typography">
|
<h1>$Title</h1>
|
||||||
<% include Breadcrumbs %>
|
<div class="content">
|
||||||
|
$Photo.SetWidth(433)
|
||||||
<div id="StaffPhoto">
|
$Content</div>
|
||||||
$Photo.SetWidth(150)
|
</article>
|
||||||
</div>
|
$Form
|
||||||
|
$PageComments
|
||||||
$Content
|
|
||||||
</div>
|
</div>
|
||||||
|
<% include SideBar %>
|
||||||
|
|
||||||
Here we also use the *SetWidth* function to get a different sized image from the same source image. You should now have
|
Here we also use the *SetWidth* function to get a different sized image from the same source image. You should now have
|
||||||
a complete staff section.
|
a complete staff section.
|
||||||
|
|
||||||
![](_images/einstein.jpg)
|
![](_images/tutorial2_einstein.jpg)
|
||||||
|
|
||||||
## Summary
|
## Summary
|
||||||
|
|
||||||
|
@ -12,7 +12,7 @@ follow this tutorial on any site of your own.
|
|||||||
We are going to add a search box on the top of the page. When a user types something in the box, they are taken to a
|
We are going to add a search box on the top of the page. When a user types something in the box, they are taken to a
|
||||||
results page.
|
results page.
|
||||||
|
|
||||||
![](_images/searchresults-small.jpg)
|
![](_images/tutorial4_search.png)
|
||||||
|
|
||||||
## Creating the search form
|
## Creating the search form
|
||||||
|
|
||||||
@ -27,110 +27,54 @@ After including that in your `_config.php` you will need to rebuild the database
|
|||||||
The actual search form code is already provided in FulltextSearchable so when you add the enable line above to your
|
The actual search form code is already provided in FulltextSearchable so when you add the enable line above to your
|
||||||
`_config.php` you can add your form as `$SearchForm`.
|
`_config.php` you can add your form as `$SearchForm`.
|
||||||
|
|
||||||
### Custom CSS code
|
In the simple theme, the SearchForm is already added to the header. We will go through the code and explain it.
|
||||||
|
|
||||||
Add the following css code to the *themes/tutorial/css/layout.css* file. This will style the header form and search
|
|
||||||
results page.
|
|
||||||
|
|
||||||
:::css
|
|
||||||
#Header form {
|
|
||||||
float:right;
|
|
||||||
width:160px;
|
|
||||||
margin:25px 25px 0px 25px;
|
|
||||||
}
|
|
||||||
#Header form * {
|
|
||||||
display:inline !important;
|
|
||||||
}
|
|
||||||
#Header form div {
|
|
||||||
}
|
|
||||||
#Header form input.text {
|
|
||||||
width:110px;
|
|
||||||
color:#000;
|
|
||||||
background:#f0f0f0;
|
|
||||||
border:1px solid #aaa;
|
|
||||||
padding:3px;
|
|
||||||
}
|
|
||||||
#Header form input.action {
|
|
||||||
font-weight:bold;
|
|
||||||
}
|
|
||||||
|
|
||||||
.searchResults h2 {
|
|
||||||
font-size:2.2em;
|
|
||||||
font-weight:normal;
|
|
||||||
color:#0083C8;
|
|
||||||
margin-bottom:15px;
|
|
||||||
}
|
|
||||||
.searchResults p.searchQuery {
|
|
||||||
color:#333;
|
|
||||||
margin-bottom:10px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.searchResults ul#SearchResults li {
|
|
||||||
margin-bottom:20px;
|
|
||||||
}
|
|
||||||
ul#SearchResults p {
|
|
||||||
font-size:1.1em;
|
|
||||||
font-weight:normal;
|
|
||||||
line-height:2em;
|
|
||||||
color:#333;
|
|
||||||
}
|
|
||||||
ul#SearchResults a.searchResultHeader {
|
|
||||||
font-size:1.3em;
|
|
||||||
font-weight:bold;
|
|
||||||
color:#0083C8;
|
|
||||||
text-decoration:none;
|
|
||||||
margin:20px 0 8px 0;
|
|
||||||
padding-left:20px;
|
|
||||||
background:url(../images/treeicons/search-file.gif) no-repeat left center;
|
|
||||||
}
|
|
||||||
ul#SearchResults a {
|
|
||||||
text-decoration:none;
|
|
||||||
color:#0083C8;
|
|
||||||
}
|
|
||||||
ul#SearchResults a:hover {
|
|
||||||
border-bottom:1px dotted #0083C8;
|
|
||||||
}
|
|
||||||
|
|
||||||
## Adding the search form
|
## Adding the search form
|
||||||
|
|
||||||
We then just need to add the search form to the template. Add *$SearchForm* to the 'Header' div in
|
To add the search form, we can add `$SearchForm` anywhere in our templates. In the simple theme, this is in
|
||||||
*themes/tutorial/templates/Page.ss*.
|
*themes/simple/templates/Includes/Header.ss*
|
||||||
|
|
||||||
*themes/tutorial/templates/Page.ss*
|
*themes/simple/templates/Includes/Header.ss*
|
||||||
|
|
||||||
:::ss
|
:::ss
|
||||||
<div id="Header">
|
...
|
||||||
$SearchForm
|
<% if SearchForm %>
|
||||||
<h1>$Title</h1>
|
<span class="search-dropdown-icon">L</span>
|
||||||
</div>
|
<div class="search-bar">
|
||||||
|
$SearchForm
|
||||||
|
<span class="search-bubble-arrow">}</span>
|
||||||
|
</div>
|
||||||
|
<% end_if %>
|
||||||
|
<% include Navigation %>
|
||||||
|
|
||||||
|
This results in:
|
||||||
|
|
||||||
![](_images/searchform.jpg)
|
![](_images/tutorial4_searchbox.png)
|
||||||
|
|
||||||
## Showing the results
|
## Showing the results
|
||||||
|
|
||||||
Next we need to create the *results* function.
|
The results function is already included in the `ContentControllerSearchExtension` which
|
||||||
|
is applied via `FulltextSearchable::enable()`
|
||||||
|
|
||||||
*mysite/code/Page.php*
|
*cms/code/search/ContentControllerSearchExtension.php*
|
||||||
|
|
||||||
:::php
|
:::php
|
||||||
class Page_Controller extends ContentController {
|
class ContentControllerSearchExtension extends Extension {
|
||||||
...
|
...
|
||||||
|
|
||||||
public function results($data, $form){
|
function results($data, $form, $request) {
|
||||||
$data = array(
|
$data = array(
|
||||||
'Results' => $form->getResults(),
|
'Results' => $form->getResults(),
|
||||||
'Query' => $form->getSearchQuery(),
|
'Query' => $form->getSearchQuery(),
|
||||||
'Title' => 'Search Results'
|
'Title' => _t('SearchForm.SearchResults', 'Search Results')
|
||||||
);
|
);
|
||||||
$this->Query = $form->getSearchQuery();
|
return $this->owner->customise($data)->renderWith(array('Page_results', 'Page'));
|
||||||
|
|
||||||
return $this->customise($data)->renderWith(array('Page_results', 'Page'));
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
First we populate an array with the data we wish to pass to the template - the search results, query and title of the
|
The code populates an array with the data we wish to pass to the template - the search results, query and title of the
|
||||||
page. The final line is a little more complicated.
|
page. The final line is a little more complicated.
|
||||||
|
|
||||||
When we call a function by its url (eg http://localhost/home/results), SilverStripe will look for a template with the
|
When we call a function by its url (eg http://localhost/home/results), SilverStripe will look for a template with the
|
||||||
@ -153,67 +97,68 @@ function, and then attempt to render it with *Page_results.ss*, falling back to
|
|||||||
|
|
||||||
## Creating the template
|
## Creating the template
|
||||||
|
|
||||||
Lastly we need to create the template for the search page. This template uses all the same techniques used in previous
|
Lastly we need the template for the search page. This template uses all the same techniques used in previous
|
||||||
tutorials. It also uses a number of pagination variables, which are provided by the `[api:DataObjectSet]`
|
tutorials. It also uses a number of pagination variables, which are provided by the `[api:DataObjectSet]`
|
||||||
class.
|
class.
|
||||||
|
|
||||||
*themes/tutorial/templates/Layout/Page_results.ss*
|
*themes/simple/templates/Layout/Page_results.ss*
|
||||||
|
|
||||||
:::ss
|
:::ss
|
||||||
<div id="Content" class="searchResults">
|
<div id="Content" class="searchResults">
|
||||||
<h2>$Title</h2>
|
<h1>$Title</h1>
|
||||||
|
|
||||||
<% if Query %>
|
<% if Query %>
|
||||||
<p class="searchQuery"><strong>You searched for "{$Query}"</strong></p>
|
<p class="searchQuery"><strong>You searched for "{$Query}"</strong></p>
|
||||||
<% end_if %>
|
<% end_if %>
|
||||||
|
|
||||||
<% if Results %>
|
<% if Results %>
|
||||||
<ul id="SearchResults">
|
<ul id="SearchResults">
|
||||||
<% control Results %>
|
<% control Results %>
|
||||||
<li>
|
<li>
|
||||||
<a class="searchResultHeader" href="$Link">
|
<a class="searchResultHeader" href="$Link">
|
||||||
<% if MenuTitle %>
|
<% if MenuTitle %>
|
||||||
$MenuTitle
|
$MenuTitle
|
||||||
<% else %>
|
<% else %>
|
||||||
$Title
|
$Title
|
||||||
<% end_if %>
|
<% end_if %>
|
||||||
</a>
|
</a>
|
||||||
<p>$Content.LimitWordCountXML</p>
|
<p>$Content.LimitWordCountXML</p>
|
||||||
<a class="readMoreLink" href="$Link" title="Read more about "{$Title}"">Read more about "{$Title}"...</a>
|
<a class="readMoreLink" href="$Link"
|
||||||
</li>
|
title="Read more about "{$Title}""
|
||||||
<% end_control %>
|
>Read more about "{$Title}"...</a>
|
||||||
</ul>
|
</li>
|
||||||
<% else %>
|
<% end_control %>
|
||||||
<p>Sorry, your search query did not return any results.</p>
|
</ul>
|
||||||
<% end_if %>
|
<% else %>
|
||||||
|
<p>Sorry, your search query did not return any results.</p>
|
||||||
|
<% end_if %>
|
||||||
|
|
||||||
<% if Results.MoreThanOnePage %>
|
<% if Results.MoreThanOnePage %>
|
||||||
<div id="PageNumbers">
|
<div id="PageNumbers">
|
||||||
<% if Results.NotLastPage %>
|
<% if Results.NotLastPage %>
|
||||||
<a class="next" href="$Results.NextLink" title="View the next page">Next</a>
|
<a class="next" href="$Results.NextLink" title="View the next page">Next</a>
|
||||||
<% end_if %>
|
<% end_if %>
|
||||||
<% if Results.NotFirstPage %>
|
<% if Results.NotFirstPage %>
|
||||||
<a class="prev" href="$Results.PrevLink" title="View the previous page">Prev</a>
|
<a class="prev" href="$Results.PrevLink" title="View the previous page">Prev</a>
|
||||||
<% end_if %>
|
<% end_if %>
|
||||||
<span>
|
<span>
|
||||||
<% control Results.Pages %>
|
<% control Results.Pages %>
|
||||||
<% if CurrentBool %>
|
<% if CurrentBool %>
|
||||||
$PageNum
|
$PageNum
|
||||||
<% else %>
|
<% else %>
|
||||||
<a href="$Link" title="View page number $PageNum">$PageNum</a>
|
<a href="$Link" title="View page number $PageNum">$PageNum</a>
|
||||||
<% end_if %>
|
<% end_if %>
|
||||||
<% end_control %>
|
<% end_control %>
|
||||||
</span>
|
</span>
|
||||||
<p>Page $Results.CurrentPage of $Results.TotalPages</p>
|
<p>Page $Results.CurrentPage of $Results.TotalPages</p>
|
||||||
</div>
|
</div>
|
||||||
<% end_if %>
|
<% end_if %>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
Then finally add ?flush=1 to the URL and you should see the new template.
|
Then finally add ?flush=1 to the URL and you should see the new template.
|
||||||
|
|
||||||
|
|
||||||
![](_images/searchresults.jpg)
|
![](_images/tutorial4_search.png)
|
||||||
|
|
||||||
|
|
||||||
## Summary
|
## Summary
|
||||||
|
|
||||||
|
Before Width: | Height: | Size: 21 KiB |
Before Width: | Height: | Size: 55 KiB |
Before Width: | Height: | Size: 34 KiB |
Before Width: | Height: | Size: 84 KiB |
Before Width: | Height: | Size: 39 KiB |
Before Width: | Height: | Size: 46 KiB |
Before Width: | Height: | Size: 91 KiB |
Before Width: | Height: | Size: 32 KiB |
Before Width: | Height: | Size: 34 KiB |
Before Width: | Height: | Size: 63 KiB |
Before Width: | Height: | Size: 54 KiB |
Before Width: | Height: | Size: 23 KiB |
Before Width: | Height: | Size: 18 KiB |
Before Width: | Height: | Size: 65 KiB |
Before Width: | Height: | Size: 35 KiB |
Before Width: | Height: | Size: 59 KiB |
Before Width: | Height: | Size: 58 KiB |
Before Width: | Height: | Size: 68 KiB |
Before Width: | Height: | Size: 29 KiB |
Before Width: | Height: | Size: 64 KiB |
Before Width: | Height: | Size: 33 KiB |
Before Width: | Height: | Size: 17 KiB |
Before Width: | Height: | Size: 63 KiB |
Before Width: | Height: | Size: 14 KiB After Width: | Height: | Size: 15 KiB |
Before Width: | Height: | Size: 58 KiB |
Before Width: | Height: | Size: 33 KiB |
Before Width: | Height: | Size: 61 KiB |
Before Width: | Height: | Size: 19 KiB |
Before Width: | Height: | Size: 66 KiB |
BIN
docs/en/tutorials/_images/treeicons/home-file.gif
Normal file
After Width: | Height: | Size: 173 B |
BIN
docs/en/tutorials/_images/treeicons/news-file.gif
Normal file
After Width: | Height: | Size: 176 B |
BIN
docs/en/tutorials/_images/treeicons/search-file.gif
Normal file
After Width: | Height: | Size: 170 B |
BIN
docs/en/tutorials/_images/tutorial1_2nd_level-cut.jpg
Normal file
After Width: | Height: | Size: 34 KiB |
BIN
docs/en/tutorials/_images/tutorial1_addpage.jpg
Normal file
After Width: | Height: | Size: 52 KiB |
BIN
docs/en/tutorials/_images/tutorial1_cms-basic.jpg
Normal file
After Width: | Height: | Size: 31 KiB |
BIN
docs/en/tutorials/_images/tutorial1_cms-numbered-2b.jpg
Normal file
After Width: | Height: | Size: 11 KiB |
BIN
docs/en/tutorials/_images/tutorial1_cms-numbered.jpg
Normal file
After Width: | Height: | Size: 44 KiB |
BIN
docs/en/tutorials/_images/tutorial1_editpage-numbered.jpg
Normal file
After Width: | Height: | Size: 10 KiB |
BIN
docs/en/tutorials/_images/tutorial1_home-small.jpg
Normal file
After Width: | Height: | Size: 15 KiB |
BIN
docs/en/tutorials/_images/tutorial1_home-template.jpg
Normal file
After Width: | Height: | Size: 21 KiB |
BIN
docs/en/tutorials/_images/tutorial1_homepage-type.jpg
Normal file
After Width: | Height: | Size: 26 KiB |
BIN
docs/en/tutorials/_images/tutorial1_menu-two-level-small.jpg
Normal file
After Width: | Height: | Size: 8.7 KiB |
BIN
docs/en/tutorials/_images/tutorial1_menu-two-level.jpg
Normal file
After Width: | Height: | Size: 17 KiB |
BIN
docs/en/tutorials/_images/tutorial1_menu.jpg
Normal file
After Width: | Height: | Size: 4.7 KiB |
BIN
docs/en/tutorials/_images/tutorial1_subtemplates-diagram.jpg
Normal file
After Width: | Height: | Size: 18 KiB |
BIN
docs/en/tutorials/_images/tutorial1_url.jpg
Normal file
After Width: | Height: | Size: 9.8 KiB |
BIN
docs/en/tutorials/_images/tutorial2_articleholder.jpg
Normal file
After Width: | Height: | Size: 62 KiB |
BIN
docs/en/tutorials/_images/tutorial2_create-staff.jpg
Normal file
After Width: | Height: | Size: 92 KiB |
BIN
docs/en/tutorials/_images/tutorial2_data-collation.jpg
Normal file
After Width: | Height: | Size: 36 KiB |
BIN
docs/en/tutorials/_images/tutorial2_einstein.jpg
Normal file
After Width: | Height: | Size: 60 KiB |
BIN
docs/en/tutorials/_images/tutorial2_homepage-news.jpg
Normal file
After Width: | Height: | Size: 55 KiB |
BIN
docs/en/tutorials/_images/tutorial2_icons2.jpg
Normal file
After Width: | Height: | Size: 18 KiB |
BIN
docs/en/tutorials/_images/tutorial2_news-cms.jpg
Normal file
After Width: | Height: | Size: 82 KiB |
BIN
docs/en/tutorials/_images/tutorial2_news.jpg
Normal file
After Width: | Height: | Size: 83 KiB |
BIN
docs/en/tutorials/_images/tutorial2_newslist.jpg
Normal file
After Width: | Height: | Size: 75 KiB |
BIN
docs/en/tutorials/_images/tutorial2_pagetype-inheritance.jpg
Normal file
After Width: | Height: | Size: 32 KiB |
BIN
docs/en/tutorials/_images/tutorial2_photo.jpg
Normal file
After Width: | Height: | Size: 26 KiB |
BIN
docs/en/tutorials/_images/tutorial2_rss-feed.jpg
Normal file
After Width: | Height: | Size: 120 KiB |
BIN
docs/en/tutorials/_images/tutorial2_staff-section.jpg
Normal file
After Width: | Height: | Size: 40 KiB |
BIN
docs/en/tutorials/_images/tutorial4_search.png
Normal file
After Width: | Height: | Size: 85 KiB |
BIN
docs/en/tutorials/_images/tutorial4_searchbox.png
Normal file
After Width: | Height: | Size: 5.1 KiB |
Before Width: | Height: | Size: 19 KiB |
BIN
docs/en/tutorials/_images/welcome.png
Normal file
After Width: | Height: | Size: 19 KiB |