
// extend Prototype library by adding some new methods for Element
// define custom methods
var customMethods = {
	resizeToPage: function(element) {
		var pg = $(document.body).getDimensions(); // page height
		var vp = $(document.viewport).getDimensions(); // viewport height
		// always use the greater of the two
		//var new_w = (pg.width >= vp.width)?pg.width:vp.width;
		var new_h = (pg.height >= vp.height)?pg.height:vp.height;
		$(element).setStyle({
			//width: new_w + 'px',
			width: '100%',
			height: new_h + 'px'
		});
		return $(element);
	},
	
	resizeToViewport: function(element, margin) {
		var vp = $(document.viewport).getDimensions(); // viewport dimensions
		var less = margin*2;
		$(element).setStyle({
			width: vp.width - less + 'px',
			height: vp.height - less + 'px'
		});
		return $(element);
	},
	
	centerInViewport: function(element, animation) {
		var vp = $(document.viewport).getDimensions();
		var el = $(element).getDimensions();
		var el_left = Math.round((vp.width - el.width)/2);
		var el_top = Math.round((vp.height - el.height)/2);
		
		// we are assuming that the position is fixed
		
		// if there is an animation parameter then slide the object in to the center position from one of the browser edges
		// possible values are "left" and "top"
		if (animation == "left" || animation == "top") {
			if (animation == "left") {
				$(element).setStyle({
					left: -el.width + 'px',
					top: el_top + 'px'
				});
			}
			if (animation == "top") {
				$(element).setStyle({
					left: el_left + 'px',
					top: -el.height + 'px'
				});
			}
			new Effect.Move(element, {
				x: el_left,
				y: el_top,
				mode: 'absolute',
				duration: 2,
				queue: 'start'
			});
		// no animation
		} else {
			$(element).setStyle({
				left: el_left + 'px',
				top: el_top + 'px'
			});
		}
		return $(element);
	}
	
}
// apply custom methods
Element.addMethods(customMethods);



//////////////////////////////////////////////////////////////////////////////////

// some special classes. namespace with my initials SDG

if (!SDG) var SDG = {};




//////////////////////////////////////////////////////////////////////////////////

// CAROUSEL CLASS

if (!SDG.carousel) SDG.carousel = {};
SDG.CAROUSELS = new Hash(); // global hash is an associative array of CAROUSEL objects, indexed by content_src

