// Functionality for showing the popup windows off of the action bar
function getposOffset(overlay, offsettype)
{
	var totaloffset=(offsettype=="left")? overlay.offsetLeft : overlay.offsetTop;
	var parentEl=overlay.offsetParent;
	while (parentEl!=null /*&& parentEl.getStyle('position') != 'relative'*/)
	{
		totaloffset=(offsettype=="left")? totaloffset+parentEl.offsetLeft : totaloffset+parentEl.offsetTop;
		parentEl=parentEl.offsetParent;
	}
	return totaloffset;
}

var ACTION_BAR =
{
  //-----------------------------------------------------------------------------
  // Desc:        Function to delete an item from the actionBar
  deleteItem: function(booth_id, item_id, item_name)
  {
      // If we're given an item, call the new_item_remove_xhr AJAX method to remove it from our items table
      if (item_id > -1)
      {
        titleEl = $j('#itemlist ul#grid_block_item_' + item_id + ' .itemTitle');
        item_title = (titleEl.text() != '' ? titleEl.text() : "this nameless item");
        confirmResult = confirm("You really wanna delete " + item_title + "?");
        if(confirmResult)
        {   
          showWaitPanel('#boothItems');
        
          new Ajax.Updater(
              'itemlist',
              '/booths/' + booth_id + '/items/' + item_id,
              { 
                asynchronous:true, 
                evalScripts:true, 
                method:'delete',
                onComplete: function() { 
                  hideWaitPanel('#boothItems'); 
                }
              });
        }
      }
  },
  
  //-----------------------------------------------------------------------------
  // Desc:        Function to delete an item from the actionBar
  duplicateItem: function(booth_id, item_id)
  {
      // If we're given an item, call the new_item_remove_xhr AJAX method to remove it from our items table
      if (item_id > -1)
      {
        showWaitPanel('#boothItems');
        
        new Ajax.Updater(
            'itemlist',
            '/booths/' + booth_id + '/items/' + item_id + '/duplicate',
            { 
              asynchronous:true, 
              evalScripts:true, 
              method:'post',
              onComplete: function() { 
                hideWaitPanel('#boothItems'); 
              }
            });
      }
  }

  //-----------------------------------------------------------------------------
  // Desc:        Function to make an AJAX request that returns a JSON object used to populate 
  //              the new item form
  // Parameters:  event     Dunno
  /*editItem: function(booth_id, item_id)
  {
    // If we have an item and were given a function to call to populate the new item form with
  	if (item_id > -1)
    {
        showWaitPanel('#itemlist');
        
        new Ajax.Updater(
            'newItemForm',
            '/booths/' + booth_id + '/items/' + item_id + '/edit',
            { 
              // parameters: $H({ item_id: this.item_id }), 
              asynchronous:true, 
              evalScripts:true,
              method:'get',
              onSuccess: function()
              {
    			      closeAllActionPanels();
              },
              onComplete: function()
              {
                StateManager.setState("items/" + item_id + "/main_form");
                displayEditItemWindow();
                captureFormStartingState();
                hideWaitPanel('#itemlist');
              }
            });            
                		  
	   }
  }*/
};

//-----------------------------------------------------------------------------
// open action_layer's action_panel by showing it and hiding the action_bar
function openActionPanel(actionLayerElID)
{
	closeAllActionPanels();
   
  var actionLayerEl = $j('#' + actionLayerElID);

	actionLayerEl.find('.action_panel').addClass('single_show');
	actionLayerEl.find('.action_bar').addClass('panel_hide');
}

//-----------------------------------------------------------------------------
// seeks out action_panels that are shown (using .single_show) and closes them
function closeAllActionPanels()
{
	$j('.action_panel').filter('.single_show').each(
    function() 
    { 
      closeActionPanel($j(this).parents('.action_layer').attr('id')); 
    });
}

//-----------------------------------------------------------------------------
// close action_layer's action_panel by hiding it and allowing the action_bar to be shown
function closeActionPanel(actionLayerElID)
{
  var actionLayerEl = $j('#' + actionLayerElID);
  
	actionLayerEl.find('.action_bar').removeClass('panel_hide');
	actionLayerEl.find('.action_panel').removeClass('single_show');
}



//-----------------------------------------------------------------------------
// Called after an item has been successfully added without killing new item form
function addItemAddedSuccessfully(oldItemName)
{
	$j("#NewItemInfoMessageContainer span#NewItemInfoMessage").text(oldItemName + ' added or saved successfully!');
	$j("#NewItemInfoMessageContainer").show();
	$j("#NewItemInfoMessageContainer span#NewItemInfoMessage").show();

  // Other maintenance to clean up the form and get it back to its original state.
	StateManager.setState("items/" + $j('#stateReturnToID').val() + "/main_form");
  //captureFormStartingState();
  //$('item_title').focus();
}

//-----------------------------------------------------------------------------
function adjustTextarea(textarea, collapsed) {
  var lines = textarea.value.split("\n");
  var count = lines.length;
  lines.each(function(line) { count += parseInt(line.length / 70); });

  var rows = parseInt(collapsed / 20);

  if (count > rows) {
    $j('#wysiwyg_link').fadeIn('fast');
  }

  if (count <= rows) {
    $j('#wysiwyg_link').fadeOut('fast');
  }
};

//-----------------------------------------------------------------------------
// Save the serialized state of the form into a global variable that we'll check against
// if the form is canceled to see if there were any changes.
function captureFormStartingState()
{
  var itemForm = $('item_fields_form');
  if (itemForm)
  {
    // Record values on form when it's opened so we know whether we're going to need to confirm the user's possible cancelation  
    gStartingForm = itemForm.serialize();
  }
  else
  {
    gStartingForm = null;
  }
}

//-----------------------------------------------------------------------------
function hideShowBoothImageGalleryHintArea()
{
	$j('#NewItemInfoMessageContainer').slideToggle("normal", function()
	{
		set_json_subcookie('_it_se', 'sbigha', $j(this).is(":visible"));
	});
}

//-----------------------------------------------------------------------------
// Don't allow naughty keys or decimals in price fields
function restrictPriceInput(e, regExp)
{
	var keyCode = !e.charCode ? e.which : e.charCode;
	var key = String.fromCharCode(keyCode);
	
	if (e.ctrlKey)
	{
		if (key == 'v')
		{	// Prevent pasting
			e.preventDefault();
		}
	}
	else if (keyCode != 0 && !regExp.test(key))	// Not a digit or backspace
	{																													// keyCode 0 is special keys like delete, home, arrows, etc.
		e.preventDefault();
	}
}

//-----------------------------------------------------------------------------
function showShippingFields(shippingOption, shippingFixedArr, shippingCalcArr)
{
  if (shippingOption == shippingFixedArr[0]) {
    $j('#' + shippingFixedArr[1]).show();
    $j('#' + shippingCalcArr[1]).hide();
  }
  else if(shippingOption == shippingCalcArr[0]) {
    $j('#' + shippingCalcArr[1]).show();
    $j('#' + shippingFixedArr[1]).hide();
  }
  else {
    $j('#' + shippingFixedArr[1]).hide();
    $j('#' + shippingCalcArr[1]).hide();
  }
    
}

//-----------------------------------------------------------------------------
function beforeEditItemFormSubmit(text)
{
  document.location.hash = "default";
  $j('a.tooltip').unbind();
  $j('#addItemFooter .bottomButton').attr('disabled', 'disabled'); 
	showItemFormWait(text);
}

//-----------------------------------------------------------------------------
function afterEditItemFormSubmit()
{
	$j('#addItemFooter .bottomButton').attr('disabled', 'enabled'); 
	hideItemFormWait();
}

//-----------------------------------------------------------------------------
function categoryBrowseClicked(){
	$j('#categoryBrowser').slideToggle('slow');
}

//-----------------------------------------------------------------------------
// Give the user some life affirming statistics on how well they're doing posting
function getPostingTimeString(timeItemCreatedString, bestTimeSeconds, yourAverageTimeSeconds)
{
  var returnStr = "";
  try {
	  //var itemStartEditTime = Date.parseDate(timeItemCreatedString, "Y-m-d H:i:s");
	  //var now = new Date();
	  //var diff = now.getTime() - itemStartEditTime.getTime();
	  //diff += 7*60*60*1000; // move forward seven hours, time zone diff between us and slicehost
	  //var oneSecond = 1000;
    //var totalSeconds = diff / oneSecond;
    //var todaysFastest = (!bestTimeSeconds || (totalSeconds < bestTimeSeconds) ? totalSeconds : bestTimeSeconds);
    //var yourAverage = (!yourAverageTimeSeconds ? totalSeconds : yourAverageTimeSeconds);
     
    //if(totalSeconds < bestTimeSeconds) {
    //  returnStr += "<blink>Congratulations!  You are the day's fastest item poster so far!</blink><br />"
    //}
    //returnStr += "Time to create this item: <strong>" + Math.floor(totalSeconds/60) + " minutes " + Math.floor(totalSeconds%60) + " seconds</strong><br />";
    if(yourAverageTimeSeconds) {
      yourAverage = yourAverageTimeSeconds;
      returnStr += "Your average posting time: <strong>" + Math.floor(yourAverage/60) + " minutes " + Math.floor(yourAverage%60) + " seconds</strong><br />";
      if(Math.floor(yourAverage/60) <= 3) { 
        returnStr += "Snappy!";
      }
      else if(Math.floor(yourAverage/60) <= 5) {
        returnStr += "Pretty quick!";
      }
    }
    else {
      returnStr += "Please wait..."
    }
    // returnStr += "Today's fastest: <strong>" + (todaysFastest/oneMinute) + ":" + (todaysFastest%oneMinute) + "</strong>";
  }
  catch(err) {
    returnStr = "Saving item...";
  } 
  return returnStr;
}

