GETメソッドのパラメータからxPageの挙動をコントロールする方法

他のページからジャンプしてきた時に、xPageの表示内容を変更したい時などに役立つ知識だと思います。

引用元のブログではGETメソッドのパラメータを使って表示するカテゴリのフィルタリングを行っています。

What this code does is before the page has loaded it looks at the URL and finds the location= part and if it exists it puts whatever the value is into a sessionscope variable called 'locationfilter'. Session Scope is a special scope where you can add variables that only last for the duration of the users session. As soon as they close their web browser the session scope variables are lost. There is also an Application Scope and a Page Scope that you can use to store these values. Heres how the code will look in the source view of your xpage, you can see the resource for the server side script library and the beforePageLoad script. As you get more advanced in XPages you may find yourself writing code directly in the source view.

引用元: Dec's Dom Blog :: Learning XPages Part 20 : Restricting The Repeat To A Single Category.

実際、GETメソッドのパラメータをbeforePageLoadイベントでチェックするのに

var cgi = new CGIVariables();
var param = cgi.getURLParam("Location");
if (param) {
if (param != "" )
sessionScope.locationfilter = param;
}

引用元: Dec's Dom Blog :: Learning XPages Part 20 : Restricting The Repeat To A Single Category.

というサンプルコードがあるのですが、Louts Notes/Domino 8.5に付属してくるディスカッションテンプレートにあるxpCGIVariables Script Libraryではcgi.getURLParam()というファンクションがないため上手く動きません。

そこで、taskjam.netからTaskJam V1.0とうテンプレートをダウンロードしてもってきます。

ここで、とても興味深かったのが、ブログで寄せられているコメントなんですが、

There is also a MUCH easier way to get the parameter instead of including the script library (although it's probably good that you showed that).

Use the global "context" JavaScript object:
context.getUrlParameter("Location")

という書き込みがあり、「context.getUrlParameter("Location")を使うともっと簡単にパラメータが取ってこれるよ」、と言っています。

で、ブロガーのDec自身が

I was thinking the exact same thing but have come to realise over the past couple of days that context.getUrlParameter() is not available in certain contexts, such as described above, and when programmatically getting the document id.

と返事してます。

実は自分も同じように

context.getUrlParameter("Location")

beforePageLoadイベントで使おうとしたんですが、なぜか値を取得しなくて、調べている内に彼のブログに辿り着きました。

興味ある方は、TaskJam V1.0テンプレートのxpCGIVariablesを覗いて頂ければ分かるとおもうのですが、

自分の結論としてはbeforePageLoadイベントでは

context.getUrlParameter()

はまだ値が格納されておらず、

facesContext.getExternalContext().getRequest()

には格納されている。

ということにしておきました :-)(自分はIBMの人間じゃないので間違っている可能性大です><)

さらに突っ込むと、同じコメント欄で

パラメータを渡すようなことをしなくてもリンク元でsessionScopeを使って予め設定しておけばいいんじゃないの?

というコメントも寄せられていて、

実際、自分もそれをまず試したのですが、結論としては(自分の環境では)動きませんでした。

リンクが同じデータベース内にあって、リンクをクリックされたとき、onclickイベントなどでsessionScopeを使って値を設定する場合は、正常に動作するとおもうのですが、

自分の場合は、他のデータベースに貼ってあるリンクからジャンプさせていたので、onclickイベントでsessionScopeの値を設定しても、リンク先のデータベースではsessionScopeの値を取得出来ませんでした。

ここで、悩んだのが、sessionScopeっていったい、どこの保存されているのか?

これも、自分の憶測と断って書かせてもらうと、

sessionScopeはUserがログインしている間保存されるが、その値自体は、定義したデータベースが持つ。なので、2つのデータベースで同じ変数のsessionScopeの値が違うということはありえる。

ということです。 検証しようと思えば簡単なので、時間が出来たときにやってみたいと思います。もしくは答えを知っているかたがおられたら教えてください(><)


【CakePHP】CakeFestで発表された「Media Plugin for CakePHP」のスライドを翻訳してみました | ECWorks Blog

