//libill.jsは複数のxmlを検索し、結果を表示するためのjsです。
//使用する際には、設定ファイルに、ファイル名などを設定してください。
//html上で関数libill('設定ファイル名')を宣言することで、使用に必要なformが表示され、
//検索できるようになります。
//すべてjavascriptでの稼動のため、処理時間などは使用するPCやブラウザで異なります。
//目安としてはWinXpsp3(celeronM1GHz、メモリ512M),IE7使用１万件で10秒程度です。
//使用しているスタイルシートのidは
//libill_f:フォーム用
//libill_cnt:ヒット件数表示用div
//libill_list:一覧表示用table
//libill_detail:詳細表示用div　となっています。デザインはcssなどで変更できます。
//使用は私的・商業目的に限らず無料・無断でかまいません。再配布についても制限を設けません。ソースの変更なども自由です。
//利用によるあらゆる損害は補償しかねます。自己責任での運用をお願いします。
//ホームページ：http://wemfls.web.fc2.com/

//設定ファイルについて
//設定ファイルは、検索対象のxmlファイルと要素の処理を指定します。
//例では、index.xmlを設定ファイルとしています。
//<files>
//<file name="books.xml" describe="コミック" root="book" checked="true">
//<facter 検索="true" 一覧="true" 表記="責任表示">author</facter>
//<facter 検索="true" 一覧="true" 表記="タイトル">title</facter>
//<facter 検索="false" 一覧="true" 表記="出版">publisher</facter>
//<facter 検索="true" 一覧="false" 表記="内容">content</facter>
//</file>
//<file........
// .
// .
//</file>
//</files>
//このような例の場合"books.xml"ファイルの"book"ノードの中が検索対象で、画面上は"コミック"と表示されます。
//またチェックボックスの初期値はチェックされた状態です。
//bookノード内のどの子ノードを検索するかなどは<file>の子ノード<facter>で指定します。
//bookの子ノード"author"は、検索="true"のため検索対象となり、一覧表示="true"のため、一覧表示時に内容が表示されます。
//その際、テーブルの見出しは"責任表示"となります。


var setnode;	//設定ファイルを保持するためのノード
var ind;
function indicator(){	//検索中表示のためのクラス
 this.div=set_ind();
 this.ind_start=ind_start;
 this.ind_stop=ind_stop;
 function set_ind(){
	this.div=document.createElement("DIV");
	this.div.position='relative';
	this.div.style.margin='0em';
 	this.div.style.display='none';
	document.getElementById('libill_ind').appendChild(this.div);
	return this.div;
 }

 function ind_start(){
 	this.div.innerHTML='検索中...';
 	this.div.style.display='inline';
	document.getElementById('lib_b1').style.display='none';
 }
 function ind_stop(){
 	this.div.innerHTML='';
 	this.div.style.display='none';
	document.getElementById('lib_b1').style.display='inline';
 }
 return this;
}

function compareString(inputky,nodetext){//検索キーをスペースで分解し、検索を行う関数
	if(inputky == ""){
		return false;
	}else{
		var s = inputky.replace(/　/g," ");
		var word = s.split(" ");
		var len = word.length;
		var ch=0;
		var ofs;
		for(var i = 0; i < len; i++){
			ofs = nodetext.indexOf(word[i]);
			if(ofs == -1){
				return false;
			}
			ch ++;
		}
		if(ch == len){
			return true;
		}
		return false;
	}
}
function createHttpRequest(){// XMLファイルを開くための関数（固定）
	if(window.ActiveXObject){
		try{
			return new ActiveXobject("Msxml2.XMLHTTP")
		}catch(e){
			try{
				return new ActiveXObject("Microsoft.XMLHTTP")
			}catch(e2){
				return null
			}
		}
	}else if(window.XMLHttpRequest){
		return new XMLHttpRequest()
	}else{
		return null;
	}
}

