ラベル Lotus Notes/開発 の投稿を表示しています。 すべての投稿を表示
ラベル Lotus Notes/開発 の投稿を表示しています。 すべての投稿を表示

IBM Sametime 8.5.2をIBM Domino 9サーバに導入する方法

Sametime 9からアーキテクチャが大幅に変わり、1台のサーバでサービスを提供するのが難しくなってしまった。

そこで、Domino 9のサーバに強引にSametime 8.5.2をインストールしてみたので
その手順をメモしておく。

まず、導入環境は以下のとおり。

  • サーバ
    • Windows server 2012 R2 (Hiper V環境の仮想サーバ)
    • IBM Domino 9.0 (既存ドメインの追加サーバとして導入)
    • IBM Sametime 8.5.2 IFR1
     
  • クライアント
    • IBM Notes 8.5.2/9.0 組み込みクライアント


以下手順

  1. 既存Notesドメインにサーバを追加
  2. 1.のサーバIDを使ってDomino 8.5.2をセットアップ
    ※Domino9ではSametime 8.5.2のインストーラのバージョン確認で引っかかるため
  3.  Sametime 8.5.2およびIFR1をインストール
  4. Dominoサーバを9.0にアップグレード
  5. Windows firewallでSametime用のポートを解放 (デフォルトはTCP1533)
  6. Sametime.ini (Dominoサーバのインストールフォルダにある)で以下のパラメータに値を追加
    • VPS_ALLOWED_LOGIN_TYPESにNotes 9組み込みクライアントの番号を追加
    • ついでにVPS_PREFERRED_LOGIN_TYPESにも同じ番号を追加

    ※クライアント番号はIBMのページを参照
  7. Domino Directoryのサーバ文書でTravelerのタブを設定

[LotusScript] 自作プログラムでメール作成画面を開くときに署名を挿入させない

スクリプトで表題や本文に値を入れた状態でメール作成画面を開く場合、
以下のように実装する。

Dim ws as New NotesUIWorkspace
Dim db as New NotesDatabase("", "")
Dim doc as NotesDocument

call db.openMail() 'メールDBを開く

set doc = db.createDocument() '新規文書作成
call doc.replaceItemValue("Form", "Memo") 'メールフォームに設定



'-------  宛先を編集 -------------
call doc.replaceItemValue("SendTo", "CN=User1/HOGE") 'To設定
call doc.replaceItemValue("CopyTo", "CN=User1/HOGE") 'Cc設定
call doc.replaceItemValue("BlindCopyTo", "CN=User1/HOGE") 'Bcc設定



'-------  表題や本文を編集 -------------
call doc.replaceItemValue("Subject", "Test") ' 表題設定

dim rtitem as NotesRichTextItem
set rtitem = doc.createRichTextItem("Body")

~~~  本文編集(補足1参照)  ~~~


'-------  作成画面を開く ------------- 
call ws.EditDocument(True, doc, False) '編集モードでUIDocumentを開く


これで宛先や表題、本文に値が入力されているメール作成画面が開く。

メールの設定で署名を自動挿入にしている場合は本文の冒頭に署名が
追加されてしまうので注意。

署名追加を回避したい場合はreplaceItemValueで"$AutoSaveRecovered"
というフィールドを作成する(R8.5のメール設計で動作確認)

補足)よく使うリッチテキストアイテムの編集用メソッド

appendText(text): テキストを追加
addNewLine(LineNumber): 改行
appendDocLink(notesdocument, discription): 文書リンク追加

[LotusScript]スクリプト実行ユーザのメールDBを取得する

プログラム実行ユーザのメールサーバを取得したいときに、
ロケーション文書から取得するしかないと思っていたが
NotesDatabaseのopenMailメソッドで簡単に取得できることが
判明した。(知ってて当たり前?)

■opemMailメソッドを使ってメールDBを取得、サーバ名をPrintする

Dim db as New NotesDatabase("", "") '適当にNotesDatabaseインスタンスを生成

call db.openMail() 'openMailを実行するとスクリプトを実行しているユーザのメールDBを開く

Print  "メールサーバ名: " & db.Server  'メールDBのサーバ名をPrint
 

[LotusScript]文書の作成日で識別番号を発行する