//-----------------------------------------------------------------------------
function showItemFormWait(text)
{
  passText = (text ? text : "Please Wait...");
  $j('#item_shipping_id').hide();
  showWaitPanel('#modalItemWindow', passText, 3); // 3 is the hack width adding... the form is somehow 3 pixels wider than its .outerWidth() call purports
}

//-----------------------------------------------------------------------------
function hideItemFormWait()
{
  $j('#item_shipping_id').show();
  hideWaitPanel('#modalItemWindow');
}
	
//-----------------------------------------------------------------------------
function quantityBoxChecked(jqCheckboxElement)
{
  if(jqCheckboxElement && jqCheckboxElement.get(0) && !jqCheckboxElement.get(0).checked) {
    $j('input#item_quantity').val(1);
  }
}

//-----------------------------------------------------------------------------
function bindNIFMovingElements() {
	$j('fieldset#data input.browse, #edit_item_container input.browse').bind('click',function(){
		categoryBrowseClicked();
	});

	$j('#item_shipping_id').bind('change',function(){
		var sp = $j('#ShippingPrice');
		(this.selectedIndex===1)?sp.show():sp.hide();
	});
	$j('#show_quantity').bind('click',function(){ //using vis instead of show so floated fieldsets don't resize and jump
		$j('#QuantitySpanID').css('visibility',(this.checked===true)?'visible':'hidden');
	});
	$j('#item_freebie').bind('click',function(){
		var p = $j('#item_price');
		(this.checked===true)?$j(p).attr('disabled','disabled'):$j(p).attr('disabled','');
	});
}

//-----------------------------------------------------------------------------
// All used by the modal new item form 
function bindStaticModalFunctions(){
	$j('h4 a').bind('click',function(){
		var that = this;
		$j('#advancedOptions').slideFadeToggle(function(){
			$j(that).css('background-position',$j(this).is(':visible')?'0 -14px':'0 -14px');
			set_json_subcookie('_it_se', 'siao', $j(this).is(':visible'));
		});
		return false;
	});


	bindNIFMovingElements();
	bindImageElements();
	bindFileUploadInputs();
	
	$j('#modalCancel').bind('click',function(){
			$j('#modalButtons').hide();
			$j('#modalCancelConfirm').show();
			return false;
		});	    
	$j('#modalNotCancel').bind('click',function(){
			$j('#modalButtons').show();
			$j('#modalCancelConfirm').hide();
			return false;
		});
		
	$j('#modalItemWindow').jqmAddClose($j('#modalAbsCancel'));
}


//-----------------------------------------------------------------------------
function boothGalleryImageParams()
{
	var imgIds = '';
	$j("div#modalGallery ul#pictureslots li img").each(function(){
		if($j(this).attr('src').indexOf('button_upload_picture_85x70.jpg')===-1){
			imgIds+= $j(this).parent()[0].id + "=" + $j(this).attr('id') + "&";
		}
	});
	return imgIds;
}

//-----------------------------------------------------------------------------
function closeItemGuessWindow() 
{
 $j('#itemGrabberContainerDiv').parent().hide().html('Looking up items similar to yours...'); 
}

//-----------------------------------------------------------------------------
function respondToTraitJson(eval_json, category_id) {
  if(eval_json) {
  	$j('#full_category_name_for_traits').html(eval_json["full_category_name"]);
	}

  if(!eval_json || (eval_json["has_traits"] == false)) {
    traitNoneFound();
  } 
  else if(eval_json["has_traits"]) {
    traitHideAll();
    if(elementExists("traitShowTraits")) {
			$j('#traitLookup').show();
			$j.ajax({ type: "POST", url: '/categories/populate_traits',
				data: "id=" + category_id,
				complete: function(response) {
					$j('#traitLookup').hide();
					$j('#trait_container').html(response.responseText);
				}
			}); // ajax request
		}
		else {
			$j('.traitShowElement').show();
			trait_profile_list = eval_json["trait_profiles"];

			// Check if there are trait profiles in this category to populate our select input with...
			if(trait_profile_list && trait_profile_list.length > 0) {
				$j('#traitShowProfile').show();
				$j('#trait_profile_id').find('option').remove(); // Remove any old options from list, then add our new options
				for(i=0;i<trait_profile_list.length;i++) {
					$j('#trait_profile_id').addOption(trait_profile_list[i][0], trait_profile_list[i][1]);
				}
				$j('#trait_profile_id').attr('selectedIndex', 0); // (-1);
			}
		}
  }
}

//-----------------------------------------------------------------------------
function categoryUpdateTraits(category_id, the_url) {
  if(!category_id) { 
    traitNoneFound();
    return;
  }
  
  $j.ajax({
    type: "POST",
    url: the_url,
    data: "id=" + category_id,
    beforeSend: function() {
      traitHideAll();
      $j('#traitLookup').show();
    },
    success: function(json) {
      eval_json = eval(json);
      respondToTraitJson(eval_json, category_id);
    },
    complete: function() {
      $j('#traitLookup').hide();
    }
  }); // ajax request
}  // change 

//-----------------------------------------------------------------------------
// Hide all of the li's that are used to give trait information
function traitHideAll() {
  $j('#traitInitialShowElement, #traitShowTraits, .traitShowElement, #traitShowProfile, #traitNoneFound, #traitLookup').hide();
 }

//-----------------------------------------------------------------------------
function traitNoneFound() {
  traitHideAll();
  $j('#traitNoneFound').show();
}

//-----------------------------------------------------------------------------
function applyTraitComplete(response) {
	eval_json = eval(response);
	$j('#apply_profile_spinner').hide(); 
	$j('#traitShowProfile').html(eval_json["message"]);
	if(eval_json["count"]) {
	  $j('#traitCount').html(eval_json["count"] + " traits");
	}
}


function toolboxRequestComplete(msg) {
  $j('#toolbox_submit').hide();
  $j('#toolboxList').hide();
  $j('#toolboxMessage').show();
  $j('#toolboxMessage').html(msg);
}

function boothFavoriteResponse(response) {
  $j('#toolbox_submit').hide();
  var json = jQuery.evalJSON(response.responseText);
  if(json && json['is_valid'] == 'true') {
    if(json['favorite_set'] == 'true') {
      $j('#favorite').html('Unfavorite').attr('class',  'faveSelect');
    } else {
      $j('#favorite').html('Favorite').attr('class',  'faveUnselect');
    }
  } else if(json) {
    $j('#favorite').unbind();
    $j('#favorite').replaceWith(json['message']);
  }
}

function boothFollowHide() {
	set_json_subcookie('_bo_se', 'hd_flw', true);
	$j('#booth_favorite').hide('fast');
}

// ----------------------------------------------------------------------------
function addToCart(url, draggable_el, true_draggable)
{
	var item_id = prepareToUpdateCart(draggable_el);
	
	jQuery("div#cart ul").load(url, { item : item_id }, function()
	{
		updateCart();
		
		if(true_draggable) {
		  var draggable = draggable_el;
		  draggable.draggable("disable");
		  setItemIcon(item_id, true);
		}
	});

  $j('#checkout_button').removeClass('unselect').addClass('select');
}

// ----------------------------------------------------------------------------
function removeFromCart(url, draggable_ui)
{
	// Kill the cloned helper
	$j(draggable_ui.helper).remove();

	draggable_el = draggable_ui.draggable;
	var item_id = prepareToUpdateCart(draggable_el);

	jQuery("div#cart ul").load(url, { item : item_id }, function()
	{
		updateCart();
		
	});
}

// ----------------------------------------------------------------------------
// Sets the given item id in a booth display list to show an icon indicating 
// whether it is in the cart or not
function setItemIcon(item_id, in_cart)
{
	var image_src = in_cart ? '/images/header/cartIcon_20x20.gif' : '/images/icon-status2.png';
	var image_alt = in_cart ? 'Item is in your cart' : 'Item is for sale';
	$j('#grid_block_item_' + item_id + ' > li.itemIcon img').attr('src', image_src).attr('alt',image_alt);
}

// ----------------------------------------------------------------------------
// Removes all items from the cart element and displays a loading message, returning
// the id of the item to change, given the draggable element.
function prepareToUpdateCart(draggable_el)
{
	jQuery("div#cart ul").addClass('loading').children('li').remove();

	return extractDigitFromString(jQuery(draggable_el).get(0) ?
		jQuery(draggable_el).attr('id') : 
		jQuery(draggable_el.element).attr('id'));
}

