More Related Content
Similar to JavaScriptおよびXPages Vote技術解説
Similar to JavaScriptおよびXPages Vote技術解説 (20)
JavaScriptおよびXPages Vote技術解説
- 2. 自己紹介
海老原 賢次
– リコーITソリューションズ株式会社 鹿児島開発部
– システム開発 主にWeb系
– 得意なもの
• Domino, XPages, C#, ASP.NET, JavaScript, HTML, CSS, jQuery・・・
– 不得意なもの
• Dojo(w)
– 嫌いなもの
• 冷やしトマト
2014/9/4 2
- 4. 本日の内容
高度な JavaScript 解説
– 私のブログ“Xpagesで行こう”で紹介している内容からピックアップして、詳しく解説します。
• JavaScriptの禁忌技
• オブジェクトリテラル
• コードの再利用(オブジェクト指向言語としての側面とその利用)
• コードの再利用(関数型言語としての側面とその利用)
海老原が作ったXpagesアプリの中を見てみよう
– お恥ずかしながら、実際のXPagesアプリの中をお見せして解説します!
2014/9/4 4
- 8. 準備
2014/9/4 8
var output = [];
//--ここから--------------
//--ここまで--------------
$.each(output, function(i,o){
var p=$('<p></p>');
p.text(o);
$('#output').append(p);
});
- 9. 禁忌技その1-変数はvarで必ず宣言する
varで変数宣言した場合と、しない場合では、振る舞いが異なります。
2014/9/4 9
var val1 = "hoge1";
function func1(){
var val1 = "hoge1-1";
val2 = "hoge2-1";
output.push("val1 - 1: " + val1);
output.push("val2 - 1: " + val2);
}
func1();
output.push("val1: " + val1);
output.push("val2: " + val2);
Run it!
val1 - 1: hoge1-1
val2 - 1: hoge2-1
val1: hoge1
val2: hoge2-1
Result
var で変数宣言していない場合、グローバル変数として扱われます。
- 10. 禁忌技その2 –等価比較演算子に”==“は使わない
等価比較演算子には、2種類あります。”==“と”===“です。
”==“は左右の項目の型が違う場合、右辺の型を左辺の型に自動変換しま
す。
“===“は左右の項目の型が違う場合、falseを返します。
2014/9/4 10
var val1 = 1;
var val2 = "1";
output.push(val1 == val2);
output.push(val1 === val2);
Run it!
true
false
Result
“==“とした場合、それが型変換を意図したものなのかそうでないのかがわかり
づらいので、”===“を使用するのをおすすめします。
否定も同様に”!=“ではなく”!==“を使用します。
- 11. 禁忌技その3 -型変換で気をつけたい事
parseInt()関数の罠
– parseInt(“07”) -> 7
– parseInt(“08”) -> 0
• ※IE8以下のバージョン。Firefox,IE9以上,Chromeでは “08” -> 8 となります。
parseIntは文字列を数値に変換しますが、0で始まる文字列は8進数と判
断してしまいます。
第2引数でn進数を指定できますが、よく忘れます。
文字 -> 数値の変換は [Number]を使用します
– Number(“07”) -> 7
– Number(“08”) -> 8
2014/9/4 11
- 12. 型変換について
文字 -> 数値
– Number(“08”)
– +“08”
数値 -> 文字
– String(8)
– 8 + “”
など
ブログでまとめています。参考にしてください。
– http://goo.gl/ApOjkj
2014/9/4 12
- 15. コンストラクタ関数
クラスがないJavaScriptでも、new を使ったオブジェクト化の仕組みが有りま
す。これがコンストラクタ関数です。
2014/9/4 15
var ProtoUser = function(){
this.f_name = "gonbe";
this.l_name = "nanashi";
this.title = "san";
this.getFullName = function(){
return this.f_name + ' ' +
this.l_name + ' ' +
this.title;
};
};
var user = new ProtoUser();
user.f_name = 'ichiro';
user.l_name = 'suzuki';
output.push(user.getFullName());
Run it!
ichiro suzuki san
Result
- 18. プロトタイプの実例
2014/9/4 18
var ProtoUser = function(){
this.f_name = 'gonbe';
this.l_name = 'nanashi';
this.title = 'san';
this.getFullName = function(){
return this.f_name + ' ' +
this.l_name + ' ' +
this.title;
};
};
var ProtoStaff = function(){
this.dep = 'kagosima';
this.getNameAndDepartment = function(title){
return this.getFullName(title) + ' @' +
this.dep;
};
};
ProtoStaff.prototype = new ProtoUser();
var ebihara = new ProtoStaff();
ebihara.f_name = 'kenji';
ebihara.l_name = 'ebihara';
output.push(ebihara.getFullName('san'));
output.push(ebihara.getNameAndDepartment('san'));
Run it!
kenji ebihara san
kenji ebihara san kagosima
Result
- 19. オブジェクトの関係
2014/9/4 19
ProtoUser
f_name=‘gonbe’
l_name=‘nanashi’
title = ‘san’
getFullName()
ProtoStaff()
Prototype
ebihara
f_name = ‘kenji’
l_name = ‘ebihara’
dep = ‘kagosima’
getNameAndDepartment()
(__prototype__)
ebiharaは、プロトタイプとしてProtoStaffのオブジェクトを持ちます。
ebihara.getFullName() と呼び出すことができますが、ebiharaオブジェクトには持っていません。プロトタイプ・チェーンに
よってProtoUserのgetFullName()がコールされます。
newでのオブジェクト生成引き継ぐ
- 20. プロトタイプチェーン
2014/9/4 20
ProtoUser
title = ‘san’
(__prototype__)
ebihara
f_name = ‘kenji’
l_name = ‘ebihara’
dep = ‘kagosima’
getNameAndDepartment()
(__prototype__)
もし、プロトタイプのオブジェクトがプロトタイプを持っている場合、
Ebihara.getFullName()
とした場合、JavaScriptエンジンは、ebiharaにそのメソッドがないので、ProtoUserを探しに行きます。
そこにもない場合は、さらに上のParentProtoUser を探しに行きます。
仮にProtoUserに getFullName() がある場合は、それが採用され、ParentProtoUserの同名のメソッドは無視されま
す。
ParentProtoUser
f_name=‘gonbe’
l_name=‘nanashi’
getFullName()
- 22. メソッド拝借
2014/9/4 22
var obj1 = {
a: 1,
func1: function(){
return this.a + 1;
}
};
var obj2 = {
a: 2,
func2: obj1.func1
};
output.push(obj1.func1());
output.push(obj2.func2());
Run it!
2
3
Result
obj2ではobj1のfunc1をfunc2として参照しています。
func1のの中の”this”は、obj1を示しているのではなく、実行し
たオブジェクトとなります。
つまり、func1はobj1に依存しない、ということがわかります。
- 23. 関数の共通化
2014/9/4 23
var func = function(){
return this.a + 1;
};
var obj1 = {
a: 1,
func1: func
};
var obj2 = {
a: 2,
func2: func
};
output.push(obj1.func1());
output.push(obj2.func2());
Run it!
2
3
Result
このように、外部で関数を変数に置き、オブジェクトでそれらを参
照することができます。
- 25. コールバック関数の例
2014/9/4 25
var each = function(arr,func){
for(var i = 0,max = arr.length; i<
max; i++){
func(i, arr[i]);
}
};
var array = ["a","b","c","d"];
each(array, function(i, item){
output.push(item + i);
});
each(array, function(i, item){
output.push(i + item);
});
Run it!
a0
b1
c2
d3
0a
1b
2c
3d
Result
- 26. each関数の仕様
動作概要
– 引数に指定した配列をループする。その際に配列内の値ごとに引数に指定された関数を実施する。
引数
– 第1引数に配列を指定する
– 第2引数に関数を指定する。この関数は第1引数にインデックスとなる数値、第2引数に配列内の値が渡
されることを想定すること。
メリット
– JavaScriptの for ステートメントは使いかたを注意する必要がある。
– この関数を使用することで、一定の for の使いかたを強制できる。また、タイプする量が少ない。
• 配列をループして順次処理するばあい、for-inは使用しないほうが良い。→ http://goo.gl/g9krt
• また、for(var i=0; i < arr.length; i++) とするとパフォーマンスに影響する
2014/9/4 26
- 28. クロージャ実践
2014/9/4 28
var createCounter = function(){
var count = 0;
var obj = {
countUp: function(){
return ++count;
},
getCurrent: function(){
return count;
}
};
return obj;
};
var counter = createCounter();
output.push(counter.getCurrent());
output.push(counter.countUp());
output.push(counter.getCurrent());
var counter2 = createCounter();
output.push(counter2.getCurrent());
output.push(counter2.countUp());
output.push(counter2.getCurrent());
Run it!
0
1
1
0
1
1
Result
- 31. アンケートWebアプリの仕様
複数の選択肢を持った質問を作成できます。
選択肢は択一です。
すべてのユーザーは質問の一覧を見ることができます。
回答者は質問毎に1つだけ回答を投票できます。(複数の回答は不可)
回答者は回答を修正することができます。
すべてのユーザーは回答の集計結果を見ることができます。
集計結果は、棒ブラフと円グラフで表示されます。
集計結果は、リアルタイムで表示されます。(画面のリフレッシュは手動)
質問を修正することができます。
2014/9/4 31
- 32. アンケートWebアプリ 今後搭載予定の機能
一覧で、投票数が表示されます。
質問を投稿した人しか編集できません。
回答の開始日-終了日を指定できます。
選択肢の選択を択一か複数可かを指定できるようにします。
質問画面のURLを他のDominoユーザーにメールで送る事ができます。
回答者を指定したユーザーのみに制限できます。
one uiとは別にbootstrap版を用意して、レスポンシブデザインとして、モバイ
ル端末でも表示できるようにします。
2014/9/4 32
- 37. ファイル構成
コードビハインド モデル
– 1つのXPagesに対して、1つのSSJS,CSJSが存在する(CSJSは必要な場合の
み)
– 対になるSSJS,CSJSの名前は、XPagesの名前に“_JSS”,“_JS”のサフィックス
をつける。
– XPagesの各イベントの処理は、SSJSに書くこととし、XPages内ではSSJSの関
数を呼び出すだけとする。
– 各SSJSでは、先頭でXPages名と同じ名前のオブジェクトを作成し、その中にメ
ソッドなどを記載することで、名前の衝突を避ける。
• JavaScriptにおける名前空間パターン→ http://goo.gl/9mLFUu
2014/9/4 37
- 42. 選択肢はJSONデータで保持
Notes文書の欠点として、複数データを持ちづらいことがあげられます。
テキストや数値の複数値は保持できるが、いくつかの値をセットとしたオブジェク
トのようなものをリストとして保持する機能はありません。
そこで、そのような値をJSONとしてテキストで保持しています。
2014/9/4 42
Choicesフィールドに、テキストでJSONデータを保持している。
オブジェクトは、id, sortkey(並び順), name(表示値) のプロパティを持っており、それを配列としている。
値の例:
[{"id":"e10974c4-2bbc-4f85-9d3f-43bcdf6ce784","sortkey":1,"name":"IE"},
{"id":"f73d3e6e-1413-1f30-60c5-b76139086a87","sortkey":2,"name":"Chrome"},
{"id":"555ac5c9-7143-85df-6c34-c42c0a4cc9a1","sortkey":3,"name":"FireFox"},
{"id":"f8d0f5c8-1773-c48a-dcdf-a219e7e5b881","sortkey":4,"name":"Safari"},
{"id":"efc1b927-a347-4d47-08df-fe9a55d12b86","sortkey":5,"name":"Other"}]
- 44. 回答・結果画面での選択肢の表示
回答・結果画面では動的に変わることがないので、サーバー側でオブジェクト化
して、それを Repeat コントロールのデータソースとして渡して描画しています。
2014/9/4 44
<ul id="ChoicesList">
<xp:repeat id=“Coices” rows=“99" disableOutputTag="true"
value="#{javascript:return fromJson(TargetDoc.getItemValueString('Choices'));}"
var="item">
<xp:panel tagName="li">
<label>
<input type="radio" name="checked”value="#{item.id}"
checked="#{javascript:
Vote.voteDocument.getItemValueString('ChoiceId') === item.id
? 'checked' : '';
}" />
<xp:text escape="true" value="#{item.name}"></xp:text>
</label>
</xp:panel>
</xp:repeat>
</ul>
- 47. 結果画面-グラフの表示
グラフの表示には、オープンソースの jQuery Visualize を利用しています。
これは、HTMLのテーブルをデータソースとしてグラフを表示します。
そのため、棒グラフで使用したオブジェクトでテーブルを作成し、非表示としてい
ます。
グラフを表示するコードは下記だけで実現できます。
2014/9/4 47
$(function(){
$('.resultTable').visualize({type: 'pie', height: '300px', width: '420px'});
});