/* Page Load Event Manager */
function addLoadEvent(func) {
  var oldonload = window.onload;
  if (typeof window.onload != 'function') {
    window.onload = func;
  } else {
    window.onload = function() {
      if (oldonload) {
        oldonload();
      }
      func();
    }
  }
}

/* DOM Loaded Event Manager */
function addDOMLoadEvent(func) {
   if (!window.__load_events) {
      var init = function () {
          // quit if this function has already been called
          if (arguments.callee.done) return;
      
          // flag this function so we don't do the same thing twice
          arguments.callee.done = true;
      
          // kill the timer
          if (window.__load_timer) {
              clearInterval(window.__load_timer);
              window.__load_timer = null;
          }
          
          // execute each function in the stack in the order they were added
          for (var i=0;i < window.__load_events.length;i++) {
              window.__load_events[i]();
          }
          window.__load_events = null;
      };
   
      // for Mozilla/Opera9
      if (document.addEventListener) {
          document.addEventListener("DOMContentLoaded", init, false);
      }
      
      // for Internet Explorer
      /*@cc_on @*/
      /*@if (@_win32)
          document.write("<scr"+"ipt id=__ie_onload defer src=//0><\/scr"+"ipt>");
          var script = document.getElementById("__ie_onload");
          script.onreadystatechange = function() {
              if (this.readyState == "complete") {
                  init(); // call the onload handler
              }
          };
      /*@end @*/
      
      // for Safari
      if (/WebKit/i.test(navigator.userAgent)) { // sniff
          window.__load_timer = setInterval(function() {
              if (/loaded|complete/.test(document.readyState)) {
                  init(); // call the onload handler
              }
          }, 10);
      }
      
      // for other browsers
      window.onload = init;
      
      // create event function stack
      window.__load_events = [];
   }
   
   // add function to event stack
   window.__load_events.push(func);
}


/* Form Submit Event Manager */
function addFormOnSubmit(form, func) {
	form = checkElement(form);
	var oldfsub = form.onsubmit;
	if (typeof form.onsubmit != 'function') {
	form.onsubmit = func;
	} else {
		form.onsubmit = function() {
		if (oldfsub) {
			oldfsub();
		}
		return func();
		}
	}
}

//Event Handler
function addEvent(element, type, handler) {
	//console.group('Function: addEvent');
	//console.info('Parameters:\nelement: ' + element + '\ntype: ' + type + '\nhandler: ' + handler);
	//console.log(element);
	element = checkElement(element);
	//console.log(element);
	if (typeof element == "undefined" || !element) {
		//console.log('No Element defined');
		//console.groupEnd();
		return false;
	}
	if (element.addEventListener) {
		element.addEventListener(type, handler, false);
	} else {
		// assign each event handler a unique ID
		if (!handler.$$guid) handler.$$guid = addEvent.guid++;
		// create a hash table of event types for the element
		if (!element.events) element.events = {};
		// create a hash table of event handlers for each element/event pair
		var handlers = element.events[type];
		if (!handlers) {
			handlers = element.events[type] = {};
			// store the existing event handler (if there is one)
			if (element["on" + type]) {
				handlers[0] = element["on" + type];
			}
		}
		// store the event handler in the hash table
		handlers[handler.$$guid] = handler;
		// assign a global event handler to do all the work
		element["on" + type] = handleEvent;
	}
	//console.groupEnd();
}
// a counter used to create unique IDs
addEvent.guid = 1;

function removeEvent(element, type, handler) {
	if (element.removeEventListener) {
		element.removeEventListener(type, handler, false);
	} else {
		// delete the event handler from the hash table
		if (element.events && element.events[type]) {
			delete element.events[type][handler.$$guid];
		}
	}
};

function handleEvent(event) {
	var returnValue = true;
	// grab the event object (IE uses a global event object)
	event = event || fixEvent(((this.ownerDocument || this.document || this).parentWindow || window).event);
	// get a reference to the hash table of event handlers
	var handlers = this.events[event.type];
	// execute each event handler
	for (var i in handlers) {
		this.$$handleEvent = handlers[i];
		if (this.$$handleEvent(event) === false) {
			returnValue = false;
		}
	}
	return returnValue;
};

function fixEvent(event) {
	// add W3C standard event methods
	event.preventDefault = fixEvent.preventDefault;
	event.stopPropagation = fixEvent.stopPropagation;
	return event;
};
fixEvent.preventDefault = function() {
	this.returnValue = false;
};
fixEvent.stopPropagation = function() {
	this.cancelBubble = true;
};

function getElementsByClassName(cssClass, tag, parentEl) {
	//Setup tag
	tag = tag || '*';
	//If no parent element is set, document as parent
	if (typeof parentEl == 'string')
		parentEl = checkElement(parentEl);
	parentEl = parentEl || document;
	//Get all Elements under parent element
	var els = parentEl.getElementsByTagName(tag);
	//Loop through elements and find elements with matching class names
	var matched = new Array(),
			currEl;
	//var re = new RegExp('(^|\\s)' + cssClass + '($|\\s)');
	var re = buildAttributeRegEx(cssClass);
	for (var x = 0; x < els.length; x++) {
		currEl = els[x];
		if (re.test(currEl.className))
			matched.push(currEl);
	}
	return matched;
}

function buildAttributeRegEx(searchString, flags) {
	if (typeof flags == 'undefined')
		flags = "";
	var re = new RegExp('(?:^|\\b)' + searchString + '(?:$|\\b)', flags);
	//var re = new RegExp('(?:^|\\s)' + searchString + '(?:$|\\s)', 'g');
	return re;
}

function getStyle(oElm, strCssRule){
    var strValue = "";
    if(document.defaultView && document.defaultView.getComputedStyle){
        strValue = document.defaultView.getComputedStyle(oElm, "").getPropertyValue(strCssRule);
    }
    else if(oElm.currentStyle){
        strCssRule = strCssRule.replace(/\-(\w)/g, function (strMatch, p1){
            return p1.toUpperCase();
        });
        strValue = oElm.currentStyle[strCssRule];
    }
    return strValue;
}


/*Element Height Equalizer
 * Element IDs are listed as pairs
 * If an element is nested (and the height of the parent element should be considered),
 *	the parent element's ID should also be provided
 * Elements are provided as parameters to the function
 * Elements are separated by a ',' character
 * Parent elements are attached to the child element with a '|' character
 *
 * Example: eqH('elementOne,elementTwo|parentTwo');
 */
