Card Asset Dependencies
A console card can need scripts and stylesheets beyond the views toolkit. A datatables card needs jQuery,
DataTables and Juneau's glue script. The card declares that need, and <@page> loads each asset once, in
dependency order, after the body has rendered.
Toolkit packs
A toolkit pack is a named list of CSS and JS assets. A pack can depend on other packs, and it has a kind:
- VENDOR packs are libraries and their glue. Their CSS comes before the page
css=, and their JS comes before every runtime script. - RUNTIME packs are Juneau UI runtimes. They keep the position the
viewspack always had.
| Pack | Kind | Loads | Depends on |
|---|---|---|---|
jquery | VENDOR | jquery.min.js (WebJar org.webjars:jquery) | |
datatables | VENDOR | dataTables.min.js, dataTables.dataTables.min.css (npm WebJars datatables.net, datatables.net-dt) | jquery |
datatables-glue | VENDOR | juneau-datatables.js (served by DataTablesMixin) | datatables |
datatables-buttons | VENDOR | dataTables.buttons.min.js, buttons.html5.min.js, buttons.dataTables.min.css | datatables |
views | RUNTIME | the views runtime | |
calendar | RUNTIME | juneau-calendar.js, juneau-calendar.css | |
xterm | VENDOR | xterm.js, xterm.css (npm WebJar @xterm/xterm) | |
terminal | RUNTIME | juneau-terminal.js, juneau-terminal.css (served by TerminalMixin) | views, xterm |
charts | RUNTIME | juneau-charts.js (served by ConsoleChromeMixin) | |
joblog | RUNTIME | juneau-joblog.js (served by ConsoleChromeMixin) |
datatables-buttons gives copy and CSV export. Excel and PDF export need JSZip and pdfmake, which aren't
included; register your own pack for them (below).
What a page loads
<@page> loads the packs in toolkit=, plus the packs its cards require:
| Card | Requires |
|---|---|
type="datatables" | datatables-glue, plus joblog when its detail.region is a job-log region |
type="html" | nothing |
type="terminal-view" | nothing extra (its runtime ships in the views pack) |
type="terminal" | terminal (which pulls in views and xterm) |
type="chart" | charts |
type="job-log" | joblog |
A card adds more with requires=:
<@card type="datatables" id="rel" requires="datatables-buttons">{ ... }</@card>
A card type can also require packs from the card's body: a CardTypeHandler overrides requiredPacks(JsonMap body)
(empty by default), and the page unions what it returns with the type's packs and requires=. That is how a
datatables card with a job-log detail region gets joblog without a requires=.
requires= takes a comma-separated string or a sequence. An unknown pack name fails the render with a 500 that
names the card.
Each pack loads after the packs it depends on, and each asset loads once, however many cards need it. Markup
outside a card records nothing. jcHasToolkit
reports only toolkit=.
Serving the WebJars
Compose WebJarsMixin (from juneau-rest-server) into the resource that serves the page. It serves
/webjars/* from the classpath with a one-year immutable Cache-Control, and the URLs carry the WebJar version.
juneau-console-datatables brings the WebJars in as dependencies.
@Rest(mixins={FreemarkerMixin.class, ViewsMixin.class, DataTablesMixin.class, WebJarsMixin.class})
public class PetConsole extends BasicRestServlet { ... }
If the host doesn't compose WebJarsMixin, the library URLs 404 and the table doesn't start.
Customizing
All of this is on ConsoleFreemarkerMixin.Builder, and build() checks it: an unknown pack name, a cycle, or a
VENDOR pack that depends on a RUNTIME pack fails the build.
ConsoleFreemarkerMixin.create()
.registerToolkitPack(ToolkitPack.create("datatables-export")
.js("/app/jszip.min.js", "/app/pdfmake.min.js", "/app/vfs_fonts.js")
.dependsOn("datatables-buttons")
.kind(ToolkitPack.Kind.VENDOR)
.resolver((req, path) -> req.getUriResolver().resolve("servlet:" + path))
.build())
.cardRequires("datatables", "datatables-export") // every datatables card
.providedPacks("jquery") // the chrome already loads jQuery
.build();
registerToolkitPack(ToolkitPack)adds a pack. A pack with a built-in name replaces it, including its dependencies, soregisterToolkitPack(ToolkitPack.create("datatables")...)swaps in your own DataTables build. The(name, css, js)form registers a RUNTIME pack with no dependencies.cardRequires(type, packs...)adds packs to every card of a type.providedPacks(names...)names packs your chrome already loads. A provided pack loads nothing; its dependencies still load unless they're provided too.
If a page already loads a file through init= or css=, a pack asset with the same file name is skipped, and
the log gets a WARN naming the template. A copy loaded through init= is not a bridge: it is skipped only when
the file name matches, and the pack's other assets still load. An app that has its own copies of the libraries
names the packs in providedPacks(...), or mounts WebJarsMixin and lets the packs load them.
Load order
<@head phase="before-page-css">, then VENDOR CSS, then the pagecss=, then RUNTIME CSS.juneau-console.js, then VENDOR JS (for a datatables card: jQuery, DataTables,juneau-datatables.js), then RUNTIME JS, then<@scripts phase="after-toolkit">, theninit=.