/*
Form validation
*/

var validation = new Object();
validation = {
	
	inputObj : new Object(),
	
	config : {
	 // jquery string to retrieve the submit button	
	  submitButton : ".submitbutton input", 
	 // the id of the div containing the list of invalid fields 
	  invalidList :  "#validationErrors",     
          requiredLabel: "wrn-label",   
	 // this is the class which should be placed on the warning span
	  invalidSpan : "status",  
	 // this is the class that should be placed on the containing div             
	  invalidDiv :  "invalid",
	 // Sets if form should be continously validated "y" or "n"
	  continousValidation : "n",
	 // Sets if the warning list should contain quicklink to invalid input elements            
	  quickLinks : "y",
	 // What string should be printed in the warning list before and after the label 
	  errorMsg : {
		empty1 : "Reiturinn",
		empty2 : "er tómur",
		invalid1: "Reiturinn",
		invalid2: "er ófullkomin"		
	  }
    },
    
    // settings fot inputfields 
    // 1 = method that validates the field
    // 2 = jquery string to detect input type
    // 3 = event that input field responds to in case of contiousValidation
    inputTypes :  new Array(
	 [ "textValidate", "input[type='text']", "keyup" ],
	 [ "checkboxRadioValidate", "input[type='radio']", "click"],
	 [ "checkboxRadioValidate","input[type='checkbox']", "click"],
	 [ "selectValidate" ,"select", "mouseup"],
	 [ "textValidate" ,"textarea", "keyup"]	
    ),
	
	// Functions that validate text input
	valFunctions : {
	    val_email : function(obj){
              var re = new RegExp("^[a-z0-9\._-]+@[A-Za-z0-9\._-]+?[\.]{1}[a-z]{2,4}$","gi");
              var str = obj.inputElem[0].value;
              var e = re.exec(str);
              if (e == null) { return false; } else { return true;}
	   },

		val_number : function(obj){
		  var regxpObj = new RegExp("(^[0-9]+$)");
	      return regxpObj.test(obj.inputElem[0].value);
		},

	    val_number_length : function(obj){
		  var valStr = obj.divContainer[0].className.match('val_number_length-[0-9]*');
	      var len = valStr[0].match('[0-9]*$')[0];
	      var baseExp =  "^[0-9]{?}$";
	      var newExp = baseExp.replace(/[?]/,len);
	      var regxpObj = new RegExp(newExp);
	      return regxpObj.test(obj.inputElem[0].value); 
	    },

	    val_dateformat_ddmmyyyy : function(obj){
	      var regxpObj = new RegExp("(^[0-2][1-9]|^[3][0-1])(\.)([0-1][0-2])(\.)[12][0-9]{3}$");
	      return regxpObj.test(obj.inputElem[0].value);
	    },

	    val_creditcard : function(obj){
	      var regxpObj = new RegExp("^[0-9]{16}$");
	      return regxpObj.test(obj.inputElem[0].value);	
	    }
	  },
	
	// Initializes form
	init : function(){
		$('.required').each(function(i){
		  // Loop through div with class="required" and setting their input type and then store them in inpObj
		  var currentDiv = $(this);
		  if(currentDiv.children().length != 0){	
			validation.inputObj[i] = new Object();
			validation.inputObj[i].divContainer = currentDiv;
			
			$.each(validation.inputTypes, function(j, n){
				// find input, select or textarea in each currentDiv and put it into the inputObj object
				var inputElem = currentDiv.find(validation.inputTypes[j][1]);
				if(inputElem[0] != undefined){
					validation.inputObj[i].inputType = validation.inputTypes[j][0];
					validation.inputObj[i].inputElem = inputElem;

					if(validation.config.continousValidation == "y")
					validation.setContinousValidation(validation.inputTypes[j], validation.inputObj[i]);

				}

			});
          }		
	    });	
		this.setSubmitButton();
	},
	
	// Attatch the correct event to the submit button
	setSubmitButton : function(){
		// setting submit button if the button exists
		var submitButton = $(validation.config.submitButton);
		// An onclick eventhandler is assigned if one is not already assigned 
		if(submitButton[0].onclick == undefined){
		  $(submitButton).click(function(){ validation.validate() });	
		}
		// if an eventhandler is already assigned a new button is created and assigned an eventhandler, the existing event is stored
		// as "defaultSubmit" property on the button to later be called after validation has occurd
		else{
		  var submitDiv = submitButton.parent();
		  var buttonValue = submitButton.attr("value");
		  var buttonType =  submitButton.attr("type");
		  var buttonClass =  submitButton.attr("class");
		  var defaultSubmit = submitButton[0].onclick;
		  submitButton.remove();
		  newSubmitButton = $('<input type='+buttonType+' value='+buttonValue+' class='+buttonClass+' >');  //ATH escape character fyrir quote !
		  newSubmitButton.appendTo(submitDiv);
		  newSubmitButton[0].defaultsubmit = defaultSubmit;
		  newSubmitButton.click(this.validate);
		}					
	},
	
	setContinousValidation : function(inputType ,obj){
				
		validation.showStatus("invalid", obj);
		var eventType = inputType[2];
		var methodStr = inputType[0];
		obj.inputElem[eventType](function(){ 
		  validation.showStatus(validation[methodStr].call(validation, obj), obj);
	    });
	},
	
	// Create the message list with the validation results
	drawValidationResults : function(invalidFields){
	
		var list = $("<ul></ul>");
		var warningDiv = $(this.config.invalidList);
    warningDiv.removeClass("no-disp");
    warningDiv.children("ul").remove("ul");

		$.each(invalidFields, function(i){
		  var label;
                  if(invalidFields[i].divContainer.find("."+validation.config.requiredLabel)[0]!= undefined)
                    label =  invalidFields[i].divContainer.find("."+validation.config.requiredLabel).html();
                  else{	
                    if(invalidFields[i].inputType == "checkboxRadioValidate")
		      label = invalidFields[i].divContainer.find("legend").html();
		    else
		      label = invalidFields[i].divContainer.find("label").html();
		  } 
		  var errorMsg = invalidFields[i].errorMsg.split(",");
		  warningLink = $("<li>"+errorMsg[0]+" "+label+" "+errorMsg[1]+"</li>");
			
		  if(validation.config.quickLinks == "y"){
		    warningLink.click( function(){
			invalidFields[i].inputElem[0].focus();
		    });
		  }
		list.append(warningLink);
		});
		warningDiv.append(list);
                
		
	},
	
	// Change class of the div container when validation occurs
	showStatus : function(status, obj){
		
	  if(this.config.invalidDiv != undefined){
	    if(status > 0)
		  obj.divContainer.addClass(this.config.invalidDiv);
		else
	      obj.divContainer.removeClass(this.config.invalidDiv);
	  }
	},
	
	// Validate text field
	textValidate : function(obj){
      
      var valFunction  = obj.divContainer[0].className.match('val_[a-z0-9_]*');
      // Check if empty
	  if(obj.inputElem[0].value == "")
	    return 1;
	  // Run additional validation if input element has a validation function in the class name 
	  else if(valFunction != null){
		if( this.valFunctions[valFunction[0]].call(this, obj) == false)
	      return 2;
	    else
	      return 0;
	   }
	   else
	      return 0;
	   
	},
	
	// Validate checkbox and radio buttons
	checkboxRadioValidate : function(obj){
	  
	  if(obj.divContainer.find("input[checked]")[0] == undefined)
	    return 1;
	  else
	    return 0;		
    },
	
	// Validate select-one elements
	selectValidate : function(obj){
		
	  if(obj.inputElem[0].selectedIndex == 0)
        return 1;
	  else
	    return 0;
		
	},
	
	// Validate the form
	validate : function(){
	  
	  // Collect invalid fields and call showStatus
	  var invalidFields = new Array();
	  var count = 0;
       $.each(validation.inputObj ,function(i,n){
	   if(validation.inputObj[i].inputElem.parents(".hidden").length == 0){
		var parent = validation.inputObj[i].inputElem.parents(".hidden");
	       var methodStr = validation.inputObj[i].inputType;
           var validationStatus = validation[methodStr].call(validation, validation.inputObj[i]);
	       validation.showStatus(validationStatus, validation.inputObj[i]);
	       if(validationStatus > 0){
		     invalidFields[count] = validation.inputObj[i];
		   
		    if(validationStatus == 1)
		      invalidFields[count].errorMsg = validation.config.errorMsg.empty1+","+validation.config.errorMsg.empty2; 
		    else if(validationStatus == 2)
		      invalidFields[count].errorMsg = validation.config.errorMsg.invalid1+","+validation.config.errorMsg.invalid2;
	       
	        count++;	
           }
          }
	   });
	 
	 // Create message list  
	 if(validation.config.continousValidation != "y" )
	    validation.drawValidationResults(invalidFields);
	 
	// Submit form - first check if input button has an existing event that needs to be called 	
	 if(invalidFields.length == 0){
	   if(this.defaultsubmit == undefined){
	      var form = $(validation.inputObj[0].inputElem[0]).parents("form");
	      form[0].submit();
	    }
	    else{
	      this.defaultsubmit.call();		
	    }
      }
	}	
};


