/*
 * RegExp pattern used for the jspf personalization pages
 */
function personalized_regexp_patt(){
	var patt=new RegExp("^[A-Z0-9&,.' ]*$");
	return patt;
}

function toupper_logbooks(name) {
	var stringit=new Array(
		'#'+name+'_P1_Motor_Carrier', 
		'#'+name+'_P1_Key_Number',
		'#'+name+'_P1_Terminal_Name',
		'#'+name+'_P2_Main_Address',
		'#'+name+'_P2_Terminal_Address',
		'#'+name+'_P3_Main_City',
		'#'+name+'_P3_Key_Number',
		'#'+name+'_P3_Terminal_City',
		'#'+name+'_P6_Main_Name',
		'#'+name+'_P6_Terminal_Address',
		'#'+name+'_P7_Terminal_City',
		'#'+name+'_P7_Main_Address',
		'#'+name+'_P8_Main_City',
		'#'+name+'_P10_DVIR_Company_Name', 
		'#'+name+'_P11_DVIR_Address',
		'#'+name+'_P11_DVIR_Company_Name',
		'#'+name+'_P12_DVIR_Address',
		'#'+name+'_P12_DVIR_City',
		'#'+name+'_P13_DVIR_City'
	);
	for(var i = 0; i < stringit.length; i++) {
	
		try
		{
      		$(stringit[i]).val($(stringit[i]).val().toUpperCase());
		}catch(e){}
	}
}

/*
 * Prepares an element for use as a select.  The following structure is assumed:
 * <div class="select" name="(select form element name)" [value="(default value)"] >
 * 	<div class="options-list">
 * 	 <ul class="options">
 *    <li class="option" v="(option value)">(display text)</li>
 *    [...]
 *   </ul>
 * 	</div>
 * </div>
 */
