
/*
Title: Meylah Scripts
Description: Slick, yet nifty. Javascript for the site
Version: 0.1
Author: Stress Limit Design (http://www.stresslimitdesign.com)
*/

/* use this function to log, console errors (if undefined) are addressed in js/config */
function log(x) { console.log(x); }

// Show sidebar tabs once whole page has loaded
window.addEvent('load', function() { Sidebar.start(); });

window.addEvent('domready', function() {

	autoFocus();
	makePopup($$('#email a'), $$('#email .popup'));
	setUpValidation( $('subscribeForm') );

	// set up post js effects
	if ( $$('.post') ) {
		postFx();
	}

	// set up StickyColumn
	if ( $(document.body).hasClass('twocolumn') ) {
		try {
			new StickyColumn();
		} catch(e) {
			// console.log(e);
		}
	}

	// set up captcha
  initCaptcha();

});

/*	==============================================================
		SITE WIDE
	============================================================*/

	/*
	Swap displayed text in input fields on focus. Default value is
	pulled from element's alt field and is also diplayed on blur.
	*/
	function autoFocus() {
		$$('input[type=text]', 'input[type=password]','textarea').each(function(input){
			var alt = input.get("alt");
			if(alt){
				var value = input.get("value");
				if (value == "") input.set("value", alt);
				input.addEvents({
					'focus': function(){ if (this.get('value') == alt) this.set("value", ""); },
					'blur': function(){ if (this.get('value') == "") this.set("value", alt);  }
				});
			}
		});
	}


	/*
	Link a button with an element to enable clicking to show/hide that
	element. (send to a friend, email form, store policy/FAQ)
	*/
	function makePopup(button, element, setOpen) {
		element.open = (setOpen ? false : true);			// element hash rulez!!
		button.addEvent('click', function() {
			if (element.open) {
				element.setStyle('display', 'none');
				element.open = false;
				this.setStyle('background-position','0 100%');
			} else {
				element.setStyle('display', 'block');
				element.open = true;
				this.setStyle('background-position','0 0');
			}
			return false;
		});
		button.fireEvent('click');
	}


	/*
	Animate the opening and closing of the tabs along the left side of
	the screen. If a different tab (than was clicked) is already open,
	close that one while opening the other
	*/
	var Sidebar = {
		tabs: [],
		activeTab: null,
		start: function() {
			Sidebar.tabs = $$('#sidebar .tab');
			Sidebar.tabs.each(function(tab) {
				tab.addEvent('click', function() { Sidebar.openTab(tab); });
			});
			Sidebar.calculateContainerSizes();
			Sidebar.repositionTabs();
			Sidebar.showTabs();
		},
		openTab: function(tab) {
			if (tab == Sidebar.activeTab) {		// If a tab is already open, close it
				Sidebar.closeTab(tab);
				return;  // We don't want to open it again so return
			}
			else if (Sidebar.activeTab != null) {
				Sidebar.closeTab(Sidebar.activeTab);
			}

			var container = tab.getParent();
			container.addClass('open');
			container.tween('margin-left', 0);
			Sidebar.activeTab = tab;			// This is now the open tab
		},
		closeTab: function(tab) {
			var container = tab.getParent();
			container.removeClass('open');
			container.addClass('closing');

			// Remove open class once animation has finished
			var tween = container.get('tween');
			var w = container.retrieve('w');

//			tween.start('margin-left', -container.getCoordinates()['width']).chain(function() {
			tween.start('margin-left', -w).chain(function() {
				container.removeClass('closing');
			});

			Sidebar.activeTab = null;			// No tabs are open so clear it
		},
		calculateContainerSizes: function() {
			var sidebarWidth = $('sidebar').getStyle('width').toInt();
			Sidebar.tabs.each(function(tab) {
				var container = tab.getParent();
				var content = container.getElement('.tab-content');

				if (Browser.Engine.trident && Browser.Engine.version == 5) {	// IE7
					content.setStyle('display','inline');
				}

				var size = content.getSize();
				var width = size.x;
				var height = size.y;

				// Check tab container isn't shorter than the tab itself
				var tabHeight = tab.getStyle('height').toInt();
				if (height < tabHeight)
					height = tabHeight;

				// Size and position the container
				container.setStyle('margin-left', -(width.toInt() + 20 + sidebarWidth));
				container.setStyle('padding-left', sidebarWidth);
				container.setStyle('height', height);
				container.setStyle('width', width + 20);

				container.setStyle('visibility', 'visible');

				// store width for later
				container.store('w', width + sidebarWidth + 20);

				// Mark this container as resized so it won't get done again
				container.store('resized', true);
			});
		},
		repositionTabs: function() {
			var tabBottom = 0;
			var tabsTop = 0;
			Sidebar.tabs.each(function(tab) {
				var container = tab.getParent();
				if (tabBottom != 0) {
					var containerTop = container.getCoordinates()['top'];

					container.setStyle('top', tabsTop - containerTop);    // set container top to be level with the first
					tab.setStyle('top', tabBottom - tabsTop);    // set tab top to be just below last tab

					// Check if the tab is lower than container and move container if so
					if (container.getCoordinates()['bottom'] < tab.getCoordinates()['bottom']) {
						var diff = tab.getCoordinates()['bottom'] - container.getCoordinates()['bottom'];
						container.setStyle('top', (tabsTop - containerTop) + diff);
						tab.setStyle('top', (tabBottom - tabsTop) - diff);
					}
				} else {
					tabsTop = container.getCoordinates()['top'];
				}
				tabBottom = tab.getCoordinates()['bottom'];
			});
		},
		showTabs: function(tab) {
			Sidebar.tabs.each(function(tab) {
				tab.tween('right', -38);
			});
			$('sidebar').setStyle('overflow','visible');
		}
	};


	/* For form buttons that should spin during submission */
	var WaitButton = new Class(
	{
		handle: null,
		state : null,
		initialize : function( handle )
		{
			this.handle = $(handle);
			var self = this;
			this.handle.addEvent('click', function(ev){self.wait();});
			this.handle.reset = function() { self.reset();};
		},
		wait : function()
		{
			this.state = this.handle.isDisplayed();
			var pos = this.handle.getPosition(this.handle.getParent());
			var size = this.handle.getSize();
			var yoffset = this.handle.getStyle('margin-top');
			var topstyle = this.handle.getStyle('top');
			if (topstyle =="0px") yoffset = 0;
			var lt = ( pos.x -17 + (size.x/2) ).toInt() + "px";
			var tp = pos.y + yoffset - (size.y/2);
			var el = new Element("div",{'class':'generic-spinner', 'styles':{ 'position':'absolute', 'left':lt, 'top':tp}});
			el.fade('out');
			this.handle.getParent().adopt(el);
			this.handle.fade('out');
			el.fade('in');
		},
		reset:function()
		{
			if (this.state)
			{
				this.handle.show();
			}
		}

	});


