/*=======================================
 File Name: jquery.ris.js
 Author: Richard Scarrott
 Copyright: Richard Scarrott
 Created (updated): 24/08/10 (16/10/10)
=======================================*/

// project namespace
$.ris = new Object();

// ie alias
var headache = $.browser.msie && $.browser.version.substr(0,1)<9,
	migraine = $.browser.msie && $.browser.version.substr(0,1)<7;

// utility methods
// toggles height and opacity
$.fn.fadeHeightToggle = function(speed, callback) {
	return this.each(function() {
		$(this).animate({
			'height': 'toggle',
			'opacity': 'toggle',
			'padding-top': 'toggle',
			'padding-bottom': 'toggle',
			'margin-top': 'toggle',
			'margin-bottom': 'toggle'
		}, speed, callback);
	});
};

// feature detection
/*$.ris.featureDetection = {
	init: function() {
		this.$dummyElement = $('<div id="dummy-element" />').appendTo('body');
		this.checkRgba();
		this.checkBoxShadow();
		this.cleanUp();
	},
	checkRgba: function() {
		var previousColor = this.$dummyElement.css('background-color');
		try {
			this.$dummyElement.css('background-color', 'rgba(0, 0, 0, 0.5)');
		}
		catch(e) {}
		
		if (this.$dummyElement.css('background-color') !== previousColor) {
			$('html').addClass('rgba');
			this.rgba = true;
		}
	},
	checkBoxShadow: function() {
		if (this.$dummyElement[0].style.BoxShadow !== undefined || this.$dummyElement[0].style.MozBoxShadow !== undefined || this.$dummyElement[0].style.WebkitBoxShadow !== undefined) {
			$('html').addClass('box-shadow');
			this.boxShadow = true;
		}
	},
	cleanUp: function() {
		this.$dummyElement.remove();
	}
};*/

// dynamic input lables (focus and blur)
$.fn.dynamicInputLabels = function() {
	var removeLabel = function($input) {
		if ($input.hasClass('dummy')) {
			$input.prev('input').show().focus().end().hide();
		}
	
		if ($input.val() === $input.data('label')) {
			$input.removeClass('blur').val('');
		}
	};
	
	var addLabel = function($input) {
		if ($input.is('input:password') && $input.val() === '') {
			$input.next('input').val($input.data('label')).show().end().hide();
		}
	
		if ($input.val() === '' || $input.val() === $input.data('label')) {
			$input.addClass('blur').val($input.data('label'));
		}
	};

	return this.each(function() {
		var $form, $inputs;
		$form = $(this);
		$inputs = $form.find('input[type=text], input[type=password], textarea');
		
		$inputs.each(function() {
			var $input, label;	
			$input = $(this);
			label = $form.find('label[for=' + $input.attr('id') + ']').hide().text();
			$input.data('label', label);
			
			$input.focus(function() {
				removeLabel($input);
			}).blur(function() {
				addLabel($input);
			});
			
			if ($input.is('input:password')) {
				var dummy = $('<input type="text" class="dummy" />').insertAfter($input).focus(function() {
					removeLabel(dummy);
				});
				
				if ($input.val() !== '') {dummy.hide();}
			}
			addLabel($input);
		});
		
		$form.submit(function() {
			$inputs.each(function() {
				removeLabel($(this));
			});
		});
	});
};

// allows text areas to dynamically expand with more/less text (uses contentEditable attribute)
$.fn.textareaExpander = function() {

	this.each(function() {
		var $form, $dummyDiv;
		$form = $(this);
		$dummyDiv = [];
		
		$form.find('textarea').each(function(i) {
			var $textarea, label, text;
			$textarea = $(this);
			
			label = $form.find('label[for=' + $textarea.attr('id') + ']').hide().text();
			text = $textarea.val();
			
			$dummyDiv[i] = $('<div class="dummy-textarea" contenteditable="true"></div>').text(text).insertBefore($textarea);
			
			if ($dummyDiv[i].text() === '' || $dummyDiv[i].text() === label) {
				$dummyDiv[i].addClass('blur').text(label);
			}
			
			$dummyDiv[i].focus(function() {
				var $this = $(this);
				
				if ($this.text() === label) {
					$this.removeClass('blur');
					$this.css('min-height', 50).text('');
					
					// fix min-height in IE6
					if (migraine) {$this.css('height', 50);}
				}
			
			}).blur(function() {
				var $this = $(this);

				if ($this.text() === '') {
					$this.addClass('blur');
					$this.css('min-height', 0).text(label);
					
					// fix min-height in IE6
					if (migraine) {$this.css('height', 'auto');}
				}
			
			});
			
		}).hide();

		$form.submit(function() {
			$.each($dummyDiv, function(i) {
				$dummyDiv[i].next('textarea').val($dummyDiv[i].text());
			});
		});
	});
};

