jCommon = {};

/**
 * @author John Resig (http://jquery.com/), Vlad Yakovlev (red.scorpix@gmail.com)
 * @version 1.0
 */
jCommon.browser = (function() {
	var userAgent = window.navigator.userAgent.toLowerCase();

	return {
		version: (userAgent.match( /.+(?:rv|it|ra|ie)[\/: ]([\d.]+)/ ) || [0,'0'])[1],
		webkit: /webkit/.test(userAgent),
		opera: /opera/.test(userAgent),
		msie: /msie/.test(userAgent) && !/opera/.test(userAgent),
		mozilla: /mozilla/.test(userAgent ) && !/(compatible|webkit)/.test(userAgent),
		safari: /safari/.test(userAgent) && !/chrome/.test(userAgent),
		chrome: /chrome/.test(userAgent)
	};
})();


/**
 * Фикс кэширования картинок на странице в IE6.
 */
if (jCommon.browser.msie && 6 >= parseInt(jCommon.browser.version)) {
	try {
		document.execCommand('BackgroundImageCache', false, true);
	} catch(e) {}
}

String.prototype.formatNumber || $.extend(String.prototype, {
	/**
	 *
	 * @param {String} groupSeparator
	 * @param {String} fractionSeparator
	 * @return {String}
	 */
	formatNumber: function(groupSeparator, fractionSeparator) {
		var
			groupSeparator = groupSeparator || ' ',
			fractionSeparator = fractionSeparator || ',',
			/** @type {Number} */
			fractionIndex = this.indexOf('.'),
			/** @type {String} */
			fraction = fractionIndex > -1 ? this.substring(fractionIndex + 1) : '',
			/** @type {String} */
			number = fractionIndex > -1 ? this.substring(0, fractionIndex) : this;

		if (5 > number.length) {
			return number + (fractionIndex > -1 ? fractionSeparator + fraction : '');
		}

		var result = '';

		while (3 < number.length) {
			result = number.substring(number.length - 3) + (result.length > 0 ? groupSeparator : '') + result;
			number = number.substring(0, number.length - 3);
		}

		result = number + groupSeparator + result + (-1 < fractionIndex ? fractionSeparator + fraction : '');

		return result;
	}
});
Number.prototype.formatNumber || $.extend(Number.prototype, {

	/**
	 *
	 * @param {String} groupSeparator
	 * @param {String} fractionSeparator
	 * @return {String}
	 */
	formatNumber: function(groupSeparator, fractionSeparator) {
		return this.toString().formatNumber(groupSeparator, fractionSeparator);
	}
});



/**
 * Объект для работы с клавиатурными сокращениями.
 *
 * @example
 * jCommon.shortcuts.unbind('next');
 * jCommon.shortcuts.bind('prev', 'http://ya.ru', 0x24, true);
 *
 * @version 1.0
 * @date 2009-08-11
 */
jCommon.shortcuts = (function()
{
	var navigationLinks = {
		'start': { keyCode: 0x24, ctrlKey: true, altKey: false },
		'prev':  { keyCode: 0x25, ctrlKey: true, altKey: false },
		'up':    { keyCode: 0x26, ctrlKey: true, altKey: false },
		'next':  { keyCode: 0x27, ctrlKey: true, altKey: false },
		'down':  { keyCode: 0x28, ctrlKey: true, altKey: false }
	};

	$(function() {
		$('link').each(function() {

			var rel = $(this).attr('rel');

			if (navigationLinks[rel]) {
				navigationLinks[rel].href = $(this).attr('href');
			}
		});

		$(document).keydown(function(event) {
			var links = navigationLinks;

			for (var rel in links) {
				if (links[rel].keyCode == event.keyCode && links[rel].ctrlKey == event.ctrlKey && links[rel].altKey == event.altKey) {
					//if (!$('input:focus, textarea:focus').length) {
						if ('string' == typeof links[rel].href && '' != links[rel].href) {
							document.location = links[rel].href;
						} else if ($.isFunction(links[rel].href)) {
							return links[rel].href(event);
						}
					//}
				}
			}
		});
	});

	return {
		/**
		 * Привязывает к шорткату клавиатуры действие.
		 * @param {String} name Тип действия.
		 * @param {String|Function} href Если строка, то осуществлять переход по адресу, если функция, то выполнить функцию (первый параметр — объект Event).
		 * @param {Number} keyCode Код нажатой клавиши.
		 * @param {Boolean} [ctrlKey] Нажат ли <code>Ctrl</code>.
		 * @param {Boolean} [altKey] Нажат ли <code>Alt</code>.
		 */
		bind: function(name, href, keyCode, ctrlKey, altKey) {
			ctrlKey = new Boolean(ctrlKey);
			altKey = new Boolean(altKey);

			navigationLinks[name] = {
				href: href,
				keyCode: keyCode,
				ctrlKey: ctrlKey,
				altKey: altKey
			};
		},

		/**
		 * Удаляет действие для шортката.
		 * @param {String} name Тип действия.
		 */
		unbind: function(name) {
			delete navigationLinks[name];
		},

		/**
		 * Удаляет все шорткаты.
		 */
		unbindAll: function() {
			navigationLinks = {};
		}
	};
})();


