/*!
 * (C) Hitachi Government & Public Corporation System Engineering, Ltd. 2009. All rights reserved.
 */
/** 
 * @fileOverview Mymenuクラス
 * @author HGP R&D Center & Universal Communication Dev.
 * @version 1.0.0
 * 
 * @requires jquery-1.3.2.min.js<br>
 */

/**
 * 気に入ったページ（現在見ているページ）のタイトル/URLをCookieに保存していき、Cookie内容からリンク集を表示する(サイト内ブックマーク）機能<br>
 * @requires jquery.json-2.2.min.js<br>
 * @requires jquery.cookies.2.1.0.js<br>
 * @requires jquery.browser.min.js<br>
 * @requires jquery.ba-urlinternal.min.js<br>
 * @requires jquery.tempest-0.2.min.js<br>
 * @requires jquery.jquery-impromptu.2.7.min.js<br>
 * 
 * @class jQuery.Mymenu。<br>
 */
(function($) {
	$.extend({
		myMenu : new function() {
			//************************  Member Objects  ************************// 
			/**
			 * 動作設定オブジェクト。(初期値)
			 * #同じプロパティをもつオブジェクトをinitialize()に引数として渡すとマージされる
			 */ 
			this.defaultconfig = {
				cookiename:"mymenu",						//Cookie名
				cookieActiveDays:365,						//Cookieの有効日数		
				canUserEditTitle:true,						//ユーザがブックマーク追加時にタイトルを編集できるか
				/**
				 * cookieが一杯になった場合の動作
				 * 'auto':古い物を自動的に削除して新しい物を追加する
				 * 'confirm':ダイアログを表示する
				 */
				fullCookieAction:'auto',
				
				listContainerId:'myMenuList',				//リスト表示領域のID
				maxListCount:5,								//リスト表示領域に表示するリストの最大数
				listPreTemplate:"<ul></ul>",				//リスト表示の親要素(listContainerIdの要素にlistPreTemplateが追加される）<ul><li>abc</li></ul>のような記述も可（この場合,liの後ろにlistTemplateの内容が追加される
				/**
				 * 各リストの表示テンプレート（listPreTemplateの子要素になる）。埋め込み内容は以下の通り
				 *  {{url}} :ブックマークのURL
				 *  {{title}} : ブックマークの保存時タイトル
				 *  {{count}} : 連番(1,2,・・・）
				 */
				listTemplate:"<li><a href='{{url}}'>{{title}}</a></li>",	
					
				listEditContainerID:'myMenuEditList',		//編集用リスト表示領域のID
				editAreaPreTemplate:"<table></table>",		//編集用リスト表示の親要素.<table><caption>abc</caption></table>のような記述も可（この場合,captionの後ろにeditlistTemplateの内容が追加される
				/**
				 * 各リストの表示テンプレート（listPreTemplateの子要素になる）。埋め込み内容はlistTemplateと同様。
				 *  ただし、編集用ボタン,削除用ボタンとなる要素には以下のIDを記述すること
				 *  編集用ボタン：{{myMenuEditTitle}}
				 *  削除用ボタン：{{myMenuEditDelete}}
				 */
				editlistTemplate:"<tr><td><a href='{{url}}'>{{title}}</a></td><td><a href='#' id='{{myMenuEditTitle}}'>編集</a></td><td><a href='#' id='{{myMenuEditDelete}}'>削除</a></td></tr>",

				errorMessageContainerId:'mymenu_errorArea',	//エラー（対象外ブラウザorCookie無効時）メッセージ表示領域
				addCurrentPageButtonId:'mymenu_addButton',	//現在のページをブックマークに追加するボタンのID
				/**
				 * 対象ブラウザ
				 * 対象とする各ブラウザのバージョンを記載。
				 * 対象としないブラウザは[]を設定。
				 * 注：jQueryの対象は IE6+,FF2+,Safari3+,Opera9+,Chrome なのでそれ以上のバージョンを設定する。
				 */
				targetBrowser : {	
					"msie": [6,7,8],
					"firefox": [3],
					"safari": [4],
					"opera": [9],		//Operaは10以降も9と判定されるのでOpera10であっても9を指定
					"chrome": [4]
				},
				/**
				 * メッセージ定義
				 */
				messages:{	
					wrong_browser	: "お使いのブラウザでは本機能はご利用になれません。",				//対象外ブラウザ時エラーメッセージ（HTMLタグ利用可能）
					cant_use_cookie	: "Cookieが無効になっているため、本機能はご利用になれません。",		//Cookie無効時時エラーメッセージ（HTMLタグ利用可能）
					nullTitle:"エラー：タイトルを空にすることは出来ません。",							//編集後タイトルが空の場合
					nullList:"",															//登録ブックマークが0件時のリスト表示領域内HTML（HTMLタグ利用可能）
					editTitlePromptDialogTitle : "<h3>お気に入り 登録タイトル編集</h3>",			//タイトル編集時ダイアログタイトル
					editTitlePromptText : "タイトルを入力してください。<br>",						//タイトル編集時プロンプトメッセージ
					promptOK:"OK",															//タイトル編集時プロンプトOKボタンラベル
					promptCancel:"キャンセル",													//タイトル編集時プロンプトキャンセルボタンラベル
					fullCookieErrorDialogTitle:'<h3>お気に入り 保存エラー</h3>',					//Cookie保存可能容量を超えた場合のエラーダイアログタイトル
					fullCookieErrorText:'保存可能な容量を超えたため、登録を中止しました。<br><a href="/myMenu/myMenuEdit.html">編集ページ</a>で不要な項目を削除してください。'				//Cookie保存可能容量を超えた場合のエラーメッセージ（fullCookieAction:'auto'の場合は未使用）
				},
				editPageURL:'myMenuEdit.html',												//編集ページのURL
				backgroundImagePath:'',	//ダイアログ表示の背景画像絶対パス（ZoomSight併用時は必ず半透明画像等を指定すること）
				/**
				 * ページタイトル編集関数(ユーザ編集の前に自動的に編集する)
				 * @param {String} ttl 編集前タイトル文字列
				 * @return {String} 編集後タイトル文字列
				 */ 
				editTitleFunction:function(titleStr){
					return titleStr;
				},			
				expertSetting:{
					isDebugMode : false,							//デバッグモードか
					/**
					 * タイトル編集プロンプトの中身のＨＴＭＬを作成する
					 * @param {String} title  タイトル初期値
					 * @param {Number} idx　編集しようとしているブックマークのインデックス（編集画面のみ。新規登録時は-1）
					 */
					editTitlePromptHTMLFunc: function(title, idx){
						var mesDef = $.myMenu.config.messages;
						return mesDef.editTitlePromptDialogTitle + '<div class="jqi_messagebody">'+mesDef.editTitlePromptText+'<div id="myMenuPromptError" style="display:none">' + mesDef.nullTitle + '</div><input type="text" style="width:auto" size="30" maxlength="30" id="myMenuTitlestr" name="titlestr" value="' + title + '" ><br><input type="hidden" id="myMenuIndex"  name="myMenuIndex" value="' + idx + '">'+'</div>';
					},
					/**
					 * クッキーが一杯で保存できなかった場合のプロンプトの中身のＨＴＭＬを作成する(config.fullCookieActionが'confirm'の場合に使用)
					 * @param {String} url 登録をキャンセルされたブックマークのURL
					 * @param {String} title 登録をキャンセルされたブックマークのタイトル
					 */
					fullCookieConfirmPromptHTMLFunc: function(url,title){
						return $.myMenu.config.messages.fullCookieErrorDialogTitle + '<div class="jqi_messagebody">'+$.myMenu.config.messages.fullCookieErrorText+'</div><input type="hidden" id="myMenuCancelURL"  name="myMenuCancelURL" value="' + url + '"><input type="hidden" id="myMenuCancelTitle"  name="myMenuCancelTitle" value="' + title + '">';
					},
					/**
					 * クッキーが一杯で保存できなかった場合のプロンプトのボタン
					 * 左側がラベル。右の'MOVE''AUTO''OK'は変更不可
					 */
					fullCookieConfirmPromptButton:{
						'編集ページに移動':'MOVE',
						'古い物を自動削除して登録':'AUTO',
						'OK':'OK'
					},
					/**
					 * クッキーが一杯で保存できなかった場合のプロンプトのデフォルトボタンのインデックス
					 */
					fullCookieConfirmPromptDefButtonIndex:2
				}
			};
			this.config = this.defaultconfig;
			
			/**
			 * 内部動作用定数オブジェクト
			 * @return {Object}
			 */
			this.defines = {
				/**
				 * エラー種別定数オブジェクト。<br>
				 * エラー時には本定数の中から種別を指定してerrorHandler()を呼んで処理させる
				 * @return {Object}
				 */
				errorType:{
					cantUse:"CANT_USE",	//利用不可
					alert:	"ALERT",	//警告(利用続行可能）
					debug:	"DEBUG"		//デバッグ用
				},
				maxCookieLength:2500
			};
			
			//************************  Low level functions  ************************// 
			//////////////// Error  ////////////////	
			/**
			 * 最終エラー内容保持メンバ(デバッグ用）
			 */
			this._lastError = {
				type:"",
				message:""
			};
			
			/**
			 * 最後に発生した内部エラーを取得する(デバッグ用）
			 * @return 
			 */
			this.getLastError = function(){
				return this._lastError;
			};
			
			/**
			 * 最終エラー内容をクリアする
			 */
			this.clearLastError = function(){
				this._lastError = {
					type:"",
					message:""
				};
			};
			
			/**
			 * エラー時動作関数。<br>
			 * typeがcantUseの時：エラーメッセージ表示領域にmessageを表示	<br>
			 * typeがalertの時：メッセージボックスでmessageを表示	<br>
			 * typeがdebugの時：config.expertSetting.isDebugModeがtrueの場合はメッセージボックスでmessageを表示。falseの場合は何もしない。	<br>
			 * 
			 * @param {String} type エラー種別
			 * @param {String} message エラーメッセージ
			 * 
			 * @see defines.errorType
			 */
			this.errorHandler = function(type , message){
				this._lastError.type=type;
				this._lastError.message=message;
				switch(type){
					case this.defines.errorType.cantUse:
						//エラーメッセージ表示領域にエラーメッセージを表示			
						$('#'+this.config.errorMessageContainerId).html(message);
						break;
					case this.defines.errorType.alert:
							alert(message);				
						break;	
					case this.defines.errorType.debug:	
						if(this.config.expertSetting.isDebugMode){
							alert(message);
						}
						break;
					default:
						break;	
				}
			};
			
			//////////////// BookMark Object  ////////////////	
			/**
			 * ブックマークオブジェクト
			 * @param {String} url
			 * @param {String} title
			 * @return {Object} obj BookMarkオブジェクト{u:{String} URL,t:{String}タイトル}
			 * 
			 * @example 
			 * new $.myMenu.bookMarkObj("http://hoge/hoge.html","hogehoge");
			 * => {u:"http://hoge/hoge.html" , t:"hogehoge"}
			 */		
			this.bookMarkObj = function(url,title){
				if (url === undefined || url === null) {
					url = "";
				}
				if (title === undefined || title === null) {
					title = "";
				}
				return {u:url,t:title};
			};
			
			/**
			 * セキュアなURL文字列に変更する<br>
			 * ・本スクリプト稼働ページと同一ドメイン＆＆ナビゲーションURLではない（javascript:等）の場合は空文字<br>
			 * ・'<>&"'が含まれる場合は参照文字に変更した文字列<br>
			 * を返す<br>
			 * @param {String} url
			 * @return {String}
			 */
			this.getSecureURL = function(url){
				if (!$.isUrlInternal(url) ) { 
					if ($.isUrlFragment(url)) {  //フラグメント(#・・・)
						var tempurl = url.substr(0,url.indexOf("#"));
						if (!$.isUrlInternal(tempurl)) {
							return "";
						}					
					}
					else {	//違うドメイン OR 不正リンク（"javascript:・・・","mailto:・・・"など）
						return "";
					}
				}
				// URLが＃で終わっていたら除去する（IEでリンククリック時にエラーになる場合があるため）
				if(url.lastIndexOf("#")==url.length-1){
					return url.substr(0,url.length-1);
				}
				return url.replace(/&/g, "&amp;").replace(/"/g, "&quot;").replace(/</g, "&lt;").replace(/>/g, "&gt;");
			};
			
			/**
			 * セキュアなタイトル文字列に変更する<br>
			 * ・'<>&"'が含まれる場合は参照文字に変更した文字列<br>
			 * を返す<br>
			 * @param {String} title
			 * @return {String}
			 */
			this.getSecureTitle = function(title){
				// HTMLEscape
				return title.replace(/&/g, "&amp;").replace(/"/g, "&quot;").replace(/</g, "&lt;").replace(/>/g, "&gt;");
			};
			
			//////////////// BookMark Collection  ////////////////
			/**
			 * ブックマークコレクション
			 * @return {Array}
			 */
			this._bookmarks= [];
			
			/**
			 * ブックマークコレクションを空にする
			 */
			this.clearBookMarks = function(){
				this._bookmarks= [];
			};
			
			/**
			 * ブックマークをブックマークコレクションの先頭に追加する。
			 * @param {String} url
			 * @param {String} title
			 * @return {Array of bookMarkObj} 追加後のブックマークコレクション
			 */
			this.addBookMark = function(url,title){
				if(url === undefined || url===null || url=="" || title === undefined || title===null || title=="" ){
					var mess = "Failed to addBookMark:Invalid arguments";
					this.errorHandler($.myMenu.defines.errorType.debug,mess);
					throw mess;
				}
				this._bookmarks.unshift(new this.bookMarkObj(url,title));	//先頭に追加
				return this._bookmarks;
			};
			
			/**
			 * ブックマークコレクションの末尾の要素を削除する
			 * @param {String} url
			 * @param {String} title
			 * @return {Array of bookMarkObj} 削除後のブックマークコレクション
			 */
			this.deleteOldestBookmark = function(){
				this._bookmarks.pop();	//末尾を削除
				return this._bookmarks;
			};
			
			/**
			 * 指定したインデックスのブックマークを削除する
			 * @param {Object} index
			 * @return {Array of bookMarkObj} 削除後のブックマークコレクション
			 */
			this.deleteBookmarkByIndex = function(index){
				var bmc = this.getBookmarksCollection(),mess = "Failed to deleteBookmarkByIndex:Invalid arguments";
				
				if(index<0 || index>bmc.length-1){
					this.errorHandler($.myMenu.defines.errorType.debug,mess);
					throw mess;
				}
				
				bmc[index].u = '';
				bmc=$.grep(bmc, function (bm) { return bm.u != ''; });
				this._bookmarks = bmc;
				return this._bookmarks;
			};
			
			/**
			 * ブックマークコレクションの内容を引数で与えられた物に変更する
			 * @param {Array of bookMarkObj} bookmarks
			 */
			this.setBookmarksCollection = function(bookmarks){
				/* 性能確保のため入力チェック無し
				try{
					//形式チェック
					for(var i=0;i<bookmarks.length;i++){
						var url = bookmarks[i].u;
						var title = bookmarks[i].t;
					}
				}catch(e){
					this.errorHandler($.myMenu.defines.errorType.debug,e.toString());
					throw e;
				}*/
				this._bookmarks = bookmarks;
			};
			
			/**
			 * ブックマークコレクションを取得する
			 * @return {Array of bookMarkObj} 
			 */
			this.getBookmarksCollection = function(){
				return this._bookmarks;
			};
			
			/**
			 * ブックマークコレクションのJSONを取得する
			 */
			this.getBookmarksCollectionJSON = function(){
				return $.toJSON(this._bookmarks);
			};
			
			/**
			 * 指定されたURLと同じURLをもつブックマークオブジェクトがブックマークコレクションに含まれている場合はそのindexを返す。
			 * 該当する物がない場合は-1を返す。
			 * @param {String} url
			 * @return {Number} 
			 */ 
			this.getRegisteredBookMarkIndex=function(url){
				var bms=this.getBookmarksCollection();
				for(var i=0;i<bms.length;i++){
					if (url == bms[i].u) {
						return i;
					}
				}
				return -1;
			};
			
			/**
			 * Cookie保存可能容量(this.defines.maxCookieLength)を超えないように古いブックマークを削除する
			 */
			this.deleteOldBookmarksToCookieSize=function(){
				while (escape(this.getBookmarksCollectionJSON()).length > this.defines.maxCookieLength) {
					this.deleteOldestBookmark();
				}
			};
					
			//////////////// Platform  ////////////////			
			/**
			 * 利用できる環境かどうかを調べる。<br>
			 * ・対象ブラウザ（config.targetBrowserに定義）か？<br>
			 * ・Cookieが利用可能か？<br>
			 */
			this.checkPlatform = function(){
				//対象ブラウザ（this.targetBrowserに定義）か？
				var allowingVersion = this.config.targetBrowser[$.browser.name];
				if (allowingVersion === undefined){	//ブラウザ名が未知の場合、対象外エラー
					return this.config.messages.wrong_browser; 
				}
				if($.inArray((Number($.browser.versionX)).valueOf(),allowingVersion) < 0){	//ブラウザバージョンが対象外の場合エラー
					return this.config.messages.wrong_browser;
				}
				//Cookieが利用可能か？
				if($.cookies.test() === false){	//Cookieが利用できない場合はエラー			
					return this.config.messages.cant_use_cookie;
				}
				return 'OK';
			};
			
			/**
			 * 現在のドキュメントのタイトルを取得する
			 * @return {String}
			 */
			this.getTitle=function(){	
				return this.config.editTitleFunction(document.title);			
			};
			
			//////////////// Cookie /////////////////////
			/**
			 * Cookieを消去する
			 */
			this.clearCookie = function(){
				$.cookies.del(this.config.cookiename);
			};
			
			/**
			 * Cookieにbookmarksの内容を保存する
			 */
			this.save = function(){
				$.cookies.set(this.config.cookiename,escape(this.getBookmarksCollectionJSON()));
			};
			
			/**
			 * Cookieからbookmarksの内容をロードする
			 */
			this.load = function(){		
				var cookiedata=$.cookies.get(this.config.cookiename),bookmarksObj = [];
				if (cookiedata === null) {
					this.errorHandler(this.defines.errorType.debug,"Failed to load :cookie is null");
					return;
				}
				try {
					bookmarksObj = $.secureEvalJSON(unescape(cookiedata));
					if(bookmarksObj===null)
					{
						throw "bookmarksObj is null";
					}
					
					//入力チェック 
					$.each(bookmarksObj,function(i,val){
						var u = $.myMenu.getSecureURL(val.u);
						if(u=='') val.u='';
						var t = $.myMenu.getSecureTitle(val.t);
						if(t=='') val.t='';
					});		
					
					if(bookmarksObj.length >0){
						//urlまたはtitleが空の場合は消去して設定
						this.clearBookMarks();
						$.each(bookmarksObj,function(i,val){
							if(val.u != '' && val.t!=''){
								$.myMenu._bookmarks.push(new $.myMenu.bookMarkObj(val.u,val.t));	
							}
						});
					}
				
				}catch(e){  //unsecure or null 
					this.errorHandler(this.defines.errorType.debug,e.toString());
					return;
				}	
						
			};
			
			//************************  Middle level functions  ************************// 
			
			//////////////// addbookmark /////////////////////	
			/**
			 *  ブックマークをブックマークコレクションの先頭に追加し、Cookieに保存する。<br>
			 *  既に同じURLで登録されている場合は、登録済みのブックマークを一端削除し、指定したtitleで先頭に追加し直す<br>
			 *  URLがセキュアでない場合は例外が発生し、ブックマークコレクションの変更は行われない。<br>
			 *  また、Cookie保存可能容量(this.defines.maxCookieLength)を超えた場合、以下のように振る舞う<br>
			 *  mode=='auto':  保存可能である（Cookie保存可能容量(this.defines.maxCookieLength)を超えていない）状態となるように古いブックマークを削除する<br>
			 *  mode!='auto': 登録を取り消す。<br>
			
			 *  
			 * @param {String} url
			 * @param {String} title
			 * @param {String} mode 
			 * @return {Array of bookMarkObj} 追加後のブックマークコレクション
			 * @exception {String} 'unsecure　url'
			 */
			this.addBookmarkEx=function(url,title,mode){
				if(mode === undefined){
					mode = this.config.fullCookieAction;
				}
				if(this.getSecureURL(url)==''){
					this.errorHandler(this.defines.errorType.debug,"Failed to addBookmarkEx :unsecure　url");
					throw 'unsecure　url';
				}
				
				var idx,bmc;
				//既に同じURLのブックマークがある場合は一端削除
				idx = this.getRegisteredBookMarkIndex(url);
				if ( idx >= 0) {
					this.deleteBookmarkByIndex(idx);
				}	
				
				this.addBookMark(url,title);

				//Cookie保存可能容量(this.defines.maxCookieLength)を超えていないかチェック
				if (escape(this.getBookmarksCollectionJSON()).length > this.defines.maxCookieLength) {
					//定義により挙動を変える
					switch(mode){
						//Cookie保存可能容量(this.defines.maxCookieLength)を超えないように古いブックマークを削除	
						case 'auto':
							this.deleteOldBookmarksToCookieSize();
							break;
						//エラーとして登録をとりやめる	
						default:
							this.errorHandler(this.defines.errorType.debug,this.config.messages.fullCookieError);
							//登録を取り消す
							bmc=this.getBookmarksCollection();
							bmc.shift();
							this.setBookmarksCollection(bmc);
							this.deleteOldBookmarksToCookieSize();	
					}
				}
				this.save();
				return this.getBookmarksCollection();
			};
			
			//////////////// create display /////////////////////	
			/**
			 * リスト表示用HTMLを取得する
			 * @return {String} リスト表示用HTML文字列
			 */
			this.getBookmarkListHTML = function(template,isHaveMax) {
				var bc=this.getBookmarksCollection(),data = [],listcount;
				if (bc === null) {
					return this.config.messages.nullList;
				}
				if (bc.length > 0) {
					//var strTmpl = '<div>' + template + '</div>';
					listcount = bc.length;
					if(isHaveMax === undefined || isHaveMax===true){
						listcount = (this.config.maxListCount > bc.length) ? bc.length : this.config.maxListCount;
					}
					for (var i = 0; i < listcount; i++) {
						data.push({
							count: i + 1,
							url: this.getSecureURL(bc[i].u),
							title: this.getSecureTitle(bc[i].t),
							myMenuEditTitle:'myMenuEditTitle_'+i,
							myMenuEditDelete:'myMenuEditDelete_'+i
						});
					}
					return $.tempest(template, data);
				}else{
					return this.config.messages.nullList;
				}
			};
			
			/**
			 * リストを描画する。
			 */
			this.updateList=function(){
				var listHTMLInnerObj,editHTMLInnerObj,listHTML,editHTML;
				listHTMLInnerObj = this.getBookmarkListHTML(this.config.listTemplate);
				
				editHTMLInnerObj = this.getBookmarkListHTML(this.config.editlistTemplate,false);
				if(this.getBookmarksCollection().length>0){		
					listHTML = $(this.config.listPreTemplate);
					listHTML.append(listHTMLInnerObj);
					$("#"+this.config.listContainerId).html(listHTML);
					//edit
					editHTML=$(this.config.editAreaPreTemplate);
					editHTML.append(editHTMLInnerObj);
					$("#"+this.config.listEditContainerID).html(editHTML);
				}else{
					$("#"+this.config.listContainerId).html(listHTMLInnerObj);
					$("#"+this.config.listEditContainerID).html(editHTMLInnerObj);
				}
				this.addListsEventHandler();		
			};
			
			this.addListsEventHandler = function(){
				for(var i=0;i<this.getBookmarksCollection().length;i++){
					$("#myMenuEditTitle_"+i).click(function(){
						var idStr=$(this).attr('id');
						var idx=idStr.substr(idStr.lastIndexOf('_')+1);
						$.myMenu.editTitle(idx);
					});
					$("#myMenuEditDelete_"+i).click(function(){
						var idStr=$(this).attr('id');
						var idx=idStr.substr(idStr.lastIndexOf('_')+1);
						$.myMenu.editDelete(idx);
					});
				}
			};
			
			
			
			//************************  High level functions  ************************//
			//////////////// edit lists /////////////////////	
			this.__callbackFunc=null;	//コールバック関数退避用
			
			/**
			 * 現在のページ情報をbookmarksに追加する(エントリポイント)
			 * config.addCurrentPageButtonIdで指定した要素,編集画面の編集要素（myMenuEditTitle_*のＩＤ）をクリックした場合に実行される
			 */
			this.addCurrentPage=function(){
				//タイトル編集
				var title = this.getTitle();
				if (this.config.canUserEditTitle) {
					this.promptEditTitleFunction(title,this._addCurrentPage_callbank,-1);
				}
				else{
					this._addCurrentPage_callbank(title);
				}
			};
			
			/**
			 * 現在のページ情報をbookmarksに追加する(コールバック：タイトル編集後に呼ばれる)
			 * @param {String} title
			 */	
			this._addCurrentPage_callbank = function(title){
				var url = location.href;
				if(title==""){
					this.errorHandler($.myMenu.defines.errorType.alert,$.myMenu.config.messages.nullTitle);
					return;
				}
				try {
					$.myMenu.addBookmarkEx(url,title)//$.myMenu.getSecureTitle(title));
					//fullCookieActionが'confirm'の場合で、Cookiegaが一杯で登録に失敗した場合はダイアログ表示
					if(this.config.fullCookieAction == 'confirm'){
						if ($.myMenu.getLastError().message == $.myMenu.config.messages.fullCookieError) {
							this.__callbackFunc = this.confirmPromtCallBack;
							$.prompt(this.config.expertSetting.fullCookieConfirmPromptHTMLFunc(url, title), {
								buttons: $.myMenu.config.expertSetting.fullCookieConfirmPromptButton,
								focus: $.myMenu.config.expertSetting.fullCookieConfirmPromptDefButtonIndex,
								callback: $.myMenu.__callbackFunc,
								isPrependTo :false,
								isShowCloseBtn :false,
								backgroundImagePath:$.myMenu.config.backgroundImagePath
							});
							if($.browser.name == 'msie'){	//for stop ZoomSight voice reading
								$('body').trigger('contextmenu');
							}
						}else{
							$.myMenu.updateList();
						}
					}else{
						$.myMenu.updateList();
					}
					
				}catch(e){
					$.myMenu.errorHandler($.myMenu.defines.errorType.debug,e.toString());
				}
			};
			
			/**
			 * fullCookieActionが'confirm'の場合で、Cookiegaが一杯で登録に失敗した場合のダイアログのコールバック
			 * @see jQuery impromptu Plugin
			 * @param {Object} v
			 * @param {Object} m
			 * @param {Object} f
			 */
			this.confirmPromtCallBack = function(v,m,f){
				switch (v) {
					//説明ページに移動
					case 'MOVE':
						location.href = $.myMenu.config.editPageURL;
						return;
					//自動で削除	
					case 'AUTO':
						$.myMenu.addBookmarkEx(f.myMenuCancelURL,f.myMenuCancelTitle,'auto');	//同じURL,TitleでaddBookmarkExを自動削除モードで実行
						$.myMenu.updateList();
						break;	
				}
			}
			
			/**
			 * プロンプトに表示するボタンオブジェクト
			 */
			this.__bts = {};
			
			/**
			 * ページタイトル編集プロンプト関数(ユーザにタイトルを編集させる)
			 * @param {String} ttl 編集前タイトル文字列
			 * @return {String} 編集後タイトル文字列
			 */ 
			this.promptEditTitleFunction=function(titleStr,callback,idx){
				var mesDef = this.config.messages;
				this.__callbackFunc=callback;
				//ボタンオブジェクト作成
				eval("this.__bts={'"+mesDef.promptOK+"':'OK','"+mesDef.promptCancel+"':'CANCEL'}");
				
				$.prompt(this.config.expertSetting.editTitlePromptHTMLFunc(titleStr,idx),{
						submit: function(v,m,f){
							an = m.children('#titlestr');
							if(f.titlestr == "" && v=='OK'){	//未入力を禁止する
								an.css("border","solid #ff0000 1px");
								$('#myMenuPromptError').show();
								return false;
							}
							$('#myMenuTitlestr').focus();
							return true;
						},
						callback: function(v,m,f){
							if (v == 'OK') {
								$.myMenu.__callbackFunc(f.titlestr,f.myMenuIndex);
							}
						},
						buttons:this.__bts,
						isPrependTo :false,
						isShowCloseBtn :false,
						backgroundImagePath:$.myMenu.config.backgroundImagePath
						
				});
				if($.browser.name == 'msie'){	//for stop ZoomSight voice reading
					$('body').trigger('contextmenu');
				}
			};
			
			/**
			 * 指定した番号のブックマークのタイトルを編集する（エントリポイント）
			 * @param {Number} index
			 */
			this.editTitle=function(index){
				this.promptEditTitleFunction($.myMenu.getBookmarksCollection()[index].t,this._editTitle_callbank,index);
			};
			
			/**
			 * 指定した番号のブックマークのタイトルを編集する(コールバック：タイトル編集後に呼ばれる)
			 * @param {String} title
			 * @param {Number} idx
			 */
			this._editTitle_callbank = function(title,idx){
				if(title==""){
					this.errorHandler($.myMenu.defines.errorType.alert,$.myMenu.config.messages.nullTitle);
					return;
				}
				try {
					var bmc = $.myMenu.getBookmarksCollection();
					bmc[idx].t = title;
					$.myMenu.setBookmarksCollection(bmc);
					this.updateList();
					this.save();
				}catch(e){
					$.myMenu.errorHandler($.myMenu.defines.errorType.debug,e.toString());
				}
			};
			
			/**
			 * 指定した番号のブックマークのタイトルを削除する
			 * @param {Object} index
			 */
			this.editDelete=function(index){
				this.deleteBookmarkByIndex(index);
				this.updateList();
				this.save();		
			};
			
			//////////////// Initialize and run /////////////////////	
			/**
			 * 初期化処理
			 * @param {Object} configObj
			 */
			this.initialize=function(configObj){
				if(configObj == null || configObj == undefined )configObj={}
				//config設定（引数のObjectと初期値オブジェクトをマージ）
				try {
					this.config = $.extend({}, this.defaultconfig, configObj);
				
					this.config.messages = $.extend({}, this.defaultconfig.messages, configObj.messages);
					this.config.expertSetting = $.extend({}, this.defaultconfig.expertSetting, configObj.expertSetting);
				}catch(e){}
				
				//環境確認
				var resultMsg=this.checkPlatform();
				if(resultMsg=='OK'){//環境OK
					//Cookie設定
					$.cookies.setOptions({
						hoursToLive: 24*this.config.cookieActiveDays		//Cookie有効期限
					});

					//イベントハンドラ―追加  
					$("#"+this.config.addCurrentPageButtonId).click(function(){
						$.myMenu.addCurrentPage();
					});
						
					//Cookieからロード
					this.load();
					//リストを表示
					this.updateList();		
				}else{//前提環境外		
					this.errorHandler(this.defines.errorType.cantUse,resultMsg);
				}
			};
		}
	});
})(jQuery);