// inserts close button into div
$.fn.closeBox = function(speed) {

	return this.each(function() {
	
		var $box, $closeBtn;
		
		$box = $(this);
		$closeBtn = $('<a href="#" class="close">x</a>').prependTo($box).click(function() {
			$box.fadeHeightToggle(speed);
			return false;
		});
	});
};

// fades in element on hover
$.fn.navFader = function() {
	this.each(function() {
	
		var $thisNav = $(this);
		
		$thisNav.css({'opacity': 0.4}).hover(function() {
			$(this).stop().animate({'opacity': 1}, 350);
		}, function() {
			$(this).stop().animate({'opacity': 0.4}, 350);
		});
		
	});
};

// custom tooltip
$.fn.toolTip = function() {

	if (!this.length) {return false;}
	
	var $toolTip = $('<div id="tooltip" class="code" />').hide().appendTo('body');

	this.each(function() {
		var $el = $(this),
			title = this.title,
			height,
			width,
			left,
			top;
		
		this.title = '';
		
		$el.hover(function(e) {
			$toolTip.text(title);
		
			height = $toolTip.outerHeight();
			top = e.pageY - height - 10;
			
			width = $toolTip.outerWidth() / 2;
			left = e.pageX - width;
			
			/* IE has bug with fadeTo() + absoute positioning so tooltip will currently not be stopped as it's using fadeIn / fadeOut
			to preserve opacity on multiple hovers. */
			//$toolTip.css({top: top, left: left}).stop().fadeTo(250, 1);
			$toolTip.css({top: top, left: left}).fadeIn(250);

			$el.bind('mousemove.toolTip', function(e) {
				//height = $toolTip.outerHeight();
				top = e.pageY - height - 10;

				//width = $toolTip.outerWidth() / 2;
				left = e.pageX - width;

				$toolTip.css({top: top, left: left});
			});
		}, function() {
			$toolTip.fadeOut(250);
			$el.unbind('mousemove.toolTip');
		});
	});
};


// carousel
$.ris.carousel = {
	itemIndex: 0,
	itemsPerPage: 4,
	itemsPerTransition: 4,
	speed: 800,
	noOfRows: 2,
	init: function($el) {
		if (!$el.length) {return false;}
		this.$container = $el;
		this.setUp();
	},
	setUp: function() {
	
		this.$runner = this.$container.find('ul').wrap('<div class="mask" />');
		this.$items = this.$runner.children();
		this.$mask = this.$container.find('div.mask');
		this.noOfItems = this.$items.length; // double row
		
		this.setWidth()
		this.noOfPages = Math.ceil((this.noOfItems - this.itemsPerPage) / this.itemsPerTransition) + 1;
		
		if (this.noOfItems <= this.itemsPerPage) {return false;}
		
		//this.insertNextPrev();
		this.insertNumberedLinks();
		this.buttonStatus();
		
		//this.$nextBtn.click($.proxy(this, 'nextHandler'));
		//this.$prevBtn.click($.proxy(this, 'prevHandler'));
		this.$paginationLinks.find('a').click($.proxy(this, 'numberedLinksHandler'));//.click(function() {return false;});
	
	},
	setWidth: function() {
		// if carousel has multiple rows
		if (this.noOfRows > 1) {
			this.noOfItems = Math.round(this.noOfItems / this.noOfRows);
			var width =  this.$items.outerWidth(true) * this.noOfItems;
			this.$runner.width(width);
		}
	},
	insertNextPrev: function() {
		// insert next and prev
		this.$prevBtn = $('<a href="#" class="prev">Prev</a>').insertAfter(this.$container);
		this.$nextBtn = $('<a href="#" class="next">Next</a>').insertAfter(this.$container);
	},
	insertNumberedLinks: function() {
	
		// insert numbered links
		var i, links = [];
		this.$paginationLinks = $('<ol class="pagination-links base" />').insertAfter(this.$container.parent('div').find('div.meta h1'));
		for (i = 0; i < this.noOfPages; i++) {
			links[i] = '<li><a href="#item-' + i + '">' + (i + 1) + '</a></li>';
		}
		this.$paginationLinks.append(links.join(''));
	
	},
	numberedLinksHandler: function(e) {
		//this.itemIndex = $(e.target).attr('href').split('--')[1] * this.itemsPerTransition;
		this.itemIndex = e.target.hash.substr(1).split('-')[1] * this.itemsPerTransition;
		
		this.animate();
		return false;
	},
	nextHandler: function() {
		this.itemIndex = this.itemIndex + this.itemsPerTransition;
		this.animate();
		return false;
	},
	prevHandler: function() {
		this.itemIndex = this.itemIndex - this.itemsPerTransition;
		this.animate();
		return false;
	},
	buttonStatus: function() {
		
		this.$paginationLinks
				.children().removeClass('current')
					.eq(Math.ceil(this.itemIndex / this.itemsPerTransition)).addClass('current');

	
		/*this.$nextBtn.add(this.$prevBtn).removeClass('disabled');
		
		// first conditional added in case filtered results mean the carousel is made invalid
		if (this.noOfItems <= this.itemsPerPage) {
			this.$nextBtn.add(this.$prevBtn).addClass('disabled');
		} 
		else if (this.itemIndex === (this.noOfItems - this.itemsPerPage)) {
			this.$nextBtn.addClass('disabled');
		} 
		else if (this.itemIndex === 0) {
			this.$prevBtn.addClass('disabled');
		}*/
	},
	animate: function() {
	
		var $nextItem, pos;
	
		// check whether there are enough items to animate to
		if (this.itemIndex > (this.noOfItems - this.itemsPerPage)) {
			this.itemIndex = this.noOfItems - this.itemsPerPage; // go to last panel - items per transition
		}
		
		if (this.itemIndex < 0) {
			this.itemIndex = 0; // go to first
		}

		$nextItem = this.$items.eq(this.itemIndex);
		pos = $nextItem.position();

		// IE performs better with positon being animated not scrollPos
		if (headache) {
			this.$runner.stop().animate({left: -pos.left}, this.speed);
		}
		else {
			this.$mask.stop().animate({scrollLeft: pos.left}, this.speed);
		}
		
		this.buttonStatus();
	},
	updateSettings: function($items) {
		this.itemIndex = 0;
		this.$items = $items;
		this.noOfItems = this.$items.length;
		
		if (headache) {
			this.$runner.css({left: 0});
		}
		else {
			this.$mask.scrollLeft(0);
		}
		
		this.setWidth();
		this.noOfPages = Math.ceil((this.noOfItems - this.itemsPerPage) / this.itemsPerTransition) + 1;
		
		// remove numbered links and insert new ones
		this.$paginationLinks.remove();
		this.insertNumberedLinks();
		this.$paginationLinks.find('a').click($.proxy(this, 'numberedLinksHandler'));
		this.buttonStatus();
	}
};