文書に識別番号を付与する場合に作成日を利用することがある。
(xx-20140203-001など)

LotusScriptではFormat関数を利用して自動発番を以下のように実装する

  1. 文書を作成日でソートしたビュー(vwCount)を作成
    ※第1列のデータの種類は作成日を昇順or降順にソートし値の種類をDate/Timeに設定
    1. スクリプトライブラリで識別番号取得用の関数(getID)を作成

      Function getID() as String
        Dim session as new NotesSession
        Dim db as NotesDatabase
        Dim vw as NotesView
        Dim dc as NotesDocumentCollection

        set db = session.getCurrentDatabase()
        set vw = db.getView("vwCount")  '文書カウント用のビューを取得

        set dc = vw.getAllDocumentsByKey(Today, True) '作成日が今日の文書を取得

        getID = "xx-" _  '接頭文字
        & Format(Today, "yyyymmdd") _  '今日の日付
        & "-" & Format(dc.Count + 1, "000")  '作成日が今日の文書数+1を3桁に変換
      End Function
    2. フォームのQueryOpenイベントに以下のコードを追加
      ※上記で定義したスクリプトライブラリを取り込む

      Sub QuerySave(Source as NotesUIDocument, Continue as Variant)
        Const FLD_ID = "docID" '文書の識別番号フィールド名

        Dim doc as NotesDocument

        set doc = Source.Document

        call doc.replaceItemValue(FLD_ID, getID())  'バックグラウンドでフィールドを更新
        call doc.save(True, True) 'バックグラウンド文書を保存
      End Sub

LotusScriptでNotesDocumentCollectionの全文書に同じ処理を実行する

NotesDocumentCollectionの全文書に対して処理を実行する場合、
whileを使って以下のようにコーディングする。

Dim dc as NotesDocumentCollection 
Dim doc as NotesDocument 

set doc = dc.getFirstDocument() 

while not doc is nothing 
  -- 処理 -- 
  set doc = dc.getNextDocument(doc) 
wend 

たまに最後の"set doc = dc.getNextDocument(doc)"を忘れて
無限ループになってしまうことがあるので、 全文書に対して
同じ処理をするようなWrapperクラスを作成してみる。  


%REM
    Class NDCWrapper
    Description: Wrapperクラス
%END REM
Class NDCWrapper
  Private zzpm_this As NotesDocumentCollection
 
    'Constructor
    Sub New(dc As NotesDocumentCollection)
      Set zzpm_this = dc
    End Sub
   
    'Destructor
    Sub Delete
    End Sub
   
    %REM
        Function forEach
        Description: 全文書に対して処理を実行するメソッド
    %END REM
    Function forEach(processor As DocumentProcessor) As Long
      Dim doc As NotesDocument
      Dim cnt As Long
     
      Set doc = zzpm_this.getFirstDocument()
      cnt = 0
      While Not doc Is Nothing
        If processor.procDoc(doc) Then cnt = cnt + 1
        Set doc = zzpm_this.getNextDocument(doc)
      Wend
     
      forEach = cnt
    End Function
   
    %REM
        Function getDocumentCollection
        Description: getter メソッド
    %END REM
    Function getDocumentCollection() As NotesDocumentCollection
      Set getDocumentCollection = zzpm_this
    End Function
End Class


%REM
    Class DocumentProcessor
    Description: WrapperのforEachで処理を行うクラス

%END REM
Class DocumentProcessor
    'Constructor
    Sub New
    End Sub
   
    %REM
        Function procDoc
        Description: forEachから渡されたNotesDocumentを処理するメソッド
    %END REM
    Function procDoc(doc As NotesDocument) As Boolean
    End Function
End Class


DocumentProcessorを継承のうえ、procDocをオーバーライドしたクラスをforEachに渡すと
コレクション内の全文書に対して処理を実行することができる。



◆使い方例

Class TestProcessor as DocumentProcessor
  Function procDoc(doc As NotesDocument) as Boolean
    Print doc.UniversalID
  End Function
End Class

Dim ws As New NotesUIWorkSpace
Dim dcWrapper As New NDCWrapper(ws.currentDatabase.UnprocessedDocuments)
Dim processor As New TestProcessor

Call dcWrapper.forEach(processor)  'UnprocessedDocumentsのUNIDをPrintで出力