// ----------------------------------------------------------------------------
// Update the cart display and text to correctly reflect the current items in it.
function updateCart()
{
	var num_items = jQuery("div#cart ul > li[class!='emptycart']").size();
	jQuery('p#lootbot span').text(num_items + (num_items === 1 ? " item" : " items"));
	
	jQuery("div#cart ul").removeClass('loading');
	if (num_items === 0)
	{
		jQuery("div#cart ul").removeClass('hasloot');
	}
	else
	{
		jQuery("div#cart ul").addClass('hasloot');
	}
	
	jQuery("div#cart ul > li a img").draggable("destroy").each(function()
	{
		jQuery(this).draggable(
		{
			helper: 'clone',
			opacity: 0.7,
			appendTo: 'body'
		});
	});
}



/* This was generated through the following:
	<% @categories = Category.find(:all)
	# Possible optimization here is to just check if the parent_id of the category is whatever nil corresponds to (0, I believe),
	# and only add it to the parent list if so
	all_parent_categories = @categories.inject([]) do |list,cat| 
		parent_cat = (cat.ancestors[0] ? cat.ancestors[0] : cat)
		list << parent_cat
	end
	all_parent_categories.uniq!		
	unique_sorted_categories = get_sorted_categories(all_parent_categories,false) %>
	<h3>Unique categories: </h3>
	<% unique_sorted_categories.each do |category| -%>
	<% if category -%> 
		<%= %{["#{category.name}","#{category.id}"],<br />} -%>
		<% end -%>               	 
    
<% unique_sorted_categories.each do |category|
	if category -%>
		<% child_categories = Category.find(:all, :conditions => { :parent_id => category } )
		child_categories.sort! { |a,b| a.name <=> b.name }
		child_categories.collect! { |category| %{["#{category.name}","#{category.id.to_s}"]} } -%>
		<%= "[" + child_categories.join(",") + "]," -%>
		<%= "<br />" %>
	  <% end
end  -%>
*/

/* categories and subcats for the modal dropdowns */
var parentCategories = [["Antiques","20081"],
      ["Art","550"],
      ["Baby","2984"],
      ["Books","267"],
      ["Business & Industrial","12576"],
      ["Cameras & Photo","625"],
      ["Cars & Trucks","6001"],
      ["Cell Phones & PDAs","15032"],
      ["Clothing, Shoes & Accessories","11450"],
      ["Coins & Paper Money","11116"],
      ["Collectibles","1"],
      ["Computers & Networking","58058"],
      ["Crafts","14339"],
      ["DVDs & Movies","11232"],
      ["Dolls & Bears","237"],
      ["Electronics","293"],
      ["Entertainment Memorabilia","45100"],
      ["Everything Else","99"],
      ["Gift Certificates","31411"],
      ["Health & Beauty","26395"],
      ["Home & Garden","11700"],
      ["Jewelry & Watches","281"],
      ["Motorcycles","6024"],
      ["Music","11233"],
      ["Musical Instruments","619"],
      ["Other Vehicles & Trailers","6038"],
      ["Pottery & Glass","870"],
      ["Powersports","66466"],
      ["Real Estate","10542"],
      ["Specialty Services","316"],
      ["Sporting Goods","382"],
      ["Sports Mem, Cards & Fan Shop","64482"],
      ["Stamps","260"],
      ["Tickets","1305"],
      ["Toys & Hobbies","220"],
      ["Travel","3252"],
      ["Vehicle Parts & Accessories","6028"],
      ["Video Games","1249"]];