function prepareSelect(element) {
	
	// confirm this hasn't already been prepared
	if($(element).children('input[type=hidden]').size() > 0) {
		return;
	}
	
	var seValue = $(element).attr('value');
	if(seValue != undefined) {
		$(element).find('li.option').each(function (index, li) {
			var v = $(li).attr('v');
			if(v == seValue) {
				$(li).addClass('selected');
			} else {
				$(li).removeClass('selected');
			}		
		});
	}
	var se = $(element).find('li.selected');
	if(se.length == 0) {
		se = $(element).find('li.option:first-child');
		$(se).addClass('selected');
	}
	var name = $(element).attr('name');
	var val = ($(se).attr('v')==undefined?"":$(se).attr('v'));
	var ht = $(se).html();
	$(element).prepend('<input type="hidden" name="'+name+'" value="'+val+'" />');
	$(element).prepend('<div class="selected"><div class="clip">'+ht+'</div></div>');

	$(element).find('li.option').each(function(index, li) {
		$(li).html('<div class="clip">' + $(li).html() + '</div>');
	});
	
	$(element).find('div.selected').click(function (event) {
		if(_isOpen(this)) {
			_closeSelect(this);
		} else {
			_openSelect(this);
			$(element).focus();
		}
		event.stopPropagation();
	});

	$(element).find('li.option').click(function(event) {
		$(element).children('input').val($(this).attr('v'));
		$(this).parent().children().removeClass('selected');
		$(this).addClass('selected');
		$(element).find('div.selected div.clip').html($(this).html());
		_closeSelect(element);
		event.stopPropagation();
	});

	var tabindex = $(element).attr("tabindex");
	if(undefined == tabindex) {
		$(element).attr('tabindex', '0');
	}
	
	// used in the event the value changes.
    if(undefined == $(element).data('_changeHandlers')) {
        $(element).data('_changeHandlers', new Array());
    }
    
	var keypressHandler = function(event) {
		if(_isOpen(element)) {
			//
			// The menu is open - use these cases to process the keys
			//
			
			switch(event.keyCode*1000 + event.which) {
			default: 
				//search for an li starts with that letter

				// build an array that starts with the elements after the current hover, then followed by the 
				// elements before it
				var hoverClass = $(_findHover(element)).hasClass('hover') ? 'hover' : 'selected';
				var _beforeSelected = new Array();
				var _afterSelected = new Array();
				var isBefore = true;
				$(this).find('li.option').each(function(index, element) {
					if($(element).hasClass(hoverClass)) {
						isBefore = false;
					} else {
						if(isBefore) {
							_beforeSelected.push(element);
						} else {
							_afterSelected.push(element);
						}
					}
				});
				var _items = _afterSelected.concat(_beforeSelected);
				// search this array for something that starts with the character of the key pressed.
				for(var i = 0; i < _items.length; i++) {
					var keychar = String.fromCharCode(event.which);
					if($(_items[i]).text().toLowerCase().indexOf(keychar.toLowerCase())==0) {
						// hover that item
						$(element).find('li.option').removeClass('hover');
						$(_items[i]).addClass('hover');
						_revealHover(element);					
						break;
					}
				}
			
				event.stopPropagation();
				break;
			}
			
		} else {

			// 
			// The menu is not open - process the keys like this
			//
			
			switch(event.keyCode*1000 + event.which) {
			default: // search for an li that starts with that letter
				// build an array that starts with the elements after the selected, then followed by the 
				// elements before it
				var _beforeSelected = new Array();
				var _afterSelected = new Array();
				var isBefore = true;
				$(this).find('li.option').each(function(index, element) {
					if($(element).hasClass('selected')) {
						isBefore = false;
					} else {
						if(isBefore) {
							_beforeSelected.push(element);
						} else {
							_afterSelected.push(element);
						}
					}
				});
				var _items = _afterSelected.concat(_beforeSelected);
				// search this array for something that starts with the character of the key pressed.
				for(var i = 0; i < _items.length; i++) {
					var keychar = String.fromCharCode(event.which);
					if($(_items[i]).text().toLowerCase().indexOf(keychar.toLowerCase())==0) {
						// select that item
						setSelectValue(this, $(_items[i]).attr('v'));
						break;
					}
				}
			}
		}
	};
	
	var keydownHandler = function(event) {
		
		if(_isOpen(element)) {
			//
			// The menu is open - use these cases to process the keys
			//
			
			switch(event.keyCode) {
			case 27: //escape
			case 9:  // tab
			case 37: // left arrow 
				// close without selecting a value
				_closeSelect(element);
				event.preventDefault();
				event.stopPropagation();
				break;
			case 13: // select the value
			case 32: 	// space
			case 39:  // right arrow
				// select the highlighted value
				var hover = _findHover(element);
				_closeSelect(element);
				if(null != hover) {
					setSelectValue(element, $(hover).attr('v'));
				}
				// don't bubble anything except the enter key
				if(13 != event.keyCode) {
					event.preventDefault();
					event.stopPropagation();
				}
			case 38: // up arrow
				// highlight the previous value
				var hover = _findHover(element);
				if(null != hover) {
					var p = $(hover).prev();
					if(null != p) {
						$(element).find('li.option').removeClass('hover');
						$(p).addClass('hover');
					}
					_revealHover(element);					
				}
				event.preventDefault();
				event.stopPropagation();
				return false;
				break;
			case 40: // down arrow
				// highlight the previous value
				var hover = _findHover(element);
				if(null != hover) {
					var n = $(hover).next();
					if(null != n) {
						$(element).find('li.option').removeClass('hover');
						$(n).addClass('hover');
					}
					_revealHover(element);					
				}
				event.preventDefault();
				event.stopPropagation();
				break;		
			}
				
		} else {

			// 
			// The menu is not open - process the keys like this
			//
			
			switch(event.keyCode) {
			case 32: // space
			case 38: // up arrow
			case 40: // down arrow
				_openSelect(this);
				$(element).focus();
				_revealHover(element);					
				event.preventDefault();
				event.stopPropagation();
				break;
			}
		}
	};
	$(element).bind("keypress", keypressHandler);
	$(element).bind("keydown", keydownHandler);
	$(element).find('li.option').click(function() {
		_fireChangeHandlers(this);
	});

	$(element).find('li.option').bind("mouseenter", function() {
		$(element).find('li.option').removeClass('hover');
		$(this).addClass('hover');
	});
}

