/*	Here I have created	an object with all my page functions and variables. Rather
		than just doing something like this:

function test(){
	....stuff
};

		I put my functions and variables in an object. This keeps all my code together 
		and tidy, but, more importantly, it keeps my variables and function namespaces
		out of the global namespace. So if I want a variable called "links" I don't
		have to worry about some other script overwriting what is otherwise a rather
		generic variable name.
		
var myPageNamespace = {
	test: function(){
		....stuff
	}
};

		Now I can reference my function as myPageNamespace.test().
		*/
var guide = {
/*	This function will find any div's on the page with the class "fxTarget"
		and make them draggable	*/
	setUpFxTargets: function(){
		/*	$$('div.fxTarget') returns an array of all the elements that match that
			  selector. Careful how you use this, as less efficient searches result
				in more CPU cycles for the user's browser.
				
				The array returned has numerous functions, and here I use .each to loop
				through them all. Other methods include .every, .some, and .map. Be sure
				to look at the docs for array and the examples in the Mootorial of how
				to use them.
					*/
		$$('div.fxTarget').each(function(target){
			/*	For each iteration through the loop, "target" is defined as each item in the array	*/
			target.makeDraggable();
			/*	and I make it draggable...	*/
		});
	},
	/*	showFxTarget is a function that takes a dom element and makes it visible	*/
	showFxTarget: function(target){
		/*	$() is like using document.getElementById, except it's shorter and it
				adds all the Mootools functions to the element returned.
				
				.setStyles let's me set numerous css properties at once...	*/
		$(target).setStyles({
			'display': 'block',
			'visibility':'visible'
		});
	},
	/*	makeAccordions finds all the accordion layouts on the page and makes an accordion
			for each one. If I wanted this function to be more useful, I might make the selector
			that is passed in a variable.	*/
	makeAccordions: function(){
		/*	find all the dl elements with the class "Accordion"	*/
		$$('dl.Accordion').each(function(el){
			/*	make a new accordion with the elements in the dl element.
			
			Element.getElements works like $$() does - it returns an array of
			elements that match that selector. Unlike $$(), getElements starts
			at the Element on which it's called so it acts like a filter.	*/
			new Accordion(el.getElements('dt.stretchtoggle'), el.getElements('dd.stretcher'));
		});
	},
	/*	Here we have a Fx.Slide menu for this page. This is kind of like the makeAccordions function
			above.	*/
	makeSlider: function(){
		/*	Here I'm using .map. Remember that $$() returns an array. .map lets me loop through
				the array, but each time I loop through an item, I return a value. .map takes all 
				those values and returns them as a new array. So, for example:
				
				[1,2,3].map(function(num){ return num*2 };
				
				That will return a new array: [2,4,6] 
				
				By using .map here, I can create a slider for each element I need to and get back
				an array of sliders that I'll use later. */
		this.sliders = $$('ul#sliderExample ul').map(function(ul){
			/*	Here we make the Fx.Slide object and return it.*/
			return new Fx.Slide(ul, {
				mode: 'horizontal'
			}).hide();
		});
		/*	Now I want to attach behaviors to other elements to open and close the slide menu.
		
				I get all the links I want to be click handles for the slide menu and loop 
				through them.
				
				.each, .map, .every, and the other iterators let you pass along both the element
				in the iteration and the index of that element in the array ("function (lnk, index)...")
					*/
		$$('ul#sliderExample a.slideOpener').each(function(lnk, index){
			/*	I want the user to click the link to open the menu, so I use addEvent to
					capture the click and execute my function.
					
					Let's talk about bind for a second. Above I saved an array of all the Fx.Slide
					objects as "this.sliders". "this" here refers to the parent object, which
					is my "guide" object that all my functions are a part of:
					
					var guide = {
						makeSlider: function(){...},
						makeAccordion: function(){...}
					};
					
					when I want to refer to a variable that's a member of my "guide" object, I can use
					"this".
					
					Whenever you have code that's part of a function, "this" refers to that parent element.
					But if that element has a childe member that's another function, "this" will be THAT
					function:
					
					var guide = {
						makeSlider: function(){
							//"this" here is the "guide" object
							[1,2,3].each(function(number){
								//"this" here is the function I declare
								//on the line above, not "guide"
							});
						}
					};
					
					So in order to preserve the "this"-ness, we have to use .bind(obj) to pass along
					the context of "this":
					
					var guide = {
						makeSlider: function(){
							[1,2,3].each(function(number){
								//this here is now "guide"
							}, this); //.each, .map, etc. take a second argument, the thing 
												//to bind "this" to
							$(element).addEvent('click', function() {
								//this here is now "guide"
							}.bind(this)); //addEvent does NOT take a second argument, so we
												//call .bind on it explicitly.
						}
					};
						*/
			lnk.addEvent('click', function(){
				/*	When the user clicks on of my menu items, we loop through all the sub-menus
						to hide any others that are open and to toggle the one they clicked
						
						here we refer to this.sliders - the array we created above. the "this"
						here is the "guide" object, but we're inside a function declared in the
						line above, so we have to use .bind() to pass the "this" along.
					*/
				this.sliders.each(function(slider, sliderIndex){
					/*	If the index of the slider we're on is the index of the menu item
							the user clicked, toggle the slider	*/
					if (sliderIndex == index) this.sliders[sliderIndex].toggle();
					/*	otherwise, let's hide the slider that they didn't click	*/
					else this.sliders[sliderIndex].slideOut();
				}, this); /*	Here's the bind "this" for .each	*/
			}.bind(this)); /*	and here's the explicit .bind(this) for .addEvent's function	*/
		}, this); /* and this is the last .each, so it has a "this" too	*/
	},
	/*	finally, I collect all the functions I want to call on pageload to keep things tidy.
			I could also just list these in the domReady call I make just past it, but I like to
			keep them like this so I can call them again if I need to.
		*/
	makeSlideShows: function() {
		new SimpleImageSlideShow({
		  startIndex: 0,
		  imgUrls: ['http://download.com/i/dl/media/dlimage/10/87/78/108778_medium.jpeg',
		'http://download.com/i/dl/media/dlimage/10/87/79/108779_medium.jpeg',
		'http://download.com/i/dl/media/dlimage/10/87/81/108781_medium.jpeg'],
		  container: 'screenShotImgs',
		  currentIndexContainer: 'imgNow',
		  maxContainer: 'imgMax',
		  nextLink: 'nextImg',
		  prevLink: 'prevImg'
		});
	},
	init: function(){
		this.makeSlideShows();
		this.makeAccordions();
		this.setUpFxTargets();
		this.makeSlider();
	}
};
/*	window.onDomReady will call my guide.init on page load, but the "this" will be the window, so
		I bind the guide to the function call explicitly. I wouldn't have this problem if I wrote it
		this way:

window.onDomReady(function()[
	guide.init();
});
		But that's more verbose than it needs to be.
		*/
