
///////////////////////////////////////////////////
///// parent() の戻り値 ////////////////////////////

var _patientId;
function setPatientId(pid){
    _patientId = pid;
}
function patientId(){
    return _patientId;
}

var _anotherId;
function setAnotherId(pid){
    _anotherId = pid;
}
function anotherId(){
    return _anotherId;
}

var _patientKanjiName;
function setPatientKanjiName(name){
    _patientKanjiName = name;
}
function patientKanjiName(){
    return _patientKanjiName;
}

///// parent() の戻り値 ////////////////////////////
///////////////////////////////////////////////////

var _noaInfo;
function setNoaInfo(obj){
	_noaInfo = obj;
}
function owner(){
    //alert("=== owner->" + _noaInfo.owner); //##
	return _noaInfo.owner;
}
function hospitalId(){
	return _noaInfo.hospitalId;
}
function hospitalName(){
	return _noaInfo.hospitalName;
}
function setArguments(){
	// parent から URI に添付して転送されたパラメータを解析して記憶
	var elm = document.getElementById("_value");
	if (elm){
		var args = decodeSTRING(elm.value);
		//alert("=== setArguments ===\n" + args); //##
		var obj = decodeObject(args);
		setNoaInfo(obj);
		if (owner() && hospitalId()) return true;
	}
	return false;
}

var _submenus;
function initSubMenu(){
	_submenus = new Array();
}
function addSubMenu(menuItem, action){
	var obj = new Object();
	obj.item = menuItem;
	obj.action = action;
	_submenus.push(obj);
}
function subMenus(){
	return _submenus;
}

var _records;
function setRecords(obj){
	_records = obj;
}
function container(dataAndId){
    // patientEditor が使うデータを入れたオブジェクト

    // isSuperUser 属性を追加：patientEditor で使用
    _records[dataAndId].isSuperUser = isSuperUser();
    
	return _records[dataAndId];
}

var _timeZones;
function setTimeZones(val){
    // val: ",,0000,0600,深夜^,日,0000,2400,休日^,,0900,1200,時間内^"
    _timeZones = ["全日"];
    var array = val.split("^");
    for (num in array){
        var ary = array[num].split(',');
        var zone = ary[4]; // 深夜・休日・時間内などの区別
        if (zone == '時間内'){
            var from = ary[2];
            var to = ary[3];
            _timeZones.push(from + '-' + to);
        }
    }
}
function timeZones(){
    // ["0900-1200","1500-1700"] 形式を返す
    return _timeZones;
}

var _hasMonthlyMode;
function setHasMonthlyMode(status){
    _hasMonthlyMode = status;
}
function hasMonthlyMode(){
    return  _hasMonthlyMode;
}

var _layoutObj;
function setLayout(obj){
    _layoutObj = obj;
}
function firstItem(){
    // 初期表示項目："日計表" などの文字列で返す
    return _layoutObj.firstItem;
}
function planArray(){
    // 予定表の属性：カンマで区切られた文字列を配列にして返す
    return _layoutObj.plan.split(",");
}
function dayArray(){
    // 日計表の属性：カンマで区切られた文字列を配列にして返す
    return _layoutObj.day.split(",");
}
function monthArray(){
    // 月計表の属性：カンマで区切られた文字列を配列にして返す
    return _layoutObj.month.split(",");
}

function isDebugMode(){
	// FireFox では checkbox の value はすべて ON になってしまう
	return document.getElementById("debug").checked;
}



/////////////////////////////////////////////

var _userCode = ""; // Global 変数
var _sectionCode = ""; // Global 変数
var _groupCode = ""; // Global 変数

var _isDaily = 0;
var _isMonthly = 1;
var _isPlan = 2;
var _mode = _isDaily;
function setMode(mode){
    //alert("setMode->"+mode); //##
	_mode = mode;
}
function mode(){
	return _mode;
}

var _timeStamp = ""; // Global 変数
function timeStamp(){
	return _timeStamp;
}
function setTimeStamp(datetime){
	_timeStamp = datetime;
}

function sectionCode(){
	return _sectionCode;
}
function setSectionCode(st){
	_sectionCode = st;
}

function groupCode(){
	return _groupCode;
}
function setGroupCode(st){
	_groupCode = st;
}

var _itemArray; // = new Array(); // Global 変数

function initItemArray(){
	_itemArray = new Array();
}
function addItemArray(item){
	_itemArray.push(item);
}
function removeItemArray(number){
	for (var i=_itemArray.length-1; i >= 0; i--){
		var _item = _itemArray[i];
		if (number == _item.number) _itemArray.splice(i, 1);
	}
}
function countOfItemArray(){
	return _itemArray.length;
}
function itemAtIndexOf(ix){
	// itemArray の ix 番目の item を返す
	return (ix < _itemArray.length) ? _itemArray[ix] : null;
}
function itemOfNumber(number){
	// number を ID とする item を返す
	var count = _itemArray.length;
	for (var i=0; i < count; i++){
		var item = _itemArray[i];
		if (item.number == number) return item;
	}
	return null;
}

var _userObjects;
function setUserObjects(obj){
    // "akitsuki(秋月 舞)sadahira(定平 芳美)delivery(配布用)ohashi(大橋 克洋)" 形式
	_userObjects = obj;
}
function userObjects(){
	// ["ohashi":"大橋 克洋",,]
	return _userObjects;
}
function userKanjiNameOf(logname){
	// loginName に対応するユーザ漢字名を返す
    for (name in _userObjects){
        if (name == logname) return _userObjects[name];
    }
	return null;
}
function userNames(){
    // ["大橋","田中"] を返す
    var array = new Array();
    for (logname in _userObjects){
        var kanjiName = _userObjects[logname];
        array.push(kanjiName);
    }
    return array;
}
function lognameForKanji(kanji){
    // 漢字名から logname を返す
    for (logname in _userObjects){
        var kanjiName = _userObjects[logname];
        
        if (kanjiName == kanji) return logname;
    }
    return null;
}

var _userInfo;
function setUserInfo(obj){
    // obj = userCode(all)sectionCode(23)groupCode(doctor)loginName(ohashi)kanjiName(大橋 克洋)identifier(c44f9b64052f12c4e9229fd899c7113b)hospitalId(1304000000077)memo()entryDate(2010-04-29 15:49:06)updateTime(2013-06-23 19:04:20)owner(ohashi)rowid(38)
    //_initDebug(true); //##
    _debug("setUserInfo->"+encodeObject(obj)); //##
    
   _userInfo = obj;
}
function isSuperUser(){
	// ユーザコードが 10 以下の場合は特別権限を持つユーザ
    return (_userInfo.userCode == "all") ? true : false;
}
function userCode(){
	return _userCode;
}
function setUserCode(st){
	_userCode = st;
}


function setWeek(date){
	// 指定された年月日の曜日を埋め込む
	var week = weekOfDate(date, "inString"); // lib.js
	document.getElementById("weekArea").innerHTML = "(" + week + ") ";
}

function polling(){
	// 再帰的に実行する内容を記述
    //    if (floatPanel() && (floatPanel().innerHTML.length > 0))
    //        return; // Preference など表示されている時はポーリング停止

    _debug("polling --");//###

    if (mode() == _isMonthly)
        return;
    else {
        // HEAT BEAT を表示: getDailyList() の前に置かないと実行されない
        var elm = document.getElementById("_heartBeat");
        elm.innerHTML = new Date();
        
        getDailyList();
    }
	
	// ポップアップ年月日が本日ならポーリング
	if (isToday()){
		// 一定時刻ごとに再帰処理
		setTimeout(polling, 3000);
	}
}

var _sortOrder;
function setSortOrder(order){
	// "1" or "0" or null
	_sortOrder = (order && (order == "1")) ? "1" : "0";
	//alert("setSortOrder:"+_sortOrder); //##
}
function sortOrder(){
	return _sortOrder;
}
function toggleSortOrder(){
	// 受付時刻でソート・逆ソートを交互に変換
	_sortOrder = (_sortOrder * 1 > 0) ? "0" : "1";
	//alert(_sortOrder); //##
	putSortOrder(_sortOrder);
}

///////////////////////////
/// CONFIGRATION //////////

var _hasDatetime;
function setHasDatetimeButton(status){
	_hasDatetime = status;
}
function hasDatetimeButton(){
	return _hasDatetime;
}

var _hasPlan;
function setHasPlanButton(status){
	_hasPlan = status;
}
function hasPlanButton(){
	return _hasPlan;
}

var _hasTotal;
function setHasTotal(status){
	_hasTotal = status;
}
function hasTotal(){
	return _hasTotal;
}

var _hasAverage;
function setHasAverage(status){
	_hasAverage = status;
}
function hasAverage(){
	return _hasAverage;
}


////////////////////////////////////////////////////////
///// 今月の受診者リスト //////////////////////////////////

function showInsListPanel(){
	// 指定月の健保受診者リストをリクエスト
    window.open("./insList.html", "", "width=400 height=700 scrollbars=yes");
}

///// 今月の受診者リスト //////////////////////////////////
////////////////////////////////////////////////////////