/*	==============================================================
		BLOG
	============================================================*/

	/*
	initialize captcha
	*/
	function initCaptcha() {
		var captcha_dummy = 0;
		$$(".captcha_challenge").addEvent("click", function() {
			// force no cache
			captcha_dummy += 1;
			var img = new Element("img", {src : '/captcha/default#'+captcha_dummy});
			var challenge = $$('.captcha_challenge')[0];
			// no clipping wait for loading new captcha
			img.addEvent("load", function() {
				img.replaces(challenge.getElement("img"));
	    	});
		});
	}

	/*
	Set up all js needed for each post. This includes the slideShow +
	overlay class, request item, and the emailToFriend popup
	*/
	function postFx() {									// [TODO] remove parsing the DOM multiples times for each added effect
		//log('postFx init');
		$$('.post .postImage').each(function(e){  new PostImageSlideShow(e);  });

		$$('.post .share').each(function(s){ makePopup(s.getElement('a.sendToAFriend'),s.getElement('div.sendToAFriend')); });

		$$('.sendToAFriend.popup form').each(function(pop){  setUpValidation(pop);  });
	}

	/*
	Class to browse multiple images embedded in a post (thanks to
	A.Newton), and toggle product info overlay.
	*/
	var PostImageSlideShow = new Class({
		Implements: Events,
		initialize: function(imgFrame){
      if (!imgFrame) return;
			imgFrame.getElements('.productImages img').each(function(slide){
				this.slides.include($(slide));
			}, this);
			if(this.slides.length) this.showSlide(0);
			if(this.slides.length > 1) {
				this.prevSlide = imgFrame.getElement('.imageSelector .prev').addEvent('click', this.cycleBack.bind(this));
				this.nextSlide = imgFrame.getElement('.imageSelector .next').addEvent('click', this.cycleForward.bind(this));
			} else { this.prevSlide = this.nextSlide = imgFrame.getElement('img'); }			// [TODO] fix this for posts with single image. Just use whatever element for now

			this.imageOverlayOpen = true;

			if (imgFrame.getElement('.desc')) this.doImageOverlay(imgFrame);
		},
		slides: [],
		cycleForward: function(){
			if($chk(this.now) && this.now < this.slides.length-1) this.showSlide(this.now+1);
			else if(!$defined(this.now)) this.showSlide(0);
		},
		cycleBack: function(){
			if(this.now > 0) this.showSlide(this.now-1);
		},
		showSlide: function(iToShow){
			if (this.fading) return;
			var now = this.now;
			var currentSlide = this.slides[now];
			var slide = this.slides[iToShow];
			var fadeIn = function (s){
				this.fading = true;
				s.setStyles({
					display:'block',
					visibility: 'visible',
					opacity: 0
				});
				s.get('tween').start('opacity', 1).chain(function(){
					this.fading = false;
					this.fireEvent('onShow', [slide, iToShow]);

					if (iToShow == 0) { this.prevSlide.addClass('theEnd'); } else { this.prevSlide.removeClass('theEnd'); }
					if (iToShow == this.slides.length-1) { this.nextSlide.addClass('theEnd'); } else { this.nextSlide.removeClass('theEnd'); }	//this.nextSlide.setStyle('color', (iToShow == this.slides.length-1 ? '#deea99' : '#fff') );

				}.bind(this));
			}.bind(this);

			if(slide) {
				if($chk(now) && now != iToShow){
					this.fading = true;
					currentSlide.get('tween').start('opacity', 0).chain(function(){
						currentSlide.setStyle('display', 'none');
						fadeIn(slide);
					}.bind(this));
				} else fadeIn(slide);
				this.now = iToShow;
			}
		},
		doImageOverlay: function(imgFrame) {
			var imageOverlaySlider = new Fx.Tween(imgFrame.getElement('.desc'), { transition: Fx.Transitions.Pow.easeOut });
			var opener = imgFrame.getElement('a.collapse');
			var imgopen = opener.get('name');
			var imgclose = opener.get('html');
			var height = imgFrame.getElement('.desc').getSize().y;
			opener.addEvent('click',function(e){
				e.stop();
				if (!this.imageOverlayOpen) {
					imageOverlaySlider.start('bottom', 0);
					opener.set('text', imgclose);
					this.imageOverlayOpen = true;
				} else {
					imageOverlaySlider.start('bottom', -height);
					opener.set('text', imgopen);
					this.imageOverlayOpen = false;
				}
			}.bind(this));
		}
	});