function eqH_ext() {
	console.group('Function: eqH_ext');
	console.info('Parameters:');
	console.log(arguments);
	//Cancel processing if no arguments were passed
	if (arguments.length < 1)
		return false;
	//Process element groups
	console.group('Processing Element Groups');
	var splitArr, elSplit, argIsString;
	var adjustHeightElements = new Array('padding-top', 'padding-bottom', 'border-top-width', 'border-bottom-width');
	for (i = 0; i < arguments.length; i++) {
		argIsString = (typeof arguments[i] == "string") ? true : false;
		console.group('Argument: ' + (i + 1) + ' of ' + arguments.length);
		console.info('Argument is a string: %s', argIsString);
		var nestArr = new Array();
		var elHeights = new Array();
		var adjustHeight;
		var mx = {val: -1, el: ""};
		//Remove all spaces from argument
		if (argIsString) {
			console.log('Original Argument: %s', arguments[i]);
			arguments[i] = arguments[i].replace(/ /g, '');
			console.log('Trimmed Argument: %s', arguments[i]);
		}
		//Split elements
		splitArr = (argIsString) ? arguments[i].split(',') : arguments[i];	
		console.info('Split Argument %d: %o', i, arguments[i]);
		console.info('Elements in Group: ' + splitArr.length);
		//Skip this iteration if there are not at least 2 elements
		if (splitArr.length < 2)
			continue;
		//Process Element Groups
		for (x = 0; x < splitArr.length; x++) {
			console.group('Current Element: %o', splitArr[x]);
			splitArr[x] = {el: splitArr[x]};
			console.log('Converted to object member: %o', splitArr[x]);
			//Get parents of elements
			if (argIsString) {
				if (splitArr[x].el.search("|") != -1) {
					elSplit = splitArr[x].el.split("|", 2);
					splitArr[x].el = elSplit[0];
					
					splitArr[x].parent = document.getElementById(elSplit[1]);
					if (null != splitArr[x].parent) {
						splitArr[x].parent.height = splitArr[x].parent.offsetHeight;
						console.log(splitArr[x].el + ' Parent: ' + splitArr[x].parent.id + '\nHeight: ' + splitArr[x].parent.height);
						//Compare Parent Height to other elements
						if (splitArr[x].parent.height > mx.val) {
							mx.val = splitArr[x].parent.height;
							mx.el = splitArr[x].el;
						}
					}
				}
			}
			//Get height of each element
			splitArr[x].el = checkElement(splitArr[x].el)
			if (null != splitArr[x].el) {
				splitArr[x].height = splitArr[x].el.offsetHeight;
				console.log(splitArr[x].el.id + ' Height: ' + splitArr[x].height);
			}
			//Compare Element Heights
			if (splitArr[x].height > mx.val) {
				mx.val = splitArr[x].height;
				mx.el = splitArr[x].el;
			}
			console.log('Max Height: ' + mx.val + '\nElement: ' + mx.el.id);
			//alert('Tallest Element\n' + mx.el.id + '\nHeight: ' + mx.val + '\nCurrent Element\n' + splitArr[x].el.id + '\nHeight: ' + splitArr[x].height);
			console.groupEnd();		
		}
		//Equalize Heights of Elements in Group
		console.group('Compare Heights of Elements in Group');
		for (x = 0; x < splitArr.length; x++) {
			console.group('splitArr Index: ' + x);
			//console.info('Current Element: ' + splitArr[x].el.id);
			if (splitArr[x].el != mx.el) {
				//console.log(splitArr[x].el.id + ' is smaller than ' + mx.el.id + '\nHeight: ' + splitArr[x].height + '\nMax Height: ' + mx.val);
				newH = (null != splitArr[x].parent) ? mx.val - splitArr[x].parent.height + splitArr[x].height : mx.val;
				console.log('New height: ' + newH);			
				//Compensate for padding/borders
				adjustHeight = 0;
				for (aH = 0; aH < adjustHeightElements.length; aH++) {
					//alert(splitArr[x].el.id + '\n' + adjustHeightElements[aH] + '\n' + getStyle(splitArr[x].el, adjustHeightElements[aH]) + '\nInt: ' + parseInt(getStyle(splitArr[x].el, adjustHeightElements[aH])));
					valTemp = parseInt(getStyle(splitArr[x].el, adjustHeightElements[aH]))
					console.log('Property: %s\nValue: %s', adjustHeightElements[aH], getStyle(splitArr[x].el, adjustHeightElements[aH]));
					adjustHeight += (valTemp > 0) ? valTemp : 0;
					//alert(adjustHeight);
				}
				//alert(splitArr[x].el.id + '\nNew Height: ' + newH + '\nAdjustment: ' + adjustHeight + '\nFinal: ' + (newH - adjustHeight).toString());
				newH -= adjustHeight;
				//alert(newH);
				//Set new height for Element
				splitArr[x].el.style.height = newH + 'px';
			}
			console.groupEnd();
		}
		console.groupEnd();
		console.groupEnd(); //Argument Loop
	}
	console.groupEnd();
	console.groupEnd();
}

//DIV Height Equalizer
function eqH(one, two, nested) {
	//Get columns to be compared
	var c1 = document.getElementById(one);
	var c2 = document.getElementById(two);
	
	//Remove Height (if set)
	c1.style.height = "";
	c2.style.height = "";
	
	//alert('Equalizing: ' + one + '(' + c1.offsetHeight + ') and ' + two + '(' + c2.offsetHeight + ')');
	
	//alert(one + ': ' + c1.offsetHeight + '\n' + two + ': ' + c2.offsetHeight);
	
	//Determine which column is taller
	//Debug - alert(one + ": " + c1.offsetHeight + "\n" + two + ": " + c2.offsetHeight);
	if ( c1.offsetHeight == c2.offsetHeight ) {
		//Debug - alert('Column heights are equal');
		return false;
	}
	if ( c1.offsetHeight > c2.offsetHeight ) {
		mx = c1.offsetHeight;
		sm = c2;
	} else {
		mx = c2.offsetHeight;
		sm = c1;
	}
	
	//Get Border-top/bottom of smaller column
	brdTop = getStyle(sm, "border-top-width");
		//Trim Value
	brdTop = parseFloat(brdTop.substr(0, (brdTop.length - 2)));
	if ( isNaN(brdTop) ) brdTop = 0;
	brdBottom = getStyle(sm, "border-bottom-width");
		//Trim Value
	brdBottom = parseFloat(brdBottom.substr(0, (brdBottom.length - 2)));
	if ( isNaN(brdBottom) ) brdBottom = 0;
	brdWidth = brdTop + brdBottom;
	
	//Get Padding-top/bottom of smaller column
	pdTop = getStyle(sm, "padding-top");
		//Trim value
	pdTop = parseFloat(pdTop.substr(0, (pdTop.length - 2)));
	if ( isNaN(pdTop) ) pdTop = 0;
	pdBottom = getStyle(sm, "padding-bottom");
		//Trim Value
	pdBottom = parseFloat(pdBottom.substr(0, (pdBottom.length - 2)));
	if ( isNaN(pdBottom) ) pdBottom = 0;
	pdTotal = pdTop + pdBottom;
	//Debug - alert("Border size: " + brdWidth);
	mx -= (brdWidth + pdTotal);
	
	//Set shorter column to the same height as the taller column
	//alert("New height of taller column: " + mx);
	if ( typeof nested != "undefined" && (c2.offsetHeight > c1.offsetHeight) ) {
		//Debug - alert("Column 2 is taller than Column 1");
		sm = document.getElementById(nested);
		mx -= 57;
	}
		
	//Debug - alert("New Height: " + mx);
	sm.style.height = mx + 'px';
}

function resetFH() {
	//console.group('Function: resetFH()');
	//Quickly Get Height of Form
	set_height = document.getElementById('fhot_form').style.height;		
	document.getElementById('fhot_form').style.height = "";
	ff_height = document.getElementById('fhot_form').offsetHeight;
	//document.getElementById('fhot_form').style.height = set_height;
	eqH('FindHotel', 'NearbyHotels', 'fhot_form');
	//console.groupEnd(); //resetFH()
}

//---------
//OnTabSelectedHandler
//Handle the tab selection to show either city or Airport
//---------
 function OnTabSelectedHandler(tabs, lblCity, lblAirport,ptxtCityAirport,pddlCities) {
	//Get Elements
	city = document.getElementById(lblCity);
	airport = document.getElementById(lblAirport);
	txtAirport = document.getElementById(ptxtCityAirport);
	ddlCities = document.getElementById(pddlCities);
	ts = document.getElementById(tabs);
	//Get Links in Tabstrip
	as = ts.getElementsByTagName('a');
	//Display text based on selected tab
    if (as[0].className == 'selected') {
      city.style.display='';
      ddlCities.style.display='';
      
      airport.style.display='none';
      txtAirport.style.display='none';
      txtAirport.value = ddlCities.options[ddlCities.selectedIndex].value;
	} else {
      city.style.display='none';
      ddlCities.style.display='none';
      
      airport.style.display='';  
      txtAirport.style.display='';  
      txtAirport.value = ""
	}  
 }
 
 //Displays Element
 function showIt(el, disp) {
	setVisibility(el, 1, disp);
 }
 
 //Hides Element
 function hideIt(el, disp) {
	setVisibility(el,0,disp);
 }
 
 //Set Visibility
