diff --git a/docs/en/02_Developer_Guides/01_Templates/00_Page_Type_Templates.md b/docs/en/02_Developer_Guides/01_Templates/00_Page_Type_Templates.md deleted file mode 100644 index d3fa469ec..000000000 --- a/docs/en/02_Developer_Guides/01_Templates/00_Page_Type_Templates.md +++ /dev/null @@ -1,285 +0,0 @@ -# Building templates for page types - -Much of your work building a SilverStripe site will involve the creation of -templates for your own page types. SilverStripe has its own template language. -Its basic features like variables, blocks and loops are described in our ["templates" reference guide](/reference/templates). -In this guide, we'll show you specific uses for creating page layouts. -This assumes you are familiar with the concept of ["page types"](/topics/page-types). - -To get a feel for what those templates look like, let's have a look at an abbreviated example. In your webroot, these templates are usually located in `themes//templates`. -Replace the `` placeholder accordingly, most likely you're using a theme called "simple") -Most of the magic happens in `Page.ss` and `Layout/Page.ss`. - -`themes//templates/Page.ss` - - :::ss - - - <% base_tag %> - $SiteConfig.Title | $Title - $MetaTags(false) - - -
-
-

Bob's Chicken Shack

-
- - - <% if $Menu(1) %> -
    - <% loop $Menu(1) %> -
  • $MenuTitle
  • - <% end_loop %> -
- <% end_if %> -
- -
- $Layout -
- -
- - - - -`themes//templates/Layout/Page.ss` - -

$Title