window.onDomReady(guide.init.bind(guide));


/*	Here I've included a relatively simple class that I wrote for handling very, very simple slideshows.
		It's not fancy, but it's not meant to be.

~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
		Class: SimpleSlideShow
		Makes a very, very simple slideshow gallery with a collection of dom elements and previous and next buttons.

		Author:
		Aaron Newton
		
		Dependencies:
		mootools - 	<Moo.js>, <Utility.js>, <Common.js>, <Function.js>, <Array.js>, <String.js>, <Element.js>, <Fx.Base.js>, <Dom.js>, <Cookie.js>
		cnet - <element.cnet.js>
		
		Arguments:
		options - an object with key/value settings.
		
		Options:
		startIndex - (integer) the first image to show
		slides - (array) a collection of elements already in the dom.
		currentSlideClass - (string; optional) class to assign the currently visible slide; defaults to "currentSlide"
		currentIndexContainer - (dom element or id) container to display the the currently shown slide index
			(i.e. "showing *2* of 3"); optional
		maxContainer - (dom element or id) container to display the maximum number of slides available; optional
		nextImg - (dom element or id) image to capture clicks to show the next image; optional, but if 
			not supplied you'll have to execute <cycleForward> yourself.
		prevImg - (dom element or id) image to capture clicks to show the next image; optional, but if 
			not supplied you'll have to execute <cycleBack> yourself.
		wrap - (boolean) when the user clicks next at the end of a set, go back to the start 
			(and if they click prev at the begining, go to the end); defaults to true
		disabledClass - (string) class to add to next/prev links when there are no next or prev slides;
			defaults to "disabled"
		onNext - (function) callback for when the user clicks next; optional
		onPrev - (function) callback for when the user clicks prev; optional
		onSlideClick - (function) callback for when the user clicks a slide, this function will 
			be passed the slide clicked and the index of the slide. optional
		crossFadeOptions - (object) options object to be passed to the opacity effects.
		
		Example:
(start code)
new SimpleSlideShow({
  startIndex: 0,
	slides: $$('.slide'),
  currentIndexContainer: 'slideNow', //an element or it's id
  maxContainer: 'slideMax',
  nextLink: 'nextImg',
  prevLink: 'prevImg'
});
(end)
	*/
	
	var SimpleSlideShow = new Class({

	
	/*	This class makes use of the Options class. Down below you'll see a line:
	
			SimpleSlideShow.implement(new Options)
	
			The Options class handles merging default options with those the user
			passes in. This lets your class have a default "out of the box" behavior
			but also allows it to be flexible so that users can change what they need
			to.
		*/

		options: {
			startIndex: 0, //what image to start on; zero is the first
			slides: [], //by defining this array here, I don't have to worry about
									 //it being undefined below. it's either empty or it has
									 //values, but it's not undefined.
			currentIndexContainer: false, //these next two hold the number of slides and
																		//what number is visible
			maxContainer: false,
			nextLink: false, //here are two links or images to be used to cycle to the next
											//slide and previous slidee
			prevLink: false,
			wrap: true, //an option to let the user go 1,2,3 and then back to 1 
									//when there are no more slides
			disabledLinkClass: 'disabled', //if wrap isn't true, we have to do something to 
									//tell the user they've reached the end and can't go any futher
									//so I give the button a class when that happens
									
			/*	Down below you'll also see 
			SimpleSlideShow.implement(new Events)
			
			together with new Options, I can have events in my class that fire when things
			happen. Here I have 3 defined: onNext, onPrev, and onSlideClick
			
			This lets someone create a new gallery and then do something else when the user
			clicks next, previous, or clicks a slide. By adding these kinds of events, the
			gallery class can become much more robust when it needs to be because you can
			attach more functionality to it.
			
			Class.create() is basically an empty function. So these events will fire no matter
			what, it's just by default they don't do anything.
				*/
			onNext: Class.create(),
			onPrev: Class.create(),
			onSlideClick: Class.create(),
			/*	This class will use Fx.Style to crossfade between slides if Fx.Style is defined.
					
					This object is just a placeholder for options to pass to Fx.Style
				*/
			crossFadeOptions: {}
		},
		
		initialize: function(options){
			/*	the Options class has the function setOptions.
					this will merge the options passed in with the options I define above
					and also set up the events to fire later
				*/
			this.setOptions(options);
			/*	I save the slides passed in in an array	*/
			this.slides = this.options.slides;
			/*	set up each slide	*/
			this.makeSlides();
			/*	insert the counter values	*/
			this.setCounters();
			/*	set up the prev/next buttons	*/
			this.setUpNav();
		},
		/*	this function just updates the placeholders for the numbers of the images. i.e.:
				viewing 3 of 7
			*/
		setCounters: function(){
			if($(this.options.currentIndexContainer))$(this.options.currentIndexContainer).setHTML(this.now+1);
			if($(this.options.maxContainer))$(this.options.maxContainer).setHTML(this.slides.length);
		},
		/*	this function makes all the slides in the options	*/
		makeSlides: function(){
			/*	$pick returns the first argument if it's not undefined or null, 
					else the second argument is returned	*/
			this.now = $pick(this.now, this.options.startIndex);
			//hide them all
			this.slides.each(function(slide, index){
				if(index != this.now) slide.setStyle('display', 'none');
				else slide.setStyle('display', 'block');
				/*	set up the click event	*/
				this.makeSlide(slide);
			}, this);
		},
		/*	this is it's own function so it can be used at any time, not just on startup	*/
		makeSlide: function(slide){
			slide.addEvent('click', function(){ this.fireEvent('onSlideClick'); }.bind(this));
		},
		/*	here I set up the click events for the prev and next buttons	*/
		setUpNav: function(){	
			/*	next calls .cycleForward	*/
			if($(this.options.nextLink)) $(this.options.nextLink).addEvent('click', function(){
					this.cycleForward();
				}.bind(this));
			/*	prev calls .cycleBack	*/
			if($(this.options.prevLink)) $(this.options.prevLink).addEvent('click', function(){
					this.cycleBack();
				}.bind(this));
		},
/*	Property: cycleForward
		Shows the next slide.
	*/
		cycleForward: function(){
			/*	I keep track of which slide is visible so I know which one is "next"
				so, if this.now is defined and it's less than the length of the slides
				available, show the next slide
				*/
			if($type(this.now) && this.now < this.slides.length-1) this.showSlide(this.now+1);
			/*	if this.now is defined and we're ok to wrap around, then show the first one	*/
			else if($type(this.now) && this.options.wrap) this.showSlide(0);
			/*	otherwise this.now isn't defined, which means this is the first time we've called
			cycle, so show the default first slide	*/
			else this.showSlide(this.options.startIndex);
			/*	fire the event "onNext"; this function is in the Events class	*/
			this.fireEvent('onNext');
			/*	if this.now is at the end of the slide links and we're not wrapping	*/
			if(this.now == this.slides.length && !this.options.wrap && $(this.options.nextLink))
				/*	disable the next button	*/
				$(this.options.nextLink).addClass(this.options.disabledLinkClass);
			/*	otherwise remove that classname because we aren't at the end or we're wrapping	*/
			else if ($(this.options.nextLink)) $(this.options.nextLink).removeClass(this.options.disabledLinkClass);
		},
/*	Property: cycleBack
		Shows the prev slide.
	*/
		cycleBack: function(){
			/*	this is a lot like the above function; I'll let you figure it out.	*/
			if(this.now > 0) this.showSlide(this.now-1);
			else if(this.options.wrap) this.showSlide(this.slides.length-1);
			this.fireEvent('onPrev');
			if(this.now == 0 && !this.options.wrap && $(this.options.prevSlide))
				$(this.options.prevSlide).addClass(this.options.disabledLinkClass);
			else if ($(this.options.prevSlide)) 
				$(this.options.prevSlide).removeClass(this.options.disabledLinkClass);
		},
/*	Property: showSlide
		Shows a specific slide.
		
		Arguments:
		iToShow - (integer) index of the slide to show.
	*/
		showSlide: function(iToShow){
			/*	let's keep track of what slide we were on before we started	*/
			var now = this.now;
			/*	if there's an slide for the index we've been passed	*/
			if(this.slides[iToShow]) {
				/*	and we're not already showing that slide	*/
				if($type(this.now) && this.now != iToShow){
					/*	fade the current slide out
							this.slides is an array of slides. this.slides[this.now] is the current slide
							.effect creates a new Fx.Style, in this case opacity
							.start(0) will fade it to zero
							.chain will execute that function when the fade out is complete
						*/
					this.slides[this.now].effect('opacity', this.options.crossFadeOptions).start(0).chain(function(){
						/*	we have to set the display to none so the next slide can be in the same place	*/
						this.slides[now].hide();
						/*	now we show the slide that we're showing next
								set it to block so it's in place
								but set it's opacity to zero so it's invisible
							*/
						this.slides[now].hide();
						this.slides[iToShow].addClass(this.options.currentSlideClass).setStyles({
							'display':'block',
							'opacity':0
							/*	then use .effect to fade it in	*/
						}).effect('opacity', this.options.crossFadeOptions).start(1);
					}.bind(this)); /*	gotta bind that "this"	*/
				/*	else we're showing an slide for the first time so we don't have to fade
						anything out first. */
				} else this.slides[iToShow].setStyles({
							'display':'block',
							'opacity':0
						}).effect('opacity', this.options.crossFadeOptions).start(1);
				/*	update the "now" index	*/
				this.now = iToShow;
				/*	update the counters	*/
				this.setCounters();
			}
		},
		/*	this handles the slide click. I could have not made this a function
				of its own, but this way it allows future functionality to be implemented
				into this section.	*/
		slideClick: function(){
			this.fireEvent('onSlideClick', [this.slides[this.now], this.now]);
		}
	});

