

// currentDate() は外部参照をわかりやすくするため noa.js に置く

var _editorId;
function setEditorId(id){
    _editorId = id;
}
function editorId(){
    // 編集中の CELL のタグ
    return _editorId;
}

var _menus;
function setMenus(array){
    _menus = array;
}
function menus(){
    return _menus;
}

var _isNewPage;
function setIsNewPage(status){
    _isNewPage = status;
}
function isNewPage(){
    // ページが遷移した
    return _isNewPage;
}

/////////////////////////////////////////////////
///// MENU //////////////////////////////////////

function menuItems(menuArray, key){
    // メニュー・データを表示用にカスタマイズして返す
    var array = [""];
    for (num in menuArray){
        var item = menuArray[num];
        // 絞り込みキーにマッチしないものはスキップ
        if (key && (item.indexOf(key) < 0)) continue;
        
        array.push(menuArray[num]);
    }
    array.push("...その他");
    return array;
}

var _targetTag;

function compareFreq(a, b){
    // a:"freq^$^item"
    // separator を ":" にすると、”lmp:" など : を含むタイトルが正確に処理されない
    var ary1 = a.split("^$^");
    var ary2 = b.split("^$^");
    
    // freq で比較
    return ary2[0] - ary1[0];        
}

function showFrequency(answer){
	// メニューの頻度がインクリメントされたレスポンスを得る
	// ポップアップメニューを再描画
	var obj = JSON.parse(answer);
    //alert("showFrequency --\n"+encodeObject(obj)); //##
    
    // incrementFrequency() で戻ってくる menuItems は attributes で記憶しているもの
    // とは形式が異なるので、attributes で記憶している形式に修正
    var array = new Array();
	for (num in obj){
        var rec = obj[num];
        array.push(rec.freq + "^$^" + rec.menu);
	}
    array.sort(compareFreq); // freq でソート
    
    // array の freq を取り除いた配列をつくる
    var menus = new Array();
    for (num in array){
        var st = array[num];
        var ary = st.split("^$^");
        var freq = ary[0];
        var item = ary[1];
        menus.push(item);
    }
    
    // ポップアップ・メニューを再描画
    var elm = document.getElementById("menuPopArea");
    if (elm){ // _rotary_ type 以外では不要
        elm.innerHTML = "";
        var pu = makePopupMenu(elm, "menuPop", menus, "");
        pu.setAttribute("onchange", "popupChanged(this)");
    }
}
function incrementFrequency(tag, menuItem, value){
	// 選択されたメニューの頻度を１つ増やす
	// ### menuItem が MenuTable に存在しない場合 menuItem の新規登録も行う
    _targetTag = tag; // currentTag() がフィールド遷移で変わるのでここで記憶しておく
	NRPutMenu(owner(), tag, menuItem , "", value, showFrequency);
}

function addMenu(){
    // menuItem を新規追加
    var item = prompt("新規に追加するメニュー項目");
    if (item.length){
        // item をサーバへ登録するために incrementFrequency() を使う
        incrementFrequency(currentTag(), item, "");
    }
}

function focusPressed(){
    // 絞り込みフィールドでキーが押される度に実行
    var elm = document.getElementById("menuPopArea");
    elm.innerHTML = "";
    
    var key = document.getElementById("focusF").value;
    var pu = makePopupMenu(elm, "menuPop", menuItems(menus(), key), "");
    pu.setAttribute("onchange", "popupChanged(this)");
}
function insertMenuItem(item){
    // メニューの選択内容が変更された
    if (item == "...その他"){
        addMenu();
        return;
    }
    
    // フィールドの種類により item をモディファイ
    // ProgressSection.treatment などの場合は年月日をつける
	// ## item 自体を変更すると最後の incrementFrequency() で
	// ## 新規登録されてしまうので menuItem に名称を変え使用する
    var menuItem = modifyItem(currentTag(), item);
    
	// 選択されたアイテムを文中に挿入
    var elm = document.getElementById(editorId() + ".text"); // 文章
    var html = elm.innerHTML;
    var field = fieldForTag(currentTag());
	if (pureSize(html) == 0){ // 入力先が空欄の場合
		elm.innerHTML = menuItem;
	} else {
		switch (field.menuAction * 1){ // insert position
			case _menu_to_tail_: // 0: 文末へ追加
				elm.innerHTML = html + " " + menuItem;
				break;
			case _menu_to_last_row_: // 1: 最終行へ追加
				elm.innerHTML = html + "<br>" + menuItem;
				break;
			default: // 2 _menu_replace_: 置換
				elm.innerHTML = menuItem;
				break;
		}
	}
    
    // 使用されたメニュー項目の頻度を increment
    incrementFrequency(currentTag(), item, "");
    
    // 一回のみ選択なら次フィールドへジャンプ
    if (field.buttonType * 1 > 0){
        saveAndJumpEditor(currentTag());
    }
    
    function pureSize(html){
        // HTML をプレーンテキストにした trim サイズ を返す
        var doc = htmlForValue(html); // "<br>" を "\n" へ変換
        doc = convertSTRING(doc, "&nbsp;", "");
        
        return trim(doc).length;
    }
}
function popupChanged(elm){
    // ポップアップメニューが選択された
    var item = elm.value;
    
    insertMenuItem(item);
}

