HTTPサーバーとWeb開発

50. 5250エミュレーター機能を実現する JavaScript5250

基幹業務を Web化するにあたり 5250エミュレータ画面の機能を踏襲したいという要望がある。
HTMLインターフェース上では 5250とは別物と考えなくてはいけないのだが、長年5250画面に
慣れ親しんできたユーザーによっては妥当性検査やField-Exit, 機能キーなどの機能を
どうしてもWebでも実現させたいという希望がある。

5250機能を実現するJavaScript では米国誌 iSeriesNetwork でも紹介記事があるが
ここでは弊社が EnterpriseServer のフレーム・ワークとして開発した JavaScript5250
紹介する。
JavaScript5250 は iSeriesNetwork での紹介記事よりも拡張された機能を持っている。
これらの機能はまた http://www.officequattro.com「ワーク・ショップ」の「受注入力」
というサンプルが公開されているので実際に動作を体験することもできる。

JavaScript5250 一覧

alertmsg.js ・・・ エラー・メッセージの表示
caret.js ・・・ キャレット(カーソル)の制御
cookie.js ・・・ クッキーの操作
fkey.js ・・・ 機能キーの処理
login.js ・・・ ログイン操作
rightadjust.js ・・・ 右寄せ
valckeck.js ・・・ 入力妥当性検査
LOGIN.HTM ・・・ ログ・イン

alertmsg (エラー・メッセージの表示)

【 構文 】

alertmsg(フォーム番号, エレメント番号)

【 組み込み 】
<script language="JavaScript" src="/AS400-NET.USR/LIB5250/alertmsg.js"></script>
【 引数 】
フォーム番号・・・エラー・メッセージ(ALERTMSG) が
組み込まれているフォーム番号の数字
エレメント番号・・・エラー・メッセージ(ALERTMSG) が
組み込まれているエレメント番号の数字
【 関数 】
function alertmsg(m,n){
    if (document.forms[m].elements[n].value == "########################################")
    return(true);
    else alert(document.forms[m].elements[n].value);
}
【 解説 】

alertmsg は JavaScript の alertメソッドによってエラー・メッセージ
をダイアログBOX として表示します。

HTML でのエラー・メッセージは一般的にはエラー・メッセージを
埋め込んだHTMLを戻す方法が普及していますが、Windows-App
のようにダイアログによってエラー・メッセージを表示すれば視認性も
高まり、ユーザーによってよりわかりやすいものとなります。

alertmsg関数は フィールド:ALERTMSG (エラー・メッセージ)
値が埋め込まれたときにだけalertメソッドでエラー・メッセージを
表示します。
ALERTMSG に値が埋め込まれていない場合は alertmsg関数は何も行わずに true を返して終了するだけです。
この機能によってCGI はエラーがあったときにだけ

CALLP     SETFLD('ALERTMSG': '得意先コードの誤りです。')

のようにALERTMSGフィールドの値を SETFLDプロシージャーに
埋め込んでやれば、alertmsg関数によってエラー・メッセージが
表示されます。
つまりエラーが発生していないような状況であっても、
HTMLテンプレートにはつねにalertmsg関数が含まれているように
設定しておきます。
エラーの無いときはalertmsg関数もブラウザへHTMLテンプレートの
一部として送出されますが、ALERTMSGフィールドに値が
埋め込まれていないので、エラーは表示されることはありません。
エラーがある場合でもエラーが無い場合でも同じHTMLテンプレート
を使用することができることになります。
このことはHTMLテンプレートの扱いを簡単にすると同時に保守を容易にします。

HTMLテンプレートでは

<BODY OnLoad="alrtmsg(0,0)">
    :
<form name=FLAG>
<FLD NAME=ALERTMSG><INPUT TYPE="HIDDEN" NAME="ERRMSG" VALUE=########################################></FLD>
</form>
    :
</BODY>

のようにしてALERTMSGフィールドを定義しておいてください。
この ALERTMSG が定義されている位置を

<BODY OnLoad="alrtmsg(0,0)">

のようにしてフォーム番号 (この場合は最初のフォームであるので、
その値は 0)
、エレメント番号 (この場合はフォーム中の最初の
エレメントであるので、その値は 0)
で指定します。

フォーム番号とはHTML内に定義されている <form>...</form>
0 から始まるフォームの順序番号のことです。
またエレメント番号とはフォームに含まれるオブジェクトで、
入力ボックスやコンボボックス、<INPUT ....>で指定される入力要素
0 から始まる順序番号のことです。

次の例をご覧下さい。このHTMLはそのままテンプレートとして
出力しても、メッセージは表示されませんが、CGI の中で

CALLP     SETFLD('ALERTMSG': '得意先コードの誤りです。')

としてセットしてから出力すると

が表示されます。

<html>
<head><title>alertmsgサンプル</title>
<script language="JavaScript" src="../LIB5250/alertmsg.js"></script>
</head>
<body OnLoad="alertmsg(0,0)">
<center>
<h1> alertmsgサンプル </h1>
</center>
<form>
<p>フィールドALERTMSG に SETFLD で値を埋めて出力するとエラーが表示されます。</p>
<FLD NAME=ALERTMSG><INPUT TYPE="HIDDEN" NAME="ERRMSG" VALUE=########################################></FLD>
<input type="TEXT" width="30">
<br>
<br><input type="button" onClick="MyScript(document.forms[0].elements[0])" name="click" value=" O K ">
</form>
</body>
</html>

caret.js (カーソル制御)

