var InputCharCounter = {
	id: '',
	maxsize: 255,
	limited: false,
	
	init: function(id, maxsize, limited) {
		this.id = id;
		if (maxsize != null) this.maxsize = maxsize;
		if (limited != null) this.limited = limited;
		
		this.setupCharCount();
	},

	charCounter: function() {
		id = this.id; maxlimit = this.maxsize; limited = this.limited;
		counter_id = id + "_counter";
		if (!$(counter_id)){
			$(id).insert({after: '<div id="'+counter_id+'"></div>'});
		}
		if($F(id).length >= maxlimit){
			if(limited){	$(id).value = $F(id).substring(0, maxlimit); }
			$(counter_id).addClassName('charcount-limit');
			$(counter_id).removeClassName('charcount-safe');
		} else {	     
			$(counter_id).removeClassName('charcount-limit');
			$(counter_id).addClassName('charcount-safe');
		}
		$(counter_id).update( $F(id).length + '/' + maxlimit );	

	},

	setupCharCount: function() {
		if ($(this.id)){
			Event.observe($(this.id), 'keyup', this.charCounter.bindAsEventListener(this), false);
			Event.observe($(this.id), 'keydown', this.charCounter.bindAsEventListener(this), false);
			this.charCounter(this.id,this.maxsize,this.limited);
		}
	}
}


// Provides the version number of the browser.

var Sniffer = {
	Browser: (function(agent) { 
		function getVersion(identifier) { 
			var version = new RegExp(identifier + '([\\d.]+)').exec(agent); 
			return version ? parseFloat(version[1]) : true; 
		} 
		return { 
			IE:     !!(window.attachEvent && !window.opera) && getVersion('MSIE '), 
			Opera:  !!window.opera && getVersion('Opera/'), 
			WebKit: agent.indexOf('AppleWebKit/') > -1 && getVersion('AppleWebKit/'), 
			Gecko:  agent.indexOf('Gecko') > -1 && agent.indexOf('KHTML') == -1 
			        && getVersion('Gecko/'), 
			MobileSafari: !!agent.match(/iPhone.*Mobile.*Safari/) 
		}; 
	})(navigator.userAgent),
	
	better_than_IE6: function() {
		if ((!Sniffer.Browser.IE) || (Sniffer.Browser.IE > 6)) {
			return true;
		}
	}
	
};

function mOver(el,img){
$(el).setAttribute("src","images/navigation/"+img+".gif");
}

function mOut(el,img){
$(el).setAttribute("src","images/navigation/"+img+".gif");
}

// rollover for the ranker home link
var logo = {
	id: 'rankers-logo',
	image: '/images/rankers_logo.gif',
	overImage: '/images/rankers_logo-over.gif',
	
	init: function() {
		var rankers_logo = $(this.id);
		if (rankers_logo != null) {
			rankers_logo.observe('mouseover', this.mouseover.bindAsEventListener(this));
			rankers_logo.observe('mouseout', this.mouseout.bindAsEventListener(this));
		}
	},
	mouseover: function(e) {
		Event.element(e).src = this.overImage;
	},
	mouseout: function(e) {
		Event.element(e).src = this.image;
	}
};

var noozeelend = {
	region_links: function() { return $$('.noozeelend_wrap .regions a, .noozeelend_wrap area'); },
	region_hilites: function() { return $$('.noozeelend_wrap .region_hilite'); },
	preload: function() {
		var preload_image = new Image();
		var region_ids = new Array("1","11","12","15","16","18","19","20","22","26","27","28","29","30","7","31","36","10","4","33","3","9","8","5","6","2","25");
		region_ids.each( function(id) { preload_image.src = "/images/noozeelend-region-" + id + ".png" });
	},
	mouseover: function(e) {
		this.region_links().invoke('removeClassName', 'selected');
		var region_id = Event.element(e).readAttribute('region_id');
		this.region_hilites().invoke('update', '<img src="/images/noozeelend-region-' + region_id + '.png" usemap="#noozeelend_map" />');
		$$('.noozeelend_wrap .regions a[region_id=' + region_id + ']').invoke('addClassName','selected');
	},
	mouseout: function(e) {
		this.region_links().invoke('removeClassName', 'selected');
		this.region_hilites().invoke('update', '');
	},
	init: function() {
		this.preload();
		this.region_links().invoke('observe', 'mouseover', this.mouseover.bindAsEventListener(this));
		this.region_links().invoke('observe', 'mouseout', this.mouseout.bindAsEventListener(this));
	}
}