SDG.carousel = Class.create({
	initialize: function(id, options) {
		var CAR = this;
		
		// expecting the id of the carousel container or the object itself
		this.container = $(id);
		this.id = this.container.identify(); // get id if present or generate one if missing.
		
		// use default options as base and overwrite as desired with options param
		this.options = Object.extend(Object.extend({ },this.default_options), options || { });
		
		this.is_playing = this.options.default_is_playing; // boolean status for if slide show is playing or not.
		this.is_in_transition = false; // flag for when slides are busy changing
		this.play_timer = false; // used to store the periodical executer function for play
		
		this.btn_previous = this.container.down('.previous');
		this.btn_previous.observe('click', function(event) {
			Event.stop(event);
			//console.log("click previous");
			if (false == this.is_in_transition) this.go_back();
		}.bind(this));
		this.btn_next = this.container.down('.next');
		this.btn_next.observe('click', function(event) {
			Event.stop(event);
			//console.log("click next");
			if (false == this.is_in_transition) this.go_forward(true);
		}.bind(this));
		
		// the slider containing all the slides
		this.slider = this.container.down('.slides');
		
		// get an array of slides
		this.slides = this.container.select('.slide');
		
		// count how many there are
		this.total_slides = this.slides.size();
		
		
		if (this.options.dots) {
			this.dot_list = new Element('ul', { 'class':'dots' });
			this.container.insert(this.dot_list);
			//this.dots = new array();
		}
		
		this.current_slide_number = 1;
		this.current_slide = this.slides[this.current_slide_number - 1];
		this.slide_width = this.current_slide.getWidth(); // get width from the first slide
		
		this.slides.each( function(slide, index) {
			if (CAR.options.transition == 'fade') {
				slide.setStyle({
					display: (index == 0) ? 'block' : 'none',
					opacity: (index == 0) ? 1 : 0,
					'zIndex': (index == 0) ? 3 : 2
				});
				//console.log("slide ", index);
			}
			// else default 'move' transition: go through and position all of the slides
			else {
				slide.setStyle({
					display: 'block',
					left: (CAR.slide_width * index) + 'px'
				});
			}
			
			if (this.options.dots) {
				
				//console.log('index: ', index);
				
				// generate a thumbnail "dot" for each slide and attach events
				var dot = new Element('li', { 'class':'dot' });//.update(index + 1);
				if (index == 0) dot.addClassName('selected');
				dot.observe('click', function(event) {
					Event.stop(event);
					this.go_to_slide(index + 1);
				}.bind(this));
				this.dot_list.insert(dot);
				//this.dots[index] = dot;
			}
			
			
		}.bind(this));
		
		this.countdown = this.options.delay;
		
		SDG.CAROUSELS.set(this.id, CAR);
		
		if (this.options.is_auto_play) {
			this.play(); // start the carousel
		}
		
		
		
	},
	
	// default options: any of these can be passed in as parameters to override the defaults
	default_options: {
		is_auto_play: true, // boolean for if slide show is playing by default
		delay: 10, // integer for how long to wait (in seconds) before moving to the next slide
		transition: 'move', //  possible: 'fade', or 'move'
		transition_duration: 1, // in seconds
		dots: false
	},
	
	play: function() {
		this.is_playing = true;
		
		// every second, countdown by one and call go_forward().
		// Do nothing if slide show is paused or in transition
		this.play_timer = new PeriodicalExecuter( function() {
			if (false == this.is_in_transition && this.is_playing) {
				this.countdown--;
				//console.log("countdown:", this.countdown);
				this.go_forward(); // do not reset timer when going forward
			}
		}.bind(this), 1);
	},
	
	pause: function() {
		this.is_playing = false;
	},
	
	go_forward: function(is_manual) {
		if ( (this.is_playing && this.countdown <= 0 ) || is_manual) {
			//console.log("going forward");
			
			this.countdown = this.options.delay; 
			//console.log("reset countdown");
			
			// go to the next slide
			var csn = this.current_slide_number;
			if (csn != this.total_slides) { csn++; } else { csn = 1; }
			this.go_to_slide(csn, 'forward');
		}
	},
	
	go_back: function() {
		//console.log("going back");
		
		// if playing, pause and reset it
		this.countdown = this.options.delay; 
		//console.log("reset countdown");
		
		// go back to the last slide
		var csn = this.current_slide_number;
		if (csn != 1) { csn--; } else { csn = this.total_slides; }
		this.go_to_slide(csn, 'back');
	},
	
	// called by both go_forward() and go_back()
	// allows you to jump to any slide
	go_to_slide: function(slide_number, direction) {
		CAR = this;
		
		// check that the slide number is legit
		if (1 <= slide_number <= this.total_slides) {
						
			this.next_slide = this.slides[slide_number - 1];
			
			// now check direction (only matters for the move animation)
			if (!direction) var direction = (this.current_slide_number < slide_number) ? 'forward' : 'back';
			
			// reset the countdown
			this.countdown = this.options.delay;
			
			// if using dots, select the new one
			if (this.options.dots) {
				var dots = this.dot_list.select('li');
				dots.invoke('removeClassName', 'selected');
				dots[slide_number - 1].addClassName('selected');
			}
			
			// do the fade transition
			if (this.options.transition == 'fade') {
				//console.log("'fade' transition");
				
				new Effect.Parallel([
					new Effect.Opacity(CAR.current_slide, { sync: true, from: 1, to: 0 }), 
					new Effect.Opacity(CAR.next_slide, { sync: true, from: 0, to: 1 }) 
					], { 
					duration: CAR.options.transition_duration,
					beforeStart: function() {
						CAR.is_in_transition = true; // countdown is paused while slides are in transition
						//console.log("slides are in transition");
						CAR.next_slide.setStyle({
							display: 'block',
							opacity: 0
						});
					},
					afterFinish: function() {
						CAR.current_slide.setStyle({ display:'none', 'zIndex': 2 });
						CAR.next_slide.setStyle({ display:'block', 'zIndex': 3 });
						
						// now set the new current slide
						CAR.current_slide_number = slide_number;
						CAR.current_slide = CAR.slides[CAR.current_slide_number - 1];
						CAR.is_in_transition = false; // allow countdown to proceed again
						//console.log("slides are no longer in transition");
						this.countdown = CAR.options.delay; // make sure we get a full countdown
					},
					queue: { position: 'end', scope: 'slideshowscope' }
				});
			}
			// default transition ("move")
			else {
				//console.log("'move' transition");
				
				new Effect.Parallel([
						new Effect.Move(CAR.current_slide, { 
							sync: true,
							mode: 'absolute',
							x: (direction == 'forward') ? -CAR.slide_width : CAR.slide_width,
							y: 0
						}), 
						new Effect.Move(CAR.next_slide, { 
							sync: true, 
							mode: 'absolute',
							x: 0,
							y: 0
						}) 
					], {
					duration: CAR.options.transition_duration,
					beforeStart: function() {
						// position the next slide
						CAR.next_slide.setStyle({ left: (direction == 'forward') ? CAR.slide_width + 'px' : -CAR.slide_width + 'px' });
						CAR.is_in_transition = true; // countdown is paused while slides are in transition
					},
					afterFinish: function() {
						// now set the new current slide
						CAR.current_slide_number = slide_number;
						CAR.current_slide = CAR.slides[CAR.current_slide_number - 1];
						CAR.is_in_transition = false; // allow countdown to proceed again
						this.countdown = CAR.options.delay; // make sure we get a full countdown
					},
					queue: { position: 'end', scope: 'slideshowscope' }
				});
				
				
			}
			//console.log("new current slide: ", slide_number);
			
		} else {
			alert("trying to go to a slide number that doesn't exist!");
		}
	}
	
});