【 構文 】
カーソル位置に続く文字列の削除・・・removeAfterCursor(エレメント)
入力欄をフォーカス・・・setFocus(フォーム, エレメント)
フォーカスと同時に文字列を選択状態にセット・・・setSelectFocus(フォーム, エレメント)
【 組み込み 】
<script language="JScript" type="text/jscript" src="/AS400-NET.USR/LIB5250/caret.js"></script>
【 引数 】
フォーム・・・入力欄のあるフォーム
エレメント・・・入力欄のあるフォーム・エレメント
【 関数 】
<!--
// removeAfterCursor : カーソル位置に続く文字列の削除
function removeAfterCursor(elem)
{
        if ( elem.isTextEdit )
		elem.caretPos = document.selection.createRange();
	if ( elem.isTextEdit && elem.caretPos ){
		var bookmark = unescape( "%u0002" );
		var orig = elem.value;
		var caretPos = elem.caretPos;
		caretPos.text = bookmark;
		var i = elem.value.search( bookmark );
		elem.value = orig;
		if ( i!=-1 ) elem.value = orig.substring(0, i);
	}
}
// setFocus : 入力欄のフォーカス
function setFocus(f,e){
	document.forms[f].elements[e].focus();
}
// setSelectFocus : フォーカスと同時に文字列を選択状態にセット
function setSelectFocus(f,e){
	document.forms[f].elements[e].focus();
	document.forms[f].elements[e].select();
	
}
// -->
【 解説 】

caret.js はカーソル制御のための機能を提供します。
最初に caret.js の組み込み指定は language が JavaScript
ではなく JScript になっていることにご注意ください。
JScript とは Microsoft社が IE (InternetExploror) で
提供している JavaScript の拡張版です。
JavaScript ではカーソルの位置を検出することができませんので
JScript を使用しています。
よって carret.jsは IE以外のブラウザでは使用することはできません。

removeAfterCursor関数(カーソル位置に続く文字列の削除)

removeAfterCursor関数は入力のためのテキスト・ボックスに
カーソル(キャッレット)がある場合、そのカーソル以降の文字列をすべて削除します。

これは5250エミュレータにおける入力欄での Field-Exitキー
操作を実現 するものです。
RemoveAfterCursor の引数には 

RemoveAfterCursor(document.forms[0].elements[0]); 

のようにしてエレメント・オブジェクトを指定します。

次の HTML の例はテキスト・ボックスが表示されるだけの
HTML ですが、何か文字列を入力して文字列の途中に
カーソルをセットしてから Enterキーを押すとカーソルに続く
後続の文字列がすべて消去されます。

-------------------------------------------------------------------------------------------
<html>
<head><title>TEST</title>
<script language="JScript" type="text/jscript" src="/AS400-NET.USR/LIB5250/caret.js"></script>
<script language="JavaScript">
<!-- 
window.document.onkeydown = doKeys;
function doKeys( key ){
	var k =  window.event.keyCode;
	if ( k == 13 )	{
		RemoveAfterCursor(document.forms[0].elements[0]);
                return false;
	}
	return true;
}
// -->
</script>
</head>
<body>
<form>
<input type="TEXT" width="30">
<br>
<br><input type="button" onClick="MyScript(document.forms[0].elements[0])" name="click" value=" O K ">
</form>
</body>
</html>
-------------------------------------------------------------------------------------------

setFocus関数 (入力欄のフォーカス)

setFocus関数は HTMLが最初に表示されたときに明示的に
カーソルをセットしてフォーカスされた状態にします。

【 例 】

setFocus(document.forms[0].elements[0]);

setSelectFocus関数(フォーカスと同時に文字列を選択状態にセット)

setSelectFocus関数は入力欄をフォーカスするだけではなく、
入力欄の文字列を選択状態にセットします。

【 例 】

setSelectFocus(document.forms[0].elements[0]);

cookie.js (クッキーの操作)

【 構文 】
フォームに入力された内容のクッキーへの保存・・・setcookie()
クッキーの読み取りとフォームへの入力・・・getcookie()
【 組み込み 】
<script language="JavaScript" src="/AS400-NET.USR/LIB5250/cookie.js"></script>
【 引数 】

なし

【 関数 】
<!-- 
cookieArray = new Array();
function setcookie(){
	cookieArray[0] = document.forms[0].elements[0].value;
	cookieArray[1] = document.forms[0].elements[1].value;
	cookieArray[2] = document.forms[0].elements[2].value;
	cookieArray[3] = document.forms[0].elements[3].value;
	cookieArray[4] = document.forms[0].elements[4].checked;
	cookieArray[5] = document.forms[0].elements[5].value;
	exp=new Date();
	exp.setTime(exp.getTime()+1000*60*60*24*3650);
	checkstrings = escape(cookieArray[0]);
	for (i=1;i < cookieArray.length;i++){
		checkstrings += "%00" + escape(cookieArray[i]);
	}
	document.cookie = "as400_net_com=" + checkstrings + "; expires=" + exp.toGMTString();
}
function getcookie(){
	cookielength = document.cookie.length;
	cookieArray = document.cookie.split("; ");
	checkstrings = "";
	i = 0;
	while (cookieArray[i]){
		if (cookieArray[i].substr(0,14) == "as400_net_com="){
			checkstrings = cookieArray[i].substr(14,cookieArray[i].length);
			break;
		}
		i++;
	}
	cookieArray = checkstrings.split("%00");
	if (cookieArray[0]) document.forms[0].elements[0].value = unescape(cookieArray[0]);
	if (cookieArray[1]) document.forms[0].elements[1].value = unescape(cookieArray[1]);
	if (cookieArray[3]) document.forms[0].elements[3].value = unescape(cookieArray[3]);
	if (cookieArray[4] == "true") {document.forms[0].elements[4].checked = true;
		document.forms[0].elements[2].value = unescape(cookieArray[2])};
		else {document.forms[0].elements[4].checked = false;
		document.forms[0].elements[2].value = "";}
	if (cookieArray[5]) document.forms[0].elements[5].value = unescape(cookieArray[5]);
	
	
}
// -->
【 解説 】