function _fireChangeHandlers(element) {
	var p = $(element).parent();
	while(true) {
		if(null == p) {
			return;
		}
		if($(p).is('div.select')) {
			break;
		}
		p = $(p).parent();
	}
	
	var handlers = $(p).data('_changeHandlers');
	for(var i = 0; i < handlers.length; i++) {
		handlers[i](p);
	}
}

/**
 * Determine if a select is open
 */
function _isOpen(element) {
	if($(element).hasClass('selected')) {
		element = $(element).parent();
	}
	var ul = $(element).find('ul.options');
	var disp = $(ul).css('display');
	return (disp != 'none');
}

/**
 * Locate the item that has the hover class set.  If there is none, it'll locate the selected one.
 */
function _findHover(element) {
	var hover = null;
	var selected = null;
	var options = $(element).find('li.option');
	for(var i = 0; i < options.length; i++) {
		var option = new Array();
		option.push(options[i]);
		if($(option).hasClass('selected')) {
			selected = option;
		}
		if($(option).hasClass('hover')) {
			hover = option;
			break;
		}
	}
	return (null != hover) ? hover : selected;
}

function _revealHover(element) {
	
	var hover = _findHover(element);
	if(null == hover) {
		return;
	}
	
	var ul = $(hover).parent();
	var ulHeight = $(ul).height();
	var liOffset =  $(hover).position().top + $(ul).scrollTop();
	var liHeight = $(hover).outerHeight();
	var middle = liHeight/2 + liOffset;

	var scrollPos = middle - ulHeight/2;
	
	$(ul).scrollTop(middle - ulHeight/2);
	scrollIfNeeded(hover);
}

function scrollIfNeeded(hover){
    var ul = $(hover).parent();
    var pos = ul.offset();
    
    var ulHeight = $(ul).outerHeight();
    var ulTop = pos.top;
    var wHeight = $(window).height();
    var wScrollTop = $(window).scrollTop();
    var ulRelPos = ulTop-wScrollTop;

    var diff = (ulRelPos + ulHeight) -wHeight;
    if(diff > 0)
    {
        $('html,body').animate({scrollTop: '+=' + (diff+10)}, 500);
    }

}
 
function _closeSelect(element) {
	if($(element).hasClass('selected')) {
		element = $(element).parent();
	}
	$(element).find('ul.options').slideUp('fast');
}
/*element = <div class="selected">*/
function _openSelect(element) {
	$('ul.options').not(element).slideUp('fast');
	$(element).find('li.option').removeClass('hover');
	var readOnly = ($(element).parent().hasClass('read-only')) || ($(element).parent().attr("readonly")== "true");
	if(false == readOnly) {
		$(element).parent().find('ul.options').slideToggle('fast', function() {
			var maxWidth = 0;
			var totalHeight = 0;
			var liods = $(element).parent().find('li.option div');
			$(liods).each(function(index, liod) {
				maxWidth = Math.max($(liod).outerWidth(), maxWidth);
				totalHeight += $(liod).parent().outerHeight();
			});

			// determines if we need to leave enough room for the scroll bar
			var ulPadding = 7;
			if(totalHeight > $(element).parent().find('ul').height()) {
				ulPadding += getScrollerWidth();                                // if there will be a scroll bar, give some space
			}
			
			var selElWidth = $(element).width();
			if(maxWidth + ulPadding > selElWidth){
    			$(liods).parent().width(maxWidth);
    			$(element).parent().find('ul.options').width(maxWidth + ulPadding);
			}else{
			    $(liods).parent().width(selElWidth - ulPadding);
			    $(element).parent().find('ul.options').width(selElWidth);
			}
			_setOptionWidths($(element).parent());
			_revealHover($(element).parent());
			
		});
		var dol = $(element).parent().find('div.options-list');
		$(dol).width($(dol).children('ul').width());
	}
}