/*	Finally, I add the functionality of the Events and Options classes	*/
SimpleSlideShow.implement(new Events);
SimpleSlideShow.implement(new Options);

/*	Now we have a slideshow, but I want to make one specific to images, so I'm going to extend
		the class above to add some more specific functionality to it.	*/
		
/*	Class: SimpleImageSlideShow
		Extends <SimpleSlideShow> to make a slideshow of images.
		
		Arguments:
		options - a key/value options object; inherits options from <SimpleSlideShow>.
		
		Options:
		imgUrls - (array; optional) an array of image urls to add to the dom and to the slideshow
		imgClass - (string; optional) a class to add to the images that get created on the fly
		container - (element; optional) if you are adding images to the dom either using <addImg> or
			the imgUrls array above, then "container" is required to know where to put them.
	*/
	
	/*	Here I extend SimpleSlideShow	*/
	var SimpleImageSlideShow = SimpleSlideShow.extend({
		/*	Options here get merged with the options from the parent; that's how .extend works	*/
		options: {
			imgUrls: [],
			imgClass: 'screenshot',
			container: false
		},
		/*	initialize has the same name as a function in the parent class (SimpleSlideShow),
				so it overwrites it	*/
		initialize: function(options){
			/*	but I can call the .initialize function in the parent class by calling this.parent().
					note how I pass the options along, because the parent class expects these options.	*/
			this.parent(options);
			/*	this next line is executed after whatever happens in this.parent() (which is
					SimpleSlideShow.initialize()
					
					Here I add new images to the slideshow using the urls passed in.
					Even if the user didn't pass any in, this.options.imgUrls is still
					an array, because that's the default. If it's empty, .each just won't
					iterate.
						*/
			this.options.imgUrls.each(function(url){
				this.addImg(url);
			}, this); /*	note the binding	*/
			/*	and here I show the first slide (because addImg adds images and hides each one	*/
			this.showSlide(this.options.startIndex);
		},
/*	Property: addImg
		Adds a new image to the group
	*/
		addImg: function(url){
			/*	the container has to be defined in the options or else I don't know where to
					put the image	*/
			if($(this.options.container)) {
				/*	I create a new image...	*/
				var img = new Element('img').setProperties({
							'src': url,
							'id': this.options.imgClass+this.slides.length
							}).addClass(this.options.imgClass).setStyle(
							'display', 'none').injectInside($(this.options.container)).addEvent(
							'click', this.slideClick.bind(this));
				/*	let's break this chunk above down a bit:
				var img = new Element('img') //new image
				
				.setProperties({
							'src': url,
							'id': this.options.imgClass+this.slides.length
							}). //set the srce and id properties
							
				.addClass(this.options.imgClass) //add a class
				
				.setStyle('display', 'none') //hide it
				
				.injectInside($(this.options.container)) //put it in the container
				
				.addEvent('click', this.slideClick.bind(this)); //add a click event
					*/			

				/*	add this image to the array of slides	*/
				this.slides.push(img);
				/*	set up the slide	*/
				this.makeSlide(img);
				/*	update the counters	*/
				this.setCounters();
			}
		}
	});
/*	Now I have two classes, but I don't duplicate my effort. If I fix a bug in SimpleSlideShow I automatically fix it in any class that extends it.	*/


window.addEvent('domready', function(){
			$('myForm').addEvent('submit', function(e) {
				/**
				 * Prevent the submit event
				 */
				new Event(e).stop();
			
				/**
				 * This empties the log and shows the spinning indicator
				 */
				var log = $('log_res').empty().addClass('ajax-loading');
			
				/**
				 * send takes care of encoding and returns the Ajax instance.
				 * onComplete removes the spinner from the log.
				 */
				this.send({
					update: log,
					onComplete: function() {
						log.removeClass('ajax-loading');
					}
				});
			});
		}); 