function setVisibility(el, viz, disp) {
	var element = (typeof(el) == 'string') ? document.getElementById(el) : el;
	var visibility = (viz == 1) ? "visible" : "hidden";
		if (element) {
		element.style.visibility = visibility;
		if (disp != undefined)
			element.style.display = disp;
	}
}

//General Form Validation Error Checker
//Checks to see if any form validation error messages were passed and displays them
function checkError(err) {
	err.msg = checkElement(err.msg);
	err.box = checkElement(err.box);
	//alert('Message: ' + err.msg.style.visibility + '\nBox: ' + err.msg.style.display);
	if (err.msg.style.visibitlity != 'hidden' && err.msg.style.display != 'none')
		showIt(err.box, err.displayType);
	else
		hideIt(err.box, '');
}

//Checks to see if any error messages were passed and displays them
function checkErrors() {
	//Check vCountry
	vc = document.getElementById('vcountry');
	cmsg = vc.getElementsByTagName('span')[0];
 	//Check Hotel Name
 	hn = document.getElementById('vhotel');
	hmsg = hn.getElementsByTagName('span')[0];
	
	//alert('Country: ' + cmsg.style.visibility + '\nHotel Name: ' + hmsg.style.visibility);
	vc.style.display = (cmsg.style.visibility == 'visible') ? 'block' : 'none';
	hn.style.display = (hmsg.style.visibility == 'visible') ? 'block' : 'none';

	retval = ( (cmsg.style.visibility != 'hidden') || (hmsg.style.visibility != 'hidden') ) ? false : true;
	
	return retval;
};

function referFormCheck() {
	//Set Error Order
	var hasError = -1;
	var errorOrder = new Array(2, 0, 1, 3);
	//Get Error Message Elements
	re = document.getElementById('refer_errors');
	reboxes = re.getElementsByTagName('div');
	respans = re.getElementsByTagName('span');
	//Check message visibility
	for (i in errorOrder) {
		if (respans[errorOrder[i]].style.display != 'none') {
			hasError = errorOrder[i];
			reboxes[errorOrder[i]].style.display = 'block';
			break;
		}	
	}
	//Hide all other boxes
	for (i = 0; i < reboxes.length; i++) {
		if (i != hasError)
			reboxes[i].style.display = 'none';
	}
	return (hasError == -1) ? true : false;
}

function registerClick(el) {
	if (typeof(el) == 'string')
		var el = document.getElementById(el);
	lastClicked = el;
	//alert('Last Clicked: ' + lastClicked.id);
}

function userFormCheck() {
	//alert(lastClicked);
	var error_signin = document.getElementById('error_signin');
	var error_join = document.getElementById('error_join');
	var eSel;
	var eHide;
	var retVal = true;
	var msgs = new Array();
	var jmsgs = new Array();
	var note;
	//Determine which form was submitted
	switch(lastClicked) {
		case btnJoin:
			eSel = error_join;
			eHide = error_signin;
			espans = document.getElementById('Join').getElementsByTagName('span');
			for(i = 0; i < espans.length; i++) {
				if (espans[i].className == 'error_val') {
					//alert('Adding: ' + espans[i].id);
					jmsgs.push(espans[i]);
				}
			}
			break;
		case btnSignIn:
			eSel = error_signin;
			eHide = error_join;
			break;
	}
	//Hide other errors
	hideIt(eHide, 'none');
	//Show selected errors
	var msgs = eSel.getElementsByTagName('span');
	if (msgs.length > 0) {
		for (i = 0; i < msgs.length; i++) {
			if (msgs[i].style.visibility != 'hidden' && msgs[i].style.display != 'none') {
				showIt(eSel, 'block');
				retVal = false;
				break;
			}
		}
	}
	if (jmsgs.length > 0) {
		for (i = 0; i < jmsgs.length; i++) {
			if (jmsgs[i].style.visibility != 'hidden' && jmsgs[i].style.display != 'none') {
				retVal = false;
				break;
			}
		}
	}
	//alert(errorBlock.id);
	eqH('Join', 'SignIn'); eqH('Join', 'jblend'); eqH('Join', 'sblend');
	return retVal;
}

//Expand/Collapse Form Groups
function formAccordion(activator, accordion) {
	var activator = checkElement(activator);
	var accordion = checkElement(accordion);
	if (activator.checked == true)
		showIt(accordion, '');
	else
		hideIt(accordion, 'none');
}

//Checks if element is defined or is string ID of element
function checkElement(el) {
	//console.group('Function: checkElement()');
	//console.info('Parameters\nel: %s', el);
	//console.log('Element Type: %s', (typeof el));
	if (typeof el == 'string') {
		//console.groupEnd();
		return document.getElementById(el);
	} else {
		//console.groupEnd();
		return el;
	}
}

//Return Position of Selected Element
function getPos(el) {
	el = checkElement(el);
	if (el == undefined)
		return false;
	var posX = posY = 0;
	if (el.offsetParent) {
		//Get Initial Values
		posX = el.offsetLeft;
		posY = el.offsetTop;
		//Iterate until coordiates are calculated at the page-level
		while (el = el.offsetParent) {
			posX += el.offsetLeft;
			posY += el.offsetTop;
		}
		//Return coordinates as Array
		return [posX,posY];
	} else
		return false;
}

//Sets the position of an element
function setPos(el, pos) {
	el = checkElement(el);
	el.style.left = pos[0].toString() + 'px';
	el.style.top = pos[1].toString() + 'px';
}

//Registers Text Field
function regTextField(el, val) {
	el = checkElement(el);
	if (!el)
		return false;
	if (!el.value) {
		//Set Text field value
		el.value = val
		//Set onClick Event
		addEvent(el, 'focus', function() {
			if (el.value == val)
				el.value = "";
		});
	}
}

//Limit Characters allowed in Textarea
function setTextareaLimit(el, limit, msg) {
	//console.group('Function: setTextareaLimit');
	//console.info('Parameters:\nel: ' + el + "\nlimit: " + limit);
	el = checkElement(el);
	if(!el)
		return false;
	//console.log("Register onKeyUp Event for " + el.id);
	el.onkeyup = function() {
		countCharacters(el, msg, limit);
		if (el.value.length > limit)
			el.value = el.value.substr(0, limit);
	};
	
	//console.groupEnd();
}

//Gets Multi-Error Boxes
function getErrorsMulti(el, e_class) {
	console.group('Function: getErrorsMulti()');
	console.info('Parameters\nel: ' + el + '\ne_class: ' + e_class);
	el = checkElement(el);
	console.log('el: ' + el);
	//Setup default parent element
	if (!el || typeof el == 'undefined') {
		console.log('No element defined, using document object as parent');
		el = document;
	}
	//Setup class to search for
	if (typeof e_class == 'undefined') {
		console.log('No class specified, using default class');
		e_class = 'error_multi';
		console.log('e_class: ' + e_class);
	}
	//Setup global variables
	if (!('m_children' in window))
		m_children = new Array();
	if (!('e_boxes' in window))
		e_boxes = new Array();
	var all_boxes = el.getElementsByTagName('div');
	var watched_inputs = new Object();
	for (i = 0; i < all_boxes.length; i++) {
		//If element is a multi-box, add it to array
		if (all_boxes[i].className.indexOf(e_class) != -1) {
			e_boxes.push(all_boxes[i]);
			//Attach Array of error messages in element to element (used when checking if errors should be displayed)
			all_boxes[i].e_msgs = new Array();
			//Get error messages contained in multi-box
			console.log('Get error messages contained in multi-box');
			m_children = all_boxes[i].getElementsByTagName('*');
			console.dir(m_children);
			//Check if error message is attached to an input field
			console.group('Iterate through children');
			for (x = 0; x < m_children.length; x++) {
				console.group('Child: ' + x);
				console.log(m_children[x].id);
				//console.log(eval(m_children[x].id));
				if("validationGroup" in m_children[x]) {
					console.log('Validation Group: %s', m_children[x].validationGroup);
					if ("controltovalidate" in m_children[x]) {
						console.log('Control to Validate: %s', m_children[x].controltovalidate);
						if (!(m_children[x].controltovalidate in watched_inputs)) {
							//Add input to list of watched inputs
							watched_inputs[m_children[x].controltovalidate] = "";
							console.log('Added ' + m_children[x].controltovalidate + ' to watched list');
							//Attach event listener to input field attached to error message
							iField = checkElement(m_children[x].controltovalidate);
							if(iField) {
								console.log('Attach Event listener to ' + m_children[x].controltovalidate);
								addEvent(iField, 'change', function() {
									console.log('Blurred: ' + this.id);
									checkErrorsMulti();
								});
							}
						}
					}
					all_boxes[i].e_msgs.push(m_children[x]);	
				}
				console.groupEnd(); //Child x
			}
			console.groupEnd();
		}
	}
	console.log('There are ' + e_boxes.length + ' multi error boxes in form');
	console.dir(e_boxes);
	console.groupEnd(); //getErrorsMulti()
}

