//Generic
;(function($){
	$.stubhub =  {
		ajaxErrorPage:'/errorAjax.html',
		helpBubbleBaseUrl:'/help/services/popUp?nodeDesc=',
		enableDebug:false,
		enableCustomConsole:false
	};


	/* add a custom debug console if there's no native support */
	if($.stubhub.enableCustomConsole && $.stubhub.enableDebug && !window.console){
		window.console={
			init:function(){
				if (!console.$el) {
					var heightPercentage='20';
					console.$el = $('<div id="debugConsole"></div>');
					if($.fn.dialog) { 
						var windowWidth = $(window).width();
						var windowHeight = $(window).height();
						console.$el.dialog({
							autoOpen:true,
							draggable:true,
							resizable:true,
							width:windowWidth,
							height:windowHeight*heightPercentage/100,
							minHeight:10,
							dialogClass:'debugConsoleDialog',				
							position:['bottom','center']
						})
					} else {
						console.$el.css('height',heightPercentage+'%');
						$('body').append(console.$el);
					}
				}
			},
			log:function(text){
				if (!console.$el) console.init();
				//text.replace('\n','<br/>');
				console.$el.append('<div>'+text+'</div>');
			}
		};
	}	

	/* provide a custom function to output debug messages to the console window */
	$.showDebug = function(text) {
		if($.stubhub.enableDebug && window.console) {
			window.console.log(text);
		};
	};

	$.fn.moveOffScreen = function() {
		return this.each(function() {
			$(this).addClass('offscreen');
		});
	};
	$.fn.moveOnScreen = function() {
		return this.each(function() {
			$(this).removeClass('offscreen');
		});
	};
	
	$.fn.charcounter = function(options) {
		var defaults = {
			textid:'eventinfocount',
    			max:5000
		};
		var opts = jQuery.extend(defaults,options);
		var id = "#"+$(this).attr("id");		
		return this.each(function() {			
			$(this).keyup(function(){
				$('#'+opts.textid).html(opts.max-$(this).val().length);
				// restrict the length of the string to the "max"
				if ($(this).val().length > opts.max) {  
				   this.value = $(this).val().substr(0, opts.max); 
				   $('#'+opts.textid).html(0) 
				}
				
			});
		});		
	}

	/*
	 * roundedCorners plugin
	 * version 1.0 (03-Mar-2009)
	 *
	 * This plugin places some extra markup around elements that need to have rounded corners.
	 * It's up to external style definitions to actually style that extra markup.
	 *
	 * example usage: $(".tabBody").roundedCorners({wrapperClass:'rc-panel2 rc-panel2-trblbr',overrideCSSRadius:true});
	 */
	$.fn.roundedCorners = function (options) {
		var opts = $.extend({
			wrapperClass:'rc-all',
			wrapperId:'',
			replaceBorder: true,
			overrideCSSRadius: false
		}, options || {} );
		return this.each ( function () {
			var CSSRadius = ''+$(this).css('border-radius-topleft')+$(this).css('border-radius-topright')+$(this).css('border-radius-bottomleft')+$(this).css('border-radius-bottomright')
			               +$(this).css('-moz-border-radius-topleft')+$(this).css('-moz-border-radius-topright')+$(this).css('-moz-border-radius-bottomleft')+$(this).css('-moz-border-radius-bottomright')
			               +$(this).css('-webkit-border-radius-topleft')+$(this).css('-webkit-border-radius-topright')+$(this).css('-webkit-border-radius-bottomleft')+$(this).css('-webkit-border-radius-bottomright');
			var hasCSSRadius = (CSSRadius.match('px') && CSSRadius!='0px0px0px0px') ? true:false;
			if (!hasCSSRadius || opts.overrideCSSRadius) {
				// store margin and clear style of 'this' because we need to move those settings to the rc wrapper element;
				thisMargin = {
					top:$(this).css('margin-top'),
					right:$(this).css('margin-right'),
					bottom:$(this).css('margin-bottom'),
					left:$(this).css('margin-left')
				};
				thisMargin.all = thisMargin.top + ' ' + thisMargin.right + ' ' + thisMargin.bottom + ' ' + thisMargin.left;
				thisClear = $(this).css('clear');
				// remove margin and clear style on 'this'
				$(this).css('margin','0');
				$(this).css('clear','none');
				// remove border settings;
				if(opts.replaceBorder) $(this).css('border','none');
				// add div elements that contain classes which need to be styled externally;
				$(this).wrap('<div id="tempRoundedCornersId" class="' + opts.wrapperClass + '"></div>');
				var wrapper = $('#tempRoundedCornersId').html(
					'<div class="rc-tl"></div><div class="rc-tr"></div><div class="rc-b"><div class="bd">' +
					$('#tempRoundedCornersId').html() +
					'</div></div><div class="rc-bl"></div><div class="rc-br"></div>'
				).removeAttr('id').css('margin', thisMargin.all).css('clear',thisClear);
				// add id if requested;
				if(opts.wrapperId != '') $(wrapper).attr('id',opts.wrapperId);
			}
		});
	};

	/* "global" overlay stack, used by the overlay plugin */
	$.stubhub.overlayStack = {
		value: [],
		add: function(elem) {
			this.value.push(elem);
		},
		remove: function(elem) {
			var pos;
			for(var i = 0; i < this.value.length; ++i) {
				if(this.value[i] == elem) {
					pos = i;
				}
			}
			
			this.value.splice(pos, 1);
		},
		closeAll: function() {
			for(var i = 0; i < this.value.length; ++i) {
				if(this.value[i].closeOverlay) {
					this.value[i].closeOverlay();
				}
			}
			this.value = [];
		}
	};
	
	/* bubbleOverlay plugin
	 * this is a shortcut to the overlay plugin with predefined settings and minimal configuration
	 */
	$.fn.bubbleOverlay = function(options) {
		var defaults = {
			width:250,
			trigger:'mouseover',
			offsetX:0,
			offsetY:0,
			preventClickDefault:true,
			exclusive:false
		};
		var opts = $.extend(defaults, options || {});
		return this.each(function() {
			$(this).overlay({
				style:'callout',
				align:'relative',
				preferedPosition:'above',
				offsetX:opts.offsetX,
				offsetY:opts.offsetY,
				overlayClass:'ov-bubble',
				showCloseIcon:false,
				openDelay:50,
				closeDelay:500,
				modal:false,
				width:opts.width,
				trigger:opts.trigger,
				preventClickDefault:opts.preventClickDefault,
				exclusive:opts.exclusive
			});
		});
	}

	/* bubblehelpOverlay plugin
	 * this is a shortcut to the overlay plugin with predefined settings and minimal configuration
	 */
	$.fn.bubblehelpOverlay = function(options) {
		var defaults = {
			width:250,
			trigger:'mouseover',
			offsetX:-5,
			offsetY:0,
			preventClickDefault:true,
			exclusive:false
		};
		var opts = $.extend(defaults, options || {});
		return this.each(function() {
			$(this).overlay({
				style:'callout',
				align:'relative',
				preferedPosition:'above',
				offsetX:opts.offsetX,
				offsetY:opts.offsetY,
				overlayClass:'ov-bubblehelp',
				showCloseIcon:false,
				openDelay:0,
				closeDelay:500,
				modal:false,
				width:opts.width,
				trigger:opts.trigger,
				preventClickDefault:opts.preventClickDefault,
				exclusive:opts.exclusive
			});
		});
	}

	
	/* overlay plugin 
	 * version 0.9 (18-Aug-2009)
	 *
	 * This plugin enables overlays using the standard jQuery dialog() function.
	 * It places some extra markup around the element that invokes it to support border graphics,
	 * and it provides extra functionality to position the overlay.
	 * It's up to external style definitions to actually style that extra markup.
	 *
	 * Main options (first option shown is the default): 
	 *   modal:false|true
	 *   align:'centered'|'relative' (general positioning on the page: either centered or aligned with the trigger element. May need to add 'fixed' later for alert-type overlays)
	 *   style:'box'|'callout' (style 'callout' will have extra markup for callout spike)
	 *   source:null|string (in case the link trigger is not an <a> element, the overlay source - either a URL or div id selector (#myId) - can be passed in)
	 *   preferedPosition:'below'|'above' (prefered position with respect to trigger element - is ignored if align:'centered')
	 *   preferedAlignment:'left'|'right' (prefered alignment with respect to trigger element - is ignored if align:'centered')
	 *   offsetX:0 (horizontal offset)
	 *   offsetY:0 (vertical offset)
	 *   showCloseIcon:true|false (enable dialog() close icon)
	 *   openDelay:null|integer (time in milliseconds to leave mouse over trigger link before overlay shows)
	 *   closeDelay:null|integer (time in milliseconds to leave overlay visible after mouse moves away)
	 *   closeSelector:null|jQuery-selector-expression (jQuery selector for elements in the overlay that should trigger a close)
	 *   overlayClass:'ov-overlay'  (string that will be passed on as parameter dialogClass to dialog())
	 *   overlayId:null|string (string that will be passed on as id attribute to the overlay wrapper element; this can be used as target id when an Ajax request updates the overlay content)
	 *   width:500  (overall width of the styled overlay)
	 *   trigger:'click'|'mouseover'|'load' (event that triggers the overlay display)
	 *   preventClickDefault:true|false (prevent default click event for triggers other than 'click')
	 *   bgiframe:true|false (implement bgiframe plugin for IE6 fixes)
	 *   open:null|function(elem,orientation,opts)  (function to run right after open of dialog; it returns the trigger element, the overlay orientation and all options)
	 *   close:null|function(elem,opts)  (function to run right before close of dialog; it returns the trigger element and all options)
	 *   cache:true|false (cache ajax responses)
	 *   exclusive:true|false (close other overlays if exist)
	 *
	 * example usage with internal source:  
	 *	<a href="#myOverlay" class="modaloverlayTrigger">open modal centered overlay</a>
	 *	$('.modaloverlayTrigger').overlay({modal:true});
	 * example usage with external source:
	 *	<a href="/myService/myContent?id=xxx" class="modaloverlayTrigger">open modal centered overlay</a>
	 *	$('.modaloverlayTrigger').overlay({modal:true});
	 */
	
	$.fn.overlay = function(options) {
		var defaults = {
			modal:false,
			align:'centered',
			style:'box',
			source:null,
			preferedPosition:'below',
			preferedAlignment:'left',
			offsetX:0,
			offsetY:0,
			showCloseIcon:true,
			openDelay:null, /*not yet implemented*/
			closeDelay:null,
			overlayClass:'ov-overlay',
			overlayId:null,
			width:500,
			trigger:'click',
			preventClickDefault:true,
			bgiframe:true,
			open:null,
			close:null,
			cache:true,
			exclusive:true
		};
		
		var opts = $.extend(defaults, options || {}),
			closeControlClass = 'ov-closeControl',
			noCloseControlClass = 'ov-noCloseControl';
		
		/* set some fixed settings for jQuery dialog() */
		opts.autoOpen=true;
		opts.closeOnEscape=true;
		opts.draggable=false;
		opts.resizable=false;
		opts.minHeight=10;
		opts.position=['center','center'];
		/* initialize context-specific settings for jQuery dialog() */
		
		if (opts.showCloseIcon) {
			opts.dialogClass = [opts.overlayClass, closeControlClass].join(' ');
		} else {
			opts.dialogClass = [opts.overlayClass, noCloseControlClass].join(' ');
		}

		return this.each(function() {
			bindOverlay(this);
		});

		function bindOverlay(elem) {
			var $elem=$(elem)
			if (opts.trigger==='load') {
				openOverlay(elem);
				return false;
			};
			$elem.bind(opts.trigger, function(e) {				
				openOverlay(elem);
				return false;
			});
			if (opts.trigger !== 'click' && opts.preventClickDefault) {
				/* prevent default click event for non-click triggers like mouseover */
				$elem.bind('click', function(e) {				
					e.preventDefault();
				});
			}
		}

		function openOverlay(elem) {
						
			var $elem=$(elem),
			    ovContentTarget,
			    $ovWrapper=$('<div class="ov-wrapper"></div>'),
			    $ovContent=$('<div></div>'),
			    ovTimeout;

			if ( elem.jqdialog ) {
				if ( elem.jqdialog.dialog('isOpen') ) {
					/* dialog is already open, move it to top of stack in case it is hidden behind others */
					elem.jqdialog.dialog('moveToTop');
					return;
				} else {
					elem.jqdialog.dialog('destroy');
				};
			};
			
			if(opts.exclusive) {
				$.stubhub.overlayStack.closeAll();
			}
			$.stubhub.overlayStack.add(elem);
			
			if(opts.closeSelector) {
				$(opts.closeSelector).live('click', function(e) { 
					$(elem).data('overlay', $ovWrapper);   
					elem.closeOverlay(); 
					e.preventDefault();
				});
			};

			if (opts.source) {
				ovContentTarget = opts.source;
			} else {
				ovContentTarget = $elem.attr('href');
				ovContentTarget = ovContentTarget.replace(location.href,'');
			}
			
			if(ovContentTarget.substr(0,1)==='#') {
				var $ovContentTarget = $(ovContentTarget),
					$contentParent = $ovContentTarget.parent().get(0); 
				$elem.data('overlay-content', $ovContentTarget);
				$elem.data('overlay-content-parent', $contentParent);
				
				$ovContentTarget.css('display','block').appendTo($ovContent);
				buildOverlay();
			} else {
				$.ajax({
					url:ovContentTarget,
					cache:opts.cache,
					success:function(html){
						$ovContent.append(html);
						buildOverlay();
					},
					error:function(){
						/* try to retrieve static ajax error page as fallback */
						$.ajax({
							url:$.stubhub.ajaxErrorPage,
							success:function(html){
								$ovContent.append(html);
								buildOverlay();
							},
							error:function(){
								return false;
							}
						});
					}
				});

			};			

			function buildOverlay() {
			
				/* final html structure of overlay:
				// <div class="ov-wrapper">
				//	<div class="ov-slice ov-slice-tr">
				//		<div class="ov-slice ov-slice-tl"></div>
				// 		<div [id="opts.overlayId"] class="ov-content"> ........ </div>
				// 	</div>
				//	<div class="ov-slice ov-slice-br">
				//		<div class="ov-slice ov-slice-bl"></div>
				//	</div>
				// </div>
				*/
				var wrapperId = (opts.overlayId)? 'id="'+opts.overlayId+'" ' : '';
			
				$ovWrapper = $ovWrapper.html('<div class="ov-slice ov-slice-tr"><div class="ov-slice ov-slice-tl"></div><div ' + wrapperId + 'class="ov-content">'
						+ $ovContent.html()
						+ '</div></div><div class="ov-slice ov-slice-br"><div class="ov-slice ov-slice-bl"></div></div>');

				$elem.data('overlay', $ovWrapper);

				/* create the dialog but hide it offscreen, so that we can get the proper styled dimensions to be able to position it */
				elem.jqdialog = $ovWrapper.dialog({
					autoOpen: true,
					closeOnEscape: opts.closeOnEscape,
					draggable: opts.draggable,
					width: opts.width,
					minHeight: opts.minHeight,
					dialogClass: opts.dialogClass,				
					resizable: opts.resizable,
					bgiframe: opts.bgiframe,
					modal: opts.modal,
					position: opts.position,
					close: function() {
						elem.closeOverlay();
					}
				}).moveOffScreen();
		
				if (opts.align === 'centered') {
					elem.jqdialog.moveOnScreen();
				} else {
					/*position has not yet been defined, so we need to determine relative position*/

					var wrapperWidth = opts.width,
					    wrapperHeight = elem.jqdialog.outerHeight(),
					    elemOffsetTop = $elem.offset().top,
					    elemOffsetLeft = $elem.offset().left, 
					    elemOffsetRight = elemOffsetLeft + $elem.outerWidth(), 
					    elemOffsetBottom = elemOffsetTop + $elem.outerHeight(),
					    scrollTop = numb($(document).scrollTop()), 
					    scrollLeft = numb($(document).scrollLeft()), 
					    winWidth = numb($(window).width()), 
					    winHeight = numb($(window).height()), 
					    availableSpace = new Object(),
					    orientation = opts.preferedPosition + '-' + opts.preferedAlignment + 'Aligned',
					    locX,
					    locY;
					    
					/* determine the available space around the trigger element: */
					availableSpace.top = elemOffsetTop - scrollTop;
					availableSpace.bottom = winHeight - (elemOffsetBottom - scrollTop);
					availableSpace.left = elemOffsetLeft - scrollLeft;
					availableSpace.right = winWidth - (elemOffsetRight - scrollLeft);
					
					/* determine the overlay orientation with respect to the trigger element */										
					orientation = decideOrientation(availableSpace, wrapperWidth, wrapperHeight, opts.preferedPosition, opts.preferedAlignment);
					
			
					if(opts.style == 'callout')	{
	    					switch(orientation) {
							case 'below-leftAligned':
								$ovWrapper.prepend('<div class="ov-spike ov-spike-tl"></div>');
								break;
							case 'below-rightAligned':
								$ovWrapper.prepend('<div class="ov-spike ov-spike-tr"></div>');
								break;
							case 'above-leftAligned':
								$ovWrapper.append('<div class="ov-spike ov-spike-bl"></div>');	
								break;
							case 'above-rightAligned':
								$ovWrapper.append('<div class="ov-spike ov-spike-br"></div>');
								break;
	    					}
	    					/* since we added the spikes, recalculate height, but we need to set/unset formatting context because ov-spike-br is likely to float:right */
	    					elem.jqdialog.addClass('setFormattingContext');
	    					wrapperHeight = elem.jqdialog.outerHeight();
	    					elem.jqdialog.removeClass('setFormattingContext');
	    				};
	    				
					switch(orientation) {
						case 'below-leftAligned':
							locY = elemOffsetBottom + opts.offsetY;
							locX = elemOffsetLeft + opts.offsetX;
							break;
						case 'below-rightAligned':
							locY = elemOffsetBottom + opts.offsetY;
							locX = elemOffsetRight - wrapperWidth - opts.offsetX;
							break;
						case 'above-leftAligned':
							locY = elemOffsetTop - wrapperHeight - opts.offsetY;
							locX = elemOffsetLeft + opts.offsetX;							
							break;
						case 'above-rightAligned':
							locY = elemOffsetTop - wrapperHeight - opts.offsetY;
							locX = elemOffsetRight - wrapperWidth - opts.offsetX;						
							break;
					};

					opts.position=[locX - scrollLeft , locY - scrollTop];
					elem.jqdialog.dialog('option', 'position', opts.position);
					elem.jqdialog.moveOnScreen();
										
					if(opts.open) {
						opts.open(elem,orientation,opts);
					}
				};


				elem.clearTimeout = function() {
					clearTimeout(elem.jqdialog.ovTimeout);
				};
				
				elem.closeOverlayAfterTimeout = function() {
					elem.jqdialog.ovTimeout = setTimeout(function(){
						/* make sure dialog still exists; it might have been closed elsewhere during timeout if opts.exclusive=true */ 
						if (elem.jqdialog) elem.jqdialog.dialog('close');
					}, opts.closeDelay);
				};
				
				if (opts.closeDelay) {
					$elem.bind('mouseenter.overlay', elem.clearTimeout).bind('mouseleave.overlay', elem.closeOverlayAfterTimeout);
					$ovWrapper.bind('mouseenter.overlay', elem.clearTimeout).bind('mouseleave.overlay', elem.closeOverlayAfterTimeout);
				}
				
				elem.closeOverlay = function() {
					var $this = $(this);
					
					if(this.jqdialog.dialog('isOpen') && $this.data('overlay')) {						
						var content = $this.data('overlay-content'),
							contentParent = $this.data('overlay-content-parent');
						if(content && contentParent) {
							content.css('display', 'none').appendTo(contentParent);
						}
												
						if (opts.close) {
							opts.close(elem,opts);
						};
						var box = $this.data('overlay');						
						
						$.stubhub.overlayStack.remove(this);
						box.unbind('.overlay');
						box.dialog('destroy');
						box.remove();
						$this.unbind('.overlay');
						//elem.jqdialog = null;
					}
				};
				return false;
				
			}; /* end buildOverlay() */

			return false;
		} /* end openOverlay() */
		
		
		function numb(num) {
			return parseInt(num) || 0;
		}
		
		function decideOrientation(availableSpace, wrapperWidth, wrapperHeight, preferedPosition, preferedAlignment) {
			preferedPosition = preferedPosition || 'below';
			preferedAlignment = preferedAlignment || 'left';
			var dimension = {
				top: 'above',
				bottom: 'below',
				left: 'leftAligned',
				right: 'rightAligned'
			};
				
			var top = availableSpace.top,
				bottom = availableSpace.bottom,
				left = availableSpace.left,
				right = availableSpace.right,
				topStr = dimension.top,
				bottomStr = dimension.bottom,
				leftStr = dimension.left,
				rightStr = dimension.right;

			if(preferedPosition === 'above') {
				top = availableSpace.bottom;
				bottom = availableSpace.top;		
				
				topStr = dimension.bottom;
				bottomStr = dimension.top;
			};
			if(preferedAlignment === 'right') {							
				left = availableSpace.right;
				right = availableSpace.left;
				
				leftStr = dimension.right;
				rightStr = dimension.left;
			};
			var orientation = preferedPosition + '-' + preferedAlignment + 'Aligned';
			if(left > wrapperWidth) {
				orientation = preferedPosition + '-' + rightStr;
			}
			if(right > wrapperWidth) {
				orientation = preferedPosition + '-' + leftStr;
			}
			if(top > wrapperHeight) {
				orientation = topStr + '-' + preferedAlignment + 'Aligned';
				if(left > wrapperWidth) {
					orientation = topStr + '-' + rightStr;
				}
				if(right > wrapperWidth) {
					orientation = topStr + '-' + leftStr;
				}
			} 
			if(bottom > wrapperHeight) {
				orientation = bottomStr + '-' + preferedAlignment + 'Aligned';
				if(left > wrapperWidth) {
					orientation = bottomStr + '-' + rightStr;
				}
				if(right > wrapperWidth) {
					orientation = bottomStr + '-' + leftStr;
				} 
			}
			
			return orientation;
		} /* end decideOrientation() */
	} /* end $.fn.overlay */
	
	

	/* JAMES: Json autocomplete made extremely simple
	 * @author: sebastien rannou - http://www.aimxhaisse.com *
	 * Modified based on Revision: 1.0.0 beta http://plugins.jquery.com/project/james
	 */

	$.fn.james = function (url_to_call, options) {
	    var that = jQuery(this),
	        results_set = [],
	        current_hovered_rank = 0,
	        keyEvents = [
	            {keycode: 38, action: function () { keyEventKeyUp(); }},
	            {keycode: 40, action: function () { keyEventKeyDown(); }},
	            {keycode: 13, action: function () { keyEventEnter(); }},
	            {keycode: 27, action: function () { keyEventEsc(); }}
	        ],
	        ul_element = false,
	    	o = jQuery.extend({
	        onKeystroke:    function (data) {
	            return data;
	        },
	        onSelect:       function (dom_value, json_obj) {
	            that.attr("value", results_set[current_hovered_rank].text);
	        },
	        beforeSubmit:   function () {
	            return;
	        }, //added by cchong
	        keydelay:       300,
	        minlength:      3,
	        method:         "get",
	        varname:        "input_content",
	        varprefix:        "", //added by cchong
	        varpostfix:        "", //added by cchong
	        params:         ""
	    },  options || {});
	    var mouseDownOnSelect= false; //cchong
	    /*
	     * This method performs DOM initialization
	     * Creates a UL with an Unique ID and push it to DOM
	     * It's called only once
	     */
	    (function initDOM() {
	        var ul_id = false;
	        var ul_node = document.createElement("ul");

	        // Performs generation of an unique ID
	        var genUniqueId = function () {
	            var result = "ul_james_" + Math.round(Math.random() * 424242);

	            if (jQuery("#" + result).length > 0)
	            {
	                result = genUniqueId();
	            }
	            return result;
	        };

	        ul_id = genUniqueId();

	        jQuery(ul_node).attr("id", ul_id).addClass("ul_james");
	        that.after(ul_node);
	        // Creating a shortcut
	        ul_element = jQuery("#" + ul_id);
	        ul_element.hide();
	        
	        //add mouseDownOnSelect for onblur event
	        ul_element.mousedown(function() {
				mouseDownOnSelect = true;
			}).mouseup(function() {
				mouseDownOnSelect = false;
			});
	    })();
	    
	    /*
		 * This method performs CSS initialization
	     * It sets position's <ul> (especially for IE6)
	     * And sets result's width to input's width
	     * Because offset can be changed, it's called each time
	     * the dom is modified
	     */
	    var initCSS = function initCSS() {
	        var input_offset = that.offset();

	        ul_element.css({
	                        top:        input_offset.top + that.outerHeight(),
	                        width:      that.outerWidth(),
	                        left:       input_offset.left,
	                        position:   "absolute",
	                        zIndex: 	99999999 //added cchong
	                        });
	    }
	    
	    /*
	     * This is used to avoid form to be submit
	     * when the user press Enter to make his choice
	     * @TODO: When user has already made his choice, submit it
	     */
	    that.keydown(function (event) {
	        if (event.keyCode === 13)
	        {
	            return false;
	        }
	    });
	    
	    //that.blur added by cchong
	    that.blur(function() {   
			if (!mouseDownOnSelect) {
				cleanResults();
			}		  
	    });
	    
	    /*
	     * This method performs Keyboard Events
	     * @TODO: Build actions for more key events (CTRL? ALT?)
	     * or recognize ASCII codes?
	     */
	    //Timer's ID of next AJAX call
	    var keyevent_current_timer = false;

	    that.keyup(function(event) {
	        var is_specific_action = false;
	        // Check if a specific action is linked to the keycode
	        for (var i = 0; keyEvents[i]; i++)
	        {
	            if (event.keyCode === keyEvents[i].keycode)
	            {
	                is_specific_action = true;
	                keyEvents[i].action();
	                break;
	            }
	        }
	        // If it's not a specific action
	        if (is_specific_action === false)
	        {
	            // Unset last timeout if it was defined
	            if (keyevent_current_timer !== false)
	            {
	                window.clearTimeout(keyevent_current_timer);
	                keyevent_current_timer = false;
	            }
	            // Set a now timeout with an AJAX call inside
	            keyevent_current_timer = window.setTimeout(function () { 
	                ajaxUpdate();
	            }, o.keydelay);
	        }
		});
	    
	    /*
	     * This method performs AJAX calls
	     */
	    var ajaxUpdate = function () {
	    	o.beforeSubmit();//cchong
	        var value_to_send = jQuery.trim(that.attr("value")).toLowerCase(); //modified by cchong
	        // Check length of input's value
	        if (value_to_send.length > 0 &&
	            (o.minlength === false ||
	            value_to_send.length >= o.minlength))
	        {
	            $.ajax({
	                type:       o.method,
	                // @TODO: Would be great if params could be an object
	                data:       o.varname + "=" + o.varprefix + value_to_send + o.varpostfix + "&" + o.params,
	                url:        url_to_call,
	                dataType:   "json",
	                success:    function (data) {
	                    var arr = o.onKeystroke(data);
	                    results_set = [];
	                    current_hovered = 0;
	                    for (var i in arr)
	                    {
	                        if (arr[i] !== null)
	                        {
	                            if (typeof(arr[i].json) === "undefined")
	                            {
	                                results_set.push({text: arr[i], json: {}});
	                            }
	                            else
	                            {
	                                results_set
	                                .push({text: arr[i].text, json: arr[i].json});
	                            }
	                        }
	                    }
	                    updateDom();
	                }
	            });
	        }
	        else
	        {
	            cleanResults();
	        }
	    }
	    
	    /*
	     * This method performs the display of the results set
	     * Basically called when an event has been made
	     */
	    var updateDom = function() {
	    	jQuery(ul_element).empty();
	    	var is_empty = true;

	        initCSS();
	        for (var i in results_set)
	        {
	            if (results_set[i] !== null)
	            {
	                var li_elem = document.createElement("li");
	                jQuery(li_elem).addClass("li_james");
	                if(i%2==1){
	                	jQuery(li_elem).addClass("li_james_odd");
	                }
	                if (i == (current_hovered_rank % results_set.length))
	                {
	                    jQuery(li_elem).addClass("li_james_hovered");
	                }
	                jQuery(li_elem).append(results_set[i].text);
	                jQuery(ul_element).append(li_elem);
	                bind_elem_mouse_hover(li_elem, i);
	                is_empty = false;
	            }
	        }
	        if (is_empty)
	        {
	            jQuery(ul_element).hide();
	        }
	        else
	        {
	            jQuery(ul_element).show();
	        }
	    }
	    
	    /*
	     * This method performs the ability to
	     * select a result with mouse
	     */
	    var bind_elem_mouse_hover = function (elem, i) {
		   jQuery(elem).hover(function() {
	            jQuery(ul_element)
	            .find(".li_james_hovered")
	            .removeClass("li_james_hovered");
	            jQuery(elem).addClass("li_james_hovered");
	            current_hovered_rank = i;
		    }, function() {
	            jQuery(elem).removeClass("li_james_hovered");
	            current_hovered_rank = 0;
		    });
	       jQuery(elem).click(function() {
	 		  keyEventEnter();
	         });
	    }
	    
	    /*
	     * This method clears results in DOM & JS
	     */
	    var cleanResults = function () {
	        jQuery(ul_element).empty();
	        jQuery(ul_element).hide();
	        results_set = [];
	        current_hovered_rank = 0;
	    }
	    
	    /*
	     * Key event actions
	     */
	    
	    // Moving up into results set
	    var keyEventKeyUp = function () {
	        if (current_hovered_rank > 0)
	        {
	            current_hovered_rank--;
	        }
	        else if (results_set.length)
	        {
	                current_hovered_rank = results_set.length - 1;
	        }
	        updateDom();
	    }
	    
	    // Moving down into resuls set
	    var keyEventKeyDown = function () {
	        if (current_hovered_rank < (results_set.length - 1))
	        {
	            current_hovered_rank++;
	        }
	        else
	        {
	            current_hovered_rank = 0;
	        }
	        updateDom();
	    }
	    
	    // Selecting a set (onSelect function is called there)
	    var keyEventEnter = function () {
	        if (results_set.length > 0)
	        {
	           that.attr("value",
	                o.onSelect(results_set[current_hovered_rank].text,
	                           results_set[current_hovered_rank].json));
	        }
	        cleanResults();
	    }
	    
	    // Removing results set
	    var keyEventEsc = function () {
	        that.attr("value", "");
	        cleanResults();
	    }
	};
	/* End JAMES: Json autocomplete made extremely simple*/
	
	
	/**
	 * A simple querystring parser.
	 * Example usage: var q = $.parseQuery(); q.fooreturns  "bar" if query contains "?foo=bar"; multiple values are added to an array. 
	 * Values are unescaped by default and plus signs replaced with spaces, or an alternate processing function can be passed in the params object .
	 * http://actingthemaggot.com/jquery
	 *
	 * Copyright (c) 2008 Michael Manning (http://actingthemaggot.com)
	 * Dual licensed under the MIT (MIT-LICENSE.txt)
	 * and GPL (GPL-LICENSE.txt) licenses.
	 **/
	jQuery.parseQuery = function(qs,options) {
		var q = (typeof qs === 'string'?qs:window.location.search), o = {'f':function(v){return unescape(v).replace(/\+/g,' ');}}, options = (typeof qs === 'object' && typeof options === 'undefined')?qs:options, o = jQuery.extend({}, o, options), params = {};
		jQuery.each(q.match(/^\??(.*)$/)[1].split('&'),function(i,p){
			p = p.split('=');
			p[1] = o.f(p[1]);
			params[p[0]] = params[p[0]]?((params[p[0]] instanceof Array)?(params[p[0]].push(p[1]),params[p[0]]):[params[p[0]],p[1]]):p[1];
		});
		return params;
	}

})(jQuery);

