Psalm

プログラマ向け技術メモ

JavaScriptからJSPに値を渡す

2008-08-29 20:22:57 | JavaScript
JSPからJavaScriptに値を渡すのはformを使えば簡単にできるが
逆は意外と難しい。
JavaScriptで値を取得してから一度、サーバにリクエストを投げないと
画面の再描画が行われないからだ。

が、JavaScriptでformの値を操作できるというところに着目すると
やや反則的ではあるが、サーバにリクエストを飛ばさなくても
JavaScript変数の値を表示することはできる。
つまりformを使うのである。
表示したい項目を

<input type="text" name="xxx" style="background-color: #f5f5dc; border: none;" readonly>

と書いておく。JavaScriptの中では

document.xxxForm.xxx.value= xxxxxx;

とセットしてやれば、セットした値がテキストフィールドに表示されるのだ。
ミソは、テキストフィールドをテキストフィールドでないかのように
見せてしまうところだ。
border:noneで境界線を消し、background-colorで背景色を揃えればOK。
あとはbodyにonLoadを設置して、ページ読み込みのタイミングで
JavaScriptから値を貰えば良い。

え?
ふざけんなって?
まあ、でも、一般の人はソースとか見ないだろうし
一応、表示はできてるヨ。(遠い目)




誰だ、こんな無茶振りしやがったやつは。

横スクロール禁止

2008-08-29 13:56:47 | CSS
ウィンドウの横スクロールバーを表示しない設定。
bodyだけに設定しても表示されてしまったので、htmlにも指定してみたら消えた。
謎。

html{
overflow-x : hidden;
overflow-y : auto;
}

body{
overflow-x : hidden;
overflow-y : auto;
}

注意点として、JavaScriptなどでscrollbars=noでウィンドウを開いていると
そちらが優先されてしまい、縦スクロールも表示されなくなる。
scrollbars=yesで開いてからCSSで指定すること。

JavaScriptでsleep

2008-08-29 12:52:23 | JavaScript
テーブル要素にカーソルを当てると、ちょっとしてから説明が表示されるような
画面を作りたかったので。
JavaScriptにはsleep関数はないので、代わりにsetTimeout()を使う。
要するにこんな感じ。

// 説明を表示する
function setCaption(id) {
var x = window.event.clientX;
var y = document.documentElement.scrollTop + window.event.clientY;
var windowHeight = document.body.scrollTop + document.body.clientHeight;
var element = document.getElementById(id);
var elementHeight = element.clientHeight;

// 説明表示位置
x = x + 10;
if( (windowHeight - y) <elementHeight ) { } else {
y = y-10;
}

viewCaption = setTimeout(
function dispCaption() {
element.style.left = x;
element.style.top = y;
element.style.display = "block";
setShim(element);
}, 500);
}

// 説明を隠す
function eraseCaption(id) {
clearTimeout(viewCaption);
var element = document.getElementById(id);
var shim = document.getElementById('shim');
element.style.display = "none";
shim.style.display = 'none';
}

マウスポインタのある位置を探して、その位置に説明が表示されるように
なっている。ちなみに0.5秒後にセット。
0.5秒経たないうちにポインタが外れた場合は、eraseCaptionを呼び出して
clearTimeoutで表示処理をキャンセルしている。

ポインタの座標の取得はブラウザに依存するので悩ましいところ。
このスクリプトではIE6.0しか考えていないので、その他のブラウザでは
動かないと思われる。笑
座標の取得のあれこれについては次回。

selectboxがメニューの上に表示される

2008-08-29 11:32:24 | CSS
カーソルを当てると表示されるようなメニューを作っていると
しばしば遭遇する現象。ただしIEのみ。
重なりが悪いのかと、z-indexを設定しても駄目。
それもその筈でselectboxを制御しているのはブラウザではなく
OSなのだそうだ。
ゲイツめ・・・!

何故かiframeはselectboxの上に表示できるので<div>の下にダミーの
<iframe>を入れ込めば良い。(shimって言うらしい)
bodyに<iframe scrolling="no" frameborder="0" id="shim"></iframe>
を記述しておいて、Javascriptのdisplay属性を切り替えるところに

setShim(element);

を追加。setShimの中身はこんな。elementで渡してるのは当然div。

function setShim(obj) {
var shim = document.getElementById('shim');

// サイズ、位置を合わせる
shim.style.left = obj.style.left;
shim.style.top = obj.style.top;
shim.style.width = obj.offsetWidth;
shim.style.height = obj.offsetHeight;
shim.style.display = 'block';
}

な感じ。ふむ。

使えるはずの関数が使えない!

2008-08-28 18:52:05 | JavaScript
オブジェクトでサポートされていないプロパティまたはメソッドです

document.form.reset()を呼んでいるのに怒られる。
なーぜーだーと悩むこと1時間。
ボタン名が「reset」だった。
ボタン名に予約語を使うなよ。
リセットボタンから変更したときに直すのを忘れたのだ・・・