クッキーとはWebサーバーからブラウザーを通じて、訪問者のPCに
一時的にデータを書き込んで保存させるしくみ(または保存された
データそのもの)を指します。

クッキーを使用すると、訪問者が入力した情報などが記録され、
次回以降そのサイトを訪問した際は、記録された情報をもとに
ページが表示されます。
例えば掲示板やショッピングカート等で多く利用されており、掲示板
では投稿する際に名前やメールアドレスなどの固定情報を
初回訪問時にクッキーとして保存し、再訪問時にこの情報を初期値
として自動表示させる、というものです。
訪問者としては、入力の手間が省けて効率的といえます。

ブラウザーを通じてPCに格納されたクッキーは次の場所で確認する
ことができます。
(Windows2000/XP環境でのInternetExplorerの場合)

\Documents and Settings\ログオン名\Local Settings\Temporary Internet Files\MyCookie
\Documents and Settings\ログオン名\Cookies\MyCookie.txt

あるいはInternetExplorerの [ツール]−[インターネット オプション]−
「全般」タブのインターネット一時ファイル−「設定」ボタン−
「ファイルの表示」でも確認できます。

クッキーの中身はこのようになっています。

as400_net_com
192.168.1.1%00QUSER%00%00CONSOLE%00false%000080
192.168.1.1/AS400-NET.USR/PROJECT/LOGIN/
1088
2041707776
30347869
3262962256
29613614
*

クッキーは便利な反面、危険性も孕んでいます。例えば、一台の
PCを複数のユーザーが同じアカウントで使用する場合、クッキーに
記録された情報が共有される事になります。
また、クッキーをセットしたサーバー以外のサーバーから、そのクッキー
に記録された情報を読み出す事は、基本的には出来ないように
なっているのですが、絶対的な保証はありません。
従って『クレジットカードやパスワードなどの大切な情報はクッキーに
保存しないようにする』といった心構えも必要かも知れません。

なお、InternetExplorer でクッキーに関する設定をする場合は次の
手順で行ないます。

  1. [ツール]−[インターネット オプション]−「プライバシー」タブ−「詳細設定」ボタンをクリックします。
  2. クッキーの処理方法を設定する画面が表示されます。

    クッキーを受け入れる場合は、【 自動 Cookie 処理を上書きする】 チェックボックスを
    クリックして、チェックを入れます。
    そのほかの項目は下記の通りです。

    [ファースト パーティ]・・・現在表示している Webページ
    [サード パーティ]・・・現在表示している Webページ以外の Webページ
    【 受け入れる 】・・・クッキーが常にコンピュータに保存されます
    【 ブロックする 】・・・クッキーはコンピュータに保存されません
    【 ダイアログを表示する 】・・・クッキーをコンピュータに保存するかどうかの
    確認メッセージが表示されます
    【 常にセッション Cookie を許可する 】・・・InternetExplorer が終了するとコンピュータから削除
    される一時的なクッキーが、常にコンピュータに
    保存されるようになります

    ユーザーがログ・イン画面として汎用的に使用できるように
    EnterpriseServer で提供されている LOGIN.HTM もクッキーを
    利用しています。
    LOGIN.HTMには ホスト、ユーザー、パスワード、端末名、パスワード
    の保存、PORT番号 といった入力欄がありますが、ログインの都度、
    毎回それらを入力していたのでは手間も時間もかかります。
    そこで最新の入力情報をクッキーに保存しておき、次のログイン時に
    その情報をあらかじめ入力欄にセットすることで、ログイン操作を
    効率よく行なえるようにするわけです。
    従って、ブラウザ側ではクッキーを受け入れる設定になっていることを
    確認してください。(初期状態は「受け入れる」設定です)

    なおクッキーの制御はすべて cookie.js に記述した JavaScript で
    行なっています。その内容は次の通りです。

    グローバル変数:cookieArray

    クッキーの操作に使用する配列です。
    グローバル変数として定義することで、後述のsetcookie関数、
    getcookie関数で共用します。

    setcookie関数

    <form>
      :
    <input type="button" value="    O  K    " onClick="javascript:setcookie();signin();">
    <input type="button" value="キャンセル" onClick="javascript:window.close();">
      :
    </form>

    setcookie関数はログインする際、LOGIN.HTMの「OK」ボタンを
    クリックしたときに実行されます。
    そしてLOGIN.HTMのフォームに入力された最新の情報を
    クッキーに保存します。

    cookieArray[0] = document.forms[0].elements[0].value;
    cookieArray[1] = document.forms[0].elements[1].value;
    cookieArray[2] = document.forms[0].elements[2].value;
    cookieArray[3] = document.forms[0].elements[3].value;
    cookieArray[4] = document.forms[0].elements[4].checked;
    cookieArray[5] = document.forms[0].elements[5].value;

    cookieArray[0]〜[5]はグローバル変数で定義した配列です。
    LOGIN.HTMの6つのエレメントの内容が次のように、それぞれ
    代入されます。

    cookieArray[0] ・・・ ホスト(IPアドレス)
    cookieArray[1] ・・・ ユーザー名
    cookieArray[2] ・・・ パスワード
    cookieArray[3] ・・・ 端末名
    cookieArray[4] ・・・ 「パスワードの保存」フラグ(真偽値)
    cookieArray[5] ・・・ PORT
    exp=new Date();
    exp.setTime(exp.getTime()+1000*60*60*24*3650);

    クッキーの有効期限(現在から3650日後)を設定します。
    なおJavaScriptの時間単位は1/1000秒ですので、計算式は

    補正(1000)×秒(60)×分(60)×時(24)×日(3650日)

    となります。

    checkstrings = escape(cookieArray[0]);
    for (i=1;i < cookieArray.length;i++){
        checkstrings += "%00" + escape(cookieArray[i]);
    }

    このループで、変数checkstringsに、ESCAPEされた配列
    cookieArray の値を "%00"で区切って連結します。
    %00はヌル文字をESCAPEしたもので、フォームの入力には
    まず使用されないため、区切り記号の利用に適しています。

    document.cookie = "as400_net_com=" + checkstrings + "; expires=" + exp.toGMTString();

    上記で定義したcheckstrings(データ)、有効期限に加え、
    クッキーを呼び出す際のために、"as400_net_com"という名前
    を付けてクッキー情報を書き込みます。

    getcookie関数

    呼び出し元となるLOGIN.HTMでは次のように、getcookie関数
    の実行を設定しています。

    <body bgcolor="#000000" onLoad="javascript:getcookie(); alertpop(1,0); setFocus(0,0);">

    これによりLOGIN.HTMがブラウザに読み込まれたら直ちに実行
    されることになります。

    cookielength = document.cookie.length;
    cookieArray = document.cookie.split("; ");

    setcookie関数がまず行なうことは、前記setcookie関数で
    クッキーの保存時に指定した、"as400_net_com"の文字列
    から始まるクッキーを選別するための作業です。

    checkstrings = "";

    checkstringsの中身をブランクに設定します。
    これは後に行なう checkstrings.split("%00") の際に、エラーを
    防ぐための対応です。

    i = 0;
    while (cookieArray[i]){
        if (cookieArray[i].substr(0,14) == "as400_net_com="){
            checkstrings = cookieArray[i].substr(14,cookieArray[i].length);
            break;
        }
        i++;
    }

    このループで cookieArray に対して、最初の14文字が
    「as400_net_com=」で始まっているか否かをチェックし、
    「as400_net_com=」で始まっているものが見つかったら、
    そこに含まれる内容を取り出して checkstrings に代入します。
    代入され次第、break でループを終了させます。

    これで目的のクッキーの選別と、そこに含まれる前回の
    ログイン情報の抽出までが完了したことになります。

    cookieArray = checkstrings.split("%00");

    配列 cookieArray に抽出した文字列を"%00"で区切った
    ものを代入します。

    if (cookieArray[0]) document.forms[0].elements[0].value = unescape(cookieArray[0]);
    if (cookieArray[1]) document.forms[0].elements[1].value = unescape(cookieArray[1]);
    if (cookieArray[3]) document.forms[0].elements[3].value = unescape(cookieArray[3]);
    if (cookieArray[4] == "true") {document.forms[0].elements[4].checked = true;
    	document.forms[0].elements[2].value = unescape(cookieArray[2])};
    else {document.forms[0].elements[4].checked = false;
    	document.forms[0].elements[2].value = "";}
    if (cookieArray[5]) document.forms[0].elements[5].value = unescape(cookieArray[5]);

    文字列をUNESCAPEしたものをフォームに書き込みます。
    (ブランクの文字列があった場合は何も行ないません)

    これでクッキーに保存されていた情報(最新のログイン時の
    入力内容)がすべてフォームの入力欄にセットされることに
    なります。

    ただし cookieArray[4] つまり「パスワードの保存」フラグが
    true(真)でない場合に限り、

    document.forms[0].elements[2].value

    つまり「パスワード」欄は空白となります。

