/*
	elaborated from
	http://old.easy-designs.net/articles/replaceSelect/
	
	FacetFilterLib is a combination of 
	FilterBox and FancySelector, to be found in 
	http://pike.kw.nl/browse/files/software/recent/javascript

	fire
	
*/


	


// Bridge XMLHTTP to XMLHttpRequest in pre-7.0 Internet Explorers

if( typeof XMLHttpRequest == "undefined" ) {
  XMLHttpRequest = function() {
	try { return new ActiveXObject("Msxml2.XMLHTTP.6.0"); } catch(e) {};
	try { return new ActiveXObject("Msxml2.XMLHTTP.3.0"); } catch(e) {};
	try { return new ActiveXObject("Msxml2.XMLHTTP"); }     catch(e) {};
	try { return new ActiveXObject("Microsoft.XMLHTTP"); }  catch(e) {};
 
	throw new Error("This browser does not support XMLHttpRequest or XMLHTTP.");
  };
}




/*
	base def
*/

var FacetFilterLib = {
	debug				: false,
	benchmarks			: new Array(),
	ActiveTimers		: new Array(),
	ActiveRequests		: new Array(),
	RequestTimeout		: 60000,
	CurrentFilterPop	: "",
	mouseX				: FFLibMouseX,
	mouseY				: FFLibMouseY,
	mouseLeaving		: FFLibMouseLeaving,
	showFilterPop 		: FFLibShowFilterPop,
	hideFilterPop 		: FFLibHideFilterPop,
	toggleFilterPop 	: FFLibToggleFilterPop,
	writeSelectors 		: FFLibWriteSelectors,
	writeSelector 		: FFLibWriteSelector,
	deselectValue		: FFLibDeselectValue,
	reset				: FFLibReset,
	toggleSelectors		: FFLibToggleSelectors,
	updateFilter 		: FFLibUpdateFilter,
	abortUpdate			: FFLibAbortUpdate,
	updateCallback		: FFLibUpdateCallback,
	drawFancySelector 	: FFDrawFancySelector,
	selectLI			: FFLibSelectLI,
	selectOption		: FFLibSelectOption,
	drawFancySelectors 	: FFDrawFancySelectors
}

/* move to sitetools */

function FFLibMouseX(evt) {
	if (evt.pageX) return evt.pageX;
	else if (evt.clientX)
		return evt.clientX +  (document.documentElement.scrollLeft ?
			document.documentElement.scrollLeft :
			document.body.scrollLeft);
	else return null;
}
function FFLibMouseY(evt) {
	if (evt.pageY) return evt.pageY;
	else if (evt.clientY)
		return evt.clientY +  (document.documentElement.scrollTop ?
			document.documentElement.scrollTop :
			document.body.scrollTop);
	else return null;
}
function FFLibMouseLeaving(elm,event) {
	var tg = (window.event) ? event.srcElement : event.target;
	//alert(tg);
	if (tg != elm) return false;
	var reltg = (event.relatedTarget) ? event.relatedTarget : event.toElement;
	while (reltg != tg && reltg.nodeName != 'BODY'  && reltg.nodeName != 'HTML') {
		reltg= reltg.parentNode;
		if (reltg==elm) return false;
	}	
	return true;
}
function FFLibClickOutside(elm,event) {
	var target = (window.event) ? event.srcElement : event.target;
	if (target==elm) return false;
	while (target.nodeName != 'BODY'  && target.nodeName != 'HTML') {
		target= target.parentNode;
		if (target==elm) return false;
	}	
	return true;
}

/* ---------------------
	From SelectBox
 --------------------- */

