/**
 * file description
 *
 * @author: Thibaut De Muynck (ab6x.net)
 * @created: 20110705
 * @modified: 20110927 17:16
 *
 * @package: saxe 2011
 */

/********************************
 *     NAMESPACE DEFINITION     *
 ********************************/
jQuery.namespace = function() {
	var a=arguments, o=null, i, j, d;
	for (i=0; i<a.length; i=i+1) {
		d=a[i].split(".");
		o=window;
		for (j=0; j<d.length; j=j+1) {
			o[d[j]]=o[d[j]] || {};
			o=o[d[j]];
		}
	}
	return o;
};


$.namespace( 'jQuery.page' );

// page sanitation function
$.page.sanitize = function() {
	delete $.page.videos;
	delete $.page.photos;
};
/********************************
 *     MASK CONTENT LOADING     *
 ********************************/
$.page.loadContent = function(e) {
	// cancel default event behaviour (click)
	e.preventDefault();
	// position mask
	if (typeof($.main.mask) == 'undefined') {
		// main area
		$.main.mask = $('<div/>')
			.attr('id', 'mask')
			.css({
				position: 'absolute',
				display: 'none'
				})
			.appendTo('#puzzle_board');
		// content area
		$('<div/>')
			.attr('id', 'content')
			.appendTo($.main.mask);
		// close box
		$('<div/>')
			.attr('class', 'close')
			.css('display','none')
			.appendTo($.main.mask);
	}
	var board = $('#puzzle_board');
	var target = $(this);
	var m_size = new Object();
	m_size.left = target.offsetParent().position().left + target.position().left;
	m_size.top = target.offsetParent().position().top + target.position().top;
	m_size.width = target.outerWidth(true);
	m_size.height = target.outerHeight(true);
	$.main.mask
		.css({
			left: m_size.left,
			top: m_size.top,
			width: m_size.width,
			height: m_size.height
		})
		.show();
	// expand mask
	$.main.mask.animate(
		{
			left: 0,
			top: 0,
			width: board.outerWidth(true),
			height: board.outerHeight(true)
		},
		500,
		function() {
			// set close box function
			$('#mask .close')
				.unbind('click')
				.css('display','block')
				.click(function(e) {
						// prevent click event propagation
						e.stopPropagation();
						// hide close button
						$(this).fadeOut(100);
						// hide and empty content
						$('#content')
							.fadeOut(150, function() {
								$(this)
									.empty()
									.show();
								// contract and hide mask
								$.main.mask.animate(
									{
										left: m_size.left,
										top: m_size.top,
										width: m_size.width,
										height: m_size.height
									},
									500,
									function() {
										$.main.mask.fadeOut(100);
										// memory sanitation
										// window.sanitize function has to be created in the loaded content
										// this code is then run on panel closure
										if (typeof($.page.sanitize) == 'function') {
											$.page.sanitize();
										}
									});
							});
						// release esc key event
						$(document).unbind('keydown');
					});
			// catch esc key press
			$(document).keydown(function(e) {
				// ESCAPE key pressed
				if (e.keyCode == 27) {
					$('#mask .close').triggerHandler('click');
				}
			});
			// load id related content
			$('#content').load('parts/'+target.attr('id')+'.html');
		}
	);
};

/***************************************
 *     STANDARD PART INIT SEQUENCE     *
 ***************************************/
