2013年12月19日木曜日

全角英数は半角英数に、半角カナは全角カナに変換する

九州のパートナー会で作成しているQAアプリで必要になったので調査しました。

要件としては「入力された半角・全角をどちらかに統一したい」ということ。

英数は半角で、カナは全角で統一するのがすっきしますよね。

ということで調べてみました。

ICU4JというJavaライブラリがあるんですね。これを使えば簡単そうです。

この例の他にも、変換の方法が色いろあるようです。ちょっと調べてみよう。

 

準備

  1. ICUのサイトからICU4Jをダウンロードする。http://site.icu-project.org/download
  2. ZIPファイルを展開し、icu4j-52_1.jar を取り出す。
  3. Designerのパッケージエクスプローラの「WebContent > WEB-INF > lib」に「icu4j-52_1.jar」をコピーする。

使い方

全角英数は半角英数に、半角カナは全角カナに変換するには、下記のStaticメソッドを呼ぶ

com.ibm.icu.text.Normalizer.normalize("変換する文字", com.ibm.icu.text.Normalizer.NFKC);

 

例: XPagesを作って下記をコピペしたら動きます。

 

<?xml version="1.0" encoding="UTF-8"?>
<xp:view xmlns:xp="http://www.ibm.com/xsp/core">
    <p>
        <xp:inputText id="input" style="width: 30em"
            defaultValue="#{'ABCDEFG12345アイウエオABC123アイウエオガギグゲゴ'}">
        </xp:inputText>
        <xp:button id="change" value="変換">
            <xp:eventHandler event="onclick" submit="true"
                refreshMode="partial" refreshId="trans">
                <xp:this.action><![CDATA[#{javascript:var input:com.ibm.xsp.component.xp.XspInputText = getComponent("input");
var sourceString = input.getValueAsString();
var transString = com.ibm.icu.text.Normalizer.normalize(sourceString,
com.ibm.icu.text.Normalizer.NFKC);
var trans:com.ibm.xsp.component.xp.XspOutputText = getComponent("trans");
trans.setValue(transString);
}]]></xp:this.action>
            </xp:eventHandler></xp:button>
    </p>
    <p>
        <xp:text id="trans"></xp:text>
    </p>
</xp:view>

2013年12月11日水曜日

連載:ちょっとディープなXPages 第2-9回~JavaScriptをもっと知ろう

みなさん!XPages開発していますか!?
今回から数回に分けてオブジェクトの継承について話したいと思います。
前回、prototypeの説明をしましたが、それも1つの継承です。しかし、JavaScriptではオブジェクトのすべてを、コンストラクタ関数を使用して作成することは多くありません。
もっと手軽に継承する方法が幾つかあります。

ミックスイン

ミックスインとは2つ以上のオブジェクトのすべてのメンバーを持つ1つのオブジェクトに統合することです。多重継承に近い概念でしょうか。
JavaScriptでの用途としては、ある関数の引数にオブジェクトを渡すこととして、そのオブジェクには設定しなくてもよいメンバーがあるとします。
設定されなかったメンバーは関数内でのデフォルト値が設定されることつぃます。
下記の例では、ユーザー登録関数に姓名と年齢、性別を持つオブジェクトを渡すことを想定しています。年齢と性別は渡さなくても良いですが、その場合は、デフォルト値として"-1"と"N"が設定されるようにします。
ミックスインを使用しない場合は、ifで個々を判断する必要があります。
    //ミックスインを使用しない場合
    var addUser = function(obj){
        //本来であれば姓名の必須チェックが必要
        if(!!obj.age){
            obj.age = -1;
        }
        if(!!obj.gender){
            obj.gender = 'N';
        }
    }
    //利用側
    addUser({name: 'Kenji Ebihara'});
    
この例では2つのプロパティだけなので、それほど大変ではありませんが、メンバーの数が増えてくると大変なのは想像できると思います。
そこで、ミックスインを使用します。
    //ミックスインを使用する場合
    //引数のデフォルトのメンバーを作成
    var addUserDefaultArg = {
        age : -1,
        gender : 'N'
    }
    var addUser = function(obj){
        //本来であれば姓名の必須チェックが必要
        var arg = mixin(addUserDefaultArg, obj);
        print(arg.age);
        print(arg.gender);
    }
    //ミックスイン関数
    var mixin = function(base, child){
        var newObj = {}, member;
        //デフォルトのオブジェクトのメンバーをコピー
        for(member in base){
            newObj[member] = base[member];
        }
        //継承するオブジェクトからメンバーをコピー
        //デフォルトと同じメンバーがあったら上書きされる
        for(member in child){
            if(!!child[member]){ // nullやundefindの場合は引き継がない
                newObj[member] = child[member];
            }
        }
        return newObj;
    }
    //利用側
    addUser({name: 'Kenji Ebihara'}); // -1, 'N'が出力される
    
mixin関数は、for-inを利用してオブジェクトのメンバーをすべてコピーし、そのあとで継承するオブジェクトのメンバーをコピーすることで、継承するオブジェクトに含まれないかnull,undefindのものは継承元のオブジェクトのものが採用されます。

次回は

継承とは少し違いますが、他のオブジェクトのメソッドを利用する、「メソッド拝借」について解説します。
海老原 賢次(EBIHARA Kenji)
リコーITソリューションズ株式会社(RICOH IT SOLUTIONS CO.,LTD.)
鹿児島ソリューション部(Kagoshima Department)

2013年11月18日月曜日

連載:ちょっとディープなXPages 第2-8回~JavaScriptをもっと知ろう

青太字文字部分、加筆しました。

みなさん!XPages開発していますか!?

前回はコンストラクタ関数について説明しましたが、前回の方法ではnewを呼び出す度にfunctionが生成されるので、非効率です。

var User = function(name){
    this.name = name; //プロパティ
    //下記のfunctionがnewが呼び出される度に生成されるの非効率
    this.sayHello = function(){
        return this.name + 'さん、こんにちは!';
    } //メソッド
}