//Checks if multi-error boxes should be displayed
function checkErrorsMulti() {
	console.group('Function: checkErrorsMulti');
	var showError;
	var e_children;
	//Display Error boxes
	console.group('Display Error Boxes');
	if (e_boxes.length > 0) {
		console.log(e_boxes.length + ' error boxes to display');
		for (i = 0; i < e_boxes.length; i++) {
			//Reset showError (error indicator)
			showError = 0;
			console.group('Box: ' + i + '\n Check if errors are displayed in box');
			e_children = e_boxes[i].e_msgs;
			console.log('Box contains ' + e_children.length + ' messages');
			console.log('Loop through messages to see if any are visible');
			for (x = 0; x < e_children.length; x++) {
				//Check if error is visible
				if (e_children[x].style.display == 'inline')
					showError = 1;
			}
			if (showError == 1) {
				e_boxes[i].style.display = 'block';
				console.log('There are errors in this box');
			} else {
				e_boxes[i].style.display = 'none';
				console.log('There are no errors in this box');
			}
			console.groupEnd() //Box i
		}
	}
	console.groupEnd(); //Display Error Boxes
	console.groupEnd(); //checkErrorsMulti()
}

//Registers CC form on Page
function registerCC(ccNum, ccType, fBtn, eBox) {
	//Setup CC Types
	setupCCTypes();
	for (var x = 0; x < arguments.length; x++)
		arguments[x] = checkElement(arguments[x]);
	//Add Events to form fields
	//CC Num
	addEvent(ccNum, 'blur', function() {
		if (ccNum.value.length > 0) {
			if (!checkCC(ccNum, ccType))
				showIt(eBox, 'block');
			else
				hideIt(eBox, 'none');
		} else {
			hideIt(eBox, 'none');
		}
	});
	//CC Type
	addEvent(ccType, 'change', function() {
		if (ccNum.value.length > 0) {
			if (!checkCC(ccNum, ccType))
				showIt(eBox, 'block');
			else
				hideIt(eBox, 'none');
		}
	});
	//Save Button
	addEvent(fBtn, 'click', function() {
		if (ccNum.value.length > 0 && ccType.selectedIndex != 0) {
			if (!checkCC(ccNum, ccType)) {
				showIt(eBox, 'block');
			} else
				hideIt(eBox, 'none');
		}
	});
	
	var theform = checkElement('form1');
	
	theform.onsubmit =  function() {
		if (ccNum.value.length > 0 && ccType.selectedIndex != 0) {
			if (!checkCC(ccNum, ccType)) {
				showIt(eBox, 'block');
				return false;
			} else
				hideIt(eBox, 'none');
		}
	};
} //END registerCC

//CC Types Setup
function setupCCTypes() {
	ccTypes = {
						AX: {length: 15, prefix: "1-3,34,37"},
						VI: {length: "13,16", prefix: "4"},
						MC: {length: 16, prefix: "51-55"},
						DC: {length: 14, prefix: "300-305,36,38"},
						DS: {length: 16, prefix: "6011"}
						}
} //END setupCCTypes

//CC Validation
function checkCC(ccNum, ccType) {
	//console.group('Function: ccVal()');
	//console.log('Arguments\nccNum: %s\nccType: %s', ccNum.value, ccType.value);
	var ccLen = 0,
			prefix,
			rStart,
			rEnd,
			preMatch = 0,
			ccSum = 0,
			ccVal,
			auth;
	//Card Type
	//Check if selected card type is supported
	//console.log('Checking Card Type');
	if (!(ccType.value in ccTypes)) {
		//console.warn('Unsupported Card Type - Exiting');
		return false;
	}
	//console.log('Card Type is Valid');
	ccType = ccTypes[ccType.value];
	
	//Set Authorization Algorithm
	auth = ('auth' in ccType) ? ccType.auth : 10;
	
	//Card Number
	//console.log('Checking Card Number');
	//Make sure it is an integer (no other symbols/characters)
	var ccInt = parseInt(ccNum.value);
	//console.log('ccInt: %s', ccInt);
	if (!ccInt || isNaN(ccInt) || ccInt.toString().length < ccNum.length) {
		//console.warn('Number is invalid');
		return false;
	}
	//console.log('Card Number is Valid');
	ccNum = ccInt.toString();
	
	//Check number against card type
	//console.log('Validating Number for Card Type: %s', ccType.value);
	//Length
	//console.log('Length\nNum: %s\nType: %s', ccNum.toString().length, ccType.length);
	//Check if multiple lengths are possible
	ccType.length = ccType.length.toString().split(',');
	for (var x = 0; x < ccType.length.length; x++) {
		if (ccNum.length == ccType.length[x]) {
			ccLen = 1;
			break;
		}
	}
	
	if (!ccLen) {
		//console.warn('Length of number does not match card type');
		return false;
	}
	//Prefix
	//Check for multiple prefixes
	//console.log('Prefix: %s', ccType.prefix);
	ccType.prefix = ccType.prefix.toString().split(',');
	//console.log('New Prefix: %o', ccType.prefix);
	//Iterate through prefixes
	//console.info('Iterating through prefixes');
	for (var i = 0; i < ccType.prefix.length; i++) {
		//console.group('Index: %s\nPrefix: %s\nLength: %s', i, ccType.prefix[i], ccType.prefix.length);
		prefix = ccType.prefix[i];
		//Check for ranges
		if (prefix.toString().indexOf('-') != -1) {
			//console.log('Range of Prefixes found - Splitting');
			preRange = prefix.split('-');
			//console.log(prefix);
			//Skip current iteration if there are not exactly 2 numbers in range (low - high)
			if ( preRange.length != 2 || isNaN(parseInt(preRange[0])) || isNaN(parseInt(preRange[1])) )
				continue;
			//Set range start/end
			for(var rx = 0; rx < preRange.length; rx++)
				preRange[rx] = parseInt(preRange[rx]);
			if (preRange[0] < preRange[1]) {
				rStart = preRange[0];
				rEnd = preRange[1];
			} else {
				rStart = preRange[1];
				rEnd = preRange[0];
			}
			for (var rI = rStart; rI <= rEnd; rI++) {
				//Add to main prefix array
				ccType.prefix.push(rI);
				//console.log('Adding %s to Prefix Array', rI);
			}
			//Exit current iteration
			//console.groupEnd();
			continue;
		}
		//Check Prefix
		//console.log('Checking Prefix');
		prefix = parseInt(prefix);
		if (isNaN(prefix))
			continue;
		if (prefix == ccNum.substr(0, prefix.toString().length)) {
			//console.log('Matching Prefix has been found!');
			preMatch = 1;
			//console.groupEnd();
			break;
		}
		//console.groupEnd();
	}
	if (!preMatch) {
		//console.warn('Prefix was not matched - Exiting');
		return false;
	}
	
	//Check Number
	//console.info('Checking Number: %s', ccNum);
	//console.info('Num type: %s', (typeof ccNum));
	for (var x = (ccNum.length - 1); x >= 0; x--) {
		//console.group('Index: %s\nValue: %d', x, ccNum.charAt(x));
		//Add current value to sum
		ccSum += parseInt(ccNum.charAt(x));
		//console.log('Sum: %d', ccSum);
		if (x == 0 || (x - 1) < 0) {
			//console.groupEnd();
			break;
		}
		x--;
		//console.log('New Index: %s\nNew Value: %s', x, ccNum.charAt(x));
		ccVal = parseInt(ccNum.charAt(x));
		//Double value
		ccVal = ccVal * 2;
		//console.log('Doubled Value: %d', ccVal);
		//Convert to string and add each digit to sum
		ccVal = ccVal.toString();
		for (var i = 0; i < ccVal.length; i++) {
			//console.log('Value: %s', ccVal.charAt(i));
			ccSum += parseInt(ccVal.charAt(i));
			//console.log('New Sum: %d', ccSum);
		}
		//console.groupEnd();
	}
	//Validate Number against algorithm
	if ((ccSum % auth) == 0) {
		//console.log('Card Number is Valid! - Exiting');
		return true;
	}
	
	//console.warn('Card Number is Invalid!\nReturn: %s', (ccSum % auth));
	
	//console.groupEnd(); //Function Group
} //END ccVal