$.page.initpart = function (has_videos,has_photos,page_url,media_dir) {

	// videos management operations
	if (has_videos) {
		/** @namespace $.page.videos - is defined in the part page's code (with $.page.videos.list) */
		$.page.videos.$scrollPane = $('#videos_thumbs');
		$.page.videos.$scrollContent = $.page.videos.$scrollPane.find('.scroll-content');

		// define projekktor variables
		// messages
		$.page.videos.pjkt_messages = {
			// flash & native:
			0:'Une erreur est survenue.',
			1:'Vous avez annulé la lecture du media. ',
			2:'Une erreur réseau a causé l\'échec de téléchargement complet du media. ',
			3:'La lecture du media a été annulée suite à un problème de corruption. ',
			4:'Le media (%{src}) n\'a pas pu être téléchargé suite à une erreur serveur ou réseau.',
			5:'Désolé, votre navigateur ne supporte pas le format media du fichier demandé (%{type}).<br/><br/>Essayez d\'installer le Plugin Flash en allant sur ﻿http://www.adobe.com/go/getflash',
			6:'Vous n\'avez pas le plugin Flash V%{flashver} ou ultérieur.<br/><br/>Essayez de l\'installer en allant sur ﻿http://www.adobe.com/go/getflash',
			7:'Pas de media prévu.',
			8:'! Configuration invalide du Modèle Media !',
			9:'Le fichier (%{src}) est introuvable.',
			97:'Pas de media prévu.',
			98:'Données de playlist mal formées ou invalides!',
			99:'Cliquez sur "afficher" pour continuer. ',
			// youtube errors:
			500: 'Cette vidéo Youtube a été retirée ou classée comme privée',
			501: 'L\'utilisateur Youtube possédant cette vidéo a désactivé l\'inclusion.',
			502: 'L\'identifiant vidéo Youtube specifié est invalide.',
			// debug popup:
			1000:'Copiez ce texte et envoyez-le à votre webmaster:'
		};

		// hide overflow from pane since we will have a custom scroller
		$.page.videos.$scrollPane.css('overflow','hidden');

		// check all videos thumbs are loaded
		$.page.videos.$scrollContent.find('img').imagesLoaded(function() {
			// make custom videos scroller
			$.page.makeCustomScroller($.page.videos.$scrollPane,$.page.videos.$scrollContent);

			// activate video projekktor
			$.page.videos.player = projekktor('#video_player', {
				debug: false,
				controls: true,
				autoplay: true,
				volume: 0.8,
				playerFlashMP4: 'libs/js/projekktor/jarisplayer.swf',
				playerFlashMP3: 'libs/js/projekktor/jarisplayer.swf',
				width: 450,
				height: 255,
				playlist: $.page.videos.list,
				messages: $.page.videos.pjkt_messages
				},
				function(player)
					{
					// catch fullscreen toggle to hide/show header
					player.addListener('fullscreen', function(state) {
						if (state) {
							$('#header').hide()
						}
						else {
							$('#header').show();
						}
					});
					// catch item to set selected and scrollto
					player.addListener('item', function(item) {
						// activate selected li
						var lis = $('#videos_thumbs li');
						lis.removeClass('selected');
						$(lis[item])
							.addClass('selected')
							.triggerHandler('scrollto');
					});
					// activate videos.list li's click behavior
					$('#videos_thumbs li').each(function(i,li) {
						var $li = $(li);
						$li.css('cursor','pointer');
						if (i === 0) { $li.addClass('selected'); }
						$li.click(function() {
							// set corresponding activeItem
							player.setActiveItem(i);
							//player.setStop();
							return false;
						});
					});
				}
			)
		});
	}

	// photos management operations
	if (has_photos) {
		// bigger image window
		$('#galleriffic_pop').dialog({
			autoOpen: false,
			modal: true,
			close: function() {
				$('#galleriffic_pop').empty();
			}
		});
		// fb action select window
		$( "#fb_op_buttons" ).dialog({
			autoOpen: false,
			height: 145,
			width: 360,
			modal: true,
			close: function() {
				//allFields.val( "" ).removeClass( "ui-state-error" );
				$.page.photos.gallery.keyboardNavigation(true);
			}
		});
		// fb file upload window
		$( "#fb_upload" ).dialog({
			autoOpen: false,
			height: 300,
			width: 360,
			modal: true,
			close: function() {
				//allFields.val( "" ).removeClass( "ui-state-error" );
				$.page.photos.gallery.keyboardNavigation(true);
			}
		});

		// buttons actions
		// fb button opens fb action selector
		$('#fb_op_buttons .upload').click(function() {
			$( "#fb_upload" ).load(
				// loads window's content
				'parts/fb_upload.html',
				function() {
					// activate content's buttons
					$( "#fb_op_buttons" ).dialog('close');
					$( "#fb_upload" ).dialog('open');
					// disable galleriffic keyboard control
					$.page.photos.gallery.keyboardNavigation(false);
					// prevent return from submitting the form
					$("#uploadImage").bind("keypress", function(e) {
						if (e.keyCode == 13) { // TODO -> check this code
							return false;
							}
					});
				}
			);
		});
		// fb share button
		$('#fb_op_buttons .share').click(function() {
			fbShare(window.base_url+page_url);
		});

		// store base content of slideshow elements
		$.page.slideshow_els = $('.photos.panel').clone();

		// download action
		window.dl_click = function(filename) {
			$.page.photos.gallery.pause();
			self.location.replace('libs/php/force_download.php?file='+$.page.photos.cur_dir+'/'+filename);
		};
		// facebook pop action
		window.fb_click = function(filename) {
			$.page.photos.gallery.pause();
			$.page.photos.gallery.keyboardNavigation(false);
			$.page.photos.filename = filename;
			$( "#fb_op_buttons" ).dialog('open');
		};

		// initial photos loading

		$.page.photosLoader(media_dir+'/photos',!has_videos);
	}

	// define tab actions and display default panel
	if (has_videos && has_photos) {
		// set video tab as active by default, also display panel
		$('#mask .tab[title=videos]').addClass('active');
		$('#mask .videos').fadeIn(250);
		// activate tabs menu
		$('#mask .tab').each(function(i,tab) {
			var $tab = $(tab);
			$tab.click(function() {
				// hide/display panels
				$('#mask .panel').hide();
				$('#mask .tab').removeClass('active');
				$('#mask .'+$tab.attr('title')).fadeIn(250);
				$tab.addClass('active');
				// tab specific action
				if ($tab.attr('title') == 'videos' && typeof($.page.photos.gallery) != 'undefined') {
					// stop gallery when tab switched
					$.page.photos.gallery.pause();
					// register piwik visit
					piwikTracker.setDocumentTitle($.main.pg_title + '/vidéos');
					piwikTracker.trackPageView();
				}
				if ($tab.attr('title') == 'photos' && typeof($.page.videos.player) != 'undefined') {
					// stop video when tab switched
					$.page.videos.player.setStop();
					$.page.photos.gallery.play();
					// register piwik visit
					piwikTracker.setDocumentTitle($.main.pg_title + '/photos');
					piwikTracker.trackPageView();
				}
			});
		});
	}
	else {
		// set single tab to active
		$.page.$tab = $('#mask .tab');
		$.page.$tab.addClass('active');
		$('#mask .'+$.page.$tab.attr('title')).fadeIn(250);
	}
};

