Challenge Engineer Life !

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

2015年振り返りと2016年やりたいこと

2016年になって初の投稿、技術的な内容というより雑記です(^^;

2015年を振り返って

アウトプット低下&仕事

去年を振り返ると、やっぱりアウトプットが色々減ったなぁ、という感想が一番です。
ブログもこんな感じに…。

f:id:kikutaro777:20160111214154j:plain

2015年年明けから結構がっつりと開発が始まって、6月くらいまで厳しかったです。

そんな中、Oracleさんから声をかけて頂いてJava Day Tokyoで発表させて頂きました。すごい緊張した記憶が(-_-;
kikutaro777.hatenablog.com

そろそろ自分も脱JSFしていきたい(^^;

なお、JJUG CCCなどの勉強会系は完全に参加のみでした。というか、勉強会自体、あまり行けなかった orz

あとでコメント頂きましたが、GlassFish勉強会でお話させて頂いていた(>_<;最近物忘れが酷いです。
kikutaro777.hatenablog.com

アウトプットだけでなく、インプットも少なかったんだなぁと改めて…。

7月以降は、色々大変だ、と聞いていたPrjに参画させられてしまいし、さらに身動きが取れない感じでした。

8月から11月くらいまでは常駐となってさらに…。

仕事は、学んだことが一番活きたり、新たなことを学ぶ機会ではありますが…ここではずっと仕様検討&打合せ、だったので中々厳しかったです。

やっぱりExcelばっかりイジる日々が続くと、「何してるんだろう…」と思うこともしばしば。いや、仕事として大事なのは理解してるのですが。

そんな中、優秀な後輩が2名ほど、他の部門などへ移ることもあったりして、色々と意気消沈(今も…)。

組織的な課題検討

ここ数年、中堅以下の若手が離脱するケースが増えています。

個人的には「そりゃそうでしょ…」と思うことが多々あるのですが、気付けば自分も中堅くらいになっていて、もっと若い人のために環境作りとか、雰囲気作りをしないといけないのだなぁと。

自分でコード書いたりするより、若い人を守る管理的な位置へ…みたいな…。いや、コード書いてたい…。

と、しばらく葛藤しそうです。

で、11月に部門オフサイトみたいなのがあって、「どうしたら人材離れを防げるか?若い人を育成できるか」みたいなテーマについてあれこれ話合いがありました。

ここについては闇が多いので伏せておきます…思ったより前向きな意見が多々ありましたが、実施はされてない気が。

2016年

Salesforce

仕事ではしばらくSalesforceのAPIと戯れる感じです。それはそれで楽しいです。

記事は少なめですが、以下。

kikutaro777.hatenablog.com

kikutaro777.hatenablog.com

アプリ作りたい

今年は個人的に作ってみたいものがあるので、それを作ることを目標に色々勉強していきたいなと思います。

WebなのでJava EEな気がしつつ、個人的にはSpring Bootが気になります(^^;;;

あと、せっかくなので、JavaScriptをしっかり勉強していこうかなぁと。

サイ本買いました。

JavaScriptリファレンス 第6版
David Flanagan
オライリージャパン
売り上げランキング: 159,888

JavaScriptは、去年やろうやろうとして結局手が出せませんでした。

あいかわらずフレームワーク衰退の速さなど凄まじく、何から学べばいいやら…と。

そんな中、大晦日にQiitaでみつけた記事そのままにelectronを触ってみたのですが

エディタではAtomを使ってるので、JavaScriptでデスクトップアプリ作れること自体は知っているものの、実際に自分でやってみると何とも衝撃で。

JavaScriptやってみるかーと。

今はAureliaを選んでGet Startedをやってみたくらいです。

aurelia.io

Reactとかと悩んだのですが、色合いが乃木坂46っぽいから、という理由でAurelia触ってますw

こう書きつつ、作りたいものはJavaでサクサク作れる気もするので、そっちになるかも(^^;

色々頑張らないとー

Infinite Scroll by using #PrimeFaces Extensions Waypoint.

I'd like to implement infinite scroll page in JSF. So I tried it.

My goal

Today's goal is following simple web page by using JSF.

f:id:kikutaro777:20140101161953p:plain

How to implement

If you are familiar with jQuery, you had better look for jQuery plugins.
There are various plugins. Following site has good summary. It's Japanese site, but you can read plugin names maybe.
http://kachibito.net/web-design/5-infinite-scroll.html

Unfortunately I'm not familiar with jQuery :q

So I search JSF and infinite scroll. One of good ways is here.

Building a page with infinite scroll in PrimeFaces using Waypoints jQuery plugin

Looks nice. But finally, I found PrimeFaces Extensnions component 'Waypoint'.

PrimeFaces Extensions Waypoint component

PrimeFaces Extensions Showcase has good examples.
http://fractalsoft.net/primeext-showcase-mojarra/views/waypoint.jsf

I show my implement result at first.
Run my web application, there are many panel components like this.
f:id:kikutaro777:20140101172735j:plain

When your scroll reached the bottom of web page, then JavaScript event is executed.
The dialog shows 'すたーと', the Japanese word means start.
f:id:kikutaro777:20140101172831j:plain

What is start? Of course, JavaScript function starts.
JavaScript starts to read new panel data from Backing Bean through RemoteCommand component.

After reading adding panel data, then another JavaScript function executes.
'えんど' means end.
f:id:kikutaro777:20140101172918j:plain

It works! Ten panels are added.
f:id:kikutaro777:20140101173040j:plain

If you scroll down again, the same processing run.
f:id:kikutaro777:20140101173254j:plain

I repeated this until around 500 panels.
f:id:kikutaro777:20140101173325j:plain

Code

Here is my Backing Bean of this sample. It's very simple.

package jp.co.hoge.pfsample.ext.waypoint;

import java.io.Serializable;
import java.util.ArrayList;
import java.util.List;
import javax.annotation.PostConstruct;
import javax.faces.view.ViewScoped;
import javax.inject.Named;
import lombok.Getter;
import lombok.Setter;

@Named(value = "wayPointPanelBean")
@ViewScoped
public class WayPointPanelBean implements Serializable{

    @Getter @Setter
    private List<String> strList;
    
    private int strListMax = 0;
    
    @PostConstruct
    public void init(){
        strList = new ArrayList<>();
        for(int i = 1; i <= 50; i++){
            strList.add(Integer.toString(i));
        }
    }
    
    public void loadMorePanel(){
        //Add more panels
        strListMax = strList.size();
        for(int i = strListMax + 1; i <= strListMax + 10; i++){
            strList.add(Integer.toString(i));
        }
    }
}

Facelets is following.

<?xml version='1.0' encoding='UTF-8' ?> 
<!DOCTYPE html>
<html lang="ja"
    xmlns="http://www.w3.org/1999/xhtml"
      xmlns:h="http://xmlns.jcp.org/jsf/html"
      xmlns:p="http://primefaces.org/ui"
      xmlns:pe="http://primefaces.org/ui/extensions">
    <h:head>
        <title>Waypoint</title>
    </h:head>
    <h:body>
        <h:form prependId="true">
            <p:dataGrid id="dgPanel" var="pnl" value="#{wayPointPanelBean.strList}">
                <p:panel id="pnl" header="#{pnl}">Name:hogehoge#{pnl}</p:panel>
            </p:dataGrid>
            
            <p:remoteCommand id="remote" name="loadMore" update="dgPanel" process="@this"
                             actionListener="#{wayPointPanelBean.loadMorePanel()}"
                             oncomplete="handleLoadEnd();">
            </p:remoteCommand>

            <pe:waypoint id="way" offset="function(){return $.waypoints('viewportHeight') - $(this).outerHeight()}" widgetVar="widgetWay">
                <pe:javascript event="reached" execute="handleLoadStart(ext);" /> 
            </pe:waypoint>

            <script type="text/javascript">
                function handleLoadStart(ext){
                    if(ext.direction === "down"){
                        alert("すたーと");
                        PF('widgetWay').remove();
                        loadMore();
                    }
                }
                
                function handleLoadEnd(){
                    alert("えんど");
                    PF('widgetWay').register();
                }
            </script>
        </h:form>
    </h:body>
</html>

This is very similar code to Showcase one.

I'm not familiar with jQuery, so the offset attribute is pretty difficult for me at first.
For understanding, I read jQuery Waypoint plugin document.
http://imakewebthings.com/jquery-waypoints/#docs

Finally I figured what offset defines in this code. And I understood it.
f:id:kikutaro777:20140101211633j:plain

Environment

  • Windows 8 Pro 64bit
  • JDK 8
  • NetBeans 7.4
  • GlassFish 4.0
  • PrimeFaces 4.0
  • PrimeFaces Extensions 1.1.0

JSFで無限スクロール(Infinite Scroll)

あけましておめでとうございます。2014年も開発を中心に、自分なりにコツコツと頑張っていこうと思います(^^)

冬休み、やっと少しまとまった時間が取れたので、今さらながらにJavaScriptやjQueryを触っています。
半分遊びですが、今後もWeb系の開発が続くと思うので無駄にはならないだろうと(^^;

あと自分で遊びのWebシステムを作ろうと思っていて(多分Java EE7ベース)、「こんなことやりたい」といったイメージの具体化を少しずつしています。

無限スクロール

で、今やりたいことの1つに無限スクロールがあります。

TwitterやFacebookで画面下にスクロールするとデータが読み込まれるアレです。
最近、動画サービスのHuluに入ったのですが、画像で同じようなことがされていました。

別にJSFにこだわるわけではないのですが、JSFだとどんな風に実現するんだ?と気になって(^^;

イメージとしては以下のようにパネルのコンポーネントが並んでいる画面で下にスクロールすると新しいパネルが表示されていく、というそんな様な画面です。

f:id:kikutaro777:20140101161953p:plain

jQueryだと

jQueryのプラグインだと色々あるみたいです(^^;以下サイトでまとまってました。

jQueryを触り始めて思ったのですが、プラグインがたくさんありすぎて、どれがマッチするのか探すの結構大変そうな気が…(^^;時間があると楽しいの間違いないですが、納期ある仕事だと悩ましそうな。

JSFだと

JSFでも普通にjQueryのプラグインとうまく組み合わせて作ることもできそうです。
実際、以下のサイトはそんな感じでした。

ただ、この例ではPrimeFacesのremoteCommandコンポーネント(クライアントサイドのJSから管理対象ビーン(Backing Bean)のメソッドを呼ぶためのコンポ)を使っているので純粋にjQueryだけでとは言えないのですが(^^;

PrimeFaces ExtensionsのWaypointコンポ

PrimeFacesのデモを何気にみていたら、Extensionsに無限スクロールのサンプルがあって、コンポーネントもありました。(なぜ上記のサンプルではPrimeFaces使ってるのにこれを使わないかは不明です…)

Waypointコンポーネント
http://fractalsoft.net/primeext-showcase-mojarra/views/waypoint.jsf

中身はjQueryのWaypointプラグインを利用してると思われます(サンプルのコード的にも)

で、これを使って簡単に最初のイメージのものを作ってみました。

画面表示時こんな感じでパネルがワラワラと並んでます。
f:id:kikutaro777:20140101172735j:plain

スクロールして画面の最下端に触れるとイベントが発火して「すたーと」ダイアログ表示とともに追加のパネルデータを読み込みます(読み込む前の時点では以下図のようにパネル50まで存在)
f:id:kikutaro777:20140101172831j:plain

パネルの読み込み完了のイベントで「えんど」ダイアログが表示されます。
f:id:kikutaro777:20140101172918j:plain

パネルがちゃんと増えてるー。
f:id:kikutaro777:20140101173040j:plain

そして再度スクロールして画面下に到達すると同じことの繰り返しです。
f:id:kikutaro777:20140101173254j:plain

500個くらいまでいってみた(^^;
f:id:kikutaro777:20140101173325j:plain

無限スクロールできた(^^)

コード

管理対象ビーン(Backing Bean)に画面に表示されるパネルの元データとしてListを定義します。この例ではサンプルを簡単にするためStringにしています。

初期表示時に文字列を50個、リストに入れます。またリストに文字列を追加するメソッドも定義しておきます。

package jp.co.hoge.pfsample.ext.waypoint;

import java.io.Serializable;
import java.util.ArrayList;
import java.util.List;
import javax.annotation.PostConstruct;
import javax.faces.view.ViewScoped;
import javax.inject.Named;
import lombok.Getter;
import lombok.Setter;

@Named(value = "wayPointPanelBean")
@ViewScoped
public class WayPointPanelBean implements Serializable{

    @Getter @Setter
    private List<String> strList;
    
    private int strListMax = 0;
    
    @PostConstruct
    public void init(){
        //画面表示時に文字列50個をリストに格納
        strList = new ArrayList<>();
        for(int i = 1; i <= 50; i++){
            strList.add(Integer.toString(i));
        }
    }
    
    public void loadMorePanel(){
        //文字列データを10個リストに追加する処理
        strListMax = strList.size();
        for(int i = strListMax + 1; i <= strListMax + 10; i++){
            strList.add(Integer.toString(i));
        }
    }
}

画面側は以下のような感じで、少しややこしい感じです。

<?xml version='1.0' encoding='UTF-8' ?> 
<!DOCTYPE html>
<html lang="ja"
    xmlns="http://www.w3.org/1999/xhtml"
      xmlns:h="http://xmlns.jcp.org/jsf/html"
      xmlns:p="http://primefaces.org/ui"
      xmlns:pe="http://primefaces.org/ui/extensions">
    <h:head>
        <title>Waypoint</title>
    </h:head>
    <h:body>
        <h:form prependId="true">
            <p:dataGrid id="dgPanel" var="pnl" value="#{wayPointPanelBean.strList}">
                <p:panel id="pnl" header="#{pnl}">Name:hogehoge#{pnl}</p:panel>
            </p:dataGrid>
            
            <p:remoteCommand id="remote" name="loadMore" update="dgPanel" process="@this"
                             actionListener="#{wayPointPanelBean.loadMorePanel()}"
                             oncomplete="handleLoadEnd();">
            </p:remoteCommand>

            <pe:waypoint id="way" offset="function(){return $.waypoints('viewportHeight') - $(this).outerHeight()}" widgetVar="widgetWay">
                <pe:javascript event="reached" execute="handleLoadStart(ext);" /> 
            </pe:waypoint>

            <script type="text/javascript">
                function handleLoadStart(ext){
                    if(ext.direction === "down"){
                        alert("すたーと");
                        PF('widgetWay').remove();
                        loadMore();
                    }
                }
                
                function handleLoadEnd(){
                    alert("えんど");
                    PF('widgetWay').register();
                }
            </script>
        </h:form>
    </h:body>
</html>

流れ的には

  1. waypointコンポを定義してスクロールで検知する対象を決めます
  2. 1の条件を満たした場合にキックするJavaScriptをjavascriptコンポで紐づけます
  3. 2で呼び出されるJavaScriptの処理を定義します
  4. 3の中で管理対象ビーン(Backing Bean)のメソッドを呼ぶためにremoteCommandコンポを定義してactionListenerでメソッドを紐づけます

こんな感じです。1では通常、for属性でコンポのIDを指定するか、入れ子にwaypointを定義します。上記ではどちらの定義でもないのですが、forがnullの場合は親に対するものとなるため、上記例はFormが対象となります

JavaScriptの中でwaypointを外したり付けたりしてるのは、データを増やしたタイミングで再度イベント実行されて無限ループされるのを防ぐためです。

offsetが最初いまいちイメージできなくてマゴマゴしたのですが、以下jQuery Waypointsのドキュメントやサンプルが参考になりました。
$.waypoints('viewportHeight')はざっくり言うと内部で表示されている縦幅なんですね。
http://imakewebthings.com/jquery-waypoints/#docs

わかりにくかったので図にしてみました。
上記のwaypointはfor属性でコンポーネント指定していないので、親であるformが指定されています。なので、formのoffsetがマイナス画面でみえない分=最下端となってます。
f:id:kikutaro777:20140101211633j:plain

慣れるとわりと自由に使えそう…かな(^^;

環境

  • Windows 8 Pro 64bit
  • JDK8
  • NetBeans 7.4
  • GlassFish 4.0
  • PrimeFaces 4.0
  • PrimeFaces Extensions 1.1.0

JSFにおいてJavaScriptで取得した値をBacking Beanへ渡す

現在、片足を突っ込んでいるプロジェクトの開発は(個人的には)チャレンジングな技術テーマが多いのでやりがいはあるのですが、如何せん割込み作業が多くて集中できないのが辛い…(ノД`)

という愚痴は置いておいて…。

……

ある機能が実現できるか検証しているのですが、ざっくり言うと

クライアントサイドで、あるコンポーネントの座標を取得してサーバサイドへ渡す

というものがありました。JSFで、という条件付き…。

そもそもWebで座標って何なん… (´;ω;`)とか思ったのですが、jQuery使うと意外と簡単に取得できるんですね…知らなかった。

ただしoffsetとpositionで少し違うようで、以下サイトが詳しそうです。
http://jquery-master.net/attrcss/offset.php

とりあえず、今回はpositionで簡単なサンプル作りました。

先に動きを書くほうがわかりやすいので、実行結果から。

実行すると以下のような画面が表示されます。

f:id:kikutaro777:20130813210248j:plain

で、ボタンを押すとJavaScriptというかjQueryで取得したラベルの座標を表示

f:id:kikutaro777:20130813210301j:plain

そのまま、BackingBeanへ!

f:id:kikutaro777:20130813210337j:plain

ラベルはドラッグ可能なようにしているので、左下に移動させてみます。

f:id:kikutaro777:20130813210456j:plain

で、ボタンで座標を確認するとそれっぽい値に。

f:id:kikutaro777:20130813210537j:plain

同じくBackingBean

f:id:kikutaro777:20130813210627j:plain

最後は左上に持っていきます。

f:id:kikutaro777:20130813210641j:plain

座標

f:id:kikutaro777:20130813210654j:plain

BackingBean

f:id:kikutaro777:20130813210705j:plain

このサンプルのように、jQueryJavaScriptを使ってクライアント(ブラウザ)で取得した値をBackingBean(管理対象Bean)へ渡したいことってあるよなぁと。

これは以下のサイトを参考に、Hiddenフィールドを利用して実現しています。

How To Pass New Hidden Value To Backing Bean In JSF
JSF Tag + JavaScriptという辺り

Core JavaServer Facesの本にも似たような記述がありました。

というわけで、コードは以下の通りです。
ドラッグ可能なラベルはPrimeFacesのOutputLabelとDraggableコンポーネントを利用しています。

JSFのビュー

<?xml version='1.0' encoding='UTF-8' ?>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" 
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml"
      xmlns:h="http://java.sun.com/jsf/html"
      xmlns:p="http://primefaces.org/ui">
    <h:head>
        <title>座標をサーバサイドへ渡すサンプル</title>
    </h:head>
    <h:body>
        <h:form id="frmDraggableComp">
            <!-- JavaScript実行とactionによるサーバ処理呼び出し -->
            <h:commandButton value="Bean確認" action="#{draggableCompBean.confirm()}"
               onclick="getPosition();" />
            
            <!-- 以下2つでドラッグ可能なラベルを生成 -->
            <p:outputLabel id="lblDraggable" value="移動可能なラベル" />
            <p:draggable id="drg" for="lblDraggable" />
            
            <!-- 座標を保持するHiddenフィールド -->
            <h:inputHidden id="txtHdnLeft" value="#{draggableCompBean.left}" />
            <h:inputHidden id="txtHdnTop"  value="#{draggableCompBean.top}" />
        </h:form>
        
        <script type="text/javascript">
            function getPosition(){
                var lblObj = $("#frmDraggableComp\\:lblDraggable");
                var position = lblObj.position();
                
                alert("左から,上から = " + position.left + "," + position.top);
                
                document.getElementById("frmDraggableComp:txtHdnLeft").value = position.left;
                document.getElementById("frmDraggableComp:txtHdnTop").value = position.top;
            }
        </script>
    </h:body>
</html>

BackingBean(管理対象Bean)

package jp.co.hoge.technicalconfirmation;

import java.io.Serializable;
import javax.faces.bean.ManagedBean;
import javax.faces.bean.ViewScoped;
import lombok.Getter;
import lombok.Setter;

@ManagedBean(name = "draggableCompBean")
@ViewScoped
public class DraggableCompBean implements Serializable{

    @Getter @Setter
    private String left;
    @Getter @Setter
    private String top;
    
    public void confirm(){
        System.out.println(left + top);
    }
}

シンプルなわりに強力な感じがしつつも、自分のJavaScript力のなさを痛感します……。

PrimeFacesのJavaScript APIでテーマチェンジ!

PrimeFacesのユーザガイドを細かく読んでいくと、意外とまだ知らない機能が多い…(^^;

テーマの切替は通常

のどちらかを使いますが、これに加えて

という方法があることを知りました(^^:

web.xmlでパラメータ指定

おそらくこれが最も標準的な設定方法かと思います。
http://www.primefaces.org/themes.html

以下のようなcontext-paramを指定するだけです。

<context-param>
    <param-name>primefaces.THEME</param-name>
    <param-value>redmond</param-value>
</context-param>		

動的に変える場合はparam-valueを変数としてプログラムから変えればOKです。

ThemeSwitcherコンポーネント利用

ThemeSwitcherコンポーネントは以下Showcaseで具体的に確認できます。
http://www.primefaces.org/showcase/ui/themeswitcher.jsf

テーマ変更専用のコンポーネントですね。

JavaScript API利用

で、こんな方法もあるらしいです。

PrimeFaces固有のJavaScript API

  • changeTheme(theme)

というのがあって、具体的には以下のように使えます。

<?xml version='1.0' encoding='UTF-8' ?>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml"
      xmlns:h="http://java.sun.com/jsf/html"
      xmlns:p="http://primefaces.org/ui">
    <h:head>
        <title>PrimeFaces Theme Switch</title>
    </h:head>
    <h:body>
        <h:form id="frm">
            <p:panel id="pnl" header="JavaScriptでテーマチェンジ">
                <p:commandButton value="redmond" onclick="PrimeFaces.changeTheme('redmond');" />
                <p:commandButton value="afterdark" onclick="PrimeFaces.changeTheme('afterdark');" />
            </p:panel>
        </h:form>
        
    </h:body>
</html>
実行結果

redmond、afterdarkはそれぞれバンドルテーマの名前です。

初期表示

redmondボタン押下

afterdarkボタン押下
f:id:kikutaro777:20130810221518j:plain

使いどころは微妙ですが(^^;まあビューだけの定義で気軽にテーマチェンジできる、ってくらいかなぁ。
この「PrimeFaces.hogehoge()」で指定できるメソッドは他にも幾つかあるようなので、気が向いたら触ってみようー。

PrimeFacesのRequestContextはパワフルな予感

先日のJJUGナイトセミナー以来、コツコツとJavaScriptを勉強し始めました。
(参加記録→JJUG ナイト・セミナー「JavaエンジニアのためのJavaScript講座」に参加しました )

Java EEに限った話ではないですが、JavaScriptをもっとよく知って上手く使えれば、強力な武器になりますよね(^^)

で、実は今日初めて知ったのですが…PrimeFacesのRequestContextを利用すると、BackingBean内で生成したインスタンスをクライアント側へ返す、なんてことができるとのこと!

PrimeFacesのUser Guideに書いてあって気づいたので…やはりドキュメントは最初にしっかり目を通すべきだなぁ(^^;

で、以下のような感じの簡単なサンプル作りました。

ユーザクラス
public class User {
    private String firstname;
    private String lastname;
    
    public User(String firstname, String lastname){
        this.firstname = firstname;
        this.lastname = lastname;
    }

    //setter,getter省略
}
BackingBean
import javax.inject.Named;
import javax.enterprise.context.RequestScoped;
import org.primefaces.context.RequestContext;

@Named(value = "requestContextBean")
@RequestScoped
public class RequestContextBean {
    
    public void createUser(){
        RequestContext requestContext = RequestContext.getCurrentInstance();
        requestContext.addCallbackParam("user", new User("kikutaro", "777"));
    }  
}

先に定義したUserクラスのインスタンスを生成して、RequestContextのaddCallbackParamにセットするだけです。

JSFの画面xhtml
<?xml version='1.0' encoding='UTF-8' ?>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-

transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml"
      xmlns:h="http://java.sun.com/jsf/html"
      xmlns:p="http://primefaces.org/ui">
    <h:head>
        <title>RequestContextサンプル</title>
    </h:head>
    <h:body>
        <h:form>
            <p:commandButton id="btnSubmit" value="Submit"
                             actionListener="#{requestContextBean.createUser()}"
                             oncomplete="showUser(xhr, status, args);"/>
            
            <script type="text/javascript">
                function showUser(xhr, status, args){
                    var firstname = args.user.firstname;
                    var lastname = args.user.lastname;
                    alert(firstname + lastname);
                }
            </script>
        </h:form>
    </h:body>
</html>

ボタンだけ置いて、actionListenerでBackingBeanの処理を呼び、onCompleteでJavaScriptの関数を呼び出しています。

たったこれだけです。実行すると

f:id:kikutaro777:20130508200927j:plain

ボタン押下すると

f:id:kikutaro777:20130508200938j:plain

おお、BackingBeanで生成したインスタンスの情報がJavaScript側で取得して表示できてる!

少し前に書いた「JavaScript内でJSFのEL式が使えることを初めて知りました ~画面表示時にダイアログ表示する挙動を例に~」に書いたようにJavaScript内でEL式も使えるし、色々JavaScriptを理解して使いこなせれば強力な感じが(^^)

JJUG ナイト・セミナー 「JavaエンジニアのためのJavaScript講座」に参加しました

4月24日(水)に行われたJJUGナイト・セミナーは「JavaScript」についてでした。
http://www.java-users.jp/?p=450

申込みは凄まじい勢いで100名満員に達して、注目度の高さを感じました(^^;
ただ当日の会場を見渡すと所々空いていたので、実際の参加人数は少し減った…のかな。
そんなわけで、事前申込みできなかった自分も半分飛び入りみたいな参加で聴講させて頂きました。

今現在自分が進めている開発では、Java EE6を利用して、画面はJSFで開発していますが、やはり所々でJavaScriptが必要になります。
また、画面のコンポーネントで利用しているPrimeFacesもjQueryajaxなどのJavaScriptベースの技術を元にしており、親和性も高いため、もっとJavaScriptができれば…!と思っていた矢先のセミナーだったので参加モチベーションが非常に高かったです(^^)

内容は…と自分がまとめるまでもなく、発表資料と録画が公開されているので、ここでの説明は省きます(^^;

発表は、実際にJavaScriptを触ってみる環境の話や文法の基本的説明、クイズ式の問題などなど…初心者から上級者まで含めて楽しめる内容だったように思います。

勉強になりました(^^)

というわけで、本日、書籍も買いましたー!笑
GWの余った時間に読んで勉強しよーっと。

PrimeFacesのTabViewをJavaScriptで操作する

PrimeFacesのタブコンポーネントは実際に使ってみると、ちょくちょく予期せぬ挙動をすることがあったりして悩まされることがあります(^^;使い方が悪い気もしますが。

そんなTabView君、User's Guideを読むと、Client Side APIが揃っていて、JavaScriptで遊べるっぽいです。

JavaScript、超初心者なのですが…検証の中で使う機会があったのでトライしてみました。

JSFのビューで

  • 無効ボタンを押すと現在アクティブになっているタブ以外を無効にする
  • 有効ボタンを押すと全てのタブを有効にする

というしょぼいサンプルです(^^;

<?xml version='1.0' encoding='UTF-8' ?>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-

transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml"
      xmlns:h="http://java.sun.com/jsf/html"
      xmlns:p="http://primefaces.org/ui">
    <h:head>
        <title>TabViewのClient side APIで遊ぶ</title>
    </h:head>
    <h:body>
        <h:form id="frmTabView">
            <p:commandButton value="タブ無効" onclick="disableTab();"/>
            <p:commandButton value="タブ有効" onclick="allenableTab();"/>
            
            <p:tabView id="tbView" widgetVar="mainTabView" >
                <p:tab id="tb1" title="タブ1"/>
                <p:tab id="tb2" title="タブ2"/>
                <p:tab id="tb3" title="タブ3"/>
            </p:tabView>
           
            <script type="text/javascript">
                //アクティブじゃないタブを無効化
                function disableTab(){
                    var tabNum = mainTabView.getLength();
                    var actIdx = mainTabView.getActiveIndex();
                    
                    for(i = 0; tabNum > i; i++){
                        if(i !== actIdx){
                            mainTabView.disable(i);
                        }
                    }
                }
                
                //全てのタブを有効化
                function allenableTab(){
                    var tabNum = mainTabView.getLength();
                    
                    for(i = 0; tabNum > i; i++){
                        mainTabView.enable(i);
                    }
                }
            </script>
        </h:form>
    </h:body>
</html>

なぜかわからないのですが、for分で「i < tabNum」と書いたらNetBeans君に怒られました(^^;
f:id:kikutaro777:20130419212206j:plain
やばい、理由がわかっていない。

表示すると、こんな感じで

f:id:kikutaro777:20130419211748j:plain

タブは動きます。タブ2を選択して

f:id:kikutaro777:20130419211757j:plain

無効ボタンを押すと

f:id:kikutaro777:20130419211803j:plain

アクティブなタブ以外が無効になった!

有効ボタンを押すと

f:id:kikutaro777:20130419211819j:plain

なんてショボイサンプルだ!

前に書いた「JavaScript内でJSFのEL式が使えることを初めて知りました ~画面表示時にダイアログ表示する挙動を例に~」にもあるように、EL式と組み合わせていけばJSFでも色々できるかなと。

可読性は落ちそうですが(^^;

あー本当にJavaScript力が欲しい…

JavaScript内でJSFのEL式が使えることを初めて知りました ~画面表示時にダイアログ表示する挙動を例に~

Java EEを初めて触るようになって8ヶ月くらい経ちました。
EEはもちろんのこと、Java SEに関してもゼロスタートだったので、日々学習が必要で未だにてんてこ舞いです。
そして最近すっかり.NETの世界を忘れています(-_-;

今は実開発に入ってるので、ゆっくり学習する余裕も既になく、かつ周囲に聞ける人がいない状況は結構辛かったりもしますが、壁にぶつかって一緒に調べたり相談し合えるメンバが一緒なだけ幸いです。

前置きが長くなりましたが…

昨日、とある画面を作っていて

画面表示時にDBのあるフラグをみて、フラグに応じて警告ダイアログを出す

みたいなのがありました。遷移する前に出せよって感じですが、まあその辺の仕様は置いておいて(^^;

Windows Formだとごくごく簡単なことですが、自分のようなWeb開発初心者にとっては「何を使うのがbestなの…」って感じだったりします。

バッキングビーンのPostConstructでFacesContextにDialogのコンポーネントぶっこむ?と考えたり、preRenderViewとか使うのか、とかあれこれ思いつつ、色々とググっていくとJavaScriptにwindow.onLoadなるものがあると知りました。

JavaScriptかぁー、でもフラグはバッキングビーンみないとねぇ…どーすんのよ」

と頭の固い自分達は「うーん」となったわけですが、一緒に調べてた人が「あれー、これできるよ」と以下stackoverflowで見つけてきました。

Mixing JSF EL in a Javascript file

なんというか、みると「あ、できるんだ(^^;」と思うし、よくよく考えれば「そりゃできるわな」って感じなのですが、頭の中が「JSFの世界」「JavaScriptの世界」みたいに何故か分けて考えてしまってたので、気づかなかった感じです。

てか、これできるなら、今まで作った所で、もう少し簡単な実装に変えられる部分もあるなぁ…と気づいて、今後リファクタとか必要になりそうです。

とりあえず、簡易サンプルを書いて検証しました。以下のようなものです。

JSFのビュー(xhtml)
<h:body>
    <script type="text/javascript">
        window.onload = function() {
            if(#{onLoadConfirm.hasOpenError()}){
                dlg.show();
            }
        };
    </script>
    
    <p:confirmDialog id="dlgId" widgetVar="dlg" message="ダイアログですー"/>
</h:body>
バッキングビーン(CDI管理対象Bean)
package jp.co.hoge.primefacessandbox;

import javax.annotation.PostConstruct;
import javax.inject.Named;
import javax.enterprise.context.RequestScoped;

@Named(value = "onLoadConfirm")
@RequestScoped
public class OnLoadConfirm {
    
    private boolean hasOpenError;

    @PostConstruct
    public void init(){
        hasOpenError = true; //false
    }

    //getter,setterは省略
}

フラグ値を直接書いてるアホなサンプルコードですが…(^^;

hasOpenError=falseの場合

f:id:kikutaro777:20130403201302j:plain

ページ表示しても何も表示されません。

hasOpenError=trueの場合

f:id:kikutaro777:20130403201244j:plain

ページ表示するとダイアログが出ます。動いたー!

補足

Twitterで@aoetkさんから「やり過ぎるとソースがカオスになるので注意です」とコメント頂きました。
確かに上記のような簡易サンプルはいいですが、複雑になった場合には、フロントのJavaScriptとバッキングビーンを追いかけるのが大変そうな感じがします(^^;

ということで、そういった辺りは注意しつつ、恩恵を受ける所は上手く使っていきたいと思います。

てか、これまた毎度ですが、有識者の方々的には「当たり前だがなー」って感じなんだろうなぁ、と思いつつ、意外とこういうところで詰まってる自分に力のなさを感じたりします。。Challengeあるのみ(^^;

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