// Menu class expects a particular HTML structure (replace 'name' with your instance's name):
//	<div id="name_wrap" class="menu_wrap">
//		<div id="name" class="menu_bar">
//			<ul>
//				<li class="menu" id="itemname_menu">
//					<a href="" class="top_item">menu title</a>
//				</li>
//			</ul>
//		</div>
//		<div class="menu_boxes">
//			<div id="itemname_menubox" class="menu_box">
//				<!-- menu content -->
//			</div>
//		</div>
//	</div>
var Menu = Class.create({	
	initialize: function(name, lockable) {
		this.name = name;
		this.id = '#'+this.name;
		if (!this.exists()) { return; }
		this.lockable = lockable || false;
		this.top_items_with_menubox().each( function(item) {
			item.up('.menu').addClassName('has_menubox');
		});
		this.menus().invoke('observe', 'mouseover', this.goMenu.bindAsEventListener(this));
		if (this.lockable) {
			this.top_items_with_menubox().invoke('observe', 'click', this.toggleLockMenu.bindAsEventListener(this));
			this.form_inputs().invoke('observe', 'focus', this.lockMenu.bindAsEventListener(this));
			this.menu_bar_form_inputs().invoke('observe', 'focus', this.goFormMenu.bindAsEventListener(this));
			this.unlocks().invoke('observe', 'click', this.unlockMenu.bindAsEventListener(this));
		}
		this.menuwrap().observe('mouseleave', this.deactivate.bindAsEventListener(this));
	}, 
	
	// properties
	offTimer: null,
	onTimer: null,
	time: 500,
	id: '',
	
	// refs to Elements
	form_inputs: function() { return $$('#'+this.name+'_wrap input'); },
	menu_bar_form_inputs: function() { return $$('#'+this.name+'_wrap .menu_bar input'); },
	menu_box_form_inputs: function() { return $$('#'+this.name+'_wrap .menu_box input'); },
	unlocks: function() { return $$('#'+this.name+' .unlock'); },
	top_items: function() { return $$('#'+this.name+' .menu .top_item'); },
	top_items_with_menubox: function() { 
		var items = $$('#'+this.name+' .menu .top_item');
		items = items.reject( function(item){ 
			return $(item.up('.menu').identify()+'box') == null;
		});
		return items;
	},
	menus: function() { return $$('#'+this.name+' .menu'); },
	menuwrap: function() { return $(this.name+'_wrap'); },
	openmenus: function() { return $$('#'+this.name+' .menu.open'); },
	openmenuboxes: function() { return $$('#'+this.name+'_wrap .menu_box.open'); },
	
	// methods
	goMenu: function(e) {
		var menu_to_open = Event.element(e).up('.menu');
		if (menu_to_open != null && ! this.isLocked()) {
			this.openMenu(menu_to_open);
		}
		e.stop();
	},
	goFormMenu: function(e) {
		this.goMenu(e);
	},
	openMenu: function(menu_to_open) {
		this.menuwrap().removeClassName('active');
		this.closeAll();
		var menubox = $(menu_to_open.identify() + 'box'); 
		if (menubox != null){ 
			this.activate();
			menubox.addClassName('open'); 
		}
		menu_to_open.addClassName('open');
	},
	activate: function() {
		this.menuwrap().addClassName('active');
	},
	clearOffTimer: function() {
		clearTimeout(this.offTimer);		
	},
	deactivate: function() {
		if (!this.isLocked()) {
			this.switchOff();
		}
	},
	switchOff: function() {
		this.menuwrap().removeClassName('active');
		this.closeAll();
	},
	closeAll: function() {
		this.openmenus().invoke('removeClassName','open');
		this.openmenuboxes().invoke('removeClassName','open');
	},
	toggleLockMenu: function(e) {
		if (this.isLocked()) {
			var el = Event.element(e);
			var clicked_menu = el.up('.menu');
			if (clicked_menu.hasClassName('open') && el.tagName != 'INPUT') {
				this.menuwrap().removeClassName('locked');
				fadebkgrnd.fade_out();
			} else {
				this.openMenu(clicked_menu);
			}
		} else {
			this.lockMenu();
		}
		e.stop();
	},
	isLocked: function() {
		return this.menuwrap().hasClassName('locked');
	},
	lockMenu: function(e) {
		this.menuwrap().addClassName('locked');
		fadebkgrnd.fade_in();
		if (e) { e.stop(); }
	},
	unlockMenu: function(e) {
		this.menuwrap().removeClassName('locked');
		fadebkgrnd.fade_out();
		this.deactivate();
		if (e) { e.stop(); }
	},
	exists: function(){
		if (this.menuwrap() != null) { return true; }
	}
});