//Enhances Error Messages
function buildErrorMessages() {
	var eMsg,
			eMulti = false,
			eContent,
			eChildren,
			eImgSrc = 'images/images/error_icon.gif',
			eImg,
			eBox,
			eBoxClass = 'error_box',
			eSpan,
			eSpanClass = 'error_msg';
	//console.group('Function: Error Message Enhancement');
	//console.log('Get all SPAN elements');
	var e_msgs = getElementsByClassName('error_wrap');
	//console.info('Error Messages on page: %d', e_msgs.length);
	//console.group('Add wrapper to error_msgs');
	for (var x = 0; x < e_msgs.length; x++) {
		/* innerHTML Method
		//console.info('Element: %d - %o', x, e_msgs[x]);
		eMsg = e_msgs[x];
		//console.log('Get innerHTML: %s', eMsg.innerHTML);
		eContent = eMsg.innerHTML; 
		//console.log('Expand Content in Error Box');
		eContent = '<div class="error_box">\n<img src="images/error_icon.gif" />\n<span class="error_msg">' + eContent + '</span>\n</div>';
		//console.log('Add Expanded content back to error message\n %s', eContent);
		eMsg.innerHTML = eContent;
		*/
	
		/* DOM Method */
		//console.group('Element: %d - %o', x, e_msgs[x]);
		eMsg = e_msgs[x];
		//console.log('Get all elements inside current element');
		eChildren = eMsg.childNodes;
		//console.log(eChildren);
		//console.log('Add Nodes to box');
		//console.log('Insert Error Box');
		eBox = document.createElement('div');
		eBox.className = eBoxClass;
		eMsg.appendChild(eBox);
		//console.log('Insert error icon into error box');
		eImg = document.createElement('img');
		eImg.setAttribute('src', eImgSrc);
		eBox.appendChild(eImg);
		//console.log('Insert message container into error box');
		eSpan = document.createElement('span');
		eSpan.className = eSpanClass;
		eBox.appendChild(document.createTextNode('\n'));
		eBox.appendChild(eSpan);
		//console.group('Move error messages into message container');
		for (var i = 0; i < eChildren.length; i) {
			//console.log('i: %d\nChildren: %d\nCurrent Element: %o', i, eChildren.length, eChildren[i]);
			if (eChildren[i] == eBox) {
				i++;
				continue;
			}
			eSpan.appendChild(eChildren[i]);
		}
		//console.groupEnd(); //Moving messages
		//console.log('Check for multi-error');
		if (eMsg.className.indexOf('error_multi') != -1) {
			eMulti = true;
			//console.log('Box is a multi-error');
			//Move multi class to box
			//console.log('Removing error_multi from wrapper\nClass: %s', eMsg.className);
			eMsg.className = eMsg.className.replace(/\berror_multi\b/, '');
			//console.log('New Class: %s', eMsg.className);
			//console.log('Set Box as multi-error\nClass: ', eBox.className);
			eBox.className += ' error_multi';
			//console.log('New Class: %s', eBox.className);
			//console.log('Register Multi-box');
			getErrorsMulti(eMsg);
		}
		//console.groupEnd(); //Current element
	}
	//console.groupEnd(); //Add Wrapper to error msgs
	
	//If there are multi-errors on page, register submit buttons to activate them as well
	if (eMulti) {
		//console.group('Binding all inputs for multi-errors');
		//Get all submit buttons
		var fInputs = document.getElementsByTagName('input');
		//console.log('Number of input elements: %d\nAdding Bindings to submit inputs', fInputs.length);
		for (x = 0; x < fInputs.length; x++) {
			if (fInputs[x].getAttribute('type') != 'submit')
				continue;
			//console.group('Index: %d\nInput: %o', x, fInputs[x]);
			//console.log('Adding Binding to click event');
			addEvent(fInputs[x], 'click', function() {
				//console.log('Submit button clicked\nChecking for multi-errors');
				checkErrorsMulti();
			});
			//console.groupEnd();
		}
		//console.groupEnd(); //Bind inputs
	}
	
	////console.warn(test);
	//test.style.visibility = 'visible';
	//console.groupEnd(); //Function end
} //END buildErrorMessages

function addCommas(nStr) {
	nStr += '';
	x = nStr.split('.');
	x1 = x[0];
	x2 = x.length > 1 ? '.' + x[1] : '';
	var rgx = /(\d+)(\d{3})/;
	while (rgx.test(x1)) {
		x1 = x1.replace(rgx, '$1' + ',' + '$2');
	}
	return x1 + x2;
}

//Equalize the heights of Country Lists in Featured Destinations
function eqHFDest() {
	var country_names = getElementsByClassName('country_name');
	var country_links = getElementsByClassName('country_link');
	
	
	//Equalize heights of link containers
	eqH_ext(country_names);
	//Align all links to bottom of containers
	console.log('Links: %o', country_links);
	for (var x = 0; x < country_links.length; x++) {
		console.info('X: %s', x);
		console.log('Parent: %o', country_links[x].parentNode);
		if (country_links[x].parentNode.style.height.toString().length > 0)
			country_links[x].style.position = "absolute";
	}
}

//Form field character counter
function countCharacters(el, msg, limit) {
	el = checkElement(el);
	msg = checkElement(msg);
	limit = parseInt(limit);
	//Cancel function if element is not valid
	if (!el || typeof el == 'undefined')
		return false;
	
	//Count Characters
	var count = el.value.length;
	//Report length
	if (msg && typeof msg != 'undefined') {
		var msgText = count;
		if (!isNaN(limit))
			msgText += ' / ' + limit
		msg.innerHTML = msgText;
	}
	
} //END countCharacters


//Automatically builds toggle lists on page
function buildToggleLists() {
	//Get all toggle lists
	lists = getElementsByClassName('list_toggle');
	items = new Array();
	var itemsA = new Array();
	var selectors = new Array();

	//Get all questions in lists
	console.log('Lists: %d', lists.length);
	for (x = 0; x < lists.length; x++) {
		console.log('List #: %d', x);
		//Get Items
		itemsA = itemsA.concat(lists[x].getElementsByTagName('li'));
		console.dir(itemsA);
		//items = items[0];
		console.dir(itemsA);
		//Get Questions
		selectors = selectors.concat(getElementsByClassName('selector', 'a', lists[x]));
		console.dir(selectors);
		//questions = selectors[0];
		console.log('Questions length: %d', selectors.length);
		console.dir(selectors);
	}
	
	//Expand Items List
	console.info('Expand Items List');
	for (x = 0; x < itemsA.length; x++) {
		console.log('Item: %d', x);
		for (i = 0; i < itemsA[x].length; i++) {
			console.log('Sub-Item: %d', i);
			items.push(itemsA[x][i]);
		}
	}
	
	console.log('Items Length: %d', items.length);
	
	console.info('Add Click Events to all questions');
	for (x = 0; x < selectors.length; x++) {
		console.log('x: %d\nAnchor: %o', x, selectors[x]);
		selectors[x].num = x;
		selectors[x].onclick = function() {
			toggleItem(this);
			return false;
		};
	}
	console.log('Set default display mode for items');
	for (x = 0; x < items.length; x++) {
		console.log('Item: %d', items.length);
		addClass(items[x], 'default');
	}
}