ヴァージョン管理、Webroot以外でのアップロードファイルを保存というところに激しく興味を覚えたので、時間があるときに試してみたいと思い、とりあえずブックマーク。

【CakePHP】CakeFestで発表された「Media Plugin for CakePHP」のスライドを翻訳してみました | ECWorks Blog.


Lotus Notes 8.5.1のためLotus Expeditor ToolkitをEclipseに設定する時の注意点

Lotus Notes 8.5.1の埋め込みブラウザをSSO(Single-Sign-On)対応させるために、Lotus Expeditor Toolkitを使ったEclipseの設定をしようとしたのですが、Lotus Notes 8.5.1のVMが見当たらないので、ググッてみると以下のように構造に変更があったみたいです。

There's no longer a JRE stored in the plugin directory way down in the directory structure. Now you simply use the JVM in /jvm - simple right?!

This is nice but it means that your Eclipse configuration needs to be a little different JVM wise. I have therefore updated my Eclipse configuration guidelines to work with Notes 8.5.1.

引用元: Configure Eclipse 3.4 for Notes 8.5.1 - lekkimworld.com.

以前は、

<Notes install dir>/framework/rcp/eclipse/plugins/com.ibm.rcp.j2se.win32.x86_1.5.0.SR4-200707311521/jre

などとなっていたのですが、Lotus Notes 8.5.1では引用元の紹介にもあるように、

<Notes install dir>/jvm

に変更になっていました。
詳しくは Eclipse configuration guidelines to work with Notes 8.5.1に書いてあります。

これは、自分の設定した場合、

Lotus Notes 8.5.1 VM

なお、Lotus Expeditor Toolkitの設定自体は以下のリンク等にかいてあるのが参考になるとおもいます。

http://www.ibm.com/developerworks/lotus/library/expeditor-notes-sametime/
http://www.ibm.com/developerworks/lotus/library/expeditor-browser/


Notes ClientでxPageをオープンするための?OpenXPages

前回の投稿に続き、Lotus Notes 8.5.1からxPagesをComposite ApplicationにComponentsとして追加できる機能がついたので、早速試してみたのですが、Dblookupで他のデータベースからドキュメント情報を取得することは出来るけど、いざ、そのドキュメントをオープンさせようとしたときに、上手いこといかない、という問題に躓いたので記しておきます。

実際、なにが上手いこと行かなかったかというと、

  1. http:// のプロトコルでリンクを手前で生成しているような場合に、Lotus NotesはWebブラウザで開けようとするが、認証をもう一度求められてしまう。
  2. リンクを参照パスにしても、Proxyエラーや、404エラーとなってしまって開くことが出来ない。

で、どうするのかな~と思い調べてみると、答えはxPagesのブログに有りました。

?OpenXPage has been added as a supported parameters for the notes:// protocol to launch an XPage in the Notes client.

引用元: What's New For XPages in 8.5.1 - XPages Blog - The XPages Blog.

Lotus Notes 8.5.1 のxPagesの新しい機能紹介の投稿なんですが、

Notes ClientでxPageをランチするために notes:// プロトコルの?OpenXPages というパラメータをサポートしました。

ということらしいので、自分の探していたのはこれかも?!と思い試してみたら見事に動きました。

自分の例では、

Link Core ControlのOptionsで「Link type」を「URL」にして、以下のようなComputed Valueで上手くいきました。

return "Notes:///88257656006337D3/content.xsp?OpenXPage"

余談ですがxPagesをComposite ApplicationのComponentとして使いたい場合は、極力xPagesで用意されたCore Controls等を使って作っていくのが近道っぽいです。もちろんThemeなども。

自分はxPagesのSourceタブからhtmlコードやCSSファイルをガツガツ埋め込んでいっていたので、Componentにしたとき、ほとんど動かず、結局かなり作り直すはめになっちゃいました・・・(涙)

追記:12月16日2009年
Domino Designere URLs for xPgages というエントリーがDomino Designer Wikiに追加されてます。