Domino DesignerでJava Agentをデバッグする

Designerでエージェント内のメインクラスを開いてDebugを実行してもエラーになりうまく動かない。
Java Agentのデバッグを行うにはDegnerでJava Agentのデバッグを有効にして以下の手順を実施する必要がある。

<Java Agentデバッグの有効化>
  1. 上部メニューの[Tools] - [Java Debugging Preferences...]を実行
  2. [Java Agents/Applets]にチェックをいれアクセスポートを入力
    ※パーソナルファイアウォールなどでポート接続を許可する必要あり。
  3. Domino Designerを再起動
<Java Agentのデバッグ手順>
  1. エージェント一覧を表示
  2. デバッグしたいエージェントを開く
  3. メインのクラス(Notesmainを実装しているクラス)のソースを表示
  4. 上部メニューの[Run] - [Debug Configrations...]を実行
  5. 左の項目にある[Remote Java Application]をダブルクリックして
    新規のデバッグを作成
  6. 5で作成したデバッグの[Connect] タブを表示
  7. [Project]に"Notes DBファイル名.エージェント名.ja"を指定
  8. [Connection Properties]で以下の通り設定
    Host: localhost
    Port: Java "Agentデバッグの有効化"で設定したアクセスポート番号
  9. [Debug]ボタンをクリック
  10. ソースコードにBreakpointを設定
    ※ソースコードの行の左をダブルクリックしてBreakpointを設定/解除
  11. エージェント一覧でデバッグするエージェントを実行
    ※右クリックメニューで[Run]実行
  12. 10で設定したブレークポイントにくると自動で「Debug」パースペクティブに
    切り替わるのでデバッグする
  13. デバッグが完了したら[Run] - [Terminate]でDebugを終了

Notes DBでJava Agentを作成する

NotesのDB上でJavaプログラムを実行するためにはJava Agentを作成する必要がある。LotusScriptのAgentと同様Applicationエクスプローラーの[Code] - [Agents]から作成できるが、どうやらDomino DesignerではJava Agentを作成するとAgent単位でプロジェクトを作成する仕様になっているらしく、作成後にパッケージエクスプローラで見るとエージェント単位でプロジェクトが作成されているのが確認できる。

ここで重要なのがデフォルトのDesigner設定ではJavaのコンパイラがJava1.2用でコンパイルしてしまうということである(JDKバージョン1.3, JVMバージョン1.2)。

JDK1.3だとアサーション(JDK1.4~)やジェネリッククラス(JDK1.5~)、可変長引数(JDK1.5~)が使えないためDomino Designerの設定を変更してコンパイルするJavaのバージョンを変更しておくのがよい。

Javaのコンパイルオプションを変更するためにはDesingerのNotes.iniファイルに以下のオプションを追加する。

JavaCompilerTarget = 1.5  (R8.0.x)
JavaCompilerTarget=CurrentJavaVersion (R8.5.x)

上記を追加してDesignerを再起動するとJava AgentのJDKバージョンが変更される(R.8.0.xは1.5に、R8.5.xは1.6になる)。

参考ページ:
IBM - Lotus Notes/Domino における Java 実行環境とその問題判別について

JavaのFor-eachが使えるようにDocumentCollectionを拡張する

標準のDocumentCollectionクラスはIterableインタフェースが実装されておらず、for-each構文が使えないため、Collection内の全文書に対して処理を実施したい場合、while(doc != null)とgetNextDocument(doc)を組み合わせる必要がある。

Iteratableインターフェースを実装したクラスを定義しfor-eachが使えるようにしておけば便利である。

実装はViewインスタンスもDocumentCollectionのように扱えるWrapperを用意しそのクラスを使ってIterableなコレクションクラスを実現している。

以下ソースコード

DocumentCollectionWrapperクラス
package hogehoge;

import lotus.domino.*;

public final class DocumentCollectionWrapper {
    private DocumentCollection _m_dc;
    private View _m_vw;
    private Document _m_currentDoc;
    private Document _m_prevDoc;
    private boolean _m_isView;
   
    public DocumentCollectionWrapper(DocumentCollection dc) {
        // TODO Auto-generated constructor stub
        _m_dc = dc;
        _m_isView = false;
    }
    public DocumentCollectionWrapper(View vw){
        _m_vw = vw;
        _m_isView = true;
    }
   