/*
 * determine the maximum width of an option in the select
 */
 function _setOptionWidths(select) {
	var opts = $(select).find('li.option');
	$(opts).css('white-space', 'nowrap');
    $(opts).css('padding-right', '25px');
	$(select).find('ul.options').css('padding-right', '25px');
}


/*
 * Actions that need to be executed after the selects are prepared
 */
var _readyQueue = new Array(); 

/*
 * Prepares selects of the form described in the above function at the time the page loads.
 */
$(document).ready(function () {
	$('div.select').each(function(index, element) {
		prepareSelect($(element));
	});
	while(_readyQueue.length > 0) {
		var f = _readyQueue.shift();
		f();
	}
	//close all when clicked outside
	$('body').click(function() {
		$('ul.options').slideUp('fast');
	});
});

 /*
  * Enqueues an action so that it is run when the document is ready, but after the selects have been built 
  * out.  This is necessary for click() events on the dropdown that depend on knowing what the value the user
  * has selected.
  */
function enqueueReadyAction(f) {
	_readyQueue.push(f);
}
 
 
/*
 * Change the value of a select.
 * element is the hidden form element in the div.select
 */
function setSelectValue(element, newValue) {
	var seFound = null;
	$(element).parent().find('li.option').each(function (index, li) {
		var v = $(li).attr('v');
		if(v == newValue) {
			seFound = li;
			$(li).addClass('selected');
			$(element).children('input').val($(li).attr('v'));
		} else {
			$(li).removeClass('selected');
		}		
	});
	if(seFound != undefined) {
		$(element).val($(seFound).attr('v'));
		$(element).parent().find('div.selected').html('<div class="clip">'+$(seFound).html()+'</div>');
		_fireChangeHandlers(seFound);	
	}
};

function addSelectOnChange(element, func) {
	var a = $(element).data('_changeHandlers');
	if(undefined == a) {
		a = new Array();
		$(element).data('_changeHandlers', a);
	}
	a.push(func);
}

/*
 * Sets a select to read-only
 * element is the hidden form element in the div.select
 * readonly is true or false.  default is true
 */
function setReadOnly(element, readOnly) {
	var ro = (readOnly == 'false' || readOnly == false) ? false : true;
	if(ro) {
		$(element).parent().addClass('read-only');
	} else {
		$(element).parent().removeClass('read-only');
	}
	$(element).parent().attr("readonly",ro);
}

var _scrollerWidth = null;
function getScrollerWidth() {
	if(null == _scrollerWidth) {
		_scrollerWidth = __getScrollerWidth();
	}
	return _scrollerWidth;
}
 
// from http://jdsharp.us/jQuery/minute/calculate-scrollbar-width.php
function __getScrollerWidth() { 
    var div = $('<div style="width:50px;height:50px;overflow:hidden;position:absolute;top:-200px;left:-200px;"><div style="height:100px;"></div>'); 
    // Append our div, do our calculation and then remove it 
    $('body').append(div); 
    var w1 = $('div', div).innerWidth(); 
    div.css('overflow-y', 'scroll'); 
    var w2 = $('div', div).innerWidth(); 
    $(div).remove(); 
    return (w1 - w2); 
}
 
//
// Tab flyouts
//

function dce(className) {
	var result = document.createElement('div');
	result.className = className
	return result;
}

/*
 * create the tab flyouts
 */ 