function FFLibShowFilterPop(id,event) {
	
	var x = FacetFilterLib.mouseX(event)-200;
	var y = FacetFilterLib.mouseY(event);
	var elm = document.getElementById(id);
	if (elm) {
		elm.style.left=(x-20)+"px";
		// since click outside hides the current anyway,
		// this is not needed anymore
		// if (FacetFilterLib.CurrentFilterPop) FacetFilterLib.hideFilterPop();
		elm.style.display="block";
		// by default, fold open upward, but keep mouse inside
		var top = y-elm.offsetHeight+15;
		// unless that places the element outside of the screen,
		// then fold open downward, but keep mouse inside
		if (top<0) top = y-15;
		elm.style.top= top+"px";
		FacetFilterLib.CurrentFilterPop = id;
	}
	// clickoutside code
	if (document.addEventListener) {
	 	document.addEventListener ("mouseup",FFLibClickOutsideCurrent,false);
	} else if (document.attachEvent) {
	 	document.attachEvent ("onmouseup",FFLibClickOutsideCurrent);
	} else {
		//document.onmouseup= FFLibClickOutsideCurrent;
	}
 
}

function FFLibHideFilterPop(id) {
	if (!id) id = FacetFilterLib.CurrentFilterPop;
	var elm = document.getElementById(id);
	if (elm) {
		elm.style.display="none";
		FacetFilterLib.CurrentFilterPop = "";
		// in this version, the search is not persistent.
		// search box emptied and pattern removed on close
		var selectelms = elm.getElementsByTagName('select');
		if (selectelms.length) {
			var selectid = selectelms[0].id;
			if (selectid) {
				var searchelm = document.getElementById(selectid+"_search");
				var fancyelm = document.getElementById(selectid+"_fancy");
				if (searchelm) searchelm.value = searchelm.getAttribute("default");
				if (fancyelm) fancyelm.setAttribute("pattern","");
				
			}
		}
	} 
	// clickoutside code
	if (document.removeEventListener) {
	 	document.removeEventListener ("mouseup",FFLibClickOutsideCurrent,false);
	} else if (document.detachEvent) {
	 	document.detachEvent ("onmouseup",FFLibClickOutsideCurrent);
	} else {
		//document.onmouseup= FFLibClickOutsideCurrent;
	}
	
}

function FFLibToggleFilterPop(id,event) {
	// only hide the elm if we are really leaving the elm
	var elm = document.getElementById(id);
	if (elm) {
		//alert(elm.style.display);
		if (elm.style.display!="block") {
			FacetFilterLib.showFilterPop(id,event);
		} else {
			FacetFilterLib.hideFilterPop(id);
		}
	}
}

function FFLibClickOutsideCurrent(event) {
	var current = document.getElementById(FacetFilterLib.CurrentFilterPop);
	if (FFLibClickOutside(current,event)) {
		FacetFilterLib.hideFilterPop();
	}
}



function FFLibWriteSelectors(facetfilterid) {
	var facetfilterelm = document.getElementById(facetfilterid);
	if (facetfilterelm) {
		var selectors = facetfilterelm.getElementsByTagName('select');
		for (var sc=0;sc<selectors.length;sc++) {
			//for (var oc=0;oc<selectors[sc].options.length;oc++) {
				//selectors[sc].options[oc].selected=false;
			//}
			FacetFilterLib.writeSelector(selectors[sc]);
		}
		if (!selectors.length) {
			if (FacetFilterLib.debug) alert("debug: filter contains no selectors "+facetfilterid);
		}
	} else {
		if (FacetFilterLib.debug) alert("debug: cant find facetfilter "+facetfilterid);
	}
}

function FFLibWriteSelector(selelm) {
	
	// find or create and wipe the outputdiv
	var outputdiv = document.getElementById(selelm.id+'_output');
	if (!outputdiv) {
		outputdiv = document.createElement('div');
		outputdiv.setAttribute('id',selelm.id+'_output');
		outputdiv.setAttribute('class',selelm.id+'selection');
		selelm.parentNode.parentNode.appendChild(outputdiv);
	}
	while (outputdiv.childNodes.length) {
		outputdiv.removeChild(outputdiv.childNodes[0]);
	}
	//alert(outputdiv);
	// loop the sel elm, and write a link for each selected option
	var comma = null;
	for (var sc=0; sc<selelm.options.length;sc++) {
		if (selelm.options[sc].selected) {
			//alert('selected');
			var span = document.createElement('span');
			span.setAttribute('class','nowrap');
			var link = document.createElement('a');
			link.setAttribute('href','javascript:FacetFilterLib.deselectValue(\''+selelm.options[sc].value+'\',\''+selelm.id+'\')');
			link.appendChild(document.createTextNode('[-] '));
			span.appendChild(link);
			span.appendChild(document.createTextNode(selelm.options[sc].text));
			if (comma) outputdiv.appendChild(comma);
			outputdiv.appendChild(span);
			comma = document.createTextNode(', ');
		}
	}
	
}