    public Document getFirstDoc() throws Exception{
        _m_currentDoc = (_m_isView)?
            _m_vw.getFirstDocument(): _m_dc.getFirstDocument();
       
        prevDocRecycle();
       
        return _m_currentDoc;
    }
    public Document getLastDoc() throws Exception{
        _m_currentDoc = (_m_isView)?
            _m_vw.getLastDocument(): _m_dc.getLastDocument();
       
        prevDocRecycle();
        return _m_currentDoc;
    }
   
    public Document getNextDoc() throws Exception{
        _m_currentDoc = (_m_isView)?
            _m_vw.getNextDocument(_m_currentDoc): _m_dc.getNextDocument();

        prevDocRecycle();
        return _m_currentDoc;
    }
    public Document getPrevDoc() throws Exception{
        _m_currentDoc = (_m_isView)?
            _m_vw.getPrevDocument(_m_currentDoc): _m_dc.getPrevDocument();

        prevDocRecycle();
        return _m_currentDoc;
    }
    public Document getNthDoc(int n) throws Exception{
        _m_currentDoc = (_m_isView)?
            _m_vw.getNthDocument(n): _m_dc.getNthDocument(n);
           
        prevDocRecycle();
        return _m_currentDoc;
    }
    public void destruction() throws Exception{
        prevDocRecycle();
        if(_m_isView){
            _m_vw.recycle();
        }
        else{
            _m_dc.recycle();
        }
    }
    protected void finalize()throws Throwable{
        destruction();
    }   
    private void prevDocRecycle() throws Exception{
        if(_m_prevDoc != null){
            _m_prevDoc.recycle();
        }
        _m_prevDoc = _m_currentDoc;
    }
   
}

IterableNotesDocCollectionクラス
package hogehoge;

import lotus.domino.*;


public final class IterableNotesDocCollection
implements implements Iterable<documen>, java.util.Iterator<document> {
    private DocumentCollectionWrapper _m_dcw;
    private lotus.domino.Document _m_nextDoc;
   
   
    public IterableNotesDocCollection(lotus.domino.DocumentCollection dc)
    throws Throwable{
        _m_dcw = new DocumentCollectionWrapper(dc);
    }
    public IterableNotesDocCollection(lotus.domino.View vw)
    throws Throwable{
        _m_dcw = new DocumentCollectionWrapper(vw);
    }
   
    public java.util.Iterator<document> iterator(){
        return this;
    }
    public boolean hasNext(){
        try{
            _m_nextDoc = (_m_nextDoc == null)?
                _m_dcw.getFirstDoc(): _m_dcw.getNextDoc();

            return _m_nextDoc != null;
        }
        catch(Throwable e){
            return false;
        }
    }
    public lotus.domino.Document next(){
        if(_m_nextDoc == null){
            throw new java.util.NoSuchElementException();   
        }
        return _m_nextDoc;
    }
    public void remove(){
        throw new UnsupportedOperationException();
    }
   
    public void destruction() throws Exception{
        _m_dcw.destruction();
    }
   
    protected void finalize()throws Throwable{
        destruction();
    }
}

使用例:
//vw: lotus.domino.Viewインスタンス

IterableNotesDocCollection dc = new IterableNotesDocCollection(vw);

Integer i = 0;
for(Document doc: dc){
  //ビューの全文書についてUNIDを表示する。
  System.out.println( ++i + ": Document UNID: " + doc.getUniversalID());
}

Lotus Domino DesignerでのJavaプログラミング

Domino DesignerはEclipseベースなため、Notes DBだけでなく、Javaのプロジェクトを作成することが可能になっている。また、Dominoのライブラリをクラスパスに追加するとDIIOPでDominoサーバに接続できる。

まずはDominoのJAVAクラスライブラリを使用するためにDesignerのクラスパスを追加しておく。

<Domino Designerの事前設定>
  1. [File] - [Preferences]を開く
  2. [Java] - [Build Path] - [Classpath Variable]を開く
  3. "New"ボタンでNCSO.jarを追加する。  
  4. [NCSO.jarのパス]: {Notes Dataフォルダ}\domino\java\NCSO.jar
