/**
 * フォームの送信を実行し、指定されたURLへ遷移します。
 *
 * fm: 送信を実行したいフォームへの参照
 * action: 遷移先URL
 * method: 送信方法。POST / GET
 */
function toSubmit(fm, action, method) {
	if (action != null && action != '') {
		fm.action = action;
	}
	if (method != null && method != '') {
		fm.method = method;
	}
	return fm.submit();
}

/**
 * popup windowを開きます。
 * 開いたwindowへの参照が返されます。
 *
 * url: 新規window遷移先URL
 * w: window幅
 * h: window高さ
 * opt: windowオプション
 * return: 新規windowへの参照
 */
function openPop(url, w, h, opt) {
	if (isNaN(w)) {
		w = 460;
	}
	if (isNaN(h)) {
		h = 320;
	}
	if (typeof(opt) == 'undefined' || opt == null) {
		opt = 'resizable=yes,scrollbars=yes';
	}
	if (opt.match(/(^|\s|,)scrollbars=(1|yes)/i)) {
		// スクロールバーの分window幅を広げる
		w += 17;
	}
	var optstr = 'width=' + w + ',height=' + h + ',' + opt;
	var wnd = window.open(url, null, optstr);
	wnd.focus();
	return wnd;
}

/**
 * 選択用popup windowを開きます。
 * URLに値戻し先のフォーム名が埋め込まれます。
 * 開いたwindowへの参照が返されます。
 *
 * url: 新規window遷移先URL
 * fm: 値戻し先フォームへの参照
 * w: window幅
 * h: window高さ
 * opt: windowオプション
 * fmvar: 値戻し先フォーム名のURLパラメータ名(default: form)
 * return: 新規windowへの参照
 */
function openSelPop(url, fm, w, h, opt, fmvar) {
	if (opt == null || opt == '') {
		opt = null;
	}
	if (fmvar == null || fmvar == '') {
		fmvar = 'form';
	}

	var joint = '';
	if (url.match(/\?/)) {
		joint = '&';
	} else {
		joint = '?';
	}
	var popurl = url + joint + fmvar + '=' + fm.name;

	return openPop(popurl, w, h, opt);
}

/**
 * aタグなどから新規popup windowを開きます。
 *
 * obj: aタグなど、hrefの指定されているオブジェクト
 * w: window幅
 * h: window高さ
 * opt: windowオプション
 * return: 新規windowへの参照
 */
function openRefPop(obj, w, h, opt) {
	if (obj) {
		if (obj.href) {
			openPop(obj.href, w, h, opt);
		}
	}
	return false;
}

/**
 * 正しい日付であればtrueを、間違っていればfalseを返します。
 */
function isValidDate(y, m, d) {
	var isValid = false;
	var dt = new Date(y, m - 1, d);
	if (((y < 2000) && (dt.getYear() == (y - 1900))) ||
			((y >= 2000) && (dt.getYear() == y))) {
		if (dt.getMonth() == (m - 1)) {
			if (dt.getDate() == d) {
				isValid = true;
			}
		}
	}
	return isValid;
}

/**
 * おおよそ正しいと思われるメールアドレスであればtrue、明らかに間違っているメ
 * ールアドレスにはfalseを返します。
 */
function isValidEmail(str) {
	isValid = false;
	if (str.match(/^[^\@]+\@[^\@]+\.[a-z]+$/i)) {
		isValid = true;
	}
	return isValid;
}

function roleoverImg(img, src) {
	img.origSrc = img.src;
	img.src = src;

	if (!img.onmouseout) {
		img.onmouseout = function () {
			if (img.origSrc) {
				img.src = img.origSrc;
			}
		};
	}
}

function releaseImg(img) {
	if (img.origSrc) {
		img.src = img.origSrc;
	}
}

function preloadImgs() {
	for (i = 0; i < arguments.length; i++) {
		(new Image).src = arguments[i];
	}
}


