	window.onload = function() {
		com.nec.jp.ngsf.wiki.init();
	}

	/* namespace preparation */

	if (com == null) {
		var com = {
		};
	};

	if (com.nec == null) {
		com.nec = {
		};
	};

	if (com.nec.jp == null) {
		com.nec.jp = {
		};
	};

	if (com.nec.jp.ngsf == null) {
		com.nec.jp.ngsf = {
		};
	};

	if (com.nec.jp.ngsf.wiki == null) {
		com.nec.jp.ngsf.wiki = {

			/* Point */

			Point : function(x, y) {
				this.x = x;
				this.y = y;
			}

		};
	};

	/* general */

	com.nec.jp.ngsf.wiki.trim = function(arg) {
		if (arg == null) {
			return arg;
		}

		return arg.replace(/^[\s ]+|[\s ]+$/g, "");
	}

	var JSARG_ESCAPE_CHAR = "'\\&";

	var JSARG_ESCAPE_TO = [ "\\'", "\\\\", "&amp;" ];

	com.nec.jp.ngsf.wiki.escapeForJSArg = function(str) {
		return com.nec.jp.ngsf.wiki.escapeText(str, JSARG_ESCAPE_CHAR, JSARG_ESCAPE_TO);
	}

	/*
	 * 非同期(初期ロード時より後という意味)にJavaScriptファイルをロードする処理です。
	 * 現在JavaScriptのロード完了を待てていないので、
	 * 多分このため関数呼び出しが失敗することがあります。
	 * 汎用にしたいためあるメソッドが存在したらというロード完了チェックができないため、
	 * 何か他の方法でロード完了を検知出来るようにしないと使い物にならない状況です...
	 * →safeCallにてある程度解消できると思います。
	 * 他に良い商用利用可能なスクリプトがあればそれを使うこともやぶさかではありません。
	 * @param scriptName スクリプトファイル名(js/tablesort.jsなど)
	 * @param scriptCharSet scriptNameで指定したファイルのキャラクタセット名
	 */
	com.nec.jp.ngsf.wiki.registerScript = function(scriptName, scriptCharSet) {
		scriptName = com.nec.jp.ngsf.wiki.trim(scriptName);
		scriptCharSet = com.nec.jp.ngsf.wiki.trim(scriptCharSet);

		var headElements = document.getElementsByTagName("head");

		if ((headElements == null) || (headElements.length == 0)) {
			return;
		}

		var headElement = headElements[0];

		var scripts = headElement.getElementsByTagName("script");

		if (scripts != null) {
			/* すでに登録されているか調べます。*/
			for (var i = 0; i < scripts.length; i++) {
				if (scriptName == scripts[i].getAttribute("src")) {
					/* すでに登録されている場合、何もしません。*/
					com.nec.jp.ngsf.wiki.debug(scriptName + " already registered", true);
					return;
				}
			}
		}

		/* 追加します。*/
		var scriptElement = document.createElement("script");
		scriptElement.setAttribute("type", "text/javascript");
		scriptElement.setAttribute("src", scriptName);

		if (scriptCharSet && (scriptCharSet.length > 0)) {
			scriptElement.setAttribute("charset", scriptCharSet);
		}

		headElement.appendChild(scriptElement);
		com.nec.jp.ngsf.wiki.debug(scriptName + "(" + scriptCharSet + ") registered", true);
	}

	/*
	 * registerScriptで読み込んだスクリプトの関数を呼び出しに失敗した場合に、
	 * リトライ、再呼び出しを行う関数です。
	 * com.nec.jp.ngsf.wiki.safeCall('hoge', function(){hoge();});のように使います。
	 * @param funcname 存在確認する関数名。
	 * @param func 存在確認後に実行する処理。
	 * @param count リトライ中のカウント。内部利用用なので指定しない。
	 */
	com.nec.jp.ngsf.wiki.safeCall = function(funcname, func, count) {
		if (count == undefined) {
			count = 1;
		}

		com.nec.jp.ngsf.wiki.debug("safeCall " + funcname + "(" + count + ")", true);

		try {
			var obj = undefined;

			eval("obj = " + funcname);

			if (obj) {
				func();
			} else {
				com.nec.jp.ngsf.wiki.debug("safeCall " + funcname + "(" + count + ") failed.", true);

				if (count < 10) {
					setTimeout(function(){
							com.nec.jp.ngsf.wiki.safeCall(funcname, func, count + 1);
						}, 100);
				} else {
					com.nec.jp.ngsf.wiki.debug("safeCall " + funcname + " retry terminated.", true);
				}
			}
		} catch (e) {
			com.nec.jp.ngsf.wiki.debug("safeCall " + funcname + "(" + count + ") failed:" + e.name + ", " + e.description, true);

			if ((count < 10)/* && (e.description.startsWith("undefined"))*/) {
				// e.nameやe.descriptionでここに入れたかったのですが、ブラウザが異なると変わるので、
				// そのままリトライにしています。
				setTimeout(function(){
						com.nec.jp.ngsf.wiki.safeCall(funcname, func, count + 1);
					}, 100);
			} else {
				com.nec.jp.ngsf.wiki.debug("safeCall " + funcname + " retry terminated.", true);
			}
		}
	}

	/*
	 * 非同期(初期ロード時より後という意味)にCSSファイルをロードする処理です。
	 * 他に良い商用利用可能なスクリプトがあればそれを使うこともやぶさかではありません。
	 * @param cssName CSS名(css/~.cssなど)
	 */
	com.nec.jp.ngsf.wiki.registerCSS = function(cssName) {
		var headElements = document.getElementsByTagName("head");

		if ((headElements == null) || (headElements.length == 0)) {
			return;
		}

		var headElement = headElements[0];

		var links = headElement.getElementsByTagName("link");

		if (links != null) {
			/* すでに登録されているか調べます。*/
			for (var i = 0; i < links.length; i++) {
				if (cssName == links[i].getAttribute("href")) {
					/* すでに登録されている場合、何もしません。*/
					com.nec.jp.ngsf.wiki.debug(cssName + " already registered", true);
					return;
				}
			}
		}

		/* 追加します。*/
		var linkElement = document.createElement("link");
		linkElement.setAttribute("rel", "stylesheet");
		linkElement.setAttribute("type", "text/css");
		linkElement.setAttribute("href", cssName);
		headElement.appendChild(linkElement);
		com.nec.jp.ngsf.wiki.debug(cssName + " registered", true);
	}

	/**
	 * str中のescape対象文字をescapeToの対応するインデックスの文字列で置換します。
	 * @param str 置換対象文字列。
	 * @param escape エスケープ対象文字の配列。
	 * @param escapeTo エスケープ先の文字列。
	 * @return str中のescape対象文字をescapeToの対応するインデックスの文字列で置換したもの。
	 */
	com.nec.jp.ngsf.wiki.escapeText = function(str, escape, escapeTo) {
		if ((str == null) || (str.length == 0) || (escape == null) || (escapeTo == null)) {
			return "";
		}

		var sb = [];

		for (var i = 0; i < str.length; i++) {
			var c = str.charAt(i);
			var index = escape.indexOf(c);

			if (index != -1) {
				sb[sb.length] = escapeTo[index];
			} else {
				sb[sb.length] = c;
			}
		}

		return sb.join("");
	}


	/* prevElement(compatibility purpose) */
	com.nec.jp.ngsf.wiki.prevElement = function(/* non_null */o) {
		do {
			var prev = o.previousSibling;

			if (prev) {
				if (prev.tagName) {
					return prev;
				} else {
					o = prev;
				}
			} else {
				return null;
			}
		} while (true);
	}

	/* nextElement(compatibility purpose) */
	com.nec.jp.ngsf.wiki.nextElement = function(/* non_null */o) {
		do {
			var next = o.nextSibling;

			if (next) {
				if (next.tagName) {
					return next;
				} else {
					o = next;
				}
			} else {
				return null;
			}
		} while (true);
	}

	/* firstChild(compatibility purpose) */
	com.nec.jp.ngsf.wiki.firstChildElement = function(/* non_null */o, elementName) {
		var children = o.childNodes;

		for (var i = 0; i < children.length; i++) {
			if (children[i] && (children[i].tagName == elementName)) {
				return children[i];
			}
		}

		return null;
	}

	/* lastChild(compatibility purpose) */
	com.nec.jp.ngsf.wiki.lastChildElement = function(/* non_null */o, elementName) {
		var children = o.childNodes;
		var child = null;

		for (var i = 0; i < children.length; i++) {
			if (children[i] && (children[i].tagName == elementName)) {
				child = children[i];
			}
		}

		return child;
	}

	com.nec.jp.ngsf.wiki.getEmSize = function() {
		var divElement = document.createElement("div");
		divElement.style.width = "1em";
		
		document.body.appendChild(divElement);
		
		var dimensions = Element.getDimensions(divElement);
		
		document.body.removeChild(divElement);
		
		return dimensions;
	}
	
	com.nec.jp.ngsf.wiki.getPixcel = function(size) {
		if (size) {
			if (size.match(new RegExp("em$")) != null) {
				// サイズがemで表現されている場合
				var emWidth = com.nec.jp.ngsf.wiki.getEmSize().width;
				size = Number(size.substring(0, size.lastIndexOf("em")) * emWidth);
			} else if (size.match(new RegExp("px$")) != null) {
				// サイズがpxで表現されている場合
				size = Number(size.substring(0, size.lastIndexOf("px")));
			} else {
				// その他の場合は0px
				size = 0;
			}
		} else {
			size = 0;
		}
		
		if (isNaN(size)) {
			size = 0;
		}
		
		return size;
	}
	
	/* initialization */

	com.nec.jp.ngsf.wiki.init = function() {
		Event.observe(document, "mousedown", com.nec.jp.ngsf.wiki.track_mouse_pos, false);
		Event.observe(document, "mousemove", com.nec.jp.ngsf.wiki.track_mouse_pos, false);
		Event.observe(document, "mouseup", com.nec.jp.ngsf.wiki.track_mouse_pos, false);

		Event.observe(document, "keydown", com.nec.jp.ngsf.wiki.onkeydown, false);

		if (document.getElementById(com.nec.jp.ngsf.wiki.editorResizeStatus.id)) {
			Event.observe(document, "mousedown", com.nec.jp.ngsf.wiki.editor_resize_onmousedown, false);
		}
		
		com.nec.jp.ngsf.wiki.resize_content();
	};
	
	com.nec.jp.ngsf.wiki.resize_content = function() {
		// メニューが存在する場合→ログイン済
		if ($("gleanfeed-wiki-menu") != null) {
			// 本文領域のパディング幅を取得
			var paddingLeftArticle = com.nec.jp.ngsf.wiki.getPixcel(Element.getStyle("gleanfeed-wiki-article", "padding-left"));
			var paddingRightArticle = com.nec.jp.ngsf.wiki.getPixcel(Element.getStyle("gleanfeed-wiki-article", "padding-right"));
			
			// 本文領域の枠線サイズを取得
			var borderLeftArticle = com.nec.jp.ngsf.wiki.getPixcel(Element.getStyle("gleanfeed-wiki-article", "border-left-width"));
			var borderRightArticle = com.nec.jp.ngsf.wiki.getPixcel(Element.getStyle("gleanfeed-wiki-article", "border-right-width"));
			
			// コンテンツ領域の枠線サイズを取得
			var borderLeftContent = com.nec.jp.ngsf.wiki.getPixcel(Element.getStyle("gleanfeed-wiki-content", "border-left-width"));
			var borderRightContent = com.nec.jp.ngsf.wiki.getPixcel(Element.getStyle("gleanfeed-wiki-content", "border-right-width"));
			
			// 本文の最大幅を取得
			var articleMaxWidth = Element.getDimensions("gleanfeed-wiki-article-table").width;
			var articleWidth = articleMaxWidth + paddingLeftArticle + paddingRightArticle
					+ borderLeftArticle + borderRightArticle
					+ borderLeftContent + borderRightContent;
			if (document.all) {
				// IEの場合は6px加算する
				articleWidth = articleWidth + 6;
			}
			
			// 本文領域の幅を取得
			var contentAreaWidth = Element.getDimensions("gleanfeed-wiki-content").width;
			
			// 整数に変換
			articleWidth = Math.floor(articleWidth);
			contentAreaWidth = Math.floor(contentAreaWidth);
			
			// 本文のサイズとコンテンツ領域のサイズを比較し、本文のサイズが大きかったらサイズを調整
			if (articleWidth > contentAreaWidth) {
				var wrapWidth = Math.floor(Element.getDimensions("gleanfeed-wiki-wrap").width);
				var diff = wrapWidth - contentAreaWidth + 2; // 2px足す必要がある
				
				$("gleanfeed-wiki-content").style.width = articleWidth + "px";
				$("gleanfeed-wiki-content").style.float = "left";
				$("gleanfeed-wiki-wrap").style.width = (articleWidth + diff) + "px";
			}
		} else {
			// メニューが存在しない場合→未ログイン状態
			// コンテンツ表示領域を広げる
			$("gleanfeed-wiki-content").style.width = "100%";
			$("gleanfeed-wiki-content").style.marginLeft = "0";
			$("gleanfeed-wiki-wrap").style.width = "99%";
		}
	}

	/* mouse */

	com.nec.jp.ngsf.wiki.mouse_pos = null;

	com.nec.jp.ngsf.wiki.track_mouse_pos = function(e) {
		com.nec.jp.ngsf.wiki.mouse_pos = new com.nec.jp.ngsf.wiki.Point(Event.pointerX(e), Event.pointerY(e));
		return com.nec.jp.ngsf.wiki.mouse_pos;
	}

	/* key */

	com.nec.jp.ngsf.wiki.onkeydown = function(e) {
		if (document.all) {
			// window.alert("" + event.keyCode);
			if (event.keyCode == 27/* ESC */) {
				com.nec.jp.ngsf.wiki.close_popup();
				popupWindow.close();
				confirmDialog.close();
			}
		} else {
			if (e.which == 27/* ESC */) {
				com.nec.jp.ngsf.wiki.close_popup();
				popupWindow.close();
				confirmDialog.close();
			}
		}
	}

	/* element */

	com.nec.jp.ngsf.wiki.get_element_style = function(id) {
		var o = document.getElementById(id);

		if (o == null) {
			return null;
		}

		return o.style;
	}

	com.nec.jp.ngsf.wiki.show_element = function(id) {
		s = com.nec.jp.ngsf.wiki.get_element_style(id);

		if (s == null) {
			return;
		}

		s.display = "block";
	}

	com.nec.jp.ngsf.wiki.hide_element = function(id) {
		s = com.nec.jp.ngsf.wiki.get_element_style(id);

		if (s == null) {
			return;
		}

		s.display = "none";
	}

	/* iframe */

	com.nec.jp.ngsf.wiki.write_iframe_content = function(id, text) {
		var o = document.getElementById(id);

		if (o == null) {
			return;
		}

		doc = o.contentWindow.document;

		if (doc == null) {
			return;
		}

		doc.open();

		if (text == null) {
			text = "";
		}

		doc.write(text);
		doc.close();
	}

	/* form utility */

	com.nec.jp.ngsf.wiki.set_enable = function(id, enable) {
		var o = document.getElementById(id);

		if (o == null) {
			return;
		}

		o.disabled = !enable;
	}

	/* merge all o's child checkboxes into value=checked[;value=checked...] form. */
	com.nec.jp.ngsf.wiki.merge_input = function(/* non_null */o) {
		var children = o.childNodes;
		var inputText = "";

		for (var i = 0; i < children.length; i++) {
			if (children[i].tagName == "INPUT") {
				if (children[i].getAttribute("type") == "checkbox") {
					if (inputText.length > 0) {
						inputText = inputText + ";";
					}

					inputText = inputText + children[i].value + "=" + children[i].checked;
				}
			} else {
				if (inputText.length > 0) {
					inputText = inputText + ";";
				}

				inputText = inputText + com.nec.jp.ngsf.wiki.merge_input(children[i]);
			}
		}

		return inputText;
	}

	/* redirect */

	com.nec.jp.ngsf.wiki.redirect = function(url) {
		location.href = url;
	}

	/* popup */

	com.nec.jp.ngsf.wiki.popup_id = null; // to keep popup-ing, this value is checked.
	com.nec.jp.ngsf.wiki.current_popup_id = null;

	com.nec.jp.ngsf.wiki.close_popup = function() {
		if (com.nec.jp.ngsf.wiki.popup_id == null) {
			if (com.nec.jp.ngsf.wiki.current_popup_id != null) {
				com.nec.jp.ngsf.wiki.hide_popup(com.nec.jp.ngsf.wiki.current_popup_id);
				com.nec.jp.ngsf.wiki.current_popup_id = null;
			}
		}

		com.nec.jp.ngsf.wiki.popup_id = null;
	}

	// to keep popup-ing, call this method.
	com.nec.jp.ngsf.wiki.current_popup = function(id) {
		if (id == com.nec.jp.ngsf.wiki.current_popup_id) {
			com.nec.jp.ngsf.wiki.popup_id = id;
		}
	}

	com.nec.jp.ngsf.wiki.popup_point = null;

	com.nec.jp.ngsf.wiki.show_popup = function(id) {
		com.nec.jp.ngsf.wiki.close_popup();

		com.nec.jp.ngsf.wiki.show_element(id);

		s = com.nec.jp.ngsf.wiki.get_element_style(id);

		if (s == null) {
			return;
		}

		com.nec.jp.ngsf.wiki.popup_id = id;
		com.nec.jp.ngsf.wiki.current_popup_id = id;

		// 表示位置補正
		// マウス位置
		var x = com.nec.jp.ngsf.wiki.popup_point.x;
		var y = com.nec.jp.ngsf.wiki.popup_point.y;

		// 画面にポップアップ表示領域はあるか差分を求める
		// (画面全体の幅 - ※余白) - マウス位置
		// ※余白：画面ギリギリまで表示する場合は 0 に設定
		var marginBottom = 5
		var diffWidth = (document.body.clientWidth - marginBottom) - x;
		var diffHeight = (document.body.clientHeight - marginBottom) - y;

		// 表示対象であるポップアップの幅
		var elmWidth = Element.getWidth(id);
		var elmHeight = Element.getHeight(id);

		// 表示領域にポップアップが入らない場合は、その差分を補正
		if (diffWidth < elmWidth) x = x - (elmWidth - diffWidth);
		if (diffHeight < elmHeight) y = y - (elmHeight - diffHeight);

		if (typeof document.body.style.maxHeight != "undefined") { 
		    // IE7/Firefoxなどの場合、スクロール量を加える 
			x = x + document.documentElement.scrollLeft;
		}
		
		s.left = x + "px";
		s.top = y + "px";

		if (document.all && $(id + "-frame")) {
			// IEの場合
			$(id + "-frame").style.display = 'block';
			$(id + "-frame").style.left = $(id).style.left;
			$(id + "-frame").style.top = $(id).style.top;
			$(id + "-frame").height = Element.getDimensions(id).height;
			$(id + "-frame").width = Element.getDimensions(id).width;
		}
	}

	com.nec.jp.ngsf.wiki.hide_popup = function(id) {
		com.nec.jp.ngsf.wiki.hide_element(id);
		
		if (document.all && $(id + "-frame")) {
			// IEの場合
			$(id + "-frame").style.display = 'none';
		}
	}

	/* context menu */

	com.nec.jp.ngsf.wiki.safePoint = function(point) {
		if (point != null) {
			return point;
		}

		return new com.nec.jp.ngsf.wiki.Point(0, 0);
	}

	com.nec.jp.ngsf.wiki.show_context_menu = function(type, /* non_null */param) {
		com.nec.jp.ngsf.wiki.popup_point = com.nec.jp.ngsf.wiki.safePoint(com.nec.jp.ngsf.wiki.mouse_pos);

		if ((type == "page") || ((type == "file")) || ((type == "category"))) {
			WikiEditPageController.getContextMenu(type, param, com.nec.jp.ngsf.wiki.getContextMenuCallback);
		} else if (type == "admin-user") {
			WikiEditUserController.getAdminUserContextMenu(param, com.nec.jp.ngsf.wiki.getContextMenuCallback);
		} else if (type == "admin-role") {
			WikiEditUserController.getAdminRoleContextMenu(param, com.nec.jp.ngsf.wiki.getContextMenuCallback);
		}
	}

	com.nec.jp.ngsf.wiki.getContextMenuCallback = function(contextMenu) {
		if ((contextMenu != null) && (contextMenu.length > 0)) {
			DWRUtil.setValue("gleanfeed-wiki-context-menu-container", contextMenu, {escapeHtml:false});
			com.nec.jp.ngsf.wiki.show_popup("gleanfeed-wiki-context-menu-container");
		}

		com.nec.jp.ngsf.wiki.close_popup(); // TODO;may be bug, should call here to close existing popup.
	}

	/* includeページのリスト */

	com.nec.jp.ngsf.wiki.show_include_list = function(param) {
		com.nec.jp.ngsf.wiki.popup_point = com.nec.jp.ngsf.wiki.safePoint(com.nec.jp.ngsf.wiki.mouse_pos);

		if (typeof document.body.style.maxHeight != "undefined") { 
			// IE 7, mozilla, safari, opera 9
			com.nec.jp.ngsf.wiki.show_popup(param);
		} else { 
			// IE6, older browsers
			com.nec.jp.ngsf.wiki.close_popup();
			com.nec.jp.ngsf.wiki.show_element(param);
			com.nec.jp.ngsf.wiki.popup_id = param;
			com.nec.jp.ngsf.wiki.current_popup_id = param;
		}
	}

	/*
	 * 確認ダイアログの表示用ユーティリティ
	 */
	var confirmDialog = {
		/*
		 * 確認ダイアログを表示します。
		 *
		 * @param message 確認ダイアログに表示するメッセージ
		 * @param okFunction 「OK」ボタンがクリックされたときに実行されるJS処理
		 * @param okLabel 「OK」ボタンのラベル
		 * @param cancelLabel 「Cancel」ボタンのラベル
		 */
		open: function(message, okFunction, okLabel, cancelLabel) {
			com.nec.jp.ngsf.wiki.close_popup();

			// ラベル指定がない場合はデフォルトを設定
			if (!okLabel || okLabel == "") {
				okLabel = "OK";
			}
			if (!cancelLabel || cancelLabel == "") {
				cancelLabel = "Cancel";
			}

			// PrototypeWindowでダイアログを表示
			Dialog.confirm(message, {zIndex:2000, okLabel:okLabel, cancelLabel:cancelLabel, ok:function(win){eval(okFunction);return true;}});
		},
		
		close: function() {
			Dialog.closeInfo();
		}
	}

	var win = null;

	/*
	 * ポップアップウィンドウの表示用ユーティリティ
	 */
	var popupWindow = {
		/*
		 * HTMLで記述されたコンテンツを指定してポップアップウィンドウを開きます。
		 *
		 * @param contents 表示するHTML
		 * @param winId ウィンドウID
		 * @param titleName ウィンドウのタイトルを格納しているオブジェクトの名前（name値）
		 * @param width ウィンドウの幅
		 * @param height ウィンドウの高さ
		 * @param resizableFlg リサイズ可能か（1：可能、0：不可能）
		 * @param closeCallback ウィンドウがクローズされた場合によばれるコールバック関数（trueをリターンしないとウィンドウが閉じません。）
		 * @param onShowFuncStr 表示直後に実行する関数呼び出し記述（例："onShowFunc()"）
		 */
		open: function(contents, winId, titleName, width, height, resizableFlg, closeCallback, onShowFuncStr) {
			if (onShowFuncStr) {
				win = new Window(winId, {className:"dialog", title:"SD-Wiki",// width:width, height:height,
						zIndex:2000, showEffectOptions:{duration:0}, hideEffectOptions:{duration:0},
						closable:false, minimizable:false, maximizable:false, resizable:resizableFlg,
						onShow:function(win){eval(onShowFuncStr);com.nec.jp.ngsf.wiki.focus_first_child(win.getContent());} });
			} else {
				win = new Window(winId, {className:"dialog", title:"SD-Wiki",// width:width, height:height,
					zIndex:2000, showEffectOptions:{duration:0}, hideEffectOptions:{duration:0},
					closable:false, minimizable:false, maximizable:false, resizable:resizableFlg,
					onShow:function(win){com.nec.jp.ngsf.wiki.focus_first_child(win.getContent());} });
			}

			// コンテンツをセット
			win.setHTMLContent(contents);
			
			// サイズを設定
			if (com.nec.jp.ngsf.wiki.getFirstElementByName(win.getContent(),
					"gleanfeed-wiki-popup-width", "INPUT")) {
				width = Number(com.nec.jp.ngsf.wiki.getFirstElementByName(win.getContent(),
						"gleanfeed-wiki-popup-width", "INPUT").value);
			}
			if (com.nec.jp.ngsf.wiki.getFirstElementByName(win.getContent(),
					"gleanfeed-wiki-popup-height", "INPUT")) {
				height = Number(com.nec.jp.ngsf.wiki.getFirstElementByName(win.getContent(),
						"gleanfeed-wiki-popup-height", "INPUT").value);
			}
			win.setSize(width, height);

			win.setCloseCallback(closeCallback);

			// タイトルを設定
			if (com.nec.jp.ngsf.wiki.getFirstElementByName(win.getContent(), titleName, "INPUT")) {
				var title = com.nec.jp.ngsf.wiki.getFirstElementByName(win.getContent(), titleName, "INPUT").value;
				win.setTitle(title);
			}
			win.setDestroyOnClose();
			win.showCenter(true);
			window.focus();
		},
		/*
		 * URLで指定したコンテンツをポップアップウィンドウとして開きます。
		 *
		 * @param url 表示するHTMLのURL
		 * @param winId ウィンドウID
		 * @param titleName ウィンドウのタイトルを格納しているオブジェクトの名前（name値）
		 * @param width ウィンドウの幅
		 * @param height ウィンドウの高さ
		 * @param resizableFlg リサイズ可能か（1：可能、0：不可能）
		 */
		openURL: function(url, winId, titleName, width, height, resizableFlg) {
			win = new Window(winId, {className:"dialog", title:"", width:width, height:height,
					zIndex:2000, url:url, showEffectOptions:{duration:0}, hideEffectOptions:{duration:0},
					resizable:resizableFlg});
			if (com.nec.jp.ngsf.wiki.getFirstElementByName(win.getContent(), titleName, "INPUT")) {
				var title = com.nec.jp.ngsf.wiki.getFirstElementByName(win.getContent(), titleName, "INPUT").value;
				win.setTitle(title);
			}
			win.setDestroyOnClose();
			win.showCenter(true);
			window.focus();
		},
		/*
		 * ポップアップウィンドウを閉じます。
		 *
		 * @param reload 閉じた後にリロードを行うか（1：リロードする、0：リロードしない）
		 */
		close: function(reload) {
			if (reload) {
				top.location.reload();
			}
			if (win) {
				win.close();
			}
		},
		/*
		 * ポップアップウィンドウを最大化します。
		 */
		maximize: function() {
			if (win) {
				if (win.visible && !win.isMaximized()) {
					win.maximize();
				}
			}
		},
		/*
		 * ポップアップウィンドウを最小化します。
		 */
		minimize: function() {
			if (win) {
				if (win.visible && win.isMaximized()) {
					win.maximize();
				}
			}
		}
	}

	/* popup form */

	com.nec.jp.ngsf.wiki.popup_form = function(type, id, path) {
		try {
			if (type == "page") {
				WikiEditPageController.getPopupForm(id, path, com.nec.jp.ngsf.wiki.getPopupFormCallback);
			} else if (type == "admin") {
				WikiEditUserController.getPopupForm(id, path, com.nec.jp.ngsf.wiki.getPopupFormCallback);
			}
		} catch (e) {
			window.alert(e.description);
		}
	}

	com.nec.jp.ngsf.wiki.getPopupFormCallback = function(popupForm) {
		if ((popupForm != null) && (popupForm.length > 0)) {
			popupWindow.open(popupForm, "popup", "gleanfeed-wiki-popup-title", 300, 150, true);
		}

		com.nec.jp.ngsf.wiki.close_popup(); // TODO;may be bug, should call here to close existing popup.
	}

	com.nec.jp.ngsf.wiki.getThemeForm = function(path) {
		try {
			WikiEditPageController.getThemeForm(path, location.href, com.nec.jp.ngsf.wiki.getPopupFormCallback);
		} catch (e) {
			window.alert(e.description);
		}
	}
	
	com.nec.jp.ngsf.wiki.getExportForm = function(path, kind) {
		try {
			var callback = function(popupForm) {
				if ((popupForm != null) && (popupForm.length > 0)) {
					popupWindow.open(popupForm, "popup", "gleanfeed-wiki-popup-title", 300, 150, true, undefined, 
							"com.nec.jp.ngsf.wiki.getCookieOnExport()");
				}

				com.nec.jp.ngsf.wiki.close_popup(); // TODO;may be bug, should call here to close existing popup.
			};
			
			WikiEditPageController.getExportForm(path, kind, callback);
		} catch (e) {
			window.alert(e.description);
		}
	}

	/*
	 *パスワード変更画面を表示します。
	 */
	com.nec.jp.ngsf.wiki.getPasswordForm = function(forward) {
		try {
			if ((forward==null) || (forward.length==0)){
				forward = location.href;
			}
			WikiEditUserController.getPasswordForm(forward, com.nec.jp.ngsf.wiki.getPopupFormCallback);
		} catch (e) {
			window.alert(e.description);
		}
	}

	/* focus first available child input element */

	com.nec.jp.ngsf.wiki.focus_first_child = function(/* non_null */o) {
		var children = o.childNodes;
		try {
			for (var i = 0; i < children.length; i++) {
				if ((children[i].tagName == "INPUT" && children[i].type != "hidden")
					|| (children[i].tagName == "SELECT")) {
					if (!children[i].readOnly && !children[i].disabled) {
						children[i].focus();
						return true;
					}
				} else {
					if (com.nec.jp.ngsf.wiki.focus_first_child(children[i])) {
						return true;
					}
				}
			}
		} catch (e) {
			com.nec.jp.ngsf.wiki.debug(e.description, true);
		}

		return false;
	}

	/* status */

	com.nec.jp.ngsf.wiki.set_status = function(msg) {
		window.status = msg;
		return true;
	}

	/* debug */

	var HTML_ESCAPE_CHAR = "'\"&<> ";

	var HTML_ESCAPE_TO = [ "&#39;", "&quot;", "&amp;", "&lt;", "&gt;", "&nbsp;" ];

	com.nec.jp.ngsf.wiki.debug = function(message, append) {
		var target = document.getElementById("gleanfeed-wiki-debug");

		if (target != null) {
			if (append) {
				target.innerHTML = target.innerHTML + "<br />" + com.nec.jp.ngsf.wiki.escapeText(message, HTML_ESCAPE_CHAR, HTML_ESCAPE_TO);
			} else {
				target.innerHTML = message;
			}
		}
	}

	/* edit */

	com.nec.jp.ngsf.wiki.getTextAreaSelection = function(textarea) {
		if (textarea == null) {
			return null;
		}

		textarea.focus();

		var selection = new Object;

		if (window.getSelection) {
			selection.start = textarea.selectionStart;
			selection.end = textarea.selectionEnd;
		} else {
			// IE
			// TODO：選択範囲の終了から連続する改行は選択範囲から除外されてしまいます。。
			var range = document.selection.createRange();
			var marker = false;

			if (range.text.length == 0) {
				marker = true;
				// range前の改行が無視されるため、マーカーとして一時的に空白を入れます。
				range.text = " ";
			}

			var clonedRange = range.duplicate();
			clonedRange.moveToElementText(textarea);
			clonedRange.setEndPoint("EndToEnd", range);

			selection.start = clonedRange.text.length - range.text.length;
			selection.end = clonedRange.text.length;

			if (marker) {
				// マーカーとして入れた空白を削除します。
				range = textarea.createTextRange();
				range.moveStart("character", selection.start - 1 - com.nec.jp.ngsf.wiki.findChars(textarea.value, 0, selection.start, '\n'));
				range.moveEnd("character", -(textarea.value.length - selection.end - com.nec.jp.ngsf.wiki.findChars(textarea.value, selection.end, textarea.value.length, '\n')));
				range.select();
				range.text = "";
				selection.start = selection.start - 1;
				selection.end = selection.end - 1;
			}
		}

		return selection;
	}

	com.nec.jp.ngsf.wiki.setTextAreaSelection = function(textarea, selection) {
		if (textarea == null) {
			return;
		}

		textarea.focus();

		if (textarea.setSelectionRange) {
			textarea.setSelectionRange(selection.start, selection.end);
		} else {
			// IE
			var range = textarea.createTextRange();

			range.moveStart("character", selection.start - com.nec.jp.ngsf.wiki.findChars(textarea.value, 0, selection.start, '\n'));
			range.moveEnd("character", -(textarea.value.length - selection.end - com.nec.jp.ngsf.wiki.findChars(textarea.value, selection.end, textarea.value.length, '\n')));

			range.select();
		}
	}

	com.nec.jp.ngsf.wiki.findChars = function(s, start, end, c) {
		var count = 0;

		for (var i = start; i < s.length && i < end; i++) {
			if (c == s.charAt(i)) {
				count = count + 1;
			}
		}

		return count;
	}

	com.nec.jp.ngsf.wiki.replaceTextAreaSelection = function(textarea_id, func, p1) {
		var o = document.getElementById(textarea_id)

		if (o == null) {
			return;
		}

		var selection = com.nec.jp.ngsf.wiki.getTextAreaSelection(o);

		var value = o.value;
		var s1 = value.substring(0, selection.start);
		var s2 = value.substring(selection.start, selection.end);
		var s3 = value.substring(selection.end, value.length);

		// main process is here.

		var new_s2;

		if (p1 == null) {
			new_s2 = func(s2);
		} else {
			new_s2 = func(s2, p1);
		}

		o.value = s1 + new_s2 + s3;

		selection.end = selection.start + new_s2.length;

		com.nec.jp.ngsf.wiki.setTextAreaSelection(o, selection);
	}

	com.nec.jp.ngsf.wiki.wikiQuote = function(s, q) {
		if (s.indexOf(q) != -1) {
			do {
				s = s.replace(q, "");
			} while (s.indexOf(q) != -1);
		}

		return q + s + q;
	}

	/* editor */

	com.nec.jp.ngsf.wiki.editorSuffix = "-editor";
	com.nec.jp.ngsf.wiki.containerSuffix = "-container";
	com.nec.jp.ngsf.wiki.editorResizeRightSuffix = "-right";
	com.nec.jp.ngsf.wiki.editorResizeBottomSuffix = "-bottom";
	com.nec.jp.ngsf.wiki.editorResizeRightBottomSuffix = "-right-bottom";

	com.nec.jp.ngsf.wiki.editorResizeStatus = {
		id: "gleanfeed-wiki-edit-page-text", // initial value.
		markerId: null,
		suffix: null,
		width: 0,
		height: 0,
		x: 0,
		y: 0
	};

	com.nec.jp.ngsf.wiki.editor_resize_onmousedown = function(e) {
		com.nec.jp.ngsf.wiki.editor_resize_onmouseup();

		var markerId = Event.element(e).id;
		var suffix;
		var markerObject = null;
		var id = null;
		var object = null;
		var editor = null;
		var container = null;

		if (!markerId) {
			return;
		}

		if (markerId.endsWith(com.nec.jp.ngsf.wiki.editorResizeRightBottomSuffix)) {
			suffix = com.nec.jp.ngsf.wiki.editorResizeRightBottomSuffix;
		} else if (markerId.endsWith(com.nec.jp.ngsf.wiki.editorResizeRightSuffix)) {
			suffix = com.nec.jp.ngsf.wiki.editorResizeRightSuffix;
		} else if (markerId.endsWith(com.nec.jp.ngsf.wiki.editorResizeBottomSuffix)) {
			suffix = com.nec.jp.ngsf.wiki.editorResizeBottomSuffix;
		} else {
			return;
		}

		id = markerId.substring(0, markerId.length - suffix.length);

		try {
			markerObject = $(markerId);
			object = $(id);
			editor = $(id + com.nec.jp.ngsf.wiki.editorSuffix);
			container = $(id + com.nec.jp.ngsf.wiki.containerSuffix);
		} catch (e) {
			return;
		}

		if ((markerObject == null) || (object == null) || (editor == null) || (container == null)) {
			return;
		}

		com.nec.jp.ngsf.wiki.editorResizeStatus.id = id;
		com.nec.jp.ngsf.wiki.editorResizeStatus.markerId = markerId;
		com.nec.jp.ngsf.wiki.editorResizeStatus.suffix = suffix;
		com.nec.jp.ngsf.wiki.editorResizeStatus.width = editor.getWidth();
		com.nec.jp.ngsf.wiki.editorResizeStatus.height = editor.getHeight();
		com.nec.jp.ngsf.wiki.editorResizeStatus.x = Event.pointerX(e);
		com.nec.jp.ngsf.wiki.editorResizeStatus.y = Event.pointerY(e);

		Event.observe(document, "mousemove", com.nec.jp.ngsf.wiki.editor_resize_onmousemove, false);
		Event.observe(document, "mouseup", com.nec.jp.ngsf.wiki.editor_resize_onmouseup, false);
	}

	com.nec.jp.ngsf.wiki.editor_resize_onmousemove = function(e) {
		if (com.nec.jp.ngsf.wiki.editorResizeStatus.markerId == null) {
			return false;
		}

		var stop = false;

		if ((com.nec.jp.ngsf.wiki.editorResizeStatus.suffix == com.nec.jp.ngsf.wiki.editorResizeRightSuffix) || (com.nec.jp.ngsf.wiki.editorResizeStatus.suffix == com.nec.jp.ngsf.wiki.editorResizeRightBottomSuffix)) {
			var x = Event.pointerX(e);
			var editor_width = com.nec.jp.ngsf.wiki.editorResizeStatus.width + (x - com.nec.jp.ngsf.wiki.editorResizeStatus.x);

			if (editor_width < 1) {
				editor_width = 1;
			}

			$(com.nec.jp.ngsf.wiki.editorResizeStatus.id + com.nec.jp.ngsf.wiki.editorSuffix).style.width = (editor_width + 4) + "px";
			$(com.nec.jp.ngsf.wiki.editorResizeStatus.id + com.nec.jp.ngsf.wiki.containerSuffix).style.width = editor_width + "px";
			$(com.nec.jp.ngsf.wiki.editorResizeStatus.id).style.width = editor_width + "px";
			var resizeRight = document.getElementById(com.nec.jp.ngsf.wiki.editorResizeStatus.id + com.nec.jp.ngsf.wiki.editorResizeRightSuffix);
			if (resizeRight) {
				resizeRight.style.left = x + "px";
			}
			var resizeBottom = document.getElementById(com.nec.jp.ngsf.wiki.editorResizeStatus.id + com.nec.jp.ngsf.wiki.editorResizeBottomSuffix);
			if (resizeBottom) {
				resizeBottom.style.width = editor_width + "px";
			}
			var resizeRightBottom = document.getElementById(com.nec.jp.ngsf.wiki.editorResizeStatus.id + com.nec.jp.ngsf.wiki.editorResizeRightBottomSuffix);
			if (resizeRightBottom) {
				resizeRightBottom.style.left = x + "px";
			}
			stop = true;
		}

		if ((com.nec.jp.ngsf.wiki.editorResizeStatus.suffix == com.nec.jp.ngsf.wiki.editorResizeBottomSuffix) || (com.nec.jp.ngsf.wiki.editorResizeStatus.suffix == com.nec.jp.ngsf.wiki.editorResizeRightBottomSuffix)) {
			var y = Event.pointerY(e);
			var editor_height = com.nec.jp.ngsf.wiki.editorResizeStatus.height + (y - com.nec.jp.ngsf.wiki.editorResizeStatus.y);

			if (editor_height < 1) {
				editor_height = 1;
			}

			$(com.nec.jp.ngsf.wiki.editorResizeStatus.id + com.nec.jp.ngsf.wiki.editorSuffix).style.height = (editor_height + 4) + "px";
			$(com.nec.jp.ngsf.wiki.editorResizeStatus.id + com.nec.jp.ngsf.wiki.containerSuffix).style.height = editor_height + "px";
			$(com.nec.jp.ngsf.wiki.editorResizeStatus.id).style.height = editor_height + "px";
			var resizeRight = document.getElementById(com.nec.jp.ngsf.wiki.editorResizeStatus.id + com.nec.jp.ngsf.wiki.editorResizeRightSuffix);
			if (resizeRight) {
				resizeRight.style.height = editor_height + "px";
			}
			var resizeBottom = document.getElementById(com.nec.jp.ngsf.wiki.editorResizeStatus.id + com.nec.jp.ngsf.wiki.editorResizeBottomSuffix);
			if (resizeBottom) {
				resizeBottom.style.top = y + "px";
			}
			var resizeRightBottom = document.getElementById(com.nec.jp.ngsf.wiki.editorResizeStatus.id + com.nec.jp.ngsf.wiki.editorResizeRightBottomSuffix);
			if (resizeRightBottom) {
				resizeRightBottom.style.top = y + "px";
			}
			stop = true;
		}

		if (stop) {
			Event.stop(e);
		}
	}

	com.nec.jp.ngsf.wiki.editor_resize_onmouseup = function(e) {
		if (com.nec.jp.ngsf.wiki.editorResizeStatus.markerId != null) {
			Event.stopObserving(document, "mousemove", com.nec.jp.ngsf.wiki.editor_resize_onmousemove, false);
			Event.stopObserving(document, "mouseup", com.nec.jp.ngsf.wiki.editor_resize_onmouseup, false);
			com.nec.jp.ngsf.wiki.editorResizeStatus.id = null;
			com.nec.jp.ngsf.wiki.editorResizeStatus.markerId = null;
			com.nec.jp.ngsf.wiki.editorResizeStatus.suffix = null;
			com.nec.jp.ngsf.wiki.editorResizeStatus.width = null;
			com.nec.jp.ngsf.wiki.editorResizeStatus.height = null;
			com.nec.jp.ngsf.wiki.editorResizeStatus.x = null;
			com.nec.jp.ngsf.wiki.editorResizeStatus.y = null;
		}
	}

	/*
	 * Editorからのレスポンスをmapに入れます。
	 */
	com.nec.jp.ngsf.wiki.parseEditFileResponse = function(results) {
		var map = new Object();

		for (var i = 0; i < results.length; i++) {
			var pos = results[i].indexOf('=');
			var name = results[i].substring(0, pos);
			var value = results[i].substring(pos + 1);

			map[name] = value;
			com.nec.jp.ngsf.wiki.debug(name + " = " + value, true);
		}

		return map;
	}

	/*
	 * 追加のJavaScriptを登録します。
	 */
	com.nec.jp.ngsf.wiki.addScripts = function(scripts) {
		if (scripts == null) {
			return;
		}

		if (scripts.length > 0) {
			var scripts = scripts.split('|');
	
			for (var i = 0; i < scripts.length; i++) {
				var scriptAndCharSet = scripts[i].split(',');

				if (scriptAndCharSet.length > 0) {
					var script = scriptAndCharSet[0];
					var charSet = null;

					if (scriptAndCharSet.length > 1) {
						charSet = scriptAndCharSet[1];
					}

					try {
						com.nec.jp.ngsf.wiki.registerScript(script, charSet);
					} catch (e) {
						com.nec.jp.ngsf.wiki.debug(e.description, true);
					}
				}
			}
		}
	}

	/*
	 * 追加のCSSを登録します。
	 */
	com.nec.jp.ngsf.wiki.addCSSs = function(csss) {
		if (csss == null) {
			return;
		}

		com.nec.jp.ngsf.wiki.debug(csss, true);

		if (csss.length > 0) {
			var csss = csss.split('|');

			for (var i = 0; i < csss.length; i++) {
				try {
					com.nec.jp.ngsf.wiki.registerCSS(csss[i]);
				} catch (e) {
					com.nec.jp.ngsf.wiki.debug(e.description, true);
				}
			}
		}
	}

	/*
	 * プレビューの内容を設定します。
	 */
	com.nec.jp.ngsf.wiki.setPreview = function(preview) {
		if (preview == null) {
			return;
		}

		com.nec.jp.ngsf.wiki.debug(preview, true);

		// DWRUtil.setValue("gleanfeed-wiki-edit-page-preview-body", preview, {escapeHtml:false});
		var bodyElement = document.getElementById("gleanfeed-wiki-edit-page-preview-body");
		bodyElement.innerHTML = preview;

		/* 追加したプレビューの内容にJavaScriptがある場合evalします。*/
		/* src指定ではなく、インラインのものを想定しています。*/
		var scriptElements = bodyElement.getElementsByTagName("script");

		if (scriptElements != null) {
			for (var i = 0; i < scriptElements.length; i++) {
				try {
					eval(scriptElements[i].innerHTML);
				} catch (e) {
					com.nec.jp.ngsf.wiki.debug("eval(" + scriptElements[i].innerHTML + ") failed:" + e.description, true);
				}
			}
		}
	}

	/* preview */

	com.nec.jp.ngsf.wiki.previewEditFile = function(actionId) {
		com.nec.jp.ngsf.wiki.set_enable("gleanfeed-wiki-edit-page-preview-button", false);
		var pageName = DWRUtil.getValue("gleanfeed-wiki-edit-page-name");
		var text = DWRUtil.getValue("gleanfeed-wiki-edit-page-text");
		var args = new Array("preview", pageName, text);
		WikiPluginController.processAction(actionId, args, com.nec.jp.ngsf.wiki.previewEditFileCallback);
	}

	com.nec.jp.ngsf.wiki.previewEditFileCallback = function(values) {
		var map = com.nec.jp.ngsf.wiki.parseEditFileResponse(values);

		if (map["status"] == "success") {
			com.nec.jp.ngsf.wiki.addScripts(map["scripts"]);
			com.nec.jp.ngsf.wiki.addCSSs(map["csss"]);
			com.nec.jp.ngsf.wiki.setPreview(map["preview"]);

			com.nec.jp.ngsf.wiki.hide_element("gleanfeed-wiki-edit-page-diff");
			com.nec.jp.ngsf.wiki.show_element("gleanfeed-wiki-edit-page-preview");
		} else {
			DWRUtil.setValue("gleanfeed-wiki-edit-page-message", map["message"], {escapeHtml:false});
		}

		com.nec.jp.ngsf.wiki.set_enable("gleanfeed-wiki-edit-page-preview-button", true);
	}

	/* diff */

	com.nec.jp.ngsf.wiki.diffEditFile = function(actionId) {
		com.nec.jp.ngsf.wiki.set_enable("gleanfeed-wiki-edit-page-diff-button", false);
		var pageName = DWRUtil.getValue("gleanfeed-wiki-edit-page-name");
		var text = DWRUtil.getValue("gleanfeed-wiki-edit-page-text");
		var args = new Array("diff", pageName, text);
		WikiPluginController.processAction(actionId, args, com.nec.jp.ngsf.wiki.diffEditFileCallback);
	}

	com.nec.jp.ngsf.wiki.diffEditFileCallback = function(values) {
		var map = com.nec.jp.ngsf.wiki.parseEditFileResponse(values);

		if (map["status"] == "success") {
			DWRUtil.setValue("gleanfeed-wiki-edit-page-diff-body", map["diff"], {escapeHtml:false});

			com.nec.jp.ngsf.wiki.hide_element("gleanfeed-wiki-edit-page-preview");
			com.nec.jp.ngsf.wiki.show_element("gleanfeed-wiki-edit-page-diff");
		} else {
			DWRUtil.setValue("gleanfeed-wiki-edit-page-message", map["message"], {escapeHtml:false});
		}

		com.nec.jp.ngsf.wiki.set_enable("gleanfeed-wiki-edit-page-diff-button", true);
	}

	/* save */

	com.nec.jp.ngsf.wiki.saveEditFile = function(actionId) {
		com.nec.jp.ngsf.wiki.set_enable("gleanfeed-wiki-edit-page-save-button", false);
		var pageName = DWRUtil.getValue("gleanfeed-wiki-edit-page-name");
		var text = DWRUtil.getValue("gleanfeed-wiki-edit-page-text");
		var lastModified = DWRUtil.getValue("gleanfeed-wiki-edit-page-last-modified");
		var notUpdateLastModified = DWRUtil.getValue("gleanfeed-wiki-edit-page-not-update-last-modified");
		var args = new Array("save", pageName, text, lastModified, notUpdateLastModified);
		WikiPluginController.processAction(actionId, args, com.nec.jp.ngsf.wiki.saveEditFileCallback);
	}

	com.nec.jp.ngsf.wiki.saveEditFileCallback = function(values) {
		var map = com.nec.jp.ngsf.wiki.parseEditFileResponse(values);

		if (map["status"] == "success") {
			com.nec.jp.ngsf.wiki.addScripts(map["scripts"]);
			com.nec.jp.ngsf.wiki.addCSSs(map["csss"]);
			com.nec.jp.ngsf.wiki.setPreview(map["preview"]);
			DWRUtil.setValue("gleanfeed-wiki-edit-page-last-modified", map["date"], {escapeHtml:false});

			com.nec.jp.ngsf.wiki.hide_element("gleanfeed-wiki-edit-page-diff");
			com.nec.jp.ngsf.wiki.show_element("gleanfeed-wiki-edit-page-preview");
			com.nec.jp.ngsf.wiki.set_enable("gleanfeed-wiki-edit-page-save-button", true);

		} else if (map["status"] == "modified") {
			DWRUtil.setValue("gleanfeed-wiki-edit-page-diff-body", map["diff"], {escapeHtml:false});

			com.nec.jp.ngsf.wiki.hide_element("gleanfeed-wiki-edit-page-preview");
			com.nec.jp.ngsf.wiki.show_element("gleanfeed-wiki-edit-page-diff");
			com.nec.jp.ngsf.wiki.set_enable("gleanfeed-wiki-edit-page-save-button", false);
			com.nec.jp.ngsf.wiki.set_enable("gleanfeed-wiki-edit-page-not-update-last-modified", false);
			com.nec.jp.ngsf.wiki.set_enable("gleanfeed-wiki-edit-page-submit", false);
		} else {
			com.nec.jp.ngsf.wiki.set_enable("gleanfeed-wiki-edit-page-save-button", true);
		}

		DWRUtil.setValue("gleanfeed-wiki-edit-page-message", map["message"], {escapeHtml:false});
	}

	/* finish */

	com.nec.jp.ngsf.wiki.finishEditFile = function(submit_button) {
		submit_button.disabled = true;
		document.getElementById("gleanfeed-wiki-edit-page-command").value = "finish";
		submit_button.form.submit();
	}

	/* upload */

	com.nec.jp.ngsf.wiki.initUploadStatus = function(uuid) {
		com.nec.jp.ngsf.wiki.set_enable("gleanfeed-wiki-upload-file-submit", false);

		if (uuid && (uuid.length > 0)) {
			// must use setTimeout here to run on Firefox correctly.
			setTimeout(function(){com.nec.jp.ngsf.wiki.updateUploadStatus(uuid)}, 1000);
		}

		return true;
	}

	com.nec.jp.ngsf.wiki.updateUploadStatus = function(uuid) {
		com.nec.jp.ngsf.wiki.set_enable("gleanfeed-wiki-upload-file-submit", false);

		WikiUploadFileController.getStatus(uuid, function(status) {
			DWRUtil.setValue("gleanfeed-wiki-upload-file-status", status, {escapeHtml:false});

			if (status && (status.length > 0)) {
				if ((status != "finish") && (status != "canceled") && (status != "error")) {
					setTimeout(function(){com.nec.jp.ngsf.wiki.updateUploadStatus(uuid)}, 1000);
				}
			} else {
				DWRUtil.setValue("gleanfeed-wiki-upload-file-status", "server may be busy.", {escapeHtml:false});
			}
		});
	}

	/* assign/deassign role x permission to a WikiContent. */

	com.nec.jp.ngsf.wiki.adminContentPermission_checkInherit = function(form_id, check_id) {
		var fo = document.getElementById(form_id);

		if (fo == null) {
			return;
		}

		var o = document.getElementById(check_id);

		if (o == null) {
			return;
		}

		var array = new Array();

		com.nec.jp.ngsf.wiki.adminContentPermission_getInherit(fo, check_id + "-role", array); // ID.ROLE_SUFFIX = "-role";

		var checked = 0;

		for (var i = 0; i < array.length; i++) {
			if (array[i].checked) {
				checked = checked + 1;
			}
		}

		for (var i = 0; i < array.length; i++) {
			array[i].disabled = o.checked;

			if (!o.checked && checked == 0) {
				array[i].checked = true;
			}
		}
	}

	com.nec.jp.ngsf.wiki.adminContentPermission_check = function(form_id, check_id) {
		var fo = document.getElementById(form_id);

		if (fo == null) {
			return;
		}

		var o = document.getElementById(check_id);

		if (o == null) {
			return;
		}

		var pid = com.nec.jp.ngsf.wiki.adminContentPermission_getParent(check_id);

		var po = document.getElementById(pid);

		var array = new Array();

		com.nec.jp.ngsf.wiki.adminContentPermission_getInherit(fo, pid + "-role", array); // ID.ROLE_SUFFIX = "-role";

		var checked = 0;

		if ((po != null) && (po.checked)) {
			checked = 1;
		}

		for (var i = 0; i < array.length; i++) {
			if (array[i].checked) {
				checked = checked + 1;
			}
		}

		if (checked == 0) {
			o.checked = true;
		}
	}

	com.nec.jp.ngsf.wiki.adminContentPermission_getInherit = function(/* non_null */o, prefix, array) {
		var children = o.childNodes;

		for (var i = 0; i < children.length; i++) {
			if (children[i].tagName == "INPUT") {
				if (children[i].getAttribute("type") == "checkbox") {
					var id = children[i].getAttribute("id");

					if ((id != null) && (id.indexOf(prefix) == 0)) {
						array[array.length] = children[i];
					}
				}
			} else {
				com.nec.jp.ngsf.wiki.adminContentPermission_getInherit(children[i], prefix, array);
			}
		}
	}

	com.nec.jp.ngsf.wiki.adminContentPermission_getParent = function(id) {
		if (id == null) {
			return null;
		}

		var index = id.indexOf("-role"); // ID.ROLE_SUFFIX = "-role";

		if (index > 0) {
			return id.substring(0, index);
		}

		return null;
	}

	com.nec.jp.ngsf.wiki.submitUpdateContentPermissions = function(form_id, path) {
		// ID.ADMIN_CONTENT_PERMISSION_APPLY_BUTTON = "gleanfeed-wiki-admin-content-permission-apply-button";
		com.nec.jp.ngsf.wiki.set_enable("gleanfeed-wiki-admin-content-permission-apply-button", false);

		o = document.getElementById(form_id);

		if (o == null) {
			return;
		}

		inputText = com.nec.jp.ngsf.wiki.merge_input(o);

		WikiEditUserController.updateContentPermissions(path, inputText, function(msg) {
			com.nec.jp.ngsf.wiki.close_popup();
			popupWindow.close(0);
		});
	}

	/*
	 * タブを切り替えます。
	 */
	com.nec.jp.ngsf.wiki.changeTab = function(name, where){
		var names = "";
		if(where=="fileselect"){
			names = new Array("fileselect-pages", "fileselect-temps", "fileselect-images", "fileselect-uploadfiles", "fileselect-url");
			var categoryElm = $('gleanfeed-wiki-popup-form-categorylist');
			var contentsElm = $('gleanfeed-wiki-popup-form-contentslist');
			var uploadElm = $('gleanfeed-wiki-fileselect-upload');
			if (categoryElm) {
				if (name == 'fileselect-url') {
					categoryElm.style.display = "none";
					contentsElm.style.width = "100%";
					uploadElm.style.display = "none";
				} else if (name == 'fileselect-images' || name == 'fileselect-uploadfiles') {
					categoryElm.style.display = "block";
					contentsElm.style.width = "60%";
				} else {
					categoryElm.style.display = "block";
					contentsElm.style.width = "60%";
					uploadElm.style.display = "none";
				}
			}
		}else{
			names = new Array("article", "categories", "pages", "uploads", "templates");
		}

		for(i = 0; i < names.length; i++){
			var objtab = document.getElementById("gleanfeed-wiki-tabs-" + names[i]);
			var objbox = document.getElementById("gleanfeed-wiki-" + names[i]);
			if(names[i] == name){
				if (objtab) {
					objtab.className = "cur";
				}
				if (objbox) {
					objbox.style.display = "block";
				}
			}else{
				if (objtab) {
					objtab.className = "";
				}
				if (objbox) {
					objbox.style.display = "none";
				}
			}
		}
	}

	/*
	 * 指定したエレメントの子オブジェクトから指定した名前のエレメントを取得します。
	 * 同名のエレメントがあった場合、1番目のエレメントを返します。
	 *
	 * @param element 親のエレメント
	 * @param name 取得するエレメントのname
	 * @param tagName タグ名の指定
	 * @return エレメント
	 */
	com.nec.jp.ngsf.wiki.getFirstElementByName = function(element, name, tagName) {
		var elements = element.getElementsByTagName(tagName);
		for (var i = 0; i < elements.length; i++) {
			if (elements[i].name == name) {
				return elements[i];
			}
		}
	}

	/*
	 * 指定したエレメントの子オブジェクトから指定したIDのエレメントを取得します。
	 * 同名のエレメントがあった場合、1番目のエレメントを返します。
	 *
	 * @param element 親のエレメント
	 * @param id 取得するエレメントのid
	 * @param tagName タグ名の指定
	 * @return エレメント
	 */
	com.nec.jp.ngsf.wiki.getFirstElementById = function(element, id, tagName) {
		var elements = element.getElementsByTagName(tagName);
		for (var i = 0; i < elements.length; i++) {
			if (elements[i].id == id) {
				return elements[i];
			}
		}
	}

	//
	// テーマ変更画面のスクリプト
	//
	/*
	 * サムネイル表示を切り替えます。
	 */
	com.nec.jp.ngsf.wiki.changeThumbnail = function(){
		var path	= "images/thumbs/";
		var suffix	= ".png";

		var skin = "skin_default";
		var skinRadios = document.getElementsByName("gleanfeed-wiki-theme-skin");
		for (var i = 0; i < skinRadios.length; i++) {
			if (skinRadios[i].checked) {
				skin = skinRadios[i].value;
			}
		}

		var layout = "layout_default";
		var layoutRadios = document.getElementsByName("gleanfeed-wiki-theme-layout");
		for (var i = 0; i < layoutRadios.length; i++) {
			if (layoutRadios[i].checked) {
				layout = layoutRadios[i].value;
			}
		}

		path = path + skin + "-" + layout + suffix;

		if(thumb = document.getElementById("thumbnail")){
			thumb.src = path;
		}
	}

	/*
	 * スキンの選択時にレイアウトセット表示を切り替えます。
	 *
	 * @param layoutsetId 表示するレイアウトセットのID
	 * @param layoutsetIdList 全レイアウトセットのID配列を表した文字列（例：[layout_adjacent,layout_separate,]）
	 */
	com.nec.jp.ngsf.wiki.changeLayoutSelection = function(layoutsetId, layoutsetIdList){
	    var layoutsetIdArray = eval(layoutsetIdList);
	    for (var i = 0; i < layoutsetIdArray.length; i++) {
	    	if (document.getElementById(layoutsetIdArray[i])) {
	    		with (document.getElementById(layoutsetIdArray[i])) {
			    	if (layoutsetIdArray[i] == layoutsetId) {
		    			getElementsByTagName("input")[0].checked = true;
			    		style.display = "block";
			    		disabled = false;
			    	} else {
			    		style.display = "none";
			    		disabled = true;
			    	}
	    		}
	    	}
	    }
	}

	/*
	 * テーマ変更画面の「親のテーマを継承」のチェックをしたとき、テーマ選択を無効化／有効化する処理を行います。
	 *
	 * @param elm チェックボックスのエレメント。
	 */
	com.nec.jp.ngsf.wiki.inheritParent = function(elm) {
		if (elm.checked) {
			com.nec.jp.ngsf.wiki.themeDisable();
		} else {
			com.nec.jp.ngsf.wiki.themeEnable();
		}
	}

	/*
	 * テーマ選択を無効化します。
	 */
	com.nec.jp.ngsf.wiki.themeDisable = function() {
		var skinRadios = document.getElementsByName("gleanfeed-wiki-theme-skin");
		for (var i = 0; i < skinRadios.length; i++) {
			skinRadios[i].disabled=true;
		}
		var layoutRadios = document.getElementsByName("gleanfeed-wiki-theme-layout");
		for (var i = 0; i < layoutRadios.length; i++) {
			layoutRadios[i].disabled=true;
		}
	}

	/*
	 * テーマ選択を有効化します。
	 */
	com.nec.jp.ngsf.wiki.themeEnable = function() {
		var skinRadios = document.getElementsByName("gleanfeed-wiki-theme-skin");
		for (var i = 0; i < skinRadios.length; i++) {
			skinRadios[i].disabled=false;
		}
		var layoutRadios = document.getElementsByName("gleanfeed-wiki-theme-layout");
		for (var i = 0; i < layoutRadios.length; i++) {
			layoutRadios[i].disabled=false;
		}
	}
	
	/*
	 * エクスポートを実行します。
	 * （エクスポート設定画面から呼び出されます）
	 */
	com.nec.jp.ngsf.wiki.submitExport = function(formElement, idListStr) {
		if ($('gleanfeed-wiki-export-target').value == 'category') {
			// カテゴリのエクスポートの場合はアラートを表示
			if (!confirm('カテゴリのエクスポートは時間がかかる場合があります。\n実行してもよろしいですか？\n（ダウンロードダイアログが表示されるまで、そのままお待ちください）')) {
				return false;
			}
		}
		
		// Cookieに保存
		var idList = eval(idListStr);
		var cookieStr = "";
		for (var i = 0; i < idList.length; i++) {
			var elements = document.getElementsByName(idList[i]);
			if (elements && elements[0]) {
				switch (elements[0].type) {
				case "radio":
				case "checkbox":
					var tmpCookieStr = idList[i] + ":";
					
					for (var k = 0; k < elements.length; k++) {
						if (elements[k].checked) {
							tmpCookieStr = tmpCookieStr + elements[k].value;
							break;
						}
					}
					cookieStr = cookieStr + tmpCookieStr + "|";
					break;
				}
			}
		}
		if (cookieStr.endsWith("|")) {
			cookieStr = cookieStr.substring(0, cookieStr.length - 1);
			document.cookie = "com.nec.jp.ngsf.wiki.cookie.export.option=" + cookieStr + "; expires=Tue, 31-Dec-2999 23:59:59 GMT;"
		}
		
		formElement.submit();
		if(popupWindow){
			popupWindow.close();
		}
	}
	
	/*
	 * Cookieから出力オプションを読み込み、エクスポート設定画面に設定します。
	 * 
	 */
	com.nec.jp.ngsf.wiki.getCookieOnExport = function() {
		var cookies = document.cookie.split(";");
		for (var i = 0; i < cookies.length; i++) {
			// 出力オプションのCookie設定のみ処理する
			if (cookies[i].startsWith("com.nec.jp.ngsf.wiki.cookie.export.option=")) {
				var valueStr = cookies[i].substring(cookies[i].indexOf("=") + 1);
				var values = valueStr.split("|");
				
				for (var j = 0; j < values.length; j++) {
					var option = values[j].split(":");
					var elements = document.getElementsByName(option[0]);
					
					// エレメントがある場合、Cookieに保存されている値を設定
					if (elements && elements[0]) {
						switch (elements[0].type) {
						case "radio":
						case "checkbox":
							for (var k = 0; k < elements.length; k++) {
								if (elements[k].value == option[1]) {
									elements[k].checked = true;
								} else {
									elements[k].checked = false;
								}
							}
							break;
						}
					}
				}
			}
		}
	}
	
	/*
	 * update user attribute
	 */
	com.nec.jp.ngsf.wiki.submitUpdateUserAttribute = function(userId) {
		var userFullName = document.getElementById('gleanfeed-wiki-admin-user-attribute-userfullname').value;
		var enabled = document.getElementById('gleanfeed-wiki-admin-user-attribute-enabled').checked;
		var description = document.getElementById('gleanfeed-wiki-admin-user-attribute-description').value;

		WikiEditUserController.updateUserAttribute(userId, userFullName, enabled, description, function(msg) {
			if (msg != null) {
				var result = eval(msg);
				if (document.getElementById("gleanfeed-wiki-user-userfullname-" + userId) && result.length > 0) {
					document.getElementById("gleanfeed-wiki-user-userfullname-" + userId).innerHTML = result[0];
				}
				if (document.getElementById("gleanfeed-wiki-user-enabled-" + userId) && result.length > 1) {
					document.getElementById("gleanfeed-wiki-user-enabled-" + userId).innerHTML = result[1];
				}
				if (document.getElementById("gleanfeed-wiki-user-description-" + userId) && result.length > 2) {
					document.getElementById("gleanfeed-wiki-user-description-" + userId).innerHTML = result[2];
				}
			}

			com.nec.jp.ngsf.wiki.close_popup();
			popupWindow.close(0);
		});
		
		return false;
	}
	
	/*
	 * update role attribute
	 */
	com.nec.jp.ngsf.wiki.submitUpdateRoleAttribute = function(roleId) {
		var name = document.getElementById('gleanfeed-wiki-admin-role-attribute-name').value;
		var description = document.getElementById('gleanfeed-wiki-admin-role-attribute-description').value;

		WikiEditUserController.updateRoleAttribute(roleId, name, description, function(msg) {
			if (msg != null) {
				var result = eval(msg);
				if (document.getElementById("gleanfeed-wiki-role-name-" + roleId) && result.length > 0) {
					document.getElementById("gleanfeed-wiki-role-name-" + roleId).innerHTML = result[0];
				}
				if (document.getElementById("gleanfeed-wiki-role-description-" + roleId) && result.length > 1) {
					document.getElementById("gleanfeed-wiki-role-description-" + roleId).innerHTML = result[1];
				}
			}

			com.nec.jp.ngsf.wiki.close_popup();
			popupWindow.close(0);
		});
		
		return false;
	}
	
	/*
	 * update role-users
	 */
	com.nec.jp.ngsf.wiki.submitUpdateRoleUsers = function(formId, roleId) {
		com.nec.jp.ngsf.wiki.set_enable("gleanfeed-wiki-admin-role-user-submit", false);
		
		o = document.getElementById(formId);

		if (o == null) {
			return;
		}

		inputText = com.nec.jp.ngsf.wiki.merge_input(o);

		WikiEditUserController.updateRoleUsers(roleId, inputText, function(msg) {
			if (msg != null) {
				var updateLabels = eval(msg);
				for (var i = 0; i < updateLabels.length; i++) {
					var id = updateLabels[i][0];
					var label = updateLabels[i][1];
					
					// ユーザーテーブルを更新
					if (document.getElementById(id)) {
						document.getElementById(id).innerHTML = label;
					}
				}
			}

			com.nec.jp.ngsf.wiki.close_popup();
			popupWindow.close(0);
		});
		
		return false;
	}

	/*
	 * ファイル属性の説明を保存します。
	 */
	com.nec.jp.ngsf.wiki.saveAttributeDescription = function(path, contentType){
		var description = DWRUtil.getValue("gleanfeed-wiki-property-description");
		WikiEditPageController.saveContentAttributeDescription(path, description, contentType, com.nec.jp.ngsf.wiki.saveAttributeDescriptionCallback);			
	}
	
	com.nec.jp.ngsf.wiki.saveAttributeDescriptionCallback = function(){
		popupWindow.close(1);
	}

	// テンプレート引用時：作成するページの親ページ名
	var SDWikiQuoteTemplate_CreatePageParentName = "";
	// テンプレート引用時：作成するページ名
	var SDWikiQuoteTemplate_CreatePageName = "";

	/*
	 * テンプレート引用時：ファイル選択ダイアログを表示します。
	 * ファイル選択後、テンプレートを引用し展開するアクションに遷移します。
	 *
	 * @param categoryName テンプレート引用時：作成するページの親ページ名
	 * @param pageName テンプレート引用時：作成するページ名
	 */
	com.nec.jp.ngsf.wiki.SDWikiQuoteTemplateOpenDialog = function(categoryName, pageName) {
		SDWikiQuoteTemplate_CreatePageParentName = categoryName;
		SDWikiQuoteTemplate_CreatePageName = pageName;
		// テンプレート引用画面を閉じる
		popupWindow.close(0);

		// ファイル選択画面を閉じた後のcallback関数
		// 穴あきエディタに遷移します。
		var callback = function() {
			if ((com.nec.jp.ngsf.wiki.SDWikiFileSelect.selectedFileTitle != null) &&
				(com.nec.jp.ngsf.wiki.SDWikiFileSelect.selectedFileTitle) &&
				(com.nec.jp.ngsf.wiki.SDWikiFileSelect.selectedFileTitle.length > 0)){
				document.forms[0].action = "wiki.quote_template.form";
				com.nec.jp.ngsf.wiki.SDWikiQuoteTemplateAppendInput("gleanfeed-wiki-create-page-parent-name", SDWikiQuoteTemplate_CreatePageParentName);
				com.nec.jp.ngsf.wiki.SDWikiQuoteTemplateAppendInput("gleanfeed-wiki-create-page-name", SDWikiQuoteTemplate_CreatePageName);
				com.nec.jp.ngsf.wiki.SDWikiQuoteTemplateAppendInput("gleanfeed-wiki-quote-template-name", com.nec.jp.ngsf.wiki.SDWikiFileSelect.selectedFileTitle);
				document.forms[0].submit();
			}
			com.nec.jp.ngsf.wiki.close_popup(); // TODO;may be bug, should call here to close existing popup.
			return true;
		};

		// ファイル選択画面を表示
		com.nec.jp.ngsf.wiki.SDWikiFileSelect.open(categoryName, ['template'], callback);
	}

	/*
	 * formにinputタグを追加します。
	 *
	 * @param id inputタグのid属性に設定する値
	 * @param value inputタグのvalue属性に設定する値
	 */
	com.nec.jp.ngsf.wiki.SDWikiQuoteTemplateAppendInput = function(id, value) {
		var input = document.createElement("input");
		input.name = id;
		input.value = value;
		input.type = "hidden";

		var objForm = document.getElementsByTagName("form").item(0);   
		objForm.appendChild(input);
	}