fkey.js (機能キーの処理)

【 構文 】

fkey(キー・イベント)

【 組み込み 】
<script language="JavaScript" src="/AS400-NET.USR/LIB5250/fkey.js"></script>
【 引数 】
キー・イベント・・・windowsオブジェクトのキー・イベントを処理する。
【 関数 】
<!--
window.document.onkeydown = fkey;
window.onhelp = disableHelp;
// fkey : 機能キーの処理... form[0] の変数 CMD にCTRL, F1, ... F24 を入れてsubmit する。
function fkey(key)
{
    var CMD;
    var k =  window.event.keyCode;
    if ( k == 13 ) return false;//EnterキーにはSUBMIT動作はさせない。
    if ( k == 17 ){//実行キー
        CMD = "CTRL";
        document.forms[0].CMD.value = CMD;
        document.forms[0].submit();
    }//実行キー
    if ( k > 111 && k < 136 ){//機能キー
        switch ( k ){
        case 112: CMD = "F1"; break; //F1
        case 113: CMD = "F2"; break; //F2
        case 114: CMD = "F3"; break; //F3
        case 115: CMD = "F4"; break; //F4
        case 116: CMD = "F5"; break; //F5
        case 117: CMD = "F6"; break; //F6
        case 118: CMD = "F7"; break; //F7
        case 119: CMD = "F8"; break; //F8
        case 120: CMD = "F9"; break; //F9
        case 121: CMD = "F10"; break;//F10
        case 122: CMD = "F11"; break;//F11
        case 123: CMD = "F12"; break;//F12
        case 124: CMD = "F13"; break;//F13
        case 125: CMD = "F14"; break;//F14
        case 126: CMD = "F15"; break;//F15
        case 127: CMD = "F16"; break;//F16
        case 128: CMD = "F17"; break;//F17
        case 129: CMD = "F18"; break;//F18
        case 130: CMD = "F19"; break;//F19
        case 131: CMD = "F20"; break;//F20
        case 132: CMD = "F21"; break;//F21
        case 133: CMD = "F22"; break;//F22
        case 134: CMD = "F23"; break;//F23
        case 135: CMD = "F24"; break;//F24
        }
        document.forms[0].CMD.value = CMD;
        document.forms[0].submit();
    }//機能キー
}
// -->
【 解説 】

fkey.js は実行キー(Ctrlキー)や機能キー(F1 - F24) が押された
ことを検知してCMD という名前で定義されている変数に押された
機能キーの種類を保管してSUBMIT を行います。
5250エミュレータ画面での典型的な機能キー操作を
HTMLインターフェース上で実現するための機能です。