次にブログラムを作成するプロジェクトを作成する。

※どうやらデフォルトでNotes.jarファイルがクラスパスに登録されているため不要の模様。

Notes DBはJavaパースペクティブで見ると一つのプロジェクトとして扱われいる模様。プロジェクトの中にCode/Javaというソースフォルダがあったためそこにクラスを作成して実行してみたところmain関数の呼び出しでClassLoaderがNoClassDefFoundErrorでエラーになってしまう。

Java Agentを作成すれば実行できるが、いろいろなアプリで使いそうなライブラリを作成したかったので独立したプロジェクトを作成する。

<Domino DesignerでのJavaプロジェクト作成手順>
  1. [File] - [New] - [Java Project]で新しいプロジェクトを作成画面を表示
  2. プロジェクト名を指定し、"Next >" "Finish"ボタンをクリック
  3. [Java Settings]が表示されるので[Libraries]タブを表示する
  4. "Add Variable..."をクリックしNCSO.jarを追加し"Finish"ボタンをクリック
プログラム中でNotesFactoryを使うとDominoのSessionクラスのインスタンスを取得できる。このSessionクラスからDatabaseインスタンスなどを取得し操作する。

<Sessionインスタンスの取得方法>
  1. "lotus.domino.*;"をインポート
  2. NotesFactory.createSession()でSessionインスタンスを取得
    e.g. Session session = NotesFactory("[ServerHostName]:[DIIOP Port]", "[UserName]", "Password");
    ServerHostName
    サーバのホスト名もしくはIPアドレス
    DIIOP Port
    DIIOPのアクセスポート番号
    UserName
    ユーザ名e.g. Taro Tanaka/CORP
    Password
    ユーザのインターネットパスワード

Lotus Domino ServerへWebブラウザで添付ファイルをアップロードする場合の注意事項

XpagesのFile Upload Controlを使ってファイルアップロード機能を実装する際の注意事項をメモする。(解消方法がわかったら随時更新予定)

  1. ファイルサイズについて
    サーバ設定およびDB設定で制限をしているので、ファイルアップロードがうまくいかない場合は以下2つの設定を確認する。
    1. サーバ設定
      サーバ文書の[Internet Protocol]-[HTTP]タブにある"HTTP Protocol Limits"という項目でHTTPリクエストのサイズ制限を行っている。
      デフォルトでは10,000KB(10MB)なので必要に応じて変更する。
    2. DB設定
      Domino Designerで対象DBのプロパティを開くと、[Xpages]タブでXpagesの設定を確認できる。その中に"File Upload Options"でファイルサイズを制限している(デフォルトは制限なし)。
  2. 文書の保存について
    原因不明だがファイル添付後、同じ画面でNotesXspDocumentのSaveを複数回行うと競合文書ができてしまう。画面遷移をすればNotesXspDocumentが再作成されるので回避できる模様

Notes DBのDDSアクセスを有効化する

DDSの有効化はDB単位で設定する必要がある。デフォルトでDDSは無効になっているのでDDSを利用するDBは以下の設定を実施する。

DDS有効化手順
  1. DesignerDBのプロパティを開く
  2. "Advanced"タブを開く
  3. "Allow Domino Data Service"を"Views only"もしくは"Views and documents"に変更
参考:
IBM Notes and Domino Application Development wiki -Enabling Domino Data Service on a database

DominoサーバのDomino Data Service (DDS)を有効にする

Dominoデータサービスを有効にするとDBのデータをJSON形式で取得したり、JSON形式のデータを送信して文書の作成・更新が可能になる。

<DDS有効化手順>
  1. DominoサーバのHTTPタスクを設定・起動(設定内容省略)
  2. サーバ文書を開く
  3. [Internet Protocols] - [Domino Web Engine]タブを表示
  4. "Domino Access Service"という項目(一番下)のEnabled Services(有効なサービス)に"Data"を追加
  5. HTTPタスク再起動
※DDSを使うDBについてはDB単位でDDSの設定が別途必要(設定方法はこちら)

参考:
IBM Notes and Domino Application Development wiki - Enabling Domino Data Service on a server

Notes DBにJSON形式のデータを送信し文書を作成・更新する