var _daylyColumnConf;
function setDailyColumnConf(buff){
	// labels = array("時刻,PID,,,") 形式
    //console.log("== setDailyColumnConf", buff); //##
    
	var labels = buff.split(",");
	var array = new Array();
	var objects = defaultColumns();
    
    for (i in labels){
		var label = trim(labels[i]);
		if (label.length == 0) continue;
		var obj = objects[label];
		if (obj) array.push(obj);
	}
	_daylyColumnConf = array;
	
	function defaultColumns(){
		// default の日計表構成を規定
		// ### この項目は preference.js の内容と一致させる必要あり ###
		var array = new Array();
        array["付箋"] = newObj("postItColor", "付箋", "");
		array["受付"] = newObj("entry", "受付", "");
		array["カルテID"] = newObj("patientId","カルテID", "");
		array["another ID"] = newObj("anotherId","another ID", "");
		array["氏名"] = newObj("name","氏名", "strings");
		array["新患"] = newObj("newPatient","新患", "numeric");
        array["伝達"] = newObj("message", "伝達", "");
		array["本人"] = newObj("honin","本人", "numeric");
		array["家族"] = newObj("kazoku","家族", "numeric");
		array["国保"] = newObj("kokuho","国保", "numeric");
		array["点数"] = newObj("point","点数", "numeric");
		array["自費"] = newObj("ownFee","自費", "numeric");
		array["未収"] = newObj("mishuu","未収", "numeric");
		array["合計"] = newObj("total","合計", "numeric");
		array["受取"] = newObj("receive","受取", "numeric");
		array["終了"] = newObj("finish","終了", "");
		array["診療待"] = newObj("wait","診療待", "numeric");
		array["会計待"] = newObj("allWait","会計待", "numeric");
		array["記録"] = newObj("user","記録", "strings");
		array["修正"] = newObj("edit","修正", "center");
		array["会計"] = newObj("bill","会計", "center");
		array["予約"] = newObj("reserved", "予約", "");
		array["釣銭"] = newObj("change","釣銭", "numeric");
		array["閲覧"] = newObj("viewer","閲覧", "");
		return array;
	}
}
function daylyColumnConf(){
	// 日計表構成を返す
	return _daylyColumnConf;
}

var _planColumnConf;
function setPlanColumnConf(buff){
	// labels = array("時刻,PID,,,") 形式
    _debug("setPlanColumnConf->"+buff); //##

    if (buff){
        var labels = buff.split(",");
        var array = new Array();
        var objects = planItems(); // preference.js
        for (i in labels){
            var label = trim(labels[i]);
            if (label.length == 0) continue;
            if (hasMember(planArray(), label) == 0) continue;
            
            var obj = objects[label];
            if (obj) array.push(obj);
        }
        _planColumnConf = array;
    }
}
function planColumnConf(){
	// 予定表構成を返す
	if (! _planColumnConf){
		var array = new Array();
		array.push(newObj("postItColor", "付箋", ""));
		array.push(newObj("reserved", "予約", ""));
		array.push(newObj("entry", "受付", ""));
		array.push(newObj("patientId","カルテID", ""));
		array.push(newObj("name","氏名", "strings"));
		array.push(newObj("plan","実施計画", "strings"));
		_planColumnConf = array;
	}
	
	return _planColumnConf;
}

var _monthlyColumnConf;
function setMonthlyColumnConf(buff){
	// labels = array("時刻,PID,,,") 形式
    //_initDebug(true); //##
    _debug("== setMonthlyColumnConf->"+buff); //##

	var labels = buff.split(",");
	var array = new Array();
	var objects = defaultColumns();
    for (i in labels){
		var label = trim(labels[i]);
		if (label.length == 0) continue;
		var obj = objects[label];
		if (obj) array.push(obj);
	}
	_monthlyColumnConf = array;
    _debug("_monthlyColumnConf->"+encodeObject(array)); //##
	
	function defaultColumns(){
		// 月計表構成を返す
		// ### この項目は frontDesigner.js の内容と一致させる必要あり ###
		var array = new Array();
		array["日付"] = newObj("entry", "日付", "");
		array["人数"] = newObj("count","人数", "numeric");
		array["新患"] = newObj("newPatient","新患", "numeric");
		array["本人"] = newObj("honin","本人", "numeric");
		array["家族"] = newObj("kazoku","家族", "numeric");
		array["国保"] = newObj("kokuho","国保", "numeric");
		array["点数"] = newObj("point","点数", "numeric");
		array["自費"] = newObj("ownFee","自費", "numeric");
		array["合計"] = newObj("total","合計", "numeric");
		array["未収"] = newObj("mishuu","未収", "numeric");
		return array;
	}
}
function monthlyColumnConf(){
	// 月計表構成を返す
	return _monthlyColumnConf;
}

function newObj(id, label, type){
	var obj = new Object();
	obj.id = id;
	obj.label = label;
	obj.type = type;
	return obj;
}

/// CONFIGRATION //////////
///////////////////////////



///////////////////////////
/// Ajax による処理 /////////

function checkedDB(answer){
    alert("checkedDB->"+answer); //##
}
function checkDB(){
	// NOA database 構造をチェックし必要なら最新構造にする
    _callServer("CHECK_DB", "../NOA/server.php", null, checkedDB);
}

function puttedSortOrder(answer){
    // polling が機能していれば不要
    //alert("puttedSortOrder:\n"+answer);//##
    getDailyList();
}
function putSortOrder(order){
	// 受付時刻による表示順を昇順・降順で反転させる
    var args = new Object();
    args['owner'] = owner();
    args['sortOrder'] = order;
    
    _callServer("PUT_SORT_ORDER", "frontServer.php", args, puttedSortOrder);
}

function gotLayout(answer){
	// レイアウトを DB から読み出し FRONT 内容を表示
    //alert("gotLayout:\n"+answer);//##
    
    // まずテンプレートを元に属性を設定
    var obj = new Object();
    obj.checkBox = layoutChecksTemplate();
    obj.firstItem = "予定表";
    obj.timeZone = "0900-1200";
    obj.plan = planTemplate();
    obj.day = dayTemplate();
    obj.month = monthTemplate();
    
    // サーバからのデータのあるものは上書き
    if (answer && (answer.length > 0)){
        var obj1 = eval('(' + answer + ')');
        //alert("== obj1->"+encodeObject(obj1));//##
        var rec = new Object();
        if (obj1.args) rec = decodeObject(obj1.args);
        rec.timeZone = obj1.timezones;
        
        if (rec.checkBox) obj.checkBox = rec.checkBox;
        if (rec.firstItem) obj.firstItem = rec.firstItem;
        if (rec.timeZone) obj.timeZone = rec.timeZone;
        if (rec.plan) obj.plan = rec.plan;
        if (rec.day) obj.day = rec.day;
        if (rec.month) obj.month = rec.month;
    }
    
    setLayout(obj);
    setTimeZones(obj.timeZone);
    showTimeZonePop(); // polling を起動：setControls() の前に実行
    
    // FRONT 内容を表示
    setControls(obj.checkBox);
    
    setPlanColumnConf(obj.plan);
    setDailyColumnConf(obj.day);
    setMonthlyColumnConf(obj.month);
}
function getLayout(){
	// レイアウトをサーバへリクエスト
    var args = new Object();
    args['owner'] = owner(); // NOA から引き継いだもの
    args['hospitalId'] = hospitalId(); // NOA から引き継いだもの
    
    _callServer("GET_LAYOUT_PARTS", "frontServer.php", args, gotLayout);
}

function gotDailyList(answer){
    //console.log("== gotDailyList", answer); //== polling を切っておくこと
    
    // mode により、患者登録フィールドを表示・非表示
    var elm1 = document.getElementById("registArea");
    elm1.style.visibility = "visible";
    var elm2 = document.getElementById("toolButton");
    elm2.style.visibility = "visible";
    
	// 当日の来院患者リストを表示
    if (answer && (answer.length > 0)){
        var obj = eval('(' + answer + ')');
        //console.log("gotDailyList", encodeObject(obj)); //##
        
        // リストを降順・昇順で表示する時に使う
        setSortOrder(obj.sortOrder);
        kickMessage(obj.message); // messenger を再表示
        setRecords(obj.records);
        
        // タイムスタンプによる処理
        var ts = obj.timeStamp;
        
        if (ts == "same"){ // サーバが更新されていなかった
            return;
        } else if (ts == "empty"){	// タイムスタンプがなかった
            setTimeStamp(ts);	// タイムスタンプを記憶
        } else {	// サーバのタイムスタンプが更新されていた
            var items = ts.split("^");
            var timeStamp = items[0];
            setTimeStamp(timeStamp);	// タイムスタンプを記憶
        }
        
        // obj.records の処理
        var elm = document.getElementById("resultsArea");
        elm.innerHTML = "";
        var tbl = newTABLE(elm, "frontTable");
        
        _debug("resultsArea->"+elm); //##
        
        // タイトル ======================================
        var tr = titleDescription(tbl); 
        // 日計表
        var recs = obj.records;
        var row = 0;
        for (dateAndId in recs){
            var rec = recs[dateAndId];
            rec.dateAndId = dateAndId;
            //_debug(dateAndId+"->"+encodeObject(rec)); //##
            
            // 患者登録行 =================================
            if (matchInOut(rec.inOut))
                recordDescription(tbl, rec, row++); // 登録者行
        }
        // 集計行 ========================================
        dailyTotalDescription(tbl);
    }    
	
	function matchInOut(inOut){
		var td = document.getElementById("inpatient");
		if (!td) return true; // inpatient が指定されていなければ true
		
		// inOut が「外来/入院」チェックボックスと一致する場合のみ表示
		// rec.inout = ["on", ""|"0"]
		if ((inOut == "on") || (inOut * 1 > 0)){ // 入院チェックボックス
			return document.getElementById("inpatient").checked;
		}
		else { // 外来チェックボックス
			return document.getElementById("outpatient").checked;
		}
	}
    
    function kickMessage(array){
        // array に me@myApp メッセージがあれば表示
        // [{"sender":"","receiver":"","app":"","message":"","docId":"", "updateTime":""},,,] 型式
        if (array){
            for (num in array){
                var rec = array[num];
                //alert("kickMessage->"+encodeObject(rec)); //##
                
                var ary = rec.receiver.split("@");
                var receiver = ary[0];
                var app = ary[1];
                if ((receiver == owner()) && (app == "FRONT")){
                    showMessenger(rec); // neuron.js
                }
            }
        }
    }
}
function getDailyList(){
	// 指定日の受診者リストをリクエスト
    // 診療時間帯ポップアップが生成されるまで多少タイムラグがあるのでこの間はスキップ
    //console.log("getDailyList"); //##
    
    var elm = document.getElementById("timeZonePopup");
    if (!elm) return;

    var zone = document.getElementById("timeZonePopup").value;
    var stamp = "";
    if (zone && (zone == "全日")){
        zone = "0000-2400";
        stamp = timeStamp();
    }
    
    var args = new Object();
    args['timeZone'] = zone;
    args['owner'] = owner();
    args['entryDate'] = pageDate();
    args['timeStamp'] = stamp;
    args['application'] = "FRONT";
    
    //console.log("getDailyList", args); //##
    
    _callServer("GET_DAILY", "frontServer.php", args, gotDailyList);
}