/***********************************************************
 *     PHOTOS GALLERY DIRECTORY BASED LOADING FUNCTION     *
 ***********************************************************/
 $.page.photosLoader = function (dir,auto) {
	// cleanup slideshow
	if (typeof($.page.photos) != 'undefined') {
		$.page.photos.gallery.pause();
		delete $.page.photos;
		$('.photos.panel').replaceWith($.page.slideshow_els.clone());
		$('#loading').css('display','block');
	}
	$.page.photos = new Object();
	$.page.photos.cur_dir = dir;
	// fill photos thumbs with script-generated list
	$('#photos_thumbs ul').load(
		'libs/php/list_dir.php?dir='+$.page.photos.cur_dir+'&ext=jpeg,jpg,png&get=photo_thumbs',
		function() {
			// collect photos scroller parts
			$.page.photos.$scrollPane = $('#photos_thumbs');
			$.page.photos.$scrollContent = $.page.photos.$scrollPane.find('.scroll-content');
			// hide overflow from pane since we will have a custom scroller
			$.page.photos.$scrollPane.css('overflow','hidden');
			// hide the panel while phpThumbs are loading
			$.page.photos.$scrollPane.hide();
			// inject message in wait panel
			var thumbs_nbr = $('#photos_thumbs li').length;
			$('#thumbs_loading').html('Chargement de '+thumbs_nbr+' photos, cela peut prendre un peu de temps, merci de patienter...');

			// check all photos thumbs are loaded
			$.page.photos.$scrollContent.find('img').imagesLoaded(function() {
				// avoid cycle execution bug
				if (typeof($.page.photos.loadex) != 'undefined') {
					return false;
				}
				else {
					$.page.photos.loadex = true;
				}
				// remove loader text
				$('#thumbs_loading').html('');
				// show scroll pane
				$.page.photos.$scrollPane.show();
				// make custom photos scroller
				$.page.makeCustomScroller($.page.photos.$scrollPane,$.page.photos.$scrollContent);

				// activate photos gallery                  TODO -> check double click "next" display bug
				$.page.photos.gallery = $.page.photos.$scrollPane.galleriffic({
					imageContainerSel:      '#slideshow',
					controlsContainerSel:   '#controls',
					captionContainerSel:    '#caption',
					loadingContainerSel:    '#loading',
					numThumbs:              300,
					playLinkText:           '',
					pauseLinkText:          '',
					prevLinkText:           '',
					nextLinkText:           '',
					nextPageLinkText:       ';',
					prevPageLinkText:       '',
					autoStart:              auto,
					enableHistory:          false,
					onSlideChange:          function(prevIndex,nextIndex) {
												$(this).find('a[href=#'+(nextIndex+1)+']').parent('li').triggerHandler('scrollto');
											},
					imgClickHandler:        function(e, link) {
												this.pause();
												e.preventDefault();
												var target_src = $(e.target).attr('src');
												target_src = target_src.replace('w=450','w=675');
												target_src = target_src.replace('h=300','h=450');
												target_src = target_src.replace('far=C','');
												var img = $('<img src="'+target_src+'" />').appendTo('#galleriffic_pop');
												img.imagesLoaded(function() {
													$('#galleriffic_pop').dialog('open');
													$('#galleriffic_pop').dialog('option',
														{
															width: $(img).outerWidth(true),
															height: $(img).outerHeight(true) + 50
														}
													);
													$('#galleriffic_pop').dialog('option',
														{
															position: 'center'
														}
													);
												});
											}
				});
			});
		}
	);
}