function FFLibDeselectValue(value,selelmid) {
	var selector = document.getElementById(selelmid);
	var changed = false;
	for (var oc=0;oc<selector.options.length;oc++) {
		if (selector.options[oc].value==value) {
			if (selector.options[oc].selected) {
				selector.options[oc].selected=false;	
				changed = true;
			}
		}
	} 
	if (changed && selector.onchange) selector.onchange();	
	if (changed && FacetFilterLib) FacetFilterLib.drawFancySelector(selector);						
}


function FFLibReset(facetfilterid) {
	var facetfilterelm = document.getElementById(facetfilterid);
	if (facetfilterelm) {
		var selectors = facetfilterelm.getElementsByTagName('select');
		for (var sc=0;sc<selectors.length;sc++) {
			var changed = false;
			for (var oc=0;oc<selectors[sc].options.length;oc++) {
				if (selectors[sc].options[oc].selected) {
					selectors[sc].options[oc].selected=false;
					changed=true;
				}
				if (selectors[sc].options[oc].disabled) {
					selectors[sc].options[oc].disabled=false;
					changed=true;
				}
			}
			if (changed) {
				FacetFilterLib.drawFancySelector(selectors[sc]);
				FacetFilterLib.writeSelector(selectors[sc]);
			}
		}
		FacetFilterLib.updateFilter(facetfilterid);
	}
}

function FFLibToggleSelectors(facetfilterid) {
	var facetfilterelm = document.getElementById(facetfilterid);
	if (facetfilterelm) {
		var selectors = facetfilterelm.getElementsByTagName('select');
		for (var sc=0;sc<selectors.length;sc++) {
			selectors[sc].style.display=(selectors[sc].style.display=="block")?"none":"block";
		}
	}			
}


/* xmlhttp stuff */

function FFLibUpdateFilter(facetfilterid) {

	
	var facetfilterelm = document.getElementById(facetfilterid);
	if (facetfilterelm) {

		// create query (topNodeID,revTopNodeID,revSelectedObjectIDs)
		
		var query = facetfilterelm["AjaxCallbackURL"].value;
		if (query) {
			query += "?TopNodeID="+facetfilterelm["TopNodeID"].value;
			query += "&RevTopNodeID="+facetfilterelm["RevTopNodeID"].value;
			var selectors = facetfilterelm.getElementsByTagName('select');
			for (var sc=0;sc<selectors.length;sc++) {
				for (var oc=0;oc<selectors[sc].options.length;oc++) {
					if (selectors[sc].options[oc].selected) {
						query += "&RevSelectedObjectIDs[]="+selectors[sc].options[oc].value;
					}				
				}
			}
			if (facetfilterelm["Phrase"].value!=facetfilterelm["DefPhrase"].value) {
				query += "&Phrase="+facetfilterelm["Phrase"].value;
			}
			
			// abort if there's already a request
			FacetFilterLib.abortUpdate(facetfilterid);

			var request =  new XMLHttpRequest();
			request.open("POST", query, true);
			request.setRequestHeader("Content-Type", "application/x-www-form-urlencoded");
			
			// the scope of an anonymous function is a bit weird
			// check the that=this examples online. it works.
			
			request.onreadystatechange = function() {
				if (request.readyState == 4) {
					//if (request.status == 200) {
						// note .. mozilla is known to lose responseXML on some conditions:
						// http://www.quirksmode.org/blog/archives/2005/09/xmlhttp_notes_a_1.html
						if (request.responseXML) {
							FacetFilterLib.updateCallback(facetfilterid,request.responseXML);
						} else {
							if (FacetFilterLib.debug) alert('debug: ajax response not in expected format ');
							FacetFilterLib.abortUpdate(facetfilterid);
						}
					//}
				}
			};
			
			request.send(null); 
			
			// feedback
			var feedbackelm = document.getElementById(facetfilterid+"_feedback");
			if (feedbackelm) feedbackelm.innerHTML = facetfilterelm["PendingResultsMsg"].value;
			
			// benchmark
			if (FacetFilterLib.debug) FacetFilterLib.benchmarks = {"requestsend":(new Date()).getTime()};
			// start timeout
			FacetFilterLib.ActiveRequests[facetfilterid] = request;
			FacetFilterLib.ActiveTimers[facetfilterid] = setTimeout(
				"FacetFilterLib.abortUpdate('"+facetfilterid+"')",FacetFilterLib.RequestTimeout); 
			
		} else {
			if (FacetFilterLib.debug) alert('debug: cant find callback url in '+facetfilterid);
		}
	} else {
		if (FacetFilterLib.debug) alert('debug: cant find filter '+facetfilterid);
	}
}