function gotMonthlyList(answer){
	// 再来患者が登録されたことを確認
    //alert("gotMonthlyList->"+answer); //##

	// 当月の来院患者リストを表示
    if (answer && (answer.length > 0)){
        // var records = JSON.parse(answer);
        var records = eval('(' + answer + ')');
        _debug("records-> "+encodeObject(records)); //##
        
        // frontServer から送られたリストを itemArray にセット
        var elm = document.getElementById("resultsArea");
        elm.innerHTML = "";
        var tbl = newTABLE(elm, "frontTable");
        tbl.style.fontSize = "10pt";
        
        // registArea を空にする
        var elm = document.getElementById("registArea");
        elm.style.visibility = "hidden";
        var elm = document.getElementById("toolButton");
        elm.style.visibility = "hidden";
        
        var tr = titleDescription(tbl);
        
        // 月計表タイトルを生成
        initItemArray();
        var rows = 0;
        for (num in records){
            var cols = records[num];
            _debug(num+"-> "+cols); //##
            
            if (cols.length > 0){
                var tr = monthlyDescription(tbl, cols);
                
                if (Math.floor(num / 2) * 1 == (num / 2)){
                    tr.style.backgroundColor="#fff";
                } else {
                    tr.style.backgroundColor="#dfc";
                }
                rows++;
            }
        }
        
        // 月計表コンテンツを生成
        monthlyTotalDescription(tbl, rows);
    } else {
		var elm = document.getElementById("resultsArea");
        elm.innerHTML = "";
        var sp = newSPAN(elm, "");
        sp.innerHTML = "Loading monthlyList ...";
        sp.style.color = "#f88";
        sp.style.fontSize = "10pt";
        sp.style.padding = "20px";
    }
}
function getMonthlyList(){
	// 指定月の受診者リストをリクエスト
    var zone = document.getElementById("timeZonePopup").value;
    if (zone && (zone == "全日"))
        zone = "0000-2400";
    
    var elm = document.getElementById("inpatient");
    var inStatus = (elm.checked) ? 1 : 0;
    var elm = document.getElementById("outpatient");
    var outStatus = (elm.checked) ? 1 : 0;
    var entryDate = pageDate();
    
    var args = new Object();
    args['timeZone'] = zone;
    args['entryDate'] = encodeSTRING(entryDate);
    args['in'] = inStatus;
    args['out'] = outStatus;
    
    _callServer("GET_MONTHLY_LIST", "frontServer.php", args, gotMonthlyList);
}


function registedNewPatient(patientId){
	// NOA:patientRegister からの返事を受け取る
    
	registPatient(patientId, todayAndTime(), false); // 新患登録された pateintId を受付
}

function registedPatient(answer){
	// 再来患者が登録されたことを確認
    //alert("registedPatient:\n"+answer); //###
    
    // 日時指定で受付のエリアを削除
    document.getElementById("maintenanceArea").innerHTML = "";
    
    var obj = eval('(' + answer + ')');
    //alert("registedPatient->"+encodeObject(obj)); //###
    
    switch (obj.mode * 1){
        case 0: // 未登録
            openPatientRegister(); // 新患登録
            break;
        case 1: // 既に登録済み
            if (confirm(obj.message + "\n同日再診で登録しますか？")){
                registPatient(obj.patientId, obj.entryDate, true);
            }
            break;
        case 2: // レコード更新
        case 3: // 新規レコード追加
            getDailyList(); // polling off の時のため設置
            break;
        default: // エラーメッセージを表示
            //alert("registedPatient->"+encodeObject(obj)); //###
            break;
    }
}
function registPatient(patientId, entryDate, duplicate){
	// 再来患者を登録する
	if (patientId.length == 0) return;
	
    //### どういうわけか jellyFish ではこの後 server でコケるので
    //### patientId フィールドに patientId を入力しておく
    //document.getElementById("patientId").value = patientId;
    // ### 以前の patientId が残っていると使いにくいとのことで空白とする
    document.getElementById("patientId").value = "";
    
    var args = new Object();
    args.owner = owner();
    args.patientId = patientId;
    args.entryDate = entryDate;
    args.userCode = userCode();
    args.groupCode = groupCode();
    args.duplicate = (duplicate) ? "" : "regist_mode";
    
    _callServer("PUT_PATIENT", "frontServer.php", args, registedPatient);
}

function puttedBill(answer){
	// 再来患者が登録されたことを確認
    //alert("puttedBill:\n"+answer);//###
}
function putBill(patientId, entryDate, receive, mishuu){
	// 再来患者を登録する
    var args = new Object();
    args.patientId = patientId;
    args.entryDate = entryDate;
    args.receive = receive;
    args.mishuu = mishuu; // "2009-01-30 19:16:00,3650" 形式
    
    _callServer("PUT_BILL", "frontServer.php", args, puttedBill);
}

function savedPlan(answer){
	// 再来患者が登録されたことを確認
    //alert("savedPlan:\n"+answer);//###
}
function savePlan(patientId, entryDate, plan){
	// 編集された plan を FrontTable へ保存
    var args = new Object();
    args["owner"] = owner();
    args["patientId"] = patientId;
    args["entryDate"] = entryDate;
    args["plan"] = plan;
    
    _callServer("PUT_PLAN", "frontServer.php", args, savedPlan);
}

/// Ajax による処理 /////////
///////////////////////////

function openingCheck(){
	window.open("../MoneyCheck","MonyCheck"
						  ,"width=900,height=800,scrollbars=yes,resizable=yes");
}

function openAge(){
    // 年齢計算ツール
	window.open("../AGE","AGE","width=400,height=200,resizable=yes");
}

function setKanjiName(kanjiName){
	var elm = document.getElementById("kanjiNameArea");
	elm.innerHTML = "取扱: "+ kanjiName + " @ " + hospitalName();
}



////////////////////////////////
/// neuron.js による処理 /////////

function gotUserList(answer){
    // ユーザリストを受け取る
    //var obj = JSON.parse(answer);
    var obj = eval('(' + answer + ')');
    //alert("gotUserList->"+encodeObject(obj)); //##
    
	setUserObjects(obj);
	
    // footer にユーザ名を表示
    var elm = document.getElementById("kanjiNameArea");
    var kanjiName = userKanjiNameOf(owner());
    elm.innerHTML = "取扱: "+ kanjiName + " @ " + hospitalName();
    
    checkDB(); // 戻り値なし ###### 機能しておらず ######

	// サーバへ owner() 用のレイアウトをリクエスト
	getLayout();
}
function gotUserTable(answer){
    // UserTable の内容を受け取る
    //var obj = JSON.parse(answer);
    var obj = eval('(' + answer + ')');
    
    setUserInfo(obj);
    
    var args = new Object();
    NRCall("GET_USER_LIST", args, gotUserList);
}
function startup(){
	// ユーザ・リストをサーバへリクエスト
    var args = new Object();
    args["logName"] = owner();
    
    NRCall("GET_USER_TABLE", args, gotUserTable);
}

function setChangeColor(elm, color, bgcolor){
	// node を mouseover/mouseout に応じ変色させる
	// mouseout 時には CELL オリジナルの色に戻す
	var col = (color) ? color : "#000";
	var bgcol = (bgcolor) ? bgcolor : "#fff";
	var cl = "'" + col + "','" + bgcol + "'";
	elm.setAttribute("onmouseout", "resetColor(this," + cl + ")");
	elm.setAttribute("onmouseover", "setColor(this, '#ff0', '#00f')");
}