/******************************
 *     CUSTOM SCROLL BARS     *
 ******************************/
$.page.makeCustomScroller = function ($scrollPane,$scrollContent) {
	// collect elements positions and dimensions
	var vis = $scrollContent.is(":visible");
	var list = $scrollContent.find('li');
	var $panel = $(list[0]).parents('.panel');
	if (!vis) { $panel.show(); }  // must be visible to get this data
	list.each(function(i,el) {
		var $el = $(el);
		$el.data('pos',$el.position());
		$el.data('owh',$el.outerWidth());
	});
	if (!vis) { $panel.hide(); }
	// compute scroll-content width (for when it's dynamically filled)
	var $last = $(list[list.length - 1]);
	var scrollContentWidth = $last.data('pos').left + $last.data('owh');
	var scrollPaneWidth = $scrollPane.width();

	// if more elements than can be displayed, create scroll area
	if (scrollContentWidth > scrollPaneWidth) {
		// compute content scrolling parameter
		var content_factor = (scrollContentWidth - scrollPaneWidth) / 100;
		// init slider (creates .ui-slider-handle)
		var elements_slider = $scrollPane.find('.slider').slider();
		// inject the button in the handle to make it visible (it's an anchor...)
		$scrollPane.find('.ui-slider-handle').append('<div class="slider-button"/>');
		// bind content sliding function
		elements_slider.bind('slide', function(e, ui) {
			$scrollContent.css('margin-left',-(content_factor * ui.value));
		});

		// display slider
		$scrollPane.find('.slider').css('visibility','visible');
		// add setpos event handler
		elements_slider.bind('setpos', function(e,params) {
			/* content position must be passed as params.pos
			 * alignment can be passed as params.align (left,center,right) - default='center'
			 * speed can be passed to animate the scrolling, passed value is for a full length scroll
			 * easing can be passed to set the animation transition - default='linear'
			 * call: $('el').slider.trigger('setpos',{'pos':value,'align':'center'});
			 */
			// check parameters
			var pos = (params.pos < 0) ? 0 : params.pos;
			if (pos > scrollContentWidth) { pos = scrollContentWidth; }
			var align = (typeof(params.align) == 'undefined') ? 'center' : params.align;
			var speed = (typeof(params.speed) == 'undefined') ? false : params.speed;
			var easing = (typeof(params.easing) == 'undefined') ? 'linear' : params.easing;
			// compute margin value
			var margin = 0;
			switch (align) {
				case 'left':
					if (pos < (scrollContentWidth - scrollPaneWidth)) {
						margin = -pos;
					}
					else {
						margin = -(scrollContentWidth - scrollPaneWidth);
					}
					break;
				case 'right':
					if ((pos - scrollPaneWidth) > 0) {
						margin = -(pos - scrollPaneWidth);
					}
					else {
						margin = 0;
					}
					break;
				default: // center
					margin = ((pos - (scrollPaneWidth / 2)) > 0) ? -(pos - (scrollPaneWidth / 2)) : 0;
					margin = (pos > (scrollContentWidth - (scrollPaneWidth / 2))) ? -(scrollContentWidth - scrollPaneWidth) : margin;
					break;
			}
			// position content
			if (speed) {
				var c_speed = speed / scrollContentWidth * (Math.abs(parseInt($scrollContent.css('margin-left')) - margin));
				$scrollContent.animate({
						'margin-left': margin
					},
					c_speed,
					easing
				);
			}
			else {
				$scrollContent.css('margin-left', margin);
			}
			// position handle
			$(this).slider('value', Math.abs(margin) / content_factor );
		});

		// activate scrollto event on each thumb
		$scrollPane.find('li').each(function(i,li) {
			// calculate element center
			// compute element position values
			var $li = $(li);
			var center = $li.data('pos').left + ($li.data('owh') / 2);
			$li.bind('scrollto click',
					{ 'pos': center },
					function(e) {
						$scrollPane.find('.slider').trigger('setpos',{
							'pos': e.data.pos,
							'align': 'center',
							'speed': '4000'
						});
					}
			);
		});
	}
};