//Automatically builds toggle lists on page
function getTogglers() {
	//conFunc(arguments);
	//Get all toggle buttons
	var buttons = getElementsByClassName('toggle_button');
	var cButton;
	var items = new Array();
	var itemsA = new Array();
	var selectors = new Array();
	
	var types = new Array('id', 'class');
	var typesRegex = new Array(types.length);
	var rePattern = '_(\\S+)';
	var typesFunc = new Array('document.getElementById', 'getElementsByClassName');
	//Build Regex for types
	for (var t = 0; t < types.length; t++)
		typesRegex[t] = buildAttributeRegEx(types[t] + rePattern, 'g');
	var el,
		cType,
		cRegex,
		targetMatch,
		targetVal,
		childType,
		childTypeMatch,
		child,
		childTypeRegex = buildAttributeRegEx('child_type' + rePattern),
		selectRegex = buildAttributeRegEx('select' + rePattern),
		switchRegex = buildAttributeRegEx('switch' + rePattern);
	
	/**********************\\Define Internal Processors//**********************/
	
	//Get Button Targets
	var getTargets = function(btn) {
		//console.warn('Getting button targets\n %o', btn);
		if (!hasProp(btn, 'targets'))
			btn.targets = [];
		//console.log('Button: %o \n Class Name: %s', btn, btn.className);
		//Get button target(s)
		for (var i = 0; i < types.length; i++) {
			//console.log('Type: %s', types[i]);
			//Find Match
			cType = types[i];
			cRegex = typesRegex[i];
			if (btn.className.search(cRegex) != -1) {
				//console.log('Match Found\nType: %s \nRegEx: %s', cType, cRegex);
				targetMatch = btn.className.match(cRegex);
				//console.log('targetMatch\n %o', targetMatch);
				//Add target(s) to respective array
				for(var t = 0; t < targetMatch.length; t++) {
					//Format match (remove target type)
					targetMatch[t] = targetMatch[t].replace(cRegex, "$1");
					el = eval(typesFunc[i] + "('" + targetMatch[t] + "')");
					//console.info('Element\n %o \n Type: %s', el, typeof(el));
					
					//If element is an Array, merge with Targets array
					if (hasProp(el, 'length')) {
						if (el.length > 0) {
							//console.log('Adding Array');
							btn.targets = btn.targets.concat(el);
						}
					} //Otherwise, if element is valid, add to Targets array 
					else if (!!el) {
						//console.log('Adding Element');
						btn.targets.push(el);
					}
				} //END Looping through matches
			}
		}
	};
	
	//Set Button Properties
	var setProps = function(btn) {
		//console.warn('Setting Button Properties\n %o', btn);
		//Add extended properties object to button (if it doesn't already exist)
		addProp(btn, 'exProps', {});
		//Selected
		if (btn.className.search(selectRegex)) {
			var sel = btn.className.match(selectRegex);
			//console.log('Select match results\n %o', sel);
			if (sel != null && sel.length > 1) {
				addProp(btn.exProps, 'selected', (sel[1].toString().toLowerCase() == 'on') ? true : false);
			}
		}
		//console.log('Extended Properties\n %o', btn.exProps);
	};
	
	//Set Button Actions
	var setActions = function(btn) {
		//console.warn('Settings Actions\n %o', btn);
		if (isInput(btn, 'checkbox')) {
			addEvent(btn, 'click', function() {
				toggleItems(this, 'default');
			});
		} else {
			btn.onclick = function() {
				toggleItems(this, 'default');
				return false;
			}
		}
		
		//Get button switch action (For adding/removing switch action class to element when toggled)
		if (hasClass(btn, switchRegex)) {
			//console.log('Add switch action to button');
			btn.toggleSwitch = switchRegex.exec(btn.className)[1];
		}
		
		//Set default display mode for targets
		//console.log('Set default display mode for targets');
		toggleItems(btn, 'default');
	};
	
	//console.log('Buttons on page: %d', buttons.length);
	
	/**********************\\Iterate through buttons//**********************/
	
	for (var x = 0; x < buttons.length; x++) {
		cButton = buttons[x];
		//Check if Child element should be assigned toggle action
		if (hasClass(cButton, 'activate_child') && cButton.hasChildNodes()) {
			//console.warn('Activate Children');
			//Find children
			if (cButton.className.search(childTypeRegex) != -1) {
				childTypeMatch = cButton.className.match(childTypeRegex);
				for (var cT = 0; cT < childTypeMatch.length; cT++) {
					childTypeMatch[cT] = childTypeMatch[cT].replace(childTypeRegex, "$1");
				}
			}
			//TEMP: Use first type match
			childType = childTypeMatch[0];
			for (var c = 0; c < cButton.childNodes.length; c++) {
				child = cButton.childNodes[c];
				if (!hasProp(child, 'type'))
					continue;
				if (child.type == childType) {
					addClass(child, cButton.className);
					cButton = child;
					break;
				}
			}
		}
		//console.info('Index: %o \nButton: %o', x, cButton);
		
		//Get Targets
		getTargets(cButton);
		
		//Set Properties
		setProps(cButton);
		
		//Set Button Actions
		setActions(cButton);
	}
	//conFuncEnd();
} //END getTogglers

//Toggle Visibility of an item
function toggleItems(el, selClass) {
	//Get targets
	if (!hasProp(el, 'targets'))
		return false;
	conFunc(arguments);
	//Default Class Name to set
	if (!isset(selClass))
		selClass = 'selected';
	
	var doToggle = true,
		cTarg;
	
	//Check if button has extra Properties to evaluate
	if (hasProp(el, 'exProps')) {
		//Selected
		if (hasProp(el.exProps, 'selected') && el.exProps.selected === true) {
			//Check if item is an input element that can be selected (i.e. checkbox, radio, etc.)
			if (isInput(el, 'checkbox') && el.checked != true) {
				doToggle = false;
			}
		}
	}
	for (var x = 0; x < el.targets.length; x++) {
		cTarg = el.targets[x];
		if (hasClass(cTarg, selClass))
			removeClass(cTarg, selClass);
		else if (doToggle)
			addClass(cTarg, selClass);
	}
	
	//Switch action
	//Adds class to button element denoting the specified Switch action
	if (hasProp(el, 'toggleSwitch')) {
		if (hasClass(el, el.toggleSwitch))
			removeClass(el, el.toggleSwitch);
		else
			addClass(el, el.toggleSwitch);
	}
	conFuncEnd();
} //END toggleItem

//Toggle Visibility of an item
function toggleItem(el, selClass) {
	if (typeof el == 'undefined')
		return false;
	if (!('num' in el))
		return false;
	if (typeof selClass == "undefined")
		selClass = "selected";
	var reClass = buildAttributeRegEx(selClass);
	console.log(reClass);
	//Get Index of question
	if (items[el.num] == null)
		return false;
	//Display Answer
	if (hasClass(items[el.num], selClass))
		removeClass(items[el.num], selClass);
	else
		addClass(items[el.num], selClass);
} //END toggleItem

//Checks whether element has a specific css class
function hasClass(el, className) {
	if (typeof el == 'undefined' || typeof className == 'undefined')
		return false;
	var reClass = ((typeof className == 'object' || typeof className == 'function') && 'exec' in className) ? className : buildAttributeRegEx(className);
	if (el.className.search(reClass) != -1)
		return true;
	return false;
} //END hasClass