prototype

この問題を解決するにはprototypeを使用するのが簡単な解決方法です。

var User = function(name){
    if(!!name){
        this.name = name;
    }
}
User.prototype = {
    name : '', //プロパティ
    sayHello : function(){
        return this.name + 'さん、こんにちは!';
    } //メソッド
}
//オブジェクト作成
var kenji = new User('Kenji');
print(kenji.name); // 'Kenji'
print(kenji.sayHello()); // Kenjiさん、こんにちは!

prototypeはすべてのfunctionオブジェクトに存在する特殊なメンバーで、通常は上記のようにオブジェクトを保持します。

上記のように、Userコンストラクタ関数ではsyaHelloメソッドはないにもかかわらず、呼び出せています。

それは、「オブジェクトに存在しないメンバを呼ばれたときは、自身のprototypeオブジェクトを参照し、そこにあればそれを呼び出す」というjavascript特有の言語仕様があるためです。

さらに、prototypeオブジェクトは new で作成されたオブジェクトに関係なく1つのオブジェクトなため、new でオブジェクトをいくつ作成しても、参照される sayHello はメモリ的にも同じものとなり、効率的です。

また、上記の例では new の引数に null または undefinde 以外が渡された場合は、name プロパティがセットされます。この場合は、kenji にはnameプロパティが存在するので、prototypeのnameは採用されず、Userのコンストラクタ関数で割り当てられたkenji の name プロパティが採用されます。

prototypeチェーン

さて、prototypeはオブジェクトですが、このオブジェクトにprototypeが定義されている場合は、どのような動作になるでしょうか?下記の例を見てみます。

var p1 = function(){
}
p1.prototype = {
    name : '1st!'
}
var p2 = function(){
}
p2.prototype = (function(){
    var obj = new p1();
    obj.old = 20;
    return obj;
})();
var c3 = new p2();

//c3は、name と old にアクセスできる
print(c3.name); // '1st!'
print(c3.old); // 20
    

c3 は p2 コンストラクタ関数から生成されます。p2 コンストラクタ関数のprototype は p1 コンストラクタ関数から生成したオブジェクトにメンバーを追加したものになります。p1 コンストラクタ関数の prototype は name プロパティを持ちます。

そうした場合、c3は p2 の prototype にも p1の prototype にもアクセスされます。

イメージ

これを利用して、クラスの継承的な実装が可能になりますが、これに関してはもう少し整理して別の機会に説明したいと思います。

海老原 賢次(EBIHARA Kenji)

リコーITソリューションズ株式会社(RICOH IT SOLUTIONS CO.,LTD.)

鹿児島ソリューション部(Kagoshima Department)

 

2013年11月10日日曜日

連載:ちょっとディープなXPages 第2-7回~JavaScriptをもっと知ろう

みなさん!XPages開発していますか!?

今回は、JavaScriptのコンストラクタ関数と強制newパターンを説明しましょう。

コンストラクタ関数

JavaScriptには、Javaなどのクラスの概念はありません。でもnewでオブジェクトを作成したり、ArrayだとかDateだとかはクラスの概念で語られることが多いですよね。それらは正確にはクラスではなくコンストラクタ関数と呼ばれるものです。

コンストラクタ関数は、ArrayやDateなどビルドインのものもありますが、自作することもできます。その記述は下記のように行います。

var User = function(name){
    this.name = name; //プロパティ
    this.sayHello = function(){
        return this.name + 'さん、こんにちは!';
    } //メソッド
}

//オブジェクト作成
var kenji = new User('Kenji');
print(kenji.name); // 'Kenji'
print(kenji.sayHello()); // Kenjiさん、こんにちは!

コンストラクタ関数の内部では、thisは新しいオブジェクトであり、それにプロパティやメソッド(関数)を追加していくように記述します。

お気づきかと思いますが、通常のメソッドと同じ記述ですよね。そのとおりで定義にコンストラクタ関数である特別な記述はありません。呼び出し方で、その関数が通常の関数として動作するかコンストラクタ関数として動作するかが決まります。

newをつけて関数を呼び出したときは、内部では下記にような動作をします。

  • 新しい空のオブジェクトをthisして定義する
  • 関数の最後にthisを関数の戻り値とする

newを使わない場合、下記と同等となります。

var User = function(name){
    var newObject = {};
    newObject.name = name; //プロパティ
    newObject.sayHello = function(){
        return this.name + 'さん、こんにちは!';
    } //メソッド
    return newObject;
}

//オブジェクト作成
var kenji = User('Kenji');
print(kenji.name); // 'Kenji'
print(kenji.sayHello()); // Kenjiさん、こんにちは!

強制newコンストラクタ関数パターン

コンストラクタ関数である特別な記述がないということは、newを付けなくても呼び出せてしまいます。その場合、thisは呼び出し元でのthisとなってしまいますので、意図しない動作になってしまいます。

そこで、コンストラクタ関数では初めにthisが自信のコンストラクタ関数で生成されたものかを確認すことで、より安全に呼び出すことができます。

var User = function(name){
    if(!(this instanceof User)){
        return new User(name);
    }
    this.name = name; //プロパティ
    this.sayHello = function(){
        return this.name + 'さん、こんにちは!';
    } //メソッド
}

//オブジェクト作成
var kenji = new User('Kenji');
print(kenji.name); // 'Kenji'
print(kenji.sayHello()); // Kenjiさん、こんにちは!
var aiko = User('Aiko');
print(kenji.name); // 'Aiko'
print(kenji.sayHello()); // Aikoさん、こんにちは!

コンストラクタ関数の更なる改善

上記で紹介したコンストラクタ関数ではその中で定義している関数(例でのsayHello)は、newで呼び出されるたびに生成されています。これは、内容が変わらない静的なメソッドなので、これでは非効率です。prototypeを利用することで、効率的な実装できます。