最初のformの最初のエレメントとして

<input type="hidden" name="CMD">

のように CMD という名前の項目を組み込んでおく必要があります。

CGI では

----------------------------------------------------------------------------
CSR                 EVAL      VALUE  = CGIPARM('CMD       ')    
CSR                 MOVEL     VALUE         CMD               4 
C*( 実行キー )                                               
CSR   CMD           IFEQ      'CTRL'                         
                     :
CSR                 END
C*( F3 = 終了 )                                        
CSR   CMD           IFEQ      'F3  '                   
                     :
CSR                 END
----------------------------------------------------------------------------

のようにしてCMD のフィールド値によって、どの機能キーが操作員に
よって押されたのかを判断することができます。

次は fkey.js を組み込んだHTMLの例を示しています。
fkey.js の中の関数自体は明示的に呼び出す必要はありません。

----------------------------------------------------------------------------
<html>
<head><title>fkeyサンプル</title>
<script language="JavaScript" src="../LIB5250/fkey.js"></script>
</head>
<body>
<center>
<h1> fkeyサンプル </h1>
</center>
<form>
<p>実行キー(Ctrl) や機能キーによってSUBMIT することができます。</p>
<input type="hidden" name="CMD">
<input type="TEXT" width="30">
<br>
<br><input type="button" onClick="MyScript(document.forms[0].elements[0])" name="click" value=" O K ">
</form>
</body>
</html> 
----------------------------------------------------------------------------

login.js (ログイン操作)

【 構文 】

ログインPOPUP画面の表示・・・popuplogin(POPUP表示するファイルのURL,POPUP画面の名称,
POPUP画面の幅, POPUP画面の高さ, スクロールバーの有無)
ログイン実行のメインルーチン・・・signin()
ログイン実行のサブルーチン
(親ウィンドウのフォームをサブミットして
ログインPOPUP画面を閉じる)
・・・loginparent()
ログイン実行のサブルーチン
(親ウィンドウのフォームをサブミットして
ログインPOPUP画面を閉じる)
・・・contlogin()
【 組み込み 】
<script language="JavaScript" src="/AS400-NET.USR/LIB5250/login.js"></script>
【 引数 】

POPUP表示するファイルのURL・・・POPUP表示するファイルのURLを親画面からの相対パス
またはルートからの絶対パスで記述
POPUP画面の名称・・・任意
POPUP画面の幅・・・ピクセル数で指定
POPUP画面の高さ・・・ピクセル数で指定
スクロールバーの有無・・・yes, no より指定
【 関数 】
<!-- 
function popuplogin(uri, win_name, popw, poph, scroll) {
  var win_width = (screen.width - popw) / 2;
  var win_height = (screen.height - poph) / 2;
  var win_param = 'height='+poph+',width='+popw+',top='+win_height+',left='+win_width+',scrollbars='+scroll;
  window.open(uri, win_name, win_param)
}
function signin(){
	loginparent();
	contlogin();
}
function loginparent(){
Adrs = document.forms[0].elements[0].value;
portnum = document.forms[0].PORT.value;
sndAdr = "http://" + Adrs + ":" + portnum + "/cgi-bin/LOGINPGM";
window.opener.document.forms[0].action = sndAdr
window.opener.document.forms[0].elements[0].value = document.forms[0].elements[1].value;
window.opener.document.forms[0].elements[1].value = document.forms[0].elements[2].value;
window.opener.document.forms[0].elements[2].value = document.forms[0].elements[3].value;
}
function contlogin(){
window.opener.document.forms[0].submit();
this.window.close();
}
// -->
【 解説 】

login.js はログインに関する一連の処理

  1. 親画面からのログインPOPUP画面の呼び出し
  2. サブミット(ログインの実行)
  3. ログインPOPUP画面のクローズ

を行なうための関数を定義したものです。

ただし、POPUP画面に入力した内容をそのままサブミットすると
POPUPウィンドウ内に次の画面が表示されてしまいますので、
Aの内容はPOPUP画面に入力された情報を親画面に渡し、
親画面から実際のサブミット動作を行なう、という特殊なものに
なっています。

popuplogin関数

親画面で使用する関数で、POPUPログイン画面をディスプレイ
の中央に表示します。

JavaScript ではウィンドウの生成位置はディスプレイ左上端
(0,0)を基点に 生成するウィンドウの左上端までの距離を
left=Xピクセル、top=Yピクセルといった記述で指定します。

そのため生成するウィンドウの幅と高さを考慮に入れなくては
ならないうえ、ウィンドウを表示するディスプレイの解像度(画面の
大きさ)も実行環境によって異なるため、left、topに一律の値を
指定することはできません。

そこで次の方法で、常にPOPUP画面を画面中央に表示する
ためのleft、topの値を変数 win_width および win_height
として求めます。

var win_width = (screen.width - popw) / 2;
var win_height = (screen.height - poph) / 2;

screen.widthscreen.height はディスプレイ表示域の幅と高さ
をそれぞれ意味するもので、popwpoph は生成するウィンドウの
幅と高さです。

var win_param = 'height='+poph+',width='+popw+',top='+win_height+',left='+win_width+',scrollbars='+scroll;
window.open(uri, win_name, win_param)

ここでウィンドウを生成するのですが、実際にその役割を
担っているのは

window.open("URL", "ウィンドウ名称", "各種パラメータ")

という関数です。
引数である各種パラメータには

toolbar[=yes|no]ツールバーの表示/非表示
location[=yes|no]ロケーションバーの表示/非表示
directories[=yes|no]ディレクトリバーの表示/非表示
status[=yes|no]ステータスバーの表示/非表示
menubar[=yes|no]メニューバーの表示/非表示
scrollbars[=yes|no]スクロールバーの表示/非表示
resizable[=yes|no]ウィンドウサイズ変更の可否
width=Xpixelsウィンドウの横幅
height=Ypixelsウィンドウの高さ
left=XXpixelsデスクトップ左端からの座標
top=YYpixelsデスクトップ上端からの座標

