jQuery(document)
		.ready( function() {
			/*!
			 * mcDropdown jQuery Plug-in
			 *
			 * Copyright 2008 Giva, Inc. (http://www.givainc.com/labs/) 
			 * 
			 * Licensed under the Apache License, Version 2.0 (the "License");
			 * you may not use this file except in compliance with the License.
			 * You may obtain a copy of the License at
			 * 
			 * 	http://www.apache.org/licenses/LICENSE-2.0
			 * 
			 * Unless required by applicable law or agreed to in writing, software
			 * distributed under the License is distributed on an "AS IS" BASIS,
			 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
			 * See the License for the specific language governing permissions and
			 * limitations under the License.
			 *
			 * Date: 2009-10-29
			 * Rev:  1.2.10
			 */
			jQuery.fn.mcDropdown = function(list, options) {
				// track the dropdown object
				var dd;

				// create a dropdown for each match
				this.each( function() {
					dd = jQuery.data(this, "mcDropdown");

					// we're already a dropdown, return a reference to myself
						if (dd) {
							return false;
						}

						new jQuery.mcDropDownMenu(this, list, options);
					});

				// return either the dropdown object or the jQuery object
				// reference
				return dd || this;
			};

			// set default options
				jQuery.mcDropdown = {
					version : "1.2.10",
					setDefaults : function(options) {
						jQuery.extend(defaults, options);
					}
				};

				// set the defaults
				var defaults = {
					minRows : 8 // specify the minimum rows before creating a
					// new column
					,
					maxRows : 25 // specify the maximum rows in a column
					,
					targetColumnSize : 2 // specify the default target column
					// size (it'll
					// attempt to create this many columns by
					// default, unless the min/max row rules are not
					// being met)
					,
					openFx : "slideDown" // the fx to use for showing the
					// root menu
					,
					openSpeed : 250 // the speed of the openFx
					,
					closeFx : "slideUp" // the fx to use for hiding the root
					// menu
					,
					closeSpeed : 250 // the speed of the closeFx
					,
					hoverOverDelay : 200 // the delay before opening a
					// submenu
					,
					hoverOutDelay : 0 // the delay before closing a submenu
					,
					showFx : "show" // the fx to use when showing a submenu
					,
					showSpeed : 0 // the speed of the showFx
					,
					hideFx : "hide" // the fx to use when closing a submenu
					,
					hideSpeed : 0 // the speed of the hideFx
					,
					dropShadow : true // determine whether drop shadows should
					// be shown on
					// the submenus
					,
					autoHeight : true // always uses the lineHeight options
					// (much faster
					// than calculating height)
					,
					lineHeight : 19 // the base height of each list item (li)
					// this is
					// normally calculated automatically, but in some cases
					// the value can't be determined and you'll need to set
					// it manually
					,
					screenPadding : 10 // the padding to use around the border
					// of the
					// screen -- this is used to make sure items stay on
					// the screen
					,
					allowParentSelect : true // determines if parent items
					// are allowed to
					// be selected (by default only end nodes
					// can be selected)
					,
					delim : " | " // the delimited to use when showing the
					// display
					// string
					,
					showACOnEmptyFocus : false // show the autocomplete box on
					// focus when
					// input is empty
					,
					valueAttr : "rel" // the attribute that contains the value
					// to use in
					// the hidden field
					,
					click : null // callback that occurs
					// when the user clicks
					// on a menu
					// item
					,
					select : null // callback that occurs when
					// a value is
					// selected
					,
					init : null
				// callback that occurs when the control is fully initialized
				};

				// check to see if the browser is IE6
				var isIE6 = (jQuery.browser.version && (jQuery.browser.version <= 6));

				jQuery.mcDropDownMenu = function(el, list, options) {
					var self, thismenu = this, list, divInput, settings, typedText = "", matchesCache, oldCache, keylist, keylistiframe, bInput, bDisabled = false;

					// create a reference to the dropdown
					self = jQuery(el);

					// is the field and input element
					bInput = self.is(":input");

					// get the settings for this instance
					settings = jQuery.extend( {}, defaults, options);

					// set the default click behavior
					if (settings.click == null) {
						settings.click = function(e, dropdown, settings) {
							dropdown.setValue(this.attr(settings.valueAttr));
							location.href = this.attr(settings.valueAttr) + '?p=1';
						}
					}

					// attach window behaviors
					jQuery(document)
					// Bind a click event to hide all visible menus when the
							// document is
							// clicked
							.bind(
									"click",
									function(e) {
										// get the target that was clicked
										var target = jQuery(e.target);
										var ul = target
												.parents()
												.filter(
														function() {
															return this === list[0]
																	|| (!!keylist && keylist[0] === this);
														});
										// check to make sure the clicked
										// element was inside
										// the list
										if (ul.length) {
											var bIsParent = target
													.is(".mc_parent");

											// if we've clicked a parent item in
											// the
											// autocomplete box, we must adjust
											// the current
											// value
											if (bIsParent && keylist
													&& ul[0] === keylist[0]) {
												// prevent the blur code from running
												clearTimeout(iBlurTimeout);
												updateValue(
														target
																.find("> ul > li:first"),
														false);
												e.stopPropagation();
												return false;
											}
											// check to see if the user can click on parent items
											else if (!settings.allowParentSelect
													&& bIsParent) {
												return false;
											}

											// make sure to hide the parent branch if we're
											// not the root
											if (target.not(".mc_root")) {
												hideBranch.apply(target
														.parent().parent()[0],
														[ e ]);
											}

											// alert(settings.click);
											if ((settings.click != null)
													&& (settings.click.apply(
															target, [ e,
																	thismenu,
																	settings ]) == false)) {
												return false;
											}
										}

										// close the menu
										thismenu.closeMenu();
									});

					// store a reference to the list, if it's not already a
					// jQuery object
					// make it one
					list = (((typeof list == "object") && !!list.jquery)) ? list
							: jQuery(list);

					// we need to calculate the visual width for each nested
					// list
					list
					// move list to body -- this allows us to always calculate
							// the correct
							// position & width of the elements
							.appendTo("body")
							// move the list way off screen
							.css( {
								position : "absolute",
								top : -10000,
								left : -10000
							})
							// find all the ul tags
							.find("ul")
							// add the root ul tag to the array
							.andSelf()
							// make all the nodes visible
							.css("display", "block")
							// loop through each node
							.each( function() {
								var el = jQuery(this);
								// calculate the width of the element -- using
									// clientWidth
									// is 2x as fast as width()
									el.data("width", el[0].clientWidth);
								})
							// now that we've gotten the widths, hide all the
							// lists and move
							// them to x:0, y:0
							.css( {
								top : 0,
								left : 0,
								display : "none"
							});

					// mark the root children items
					list.find("> li").addClass("mc_root");
					// add parent class
					jQuery("li > ul", list).parent().addClass("mc_parent");

					// create the div to wrap everything in
					divInput = jQuery(
							'<div class="mcdropdown"><a href="#" tabindex="-1"></a><input type="hidden" name="'
									+ (el.name || el.id)
									+ '" id="'
									+ (el.id || el.name) + '" /></div>')
							.appendTo(
									jQuery('<div style="position: relative;"></div>'))
							.parent();

					// get a reference to the input element and remove it from
					// the DOM
					var input = self.replaceWith(divInput).attr( {
						id : "",
						name : ""
					});
					// get a reference to the hidden form field
					var hidden = divInput.find(":input");

					// put the input element back in the div.mcdropdown layer
					divInput = divInput.find(".mcdropdown").prepend(input);

					// make a visible copy of the element so we can get the
					// correct sizes,
					// then delete it
					var divInputClone = divInput.clone().css( {
						position : "absolute",
						top : -9999999,
						left : -999999,
						visibility : "visible"
					}).show().appendTo("body");
					var di = {
						width : divInputClone.width()
								- jQuery("a", divInputClone).width(),
						height : divInputClone.outerHeight()
					}
					divInputClone.remove();

					// store a reference to this link select
					jQuery.data(hidden[0], "mcDropdown", thismenu);

					// update the height of the outer relative div, this allows
					// us to
					// correctly anchor the dropdown
					divInput.parent().height(di.height);

					// safari will not get the correct width until after
					// everything has
					// rendered
					if (jQuery.browser.safari) {
						setTimeout( function() {
							self.width(divInput.width()
									- jQuery("a", divInput).width());
						}, 100);
					}

					// adjust the width of the new input element
					self.width(di.width)
					// make sure we only attach the next events if we're in
							// input element
							.filter(":input")
							// turn autocomplete off
							.attr("autocomplete", "off")
							// add key stroke bindings (IE6 requires keydown)
							.bind("keypress", checkKeypress)
							// prevent user from selecting text
							.bind("mousedown", function(e) {
								jQuery(this).triggerHandler("focus");
								e.stopPropagation();
								return false;
							})
							// disable context menu
							.bind("contextmenu", function() {
								return false;
							})
							// select the text when the cursor is placed in the
							// field
							.bind("focus", onFocus)
							// when the user leaves the text field
							.bind("blur", onBlur);

					// IE6 doesn't register certain keypress events, so we must
					// catch them
					// during the keydown event
					if (jQuery.browser.msie || jQuery.browser.safari) {
						self.bind("keydown", function(e) {
							// check to see if a key was pressed that IE6 doesn't trigger a keypress event for
								if (",8,9,37,38,39,40,".indexOf("," + e.keyCode
										+ ",") > -1) {
									return checkKeypress(e);
								}
							});
					}

					// attach a click event to the anchor
					jQuery("a", divInput).bind("click", function(e) {
						// if disabled, skip processing
							if (bDisabled) {
								return false;
							}
							thismenu.openMenu(e);
							return false;
						});

					// set the value of the field
					this.setValue = function(value, skipCallback) {
						// alert('a:' + value);
						// update the hidden value
						hidden.val(value);
						// get the display name
						var name = displayString(value);
						// alert('b:' + name);
						// run the select callback (some keyboard entry methods
						// will manage
						// this callback manually)
						if ((settings.select != null) && (skipCallback != true)) {
							settings.select.apply(thismenu, [ value, name ]);
						}

						// update the display value and return the jQuery object
						return self[bInput ? "val" : "text"](name);
					};

					this.displayCurrentValue = function displayCurrentValue(
							value) {
						// return the display name
						return displayValue(value).join(settings.delim);
					}

					// set the default value (but don't run callback)
					if (bInput) {
						this.setValue(self.attr("defaultValue"), true);
					}

					// get the value of the field (returns array)
					this.getValue = function(value) {
						return [ hidden.val(), self[bInput ? "val" : "text"]() ];
					};

					// open the menu programmatically
					this.openMenu = function(e) {
						// if the menu is open, kill processing
						if (list.is(":visible")) {
							// on a mouse click, close the menu, otherwise just cancel
							return (!!e) ? thismenu.closeMenu() : false;
						}

						function open() {
							// columnize the root list
							columnizeList(list).hide();
							// add the bindings to the menu
							addBindings(list);

							// anchor the menu relative parent
							anchorTo(divInput.parent(), list, true);

							// remove existing hover classes, which might exist
							// from
							// keyboard entry
							list.find(".mc_hover").removeClass("mc_hover");

							// show the menu
							list[settings.openFx](settings.openSpeed,
									function() {
										// scroll the list into view
									scrollToView(list);
								});

							// if the bgIframe exists, use the plug-in
							if (isIE6 && !!jQuery.fn.bgIframe) {
								list.bgIframe();
							}
						}

						// if this is triggered via an event, just open the menu
						if (e) {
							open();
							// otherwise we need to open the menu asynchronously
							// to avoid
							// collision with jQuery(document).click event
						} else {
							setTimeout(open, 1);
						}
					};

					// close the menu programmatically
					this.closeMenu = function(e) {
						// hide any open menus
						list.find("ul:visible").parent().each( function() {
							hideBranch.apply(this);
						});

						// remove the bindings
						removeBindings(list);

						// close the menu
						list[settings.closeFx](settings.closeSpeed);
					};

					// place focus in the input box
					this.focus = function() {
						self.focus();
					};

					// disable the element
					this.disable = function(status) {
						// change the disabled status
						bDisabled = !!status;

						divInput[bDisabled ? "addClass" : "removeClass"]
								("mcdropdownDisabled");
						input.attr("disabled", bDisabled ? "disabled" : "");
					};

					function getNodeText(el) {
						// return either an empty string or the node's value
						return el.contents()[0] ? jQuery
								.trim(el.contents()[0].nodeValue) : "";
					}
					;

					function getTreePath(li) {
						//alert(li.length);
						if (li.length == 0) {
							return [];
						}

						var name = [ getNodeText(li) ];
						// alert("c : " + name);
						// loop through the parents and get the value
						li.parents().each( function() {
							var el = jQuery(this);
							// break when we get to the main list element
								if (this === list[0]) {
									return false;
								} else if (el.is("li")) {
									name.push(getNodeText(el));
								}
							});

						// return the display name
						return name.reverse();
					}
					;

					function displayValue(value) {
						// return the path as an array
						return getTreePath(getListItem(value));
					}
					;

					function displayString(value) {
						// return the display name
						return displayValue(value).join(settings.delim);
					}
					;

					function parseTree(selector) {
						var s = [], level = (arguments.length > 1) ? ++arguments[1]
								: 1;

						// loop through all the children and store information
						// about the
						// tree
						jQuery("> li", selector).each( function() {
							// get a reference to the current object
								var self = jQuery(this);

								// look for a ul tag as a direct child
								var ul = jQuery("> ul", this);

								// push a reference to the element to the tree
								// array
								s.push( {
									// get the name of the node
									name : getNodeText(self)
									// store a reference to the current element
									,
									element : this
									// parse and store any children items
									,
									children : (ul.length) ? parseTree(ul,
											level) : []
								});

							});

						return s;
					}
					;

					function addBindings(el) {
						removeBindings(el);
						jQuery("> li", el).bind("mouseover", hoverOver).bind(
								"mouseout", hoverOut);
					}
					;

					function removeBindings(el) {
						jQuery("> li", el).unbind("mouseover", hoverOver)
								.unbind("mouseout", hoverOut);
					}
					;

					// scroll the current element into view
					function scrollToView(el) {
						// get the current position
						var p = position(el, true);
						// get the screen dimensions
						var sd = getScreenDimensions();

						// if we're hidden off the bottom of the page, move up
						if (p.bottom > sd.y) {
							jQuery("html,body")
									.animate(
											{
												"scrollTop" : "+="
														+ ((p.bottom - sd.y) + settings.screenPadding)
														+ "px"
											})
						}
					}
					;

					function hoverOver(e) {
						var self = this;
						var timer = jQuery.data(self, "timer");

						// if the timer exists, clear it
						if (!isNaN(timer)) {
							clearTimeout(timer);
						}

						// if IE6, add the hover class
						jQuery(this).addClass("mc_hover");

						// show the branch
						jQuery.data(self, "timer", setTimeout( function() {
							showBranch.apply(self);
						}, settings.hoverOverDelay));
					}
					;

					function hoverOut(e) {
						var self = this;
						var timer = jQuery.data(self, "timer");

						// if the timer exists, clear it
						if (!isNaN(timer)) {
							clearTimeout(timer);
						}

						// if IE6, remove the hover class
						jQuery(this).removeClass("mc_hover");

						// hide the branch
						jQuery
								.data(
										self,
										"timer",
										setTimeout(
												function() {
													var li = jQuery(self);
													setTimeout(
															function() {
																// if no children selected, we must close the parent menus
																if (li
																		.parent()
																		.find(
																				"> li.mc_hover").length == 0) {
																	li
																			.parents(
																					"li")
																			.each(
																					function() {
																						var self = this;
																						clearTimeout(jQuery
																								.data(
																										self,
																										"timer"));
																						hideBranch
																								.apply(self);
																						// check
																						// to
																						// see
																						// if
																						// we've
																						// hovered
																						// over
																						// a
																						// parent
																						// item
																						if (jQuery(
																								this)
																								.siblings()
																								.filter(
																										".mc_hover").length > 0) {
																							return false;
																						}
																					});
																}

															},
															settings.hoverOverDelay);

													hideBranch.apply(self);
												}, settings.hoverOutDelay));

						// this will stop flickering in IE6, but it leaves
						// mc_hover classes
						// behind
						if (isIE6) {
							e.stopPropagation();
						}
					}
					;

					function getShadow(depth) {
						var shadows = self.data("shadows");

						// if the shadows don't exist, create an object to track
						// them
						if (!shadows) {
							shadows = {};
						}

						// if the shadow doesn't exist, create it
						if (!shadows[depth]) {
							// create shadow
							shadows[depth] = jQuery(
									'<div class="mcdropdown_shadow"></div>')
									.appendTo('body');
							// if the bgIframe exists, use the plug-in
							if (!!jQuery.fn.bgIframe) {
								shadows[depth].bgIframe();
							}
							// update the shadows cache
							self.data("shadows", shadows);
						}

						return shadows[depth];
					}
					;

					function showBranch() {
						var self = this;
						// the child menu
						var ul = jQuery("> ul", this);

						// if the menu is already visible or there is no
						// submenu, cancel
						if (ul.is(":visible") || (ul.length == 0)) {
							return false;
						}

						// hide any visible sibling menus
						jQuery(this).parent().find('> li ul:visible').not(ul)
								.parent().each( function() {
									hideBranch.apply(this);
								});

						// columnize the list
						columnizeList(ul);

						// add new bindings
						addBindings(ul);

						var depth = ul.parents("ul").length;

						// get the screen dimensions
						var sd = getScreenDimensions();

						// get the coordinates for the menu item
						var li_coords = position(jQuery(this));

						// move the menu to the correct position and show the
						// menu ||
						// ((depth)*2)
						ul.css( {
							top : li_coords.bottom,
							left : li_coords.marginLeft
						/* , zIndex: settings.baseZIndex + ((depth)*2) */})
								.show();

						// get the bottom of the menu
						var menuBottom = ul.outerHeight() + ul.offset().top;

						// if we're hidden off the bottom of the page, move up
						if (menuBottom > sd.y) {
							// adjust the menu by subtracting the bottom edge by the screen offset
							ul.css("top", li_coords.bottom
									- (menuBottom - sd.y)
									- settings.screenPadding);
						}

						var showShadow = function() {
							// if using drop shadows, then show them		
							if (settings.dropShadow) {
								// get a reference to the current shadow
								var shadow = getShadow(depth);
								// get the position of the parent element
								var pos = position(ul);

								// move the shadow to the correct visual & DOM
								// position
								shadow.css( {
									top : pos.top + pos.marginTop,
									left : pos.left + pos.marginLeft,
									width : pos.width,
									height : pos.height
								/* , zIndex: settings.baseZIndex + ((2*depth)-1) */
								}).insertAfter(ul).show();

								// store a reference to the shadow so we can
								// hide it
								jQuery.data(self, "shadow", shadow);
							}
						}

						// columnize the list and then show it using the defined effect
						// if the menu has a zero delay, just open it and then
						// draw the
						// shadow, otherwise show the effect and the draw the
						// shadow
						// after you're done.
						if (settings.showSpeed <= 0) {
							showShadow();
						} else {
							ul.hide()[settings.showFx](settings.showSpeed,
									showShadow);
						}
					}
					;

					function hideBranch() {
						var ul = jQuery("> ul", this);
						// if the menu is already visible or there is no
						// submenu, cancel
						if (ul.is(":hidden") || (ul.length == 0)) {
							return false;
						}

						// if using drop shadows, then hide
						if (settings.dropShadow && jQuery.data(this, "shadow")) {
							jQuery.data(this, "shadow").hide();
						}

						// if we're IE6, we need to set the visiblity to "hidden" so child
						// menus are correctly hidden and remove the .mc_hover
						// class due to
						// the e.stopPropagation() call in the hoverOut() call
						if (isIE6) {
							ul.css("visibility", "hidden").parent()
									.removeClass("mc_hover");
						}

						// hide the menu
						ul.stop()[settings.hideFx](settings.hideSpeed);
					}
					;

					function position(el, bUseOffset) {
						var bHidden = false;
						// if the element is hidden we must make it visible to
						// the DOM to
						// get
						if (el.is(":hidden")) {
							bHidden = !!el.css("visibility", "hidden").show();
						}

						var pos = jQuery
								.extend(
										el[bUseOffset === true ? "offset"
												: "position"](),
										{
											width : el.outerWidth(),
											height : el.outerHeight(),
											marginLeft : parseInt(
													jQuery.curCSS(el[0],
															"marginLeft", true),
													10) || 0,
											marginRight : parseInt(
													jQuery
															.curCSS(
																	el[0],
																	"marginRight",
																	true), 10) || 0,
											marginTop : parseInt(jQuery.curCSS(
													el[0], "marginTop", true),
													10) || 0,
											marginBottom : parseInt(jQuery
													.curCSS(el[0],
															"marginBottom",
															true), 10) || 0
										});

						if (pos.marginTop < 0) {
							pos.top += pos.marginTop;
						}
						if (pos.marginLeft < 0) {
							pos.left += pos.marginLeft;
						}

						pos["bottom"] = pos.top + pos.height;
						pos["right"] = pos.left + pos.width;

						// hide the element again
						if (bHidden) {
							el.hide().css("visibility", "visible");
						}

						return pos;
					}
					;

					function anchorTo(anchor, target, bUseOffset) {
						var pos = position(anchor, bUseOffset);

						target.css( {
							position : "absolute",
							top : pos.bottom,
							left : pos.left
						});

						/*
						 * we need to return the top edge of the core drop down
						 * menu, because the top:0 starts at this point when
						 * repositioning items absolutely this means we have to
						 * offset everything by the offset of the top menu
						 */

						return pos.bottom;
					}
					;

					function getScreenDimensions() {
						var d = {
							scrollLeft : jQuery(window).scrollLeft(),
							scrollTop : jQuery(window).scrollTop(),
							width : jQuery(window).width() // changed from
							// innerWidth
							,
							height : jQuery(window).height()
						// changed from innerHeight
						};

						// calculate the correct x/y positions
						d.x = d.scrollLeft + d.width;
						d.y = d.scrollTop + d.height;

						return d;
					}
					;

					function getPadding(el, name) {
						var torl = name == 'height' ? 'Top' : 'Left', // top or left
						borr = name == 'height' ? 'Bottom' : 'Right'; // bottom
						// or
						// right

						return (
						// we add "0" to each string to make sure parseInt() returns a number
						parseInt("0"
								+ jQuery.curCSS(el, "border" + torl + "Width",
										true), 10)
								+ parseInt("0"
										+ jQuery.curCSS(el, "border" + borr
												+ "Width", true), 10)
								+ parseInt("0"
										+ jQuery.curCSS(el, "padding" + torl,
												true), 10)
								+ parseInt("0"
										+ jQuery.curCSS(el, "padding" + borr,
												true), 10)
								+ parseInt("0"
										+ jQuery.curCSS(el, "margin" + torl,
												true), 10) + parseInt("0"
								+ jQuery.curCSS(el, "margin" + borr, true), 10));
					}
					;

					function getListDimensions(el, cols) {
						if (!el.data("dimensions")) {
							// get the width of the dropdown menu
							var ddWidth = divInput.outerWidth();
							// if showing the root item, then try to make sure
							// the width of
							// the menu is sized to the drop down menu
							var width = ((el === list) && (el.data("width")
									* cols < ddWidth)) ? Math.floor(ddWidth
									/ cols) : el.data("width");

							el.data("dimensions", {
								// get the original width of the list item
								column : width
								// subtract the padding from the first list item
								// from the
								// width to get the width of the items
								,
								item : width
										- getPadding(el.children().eq(0)[0],
												"width")
								// get the original height
								,
								height : el.height()
							});
						}

						return el.data("dimensions");
					}
					;

					function getHeight(el) {
						// skip height calculation and use lineHeight
						if (settings.autoHeight === false) {
							return settings.lineHeight;
						}
						// if we haven't cached our height, do so now
						if (!el.data("height")) {
							el.data("height", el.outerHeight());
						}

						// return the cached value
						return el.data("height");
					}
					;

					function columnizeList(el) {
						// get the children items
						var children = el.find("> li");
						// get the total number of items
						var items = children.length;

						// calculate how many columns we think we should have
						// based on the
						// max rows
						var calculatedCols = Math
								.ceil(items / settings.maxRows);
						// get the number of columns, don't columnize if we
						// don't have
						// enough rows
						// if the height of the column is bigger than the
						// screen, we
						// automatically try
						// moving to a new column
						var cols = !!arguments[1] ? arguments[1]
								: (items <= settings.minRows) ? 1
										: (calculatedCols > settings.targetColumnSize) ? calculatedCols
												: settings.targetColumnSize;
						// get the dimension of this element
						var widths = getListDimensions(el, cols);
						var prevColumn = 0;
						var columnHeight = 0;
						var maxColumnHeight = 0;
						var maxRows = Math.ceil(items / cols);

						// get the width of the parent item
						var parentLIWidth = el.parent("li").width();

						// we need to draw the list element, but hide it so we
						// can correctly
						// calculate it's information
						el.css( {
							"visibility" : "hidden",
							"display" : "block"
						});

						// loop through each child item
						children.each( function(i) {
							var currentItem = i + 1;
							var nextItemColumn = Math
									.floor((currentItem / items) * cols);
							// calculate the column we're in
								var column = Math.floor((i / items) * cols);
								// reference the current item
								var li = jQuery(this);
								// variable to track margin-top
								var marginTop;

								// if we're in the same column
								if (prevColumn != column) {
									// move to the top of the next column
									marginTop = (columnHeight + 1) * -1;
									// reset column height
									columnHeight = 0;
									// if we're in a new column
								} else {
									marginTop = 0;
								}

								// increase the column height based on it's current height (calculate this before adding classes)
								columnHeight += (getHeight(li) || settings.lineHeight);

								// update the css settings
								li.css( {
									"marginLeft" : (widths.column * column),
									"marginTop" : marginTop,
									"width" : widths.item
								})[((nextItemColumn > column) || (currentItem == items)) ? "addClass"
										: "removeClass"]("mc_endcol")[(marginTop != 0) ? "addClass"
										: "removeClass"]("mc_firstrow");
								// get the height of the longest column
								if (columnHeight > maxColumnHeight) {
									maxColumnHeight = columnHeight;
								}

								// update the previous column
								prevColumn = column;
							});

						// if the menu is too tall to fit on the screen, try
						// adding another
						// column
						if ((el !== list)
								&& (maxColumnHeight
										+ (settings.screenPadding * 2) >= getScreenDimensions().height)) {
							return columnizeList(el, cols + 1);
						}

						/*
						 * set the height of the list to the max column height. this fixes
						 * display problems in FF when the last column is not full.	
						 * 
						 * we also need to set the visiblity to "visible" to make sure that
						 * the element will show up	
						 */
						el.css("visibility", "visible").height(maxColumnHeight);

						return el;
					}
					;

					function getListItem(value) {
						return list.find("li[" + settings.valueAttr + "='"
								+ value + "']");
					}
					;

					function getCurrentListItem() {
						return getListItem(hidden.val());
					}
					;

					function onFocus(e) {
						var current = getCurrentListItem();
						var value = self.val().toLowerCase();
						var treePath = value.toLowerCase()
								.split(settings.delim);
						var currentNode = treePath.pop();
						var lastDelim = value.lastIndexOf(settings.delim) + 1;

						// reset the typed text
						typedText = treePath.join(settings.delim)
								+ (treePath.length > 0 ? settings.delim : "");

						// we need to set the selection asynchronously so that
						// when user
						// TABs to field the pre-select isn't overwritten
						setTimeout( function() {
							// preselect the last child node
								setSelection(self[0], lastDelim, lastDelim
										+ currentNode.length);
							}, 0);

						// create the keyboard hint list
						if (!keylist) {
							keylist = jQuery(
									'<ul class="mcdropdown_autocomplete"></ul>')
									.appendTo("body");
							// if IE6 we need an iframe to hide the scrolling
							// list
							if (isIE6 && !!jQuery.fn.bgIframe) {
								keylistiframe = jQuery('<div></div>')
										.bgIframe().appendTo("body");
							}
						}

						// should we show matches?
						var hideResults = !(settings.showACOnEmptyFocus && (typedText.length == 0));

						// get the siblings for the current item
						var siblings = ((current.length == 0) || current
								.hasClass("mc_root")) ? list.find("> li")
								: current.parent().find("> li");
						// show all matches
						showMatches(siblings, hideResults);
					}
					;

					var iBlurTimeout;
					function onBlur(e) {
						// we may need to cancel this blur event, so we run it asynchronously
						iBlurTimeout = setTimeout( function() {
							// get the current item
								var current = getCurrentListItem();

								// if we must select a child item, then update
								// to the first
								// child we can find
								if (!settings.allowParentSelect
										&& current.is(".mc_parent")) {
									// grab the first end child item we can find for the current path
									var value = current.find(
											"li:not('.mc_parent'):first").attr(
											settings.valueAttr);
									// update the value
									thismenu.setValue(value, true);
								}

								// run the select callback
								if (settings.select != null) {
									settings.select.apply(thismenu, thismenu
											.getValue());
								}

								// hide matches
								hideMatches();
							}, 200);
					}
					;

					function showMatches(li, hideResults) {
						var bCached = (li === oldCache), items = bCached ? keylist
								.find("> li").removeClass(
										"mc_hover mc_hover_parent mc_firstrow")
								: li
										.clone()
										.removeAttr("style")
										.removeClass(
												"mc_hover mc_hover_parent mc_firstrow mc_endcol")
										.filter(":last").addClass("mc_endcol")
										.end();

						// only do the following if we've updated the cache or
						// the list is
						// hidden
						if (!bCached || keylist.is(":hidden")) {
							// update the matches
							keylist.empty().append(items).width(
									divInput.outerWidth()
											- getPadding(keylist[0], "width"))
									.css("height", "auto");

							// anchor the menu relative parent
							anchorTo(divInput.parent(), keylist, true);

							// show hover on mouseover
							items.hover( function() {
								keylist.find("> li").removeClass(
										"mc_hover_parent mc_hover");
								jQuery(this).addClass("mc_hover")
							}, function() {
								jQuery(this).removeClass("mc_hover")
							});

							// make sure the the ul's are hidden (so the li's
							// are sized
							// correctly)
							items.find("> ul").css("display", "none");

							// show the list
							keylist.show().css(
									"visibility",
									(hideResults === true) ? "hidden"
											: "visible");

							// if we're IE6, ensure we enforce the "max-height"
							// CSS property
							if (isIE6) {
								var maxHeight = parseInt(keylist
										.css("max-height"), 10) || 0;
								if ((maxHeight > 0)
										&& (maxHeight < keylist.outerHeight())) {
									keylist.height(maxHeight);
								}

								// anchor the iframe behind the scrollable list
								if (!!jQuery.fn.bgIframe) {
									anchorTo(divInput.parent(), keylistiframe
											.css( {
												height : keylist.outerHeight(),
												width : keylist.width()
											}, true).show())
								}
							}

							// scroll the list into view
							if (hideResults !== true) {
								scrollToView(keylist);
							}
						}

						// do not show the list on screen
						if (hideResults === true) {
							// hide the results and move them offscreen (so it doesn't hide the cursor in FF2)
							keylist.css( {
								top : "-10000px",
								left : "-10000px"
							});
							// hiden the iframe overlay
							if (isIE6 && !!jQuery.fn.bgIframe) {
								keylistiframe.css("display", "none");
							}
						}

						// get the currently selected item
						var current = keylist.find("li[" + settings.valueAttr
								+ "='" + hidden.val() + "']");

						// make sure the last match is still highlighted
						current.addClass("mc_hover"
								+ (current.is(".mc_parent") ? "_parent" : ""));

						// scroll the item into view
						if ((current.length > 0) && (hideResults != true)) {
							scrollIntoView(current);
						}

						// update the cache
						oldCache = matchesCache = li;
					}
					;

					function hideMatches() {
						// hide the bgiframe
						if (isIE6 && !!jQuery.fn.bgIframe && keylistiframe) {
							keylistiframe.hide();
						}
						if (keylist) {
							keylist.hide();
						}
					}
					;

					// check the user's keypress
					function checkKeypress(e) {
						var key = String.fromCharCode(e.keyCode || e.charCode)
								.toLowerCase();
						var current = getCurrentListItem();
						var lis = ((current.length == 0) || current
								.hasClass("mc_root")) ? list.find("> li")
								: current.parent().find("> li");
						var treePath = typedText.split(settings.delim);
						var currentNode = treePath.pop();
						var compare = currentNode + key;
						var selectedText = getSelection(self[0]).toLowerCase();
						var value = self.val().toLowerCase();

						// if the up arrow was pressed
						if (e.keyCode == 38) {
							moveMatch(-1);
							return false;

							// if the down arrow was pressed
						} else if (e.keyCode == 40) {
							moveMatch(1);
							return false;

							// if the [ESC] was pressed
						} else if (e.keyCode == 27) {
							// clear typedText
							typedText = "";
							// clear the value
							thismenu.setValue("");
							// show the root level
							showMatches(list.find("> li"));

							return false;

							// if user pressed [DEL] or [LEFT ARROW], go remove
							// last typed
							// character
						} else if ((e.keyCode == 8) || (e.keyCode == 37)) {
							// if left arrow, go back to previous parent
							compare = (e.keyCode == 37) ? "" : currentNode
									.substring(0, currentNode.length - 1);

							// if all the text is highlighted we just came from
							// a delete
							if (selectedText == currentNode) {
								currentNode = "";
							}
							// we're going backwards to the last parent, move backwards
							if ((treePath.length > 0)
									&& (currentNode.length == 0)) {
								updateValue(current.parent().parent());
								return false;
								// if all the text is selected, remove
								// everything
							} else if (selectedText == value) {
								typedText = "";
								thismenu.setValue("");
								return false;
							}
							// if the user pressed [ENTER], [TAB], [RIGHT ARROW] or the delimiter--go to next level
						} else if ((e.keyCode == 9) || (e.keyCode == 13)
								|| (e.keyCode == 39) || (key == settings.delim)) {
							// get the first child item if there is one
							var first = current.find("> ul > li:first");

							// update with the next child branch
							if (first.length > 0) {
								updateValue(first);
								// leave the field
							} else {
								// if IE6, we must deselect the selection
								if (jQuery.browser.msie) {
									setSelection(self[0], 0, 0);
								}
								if (e.keyCode == 9) {
									// blur out of the field
									self.triggerHandler("blur");
									// hide the matches
									hideMatches();
									// allow the tab
									return true;
								} else {
									// blur out of the field
									self.trigger("blur");
									// hide the matches
									hideMatches();
								}
							}

							return false;
							// if all the text is highlighted then we need to
							// delete
							// everything
						} else if (selectedText == value) {
							typedText = "";
							compare = key;
						}

						// update the match cache with all the matches
						matchesCache = findMatches(lis, compare);

						// if we have some matches, populate autofill and show
						// matches
						if (matchesCache.length > 0) {
							// update the a reference to what the user's typed
							typedText = treePath.join(settings.delim)
									+ (treePath.length > 0 ? settings.delim
											: "") + compare;
							updateValue(matchesCache.eq(0), true);
						} else {
							// find the previous compare string
							compare = compare.length ? compare.substring(0,
									compare.length - 1) : "";

							// since we have no matches, get the previous
							// matches
							matchesCache = findMatches(lis, compare);

							// if we have some matches, show them
							if (matchesCache.length > 0) {
								showMatches(matchesCache);
								// hide the matches
							} else {
								hideMatches();
							}
						}

						// stop default behavior
						e.preventDefault();

						return false;
					}
					;

					function moveMatch(step) {
						// find the current item in the matches cache
						var current = getCurrentListItem(), next, pos = 0;

						// if nothing selected, look for the item with the hover
						// class
						if (current.length == 0) {
							current = matchesCache
									.filter(".mc_hover, .mc_hover_parent");
						}
						// if still nothing, grab the first item in the cache
						if ((current.length == 0) || keylist.is(":hidden")) {
							// grab the first item
							current = matchesCache.eq(0);
							// since nothing is selected, don't step
							// forward/back
							step = 0;
						}

						// find the current position of the element		
						matchesCache.each( function(i) {
							if (this === current[0]) {
								pos = i;
								return false;
							}
						});

						// if no matches, cancel
						if (!matchesCache || (matchesCache.length == 0)
								|| (current.length == 0)) {
							return false;
						}

						// adjust by the step count
						pos = pos + step;

						// make sure pos is in valid bounds
						if (pos < 0) {
							pos = matchesCache.length - 1;
						} else if (pos >= matchesCache.length) {
							pos = 0;
						}

						// get the next item
						next = matchesCache.eq(pos);

						updateValue(next, true);
					}
					;

					function findMatches(lis, compare) {
						var matches = jQuery( []); // jQuery([]) = empty jquery
						// object

						lis.each( function() {
							// get the current list item and it's label
								var li = jQuery(this), label = getNodeText(li);

								// label matches what the user typed, add it to
								// the queue
								if (label.substring(0, compare.length)
										.toLowerCase() == compare) {
									// store a copy to this jQuery item
									matches = matches.add(li);
								}
							});

						// return the matches found
						return matches;
					}
					;

					function updateValue(li, keepTypedText) {
						// grab all direct children items
						var siblings = keepTypedText ? matchesCache
								: ((li.length == 0) || li.hasClass("mc_root")) ? list
										.find("> li")
										: li.parent().find("> li");
						var treePath = getTreePath(li);
						var currentNode = treePath.pop().toLowerCase();

						// update the a reference to what the user's typed
						if (!keepTypedText) {
							typedText = treePath.join(settings.delim)
									.toLowerCase()
									+ (treePath.length > 0 ? settings.delim
											: "");
						}

						// update form field and display with the updated value
						thismenu.setValue(li.attr(settings.valueAttr), true);

						// pre-select the last node
						setSelection(self[0], typedText.length,
								currentNode.length + typedText.length);

						// remove any currently selected items
						siblings.filter(".mc_hover,.mc_hover_parent")
								.removeClass("mc_hover mc_hover_parent");
						// add the hover class
						li.addClass("mc_hover"
								+ (li.is(".mc_parent") ? "_parent" : ""));

						// show all the matches
						showMatches(siblings);
					}
					;

					// get the text currently selected by the user in a text
					// field
					function getSelection(field) {
						var text = "";
						if (field.setSelectionRange) {
							text = field.value.substring(field.selectionStart,
									field.selectionEnd);
						} else if (document.selection) {
							var range = document.selection.createRange();
							if (range.parentElement() == field) {
								text = range.text;
							}
						}
						return text;
					}
					;

					// set the text selected in a text field
					function setSelection(field, start, end) {
						if (field.createTextRange) {
							var selRange = field.createTextRange();
							selRange.collapse(true);
							selRange.moveStart("character", start);
							selRange.moveEnd("character", end);
							selRange.select();
						} else if (field.setSelectionRange) {
							field.setSelectionRange(start, end);
						} else {
							if (field.selectionStart) {
								field.selectionStart = start;
								field.selectionEnd = end;
							}
						}
						field.focus();
					}
					;

					function scrollIntoView(el, center) {
						var el = el[0];
						var scrollable = keylist[0];
						// get the padding which is need to adjust the scrollTop
						var s = {
							pTop : parseInt(keylist.css("paddingTop"), 10) || 0,
							pBottom : parseInt(keylist.css("paddingBottom"), 10) || 0,
							bTop : parseInt(keylist.css("borderTopWidth"), 10) || 0,
							bBottom : parseInt(
									keylist.css("borderBottomWidth"), 10) || 0
						};

						// scrolling down
						if ((el.offsetTop + el.offsetHeight) > (scrollable.scrollTop + scrollable.clientHeight)) {
							scrollable.scrollTop = el.offset().top
									+ (scrollable.scrollTop - keylist.offset().top)
									- ((scrollable.clientHeight / ((center == true) ? 2
											: 1)) - (el.outerHeight() + s.pBottom));
							// scrolling up
						} else if (el.offsetTop - s.bTop - s.bBottom <= (scrollable.scrollTop
								+ s.pTop + s.pBottom)) {
							scrollable.scrollTop = el.offset().top
									+ (scrollable.scrollTop - keylist.offset().top)
									- s.pTop;
						}
					}
					;

					// run the init callback (some keyboard entry methods will
					// manage this
					// callback manually)
					if (settings.init != null) {
						settings.init.apply(thismenu, [ input, hidden, list ]);
					}

				};

			});