また、ここでのnameやsayHelloはパブリックなメンバーになりますが、プライベートなものを作るには、クロージャを利用することで実現できます

これらについても、今後解説していきます。

海老原 賢次(EBIHARA Kenji)

リコーITソリューションズ株式会社(RICOH IT SOLUTIONS CO.,LTD.)

鹿児島ソリューション部(Kagoshima Department)

 

2013年11月7日木曜日

XPagesDay 2013 B-3 XPages開発を始める Notes技術者のためのWeb技術概論

*スライドを更新しました。 また  nsf ファイルも合わせて置き場所を変更しました。*

みなさん!XPages開発していますか!?

このエントリーは、2013年11月6日~8日に渡って行われた「XPagesDay2013」で、私がセッションのスピーカーとして担当する「【B-3】XPages開発を始める Notes技術者のためのWeb技術概論」の補足資料および質問受付のためのものです。

私のセッションをご視聴いただけた方はもちろん、そうでない方も資料をみて質問・疑問等あれば、このエントリーのコメントに投稿して下さい。

出来る限りの範囲でお応えしていきたいと思います。

スライド

資料

おすすめリンク

2013年10月30日水曜日

連載:ちょっとディープなXPages 第2-6回~JavaScriptをもっと知ろう

みなさん!XPages開発していますか!?

今回から、JavaScriptでよく使用されるパターンについてご紹介したいと思います。

その前に、

なぜパターンが必要か?

パターンとは、ソフトウェア開発においてよくある問題に対しての、定型的な解決方法のことです。テンプレートといってもいいでしょうね。

なぜ必要なのかは、私が今更述べなくてもいいでしょうけど、一応おさらい。

簡単に再利用できる

多くの人に使用されていて実績がある

未然にトラブルを防ぐ

などの効能があるので、多くのパターンを習得して使いこなせるといいですね。

名前空間パターン

名前空間とは、名前の集合をグルーピング化する考え方のことです。ネームスペースといったほうがわかりやすいかもですね。

JavaScriptでは、関数名やオブジェクト名が衝突しても後のものが上書きされるだけで、コンパイル時にも実行時にもエラーにならず、バグが見つけにくいものの1つです。

XPagesで、SSJSなどで関数を下記のような書き方をする場合が多いと思いますが、他のスクリプトライブラリで同じ関数名を使ってしまっていても、やはりエラーにならず上書きされるだけです。

function methodName(){
}

名前が衝突しないように、プレフィクスなどを付けることもあるかと思いますが、それでは関数名が長くなって使いづらいですよね。

そこで名前空間パターンです。

名前空間の宣言

名前空間の宣言は、下記のようにします。

var myNameSpace = {}; //名前空間の宣言
myNameSpace.methodName = function(){
}
    

オブジェクト・リテラルの書き方と変わりません。空のオブジェクトを生成しているだけです。

もともとJavaScriptには名前空間の概念はなく、当然そのようなステートメントはありません。JavaScriptの持つオブジェクトの柔軟性を利用しています。

JavaScriptでは、既に存在するオブジェクトにメンバーを追加できる仕様となっています。このパターンでは、空のオブジェクトにメソッドを追加指定だけなんですね。で、この空のオブジェクトを名前空間と見立てているだけです。

入れ子の名前空間

さて、名前空間の中にさらに名前空間は作れるでしょうか?

先程も述べたとおり、既に存在するオブジェクトにメンバーを追加できるわけですから、オブジェクトのメンバとしてオブジェクトを入れることができます。

これを利用すれば入れ子もできます。

var myNameSpace = {}; //名前空間の宣言
myNameSpace.subNameSpace = {}; // 入れ子の名前空間の宣言
myNameSpace.subNameSpace.methodName = function(){
}
    

簡単ですね。

1つ注意があるとすれば、varを付けるのは初めだけということです。この例では変数の宣言は"myNameSpace"だけで、あとはそれにメンバーを追加しているだけですから。

追加できるメンバーはメソッドだけではないですから、文字列や数値を定数として定義することも、もちろんできます。

XPagesでの活用は?

ちなみに、私はXPagesのサーバーサイド・JavaScriptでは、スクリプトライブラリのSSJSの先頭で、ファイル名と同じ名前空間を宣言するようにし、メソッドなどをその名前空間に入れるようにしています。

メソッド名の重複を気にしなくなるので非常に便利です。みなさん試してみて下さい。

海老原 賢次(EBIHARA Kenji)

リコーITソリューションズ株式会社(RICOH IT SOLUTIONS CO.,LTD.)

鹿児島ソリューション部(Kagoshima Department)

連載:ちょっとディープなXPages 第2-5回~JavaScriptをもっと知ろう

みなさん!XPages開発していますか!?
JavaScriptでよく使用されるパターンについてご紹介したいと思いますが、その前にパターンでもよく使用されるオブジェクト・リテラルについて説明したいと思います。

オブジェクト・リテラル

リテラルとはソースコード中に直接記載される定数のことです。
数値・文字列のリテラルは下記のようになります。これは通常良く使われますよね。
var name = 'abcd'; //文字リテラル
var count = 0; //数値リテラル
    
オブジェクト・リテラルは、下記のような記述になります。
//{}で囲むとオブジェクト・リテラル
// メンバー名 : 値 でプロパティ
// メンバー名 : function(){} でメソッド
var obj = {
    name: 'hoge', //プロパティ
    getName: function(keisho){
        return this.name + ' ' + keisho;
    }
}
print(obj.name); // "hoge"
print(obj.getName('さん')); // "hoge さん"
    
メソッドは名前なし関数を定義することで実装することができます。またその内部で自分自身を表すのに this を用いることができます。
これで作成されたオブジェクトは他のオブジェクトと何ら変わらず扱えるため、当然プロパティ値を変更したり、メンバーを追加したりすることもできます。
var obj = {
    name: 'hoge', //プロパティ
    getName: function(keisho){
        return this.name + ' ' + keisho;
    }
}
obj.name = 'geho'; //プロパティ値の変更
obj.lastName = 'foo'; //プロパティの追加
    
