前回「Cozy Web/Bootstrap」ではBootstrapのテンプレートを使用するためにレイアウト機能を使用しました。
今回は、このCozy Webのレイアウト機能について少し詳しく説明します。
HelloLayout
まず、レイアウト機能を使ったHelloLayoutアプリケーションを作成します。
準備
cozyを起動するディレクトリのwebappsディレクトリに、アプリケーションのホームとなるディレクトリHelloLayoutを作成します。このディレクトリHelloLayoutをアプリケーションのホームディレクトリとなります。
共通テンプレート
Webページで共有されるテンプレートとして以下のものをWEB-INF/layouts/default.jadeに作成します。
-@val model: ViewModel
!!! 5
html(lang="ja")
head
=model.pageTitle
body
=model.header
=model.navigation
=model.sidebar
=model.content
=model.footer
headに以下の設定があります。
=model.pageTitle
ページのタイトルをhead要素の配下に追加する指定になります。
またbodyに以下の設定があります。
=model.header
=model.navigation
=model.sidebar
=model.content
=model.footer
それぞれ以下の部品をbody要素の配下に追加する指定です。
- model.header
- ページのヘッダー
- model.navigation
- ナビゲーション・バー
- model.sidebar
- サイド・バー
- model.content
- ページの本文
- model.footer
- ページのフッター
ヘッダー、フッター、ナビゲーション・バー、サイド・バーで構成される固定レイアウト内に本文を埋め込む構成になっています。
部品ページ
Webページの部品はWEB-INF/partialsに格納します。
partialsに格納する部品は、header.htmlやheader.jadeのようにファイル名本体を部品名とします。サフィックスは部品の記述を行う言語になります。
ヘッダー
ヘッダーとして以下のheader.jadeをWEB-INF/partialsに格納しました。
div Header
ナビゲーション・バー
ナビゲーション・バーとして以下のnavigation.jadeをWEB-INF/partialsに格納しました。
div Navigation
フッター
フッターとして以下のfooter.jadeをWEB-INF/partialsに格納しました。
div Footer
サイド・バー
フッターとして以下のsidebar.jadeをWEB-INF/partialsに格納しました。
div Sidebar
Webページ
WebアプリケーションのWebページとしてindex.htmlを用意します。
後述のBootstrap版との比較のために、Bootstrapのクラスを用いた同じWebページを用いています。この版ではBootstrapの設定は行っていないので、画面表示に影響しません。
<!doctype html>
<html>
<head>
<title>HelloLayout</title>
</head>
<body>
<h1>HelloLayout</h1>
<table class="table">
<thead>
<tr>
<th scope="col">#</th>
<th scope="col">First</th>
<th scope="col">Last</th>
<th scope="col">Handle</th>
</tr>
</thead>
<tbody>
<tr>
<th scope="row">1</th>
<td>Mark</td>
<td>Otto</td>
<td>@mdo</td>
</tr>
<tr>
<th scope="row">2</th>
<td>Jacob</td>
<td>Thornton</td>
<td>@fat</td>
</tr>
<tr>
<th scope="row">3</th>
<td colspan="2">Larry the Bird</td>
<td>@twitter</td>
</tr>
</tbody>
</table>
</body>
</html>
実行
curlコマンドによってローカルホストの8080ポート上の/web/HelloLayout/を取得します。
/web はCozy上のWebアプリケーションのホームです。その配下のHelloLayoutが、先程作成したディレクトリHelloLayoutに対応するもので、ディレクトリ名がアプリケーション名になっています。
$ curl http://localhost:8080/web/HelloLayout/
取得結果は以下になります。無事登録したHTML文書を取得することができました。
HTML文書には期待通りLayoutの各種設定が自動的に行われています。
<!DOCTYPE html>
<html lang="ja">
<head>
<title>HelloLayout</title>
</head>
<body>
<div>Header</div>
<div>Navigation</div>
<div>Sidebar</div>
<h1>HelloLayout</h1>
<table class="table">
<thead>
<tr>
<th scope="col">#</th>
<th scope="col">First</th>
<th scope="col">Last</th>
<th scope="col">Handle</th>
</tr>
</thead>
<tbody>
<tr>
<th scope="row">1</th>
<td>Mark</td>
<td>Otto</td>
<td>@mdo</td>
</tr>
<tr>
<th scope="row">2</th>
<td>Jacob</td>
<td>Thornton</td>
<td>@fat</td>
</tr>
<tr>
<th scope="row">3</th>
<td colspan="2">Larry the Bird</td>
<td>@twitter</td>
</tr>
</tbody>
</table>
<div>Footer</div>
</body>
</html>
このページは以下のように表示されます。
LayoutBootstrap
レイアウト機能を使うと、定形のWebページ内に定義した部品を差し込める事が分かりました。
このレイアウト機能を使って、Bootstrapベースの定形ページを作ってみます。
準備
cozyを起動するディレクトリのwebappsディレクトリに、アプリケーションのホームとなるディレクトリLayoutBootstrapを作成します。このディレクトリLayoutBootstrapをアプリケーションのホームディレクトリとなります。
共通テンプレート
Webページで共有されるテンプレートとして以下のものをWEB-INF/layouts/default.jadeに作成します。このテンプレートページでBootstrapに必要な設定を行っています。
-@val model: ViewModel
!!! 5
html(lang="ja")
head
meta(charset="utf-8")
meta(name="viewport" content="width=device-width, initial-scale=1")
link(href="https://cdn.jsdelivr.net/npm/bootstrap@5.1.3/dist/css/bootstrap.min.css" rel="stylesheet" integrity="sha384-1BmE4kWBq78iYhFldvKuhfTAU6auU8tT94WrHftjDbrCEXSU1oBoqyl2QvZ6jIW3" crossorigin="anonymous")
=model.pageTitle
body
script(src="https://cdn.jsdelivr.net/npm/bootstrap@5.1.3/dist/js/bootstrap.bundle.min.js" integrity="sha384-ka7Sk0Gln4gmtz2MlQnikT1wXgYsOg+OMhuP+IlRH9sENBO0LRn5q+8nbTov4+1p" crossorigin="anonymous")
header
=model.header
=model.navigation
div(class="container-fluid pb-3 flex-grow-1 d-flex flex-column flex-sm-row overflow-auto")
div(class="row flex-grow-sm-1 flex-grow-0")
aside(class="col-sm-3 flex-grow-sm-1 flex-shrink-1 flex-grow-0 sticky-top pb-sm-0 pb-3")
div(class="bg-light border p-1 h-100 sticky-top")
=model.sidebar
main(class="col overflow-auto h-100")
=model.content
footer
=model.footer
部品ページ
Webページの部品はWEB-INF/partialsに格納します。
ヘッダー
ヘッダーとして以下のheader.jadeをWEB-INF/partialsに格納しました。
Bootstrapのクラスを設定しています。
nav(class="navbar navbar-light bg-primary")
div(class="container-fluid")
span(class="navbar-brand mb-0 h1") Cozy Web
ナビゲーション・バー
ナビゲーション・バーとして以下のnavigation.jadeをWEB-INF/partialsに格納しました。
Bootstrapの機能を用いてナビゲーション・バーを実現しています。
nav(class="navbar navbar-expand-lg navbar-light bg-light")
div(class="container-fluid")
a(class="navbar-brand" href="#") Navbar
button(class="navbar-toggler" type="button" data-bs-toggle="collapse" data-bs-target="#navbarNav" aria-controls="navbarNav" aria-expanded="false" aria-label="Toggle navigation")
span(class="navbar-toggler-icon")
div(class="collapse navbar-collapse" id="navbarNav")
ul(class="navbar-nav")
li(class="nav-item")
a(class="nav-link active" aria-current="page" href="#") Home
li(class="nav-item")
a(class="nav-link" href="#") Features
li(class="nav-item")
a(class="nav-link" href="#") Pricing
li(class="nav-item")
a(class="nav-link disabled" href="#" tabindex="-1" aria-disabled="true") Disabled
フッター
フッターとして以下のfooter.jadeをWEB-INF/partialsに格納しました。
Bootstrapのクラスを設定しています。
nav(class="navbar navbar-light bg-secondary") span Cozy Web
サイド・バー
サイド・バーとして以下のsidebar.jadeをWEB-INF/partialsに格納しました。
Bootstrapの機能を用いてサイド・バーを実現しています。
ul(class="nav nav-pills flex-sm-column flex-row mb-auto justify-content-between text-truncate")
li(class="nav-item")
a(href="#" class="nav-link px-2 text-truncate")
i(class="bi bi-house fs-5")
span(class="d-none d-sm-inline") Home
li
a(href="#" class="nav-link px-2 text-truncate")
i(class="bi bi-speedometer fs-5")
span(class="d-none d-sm-inline") Dashboard
li
a(href="#" class="nav-link px-2 text-truncate")
i(class="bi bi-card-text fs-5")
span(class="d-none d-sm-inline") Orders
li
a(href="#" class="nav-link px-2 text-truncate")
i(class="bi bi-bricks fs-5")
span(class="d-none d-sm-inline") Products
li
a(href="#" class="nav-link px-2 text-truncate")
i(class="bi bi-people fs-5")
span(class="d-none d-sm-inline") Customers
Webページ
表示したい本文を記述したページをindex.htmlとして用意します。
これは前出のHelloLayout版と基本的に同じ内容です。(タイトルだけ変更しています)今度はBootstrapのクラス指定が活きてくるはずです。
<!doctype html>
<html>
<head>
<title>LayoutBootstrap</title>
</head>
<body>
<h1>LayoutBootstrap</h1>
<table class="table">
<thead>
<tr>
<th scope="col">#</th>
<th scope="col">First</th>
<th scope="col">Last</th>
<th scope="col">Handle</th>
</tr>
</thead>
<tbody>
<tr>
<th scope="row">1</th>
<td>Mark</td>
<td>Otto</td>
<td>@mdo</td>
</tr>
<tr>
<th scope="row">2</th>
<td>Jacob</td>
<td>Thornton</td>
<td>@fat</td>
</tr>
<tr>
<th scope="row">3</th>
<td colspan="2">Larry the Bird</td>
<td>@twitter</td>
</tr>
</tbody>
</table>
</body>
</html>
実行
curlコマンドによってローカルホストの8080ポート上の/web/LayoutBootstrap を取得します。
$ curl http://localhost:8080/web/LayoutBootstrap/
取得結果は以下になります。無事、登録したHTML文書にBootstrapの各種設定を行ったHTML文書を取得することができました。
<!DOCTYPE html>
<html lang="ja">
<head>
<meta charset="utf-8" />
<meta content="width=device-width, initial-scale=1" name="viewport" />
<link crossorigin="anonymous" integrity="sha384-1BmE4kWBq78iYhFldvKuhfTAU6auU8tT94WrHftjDbrCEXSU1oBoqyl2QvZ6jIW3" rel="stylesheet" href="https://cdn.jsdelivr.net/npm/bootstrap@5.1.3/dist/css/bootstrap.min.css" />
<title>LayoutBootstrap</title>
</head>
<body>
<script crossorigin="anonymous" integrity="sha384-ka7Sk0Gln4gmtz2MlQnikT1wXgYsOg+OMhuP+IlRH9sENBO0LRn5q+8nbTov4+1p" src="https://cdn.jsdelivr.net/npm/bootstrap@5.1.3/dist/js/bootstrap.bundle.min.js"></script>
<header>
<nav class="navbar navbar-light bg-primary">
<div class="container-fluid">
<span class="navbar-brand mb-0 h1">Cozy Web</span>
</div>
</nav>
<nav class="navbar navbar-expand-lg navbar-light bg-light">
<div class="container-fluid">
<a class="navbar-brand" href="#">Navbar</a>
<button class="navbar-toggler" type="button" data-bs-toggle="collapse" data-bs-target="#navbarNav" aria-controls="navbarNav" aria-expanded="false" aria-label="Toggle navigation">
<span class="navbar-toggler-icon"></span>
</button>
<div class="collapse navbar-collapse" id="navbarNav">
<ul class="navbar-nav">
<li class="nav-item">
<a class="nav-link active" aria-current="page" href="#">Home</a>
</li>
<li class="nav-item">
<a class="nav-link" href="#">Features</a>
</li>
<li class="nav-item">
<a class="nav-link" href="#">Pricing</a>
</li>
<li class="nav-item">
<a class="nav-link disabled" href="#" tabindex="-1" aria-disabled="true">Disabled</a>
</li>
</ul>
</div>
</div>
</nav>
</header>
<div class="container-fluid pb-3 flex-grow-1 d-flex flex-column flex-sm-row overflow-auto">
<div class="row flex-grow-sm-1 flex-grow-0">
<aside class="col-sm-3 flex-grow-sm-1 flex-shrink-1 flex-grow-0 sticky-top pb-sm-0 pb-3">
<div class="bg-light border p-1 h-100 sticky-top">
<ul class="nav nav-pills flex-sm-column flex-row mb-auto justify-content-between text-truncate">
<li class="nav-item">
<a href="#" class="nav-link px-2 text-truncate">
<i class="bi bi-house fs-5"></i>
<span class="d-none d-sm-inline">Home</span>
</a>
</li>
<li>
<a href="#" class="nav-link px-2 text-truncate">
<i class="bi bi-speedometer fs-5"></i>
<span class="d-none d-sm-inline">Dashboard</span>
</a>
</li>
<li>
<a href="#" class="nav-link px-2 text-truncate">
<i class="bi bi-card-text fs-5"></i>
<span class="d-none d-sm-inline">Orders</span>
</a>
</li>
<li>
<a href="#" class="nav-link px-2 text-truncate">
<i class="bi bi-bricks fs-5"></i>
<span class="d-none d-sm-inline">Products</span>
</a>
</li>
<li>
<a href="#" class="nav-link px-2 text-truncate">
<i class="bi bi-people fs-5"></i>
<span class="d-none d-sm-inline">Customers</span>
</a>
</li>
</ul>
</div>
</aside>
<main class="col overflow-auto h-100">
<h1>LayoutBootstrap</h1>
<table class="table">
<thead>
<tr>
<th scope="col">#</th>
<th scope="col">First</th>
<th scope="col">Last</th>
<th scope="col">Handle</th>
</tr>
</thead>
<tbody>
<tr>
<th scope="row">1</th>
<td>Mark</td>
<td>Otto</td>
<td>@mdo</td>
</tr>
<tr>
<th scope="row">2</th>
<td>Jacob</td>
<td>Thornton</td>
<td>@fat</td>
</tr>
<tr>
<th scope="row">3</th>
<td colspan="2">Larry the Bird</td>
<td>@twitter</td>
</tr>
</tbody>
</table>
</main>
</div>
</div>
<footer>
<nav class="navbar navbar-light bg-secondary">
<span>Cozy Web</span>
</nav>
</footer>
</body>
</html>
このページは以下のように表示されます。
Bootstrapの機能を活かしたレイアウト、カラーコーディネーションになっています。
小さな画面で表示すると、以下のようにメニューが折り畳まれて表示されます。Bootstrapのレシポンシブデザインが効いていることが分かります。
まとめ
Cozy Webのレイアウト機能について説明しました。
BootstrapのようなWebフレームワークの定形テンプレートを容易に作成することができます。
次回は、定形テンプレートをさらに部品化する方法について説明します。
諸元
- Cozy
- 0.0.6