var childCategories = [
  [["Antiquities (Classical, Amer.)","37903"],["Architectural & Garden","4707"],["Asian Antiques","20082"],["Books, Manuscripts","2195"],["Decorative Arts","20086"],["Ethnographic","2207"],["Furniture","20091"],["Maps, Atlases, Globes","37958"],["Maritime","37965"],["Musical Instruments","37974"],["Other Antiques","12"],["Periods, Styles","100927"],["Primitives","1217"],["Reproduction Antiques","22608"],["Rugs, Carpets","37978"],["Science & Medicine","20094"],["Silver","20096"],["Textiles, Linens","2218"]],
  [["Digital Art","20118"],["Drawings","20119"],["Folk Art","357"],["Mixed Media","20122"],["Other Art","4174"],["Paintings","20125"],["Photographic Images","66465"],["Posters","28009"],["Prints","20140"],["Sculpture, Carvings","553"],["Self-Representing ACEOs","151719"],["Self-Representing Artists","20158"],["Wholesale Lots","52524"]],
  [["Baby Gear","100223"],["Baby Safety & Health","20433"],["Baby Wholesale Lots","48757"],["Bathing & Grooming","20394"],["Car Safety Seats","66692"],["Diapering","45455"],["Feeding","20400"],["Keepsakes & Baby Announcements","117388"],["Nursery Bedding","20416"],["Nursery Decor","66697"],["Nursery Furniture","20422"],["Other Baby Items","1261"],["Potty Training","37631"],["Strollers","66698"],["Toys","19068"]],
  [["Accessories","45110"],["Antiquarian & Collectible","29223"],["Audiobooks","29792"],["Catalogs","118254"],["Children's Books","279"],["Cookbooks","11104"],["Fiction Books","377"],["Magazine Back Issues","280"],["Magazine Subscriptions","29253"],["Nonfiction Books","378"],["Other","268"],["Textbooks, Education","2228"],["Wholesale, Bulk Lots","29399"]],
  [["Agriculture & Forestry","11748"],["Construction","11765"],["Food Service & Retail","11874"],["Healthcare, Lab & Life Science","11815"],["Industrial Electrical & Test","92074"],["Industrial Supply, MRO","1266"],["Manufacturing & Metalworking","11804"],["Office, Printing & Shipping","25298"],["Other Industries","26255"]],
  [["Bags, Cases & Straps","107894"],["Binoculars & Telescopes","28179"],["Camcorder Accessories","11723"],["Camcorders","23781"],["Digital Camera Accessories","3327"],["Digital Cameras","29997"],["Film","4201"],["Film Camera Accessories","43478"],["Film Cameras","15230"],["Film Processing & Darkroom","15224"],["Flashes & Accessories","64353"],["Lenses & Filters","78997"],["Lighting & Studio Equipment","30078"],["Manuals, Guides & Books","4684"],["Photo Albums & Archive Items","29951"],["Printers, Scanners & Supplies","30021"],["Professional Video Equipment","21162"],["Projection Equipment","15250"],["Stock Photography & Footage","21198"],["Tripods, Monopods","30090"],["Vintage","3326"],["Wholesale Lots","45086"]],
  [["AMC","5357"],["Acura","5330"],["Alfa Romeo","5340"],["Aston Martin","157054"],["Audi","6002"],["Austin","6126"],["Austin Healey","6023"],["BMW","6006"],["Bentley","157059"],["Buick","6135"],["Cadillac","5347"],["Chevrolet","5346"],["Chrysler","5351"],["Citroen","6183"],["Cord","6185"],["Daewoo","157064"],["Datsun","6186"],["DeLorean","31830"],["DeSoto","6190"],["Dodge","6191"],["Eagle","6214"],["Edsel","6216"],["Ferrari","6211"],["Fiat","6218"],["Ford","6010"],["GMC","6243"],["Geo","6242"],["Honda","6252"],["Hummer","5342"],["Hyundai","6261"],["Infiniti","6263"],["International Harvester","31845"],["Isuzu","6266"],["Jaguar","6272"],["Jeep","6279"],["Kia","6287"],["Lamborghini","157067"],["Lancia","6292"],["Land Rover","6293"],["Lexus","6297"],["Lincoln","6302"],["Lotus","116480"],["MG","6308"],["Mazda","6310"],["Mercedes-Benz","6311"],["Mercury","5363"],["Mini","31860"],["Mitsubishi","6348"],["Nash","31863"],["Nissan","6371"],["Oldsmobile","6372"],["Opel","6390"],["Other Makes","6472"],["Packard","6389"],["Peugeot","6388"],["Plymouth","6376"],["Pontiac","6377"],["Porsche","6013"],["Renault","6385"],["Replica/Kit Makes","7251"],["Rolls-Royce","157071"],["Saab","6380"],["Saturn","6381"],["Scion","116483"],["Shelby","6465"],["Smart","157077"],["Studebaker","6466"],["Subaru","6452"],["Suzuki","6468"],["Toyota","6016"],["Triumph","6449"],["Volkswagen","6018"],["Volvo","6454"],["Willys","6470"]],
  [["Accessories, Parts","20336"],["Bluetooth Wireless Accessories","133225"],["Cell Phones","146487"],["PDAs & Pocket PCs","38331"],["Phone & SIM Cards","146492"],["Smartphones","32233"],["Wholesale & Large Lots","45065"]],
  [["Boys","11452"],["Dancewear & Dance Shoes","112425"],["Girls","11462"],["Infants & Toddlers","3082"],["Men's Clothing","1059"],["Men's Accessories","4250"],["Men's Shoes","63850"],["Uniforms","28015"],["Vintage","110"],["Wedding Apparel","3259"],["Wholesale, Large & Small Lots","41964"],["Women's Accessories, Handbags","4251"],["Women's Clothing","15724"],["Women's Shoes","63889"]],
  [["Bullion","39482"],["Coins: Ancient","4733"],["Coins: Canada","3377"],["Coins: US","253"],["Coins: World","256"],["Exonumia","3452"],["Paper Money: US","3412"],["Paper Money: World","3411"],["Publications & Supplies","83274"],["Scripophily","3444"]],
  [["Advertising","34"],["Animals","1335"],["Animation Art, Characters","13658"],["Arcade, Jukeboxes & Pinball","66502"],["Autographs","14429"],["Banks, Registers & Vending","66503"],["Barware","3265"],["Bottles & Insulators","29797"],["Breweriana, Beer","562"],["Casino","898"],["Clocks","397"],["Comics","63"],["Cultures, Ethnicities","3913"],["Decorative Collectibles","13777"],["Disneyana","137"],["Fantasy, Mythical & Magic","10860"],["Furniture, Appliances & Fans","39629"],["Historical Memorabilia","13877"],["Holiday, Seasonal","907"],["Housewares & Kitchenware","13905"],["Knives, Swords & Blades","1401"],["Lamps, Lighting","1404"],["Linens, Fabric & Textiles","940"],["Metalware","1430"],["Militaria","13956"],["Pens & Writing Instruments","966"],["Pez, Keychains, Promo Glasses","14005"],["Photographic Images","14277"],["Pinbacks, Nodders, Lunchboxes","39507"],["Postcards & Paper","124"],["Radio, Phonograph, TV, Phone","29832"],["Religions, Spirituality","1446"],["Rocks, Fossils, Minerals","3213"],["Science Fiction","152"],["Science, Medical","412"],["Tobacciana","593"],["Tools, Hardware & Locks","13849"],["Trading Cards","868"],["Transportation","417"],["Vanity, Perfume & Shaving","597"],["Vintage Sewing","113"],["Wholesale Lots","45058"]],
  [["Apple, Macintosh Computers","4599"],["Desktop & Laptop Accessories","31530"],["Desktop & Laptop Components","3667"],["Desktop PCs","3736"],["Drives, Controllers & Storage","165"],["Laptops, Notebooks","51148"],["Monitors & Projectors","3694"],["Networking","11176"],["Other Hardware & Services","58059"],["Printer Supplies & Accessories","11195"],["Printers","1245"],["Scanners","11205"],["Servers","11211"],["Software","18793"],["Technology Books","3516"],["Vintage Computing Products","11189"]],
  [["Basketry","134304"],["Bead Art","31723"],["Candle & Soap Making","28114"],["Ceramics, Pottery","28121"],["Crafts Wholesale Lots","45074"],["Crocheting","3094"],["Cross Stitch","3091"],["Decorative, Tole Painting","28126"],["Drawing","28106"],["Embroidery","28141"],["Fabric","28155"],["Fabric Embellishments","31727"],["Floral Crafts","16491"],["Framing & Matting","37573"],["General Art & Craft Supplies","28102"],["Glass Art Crafts","3100"],["Handcrafted Items","71183"],["Kids Crafts","116652"],["Knitting","3103"],["Lacemaking, Tatting","134590"],["Latch Rug Hooking","28147"],["Leathercraft","28131"],["Macrame","28151"],["Metalworking","41369"],["Mosaic","28134"],["Needlepoint","3104"],["Other Arts & Crafts","75576"],["Painting","28110"],["Paper Crafts","134593"],["Quilting","3111"],["Ribbon","83974"],["Rubber Stamping & Embossing","3122"],["Scrapbooking","11788"],["Sewing","3116"],["Shellcraft","3120"],["Spinning","36600"],["Upholstery","113354"],["Wall Decor, Tatouage","75575"],["Weaving","57739"],["Woodworking","3127"],["Yarn","36589"]],
  [["DVD, HD DVD & Blu-ray","617"],["Film","63821"],["Laserdisc","381"],["Other Formats","41676"],["UMD","132975"],["VHS","309"],["VHS Non-US (PAL)","1508"],["Wholesale Lots","31606"]],
  [["Bear Making Supplies","50253"],["Bears","386"],["Dollhouse Miniatures","1202"],["Dolls","238"],["Paper Dolls","2440"],["Wholesale Lots","52546"]],
  [["A/V Accessories & Cables","14961"],["Apple iPod, MP3 Players","15057"],["Batteries & Chargers","40971"],["Car Electronics","3270"],["DVD & Home Theater","32852"],["GPS Devices","34288"],["Gadgets & Other Electronics","14948"],["Home Audio","14969"],["MP3 Accessories","56169"],["Portable Audio/Video","15052"],["Radios: CB, Ham & Shortwave","1500"],["Satellite Radio","60204"],["Satellite, Cable TV","61383"],["Telephones & Pagers","3286"],["Televisions","11071"],["Vintage Electronics","14998"],["Wholesale Lots","61494"]],
  [["Autographs-Original","57"],["Autographs-Reprints","104412"],["Movie Memorabilia","196"],["Music Memorabilia","2329"],["Other Memorabilia","2312"],["Television Memorabilia","1424"],["Theater Memorabilia","2362"],["Video Game Memorabilia","45101"]],
  [["Advertising Opportunities","102333"],["Education & Learning","16706"],["Funeral & Cemetery","88739"],["Genealogy","20925"],["Gifts & Occasions","16086"],["Information Products","102480"],["Mature Audiences","319"],["Memberships","16709"],["Metaphysical","19266"],["Mystery Auctions","102534"],["Other","88433"],["Personal Security","102535"],["Religious Products & Supplies","102545"],["Reward Pts, Incentive Progs","102553"],["Test Auctions","14112"],["Weird Stuff","1466"],["eBay User Tools","20924"]],
  [],
  [["Bath & Body","11838"],["Coupons","82567"],["Dietary Supplements, Nutrition","19259"],["Fragrances","26396"],["Hair Care","11854"],["Hair Removal","31762"],["Health Care","67588"],["Makeup","31786"],["Massage","36447"],["Medical, Special Needs","11778"],["Nail","11871"],["Natural Therapies","67659"],["Oral Care","31769"],["Other Health & Beauty Items","1277"],["Over-the-Counter Medicine","75036"],["Skin Care","11863"],["Tanning Beds, Lamps","31775"],["Tattoos, Body Art","33914"],["Vision Care","31414"],["Weight Management","31817"],["Wholesale Lots","40965"]],
  [["Bath","20438"],["Bedding","20444"],["Building & Hardware","3187"],["Dining & Bar","71236"],["Electrical & Solar","20595"],["Food & Wine","14308"],["Furniture","3197"],["Gardening & Plants","2032"],["Heating, Cooling & Air","41986"],["Home Decor","10033"],["Home Security","41968"],["Kitchen","20625"],["Lamps, Lighting, Ceiling Fans","20697"],["Major Appliances","20710"],["Outdoor Power Equipment","29518"],["Patio & Grilling","20716"],["Pet Supplies","1281"],["Plumbing & Fixtures","20601"],["Pools & Spas","20727"],["Rugs & Carpets","20584"],["Tools","631"],["Vacuum Cleaners & Housekeeping","299"],["Wholesale Lots","31605"],["Window Treatments","63514"]],
  [["Body Jewelry","10968"],["Bracelets","10975"],["Charms & Charm Bracelets","3835"],["Children's Jewelry","84605"],["Designer Brands","11317"],["Earrings","10985"],["Ethnic, Tribal Jewelry","11312"],["Hair Jewelry","110620"],["Handcrafted, Artisan Jewelry","110633"],["Jewelry Boxes & Supplies","10321"],["Jewelry Sets","43209"],["Loose Beads","488"],["Loose Diamonds & Gemstones","491"],["Men's Jewelry","10290"],["Necklaces & Pendants","10994"],["Other Items","505"],["Pins, Brooches","11008"],["Rings","67725"],["Vintage, Antique","48579"],["Watches","14324"],["Wholesale Lots","40131"]],
  [["American Ironhorse","49973"],["Aprilia","38627"],["BMW","49974"],["BSA","6703"],["Benelli","159586"],["Big Dog","49978"],["Bimota","159587"],["Boss Hoss","49979"],["Bourget","49980"],["Buell","49981"],["Bultaco","6705"],["Can-Am","159588"],["Ciello","159589"],["Cushman","159590"],["Custom Built Motorcycles","147899"],["Desperado","133175"],["Ducati","49987"],["Greeves","159591"],["Harley-Davidson","49992"],["Hodaka","159592"],["Honda","49998"],["Husqvarna","50013"],["Hyosung","159593"],["Indian","6709"],["KTM","50021"],["Kawasaki","50014"],["Kymco","159594"],["Lifan","159595"],["MV Agusta","159596"],["Moto Guzzi","6713"],["Norton","6714"],["Other Makes","6719"],["Royal Enfield","50024"],["Suzuki","50025"],["Titan","6715"],["Triumph","50035"],["Ural","6717"],["Vento","159597"],["Victory","38628"],["Vincent","159598"],["Yamaha","50041"]],
  [["Accessories","52473"],["CDs","307"],["Cassettes","1600"],["DVD Audio","46353"],["Digital Music Downloads","88451"],["Other Formats","618"],["Records","306"],["Super Audio CDs","46354"],["Wholesale Lots","31608"]],
  [["Brass","16212"],["DJ Gear & Lighting","14982"],["Electronic","38068"],["Equipment","41402"],["Guitar","3858"],["Harmonica","47078"],["Instruction Books, CDs, Videos","100228"],["Keyboard, Piano","16217"],["Other Instruments","308"],["Percussion","10172"],["Pro Audio","15197"],["Sheet Music, Song Books","20833"],["String","10176"],["Wholesale Lots","52555"],["Woodwind","10181"]],
  [["Aircraft","63676"],["Boats","26429"],["Buses","6728"],["Commercial Trucks","63732"],["Military Vehicles","80765"],["Other","6737"],["RVs and Campers","50054"],["Race Cars (Not Street Legal)","98060"],["Trailers","66468"]],
  [["Glass","50693"],["Pottery & China","18875"]],
  [["ATVs","6723"],["Dune Buggies / Sand Rails","133220"],["Go Karts: High-performance","46105"],["Other Powersports","66467"],["Personal Watercraft","31273"],["Powersport Vehicles Under 50cc","90983"],["Scooters & Mopeds","6720"],["Snowmobiles","42595"]],
  [["Commercial","15825"],["Land","15841"],["Manufactured Homes","94825"],["Other Real Estate","1607"],["Residential","12605"],["Timeshares for Sale","15897"]],
  [["Advice & Instruction","50337"],["Artistic Services","47126"],["Custom Clothing & Jewelry","50343"],["Graphic & Logo Design","47131"],["Media Editing & Duplication","50355"],["Other Services","317"],["Printing & Personalization","20943"],["Restoration & Repair","47119"],["Web & Computer Services","47104"],["eBay Auction Services","50349"]],
  [["Airsoft","31680"],["Archery","20835"],["Athletic Apparel","137006"],["Athletic Footwear","137010"],["Baseball & Softball","16021"],["Basketball","21194"],["Billiards","21209"],["Bowling","20846"],["Boxing","30100"],["Camping, Hiking, Backpacking","16034"],["Canoes, Kayaks, Rafts","36121"],["Climbing","30105"],["Cycling","7294"],["Disc Golf","79802"],["Equestrian","3153"],["Exercise & Fitness","15273"],["Fishing","14104"],["Football","21214"],["Go-Karts, Recreational","64655"],["Golf","1513"],["Gymnastics","79792"],["Hunting","7301"],["Ice Skating","21225"],["Ice, Roller Hockey","40154"],["Indoor Games","36274"],["Inline, Roller Skating","16258"],["Lacrosse","62163"],["Martial Arts","36279"],["Other Sports","40141"],["Paintball","16045"],["Racquetball & Squash","62166"],["Running","64685"],["Scooters","11330"],["Scuba, Snorkeling","16052"],["Skateboarding","16262"],["Skiing & Snowboarding","36259"],["Snowmobiling","23831"],["Soccer","20862"],["Surfing, Wind Surfing","22709"],["Swimming","74050"],["Tennis","20868"],["Triathlon","64680"],["Wakeboarding, Waterskiing","23806"],["Wholesale Lots","40146"]],
  [["Autographs-Original","51"],["Autographs-Reprints","50115"],["Cards","212"],["Fan Apparel & Souvenirs","24409"],["Game Used Memorabilia","50116"],["Manufacturer Authenticated","60591"],["Vintage Sports Memorabilia","50123"],["Wholesale Lots","56080"]],
  [["Africa","692"],["Asia","47174"],["Australia","3468"],["Br. Comm. Other","263"],["Canada","3478"],["Europe","4742"],["Latin America","4747"],["Middle East","3491"],["Publications & Supplies","704"],["Topical & Specialty","4752"],["UK (Great Britain)","3499"],["United States","261"],["Worldwide","352"]],
  [["Event Tickets","16122"],["Experiences","16071"],["Other Items","1306"]],
  [["Action Figures","246"],["Beanbag Plush, Beanie Babies","49019"],["Building Toys","18991"],["Classic Toys","19016"],["Diecast, Toy Vehicles","222"],["Educational","11731"],["Electronic, Battery, Wind-Up","19071"],["Fast Food, Cereal Premiums","19077"],["Games","233"],["Model RR, Trains","479"],["Models, Kits","1188"],["Outdoor Toys, Structures","11743"],["Pretend Play, Preschool","19169"],["Puzzles","2613"],["Radio Control","2562"],["Ride-ons", "100600"],["Robots, Monsters, Space Toys","19192"],["Slot Cars","2616"],["Stuffed Animals","436"],["TV, Movie, Character Toys","2624"],["Toy Soldiers","2631"],["Trading Card Games","2536"],["Vintage, Antique Toys","717"],["Wholesale Lots","40149"]],
  [["Airline","3253"],["Car Rental","147399"],["Cruises","16078"],["Lodging","16079"],["Luggage","16085"],["Other Travel","1310"],["Vacation Packages","29578"]],
  [["ATV Parts","43962"],["Apparel & Merchandise","6747"],["Automotive Tools","34998"],["Aviation Parts","26435"],["Boat Parts","26443"],["Car & Truck Parts","6030"],["Car Audio, Video","38635"],["Manuals & Literature","6029"],["Motorcycle Parts","10063"],["Other","6755"],["Other Vehicle Parts","34285"],["Personal Watercraft Parts","124107"],["Racing Parts","107057"],["Services & Installation","111098"],["Snowmobile Parts","100448"],["Vintage Car & Truck Parts","10073"],["Wholesale Lots","50467"]],
  [["Accessories","49220"],["Games","62053"],["Internet Games","1654"],["Other","187"],["Systems","62054"],["Vintage Games","4315"],["Wholesale Lots","48749"]]
  ];