/**
* jQuery 1.3.x, fckeditor 2.6.x使用の前提。
* htmlエディタ（common/wysiwyg/pop_html_editor.php）を立ち上げます。
* topはcommonに対するBasePath、OKボタンの結果はelmIdが示すテキストエリアに返
* されます。
* @param top string サイトのトップパス
* @param elmId string 編集対象のテキストエリアのID
* @param dispName string テキストエリアの表示呼称
* @return boolean true
*/
function popHtmlEditor(top, elmId, dispName) {
	// 初期値設定
	var url = top + '/common/wysiwyg/pop_html_editor.php';
	var tgt = 'pop_html_editor' + elmId;
	var w = 800;
	var h = 600;
	var opt = 'resizable=yes,scrollbars=yes,' + 'width=' + w + ',height=' + h;

	// ターゲットウィンドウオープン
	var wnd = window.open('about:blank', tgt, opt);
	wnd.focus();

	// 一時無名フォームから送信
	var fm = jQuery('<form method="POST" />').attr('target', tgt).attr('action', url).hide()
		.append(jQuery('<input type="text" name="elm_name" />').hide().val(elmId))
		.append(jQuery('<input type="text" name="disp_name" />').hide().val(dispName))
		.append(jQuery('<textarea name="html_txt"></textarea>').hide().val(jQuery('#' + elmId).val()))
		.appendTo('body').submit().remove();

	return true;
}

/**
* jQuery 1.3.x使用の前提。
* 文字数カウント + 制限
* @param elmId string 対象となるテキストエリアのID
* @param counterId string カウンター表示エリアのID
* @param errmsgId string エラー表示エリアのID
* @param maxLen int 最大文字数
* @param minLen int 最小文字数
*/
function initCharNavi(elmId, counterId, errmsgId, maxLen, minLen) {
	var fld = jQuery('#' + elmId);
	var rawfld = fld.get(0);

	rawfld.myLen = fld.val().length;
	rawfld.myMaxLen = !isNaN(maxLen) ? maxLen : 0;
	rawfld.myMinLen = !isNaN(minLen) ? minLen : 0;
	rawfld.myModified = false;

	function refleshCounter(counterId, len, maxLen) {
		// 文字数を表示
		var cntr = jQuery('#' + counterId);
		if (cntr) {
			cntr.html(len + '/' + maxLen);
		}
		return true;
	}

	function refleshErrMsg(errmsgId, len, maxLen, minLen) {
		// エラーメッセージ
		var ctl = jQuery('#' + errmsgId);
		if (ctl) {
			var msg = '';
			if (maxLen > 0 && len > maxLen) {
				// 最大文字数
				msg = "最大文字数" + maxLen + "を超えています。";
			} else if (minLen > 0 && len < minLen) {
				// 最小文字数
				if (minLen == 1) {
					msg = "文字を入力してください。";
				} else {
					msg = "最小文字数" + minLen + "未満です。";
				}
			}
			ctl.html(msg);
		}
		return true;
	}

	fld.keyup(function() {
		var len = jQuery(this).val().length;
		var oldLen = this.myLen;
		if (len != oldLen) {
			this.myLen = len;
			var maxLen = this.myMaxLen;
			var minLen = this.myMinLen;
			// カウンターを更新
			refleshCounter(counterId, len, maxLen);
			// エラー表示を更新
			refleshErrMsg(errmsgId, len, maxLen, minLen)
		}
	});
	fld.focus(function() {
		var len = jQuery(this).val().length;
		var oldLen = this.myLen;
		if (len != oldLen) {
			this.myLen = len;
			var maxLen = this.myMaxLen;
			var minLen = this.myMinLen;
			// カウンターを更新
			refleshCounter(counterId, len, maxLen);
			// エラー表示を更新
			refleshErrMsg(errmsgId, len, maxLen, minLen);
		}
	});
	//fld.blur(function(e) {
	//	// 文字数を制限
	//	var len = jQuery(this).val().length;
	//	var tgt = this;
	//	if (len > this.myMaxLen) {
	//		setTimeout(function () {
	//			tgt.focus();
	//			if (tgt.createTextRange) {
	//				var rng = tgt.createTextRange();
	//				rng.move('character', len);
	//				rng.select();
	//			} else {
	//				tgt.setSelectionRange(len, len);
	//			}
	//		}, 0);
	//	}
	//});

	// カウンターを更新
	refleshCounter(counterId, rawfld.myLen, maxLen);

	return true;
}

