

/* ------------------------------------------------------------------------------------------- */






function MultiListEditor(name) 
{

	this.name = name;
	this.showLinks = true;
	this.useDeleteLink = false;
	this.setDeleteLink = '';
	this.showPosition = true;
	this.showPositionDepth = true;
	this.showPositionNumbers = true;
	this.showPositionSeperator = '.';
	this.showPositionPad = false;
	this.showPositionTitleSeperator = ' - ';
	this.itemMaxLength = false;
	this.allowDuplicateText = false;
	this.allowAddItems = true;
	this.allowSortItems = true;
	this.allowDeleteItems = true;
	this.allowNumericOnly = false;
	this.allowCommaDelimited = false;
	this.itemLimit = false;
	
	this.disableFirstListLinks = false;
	
	this.linksArray = [];
	this.linksCount = 0;
	
	this.lists = [];
	this.listCount = 0;
	
	this.itemText = [];
	this.itemTextCount = 0;
	
	this.items = [];
	this.itemCount = 0;
	this.newItemCount = 1;
	
	this.isNumeric = function(expression) 
	{
		if (this.allowCommaDelimited) {
			var nums = "0123456789,";
		} else {
			var nums = "0123456789";
		}
		
		if (expression.length==0)return(false);

		for (var n=0; n < expression.length; n++){
			if (nums.indexOf(expression.charAt(n))==-1) return (false);
		}

		return(true);

	}
	
	
	this.setCurrentState = function() {
		setTimeout(this.name+".recurseList('"+this.name+"-List0',null,null,'')",200);
	}
	
	this.startList = function() 
	{
		var list = this.lists.reverse();
		for (var i=0;i<list.length;i++) {
			if (this.allowSortItems) {
				var container = this.name+'-'+list[i][0];
				Sortable.create(container,{tag:'div',dropOnEmpty:true,handle:'handle',containment: [container] ,constraint:false,onChange:this.setCurrentState.bind(this)});
			}
		}
		this.setCurrentState(); 
	}
	
	this.addList = function(currentlist,parentlist) 
	{	
		this.lists[this.listCount] = [currentlist,parentlist];
		this.listCount++;

		var MultiListEditor = $(this.name);
		var sortablecontainer = Builder.node('div',{className:'sortablecontainer',id:this.name+'-'+currentlist});
		if (parentlist == null) {
			var MultiListEditor = $(this.name);
		} else {
			var MultiListEditor = $('CURRENT_'+parentlist);
			}
		MultiListEditor.appendChild(sortablecontainer);
	}
	
	this.checkQuestionText = function(text) 
	{
		for (var i=0; i < this.questions.length; i++) {
			if (this.questions[i][1] == text)
				return true;
		}
		return false;
	}
	
	
	this.clearAll = function() {		
		for (i=0;i<this.items.length;i++) {			
			this.deleteNode('List0',this.items[i]);
		}			
		this.items.length = 0;		
		this.itemCount = 0;
		this.newItemCount = 1;
	}
	
	
	this.addNodeFromText = function(list) 
	{
		
		eval('value = document.fm.'+this.name+'_Add.value');
		
		if (this.allowCommaDelimited) {
		
			valueArray = value.split( "," );
				for( i = 0; i < valueArray.length; i++ ) 
				{
					token = valueArray[i];
					trimmed = token.replace(/^\s+|\s+$/g, '') ;
					
					if( trimmed.length > 0 )
					{
						this.validateNode(list,null,trimmed);
					}
				}
		} else {
		
			this.validateNode(list,null,value) 
		}
		
	}
	
	this.addNodeFromSelect = function(list) 
	{
		
		value = $(this.name+'_Add').value;
		text = $(this.name+'_Add')[$(this.name+'_Add').selectedIndex].label;
		
		if (value != '') {
			this.validateNode(list,value,text);
		}
		
		eval('document.fm.'+this.name+'_Add.value = \'\'');
		
	}	
	
	
	this.validateNode = function(list,id,value) 
	{		
		if (value == '') {
			alert('The field is empty.');
			return false;
		}
		
		if (this.allowNumericOnly) {
			if (!this.isNumeric(value)) {
				alert('Only whole numbers are allowed in this field.')
				return false;
			}
		}

		if (this.itemLimit) {
			if (this.itemCount >= this.itemLimit) {
				alert('Only '+this.itemLimit+' items are allowed in this field.')
				return false;
			}
		}
		
		if (this.itemMaxLength) {
			if (this.itemMaxLength < value.length) {
				alert('This field allows a maximum of '+this.itemMaxLength+' characters.')
				return false;
			}
		}
				
		if (this.allowDuplicateText == false)
		{
			var duplicate = false;
			
			for (var i=0;i<this.itemText.length;i++) 
			{
				if (this.itemText[i].toLowerCase() == value.toLowerCase()) 
				{
					duplicate = true;
				}
			}
			if (duplicate == true) {
				alert('This item is already in the list.');
				return false;
			}
		}
		
		this.addNode(list,id,value);
		eval('document.fm.'+this.name+'_Add.value = \'\'');

	}	
	
	
	this.strpad = function(value) {
		if (this.showPositionPad)
		{	
			if (value > 9) {
				var value = value;
			} else {
				var value = '0'+value;
			}
		} 
		return value;
	}

	this.addNode = function(list,id,text, voidStartList, errormessage) 
	{
		
		if (id == null) {
			idprefix = 'NEW_';
			itemid = this.newItemCount;
			this.newItemCount++;
		} else {
			idprefix = 'CURRENT_';
			itemid = id;
		}
		
		
		this.items[this.itemCount] = idprefix + itemid;
		this.itemCount++;
		
		divsortableitem = Builder.node('div',{className:'sortableitem',id:idprefix+itemid});
		divitem = Builder.node('div',{className:'item'});
		
		if (this.allowSortItems == true) {
			divhandle = Builder.node('div',{className:'handle'});
		} else {
			divhandle = Builder.node('div',{className:'handle disabledhandle'});
		}
		
		spanposition = Builder.node('span',{className:'position'});
		spantext = Builder.node('span',{className:'text'},text);
		divcontrols = Builder.node('div',{className:'controls'});
		if (this.useDeleteLink) {
			var replacedDeleteIDonclick = this.setDeleteLink.replace("{ID}", itemid);
			adelete = Builder.node('a',{className:'delete',href:replacedDeleteIDonclick},'X');
		} else {
			adelete = Builder.node('a',{className:'delete',href:'javascript:void(0);',onclick:this.name+'.deleteNode(\''+list+'\',\''+idprefix+itemid+'\')'},'X');
		}
		divclear = Builder.node('div',{className:'clear'});
		if (this.allowDeleteItems == true) {
			divcontrols.appendChild(adelete);
		}
		if (errormessage!=null) {
			//aerror = Builder.node('div',{className:'errors'},errormessage);
			dv = document.createElement('div');
			dv.style.textAlign = 'left';
			dv.style.color = '#0000AA';
			dv.innerHTML = errormessage;
			divclear.appendChild(dv);
		}
		
		if (this.showLinks == true) {
			if (this.disableFirstListLinks == false || list != 'List0') {
				for (var i=0;i<this.linksArray.length;i++)
				{
					href = this.linksArray[i][1];
					var replacedIDhref = href.replace("{ID}", itemid);
					var replacedLISThref = replacedIDhref.replace("{LIST}", list);
					
					var node = Builder.node('a',{href:replacedLISThref,className:this.linksArray[i][2]},this.linksArray[i][0]);
					divcontrols.appendChild(node);
				}
			}
		}
		divitem.appendChild(divhandle);
		divhandle.appendChild(spanposition);
		divhandle.appendChild(spantext);
		divitem.appendChild(divcontrols);
		divitem.appendChild(divclear);
		divsortableitem.appendChild(divitem);
	

		var listid = $(this.name+'-'+list);
		listid.appendChild(divsortableitem);
		
		if (voidStartList != true) {
			this.startList();
		}
	}

	this.deleteNode = function(list,id) 
	{
		elem = $(this.name+'-'+list);
		elem.removeChild($(id));
		
		this.itemCount = this.itemCount-1;
		
		this.startList();
	}
	
	this.addLink = function(text,href,classname) {
	
		if (!classname) classname = '';
		if (!href) href = '';
	
		this.linksArray[this.linksCount] = [text,href,classname];
		this.linksCount++;;
	}
	
	this.recurseList = function(contid,parentseq,grandparentseq,seqstr) {
	
		if(!parentseq && !grandparentseq) {
			this.itemText = [];
			this.itemTextCount = 0;
		}
		
		var container = $(contid);
		var items = container.childNodes;
		var order = 0;
		for (var i=0;i < items.length;i++)
		{
			if (items[i].tagName == 'DIV') {
				order++;
				
				var child = items[i].childNodes;
				var childitem = child[0];
				var childtext = childitem.childNodes[0];
				if (this.showPosition == true) {
						var childnum = childtext.childNodes[0];
					
					if (this.showPositionNumbers == true) {
						var grandparentnum = this.strpad(grandparentseq);
						var parentnum = this.strpad(parentseq);
						var ordernum = this.strpad(order);
					} else {
						var grandparentnum = ''	;
						var parentnum = '';
						var ordernum = '';
					}
					
					if (seqstr=='') {
						childnum.innerHTML = ordernum+this.showPositionTitleSeperator;
					} else {
						childnum.innerHTML = seqstr+ordernum+this.showPositionTitleSeperator;
					}
					/*
					if ((parentseq == null && grandparentseq == null) || this.showPositionDepth == false) {
						childnum.innerHTML = ordernum+this.showPositionTitleSeperator;
					} else if (grandparentseq == null) {
						childnum.innerHTML = seqstr+this.showPositionSeperator+ordernum+this.showPositionTitleSeperator;//parentnum+this.showPositionSeperator+ordernum+this.showPositionTitleSeperator;
					} else {
						childnum.innerHTML = grandparentnum+this.showPositionSeperator+parentnum+this.showPositionSeperator+ordernum+this.showPositionTitleSeperator;
					}
					*/
				}

				this.itemText[this.itemTextCount] = childtext.childNodes[1].innerHTML;
				this.itemTextCount++;
				
				var children = items[i].childNodes;
				for (var c=0;c < children.length;c++) {
					if (children[c].className == 'sortablecontainer') {
						
						if (this.allowDeleteItems)
						{
							if (children[c].childNodes.length > 0) {
								var adelete = childitem.childNodes[1].childNodes;
								for (var d=0;d < adelete.length;d++) {
									if (adelete[d].className == 'delete') {
										adelete[d].className = 'deleteDisable';
										adelete[d].onclick = '';
										adelete[d].href  = 'javascript: alert(\'This item cannot be deleted because it currently has children assigned to it.\');';
									} 
								}
							} else {
								var adelete = childitem.childNodes[1].childNodes;
								for (var d=0;d < adelete.length;d++) {
									if (adelete[d].className == 'deleteDisable') {
										var deleteitemlist = adelete[d].parentNode.parentNode.parentNode.parentNode.id;
										var deleteitemid = adelete[d].parentNode.parentNode.parentNode.id;
										if (this.useDeleteLink) {
											adelete[d].className = 'delete';
											adelete[d].onclick = this.setDeleteLink+'id='+deleteitemid;
											adelete[d].href  = '';
										} else {
											var deleteitemlist = adelete[d].parentNode.parentNode.parentNode.parentNode.id;
											var deleteitemid = adelete[d].parentNode.parentNode.parentNode.id;
											adelete[d].className = 'delete';
											adelete[d].href = 'javascript:'+this.name+'.deleteNode(\''+deleteitemlist+'\',\''+deleteitemid+'\');';
										}
									} 
								}
							}
						}
						if (parentseq == 'null') {
							this.recurseList(children[c].id,order,null);
						} else {
							this.recurseList(children[c].id,order,parentseq,seqstr+ordernum+this.showPositionSeperator);
						}						
					}
				}
			}
		}
	}
	
	this.buildItems = function() 
	{
		
		this.items = [];
		this.itemcount = 0;
		
		currentLists = $(this.name).getElementsByTagName('*');
		for (var i = 0; i < currentLists.length; i++)
		{
			if (currentLists[i].className.toUpperCase() == 'SORTABLECONTAINER') 
			{
				currentListItems = currentLists[i].childNodes;
				for (var j = 0; j < currentListItems.length; j++)
				{
					var parent = currentListItems[j].parentNode.parentNode;
					
					if (parent.className == 'sortableitem') {
						parentid = parent.id; 
					} else {
						parentid = 0;
					}
					
					var currentListItemElemText = currentListItems[j].childNodes[0].childNodes[0].childNodes[1].innerHTML;
					var currentListItemElemId = currentListItems[j].id;
					var currentParent = parentid;
					
					this.items[this.itemcount] = [currentParent+'-'+currentListItemElemId,currentListItemElemText];
					this.itemcount++;
				}
			}
		}
	}	

	this.onSubmit = function()
	{
		this.buildItems();
		for (var i=0;i<this.items.length;i++)
		{
			var hiddenInput = document.createElement('INPUT');		
			hiddenInput.type = 'hidden';
			hiddenInput.name = this.name+i+'-'+this.items[i][0];
			hiddenInput.value = this.items[i][1];
			
			currentMultiList = $(this.name);
			currentMultiList.appendChild(hiddenInput);
		}
	}

	this.onSubmitArray = function()
	{
		this.buildItems();
		for (var i=0;i<this.items.length;i++)
		{
			var hiddenInput = document.createElement('INPUT');		
			hiddenInput.type = 'hidden';
			hiddenInput.name = this.name+'['+i+'-'+this.items[i][0]+']';
			hiddenInput.value = this.items[i][1];
			
			currentMultiList = $(this.name);
			currentMultiList.appendChild(hiddenInput);
		}
	}

}



/* CORE LIBRARY */

if (document.images)
{
  initloaderpic= new Image(24,24); 
  initloaderpic.src="images/interface/ajax-loader.gif"; 
}

function getElementsByClass( searchClass, domNode, tagName) {
	if (domNode == null) domNode = document;
	if (tagName == null) tagName = '*';
	var el = new Array();
	var tags = domNode.getElementsByTagName(tagName);
	var tcl = " "+searchClass+" ";
	for(i=0,j=0; i<tags.length; i++) {
		var test = " " + tags[i].className + " ";
		if (test.indexOf(tcl) != -1)
			el[j++] = tags[i];
	}
	return el;
}


function submitOnEnter(myfield,e)
{
	var keycode;
	var target;
	
	if (!e) var e = window.event;
	if (e.target) target = e.target;
	else if (e.srcElement) target = e.srcElement;
	if (target.nodeType == 3) // defeat Safari bug
		target = target.parentNode;
	
	if (window.event) {keycode = window.event.keyCode;}
	else if (e) {keycode = e.which;}
	else return true;
	
	if (keycode == 13)
	{				   
	   document.getElementById(target.form.id).submit();
	   return false;
	}
	else
	   return true;
}