- $Content - $Form - -### Template inheritance through $Layout - -Our example shows two templates, both called `Page.ss`. -One is located in the `templates/` "root" folder, the other one in a `templates/Layout/` subfolder. -This "inner template" is used by the `$Layout` placeholder in the "root template", -and is inherited based on the underlying PHP classes (read more about template inheritance -on the ["page types" topic](/topics/page-types)). - -"Layout" is a fixed naming convention, -you can't use the same pattern for other folder names. - -### Page Content - - :::ss - $Content - -This variable in the `Layout` template contains the main content of the current page, -edited through the WYSIWIG editor in the CMS. -It returns the database content of the `SiteTree.Content` property. - -Please note that this database content can be "staged", -meaning that draft content edited in the CMS can be different from published content -shown to your website visitors. In templates, you don't need to worry about this distinction. -The `$Content` variable contain the published content by default, -and only preview draft content if explicitly requested (e.g. by the "preview" feature in the CMS) -(see the ["versioning" topic](topics/versioning) for more details). - -### Menu Loops - - :::ss - <% loop $Menu(1) %>...<% end_loop %> - -`$Menu(1)` is a built-in page control that defines the top-level menu. -You can also create a sub-menu using `$Menu(2)`, and so forth. - -The `<% loop $Menu(1) %>...<% end_loop %>` block defines a repeating element. -It will change the "scope" of your template, which means that all of the template variables you use inside it will refer to a menu item. The template code will be repeated once per menu item, with the scope set to that menu item's page. In this case, a menu item refers to an instance -of the `Page` class, so you can access all properties defined on there, for example `$Title`. - -Note that pages with the `ShowInMenus` property set to FALSE will be filtered out -(its a checkbox in the "Settings" panel of the CMS). - -### Children Loops - - :::ss - <% loop $Children %>...<% end_loop %> - -Will loop over all children of the current page context. -Helpful to create page-specific subnavigations. -Most likely, you'll want to use `<% loop $Menu %>` for your main menus, -since its independent of the page context. - - :::ss - <% loop $ChildrenOf() %>...<% end_loop %> - -Will create a list of the children of the given page, -as identified by its `URLSegment` value. This can come in handy because its not dependent -on the context of the current page. For example, it would allow you to list all staff member pages -underneath a "staff" holder on any page, regardless if its on the top level or elsewhere. - - :::ss - <% loop $allChildren %>...<% end_loop %> - -This will show all children of a page even if the `ShowInMenus` property is set to FALSE. - -### Access to Parent and Level Pages - - :::ss - <% with $Level(1) %> - $Title - <% end_with %> - -Will return a page in the current path, at the level specified by the numbers. -It is based on the current page context, looking back through its parent pages. - -For example, imagine you're on the "bob marley" page, -which is three levels in: "about us > staff > bob marley". - -* `$Level(1).Title` would return "about us" -* `$Level(2).Title` would return "staff" -* `$Level(3).Title` would return "bob marley" - -To simply retrieve the parent page of the current context (if existing), use the `$Parent` variable. - -### Access to a specific Page - - :::ss - <% with $Page(my-page) %>...<% end_with %>` - -"Page" will return a single page from the site tree, looking it up by URL. You can use it in the `<% loop %>` format. -Can't be called using `$Page(my-page).Title`. - -### Title and Menu Title - -The CMS provides two fields to label a page: "Title" and "Menu Title". -"Title" is the title in its full length, while "Menu Title" can be -a shorter version suitable for size-constrained menus. -If "Menu Title" is left blank by the CMS author, it'll just default to "Title". - -### Links and Linking Modes - - :::ss - $LinkingMode - -Each menu item we loop over knows its location on the website, so can generate a link to it. -This happens through the `[api:SiteTree->Link()]` method behind the scenes. -We're not using the direct database property `SiteTree.URLSegment` here -because pages can be nested, so the link needs to be generated on the fly. -In the template syntax, there's no distinction between a method and a property though. -The link is relative by default (see `<% base_tag %>`), -you can get an absolute one including the domain through [$AbsoluteLink](api:SiteTree->AbsoluteLink())`. - -In addition, each menu item gets some context information relative -to the page you're currently viewing, contained in the `$LinkingMode` placeholder. -By setting a HTML class to this value, you can distinguish the styling of -the currently selected menu item. It can have the following values: - - * `link`: You are neither on this page nor in this section. - * `current`: You are currently on this page. - * `section`: The current page is a child of this menu item, so the current "section" - -More common uses: - - * `$LinkOrCurrent`: Determines if the item is the current page. Returns "link" or "current" strings. - * `$LinkOrSection`: Determines if the item is in the current section, so in the path towards the current page. Useful for menus which you only want to show a second level menu when you are on that page or a child of it. Returns "link" or "section" strings. - * `InSection(page-url)`: This if block will pass if we're currently on the page-url page or one of its children. - -Example: Only show the menu item linked if its the current one: - - :::ss - <% if $LinkOrCurrent = current %> - $Title - <% else %> - $Title - <% end_if %> - -### Breadcrumbs - -Breadcrumbs are the path of parent pages which needs to be taken -to reach the current page, and can be a great navigation aid for website users. - -While you can achieve breadcrumbs through the `<% Level() %>` control already, -there's a nicer shortcut: The `$Breadcrumbs` control. - -It uses its own template defined in `BreadcrumbsTemplate.ss`. -Simply place a file with the same name in your `themes//templates` -folder to customize its output. Here's the default template: - - :::ss - <% if $Pages %> - <% loop $Pages %> - <% if $Last %>$Title.XML<% else %>$MenuTitle.XML »<% end_if %> - <% end_loop %> - <% end_if %> - -For more customization options like limiting the amount of breadcrumbs, -take a look at `[api:SiteTree->Breadcrumbs()]`. - -### SiteConfig: Global settings - - :::ss - $SiteConfig.Title - -The ["SiteConfig"](/reference/siteconfig) object allows content authors -to modify global data in the CMS, rather than PHP code. -By default, this includes a website title and tagline -(as opposed to the title of a specific page). -It can be extended to hold other data, for example a logo image -which can be uploaded through the CMS. -The object is available to all page templates through the `$SiteConfig` placeholder. - -### Meta Tags - -The `$MetaTags` placeholder in a template returns a segment of HTML appropriate for putting into the `` tag. It -will set up title, keywords and description meta-tags, based on the CMS content and is editable in the 'Meta-data' tab -on a per-page basis. If you don’t want to include the title-tag `` (for custom templating), use -`$MetaTags(false)`. - -By default `$MetaTags` renders: - - :::ss - <title>Title of the Page - - - -#### URLSegment - -This returns the part of the URL of the page you're currently on. -Shouldn't be used for linking to a page, since the link -is a composite value based on all parent pages as well (through the `$Link` variable). - -#### ClassName - -Returns the class of the underlying `Page` record. -This can be handy to add to your `` tag to influence -CSS styles and JavaScript behaviour based on the page type used: - - :::ss - - -In case you want to include parent PHP classes in this list as well, -use the `$CSSClasses` placeholder instead. - -#### BaseHref - -Returns the base URL for the current site. -This is used to populate the `` tag by default. -Can be handy to prefix custom links (not generated through `SiteTree->Link()`), -to ensure they work correctly when the webroot is hosted in a subfolder -rather than its own domain (a common development setup). - -### Forms - - :::ss - $Form - -Very often, a page will contain some content and a form of some kind. For example, the log-in page has a log-in form. If you are on such a page, the `$Form` variable will contain the HTML content of the form. Placing it just below `$Content` is a good default. Behind the scenes, -it maps to the `Page_Controller->Form()` method. You can add more forms by implementing -new methods there (see ["forms" topic](/topics/forms) for details). - -### More Advanced Controls - -Template variables and controls are just PHP properties and methods -on the underlying controllers and model classes. -We've just shown you the most common once, in practice -you can use any public API on those classes, and [extend](/reference/dataextension) them -with your own. To get an overview on what's available to you, -we recommend that you dive into the API docs for the following classes: - - * `[api:ContentController]`: The main controller responsible for handling pages - * `[api:Controller]`: Generic controller (not specific to pages) - * `[api:DataObject]`: Underlying model class for page objects - * `[api:ViewableData]`: Underlying object class for pretty much anything displayable diff --git a/docs/en/02_Developer_Guides/01_Templates/01_Syntax.md b/docs/en/02_Developer_Guides/01_Templates/01_Syntax.md new file mode 100644 index 000000000..fa4bfe7d5 --- /dev/null +++ b/docs/en/02_Developer_Guides/01_Templates/01_Syntax.md @@ -0,0 +1,487 @@ +title: Template Syntax +summary: A look at the operations, variables and language controls you can use within templates. + +# Template Syntax + +SilverStripe templates are plain text files that have `.ss` extension and located within the `templates` directory of +a module, theme, or your `mysite` folder. A template can contain any markup language (e.g HTML, CSV, JSON..) and before +being rendered to the user, they're processed through [api:SSViewer]. This process replaces placeholders such as `$Var` +with real content from your [model](../model) and allows you to define logic controls like `<% if $Var %>`. + +An example of a SilverStripe template is below: + +**mysite/templates/Page.ss** + + :::ss + + + <% base_tag %> + $Title + <% require themedCSS("screen") %> + + +
+

Bob's Chicken Shack

+
+ + <% with $CurrentMember %> +

Welcome $FirstName $Surname.

+ <% end_with %> + + <% if $Dishes %> +
    + <% loop $Dishes %> +
  • $Title ($Price.Nice)
  • + <% end_loop %> +