/**
* jQuery 1.3.x使用の前提。
* 画像の表示/非表示
*/
function initImgSw(imgId, togleSwId) {
	jQuery('#' + togleSwId).click(function() {
		var elm = jQuery('#' + imgId);
		if (elm) {
			if (elm.css('display') == 'none') {
				jQuery(this).html('画像非表示');
				elm.show();
			} else {
				jQuery(this).html('画像表示');
				elm.hide();
			}
		}
		return false;
	});
	jQuery('#' + imgId).click(function() {
		var elm = jQuery('#' + togleSwId);
		if (elm) {
			elm.html('画像表示');
			jQuery(this).hide();
		}
	});
}
/**
* jQuery 1.3.x使用の前提。
* チェックボックス関連内容の表示/非表示
*/
function initInfoSw(infoId, togleSwId) {
/*		chk = jQuery('#' + togleSwId)
		var elm_load = jQuery('#' + infoId);
		if (elm_load){
			if (chk.checked) {
				elm_load.show();
			} else {
				elm_load.hide();
			}
		} else {
			return false;
		}
*/
	jQuery('#' + togleSwId).click(function() {
		var elm = jQuery('#' + infoId);
		if (elm){
			if (this.checked) {
					elm.show();
			} else {
					elm.hide();
			}
		} else {
			return false;
		}
/*		if (elm) {
			if (elm.css('display') == 'none') {
				//jQuery(this).html('画像非表示');
				elm.show();
			} else {
				//jQuery(this).html('画像表示');
				elm.hide();
			}
		}
*/		return true;
	});

}


