// "Criminal Sorter" 
// part of Alachua County Crime Stoppers
// http://www.stopcrime.tv
// 
// Version History
// -----------------------------------------------
// 122806 MAT - v1.1   Added Sorting feature
// 122706 MAT - v1.0.1 Fixed display error with checkboxes in IE6 to remove add. space.
// 080106 MAT - v1.0   Release (dev releases not versioned)

	var criminals = getElementsByClassName(document,"a","criminal");
	var criminal_names = getElementsByClassName(document,"a","criminal_name");


	window.onload = function() {assignOnclickHandlersToCheckboxes();checkActiveConditions();}


	//places the event triggers on each form input in the filter to simulate "live updating" filtering results
	function assignOnclickHandlersToCheckboxes()
	{
		for(var i=0; i<document.forms.length; i++)														//in all forms
			for(var j=0; j<document.forms[i].childNodes.length; j++)									//check all form children
				if(document.forms[i].childNodes[j].type == "checkbox"){									//whose type is checkbox
					if(document.forms[i].parentNode.id == "age") {
						document.forms[i].childNodes[j].disabled = 'disabled';}
					else{
						document.forms[i].childNodes[j].onclick=function() {showCriminalsWithCondition(collectConditions());}}			//and assign them this function
				}

		//** Age
		document.getElementById('byo').onclick = function() {changeAgeCriteria('byYearsOld');};
		//document.getElementById('bby').onclick = function() {changeAgeCriteria('byBirthYear');}; disabled until implemented
		document.getElementById('ageBox').onkeypress = showAgeConditionResult;
		document.getElementById('sel_byo').onchange = function() {showCriminalsWithCondition(collectConditions());}
        document.getElementById('submitSort').onclick = function() {
            //collect filters and store in hidden field to preserve from sort-to-sort
            var str = "";
            var conds = collectConditions();
            
            //create concatonated filter string
            var tmp = [];
            for(var i=0; i<conds.length; i++){
                tmp.push(conds[i].name + "|" + conds[i].value + ",");}
                //str += conds[i].name + "|" + conds[i].value + ",";} ~ simple optimization
            str = tmp.join('');
            
            //set hidden field value to concatonated activeFilters string
            if(str == ""){$('activeFilters').parentNode.removeChild($('activeFilters'));}   //if no filters, don't add garbage to the URL
            else{$('activeFilters').value = str;}                                           //set hidden field to be POSTed
        
        };  //end onclick
	}
	
	function checkActiveConditions(){       //conditions in the form of con1|val1,con2|val2,con3|val3,...etc
	    if ($('activeFilters').value == "") return;
	    var conds = $('activeFilters').value.split(",");   //create array of conditions
	    for(var i=0; i<conds.length; i++){                 // cycle through all conditions from POST

	        try{                                           //FF seems to put an extra element at the end of the split array, use this to simply die
	            var c = conds[i].split("|",2);             //split each array element into a name-value array pair
	            if(c[0] == "sex" && c[1] == "M") {c[1] = "male";}           //convert gender "M" to value "male"
	            else if(c[0] == "sex" && c[1] == "F") {c[1] = "female";}    //convert gender "F" to value "female"
	            else if(c[0] == "age") {$('ageBox').value = c[1]; throw e;}   //if condition is age, instead set value
	            else if(c[0] == "sel_byo") { $('sel_byo').value = c[1];  throw e;}   //if condition is age, instead set value
                
	            $(c[0]+"_"+c[1].toLowerCase()).checked = 'checked';}        //check the appropriate html checkbox of passed condition
	        catch(e){}
         }
         showCriminalsWithCondition(collectConditions());                   //process the applied filters
	}

	function showAgeConditionResult(e){
		if(!e) var e = window.event;
		if(e.keyCode == 13) {
		showCriminalsWithCondition(collectConditions());}
	}

	function Condition(conditionName, conditionValue)
	{
		this.name = conditionName;
		this.value = conditionValue;

		this.previousInstance = -1;
	}

	function getLastInstanceOfCondition(conditionList, newCond)
	{
		for(var i=conditionList.length-1; i>-1; i--)
			if(conditionList[i].name == newCond.name)
				return i;

		return -1;
	}

	function collectConditions()
	{
		var conditions = new Array();

		var checkedConditions = getElementsByClassName(document,"input","control");
		checkedConditions.push($('sel_byo'));   //add the age dropdown to the filter array
        //alert($('sel_byo').selected);
        //alert(checkedConditions[checkedConditions.length - 1]);
		for(var i=0; i<checkedConditions.length; i++){
			if(checkedConditions[i] == null);
			else if(checkedConditions[i].checked || (checkedConditions[i].type == "text" & checkedConditions[i].value != "") || (checkedConditions[i].type == "select-one" & checkedConditions[i].value != "ageNull")) {
				var name = getName(checkedConditions[i].id);
				var val = getVal(checkedConditions[i].id);
				var newCond = new Condition(name, val);
				newCond.previousInstance = getLastInstanceOfCondition(conditions, newCond);
				conditions.push(newCond);}}

		return conditions;
	}

	function getName(id){
		if(id.match('race_'))		{return "race";}
		else if(id.match('sex_'))	{return "sex";}
		else if(id.match('hair_'))	{return "hair";}
		else if(id.match('eye_'))	{return "eye";}
		else if(id == 'ageBox') {return "age";}
		else if(id == 'sel_byo')    {return "sel_byo";}
		else	return null;
	}

	function getVal(id){
		if(id.match('race_'))		{return id.substring(5).toUpperCase();}
		else if(id.match('sex_'))	{return id.substring(4,5).toUpperCase();}
		else if(id.match('hair_'))	{return id.substring(5).toUpperCase();}
		else if(id.match('eye_'))	{return id.substring(4).toUpperCase();}
		else if(id.match('ageBox')) {return $('ageBox').value;}
		else if(id.match('sel_byo'))    {return $('sel_byo').value;}
		else	return null;
	}

	function doesntSatisfyLikeCondition(criminalValue, conditionsSet, index)
	{
		var name = conditionsSet[index].name;
		var oldVal = conditionsSet[index].value;
		var prevInstance = conditionsSet[index].previousInstance;

		if(prevInstance == -1)	return false;
		else if(conditionsSet[prevInstance].value == criminalValue) return true;
		else	doesntSatisfyLikeCondition(criminalValue, conditionSet,prevInstance);
	}


	function showCriminalsWithCondition(conditions)
	{
		hideAllCriminals();                                         //schema used is 1)hide all 2)show all that meet criteria
		var ageEntered = document.getElementById('ageBox').value;   //capture age criteria to JS var

		if(conditions.length == 0 && ageEntered == ''){             //nothing checked and no age entered
			showAllCriminals();return;}                             // > show all


		/* ***************************
			Forced breakup of conditions because of logic conditions of simultaneously including ANDs and ORs
		  	> and still keeping the system relatively dynamic */

		var race = new Array();
		var sex = new Array();
		var hair = new Array();
		var eye = new Array();


		for(var p=0; p<conditions.length; p++){ //collect activated criteria into a stack
			if(conditions[p].name == 'race')	race.push(conditions[p]);
			else if(conditions[p].name == 'sex')	sex.push(conditions[p]);
			else if(conditions[p].name == 'hair')	hair.push(conditions[p]);
			else if(conditions[p].name == 'eye')	eye.push(conditions[p]);}


		for(var i=0; i<criminals.length; i++){      //for each criminal, if he/she meets a condition, show
			if(		criminalHasConditions(criminals[i],race) &&
					criminalHasConditions(criminals[i],sex) &&
					criminalHasConditions(criminals[i],hair) &&
					criminalHasConditions(criminals[i],eye) &&
					criminalMeetsAgeCondition(getAgeFromBirthDate(criminals[i].getAttribute('birthdate')), ageEntered) &&
					getAgeFromBirthDate(criminals[i].getAttribute('birthdate')) != -1)

				{showCriminal(i);
				}


		}
	}


	function criminalMeetsAgeCondition(criminalAge, ageEntered)
	{
		var comparator = document.getElementById('sel_byo').value;

		switch(comparator){
			case "ageNull":
				return true;
			case "gt":
				return (criminalAge > ageEntered || ageEntered == "");
			case "lt":
				return (criminalAge < ageEntered || ageEntered == "");
			case "gte":
				return (criminalAge >= ageEntered || ageEntered == "");
			case "lte":
				return (criminalAge <= ageEntered || ageEntered == "");
			case "equ":
				return (criminalAge == ageEntered || ageEntered == "");
		    default:
		        return false
		}
	}

	function criminalHasConditions(criminal, conditions)        //take set of conditions and return whether criminal possesses
	{
		if(conditions.length == 0)	{return true;}                //no conditions of this type exist for this criminal

		for(var j=0; j<conditions.length; j++){                  //cycle through all possible values of this condition
			if(criminalHasCondition(criminal, conditions[j])) {return true; }} //check if condition for criminal has condition instance
	}

	function criminalHasCondition(criminal, condition)
	{
		if(!condition) return false;    //condition invalid, return

		for(var i=0; i<criminal.attributes.length; i++)     //From all of the criminal's attributes...
			if(!criminal.attributes[i]) { return false;}    
			else if(criminal.attributes[i].name.toUpperCase() == condition.name.toUpperCase() && criminal.attributes[i].value.toUpperCase() == condition.value.toUpperCase()) { return true;}
			else;// {document.getElementById('status').innerHTML += criminal.attributes[i].value + " " + condition.value + "<br />"; }
	}

	function IEJS()
	{
		document.write("<br />");
	}