///// MENU //////////////////////////////////////
/////////////////////////////////////////////////

/////////////////////////////////////////////////
///// GROUP_MENU ////////////////////////////////

var _groupEditorOpen;
function setGroupEditorOpen(status){
    //showToolMessage("setGroupEditorOpen-> "+status);
    _groupEditorOpen = status;
}
function groupEditorOpen(){
    // グループ・メニューのサブ・エディターが開いていれば true を返す
    return _groupEditorOpen;
}

function addGroupMenu(){
    // グループ・メニューに新しい項目を追加
	window.open("groupMenuEditor.php", "tools"); // CELL PREFERENCE
}

function doNothing(answer){
    // ### 頻度情報が変更になっただけなので何もしない ###
}
function groupPopupChanged(elm){
    // グループ・メニューの選択内容が変更された
    var item = elm.value;
	if (isSame(item, "...その他")){
		addGroupMenu();
        return;
	}
    
    // freq = "" なら、使用されたメニュー項目の頻度を increment
    // ### doNothing の代わりに null や "" を指定すると正常終了しない
    NRPutGroupMenu(owner(), item, "", null, doNothing);
}

function closedGroupSubEditor(answer){
    // 全てのサブ・エディターを閉じサーバの保存内容を表示
    var obj = JSON.parse(answer);
    //alert("closedGroupSubEditor->"+encodeObject(obj)); //##
    
    setGroupEditorOpen(false);
    
    var array = progressTagArray();
    for (num in array){
        var tag = array[num];
        var eid = cellId(currentDate(), tag);
        
        var cell = setCell(currentDate(), tag, obj[tag]);
        setCellToStructure(currentDate(), tag, cell);
        
        var elm = document.getElementById(cell.id);
        elm.innerHTML = cell.htmlValue;
    }
}
function closeGroupSubEditor(needSave){
    // 何も変更せずに subEditor を閉じる
    if (groupEditorOpen()){
        // サブ・エディターが開いているなら
        setEditorId(null);
        setGroupEditorOpen(false);
        var array = progressTagArray();
        if (needSave){
            var container = new Object();
            for (num in array){
                var tag = array[num];
                var eid = cellId(currentDate(), tag);
                // 内容に変更あれば Editor 内容をサーバへ保存
                var val = document.getElementById(eid + ".text").innerHTML;
                val = seeAsNOAFormat(val);
                var cell = cellFor(currentDate(), tag);
                var originalVal = seeAsNOAFormat(cell.htmlValue);
                if (originalVal != val){ // データが編集されているなら
                    container[tag] = val; // 編集されたデータ
                }
            }
            
            NRPutPage(owner(),patient_id(),currentDate(),timeLimit(),container,closedGroupSubEditor);
        } else {
            for (num in array){
                var tag = array[num];
                var cell = cellFor(currentDate(), tag);
                
                // Editor を削除し、元の表示に戻す
                document.getElementById(cell.id).innerHTML = cell.htmlValue;
            }
        }
    } else {
        // グループ・メニューのあるエディターだけが開いているなら
        closeEditor(editorId(), needSave);
    }
}