$(document).ready(function () {
	
	$('li.child-category ul.level3').each(function (index, element) {
				
		var flyout = dce('flyout');
		var flyoutOverstate = dce('flyout-overstate');
		var flyoutAnchor = dce('flyout-anchor');
		var flyoutAnchorFill = dce('flyout-anchor-fill');
		var flyoutContainer = dce('flyout-container');
		var flyoutTop = dce('flyout-top');
		var flyoutBottom = dce('flyout-btm');
		var flyoutMain = dce('flyout-main');
		var flyoutClear = dce('clear');
		var flyoutBrowseAll = dce('flyout-browse-all');

		var l2link = $(element).prev().clone();
		var l2BrowseLink = l2link.clone();
		$(l2BrowseLink).attr('style', '');
		$(l2BrowseLink).html('Browse All');
		
		//flyout.style.display="none";
		
		$(element).parent().attr('hasflyout', 'true');
		
		$(element).after(flyout);
		$(flyout).append(flyoutOverstate);
		$(flyoutOverstate).append(l2link);
		$(flyout).append(flyoutContainer);
		$(flyoutContainer).append(flyoutAnchor);
		$(flyoutAnchor).append(flyoutAnchorFill);
		$(flyoutContainer).append(flyoutTop);
		$(flyoutTop).append(flyoutBottom);
		$(flyoutBottom).append(flyoutMain);
		$(flyoutMain).append(element);
		// flyoutClear and flyoutBrowseAll are appended at the end
		
		var numL3Elems = $(element).children('li').size()
		var numCols = (numL3Elems < 10) ? 1 : ((numL3Elems < 19) ? 2 : 3);
		var numRows = Math.ceil(numL3Elems/numCols);
		
		// estimate height of flyout vs position of parent
		var flyoutHeight = 7 + 22*numRows;
		var parentY = 10 + 35*index;
		var position = (parentY > flyoutHeight) ? 'btm' : 'top';
		
		$(flyout).attr('pos', position);
		$(flyout).attr('cols', numCols);

		var colsLeft = numCols;
		var lastInCol = -1;
		var colElem = null;
		var colNum = 0;
		$(element).children('li').each(function (i, li) {
			if(lastInCol <= i) {
				colNum++;
				colElem = document.createElement('ul');
				$(element).parent().append(colElem);
				
				lastInCol = Math.ceil(colNum * numL3Elems / numCols);
			}
			$(colElem).append(li);
		});

		$(flyoutMain).append(flyoutClear);
		$(flyoutMain).append(flyoutBrowseAll);
		$(flyoutBrowseAll).append(l2BrowseLink);
		
		// activate the tab flyout
		
		$(flyout).prev().bind("mouseenter", function() {
			
			$('.flyout').css('display', 'none');
			$('.flyout').parent().removeClass('covered');
			$(flyout).parent().addClass('covered')
			
			flyout.style.display = 'block';

			var flyoutMain = $(flyout).find('.flyout-main');

			// pre-widen the flyout to make the next calculation more accurate in IE.
			$(flyoutMain).width(300);

			// set the width of the flyoutMain so the columns can float
			var totalWidth = 1;
			$(flyoutMain).children('ul').each(function(index, ul) {
				var maxLiWidth = 0;
				$(ul).find('li span').each(function(spanindex, lispan) {
					maxLiWidth = Math.max(maxLiWidth, Math.min($(lispan).width(), 210));  // 210 is the max width of a column minus the padding on the span's enclosing <a>
				});
				
				var w = Math.max(160, maxLiWidth + 20) // 160 for the min-width of the ul, 20 for the padding on the span's enclosing <a>
				
				$(ul).width(w); // 20 for the padding on the span's enclosing <a>
				
				totalWidth += w + 19;  // 20 for the padding on the span's enclosing <a>, 19 for the margin width 
			});
			$(flyoutMain).width(Math.max(160, totalWidth));

		});
		$(flyout).bind("mouseleave", function() {
			flyout.style.display = 'none';
			$(flyout).parent().removeClass('covered')
		});

		// remove the original one-column from the layout
		$(element).remove();
	});
	
	$('li.child-category ul.level3b').each(function (index, element) {
		
		var flyout = dce('flyout');
		var flyoutOverstate = dce('flyout-overstate');
		var flyoutAnchor = dce('flyout-anchor');
		var flyoutAnchorFill = dce('flyout-anchor-fill');
		var flyoutContainer = dce('flyout-container');
		var flyoutTop = dce('flyout-top');
		var flyoutBottom = dce('flyout-btm');
		var flyoutMain = dce('flyout-main');
		var flyoutClear = dce('clear');
		var flyoutBrowseAll = dce('flyout-browse-all');

		var l2link = $(element).prev().clone();
		var l2BrowseLink = l2link.clone();
		$(l2BrowseLink).attr('style', '');
		$(l2BrowseLink).html('Browse All');
		
		//flyout.style.display="none";
		
		$(element).parent().attr('hasflyout', 'true');
		
		$(element).after(flyout);
		$(flyout).append(flyoutOverstate);
		$(flyoutOverstate).append(l2link);
		$(flyout).append(flyoutContainer);
		$(flyoutContainer).append(flyoutAnchor);
		$(flyoutAnchor).append(flyoutAnchorFill);
		$(flyoutContainer).append(flyoutTop);
		$(flyoutTop).append(flyoutBottom);
		$(flyoutBottom).append(flyoutMain);
		$(flyoutMain).append(element);
		// flyoutClear and flyoutBrowseAll are appended at the end
		
		var numL3Elems = $(element).children('li').size()
		var numCols = (numL3Elems < 10) ? 1 : ((numL3Elems < 19) ? 2 : 3);
		var numRows = Math.ceil(numL3Elems/numCols);
		
		// estimate height of flyout vs position of parent
		var flyoutHeight = 7 + 22*numRows;
		var parentY = 10 + 35*index;
		var position = (parentY > flyoutHeight) ? 'btm' : 'top';
		
		$(flyout).attr('pos', position);
		$(flyout).attr('cols', numCols);

		var colsLeft = numCols;
		var lastInCol = -1;
		var colElem = null;
		var colNum = 0;
		$(element).children('li').each(function (i, li) {
			if(lastInCol <= i) {
				colNum++;
				colElem = document.createElement('ul');
				$(element).parent().append(colElem);
				
				lastInCol = Math.ceil(colNum * numL3Elems / numCols);
			}
			$(colElem).append(li);
		});

		$(flyoutMain).append(flyoutClear);
		$(flyoutMain).append(flyoutBrowseAll);
		//$(flyoutBrowseAll).append(l2BrowseLink);
		
		// activate the tab flyout
		
		$(flyout).prev().bind("mouseenter", function() {
			
			$('.flyout').css('display', 'none');
			$('.flyout').parent().removeClass('covered');
			$(flyout).parent().addClass('covered')
			
			flyout.style.display = 'block';

			var flyoutMain = $(flyout).find('.flyout-main');

			// pre-widen the flyout to make the next calculation more accurate in IE.
			$(flyoutMain).width(300);

			// set the width of the flyoutMain so the columns can float
			var totalWidth = 1;
			$(flyoutMain).children('ul').each(function(index, ul) {
				var maxLiWidth = 0;
				$(ul).find('li span').each(function(spanindex, lispan) {
					maxLiWidth = Math.max(maxLiWidth, Math.min($(lispan).width(), 210));  // 210 is the max width of a column minus the padding on the span's enclosing <a>
				});
				
				var w = Math.max(160, maxLiWidth + 20) // 160 for the min-width of the ul, 20 for the padding on the span's enclosing <a>
				
				$(ul).width(w); // 20 for the padding on the span's enclosing <a>
				
				totalWidth += w + 19;  // 20 for the padding on the span's enclosing <a>, 19 for the margin width 
			});
			$(flyoutMain).width(Math.max(160, totalWidth));

		});
		$(flyout).bind("mouseleave", function() {
			flyout.style.display = 'none';
			$(flyout).parent().removeClass('covered')
		});

		// remove the original one-column from the layout
		$(element).remove();
	});
});
 