$.namespace( 'jQuery.form' );
/******************************************
 *       FORM INTERACTION FUNCTIONS       *
 ******************************************/
$.form.checkLength = function ( tips_target, o, name, min, max ) {
	// no max length specified
	var sentence = '';
	if (typeof(max) == 'undefined') {
		sentence = '%1$s ne peut être vide.';
	}
	else {
		sentence = 'La longeur de "%1$s" doit être entre %2$s et %3$s.';
	}
	if ( o.val().length > max || o.val().length < min ) {
		o.addClass( "ui-state-error" );
		o.focus();
		sentence = sentence.replace( "%1$s", name );
		sentence = sentence.replace( '%2$s', min );
		sentence = sentence.replace( '%3$s', max );
		$.form.updateTips( tips_target, sentence );
		return false;
	} else {
		return true;
	}
};
$.form.checkRegexp = function ( target, o, regexp, n ) {
	if ( !( regexp.test( o.val() ) ) ) {
		o.addClass( "ui-state-error" );
		o.focus();
		$.form.updateTips( target, n );
		return false;
	} else {
		return true;
	}
};
$.form.updateTips = function ( target, tips, flash ) {
	// manage optional flash argument
	flash = (typeof(arguments[2]) == 'undefined') ? true : flash;
	target = $( target )
		.html( tips );
	if (tips != '' && flash) {
		$.form.flashTips(target);
	}
};
$.form.flashTips = function ( target ) {
	target.addClass( "ui-state-highlight" );
	setTimeout(function() {
		target.removeClass( "ui-state-highlight", 1500 );
	}, 500 );
};