function selectBoxSelectAll(selectBox,selectAll) {
	// have we been passed an ID
	if (typeof selectBox == "string") {
		selectBox = document.getElementById(selectBox);
	}
	// is the select box a multiple select box?
	if (selectBox.type == "select-multiple") {
		for (var i = 0; i < selectBox.options.length; i++) {
			selectBox.options[i].selected = selectAll;
		}
	}
}

function updatebg() {

	height = document.viewport.getDimensions()['height'];
	width = document.viewport.getDimensions()['width'];
	topscroll = document.viewport.getScrollOffsets()['top'];
	leftscroll = document.viewport.getScrollOffsets()['left'];
	
	document.getElementById('loaderbg').style.height = height+topscroll+'px';
	document.getElementById('loaderbg').style.width = width+leftscroll+'px';
	
	document.getElementById('loadercontainer').style.width = width+leftscroll+'px';
}

function initLoader() 
{
	document.getElementById('ldr').style.display = 'block';
	document.getElementById('ldr').innerHTML = '<div id="loaderbg"></div><div id="loadercontainer"><div id="loader"><div><img src="images/interface/ajax-loader.gif" /></div><div>Loading...</div></div></div></div>';
	
	updatebg();
	
	Event.observe(window, 'scroll', function() {  updatebg();  }); 
	Event.observe(window, 'resize', function() {  updatebg();  }); 
}


var newwindow = '';

function initPopupWindow(url,id,height,width) 
{
	if (height == null)  height = 710;
	if (width == null)  width = 900;
	if (id == null)  id = 'popupwindow';
	
	if (!newwindow.closed && newwindow.location) {
		newwindow.location.href = url;
	}
	else {
		newwindow = window.open(url,id,config='height='+height+',width='+width+',toolbar=no,menubar=no,scrollbars=yes,resizable=no,location=no,directories=no,status=no');
	
		if (!newwindow.opener) newwindow.opener = self;
	}
	if (window.focus) {newwindow.focus()}
}

function initInlinePopup(url,width,callback) 
{

	if (width == null) {
		width = 300;
	}
	
	Event.observe(window, 'load', function() { 
		$('inlinePopup').innerHTML = '<div class="inlinePopupBackground"></div><div class="inlinePopupContainer"><div class="inlinePopupContent" style="width:'+width+'px;"><div id="inlinePopupHtml"><center><img src="/public/images/interface/ajax-loader.gif" /><br />Loading...</center></div></div></div>';
		
		new Ajax.Request(url, {   method: 'get',   onSuccess: function(transport) {    
			 $('inlinePopupHtml').innerHTML = transport.responseText;
			 if (callback != null) {
				eval(callback);
			}
		 }
		}); 
	});
}

function startInlinePopup(url,width,callback) 
{

	if (width == null) {
		width = 300;
	}
	
	$('inlinePopup').innerHTML = '<div class="inlinePopupBackground"></div><div class="inlinePopupContainer"><div class="inlinePopupContent" style="width:'+width+'px;"><div id="inlinePopupHtml"><center><img src="/public/images/interface/ajax-loader.gif" /><br />Loading...</center></div></div></div>';
	
	new Ajax.Request(url, {   method: 'get',   onSuccess: function(transport) {    
		 $('inlinePopupHtml').innerHTML = transport.responseText;
		 if (callback != null) {
			eval(callback);
		}
	 }
	}); 
}

function closeInlinePopup() {
	$('inlinePopup').innerHTML = '';
		 
}




var Calendar = Class.create()

//------------------------------------------------------------------------------
// Constants
//------------------------------------------------------------------------------

Calendar.VERSION = '1.0'

Calendar.DAY_NAMES = new Array(
  'Sunday', 'Monday', 'Tuesday', 'Wednesday', 'Thursday', 'Friday', 'Saturday',
  'Sunday'
)

Calendar.SHORT_DAY_NAMES = new Array(
  'S', 'M', 'T', 'W', 'T', 'F', 'S', 'S'
)

Calendar.MONTH_NAMES = new Array(
  'January', 'February', 'March', 'April', 'May', 'June', 'July', 'August',
  'September', 'October', 'November', 'December'
)

Calendar.SHORT_MONTH_NAMES = new Array(
  'Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun', 'Jul', 'Aug', 'Sep', 'Oct', 'Nov',
  'Dec' 
)

Calendar.NAV_PREVIOUS_YEAR  = -2
Calendar.NAV_PREVIOUS_MONTH = -1
Calendar.NAV_TODAY          =  0
Calendar.NAV_NEXT_MONTH     =  1
Calendar.NAV_NEXT_YEAR      =  2
Calendar.currentDisplayYear =  0

//------------------------------------------------------------------------------
// Static Methods
//------------------------------------------------------------------------------

// This gets called when the user presses a mouse button anywhere in the
// document, if the calendar is shown. If the click was outside the open
// calendar this function closes it.
Calendar._checkCalendar = function(event) {
  if (!window._popupCalendar)
    return false
  if (Element.descendantOf(Event.element(event), window._popupCalendar.container))
    return
  window._popupCalendar.callCloseHandler()
  return Event.stop(event)
}

//------------------------------------------------------------------------------
// Event Handlers
//------------------------------------------------------------------------------

Calendar.handleMouseDownEvent = function(event)
{
  Event.observe(document, 'mouseup', Calendar.handleMouseUpEvent)
  Event.stop(event)
}

// XXX I am not happy with how clicks of different actions are handled. Need to
// clean this up!
Calendar.handleMouseUpEvent = function(event)
{
  var el        = Event.element(event)
  var calendar  = el.calendar
  var isNewDate = false

  // If the element that was clicked on does not have an associated Calendar
  // object, return as we have nothing to do.
  if (!calendar) return false

  // Clicked on a day
  if (typeof el.navAction == 'undefined')
  {
    if (calendar.currentDateElement) {
      Element.removeClassName(calendar.currentDateElement, 'selected')
      Element.addClassName(el, 'selected')
      calendar.shouldClose = (calendar.currentDateElement == el)
      if (!calendar.shouldClose) calendar.currentDateElement = el
    }
    calendar.date.setDateOnly(el.date)
    isNewDate = true
    calendar.shouldClose = !el.hasClassName('otherDay')
    var isOtherMonth     = !calendar.shouldClose
    if (isOtherMonth) calendar.update(calendar.date)
  }

  // Clicked on an action button
  else
  {
    var date = new Date(calendar.date)

    if (el.navAction == Calendar.NAV_TODAY)
      date.setDateOnly(new Date())

    var year = date.getFullYear()
    var mon = date.getMonth()
    function setMonth(m) {
      var day = date.getDate()
      var max = date.getMonthDays(m)
      if (day > max) date.setDate(max)
      date.setMonth(m)
    }
    switch (el.navAction) {

      // Previous Year
      case Calendar.NAV_PREVIOUS_YEAR:
        if (year > calendar.minYear)
	    Calendar.currentDisplayYear = year - 1
          date.setFullYear(year - 1)
        break

      // Previous Month
      case Calendar.NAV_PREVIOUS_MONTH:
        if (mon > 0) {
          setMonth(mon - 1)
        }
        else if (year > calendar.minYear) {
	    Calendar.currentDisplayYear = year - 1
          date.setFullYear(year - 1)
          setMonth(11)
        }
        break

      // Today
      case Calendar.NAV_TODAY:
        break

      // Next Month
      case Calendar.NAV_NEXT_MONTH:
        if (mon < 11) {
          setMonth(mon + 1)
        }
        else if (year < calendar.maxYear) {
	    Calendar.currentDisplayYear = year + 1
          date.setFullYear(year + 1)
          setMonth(0)
        }
        break

      // Next Year
      case Calendar.NAV_NEXT_YEAR:
        if (year < calendar.maxYear)
	    Calendar.currentDisplayYear = year + 1
          date.setFullYear(year + 1)
        break

    }

    if (!date.equalsTo(calendar.date)) {
      calendar.setDate(date)
      isNewDate = true
    } else if (el.navAction == 0) {
      isNewDate = (calendar.shouldClose = true)
    }
  }

  if (isNewDate) event && calendar.callSelectHandler()
  if (calendar.shouldClose) event && calendar.callCloseHandler()

  Event.stopObserving(document, 'mouseup', Calendar.handleMouseUpEvent)

  return Event.stop(event)
}

Calendar.defaultSelectHandler = function(calendar)
{
  if (!calendar.dateField) return false

  // Update dateField value
  if (calendar.dateField.tagName == 'DIV')
    Element.update(calendar.dateField, calendar.date.print(calendar.dateFormat))
  else if (calendar.dateField.tagName == 'INPUT') {
    calendar.dateField.value = calendar.date.print(calendar.dateFormat) }

  // Trigger the onchange callback on the dateField, if one has been defined
  if (typeof calendar.dateField.onchange == 'function')
    calendar.dateField.onchange()

  // Call the close handler, if necessary
  if (calendar.shouldClose) calendar.callCloseHandler()
}

Calendar.defaultCloseHandler = function(calendar)
{
  calendar.hide()
}


//------------------------------------------------------------------------------
// Calendar Setup
//------------------------------------------------------------------------------

Calendar.setup = function(params)
{
    function param_default(name, def) {
    if (!params[name]) params[name] = def
  }

  param_default('dateField', null)
  param_default('triggerElement', null)
  param_default('parentElement', null)
  param_default('selectHandler',  null)
  param_default('closeHandler', null)

  // In-Page Calendar
  if (params.parentElement)
  {
    var calendar = new Calendar(params.parentElement)
    calendar.setSelectHandler(params.selectHandler || Calendar.defaultSelectHandler)
    if (params.dateFormat)
      calendar.setDateFormat(params.dateFormat)
    if (params.dateField) {
      calendar.setDateField(params.dateField)
      calendar.parseDate(calendar.dateField.innerHTML || calendar.dateField.value)
    }
    calendar.show()
    return calendar
  }

  // Popup Calendars
  //
  // XXX There is significant optimization to be had here by creating the
  // calendar and storing it on the page, but then you will have issues with
  // multiple calendars on the same page.
  else
  {
    var triggerElement = $(params.triggerElement || params.dateField)
    triggerElement.onclick = function() {
      var calendar = new Calendar()
      calendar.setSelectHandler(params.selectHandler || Calendar.defaultSelectHandler)
      calendar.setCloseHandler(params.closeHandler || Calendar.defaultCloseHandler)
      if (params.dateFormat)
        calendar.setDateFormat(params.dateFormat)
      if (params.dateField) {
        calendar.setDateField(params.dateField)
        calendar.parseDate(calendar.dateField.innerHTML || calendar.dateField.value)
      }
      if (params.dateField)
        Date.parseDate(calendar.dateField.value || calendar.dateField.innerHTML, calendar.dateFormat)
      calendar.showAtElement(triggerElement)
      return calendar
    }
  }

}



//------------------------------------------------------------------------------
// Calendar Instance
//------------------------------------------------------------------------------