var fadebkgrnd = {
	fade_element: function() {
		var fade_bkgrnd = $('fadebkgrnd');
		if ( fade_bkgrnd == null ) { 
			$($$('body').first()).insert({top:'<div id="fadebkgrnd" style="display:none;"></div>'});
			fade_bkgrnd = $('fadebkgrnd');
		}
		return fade_bkgrnd;
	},
	fade_out: function() {
		new Effect.Fade(this.fade_element(),{
			duration: .25
		});
	},
	fade_in: function() {
		var element = this.fade_element();
		new Effect.Appear(element,{
			duration: .25,
			to: .40
		});
	},
	switchOff: function() {
		this.fade_out();
	}
}

var search = {
	search_term: '',
	default_text: 'Search',
	min_chars: 2,
	gsearch_input_id: 'globalsearchterms',
	gsearch_results_id: 'globalsearch_results',
	goodToGo: true,
	gsearch_input: function() { return $(this.gsearch_input_id); },
	results: function() { return $(this.gsearch_results_id); },
	spinner: function() { return $('globalsearch_spinner'); },
	loading: function() {
		this.spinner().show();
		results = this.results();
		results.removeClassName('has_results');
		results.update('<p style="text-align:center;">Searching for <strong>' + this.gsearch_input().value + '</strong>...</p>');
	},
	complete: function() {
		this.results().addClassName('has_results');
		this.spinner().hide();
	},
	switchOn: function() {
		var gsearch_input = this.gsearch_input();
		if (gsearch_input.value == '' || gsearch_input.value == this.default_text) {
			gsearch_input.up('.search-wrapper').removeClassName('blurred');
			gsearch_input.value = '';
		}
	},
	switchOff: function() {
		var gsearch_input = this.gsearch_input();
		if (gsearch_input.value == '' || gsearch_input.value == this.default_text) {
			gsearch_input.up('.search-wrapper').addClassName('blurred');
			gsearch_input.value = this.default_text;
		}
	},
	setGoodToGo: function() {
		this.goodToGo = false;
	},
	resetGoodToGo: function() { 
		this.goodToGo = true;
		window.clearInterval(this.timer);
	},
	getSearchResults: function() {
		new Ajax.Updater(search.gsearch_results_id, '/search/global_search', { 
			asynchronous:true, 
			evalScripts:true, 
			onComplete:function(request){ search.complete() }, 
			onLoading:function(request){ search.loading() }, 
			parameters:'terms=' + encodeURIComponent(this.search_term)
		});
		this.resetGoodToGo();
	},
	doSearch: function(e) {
		var el = Event.element(e);
		if (el.value.length >= this.min_chars) {
			this.search_term = el.value;
			if (this.goodToGo == true) {
				this.timer = window.setInterval('search.getSearchResults()', 1000);
			}
			this.setGoodToGo();
		}
	},
	init: function() {
		if (!this.exists()) { return; }
		var gsearch_input = this.gsearch_input();
		this.switchOff();
		gsearch_input.observe('focus', this.switchOn.bindAsEventListener(this));
		gsearch_input.observe('blur', this.switchOff.bindAsEventListener(this));
		gsearch_input.observe('keyup', this.doSearch.bindAsEventListener(this));
	},
	exists: function() {
		if (this.gsearch_input() != null) { return true; }
	}
};

var flashes = {
	init: function() {
		// new Effect.Highlight($('messagebar'));
	}
};

var fluff = {
	picture: new Image(),
	render: function() {
		if (fluff.picture.complete){
			var header = $('ir');
			header.style.backgroundImage = "url("+fluff.picture.src+")";
			header.style.height = fluff.picture.height+"px";
			header.style.width = fluff.picture.width+"px";
			new Effect.Appear(header,{
					duration: 1,
					queue:'end'
				});
			window.clearInterval(fluff.timer);
		}
	},
	init: function() {
		if(!document.getElementById || !document.createTextNode) { return; }
		// retrieve class name of the fluff element
		var fluff_el = $('fluff');
		if (fluff_el != null) {
			var fluff_name = fluff_el.className;
			if (fluff_name != "") {
				fluff.picture.src = "/images/"+fluff_name+".jpg";
				$('ir').hide();
				// periodically test that image is loaded
				fluff.timer = window.setInterval('fluff.render()', 500);
			}
		}
	}
};

// Hide all the elements with class .hide_js (including after an Ajax call)
var hide_elements = {
	hide_em: function() {
		// Hide all elements that are classed to be hidden by javascript
		var hides = $$('.hide_js');
		hides.invoke('hide');
		hides.invoke('removeClassName','hide_js');
		// Hide all the elements that are classed to be hidden by CSS. This means we don't need to hide them with JS before showing with JS :-P
		hides = $$('.hide');
		hides.invoke('hide');
		hides.invoke('removeClassName','hide');
	},
	show_em: function() {
		var shows = $$('.show_js');
		shows.invoke('show');
		shows.invoke('removeClassName','show_js');
	},
	auto_hide_em: function() {
		Ajax.Responders.register({
		  onComplete: function() {
		    hide_elements.hide_em();
		    hide_elements.show_em();
		  }
		});		
	},
	init: function() {
		this.hide_em();
		this.show_em();
		this.auto_hide_em();
	}
}