function closePatientList(){
	// 患者リストを閉じる
	document.getElementById("paientListArea").innerHTML = "";
}
function patientSelected(patientId){
	// 患者リストから１患者が選択された
	// 選択された patientId を検索欄に転記して患者リストを閉じる
	document.getElementById("patientId").value = patientId;
	closePatientList();
}
function gotPatients(answer){
	// 検索条件にマッチした患者リストを表示
	var records = eval('('+answer+')');
	records.sort(cmp_LVD); // 最終受診日順にソート
	//alert("records ->"+encodeObject(records)); //##
	
	var dom = document.getElementById("paientListArea");
    dom.innerHTML = "";
    dom.style.clear = "both";
    if (records.length == 0){
        var sp = newSPAN(dom, "");
        sp.innerHTML = "該当するものはありません";
        sp.style.padding = "5px";
        sp.style.color = "#f88";
        return;
    }
    
	var tbl = newTABLE(dom, "baseTable");
	var tr = newTR(tbl, "header", "");
	var td = newTD(tr, "", "");
	td.style.width = "15px";
	var img = newIMAGE(td, "", "./close.png", "close");
	img.setAttribute("onclick","closePatientList()");
	img.style.height = "12px";
	var td = newTD(tr, "", "カルテ番号");
	var td = newTD(tr, "", "氏名");
	var td = newTD(tr, "", "ローマ字");
	var td = newTD(tr, "", "最終受診日");
	
	var patientIdAndName;
	var count = records.length;
	for (var r=0; r < count; r++){
		var rec = records[r];
		var kanji = (rec.patientKanjiName) ? rec.patientKanjiName : "";
		patientIdAndName = rec.patientId + ":" + kanji;
		var romaji = (rec.patientRomajiName) ? rec.patientRomajiName : "";
		var lvd = (rec.lastVisitDate) ? rec.lastVisitDate : "";
		var tr = newTR(tbl, "/record", "");
		var action = "patientSelected('" + rec.patientId + "')";
		tr.setAttribute("onclick", action);
		var td = newTD(tr, "", "");
		var td = newTD(tr, "", rec.patientId);
		var td = newTD(tr, "", kanji);
		var td = newTD(tr, "", romaji);
		var td = newTD(tr, "", lvd);
	}
	var tr = newTR(tbl, "header", "");
    var msg = records.length + " 件あります、目的のものを選択してください";
	var td = newTD(tr, "", msg);
	td.setAttribute("colspan", "5");
    td.style.paddingLeft = "5px";
	
	function cmp_LVD(a, b){
		// 最終受診日で比較
		var st = a.lastVisitDate; //##
        if (!st || st.length == 0) return true;
        
		var st = st.substr(0, 10); //##
		var ary = st.split("-");
		var lvd = ary.join("/");
		var timea = new Date(lvd).getTime();
        
		var st = b.lastVisitDate; //##
        if (!st || st.length == 0) return false;
        
		var st = st.substr(0, 10); //##
		var ary = st.split("-");
		var lvd = ary.join("/");
		var timeb = new Date(lvd).getTime();
		
		return (timeb - timea);
	}
}
function registOldPatient(){
	// 本日の受診者を日計表に登録
	var elm = document.getElementById("patientId");
	var patientId = elm.value;
	elm.value = "";
	if (patientId.length > 0){
		// patientId の受診者を FrontTable へ追加
		var ch = patientId.charAt(0);
        if ((patientId.length == 8) && ('0' <= ch) && (ch <='9')){
            // 検索キーが patientId 
			registPatient(patientId, todayAndTime(), false);
        } else {
            var array = patientId.split("/");
            if (array.length > 2){ // 検索キーが生年月日
                // 生年月日 "s17/3/23","1942/3/23" 形式
                var yst = array[0];
                var yy = yst * 1;
                var mm = array[1] * 1;
                mm = (mm < 10) ? "0" + mm : mm;
                var dd = array[2] * 1;
                dd = (dd < 10) ? "0" + dd : dd;
                var nengou = yst.charAt(0);
                if ((nengou < '0') || ('9' < nengou)){
                    // "s17/3/23" 形式の場合
                    var warekiYear = yst.substr(1) * 1;
                    if (isSame(nengou, "h"))
                        yy = warekiYear + 1988;
                    else if (isSame(nengou, "s"))
                        yy = warekiYear + 1925;
                    else if (isSame(nengou, "t"))
                        yy = warekiYear + 1911;
                    else if (isSame(nengou, "m"))
                        yy = warekiYear + 1867;
                }
                if (yy < 1000){
                    alert("西暦の入力間違い: " + patientId);
                    return;
                }
                patientId = "" + mm + dd + (yy % 100);
            }
            
            document.getElementById("paientListArea").innerHTML = "";
            get_patients(patientId, gotPatients);
        }
	} else {
		// 新患登録
		openPatientRegister();
	}
	
	function patientIdWithBirthDate(year, month, day){
		// 生年月日から patientId を計算して返す
		// 年は西暦であること
		if (year < 1900) return "???"; // エラー
		
		var yy = year % 100;
		var mm = (month < 10) ? "0" + month : month;
		var dd  = (day < 10) ? "0" + day : day;
		
		return mm + dd + yy;
	}
}

/// neuron.js による処理 /////////
////////////////////////////////



function pageDate(){
	var elm = document.getElementById("datePop");
	if (elm){
		return elm.value;
	} else {
		var now = todayAndTime();
		return now.substr(0, 10);
	}
}

function makeDateString(td){
	var st = todayAndTime().substr(0, 10); // lib.js
	var array = st.split("-");
	var dt = array[0]+"年"+array[1]+"月"+array[2]+"日";
	var tx = newTEXT(td, dt);
}

function isToday(){
	// 本日のページなら true そうでなければ false を返す
	var now = todayAndTime();
	var entryDate = pageDate(); // dom.js
	
	return (isSameDate(entryDate, now)) ? true : false;
}

function modeSelected(elm){
	// 日計表、月計表、予定表のポップアップメニューが選択された
	var value = elm.value;
	if (value == "月計表"){
		setMode(_isMonthly);
		getMonthlyList();
	} else if (value == "予定表"){
		setMode(_isPlan);
		showSelectedPage();
	} else { // 日計表
		setMode(_isDaily);
		showSelectedPage();
	}
    
    // 診療時間帯による表示エリアを隠す
    closeRegistWithDateTime();
}

var _controls;
var _hasInsImageEditor;
function setControls(buff){
	// コントロールの構成を設定
    //_initDebug(true); //##
    _debug("setControls ==="); //##
    //_debug("setControls->"+buff); //##
    
    _controls = buff.split(",");
    
	var inOut = monthB = false;
	var menus = ["日計表"]; // 常に表示
    _hasInsImageEditor = false;
	var items = _controls;
	for (i in items){
		var label = items[i];
        if (label == "保険証画像を編集可とする") _hasInsImageEditor = true;
        
		if (label == "他日も表示") monthB = true;
		if (label == "入院・外来表示") inOut = true;
		if (label == "患者受付"){
			makeRegistField(); // 受診者登録を生成
		}
		if (label == "日時指定受付") 
            setHasDatetimeButton(true);
		if (label == "予定表"){
			setHasPlanButton(true);
			menus.push("予定表"); // 予定表 が指定されている場合のみ
		}
		if (label == "月計表示"){
			monthB = true;
            setHasMonthlyMode(true); // 診療時間帯表示に反映
			menus.push("月計表"); // 月計表 が指定されている場合のみ
		}
		if (label == "合計を表示") setHasTotal(true);
		if (label == "平均値を表示") setHasAverage(true);
	}

	// 入院、外来のチェックボックスを生成
	if (inOut){
		var td = document.getElementById("inOutArea");
		td.innerHTML = "";
		var ip = newCHECKBOX(td, "outpatient", "外来", 1);
		ip.setAttribute("onclick", "showSelectedPage()");
		var ip = newCHECKBOX(td, "inpatient", "入院", 0);
		ip.setAttribute("onclick", "showSelectedPage()");
	}
    
	// 年月日を生成
	var td = document.getElementById("dateArea");
	td.innerHTML = "";
	if (monthB)
		makeDatePopupButtons(td, "YYMMDD", todayAndTime());
	else 
		makeDateString(td);
    
	// 日計表ポップアップメニューを生成
	var td = document.getElementById("modePopupArea");
	td.innerHTML = "";
	var pu = newPopupMenu(td, "modePopup", menus, firstItem());
	pu.setAttribute("onchange", "modeSelected(this)");
    // 初期値によりモード設定：初期値に月計表はない
    if (firstItem() == "予定表")
        setMode(_isPlan);
    else
        setMode(_isDaily);
	
    _debug("道具メニューのサブメニューを生成 ---"); //##
    
	// 道具メニューのサブメニューを生成
	initSubMenu();
    _debug("isSuperUser->"+isSuperUser()); //##
    if (isSuperUser())
        addSubMenu("初期設定", "openPreference()");
    addSubMenu("始業点検", "openingCheck()");
    addSubMenu("年齢計算", "openAge()");
	if (hasDatetimeButton()) addSubMenu("日時指定受付", "registWithDateTime()");
	//if (hasPlanButton()) addSubMenu("予約ツール", "openBooking()");
    //addSubMenu("診療時間帯の設定", "getTimeZone()");
    //addSubMenu("今月の受診者リスト", "showInsListPanel()");
    _debug("setControls === end"); //##
}
function controls(){
    return _controls; // array
}
function hasInsImageEditor(){
    // 保険証 scan date をクリックした時に、編集画面を立ち上げるか、viewer だけにするかを返す
    return _hasInsImageEditor;
}