リテラルは定数なのに変更できるのはどういうこと?と思われる方がいるかもしれませんが、それを理解するにはメモリのヒープ領域のポインタが…みたいな話になるのでここでは割愛します。(^^ゞ
これの利点としては、関連するいくつかのリテラルや、クラスでいうところの static な変数や関数をまとめておくことができることが挙げられます。
また、関数で多くの引数が必要になる場合、使用者側はその順番を把握しなくてはならず、また省略できる項目が中にあった場合、nullなのか空文字なのかわかっておく必要があり、不便です。また拡張する場合は、引数の最後に付け足していくほかありません。
そこで、引数をオブジェクトととし、関数を使用する側はオブジェクト・リテラルを使用して渡すことで、非常にわかりやすくなり、拡張しやすくもなります。
//bad pattern
var addUser = function(name, lastName, age, corporation, department){
}
//Good Pattern
var addUser = function(user){
    user.name; //などとして引数にアクセス
    var department = user.department || 'なし'; //departmentがない場合のデフォルト値
}
//使用者側
addUser({
    lastName: 'ebihara', //順番を意識しなくても良い
    name: 'kenji',
    age: '39',
    corporation: 'RITS'
    //department: 'kagoshima //省略できる項目は入れない事もできる。(関数側で配慮が必要)
});
    
Javaなど他のオブジェクト指向言語では、オブジェクトを作成するにはクラスが必要なのに、この場合のクラスは何?と思う人もいると思います。
実はJavaScriptにはクラスと言う概念はありません。存在するのは、オブジェクトと関数のみです。
しかし関数にはクラスのように扱える、コンストラクタ関数というものもあります。
これについては次回以降に説明したいと思います。
海老原 賢次(EBIHARA Kenji)
リコーITソリューションズ株式会社(RICOH IT SOLUTIONS CO.,LTD.)
鹿児島ソリューション部(Kagoshima Department)

連載:ちょっとディープなXPages コラム2

みなさん!XPages開発していますか!?
前の投稿から、だいぶ時間が立ってしまって申し訳ありません!
ちょっとハードな仕事にハマってしまっていました・・・
今回はコラムということで、お伝えしていこうと思います。
というのも今回の内容は、2013年11月6~8日に開催される、XPages Dayでもちょっと触れる部分で、この記事をその資料としてもご提供しようという腹づもりです。

DBへのjQueryのインポート方法について

jQueryについて

jQueryは、JavaScriptライブラリの中でもデファクト・スタンダードと言ってもいいくらい、普及しているもので、非常に少ないコード量で多くのことを実行できるのが特徴です。
ご存じない方は、下記のサイトなどが参考になると思います。
jquery.com(公式サイト)
私も使い始めて、めちゃめちゃJavaScriptのコーディング時間が減りました!ほんとにもう手放せないです。(個人の感想です)
XPagesではJavaScriptライブラリとしてDojoが採用されていますが、正直なところjQueryの方が扱いやすいですし、何よりjQueryの方が普及率が格段に高いので、情報量やプラグインの数も多いのが決定的です。
そんなjQueryをXPagesで最大限に活用して楽しましょう!

jQueryのDBへのインポート

jQueryも(当然なのですが)JavaScriptで書かれているので、スクリプトライブラリに入れればいい・・・はずなのですが、何故か構文エラーになってしまいます。
そこで、少々面倒ですが下記の手順でインポートします。
※サーバーに置いて読み込ませることもできますが、実際にはそれが出来る環境は限られますからねぇ。
  1. 公式サイトからファイルをダウンロードします。

    * ver 2.x系は、IE6,7,8をサポートしていないので注意!
  2. Domino DesignerのDBで「パッケージ・エクスプローラ」を開きます。 * そのウィンドウがない場合は、メニューの「ウィンドウ」→「Eclipseビュー」→「パッケージ・エクスプローラ」から選択します。
    イメージ
  3. パッケージエクスプローラーの「WebContent」フォルダに「js」というフォルダを新しく作り、ダウンロードした .js ファイルをドラッグ&ドロップします。
    フォルダの追加は、「WebContent」フォルダの上で右クリック→「新規」→「その他」→「一般」→「フォルダー」でできます。
    イメージ
  4. 次に使用したいXPagesでリソースを指定します。この時、プロパティウィンドウの「すべてのプロパティ」→「resources」に追加します。
    [+]を押すとリソースのタイプを聞いてくるので"JavaScript"を選択します。
  5. 「clientSide」に"true"、「src」に"./js/jquery-1.10.2.min.js"(ファイル名はダウンロードしたファイルのファイル名です)と入れます。
    イメージ
これで、jQueryがブラウザでロードされるはずです。
すべての画面で使用したいのであれば、カスタムコントロールのリソースとして追加したり、Themeを利用するのも手ですね。

jQueryの使い方については…

後ほど解説していきたいと思いますが、Webで検索すると日本語の記事も多くあるので、探してみて下さいね。
海老原 賢次(EBIHARA Kenji)
リコーITソリューションズ株式会社(RICOH IT SOLUTIONS CO.,LTD.)
鹿児島ソリューション部(Kagoshima Department)

2013年10月25日金曜日

連載:ちょっとディープなXPages コラム1

みなさん!XPages開発していますか!?
前回の予告でJavaScriptのパターンをいくつか紹介します、と書いていましたがJavaScriptをちょっとおやすみして、XPagesの小ネタをはさもうと思います。

renderedとloadedの違い

配置したコントロールを表示/非表示するときに、renderedのプロパティを使用するかと思います。
renderedに聞き覚えのない方は、下記のチェックボックスと言えばわかるでしょうか?
イメージ
このチェックボックスをoffにすると、「すべてのプロパティ」でrenderedの値が"false"になっているのが確認できると思います。
一方で同じ「すべてのプロパティ」にはloadedというものが有り、これを"false"に設定すると同じように表示されなくなります。
では、これらの違いはどこにあるのでしょうか?
実は、画面にあるコントロールは、renderedの値にかかわらず、サーバーのメモリに展開されますが、loadedを"false"とするとメモリ上にも展開されなくなります。
つまり実行時にコントロールが存在しない扱いになるわけです。
もちろん、メモリ上に展開しない分だけサーバーの負荷は減るわけで、パフォーマンスにも影響します。
じゃあ、loadedだけを使えばいいのかというとそういうわけではありません。メモリ上に展開しないということは、ボタンなどのイベント処理でアクセス出来ない-再表示させたりできなくなることになります。
なので、loadedの式は"動的な計算"は使えず"ページの読み込み時に計算"しか選択できないようになっています。

まとめ

画面内のボタン等で表示を切り替えたい場合は、renderedで、ページの読み込み時に表示/非表示が決定して、ページを離れるまで変更ない場合は、loadedで設定しましょう。

次はJavaScriptに戻ります

次はちょっと組立を変えて、JavaScriptのオブジェクト・リテラルについてお話します。
海老原 賢次(EBIHARA Kenji)
リコーITソリューションズ株式会社(RICOH IT SOLUTIONS CO.,LTD.)
鹿児島ソリューション部(Kagoshima Department)

2013年7月24日水曜日

連載:ちょっとディープなXPages 第2-4回~JavaScriptをもっと知ろう

みなさん!XPages開発していますか!?
さて今回は型変換の続きで、文字や日付型から数値への型変換を書いていきます。

数値型への型変換

文字列→数値

これについては、前々回でお話していますが、おさらいしておきましょう
  • JavaScriptのビルドイン関数にparseInt()がありますが、これは使わない
  • 代わりに Number() を使用する
  • 自動型変換を利用した方法でも良い (+"08")
ということでした。理由については、前々回の記事を参照してください。
ここで1つ注意。new Number() としてはダメです。下記のように不思議な現象が起きます。
var str = '08',
    num_a = Number(str),
    num_b = +str,
    num_c = new Number(str);
print(num_a); // 8
print(num_b); // 8
print(num_c); // 8 (chromeのconsoleで出せば Number{} と表示されます)
print(num_a === num_b); // true
print(num_a === num_c); // false ←?
じつは、new をつけると数値型ではなく数値オブジェクト型になるためです。数値はオブジェクトではなくプリミティブですが、new をつけると数値をラップしたオブジェクトになるため、数値とは異なるものになるからです。
ちょっと話が難しくなりましたね。今はわかんねーよという方は、とりあえずnew Number() を使わないようにしましょう。(勉強してわかるようになろうね!)
あ、下記も同じことが言えるので、使用禁止です。(前々回でやっとけばよかったねー)
// ダメな例
new String();
new Number();
new Boolean();
あれ? (1).toString() とかできるよね?プリミティブ値にはメンバー無いんじゃない? と思った方がいるかもしれません。実は、内部で暗黙的にオブジェクトに変換しているんですね。
(1).toString();
↓内部的には
(new Number(1)).toString();
として処理されます。便利ではあるんですが、ややこしさの一因にもなってますね(^^;

日付→数値

これは、Date.getTime()で変換する他ありません。前回「日付→文字列」でも書いた方法ですね。
こ れで得られる値は、タイムゾーンに関係なくUTCの1970/1/1 0時からの経過ミリ秒数で得られるので、日付型で保持できない(例えばプレーンなテキスト、JSONなど)場合にこの数値に変換して、使用するときには Data.setTime()で日付型に戻すと良いでしょう。

Boolean値の変換

Booleanはまとめたほうがわかりやすいかなと思い最後まとめました。

対数値

Booleanは、true -> 1、false -> 0 の関係にあり、それぞれ相互に変換されます。また、数値は0以外("以下"ではない!!)はtrue、0はfalseに変換されます。
print(Number(true)); // 1
print(Number(false)); // 0
print(Boolean(0)); // false
print(Boolean(1)); // true
print(Boolean(100)); // true
print(Boolean(-1)); // true
繰り返しになりますが、new Boolean() は使わないように。

対文字列

文字列は、空文字(長さが0の文字列)以外は、trueになります。
またBoolean値を文字列に変換すると、"true","false"になります。
・・・気づきました?
そう、false→文字列で"false"ですが、"false"→Booleanで true になってしまいます!
print(Boolean("a")); // true
print(Boolean("")); // false
var t = true,
    f = false,
    f_a;
print(String(t)); // "true"
f_a = String(f);
print(f_a); // "false"
print(Boolean(f_a)); // true

null と undefined

これらはBoolean型に変換すると、falseになります。
変数に値が割り当てられたかもしくはnullの場合は、処理しない・・・などどいうシーンでよく使用しますね。
var f = function(a, b){
    // !!は、自動型変換を利用した変換方法
    // ifの場合は()内を自動的に変換するため不要だが
    // 明示的に示すことで、意図を明確にできる。
    if(!!(a) && !!(b)){
        return 'o';
    }
    return 'x';
}
print(f("i")); // 'x' bがundefined
print(f(null, "i")); // 'x' aがnull
print(f("i", null)); // 'x' bがnull
print(f(1, "i")); // 'o'

型変換はおしまい

次は、JavaScriptのいろいろな実装パターンについて書いていこうかと思います。
海老原 賢次(EBIHARA Kenji)
リコーITソリューションズ株式会社(RICOH IT SOLUTIONS CO.,LTD.)
鹿児島ソリューション部(Kagoshima Department)

連載:ちょっとディープなXPages 第2-3回~JavaScriptをもっと知ろう

みなさん!XPages開発していますか!?
さて今回は、JavaScriptの型変換について記載してみたいと思います。SSJSについてもやるので、JavaScriptが続いてなんだかXPagesから離れてるな~なんて思っている方、ぜひ見てくださいね。
型変換についての説明は、文字列、数値、日付型の相互変換について書いていきます。

文字列型への型変換

数値→文字列

Number型にtoString()メソッドが存在するので、これを使うことで良いでしょう。また、String関数や自動型変換を利用することもできます。
また、自動型変換を利用した記述の少ない方法もよく取られます。
/* SSJS, CSJS */
var num0 = 123,
    num1 = 456.789,
    num2 = 987.654;
//SSJSの場合はprintを使う
console.log('num0:' + num0.toString()); // "num0:123"
console.log('num1:' + String(num1)); // "num1:456.789"
console.log('num2:' + (num2+'')); // "num2:987.654"
// 一番下は、'num2:' + num2 でも同じ結果だが、
//num2を数値から文字列に型変換することを名確認するため、(num2+'')とする。
書式を指定した変換の仕組みは、ビルドイン関数にありませんが、XPagesでは書式変換用の関数を利用できます。
CSJSではDojoの関数"dojo.number.format"を利用します。
dojo.numberオブジェクトを使用するためには、XPagesのリソース→追加→Dojoモジュール→Dojoモジュール名"dojo.number"を指定します。
イメージ
/* CSJS */
var num0 = 123456;
console.log('num0-1:' + dojo.number.format(num0,{pattern: '0000000000'})); // "num0-1:0000123456"
console.log('num0-2:' + dojo.number.format(num0,{pattern: '#,###.00'})); // "num0-2:123,456.00"
※ 書式については、こちらにを参照してください。
SSJSについては、I18n.toString()を使用することで、任意のフォーマットに安全に変換出来ます。
/* SSJS */
var num0 = 123456;
print('num0-1:' + I18n.toString(num0, '0000000000')); // "num0-1:0000123456"
print('num0-2:' + I18n.toString(num0, '#,###.00')); // "num0-2:123,456.00"

日付→文字列

JavaScriptのDateオブジェクトには、toString()メソッドが存在しますが、これはローケーションによって書式が異なり、戻り値の予測が困難なため、使用してはいけません。
XPagesでは数値型と同じようにCSJS、SSJSに関数が用意されていますので、それを利用しましょう。
dojo.date.localeオブジェクトを使用するので、XPagesのリソース→追加→Dojoモジュール→Dojoモジュール名"dojo.date.locale"を指定してください。
イメージ
/* CSJS */
var date = new Date();
//日付のみ変換
console.log('date0-1:' +
  dojo.date.locale.format(date,{datePattern: 'yyyy/MM/dd', selector:'date'})); // "date0-1:2013/07/01"
//日時
console.log('date0-2:' +
  dojo.date.locale.format(date,{datePattern: 'yyyy/MM/dd HH:mm:ss'})); // "date0-2:2013/07/01 17:25:31"
/* SSJS */
var date = new Date();
//日付のみ変換
print('date0-1:' + I18n.toString(date, "yyyy/MM/dd")); // "date0-1:2013/07/01"
//日時
print('date0-2:' + I18n.toString(date,"yyyy/MM/dd HH:mm:ss")); // "date0-2:2013/07/01 17:25:31"
日付から文字列への変換で、注意しなければならないのは日付、時刻をユーザーのタイムゾーンに合わせる必要がある、ということです。
日本国内のみのアクセスに限定されるのであれば意識することはないですが、複数のタイムゾーンからのアクセスが考えられる場合は必ず配慮してください。
サーバーとクライアントとのタイムゾーンが違う場合、サーバーでDateオブジェクトから文字列に変換すると、通常はサーバーのタイムゾーンで変換され、レンダリングされるので、ユーザーには間違った日時が出力されてしまいます。
XPagesでは、SSJSでの日付の処理をクライアントのタイムゾーンに合わせることができます。DBのプロパティで設定出来ます。
イメージ
こ の設定を行うとXPagesは、初回アクセス時にブラウザのタイムゾーンを取得するためのレスポンスを出力し、クライアント側でJavaScriptに よって自動的にタイムゾーンの取得と、サーバーへの送信が行われ、サーバーがセッション情報として保持する、という動作をするようです。
また、XPagesをJSONを使用したWebサービスとして使うような場合では、この支援が受けられない場合があります。
そういった場合には、JavaScriptビルドインのDate.getTime() / Date.setTime() を使用することで、数値を介して変換します。
getTime() / setTime() はタイムゾーンに関係なく、UTCの1970/1/1からその日付までのミリ秒値(Tick値)を出力/入力できますので、タイムゾーンを意識することなく安全で確実に日時情報のデータの送受信ができます。
//サーバー側
var date = new Date(),
    retObj = {
        tick: date.getTime();
    }
//レスポンスDobyに書き出し(例
writer.write(retObj.toJSON());

//-クライアント側-------------
//--ajax通信については後日やります
var resDate = new Date();
$.ajax({
  url: "test.xsp",
  context: document.body,
  success: function(resBody){
   var retObj = xsp.fromJson(resBody);
   resDate.setTime(retObj.tick); 
  }
});

まだまだ続くよ

今日はこのへんで。次回は数値型、日付型への変換について書く予定です。
JavaScriptが続きますが、もう少しお付き合いを

2013年7月1日月曜日

連載:ちょっとディープなXPages 第2-2回~JavaScriptをもっと知ろう

みなさん!XPages開発していますか!? さて、今回は前回からの引き続きで、JavaScriptについて書いていきます。

JavaScript禁忌技(続き)

やるなよ、絶対にやるなよ。

parseInt()での数値変換は禁止

parseInt()は、文字列を数値に変換する便利な関数ですが、この関数の使用を十分理解していない場合、バグを生む原因にもなります。
IE8以降か、IE9以降のIE8モードで下記を実行してみてください。
alert(parseInt('07'));
alert(parseInt('08'));
"07"は"7"と表示されましたが、"08"は"0"が表示されました。おかしいですね?なんででしょう。
実は、parseIntには第2引数を渡すことができて、これは変換する進数の値です。
渡した文字列を16進数として扱いたい場合は、"16"を渡します。
alert(parseInt('0xFF'));
//→256 が表示される。
第2引数が渡されない場合は、文字列の内容によって進数が自動的に決定されるのですが、"0"で始まるものは8進数として処理しようとします。
よって、"08"は8進数として変換しようとしてしまいます。
しかし、"08"は8進数としては不正な文字列のため、(エラーになればいいのですが)0を返してしまいます。
最近のブラウザでは、"0x"で始まれば16進数、そうでない場合は10進数として処理するように仕様が変更されているので、この問題はおきません。XPagesのSSJSでも、同様です。
しかし、環境の違いを意識してコーディングするよりも、parseIntを禁止して別な手段を使ったほうが無難でしょう。
代わりに下記を使用します。
var str = '08',
    intStr1 = +str,
    intStr2 = Number(str);
console.log(intStr1); // -> 8
console.log(intStr2); // -> 8
parseIntと上記の代替例では、異なる点があります。
parseIntは数値で始まっていれば、数値以外の文字があっても数値に変換します。
一方代替例では、NaN となります。
var str = '123text',
    intStr0 = parseInt(str),
    intStr1 = +str,
    intStr2 = Number(str);
console.log(intStr0); // -> 123
console.log(intStr1); // -> NaN
console.log(intStr2); // -> NaN

まだまだつづくよ

今回は短いですが、このへんで。
次回もJavaScript。型変換についてもう少し説明します。

連載:ちょっとディープなXPages 第2-1回~JavaScriptをもっと知ろう

みなさん!XPages開発していますか!?
最近は、JavaScriptの重要性が上がってきていますね。
ご存じのとおり、XPagesでもサーバー、クライアント側ともにJavaScriptを使うのでXPagers(エックスページャーズ→XPages開発者→今作った言葉(*ノω・*)テヘ)は必携の技術です。
でも、JavaScriptってなんとなくで使ってませんか?
JavaScriptは簡単に使える言語だけでなく、高度な使い方を覚えると非常に強力で、開発効率が向上します。
また、JavaScriptでは気をつけておきたい定石もありますので、しっかり身につけておきましょう。
なお、サンプルコードはサーバーサイドJavaScript(SSJS)を想定していますが、ログの出力以外に関しては、全く同じです。

JavaScript禁忌技

まずは、JavaScriptで行なってはならないことから。やるなよ、絶対にやるなよ。

等価演算子に"=="は使わない

ifの条件分岐でよく使う等価比較演算子は、2種類あります。"=="と"==="です。"=="だけ使ってませんか?
さてその違いですが・・・実際に試してみましょう
var a = 1,
    b = "1";
print( a == b ); // true
print( a === b ); // false
この結果から分かる通り、
"=="は両端が違う型の場合は、右辺を左辺と同じ型になるように自動型変換して比較します。
"==="は、自動型変換しません。厳密等価演算というやつですね。
"=="のほうが何やら楽…と思われるかしれませんが、ソースコードを他の人や後から見たときに、この比較が型変換を意図したものかどうか、判断することができません。
型変換する場合は"=="を使わず、明示的に変換してから"==="で比較するのがマナー。
var a = 1,
    b = "1";
print( a === (+b) ); // true
型変換については後ほどまとめてやります。

配列を for-in で回さない!

配列を巡回して処理することはよくあります。で、for( var i in array) とよくやりがちですが、これはNGです。
JavaScriptにおける for...in は配列のアイテムを反復するのではなく、オブジェクトのメンバーを反復するステートメントです。
var a = ["A","B","C"];
//オブジェクトaにメソッドを追加
a.doubleJoin = function(){
    return a[0] + a[0] + a[1] + a[1] + a[2] + a[2];
}
for( var i in a){
    print(a[i]);
}
// 結果
// A
// B
// C
// function(){…}  ←想定外の出力
for...inを見たら、即座に頭の上に"!"が出てくる位に気を付けてください。
もちろん、オブジェクトのメンバーを反復する意図として使うのは可能です。
しかし、forにはまだ気を付けなくてはならないことがあります。

forの書き方によってはパフォーマンスに大きな影響あり!

↓のソースには問題があります。
for(var i=0; i < array.length; i++){
    //何らかの処理
}
このどこがいけないのか、と思うかもしれません。動作としては問題ありませんが、パフォーマンスに影響します。
問題は、2番目の項[i < array.length]にあります。この項は反復のたびに実行される部分で、array.lengthが毎回評価されるため、パフォーマンスに影響します。
array.lengthを先に確保することで回避できます。下記のように書き換えるだけで、SSJSでは処理速度に約2倍の差が出ることを確認しています。
var array = [], i = 0;

//ここで配列 arrayに大量に要素が入れられると仮定

for(var i = 0, max = a.length; i < max; i++){
    //反復ごとの処理
}
配列の要素の数が少ない場合は微々たる差ではありますが、癖をつけておくと良いでしょう。
また、コールバック関数を利用して、この反復を強制させる手段もありますが、それは後日にしたいと思います。

まだまだ続くよ

JavaScriptについてはまだまだ書き足りませんねぇ。
何回かに分けて書いていくのでお楽しみに!

2013年6月13日木曜日

連載:ちょっとディープなXPages 第1回~HTMLタグを自由にコントロールしよう

みなさん!XPages開発していますか!?

本題に入る前に

XPageの画面を編集する際、WYSIWYGの画面で実装しています?
もし、ちょっとディープな世界に足を踏み入れたければ(沼に足をつっこみたければ!?)ソースの画面を開きましょう!

↑恐れずに[ソース]を押しましょう!
この連載では、タグをガシガシ書いていくことが多いので、是非ソース表示に慣れてくださいね。

HTMLタグを書こう

今回のテーマは、「HTMLタグを自由にコントロールしよう」ということですが、これはHTMLを書こうぜ!ということです。
サーバーコントロールがあるのに、なぜわざわざHTMLを書かなくてはならないのか、もちろんそれにはメリットがあるからです。
簡単に比較してみました。
HTML サーバーコントロール
意図したHTML
記述したHTMLがそのまま描画される
コントロール名から想像するか、実際に出力されたものを確認するしかない。
また、プロパティ等によって出力されるHTMLが異なる。
クライアントサイドJavaScriptでの操作
HTMLが意図したものなので、操作しやすい。
プロパティや状態によりHTMLが異なったり、クライアントIDが動的に変わるため、操作しづらい。
サーバーのメモリ消費量
サーバーコントロールに比べて少ない
HTMLタグに比べて多い
テキストボックスなどのフォームへのデータバインド
できない。ただし、サーバー側で入力値を受け取ることはできる。(後述)
できる。
開発効率
WYSIWYG画面で編集できない。プロパティウィンドウ等の支援もない。
しかし、HTMLタグやIDが書いたままがレンダリングされるため、クライアントJavaScriptを多用する場合は有利な場合もある。
WYSIWYG画面で編集でき、プロパティウィンドウ等の支援もある。
しかし、レンダリングされるHTMLが動的であったりIDが動的なため、クライアントJavaScriptを多用する場合は不利な場合もある。
サーバーサイドJavaScriptでの操作
属性を動的に変更できるが、タグ自身を操作したりするのが困難
タグのレンダリングを含め、様々なコントロールができる
このように一長一短で、すべてにおいてHTMLを使用するのが望ましいわけではありませんので、適所に使用することを心がけましょう。

HTMLの記述と属性値の動的割り当て

どうやってHTMLを書くのかは、まあ簡単だと思います。コード画面を開いておもむろにタグを記述します。
id属性も記述した通りのHTMLが出力されるので、Javascriptでの操作やCSSの適用などにid名がそのまま使えて便利です。
しかし、属性の内容をサーバーサイドで動的に書き換えたい場合はどうでしょう?XPagesでは記述したタグの属性値を動的にレンダリングする方法がありますので、ご紹介します。
属性値のところで、動的に値を変えたい場所に、#{}や${}式を書くことができます。

例1)データソースのNotesXspDocumentが編集モードの場合に表示する。
<div id="editBox" style="display:#{javascript: doc.isEditable ? 'block' : 'none'}">・・・</div>
例2)クラス名にviewScopeの"class"の値を入れる。
<button class="lotusButton #{viewScope.class}">送信</button>
例3)ビュー"view01"がデータソースのリピートコントロール内の繰り返し要素で、ビュー列"title"の値をテキストボックスに表示する。
・・・