function insertedGroupMenuItems(answer){
	// グループメニューのテンプレートを各フィールドに挿入
    //alert("insertedGroupMenuItems->"+answer); //##
    
    var obj = JSON.parse(answer);
    //alert("obj->"+encodeObject(obj)); //##
    
    var array = progressTagArray();
    
    //_initDebug(false); //##
    
    //alert("progressTagArray->"+encodeObjectarray); //##
    
    // 各編集フィールドにメニュー内容を追加し、それを save する
    for (num in array){
        var tag = array[num];
        var ary = tag.split('.');
        var fieldName = ary[1];
        var menuItem = obj[fieldName];
        
        var cell = cellFor(currentDate(), tag);
        
        if (tag == currentTag()){
            // tag の編集フィールド内データに menuItem を挿入
            var elm = document.getElementById(cell.id + ".text");
            elm.innerHTML = addGroupItem(elm.innerHTML, menuItem);
        } else {
            // tag に相当する cell.value に menuItem を挿入
            showSubEditor(cell, menuItem);
        }
    }
    setGroupEditorOpen(true);
    
    function addGroupItem(cVal, mVal){
        // 元々の値にグループ・メニューの値を加える
        // mVal の改行を <BR/> に変換し、文字列前後の <BR/> を取り去る
        mVal = convertSTRING(mVal, "<BR/>", "\n");
        mVal = trim(mVal); // mVal 前後の改行や空白を取り去る
        mVal = (mVal.length > 0) ? convertSTRING(mVal, "\n", "<BR/>") : "";
        
        // CELL の値である cValue にメニュー・アイテムの文字列を追加
        cVal = convertSTRING(cVal, "<BR/>", "\n");
        cVal = trim(cVal); // cVal 前後の改行や空白を取り去る
        
        if (cell.tag == "ProgressSection.subject"){
			// 入力欄に存在する #problemNumber の最大値のひとつ上の値
			// を付した #problemNumber で template を文頭に挿入
            // ### maxNum() には cVal が '\n' で区切られていることが必要 ###
            mVal = "#" + maxNum(cVal) + " " + mVal;
            cVal = (cVal.length > 0) ? convertSTRING(cVal, "\n", "<BR/>") : "";

            // メニュー項目を先頭に挿入
            return (trim(cVal).length > 0) ? mVal + "<BR/>" + cVal : mVal;
        } else if (cell.tag == "ProgressSection.disease"){
            var array = new Array();
            var ary = mVal.split('<BR/>');
            for (num in ary)
                array.push(modifyItem(cell.tag, ary[num]));
            mVal = array.join('<BR/>');
            cVal = (cVal.length > 0) ? convertSTRING(cVal, "\n", "<BR/>") : "";

            // メニュー項目を末尾に追加
            return (trim(cVal).length > 0) ? cVal + "<BR/>" + mVal : mVal;
        } else {
            cVal = (cVal.length > 0) ? convertSTRING(cVal, "\n", "<BR/>") : "";
            
            // メニュー項目を末尾に追加
            return (trim(cVal).length > 0) ? cVal + "<BR/>" + mVal : mVal;
        }
      
        function maxNum(doc){
            // 各行をチェックして最大番号を取り出す
            var array = doc.split("#"), max=0;
            for (i in array){
                var ln = array[i];
                var ary = ln.split(" ");
                num = ary[0] * 1;
                if (num > max) max = num;
            }
            return max + 1;
        }
    }
    
    function showSubEditor(cell, val){
        // GROUP MENU により従属するフィールドの CELL EDITOR を開く
        var elm = document.getElementById(cell.id);
        elm.innerHTML = "";
        var div = newDIV(elm, "");
        div.style.padding = "0px 10px";
        div.style.backgroundColor = "#ffa";
        div.style.border = "thin solid #aaa";

        // TEXT
        var dv = newDIV(div, cellId(currentDate(), cell.tag) + ".text");
        dv.style.padding = "3px 3px";
        dv.style.backgroundColor = "#fff";
        dv.innerHTML = addGroupItem(cell.htmlValue, val);
        dv.contentEditable = true; // TEXT を編集可能状態にする
    }
}
function insertGroupItems(){
	// グループメニューのクリックによりテンプレート内容を各フィールドに挿入
	// グループメニューの頻度をインクリメント
	var item = document.getElementById("menuPop").value;
    //alert("insertGroupItems->"+item+"->"+owner()); //##
    
	NRGetGroupMenuItems(owner(), item, insertedGroupMenuItems);
}

///// GROUP_MENU ////////////////////////////////
/////////////////////////////////////////////////

/////////////////////////////////////////////
///// address ///////////////////////////////

function putAddress(){
    // 住所メニューの町村が選択された時、メニューの都道府県を入力欄へ転記
    var tag = "AddressSection.address";
    var prefecture = document.getElementById("prefPop").value;
    var city = document.getElementById("cityPop").value;
    var village = document.getElementById("villagePop").value;
    
    if (isSame(village, "...その他")){
		village = window.prompt("町村名(のみ)を入力してください", "");
		if (village.length == 0) return;
        
        // 町村を登録
        // 選択アイテムが存在しなければ登録、存在すれば頻度をインクリメント
        NRPutMenu(owner(), city, village, 1, "", gotVILLAGE);
	} else {
        // 選択されたアイテムを文中に挿入
        var elm = document.getElementById(editorId() + ".text"); // 文章
        elm.innerHTML = prefecture + " " + city + " " + village + "&nbsp;";
        elm.focus();
        // HTML5：選択された欄の文末にカーソルを置く
        var sel = window.getSelection();
        sel.collapseToEnd();
    }
}

var _selectedAddress;
function gotVILLAGE(answer){
	var obj = JSON.parse(answer);
    var shiku = document.getElementById("cityPop").value;
    if (shiku.length == 0){
        return; // 町村のポップアップメニューを表示しない
    } else {
        var menuItems = [""]; // 最初に空メニューを入れておく
        for (num in obj){
            var rec = obj[num];
            menuItems.push(rec.menu); // メニューアイテム
        }
        menuItems.push("...その他");
    }
    
	// 町村ポップアップを更新
    var elm = document.getElementById("_chouson");
    elm.innerHTML = "";
    var cell = cellFor(currentDate(), currentTag());
    var value = cell.trimValue;
    var val = "";
    if (value){
        var addressArray = value.split(" ");
        val = addressArray[2];
    }
    
    var pu = makePopupMenu(elm, "villagePop", menuItems, val);
    // 町村 が変更されたら 都道府県 を入力欄に転記
    pu.setAttribute("onchange", "putAddress()");
}
function getVILLAGE(elm){
    // 町村のポップアップを設定
    var shiku = elm.value;
	if (isSame(shiku, "...その他")){
		shiku = window.prompt("市区名(のみ)を入力してください", "");
		if (shiku.length == 0) return;
        var tag = document.getElementById("prefPop").value;
        _selectedAddress = shiku;
        // todoufuken を登録
        // 選択アイテムが存在しなければ登録、存在すれば頻度をインクリメント
        NRPutMenu(owner(), tag, shiku, 1, "", gotCITY);
	} else {
        NRGetMenu(owner(), shiku, gotVILLAGE);
    }
}

