Challenge Engineer Life !

エンジニア人生を楽しみたい!仕事や趣味で学んだ技術的なことを書いていくブログです。

JSFでもモダンなUIが作りたい!

この記事は「Java EE Advent Calendar 2014」の23日目のエントリーです。
昨日は@den2snさんの「JSFのバリデーション - DENの思うこと」でした。明日は@HirofumiIwasakiさんです。

受託でエンプラ

私の仕事は受託開発がメインで、主に製造業のお客様向けに販売管理システムの構築を行っています。
(製造業で複雑な製品扱っている所は営業さんが見積作るの大変なので、その辺をコンフィグレータ使ってうまいことするシステム)

見積業務もお客様によってそれぞれ異なるので、要件に合わせて毎回要件定義して、システムも裏にERPがいたり、フロントでCRMがいて連携したり、色々です。まぁ、いわゆるエンプラなシステムです。

昨今、Web系への憧れというのは当然あって、受託やエンプラで負のネタをみるたび「ですよねー」と思ったりも(^^;;

……

おっと、愚痴でなくAdventでした。

そんなWeb系、フロントとバックで色々と違うのでしょうが、フロント側というのは、素のHTMLは当然のこと、HTML5やCSS、JavaScriptはバリバリで、特に昨今のJavaScriptフレームワークなんかは色々と使いこなせるエンジニアなんだろなぁと勝手にそんなイメージでいます(^^;

一方自分はというと、Web系システムやってるけど全然違います(^^;

最近では、AngularJSとか勉強して、業務でもやってみたいとは思いつつ、周囲をみてもJavaScript書けるエンジニアは一人もいませんし、チームとしての学習コストや保守性を等を考えると中々上長の承認も難しいのかなと(この辺がエンプラ的…)

とはいえ、昨今、お客さんの目が肥えているのは事実で、モダンなWebを求められることはあるわけです。

最近のケースだと、お客さんがNulabさんのBacklogを使っていて「クリックするとダイアログじゃなくてパネルが出てきて、こういう動きとか」みたいな感じでお話があったり。

JSF + PrimeFaces

私の所では、Java EEのJSF(JavaServer Faces)をここ2年くらいメインにしていて、さらにPrimeFacesと呼ばれるリッチコンポーネントを利用しています。

ちょうど初めてJava EE Advent Calendarに参加した2012年がそのネタでした。

JSFイケてないよね、というのは散々あちこちで聞きますし、もう言われ疲れたので、その辺の議論は置いておいて(^^;
今日はJSFだとこんな感じに、という所を書きたいなと思います。

NulabさんのBacklog

ここ1年くらいですが、仕事での課題管理は、社内開発された障害管理システムやTracからNulabさんのBacklogへ移行しています。

以前にnulabさんのカンファレンスnuconに参加しましたが、利用してる会社は相当多いですよね(^^;すごい

せっかくなので、今日はBacklogを参考に、JSFだとどんな風に作れるか、少し遊んでみました。

Backlogはメイン画面がこんな感じです。
f:id:kikutaro777:20141223221613j:plain
ちなみにこれは、会社の社内公募(コンペ)のチームで使ったときのものですが、昨日に社内で結果発表があって何と最優秀に選ばれました!わーい(^^)/

この画面をJSF+PrimeFacesでちょっと作ってみました(^^;
時間の都合で、簡易版ですが…
f:id:kikutaro777:20141223223541j:plain

また、Backlogではどう作られているか、という所までは時間の都合上みれていないです。すみません。

Sticky

Backlogの上段にあるメニューバーは常に最上段に表示されていて、課題のフィードとかが長くなったときでもちゃんと利用できます。
f:id:kikutaro777:20141223222722j:plain

最近だとよくあるものですが、業務系だと…どうでしょう(^^;
マウスで戻らせるものも多々ある気が…。

PrimeFacesにはStickyというコンポーネントがあって、これで同じことができるようになっています。

f:id:kikutaro777:20141223223625j:plain

faceletsの定義は簡単でstickyコンポを置いて、target属性で、固定したいコンポーネントのidを指定するだけです。
今回の例ではツールバーを固定しています。

<p:sticky target="tlbHeader" />

<p:toolbar id="tlbHeader">
    <f:facet name="left">
        <p:commandButton id="btnHomeMenu" icon="ui-icon-home" />
    </f:facet>
    <f:facet name="right">
        <p:themeSwitcher effect="fade">
            <f:selectItems value="#{backlogBean.listTheme}" />
        </p:themeSwitcher>
    </f:facet>
</p:toolbar>

Overlay PanelとTooltip

Backlogの左上にあるアイコンをクリックすると
f:id:kikutaro777:20141223222301j:plain

同じ画面に吹き出し形のパネルが表示されます。
また、画像にマウスオーバーするとツールチップも吹き出しの形で出てますね。
f:id:kikutaro777:20141223222316j:plain

こういうパーツはここだけでなく結構いろんな所で使われています。
ユーザ的にはダイアログ表示より手軽に付加情報がみれていいですよね。

PrimeFacesだとOverlay Panelを使うのが良さそうです。
ツールチップはTooltipコンポーネントがあります。

ボタンがあって
f:id:kikutaro777:20141223223918j:plain

クリックするとパネル表示。ツールチップは吹き出しではないですが。
f:id:kikutaro777:20141223223924j:plain

faceletsはこんな感じで、overlayPanelのfor属性で、先ほどのツールバーに置いてあるボタンのidを指定しています。

<p:overlayPanel for="btnHomeMenu" showEffect="slide" hideEffect="slide" dynamic="true">
    堀北真希さん写真集 絶賛発売中
    <h:panelGrid columns="3">
        <h:graphicImage id="imgCastella" value="/resources/images/castella.jpg" />
        <h:graphicImage id="imgDramatic" value="/resources/images/dramatic.jpg" />
        <h:graphicImage id="imgS" value="/resources/images/s.jpg" />
    </h:panelGrid>
    <p:tooltip for="imgCastella" showEffect="fade" hideEffect="fade"
               value="出版社: ワニブックス ISBN-10: 4847029283 発売日: 2006/3/25" 
               trackMouse="true" />
    <p:tooltip for="imgDramatic" showEffect="fade" hideEffect="fade"
               value="出版社: マガジンハウス ISBN-10: 483872604X 発売日: 2013/9/26" 
               trackMouse="true" />
    <p:tooltip for="imgS" showEffect="fade" hideEffect="fade"
               value="出版社: マガジンハウス ISBN-10: 4838719159 発売日: 2008/10/10" 
               trackMouse="true" />
</p:overlayPanel>

パネルの表示と隠れる際にエフェクトを指定することもできます。ここではslideにして、横からスライドしてくるような表示です。
また、tooltipも色々と属性があって、trackMouseをtrueにすると、マウスカーソルの移動にあわせてツールチップが付いてくるような動きになったりします。

マウスカーソルが画像の右上にあるとき
f:id:kikutaro777:20141223224604j:plain

左下
f:id:kikutaro777:20141223224638j:plain

DataTableのExpansion

Backlogではマウスオーバーすると展開されて情報が出てくるものもよくありますよね。
例えばプロジェクト情報の行にマウスオーバーすると
f:id:kikutaro777:20141223224756j:plain

メニューが
f:id:kikutaro777:20141223224802j:plain

PrimeFacesで、これと同じもの、、、は今回見つからなかったのですが、DataTableのExpansionで少し近いものができるのかなと。

これだとカラムでこんなのがついて
f:id:kikutaro777:20141223225004j:plain

クリックすると展開される形で、マウスオーバーよりアクションは多いですが(^^;
f:id:kikutaro777:20141223225044j:plain

faceletsは次のような形で、普通のdataTableに対して、rowTogglerとrowExpansionを付けてあげるだけでできます。

<p:dataTable var="prj" value="#{backlogBean.listProject}">
    <f:facet name="header">
        プロジェクト
    </f:facet>
    <p:column>
        <h:outputText value="#{prj}" />
    </p:column>
    <p:column width="16">
        <p:rowToggler />
    </p:column>
    <p:rowExpansion>
        <h:commandLink value="課題の検索" />
        <h:commandLink value=" | " />
        <h:commandLink value="課題の追加" />
    </p:rowExpansion>
</p:dataTable>

最初から全部展開させておきたい場合はdataTableにexpandRow属性というのがあるので、これをtrueにすればできたりします。

Rating

Backlogでは各投稿に「いいね」チックに星マークがつけられます。
人によって利用頻度が違いますが、いいですよね。
f:id:kikutaro777:20141223230311j:plain

PrimeFacesだとRatingコンポーネントが、そのままの機能です。
f:id:kikutaro777:20141223230416j:plain

faceletsではratingコンポを置いて、value属性でIntegerの変数(星の数を表す)とバインドするだけです。

<p:rating value="#{ticket.rating}" />

その他の属性で星の数を変えたり、色々な設定が可能です。

DataScroller

課題のフィードは、TwitterやFacebookみたいに、ある一定が表示されていて、どんどん追加表示していくことができます。
「もっと見る」にマウスオーバーすると次の何件かの課題が追加表示される形です。
f:id:kikutaro777:20141223225555j:plain

PrimeFacesだとDataScrollerを使うのが良さそうです。
f:id:kikutaro777:20141223225744j:plain

ボタンを押すと
f:id:kikutaro777:20141223225822j:plain

ボタンでない形式もできて、その場合はTwitterと同じようにフィードの最下端がブラウザの一番下にあたったときに自動的に読み込まれる形式です。
PrimeFacesのshowcaseがそうなってますね。
http://www.primefaces.org/showcase/ui/data/datascroller/basic.xhtml

そのせいで、このshowcaseページは下にあるサンプルコードが読めないっていうあれになってるんですが(^^;

faceletsは次のような感じです。DataTableとかと同じで、POJOなインスタンスを処理できるので、ここではTicketという課題を表すクラスのリストを渡して表示しています。

<p:dataScroller var="ticket" value="#{backlogBean.listTicket}"
                chunkSize="10">
    <f:facet name="loader">
        <p:commandButton type="button" value="View More" />
    </f:facet>
    <h:graphicImage value="/resources/images/makimaki.jpeg" width="32" />
    <h:commandLink value="#{ticket.id}" />
    <p:rating value="#{ticket.rating}" />
    <h:outputText value="#{ticket.content}" />
</p:dataScroller>

GridCSS

最後ですが、Backlogではブラウザの横幅サイズを変えるとレスポンシブにUIが変わります。

f:id:kikutaro777:20141223230955j:plain

横を縮めていくと
f:id:kikutaro777:20141223231008j:plain

PrimeFacesではGridCSSをつかって同じことができます。前に少し書きましたが、この仕組みです。

通常の画面を縮めていき
f:id:kikutaro777:20141223232152j:plain

こうなる
f:id:kikutaro777:20141223232213j:plain

ThemeSwitcher

最後に、これはBacklogと少し違いますが、PrimeFacesでは色々なテーマが用意されており、ThemeSwitcherコンポにて切り替えることができます。

今までのはRedmondというテーマだったのですが、

オレンジベースで少し明るめなui-lightnessや
f:id:kikutaro777:20141223232637j:plain

Flickrチックなもの
f:id:kikutaro777:20141223232702j:plain

カエル的な…
f:id:kikutaro777:20141223232724j:plain

jQuery UIのTheme使ったことある方はお馴染みかもしれませんが(^^;

まとめ

作ったサンプルコードはGitHubに置きました。
kikutaro/JsfBacklogSample · GitHub

今回の例では、自分で書いたCSS、JavaScriptはゼロです(^^;
これは全て、PrimeFacesのコンポーネントが内包しているためです。

それが良いわけでは全然ないのですが、私のように書けない人間がエンプラでモダンさを求められた場合、今こんな風にやっていますという所でした。

ちなみにPrimeFacesは相当な数のコンポーネントが揃っているのですが、まだまだ今でも追加していて驚きます(^^;

JSFはコンポーネントベースなので、どういうコンポがあるか抑えていれば、プロトタイピングもサクサクできるので、今は要件定義でも積極的に使うようにして、はやめに動きの認識合わせをお客さんとすることに利用しています。

JSFはJava EE 8でのJSF2.3に向けて、様々な拡張も継続しているようです。

日本OracleのJavaエバンジェリストである寺田さんから教えて頂いた情報↓

既にブログ書かれている方も(はやい!)

2015年はJavaScriptなどWeb系の勉強やウォッチに力を入れていきたいなと思う今日この頃です。

にほんブログ村 IT技術ブログへ
にほんブログ村 にほんブログ村 IT技術ブログ Javaへ
にほんブログ村