サーバーのメモリ消費量

上の比較表で、HTMLの方がサーバーサイドのメモリの消費量が少ない、と書きました。
実際に計測したので、その方法と結果をご紹介します。

=検証環境=

Domino8.5.3 FP3

=測定方法=

サーバーコントロール(編集ボックス)を100個あるページ(1)と HTMLフォーム(input type="text")が100個あるページ(2)を用意。
メモリ消費量は、Runtime.getRuntime().totalMemory() - Runtime.getRuntime().freeMemory() で算出。
Httpサービスを起動直後に(1)のページを表示し、メモリ消費量を記録。Httpサービスを停止→起動し(2)を表示しメモリ消費量を記録。

=結果=

メモリ消費量
サーバーコントロール(1)ページ 19.2MB
HTML(2)ページ 16.8MB

このように、同じテキストボックスでもHTMLタグで書いたほうがメモリ消費量が少ないことがわかります。
同時接続の数や頻度が多くなると、その差も開いてくることが考えられますので、特に多セッションが考えられる場合、厳しいレスポンス要件が期待される場合は、HTMLタグ記述が有効です。

POSTデータの受け取り

HTMLタグで書いたフォーム(input type="text"など)の入力値をサーバーで受け取るには、paramグローバルオブジェクトを利用します。
<input type="text" name="title" />
このテキストボックスに入力された値を、サーバー側で受け取るには
param.get('title') 
で取得できます。 クライアントからの送信は、全更新、部分更新とともに自動的に送信されるので、HTMLタグで書いたとしても、特に意識する必要はありません。