function populateCategoryParent(selectElement){
  selectElement.empty();
  selectElement.append( $j("<option>").val(-1).text("No category") );
  for (var i=0; i<parentCategories.length; i++){
	  selectElement.append( $j("<option>").val(parentCategories[i][1]).text(parentCategories[i][0]) );
  }
}
function populateCategoryChild(selectElement, parentIndex){
  selectElement.empty();
  selectElement.append( $j("<option>").val(-1).text("No subcategory") );
  if (parentIndex > 0 && parentIndex < childCategories.length + 1){
	  var childCategorySubset = childCategories[parentIndex-1]; // -1 since the first option is no option at'all
	  for (var i=0; i<childCategorySubset.length; i++){
		  selectElement.append( $j("<option>").val(childCategorySubset[i][1]).text(childCategorySubset[i][0]) );
	  }
  }
}

/// <reference path="jquery-intellisense.js" />

var TO_USER_ID = null;

//-----------------------------------------------------------------------------
// Setup HTML for sending a message to a specific user
function messageToUser(chatUserID, chatUserName)
{
  TO_USER_ID = chatUserID;
  $j("#to_user_id").html("<a href='#' onclick='clearMessageToUser(); return false;'>" + chatUserName + "</a>");
}

//-----------------------------------------------------------------------------
// Clear HTML for sending a message to a specific user
function clearMessageToUser()
{
  TO_USER_ID = null;
  $j("#to_user_id").html("all in this booth");
}