/*	==============================================================
		BYTE SYZE
	============================================================*/

	var Carousel = new Class({			// [TODO] this is too customized to be a class

		initialize: function(element) {
			//log('carousel init');
			var box = document.id(element);
			if ($type(box) != 'element') box = document.id(box.getDocument().body);

			box.getElements('ul li a').each(function(a) {
				a.addEvent('click', function(evt) {
					evt.preventDefault();
//					this.moveSlider(a);	// a fancy hover a la in over your head
					this.updateStepView(a);
				}.bind(this));
			}, this);
			$('bytesyze').addEvent('click:relay(#stepSelector .prev a, #stepSelector .next a)', function(evt) {
				evt.preventDefault();
				this.updateStepView(evt.target);
			}.bind(this));

			this.items = box.getElements('ul li');
			if (this.items.length < 7 ) {
				$$('#stepCarousel .prev span, #stepCarousel .next span').setStyle('background-position','-37px 0');
				return;		// don't do carousel if all items can fit on screen
			}
			this.size = this.items[0].getSize().x || 123;
			this.carousel = box.getElement('ul').setStyles({'left':0,'width':(this.size*this.items.length)+'px'});

			this.currentIndex = null;
			this.previousIndex = null;
			this.nextIndex = null;

			this.prevButton = box.getElement('.prev span').addEvent('click', this.previous.bind(this) );
			this.prevButton.setStyle('background-position','-37px 0');				// starts off greyed out.
			this.nextButton = box.getElement('.next span').addEvent('click', this.next.bind(this) );

			this.fx = new Fx.Tween(this.carousel, { duration:500, wait:false, property:'left' });

		},
		updateStepView: function(a) {
			var self = this;
			var href = a.href.split('/');
			var step = href[href.length-1];

			$$('#stepCarousel ul li.selected').removeClass('selected');
			$$('#stepCarousel ul li.step-'+step).addClass('selected');
			var current = this.currentIndex + 1;

			new Request.HTML({
				method: 'get',
				url: a.href,
				onSuccess: function(tree, xml, html, js) {
					$('stepView').fade('out').get('tween').chain(function(){
						$('stepView').set('html', html);
						$exec(js);
						$('stepView').fade('in');

						//log(current+' '+step);
						if (current > step) self.move(step-1);		// scroll Carousel if new step is not in view
						else if (step-current >= 6) self.move(step-6);
					});
				}
			}).send();
		},
		previous: function() {
			this.move(this.currentIndex > 0 ? this.currentIndex-1 : 0 );
		},
		next: function() {
			this.move(this.currentIndex<this.items.length-6 ? this.currentIndex+1 : this.items.length-6 /* because 6 items remain on screen */);
		},
		move: function(item) {
			if (item != this.currentIndex) {
				this.currentIndex=item;
				this.previousIndex = this.currentIndex + (this.currentIndex>0 ? -1 : this.items.length-1);
				this.nextIndex = this.currentIndex + (this.currentIndex<this.items.length-1 ? 1 : 1-this.items.length);
				this.fx.start(this.size*-this.currentIndex);

				if(this.currentIndex == 0) this.prevButton.setStyle('background-position','-37px 0');	// note, inlining the style like this trumps the hover state in the css. Sliiick
//				else this.prevButton.removeProperty('style');
				else this.prevButton.setStyle('background-position','');

				if(this.currentIndex == this.items.length-6) this.nextButton.setStyle('background-position','-37px 0');
//				else this.nextButton.removeProperty('style');
				else this.nextButton.setStyle('background-position','');
			}
		}

/*
		// note: these come from jQuery, need to be modified:		[TODO]
		setUpSlider: function() {
			var slider = new Element('div', {'id':'slider'});
			$('stepCarousel').grab(slider);						// our sliding thingy
			slider.setStyle('width', $$('#stepCarousel ul li.selected').get('width') );
			slider.setStyle('height', $$('#stepCarousel ul li.selected').get('height') );

			var pos = $('#stepCarousel ul li.selected').getPosition();
			slider.setStyles({'position':'absolute', 'top':pos.y+'px', 'left':pos.x+'px', 'background':'#bebebe', 'z-index':1, 'display':'block'});

			$('#stepCarousel ul li a img').setStyle('border-color', 'transparent');			// remove grey border, use grey slider as hover instead

			$('#stepCarousel ul li a').addStyles({
				'mouseover': function(){
					if ( ! $(this).parent().hasClass('date') ) moveSlider( $(this).parent() );
				},
				'mouseout': function(){
					if ( ! $(this).parent().hasClass('date') ) moveSlider( $('#stepCarousel ul li.selected') );
				}
			});

		},
		moveSlider: function(el) {
			var pos = el.position();	// where it's going

			slider.stop();

			var obj = {};
			obj.y = pos.y+'px';
			obj.x = pos.x+'px';

			slider.animate(obj, "slow");
		}
*/

	});