などがあります。
なお、ブラウザの種別やバージョンによって使用できるパラメータ
は異なりますのでご注意下さい。
(上記はInternetExplorer 5.0 以上で動作可能なもの)

このパラメータは "," 区切りで複数を指定することも可能です。

ちなみに「TOP_Window」という名称の320×240のウィンドウを
スクロールバー無しで表示する場合は次のようになります。

window.open("MyWin.html","TOP_Window","width=320,height=240,scrollbars=no")

注意していただきたいのが " " (ダブル・クォート)の位置です。
パラメータ部分全体で " " で括られており、複数の項目を
一括して扱っていることがわかります。従って、

var win_param =

はパラメータ部分を一括りにするための変数で、ここに先ほど
求めた画面中央にPOPUP画面を生成するための座標と
ウィンドウの幅、高さ、およびスクロールバーを表示しない指定
を代入しているわけです。

< LOGIN.HTM を呼び出す HTML の例 >

<form method="GET">
<input type="hidden" name="USER">
<input type="hidden" name="PASSWRD">
<input type="hidden" name="DSPID">
<input type="hidden" name="@TEMPLATE" value="/AS400-NET.USR/PROJECT/MENU/MENU.HTM">
</form>
<a href="javascript:popuplogin('/AS400-NET.USR/PROJECT/LOGIN/LOGIN.HTM','LOGINPOPUP','390','210','no')">
<font><b>ログインはこちらからどうぞ</b></font></a>

呼び出し元のHTMLにある「ログインはこちらから」のリンク部分を
クリックすると

popuplogin('/AS400-NET.USR/PROJECT/LOGIN/LOGIN.HTM','LOGINPOPUP','390','210','no')

が実行されることになります。
/AS400-NET.USR/PROJECT/LOGIN/LOGIN.HTMを、
LOGINPOPUPという名称の 幅390、高さ210のウィンドウで、
スクロールバーを表示しない設定で、画面中央に生成する、
という動作が行なわれるのです。

signin関数

signin関数はloginparent関数を実行した後にcontlogin関数を
実行します。

サブルーチン:loginparent関数

loginparent関数はログインPOPUP画面に入力された内容を
親画面のフォームに代入する、というものです。

< 親画面・例 >

<form method="GET">
<input type="hidden" name="USER">
<input type="hidden" name="PASSWRD">
<input type="hidden" name="DSPID">
<input type="hidden" name="@TEMPLATE" value="/AS400-NET.USR/PROJECT/MENU/MENU.HTM">
</form>
<a href="javascript:popuplogin('/AS400-NET.USR/PROJECT/LOGIN/LOGIN.HTM','LOGINPOPUP','390','210','no')">
<font><b>ログインはこちらからどうぞ</b></font></a>

上記のように親画面の <form> にはアクション先の明示が
ありません。これはログインPOPUP画面で入力したホスト欄の
IPアドレス、PORT欄のポート番号宛にサブミットする必要が
あるため、loginparent関数内部でアクションに関する処理も
行なっていることに依ります。

Adrs = document.forms[0].elements[0].value;
portnum = document.forms[0].PORT.value;
sndAdr = "http://" + Adrs + ":" + portnum + "/cgi-bin/LOGINPGM";
window.opener.document.forms[0].action = sndAdr

document.forms[0].elements[0].value がホスト欄の
IPアドレスで、document.forms[0].PORT.value がPORT欄の
ポート番号です。
http://" + Adrs + ":" + portnum としてIPアドレスと
ポート番号を組み合わせ、更に + "/cgi-bin/LOGINPGM"
にてプログラムへのパスを指定します。これを sndAdr という変数
に代入し、window.opener.document.forms[0].action つまり
ログインPOPUP画面の親画面にある、最初のフォームの
アクション先に指定します。

window.opener.document.forms[0].elements[0].value = document.forms[0].elements[1].value;
window.opener.document.forms[0].elements[1].value = document.forms[0].elements[2].value;
window.opener.document.forms[0].elements[2].value = document.forms[0].elements[3].value;

ログインPOPUP画面で入力したユーザー名、パスワード、
端末名を、それぞれ親画面の最初のフォームのエレメント[0]、
[1]、[2]に順番に代入します。

サブルーチン:contlogin関数

前記loginparent関数によって、ログインPOPUP画面で入力した
内容に従って必要な値が親画面のフォームに埋め込まれました
ので、これをサブミットします。

window.opener.document.forms[0].submit();
this.window.close();

親画面におけるサブミットが完了したらログインPOPUP画面
(this.window)を閉じます。

rightadjust.js (右寄せ)

【 構文 】

rightAdjust(フォーム, エレメント)

【 組み込み 】
<script language="JavaScript" src="/AS400-NET.USR/LIB5250/rightadjust.js"></script>
【 引数 】

フォーム・・・入力欄のあるフォーム
エレメント・・・入力欄のあるフォーム・エレメント
【 関数 】
<!--
function rightAdjust( iForm, iElem )
{
    if( window.event.keyCode != 13) return;
    var obj = document.forms[iForm].elements[iElem];
    obj.style.textAlign="right";
}
// -->
【 解説 】

rightAdjust 関数は5250エミュレーター画面でのEnterキーによる
数字の右寄せを実現します。
処理の原理としては最初に右寄せを実現したいフィールドの
イベント・ハンドラとしてrightAdjust関数を割り当てておくと
Enterキーによる右寄せ機能が働くというものです。