var modalbox = {
	id: 'modalbox',
	content_id: "modalbox_content",
	element: function() {
		return $(this.id);
	},
	exists: function() {
		if (this.element() != null) { 
			return true;
		} else {
			return false;
		}
	},
	liner_el: function() {
		if (this.exists()) { 
			return this.element().select('.liner').first();
		}
	},
	content_el: function() {
		if (this.exists()) { 
			return this.liner_el().select('.content').first();
		}
	},
	insert: function() {
		if (!this.exists()) {
			$($$('body').first()).insert({ 
				bottom: '<div id="' + this.id + '"><div class="liner"><div class="closebox"></div><div class="content"></div></div></div>'
			});
		}
	},
	clear: function() {
		
	},
	remove: function() {
		if (this.exists()) {
			this.element().remove();
		}
	},
	open: function() {
		fadebkgrnd.fade_in();
		this.insert();
		this.element().select('.closebox').invoke('observe', 'click', this.close.bind(this)).invoke('setStyle',{display: 'block'});
		var offsets = document.viewport.getScrollOffsets();
		var windowTopOffset = {marginTop: ((offsets.top + 50) + "px")};
		this.styler(windowTopOffset);
		this.loading();
	},
	close: function(e) {
		fadebkgrnd.fade_out();
		this.remove();
		e.stop();
	},
	loading: function() {
		this.content_el().update();
		this.styler({
			backgroundImage: 'url(/images/spinner-dialog-48px.gif)',
			height: '128px',
			width: '128px'
		});
	},
	stop_loading: function() {
		this.styler({
			backgroundImage: 'none',
			height: '',
			width: ''
		});
	},
	size_to: function(width, height) {
		this.styler({
			width: width,
			height: height
		});
	},
	styler: function(styles) {
		modalbox.liner_el().setStyle( styles );
	}
}

/* ##########################################################################
Copyright 2007 	Daniel Skinner
Contact: www.destiny-denied.co.uk/contact/

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

This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
GNU General Public License for more details.

You should have received a copy of the GNU General Public License
along with this program.  If not, see <http://www.gnu.org/licenses/>.
########################################################################### */

var ImageRoller = Class.create();

ImageRoller.prototype = {
	prefix: "image_roller_",
	loadCount: 0,
	imageCount: 0,
	initialize: function (c,options) {
		this.setOptions(options);
		this.outEvent=function(i){ return this.out.bindAsEventListener(this,i);}.bind(this);
		this.overEvent=function(i){ return this.over.bindAsEventListener(this,i);}.bind(this);
		this.imageCount = $A($$("img."+c)).length;
		$A($$("img."+c)).each(function(image) {
			Object.extend(image.parentNode.style,{backgroundRepeat:'no-repeat',cursor:'pointer',cursor:'hand',display:'block',width:image.width+'px',height:image.height+'px'});
			var temp={};
			if (image.parentNode.style && image.parentNode.style.backgroundImage) {
  		  var re = new RegExp("[(](.*)[)]");
  		  temp.src = re.exec(image.parentNode.style.backgroundImage)[1];
  			temp.ele=image;
  			var rollImage = new Image();
  			Event.observe(rollImage,'load',this.applyBehaviours.bindAsEventListener(this,temp,rollImage));	
  			rollImage.src=temp.src;	
  		} else {
  		  this.imageCount--;
  		}
		}.bind(this));	
	},
	//Private Initialisation
	setOptions: function(options) {
		this.options = Object.extend({
      onComplete:function(){},
      duration:0.1
    },(options || {}));
	},
	applyBehaviours: function(e,temp,rollImage) {
	  //apply event handling
		Event.observe(temp.ele, 'mouseover', this.overEvent(temp));
		Event.observe(temp.ele, 'mouseout', this.outEvent(temp));
		//add to the loaded image count
		this.loadCount++;
		//check if this was the last loaded image
		if (this.loadCount == this.imageCount) this.options.onComplete();
	},
  out: function(e,temp) {
			new Effect.Opacity(temp.ele,{duration:this.options.duration, from:0.0, to: 1.0,queue:{position:'end',scope:'sc'+temp.src,limit:2}});  
			Event.stop(e);
  },
  over: function(e,temp) {
			new Effect.Opacity(temp.ele,{duration:this.options.duration, from:1.0, to:0.0,queue:{position:'end',scope:'sc1'+temp.src,limit:2}});   
			Event.stop(e);
  }
}

