2020/03/29

XPagesでBootstrap導入

これまでOneUI使ってアプリ開発してきたが、Bootstrapのテーマを使ってみよう。 画面構成は以下のようなヘッダ、メニュー、コンテンツ、フッターの構成。

アプリ構成

この構成は以前作ったOneUIを使ったXPageの作り方と同じ。 HUMCOM.nsfを元に改造してみる。 OneUIからBootstrapに切り替えるときに参考になるように。

OneUIの考え方

OneUIでは中身に応じてlotusMenuやlotusContentみたいなクラスが用意されてて、それを<div>要素に適用して画面構成を作る。

oneUIのレイアウト

Bootstrapテーマにもその手のものが何か用意されてるといいんだけど、デザインはある程度自分で設定しないといけないみたい。 まぁそれは後でまとめてやるとして、さっそく作ってみよう。

基本設定

Bootstrapを使うときは、まずはテーマを設定。

Bootstrapテーマ設定

BootstrapのテーマはV10から? V9にはなかったはず。ただしV10ではBootstrap3まで。Bootstrap4はV11から使えるのだろうか。

<xp:callback>を使ったレイアウト設計

文書の一覧を表示するXPageのソースはこんな感じ。このレベルではOneUIもBootstrapもさほど変わらない。

  01:  <?xml version="1.0" encoding="UTF-8"?>
  02:  <xp:view xmlns:xp="http://www.ibm.com/xsp/core"
  03:    xmlns:xc="http://www.ibm.com/xsp/custom">
  04:    <xp:this.resources>
  05:      <xp:script src="/hc.jss" clientSide="false"></xp:script>
  06:      <xp:script src="/hcacc.jss" clientSide="false"></xp:script>
  07:      <xp:styleSheet href="/humcon.css"></xp:styleSheet>
  08:      <xp:styleSheet href="/myStyle.css"></xp:styleSheet>
  09:    </xp:this.resources>
  10:    <xc:xcLayout>
  11:      <xp:this.facets>
  12:        <xc:pcBookViewCC xp:key="facetBody" />
  13:      </xp:this.facets>
  14:    </xc:xcLayout>
  15:  </xp:view>
  

<xc:xcLayout>の設計

<xc:xcLayout>でアプリ内の基本構造を決めている。

<xc:xcLayout>はこんな設計になってる。

  01:  <?xml version="1.0" encoding="UTF-8"?>
  02:  <xp:view xmlns:xp="http://www.ibm.com/xsp/core" xmlns:xc="http://www.ibm.com/xsp/custom">
  03:    <div>
  04:      <xc:xcBanner></xc:xcBanner>
  05:      <div class="container-fluid">
  06:        <div class="row">
  07:          <div class="col-md-2 ">
  08:            <xc:xcMenu></xc:xcMenu>
  09:          </div>
  10:          <div class="col-md-10">
  11:            <xp:callback facetName="facetBody" id="facetBody"></xp:callback>
  12:          </div>
  13:        </div>
  14:      </div>
  15:      <xc:xcFooter></xc:xcFooter>
  16:    </div>
  17:  </xp:view>  
  
  • <xc:xcBanner>は画面のヘッダ部。ここはBootstrapで用意されてるNavibarを使ってみる
  • メニュー部とコンテンツ部はBootstrapのグリッドシステムを使って作る。グリッドシステムについてはBootstrap導入で説明してるけど、 これを使っている。
  • メニュー用に2カラム分、コンテンツ用に10カラム分を用意して配置している。
  • Bootstrapのグリッドシステムは、全体をcontainerで囲って、1行分をrowで囲み、メニューをcol-md-2、コンテンツをcol-md-10で区切っている
  • Bootstrap3では"col-2"のような指定ができないので注意

<xc:xcBanner>の設計

単にロゴ、タイトル、ログオン情報を表示するだけならわざわざNavbarを使うまでもないかもしれないが、プルダウンメニューなども使えるので、覚えてて損はないかも。

こんなのを作ってみる。

oneUIのレイアウト