function serchxml(ky,setnum,md){//ノード検索・表示用関数　mdには件数表示モード(count)と一覧表示モード(list)を指定
	var i = 0;
	var dbn = setnode[setnum].getAttribute('describe');	//対象ファイル表示用
	var fn = setnode[setnum].getAttribute('name');		//対象ファイル名
	var rt = setnode[setnum].getAttribute('root');		//検索対象親ノード
	var hyoki = new Array;		//要素の表記名を格納
	var list = new Array;		//一覧表示用要素を格納
	var kensaku = new Array;	//検索用要素を格納
	var elTD;
	for(i=0;i<setnode[setnum].childNodes.length; i++){	//設定ファイル（setfile.xml）より設定を各配列に格納
		if(setnode[setnum].childNodes[i].nodeName =="facter"){
			if(setnode[setnum].childNodes[i].getAttribute("検索")=="true"){
				kensaku[i]=setnode[setnum].childNodes[i].firstChild.nodeValue;	//検索対象の要素名を格納
			}
			if(setnode[setnum].childNodes[i].getAttribute("一覧")=="true"){
				list[i]=setnode[setnum].childNodes[i].firstChild.nodeValue;		//一覧表示対象の要素名を格納
				hyoki[i]=setnode[setnum].childNodes[i].getAttribute("表記");	//要素のテーブル見出表記を格納
			}
		}
	}
	var bodiesCount = $('libill_list').tBodies.length;	//	ここから表示テーブル初期化
	for (i = bodiesCount; i > 0; i --) {
	    var bodyItem = $('libill_list').tBodies.item(i - 1);
	    var rowCount = bodyItem.rows.length;
	    for (var j = rowCount; j > 0; j --) {
	    	$('libill_list').deleteRow(bodyItem.rows.item(j - 1).rowIndex);
	    }
	}
	if(md == 'list'){		//新しく表示テーブルの見出を出力（一覧表示モードのみ）
		var elTR = $('libill_list').insertRow( -1 );
		elTD = elTR.insertCell( -1 );
		elTD.innerHTML = 'No';
		for(i=0;i<hyoki.length;i++){
			if(hyoki[i]){
				elTD = elTR.insertCell( -1 );
				elTD.innerHTML = hyoki[i];
			}
		}
	}
	$('libill_detail').innerHTML="";//詳細表示divの初期化

	var tim = new Date();

	var httpobj = createHttpRequest(); //検索対象のファイルを開く
	httpobj.open("GET",fn,false);
	httpobj.send(null);
	var node = httpobj.responseXML.getElementsByTagName( rt );
	i=0;
	if(!node.length){
		alert(rt+'がありません。\n'+fn+'を確認してください');
	}else{
		for(var j=0;j<node.length; j++){ //検索対象ノードを順番に検索(ｊがノード番号）
			var content = new Array(hyoki.length);
			var dbdata = "";
			var cnode=node[j];
			for(var k=0;k<hyoki.length;k++){	//表記データ収納用配列の初期化
				content[k]="";
			}
			//検索用の文字列の作成
			for(k=0;k<kensaku.length;k++){
				if(kensaku[k]){
					var str = cnode.getElementsByTagName(kensaku[k]);
					for(var l=0;l<str.length;l++){
						if(str[l].firstChild){
							dbdata = dbdata + str[l].firstChild.nodeValue;
						}
					}
				}
			}
			if(compareString(ky.value,dbdata)){	//検索対象ノードと検索キーの比較
				if(md == 'list'){	//一覧表示モードの処理
					elTR = $('libill_list').insertRow( -1 );
					elTD = elTR.insertCell( -1 );
					elTD.innerHTML ='<a href="#" onClick="detailNode(' + "'" + setnum + "','" + j + "')" +'">' + j + '</a>';
					for(k=0;k<list.length;k++){
						if(list[k]){	//表記に値があった場合は、セルを追加
							str = cnode.getElementsByTagName(list[k]);
							for(l=0;l<str.length;l++){
								content[k]=content[k]+' '+ str[l].firstChild.nodeValue;
							}
							elTD = elTR.insertCell( -1 );
							elTD.innerHTML =content[k];
						}
					}
				}
				i++;	//ヒット件数カウントアップ
			}
		}
		var et = (new Date() - tim)/1000;
		$('libill_time').innerHTML=$('libill_time').innerHTML+dbn+' serch time:'+et+'<br>';
		if(md == 'count'){	//件数表示モードでは返り値にヒット件数を渡す
		 	return i;
		}
	}
}
function detailNode(setnum,nodenum){ //詳細表示用の関数
	var dbn = setnode[setnum].getAttribute('describe');	//対象ファイル表示用
	var fn = setnode[setnum].getAttribute('name');		//対象ファイル名
	var rt = setnode[setnum].getAttribute('root');		//検索対象親ノード
	var hyoki = new Array;
	var list = new Array;
	for(var i=0; i<setnode[setnum].childNodes.length; i++){	//設定ファイル（setfile.xml）より設定を各配列に格納
		if(setnode[setnum].childNodes[i].nodeName =="facter"){
			hyoki[i] = setnode[setnum].childNodes[i].getAttribute("表記");	//要素のテーブル見出表記を格納
			list[i] = setnode[setnum].childNodes[i].firstChild.nodeValue;
		}
	}
	$('libill_detail').innerHTML="";
	var httpobj = createHttpRequest(); //詳細表示対象のファイルを開く
	httpobj.open("GET",fn,false);
	httpobj.send(null);
	var node = httpobj.responseXML.getElementsByTagName( rt );
	
	var cnode=node[nodenum];			//指定の番号（表示対象）ノードを取得
	$('libill_detail').innerHTML='<h2>'+dbn+':'+nodenum+'詳細表示</h2>';
	for(var j=0 ; j < cnode.childNodes.length; j++){//指定ノードの内容を表示
		if(cnode.childNodes[j].firstChild!=null){	//子ノードを持っていること（内容があること）を確認
			var flg=0;
			for(i=0 ; i< list.length; i++){	//属性:'表記'が指定されていた場合、見出しにそれを使用
				if(list[i]== cnode.childNodes[j].nodeName&&hyoki[i]){
					$('libill_detail').innerHTML = $('libill_detail').innerHTML + '<span>' + hyoki[i]+':</span>';
					flg=1;
					break;
				}
			}
			if(flg==0){		//属性:'表記'が指定されていない場合、見出しはXMLの通り
				$('libill_detail').innerHTML = $('libill_detail').innerHTML  + '<span>' + cnode.childNodes[j].nodeName +':</span>';
			}
			$('libill_detail').innerHTML = $('libill_detail').innerHTML + cnode.childNodes[j].firstChild.nodeValue +'<br />';
		}
	}
}
function xSerch(){ //ファイル横断（件数表示）用の関数　結果表示に一覧を呼び出すリンクを含む
	var fn;
	var dbn;
	var rt;
	var ct;
	var ky=$('libill_ky');
	$('libill_cnt').innerHTML = '<ul>';
	for(var i=0;i<setnode.length; i++){
		dbn = setnode[i].getAttribute('describe');
		if($('libill_f').elements[i+2].checked){
			ct = serchxml(ky,i,'count');
			if(ct==0){
				$('libill_cnt').innerHTML = $('libill_cnt').innerHTML +'<li>'+ dbn +'　' + ct +'件</li>';
			}else{
				$('libill_cnt').innerHTML = $('libill_cnt').innerHTML +'<li><a href="#" onClick="serchxml('+"$('libill_ky')"+',' + "'" + i + "','list')"+'">' + dbn + '</a>　'+ ct +'件</li>';
			}
		}
	}
	$('libill_cnt').innerHTML = $('libill_cnt').innerHTML + '</ul>';
}
function send(){
	if($('libill_ky').value){
		ind.ind_start();
		setTimeout('xSerch()',1);	//表示の処理を待って検索スタート
		setTimeout('ind.ind_stop()',1);
	}else{
		alert('検索語が入力してください。');
	}
}
function libill(filename){//初期表示用の関数
	var fn;	
	var dbn;
	var cd;
	var ojbbody=document.getElementsByTagName('body').item(0);
	var httpobj = createHttpRequest();
	httpobj.open('GET',filename,false);
	httpobj.send(null);
	setnode = httpobj.responseXML.getElementsByTagName( 'file' );	//グローバル変数setnodeに設定ファイルを渡す
	if(!setnode.length){
		var element = document.createElement('div');
		element.id="libill_cnt";
		element.innerHTML='<strong style="color:#ff0000;">'+filename+'を確認してください</strong><br />';
		document.getElementsByTagName('body').appendChild(element);
	}else{
		//以下は表示に必要なものをページに出力するためのもの
		var elefrom = document.createElement('form');
		elefrom.name='libill_f';
		elefrom.id='libill_f';
		elefrom.innerHTML='<input type="text" size="20" name="ky" id="libill_ky">　<input type="button" id ="lib_b1" name="sbutton" value="検索" onClick="send()">';
		elefrom.innerHTML =elefrom.innerHTML + '<div id="libill_ind" style="display:inline;"></div><ul>';
		for(var i=0;i<setnode.length; i++){
			dbn=setnode[i].getAttribute('describe');
			fn=setnode[i].getAttribute('name');
			cd=setnode[i].getAttribute('checked');
			if(cd=='true'){
				elefrom.innerHTML =elefrom.innerHTML + '<li><input name="' + fn + '" type="checkbox" checked="checked"><a href="' + fn + '">' + dbn +'</a></li>';
			}else{
				elefrom.innerHTML =elefrom.innerHTML + '<li><input name="' + fn + '" type="checkbox"><a href="' + fn + '">' + dbn +'</a></li>';
			}
		}
		elefrom.innerHTML =elefrom.innerHTML + '</ul>';
		ojbbody.appendChild(elefrom);
		var eletime= document.createElement('div');
		eletime.id="libill_time";
		ojbbody.appendChild(eletime);
		var elecnt= document.createElement('div');
		elecnt.id="libill_cnt";
		ojbbody.appendChild(elecnt);
		var elelist= document.createElement('table');
		elelist.id="libill_list";
		ojbbody.appendChild(elelist);
		var eledetail= document.createElement('div');
		eledetail.id="libill_detail";
		ojbbody.appendChild(eledetail);
	}
}
window.onload = function(){
	ind = new indicator();
}