//------------------------------------------------------------------------------
chatHandler = function(options)
{
  //----------------------------------------------------------------------------
  // Internal prototype
	_chatHandler = function (options)
	{
	  this.chat_id          = options.chat_id;
	  this.last_msg_id      = options.last_msg_id;
	  this.updating_user_id = options.user_id;
	  this.show_remove_link = options.show_remove_link;
	  this.autoscroll_pixels= options.autoscroll_pixels || 50;
	  this.flash            = false;
	  this.started_at       = new Date();
	  this.blurred          = false;
	  this.page_title       = document.title;
	  
	  
	  //--------------------------------------------------------------------------
	  this.window_open = function()
	  {
  	  return ($j('#chat_window').css("display") != 'none');
	  };
	  
	  //--------------------------------------------------------------------------
	  // Start the chat message updater, with the given interval
	  this.start = function(update_interval)
	  {
	     self.read_messages(function(new_message_posted)
	      {
	        self.chat_bottom_scroll(true);
  	      
          self.timer = jQuery.timer(update_interval, function(timer) 
          {
       	    if(self.window_open()) {
	            // This is the perpetual read loop
	            self.read_messages(function(new_message_posted) {
								if(new_message_posted && get_json_subcookie("_bo_se", "beep")) {
									 playSound("/flash/bleep.mp3");
								}						
							});
	          }
          });
        });      
	  };
	  
	  //--------------------------------------------------------------------------
    // A work in progrses to update user list via mongrel handler
	  this.start_service_user_list = function(update_interval)
	  {
	    self.service_timer = jQuery.timer(update_interval, function(timer) 
      {
        if(self.window_open()) {
          $j.ajax({
	          type: "GET",
	          dataType: "json",
	          cache: false,
	          url: '/handlers/chat/service', 
	          data: { id: self.chat_id, user_id: self.updating_user_id }, 
	          success: function(json) {
	            for (var i = 0; i < json.length; i++) {
                var user = json[i];  
                var li = $j("<li class='" + (i % 1 == 0 ? 'odd' : '') + "'>");
                li.html("hi");
                $j('#user_list_container').html('');
              }
            }  
          });
        }
      });
	  };
	  
	  //--------------------------------------------------------------------------
	  // Read the latest chat messages, calling the given callback when done
	  this.read_messages = function(callback)
	  {
	    $j.ajax({
	      type: "GET",
	      dataType: "json",
	      cache: false,
	      url: '/handlers/chat/read', 
	      data: { chat_id: self.chat_id, msg_id: self.last_msg_id }, 
	      success: function(json) {
          var old_last_id = self.last_msg_id;
          var new_message_posted = false;
          
  	      for (var i = 0; i < json.length; i++)
          {
            var msg = json[i];  
            if (msg.id <= self.last_msg_id)
            {
              continue;      
            }
            
            var span = $j('<div>');
            span.attr('id', "chat_message_" + msg.id);
           
            if (self.show_remove_link)
            {
              // Creating a closure function here allows us to bind
              // msg.id with the value it has right now, rather than
              // trying to set .click(function() { self.delete_message(msg.id); })
              // which would result in msg.id getting evaluated at the
              // time the function is called, and the last assignment of msg
              // would not get garbage collected because the GC knows that
              // there is something holding on to it.  Every click handler would
              // then delete whatever the last msg's id was.
              function bindDeleteHandler(clicked_msg_id)
              {
                return function () { return self.delete_message(clicked_msg_id); };
              }
              
              span
                .append(jQuery('<a></a>') // WBH: IE works only if the a tag gets closed.  This exceeds my comprehension.
                  .attr({ href: "#", title: "Remove this line of chat" })
                  .text("X")
                  .click(bindDeleteHandler(msg.id)))
                .append(" ");
            }
            
            var message_content = msg.content;
            if (msg.to)
            {
              span.append('<span style="color:gray">' + msg.time + ' </span><b>' + msg.from + '</b> (sent to ' + msg.to + ' only): ' + message_content + '<br />');
            }
            else if(msg.is_action)
						{
							span.append('<span style="color:gray">' + msg.time + ' </span><em><a href="/users/' + msg.from + '/profile">' + msg.from + '</a> ' + message_content + '</em><br />');
						}
						else
            {
              span.append('<span style="color:gray">' + msg.time + ' </span><b><a href="/users/' + msg.from + '/profile">' + msg.from + '</a></b>: ' + message_content + '<br />');
            }
            jQuery('#chat_text_area').append(span);
              
            if (msg.id > self.last_msg_id)
            {
              self.last_msg_id = msg.id;
            }
          }
          
          if (self.last_msg_id > old_last_id)
          {
						new_message_posted = true;
            
            if(self.flash) {
              self.flash_new_message();
            }
            else {
              timeNow = new Date(); 
              // After 5 seconds have passed since chat was loaded, then we'll say that new messages are noteworthy
              if( (timeNow.getTime() - self.started_at.getTime()) > 1000*2) {
                self.flash = true;
              }
            }
            self.chat_bottom_scroll(false);
          }
          
          if (callback != null)
          {
            callback(new_message_posted);
          }
        } // successful read
       });	
    };

		//-----------------------------------------------------------------------------
		// Taken from Ruby on Rails forum...this tries to be smart about not scrolling
		// user down if they were in the middle of reading history
		this.chat_bottom_scroll = function(force)
		{
			var chatWindow = $j('#chat_text_area').get(0);

			var h = chatWindow.scrollHeight;
			var sh = chatWindow.scrollTop;
			var st = chatWindow.offsetHeight;
			var difference = h - sh;
			var alt = st + this.autoscroll_pixels;
			if ((difference < alt) || force)
			{
				chatWindow.scrollTop = h;
			}
		}

    
    //--------------------------------------------------------------------------
	  // Post the given message content to the given user id (or null to post to all)
    this.post_message = function(to_id, content)
    {
      $j.ajax({
        type: "GET",
	      dataType: "json",
	      cache: false,
	      url: '/handlers/chat/post', 
	      data: { chat_id: self.chat_id, to_id: to_id == null ? -1 : to_id, content: content }, 
	      success: function(json) {
          self.read_messages(function(new_message_posted)
	        {
	          self.chat_bottom_scroll(true);
	        });
        }
     });
    };
    
    //--------------------------------------------------------------------------
	  // Delete the message - validation is run on the server side to ensure that
	  // the user attempting this has the correct permissions to delete the 
	  // specified message.
    this.delete_message = function(msg_id)
    {
      $j.ajax({
        type: "GET",
        dataType: "json",
        cache: false,
        url: '/handlers/chat/delete', 
        data: { chat_id: self.chat_id, msg_id: msg_id },
        success: function(json) {
          jQuery('#chat_message_' + json.deleted_id).remove();
        }
      });
    };

    //-----------------------------------------------------------------------------
    // If a user is sitting on the booth page with chat window closed, make sure they know messages are incoming
    this.flash_new_message = function() {
      if($j('#chat_window').css("display")==='none') {
        $j('#newMessageIndicatorSpan').show();
      }
      
      if(self.blurred) {
        document.title = "New chat text - " + self.page_title;
      }
    };

    this.window_blur = function(isBlurred) {
      self.blurred = isBlurred;
      if(!self.blurred) {
        document.title = self.page_title;
      }      
    };

    var self = this;
	};

	return new _chatHandler(options);
};


// Get the namespace.
var EXANIMO = EXANIMO || {};




/**
 *
 * StateManager
 *
 *     Adds state management (back button and deep-linking) to your single-page
 *     web application.
 *
 *     For usage instructions, see
 *     <http://exanimo.com/javascript/using-the-statemanager-in-ajax-apps>.
 *
 *     copyright 2007 matthew john tretter.  available under the MIT License.
 *     (<http://www.opensource.org/licenses/mit-license.php>)

 *     @author     matthew at exanimo dot com
 *     @version    2007.04.30
 *
 */