+ <% end_if %> + + <% include Footer %> + + + +
+Templates can be used for more than HTML output. You can use them to output your data as JSON, XML, CSV or any other +text based format. +
+ +## Variables + +Variables are placeholders that will be replaced with data from the [DataModel](../model/) or the current +[Controller](../controllers). Variables are prefixed with a `$` character. Variable names must start with an +alphabetic character or underscore, with subsequent characters being alphanumeric or underscore: + + :::ss + $Title + +This inserts the value of the Title database field of the page being displayed in place of `$Title`. + +Variables can be chained together, and include arguments. + + :::ss + $Foo + $Foo(param) + $Foo.Bar + +These variables will call a method / field on the object and insert the returned value as a string into the template. + +* `$Foo` will call `$obj->Foo()` (or the field `$obj->Foo`) +* `$Foo(param)` will call `$obj->Foo("param")` +* `$Foo.Bar` will call `$obj->Foo()->Bar()` + +If a variable returns a string, that string will be inserted into the template. If the variable returns an object, then +the system will attempt to render the object through its' `forTemplate()` method. If the `forTemplate()` method has not +been defined, the system will return an error. + +
+For more detail around how variables are inserted and formatted into a template see +[Formating, Modifying and Casting Variables](casting) +
+ +Variables can come from your database fields, or custom methods you define on your objects. + +**mysite/code/Page.php** + + :::php + public function UsersIpAddress() { + return $this->request->getIP(); + } + +**mysite/code/Page.ss** + + :::html +

You are coming from $UsersIpAddress.

+ +The variable's that can be used in a template vary based on the object currently in [scope](#scope). Scope defines what +object the methods get called on. For the standard `Page.ss` template the scope is the current [api:Page_Controller] +class. This object gives you access to all the database fields on [api:Page_Controller], its corresponding [api:Page] +record and any subclasses of those two. + +**mysite/code/Layout/Page.ss** + + :::ss + $Title + // returns the page `Title` property + + $Content + // returns the page `Content` property + + +## Conditional Logic + +The simplest conditional block is to check for the presence of a value (does not equal 0, null, false). + + :::ss + <% if $CurrentMember %> +

You are logged in as $CurrentMember.FirstName $CurrentMember.Surname.