/**
* suggest機能
* @param input string 入力ボックスのDOM要素のID。
* @param suggest string 候補表示エリアのDOM要素のID。
* @param url string 候補一覧問合せ先URL。キーワードは [KEYWORD] を置換する。
*   例 ../common/test.php?qstr=[KEYWORD]
* @param dispField string 問い合わせ結果のうち、候補として一覧表示する項目の名前。
* @param binds object 入力ボックス以外に値を設定する場合に指定。行項目名 => DOM要素IDの連想配列。
*/
function initSuggest(params) {
	$ = jQuery;

	// 候補表示エリアスタイル
	var areaStyle = {
		'position': 'absolute',
		/*'height': '180px',*/
		'overflow': 'auto',
		'display': 'none',
		'border-width': '1px',
		'border-style': 'solid',
		'border-color': '#888888',
		'background-color': 'white',
		'white-space': 'nowrap'
	};
	// 候補各行スタイル（未選択）
	var rowStyle = {
		'display': 'block',
		'margin': '0',
		'padding': '0.3em 0',
		'color': '#333333',
		'background-color': '#ffffff',
		'text-decoration': 'none'
	};
	// 候補各行スタイル（選択）
	var rowStyleSel = {
		'display': 'block',
		'margin': '0',
		'padding': '0.3em 0',
		'color': '#ffffff',
		'background-color': '#8888ff',
		'text-decoration': 'none'
	};
	// 候補文字列スタイル
	var txtStyle = {
		'margin': '0',
		'padding': '0 0.3em',
		'font-weight': 'normal'
	};

	// 入力内容確認間隔（ms）
	var txtChkSpan = 240;
	// 最大表示件数
	var maxRows = !isNaN(params['maxRows']) ? params['maxRows'] : 0;
	// 最大表示高さ（単位px）
	var maxAreaH = 240;

	// 入力テキストボックス
	var inpElm = $('#' + params['input']);
	// 入力テキストボックス幅
	var inpW = inpElm.outerWidth();
	// 入力テキストボックス高さ
	var inpH = inpElm.outerHeight();
	// 入力テキストボックス位置
	var inpPos = inpElm.position();

	// バインドする要素
	var bindElmMap = {};
	if (params['binds']) {
		for (var key in params['binds']) {
			bindElmMap[key] = $('#' + params['binds'][key]);
		}
	}
	// 候補一覧要素
	var sgstElm = $('#' + params['suggest']).css(areaStyle);
	// IE6の場合に、selectが前へ出てしまう件への対策
	var _forIe6ZIndexElm = null;
	if (typeof document.body.style.maxHeight == "undefined") {
		_forIe6ZIndexElm = $('<iframe style="position:absolute; top:0; left:0; display:none" frameborder="0" />').insertBefore(sgstElm);
	}

	// 候補問い合わせURL
	var sgstURL = params['url'];
	// 候補一覧作成用の項目名
	var dispField = params['dispField'];

	// タイマーID
	var tm = null;
	// 入力中検索キーワード
	var crrTxt = '';
	// 最終検索済みキーワード
	var lastSrch = '';
	// 最終選択データ
	var lastSelRow = null;
	// 現在の選択番号
	var crrSelNum = 0;
	// マウスが候補上にあるか
	var isMouseSel = false;
	// マウスが入力ボックス上にあるか
	var isMouseInp = false;

	function watchInp() {
		var val = inpElm.val();
		if (crrTxt == val) {
			// タイマー再度開始
			tm = setTimeout(watchInp, txtChkSpan);
		} else if (!val.length) {
			// タイマー再度開始
			tm = setTimeout(watchInp, txtChkSpan);
			// 候補ボックス消去
			crrTxt = lastSrch = '';
			lastSelRow = {};
			setBinds({});
			clearSgst();
		} else {
			// 検索
			crrTxt = val;
			lastSrch = '';
			setBinds({}, [inpElm.attr('id')]);
			$.getJSON(sgstURL.replace('[KEYWORD]', encodeURI(val)), {}, sgstInp);
		}
	}

	function unwatchInp() {
		if (tm) {
			clearTimeout(tm);
			tm = null;
		}
	}

	function clearSgst() {
		sgstElm.css({ 'display': 'none', 'height' : 0 }).empty();
		if (_forIe6ZIndexElm) {
			_forIe6ZIndexElm.css({ 'display': 'none', 'height' : 0 });
		}
	}

	function sgstInp(dat) {
		if (dat.length && sgstElm.length) {
			// 検索キーワード保存
			lastSrch = crrTxt;
			//lastSelVal = '';
			lastSelRow = {};
			// 既存表示内容消去
			sgstElm.empty();
			// 表示候補一覧作成
			var numrows = ((dat.length < maxRows) || !maxRows) ? dat.length : maxRows;
			for (var i = 0; i < numrows; i++) {
				var selNum = i + 1;
				var elm = $('<a href="#" />').hover(function() {
					if (crrSelNum != 0) {
						sgstElm.children().eq(crrSelNum - 1).css(rowStyle);
					}
					var num = $(this).get(0).sgstSelectNo;
					crrSelNum = num;
					$(this).css(rowStyleSel);
				}, function() {
					// do nothing.
				}).click(function() {
					setSelVal($(this));
					clearSgst();
					inpElm.focus();
					return false;
				}).css(rowStyle).append(
					$('<span />').css(txtStyle).html(dat[i][dispField])
				);

				// 候補固有値の設定
				var selDom = elm.get(0);
				// 現在行の設定
				selDom.sgstRow = dat[i];
				// エレメントに選択番号をつける
				selDom.sgstSelectNo = i + 1;
				// 候補エリアへ追加
				sgstElm.append(elm);
			}
			// 入力候補エリアへ表示
			if (inpElm.length) {
				var pos = inpElm.position();
				var x = inpPos.left;
				var y = inpPos.top + inpH;
				sgstElm.width(inpW).css({
					'display': 'block', 'top': y, 'left': x
				});

				// 候補エリアの幅。最低限、入力ボックスの幅
				var areaW = inpW;
				// 候補エリアの高さ。
				var areaH = 0;
				// 最大幅に追加するスクロールバーなどの幅余裕
				var bufW = 24;
				// 候補行内のspan要素
				var chld = sgstElm.children();
				for (var i = 0; i < chld.length; i++) {
					var rowElm = chld.eq(i);
					var txtElm = rowElm.children().eq(0);
					var w = txtElm.outerWidth() + bufW;
					var h = rowElm.outerHeight();
					if (w > areaW) {
						areaW = w;
					}
					if ((areaH + h) <= maxAreaH) {
						areaH += h;
					}
				}
				sgstElm.width(areaW).height(areaH);
				if (_forIe6ZIndexElm) {
					_forIe6ZIndexElm.css({
						'display': 'block', 'top': y, 'left': x
					}).width(areaW).height(areaH);
				}
			}
		} else {
			clearSgst();
			// タイマー再セット
			watchInp();
		}
		// 現在選択リセット
		crrSelNum = 0;
	}

	function onKeyDown(e) {
		var code = e.which;
		var len = sgstElm.children().length;

		if ((code != 40) && (code != 38) && (code != 13)) {
			return true;
		} if (!len) {
			return true;
		}

		var befSelNum = crrSelNum;
		if (code == 40) {
			// 下へ
			if (crrSelNum < len) {
				crrSelNum++;
			} else {
				crrSelNum = 0;
			}
		} else if (code == 38) {
			// 上へ
			if (crrSelNum > 0) {
				crrSelNum--;
			} else {
				crrSelNum = len;
			}
		} else if (code == 13) {
			// エンターキー
			clearSgst();
			// キーイベントキャンセル
			return false;
		}

		if (befSelNum != 0) {
			sgstElm.children().eq(befSelNum - 1).css(rowStyle);
		}
		if (crrSelNum) {
			var selElm = sgstElm.children().eq(crrSelNum - 1);
			// 上下キー、選択移動、値設定
			selElm.css(rowStyleSel);
			setSelVal(selElm);
			// スクロール調整
			var selPos = selElm.position();
			var selBtm = selPos.top + selElm.outerHeight();
			var sgstH = sgstElm.outerHeight();
			if (selBtm > sgstH) {
				sgstElm.scrollTop(sgstElm.scrollTop() + (selBtm - sgstH));
			} else if (selPos.top < 0) {
				sgstElm.scrollTop(sgstElm.scrollTop() + selPos.top);
			}
		} else {
			setBinds({}, [inpElm.attr('id')]);
			inpElm.val(crrTxt = lastSrch);
		}
	}

	function onKeyUp(e) {
		var code = e.which;
		if (code == 27) {
			// ECSキー
			clearSgst();
		}
		// もし内容に変更があるならば入力チェック再開
		if (crrTxt != inpElm.val()) {
			watchInp();
		}
	}
	
	function setSelVal(selElm) {
		if (!selElm.length) {
			return false;
		}
		var selDom = selElm.get(0);
		// 現在値の更新
		lastSelRow = (selDom.sgstRow ? selDom.sgstRow : {});
		setBinds(lastSelRow);
		crrTxt = inpElm.val();
	}

	function setBinds(row, excludes) {
		// excludes mapの作成
		var arr = (excludes != null) ? excludes : [];
		var exMap = {};
		for (var i = 0; i < arr.length; i++) {
			exMap[arr[i]] = true;
		}
		// 値の設定
		for (var key in bindElmMap) {
			var elm = bindElmMap[key];
			if (!elm || exMap[elm.attr('id')]) {
				continue;
			}
			if ((row[key] != null) && row[key].length) {
				elm.val(row[key]);
			} else {
				elm.val('');
			}
		}
	}

	// 入力ボックスイベント動作定義
	inpElm.mouseenter(function() {
		isMouseInp = true;
	}).focus(function() {
		crrSelNum = 0;
		crrTxt = lastSrch = $(this).val();
		watchInp();
	}).mouseleave(function() {
		isMouseInp = false;
	}).blur(function() {
		if (!isMouseSel) {
			clearSgst();
		}
		unwatchInp();
	}).keydown(onKeyDown).keyup(onKeyUp);

	// 候補ボックスイベント動作定義
	sgstElm.mouseenter(function() {
		isMouseSel = true;
	}).mouseleave(function() {
		isMouseSel = false;
	}).blur(function() {
		if (!isMouseInp) {
			clearSgst();
		}
		unwatchInp();
	}).keydown(onKeyDown).keyup(onKeyUp);

	function dbgmsg(msg) {
		$('#dbgmsg').html($('#dbgmsg').html() + '<br />' + msg);
	}
}