function gotCITY(answer){
	var obj = JSON.parse(answer);
    var todoufuken = document.getElementById("prefPop").value;
    
    if (todoufuken.length == 0){
        return; // 市区のポップアップメニューを表示しない
    } else {
        var menuItems = [""]; // 最初に空メニューを入れておく
        for (num in obj){
            var rec = obj[num];
            menuItems.push(rec.menu); // メニューアイテム
        }
        menuItems.push("...その他");
    }
    
	// 町村ポップアップを更新
    var elm = document.getElementById("_shiku");
    elm.innerHTML = "";
    var cell = cellFor(currentDate(), currentTag());
    var value = cell.trimValue;
    var val = "";
    if (value){
        var addressArray = value.split(" ");
        val = addressArray[1];
    }
    
    var pu = makePopupMenu(elm, "cityPop", menuItems, val);
    // 市区 が変更されたら 町村 のメニューを取り寄せる
    pu.setAttribute("onchange", "getVILLAGE(this)");
    getVILLAGE(pu);
}
function getCITY(elm){
    // 市区のポップアップを設定
    var todoufuken = elm.value;
	if (isSame(todoufuken, "...その他")){
		todoufuken = window.prompt("都道府県名(のみ)を入力してください", "");
		if (todoufuken.length == 0) return;
        _selectedAddress = todoufuken;
        // todoufuken を登録
        // 選択アイテムが存在しなければ登録、存在すれば頻度をインクリメント
        NRPutMenu(owner(), "都道府県", todoufuken, 1, "", gotCITY);
	} else {
        NRGetMenu(owner(), todoufuken, gotCITY);
    }
}

///// address ///////////////////////////////
/////////////////////////////////////////////


///////////////////////////////////////////////////////
///// 周辺ツール ////////////////////////////////////////

///// 処方ツール

function getPrescription(value, touchAndGo){
	// 処方箋からデータを受け取る標準 API
	var type = medicalEncodeType(value); // lib.js
	if (type == "NOA"){
		// NOA 形式で受け取る場合 (prescription.js 側も対応の必要あり)
		var obj = decodeObject(value); // value は処方情報のみ
	} else if (type == "HL7"){
		// HL7 形式で受け取る場合 (prescription.js 側も対応の必要あり)
		var obj = HL7ToObject(value); // value は患者基本情報・保険情報・処方情報
	}
	
    var val = objectToShohouText(obj.prescription, obj.isOwn);
    
    // 編集エリアの内容を val へ置換
    gotValueFromTool(val, touchAndGo);
    
	function objectToShohouText(obj, isOwn){
		// object をこの電子カルテの処方表示フォーマットへ変換
		var buff = "";
        if (isOwn) buff = "=== 自費処方 ===<br>";
		for (key in obj){
			var val = obj[key];
			if (typeof(val) == "object"){
				// グループの中を処理
				buff +=  objectToShohouText(val);
			}
			else {
				// レコードの処理
				if (obj.code > 100) buff += "----- "; // 用法行の場合
				buff += obj.name + "(" + obj.dose + " " + obj.unit + ")<br>";
				return buff;
			}
		}
		return buff;
	}
}
function doOpenPrescriptionEditor(){
    // ### 処方箋ツールからデータ受信 API として getPrescription() をインプリしておくこと
	window.open("/Prescription/prescription.php", "tools");
    openPageHeader(); // NRGetBasic() を使ったら原則的に起動
}
function openPrescriptionEditor(){
	// 処方箋ツールを開く
    // その受診日の 基本情報を 読込んだ後 doOpenPrescriptionEditor を実行
    NRGetBasic(currentDate(), doOpenPrescriptionEditor);
}


///// FORM 伝票ツール

function cellLabel(){
    // Form.js から呼ばれる API
    var cell = cellForId(editorId());
    
    return cell.label;
}

function cellTag(){
    // Form.js から呼ばれる API
    return currentTag();
}

function cellValue(){
    // Form.js から呼ばれる API
    var cell = cellForId(editorId());
    
    var val = convertSTRING(cell.htmlValue, "<BR/>", "");
    
    return val;
}

function gotValueFromTool(val, touchAndGo){
    // 周辺ツールから値 val を受け取るための API
    var cell = cellForId(editorId());
    if (!cell){
        alert(editorId() + " の CELL がありません");
        return;
    }
    
    // 編集エリアの内容を置換
	document.getElementById(cell.id + ".text").innerHTML = val;
    
    // 必要なら内容をサーバへ保存し Editor を閉じる
    if (touchAndGo) closeEditor(editorId(), true);
}
function doOpenForm(){
    // ### 処方箋ツールからデータ受信 API として gotValueFromTool() をインプリしておくこと
	window.open("form.php", "tools");
    openPageHeader(); // NRGetBasic() を使ったら原則的に起動
}
function openForm(){
	// FORM 編集ペーンを開く
    NRGetBasic(currentDate(), doOpenForm);
}


///// その他のツール