/*
Allows two radiobutton to toggle the display of other elements.

--parameters--
trigger:
is the class of the element which contians the two radiobuttions

toggleElem:
is the class name of those elements that should react to the toggle,
these elements must be following siblings to the trigger element
      
*/


var radioToggle = new Object();

  radioToggle = {
	config:{
	  trigger: "radiotoggle",
	  toggleElem: "rt-hide"	
		
	},
	
	
  init:  function(){
	
	$("."+this.config.trigger).each(function(){
            
      var fields = radioToggle._getAdjecentSiblings(this, radioToggle.config.toggleElem);
	  $(fields).each(function(){ this.addClass("hidden"); });

	  var radio = $(this).find("input[type=radio]");
      if(radio.length == 2){
	    $(radio[0]).click(function(){ $(fields).each(function(){ this.removeClass("hidden"); });});
	    $(radio[1]).click(function(){ $(fields).each(function(){ this.addClass("hidden"); });});
	  }
	  else{
		radio.click(function(){ $(fields).each(function(){ this.removeClass("hidden"); });});
	  }
	 
	 });
  },

  	_getAdjecentSiblings: function(obj, className){
	
	  	var fields = new Array($(obj).next());
		  var i = 0;
		  while($(fields[i]).next().is("."+className)){
			  fields[i+1] = fields[i].next();
			  i++; 
		  }
		  return fields;
	}
}  
    