/**
* 数値をカンマ区切りにする
*/
function numfmt(num) {
	if (num != null && num.length && !isNaN(num)) {
		var arr = num.toString().split('.');
		return arr.shift().replace(/(\d+?)(?=(?:\d{3})+$)/g, '$1,')
			+ (arr.length ? '.' + arr.join('.') : '');
	} else {
		return num;
	}
}

/**
* 日本での数値表記フォーマット。
* 万 億 兆 京 垓
*/
function numfmtJP(num) {
	if (isNaN(num)) {
		return num;
	}

	var str = String(num);
	var ret = '';
	var part = null;
	var units = ['', '万', '億', '兆', '京', '垓'];

	while (part = str.match(/\d{1,4}$/)) {
		str = str.replace(/\d{1,4}$/, '');
		var val = String(parseInt(part[0]));
		var unit = units.length ? units.shift() : '';
		if (val != '0') {
			ret = ((val.length >= 4)
				? val.substr(0, 1) + ',' + val.substr(1, 3)
				: val) + unit + ret;
		}
	}
	return (ret.length ? ret : '0');
}

/**
* !!
* !! まだ、正式取り込みではない実験的関数です。廃止、他関数との統合がありえま
* !! すので注意して利用してください。sasaki
* !!
* 小数点の連続した0を削除
*/
function trimAftDecPtZero(num) {
	var ret = null;
	if (typeof num == 'number' || typeof num == 'string') {
		if (num.length && !isNaN(num)) {
			ret = String(num).replace(/(\.\d*?)0+$/, '$1').replace(/\.$/, '');
		} else {
			ret = num;
		}
	} else {
		ret = num;
	}
	return ret;
}