//Adds class to element
function addClass(el, className) {
	el = checkElement(el);
	if (!el || !className)
		return false;
	//Make sure element doesn't already have class
	if (!hasClass(el, className))
		el.className = el.className + " " + className;
} //END addClass

//Removes class from element
function removeClass(el, className) {
	if (!el || !className)
		return false;
	var els = new Array();
	//Check if element is an array
	if ('length' in el)
		els = el;
	else
		els[0]= el;
	var reClass = buildAttributeRegEx(className);
	for (var x = 0; x < els.length; x++) { 
		els[x].className = els[x].className.replace(reClass, "");
	}
} //END removeClass

/* Retrieves class names of an Element as Array
 * Parameters
 * 	el (Element/String ID)		: Element to get class
 * 	@filter (String/RegExp)		: Filter (Future Development)
 * 	
 * Methodology
 * 	- Get full className text of element
 * 	- Split class names into array
 * 	
 * Return Value: Array
 * Structure
 *  - 0 	: Full className string
 *  - 1-n	: Individual classNames
 */
function fetchClass(el, filter) {
	el = checkElement(el);
	if (!el || !hasProp(el, 'className'))
		return false;
	//Get Element's class value & split into individual class names 
	var elClass = el.className;
	
	//Return only classes matching filter
	if (isset(filter)) {
	}
	//Otherwise, return Array of class names
	else {
		namesArr = elClass.split(' ');
		//Add full class string to front of names array
		namesArr.unshift(elClass);
		return namesArr;
	}
}

//Retrieves array of rows in member list
function getMemberListRows() {
	var m_list = checkElement('m_list');
	var tr = m_list.getElementsByTagName('tbody')[0].getElementsByTagName('tr');
	return tr;
}

//Adds functionality to member list rows
function memberListRows() {
	var tr = getMemberListRows();
	for (x = 0; x < tr.length; x++) {
		tr[x].onmouseover = function() {
			addClass(this, 'over');
		};
		tr[x].onmouseout = function() {
			removeClass(this, 'over');	
		};
		tr[x].onclick = function() {
			//Remove action link from all rows
			removeClass(getMemberListRows(), 'action');
			//Remove mouseover class
			removeClass(this, 'over');
			//Add Action class
			addClass(this, 'action');
			//Get link
			var link = this.getElementsByTagName('a');
			link = link[0];
			//Open link
			location.href = link.href;
		};
	}
} //END memberListRows

/*Group Builder 
 *
 * - Allows elements to be grouped together
 * - Multiple Groups
 * 
 *Naming:
 *Grouping: class="in_groupname" (groupname = name of group)
 *Switcher: class="switch_groupname" (groupname = name of group to switch amongst)   
 */
function buildGroups() {
	conFunc(arguments);
	//Get Groups
	groups = getElementsByClassName('group');
	//Get Switches
	switches = getElementsByClassName('group_switch');
	
	//Cancel if there are no groups/switches
	if (groups.length < 1 || switches.length < 1)
		return false;
	
	console.log('Grouped Elements on page: %d \nSwitch Elements on Page: %d', groups.length, switches.length);
	
	group_default = "group_default";
	
	//Group elements by group name
	
	//Create new group object
	in_group = {};
	var groupSearch = "in_(\\w+)";
	var groupName;
	var reGroup = buildAttributeRegEx(groupSearch);
	for (x = 0; x < groups.length; x++) {
		if (!hasClass(groups[x], groupSearch))
			continue;
		console.log('Grouping Found: %s', groups[x].className);
		//Get group name
		groupName = groups[x].className.match(reGroup);
		groupName = groupName[2];
		console.log('Group Name: "%s"', groupName);
		//Check if group already exists
		if (!(groupName in in_group))
			in_group[groupName] = [];
		else {
			//Hide current element because other elements have already been added to this group
			addClass(groups[x], group_default);
		}
		//Add element to group
		in_group[groupName].push(groups[x]);
		console.log('%s Length: %d \n %o', groupName, in_group[groupName].length, in_group[groupName]);
	}
	
	//Get Switches for each group
	
	var switchSearch = "switch_(\\w+)";
	var reSwitch = buildAttributeRegEx(switchSearch);
	for (x = 0; x < switches.length; x++) {
		if (!hasClass(switches[x], switchSearch)) {
			console.warn('Switch %d: No Switch Group found', x);
			continue;
		}
		console.log('Group for Switch found: %s', switches[x].className);
		//Get group to switch
		groupName = switches[x].className.match(reSwitch);
		groupName = groupName[2];
		console.log('Group to Switch: "%s"', groupName);
		//Only add event to switcher if group exists
		if (!(groupName in in_group))
			continue;
		//Add Group to Switcher
		switches[x].switch_group = groupName;
		switches[x].onchange = function() {
			switchGroup(this);
		};
	}
	conFuncEnd();
}

function switchGroup(el, classShow, classHide) {
	console.group('Function: switchGroup()');
	if (typeof el == 'undefined')
		return false;
	//Setup defaults
	if (typeof classShow != 'string' || classShow.length < 1)
		classShow = 'group_selected';
	if (typeof classHide != 'string' || classHide.length < 1)
		classHide = 'group_default';
	//Check if selected group is currently hidden
	if (hasClass(in_group[el.switch_group][el.selectedIndex], classHide)) {
		//If so, hide all groups
		for (x = 0; x < in_group[el.switch_group].length; x++) {
			addClass(in_group[el.switch_group][x], classHide);
		}
		//Then show selected group
		removeClass(in_group[el.switch_group][el.selectedIndex], classHide);
	}
	console.groupEnd();
}

/* Creates console.group for Function
 * Parameters
 * 	args (Function arguments)	: Arguments passed from calling function
 * 	showParams (Boolean)		: Whether or not function parameters should be displayed or not   
 */
function conFunc(args, showParams) {
	console.group(args.callee);
	if (!isset(showParams))
		showParams = true;
	if (!!showParams)
		conParams(args);
}

// Closes console.group for a function call (wrapper to console.groupEnd for consistency)
function conFuncEnd() {
	console.groupEnd();
}

/* Creates console.info to list parameter values of a function call
 * Parameters
 * 	args (Function arguments)	: Arguments passed from calling function
 */
function conParams(args) {
	var disp = 'Parameters\\n',
		argList = '',
		arg,
		cInfo,
		params,
		argName;
	//Get argument names
	params = getFuncParams(args);
	
	//Build Console.info Call String
	if (args.length > 0) {
		for (var arg = 0; arg < args.length; arg++) {
			argName = (arg < params.length) ? params[arg] : arg;
			disp += argName + ': %o \\n';
			if (argList.length > 0)
				argList += ', ';
			argList += "args[" + arg + "]"
		}
	} else {
		argList = "'No Paramters'";
	}
	cInfo = "console.info(\"" + disp + "\", " + argList + ")";
	//Call console.info
	eval(cInfo);
}

/* Gets Parameter names for a function call
 * Parameters
 * 	args (Function arguments)	: Arguments passed from calling function
 * 	
 * Return Value: Parameter Names (Array)   
 */
function getFuncParams(args) {
	var p = [];
	if (!isset(args))
		return p;
	//Get string of function
	var f = ((isFunction(args)) ? args : args.callee).toString(),
		pS = f.indexOf('(');
		pE = f.indexOf(')');
	//Get Params from string
	if (pS == -1 || pE == -1)
		return p;
	//Extract Param list from string and Split Params into Array
	p = (f.substring(pS + 1, pE)).replace(' ', '').split(',');
	return p;
}
 
//Checks function call to make sure all parameters have a value
function checkFuncParams(args) {
	//Compare number of required params to number of passed params
	if (args.length < getFuncParams(args).length)
		return false;
	else {
		//Make sure all parameters have valid values
		for (var x = 0; x < args.length; x++) {
			if (!isset(args[x]))
				return false;
		}
	}
}

//Checks if item is function
function isFunction(o) {
	return typeof o == 'function';
}