// Track clicks on external links
var external_page_track = {
	init: function() {
		$$('.external_link').each( function(link) {
			link.observe('click', function(event){
				if(typeof _gaq != 'undefined') {
					_gaq.push(['_trackPageview', this.readAttribute('href')]);
				}
			});
		});
	}
}

var user_signup_form = {
	signup_wrap_id: 'user_signup_form_wrap',
	overlay_id: 'user_signup_form_overlay',
	init: function() {
		if (this.exists()) {
			this.signup_form_el().observe('submit', this.submit_handler.bindAsEventListener(this));
		}
	},
	exists: function() {
		if (this.signup_form_el() != null) { return true; }
	},
	signup_form_el: function() {
		if ($(this.signup_wrap_id) != null) {
			return $(this.signup_wrap_id).down('form');
		}
	},
	submit_handler: function(e) {
		var form = this.signup_form_el();
		this.show_overlay();
		new Ajax.Request(form.readAttribute('action'), { 
			asynchronous:true, 
			evalScripts:true, 
			method:'post', 
			parameters:Form.serialize(form)
		});
		Event.stop(e);
	},
	show_overlay: function() {
		this.set_overlay_size();
		$(this.overlay_id).show();
	},
	set_overlay_size: function() {
		var dimensions = this.signup_form_el().getDimensions();
		$(this.overlay_id).setStyle({width:dimensions.width + 'px', height:dimensions.height + 'px'});
	}
}

// build radio_select lists using this HTML structure:
// <ul class="radio_select">
//     <li class="radio_select_item">
//         <label class="radio_select_label">
//             <span class="radio"><input type="radio"></span>
//             <span class="radio_select_content">Item name/content</span>
//         </label>
//     </li>
//     <li…
// </ul>
var radio_selects = {
	radio_select_css: '.radio_select',
	radio_select_els: null,
	init: function() {
		this.observe_els();
		this.handle_responders();
	},
	observe_els: function() {
		this.radio_select_els = $$(this.radio_select_css);
		this.radio_select_els.each( function(rs) {
			rs.observe('click', this.update_item_state.bindAsEventListener(this));
		}.bind(this));
	},
	update_item_state: function(e) {
		var rs = e.findElement(this.radio_select_css);
		var inputs = rs.select('input');
		inputs.each( function(input) {
			if (input.getValue() != null) {
				input.up('.radio_select_item').addClassName('selected');
			} else {
				input.up('.radio_select_item').removeClassName('selected');
			}
		});
	},
	handle_responders: function() {
		Ajax.Responders.register({
			onComplete: function() {
				$$(radio_selects.radio_select_css).each( function(rs) {
					rs.stopObserving('click');
				});
				radio_selects.observe_els();
			}
		});
		
	}
}

var popovers = {
	popover_css: '.popover',
	popover_els: null,
	init: function(){
		this.observe_popovers();
		this.handle_responders();
	},
	observe_popovers: function() {
		this.popover_els = this.get_popover_els();
		this.popover_els.each( function(po) {
			new PopOver(po);
		});
	},
	get_popover_els: function(){
		return $$(this.popover_css + ":not(.pop_over_done)" );
	},
	handle_responders: function() {
		Ajax.Responders.register({
			onComplete: this.observe_new_popovers.bind(this)
		});
	},
	observe_new_popovers: function() {
		this.observe_popovers();
	}
}