http://www-10.lotus.com/ldd/ddwiki.nsf/dx/Domino_Designer_URLs_for_XPages


xPages Component(Notes 8.5.1)でDblookup()使用時の注意点

xPages Componentを使ってLotus Notes Client 8.5.1上でxPagesを表示させる新しい機能を試したときに、自分のxPagesを以下のようにチューニングしないと上手く動かなかったので、注意が必要になります。

症状

xPagesをブラウザで見るとうまく表示されるのに、Notes Clientで見るとDblookup()でエラーが発生する。

状況

サーバのComposite Applicationを直接開いたときにエラーが発生するが、ローカルレプリカを開いたときは発生しない。

原因

@Dblookup()の1st パラメータの dbName が正しく設定されていなかった。

詳細

以下のコードではDblookup()が正常に値を返しません。

<![CDATA[#{javascript:var db = ["" ,"folder/cms.nsf"];
var viewName = "(vwTestLookup)";
var key ="Keyword";
var value = "";
var value = @DbLookup( db , viewName , key , 6 );
var retValue = "";
if(!@IsError(value)){
for( var i=0; i< value.length && i < maxEntry; i++){
retValue += "<li>"+value[i]+"</li>";
}
}
else{
retValue = "Error happened in DbLookup(). ";
}
return "<ul>"+retValue+"</ul>";}]]>

原因は一行目の

var db = ["" ,"folder/cms.nsf"];

にありました。 Webブラウザから見る場合はサーバ自身のfolder/cms.nsf データベースを参照してくれるので、問題なく期待した動作をするのですが、Notes Clientで開くと、ローカルPCのfolder/cms.nsfを参照しにいってしまうため、レプリケーションがない環境ではエラーが発生してしまいます。

対処法

Dblookup() のdbName Arrayの 1st elementにサーバネームを渡すようにする。

var db = [database.getServer() ,"folder/cms.nsf"];

としてやれば、どちらも動くようになります。

ちなみに、xPages Componentと同じDBを参照する場合は、

var db = @DbName();

としてやるだけでOKです。

複雑な処理をしている既存のxPagesをComponentで動かす言った場合、このようなケースではただエラーが発生するので、丁寧なコードを書いていないとデバッグ作業は思いのほか時間がかかってしまいます。


mod_rewrite サンプル集のメモのメモ

使いこなせばスイス製のアーミーナイフのような切れ味を発揮すると説明されている、apacheのmod_rewrite。

わかっちゃいるけど、正規表現と同じで、いつも必要なところだけサラッとかっさらって、いつまでも使い方をちゃんと理解していない。 いつか腰をすえて習得しないといけないなぁ~と思ってはいるんだけど・・・

ってことで、サンプルのメモ

mod_rewrite サンプル集

mod_rewrite はすげー色んなことができて楽しい。

でもけっこう難しい。

そこで、オイラ用メモで簡単なサンプル集をば。

引用元: mod_rewrite サンプル集/楽.


どのフォルダにドキュメントが格納されているかを知る @WhichFolders

自分の使っているLotus Notes 8.5.1のメールで「All Documents」にフォルダ情報が表示されているのが不思議で、Designerで($All) view を開いてみたら「Folder」columnに@WhichFolders ってのが記載されていました。

@WhichFoldersなんて便利なコマンドあったっけ?と思ってググってみました。

Knowing which folder a document is in - @WhichFolders

Steve Castledine 8 September 2008 09:28:53

Sometimes people don't see the release notes (I'm not saying this is definitely in them), or new formula etc can be forgotten, but a nice new formula in 8.5 was @WhichFolders which can be used to determine, surprisingly, which folder the current document is in.

To see it in action, it was added to the mail template, all documents view.

Funny, I'm not even sure this made it into the designer help db, I will have to check.

引用元: Knowing which folder a document is in - @WhichFolders.

Lotus Notes 8.5から出来たFormula だったんですね。
しかもドキュメントにはなっていないみたい。 隠しコマンド?