$.form.validateForm = function ( form_sel, tips_sel ) {
	// validate form information function
	var allFields = $(form_sel).find('input[type=text],textarea');
	var bValid = true;
	allFields.removeClass( "ui-state-error" );
	allFields.each( function( index, field ) {
		field = $(field);
		// get field label
		var label = $('label[for=' + field.attr("id") + ']').text();
		// check non empty fields
		if ( !field.hasClass( 'allowBlank' )) {
			bValid = bValid && $.form.checkLength( tips_sel, field, label, 1, field.attr('maxlength') );
		}
		var regExp = /.?/i;
		var tips = '';
		// check e-mail format
		if ( field.hasClass( 'email' )) {
			regExp = /^((([a-z]|\d|[!#\$%&'\*\+\-\/=\?\^_`{\|}~]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])+(\.([a-z]|\d|[!#\$%&'\*\+\-\/=\?\^_`{\|}~]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])+)*)|((\x22)((((\x20|\x09)*(\x0d\x0a))?(\x20|\x09)+)?(([\x01-\x08\x0b\x0c\x0e-\x1f\x7f]|\x21|[\x23-\x5b]|[\x5d-\x7e]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(\\([\x01-\x09\x0b\x0c\x0d-\x7f]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF]))))*(((\x20|\x09)*(\x0d\x0a))?(\x20|\x09)+)?(\x22)))@((([a-z]|\d|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(([a-z]|\d|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])([a-z]|\d|-|\.|_|~|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])*([a-z]|\d|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])))\.)+(([a-z]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(([a-z]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])([a-z]|\d|-|\.|_|~|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])*([a-z]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])))\.?$/i;
			tips = 'Une adresse e-mail valide est requise pour "%1$s" (ie. name@domain.tld).';
			tips = tips.replace( "%1$s", label );
		}
		// check text format
		if ( field.hasClass( 'freetext' )) {
			regExp = /^[0-9a-zâêîôûàèìòùáéíóúäëïöüãõñç'_\. ,-]+$/i;
			tips = 'Le champ "%1$s" ne peut contenir que des caractères alphabetiques, nombres, apostrophes, tirets, points, virgules, underscores et espaces.';
			tips = tips.replace( "%1$s", label );
		}
		// check file name (no accent, no space)
		if ( field.hasClass( 'filename' )) {
			regExp = /^[a-z]([0-9a-z_\.-])+$/i;
			tips = 'Le champ "%1$s" ne peut contenir que des caractères alphabetiques, nombres, tirets, points et underscores, et doit débuter par une lettre.';
			tips = tips.replace( "%1$s", label );
		}
		bValid = bValid && $.form.checkRegexp( tips_sel, field, regExp, tips );
		//bValid = bValid && checkRegexp( email, /^((([a-z]|\d|[!#\$%&'\*\+\-\/=\?\^_`{\|}~]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])+(\.([a-z]|\d|[!#\$%&'\*\+\-\/=\?\^_`{\|}~]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])+)*)|((\x22)((((\x20|\x09)*(\x0d\x0a))?(\x20|\x09)+)?(([\x01-\x08\x0b\x0c\x0e-\x1f\x7f]|\x21|[\x23-\x5b]|[\x5d-\x7e]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(\\([\x01-\x09\x0b\x0c\x0d-\x7f]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF]))))*(((\x20|\x09)*(\x0d\x0a))?(\x20|\x09)+)?(\x22)))@((([a-z]|\d|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(([a-z]|\d|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])([a-z]|\d|-|\.|_|~|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])*([a-z]|\d|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])))\.)+(([a-z]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(([a-z]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])([a-z]|\d|-|\.|_|~|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])*([a-z]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])))\.?$/i, "eg. name@domain.tld" );
		//bValid = bValid && checkRegexp( password, /^([0-9a-zA-Z])+$/, "Password field only allow : a-z 0-9" );
	});
	return bValid;
};

$.fn.serializeObject = function () {
    var o = {};
    var a = this.serializeArray();
    $.each(a, function() {
        if (o[this.name]) {
            if (!o[this.name].push) {
                o[this.name] = [o[this.name]];
            }
            o[this.name].push(this.value || '');
        } else {
            o[this.name] = this.value || '';
        }
    });
    return o;
};

/**
 * Transforms select options to clickable pictures
 *
 * @param starClass
 * @param src
 * @param imgClass
 * @param multi
 */
$.form.picturiseSelect = function ( starClass, src, imgClass, multi ) {
	// manage optional argument multi
	multi = (typeof(arguments[3]) == 'undefined') ? false : multi;
	// collect elements
	var collection = $('select.'+starClass);
	// substitute star elements
	collection.each(function(i,sel) {
		sel = $(sel);
		var picts = new Array();
		sel.find('option').each(function(j,opt) {
			picts[j] = $('<img src="' + src + '" class="' + imgClass + ' off" alt="' + $(opt).val() + '" />');
			picts[j].click(function() {
				for( x=0; x<=j; x++ ) {
					picts[x].removeClass('off');
					picts[x].addClass('on');
				}
				for( x=j+1; x<picts.length; x++ ) {
					picts[x].removeClass('on');
					picts[x].addClass('off');
				}
				var prev_sel = $(this).prevAll('select');
				if (!multi) {
					prev_sel.children('option').removeAttr('selected');
				}
				prev_sel.find('option:eq('+j+')').attr('selected', 'selected');
			});
			for ( x=picts.length-1; x>=0; x--) {
				picts[x].insertAfter(sel);
			}
		});
		sel.css('display','none');
	});
};

/************************************
 *      URL PARAMETERS RECOVERY     *
 ************************************
 * Get object of URL parameters
 * var allVars = $.getUrlVars();
 *
 * Getting URL var by its nam
 * var byName = $.getUrlVar('name');
 */
$.extend({
	getUrlVars: function(){
		var vars = [], hash;
		var hashes = window.location.href.slice(window.location.href.indexOf('?') + 1).split('&');
		for(var i = 0; i < hashes.length; i++)
		{
			hash = hashes[i].split('=');
			vars.push(hash[0]);
			vars[hash[0]] = hash[1];
		}
		return vars;
	},
	getUrlVar: function(name){
		return $.getUrlVars()[name];
	}
});
