XPagesDay 2014 「SSJSでも使える!Javascriptでオブジェクト指向プログラミング入門」スライド公開
XPagesDay 2014 (2014/11/18) 【A-3】「SSJSでも使える!Javascriptでオブジェクト指向プログラミング入門」で使用したスライドを公開しました。
XPagesリッチテキスト CKEditorツールバーをカスタマイズ
XPages リッチテキスト コントロール
XPagesのリッチテキストコントロールはDomino 8.5.2からCKEditorが採用されるようになりました。
デフォルトでのリッチテキスト コントロールは以下の様なレイアウトになります。
デフォルトでは文字の修飾など基本的なことしか出来ないようになっています。
今回はこのCKEditorをカスタマイズする方法をご紹介します。
toolbarTypeを指定してカスタマイズ
以下の用にDojo属性を追加し、名前を「toolbarType」にし値を指定します。
値には
- Slim
- Medium
- Large
を指定することができます。
それぞれのレイアウト
Javascriptを使ってフルカスタマイズ
dojo属性に「toolbar」を作り、ツールバーの項目をJavascriptの配列で指定することでリッチテキストコントロールのツールバーをフルカスタマイズすることが可能になります。
値の部分にサーバーサイドJavascriptでツールバーの項目を以下のようにセットします。
全てのツールバーの項目を表示させたい場合、
のようになります。
このように、フルカスタマイズすることで、今までになかったHTMLソースコードでの編集等も可能になります。
CKEditor 3.X Developer's Guide も参考にしてください。
XPagesDay 2013 【C-3】予約システムをXPagesで構築した提案事例のスライドとコードの公開
XPagesDay 2013が無事に終わりましたね。
参加された皆様、講師の皆様、そして運営の皆様、本当にお疲れ様でした。
やはり、自分のプレゼンはかなり緊張していたようです。
自宅で行ったリハでは「え~っと」の回数を30回以下まで減らすことができたんですが、本番はゆうに50回は超えていたようです。
お聞き苦しく感じてしまった方すいません、次プレゼンをする機会があればその時はがんばります (^_^;)
XPagesDayでの自分のプレゼンテーションのスライドをアップしました。
リンク先はこちら:http://www.slideshare.net/KazunoriTatsuki/c3-xpages
また、スライドの中で利用したDojo GridViewのXPagesコードを以下に貼り付けておきます。
[toggle title="Dojo GridViewのXPagesコードを表示するにはここをクリック"]
<?xml version="1.0" encoding="UTF-8"?>
<xp:view xmlns:xp="http://www.ibm.com/xsp/core"
xmlns:xe="http://www.ibm.com/xsp/coreex"
xmlns:xc="http://www.ibm.com/xsp/custom"> <xp:div id="div_Schedule_depart"
styleClass="gridbox">
<xe:restService
id="restServiceDepartSche">
<xe:this.service>
<xe:viewJsonService
viewName="[YOUR_VIEW_HERE]" defaultColumns="true"
contentType="application/json" var="entry"
formName="[YOUR_FORM_HERE]">
<xe:this.columns>
<xe:restViewColumn
name="DSResvStat">
<xp:this.value><![CDATA[#{javascript:""; /*予約状況の計算プログラムが入ります*/ }]]></xp:this.value>
</xe:restViewColumn>
</xe:this.columns>
<xe:this.keys><![CDATA[#{javascript:""; /*Viewの絞込のキーワードを返すようにします*/ }]]></xe:this.keys>
</xe:viewJsonService>
</xe:this.service>
</xe:restService>
<xe:djxDataGrid id="djxDataGridDepart"
style="width: 100%;height: auto; padding: 1px"
storeComponentId="restServiceDepartSche" selectionMode="single"
selectable="false" loadingMessage="検索しています" autoHeight="5"
jsId="jsDataGridDepart"> <xe:djxDataGridColumn
id="djxDataGridColumn1" label="ラベル1" field="DSName">
</xe:djxDataGridColumn>
<xe:djxDataGridColumn
id="djxDataGridColumn2" label="ラベル2" field="DSDepartCity"
width="50px">
</xe:djxDataGridColumn>
<xe:djxDataGridColumn
id="djxDataGridColumn3" label="ラベル3" field="DSDepartTimeStr">
</xe:djxDataGridColumn>
<xe:djxDataGridColumn
id="djxDataGridColumn4" label="ラベル4" field="DSArriveCity"
width="50px">
</xe:djxDataGridColumn>
<xe:djxDataGridColumn
id="djxDataGridColumn5" label="ラベル5" field="DSArriveTimeStr"
width="50px">
</xe:djxDataGridColumn>
<xe:djxDataGridColumn
id="djxDataGridColumn11" label="ラベル6" field="DSResvStat" width="auto">
</xe:djxDataGridColumn>
</xe:djxDataGrid>
<xp:scriptBlock id="scriptBlock1">
<xp:this.value><![CDATA[XSP.addOnLoad(function(){
dojo.connect(dijit.byId("#{id:djxDataGridDepart}"), "_onFetchComplete",function()
{
// 画面遷移先から戻ってきた時に以前に選択された値を選択状態にしておくためのCSJS
var selUnid = dojo.byId('#{id:scheDepartDSUnid}');
var grid = dijit.byId("#{id:djxDataGridDepart}");
if( selUnid && selUnid.value != ""){
for (var i = 0; i < grid.rowCount; i++){
theitem = grid.getItem(i);
dojo.forEach(grid.store.getAttributes(theitem), function(attr){
if(attr == '@unid'){
var value = grid.store.getValues(theitem, attr);
if( value == selUnid.value){
grid.selection.setSelected(i,true);
}
}
});
}
}
grid.canSort = function(){return false};
}); });]]></xp:this.value>
</xp:scriptBlock>
</xp:div> <!-- GridViewで選択された行のUNIDを格納する隠しフィールド -->
<xp:inputText id="scheDepartDSUnid" style="display:none;"
value="#{sessionScope.scheDepartDSUnid}">
</xp:inputText>
<!-- 次へ進むボタンを押下時にGridViewで選択された行のUNIDを取得して隠しフィールドに保存 -->
<xp:div styleClass="enter">
<xp:link escape="true" id="link2">
<xp:image id="image15" url="/button-next.gif"
alt="次へ進む">
</xp:image>
<xp:eventHandler event="onclick" submit="true"
immediate="false" save="true">
<xp:this.script><![CDATA[var grid = dijit.byId('#{id:djxDataGridDepart}');
var bSelDept = false;
var bSelDeptOF = false;
var items = grid.selection.getSelected();
if(items.length) {
dojo.forEach(items, function(selectedItem) {
if(selectedItem!==null) {
dojo.forEach(grid.store.getAttributes(selectedItem), function(attribute){
var value = grid.store.getValues(selectedItem, attribute);
// alert('attribute: ' + attribute + ', value: ' + value);
if(attribute == '@unid'){
dojo.byId('#{id:scheDepartDSUnid}').value = value;
bSelDept = true;
}
if(attribute == 'DSResvStat' && value == 'X'){
bSelDeptOF = true;
}
});
}
});
}
]]></xp:this.script>
</xp:eventHandler>
</xp:link>
</xp:div>
</xp:view>
[/toggle]
XPagesのRadio Button Groupから選択された値をクライアントJavascriptで取得する方法
Radio Button Groupを使うと簡単にXPagesでラジオボタンを実装することができます。
サーバーで選択された値を取得するためには、以下のようにデータバインド(Bind)してやることで実装が可能です。
右の画像が今回作るサンプルのXPagesのスクリーンショットになりますが、ラジオボタンを選択してボタンをクリックすると、クライアントJavascriptが現在選択されているラジオボタンの値(value)を返す、というものです。 言いかえると、サーバーを介さない本来のJavascriptでよく行うタイプの使い方を実装してみる、という試みです。
まず、Radio Button GroupをXPagesに以下のように配置しました。
<xp:radioGroup id="radioGroupMember" value="#{sessionScope.SelectedName}"> <xp:selectItem itemLabel="エレン" itemValue="エレン・イエーガー"> </xp:selectItem> <xp:selectItem itemLabel="ミカサ" itemValue="ミカサ・アッカーマン"> </xp:selectItem> <xp:selectItem itemLabel="アルミン" itemValue="アルミン・アルレルト"> </xp:selectItem> </xp:radioGroup>
次に、実際にクライアントJavascriptをトリガーするためのボタンを配置します。コードは以下のようになるとおもいます。
<xp:button value="" id="button1"> </xp:button>
配置がおわったら、ボタンを選択した状態で、「Events」タブの [onclick] にコードを記述していきます。
今回はクライアントJavascriptですので、[client]のタブが選択されているのに気をつけてください。
サンプルのJavascriptは以下のようになります。
var chkRadioMember = dojo.query("input[name$='#{id:radioGroupMember}']"); for(var i=0; i < chkRadioMember.length; i++){ if(chkRadioMember[i].checked){ alert(chkRadioMember[i].value +"であります!"); } } return false;
さて、お膳立てはできましたので、早速このコードの解説に移ります。
このコードの肝はなんといっても一行目です。
まず、dojo.query を使って効果的にラジオボタンのDOMオブジェクトの取得を試みています。
dojo.queryの引数に"input[name$='hogehoge']" とすることで、INPUT要素でname 属性がhogehoge であるDOMオブジェクトを配列で返す、となっています。
なぜ、このような指定の仕方をしているのか?
実際にXPagesが生成するHTMLのソースコードを覗いてみると以下のようになっているのが確認できます。
この緑で囲んだ部分 「view:_id1:radioGroupMember」と全て同じ値となっています。
ですので、INPUT要素でname 属性が「view:_id1:radioGroupMember」となっている全てのDOMオブジェクトを返して欲しいために、このような記述としているのです。
これで、ラジオボタンのDOMオブジェクトを全て取得できましたので、あとはChecked属性が付いている要素を探せばOKです。
クライアントJavascriptでRadioボタンの値を取得する方法の説明は以上になります。
ん、ちょっとまてよ? と思われた方 (ギクッ)
そうなんです、 実は1行目のサンプルコードは
var chkRadioMember = dojo.query("input[name$='#{id:radioGroupMember}']");
であって
var chkRadioMember = dojo.query("input[name$='view:_id1:radioGroupMember']");
ではないのです。
この#{id:radioGroupMember} という値はどこから来たのか?
実はこの#{id:hogehoge}というフォーマットで記述されたコードはHTMLがブラウザに表示される前にサーバー側で 'view:_id1:radioGroupMember' といった値に動的に変換されることになっています。
今、「はぁ~?」 と思われた方、実際に言っちゃった方、・・・いや、お気持ちはよく分かります。 (ちょっといきなりのブログで難易度高いの選んでしまったとここで後悔)
この部分、次回のブログで詳しく説明していきたいと思います。
今回の例では、上記で作ったRadio Button GroupのコントロールIDを使って#{id:radioGroupMember} と指定している、となっています。
<xp:radioGroup id="radioGroupMember" ← このID
ちょっと腑に落ちない終わり方になってしまいましたが、是非次回をお楽しみに(苦笑)
<<こちらに追加の記事を書きました>>
最後に今回使用したXPagesのソースコードを全て貼り付けておきます。
[toggle title="XPagesの全てのソースコードを表示するにはここをクリック"]
<?xml version="1.0" encoding="UTF-8"?>
<xp:view xmlns:xp="http://www.ibm.com/xsp/core">
<xp:radioGroup id="radioGroupMember"
value="#{sessionScope.SelectedName}">
<xp:selectItem itemLabel="エレン" itemValue="エレン・イエーガー">
</xp:selectItem>
<xp:selectItem itemLabel="ミカサ" itemValue="ミカサ・アッカーマン">
</xp:selectItem>
<xp:selectItem itemLabel="アルミン" itemValue="アルミン・アルレルト">
</xp:selectItem>
</xp:radioGroup>
<xp:button value="誰だ、貴様は?!" id="button1">
<xp:eventHandler event="onclick" submit="false">
<xp:this.script><![CDATA[var chkRadioMember = dojo.query("input[name$='#{id:radioGroupMember}']");
for(var i=0; i < chkRadioMember.length; i++){
if(chkRadioMember[i].checked){
alert(chkRadioMember[i].value +"であります!");
}
}
return false;
]]></xp:this.script>
</xp:eventHandler>
</xp:button>
</xp:view>
[/toggle]