(function()
{
	// Create the package.
	EXANIMO.managers = EXANIMO.managers || {};

	//
	// "Private" properties.
	//

	var _initialized = false;
	var _checkInterval;
	var _method;
	var _swf;
	var _oldStateID;
	var _preventPageRefresh = false;
	var _iframeID = 'EXANIMO-managers-StateManager-iFrame';
	var _e;
	function _self()
	{
		return EXANIMO.managers.StateManager;
	}
	
	// Decide which method to use by (blech!) browser sniffing.
	var _method = navigator.appName.indexOf('Microsoft Internet') != -1 ? 'IFRAME' : navigator.userAgent.indexOf('Safari') != -1 ? 'LINK' : 'HASH';

	
    /**
     *
     * Retrieves state ID.
     *
     *     @return    the id of the current state
     *
     */
    function _getStateID()
    {
        return document.location.href.split('#')[1] || _self().defaultStateID;
    };

	/**
	 *
	 * Gets the SWF that has been "setup" (i.e. has the callback added). This
	 * prevents the user from having to call StateManager.initialize(mySWF) in
	 * their JavaScript. 	 		 
	 *
	 */		 		 		 		 		
	function _getSWF()
	{
		var tags = ['object', 'embed'];
		for (var i = 0; i < tags.length; i++)
		{
			var a = document.getElementsByTagName(tags[i]);
			for (var j = 0; j < a.length; j++)
			{
				if (a[j].dispatchStateChangeEvents)
				{
					return a[j];
				}			
			}	
		}
	};

    /**
     *
     * Dispatches a stateChange event.
     *
     *     @param stateID    the id of the state to load
     *     @param manual     was the stateChange manual? manual changes
     *                       are the result of calls to setState. (automatic
     *                       changes are the result of the back / forward
     *                       buttons or deep-linking.)
     *
     */
    function _dispatchEvent(stateID, manual)
    {
        stateID = stateID || _self().defaultStateID;

        if (!_swf)
        {
        	//
        	// AJAX mode
        	//
        
	        _e = {id: stateID};
	        var f;

	        // If a handler is set, call it.
	        if (f = _self().onstatechange)
	        {
	        	_e.type = 'stateChange';
	            f(_e);
	        }
	
	        if (manual)
	        {
	            if (f = _self().onstateset)
	            {
	            	_e.type = 'stateSet';
	                f(_e);
	            }
	        }
	        else
	        {
	            if (f = _self().onstaterevisit)
	            {
	            	_e.type = 'stateRevisit';
	                f(_e);
	            }
	        }

	        _e = null;
	    }
        else if (!manual)
		{
			//
			// SWF mode
			//
			_swf.dispatchStateChangeEvents(stateID);
        }
    };

	var _setHash = (function()
	{
    	switch(_method)
        {
            case 'HASH':

				return function(stateID)
				{
                	document.location.hash = stateID == _self().defaultStateID ? '#' : stateID;
                	_oldStateID = stateID;
                };

            case 'IFRAME':

				return function(stateID)
				{
					_preventPageRefresh = true;
            		var iframe = document.getElementById(_iframeID);

                    frames[_iframeID].document.open();
                    frames[_iframeID].document.write('<script>parent.document.location.hash = "' + (stateID == _self().defaultStateID ? '#' : stateID) + '"; /* Wait for IE to impose its title before setting ours. */ setTimeout( function(){ parent.EXANIMO.managers.StateManager._updateIFrame("' + stateID + '"); }, 0);</script>');
                    frames[_iframeID].document.close();
				};

            case 'LINK':

				return function(stateID)
				{
                    _preventPageRefresh = true;

                    var a = document.createElement('a');
                    a.setAttribute('href', stateID == _self().defaultStateID ? '#' : '#' + stateID);

                    var evt = document.createEvent('MouseEvents');
                    evt.initEvent('click', true, true);
                    a.dispatchEvent(evt);

                    document.location.EXANIMO.managers.StateManager.stateList.push(stateID);
                };
        }
	})();

    EXANIMO.managers.StateManager = {

        CHECK_RATE: 100,
        onstatechange: null,
        onstateset: null,
        onstaterevisit: null,
        DEFAULT_STATE: 'defaultState',
        defaultStateID: 'defaultState',

        /**
         *
         * Does all the behind-the-scenes startup work for the StateManager.
         *
         *     @param swf    (optional) the SWF to add state management to. if
         *                   the boolean value true is passed, the StateManager
         *                   will use the swf returned by _getSWF(). if no
         *                   argument is passed, the StateManager will operate
         *                   in "ajax mode".     
         *
         */
        initialize: function(swf)
        {
        	if (_initialized) return;
            _initialized = true;
			_swf = swf == true ? _getSWF() : swf;

            switch(_method)
            {
                case 'HASH':

                    _oldStateID = _getStateID() == _self().defaultStateID ? _self().defaultStateID : null;

                    // Watch to see if the hash changes.
                    var checkForHashChange = function()
                    {
                        var stateID = _getStateID();

                        if (stateID != _oldStateID)
                        {
                            _oldStateID = stateID;
                            _dispatchEvent(stateID)
                        }
                    }

                    _checkInterval = setInterval(checkForHashChange, _self().CHECK_RATE);

                    break;

                case 'IFRAME':

                    //
                    // Make sure the iframe knows that, when it loads, it should
                    // not refresh this page.
                    //
					_preventPageRefresh = true;

                    // Create and attach the iframe.
                    var iframe = document.createElement('iframe');
                    iframe.setAttribute('src', 'about:blank');
                    iframe.setAttribute('name', _iframeID);
                    iframe.setAttribute('id', _iframeID);
                    iframe.style.visibility = 'hidden';
                    iframe.style.width = '0';
                    iframe.style.height = '0';
                    iframe.style.position = 'absolute';
                    iframe.style.overflow = 'hidden';
                    document.body.appendChild(iframe);

                    // If a state id is already present in the hash, go to it.
                    var stateID = _getStateID();
                    if (stateID != _self().defaultStateID)
                    {
                        setTimeout(
                            function()
                            {
                                _dispatchEvent(stateID)
                            },
                            0
                        );
                    }

                    // Update the page and hash from the iframe.
                    frames[_iframeID].document.open();
                    if (stateID)
                        frames[_iframeID].document.write('<script>parent.document.location.hash = "' + (stateID == _self().defaultStateID ? '' : stateID) + '"; parent.EXANIMO.managers.StateManager._updateIFrame("' + stateID + '");</script>');
                    else
                        frames[_iframeID].document.write('<script>parent.document.location.hash = ""; parent.EXANIMO.managers.StateManager._updateIFrame();</script>');
                    frames[_iframeID].document.close();

                    break;

                case 'LINK':

                    document.location.EXANIMO = document.location.EXANIMO || {};
                    document.location.EXANIMO.managers = document.location.EXANIMO.managers || {};
                    document.location.EXANIMO.managers.StateManager = document.location.EXANIMO.managers.StateManager || {};

                    var loc = document.location.EXANIMO.managers.StateManager;

                    // Make sure the last state is loaded when you come back to
                    // this page after navigating away.
                    window.onunload = function()
                    {
                        loc.oldHistoryLength = -1;
                    }

                    if (loc.deepLink && loc.deepLink != _self().defaultStateID)
                    {
                    	loc.oldHistoryLength = -1;
						loc.deepLink = null;                   	
                    }

                    // Create a list of the states we click through.
                    if (typeof loc.stateList == 'undefined')
                    {
                        loc.stateList = [_getStateID() || _self().defaultStateID];
                        loc.deepLink = loc.stateList[0];

                        loc.offset = history.length - 1;
                        while (loc.offset)
                        {
                            loc.stateList.unshift(null);
                            loc.offset--;
                        }
                        delete loc.offset;

                        loc.oldHistoryLength = document.location.hash ? -1 : history.length;

                    }

                    // Watch to see if the length of the history object changes.
                    var checkForHistoryLengthChange = function() 
                    {
                        var loc = document.location.EXANIMO.managers.StateManager;

                        if (_preventPageRefresh)
                        {
                            _preventPageRefresh = false;
                            loc.oldHistoryLength = history.length;
                            return;
                        }

                        if (history.length != loc.oldHistoryLength)
                        {
                            var stateID = loc.stateList[history.length - 1];

                            _dispatchEvent(stateID)
                            loc.oldHistoryLength = history.length;
                        }
                    }

                    _checkInterval = setInterval(checkForHistoryLengthChange, _self().CHECK_RATE);

                    break;

            }
        },


        /**
         *
         * Adds an entry to the history.
         *
         *     @param stateID       a unique identifier corresponding to a
         *                          specific state
         *
         */
        setState: function(stateID, title)
        {
			// Set the title.
        	if (title) _self().setTitle(title);

        	// Block infinite loops.
            if (_e) return;

        	_setHash(stateID);
        			
        	// Dispatch the stateChange events
        	_dispatchEvent(stateID, true);
        },		


        /**
         *
         * Sets the window's title.
         *
         *     @param title    the string to put in the browser's title bar
         *
         */
        setTitle: function(title)
        {
            window.document.title = title || ' ';
        },


        /**
         *
         * Updates the iframe. Must be public so that it can be accessed from
         * the iframe.         
         *
         *     @param stateID    the id of the state to record
         *
         */
        _updateIFrame: function(stateID)
        {
			if (!_preventPageRefresh)
			{
				_dispatchEvent(stateID);
			}
			
			_preventPageRefresh = false;
        }

    }

})();



// Copyright (c) 2007 matthew john tretter.  Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.


/**
 * SWFObject v1.5: Flash Player detection and embed - http://blog.deconcept.com/swfobject/
 *
 * SWFObject is (c) 2007 Geoff Stearns and is released under the MIT License:
 * http://www.opensource.org/licenses/mit-license.php
 *
 */