/* *************** Age conditionals ************************** */

	function changeAgeCriteria(criteria)
	{
		if(criteria == 'byYearsOld') {
			showElementById('sel_byo');
			showElementById('yearsLabelRight');
			hideElementById('sel_bby');
			hideElementById('yearsLabelLeft');}

		else{
			showElementById('sel_bby');
			showElementById('yearsLabelLeft');
			hideElementById('sel_byo');
			hideElementById('yearsLabelRight');}

	}


	function getYearFromBirthdate(b)
	{
		if(b.length < 8) return -1;

		return ("19" + b.substr(6,2));
	}

	function getAgeFromBirthDate(b)
	{
		if(b.length == 2) return b;         //age is explicity (e.g. 40)
		else if(b.length < 8) return -1;    //dob is not correctly formatted

		var birthDate = new Date();         //a base date obj to manipulate below
		var currentDate = new Date();       //subtraction used with this to determine age

		birthDate.setFullYear("19" + b.substr(6,2),b.substr(0,2) - 1,b.substr(3,2));    //sets birthdate based on input string (mm/dd/yy)
		return (new String((currentDate - birthDate)/31536000000)).substr(0,2);         //value derived from converting msec to years
	}


/* ********* Criminal Generics *************** */

	function showCriminal(index)
	{
		criminals[index].parentNode.parentNode.style.display = 'block';
		//criminal_names[index].parentNode.parentNode.style.display = 'block';
	}

	function hideCriminal(index)
	{
		criminals[index].parentNode.parentNode.style.display = 'none';
		//criminal_names[index].parentNode.parentNode.style.display = 'none';
	}

	function hideAllCriminals(){
		for(var i=0; i<criminals.length; i++){
			hideCriminal(i);}}

	function showAllCriminals(){
		for(var i=0; i<criminals.length; i++){
			showCriminal(i);}}