<xc:xcBanner>でNavbarを作ってる。 ソースコードはこんな感じ。

  01: <?xml version="1.0" encoding="UTF-8"?>
  02: <xp:view xmlns:xp="http://www.ibm.com/xsp/core">
  03:   <nav class="navbar navbar-default">
  04:     <div class="container-fluid">
  05:       <div class="navbar-header">
  06:         <button type="button" class="navbar-toggle collapsed"
  07:           data-toggle="collapse" data-target="#navbarEexample">
  08:           <span class="sr-only">Toggle navigation</span>
  09:           <span class="icon-bar"></span>
  10:           <span class="icon-bar"></span>
  11:           <span class="icon-bar"></span>
  12:         </button>
  13:         <p class="navbar-text" ><xp:image url="/logo.png" /></p>
  14:         <p class="navbar-text">
  15:           <xp:label value="PC管理台帳" style="font-weight:bold;font-size:24pt">
  16:           </xp:label>
  17:         </p>
  18:       </div>
  19:       <div class="collapse navbar-collapse" id="navbarEexample">
  20:         <ul class="nav navbar-nav">
  21:           <li>
  22:             <a href="#">メニューA</a>
  23:           </li>
  24:           <li>
  25:             <a href="#">メニューB</a>
  26:           </li>
  27:           <li class="dropdown ">
  28:             <a href="#" class="dropdown-toggle" data-toggle="dropdown" role="button">
  29:               ドロップダウンA
  30:               <span class="caret"></span>
  31:             </a>
  32:             <ul class="dropdown-menu" role="menu">
  33:               <li>
  34:                 <a href="#">リンクリストA1</a>
  35:               </li>
  36:               <li>
  37:                 <a href="#">リンクリストA2</a>
  38:               </li>
  39:               <li>
  40:                 <a href="#">リンクリストA3</a>
  41:               </li>
  42:             </ul>
  43:           </li>
  44:         </ul>
  45:         <ul class="nav navbar-nav navbar-right">
  46:           <li>
  47:             <div style="margin: 1em;">
  48:               <xp:label value="ユーザー:" id="label1"></xp:label>
  49:               <xp:label id="label2">
  50:                 <xp:this.value><![CDATA[#{javascript:$hcacc.un2kanji(@UserName()) + "/" + $hcacc.un2group(@UserName())}]]></xp:this.value>
  51:               </xp:label>
  52:             </div>
  53:           </li>
  54:         </ul>
  55:       </div>
  56:     </div>
  57:   </nav>
  58: </xp:view>
  
  • 3行目の <nav class="navbar navbar-default">と4行目の<div class="container-fluid">で外側の器を作ってる
  • 内側は<div class="navbar-header"> と<div class="collapse navbar-collapse"> に分かれてる
  • navbar-headerは、Navbarの見出しみたいなもので、画面の幅を狭めた時も表示されるエリア
  • navbar-header部にはハンバーガーボタン、ロゴ、タイトルを含ませている。<p class="navbar-text" >で区切りながら、ロゴや文字列を配置できる
  • "collapse navbar-collapse"は、メニュー部で、画面の幅が狭くなるとハンバーガーメニュークリックで表示されるエリア
  • メニュー部のid指定を6〜7行目のdata-targetで指定することで、画面の幅が狭くなった時にハンバーガーメニューに自動で切り替わるようになる
  • メニューとプルダウンメニューは<ul>と<li>で表現される
  • 右端に情報を表示するために、<ul>で2番目の塊を追加し、navbar-rightを指定して、右寄りに配置している

<xc:xcMenu>の設計

ここは左側のサイドメニュー。 こんなのを作ってみる。

oneUIのレイアウト

グリッドシステムで2カラム分を使っているので、画面の幅が狭くなると、画面の上部(Navbarの下)に配置されるようになる。

メニューのタイトルみたいなものはどうやって作るのかと思ったが、class="panel-heading"というものをつかえばいいらしい。 OneUIのメニューよりはだいぶシンプルに記載できる。

  01: <?xml version="1.0" encoding="UTF-8"?>
  02: <xp:view xmlns:xp="http://www.ibm.com/xsp/core">
  03:   <div class="panel panel-default">
  04:     <div class="panel-heading">
  05:       Select View
  06:     </div>
  07:     <ul class="nav nav-pills nav-stacked">
  08:       <li>
  09:         <xp:link escape="true" id="link1" value="/pcBookView.xsp">
  10:           <i class="glyphicon glyphicon-folder-open"></i>一覧
  11:         </xp:link>
  12:       </li>
  13:       <li>
  14:         <xp:link escape="true" id="link2"  value="/pcBook.xsp">
  15:           <i class="glyphicon glyphicon-pencil"></i>新規作成
  16:         </xp:link>
  17:       </li>
  18:     </ul>
  19:   </div>
  20: </xp:view>
  
  • 10行目の"glyphicon"はBootstrap3のWebフォントアイコンというやつ。文字のような感覚で指定できる。

<xc:xcFooter>の設計

Footerは単に背景色つけて、ちょっとした文言を入れてる。

  01: <?xml version="1.0" encoding="UTF-8"?>
  02: <xp:view xmlns:xp="http://www.ibm.com/xsp/core">
  03:   <footer class="page-footer bg-success ">
  04:     <div class="container">
  05:       <div class="row">
  06:         <div class="col-12 ">
  07:           <div class="text-right py-3 ">
  08:             Produced by
  09:             <xp:link escape="true" text=" My Technical Notes" id="link1"
  10:               value="https://tech-notes.org" title="TechNotes">
  11:             </xp:link>
  12:           </div>
  13:         </div>
  14:       </div>
  15:     </div>
  16:   </footer>
  17: </xp:view>
  
  • 3行目のpage-footerは自前で定義したものでmarginとpaddingを設定してる
  • レスポンシブデザインに対応できるように、グリッドシステムで幅を設定してる

Contentsの部分

Contents部分は基本さわらなくていい。OneUIのクラス設定はしてないので。

ただ、Pagerの表示がおかしくなってしまった。

Pagerのイメージ

OneUIの時のPagerの表示はこんな感じ。右寄せして文字を小さめにしたい。

Pagerのイメージ

OneUIとBootstrapのページを解析してみると、Pagerの部分で生成されるHTMLが全く違うのね。 指定されてるclassも結構違う。

<xp:Pager>がBootstrapで用意されているPaginationに変換されるようだ。

BootstrapテーマのPagerの構造

BootstrapテーマでPagerの部分のHTMLはこんな構造になっている。

  01: <ul class="pagination" id="view:_id1:_id2:_id57:pager1">
  02:   <li class="disabled">
  03:     <a aria-disabled="true" id="view:_id1:_id2:_id57:pager1__Previous__lnk" role="button" aria-label="前のページ">?</a>
  04:   </li>
  05:   <li class="active">
  06:     <a id="view:_id1:_id2:_id57:pager1__Group__lnk__0" aria-label="ページ 1" role="button" aria-pressed="true">1</a>
  07:   </li>
  08:   <li>
  09:     <a id="view:_id1:_id2:_id57:pager1__Group__lnk__1" aria-label="ページ 2" role="button" tabindex="0" aria-pressed="false">2</a>
  10:   </li>
  11:   ...省略...
  12:   <li>
  13:     <a id="view:_id1:_id2:_id57:pager1__Group__lnk__7" aria-label="ページ 8" role="button" tabindex="0" aria-pressed="false">8</a>
  14:   </li>
  15:   <li class="disabled">
  16:     <a>...</a>
  17:   </li>
  18:   <li>
  19:     <a aria-disabled="false" href="#" id="view:_id1:_id2:_id57:pager1__Next__lnk" role="button" aria-label="次のページ">?</a>
  20:   </li>
  21: </ul>
  
  • 1行目の<ul>にclass="pagination"が設定されているのがわかる。これはBootstrapで用意されているクラス名
  • あとは<li>要素と中に含まれる<a>要素でPagerの[1]とか[>]の枠を作っている。標準では<li>はblock要素なので縦に並ぶが、これをinline要素に変えて枠を作る必要がある
  • 標準で読み込まれるCSSにpagination関係の設定があって、<li>要素を横に並べたり、paginationの中の<a>に枠をつけたりしてる。ここはそのまま利用させてもらえばいい
  • あとは右寄せにして、文字を小さくする設定を追加すればいい
  • pagination自体の設定を変えると、他の使われ方をしている場所にも全部影響が出てしまうが、名前や表示方法からすると、たぶんこのクラスはPagerにしか関係しなさそう

右寄せにする設定

class="pagination"されている<ul>を右寄せになるよう設定してみよう。 全ページに読み込ませているMyStyle.cssがあるので、ここで設定してみる。上下のマージンがちょっと大きすぎるので、ちょっと減らしてる。

  ul.pagination {
    float: right;
    margin: 5px 0px 5px 0px;
  }
  

文字を小さくする設定

Pagerの文字の大きさは<a>要素で設定している。そのため、class="pagination"が設定されている<ul>内の<li>内の<a>に適用するスタイルはこんな感じで。 同時に余白を変えてみよう。

  ul.pagination > li > a {
    font-size: 0.9em;
    padding: 6px 6px 6px 6px;
  }
  

これをすることで、Pagerがこんな感じに変わった。

Pagerのイメージ

ViewPanelの表示設定

BootstrapにはTableに対する装飾があるのでこれを設定してみよう。

  <xp:viewPanel rows="30" pageName="/pcBook.xsp" id="viewPanel2"
    viewStyle="width:100%" dataTableStyleClass="myViewPanel table table-striped" >
  

dataTableStyleClassにCSSのクラス名を設定すると、ViewPanelの一覧表示部の<table>のclass指定に反映されるので、ここでBootstrapで用意されているtableとtable-stripedを設定すると、 枠線や背景が設定されて見やすくなる。

Pagerのイメージ

IE11に対応するための設定

標準的な設定ではIE11でBootstrap対応のXPageを表示すると、以下のように表示が崩れる。

IE11表示NG例

画面が十分広いのにSideBarが広がってるし、Navibarのメニューも表示されてない。

この不都合を解消するいは、<head>に<meta http-equiv="X-UA-Compatible" content="IE=edge"> という記述をすればいいらしい。 IE11の互換性機能を無効(古いIEの動作をさせない)という意味らしい。IE11以外のブラウザには無意味。

この設定は各XPageのresourcesプロパティに追加すればいいらしい。元ネタはXPagesでBootstrap!

IE11用の設定

  • XPageの「すべてのプロパティ」を開く
  • "resources"の追加ボタンを押して、"xp:metaData"を選択
  • contentに"IE=edge"を設定
  • httpEquivに"X-UA-Compatible"を設定

こうすると、IE11でも正しく表示できるようになる。

<HEAD>を見てみると、以下の<meda>が追加されていた。

  <meta http-equiv="X-UA-Compatible" content="IE=edge">
  

本DBのサンプルDB

ここで作ったDBのサンプルを HUMCOM_BS.nsfに置いている。