function FFLibAbortUpdate(facetfilterid){
	// abort if there's already a request
	if (FacetFilterLib.ActiveRequests[facetfilterid]) {
		if (FacetFilterLib.debug) {
			alert('debug: aborting running ajax request for '+facetfilterid);
			FacetFilterLib.benchmarks = new Array();		
		}
		FacetFilterLib.ActiveRequests[facetfilterid].onreadystatechange = function () {}
		FacetFilterLib.ActiveRequests[facetfilterid].abort();
		FacetFilterLib.ActiveRequests[facetfilterid] = null;
	}
	if (FacetFilterLib.ActiveTimers[facetfilterid])
		clearTimeout(FacetFilterLib.ActiveTimers[facetfilterid]);
	// feedback
	var feedbackelm = document.getElementById(facetfilterid+"_feedback");
	if (feedbackelm) feedbackelm.innerHTML = "";


}

function FFLibUpdateCallback(facetfilterid,xmlDoc) {
	//alert('callback');
	// parse result (topNodeID,revTopNodeID,revDisabledNodeIDs)
	// loop all selectors
	// 	disable any if needed
	//alert(xmlDoc);
	
	// end timeout
	FacetFilterLib.ActiveRequests[facetfilterid] = null;
	clearTimeout(FacetFilterLib.ActiveTimers[facetfilterid]);
	
	var remainingoids = new Array(); 
	var numremaining = 0;
	
	if (FacetFilterLib.debug) FacetFilterLib.benchmarks["responsereceived"] = (new Date()).getTime();
	
	if (xmlDoc) {
		
		if (FacetFilterLib.debug) FacetFilterLib.benchmarks["xmlparsed"] = (new Date()).getTime();
		
		
		// parse xml
		
		var resnodes = xmlDoc.getElementsByTagName('revRemainingObjectIDs');
		//alert(resnodes.length);
		if (resnodes[0]) {
			var remainnodes=resnodes[0].getElementsByTagName('objectID');
			//alert(remainnodes.length);
			for (var nc=0;nc<remainnodes.length;nc++) {
				var remainingoid = remainnodes[nc].childNodes[0].nodeValue;
				//alert(remainingoid);
				remainingoids[parseInt(remainingoid)]=true;
			}
		} else {
			// no result
			var errnodes = xmlDoc.getElementsByTagName('error');
			if (errnodes.length) {
				if (FacetFilterLib.debug) alert("error: "+remainnodes[nc].errornodes[0].nodeValue);
			} else {
				if (FacetFilterLib.debug) alert("debug: no results");
			}
		}
	
		var facetfilterelm = document.getElementById(facetfilterid);
		if (facetfilterelm) {
		
			// feedback
			var feedbackelm = document.getElementById(facetfilterid+"_feedback");
			if (feedbackelm) {
				var	countnodes = xmlDoc.getElementsByTagName('numRemainingNodes');
				if (countnodes.length) {
					if (countnodes[0].childNodes[0].nodeValue) {
						feedbackelm.innerHTML = facetfilterelm["ResultsMsg"].value.replace('%',countnodes[0].childNodes[0].nodeValue);
					} else {
						feedbackelm.innerHTML = facetfilterelm["ZeroResultsMsg"].value;
					}
				} else {
					feedbackelm.innerHTML = "";
				}
			}
			
			// store parsed xml
			
			var selectors = facetfilterelm.getElementsByTagName('select');
			var selectorsChanged = new Array();
			for (var sc=0;sc<selectors.length;sc++) {
				//alert('b');
				var changed = false;
				for (var oc=0;oc<selectors[sc].options.length;oc++) {
					
					if (!remainingoids[selectors[sc].options[oc].value]) {
						// disable option
						if (!selectors[sc].options[oc].getAttribute("disabled")) {
							selectors[sc].options[oc].setAttribute("disabled","true");
							selectors[sc].options[oc].setAttribute("title",facetfilterelm["ZeroResultsMsg"].value);
							changed = true;
						} 
					} else {
						//enable option
						if (selectors[sc].options[oc].getAttribute("disabled")) {
							selectors[sc].options[oc].removeAttribute("disabled");
							selectors[sc].options[oc].removeAttribute("title");
							changed = true;
						}
					}
				}
				selectorsChanged[sc] = changed;
				
			}
		
		
			if (FacetFilterLib.debug) FacetFilterLib.benchmarks["selectorschanged"] = (new Date()).getTime();
			
			// now rewrite the changed selectors
			for (var cc=0;cc<selectors.length;cc++) {
				if (selectorsChanged[cc]) {
					FacetFilterLib.drawFancySelector(selectors[cc]);
				}
			}
			if (FacetFilterLib.debug) {
				FacetFilterLib.benchmarks["selectorsdrawn"] = (new Date()).getTime();
				alert(
					"debug:\n"+
					"responsereceived\t@"+(FacetFilterLib.benchmarks["responsereceived"]-FacetFilterLib.benchmarks["requestsend"])+"msecs\n"+
					"xmlparsed\t@"+(FacetFilterLib.benchmarks["xmlparsed"]-FacetFilterLib.benchmarks["requestsend"])+"msecs\n"+
					"selectorschanged\t@"+(FacetFilterLib.benchmarks["selectorschanged"]-FacetFilterLib.benchmarks["requestsend"])+"msecs\n"+
					"selectorsdrawn\t@"+(FacetFilterLib.benchmarks["selectorsdrawn"]-FacetFilterLib.benchmarks["requestsend"])+"msecs\n"
				);
			}
			
		} else {
			if (FacetFilterLib.debug) alert("debug: can't find facetfilter "+facetfilterid);
		}

	} else {
		if (FacetFilterLib.debug) alert("debug: ajax returned no xml document");
	}
	

	
}