次の例では最初だけ setHandler関数によってフォーム番号= 0
(最初のフォーム) の エレメント番号 = 0 (最初のエレメント) に
rightAdjust 関数を キー・ダウン(onkeydown) の関数として
ハンドラを割り当てています。
fkey.js を包含しているのは EnterキーによるSUBMIT動作を
抑えてしまうためです。

------------------------------------------------------------------------------------------
<html>
<head><title>rightadjustサンプル</title>
<script language="JavaScript" src="../LIB5250/rightadjust.js"></script>
<script language="JavaScript" src="../LIB5250/fkey.js"></script>
<script language="JavaScript">
<!-- 
window.document.onkeydown = fkey;
function setHandler(){
	var i = 0;//form no
	var j = 0;//element no
	document.forms[i].elements[j].onkeydown=new Function("rightAdjust(" + i + "," + j + ")");
}
// -->
</script>
</head>
<body OnLoad="setHandler()">
<center>
<h1> rightadjust サンプル </h1>
</center>
<form>
<p>項目に数字を入力してEnterキーを押すと右寄せされます。</p>
<input type="TEXT" width="10">
------------------------------------------------------------------------------------------

valcheck.js (入力妥当性検査)

【 構文 】

半角英数記号チェック・・・isAlpha(エレメント)
全角文字チェック・・・isKanji(エレメント)
半角数字・・・isNumeric(エレメント)
半角整数・・・isSuji(エレメント)
半角カナチェック・・・isKana(エレメント)
【 組み込み 】
<script language="JScript" type="text/jscript" src="/AS400-NET.USR/LIB5250/valcheck.js"></script>
【 引数 】

エレメント・・・入力欄のあるフォーム・エレメント
【 関数 】
<!--
// 半角英数記号チェック
function isAlpha( te ){
    var newText = "";
    for (i = 0; i < te.value.length; i++) {
        ch = te.value.substring(i, i+1);
        if (ch >= " " && ch <= "~") {
            newText += ch;
        }
    }
    return ShowDialog(newText,te,"半角英数入力","半角英数記号");
}
// 全角文字チェック
function isKanji( te ){
    var newText = "";
    for (i = 0; i < te.value.length; i++) {
        ch = te.value.substring(i, i+1);
        if (!(ch > " " && ch <= "~") && !(ch >= "ア" && ch <= "ン") && !(ch >= "ァ" && ch <= "ッ")
        && !(ch >= "。" && ch <= "゚")) {
            newText += ch;
        }
    }
    return ShowDialog(newText,te,"全角文字入力","全角文字(漢字、カナ、かな、A、記号)");
}
// 半角数字("0"〜"9" "-" "," "." " ")チェック
function isNumeric(te){
    var newText = "";
    for (i = 0; i < te.value.length; i++) {
        ch = te.value.substring(i, i+1);
        if (ch > "+" && ch < "/" || ch>="0" && ch <="9" || ch==" " ) {
            newText += ch;
        }
    }
    return ShowDialog(newText,te,"半角数字入力","半角数字");
}
// 半角整数(0〜9)チェック
function isSuji(te){
    var newText = "";
    for (i = 0; i < te.value.length; i++) {
        ch = te.value.substring(i, i+1);
        if (ch >= "0" && ch <= "9") {
            newText += ch;
        }
    }
    return ShowDialog(newText,te,"半角整数入力","半角整数(0〜9)");
}
// 半角カナチェック
function isKana(te){
    var newText = "";
    for (i = 0; i < te.value.length; i++) {
        ch = te.value.substring(i, i+1);
        if (ch >= "ア" && ch <= "ン" || ch >="ァ" && ch <="ッ" || ch >= "。" && ch <="゚" || ch==" " ) {
            newText += ch;
        }
    }
    return ShowDialog(newText,te,"半角カナ入力","半角カナ");
}
// ダイアログ表示
function ShowDialog(newText, te, Area,Text){
    var checkText = te.value;
    if (checkText != newText) {
        //if (confirm(Area+"欄に不正な文字が入力されています。\n"+Text+"のみを入力してください。")) {
        //window.status = Area + "欄に不正な文字が入力されています。\n"+Text+"のみを入力してください。";
        alert(Area+"欄に不正な文字が入力されています。\n"+Text+"のみを入力してください。");
        //te.focus();
        te.value = newText;
        return false;
        //}
    }
    return true;
}
// -->
【 解説 】

valcheck.js (入力妥当性検査)は5250エミュレーター画面と
同じような入力文字の妥当性検査の機能を提供します。

通常、HTML画面では措置を施さない限りにおいては、どのような
文字であっても検査されることなく入力されてしまいますが、
5250画面では例えば数字として定義されているフィールドには
数字以外の文字は入力することはできません。RPGプログラマーは
数字フィールドに対して数字でない文字が不正な文字として入力
されてしまうことについてまで想定して検査する必要はありません
でしたが、HTMLでは、すべての文字が入力可能になってしまいます
ので、JavaScriptで不正な文字が入力されないように防御する
必要があります。

ここで考慮が必要であるのはひとくちに数字とは言っても

数字= 0,1, ... 9

だけではなく、小数点やカンマ、マイナス符号も「数字」の一部として
認める必要があることです。

Windowsの世界では数字というと「数」しか入力できなくしてしまう
という非常に現実離れした考えで構成されています。
これはMicrosoft社の開発者がビジネスの適用業務の開発経験が
ほとんど無いからではではないかとも思えてしまいます。

5250画面の「数字」という概念をサポートしているのが
isNumeric関数です。
次の例のHTMLでは数字以外を入力してSUBMIT しようとすると
エラーとなる使用方法を示しています。