Domino Data Serviceを使うとNotes DBにHTTPでJSON形式のデータを送信し文書の新規作成や更新をすることができる。

Domino Data Serviceを使うための設定はこちらを参照。

JSON形式で送信する場合、リクエストのヘッダにContent-typeを"application/json"で指定する必要がある。
作成・更新・削除のリクエストURLと送信タイプはそれぞれ以下の通り。
  •  文書の作成
    URL: http(s)://[サーバ名]:[ポート]/[DBパス]/api/data/documents
    Method: POST
     
  • 文書の更新
    URL: http(s)://[サーバ名]:[ポート]/[DBパス]/api/data/documents/unid/[UNID]
    Method: PUT
  • 文書の削除
    URL: http(s)://[サーバ名]:[ポート]/[DBパス]/api/data/documents/unid/[UNID]
    Method: DELETE
XMLHttpResponsを使ってデータを送信する関数は以下のとおり。

注意1)Xpagesなどで使う場合はDOCTYPEをデフォルトから変更していないと使えないかもしれません(DOCTYPEの変更方法はこちら)。
注意2)クロスドメイン対応してません。


◆引数の説明
server
サーバのURL
ex.)server = "http://domino01.mydomain.co.jp"
dbpath
DBのパス(リダイレクトルールを作っている場合はURLパターン)
ex.)dbpath = "WebApps/test.nsf"
form
新規作成するフォーム名
json
json形式のテキストデータ
unid
更新・削除対象となる文書のユニバーサルID

◆関数
//JSON形式のデータから文書を作成
function createDocFromJSON(server, dbpath, form, json){
    var request = new XMLHttpRequest();
    var url =
    server
    + '/' + dbpath
    + '/api/data/documents?coumputeform=true&form=' + form;
    request.open('POST', url);
    request.setRequestHeader('Content-Type', 'application/json; charset=UTF-8');
    request.setRequestHeader('Access-Control-Allow-Methods', 'POST, PUT, GET, DELETE, OPTIONS');
    request.send(json);
}

//JSON形式のデータで文書を更新
function updateDocFromJSON(server, dbpath, unid, json){
    var request = new XMLHttpRequest();
    var url =
    server
    + '/' + dbpath
    + '/api/data/documents/unid/' + unid + '?coumputeform=true';
    request.open('PUT', url);
    request.setRequestHeader('Content-Type', 'application/json; charset=UTF-8');
    request.setRequestHeader('Access-Control-Allow-Methods', 'POST, PUT, GET, DELETE, OPTIONS');
    request.send(json);
}

//UNIDを指定して文書を削除
function deleteDocByUNID(server, dbpath, unid){
    var request = new XMLHttpRequest();
    var url =
    server
    + '/' + dbpath
    + '/api/data/documents/unid/' + unid;
    request.open('DELETE', url);
    request.setRequestHeader('Content-Type', 'application/json; charset=UTF-8');
    request.setRequestHeader('Access-Control-Allow-Methods', 'POST, PUT, GET, DELETE, OPTIONS');
    request.send();
}

Lotus NotesのWebアプリでjQueryを使用する

DB単位でjsファイルをimportして使用する方法は以下の通り

  1. jQueryライブラリをダウンロード
    適当なサイトからjQuery(やplugin)をダウンロード
  2. jQueryライブラリをNotes DBにインポート
    Domino Designerでjavaパースペクティブを開きWebContent直下にjQueryディレクトリを作成し1.のファイルをそのままインポート

    ※jQueryのファイル(jQuery-1.8.5.min.jsなど)をNotes DBのスクリプトライブラリに登録するとなぜかエラーがでるのでWebContentにインポート
  3. WebContent/WEB-INF/xps.propertiesでDOCTYPEを設定
    デフォルトではjQueryが動かないようなのでリンクを参考にDOCTYPEを指定
  4. Xpagesの編集画面を開く
    jQueryを使用するページの設計を開く
  5. リソースにjsファイルやcssファイルを追加
    Sourceタブに切り替えて
    <xp:view>の間に<xp:this.resources>を追加し、その中に<xp:headTag>で追加していく。

    CSS取り込み例)
            <xp:headTag tagName="link">
                <xp:this.attributes>
                    <xp:parameter name="rel" value="stylesheet"></xp:parameter>
                    <xp:parameter name="type" value="text/css"></xp:parameter>
                    <xp:parameter name="href"
                        value="jQuery/jquery-ui/theme/jquery-ui.min.css">
                    </xp:parameter>
                </xp:this.attributes>
            </xp:headTag>


    JS取り込み例)
            <xp:headTag tagName="script">
                <xp:this.attributes>
                    <xp:parameter name="script" value="text/javascript"></xp:parameter>
                    <xp:parameter name="src" value="jQuery/jquery-1.8.3.min.js">
                    </xp:parameter>
                </xp:this.attributes>
            </xp:headTag>

    ※でCSSを取り込むとサーバが自動でCSSファイルを統合してしまうのでCSSで指定しているイメージのパスがおかしくなるのでheadTagで指定する。
  6. jQuery用のjavascriptを実行
    後は普通にjQueryを使う。リソースのjavascriptではスクリプトを記入するときに"#{id:xxx}"でIDをバインドできないようなのでもし、IDをバインドさせたい場合は"Output Script"コントロールで内に記述する必要がある模様。