// filter icons
$.ris.iconFilter = {
	category: 'all',
	transitionSpeed: 400,
	init: function($el) {
		if (!$el.length) {return false;}
		this.$container = $el;
		this.setup();
	},
	setup: function() {
		this.$items = this.$container.find('ul > li');
		//this.filterLinks = this.$container.find('ul.filters').click($.proxy(this, 'filterHandler'));
		//this.$filterLinks = $('a.all, a.clients, a.skills').click($.proxy(this, 'filterHandler'));
		var filters = this.insertFilters();
		
		$('a.all, a.client, a.skill').click($.proxy(this, 'filterHandler'));
		
	},
	insertFilters: function() {
		
		$('span.all, span.client, span.skill').each(function(i) {
			var $thisItem = $(this),
				filter = $thisItem.attr('class'),
				content = $thisItem.text();
			
			$thisItem.replaceWith('<a href="#' + filter + '" class="' + filter + '"><strong>' + content + '</strong></a>');
		});
	
	},
	filterHandler: function(e) {

		var currentCategory = this.category;
		this.category = e.currentTarget.hash.substr(1).toLowerCase();
			
		if (this.category !== currentCategory) {
			this.filter();
		}
		
		return false;
	},
	filter: function() {
	
		var that = this, $newItems, $oldItems;
	
		if (that.category !== 'all') {
			$oldItems = this.$items.filter(':not(.' + this.category + ')');
			$newItems = this.$items.filter('.' + this.category);
		} else {
			$oldItems = false;
			$newItems = this.$items;
		}

		$.ris.carousel.$paginationLinks.fadeTo(this.transitionSpeed, 0);
		$.ris.carousel.$runner.fadeTo(this.transitionSpeed, 0, function() {
				$.ris.carousel.updateSettings($newItems);
				if ($oldItems) {$oldItems.hide();}
				$newItems.show();
				$.ris.carousel.$paginationLinks.hide();
				$.ris.carousel.$runner.add($.ris.carousel.$paginationLinks).fadeTo(this.transitionSpeed, 1);
		});
	}
};