+ <% end_if %> + +A conditional can also check for a value other than falsey. + + :::ss + <% if $MyDinner == "kipper" %> + Yummy, kipper for tea. + <% end_if %> + +
+When inside template tags variables should have a '$' prefix, and literals should have quotes. +
+ +Conditionals can also provide the `else` case. + + :::ss + <% if $MyDinner == "kipper" %> + Yummy, kipper for tea + <% else %> + I wish I could have kipper :-( + <% end_if %> + +`else_if` commands can be used to handle multiple `if` statements. + + :::ss + <% if $MyDinner == "quiche" %> + Real men don't eat quiche + <% else_if $MyDinner == $YourDinner %> + We both have good taste + <% else %> + Can I have some of your chips? + <% end_if %> + +### Negation + +The inverse of `<% if %>` is `<% if not %>`. + + :::ss + <% if not $DinnerInOven %> + I'm going out for dinner tonight. + <% end_if %> + +### Boolean Logic + +Multiple checks can be done using `||`, `or`, `&&` or `and`. + +If *either* of the conditions is true. + + :::ss + <% if $MyDinner == "kipper" || $MyDinner == "salmon" %> + yummy, fish for tea + <% end_if %> + +If *both* of the conditions are true. + + :::ss + <% if $MyDinner == "quiche" && $YourDinner == "kipper" %> + Lets swap dinners + <% end_if %> + +### Inequalities + +You can use inequalities like `<`, `<=`, `>`, `>=` to compare numbers. + + :::ss + <% if $Number >= "5" && $Number <= "10" %> + Number between 5 and 10 + <% end_if %> + + +## Includes + +Within SilverStripe templates we have the ability to include other templates from the `template/Includes` directory +using the `<% include %>` tag. + + :::ss + <% include SideBar %> + +The `include` tag can be particularly helpful for nested functionality and breaking large templates up. In this example, +the include only happens if the user is logged in. + + :::ss + <% if $CurrentMember %> + <% include MembersOnlyInclude %> + <% end_if %> + +Includes can't directly access the parent scope when the include is included. However you can pass arguments to the +include. + + :::ss + <% with $CurrentMember %> + <% include MemberDetails Top=$Top, Name=$Name %> + <% end_with %> + + +## Looping Over Lists + +The `<% loop %>` tag is used to iterate or loop over a collection of items such as [api:DataList] or a [api:ArrayList] +collection. + + :::ss +

Children of $Title

+ +
    + <% loop $Children %> +
  • $Title
  • + <% end_loop %> +
+ +This snippet loops over the children of a page, and generates an unordered list showing the `Title` property from each +page. + +
+$Title inside the loop refers to the Title property on each object that is looped over, not the current page like +the reference of `$Title` outside the loop. + +This demonstrates the concept of [Scope](#scope). When inside a <% loop %> the scope of the template has changed to the +object that is being looped over. +
+ +### Altering the list + +`<% loop %>` statements iterate over a [api:DataList] instance. As the template has access to the list object, +templates can call [api:DataList] methods. + +Sort the list by a given field. + + :::ss +
    + <% loop $Children.Sort(Title, ASC) %> +
  • $Title
  • + <% end_loop %> +
+ +Limiting the number of items displayed. + + :::ss +
    + <% loop $Children.Limit(10) %> +
  • $Title
  • + <% end_loop %> +
+ +Reversing the loop. + + :::ss +
    + <% loop $Children.Reverse %> +
  • $Title
  • + <% end_loop %> +
+ +Filtering the loop + + :::ss +
    + <% loop $Children.Filter('School', 'College') %> +
  • $Title
  • + <% end_loop %> +
+ +Methods can also be chained + + :::ss +
    + <% loop $Children.Filter('School', 'College').Sort(Score, DESC) %> +
  • $Title
  • + <% end_loop %> +
+ +### Position Indicators + +Inside the loop scope, there are many variables at your disposal to determine the current position in the list and +iteration. + + * `$Even`, `$Odd`: Returns boolean, handy for zebra striping + * `$EvenOdd`: Returns a string, either 'even' or 'odd'. Useful for CSS classes. + * `$First`, `$Last`, `$Middle`: Booleans about the position in the list + * `$FirstLast`: Returns a string, "first", "last", or "". Useful for CSS classes. + * `$Pos`: The current position in the list (integer). Will start at 1. + * `$TotalItems`: Number of items in the list (integer) + + :::ss +
    + <% loop $Children.Reverse %> + <% if First %> +
  • My Favourite
  • + <% end_if %> + +
  • Child $Pos of $TotalItems - $Title
  • + <% end_loop %> +
+ +
+A common task is to paginate your lists. See the [Pagination](how_tos/pagination) how to for a tutorial on adding +pagination. +
+ +### Modulus and MultipleOf + +$Modulus and $MultipleOf can help to build column and grid layouts. + + :::ss + // returns an int + $Modulus(value, offset) + + // returns a boolean. + $MultipleOf(factor, offset) + + <% loop $Children %> +
+ ... +
+ <% end_loop %> + + // returns
,
, + +
+`$Modulus` is useful for floated grid CSS layouts. If you want 3 rows across, put $Modulus(3) as a class and add a +`clear: both` to `.column-1`. +
+ +$MultipleOf(value, offset) can also be utilized to build column and grid layouts. In this case we want to add a `
` +after every 3th item. + + :::ss + <% loop $Children %> + <% if $MultipleOf(3) %> +
+ <% end_if %> + <% end_loop %> + +### Escaping + +Sometimes you will have template tags which need to roll into one another. Use `{}` to contain variables. + + :::ss + $Foopx // will returns "" (as it looks for a `Foopx` value) + {$Foo}px // returns "3px" (CORRECT) + + +Or when having a `$` sign in front of the variable such as displaying money. + + :::ss + $$Foo // returns "" + ${$Foo} // returns "$3" + +You can also use a backslash to escape the name of the variable, such as: + + :::ss + $Foo // returns "3" + \$Foo // returns "$Foo" + +
+For more information on formatting and casting variables see [Formating, Modifying and Casting Variables](casting) +
+ +## Scope + +In the `<% loop %>` section, we saw an example of two **scopes**. Outside the `<% loop %>...<% end_loop %>`, we were in +the scope of the top level `Page`. But inside the loop, we were in the scope of an item in the list (i.e the `Child`) + +The scope determines where the value comes from when you refer to a variable. Typically the outer scope of a `Page.ss` +layout template is the [api:Page_Controller] that is currently being rendered. + +When the scope is a `Page_Controller` it will automatically also look up any methods in the corresponding `Page` data +record. In the case of `$Title` the flow looks like + + $Title --> [Looks up: Current Page_Controller and parent classes] --> [Looks up: Current Page and parent classes]. + +The list of variables you could use in your template is the total of all the methods in the current scope object, parent +classes of the current scope object, and any [api:Extension] instances you have. + +### Navigating Scope + +#### Up + +When in a particular scope, `$Up` takes the scope back to the previous level. + + :::ss +

Children of '$Title'

+ + <% loop $Children %> +

Page '$Title' is a child of '$Up.Title'

+ + <% loop $Children %> +

Page '$Title' is a grandchild of '$Up.Up.Title'

+ <% end_loop %> + <% end_loop %> + +Given the following structure, it will output the text. + + My Page + | + +-+ Child 1 + | | + | +- Grandchild 1 + | + +-+ Child 2 + + Children of 'My Page' + + Page 'Child 1' is a child of 'My Page' + Page 'Grandchild 1' is a grandchild of 'My Page' + Page 'Child 2' is a child of 'MyPage' + + +#### Top + +While `$Up` provides us a way to go up one level of scope, `$Top` is a shortcut to jump to the top most scope of the +page. The previous example could be rewritten to use the following syntax. + + :::ss +

Children of '$Title'

+ + <% loop $Children %> +

Page '$Title' is a child of '$Top.Title'

+ + <% loop $Children %> +

Page '$Title' is a grandchild of '$Top.Title'

+ <% end_loop %> + <% end_loop %> + + + +### With + +The `<% with %>` tag lets you change into a new scope. Consider the following example: + + :::ss + <% with $CurrentMember %> + Hello $FirstName, welcome back. Your current balance is $Balance. + <% end_with %> + + +Outside the `<% with %>.`, we are in the page scope. Inside it, we are in the scope of `$CurrentMember` object. We can +refer directly to properties and methods of the [api:Member] object. `$FirstName` inside the scope is equivalent to +`$CurrentMember.FirstName`. + +
+Why would you use `with`? This keeps the markup clean, and if the scope is a complicated expression we don't +have to repeat it on each reference of a property. +
+ + +## Comments + +Using standard HTML comments is supported. These comments will be included in the published site. + + :::ss + $EditForm + + +However you can also use special SilverStripe comments which will be stripped out of the published site. This is useful +for adding notes for other developers but for things you don't want published in the public html. + + :::ss + $EditForm <%-- Some hidden comment about the form --%> + +## Related + +[CHILDREN] + +## How to's + +[CHILDREN How_Tos] + +## API Documentation + +* [api:SSViewer] +* [api:SS_TemplateManifest] \ No newline at end of file diff --git a/docs/en/02_Developer_Guides/01_Templates/01_Templates.md b/docs/en/02_Developer_Guides/01_Templates/01_Templates.md deleted file mode 100644 index 2a7a58cfd..000000000 --- a/docs/en/02_Developer_Guides/01_Templates/01_Templates.md +++ /dev/null @@ -1,719 +0,0 @@ -# Templates - -## Introduction - -SilverStripe templates consist of HTML code augmented with special control codes, described below. Because of this, you -can have as much control of your site's HTML code as you like. - -Because the SilverStripe templating language is a string processing language it can therefore be used to make other -text-based data formats, such as XML or RTF. - -Here is a very simple template: - - :::ss - - - <% base_tag %> - $Title - <% require themedCSS("screen") %> - - -
-

Bob's Chicken Shack

-
- - <% with $CurrentMember %> -

Welcome $FirstName $Surname.

- <% end_with %> - - <% if $Dishes %> -
    - <% loop $Dishes %> -
  • $Title ($Price.Nice)
  • - <% end_loop %> -
- <% end_if %> - - <% include Footer %> - - - -More sophisticated use of templates for pages managed in the CMS, -including template inheritance and navigation loops -is documented in the [page types](/topics/page-types) topic. - -# Template elements - -## Variables - -Variables are things you can use in a template that grab data from the page and put in the HTML document. For example: - - :::ss - $Title - -This inserts the value of the Title field of the page being displayed in place of `$Title`. This type of variable is called a **property**. It is often something that can be edited in the CMS. Variables can be chained together, and include arguments. - - :::ss - $Property - $Property(param) - $Property.SubProperty - -These **variables** will call a method/field on the object and insert the returned value as a string into the template. - -* `$Property` will call `$obj->Property()` (or the field `$obj->Property`) -* `$Property(param)` will call `$obj->Property("param")` -* `$Property.SubProperty` will call `$obj->Property()->SubProperty()` (or field equivalents) - -If a variable returns a string, that string will be inserted into the template. If the variable returns an object, then -the system will attempt to render the object through its forTemplate() method. If the `forTemplate()` method has not been -defined, the system will return an error. - -SilverStripe provides many additional properties on the `SiteTree` class, -see [Page Type Templates](/topics/page-type-templates) for details. - -### Escaping - -Sometimes you will have template tags which need to roll into one another. This can often result in SilverStripe looking -for a "FooBar" value rather than a "Foo" and then "Bar" value or when you have a string directly before or after the -variable you will need to escape the specific variable. In the following example `$Foo` is `3`. - - :::ss - $Foopx // returns "" (as it looks for a Foopx value) - {$Foo}px // returns "3px" (CORRECT) - - -Or when having a `$` sign in front of the variable - - :::ss - $$Foo // returns "" - ${$Foo} // returns "$3" - -You can also use a backslash to escape the name of the variable, such as: - - :::ss - $Foo // returns "3" - \$Foo // returns "$Foo" - -## Includes - -Within SilverStripe templates we have the ability to include other templates from the Includes directory using the SS -'include' tag. For example, the following code would include the `Includes/SideBar.ss` code: - - :::ss - <% include SideBar %> - -The "include" tag can be particularly helpful for nested functionality. In this example, the include only happens if -a variable is true - - :::ss - <% if $CurrentMember %> - <% include MembersOnlyInclude %> - <% end_if %> - -Includes can't directly access the parent scope of the scope active when the include is included. However you can -pass arguments to the include, which are available on the scope top within the include - - :::ss - <% with $CurrentMember %> - <% include MemberDetails PageTitle=$Top.Title, PageID=$Top.ID %> - <% end_with %> - -You can also perform includes using the Requirements Class via the template controls. See the section on -[Includes in Templates](requirements#including_inside_template_files) for more details and examples. - - :::ss - <% require themedCSS("LeftNavMenu") %> - -### Including CSS and JavaScript files (a.k.a "Requirements") - -See [CSS](/topics/css) and [Javascript](/topics/javascript) topics for individual including of files and -[requirements](reference/requirements) for good examples of including both Javascript and CSS files. - -## Conditional Logic - -You can conditionally include markup in the output. That is, test for something -that is true or false, and based on that test, control what gets output. - -The simplest if block is to check for the presence of a value. - - :::ss - <% if $CurrentMember %> -

You are logged in as $CurrentMember.FirstName $CurrentMember.Surname.

- <% end_if %> - -The following compares a page property called `MyDinner` with the value in -quotes, `kipper`, which is a **literal**. If true, the text inside the if-block -is output. - - :::ss - <% if $MyDinner=="kipper" %> - Yummy, kipper for tea. - <% end_if %> - -Note that inside a tag like this, variables should have a '$' prefix, and -literals should have quotes. SilverStripe 2.4 didn't include the quotes or $ -prefix, and while this still works, we recommend the new syntax as it is less -ambiguous. - -This example shows the use of the `else` option. The markup after `else` is -output if the tested condition is *not* true. - - :::ss - <% if $MyDinner=="kipper" %> - Yummy, kipper for tea - <% else %> - I wish I could have kipper :-( - <% end_if %> - -This example shows the user of `else_if`. There can be any number of `else_if` -clauses. The conditions are tested from first to last, until one of them is true, -and the markup for that condition is used. If none of the conditions are true, -the markup in the `else` clause is used, if that clause is present. - - :::ss - <% if $MyDinner=="quiche" %> - Real men don't eat quiche - <% else_if $MyDinner==$YourDinner %> - We both have good taste - <% else %> - Can I have some of your chips? - <% end_if %> - -This example shows the use of `not` to negate the test. - - :::ss - <% if not $DinnerInOven %> - I'm going out for dinner tonight. - <% end_if %> - -You can combine two or more conditions with `||` ("or"). The markup is used if -*either* of the conditions is true. - - :::ss - <% if $MyDinner=="kipper" || $MyDinner=="salmon" %> - yummy, fish for tea - <% end_if %> - -You can combine two or more conditions with `&&` ("and"). The markup is used if -*both* of the conditions are true. - - :::ss - <% if $MyDinner=="quiche" && $YourDinner=="kipper" %> - Lets swap dinners - <% end_if %> - -You can use inequalities like `<`, `<=`, `>`, `>=` to compare numbers. - - :::ss - <% if $Number>="5" && $Number<="10" %> - Number between 5 and 10 - <% end_if %> - -## Looping Over Lists - -The `<% loop %>...<% end_loop %>` tag is used to **iterate** or loop over a -collection of items. For example: - - :::ss -
    - <% loop $Children %> -
  • $Title
  • - <% end_loop %> -
- -This loops over the children of a page, and generates an unordered list showing -the `Title` property from each one. Note that `$Title` *inside* the loop refers -to the `Title` property on each object that is looped over, not the current page. -This is know as the `Scope` of the template. For more information about `Scope` -see the section below. - -To refer to the current page's `Title` property inside the loop, you can do -`$Up.Title`. More about `Up` later. - -`$Me` can be used to refer to the current object context the template is rendered -with. - -### Position Indicators - -Inside the loop scope, there are many variables at your disposal to determine the -current position in the list and iteration: - - * `$Even`, `$Odd`: Returns boolean, handy for zebra striping - * `$EvenOdd`: Returns a string, either 'even' or 'odd'. Useful for CSS classes. - * `$First`, `$Last`, `$Middle`: Booleans about the position in the list - * `$FirstLast`: Returns a string, "first", "last", or "". Useful for CSS classes. - * `$Pos`: The current position in the list (integer). Will start at 1. - * `$TotalItems`: Number of items in the list (integer) - -### Altering the list - -`<% loop %>` statements iterate over a `[api:DataList]` instance. As the -template has access to the list object, templates can call `[api:DataList]` -functions. For instance, see the following examples: - -Providing a custom sort. - - :::ss -
    - <% loop $Children.Sort(Title) %> -
  • $Title
  • - <% end_loop %> -
- -Limiting the number of items displayed. - - :::ss -
    - <% loop $Children.Limit(10) %> -
  • $Title
  • - <% end_loop %> -
- -Reversing the loop. - - :::ss -
    - <% loop $Children.Reverse %> -
  • $Title
  • - <% end_loop %> -
- - -The `DataList` class also supports chaining methods. For example, to reverse -the list and output the last 3 items we would write: - - :::ss -
    - <% loop $Children.Reverse.Limit(3) %> -
  • $Title
  • - <% end_loop %> -
- -### Modulus and MultipleOf - -$Modulus and $MultipleOf can help to build column layouts. - - :::ss - $Modulus(value, offset) // returns an int - $MultipleOf(factor, offset) // returns a boolean. - -The following example demonstrates how you can use $Modulus(4) to generate -custom column names based on your loop statement. Note that this works for any -control statement (not just children). - - :::ss - <% loop $Children %> -
- ... -
- <% end_loop %> - -Will return you column-3, column-2, column-1, column-0, column-3 etc. You can -use these as styling hooks to float, position as you need. - -You can also use $MultipleOf(value, offset) to help build columned layouts. In -this case we want to add a
after every 3th item. - - :::ss - <% loop $Children %> - <% if $MultipleOf(3) %> -
- <% end_if %> - <% end_loop %> - -## Scope - -In the `<% loop %>` section, we saw an example of two **scopes**. Outside the -`<% loop %>...<% end_loop %>`, we were in the scope of the page. But inside the -loop, we were in the scope of an item in the list. The scope determines where -the value comes from when you refer to a variable. Typically the outer scope of -a page type's layout template is the page that is currently being rendered. -The outer scope of an included template is the scope that it was included into. - -### Up - -When we are in a scope, we sometimes want to refer to the scope outside the -<% loop %> or <% with %>. We can do that easily by using `$Up`. `$Up` takes -the scope back to the previous level. Take the following example: - - :::ss - $Title - -- - <% loop $Children %> - $Title - $Up.Title - -- - <% loop $Children %> - $Title - $Up.Title - <% end_loop %> - <% end_loop %> - -With a page structure (Blog -> Blog entry -> Child blog entry) the -above will produce: - - :::ss - Blog - -- - Blog entry - Blog - -- - Child blog entry - Blog entry - - -### Top - -While `$Up` provides us a way to go up 1 scope, `$Top` is a shortcut to jump to -the top most scope of the page. Using the previous example but expanded to -include `$Top`: - - :::ss - $Title - -- - <% loop $Children %> - $Title - $Up.Title - $Top.Title - -- - <% loop $Children %> - $Title - $Up.Title - $Top.Title - <% end_loop %> - <% end_loop %> - -Will produce - - :::ss - Blog - -- - Blog entry - Blog - Blog - -- - Child blog entry - Blog entry - Blog - -### With - -The `<% with %>...<% end_with %>` tag lets you introduce a new scope. Consider -the following example: - - :::ss - <% with $CurrentMember %> - Hello $FirstName, welcome back. Your current balance is $Balance. - <% end_with %> - - -Outside the `<% with %>...<% end_with %>`, we are in the page scope. Inside it, -we are in the scope of `$CurrentMember`. We can refer directly to properties and -methods of that member. So $FirstName is equivalent to $CurrentMember.FirstName. -This keeps the markup clean, and if the scope is a complicated expression we don't -have to repeat it on each reference of a property. - -`<% with %>` also lets us use a collection as a scope, so we can access -properties of the collection itself, instead of iterating over it. For example: - - :::ss - $Children.Count - -returns the number of items in the $Children collection. - -## Pagination - -Lists can be paginated, and looped over to generate pagination. For this to -work, the list needs to be wrapped in a `[api:PaginatedList]`. The process is -explained in detail on the ["pagination" howto](/howto/pagination). - -The list is split up in multiple "pages", each . Note that "page" is this context -does not necessarily refer to a `Page` class (although it often happens to be one). - - * `$MoreThanOnePage`: Returns true when we have a multi-page list, restricted with a limit. - * `$NextLink`, `$PrevLink`: This returns links to the next and previous page in a multi-page datafeed. They will return blank if there's no appropriate page to go to, so `$PrevLink` will return blank when you're on the first page. - * `$CurrentPage`: Current page iterated on - * `$TotalPages`: Total number of pages - * `$TotalItems`: This returns the total number of items across all pages. - * `$Pages`: The actual (limited) list of records, use in an inner loop - * `$PageNum`: Page number, starting at 1 (within `$Pages`) - * `$Link`: Links to the current controller URL, setting this page as current via a GET parameter (within `$Pages`) -* `$CurrentBool`: Returns true if you're currently on that page (within `$Pages`) - -## Formatting and Casting - -Properties are usually auto-escaped in templates to ensure consistent representation, -and avoid format clashes like displaying unescaped ampersands in HTML. -By default, values are escaped as `XML`, which is equivalent to `HTML` for this purpose. -There's some exceptions to this rule, see the ["security" topic](/topics/security). - -In case you want to explicitly allow unescaped HTML input, -the property can be cast as `[api:HTMLText]`. -The following example takes the `Content` field in a `SiteTree` class, -which is of this type. It forces the content into an explicitly escaped format. - - :::ss - $Content.XML // transforms e.g. "alert" to "<em>alert</em>" - -Apart from value formatting, there's many methods to transform them as well, -For example, the built in `$Now` placeholder is an instance of `[api:Date]`, -and returns the current date in a standard system format. -Since its an object, you can use the helper methods to return other formats: - - :::ss - $Now.Year // Current year - $Now.Nice // Localized date, based on i18n::get_locale() - -See [data-types](/topics/data-types) for more information. - -## Translations - -Translations are easy to use with a template, and give access to SilverStripe's translation facilities. Here is an example: - - <%t Member.WELCOME 'Welcome {name} to {site}' name=$Member.Name site="Foobar.com" %> - -Pulling apart this example we see: - - * `Member.WELCOME` is an identifier in the translation system, for which different translations may be available. This string may include named placeholders, in braces. - * `'Welcome {name} to {site}'` is the default string used, if there is no translation for Member.WELCOME in the current locale. This contains named placeholders. - * `name=$Member.Name` assigns a value to the named placeholder `name`. This value is substituted into the translation string wherever `{name}` appears in that string. In this case, it is assigning a value from a property `Member.Name` - * `site="Foobar.com"` assigns a literal value to another named placeholder, `site`. - -## Comments - -Using standard HTML comments is supported. These comments will be included in the published site. - - :::ss - $EditForm - - -However you can also use special SilverStripe comments which will be stripped out of the published site. This is useful -for adding notes for other developers but for things you don't want published in the public html. - - :::ss - $EditForm <%-- Some hidden comment about the form --%> - -## Partial Caching - -Partial caching lets you define blocks of your template that are cached for better performance. See [Partial Caching](/reference/partial-caching) for more information. - -### Base Tag - -The `<% base_tag %>` placeholder is replaced with the HTML base element. Relative links within a document (such as ``) will become relative to the URI specified in the base tag. This ensures the browser knows where -to locate your site’s images and css files. So it is a must for templates! - -It renders in the template as `` - -## CurrentMember - -Returns the currently logged in member, if there is one. -All of their details or any special Member page controls can be called on this. -Alternately, you can use `<% if $CurrentMember %>` to detect whether someone has logged -in. - - :::ss - <% if $CurrentMember %> - Welcome Back, $CurrentMember.FirstName - <% end_if %> - -## Custom Template Variables and Controls - -There are two ways you can extend the template variables you have available. You can create a new database field in your -`$db` or if you do not need the variable to be editable in the cms you can create a function which returns a value in your -`Page.php` class. - - :::php - // mysite/code/Page.php - public function MyCustomValue() { - return "Hi, this is my site"; - } - -Will give you the ability to call `$MyCustomValue` from anywhere in your template. - - :::ss - I've got one thing to say to you: $MyCustomValue - // output "I've got one thing to say to you: Hi, this is my site" - -Your function could return a single value as above or it could be a subclass of `[api:ArrayData]` for example a -`[api:DataObject]` with many values then each of these could be accessible via a control loop - - :::php - // ... - public function MyCustomValues() { - return new ArrayData(array("Hi" => "Kia Ora", "Name" => "John Smith")); - } - - -And now you could call these values by using - - :::ss - <% with $MyCustomValues %> - $Hi , $Name - <% end_with %> - // output "Kia Ora , John Smith" - -Or by using the dot notation you would have - - :::ss - $MyCustomValues.Hi , $MyCustomValues.Name - // output "Kia Ora , John Smith" - -### Side effects - -All functions that provide data to templates must have no side effects, as the value is cached after first access. For example, this controller method - - :::php - private $counter = 0; - - public function Counter() { - $this->counter += 1; - return $this->counter; - } - - -and this template - - :::ss - $Counter, $Counter, $Counter - - -will render as "1, 1, 1", not "1, 2, 3" - -## .typography style - -By default, SilverStripe includes the `theme/css/typography.css` file into the Content area. So you should always include the -typography style around the main body of the site so both styles appear in the CMS and on the template. Where the main body of -the site is can vary, but usually it is included in the /Layout files. These files are included into the main Page.ss template -by using the `$Layout` variable so it makes sense to add the .typography style around $Layout. - - :::ss -
- $Layout -
- -## Calling templates from PHP code - -This is all very well and good, but how do the templates actually get called? - -Templates do nothing on their own. Rather, they are used to render *a particular object*. All of the `<% if %>`, `<%control %>`, -and variable codes are methods or parameters that are called *on that object*. All that is necessary is -that the object is an instance of `[api:ViewableData]` (or one of its subclasses). - -The key is `[api:ViewableData::renderWith()]`. This method is passed a For example, within the controller's default action, -there is an instruction of the following sort: - - :::php - $controller->renderWith("TemplateName"); - - -Here's what this line does: - -* First `renderWith()` constructs a new object: `$template = new SSViewer("TemplateName");` -* `[api:SSViewer]` will take the content of `TemplateName.ss`, and turn it into PHP code. -* Then `renderWith()` passes the controller to `$template->process($controller);` -* `SSViewer::process()` will execute the PHP code generated from `TemplateName.ss` and return the results. - -`renderWith()` returns a string - the populated template. In essence, it uses a template to cast an object to a string. - -`renderWith()` can also be passed an array of template names. If this is done, then `renderWith()` will use the first -available template name. - -Below is an example of how to implement renderWith. In the example below the page is rendered using the myAjaxTemplate -if the page is called by an ajax function (using `[api:Director::is_ajax()]`). Note that the index function is called by -default if it exists and there is no action in the url parameters. - - :::php - class MyPage_Controller extends Page_Controller { - - private static $allowed_actions = array('index'); - - public function init(){ - parent::init(); - } - - public function index() { - if(Director::is_ajax()) { - return $this->renderWith("myAjaxTemplate"); - } else { - return Array();// execution as usual in this case... - } - } - } - -## Anchor Link rewriting - -Anchor links are links with a "#" in them. A frequent use-case is to use anchor links to point to different -sections of the current page. For example, we might have this in our template. - -For, example, we might have this on http://www.example.com/my-long-page/ - - :::ss - - - -So far, so obvious. However, things get tricky because of we have set our `` tag to point to the root of your -site. So, when you click the first link you will be sent to http://www.example.com/#section1 instead of -http://www.example.com/my-long-page/#section1 - -In order to prevent this situation, the SSViewer template renderer will automatically rewrite any anchor link that -doesn't specify a URL before the anchor, prefixing the URL of the current page. For our example above, the following -would be created: - - :::ss - - - -There are cases where this can be unhelpful. HTML anchors created from Ajax responses are the most common. In these -situations, you can disable anchor link rewriting by setting the -`SSViewer.rewrite_hash_links` configuration value to `false`. - -### More Advanced Controls - -Template variables and controls are just PHP properties and methods -on the underlying controllers and model classes. -We've just shown you the most common once, in practice -you can use any public API on those classes, and [extend](/reference/dataextension) them -with your own. To get an overview on what's available to you, -we recommend that you dive into the API docs for the following classes: - - * `[api:Controller]`: Generic controller class - * `[api:DataObject]`: Generic model class - * `[api:ViewableData]`: Underlying object class for pretty much anything displayable - -## Designing reusable templates - -Although SilverStripe is ultimately flexible in how you create your templates, there's a couple of best practices. These -will help you to design templates for modules, and make it easier for other site developers to integrate them into their -own base templates. - -* Most of your templates should be `Layout` templates -* Build your templates as a [Theme](/topics/themes) so you can easily re-use and exchange them -* Your layout template should include a standard markup structure (`
$Layout
`) -* Layout templates only include content that could be completely replaced by another module (e.g. a forum thread). It -might be infeasible to do this 100%, but remember that every piece of navigation that needs to appear inside `$Layout` -will mean that you have to customise templates when integrating the module. -* Any CSS applied to layout templates should be flexible width. This means the surrounding root template can set its -width independently. -* Don't include any navigation elements in your `Layout` templates, they should be contained in the root template. -* Break down your templates into groups of includes. Site integrators would then have the power to override individual -includes, rather than entire templates. - -## Related - - * [Built in page controls](/reference/built-in-page-controls) - * [Page Type Templates](/topics/page-type-templates) - * [Typography](/reference/typography) - * [Themes](/topics/themes) - * [Widgets](/topics/widgets) - * [Images](/reference/image) - * [Tutorial 1: Building a basic site](/tutorials/1-building-a-basic-site) - * [Tutorial 2: Extending a basic site](/tutorials/2-extending-a-basic-site) - * [Developing Themes](/topics/theme-development) - * [Templates: formal syntax description](/reference/templates-formal-syntax) diff --git a/docs/en/02_Developer_Guides/01_Templates/02_CSS.md b/docs/en/02_Developer_Guides/01_Templates/02_CSS.md deleted file mode 100644 index e087014c0..000000000 --- a/docs/en/02_Developer_Guides/01_Templates/02_CSS.md +++ /dev/null @@ -1,94 +0,0 @@ -# CSS # - -## Introduction ## - -SilverStripe strives to keep out of a template designer's way as much as possible - -this also extends to how you want to write your CSS. - -## Adding CSS to your template ## - -You are free to add `