/**
 * JavaScript выполняется на странице.
 */
$(document.documentElement).addClass('js');



/**
 * Попапы-блоки внутри окна браузера.
 *
 * @param {String|Element|jQuery} Контейнер попапа.
 * @param {Object} options Настройки:
 * <ul>
 *   <li>{String|Element|jQuery} fader - блок тени,</li>
 *   <li>{String|Element|Array[Element]|jQuery} link - блоки для показа/скрытия попапа,</li>
 *   <li>{String|Element|Array[Element]|jQuery} close - блоки для закрытия попапа,</li>
 *   <li>beforeShow - функция, выполняемая перед открытием,</li>
 *   <li>afterShow - функция, выполняемая после открытия,</li>
 *   <li>beforeHide - функция, выполняемая перед закрытием,</li>
 *   <li>afterHide - функция, выполняемая после закрытия.</li>
 * </ul>
 * @return {Object} Функции:
 * <ul>
 *   <li>hide</li>
 *   <li>cancel</li>
 *   <li>show</li>
 *   <li>toggle</li>
 * </ul>
 *
 * @author Stepan Reznikov [stepan.reznikov@gmail.com], Vladislav Yakovlev [red.scorpix@gmail.com]
 * @version 2.1.5
 * @date 2009-08-12
 *
 * @changelog
 * Version 2.1.5
 * Исправлена ошибки, по которой были проблемы с множественным созданием попапов.
 * Оптимизирован код.
 * Обязательная опция блока вынесена в отдельный параметр <code>container</code>.
 *
 * @changelog
 * Version 2.1.4
 * Оптимизирован код.
 *
 * @changelog
 * Version 2.1.3
 * Добавлены комментарии.</li>
 * Параметр <code>showFunction</code> удален.</li>
 * Добавлены параметры <code>beforeShow</code>, <code>afterShow</code>, <code>beforeHide</code>, <code>afterHide</code>.</li>
 *
 * @changelog
 * Version 2.1
 * Флаг <code>keep</code> заменен на <code>event.stopPropagation().</code>
 * Форма появляется и исчезает плавно (под IE появляется/исчезает мгновенно в виду проблем с <code>filter</code>).
 * Добавлен параметр <code>showFunction</code> - функция, выполняемая после показа popup'а.
 */
/*
jCommon.popupBlock = (function() {

	function PopupBlock(container, options) {
		var
			documentClickHandler,
			documentKeyDownHandler;

		container.click(function(event) {
			event.stopPropagation();
		});

		if (options.fader) {
			options.fader = $(options.fader);
		}

		if (options.link) {
			options.link = $(options.link);
			options.link.click(toggle);
		}

		if (options.close) {
			options.close = $(options.close);
			options.close.click(toggle);
		}

		function cancel(event) {
			var code = event.keyCode ? event.keyCode : event.which ? event.which : null;
			code === 27 && hide(event);
		}

		function hide(event) {
			if (container.hasClass('hidden') || !event.which || event.which !== 1) return;

			options.beforeHide && options.beforeHide();
			options.fader && options.fader.addClass('hidden');

			jCommon.browser.msie ? container.addClass('hidden') : container.fadeOut(250, function() {
				container.addClass('hidden');
				container.css({
					'opacity': '',
					'display': ''
				});
			});

			$(document)
				.unbind('click', documentClickHandler)
				.unbind('keydown', documentKeyDownHandler);

			options.afterHide && options.afterHide();

			if (event) {
				event.preventDefault();
				event.stopPropagation();
			}
			return false;
		}

		function show(event) {
			if (!container.hasClass('hidden')) return;

			options.beforeShow && options.beforeShow();
			options.fader && options.fader.removeClass('hidden');

			jCommon.browser.msie ? container.removeClass('hidden') : container.css('opacity', 0).removeClass('hidden').animate({ opacity: 1 }, 300, function() {
				container.css('opacity', '');
				options.afterShow && options.afterShow();
			});

			documentClickHandler = hide;
			documentKeyDownHandler = cancel;

			$(document)
				.click(documentClickHandler)
				.keydown(documentKeyDownHandler);

			jCommon.browser.msie && options.afterShow && options.afterShow();

			if (event) {
				event.preventDefault();
				event.stopPropagation();
			}
		}

		function toggle(event) {
			container.hasClass('hidden') ? show(event) : hide(event);
		}

		return {

			hide: hide,

			show: show,

			toggle: toggle
		};
	}

	return function(container, options) {
		return new PopupBlock($(container), options);
	};
})();
*/

/**
 * PopupBlock
 *
 *  container
 *  fader
 *  open
 *  close
 */