function doOpenVinEditor(){
    window.open("vin.php", "tools");
    openPageHeader(); // NRGetBasic() を使ったら原則的に起動
}
function openVinEditor(){
	// VIN：診療費計算ツールを開く
    NRGetBasic(currentDate(), doOpenVinEditor);
}

function openGestateCalendar(cellId){
    // 妊娠歴を開く
    var url = encodeSTRING("../../GC?elementId=" + cellId + ".text");
	var win = window.open(url ,"tools"
						  ,"width=330,height=900,scrollbars=yes,resizable=yes");
	win.focus();
}

function openPictureTool(){
    // 画像読込ツールを開く
	var win = window.open("../../Picture","tools");
}

function doOpenOpenBasicInfo(){
    // 基本情報画面を開く
    window.open("panelEditor.php", "tools");
}
function openBasicInfo(){
    // 基本情報画面を開く
    NRGetBasic(currentDate(), doOpenOpenBasicInfo);
}

function openInsurance(){
    // 保険情報編集ツールを開く
    window.open("insurance.php", "tools");
}

///// 周辺ツール ////////////////////////////////////////
///////////////////////////////////////////////////////


function seeAsNOAFormat(val){
    // 比較用に HTML 関連の文字列を NOA 形式に正規化
    val = convertSTRING(val, "<br>", "\n");
    val = convertSTRING(val, "<BR/>", "\n");
    val = convertSTRING(val, "&nbsp;", " ");
    val = convertSTRING(val, "<div>", "\n");
    val = convertSTRING(val, "</div>", "\n");
    val = convertSTRING(val, "\n\n", "\n"); // ## これで果たして OK ? ##
    
    return val;
}

var _textForEdit;
var _nextTag;
function savedEditor(answer){
    // サーバへ保存された内容を確認のため再表示
    var obj = JSON.parse(answer);
    
    //showFadeoutInfo("alertArea", "savedEditor-> "+encodeObject(obj), 5000);
    
    // CELL 内容を書き戻す
    var cell = setCell(obj.entryDate, currentTag(), obj[currentTag()]);
    setCellToStructure(obj.entryDate, currentTag(), cell);
    
    // Editor を削除し、元の表示に戻す
    recoverCellView(cell.id);

    // 次に開くべきエディターがあれば開く
    if (_nextTag){
        openEditor(_nextTag['date'], _nextTag['tag']);
    }
}
function recoverCellView(eid){
    // エディターを閉じた後、元の表示に戻す
    var cell = cellForId(eid);
    var elm = document.getElementById(cell.id);
    elm.innerHTML = cell.htmlValue;
    resetColor(elm, "#000", "#fff"); // address の場合 yellow のことがあるので
    setEditorId(null);
}
function closeEditor(eid, needSave, nextTag){
    // CELL EDITOR を閉じる：needSave が true なら変更内容を保存
    var elm = document.getElementById(eid);
    if (!elm){
        // cellEditor の elm はここでは存在しないはずなので panelEditor のはず
        // panelEditor 側に開いている editor があったら閉じる
        // cellEditor から直接 panelEditor の個別エディターを操作できないので
        // panelEditor 自体を開き直す
        setEditorId(null);
        doOpenBasicEditor();
        return;
    }

    _nextTag = nextTag; // 次に開くべきエディターの tag: null の場合もある
    
    if (needSave){
        // 内容に変更あれば Editor 内容をサーバへ保存
        var val = document.getElementById(eid + ".text").innerHTML;
        val = seeAsNOAFormat(val);
        var cell = cellForId(eid);
        var originalVal = seeAsNOAFormat(cell.htmlValue);
        
        if (originalVal != val){ // データが編集された
            if (currentTag() == "ProgressSection.object"){
                // val にイメージデータがペーストされた場合 < > を実データに変換
                val = replaceAll(val, "&lt;", "<");
                val = replaceAll(val, "&gt;", "/>");
                
                // val 中に表示用イメージ・アンカーがあった場合、元の保存形式に戻す
                val = decodeImageLink(val);
            }
            
            // 変更内容をサーバへ送る：savedEditor() でサーバから結果を CELL へ書き戻す
            var container = new Object();
            container[cell.tag] = val; // 編集されたデータ
            
            // この後 openEditor() でサーバへのリクエストがある
            NRPutPage(owner(),patient_id(),currentDate(),timeLimit(),container,savedEditor);
            return;
        }
    }
    
    // Editor を削除し、元の表示に戻す
    recoverCellView(eid);
    
    // 次に開くべきエディターがあれば、そのエディターを開く
    if (_nextTag){
        openEditor(_nextTag['date'], _nextTag['tag']);
    }
    
    function decodeImageLink(buff){
        // 表示用に変換された openImage() の入ったイメージ・アンカーを <IMG:url> 形式に戻す
        if (buff.indexOf("openImage(") < 0) return buff;
        
        var array = buff.split("<a onclick=");
        if (array.length == 1) return buff;
        
        var results = new Array();
        for (num in array){
            var st = array[num];
            if (num * 1 == 0){
                results.push(st);
            } else {
                // <a onclick=openImage()...>foo<img src=url height=20px>bar</a>
                var fromPos = st.indexOf(">");
                var toPos = st.lastIndexOf("</a>");
                // anchorContents = "foo<img src=url height=20px>bar"
                var anchorContents = st.substr(fromPos + 1, toPos - fromPos - 1);
                
                var ary = anchorContents.split("<img ");
                var beforImage = ary[0];
                // beforImage = "foo"
                results.push(beforImage);
                
                if (ary.length > 1){
                    // ary[1] = "src=url height=20px>bar"
                    var toPos = ary[1].indexOf(">");
                    // imageContents = "src=url height=20px"
                    var imageContents = ary[1].substr(0, toPos);
                    var ary2 = imageContents.split(" "); // ary2[0] = "src=url"
                    var ary3 = ary2[0].split("=");
                    if (ary3.length > 1){
                        var url = trimQuotation(ary3[1]);
                        results.push("<IMG:" + url + ">"); // ary3[1] = "url"
                    }
                    
                    // lest = "bar"
                    var afterImage = ary[1].substr(toPos + 1);
                    results.push(afterImage);
                }
                
                var toPos = st.lastIndexOf("</a>");
                if (toPos >=0){
                    // st = "after"
                    st = st.substr(toPos + 4);
                    results.push(st);
                }
            }
        }
        return results.join("");
    }
}
function gotMenu(answer){
    // メニュー属性をサーバから受け取り CELL に設定
    // obj=[{"menu":"下腹痛","value":"","public":"","freq":"55","menu":"下腹痛"},,,]
    // obj は freq で降順ソートされている
    // メニューデータ obj は記憶せず使い捨て
    //alert(answer); //##
    
    var obj = JSON.parse(answer);
    
    //alert("gotMenu->"+encodeObject(obj)); //##
    
    var menus = [""];
    for (num in obj){
        var rec = obj[num];
        if (rec.menu.length)
            menus.push(rec.menu);
    }
    menus.push("...その他");
    //alert("gotMenu->"+encodeObject(menus)); //##
    
    setMenus(menus); // メニューを記憶
    showEditor(); // CellEditor を開く
}

