/*/////////////////////////////////////////////////////////////////////////////////////////////////
	KONICA MINOLTA User's Guide
		Search Rresults JavaScript
 Modified : 2017-03-16
/////////////////////////////////////////////////////////////////////////////////////////////////*/


/* global books, decodeURIComponent, search_index, keyword_data, textData, _ua, search_setting */


var search = (function(){
	
	/*************************************
	 * 設定
	 */
	var loadIniFile = true;//ini.jsを読み込む
	
	var setting = {
		// 1ページあたりの結果数
		"itemByPage":            10
		
		// ヒットキーワードの前何文字表示
		,"clampFrontPoint":      30
		
		//１項目の説明全体の表示文字数
		,"clampDescLength":      115
		
		// (and|or)// 検索タイプ
		,"searchType":           'and'
		
		// 大文字小文字の区別
		,"charUpLo":             false
		
		// 大文字小文字の区別のチェックボックス要素
		,"charUpLo_elm":         "#charUpLo"
		
		// 全角半角の区別
		,"zenHan":               false
		
		// 全角半角の区別のチェックボックス要素
		,"zenHan_elm":           "#zenHan"
		
		//カウント表示要素
		,"count_elm":            "#searchResult > .sCount"
		
		//結果表示要素
		,"results_elm":          "#searchResult > .results"
		
		//ページネーション表示要素
		,"navi_elm":             "#searchResult > .navi"
		
		// 絞り込み「タイトルのみ」の要素
		,"filterTitle_elm":      "#filter_title"
		
		//絞り込みブック表示要素
		,"filter_elm":           "#searchCt"
		
		// 「タイトルのみ」と絞り込みブックの表示要素
		,"searchFilterItem_elm": "#searchFilterItem"
		
		// ユーザーフォントパターン
		,"ufPattern":            /%#symbol-([^#]+?)#%/
		
		//ハイライトタグにつけるクラス
		,"highlightClass":       "hitkey"
		
		//スコア
		,"score": {
			//タイトルにヒット
			"title":             10000
			
			//タイトルの何文字目かで減点する。１文字あたりの減点
			,"title_indexPoint": -1
			
			//説明にヒット
			,"text":             1000
			
			//説明の何文字目かで減点する。１文字あたりの減点
			,"text_indexPoint":  -1
			
			//減点の最大値
			,"dePointMax":       -1000
			
			//カテゴリー加算点数
			,"add_point":        1000
			
			//加算カテゴリー（ブック識別子）
			,"add_pointCT":      ["id15","id16"]
		}
	};
	//*************************************
	
	/*
	 * 設定（システム用）
	 */
	
	var conf = {
		// 区切りに使う文字候補
		"splitStrBase": '㌀|㌞|㍇|㍧|㍨|㍩|㍪|㍫|㍬|㍭|㍮|㍯|㍰'
		
		// ブックの変数名
		,"books_name": "books"
		
		// ブックの変数初期化
		,"books": []
		
		// インデックスの変数名
		,"index_name": "search_index"
		
		// インデックスの変数初期化
		,"index": {}
		
		// 関連ワードの変数
		,"keywordData": keyword_data
		
		// 検索動作開始を記録
		,"runStart": new Date().getTime()
		
		// URIパス
		,"thisFullPath": (window.location.origin + window.location.pathname).replace(/\\/g, "/")
		
		//WebStorage判定の箱
		,"isWebStorage": false
		
		// デバッグ用
		,"debug": {
			// 経過時間表示 [true: 表示 | false: 非表示 ]
			"runtime": true
			// スコアの表示：[ true: 表示 | true以外の真値("hide", 1): 非表示 | 偽値(false, null)など: タグ構造を作成しない ]
			,"scoreDisplay": 1
		}
	};
	
	// sessionStorageが使えるか判定
	try{
		conf.isWebStorage = ('sessionStorage' in window) && (window.sessionStorage !== undefined) && (window.sessionStorage !== null);
	}catch(e){
		conf.isWebStorage = false;
	}
	
	//SHAキー作成
	conf.shaKey = (function(){
		try{
			var shaObj = new jsSHA("SHA-1", "TEXT");
			shaObj.update(conf.thisFullPath + window.name);
			return shaObj.getHash("HEX");
		}catch(e){
			return false;
		}
	}());
	
	
	
	// 検索結果の保存オブジェクト
	var results = {};
	
	
	/*
	 * 関数群
	 */
	var func = {
		
		/*
		 * 初期設定
		 */
		"_init": function(){
			
			var setting2 = {};
			if(loadIniFile){
				try{
					if(search_setting)  setting2 = search_setting;
				}catch(e){}
			}
			
			$.extend(conf, setting, setting2, {
				"$count": $(setting.count_elm)
				,"$results": $(setting.results_elm)
				,"$navi": $(setting.navi_elm)
				,"$searchFilterItem": $(setting.searchFilterItem_elm)
				,"$filterTitle": $(setting.filterTitle_elm)
				,"$filter": $(setting.filter_elm)
				,"$charUpLo": $(setting.charUpLo_elm)
				,"$zenHan": $(setting.zenHan_elm)
				,"sData": getData
			});
			conf.sData.p = conf.sData.p || 1;
			conf.sData.pc = conf.sData.pc || 1;
			conf.andSearch = (conf.searchType == "and")? true : false;
			
			//文字参照を実態へ
			$.each(conf.index, function(key, val){
				val.title = func._repEntity(val.title, "rev");
				val.text = func._repEntity(val.text, "rev");
			});
			
			//絞り込みリスト作成
			func._setFilterHtml();
			//イベントセット
			func._setEvent();
			
			if(conf.sData.k){
				results.inputWord = conf.sData.k;
				results.keywords = func._getKeywordArr(results.inputWord);
				results.keywordsLength = results.keywords.length;
				results.filters = (conf.sData.f) ? conf.sData.f.split(',') : [];
				results.filtersTitle = (/^1$/i.test(conf.sData.t)) ? true : false;
				results.filtersCharUpLo = conf.charUpLo;
				results.filtersZenHan = conf.zenHan;
				results.viewPage = conf.sData.p;
				results.viewPageCheck = conf.sData.pc;
				results.resultsIndex = {};
				
				$("#searchKey").val(results.inputWord);
				
				results.visitedCheck = {"check":[]};
				if(conf.isWebStorage){
					func._visited('research');
				}
			}else{
				conf.$results.html('<div class="item"><h3>' + textData.searchNotFound + '</h3></div>');
			}
			
		}
		
		
		/*
		 * GETデータ取得
		 */
		,"_getGetData": function(){
			var get = {};
			var data = window.location.search.replace(/^\?/,'').split('&');
			for(var i in data){
				temp = decodeURIComponent(data[i]).split('=');
				ak = temp[0];
				temp.shift();
				get[ak] = temp.join('=');
			}
			return get;
		}
		
		
		/*
		 * 絞り込み項目をセット
		 */
		,"_setFilterHtml": function(){
			
			//絞り込み項目生成
			var chapFilter = [];
			$.each(conf.books, function(i,v){
				chapFilter.push('<div><label>'
						+ '<input type="checkbox" id="filter_' + v.book_key + '" value="' + v.book_key + '">'
						+ '<span>' + v.bookname + '</span>'
						+ '</label></div>');
			});
			conf.$filter.html(chapFilter.join(''));
			
			//タイトルのみのチェック付加
			if(conf.sData.t && /^(1|true)$/i.test(conf.sData.t.toString())){
				conf.$filterTitle.prop('checked', true);
			}
			
			//絞り込みのチェック付加
			if(conf.sData.f){
				$.each(conf.sData.f.split(','), function(i,v){
					$('#filter_' + v).prop('checked', true);
				});
			}
			
			//大文字小文字のチェック付加
			if(conf.sData.ul && /(1|true)/i.test(conf.sData.ul.toString())){
				conf.charUpLo =  true;
				conf.$charUpLo.prop('checked', true);
			}
			
			//全角半角のチェック付加
			if(conf.sData.zh && /(1|true)/i.test(conf.sData.zh.toString())){
				conf.zenHan = true;
				conf.$zenHan.prop('checked', true);
			}
		}
		
		
		/*
		 * イベントをセット
		 */
		,"_setEvent": function(){
			//絞り込み全解除
			$('#contents').on('click', '.allDeselect', function(e){
				conf.$searchFilterItem.find(':checkbox').prop('checked', false);
				$('#search form').submit();
			});
			
			//ページネーション
			conf.$navi.on('click', 'span:not(.selected)', function(e){
				if(results.visitedCheck.filter){
					conf.sData.pc = $(this).attr('page');
				}else{
					conf.sData.p = $(this).attr('page');
				}
				func._jampPage();
			});
			
			//検索オプション、絞り込みの状態が変わったときにsubmit
			$('#search .searchOption' +','+ conf.searchFilterItem_elm).on('change', ':checkbox, :radio', function(){
				$('#search form').submit();
			});
			
			//既読/未読チェックのコントロールイベント
			$('#searchResult').on('click', '.visitedCtrl button', function(e){
				var clickBtn = $(e.target);
				if(clickBtn.is('.viewCheck')){
					func._visited('view');
				}else if(clickBtn.is('.reset')){
					func._visited('reset');
				}
			});
			$('#searchResult').on('change', '.results input[type="checkbox"]', function(e){
				func._visited('checkbox', e.target.value, e.target.checked);
			});
		}
		
		
		/*
		* 配列の重複削除
		*/
		,"_uniqueArray": function(array){
			var storage = {};
			var uniqueArray = [];
			var i,value;
			for ( i=0; i<array.length; i++){
				value = array[i];
				if (!(value in storage)){
					storage[value] = true;
					uniqueArray.push(value);
				}
			}
			return uniqueArray;
		}
		
		
		/*
		 * 
		 */
		,"_addComma": function(num){
			var parts = num.toString().split('.');
			parts[0] = parts[0].replace(/(\d)(?=(\d\d\d)+(?!\d))/g, '$1,');
			return parts.join('.');
		}
		
		/*
		 * セパレータ文字取得
		 */
		,"_sepStr": function(text){
			var temp = text.match(new RegExp('('+ conf.splitStrBase + ')', "g"));
			if(temp){
				temp = new RegExp('(' + temp.join('|') + ')', "g");
				return conf.splitStrBase.replace(/\|/, '').replace(temp, '').split('|');
			}else{
				return conf.splitStrBase.split('|');
			}
		}
		
		
		/*
		 * 入力キーワードを配列に分離。
		 */
		,"_getKeywordArr": function(inputWord){
			var sep = func._sepStr(inputWord);
			var arr = [];
			var phraseArr = [];
			var temp = inputWord;
			
			temp = temp.replace(/"([^"]+)"/g, function(a,$1){
				phraseArr.push($1);
				return sep[0];
			});
			
			arr = temp.split(/[\s　]+/);
			
			$.each(arr, function(i,val){
				if(val == void(0)) arr.splice(i,1);
				if(val == sep[0]) {
					arr[i] = phraseArr.shift();
				}
			});
			
			return arr;
		}
		
		
		/*
		 * 正規表現エスケープ処理
		 */
		,"_escapeRegex": function(s){
			return s.replace(/[\[\]{}()*+?\\^$|#;\.]/g, "\\$&");
		}
		
		
		/*
		* カタカナ表現生成 ガ=> (ガ|ｶﾞ)、
		*/
		,"_katakanaRegExp": function(str){
			
			//
			var zenHanReg = [
				"(ガ|ｶﾞ)","(ギ|ｷﾞ)","(グ|ｸﾞ)","(ゲ|ｹﾞ)","(ゴ|ｺﾞ)","(ザ|ｻﾞ)","(ジ|ｼﾞ)","(ズ|ｽﾞ)","(ゼ|ｾﾞ)","(ゾ|ｿﾞ)",
				"(ダ|ﾀﾞ)","(ヂ|ﾁﾞ)","(ヅ|ﾂﾞ)","(デ|ﾃﾞ)","(ド|ﾄﾞ)","(バ|ﾊﾞ)","(パ|ﾊﾟ)","(ビ|ﾋﾞ)","(ピ|ﾋﾟ)","(ブ|ﾌﾞ)",
				"(プ|ﾌﾟ)","(ベ|ﾍﾞ)","(ペ|ﾍﾟ)","(ボ|ﾎﾞ)","(ポ|ﾎﾟ)","(ヴ|ｳﾞ)","(ァ|ｧ)","(ア|ｱ)","(ィ|ｨ)","(イ|ｲ)","(ゥ|ｩ)",
				"(ウ|ｳ)","(ェ|ｪ)","(エ|ｴ)","(ォ|ｫ)","(オ|ｵ)","(カ|ｶ)","(キ|ｷ)","(ク|ｸ)","(ケ|ｹ)","(コ|ｺ)","(サ|ｻ)",
				"(シ|ｼ)","(ス|ｽ)","(セ|ｾ)","(ソ|ｿ)","(タ|ﾀ)","(チ|ﾁ)","(ッ|ｯ)","(ツ|ﾂ)","(テ|ﾃ)","(ト|ﾄ)","(ナ|ﾅ)",
				"(ニ|ﾆ)","(ヌ|ﾇ)","(ネ|ﾈ)","(ノ|ﾉ)","(ハ|ﾊ)","(ヒ|ﾋ)","(フ|ﾌ)","(ヘ|ﾍ)","(ホ|ﾎ)","(マ|ﾏ)","(ミ|ﾐ)",
				"(ム|ﾑ)","(メ|ﾒ)","(モ|ﾓ)","(ャ|ｬ)","(ヤ|ﾔ)","(ュ|ｭ)","(ユ|ﾕ)","(ョ|ｮ)","(ヨ|ﾖ)","(ラ|ﾗ)","(リ|ﾘ)",
				"(ル|ﾙ)","(レ|ﾚ)","(ロ|ﾛ)","(ワ|ﾜ)","(ヲ|ｦ)","(ン|ﾝ)","(。|｡)","(「|｢)","(」|｣)","(、|､)","(・|･)",
				"(ー|ｰ)","(゛|ﾞ)","(゜|ﾟ)"
			];
			for(var i in zenHanReg){
				var re = new RegExp(zenHanReg[i], "g");
				str = str.replace(re, re.source);
			}
			
			return str;
		}
		
		
		/*
		 * 全角半角正規表現生成　＆　エスケープ　a => (a|ａ)、ＡＢ => (Ａ|A)(Ｂ|B)、［ => (［|\[)
		 */
		,"_zenHanRegExp": function(str){
			var re = /[\!-\~！-～￥　 ]/;
			if( re.test(str) ){
				str = str.split('');
				for(var i in str){
					str[i] = str[i].replace(re, function(s){
						if(/[！-～]/.test(s)){
							return '(' + s + '|' + func._escapeRegex(String.fromCharCode(s.charCodeAt(0) - 0xFEE0)) + ')';
						}else if(/[￥]/.test(s)){
							return '(' + s + '|' + func._escapeRegex(String.fromCharCode(0x005C)) + ')';
						}else if(/[\\]/.test(s)){
							return '(' + func._escapeRegex(s) + '|' + String.fromCharCode(0xFFE5) + ')';
						}else if(/[　 ]/.test(s)){
							return '(' + String.fromCharCode(0x0020) + '|' + String.fromCharCode(0x3000) + ')';
						}else{
							return '(' + func._escapeRegex(s) + '|' + String.fromCharCode(s.charCodeAt(0) + 0xFEE0) + ')';
						}
					});
				}
				str = str.join('');
			}else{
				str = func._escapeRegex(str);
			}
			//if(!r)
			str = func._katakanaRegExp(str);
			
			return str;
		}
		
		
		/*
		 * ユーザーフォント削除
		 */
		,"_ufrm": function(d){
			var re = new RegExp(conf.ufPattern.source, "g");
			return d.replace(re, '');
		}
		
		
		/*
		 * 文字参照に置換 逆の場合は第二引数に"rev"を入れる
		 */
		,"__entityChar": {
			"&": ["&amp;","&#38;"], //[&]を一番最初に処理しないと2重になる
			"<": ["&lt;","&#60;"], 
			">": ["&gt;","&#62;"], 
			'"': ["&quot;","&#34;"],
			"'": ["&apos;","&#39;"]
		}
		,"_repEntity": function(str, rev){
			var r = str;
			$.each(func.__entityChar, function(key, val){
				if(rev != "rev"){
					r = r.replace(new RegExp(key, "g"), val[0]);
				}else{
					r = r.replace(new RegExp('&((nb|en|em|thin)sp|#(160|8194|8195|8201));', "g"), " ");
					r = r.replace(new RegExp('(' + val.join('|') + ')', "g"), key);
				}
			});
			return r;
		}
		
		
		/*
		 * 検索実行
		 */
		,"_search": function(){
			var result = {};
			
			//検索用正規表現作成
			func._createfindreg();
			
			//対象インデックス作成
			var searchIndex = {};
			$.each(conf.index, function(key, indexItem){
				//スコア０点付加
				indexItem._score = indexItem._score || 0;
				//スコア詳細配列
				indexItem._scoreDetail = [];
				//全対象
				if(results.filters.length == 0){
					var temp = {};
					temp[key] = indexItem;
					$.extend(searchIndex, temp);
				}
				//絞り込みによる
				else if($.inArray(indexItem.book_key, results.filters) != -1){
					var temp = {};
					temp[key] = indexItem;
					$.extend(searchIndex, temp);
				}
			});
			
			var calcScore = function(hitType, loopIni, hitIndex, dScore, hit){
				var demeritPoints = hitPoint = point = 0;
				
				if(hit){
					var demeritPoints = Math.max(hitIndex * conf.score[hitType + "_indexPoint"], conf.score.dePointMax);
					var hitPoint = conf.score[hitType] * (results.keywordsLength - loopIni);
					point = hitPoint + demeritPoints;
				}
				dScore["_"+ hitType + "_1_HitPoint"] = hitPoint;
				dScore["_"+ hitType + "_2_DePoint"] = demeritPoints;
				dScore["_"+ hitType + "_3_Formula"] = hitPoint +' - '+ Math.abs(demeritPoints) +' = '+ point;
				
				point = Math.max(point, 0);
				
				dScore["_"+ hitType + "_4_Point"] = point;
				
				return point;
			};
			
			//検索
			$.each(results.regsFind, function(findregIni, findReg){//キーワードループ
				
				//and検索の第２検索語以降
				if(conf.andSearch && findregIni > 0){
					searchIndex = result;
					result = {};
				}
				//and検索の第１検索語、もしくはor検索
				else{
					result = results.resultsIndex;
				}
				
				$.each(searchIndex, function(key, indexItem){//対象インデックスループ
					var hit = false, score = 0;
					
					//スコア詳細オブジェクト設定
					var dScore = indexItem._scoreDetail[findregIni] = {};
					
					//タイトルサーチ
					var titleMatch = func._ufrm(indexItem.title).match(findReg);
					if(titleMatch){
						hit = true;
						score += calcScore("title", findregIni, titleMatch.index, dScore, true);
					}else{
						calcScore("title", findregIni, 0, dScore, false);
					}
					//「タイトルのみ」のチェックがない場合は本文をサーチ
					if(!results.filtersTitle){
						var textMatch = func._ufrm(indexItem.text).match(findReg);
						if(textMatch){
							hit = true;
							score += calcScore("text", findregIni, textMatch.index, dScore, true);
						}else{
							calcScore("text", findregIni, 0, dScore, false);
						}
					}
					//ヒット
					if(hit){
						//カテゴリー加算
						var addPoint = 0;
						if($.inArray(indexItem.book_key, conf.score.add_pointCT) > -1){
							addPoint = conf.score.add_point;
							score += addPoint;
						}
						dScore['_add_Point'] = addPoint;
						
						//スコア加算
						indexItem._score += score;
						dScore['Word'] = results.keywords[findregIni];
						dScore['Word_Total'] = score;
						
						//結果オブジェクトへマージ
						var temp = {};
						temp[key] = indexItem;
						$.extend(result, temp);
					}
				});
				results.resultsIndex = result;
				
			});
			
			results.resultsLength = Object.keys(results.resultsIndex).length;
		}
		
		
		/*
		 * 検索用正規表現作成
		 */
		,"_createfindreg": function(){
			var regsFind = [];
			var keys = results.keywords;
			var reFlag = (conf.charUpLo) ? "":'i';
			for(var i in keys){
				try{
					var temp = '';
					if(conf.zenHan){
						temp = func._escapeRegex(keys[i]);
					}else{
						temp = func._zenHanRegExp(keys[i]);
					}
					regsFind.push(new RegExp(temp, reFlag));
				}catch(e){}
			}
			//検索の正規表現配列をセット
			results.regsFind = regsFind;
		}
		
		/*
		 * 関連キーワード作成
		 */
		,"_createReleateArr": function(){
			var releatekey = [];
			
			var inputWord = $.trim(results.inputWord.replace(/[\s　]+/g," "));
			$.each(conf.keywordData, function(key,val){
				var re = new RegExp('(^| |")' + val.reg + '( |"|$)', "i");
				if(re.test(inputWord)){
					releatekey = releatekey.concat(val.values);
				}
			});
			
			results.releatekeywords = func._uniqueArray(releatekey);
		}
		
		
		/*
		 * ページネーション作成
		 */
		,"_pagination": function(){
			var resultIni = results.resultsLength;
			var p = results.viewPage;
			if(results.visitedCheck.filter){
				resultIni = results.visitedCheck.check.length;
				p = results.viewPageCheck;
			}
			var ct = Math.ceil(resultIni / conf.itemByPage);
			var buf = [];
			for(var i=1; i<=ct; i++){
				buf.push('<span page="' + i + '">' + i + '</span>');
			}
			conf.$navi.html(buf.join(""))
					.find("span").removeClass("selected").eq(p - 1).addClass("selected");
		}
		
		
		/*
		 * 結果項目の説明トリミング
		 */
		,"_clamping": function(item){
			var ufRe = new RegExp(conf.ufPattern.source, "g");
			var userFont = [];
			var clamp = {"front": 0, "rear": -1};
			var hitPoint = 0;
			item.clamp = {"front": false, "rear": false};
			
			//ユーザーフォントをセパレーター文字に置き換えておく。文字数計算のため１文字に置き換えておく。
			if(conf.ufPattern.test(item.text)){
				var sepStr = func._sepStr(item.text);
				item.text = item.text.replace(ufRe, function(s){
					userFont.push(s);
					return sepStr[0];
				});
			}
			
			var isMatch = null;
			$.each(results.regsFind, function(i,reg){
				isMatch = item.text.match(reg);
				if(isMatch){
					hitPoint = Math.max(clamp.front, isMatch.index);
					return false;
				}
			});

			clamp.front = Math.max(hitPoint - conf.clampFrontPoint, 0);
			clamp.front = Math.min(clamp.front, Math.max(item.text.length - conf.clampDescLength, 0));
			clamp.rear = clamp.front + conf.clampDescLength;
			
			item.clamp.front = clamp.front > 0;
			item.clamp.rear = clamp.rear < item.text.length;
			
			var clampStrings = {
				"before": item.text.substring(0, clamp.front)
				,"clamp": item.text.substring(clamp.front, clamp.rear)
				,"after": item.text.substring(clamp.rear)
			};
			
			if(userFont.length){
				var re = new RegExp(sepStr[0], "g");
				var ufNum = [];
				$.each(clampStrings, function(key, str){
					ufNum.push((str.match(re)||[]).length);
				});
				for(var i=ufNum[0],len=ufNum[0]+ufNum[1]; i<len; i++){
					clampStrings.clamp = clampStrings.clamp.replace(sepStr[0], userFont[i]);
				}
			}
			item.text = clampStrings.clamp;
			
			return item;
		}
		
		
		/*
		 * 結果項目のキーワードハイライト
		 */
		,"_highlight": function(str){
			var ufRe = new RegExp(conf.ufPattern.source, "g");
			var userFont = [];
			var markClass = '';
			
			//ユーザーフォントをセパレーター文字に置き換えておく。文字数計算のため１文字に置き換えておく。
			var sepStr = func._sepStr(str);
			if(conf.ufPattern.test(str)){
				str = str.replace(ufRe, function(s){
					userFont.push(s);
					return sepStr[0];
				});
			}
			
			var re = [];
			$.each(results.regsFind, function(i,reg){
				re.push(reg.source);
			});
			re = new RegExp("(" + re.join('|') + ")", (results.filtersCharUpLo)?"g":'ig');
			if(conf.highlightClass) markClass = ' class="' + conf.highlightClass + '"';
			//str = str.replace(re, '<mark' + markClass + '>$1</mark>');
			str = str.replace(re, sepStr[1] + '$1' + sepStr[2]);
			
			str = func._repEntity(str);
			
			str = str.replace(new RegExp(sepStr[1], "g"), '<mark' + markClass + '>');
			str = str.replace(new RegExp(sepStr[2], "g"), '</mark>');
			
			if(userFont.length){
				$.each(userFont, function(i, val){
					str = str.replace(sepStr[0], val);
				});
			}
			
			return str;
		}
		
		
		/*
		 * ソート
		 */
		,"_sortResults": function(){
			var arr = [];
			var i = 0;
			$.each(results.resultsIndex, function(key, val){
				val._file = key;
				val.i = i;
				arr.push(val);
				i++;
			});
			
			arr.sort(function(a,b){
				if(a._score > b._score){
					return -1;
				}else if(a._score < b._score){
					return 1;
				}else{
					return a.i < b.i ? -1:1;
				}
			});
			
			$.each(arr, function(i, obj){
				delete obj.i;
			});
			
			results.sortResultsArr = arr;
		}
		
		/*
		 * 検索結果を表示
		 */
		,"_view": function(){
			var loopStart = 0;
			var loopStop = loopStart + conf.itemByPage;
			var vCheck = results.visitedCheck;
			var html = ['<div class="item"><h3>', textData.searchNotFound, '</h3></div>'];

			if(results.resultsLength){
				html = [];
				func._sortResults();
				results.viewItems = [];
				
				funcCommon._setVisitedCtrlBtn();
				
				if(vCheck.filter){//選択した項目のみ表示の処理
					var resultIni = results.sortResultsArr.length;
					var checkIni = vCheck.check.length;
					results.checkResultsArr = [];
					for(i = 0; i < resultIni; i++){
						for(var j = 0; j < checkIni; j++){
							if(new RegExp('^' + vCheck.check[j]).test(results.sortResultsArr[i]._file)){
								results.checkResultsArr.push(results.sortResultsArr[i]);
								break;
							}
						}
					}
					var maxPage = Math.ceil(results.checkResultsArr.length / conf.itemByPage);
					var getPage = results.viewPageCheck;
					loopStart = Math.max((Math.min(getPage, maxPage) - 1), 0) * conf.itemByPage;
					loopStop = loopStart + conf.itemByPage;
					for(var i = loopStart; i < loopStop && results.checkResultsArr[i]; i++){
						html.push(funcCommon._viewItemLoop(results.checkResultsArr[i]));
					}
					
				}else{//通常表示の処理
					loopStart = (results.viewPage - 1) * conf.itemByPage;
					loopStop = loopStart + conf.itemByPage;
					for(var i = loopStart; i < loopStop && results.sortResultsArr[i]; i++){
						html.push(funcCommon._viewItemLoop(results.sortResultsArr[i]));
					}
				}
			}
			
			funcCommon._setHTML(html, loopStart);
			
		}
		
		/*
		 * 既読/未読の判別機能
		 */
		,"_visited": function(cmd, id, behavior){
			var getStorage = function(){
				var st = sessionStorage.getItem(conf.shaKey);
				return (st)? JSON.parse(st).visitedCheck : false;
			};
			var setStorage = function(){
				val = JSON.stringify({"visitedCheck": results.visitedCheck});
				sessionStorage.setItem(conf.shaKey, val);
			};
			
			var vCheck = results.visitedCheck;
			if("view" == cmd){
				//選択した項目のみ表示切り替え
				if(vCheck.filter){
					vCheck.filter = false;
				}else{
					vCheck.filter = true;
				}
				setStorage();
				conf.sData.pc = 1;
				conf.sData.p = 1;
				func._jampPage();
				
			}else if("reset" == cmd){
				//すべての選択を解除
				$('#searchResult .visitCheckbox').prop("checked", false);
				vCheck.check = [];
				if(vCheck.filter){
					//vCheck.filter = false;
					setStorage();
					//delete conf.sData.pc;
					//conf.sData.p = 1;
					//func._jampPage();
				}else{
					//vCheck.filter = false;
					setStorage();
				}
			}else if("checkbox" == cmd){
				//チェックボックスをクリック
				if(behavior){//追加
					vCheck.check.push(id);
				}else{//削除
					var targetIndex = vCheck.check.indexOf(id);;
					if(targetIndex > -1){
						vCheck.check.splice(targetIndex, 1) ;
					}
				}
				vCheck.check = func._uniqueArray(vCheck.check);
				func._visitedCtrlBtn();
				setStorage();
			}else if("research" == cmd){
				//再検索チェック
				var st = getStorage();
				if(results.inputWord != st.keyword){
					//検索/再検索
					vCheck.keyword = results.inputWord;
					vCheck.check = [];
					vCheck.filter = false;
				}else{
					//ページ遷移
					vCheck.keyword = st.keyword;
					vCheck.check = st.check;
					vCheck.filter = st.filter || false;
				}
				func._visitedCtrlBtn();
				
				var re = new RegExp('^(' + results.filters.join('|') + ')');
				var temp = [];
				$.each(vCheck.check, function(i,v){
					if(re.test(v)){
						temp.push(v);
					}
				});
				if(!vCheck.check.length) vCheck.filter = false;
				setStorage();
				vCheck.check = temp;
				
			}
			
		}
		,"_visitedCtrlBtn": function(){
			if(results.visitedCheck.check.length){
				$('#searchResult .visitedCtrl button').filter('.viewCheck, .reset').prop('disabled', false);
			}else{
				$('#searchResult .visitedCtrl button').filter('.viewCheck, .reset').prop('disabled', true);
			}
		}
		
		/*
		 * ページ遷移
		 */
		,"_jampPage": function(p){
			var fil = [];
			$.each(conf.sData, function(key,val){
				fil.push(key + '=' + encodeURIComponent(val));
			});
			window.location =  $('#search form').attr('action') + "?" + fil.join('&');
		}
		
	};
	
	
	
	var funcCommon = {
		/*
		 * 「気になる」ボタン表示
		 */
		"_setVisitedCtrlBtn": function(){
			if(conf.isWebStorage){
				var viewText = textData.viewSelected;
				if(results.visitedCheck.filter){
					viewText = textData.viewAll;
				}
				$('#searchResult .visitedCtrl').remove();
				var visitedCtrl = '<div class="visitedCtrl">'
						+ '<button class="viewCheck" disabled="disabled">'+ viewText +'</button>'
						+ '<button class="reset" disabled="disabled">'+ textData.resetCheck +'</button>'
						+ '</div>';
				conf.$results.before(visitedCtrl).closest('#searchResult').addClass('visitedFunc');
				func._visitedCtrlBtn();
			}
		}

		/*
		 * 結果項目HTML生成
		 */
		,"_viewItemLoop": function(target){
			var html = [];
			var item = $.extend({}, target);
			var checkbox = '';
			if(conf.isWebStorage){
				checkbox = '<input type="checkbox" class="visitCheckbox" value="' + item._file.replace(/^(.+\.html)\?(.*)$/, '$1') + '">';
			}

			if(!_ua._isWebAccess) item = func._clamping(item);
			
			item.title = func._highlight(item.title);
			item.text = func._highlight(item.text);

			var reFont = new RegExp(conf.ufPattern.source, "g");
			item.title = item.title.replace(reFont, '<span class="kmsymbol" data-charcode="$1"></span>');
			item.text = item.text.replace(reFont, '<span class="kmsymbol" data-charcode="$1"></span>');

			var path = '<span>' + item.topic_path.join('</span><span>') + '</span>';

			var fil = [];
			if(results.filtersCharUpLo) fil.push('ul=1');
			if(results.filtersZenHan) fil.push('zh=1');
			fil = (fil.length) ? "&" + fil.join('&'):'';
			item._file = item._file.replace(/\.html/, '$&' + "?k=" + encodeURIComponent(results.inputWord) + fil);

			if(!_ua._isWebAccess) results.viewItems.push(item);

			var clampClass = function(){
				var re = '', clamp = [];
				if(item.clamp.front) clamp.push('clamp-front');
				if(item.clamp.rear) clamp.push('clamp-rear');
				if(clamp.length) re = ' class="' + clamp.join(' ') + '"';
				return re;
			};

			var scoreHtml = function(){
				var re = '', html = [];
				if(conf.debug.scoreDisplay){
					html.push('<div class="score">');
					html.push('<div class="score-keywords">');
					$.each(item._scoreDetail, function(i,val){
						html.push(
							'<div>'
								,'<table>'
									,'<caption>Word ', (i + 1),': <span>', val.Word,'</span></caption>'
									,'<tr><th>Title Point</th><td>', val._title_3_Formula,'</td></tr>'
									,'<tr><th>Text Point</th><td>', val._text_3_Formula,'</td></tr>'
									,'<tr><th>Add Point</th><td>', val._add_Point,'</td></tr>'
									,'<tr class="total"><th>Keyword Point</th><td>', func._addComma(val.Word_Total),'</td></tr>'
								,'</table>'
							,'</div>'
						);
					});
					html.push('</div>');
					html.push('<div class="score-total">Score: <span>', func._addComma(item._score), '</span></div>');
					html.push('</div>');
					re = html.join('');
				}
				return re;
			};
			
			html.push(
				'<div class="item">'
					,'<div class="result">'
						,'<h3>' +  checkbox + '<a href="', item._file ,'">', item.title ,'</a></h3>'
						,'<div', clampClass() ,'>', item.text ,'</div>'
						,'<div class="path">', path ,'</div>'
					,'</div>'
					,scoreHtml()
				,'</div>'
			);
			
			return html.join('');
		}


		,"_setHTML": function(html, loopStart){
			var vCheck = results.visitedCheck;
			
			var isScoreView = function(){
				if(conf.debug.scoreDisplay){
					conf.$results.addClass('inScore');
					if(conf.debug.scoreDisplay !== true){
						conf.$results.addClass('hide');
					}
				}
			};
			isScoreView();
			
			conf.$results.html( html.join("") );
			
			$.each(results.visitedCheck.check, function(i,v){
				$('#searchResult .results input[value="' + v + '"]').prop('checked', true);
			});
			
			//関連ワード
			if(results.releatekeywords.length){
				conf.$results.find('.relatedWords').remove();
				var upper = [];
				var lower = [];
				$.each(results.releatekeywords, function(i,val){
					var keyUrl = function(key){
						if(/[\s　]+/.test(key)){
							return encodeURIComponent('"' + key + '"');
						}else{
							return encodeURIComponent(key);
						}
					};
					var relatedUrl = location.href.replace(/(k\=)([^&]+)(\&|$)/, '$1' + keyUrl(val) + '$3').replace(/(\&pc?=[0-9]+)/g, '');
					var relatedItem = '<span class="relatedKey"><a href="' + relatedUrl + '">' + val + '</a></span>';
					if(i < 3){
						upper.push(relatedItem);
					}else{
						lower.push(relatedItem);
					}
				});
				conf.$count.after('<div class="relatedWords upper"><h4>'+ textData.searchRelatedHeader +'</h4>'
					+ upper.join('')+'</div>');
				if(lower.length){
					conf.$navi.after('<div class="relatedWords lower"><h4>'+ textData.searchRelatedHeader +'</h4>'
						+ lower.join('')+'</div>');
				}
			}
			
			
			func._pagination();
			
			conf.runFinish =  new Date().getTime();
			results.runTimes = (conf.runFinish - conf.runStart) / 1000;
			
			
			//カウント表示
			var countsArr = [
				results.resultsLength,
				Math.min(loopStart + 1, results.resultsLength),
				Math.min(loopStart + conf.itemByPage, results.resultsLength)
			];
			if(vCheck.filter){
				countsArr = [
					vCheck.check.length,
					Math.min(loopStart + 1, vCheck.check.length),
					Math.min(loopStart + conf.itemByPage, vCheck.check.length)
				];
			}
			
			var Count = textData.searchCounts;
			Count = Count.replace(/#(\d+)#/g, function(hitAll,$1,index,strAll){
				var r = '0';
				if(countsArr[$1]){
					r = countsArr[$1];
				}
				return r;
			});
			
			var timeArr = [
				results.runTimes
			];
			var Time =  textData.searchTimes;
			Time = Time.replace(/#(\d+)#/g, function(hitAll,$1,index,strAll){
				var r = '0';
				if(timeArr[$1]){
					r = timeArr[$1];
				}
				return r;
			});

			var srCount = [ Count ];
			if(conf.debug.runtime) srCount.push(Time);
			srCount = srCount.join(' ');

			conf.$count.html(function(){
				var num = results.resultsLength;
				var re = srCount;
				if(num < 1){
					re = '';
				}else if(num == 1){
					re = srCount.replace(/items\b/g, 'item ');
				}
				return re;
			});
		}
	};
	
	
	
	var funcPHP = {
		
		/*
		 * Ajaxコール
		 */
		"_callAjax": function(op){
			var req = $.extend({"url":"search_result.php"}, op||{});
			return $.ajax(req);
		}
		
		
		/*
		 * 検索結果を表示
		 */
		,"_viewPHP": function(){
			var loopStart = 0;
			var html = ['<div class="item"><h3>', results.error || textData.searchNotFound, '</h3></div>'];

			if(results.resultsLength){
				html = [];
				func._createfindreg();
				
				funcCommon._setVisitedCtrlBtn();
				
				$.each(results.viewItems, function(i,v){
					html.push(funcCommon._viewItemLoop(v));
				});
				
				loopStart = (results.viewPage - 1) * conf.itemByPage;
				
			}
			
			funcCommon._setHTML(html, loopStart);
			
			
		}
	};
	
	
	var getData = func._getGetData();
	
	/**************************************************
	* jQuery ready
	*/
	$(function(){
		
		if(_ua._isWebAccess){
			
			$('#searchResult .results').html('<div class="loading" style="height: calc(100vh - 400px);"><span class="fa fa-spinner fa-spin fa-3x fa-fw"></span></div>');
			
			funcPHP._callAjax({
				"dataType": "json",
				"data": {
					"type": "getBooks",
					"name": conf.books_name
				}
			}).then(function(data){
				if(data){
					conf.books = data;
				}else{
					results.error = "Data Load Error. :1";
				}

				//初期設定
				func._init();

				//IE9 -----------
				if(_ua._IEolder9) $('#searchResult').addClass('olderIE');

				if(conf.sData.k) {

					//関連キーワード配列作成(あいまい)
					func._createReleateArr();
					
					var send_conf = $.extend({}, {
						"sData": conf.sData
						,"andSearch": conf.andSearch
						,"charUpLo": conf.charUpLo
						,"zenHan": conf.zenHan
						,"clampDescLength": conf.clampDescLength
						,"clampFrontPoint": conf.clampFrontPoint
						,"highlightClass": conf.highlightClass
						,"itemByPage": conf.itemByPage
						,"score": conf.score
						,"splitStrBase": conf.splitStrBase
						,"ufPattern": '"' + conf.ufPattern + '"'
						,"visitedCheck": results.visitedCheck
						,"isWebStorage": conf.isWebStorage
					});

					//検索実行
					funcPHP._callAjax({
						"dataType": "json",
						"data": {
							"type": "getViewItems",
							"conf": JSON.stringify(send_conf)
						}
					}).then(function(data){
						if(data){
							$.extend(results, data);
						}else{
							results.error = "Data Load Error. :2";
						}

						//検索結果を表示
						funcPHP._viewPHP();
						
					},function(){
						$('#searchResult .results').html("Data Load Error. : index");
					});
				}
				
			},function(){
				$('#searchResult .results').html("Data Load Error. : books");
			});
		}else{
			conf.books = window[conf.books_name];
			conf.index = window[conf.index_name];
			
			//初期設定
			func._init();

			//IE9 -----------
			if(_ua._IEolder9) $('#searchResult').addClass('olderIE');

			if(conf.sData.k) {

				//検索実行
				func._search();

				//関連キーワード配列作成(あいまい)
				func._createReleateArr();

				//検索結果を表示
				func._view();

			}
			
		}
		
		$('#searchKey').focus().blur();
		
		//console.log(conf);
		//console.log(results);
		
	});
	//end jQuery ready
	
}());