Lotus NotesのWebアプリケーションでDOCTYPEを変更する

以下3つの方法がある

・Xpagesのプロパティで指定する
Xpagesで実装している場合、DBのxspプロパティで指定可能
  1.  Domino DesignerでJavaのパースペクティブを開く。
    (上部メニュー[Window]-[Open Parspective]-[java])
  2. Packege Explorer(左側に表示)でDB内部のディレクトリからXpagesの設定(WebContent/WEB-INF/xsp.properties)を表示
  3. 下側のタブから[Source]を選択し、表示
  4. 以下のプロパティを追加(既に設定している場合は変更)
    xsp.html.doctype=[DOCTYPE宣言]

    例)
      xsp.html.doctype=<!DOCTYPE HTML>
・Notes.iniのオプションを使う
サーバのNotes.iniにDominoCompleteDocTypeオプションを設定することで自動生成のDOCTYPEを変更可能
値 自動生成されるDOCTYPE
0 (default) <!DOCTYPE HTML PUBLIC “-//W3C//DTD HTML 4.01 Transitional//EN”\\>
1 <!DOCTYPE HTML PUBLIC “-//W3C//DTD HTML 4.01 Transitional//EN” “http://www.w3.org/TR/html4/loose.dtd”>
2 <!DOCTYPE HTML PUBLIC “-//W3C//DTD HTML 4.01//EN” “http://www.w3.org/TR/html4/strict.dtd”>

設定例) DominoCompleteDocType=1

・フォームの特殊フィールドを使う
"$$HTMLFrontMatter"というフィールドを作成し、DOCTYPEの宣言を記入することでフォームをWebブラウザで開くときのDOCTYPEを指定できる。

NotesUIDocumentやNotesUIViewのイベントをフックする

UIDocumentやUIViewはOn Eventを使うとイベントハンドラをフックできる。
複数のビューやフォームで同じイベント処理を実施する場合は、事前に関数やオブジェクトを定義し、PostOpenなどでOn Eventを使うとよい。


例)編集可能なビューのクラス

%REM
    Class objEditableVw
    Description:
  使い方
    1.ビューでライブラリ取込
    (option) - Use "objEditableVw"
    2.ビューで変数宣言
    (declarations) - Dim objVw as objEditableVw
    3.ビューのpostopenイベントでインスタンス生成
    sub PostOpen - set objVw = new objEditableVw(Source)
    4.列のプロパティで編集可能にチェック