/* *********************************************
	Generics
************************************************ */
	function getElementsByClassName(oElm, strTagName, oClassNames){
		var arrElements = (strTagName == "*" && document.all)? document.all : oElm.getElementsByTagName(strTagName);
		var arrReturnElements = new Array();
		var arrRegExpClassNames = new Array();
		if(typeof oClassNames == "object"){
			for(var i=0; i<oClassNames.length; i++){
				arrRegExpClassNames.push(new RegExp("(^|\\s)" + oClassNames[i].replace(/\-/g, "\\-") + "(\\s|$)"));
			}
		}
		else{
			arrRegExpClassNames.push(new RegExp("(^|\\s)" + oClassNames.replace(/\-/g, "\\-") + "(\\s|$)"));
		}
		var oElement;
		var bMatchesAll;
		for(var j=0; j<arrElements.length; j++){
			oElement = arrElements[j];
			bMatchesAll = true;
			for(var k=0; k<arrRegExpClassNames.length; k++){
				if(!arrRegExpClassNames[k].test(oElement.className)){
					bMatchesAll = false;
					break;
				}
			}
			if(bMatchesAll){
				arrReturnElements.push(oElement);
			}
		}
		return (arrReturnElements)
	}

	function showElementById(id){
		document.getElementById(id).style.display = 'block';}

	function hideElementById(id){
		document.getElementById(id).style.display = 'none';}

	function toggleDisplay(id){
		var target = document.getElementById(id);
		if(target.style.display = 'none')		{showElementById(id);}
		else									{hideElementById(id);}
	}

/* *********************************************** */