function isset(obj) {
	//console.info('Function: %o \nobj: %o', arguments.callee, obj);
	if (typeof obj == 'undefined' || obj == null)
		return false;
	return true;
}

/* Checks if an object has a property
 * Parameters:
 * 	obj (Object)		: Object to evaluate
 * 	prop (String/Array)	: Name (or Array of Names) of property/properties to evaluate
 * 	
 * Return value: Boolean
 * 	TRUE	: If all requested properties exist in object
 * 	FALSE	: If at least one requested property does NOT exist in object      
 */
function hasProp(obj, prop, type) {
	//console.group(arguments.callee);
	//console.info('Parameters\nobj: %o \nprop: %o \ntype: %o', obj, prop, type);
	if (!isset(obj) || !isset(prop))
		return false;
	var ret = false,
		iProp;
	//Check if prop is an Array
	if (!(prop instanceof Array))
		prop = [prop];
	for (var x = 0; x < prop.length; x++) {
		iProp = prop[x];
		if (iProp in obj) {
			ret = true;
			if (isset(type) && !(obj[iProp] instanceof type))
				ret = false;
		}
		if (!ret)
			break;
	}
	//console.log('Return value: %o', ret);
	//console.groupEnd();
	return ret;
}

/* Adds Property to Object
 * Parameters
 * 	obj (Object)			: Object to add Property to
 * 	prop (String)			: Property to add to Object
 * 	[val]	(Misc)			: Value to set for Property (Can be Anything)
 * 	[overwrite] (Boolean)	: Clear previous value (if property already exists) [Default: true]    
 */
function addProp(obj, prop, val, overwrite) {
	if (!isset(obj) || !isset(prop))
		return false;
	if (!isset(overwrite))
		overwrite = true;
	//Set prop to its string value
	prop = prop.toString();
	if (!isset(val))
		val = '';
		
	//Add Property to Object
	if (!hasProp(obj, prop) || overwrite) {
		obj[prop] = val;
	}
}


//Checks if an element is an INPUT element
function isInput(el, iType) {
	el = checkElement(el);
	var ret = false;
	if (!el)
		return false;
	if (!hasProp(el, 'tagName'))
		return false;
	//Check if element is an input element
	if (el.tagName.toLowerCase() == 'input') {
		ret = true;
		//Check Input type
		if (isset(iType)) {
			if (!hasProp(el, 'type') || el.type != iType)
				ret = false;
		}
	}
	console.warn('Is Input: %o', ret);
	return ret;
}


/**********************\\Page-Specific Scripts//**********************/

function addFolio_CheckConfirmation(chk, field) {
	conFunc(arguments);
	chk = checkElement(chk);
	field = checkElement(field);
	var vEnable = false;
	
	if (!chk || !field)
		return false;
	if (hasProp(field, 'Validators')) {
		if (chk.checked == false)
			vEnable = true;
		
		//Enable/Disable Validators
		for (var x = 0; x < field.Validators.length; x++) {
			field.Validators[x]['enabled'] = vEnable;
		}
	}
	console.warn('Enable Validators: %o', vEnable);
	conFuncEnd();
}

function onDailyStats(reportName, paramBrands, paramYearWeek, paramDay, paramMode, affect) {

        var frm = document.getElementById("formDailyStats");
        frm.p_report.value = reportName;
        frm.p_renderer.value = affect;

        frm.p_paramDay.value = paramDay;
       // alert('paramDay:' + paramDay);
        //alert('YearWeek:' + paramYearWeek);

        var YearWeek = paramYearWeek.split(",");
        frm.p_paramYear.value = YearWeek[0];
        frm.p_paramWeek.value = YearWeek[1];
        frm.p_paramBrand.value = paramBrands;
        frm.p_paramMode.value = paramMode;
       

       /* var ids = paramBrands.split(",");
        var ddlBrands1 = document.getElementById("p_paramBrand")
        while (ddlBrands1.options.length > 0) {
            ddlBrands1.remove(ddlBrands1.options.length - 1)
        }

        for (var i = 0; i < ids.length; i++) {

            var o = document.createElement("option");
            o.text = ids[i];  // text 
            o.value = ids[i];  // value
            // o.selected = true;
            o.setAttribute("selected", true);
            //alert(hotelGroups[i].hotel_group_id);
            //alert('created');

            ddlBrands1.options.add(o);
        }*/

        frm.submit();

    }
    //------------------------------------------------
    function onRedemptionCredits(reportName, paramHotelGroup, paramFromMonth, paramToMonth, affect) {
       //alert('onRedemptionCredits');
        var frm = document.getElementById("formRedemptionNights");
        frm.p_report.value = reportName;
        frm.p_renderer.value = affect;

     
        frm.p_paramHotelGroup.value = paramHotelGroup;
        frm.p_paramFromMonth.value = paramFromMonth;
        frm.p_paramToMonth.value = paramToMonth;

        //alert(frm.p_paramFromMonth.value);

        frm.submit();



    }
    //------------------------------------------------

    function onRedemptionReservesByEntities(reportName, paramBrands, paramYear, paramMonth, affect) {
       // alert('onRedemptionReservesByEntities');
        var frm = document.getElementById("formRedemptionReservesByEntities");
        frm.p_report.value = reportName;
        frm.p_renderer.value = affect;

        frm.p_paramYear.value = paramYear;
        frm.p_paramMonth.value = paramMonth;
        frm.p_paramBrand.value = paramBrands;
     
        frm.submit();



    }
    function onRedemptionReservesByMonths(reportName, paramBrands, paramYear,  affect) {
        //alert('onRedemptionReservesByEntities');
        var frm = document.getElementById("formRedemptionReservesByMonths");
        frm.p_report.value = reportName;
        frm.p_renderer.value = affect;

        frm.p_paramYear.value = paramYear;
        frm.p_paramBrand.value = paramBrands;
        //alert('p_paramYear:' + frm.p_paramYear.value);
        //alert('paramBrands:' + paramBrands);

        /*var ids = paramBrands.split(",");
        var ddlBrands1 = document.getElementById("p_paramBrand")
        while (ddlBrands1.options.length > 0) {
            ddlBrands1.remove(ddlBrands1.options.length - 1)
        }

        for (var i = 0; i < ids.length; i++) {

            var o = document.createElement("option");
            o.text = ids[i];  // text 
            o.value = ids[i];  // value
            o.setAttribute("selected", true);


            ddlBrands1.options.add(o);
        }*/

        frm.submit();

    }

    //------------------------------------------------

    function onRedemptionAccountYearToDateByBrands(reportName, paramYear, paramMonth, affect) {
     
        var frm = document.getElementById("formRedemptionAccountYearToDateByBrands");
        frm.p_report.value = reportName;
        frm.p_renderer.value = affect;

        frm.p_paramYear.value = paramYear;
        frm.p_paramMonth.value = paramMonth;
        

        frm.submit();



    }

    function onInvoice(reportName, paramInvoiceId, paramCompany, paramType, affect){
        //alert('onInvoice');
        var frm = document.getElementById("formInvoice");
        frm.p_report.value = reportName;
        frm.p_renderer.value = affect;

        frm.p_paramInvoiceId.value = paramInvoiceId;
        frm.p_paramCompany.value = paramCompany;
        frm.p_paramType.value = paramType;

        //alert(frm.p_paramCompany.value);
        //alert(frm.p_paramType.value);

        frm.submit();



    }

    //------------------------------------------------
    function onMemberListing(reportName, paramHotelGroup, paramJoinYear, paramTier, paramSortBy, affect) {
       // alert('onMemberListing ' + reportName);
        var frm = document.getElementById("formMemberListing");
        frm.p_report.value = reportName;
        frm.p_renderer.value = affect;


        frm.p_paramHotelGroup.value = paramHotelGroup;

        frm.p_paramJoinYear.value = paramJoinYear;
        frm.p_paramTier.value = paramTier;
        frm.p_paramSortBy.value = paramSortBy;
       
         alert(frm.p_paramSortBy.value);

        frm.submit();



    }