%END REM
Class objEditableVw
  'Constructor
  Sub New( Source As NotesUIView )
    On Event InViewEdit From Source Call InViewEdit
  End Sub
 
  'Destructor
  Sub Delete
  End Sub
 
  'private function
  Private Sub InViewEdit(Source As NotesUIView, Requesttype As Integer,_
  Colprogname As Variant, Columnvalue As Variant, Continue As Variant)
    REM Define constants for request types
    Const QUERY_REQUEST = 1
    Const VALIDATE_REQUEST = 2
    Const SAVE_REQUEST = 3
    Const NEWENTRY_REQUEST = 4
   
    REM Define variables
    Dim db As NotesDatabase
    Dim doc As NotesDocument
    Dim caret As String
    Dim i As Integer
   
    REM Get the CaretNoteID - exit if it does not point at a document
    caret = Source.CaretNoteID
    If caret = "0" Then Exit Sub
   
    REM Get the current database and document
    Set db = Source.View.Parent
    Set doc = db.GetDocumentByID(caret)
   
    REM Select the request type
    Select Case Requesttype
       
      Case QUERY_REQUEST
        REM Reserved - do not use in Release 6.0
       
      Case VALIDATE_REQUEST
        REM Cause validation error if user tries to exit column with no value
        If FullTrim(Columnvalue(0)) = "" Then
          'Messagebox "You must enter a value",, "No value in column"
          'Continue = False
        End If
       
      Case SAVE_REQUEST
        REM Write the edited column view entries back to the document
        For i = 0 To UBound(Colprogname) Step 1
          Call doc.ReplaceItemValue(Colprogname(i), Columnvalue(i))
        Next
        REM Save(force, createResponse, markRead)
        Call doc.Save(True, True, True)
       
      Case NEWENTRY_REQUEST
        REM Create document and create "Form" item
        REM Write column values to the new document
        Set doc = New NotesDocument(db)
        Call doc.ReplaceItemValue("Form", "Main")
        For i = 0 To UBound(Colprogname) Step 1
          Call doc.ReplaceItemValue(Colprogname(i), Columnvalue(i))
        Next
        REM Save(force, createResponse, markRead)
        Call doc.Save(True, True, True)
       
    End Select
  End Sub
  

XpagesのJavascriptでテキストボックスの値を取得・変更する

サーバサイドJavaScriptではLotus Dominoの専用関数"getComponent"を使い
テキストボックスにアクセスする。クライアントサイドは"Dojo.byId"を使うとよい。

  • Server Side Javascriptの例
    //テキストボックスのIDを指定してインスタンスを取得
    var objTextBox = getComponent( "componentID")

    var strTextValue = objTextBox.getValue() //入力されたテキストを取得
    /*
    値を処理
    */

    objTextBox.setValue( strTextValue )  //テキストボックスの値を修正
  • Client Side Javascriptの例
    //テキストボックスのIDを指定してインスタンスを取得
    //"#{id:hogehoge}"と書いておくとサーバが動的にHTMLのIDに変換してくれる

    var objTextBox = Dojo.byID( "#{id:componentID}")

    var strTextValue = objTextBox.getValue() //入力されたテキストを取得
    /*
    値を処理
    */

    objTextBox.setValue( strTextValue )  //テキストボックスの値を修正

Enterを押すと処理を実行するテキストボックスをXpageで実装

ユーザからしてみるとキーワードをテキストボックスに入力した後に
実行ボタンをクリックしなくてもEnterを押すだけで処理が実行される
ほうが当然だが使いやすい。
( キーボード入力→マウス操作よりキーボード入力だけのほうが簡単)

実装は簡単で、 テキストコントロールのonKeypressイベントに
処理を書くだけである。但し、onKeypressイベントに処理を書くと
1文字入力されるごとに処理が実行されてしまうため、イベントの
クライアントサイドで"入力がEnterでない場合は処理しない"という
コードを追加する。

手順は以下のとおり。

  1. キーワード入力用のテキストボックスのonKeypressイベントに
    実行したいアクションを追加
  2. クライアントサイドのアクションの最初で以下のコードを実行
    (クライアントサイドのアクションの一番上に"Execute Client Script"を追加)

    If(thisEvent.keyCode != '13') {
        return false;
    }





Notes式での日付計算

  • 今日の日付は@Todayや@Nowから取得する。
  • 日付データから年や月を取得したい場合は@Year, @Month, @Dayを使う
  • ある日付から何日後(何日前)の日付データを計算したい場合は@Adjustを使う

例)
値 式
現在時刻 @Now
今日の日付 @Today
今日からx年yか月とz日後の日付 @Adjust( @Today; x; y; z; 0; 0; 0 )
Date1からDate2までの日数 ( Date2 - Date1 )/(60*60*24)

管理者権限のユーザにだけテキストを表示させる。

テキストの非表示式に以下を設定する。
@TextToNumber( @UserAccess( @DbName; [AccessLevel] ) ) < 6