if(typeof deconcept=="undefined"){var deconcept=new Object();}if(typeof deconcept.util=="undefined"){deconcept.util=new Object();}if(typeof deconcept.SWFObjectUtil=="undefined"){deconcept.SWFObjectUtil=new Object();}deconcept.SWFObject=function(_1,id,w,h,_5,c,_7,_8,_9,_a){if(!document.getElementById){return;}this.DETECT_KEY=_a?_a:"detectflash";this.skipDetect=deconcept.util.getRequestParameter(this.DETECT_KEY);this.params=new Object();this.variables=new Object();this.attributes=new Array();if(_1){this.setAttribute("swf",_1);}if(id){this.setAttribute("id",id);}if(w){this.setAttribute("width",w);}if(h){this.setAttribute("height",h);}if(_5){this.setAttribute("version",new deconcept.PlayerVersion(_5.toString().split(".")));}this.installedVer=deconcept.SWFObjectUtil.getPlayerVersion();if(!window.opera&&document.all&&this.installedVer.major>7){deconcept.SWFObject.doPrepUnload=true;}if(c){this.addParam("bgcolor",c);}var q=_7?_7:"high";this.addParam("quality",q);this.setAttribute("useExpressInstall",false);this.setAttribute("doExpressInstall",false);var _c=(_8)?_8:window.location;this.setAttribute("xiRedirectUrl",_c);this.setAttribute("redirectUrl","");if(_9){this.setAttribute("redirectUrl",_9);}};deconcept.SWFObject.prototype={useExpressInstall:function(_d){this.xiSWFPath=!_d?"expressinstall.swf":_d;this.setAttribute("useExpressInstall",true);},setAttribute:function(_e,_f){this.attributes[_e]=_f;},getAttribute:function(_10){return this.attributes[_10];},addParam:function(_11,_12){this.params[_11]=_12;},getParams:function(){return this.params;},addVariable:function(_13,_14){this.variables[_13]=_14;},getVariable:function(_15){return this.variables[_15];},getVariables:function(){return this.variables;},getVariablePairs:function(){var _16=new Array();var key;var _18=this.getVariables();for(key in _18){_16[_16.length]=key+"="+_18[key];}return _16;},getSWFHTML:function(){var _19="";if(navigator.plugins&&navigator.mimeTypes&&navigator.mimeTypes.length){if(this.getAttribute("doExpressInstall")){this.addVariable("MMplayerType","PlugIn");this.setAttribute("swf",this.xiSWFPath);}_19="<embed type=\"application/x-shockwave-flash\" src=\""+this.getAttribute("swf")+"\" width=\""+this.getAttribute("width")+"\" height=\""+this.getAttribute("height")+"\" style=\""+this.getAttribute("style")+"\"";_19+=" id=\""+this.getAttribute("id")+"\" name=\""+this.getAttribute("id")+"\" ";var _1a=this.getParams();for(var key in _1a){_19+=[key]+"=\""+_1a[key]+"\" ";}var _1c=this.getVariablePairs().join("&");if(_1c.length>0){_19+="flashvars=\""+_1c+"\"";}_19+="/>";}else{if(this.getAttribute("doExpressInstall")){this.addVariable("MMplayerType","ActiveX");this.setAttribute("swf",this.xiSWFPath);}_19="<object id=\""+this.getAttribute("id")+"\" classid=\"clsid:D27CDB6E-AE6D-11cf-96B8-444553540000\" width=\""+this.getAttribute("width")+"\" height=\""+this.getAttribute("height")+"\" style=\""+this.getAttribute("style")+"\">";_19+="<param name=\"movie\" value=\""+this.getAttribute("swf")+"\" />";var _1d=this.getParams();for(var key in _1d){_19+="<param name=\""+key+"\" value=\""+_1d[key]+"\" />";}var _1f=this.getVariablePairs().join("&");if(_1f.length>0){_19+="<param name=\"flashvars\" value=\""+_1f+"\" />";}_19+="</object>";}return _19;},write:function(_20){if(this.getAttribute("useExpressInstall")){var _21=new deconcept.PlayerVersion([6,0,65]);if(this.installedVer.versionIsValid(_21)&&!this.installedVer.versionIsValid(this.getAttribute("version"))){this.setAttribute("doExpressInstall",true);this.addVariable("MMredirectURL",escape(this.getAttribute("xiRedirectUrl")));document.title=document.title.slice(0,47)+" - Flash Player Installation";this.addVariable("MMdoctitle",document.title);}}if(this.skipDetect||this.getAttribute("doExpressInstall")||this.installedVer.versionIsValid(this.getAttribute("version"))){var n=(typeof _20=="string")?document.getElementById(_20):_20;n.innerHTML=this.getSWFHTML();return true;}else{if(this.getAttribute("redirectUrl")!=""){document.location.replace(this.getAttribute("redirectUrl"));}}return false;}};deconcept.SWFObjectUtil.getPlayerVersion=function(){var _23=new deconcept.PlayerVersion([0,0,0]);if(navigator.plugins&&navigator.mimeTypes.length){var x=navigator.plugins["Shockwave Flash"];if(x&&x.description){_23=new deconcept.PlayerVersion(x.description.replace(/([a-zA-Z]|\s)+/,"").replace(/(\s+r|\s+b[0-9]+)/,".").split("."));}}else{if(navigator.userAgent&&navigator.userAgent.indexOf("Windows CE")>=0){var axo=1;var _26=3;while(axo){try{_26++;axo=new ActiveXObject("ShockwaveFlash.ShockwaveFlash."+_26);_23=new deconcept.PlayerVersion([_26,0,0]);}catch(e){axo=null;}}}else{try{var axo=new ActiveXObject("ShockwaveFlash.ShockwaveFlash.7");}catch(e){try{var axo=new ActiveXObject("ShockwaveFlash.ShockwaveFlash.6");_23=new deconcept.PlayerVersion([6,0,21]);axo.AllowScriptAccess="always";}catch(e){if(_23.major==6){return _23;}}try{axo=new ActiveXObject("ShockwaveFlash.ShockwaveFlash");}catch(e){}}if(axo!=null){_23=new deconcept.PlayerVersion(axo.GetVariable("$version").split(" ")[1].split(","));}}}return _23;};deconcept.PlayerVersion=function(_29){this.major=_29[0]!=null?parseInt(_29[0]):0;this.minor=_29[1]!=null?parseInt(_29[1]):0;this.rev=_29[2]!=null?parseInt(_29[2]):0;};deconcept.PlayerVersion.prototype.versionIsValid=function(fv){if(this.major<fv.major){return false;}if(this.major>fv.major){return true;}if(this.minor<fv.minor){return false;}if(this.minor>fv.minor){return true;}if(this.rev<fv.rev){return false;}return true;};deconcept.util={getRequestParameter:function(_2b){var q=document.location.search||document.location.hash;if(_2b==null){return q;}if(q){var _2d=q.substring(1).split("&");for(var i=0;i<_2d.length;i++){if(_2d[i].substring(0,_2d[i].indexOf("="))==_2b){return _2d[i].substring((_2d[i].indexOf("=")+1));}}}return "";}};deconcept.SWFObjectUtil.cleanupSWFs=function(){var _2f=document.getElementsByTagName("OBJECT");for(var i=_2f.length-1;i>=0;i--){_2f[i].style.display="none";for(var x in _2f[i]){if(typeof _2f[i][x]=="function"){_2f[i][x]=function(){};}}}};if(deconcept.SWFObject.doPrepUnload){if(!deconcept.unloadSet){deconcept.SWFObjectUtil.prepUnload=function(){__flash_unloadHandler=function(){};__flash_savedUnloadHandler=function(){};window.attachEvent("onunload",deconcept.SWFObjectUtil.cleanupSWFs);};window.attachEvent("onbeforeunload",deconcept.SWFObjectUtil.prepUnload);deconcept.unloadSet=true;}}if(!document.getElementById&&document.all){document.getElementById=function(id){return document.all[id];};}var getQueryParamValue=deconcept.util.getRequestParameter;var FlashObject=deconcept.SWFObject;var SWFObject=deconcept.SWFObject;

/**
 * Construct a new Facebook object to handle all communication with Facebook via the Facebook
 * Graph API.  Uses the FB JavaScript API.
 * @singleton
 */
facebookAPI = new function FacebookAPI() {
  var session = null;

  //private methods
  //Initialize the Facebook Javascript API (http://developers.facebook.com/docs/reference/javascript).
  var initialize = function(callback, params) {
    if ($j('#fb-root').length == 0) {
      $j('<div id="fb-root"></div>').appendTo("body");
      window.fbAsyncInit = function() {
        FB.init({appId: '9c99c3a2b1082b72be1d58e2d4c95a83', status: true, cookie: true, xfbml: true});
        FB.getLoginStatus(function(response) {
          session = response.session;
          callback(params);
        });

        //log any likes to GA.
        //http://developers.facebook.com/docs/reference/javascript/FB.Event.subscribe
        FB.Event.subscribe('edge.create', function(response) {
          if (typeof(pageTracker) != 'undefined') {
            pageTracker._trackPageview('facebook/like');
          }
        });

        //HACK: overrides FB's post method to flatten the params before sending. (Rob Colburn's "fix" at: http://bugs.developers.facebook.net/show_bug.cgi?id=10180)
        FB.Content.origPostTarget = FB.Content.postTarget;
        FB.Content.postTarget = function(opts) {
          opts.params = FB.JSON.flatten(opts.params);
          FB.Content.origPostTarget(opts);
        };
      };
      var e = document.createElement('script');
      e.async = true;
      e.src = document.location.protocol + '//connect.facebook.net/en_US/all.js';
      document.getElementById('fb-root').appendChild(e);
    } else {
      callback(params);
    }
  };
  var ensureLoggedIn = function(callback, params) {
    if (session == null) {
      FB.login(function(response) {
        if (response.session) {
          callback(params);
        }
      });
    } else {
      callback(params);
    }
  };
  var filterParams = function(params) {
    if (jQuery.browser.msie && parseInt(jQuery.browser.version) < 8) params.display = 'popup';
    return params;
  };
  var uiCallback = function(params) {
    if (session == null) {
      ensureLoggedIn(uiCallback, params);
    } else {
      FB.ui(filterParams(params), function(response) {
        //send a note to GA about the event, whether it succeeded or failed.
        if (typeof(pageTracker) != 'undefined') {
          pageTracker._trackPageview('facebook/ui/' + params.method + ((response) ? '/success' : '/failure'));
        }
      });
    }
  };
  var xfbmlCallback = function(params) {
    FB.XFBML.parse(params);
  };

  // Privileged methods
  this.ui = function(params) {
    initialize(uiCallback, params)
  };
  // Privileged methods
  this.xfbmlParse = function(params) {
    initialize(xfbmlCallback, params)
  };
};