/* ======+====== Default settings ======+====== */
;(function($){
	/* tabs defaults */
	$.extend($.ui.tabs, {
		defaults: {
			ajaxOptions: null,
			cache: true,
			cookie: null,
			collapsible: false,
			disabled: [],
			event: 'click',
			idPrefix: 'ui-tabs-',
			panelTemplate: '<div></div>',
			spinner: '',
			tabTemplate: '<li><a href="#{href}"><span>#{label}</span></a></li>'
		}
	});
})(jQuery);

/* ======+====== jQuery Debug Helper Functions ======+====== */

function showRequest(formData, jqForm, options) { 
    alert('About to submit: \n\n' + $.param(formData)); 
    return true; 
} 
function showResponse(responseText, statusText)  { 
    alert('status: ' + statusText + '\n\nresponseText: \n' + responseText); 
} 		
					
/* ======+====== Default Initializations ======+====== */

(function($) {
	$(function() {
		/* remove all non-js fallback elements */
		$('.nonjsFallback').remove();
		/* Tab initialization */
		$('ul.tabs li a').removeAttr('target');
	});
})(jQuery);		



/* ======+====== offers ======+====== */
(function($){
	$(function() {
		var offerPageTypes = ["BrowseCategory", "BrowseEvent", "BrowseGenre", "BrowseGenreLeaf", "BrowseTicketDetail", "HomePage", "PostPurchasePage", "SearchResult"];
		if(typeof(pageType) !== 'undefined'){
			$.each(offerPageTypes, function(i){
				if(pageType==offerPageTypes[i]){
					  $.ajax({
						    type: "POST",
							//url: "http://d-sfa-515969.corp.ebay.com/debug/offer/offer.asp",
							url: "/content/getPromoContent",
							data:"pageType="+pageType,	 
						    dataType: "html",
						    success: processPromoContent,
						    error: function(){ }
					    });
				}
			});
		}

	  function processPromoContent(response) { 			 
		// set up the possible non-offer responses from backend    
		var noOfferResponse = ["<blocks>","<blocks/>","No Promo Content"];  
		var thereIsAnOffer = true;
		// determine if there is an actual offer based on the response from back end
		$.each(noOfferResponse,function(i) { thereIsAnOffer = response.indexOf(noOfferResponse[i])>=0?false:thereIsAnOffer ; })
		// put the html response in the header div
		if(thereIsAnOffer) {   
			$("#offer_content").html( response )  
		} 
		//else { $("#offer_container").html(" this was the NoPromo response: " + response )  }
	  }	    
	});
})(jQuery);
 