//////////////////////////////////////////////////////////////////////////////////

// DROP DOWN MENU CLASS

if (!SDG.drop_down_menu) SDG.drop_down_menu = {};

SDG.drop_down_menu = Class.create({
	initialize: function(nav_menu, options) {
		var DDM = this;
		
		// id of the nav menu container or the object itself
		this.nav_menu = $(nav_menu);
		//this.id = this.container.identify(); // get id if present or generate one if missing.
		
		// use default options as base and overwrite as desired with options param
		this.options = Object.extend(Object.extend({ },this.default_options), options || { });
		
		// attach events
		// loop through each li element
		this.nav_menu.select('li').each(function(parent_li) {
			
			/*
			trying to prepopulate the style ob but it's not working
			
			var submenu = parent_li.down('ul.children');
			if (submenu) {
				submenu.style.display ='none';
			}
			*/
			
			parent_li.observe("mouseenter", function() {
				DDM.open_submenu(parent_li);
			});
			
			parent_li.observe("mouseleave", function() {
				DDM.close_submenu(parent_li);
			});
			
		});
		
	},
	
	// default options: any of these can be passed in as parameters to override the defaults
	default_options: {
		//is_auto_play: true, // boolean for if slide show is playing by default
		//delay: 10, // integer for how long to wait (in seconds) before moving to the next slide
		//transition: 'move' //  possible: 'fade', or 'move'
	},
	
	open_submenu: function(parent_li) {
		var DDM = this;
		var a = $(parent_li).down('a');
		var submenu = $(parent_li).down('ul.sub-menu');
		if (submenu) {
			if (!submenu.is_open) {
				submenu.is_open = true;
				// add a class to the parent li
				a.addClassName("hover");
				
				// ie8 can't clone position unless element is visible
				submenu.setStyle({display:'block'});
				
				submenu.clonePosition($(parent_li), {
					setWidth:false,
					setHeight:false,
					offsetTop: $(parent_li).getHeight() + 1
				});
				
				// open the submenu with an animation effect
				
				
				
				// ***
				// before we can use this animation stuff, we need to figure out how to write style="display:none;" inline
				// into the ul.children elements
				//Effect.BlindDown(submenu, {duration:0.33, scaleContent:false});
				//submenu.show();
			}
		}
	},
	
	close_submenu: function(parent_li) {
		var DDM = this;
		var a = $(parent_li).down('a');
		var submenu = $(parent_li).down('ul.sub-menu');
		if (submenu) {
			submenu.is_open = false;
			// add a class to the parent li
			a.removeClassName("hover");
			// open the submenu with an animation effect
			submenu.setStyle({display:'none'});
			//Effect.BlindDown(submenu, {duration:0.5});
			//submenu.hide();
		}
	}
	
});






//////////////////////////////////////////////////////////////////////////////////

// MAGIC LABEL CLASS

if(!SDG.magic_label) SDG.magic_label = {};
SDG.magic_label = Class.create({
	// constructor
	initialize: function(input_id) {
		this.input = $(input_id);
		this.label = this.input.previous('label');
		
		if (this.input.getValue() != '') this.label.hide();
		
		this.input.observe('focus', function() {
			this.label.hide();
		}.bind(this) );
		
		this.input.observe('blur', function() {
			if (this.input.getValue() == '') this.label.show();
		}.bind(this) );
		
		this.label.observe('click',function() {
			this.input.focus();
		}.bind(this) );
	}
});