/*
Creates a cascade of elements where hidden elements are shown one at a time on the event of a click 
-- param --
triger:
class name of the parent element containing the controls which hide and display other elements and 
should be structured as in the example

add:
class of the li element that displays elements

remove:
class of the li element the hides elements

cascadeElement:
class of the elements which should be part of the cascade. MUST be followin siblings to the element 
containing the trigger
    
		<div class="cascade">
			<ul>
			<li class="cascade-add">+ Add item</li>
			<li class="cascade-remove">-Remove item</li>
			</ul>
		</div>
		<fieldset class="cascade-elem"> ..<fieldset>
		.
		.
		<fieldset class="cascade-elem"> ..<fieldset>

*/
var cascade = new Object();
cascade = {
  config:{
  triger: "cascade",
	add: "cascade-add",
	remove: "cascade-remove",
	inActiveClass: "dormant",
	cascadeElement: "cascade-elem"
  },
	
  init: function(){
	  
    $("."+this.config.triger).each(function(){
    	var obj = this;
	    var cElem = cascade._getAdjecentSiblings(obj, cascade.config.cascadeElement);
	    var ctrl = $(this).find("ul");
	    ctrl.children("li").click(function(){ cascade._addRemove(this, cElem);});
	      $(cElem).each(function(i){
	        $(this).addClass("hidden");
	        var newCtrl = ctrl.clone();
	        $(this).prepend(newCtrl);
	        var li = newCtrl.children("li");
	        li.click(function(){ cascade._addRemove(this, cElem);});
	        li.removeClass(cascade.config.inActiveClass);
	        if($(cElem).size() == (i+1)){
	        	$(li[0]).addClass(cascade.config.inActiveClass);
	        }
	       });
	   	
	    });
    },

    _getAdjecentSiblings: function(obj, className){
	
	  	  var fields = new Array($(obj).next());
		  var i = 0;
		  while($(fields[i]).next().is("."+className)){
			  fields[i+1] = fields[i].next();
			  i++; 
		  }
		  return fields;
	},
   
   _addRemove: function(link, cElem){
	// add fields 
	if($(link).attr("class").search(cascade.config.add) != -1){
	  for(var i = 0; i < cElem.length; i++){
	    if($(cElem[i]).attr("class").search("hidden") != -1){
		  $(cElem[i]).removeClass("hidden"); 
		    break; 
		  }
	  }
	} 
	
	// remove fields
	if($(link).attr("class").search(cascade.config.remove) != -1 && $(link).attr("class").search(cascade.config.inActiveClass) == -1){
	  for(var i = cElem.length-1 ; i >= 0; i--){
		  if($(cElem[i]).attr("class").search("hidden") == -1){
		    $(cElem[i]).addClass("hidden");
		    break; 
		  }
	  }
	} 
  }
}
