/* ---------------------
	From FancySelector:
 --------------------- */

function FFDrawFancySelector(selobj,pattern) {

	//alert("drawFancySelector "+selobj.id);
	var size = selobj.getAttribute('size');
	if (!size) size=1;
	
	var currentul = document.getElementById(selobj.id+'_fancy');
	if (currentul) {
		while (currentul.childNodes.length) {
			currentul.removeChild(currentul.childNodes[0]);
		}
		ul = currentul;
		// set selectbox, close any open popup
		if (size>1) {
			if (ul.className.indexOf("fancySelectBox")==-1) ul.className += " fancySelectBox ";
		} else {
			if (ul.className.indexOf("fancySelectPopOpen")==-1) ul.className += " fancySelectPop ";
			else ul.className = ul.className.replace(new RegExp("fancySelectPopOpen"), 'fancySelectPop');
		}
		
	} else {
		//alert('creating new');
		ul = document.createElement('ul');
		ul.setAttribute('id',selobj.id+'_fancy');
		if (size>1) ul.className = 'fancySelectBox ';
		else ul.className = 'fancySelectPop ';
	}
	
	// make pattern persistent
	if (pattern) {
		try {
			var rxstring = "("+pattern+")";
			//alert(rxstring);
			var rxpattern = new RegExp(rxstring,"i");
			pattern = rxstring;
			//alert(pattern);
		} catch (e) {
			//alert("err" +pattern);
			var rxpattern = null;
			pattern=null;	
		}
	} else {
		var rxpattern = null;
	}	
	if (pattern || pattern==='') ul.setAttribute('pattern',pattern);
	else pattern = ul.getAttribute('pattern');
	
	if (selobj.className.indexOf("replaced")==-1) selobj.className += ' replaced';
	var selopts = selobj.options;
	for (var i=0; i<selopts.length; i++) {
		if (!rxpattern || selopts[i].text.match(rxpattern)) {
		
			var li = document.createElement('li');
			var txt = document.createTextNode(selopts[i].text);
			//alert('attach '+txt.textContent);
			li.appendChild(txt);
			li.selIndex = selopts[i].index;
			li.selectID = selobj.id;
			
			/* inherit classes from select elm */
			li.className = selopts[i].className;
			/* inherit title from select elm */
			if (selopts[i].getAttribute("title")) li.setAttribute("title",selopts[i].getAttribute("title"));
			if (selopts[i].selected) li.className += ' selected';

			if (size>1) {
									
				if (!selopts[i].getAttribute("disabled")) {
					
					li.onclick = function() {
						FacetFilterLib.selectLI(this);
					}
					
				} else {
					li.className += ' disabled';
				}

			} else {
					
				/* single select pop */
				
				if (!selopts[i].selected) {		
						
					if (!selopts[i].getAttribute("disabled")) {
						li.onclick = function() {
							FacetFilterLib.selectLI(this);
							//this.parentNode.className = 
							//	this.parentNode.className.replace(new RegExp("fancySelectPopOpen"), 'fancySelectPop');
						}
					} else {
						li.className += ' disabled';
					}
				
				} else {

					// selected selectpop should open when you click this element,
					// and change its own onclick if not disabled.
					if (size<=1) {
						if (selopts[i].getAttribute("disabled")) {
							li.onclick = function() {
								//alert(this.parentNode.className);
								this.parentNode.className = 
									this.parentNode.className.replace(new RegExp("fancySelectPop"), 'fancySelectPopOpen');
								//alert(this.parentNode.className);
								//this.parentNode.className += ' fsopen';
							}
						} else {
							li.onclick = function() {
								//alert(this.parentNode.className);
								this.parentNode.className =
									this.parentNode.className.replace(new RegExp("fancySelectPop"), 'fancySelectPopOpen');
								//alert(this.parentNode.className);
								//this.parentNode.className += ' fsopen';
								this.onclick = function() { selectLI(this); }
							}
						}
						
					}
					
				}
				
			}
			
			// if its not disabled, it should have hover effect
			if (!selopts[i].getAttribute("disabled")) {
				if (window.attachEvent) {
					li.onmouseover = function() {
						this.className += ' hover';
					}
					li.onmouseout = function() {
						this.className = 
							this.className.replace(new RegExp(" hover\\b"), '');
					}
				}
			}
				
			ul.appendChild(li);
			
		} else {
			// element text doesnt match pattern
		}
		
	} // loop for all elements
	
	if (!currentul) selobj.parentNode.appendChild(ul,selobj);
}

function FFLibSelectLI(lielm) {
	var ulelm = lielm.parentNode;
	var ulid = ulelm.getAttribute('id');
	var selelmid = ulid.substring(0,ulid.length-6);
	//alert(selelmid);
	var selelm = document.getElementById(selelmid);
	if (selelm) {
		FacetFilterLib.selectOption(selelm,lielm);
		FacetFilterLib.drawFancySelector(selelm);
	}
}

function FFLibSelectOption(selelm,lielm) {
	selelm.options[lielm.selIndex].selected=!selelm.options[lielm.selIndex].selected;
	if (selelm.onchange) selelm.onchange();
}

function FFDrawFancySelectors(topelmid) {
	if (!topelmid) selectors = document.getElementsByTagName('select');
	else {
		var topelm = document.getElementById(topelmid);
		if (topelm) {
			var selectors = topelm.getElementsByTagName('select');
			for (var sc=0; sc<selectors.length; sc++) {
				FacetFilterLib.drawFancySelector(selectors[sc]);
			}
		}
	}
}

