3.2 SiteMap
Lift has an optional feature called SiteMap. You don’t have to use it. But if you do set a sitemap in boot, then Lift will use the sitemap as a white list of HTML pages for your site (note that REST URLs do not need to be listed in the sitemap). SiteMap defines navigation and access control, allows you to create hierarchical menus, grouped menu items, display the entire sitemap, a relative sitemap, as well breadcrumbs. This section will discuss some of SiteMap’s capabilities.
3.2.1 Defining the SiteMap
The SiteMap must be defined in boot and is only defined once. Typically, you will define a function that returns a SiteMap instance:
// Build SiteMap
def sitemap(): SiteMap = ...
And then define the SiteMap in LiftRules:
// set the sitemap. Note if you don’t want access control for
// each page, just comment this line out.
LiftRules.setSiteMapFunc(() => sitemap())
In development mode, the function will be called on each page load to rebuilt the SiteMap. In all other Lift run modes, the sitemap will be built once during boot.
A SiteMap is a collection of Menu instances. Each Menu has one Loc[_] and a set of Menu instances as submenus (zero or more). Each Menu instance has a unique name.
If an HTML page is not defined in the sitemap, Lift will not serve it. SiteMap is a white list of pages to serve. Further, the Loc[_] has parameters that can include multiple access control rules.
3.2.2 Simplest SiteMap
The simplest sitemap defines a single page:
def sitemap(): SiteMap = SiteMap(Menu.i("Home") / "index")
This is a SiteMap with a single menu item. The Menu has the name “Home” and will be displayed as the localized (see
8.1 on page 1↓) string “Home”. The Menu.i method generates a
Menu with a
Loc[Unit].
3.2.3 Menu and Loc[_]
You may be wondering why a Menu and a Loc[_] (short for location, pronouned “Loke”) are separate and why the Loc takes a type parameter.
A Menu contains a location and many submenus. The original thought was that you could have a single Loc[_] that might be placed in different places in the menu hierarchy. So, historically, they are separated, but there’s a one to one relation between them.
The Loc[_] takes a type parameter which defines a current value type for the Loc. For example, if the Loc refers to a page that will display a wiki page, then the type parameter of the Loc would be WikiPage: Loc[WikiPage].
Each Loc can have many parameters (know as LocParam, “loke param”) that define behavior for the Loc[_]. These parameters include access control testing, template definition, title, group, etc.
3.2.4 Access Control
You can control access to the URL/page represented by the Loc with the If() LocParam:
/**
* Calculate if the page should be displayed.
* In this case, it will be visible every other minute
*/
def displaySometimes_? : Boolean =
(millis / 1000L / 60L) % 2 == 0
Menu.i("Sometimes") / "sometimes" >> If(displaySometimes_? _,
S ? "Can’t view now")
We define a method that returns true if access is allowed. Adding the If() LocParam will restrict access to the page unless the function returns true. Menu items will not be visible for pages that do not pass the access control rules and even if the user types the URL into the browser, the page will not be displayed (by default, the user will be redirected by to the home page and an error will be displayed.)
3.2.5 Hidden and Group
Menu items can be hidden from the default menu hierarchy even if the page is accessible. The Hidden LocParam says “hide from default menu.”
Menu.i("About") / "about" >> Hidden >> LocGroup("bottom")
Menu items can also be grouped together in a named group and then displayed:
<span class="lift:Menu.group?group=bottom"></span>
Which results in:
<a href="/about">About</a> <a href="/feedback">Feedback</a> <a href="/sitemap">Sitemap</a>
You can nest menus:
// A menu with submenus
Menu.i("Info") / "info" submenus(
Menu.i("About") / "about" >> Hidden >> LocGroup("bottom"),
Menu.i("Contact") / "contact",
Menu.i("Feedback") / "feedback" >> LocGroup("bottom"))
The About, Contact and Feedback pages are nested under the Info page.
3.2.7 Parameters
You can parse the incoming URL and extract parameters from it into type-safe variables:
// capture the page parameter information
case class ParamInfo(theParam: String)
// Create a menu for /param/somedata
val menu = Menu.param[ParamInfo]("Param", "Param",
s => Full(ParamInfo(s)),
pi => pi.theParam) / "param"
The above code creates a menu called “Param”. The menu is for the url /param/xxx where xxx can match anything.
When the URL /param/dogfood or /param/fruitbat is presented, it matches the Loc and the function (s => Full(ParamInfo(s))) is invoked. If it returns a Full Box, the value is placed in the Loc’s currentValue.
It’s possible to hand-write Loc implementation that will match many URL parameters.
For information on accessing the captured parameters (in this case the
ParamInfo), see
3.4.5 on page 1↓.
You can create menus that match all the contents of a given path. In this case, all the html files in /static/ will be served. That includes /static/index, /static/fruitbat, and /static/moose/frog/wombat/meow.
// more complex because this menu allows anything in the
// /static path to be visible
Menu.i("Static") / "static" / **
Note that Lift will not serve any files or directories that start with . (period) or _ (underscore) or end with -hidden.
We’ve demonstrated how to create a SiteMap with many different kinds of menu items. Next, let’s look at the views.
(C) 2012 David Pollak