Calendar.prototype = {

  // The HTML Container Element
  container: null,

  // Callbacks
  selectHandler: null,
  closeHandler: null,

  // Configuration
  minYear: 1900,
  maxYear: 2100,
  dateFormat: '%m/%d/%Y',

  // Dates
  date: new Date(),
  currentDateElement: null,

  // Status
  shouldClose: false,
  isPopup: true,

  dateField: null,


  //----------------------------------------------------------------------------
  // Initialize
  //----------------------------------------------------------------------------

  initialize: function(parent)
  {
    if (parent)
      this.create($(parent))
    else
      this.create()
  },



  //----------------------------------------------------------------------------
  // Update / (Re)initialize Calendar
  //----------------------------------------------------------------------------

  update: function(date)
  {
    var calendar   = this
    var today      = new Date()
    var thisYear   = today.getFullYear()
    var thisMonth  = today.getMonth()
    var thisDay    = today.getDate()
    var month      = date.getMonth();
    var dayOfMonth = date.getDate();

    // Ensure date is within the defined range
    if (date.getFullYear() < this.minYear)
      date.setFullYear(this.minYear)
    else if (date.getFullYear() > this.maxYear)
      date.setFullYear(this.maxYear)

    this.date = new Date(date)

    Calendar.currentDisplayYear = date.getFullYear()

    // Calculate the first day to display (including the previous month)
    date.setDate(1)
    date.setDate(-(date.getDay()) + 1)

    // Fill in the days of the month
    Element.getElementsBySelector(this.container, 'tbody tr').each(
      function(row, i) {
        var rowHasDays = false
        row.immediateDescendants().each(
          function(cell, j) {
            var day            = date.getDate()
            var dayOfWeek      = date.getDay()
            var isCurrentMonth = (date.getMonth() == month)

            // Reset classes on the cell
            cell.className = ''
            cell.date = new Date(date)
            Element.update(cell, day)

            // Account for days of the month other than the current month
            if (!isCurrentMonth)
              Element.addClassName(cell, 'otherDay')
            else
              rowHasDays = true

            // Ensure the current day is selected
            if (isCurrentMonth && day == dayOfMonth) {
              Element.addClassName(cell, 'selected')
              calendar.currentDateElement = cell
            }

            // Today
            if (date.getFullYear() == thisYear && date.getMonth() == thisMonth && day == thisDay)
              Element.addClassName(cell, 'today')

            // Weekend
            if ([0, 6].indexOf(dayOfWeek) != -1)
              Element.addClassName(cell, 'weekend')

            // Set the date to tommorrow
            date.setDate(day + 1)
          }
        )
        // Hide the extra row if it contains only days from another month
        !rowHasDays ? Element.hide(row) : Element.show(row)
      }
    )


    this.container.getElementsBySelector('td.title')[0].update(
      Calendar.MONTH_NAMES[month] + ' ' + Calendar.currentDisplayYear
    )
  },



  //----------------------------------------------------------------------------
  // Create/Draw the Calendar HTML Elements
  //----------------------------------------------------------------------------

  create: function(parent)
  {

    // If no parent was specified, assume that we are creating a popup calendar.
    if (!parent) {
      parent = document.getElementsByTagName('body')[0]
      this.isPopup = true
    } else {
      this.isPopup = false
    }

    // Calendar Table
    var table = Builder.node('table')

    // Calendar Header
    var thead = Builder.node('thead')
    table.appendChild(thead)

    // Title Placeholder
    var row = Builder.node('tr', [ Builder.node('td', { colSpan: 7, className: 'title' })])
    thead.appendChild(row)

    // Calendar Navigation
    row = Builder.node('tr')
    this._drawButtonCell(row, '&#x00ab;', 1, Calendar.NAV_PREVIOUS_YEAR)
    this._drawButtonCell(row, '&#x2039;', 1, Calendar.NAV_PREVIOUS_MONTH)
    this._drawButtonCell(row, 'Today',    3, Calendar.NAV_TODAY)
    this._drawButtonCell(row, '&#x203a;', 1, Calendar.NAV_NEXT_MONTH)
    this._drawButtonCell(row, '&#x00bb;', 1, Calendar.NAV_NEXT_YEAR)
    thead.appendChild(row)

    // Day Names
    row = Builder.node('tr')
    for (var i = 0; i < 7; ++i) {
      cell = Builder.node('th', Calendar.SHORT_DAY_NAMES[i])
      if (i == 0 || i == 6)
        Element.addClassName(cell, 'weekend')
      row.appendChild(cell)
    }
    thead.appendChild(row)

    // Calendar Days
    var tbody = table.appendChild(Builder.node('tbody'))
    for (i = 6; i > 0; --i) {
      row = tbody.appendChild(Builder.node('tr', { className: 'days' }))
      for (var j = 7; j > 0; --j) {
        cell = row.appendChild(Builder.node('td'))
        cell.calendar = this
      }
    }

    // Calendar Container (div)
    this.container = Builder.node('div', { className: 'calendar' })
    if (this.isPopup) {
      Element.setStyle(this.container, { position: 'absolute', display: 'none' })
      Element.addClassName(this.container, 'popup')
    }
    this.container.appendChild(table)

    // Initialize Calendar
    this.update(this.date)

    // Observe the container for mousedown events
    Event.observe(this.container, 'mousedown', Calendar.handleMouseDownEvent)

    // Append to parent element
    parent.appendChild(this.container)

  },

  _drawButtonCell: function(parent, text, colSpan, navAction)
  {
    var cell          = Builder.node('td')
    if (colSpan > 1) cell.colSpan = colSpan
    cell.className    = 'button'
    cell.calendar     = this
    cell.navAction    = navAction
    cell.innerHTML    = text
    cell.unselectable = 'on' // IE
    parent.appendChild(cell)
    return cell
  },



  //------------------------------------------------------------------------------
  // Callbacks
  //------------------------------------------------------------------------------

  // Calls the Select Handler (if defined)
  callSelectHandler: function()
  {
    if (this.selectHandler)
      this.selectHandler(this, this.date.print(this.dateFormat))
  },

  // Calls the Close Handler (if defined)
  callCloseHandler: function()
  {
    if (this.closeHandler)
      this.closeHandler(this)
  },



  //------------------------------------------------------------------------------
  // Calendar Display Functions
  //------------------------------------------------------------------------------

  // Shows the Calendar
  show: function()
  {
    Element.show(this.container)
    if (this.isPopup) {
      window._popupCalendar = this
      Event.observe(document, 'mousedown', Calendar._checkCalendar)
    }
  },

  // Shows the calendar at the given absolute position
  showAt: function (x, y)
  {
    Element.setStyle(this.container, { left: x + 'px', top: y + 'px' })
    this.show()
  },

  // Shows the Calendar at the coordinates of the provided element
  showAtElement: function(element)
  {
    var pos = Position.cumulativeOffset(element)
    this.showAt(pos[0], pos[1])
  },

  // Hides the Calendar
  hide: function()
  {
    if (this.isPopup)
      Event.stopObserving(document, 'mousedown', Calendar._checkCalendar)
    Element.hide(this.container)
  },



  //------------------------------------------------------------------------------
  // Miscellaneous
  //------------------------------------------------------------------------------

  // Tries to identify the date represented in a string.  If successful it also
  // calls this.setDate which moves the calendar to the given date.
  parseDate: function(str, format)
  {
    if (!format)
      format = this.dateFormat
    this.setDate(Date.parseDate(str, format))
  },



  //------------------------------------------------------------------------------
  // Getters/Setters
  //------------------------------------------------------------------------------

  setSelectHandler: function(selectHandler)
  {
    this.selectHandler = selectHandler
  },

  setCloseHandler: function(closeHandler)
  {
    this.closeHandler = closeHandler
  },

  setDate: function(date)
  {
    if (!date.equalsTo(this.date))
      this.update(date)
  },

  setDateFormat: function(format)
  {
    this.dateFormat = format
  },

  setDateField: function(field)
  {
    this.dateField = $(field)
  },

  setRange: function(minYear, maxYear)
  {
    this.minYear = minYear
    this.maxYear = maxYear
  }

}

// global object that remembers the calendar
window._popupCalendar = null





//==============================================================================
//
// Date Object Patches
//
// This is pretty much untouched from the original. I really would like to get
// rid of these patches if at all possible and find a cleaner way of
// accomplishing the same things. It's a shame Prototype doesn't extend Date at
// all.
//
//==============================================================================

Date.DAYS_IN_MONTH = new Array(31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31)
Date.SECOND        = 1000 /* milliseconds */
Date.MINUTE        = 60 * Date.SECOND
Date.HOUR          = 60 * Date.MINUTE
Date.DAY           = 24 * Date.HOUR
Date.WEEK          =  7 * Date.DAY

// Parses Date
Date.parseDate = function(str, fmt) {
  var today = new Date();
  var y     = 0;
  var m     = -1;
  var d     = 0;
  var a     = str.split(/\W+/);
  var b     = fmt.match(/%./g);
  var i     = 0, j = 0;
  var hr    = 0;
  var min   = 0;

  for (i = 0; i < a.length; ++i) {
    if (!a[i]) continue;
    switch (b[i]) {
      case "%d":
      case "%e":
        d = parseInt(a[i], 10);
        break;
      case "%m":
        m = parseInt(a[i], 10) - 1;
        break;
      case "%Y":
      case "%y":
        y = parseInt(a[i], 10);
        (y < 100) && (y += (y > 29) ? 1900 : 2000);
        break;
      case "%b":
      case "%B":
        for (j = 0; j < 12; ++j) {
          if (Calendar.MONTH_NAMES[j].substr(0, a[i].length).toLowerCase() == a[i].toLowerCase()) {
            m = j;
            break;
          }
        }
        break;
      case "%H":
      case "%I":
      case "%k":
      case "%l":
        hr = parseInt(a[i], 10);
        break;
      case "%P":
      case "%p":
        if (/pm/i.test(a[i]) && hr < 12)
          hr += 12;
        else if (/am/i.test(a[i]) && hr >= 12)
          hr -= 12;
        break;
      case "%M":
        min = parseInt(a[i], 10);
        break;
    }
  }
  if (isNaN(y)) y = today.getFullYear();
  if (isNaN(m)) m = today.getMonth();
  if (isNaN(d)) d = today.getDate();
  if (isNaN(hr)) hr = today.getHours();
  if (isNaN(min)) min = today.getMinutes();
  if (y != 0 && m != -1 && d != 0)
    return new Date(y, m, d, hr, min, 0);
  y = 0; m = -1; d = 0;
  for (i = 0; i < a.length; ++i) {
    if (a[i].search(/[a-zA-Z]+/) != -1) {
      var t = -1;
      for (j = 0; j < 12; ++j) {
        if (Calendar.MONTH_NAMES[j].substr(0, a[i].length).toLowerCase() == a[i].toLowerCase()) { t = j; break; }
      }
      if (t != -1) {
        if (m != -1) {
          d = m+1;
        }
        m = t;
      }
    } else if (parseInt(a[i], 10) <= 12 && m == -1) {
      m = a[i]-1;
    } else if (parseInt(a[i], 10) > 31 && y == 0) {
      y = parseInt(a[i], 10);
      (y < 100) && (y += (y > 29) ? 1900 : 2000);
    } else if (d == 0) {
      d = a[i];
    }
  }
  if (y == 0)
    y = today.getFullYear();
  if (m != -1 && d != 0)
    return new Date(y, m, d, hr, min, 0);
  return today;
};

// Returns the number of days in the current month
Date.prototype.getMonthDays = function(month) {
  var year = this.getFullYear()
  if (typeof month == "undefined")
    month = this.getMonth()
  if (((0 == (year % 4)) && ( (0 != (year % 100)) || (0 == (year % 400)))) && month == 1)
    return 29
  else
    return Date.DAYS_IN_MONTH[month]
};

// Returns the number of day in the year
Date.prototype.getDayOfYear = function() {
  var now = new Date(this.getFullYear(), this.getMonth(), this.getDate(), 0, 0, 0);
  var then = new Date(this.getFullYear(), 0, 0, 0, 0, 0);
  var time = now - then;
  return Math.floor(time / Date.DAY);
};

/** Returns the number of the week in year, as defined in ISO 8601. */
Date.prototype.getWeekNumber = function() {
  var d = new Date(this.getFullYear(), this.getMonth(), this.getDate(), 0, 0, 0);
  var DoW = d.getDay();
  d.setDate(d.getDate() - (DoW + 6) % 7 + 3); // Nearest Thu
  var ms = d.valueOf(); // GMT
  d.setMonth(0);
  d.setDate(4); // Thu in Week 1
  return Math.round((ms - d.valueOf()) / (7 * 864e5)) + 1;
};

/** Checks date and time equality */
Date.prototype.equalsTo = function(date) {
  return ((this.getFullYear() == date.getFullYear()) &&
   (this.getMonth() == date.getMonth()) &&
   (this.getDate() == date.getDate()) &&
   (this.getHours() == date.getHours()) &&
   (this.getMinutes() == date.getMinutes()));
};

/** Set only the year, month, date parts (keep existing time) */
Date.prototype.setDateOnly = function(date) {
  var tmp = new Date(date);
  this.setDate(1);
  this.setFullYear(tmp.getFullYear());
  this.setMonth(tmp.getMonth());
  this.setDate(tmp.getDate());
};

/** Prints the date in a string according to the given format. */
Date.prototype.print = function (str) {
  var m = this.getMonth();
  var d = this.getDate();
  var y = this.getFullYear();
  var wn = this.getWeekNumber();
  var w = this.getDay();
  var s = {};
  var hr = this.getHours();
  var pm = (hr >= 12);
  var ir = (pm) ? (hr - 12) : hr;
  var dy = this.getDayOfYear();
  if (ir == 0)
    ir = 12;
  var min = this.getMinutes();
  var sec = this.getSeconds();
  s["%a"] = Calendar.SHORT_DAY_NAMES[w]; // abbreviated weekday name [FIXME: I18N]
  s["%A"] = Calendar.DAY_NAMES[w]; // full weekday name
  s["%b"] = Calendar.SHORT_MONTH_NAMES[m]; // abbreviated month name [FIXME: I18N]
  s["%B"] = Calendar.MONTH_NAMES[m]; // full month name
  // FIXME: %c : preferred date and time representation for the current locale
  s["%C"] = 1 + Math.floor(y / 100); // the century number
  s["%d"] = (d < 10) ? ("0" + d) : d; // the day of the month (range 01 to 31)
  s["%e"] = d; // the day of the month (range 1 to 31)
  // FIXME: %D : american date style: %m/%d/%y
  // FIXME: %E, %F, %G, %g, %h (man strftime)
  s["%H"] = (hr < 10) ? ("0" + hr) : hr; // hour, range 00 to 23 (24h format)
  s["%I"] = (ir < 10) ? ("0" + ir) : ir; // hour, range 01 to 12 (12h format)
  s["%j"] = (dy < 100) ? ((dy < 10) ? ("00" + dy) : ("0" + dy)) : dy; // day of the year (range 001 to 366)
  s["%k"] = hr;   // hour, range 0 to 23 (24h format)
  s["%l"] = ir;   // hour, range 1 to 12 (12h format)
  s["%m"] = (m < 9) ? ("0" + (1+m)) : (1+m); // month, range 01 to 12
  s["%M"] = (min < 10) ? ("0" + min) : min; // minute, range 00 to 59
  s["%n"] = "\n";   // a newline character
  s["%p"] = pm ? "PM" : "AM";
  s["%P"] = pm ? "pm" : "am";
  // FIXME: %r : the time in am/pm notation %I:%M:%S %p
  // FIXME: %R : the time in 24-hour notation %H:%M
  s["%s"] = Math.floor(this.getTime() / 1000);
  s["%S"] = (sec < 10) ? ("0" + sec) : sec; // seconds, range 00 to 59
  s["%t"] = "\t";   // a tab character
  // FIXME: %T : the time in 24-hour notation (%H:%M:%S)
  s["%U"] = s["%W"] = s["%V"] = (wn < 10) ? ("0" + wn) : wn;
  s["%u"] = w + 1;  // the day of the week (range 1 to 7, 1 = MON)
  s["%w"] = w;    // the day of the week (range 0 to 6, 0 = SUN)
  // FIXME: %x : preferred date representation for the current locale without the time
  // FIXME: %X : preferred time representation for the current locale without the date
  s["%y"] = ('' + y).substr(2, 2); // year without the century (range 00 to 99)
  s["%Y"] = y;    // year with the century
  s["%%"] = "%";    // a literal '%' character

  return str.gsub(/%./, function(match) { return s[match] || match });
};

Date.prototype.__msh_oldSetFullYear = Date.prototype.setFullYear;
Date.prototype.setFullYear = function(y) {
  var d = new Date(this);
  d.__msh_oldSetFullYear(y);
  if (d.getMonth() != this.getMonth())
    this.setDate(28);
  this.__msh_oldSetFullYear(y);
}



/**
 * @author Ryan Johnson <ryan@livepipe.net>
 * @copyright 2007 LivePipe LLC
 * @package Control.Tabs
 * @license MIT
 * @url http://livepipe.net/projects/control_tabs/
 * @version 2.1.1
 */

if(typeof(Control) == 'undefined')
	var Control = {};