--------------------------------------------------------------------------------------------
<html>
<head><title>valcheckサンプル</title>
<script language="JavaScript" src="../LIB5250/valcheck.js"></script>
<script language="JavaScript">
<!-- 
function MyScript( elem ){
	if(isNumeric(elem)) return false;
}
// -->
</script>
</head>
<body>
<center>
<h1> valcheckサンプル </h1>
</center>
<form>
<p>項目には数字以外を入力してSUBMITするとエラーになります。</p>
<input type="TEXT" width="30">
<br>
<br><input type="button" onClick="MyScript(document.forms[0].elements[0])" name="click" value=" O K ">
</form>
</body>
</html>
--------------------------------------------------------------------------------------------

LOGIN.HTM (ログ・イン)

【 解説 】

LOGIN.HTM (ログ・イン) はユーザーがログ・イン画面として
汎用的に使用できるようにEnterprise Server で提供されている
HTML です。

LOGIN.HTM を表示してSUBMIT するとCGI: CGIBIN/LOGINPGM
が呼び出されて実行されます。
LOGIN.HTM は初期値として

IPアドレス = 192.168.1.1
ユーザー = QUSER
パスワード = QUSER
端末ID = CONSOLE

が埋め込まれていますので、ユーザーの仕様に合わせて修正して、
ご利用ください。
また、LOGIN.HTM のSUBMIT と同時に 次に表示すべきである
HTMLのフル・パス名を @TEMPLATEパラメータとして渡してやると
CGI: CGIBIN/LOGINPGM はログインが成功裡に完了すると
@TEMPLATEとして指定されたHTMLをオープンします。
@TEMPLATEで指定された次に表示するHTMLにもユーザー、
パスワード、端末ID が用意されていなければなりません。
LOGINPGM は次のHTMLテンプレートにも、これらの値を
埋め込みます。

また LOGIN.HTM はユーザーの入力値をクッキーに保存します。
つまり、これらの関係は次のようになります。

【 LOGIN.HTM を呼び出す HTML の例 】
<form method="GET">
<input type="hidden" name="USER">
<input type="hidden" name="PASSWRD">
<input type="hidden" name="DSPID">
<input type="hidden" name="@TEMPLATE" value="/AS400-NET.USR/PROJECT/MENU/MENU.HTM">
</form>
<a href="javascript:popuplogin('/AS400-NET.USR/PROJECT/LOGIN/LOGIN.HTM','LOGINPOPUP','390','210','no')">
<font><b>ログインはこちらからどうぞ</b></font></a>
【 CGI : LOGINPGM のソース (ASNET.USR/QRPGLESRC.LOGINPGM) 】
0001.00 H DATEDIT(*YMD/) COPYRIGHT('(C) OFFICE QUATTRO CO,.LTD JAPAN 2003-')    
0002.00 F**********  ログイン ************************************************* 
0003.00 F*                                                                      
0004.00 F********************************************************************** 
0005.00  /COPY ASNET.USR/QRPGLESRC,PROTOTYPE                                    
0006.00 D SPCBIN          DS                                                    
0007.00 D  USER                   1     10                                      
0008.00 D  PASSWRD               11     20                                      
0009.00 D  DSPID                 21     30                                      
0010.00  *  固定情報                                                            
0011.00 D MENU            C                   CONST('/AS400-NET.USR/PROJECT-    
0012.00 D                                     /MENU/MENU.HTM')                  
0013.00 D BASEHTML        C                   CONST('/AS400-NET.USR/PROJECT-    
0014.00 D                                     /LOGIN/INDEX.HTML')               
0015.00 D ERRMSG          C                   CONST(' ユーザーまたはパスワード  
0016.00 D                                      の誤りです。 ')                  
0017.00 D ERRFLD          C                   CONST('*ERROR*')                  
0018.00 C*( 標準入力 )                                                          
0019.00 C                   EXSR      STDIN                                     
0020.00 C*( ログイン ... 仮想ユーザー環境を開始します。 )                       
0021.00 C*----------------------------------------------------+              
0022.00 C* 指定したユーザー・プロフィールで JOB を開始する                   
0023.00 C*----------------------------------------------------+              
0024.00 C                   EVAL      RESULT = LOGIN(USER : PASSWRD: DSPID)  
0025.00 C*( ログインが成功すればユーザー、パスワードをメニューに埋め込みます 
0026.00 C     RESULT        IFEQ      TRUE                                   
0027.00 C                   CALLP     OPENHTML(TEMPLATE)                     
0028.00 C                   CALLP     SETFLD('$(USER)': USER)                
0029.00 C                   CALLP     SETFLD('$(PASSWRD)': PASSWRD)          
0030.00 C                   CALLP     SETFLD('$(DSPID)': DSPID)              
0031.00 C                   ELSE                                             
0032.00 C                   MOVEL     BASEHTML      TEMPLATE                 
0033.00 C                   CALLP     OPENHTML(TEMPLATE)                     
0034.00 C                   CALLP     SETFLD('ALERTMSG': ERRMSG)             
0035.00 C                   END                                              
0036.00 C                   CALLP     WRITE                                  
0037.00 C*( ログオフ ... 仮想ユーザー環境を終了します。 )                    
0038.00 C                   CALLB     'LOGOFF'                             99
0039.00 C                   SETON                                        LR  
0040.00 C                   RETURN                                           
0041.00 C******************************************************              
0042.00 C     STDIN         BEGSR                                       
0043.00 C******************************************************         
0044.00 C*( HTML からの標準入力されたフィールド値の受け取り )           
0045.00 C*( HTML からフィールド値の取得 )                               
0046.00 CSR                 EVAL      USER   = CGIPARM('USER      ')    
0047.00 CSR                 EVAL      PASSWRD= CGIPARM('PASSWRD   ')    
0048.00 CSR                 EVAL      DSPID  = CGIPARM('DSPID     ')    
0049.00 CSR                 EVAL      TEMPLATE = CGIPARM('@TEMPLATE ')  
0050.00 CSR                 ENDSR