/*	==============================================================
		FILTERED LIST
	============================================================*/

	var Explorer = new Class ({				// [TODO] this doesn't need to be a class
		Implements: [Options, Events],
		options: {
			container:"forsale"
		},
		initialize: function(options) {
			this.setOptions(options);
//			log("init");

//			var self = this;
//			setUpRequestForms();

			$$('#forsale').addEvent('click:relay("forsale .relayed")', function(e) {		// :relay( this.options.forsale )
				e.preventDefault();
				var href = this.get("href");

				new Request.HTML({
					url: href,
					update: "forsale",		// this.options.container,
					onSuccess: function(text, xml) {
						setUpRequestForms();
					}
				}).send();
			});
		}

	});

	function setUpRequestForms() {
//		console.log('set up request form');



	$$('.itemrequest_overlay form').each(function(requestForm) {

	//			console.log('validate: '+requestForm.get('id'));

		});

		$$('.itemrequest button[name!=request]').addEvent('click', function(){

			var origButton = this;

			var containerO =  this.getPrevious('form');
			SqueezeBox.initialize({ 'size': {'x': 400, 'y': 225}});

			var container = containerO.clone().cloneEvents(containerO);



			new Form.Validator.Inline( container, {
				errorPrefix: '',
				evaluateFieldsOnBlur:false,
				onFormValidate: function(passed, form, e) {
					if (passed) {
						e.preventDefault();
						var button = container.getElement('button');
						button.addClass('spinner');

						//log('request item:'+id);
						var email = container.getElement('input[name=email]').get("value");
						var id = container.getElement('input[name=object_id]').get("value");
						var name = container.getElement('input[name=name]').get("value");
						var type = container.getElement('input[name=object_type]').get("value");

						new Request.HTML({
							url: '/' + ARTIST.username + '/api/item_request',
							data: "object_id="+id+"&object_type="+type+"&email="+email+"&name="+name,
							update: container,
							onComplete: function(response) {
								button.removeClass('spinner');
								(function() {
								SqueezeBox.close();
								 }).delay(5000);
							}
						}).send();

					}
				}
			});

			SqueezeBox.open( container, {
				handler:'adopt',
				classWindow:'itemrequest_overlay'
			});




		});


	}

