Switcher Card
A switcher card holds several views of the same data behind one strip of tabs, for example a chart and a table. Only
the selected view is shown. A view is built the first time it is selected and stays alive when hidden, so switching
back is instant and a chart keeps its state. The script is juneau-switcher.js, and <@page> loads it for you when a
page has a switcher card.
A chart and a table
<@card type="switcher" id="revenue-sw" title="Revenue, last 30 days">
{ initialView: 'chart',
views: [
{ id: 'chart', label: 'Chart', card: { type: 'chart', id: 'revenue-chart', src: '/console/store/stats/revenue',
kind: 'line', x: { field: 'day', label: 'Day' }, series: [ { field: 'revenue', label: 'Revenue' } ] } },
{ id: 'data', label: 'Data', card: { type: 'datatables', id: 'revenue-data', dataMode: 'client', dataUrl: '/console/store/stats/revenue',
columns: [ { key: 'day', label: 'Day' }, { key: 'revenue', label: 'Revenue' } ] } }
] }
</@card>
From Java, build the same card with SwitcherDef:
page.card(SwitcherDef.create("revenue-sw").title("Revenue, last 30 days")
.view("chart", "Chart", v -> v.section(ChartDef.line("revenue-chart").src("/console/store/stats/revenue")
.x("day", null, "Day").series("revenue", "Revenue").toCardSpec()))
.view("data", "Data", v -> v.section(tableCard))
.initialView("chart")
.toCardSpec());
A view holds one card, or a list of sections that each hold a card. A view with several sections shows a second
strip of tabs under the view tabs, and initialSection picks the section shown first. The first view is shown when
initialView is not set.
Which view is shown
The page chooses the view in this order:
- The page address, when it names this switcher.
- The choice saved in the browser for this card.
- The card's
initialView(andinitialSection). - The first view.
Selecting a tab writes sw(<id>:<view>), or sw(<id>:<view>.<section>) for a section, to the page address. Several
switchers on one page join with ~. Selecting a switcher's default view (and its default section, when it has several) removes its entry, so an unchanged page keeps
a clean address. A link that carries the entry opens the same view for whoever follows it, whatever they saved.
The browser keeps the choice per card, under juneau-card:<card id>:switcher:view and
juneau-card:<card id>:switcher:section.<view id>, so a reload returns to the view you left.
Nested cards
A nested card is a full card of any type except switcher. Its id must be unique on the page. A nested card publishes
its card:<id> topic only once its view has been built, so a subscriber to that topic sees nothing until the view is
first selected. A nested card needs no contractVersion of its own; the switcher supplies it, and an explicit
version other than "1" is still rejected. A nested card that publishes its own topics lists them under publishes
as usual, either as objects (each entry needs both topic and retain) or in the string shorthand that top-level
cards accept, such as 'topic' or 'a, b!retain'.
Selecting from script
select(target) on a switcher handle selects a view by id. select('view/section') selects the view and then a
section within it. It returns true on success and false for an unknown view or section, in which case nothing
changes.
The folder-tab look
Tab strips in the console use a folder-tab look. The selected tab is washed with the accent color and has an accent top border, and the panes under the strip share the accent border. Keyboard use follows the usual tab pattern: the arrow keys move between tabs, and Tab moves into the displayed view, which is labelled by the selected tab.
Errors
| Code | When |
|---|---|
| E-JS-126 | card '<id>': switchers cannot be nested. A nested card was itself a switcher. |
| E-JS-127 | nested card id '<id>' is already in use. A nested card reused the id of a card that is still alive. |
Java checks the body when the page renders: at least one view, view and section ids that match the id pattern, a card
in each view or section, and no switcher among the nested cards. SwitcherDef reports the same messages.