こんなエラーで悩んだときはボタン名とかフォーム名を見直そう。
同じものがあったり、予約語使ってたりするはず。

メッセージリソースの使い方

2008-08-28 14:30:18 | Struts
キー org.apache.struts.action.MESSAGE に対するメッセージリソースが見つかりません

そのまんま、JSPで指定したキーがない。
チェックするべき点はいくつかある。

1、WEB-INF/classesの下にメッセージリソースファイルはあるか
 Eclipseくんが親切にもclean upしてくれてることがある。
 プロジェクトのクリーンをした場合は要チェック。

2、struts-config.xmlの記述
 こんな感じ↓
 <message-resources parameter="ApplicationMessageResources" key="messages" />
 意外と間違いやすいのが「parameter」はファイル名ではないという点。
 ここには拡張子はいらない。
 classesにディレクトリを掘ってる場合はディレクトリのパスから書くこと。
 keyを書かない場合はデフォルトが使われるらしいけど、動かなかった。

3、JSPの記述は合ってる?
 JSPから直接メッセージリソースを読み出すときは
 <bean:message bundle="messages" key="key名" />

 ActionMessagesを使ったときは
 <html:messages id="msg" bundle="messages" message="true">
  <bean:write name="msg" ignore="true"/>
 </html:messages>

 ActionMessagesのときは、keyを指定しない。
 ・・・微妙。
 struts-configでkeyを指定した場合は、bundle必須。

日本語ファイル文字化け

2008-08-28 14:27:32 | Struts
日本語ファイルダウンロードの文字化け問題。
IE ONLY。
簡単なのでずばり解決方法。

fileName = new String(fileName.getBytes("Shift_JIS"), "ISO-8859-1");

IEはUTF-8のファイル名を勝手にShift_JISに変換するので
予めShift_JISで送ればOK。

Tomcat起動エラー

2008-08-28 14:25:28 | Tomcat
Tomcat、6.0.18のWindows版で発生。
インストールして起動しようとすると

キー UserDatabase でユーザデータベースコンポーネントが見つかりません

というエラーを吐く。
confの下のtomcat-users.xmlの宣言が「encoding="cp932"」に
なっているのが原因。
「encoding="utf-8"」で問題解決。

Validatorが動かない

2008-08-28 14:10:04 | Struts
解決した。
実に馬鹿馬鹿しい理由だった。
validation.xmlで設定したメッセージが見つからないためだった。
もともと、struts-config.xmlには
<message-resources parameter="ApplicationMessageResources" key="messages" />
を指定していたのだが、ここにkeyを指定しているのが原因だったらしい。
validation.xmlに
<msg name="required" key="error.txUserId.required" />
という指定をすると、デフォルトのリソースからkeyを探してしまうのだ。
当たり前だ。
だって、リソースファイルの指定してないもん。
validation.xmlでリソースファイルの指定をすれば良いのだろうが
もう調べるのも疲れたので、validator用にデフォルトのリソースを
用意することにした。

さて、めでたくvalidatorは動いたのだが、予想していた問題が発生した。
Dispatchアクションを使って1つのアクションに複数の処理を
書いていると、Validateして欲しくない処理にまでValidateが
走ってしまうのだ。
ログアウトしてログイン画面を表示すると「ユーザIDを入力してください」って
ありえん。笑
はて、どうしてくれようか。
Mappingで無理矢理Validateありなしを分けてもいいんだけど
なんかスマートじゃない気がする。
普通はどうやるんだろう?

ApacheとTomcatの連携SSL有り

2008-08-27 20:56:49 | Apache
ApacheとTomcatの連携、mod_jk使用。
httpではJSPが表示できるが、httpsでファイルが見つかりませんのエラー。
原因は、httpd-ssl.confにJkMountを設定していなかったため。

モジュールのインストールとかは説明サイト参照。
httpd.confに以下を設定。

#tomcat-connectors
JkWorkersFile "/usr/local/apache2/conf/workers.properties"
JkLogFile "logs/mod_jk.log"
JkLogLevel info
JkLogStampFormat "[%a %b %d %H:%M:%S %Y]"
JkShmFile /logs/jk-shm
JkOptions +ForwardKeySize +ForwardURICompat -ForwardDirectories
JkMount /コンテキスト/* ajp13
JkMount /コンテキスト ajp13
JkMount /コンテキスト/pages/*.jsp ajp13

httpd-ssl.confに以下を設定。

JkMount /コンテキスト/* ajp13
JkMount /コンテキスト ajp13
JkMount /コンテキスト/pages/*.jsp ajp13

余計なものも書いてる気がするけど、今日のところは放置。
まだValidatorが動かないから、そっち優先。
なんとなくListenerが怪しい。
じゃなかったらFilterあたり。