var PopupBlock = $.inherit(
{
	__constructor: function(container, hParam)
	{
		this.hParam = hParam;

		this.jContainer=$(container);
		this.jFader=$(hParam.fader);
		this.jOpen=hParam.open;
		this.jClose=hParam.close;

		this.bKeep=false;

		this.jContainer.click(function(self){return function(event)
		{
			self.bKeep=true;
		}}(this));
		this.cbDocumentClick = function(self){return function(event)
		{
			if (!event.which || event.which !== 1)
				self.bKeep=true;
			self.hide(event);
		}}(this);
		this.cbDocumentKeyDown = function(self){return function(event)
		{
			self.cancel(event);
		}}(this);
		this.jOpen.click(function(self){return function(event)
		{
			self.toggle(event);
		}}(this));
		this.jClose.click(function(self){return function(event)
		{
			self.toggle(event);
		}}(this));
	},

	toggle: function(event)
	{
		this.stopEvent(event);

		if(this.jContainer.hasClass("hidden"))
			this.show(event);
		else
			this.hide(event);
	},

	hide: function(event)
	{
		if(this.bKeep)
		{
			this.bKeep=false;
			return;
		}
		this._hide();
	},

	_hide: function()
	{
		if (this.hParam.onBlockHide) this.hParam.onBlockHide(this.hParam);

		this.jFader.addClass("hidden");
		this.jContainer.addClass("hidden");

		$(document).unbind("click", this.cbDocumentClick);
		$(document).unbind("keydown", this.cbDocumentKeyDown);
	},

	cancel: function(event)
	{
		var code = event.keyCode ? event.keyCode : event.which ? event.which : null;
		if (code === 27) // Esc
			this.hide(event);
	},

	show: function(event)
	{
		this.jFader.removeClass("hidden");

		if (this.hParam.onBlockShow) this.hParam.onBlockShow(this.hParam);

		if(jQuery.browser.msie)
			this.jContainer.removeClass("hidden");
		else
			this.jContainer.removeClass("hidden");

		$(document).click(this.cbDocumentClick);
		$(document).keydown(this.cbDocumentKeyDown);
	},

	stopEvent: function(event)
	{
		event.preventDefault();
		event.stopPropagation();
	}
});



initInputPlaceHolder = function (jInput) {
	if (jInput.length && !$.browser.webkit) {
		var sInputPlaceholder = jInput.attr('placeholder');
		if(!jInput.val()){
			jInput
			.addClass("empty")
			.val(sInputPlaceholder);
		}
		jInput
			.focus(function(){
				$(this).hasClass("empty") && $(this).val('').removeClass("empty");
			})
			.blur(function(){
				!$(this).val() && $(this).addClass("empty").val(sInputPlaceholder);
			})
		;
	}
}


var Quiz = $.inherit(
{
	__constructor: function(oOptions) {
		this.jResultContainer = oOptions.jResultContainer || $(".quiz-result");
		this.jFormContainer = oOptions.jFormContainer || $(".quiz-form");
		this.jForm = oOptions.jForm || $("#quiz-form");
		this.iQuizId = this.jForm.find('input[name=quiz_id]').val();
		this.iQuestionId = this.jForm.find('input[name=question_id]').val();
		
		if(this.jForm.length && this.iQuizId && this.iQuestionId)
		{
			this.init();
		} else {
			this.showResult();
		}
	},
	init: function(){
		// если пользователь авторизован и есть форма для опроса
		// проверяем учавствовал ли пользователь в этом опросе
		var sVoted = $.cookie("qvoted") || "";
		var aVoted = sVoted.split(",");
		if(aVoted.indexOf(""+this.iQuizId) < 0){
			// пользователь еще не отвечал на опрос, поэтому показываем ему форму
			var oThis = this;
			this.jForm.submit(function(e){ oThis.vote(e); return false; })
			this.showForm();
		} else {
			// пользователь уже учавствовал
			this.showResult();
		}
	},
	vote: function(e){
		var q = this.iQuestionId;
		var aVal = [];
		var jOptions = $("input[name=question"+q+"_a]:checked",this.jForm);
		jOptions.each(function(i,j){ aVal[i] = $(j).val(); });
		var hData = {};
		hData.qid = this.iQuizId;
		hData.q = this.iQuestionId;
		hData['q'+q+'_a'] = aVal;

		var oThis = this;
		$.get(
			"/ajax/quiz/",
			hData,
			function(status){
				oThis.setVoted();
				oThis.showResult();
			}
		);
		this.showResult();
	},
	setVoted: function(){
		if(this.iQuizId){
			$.cookie(
				"qvoted",
				$.cookie("qvoted") + ","  + this.iQuizId,
				{
					expires: new Date(2015, 0, 1),
					path: '/'
				}
			);
		}
	},
	showForm: function(){
		this.jFormContainer.show();
		this.jResultContainer.hide();
	},
	showResult: function(){
		this.jFormContainer.hide();
		this.jResultContainer.show();
	}

});


$(function(){
	$('#navigator-control').click(function()
	{
		$(this).toggleClass('selected');
		$('#top-navigation-expand').toggleClass('animated').slideToggle(function(){ $(this).toggleClass('animated') });
	});
	
	initInputPlaceHolder($('#site-search-input'));
})