function timeZoneSelected(elm){
    // 診療時間帯ポップアップが選択された
    var zone = elm.value;
	var mode = document.getElementById("modePopup").value;
    if (mode == "月計表"){
        setTimeStamp("");
        getMonthlyList();
    } else {
        if (zone == "全日")
            setTimeStamp("");
        
        // 過去の日付のものも表示できるようにする
        if (!isSameDate(today(), pageDate()))
            setTimeStamp("");
        
        getDailyList();
    }
}
function showTimeZonePop(){
    // 診療時間帯ポップアップメニューを生成
    // timeZones() = ["全日", "0900..1200", "1500..1700"];
	var td = document.getElementById("timeZonePopupArea");
	td.innerHTML = "";
    var pu = newPopupMenu(td, "timeZonePopup", timeZones(), "全日");
	pu.setAttribute("onchange", "timeZoneSelected(this)");
    
    //_initDebug(true); //##
    _debug("showTimeZonePop");//###

    // polling() を起動
    showSelectedPage();
}

function showDaily(date){
	// 月計表で選択された日の日計表を表示
	
	// 年月日ポップアップを選択された年月日で再設定
	var elm = document.getElementById("dateArea");
	makeDatePopupButtons(elm, "YYMMDD", date);
	
	setMode(_isDaily);
	showSelectedPage();
}

function showSelectedPage(){
	// 年月日ポップアップメニューで指定された日計表を開く
    // newDatePopUp() のレシーバ
	setWeek(pageDate()); // 指定された年月日の曜日を表示
	setTimeStamp("");
	polling();
}

function showInsImage(url){
    // 保険証画像の path をリクエスト
    var notMultiThread = true;
    kick_window(url, "_blank", kickedWindow); // dataCenter.js
}
function setScanDateWith(elm, rec){
    // 保険証画像の scan date を表示し action 設定
    //alert("setScanDateWith->"+encodeObject(rec)); //##
    
    var path = rec.scanDataPath;
    var filename = rec.scanDateTime;
    // filename から 日付を抽出して返す
    // filename = "03234202_20120113165123.JPG" 形式
    if (filename){
        var array = filename.split("_");
        if (array.length > 1){
            var st = array[1];
            var yyyy = st.substr(0, 4);
            var mm = st.substr(4, 2);
            var dd = st.substr(6, 2);
            var hour = st.substr(8, 2);
            var min = st.substr(10, 2);
            var sec = st.substr(12, 2);
            var dateTime = yyyy+"-"+mm+"-"+dd+" "+hour+":"+min;
            elm.innerHTML = yyyy+"-"+mm+"-"+dd;
            elm.setAttribute("class", "insurance");
            
            var pastDays = daysBetween(dateTime, pageDate());
            if (pastDays > 30){
                // 一定日数を越えたものは「経過日数」表示
                elm.innerHTML += " ( " + pastDays + " 日経過)";
            }
        }
        var path = path + "/" + filename;
        if (hasInsImageEditor() == false){
            // 保険証 viwer だけの場合
            elm.setAttribute("onclick", "showInsImage('" + path + "')");
        }
    } else {
        elm.innerHTML = "画像はありません";
        elm.setAttribute("class", "noInsurance");
    }
    
    if (hasInsImageEditor()){
        // ## 保険証読込ツールを使う場合
        var pid = rec.patientId;
        var date = pageDate();
        elm.setAttribute("onclick", "open_InsViewer('" + pid + "','" + date + "')");
    }

    
    function daysBetween(datetime1, datetime2){
        // datetime1, datetime2 間の日数を返す
        // 両日の０時０分０秒同士で計算するので、多少誤差が出る可能性あり
        var date1 = datetime1.substr(0, 10) + " 00:00:00";
        var date2 = datetime2.substr(0, 10) + " 00:00:00";
        var seconds = secondsBetween(date1, date2);
        
        //return seconds / (60 * 60 * 24);
        return (seconds) ? seconds / (60 * 60 * 24) : 0;
    }
}

function open_InsViewer(pid, date){
    // 保険証画像の編集ツールを開く
    var url = "../InsViewer?patientId=" + pid + "&currentDate=" + date;    
    // kickedWindow は neuron.js
    kick_window(url, "_blank", kickedWindow); // dataCenter.js
}

function openMessenger(patientId, kanjiName){
    // メッセンジャーを起動
    //console.log("== openMessenger", patientId, kanjiName); //##
    
    var obj = new Object();
    obj.sender = "@NOA";
    obj.receiver = "@FRONT";
    obj.message = "--- " + patientId + " " + kanjiName + "さん ---\n";
    obj.docId = "";
    obj.updateTime = todayAndTime();
    //console.log("openMessenger: obj", encodeObject(obj)); //##
    
    showMessenger(obj);
}

function openWaitEditor(st){
    // 予約情報の変更パネルを開く
    var obj = decodeObject(st);
    //alert("openWaitEditor->"+encodeObject(obj)); //##
    
    var patientId = obj.patientId;
    var entryDate = obj.entryDate;
    var reservedDate = obj.reservedDate;
    var accepted = (entryDate != reservedDate) ? true : false;
    
    if (! isSameDate(reservedDate, today())){
        alert(reservedDate + " は本日の予約ではないので変更できません");
        return;
    }
    if (accepted){
        if (confirm(entryDate+" の「受付」を " + reservedDate + "の「予約」に戻します")){
            var args = new Object();
            args["patientId"] = patientId;
            args["entryDate"] = reservedDate;
            args["reservedDate"] = reservedDate;
            
            NRCall("PUT_FRONT_BOOKING", args);
        }
    } else {
        if (confirm(reservedDate+" の「予約」を、現在時刻で「受診」に変更します")){
            var args = new Object();
            args["patientId"] = patientId;
            args["entryDate"] = "";
            args["reservedDate"] = reservedDate;
            
            NRCall("PUT_FRONT_BOOKING", args);
        }
    }
}

function kicked_window(answer){
    var obj = JSON.parse(answer);
    
    var win = window.open(obj.url, obj.arguments, "width=400,height=270");
    win.focus();
}
function openPostIt(patientId, entryDate){
    // 付箋を開く
    console.log("openPostIt", patientId, entryDate); //##
    
    var url = "../NOA/postIt.php";
    url += "?owner=" + owner();
    url += "&patientId=" + patientId;
    url += "&currentDate=" + entryDate;
    
    kick_window(url, "_blank", kicked_window); // dataCenter.js
}