function saveAndJumpEditor(tag){
    // 内容を保存し次のエディターへジャンプ
    if (editorId()){
        var nextTagObj = null;
        var nextTag = nextTagFor(tag, _progress);
        if (nextTag)
            nextTagObj = { "date":currentDate(), "tag":nextTag };

        // 開いているエディター内容を保存し閉じ次のエディターへジャンプ
        closeEditor(editorId(), true, nextTagObj);
    }
}

function closeWarmAndOpenCell(entryDate, tag){
    closeWarm();
    removeCheck(); // 編集不可のチェックをはずす
    
    _textForEdit = null;
    setCurrentDate(entryDate);
    setCurrentTag(tag);
    
    if (tag == "AddressSection.address") tag = "都道府県";
    
    getCellEditor();
}

function openEditor(entryDate, tag, value){
    // CELL EDITOR を開く：value があれば cell.htmlValue でなく value を編集内容とする
    _initDebug(false); //##
    _debug("openEditor->"+entryDate+"->"+tag); //##
    
    var el = document.getElementById("_alerm");
    if (el.style.visibility == "visible"){
        // すでに警告パネルが開いているなら警告パネルを閉じるだけで終了
        closeWarm();
        return;
    }

    if (editorId()){
        // closeEditor の前に editorId() をチェックしておく
        var isSameEditor = (editorId() == cellId(entryDate, tag)) ? true :false;

        _debug("closeEditor and EXIT->"+editorId()+"->"+cellId(entryDate, tag)); //##
        
        // 開いているエディター内容を保存し閉じる
        if (isSameEditor){
            // 閉じたのが今開いていたエディターなら何もせず終了
            closeEditor(editorId(), true);
        } else {
            // 開いていた他のエディターを閉じ、tag のエディターを開く
            var nextTag = { "date":entryDate, "tag":tag };
            closeEditor(editorId(), true, nextTag);
        }
        
        return;
    }

    if (groupEditorOpen()){
        showFadeoutInfo("alert", "グループ・メニュー操作中は使えません", 1000);
        return;
    }

    _textForEdit = value;
    
    var oldDate = currentDate();
    var oldTag = currentTag();
    
    setCurrentDate(entryDate);
    setCurrentTag(tag);

    if (oldDate == entryDate){
        // ページ遷移ない場合は DB を読みにいかない
        setIsNewPage(false); // ページは遷移しない
        gotCellEditor();
    } else {
        setIsNewPage(true); // ページが遷移した
        if (tag == "AddressSection.address") tag = "都道府県";
        
        // CellEditor のデータをサーバへリクエスト
        getCellEditor();
    }
}

function removeValue(){
    // 編集内容を空にする
    var elm = document.getElementById(editorId() + ".text");
    elm.innerHTML = " ";
    elm.focus();
}

function cleardValue(answer){
    //alert(answer); //##
    var obj = JSON.parse(answer);
    setEditorId(null);
    
    // カルテを再表示
    openChart(obj.patientId, patientKanjiName());
}
function clearValue(){
    // 編集内容を削除し前回受診時の記述が透けて見えるようにする
    var elm = document.getElementById(editorId() + ".text");
    elm.innerHTML = "";
    
    var cell = cellForId(editorId());
    var container = new Object();
    container[cell.tag] = "";
    NRPutPage(owner(),patient_id(),currentDate(),timeLimit(),container,cleardValue);
}