var PopOver = Class.create({
	popover_css: '.popover',
	popoverbox_css: '.popoverbox',
	popoverliner_css: '.popoverliner',
	popovercontent_css: '.content',
	popover_el: null,
	popoverbox_el: null,
	include_closebox: true,
	event_name: 'click',
	the_event: null,
	initialize: function(el) {
		this.popover_el = $(el);
		this.set_up_observers();
	},
	set_up_observers: function() {
	if (this.popover_el.readAttribute('data-popovereventname') != null) { 
		this.event_name = this.popover_el.readAttribute('data-popovereventname');
	}
	if (this.event_name == 'hover') {
		this.popover_el.observe('mouseenter', this.do_open.bindAsEventListener(this));
		this.popover_el.observe('mouseleave', this.do_close.bindAsEventListener(this));
		this.popover_el.observe('click', this.do_close.bindAsEventListener(this));
		this.include_closebox = false;
	} else {
		this.popover_el.observe(this.event_name, this.click_handler.bindAsEventListener(this));
	}
	this.popover_el.addClassName('pop_over_done');
	},
	do_open: function(e) {
		this.the_event = e;
		this.open_box();
		this.create_box_el();
		this.load_content();
		e.stop();
	},
	do_close: function(e) {
		this.the_event = e;
		this.close_box();
		e.stop();
	},
	click_handler: function(e) {
		if (this.is_open()) {
			this.do_close(e);
		} else {
			this.do_open(e);
		}
	},
	create_box_el: function() {
		this.popoverbox_el = new Element('div', { 'class': 'popoverbox loading' }).update(
			new Element('div', { 'class': 'popoverliner' }).update(
				this.closebox_el()
			).insert( new Element('div', { 'class': 'content' }) )
		);
		$($$('body').first()).insert({ bottom: this.popoverbox_el });
		this.popovercontent_el = this.popoverbox_el.down(this.popovercontent_css);
		if (this.popover_el.readAttribute('data-popoverwidth') != null) { 
			this.styler({ width: this.popover_el.readAttribute('data-popoverwidth') });
		}
		this.center_box();
		this.popoverbox_el.select('.closebox').invoke('observe', 'click', function(e) {
			this.close_box();
		}.bind(this));
	},
	load_content: function() {
		var source = this.popover_el.readAttribute('data-source');
		if (source == null) {
			var url = this.popover_el.readAttribute('href');
			if (url == null) {
				url = this.popover_el.readAttribute('data-href');
			}
			this.load_request = new Ajax.Request(url, {
				method: 'get',
				onCreate: this.load_content_on_create.bind(this),
				onSuccess: this.load_content_on_success.bind(this)
			});
		} else {
			this.popovercontent_el.update($(source).innerHTML);
			this.stop_loading();
		}
	},
	load_content_on_create: function() {
		this.popover_el.addClassName('loading');
	},
	load_content_on_success: function(response) {
		this.popovercontent_el.update(response.responseText);
		this.stop_loading();
	},
	stop_loading: function() {
		this.popover_el.removeClassName('loading');
		this.popoverbox_el.removeClassName('loading');
		this.center_box();
		this.popoverbox_el.select('.closebox').invoke('show');
	},
	close_box: function() {
		this.popover_el.removeClassName('open');
		try {
			this.popoverbox_el.remove();
		} catch(e){}
	},
	open_box: function() {
		this.popover_el.addClassName('open');
	},
	is_open: function() {
		if (this.popover_el.hasClassName('open')) { return true }
	},
	styler: function(styles) {
		this.liner_el().setStyle( styles );
	},
	liner_el: function() {
		return this.popoverbox_el.select('.popoverliner')[0];
	},
	closebox_el: function() {
		if (this.include_closebox == true) { 
			return new Element('div', { 'class': 'closebox', 'style': 'display:none;' }) 
		}
	},
	center_box: function() {
		try {
			var offset_left = (-(this.popoverbox_el.getWidth() / 2) + (this.popover_el.getWidth() / 2));
			var offset_top = (this.popover_el.getHeight());
			$(this.popoverbox_el).clonePosition(this.popover_el, { 'setWidth':false, 'setHeight':false, 'offsetLeft':offset_left, 'offsetTop':offset_top });
		} catch(e){
			this.center_on_point(this.the_event.pointerX(),this.the_event.pointerY());
		} // Handle exceptions in IE7/8 gracefully
	},
	center_on_point: function(x,y) {
		var offset_left = (-(this.popoverbox_el.getWidth() / 2));
		var offset_top = (this.popover_el.getHeight());
		this.popoverbox_el.setStyle({ top: (y+offset_top) + "px", left: (x+offset_left) + "px" });
	}
});


var concertinas = {
	concertina_selector: '.concertina',
	concertina_done_class: 'concertina_done',
	concertina_els: null,
	init: function() {
		this.observe_concertinas();
		this.handle_responders();
	},
	observe_concertinas: function() {
		this.concertina_els = this.get_concertina_els();
		this.concertina_els.each( function(c) {
			new Concertina(c);
		});
	},
	get_concertina_els: function(){
		var selector = this.concertina_selector + ":not(." + this.concertina_done_class + ")";
		return $$(selector);
	},
	handle_responders: function() {
		Ajax.Responders.register({
			onComplete: this.observe_concertinas.bind(this)
		});
	}
}
var Concertina = Class.create({
	concertina_id: '',
	concertina_selector: '.concertina',
	concertina_done_class: 'concertina_done',
	concertina_el: null,
	initialize: function(el) {
		this.concertina_el = $(el);
		this.set_up_observers();
	},
	set_up_observers: function() {
		this.concertina_el.select('.concertina_title').invoke('observe','click', this.click_handler.bindAsEventListener(this));
		this.concertina_el.addClassName(this.concertina_done_class);
	},
	click_handler: function(e) {
		var el = e.findElement('.concertina_title');
		if (el != undefined) {
			var pane = el.up('.concertina_pane');
			this.toggle_pane(pane);
		}
		e.stop();
	},
	toggle_pane: function(el) {
		el.toggleClassName('closed');
	},
	set_current_title: function(el) {
		this.close_all_panes();
		el.up('li').addClassName('current');
	},
	close_all_panes: function() {
		this.concertina_el.select('li').invoke('removeClassName', 'current');
	},
	set_current_content: function(el) {
		var source = el.readAttribute('data-content');
		this.close_all_content();
		$(source).addClassName('current');
	},
	close_all_content: function() {
		this.concertina_el.select('li').invoke('removeClassName', 'current');
	}
	
});


