- 2004/10/07 より良い方法があった
-
2004/10/11 「文字コード問題解決へのアプローチ」 続編をアップロードしました。
Iframe を利用して複数の文字コードをformからCGIへ送信する方法
任意の文字コードを JavaScript を使って CGI へ送信する良い方法を見つけました。
インラインフレームを使う方法ですがこの方法なら下記の IE での問題点も全て解決できます。
- 目的
Shift_JIS または任意の文字コードで書かれたHTMLによるフォームからCGIへ送信する文字コードをJavaScriptを使って自在に変換する。
たったこれだけの事ですが、適切に変換する方法を探し当てるまでに3ヶ月程かかってしまいました。
実はこの検索サイトもどきを作成している最中でも、この程度の問題は簡単に解決するのではないかと安易に考えていました。
所がいくらWebで検索しても情報が無いんです。
これには全く困ってしまいました。
まあ、何とか自力で解決する事が出来ました。
大勢の人の中には同じ様な問題を抱えている方が居るのではないかと思い、参考程度に書いてみました。
- フォームから送信される文字コード
日本語のウェブサイトで使用されている charset は主に下記のコードが一般的です。
- Shift_JIS シフト JIS(MSの呪縛?) *一般的に最も多い
- EUC-JP UNIX 内部コード *ポータルサイトなど
- ISO-2022-JP JIS コード *たまにある
- UTF-8 ユニコード *Googleなどの複数言語に対応する検索サイト
フォームから送信される文字コードはファイルへ保存(ウェブサーバーにアップロード)した時の文字コードと
そのページの<head>...</head>間にあるメタタグ
<meta http-equiv="Content-Type" content="text/html; charset=Shift_JIS">
の charset=Shift_JIS で指定した文字コードにより決まります(この場合は Shift_JIS)
charset=Shift_JIS ならフォームから送信される文字コードは Shift_JIS になり、
charset=EUC-JP を指定すればフォームから送信される文字コードも EUC-JP になります。
当然ですが charset とウェブサーバー上の文字コードは一致させておかなければなりません。
文字コードに付いてはここで私が浅知恵を披露するよりも遥かにすばらしい解説をされているサイトがありますので、
参考にされるとよいでしょう。
日本語と文字コード
二千年紀の文字コード問題
文字コードに関する興味深い連載記事を見つけましたのでリンクしておきます。
小形克宏の「文字の海、ビットの舟」――文字コードが私たちに問いかけるもの
- 同じページから複数の文字コードを送信する
フォームから送信する場合ですと Shift_JIS のページからでも EUC-JP や UTF-8 など任意の文字コードを送信する事が出来ます。
ブラウザが Netscape Navigator(以降ネスケと略す)の場合は form の属性 Accept-charset="****"
に符号化方式を指定するだけで上手く行くようです。
<form method="***" action="http://***" Accept-charset="euc-jp">
最後のAccept-charset="euc-jp" にエンコードの種類を指定するだけでSubmitの時EUC-JPに変換され URI エンコードされたコードが送信されます。
但し Internet Explorer(以降IEと略す)でこの方法は使えません。
試してみましたが Accept-charset="****" での指定はまったく無視されています。
だからと言って利用者の多いIEを切り捨てるわけには行きませんし困った・・・
- IEでの解決策
実はとても簡単な方法で解決する事が出来たのですが、思いつくまでにはかなりの時間がかかってしまいました。
IEでの解決方法はサブミットの瞬間だけページ全体の charset の指定を入れ替えると言う方法です。
form の Submit は使わず JavaScript の submit() を使います。
シフト JIS ページのフォームからターゲットの CGI に EUC-JP で送信したいのであれば、サブミットする直前に
document.charset='EUC-JP'; を記述し
★.submit();
サブミット終了後に
document.charset='shift_jis'; と記述し元に戻せば良いのです。
任意のコードのページで利用したければ
org_chr=document.charset; で元のコードを取得し、変数 org_chr に保存
document.charset='EUC-JP';
★.submit();
サブミット終了後に
document.charset=org_chr; と記述し書き戻した方が汎用性はあるでしょう。
切り替え中に多少画面がゆれる場合も有りますが、何とか許容出来る範囲でしょう。
IE の JScript には不可解な点が沢山あります document.charset='***'; 何でこんな事が出来るのか理解できませんし MSの
MSDN ライブラリ
JScript
等でも見つかりません。
取りあえず問題なく使えるようですし、ネスケでもエラーにはなりません。
- IEでは解決出来ない重大な欠点
検索窓と同一ページに結果を表示させる事が出来ません。
正しく言うと結果を表示出来ないのではなくブラウザの戻るボタンを押した場合に元のページが文字化けを起こすと言う事です。
リロードボタンをクリックすれば元には戻りますが、これでは勘弁してくれー状態ですね。
document.charset='EUC-JP';
★.submit(); ← この時点で呼び出し側の JavaScript 終了?
document.charset='shift_jis'; ← 実行されず charset='EUC-JP' のまま終了。
当サイトではこの問題を避ける為に下記の様な JavaScript を使い検索結果は別窓で表示する様にしています。
function sarch(formx) {
swin=window.open("","swin","");
formx.target="swin";
formx.submit(); swin.focus();
}
所詮 JavaScript では限界も有ると言うことです。
CGI が使える環境でサーバーの負荷を気にしないのであれば途中に CGI を経由し文字コードの変換をさせれば問題はすべて解決するのですが・・・
- サンプル
一応 Internet Explorer6.0 と Netscape 7.01 では動作確認をしていますが他のブラウザでは ? です。
もし、他のブラウザをご利用の方で、「○○では駄目よ」って連絡してくださる方がいらっしゃいましたら大変ありがたく思います。
と言っても特に対処法がある訳では有りませんが...
サンプルの検索窓から適当な日本語で検索してブラウザのアドレスバーに表示される ? 以降の %○○ を比較すると違いがわかると思います。
実際の所Google等は大抵の文字コードは正しく処理してくれるはずですので問題にはならないと思います。
2004/04/22 Googleの仕様変更があり文字コードを指定しない場合は UTF-8 と解釈されてしまい文字化けが発生します。
詳細: Google検索の文字化け対策
Googleに明確な文字コードで送信したい場合は
<input type="hidden" name="ie" value="Shift_JIS"> とか
<input type="hidden" name="ie" value="UTF-8"> を指定を指定する必要があります。
-
ページ先頭
- 上記検索フォームのソース
UTF-8 ユニコードで Googleを検索
<form name="f_google" method="GET" action="http://www.google.co.jp/search" target="smp" onSubmit="return false;" Accept-charset="UTF-8">
<input type="text" name="q" value="" size="31">
<input type="button" value="UTF-8" onClick="org=document.charset; document.charset='UTF-8'; document.f_google.submit(); document.charset=org;">
<input type="hidden" name="ie" value="UTF-8">
<input type="hidden" name="oe" value="UTF-8">
<input type="hidden" name="hl" value="ja">
</form>
EUC-JP UNIXコードで Yahoo! オークションを検索
<form name="f_yahoo" method="GET" action="http://search.auctions.yahoo.co.jp/jp/search/auc" target="smp" onSubmit="return false;" Accept-charset="EUC-JP">
<input type="text" name="p" value="" size="31">
<input type="button" value="EUC-JP" onClick="org=document.charset; document.charset='EUC-JP'; document.f_yahoo.submit(); document.charset=org;">
<input type="hidden" name="auccat" value="0">
<input type="hidden" name="alocale" value="0jp">
<input type="hidden" name="acc" value="jp">
</form>
Shift_Jis シフトJISで 窓の杜を検索
<form name="f_mado" method="GET" action="http://search.impress.co.jp/cgi-bin/forest/library/namazu.cgi" target="smp" onSubmit="return false;">
<input type="text" name="query" value="" size="31">
<input type="button" value="Shift_Jis" onClick="document.f_mado.submit();">
<input type="hidden" name="whence" value="0">
<input type="hidden" name="sort" value="score">
</form>
- UTF-8なら他の方法も可能
UTF-8に対応する場合は JavaScript の encodeURIComponent でクエリー部分のみ変換してしまう手もあります。
この方法だと画面が揺れる事も有りません。
下のGoogle検索の例では submit ボタンを onClick で取得し定型パラメータの文字列を引数にして JavaScript の関数を呼び出すようにしてみました。
全部 onClick="**" 内に記述する事も可能ですが一行がダラダラと長くなりますので汎用性のある関数を呼び出すようにしています。
多分下手な説明よりもソースをご覧になった方が早いと思います。
フォーム
<form name="smp" action="" onSubmit="return false;">
<input Type="text" name="txt" size="31" value="">
<input type="submit" value="UTF-8" onClick="op('http://www.google.com/search?ie=UTF-8\x26oe=UTF-8\x26hl=ja\x26num=20\x26q=');">
</form>
JavaScript
<script LANGUAGE="JavaScript" Type="text/javascript">
<!--
function op(adrs){
va=encodeURIComponent(document.smp.txt.value);
va=adrs + va;
window.open(va,"smp","");
}
//-->
</script>
エンターキーも使える様にしたい場合はこんな感じでどうですかね?
<input Type="text" name="txt" value="" onKeyPress="if(event.keyCode == 13) op('***');">
- 最後に 検索サイトの作り方?
ここまで公開したら誰でも JavaScript だけで非統合型のメタ検索もどきを作る事ができるのです。
後は検索窓を一つにまとめて検索ボタンを適当に配置するだけです。
検索窓を一つにまとめるのは簡単だと思いますので、興味のある方は自分なりの方法で試して見ると良いでしょう。
- おまけ
JavaScript で新しいウインドウを開いてテキストを書き込む事は良くある事だと思います。
この場合新しく開かれたウインドウの文字セットはユニコードになります。
これを回避し任意の文字コードを使いたい場合は document.write("○○○"); の前に
document.charset="Shift_Jis"; などと記述すれば IE ではうまく行きます。