function openCellPreference(){
    // tag の CELL 属性編集パネルを開く
	window.open("cellPreference.php?tag=" + currentTag(), "tools");
}

function dateChanged(answer){
    // newDatePopUp() の操作で返される '2012-07-15' のような answer
    var elm = document.getElementById(editorId() + ".text"); // 文章
    
    // まだ elm が生成されたいないうちに動作することがある
    if (elm) elm.innerHTML = answer;
}

function cellEditorHelp(type){
    // HELP を開く
    var url = "cellEditorHelp.html";
    switch (type * 1){
        case _group_: url = "groupCellEditorHelp.html";
            break;
    }
    window.open(url,"Help","width=450,height=700,scrollbars=yes,resizable=yes");
}

function showEditor(){
    // CELL EDITOR を開く
    var cell = cellFor(currentDate(), currentTag());

    if (!cell){
        alert("currentDate: "+currentDate()+"\ncurrentTag: "+currentTag()+"\nの CELL がみつかりません");
        return;
    }

    if (isReadOnly()){
		var action = "closeWarmAndOpenCell('" + currentDate()+"','"+currentTag() + "')";
        var elm = document.getElementById(cell.id);
        var h =  (elm.clientHeight < 70) ? 70 : elm.clientHeight;
        var w = elm.parentNode.clientWidth;
        var pos = getPosition(elm); // dom.js
        openWarm(pos.x, pos.y, h, w, action);
        return;
    }
    
    var field = fieldForTag(cell.tag);
    
    if (field.disabled > 0) return;
    
    setEditorId(cell.id);

    var elm = document.getElementById(cell.id);
    elm.innerHTML = "";
    
    var div = newDIV(elm, "/editor-pane");
    div.style.width = "450px"; // 固定にしないとフレームをはみ出してしまう
    
    // MENU
    var dv = newDIV(div, "");
    var tbl = newTABLE(dv, "base-table");
    // tbl.style.width = "400px"; // 固定幅にしておかないと、やたら狭くなることがある
    var tr = newTR(tbl, "", "");
    // === LEFT SIDE ==========
    var td = newTD(tr, "left-side", "");
    td.style.paddingBottom = "7px";
    // REMOVE ICON
    var sp = newSPAN(td, "removeFieldTip");
    sp.style.paddingRight = "8px";
    setInfoTip("removeFieldTip", "空欄にする"); // HELP
    var img = newIMAGE(sp, "", "./remove-field.png", "X");
    img.style.height = "12px";
    img.setAttribute("onclick", "removeValue()");
    // CLEAR ICON
    var sp = newSPAN(td, "clearFieldTip");
    sp.style.paddingRight = "8px";
    setInfoTip("clearFieldTip", "前回記述が透けて見えるようにする"); // HELP
    var img = newIMAGE(sp, "", "./selection.png", "X");
    img.style.height = "12px";
    img.setAttribute("onclick", "clearValue()");
    // POPUP MENU
    var sp = newSPAN(td, "menuArea");
    sp.style.paddingRight = "8px";

    // === RIGHT SIDE ===========
    var td = newTD(tr, "right-side", "");
    td.style.verticalAlign = "top";
    if (cell.tag == "ProgressSection.subject"){
        // 「GestateCalendar」アイコン
        if (cell.value){
            // 文中に "lmp:" 文字列があれば「妊娠歴アンカー」を表示
            var array = cell.value.split("lmp:");
            if (array.length > 1){
                var sp = newSPAN(td, " ");
                sp.style.fontSize = "9pt";
                sp.style.paddingLeft = "5px";
                var a = newA(sp, "妊娠歴", "#", "");
                a.setAttribute("onclick", "openGestateCalendar('"+cell.id+"')");
            }
        }
    } else if (cell.tag == "ProgressSection.object"){
        // 「画像読込ツール」アイコン
        var sp = newSPAN(td, "pictTip");
        sp.style.paddingLeft = "5px";
        setInfoTip("pictTip", "画像読込"); // HELP
        var img = newIMAGE(sp, "", "./camera.png", "pict");
        img.style.height = "20px";
        img.setAttribute("onclick", "openPictureTool()");
        img.style.verticalAlign = "bottom";
    }
    // PREFERENCE ICON
    var sp = newSPAN(td, "fieldPrefTip");
    setInfoTip("fieldPrefTip", "初期設定"); // HELP
    var img = newIMAGE(sp, "", "./hammer.png", "X");
    img.style.height = "15px";
    img.setAttribute("onclick", "openCellPreference()");
    // HELP ICON
    var sp = newSPAN(td, "helpTip");
    setInfoTip("helpTip", "HELP"); // HELP
    sp.style.paddingLeft = "2px";
    var img = newIMAGE(sp, "", "./info.png", "info");
    img.style.height = "16px";
    img.setAttribute("onclick", "cellEditorHelp('" + field.menuType * 1 + "')");

    var dv = newDIV(div, "panelMenuArea");

    // === TEXT ===
    var dv = newDIV(div, editorId() + ".text");
    dv.style.marginLeft = "8px";
    dv.style.marginRight = "8px";
    dv.style.padding = "3px 3px";
    dv.style.backgroundColor = "#fff";
    dv.innerHTML = (_textForEdit) ? _textForEdit : cell.htmlValue;
    dv.contentEditable = true; // TEXT を編集可能状態にする
    // HTML5：node 末尾を選択
    var sel = window.getSelection();
    sel.selectAllChildren(dv);
    sel.collapseToEnd(); // 文末にカーソルを置く: node ではうまく機能しない
  
    // === FOOTER ===
    var dv = newDIV(div, "");
    dv.style.textAlign = "right";
    dv.style.paddingTop = "7px";
    dv.style.paddingRight = "5px";
    
    if (field.menuType == _group_){
        // グループ・メニューの確定ボタン
        var bt = newBUTTON(dv, "", "とりやめ");
        bt.setAttribute("onclick", "closeGroupSubEditor()");
        var bt = newBUTTON(dv, "", " 確　定 ");
        bt.setAttribute("onclick", "closeGroupSubEditor(true)");
    } else {
        // 通常のメニューの確定ボタン
        var bt = newBUTTON(dv, "", "とりやめ");
        bt.setAttribute("onclick", "closeEditor('"+editorId()+"')");
        var bt = newBUTTON(dv, "", " 確　定 ");
        bt.setAttribute("onclick", "saveAndJumpEditor('"+currentTag()+"')");
    }
    
    // ポップアップメニューなどを生成
    showMenu(field.menuType * 1);
    
	if (field.editor){
        // field.editor が設定されていれば tools エリアに開く
		eval( field.editor + '()');
    } else if (isNewPage()) {
        // currentDate が更新された：ページが遷移した
        openBasicEditor(currentDate());
    }
    
    function showMenu(menuType){
        // メニューを生成
        var elm = document.getElementById("menuArea");
        
        switch (menuType){
            case _group_:
                // グループ・メニュー
                var sp = newSPAN(elm, "menuPopArea");
                var pu = makePopupMenu(sp, "menuPop", menus(), "");
                pu.setAttribute("onchange", "groupPopupChanged(this)");
                var bt = newBUTTON(elm, "", "挿入");
                bt.setAttribute("onclick", "insertGroupItems()");
                break;
            case _address_:
                // ### menus() に挿入すると menus() が変化してしまうのでコピー作成
                var items = new Array();
                for (num in menus()) items.push(menus()[num]);
                
                var value = cell.trimValue;
                var addressArray = value.split(" ");
                var prefecture = addressArray[0];
                
                // 都道府県ポップメニュー・エリア
                var span = newSPAN(elm, "addressPopArea");
                span.innerHTML = "";
                var sp = newSPAN(span, "_prefecture");
                var popup = makePopupMenu(sp, "prefPop", items, prefecture);
                // 都道府県 が変更されたら 市区 のメニューを取り寄せる
                popup.setAttribute("onchange", "getCITY(this)");
                
                // 市区・町村ポップアップメニュー・エリア
                var sp = newSPAN(span, "_shiku");
                var sp = newSPAN(span, "_chouson");
                getCITY(popup);
                break;
            case _panel_:
                var elm = document.getElementById("panelMenuArea");
                elm.style.fontSize = "9pt";
                elm.style.paddingBottom = "10px";
                for (num in menus()){
                    var item = menus()[num];
                    if (item.length == 0) continue;
                    
                    var sp = newDIV(elm, "/menu-item");
                    sp.innerHTML = item;
                    sp.setAttribute("onclick", "insertMenuItem('"+item+"')");
                }
                break;
            case _date_:
                var yy = "";
                var mm = "";
                var dd = "";
                var value = cell.trimValue;
                if (value && value.length){
                    var dateArray = value.split("-");
                    yy = dateArray[0];
                    mm = (dateArray.length > 1) ? dateArray[1] : "";
                    dd = (dateArray.length > 2) ? dateArray[2] : "";
                }
                // 年月日ボタン表示エリア
                var sp = newSPAN(elm, "");
                var cid = editorId() + ".hidden"; // 隠しフィールドの ID
                newDatePopUp(sp, cid, "平成", yy, mm, dd, false, dateChanged);
                break;
            case _rotary_:
                // ポップアップ・メニュー
                var sp = newSPAN(elm, "menuPopArea");
                sp.style.paddingRight = "3px";
                var pu = makePopupMenu(sp, "menuPop", menus(), "");
                pu.setAttribute("onchange", "popupChanged(this)");
                // 絞り込み
                var fd = newFIELD(elm, "focusF", "", 10, "");
                fd.setAttribute("placeholder", "絞り込み"); // 入力ヒントを表示
                fd.setAttribute("onkeyup", "focusPressed()");
                break;
            case _none_:
            case _calendar_:
            default:
                break;
        }
    }
}

function gotCellEditor(){
    openPageHeader(); // NRGetBasic() を使ったら原則的に起動
    NRGetMenu(owner(), currentTag(), gotMenu);
}
function getCellEditor(){
	// ページヘッダー・データをサーバへリクエスト
    NRGetBasic(currentDate(), gotCellEditor);
}