ちなみに、@WhichFolders を調べているときに発見した別のブログ「Interesting undocumented formulas」( http://lotus-blogs.blogspot.com/2009/01/interesting-and-undocumented-formulas.html )

にもいろいろと紹介されています。

さて、こんな便利なコマンドが@Formulaには用意されたみたいなんですが、自分への命題は「Lotus Notes C API」を使って同等の機能を実装できるか?

これが、簡単なようで上手くいかない。 IMAPコマンドをメールDBに対して掛けてやると$FolderRefが埋め込まれるのでこれによってフォルダ階層を割り出すことが可能になるのだが、もうちょっとスマートな方法を模索中・・・

と、またまた、ためにならない投げっぱなしな投稿でおわり。


CakePHPでWordpressにアクセス

If you’re like me, you’ve fallen in love with CakePHP. It’s a tight bit of code that’s easy to use and once you have your application using it, easy to maintain and add new features. For my recent redesign of my freelance site www.systemsevendesigns.com I wanted to be able to display my 3 most recent blog posts on the homepage. Both sites run off of different databases, so how do we do it with Cake? (This post assumes you know a little bit about Cake, but is not too terribly complex. Cake newbies welcome!)

引用元: WebDevKungfu » Blog Archive » Accessing WordPress with CakePHP | Web Development, Web Design, Coldfusion, Rails, Ruby on Rails, PHP blog.

仕事の合間に、ふと思いたってググッてみた。

やっぱみんな考えることは同じだなぁ~。

ちょっと前にWordpressで動くフリーマケットとか購入したし、これからどんどんインテグレートしていこう。

最近、CakePHP用の掲示板をPluginとして取り入れたばかりだけど、ちゃちゃっと別システムを取り入れれるCakePHPの柔軟性がステキすぎです。(といってもCakePHPのACL周りで結構書き換えに工夫が必要だったけど)

ってことで、今回も自分用メモ。。。 あしからず。


CakePHP1.2を使った多言語サポート対応時の覚書き

CakePHP 1.2を使った国際化を実装する際に調べて役に立ったサイトを(主に自分のために)纏めておきます。

1)いつも、人知れずお世話になっているサイト「CakePHPのおいしい食べ方」にとても分かりやすい解説がありました。

CakePHP1.2の簡単国際化

CakePHP1.2のbakeで自動生成した画面は、画面に表示される文字列が__('文字列') で囲まれています。これは、簡単に多言語翻訳ができるように配慮されているからです。

引用元: CakePHP のおいしい食べ方: CakePHP1.2の簡単国際化.

2)次に、言語の切り替えをマニュアルでするためのリンクの作り方では、このサイトの情報が役に立ちました。

To better understand the goal and why some things were done the way they were, I’ll summarize the requirements:

1. The app has to support two languages or more (in this case English and Russian)

2. Default language is English

3. The language switching is based on a URL param

4. The URL format should be: example.com/eng/controller/action

5. Language choice should persist in the session and a cookie

引用元: CakePHP URL-based language switching for i18n and l10n (internationalization and localization) « nuts and bolts of cakephp.

なお、自分のサイトでは

  1. 多言語サポートとして英語と日本語をサポート
  2. デフォルトの言語は日本語
  3. 言語はURL paramで変更できる
  4. URLフォーマットは: example.com/ja/controller/action といった感じ
  5. 好みの言語はセッションとクッキーで保持される。

としています。用はWordpressのプラグインで「qTranslate」という便利なプラグインがあるが、同じことをしたい!

なので、こちらの例ではConfigフォルダの中のroutes.phpで以下のように

Router::connect('/:language/:controller/:action/*',
                       array(),
                       array('language' => '[a-z]{3}'));

としていますが、自分は[en]と[ja]など2文字がよかったので以下のようにしました。

Router::connect('/:language/:controller/:action/*', array(), array('language' => '[a-z]{2}'));