var _count;
var _insCount;
var _honin;
var _kazoku;
var _kokuho;
var _point;
var _ownFee;
var _mishuu;
var _newPatient;
function titleDescription(tbl){
	// 日計または月計ヘッダーを生成
	_count = 0;
	_insCount = 0; // 健保使用回数
	_honin = 0;
	_kazoku = 0;
	_kokuho = 0;
	_point = 0;
	_ownFee = 0;
	_mishuu = 0;
	_newPatient = 0;
	
	// daylyColumnConf() を元にヘッダー生成
	var tr = newTR(tbl, "title", "");
	if (mode() == _isDaily)
		array = daylyColumnConf();
	else if (mode() == _isMonthly)
		array = monthlyColumnConf();
	else
		array = planColumnConf();
	
	for (i in array){
		var col = array[i];
		if (col.id == "entry"){
            if (mode() == _isMonthly){
                var td = newTD(tr, "", col.label);
            } else {
                var td = newTD(tr, "", "");
                var a = newA(td, col.label, "#", "");
                a.setAttribute("onclick", "toggleSortOrder()");
            }
		} else if (col.type == "numeric")
			var td = newTD(tr, "title_num", col.label);
		else if (col.type == "center")
			var td = newTD(tr, "title_center", col.label);
		else
			var td = newTD(tr, "", col.label);
        td.style.padding = "0 5px";
	}
	return tr;
}
function recordDescription(tbl, rec, row){
	// 日計レコードを生成
    //alert("recordDescription->"+encodeObject(rec)); //##
	var honin = honin(rec);
	var kazoku = kazoku(rec);
	var kokuho = kokuho(rec);
	var point = point(rec);
	var reserved = isReserved(rec);
	var ownFee = (rec.ownFee) ? rec.ownFee : 0;
	var mishuu = (rec.mishuu) ? rec.mishuu : 0;
	var receive = (rec.receive) ? rec.receive : 0;
	var newPatient = isNewPatient(rec);
    var isWait = (!rec.endTime || rec.endTime.toString()=="0000-00-00 00:00:00") ? true : false; // 診療待ち
    var beforChekBill = (!rec.checkOutTime) ? true : false; // 会計待ち
    
    var _finished = 0;
    var _waiting = 1;
    var _beforCheckBill = 2;
    var status = _finished; // 会計終了
    if (!rec.endTime || rec.endTime.toString()=="0000-00-00 00:00:00")
        status = _waiting; // 診療待ち
    else if (!rec.checkOutTime)
        status = _beforCheckBill; // 会計待ち

	//	alert(encodeObject(rec)); //##
	_count += 1;
	_honin += honin * 1;
	_kazoku += kazoku * 1;
	_kokuho += kokuho * 1;
	_point += point * 1;
	_ownFee += ownFee * 1;
	_mishuu += mishuu * 1;
	_newPatient += newPatient;
	if (point > 0) _insCount++; // 健保を使用した回数
	var total = honin * 1 + kazoku * 1 + kokuho * 1 + ownFee * 1 + mishuu*1;
    
    //console.log("recordDescription", encodeObject(rec)); //##
	
	// daylyColumnConf() を元にレコード生成
	var tr = newTR(tbl, "/frontRow", "");
    
    var bgcolor = "#afa"; //################

	if (mode() == _isDaily)
		var array = daylyColumnConf();
	else if (mode() == _isPlan)
		var array = planColumnConf();
	
	for (i in array){
		var col = array[i];
		var td = newTD(tr, col.type, "");
		var val = valueWithId(col);
        var reserved = false;
        if (rec.reservedDate && (rec.reservedDate != "0000-00-00 00:00:00"))
            reserved = true; // 予約患者
        var isFinished = (rec.endTime && rec.endTime.toString().length)
            ? true : false;
        		
		// アクションを設定
		if (isSame(col.id, "postItColor")){ // 付箋カラー
            //console.log("col.id", rec.patientId, rec.entryDate); //##
            
            var colorNumber = rec.postItColor;
            if (colorNumber >= 0){
                var dot = newDIV(td, "");
                dot.innerHTML = colorNumber;
                dot.style.padding = "0 4px";
                var action = "openPostIt('" + rec.patientId + "','" + rec.entryDate + "')";
                dot.setAttribute("onclick", action);
                switch (colorNumber * 1){ // 以下は ../NOA/base.css を参照
                    case 1: dot.setAttribute("class", "postItDotBlue"); break;
                    case 2: dot.setAttribute("class", "postItDotYellow"); break;
                    case 3: dot.setAttribute("class", "postItDotRed"); break;
                    default: dot.setAttribute("class", "postItDotGreen"); break;
                }
            }
		} else if (isSame(col.id, "reserved")){ // 予約時刻
            td.innerHTML = (reserved) ? rec.reservedDate.substr(11, 5) : "";
			if (rec.reservedDate == rec.entryDate){ // 予約だが受付未済
                td.style.color = "#000";
			} else {
                td.style.color = "#aaa";
			}
            td.setAttribute("onclick", "openThisBooking('"+rec.patientId+"','"+rec.anotherId+"','"+rec.kanjiName+"')");
            td.setAttribute("class", "reservedBase");
		} else if (isSame(col.id, "viewer")){ // 閲覧
            var bt = newBUTTON(td, "", "閲覧");
            var st = rec.patientId + "','" + rec.kanjiName + "','" + rec.entryDate;
            bt.setAttribute("onclick", "openViewer('" + st + "')");
		} else if (isSame(col.id, "edit")){ // 修正
			td.style.textAlign = "center";
			var action = "openPatientEditor('" + rec.dateAndId + "')";
			var bt = newBUTTON(td, "", "修正");
			bt.setAttribute("onclick", action);
		} else if (isSame(col.id, "bill")){ // 会計
			td.style.textAlign = "center";
			var bt = newBUTTON(td, "", "会計");
			var action = "openBill('" + rec.dateAndId + "')";
			bt.setAttribute("onclick", action);
		} else if (isSame(col.id, "entry")){ // 受付時刻
            var sp = newSPAN(td, "");
            sp.innerHTML = val;
            if (reserved){ // 予約患者
                if (rec.reservedDate == rec.entryDate){ // 受付未済の予約患者
                    // 時刻がピンク表示になりクリックすると、受付け時刻刻印できるようになる
                    sp.setAttribute("class", "reserved");
                } else if (isFinished){ // 診療済みのもの
                    sp.setAttribute("class", "finishedOnly"); // レスポンスなし
                } else { // 受付済みのもの
                    sp.setAttribute("class", "acceptedOnly"); // レスポンスなし
                }
                var st = encodeObject(rec); // rec をアーカイブする
                sp.setAttribute("onclick", "openWaitEditor('"+st+"')");
            } else if (isFinished){ // 診療済みのもの
                sp.setAttribute("class", "finishedOnly"); // レスポンスなし
            } else { // 受付済みのもの
                sp.setAttribute("class", "acceptedOnly"); // レスポンスなし
            }
		} else if (isSame(col.id, "patientId") || isSame(col.id, "anotherId")){
            var sp = newSPAN(td, "");
            sp.innerHTML = val;
            if (rec.inOut == "on"){ // 入院は赤文字
                td.style.color = "#f00";
            }
            if (isSuperUser()){ // super user ならカルテを開くことができる
                var st = rec.patientId + "^" + rec.kanjiName + "^" + rec.entryDate;
                var action = "openPatientNOA('" + st + "')";
                sp.setAttribute("onclick", action);
                sp.setAttribute("class", "idRow");
            }
		} else if (isSame(col.id, "name")){ // 患者氏名
            var sp = newSPAN(td, "");
            sp.style.padding = "0 5px";
            sp.style.fontSize = "10pt";
            sp.innerHTML = val;
            switch (status){
                case _waiting: td.style.color = "#000"; break; // 診療待ち
                case _beforCheckBill: td.style.color = "#00f"; break; // 会計待ち
                default: td.style.color = "#aaa"; break; // 会計終了
            }
		} else if (isSame(col.id, "plan")){ // 実施計画
            var sp = newSPAN(td, "");
            sp.innerHTML = val;
			if (trim(rec.plan).length > 0){
				// 実施計画がある場合のみマウスに反応して編集パネルを開ける
				var action = "openPlanEditor('" + rec.dateAndId + "')";
				sp.setAttribute("onclick", action);
                sp.setAttribute("class", "plan");
			}
		} else if (isSame(col.id, "message")){ // 伝達
            var action = "openMessenger('"+rec.patientId+"','"+rec.kanjiName+ "')";
            td.setAttribute("onclick", action);
            td.setAttribute("class", "plan");
		} else if (isSame(col.id, "point")){ // 点数
			var tx = newTEXT(td, point);
		} else if (isSame(col.id, "image")){ // 保険証画像
            var sp = newSPAN(td, "/insurance");
            setScanDateWith(sp, rec);
		} else
			var tx = newTEXT(td, val);
	}
	
	
	//alert(encodeObject(rec)); //###
	
	function valueWithId(col){
		if (isSame(col.id, "entry"))
			return timeOf(rec);
		else if (isSame(col.id, "patientId"))
			return rec.patientId;
		else if (isSame(col.id, "anotherId"))
			return rec.anotherId;
		else if (isSame(col.id, "name"))
			return rec.kanjiName;
		else if (isSame(col.id, "newPatient"))
			return (newPatient > 0) ? "*" : "";
		else if (isSame(col.id, "honin"))
			return honin.toString();
		else if (isSame(col.id, "kazoku"))
			return kazoku.toString();
		else if (isSame(col.id, "kokuho"))
			return kokuho.toString();
		else if (isSame(col.id, "ownFee"))
			return ownFee.toString();
		else if (isSame(col.id, "honin"))
			return honin.toString();
		else if (isSame(col.id, "total"))
			return total.toString();
		else if (isSame(col.id, "wait"))
			return waitingMinutes(rec);
		else if (isSame(col.id, "allWait"))
			return allWaitingMinutes(rec);
		else if (isSame(col.id, "finish"))
			return endTime(rec).toString();
		else if (isSame(col.id, "user"))
			return rec.owner;
		else if (isSame(col.id, "mishuu"))
			return rec.mishuu;
		else if (isSame(col.id, "receive"))
			return rec.receive;
		else if (isSame(col.id, "change"))
			return rec.receive - total;
		else if (isSame(col.id, "plan"))
			return rec.plan;
		else
			return ".";
	}
	
	function isReserved(rec){
		// 登録年月日より以前に更新されていれば予約と判断
		if (rec.entryDate > rec.updateTime)
			return true;
		else
			return false;
	}
	
	function reservationOf(rec){
		// 予約行なら「予約」ボタンを返す
		return (reserved) ? "RSV" : "";
	}
	
	function timeOf(rec){
		// "2007-08-29 12:05:00" 形式を "12:05:00" 形式にして返す
		// "00:00:00" の場合は "" を返す
		var time = rec.entryDate.substr(11, 5);
		return (isSame(time, "00:00:00") > 0) ? "" : time;
	}
	
	function isNewPatient(rec){
		if (rec.newPatient * 1 > 0)
			return 1;
		else 
			return 0;
	}
	
	function point(rec){
		return (rec.point) ? rec.point : 0;
	}
	
	function honin(rec){
		return (rec.groupCode == 0) ? rec.insFee : 0;
	}
	
	function kazoku(rec){
		return (rec.groupCode == 1) ? rec.insFee : 0;
	}
	
	function kokuho(rec){
		return (rec.groupCode == 2) ? rec.insFee : 0;
	}
	
	function waitingMinutes(rec){
		// 受付時刻から診療終了までの経過時間を分で返す
		var entry = rec.entryDate;
		if (!entry ) return "";
		
		var now = (rec.endTime) ? rec.endTime : todayAndTime();
		var min = Math.floor(secondsBetween(entry, now) / 60);
		
		// 一日以上経過している場合は "..." で表す
		return (min < 60 * 24) ? min + " 分" : "...";
	}
	
	function allWaitingMinutes(rec){
		// 受付時刻から会計終了までの経過時間を分で返す
		var entry = rec.entryDate;
		if (!entry ) return "";
		
		var now = (rec.checkOutTime) ? rec.checkOutTime : todayAndTime();
		var min = Math.floor(secondsBetween(entry, now) / 60);
		
		// 一日以上経過している場合は "..." で表す
		return (min < 60 * 24) ? min + " 分" : "...";
	}
	
	function endTime(rec){
		// endTime は "2008-05-04 15:34:34" のような形式なので時刻のみ返す
		var st = rec.endTime;
		if (!st ) return "";
		
		var array = st.split(" ");
		return array[1].substr(0, 5);
	}
}
function dailyTotalDescription(tbl){
	// 日計合計行を生成
	if (mode() == _isPlan) return;
	var total = _honin + _kazoku + _kokuho + _ownFee;
	var confs = daylyColumnConf();
    
	if (hasTotal()){ // 合計行
        var tr = newTR(tbl, "average", "");
        for (i in confs){
            var col = confs[i];
            var val = valueWithId(col).toString();
            var td = newTD(tr, col.type, val);
        }
    }

	if (hasAverage()){ // 平均行
		var tr = newTR(tbl, "average", "");
        for (i in confs){
			var col = confs[i];
			var val = averageWithId(col).toString();
			var td = newTD(tr, col.type, val);
		}
	}
	
	function valueWithId(col){
		if (isSame(col.id, "entry"))
			return "合計";
		else if (isSame(col.id, "patientId"))
			return _count+" 名";
		else if (isSame(col.id, "newPatient"))
			return _newPatient;
		else if (isSame(col.id, "honin"))
			return _honin;
		else if (isSame(col.id, "kazoku"))
			return _kazoku;
		else if (isSame(col.id, "kokuho"))
			return _kokuho;
		else if (isSame(col.id, "point"))
			return _point;
		else if (isSame(col.id, "ownFee"))
			return _ownFee;
		else if (isSame(col.id, "total"))
			return total;
		else if (isSame(col.id, "mishuu"))
			return _mishuu;
		else
			return "";
	}
	
	function averageWithId(col){
		if (isSame(col.id, "entry"))
			return "平均";
		else if (isSame(col.id, "honin"))
			return average(_honin, _count);
		else if (isSame(col.id, "kazoku"))
			return average(_kazoku, _count);
		else if (isSame(col.id, "kokuho"))
			return average(_kokuho, _count);
		else if (isSame(col.id, "point"))
			return average(_point, _insCount);
		else if (isSame(col.id, "ownFee"))
			return average(_ownFee, _count);
		else if (isSame(col.id, "total"))
			return average(total, _count);
		else
			return "";

		function average(val, count){
            // 小数点以下を四捨五入した平均値を返す
			return (count == 0) ? 0 : Math.round(val / count);
		}
	}
}	

function monthlyDescription(tbl, ary){
	// ary[] 内容は frontServer の calcSum() で定義
	var count = ary[0] * 1;
	var date = ary[1];
	var honin = ary[2] * 1;
	var kazoku = ary[3] * 1;
	var kokuho = ary[4] * 1;
	var ownFee = ary[5] * 1;
	var mishuu = ary[6] * 1;
	var inOut = ary[8] * 1;
	var newPatient = ary[9] * 1;
	var point = ary[10] * 1;
	_count += count;
	if (point > 0) _insCount++;
	_honin += honin;
	_kazoku += kazoku;
	_kokuho += kokuho;
	_ownFee += ownFee;
	_mishuu += mishuu;
	_newPatient += newPatient;
	_point += point;
	var tr = newTR(tbl, "record", "");
	
    // 一行の各カラムを表示
	var array = monthlyColumnConf();
    for (i in array){
		var col = array[i];
		var val = valueWithId(col, ary);
		var td = newTD(tr, col.type, val);
        td.style.padding = "0 5px";
        
		// アクションを設定
		if (isSame(col.id, "entry")){
			var a = newA(td, date, "#", "");
			var action = "showDaily('"+date+"')";
			a.setAttribute("onclick", action);
			
			// week
			var week = " " + weekOfDate(date, "inString");
			var tx = newTEXT(td, week);
		}
	}
	return tr;
	
	function valueWithId(col, ary){
		var count = ary[0] * 1;
		var date = ary[1];
		var honin = ary[2] * 1;
		var kazoku = ary[3] * 1;
		var kokuho = ary[4] * 1;
		var ownFee = ary[5] * 1;
		var mishuu = ary[6] * 1;
		var inOut = ary[8] * 1;
		var newPatient = ary[9] * 1;
		var point = ary[10] * 1;
		var total = honin + kazoku + kokuho + ownFee - mishuu;
		
		if (isSame(col.id, "count"))
			return count.toString();
		else if (isSame(col.id, "newPatient"))
			return newPatient.toString();
		else if (isSame(col.id, "honin"))
			return honin.toString();
		else if (isSame(col.id, "kazoku"))
			return kazoku.toString();
		else if (isSame(col.id, "kokuho"))
			return kokuho.toString();
		else if (isSame(col.id, "ownFee"))
			return ownFee.toString();
		else if (isSame(col.id, "total"))
			return total.toString();
		else if (isSame(col.id, "mishuu"))
			return mishuu.toString();
		else if (isSame(col.id, "point"))
			return point.toString();
		else
			return "";
	}
}
function monthlyTotalDescription(tbl, dayCount){
	// 日計合計行を生成
	var total = _honin + _kazoku + _kokuho + _ownFee;
	var tr = newTR(tbl, "", "");
	var array = monthlyColumnConf();
	for (i in array){
		var col = array[i];
		var val = valueWithId(col, dayCount);
		var td = newTD(tr, col.type, val);
        td.style.padding = "0 5px";
	}
	
	if (hasAverage()){
		var tr = newTR(tbl, "average", "");
		for (var i=0,count=array.length; i < count; i++){
			var col = array[i];
			var val = averageWithId(col, dayCount).toString();
			var td = newTD(tr, col.type, val);
            td.style.padding = "0 5px";
		}
	}
	
	function valueWithId(col, dayCount){
		if (isSame(col.id, "entry"))
			return "合計 " + dayCount +" 日";
		else if (isSame(col.id, "count"))
			return _count+" 名";
		else if (isSame(col.id, "newPatient"))
			return _newPatient.toString();
		else if (isSame(col.id, "honin"))
			return _honin.toString();
		else if (isSame(col.id, "kazoku"))
			return _kazoku.toString();
		else if (isSame(col.id, "kokuho"))
			return _kokuho.toString();
		else if (isSame(col.id, "ownFee"))
			return _ownFee.toString();
		else if (isSame(col.id, "honin"))
			return honin.toString();
		else if (isSame(col.id, "total"))
			return total.toString();
		else if (isSame(col.id, "mishuu"))
			return _mishuu.toString();
		else if (isSame(col.id, "point"))
			return _point.toString();
		else
			return "";
	}
	
	function averageWithId(col, dayCount){
		if (isSame(col.id, "entry"))
			return "平均";
		else if (isSame(col.id, "count"))
			return Math.round(_count / dayCount) + "名";
		else if (isSame(col.id, "newPatient"))
			return Math.round(_newPatient / dayCount);
		else if (isSame(col.id, "honin"))
			return Math.round(_honin / dayCount);
		else if (isSame(col.id, "kazoku"))
			return Math.round(_kazoku / dayCount);
		else if (isSame(col.id, "kokuho"))
			return Math.round(_kokuho / dayCount);
		else if (isSame(col.id, "ownFee"))
			return Math.round(_ownFee / dayCount);
		else if (isSame(col.id, "total"))
			return Math.round(total / dayCount);
		else if (isSame(col.id, "point"))
			return Math.round(_point / _insCount);
		else
			return "";
	}
}	

function registOldTimePatient(){
	// 指定した日時の受診者を日計表に登録
	var id = "_YYMMDD";
	var patientId = document.getElementById(id+".patientId").value;
    var entryDate = document.getElementById("datePop").value;
	var hour = document.getElementById(id+".hour").value;
	var min = document.getElementById(id+".minute").value;
	var sec = document.getElementById(id+".second").value;
	if (hour < 10) { hour = "0" + hour; }
	if (min < 10) { min = "0" + min; }
	if (sec < 10) { sec = "0" + sec; }
	var dateTime = entryDate + " " + hour + ":" + min + ":" + sec;
    
//    alert(dateTime); return; //##
	
	registPatient(patientId, dateTime, false);
}

function openPatientEditor(dateAndId){
	// 患者会計レコードの編集パネルを開く
    var array = dateAndId.split("^");
    var date = array[0];
    var pid = array[1];
	var url = "./patientEditor.php?dateAndId=" + dateAndId;

	var w = window.open(encodeURI(url),
						"patientEditor",
						"width=260,height=550,resizable=yes");
}

function openPlanEditor(dataAndId){
	// plan 編集パネルを開く
	var rec = container(dataAndId);
	if (newPlan = prompt("実施計画 編集パネル", rec.plan)){
		savePlan(rec.patientId, rec.entryDate, newPlan);
	}
}

function openBill(dateAndId){
	// 会計パネルを開く
	var url = "./billEditor.php?dateAndId=" + dateAndId
	+ "&owner=" + owner()
	+ "&isSuperUser=" + isSuperUser();
	//alert("openBill ---\n"+url); //##
	var w = window.open(encodeURI(url),
		"会計パネル",
		"width=350,height=400,resizable=yes");
}

function openPatientNOA(patientIdAndNameAndDateTime){
	// 現在時刻を受付レコードにタイムスタンプした後、カルテを開く
    var array = patientIdAndNameAndDateTime.split("^");
    var patientId = array[0];
    var patientName = array[1];
    var entryDate = array[2];
    
    // カルテを開く
    var url = "../NOA/top.php?patientId=" + patientId
    + "&currentDate=" + encodeSTRING(entryDate)
    + "&hospitalId=" + hospitalId()
    + "&loginName=" + owner();
    var w = window.open(encodeURI(url), patientId
                        ,"width=1100,height=800,resizable=yes");
}

function openViewer(patientId, name, currentDate){
    // カルテの簡易閲覧パネルを開く
    var url = "viewer.php?hospitalId=" + hospitalId()
    + "&owner=" + owner()
    + "&patientId=" + patientId
    + "&patientKanjiName=" + name
    + "&currentDate=" + currentDate;
	window.open(url,"viewr","width=600,height=1000,scrollbars=yes,resizable=yes");
}

function openPatientRegister(){
	// 新患登録パネルを開く
	// ## patientRegister からの受け口として receiver を用意しておくこと
	// ## receiver に添えるパラメータは patientRegister との間で暗黙の了解
	var obj = new Array();
	obj["owner"] = owner();
	obj["hospitalId"] = hospitalId()
	obj["receiver"] = "registedNewPatient";
	obj["frontmode"] = "yes";
	var url = "../NOA/patientRegister.php?value=" + encodeObject(obj);
	//alert(url); //##
	var w = window.open(encodeURI(url),
						"patientRegister",
						"width=500,height=350,resizable=yes");
}

function makeDatePopupButtons(elm, id, date){
	// idで指定されたエレメント上に年月日のポップアップメニューを生成し elm へ追加
	var yy = date.substr(0, 4) * 1;
	var mm = date.substr(5, 2) * 1;
	var dd = date.substr(8, 2) * 1;
    
	var sp = document.getElementById(id);
    if (sp) 
        sp.innerHTML = "";
    else
        sp = newSPAN(elm, id);
    newDatePopUp(sp, "datePop", "平成", yy, mm, dd, false, showSelectedPage);
	
	// 指定された年月日の曜日を埋め込む
	setWeek(date);
}

function closeRegistWithDateTime(){
	var elm = document.getElementById("maintenanceArea");
	elm.innerHTML = "";
}
function registWithDateTime(){
	// 日時指定受付を開く
	var elm = document.getElementById("maintenanceArea");
	if (elm.innerHTML.length == 0){
		elm.innerHTML = "";
        elm.style.border = "thin solid #eee"; //###

		// メンテ作業の種別を選択するポップアップメニューを生成
		var im = newIMAGE(elm, "", "./close.png", "?");
		im.setAttribute("onclick", "closeRegistWithDateTime()");
		im.style.height = "12px";
        sp = newSPAN(elm, "");
        sp.innerHTML = "日時指定で受付";
        sp.style.padding = "0 5px";
        sp = newSPAN(elm, "");
        sp.style.padding = "0 5px";
		var id = "_YYMMDD";
		var pu = makeDatePopupButtons(sp, id, todayAndTime());
		var hours = makeArray(0, 24);
		var sl = newPopupMenu(elm, id+".hour", hours, 10);
		var tx = newTEXT(elm, ":");
		var minutes = makeArray(0, 60);
		var sl = newPopupMenu(elm, id+".minute", minutes, 30);
		var tx = newTEXT(elm, ":");
		var sec = makeArray(0, 60);
		var sl = newPopupMenu(elm, id+".second", sec, 0);
		var tx = newTEXT(elm, " ");
		
		var ip = newFIELD(elm, id+".patientId", "カルテID ", 9, "");
		var bt = newBUTTON(elm, "", "再来登録");
		bt.setAttribute("onclick", "registOldTimePatient()");
	} else
		elm.innerHTML = "";
}

function changePasswd(){
	// パスワードを変更
	setPasswd(owner());
}

function makeRegistField(){
	// カルテID、再来受付、新患登録などのボタンを生成
	var elm = document.getElementById("registArea");
	elm.innerHTML = "";
	
	if (! isToday()){
		var tx = newTEXT(elm, "患者登録は本日のページで");
		elm.style.color = "#888";
		return;
	} else
		elm.style.color = "#000";
	
	var fd = newFIELD(elm, "patientId", "", 10, "");
	fd.setAttribute("onchange", "registOldPatient()");
    fd.setAttribute("placeholder", "カルテID"); // 入力ヒントを表示
    fd.focus();
	var bt = newBUTTON(elm, "", "患者受付");
	bt.setAttribute("onclick", "registOldPatient()");
}

function hideSubmenu(){
	// サブ・メニューを閉じる
	var elm = document.getElementById("_submenu");
	elm.style.visibility = "hidden";
}
function closeSubMenu(){
	// どういう訳か hideSubmenu() を直接読むとうまく動作しない
	hideSubmenu();
}
function showSubMenu(elm){
	// メイン・メニューにマウスがのった時、サブ・メニューを生成表示
	// メニュー CELL の位置やサイズを検出
    var pos = getPosition(elm);
	var x = pos.x; // 表示するx座標
	var y = pos.y; // 表示するy座標
	var h = elm.offsetHeight;
	var w = elm.offsetWidth;

	// サブ・メニューを生成
	var elm = document.getElementById("_submenu"); // noa.php
	elm.innerHTML = "";
	elm.style.left = x; // 表示するx座標
	elm.style.top = y + h; // 表示するy座標
	elm.style.visibility = "visible";
    
	// tbl にサブメニューを表示
	var tbl = newTABLE(elm, "");
	tbl.style.fontSize = "10pt";
	tbl.style.border = "thin solid #aaa";
	tbl.style.backgroundColor = "#fff";
	tbl.style.fontFamily = "arial, Helvetica";
	
	// サブメニューの各項目設定
	var array = subMenus();
	for (i in array){
		var obj = array[i];
		var tr = newTR(tbl, "", "");
		var td = newTD(tr, "/menuItem", obj.item);
		td.style.padding = "2px 5px";
		td.setAttribute("onclick", "doAction('" + obj.action +"')");
	}
	
	// サブメニュー消去用
	var tr = newTR(tbl, "", "");
	var td = newTD(tr, "", "");
	td.style.height = "10px";
	td.style.backgroundColor = "#ddd";
	td.setAttribute("onmouseover", "closeSubMenu()");
	
	// サブメニュー消去用
	var elm = document.getElementById("resultsArea"); // noa.php
	elm.setAttribute("onmouseover","closeSubMenu()");
}
function doAction(action){
	// サブメニューを消し action を実行
	closeSubMenu();
	eval(action);
}

function helpTimeZone(){
    // 診療時間帯指定のヘルプを開く
	window.open("./timeZoneHelp.html","Help"
				,"width=450,height=700,scrollbars=yes,resizable=yes");
}

function openBooking(){
	// 予約ツールを開く
	window.open("../Booking","Booking"
				,"width=900,height=700,scrollbars=yes,resizable=yes");
}
function openThisBooking(pid, aid, name){
	// 行の予約コラムから予約ツールを開く
    setPatientId(pid);
    setAnotherId(aid);
    setPatientKanjiName(name);
    
    //elmFor("_debug").innerHTML = patientId(); //##
    
	window.open("../Booking","Booking"
				,"width=900,height=700,scrollbars=yes,resizable=yes");
}

function frontHelp(){
	window.open("./frontHelp.html","Help"
				,"width=450,height=700,scrollbars=yes,resizable=yes");
}

function showFront(){
    //_initDebug(true); //##
    _debug("== showFront"); //##
    
	// テンプレートで FRONT のヘッダー部分を生成
	var elm = document.getElementById("base");
	elm.innerHTML = "";
    var div = newDIV(elm, "/tool-header");
    var dv = newDIV(div, "/left-side");
    dv.style.width = "90%";
    dv.style.position = "relative";
    dv.style.bottom = "3px";
    var sp = newSPAN(dv, "inOutArea"); sp.style.paddingLeft = "5px";
    var sp = newSPAN(dv, "dateArea"); sp.style.paddingLeft = "10px";
    var sp = newSPAN(dv, "weekArea"); sp.style.paddingLeft = "3px";
    var sp = newSPAN(dv, "modePopupArea"); 
    var sp = newSPAN(dv, "timeZonePopupArea"); 
    var sp = newSPAN(dv, "registArea"); sp.style.paddingLeft = "3px";
	// 道具ボタン
    var sp = newSPAN(dv, "");
    sp.style.paddingLeft = "10px";
    var bt = newDIV(sp, "toolButton/blueButton");
    bt.innerHTML = "道具";
	bt.setAttribute("onmouseover","showSubMenu(this)");
    bt.style.padding = "0 15px";
    bt.style.marginRight = "10px";
    var dv = newDIV(div, "/right-side");
	// ヘルプ・ボタン
	var im = newIMAGE(dv, "", "./Help.png", "?");
	im.setAttribute("onclick", "frontHelp()");
	im.style.height = "20px";
	im.style.verticalAlign = "bottom";
	
	// 検索結果表示エリア
    var div = newDIV(elm, "paientListArea");
	
	// 管理ペーン
    var div = newDIV(elm, "maintenanceArea");
	
	// リスト表示領域
    var div = newDIV(elm, "resultsArea");
	
	// footer を生成
    var div = newDIV(elm, "/tool-footer");
    var dv = newDIV(div, "kanjiNameArea/left-side");
    dv.style.width = "50%";
    dv.style.paddingLeft = "20px";
    var dv = newDIV(div, "/right-side");
    var sp = newSPAN(dv, "");
    sp.innerHTML = version();
	
	// サーバへユーザ・リストをリクエスト
	// その返事を待って年月日ポップアップメニューで指定されたページを開く
	startup();
}

function initFront(){
	// ユーザを認証
    //window.name = "front"; // parent() 機能のために必要 -- window.opener.name に反映されない
    
	if (setArguments()){ // URI に owner,hospitalId が添付されてきた
		showFront();
	} else {			// owner,hospitalId が添付されていない
		initLogin(); // login パネルを生成
	}
}

function version(){
	return "Ver.1401124";
}

