var ms = {};

(function () {
	ms.ff = ms.ie = ms.safari = ms.opera = NaN;
	if (navigator.userAgent.indexOf('Gecko') > -1 && navigator.userAgent.indexOf('KHTML') == -1) {
		ms.browserEngine = 'Gecko';
		navigator.userAgent.match(/Firefox\/(\d+\.\d+)\.(\d+)/);
		/**
		 * 使用するブラウザがFirefoxの場合これのバージョン番号を数値で返し、偽の場合NaNを返す.
		 * @type Number, NaN
		 */
		ms.ff = Number(RegExp.$1 + RegExp.$2);
	}
	else if (!!window.attachEvent && !window.opera) {
		ms.browserEngine = 'MSIE';
		navigator.userAgent.match(/MSIE (\d+\.\d+)/);
		/**
		 * 使用するブラウザがInternet Explorerの場合これのバージョン番号を数値で返し、偽の場合NaNを返す.
		 * @type Number, NaN
		 */
		ms.ie = Number(RegExp.$1);
	}
	else if (navigator.userAgent.indexOf('AppleWebKit/') > -1) {
		ms.browserEngine = 'AppleWebKit';
		navigator.userAgent.match(/Version\/(\d+\.\d+)\.(\d+)/);
		/**
		 * 使用するブラウザがSafariの場合これのバージョン番号を数値で返し、偽の場合はNaNを返す.
		 * @type Number, NaN
		 */
		ms.safari = Number(RegExp.$1 + RegExp.$2);
	}
	else if (!!window.opera) {
		ms.browserEngine = 'Opera';
		/**
		 * 使用するブラウザがOperaの場合これのバージョン番号を数値で返し、偽の場合はNaNを返す.
		 * @type Number, NaN
		 */
		ms.opera = parseFloat(navigator.appVersion);
	}
	else {
		/**
		 * 使用するブラウザエンジンの名前を文字列で返し、これが不明の場合undifinedを返す.
		 * @type Number, NaN
		 */
		ms.browserEngine = undifined;
	}
}) ();

/*------------------------------
msメソッド
------------------------------*/

/**
 * 要素にアンカーとこの要素自身にリンクする文字を追加する.
 * @param   {Array} tagNamesAry 対象要素のタグ名を含む配列
 * @param   {String} linkStr リンク文字
 * @param   {String} prefixStr id名接頭辞
 * @param   {Element Object} parentElement 対象要素の親要素
 * @returns void
 * @version 1.2
 */
ms.addSelfLink = function (tagNamesAry, linkStr, prefixStr, parentElement) {
	prefixStr = prefixStr || 'section';
	parentElement = parentElement || 'body';
	var k = 0;
	for (var i = 0; i < tagNamesAry.length; i++) {
		var elements = window.document.getElementsByTagName(tagNamesAry[i], parentElement);
		for (var j = 0; j < elements.length; j++) {

			// 対象要素にid属性がない又は対象要素のid属性値がヌル文字の場合これに連番のid属性値を振る。
			if(!elements.item(j).id) { elements.item(j).id = prefixStr + k++; }

			var aObj = window.document.createElement('a');
			aObj.className = 'inner-link';
			aObj.href = '#' + elements.item(j).id;
			aObj.title = elements.item(j).id;
			
			// element.textContentプロパティ(W3C DOM)がない場合element.innerHTMLで実装する。
			aObj[aObj.textContent ? 'textContent' : 'innerHTML'] = linkStr;
			var smallObj = window.document.createElement('small');
			smallObj.appendChild(aObj);
			elements.item(j).appendChild(smallObj);
		}
	}
};

/**
 * 新規ウィンドウに外部リンクページを表示する.
 * @param   {Event Object} event イベント
 * @returns void
 * @version 1.0
 */
ms.openWindowToHref = function (event) {
	ms.standardizeEvent(event);

	// デェフォルト動作を中止する.
	event.preventDefault();

	/* 
	IEの場合thisキーワードがevent.currentTargetではなくWindowオブジェクトを指す。
	新規ウィンドウの場合refererというキーワードはuriに置換されないため、強制的に置換する。
	*/
	window.open(event.currentTarget.href.replace(/uri=referer/i, 'uri=' + encodeURIComponent(location.href)));
};

/**
 * Eventインターフェース(W3C DOM)が存在しない場合、window.eventを使って標準化されたEventを実装する.
 * @param   {Object} event
 * @returns void
 * @version 1.0
 */
ms.standardizeEvent = function (event) {
	if(!event && !!window.event) {
		/**
		 * イベントオブジェクト
		 */
		event = window.event;
	}

	// event.currentTarget(W3C DOM)が存在しない場合、ms.currentTargetを使って実装する.
	if(!event.currentTarget && !!ms.currentTarget) { event.currentTarget = ms.currentTarget; }

	// event.preventDefault(W3C DOM)が存在しない場合
	if(!event.preventDefault) {
		event.preventDefault = function () { event.returnValue = false; };
	}
};

/**
 * EventTargetインターフェース(W3C DOM)が存在しない場合、これを実装する.
 * @param   {Element Object} ElementObj
 * @returns boolean 標準化が成功した場合true、偽の場合false.
 * @version 1.0
 */
ms.standardizeEventTarget = function (ElementObj) {

	// ElementObj.addEventListenerが存在しない場合、attachEventを使って実装する.
	if (!ElementObj.addEventListener && !!ElementObj.attachEvent) {
		ElementObj.addEventListener = ms._addEventListener;
	}

	// ElementObj.removeEventListenerが存在しない場合、ms.detachEventを使って実装する.
	if (!ElementObj.removeEventListener && !!ElementObj.detachEvent) {
		ElementObj.removeEventListener = ms._removeEventListener;
	}
	return (!!ElementObj.addEventListener && !!ElementObj.removeEventListener)  ? true : false;
};

/**
 * 指定要素がデフォルト動作をする前に確認する.
 * @param {Element  Object} ElementObj 指定要素
 * @param {String}  msg 確認メッセージ
 * @param {String}  eventType click、load等のイベントタイプの名前
 * @param {Boolean} useCaptureBoo trueの場合captureフェーズが実行され、偽の場合実行されない。
 * @returns void
 * @version 1.0
 */
ms.confirm = function (ElementObj, msg, eventType, useCaptureBoo) {
	eventType = eventType || 'click';
	ElementObj.addEventListener(eventType,
		function (event) {
			ms.standardizeEvent(event);
			if (!confirm(msg)) { event.preventDefault(); }
		},useCaptureBoo);
};

/**
 * attachEventメソッドを使ってaddEventListener(W3C DOMメソッド)を実装する.
 * @param   {String} eventType click、load等のイベントタイプの名前
 * @param   {Function Object} listenerFunc イベント発生時にコールされる関数
 * @returns void
 * @version 1.0
 */
ms._addEventListener = function (eventType, listenerFunc) {
	if (!!this.attachEvent) { this.attachEvent('on' + eventType, listenerFunc); }

	// IEにevent.currentTargetを実装するためthis値を保存する。
	this.onclick = function () { ms.currentTarget = this; };
};

/**
 * detachEventメソッドを使ってremoveEventListener(W3C DOMメソッド)を実装する.
 * @param   {String} eventType click、load等のイベントタイプの名前
 * @param   {Function Object} listenerFunc 削除の対象となる関数
 * @returns void
 * @version 1.0
 */
ms._removeEventListener = function (eventType, listenerFunc) {
		if(!!this.detachEvent) { this.detachEvent('on' + eventType, listenerFunc); }
		this.onclick = null;
};