で、後は引用元にもあるように、_setLanguage()をapp_controller.phpの中に記述して、beforeFilter()関数から呼び出すようにします。

	function _setLanguage() {

	    if ($this->Cookie->read('lang') && !$this->Session->check('Config.language')) {
	        $this->Session->write('Config.language', $this->Cookie->read('lang'));
	    }
	    else if (isset($this->params['language']) && ($this->params['language']
	             !=  $this->Session->read('Config.language'))) {     

	        $this->Session->write('Config.language', $this->params['language']);
	        $this->Cookie->write('lang', $this->params['language'], null, '20 days');
	    }
	}

さらに、app_helper.phpに以下のurl()関数をオーバーライドする関数を作ってお膳立ては出来上がり。

	function url($url = null, $full = false) {
        if(!isset($url['language']) && isset($this->params['language'])) {
          $url['language'] = $this->params['language'];
        }     

        return parent::url($url, $full);
	}

最後に、肝心のリンクを作ります。
自分はviews/layouts/default.ctpにリンクを作りました。

<p>
    <?php echo $html->link('English', array('language'=>'en')); ?>
</p>
<p>
    <?php echo $html->link('Japanese', array('language'=>'ja')); ?>
</p>

で、出来上がり。
example.com/en/controller/action
で言語を英語に切り替えた後、
example.com/controller/action
でアクセスしても、選択言語が保持されているのを確認します。

自分が作っているCakePHPサイトで挙動が確認できます。
http://labeauty.getmycity.com
(実はまだ多言語サポート対応中のためFooterの一番下にEnglish、Japaneseの隠しリンクがあるw)


xPagesのTabbed PanelをPartial RefreshでAjax化させよう

xPagesのTabbed Panelってとても便利だと思うのですが、デフォルトだと、クリック毎にページ全体を読み直すのでかっこ悪い。
そこで、Partial Refreshを使ってAjax化させてみました。

<xp:panel id="container">
<xp:tabbedPanel id="tabbedPanel1">
<xp:this.selectedTab>
<![CDATA[#{javascript:(null == sessionScope.selectedTabId) ? "tabPanel1" : sessionScope.selectedTabId}]]>
</xp:this.selectedTab>
<xp:tabPanel label="Tab1" id="tabPanel1">
Tab1のコンテンツが入ります。
<xp:eventHandler event="onclick" submit="true" refreshMode="partial" refreshId="container">
<xp:this.action>
<![CDATA[#{javascript:sessionScope.selectedTabId = "tabPanel1"}]]></xp:this.action>
</xp:eventHandler>
</xp:tabPanel>
<xp:tabPanel label="Other" id="tabPanel2">
Tab2のコンテンツが入ります。
<xp:eventHandler event="onclick" submit="true" refreshMode="partial" refreshId="container">
<xp:this.action>
<![CDATA[#{javascript:sessionScope.selectedTabId = "tabPanel2"}]]>
</xp:this.action>
</xp:eventHandler>
</xp:tabPanel>
</xp:tabbedPanel>
</xp:panel>

ここでは、

1)各Tabの中にonclickイベントを作成。
2)Partial UpdateのElementに親タグのID"container"をRefreshIDに指定。
3)onclickイベントの中で、各タブごとに、selectedTabIdを以下のように指定する。
sessionScope.selectedTabId = "tabPanel1"

しかし、これをデザインのプロパティからやろうとすると、操作が難しい(というか出来ない)ので、ソースをガシガシ書いていくのが吉です。

ちなみに、自分の環境では8.5.0までは "_10f.push is not a function"のエラーが出て上手く動いていなかったので、XPages Blogにある通り8.5.1にアップデートしたら問題は解消されました。

Partial refresh and Firefox 3.5, Safari, Opera on 8.5.0 - XPages Blog - The XPages Blog

I just stumbled upon this post in the 8.5 forum: it describes the known problem that partial refreshes on a Domino 8.5.0 server causes the message "_10f.push is not a function".

This happens with Firefox 3.5, Safari 4, Opera and I believe in IE 8, too.There is no workaround at least none I'm aware of but using full refreshes all the time.But: the solution is underway! This is fixed in the upcoming 8.5.1.

引用元: Partial refresh and Firefox 3.5, Safari, Opera on 8.5.0 - XPages Blog - The XPages Blog.