var tab_boxes = {
	tab_box_selector: '.tab_box',
	tab_box_done_class: 'tab_box_done',
	tab_box_els: null,
	init: function() {
		this.observe_tab_boxes();
		this.handle_responders();
	},
	observe_tab_boxes: function() {
		this.tab_box_els = this.get_tab_box_els();
		this.tab_box_els.each( function(tb) {
			new TabBox(tb);
		});
	},
	get_tab_box_els: function(){
		var selector = this.tab_box_selector + ":not(." + this.tab_box_done_class + ")";
		return $$(selector);
	},
	handle_responders: function() {
		Ajax.Responders.register({
			onComplete: this.observe_tab_boxes.bind(this)
		});
	}
}

var TabBox = Class.create({
	tab_box_id: '',
	tab_box_selector: '.tab_box',
	tab_box_done_class: 'tab_box_done',
	tab_box_el: null,
	initialize: function(el) {
		this.tab_box_el = $(el);
		this.tab_box_id = this.tab_box_el.identify();
		this.set_up_observers();
	},
	set_up_observers: function() {
		this.tab_box_el.down('.tab_box_tabs').observe('click', this.click_handler.bindAsEventListener(this));
		this.tab_box_el.addClassName(this.tab_box_done_class);
	},
	click_handler: function(e) {
		var el = e.findElement('a');
		if (el != undefined) {
			if (!el.up('li').hasClassName('current')) {
				this.switch_to_tab(el);
			}
		}
		e.stop();
	},
	switch_to_tab: function(el) {
		this.set_current_content(el);
		this.set_current_tab(el);
	},
	set_current_tab: function(el) {
		this.close_all_tabs();
		el.up('li').addClassName('current');
	},
	close_all_tabs: function() {
		this.tab_box_el.select('.tab_box_tabs > li').invoke('removeClassName', 'current');
	},
	set_current_content: function(el) {
		var source = el.readAttribute('data-content');
		this.close_all_content();
		$(source).addClassName('current');
	},
	close_all_content: function() {
		this.tab_box_el.select('.tab_box_content > li').invoke('removeClassName', 'current');
	}
	
});

// Observes links (including after Ajax loads) for class and loads modalbox with experience search form as required.
// Watches for an experience search form in the page and handles focus,blur etc
// Watches for submits of the experience search form and drops them.
var experience_search_form = {
	id: 'experience_search_form_wrap',
	experience_search_form_id: 'experience_search_form',
	experience_search_form: null,
	experience_search_link_css: '.experience_search_link',
	default_experience_search_field_text: 'Start typing here to begin searching',
	element: function() {
		return $(this.id);
	},
	init: function() {
		this.handle_observers();
		this.handle_responders();
	},
	handle_responders: function() {
		Ajax.Responders.register({
			onComplete: this.handle_observers.bind(this)
		});
	},
	handle_observers: function() {
		this.observe_links();
		this.observe_search_form();
	},
	observe_links: function() {
		// Only observe links that have not already been observed ie. marked as 'experience_search_link_done'.
		$$( this.experience_search_link_css + ":not(.experience_seach_link_done)" ).each( function(link){
			link.observe("click", this.show.bindAsEventListener(this));
			link.addClassName('experience_seach_link_done');
		}.bind(this));
	},
	show: function(e) {
		var el = e.findElement('a');
		var url = "/search/experience_select";
		url = url + "?destination=" + encodeURIComponent(el.readAttribute('href'));
		
		modalbox.open();
		modalbox.liner_el().addClassName('dialog');
		modalbox.content_el().writeAttribute({ id: this.id });

		new Ajax.Updater(modalbox.content_el(), url, {
			asynchronous:true, 
			evalScripts:true, 
			method: 'get', 
			onComplete: this.after_form_load.bind(this)
		});
		Event.stop(e);
	},
	after_form_load: function() {
		modalbox.stop_loading();
	},
	observe_search_form: function() {
		if (this.experience_search_form_exists()) {
			var search_input = $(this.experience_search_form_id).down('#experience_name');
			search_input.writeAttribute("autocomplete","off"); // no browser supplied autocomplete
			
			if ($F(search_input) == "") {
				search_input.writeAttribute('value',this.default_experience_search_field_text)
				search_input.up('.search-wrapper').addClassName('blurred');
			};
			
			search_input.observe('focus', this.focus_on_experience_search_field.bindAsEventListener(this));
			search_input.observe('blur', this.blur_on_experience_search_field.bindAsEventListener(this));
			
			$(this.experience_search_form_id).observe('submit', this.handle_submit.bindAsEventListener(this));
		}
	},
	experience_search_form_exists: function() {
		if ($(this.experience_search_form_id) != null) { return true; }
	},
	focus_on_experience_search_field: function(e){
		el = e.element();
		if (el.value == '' || el.value == this.default_experience_search_field_text) {
			el.up('.search-wrapper').removeClassName('blurred');
			el.value = '';
		}
	},
	blur_on_experience_search_field: function(e){
		el = e.element();
		if (el.value == '' || el.value == this.default_experience_search_field_text) {
			el.up('.search-wrapper').addClassName('blurred');
			el.value = this.default_experience_search_field_text;
		}
	},
	handle_submit: function(e) {
		e.stop(); // the field observer inline in the form handles form interaction
	}
}