/*	==============================================================
		VALIDATION
	============================================================*/

	function setUpValidation(validateMe, andThen) {
		validateMe = document.id(validateMe);
		//log ('validate: '+validateMe.get('id') );
		new Form.Validator.Inline( validateMe, {
			errorPrefix: '',
			evaluateFieldsOnBlur:false,
			onFormValidate: function(passed, form, event) {
				if (passed) {
					event.preventDefault(); 							// stop the normal behavior of submitting the form.
					if ( $$('.subscr-spinner'))$$('.subscr-spinner').fade('in');

					if ( $$(".sendfriendbutton")){$$(".sendfriendbutton").addClass('disabled');$$(".sendfriendbutton").set('disabled', true);}

//					if($defined(andThen)) andThen();					// execute the callback
					if(andThen) {										// execute the callback
						form.submit();
					} else {											// add email, email to friend
						form.getParent().getParent().getChildren('a.sendToAFriend').removeEvents().addEvent('click', $lambda(false));	// deactivate toggle switch, override previous click event. Messy?
						var wb = $(form).getElement(".wait-button");
						if(wb) wb = new WaitButton(wb);
						if(wb) wb.wait();
						form.set('send', {
							onSuccess: function(message){
								if ( $$('.subscr-spinner'))$$('.subscr-spinner').fade('out');
								if ( $$(".sendfriendbutton")){$$(".sendfriendbutton").removeClass('disabled');$$(".sendfriendbutton").set('disabled', false);}
								if(wb) wb.reset();
								var parentDiv = form.getParent('.popup');
								new Element('div', { 'html':message, 'class':'formResponse' }).replaces(form);
								(function(){

									parentDiv.fade('out').get('tween').chain(function(){
										parentDiv.setStyle('display', 'none');
										parentDiv.open = false;
									});
								}).delay(2000);
							}
						});
						form.send(); 									// send via ajax
					}
				}
			}
		});
		Form.Validator.add('cannotContain', {
			errorMsg: 'This is required.',
			test: function(field, props){
				return (!field.get('value').test(props.cannotContain));
			}
		});
	}