// thumbs popup
$.ris.iconPopups = {
	timer: false,
	pause: 100,
	transitionSpeed: 150,
	init: function($el) {
	
		if (!$el.length) {return false;}
		
		this.$thisItem; // ??
		
		this.$container = $el;
		this.insertPopup();
		
		this.$items = this.$container.find('li').mouseenter($.proxy(this, 'mouseEnterHandler'));
		
		this.popup.add(this.$container).mouseleave($.proxy(this, 'mouseOutHandler'));
		
		//this.$container.mouseleave($.proxy(this, 'mouseOutHandler'));
	},
	insertPopup: function() {
		this.popup = $('<div id="about-me-popup" />').appendTo(this.$container);
	},
	mouseEnterHandler: function() {
		this.$items.bind('mousemove', $.proxy(this, 'mouseMoveHandler'));
	},
	mouseMoveHandler: function(e) {
		
		//console.log('mousemoved');
		this.$thisItem = $(e.currentTarget);
	
		if (this.timer) {
			clearTimeout(this.timer);
		}
		
		this.timer = setTimeout($.proxy(this, 'setupItemPostion'), this.pause);
	
	},
	mouseOutHandler: function(e) {
		this.$thisItem.css('opacity', 1);
		this.popup.hide();
		this.clearTimer();
		// remove hovered class and rebind mouse move event
		//this.$thisItem.removeClass('hovered').bind('mousemove', $.proxy(this, 'mouseMoveHandler'));
	},
	setupItemPostion: function() {

		// local vars
		var boxPos, boxWidth, boxHeight, popupWidth, popupHeight, carouselScrollLeft, boxOffset, scrollTop;
		
		// get box position, width and height
		boxPos = this.$thisItem.position();
		boxWidth = this.$thisItem.width();
		boxHeight = this.$thisItem.height();
		
		// append box's html to popup and get width and height
		popupWidth = this.popup.html(this.$thisItem.html()).outerWidth();
		popupHeight = this.popup.outerHeight();
		
		// The posiitoning calculation needs to take into account IE as it
		// animates 'left' pos not scroll pos..forking is baaaaad
		if (headache) {
			carouselScrollLeft = Math.abs(parseInt($.ris.carousel.$runner.css('left'), 10));
			if (isNaN(carouselScrollLeft)) {carouselScrollLeft = 0;}
		}
		else {
			carouselScrollLeft = $.ris.carousel.$mask.scrollLeft();
		}

		// add 8 from both top and bottom to account for container padding...not exactly smart...
		this.left =  (boxPos.left - carouselScrollLeft) - ((popupWidth - boxWidth) / 2) + 8;
		this.top = boxPos.top - ((popupHeight - boxHeight) / 2) + 8;
		
		// check image will fit within viewport NEEDS WORK
		boxOffset = this.$thisItem.offset();
		scrollTop = $(window).scrollTop();
		availableSpace = (boxOffset.top - scrollTop) - 20; // ading 20 pixels to keep padding above popup.
		
		if ((popupHeight - boxHeight) / 2 > availableSpace) {
			this.top = boxPos.top - (availableSpace);
		}
		
		this.enlarge();
	
	},
	enlarge: function() {
		
		//this.$thisItem.fadeTo(this.transitionSpeed, 0);
		
		this.popup.css({
			'left': this.left,
			'top': this.top
		}).fadeIn(this.transitionSpeed);

	},
	clearTimer: function() {
		
		if (this.timer) {
			clearTimeout(this.timer);
		}
	}
};

$(document).ready(function() {

	$('body').addClass('js-enabled');
	// $.ris.featureDetection.init();
	
	// about me icons
	var $aboutMeIcons = $('#about-me-icons');
	$.ris.iconPopups.init($aboutMeIcons);
	$.ris.carousel.init($aboutMeIcons);
	$.ris.iconFilter.init($aboutMeIcons);
	
	// navigation - IE has issue with cleartype and filter opacity
	if (!headache) {
		$('ul.nav-links, form.base .submit input, .pagination').navFader();
	}
	
	// textarea expander (cannot detect support for content editable: https://github.com/Modernizr/Modernizr/wiki/Undetectables)
	var userAgent = window.navigator.userAgent;
	if (!userAgent.match(/iPad/i) && !userAgent.match(/iPhone/i)) {
		$('form').textareaExpander();
	}
	
	// dynamic inputs
	$('form').dynamicInputLabels();
	
	// add close box buttons
	$('#flash-message').closeBox(200);
	
	if (typeof SyntaxHighlighter !== 'undefined') {
		SyntaxHighlighter.autoloader(
		  'js jscript javascript http://alexgorbatchev.com/pub/sh/current/scripts/shBrushJScript.js',
		  'css http://alexgorbatchev.com/pub/sh/current/scripts/shBrushCss.js',
		  'xml http://alexgorbatchev.com/pub/sh/current/scripts/shBrushXml.js'
		);

		SyntaxHighlighter.all();
	}
	
	$('span.tooltip[title]').toolTip();
	
});
