if(!jsFrontend) { var jsFrontend }

/**
 * Frontend related objects
 *
 * @author Thomas Deceuninck <thomasdeceuninck@netlash.com>
 */
jsFrontend =
{
	// datamembers
	debug: false,

	// init, something like a constructor
	init: function()
	{
		// init datagrid
		jsFrontend.datagrid.init();

		// init navigation enhancements
		jsFrontend.navigation.init();

		// init search enhancements
		jsFrontend.search.init();
	},

	ios: navigator.userAgent.match(/iPhone/i) || navigator.userAgent.match(/iPod/i) || navigator.userAgent.match(/iPad/i),


	// end
	eoo: true
}


jsFrontend.datagrid =
{
	// init, something like a constructor
	init: function()
	{
		jsFrontend.datagrid.addHoverEnhancements();
		jsFrontend.datagrid.highlightCurrentRow();
		jsFrontend.datagrid.manageCheckboxes();
		jsFrontend.datagrid.sellActions();
		jsFrontend.datagrid.pendingActions();
		jsFrontend.datagrid.historyActions();
		jsFrontend.datagrid.manageScrolling();
		jsFrontend.datagrid.fixTableHeaders();
		jsFrontend.datagrid.singleSelections();
		jsFrontend.datagrid.multipleSelections();
		jsFrontend.datagrid.spannedSelections();
		jsFrontend.datagrid.bigButton();
	},


	// add hover enhancements
	addHoverEnhancements: function()
	{
		$('.dataGrid tbody tr').hover(function()
		{
			// only add class if not in results datagrid
			if(!$(this).parents('.results').length)
			{
				$(this).addClass('currentRow');
			}
			else
			{
				// only add class if in results datagrid but not on hover of certain rows
				if(!$(this).is('.mazalRow, .soldRow, .pendingRow, .historyRow'))
				{
					$(this).addClass('currentRow');
				}
			}
		}, function()
		{
			// only remove class when there is no input focus
			if(!$(this).find('input.inputText:focus').length)
			{
				$(this).removeClass('currentRow');
			}
		});
	},


	// highlight current row
	highlightCurrentRow: function()
	{
		// variables which are used
		var $valueEditorInput = $('.dataGrid .valueEditorHolder input.inputText');

		// on focus
		$valueEditorInput.bind('focus', function()
		{
			$(this).closest('tr').addClass('currentRow');
		});

		// on blur
		$valueEditorInput.bind('blur', function()
		{
			$(this).closest('tr').removeClass('currentRow');
		});
	},


	// manage checkboxes
	manageCheckboxes: function()
	{
		// check checkbox on row click
		$('.dataGrid tbody tr').bind('click', function(e)
		{
			// prevent event bubbling
			if(e.target.nodeName.toLowerCase() !== 'input' && e.target.nodeName.toLowerCase() !== 'a' && e.target.nodeName.toLowerCase() !== 'span')
			{
				// variables which are used
				var $checkbox = $(this).find('.inputCheckbox');

				// check if not already so, else uncheck of course
				$checkbox.attr('checked', !$checkbox.is(':checked'));
			}
		});

		// check or uncheck all checkboxes at once
		$('#checkAll').bind('click', function()
		{
			$('.dataGrid tbody tr .inputCheckbox').each(function(i)
			{
				$(this).attr('checked', $('#checkAll').is(':checked'));
			});
		});
	},


	// sell actions
	sellActions: function()
	{
		// variables which are used
		var $sellDataGrid = $('#bottomWrapper').find('.sell .dataGrid');

		// show accept and reject button on hover of pending element
		$sellDataGrid.delegate('.pendingRow',
		{
			mouseenter: function()
			{
				$(this).find('.action span').replaceWith('<ul><li class="firstChild"><a class="button acceptButton" href="#">Accept</a></li><li class="lastChild"><a class="button rejectButton" href="#">Reject</a></li></ul>');
			},
			mouseleave: function()
			{
				$(this).find('.action ul').replaceWith('<span class="text">Pending</span>');
			}
		});

		// process accept action
		$sellDataGrid.delegate('.pendingRow .action a.acceptButton', 'click', function(e)
		{
			// prevent default
			e.preventDefault();

			// variables which are used
			var $closestRow = $(this).closest('tr');

			// remove the increase and decrease buttons
			$closestRow.find('.valueEditorHolder').each(function()
			{
				$(this).find('.increaseValue, .decreaseValue').remove();
			});

			// remove parent class and replace cancel with mazal
			$closestRow.removeClass('pendingRow').addClass('mazalRow').find('.action ul').replaceWith('<span class="text">Mazal</span>');
		});

		// process reject action
		$sellDataGrid.delegate('.pendingRow .action a.rejectButton', 'click', function(e)
		{
			// prevent default
			e.preventDefault();

			// variables which are used
			var $closestRow = $(this).closest('tr');

			// remove parent class and replace cancel with mazal
			$closestRow.removeClass('pendingRow').find('.action ul').replaceWith('<a class="button removeButton" href="#">Remove</a>');
		});

		// process confirm action
		$sellDataGrid.delegate('.action a.confirmButton', 'click', function(e)
		{
			// prevent default
			e.preventDefault();

			// variables which are used
			var $closestRow = $(this).closest('tr');

			// remove the increase and decrease buttons
			$closestRow.find('.valueEditorHolder').each(function()
			{
				$(this).find('.increaseValue, .decreaseValue').remove();
			});

			// remove parent class and replace cancel with mazal
			$closestRow.addClass('mazalRow').find('.action a').replaceWith('<span class="text">Mazal</span>');
		});

		// process remove action
		$('#bottomWrapper').delegate('.sell .dataGrid .action a.removeButton', 'click', function(e)
		{
			// prevent default
			e.preventDefault();

			// variables which are used
			var $closestRow = $(this).closest('tr');

			// remove the row
			$closestRow.remove();
		});
	},


	// pending actions
	pendingActions: function()
	{
		// show cancel button on hover of pending element
		$('#bottomWrapper').delegate('.results .dataGrid .pendingRow',
		{
			mouseenter: function()
			{
				$(this).find('.action span').replaceWith('<a class="button shinyBlackButton" href="#">Cancel</a>');
			},
			mouseleave: function()
			{
				$(this).find('.action a').replaceWith('<span class="text">Pending</span>');
			}
		});

		// process cancel action
		$('#bottomWrapper').delegate('.results .dataGrid .pendingRow .action a.shinyBlackButton', 'click', function(e)
		{
			// prevent default
			e.preventDefault();

			// variables which are used
			var $closestRow = $(this).closest('tr');

			// remove parent class and replace cancel with bid button
			$closestRow.removeClass('pendingRow').find('.action a').replaceWith('<a class="button bidButton" href="#">Bid</a>');
		});
	},


	// history actions
	historyActions: function()
	{
		// variables which are used
		$bidCount = $('.dataGrid .value .count');
		$bidItem = $('.historyRow li.bid');
		$arrowUp = $('.historyRow .arrowHolder a.arrowUpWhiteIcon');

		// show history when bid count is clicked
		$bidCount.bind('click', function(e)
		{
			$(this).closest('tr').next('.historyRow').show();
		});

		// show or hide the bid date on click
		$bidItem.bind('click', function(e)
		{
			// prevent default
			e.preventDefault();

			// variables which are used
			var $bidText = $(this).closest('li').find('.bidText');
			var $bidDate = $(this).closest('li').find('.bidDate');

			// switch visible elements
			$bidText.css('display', $bidText.is(':visible') ? 'none' : 'block');
			$bidDate.css('display', $bidDate.is(':visible') ? 'none' : 'inline');
		});

		// hide the history row
		$arrowUp.bind('click', function(e)
		{
			// prevent default
			e.preventDefault();

			// hide row
			$(this).closest('tr').hide();
		});
	},


	// manage scrolling
	manageScrolling: function()
	{
		// variables which are used to increase performance
		var $results = $('div.results');
		var $calculatorHolder = $('#calculatorHolder');
		var $window = $(window);
		var $document = $(document);

		if($results.length)
		{
			// calculate top distance minus possible margins plus header height
			var top = $('.results .header').offset().top - parseFloat($('.results .header').css('marginTop').replace(/auto/,0) + 69);
			scrolling = false;
			isFixed = false;

			// bind scroll event
			$window.bind("scroll", function()
			{
				scrolling = true;
			});

			// check if scrolling with interval
			setInterval(function()
			{
				if(scrolling)
				{
					scrolling = false;
					var y = $(this).scrollTop() + 69;
					var height = top;

					if(y >= top)
					{
						// only add fixed class if not ios device nor resize the table headers
						if(!jsFrontend.ios && !isFixed)
						{
							$results.addClass('fixed');
							jsFrontend.datagrid.fixTableHeaders();
							isFixed = true;
						}
					}
					else
					{
						$results.removeClass('fixed');
						isFixed = false;
					}

					// if ios device, make calculatorholder absolute instead of fixed
					if(jsFrontend.ios)
					{
						$calculatorHolder.css('position', 'absolute').css('top', $document.height() - 99).show();
					}
					else
					{
						if($document.scrollTop() + $window.height() > $document.height() - $results.height() + 100)
						{
							$calculatorHolder.fadeIn();
						}
						else
						{
							$calculatorHolder.fadeOut();
						}
					}
				}
			}, 150);
		}
	},


	// fix table column width
	fixTableHeaders: function()
	{
		// variables which are used to increase performance
		var $results = $('div.results');

		if(jsFrontend.ios) return;

		// bind resize event
		$(window).bind('resize', function()
		{
			setInterval(fixColumnWidth, 150);
		});

		function fixColumnWidth()
		{
			if($results.hasClass('fixed'))
			{
				var $th = $('.dataGrid thead tr th');
				var $td = $('.dataGrid tbody tr:first td');

				// no fixed; let the browser treat it as normal cells and calculate the widths from there
				$results.removeClass('fixed');

				var widths = [];

				// fetch widths
				$td.each(function(i)
				{
					widths[i] = $td.eq(i).width();
				});

				// widths have been gathered, we're good to go back to fixed
				$results.addClass('fixed');

				// apply widths
				$('.dataGrid thead tr').width($('.dataGrid tbody tr:first').width());
				$td.each(function(i)
				{
					$th.eq(i).width(widths[i]);
					$td.eq(i).width(widths[i]);
				});
			}
		}

		fixColumnWidth();
	},


	// single selections
	singleSelections: function()
	{
		// bind click event to the buttons in the "normal rows"
		$('.shapeRow a.button, .labRow a.button').bind('click', function(e)
		{
			// prevent default action
			e.preventDefault();

			// already selected = deselect
			if($(this).hasClass('activeButton')) $(this).removeClass('activeButton');
			else
			{
				// deselect existing selected buttons
				$(this).parent().parent().find('a.button').removeClass('activeButton');

				// select clicked button
				$(this).addClass('activeButton');
			}
		});
	},


	// multiple selections
	multipleSelections: function()
	{
		// bind click event to the buttons in the "normal rows"
		$('.sizeRow a.button').bind('click', function(e)
		{
			// prevent default action
			e.preventDefault();

			// already selected = deselect
			if($(this).hasClass('activeButton')) $(this).removeClass('activeButton');
			// select clicked button
			else $(this).addClass('activeButton');
		});
	},


	// in some columns, when clicking 2 items, all items in between should also be selected
	spannedSelections: function()
	{
		// bind click event to the buttons in the "special rows"
		$('.sizeGroupsRow a.button, .colorRow a.button, .clarityRow a.button, .cutRow a.button, .polishRow a.button:not(#bigButton), .symmetryRow a.button, .fluoRow a.button').bind('click', function(e)
		{
			// prevent default action
			e.preventDefault();

			// already selected?
			if($(this).hasClass('activeButton'))
			{
				// deselected clicked button
				$(this).removeClass('activeButton');

				// only the buttons in "size groups" should dome some extra things
				if($(this).parent().parent().hasClass('sizeGroupsRow'))
				{
					// find position
					var position = $(this).parent().prevAll().length;

					// make corresponding sizes active
					$('.sizeRow div:eq(' + position + ') a.button').removeClass('activeButton');
				}
			}
			else
			{
				// check if this button is no "sibling" of the big button or if the big button isn't pressed
				if(($(this).parent().parent().hasClass('polishRow') || $(this).parent().parent().hasClass('symmetryRow')) && $('#bigButton').hasClass('activeButton')) return;

				// declare vars
				var indexFirst = 0;
				var indexCurrent = 0;

				// add new class to currently clicked button
				$(this).addClass('currentButton');

				// is another button already selected?
				if($(this).parent().parent().find('a.activeButton').length)
				{
					// loop all buttons
					$(this).parent().parent().find('a.button').each(function(i)
					{
						// find index of first selected button
						if($(this).hasClass('activeButton')) indexFirst = i;

						// find index of current button
						else if($(this).hasClass('currentButton')) indexCurrent = i;
					});

					// loop all buttons in between these two buttons
					$(this).parent().parent().find('a.button:gt(' + indexFirst + '):lt(' + (indexCurrent - indexFirst) + '):not(#bigButton)').each(function()
					{
						if(!$(this).hasClass('activeButton')) $(this).addClass('currentButton');
					});
				}

				// only the buttons in "size groups" should dome some extra things
				if($(this).parent().parent().hasClass('sizeGroupsRow'))
				{
					// loop newly selected buttons
					$('.currentButton').each(function()
					{
						// find position
						var position = $(this).parent().prevAll().length;

						// make corresponding sizes active
						$('.sizeRow div:eq(' + position + ') a.button').addClass('activeButton');
					});
				}

				// add selected class on buttons
				$('a.currentButton').removeClass('currentButton').addClass('activeButton');
			}
		});
	},


	// clicking the big button disables the buttons next to it
	bigButton: function()
	{
		// bind click event of big button
		$('.brokenUnit a.button').live('click', function(e)
		{
			// prevent default action
			e.preventDefault();

			// big button is selected already
			if($(this).hasClass('activeButton'))
			{
				// remove selected state
				$(this).removeClass('activeButton');

				// enable surrounding buttons
				$('.polishRow a.button:not(#bigButton), .symmetryRow a.button').removeClass('disabledButton');
			}
			// big button is not yet selected
			else
			{
				// add selected state
				$(this).addClass('activeButton');

				// disable surrounding buttons and remove active state
				$('.polishRow a.button:not(#bigButton), .symmetryRow a.button').addClass('disabledButton').removeClass('activeButton');
			}
		});
	},

	// end
	eoo: true
},