// Handles observers on review form related links.
// Handles behaviour of rating options in the review form.
var review_form = {
	id: 'review_form',
	review_form_link_css: ".review_form_link",
	element: function() {
		return $(this.id);
	},
	new_review_form_link_els: function() {
		return $$(this.review_form_link_css);
	},
	new_review_form_link_els_that_are_not_handled: function() {
		return $$(this.review_form_link_css + ":not(.review_form_link_done)");
	},
	init: function() {
		this.handle_observers();
		this.handle_responders();
	},
	handle_responders: function() {
		Ajax.Responders.register({
			onComplete: this.handle_observers.bind(this)
		});
	},
	handle_observers: function() {
		this.observe_new_review_form_links();
		this.observe_rating_options();
	},
	observe_new_review_form_links: function() {
		this.new_review_form_link_els_that_are_not_handled().each( function(link) {
			link.observe("click", this.show.bindAsEventListener(this));
			link.addClassName('review_form_link_done');
		}.bind(this));
	},
	show: function(e) {
		var el = Event.element(e);
		var url = el.readAttribute('href');
		var method = 'get';
		if (el.hasClassName('delete')) { method = 'delete' }
		
		modalbox.open();
		modalbox.liner_el().addClassName('dialog');
		modalbox.content_el().writeAttribute({ id: this.id });
		
		new Ajax.Updater(modalbox.content_el(), url, {
			asynchronous:true, 
			evalScripts:true, 
			method: method, 
			onComplete: this.after_form_load.bind(this)
		});
		Event.stop(e);
	},
	after_form_load: function() {
		modalbox.stop_loading();
	},
	observe_rating_options: function() {
		if (this.rating_options_exists()) {
			var rating_options = $('rating_options');
			if (!rating_options.hasClassName('rating_options_done')) {
				rating_options.observe('click', this.update_rating_state.bind(this));
				rating_options.addClassName('rating_options_done');
			};
			this.update_rating_state();
		}
	},
	update_rating_state: function() {
		$('rating_options').select('label').each( function(label) {
			label.removeClassName('selected');
			if (label.down('input').checked) {
				label.addClassName('selected');
			};
		});
	},
	rating_options_exists: function() {
		if ($('rating_options') != null) { return true; }
	}
};


var PolymorphicSelect = Class.create({
	initialize: function(type_select, id_select, selects) {
		this.id_select_id = $(id_select).identify();
		this.selects = selects;
		this.type_select = $(type_select);
		this.type_select.observe('change', this.replace_id_select_on_change.bindAsEventListener(this));
		this.insert_id_select(this.type_select.getValue());
	},
	replace_id_select_on_change: function(e) {
		var type_select = e.element();
		this.insert_id_select(type_select.getValue());
	},
	insert_id_select: function(value) {
		var new_id_select = this.selects.get(value);
		var old_id_select = $(this.id_select_id);
		if (old_id_select != null) {
			old_id_select.replace( new_id_select );
		} else {
			this.type_select.up().insert({ after: new_id_select });
		}
	}
});

/* ########################################################################## */

document.observe('dom:loaded', function() {
	logo.init();
	fluff.init();
	allMenus = new Hash();
	allMenus.navbar = new Menu("navbar", true);
	allMenus.menubar = new Menu("menubar", true);
	noozeelend.init();
	search.init();
	hide_elements.init();
	radio_selects.init();
	popovers.init();
	tab_boxes.init();
	concertinas.init();
	external_page_track.init();
	user_signup_form.init();
	experience_search_form.init();
	review_form.init();
	try{Typekit.load();}catch(e){}
});
