This recipe shows how to make a history-based tabs widget and have routes
configured independently by can.route.
How it works
The HTML is structured such that each tab button has an <a> element with an
href property that matches the id attribute of the tab content
panel it should show. This means that even if JavaScript was disabled,
clicking a button would send the user to the tab panel (even though
HistoryTabs overwrites this behavior).
For example:
<li><a href="#model">can.Model</a></li>
references:
<div id="model" class="tab">
The JavaScript code begins by creating a HistoryTabs
control. When a new HistoryTabs instance is created, it gets
an attr option like:
new HistoryTabs( '#components',{attr: 'component'});
The attr method is used to configure which part of can.route's data the
history tab will be listening to.
When init is called, it hides each tab button's content div, looking up
the content div with the tab helper method. It then reads the current
active tab with:
var active = can.route.attr(this.options.attr);
It passes that value to the active helper which will hide the old active
content (if oldActive is passed) and activate the new active button and
show it's content.
HistoryTab updates the active tab by listening when a tab button is clicked with
"li click". It prevents the default behavior (which is changing the hash) and
updates it's route data attribute with the select tab's id:
This matches the empty routes ("","#","#!"), and a single "word" route. If the route
is one of the empty routes, the route data will look
like: {component: "modal", person: "mihael"}. If it is a single "word" route like
"#!view", the data will look like: {component: "view", person: "mihael"}.
This matches two-word routes seperated by a slash ("/"). Each word can be empty. If both
words are empty "#!/", the data will look
like: {component: "model", person: "mihael"}. If the words are non-empty, that word
will replace the default value.
Observe Backed Routes
This recipe shows how to have multiple widgets listening on
overlapping parts of the route. The app lets the user select a type of issue, show issues for that type,
and select a issue and see details about that issue.
How it works
This functionality is broken down
into Nav, Issues, and Details can.controls. Here's how
each part works:
Nav creates links using can.route.link that update the hash like:
The following recipes explore using
can.route
.History Tabs
This recipe shows how to make a history-based tabs widget and have routes configured independently by can.route.
How it works
The HTML is structured such that each tab button has an
<a>
element with an href property that matches theid
attribute of the tab content panel it should show. This means that even if JavaScript was disabled, clicking a button would send the user to the tab panel (even though HistoryTabs overwrites this behavior).For example:
references:
The JavaScript code begins by creating a
HistoryTabs
control. When a newHistoryTabs
instance is created, it gets an attr option like:The attr method is used to configure which part of
can.route
's data the history tab will be listening to.When
init
is called, it hides each tab button's content div, looking up the content div with thetab
helper method. It then reads the current active tab with:It passes that value to the
active
helper which will hide the old active content (ifoldActive
is passed) and activate the new active button and show it's content.HistoryTab
updates the active tab by listening when a tab button is clicked with"li click"
. It prevents the default behavior (which is changing the hash) and updates it's route data attribute with the select tab's id:HistoryTabs
listens to these route changes with"{can.route} {attr}"
and activates the new tab.Configuring Routes
The code ends by configuring the routes and creating the
HistoryTabs
. Here's what each route rule means:This matches the empty routes
("","#","#!")
, and a single "word" route. If the route is one of the empty routes, the route data will look like:{component: "modal", person: "mihael"}
. If it is a single "word" route like"#!view"
, the data will look like:{component: "view", person: "mihael"}
.This matches two-word routes seperated by a slash ("/"). Each word can be empty. If both words are empty "#!/", the data will look like:
{component: "model", person: "mihael"}
. If the words are non-empty, that word will replace the default value.Observe Backed Routes
This recipe shows how to have multiple widgets listening on overlapping parts of the route. The app lets the user select a type of issue, show issues for that type, and select a issue and see details about that issue.
How it works
This functionality is broken down into Nav, Issues, and Details can.controls. Here's how each part works:
Nav
creates links usingcan.route.link
that update the hash like:When these are clicked on, they update the route's filter data.
Issues
listens to filter changes like:It then retrieve's issue with
Issue.findAll
and renders them into the#issues
element.When an issue is clicked,
Issues
updates the route's issue data like:It listens to changes in
issue
data and highlights the corresponding issue in the list like:Details
listens to issue chagnes like:And updates the details panel.