Control.Tabs = Class.create();
Object.extend(Control.Tabs,{
	instances: [],
	findByTabId: function(id){
		return Control.Tabs.instances.find(function(tab){
			return tab.links.find(function(link){
				return link.key == id;
			});
		});
	}
});
Object.extend(Control.Tabs.prototype,{
	initialize: function(tab_list_container,options){
		this.activeContainer = false;
		this.activeLink = false;
		this.containers = $H({});
		this.links = [];
		Control.Tabs.instances.push(this);
		this.options = {
			beforeChange: Prototype.emptyFunction,
			afterChange: Prototype.emptyFunction,
			hover: false,
			linkSelector: 'li a',
			setClassOnContainer: false,
			activeClassName: 'active',
			defaultTab: 'first',
			autoLinkExternal: true,
			targetRegExp: /#(.+)$/,
			showFunction: Element.show,
			hideFunction: Element.hide
		};
		Object.extend(this.options,options || {});
		(typeof(this.options.linkSelector == 'string')
			? $(tab_list_container).getElementsBySelector(this.options.linkSelector)
			: this.options.linkSelector($(tab_list_container))
		).findAll(function(link){
			return (/^#/).exec(link.href.replace(window.location.href.split('#')[0],''));
		}).each(function(link){
			this.addTab(link);
		}.bind(this));
		this.containers.values().each(this.options.hideFunction);
		if(this.options.defaultTab == 'first')
			this.setActiveTab(this.links.first());
		else if(this.options.defaultTab == 'last')
			this.setActiveTab(this.links.last());
		else
			this.setActiveTab(this.options.defaultTab);
		var targets = this.options.targetRegExp.exec(window.location);
		if(targets && targets[1]){
			targets[1].split(',').each(function(target){
				this.links.each(function(target,link){
					if(link.key == target){
						this.setActiveTab(link);
						throw $break;
					}
				}.bind(this,target));
			}.bind(this));
		}
		if(this.options.autoLinkExternal){
			$A(document.getElementsByTagName('a')).each(function(a){
				if(!this.links.include(a)){
					var clean_href = a.href.replace(window.location.href.split('#')[0],'');
					if(clean_href.substring(0,1) == '#'){
						if(this.containers.keys().include(clean_href.substring(1))){
							$(a).observe('click',function(event,clean_href){
								this.setActiveTab(clean_href.substring(1));
							}.bindAsEventListener(this,clean_href));
						}
					}
				}
			}.bind(this));
		}
	},
	addTab: function(link){
		this.links.push(link);
		link.key = link.getAttribute('href').replace(window.location.href.split('#')[0],'').split('#').last().replace(/#/,'');
		this.containers[link.key] = $(link.key);
		
		link[this.options.hover ? 'onmouseover' : 'onclick'] = function(link){
			if(window.event)
				Event.stop(window.event);
			this.setActiveTab(link);
			return false;
		}.bind(this,link);
	},
	setActiveTab: function(link){
		if(!link)
			return;
		if(typeof(link) == 'string'){
			this.links.each(function(_link){
				if(_link.key == link){
					this.setActiveTab(_link);
					throw $break;
				}
			}.bind(this));
		}else{
			this.notify('beforeChange',this.activeContainer);
			if(this.activeContainer)
				this.options.hideFunction(this.activeContainer);
			this.links.each(function(item){
				(this.options.setClassOnContainer ? $(item.parentNode) : item).removeClassName(this.options.activeClassName);
			}.bind(this));
			(this.options.setClassOnContainer ? $(link.parentNode) : link).addClassName(this.options.activeClassName);
			this.activeContainer = this.containers[link.key];
			this.activeLink = link;
			this.options.showFunction(this.containers[link.key]);
			this.notify('afterChange',this.containers[link.key]);
		}
	},
	next: function(){
		this.links.each(function(link,i){
			if(this.activeLink == link && this.links[i + 1]){
				this.setActiveTab(this.links[i + 1]);
				throw $break;
			}
		}.bind(this));
		return false;
	},
	previous: function(){
		this.links.each(function(link,i){
			if(this.activeLink == link && this.links[i - 1]){
				this.setActiveTab(this.links[i - 1]);
				throw $break;
			}
		}.bind(this));
		return false;
	},
	first: function(){
		this.setActiveTab(this.links.first());
		return false;
	},
	last: function(){
		this.setActiveTab(this.links.last());
		return false;
	},
	notify: function(event_name){
		try{
			if(this.options[event_name])
				return [this.options[event_name].apply(this.options[event_name],$A(arguments).slice(1))];
		}catch(e){
			if(e != $break)
				throw e;
			else
				return false;
		}
	}
});
if(typeof(Object.Event) != 'undefined')
	Object.Event.extend(Control.Tabs);
	





/* DateRangeCalendar
-------------------------------------------------------*/

function DateRange(name,containerId,valueFieldId,startFieldId,endFieldId,callback) 
{
	this.name = name;
	this.containerId = containerId;
	this.valueFieldId = valueFieldId;
	this.startFieldId = startFieldId;
	this.endFieldId = endFieldId;
	this.created = false;
	this.element = null;
	this.container = null;
	this.callback = callback;
	
	this.setup = function() 
	{
		var pos = Position.cumulativeOffset($(this.containerId))
		
		posrightedge = pos[0]+395;
		if (posrightedge > document.viewport.getWidth()) {
			posDifference = posrightedge - document.viewport.getWidth();
			pos[0] = pos[0]-posDifference;
		}
		
		
		bodyElement = $$('body')[0];
   
		this.container = Builder.node('div', { className: 'dateRangeCalendar'});
		Element.setStyle(this.container, { display: 'none', position: 'absolute', left: pos[0]-6 + 'px', top: pos[1]+30 + 'px', width: '377px'})
		
		this.startLabel = Builder.node('span', { },'Start Date:');
		this.endLabel = Builder.node('span', { },'End Date:');
		Element.setStyle(this.endLabel, { margin: '0px 0px 0px 130px'  })
   		
		labelWrapper = Builder.node('div', {  });
		Element.setStyle(labelWrapper, { height: '20px', clear:'both'  })
		
		buttonWrapper = Builder.node('div', {  });
		Element.setStyle(buttonWrapper, { height: '25px', clear:'both'  })
   	
   		clearButton = Builder.node('a', { className: 'smbutton back', href: 'javascript:void(0)', onclick: name + '.clearValues();' }, 'Clear');
		applyButton = Builder.node('a', { className: 'smbutton next', href: 'javascript:void(0)', onclick: name + '.setValues();' }, 'Apply');
				
		labelWrapper.appendChild(this.startLabel);
		labelWrapper.appendChild(this.endLabel);
		this.container.appendChild(labelWrapper);
		
		Calendar.setup({ dateField : $(this.startFieldId),parentElement:this.container });
		Calendar.setup({ dateField : $(this.endFieldId),parentElement:this.container });
		
		buttonWrapper.appendChild(clearButton);
		buttonWrapper.appendChild(applyButton);
		this.container.appendChild(buttonWrapper);
		
		bodyElement.appendChild(this.container);
	}
	
	this.show = function() 
	{
		if (this.created == false) {
			this.setup();
		}
		
		new Effect.Appear(this.container,{duration: 0.3});
		this.created = true;
		
	}
	
	this.clearValues = function()
	{
		$(startFieldId).innerHTML = 'Start Date';
		$(endFieldId).innerHTML = 'End Date';
		
		$(this.valueFieldId).value = 'DATERANGE(00/00/0000-99/99/9999)';
		this.close();
	}
	
	this.setValues = function() 
	{
		startvalue = $(startFieldId).innerHTML;
		endvalue = $(endFieldId).innerHTML;
		
		if (endvalue != 'End Date' || startvalue != 'Start Date') {			
			
			if (startvalue == 'Start Date') {
				var tmp = new Date();
				startvalue = (tmp.getMonth()+1) + '/' + tmp.getDate() + '/' + tmp.getFullYear();
			}
			
			if (endvalue == 'End Date') {
				var tmp = new Date();
				endvalue = (tmp.getMonth()+1) + '/' + tmp.getDate() + '/' + tmp.getFullYear();
			}
			
			startArray = startvalue.split( "/" );
			endArray = endvalue.split( "/" );
			
			startMonth =  parseFloat(startArray[0]);
			startDay =  parseFloat(startArray[1]);
			startYear =  parseFloat(startArray[2]);
			
			endMonth =  parseFloat(endArray[0]);
			endDay =  parseFloat(endArray[1]);
			endYear =  parseFloat(endArray[2]);
			
			
			dateFailString = 'The start date must be earlier than the end date'; 
			
			if (startYear > endYear) {
				alert(dateFailString);
				return false;
			}
			
			if (startYear == endYear && startMonth > endMonth) {
				alert(dateFailString);
				return false;
			}
			
			if (startYear == endYear && startMonth == endMonth && startDay > endDay) {
				alert(dateFailString);
				return false;
			}
		}
		
		if (startvalue == 'Start Date') {
			startvalue = '00/00/0000';
		}
		
		if (endvalue == 'End Date') {
			endvalue = '99/99/9999';
		}
		
		$(this.valueFieldId).value = 'DATERANGE('+startvalue+'-'+endvalue+')';
		this.close();
	}
	
	this.close = function() 
	{
		new Effect.Fade(this.container,{duration: 0.1});
		if (this.callback) {
			eval(this.callback);
		}
	}
}	


/**
 * flightdetails.js
 *
 * @description:  displays a message on the bottom of a table-field
 */
 
var fbo =  Class.create( 
{
	initialize: function() {
	//alert( "am in initialize.." );
		//config vars, can be set during runtime if the appropriate setters are created for each config var
		/* comma separated list of field elements */
	 	this.fields = "DEPARTLOCATION, ARRIVELOCATION";
	 	/* string that is displayed when there is no information returned by the ajax script */
	 	this.noFBOInfo = "<span>FBO information not found.</span>";
	 	/* string that is appended to this.id to generate this.childDivId */
	 	this.childDivSuffix = "_fboInfo";
	 	/* location of the ajax script */
	 	this.ajaxURL = '/flightlog/flights/showxmlfboinformation';
	 	/* message that is displayed before making the ajax request */
	 	this.loadingMessage = "Loading FBO Information...";
	 	/* holds the id of the childDiv */
	 	this.childDivId = null;
	 	/* minimum number of characters the element's value must have before making an ajax request */
	 	this.minValChars = 3;
	 	/* maximum number of characters the element can have before the script terminates execution of the ajax request handler */
	 	this.maxValChars = 3;
	 	/* holds the array of fields */
	 	this.fieldsArray = this.fields.split( "," );
	 	/* holds the id of the current element */
	 	this.id = 0;
	 	/* holds the returned xml value */
	 	this.fboInfoXML = null;
	},
	 
 	init: function() {//alert( "am in init.." );
		for( i = 0; i <= this.fieldsArray.length; i++ ) {
			if( this.fieldsArray[ i ] != null ) {		
		 		this.id = this.fieldsArray[ i ].replace( /^\s+|\s+$/g, '' );
		 		this.element = $( this.id );
		 		//alert( "trying to setup this thing: " + this.id );
		 		if( this.element != null ) {
		 		//alert( "this thing isn't null: " + this.id );
		 			Event.observe( this.element, 'keyup', updateFBOInfoEventHandler );
		 			//alert( "trying to set up: " + this.id );
		 			this.childDivId = this.id + this.childDivSuffix;
		 			this.getFBOInformation();
		 		}
		 	}
	 	}
	},
 
	getFBOInformation: function() {	//alert( "am in getFBOInformation.." );	
		if( $F( this.id ) != '' ) {
			var txtValue = $F( this.id );
			var elementID = this.id;
			
			// display "Loading..." message in childDiv right before making the ajax request
			this.createDiv( this.childDivId, this.element.parentNode ); // running function just in case childDiv wasn't created
			this.setDivInnerHTML( this.childDivId, this.loadingMessage );
			
			new Ajax.Request( this.ajaxURL,
				{
					method: 'get',
					parameters: { txtString: txtValue },
					onComplete: function( transport ) {
						var response = transport.responseText || this.noFBOInfo;
						setFBOInfoAjaxHandler( elementID, response );
					},
					onFailure: function() { 
						alert( 'Sorry!  We are unable to retrieve FBO information at this time.' ); 
					}
				} 
			);
		}
	},
 
 	createDiv: function( divId, parentDiv ) {
 		var childDiv = $( divId );
 		
 		if( parentDiv == null ) {
	 			parentDiv = this.element.parentNode;
	 	}
	 		
		if( childDiv == null ) {	 		
	 		childDiv = document.createElement( 'div' );
	 		childDiv.setAttribute( 'id', divId );
	 		parentDiv.appendChild( childDiv );
	 	}
 	},
 	
 	setDivInnerHTML: function( divId, text ) {
 		$( divId ).innerHTML = text;
 	},
 	
	setFBOInformation: function( fboXML ) { 
	 	//alert( "am in setFBOInformation.., childDivId is: " + this.childDivId );
		this.childDivId = this.id + this.childDivSuffix; 
		var childDiv = $( this.childDivId );
	 	var parentElement = this.element.parentNode;
	 	if( ( $F( this.id ).length >= this.minValChars ) && ( $F( this.id ).length <= this.maxValChars ) ) {
	 		this.createDiv( this.childDivId, parentElement );
			( fboXML == null ) ? this.setDivInnerHTML( this.childDivId, this.noFBOInfo ) : this.setDivInnerHTML( this.childDivId, fboXML );
		}
	}
 } // end class FBO
 
 ) // end class create
 
 function updateFBOInfoEventHandler( e ) { //alert( "am in updateEventHandler.." );
 	fbo_field = new fbo();
 	fbo_field.id = e.target.getAttribute( 'id' );
 	fbo_field.childDivId = fbo_field.id + fbo_field.childDivSuffix;
 	fbo_field.element = $( fbo_field.id );
 	
 	if( ( e.keyCode || e.which ) != 9  && e.keyCode != 16 ) {
	 	if( ( $F( fbo_field.id ).length >= fbo_field.minValChars ) && ( $F( fbo_field.id ).length <= fbo_field.maxValChars ) ) {
		 	fbo_field.fieldsArray.push( fbo_field.id );
		 	fbo_field.getFBOInformation();
		}
	}
	
	if ( $F( fbo_field.id ).length < fbo_field.minValChars  ) {
		if( $( fbo_field.childDivId ) != null ) {
			fbo_field.setDivInnerHTML( fbo_field.childDivId, '' );
			$( fbo_field.childDivId ).parentNode.removeChild( $( fbo_field.childDivId ) );
			//alert( "removed: " + fbo_field.id + fbo_field.childDivSuffix );
		}
		return;
	}
 }
 
 function setFBOInfoAjaxHandler( elementID, xmlResponse ) { //alert( "am in setFBOInfoAjaxHandler.., elementId is: " + elementID + "and response is: " + xmlResponse );
 	fbo_field = new fbo();
 	fbo_field.id = elementID;
 	fbo_field.element = $( fbo_field.id );
 	fbo_field.childDivId = fbo_field.id + fbo_field.childDivSuffix;
 	fbo_field.setFBOInformation( xmlResponse );
 }
 
 function updateVendorDetails()
{
	var vendorselect = document.getElementById("VENDORID");
	var url = "/debitmemo/index/showxmlvendorinfo?vendorid=" + vendorselect.options[vendorselect.selectedIndex].value;
	var req;
	
	var fieldAddress = document.getElementById('ADDRESS_');
	var fieldAttention = document.getElementById('ATTENTION_');
	
	fieldAddress.innerHTML = "Loading...";
	fieldAttention.innerHTML = "Loading...";
	
	if ((!fieldAddress) || (!fieldAttention)) return;		
	
	// branch for native XMLHttpRequest object
	if (window.XMLHttpRequest) {
	    req = new XMLHttpRequest();	        
	    req.open("GET", url, false);
	    req.send(null);
	 	        
	 // branch for IE/Windows ActiveX version
	 } else if (window.ActiveXObject) {
	    isIE = true;
	    req = new ActiveXObject("Microsoft.XMLHTTP");
	    
	    if (req) {	            
	        req.open("GET", url, false);
	        req.send();
        }
    }
	    
    var xdoc = req.responseXML;
	    
    if (xdoc) {
		var items = xdoc.getElementsByTagName("option");
		
		if (items.length>0) {
			fieldAddress.innerHTML = items[0].getElementsByTagName("vendoraddress")[0].firstChild.nodeValue;
				
			var contactname = "&nbsp;";
				
			contactname=items[0].getElementsByTagName("contactname")[0].firstChild.nodeValue;
						 
			fieldAttention.innerHTML = contactname;
		}
	} else {
		fieldAddress.innerHTML = "An error occured while loading this information from the server.";
		fieldAttention.innerHTML = "An error occured while loading this information from the server.";
	}
}

function hideUnneededFields()
{
	alert("In hideUnneededFields");
	var typeselect = document.getElementById("DEBITMEMOTYPEID");
	var url = "/debitmemo/index/displayXMLFormFields?typeid=" + typeselect.options[typeselect.selectedIndex].value;
	var req;
	
	// branch for native XMLHttpRequest object
	if (window.XMLHttpRequest) {
	    req = new XMLHttpRequest();	        
	    req.open("GET", url, false);
	    req.send(null);
	 	        
	 // branch for IE/Windows ActiveX version
	 } else if (window.ActiveXObject) {
	    isIE = true;
	    req = new ActiveXObject("Microsoft.XMLHTTP");
	    
	    if (req) {	            
	        req.open("GET", url, false);
	        req.send();
        }
    }
	    
    var xdoc = req.responseXML;
	    
    if (xdoc) {
		var items = xdoc.getElementsByTagName("option");
	
		alert(items.length);	
		if (items.length>0) {
//			var fieldlist = document.getElementsByTagName('showfields');
//			alert(fieldlist);
			
//			if (fieldlist.length > 0) {
//				for (i = 0; i < fieldlist.length; i++) {
//					alert(fieldlist[i]);
//					var field = document.getElementById(fieldlist[i]);
//					field.style.display = 'block';
//				}
//			} 
				
//			fieldlist = document.getElementsByTagName('hidefields');
			
//			if (fieldlist.length > 0) {
//				for (i = 0; i < fieldlist.length; i++) {
//					var field = document.getElementById(fieldlist[i]);
//					field.style.display = 'none';
//				}
//			}	
		}		
	}			
}				
 
function setParticipants(values,count) 
{
	//xhtml = '<div id=\"div-CURRENTPARTICIPANTSNAV_\"><div><b>Current Participants: '+count+'</b>';
	//xhtml += '<a href=\"javascript:void(0);\" onclick=\"new Effect.toggle($(\'div-CURRENTPARTICIPANTS_\'),\'blind\',{duration: 0.8});\" class=\"Xbutton\">Show/Hide Current Participants</a>';
	//xhtml += '</div><div class=\"clear\"></div>';
	//xhtml += '<div class=\"participantsfooter\" id=\"div-CURRENTPARTICIPANTS_\" style=\"display:none;\"><small>'+values+'</small></div>';
	//xhtml += '<div class=\"clear\"></div></div>';
	//$('PARTICIPANTSMETHODWRAPPER').innerHTML = xhtml;
	document.fm.PARTICIPANTSCHOOSE_.value = values;
}
	
function setTraits( values ) 
{
	field = $('STORESELECTION');
	
	if( field ) {
		$('STORESELECTION').value = values;
	}
}

function checkType() 
{
	if (document.fm.QUESTIONTYPEID.value == '2') {
		new Effect.Fade($('table-MAXQUANTITY'),{duration: 0});
		new Effect.Appear($('table-RESPONSES_'),{duration: 0.5});
		new Effect.Appear($('table-COPYRESPONSESBUTTON_'),{duration: 0.5});
		new Effect.Appear($('table-KWMULTI'),{duration: 0.5});
	} else if (document.fm.QUESTIONTYPEID.value == '3') {
		new Effect.Fade($('table-KWMULTI'),{duration: 0});
		new Effect.Fade($('table-RESPONSES_'),{duration: 0});
		new Effect.Fade($('table-COPYRESPONSESBUTTON_'),{duration: 0});
		new Effect.Appear($('table-MAXQUANTITY'),{duration: 0.5});
	} else {
		new Effect.Fade($('table-KWMULTI'),{duration: 0});
		new Effect.Fade($('table-RESPONSES_'),{duration: 0});
		new Effect.Fade($('table-COPYRESPONSESBUTTON_'),{duration: 0});
		new Effect.Fade($('table-MAXQUANTITY'),{duration: 0});
	}
}

function setStoresCount()
{
	$( 'STORESCURRENTLYSELECTED' ).value = $( 'PARTICIPANTSCHOOSE_' ).value.split( "," ).length;
}

function checkParticipants()
{
	for (var i=0; i < document.fm.PARTICIPANTSMETHOD_.length; i++)
	{
		if (document.fm.PARTICIPANTSMETHOD_[i].checked)
		{
			var partval = document.fm.PARTICIPANTSMETHOD_[i].value;
	  
			if (partval == 'UF') {
				new Effect.Fade($('table-PARTICIPANTSCHOOSEBUTTON_'),{duration: 0});
				new Effect.Fade($('table-PARTICIPANTSALIGNBUTTON_'),{duration: 0});
				new Effect.Appear($('table-PARTICIPANTSUPLOADBUTTON_'),{duration: 0, delay: 0.1});
				new Effect.Appear($('PARTICIPANTSTEXTAREA'),{duration: 0.5});				
			} else if (partval == 'AGN') {
				new Effect.Fade($('table-PARTICIPANTSCHOOSEBUTTON_'),{duration: 0});
				new Effect.Fade($('table-PARTICIPANTSUPLOADBUTTON_'),{duration: 0});
				new Effect.Appear($('table-PARTICIPANTSALIGNBUTTON_'),{duration: 0, delay: 0.1});
				new Effect.Appear($('PARTICIPANTSTEXTAREA'),{duration: 0.5});				
			} else if (partval == 'CUR') {
				new Effect.Fade($('table-PARTICIPANTSCHOOSEBUTTON_'),{duration: 0});
				new Effect.Fade($('table-PARTICIPANTSUPLOADBUTTON_'),{duration: 0});
				new Effect.Fade($('table-PARTICIPANTSALIGNBUTTON_'),{duration: 0});
				new Effect.Appear($('PARTICIPANTSTEXTAREA'),{duration: 0.5});				
			} else if (partval == 'ALL') {
				new Effect.Fade($('table-PARTICIPANTSCHOOSEBUTTON_'),{duration: 0});
				new Effect.Fade($('table-PARTICIPANTSUPLOADBUTTON_'),{duration: 0});
				new Effect.Fade($('table-PARTICIPANTSALIGNBUTTON_'),{duration: 0});
				new Effect.Fade($('PARTICIPANTSTEXTAREA'),{duration: 0});				
			} else {
				new Effect.Fade($('table-PARTICIPANTSALIGNBUTTON_'),{duration: 0});
				new Effect.Fade($('table-PARTICIPANTSUPLOADBUTTON_'),{duration: 0});
				new Effect.Appear($('table-PARTICIPANTSCHOOSEBUTTON_'),{duration: 0, delay: 0.1});
				new Effect.Appear($('PARTICIPANTSTEXTAREA'),{duration: 0.5});		
			}
		}
	}
}	

var parents = [];
var responses = [];

function addResponseCondition(id,qid,rid,text) {
	responses[id] = [qid,rid,text];
}

function addParentCondition(id,qid,type,text) {
	parents[id] = [qid,type,text];
}

function buildResponseHTML(id) {
	responsehtml = '<table class=\"tblform\"><tr><td width=\"25%\"><label>Show question when user selects</label></td><td><select name=\"QUESTIONPARENTCONDRESP\">';
	
	for (var i=0; i < responses.length; i++) {
	
		if (id == responses[i][0]) {
			responsehtml += '<option value=\"';
			responsehtml += responses[i][1];
			
			if (selected == responses[i][1]) {
			responsehtml += '\" selected>';
			} else {
			responsehtml += '\">';
			}
			
			responsehtml += responses[i][2];
			responsehtml += '</option>';
		}
	}
	
	responsehtml += '</select></td></tr></table>';
	return responsehtml;
}

function showParentConditions(id) {
	
	$('div-QUESTIONPARENTCOND_').innerHTML = '';
	for (var i=0; i < parents.length; i++) {
		if (parents[i][0] == id) {
			addParentConditionHTML(parents[i][0],parents[i][1],parents[i][2])
		}
	}
	
	if (id == 0) {
		
		new Effect.Appear($('participantWrapper'),{duration: 0});
		new Effect.Appear($('table-VENDORS_'),{duration: 0});
	} else {
		
		new Effect.Fade($('participantWrapper'),{duration: 0});
		new Effect.Fade($('table-VENDORS_'),{duration: 0});
	}
}
	
function addParentConditionHTML(id, type, title) {
	if (type == 1 || type == 2) {
		$('div-QUESTIONPARENTCOND_').innerHTML = buildResponseHTML(id);
	}
	else {
		$('div-QUESTIONPARENTCOND_').innerHTML = '';
	}
}

function updateParentConditions() {
	
	if (document.fm.PARENTQUESTIONID.options == null) {
		var questionid = document.fm.PARENTQUESTIONID.value;
	
	} else {
	
		var questionid = document.fm.PARENTQUESTIONID.options[document.fm.PARENTQUESTIONID.selectedIndex].value;
	}
	
	showParentConditions(questionid);
}

/* This notice must be untouched at all times.
Copyright (c) 2002-2008 Walter Zorn. All rights reserved.

wz_tooltip.js	 v. 5.31

The latest version is available at
http://www.walterzorn.com
or http://www.devira.com
or http://www.walterzorn.de

Created 1.12.2002 by Walter Zorn (Web: http://www.walterzorn.com )
Last modified: 7.11.2008

Easy-to-use cross-browser tooltips.
Just include the script at the beginning of the <body> section, and invoke
Tip('Tooltip text') to show and UnTip() to hide the tooltip, from the desired
HTML eventhandlers. Example:
<a onmouseover="Tip('Some text')" onmouseout="UnTip()" href="index.htm">My home page</a>
No container DIV required.
By default, width and height of tooltips are automatically adapted to content.
Is even capable of dynamically converting arbitrary HTML elements to tooltips
by calling TagToTip('ID_of_HTML_element_to_be_converted') instead of Tip(),
which means you can put important, search-engine-relevant stuff into tooltips.
Appearance & behaviour of tooltips can be individually configured
via commands passed to Tip() or TagToTip().

Tab Width: 4
LICENSE: LGPL

This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
License (LGPL) as published by the Free Software Foundation; either
version 2.1 of the License, or (at your option) any later version.

This library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.

For more details on the GNU Lesser General Public License,
see http://www.gnu.org/copyleft/lesser.html
*/

var config = new Object();


//===================  GLOBAL TOOLTIP CONFIGURATION  =========================//
var tt_Debug	= true		// false or true - recommended: false once you release your page to the public
var tt_Enabled	= true		// Allows to (temporarily) suppress tooltips, e.g. by providing the user with a button that sets this global variable to false
var TagsToTip	= true		// false or true - if true, HTML elements to be converted to tooltips via TagToTip() are automatically hidden;
							// if false, you should hide those HTML elements yourself

// For each of the following config variables there exists a command, which is
// just the variablename in uppercase, to be passed to Tip() or TagToTip() to
// configure tooltips individually. Individual commands override global
// configuration. Order of commands is arbitrary.
// Example: onmouseover="Tip('Tooltip text', LEFT, true, BGCOLOR, '#FF9900', FADEIN, 400)"

config. Above			= false		// false or true - tooltip above mousepointer
config. BgColor			= '#E2E7FF'	// Background colour (HTML colour value, in quotes)
config. BgImg			= ''		// Path to background image, none if empty string ''
config. BorderColor		= '#003099'
config. BorderStyle		= 'solid'	// Any permitted CSS value, but I recommend 'solid', 'dotted' or 'dashed'
config. BorderWidth		= 1
config. CenterMouse		= false		// false or true - center the tip horizontally below (or above) the mousepointer
config. ClickClose		= false		// false or true - close tooltip if the user clicks somewhere
config. ClickSticky		= false		// false or true - make tooltip sticky if user left-clicks on the hovered element while the tooltip is active
config. CloseBtn		= false		// false or true - closebutton in titlebar
config. CloseBtnColors	= ['#990000', '#FFFFFF', '#DD3333', '#FFFFFF']	// [Background, text, hovered background, hovered text] - use empty strings '' to inherit title colours
config. CloseBtnText	= '&nbsp;X&nbsp;'	// Close button text (may also be an image tag)
config. CopyContent		= true		// When converting a HTML element to a tooltip, copy only the element's content, rather than converting the element by its own
config. Delay			= 400		// Time span in ms until tooltip shows up
config. Duration		= 0			// Time span in ms after which the tooltip disappears; 0 for infinite duration, < 0 for delay in ms _after_ the onmouseout until the tooltip disappears
config. Exclusive		= false		// false or true - no other tooltip can appear until the current one has actively been closed
config. FadeIn			= 100		// Fade-in duration in ms, e.g. 400; 0 for no animation
config. FadeOut			= 100
config. FadeInterval	= 30		// Duration of each fade step in ms (recommended: 30) - shorter is smoother but causes more CPU-load
config. Fix				= null		// Fixated position, two modes. Mode 1: x- an y-coordinates in brackets, e.g. [210, 480]. Mode 2: Show tooltip at a position related to an HTML element: [ID of HTML element, x-offset, y-offset from HTML element], e.g. ['SomeID', 10, 30]. Value null (default) for no fixated positioning.
config. FollowMouse		= true		// false or true - tooltip follows the mouse
config. FontColor		= '#000044'
config. FontFace		= 'Verdana,Geneva,sans-serif'
config. FontSize		= '8pt'		// E.g. '9pt' or '12px' - unit is mandatory
config. FontWeight		= 'normal'	// 'normal' or 'bold';
config. Height			= 0			// Tooltip height; 0 for automatic adaption to tooltip content, < 0 (e.g. -100) for a maximum for automatic adaption
config. JumpHorz		= false		// false or true - jump horizontally to other side of mouse if tooltip would extend past clientarea boundary
config. JumpVert		= true		// false or true - jump vertically		"
config. Left			= false		// false or true - tooltip on the left of the mouse
config. OffsetX			= 14		// Horizontal offset of left-top corner from mousepointer
config. OffsetY			= 8			// Vertical offset
config. Opacity			= 100		// Integer between 0 and 100 - opacity of tooltip in percent
config. Padding			= 3			// Spacing between border and content
config. Shadow			= false		// false or true
config. ShadowColor		= '#C0C0C0'
config. ShadowWidth		= 5
config. Sticky			= false		// false or true - fixate tip, ie. don't follow the mouse and don't hide on mouseout
config. TextAlign		= 'left'	// 'left', 'right' or 'justify'
config. Title			= ''		// Default title text applied to all tips (no default title: empty string '')
config. TitleAlign		= 'left'	// 'left' or 'right' - text alignment inside the title bar
config. TitleBgColor	= ''		// If empty string '', BorderColor will be used
config. TitleFontColor	= '#FFFFFF'	// Color of title text - if '', BgColor (of tooltip body) will be used
config. TitleFontFace	= ''		// If '' use FontFace (boldified)
config. TitleFontSize	= ''		// If '' use FontSize
config. TitlePadding	= 2
config. Width			= 0			// Tooltip width; 0 for automatic adaption to tooltip content; < -1 (e.g. -240) for a maximum width for that automatic adaption;
									// -1: tooltip width confined to the width required for the titlebar
//=======  END OF TOOLTIP CONFIG, DO NOT CHANGE ANYTHING BELOW  ==============//




//=====================  PUBLIC  =============================================//
function Tip()
{
	tt_Tip(arguments, null);
}
function TagToTip()
{
	var t2t = tt_GetElt(arguments[0]);
	if(t2t)
		tt_Tip(arguments, t2t);
}
function UnTip()
{
	tt_OpReHref();
	if(tt_aV[DURATION] < 0 && (tt_iState & 0x2))
		tt_tDurt.Timer("tt_HideInit()", -tt_aV[DURATION], true);
	else if(!(tt_aV[STICKY] && (tt_iState & 0x2)))
		tt_HideInit();
}

//==================  PUBLIC PLUGIN API	 =====================================//
// Extension eventhandlers currently supported:
// OnLoadConfig, OnCreateContentString, OnSubDivsCreated, OnShow, OnMoveBefore,
// OnMoveAfter, OnHideInit, OnHide, OnKill

var tt_aElt = new Array(10), // Container DIV, outer title & body DIVs, inner title & body TDs, closebutton SPAN, shadow DIVs, and IFRAME to cover windowed elements in IE
tt_aV = new Array(),	// Caches and enumerates config data for currently active tooltip
tt_sContent,			// Inner tooltip text or HTML
tt_t2t, tt_t2tDad,		// Tag converted to tip, and its DOM parent element
tt_musX, tt_musY,
tt_over,
tt_x, tt_y, tt_w, tt_h; // Position, width and height of currently displayed tooltip

function tt_Extension()
{
	tt_ExtCmdEnum();
	tt_aExt[tt_aExt.length] = this;
	return this;
}
function tt_SetTipPos(x, y)
{
	var css = tt_aElt[0].style;

	tt_x = x;
	tt_y = y;
	css.left = x + "px";
	css.top = y + "px";
	if(tt_ie56)
	{
		var ifrm = tt_aElt[tt_aElt.length - 1];
		if(ifrm)
		{
			ifrm.style.left = css.left;
			ifrm.style.top = css.top;
		}
	}
}
function tt_HideInit()
{
	if(tt_iState)
	{
		tt_ExtCallFncs(0, "HideInit");
		tt_iState &= ~(0x4 | 0x8);
		if(tt_flagOpa && tt_aV[FADEOUT])
		{
			tt_tFade.EndTimer();
			if(tt_opa)
			{
				var n = Math.round(tt_aV[FADEOUT] / (tt_aV[FADEINTERVAL] * (tt_aV[OPACITY] / tt_opa)));
				tt_Fade(tt_opa, tt_opa, 0, n);
				return;
			}
		}
		tt_tHide.Timer("tt_Hide();", 1, false);
	}
}
function tt_Hide()
{
	if(tt_db && tt_iState)
	{
		tt_OpReHref();
		if(tt_iState & 0x2)
		{
			tt_aElt[0].style.visibility = "hidden";
			tt_ExtCallFncs(0, "Hide");
		}
		tt_tShow.EndTimer();
		tt_tHide.EndTimer();
		tt_tDurt.EndTimer();
		tt_tFade.EndTimer();
		if(!tt_op && !tt_ie)
		{
			tt_tWaitMov.EndTimer();
			tt_bWait = false;
		}
		if(tt_aV[CLICKCLOSE] || tt_aV[CLICKSTICKY])
			tt_RemEvtFnc(document, "mouseup", tt_OnLClick);
		tt_ExtCallFncs(0, "Kill");
		// In case of a TagToTip tip, hide converted DOM node and
		// re-insert it into DOM
		if(tt_t2t && !tt_aV[COPYCONTENT])
			tt_UnEl2Tip();
		tt_iState = 0;
		tt_over = null;
		tt_ResetMainDiv();
		if(tt_aElt[tt_aElt.length - 1])
			tt_aElt[tt_aElt.length - 1].style.display = "none";
	}
}
function tt_GetElt(id)
{
	return(document.getElementById ? document.getElementById(id)
			: document.all ? document.all[id]
			: null);
}
function tt_GetDivW(el)
{
	return(el ? (el.offsetWidth || el.style.pixelWidth || 0) : 0);
}
function tt_GetDivH(el)
{
	return(el ? (el.offsetHeight || el.style.pixelHeight || 0) : 0);
}
function tt_GetScrollX()
{
	return(window.pageXOffset || (tt_db ? (tt_db.scrollLeft || 0) : 0));
}
function tt_GetScrollY()
{
	return(window.pageYOffset || (tt_db ? (tt_db.scrollTop || 0) : 0));
}
function tt_GetClientW()
{
	return tt_GetWndCliSiz("Width");
}
function tt_GetClientH()
{
	return tt_GetWndCliSiz("Height");
}
function tt_GetEvtX(e)
{
	return (e ? ((typeof(e.pageX) != tt_u) ? e.pageX : (e.clientX + tt_GetScrollX())) : 0);
}
function tt_GetEvtY(e)
{
	return (e ? ((typeof(e.pageY) != tt_u) ? e.pageY : (e.clientY + tt_GetScrollY())) : 0);
}
function tt_AddEvtFnc(el, sEvt, PFnc)
{
	if(el)
	{
		if(el.addEventListener)
			el.addEventListener(sEvt, PFnc, false);
		else
			el.attachEvent("on" + sEvt, PFnc);
	}
}
function tt_RemEvtFnc(el, sEvt, PFnc)
{
	if(el)
	{
		if(el.removeEventListener)
			el.removeEventListener(sEvt, PFnc, false);
		else
			el.detachEvent("on" + sEvt, PFnc);
	}
}
function tt_GetDad(el)
{
	return(el.parentNode || el.parentElement || el.offsetParent);
}
function tt_MovDomNode(el, dadFrom, dadTo)
{
	if(dadFrom)
		dadFrom.removeChild(el);
	if(dadTo)
		dadTo.appendChild(el);
}

//======================  PRIVATE  ===========================================//
var tt_aExt = new Array(),	// Array of extension objects

tt_db, tt_op, tt_ie, tt_ie56, tt_bBoxOld,	// Browser flags
tt_body,
tt_ovr_,				// HTML element the mouse is currently over
tt_flagOpa,				// Opacity support: 1=IE, 2=Khtml, 3=KHTML, 4=Moz, 5=W3C
tt_maxPosX, tt_maxPosY,
tt_iState = 0,			// Tooltip active |= 1, shown |= 2, move with mouse |= 4, exclusive |= 8
tt_opa,					// Currently applied opacity
tt_bJmpVert, tt_bJmpHorz,// Tip temporarily on other side of mouse
tt_elDeHref,			// The tag from which we've removed the href attribute
// Timer
tt_tShow = new Number(0), tt_tHide = new Number(0), tt_tDurt = new Number(0),
tt_tFade = new Number(0), tt_tWaitMov = new Number(0),
tt_bWait = false,
tt_u = "undefined";


function tt_Init()
{
	tt_MkCmdEnum();
	// Send old browsers instantly to hell
	if(!tt_Browser() || !tt_MkMainDiv())
		return;
	tt_IsW3cBox();
	tt_OpaSupport();
	tt_AddEvtFnc(document, "mousemove", tt_Move);
	// In Debug mode we search for TagToTip() calls in order to notify
	// the user if they've forgotten to set the TagsToTip config flag
	if(TagsToTip || tt_Debug)
		tt_SetOnloadFnc();
	// Ensure the tip be hidden when the page unloads
	tt_AddEvtFnc(window, "unload", tt_Hide);
}
// Creates command names by translating config variable names to upper case
function tt_MkCmdEnum()
{
	var n = 0;
	for(var i in config)
		eval("window." + i.toString().toUpperCase() + " = " + n++);
	tt_aV.length = n;
}
function tt_Browser()
{
	var n, nv, n6, w3c;

	n = navigator.userAgent.toLowerCase(),
	nv = navigator.appVersion;
	tt_op = (document.defaultView && typeof(eval("w" + "indow" + "." + "o" + "p" + "er" + "a")) != tt_u);
	tt_ie = n.indexOf("msie") != -1 && document.all && !tt_op;
	if(tt_ie)
	{
		var ieOld = (!document.compatMode || document.compatMode == "BackCompat");
		tt_db = !ieOld ? document.documentElement : (document.body || null);
		if(tt_db)
			tt_ie56 = parseFloat(nv.substring(nv.indexOf("MSIE") + 5)) >= 5.5
					&& typeof document.body.style.maxHeight == tt_u;
	}
	else
	{
		tt_db = document.documentElement || document.body ||
				(document.getElementsByTagName ? document.getElementsByTagName("body")[0]
				: null);
		if(!tt_op)
		{
			n6 = document.defaultView && typeof document.defaultView.getComputedStyle != tt_u;
			w3c = !n6 && document.getElementById;
		}
	}
	tt_body = (document.getElementsByTagName ? document.getElementsByTagName("body")[0]
				: (document.body || null));
	if(tt_ie || n6 || tt_op || w3c)
	{
		//if(tt_body && tt_db)
		//{
			if(document.attachEvent || document.addEventListener)
				return true;
		//}
		//else
		//	tt_Err("wz_tooltip.js must be included INSIDE the body section,"
		//			+ " immediately after the opening <body> tag.", false);
	}
	tt_db = null;
	return false;
}
function tt_MkMainDiv()
{
	// Create the tooltip DIV
	if(tt_body.insertAdjacentHTML)
		tt_body.insertAdjacentHTML("afterBegin", tt_MkMainDivHtm());
	else if(typeof tt_body.innerHTML != tt_u && document.createElement && tt_body.appendChild)
		tt_body.appendChild(tt_MkMainDivDom());
	if(window.tt_GetMainDivRefs /* FireFox Alzheimer */ && tt_GetMainDivRefs())
		return true;
	tt_db = null;
	return false;
}
function tt_MkMainDivHtm()
{
	return(
		'<div id="WzTtDiV"></div>' +
		(tt_ie56 ? ('<iframe id="WzTtIfRm" src="javascript:false" scrolling="no" frameborder="0" style="filter:Alpha(opacity=0);position:absolute;top:0px;left:0px;display:none;"></iframe>')
		: '')
	);
}
function tt_MkMainDivDom()
{
	var el = document.createElement("div");
	if(el)
		el.id = "WzTtDiV";
	return el;
}
function tt_GetMainDivRefs()
{
	tt_aElt[0] = tt_GetElt("WzTtDiV");
	if(tt_ie56 && tt_aElt[0])
	{
		tt_aElt[tt_aElt.length - 1] = tt_GetElt("WzTtIfRm");
		if(!tt_aElt[tt_aElt.length - 1])
			tt_aElt[0] = null;
	}
	if(tt_aElt[0])
	{
		var css = tt_aElt[0].style;

		css.visibility = "hidden";
		css.position = "absolute";
		css.overflow = "hidden";
		return true;
	}
	return false;
}
function tt_ResetMainDiv()
{
	tt_SetTipPos(0, 0);
	tt_aElt[0].innerHTML = "";
	tt_aElt[0].style.width = "0px";
	tt_h = 0;
}
function tt_IsW3cBox()
{
	var css = tt_aElt[0].style;

	css.padding = "10px";
	css.width = "40px";
	tt_bBoxOld = (tt_GetDivW(tt_aElt[0]) == 40);
	css.padding = "0px";
	tt_ResetMainDiv();
}
function tt_OpaSupport()
{
	var css = tt_body.style;

	tt_flagOpa = (typeof(css.KhtmlOpacity) != tt_u) ? 2
				: (typeof(css.KHTMLOpacity) != tt_u) ? 3
				: (typeof(css.MozOpacity) != tt_u) ? 4
				: (typeof(css.opacity) != tt_u) ? 5
				: (typeof(css.filter) != tt_u) ? 1
				: 0;
}
// Ported from http://dean.edwards.name/weblog/2006/06/again/
// (Dean Edwards et al.)
function tt_SetOnloadFnc()
{
	tt_AddEvtFnc(document, "DOMContentLoaded", tt_HideSrcTags);
	tt_AddEvtFnc(window, "load", tt_HideSrcTags);
	if(tt_body.attachEvent)
		tt_body.attachEvent("onreadystatechange",
			function() {
				if(tt_body.readyState == "complete")
					tt_HideSrcTags();
			} );
	if(/WebKit|KHTML/i.test(navigator.userAgent))
	{
		var t = setInterval(function() {
					if(/loaded|complete/.test(document.readyState))
					{
						clearInterval(t);
						tt_HideSrcTags();
					}
				}, 10);
	}
}
function tt_HideSrcTags()
{
	if(!window.tt_HideSrcTags || window.tt_HideSrcTags.done)
		return;
	window.tt_HideSrcTags.done = true;
	if(!tt_HideSrcTagsRecurs(tt_body))
		tt_Err("There are HTML elements to be converted to tooltips.\nIf you"
				+ " want these HTML elements to be automatically hidden, you"
				+ " must edit wz_tooltip.js, and set TagsToTip in the global"
				+ " tooltip configuration to true.", true);
}
function tt_HideSrcTagsRecurs(dad)
{
	var ovr, asT2t;
	// Walk the DOM tree for tags that have an onmouseover or onclick attribute
	// containing a TagToTip('...') call.
	// (.childNodes first since .children is bugous in Safari)
	var a = dad.childNodes || dad.children || null;

	for(var i = a ? a.length : 0; i;)
	{--i;
		if(!tt_HideSrcTagsRecurs(a[i]))
			return false;
		ovr = a[i].getAttribute ? (a[i].getAttribute("onmouseover") || a[i].getAttribute("onclick"))
				: (typeof a[i].onmouseover == "function") ? (a[i].onmouseover || a[i].onclick)
				: null;
		if(ovr)
		{
			asT2t = ovr.toString().match(/TagToTip\s*\(\s*'[^'.]+'\s*[\),]/);
			if(asT2t && asT2t.length)
			{
				if(!tt_HideSrcTag(asT2t[0]))
					return false;
			}
		}
	}
	return true;
}
function tt_HideSrcTag(sT2t)
{
	var id, el;

	// The ID passed to the found TagToTip() call identifies an HTML element
	// to be converted to a tooltip, so hide that element
	id = sT2t.replace(/.+'([^'.]+)'.+/, "$1");
	el = tt_GetElt(id);
	if(el)
	{
		if(tt_Debug && !TagsToTip)
			return false;
		else
			el.style.display = "none";
	}
	else
		tt_Err("Invalid ID\n'" + id + "'\npassed to TagToTip()."
				+ " There exists no HTML element with that ID.", true);
	return true;
}
function tt_Tip(arg, t2t)
{
	if(!tt_db || (tt_iState & 0x8))
		return;
	if(tt_iState)
		tt_Hide();
	if(!tt_Enabled)
		return;
	tt_t2t = t2t;
	if(!tt_ReadCmds(arg))
		return;
	tt_iState = 0x1 | 0x4;
	tt_AdaptConfig1();
	tt_MkTipContent(arg);
	tt_MkTipSubDivs();
	tt_FormatTip();
	tt_bJmpVert = false;
	tt_bJmpHorz = false;
	tt_maxPosX = tt_GetClientW() + tt_GetScrollX() - tt_w - 1;
	tt_maxPosY = tt_GetClientH() + tt_GetScrollY() - tt_h - 1;
	tt_AdaptConfig2();
	// Ensure the tip be shown and positioned before the first onmousemove
	tt_OverInit();
	tt_ShowInit();
	tt_Move();
}
function tt_ReadCmds(a)
{
	var i;

	// First load the global config values, to initialize also values
	// for which no command is passed
	i = 0;
	for(var j in config)
		tt_aV[i++] = config[j];
	// Then replace each cached config value for which a command is
	// passed (ensure the # of command args plus value args be even)
	if(a.length & 1)
	{
		for(i = a.length - 1; i > 0; i -= 2)
			tt_aV[a[i - 1]] = a[i];
		return true;
	}
	tt_Err("Incorrect call of Tip() or TagToTip().\n"
			+ "Each command must be followed by a value.", true);
	return false;
}
function tt_AdaptConfig1()
{
	tt_ExtCallFncs(0, "LoadConfig");
	// Inherit unspecified title formattings from body
	if(!tt_aV[TITLEBGCOLOR].length)
		tt_aV[TITLEBGCOLOR] = tt_aV[BORDERCOLOR];
	if(!tt_aV[TITLEFONTCOLOR].length)
		tt_aV[TITLEFONTCOLOR] = tt_aV[BGCOLOR];
	if(!tt_aV[TITLEFONTFACE].length)
		tt_aV[TITLEFONTFACE] = tt_aV[FONTFACE];
	if(!tt_aV[TITLEFONTSIZE].length)
		tt_aV[TITLEFONTSIZE] = tt_aV[FONTSIZE];
	if(tt_aV[CLOSEBTN])
	{
		// Use title colours for non-specified closebutton colours
		if(!tt_aV[CLOSEBTNCOLORS])
			tt_aV[CLOSEBTNCOLORS] = new Array("", "", "", "");
		for(var i = 4; i;)
		{--i;
			if(!tt_aV[CLOSEBTNCOLORS][i].length)
				tt_aV[CLOSEBTNCOLORS][i] = (i & 1) ? tt_aV[TITLEFONTCOLOR] : tt_aV[TITLEBGCOLOR];
		}
		// Enforce titlebar be shown
		if(!tt_aV[TITLE].length)
			tt_aV[TITLE] = " ";
	}
	// Circumvents broken display of images and fade-in flicker in Geckos < 1.8
	if(tt_aV[OPACITY] == 100 && typeof tt_aElt[0].style.MozOpacity != tt_u && !Array.every)
		tt_aV[OPACITY] = 99;
	// Smartly shorten the delay for fade-in tooltips
	if(tt_aV[FADEIN] && tt_flagOpa && tt_aV[DELAY] > 100)
		tt_aV[DELAY] = Math.max(tt_aV[DELAY] - tt_aV[FADEIN], 100);
}
function tt_AdaptConfig2()
{
	if(tt_aV[CENTERMOUSE])
	{
		tt_aV[OFFSETX] -= ((tt_w - (tt_aV[SHADOW] ? tt_aV[SHADOWWIDTH] : 0)) >> 1);
		tt_aV[JUMPHORZ] = false;
	}
}
// Expose content globally so extensions can modify it
function tt_MkTipContent(a)
{
	if(tt_t2t)
	{
		if(tt_aV[COPYCONTENT])
			tt_sContent = tt_t2t.innerHTML;
		else
			tt_sContent = "";
	}
	else
		tt_sContent = a[0];
	tt_ExtCallFncs(0, "CreateContentString");
}
function tt_MkTipSubDivs()
{
	var sCss = 'position:relative;margin:0px;padding:0px;border-width:0px;left:0px;top:0px;line-height:normal;width:auto;',
	sTbTrTd = ' cellspacing="0" cellpadding="0" border="0" style="' + sCss + '"><tbody style="' + sCss + '"><tr><td ';

	tt_aElt[0].style.width = tt_GetClientW() + "px";
	tt_aElt[0].innerHTML =
		(''
		+ (tt_aV[TITLE].length ?
			('<div id="WzTiTl" style="position:relative;z-index:1;">'
			+ '<table id="WzTiTlTb"' + sTbTrTd + 'id="WzTiTlI" style="' + sCss + '">'
			+ tt_aV[TITLE]
			+ '</td>'
			+ (tt_aV[CLOSEBTN] ?
				('<td align="right" style="' + sCss
				+ 'text-align:right;">'
				+ '<span id="WzClOsE" style="position:relative;left:2px;padding-left:2px;padding-right:2px;'
				+ 'cursor:' + (tt_ie ? 'hand' : 'pointer')
				+ ';" onmouseover="tt_OnCloseBtnOver(1)" onmouseout="tt_OnCloseBtnOver(0)" onclick="tt_HideInit()">'
				+ tt_aV[CLOSEBTNTEXT]
				+ '</span></td>')
				: '')
			+ '</tr></tbody></table></div>')
			: '')
		+ '<div id="WzBoDy" style="position:relative;z-index:0;">'
		+ '<table' + sTbTrTd + 'id="WzBoDyI" style="' + sCss + '">'
		+ tt_sContent
		+ '</td></tr></tbody></table></div>'
		+ (tt_aV[SHADOW]
			? ('<div id="WzTtShDwR" style="position:absolute;overflow:hidden;"></div>'
				+ '<div id="WzTtShDwB" style="position:relative;overflow:hidden;"></div>')
			: '')
		);
	tt_GetSubDivRefs();
	// Convert DOM node to tip
	if(tt_t2t && !tt_aV[COPYCONTENT])
		tt_El2Tip();
	tt_ExtCallFncs(0, "SubDivsCreated");
}
function tt_GetSubDivRefs()
{
	var aId = new Array("WzTiTl", "WzTiTlTb", "WzTiTlI", "WzClOsE", "WzBoDy", "WzBoDyI", "WzTtShDwB", "WzTtShDwR");

	for(var i = aId.length; i; --i)
		tt_aElt[i] = tt_GetElt(aId[i - 1]);
}
function tt_FormatTip()
{
	var css, w, h, pad = tt_aV[PADDING], padT, wBrd = tt_aV[BORDERWIDTH],
	iOffY, iOffSh, iAdd = (pad + wBrd) << 1;

	//--------- Title DIV ----------
	if(tt_aV[TITLE].length)
	{
		padT = tt_aV[TITLEPADDING];
		css = tt_aElt[1].style;
		css.background = tt_aV[TITLEBGCOLOR];
		css.paddingTop = css.paddingBottom = padT + "px";
		css.paddingLeft = css.paddingRight = (padT + 2) + "px";
		css = tt_aElt[3].style;
		css.color = tt_aV[TITLEFONTCOLOR];
		if(tt_aV[WIDTH] == -1)
			css.whiteSpace = "nowrap";
		css.fontFamily = tt_aV[TITLEFONTFACE];
		css.fontSize = tt_aV[TITLEFONTSIZE];
		css.fontWeight = "bold";
		css.textAlign = tt_aV[TITLEALIGN];
		// Close button DIV
		if(tt_aElt[4])
		{
			css = tt_aElt[4].style;
			css.background = tt_aV[CLOSEBTNCOLORS][0];
			css.color = tt_aV[CLOSEBTNCOLORS][1];
			css.fontFamily = tt_aV[TITLEFONTFACE];
			css.fontSize = tt_aV[TITLEFONTSIZE];
			css.fontWeight = "bold";
		}
		if(tt_aV[WIDTH] > 0)
			tt_w = tt_aV[WIDTH];
		else
		{
			tt_w = tt_GetDivW(tt_aElt[3]) + tt_GetDivW(tt_aElt[4]);
			// Some spacing between title DIV and closebutton
			if(tt_aElt[4])
				tt_w += pad;
			// Restrict auto width to max width
			if(tt_aV[WIDTH] < -1 && tt_w > -tt_aV[WIDTH])
				tt_w = -tt_aV[WIDTH];
		}
		// Ensure the top border of the body DIV be covered by the title DIV
		iOffY = -wBrd;
	}
	else
	{
		tt_w = 0;
		iOffY = 0;
	}

	//-------- Body DIV ------------
	css = tt_aElt[5].style;
	css.top = iOffY + "px";
	if(wBrd)
	{
		css.borderColor = tt_aV[BORDERCOLOR];
		css.borderStyle = tt_aV[BORDERSTYLE];
		css.borderWidth = wBrd + "px";
	}
	if(tt_aV[BGCOLOR].length)
		css.background = tt_aV[BGCOLOR];
	if(tt_aV[BGIMG].length)
		css.backgroundImage = "url(" + tt_aV[BGIMG] + ")";
	css.padding = pad + "px";
	css.textAlign = tt_aV[TEXTALIGN];
	if(tt_aV[HEIGHT])
	{
		css.overflow = "auto";
		if(tt_aV[HEIGHT] > 0)
			css.height = (tt_aV[HEIGHT] + iAdd) + "px";
		else
			tt_h = iAdd - tt_aV[HEIGHT];
	}
	// TD inside body DIV
	css = tt_aElt[6].style;
	css.color = tt_aV[FONTCOLOR];
	css.fontFamily = tt_aV[FONTFACE];
	css.fontSize = tt_aV[FONTSIZE];
	css.fontWeight = tt_aV[FONTWEIGHT];
	css.textAlign = tt_aV[TEXTALIGN];
	if(tt_aV[WIDTH] > 0)
		w = tt_aV[WIDTH];
	// Width like title (if existent)
	else if(tt_aV[WIDTH] == -1 && tt_w)
		w = tt_w;
	else
	{
		// Measure width of the body's inner TD, as some browsers would expand
		// the container and outer body DIV to 100%
		w = tt_GetDivW(tt_aElt[6]);
		// Restrict auto width to max width
		if(tt_aV[WIDTH] < -1 && w > -tt_aV[WIDTH])
			w = -tt_aV[WIDTH];
	}
	if(w > tt_w)
		tt_w = w;
	tt_w += iAdd;

	//--------- Shadow DIVs ------------
	if(tt_aV[SHADOW])
	{
		tt_w += tt_aV[SHADOWWIDTH];
		iOffSh = Math.floor((tt_aV[SHADOWWIDTH] * 4) / 3);
		// Bottom shadow
		css = tt_aElt[7].style;
		css.top = iOffY + "px";
		css.left = iOffSh + "px";
		css.width = (tt_w - iOffSh - tt_aV[SHADOWWIDTH]) + "px";
		css.height = tt_aV[SHADOWWIDTH] + "px";
		css.background = tt_aV[SHADOWCOLOR];
		// Right shadow
		css = tt_aElt[8].style;
		css.top = iOffSh + "px";
		css.left = (tt_w - tt_aV[SHADOWWIDTH]) + "px";
		css.width = tt_aV[SHADOWWIDTH] + "px";
		css.background = tt_aV[SHADOWCOLOR];
	}
	else
		iOffSh = 0;

	//-------- Container DIV -------
	tt_SetTipOpa(tt_aV[FADEIN] ? 0 : tt_aV[OPACITY]);
	tt_FixSize(iOffY, iOffSh);
}
// Fixate the size so it can't dynamically change while the tooltip is moving.
function tt_FixSize(iOffY, iOffSh)
{
	var wIn, wOut, h, add, pad = tt_aV[PADDING], wBrd = tt_aV[BORDERWIDTH], i;

	tt_aElt[0].style.width = tt_w + "px";
	tt_aElt[0].style.pixelWidth = tt_w;
	wOut = tt_w - ((tt_aV[SHADOW]) ? tt_aV[SHADOWWIDTH] : 0);
	// Body
	wIn = wOut;
	if(!tt_bBoxOld)
		wIn -= (pad + wBrd) << 1;
	tt_aElt[5].style.width = wIn + "px";
	// Title
	if(tt_aElt[1])
	{
		wIn = wOut - ((tt_aV[TITLEPADDING] + 2) << 1);
		if(!tt_bBoxOld)
			wOut = wIn;
		tt_aElt[1].style.width = wOut + "px";
		tt_aElt[2].style.width = wIn + "px";
	}
	// Max height specified
	if(tt_h)
	{
		h = tt_GetDivH(tt_aElt[5]);
		if(h > tt_h)
		{
			if(!tt_bBoxOld)
				tt_h -= (pad + wBrd) << 1;
			tt_aElt[5].style.height = tt_h + "px";
		}
	}
	tt_h = tt_GetDivH(tt_aElt[0]) + iOffY;
	// Right shadow
	if(tt_aElt[8])
		tt_aElt[8].style.height = (tt_h - iOffSh) + "px";
	i = tt_aElt.length - 1;
	if(tt_aElt[i])
	{
		tt_aElt[i].style.width = tt_w + "px";
		tt_aElt[i].style.height = tt_h + "px";
	}
}
function tt_DeAlt(el)
{
	var aKid;

	if(el)
	{
		if(el.alt)
			el.alt = "";
		if(el.title)
			el.title = "";
		aKid = el.childNodes || el.children || null;
		if(aKid)
		{
			for(var i = aKid.length; i;)
				tt_DeAlt(aKid[--i]);
		}
	}
}
// This hack removes the native tooltips over links in Opera
function tt_OpDeHref(el)
{
	if(!tt_op)
		return;
	if(tt_elDeHref)
		tt_OpReHref();
	while(el)
	{
		if(el.hasAttribute && el.hasAttribute("href"))
		{
			el.t_href = el.getAttribute("href");
			el.t_stats = window.status;
			el.removeAttribute("href");
			el.style.cursor = "hand";
			tt_AddEvtFnc(el, "mousedown", tt_OpReHref);
			window.status = el.t_href;
			tt_elDeHref = el;
			break;
		}
		el = tt_GetDad(el);
	}
}
function tt_OpReHref()
{
	if(tt_elDeHref)
	{
		tt_elDeHref.setAttribute("href", tt_elDeHref.t_href);
		tt_RemEvtFnc(tt_elDeHref, "mousedown", tt_OpReHref);
		window.status = tt_elDeHref.t_stats;
		tt_elDeHref = null;
	}
}
function tt_El2Tip()
{
	var css = tt_t2t.style;

	// Store previous positioning
	tt_t2t.t_cp = css.position;
	tt_t2t.t_cl = css.left;
	tt_t2t.t_ct = css.top;
	tt_t2t.t_cd = css.display;
	// Store the tag's parent element so we can restore that DOM branch
	// when the tooltip is being hidden
	tt_t2tDad = tt_GetDad(tt_t2t);
	tt_MovDomNode(tt_t2t, tt_t2tDad, tt_aElt[6]);
	css.display = "block";
	css.position = "static";
	css.left = css.top = css.marginLeft = css.marginTop = "0px";
}
function tt_UnEl2Tip()
{
	// Restore positioning and display
	var css = tt_t2t.style;

	css.display = tt_t2t.t_cd;
	tt_MovDomNode(tt_t2t, tt_GetDad(tt_t2t), tt_t2tDad);
	css.position = tt_t2t.t_cp;
	css.left = tt_t2t.t_cl;
	css.top = tt_t2t.t_ct;
	tt_t2tDad = null;
}
function tt_OverInit()
{
	if(window.event)
		tt_over = window.event.target || window.event.srcElement;
	else
		tt_over = tt_ovr_;
	tt_DeAlt(tt_over);
	tt_OpDeHref(tt_over);
}
function tt_ShowInit()
{
	tt_tShow.Timer("tt_Show()", tt_aV[DELAY], true);
	if(tt_aV[CLICKCLOSE] || tt_aV[CLICKSTICKY])
		tt_AddEvtFnc(document, "mouseup", tt_OnLClick);
}
function tt_Show()
{
	var css = tt_aElt[0].style;

	// Override the z-index of the topmost wz_dragdrop.js D&D item
	css.zIndex = Math.max((window.dd && dd.z) ? (dd.z + 2) : 0, 1010);
	if(tt_aV[STICKY] || !tt_aV[FOLLOWMOUSE])
		tt_iState &= ~0x4;
	if(tt_aV[EXCLUSIVE])
		tt_iState |= 0x8;
	if(tt_aV[DURATION] > 0)
		tt_tDurt.Timer("tt_HideInit()", tt_aV[DURATION], true);
	tt_ExtCallFncs(0, "Show")
	css.visibility = "visible";
	tt_iState |= 0x2;
	if(tt_aV[FADEIN])
		tt_Fade(0, 0, tt_aV[OPACITY], Math.round(tt_aV[FADEIN] / tt_aV[FADEINTERVAL]));
	tt_ShowIfrm();
}
function tt_ShowIfrm()
{
	if(tt_ie56)
	{
		var ifrm = tt_aElt[tt_aElt.length - 1];
		if(ifrm)
		{
			var css = ifrm.style;
			css.zIndex = tt_aElt[0].style.zIndex - 1;
			css.display = "block";
		}
	}
}
function tt_Move(e)
{
	if(e)
		tt_ovr_ = e.target || e.srcElement;
	e = e || window.event;
	if(e)
	{
		tt_musX = tt_GetEvtX(e);
		tt_musY = tt_GetEvtY(e);
	}
	if(tt_iState & 0x4)
	{
		// Prevent jam of mousemove events
		if(!tt_op && !tt_ie)
		{
			if(tt_bWait)
				return;
			tt_bWait = true;
			tt_tWaitMov.Timer("tt_bWait = false;", 1, true);
		}
		if(tt_aV[FIX])
		{
			tt_iState &= ~0x4;
			tt_PosFix();
		}
		else if(!tt_ExtCallFncs(e, "MoveBefore"))
			tt_SetTipPos(tt_Pos(0), tt_Pos(1));
		tt_ExtCallFncs([tt_musX, tt_musY], "MoveAfter")
	}
}
function tt_Pos(iDim)
{
	var iX, bJmpMod, cmdAlt, cmdOff, cx, iMax, iScrl, iMus, bJmp;

	// Map values according to dimension to calculate
	if(iDim)
	{
		bJmpMod = tt_aV[JUMPVERT];
		cmdAlt = ABOVE;
		cmdOff = OFFSETY;
		cx = tt_h;
		iMax = tt_maxPosY;
		iScrl = tt_GetScrollY();
		iMus = tt_musY;
		bJmp = tt_bJmpVert;
	}
	else
	{
		bJmpMod = tt_aV[JUMPHORZ];
		cmdAlt = LEFT;
		cmdOff = OFFSETX;
		cx = tt_w;
		iMax = tt_maxPosX;
		iScrl = tt_GetScrollX();
		iMus = tt_musX;
		bJmp = tt_bJmpHorz;
	}
	if(bJmpMod)
	{
		if(tt_aV[cmdAlt] && (!bJmp || tt_CalcPosAlt(iDim) >= iScrl + 16))
			iX = tt_PosAlt(iDim);
		else if(!tt_aV[cmdAlt] && bJmp && tt_CalcPosDef(iDim) > iMax - 16)
			iX = tt_PosAlt(iDim);
		else
			iX = tt_PosDef(iDim);
	}
	else
	{
		iX = iMus;
		if(tt_aV[cmdAlt])
			iX -= cx + tt_aV[cmdOff] - (tt_aV[SHADOW] ? tt_aV[SHADOWWIDTH] : 0);
		else
			iX += tt_aV[cmdOff];
	}
	// Prevent tip from extending past clientarea boundary
	if(iX > iMax)
		iX = bJmpMod ? tt_PosAlt(iDim) : iMax;
	// In case of insufficient space on both sides, ensure the left/upper part
	// of the tip be visible
	if(iX < iScrl)
		iX = bJmpMod ? tt_PosDef(iDim) : iScrl;
	return iX;
}
function tt_PosDef(iDim)
{
	if(iDim)
		tt_bJmpVert = tt_aV[ABOVE];
	else
		tt_bJmpHorz = tt_aV[LEFT];
	return tt_CalcPosDef(iDim);
}
function tt_PosAlt(iDim)
{
	if(iDim)
		tt_bJmpVert = !tt_aV[ABOVE];
	else
		tt_bJmpHorz = !tt_aV[LEFT];
	return tt_CalcPosAlt(iDim);
}
function tt_CalcPosDef(iDim)
{
	return iDim ? (tt_musY + tt_aV[OFFSETY]) : (tt_musX + tt_aV[OFFSETX]);
}
function tt_CalcPosAlt(iDim)
{
	var cmdOff = iDim ? OFFSETY : OFFSETX;
	var dx = tt_aV[cmdOff] - (tt_aV[SHADOW] ? tt_aV[SHADOWWIDTH] : 0);
	if(tt_aV[cmdOff] > 0 && dx <= 0)
		dx = 1;
	return((iDim ? (tt_musY - tt_h) : (tt_musX - tt_w)) - dx);
}
function tt_PosFix()
{
	var iX, iY;

	if(typeof(tt_aV[FIX][0]) == "number")
	{
		iX = tt_aV[FIX][0];
		iY = tt_aV[FIX][1];
	}
	else
	{
		if(typeof(tt_aV[FIX][0]) == "string")
			el = tt_GetElt(tt_aV[FIX][0]);
		// First slot in array is direct reference to HTML element
		else
			el = tt_aV[FIX][0];
		iX = tt_aV[FIX][1];
		iY = tt_aV[FIX][2];
		// By default, vert pos is related to bottom edge of HTML element
		if(!tt_aV[ABOVE] && el)
			iY += tt_GetDivH(el);
		for(; el; el = el.offsetParent)
		{
			iX += el.offsetLeft || 0;
			iY += el.offsetTop || 0;
		}
	}
	// For a fixed tip positioned above the mouse, use the bottom edge as anchor
	// (recommended by Christophe Rebeschini, 31.1.2008)
	if(tt_aV[ABOVE])
		iY -= tt_h;
	tt_SetTipPos(iX, iY);
}
function tt_Fade(a, now, z, n)
{
	if(n)
	{
		now += Math.round((z - now) / n);
		if((z > a) ? (now >= z) : (now <= z))
			now = z;
		else
			tt_tFade.Timer(
				"tt_Fade("
				+ a + "," + now + "," + z + "," + (n - 1)
				+ ")",
				tt_aV[FADEINTERVAL],
				true
			);
	}
	now ? tt_SetTipOpa(now) : tt_Hide();
}
function tt_SetTipOpa(opa)
{
	// To circumvent the opacity nesting flaws of IE, we set the opacity
	// for each sub-DIV separately, rather than for the container DIV.
	tt_SetOpa(tt_aElt[5], opa);
	if(tt_aElt[1])
		tt_SetOpa(tt_aElt[1], opa);
	if(tt_aV[SHADOW])
	{
		opa = Math.round(opa * 0.8);
		tt_SetOpa(tt_aElt[7], opa);
		tt_SetOpa(tt_aElt[8], opa);
	}
}
function tt_OnCloseBtnOver(iOver)
{
	var css = tt_aElt[4].style;

	iOver <<= 1;
	css.background = tt_aV[CLOSEBTNCOLORS][iOver];
	css.color = tt_aV[CLOSEBTNCOLORS][iOver + 1];
}
function tt_OnLClick(e)
{
	//  Ignore right-clicks
	e = e || window.event;
	if(!((e.button && e.button & 2) || (e.which && e.which == 3)))
	{
		if(tt_aV[CLICKSTICKY] && (tt_iState & 0x4))
		{
			tt_aV[STICKY] = true;
			tt_iState &= ~0x4;
		}
		else if(tt_aV[CLICKCLOSE])
			tt_HideInit();
	}
}
function tt_Int(x)
{
	var y;

	return(isNaN(y = parseInt(x)) ? 0 : y);
}
Number.prototype.Timer = function(s, iT, bUrge)
{
	if(!this.value || bUrge)
		this.value = window.setTimeout(s, iT);
}
Number.prototype.EndTimer = function()
{
	if(this.value)
	{
		window.clearTimeout(this.value);
		this.value = 0;
	}
}
function tt_GetWndCliSiz(s)
{
	var db, y = window["inner" + s], sC = "client" + s, sN = "number";
	if(typeof y == sN)
	{
		var y2;
		return(
			// Gecko or Opera with scrollbar
			// ... quirks mode
			((db = document.body) && typeof(y2 = db[sC]) == sN && y2 &&  y2 <= y) ? y2 
			// ... strict mode
			: ((db = document.documentElement) && typeof(y2 = db[sC]) == sN && y2 && y2 <= y) ? y2
			// No scrollbar, or clientarea size == 0, or other browser (KHTML etc.)
			: y
		);
	}
	// IE
	return(
		// document.documentElement.client+s functional, returns > 0
		((db = document.documentElement) && (y = db[sC])) ? y
		// ... not functional, in which case document.body.client+s 
		// is the clientarea size, fortunately
		: document.body[sC]
	);
}
function tt_SetOpa(el, opa)
{
	var css = el.style;

	tt_opa = opa;
	if(tt_flagOpa == 1)
	{
		if(opa < 100)
		{
			// Hacks for bugs of IE:
			// 1.) Once a CSS filter has been applied, fonts are no longer
			// anti-aliased, so we store the previous 'non-filter' to be
			// able to restore it
			if(typeof(el.filtNo) == tt_u)
				el.filtNo = css.filter;
			// 2.) A DIV cannot be made visible in a single step if an
			// opacity < 100 has been applied while the DIV was hidden
			var bVis = css.visibility != "hidden";
			// 3.) In IE6, applying an opacity < 100 has no effect if the
			//	   element has no layout (position, size, zoom, ...)
			css.zoom = "100%";
			if(!bVis)
				css.visibility = "visible";
			css.filter = "alpha(opacity=" + opa + ")";
			if(!bVis)
				css.visibility = "hidden";
		}
		else if(typeof(el.filtNo) != tt_u)
			// Restore 'non-filter'
			css.filter = el.filtNo;
	}
	else
	{
		opa /= 100.0;
		switch(tt_flagOpa)
		{
		case 2:
			css.KhtmlOpacity = opa; break;
		case 3:
			css.KHTMLOpacity = opa; break;
		case 4:
			css.MozOpacity = opa; break;
		case 5:
			css.opacity = opa; break;
		}
	}
}
function tt_Err(sErr, bIfDebug)
{
	if(tt_Debug || !bIfDebug)
		alert("Tooltip Script Error Message:\n\n" + sErr);
}

//============  EXTENSION (PLUGIN) MANAGER  ===============//
function tt_ExtCmdEnum()
{
	var s;

	// Add new command(s) to the commands enum
	for(var i in config)
	{
		s = "window." + i.toString().toUpperCase();
		if(eval("typeof(" + s + ") == tt_u"))
		{
			eval(s + " = " + tt_aV.length);
			tt_aV[tt_aV.length] = null;
		}
	}
}
function tt_ExtCallFncs(arg, sFnc)
{
	var b = false;
	for(var i = tt_aExt.length; i;)
	{--i;
		var fnc = tt_aExt[i]["On" + sFnc];
		// Call the method the extension has defined for this event
		if(fnc && fnc(arg))
			b = true;
	}
	return b;
}

tt_Init();





function phpnotes_services_history_get(dto,id,property,alturl)
{		
	
	document.body.style.cursor = 'wait';
	
	var baseurl = "/system/historical/history";
	
	if (alturl!='') baseurl = alturl;
	
	var url = baseurl+"?dto=" + dto+"&id="+id+"&property="+property;	
	
	var req;	
	
	
	// branch for native XMLHttpRequest object
	if (window.XMLHttpRequest) {
	    req = new XMLHttpRequest();	        
	    req.open("GET", url, false);
	    req.send(null);
	 	        
	 // branch for IE/Windows ActiveX version
	 } else if (window.ActiveXObject) {
	    isIE = true;
	    req = new ActiveXObject("Microsoft.XMLHTTP");
	    
	    if (req) {	            
	        req.open("GET", url, false);
	        req.send();
        }
    }
	document.body.style.cursor = 'default';    
    return req.responseText;
	    
    
}