/*	==============================================================
		STICKY COLUMN
	============================================================*/

	/*
	Stick the store in place while scrolling so that it is always
	visible. However, if the height of the store exceeds the window
	height, it should scroll along with the window
	*/
	var StickyColumn = new Class ({
		initialize:function(){
			if(Browser.Engine.trident4){ return; }							// if IE6 just forget it
			//log('stickyColumn init');

			var moveIt = new Fx.Move('rightColumn', { link:'cancel', transition:Fx.Transitions.Quad.easeOut });

			this.states = { PINNED_TOP:"pinnedTop", FLOATING:"floating", PINNED_BOTTOM:"pinnedBottom" };
			this.determine = {
				pinnedTop:function(){
					if( this._viewport.y >= this._rightColumn.height && this._container.height > this._rightColumn.height) {
						if( this._container.bottom < this._rightColumn.height ) {
							return this.setState(this.states.PINNED_BOTTOM);
						}
						return this.setState(this.states.FLOATING);
					}
				},
				floating:function(){
					if(this._viewport.y < this._rightColumn.height           || this._container.height <= this._rightColumn.height){
	//					moveIt.start('top', 0).chain(function(){return this.setState(this.states.PINNED_TOP)});
						return this.setState(this.states.PINNED_TOP);
					}
					if (this._container.bottom <= this._rightColumn.bottom){
						return this.setState(this.states.PINNED_BOTTOM);
					}
				},
				pinnedBottom:function(){
					if (this._viewport.y < this._rightColumn.height         || this._container.height <= this._rightColumn.height) {
	//					moveIt.start('top', 0).chain(function(){return this.setState(this.states.PINNED_TOP)});
						return this.setState(this.states.PINNED_TOP);
					}
					if (this._rightColumn.top > 0) {
						return this.setState(this.states.FLOATING);
					}
				}
			};

																				// [TODO] these can eventually be options, not hard-coded:
			this._viewport = window.getSize();
			this._container = $('container').getBoundingClientRect();			// [TODO] this needs to be relative to the viewport, not document. works for now
			this._rightColumn = $('wrap').getBoundingClientRect();
			this.setState(this.states.PINNED_TOP);


	// [TODO] MAJOR todo: this has to work. has to:
//			$('cart').addEvent("resize:relay(div)", this.itemFrameChanged.bind(this));


			window.addEvents({
				"resize": this.viewportResized.bind(this),
				"scroll": this.viewportScrolled.bind(this)
			});

		},
		viewportResized:function(D){
			//log('viewportResized');
			this._viewport = window.getSize();
	//		if(Browser.Engine.webkit){ this.setState(this.states.PINNED_TOP) }
			this.viewportScrolled();
		},
		viewportScrolled:function(){
			//log('viewportScrolled');
			this._container = $('container').getCoords();
			this._rightColumn = $('wrap').getCoords();

//			log('rightColumn top height bottom: ' + this._rightColumn.top +' ,' + this._rightColumn.height + ' ,' + this._rightColumn.bottom);
//			log('container top height bottom: ' +   this._container.top +' ,' + this._container.height +' ,' + this._container.bottom);


			this._stateSwitcher();
		},
		itemFrameChanged:function(E){
			//log('itemFrameChanged');
			this._rightColumn = $('wrap').getCoords();
			this._stateSwitcher();
		},
		setState:function(state){
//			log('currentState: '+state);
			if(this._currentState == state) { return; }
			$('rightColumn').removeClass(this._currentState);
			$('rightColumn').addClass(state);
			this._currentState = state;
			this._stateSwitcher = this.determine[state];
		}
	});







(function(){						// make the getCoordinates function work as i need it (ie properly). This should be fixed in moo1.3



Element.implement({
  getCoords: function(element){
    var position = this.getPosition(element), size = this.getSize();
    var obj = {left: position.x, top: position.y, width: size.x, height: size.y};
    if (this.getStyle('position') != 'fixed') {
      var offset = window.getScroll();
      obj.left = obj.left - offset.x;
      obj.top = obj.top - offset.y;
    }
    obj.right = obj.left + obj.width;
    obj.bottom = obj.top + obj.height;

//log(this.get("id") + ' top: ' + obj.top);
//log(this.get("id") + ' height: ' + obj.height);

    return obj;
  }
});


})();