jsFrontend.navigation =
{
	// init, something like a constructor
	init: function()
	{
		jsFrontend.navigation.bindScrolling();
		jsFrontend.navigation.bindHidingAndShowing();
	},


	// hide results
	arrowDown: function()
	{
		// hide search wrapper
		$('.searchWrapper').hide('blind', { direction: 'vertical' }, 500);

		// switch arrows
		$(this).removeClass('arrowUpWhiteIcon').addClass('arrowDownWhiteIcon');

		// add open search button
		$('#topWrapper .inner').append('<div class="openSearch"><a href="#" class="button openButton">Open search</a></div>')
	},


	// show results
	arrowUp: function()
	{
		// hide search wrapper
		$('.searchWrapper').show('blind', { direction: 'vertical' }, 500);

		// switch arrows
		$(this).removeClass('arrowDownWhiteIcon').addClass('arrowUpWhiteIcon');

		// remove open search button
		$('#topWrapper .inner .openSearch').remove();
	},


	// bind scrolling
	bindScrolling: function()
	{
		// scroll to top
		$('#calculatorHolder .arrowUpWhiteIcon, #calculatorHolder .backToTop a.button').bind('click', function(e)
		{
			// prevent default
			e.preventDefault();

			// scroll to topwrapper
			$.scrollTo('#topWrapper', 1000);
		});
	},


	// bind hiding and showing
	bindHidingAndShowing: function()
	{
		$arrow = $('#topWrapper .arrowHolder a');

		// hide search wrapper by clicking the fold arrow
		$arrow.live('click', function(e)
		{
			// prevent default
			e.preventDefault();

			// arrow is currently up, switch  it down
			if($(this).hasClass('arrowUpWhiteIcon')) jsFrontend.navigation.arrowDown.call(this);

			// arrow is currently down, switch it up
			else jsFrontend.navigation.arrowUp.call(this);
		});

		// hide search wrapper by going to the results
		$('#topWrapper .searchWrapper .actionsBox .blueButton').live('click', function(e)
		{
			// prevent default
			e.preventDefault();

			// arrow is currently up, switch  it down
			jsFrontend.navigation.arrowDown.call($arrow.eq(0));
		});

		// show search wrapper by clicking open search button
		$('#topWrapper .inner .openSearch .openButton').live('click', function(e)
		{
			// prevent default
			e.preventDefault();

			// arrow is currently down, switch it up
			jsFrontend.navigation.arrowUp.call($arrow.eq(0));
		});
	},


	// end
	eoo: true
},

jsFrontend.search =
{
	// init, something like a constructor
	init: function()
	{
		jsFrontend.search.advancedSearch();
	},


	// manange advanced search
	advancedSearch: function()
	{
		$('#topWrapper').delegate('.advancedSearch .button', 'click', function(e)
		{
			// prevent default
			e.preventDefault();

			// variables which are used
			$advancedInputRow = $('#topWrapper').find('.searchFilter .advancedInputRow');

			// check if visible or invisible and act accordingly
			if($advancedInputRow.is(':visible'))
			{
				// change current text to show advanced search
				$(this).find('.textWrapper').text('Advanced search');

				// hide advanced search rows
				$advancedInputRow.hide('blind', { direction: 'vertical' }, 500);
			}
			else
			{
				// change current text to hide advanced
				$(this).find('.textWrapper').text('Hide advanced');

				// show advanced search rows
				$advancedInputRow.show('blind', { direction: 'vertical' }, 500);
			}
		});
	},


	// end
	eoo: true
}

$(jsFrontend.init);
