This section explains what navigation is and how it works, and gives an overview of the components within the Navigation Library (library.navigation) that support navigation.
Overview of navigation
Navigation presents the user with additional content to allow them to navigate around a solution.
At its simplest, navigation is just a list of links.
The list is know as the navigation, and the items in the list are known as the navigation items.
Navigation items are flexible.
- They usually have a name, but do not have to have one.
- They usually have a link, but do not have to have one.
- They may have a summary (which can be any content).
- They may have their own navigation list.
Here is an example of more complicated navigation.
- Node Two With No Link
Node three has other content associated with it.
- This is a summary that does not have a name.
How navigation is used
Navigation is used to build two different types of structures.
It is used to build components that appear on every page, such as menus and sidebars.
On some pages, it is used to build the page content itself. For example, it can be used to build a dashboard-like page, with panels containing high-level reports.
Each navigation item has properties for:
- A name.
- A link.
- A summary.
- A list of items, i.e. another level of navigation list.
It has properties to aid rendering:
- An order to apply to the item relative to its peers. This defaults to 0. Low items come first.
- A CSS class to be applied to the item.
It has properties to aid navigation list processing:
- An identifier, called a navid, which is used to uniquely identify a navigation item in the navigation list.
- An action. The action is a declarative method for tailoring navigation, for example to embellish a menu with page-specific options. Specifically, the action determines what should be done if an item with the same navid is already in the navigation structure.
Action can have one of four values:
- insert – Add this item as a child of the specified item, creating the specified item if necessary. This is the default action.
- merge – keep the first item in place, but add child items from this item to the first item.
- replace – replace the first item with this one.
- delete – delete the first item and do not add this one.
One way of thinking of the actions is that the default is to add the item to the named list (insert), or add child items from this item to the list (merge), or replace the entire item and list (replace), or delete the item (delete).
- An inherit flag. This is used when merging navigation structures to prevent some items from being merged. For example, if you have a summary package which has dashboard-like content, the inherit flag can be used to specify that the nodes in the package inherit the menu from the package, but not the dashboard content. The flag is true or false, the default is true.
All properties are optional.
The internal navigation script structure can easily be transformed into an HTML structure.
The Navigation Script provides a standard rendering method that transforms the navigation list into a nested set of unordered lists (<ul> and <li> elements). You can use classes on this list to style the output as you like. The navids are used as identifiers of the elements in the generated HTML, and can be used for specific styling and actions.
Alternatively, you can write your own rendering methods that use the navigation list structure.
Node navigation and effective navigation
Navigation is associated with nodes.
Each node has two different navigation lists.
The node navigation is specific to the node, and does not depend on where the node is in the package hierarchy and how the user has accessed it.
The effective navigation depends on where the node is in the node hierarchy and how the user has accessed it, and is created by merging a parent navigation with the node navigation. The effective navigation is generally what is used as the basis for rendering the navigation.
The parent navigation typically defines common page components such as menus and sidebars, and the node navigation defines page-specific navigation such as extra menu options or page content.
Calculation of node navigation
Node navigation is calculated using the Navigation.getNodeNavigation() method on the Navigation Script.
This looks for the navigation in one of four places, in order of precedence:
- Read from the Node Navigation (library.navigation.NodeNavigation) member. This allows node navigation to be pre-calculated using derivation.
- If the node has the tag Navigation Script (library.tags.NavigationScriptTag) set, but running the Node Script (system.NODE_SCRIPT) member if the node.
- From executing the Get Node Navigation (library.navigation.GetNodeNavigationMethod) method on the node.
- From the members of the Navigation List (library.navigation.NavigationList) member, which provides a list of nodes to form the navigation items.
The Navigation.getNodeNavigation() method applies the navid and action properties as appropriate.
Where the navigation is read from the Navigation List, the navid and action are read from the list itself in a navid/action format. This makes it simple to apply navigation tailoring, for example using a "file/merge" to add items to the file menu, or "help/replace" to replace the help link.
By default, only one level of Navigation List is navigated. However, if the Follow Navigation (library.navigation.FollowNavigation) indicator is set to true on a target node, then its Navigation List will also be followed. This means that a high-level navigation can refer to a node without including that node's node-specific navigation.
When designing solutions, some care is required to balance the requirements for speed and flexibility. Using derived navigation from the Node Navigation member is faster than accessing lots of nodes, but does not allow tailoring per user. To allow tailoring, then some levels of the navigation must be sourced using the Get Node Navigation method or using the Navigation List. Be cautious that the Navigation Item (library.navigation.NavigationItemType) node type caches the navigation in Node Navigation by default. Also, if you are using caching, the Node Navigation will be built using the node owner's authority. If you are not using caching, then it will be built using the current user's authority, and can, for example, detect where a user is not authorised to read a particular node.
Calculation of effective navigation
Effective navigation is "all the navigation relevant to this node", whereas node navigation is "all the navigation specific to this node".
Effective navigation is calculated using the Navigation.getEffectiveNavigation() method on the Navigation Script.
The basic process is to calculate a parent navigation, and then to merge the node navigation into the parent navigation. The merge process applies navid/action rules to tailor the parent navigation. It also removes from the parent navigation any navigation items with the inherit property set to false.
The parent navigation is calculated in different ways according to whether the node is within one of the account pages listed on the the user's account.
If the node is within an account package, then the parent navigation is the effective navigation of the parent package. This, in turn, is based on the the package's package, up to the high level package.
If the node is not within an account package, then the parent navigation is the effective navigation of the user's home page (which is typically within an account package).
This means that whatever node the user is accessing, they get the right blend of account-specific navigation and node-specific navigation.
Effective navigation is not cached, and is calculated using the current user's authority. It can therefore run scripts to provide user-specific navigation (such as favourites), though care is required to ensure that these are not accidentally cached.
Get Node Navigation Method
A node can provide its navigation by executing the Get Node Navigation Method (library.navigation.GetNodeNavigationMethod) against the script. The script must be defined against the node type, and return the navigation structure in the items attribute.
The type Script Navigation Item (library.navigation.ScriptNavigationItemType) provides support for creating script-based navigation. In this case, the script is defined against the node instance.
Remember that if you are using the Get Node Navigation Method you must not cache the results if the results are different for each user. If you include a script-based item in a navigation item's navigation list, set the recalculation frequency to always recalculate.
Navigation components and API
Navigation Library (library.navigation) provides components for working with navigation structures.
It contains the following main node types:
- Navigation Item (library.navigation.NavigationItemType) is a flexible node type for creating navigation structures. It can act as a shortcut, for creating a navigation item that links to another node or any other URL. It can be used to build nested navigation lists. It supports all the Navigation Item properties.
- Navigation Page (library.navigation.NavigationPageType) is an example of a page type that displays a navigation list as content. It is of limited usefullness of itself, but provides a model for other more specialised node types. It can also be used to test navigation structures.
- JSON Navigation Item (library.navigation.JSONNavigationItemType) is similar to Navigation Item, except that its navigation list is defined using JSON rather than a Navigation List. This can be useful for testing, or for specialised applications (for example, for generating a navigation list).
- Script Navigation Item (library.navigation.ScriptNavigationItemType) is similar to Navigation Item, except that its navigation list is defined using a script.
If you are building new navigation components, use these and the member types they contain as the basis for your own node types.
The Navigation Library also contains the following API components: