

function isDebug(){
    // debug check box の status を返す
    return (noaDebug()) ? true : false;
}

function noaType(){
    // NOA のタイプ識別用
    return "NOA8G"; // 第８世代 NOA
}

function thumbNailSize(){
    // htmlForValue() に必要
    // preference.js などでカスタマイズできるようにする
    return "50px";
}

function showToolMessage(msg){
    // tools の workArea にメッセージを表示：デバッグ用に使う
    window.top.tools.document.getElementById("messageArea").innerHTML = msg;
}

function archiveMessage(msg){
    // カルテをアーカイブしたメッセージを表示
    showFadeoutInfo("alertArea", msg, 50000);
}

function showIconBar(){
    // NOA のヘッダーに TOOL ICON を表示
    var div = document.getElementById("toolIconArea");
    div.innerHTML = "";
    
    _initDebug(false); //##
    
    var ul = newUL(div, "/listMembers");
    var array = menuStructure();
    for (num in array){
        var cell = array[num];
        
        if (cell.menuType * 1 != _main) continue;
        if (cell.disabled * 1) continue;
        if (cell.subTitle * 1) continue;
        
        // メニュー項目を生成
        var li = newLI(ul, "", cell.id + "/listMemberIcon");

        if (cell.url == "search()"){
            // cell.editor に infoTip に表示する内容が入っている
            setInfoTip(cell.id, cell.editor); // HELP
            
            // これだけは特別扱い
            var dv = newDIV(li, "/searchFrame");
            var fd = newFIELD(dv, "searchF", "", 15, "");
            setInfoTip(cell.id, "このカルテ内の文言検索"); // HELP
            fd.setAttribute("class", "searchField");
            fd.setAttribute("onchange", "search()");
            var bt = newSPAN(dv, "/searchButton");
            bt.innerHTML = "検索";
            bt.setAttribute("onclick", "search()");
        } else if (cell.icon){
            // ICON があれば ICON を表示
            // cell.editor に infoTip に表示する内容が入っている
            setInfoTip(cell.id, cell.editor); // HELP
            var img = newIMAGE(li, "", cell.icon, "icon");
            img.style.margin = "0 5px"; // ボタン間隔
            img.style.height = "15px";
            img.style.verticalAlign = "middle";
            var action = "kickMenuCell('" + cell.url + "','" + cell.window +"')";
            img.setAttribute("onclick", action);
            img.setAttribute("class", "expandIcon");
        } else {
            // アンカー表示
            // cell.editor に infoTip に表示する内容が入っている
            setInfoTip(cell.id, cell.editor); // HELP
            var bt = newDIV(li, "/greenButton");
            bt.innerHTML = cell.label;
            bt.style.position = "relative";
            bt.style.bottom = "1px"; // ボタン位置調整
            if (cell.url){
                var action = "kickMenuCell('" + cell.url + "','" + cell.window +"')";
                bt.setAttribute("onclick", action);
            }
        }
    }
   
    // TOOL MENU
    var li = newLI(ul, "", "gearIcon/listMemberIcon");
    setInfoTip("gearIcon", "Tool Menu"); // HELP
    var img = newIMAGE(li, "", "gear.png", "icon");
    img.style.height = "15px";
    img.style.verticalAlign = "middle";
    img.setAttribute("onclick", "openToolPane()");
    img.setAttribute("class", "expandIcon");
}

function showToolAndIcons(answer){
    // サーバから得たフィールド属性の配列を記憶
    // obj = {"records":{"tag":{"label":""},,,},"userInfo":{},,,} 形式
    //alert("showToolAndIcons->"+answer); //##
    var obj = JSON.parse(answer);
    
    // ユーザ情報を記憶
    setUserList(obj.userList);
    setUserInfo(obj.userInfo);
    
    // 施設情報を記憶
    setHospitalInfo(obj.hospitalInfo);
    
    //alert("== gotAllFields: obj->"+encodeObject(obj.userList)); //##
    
    // サーバから cell 構造が得られない場合はテンプレートを使う
    var useTemplate = false;
    if (objectCount(obj.records) > 0){
        var fieldObj = obj.records;
    } else {
        var fieldObj = cellTemplate();
        useTemplate = true;
    }
    
    var tagObj = new Object();
    for (tag in fieldObj){
        var cell = fieldObj[tag];
        
        if (trim(cell.label).length == 0) continue;
        
        // cell (属性: menuAction,study,,,) を tagObj に記憶
        tagObj[tag] = cell;
    }
    
    // tagObj = {tag:cell,,,} から layoutArray = [cell, cell, ,,,] を生成
    setLayoutArray(tagObj, useTemplate);
    
    //alert("showToolAndIcons をデバッグ用に改変しています"); return; //##
    
    openToolPane();
    showIconBar();
}

function gotToolMenuStructure(answer){
    // TOOL MENU を表示するとともに全フィールド属性をサーバへリクエスト
    //alert("gotToolMenuStructure->"+answer); //##
    var obj = JSON.parse(answer);
    
    setMenuStructure(obj);
    
    // 以下の戻り値は neuron に記憶される
    NRGetCellUserHospitalInfo(owner(), showToolAndIcons);
}

/////////////////////////////////////
///// POLLING ///////////////////////

var _worker;

function setNoCheckWaiting(elm){
    // polling を停止
    var status = elm.checked;
    window.localStorage["noCheckWaiting"] = (status) ? "1" : "0";
    
    if (status){
        // 裏プロセスを終了し polling を停止
        _worker.terminate();
        
        document.getElementById("pollingArea").innerHTML = "";
    } else {
        polling();
    }
}

function polling(){
    // 受付の患者登録を Worker を使い裏プロセスの polling でチェック
    // DB とのやりとりや polling は polling.js で設定
    _worker = new Worker('./polling.js');
    
    _worker.onmessage = function (event) {
        // 新たに受け付けられた受診者データを受け取る
        var obj = event.data;
        
        var records = obj.records; // 本日の日計表レコード
        var messageArray = obj.message; // メッセージ・オブジェクト
        
        //alert(encodeObject(records)); //##

        // 他アプリからのメッセージを表示
        if (messageArray && (messageArray.length > 0)){
            //var found = false;
            for (num in messageArray){
                var rec = messageArray[num];
                //alert(encodeObject(rec)); //##
                
                var ary = rec.receiver.split("@");
                var receiver = ary[0];
                var app = ary[1];
                if ((receiver == owner()) && (app == "NOA")){
                    //found = true;
                    showMessenger(rec); // neuron.js
                }
            }
        }
        
        // 本日の受診者リストを表示
        var elm = document.getElementById("pollingArea");
        elm.innerHTML = "";
        var div = newDIV(elm, "");
        
        for (num in records){
            var rec = records[num];
            var etime = rec.endTime; // 診察終了時刻
            
            if (rec.entryDate > rec.updateTime){
                // 登録年月日より以前に更新されていれば予約と判断
                var sp = newSPAN(div, "/reserved-patient-tab");
                sp.innerHTML = rec.patientId + " " + rec.kanjiName;
                var action = "openChart('" + rec.patientId + "','" + rec.kanjiName + "')";
                sp.setAttribute("onclick", action);
            } else if (etime && etime.toString().length) {
                // 診療終了したものは表示しない
            } else {
                // 診療終了していないものだけを拾い出す
                var sp = newSPAN(div, "/waiting-patient-tab");
                sp.innerHTML = rec.patientId + " " + rec.kanjiName;
                var action = "openChart('" + rec.patientId + "','" + rec.kanjiName + "','addPage')";
                sp.setAttribute("onclick", action);
            }
        }
    }
    
    // worker 側で polling すると Ajax の場合はうまくいかないのでこちら側で polling
    //    setTimeout(polling, 3000);
}

///// POLLING ///////////////////////
/////////////////////////////////////



/////////////////////////////////////
///// SEARCH ////////////////////////

var _keyArray;
var _keyPos;

function jumpToKey(keyPos){
    // テキスト中の次のキーへカーソル・ジャンプ
    if (_keyPos * 1 > (keyPos * 1 + 1)){
        var fieldId = _keyArray[(keyPos * 1 + 1)]; // 次のフィールド
        var elm = document.getElementById(fieldId);
        
        // 次のヒット・ページの先頭にジャンプ
        var pos = getPosition(elm.parentNode.parentNode);
        window.scroll(0, pos.y);
    } else {
        window.scroll(0, 0);
    }
}
function searchRecord(key){
    // 全レコードの ProgressSection 中を検索
    _keyPos = 0;
    _keyArray = new Array();
    var count = 0;
    var obj = structure();
    for (entryDate in obj){
        // rec は ProgressSection と NameSection のデータを保有
        var rec = obj[entryDate];
        var array = layoutArray(_progress);
        for (num in array){
            var layoutObj = array[num];
            if (layoutObj.hitAndRun * 1) continue; // 非表示セルをスキップ
            
            var tag = layoutObj.tag;
            var cell = rec[tag];
            if (!cell) continue;
            
            var val = cell.trimValue;
            if (!val) continue;
            
           // vALUE
            val = cell.htmlValue;
            if (!val) continue;
            if (trim(val).length == 0) continue;
            
            var elm = document.getElementById(cellId(entryDate, tag));
            var ary = val.split(key);
            if (ary.length > 1){
                var st = '<span style="background-color:#ff0">';
                st += key + '</span>';
                elm.innerHTML = ary.join(st);
                elm.setAttribute("onclick", "jumpToKey('" + _keyPos + "')");
                
                // key にマッチした element の id を記憶
                _keyArray[_keyPos++] = cellId(entryDate, tag);
                
                // key に一致した回数をカウント
                count += (ary.length - 1);
            } else {
                elm.innerHTML = val;
            }
        }
    }
    return count;
}

///// SEARCH ////////////////////////
/////////////////////////////////////

/////////////////////////////////////
///// PAGE //////////////////////////

function removedPage(answer){
    // ページ削除を画面に反映させる
    openChart(patient_id(), patientKanjiName());
}
function removePage(dateTime){
    // dateTime のページを削除
	var userCode = userInfoForKey("userCode");
	if (userCode != "all"){
		alert("アクセス・コード: "+userCode+" なのでページ削除権限がありません");
	} else if (confirm(dateTime + " のページを削除しますか")){
		setCurrentDate("");
		NRRemovePage(owner(),patient_id(),dateTime,timeLimit(), removedPage);
	}
}

function addedPage(answer){
    // 新規ページを追加
    //alert("addedPage->"+answer); //##
    
    openChart(patient_id(), patientKanjiName());
}
function addPage(dateTime){
    // dateTime の新規ページを追加
    _initDebug(isDebug(), window.document.getElementById("_test")); //##
    _debug("--- addPage ---"); //##
    _debug("dateTime->"+dateTime); //##
    _debug("currentDate->"+currentDate()); //##
    _debug("patient_id->"+patient_id()); //##
    _debug("patientKanjiName->"+patientKanjiName()); //##
    _debug("userCode->"+userCode()); //##
    
    if (!patient_id()){
        alert("カルテが読込まれていません");
        return;
    }
    
	if (userCode() != "all"){
		// アクセスコード４（参照・修正・削除許可）以外ならページ追加をしない
		alert("アクセス・コード: "+userCode()+" なので新規ページ追加権限がありません");
    } else if (isSameDate(dateTime, currentDate()) == 1){
		// dateTime と時刻は違うが、同じ日付のページがすでに存在する
		if (confirm(dateTime + " と同じ日付のページ（ "+currentDate()+" ）はすでにあります。同日再診として追加しますか？")){
            setCurrentDate(dateTime);
			NRAddPage(owner(), patient_id(), dateTime, addedPage);
		}
	} else {
		// 開こうとするページが存在しなかった
		if (isSameDate(dateTime, today())){
			// 開こうとするページが本日なら、新規ページを追加
            _debug("addPage today->"+owner()+"->"+patient_id()+"->"+dateTime); //##
            
            setCurrentDate(dateTime);
			NRAddPage(owner(), patient_id(), dateTime, addedPage);
		} else {
			if (confirm(dateTime + " は本日ではありません。追加しますか？")){
                setCurrentDate(dateTime);
				NRAddPage(owner(), patient_id(), dateTime, addedPage);
			} else {
                alert("ページは追加しません"); //##
			}
		}
	}
}

///// PAGE //////////////////////////
/////////////////////////////////////

/////////////////////////////////////
///// OPEN CHART ////////////////////

var _currentBasicId;

function setCurrentBasicId(id){
    _currentBasicId = id;
}
function currentBasicId(){
    // 基本情報を表示するエリアの ID
    return _currentBasicId;
}

function doOpenBasicEditor(){
    // NRGetBasic() で氏名などが読み込まれてからページ・ヘッダーを表示
    openPageHeader();
    
    // パネル・エディターを表示
	window.open("panelEditor.php", "tools");
}
function openBasicEditor(dateTime){
	// panelEditor を開く
    // CellEditor が開いていたなら、close status にする必要あり
    var eid = editorId();
    if (eid)
        closeEditor(eid, true);
    
    // 空欄も省略せず表示
    setCurrentDate(dateTime);
    showPage(dateTime, true);
    
    NRGetBasic(dateTime, doOpenBasicEditor);
}

function doPageScrollTo(){
    // entryDate のページを画面上端にスクロール
    var elm = document.getElementById(currentDate() + ".date");
    var pos = getPosition(elm.parentNode.parentNode);
    
    // ページ・ヘッダーがきっかり画面の上端だと心理的にその上を見たい気持ちになるので
    // 80px ほどその上の部分も見えるようにする
    window.scroll(0, pos.y - 80);
    
    openPageHeader();
}
function pageScrollTo(dateTime){
    // entryDate のページを画面上端にスクロール
    setCurrentDate(dateTime);
    NRGetBasic(dateTime, doPageScrollTo);
}

function clickedReadOnly(elm){
    // 編集可能かどうかを返す：日付に関係なく無条件に checkBox の値に従わせる
    setIsReadOnly(elm.checked);
    closeWarm();
}

function openPageHeader(){
    // ページヘッダーを開く
    var elm = document.getElementById(currentDate() + ".basic");
    elm.innerHTML = "";

    var isToday = (isSameDate(currentDate(), today())) ? true :false;
    if (! isToday) elm.style.backgroundColor = "#eee";
    
    // === LEFT SIDE ===
    var div = newDIV(elm, "left-side");

    // 漢字氏名
    var kanji = valueForTag("NameSection.patientKanjiName");
    // if (!kanji) kanji = patientKanjiName(); // DB から読み出せない場合 TAB の名前を使う
    var sp = newSPAN(div, "");
    sp.style.paddingLeft = "5px";
    sp.style.fontSize = "12pt";
    sp.innerHTML = kanji;
    
    // かな氏名
    var kana = valueForTag("NameSection.patientKanaName");
    if (kana){
        // 他オーナーが登録したカルテを開く場合、自分で登録するまでフリガナは表示されない
        var sp = newSPAN(div, "");
        sp.style.paddingLeft = "10px";
        sp.style.fontFamily = "times, arial, Helvetica";
        sp.innerHTML =　"( " + kana + " )";
    }
    
    // 診療日の年令
    var sp = newSPAN(div, "");
    sp.style.paddingLeft = "10px";
    sp.style.fontFamily = "times, arial, Helvetica";
    var birthDate = birthDateWithPatientId(patient_id());
    sp.innerHTML =　ageAtDate(birthDate, currentDate()) + " 才";
    
    // 変更不可チェック
    var sp = newSPAN(div, "readOnlyCheckArea");
    sp.style.paddingLeft = "10px";
    if (isToday){
        // 本日なら無条件に readOnly を否定
        setIsReadOnly(false, currentDate());
    } else {
        // 本日以外なら setIsReadOnly() の判断に任せる
        setIsReadOnly(isReadOnly(), currentDate());
        var num = (isReadOnly()) ? 1 : 0;
        var cb = newCHECKBOX(sp, "readOnlyCheck", "編集不可", num);
        cb.setAttribute("onchange", "clickedReadOnly(this)");
    }

    // === RIRGHT SIDE ===
    var div = newDIV(elm, "right-side");
    div.style.paddingRight = "0"; // CSS を over write
    
    // ページ・メニューを表示
    var array = menuStructure();
    for (num in array){
        var cell = array[num];
        
        if (cell.menuType * 1 != _page) continue;
        if (cell.disabled * 1) continue;
        if (cell.subTitle * 1) continue;
        
        // メニュー項目を生成
        var sp = newSPAN(div, cell.id);
        sp.style.marginRight = "15px";
        sp.style.fontSize = "10pt";
        // cell.editor に infoTip に表示する内容が入っている
        setInfoTip(cell.id, cell.editor); // HELP
        
        if (cell.icon){
            // ICON があれば ICON を表示
            var img = newIMAGE(sp, "", cell.icon, "icon");
            img.style.height = "15px";
            img.style.verticalAlign = "middle";
            //    img.setAttribute("onclick", cell.url);
            var action = "kickMenuCell('" + cell.url + "','" + cell.window +"')";
            img.setAttribute("onclick", action);
            img.setAttribute("class", "expandIcon");
        } else {
            // アンカー表示
            var a = newA(sp, cell.label, "#", "");
            if (cell.url){
                // a.setAttribute("onclick", cell.url);
                var action = "kickMenuCell('" + cell.url + "','" + cell.window +"')";
                a.setAttribute("onclick", action);
            }
        }
    }

    // currentDate の付箋があれば開く
    showPostIt(); // postIt.js
}

function disableLabels(entryDate){
    // entryDate のラベルをインアクティブにする
    var obj = structure();
    var rec = obj[entryDate];
    var array = layoutArray(_progress);
    for (num in array){
        var layoutObj = array[num];
        
        if (layoutObj.disabled * 1) continue; // read-only
        
        var tag = layoutObj.tag;
        var cell = rec[tag];
        var id = entryDate + "." + tag + ".label";
        var labelBox = document.getElementById(id);
        if (labelBox){
            // レイアウト編集でチェックがはずれ非表示になっているものはスキップ
            labelBox.setAttribute("class", "");
            labelBox.setAttribute("onmouseout", null);
            labelBox.setAttribute("onmouseover", null);
            labelBox.setAttribute("onclick", null);
        }
    }
}

function showPage(entryDate, isTargetPage){
    // 一日分のページを生成
    var obj = structure();
    // rec は ProgressSection と NameSection のデータを保有
    var rec = obj[entryDate];
    
    // ページ・フレーム
    var pageBox = document.getElementById(entryDate + ".page");
    pageBox.innerHTML = "";
    pageBox.setAttribute("class", "pageBox"); 
    
    // ページ・ヘッダー・エリア
    var dv = newDIV(pageBox, entryDate + ".basic");
    dv.setAttribute("class", "pageHeader");
    
    var dv = newDIV(pageBox, "");
    var tbl = newTABLE(dv, "base-table");
    tbl.style.fontSize = "10pt";
    
    // 各 CELL を生成
    var array = layoutArray(_progress);
    for (num in array){
        var layoutObj = array[num];
        var tag = layoutObj.tag;
        var cell = rec[tag];
        
        if (!cell){
            // レイアウト編集で新たに追加されたフィールドなどの場合に発生
            // CELL が存在しないので新規に CELL 生成
            cell = setCell(entryDate, tag, "");
        }
        
        // 非表示セルをスキップ
        if (layoutObj.hitAndRun * 1) continue;
        
        // 空欄省略モードなら２ページ目以後の空欄をスキップ
        if ((trim(cell.htmlValue).length) == 0){
            if (!isTargetPage && omitStatus()) continue;
        }
        
        // === CELL ==============
        var tr = newTR(tbl, "", "");
        if ((isTargetPage == false) && (num > 0)){
            // 過去ページで主訴以後の欄なら罫線を表示
            tr.style.borderTop = "thin solid #ccc";
        }
        tr.setAttribute("onmouseover", "closeInfoTip()"); //##
        
        // === LABEL =============
        var labelBox = newTD(tr, entryDate + "." + tag + ".label", cell.label);
        labelBox.style.width = "60px"; // どういう訳か CSS が反映されない
        labelBox.style.veticalAlign = "top"; // どういう訳か機能しない
        labelBox.setAttribute("class", "labelBox");
        labelBox.setAttribute("onclick","openEditor('"+entryDate+"','"+tag+"')");
        
        // === VALUE ==============
        var valueBox = newTD(tr, cellId(entryDate, tag), "");
        valueBox.style.paddingLeft = "10px";
        valueBox.innerHTML = cell.htmlValue;

        // elm の背景色を cell.isPast により設定
        if (cell.isPast && isTargetPage)
            valueBox.style.backgroundColor = "#eff";
    }
}

var _addPageFlag;
function showPages(answer){
    // 指定された patientId の各ページを表示
    //alert("showPages->"+answer); //##
    
    var objct = JSON.parse(answer);
    
    _initDebug(false); //##
    _debug("== showPages: objct->"+encodeObject(objct)); //##
    
    setStructure(objct);
    
    // ページを時系列的に表示
	var div = document.getElementById("body");
	div.innerHTML = "";
    div.style.paddingTop = "5px";
    
    // structure() からページを表示するとともに cellList を生成
    var obj = structure();
    
    var firstPage = true;
    var hasTodayPage = false;
    var hasRecord = false; // obj にレコードが存在するか否か
    for (entryDate in obj){ // entryDate は最終受診日からはじまる
        // === PAGE FRAME ==========================
        var dv = newDIV(div, entryDate + ".pageFrame/pageNonFrame");
        //dv.style.border = "thin solid #f00"; //##
        var tbl = newTABLE(dv, "base-table");
        var tr = newTR(tbl, "", "");
        
        // === DATE TIME ===========================
        var td = newTD(tr, "/dateTag", "");
        td.style.width = "85px";
        td.style.textAlign = "right";
        td.style.padding = "3px 5px";
        td.style.verticalAlign = "top";
        td.setAttribute("onclick", "openBasicEditor('" + entryDate + "')");
        if (isSameDate(entryDate, today()))
            hasTodayPage = true;
        
        var ary = entryDate.split(" ");
        var date = ary[0];
        var time = ary[1];
        
        // === DATE ===
        var dv = newDIV(td, entryDate + ".date");
        dv.innerHTML = date;
        dv.style.fontFamily = "arial, Helvetica";
        dv.style.fontSize = "12pt";
        
        // === TIME and WEEK ===
        var dv = newDIV(td, "");
        var week = weekOfDate(entryDate);
        dv.innerHTML = time + " " + week;
        dv.style.fontSize = "10pt";
        dv.style.color = "#aaa";
        
        // === entryDate のページを生成 ==================
        var td = newTD(tr, entryDate + ".page", "");
        // ページ生成：フィールド毎に LABEL, VALUE を表示
        showPage(entryDate, firstPage);
        
        // 最初のページかどうかを判定
        if (firstPage){
            setCurrentDate(entryDate);
            
            var status = (isToday()) ? false : true;
            setIsReadOnly(status, entryDate);
            firstPage = false;
        }
        
        hasRecord = true;
    }
    
    if (!hasRecord){
        // カルテに１頁もない場合は自動的に頁追加
        addPage(todayAndTime());  // Ajax を起動するので openBasicInfo() 実行しない
        return;
    } else if (_addPageFlag && !hasTodayPage){
        // FRONT リストから開かれ、本日のページがない場合のみ
        addPage(todayAndTime()); // Ajax を起動するので openBasicInfo() 実行しない
        return;
    }
    
    // 最終受診日の基本情報を tools へ表示：ヘッダーへ氏名・フリガナなどを表示
    openBasicInfo(); // cellEditor.js
}

function pid_dragstart(event, pid){
    // ドラッグ開始時の処理
    // ドラッグするデータのid名をDataTransferオブジェクトにセット
    event.dataTransfer.setData("text", pid);
}

function closeWorkArea(){
    // workArea の padding を消す
    var elm =document.getElementById("workArea");
    elm.innerHTML = "";
    elm.style.padding = "0";
    
    return elm;
}

function openChart(pid, name, addPageFlag) {
	// patienId のカルテを開く
    setPatientId(pid); // patientId を記憶
    setPatientKanjiName(name); // name を記憶
    setCurrentBasicId(null); // 基本情報を表示するエリアの ID
    setEditorId(null); // エディターを閉じた状態にする
    _addPageFlag = (addPageFlag) ? true : false;
    
    // patientIdAndName の tab を挿入
    var action = "openChart('" + pid + "','" + name + "')";
    
    // workArea を閉じる
    closeWorkArea();
    
    // カルテを開く
    var elm = document.getElementById("pidArea");
    elm.innerHTML = pid.substr(0, 4) + "-" + pid.substr(4);
    setInfoTip("pidArea", "カルテ番号：drag & drop 可能"); // HELP
    
    // カルテID を drag and drop できるようにする
    elm.setAttribute("draggable", "true"); // HTML5: ドラッグ可能にする
    elm.setAttribute("ondragstart", "pid_dragstart(event,'" + pid + "')");
    
    
    NRGetProgressSection(owner(), pid, showPages);
}

function closeChart(pid, name){
    // patientIdAndName のタブを削除してカルテを閉じる
    if (!pid) pid = patient_id();
    if (!name) name = patientKanjiName();
    
    if (pid){
        document.getElementById("pidArea").innerHTML = "";
        document.getElementById("body").innerHTML = "";
    }
}

///// OPEN CHART ////////////////////
/////////////////////////////////////


/////////////////////////////////////
///// FIND PATIENT //////////////////

function gotPatientList(answer){
	// rowid のレコードをサーバから読込み
    var dom = closeWorkArea();
	var tbl = newTABLE(dom, "baseTable");
    tbl.style.fontSize = "10pt";
	var tr = newTR(tbl, "", "");
    tr.style.backgroundColor = "#ddd";
	var td = newTD(tr, "", "カルテ番号");
	var td = newTD(tr, "", "氏名");
	var td = newTD(tr, "", "ローマ字");
	var td = newTD(tr, "", "最終受診日");
	
	var records = JSON.parse(answer);
    
	var patientId, name;
	var count = records.length;
    for (r in records){
		var rec = records[r];
		var kanji = (rec.patientKanjiName) ? rec.patientKanjiName : "";
		patientId = rec.patientId;
        name = kanji;
		var romaji = (rec.patientRomajiName) ? rec.patientRomajiName : "";
		var lvd = (rec.lastVisitDate) ? rec.lastVisitDate : "";
		var tr = newTR(tbl, "record", "");
		var action = "openChart('" + rec.patientId + "','" + name + "')";
		tr.setAttribute("onclick", action);
		setChangeColor(tr, '#000', '#fff');
		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, "", "");
    tr.style.backgroundColor = "#ddd";
	var td = newTD(tr, "", records.length + " レコード ");
	td.setAttribute("colspan", "4");
    
	if (count == 1){
		// 検索結果が１件のみなら直ちにそのカルテを開く
		openChart(patientId, name);
	}
}
function showPatientList(){
	// 検索キーにマッチしたカルテのリストを表示
    var searchKey = document.getElementById("keyF").value;

    if (searchKey.length == 0){
        alert("検索キーが指定されていません");
    } else {
        setStoragedKey(searchKey); // localStorage に記憶
        NRGetPatients(searchKey, gotPatientList); // サーバでアクセス・ログに記憶
    }
}

///// FIND PATIENT //////////////////
/////////////////////////////////////

/////////////////////////////////////
///// FRONT /////////////////////////

function getFrontList(){
    // FRONT の受診者リストを表示
    var elm = document.getElementById("workArea");
    if (elm.innerHTML.length > 0){
        closeWorkArea();
        return;
    }

    // カルテ検索フィールドを生成
    var elm = document.getElementById("workArea");
    elm.innerHTML = "";
    elm.style.padding = "5px 5px";

    var dv = newDIV(elm, "/searchFrame");
    
    var fd = newFIELD(dv, "keyF", "", 20, storagedKey());
    fd.setAttribute("class", "searchField");
    fd.setAttribute("onchange", "showPatientList()");
    fd.focus();
    // 検索ボタン
    var bt = newSPAN(dv, "/searchButton");
    bt.innerHTML = "検索";
    bt.setAttribute("onclick", "showPatientList()");
}

///// FRONT /////////////////////////
/////////////////////////////////////


/////////////////////////////////////
///// CHART TAB ////////////////////

var _tabArray;
function initTabArray() {
	_tabArray = new Array();
}
function tabArray() {
	// CHART TAB の配列を返す
	return _tabArray
}
function addTab(label, action) {
	// label のタブを追加し action を設定
	if (label && trim(label).length){
		var obj = new Object();
		obj.label = label;
		obj.action = action;
		_tabArray.splice(0, 0, obj);
	}
}
function removeTab(label) {
	// label のタブを削除
	var array = new Array();
	for (num in _tabArray){
        var obj = _tabArray[num];
        if (obj.label != label)
            array.push(obj);
	}
	_tabArray = array;
	
	return _tabArray;
}

///// CHART TAB ////////////////////
/////////////////////////////////////


/////////////////////////////////////
///// OPEN TOOLS ////////////////////

function openToolPane(){
    // tools パネルを開く
    window.open("./tools.php", "tools");
}

function openCalendar(){
    // カレンダーを開く
    window.open("./calendar.php", "tools");
}

function doOpenDocMaker(){
    window.open("/DocMaker", "_blank");
}
function openDocMaker(){
    // 基本情報を読込んでから文書作成を開く
    _initDebug(isDebug(), window.document.getElementById("_test")); //##
    _debug("--- openDocMaker ---"); //##
    
    NRGetBasic(currentDate(), doOpenDocMaker);
}

function doOpenPrenatal(){
    window.open("/PerinatalManager", "_blank");
}
function openPrenatal(){
    // 基本情報を読込んでから周産期管理を開く
    NRGetBasic(currentDate(), doOpenPrenatal);
}

function doOpenHL7(answer){
    window.open("/HL7", "_blank");
}
function openHL7(){
    // Ajax 経由でないと別ウインドウでなくタブで開いてしまう
    NRGetToolMenu(owner(), doOpenHL7);
}

function openProblemList(){
    // problemList を表示
    window.open("problemList.php", "tools");
}

function htmlToPlain(html){
    // html テキストから全てのタグを取除いたテキストを返す
    var plain = "";
    var isTag = false;
    for (pos in html){
        var ch = html.charAt(pos);
        
        if (ch == "<") isTag = true;
        if (!isTag) plain += ch;
        if (ch == ">") isTag = false;
    }
    return plain;
}

function openMessenger(){
    // メッセンジャーを起動
    var obj = new Object();
    obj.sender = "@FRONT";
    obj.receiver = "@NOA";
    obj.message = "";
    obj.docId = "";
    obj.updateTime = todayAndTime();
    
    var st = "";
    if (patient_id())
        st = "--- " + patient_id() + " " + patientKanjiName() + "さん ---\n";

    showMessenger(obj, st);
}

function addTodayPage(){
    // グリーン・プラス・アイコンから起動される
    addPage(todayAndTime());
}

function removeTodayPage(){
    // レッド・マイナス・アイコンから起動される
    removePage(currentDate());
}

///// OPEN TOOLS ////////////////////
/////////////////////////////////////

/////////////////////////////////////
///// ACCESSS LOG ///////////////////

function opneLogChart(mode, patientId, patientName, addPageFlag){
    if ((mode == 0) && isShiftDown()){ // mode -- 0:履歴 1:待受
        var st = patientId+ " " + patientName + " の行を削除していいですか";
        if (confirm(st)){
            NRRemoveAccessLog(owner(), patientId, gotAccessLog);
        }
    } else {
        closeFloatPanel();
        openChart(patientId, patientName, addPageFlag);
    }
}

var _accessLog;
function sortAccessLog(){
    // 受付日時で逆ソートする
    var status = (accessLogReverse()) ? "" : "1";
    setAccessLogReverse(status);
    
    NRGetAccessLog(owner(), status, gotAccessLog);
}

function gotAccessLog(answer){
    //alert("gotAccessLog->"+answer); //##
    var obj = JSON.parse(answer);
    //alert("gotAccessLog->"+encodeObject(obj)); //return; //##

    var elm = document.getElementById("_confirm");
    if (!elm){
        alert("_confirm がないのでメッセージを表示できません"); return;
    }
	elm.innerHTML = "";
	elm.style.visibility = "visible";
	elm.style.left = 10; // 表示するx座標
	elm.style.top = 30; // 表示するy座標
	setFloatPanel(elm);
        
    var div = newDIV(elm, "");
    div.style.background = "#999";
    div.style.border = "thin solid #44f";
    
    // TITLE
	var tbl = newTABLE(div, "/logTable");
    var tr = newTR(tbl, "", "");
    tr.style.background = "#555";
    tr.style.fontSize = "9pt";
    var td = newTD(tr, "bookingSortTab/logTitle", "参照年月日");
    td.style.width = "140px";
    td.setAttribute("onclick", "sortAccessLog()");
    var td = newTD(tr, "/logTitle", "カルテID");
    td.style.width = "70px";
    var td = newTD(tr, "/logTitle", "氏名");
    td.style.width = "150px";

    var dv = newDIV(div, "");
	dv.style.height = "200px";
	dv.style.overflow = "auto";
    var tbl = newTABLE(dv, "/logTable");
    
    // RECORDS
    for (date in obj){
        var rec = obj[date];
        
        var tr = newTR(tbl, "", "");
        setChangeColor(tr, '#fff', '#888');
        var action = "opneLogChart(0,'" + rec.pid + "','" + rec.name + "')"
        tr.setAttribute("onclick", action);
        var td = newTD(tr, "/logColumn", date);
        td.style.width = "140px";
        var td = newTD(tr, "/logColumn", rec.pid + ""); // 数値だと表示されない
        td.style.width = "75px";
        var td = newTD(tr, "/logColumn", rec.name);
        td.style.paddingRight = "20px";
        td.style.width = "150px";
    }
    
    // FOOOTER
    var div = newDIV(div, "");
    div.style.background = "#555";
    div.style.textAlign = "right";
    div.style.padding = "2px 5px";
    var bt = newDIV(div, "/closeButton");
    bt.innerHTML = "X";
    bt.setAttribute("onclick", "closeFloatPanel()");
}
function showAccessLog(){
    // カルテのアクセス・ログを表示
    var elm = document.getElementById("_confirm");
    if (elm.innerHTML.length){
        closeFloatPanel();
        return;
    }

    // status が "1" なら逆順にソート
    var status = (accessLogReverse()) ? "1" : "";
    
    NRGetAccessLog(owner(), status, gotAccessLog);
}

///// ACCESSS LOG ///////////////////
/////////////////////////////////////


/////////////////////////////////////
///// BOOKING LIST //////////////////

var _waitingRecords;
function bookingCheckChanged(elm){
    // 診療済のレコードを表示/非表示に切り替え
    setBookingCheck(elm);

    // その条件で受診者リストを再表示
    showWaitingList();
}

function setBookingTodayCheanged(elm){
    // 本日のみ表示/非表示
    setBookingTodayCheck(elm);
    
    // その条件で受診者リストを再表示
    showWaitingList();
}

function showControls(){
    // フッター上のコントロール類を表示
    var elm = document.getElementById("controlBar");
    if (elm.innerHTML.length){
        elm.innerHTML = "";
        return;
    }
    makeControls(elm);
}

function makeControls(ctrl){
    // フッター上のコントロール類を生成
    ctrl.innerHTML = "";
    
    // 適用
    var sp = newSPAN(ctrl, "");
    sp.style.marginLeft = "5px";
    sp.innerHTML = "予約者";
    sp.setAttribute("class", "reserved");
    var sp = newSPAN(ctrl, "");
    sp.style.marginLeft = "5px";
    sp.innerHTML = "診療待";
    sp.setAttribute("class", "accepted");
    var sp = newSPAN(ctrl, "");
    sp.innerHTML = "診療済";
    sp.setAttribute("class", "finished");
    var sp = newSPAN(ctrl, "");
    sp.style.color = "#fff";
    var cb = newCHECKBOX(sp, "bookingCheck", "診療済を非表示", bookingCheck());
    cb.setAttribute("onchange", "bookingCheckChanged(this)");
    var sp = newSPAN(ctrl, "");
    sp.style.color = "#fff";
    var cb = newCHECKBOX(sp, "bookingTodayCheck", "本日のみ表示", bookingTodayCheck());
    cb.setAttribute("onchange", "setBookingTodayCheanged(this)");
}

function sortBookingList(){
    // 受付日時で逆ソートする
    var status = (bookingReverse()) ? "" : "1";
    setBookingReverse(status);

    // 本日の受診者と、それ以後の予約者のリストをサーバへリクエスト
    NRGetAcceptanceList(todayAndTime(), gotAcceptanceList);
}

function showWaitingList(){
    // 受診者リストを表示
    // localStorage の値によりソートするか逆ソートするかを決める
    var obj = _waitingRecords;
    
    var elm = window.top.noa.document.getElementById("_confirm");
	elm.innerHTML = "";
	elm.style.visibility = "visible";
	elm.style.left = 10; // 表示するx座標
	elm.style.top = 30; // 表示するy座標
	setFloatPanel(elm);
    
    var div = newDIV(elm, "");
    div.style.background = "#77f";
    div.style.border = "thin solid #44f";
    
    // === TITLE ===
	var tbl = newTABLE(div, "/bookingTable");
    var tr = newTR(tbl, "", "");
    tr.style.fontSize = "9pt";
    var td = newTD(tr, "bookingSortTab/bookingTitle", "受 付 日 時");
    td.style.width = "140px";
    td.setAttribute("onclick", "sortBookingList()");
    var td = newTD(tr, "/bookingTitle", "カルテ ID");
    td.style.width = "70px";
    var td = newTD(tr, "/bookingTitle", "氏 名");
    td.style.width = "150px";
    
    var dv = newDIV(div, "");
	dv.style.height = "200px"; // パネルの高さ
	dv.style.overflow = "auto";
    var tbl = newTABLE(dv, "/bookingTable");
    
    // === RECORDS ===
    var ignoreFinished = bookingCheck(); // 診療済を非表示
    for (num in obj){
        var rec = obj[num];
        var isFinished = (rec.endTime && rec.endTime.toString().length) ? true : false;
        var isToday = isSameDate(rec.entryDate, today());
        
        if (ignoreFinished && isFinished) continue; // 診療済をスキップ
        if (bookingTodayCheck() && !isToday) continue; // 本日以外をスキップ
        
        var tr = newTR(tbl, "", "");
        setChangeColor(tr, '#fff', '#77f');
        // entryDate
        var td = newTD(tr, "/bookingColumn", rec.entryDate);
        td.style.width = "140px";
        if (rec.reserved * 1 > 0){
            td.setAttribute("class", "reserved"); // 予約
            var action = "opneLogChart(1,'" + rec.patientId + "','" + rec.kanjiName + "')"
        } else if (isFinished){
            td.setAttribute("class", "finished"); // 診療済み
            var action = "opneLogChart(1,'" + rec.patientId + "','" + rec.kanjiName + "')"
        } else {
            td.setAttribute("class", "accepted"); // 診療待ち
            var action = "opneLogChart(1,'" + rec.patientId + "','" + rec.kanjiName + "','addPage')"
        }
        tr.setAttribute("onclick", action);
        // patientId
        var td = newTD(tr, "/bookingColumn", rec.patientId + ""); // 数値だと表示されない
        td.style.width = "70px";
        // patientKanjiName
        var td = newTD(tr, "/bookingColumn", rec.kanjiName);
        td.style.paddingRight = "20px";
        td.style.width = "150px";
    }
    
    // === FOOOTER ===
    var dv = newDIV(div, "");
    dv.style.background = "#55f";
    dv.style.fontSize = "9pt";
    // --- 設定コントロール類 ---
    var sp = newSPAN(dv, "bookingOpen");
    sp.setAttribute("onclick", "showControls()");
	var img = newIMAGE(sp, "", "./hammer.png", "?");
	img.style.height = "14px";
	img.style.verticalAlign = "middle";
    var ctrl = newDIV(dv, "controlBar/bookingControls");
    setInfoTip("bookingOpen", "摘要や初期設定を表示"); // HELP
    // --- CLOSe BUTTON ---
    var sp = newSPAN(dv, "");
    sp.style.padding = "4px 5px 0px 0px";
    sp.style.display = "inline";
    sp.style.float = "right";
    var bt = newDIV(sp, "/closeButton");
    bt.innerHTML = "X";
    bt.setAttribute("onclick", "closeFloatPanel()");
}

function gotAcceptanceList(answer){
    //alert("gotAcceptanceList->"+answer); //##
    var obj = JSON.parse(answer);
    //alert("gotAcceptanceList->"+encodeObject(_waitingRecords)); //return; //##

    _waitingRecords = (bookingReverse()) ? obj.reverse() : obj;

    showWaitingList();
}
function showBookingList(){
    // 受診者リストを表示
    var elm = document.getElementById("_confirm");
    if (elm.innerHTML.length){
        closeFloatPanel();
        return;
    }
    
    // 本日の受診者と、それ以後の予約者のリストをサーバへリクエスト
    NRGetAcceptanceList(todayAndTime(), gotAcceptanceList);
}

///// BOOKING LIST //////////////////
/////////////////////////////////////



/////////////////////////////////////
///// SEARCH ////////////////////////

function search(){
    // 検索を実行
	var key = document.getElementById("searchF").value;
    if (!key) return;
    
    var count = searchRecord(key);
    
    // キーが最初にみつかったページを画面上端に表示
    jumpToKey(-1);
    
    alert(key + " が ( " + count + " 件 ) みつかりました。黄色い該当部分をクリックすると次の該当部分へジャンプします。");
}

///// SEARCH ////////////////////////
/////////////////////////////////////

function test(){
    var url = "./imageViewer.php?value=/NOA_ARCHIVE/11028300/20121022152257_0.jpg";
    
	openImage(url);
}

function noaHelp(){
	// 別途ヘルプをパネル表示
	window.open("./noaHelp.html","Help"
				,"width=450,height=700,scrollbars=yes,resizable=yes");
}

// ###########################################
// ### FireFox 系ブラウザのイベント操作に必要 ######
var _Event = null;
document.onkeyup = function(e){
    　_Event = null;
}
document.onkeydown = function(e){
    　_Event = e;
}
function isShiftDown(){
    // shift が押されていれば true を返す
    var shift;
    
    if (_Event != null){
        shift = _Event.shiftKey;
    } else {
        if (navigator.userAgent.indexOf('Firefox', 0) == -1)
            shift = event.shiftKey;
        else
            shift = false;
    }
    return shift;
}
function eventKeyCode(){
    // keyCode 返す
    if (_Event != null){
        return _Event.keyCode;
    }
    return null;
}
// ### FireFox 系ブラウザのイベント操作に必要 ######
// ###########################################

function initNOA( ) {
    setHospitalContainer(); // neuron.js: localStorage 渡しのパラメータを記憶
    
    var elm = document.getElementById("base");
    elm.innerHTML = "";
    
    // workArea
    var div = newDIV(elm, "workArea");
    
    // polling でゲットした受診者タブを表示
    var div = newDIV(elm, "pollingArea");
    
    // メッセージ退避エリア
    var div = newDIV(elm, "messageShelterArea");
    
    // alertArea
    var div = newDIV(elm, "alertArea");
    div.style.paddingLeft = "10px";
    div.style.fontSize = "10pt";
    
    // === HEADER ===
    var div = newDIV(elm, "title-bar");
    // --- LEFT SIDE ---------------
    // カルテ検索アイコン
    var dv = newDIV(div, "");
    dv.style.float = "left";
    dv.style.margin = "0 10px";
    var img = newIMAGE(dv, "addChartIcon", "search.png", "search");
    img.style.height = "18px";
    img.style.verticalAlign = "bottom";
    img.setAttribute("onclick", "getFrontList()");
    setInfoTip("addChartIcon", "カルテを検索して開く"); // HELP
    img.setAttribute("class", "expandIcon");
    // patientId
    var dv = newDIV(div, "pidArea");
    // --- RIGHT SIDE ---------------
    // 周辺ツール・アイコンを表示するエリア
    var dv = newDIV(div, "toolIconArea");
    
    // === BODY ===
    var div = newDIV(elm, "body/close-float");
    
    // === FOOTER ===
    var div = newDIV(elm, "title-bar");
    // LEFT-SIDE
    var dv = newDIV(div, "left-side");
    dv.innerHTML = hospitalName() + " ( 取扱者 " + userName() + " )";
    // RIGHT-SIDE
    var dv = newDIV(div, "version/right-side");
    dv.innerHTML = version();
    dv.style.position = "relative";
    dv.style.marginTop = "4px";

    /*************
    // デバッグ用チェックボックス
    var div = newDIV(elm, "");
    div.style.fontSize = "9pt";
    div.style.padding = "2px 2px";
    var cb = newCHECKBOX(div, "", "debug", noaDebug());
    cb.setAttribute("onchange", "setNoaDebug(this)");
     *************/
    
    // FRONT での新規受付患者をチェック
    if (noCheckWaiting() == 0)
        polling();
    
    // 初心者用に NOA ヘルプを表示
    if (showHelp() == 0) noaHelp();
    
    // TOOL MENU 構造をサーバへリクエスト
    NRGetToolMenu(owner(), gotToolMenuStructure);
}

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