まとめ

サーバー側での操作を必要としない要素はHTMLタグで書こう!

2013年6月3日月曜日

連載:ちょっとディープなXPages 第0回

みなさん!XPages開発してますか?!

XPages、便利ですよねぇ。Notesの資産を手軽に且つ見栄え良のいいWebを手軽に作成出来ますよね。

Extension Libraryを組み合わせればさらに強力なユーザー・エクスペリエンスを提供できますし、ますます便利に。

XPagesを知ると、いままでのFormWebには戻りたくないですよね。

それも、XPagesのフレームワークが非常に強力であるおかげなのですが、裏を返せば自由度が少ないとも言えます。

フレームワークの枠を外れた複雑なことをしようとすると、フレームワークが何をしているかというのを解析して把握する必要あるんですよね。
ということでこのブログでは、XPagesをより深く掘り下げてみてわかったことを連載でお伝えしたいと思います。

すでにお分かりかと思いますが、初心者向けの内容ではないので、あしからず。
連載の項目は大雑排にしか決まっていないのですが、こんな感じです。


  • サーバーコントロールに頼らない!HTMLタグを自由にコントロールしよう!
  • JavaScriptをもっと知ろう!
  • jQueryを使おう!
  • 独自でAjaxしてみよう!
  • Javaのライブラリを使ってみよう!


今回は、プロローグということで、具体的な記事は次回からです。